Testing chain0 conf and mux SPI shift registers
authorDan White <dan@whiteaudio.com>
Wed, 25 Apr 2012 19:48:19 +0000 (14:48 -0500)
committerDan White <dan@whiteaudio.com>
Wed, 25 Apr 2012 19:48:19 +0000 (14:48 -0500)
python-lib/mpsse-test.py [changed mode: 0644->0755]
python-lib/usbio.py

old mode 100644 (file)
new mode 100755 (executable)
index f62ed24..c1502d9
@@ -10,6 +10,17 @@ import mpsse
 import usbio
 from usbio import int2str
 
+import IPython
+import numpy as np
+
+def bytes2str(self, c):
+    r = c
+    if not isinstance(c, str):
+        if isinstance(c, (tuple, list)):
+            r = r''.join(map(chr, c))
+        else:
+            raise TypeError, 'Cannot convert type %s to raw string.' % type(c)
+    return r
 
 
 class AtoiSPI0(mpsse.MPSSE):
@@ -22,26 +33,53 @@ class AtoiSPI0(mpsse.MPSSE):
     def SetCS(self, name):
         """Setup the chip-select pins for a given 'name'."""
         if name == 'flash':
-            self.context.pidle = self.context.pstop = 0x08
-            self.context.pstart = 0x00
+            self.context.pidle = self.context.pstop = 0xc8
+            self.context.pstart = 0xc0
         elif name == 'dac':
-            self.context.pidle = self.context.pstop = 0x08
-            self.context.pstart = 0x18
+            self.context.pidle = self.context.pstop = 0xc8
+            self.context.pstart = 0xd8
         elif name == 'adc':
-            self.context.pidle = self.context.pstop = 0x08
-            self.context.pstart = 0x28
+            self.context.pidle = self.context.pstop = 0xc8
+            self.context.pstart = 0xe8
         elif name == 'convst':
-            self.context.pidle = self.context.pstop = 0x08
-            self.context.pstart = 0x38
+            self.context.pidle = self.context.pstop = 0xc8
+            self.context.pstart = 0xf8
         else:
             raise Exception, 'Unknown CS name: %s' % name
 
 
+
+class AtoiSPI1(mpsse.MPSSE):
+    def __init__(self, freq):
+        super(AtoiSPI1, self).__init__()
+        self.Open(0x0403, 0x6011, mpsse.SPI0, int(freq),
+                interface=mpsse.IFACE_B)
+        self.SetCS('chain0_conf')
+
+    def SetCS(self, name):
+        """Setup the chip-select pins for a given 'name'."""
+        if name == 'chain0_conf':
+            self.context.pidle = self.context.pstop = 0xf8
+            self.context.pstart = 0xf0
+        elif name == 'chain0_mux':
+            self.context.pidle = self.context.pstop = 0xf8
+            self.context.pstart = 0xe8
+        elif name == 'chain1_conf':
+            self.context.pidle = self.context.pstop = 0xf8
+            self.context.pstart = 0xd0
+        elif name == 'chain1_mux':
+            self.context.pidle = self.context.pstop = 0xf8
+            self.context.pstart = 0xb8
+        else:
+            raise Exception, 'Unknown CS name: %s' % name
+
+
+
 class AtoiI2C(mpsse.MPSSE):
     def __init__(self, freq):
         super(AtoiI2C, self).__init__()
         self.Open(0x0403, 0x6011, mpsse.I2C, int(freq),
-                interface=mpsse.IFACE_B)
+                interface=mpsse.IFACE_A)
         
     def _tostring(self, c):
         r = c
@@ -79,14 +117,31 @@ class AtoiI2C(mpsse.MPSSE):
         return r
 
 
+#
+# Atoi UART / rs232 is on IFACE_D
+#
+
+
+
 
 class DigiReg(usbio.AD524x):
+    """
+    Wrapper for digital potentiometers which control power supply voltages.
+    Allows setting desired voltage instead of pot position.
+
+    These power supplies have a regulator output of:
+        Vout = Vref * (1 + (Ra + Rpot)/Rb)
+    It is sufficient then to specify the end voltages at pos=0 and pos=255 as
+    the output is linear with pot position.
+    """
     def __init__(self, i2cbus, addr, va=[0.0,1.0], vb=[0.0, 1.0]):
         super(DigiReg, self).__init__(i2cbus, addr)
+        # calibration voltages, measure actual hardware
         self.va_min = min(va)
         self.va_max = max(va)
         self.vb_min = min(vb)
         self.vb_max = max(vb)
+        # POR pot position
         self.posA = 128
         self.posB = 128
 
@@ -115,6 +170,14 @@ class DigiReg(usbio.AD524x):
     vb = property(_vb_getter, _vb_setter)
 
     def alias(self, source, dest):
+        """
+        Make a property named by string dest which is an alias for actual
+        property string source.  The valid sources are 'va' and 'vb'.
+
+        > self.alias('va', 'vfoo')
+        > self.vfoo = 1.2
+        > self.va = 1.2 #same effect as above
+        """
         if source == 'va':
             setattr(DigiReg, dest,
                     property(lambda s: s.va, lambda s,v: s._va_setter(v)))
@@ -138,17 +201,15 @@ def dacval(value):
     return int2str(v, 32)
 
 
-def w(v):
-    spi.Start()
-    spi.Write(v)
-    spi.Stop()
-
-spi = AtoiSPI0(100e3)
-#spi.SetLoopback(0)
-
 
+spi0 = AtoiSPI0(100e3)
 i2c = AtoiI2C(10e3)
 
+def w(v):
+    spi0.Start()
+    spi0.Write(v)
+    spi0.Stop()
+
 
 ibias = usbio.AD524x(i2c, 0)
 
@@ -184,7 +245,7 @@ if 0:
 #
 if 0:
     #turn on internal reference always
-    spi.SetCS('dac')
+    spi0.SetCS('dac')
 
     int_ref_always_on = intbv(0)[32:]
     int_ref_always_on[27] = 1
@@ -207,7 +268,7 @@ if 0:
 # ADC testing
 #
 if 0:
-    adc = usbio.ADS8201(spi)
+    adc = usbio.ADS8201(spi0)
     adc.setRegister(adc.TRIGGER_SCR, 0x02)
     rv  = adc.getRegister(adc.TRIGGER_SCR)
     print 'receivd:', b(rv, 16)
@@ -239,6 +300,49 @@ def psdefaults():
     v430.dvdd = 2.5
 
 
-psdefaults()
-psdefaults()
+#psdefaults()
+
+
+
+
+def mkcfg(n):
+    return ''.join(map(chr, np.random.randint(0, 256, n)))
+
+def cfg2hexstr(x):
+    return ''.join(map(lambda h: '%02x' % ord(h), x))
+
+
+#
+# chain0 config registers
+#
+spi1 = AtoiSPI1(100e3)
+chain = usbio.Chain(spi1, 'chain0_conf', length=48)
+mux = usbio.Mux(spi1, 'chain0_mux')
+
+#calibration mode for all channels
+for h in chain.h:
+    h.cal = 1
+    for ota in h.ota:
+        ota.se = 0
+        ota.cint = 1
+        ota.zero = 0
+        ota.fast = 1
+        ota.gain = 8
+        ota.offset = 0
+
+cfg = ''.join(map(chr, chain.bytes))
+
+spi1.SetCS('chain0_conf')
+out = spi1.Exchange(cfg)
+print
+print ''.join(map(lambda x: '%02x' % ord(x), cfg))
+print
+print ''.join(map(lambda x: '%02x' % ord(x), out))
+
+out = spi1.Exchange(cfg)
+print
+print ''.join(map(lambda x: '%02x' % ord(x), out))
+
+IPython.embed()
+
 
index b7eeb402997f53521fbf8e14c5080f2874ab0ba8..b1e425d9fd666784880b430ad156d7160329fb5d 100644 (file)
@@ -194,14 +194,14 @@ class OTA(object):
         v = intbv(v, max=2**self.OFFSET_WIDTH).signed()
         ret = intbv(v,
                 min=-2**(self.OFFSET_WIDTH-1),
-                max=2**((self.OFFSET_WIDTH-1)-1))
+                max=2**((self.OFFSET_WIDTH-1)))
         return ret
 
     @offset.setter
     def offset(self, value):
         v = intbv(value,
                 min=-2**(self.OFFSET_WIDTH-1),
-                max=2**((self.OFFSET_WIDTH-1)-1))
+                max=2**((self.OFFSET_WIDTH-1)))
         #convert to offset binary
         b = self.OFFSET_SHIFT
         a = b + self.OFFSET_WIDTH
@@ -275,11 +275,16 @@ class Harmonic(object):
 
 
 class Chain(object):
-    def __init__(self, length=48):
+    def __init__(self, spibus, csname, length=48):
+        self.bus = spibus
+        self.csname = csname
         self.length = length
         h = [Harmonic() for i in range(self.length)]
         self.h = tuple(h)
 
+    def __str__(self):
+        return ''.join(map(chr, self.bytes))
+
     @property
     def bytes(self):
         """Return the control data as a byte sequence in MSB..LSB order."""
@@ -289,6 +294,14 @@ class Chain(object):
             data.extend(h.bytes)
         return tuple(data)
 
+    def write(self):
+        self.bus.SetCS(self.csname)
+        self.bus.Start()
+        s = str(self)
+        out = self.bus.Exchange(s)
+        self.bus.Stop()
+        return out
+
 
 class Mux(object):
     MUX_WIDTH = 48
@@ -305,7 +318,9 @@ class Mux(object):
     CAL_CMP = 2
     CAL_BUF = 3
 
-    def __init__(self):
+    def __init__(self, spibus, csname):
+        self.bus = spibus
+        self.csname = csname
         self._word = intbv(0)[self.MUX_WIDTH:]
         self._selA = intbv(48, max=2**self.SEL_WIDTH) #select CMI
         self._selB = intbv(48, max=2**self.SEL_WIDTH) #select CMI
@@ -315,6 +330,9 @@ class Mux(object):
         self.otaB.mode = self.MUX_BUF
         self.ota = (self.otaA, self.otaB)
 
+    def __str__(self):
+        return ''.join(map(chr, self.bytes))
+
     @property
     def selA(self):
         return self._selA
@@ -352,6 +370,15 @@ class Mux(object):
         b = [w[i:i-8] for i in range(self.MUX_WIDTH, 0, -8)]
         return tuple(b)
 
+    def write(self):
+        self.bus.SetCS(self.csname)
+        self.bus.Start()
+        s = str(self)
+        out = self.bus.Exchange(s)
+        self.bus.Stop()
+        return out
+
+
 
 class AD524x(object):
     ADDR_BASE = intbv(0b0101100, max=2**7)