2014-07-11 00:13:37 +08:00
|
|
|
from artiq.language.core import *
|
2014-05-31 00:20:13 +08:00
|
|
|
from artiq.language.units import *
|
2014-09-12 15:36:17 +08:00
|
|
|
from artiq.devices import rtio_core
|
2014-05-31 00:20:13 +08:00
|
|
|
|
2014-09-05 12:03:22 +08:00
|
|
|
|
2014-08-13 18:30:57 +08:00
|
|
|
class DDS(AutoContext):
|
2014-09-30 17:38:52 +08:00
|
|
|
"""Core device Direct Digital Synthesis (DDS) driver.
|
|
|
|
|
2014-09-30 18:10:40 +08:00
|
|
|
Controls DDS devices managed directly by the core device's runtime. It also
|
|
|
|
uses a RTIO channel (through :class:`artiq.devices.rtio_core.RTIOOut`) to
|
|
|
|
control a RF switch that gates the output of the DDS device.
|
2014-09-30 17:38:52 +08:00
|
|
|
|
|
|
|
:param dds_sysclk: DDS system frequency, used for computing the frequency
|
|
|
|
tuning words.
|
|
|
|
:param reg_channel: channel number of the DDS device to control.
|
|
|
|
:param rtio_channel: RTIO channel number of the RF switch associated with
|
|
|
|
the DDS device.
|
|
|
|
|
|
|
|
"""
|
2014-09-05 12:03:22 +08:00
|
|
|
parameters = "dds_sysclk reg_channel rtio_channel"
|
2014-05-31 00:20:13 +08:00
|
|
|
|
2014-09-05 12:03:22 +08:00
|
|
|
def build(self):
|
2014-09-12 15:36:17 +08:00
|
|
|
self.previous_frequency = 0*MHz
|
|
|
|
self.sw = rtio_core.RTIOOut(self, channel=self.rtio_channel)
|
2014-05-31 00:20:13 +08:00
|
|
|
|
2014-10-06 17:23:00 +08:00
|
|
|
kernel_attr = "previous_frequency"
|
2014-05-31 00:20:13 +08:00
|
|
|
|
2014-09-05 12:03:22 +08:00
|
|
|
@kernel
|
2014-09-12 15:36:17 +08:00
|
|
|
def on(self, frequency):
|
2014-09-30 17:38:52 +08:00
|
|
|
"""Sets the DDS channel to the specified frequency and turns it on.
|
|
|
|
|
|
|
|
If the DDS channel was already on, a real-time frequency update is
|
|
|
|
performed.
|
|
|
|
|
|
|
|
"""
|
2014-09-12 15:36:17 +08:00
|
|
|
if self.previous_frequency != frequency:
|
2014-10-06 23:28:56 +08:00
|
|
|
if self.sw.previous_timestamp != time_to_cycles(now()):
|
2014-09-12 15:36:17 +08:00
|
|
|
self.sw.sync()
|
|
|
|
if self.sw.previous_value:
|
|
|
|
# Channel is already on.
|
|
|
|
# Precise timing of frequency change is required.
|
2014-10-06 23:28:56 +08:00
|
|
|
fud_time = time_to_cycles(now())
|
2014-09-12 15:36:17 +08:00
|
|
|
else:
|
|
|
|
# Channel is off.
|
|
|
|
# Use soft timing on FUD to prevent conflicts when
|
|
|
|
# reprogramming several channels that need to be turned on at
|
|
|
|
# the same time.
|
|
|
|
fud_time = -1
|
2014-09-05 12:03:22 +08:00
|
|
|
syscall("dds_program", self.reg_channel,
|
2014-09-12 15:36:17 +08:00
|
|
|
int(2**32*frequency/self.dds_sysclk),
|
|
|
|
fud_time)
|
|
|
|
self.previous_frequency = frequency
|
|
|
|
self.sw.on()
|
2014-09-09 22:00:51 +08:00
|
|
|
|
|
|
|
@kernel
|
2014-09-12 15:36:17 +08:00
|
|
|
def off(self):
|
2014-09-30 17:38:52 +08:00
|
|
|
"""Turns the DDS channel off.
|
|
|
|
|
|
|
|
"""
|
2014-09-12 15:36:17 +08:00
|
|
|
self.sw.off()
|
2014-09-09 22:00:51 +08:00
|
|
|
|
|
|
|
@kernel
|
2014-09-12 15:36:17 +08:00
|
|
|
def pulse(self, frequency, duration):
|
2014-09-30 17:38:52 +08:00
|
|
|
"""Pulses the DDS channel for the specified duration at the specified
|
|
|
|
frequency.
|
|
|
|
|
|
|
|
Equivalent to a ``on``, ``delay``, ``off`` sequence.
|
|
|
|
|
|
|
|
"""
|
2014-09-12 15:36:17 +08:00
|
|
|
self.on(frequency)
|
|
|
|
delay(duration)
|
|
|
|
self.off()
|