mirror of
https://github.com/m-labs/artiq.git
synced 2025-02-03 06:10:18 +08:00
Un-format for clearer review
This commit is contained in:
parent
4dcc492382
commit
18dab3aace
@ -13,18 +13,10 @@ urukul_sta_smp_err = urukul.urukul_sta_smp_err
|
||||
|
||||
__all__ = [
|
||||
"AD9910",
|
||||
"PHASE_MODE_CONTINUOUS",
|
||||
"PHASE_MODE_ABSOLUTE",
|
||||
"PHASE_MODE_TRACKING",
|
||||
"RAM_DEST_FTW",
|
||||
"RAM_DEST_POW",
|
||||
"RAM_DEST_ASF",
|
||||
"RAM_DEST_POWASF",
|
||||
"RAM_MODE_DIRECTSWITCH",
|
||||
"RAM_MODE_RAMPUP",
|
||||
"RAM_MODE_BIDIR_RAMP",
|
||||
"RAM_MODE_CONT_BIDIR_RAMP",
|
||||
"RAM_MODE_CONT_RAMPUP",
|
||||
"PHASE_MODE_CONTINUOUS", "PHASE_MODE_ABSOLUTE", "PHASE_MODE_TRACKING",
|
||||
"RAM_DEST_FTW", "RAM_DEST_POW", "RAM_DEST_ASF", "RAM_DEST_POWASF",
|
||||
"RAM_MODE_DIRECTSWITCH", "RAM_MODE_RAMPUP", "RAM_MODE_BIDIR_RAMP",
|
||||
"RAM_MODE_CONT_BIDIR_RAMP", "RAM_MODE_CONT_RAMPUP",
|
||||
]
|
||||
|
||||
_PHASE_MODE_DEFAULT = -1
|
||||
@ -144,33 +136,13 @@ class AD9910:
|
||||
to the same string value.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
dmgr,
|
||||
chip_select,
|
||||
cpld_device,
|
||||
sw_device=None,
|
||||
pll_n=40,
|
||||
pll_cp=7,
|
||||
pll_vco=5,
|
||||
sync_delay_seed=-1,
|
||||
io_update_delay=0,
|
||||
pll_en=1,
|
||||
):
|
||||
self.kernel_invariants = {
|
||||
"cpld",
|
||||
"core",
|
||||
"bus",
|
||||
"chip_select",
|
||||
"pll_en",
|
||||
"pll_n",
|
||||
"pll_vco",
|
||||
"pll_cp",
|
||||
"ftw_per_hz",
|
||||
"sysclk_per_mu",
|
||||
"sysclk",
|
||||
"sync_data",
|
||||
}
|
||||
def __init__(self, dmgr, chip_select, cpld_device, sw_device=None,
|
||||
pll_n=40, pll_cp=7, pll_vco=5, sync_delay_seed=-1,
|
||||
io_update_delay=0, pll_en=1):
|
||||
self.kernel_invariants = {"cpld", "core", "bus", "chip_select",
|
||||
"pll_en", "pll_n", "pll_vco", "pll_cp",
|
||||
"ftw_per_hz", "sysclk_per_mu", "sysclk",
|
||||
"sync_data"}
|
||||
self.cpld = dmgr.get(cpld_device)
|
||||
self.core = self.cpld.core
|
||||
self.bus = self.cpld.bus
|
||||
@ -189,14 +161,8 @@ class AD9910:
|
||||
assert clk <= 60e6
|
||||
assert 12 <= pll_n <= 127
|
||||
assert 0 <= pll_vco <= 5
|
||||
vco_min, vco_max = [
|
||||
(370, 510),
|
||||
(420, 590),
|
||||
(500, 700),
|
||||
(600, 880),
|
||||
(700, 950),
|
||||
(820, 1150),
|
||||
][pll_vco]
|
||||
vco_min, vco_max = [(370, 510), (420, 590), (500, 700),
|
||||
(600, 880), (700, 950), (820, 1150)][pll_vco]
|
||||
assert vco_min <= sysclk / 1e6 <= vco_max
|
||||
assert 0 <= pll_cp <= 7
|
||||
else:
|
||||
@ -211,13 +177,12 @@ class AD9910:
|
||||
|
||||
if isinstance(sync_delay_seed, str) or isinstance(io_update_delay, str):
|
||||
if sync_delay_seed != io_update_delay:
|
||||
raise ValueError(
|
||||
"When using EEPROM, sync_delay_seed must be "
|
||||
"equal to io_update_delay"
|
||||
)
|
||||
raise ValueError("When using EEPROM, sync_delay_seed must be "
|
||||
"equal to io_update_delay")
|
||||
self.sync_data = SyncDataEeprom(dmgr, self.core, sync_delay_seed)
|
||||
else:
|
||||
self.sync_data = SyncDataUser(self.core, sync_delay_seed, io_update_delay)
|
||||
self.sync_data = SyncDataUser(self.core, sync_delay_seed,
|
||||
io_update_delay)
|
||||
|
||||
self.phase_mode = PHASE_MODE_CONTINUOUS
|
||||
|
||||
@ -271,10 +236,9 @@ class AD9910:
|
||||
:param addr: Register address
|
||||
:param data: Data to be written
|
||||
"""
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG | spi.SPI_END, 24, urukul.SPIT_DDS_WR, self.chip_select
|
||||
)
|
||||
self.bus.write((addr << 24) | ((data & 0xFFFF) << 8))
|
||||
self.bus.set_config_mu(urukul.SPI_CONFIG | spi.SPI_END, 24,
|
||||
urukul.SPIT_DDS_WR, self.chip_select)
|
||||
self.bus.write((addr << 24) | ((data & 0xFFFF) << 8))
|
||||
|
||||
@kernel
|
||||
def write32(self, addr: TInt32, data: TInt32):
|
||||
@ -283,13 +247,11 @@ class AD9910:
|
||||
:param addr: Register address
|
||||
:param data: Data to be written
|
||||
"""
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG, 8, urukul.SPIT_DDS_WR, self.chip_select
|
||||
)
|
||||
self.bus.set_config_mu(urukul.SPI_CONFIG, 8,
|
||||
urukul.SPIT_DDS_WR, self.chip_select)
|
||||
self.bus.write(addr << 24)
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG | spi.SPI_END, 32, urukul.SPIT_DDS_WR, self.chip_select
|
||||
)
|
||||
self.bus.set_config_mu(urukul.SPI_CONFIG | spi.SPI_END, 32,
|
||||
urukul.SPIT_DDS_WR, self.chip_select)
|
||||
self.bus.write(data)
|
||||
|
||||
@kernel
|
||||
@ -298,16 +260,12 @@ class AD9910:
|
||||
|
||||
:param addr: Register address
|
||||
"""
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG, 8, urukul.SPIT_DDS_WR, self.chip_select
|
||||
)
|
||||
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,
|
||||
16,
|
||||
urukul.SPIT_DDS_RD,
|
||||
self.chip_select,
|
||||
)
|
||||
16, urukul.SPIT_DDS_RD, self.chip_select)
|
||||
self.bus.write(0)
|
||||
return self.bus.read()
|
||||
|
||||
@ -317,16 +275,12 @@ class AD9910:
|
||||
|
||||
:param addr: Register address
|
||||
"""
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG, 8, urukul.SPIT_DDS_WR, self.chip_select
|
||||
)
|
||||
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,
|
||||
)
|
||||
32, urukul.SPIT_DDS_RD, self.chip_select)
|
||||
self.bus.write(0)
|
||||
return self.bus.read()
|
||||
|
||||
@ -338,19 +292,16 @@ class AD9910:
|
||||
:return: 64-bit integer register value
|
||||
"""
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG, 8, urukul.SPIT_DDS_WR, self.chip_select
|
||||
)
|
||||
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_INPUT, 32, urukul.SPIT_DDS_RD, self.chip_select
|
||||
)
|
||||
urukul.SPI_CONFIG | spi.SPI_INPUT, 32,
|
||||
urukul.SPIT_DDS_RD, self.chip_select)
|
||||
self.bus.write(0)
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG | spi.SPI_END | spi.SPI_INPUT,
|
||||
32,
|
||||
urukul.SPIT_DDS_RD,
|
||||
self.chip_select,
|
||||
)
|
||||
urukul.SPI_CONFIG | spi.SPI_END | spi.SPI_INPUT, 32,
|
||||
urukul.SPIT_DDS_RD, self.chip_select)
|
||||
self.bus.write(0)
|
||||
hi = self.bus.read()
|
||||
lo = self.bus.read()
|
||||
@ -361,20 +312,17 @@ class AD9910:
|
||||
"""Write to 64-bit register.
|
||||
|
||||
:param addr: Register address
|
||||
:param data_high: High (MSB) 32 data bits
|
||||
:param data_high: High (MSB) 32 data bits
|
||||
:param data_low: Low (LSB) 32 data bits
|
||||
"""
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG, 8, urukul.SPIT_DDS_WR, self.chip_select
|
||||
)
|
||||
self.bus.set_config_mu(urukul.SPI_CONFIG, 8,
|
||||
urukul.SPIT_DDS_WR, self.chip_select)
|
||||
self.bus.write(addr << 24)
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG, 32, urukul.SPIT_DDS_WR, self.chip_select
|
||||
)
|
||||
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.set_config_mu(urukul.SPI_CONFIG | spi.SPI_END, 32,
|
||||
urukul.SPIT_DDS_WR, self.chip_select)
|
||||
self.bus.write(data_low)
|
||||
|
||||
@kernel
|
||||
@ -388,18 +336,15 @@ class AD9910:
|
||||
|
||||
:param data: Data to be written to RAM.
|
||||
"""
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG, 8, urukul.SPIT_DDS_WR, self.chip_select
|
||||
)
|
||||
self.bus.set_config_mu(urukul.SPI_CONFIG, 32,
|
||||
urukul.SPIT_DDS_WR, self.chip_select)
|
||||
self.bus.write(_AD9910_REG_RAM << 24)
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG, 32, urukul.SPIT_DDS_WR, self.chip_select
|
||||
)
|
||||
self.bus.set_config_mu(urukul.SPI_CONFIG, 32,
|
||||
urukul.SPIT_DDS_WR, self.chip_select)
|
||||
for i in range(len(data) - 1):
|
||||
self.bus.write(data[i])
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG | spi.SPI_END, 32, urukul.SPIT_DDS_WR, self.chip_select
|
||||
)
|
||||
self.bus.set_config_mu(urukul.SPI_CONFIG | spi.SPI_END, 32,
|
||||
urukul.SPIT_DDS_WR, self.chip_select)
|
||||
self.bus.write(data[len(data) - 1])
|
||||
|
||||
@kernel
|
||||
@ -408,53 +353,43 @@ class AD9910:
|
||||
|
||||
The profile to read from and the step, start, and end address
|
||||
need to be configured before and separately using
|
||||
:meth:`set_profile_ram` and the parent CPLD
|
||||
:meth:`set_profile_ram` and the parent CPLD
|
||||
:meth:`~artiq.coredevice.urukul.CPLD.set_profile`.
|
||||
|
||||
:param data: List to be filled with data read from RAM.
|
||||
"""
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG, 8, urukul.SPIT_DDS_WR, self.chip_select
|
||||
)
|
||||
self.bus.set_config_mu(urukul.SPI_CONFIG, 8, urukul.SPIT_DDS_WR,
|
||||
self.chip_select)
|
||||
self.bus.write((_AD9910_REG_RAM | 0x80) << 24)
|
||||
n = len(data) - 1
|
||||
if n > 0:
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG | spi.SPI_INPUT,
|
||||
32,
|
||||
urukul.SPIT_DDS_RD,
|
||||
self.chip_select,
|
||||
)
|
||||
self.bus.set_config_mu(urukul.SPI_CONFIG | spi.SPI_INPUT, 32,
|
||||
urukul.SPIT_DDS_RD, self.chip_select)
|
||||
preload = min(n, 8)
|
||||
for i in range(n):
|
||||
self.bus.write(0)
|
||||
if i >= preload:
|
||||
data[i - preload] = self.bus.read()
|
||||
self.bus.set_config_mu(
|
||||
urukul.SPI_CONFIG | spi.SPI_INPUT | spi.SPI_END,
|
||||
32,
|
||||
urukul.SPIT_DDS_RD,
|
||||
self.chip_select,
|
||||
)
|
||||
urukul.SPI_CONFIG | spi.SPI_INPUT | spi.SPI_END, 32,
|
||||
urukul.SPIT_DDS_RD, self.chip_select)
|
||||
self.bus.write(0)
|
||||
for i in range(preload + 1):
|
||||
data[(n - preload) + i] = self.bus.read()
|
||||
|
||||
@kernel
|
||||
def set_cfr1(
|
||||
self,
|
||||
power_down: TInt32 = 0b0000,
|
||||
phase_autoclear: TInt32 = 0,
|
||||
drg_load_lrr: TInt32 = 0,
|
||||
drg_autoclear: TInt32 = 0,
|
||||
phase_clear: TInt32 = 0,
|
||||
internal_profile: TInt32 = 0,
|
||||
ram_destination: TInt32 = 0,
|
||||
ram_enable: TInt32 = 0,
|
||||
manual_osk_external: TInt32 = 0,
|
||||
osk_enable: TInt32 = 0,
|
||||
select_auto_osk: TInt32 = 0,
|
||||
):
|
||||
def set_cfr1(self,
|
||||
power_down: TInt32 = 0b0000,
|
||||
phase_autoclear: TInt32 = 0,
|
||||
drg_load_lrr: TInt32 = 0,
|
||||
drg_autoclear: TInt32 = 0,
|
||||
phase_clear: TInt32 = 0,
|
||||
internal_profile: TInt32 = 0,
|
||||
ram_destination: TInt32 = 0,
|
||||
ram_enable: TInt32 = 0,
|
||||
manual_osk_external: TInt32 = 0,
|
||||
osk_enable: TInt32 = 0,
|
||||
select_auto_osk: TInt32 = 0):
|
||||
"""Set CFR1. See the AD9910 datasheet for parameter meanings and sizes.
|
||||
|
||||
This method does not pulse ``IO_UPDATE.``
|
||||
@ -473,34 +408,30 @@ class AD9910:
|
||||
:param osk_enable: Enable OSK mode.
|
||||
:param select_auto_osk: Select manual or automatic OSK mode.
|
||||
"""
|
||||
self.write32(
|
||||
_AD9910_REG_CFR1,
|
||||
(ram_enable << 31)
|
||||
| (ram_destination << 29)
|
||||
| (manual_osk_external << 23)
|
||||
| (internal_profile << 17)
|
||||
| (drg_load_lrr << 15)
|
||||
| (drg_autoclear << 14)
|
||||
| (phase_autoclear << 13)
|
||||
| (phase_clear << 11)
|
||||
| (osk_enable << 9)
|
||||
| (select_auto_osk << 8)
|
||||
| (power_down << 4)
|
||||
| 2,
|
||||
) # SDIO input only, MSB first
|
||||
self.write32(_AD9910_REG_CFR1,
|
||||
(ram_enable << 31) |
|
||||
(ram_destination << 29) |
|
||||
(manual_osk_external << 23) |
|
||||
(internal_profile << 17) |
|
||||
(drg_load_lrr << 15) |
|
||||
(drg_autoclear << 14) |
|
||||
(phase_autoclear << 13) |
|
||||
(phase_clear << 11) |
|
||||
(osk_enable << 9) |
|
||||
(select_auto_osk << 8) |
|
||||
(power_down << 4) |
|
||||
2) # SDIO input only, MSB first
|
||||
|
||||
@kernel
|
||||
def set_cfr2(
|
||||
self,
|
||||
asf_profile_enable: TInt32 = 1,
|
||||
drg_destination: TInt32 = 0,
|
||||
drg_enable: TInt32 = 0,
|
||||
drg_nodwell_high: TInt32 = 0,
|
||||
drg_nodwell_low: TInt32 = 0,
|
||||
effective_ftw: TInt32 = 1,
|
||||
sync_validation_disable: TInt32 = 0,
|
||||
matched_latency_enable: TInt32 = 0,
|
||||
):
|
||||
def set_cfr2(self,
|
||||
asf_profile_enable: TInt32 = 1,
|
||||
drg_destination: TInt32 = 0,
|
||||
drg_enable: TInt32 = 0,
|
||||
drg_nodwell_high: TInt32 = 0,
|
||||
drg_nodwell_low: TInt32 = 0,
|
||||
effective_ftw: TInt32 = 1,
|
||||
sync_validation_disable: TInt32 = 0,
|
||||
matched_latency_enable: TInt32 = 0):
|
||||
"""Set CFR2. See the AD9910 datasheet for parameter meanings and sizes.
|
||||
|
||||
This method does not pulse ``IO_UPDATE``.
|
||||
@ -519,24 +450,22 @@ class AD9910:
|
||||
* matched_latency_enable = 0: in the order listed
|
||||
* matched_latency_enable = 1: simultaneously.
|
||||
"""
|
||||
self.write32(
|
||||
_AD9910_REG_CFR2,
|
||||
(asf_profile_enable << 24)
|
||||
| (drg_destination << 20)
|
||||
| (drg_enable << 19)
|
||||
| (drg_nodwell_high << 18)
|
||||
| (drg_nodwell_low << 17)
|
||||
| (effective_ftw << 16)
|
||||
| (matched_latency_enable << 7)
|
||||
| (sync_validation_disable << 5),
|
||||
)
|
||||
self.write32(_AD9910_REG_CFR2,
|
||||
(asf_profile_enable << 24) |
|
||||
(drg_destination << 20) |
|
||||
(drg_enable << 19) |
|
||||
(drg_nodwell_high << 18) |
|
||||
(drg_nodwell_low << 17) |
|
||||
(effective_ftw << 16) |
|
||||
(matched_latency_enable << 7) |
|
||||
(sync_validation_disable << 5))
|
||||
|
||||
@kernel
|
||||
def init(self, blind: TBool = 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``
|
||||
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.
|
||||
@ -565,13 +494,9 @@ class AD9910:
|
||||
# sync timing validation disable (enabled later)
|
||||
self.set_cfr2(sync_validation_disable=1)
|
||||
self.cpld.io_update.pulse(1 * us)
|
||||
cfr3 = (
|
||||
0x0807C000
|
||||
| (self.pll_vco << 24)
|
||||
| (self.pll_cp << 19)
|
||||
| (self.pll_en << 8)
|
||||
| (self.pll_n << 1)
|
||||
)
|
||||
cfr3 = (0x0807c000 | (self.pll_vco << 24) |
|
||||
(self.pll_cp << 19) | (self.pll_en << 8) |
|
||||
(self.pll_n << 1))
|
||||
self.write32(_AD9910_REG_CFR3, cfr3 | 0x400) # PFD reset
|
||||
self.cpld.io_update.pulse(1 * us)
|
||||
if self.pll_en:
|
||||
@ -604,16 +529,11 @@ class AD9910:
|
||||
self.cpld.io_update.pulse(1 * us)
|
||||
|
||||
@kernel
|
||||
def set_mu(
|
||||
self,
|
||||
ftw: TInt32 = 0,
|
||||
pow_: TInt32 = 0,
|
||||
asf: TInt32 = 0x3FFF,
|
||||
phase_mode: TInt32 = _PHASE_MODE_DEFAULT,
|
||||
ref_time_mu: TInt64 = int64(-1),
|
||||
profile: TInt32 = DEFAULT_PROFILE,
|
||||
ram_destination: TInt32 = -1,
|
||||
) -> TInt32:
|
||||
def set_mu(self, ftw: TInt32 = 0, pow_: TInt32 = 0, asf: TInt32 = 0x3FFF,
|
||||
phase_mode: TInt32 = _PHASE_MODE_DEFAULT,
|
||||
ref_time_mu: TInt64 = int64(-1),
|
||||
profile: TInt32 = DEFAULT_PROFILE,
|
||||
ram_destination: TInt32 = -1) -> TInt32:
|
||||
"""Set DDS data in machine units.
|
||||
|
||||
This uses machine units (FTW, POW, ASF). The frequency tuning word
|
||||
@ -663,9 +583,8 @@ class AD9910:
|
||||
dt = int32(now_mu()) - int32(ref_time_mu)
|
||||
pow_ += dt * ftw * self.sysclk_per_mu >> 16
|
||||
if ram_destination == -1:
|
||||
self.write64(
|
||||
_AD9910_REG_PROFILE0 + profile, (asf << 16) | (pow_ & 0xFFFF), ftw
|
||||
)
|
||||
self.write64(_AD9910_REG_PROFILE0 + profile,
|
||||
(asf << 16) | (pow_ & 0xFFFF), ftw)
|
||||
else:
|
||||
if not ram_destination == RAM_DEST_FTW:
|
||||
self.set_ftw(ftw)
|
||||
@ -683,9 +602,8 @@ class AD9910:
|
||||
return pow_
|
||||
|
||||
@kernel
|
||||
def get_mu(
|
||||
self, profile: TInt32 = DEFAULT_PROFILE
|
||||
) -> TTuple([TInt32, TInt32, TInt32]):
|
||||
def get_mu(self, profile: TInt32 = DEFAULT_PROFILE
|
||||
) -> TTuple([TInt32, TInt32, TInt32]):
|
||||
"""Get the frequency tuning word, phase offset word,
|
||||
and amplitude scale factor.
|
||||
|
||||
@ -704,16 +622,10 @@ class AD9910:
|
||||
return ftw, pow_, asf
|
||||
|
||||
@kernel
|
||||
def set_profile_ram(
|
||||
self,
|
||||
start: TInt32,
|
||||
end: TInt32,
|
||||
step: TInt32 = 1,
|
||||
profile: TInt32 = _DEFAULT_PROFILE_RAM,
|
||||
nodwell_high: TInt32 = 0,
|
||||
zero_crossing: TInt32 = 0,
|
||||
mode: TInt32 = 1,
|
||||
):
|
||||
def set_profile_ram(self, start: TInt32, end: TInt32, step: TInt32 = 1,
|
||||
profile: TInt32 = _DEFAULT_PROFILE_RAM,
|
||||
nodwell_high: TInt32 = 0, zero_crossing: TInt32 = 0,
|
||||
mode: TInt32 = 1):
|
||||
"""Set the RAM profile settings. See also AD9910 datasheet.
|
||||
|
||||
:param start: Profile start address in RAM (10-bit).
|
||||
@ -732,13 +644,8 @@ class AD9910:
|
||||
:const:`RAM_MODE_RAMPUP`)
|
||||
"""
|
||||
hi = (step << 8) | (end >> 2)
|
||||
lo = (
|
||||
(end << 30)
|
||||
| (start << 14)
|
||||
| (nodwell_high << 5)
|
||||
| (zero_crossing << 3)
|
||||
| mode
|
||||
)
|
||||
lo = ((end << 30) | (start << 14) | (nodwell_high << 5) |
|
||||
(zero_crossing << 3) | mode)
|
||||
self.write64(_AD9910_REG_PROFILE0 + profile, hi, lo)
|
||||
|
||||
@kernel
|
||||
@ -876,9 +783,8 @@ class AD9910:
|
||||
ram[i] = self.amplitude_to_asf(amplitude[i]) << 18
|
||||
|
||||
@portable(flags={"fast-math"})
|
||||
def turns_amplitude_to_ram(
|
||||
self, turns: TList(TFloat), amplitude: TList(TFloat), ram: TList(TInt32)
|
||||
):
|
||||
def turns_amplitude_to_ram(self, turns: TList(TFloat),
|
||||
amplitude: TList(TFloat), ram: TList(TInt32)):
|
||||
"""Convert phase and amplitude values to RAM profile data.
|
||||
|
||||
To be used with :const:`RAM_DEST_POWASF`.
|
||||
@ -889,9 +795,8 @@ class AD9910:
|
||||
Suitable for :meth:`write_ram`.
|
||||
"""
|
||||
for i in range(len(ram)):
|
||||
ram[i] = (self.turns_to_pow(turns[i]) << 16) | self.amplitude_to_asf(
|
||||
amplitude[i]
|
||||
) << 2
|
||||
ram[i] = ((self.turns_to_pow(turns[i]) << 16) |
|
||||
self.amplitude_to_asf(amplitude[i]) << 2)
|
||||
|
||||
@kernel
|
||||
def set_frequency(self, frequency: TFloat):
|
||||
@ -948,16 +853,10 @@ class AD9910:
|
||||
return self.pow_to_turns(self.get_pow())
|
||||
|
||||
@kernel
|
||||
def set(
|
||||
self,
|
||||
frequency: TFloat = 0.0,
|
||||
phase: TFloat = 0.0,
|
||||
amplitude: TFloat = 1.0,
|
||||
phase_mode: TInt32 = _PHASE_MODE_DEFAULT,
|
||||
ref_time_mu: TInt64 = int64(-1),
|
||||
profile: TInt32 = DEFAULT_PROFILE,
|
||||
ram_destination: TInt32 = -1,
|
||||
) -> TFloat:
|
||||
def set(self, frequency: TFloat = 0.0, phase: TFloat = 0.0,
|
||||
amplitude: TFloat = 1.0, phase_mode: TInt32 = _PHASE_MODE_DEFAULT,
|
||||
ref_time_mu: TInt64 = int64(-1), profile: TInt32 = DEFAULT_PROFILE,
|
||||
ram_destination: TInt32 = -1) -> TFloat:
|
||||
"""Set DDS data in SI units.
|
||||
|
||||
See also :meth:`AD9910.set_mu`.
|
||||
@ -971,22 +870,14 @@ class AD9910:
|
||||
:param ram_destination: RAM destination.
|
||||
:return: Resulting phase offset in turns
|
||||
"""
|
||||
return self.pow_to_turns(
|
||||
self.set_mu(
|
||||
self.frequency_to_ftw(frequency),
|
||||
self.turns_to_pow(phase),
|
||||
self.amplitude_to_asf(amplitude),
|
||||
phase_mode,
|
||||
ref_time_mu,
|
||||
profile,
|
||||
ram_destination,
|
||||
)
|
||||
)
|
||||
return self.pow_to_turns(self.set_mu(
|
||||
self.frequency_to_ftw(frequency), self.turns_to_pow(phase),
|
||||
self.amplitude_to_asf(amplitude), phase_mode, ref_time_mu,
|
||||
profile, ram_destination))
|
||||
|
||||
@kernel
|
||||
def get(
|
||||
self, profile: TInt32 = DEFAULT_PROFILE
|
||||
) -> TTuple([TFloat, TFloat, TFloat]):
|
||||
def get(self, profile: TInt32 = DEFAULT_PROFILE
|
||||
) -> TTuple([TFloat, TFloat, TFloat]):
|
||||
"""Get the frequency, phase, and amplitude.
|
||||
|
||||
See also :meth:`AD9910.get_mu`.
|
||||
@ -998,11 +889,8 @@ class AD9910:
|
||||
# Get values
|
||||
ftw, pow_, asf = self.get_mu(profile)
|
||||
# Convert and return
|
||||
return (
|
||||
self.ftw_to_frequency(ftw),
|
||||
self.pow_to_turns(pow_),
|
||||
self.asf_to_amplitude(asf),
|
||||
)
|
||||
return (self.ftw_to_frequency(ftw), self.pow_to_turns(pow_),
|
||||
self.asf_to_amplitude(asf))
|
||||
|
||||
@kernel
|
||||
def set_att_mu(self, att: TInt32):
|
||||
@ -1041,7 +929,7 @@ class AD9910:
|
||||
|
||||
@kernel
|
||||
def get_att(self) -> TFloat:
|
||||
"""Get digital step attenuator value in SI units. See also
|
||||
"""Get digital step attenuator value in SI units. See also
|
||||
:meth:`CPLD.get_channel_att <artiq.coredevice.urukul.CPLD.get_channel_att>`.
|
||||
|
||||
:return: Attenuation in dB.
|
||||
@ -1104,7 +992,10 @@ class AD9910:
|
||||
self.cpld.cfg_att_en(self.chip_select - 4, state)
|
||||
|
||||
@kernel
|
||||
def set_sync(self, in_delay: TInt32, window: TInt32, en_sync_gen: TInt32 = 0):
|
||||
def set_sync(self,
|
||||
in_delay: TInt32,
|
||||
window: TInt32,
|
||||
en_sync_gen: TInt32 = 0):
|
||||
"""Set the relevant parameters in the multi device synchronization
|
||||
register. See the AD9910 datasheet for details. The ``SYNC`` clock
|
||||
generator preset value is set to zero, and the ``SYNC_OUT`` generator is
|
||||
@ -1117,16 +1008,14 @@ class AD9910:
|
||||
(``SYNC_OUT``, cf. ``sync_sel == 1``). Should be left off for the normal
|
||||
use case, where the ``SYNC`` clock is supplied by the core device.
|
||||
"""
|
||||
self.write32(
|
||||
_AD9910_REG_SYNC,
|
||||
(window << 28) # SYNC S/H validation delay
|
||||
| (1 << 27) # SYNC receiver enable
|
||||
| (en_sync_gen << 26) # SYNC generator enable
|
||||
| (0 << 25) # SYNC generator SYS rising edge
|
||||
| (0 << 18) # SYNC preset
|
||||
| (0 << 11) # SYNC output delay
|
||||
| (in_delay << 3),
|
||||
) # SYNC receiver delay
|
||||
self.write32(_AD9910_REG_SYNC,
|
||||
(window << 28) | # SYNC S/H validation delay
|
||||
(1 << 27) | # SYNC receiver enable
|
||||
(en_sync_gen << 26) | # SYNC generator enable
|
||||
(0 << 25) | # SYNC generator SYS rising edge
|
||||
(0 << 18) | # SYNC preset
|
||||
(0 << 11) | # SYNC output delay
|
||||
(in_delay << 3)) # SYNC receiver delay
|
||||
|
||||
@kernel
|
||||
def clear_smp_err(self):
|
||||
@ -1145,7 +1034,8 @@ class AD9910:
|
||||
self.cpld.io_update.pulse(1 * us)
|
||||
|
||||
@kernel
|
||||
def tune_sync_delay(self, search_seed: TInt32 = 15) -> TTuple([TInt32, TInt32]):
|
||||
def tune_sync_delay(self,
|
||||
search_seed: TInt32 = 15) -> TTuple([TInt32, TInt32]):
|
||||
"""Find a stable ``SYNC_IN`` delay.
|
||||
|
||||
This method first locates a valid ``SYNC_IN`` delay at zero validation
|
||||
@ -1201,9 +1091,8 @@ class AD9910:
|
||||
raise ValueError("no valid window/delay")
|
||||
|
||||
@kernel
|
||||
def measure_io_update_alignment(
|
||||
self, delay_start: TInt64, delay_stop: TInt64
|
||||
) -> TInt32:
|
||||
def measure_io_update_alignment(self, delay_start: TInt64,
|
||||
delay_stop: TInt64) -> TInt32:
|
||||
"""Use the digital ramp generator to locate the alignment between
|
||||
``IO_UPDATE`` and ``SYNC_CLK``.
|
||||
|
||||
@ -1275,9 +1164,11 @@ class AD9910:
|
||||
for j in range(repeat):
|
||||
t1[0] += self.measure_io_update_alignment(i, i + 1)
|
||||
t1[1] += self.measure_io_update_alignment(i + 1, i + 2)
|
||||
if (t1[0] == 0 and t1[1] == 0) or (t1[0] == repeat and t1[1] == repeat):
|
||||
if ((t1[0] == 0 and t1[1] == 0) or
|
||||
(t1[0] == repeat and t1[1] == repeat)):
|
||||
# edge is not close to i + 1, can't interpret result
|
||||
raise ValueError("no clear IO_UPDATE-SYNC_CLK alignment edge found")
|
||||
raise ValueError(
|
||||
"no clear IO_UPDATE-SYNC_CLK alignment edge found")
|
||||
else:
|
||||
# the good delay is period//2 after the edge
|
||||
return (i + 1 + period // 2) & (period - 1)
|
||||
|
@ -8,16 +8,10 @@ from artiq.language.core import at_mu, delay, kernel, now_mu, portable
|
||||
from artiq.language.types import TBool, TFloat, TInt32, TInt64
|
||||
from artiq.language.units import ms, us
|
||||
|
||||
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_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
|
||||
@ -693,23 +687,11 @@ class CPLD:
|
||||
|
||||
kernel_invariants = {"refclk", "bus", "core", "io_update", "clk_div"}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
dmgr,
|
||||
spi_device,
|
||||
io_update_device=None,
|
||||
dds_reset_device=None,
|
||||
sync_device=None,
|
||||
sync_sel=0,
|
||||
clk_sel=0,
|
||||
clk_div=0,
|
||||
rf_sw=0,
|
||||
refclk=125e6,
|
||||
att=0x00000000,
|
||||
sync_div=None,
|
||||
proto_rev=0x08,
|
||||
core_device="core",
|
||||
):
|
||||
def __init__(self, dmgr, spi_device, io_update_device=None,
|
||||
dds_reset_device=None, sync_device=None,
|
||||
sync_sel=0, clk_sel=0, clk_div=0, rf_sw=0,
|
||||
refclk=125e6, att=0x00000000, sync_div=None,
|
||||
proto_rev=0x08, core_device="core"):
|
||||
|
||||
self.core = dmgr.get(core_device)
|
||||
self.refclk = refclk
|
||||
@ -901,13 +883,14 @@ class CPLD:
|
||||
self.set_all_att_mu(a)
|
||||
|
||||
@kernel
|
||||
def set_all_att_mu(self, att_reg: TInt32):
|
||||
def set_all_att_mu(self, att_reg: TInt32):
|
||||
"""Set all four digital step attenuators (in machine units).
|
||||
See also :meth:`set_att_mu`.
|
||||
|
||||
:param att_reg: Attenuator setting string (32-bit)
|
||||
"""
|
||||
self.bus.set_config_mu(SPI_CONFIG | spi.SPI_END, 32, SPIT_ATT_WR, CS_ATT)
|
||||
self.bus.set_config_mu(SPI_CONFIG | spi.SPI_END, 32,
|
||||
SPIT_ATT_WR, CS_ATT)
|
||||
self.bus.write(att_reg)
|
||||
self.att_reg = att_reg
|
||||
|
||||
@ -935,9 +918,11 @@ class CPLD:
|
||||
|
||||
:return: 32-bit attenuator settings
|
||||
"""
|
||||
self.bus.set_config_mu(SPI_CONFIG | spi.SPI_INPUT, 32, SPIT_ATT_RD, CS_ATT)
|
||||
self.bus.set_config_mu(SPI_CONFIG | spi.SPI_INPUT, 32,
|
||||
SPIT_ATT_RD, CS_ATT)
|
||||
self.bus.write(0) # shift in zeros, shift out current value
|
||||
self.bus.set_config_mu(SPI_CONFIG | spi.SPI_END, 32, SPIT_ATT_WR, CS_ATT)
|
||||
self.bus.set_config_mu(SPI_CONFIG | spi.SPI_END, 32,
|
||||
SPIT_ATT_WR, CS_ATT)
|
||||
delay(10 * us)
|
||||
self.att_reg = self.bus.read()
|
||||
self.bus.write(self.att_reg) # shift in current value again and latch
|
||||
|
@ -59,9 +59,8 @@ class UrukulExp(EnvExperiment):
|
||||
t0 = self.core.get_rtio_counter_mu()
|
||||
for i in range(n):
|
||||
self.dev.cfg_sw(2, bool(i & 1))
|
||||
self.set_dataset(
|
||||
"dt", self.core.mu_to_seconds(self.core.get_rtio_counter_mu() - t0) / n
|
||||
)
|
||||
self.set_dataset("dt", self.core.mu_to_seconds(
|
||||
self.core.get_rtio_counter_mu() - t0) / n)
|
||||
|
||||
@kernel
|
||||
def switches_readback(self):
|
||||
@ -90,9 +89,8 @@ class UrukulExp(EnvExperiment):
|
||||
t0 = self.core.get_rtio_counter_mu()
|
||||
for i in range(n):
|
||||
self.dev.cfg_att_en(1, bool(i & 1))
|
||||
self.set_dataset(
|
||||
"dt", self.core.mu_to_seconds(self.core.get_rtio_counter_mu() - t0) / n
|
||||
)
|
||||
self.set_dataset("dt", self.core.mu_to_seconds(
|
||||
self.core.get_rtio_counter_mu() - t0) / n)
|
||||
|
||||
@kernel
|
||||
def att(self):
|
||||
@ -135,7 +133,8 @@ class UrukulExp(EnvExperiment):
|
||||
self.dev.init()
|
||||
# clear backing state
|
||||
self.dev.att_reg = 0
|
||||
att_set = [int32(0x21), int32(0x43), int32(0x65), int32(0x87)]
|
||||
att_set = [int32(0x21), int32(0x43),
|
||||
int32(0x65), int32(0x87)]
|
||||
# set individual attenuators
|
||||
for i in range(len(att_set)):
|
||||
self.dev.set_att_mu(i, att_set[i])
|
||||
@ -158,9 +157,8 @@ class UrukulExp(EnvExperiment):
|
||||
t0 = self.core.get_rtio_counter_mu()
|
||||
for i in range(n):
|
||||
self.dev.set_att(3, 30 * dB)
|
||||
self.set_dataset(
|
||||
"dt", self.core.mu_to_seconds(self.core.get_rtio_counter_mu() - t0) / n
|
||||
)
|
||||
self.set_dataset("dt", self.core.mu_to_seconds(
|
||||
self.core.get_rtio_counter_mu() - t0) / n)
|
||||
|
||||
@kernel
|
||||
def osk(self):
|
||||
@ -179,9 +177,8 @@ class UrukulExp(EnvExperiment):
|
||||
t0 = self.core.get_rtio_counter_mu()
|
||||
for i in range(n):
|
||||
self.dev.cfg_osk(1, bool(i & 1))
|
||||
self.set_dataset(
|
||||
"dt", self.core.mu_to_seconds(self.core.get_rtio_counter_mu() - t0) / n
|
||||
)
|
||||
self.set_dataset("dt", self.core.mu_to_seconds(
|
||||
self.core.get_rtio_counter_mu() - t0) / n)
|
||||
|
||||
@kernel
|
||||
def drctl(self):
|
||||
@ -200,9 +197,8 @@ class UrukulExp(EnvExperiment):
|
||||
t0 = self.core.get_rtio_counter_mu()
|
||||
for i in range(n):
|
||||
self.dev.cfg_drctl(2, bool(i & 1))
|
||||
self.set_dataset(
|
||||
"dt", self.core.mu_to_seconds(self.core.get_rtio_counter_mu() - t0) / n
|
||||
)
|
||||
self.set_dataset("dt", self.core.mu_to_seconds(
|
||||
self.core.get_rtio_counter_mu() - t0) / n)
|
||||
|
||||
@kernel
|
||||
def drhold(self):
|
||||
@ -221,9 +217,8 @@ class UrukulExp(EnvExperiment):
|
||||
t0 = self.core.get_rtio_counter_mu()
|
||||
for i in range(n):
|
||||
self.dev.cfg_drhold(1, bool(i & 1))
|
||||
self.set_dataset(
|
||||
"dt", self.core.mu_to_seconds(self.core.get_rtio_counter_mu() - t0) / n
|
||||
)
|
||||
self.set_dataset("dt", self.core.mu_to_seconds(
|
||||
self.core.get_rtio_counter_mu() - t0) / n)
|
||||
|
||||
@kernel
|
||||
def mask_nu(self):
|
||||
@ -242,9 +237,8 @@ class UrukulExp(EnvExperiment):
|
||||
t0 = self.core.get_rtio_counter_mu()
|
||||
for i in range(n):
|
||||
self.dev.cfg_mask_nu(2, bool(i & 1))
|
||||
self.set_dataset(
|
||||
"dt", self.core.mu_to_seconds(self.core.get_rtio_counter_mu() - t0) / n
|
||||
)
|
||||
self.set_dataset("dt", self.core.mu_to_seconds(
|
||||
self.core.get_rtio_counter_mu() - t0) / n)
|
||||
|
||||
# Note, cfg_io_update is tested in test_ad9910.py
|
||||
@kernel
|
||||
@ -339,7 +333,7 @@ class UrukulTest(ExperimentCase):
|
||||
self.assertListEqual(att_set, self.dataset_mgr.get("att_get"))
|
||||
att_reg = self.dataset_mgr.get("att_reg")
|
||||
for att in att_set:
|
||||
self.assertEqual(att, att_reg & 0xFF)
|
||||
self.assertEqual(att, att_reg & 0xff)
|
||||
att_reg >>= 8
|
||||
|
||||
def test_att_speed(self):
|
||||
|
Loading…
Reference in New Issue
Block a user