From a63fd306af3e4cce0419aee812f9d5a37d5b4eb5 Mon Sep 17 00:00:00 2001 From: Robert Jordens Date: Wed, 21 Feb 2018 15:00:28 +0000 Subject: [PATCH] urukul: use spi2 * switch kc705 and kasli targets to spi2 gateware on urukul * rewrite urukul, ad9912, ad9910 * update example experiments, device_dbs --- artiq/coredevice/ad9910.py | 104 +++++---- artiq/coredevice/ad9912.py | 77 ++++--- artiq/coredevice/spi.py | 2 + artiq/coredevice/urukul.py | 206 +++++++++++------- artiq/examples/kasli_opticlock/device_db.py | 7 +- .../kasli_opticlock/repository/urukul.py | 5 +- artiq/examples/kc705_nist_clock/device_db.py | 2 +- .../kc705_nist_clock/repository/urukul.py | 34 ++- artiq/gateware/targets/kasli.py | 6 +- artiq/gateware/targets/kc705.py | 6 +- 10 files changed, 256 insertions(+), 193 deletions(-) diff --git a/artiq/coredevice/ad9910.py b/artiq/coredevice/ad9910.py index 3f44a7625..ff2c35070 100644 --- a/artiq/coredevice/ad9910.py +++ b/artiq/coredevice/ad9910.py @@ -1,9 +1,12 @@ -from artiq.language.core import kernel, delay_mu, delay, portable -from artiq.language.units import us, ns, ms -from artiq.coredevice.urukul import urukul_sta_pll_lock - from numpy import int32, int64 +from artiq.language.core import kernel, delay, portable +from artiq.language.units import us, ns, ms + +from artiq.coredevice import spi2 as spi +from artiq.coredevice import urukul +urukul_sta_pll_lock = urukul.urukul_sta_pll_lock + _AD9910_REG_CFR1 = 0x00 _AD9910_REG_CFR2 = 0x01 @@ -47,7 +50,7 @@ class AD9910: :param pll_vco: DDS PLL VCO range selection. """ kernel_invariants = {"chip_select", "cpld", "core", "bus", "sw", - "ftw_per_hz", "sysclk", "pll_n", "pll_cp", "pll_vco"} + "ftw_per_hz", "pll_n", "pll_cp", "pll_vco"} def __init__(self, dmgr, chip_select, cpld_device, sw_device=None, pll_n=40, pll_cp=7, pll_vco=5): @@ -60,14 +63,14 @@ class AD9910: self.sw = dmgr.get(sw_device) assert 12 <= pll_n <= 127 self.pll_n = pll_n - assert self.cpld.refclk < 60e6 - self.sysclk = self.cpld.refclk*pll_n/4 # Urukul clock fanout divider - assert self.sysclk <= 1e9 - self.ftw_per_hz = 1./self.sysclk*(int64(1) << 32) + assert self.cpld.refclk/4 <= 60e6 + sysclk = self.cpld.refclk*pll_n/4 # Urukul clock fanout divider + assert sysclk <= 1e9 + self.ftw_per_hz = 1./sysclk*(int64(1) << 32) assert 0 <= pll_vco <= 5 vco_min, vco_max = [(370, 510), (420, 590), (500, 700), (600, 880), (700, 950), (820, 1150)][pll_vco] - assert vco_min <= self.sysclk/1e6 <= vco_max + assert vco_min <= sysclk/1e6 <= vco_max self.pll_vco = pll_vco assert 0 <= pll_cp <= 7 self.pll_cp = pll_cp @@ -79,12 +82,27 @@ class AD9910: :param addr: Register address :param data: Data to be written """ - self.bus.set_xfer(self.chip_select, 8, 0) + self.bus.set_config_mu(urukul.SPI_CONFIG, 8, + urukul.SPIT_DDS_WR, self.chip_select) self.bus.write(addr << 24) - delay_mu(-self.bus.xfer_period_mu + 8) - self.bus.set_xfer(self.chip_select, 32, 0) + self.bus.set_config_mu(urukul.SPI_CONFIG | spi.SPI_END, 32, + urukul.SPIT_DDS_WR, self.chip_select) self.bus.write(data) - delay_mu(self.bus.xfer_period_mu - self.bus.write_period_mu) + + @kernel + def read32(self, addr): + """Read from 32 bit register. + + :param addr: Register address + """ + self.bus.set_config_mu(urukul.SPI_CONFIG, 8, + urukul.SPIT_DDS_WR, self.chip_select) + self.bus.write((addr | 0x80) << 24) + self.bus.set_config_mu(urukul.SPI_CONFIG | spi.SPI_END + | spi.SPI_INPUT, 32, + urukul.SPIT_DDS_RD, self.chip_select) + self.bus.write(0) + return self.bus.read() @kernel def write64(self, addr, data_high, data_low): @@ -94,68 +112,58 @@ class AD9910: :param data_high: High (MSB) 32 bits of the data :param data_low: Low (LSB) 32 data bits """ - self.bus.set_xfer(self.chip_select, 8, 0) + self.bus.set_config_mu(urukul.SPI_CONFIG, 8, + urukul.SPIT_DDS_WR, self.chip_select) self.bus.write(addr << 24) - t = self.bus.xfer_period_mu - delay_mu(-t + 8) - self.bus.set_xfer(self.chip_select, 32, 0) + self.bus.set_config_mu(urukul.SPI_CONFIG, 32, + urukul.SPIT_DDS_WR, self.chip_select) self.bus.write(data_high) + self.bus.set_config_mu(urukul.SPI_CONFIG | spi.SPI_END, 32, + urukul.SPIT_DDS_WR, self.chip_select) self.bus.write(data_low) - delay_mu(t - 2*self.bus.write_period_mu) - - @kernel - def read32(self, addr): - """Read from 32 bit register. - - :param addr: Register address - """ - self.bus.set_xfer(self.chip_select, 8, 0) - self.bus.write((addr | 0x80) << 24) - delay_mu(-self.bus.xfer_period_mu + 8) - self.bus.set_xfer(self.chip_select, 0, 32) - self.bus.write(0) - delay_mu(2*self.bus.xfer_period_mu) - data = self.bus.read_sync() - return data @kernel def init(self): - """Initialize and configure the DDS.""" + """Initialize and configure the DDS. + + Sets up SPI mode, confirms chip presence, powers down unused blocks, + configures the PLL, waits for PLL lock. Uses the + IO_UPDATE signal multiple times. + """ # Set SPI mode self.write32(_AD9910_REG_CFR1, 0x00000002) - delay(100*us) - self.cpld.io_update.pulse(100*ns) + self.cpld.io_update.pulse(1*us) # Use the AUX DAC setting to identify and confirm presence aux_dac = self.read32(_AD9910_REG_AUX_DAC) if aux_dac & 0xff != 0x7f: raise ValueError("Urukul AD9910 AUX_DAC mismatch") - delay(100*us) + delay(20*us) # slack # Configure PLL settings and bring up PLL self.write32(_AD9910_REG_CFR2, 0x01400020) + self.cpld.io_update.pulse(1*us) cfr3 = (0x0807c100 | (self.pll_vco << 24) | (self.pll_cp << 19) | (self.pll_n << 1)) self.write32(_AD9910_REG_CFR3, cfr3 | 0x400) # PFD reset - delay(100*us) - self.cpld.io_update.pulse(100*ns) + self.cpld.io_update.pulse(100*us) self.write32(_AD9910_REG_CFR3, cfr3) - delay(100*us) - self.cpld.io_update.pulse(100*ns) + self.cpld.io_update.pulse(100*us) # Wait for PLL lock, up to 100 ms for i in range(100): - lock = urukul_sta_pll_lock(self.cpld.sta_read()) + sta = self.cpld.sta_read() + lock = urukul_sta_pll_lock(sta) delay(1*ms) - if lock & (1 << self.chip_select - 4) != 0: + if lock & (1 << self.chip_select - 4): return - raise ValueError("PLL failed to lock") + raise ValueError("PLL lock timeout") @kernel - def set_mu(self, ftw=int32(0), pow=int32(0), asf=int32(0x3fff)): + def set_mu(self, ftw, pow=0, asf=0x3fff): """Set profile 0 data in machine units. After the SPI transfer, the shared IO update pin is pulsed to activate the data. - :param ftw: Frequency tuning word: 32 bit unsigned. + :param ftw: Frequency tuning word: 32 bit. :param pow: Phase tuning word: 16 bit unsigned. :param asf: Amplitude scale factor: 14 bit unsigned. """ @@ -195,7 +203,7 @@ class AD9910: self.amplitude_to_asf(amplitude)) @kernel - def set_att_mu(self, att=int32(0)): + def set_att_mu(self, att): """Set digital step attenuator in machine units. .. seealso:: :meth:`artiq.coredevice.urukul.CPLD.set_att_mu` diff --git a/artiq/coredevice/ad9912.py b/artiq/coredevice/ad9912.py index f09e91695..67549a74d 100644 --- a/artiq/coredevice/ad9912.py +++ b/artiq/coredevice/ad9912.py @@ -1,8 +1,11 @@ -from artiq.language.core import kernel, delay_mu, delay, portable +from numpy import int32, int64 + +from artiq.language.core import kernel, delay, portable from artiq.language.units import us, ns from artiq.coredevice.ad9912_reg import * -from numpy import int32, int64 +from artiq.coredevice import spi2 as spi +from artiq.coredevice import urukul class AD9912: @@ -39,8 +42,9 @@ class AD9912: self.ftw_per_hz = 1/self.sysclk*(int64(1) << 48) @kernel - def write(self, addr=int32(0), data=int32(0), length=int32(1)): - """Variable length write to a register. Up to 32 bits. + def write(self, addr, data, length): + """Variable length write to a register. + Up to 4 bytes. :param addr: Register address :param data: Data to be written: int32 @@ -48,51 +52,60 @@ class AD9912: """ assert length > 0 assert length <= 4 - self.bus.set_xfer(self.chip_select, 16, 0) + self.bus.set_config_mu(urukul.SPI_CONFIG, 16, + urukul.SPIT_DDS_WR, self.chip_select) self.bus.write((addr | ((length - 1) << 13)) << 16) - delay_mu(-self.bus.xfer_period_mu) - self.bus.set_xfer(self.chip_select, length*8, 0) + self.bus.set_config_mu(urukul.SPI_CONFIG | spi.SPI_END, length*8, + urukul.SPIT_DDS_WR, self.chip_select) self.bus.write(data << (32 - length*8)) - delay_mu(self.bus.xfer_period_mu - self.bus.write_period_mu) @kernel - def read(self, addr=int32(0), length=int32(1)): - """Variable length read from a register. Up to 32 bits. + def read(self, addr, length): + """Variable length read from a register. + Up to 4 bytes. :param addr: Register address :param length: Length in bytes (1-4) + :return: Data read """ assert length > 0 assert length <= 4 - self.bus.set_xfer(self.chip_select, 16, 0) + self.bus.set_config_mu(urukul.SPI_CONFIG, 16, + urukul.SPIT_DDS_WR, self.chip_select) self.bus.write((addr | ((length - 1) << 13) | 0x8000) << 16) - delay_mu(-self.bus.xfer_period_mu) - self.bus.set_xfer(self.chip_select, 0, length*8) + self.bus.set_config_mu(urukul.SPI_CONFIG | spi.SPI_END + | spi.SPI_INPUT, length*8, + urukul.SPIT_DDS_RD, self.chip_select) self.bus.write(0) - delay_mu(2*self.bus.xfer_period_mu) - data = self.bus.read_sync() + data = self.bus.read() if length < 4: data &= (1 << (length*8)) - 1 return data @kernel def init(self): - """Initialize and configure the DDS.""" - t = now_mu() + """Initialize and configure the DDS. + + Sets up SPI mode, confirms chip presence, powers down unused blocks, + and configures the PLL. Does not wait for PLL lock. Uses the + IO_UPDATE signal multiple times. + """ # SPI mode - self.write(AD9912_SER_CONF, 0x99) + self.write(AD9912_SER_CONF, 0x99, length=1) + self.cpld.io_update.pulse(1*us) # Verify chip ID and presence prodid = self.read(AD9912_PRODIDH, length=2) if (prodid != 0x1982) and (prodid != 0x1902): raise ValueError("Urukul AD9912 product id mismatch") - delay(10*us) + delay(20*us) # HSTL power down, CMOS power down - self.write(AD9912_PWRCNTRL1, 0x80) - delay(10*us) - self.write(AD9912_N_DIV, self.pll_n//2 - 2) - delay(10*us) + self.write(AD9912_PWRCNTRL1, 0x80, length=1) + self.cpld.io_update.pulse(1*us) + self.write(AD9912_N_DIV, self.pll_n//2 - 2, length=1) + self.cpld.io_update.pulse(1*us) # I_cp = 375 µA, VCO high range - self.write(AD9912_PLLCFG, 0b00000101) + self.write(AD9912_PLLCFG, 0b00000101, length=1) + self.cpld.io_update.pulse(1*us) @kernel def set_att_mu(self, att): @@ -110,12 +123,12 @@ class AD9912: .. seealso:: :meth:`artiq.coredevice.urukul.CPLD.set_att` - :param att: Attenuation in dB. + :param att: Attenuation in dB. Higher values mean more attenuation. """ self.cpld.set_att(self.chip_select - 4, att) @kernel - def set_mu(self, ftw=int64(0), pow=int32(0)): + def set_mu(self, ftw, pow): """Set profile 0 data in machine units. After the SPI transfer, the shared IO update pin is pulsed to @@ -125,13 +138,15 @@ class AD9912: :param pow: Phase tuning word: 16 bit unsigned. """ # streaming transfer of FTW and POW - self.bus.set_xfer(self.chip_select, 16, 0) + self.bus.set_config_mu(urukul.SPI_CONFIG, 16, + urukul.SPIT_DDS_WR, self.chip_select) self.bus.write((AD9912_POW1 << 16) | (3 << 29)) - delay_mu(-self.bus.xfer_period_mu) - self.bus.set_xfer(self.chip_select, 32, 0) - self.bus.write((pow << 16) | int32(ftw >> 32)) + self.bus.set_config_mu(urukul.SPI_CONFIG, 32, + urukul.SPIT_DDS_WR, self.chip_select) + self.bus.write((pow << 16) | (int32(ftw >> 32) & 0xffff)) + self.bus.set_config_mu(urukul.SPI_CONFIG | spi.SPI_END, 32, + urukul.SPIT_DDS_WR, self.chip_select) self.bus.write(int32(ftw)) - delay_mu(self.bus.xfer_period_mu - self.bus.write_period_mu) self.cpld.io_update.pulse(10*ns) @portable(flags={"fast-math"}) diff --git a/artiq/coredevice/spi.py b/artiq/coredevice/spi.py index 22859a962..1d60722d5 100644 --- a/artiq/coredevice/spi.py +++ b/artiq/coredevice/spi.py @@ -1,6 +1,8 @@ """ Driver for generic SPI on RTIO. +This ARTIQ coredevice driver corresponds to the legacy MiSoC SPI core (v1). + Output event replacement is not supported and issuing commands at the same time is an error. """ diff --git a/artiq/coredevice/urukul.py b/artiq/coredevice/urukul.py index 6648205c6..2cc0b80ba 100644 --- a/artiq/coredevice/urukul.py +++ b/artiq/coredevice/urukul.py @@ -1,22 +1,23 @@ -from artiq.language.core import kernel, delay_mu, delay, now_mu, at_mu +from artiq.language.core import kernel, delay, portable from artiq.language.units import us, ms from numpy import int32, int64 -from artiq.coredevice import spi +from artiq.coredevice import spi2 as spi -_SPI_CONFIG = (0*spi.SPI_OFFLINE | 1*spi.SPI_CS_POLARITY | +SPI_CONFIG = (0*spi.SPI_OFFLINE | 0*spi.SPI_END | + 0*spi.SPI_INPUT | 1*spi.SPI_CS_POLARITY | 0*spi.SPI_CLK_POLARITY | 0*spi.SPI_CLK_PHASE | 0*spi.SPI_LSB_FIRST | 0*spi.SPI_HALF_DUPLEX) # SPI clock write and read dividers -_SPIT_CFG_WR = 2 -_SPIT_CFG_RD = 16 -_SPIT_ATT_WR = 2 -_SPIT_ATT_RD = 16 -_SPIT_DDS_WR = 3 -_SPIT_DDS_RD = 16 +SPIT_CFG_WR = 2 +SPIT_CFG_RD = 16 +SPIT_ATT_WR = 2 +SPIT_ATT_RD = 16 +SPIT_DDS_WR = 2 +SPIT_DDS_RD = 16 # CFG configuration register bit offsets CFG_RF_SW = 0 @@ -29,17 +30,6 @@ CFG_SYNC_SEL = 18 CFG_RST = 19 CFG_IO_RST = 20 - -@kernel -def urukul_cfg(rf_sw, led, profile, io_update, mask_nu, - clk_sel, sync_sel, rst, io_rst): - return ((rf_sw << CFG_RF_SW) | (led << CFG_LED) | - (profile << CFG_PROFILE) | - (io_update << CFG_IO_UPDATE) | (mask_nu << CFG_MASK_NU) | - (clk_sel << CFG_CLK_SEL) | (sync_sel << CFG_SYNC_SEL) | - (rst << CFG_RST) | (io_rst << CFG_IO_RST)) - - # STA status register bit offsets STA_RF_SW = 0 STA_SMP_ERR = 4 @@ -47,32 +37,6 @@ STA_PLL_LOCK = 8 STA_IFC_MODE = 12 STA_PROTO_REV = 16 - -@kernel -def urukul_sta_rf_sw(sta): - return (sta >> STA_RF_SW) & 0xf - - -@kernel -def urukul_sta_smp_err(sta): - return (sta >> STA_SMP_ERR) & 0xf - - -@kernel -def urukul_sta_pll_lock(sta): - return (sta >> STA_PLL_LOCK) & 0xf - - -@kernel -def urukul_sta_ifc_mode(sta): - return (sta >> STA_IFC_MODE) & 0xf - - -@kernel -def urukul_sta_proto_rev(sta): - return (sta >> STA_PROTO_REV) & 0x7f - - # supported hardware and CPLD code version STA_PROTO_REV_MATCH = 0x08 @@ -86,6 +50,51 @@ CS_DDS_CH2 = 6 CS_DDS_CH3 = 7 +@portable +def urukul_cfg(rf_sw, led, profile, io_update, mask_nu, + clk_sel, sync_sel, rst, io_rst): + """Build Urukul CPLD configuration register""" + return ((rf_sw << CFG_RF_SW) | + (led << CFG_LED) | + (profile << CFG_PROFILE) | + (io_update << CFG_IO_UPDATE) | + (mask_nu << CFG_MASK_NU) | + (clk_sel << CFG_CLK_SEL) | + (sync_sel << CFG_SYNC_SEL) | + (rst << CFG_RST) | + (io_rst << CFG_IO_RST)) + + +@portable +def urukul_sta_rf_sw(sta): + """Return the RF switch status from Urukul status register value.""" + return (sta >> STA_RF_SW) & 0xf + + +@portable +def urukul_sta_smp_err(sta): + """Return the SMP_ERR status from Urukul status register value.""" + return (sta >> STA_SMP_ERR) & 0xf + + +@portable +def urukul_sta_pll_lock(sta): + """Return the PLL_LOCK status from Urukul status register value.""" + return (sta >> STA_PLL_LOCK) & 0xf + + +@portable +def urukul_sta_ifc_mode(sta): + """Return the IFC_MODE status from Urukul status register value.""" + return (sta >> STA_IFC_MODE) & 0xf + + +@portable +def urukul_sta_proto_rev(sta): + """Return the PROTO_REV value from Urukul status register value.""" + return (sta >> STA_PROTO_REV) & 0x7f + + class CPLD: """Urukul CPLD SPI router and configuration interface. @@ -94,11 +103,18 @@ class CPLD: :param dds_reset_device: DDS reset RTIO TTLOut channel name :param refclk: Reference clock (SMA, MMCX or on-board 100 MHz oscillator) frequency in Hz + :param clk_sel: Reference clock selection. 0 corresponds to the internal + MMCX or ob-board XO clock. 1 corresponds to the front panel SMA. + :param sync_sel: SYNC clock selection. 0 corresponds to SYNC clock over EEM + from FPGA. 1 corresponds to SYNC clock from DDS0. :param core_device: Core device name """ + kernel_invariants = {"refclk", "bus", "core", "io_update"} + def __init__(self, dmgr, spi_device, io_update_device, dds_reset_device=None, - refclk=100e6, core_device="core"): + sync_sel=0, clk_sel=0, + refclk=125e6, core_device="core"): self.core = dmgr.get(core_device) self.refclk = refclk @@ -108,63 +124,83 @@ class CPLD: if dds_reset_device is not None: self.dds_reset = dmgr.get(dds_reset_device) - self.cfg_reg = int32(0) - self.att_reg = int32(0) + self.cfg_reg = urukul_cfg(rf_sw=0, led=0, profile=0, + io_update=0, mask_nu=0, clk_sel=clk_sel, + sync_sel=sync_sel, rst=0, io_rst=0) + self.att_reg = 0 @kernel - def cfg_write(self, data=int32(0)): + def cfg_write(self, cfg): """Write to the configuration register. + See :func:`urukul_cfg` for possible flags. + :param data: 24 bit data to be written. Will be stored at :attr:`cfg_reg`. """ - self.bus.set_config_mu(_SPI_CONFIG, _SPIT_CFG_WR, _SPIT_CFG_RD) - self.bus.set_xfer(CS_CFG, 24, 0) - self.bus.write(data << 8) - self.bus.set_config_mu(_SPI_CONFIG, _SPIT_DDS_WR, _SPIT_DDS_RD) - self.cfg_reg = data + self.bus.set_config_mu(SPI_CONFIG | spi.SPI_END, 24, + SPIT_CFG_WR, CS_CFG) + self.bus.write(cfg << 8) + self.cfg_reg = cfg @kernel def sta_read(self): - self.bus.set_config_mu(_SPI_CONFIG, _SPIT_CFG_WR, _SPIT_CFG_RD) - self.bus.set_xfer(CS_CFG, 0, 24) + """Read the status register. + + Use any of the following functions to extract values: + + * :func:`urukul_sta_rf_sw` + * :func:`urukul_sta_smp_err` + * :func:`urukul_sta_pll_lock` + * :func:`urukul_sta_ifc_mode` + * :func:`urukul_sta_proto_rev` + + :return: The status register value. + """ + self.bus.set_config_mu(SPI_CONFIG | spi.SPI_END | spi.SPI_INPUT, 24, + SPIT_CFG_RD, CS_CFG) self.bus.write(self.cfg_reg << 8) - self.bus.set_config_mu(_SPI_CONFIG, _SPIT_DDS_WR, _SPIT_DDS_RD) - return self.bus.read_sync() + return self.bus.read() @kernel - def init(self, clk_sel=0, sync_sel=0): - cfg = urukul_cfg(rf_sw=0, led=0, profile=0, - io_update=0, mask_nu=0, clk_sel=clk_sel, - sync_sel=sync_sel, rst=0, io_rst=0) - self.cfg_write(cfg | (1 << CFG_RST) | (1 << CFG_IO_RST)) - delay(1*ms) - self.cfg_write(cfg) - delay(10*ms) # DDS wake up + def init(self): + """Initialize and detect Urukul. + + Resets the DDS and verifies correct CPLD gateware version. + """ + cfg = self.cfg_reg + self.cfg_reg = cfg | (1 << CFG_RST) | (1 << CFG_IO_RST) proto_rev = urukul_sta_proto_rev(self.sta_read()) if proto_rev != STA_PROTO_REV_MATCH: raise ValueError("Urukul proto_rev mismatch") - delay(100*us) + delay(20*us) # slack, reset + self.cfg_write(cfg) + delay(1*ms) # DDS wake up @kernel def io_rst(self): - delay(1*us) + """Pulse IO_RST""" self.cfg_write(self.cfg_reg | (1 << CFG_IO_RST)) - delay(1*us) self.cfg_write(self.cfg_reg & ~(1 << CFG_IO_RST)) - delay(1*us) @kernel - def cfg_sw(self, sw, on): + def cfg_sw(self, channel, on): + """Configure the RF switches through the configuration register. + + These values are logically OR-ed with the LVDS lines on EEM1. + + :param channel: Channel index (0-3) + :param on: Switch value + """ c = self.cfg_reg if on: - c |= 1 << sw + c |= 1 << channel else: - c &= ~(1 << sw) + c &= ~(1 << channel) self.cfg_write(c) @kernel - def set_att_mu(self, channel=int32(0), att=int32(0)): + def set_att_mu(self, channel, att): """Set digital step attenuator in machine units. :param channel: Attenuator channel (0-3). @@ -173,16 +209,28 @@ class CPLD: """ a = self.att_reg & ~(0xff << (channel * 8)) a |= att << (channel * 8) - self.att_reg = a - self.bus.set_config_mu(_SPI_CONFIG, _SPIT_ATT_WR, _SPIT_ATT_RD) - self.bus.set_xfer(CS_ATT, 32, 0) + self.bus.set_config_mu(SPI_CONFIG | spi.SPI_END, 32, + SPIT_ATT_WR, CS_ATT) self.bus.write(a) + self.att_reg = a @kernel def set_att(self, channel, att): """Set digital step attenuator in SI units. :param channel: Attenuator channel (0-3). - :param att: Attenuation in dB. + :param att: Attenuation setting in dB. Higher value is more + attenuation. """ self.set_att_mu(channel, 255 - int32(round(att*8))) + + @kernel + def get_att_mu(self): + """Return the digital step attenuator settings in machine units. + + :return: 32 bit attenuator settings + """ + self.bus.set_config_mu(SPI_CONFIG | spi.SPI_END | spi.SPI_INPUT, 32, + SPIT_ATT_RD, CS_ATT) + self.bus.write(self.att_reg) + return self.bus.read() diff --git a/artiq/examples/kasli_opticlock/device_db.py b/artiq/examples/kasli_opticlock/device_db.py index 1600797ec..773962d73 100644 --- a/artiq/examples/kasli_opticlock/device_db.py +++ b/artiq/examples/kasli_opticlock/device_db.py @@ -188,7 +188,7 @@ device_db = { "spi_novogorny0": { "type": "local", - "module": "artiq.coredevice.spi", + "module": "artiq.coredevice.spi2", "class": "SPIMaster", "arguments": {"channel": 24} }, @@ -201,7 +201,7 @@ device_db = { "spi_urukul0": { "type": "local", - "module": "artiq.coredevice.spi", + "module": "artiq.coredevice.spi2", "class": "SPIMaster", "arguments": {"channel": 26} }, @@ -242,7 +242,8 @@ device_db = { "arguments": { "spi_device": "spi_urukul0", "io_update_device": "ttl_urukul0_io_update", - "refclk": 100e6 + "refclk": 100e6, + "clk_sel": 1 } }, "urukul0_ch0": { diff --git a/artiq/examples/kasli_opticlock/repository/urukul.py b/artiq/examples/kasli_opticlock/repository/urukul.py index 2f6a28d9f..39b8ea3c2 100644 --- a/artiq/examples/kasli_opticlock/repository/urukul.py +++ b/artiq/examples/kasli_opticlock/repository/urukul.py @@ -11,9 +11,6 @@ class UrukulTest(EnvExperiment): self.setattr_device("urukul0_ch3") self.setattr_device("led0") - def p(self, f, *a): - print(f % a) - @kernel def run(self): self.core.reset() @@ -21,7 +18,7 @@ class UrukulTest(EnvExperiment): delay(5*ms) self.led0.off() - self.urukul0_cpld.init(clk_sel=0) + self.urukul0_cpld.init() self.urukul0_ch0.init() self.urukul0_ch1.init() self.urukul0_ch2.init() diff --git a/artiq/examples/kc705_nist_clock/device_db.py b/artiq/examples/kc705_nist_clock/device_db.py index 1beebf7c1..deef2723a 100644 --- a/artiq/examples/kc705_nist_clock/device_db.py +++ b/artiq/examples/kc705_nist_clock/device_db.py @@ -192,7 +192,7 @@ device_db = { "spi_urukul": { "type": "local", - "module": "artiq.coredevice.spi", + "module": "artiq.coredevice.spi2", "class": "SPIMaster", "arguments": {"channel": 32} }, diff --git a/artiq/examples/kc705_nist_clock/repository/urukul.py b/artiq/examples/kc705_nist_clock/repository/urukul.py index ea85597f9..129daf0b7 100644 --- a/artiq/examples/kc705_nist_clock/repository/urukul.py +++ b/artiq/examples/kc705_nist_clock/repository/urukul.py @@ -16,9 +16,6 @@ class UrukulTest(EnvExperiment): self.setattr_device("urukul_ch3b") self.setattr_device("led") - def p(self, f, *a): - print(f % a) - @kernel def run(self): self.core.reset() @@ -28,7 +25,7 @@ class UrukulTest(EnvExperiment): self.fmcdio_dirctl.set(0x0A008800) self.led.off() - self.urukul_cpld.init(clk_sel=0) + self.urukul_cpld.init() self.urukul_ch0b.init() self.urukul_ch1b.init() self.urukul_ch2b.init() @@ -54,24 +51,19 @@ class UrukulTest(EnvExperiment): self.urukul_ch3b.sw.on() self.urukul_ch3b.set_att(20.) - i = 0 - j = 0 - while True: - delay(13*us) - self.urukul_ch0b.write32(0x07, i) - self.urukul_cpld.io_update.pulse(10*ns) - k = self.urukul_ch0b.read32(0x07) - delay(100*us) - if k != i: - #print(i) - #print(k) - #if j > 20: - # return - j += 1 - #delay(20*ms) - i += 1 + data = 0 + errors = 0 + delay(100*us) + while data != -1: + self.urukul_ch0b.write32(0x07, data) + read = self.urukul_ch0b.read32(0x07) + if read != data: + errors += 1 + if errors > 20: + return + data += 1 - while True: + while False: self.urukul_ch0b.sw.pulse(5*ms) delay(5*ms) diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index e45c57ff1..d5affe656 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -19,7 +19,7 @@ from misoc.integration.builder import builder_args, builder_argdict from artiq.gateware.amp import AMPSoC from artiq.gateware import rtio -from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, spi +from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, spi2 from artiq.gateware.drtio.transceiver import gtp_7series from artiq.gateware.drtio import DRTIOMaster, DRTIOSatellite from artiq.build_soc import build_artiq_soc @@ -265,7 +265,7 @@ class Opticlock(_StandaloneBase): self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy)) - phy = spi.SPIMaster(self.platform.request("eem3_spi_p"), + phy = spi2.SPIMaster(self.platform.request("eem3_spi_p"), self.platform.request("eem3_spi_n")) self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) @@ -276,7 +276,7 @@ class Opticlock(_StandaloneBase): self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy)) - phy = spi.SPIMaster(self.platform.request("eem5_spi_p"), + phy = spi2.SPIMaster(self.platform.request("eem5_spi_p"), self.platform.request("eem5_spi_n")) self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 7b868910d..1479c8e6c 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -17,7 +17,7 @@ from misoc.integration.builder import builder_args, builder_argdict from artiq.gateware.amp import AMPSoC from artiq.gateware import rtio, nist_clock, nist_qc2 from artiq.gateware.rtio.phy import (ttl_simple, ttl_serdes_7series, - dds, spi, ad5360_monitor) + dds, spi, spi2, ad5360_monitor) from artiq.build_soc import build_artiq_soc from artiq import __version__ as artiq_version @@ -355,8 +355,8 @@ class NIST_CLOCK(_StandaloneBase): self.submodules += dac_monitor sdac_phy.probes.extend(dac_monitor.probes) - phy = spi.SPIMaster(self.platform.request("urukul_spi_p"), - self.platform.request("urukul_spi_n")) + phy = spi2.SPIMaster(self.platform.request("urukul_spi_p"), + self.platform.request("urukul_spi_n")) self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4))