"""MPSSE pin names""" class Pin: """A basic Pin class for use with FTDI MPSSEs.""" IN = 0 OUT = 1 LOW = 0 HIGH = 1 mpsse_gpio = None def __init__(self, pin_id=None, url="ftdi://ftdi:ft232h/1"): # setup GPIO controller if not done yet # use one provided by I2C as default if not Pin.mpsse_gpio: # pylint: disable=import-outside-toplevel from pyftdi.i2c import I2cController # pylint: enable=import-outside-toplevel i2c = I2cController() i2c.configure(url) Pin.mpsse_gpio = i2c.get_gpio() # check if pin is valid if pin_id: if Pin.mpsse_gpio.all_pins & 1 << pin_id == 0: raise ValueError("Can not use pin {} as GPIO.".format(pin_id)) # ID is just bit position self.id = pin_id def init(self, mode=IN, pull=None): """Initialize the Pin""" if not self.id: raise RuntimeError("Can not init a None type pin.") # MPSSE does't have configurable internal pulls? if pull: raise ValueError("Internal pull up/down not currently supported.") pin_mask = Pin.mpsse_gpio.pins | 1 << self.id current = Pin.mpsse_gpio.direction if mode == self.OUT: current |= 1 << self.id else: current &= ~(1 << self.id) Pin.mpsse_gpio.set_direction(pin_mask, current) def value(self, val=None): """Set or return the Pin Value""" if not self.id: raise RuntimeError("Can not access a None type pin.") current = Pin.mpsse_gpio.read(with_output=True) # read if val is None: return 1 if current & 1 << self.id != 0 else 0 # write if val in (self.LOW, self.HIGH): if val == self.HIGH: current |= 1 << self.id else: current &= ~(1 << self.id) # must mask out any input pins Pin.mpsse_gpio.write(current & Pin.mpsse_gpio.direction) return None # release the kraken raise RuntimeError("Invalid value for pin")