urukul/ad9910: support blind init

urukul: always set io_update attribute
to silence compiler warning w.r.t. kernel_invariants
This commit is contained in:
Robert Jördens 2018-04-26 07:59:08 +00:00 committed by Robert Jordens
parent 3802c7badb
commit 01f762a8f5
2 changed files with 36 additions and 12 deletions

View File

@ -57,7 +57,7 @@ class AD9910:
self.cpld = dmgr.get(cpld_device)
self.core = self.cpld.core
self.bus = self.cpld.bus
assert 4 <= chip_select <= 7
assert 3 <= chip_select <= 7
self.chip_select = chip_select
if sw_device:
self.sw = dmgr.get(sw_device)
@ -124,21 +124,25 @@ class AD9910:
self.bus.write(data_low)
@kernel
def init(self):
def init(self, blind=False):
"""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.
:param blind: Do not read back DDS identity and do not wait for lock.
"""
# Set SPI mode
self.write32(_AD9910_REG_CFR1, 0x00000002)
self.cpld.io_update.pulse(2*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(50*us) # slack
delay(1*ms)
if not blind:
# 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(50*us) # slack
# Configure PLL settings and bring up PLL
self.write32(_AD9910_REG_CFR2, 0x01400020)
self.cpld.io_update.pulse(2*us)
@ -148,6 +152,9 @@ class AD9910:
self.cpld.io_update.pulse(100*us)
self.write32(_AD9910_REG_CFR3, cfr3)
self.cpld.io_update.pulse(100*us)
if blind:
delay(100*ms)
return
# Wait for PLL lock, up to 100 ms
for i in range(100):
sta = self.cpld.sta_read()

View File

@ -95,6 +95,18 @@ def urukul_sta_proto_rev(sta):
return (sta >> STA_PROTO_REV) & 0x7f
class _RegIOUpdate:
def __init__(self, cpld):
self.cpld = cpld
@portable
def pulse(self, t):
cfg = self.cpld.cfg_reg
self.cpld.cfg_write(cfg | (1 << CFG_IO_UPDATE))
delay(t)
self.cpld.cfg_write(cfg)
class CPLD:
"""Urukul CPLD SPI router and configuration interface.
@ -122,6 +134,8 @@ class CPLD:
self.bus = dmgr.get(spi_device)
if io_update_device is not None:
self.io_update = dmgr.get(io_update_device)
else:
self.io_update = _RegIOUpdate(self)
if dds_reset_device is not None:
self.dds_reset = dmgr.get(dds_reset_device)
@ -164,20 +178,23 @@ class CPLD:
return self.bus.read()
@kernel
def init(self):
def init(self, blind=False):
"""Initialize and detect Urukul.
Resets the DDS I/O interface and verifies correct CPLD gateware
version.
Does not pulse the DDS MASTER_RESET as that confuses the AD9910.
:param blind: Do not attempt to verify presence and compatibility.
"""
cfg = self.cfg_reg
# Don't pulse MASTER_RESET (m-labs/artiq#940)
self.cfg_reg = cfg | (0 << 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(20*us) # slack, reset
if not blind:
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) # reset, slack
self.cfg_write(cfg)
delay(1*ms) # DDS wake up