def __init__(self, if_id, index, direction): """Return a new instance of a Pmod IO object. Parameters ---------- if_id : int The interface ID (1, 2) corresponding to (PMODA, PMODB). index: int The index of the Pmod pin, from 0 to 7. direction : str Input 'in' or output 'out'. """ if not if_id in [PMODA, PMODB]: raise ValueError("No such IOP for Pmod device.") if not index in range(8): raise ValueError("Valid pin indexes are 0 - 7.") if not direction in ['in', 'out']: raise ValueError("Direction can only be 'in', or 'out'.") self.iop = DevMode(if_id, iop_const.PMOD_SWCFG_DIOALL) self.index = index self.direction = direction self.iop.start() if self.direction == 'in': self.iop.write_cmd( iop_const.PMOD_DIO_BASEADDR + iop_const.PMOD_DIO_TRI_OFFSET, iop_const.PMOD_CFG_DIO_ALLINPUT) else: self.iop.write_cmd( iop_const.PMOD_DIO_BASEADDR + iop_const.PMOD_DIO_TRI_OFFSET, iop_const.PMOD_CFG_DIO_ALLOUTPUT) self.iop.load_switch_config()
def __init__(self, if_id, index): """Return a new instance of a LED object. Parameters ---------- if_id : int The interface ID (1, 2) corresponding to (PMODA, PMODB). index: int The index of the pin in a Pmod, from 0 to 7. """ if not if_id in [PMODA, PMODB]: raise ValueError("No such IOP for Pmod device.") if not index in range(8): raise ValueError("Valid pin indexes are 0 - 7.") self.iop = DevMode(if_id, iop_const.PMOD_SWCFG_DIOALL) self.index = index self.iop.start() self.iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_TRI_OFFSET, \ iop_const.PMOD_CFG_DIO_ALLOUTPUT) self.iop.load_switch_config()
def __init__(self, if_id, index, direction): """Return a new instance of a Arduino IO object. Parameters ---------- if_id : int The interface ID (3) corresponding to (ARDUINO). index: int The index of the Arduino pin, from 0 to 19. direction : str Input 'in' or output 'out'. """ if not if_id in [ARDUINO]: raise ValueError("No such IOP for Arduino device.") if (index not in range(20)): raise ValueError("Valid pin indexes are 0 - 19.") if (direction not in ['in', 'out']): raise ValueError("Direction can only be 'in', or 'out'.") self.iop = DevMode(if_id, iop_const.ARDUINO_SWCFG_DIOALL) self.index = index self.direction = direction self.iop.start() if self.index in range(2): if (self.direction == 'in'): self.iop.write_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_TRI_OFFSET, \ iop_const.ARDUINO_CFG_UART_ALLINPUT) else: self.iop.write_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_TRI_OFFSET, \ iop_const.ARDUINO_CFG_UART_ALLOUTPUT) elif self.index in range(2, 14): if (self.direction == 'in'): self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_DIO_ALLINPUT) else: self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_DIO_ALLOUTPUT) else: if (self.direction == 'in'): self.iop.write_cmd(iop_const.ARDUINO_AIO_BASEADDR + \ iop_const.ARDUINO_AIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_AIO_ALLINPUT) else: self.iop.write_cmd(iop_const.ARDUINO_AIO_BASEADDR + \ iop_const.ARDUINO_AIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_AIO_ALLOUTPUT) self.iop.load_switch_config()
def __init__(self, if_id, scl_pin, sda_pin, iic_addr): """Return a new instance of a Pmod IIC object. Parameters ---------- if_id : int The interface ID (1, 2) corresponding to (PMODA, PMODB). scl_pin : int The SCL pin number. sda_pin : int The SDA pin number. iic_addr : int The IIC device address. """ if not if_id in [PMODA, PMODB]: raise ValueError("No such IOP for Pmod device.") if scl_pin not in range(8): raise ValueError("Valid SCL pin numbers are 0 - 7.") if sda_pin not in range(8): raise ValueError("Valid SDA pin numbers are 0 - 7.") switchconfig = [] for i in range(8): if i == sda_pin: switchconfig.append(iop_const.PMOD_SWCFG_IIC0_SDA) elif i == scl_pin: switchconfig.append(iop_const.PMOD_SWCFG_IIC0_SCL) else: switchconfig.append(iop_const.PMOD_SWCFG_DIO0) self.iop = DevMode(if_id, switchconfig) self.iop.start() self.iop.load_switch_config(switchconfig) self.iic_addr = iic_addr # Useful IIC controller addresses self.sr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_SR_REG_OFFSET self.dtr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_DTR_REG_OFFSET self.cr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_CR_REG_OFFSET self.rfd_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_RFD_REG_OFFSET self.drr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_DRR_REG_OFFSET
def test_devmode(): """Tests whether DevMode returns an _IOP for Pmod 1 and 2. For each Pmod ID, instantiate a DevMode object with various switch configurations. The returned objects should not be None. """ for iop_id in range(1,3): assert DevMode(iop_id, iop_const.PMOD_SWCFG_IIC0_TOPROW) is not None assert DevMode(iop_id, iop_const.PMOD_SWCFG_IIC0_BOTROW) is not None assert DevMode(iop_id, iop_const.PMOD_SWCFG_DIOALL) is not None ol.reset()
def test_devmode(): """Tests whether DevMode write and read work for Pmod 1 and 2. For each Pmod ID, write a command to the mailbox and read another command from the mailbox. Test whether the write and the read are successful. """ for iop_id in range(1,3): # Initiate the IOP iop = DevMode(iop_id, iop_const.PMOD_SWCFG_DIOALL) iop.start() assert iop.status()=="RUNNING" # Test whether writing is successful data = 0 iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_TRI_OFFSET, iop_const.PMOD_CFG_DIO_ALLINPUT) iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET, data) # Test whether reading is successful iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_TRI_OFFSET, iop_const.PMOD_CFG_DIO_ALLOUTPUT) data = iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) # Stop the IOP iop.stop() assert iop.status()=="STOPPED" ol.reset()
def __init__(self, if_id, index, direction): """Return a new instance of a Pmod IO object. Parameters ---------- if_id : int The interface ID (1, 2) corresponding to (PMODA, PMODB). index: int The index of the Pmod pin, from 0 to 7. direction : str Input 'in' or output 'out'. """ if not if_id in [PMODA, PMODB]: raise ValueError("No such IOP for Pmod device.") if not index in range(8): raise ValueError("Valid pin indexes are 0 - 7.") if not direction in ['in', 'out']: raise ValueError("Direction can only be 'in', or 'out'.") self.iop = DevMode(if_id, iop_const.PMOD_SWCFG_DIOALL) self.index = index self.direction = direction self.iop.start() if (self.direction == 'in'): self.iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_TRI_OFFSET, \ iop_const.PMOD_CFG_DIO_ALLINPUT) else: self.iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_TRI_OFFSET, \ iop_const.PMOD_CFG_DIO_ALLOUTPUT) self.iop.load_switch_config()
def __init__(self, if_id, index, direction): """Return a new instance of a Arduino IO object. Parameters ---------- if_id : int The interface ID (3) corresponding to (ARDUINO). index: int The index of the Arduino pin, from 0 to 19. direction : str Input 'in' or output 'out'. """ if not if_id in [ARDUINO]: raise ValueError("No such IOP for Arduino device.") if (index not in range(20)): raise ValueError("Valid pin indexes are 0 - 19.") if (direction not in ['in', 'out']): raise ValueError("Direction can only be 'in', or 'out'.") self.iop = DevMode(if_id, iop_const.ARDUINO_SWCFG_DIOALL) self.index = index self.direction = direction self.iop.start() if self.index in range(2): if (self.direction == 'in'): self.iop.write_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_TRI_OFFSET, \ iop_const.ARDUINO_CFG_UART_ALLINPUT) else: self.iop.write_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_TRI_OFFSET, \ iop_const.ARDUINO_CFG_UART_ALLOUTPUT) elif self.index in range(2,14): if (self.direction == 'in'): self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_DIO_ALLINPUT) else: self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_DIO_ALLOUTPUT) else: if (self.direction == 'in'): self.iop.write_cmd(iop_const.ARDUINO_AIO_BASEADDR + \ iop_const.ARDUINO_AIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_AIO_ALLINPUT) else: self.iop.write_cmd(iop_const.ARDUINO_AIO_BASEADDR + \ iop_const.ARDUINO_AIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_AIO_ALLOUTPUT) self.iop.load_switch_config()
def __init__(self, if_id, scl_pin, sda_pin, iic_addr): """Return a new instance of a Pmod IIC object. Parameters ---------- if_id : int The interface ID (1, 2) corresponding to (PMODA, PMODB). scl_pin : int The SCL pin number. sda_pin : int The SDA pin number. iic_addr : int The IIC device address. """ if not if_id in [PMODA, PMODB]: raise ValueError("No such IOP for Pmod device.") if (scl_pin not in range(8)): raise ValueError("Valid SCL pin numbers are 0 - 7.") if (sda_pin not in range(8)): raise ValueError("Valid SDA pin numbers are 0 - 7.") switchconfig = [] for i in range(8): if i == sda_pin: switchconfig.append(iop_const.PMOD_SWCFG_IIC0_SDA) elif i == scl_pin: switchconfig.append(iop_const.PMOD_SWCFG_IIC0_SCL) else: switchconfig.append(iop_const.PMOD_SWCFG_DIO0) self.iop = DevMode(if_id, switchconfig) self.iop.start() self.iop.load_switch_config(switchconfig) self.iic_addr = iic_addr # Useful IIC controller addresses self.sr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_SR_REG_OFFSET self.dtr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_DTR_REG_OFFSET self.cr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_CR_REG_OFFSET self.rfd_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_RFD_REG_OFFSET self.drr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_DRR_REG_OFFSET
class Pmod_IO(object): """This class controls the Pmod IO pins as inputs or outputs. Note ---- The parameter 'direction' determines whether the instance is input/output: 'in' : receiving input from offchip to onchip. 'out' : sending output from onchip to offchip. The index of the Pmod pins: upper row, from left to right: {vdd,gnd,3,2,1,0}. lower row, from left to right: {vdd,gnd,7,6,5,4}. Attributes ---------- iop : _IOP The _IOP object returned from the DevMode. index : int The index of the Pmod pin, from 0 to 7. direction : str Input 'in' or output 'out'. """ def __init__(self, if_id, index, direction): """Return a new instance of a Pmod IO object. Parameters ---------- if_id : int The interface ID (1, 2) corresponding to (PMODA, PMODB). index: int The index of the Pmod pin, from 0 to 7. direction : str Input 'in' or output 'out'. """ if not if_id in [PMODA, PMODB]: raise ValueError("No such IOP for Pmod device.") if not index in range(8): raise ValueError("Valid pin indexes are 0 - 7.") if not direction in ['in', 'out']: raise ValueError("Direction can only be 'in', or 'out'.") self.iop = DevMode(if_id, iop_const.PMOD_SWCFG_DIOALL) self.index = index self.direction = direction self.iop.start() if (self.direction == 'in'): self.iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_TRI_OFFSET, \ iop_const.PMOD_CFG_DIO_ALLINPUT) else: self.iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_TRI_OFFSET, \ iop_const.PMOD_CFG_DIO_ALLOUTPUT) self.iop.load_switch_config() def write(self, value): """Send the value to the offboard Pmod IO device. Note ---- Only use this function when direction is 'out'. Parameters ---------- value : int The value to be written to the Pmod IO device. Returns ------- None """ if not value in (0,1): raise ValueError("Pmod IO can only write 0 or 1.") if not self.direction == 'out': raise ValueError('Pmod IO used as output, declared as input.') if value: curVal = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) newVal = curVal | (0x1<<self.index) self.iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET, newVal) else: curVal = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) newVal = curVal & (0xff ^ (0x1<<self.index)) self.iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET, newVal) def read(self): """Receive the value from the offboard Pmod IO device. Note ---- Only use this function when direction is 'in'. Parameters ---------- None Returns ------- int The data (0 or 1) on the specified Pmod IO pin. """ if not self.direction == 'in': raise ValueError('Pmod IO used as input, but declared as output.') raw_value = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) return (raw_value >> (self.index)) & 0x1 def _state(self): """Retrieve the current state of the Pmod IO. This function is usually used for debug purpose. Users should still rely on read() or write() to get/put a value. Parameters ---------- None Returns ------- int The data (0 or 1) on the specified Pmod IO pin. """ raw_value = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) return (raw_value >> (self.index)) & 0x1
class Arduino_IO(object): """This class controls the Arduino IO pins as inputs or outputs. Note ---- The parameter 'direction' determines whether the instance is input/output: 'in' : receiving input from offchip to onchip. 'out' : sending output from onchip to offchip. Note ---- The index of the Arduino pins: upper row, from right to left: {0, 1, ..., 13}. (D0 - D13) lower row, from left to right: {14, 15,..., 19}. (A0 - A5) Attributes ---------- iop : _IOP The _IOP object returned from the DevMode. index : int The index of the Arduino pin, from 0 to 19. direction : str Input 'in' or output 'out'. """ def __init__(self, if_id, index, direction): """Return a new instance of a Arduino IO object. Parameters ---------- if_id : int The interface ID (3) corresponding to (ARDUINO). index: int The index of the Arduino pin, from 0 to 19. direction : str Input 'in' or output 'out'. """ if not if_id in [ARDUINO]: raise ValueError("No such IOP for Arduino device.") if (index not in range(20)): raise ValueError("Valid pin indexes are 0 - 19.") if (direction not in ['in', 'out']): raise ValueError("Direction can only be 'in', or 'out'.") self.iop = DevMode(if_id, iop_const.ARDUINO_SWCFG_DIOALL) self.index = index self.direction = direction self.iop.start() if self.index in range(2): if (self.direction == 'in'): self.iop.write_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_TRI_OFFSET, \ iop_const.ARDUINO_CFG_UART_ALLINPUT) else: self.iop.write_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_TRI_OFFSET, \ iop_const.ARDUINO_CFG_UART_ALLOUTPUT) elif self.index in range(2, 14): if (self.direction == 'in'): self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_DIO_ALLINPUT) else: self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_DIO_ALLOUTPUT) else: if (self.direction == 'in'): self.iop.write_cmd(iop_const.ARDUINO_AIO_BASEADDR + \ iop_const.ARDUINO_AIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_AIO_ALLINPUT) else: self.iop.write_cmd(iop_const.ARDUINO_AIO_BASEADDR + \ iop_const.ARDUINO_AIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_AIO_ALLOUTPUT) self.iop.load_switch_config() def write(self, value): """Send the value to the offboard Arduino IO device. Note ---- Only use this function when direction is 'out'. Parameters ---------- value : int The value to be written to the Arduino IO device. Returns ------- None """ if not value in (0, 1): raise ValueError("Arduino IO can only write 0 or 1.") if not self.direction == 'out': raise ValueError('Arduino IO used as output, declared as input.') if self.index in range(2): if value: curVal = self.iop.read_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_DATA_OFFSET) newVal = curVal | (0x1 << self.index) self.iop.write_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_DATA_OFFSET, newVal) else: curVal = self.iop.read_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_DATA_OFFSET) newVal = curVal & (0xffffffff ^ (0x1 << self.index)) self.iop.write_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_DATA_OFFSET, newVal) elif self.index in range(2, 14): if value: curVal = self.iop.read_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET) newVal = curVal | (0x1 << (self.index - 2)) self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET, newVal) else: curVal = self.iop.read_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET) newVal = curVal & (0xffffffff ^ (0x1 << (self.index - 2))) self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET, newVal) else: if value: curVal = self.iop.read_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET) newVal = curVal | (0x1 << (self.index - 14)) self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET, newVal) else: curVal = self.iop.read_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET) newVal = curVal & (0xffffffff ^ (0x1 << (self.index - 14))) self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET, newVal) def read(self): """Receive the value from the offboard Arduino IO device. Note ---- Only use this function when direction is 'in'. Parameters ---------- None Returns ------- int The data (0 or 1) on the specified Arduino IO pin. """ if not self.direction == 'in': raise ValueError('Arduino IO used as input, declared as output.') if self.index in range(2): raw_value = self.iop.read_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_DATA_OFFSET) return (raw_value >> (self.index)) & 0x1 elif self.index in range(2, 14): raw_value = self.iop.read_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET) return (raw_value >> (self.index - 2)) & 0x1 else: raw_value = self.iop.read_cmd(iop_const.ARDUINO_AIO_BASEADDR + \ iop_const.ARDUINO_AIO_DATA_OFFSET) return (raw_value >> (self.index - 14)) & 0x1 def _state(self): """Retrieve the current state of the Arduino IO. This function is usually used for debug purpose. Users should still rely on read() or write() to get/put a value. Parameters ---------- None Returns ------- int The data (0 or 1) on the specified Arduino IO pin. """ if self.index in range(2): raw_value = self.iop.read_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_DATA_OFFSET) return (raw_value >> (self.index)) & 0x1 elif self.index in range(2, 14): raw_value = self.iop.read_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET) return (raw_value >> (self.index - 2)) & 0x1 else: raw_value = self.iop.read_cmd(iop_const.ARDUINO_AIO_BASEADDR + \ iop_const.ARDUINO_AIO_DATA_OFFSET) return (raw_value >> (self.index - 14)) & 0x1
class Arduino_IO(object): """This class controls the Arduino IO pins as inputs or outputs. Note ---- The parameter 'direction' determines whether the instance is input/output: 'in' : receiving input from offchip to onchip. 'out' : sending output from onchip to offchip. Note ---- The index of the Arduino pins: upper row, from right to left: {0, 1, ..., 13}. (D0 - D13) lower row, from left to right: {14, 15,..., 19}. (A0 - A5) Attributes ---------- iop : _IOP The _IOP object returned from the DevMode. index : int The index of the Arduino pin, from 0 to 19. direction : str Input 'in' or output 'out'. """ def __init__(self, if_id, index, direction): """Return a new instance of a Arduino IO object. Parameters ---------- if_id : int The interface ID (3) corresponding to (ARDUINO). index: int The index of the Arduino pin, from 0 to 19. direction : str Input 'in' or output 'out'. """ if not if_id in [ARDUINO]: raise ValueError("No such IOP for Arduino device.") if (index not in range(20)): raise ValueError("Valid pin indexes are 0 - 19.") if (direction not in ['in', 'out']): raise ValueError("Direction can only be 'in', or 'out'.") self.iop = DevMode(if_id, iop_const.ARDUINO_SWCFG_DIOALL) self.index = index self.direction = direction self.iop.start() if self.index in range(2): if (self.direction == 'in'): self.iop.write_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_TRI_OFFSET, \ iop_const.ARDUINO_CFG_UART_ALLINPUT) else: self.iop.write_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_TRI_OFFSET, \ iop_const.ARDUINO_CFG_UART_ALLOUTPUT) elif self.index in range(2,14): if (self.direction == 'in'): self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_DIO_ALLINPUT) else: self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_DIO_ALLOUTPUT) else: if (self.direction == 'in'): self.iop.write_cmd(iop_const.ARDUINO_AIO_BASEADDR + \ iop_const.ARDUINO_AIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_AIO_ALLINPUT) else: self.iop.write_cmd(iop_const.ARDUINO_AIO_BASEADDR + \ iop_const.ARDUINO_AIO_TRI_OFFSET, \ iop_const.ARDUINO_CFG_AIO_ALLOUTPUT) self.iop.load_switch_config() def write(self, value): """Send the value to the offboard Arduino IO device. Note ---- Only use this function when direction is 'out'. Parameters ---------- value : int The value to be written to the Arduino IO device. Returns ------- None """ if not value in (0,1): raise ValueError("Arduino IO can only write 0 or 1.") if not self.direction == 'out': raise ValueError('Arduino IO used as output, declared as input.') if self.index in range(2): if value: curVal = self.iop.read_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_DATA_OFFSET) newVal = curVal | (0x1<<self.index) self.iop.write_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_DATA_OFFSET, newVal) else: curVal = self.iop.read_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_DATA_OFFSET) newVal = curVal & (0xffffffff ^ (0x1<<self.index)) self.iop.write_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_DATA_OFFSET, newVal) elif self.index in range(2,14): if value: curVal = self.iop.read_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET) newVal = curVal | (0x1<<(self.index-2)) self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET, newVal) else: curVal = self.iop.read_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET) newVal = curVal & (0xffffffff ^ (0x1<<(self.index-2))) self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET, newVal) else: if value: curVal = self.iop.read_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET) newVal = curVal | (0x1<<(self.index-14)) self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET, newVal) else: curVal = self.iop.read_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET) newVal = curVal & (0xffffffff ^ (0x1<<(self.index-14))) self.iop.write_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET, newVal) def read(self): """Receive the value from the offboard Arduino IO device. Note ---- Only use this function when direction is 'in'. Parameters ---------- None Returns ------- int The data (0 or 1) on the specified Arduino IO pin. """ if not self.direction == 'in': raise ValueError('Arduino IO used as input, declared as output.') if self.index in range(2): raw_value = self.iop.read_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_DATA_OFFSET) return (raw_value >> (self.index)) & 0x1 elif self.index in range(2,14): raw_value = self.iop.read_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET) return (raw_value >> (self.index-2)) & 0x1 else: raw_value = self.iop.read_cmd(iop_const.ARDUINO_AIO_BASEADDR + \ iop_const.ARDUINO_AIO_DATA_OFFSET) return (raw_value >> (self.index-14)) & 0x1 def _state(self): """Retrieve the current state of the Arduino IO. This function is usually used for debug purpose. Users should still rely on read() or write() to get/put a value. Parameters ---------- None Returns ------- int The data (0 or 1) on the specified Arduino IO pin. """ if self.index in range(2): raw_value = self.iop.read_cmd(iop_const.ARDUINO_UART_BASEADDR + \ iop_const.ARDUINO_UART_DATA_OFFSET) return (raw_value >> (self.index)) & 0x1 elif self.index in range(2,14): raw_value = self.iop.read_cmd(iop_const.ARDUINO_DIO_BASEADDR + \ iop_const.ARDUINO_DIO_DATA_OFFSET) return (raw_value >> (self.index-2)) & 0x1 else: raw_value = self.iop.read_cmd(iop_const.ARDUINO_AIO_BASEADDR + \ iop_const.ARDUINO_AIO_DATA_OFFSET) return (raw_value >> (self.index-14)) & 0x1
class Pmod_IIC(object): """This class controls the Pmod IIC pins. Note ---- The index of the Pmod pins: upper row, from left to right: {vdd,gnd,3,2,1,0}. lower row, from left to right: {vdd,gnd,7,6,5,4}. Attributes ---------- iop : _IOP The _IOP object returned from the DevMode. scl_pin : int The SCL pin number. sda_pin : int The SDA pin number. iic_addr : int The IIC device address. sr_addr : int The IIC device SR address (base address + 0x104). dtr_addr : int The IIC device DTR address (base address + 0x108). cr_addr : int The IIC device CR address (base address + 0x100). rfd_addr : int The IIC device RFD address (base address + 0x120). drr_addr : int The IIC device DRR address (base address + 0x10C). """ def __init__(self, if_id, scl_pin, sda_pin, iic_addr): """Return a new instance of a Pmod IIC object. Parameters ---------- if_id : int The interface ID (1, 2) corresponding to (PMODA, PMODB). scl_pin : int The SCL pin number. sda_pin : int The SDA pin number. iic_addr : int The IIC device address. """ if not if_id in [PMODA, PMODB]: raise ValueError("No such IOP for Pmod device.") if (scl_pin not in range(8)): raise ValueError("Valid SCL pin numbers are 0 - 7.") if (sda_pin not in range(8)): raise ValueError("Valid SDA pin numbers are 0 - 7.") switchconfig = [] for i in range(8): if i == sda_pin: switchconfig.append(iop_const.PMOD_SWCFG_IIC0_SDA) elif i == scl_pin: switchconfig.append(iop_const.PMOD_SWCFG_IIC0_SCL) else: switchconfig.append(iop_const.PMOD_SWCFG_DIO0) self.iop = DevMode(if_id, switchconfig) self.iop.start() self.iop.load_switch_config(switchconfig) self.iic_addr = iic_addr # Useful IIC controller addresses self.sr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_SR_REG_OFFSET self.dtr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_DTR_REG_OFFSET self.cr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_CR_REG_OFFSET self.rfd_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_RFD_REG_OFFSET self.drr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_DRR_REG_OFFSET def _iic_enable(self): """This method enables the IIC drivers. The correct sequence to enable the drivers is: 1. Disale the IIC core. 2. Set the Rx FIFO depth to maximum. 3. Reset the IIC core and flush the Tx FIFO. 4. Enable the IIC core. Note ---- This function is only required during initialization. Parameters ---------- None Returns ------- None """ # Disable the IIC core self.iop.write_cmd(self.cr_addr, 0x00) # Set the Rx FIFO depth to maximum self.iop.write_cmd(self.rfd_addr, 0x0F) # Reset the IIC core and flush the Tx FIFO self.iop.write_cmd(self.cr_addr, 0x02) # Enable the IIC core self.iop.write_cmd(self.cr_addr, 0x01) sleep(I2C_DELAY) def send(self, iic_bytes): """This method sends the command or data to the driver. Parameters ---------- iic_bytes : list A list of 8-bit bytes to be sent to the driver. Returns ------- None Raises ------ RuntimeError Timeout when waiting for the FIFO to be empty. """ # Enable IIC Core self._iic_enable() # Transmit 7-bit address and Write bit (with START) self.iop.write_cmd(self.dtr_addr, 0x100 | (self.iic_addr << 1)) # Iteratively write into Tx FIFO, wait for it to be empty for tx_cnt in range(len(iic_bytes)): timeout = 100 # Construct the TX word if (tx_cnt == len(iic_bytes) - 1): tx_word = (0x200 | iic_bytes[tx_cnt]) else: tx_word = iic_bytes[tx_cnt] # Write data self.iop.write_cmd(self.dtr_addr, tx_word) while ((timeout > 0) and \ ((self.iop.read_cmd(self.sr_addr) & 0x80) == 0x00)): timeout -= 1 if (timeout == 0): raise RuntimeError("Timeout when writing IIC.") sleep(I2C_DELAY) def receive(self, num_bytes): """This method receives IIC bytes from the device. Parameters ---------- num_bytes : int Number of bytes to be received from the device. Returns ------- iic_bytes : list A list of 8-bit bytes received from the driver. Raises ------ RuntimeError Timeout when waiting for the RX FIFO to fill. """ # Reset the IIC core and flush the Tx FIFO self.iop.write_cmd(self.cr_addr, 0x02) # Set the Rx FIFO depth to one byte self.iop.write_cmd(self.rfd_addr, 0x0) # Transmit 7-bit address and Read bit self.iop.write_cmd(self.dtr_addr, 0x101 | (self.iic_addr << 1)) # Enable the IIC core cr_reg = 0x05 if num_bytes == 1: cr_reg |= 0x10 self.iop.write_cmd(self.cr_addr,cr_reg) sleep(I2C_DELAY) # Program IIC Core to read num_bytes bytes and issue STOP self.iop.write_cmd(self.dtr_addr, 0x200 + num_bytes) # Read num_bytes from RX FIFO iic_bytes = list() while(len(iic_bytes) < num_bytes): # Special condition for last two bytes if (num_bytes - len(iic_bytes)) == 1: self.iop.write_cmd(self.cr_addr,0x1) elif (num_bytes - len(iic_bytes)) == 2: self.iop.write_cmd(self.cr_addr, \ self.iop.read_cmd(self.cr_addr) | 0x10) # Wait for data to be available in RX FIFO timeout = 100 while(((self.iop.read_cmd(self.sr_addr) & 0x40) == 0x40) and \ (timeout > 0)): timeout -= 1 if(timeout == 0): raise RuntimeError("Timeout when reading IIC.") # Read data iic_bytes.append((self.iop.read_cmd(self.drr_addr) & 0xff)) sleep(I2C_DELAY) return iic_bytes
class Pmod_LED8(object): """This class controls a single LED on the LED8 Pmod. The Pmod LED8 (PB 200-163) has eight high-brightness LEDs. Each LED can be individually illuminated from a logic high signal. Attributes ---------- iop : _IOP I/O processor instance used by LED8. index : int Index of the pin on LED8, from 0 to 7. """ def __init__(self, if_id, index): """Return a new instance of a LED object. Parameters ---------- if_id : int The interface ID (1, 2) corresponding to (PMODA, PMODB). index: int The index of the pin in a Pmod, from 0 to 7. """ if not if_id in [PMODA, PMODB]: raise ValueError("No such IOP for Pmod device.") if not index in range(8): raise ValueError("Valid pin indexes are 0 - 7.") self.iop = DevMode(if_id, iop_const.PMOD_SWCFG_DIOALL) self.index = index self.iop.start() self.iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_TRI_OFFSET, \ iop_const.PMOD_CFG_DIO_ALLOUTPUT) self.iop.load_switch_config() def toggle(self): """Flip the bit of a single LED. Note ---- The LED will be turned off if it is on. Similarly, it will be turned on if it is off. Parameters ---------- None Returns ------- None """ curr_val = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) new_val = (curr_val) ^ (0x1 << self.index) self._set_leds_values(new_val) def on(self): """Turn on a single LED. Parameters ---------- None Returns ------- None """ curr_val = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) new_val = (curr_val) | (0x1 << self.index) self._set_leds_values(new_val) def off(self): """Turn off a single LED. Parameters ---------- None Returns ------- None """ curr_val = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) new_val = (curr_val) & (0xff ^ (0x1 << self.index)) self._set_leds_values(new_val) def write(self, value): """Set the LED state according to the input value Note ---- This method does not take into account the current LED state. Parameters ---------- value : int Turn on the LED if value is 1; turn it off if value is 0. Returns ------- None """ if not value in (0, 1): raise ValueError("LED8 can only write 0 or 1.") if value: self.on() else: self.off() def read(self): """Retrieve the LED state. Parameters ---------- None Returns ------- int The data (0 or 1) read out from the selected pin. """ curr_val = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) return (curr_val >> self.index) & 0x1 def _set_leds_values(self, value): """Set the state for all the LEDs. Note ---- Should not be used directly. User should rely on toggle(), on(), off(), write(), and read() instead. Parameters ---------- value : int The state of all the LEDs encoded in one single value Returns ------- None """ self.iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET, value)
class Pmod_LED8(object): """This class controls a single LED on the LED8 Pmod. The Pmod LED8 (PB 200-163) has eight high-brightness LEDs. Each LED can be individually illuminated from a logic high signal. Attributes ---------- iop : _IOP I/O processor instance used by LED8. index : int Index of the pin on LED8, from 0 to 7. """ def __init__(self, if_id, index): """Return a new instance of a LED object. Parameters ---------- if_id : int The interface ID (1, 2) corresponding to (PMODA, PMODB). index: int The index of the pin in a Pmod, from 0 to 7. """ if not if_id in [PMODA, PMODB]: raise ValueError("No such IOP for Pmod device.") if not index in range(8): raise ValueError("Valid pin indexes are 0 - 7.") self.iop = DevMode(if_id, iop_const.PMOD_SWCFG_DIOALL) self.index = index self.iop.start() self.iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_TRI_OFFSET, \ iop_const.PMOD_CFG_DIO_ALLOUTPUT) self.iop.load_switch_config() def toggle(self): """Flip the bit of a single LED. Note ---- The LED will be turned off if it is on. Similarly, it will be turned on if it is off. Parameters ---------- None Returns ------- None """ curr_val = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) new_val = (curr_val) ^ (0x1 << self.index) self._set_leds_values(new_val) def on(self): """Turn on a single LED. Parameters ---------- None Returns ------- None """ curr_val = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) new_val = (curr_val) | (0x1 << self.index) self._set_leds_values(new_val) def off(self): """Turn off a single LED. Parameters ---------- None Returns ------- None """ curr_val = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) new_val = (curr_val) & (0xff ^ (0x1 << self.index)) self._set_leds_values(new_val) def write(self, value): """Set the LED state according to the input value Note ---- This method does not take into account the current LED state. Parameters ---------- value : int Turn on the LED if value is 1; turn it off if value is 0. Returns ------- None """ if not value in (0,1): raise ValueError("LED8 can only write 0 or 1.") if value: self.on() else: self.off() def read(self): """Retrieve the LED state. Parameters ---------- None Returns ------- int The data (0 or 1) read out from the selected pin. """ curr_val = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) return (curr_val >> self.index) & 0x1 def _set_leds_values(self, value): """Set the state for all the LEDs. Note ---- Should not be used directly. User should rely on toggle(), on(), off(), write(), and read() instead. Parameters ---------- value : int The state of all the LEDs encoded in one single value Returns ------- None """ self.iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET, value)
class Pmod_IO(object): """This class controls the Pmod IO pins as inputs or outputs. Note ---- The parameter 'direction' determines whether the instance is input/output: 'in' : receiving input from offchip to onchip. 'out' : sending output from onchip to offchip. The index of the Pmod pins: upper row, from left to right: {vdd,gnd,3,2,1,0}. lower row, from left to right: {vdd,gnd,7,6,5,4}. Attributes ---------- iop : _IOP The _IOP object returned from the DevMode. index : int The index of the Pmod pin, from 0 to 7. direction : str Input 'in' or output 'out'. """ def __init__(self, if_id, index, direction): """Return a new instance of a Pmod IO object. Parameters ---------- if_id : int The interface ID (1, 2) corresponding to (PMODA, PMODB). index: int The index of the Pmod pin, from 0 to 7. direction : str Input 'in' or output 'out'. """ if not if_id in [PMODA, PMODB]: raise ValueError("No such IOP for Pmod device.") if not index in range(8): raise ValueError("Valid pin indexes are 0 - 7.") if not direction in ['in', 'out']: raise ValueError("Direction can only be 'in', or 'out'.") self.iop = DevMode(if_id, iop_const.PMOD_SWCFG_DIOALL) self.index = index self.direction = direction self.iop.start() if self.direction == 'in': self.iop.write_cmd( iop_const.PMOD_DIO_BASEADDR + iop_const.PMOD_DIO_TRI_OFFSET, iop_const.PMOD_CFG_DIO_ALLINPUT) else: self.iop.write_cmd( iop_const.PMOD_DIO_BASEADDR + iop_const.PMOD_DIO_TRI_OFFSET, iop_const.PMOD_CFG_DIO_ALLOUTPUT) self.iop.load_switch_config() def write(self, value): """Send the value to the offboard Pmod IO device. Note ---- Only use this function when direction is 'out'. Parameters ---------- value : int The value to be written to the Pmod IO device. Returns ------- None """ if not value in (0, 1): raise ValueError("Pmod IO can only write 0 or 1.") if not self.direction == 'out': raise ValueError('Pmod IO used as output, declared as input.') if value: cur_val = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) new_val = cur_val | (0x1 << self.index) self.iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET, new_val) else: cur_val = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) new_val = cur_val & (0xff ^ (0x1 << self.index)) self.iop.write_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET, new_val) def read(self): """Receive the value from the offboard Pmod IO device. Note ---- Only use this function when direction is 'in'. Returns ------- int The data (0 or 1) on the specified Pmod IO pin. """ if not self.direction == 'in': raise ValueError('Pmod IO used as input, but declared as output.') raw_value = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) return (raw_value >> self.index) & 0x1 def _state(self): """Retrieve the current state of the Pmod IO. This function is usually used for debug purpose. Users should still rely on read() or write() to get/put a value. Returns ------- int The data (0 or 1) on the specified Pmod IO pin. """ raw_value = self.iop.read_cmd(iop_const.PMOD_DIO_BASEADDR + \ iop_const.PMOD_DIO_DATA_OFFSET) return (raw_value >> self.index) & 0x1
class Pmod_IIC(object): """This class controls the Pmod IIC pins. Note ---- The index of the Pmod pins: upper row, from left to right: {vdd,gnd,3,2,1,0}. lower row, from left to right: {vdd,gnd,7,6,5,4}. Attributes ---------- iop : _IOP The _IOP object returned from the DevMode. scl_pin : int The SCL pin number. sda_pin : int The SDA pin number. iic_addr : int The IIC device address. sr_addr : int The IIC device SR address (base address + 0x104). dtr_addr : int The IIC device DTR address (base address + 0x108). cr_addr : int The IIC device CR address (base address + 0x100). rfd_addr : int The IIC device RFD address (base address + 0x120). drr_addr : int The IIC device DRR address (base address + 0x10C). """ def __init__(self, if_id, scl_pin, sda_pin, iic_addr): """Return a new instance of a Pmod IIC object. Parameters ---------- if_id : int The interface ID (1, 2) corresponding to (PMODA, PMODB). scl_pin : int The SCL pin number. sda_pin : int The SDA pin number. iic_addr : int The IIC device address. """ if not if_id in [PMODA, PMODB]: raise ValueError("No such IOP for Pmod device.") if scl_pin not in range(8): raise ValueError("Valid SCL pin numbers are 0 - 7.") if sda_pin not in range(8): raise ValueError("Valid SDA pin numbers are 0 - 7.") switchconfig = [] for i in range(8): if i == sda_pin: switchconfig.append(iop_const.PMOD_SWCFG_IIC0_SDA) elif i == scl_pin: switchconfig.append(iop_const.PMOD_SWCFG_IIC0_SCL) else: switchconfig.append(iop_const.PMOD_SWCFG_DIO0) self.iop = DevMode(if_id, switchconfig) self.iop.start() self.iop.load_switch_config(switchconfig) self.iic_addr = iic_addr # Useful IIC controller addresses self.sr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_SR_REG_OFFSET self.dtr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_DTR_REG_OFFSET self.cr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_CR_REG_OFFSET self.rfd_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_RFD_REG_OFFSET self.drr_addr = iop_const.PMOD_XIIC_0_BASEADDR + \ iop_const.PMOD_XIIC_DRR_REG_OFFSET def _iic_enable(self): """This method enables the IIC drivers. The correct sequence to enable the drivers is: 1. Disale the IIC core. 2. Set the Rx FIFO depth to maximum. 3. Reset the IIC core and flush the Tx FIFO. 4. Enable the IIC core. Note ---- This function is only required during initialization. Parameters ---------- None Returns ------- None """ # Disable the IIC core self.iop.write_cmd(self.cr_addr, 0x00) # Set the Rx FIFO depth to maximum self.iop.write_cmd(self.rfd_addr, 0x0F) # Reset the IIC core and flush the Tx FIFO self.iop.write_cmd(self.cr_addr, 0x02) # Enable the IIC core self.iop.write_cmd(self.cr_addr, 0x01) sleep(I2C_DELAY) def send(self, iic_bytes): """This method sends the command or data to the driver. Parameters ---------- iic_bytes : list A list of 8-bit bytes to be sent to the driver. Returns ------- None Raises ------ RuntimeError Timeout when waiting for the FIFO to be empty. """ # Enable IIC Core self._iic_enable() # Transmit 7-bit address and Write bit (with START) self.iop.write_cmd(self.dtr_addr, 0x100 | (self.iic_addr << 1)) # Iteratively write into Tx FIFO, wait for it to be empty for tx_cnt in range(len(iic_bytes)): timeout = 100 # Construct the TX word if tx_cnt == len(iic_bytes) - 1: tx_word = (0x200 | iic_bytes[tx_cnt]) else: tx_word = iic_bytes[tx_cnt] # Write data self.iop.write_cmd(self.dtr_addr, tx_word) while ((timeout > 0) and ((self.iop.read_cmd(self.sr_addr) & 0x80) == 0x00)): timeout -= 1 if timeout == 0: raise RuntimeError("Timeout when writing IIC.") sleep(I2C_DELAY) def receive(self, num_bytes): """This method receives IIC bytes from the device. Parameters ---------- num_bytes : int Number of bytes to be received from the device. Returns ------- iic_bytes : list A list of 8-bit bytes received from the driver. Raises ------ RuntimeError Timeout when waiting for the RX FIFO to fill. """ # Reset the IIC core and flush the Tx FIFO self.iop.write_cmd(self.cr_addr, 0x02) # Set the Rx FIFO depth to one byte self.iop.write_cmd(self.rfd_addr, 0x0) # Transmit 7-bit address and Read bit self.iop.write_cmd(self.dtr_addr, 0x101 | (self.iic_addr << 1)) # Enable the IIC core cr_reg = 0x05 if num_bytes == 1: cr_reg |= 0x10 self.iop.write_cmd(self.cr_addr, cr_reg) sleep(I2C_DELAY) # Program IIC Core to read num_bytes bytes and issue STOP self.iop.write_cmd(self.dtr_addr, 0x200 + num_bytes) # Read num_bytes from RX FIFO iic_bytes = list() while len(iic_bytes) < num_bytes: # Special condition for last two bytes if (num_bytes - len(iic_bytes)) == 1: self.iop.write_cmd(self.cr_addr, 0x1) elif (num_bytes - len(iic_bytes)) == 2: self.iop.write_cmd(self.cr_addr, self.iop.read_cmd(self.cr_addr) | 0x10) # Wait for data to be available in RX FIFO timeout = 100 while (((self.iop.read_cmd(self.sr_addr) & 0x40) == 0x40) and (timeout > 0)): timeout -= 1 if timeout == 0: raise RuntimeError("Timeout when reading IIC.") # Read data iic_bytes.append((self.iop.read_cmd(self.drr_addr) & 0xff)) sleep(I2C_DELAY) return iic_bytes