aboutsummaryrefslogtreecommitdiff
path: root/src/pico/adafruit_register/i2c_bits.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/pico/adafruit_register/i2c_bits.py')
-rwxr-xr-xsrc/pico/adafruit_register/i2c_bits.py114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/pico/adafruit_register/i2c_bits.py b/src/pico/adafruit_register/i2c_bits.py
new file mode 100755
index 0000000..9a9f1d2
--- /dev/null
+++ b/src/pico/adafruit_register/i2c_bits.py
@@ -0,0 +1,114 @@
+# SPDX-FileCopyrightText: 2016 Scott Shawcroft for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+# pylint: disable=too-few-public-methods
+
+"""
+`adafruit_register.i2c_bits`
+====================================================
+
+Multi bit registers
+
+* Author(s): Scott Shawcroft
+"""
+
+__version__ = "0.0.0+auto.0"
+__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Register.git"
+
+try:
+ from typing import Optional, Type, NoReturn
+ from circuitpython_typing.device_drivers import I2CDeviceDriver
+except ImportError:
+ pass
+
+
+class RWBits:
+ """
+ Multibit register (less than a full byte) that is readable and writeable.
+ This must be within a byte register.
+
+ Values are `int` between 0 and 2 ** ``num_bits`` - 1.
+
+ :param int num_bits: The number of bits in the field.
+ :param int register_address: The register address to read the bit from
+ :param int lowest_bit: The lowest bits index within the byte at ``register_address``
+ :param int register_width: The number of bytes in the register. Defaults to 1.
+ :param bool lsb_first: Is the first byte we read from I2C the LSB? Defaults to true
+ :param bool signed: If True, the value is a "two's complement" signed value.
+ If False, it is unsigned.
+ """
+
+ def __init__( # pylint: disable=too-many-arguments
+ self,
+ num_bits: int,
+ register_address: int,
+ lowest_bit: int,
+ register_width: int = 1,
+ lsb_first: bool = True,
+ signed: bool = False,
+ ) -> None:
+ 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.lsb_first = lsb_first
+ self.sign_bit = (1 << (num_bits - 1)) if signed else 0
+
+ def __get__(
+ self,
+ obj: Optional[I2CDeviceDriver],
+ objtype: Optional[Type[I2CDeviceDriver]] = None,
+ ) -> int:
+ with obj.i2c_device as i2c:
+ i2c.write_then_readinto(self.buffer, self.buffer, out_end=1, in_start=1)
+ # read the number of bytes into a single variable
+ reg = 0
+ order = range(len(self.buffer) - 1, 0, -1)
+ if not self.lsb_first:
+ order = reversed(order)
+ for i in order:
+ reg = (reg << 8) | self.buffer[i]
+ reg = (reg & self.bit_mask) >> self.lowest_bit
+ # If the value is signed and negative, convert it
+ if reg & self.sign_bit:
+ reg -= 2 * self.sign_bit
+ return reg
+
+ def __set__(self, obj: I2CDeviceDriver, value: int) -> None:
+ value <<= self.lowest_bit # shift the value over to the right spot
+ with obj.i2c_device as i2c:
+ i2c.write_then_readinto(self.buffer, self.buffer, out_end=1, in_start=1)
+ reg = 0
+ order = range(len(self.buffer) - 1, 0, -1)
+ if not self.lsb_first:
+ order = range(1, len(self.buffer))
+ for i in order:
+ 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 reversed(order):
+ self.buffer[i] = reg & 0xFF
+ reg >>= 8
+ i2c.write(self.buffer)
+
+
+class ROBits(RWBits):
+ """
+ Multibit register (less than a full byte) that is read-only. This must be
+ within a byte register.
+
+ Values are `int` between 0 and 2 ** ``num_bits`` - 1.
+
+ :param int num_bits: The number of bits in the field.
+ :param int register_address: The register address to read the bit from
+ :param type lowest_bit: The lowest bits index within the byte at ``register_address``
+ :param int register_width: The number of bytes in the register. Defaults to 1.
+ """
+
+ def __set__(self, obj: I2CDeviceDriver, value: int) -> NoReturn:
+ raise AttributeError()