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])
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
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
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()
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)
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]
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
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]
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
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]
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]
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]
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]
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]
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]
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]
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
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]
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]
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)
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]
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
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)