Beispiel #1
0
    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()
Beispiel #2
0
    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()
Beispiel #3
0
    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()
Beispiel #4
0
    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
Beispiel #5
0
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()
Beispiel #6
0
    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()
Beispiel #7
0
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()
Beispiel #8
0
 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()
Beispiel #9
0
 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()
Beispiel #10
0
    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
Beispiel #11
0
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
        
Beispiel #12
0
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
Beispiel #13
0
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
Beispiel #14
0
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
Beispiel #15
0
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)
Beispiel #16
0
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)
Beispiel #17
0
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
Beispiel #18
0
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