artiq/artiq/coredevice/sawg.py

74 lines
2.4 KiB
Python

from artiq.language.core import kernel, now_mu
from artiq.coredevice.rtio import rtio_output
from artiq.language.types import TInt32, TFloat
class SAWG:
"""Smart arbitrary waveform generator channel.
:param channel_base: RTIO channel number of the first channel (amplitude).
Frequency and Phase are then assumed to be successive channels.
"""
kernel_invariants = {"amplitude_scale", "frequency_scale", "phase_scale",
"channel_base", "core"}
def __init__(self, dmgr, channel_base, parallelism=4, core_device="core"):
self.core = dmgr.get(core_device)
self.channel_base = channel_base
cordic_gain = 1.646760258057163 # Cordic(width=16, guard=None).gain
a_width = 16
f_width = 32
p_width = 16
self.amplitude_scale = (1 << a_width) / 2 / cordic_gain
self.phase_scale = 1 << p_width
self.frequency_scale = ((1 << f_width) * self.core.coarse_ref_period /
parallelism)
@kernel
def set_amplitude_mu(self, amplitude: TInt32):
"""Set DDS amplitude (machine units).
:param amplitude: DDS amplitude in machine units.
"""
rtio_output(now_mu(), self.channel_base, 0, amplitude)
@kernel(flags=["fast-math"])
def set_amplitude(self, amplitude: TFloat):
"""Set DDS amplitude.
:param amplitude: DDS amplitude relative to full-scale.
"""
self.set_amplitude_mu(int(round(amplitude*self.amplitude_scale)))
@kernel
def set_frequency_mu(self, frequency: TInt32):
"""Set DDS frequency (machine units).
:param frequency: DDS frequency in machine units.
"""
rtio_output(now_mu(), self.channel_base + 1, 0, frequency)
@kernel(flags=["fast-math"])
def set_frequency(self, frequency: TFloat):
"""Set DDS frequency.
:param frequency: DDS frequency in Hz.
"""
self.set_frequency_mu(int(round(frequency*self.frequency_scale)))
@kernel
def set_phase_mu(self, phase: TInt32):
"""Set DDS phase (machine units).
:param phase: DDS phase in machine units.
"""
rtio_output(now_mu(), self.channel_base + 2, 0, phase)
@kernel(flags=["fast-math"])
def set_phase(self, phase: TFloat):
"""Set DDS phase.
:param phase: DDS phase relative in turns.
"""
self.set_phase_mu(int(round(phase*self.phase_scale)))