From d671f7ede46152b7a1782a35eccf17d08a66941a Mon Sep 17 00:00:00 2001 From: Dan White Date: Mon, 30 Apr 2012 14:10:55 -0500 Subject: [PATCH] Update devboard libraries --- python-lib/mpsse-test.py | 398 ++++++++++--------------------------- python-lib/usbio.py | 420 ++++++++++++++++++++++++++++++++------- 2 files changed, 454 insertions(+), 364 deletions(-) diff --git a/python-lib/mpsse-test.py b/python-lib/mpsse-test.py index c1502d9..380de58 100755 --- a/python-lib/mpsse-test.py +++ b/python-lib/mpsse-test.py @@ -6,9 +6,7 @@ from time import sleep from myhdl import intbv from myhdl import bin as b -import mpsse import usbio -from usbio import int2str import IPython import numpy as np @@ -22,326 +20,142 @@ def bytes2str(self, c): 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() diff --git a/python-lib/usbio.py b/python-lib/usbio.py index 19ba75a..367f9c8 100644 --- a/python-lib/usbio.py +++ b/python-lib/usbio.py @@ -1,8 +1,10 @@ #!/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 @@ -60,6 +62,170 @@ def int2str(value, width): 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 @@ -379,7 +545,6 @@ class Mux(object): return out - class AD524x(object): ADDR_BASE = intbv(0b0101100, max=2**7) SEL_POS = 7 @@ -516,6 +681,7 @@ class AD524x(object): self.instruction, pos) + #print ' '.join(map(lambda v: b(v, 8), cmd)) self.lastSel = self.sel if sel: self.lastB = pos @@ -537,13 +703,11 @@ class AD524x(object): 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 @@ -581,6 +745,7 @@ class DAC8568(object): 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())) @@ -593,31 +758,38 @@ class DAC8568(object): 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.""" @@ -646,15 +818,12 @@ class DAC8568(object): 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 @@ -675,21 +844,21 @@ class ADS8201(object): 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 @@ -712,68 +881,175 @@ class ADS8201(object): 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('