def attach_irq(self, event, callback=None, user_object=None, debounce_time=50): """ Attach (enable) or reconfigure GPIO interrupt event. :param event: GPIO interrupt event. Can have one of these values: GPIO.RISE, GPIO.FALL, GPIO.CHANGE, \ GPIO.LOW or GPIO.HIGH. :param callback: User callback function. This function is executed when the interrupt event is received. \ It should take two arguments: interrupt event description and user object. Interrupt event descriptor is \ dictionary with three fields: 'id' - the interrupt ID (interrupt channel), 'event' - interrupt event type \ and 'values' - the logical values on each of interrupt channel (N-th bit represents logical pin value of \ interrupt channel N). User object is the same object as user_object. :param user_object: User defined object, which will be passed back to the callback function. Optional, \ default is None. :param debounce_time: Interrupt disable time in milliseconds after the triggering event. This is used to \ "debounce" buttons or to protect communication channel from data flood. Optional, default is 50ms. :return: Logical interrupt ID :rtype: int :raise: IoTPy_APIError """ try: irq_id = self.board.interrupts.index(self.logical_pin) self.board.uper_io(0, encode_sfp(7, [irq_id])) # detach interrupt except ValueError: try: irq_id = self.board.interrupts.index(None) self.board.interrupts[irq_id] = self.logical_pin except ValueError: errmsg("UPER API: more than 8 interrupts requested") raise IoTPy_APIError("Too many interrupts.") self.board.callbackdict[self.logical_pin] = {'mode': event, 'callback': callback, 'userobject': user_object} self.board.uper_io(0, encode_sfp(6, [irq_id, self.logical_pin, event, debounce_time])) return irq_id
def __init__(self, board, pin): self.board = board if self.board.pinout[pin].capabilities & CAP_ADC: self.logical_pin = self.board.pinout[pin].pinID else: errmsg("IO API: Pin "+str(pin)+" is not an ADC pin.") raise IoTPy_APIError("Trying to assign ADC function to non ADC pin.") self.adc_pin = self.board.pinout[pin].extra[0] self.board.uper_io(0, encode_sfp(3, [self.logical_pin, 0])) # set GPIO to HIGH_Z self.board.uper_io(0, encode_sfp(2, [self.logical_pin])) # set secondary pin function self.primary = False
def setup(self, direction, resistor=GPIO.PULL_UP): """ Configure GPIO. :param direction: GPIO direction: GPIO.OUTPUT or GPIO.INPUT :param resistor: GPIO internal resistor mode. Used when direction is GPIO.INPUT. Should be GPIO.PULL_UP, \ GPIO.PULL_DOWN or GPIO.NONE. :raise: IoTPy_APIError """ if not direction in [GPIO.OUTPUT, GPIO.INPUT]: raise IoTPy_APIError("Invalid GPIO direction. Should be GPIO.INPUT or GPIO.OUTPUT") if direction == GPIO.INPUT and not resistor in [GPIO.NONE, GPIO.PULL_UP, GPIO.PULL_DOWN]: raise IoTPy_APIError("Invalid GPIO resistor setting. Should be GPIO.NONE, GPIO.PULL_UP or GPIO.PULL_DOWN") self.direction = direction if direction == GPIO.INPUT: self.resistor = resistor if resistor == GPIO.PULL_UP: mode = 4 # PULL_UP elif resistor == GPIO.PULL_DOWN: mode = 2 # PULL_DOWN else: mode = 0 # HIGH_Z else: mode = 1 # OUTPUT self.board.uper_io(0, encode_sfp(3, [self.logical_pin, mode]))
def read_raw(self): """ Read ADC value :return: Raw ADC value. :rtype: int """ return decode_sfp(self.board.uper_io(1, encode_sfp(10, [self.adc_pin])))[1][1]
def write(self, value): """ Write a digital value (0 or 1). If GPIO pin is not configured as output, set it's GPIO mode to GPIO.OUTPUT. :param value: Digital output value (0 or 1) :type value: int """ if self.direction != GPIO.OUTPUT: self.setup(GPIO.OUTPUT) self.board.uper_io(0, encode_sfp(4, [self.logical_pin, value]))
def read(self): """ Read a digital signal value. If GPIO pis in not configure as input, set it to GPIO.PULL_UP pin mode. :return: Digital signal value: 0 (LOW) or 1 (HIGH). :rtype: int """ if self.direction != GPIO.INPUT: self.setup(GPIO.INPUT, self.resistor) return decode_sfp(self.board.uper_io(1, encode_sfp(5, [self.logical_pin])))[1][1]
def __exit__(self, exc_type, exc_value, traceback): self.board.uper_io(0, encode_sfp(22 + self.port * 10, [])) if self.port: self.board.uper_io(0, encode_sfp(1, [4])) # set pin primary function self.board.uper_io(0, encode_sfp(1, [5])) self.board.uper_io(0, encode_sfp(1, [11])) else: self.board.uper_io(0, encode_sfp(1, [12])) # set pin primary function self.board.uper_io(0, encode_sfp(1, [13])) self.board.uper_io(0, encode_sfp(1, [14]))
def __init__(self, board, pin): self.board = board if self.board.pinout[pin].capabilities & CAP_GPIO: self.logical_pin = self.board.pinout[pin].pinID else: errmsg("UPER API: Pin No:%d is not GPIO pin.", pin) raise IoTPy_APIError("Trying to assign GPIO function to non GPIO pin.") # Configure default state to be input with pull-up resistor self.board.uper_io(0, encode_sfp(1, [self.logical_pin])) # set primary self.direction = GPIO.INPUT self.resistor = GPIO.PULL_UP self.setup(self.direction, self.resistor) # default GPIO pin state is INPUT and PULL_UP
def write(self, value): """ Write a digital port value. If GPIO port is not configured as output, set it's GPIO mode to GPIO.OUTPUT. :param value: Digital output value :type value: int """ if self.direction != GPIO.OUTPUT: self.setup(GPIO.OUTPUT) values = list(((value >> i) & 1) for i in xrange(len(self._logical_pins))) values = struct.pack("B"*len(self._logical_pins), *values) self.board.uper_io(0, encode_sfp(4, [self._logical_pins, values]))
def __init__(self, board, pins): self.board = board for pin in pins: if not self.board.pinout[pin].capabilities & CAP_GPIO: raise IoTPy_APIError("Trying to assign GPIO function to non GPIO pin.") self._logical_pins = list(self.board.pinout[pin].pinID for pin in pins) self._logical_pins = struct.pack("B"*len(self._logical_pins), *self._logical_pins) # Configure default state to be input with pull-up resistor self.direction = GPIO.INPUT self.resistor = GPIO.PULL_UP self.setup(self.direction, self.resistor) self.board.uper_io(0, encode_sfp(1, [self._logical_pins])) # set primary
def transaction(self, write_data, read_from_slave=True): """ Perform SPI data transaction. :param write_data: Data to be shifted on MOSI line. :type write_data: str :param read_from_slave: Flag indicating whether the data received on MISO line should be ignored or not. Optional, default True. :type read_from_slave: bool :return: Data received on MISO line, if read_from_slave is True. :rtype: str """ res = self.board.uper_io(read_from_slave, encode_sfp(21 + self.port * 10, [write_data, int(read_from_slave)])) if res: return decode_sfp(res)[1][0]
def read(self): """ Read a digital port value. If GPIO port in not configure as input, set it to GPIO.PULL_UP pin mode. :return: Digital port value. :rtype: int """ if self.direction != self.INPUT: self.setup(GPIO.INPUT, self.resistor) values = decode_sfp(self.board.uper_io(1, encode_sfp(5, [self._logical_pins])))[1][1] value = 0 for i, bit in enumerate(values): value |= (ord(bit) & 0x1) << i return value
def detach_irq(self): """ Detach (disable) GPIO interrupt. :return: True on success, False otherwise :raise: IoTPy_APIError """ try: irq_id = self.board.interrupts.index(self.logical_pin) except ValueError: #errmsg("UPER API: trying to detach non existing interrupt.") return False self.board.interrupts[irq_id] = None del self.board.callbackdict[self.logical_pin] self.board.uper_io(0, encode_sfp(7, [irq_id])) return True
def __init__(self, board, port=0, divider=1, mode=SPI.MODE_0): divider = min(max(divider, 1), 256) self.board = board self.port = port self.divider = divider self.mode = mode if self.port == 1: self.board.uper_io(0, encode_sfp(2, [4])) self.board.uper_io(0, encode_sfp(2, [5])) self.board.uper_io(0, encode_sfp(2, [11])) self.board.uper_io(0, encode_sfp(30, [self.divider, self.mode])) elif self.port == 0: self.board.uper_io(0, encode_sfp(2, [12])) self.board.uper_io(0, encode_sfp(2, [13])) self.board.uper_io(0, encode_sfp(2, [14])) self.board.uper_io(0, encode_sfp(20, [self.divider, self.mode])) else: errmsg("UPER API: Wrong SPI port number.", self.port) raise IoTPy_APIError("SPI port must be 0 or 1, trying to assign something else.")
def setup(self, direction, resistor=GPIO.PULL_UP): if not direction in [GPIO.OUTPUT, GPIO.INPUT]: raise IoTPy_APIError("Invalid GPIO direction. Should be GPIO.INPUT or GPIO.OUTPUT") if direction == GPIO.INPUT and not resistor in [GPIO.NONE, GPIO.PULL_UP, GPIO.PULL_DOWN]: raise IoTPy_APIError("Invalid GPIO resistor setting. Should be GPIO.NONE, GPIO.PULL_UP or GPIO.PULL_DOWN") self.direction = direction if direction == GPIO.INPUT: self.resistor = resistor if resistor == GPIO.PULL_UP: mode = 4 # PULL_UP elif resistor == GPIO.PULL_DOWN: mode = 2 # PULL_DOWN else: mode = 0 # HIGH_Z else: mode = 1 # OUTPUT self.board.uper_io(0, encode_sfp(3, [self._logical_pins, chr(mode)*len(self._logical_pins)]))
def test_simple_sfp_encode(self): self.assertEqual(sfp.encode_sfp(255, []), b'\xd4\x00\x01\xff')
def test_encode_sfp(self): sfp_parameters = [b'09876543210987654321098765432109876543210987654321098765432109876543210987654321', b'0987654321', 0, 1, 64, 6000, 70000] sfp_command = 255 encode_result = sfp.encode_sfp(sfp_command, sfp_parameters) self.assertEqual(encode_result, b'\xd4\x00i\xff\xc4P09876543210987654321098765432109876543210987654321098765432109876543210987654321J0987654321\x00\x01\xc0@\xc1\x17p\xc2\x01\x11p')
def read_pulse(self, level=GPIO.HIGH, timeout=100000): if self.direction != self.INPUT: self.setup(GPIO.INPUT, self.resistor) return decode_sfp(self.board.uper_io(1, encode_sfp(9, [self.logical_pin, level, timeout])))[1][0]