forked from M-Labs/artiq
added typing and reformatted driver for ad9910, ad9912, and urukul
Signed-off-by: Leon Riesebos <leon.riesebos@duke.edu>
This commit is contained in:
parent
5ba22c11c3
commit
c22f731a61
@ -3,15 +3,15 @@ from numpy import int32, int64
|
|||||||
from artiq.language.core import (
|
from artiq.language.core import (
|
||||||
kernel, delay, portable, delay_mu, now_mu, at_mu)
|
kernel, delay, portable, delay_mu, now_mu, at_mu)
|
||||||
from artiq.language.units import us, ms
|
from artiq.language.units import us, ms
|
||||||
from artiq.language.types import *
|
from artiq.language.types import TBool, TInt32, TInt64, TFloat, TList, TTuple
|
||||||
|
|
||||||
from artiq.coredevice import spi2 as spi
|
from artiq.coredevice import spi2 as spi
|
||||||
from artiq.coredevice import urukul
|
from artiq.coredevice import urukul
|
||||||
|
|
||||||
# Work around ARTIQ-Python import machinery
|
# Work around ARTIQ-Python import machinery
|
||||||
urukul_sta_pll_lock = urukul.urukul_sta_pll_lock
|
urukul_sta_pll_lock = urukul.urukul_sta_pll_lock
|
||||||
urukul_sta_smp_err = urukul.urukul_sta_smp_err
|
urukul_sta_smp_err = urukul.urukul_sta_smp_err
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"AD9910",
|
"AD9910",
|
||||||
"PHASE_MODE_CONTINUOUS", "PHASE_MODE_ABSOLUTE", "PHASE_MODE_TRACKING",
|
"PHASE_MODE_CONTINUOUS", "PHASE_MODE_ABSOLUTE", "PHASE_MODE_TRACKING",
|
||||||
@ -20,7 +20,6 @@ __all__ = [
|
|||||||
"RAM_MODE_CONT_BIDIR_RAMP", "RAM_MODE_CONT_RAMPUP",
|
"RAM_MODE_CONT_BIDIR_RAMP", "RAM_MODE_CONT_RAMPUP",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
_PHASE_MODE_DEFAULT = -1
|
_PHASE_MODE_DEFAULT = -1
|
||||||
PHASE_MODE_CONTINUOUS = 0
|
PHASE_MODE_CONTINUOUS = 0
|
||||||
PHASE_MODE_ABSOLUTE = 1
|
PHASE_MODE_ABSOLUTE = 1
|
||||||
@ -124,15 +123,15 @@ class AD9910:
|
|||||||
To stabilize the SYNC_IN delay tuning, run :meth:`tune_sync_delay` once
|
To stabilize the SYNC_IN delay tuning, run :meth:`tune_sync_delay` once
|
||||||
and set this to the delay tap number returned (default: -1 to signal no
|
and set this to the delay tap number returned (default: -1 to signal no
|
||||||
synchronization and no tuning during :meth:`init`).
|
synchronization and no tuning during :meth:`init`).
|
||||||
Can be a string of the form "eeprom_device:byte_offset" to read the value
|
Can be a string of the form "eeprom_device:byte_offset" to read the
|
||||||
from a I2C EEPROM; in which case, `io_update_delay` must be set to the
|
value from a I2C EEPROM; in which case, `io_update_delay` must be set
|
||||||
same string value.
|
to the same string value.
|
||||||
:param io_update_delay: IO_UPDATE pulse alignment delay.
|
:param io_update_delay: IO_UPDATE pulse alignment delay.
|
||||||
To align IO_UPDATE to SYNC_CLK, run :meth:`tune_io_update_delay` and
|
To align IO_UPDATE to SYNC_CLK, run :meth:`tune_io_update_delay` and
|
||||||
set this to the delay tap number returned.
|
set this to the delay tap number returned.
|
||||||
Can be a string of the form "eeprom_device:byte_offset" to read the value
|
Can be a string of the form "eeprom_device:byte_offset" to read the
|
||||||
from a I2C EEPROM; in which case, `sync_delay_seed` must be set to the
|
value from a I2C EEPROM; in which case, `sync_delay_seed` must be set
|
||||||
same string value.
|
to the same string value.
|
||||||
"""
|
"""
|
||||||
kernel_invariants = {"chip_select", "cpld", "core", "bus",
|
kernel_invariants = {"chip_select", "cpld", "core", "bus",
|
||||||
"ftw_per_hz", "sysclk_per_mu"}
|
"ftw_per_hz", "sysclk_per_mu"}
|
||||||
@ -169,17 +168,20 @@ class AD9910:
|
|||||||
self.sysclk_per_mu = int(round(sysclk * self.core.ref_period))
|
self.sysclk_per_mu = int(round(sysclk * self.core.ref_period))
|
||||||
self.sysclk = sysclk
|
self.sysclk = sysclk
|
||||||
|
|
||||||
if isinstance(sync_delay_seed, str) or isinstance(io_update_delay, str):
|
if isinstance(sync_delay_seed, str) or isinstance(io_update_delay,
|
||||||
|
str):
|
||||||
if sync_delay_seed != io_update_delay:
|
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)
|
self.sync_data = SyncDataEeprom(dmgr, self.core, sync_delay_seed)
|
||||||
else:
|
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
|
self.phase_mode = PHASE_MODE_CONTINUOUS
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_phase_mode(self, phase_mode):
|
def set_phase_mode(self, phase_mode: TInt32):
|
||||||
r"""Set the default phase mode.
|
r"""Set the default phase mode.
|
||||||
|
|
||||||
for future calls to :meth:`set` and
|
for future calls to :meth:`set` and
|
||||||
@ -224,7 +226,7 @@ class AD9910:
|
|||||||
self.phase_mode = phase_mode
|
self.phase_mode = phase_mode
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def write16(self, addr, data):
|
def write16(self, addr: TInt32, data: TInt32):
|
||||||
"""Write to 16 bit register.
|
"""Write to 16 bit register.
|
||||||
|
|
||||||
:param addr: Register address
|
:param addr: Register address
|
||||||
@ -235,7 +237,7 @@ class AD9910:
|
|||||||
self.bus.write((addr << 24) | (data << 8))
|
self.bus.write((addr << 24) | (data << 8))
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def write32(self, addr, data):
|
def write32(self, addr: TInt32, data: TInt32):
|
||||||
"""Write to 32 bit register.
|
"""Write to 32 bit register.
|
||||||
|
|
||||||
:param addr: Register address
|
:param addr: Register address
|
||||||
@ -249,7 +251,7 @@ class AD9910:
|
|||||||
self.bus.write(data)
|
self.bus.write(data)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def read16(self, addr):
|
def read16(self, addr: TInt32) -> TInt32:
|
||||||
"""Read from 16 bit register.
|
"""Read from 16 bit register.
|
||||||
|
|
||||||
:param addr: Register address
|
:param addr: Register address
|
||||||
@ -264,7 +266,7 @@ class AD9910:
|
|||||||
return self.bus.read()
|
return self.bus.read()
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def read32(self, addr):
|
def read32(self, addr: TInt32) -> TInt32:
|
||||||
"""Read from 32 bit register.
|
"""Read from 32 bit register.
|
||||||
|
|
||||||
:param addr: Register address
|
:param addr: Register address
|
||||||
@ -279,7 +281,7 @@ class AD9910:
|
|||||||
return self.bus.read()
|
return self.bus.read()
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def read64(self, addr):
|
def read64(self, addr: TInt32) -> TInt64:
|
||||||
"""Read from 64 bit register.
|
"""Read from 64 bit register.
|
||||||
|
|
||||||
:param addr: Register address
|
:param addr: Register address
|
||||||
@ -302,7 +304,7 @@ class AD9910:
|
|||||||
return (int64(hi) << 32) | lo
|
return (int64(hi) << 32) | lo
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def write64(self, addr, data_high, data_low):
|
def write64(self, addr: TInt32, data_high: TInt32, data_low: TInt32):
|
||||||
"""Write to 64 bit register.
|
"""Write to 64 bit register.
|
||||||
|
|
||||||
:param addr: Register address
|
:param addr: Register address
|
||||||
@ -320,14 +322,14 @@ class AD9910:
|
|||||||
self.bus.write(data_low)
|
self.bus.write(data_low)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def write_ram(self, data):
|
def write_ram(self, data: TList(int32)):
|
||||||
"""Write data to RAM.
|
"""Write data to RAM.
|
||||||
|
|
||||||
The profile to write to and the step, start, and end address
|
The profile to write to and the step, start, and end address
|
||||||
need to be configured before and separately using
|
need to be configured before and separately using
|
||||||
:meth:`set_profile_ram` and the parent CPLD `set_profile`.
|
:meth:`set_profile_ram` and the parent CPLD `set_profile`.
|
||||||
|
|
||||||
:param data List(int32): Data to be written to RAM.
|
:param data: Data to be written to RAM.
|
||||||
"""
|
"""
|
||||||
self.bus.set_config_mu(urukul.SPI_CONFIG, 8, urukul.SPIT_DDS_WR,
|
self.bus.set_config_mu(urukul.SPI_CONFIG, 8, urukul.SPIT_DDS_WR,
|
||||||
self.chip_select)
|
self.chip_select)
|
||||||
@ -341,14 +343,14 @@ class AD9910:
|
|||||||
self.bus.write(data[len(data) - 1])
|
self.bus.write(data[len(data) - 1])
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def read_ram(self, data):
|
def read_ram(self, data: TList(int32)):
|
||||||
"""Read data from RAM.
|
"""Read data from RAM.
|
||||||
|
|
||||||
The profile to read from and the step, start, and end address
|
The profile to read from and the step, start, and end address
|
||||||
need to be configured before and separately using
|
need to be configured before and separately using
|
||||||
:meth:`set_profile_ram` and the parent CPLD `set_profile`.
|
:meth:`set_profile_ram` and the parent CPLD `set_profile`.
|
||||||
|
|
||||||
:param data List(int32): List to be filled with data read from RAM.
|
: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.bus.set_config_mu(urukul.SPI_CONFIG, 8, urukul.SPIT_DDS_WR,
|
||||||
self.chip_select)
|
self.chip_select)
|
||||||
@ -370,10 +372,12 @@ class AD9910:
|
|||||||
data[(n - preload) + i] = self.bus.read()
|
data[(n - preload) + i] = self.bus.read()
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_cfr1(self, power_down=0b0000, phase_autoclear=0,
|
def set_cfr1(self, power_down: TInt32 = 0b0000,
|
||||||
drg_load_lrr=0, drg_autoclear=0,
|
phase_autoclear: TInt32 = 0,
|
||||||
internal_profile=0, ram_destination=0, ram_enable=0,
|
drg_load_lrr: TInt32 = 0, drg_autoclear: TInt32 = 0,
|
||||||
manual_osk_external=0, osk_enable=0, select_auto_osk=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.
|
"""Set CFR1. See the AD9910 datasheet for parameter meanings.
|
||||||
|
|
||||||
This method does not pulse IO_UPDATE.
|
This method does not pulse IO_UPDATE.
|
||||||
@ -405,7 +409,7 @@ class AD9910:
|
|||||||
2) # SDIO input only, MSB first
|
2) # SDIO input only, MSB first
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def init(self, blind=False):
|
def init(self, blind: TBool = False):
|
||||||
"""Initialize and configure the DDS.
|
"""Initialize and configure the DDS.
|
||||||
|
|
||||||
Sets up SPI mode, confirms chip presence, powers down unused blocks,
|
Sets up SPI mode, confirms chip presence, powers down unused blocks,
|
||||||
@ -464,7 +468,7 @@ class AD9910:
|
|||||||
delay(1 * ms)
|
delay(1 * ms)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def power_down(self, bits=0b1111):
|
def power_down(self, bits: TInt32 = 0b1111):
|
||||||
"""Power down DDS.
|
"""Power down DDS.
|
||||||
|
|
||||||
:param bits: Power down bits, see datasheet
|
:param bits: Power down bits, see datasheet
|
||||||
@ -472,16 +476,15 @@ class AD9910:
|
|||||||
self.set_cfr1(power_down=bits)
|
self.set_cfr1(power_down=bits)
|
||||||
self.cpld.io_update.pulse(1 * us)
|
self.cpld.io_update.pulse(1 * us)
|
||||||
|
|
||||||
# KLUDGE: ref_time_mu default argument is explicitly marked int64() to
|
|
||||||
# avoid silent truncation of explicitly passed timestamps. (Compiler bug?)
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_mu(self, ftw, pow_=0, asf=0x3fff, phase_mode=_PHASE_MODE_DEFAULT,
|
def set_mu(self, ftw: TInt32, pow_: TInt32 = 0, asf: TInt32 = 0x3fff,
|
||||||
ref_time_mu=int64(-1), profile=0):
|
phase_mode: TInt32 = _PHASE_MODE_DEFAULT,
|
||||||
|
ref_time_mu: TInt64 = int64(-1), profile: TInt32 = 0):
|
||||||
"""Set profile 0 data in machine units.
|
"""Set profile 0 data in machine units.
|
||||||
|
|
||||||
This uses machine units (FTW, POW, ASF). The frequency tuning word
|
This uses machine units (FTW, POW, ASF). The frequency tuning word
|
||||||
width is 32, the phase offset word width is 16, and the amplitude
|
width is 32, the phase offset word width is 16, and the amplitude
|
||||||
scale factor width is 12.
|
scale factor width is 14.
|
||||||
|
|
||||||
After the SPI transfer, the shared IO update pin is pulsed to
|
After the SPI transfer, the shared IO update pin is pulsed to
|
||||||
activate the data.
|
activate the data.
|
||||||
@ -530,8 +533,9 @@ class AD9910:
|
|||||||
return pow_
|
return pow_
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_profile_ram(self, start, end, step=1, profile=0, nodwell_high=0,
|
def set_profile_ram(self, start: TInt32, end: TInt32, step: TInt32 = 1,
|
||||||
zero_crossing=0, mode=1):
|
profile: TInt32 = 0, nodwell_high: TInt32 = 0,
|
||||||
|
zero_crossing: TInt32 = 0, mode: TInt32 = 1):
|
||||||
"""Set the RAM profile settings.
|
"""Set the RAM profile settings.
|
||||||
|
|
||||||
:param start: Profile start address in RAM.
|
:param start: Profile start address in RAM.
|
||||||
@ -555,57 +559,60 @@ class AD9910:
|
|||||||
self.write64(_AD9910_REG_PROFILE0 + profile, hi, lo)
|
self.write64(_AD9910_REG_PROFILE0 + profile, hi, lo)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_ftw(self, ftw):
|
def set_ftw(self, ftw: TInt32):
|
||||||
"""Set the value stored to the AD9910's frequency tuning word (FTW) register.
|
"""Set the value stored to the AD9910's frequency tuning word (FTW)
|
||||||
|
register.
|
||||||
|
|
||||||
:param ftw: Frequency tuning word to be stored, range: 0 to 0xffffffff.
|
:param ftw: Frequency tuning word to be stored, range: 0 to 0xffffffff.
|
||||||
"""
|
"""
|
||||||
self.write32(_AD9910_REG_FTW, ftw)
|
self.write32(_AD9910_REG_FTW, ftw)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_asf(self, asf):
|
def set_asf(self, asf: TInt32):
|
||||||
"""Set the value stored to the AD9910's amplitude scale factor (ASF) register.
|
"""Set the value stored to the AD9910's amplitude scale factor (ASF)
|
||||||
|
register.
|
||||||
|
|
||||||
:param asf: Amplitude scale factor to be stored, range: 0 to 0x3fff.
|
:param asf: Amplitude scale factor to be stored, range: 0 to 0x3fff.
|
||||||
"""
|
"""
|
||||||
self.write32(_AD9910_REG_ASF, asf << 2)
|
self.write32(_AD9910_REG_ASF, asf << 2)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_pow(self, pow_):
|
def set_pow(self, pow_: TInt32):
|
||||||
"""Set the value stored to the AD9910's phase offset word (POW) register.
|
"""Set the value stored to the AD9910's phase offset word (POW)
|
||||||
|
register.
|
||||||
|
|
||||||
:param pow_: Phase offset word to be stored, range: 0 to 0xffff.
|
:param pow_: Phase offset word to be stored, range: 0 to 0xffff.
|
||||||
"""
|
"""
|
||||||
self.write16(_AD9910_REG_POW, pow_)
|
self.write16(_AD9910_REG_POW, pow_)
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def frequency_to_ftw(self, frequency) -> TInt32:
|
def frequency_to_ftw(self, frequency: TFloat) -> TInt32:
|
||||||
"""Return the 32-bit frequency tuning word corresponding to the given
|
"""Return the 32-bit frequency tuning word corresponding to the given
|
||||||
frequency.
|
frequency.
|
||||||
"""
|
"""
|
||||||
return int32(round(self.ftw_per_hz * frequency))
|
return int32(round(self.ftw_per_hz * frequency))
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def ftw_to_frequency(self, ftw):
|
def ftw_to_frequency(self, ftw: TInt32) -> TFloat:
|
||||||
"""Return the frequency corresponding to the given frequency tuning
|
"""Return the frequency corresponding to the given frequency tuning
|
||||||
word.
|
word.
|
||||||
"""
|
"""
|
||||||
return ftw / self.ftw_per_hz
|
return ftw / self.ftw_per_hz
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def turns_to_pow(self, turns) -> TInt32:
|
def turns_to_pow(self, turns: TFloat) -> TInt32:
|
||||||
"""Return the 16-bit phase offset word corresponding to the given phase
|
"""Return the 16-bit phase offset word corresponding to the given phase
|
||||||
in turns."""
|
in turns."""
|
||||||
return int32(round(turns * 0x10000)) & int32(0xffff)
|
return int32(round(turns * 0x10000)) & int32(0xffff)
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def pow_to_turns(self, pow_):
|
def pow_to_turns(self, pow_: TInt32) -> TFloat:
|
||||||
"""Return the phase in turns corresponding to a given phase offset
|
"""Return the phase in turns corresponding to a given phase offset
|
||||||
word."""
|
word."""
|
||||||
return pow_ / 0x10000
|
return pow_ / 0x10000
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def amplitude_to_asf(self, amplitude) -> TInt32:
|
def amplitude_to_asf(self, amplitude: TFloat) -> TInt32:
|
||||||
"""Return 14-bit amplitude scale factor corresponding to given
|
"""Return 14-bit amplitude scale factor corresponding to given
|
||||||
fractional amplitude."""
|
fractional amplitude."""
|
||||||
code = int32(round(amplitude * 0x3fff))
|
code = int32(round(amplitude * 0x3fff))
|
||||||
@ -614,13 +621,13 @@ class AD9910:
|
|||||||
return code
|
return code
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def asf_to_amplitude(self, asf):
|
def asf_to_amplitude(self, asf: TInt32) -> TFloat:
|
||||||
"""Return amplitude as a fraction of full scale corresponding to given
|
"""Return amplitude as a fraction of full scale corresponding to given
|
||||||
amplitude scale factor."""
|
amplitude scale factor."""
|
||||||
return asf / float(0x3fff)
|
return asf / float(0x3fff)
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def frequency_to_ram(self, frequency, ram):
|
def frequency_to_ram(self, frequency: TList(TFloat), ram: TList(TInt32)):
|
||||||
"""Convert frequency values to RAM profile data.
|
"""Convert frequency values to RAM profile data.
|
||||||
|
|
||||||
To be used with :const:`RAM_DEST_FTW`.
|
To be used with :const:`RAM_DEST_FTW`.
|
||||||
@ -633,7 +640,7 @@ class AD9910:
|
|||||||
ram[i] = self.frequency_to_ftw(frequency[i])
|
ram[i] = self.frequency_to_ftw(frequency[i])
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def turns_to_ram(self, turns, ram):
|
def turns_to_ram(self, turns: TList(TFloat), ram: TList(TInt32)):
|
||||||
"""Convert phase values to RAM profile data.
|
"""Convert phase values to RAM profile data.
|
||||||
|
|
||||||
To be used with :const:`RAM_DEST_POW`.
|
To be used with :const:`RAM_DEST_POW`.
|
||||||
@ -646,7 +653,7 @@ class AD9910:
|
|||||||
ram[i] = self.turns_to_pow(turns[i]) << 16
|
ram[i] = self.turns_to_pow(turns[i]) << 16
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def amplitude_to_ram(self, amplitude, ram):
|
def amplitude_to_ram(self, amplitude: TList(TFloat), ram: TList(TInt32)):
|
||||||
"""Convert amplitude values to RAM profile data.
|
"""Convert amplitude values to RAM profile data.
|
||||||
|
|
||||||
To be used with :const:`RAM_DEST_ASF`.
|
To be used with :const:`RAM_DEST_ASF`.
|
||||||
@ -659,7 +666,8 @@ class AD9910:
|
|||||||
ram[i] = self.amplitude_to_asf(amplitude[i]) << 18
|
ram[i] = self.amplitude_to_asf(amplitude[i]) << 18
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def turns_amplitude_to_ram(self, turns, amplitude, ram):
|
def turns_amplitude_to_ram(self, turns: TList(TFloat),
|
||||||
|
amplitude: TList(TFloat), ram: TList(TInt32)):
|
||||||
"""Convert phase and amplitude values to RAM profile data.
|
"""Convert phase and amplitude values to RAM profile data.
|
||||||
|
|
||||||
To be used with :const:`RAM_DEST_POWASF`.
|
To be used with :const:`RAM_DEST_POWASF`.
|
||||||
@ -674,32 +682,36 @@ class AD9910:
|
|||||||
self.amplitude_to_asf(amplitude[i]) << 2)
|
self.amplitude_to_asf(amplitude[i]) << 2)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_frequency(self, frequency):
|
def set_frequency(self, frequency: TFloat):
|
||||||
"""Set the value stored to the AD9910's frequency tuning word (FTW) register.
|
"""Set the value stored to the AD9910's frequency tuning word (FTW)
|
||||||
|
register.
|
||||||
|
|
||||||
:param frequency: frequency to be stored, in Hz.
|
:param frequency: frequency to be stored, in Hz.
|
||||||
"""
|
"""
|
||||||
return self.set_ftw(self.frequency_to_ftw(frequency))
|
self.set_ftw(self.frequency_to_ftw(frequency))
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_amplitude(self, amplitude):
|
def set_amplitude(self, amplitude: TFloat):
|
||||||
"""Set the value stored to the AD9910's amplitude scale factor (ASF) register.
|
"""Set the value stored to the AD9910's amplitude scale factor (ASF)
|
||||||
|
register.
|
||||||
|
|
||||||
:param amplitude: amplitude to be stored, in units of full scale.
|
:param amplitude: amplitude to be stored, in units of full scale.
|
||||||
"""
|
"""
|
||||||
return self.set_asf(self.amplitude_to_asf(amplitude))
|
self.set_asf(self.amplitude_to_asf(amplitude))
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_phase(self, turns):
|
def set_phase(self, turns: TFloat):
|
||||||
"""Set the value stored to the AD9910's phase offset word (POW) register.
|
"""Set the value stored to the AD9910's phase offset word (POW)
|
||||||
|
register.
|
||||||
|
|
||||||
:param turns: phase offset to be stored, in turns.
|
:param turns: phase offset to be stored, in turns.
|
||||||
"""
|
"""
|
||||||
return self.set_pow(self.turns_to_pow(turns))
|
self.set_pow(self.turns_to_pow(turns))
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set(self, frequency, phase=0.0, amplitude=1.0,
|
def set(self, frequency: TFloat, phase: TFloat = 0.0,
|
||||||
phase_mode=_PHASE_MODE_DEFAULT, ref_time_mu=int64(-1), profile=0):
|
amplitude: TFloat = 1.0, phase_mode: TInt32 = _PHASE_MODE_DEFAULT,
|
||||||
|
ref_time_mu: TInt64 = int64(-1), profile: TInt32 = 0):
|
||||||
"""Set profile 0 data in SI units.
|
"""Set profile 0 data in SI units.
|
||||||
|
|
||||||
.. seealso:: :meth:`set_mu`
|
.. seealso:: :meth:`set_mu`
|
||||||
@ -718,7 +730,7 @@ class AD9910:
|
|||||||
profile))
|
profile))
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_att_mu(self, att):
|
def set_att_mu(self, att: TInt32):
|
||||||
"""Set digital step attenuator in machine units.
|
"""Set digital step attenuator in machine units.
|
||||||
|
|
||||||
This method will write the attenuator settings of all four channels.
|
This method will write the attenuator settings of all four channels.
|
||||||
@ -730,7 +742,7 @@ class AD9910:
|
|||||||
self.cpld.set_att_mu(self.chip_select - 4, att)
|
self.cpld.set_att_mu(self.chip_select - 4, att)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_att(self, att):
|
def set_att(self, att: TFloat):
|
||||||
"""Set digital step attenuator in SI units.
|
"""Set digital step attenuator in SI units.
|
||||||
|
|
||||||
This method will write the attenuator settings of all four channels.
|
This method will write the attenuator settings of all four channels.
|
||||||
@ -742,7 +754,7 @@ class AD9910:
|
|||||||
self.cpld.set_att(self.chip_select - 4, att)
|
self.cpld.set_att(self.chip_select - 4, att)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def cfg_sw(self, state):
|
def cfg_sw(self, state: TInt32):
|
||||||
"""Set CPLD CFG RF switch state. The RF switch is controlled by the
|
"""Set CPLD CFG RF switch state. The RF switch is controlled by the
|
||||||
logical or of the CPLD configuration shift register
|
logical or of the CPLD configuration shift register
|
||||||
RF switch bit and the SW TTL line (if used).
|
RF switch bit and the SW TTL line (if used).
|
||||||
@ -752,7 +764,7 @@ class AD9910:
|
|||||||
self.cpld.cfg_sw(self.chip_select - 4, state)
|
self.cpld.cfg_sw(self.chip_select - 4, state)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_sync(self, in_delay, window):
|
def set_sync(self, in_delay: TInt32, window: TInt32):
|
||||||
"""Set the relevant parameters in the multi device synchronization
|
"""Set the relevant parameters in the multi device synchronization
|
||||||
register. See the AD9910 datasheet for details. The SYNC clock
|
register. See the AD9910 datasheet for details. The SYNC clock
|
||||||
generator preset value is set to zero, and the SYNC_OUT generator is
|
generator preset value is set to zero, and the SYNC_OUT generator is
|
||||||
@ -787,7 +799,8 @@ class AD9910:
|
|||||||
self.cpld.io_update.pulse(1 * us)
|
self.cpld.io_update.pulse(1 * us)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def tune_sync_delay(self, search_seed=15):
|
def tune_sync_delay(self,
|
||||||
|
search_seed: TInt32 = 15) -> TTuple([TInt32, TInt32]):
|
||||||
"""Find a stable SYNC_IN delay.
|
"""Find a stable SYNC_IN delay.
|
||||||
|
|
||||||
This method first locates a valid SYNC_IN delay at zero validation
|
This method first locates a valid SYNC_IN delay at zero validation
|
||||||
@ -843,7 +856,8 @@ class AD9910:
|
|||||||
raise ValueError("no valid window/delay")
|
raise ValueError("no valid window/delay")
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def measure_io_update_alignment(self, delay_start, delay_stop):
|
def measure_io_update_alignment(self, delay_start: TInt64,
|
||||||
|
delay_stop: TInt64) -> TInt32:
|
||||||
"""Use the digital ramp generator to locate the alignment between
|
"""Use the digital ramp generator to locate the alignment between
|
||||||
IO_UPDATE and SYNC_CLK.
|
IO_UPDATE and SYNC_CLK.
|
||||||
|
|
||||||
@ -885,7 +899,7 @@ class AD9910:
|
|||||||
return ftw & 1
|
return ftw & 1
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def tune_io_update_delay(self):
|
def tune_io_update_delay(self) -> TInt32:
|
||||||
"""Find a stable IO_UPDATE delay alignment.
|
"""Find a stable IO_UPDATE delay alignment.
|
||||||
|
|
||||||
Scan through increasing IO_UPDATE delays until a delay is found that
|
Scan through increasing IO_UPDATE delays until a delay is found that
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from numpy import int32, int64
|
from numpy import int32, int64
|
||||||
|
|
||||||
from artiq.language.types import TInt32, TInt64
|
from artiq.language.types import TInt32, TInt64, TFloat, TTuple
|
||||||
from artiq.language.core import kernel, delay, portable
|
from artiq.language.core import kernel, delay, portable
|
||||||
from artiq.language.units import ms, us, ns
|
from artiq.language.units import ms, us, ns
|
||||||
from artiq.coredevice.ad9912_reg import *
|
from artiq.coredevice.ad9912_reg import *
|
||||||
@ -44,7 +44,7 @@ class AD9912:
|
|||||||
self.ftw_per_hz = 1 / sysclk * (int64(1) << 48)
|
self.ftw_per_hz = 1 / sysclk * (int64(1) << 48)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def write(self, addr, data, length):
|
def write(self, addr: TInt32, data: TInt32, length: TInt32):
|
||||||
"""Variable length write to a register.
|
"""Variable length write to a register.
|
||||||
Up to 4 bytes.
|
Up to 4 bytes.
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ class AD9912:
|
|||||||
self.bus.write(data << (32 - length * 8))
|
self.bus.write(data << (32 - length * 8))
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def read(self, addr, length):
|
def read(self, addr: TInt32, length: TInt32) -> TInt32:
|
||||||
"""Variable length read from a register.
|
"""Variable length read from a register.
|
||||||
Up to 4 bytes.
|
Up to 4 bytes.
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ class AD9912:
|
|||||||
delay(1 * ms)
|
delay(1 * ms)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_att_mu(self, att):
|
def set_att_mu(self, att: TInt32):
|
||||||
"""Set digital step attenuator in machine units.
|
"""Set digital step attenuator in machine units.
|
||||||
|
|
||||||
This method will write the attenuator settings of all four channels.
|
This method will write the attenuator settings of all four channels.
|
||||||
@ -123,7 +123,7 @@ class AD9912:
|
|||||||
self.cpld.set_att_mu(self.chip_select - 4, att)
|
self.cpld.set_att_mu(self.chip_select - 4, att)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_att(self, att):
|
def set_att(self, att: TFloat):
|
||||||
"""Set digital step attenuator in SI units.
|
"""Set digital step attenuator in SI units.
|
||||||
|
|
||||||
This method will write the attenuator settings of all four channels.
|
This method will write the attenuator settings of all four channels.
|
||||||
@ -135,14 +135,14 @@ class AD9912:
|
|||||||
self.cpld.set_att(self.chip_select - 4, att)
|
self.cpld.set_att(self.chip_select - 4, att)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_mu(self, ftw, pow):
|
def set_mu(self, ftw: TInt64, pow_: TInt32):
|
||||||
"""Set profile 0 data in machine units.
|
"""Set profile 0 data in machine units.
|
||||||
|
|
||||||
After the SPI transfer, the shared IO update pin is pulsed to
|
After the SPI transfer, the shared IO update pin is pulsed to
|
||||||
activate the data.
|
activate the data.
|
||||||
|
|
||||||
:param ftw: Frequency tuning word: 48 bit unsigned.
|
:param ftw: Frequency tuning word: 48 bit unsigned.
|
||||||
:param pow: Phase tuning word: 16 bit unsigned.
|
:param pow_: Phase tuning word: 16 bit unsigned.
|
||||||
"""
|
"""
|
||||||
# streaming transfer of FTW and POW
|
# streaming transfer of FTW and POW
|
||||||
self.bus.set_config_mu(urukul.SPI_CONFIG, 16,
|
self.bus.set_config_mu(urukul.SPI_CONFIG, 16,
|
||||||
@ -150,47 +150,58 @@ class AD9912:
|
|||||||
self.bus.write((AD9912_POW1 << 16) | (3 << 29))
|
self.bus.write((AD9912_POW1 << 16) | (3 << 29))
|
||||||
self.bus.set_config_mu(urukul.SPI_CONFIG, 32,
|
self.bus.set_config_mu(urukul.SPI_CONFIG, 32,
|
||||||
urukul.SPIT_DDS_WR, self.chip_select)
|
urukul.SPIT_DDS_WR, self.chip_select)
|
||||||
self.bus.write((pow << 16) | (int32(ftw >> 32) & 0xffff))
|
self.bus.write((pow_ << 16) | (int32(ftw >> 32) & 0xffff))
|
||||||
self.bus.set_config_mu(urukul.SPI_CONFIG | spi.SPI_END, 32,
|
self.bus.set_config_mu(urukul.SPI_CONFIG | spi.SPI_END, 32,
|
||||||
urukul.SPIT_DDS_WR, self.chip_select)
|
urukul.SPIT_DDS_WR, self.chip_select)
|
||||||
self.bus.write(int32(ftw))
|
self.bus.write(int32(ftw))
|
||||||
self.cpld.io_update.pulse(10 * ns)
|
self.cpld.io_update.pulse(10 * ns)
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def frequency_to_ftw(self, frequency) -> TInt64:
|
def frequency_to_ftw(self, frequency: TFloat) -> TInt64:
|
||||||
"""Returns the 48-bit frequency tuning word corresponding to the given
|
"""Returns the 48-bit frequency tuning word corresponding to the given
|
||||||
frequency.
|
frequency.
|
||||||
"""
|
"""
|
||||||
return int64(round(self.ftw_per_hz*frequency)) & ((int64(1) << 48) - 1)
|
return int64(round(self.ftw_per_hz * frequency)) & (
|
||||||
|
(int64(1) << 48) - 1)
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def ftw_to_frequency(self, ftw):
|
def ftw_to_frequency(self, ftw: TInt64) -> TFloat:
|
||||||
"""Returns the frequency corresponding to the given
|
"""Returns the frequency corresponding to the given
|
||||||
frequency tuning word.
|
frequency tuning word.
|
||||||
"""
|
"""
|
||||||
return ftw / self.ftw_per_hz
|
return ftw / self.ftw_per_hz
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def turns_to_pow(self, phase) -> TInt32:
|
def turns_to_pow(self, phase: TFloat) -> TInt32:
|
||||||
"""Returns the 16-bit phase offset word corresponding to the given
|
"""Returns the 16-bit phase offset word corresponding to the given
|
||||||
phase.
|
phase.
|
||||||
"""
|
"""
|
||||||
return int32(round((1 << 14) * phase)) & 0xffff
|
return int32(round((1 << 14) * phase)) & 0xffff
|
||||||
|
|
||||||
|
@portable(flags={"fast-math"})
|
||||||
|
def pow_to_turns(self, pow_: TInt32) -> TFloat:
|
||||||
|
"""Return the phase in turns corresponding to a given phase offset
|
||||||
|
word.
|
||||||
|
|
||||||
|
:param pow_: Phase offset word.
|
||||||
|
:return: Phase in turns.
|
||||||
|
"""
|
||||||
|
return pow_ / (1 << 14)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set(self, frequency, phase=0.0):
|
def set(self, frequency: TFloat, phase: TFloat = 0.0):
|
||||||
"""Set profile 0 data in SI units.
|
"""Set profile 0 data in SI units.
|
||||||
|
|
||||||
.. seealso:: :meth:`set_mu`
|
.. seealso:: :meth:`set_mu`
|
||||||
|
|
||||||
:param ftw: Frequency in Hz
|
:param frequency: Frequency in Hz
|
||||||
:param pow: Phase tuning word in turns
|
:param phase: Phase tuning word in turns
|
||||||
"""
|
"""
|
||||||
self.set_mu(self.frequency_to_ftw(frequency),
|
self.set_mu(self.frequency_to_ftw(frequency),
|
||||||
self.turns_to_pow(phase))
|
self.turns_to_pow(phase))
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def cfg_sw(self, state):
|
def cfg_sw(self, state: TInt32):
|
||||||
"""Set CPLD CFG RF switch state. The RF switch is controlled by the
|
"""Set CPLD CFG RF switch state. The RF switch is controlled by the
|
||||||
logical or of the CPLD configuration shift register
|
logical or of the CPLD configuration shift register
|
||||||
RF switch bit and the SW TTL line (if used).
|
RF switch bit and the SW TTL line (if used).
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
from artiq.language.core import kernel, delay, portable, at_mu, now_mu
|
|
||||||
from artiq.language.units import us, ms
|
|
||||||
|
|
||||||
from numpy import int32, int64
|
from numpy import int32, int64
|
||||||
|
|
||||||
from artiq.coredevice import spi2 as spi
|
from artiq.language.core import kernel, delay, portable, at_mu, now_mu
|
||||||
|
from artiq.language.units import us, ms
|
||||||
|
from artiq.language.types import TInt32, TFloat, TBool
|
||||||
|
|
||||||
|
from artiq.coredevice import spi2 as spi
|
||||||
|
|
||||||
SPI_CONFIG = (0 * spi.SPI_OFFLINE | 0 * spi.SPI_END |
|
SPI_CONFIG = (0 * spi.SPI_OFFLINE | 0 * spi.SPI_END |
|
||||||
0 * spi.SPI_INPUT | 1 * spi.SPI_CS_POLARITY |
|
0 * spi.SPI_INPUT | 1 * spi.SPI_CS_POLARITY |
|
||||||
@ -105,7 +105,7 @@ class _RegIOUpdate:
|
|||||||
self.cpld = cpld
|
self.cpld = cpld
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def pulse(self, t):
|
def pulse(self, t: TFloat):
|
||||||
cfg = self.cpld.cfg_reg
|
cfg = self.cpld.cfg_reg
|
||||||
self.cpld.cfg_write(cfg | (1 << CFG_IO_UPDATE))
|
self.cpld.cfg_write(cfg | (1 << CFG_IO_UPDATE))
|
||||||
delay(t)
|
delay(t)
|
||||||
@ -117,7 +117,7 @@ class _DummySync:
|
|||||||
self.cpld = cpld
|
self.cpld = cpld
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_mu(self, ftw):
|
def set_mu(self, ftw: TInt32):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@ -196,12 +196,12 @@ class CPLD:
|
|||||||
self.sync_div = sync_div
|
self.sync_div = sync_div
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def cfg_write(self, cfg):
|
def cfg_write(self, cfg: TInt32):
|
||||||
"""Write to the configuration register.
|
"""Write to the configuration register.
|
||||||
|
|
||||||
See :func:`urukul_cfg` for possible flags.
|
See :func:`urukul_cfg` for possible flags.
|
||||||
|
|
||||||
:param data: 24 bit data to be written. Will be stored at
|
:param cfg: 24 bit data to be written. Will be stored at
|
||||||
:attr:`cfg_reg`.
|
:attr:`cfg_reg`.
|
||||||
"""
|
"""
|
||||||
self.bus.set_config_mu(SPI_CONFIG | spi.SPI_END, 24,
|
self.bus.set_config_mu(SPI_CONFIG | spi.SPI_END, 24,
|
||||||
@ -210,7 +210,7 @@ class CPLD:
|
|||||||
self.cfg_reg = cfg
|
self.cfg_reg = cfg
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def sta_read(self):
|
def sta_read(self) -> TInt32:
|
||||||
"""Read the status register.
|
"""Read the status register.
|
||||||
|
|
||||||
Use any of the following functions to extract values:
|
Use any of the following functions to extract values:
|
||||||
@ -229,7 +229,7 @@ class CPLD:
|
|||||||
return self.bus.read()
|
return self.bus.read()
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def init(self, blind=False):
|
def init(self, blind: TBool = False):
|
||||||
"""Initialize and detect Urukul.
|
"""Initialize and detect Urukul.
|
||||||
|
|
||||||
Resets the DDS I/O interface and verifies correct CPLD gateware
|
Resets the DDS I/O interface and verifies correct CPLD gateware
|
||||||
@ -261,7 +261,7 @@ class CPLD:
|
|||||||
self.cfg_write(self.cfg_reg & ~(1 << CFG_IO_RST))
|
self.cfg_write(self.cfg_reg & ~(1 << CFG_IO_RST))
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def cfg_sw(self, channel, on):
|
def cfg_sw(self, channel: TInt32, on: TBool):
|
||||||
"""Configure the RF switches through the configuration register.
|
"""Configure the RF switches through the configuration register.
|
||||||
|
|
||||||
These values are logically OR-ed with the LVDS lines on EEM1.
|
These values are logically OR-ed with the LVDS lines on EEM1.
|
||||||
@ -277,7 +277,7 @@ class CPLD:
|
|||||||
self.cfg_write(c)
|
self.cfg_write(c)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def cfg_switches(self, state):
|
def cfg_switches(self, state: TInt32):
|
||||||
"""Configure all four RF switches through the configuration register.
|
"""Configure all four RF switches through the configuration register.
|
||||||
|
|
||||||
:param state: RF switch state as a 4 bit integer.
|
:param state: RF switch state as a 4 bit integer.
|
||||||
@ -285,11 +285,12 @@ class CPLD:
|
|||||||
self.cfg_write((self.cfg_reg & ~0xf) | state)
|
self.cfg_write((self.cfg_reg & ~0xf) | state)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_att_mu(self, channel, att):
|
def set_att_mu(self, channel: TInt32, att: TInt32):
|
||||||
"""Set digital step attenuator in machine units.
|
"""Set digital step attenuator in machine units.
|
||||||
|
|
||||||
This method will also write the attenuator settings of the three other channels. Use
|
This method will also write the attenuator settings of the three
|
||||||
:meth:`get_att_mu` to retrieve the hardware state set in previous experiments.
|
other channels. Use :meth:`get_att_mu` to retrieve the hardware
|
||||||
|
state set in previous experiments.
|
||||||
|
|
||||||
:param channel: Attenuator channel (0-3).
|
:param channel: Attenuator channel (0-3).
|
||||||
:param att: 8-bit digital attenuation setting:
|
:param att: 8-bit digital attenuation setting:
|
||||||
@ -300,7 +301,7 @@ class CPLD:
|
|||||||
self.set_all_att_mu(a)
|
self.set_all_att_mu(a)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_all_att_mu(self, att_reg):
|
def set_all_att_mu(self, att_reg: TInt32):
|
||||||
"""Set all four digital step attenuators (in machine units).
|
"""Set all four digital step attenuators (in machine units).
|
||||||
|
|
||||||
.. seealso:: :meth:`set_att_mu`
|
.. seealso:: :meth:`set_att_mu`
|
||||||
@ -313,7 +314,7 @@ class CPLD:
|
|||||||
self.att_reg = att_reg
|
self.att_reg = att_reg
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_att(self, channel, att):
|
def set_att(self, channel: TInt32, att: TFloat):
|
||||||
"""Set digital step attenuator in SI units.
|
"""Set digital step attenuator in SI units.
|
||||||
|
|
||||||
This method will write the attenuator settings of all four channels.
|
This method will write the attenuator settings of all four channels.
|
||||||
@ -325,16 +326,16 @@ class CPLD:
|
|||||||
attenuation. Minimum attenuation is 0*dB, maximum attenuation is
|
attenuation. Minimum attenuation is 0*dB, maximum attenuation is
|
||||||
31.5*dB.
|
31.5*dB.
|
||||||
"""
|
"""
|
||||||
code = 255 - int32(round(att*8))
|
self.set_att_mu(channel, self.att_to_mu(att))
|
||||||
if code < 0 or code > 255:
|
|
||||||
raise ValueError("Invalid urukul.CPLD attenuation!")
|
|
||||||
self.set_att_mu(channel, code)
|
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def get_att_mu(self):
|
def get_att_mu(self) -> TInt32:
|
||||||
"""Return the digital step attenuator settings in machine units.
|
"""Return the digital step attenuator settings in machine units.
|
||||||
|
|
||||||
The result is stored and will be used in future calls of :meth:`set_att_mu`.
|
The result is stored and will be used in future calls of
|
||||||
|
:meth:`set_att_mu` and :meth:`set_att`.
|
||||||
|
|
||||||
|
.. seealso:: :meth:`get_channel_att_mu`
|
||||||
|
|
||||||
:return: 32 bit attenuator settings
|
:return: 32 bit attenuator settings
|
||||||
"""
|
"""
|
||||||
@ -349,7 +350,7 @@ class CPLD:
|
|||||||
return self.att_reg
|
return self.att_reg
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_sync_div(self, div):
|
def set_sync_div(self, div: TInt32):
|
||||||
"""Set the SYNC_IN AD9910 pulse generator frequency
|
"""Set the SYNC_IN AD9910 pulse generator frequency
|
||||||
and align it to the current RTIO timestamp.
|
and align it to the current RTIO timestamp.
|
||||||
|
|
||||||
@ -366,7 +367,7 @@ class CPLD:
|
|||||||
self.sync.set_mu(ftw)
|
self.sync.set_mu(ftw)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_profile(self, profile):
|
def set_profile(self, profile: TInt32):
|
||||||
"""Set the PROFILE pins.
|
"""Set the PROFILE pins.
|
||||||
|
|
||||||
The PROFILE pins are common to all four DDS channels.
|
The PROFILE pins are common to all four DDS channels.
|
||||||
|
Loading…
Reference in New Issue
Block a user