diff --git a/artiq/coredevice/ad5360.py b/artiq/coredevice/ad5360.py index 9e1b6781c..0df78f824 100644 --- a/artiq/coredevice/ad5360.py +++ b/artiq/coredevice/ad5360.py @@ -1,7 +1,8 @@ -from artiq.language.core import kernel, portable, delay -from artiq.language.units import ns +from artiq.language.core import kernel, portable, delay_mu 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 | 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_OFS0 = 2 << 16 _AD5360_SPECIAL_OFS1 = 3 << 16 -_AD5360_SPECIAL_READ = 3 << 16 +_AD5360_SPECIAL_READ = 5 << 16 @portable @@ -43,11 +44,12 @@ class AD5360: 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.bus = dmgr.get(spi_bus) - if ldac is not None: - ldac = dmgr.get(ldac) + self.bus = dmgr.get(spi_device) + if ldac_device is not None: + ldac = dmgr.get(ldac_device) self.ldac = ldac 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_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 def write_offsets(self, value=0x1fff): value &= 0x3fff - self.bus.write((_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_OFS0 | value - ) << 8) - self.bus.write((_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_OFS1 | value - ) << 8) + self.write(_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_OFS0 | value) + self.write(_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_OFS1 | value) @kernel def write_channel(self, channel=0, value=0, op=_AD5360_CMD_DATA): channel &= 0x3f value &= 0xffff - self.bus.write((op | _AD5360_WRITE_CHANNEL(channel) | value) << 8) + self.write(op | _AD5360_WRITE_CHANNEL(channel) | value) @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)): - self.write_channel(i + first, values[i], op) + self.write_channel(i, values[i], op) @kernel def read_channel_sync(self, channel=0, op=_AD5360_READ_X1A): channel &= 0x3f - self.bus.write((_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_READ | op | - _AD5360_READ_CHANNEL(channel)) << 8) + self.write(_AD5360_CMD_SPECIAL | _AD5360_SPECIAL_READ | op | + _AD5360_READ_CHANNEL(channel)) 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.set_xfer(self.chip_select, 24, 0) return self.bus.input_async() & 0xffff @@ -91,5 +96,5 @@ class AD5360: @kernel def load(self): self.ldac.off() - delay(24*ns) + delay_mu(3*self.bus.ref_period_mu) self.ldac.on() diff --git a/artiq/coredevice/spi.py b/artiq/coredevice/spi.py index 159bd4da4..6221c8f53 100644 --- a/artiq/coredevice/spi.py +++ b/artiq/coredevice/spi.py @@ -38,17 +38,16 @@ class SPIMaster: * If desired, :meth:`write` ``data`` queuing the next (possibly chained) transfer. - :param ref_period: clock period of the SPI core. :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.ref_period = ref_period - self.ref_period_mu = int(seconds_to_mu(ref_period, self.core)) + self.ref_period_mu = seconds_to_mu(self.core.coarse_ref_period, + self.core) self.channel = channel - self.write_period_mu = int(0) - self.read_period_mu = int(0) - self.xfer_period_mu = int(0) + self.write_period_mu = int(0, 64) + self.read_period_mu = int(0, 64) + self.xfer_period_mu = int(0, 64) # A full transfer takes write_period_mu + xfer_period_mu. # Chained transfers can happen every xfer_period_mu. # The second transfer of a chain can be written 2*ref_period_mu diff --git a/examples/master/device_db.pyon b/examples/master/device_db.pyon index 1644ed176..dce234bf2 100644 --- a/examples/master/device_db.pyon +++ b/examples/master/device_db.pyon @@ -81,7 +81,7 @@ "arguments": {"channel": 19} }, - "ams101_ldac": { + "ttl_ams101_ldac": { "type": "local", "module": "artiq.coredevice.ttl", "class": "TTLOut", @@ -94,7 +94,7 @@ "arguments": {"channel": 21} }, - "ams101_spi": { + "spi_ams101": { "type": "local", "module": "artiq.coredevice.spi", "class": "SPIMaster", @@ -108,6 +108,13 @@ "arguments": {"channel": 23} }, + "dac0": { + "type": "local", + "module": "artiq.coredevice.ad5360", + "class": "AD5360", + "arguments": {"spi_device": "spi0", "ldac_device": "ttl0"} + }, + "dds_bus": { "type": "local", "module": "artiq.coredevice.dds",