forked from M-Labs/artiq
1
0
Fork 0

spi/ad5360: refactor, small fixes

This commit is contained in:
Robert Jördens 2016-03-04 18:12:30 +01:00
parent 200cddc346
commit 4ae3ca5f23
3 changed files with 38 additions and 27 deletions

View File

@ -1,7 +1,8 @@
from artiq.language.core import kernel, portable, delay from artiq.language.core import kernel, portable, delay_mu
from artiq.language.units import ns
from artiq.coredevice import spi from artiq.coredevice import spi
# Designed from the data sheets and somewhat after the linux kernel
# iio driver.
_AD5360_SPI_CONFIG = (0*spi.SPI_OFFLINE | 0*spi.SPI_CS_POLARITY | _AD5360_SPI_CONFIG = (0*spi.SPI_OFFLINE | 0*spi.SPI_CS_POLARITY |
0*spi.SPI_CLK_POLARITY | 1*spi.SPI_CLK_PHASE | 0*spi.SPI_CLK_POLARITY | 1*spi.SPI_CLK_PHASE |
@ -21,7 +22,7 @@ _AD5360_SPECIAL_NOP = 0 << 16
_AD5360_SPECIAL_CONTROL = 1 << 16 _AD5360_SPECIAL_CONTROL = 1 << 16
_AD5360_SPECIAL_OFS0 = 2 << 16 _AD5360_SPECIAL_OFS0 = 2 << 16
_AD5360_SPECIAL_OFS1 = 3 << 16 _AD5360_SPECIAL_OFS1 = 3 << 16
_AD5360_SPECIAL_READ = 3 << 16 _AD5360_SPECIAL_READ = 5 << 16
@portable @portable
@ -43,11 +44,12 @@ class AD5360:
multi-channel Digital to Analog Converters multi-channel Digital to Analog Converters
""" """
def __init__(self, dmgr, spi_bus, ldac=None, chip_select=0): def __init__(self, dmgr, spi_device, ldac_device=None,
chip_select=1):
self.core = dmgr.get("core") self.core = dmgr.get("core")
self.bus = dmgr.get(spi_bus) self.bus = dmgr.get(spi_device)
if ldac is not None: if ldac_device is not None:
ldac = dmgr.get(ldac) ldac = dmgr.get(ldac_device)
self.ldac = ldac self.ldac = ldac
self.chip_select = chip_select self.chip_select = chip_select
@ -58,32 +60,35 @@ class AD5360:
self.bus.set_config_mu(_AD5360_SPI_CONFIG, write_div, read_div) self.bus.set_config_mu(_AD5360_SPI_CONFIG, write_div, read_div)
self.bus.set_xfer(self.chip_select, 24, 0) self.bus.set_xfer(self.chip_select, 24, 0)
@kernel
def write(self, data):
self.bus.write(data << 8)
delay_mu(self.bus.ref_period_mu) # get to 20ns min cs high
@kernel @kernel
def write_offsets(self, value=0x1fff): def write_offsets(self, value=0x1fff):
value &= 0x3fff value &= 0x3fff
self.bus.write((_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_OFS0 | value self.write(_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_OFS0 | value)
) << 8) self.write(_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_OFS1 | value)
self.bus.write((_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_OFS1 | value
) << 8)
@kernel @kernel
def write_channel(self, channel=0, value=0, op=_AD5360_CMD_DATA): def write_channel(self, channel=0, value=0, op=_AD5360_CMD_DATA):
channel &= 0x3f channel &= 0x3f
value &= 0xffff value &= 0xffff
self.bus.write((op | _AD5360_WRITE_CHANNEL(channel) | value) << 8) self.write(op | _AD5360_WRITE_CHANNEL(channel) | value)
@kernel @kernel
def write_channels(self, values, first=0, op=_AD5360_CMD_DATA): def write_channels(self, values, op=_AD5360_CMD_DATA):
for i in range(len(values)): for i in range(len(values)):
self.write_channel(i + first, values[i], op) self.write_channel(i, values[i], op)
@kernel @kernel
def read_channel_sync(self, channel=0, op=_AD5360_READ_X1A): def read_channel_sync(self, channel=0, op=_AD5360_READ_X1A):
channel &= 0x3f channel &= 0x3f
self.bus.write((_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_READ | op | self.write(_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_READ | op |
_AD5360_READ_CHANNEL(channel)) << 8) _AD5360_READ_CHANNEL(channel))
self.bus.set_xfer(self.chip_select, 0, 24) self.bus.set_xfer(self.chip_select, 0, 24)
self.bus.write((_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_NOP) << 8) self.write(_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_NOP)
self.bus.read_async() self.bus.read_async()
self.bus.set_xfer(self.chip_select, 24, 0) self.bus.set_xfer(self.chip_select, 24, 0)
return self.bus.input_async() & 0xffff return self.bus.input_async() & 0xffff
@ -91,5 +96,5 @@ class AD5360:
@kernel @kernel
def load(self): def load(self):
self.ldac.off() self.ldac.off()
delay(24*ns) delay_mu(3*self.bus.ref_period_mu)
self.ldac.on() self.ldac.on()

View File

@ -38,17 +38,16 @@ class SPIMaster:
* If desired, :meth:`write` ``data`` queuing the next * If desired, :meth:`write` ``data`` queuing the next
(possibly chained) transfer. (possibly chained) transfer.
:param ref_period: clock period of the SPI core.
:param channel: RTIO channel number of the SPI bus to control. :param channel: RTIO channel number of the SPI bus to control.
""" """
def __init__(self, dmgr, ref_period, channel): def __init__(self, dmgr, channel):
self.core = dmgr.get("core") self.core = dmgr.get("core")
self.ref_period = ref_period self.ref_period_mu = seconds_to_mu(self.core.coarse_ref_period,
self.ref_period_mu = int(seconds_to_mu(ref_period, self.core)) self.core)
self.channel = channel self.channel = channel
self.write_period_mu = int(0) self.write_period_mu = int(0, 64)
self.read_period_mu = int(0) self.read_period_mu = int(0, 64)
self.xfer_period_mu = int(0) self.xfer_period_mu = int(0, 64)
# A full transfer takes write_period_mu + xfer_period_mu. # A full transfer takes write_period_mu + xfer_period_mu.
# Chained transfers can happen every xfer_period_mu. # Chained transfers can happen every xfer_period_mu.
# The second transfer of a chain can be written 2*ref_period_mu # The second transfer of a chain can be written 2*ref_period_mu

View File

@ -81,7 +81,7 @@
"arguments": {"channel": 19} "arguments": {"channel": 19}
}, },
"ams101_ldac": { "ttl_ams101_ldac": {
"type": "local", "type": "local",
"module": "artiq.coredevice.ttl", "module": "artiq.coredevice.ttl",
"class": "TTLOut", "class": "TTLOut",
@ -94,7 +94,7 @@
"arguments": {"channel": 21} "arguments": {"channel": 21}
}, },
"ams101_spi": { "spi_ams101": {
"type": "local", "type": "local",
"module": "artiq.coredevice.spi", "module": "artiq.coredevice.spi",
"class": "SPIMaster", "class": "SPIMaster",
@ -108,6 +108,13 @@
"arguments": {"channel": 23} "arguments": {"channel": 23}
}, },
"dac0": {
"type": "local",
"module": "artiq.coredevice.ad5360",
"class": "AD5360",
"arguments": {"spi_device": "spi0", "ldac_device": "ttl0"}
},
"dds_bus": { "dds_bus": {
"type": "local", "type": "local",
"module": "artiq.coredevice.dds", "module": "artiq.coredevice.dds",