from myhdl import intbv
from myhdl import bin as b
-import mpsse
import usbio
-from usbio import int2str
import IPython
import numpy as np
raise TypeError, 'Cannot convert type %s to raw string.' % type(c)
return r
+def mkcfg(n):
+ return ''.join(map(chr, np.random.randint(0, 256, n)))
-class AtoiSPI0(mpsse.MPSSE):
- def __init__(self, freq):
- super(AtoiSPI0, self).__init__()
- self.Open(0x0403, 0x6011, mpsse.SPI1, int(freq),
- interface=mpsse.IFACE_A)
- self.SetCS('flash')
-
- def SetCS(self, name):
- """Setup the chip-select pins for a given 'name'."""
- if name == 'flash':
- self.context.pidle = self.context.pstop = 0xc8
- self.context.pstart = 0xc0
- elif name == 'dac':
- self.context.pidle = self.context.pstop = 0xc8
- self.context.pstart = 0xd8
- elif name == 'adc':
- self.context.pidle = self.context.pstop = 0xc8
- self.context.pstart = 0xe8
- elif name == 'convst':
- 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_A)
-
- def _tostring(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
-
- def write(self, c):
- outdata = self._tostring(c)
-
- n = 0
- i = len(outdata)-1
- s = []
- for d in outdata:
- r = struct.unpack('>B', d)[0]
- s.append(b(r, 8))
- n += r << (i*8)
- i -= 1
- #print ' '.join(s)
-
-
- self.Start()
- self.Write(outdata)
- self.Stop()
-
- def read(self, c, n):
- outdata = self._tostring(c)
- self.Start()
- self.Write(outdata)
- r = self.Read(n)
- self.Stop()
- 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
-
- def _va_getter(self):
- return ((float(self.posA) / 255) * (self.va_max - self.va_min)
- + self.va_min)
-
- def _va_setter(self, value):
- v = max(value, self.va_min)
- v = min(v, self.va_max)
- n = int(round(255 * (v - self.va_min) / (self.va_max - self.va_min)))
- self.posA = n
-
- va = property(_va_getter, _va_setter)
-
- def _vb_getter(self):
- return ((float(self.posB) / 255) * (self.vb_max - self.vb_min)
- + self.vb_min)
-
- def _vb_setter(self, value):
- v = max(value, self.vb_min)
- v = min(v, self.vb_max)
- n = int(round(255 * (v - self.vb_min) / (self.vb_max - self.vb_min)))
- self.posB = n
-
- 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)))
- setattr(DigiReg, dest+'_min', self.va_min)
- setattr(DigiReg, dest+'_max', self.va_max)
- elif source == 'vb':
- setattr(DigiReg, dest,
- property(lambda s: s.vb, lambda s,v: s._vb_setter(v)))
- setattr(DigiReg, dest+'_min', self.vb_min)
- setattr(DigiReg, dest+'_max', self.vb_max)
-
-
-
-
-
-def dacval(value):
- v = intbv(0)[32:]
- v[28:24] = 0x3
- v[24:20] = 0xf
- v += (value << 4)
- return int2str(v, 32)
-
+def cfg2hexstr(x):
+ return ''.join(map(lambda h: '%02x' % ord(h), x))
-spi0 = AtoiSPI0(100e3)
-i2c = AtoiI2C(10e3)
-def w(v):
- spi0.Start()
- spi0.Write(v)
- spi0.Stop()
+##############################################################################
+# Setup FTDI serial ports
+#
+spi0 = usbio.AtoiSPI0(1000e3) #port A
+spi1 = usbio.AtoiSPI1(500e3) #port B
+i2c = usbio.I2C(interface=usbio.ftdi.INTERFACE_C, scl=0, sda=1,
+ vid=0x0403, pid=0x6011, delay=10e-6)
+##############################################################################
+# Analog bias
+# (bias generator also uses DAC_1 and DAC_3,
+# need to make a wrapper class to do ibias.buf = 10 uA)
+#
ibias = usbio.AD524x(i2c, 0)
+ibias.posA = 0
+ibias.posB = 0
-vatoi = DigiReg(i2c, 2, (0.5011, 1.2972), (1.9544, 2.7503))
+
+##############################################################################
+# Power supplies
+#
+vatoi = usbio.DigiReg(i2c, 2, (0.5011, 1.2972), (1.9544, 2.7503))
vatoi.alias('va', 'vdd')
vatoi.alias('vb', 'avdd')
-v430 = DigiReg(i2c, 3, (1.9539, 2.7325), (0.5006, 1.2776))
+v430 = usbio.DigiReg(i2c, 3, (1.9539, 2.7325), (0.5006, 1.2776))
v430.alias('va', 'dvdd')
v430.alias('vb', 'vdd')
-
-#
-# Power supply testing
-#
-if 0:
- v430.posA = 0
- v430.update(True)
- sleep(1)
- v430.posA = 255
- v430.update(True)
- sleep(1)
- v430.posB = 0
- v430.update(True)
- sleep(1)
- v430.posB = 255
- v430.update(True)
-
-
-
-#
-# DAC testing
-#
-if 0:
- #turn on internal reference always
- spi0.SetCS('dac')
-
- int_ref_always_on = intbv(0)[32:]
- int_ref_always_on[27] = 1
- int_ref_always_on[24] = 1
- int_ref_always_on[19] = 1
- int_ref_always_on[13] = 1
- w(int2str(int_ref_always_on, 32))
-
- all_dacs_on = intbv(0)[32:]
- all_dacs_on[26] = 1
- all_dacs_on[8:] = 0xff
- w(int2str(all_dacs_on, 32))
-
- w(dacval(0x8000))
-
-
-
-
-#
-# ADC testing
-#
-if 0:
- adc = usbio.ADS8201(spi0)
- adc.setRegister(adc.TRIGGER_SCR, 0x02)
- rv = adc.getRegister(adc.TRIGGER_SCR)
- print 'receivd:', b(rv, 16)
-
- def sr(n):
- adc.setRegister(adc.CHAN_SEL, n)
- rv = adc.getRegister(adc.CHAN_SEL)
- print 'receivd:', b(rv, 16)
-
-
-
-
-#
-# devboard setup
-#
-# power supply defaults
+# setup power supply defaults
def psdefaults():
- sleep(1)
print "Setting atoi.avdd"
vatoi.avdd = 2.5
- sleep(1)
print "Setting atoi.vdd"
vatoi.vdd = 1.2
- sleep(1)
print "Setting 430.vdd"
v430.vdd = 1.2
- sleep(1)
print "Setting 430.dvdd"
v430.dvdd = 2.5
+psdefaults()
-#psdefaults()
+##############################################################################
+# DAC
+#
+dac = usbio.DAC_atoi(spi0, 'dac')
+dac.swreset()
+
+# reference is tied to ADC also
+dac.reference(dac.REF_FLEXIBLE_ALWAYS_ON)
+
+# CLR is tied high, explicitly ignore anyway
+dac.CCR(dac.IGNORE_CLR)
+
+# power up used channels
+bitfield = 0
+for i in (0, 1, 2, 3, 4):
+ bitfield += (1 << i)
+dac.power(dac.POWER_ON, bitfield)
+
+# power up used channels
+bitfield = 0
+for i in (0, 1, 2, 3, 4):
+ bitfield += (1 << i)
+dac.power(dac.POWER_ON, bitfield)
+
+# others set 1k to gnd
+bitfield = 0
+for i in (5, 6, 7):
+ bitfield += (1 << i)
+dac.power(dac.POWER_OFF_1k, bitfield)
+
+# set initial output voltages
+# before tuning
+dac.vina(1.0)
+dac.vinb(1.0)
+dac.vcmi(1.0)
+dac.vbias_core(0.0)
+dac.vbias_buf(0.0)
+
+
+##############################################################################
+# ADC
+# (TODO)
+#
+adc = usbio.ADS8201(spi0)
+adc.setRegister(adc.TRIGGER_SCR, 0x02)
+rv = adc.getRegister(adc.TRIGGER_SCR)
+print 'receivd:', b(rv, 16)
+
+def sr(n):
+ adc.setRegister(adc.CHAN_SEL, n)
+ rv = adc.getRegister(adc.CHAN_SEL)
+ print 'receivd:', b(rv, 16)
-
-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))
+if 1:
+ 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()
#!/usr/bin/env python
-from array import array
-import struct
-import time
+
+from time import sleep
+
+import ftdi
+import mpsse
from myhdl import intbv
from myhdl import bin as b
return ''.join(map(chr, b))
+class I2C(object):
+ def __init__(self, interface=ftdi.INTERFACE_A, scl=0, sda=1,
+ vid=0x0403, pid=0x6011, delay=0.001, timeout=100):
+ """Bitbanged I2C for use on FT4232H ports C and D.
+
+ interface = [0,1,2,3]
+ scl/sda = port pin numbers
+ """
+ self.interface = interface
+ self.scl = scl
+ self.sda = sda
+ self.vid = vid
+ self.pid = pid
+ self.DELAY = delay
+ self.TIMEOUT = timeout
+
+ self.context = ftdi.new()
+ ftdi.set_interface(self.context, interface)
+ ftdi.write_data_set_chunksize(self.context, 1)
+ ftdi.read_data_set_chunksize(self.context, 1)
+
+ self.io = intbv(0xff)[8:]
+ self.io[scl] = 1
+ self.io[sda] = 1
+ self.port = intbv(0)[8:]
+
+ ftdi.set_bitmode(self.context, int(self.io), ftdi.BITMODE_BITBANG)
+
+ e = ftdi.usb_open(self.context, vid, pid)
+ if e != 0:
+ raise Exception, 'Could not open usb device, error: %i' % e
+
+ ftdi.set_baudrate(self.context, 1000)
+ ftdi.usb_purge_buffers(self.context)
+ self.started = False
+
+ def _clear_scl(self):
+ self.io[self.scl] = 1
+ ftdi.set_bitmode(self.context, int(self.io), ftdi.BITMODE_BITBANG)
+ self.port[self.scl] = 0
+ ftdi.write_data(self.context, chr(self.port), 1)
+
+ def _read_scl(self):
+ if 1:
+ self.io[self.scl] = 0
+ ftdi.set_bitmode(self.context, int(self.io), ftdi.BITMODE_BITBANG)
+ port = ftdi.read_pins(self.context)
+ scl = intbv(ord(port[1]))[self.scl]
+ if scl:
+ return 1
+ else:
+ return 0
+
+ def _clear_sda(self):
+ self.io[self.sda] = 1
+ ftdi.set_bitmode(self.context, int(self.io), ftdi.BITMODE_BITBANG)
+ self.port[self.sda] = 0
+ ftdi.write_data(self.context, chr(self.port), 1)
+
+ def _read_sda(self):
+ if 1:
+ self.io[self.sda] = 0
+ ftdi.set_bitmode(self.context, int(self.io), ftdi.BITMODE_BITBANG)
+ port = ftdi.read_pins(self.context)
+ sda = intbv(ord(port[1]))[self.sda]
+ if sda:
+ return 1
+ else:
+ return 0
+
+ def _clock_stretch(self):
+ i = 0
+ while (self._read_scl() == 0):
+ sleep(self.DELAY)
+ i += 1
+ if i > self.TIMEOUT:
+ raise Exception, "Timeout waiting for SCL to go high."
+
+ def _start(self):
+ if self.started:
+ self._read_sda()
+ sleep(self.DELAY)
+ self._clock_stretch()
+ sleep(self.DELAY)
+ if self._read_sda() == 0:
+ raise Exception, "Lost bus arbitration."
+ self._clear_sda()
+ sleep(self.DELAY)
+ self._clear_scl()
+ self.started = True
+
+ def _stop(self):
+ self._clear_sda()
+ sleep(self.DELAY)
+
+ self._clock_stretch()
+
+ sleep(self.DELAY)
+ if self._read_sda() == 0:
+ raise Exception, "Lost bus arbitration."
+ sleep(self.DELAY)
+ self.started = False
+
+ def _write_bit(self, bit):
+ if bit:
+ self._read_sda()
+ else:
+ self._clear_sda()
+ sleep(self.DELAY)
+ self._clock_stretch()
+ if bit and (self._read_sda() == 0):
+ raise Exception, "Lost bus arbitration."
+ sleep(self.DELAY)
+ self._clear_scl()
+
+ def _read_bit(self):
+ self._read_sda()
+ sleep(self.DELAY)
+ self._clock_stretch()
+ bit = self._read_sda()
+ sleep(self.DELAY)
+ self._clear_scl()
+ return bit
+
+ def _write_byte(self, byte, start, stop):
+ byt = intbv(byte, max=256)
+ if start:
+ self._start()
+ for i in range(7, -1, -1):
+ bit = byt[i]
+ self._write_bit(bit)
+ nack = self._read_bit()
+ if stop:
+ self._stop()
+ return nack
+
+ def _read_byte(self, nack, stop):
+ byte = 0
+ for i in range(8):
+ byte = (byte << 1) | self._read_bit()
+ self._write_bit(nack)
+ if stop:
+ self._stop()
+ return byte
+
+ def write(self, data, stop=True):
+ """Send i2c command data to slave,
+ data is a list-like of integers constrained to uint8 range."""
+ n = len(data)
+ self._write_byte(data[0], start=True, stop=False)
+ for i in range(1, n-1):
+ self._write_byte(data[i], start=False, stop=False)
+ self._write_byte(data[n-1], start=False, stop=stop)
+
+ def read(self, n):
+ """Read n bytes from a slave. Usually preceded by write(data, stop=False).
+ """
+ data = []
+ for i in range(n-1):
+ data.append(self._read_byte(0, stop=False))
+ data.append(self._read_byte(0, stop=True))
+ return data
+
+
class NCO(object):
RST_POS = 14
FCW_WIDTH = 14
return out
-
class AD524x(object):
ADDR_BASE = intbv(0b0101100, max=2**7)
SEL_POS = 7
self.instruction,
pos)
+ #print ' '.join(map(lambda v: b(v, 8), cmd))
self.lastSel = self.sel
if sel:
self.lastB = pos
self.send(sel)
cmd = ((self.addr << 1) + self.READ, )
- val = self.bus.read(cmd, 1)
+ self.bus.write([cmd], stop=False)
+ val = self.bus.read(1)
return val[0]
-
-
-
class DAC8568(object):
CTL_WIDTH = 32
DAC_WIDTH = 16
self.bus = spibus
self.cs = 'dac'
self._word = intbv(0)[self.CTL_WIDTH:]
+ self._chpos = [0 for i in range(8)]
def __str__(self):
return ''.join(map(chr, self.bytes()))
self._clear()
self._control(0x5)
self._feature(mode)
+ self.send()
def LDAC(self, bitfield):
self._clear()
self._control(0x6)
self._word[8:0] = intbv(bitfield, max=2**8)
+ self.send()
def swreset(self):
self._clear()
self._control(0x7)
+ self.send()
- def set(self, addr, value, mode):
+ def set(self, addr, value, mode=INPUT_UPDATE_SINGLE):
self._clear()
self._control(mode)
self._address(addr)
self._data(value)
+ self._chpos[addr] = value
+ self.send()
def power(self, mode, bitfield):
self._clear()
self._control(0x4)
self._word[10:8] = intbv(mode, max=2**2)
self._word[8:0] = intbv(bitfield, max=2**8)
+ self.send()
def reference(self, mode):
self._clear()
self._word = intbv(mode, max=2**32)
+ self.send()
def bytes(self):
"""Return the control data as a byte sequence in MSB..LSB order."""
self._word[24:20] = intbv(value, max=2**4)
def _data(self, value):
- self._word[20:4] = intbv(value, max=2**16)
+ self._word[20:20-self.DAC_WIDTH] = intbv(value, max=2**self.DAC_WIDTH)
def _feature(self, value):
self._word[4:0] = intbv(value, max=2**4)
-
-
-
class ADS8201(object):
CH01_CCR = 0
CH23_CCR = 1
w = intbv(0x8000)[16:]
w[14:10] = intbv(address, max=2**4)
w[8:] = intbv(value, max=2**8)
- print 'sending:', b(w, 16)
+ #print 'sending:', b(w, 16)
self.bus.SetCS('adc')
self.bus.Start()
self.bus.Write(int2str(w, 16))
- time.sleep(1e-3)
+ sleep(1e-3)
self.bus.Stop()
def getRegister(self, address):
w = intbv(0x4000)[16:]
w[14:10] = intbv(address, max=2**4)
- print 'sending:', b(w, 16)
+ #print 'sending:', b(w, 16)
self.bus.SetCS('adc')
self.bus.Start()
rval = self.bus.Exchange(int2str(w, 16))
- time.sleep(1e-3)
+ sleep(1e-3)
self.bus.Stop()
i = 8 * (len(rval)-1)
r = 0
return r
+class AtoiSPI0(mpsse.MPSSE):
+ def __init__(self, freq):
+ super(AtoiSPI0, self).__init__()
+ self.Open(0x0403, 0x6011, mpsse.SPI1, int(freq),
+ interface=mpsse.IFACE_A)
+ self.SetCS('flash')
+
+ def SetCS(self, name):
+ """Setup the chip-select pins for a given 'name'."""
+ if name == 'flash':
+ self.context.pidle = self.context.pstop = 0xc8
+ self.context.pstart = 0xc0
+ elif name == 'dac':
+ self.context.pidle = self.context.pstop = 0xc8
+ self.context.pstart = 0xd8
+ elif name == 'adc':
+ self.context.pidle = self.context.pstop = 0xc8
+ self.context.pstart = 0xe8
+ elif name == 'convst':
+ 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 I2C(object):
- def write(self, data):
- """Send i2c command data to slave."""
- raise NotImplementedError
- def read(self, cmd, n):
- """Send i2c command cmd and read n additional bytes from slave."""
- raise NotImplementedError
+#
+# Atoi UART / rs232 is on IFACE_D
+#
-if __name__ == '__main__':
+class DigiReg(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
+
+ def _va_getter(self):
+ return ((float(self.posA) / 255) * (self.va_max - self.va_min)
+ + self.va_min)
+
+ def _va_setter(self, value):
+ v = max(value, self.va_min)
+ v = min(v, self.va_max)
+ n = int(round(255 * (v - self.va_min) / (self.va_max - self.va_min)))
+ self.posA = n
+
+ va = property(_va_getter, _va_setter)
+
+ def _vb_getter(self):
+ return ((float(self.posB) / 255) * (self.vb_max - self.vb_min)
+ + self.vb_min)
+
+ def _vb_setter(self, value):
+ v = max(value, self.vb_min)
+ v = min(v, self.vb_max)
+ n = int(round(255 * (v - self.vb_min) / (self.vb_max - self.vb_min)))
+ self.posB = n
+
+ 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)))
+ setattr(DigiReg, dest+'_min', self.va_min)
+ setattr(DigiReg, dest+'_max', self.va_max)
+ elif source == 'vb':
+ setattr(DigiReg, dest,
+ property(lambda s: s.vb, lambda s,v: s._vb_setter(v)))
+ setattr(DigiReg, dest+'_min', self.vb_min)
+ setattr(DigiReg, dest+'_max', self.vb_max)
+
+
+class DAC_atoi(DAC8568):
+ """Specific configuration and calibration for devboard DAC."""
+ VREF = 2.5
+ GAIN = 2.0 #part options C/D
+ #POR_VALUE = 0 #part C
+ POR_VALUE = DAC8568.DAC_WIDTH / 2 #part D
+
+ #zero-code output voltages
+ VOS = ( 0.0,
+ 0.0,
+ 0.0,
+ 5e-3,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0)
- if 0:
- o = OTA()
- o.tune = 0x3ff
- print o.tune
- print o.word
- o.word[15] = 1
- print o.word
- print o.cint
- o.cint = 0
- print o.cint
- o.cint = 1
- print o.cint
+ def __init__(self, spibus, cs='dac'):
+ super(DAC_atoi, self).__init__(spibus, cs)
+ self._chpos = [self.POR_VALUE for i in range(8)]
+
+ def _pos2v(self, pos):
+ return (pos / float(2**self.DAC_WIDTH)) * self.VREF * self.GAIN
+
+ def setv(self, channel, voltage, mode=DAC8568.INPUT_UPDATE_SINGLE):
+ code = voltage * float(2**self.DAC_WIDTH) / self.VREF / self.GAIN
+ code = int(round(code))
+ code = min(2**self.DAC_WIDTH - 1, code)
+ code = max(0, code)
+ self.set(channel, code, mode)
+
+ def vina(self, v, mode=DAC8568.INPUT_UPDATE_SINGLE):
+ self.setv(0, v, mode)
+
+ def vinb(self, v, mode=DAC8568.INPUT_UPDATE_SINGLE):
+ self.setv(2, v, mode)
+
+ def vcmi(self, v, mode=DAC8568.INPUT_UPDATE_SINGLE):
+ self.setv(4, v, mode)
+
+ def vbias_core(self, v, mode=DAC8568.INPUT_UPDATE_SINGLE):
+ self.setv(1, v, mode)
+
+ def vbias_buf(self, v, mode=DAC8568.INPUT_UPDATE_SINGLE):
+ self.setv(3, v, mode)
- h = Harmonic()
- h.otaA.offset = -1
- print 'offset:', h.otaA.offset
- o = h.otaA.offset
- def arr(a):
- return array('B', a)
- if 1:
- sc0 = SpiController()
- sc0.configure(0x0403, 0x6011, 0, loopback=True)
-
- sc1 = SpiController()
- sc1.configure(0x0403, 0x6011, 1, loopback=True)
-
- p0 = sc0.get_port(0)
- p1 = sc1.get_port(0)
-
- def rw(p, a, readlen=None):
- if readlen is None:
- readlen = len(a)
- cmd = array('B')
- cmd.fromstring(struct.pack('<BH', Ftdi.RW_BYTES_NVE_PVE_MSB, len(a)-1))
- cmd.extend(a)
- cmd.extend(p._controller._immediate)
- p._controller._ftdi.write_data(cmd)
- return p._controller._ftdi.read_data_bytes(readlen, 4)
-
-
- print 'Loopback SPI interfaces 0, 1'
- a = [0,1,2,3,4,5,6,7,8,9]
- print a
- print rw(p0, arr(a))
-
- a = [i for i in range(256)]
- print a
- print rw(p1, arr(a))