import ftdi
import mpsse
+from math import log
from myhdl import intbv
from myhdl import bin as b
# 7..0 - offset
+def log2(x):
+ return log(x) / log(2)
+
def truth(v):
if isinstance(v, (int, intbv)):
# NB: ~True == -2
self._word[4:0] = intbv(value, max=2**4)
+
+
class ADS8201(object):
+ """Configures and operates an ADS8201 over the given SPI bus."""
+ # register addresses
CH01_CCR = 0
CH23_CCR = 1
CH45_CCR = 2
def __init__(self, spibus):
self.bus = spibus
+ #channel registers are paired
+ #MUST set these values as _ch[n][a:b]
+ #this assigns values to bit positions within the created intbv,
+ # this keeps ch0/1, ch2/3, etc the same object
+ self._ch = []
+ for i in (0, 2, 4, 6):
+ self._ch.append(intbv(0)[8:])
+ self._ch.append(self._ch[-1])
+
+ self._ADC_SCR = intbv(0)[8:]
+ self._INT_SCR = intbv(0)[8:]
+ self._TRIGGER_SCR = intbv(0)[8:]
+
def setRegister(self, address, value):
w = intbv(0x8000)[16:]
w[14:10] = intbv(address, max=2**4)
w[8:] = intbv(value, max=2**8)
- #print 'sending:', b(w, 16)
self.bus.SetCS('adc')
self.bus.Start()
self.bus.Write(int2str(w, 16))
rval = self.bus.Exchange(int2str(w, 16))
sleep(1e-3)
self.bus.Stop()
- i = 8 * (len(rval)-1)
- r = 0
- for c in rval:
- r += ord(c) << i
- i -= 8
- return r
+ #i = 8 * (len(rval)-1)
+ #r = 0
+ #for c in rval:
+ #r += ord(c) << i
+ #i -= 8
+ #return r
+ # first byte is xxx00000, second is data
+ return ord(rval[1])
+
+ #
+ # ADC_SCR configuration
+ #
+ def channelGain(self, channel, gain):
+ """Set channel PGA gain to one of 1, 2, 4, or 8."""
+ g = int(gain)
+ if g in (1, 2, 4, 8):
+ g = int(log2(g))
+ else:
+ raise Exception, 'Gain is only (1, 2, 4, 8), you tried %i' % g
+
+ if (channel % 2) == 0:
+ self._ch[channel][2:0] = g
+ else:
+ self._ch[channel][6:4] = g
+
+ self.setRegister(int(channel/2), self._ch[channel])
+
+ #channel CCR mode config
+ SE = 0b00
+ DIFF_EVEN = 0b01
+ DIFF_ODD = 0b11
+ def channelMode(self, channel, mode):
+ """Setup channel (pair) to SE or differential even/odd modes."""
+ if mode not in (0, 1, 3):
+ raise Exception, 'Invalid mode: %i' % mode
+
+ if ((channel % 2) == 1):
+ raise Exception, 'Cannot set mode on odd channel: %i' % channel
+
+ self._ch[channel][4:2] = mode
+ self.setRegister(int(channel/2), self._ch[channel])
+
+ #
+ # Channel Select CCR config
+ #
+ def mux(self, channel):
+ """Select Mux input/start channel."""
+ self.setRegister(self.CHAN_SEL, channel)
+
+ #
+ # System Configuration Register config
+ #
+ def average(self, results, accurate=True):
+ if results not in (0, 1, 4, 8, 16):
+ raise Exception, 'Invalid average number: %i, must be 0, 4, 8, 16' % results
+ v = 0
+ if accurate:
+ v += 0b100
+ if results > 1:
+ v += int(log2(results / 2))
+ print v
+ self._ADC_SCR[8:5] = v
+ print hex(self._ADC_SCR)
+ self.setRegister(self.ADC_SCR, self._ADC_SCR)
+
+ def busy_int(self, level_edge, act_low_high, busy_int):
+ """Setup busy/interrupt pin and mode. Level/edge triggered, active
+ low/high, and busy/interrupt mode."""
+ self._ADC_SCR[4] = level_edge
+ self._ADC_SCR[3] = act_low_high
+ self._ADC_SCR[2] = busy_int
+ self.setRegister(self.ADC_SCR, self._ADC_SCR)
+
+ def fifo(self, enable=0):
+ """Enable FIFO buffer=1, disable=0."""
+ self._ADC_SCR[1] = enable
+ self.setRegister(self.ADC_SCR, self._ADC_SCR)
+
+ def convst_spi(self, spi_trigger):
+ """0 - conversion triggered by CONVST pin
+ 1 - conversion triggered by sham adc read()"""
+ self._ADC_SCR[0] = spi_trigger
+ self.setRegister(self.ADC_SCR, self._ADC_SCR)
+
+ #
+ # interrupt SCR (INT_SCR) config
+ #
+ # NB: from datasheet p.15 "care must be taken to ensure that the ADC is in
+ # idle mode before writing to the Interrupt SCR."
+ def powerdown(self, pd):
+ """Set 1 to shutdown chip."""
+ #ensure idle mode
+ self.triggerMode(self.MODE_IDLE)
+ self._INT_SCR[7] = pd
+ self.setRegister(self.INT_SCR, self._INT_SCR)
+
+ # TODO: set/get interrupt sources
+
+ #
+ # TRIGGER_SCR
+ # adc operating mode (state machine)
+ #
+ MODE_IDLE = 0
+ MODE_MANUAL_MANUAL = 2
+ MODE_MANUAL_DELAY = 3
+ MODE_AUTO_MANUAL = 4
+ MODE_AUTO_AUTO_SINGLE = 5
+ MODE_AUTO_AUTO_CONTINUOUS = 6
+ def triggerMode(self, mode):
+ """Set trigger operating mode. NB: 0 (idle) is required for setting
+ most config registers."""
+ if mode in (1, 7):
+ raise Exception, 'Invalid trigger mode: %i' % mode
+ self._TRIGGER_SCR = intbv(mode, max=2**8)
+ self.setRegister(self.TRIGGER_SCR, self._TRIGGER_SCR)
+
+ #
+ # Status SCR
+ #
+ def status(self):
+ """Get ADC status bitvector."""
+ return self.getRegister(self.STATUS_SCR)
+
+ #
+ # Reset SCR
+ #
+ def reset(self):
+ """Send a software reset."""
+ self.setRegister(self.RESET_SCR, 0xaa)
+
+ #
+ # Conversion Delay SCR
+ #
+ def conv_delay(self, delay):
+ """Set the conversion delay."""
+ d = intbv(delay, max=2**8)
+ self.setRegister(self.DELAY_SCR, d)
def read(self):
+ """Read ODR value, meaning of result depends on Mode and FIFO
+ settings. Last 4 LSB are averaging bits."""
+ # TODO: also optionally read 4 TAG bits
w = intbv(0x0000)[16:]
self.bus.SetCS('adc')
self.bus.Start()