Skip to content

Commit

Permalink
Merge pull request #22 from ladyada/master
Browse files Browse the repository at this point in the history
Fix off-by-one, replace write/read with write_then_readinto, allow straddling bits
  • Loading branch information
tannewt committed Feb 20, 2019
2 parents e6c0b45 + 6ded136 commit 27aef0d
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 40 deletions.
8 changes: 4 additions & 4 deletions adafruit_register/i2c_bit.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ def __init__(self, register_address, bit, register_width=1):

def __get__(self, obj, objtype=None):
with obj.i2c_device as i2c:
i2c.write(self.buffer, end=1, stop=False)
i2c.readinto(self.buffer, start=1)
i2c.write_then_readinto(self.buffer, self.buffer,
out_end=1, in_start=1, stop=False)
return bool(self.buffer[self.byte] & self.bit_mask)

def __set__(self, obj, value):
with obj.i2c_device as i2c:
i2c.write(self.buffer, end=1, stop=False)
i2c.readinto(self.buffer, start=1)
i2c.write_then_readinto(self.buffer, self.buffer,
out_end=1, in_start=1, stop=False)
if value:
self.buffer[self.byte] |= self.bit_mask
else:
Expand Down
46 changes: 25 additions & 21 deletions adafruit_register/i2c_bits.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,35 +45,39 @@ class RWBits:
:param int register_width: The number of bytes in the register. Defaults to 1.
"""
def __init__(self, num_bits, register_address, lowest_bit, register_width=1):
self.bit_mask = 0
for _ in range(num_bits):
self.bit_mask = (self.bit_mask << 1) + 1
self.bit_mask = self.bit_mask << (lowest_bit%8)
if self.bit_mask >= 0xFF:
raise ValueError("Cannot have more bits than fit in a single byte")

self.bit_mask = ((1 << num_bits)-1) << lowest_bit
#print("bitmask: ",hex(self.bit_mask))
if self.bit_mask >= 1 << (register_width*8):
raise ValueError("Cannot have more bits than register size")
self.lowest_bit = lowest_bit
self.buffer = bytearray(1 + register_width)
self.buffer[0] = register_address
self.lowest_bit = lowest_bit % 8 # lowest bit within byte
self.byte = lowest_bit // 8 + 1

def __get__(self, obj, objtype=None):
with obj.i2c_device as i2c:
i2c.write(self.buffer, end=1, stop=False)
i2c.readinto(self.buffer, start=1)
return (self.buffer[self.byte] & self.bit_mask) >> self.lowest_bit
i2c.write_then_readinto(self.buffer, self.buffer,
out_end=1, in_start=1, stop=False)
# read the number of bytes into a single variable
reg = 0
for i in range(len(self.buffer)-1, 0, -1):
reg = (reg << 8) | self.buffer[i]
return (reg & self.bit_mask) >> self.lowest_bit

def __set__(self, obj, value):
# Shift the value to the appropriate spot and set all bits that aren't
# ours to 1 (the negation of the bitmask.)
value = (value << self.lowest_bit) | ~self.bit_mask
value <<= self.lowest_bit # shift the value over to the right spot
with obj.i2c_device as i2c:
i2c.write(self.buffer, end=1, stop=False)
i2c.readinto(self.buffer, start=1)
# Set all of our bits to 1.
self.buffer[self.byte] |= self.bit_mask
# Set all 0 bits to 0 by anding together.
self.buffer[self.byte] &= value
i2c.write_then_readinto(self.buffer, self.buffer,
out_end=1, in_start=1, stop=False)
reg = 0
for i in range(len(self.buffer)-1, 0, -1):
reg = (reg << 8) | self.buffer[i]
#print("old reg: ", hex(reg))
reg &= ~self.bit_mask # mask off the bits we're about to change
reg |= value # then or in our new value
#print("new reg: ", hex(reg))
for i in range(1, len(self.buffer)):
self.buffer[i] = reg & 0xFF
reg >>= 8
i2c.write(self.buffer)

class ROBits(RWBits):
Expand Down
20 changes: 10 additions & 10 deletions adafruit_register/i2c_struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ def __init__(self, register_address, struct_format):
self.buffer[0] = register_address

def __get__(self, obj, objtype=None):
with obj.i2c_device:
obj.i2c_device.write(self.buffer, end=1, stop=False)
obj.i2c_device.readinto(self.buffer, start=1)
with obj.i2c_device as i2c:
i2c.write_then_readinto(self.buffer, self.buffer,
out_end=1, in_start=1, stop=False)
return struct.unpack_from(self.format, memoryview(self.buffer)[1:])

def __set__(self, obj, value):
struct.pack_into(self.format, self.buffer, 1, *value)
with obj.i2c_device:
obj.i2c_device.write(self.buffer)
with obj.i2c_device as i2c:
i2c.write(self.buffer)


class UnaryStruct:
Expand All @@ -82,17 +82,17 @@ def __init__(self, register_address, struct_format):
def __get__(self, obj, objtype=None):
buf = bytearray(1+struct.calcsize(self.format))
buf[0] = self.address
with obj.i2c_device:
obj.i2c_device.write(buf, end=1, stop=False)
obj.i2c_device.readinto(buf, start=1)
with obj.i2c_device as i2c:
i2c.write_then_readinto(buf, buf,
out_end=1, in_start=1, stop=False)
return struct.unpack_from(self.format, buf, 1)[0]

def __set__(self, obj, value):
buf = bytearray(1+struct.calcsize(self.format))
buf[0] = self.address
struct.pack_into(self.format, buf, 1, value)
with obj.i2c_device:
obj.i2c_device.write(buf)
with obj.i2c_device as i2c:
i2c.write(buf)


class ROUnaryStruct(UnaryStruct):
Expand Down
10 changes: 5 additions & 5 deletions adafruit_register/i2c_struct_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,16 @@ def _get_buffer(self, index):

def __getitem__(self, index):
buf = self._get_buffer(index)
with self.obj.i2c_device:
self.obj.i2c_device.write(buf, end=1, stop=False)
self.obj.i2c_device.readinto(buf, start=1)
with self.obj.i2c_device as i2c:
i2c.write_then_readinto(buf, buf,
out_end=1, in_start=1, stop=False)
return struct.unpack_from(self.format, buf, 1) # offset=1

def __setitem__(self, index, value):
buf = self._get_buffer(index)
struct.pack_into(self.format, buf, 1, *value)
with self.obj.i2c_device:
self.obj.i2c_device.write(buf)
with self.obj.i2c_device as i2c:
i2c.write(buf)

def __len__(self):
return self.count
Expand Down

0 comments on commit 27aef0d

Please sign in to comment.