from __future__ import absolute_import, division, print_function from builtins import * # @UnusedWildImport from mcculw import ul from mcculw.enums import InfoType, BoardInfo, DigitalInfo, DigitalPortType, \ DigitalIODirection, FunctionType from props.propsbase import Props from mcculw.ul import ULError class DigitalProps(Props): """Provides digital IO information on the hardware configured at the board number given. This class is used to provide hardware information for the library examples, and may change hardware values. It is recommended that the values provided by this class be hard-coded in production code. """ def __init__(self, board_num): self._board_num = board_num self.num_ports = self._get_num_digital_chans() self.port_info = [] for port_index in range(self.num_ports): self.port_info.append(PortInfo(board_num, port_index)) def _get_num_digital_chans(self): try: return ul.get_config( InfoType.BOARDINFO, self._board_num, 0, BoardInfo.DINUMDEVS) except ULError: return 0 class PortInfo(object): def __init__(self, board_num, port_index): self._board_num = board_num self._port_index = port_index self.type = self._get_digital_dev_type() self.first_bit = self._get_first_bit(port_index, self.type) self.num_bits = self._get_num_bits() self.in_mask = self._get_in_mask() self.out_mask = self._get_out_mask() self.is_bit_configurable = self._get_is_bit_configurable( self.type, self.first_bit, self.in_mask, self.out_mask) self.is_port_configurable = self._get_is_port_configurable( self.type, self.in_mask, self.out_mask) self.supports_input = self._get_supports_input( self.in_mask, self.is_port_configurable) self.supports_input_scan = self._get_supports_input_scan() self.supports_output = self._get_supports_output( self.out_mask, self.is_port_configurable) self.supports_output_scan = self._get_supports_output_scan() def _get_num_bits(self): return ul.get_config( InfoType.DIGITALINFO, self._board_num, self._port_index, DigitalInfo.NUMBITS) def _get_supports_input(self, in_mask, is_port_programmable): return in_mask > 0 or is_port_programmable def _get_supports_input_scan(self): try: ul.get_status(self._board_num, FunctionType.DIFUNCTION) except ULError: return False return True def _get_supports_output_scan(self): try: ul.get_status(self._board_num, FunctionType.DOFUNCTION) except ULError: return False return True def _get_supports_output(self, out_mask, is_port_programmable): return out_mask > 0 or is_port_programmable def _get_first_bit(self, port_index, port_type): # A few devices (USB-SSR08 for example) start at FIRSTPORTCL and # number the bits as if FIRSTPORTA and FIRSTPORTB exist for # compatibility with older digital peripherals if port_index == 0 and port_type == DigitalPortType.FIRSTPORTCL: return 16 return 0 def _get_is_bit_configurable(self, port_type, first_bit, in_mask, out_mask): if in_mask & out_mask > 0: return False # AUXPORT type ports might be configurable, check if d_config_bit # completes without error if port_type == DigitalPortType.AUXPORT: try: ul.d_config_bit( self._board_num, port_type, first_bit, DigitalIODirection.OUT) ul.d_config_bit( self._board_num, port_type, first_bit, DigitalIODirection.IN) except ULError: return False return True return False def _get_is_port_configurable(self, port_type, in_mask, out_mask): if in_mask & out_mask > 0: return False # Check if d_config_port completes without error try: ul.d_config_port(self._board_num, port_type, DigitalIODirection.OUT) ul.d_config_port(self._board_num, port_type, DigitalIODirection.IN) except ULError: return False return True def _get_digital_dev_type(self): return DigitalPortType(ul.get_config( InfoType.DIGITALINFO, self._board_num, self._port_index, DigitalInfo.DEVTYPE)) def _get_in_mask(self): return ul.get_config( InfoType.DIGITALINFO, self._board_num, self._port_index, DigitalInfo.INMASK) def _get_out_mask(self): return ul.get_config( InfoType.DIGITALINFO, self._board_num, self._port_index, DigitalInfo.OUTMASK)