make SPI class work
authorDan White <dan@whiteaudio.com>
Fri, 13 Jul 2012 02:18:24 +0000 (21:18 -0500)
committerDan White <dan@whiteaudio.com>
Fri, 13 Jul 2012 02:18:24 +0000 (21:18 -0500)
python-lib/usbio.py

index 77833f7ecae9603ec46834c10036ce144eeffa80..e1e82a7d3f95186608bcc8ea83ac0850c884fc12 100644 (file)
@@ -311,13 +311,13 @@ class SPI(object):
     MPSSE_BITWISE_MODE = ftdi.MPSSE_BITMODE
     MPSSE_LSB_FIRST = ftdi.MPSSE_LSB
 
-    def __init__(self, interface=ftdi.INTERFACE_A, csidle=0, cs=None,
+    def __init__(self, interface=ftdi.INTERFACE_A, cs=None,
                     mode=0,
                     freq=1e6,
                     vid=0x0403, pid=0x6011,
                     pindir=0xc0, pinstate=0xc0,
-                    latency=1,
-                    delay=0.001, timeout=100):
+                    latency=1
+                ):
         """SPI port using the MPSSE on compatible FTDI devices with flexible
         chip-select and composite command sequences.  Uses the libftdi python
         bindings.
@@ -327,7 +327,6 @@ class SPI(object):
         Hence this class..
 
         interface = ftdi.INTERFACE_x or [1,2,3,4]
-        csidle = 8-bit port state for no chip-selects asserted
         cs = dict specifying pin states to affect chip-select lines
             special keys are '_idle': no-cs-asserted pin state
                              '_mask': bitmask with 1's in CS-related pin bits
@@ -337,40 +336,40 @@ class SPI(object):
         pinstate = initial pin state
         """
         self.interface = interface
-        self.csidle = csidle
         self.cs = cs
         #defer mode until chip is init'd
         #defer freq until chip is init'd
         self.vid = vid
         self.pid = pid
-        #self._pindir = pindir 
-        #self._pinstate = pinstate
-
-        self.DELAY = delay
-        self.TIMEOUT = timeout
+        self.latency = latency
 
         # setup the driver for this interface, init usb
-        self.context = ftdi.new()
-        ftdi.set_interface(self.context, interface)
+        self.ftdi = ftdi #local reference to speed lookups
+        self.context = self.ftdi.new()
+        self.ftdi.set_interface(self.context, interface)
 
         # TODO: what should chunksize be? 4k is libftdi default,
         # 4232h uses 2k FIFOs
         # 2232h uses 4k FIFOs
-        #ftdi.write_data_set_chunksize(self.context, 4096)
-        #ftdi.read_data_set_chunksize(self.context, 4096)
+        #self.ftdi.write_data_set_chunksize(self.context, 4096)
+        #self.ftdi.read_data_set_chunksize(self.context, 4096)
 
         # libftdi has several ways of selecting the desired device, see its
         # source
-        e = ftdi.usb_open(self.context, vid, pid)
+        e = self.ftdi.usb_open(self.context, vid, pid)
         if e != 0:
-            raise Exception, ftdi.get_error_string(self.context)
+            raise Exception, self.ftdi.get_error_string(self.context)
 
-        ftdi.set_bitmode(self.context, int(self.pindir), ftdi.BITMODE_RESET)
-        ftdi.set_bitmode(self.context, int(self.pindir), ftdi.BITMODE_MPSSE)
-        self.set_mode(mode)
+        self.ftdi.set_latency_timer(self.context, max(1, min(255, latency)))
+        self.ftdi.set_bitmode(self.context, int(pindir), self.ftdi.BITMODE_RESET)
+        self.ftdi.set_bitmode(self.context, int(pindir), self.ftdi.BITMODE_MPSSE)
         self.set_freq(freq)
+        self._pindir = 0
+        self._pinstate = 0
+        self._mode = mode #hack to get an initial value
         self.set_pins(pinstate, pindir)
-        ftdi.usb_purge_buffers(self.context)
+        self.set_mode(mode)
+        self.ftdi.usb_purge_buffers(self.context)
 
     def _raw_write(self, data):
         """Write data as
@@ -378,21 +377,20 @@ class SPI(object):
         #translate data to a string
         if not isinstance(data, str):
             data = ''.join(map(chr, data))
-        ret = ftdi.write_data(self.context, data, len(data))
-        if ret != 0:
-            raise Exception, ftdi.get_error_string(self.context)
+        ret = self.ftdi.write_data(self.context, data, len(data))
+        if ret < 0:
+            raise Exception, self.ftdi.get_error_string(self.context)
 
     def _raw_read(self, n):
         """Read n bytes from buffer."""
         nread = 0
         r = ''
         while len(r) < n:
-            s = ftdi.read_data(self.context, n)
-            #does this really catch errors??
-            if not s:
-                raise Exception, ftdi.get_error_string(self.context)
+            ret, s = self.ftdi.read_data(self.context, n)
+            if ret < 0:
+                raise Exception, self.ftdi.get_error_string(self.context)
             r += s
-        ftdi.usb_purge_rx_buffer(self.context)
+        self.ftdi.usb_purge_rx_buffer(self.context)
         return r
 
     def set_freq(self, freq):
@@ -401,8 +399,6 @@ class SPI(object):
         """
         # calc rates for both x5 and /5 modes and choose the closest, prefer
         # the /5 mode if a tie
-        f = CLK / ((1+divisor)*2)
-        options = [] # (prescale, divisor, actual)
         CLK = 12000000
         div5 = max(int(round((CLK / (2.0 * freq)))) - 1, 0) #ensure >= 0
         div1 = max(int(round((5*CLK / (2.0 * freq)))) - 1, 0)
@@ -413,14 +409,14 @@ class SPI(object):
             div = div5
             act = act5
             #reset state has 60 MHz / 5 prescaler enabled
-            #ftdi.write_data(self.context, chr(ftdi.EN_DIV_5), 1)
+            #self.ftdi.write_data(self.context, chr(self.ftdi.EN_DIV_5), 1)
         else:
             div = div1
             act = act1
-            ftdi.write_data(self.context, chr(ftdi.DIS_DIV_5), 1)
+            self.ftdi.write_data(self.context, chr(self.ftdi.DIS_DIV_5), 1)
 
-        cmd = chr(ftdi.TCK_DIVISOR) + uint16str(div)
-        ftdi.write_data(self.context, cmd, len(cmd))
+        cmd = chr(self.ftdi.TCK_DIVISOR) + uint16str(div)
+        self.ftdi.write_data(self.context, cmd, len(cmd))
         self._freq = act
         return act
 
@@ -436,7 +432,7 @@ class SPI(object):
             #ensure pin 0/SK starts in its idle state in case this is a mode change
             #yes, the check is done in set_pins(), but paranoia never hurts..
             p = self._pinstate
-            if self.mode in (0, 1):
+            if mode in (0, 1):
                 #cpol = 0
                 p &= 0xFE
             else:
@@ -453,7 +449,7 @@ class SPI(object):
         """
         return self._mode
 
-    def set_pins(pinstate=None, pindir=None, audit_cs=True):
+    def set_pins(self, pinstate=None, pindir=None, audit_cs=True):
         """Change the GPIO pins [3..7] to the given state and direction.
         Argument values of None mean "do not change".  Audits the values to
         keep the SPI SK/DO/DI pins and configured chip-select pins in correct
@@ -464,7 +460,7 @@ class SPI(object):
             self._pindir = pindir
             #we are changing pin directions, audit them
             self._pindir |= 0x03 # pins 0/SK and 1/DO are outputs for sure
-            self._pindir |= self._cs_mask # chip-select pins are always outputs
+            self._pindir |= self.cs['_mask'] # chip-select pins are always outputs
             self._pindir &= 0xFB # pin 2/DI is an input for sure
             # most implementations force pin 3/CS to an output, IT DOES NOT
             # NEED DO BE.  The top 5 pins are available for GPIO, CS, or both
@@ -473,8 +469,8 @@ class SPI(object):
 
         if pinstate is not None:
             if audit_cs:
-                self._pinstate = ((pinstate & ~self._cs_mask) +
-                                    (self.csidle & self._cs_mask))
+                self._pinstate = ((pinstate & ~self.cs['_mask']) +
+                                    (self.cs['_idle'] & self.cs['_mask']))
             else:
                 self._pinstate = pinstate
 
@@ -486,11 +482,11 @@ class SPI(object):
                 #cpol = 1
                 self._pinstate |= 0x01
 
-        cmd = chr(ftdi.SET_BITS_LOW) + chr(self._pinstate) + chr(self._pindir)
+        cmd = chr(self.ftdi.SET_BITS_LOW) + chr(self._pinstate) + chr(self._pindir)
         self._raw_write(cmd)
 
     def get_pins(self):
-        cmd = chr(ftdi.GET_BITS_LOW) + chr(ftdi.SEND_IMMEDIATE)
+        cmd = chr(self.ftdi.GET_BITS_LOW) + chr(self.ftdi.SEND_IMMEDIATE)
         self._raw_write(cmd)
         p = self._read_raw(1)
         self._pinstate = p
@@ -517,7 +513,7 @@ class SPI(object):
         p += self.cs[device] & mask
 
         self._pinstate = p
-        cmd = chr(ftdi.SET_BITS_LOW) + chr(p) + chr(self._pindir)
+        cmd = chr(self.ftdi.SET_BITS_LOW) + chr(p) + chr(self._pindir)
         return cmd
 
     def _write_cmd(self, data):
@@ -551,7 +547,7 @@ class SPI(object):
             data = ''.join(map(chr, data))
 
         cmd += data
-        cmd += chr(ftdi.SEND_IMMEDIATE)
+        cmd += chr(self.ftdi.SEND_IMMEDIATE)
         return cmd
 
     def _read_cmd(self, n):
@@ -561,7 +557,7 @@ class SPI(object):
         cmd = chr(self.MPSSE_SPI_MODE_CONFIG[self.mode] |
                   self.MPSSE_READ)
         cmd += uint16str(n - 1)
-        cmd += chr(ftdi.SEND_IMMEDIATE)
+        cmd += chr(self.ftdi.SEND_IMMEDIATE)
         return cmd
 
     def write(self, data, device):
@@ -590,7 +586,7 @@ class SPI(object):
         cmd = (self._cs_cmd(device) + self._exchange_cmd(data) +
                 self._cs_cmd('_idle'))
         self._raw_write(cmd)
-        return self._raw_read(n)
+        return self._raw_read(len(data))
 
 
 
@@ -1175,11 +1171,7 @@ class DAC8568(object):
         return tuple(b)
 
     def send(self):
-        self.bus.SetCS('dac')
-        #self.bus.Start()
-        #self.bus.Write(str(self))
-        #self.bus.Stop()
-        self.bus.Exchange(str(self))
+        self.bus.exchange(str(self), 'dac')
 
     #
     # internal functions to help construct a command
@@ -1237,19 +1229,19 @@ class ADS8201(object):
         w = intbv(0x8000)[16:]
         w[14:10] = intbv(address, max=2**4)
         w[8:] = intbv(value, max=2**8)
-        self.bus.SetCS('adc')
-        self.bus.Start()
-        self.bus.Write(int2str(w, 16))
-        self.bus.Stop()
+        #self.bus.SetCS('adc')
+        #self.bus.Start()
+        self.bus.write(int2str(w, 16), 'adc')
+        #self.bus.Stop()
 
     def getRegister(self, address):
         w = intbv(0x4000)[16:]
         w[14:10] = intbv(address, max=2**4)
         #print 'sending:', b(w, 16)
-        self.bus.SetCS('adc')
-        self.bus.Start()
-        rval = self.bus.Exchange(int2str(w, 16))
-        self.bus.Stop()
+        #self.bus.SetCS('adc')
+        #self.bus.Start()
+        rval = self.bus.exchange(int2str(w, 16), 'adc')
+        #self.bus.Stop()
         #i = 8 * (len(rval)-1)
         #r = 0
         #for c in rval:
@@ -1391,9 +1383,9 @@ class ADS8201(object):
         settings.  Last 4 LSB are averaging bits."""
         # TODO: also optionally read 4 TAG bits
         w = intbv(0x0000)[16:]
-        self.bus.SetCS('adc')
+        #self.bus.SetCS('adc')
         #self.bus.Start()
-        rval = self.bus.Exchange(int2str(w, 16))
+        rval = self.bus.exchange(int2str(w, 16), 'adc')
         #self.bus.Stop()
         i = 8 * (len(rval)-1)
         r = 0
@@ -1520,20 +1512,24 @@ class M25PExx(object):
 
 
 
-class AtoiSPI0(mpsse.MPSSE):
+class AtoiSPI0(SPI):
     def __init__(self, freq):
-        super(AtoiSPI0, self).__init__()
-        self._freq = int(freq)
-        self.Open(0x0403, 0x6011, mpsse.SPI1, int(freq),
-                interface=mpsse.IFACE_A)
-        self._cs = None
-        self._cs_mode = {
-                'flash': mpsse.SPI0,
-                'dac': mpsse.SPI1,
-                'adc': mpsse.SPI1,
-                'convst': mpsse.SPI1,
-                }
-
+        super(AtoiSPI0, self).__init__(
+                interface=ftdi.INTERFACE_A,
+                cs={'_idle': 0xc8,
+                    '_mask': 0xff, #TODO
+                    'flash': 0xc0,
+                    'dac':   0xd8,
+                    'adc':   0xe8,
+                    'convst': 0xf8},
+                mode=1, #flash is mode 0, others are 1
+                freq=int(freq),
+                vid=0x0403,
+                pid=0x6011,
+                pindir=0xc0,
+                pinstate=0xc8,
+                latency=1
+                )
 
     def SetCS(self, name):
         """Setup the chip-select pins for a given 'name'."""
@@ -1566,7 +1562,7 @@ class AtoiSPI0(mpsse.MPSSE):
         else:
             raise Exception, 'Unknown CS name: %s' % name
 
-        self._cs = name
+        #self._cs = name
 
 
 class AtoiSPI1(mpsse.MPSSE):