forked from M-Labs/artiq
1
0
Fork 0
artiq/artiq/coredevice/dds.py

121 lines
3.8 KiB
Python
Raw Normal View History

from artiq.language.core import *
from artiq.language.db import *
2014-05-31 00:20:13 +08:00
from artiq.language.units import *
2014-09-05 12:03:22 +08:00
2014-11-21 04:32:56 +08:00
PHASE_MODE_DEFAULT = -1
# keep in sync with dds.h
2014-11-21 04:32:56 +08:00
PHASE_MODE_CONTINUOUS = 0
PHASE_MODE_ABSOLUTE = 1
PHASE_MODE_TRACKING = 2
2015-05-09 14:47:40 +08:00
class _BatchContextManager:
def __init__(self, dds_bus):
self.dds_bus = dds_bus
@kernel
def __enter__(self):
self.dds_bus.batch_enter()
@kernel
def __exit__(self, type, value, traceback):
self.dds_bus.batch_exit()
2015-05-08 22:17:06 +08:00
class DDSBus(AutoDB):
"""Core device Direct Digital Synthesis (DDS) bus batching driver.
Manages batching of DDS commands on a DDS shared bus."""
class DBKeys:
core = Device()
2015-05-09 14:47:40 +08:00
def build(self):
self.batch = _BatchContextManager(self)
2015-05-08 22:17:06 +08:00
@kernel
def batch_enter(self):
"""Starts a DDS command batch. All DDS commands are buffered
after this call, until ``batch_exit`` is called."""
syscall("dds_batch_enter", time_to_cycles(now()))
@kernel
def batch_exit(self):
"""Ends a DDS command batch. All buffered DDS commands are issued
on the bus, and FUD is pulsed at the time the batch started."""
syscall("dds_batch_exit")
class DDS(AutoDB):
2014-09-30 17:38:52 +08:00
"""Core device Direct Digital Synthesis (DDS) driver.
2015-05-08 22:17:06 +08:00
Controls one DDS channel managed directly by the core device's runtime.
2014-09-30 17:38:52 +08:00
2015-06-20 05:30:17 +08:00
:param sysclk: DDS system frequency.
:param channel: channel number of the DDS device to control.
2014-09-30 17:38:52 +08:00
"""
class DBKeys:
2015-03-08 18:37:53 +08:00
core = Device()
2015-06-20 05:30:17 +08:00
sysclk = Argument()
channel = Argument()
2014-05-31 00:20:13 +08:00
2014-09-05 12:03:22 +08:00
def build(self):
self.phase_mode = PHASE_MODE_CONTINUOUS
2014-05-31 00:20:13 +08:00
@portable
def frequency_to_ftw(self, frequency):
"""Returns the frequency tuning word corresponding to the given
frequency.
"""
2015-06-20 05:30:17 +08:00
return round(2**32*frequency/self.sysclk)
@portable
def ftw_to_frequency(self, ftw):
"""Returns the frequency corresponding to the given frequency tuning
word.
"""
2015-06-20 05:30:17 +08:00
return ftw*self.sysclk/2**32
@kernel
def init(self):
2015-05-09 17:11:34 +08:00
"""Resets and initializes the DDS channel.
The runtime does this for all channels upon core device startup."""
syscall("dds_init", time_to_cycles(now()), self.channel)
2014-09-05 12:03:22 +08:00
@kernel
2014-11-21 04:32:56 +08:00
def set_phase_mode(self, phase_mode):
"""Sets the phase mode of the DDS channel. Supported phase modes are:
* ``PHASE_MODE_CONTINUOUS``: the phase accumulator is unchanged when
switching frequencies. The DDS phase is the sum of the phase
accumulator and the phase offset. The only discrete jumps in the
DDS output phase come from changes to the phase offset.
* ``PHASE_MODE_ABSOLUTE``: the phase accumulator is reset when
switching frequencies. Thus, the phase of the DDS at the time of
the frequency change is equal to the phase offset.
* ``PHASE_MODE_TRACKING``: when switching frequencies, the phase
accumulator is set to the value it would have if the DDS had been
running at the specified frequency since the start of the
experiment.
"""
self.phase_mode = phase_mode
@kernel
def set(self, frequency, phase_mode=PHASE_MODE_DEFAULT, phase_offset=0):
"""Sets the DDS channel to the specified frequency and phase.
2014-11-21 04:32:56 +08:00
:param frequency: frequency to generate.
:param phase_mode: if specified, overrides the default phase mode set
by ``set_phase_mode`` for this call.
:param phase_offset: adds an offset, in turns, to the phase.
2014-09-30 17:38:52 +08:00
"""
if phase_mode == PHASE_MODE_DEFAULT:
phase_mode = self.phase_mode
2014-09-09 22:00:51 +08:00
syscall("dds_set", time_to_cycles(now()), self.channel,
self.frequency_to_ftw(frequency), round(phase_offset*2**14),
2015-06-21 08:42:39 +08:00
phase_mode)