Skip to content

Commit bf819ef

Browse files
committed
RWBits: Add support for signed registers
An example of a signed register is the calibration value of the PCF8523 real-time clock, which stores values from -64 to +63 in 7 bits. This could now be specified as calibration = i2c_bits.RWBits(7, 0xe, 0, signed=True) Note that assigning a negative value to an RWBits already worked, regardless of whether the register was signed, so it was already possible to *write* -2 to the register; this just allows it to be read back as -2 instead of 126.
1 parent 9f86b51 commit bf819ef

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

adafruit_register/i2c_bits.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@ class RWBits:
4545
:param type lowest_bit: The lowest bits index within the byte at ``register_address``
4646
:param int register_width: The number of bytes in the register. Defaults to 1.
4747
:param bool lsb_first: Is the first byte we read from I2C the LSB? Defaults to true
48+
:param bool signed: If True, the value is a "two's complement" signed value. If False, it is unsigned.
4849
"""
4950

5051
def __init__( # pylint: disable=too-many-arguments
51-
self, num_bits, register_address, lowest_bit, register_width=1, lsb_first=True,
52+
self, num_bits, register_address, lowest_bit, register_width=1, lsb_first=True, signed=False
5253
):
5354
self.bit_mask = ((1 << num_bits) - 1) << lowest_bit
5455
# print("bitmask: ",hex(self.bit_mask))
@@ -58,6 +59,7 @@ def __init__( # pylint: disable=too-many-arguments
5859
self.buffer = bytearray(1 + register_width)
5960
self.buffer[0] = register_address
6061
self.lsb_first = lsb_first
62+
self.sign_bit = (1 << (num_bits-1)) if signed else 0
6163

6264
def __get__(self, obj, objtype=None):
6365
with obj.i2c_device as i2c:
@@ -69,7 +71,11 @@ def __get__(self, obj, objtype=None):
6971
order = reversed(order)
7072
for i in order:
7173
reg = (reg << 8) | self.buffer[i]
72-
return (reg & self.bit_mask) >> self.lowest_bit
74+
reg = (reg & self.bit_mask) >> self.lowest_bit
75+
# If the value is signed and negative, convert it
76+
if reg & self.sign_bit:
77+
reg -= 2*self.sign_bit
78+
return reg
7379

7480
def __set__(self, obj, value):
7581
value <<= self.lowest_bit # shift the value over to the right spot

0 commit comments

Comments
 (0)