From 9b15b0ae14cd82126a8f2d7ec9a5d5d5e03ed8b2 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 18 Jun 2020 15:35:30 +0100 Subject: [PATCH 1/2] Add default value field --- library/i2cdevice/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/i2cdevice/__init__.py b/library/i2cdevice/__init__.py index 64b9aad..5235042 100644 --- a/library/i2cdevice/__init__.py +++ b/library/i2cdevice/__init__.py @@ -123,6 +123,8 @@ def __init__(self, name, address, fields=None, bit_width=8, read_only=False, vol self.is_read = False self.fields = {} + if fields is None: + fields = (BitField("value", 0xff), ) for field in fields: self.fields[field.name] = field From 1f689a6a81f1fd0e0fc676d80ce7c80379b87766 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 18 Jun 2020 15:37:51 +0100 Subject: [PATCH 2/2] Add support for bank switching --- library/i2cdevice/__init__.py | 32 ++++++++++++++++++++++------- library/tests/test_bank_select.py | 32 +++++++++++++++++++++++++++++ library/tests/test_device.py | 14 ++++++------- library/tests/test_registerproxy.py | 4 ++-- library/tests/test_set_and_get.py | 6 +++--- 5 files changed, 69 insertions(+), 19 deletions(-) create mode 100644 library/tests/test_bank_select.py diff --git a/library/i2cdevice/__init__.py b/library/i2cdevice/__init__.py index 5235042..2fdef21 100644 --- a/library/i2cdevice/__init__.py +++ b/library/i2cdevice/__init__.py @@ -59,17 +59,23 @@ def _int_to_bytes(value, length, endianness='big'): class MockSMBus: - def __init__(self, i2c_bus, default_registers=None): - self.regs = [0 for _ in range(255)] + def __init__(self, i2c_bus, default_registers=None, bank_select_register=None, banks=1): + self.regs = [[0 for register in range(255)] for bank in range(banks)] + self.bank_select_register = bank_select_register + self.bank = 0 if default_registers is not None: for index in default_registers.keys(): - self.regs[index] = default_registers.get(index) + self.regs[self.bank][index] = default_registers.get(index) def write_i2c_block_data(self, i2c_address, register, values): - self.regs[register:register + len(values)] = values + if len(values) == 1 and register == self.bank_select_register: + self.bank = values[0] + self.regs[0][0] = values[0] + + self.regs[self.bank][register:register + len(values)] = values def read_i2c_block_data(self, i2c_address, register, length): - return self.regs[register:register + length] + return self.regs[self.bank][register:register + length] class _RegisterProxy(object): @@ -114,12 +120,13 @@ def __exit__(self, exception_type, exception_value, exception_traceback): class Register(): """Store information about an i2c register""" - def __init__(self, name, address, fields=None, bit_width=8, read_only=False, volatile=True): + def __init__(self, name, address, fields=None, bit_width=8, read_only=False, volatile=True, bank=0): self.name = name self.address = address self.bit_width = bit_width self.read_only = read_only self.volatile = volatile + self.bank = bank self.is_read = False self.fields = {} @@ -142,14 +149,17 @@ def __init__(self, name, mask, adapter=None, bit_width=8, read_only=False): class BitFlag(BitField): + """Alias for BitField that stores information about a single flag""" def __init__(self, name, bit, read_only=False): BitField.__init__(self, name, 1 << bit, adapter=None, bit_width=8, read_only=read_only) class Device(object): - def __init__(self, i2c_address, i2c_dev=None, bit_width=8, registers=None): + def __init__(self, i2c_address, i2c_dev=None, bit_width=8, registers=None, bank_select=None): self._bit_width = bit_width + self.bank = 0 + self.bank_select = bank_select self.locked = {} self.registers = {} self.values = {} @@ -173,6 +183,10 @@ def __init__(self, i2c_address, i2c_dev=None, bit_width=8, registers=None): self.registers[register.name] = register self.__dict__[register.name] = _RegisterProxy(self, register) + def change_bank(self, bank): + self._i2c_write(self.bank_select.address, bank, self.bank_select.bit_width) + self.bank = bank + def lock_register(self, name): self.locked[name] = True @@ -181,6 +195,8 @@ def unlock_register(self, name): def read_register(self, name): register = self.registers[name] + if self.bank_select: + self.change_bank(register.bank) if register.volatile or not register.is_read: self.values[register.name] = self._i2c_read(register.address, register.bit_width) register.is_read = True @@ -188,6 +204,8 @@ def read_register(self, name): def write_register(self, name): register = self.registers[name] + if self.bank_select: + self.change_bank(register.bank) return self._i2c_write(register.address, self.values[register.name], register.bit_width) def get_addresses(self): diff --git a/library/tests/test_bank_select.py b/library/tests/test_bank_select.py new file mode 100644 index 0000000..7bd0cf4 --- /dev/null +++ b/library/tests/test_bank_select.py @@ -0,0 +1,32 @@ +from i2cdevice import MockSMBus, Device, Register, BitField +from i2cdevice.adapter import LookupAdapter +import pytest + + +def test_bank_select(): + bus = MockSMBus(1, bank_select_register=0x00, banks=2) + device = Device(0x00, i2c_dev=bus, registers=( + Register('one', 0x01, bank=0, fields=( + BitField('value', 0xFF), + )), + Register('two', 0x01, bank=1, fields=( + BitField('value', 0xFF), + )), + ), bank_select=Register('bank', 0x00)) + + device.set('one', value=111) + assert bus.bank == 0 + + device.set('two', value=222) + assert bus.bank == 1 + + assert device.get('two').value == 222 + assert bus.regs[1][1] == 222 + assert bus.bank == 1 + + assert device.get('one').value == 111 + assert bus.regs[0][1] == 111 + assert bus.bank == 0 + + + diff --git a/library/tests/test_device.py b/library/tests/test_device.py index a000af3..d18763c 100644 --- a/library/tests/test_device.py +++ b/library/tests/test_device.py @@ -14,7 +14,7 @@ def test_register_locking(): device.test.set_test(77) device.lock_register('test') - bus.regs[0] = 11 + bus.regs[0][0] = 11 assert device.test.get_test() == 77 device.unlock_register('test') @@ -33,7 +33,7 @@ def test_adapters(): assert device.adapter.get_test() == 0xFF00 - assert bus.regs[0:2] == [0x00, 0xFF] + assert bus.regs[0][0:2] == [0x00, 0xFF] def test_address_select(): @@ -65,7 +65,7 @@ def test_get_set_field(): assert device.get_field('test', 'test') == 99 - assert bus.regs[0] == 99 + assert bus.regs[0][0] == 99 def test_get_set_field_overflow(): @@ -80,7 +80,7 @@ def test_get_set_field_overflow(): assert device.get_field('test', 'test') == 127 - assert bus.regs[0] == 127 + assert bus.regs[0][0] == 127 def test_bitflag(): @@ -93,16 +93,16 @@ def test_bitflag(): device.test.set_test(True) - assert bus.regs[0] == 0b01000000 + assert bus.regs[0][0] == 0b01000000 device.test.set_test(False) - assert bus.regs[0] == 0b00000000 + assert bus.regs[0][0] == 0b00000000 def test_get_register(): bus = MockSMBus(1) - bus.regs[0:3] = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF] + bus.regs[0][0:3] = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF] device = Device([0x00, 0x01], i2c_dev=bus, registers=( Register('test24', 0x00, fields=( BitField('test', 0xFFF), diff --git a/library/tests/test_registerproxy.py b/library/tests/test_registerproxy.py index d992a74..197edbe 100644 --- a/library/tests/test_registerproxy.py +++ b/library/tests/test_registerproxy.py @@ -13,7 +13,7 @@ def test_register_proxy(): assert device.test.get_test() == 123 - assert bus.regs[0] == 123 + assert bus.regs[0][0] == 123 with device.test as test: test.set_test(77) @@ -21,6 +21,6 @@ def test_register_proxy(): assert device.test.get_test() == 77 - assert bus.regs[0] == 77 + assert bus.regs[0][0] == 77 assert device.test.read() == 77 diff --git a/library/tests/test_set_and_get.py b/library/tests/test_set_and_get.py index 4d5048c..759091b 100644 --- a/library/tests/test_set_and_get.py +++ b/library/tests/test_set_and_get.py @@ -14,7 +14,7 @@ def test_set_regs(): assert device.get('test').test == 123 - assert bus.regs[0] == 123 + assert bus.regs[0][0] == 123 def test_get_regs(): @@ -31,8 +31,8 @@ def test_get_regs(): reg.test == 0x66 reg.monkey == 0x77 - assert bus.regs[0] == 0x66 - assert bus.regs[1] == 0x77 + assert bus.regs[0][0] == 0x66 + assert bus.regs[0][1] == 0x77 def test_field_name_in_adapter_error():