From 24c6ce59141e6aa38286d1232527e3e6e9bd014c Mon Sep 17 00:00:00 2001 From: SquirtleSquadLeader <112285567+SquirtleSquadLeader@users.noreply.github.com> Date: Wed, 22 May 2024 21:28:15 -0400 Subject: [PATCH] Add files via upload Folder containing register.py for consideration into micropython-lib --- micropython/register/register.py | 999 +++++++++++++++++++++++++++++++ 1 file changed, 999 insertions(+) create mode 100644 micropython/register/register.py diff --git a/micropython/register/register.py b/micropython/register/register.py new file mode 100644 index 00000000..e1b09794 --- /dev/null +++ b/micropython/register/register.py @@ -0,0 +1,999 @@ +""" + * Author(s): SquirtleSquadLeader + + * License: MIT + + * Purpose: + * The purpose of this module is to provide easy I2C Register + * access. It is inspired by the CircuitPython Register + * module maintained by Adafruit. + + * RORegBit - Single bit Read Only + * RWRegBit - Single bit Read/Write + + * RORegBits - Multi-bit Read Only + * RWRegBits - Multi-bit Read/Write + + * ROReg - Single/Multi Read Only + * RWReg - Single/Multi Read/Write + + + * Notes: + 1) Reference format strings below: + Format C Type Standard size + c char 1 + b signed char 1 + B unsigned char 1 + h short 2 + H unsigned short 2 + i integer 4 + I unsigned int 4 + l long 4 + L unsigned long 4 + q long long 8 + Q unsigned long long 8 + f float 4 + d double 8 + + +""" + +from machine import I2C +from struct import pack, unpack + +class RORegBit: + def __init__(self, i2c, dev_addr, reg_addr, num_bytes, bit_location, endian='', fmt='B'): + """ + Creates an :class:`RORegBit` object which allows read only access to a single bit within a register. + + + :param i2c: I2C bus which connects the host system to the peripheral device + :type kind: machine.I2C() + :param dev_addr: I2C address of the device which + :type dev_addr: int() + :param reg_addr: Physical register address which contains the bit of interest + :type reg_addr: int() + :param num_bytes: Number of bytes to read + :type num_bytes: int() + :param bit_location: Location of bit within bitfield + :type bit_locatin: int() + :param endian: Endian-ness of system for which the code is intended to run on. str('') uses native Endian-ness. + :type endian: str() + :param fmt: Format code which is used to unpack data from bytes(). Defaults to 'B' which is good for a single 8-bit register + :type fmt: int() + + :return: An initialized RORegBit object + :rtype: RORegBit() + + + **Quickstart: Importing and using the device** + + Here is an example of using the :class:`RORegBit` class. + First you will need to import the following libraries: + + .. code-block:: python + + from machine import I2C + from register.register import RORegBit + + Once this is done you must define a :class:`machine.I2C` object and then pass that + to the :class:`RORegBit` object to instantiate it. + + .. code-block:: python + + i2c = I2C(0) # I2C details are project specific + + my_reg = RORegBit(i2c, 68, 5, 1, 5) + + 'my_reg' can now provide access to the :method:`__get__(). Using this method + will return the value of the bit found at :param bit_location:. + + .. code-block:: python + + value = my_reg.__get__() # 0 or 1 + + Alternatively, a :class:`RORegBit` object(s) can be placed within another class. + + .. code-block:: python + # import + from machine import I2C + from register.register import RORegBit + + # define I2C + i2c = I2C(0) + + # create class with desired functionality + class FooDevice: + + def __init__(self, i2c_bus): + self._my_reg_1 = RORegBit(i2c_bus, 68, 5, 1, 5) + self._my_reg_2 = RORegBit(i2c_bus, 68, 6, 1, 5) + + def get_my_reg1(self): + return self._my_reg_1.__get__() + + def get_my_reg2(self): + return self._my_reg_1.__get__() + + # invoke class object + device = FooDevice(i2c) + + """ + self._i2c = i2c + self._dev_addr = dev_addr + self._reg_addr = reg_addr + self._num_bytes = num_bytes + self._bit_location = bit_location + self._endian = endian + self._fmt = fmt + + __check_reg(self) + + del(i2c, dev_addr, reg_addr, num_bytes, bit_location, fmt) + + def __get__(self): + """ + :return: Returns the value of the bit located at :param bit_location: + :rtype: int() + """ + return __getbit(self) + +class RWRegBit: + def __init__(self, i2c, dev_addr, reg_addr, num_bytes, bit_location, endian='', fmt='B'): + """ + Creates an :class:`RORegBit` object which allows read and write access to a single bit within a register. + + :param i2c: I2C bus which connects the host system to the peripheral device + :type kind: machine.I2C() + :param dev_addr: I2C address of the device which + :type dev_addr: int() + :param reg_addr: Physical register address which contains the bit of interest + :type reg_addr: int() + :param num_bytes: Number of bytes to read + :type num_bytes: int() + :param bit_location: Location of bit within bitfield + :type bit_locatin: int() + :param endian: Endian-ness of system for which the code is intended to run on. str('') uses native Endian-ness. + :type endian: str() + :param fmt: Format code which is used to unpack data from bytes(). Defaults to 'B' which is good for a single 8-bit register + :type fmt: int() + + :return: An initialized RWRegBit object + :rtype: RWRegBit() + + + **Quickstart: Importing and using the device** + + Here is an example of using the :class:`RWRegBit` class. + First you will need to import the following libraries: + + .. code-block:: python + + from machine import I2C + from register.register import RWRegBit + + Once this is done you must define a :class:`machine.I2C` object and then pass that + to the :class:`RWRegBit` object to instantiate it. + + .. code-block:: python + + i2c = I2C(0) # I2C details are project specific + + my_reg = RWRegBit(i2c, 68, 5, 1, 5) + + 'my_reg' can now provide access to the :method:`__get__() and :method:`__set__(). + Using these methods will get/set the value of the bit found at :param bit_location:. + + .. code-block:: python + my_reg.__set__(1) + + print(my_reg.__get__()) # prints 1 + + Alternatively, a :class:`RWRegBit` object(s) can be placed within another class. + + .. code-block:: python + # import + from machine import I2C + from register.register import RWRegBit + + # define I2C + i2c = I2C(0) + + # create class with desired functionality + class FooDevice: + + def __init__(self, i2c_bus): + self._my_reg = RORegBit(i2c_bus, 68, 5, 1, 5) + + def get_my_reg(self): + return self._my_reg.__get__() + + def get_my_reg2(self, n): + return self._my_reg.__set__(n) + + # invoke class object + device = FooDevice(i2c) + + """ + self._i2c = i2c + self._dev_addr = dev_addr + self._reg_addr = reg_addr + self._num_bytes = num_bytes + self._bit_location = bit_location + self._endian = endian + self._fmt = fmt + + __check_reg(self) + + self._premask, self._postmask = __calc_mask(bit_location, bit_location, num_bytes) + + del(i2c, dev_addr, reg_addr, num_bytes, bit_location, endian, fmt) + + def __get__(self): + """ + :return: Returns the value of the bit located at :param bit_location: + :rtype: int() + """ + return __getbit(self) + + def __set__(self, setting): + """ + :return: Returns 'True' if operation successful + :rtype: bool() + """ + return __setbit(self, setting) + +class RORegBits: + def __init__(self, i2c, dev_addr, reg_addr, num_bytes, lsb, msb, endian='', fmt='B'): + """ + Creates an :class:`RORegBits` object which allows read only access to a sequential set of bits within a bitfield. + + :param i2c: I2C bus which connects the host system to the peripheral device + :type kind: machine.I2C() + :param dev_addr: I2C address of the device which + :type dev_addr: int() + :param reg_addr: Physical register address which contains the bit of interest + :type reg_addr: int() + :param num_bytes: Number of bytes to read + :type num_bytes: int() + :param lsb: Location of least significant bit within bitfield + :type lsb: int() + :param msb: Location of most significant bit within bitfield + :type msb: int() + :param endian: Endian-ness of system for which the code is intended to run on. str('') uses native Endian-ness. + :type endian: str() + :param fmt: Format code which is used to unpack data from bytes(). Defaults to 'B' which is good for a single 8-bit register + :type fmt: int() + + :return: An initialized RORegBits object + :rtype: RORegBits() + + + **Quickstart: Importing and using the device** + + Here is an example of using the :class:`RORegBits` class. + First you will need to import the following libraries: + + .. code-block:: python + + from machine import I2C + from register.register import RORegBits + + Once this is done you must define a :class:`machine.I2C` object and then pass that + to the :class:`RORegBits` object to instantiate it. + + .. code-block:: python + + i2c = I2C(0) # I2C details are project specific + + my_reg = RORegBits(i2c_bus, 68, 5, 1, 0, 2) + + 'my_reg' can now provide access to the :method:`__get__(). Using this method + will return the value of the bit found at :param bit_location:. + + .. code-block:: python + + value = my_reg.__get__() # Returns some value from 0b000 to 0b111 + + Alternatively, a :class:`RORegBits` object(s) can be placed within another class. + + .. code-block:: python + # import + from machine import I2C + from register.register import RORegBits + + # define I2C + i2c = I2C(0) + + # create class with desired functionality + class FooDevice: + + def __init__(self, i2c_bus): + self._my_reg_1 = RORegBits(i2c_bus, 68, 5, 1, 0, 2) + self._my_reg_2 = RORegBits(i2c_bus, 68, 6, 1, 3, 6) + + def get_my_reg1(self): + return self._my_reg_1.__get__() + + @property + def my_reg2(self): + return self._my_reg_2.__get__() + + # invoke class object + device = FooDevice(i2c) + + n1 = device.get_my_reg() + n2 = device.my_reg2 + + """ + self._i2c = i2c + self._dev_addr = dev_addr + self._reg_addr = reg_addr + self._num_bytes = num_bytes + self._endian = endian + self._fmt = fmt + + __check_reg(self) + + self._premask, self._mask, self._postmask = __calc_mask(lsb, msb, num_bytes) + + del(i2c, dev_addr, reg_addr, num_bytes, lsb, msb, endian, fmt) + + def __get__(self): + """ + :return: Returns the value of the bitfield located between :param lsb: and :param msb: + :rtype: int() + """ + return __getbits(self) + +class RWRegBits: + def __init__(self, i2c, dev_addr, reg_addr, num_bytes, lsb, msb, endian='', fmt='B'): + """ + Creates an :class:`RWRegBits` object which allows read and write access to a sequential set of bits within a bitfield. + + :param i2c: I2C bus which connects the host system to the peripheral device + :type kind: machine.I2C() + :param dev_addr: I2C address of the device which + :type dev_addr: int() + :param reg_addr: Physical register address which contains the bit of interest + :type reg_addr: int() + :param num_bytes: Number of bytes to read + :type num_bytes: int() + :param lsb: Location of least significant bit within bitfield + :type lsb: int() + :param msb: Location of most significant bit within bitfield + :type msb: int() + :param endian: Endian-ness of system for which the code is intended to run on. str('') uses native Endian-ness. + :type endian: str() + :param fmt: Format code which is used to unpack data from bytes(). Defaults to 'B' which is good for a single 8-bit register + :type fmt: int() + + :return: An initialized RWRegBits object + :rtype: RWRegBits() + + + **Quickstart: Importing and using the device** + + Here is an example of using the :class:`RWRegBits` class. + First you will need to import the following libraries: + + .. code-block:: python + + from machine import I2C + from register.register import RWRegBits + + Once this is done you must define a :class:`machine.I2C` object and then pass that + to the :class:`RWRegBits` object to instantiate it. + + .. code-block:: python + + i2c = I2C(0) # I2C details are project specific + + my_reg = RWRegBits(i2c_bus, 68, 5, 1, 0, 2) + + 'my_reg' can now provide access to :method:`__get__() and :method:`__set__(). + + .. code-block:: python + + my_reg.__set__(0b110) # Returns some value from 0b000 to 0b111 + value = my_reg.__get__() # Returns 0b110, assuming nothing changes + + Alternatively, a :class:`RWRegBits` object(s) can be placed within another class. + + .. code-block:: python + # import + from machine import I2C + from register.register import RWRegBits + + # define I2C + i2c = I2C(0) + + # create class with desired functionality + class FooDevice: + + def __init__(self, i2c_bus): + self._my_reg_1 = RWRegBits(i2c_bus, 68, 5, 1, 0, 2) + self._my_reg_2 = RWRegBits(i2c_bus, 68, 6, 1, 3, 6) + + def get_my_reg1(self): + return self._my_reg_1.__get__() + + def set_my_reg1(self, n): + return self._my_reg_1.__set__(n) + + @property + def my_reg2(self): + return self._my_reg_2.__get__() + + @my_reg2.setter + def my_reg2(self, n): + return self._my_reg_2.__set__(n) + + # invoke class object + device = FooDevice(i2c) + + device.set_my_reg(0b110) + print(device.get_my_reg()) # prints 6 + + device.my_reg2 = 0b110 + print(device.my_reg2) # prints 6 + + """ + self._i2c = i2c + self._dev_addr = dev_addr + self._reg_addr = reg_addr + self._num_bytes = num_bytes + self._endian = endian + self._fmt = fmt + + __check_reg(self) + + self._premask, self._mask, self._postmask = __calc_mask(lsb, msb, num_bytes) + + del(i2c, dev_addr, reg_addr, num_bytes, lsb, msb, fmt, endian) + + def __get__(self): + """ + :return: Returns the value of the bitfield located between :param lsb: and :param msb: + :rtype: int() + """ + return __getbits(self) + + def __set__(self, setting): + """ + :return: True if successful + :rtype: bool() + """ + return __setbits(self, setting) + +class ROReg: + def __init__(self, i2c, dev_addr, reg_addr, num_bytes=1, endian='', fmt='B'): + """ + Creates a :class:`ROReg` object which allows read only access to n number of sequential registers, + where n is specified by :param num_bytes:. + + + :param i2c: I2C bus which connects the host system to the peripheral device + :type kind: machine.I2C() + :param dev_addr: I2C address of the device which + :type dev_addr: int() + :param reg_addr: Physical register address which contains the bit of interest + :type reg_addr: int() + :param num_bytes: Number of bytes to read. Defaults to 1. + :type num_bytes: int() + :param fmt: Format code which is used to unpack data from bytes(). Defaults to 'B'. + :type fmt: int() + + :return: An initialized ROReg object + :rtype: ROReg() + + + **Quickstart: Importing and using the device** + + Here is an example of using the :class:`ROReg` class. + First you will need to import the following libraries: + + .. code-block:: python + + from machine import I2C + from register.register import ROReg + + Once this is done you must define a :class:`machine.I2C` object and then pass that + to the :class:`ROReg` object to instantiate it. + + .. code-block:: python + + i2c = I2C(0) # I2C details are project specific + + my_reg = ROReg(i2c, 68, 5) + + 'my_reg' can now provide access to the :method:`__get__(). Using this method + will return the value of the bit found at :param bit_location:. + + .. code-block:: python + + value = my_reg.__get__() # some value between 0b0 and 0b1111_1111 + + Alternatively, a :class:`ROReg` object(s) can be placed within another class. + + .. code-block:: python + # import + from machine import I2C + from register.register import ROReg + + # define I2C + i2c = I2C(0) + + # create class with desired functionality + class FooDevice: + + def __init__(self, i2c_bus): + self._my_reg_1 = ROReg(i2c_bus, 68, 5) + self._my_reg_2 = ROReg(i2c_bus, 68, 6) + + def get_my_reg1(self): + return self._my_reg_1.__get__() + + @property + def my_reg2(self): + return self._my_reg_1.__get__() + + # invoke class object + device = FooDevice(i2c) + + print(device.get_my_reg1()) + print(device.my_reg2) + + """ + self._i2c = i2c + self._dev_addr = dev_addr + self._reg_addr = reg_addr + self._num_bytes = num_bytes + self._fmt = fmt + self._endian = endian + + __check_reg(self) + + del(i2c, dev_addr, reg_addr, num_bytes, fmt, endian) + + def __get__(self): + """ + :return: Returns tuple containing n number of elements, where n is the number of characters in :param fmt: + :rtype: tuple() + """ + return __getreg(self) + +class RWReg: + """ + Creates a :class:`RWReg` object which allows read and write access to n number of sequential registers, + where n is specified by :param num_bytes:. + + :param i2c: I2C bus which connects the host system to the peripheral device + :type kind: machine.I2C() + :param dev_addr: I2C address of the device which + :type dev_addr: int() + :param reg_addr: Physical register address which contains the bit of interest + :type reg_addr: int() + :param num_bytes: Number of bytes to read. Defaults to 1. + :type num_bytes: int() + :param fmt: Format code which is used to unpack data from bytes(). Defaults to 'B'. + :type fmt: int() + + :return: An initialized RWReg object + :rtype: RWReg() + + + **Quickstart: Importing and using the device** + + Here is an example of using the :class:`RWReg` class. + First you will need to import the following libraries: + + .. code-block:: python + + from machine import I2C + from register.register import RWReg + + Once this is done you must define a :class:`machine.I2C` object and then pass that + to the :class:`RWReg` object to instantiate it. + + .. code-block:: python + + i2c = I2C(0) # I2C details are project specific + + my_reg = RWReg(i2c, 68, 5) + + 'my_reg' can now provide access to the :method:`__get__() and __set__(). + + .. code-block:: python + my_reg.__set__(0b0) + value = my_reg.__get__() # 0b0 if nothing changed + + Alternatively, a :class:`RWReg` object(s) can be placed within another class. + + .. code-block:: python + # import + from machine import I2C + from register.register import RWReg + + # define I2C + i2c = I2C(0) + + # create class with desired functionality + class FooDevice: + + def __init__(self, i2c_bus): + self._my_reg_1 = RWReg(i2c_bus, 68, 5) + self._my_reg_2 = RWReg(i2c_bus, 68, 6) + + def get_my_reg1(self): + return self._my_reg_1.__get__() + + def set_my_reg1(self, n): + return self._my_reg_1.__set__(n) + + @property + def my_reg2(self): + return self._my_reg_1.__get__() + + @my_reg2.setter + def my_reg2(self, n): + return self._my_reg_1.__set__(n) + + + # invoke class object + device = FooDevice(i2c) + + device.set_my_reg1(0b110) + print(device.get_my_reg1()) # prints 6, assuming nothing changed + + device.my_reg2 = 0b1111_0000 + print(device.my_reg2) # prints 240 + + """ + def __init__(self, i2c, dev_addr, reg_addr, num_bytes, endian='', fmt='B'): + self._i2c = i2c + self._dev_addr = dev_addr + self._reg_addr = reg_addr + self._num_bytes = num_bytes + self._fmt = fmt + self._endian = endian + + __check_reg(self) + + del(i2c, dev_addr, reg_addr, num_bytes, fmt, endian) + + def __get__(self): + """ + :return: Returns tuple containing n number of elements, where n is the number of characters in :param fmt: + :rtype: tuple() + """ + return __getreg(self) + + def __set__(self, setting): + """ + :param setting: Value(s) to be written to register(s). Order must match :param fmt:. + :type setting: int(), bytes(), bytearray(), or list/tuple containing those values in order + :return: Returns True if operation successful + :rtype: tuple() + """ + return __setreg(self, setting) + +""" +* +* GLOBAL HELPER FUNCTIONS +* +* +""" +def __getbit(reg_object): + if isinstance(reg_object, (RORegBit, RWRegBit)): + # Retrieve register value and unpack to int + value = reg_object._i2c.readfrom_mem(reg_object._dev_addr, reg_object._reg_addr, reg_object._num_bytes) + + # Unpack byte + value = unpack(reg_object._endian+reg_object._fmt, value)[0] + + # Perform shift followed by _AND_ operation to determine bit state + return (value >> reg_object._bit_location)&0b1 + + else: + raise TypeError("incorrect object type - must be RORegBit, RWRegBit") + +def __setbit(reg_object, setting): + if isinstance(reg_object, RWRegBit): + if setting in (0,1): + # Retrieve register value and unpack to int + value = reg_object._i2c.readfrom_mem(reg_object._dev_addr, reg_object._reg_addr, reg_object._num_bytes) + + # Unpack byte + value = unpack(reg_object._endian+reg_object._fmt, value)[0] + + # Assemble byte + value = (value®_object._postmask) + (setting<>reg_object._lsb + + else: + raise TypeError("incorrect object type - must be RORegBits, RWRegBits") + +def __setbits(reg_object, setting): + if isinstance(reg_object, RWRegBits): + if isinstance(setting, int) and setting <= reg_object._mask: + + # Retrieve register value and unpack to int + value = reg_object._i2c.readfrom_mem(reg_object._dev_addr, reg_object._reg_addr, reg_object._num_bytes) + + # Unpack bytes + value = unpack(reg_object._endian+reg_object._fmt, value)[0] + + # Assemble + value = (value®_object._postmask) + (setting<= 0: + if msb.__class__() == int() and msb >= 0: + if numbytes.__class__() == int() and numbytes >= 0: + + # Check for detectable errors + if msb>=lsb: + + # Single bit mask + if msb == lsb: + pre, post = 0b0, 0b0 + + # Calc post masking + for bit in range(msb+1, numbytes*8): + post = (post<<1) + 0b1 + + # Calc pre masking + for bit in range(0, lsb): + pre = (pre<<1) + 0b1 + + return pre, post + + # Multibit mask + else: + + # Values to return + pre, mask, post = 0b0, 0b0, 0b0 + + # Calc post masking + for bit in range(msb+1, numbytes*8): + post = (post<<1) + 0b1 + + # Calc bitfield masking + for bit in range(lsb, msb+1): + mask = (mask<<1) + 0b1 + + # No bits lower than 0 + if lsb == 0: + return 0b0, mask, post + + else: + for bit in range(0, lsb): + pre = (pre<<1) + 0b1 + + return pre, mask, post + else: + raise ValueError("msb must be greater than or equal to lsb") + else: + raise ValueError("numbytes must be of type int() and 0 or greater") + else: + raise ValueError("msb must be of type int() and 0 or greater") + else: + raise ValueError("lsb must be of type int() and 0 or greater") + +def __check_reg(reg_object): + + # Alowable struct.pack/unpack formats to check for + fmts = {'b':1, 'B':1, 'h':2, 'H':2, 'f':4, 'i':4, 'I':4, 'l':4, 'L':4, 'q':8, 'Q':8} + endians = '@><' + byte_count = 0 + + # Take in only register objects + if isinstance(reg_object, (RORegBit, RWRegBit, RORegBits, RWRegBits, ROReg, RWReg)): + + # Make sure they are strings + if type(reg_object._fmt) == str and type(reg_object._endian) == str: + + # Check each letter in format string, To see if allowable + for n in range(0, len(reg_object._fmt)): + if reg_object._fmt[n] in fmts: + # Add corresonding byte length to verify _num_bytes and format string agree + byte_count = byte_count + fmts[reg_object._fmt[n]] + + else: + raise ValueError(f"unsupported format code of '{reg_object._fmt[n]}'") + + if byte_count != reg_object._num_bytes: + raise ValueError(f"format string accounts for {byte_count} bytes, _num_bytes value of {reg_object._num_bytes} does not match") + + else: + raise TypeError("format and endian must be of type str()") + else: + raise TypeError("incorrect object type - must be ROReg, RWReg, ROBits, RWBits, ROReg, RWReg") + +class Transaction: + """ + The user can supply a transaction object with a list of any number of + Register objects. The Transaction object will then perform one I2C + transaction and return all data as a list OR perform all write operations. + + 1) The Register objects should all be from one physical I2C device + 2) True = Read, False = Write (Default is read) + 3) Reads can be from non-sequential registers + 4) Writes can be made only to sequential registers OR more than one + transaction will be generated + + i.e. + + # Define Register objects + register1 = ROBits() + register2 = ROBits() + register3 = ROBits() + + # Create list object containing only Register objects + list_of_registers = [register1, register2, register3] + + # Instantiate Transaction object + data_from_device = Transaction(list_of_registers) + + # Retrieve data + data = data_from_device.__get__() + + # Use data as desired + datapoint_1 = data_from_device[0] + datapoint_2 = data_from_device[1] + datapoint_3 = data_from_device[2] + """ + + + def __init__(self, read_or_write:bool = True, list_of_registers:list() =[]): + # Data + self.__list_of_registers = list_of_registers + + # Check if it is a list + if self.__list_of_registers.__class__() == list(): + + for reg in self.__list_of_registers: + # Check each element against all possible Register types + if self.__list_of_registers[reg].__class__() in [RORegBit, RORegBits, RWRegBit, RWRegBits, RORegStruct]: + pass + + else: + # Error - list_element[reg] not a register object + pass + + else: + # Error - list_of_registers object must be list() + pass + + def add_reg(self, reg_object): + """ + This function allows for register objects to be added to an already + instantiated Transaction object + """ + if reg_object.__class__() in [RORegBit, RORegBits, RWRegBit, RWRegBits, RORegStruct]: + self.__list_of_registers.append(reg_object) + + self._order_list() + + else: + # Error - reg object of incorrect type() + pass + + def rem_reg(self, index): + """ + This function allows for a register object to be removed from an + already instantiated transaction object + """ + if index in range(0, len(self.__list_of_registers)): + # Remove element + self.__list_of_registers.remove(index) + else: + # Error - index out of bounds + pass + + def order_list(self): + """ + Sorts list of registers by register address + """ + self.__list_of_registers = sorted(self.__list_of_registers, key=lambda reg:reg.reg_addr) + + def data(self): + """ + Performs 1 i2c transaction and returns data as list + """ + + + + + + + + + + +