Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions library/i2cdevice/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -114,15 +120,18 @@ 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 = {}

if fields is None:
fields = (BitField("value", 0xff), )
for field in fields:
self.fields[field.name] = field

Expand All @@ -140,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 = {}
Expand All @@ -171,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

Expand All @@ -179,13 +195,17 @@ 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
return self.values[register.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):
Expand Down
32 changes: 32 additions & 0 deletions library/tests/test_bank_select.py
Original file line number Diff line number Diff line change
@@ -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



14 changes: 7 additions & 7 deletions library/tests/test_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand All @@ -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():
Expand Down Expand Up @@ -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():
Expand All @@ -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():
Expand All @@ -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),
Expand Down
4 changes: 2 additions & 2 deletions library/tests/test_registerproxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ 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)
test.write()

assert device.test.get_test() == 77

assert bus.regs[0] == 77
assert bus.regs[0][0] == 77

assert device.test.read() == 77
6 changes: 3 additions & 3 deletions library/tests/test_set_and_get.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand All @@ -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():
Expand Down