Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3b63c39d2f52
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ad3d7dc687c9
Choose a head ref
  • 3 commits
  • 6 files changed
  • 1 contributor

Commits on Jun 12, 2016

  1. Copy the full SHA
    7dff446 View commit details
  2. Copy the full SHA
    3aab77d View commit details
  3. Copy the full SHA
    ad3d7dc View commit details
Showing with 87 additions and 31 deletions.
  1. +3 −3 artiq/browser/experiments.py
  2. +1 −1 artiq/browser/files.py
  3. +7 −2 artiq/coredevice/dds.py
  4. +62 −23 artiq/coredevice/ttl.py
  5. +6 −1 artiq/language/environment.py
  6. +8 −1 artiq/master/worker_db.py
6 changes: 3 additions & 3 deletions artiq/browser/experiments.py
Original file line number Diff line number Diff line change
@@ -225,7 +225,7 @@ def dragEnterEvent(self, ev):
def dropEvent(self, ev):
for uri in ev.mimeData().urls():
if uri.scheme() == "file":
logger.info("Loading HDF5 arguments from %s", uri.path())
logger.debug("Loading HDF5 arguments from %s", uri.path())
asyncio.ensure_future(self._load_hdf5_task(uri.path()))
break

@@ -289,7 +289,7 @@ def run_clicked(self):
self._terminate.setEnabled(True)

def done(fut):
logger.info("Analysis done")
logger.debug("Analysis done")
self._run_task = None
self._run.setEnabled(True)
self._terminate.setEnabled(False)
@@ -405,7 +405,7 @@ async def _select_experiment_task(self):
except asyncio.CancelledError:
return
self.current_dir = os.path.dirname(file)
logger.info("Opening experiment %s", file)
logger.debug("Opening experiment %s", file)
try:
description = await self.examine(file)
except:
2 changes: 1 addition & 1 deletion artiq/browser/files.py
Original file line number Diff line number Diff line change
@@ -171,7 +171,7 @@ def list_current_changed(self, current, previous):
f = open_h5(info)
if not f:
return
logger.info("loading datasets from %s", info.filePath())
logger.debug("loading datasets from %s", info.filePath())
with f:
if "datasets" not in f:
return
9 changes: 7 additions & 2 deletions artiq/coredevice/dds.py
Original file line number Diff line number Diff line change
@@ -65,8 +65,8 @@ def dds_batch_enter(self):
"""Starts a DDS command batch. All DDS commands are buffered
after this call, until ``batch_exit`` is called.
The time of execution of the DDS commands is the time of entering the
batch (as closely as hardware permits)."""
The time of execution of the DDS commands is the time cursor position
when the batch is entered."""
dds_batch_enter(now_mu())

@kernel
@@ -84,6 +84,8 @@ class _DDSGeneric:
This class should not be used directly, instead, use the chip-specific
drivers such as ``AD9858`` and ``AD9914``.
The time cursor is not modified by any function in this class.
:param bus: name of the DDS bus device that this DDS is connected to.
:param channel: channel number of the DDS device to control.
"""
@@ -179,6 +181,9 @@ def set_mu(self, frequency, phase=0, phase_mode=_PHASE_MODE_DEFAULT,
chip and can be retrieved via the ``pow_width`` attribute. The amplitude
width is 12.
The "frequency update" pulse is sent to the DDS with a fixed latency
with respect to the current position of the time cursor.
:param frequency: frequency to generate.
:param phase: adds an offset, in turns, to the phase.
:param phase_mode: if specified, overrides the default phase mode set
85 changes: 62 additions & 23 deletions artiq/coredevice/ttl.py
Original file line number Diff line number Diff line change
@@ -37,26 +37,36 @@ def sync(self):

@kernel
def on(self):
"""Sets the output to a logic high state."""
"""Sets the output to a logic high state at the current position
of the time cursor.
The time cursor is not modified by this function."""
self.set_o(True)

@kernel
def off(self):
"""Set the output to a logic low state."""
"""Set the output to a logic low state at the current position
of the time cursor.
The time cursor is not modified by this function."""
self.set_o(False)

@kernel
def pulse_mu(self, duration):
"""Pulse the output high for the specified duration
(in machine units)."""
(in machine units).
The time cursor is advanced by the specified duration."""
self.on()
delay_mu(duration)
self.off()

@kernel
def pulse(self, duration):
"""Pulse the output high for the specified duration
(in seconds)."""
(in seconds).
The time cursor is advanced by the specified duration."""
self.on()
delay(duration)
self.off()
@@ -100,15 +110,17 @@ def set_oe(self, oe):

@kernel
def output(self):
"""Set the direction to output.
"""Set the direction to output at the current position of the time
cursor.
There must be a delay of at least one RTIO clock cycle before any
other command can be issued."""
self.set_oe(True)

@kernel
def input(self):
"""Set the direction to input.
"""Set the direction to input at the current position of the time
cursor.
There must be a delay of at least one RTIO clock cycle before any
other command can be issued."""
@@ -128,30 +140,40 @@ def sync(self):

@kernel
def on(self):
"""Set the output to a logic high state.
"""Set the output to a logic high state at the current position of the
time cursor.
The channel must be in output mode.
The channel must be in output mode."""
The time cursor is not modified by this function."""
self.set_o(True)

@kernel
def off(self):
"""Set the output to a logic low state.
"""Set the output to a logic low state at the current position of the
time cursor.
The channel must be in output mode."""
The channel must be in output mode.
The time cursor is not modified by this function."""
self.set_o(False)

@kernel
def pulse_mu(self, duration):
"""Pulses the output high for the specified duration
(in machine units)."""
(in machine units).
The time cursor is advanced by the specified duration."""
self.on()
delay_mu(duration)
self.off()

@kernel
def pulse(self, duration):
"""Pulses the output high for the specified duration
(in seconds)."""
(in seconds).
The time cursor is advanced by the specified duration."""
self.on()
delay(duration)
self.off()
@@ -164,55 +186,69 @@ def _set_sensitivity(self, value):
@kernel
def gate_rising_mu(self, duration):
"""Register rising edge events for the specified duration
(in machine units)."""
(in machine units).
The time cursor is advanced by the specified duration."""
self._set_sensitivity(1)
delay_mu(duration)
self._set_sensitivity(0)

@kernel
def gate_falling_mu(self, duration):
"""Register falling edge events for the specified duration
(in machine units)."""
(in machine units).
The time cursor is advanced by the specified duration."""
self._set_sensitivity(2)
delay_mu(duration)
self._set_sensitivity(0)

@kernel
def gate_both_mu(self, duration):
"""Register both rising and falling edge events for the specified
duration (in machine units)."""
duration (in machine units).
The time cursor is advanced by the specified duration."""
self._set_sensitivity(3)
delay_mu(duration)
self._set_sensitivity(0)

@kernel
def gate_rising(self, duration):
"""Register rising edge events for the specified duration
(in seconds)."""
(in seconds).
The time cursor is advanced by the specified duration."""
self._set_sensitivity(1)
delay(duration)
self._set_sensitivity(0)

@kernel
def gate_falling(self, duration):
"""Register falling edge events for the specified duration
(in seconds)."""
(in seconds).
The time cursor is advanced by the specified duration."""
self._set_sensitivity(2)
delay(duration)
self._set_sensitivity(0)

@kernel
def gate_both(self, duration):
"""Register both rising and falling edge events for the specified
duration (in seconds)."""
duration (in seconds).
The time cursor is advanced by the specified duration."""
self._set_sensitivity(3)
delay(duration)
self._set_sensitivity(0)

@kernel
def count(self):
"""Poll the RTIO input during all the previously programmed gate
openings, and returns the number of registered events."""
openings, and returns the number of registered events.
This function does not interact with the time cursor."""
count = 0
while rtio_input_timestamp(self.i_previous_timestamp, self.channel) >= 0:
count += 1
@@ -224,7 +260,8 @@ def timestamp_mu(self):
units), according to the gating.
If the gate is permanently closed, returns a negative value.
"""
This function does not interact with the time cursor."""
return rtio_input_timestamp(self.i_previous_timestamp, self.channel)


@@ -234,6 +271,8 @@ class TTLClockGen:
This should be used with TTL channels that have a clock generator
built into the gateware (not compatible with regular TTL channels).
The time cursor is not modified by any function in this class.
:param channel: channel number
"""
kernel_invariants = {"core", "channel", "acc_width"}
@@ -262,7 +301,8 @@ def ftw_to_frequency(self, ftw):

@kernel
def set_mu(self, frequency):
"""Set the frequency of the clock, in machine units.
"""Set the frequency of the clock, in machine units, at the current
position of the time cursor.
This also sets the phase, as the time of the first generated rising
edge corresponds to the time of the call.
@@ -276,8 +316,7 @@ def set_mu(self, frequency):
Due to the way the clock generator operates, frequency tuning words
that are not powers of two cause jitter of one RTIO clock cycle at the
output.
"""
output."""
rtio_output(now_mu(), self.channel, 0, frequency)
self.previous_timestamp = now_mu()

7 changes: 6 additions & 1 deletion artiq/language/environment.py
Original file line number Diff line number Diff line change
@@ -286,7 +286,12 @@ def mutate_dataset(self, key, index, value):
a given position in a NumPy array)
If the dataset was created in broadcast mode, the modification is
immediately transmitted."""
immediately transmitted.
If the index is a tuple of integers, it is interpreted as
``slice(*index)``.
If the index is a tuple of tuples, each sub-tuple is interpreted
as ``slice(*sub_tuple)`` (multi-dimensional slicing)."""
self.__dataset_mgr.mutate(key, index, value)

def get_dataset(self, key, default=NoDefault):
9 changes: 8 additions & 1 deletion artiq/master/worker_db.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from operator import setitem
from collections import OrderedDict
import importlib
import logging
@@ -194,7 +195,13 @@ def mutate(self, key, index, value):
target = self.broadcast[key][1]
if target is None:
raise KeyError("Cannot mutate non-existing dataset")
target[index] = value

if isinstance(index, tuple):
if isinstance(index[0], tuple):
index = tuple(slice(*e) for e in index)
else:
index = slice(*index)
setitem(target, index, value)

def get(self, key):
if key in self.local: