Esempio n. 1
0
    def __device_callback(self, device):
        """Internal device callback method.

        This method is called internally to allow attached devices to transparently
        select the appropriate TCA multiplexer channel. The TCA is accessed only if the
        device being accessed is not on the currently selected channel.

        :param device: the device for which the callback is being called.
        """
        # Check the device is attached, otherwise raise an exception
        if device not in self._attached_devices:
            raise I2CException('Device %s was not properly detached from the TCA' % device)

        # Call own callback (for chained TCAs)
        if self.pre_access is not None:
            self.pre_access(self)

        # Skip accessing the TCA if the current channel is already selected
        if self._attached_devices[device] == self._selected_channel:
            return

        self._selected_channel = self._attached_devices[device]

        # Write to the TCA to select the correct channel
        self.write8(0, 1 << self._attached_devices[device])
Esempio n. 2
0
    def attach_device(self, device, *args, **kwargs):
        """Attach an I2C device to the container.

        This method attaches a device to the container. The device must be an instance of,
        or type, derived from I2CDevice or I2CContainer. If a class is passed, a device of the
        appropriate type is initialised and returned.

        :param device: class or instance to attach to the TCA
        :param args: positional arguments to pass to device initialisation
        :param kwargs: keyword arguments to pass to device initialisation
        """
        # If passed a callable type for a device, initialise it with the appropriate arguments
        if callable(device):
            if self.pre_access is not None:
                self.pre_access(self)
            device = device(*args, **kwargs)

        # Raise an exception if the device is not and I2CDevice or I2CContainer instance
        if not isinstance(device, I2CDevice) and not isinstance(
                device, I2CContainer):
            raise I2CException(
                'Device %s must be of type or an instance of I2CDevice or I2CContainer'
                % device)

        # Append device to attached devices, set its callback and return
        self._attached_devices.append(device)
        device.pre_access = self._device_callback
        return device
Esempio n. 3
0
    def attach_device(self, channel, device, *args, **kwargs):
        """Attach an I2C device to the TCA multiplexer.

        This method attaches a device to the TCA multiplexer on a specified TCA
        channel. The device must be an instance of, or type, derived from I2CDevice or
        I2CContainer. If a class is passed, a device of the appropriate type is
        initialised and returned.

        :param channel: TCA channel on which the device is present
        :param device: class or instance to attach to the TCA
        :param args: positional arguments to pass to device initialisation
        :param kwargs: keyword arguments to pass to device initialisation
        """
        # If passed a callable type for a device, initialise it having selected the appropriate
        # TCA channel
        if callable(device):
            self.write8(0, 1 << channel)
            self._selected_channel = channel
            device = device(*args, **kwargs)

        # Raise an exception if the device is not and I2CDevice or I2CContainer instance
        if not isinstance(device, I2CDevice) and not isinstance(device, I2CContainer):
            raise I2CException(
                'Device %s must be a type or an instance of I2CDevice or I2CContainer' % device)

        # Add device to attached devices and set its pre-access callback
        self._attached_devices[device] = channel
        device.pre_access = self.__device_callback
        return device
Esempio n. 4
0
    def set_enables(self, channels):
        """Set the output enable for multiple channels.

        This method sets the output enable state of multiple channels specified in a
        dict of channel: enabled pairs, e.g. {0: True, 1: False, ...}.

        :param channels: dict of channel enables to set
        """
        data = {}

        for channel in channels:
            if channel > 3 or channel < 0:
                raise I2CException(
                    "%s is not a channel on the Quad. Must be between 0 & 3" %
                    channel)

            # If the channel is not currently in the desired state (on/off)
            if self.get_enable(channel) != channels[channel]:
                data[channel] = True

        # No channels to toggle
        if not len(data):
            return

        # Toggle the output enable of the Quad to set the appropriate enable state.
        # A 0-1-0 transition is required by the control circuit to enable a channel.
        self.mcp.disable_outputs()
        self.mcp.output_pins(data)
        self.mcp.disable_outputs()
Esempio n. 5
0
    def quad_enable_channel(self, quad_idx, channel_idx):
        """Enable a quad output channel.

        This method enables the specified quad output channel. It is primarily intended
        for use within a sequenced turn on via call to enable_all().

        :param quad_idx: index of quad to control
        :param channel_idx: index of the channel to turn on
        """
        if quad_idx >= self.num_quads or quad_idx < 0:
            raise I2CException("Illegal quad index {} specified".format(quad_idx))

        if channel_idx >= Quad.NUM_CHANNELS or channel_idx < 0:
            raise I2CException("Illegal channel index {} specified".format(channel_idx))

        logging.debug("Enabling quad {} channel {} output".format(quad_idx, channel_idx))
        self.quad[quad_idx].set_enable(channel_idx, True)
Esempio n. 6
0
    def get_temperature(self, sensor):
        """Get the value of a PSCU temperature sensor.

        This method returns the current temperature value of the specified sensor.

        :param sensor: temperature sensor index
        :returns: temperature value for sensor
        """
        if sensor >= self.num_temperatures or sensor < 0:
            raise I2CException('Illegal sensor index {} specified'.format(sensor))

        return self.__temperature_values[sensor]
Esempio n. 7
0
    def get_temperature_set_point_volts(self, sensor):
        """Get the raw set point of a PSCU temperature sensor.

        This method returns the current raw set point for the specified temperature sensor.

        :param sensor: temperature sensor index
        :returns: raw value of the temperature sensor set point in volts
        """
        if sensor >= self.num_temperatures or sensor < 0:
            raise I2CException('Illegal sensor index {} specified'.format(sensor))

        return self.__temperature_set_points_raw[sensor] * PSCU.TEMP_VREF
Esempio n. 8
0
    def get_humidity_name(self, sensor):
        """Get the name of a PSCU humidity sensor.

        This method returns the descriptive name for the specified PSCU humidity sensor.

        :param sensor: humidity sensor index
        :returns: humidity sensor decriptive name
        """
        if sensor >= self.num_humidities or sensor < 0:
            raise I2CException('Illegal sensor index {} specified'.format(sensor))

        return PSCU.HUMIDITY_SENSOR_NAMES[sensor]
Esempio n. 9
0
    def get_humidity_set_point_volts(self, sensor):
        """Get the raw set point of a PSCU humidity sensor.

        This method returns the current set point for the specified humidity sensor.

        :param sensor: humidity sensor index
        :returns: raw value of the humidity sensor set point in volts
        """
        if sensor >= self. num_humidities or sensor < 0:
            raise I2CException('Illegal sensor index {} specified'.format(sensor))

        return self.__humidity_set_points_raw[sensor] * PSCU.HUMIDITY_VREF
Esempio n. 10
0
    def get_humidity_disabled(self, sensor):
        """Get the disabled status of a PSCU humidity sensor.

        This method returns the current disable status for the specified humidity sensor.

        :param sensor: humidity sensor index
        :returns: humidity sensor disable status
        """
        if sensor >= self. num_humidities or sensor < 0:
            raise I2CException('Illegal sensor index {} specified'.format(sensor))

        return self.__humidity_disabled[sensor]
Esempio n. 11
0
    def get_humidity(self, sensor):
        """Get the value of a PSCU humidity sensor.

        This method returns the current humidity value of the specified sensor.

        :param sensor: humidity sensor index
        :returns: humidity value for sensor
        """
        if sensor >= self. num_humidities or sensor < 0:
            raise I2CException('Illegal sensor index {} specified'.format(sensor))

        return self.__humidity_values[sensor]
Esempio n. 12
0
    def get_humidity_set_point(self, sensor):
        """Get the set point of a PSCU humidity sensor.

        This method returns the current set point for the specified humidity sensor.

        :param sensor: humidity sensor index
        :returns: value of the humidity sensor set point
        """
        if sensor >= self. num_humidities or sensor < 0:
            raise I2CException('Illegal sensor index {} specified'.format(sensor))

        return self.__humidity_set_points[sensor]
Esempio n. 13
0
    def get_temperature_trace(self, sensor):
        """Get the trace status of a PSCU temperature sensor.

        This method returns the current trace status for the specified temperature sensor.

        :param sensor: temperature sensor index
        :returns: temperature sensor trace status
        """
        if sensor >= self.num_temperatures or sensor < 0:
            raise I2CException('Illegal sensor index {} specified'.format(sensor))

        return self.__temperature_traces[sensor]
Esempio n. 14
0
    def get_temperature_name(self, sensor):
        """Get the name of a PSCU temperature sensor.

        This method returns the descriptive name for the specified PSCU temperature sensor.

        :param sensor: temperature sensor index
        :returns: temperature sensor decriptive name
        """
        if sensor >= self.num_temperatures or sensor < 0:
            raise I2CException('Illegal sensor index {} specified'.format(sensor))

        return PSCU.TEMP_SENSOR_NAMES[sensor]
Esempio n. 15
0
    def get_quad_trace(self, quad_idx):
        """Get the trace status for a specified quad.

        This method returns the trace status for the specified quad.

        :param quad_idx: quad index
        :returns: quad trace status as bool
        """
        if quad_idx >= self.num_quads or quad_idx < 0:
            raise I2CException("Illegal quad index {} specified".format(quad_idx))

        return self.__quad_traces[quad_idx]
Esempio n. 16
0
    def get_humidity_mode(self, sensor):
        """Get the mode of a PSCU humidity sensor.

        This method returns the descriptive mode for the specified PSCU humidity sensor, i.e.
        whether the sensor channel has an over- or under-humidity trip condition.

        :param sensor: humidity sensor index
        :returns: humidity sensor decriptive mode as string
        """
        if sensor >= self.num_humidities or sensor < 0:
            raise I2CException('Illegal sensor index {} specified'.format(sensor))

        return self.__humidity_mode[sensor]
Esempio n. 17
0
    def remove_device(self, device):
        """Remove an I2C device from the TCA multiplexer.

        This method removes an attached device from the TCA multiplexer and clears the
        device callback to prevent TCA access for that device.

        :param device: Device to remove from the TCA.
        """
        if device not in self._attached_devices:
            raise I2CException('Device %s is not attached to this TCA' % device)

        self._attached_devices.pop(device)
        device.pre_access = None
Esempio n. 18
0
    def get_channel_current(self, channel):
        """Get output channel current.

        This method returns the current current on the specified output channel.

        :param channel: channel to get value for
        :return channel output current in amps
        """
        if channel > 3 or channel < 0:
            raise I2CException(
                "%s is not a channel on the Quad. Must be between 0 & 3" %
                channel)

        return self.__channel_current[channel]
Esempio n. 19
0
    def get_fuse_voltage(self, channel):
        """Get output channel fuse voltage.

        This method returns the current voltage before the fuse on the specified channel.

        :param channel: channel to get value for
        :return channel output fuse voltage in volts
        """
        if channel > 3 or channel < 0:
            raise I2CException(
                "%s is not a channel on the Quad. Must be between 0 & 3" %
                channel)

        return self.__fuse_voltage[channel]
Esempio n. 20
0
    def remove_device(self, device):
        """Remove an I2C device from the container.

        This method removes an attached device from the container and clears the
        device callback to prevent it being called for that device.

        :param device: Device to remove from the device.
        """
        if device in self._attached_devices:
            self._attached_devices.remove(device)
            device.pre_access = None
        else:
            raise I2CException(
                'Device %s was not attached to this I2CContainer' % device)
Esempio n. 21
0
    def get_enable(self, channel):
        """Get output channel enable.

        This method returns the enable status for the specified channel.

        :param channel: channel to get value for
        :return channel enable status as bool
        """
        if channel > 3 or channel < 0:
            raise I2CException(
                "%s is not a channel on the Quad. Must be between 0 & 3" %
                channel)

        return self.__channel_enable[channel]
Esempio n. 22
0
    def read_input_raw(self, channel):
        """Convert and read a raw ADC value on a channel.

        This method triggers a conversion on the specified channel and
        reads back the raw 16-bit value from the device

        :param channel: channel to convert
        :return raw conversion result
        """
        # Check legal channel requested
        if channel < 0 or channel >= self.NUM_ADC_CHANNELS:
            raise I2CException("Illegal channel {} requested".format(channel))

        # Trigger a conversion on channel, setting upper 4 bits of address pointer
        self.write8(0x70 + ((channel + 1) << 4), 0)

        # Read conversion register
        data = self.readU16(0)

        # Swap bytes to correct order
        data = ((data & 0xff) << 8) + ((data & 0xff00) >> 8)

        return data
Esempio n. 23
0
    def set_output_scaled(self, value):
        """Set the output voltage of the DAC.

        This method sets the output voltage of the DAC, specified as a fraction of the
        full scale, i.e between values of 0.0 and 1.0.

        :param value: output voltage value (0.0-1.0)
        """
        # Check a legal output value has been specified
        if value < 0.0 or value > 1.0:
            raise I2CException(
                "Illegal output value {} specified".format(value))

        # Convert the value to ADUs
        value = int(value * 4096)
        if value == 4096:
            value = 4095

        # Extract the MSB and LSB
        msb = (value & 0xFF00) >> 8
        lsb = (value & 0xFF)

        # Write values to device
        self.write8(msb, lsb)