Beispiel #1
0
 def __init__(self, address=0xc, **kwargs):
     """Initialise the AD5321 device.
     :param address: address of the AD5321 on the I2C bus
     :param kwargs: keyword arguments to be passed to the underlying I2CDevice
     """
     # Initialise the I2CDevice superclass instance
     I2CDevice.__init__(self, address, **kwargs)
    def test_change_default_bus(self, test_i2c_device):

        default_i2c_bus = 0
        I2CDevice.set_default_i2c_bus(default_i2c_bus)

        new_device = I2CDevice(test_i2c_device.device_address,
                               debug=test_i2c_device.device_debug)
        assert default_i2c_bus == new_device.busnum
Beispiel #3
0
    def __init__(self, address, **kwargs):

        I2CDevice.__init__(self, address, **kwargs)
        self.address = address
        #addresses of the 4 DACs
        self.dacs = [0x01, 0x02, 0x04, 0x08]
        #store dac values to minimise i2c traffic
        self.dac_values = [0x00, 0x00, 0x00, 0x00]
        #store
        self.dac_mult = [0.0004, 0.1, 0.1, 0.00002]
Beispiel #4
0
    def __init__(self, address=0x20, **kwargs):
        """Initialise the AD7998 device.

        :param address: address of the AD7998 device on the I2C bus
        :param kwargs: keyword arguments to be passed to the underlying I2CDevice
        """
        # Initialise the I2CDevice superclass instance
        I2CDevice.__init__(self, address, **kwargs)

        # Set cycle register to fastest conversion mode
        self.write8(3, 1)
Beispiel #5
0
    def __init__(self, address=0x68, **kwargs):
        """
        Initialise the SI5324 device.

        :param address: The address of the SI5324 is determined by pins A[2:0] as follows:
                        0b1101[A2][A1][A0].
        """
        I2CDevice.__init__(self, address, **kwargs)
        logger.info(
            "Created new si5324 instance with address 0x{:02X}.".format(
                address))
        self.iCAL_required = True  # An iCAL is required at least once before run
Beispiel #6
0
    def __init__(self, address=0x20, **kwargs):
        """Initialise the MCP23008 device.

        :param address: address of the MCP23008 deviceon the I2C bus
        :param kwargs: keyword arguments to be passed to the underlying I2CDevice
        """
        # Initialise the I2CDevice superclass instance
        I2CDevice.__init__(self, address, **kwargs)

        # Synchronise local buffered register values with state of device
        self.__iodir = self.readU8(self.IODIR)
        self.__gppu = self.readU8(self.GPPU)
        self.__gpio = self.readU8(self.GPIO)
Beispiel #7
0
    def __init__(self, address=0x50, **kwargs):
        """Initialise the TPL0102 device.
        :param address: The address of the TPL0102 default: 0x50
        """

        I2CDevice.__init__(self, address, **kwargs)

        #Read back current wiper settings
        self.__wiper_pos = [self.readU8(0), self.readU8(1)]
        self.__tot_resistance = 100.0
        self.__low_pd = [0.0, 0.0]
        self.__high_pd = [3.3, 3.3]
        self.disable_shutdown(True)
        self.set_non_volatile(False)
Beispiel #8
0
    def __init__(self, address=0x70, allowMultiple=True, **kwargs):
        """Initialise the the TCA9548 device.

        :param address: address of TCA9548 on the I2C bus
        :param kwargs: keyword arguments to be passed to underlying I2CDevice
        """
        # Initialise the I2CDevice superclass instance
        I2CDevice.__init__(self, address, **kwargs)

        # Clear attached devices and currently enabled channel
        self._attached_devices = {}
        self._selected_channel = None

        # Disable any already enabled devices by clearing output bus selection
        self.write8(0, 0)
Beispiel #9
0
    def _init_select(self, chosen_address):
        """
        Set up the FireFly to respond on a chosen address, and to use the select line correctly
        when when the _select_device() functions are used.
        """
        # Set up device to respond on chosen address with _select_device() functions
        if self._select_line is None:
            # If no selectL line is provided, it must be assumed that it is being pulled low
            # externally, or setup cannot be completed. It must also be the only device pulled low
            # on the bus.
            self._log.warning(
                "Select Line not specified. "
                "This MUST be the only device with selectL pulled low on the bus"
            )

        # Apply extra address-specific measures
        if chosen_address in [0x00, 0x7F]:
            # Revert to default behaviour, where address is 0x50 when selectL pulled low
            self._base_address = 0x50
            return

        if 0x40 < chosen_address < 0x7E and chosen_address is not 0x50:
            # Addresses in this range will ignore selectL, so disable it (if not already None)
            # Note that 0x50 is a special case as the default, since it is responded to with
            # address register set to 0x00, and so not in this range...
            self._select_line = None

        # Write address field with initial settings for select line
        self._tx_device = I2CDevice(
            0x50)  # Temporarily assign the tx_device to default address
        self.write_field(self.FLD_I2C_Address, [chosen_address])
        self._base_address = chosen_address
        self._tx_device = None  # Will be properly assigned later
Beispiel #10
0
    def _init_select(self, chosen_address):
        """
        Set up the FireFly to respond on a chosen address, and to use the select line correctly
        when when the _select_device() functions are used.
        """
        # Set up device to respond on chosen address with _select_device() functions
        if self._select_line is None:
            # If no selectL line is provided, it must be assumed that it is being pulled low
            # externally, or setup cannot be completed. It must also be the only device pulled low
            # on the bus.
            self._log.warning(
                "Select Line not specified. "
                "This MUST be the only device with selectL pulled low on the bus"
            )

        # Apply extra address-specific measures
        if chosen_address == 0x00 or 0x7F < chosen_address < 0xFF:
            # Revert to default behaviour, where address is 0x50 when selectL pulled low
            self._log.warning(
                "Device will be responding to 0x50, not {}".format(
                    chosen_address))
            self._address = 0x50
            return

        # Write address field with initial settings for select line
        self._device = I2CDevice(
            0x50)  # Temporarily assign the tx_device to default address
        self.write_field(self.FLD_I2C_Address, [chosen_address])
        self._address = chosen_address
        self._device = None  # Will be properly assigned later
 def __init__(self):
     self.device_busnum = 1
     self.device_address = 0x70
     self.device_debug = True
     self.device = I2CDevice(self.device_address, self.device_busnum,
                             self.device_debug)
     self.device.pre_access = Mock()
Beispiel #12
0
    def __init__(self, loggername, base_address=0x00, select_line=None):
        """
        Configure the two I2C device drivers, and set up the FireFly device to a specified address
        if requried. Also initiate use of the GPIO selection line.
        """
        _FireFly_Interface.__init__(self, 0,
                                    loggername)  # Channels start at 00

        # Set up select line use for the given address
        self._select_line = select_line

        self._base_address = base_address
        self._init_select(base_address)  # May modify _base_address

        # CXP uses seperate 'devices' for Tx/Rx operations
        self._tx_device = I2CDevice(self._base_address)
        self._rx_device = I2CDevice(self._base_address + 4)
    def test_remove_missing_device(self, test_i2c_container):

        device = I2CDevice(0x24)

        assert_message = 'Device %s was not attached to this I2CContainer' % device
        with pytest.raises(I2CException) as excinfo:
            test_i2c_container.container.remove_device(device)

            assert assert_message in excinfo.value
Beispiel #14
0
    def test_remove_missing_device(self, test_tca9548_driver):

        device_not_attached = I2CDevice(0x20)

        exc_message = 'Device %s is not attached to this TCA' % device_not_attached
        with pytest.raises(I2CException) as excinfo:
            test_tca9548_driver.tca.remove_device(device_not_attached)

            assert exc_message in excinfo.value
Beispiel #15
0
    def __init__(self, address=0x55, model=SI570_C, **kwargs):
        """Initialise the SI570 and determine the crystal frequency.
        This resets the device to the factory programmed frequency.
        """

        I2CDevice.__init__(self, address, **kwargs)

        # Registers used are dependant on the device model
        self.__register = 13 if model == self.SI570_C else 7

        # Reset device to 156.25MHz and calculate fXTAL
        self.write8(135, 1 << 7)
        while self.readU8(135) & 1:
            continue

        # Device is reset, read initial register configurations
        data = self.readList(self.__register, 6)
        self.__hs_div, self.__n1, self.__rfreq = self.__calculate_params(data)
        self.__fxtal = (156250000 * self.__hs_div * self.__n1) / self.__rfreq / 1000000
        self.__fout = (self.__fxtal * self.__rfreq) / (self.__n1 * self.__hs_div)
Beispiel #16
0
    def test_field_read(self, test_firefly):
        # These functions have been tested indirectly already, but these are to double-check
        # any untested functionality. The superfunction will be tested, which will sidestep the
        # page selection logic.
        tmp_mock_readList = MagicMock()
        with \
                patch.object(I2CDevice, 'readList') as tmp_mock_readList:

            test_generic_interface = _FireFly_Interface(0, None)
            test_i2cdevice = I2CDevice(0x50)

            # Check that reading a byte works normally
            tmp_mock_readList.side_effect = lambda reg, num: [0xAA]
            tmp_field = _Field(register=0x00, startbit=7, length=8)
            assert (test_generic_interface.read_field(
                tmp_field, test_i2cdevice) == [0xAA])

            # Check that reading a subsection of a byte works normally
            tmp_mock_readList.side_effect = lambda reg, num: [0xAA]
            tmp_field.startbit = 6
            tmp_field.length = 3
            result = test_generic_interface.read_field(tmp_field,
                                                       test_i2cdevice)
            print(result)
            assert (result == [0b010])  # 0b10101010 bits 6-4 are 0b010

            # Check that reading a selection of bits over a byte boundary works
            tmp_mock_readList.side_effect = lambda reg, num: [
                0b00000111, 0b11100000
            ]
            tmp_field.startbit = 11
            tmp_field.length = 8
            result = test_generic_interface.read_field(tmp_field,
                                                       test_i2cdevice)
            assert (result == [0b01111110])

            # Check that if the I2CDevice returns nothing, an error is raised
            tmp_mock_readList.side_effect = None
            with pytest.raises(I2CException, match=".*Failed to read byte.*"):
                result = test_generic_interface.read_field(
                    tmp_field, test_i2cdevice)

            # Check that if the number of full bytes returned is not as expected, an error is raised
            tmp_mock_readList.side_effect = lambda reg, num: [1, 2]
            tmp_field.startbit = 2
            tmp_field.length = 1
            with pytest.raises(
                    I2CException,
                    match=
                    ".*Number of bytes read incorrect.*Expected 1, got 2.*"):
                result = test_generic_interface.read_field(
                    tmp_field, test_i2cdevice)
Beispiel #17
0
    def __init__(self, address=0x2F, **kwargs):
        #Initialise the AD5272 device.
        #:param address: The address of the AD5272 default: 0x2F when ADDR=0, 2E when ADD= FLOAT (see schematics)
        #

        I2CDevice.__init__(self, address, **kwargs)
        self.write8(0x1C,
                    0x02)  # enable the update of wiper position by default

        #Read back current wiper settings
        self.write8(
            0x08,
            0x00)  # Have to write code 0x0800 to initiate a read of the wiper
        tmp = self.readU16(0)  # read the result into tmp variable
        self.__wiper_pos = ((tmp & 0x03) << 8) + (
            (tmp & 0xFF00) >> 8
        )  #mask off lower 8 bits and shift down 8, mask off upper 8 bits and bits 7-2 & shift up 8

        #read the contents of the control register
        #0x1 = 50-TP program enable 0 = default, dissable
        #0x2 = RDAC register write protect 0 = default, wiper position frozen, 1 = allow update via i2c
        #0x4 = Resistance performance enable 0 = default = enabled, 1 = dissbale
        #0x8 = 50-TP memory program success bit 0 = default = unsuccessful, 1 = successful

        #send the command to read the contents of the control register
        self.write8(
            0x20, 0x00
        )  #send the command to read the contents of the control register

        # when read, byte swap to get register contents
        self.__control_reg = (self.readU16(0) & 0xF00 >> 8)

        #Internal variable settings depending on device / voltage connections
        self.__num_wiper_pos = 1024
        self.__tot_resistance = 100.0
        self.__low_pd = 0.0
        self.__high_pd = 3.3
Beispiel #18
0
    def __init__(self, loggername, address=0x00, select_line=None):
        """
        Configure the two I2C device drivers, and set up the FireFly device to a specified address
        if requried. Also initiate use of the GPIO selection line.
        """
        _FireFly_Interface.__init__(
            self, 1, loggername)  # Channels start at 1 for some reason...

        # Set up select line use for the given address
        self._select_line = select_line

        self._address = address
        self._init_select(address)  # May modify _address

        self._device = I2CDevice(self._address)
        self._device.enable_exceptions()  #TODO remove
Beispiel #19
0
    def __init__(self, use_spi=True, bus=0, device=0):
        """Initialise the BME280 device.

        :param use_spi: bool to specify device type for bme to use. 
        Default True = SPI will be used, False = I2C.
        :param bus: bus number for SPI/I2C device. Default: 0
        :param device: device number for SPI device. Default: 0

        Device settings can be adjusted with the functions in the respective device class.
        """
        self.use_spi = use_spi

        if self.use_spi:  # using SPI
            self.device = SPIDevice(bus=bus, device=device)
            # This device is compatible with SPI modes 0 and 2 (00, 11).
            self.device.set_mode(0)
            # Longest transaction is 24 bytes read, one written.
            self.device.set_buffer_length(25)
        else:
            self.device = I2CDevice(address=_BME280_ADDRESS, busnum=bus)

        # Check device ID.
        chip_id = self._read_byte(_BME280_REGISTER_CHIPID)
        print("Chip ID: 0x%x" % int(chip_id))

        if _BME280_CHIPID != chip_id:
            raise RuntimeError('Failed to find BME280! Chip ID 0x%x' % chip_id)

        # Reasonable defaults.
        self._iir_filter = IIR_FILTER_DISABLE
        self._overscan_humidity = OVERSCAN_X1
        self._overscan_temperature = OVERSCAN_X1
        self._overscan_pressure = OVERSCAN_X16
        self._t_standby = STANDBY_TC_125
        self._mode = MODE_SLEEP
        self._reset()
        self._read_coefficients()
        self._write_ctrl_meas()
        self._write_config()

        # Pressure in hPa at sea level. Used to calibrate altitude.
        self_t_fine = None
    def test_attach_existing_device(self, test_i2c_container):

        device = I2CDevice(0x21)
        test_i2c_container.container.attach_device(device)
        assert device in test_i2c_container.container._attached_devices
Beispiel #21
0
    def test_field_write(self, test_firefly):
        # These functions have been tested indirectly already, but these are to double-check
        # any untested functionality. The superfunction will be tested, which will sidestep the
        # page selection logic.
        tmp_mock_readList = MagicMock()
        tmp_mock_writeList = MagicMock()
        with \
                patch.object(I2CDevice, 'writeList') as tmp_mock_writeList, \
                patch.object(I2CDevice, 'readList') as tmp_mock_readList:
            pass

            test_generic_interface = _FireFly_Interface(0, None)
            test_i2cdevice = I2CDevice(0x50)

            # Check that writing a byte works
            tmp_mock_writeList.reset_mock()
            tmp_mock_readList.side_effect = lambda reg, ln: [
                0x00
            ]  # Used when reading old value
            tmp_field = _Field(register=0x00, startbit=7, length=8)
            test_generic_interface.write_field(tmp_field, [0xAA],
                                               test_i2cdevice)
            tmp_mock_writeList.assert_called_with(0x00, [0xAA])

            # Check that writing a subsection of a byte works
            tmp_mock_writeList.reset_mock()
            tmp_field = _Field(register=0x00, startbit=6, length=3)
            tmp_mock_readList.side_effect = lambda reg, ln: [
                0x00
            ]  # Initial value 0
            test_generic_interface.write_field(tmp_field, [0b101],
                                               test_i2cdevice)
            tmp_mock_writeList.assert_called_with(0x00, [0b01010000])

            # Check that writing a selection of bits over a byte boundary works
            tmp_mock_writeList.reset_mock()
            tmp_field = _Field(register=0x00, startbit=11, length=8)
            tmp_mock_readList.side_effect = lambda reg, ln: [
                0x00, 0x00
            ]  # Initial values 0
            test_generic_interface.write_field(tmp_field, [0b10101010],
                                               test_i2cdevice)
            tmp_mock_writeList.assert_called_with(0x00,
                                                  [0b00001010, 0b10100000])

            # Check that if the value does not fit inside the specified field an error is raised
            tmp_mock_writeList.reset_mock()
            tmp_field = _Field(register=0x00, startbit=3, length=4)
            tmp_mock_readList.side_effect = lambda reg, ln: [
                0x00
            ]  # Initial value 0
            with pytest.raises(I2CException,
                               match=".*Value 255 does not fit.*length 4.*"):
                test_generic_interface.write_field(tmp_field, [0b11111111],
                                                   test_i2cdevice)

            # Check that the verify passes on success
            tmp_mock_writeList.reset_mock()
            tmp_mock_readList.side_effect = lambda reg, ln: [
                0xAA
            ]  # Readback will return 0xAA
            tmp_field = _Field(register=0x00, startbit=7, length=8)
            test_generic_interface.write_field(tmp_field, [0xAA],
                                               test_i2cdevice,
                                               verify=True)

            # Check that the verify raises an error on failure
            tmp_mock_writeList.reset_mock()
            tmp_mock_readList.side_effect = lambda reg, ln: [
                0x00
            ]  # Readback will return 0x00
            tmp_field = _Field(register=0x00, startbit=7, length=8)
            with pytest.raises(
                    I2CException,
                    match=".*Value.*was not successfully written.*"):
                test_generic_interface.write_field(tmp_field, [0xAA],
                                                   test_i2cdevice,
                                                   verify=True)
Beispiel #22
0
    def test_device_info_report_pn(self, test_firefly):
        with \
                patch.object(I2CDevice, 'write8') as mock_I2C_write8, \
                patch.object(I2CDevice, 'readU8') as mock_I2C_readU8, \
                patch.object(I2CDevice, 'writeList') as mock_I2C_writeList, \
                patch.object(I2CDevice, 'readList') as mock_I2C_readList:
            # Set up the mocks
            mock_I2C_readList.side_effect = model_I2C_readList
            mock_I2C_writeList.side_effect = model_I2C_writeList
            mock_I2C_write8.side_effect = model_I2C_write8
            mock_I2C_readU8.side_effect = model_I2C_readU8

            mock_registers_reset()  # reset the register systems, PS is 0
            mock_I2C_SwitchDeviceQSFP()  # Model a QSFP device

            valid_part_number = 'B0425xxx0x1xxx  '
            input_vendor_name = 'PRETEND MANUFAC '

            I2CDevice.writeList(168,
                                [ord(x)
                                 for x in valid_part_number])  # Insert info
            I2CDevice.writeList(148,
                                [ord(x)
                                 for x in input_vendor_name])  # Insert info

            test_firefly = FireFly()

            # Check fields returned
            ret_pn, ret_vn, ret_oui = test_firefly.get_device_info()
            assert (valid_part_number == ret_pn)
            assert (input_vendor_name == ret_vn)
            # (OUI is already set to Samtec's one, or init will fail)

            # Check part number parts
            assert (test_firefly.data_rate_Gbps == 25)
            assert (test_firefly.num_channels == 4)

            # Check that an unsupported num of channels raises an error
            pn_unsupported_channels = 'B0625xxx0x1xxx  '  # 6-channel (not real)
            I2CDevice.writeList(
                168, [ord(x) for x in pn_unsupported_channels])  # Insert info
            with pytest.raises(Exception,
                               match=".*Unsupported number of channels: 06.*"):
                test_firefly = FireFly()

            # Check that an invalid direction raises an error
            pn_invalid_direction = 'P0425xxx0x1xxx  '  # 'P' direction (not real)
            I2CDevice.writeList(168,
                                [ord(x)
                                 for x in pn_invalid_direction])  # Insert info
            with pytest.raises(
                    Exception,
                    match=
                    ".*Data direction P in part number field not recognised.*"
            ):
                test_firefly = FireFly()

            # Check that invalid static padding fields raise an error (these never change)
            pn_invalid_static_bits = 'B0425xxx1x0xxx  '  # Static bits 0, 1 swapped
            I2CDevice.writeList(
                168, [ord(x) for x in pn_invalid_static_bits])  # Insert info
            with pytest.raises(Exception, match=".*Invalid PN static field.*"):
                test_firefly = FireFly()
Beispiel #23
0
    def _get_interface(select_line, default_address, log_instance=None):
        """
        Attempt to automatically determine the interface type (QSFP+ or CXP) that is being used by
        the FireFly device at a given I2C address, using a given select line (if used).

        :param select_line:     gpiod Line being used for CS. Provide with gpio_bus or gpiod.
        :param default_address: The address to use when attempting to communicate. Most likely this
                                is the default (0x50) since the device has not been configured.
        :param log_instance:    Because this is a static method, the self._log must be passed in
                                for logging to work.
        :return:                Interface type (FireFly.INTERFACE_*) or None if it could not be
                                determined automatically.
        """
        # Assuming the device is currently on the default address, and OUI is 0x40C880
        tempdevice = I2CDevice(default_address)

        if select_line is not None:
            # Check GPIO control is available
            if not _GPIO_AVAIL:
                raise I2CException(
                    "GPIO control is not available, cannot use CS line")

            # Check select_line is valid
            try:
                if not select_line.is_requested():
                    raise I2CException(
                        "GPIO Line supplied is not requested by user")
            except AttributeError:
                raise I2CException(
                    "Supplied line was not a valid object. Use gpiod or odin_devices.gpio_bus"
                )

            # GPIO select line low
            select_line.set_value(0)

        # Force the page to 0x00
        tempdevice.write8(127, 0x00)
        # Read bytes 168, 169, 170
        cxp_oui = tempdevice.readList(168, 3)
        # Read bytes 165, 166, 167
        qsfp_oui = tempdevice.readList(165, 3)

        if select_line is not None:
            # GPIO select line high
            select_line.set_value(1)

        if log_instance is not None:
            log_instance.debug(
                "Reading OUI fields from device at {}: CXP OUI {}, QSFP OUI {}"
                .format(default_address, cxp_oui, qsfp_oui))

        if cxp_oui == [0x04, 0xC8, 0x80]:
            # OUI found correctly, must be CXP device
            return FireFly.INTERFACE_CXP
        elif qsfp_oui == [0x04, 0xC8, 0x80]:
            # OUI found correctly, must be QSFP interface
            return FireFly.INTERFACE_QSFP
        else:
            if log_instance is not None:
                log_instance.critical(
                    "OUI not found during automatic detection")
            return None