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 """ try: irq_id = self.board.interrupts.index(self.logical_pin) self.board.uper_io(0, self.board.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") self.board.callbackdict[self.logical_pin] = {'mode': event, 'callback': callback, 'userobject': user_object} self.board.uper_io(0, self.board.encode_sfp(6, [irq_id, self.logical_pin, event, debounce_time])) return irq_id
def transaction(self, address, write_data, read_length): """ Perform I2C data transaction. I2C data transaction consists of (optional) write transaction, followed by (optional) read transaction. :param address: I2C device address. :type address: int :param write_data: A byte sequence to be transmitted. If write_data is empty string, no write transaction \ will be executed. :type write_data: str :param read_length: A number of bytes to be received. If read_length is 0, no read transaction will be executed. :type read_length: int :return: Received data or I2C communication error code. :rtype: str or int :raise: IoTPy_APIError, IoTPy_ThingError """ try: result = self.board.decode_sfp( self.board.uper_io( 1, self.board.encode_sfp(41, [address, write_data, read_length]))) except IoTPy_APIError: errmsg("UPER API: I2C bus not connected.") raise IoTPy_IOError("I2C bus not connected.") return result[1][1], result[1][2] # return read buffer and error
def transaction(self, address, write_data, read_length): """ Perform I2C data transaction. I2C data transaction consists of (optional) write transaction, followed by (optional) read transaction. :param address: I2C device address. :type address: int :param write_data: A byte sequence to be transmitted. If write_data is empty string, no write transaction \ will be executed. :type write_data: str :param read_length: A number of bytes to be received. If read_length is 0, no read transaction will be executed. :type read_length: int :return: Received data and I2C transaction status/error code. :rtype: (str, int) :raise: IoTPy_APIError, IoTPy_ThingError """ try: result = self.board.decode_sfp(self.board.uper_io(1, self.board.encode_sfp(41, [address, write_data, read_length]))) except IoTPy_APIError: errmsg("UPER API: I2C bus not connected.") raise IoTPy_IOError("I2C bus not connected.") return result[1][1], result[1][2] # return read buffer and error
def width_us(self, hightime): """ Set PWM high (on state) time. :param hightime: On state time in microseconds. :type hightime: int :raise: IoTPy_APIError """ if self.primary: self.board.uper_io(0, self.board.encode_sfp( 2, [self.logical_pin])) # set pin secondary function self.primary = False if 0 <= hightime <= PWM_PORT_RUNNING[self.pwm_port]['period']: self.hightime = hightime if self.polarity == 1: hightime = PWM_PORT_RUNNING[self.pwm_port]['period'] - hightime self.board.uper_io( 0, self.board.encode_sfp( PWM._PWM_PORT_FUNCTIONS[self.pwm_port][1], [self.pwm_pin, hightime])) else: errmsg( "UPER error: PWM high time is out of range on logical pin %d." % self.logical_pin) raise IoTPy_APIError("PWM high time is out of range.")
def attach(self, mode, callback, user_object=None, debounce_time=50): """ Attach (enable) or reconfigure GPIO interrupt event. :param mode: GPIO interrupt mode. :param callback: User callback function. This function is executed when the interrupt event is received. :param user_object: Optional user defined object, which will be passed back to the callback function. :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: True :raise: IoTPy_APIError """ try: interruptID = self.board.interrupts.index(self.logical_pin) self.board.uper_io(0, self.board.encode_sfp( 7, [interruptID])) #detach interrupt except ValueError: try: interruptID = self.board.interrupts.index(None) self.board.interrupts[interruptID] = 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': mode, 'callback': callback, 'userobject': user_object } self.board.uper_io( 0, self.board.encode_sfp( 6, [interruptID, self.logical_pin, mode, debounce_time])) return True
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, can't attach interrupt.", pin) raise IoTPy_APIError("Wrong Pin number.")
def port_mode(self, direction, port, resistor=GPIO.PULL_UP): """ Configure PORT. :param direction: GPIO direction: GPIO.OUTPUT or GPIO.INPUT :param port: PORT number (0...3) :param resistor: GPIO internal resistor mode. Used when direction is GPIO.INPUT. Should be GPIO.PULL_UP, \ GPIO.PULL_DOWN or GPIO.INPUT. """ if not direction in [GPIO.OUTPUT, GPIO.INPUT]: errmsg("UPER API: Invalid GPIO direction. Should be GPIO.INPUT or GPIO.OUTPUT") if direction == GPIO.INPUT and not resistor in [GPIO.INPUT, GPIO.PULL_UP, GPIO.PULL_DOWN]: errmsg("UPER API: Invalid GPIO resistor setting. Should be GPIO.INPUT, 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, self.board.encode_sfp(72, [port, mode]))
def attach(self, mode, callback, user_object=None, debounce_time=50): """ Attach (enable) or reconfigure GPIO interrupt event. :param mode: GPIO interrupt mode. Can have one of these values: Interrupt.EDGE_RISE, Interrupt.EDGE_FALL, \ Interrupt.EDGE_CHANGE, Interrupt.LEVEL_LOW or Interrupt.LEVEL_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), 'type' - interrupt event type \ (same meaning as mode) 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: True :raise: IoTPy_APIError """ try: interruptID = self.board.interrupts.index(self.logical_pin) self.board.uper_io(0, self.board.encode_sfp(7, [interruptID])) #detach interrupt except ValueError: try: interruptID = self.board.interrupts.index(None) self.board.interrupts[interruptID] = 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':mode, 'callback':callback, 'userobject':user_object } self.board.uper_io(0, self.board.encode_sfp(6, [interruptID, self.logical_pin, mode, debounce_time])) return True
def transaction(self, address, write_data, read_length, ignore_error=False): """ Perform I2C data transaction. I2C data transaction consists of (optional) write transaction, followed by (optional) read transaction. :param address: I2C device address. :type address: int :param write_data: A byte sequence to be transmitted. If write_data is None, no write transaction will be executed. :type write_data: str :param read_length: A number of bytes to be received. If read_length is 0, no read trasaction will be executed. :type read_length: int :param ignore_error: :type ignore_error: bool :return: Received data or I2C communication error code. :rtype: str or int :raise: IoTPy_APIError, IoTPy_ThingError """ try: result = self.board.decode_sfp(self.board.uper_io(1, self.board.encode_sfp(41, [address, write_data, read_length]))) except IoTPy_APIError: errmsg("UPER API: I2C bus not connected.") raise IoTPy_IOError("I2C bus not connected.") if type(result[1][0]) == IntType and not ignore_error: errmsg("UPER Interface: I2C device with address %#x returned error code %#x.", address, result[1][0]) raise IoTPy_ThingError("I2C slave reading error.") else: return result[1][0]
def attach(self, mode, callback, user_object=None, debounce_time=50): """ Attach (enable) or reconfigure GPIO interrupt event. :param mode: GPIO interrupt mode. :param callback: User callback function. This function is executed when the interrupt event is received. :param user_object: Optional user defined object, which will be passed back to the callback function. :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: True :raise: IoTPy_APIError """ try: interruptID = self.board.interrupts.index(self.logical_pin) self.board.uper_io(0, self.board.encode_sfp(7, [interruptID])) #detach interrupt except ValueError: try: interruptID = self.board.interrupts.index(None) self.board.interrupts[interruptID] = 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':mode, 'callback':callback, 'userobject':user_object } self.board.uper_io(0, self.board.encode_sfp(6, [interruptID, self.logical_pin, mode, debounce_time])) return True
def set_pulse_time(self, pulse_us): """ Set PWM high (on state) time. :param pulse_us: Pulse time in microseconds. :type pulse_us: int :raise: IoTPy_APIError """ if self.primary: self.board.uper_io(0, self.board.encode_sfp( 2, [self.logical_pin])) # set pin secondary function self.primary = False if 0 <= pulse_us <= PWM_PORT_RUNNING[self.pwm_port]['period']: self.pulse_time = pulse_us high_time = pulse_us if self.polarity == 0: high_time = PWM_PORT_RUNNING[ self.pwm_port]['period'] - pulse_us self.board.uper_io( 0, self.board.encode_sfp( UPER1_PWM._PWM_PORT_FUNCTIONS[self.pwm_port][1], [self.pwm_pin, high_time])) else: errmsg( "UPER error: PWM high time is out of range on logical pin %d." % self.logical_pin) raise IoTPy_APIError("PWM high time is out of range.")
def detach(self): """ Detach (disable) GPIO interrupt. :return: True :raise: IoTPy_APIError """ try: interruptID = self.board.interrupts.index(self.logical_pin) except ValueError: errmsg("UPER API: trying to detach non existing interrupt.") return False #raise IoTPy_APIError("trying to detaching non existing interrupt.") self.board.interrupts[interruptID] = None try: del self.board.callbackdict[self.logical_pin] except KeyError: errmsg("UPER API: trying to detach non existing interrupt.") raise IoTPy_APIError("trying to detaching non existing interrupt.") self.board.uper_io(0, self.board.encode_sfp(7, [interruptID])) return True
def reader(self): while self.alive: # In some case, when the SFP frame to receive is larger than an USB frame, # the SFP frame is received incomplete. This is a major problem as the sfp # decoder can crash. # To fix this problem, a pre-decodage is done here to get the size of the # expected SFP frame. This prevent incomplete SFP frames to be sent to the # decoder. try: data = self.serial.read(3) if data[0:1] == '\xd4': expected_len = struct.unpack('>H', data[1:3])[0] while (self.serial.inWaiting() < expected_len): pass data = data + self.serial.read(expected_len) # get the needed bytes if data: if data[3] == '\x08': interrupt = self.decodefun(data) with self.irq_available: self.irq_requests.append(interrupt) self.irq_available.notify() else: self.outq.put(data) except: errmsg("UPER API: serial port reading error.") break self.alive = False
def __init__(self, board, pin): self.board = board if self.board.pinout[pin][0] & self.board.cap_gpio: self.logical_pin = self.board.pinout[pin][1][0] else: errmsg("UPER API: Pin No:%d is not GPIO pin, can't attach interrupt.", pin) raise IoTPy_APIError("Wrong Pin number.")
def distance(self, distance_unit=CM): """ Measure distance to closest object. :param distance_unit: The units to measure the distance in. Optional, default Srf08.CM. :type distance_unit: Srf08.CM, Srf08.INCH or Srf08.MS. :return: The distance in specified units. :rtype: int :raise: IoTPy_ThingError """ if distance_unit not in (Srf08.CM, Srf08.INCH, Srf08.MS): errmsg("Wrong units for distance, should be 'c' or 'i' or 'm'.") raise IoTPy_ThingError( "Wrong units for distance, should be 'c' or 'i' or 'm'.") try: self.interface.transaction(self.address, Srf08.CMD + distance_unit, 0) sleep(0.08) distance = unpack( '>H', self.interface.transaction(self.address, Srf08.RESULT, 2)[:2])[0] except IoTPy_ThingError: raise IoTPy_ThingError("srf08 - distance reading error.") return distance
def reader(self): while self.alive: # In some case, when the SFP frame to receive is larger than an USB frame, # the SFP frame is received incomplete. This is a major problem as the sfp # decoder can crash. # To fix this problem, a pre-decodage is done here to get the size of the # expected SFP frame. This prevent incomplete SFP frames to be sent to the # decoder. try: data = self.serial.read(3) if data[0:1] == '\xd4': expected_len = struct.unpack('>H', data[1:3])[0] while (self.serial.inWaiting() < expected_len): pass data = data + self.serial.read( expected_len) # get the needed bytes if data: if data[3] == '\x08': interrupt = self.decodefun(data) with self.irq_available: self.irq_requests.append(interrupt) self.irq_available.notify() else: self.outq.put(data) except: errmsg("UPER API: serial port reading error.") break self.alive = False
def __init__(self, pinout=WEIO_PINOUT, serial_port=None): """__init__(self, pinout=UPER1_PINOUT, serial_port=None)""" ser = None if serial_port is None: my_platform = platform.system() if my_platform == "Windows": ports_list = [] for i in xrange(256): try: ser = serial.Serial(i) ports_list.append('COM' + str(i + 1)) ser.close() except serial.SerialException: pass elif my_platform == "Darwin": ports_list = glob.glob("/dev/tty.usbmodem*") elif my_platform == "Linux": if platform.machine( ) == 'mips': # MIPS : This is probably WeIO ports_list = glob.glob("/dev/lpc") else: ports_list = glob.glob("/dev/ttyACM*") for my_port in ports_list: try: port_to_try = serial.Serial( port=my_port, baudrate= 230400, #virtual com port on USB is always max speed parity=serial.PARITY_ODD, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=0.1) port_to_try.write(self.encode_sfp(255, [])) uper_response = port_to_try.read(1) #read one, blocking n = port_to_try.inWaiting() #look if there is more if n: uper_response = uper_response + port_to_try.read(n) if self.decode_sfp( uper_response)[0] == -1: # found port with UPER ser = port_to_try break port_to_try.close() except: errmsg("UPER API: Unrecoverable serial port error.") if not ser: errmsg("UPER API: No UPER found on USB/serial ports.") self.interrupts = [None] * 8 self.callbackdict = {} self.ser = ser self.ser.flush() self.outq = Queue.Queue() self.reader = Reader(self.ser, self.outq, self.internalCallBack, self.decode_sfp) self.devicename = "uper" self.version = __version__ self.pinout = pinout
def period(self, period): if 0 <= period <= self.PWM_PORT_MAX[self.pwm_port]: if PWM_PORT_RUNNING[self.pwm_port][1] != period: self.board.uper_io(0, self.board.encode_sfp(self.PWM_PORT_FUNCTIONS[self.pwm_port][0], [period])) PWM_PORT_RUNNING[self.pwm_port][1] = period else: errmsg("UPER API: PWM period for port %d can be only between 0-%d" % (self.pwm_port, self.PWM_PORT_MAX[self.pwm_port])) raise IoTPy_APIError("PWM period is out of range.")
def decode_sfp(self, buffer): """ Decode SFP command from byte buffer. :param buffer: A byte buffer which stores SFP command. :type buffer: str :return: A list containing decoded SFP function ID and arguments (if any). """ result = [] if buffer[0:1] != '\xd4': return result buflen = struct.unpack('>H', buffer[1:3])[0] + 3 result.append(struct.unpack('b', buffer[3:4])[0]) pointer = 4 args = [] while pointer < buflen: argtype = ord(buffer[pointer:pointer + 1]) pointer += 1 if argtype < 64: # short int args.append(argtype) elif argtype < 128: # short str arglen = argtype & 0x3f args.append(buffer[pointer:pointer + arglen]) pointer += arglen else: arglen = argtype & 0x0f if arglen < 4: # decoding integers if arglen == 0: args.append(ord(buffer[pointer:pointer + 1])) elif arglen == 1: args.append( struct.unpack('>H', buffer[pointer:pointer + 2])[0]) elif arglen == 2: args.append( struct.unpack('>I', '\x00' + buffer[pointer:pointer + 3])[0]) elif arglen == 3: args.append( struct.unpack('>I', buffer[pointer:pointer + 4])[0]) pointer += arglen + 1 else: if argtype == 0xc4: # decoding strings arglen = ord(buffer[pointer:pointer + 1]) elif argtype == 0xc5: arglen = struct.unpack('>H', buffer[pointer:pointer + 2])[0] pointer += 1 else: errmsg( "UPER API: Bad parameter type in decodeSFP method." ) pointer += 1 args.append(buffer[pointer:pointer + arglen]) pointer += arglen result.append(args) return result
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, can't attach interrupt.", pin) raise IoTPy_APIError("Wrong Pin number.")
def __init__(self, board, pin): self.board = board if self.board.pinout[pin][0] & self.board.cap_gpio: self.logical_pin = self.board.pinout[pin][1][0] else: errmsg( "UPER API: Pin No:%d is not GPIO pin, can't attach interrupt.", pin) raise IoTPy_APIError("Wrong Pin number.")
def __init__(self, pinout=WEIO_PINOUT, serial_port=None): """__init__(self, pinout=UPER1_PINOUT, serial_port=None)""" ser = None if serial_port is None: my_platform = platform.system() if my_platform == "Windows": ports_list = [] for i in xrange(256): try: ser = serial.Serial(i) ports_list.append('COM' + str(i + 1)) ser.close() except serial.SerialException: pass elif my_platform == "Darwin": ports_list = glob.glob("/dev/tty.usbmodem*") elif my_platform == "Linux": if platform.machine() == 'mips': # MIPS : This is probably WeIO ports_list = glob.glob("/dev/lpc") else: ports_list = glob.glob("/dev/ttyACM*") for my_port in ports_list: try: port_to_try = serial.Serial( port=my_port, baudrate=230400, #virtual com port on USB is always max speed parity=serial.PARITY_ODD, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=0.1 ) port_to_try.write(self.encode_sfp(255, [])) uper_response = port_to_try.read(1) #read one, blocking n = port_to_try.inWaiting() #look if there is more if n: uper_response = uper_response + port_to_try.read(n) if self.decode_sfp(uper_response)[0] == -1: # found port with UPER ser = port_to_try break port_to_try.close() except: errmsg("UPER API: Unrecoverable serial port error.") if not ser: errmsg("UPER API: No UPER found on USB/serial ports.") self.interrupts = [None] * 8 self.callbackdict = {} self.ser = ser self.ser.flush() self.outq = Queue.Queue() self.reader = Reader(self.ser, self.outq, self.internalCallBack, self.decode_sfp) self.devicename = "uper" self.version = __version__ self.pinout = pinout
def _encode_bytes(self, bytestr): if len(bytestr) < 64: return chr(0x40 | len(bytestr)) + bytestr packedlen = struct.pack('>I', len(bytestr)).lstrip('\x00') if len(packedlen) == 1: return '\xc4' + packedlen + bytestr elif len(packedlen) == 2: return '\xc5' + packedlen + bytestr else: errmsg("UPER API: - too long string passed to UPER, encode_bytes can't handle it.")
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("UPER API: Pin No:%d is not an ADC pin.", pin) self.adc_pin = self.board.pinout[pin].extra[0] self.board.uper_io(0, self.board.encode_sfp(3, [self.logical_pin, 0])) # set GPIO to HIGH_Z self.board.uper_io(0, self.board.encode_sfp(2, [self.logical_pin])) # set secondary pin function self.primary = False
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("UPER API: Pin No:%d is not an ADC pin.", 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, self.board.encode_sfp(3, [self.logical_pin, GPIO.HIGH_Z])) self.board.uper_io(0, self.board.encode_sfp(2, [self.logical_pin])) # set secondary pin function self.primary = False
def distance(self, distance_unit = CM): if distance_unit not in (Srf08.CM, Srf08.INCH, Srf08.MS): errmsg("Wrong units for distance, should be 'c' or 'i' or 'm'.") raise IoTPy_ThingError("Wrong units for distance, should be 'c' or 'i' or 'm'.") try: self.interface.transaction(self.address, Srf08.CMD + distance_unit, 0) sleep(0.08) distance = unpack('>H', self.interface.transaction(self.address, Srf08.RESULT, 2)[:2])[0] except IoTPy_ThingError: raise IoTPy_ThingError("srf08 - distance reading error.") return distance
def transaction(self, address, write_data, read_length, ignore_error=False): try: result = self.board.decode_sfp(self.board.uper_io(1, self.board.encode_sfp(41, [address, write_data, read_length]))) except IoTPy_APIError: errmsg("UPER API: I2C bus not connected.") raise IoTPy_IOError("I2C bus not connected.") if type(result[1][0]) == IntType and not ignore_error: errmsg("UPER Interface: I2C device with address %#x returned error code %#x.", address, result[1][0] ) raise IoTPy_ThingError("I2C slave reading error.") else: return result[1][0]
def __init__(self, board, pin): self.board = board if self.board.pinout[pin][0] & self.board.cap_adc: self.logical_pin = self.board.pinout[pin][1][0] else: errmsg("UPER API: Pin No:%d is not an ADC pin.", pin) raise IoTPy_APIError("Trying to assign ADC function to non ADC pin.") self.adc_pin = self.board.pinout[pin][1][1] self.board.uper_io(0, self.board.encode_sfp(3, [self.logical_pin, self.HIGH_Z])) self.board.uper_io(0, self.board.encode_sfp(2, [self.logical_pin])) # set secondary pin function self.pull = self.HIGH_Z self.primary = False
def interrupt_handler(self): with self.irq_available: while self.alive: self.irq_available.wait(0.05) while len(self.irq_requests): interrupt = self.irq_requests.pop(0) try: self.callback(interrupt[1]) except Exception as e: errmsg("UPER API: Interrupt callback error (%s)" % e) self.alive = False
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.") self.direction = self.INPUT self.pull = self.PULL_UP self.board.uper_io(0, self.board.encode_sfp(1, [self.logical_pin])) # set primary self.primary = True self.input_pullmode = self.PULL_UP
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) # 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, self.board.encode_sfp(1, [self.logical_pin])) # set primary
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("UPER API: Pin No:%d is not an ADC pin.", pin) self.adc_pin = self.board.pinout[pin].extra[0] self.board.uper_io(0, self.board.encode_sfp( 3, [self.logical_pin, 0])) # set GPIO to HIGH_Z self.board.uper_io(0, self.board.encode_sfp( 2, [self.logical_pin])) # set secondary pin function self.primary = False
def mode(self, pin_mode): if pin_mode in [self.HIGH_Z, self.PULL_UP, self.PULL_DOWN, self.OUTPUT]: if pin_mode != self.OUTPUT: self.direction = self.INPUT self.input_pullmode = pin_mode self.pull = pin_mode else: self.direction = self.OUTPUT self.board.uper_io(0, self.board.encode_sfp(3, [self.logical_pin, pin_mode])) else: errmsg("UPER API: pinMode - Illegal pin mode - %d", pin_mode) raise IoTPy_APIError("Illegal pin mode.")
def width_us(self, hightime): if self.primary: self.board.uper_io(0, self.board.encode_sfp(2, [self.logical_pin])) # set pin secondary function self.primary = False if 0 <= hightime <= PWM_PORT_RUNNING[self.pwm_port][1]: self.hightime = hightime if self.polarity == 1: hightime = PWM_PORT_RUNNING[self.pwm_port][1] - hightime self.board.uper_io(0, self.board.encode_sfp(PWM.PWM_PORT_FUNCTIONS[self.pwm_port][1], [self.pwm_pin, hightime])) else: errmsg("UPER error: PWM high time is out of range on logical pin %d." % self.logical_pin) raise IoTPy_APIError("PWM high time is out of range.")
def _encode_bytes(self, bytestr): if len(bytestr) < 64: return chr(0x40 | len(bytestr)) + bytestr packedlen = struct.pack('>I', len(bytestr)).lstrip('\x00') if len(packedlen) == 1: return '\xc4' + packedlen + bytestr elif len(packedlen) == 2: return '\xc5' + packedlen + bytestr else: errmsg( "UPER API: - too long string passed to UPER, encode_bytes can't handle it." )
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) # 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, self.board.encode_sfp( 1, [self.logical_pin])) # set primary
def set_period(self, period_us): """ Set PWM period. :param period_us: PWM signal period in microseconds. :type period_us: int """ if 0 <= period_us <= self._PWM_PORT_MAX[self.pwm_port]: if PWM_PORT_RUNNING[self.pwm_port]['period'] != period_us: self.board.uper_io(0, self.board.encode_sfp(self._PWM_PORT_FUNCTIONS[self.pwm_port][0], [period_us])) PWM_PORT_RUNNING[self.pwm_port]['period'] = period_us else: errmsg("UPER API: PWM period for port %d can be only between 0-%d" % (self.pwm_port, self._PWM_PORT_MAX[self.pwm_port]))
def ADC(self, name, *args, **kwargs): _names = {"ADC0": 23, "ADC1": 24, "ADC2": 25, "ADC3": 26, "ADC4": 30, "ADC5": 31, "ADC6": 32, "ADC7": 33} if isinstance(name, int): pin = name elif isinstance(name, str): if _names.has_key(name): pin = _names[name] else: errmsg("UPER API: Invalid ADC name %s. Must be one of %s." % (name, ", ".join(sorted(_names.keys())))) else: errmsg("UPER API: ADC name must be an integer or a string") return UPER1_ADC(self, pin)
def PWM(self, name, freq=100, polarity=1, *args, **kwargs): _names = {"PWM0_0": 27, "PWM0_1": 28, "PWM0_2": 34, "PWM1_0": 10, "PWM1_1": 39, "PWM1_2": 3} if isinstance(name, int): pin = name elif isinstance(name, str): if _names.has_key(name): pin = _names[name] else: errmsg("UPER API: Invalid PWM name %s. Must be one of %s." % (name, ", ".join(sorted(_names.keys())))) else: errmsg("UPER API: PWM name must be an integer or a string") return UPER1_PWM(self, pin, freq, polarity)
def stop(self): """ Stop all communications with the board and close serial communication port. """ #for i in range(7): # self.detachInterrupt(i) try: self.reader.stop() self.ser.flush() self.ser.close() except: errmsg("UPER API: Serial/USB port disconnected.")
def __init__(self, board, pin, freq=100, polarity=1): self.board = board if self.board.pinout[pin].capabilities & CAP_PWM: self.logical_pin = self.board.pinout[pin].pinID else: errmsg("UPER API: Pin No:%d is not a PWM pin.", pin) self.pwm_port = self.board.pinout[pin].extra[0] self.pwm_pin = self.board.pinout[pin].extra[1] self.primary = True self.pulse_time = 0 self.polarity = polarity PWM_PORT_RUNNING[self.pwm_port]['channels'] += 1 if PWM_PORT_RUNNING[self.pwm_port]['channels'] == 1: self.set_frequency(freq)
def detach(self): try: interruptID = self.board.interrupts.index(self.logical_pin) except ValueError: errmsg("UPER API: trying to detach non existing interrupt.") IoTPy_APIError("trying to detaching non existing interrupt.") self.board.interrupts[interruptID] = None try: del self.board.callbackdict[self.logical_pin] except KeyError: errmsg("UPER API: trying to detach non existing interrupt.") IoTPy_APIError("trying to detaching non existing interrupt.") self.board.uper_io(0, self.board.encode_sfp(7, [interruptID])) return True
def attach(self, mode, callback): try: interruptID = self.board.interrupts.index(self.logical_pin) self.board.uper_io(0, self.board.encode_sfp(7, [interruptID])) # detach interrupt except ValueError: try: interruptID = self.board.interrupts.index(None) self.board.interrupts[interruptID] = 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, callback] self.board.uper_io(0, self.board.encode_sfp(6, [interruptID, self.logical_pin, mode])) return True
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.") self.direction = self.INPUT self.pull = self.PULL_UP self.board.uper_io(0, self.board.encode_sfp( 1, [self.logical_pin])) # set primary self.primary = True self.input_pullmode = self.PULL_UP
def period(self, period): if 0 <= period <= self.PWM_PORT_MAX[self.pwm_port]: if PWM_PORT_RUNNING[self.pwm_port][1] != period: self.board.uper_io( 0, self.board.encode_sfp( self.PWM_PORT_FUNCTIONS[self.pwm_port][0], [period])) PWM_PORT_RUNNING[self.pwm_port][1] = period self.PWM_PERIOD = period else: errmsg( "UPER API: PWM period for port %d can be only between 0-%d" % (self.pwm_port, self.PWM_PORT_MAX[self.pwm_port])) raise IoTPy_APIError("PWM period is out of range.")
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("UPER API: Pin No:%d is not an ADC pin.", 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, self.board.encode_sfp(3, [self.logical_pin, GPIO.HIGH_Z])) self.board.uper_io(0, self.board.encode_sfp( 2, [self.logical_pin])) # set secondary pin function self.primary = False
def decode_sfp(self, buffer): """ Decode SFP command from byte buffer. :param buffer: A byte buffer which stores SFP command. :type buffer: str :return: A list containing decoded SFP function ID and arguments (if any). """ result = [] if buffer[0:1] != '\xd4': return result buflen = struct.unpack('>H', buffer[1:3])[0] + 3 result.append(struct.unpack('b', buffer[3:4])[0]) pointer = 4 args = [] while pointer < buflen: argtype = ord(buffer[pointer:pointer + 1]) pointer += 1 if argtype < 64: # short int args.append(argtype) elif argtype < 128: # short str arglen = argtype & 0x3f args.append(buffer[pointer:pointer + arglen]) pointer += arglen else: arglen = argtype & 0x0f if arglen < 4: # decoding integers if arglen == 0: args.append(ord(buffer[pointer:pointer + 1])) elif arglen == 1: args.append(struct.unpack('>H', buffer[pointer:pointer + 2])[0]) elif arglen == 2: args.append(struct.unpack('>I', '\x00' + buffer[pointer:pointer + 3])[0]) elif arglen == 3: args.append(struct.unpack('>I', buffer[pointer:pointer + 4])[0]) pointer += arglen + 1 else: if argtype == 0xc4: # decoding strings arglen = ord(buffer[pointer:pointer + 1]) elif argtype == 0xc5: arglen = struct.unpack('>H', buffer[pointer:pointer + 2])[0] pointer += 1 else: errmsg("UPER API: Bad parameter type in decodeSFP method.") pointer += 1 args.append(buffer[pointer:pointer + arglen]) pointer += arglen result.append(args) return result
def mode(self, pin_mode): if pin_mode in [ self.HIGH_Z, self.PULL_UP, self.PULL_DOWN, self.OUTPUT ]: if pin_mode != self.OUTPUT: self.direction = self.INPUT self.input_pullmode = pin_mode self.pull = pin_mode else: self.direction = self.OUTPUT self.board.uper_io( 0, self.board.encode_sfp(3, [self.logical_pin, pin_mode])) else: errmsg("UPER API: pinMode - Illegal pin mode - %d", pin_mode) raise IoTPy_APIError("Illegal pin mode.")
def distance(self, distance_unit=CM): if distance_unit not in (Srf08.CM, Srf08.INCH, Srf08.MS): errmsg("Wrong units for distance, should be 'c' or 'i' or 'm'.") raise IoTPy_ThingError( "Wrong units for distance, should be 'c' or 'i' or 'm'.") try: self.interface.transaction(self.address, Srf08.CMD + distance_unit, 0) sleep(0.08) distance = unpack( '>H', self.interface.transaction(self.address, Srf08.RESULT, 2)[:2])[0] except IoTPy_ThingError: raise IoTPy_ThingError("srf08 - distance reading error.") return distance
def attach(self, mode, callback): try: interruptID = self.board.interrupts.index(self.logical_pin) self.board.uper_io(0, self.board.encode_sfp( 7, [interruptID])) #detach interrupt except ValueError: try: interruptID = self.board.interrupts.index(None) self.board.interrupts[interruptID] = 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, callback] self.board.uper_io( 0, self.board.encode_sfp(6, [interruptID, self.logical_pin, mode])) return True
def __init__(self, board, pin, polarity=1): self.board = board if self.board.pinout[pin].capabilities & CAP_PWM: self.logical_pin = self.board.pinout[pin].pinID else: errmsg("UPER API: Pin No:%d is not a PWM pin.", pin) raise IoTPy_APIError( "Trying to assign PWM function to non PWM pin.") self.pwm_port = self.board.pinout[pin].extra[0] self.pwm_pin = self.board.pinout[pin].extra[1] self.primary = True self.hightime = 0 self.polarity = polarity PWM_PORT_RUNNING[self.pwm_port]['channels'] += 1 if PWM_PORT_RUNNING[self.pwm_port]['channels'] == 1: self.period(10000)
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 return True
def __init__(self, board, pin, polarity=1): self.board = board if self.board.pinout[pin][0] & self.board.cap_pwm: self.logical_pin = self.board.pinout[pin][1][0] else: errmsg("UPER API: Pin No:%d is not a PWM pin.", pin) raise IoTPy_APIError( "Trying to assign PWM function to non PWM pin.") self.pwm_port = self.board.pinout[pin][1][1] self.pwm_pin = self.board.pinout[pin][1][2] self.primary = True self.hightime = 0 self.polarity = polarity PWM_PORT_RUNNING[self.pwm_port][0] += 1 if PWM_PORT_RUNNING[self.pwm_port][0] == 1: self.period(self.PWM_PERIOD)
def SPI(self, name, clock=1000000, mode=SPI.MODE_0, *args, **kwargs): _names = {"SPI0": 0, "SPI1": 1} if isinstance(name, int): port = name elif isinstance(name, str): if _names.has_key(name): port = _names[name] else: errmsg("UPER API: Invalid SPI name %s. Must be one of %s." % (name, ", ".join(sorted(_names.keys())))) else: errmsg("UPER API: PWM name must be an integer or a string") divider = int(round(2.0e6 / clock)) return UPER1_SPI(self, port, divider, mode)