Core drivers reference

These drivers are for the core device and the peripherals closely integrated into it, which do not use the controller mechanism.

System drivers

artiq.coredevice.core module

class artiq.coredevice.core.Core(dmgr, host, ref_period, ref_multiplier=8)[source]

Core device driver.

Parameters:
  • host – hostname or IP address of the core device.
  • ref_period – period of the reference clock for the RTIO subsystem. On platforms that use clock multiplication and SERDES-based PHYs, this is the period after multiplication. For example, with a RTIO core clocked at 125MHz and a SERDES multiplication factor of 8, the reference period is 1ns. The time machine unit is equal to this period.
  • ref_multiplier – ratio between the RTIO fine timestamp frequency and the RTIO coarse timestamp frequency (e.g. SERDES multiplication factor).
break_realtime()[source]

Set the time cursor after the current value of the hardware RTIO counter plus a margin of 125000 machine units.

If the time cursor is already after that position, this function does nothing.

get_rtio_counter_mu()[source]

Retrieve the current value of the hardware RTIO timeline counter.

As the timing of kernel code executed on the CPU is inherently non-deterministic, the return value is by necessity only a lower bound for the actual value of the hardware register at the instant when execution resumes in the caller.

For a more detailed description of these concepts, see ARTIQ Real-Time I/O Concepts.

get_rtio_destination_status(destination)[source]

Returns whether the specified RTIO destination is up. This is particularly useful in startup kernels to delay startup until certain DRTIO destinations are up.

mu_to_seconds(mu)[source]

Convert machine units (RTIO cycles) to seconds.

Parameters:mu – cycle count to convert.
reset()[source]

Clear RTIO FIFOs, release RTIO PHY reset, and set the time cursor at the current value of the hardware RTIO counter plus a margin of 125000 machine units.

seconds_to_mu(seconds)[source]

Convert seconds to the corresponding number of machine units (RTIO cycles).

Parameters:seconds – time (in seconds) to convert.
wait_until_mu(cursor_mu)[source]

Block execution until the hardware RTIO counter reaches the given value (see get_rtio_counter_mu()).

If the hardware counter has already passed the given time, the function returns immediately.

artiq.coredevice.exceptions module

exception artiq.coredevice.exceptions.CacheError[source]

Raised when putting a value into a cache row would violate memory safety.

exception artiq.coredevice.exceptions.ClockFailure[source]

Raised when RTIO PLL has lost lock.

class artiq.coredevice.exceptions.CoreException(name, message, params, traceback)[source]

Information about an exception raised or passed through the core device.

exception artiq.coredevice.exceptions.DMAError[source]

Raised when performing an invalid DMA operation.

exception artiq.coredevice.exceptions.I2CError[source]

Raised when a I2C transaction fails.

exception artiq.coredevice.exceptions.InternalError[source]

Raised when the runtime encounters an internal error condition.

exception artiq.coredevice.exceptions.RTIODestinationUnreachable[source]

Raised with a RTIO operation could not be completed due to a DRTIO link being down.

exception artiq.coredevice.exceptions.RTIOOverflow[source]

Raised when at least one event could not be registered into the RTIO input FIFO because it was full (CPU not reading fast enough).

This does not interrupt operations further than cancelling the current read attempt and discarding some events. Reading can be reattempted after the exception is caught, and events will be partially retrieved.

exception artiq.coredevice.exceptions.RTIOUnderflow[source]

Raised when the CPU or DMA core fails to submit a RTIO event early enough (with respect to the event’s timestamp).

The offending event is discarded and the RTIO core keeps operating.

exception artiq.coredevice.exceptions.SPIError[source]

Raised when a SPI transaction fails.

exception artiq.coredevice.exceptions.WatchdogExpired[source]

Raised when a watchdog expires.

artiq.coredevice.dma module

Direct Memory Access (DMA) extension.

This feature allows storing pre-defined sequences of output RTIO events into the core device’s SDRAM, and playing them back at higher speeds than the CPU alone could achieve.

class artiq.coredevice.dma.CoreDMA(dmgr, core_device='core')[source]

Core device Direct Memory Access (DMA) driver.

Gives access to the DMA functionality of the core device.

erase(name)[source]

Removes the DMA trace with the given name from storage.

get_handle(name)[source]

Returns a handle to a previously recorded DMA trace. The returned handle is only valid until the next call to record() or erase().

playback(name)[source]

Replays a previously recorded DMA trace. This function blocks until the entire trace is submitted to the RTIO FIFOs.

playback_handle(handle)[source]

Replays a handle obtained with get_handle(). Using this function is much faster than playback() for replaying a set of traces repeatedly, but incurs the overhead of managing the handles onto the programmer.

record(name)[source]

Returns a context manager that will record a DMA trace called name. Any previously recorded trace with the same name is overwritten. The trace will persist across kernel switches.

class artiq.coredevice.dma.DMARecordContextManager[source]

Context manager returned by CoreDMA.record().

Upon entering, starts recording a DMA trace. All RTIO operations are redirected to a newly created DMA buffer after this call, and now is reset to zero.

Upon leaving, stops recording a DMA trace. All recorded RTIO operations are stored in a newly created trace, and now is restored to the value it had before the context manager was entered.

artiq.coredevice.cache module

class artiq.coredevice.cache.CoreCache(dmgr, core_device='core')[source]

Core device cache access

get(key)[source]

Extract a value from the core device cache. After a value is extracted, it cannot be replaced with another value using put() until all kernel functions finish executing; attempting to replace it will result in a artiq.coredevice.exceptions.CacheError.

If the cache does not contain any value associated with key, an empty list is returned.

The value is not copied, so mutating it will change what’s stored in the cache.

Parameters:key (str) – cache key
Returns:a list of 32-bit integers
put(key, value)[source]

Put a value into the core device cache. The value will persist until reboot.

To remove a value from the cache, call put() with an empty list.

Parameters:
  • key (str) – cache key
  • value (list) – a list of 32-bit integers

Digital I/O drivers

artiq.coredevice.ttl module

Drivers for TTL signals on RTIO.

TTL channels (including the clock generator) all support output event replacement. For example, pulses of “zero” length (e.g. TTLInOut.on() immediately followed by TTLInOut.off(), without a delay) are suppressed.

class artiq.coredevice.ttl.TTLClockGen(dmgr, channel, acc_width=24, core_device='core')[source]

RTIO TTL clock generator driver.

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.

Parameters:
  • channel – channel number
  • acc_width – accumulator width in bits
frequency_to_ftw(frequency)[source]

Returns the frequency tuning word corresponding to the given frequency.

ftw_to_frequency(ftw)[source]

Returns the frequency corresponding to the given frequency tuning word.

set(frequency)[source]

Like set_mu(), but using Hz.

set_mu(frequency)[source]

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.

The clock generator contains a 24-bit phase accumulator operating on the RTIO clock. At each RTIO clock tick, the frequency tuning word is added to the phase accumulator. The most significant bit of the phase accumulator is connected to the TTL line. Setting the frequency tuning word has the additional effect of setting the phase accumulator to 0x800000.

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.

stop()[source]

Stop the toggling of the clock and set the output level to 0.

class artiq.coredevice.ttl.TTLInOut(dmgr, channel, gate_latency_mu=None, core_device='core')[source]

RTIO TTL input/output driver.

In output mode, provides functions to set the logic level on the signal.

In input mode, provides functions to analyze the incoming signal, with real-time gating to prevent overflows.

RTIO TTLs supports zero-length transition suppression. For example, if two pulses are emitted back-to-back with no delay between them, they will be merged into a single pulse with a duration equal to the sum of the durations of the original pulses.

This should be used with bidirectional channels.

Note that the channel is in input mode by default. If you need to drive a signal, you must call output(). If the channel is in output mode most of the time in your setup, it is a good idea to call output() in the startup kernel.

There are three input APIs: gating, sampling and watching. When one API is active (e.g. the gate is open, or the input events have not been fully read out), another API must not be used simultaneously.

Parameters:channel – channel number
count(up_to_timestamp_mu)[source]

Consume RTIO input events until the hardware timestamp counter has reached the specified timestamp and return the number of observed events.

This function does not interact with the timeline cursor.

See the gate_*() family of methods to select the input transitions that generate events, and timestamp_mu() to obtain the timestamp of the first event rather than an accumulated count.

Parameters:up_to_timestamp_mu – The timestamp up to which execution is blocked, that is, up to which input events are guaranteed to be taken into account. (Events with later timestamps might still be registered if they are already available.)
Returns:The number of events before the timeout elapsed (0 if none observed).

Examples

To count events on channel ttl_input, up to the current timeline position:

ttl_input.count(now_mu())

If other events are scheduled between the end of the input gate period and when the number of events is counted, using now_mu() as timeout consumes an unnecessary amount of timeline slack. In such cases, it can be beneficial to pass a more precise timestamp, for example:

gate_end_mu = ttl_input.gate_rising(100 * us)

# Schedule a long pulse sequence, represented here by a delay.
delay(10 * ms)

# Get number of rising edges. This will block until the end of
# the gate window, but does not wait for the long pulse sequence
# afterwards, thus (likely) completing with a large amount of
# slack left.
num_rising_edges = ttl_input.count(gate_end_mu)

The gate_*() family of methods return the cursor at the end of the window, allowing this to be expressed in a compact fashion:

ttl_input.count(ttl_input.gate_rising(100 * us))
gate_both(duration)[source]

Register both rising and falling edge events for the specified duration (in seconds).

The time cursor is advanced by the specified duration.

Returns:The timeline cursor at the end of the gate window, for convenience when used with count()/timestamp_mu().
gate_both_mu(duration)[source]

Register both rising and falling edge events for the specified duration (in machine units).

The time cursor is advanced by the specified duration.

Returns:The timeline cursor at the end of the gate window, for convenience when used with count()/timestamp_mu().
gate_falling(duration)[source]

Register falling edge events for the specified duration (in seconds).

The time cursor is advanced by the specified duration.

Returns:The timeline cursor at the end of the gate window, for convenience when used with count()/timestamp_mu().
gate_falling_mu(duration)[source]

Register falling edge events for the specified duration (in machine units).

The time cursor is advanced by the specified duration.

Returns:The timeline cursor at the end of the gate window, for convenience when used with count()/timestamp_mu().
gate_rising(duration)[source]

Register rising edge events for the specified duration (in seconds).

The time cursor is advanced by the specified duration.

Returns:The timeline cursor at the end of the gate window, for convenience when used with count()/timestamp_mu().
gate_rising_mu(duration)[source]

Register rising edge events for the specified duration (in machine units).

The time cursor is advanced by the specified duration.

Returns:The timeline cursor at the end of the gate window, for convenience when used with count()/timestamp_mu().
input()[source]

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.

off()[source]

Set the output to a logic low state at the current position of the time cursor.

The channel must be in output mode.

The time cursor is not modified by this function.

on()[source]

Set the output to a logic high state at the current position of the time cursor.

The channel must be in output mode.

The time cursor is not modified by this function.

output()[source]

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.

pulse(duration)[source]

Pulses the output high for the specified duration (in seconds).

The time cursor is advanced by the specified duration.

pulse_mu(duration)[source]

Pulses the output high for the specified duration (in machine units).

The time cursor is advanced by the specified duration.

sample_get()[source]

Returns the value of a sample previously obtained with sample_input().

Multiple samples may be queued (using multiple calls to sample_input()) into the RTIO FIFOs and subsequently read out using multiple calls to this function.

This function does not interact with the time cursor.

sample_get_nonrt()[source]

Convenience function that obtains the value of a sample at the position of the time cursor, breaks realtime, and returns the sample value.

sample_input()[source]

Instructs the RTIO core to read the value of the TTL input at the position of the time cursor.

The time cursor is not modified by this function.

timestamp_mu(up_to_timestamp_mu)[source]

Return the timestamp of the next RTIO input event, or -1 if the hardware timestamp counter reaches the given value before an event is received.

This function does not interact with the timeline cursor.

See the gate_*() family of methods to select the input transitions that generate events, and count() for usage examples.

Parameters:up_to_timestamp_mu – The timestamp up to which execution is blocked, that is, up to which input events are guaranteed to be taken into account. (Events with later timestamps might still be registered if they are already available.)
Returns:The timestamp (in machine units) of the first event received; -1 on timeout.
watch_done()[source]

Stop watching the input at the position of the time cursor.

Returns True if the input has not changed state while it was being watched.

The time cursor is not modified by this function. This function always makes the slack negative.

watch_stay_off()[source]

Like watch_stay_on(), but for low levels.

watch_stay_on()[source]

Checks that the input is at a high level at the position of the time cursor and keep checking until watch_done() is called.

Returns True if the input is high. A call to this function must always be followed by an eventual call to watch_done() (use e.g. a try/finally construct to ensure this).

The time cursor is not modified by this function.

class artiq.coredevice.ttl.TTLOut(dmgr, channel, core_device='core')[source]

RTIO TTL output driver.

This should be used with output-only channels.

Parameters:channel – channel number
off()[source]

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.

on()[source]

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.

pulse(duration)[source]

Pulse the output high for the specified duration (in seconds).

The time cursor is advanced by the specified duration.

pulse_mu(duration)[source]

Pulse the output high for the specified duration (in machine units).

The time cursor is advanced by the specified duration.

artiq.coredevice.shiftreg module

class artiq.coredevice.shiftreg.ShiftReg(dmgr, clk, ser, latch, n=32, dt=9.999999999999999e-06)[source]

Driver for shift registers/latch combos connected to TTLs

set(data)[source]

Sets the values of the latch outputs. This does not advance the timeline and the waveform is generated before now.

artiq.coredevice.spi2 module

Driver for generic SPI on RTIO.

This ARTIQ coredevice driver corresponds to the “new” MiSoC SPI core (v2).

Output event replacement is not supported and issuing commands at the same time is an error.

class artiq.coredevice.spi2.SPIMaster(dmgr, channel, div=0, length=0, core_device='core')[source]

Core device Serial Peripheral Interface (SPI) bus master.

Owns one SPI bus.

This ARTIQ coredevice driver corresponds to the “new” MiSoC SPI core (v2).

Transfer Sequence:

  • If necessary, set the config register (set_config() and set_config_mu()) to activate and configure the core and to set various transfer parameters like transfer length, clock divider, and chip selects.
  • write() to the data register. Writing starts the transfer.
  • If the transfer included submitting the SPI input data as an RTIO input event (SPI_INPUT set), then read() the data.
  • If SPI_END was not set, repeat the transfer sequence.

A transaction consists of one or more transfers. The chip select pattern is asserted for the entire length of the transaction. All but the last transfer are submitted with SPI_END cleared in the configuration register.

Parameters:
frequency_to_div(f)[source]

Convert a SPI clock frequency to the closest SPI clock divider.

read()[source]

Read SPI data submitted by the SPI core.

For bit alignment and bit ordering see set_config().

This method does not alter the timeline.

Returns:SPI input data.
set_config(flags, length, freq, cs)[source]

Set the configuration register.

  • If SPI_CS_POLARITY is cleared (cs active low, the default), “cs all deasserted” means “all cs_n bits high”.
  • cs_n is not mandatory in the pads supplied to the gateware core. Framing and chip selection can also be handled independently through other means, e.g. TTLOut.
  • If there is a miso wire in the pads supplied in the gateware, input and output may be two signals (“4-wire SPI”), otherwise mosi must be used for both output and input (“3-wire SPI”) and SPI_HALF_DUPLEX must to be set when reading data or when the slave drives the mosi signal at any point.
  • The first bit output on mosi is always the MSB/LSB (depending on SPI_LSB_FIRST) of the data written, independent of the length of the transfer. The last bit input from miso always ends up in the LSB/MSB (respectively) of the data read, independent of the length of the transfer.
  • cs is asserted at the beginning and deasserted at the end of the transaction.
  • cs handling is agnostic to whether it is one-hot or decoded somewhere downstream. If it is decoded, “cs all deasserted” should be handled accordingly (no slave selected). If it is one-hot, asserting multiple slaves should only be attempted if miso is either not connected between slaves, or open collector, or correctly multiplexed externally.
  • Changes to the configuration register take effect on the start of the next transfer with the exception of SPI_OFFLINE which takes effect immediately.
  • The SPI core can only be written to when it is idle or waiting for the next transfer data. Writing (set_config(), set_config_mu() or write()) when the core is busy will result in an RTIO busy error being logged.

This method advances the timeline by one coarse RTIO clock cycle.

Configuration flags:

  • SPI_OFFLINE: all pins high-z (reset=1)
  • SPI_END: transfer in progress (reset=1)
  • SPI_INPUT: submit SPI read data as RTIO input event when transfer is complete (reset=0)
  • SPI_CS_POLARITY: active level of cs_n (reset=0)
  • SPI_CLK_POLARITY: idle level of clk (reset=0)
  • SPI_CLK_PHASE: first edge after cs assertion to sample data on (reset=0). In Motorola/Freescale SPI language (SPI_CLK_POLARITY, SPI_CLK_PHASE) == (CPOL, CPHA):
    • (0, 0): idle low, output on falling, input on rising
    • (0, 1): idle low, output on rising, input on falling
    • (1, 0): idle high, output on rising, input on falling
    • (1, 1): idle high, output on falling, input on rising
  • SPI_LSB_FIRST: LSB is the first bit on the wire (reset=0)
  • SPI_HALF_DUPLEX: 3-wire SPI, in/out on mosi (reset=0)
Parameters:
  • flags – A bit map of SPI_* flags.
  • length – Number of bits to write during the next transfer. (reset=1)
  • freq – Desired SPI clock frequency. (reset=f_rtio/2)
  • cs – Bit pattern of chip selects to assert. Or number of the chip select to assert if cs is decoded downstream. (reset=0)
set_config_mu(flags, length, div, cs)[source]

Set the config register (in SPI bus machine units).

See also

set_config()

Parameters:
  • flags – A bit map of SPI_* flags.
  • length – Number of bits to write during the next transfer. (reset=1)
  • div – Counter load value to divide the RTIO clock by to generate the SPI clock. (minimum=2, reset=2) f_rtio_clk/f_spi == div. If div is odd, the setup phase of the SPI clock is one coarse RTIO clock cycle longer than the hold phase.
  • cs – Bit pattern of chip selects to assert. Or number of the chip select to assert if cs is decoded downstream. (reset=0)
update_xfer_duration_mu(div, length)[source]

Calculate and set the transfer duration.

This method updates the SPI transfer duration which is used in write() to advance the timeline.

Use this method (and avoid having to call set_config_mu()) when the divider and transfer length have been configured (using set_config() or set_config_mu()) by previous experiments and are known.

This method is portable and can also be called from e.g. __init__().

Warning

If this method is called while recording a DMA

sequence, the playback of the sequence will not update the driver state. When required, update the driver state manually (by calling this method) after playing back a DMA sequence.

Parameters:
write(data)[source]

Write SPI data to shift register register and start transfer.

  • The data register and the shift register are 32 bits wide.
  • Data writes take one ref_period cycle.
  • A transaction consisting of a single transfer (SPI_END) takes xfer_duration_mu =(n + 1)*div cycles RTIO time where n is the number of bits and div is the SPI clock divider.
  • Transfers in a multi-transfer transaction take up to one SPI clock cycle less time depending on multiple parameters. Advanced users may rewind the timeline appropriately to achieve faster multi-transfer transactions.
  • The SPI core will be busy for the duration of the SPI transfer.
  • For bit alignment and bit ordering see set_config().
  • The SPI core can only be written to when it is idle or waiting for the next transfer data. Writing (set_config(), set_config_mu() or write()) when the core is busy will result in an RTIO busy error being logged.

This method advances the timeline by the duration of one single-transfer SPI transaction (xfer_duration_mu).

Parameters:data – SPI output data to be written.
class artiq.coredevice.spi2.NRTSPIMaster(dmgr, busno=0, core_device='core')[source]

Core device non-realtime Serial Peripheral Interface (SPI) bus master. Owns one non-realtime SPI bus.

With this driver, SPI transactions and are performed by the CPU without involving RTIO.

Realtime and non-realtime buses are separate and defined at bitstream compilation time.

See SPIMaster for a description of the methods.

set_config_mu(flags=0, length=8, div=6, cs=1)[source]

Set the config register.

Note that the non-realtime SPI cores are usually clocked by the system clock and not the RTIO clock. In many cases, the SPI configuration is already set by the firmware and you do not need to call this method.

artiq.coredevice.i2c module

Non-realtime drivers for I2C chips on the core device.

class artiq.coredevice.i2c.PCA9548(dmgr, busno=0, address=232, core_device='core')[source]

Driver for the PCA9548 I2C bus switch.

I2C transactions not real-time, and are performed by the CPU without involving RTIO.

On the KC705, this chip is used for selecting the I2C buses on the two FMC connectors. HPC=1, LPC=2.

select(mask)[source]

Enable/disable channels.

Parameters:mask – Bit mask of enabled channels
set(channel)[source]

Enable one channel.

Parameters:channel – channel number (0-7)
class artiq.coredevice.i2c.TCA6424A(dmgr, busno=0, address=68, core_device='core')[source]

Driver for the TCA6424A I2C I/O expander.

I2C transactions not real-time, and are performed by the CPU without involving RTIO.

On the NIST QC2 hardware, this chip is used for switching the directions of TTL buffers.

set(outputs)[source]

Drive all pins of the chip to the levels given by the specified 24-bit word.

On the QC2 hardware, the LSB of the word determines the direction of TTL0 (on a given FMC card) and the MSB that of TTL23.

A bit set to 1 means the TTL is an output.

artiq.coredevice.i2c.i2c_poll(busno, busaddr)[source]

Poll I2C device at address.

Parameters:
  • busno – I2C bus number
  • busaddr – 8 bit I2C device address (LSB=0)
Returns:

True if the poll was ACKed

artiq.coredevice.i2c.i2c_read_byte(busno, busaddr)[source]

Read one byte from a device.

Parameters:
  • busno – I2C bus number
  • busaddr – 8 bit I2C device address (LSB=0)
Returns:

Byte read

artiq.coredevice.i2c.i2c_read_many(busno, busaddr, addr, data)[source]

Transfer multiple bytes from a device.

Parameters:
  • busno – I2c bus number
  • busaddr – 8 bit I2C device address (LSB=0)
  • addr – 8 bit data address
  • data – List of integers to be filled with the data read. One entry ber byte.
artiq.coredevice.i2c.i2c_write_byte(busno, busaddr, data, ack=True)[source]

Write one byte to a device.

Parameters:
  • busno – I2C bus number
  • busaddr – 8 bit I2C device address (LSB=0)
  • data – Data byte to be written
  • nack – Allow NACK
artiq.coredevice.i2c.i2c_write_many(busno, busaddr, addr, data, ack_last=True)[source]

Transfer multiple bytes to a device.

Parameters:
  • busno – I2c bus number
  • busaddr – 8 bit I2C device address (LSB=0)
  • addr – 8 bit data address
  • data – Data bytes to be written
  • ack_last – Expect I2C ACK of the last byte written. If False, the last byte may be NACKed (e.g. EEPROM full page writes).

artiq.coredevice.pcf8574a module

class artiq.coredevice.pcf8574a.PCF8574A(dmgr, busno=0, address=124, core_device='core')[source]

Driver for the PCF8574 I2C remote 8-bit I/O expander.

I2C transactions not real-time, and are performed by the CPU without involving RTIO.

get()[source]

Retrieve quasi-bidirectional pin input data.

Returns:Pin data
set(data)[source]

Drive data on the quasi-bidirectional pins.

Parameters:data – Pin data. High bits are weakly driven high (and thus inputs), low bits are strongly driven low.

RF generation drivers

artiq.coredevice.urukul module

class artiq.coredevice.urukul.CPLD(dmgr, spi_device, io_update_device=None, dds_reset_device=None, sync_device=None, sync_sel=0, clk_sel=0, rf_sw=0, refclk=125000000.0, att=0, sync_div=None, core_device='core')[source]

Urukul CPLD SPI router and configuration interface.

Parameters:
  • spi_device – SPI bus device name
  • io_update_device – IO update RTIO TTLOut channel name
  • dds_reset_device – DDS reset RTIO TTLOut channel name
  • sync_device – AD9910 SYNC_IN RTIO TTLClockGen channel name
  • refclk – Reference clock (SMA, MMCX or on-board 100 MHz oscillator) frequency in Hz
  • clk_sel – Reference clock selection. For hardware revision >= 1.3 valid options are: 0 - internal 100MHz XO; 1 - front-panel SMA; 2 internal MMCX. For hardware revision <= v1.2 valid options are: 0 - either XO or MMCX dependent on component population; 1 SMA. Unsupported clocking options are silently ignored.
  • sync_sel – SYNC_IN selection. 0 corresponds to SYNC_IN over EEM from FPGA. 1 corresponds to SYNC_IN from DDS0.
  • rf_sw – Initial CPLD RF switch register setting (default: 0x0). Knowledge of this state is not transferred between experiments.
  • att – Initial attenuator setting shift register (default: 0x00000000). See also get_att_mu() which retrieves the hardware state without side effects. Knowledge of this state is not transferred between experiments.
  • sync_div – SYNC_IN generator divider. The ratio between the coarse RTIO frequency and the SYNC_IN generator frequency (default: 2 if sync_device was specified).
  • core_device – Core device name
cfg_sw(channel, on)[source]

Configure the RF switches through the configuration register.

These values are logically OR-ed with the LVDS lines on EEM1.

Parameters:
  • channel – Channel index (0-3)
  • on – Switch value
cfg_switches(state)[source]

Configure all four RF switches through the configuration register.

Parameters:state – RF switch state as a 4 bit integer.
cfg_write(cfg)[source]

Write to the configuration register.

See urukul_cfg() for possible flags.

Parameters:data – 24 bit data to be written. Will be stored at cfg_reg.
get_att_mu()[source]

Return the digital step attenuator settings in machine units.

Returns:32 bit attenuator settings
init(blind=False)[source]

Initialize and detect Urukul.

Resets the DDS I/O interface and verifies correct CPLD gateware version. Does not pulse the DDS MASTER_RESET as that confuses the AD9910.

Parameters:blind – Do not attempt to verify presence and compatibility.
io_rst()[source]

Pulse IO_RST

set_all_att_mu(att_reg)[source]

Set all four digital step attenuators (in machine units).

See also

set_att_mu()

Parameters:att_reg – Attenuator setting string (32 bit)
set_att(channel, att)[source]

Set digital step attenuator in SI units.

Parameters:
  • channel – Attenuator channel (0-3).
  • att – Attenuation setting in dB. Higher value is more attenuation. Minimum attenuation is 0*dB, maximum attenuation is 31.5*dB.
set_att_mu(channel, att)[source]

Set digital step attenuator in machine units.

This method will write the attenuator settings of all four channels.

Parameters:
  • channel – Attenuator channel (0-3).
  • att – Digital attenuation setting: 255 minimum attenuation, 0 maximum attenuation (31.5 dB)
set_profile(profile)[source]

Set the PROFILE pins.

The PROFILE pins are common to all four DDS channels.

Parameters:profile – PROFILE pins in numeric representation (0-7).
set_sync_div(div)[source]

Set the SYNC_IN AD9910 pulse generator frequency and align it to the current RTIO timestamp.

The SYNC_IN signal is derived from the coarse RTIO clock and the divider must be a power of two two. Configure sync_sel == 0.

Parameters:div – SYNC_IN frequency divider. Must be a power of two. Minimum division ratio is 2. Maximum division ratio is 16.
sta_read()[source]

Read the status register.

Use any of the following functions to extract values:

Returns:The status register value.
artiq.coredevice.urukul.urukul_cfg(rf_sw, led, profile, io_update, mask_nu, clk_sel, sync_sel, rst, io_rst)[source]

Build Urukul CPLD configuration register

artiq.coredevice.urukul.urukul_sta_ifc_mode(sta)[source]

Return the IFC_MODE status from Urukul status register value.

artiq.coredevice.urukul.urukul_sta_pll_lock(sta)[source]

Return the PLL_LOCK status from Urukul status register value.

artiq.coredevice.urukul.urukul_sta_proto_rev(sta)[source]

Return the PROTO_REV value from Urukul status register value.

artiq.coredevice.urukul.urukul_sta_rf_sw(sta)[source]

Return the RF switch status from Urukul status register value.

artiq.coredevice.urukul.urukul_sta_smp_err(sta)[source]

Return the SMP_ERR status from Urukul status register value.

artiq.coredevice.ad9910 module

class artiq.coredevice.ad9910.AD9910(dmgr, chip_select, cpld_device, sw_device=None, pll_n=40, pll_cp=7, pll_vco=5, sync_delay_seed=-1, io_update_delay=0)[source]

AD9910 DDS channel on Urukul.

This class supports a single DDS channel and exposes the DDS, the digital step attenuator, and the RF switch.

Parameters:
  • chip_select – Chip select configuration. On Urukul this is an encoded chip select and not “one-hot”: 3 to address multiple chips (as configured through CFG_MASK_NU), 4-7 for individual channels.
  • cpld_device – Name of the Urukul CPLD this device is on.
  • sw_device – Name of the RF switch device. The RF switch is a TTLOut channel available as the sw attribute of this instance.
  • pll_n – DDS PLL multiplier. The DDS sample clock is f_ref/4*pll_n where f_ref is the reference frequency (set in the parent Urukul CPLD instance).
  • pll_cp – DDS PLL charge pump setting.
  • pll_vco – DDS PLL VCO range selection.
  • sync_delay_seed – SYNC_IN delay tuning starting value. To stabilize the SYNC_IN delay tuning, run tune_sync_delay() once and set this to the delay tap number returned (default: -1 to signal no synchronization and no tuning during init()).
  • io_update_delay – IO_UPDATE pulse alignment delay. To align IO_UPDATE to SYNC_CLK, run tune_io_update_delay() and set this to the delay tap number returned.
amplitude_to_asf(amplitude)[source]

Return amplitude scale factor corresponding to given amplitude.

cfg_sw(state)[source]

Set CPLD CFG RF switch state. The RF switch is controlled by the logical or of the CPLD configuration shift register RF switch bit and the SW TTL line (if used).

Parameters:state – CPLD CFG RF switch bit
clear_smp_err()[source]

Clear the SMP_ERR flag and enables SMP_ERR validity monitoring.

Violations of the SYNC_IN sample and hold margins will result in SMP_ERR being asserted. This then also activates the red LED on the respective Urukul channel.

Also modifies CFR2.

frequency_to_ftw(frequency)[source]

Return the frequency tuning word corresponding to the given frequency.

init(blind=False)[source]

Initialize and configure the DDS.

Sets up SPI mode, confirms chip presence, powers down unused blocks, configures the PLL, waits for PLL lock. Uses the IO_UPDATE signal multiple times.

Parameters:blind – Do not read back DDS identity and do not wait for lock.
measure_io_update_alignment(delay_start, delay_stop)[source]

Use the digital ramp generator to locate the alignment between IO_UPDATE and SYNC_CLK.

The ramp generator is set up to a linear frequency ramp (dFTW/t_SYNC_CLK=1) and started at a coarse RTIO time stamp plus delay_start and stopped at a coarse RTIO time stamp plus delay_stop.

Parameters:
  • delay_start – Start IO_UPDATE delay in machine units.
  • delay_stop – Stop IO_UPDATE delay in machine units.
Returns:

Odd/even SYNC_CLK cycle indicator.

pow_to_turns(pow_)[source]

Return the phase in turns corresponding to a given phase offset word.

power_down(bits=15)[source]

Power down DDS.

Parameters:bits – Power down bits, see datasheet
read32(addr)[source]

Read from 32 bit register.

Parameters:addr – Register address
read64(addr)[source]

Read from 64 bit register.

Parameters:addr – Register address
Returns:64 bit integer register value
read_ram(data)[source]

Read data from RAM.

The profile to read from and the step, start, and end address need to be configured before and separately using set_profile_ram() and the parent CPLD set_profile.

Parameters:List(int32) (data) – List to be filled with data read from RAM.
set(frequency, phase=0.0, amplitude=1.0, phase_mode=-1, ref_time=-1, profile=0)[source]

Set profile 0 data in SI units.

See also

set_mu()

Parameters:
  • frequency – Frequency in Hz
  • phase – Phase tuning word in turns
  • amplitude – Amplitude in units of full scale
  • phase_mode – Phase mode constant
  • ref_time – Fiducial time stamp in machine units
  • profile – Profile to affect
Returns:

Resulting phase offset in turns

set_att(att)[source]

Set digital step attenuator in SI units.

Parameters:att – Attenuation in dB.
set_att_mu(att)[source]

Set digital step attenuator in machine units.

Parameters:att – Attenuation setting, 8 bit digital.
set_cfr1(power_down=0, phase_autoclear=0, drg_load_lrr=0, drg_autoclear=0, internal_profile=0, ram_destination=0, ram_enable=0)[source]

Set CFR1. See the AD9910 datasheet for parameter meanings.

This method does not pulse IO_UPDATE.

Parameters:
  • power_down – Power down bits.
  • phase_autoclear – Autoclear phase accumulator.
  • drg_load_lrr – Load digital ramp generator LRR.
  • drg_autoclear – Autoclear digital ramp generator.
  • internal_profile – Internal profile control.
  • ram_destination – RAM destination (_AD9910_RAM_DEST_FTW, _AD9910_RAM_DEST_POW, _AD9910_RAM_DEST_ASF, _AD9910_RAM_DEST_POWASF).
  • ram_enable – RAM mode enable.
set_mu(ftw, pow_=0, asf=16383, phase_mode=-1, ref_time=-1, profile=0)[source]

Set profile 0 data in machine units.

This uses machine units (FTW, POW, ASF). The frequency tuning word width is 32, the phase offset word width is 16, and the amplitude scale factor width is 12.

After the SPI transfer, the shared IO update pin is pulsed to activate the data.

Parameters:
  • ftw – Frequency tuning word: 32 bit.
  • pow – Phase tuning word: 16 bit unsigned.
  • asf – Amplitude scale factor: 14 bit unsigned.
  • phase_mode – If specified, overrides the default phase mode set by set_phase_mode() for this call.
  • ref_time – Fiducial time used to compute absolute or tracking phase updates. In machine units as obtained by now_mu().
  • profile – Profile number to set (0-7, default: 0).
Returns:

Resulting phase offset word after application of phase tracking offset. When using PHASE_MODE_CONTINUOUS in subsequent calls, use this value as the “current” phase.

set_phase_mode(phase_mode)[source]

Set the default phase mode.

for future calls to set() and set_mu(). Supported phase modes are:

  • PHASE_MODE_CONTINUOUS: the phase accumulator is unchanged when changing frequency or phase. The DDS phase is the sum of the phase accumulator and the phase offset. The only discontinuous changes in the DDS output phase come from changes to the phase offset. This mode is also knows as “relative phase mode”. \(\phi(t) = q(t^\prime) + p + (t - t^\prime) f\)
  • PHASE_MODE_ABSOLUTE: the phase accumulator is reset when changing frequency or phase. Thus, the phase of the DDS at the time of the change is equal to the specified phase offset. \(\phi(t) = p + (t - t^\prime) f\)
  • PHASE_MODE_TRACKING: when changing frequency or phase, the phase accumulator is cleared and the phase offset is offset by the value the phase accumulator would have if the DDS had been running at the specified frequency since a given fiducial time stamp. This is functionally equivalent to PHASE_MODE_ABSOLUTE. The only difference is the fiducial time stamp. This mode is also known as “coherent phase mode”. The default fiducial time stamp is 0. \(\phi(t) = p + (t - T) f\)

Where:

  • \(\phi(t)\): the DDS output phase
  • \(q(t) = \phi(t) - p\): DDS internal phase accumulator
  • \(p\): phase offset
  • \(f\): frequency
  • \(t^\prime\): time stamp of setting \(p\), \(f\)
  • \(T\): fiducial time stamp
  • \(t\): running time

Warning

This setting may become inconsistent when used as part of a DMA recording. When using DMA, it is recommended to specify the phase mode explicitly when calling set() or set_mu().

set_profile_ram(start, end, step=1, profile=0, nodwell_high=0, zero_crossing=0, mode=1)[source]

Set the RAM profile settings.

Parameters:
  • start – Profile start address in RAM.
  • end – Profile end address in RAM (last address).
  • step – Profile address step size (default: 1).
  • profile – Profile index (0 to 7) (default: 0).
  • nodwell_high – No-dwell high bit (default: 0, see AD9910 documentation).
  • zero_crossing – Zero crossing bit (default: 0, see AD9910 documentation).
  • mode – Profile RAM mode (RAM_MODE_DIRECTSWITCH, RAM_MODE_RAMPUP, RAM_MODE_BIDIR_RAMP, RAM_MODE_CONT_BIDIR_RAMP, or RAM_MODE_CONT_RECIRCULATE, default: RAM_MODE_RAMPUP)
set_sync(in_delay, window)[source]

Set the relevant parameters in the multi device synchronization register. See the AD9910 datasheet for details. The SYNC clock generator preset value is set to zero, and the SYNC_OUT generator is disabled.

Parameters:
  • in_delay – SYNC_IN delay tap (0-31) in steps of ~75ps
  • window – Symmetric SYNC_IN validation window (0-15) in steps of ~75ps for both hold and setup margin.
tune_io_update_delay()[source]

Find a stable IO_UPDATE delay alignment.

Scan through increasing IO_UPDATE delays until a delay is found that lets IO_UPDATE be registered in the next SYNC_CLK cycle. Return a IO_UPDATE delay that is as far away from that SYNC_CLK edge as possible.

This method assumes that the IO_UPDATE TTLOut device has one machine unit resolution (SERDES).

Returns:Stable IO_UPDATE delay to be passed to the constructor AD9910 via the device database.
tune_sync_delay(search_seed=15)[source]

Find a stable SYNC_IN delay.

This method first locates a valid SYNC_IN delay at zero validation window size (setup/hold margin) by scanning around search_seed. It then looks for similar valid delays at successively larger validation window sizes until none can be found. It then deacreses the validation window a bit to provide some slack and stability and returns the optimal values.

Parameters:search_seed – Start value for valid SYNC_IN delay search. Defaults to 15 (half range).
Returns:Tuple of optimal delay and window size.
turns_to_pow(turns)[source]

Return the phase offset word corresponding to the given phase in turns.

write32(addr, data)[source]

Write to 32 bit register.

Parameters:
  • addr – Register address
  • data – Data to be written
write64(addr, data_high, data_low)[source]

Write to 64 bit register.

Parameters:
  • addr – Register address
  • data_high – High (MSB) 32 bits of the data
  • data_low – Low (LSB) 32 data bits
write_ram(data)[source]

Write data to RAM.

The profile to write to and the step, start, and end address need to be configured before and separately using set_profile_ram() and the parent CPLD set_profile.

Parameters:List(int32) (data) – Data to be written to RAM.

artiq.coredevice.ad9912 module

class artiq.coredevice.ad9912.AD9912(dmgr, chip_select, cpld_device, sw_device=None, pll_n=10)[source]

AD9912 DDS channel on Urukul

This class supports a single DDS channel and exposes the DDS, the digital step attenuator, and the RF switch.

Parameters:
  • chip_select – Chip select configuration. On Urukul this is an encoded chip select and not “one-hot”.
  • cpld_device – Name of the Urukul CPLD this device is on.
  • sw_device – Name of the RF switch device. The RF switch is a TTLOut channel available as the sw attribute of this instance.
  • pll_n – DDS PLL multiplier. The DDS sample clock is f_ref*pll_n where f_ref is the reference frequency (set in the parent Urukul CPLD instance).
cfg_sw(state)[source]

Set CPLD CFG RF switch state. The RF switch is controlled by the logical or of the CPLD configuration shift register RF switch bit and the SW TTL line (if used).

Parameters:state – CPLD CFG RF switch bit
frequency_to_ftw(frequency)[source]

Returns the frequency tuning word corresponding to the given frequency.

ftw_to_frequency(ftw)[source]

Returns the frequency corresponding to the given frequency tuning word.

init()[source]

Initialize and configure the DDS.

Sets up SPI mode, confirms chip presence, powers down unused blocks, and configures the PLL. Does not wait for PLL lock. Uses the IO_UPDATE signal multiple times.

read(addr, length)[source]

Variable length read from a register. Up to 4 bytes.

Parameters:
  • addr – Register address
  • length – Length in bytes (1-4)
Returns:

Data read

set(frequency, phase=0.0)[source]

Set profile 0 data in SI units.

See also

set_mu()

Parameters:
  • ftw – Frequency in Hz
  • pow – Phase tuning word in turns
set_att(att)[source]

Set digital step attenuator in SI units.

Parameters:att – Attenuation in dB. Higher values mean more attenuation.
set_att_mu(att)[source]

Set digital step attenuator in machine units.

Parameters:att – Attenuation setting, 8 bit digital.
set_mu(ftw, pow)[source]

Set profile 0 data in machine units.

After the SPI transfer, the shared IO update pin is pulsed to activate the data.

Parameters:
  • ftw – Frequency tuning word: 32 bit unsigned.
  • pow – Phase tuning word: 16 bit unsigned.
turns_to_pow(phase)[source]

Returns the phase offset word corresponding to the given phase.

write(addr, data, length)[source]

Variable length write to a register. Up to 4 bytes.

Parameters:
  • addr – Register address
  • data – Data to be written: int32
  • length – Length in bytes (1-4)

artiq.coredevice.ad9914 module

Driver for the AD9914 DDS (with parallel bus) on RTIO.

class artiq.coredevice.ad9914.AD9914(dmgr, sysclk, bus_channel, channel, core_device='core')[source]

Driver for one AD9914 DDS channel.

The time cursor is not modified by any function in this class.

Output event replacement is not supported and issuing commands at the same time is an error.

Parameters:
  • sysclk – DDS system frequency. The DDS system clock must be a phase-locked multiple of the RTIO clock.
  • bus_channel – RTIO channel number of the DDS bus.
  • channel – channel number (on the bus) of the DDS device to control.
amplitude_to_asf(amplitude)[source]

Returns amplitude scale factor corresponding to given amplitude.

asf_to_amplitude(asf)[source]

Returns the amplitude corresponding to the given amplitude scale factor.

exit_x()[source]

Exits extended-resolution mode.

frequency_to_ftw(frequency)[source]

Returns the frequency tuning word corresponding to the given frequency.

frequency_to_xftw(frequency)[source]

Returns the frequency tuning word corresponding to the given frequency (extended resolution mode).

ftw_to_frequency(ftw)[source]

Returns the frequency corresponding to the given frequency tuning word.

init()[source]

Resets and initializes the DDS channel.

This needs to be done for each DDS channel before it can be used, and it is recommended to use the startup kernel for this purpose.

init_sync(sync_delay)[source]

Resets and initializes the DDS channel as well as configures the AD9914 DDS for synchronisation. The synchronisation procedure follows the steps outlined in the AN-1254 application note.

This needs to be done for each DDS channel before it can be used, and it is recommended to use the startup kernel for this.

This function cannot be used in a batch; the correct way of initializing multiple DDS channels is to call this function sequentially with a delay between the calls. 10ms provides a good timing margin.

Parameters:sync_delay – integer from 0 to 0x3f that sets the value of SYNC_OUT (bits 3-5) and SYNC_IN (bits 0-2) delay ADJ bits.
pow_to_turns(pow)[source]

Returns the phase in turns corresponding to the given phase offset word.

set(frequency, phase=0.0, phase_mode=-1, amplitude=1.0)[source]

Like set_mu(), but uses Hz and turns.

set_mu(ftw, pow=0, phase_mode=-1, asf=4095, ref_time=-1)[source]

Sets the DDS channel to the specified frequency and phase.

This uses machine units (FTW and POW). The frequency tuning word width is 32, the phase offset word width is 16, and the amplitude scale factor 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.

Parameters:
  • ftw – frequency to generate.
  • pow – adds an offset to the phase.
  • phase_mode – if specified, overrides the default phase mode set by set_phase_mode() for this call.
  • ref_time – reference time used to compute phase. Specifying this makes it easier to have a well-defined phase relationship between DDSes on the same bus that are updated at a similar time.
Returns:

Resulting phase offset word after application of phase tracking offset. When using PHASE_MODE_CONTINUOUS in subsequent calls, use this value as the “current” phase.

set_phase_mode(phase_mode)[source]

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.

Warning

This setting may become inconsistent when used as part of a DMA recording. When using DMA, it is recommended to specify the phase mode explicitly when calling set() or set_mu().

set_x(frequency, amplitude=1.0)[source]

Like set_x_mu(), but uses Hz and turns.

Note that the precision of float is less than the precision of the extended frequency tuning word.

set_x_mu(xftw, amplitude=4095)[source]

Set the DDS frequency and amplitude with an extended-resolution (63-bit) frequency tuning word.

Phase control is not implemented in this mode; the phase offset can assume any value.

After this function has been called, exit extended-resolution mode before calling functions that use standard-resolution mode.

turns_to_pow(turns)[source]

Returns the phase offset word corresponding to the given phase in turns.

xftw_to_frequency(xftw)[source]

Returns the frequency corresponding to the given frequency tuning word (extended resolution mode).

artiq.coredevice.spline module

class artiq.coredevice.spline.Spline(width, time_width, channel, core_device, scale=1.0)[source]

Spline interpolating RTIO channel.

One knot of a polynomial basis spline (B-spline) \(u(t)\) is defined by the coefficients \(u_n\) up to order \(n = k\). If the coefficients are evaluated starting at time \(t_0\), the output \(u(t)\) for \(t > t_0, t_0\) is:

\[\begin{split}u(t) &= \sum_{n=0}^k \frac{u_n}{n!} (t - t_0)^n \\ &= u_0 + u_1 (t - t_0) + \frac{u_2}{2} (t - t_0)^2 + \dots\end{split}\]

This class contains multiple methods to convert spline knot data from SI to machine units and multiple methods that set the current spline coefficient data. None of these advance the timeline. The smooth() method is the only method that advances the timeline.

Parameters:
  • width – Width in bits of the quantity that this spline controls
  • time_width – Width in bits of the time counter of this spline
  • channel – RTIO channel number
  • core_device – Core device that this spline is attached to
  • scale – Scale for conversion between machine units and physical units; to be given as the “full scale physical value”.
coeff_as_packed(coeff)[source]

Convert floating point spline coefficients into 32 bit integer packed data.

This is a host-only method that can be used to generate packed spline coefficient data to be frozen into kernels at compile time.

coeff_as_packed_mu(coeff64)[source]

Pack 64 bit integer machine units coefficients into 32 bit integer RTIO data list.

This is a host-only method that can be used to generate packed spline coefficient data to be frozen into kernels at compile time.

coeff_to_mu(coeff, coeff64)[source]

Convert a floating point list of coefficients into a 64 bit integer (preallocated).

Parameters:
  • coeff – TList(TFloat) list of coefficients in physical units.
  • coeff64 – TList(TInt64) preallocated list of coefficients in machine units.
from_mu(value: numpy.int32) → float[source]

Convert 32 bit integer value from machine units to floating point physical units.

pack_coeff_mu(coeff, packed)[source]

Pack coefficients into RTIO data

Parameters:
  • coeff – TList(TInt64) list of machine units spline coefficients. Lowest (zeroth) order first. The coefficient list is zero-extended by the RTIO gateware.
  • packed – TList(TInt32) list for packed RTIO data. Must be pre-allocated. Length in bits is n*width + (n - 1)*n//2*time_width
set(value: float)[source]

Set spline value.

Parameters:value – Spline value relative to full-scale.
set_coeff(coeff)[source]

Set spline coefficients.

Missing coefficients (high order) are zero-extended byt the RTIO gateware.

If more coefficients are supplied than the gateware supports the extra coefficients are ignored.

Parameters:value – List of floating point spline coefficients, lowest order (constant) coefficient first. Units are the unit of this spline’s value times increasing powers of 1/s.
set_coeff_mu(value)[source]

Set spline raw values.

Parameters:value – Spline packed raw values.
set_mu(value: numpy.int32)[source]

Set spline value (machine units).

Parameters:value – Spline value in integer machine units.
smooth(start: float, stop: float, duration: float, order: numpy.int32)[source]

Initiate an interpolated value change.

For zeroth order (step) interpolation, the step is at start + duration/2.

First order interpolation corresponds to a linear value ramp from start to stop over duration.

The third order interpolation is constrained to have zero first order derivative at both start and stop.

For first order and third order interpolation (linear and cubic) the interpolator needs to be stopped explicitly at the stop time (e.g. by setting spline coefficient data or starting a new smooth() interpolation).

This method advances the timeline by duration.

Parameters:
  • start – Initial value of the change. In physical units.
  • stop – Final value of the change. In physical units.
  • duration – Duration of the interpolation. In physical units.
  • order – Order of the interpolation. Only 0, 1, and 3 are valid: step, linear, cubic.
to_mu(value: float) → numpy.int32[source]

Convert floating point value from physical units to 32 bit integer machine units.

to_mu64(value: float) → numpy.int64[source]

Convert floating point value from physical units to 64 bit integer machine units.

artiq.coredevice.sawg module

Driver for the Smart Arbitrary Waveform Generator (SAWG) on RTIO.

The SAWG is an “improved DDS” built in gateware and interfacing to high-speed DACs.

Output event replacement is supported except on the configuration channel.

class artiq.coredevice.sawg.Config(channel, core, cordic_gain=1.0)[source]

SAWG configuration.

Exposes the configurable quantities of a single SAWG channel.

Access to the configuration registers for a SAWG channel can not be concurrent. There must be at least _rtio_interval machine units of delay between accesses. Replacement is not supported and will be lead to an RTIOCollision as this is likely a programming error. All methods therefore advance the timeline by the duration of one configuration register transfer.

Parameters:
  • channel – RTIO channel number of the channel.
  • core – Core device.
set_clr(clr0: numpy.int32, clr1: numpy.int32, clr2: numpy.int32)[source]

Set the accumulator clear mode for the three phase accumulators.

When the clr bit for a given DDS/DUC phase accumulator is set, that phase accumulator will be cleared with every phase offset RTIO command and the output phase of the DDS/DUC will be exactly the phase RTIO value (“absolute phase update mode”).

\[q^\prime(t) = p^\prime + (t - t^\prime) f^\prime\]

In turn, when the bit is cleared, the phase RTIO channels determine a phase offset to the current (carrier-) value of the DDS/DUC phase accumulator. This “relative phase update mode” is sometimes also called “continuous phase mode”.

\[q^\prime(t) = q(t^\prime) + (p^\prime - p) + (t - t^\prime) f^\prime\]

Where:

  • \(q\), \(q^\prime\): old/new phase accumulator
  • \(p\), \(p^\prime\): old/new phase offset
  • \(f^\prime\): new frequency
  • \(t^\prime\): timestamp of setting new \(p\), \(f\)
  • \(t\): running time
Parameters:
  • clr0 – Auto-clear phase accumulator of the phase0/ frequency0 DUC. Default: True
  • clr1 – Auto-clear phase accumulator of the phase1/ frequency1 DDS. Default: True
  • clr2 – Auto-clear phase accumulator of the phase2/ frequency2 DDS. Default: True
set_div(div: numpy.int32, n: numpy.int32 = 0)[source]

Set the spline evolution divider and current counter value.

The divider and the spline evolution are synchronized across all spline channels within a SAWG channel. The DDS/DUC phase accumulators always evolves at full speed.

Note

The spline evolution divider has not been tested extensively and is currently considered a technological preview only.

Parameters:
  • div – Spline evolution divider, such that t_sawg_spline/t_rtio_coarse = div + 1. Default: 0.
  • n – Current value of the counter. Default: 0.
set_duc_max(limit: float)[source]

Set the digital up-converter (DUC) I and Q data summing junctions upper limit.

Each of the three summing junctions has a saturating adder with configurable upper and lower limits. The three summing junctions are:

  • At the in-phase input to the phase0/frequency0 fast DUC, after the anti-aliasing FIR filter.

  • At the quadrature input to the phase0/frequency0 fast DUC, after the anti-aliasing FIR filter. The in-phase and quadrature data paths both use the same limits.

  • Before the DAC, where the following three data streams are added together:

    • the output of the offset spline,
    • (optionally, depending on i_enable) the in-phase output of the phase0/frequency0 fast DUC, and
    • (optionally, depending on q_enable) the quadrature output of the phase0/frequency0 fast DUC of the buddy channel.

Refer to the documentation of SAWG for a mathematical description of the summing junctions.

Parameters:limit – Limit value [-1, 1]. The output of the limiter will never exceed this limit. The default limits are the full range [-1, 1].

See also

set_duc_max_mu(limit: numpy.int32)[source]

Set the digital up-converter (DUC) I and Q data summing junctions upper limit. In machine units.

The default limits are chosen to reach maximum and minimum DAC output amplitude.

For a description of the limiter functions in normalized units see:

See also

set_duc_max()

set_duc_min(limit: float)[source]

See also

set_duc_max()

set_duc_min_mu(limit: numpy.int32)[source]

See also

set_duc_max_mu()

set_iq_en(i_enable: numpy.int32, q_enable: numpy.int32)[source]

Enable I/Q data on this DAC channel.

Every pair of SAWG channels forms a buddy pair. The iq_en configuration controls which DDS data is emitted to the DACs.

Refer to the documentation of SAWG for a mathematical description of i_enable and q_enable.

Note

Quadrature data from the buddy channel is currently a technological preview only. The data is ignored in the SAWG gateware and not added to the DAC output. This is equivalent to the q_enable switch always being 0.

Parameters:
  • i_enable – Controls adding the in-phase DUC-DDS data of this SAWG channel to this DAC channel. Default: 1.
  • q_enable – controls adding the quadrature DUC-DDS data of this SAWG’s buddy channel to this DAC channel. Default: 0.
set_out_max(limit: float)[source]

See also

set_duc_max()

set_out_max_mu(limit: numpy.int32)[source]

See also

set_duc_max_mu()

set_out_min(limit: float)[source]

See also

set_duc_max()

set_out_min_mu(limit: numpy.int32)[source]

See also

set_duc_max_mu()

class artiq.coredevice.sawg.SAWG(dmgr, channel_base, parallelism, core_device='core')[source]

Smart arbitrary waveform generator channel. The channel is parametrized as:

oscillators = exp(2j*pi*(frequency0*t + phase0))*(
    amplitude1*exp(2j*pi*(frequency1*t + phase1)) +
    amplitude2*exp(2j*pi*(frequency2*t + phase2)))

output = (offset +
    i_enable*Re(oscillators) +
    q_enable*Im(buddy_oscillators))

This parametrization can be viewed as two complex (quadrature) oscillators (frequency1/phase1 and frequency2/phase2) that are executing and sampling at the coarse RTIO frequency. They can represent frequencies within the first Nyquist zone from -f_rtio_coarse/2 to f_rtio_coarse/2.

Note

The coarse RTIO frequency f_rtio_coarse is the inverse of ref_period*multiplier. Both are arguments of the Core device, specified in the device database device_db.py.

The sum of their outputs is then interpolated by a factor of parallelism (2, 4, 8 depending on the bitstream) using a finite-impulse-response (FIR) anti-aliasing filter (more accurately a half-band filter).

The filter is followed by a configurable saturating limiter.

After the limiter, the data is shifted in frequency using a complex digital up-converter (DUC, frequency0/phase0) running at parallelism times the coarse RTIO frequency. The first Nyquist zone of the DUC extends from -f_rtio_coarse*parallelism/2 to f_rtio_coarse*parallelism/2. Other Nyquist zones are usable depending on the interpolation/modulation options configured in the DAC.

The real/in-phase data after digital up-conversion can be offset using another spline interpolator offset.

The i_enable/q_enable switches enable emission of quadrature signals for later analog quadrature mixing distinguishing upper and lower sidebands and thus doubling the bandwidth. They can also be used to emit four-tone signals.

Note

Quadrature data from the buddy channel is currently ignored in the SAWG gateware and not added to the DAC output. This is equivalent to the q_enable switch always being 0.

The configuration channel and the nine artiq.coredevice.spline.Spline interpolators are accessible as attributes:

  • config: Config
  • offset, amplitude1, amplitude2: in units of full scale
  • phase0, phase1, phase2: in units of turns
  • frequency0, frequency1, frequency2: in units of Hz

Note

The latencies (pipeline depths) of the nine data channels (i.e. all except config) are matched. Equivalent channels (e.g. phase1 and phase2) are exactly matched. Channels of different type or functionality (e.g. offset vs amplitude1, DDS vs DUC, phase0 vs phase1) are only matched to within one coarse RTIO cycle.

Parameters:
  • channel_base – RTIO channel number of the first channel (amplitude). The configuration channel and frequency/phase/amplitude channels are then assumed to be successive channels.
  • parallelism – Number of output samples per coarse RTIO clock cycle.
  • core_device – Name of the core device that this SAWG is on.
reset()[source]

Re-establish initial conditions.

This clears all spline interpolators, accumulators and configuration settings.

This method advances the timeline by the time required to perform all 7 writes to the configuration channel, plus 9 coarse RTIO cycles.

DAC/ADC drivers

artiq.coredevice.ad53xx module

“RTIO driver for the Analog Devices AD53[67][0123] family of multi-channel Digital to Analog Converters.

Output event replacement is not supported and issuing commands at the same time is an error.

class artiq.coredevice.ad53xx.AD53xx(dmgr, spi_device, ldac_device=None, clr_device=None, chip_select=1, div_write=4, div_read=16, vref=5.0, offset_dacs=8192, core='core')[source]

Analog devices AD53[67][0123] family of multi-channel Digital to Analog Converters.

Parameters:
  • spi_device – SPI bus device name
  • ldac_device – LDAC RTIO TTLOut channel name (optional)
  • clr_device – CLR RTIO TTLOut channel name (optional)
  • chip_select – Value to drive on SPI chip select lines during transactions (default: 1)
  • div_write – SPI clock divider for write operations (default: 4, 50MHz max SPI clock with {t_high, t_low} >=8ns)
  • div_read – SPI clock divider for read operations (default: 8, not optimized for speed, but cf data sheet t22: 25ns min SCLK edge to SDO valid)
  • vref – DAC reference voltage (default: 5.)
  • offset_dacs – Initial register value for the two offset DACs, device dependent and must be set correctly for correct voltage to mu conversions. Knowledge of his state is not transferred between experiments. (default: 8192)
  • core_device – Core device name (default: “core”)
calibrate(channel, vzs, vfs)[source]

Two-point calibration of a DAC channel.

Programs the offset and gain register to trim out DAC errors. Does not take effect until LDAC is pulsed (see :meth load:).

Calibration consists of measuring the DAC output voltage for a channel with the DAC set to zero-scale (0x0000) and full-scale (0xffff).

Note that only negative offsets and full-scale errors (DAC gain too high) can be calibrated in this fashion.

Parameters:channel – The number of the calibrated channel
Params vzs:Measured voltage with the DAC set to zero-scale (0x0000)
Params vfs:Measured voltage with the DAC set to full-scale (0xffff)
init(blind=False)[source]

Configures the SPI bus, drives LDAC and CLR high, programmes the offset DACs, and enables overtemperature shutdown.

This method must be called before any other method at start-up or if the SPI bus has been accessed by another device.

Parameters:blind – If True, do not attempt to read back control register or check for overtemperature.
load()[source]

Pulse the LDAC line.

Note that there is a <= 1.5us “BUSY” period (t10) after writing to a DAC input/gain/offset register. All DAC registers may be programmed normally during the busy period, however LDACs during the busy period cause the DAC output to change after the BUSY period has completed, instead of the usual immediate update on LDAC behaviour.

This method advances the timeline by two RTIO clock periods.

read_reg(channel=0, op=1024)[source]

Read a DAC register.

This method advances the timeline by the duration of two SPI transfers plus two RTIO coarse cycles plus 270 ns and consumes all slack.

Parameters:
  • channel – Channel number to read from (default: 0)
  • op – Operation to perform, one of AD53XX_READ_X1A, AD53XX_READ_X1B, AD53XX_READ_OFFSET, AD53XX_READ_GAIN etc. (default: AD53XX_READ_X1A).
Returns:

The 16 bit register value

set_dac(voltages, channels=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39])[source]

Program multiple DAC channels and pulse LDAC to update the DAC outputs.

This method does not advance the timeline; write events are scheduled in the past. The DACs will synchronously start changing their output levels now.

If no LDAC device was defined, the LDAC pulse is skipped.

Parameters:
  • voltages – list of voltages to program the DAC channels to
  • channels – list of DAC channels to program. If not specified, we program the DAC channels sequentially, starting at 0.
set_dac_mu(values, channels=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39])[source]

Program multiple DAC channels and pulse LDAC to update the DAC outputs.

This method does not advance the timeline; write events are scheduled in the past. The DACs will synchronously start changing their output levels now.

If no LDAC device was defined, the LDAC pulse is skipped.

See :meth load:.

Parameters:
  • values – list of DAC values to program
  • channels – list of DAC channels to program. If not specified, we program the DAC channels sequentially, starting at 0.
write_dac(channel, voltage)[source]

Program the DAC output voltage for a channel.

The DAC output is not updated until LDAC is pulsed (see :meth load:). This method advances the timeline by the duration of one SPI transfer.

write_dac_mu(channel, value)[source]

Program the DAC input register for a channel.

The DAC output is not updated until LDAC is pulsed (see :meth load:). This method advances the timeline by the duration of one SPI transfer.

write_gain_mu(channel, gain=65535)[source]

Program the gain register for a DAC channel.

The DAC output is not updated until LDAC is pulsed (see :meth load:). This method advances the timeline by the duration of one SPI transfer.

Parameters:gain – 16-bit gain register value (default: 0xffff)
write_offset(channel, voltage)[source]

Program the DAC offset voltage for a channel.

An offset of +V can be used to trim out a DAC offset error of -V. The DAC output is not updated until LDAC is pulsed (see :meth load:). This method advances the timeline by the duration of one SPI transfer.

Parameters:voltage – the offset voltage
write_offset_dacs_mu(value)[source]

Program the OFS0 and OFS1 offset DAC registers.

Writes to the offset DACs take effect immediately without requiring a LDAC. This method advances the timeline by the duration of two SPI transfers.

Parameters:value – Value to set both offset DAC registers to
write_offset_mu(channel, offset=32768)[source]

Program the offset register for a DAC channel.

The DAC output is not updated until LDAC is pulsed (see :meth load:). This method advances the timeline by the duration of one SPI transfer.

Parameters:offset – 16-bit offset register value (default: 0x8000)
artiq.coredevice.ad53xx.ad53xx_cmd_read_ch(channel, op)[source]

Returns the word that must be written to the DAC to read a given DAC channel register.

Parameters:
  • channel – DAC channel to read (8 bits)
  • op – The channel register to read, one of AD53XX_READ_X1A, AD53XX_READ_X1B, AD53XX_READ_OFFSET, AD53XX_READ_GAIN etc.
Returns:

The 24-bit word to be written to the DAC to initiate read

artiq.coredevice.ad53xx.ad53xx_cmd_write_ch(channel, value, op)[source]

Returns the word that must be written to the DAC to set a DAC channel register to a given value.

Parameters:
  • channel – DAC channel to write to (8 bits)
  • value – 16-bit value to write to the register
  • op – The channel register to write to, one of AD53XX_CMD_DATA, AD53XX_CMD_OFFSET or AD53XX_CMD_GAIN.
Returns:

The 24-bit word to be written to the DAC

artiq.coredevice.ad53xx.voltage_to_mu(voltage, offset_dacs=8192, vref=5.0)[source]

Returns the DAC register value required to produce a given output voltage, assuming offset and gain errors have been trimmed out.

Also used to return offset register value required to produce a given voltage when the DAC register is set to mid-scale. An offset of V can be used to trim out a DAC offset error of -V.

Parameters:
  • voltage – Voltage
  • offset_dacs – Register value for the two offset DACs (default: 0x2000)
  • vref – DAC reference voltage (default: 5.)

artiq.coredevice.zotino module

RTIO driver for the Zotino 32-channel, 16-bit 1MSPS DAC.

Output event replacement is not supported and issuing commands at the same time is an error.

class artiq.coredevice.zotino.Zotino(dmgr, spi_device, ldac_device=None, clr_device=None, div_write=4, div_read=8, vref=5.0, core='core')[source]

Zotino 32-channel, 16-bit 1MSPS DAC.

Controls the AD5372 DAC and the 8 user LEDs via a shared SPI interface.

Parameters:
  • spi_device – SPI bus device name
  • ldac_device – LDAC RTIO TTLOut channel name.
  • clr_device – CLR RTIO TTLOut channel name.
  • div_write – SPI clock divider for write operations (default: 4, 50MHz max SPI clock)
  • div_read – SPI clock divider for read operations (default: 8, not optimized for speed, but cf data sheet t22: 25ns min SCLK edge to SDO valid)
  • vref – DAC reference voltage (default: 5.)
  • core_device – Core device name (default: “core”)
set_leds(leds)[source]

Sets the states of the 8 user LEDs.

Parameters:leds – 8-bit word with LED state

artiq.coredevice.sampler module

class artiq.coredevice.sampler.Sampler(dmgr, spi_adc_device, spi_pgia_device, cnv_device, div=8, gains=0, core_device='core')[source]

Sampler ADC.

Controls the LTC2320-16 8 channel 16 bit ADC with SPI interface and the switchable gain instrumentation amplifiers.

Parameters:
  • spi_adc_device – ADC SPI bus device name
  • spi_pgia_device – PGIA SPI bus device name
  • cnv_device – CNV RTIO TTLOut channel name
  • div – SPI clock divider (default: 8)
  • gains – Initial value for PGIA gains shift register (default: 0x0000). Knowledge of this state is not transferred between experiments.
  • core_device – Core device name
get_gains_mu()[source]

Read the PGIA gain settings of all channels.

Returns:The PGIA gain settings in machine units.
init()[source]

Initialize the device.

Sets up SPI channels.

sample(data)[source]

Acquire a set of samples.

See also

sample_mu()

Parameters:data – List of floating point data samples to fill.
sample_mu(data)[source]

Acquire a set of samples.

Perform a conversion and transfer the samples.

This assumes that the input FIFO of the ADC SPI RTIO channel is deep enough to buffer the samples (half the length of data deep). If it is not, there will be RTIO input overflows.

Parameters:data – List of data samples to fill. Must have even length. Samples are always read from the last channel (channel 7) down. The data list will always be filled with the last item holding to the sample from channel 7.
set_gain_mu(channel, gain)[source]

Set instrumentation amplifier gain of a channel.

The four gain settings (0, 1, 2, 3) corresponds to gains of (1, 10, 100, 1000) respectively.

Parameters:
  • channel – Channel index
  • gain – Gain setting
artiq.coredevice.sampler.adc_mu_to_volt(data, gain=0)[source]

Convert ADC data in machine units to Volts.

Parameters:
  • data – 16 bit signed ADC word
  • gain – PGIA gain setting (0: 1, ..., 3: 1000)
Returns:

Voltage in Volts

artiq.coredevice.novogorny module

class artiq.coredevice.novogorny.Novogorny(dmgr, spi_device, cnv_device, div=8, gains=0, core_device='core')[source]

Novogorny ADC.

Controls the LTC2335-16 8 channel ADC with SPI interface and the switchable gain instrumentation amplifiers using a shift register.

Parameters:
  • spi_device – SPI bus device name
  • cnv_device – CNV RTIO TTLOut channel name
  • div – SPI clock divider (default: 8)
  • gains – Initial value for PGIA gains shift register (default: 0x0000). Knowledge of this state is not transferred between experiments.
  • core_device – Core device name
burst_mu(data, dt_mu, ctrl=0)[source]

Acquire a burst of samples.

If the burst is too long and the sample rate too high, there will be RTIO input overflows.

High sample rates lead to gain errors since the impedance between the instrumentation amplifier and the ADC is high.

Parameters:
  • data – List of data values to write result packets into. In machine units.
  • dt – Sample interval in machine units.
  • ctrl – ADC control word to write during each result packet transfer.
configure(data)[source]

Set up the ADC sequencer.

Parameters:data – List of 8 bit control words to write into the sequencer table.
sample(next_ctrl=0)[source]

Acquire a sample

See also

sample_mu()

Parameters:next_ctrl – ADC control word for the next sample
Returns:The ADC result packet (Volt)
sample_mu(next_ctrl=0)[source]

Acquire a sample:

Perform a conversion and transfer the sample.

Parameters:next_ctrl – ADC control word for the next sample
Returns:The ADC result packet (machine units)
set_gain_mu(channel, gain)[source]

Set instrumentation amplifier gain of a channel.

The four gain settings (0, 1, 2, 3) corresponds to gains of (1, 10, 100, 1000) respectively.

Parameters:
  • channel – Channel index
  • gain – Gain setting
artiq.coredevice.novogorny.adc_channel(data)[source]

Return the channel index from a result packet

artiq.coredevice.novogorny.adc_ctrl(channel=1, softspan=7, valid=1)[source]

Build a LTC2335-16 control word

artiq.coredevice.novogorny.adc_data(data)[source]

Return the ADC value from a result packet

artiq.coredevice.novogorny.adc_softspan(data)[source]

Return the softspan configuration index from a result packet

artiq.coredevice.novogorny.adc_value(data, v_ref=5.0)[source]

Convert a ADC result packet to SI units (Volt)

Miscellaneous

artiq.coredevice.suservo module

class artiq.coredevice.suservo.Channel(dmgr, channel, servo_device)[source]

Sampler-Urukul Servo channel

Parameters:
  • channel – RTIO channel number
  • servo_device – Name of the parent SUServo device
get_profile_mu(profile, data)[source]

Retrieve profile data.

Profile data is returned in the data argument in machine units packed as: [ftw >> 16, b1, pow, adc | (delay << 8), offset, a1, ftw & 0xffff, b0].

See also

The individual fields are described in set_iir_mu() and set_dds_mu().

This method advances the timeline by 32 µs and consumes all slack.

Parameters:
  • profile – Profile number (0-31)
  • data – List of 8 integers to write the profile data into
get_y(profile)[source]

Get a profile’s IIR state (filter output, Y0).

The IIR state is also know as the “integrator”, or the DDS amplitude scale factor. It is 18 bits wide and unsigned.

This method does not advance the timeline but consumes all slack.

Parameters:profile – Profile number (0-31)
Returns:IIR filter output in Y0 units of full scale
get_y_mu(profile)[source]

Get a profile’s IIR state (filter output, Y0) in machine units.

The IIR state is also know as the “integrator”, or the DDS amplitude scale factor. It is 18 bits wide and unsigned.

This method does not advance the timeline but consumes all slack.

Parameters:profile – Profile number (0-31)
Returns:18 bit unsigned Y0
set(en_out, en_iir=0, profile=0)[source]

Operate channel.

This method does not advance the timeline. Output RF switch setting takes effect immediately and is independent of any other activity (profile settings, other channels). The RF switch behaves like artiq.coredevice.ttl.TTLOut. RTIO event replacement is supported. IIR updates take place once the RF switch has been enabled for the configured delay and the profile setting has been stable. Profile changes take between one and two servo cycles to reach the DDS.

Parameters:
  • en_out – RF switch enable
  • en_iir – IIR updates enable
  • profile – Active profile (0-31)
set_dds(profile, frequency, offset, phase=0.0)[source]

Set profile DDS coefficients.

This method advances the timeline by four servo memory accesses. Profile parameter changes are not synchronized. Activate a different profile or stop the servo to ensure synchronous changes.

Parameters:
  • profile – Profile number (0-31)
  • frequency – DDS frequency in Hz
  • offset – IIR offset (negative setpoint) in units of full scale. For positive ADC voltages as setpoints, this should be negative. Due to rounding and representation as two’s complement, offset=1 can not be represented while offset=-1 can.
  • phase – DDS phase in turns
set_dds_mu(profile, ftw, offs, pow_=0)[source]

Set profile DDS coefficients in machine units.

See also

set_amplitude()

Parameters:
  • profile – Profile number (0-31)
  • ftw – Frequency tuning word (32 bit unsigned)
  • offs – IIR offset (17 bit signed)
  • pow – Phase offset word (16 bit)
set_iir(profile, adc, kp, ki=0.0, g=0.0, delay=0.0)[source]

Set profile IIR coefficients.

This method advances the timeline by four servo memory accesses. Profile parameter changes are not synchronized. Activate a different profile or stop the servo to ensure synchronous changes.

Gains are given in units of output full per scale per input full scale.

The transfer function is (up to time discretization and coefficient quantization errors):

\[H(s) = k_p + \frac{k_i}{s + \frac{k_i}{g}}\]
Where:
  • \(s = \sigma + i\omega\) is the complex frequency
  • \(k_p\) is the proportional gain
  • \(k_i\) is the integrator gain
  • \(g\) is the integrator gain limit
Parameters:
  • profile – Profile number (0-31)
  • adc – ADC channel to take IIR input from (0-7)
  • kp – Proportional gain (1). This is usually negative (closed loop, positive ADC voltage, positive setpoint). When 0, this implements a pure I controller.
  • ki – Integrator gain (rad/s). When 0 (the default) this implements a pure P controller. Same sign as kp.
  • g – Integrator gain limit (1). When 0 (the default) the integrator gain limit is infinite. Same sign as ki.
  • delay – Delay (in seconds, 0-300 µs) before allowing IIR updates after invoking set(). This is rounded to the nearest number of servo cycles (~1.2 µs). Since the RF switch (set()) can be opened at any time relative to the servo cycle, the first DDS update that carries updated IIR data will occur approximately between delay + 1 cycle and delay + 2 cycles after set().
set_iir_mu(profile, adc, a1, b0, b1, dly=0)[source]

Set profile IIR coefficients in machine units.

The recurrence relation is (all data signed and MSB aligned):

\[a_0 y_n = a_1 y_{n - 1} + b_0 (x_n + o)/2 + b_1 (x_{n - 1} + o)/2\]

Where:

  • \(y_n\) and \(y_{n-1}\) are the current and previous filter outputs, clipped to \([0, 1[\).
  • \(x_n\) and \(x_{n-1}\) are the current and previous filter inputs in \([-1, 1[\).
  • \(o\) is the offset
  • \(a_0\) is the normalization factor \(2^{11}\)
  • \(a_1\) is the feedback gain
  • \(b_0\) and \(b_1\) are the feedforward gains for the two delays

See also

set_iir()

Parameters:
  • profile – Profile number (0-31)
  • adc – ADC channel to take IIR input from (0-7)
  • a1 – 18 bit signed A1 coefficient (Y1 coefficient, feedback, integrator gain)
  • b0 – 18 bit signed B0 coefficient (recent, X0 coefficient, feed forward, proportional gain)
  • b1 – 18 bit signed B1 coefficient (old, X1 coefficient, feed forward, proportional gain)
  • dly – IIR update suppression time. In units of IIR cycles (~1.2 µs, 0-255).
set_y(profile, y)[source]

Set a profile’s IIR state (filter output, Y0).

The IIR state is also know as the “integrator”, or the DDS amplitude scale factor. It is 18 bits wide and unsigned.

This method must not be used when the servo could be writing to the same location. Either deactivate the profile, or deactivate IIR updates, or disable servo iterations.

This method advances the timeline by one servo memory access.

Parameters:
  • profile – Profile number (0-31)
  • y – IIR state in units of full scale
set_y_mu(profile, y)[source]

Set a profile’s IIR state (filter output, Y0) in machine units.

The IIR state is also know as the “integrator”, or the DDS amplitude scale factor. It is 18 bits wide and unsigned.

This method must not be used when the servo could be writing to the same location. Either deactivate the profile, or deactivate IIR updates, or disable servo iterations.

This method advances the timeline by one servo memory access.

Parameters:
  • profile – Profile number (0-31)
  • y – 17 bit unsigned Y0
class artiq.coredevice.suservo.SUServo(dmgr, channel, pgia_device, cpld0_device, cpld1_device, dds0_device, dds1_device, gains=0, core_device='core')[source]

Sampler-Urukul Servo parent and configuration device.

Sampler-Urukul Servo is a integrated device controlling one 8-channel ADC (Sampler) and two 4-channel DDS (Urukuls) with a DSP engine connecting the ADC data and the DDS output amplitudes to enable feedback. SU Servo can for example be used to implement intensity stabilization of laser beams with an amplifier and AOM driven by Urukul and a photodetector connected to Sampler.

Additionally SU Servo supports multiple preconfigured profiles per channel and features like automatic integrator hold.

Notes

  • See the SU Servo variant of the Kasli target for an example of how to connect the gateware and the devices. Sampler and each Urukul need two EEM connections.
  • Ensure that both Urukuls are AD9910 variants and have the on-board dip switches set to 1100 (first two on, last two off).
  • Refer to the Sampler and Urukul documentation and the SU Servo example device database for runtime configuration of the devices (PLLs, gains, clock routing etc.)
Parameters:
  • channel – RTIO channel number
  • pgia_device – Name of the Sampler PGIA gain setting SPI bus
  • cpld0_device – Name of the first Urukul CPLD SPI bus
  • cpld1_device – Name of the second Urukul CPLD SPI bus
  • dds0_device – Name of the AD9910 device for the DDS on the first Urukul
  • dds1_device – Name of the AD9910 device for the DDS on the second Urukul
  • gains – Initial value for PGIA gains shift register (default: 0x0000). Knowledge of this state is not transferred between experiments.
  • core_device – Core device name
get_adc(channel)[source]

Get an ADC reading (IIR filter input X0).

This method does not advance the timeline but consumes all slack.

The PGIA gain setting must be known prior to using this method, either by setting the gain (set_pgia_mu()) or by supplying it (gains or via the constructor/device database).

Parameters:adc – ADC channel number (0-7)
Returns:ADC voltage
get_adc_mu(adc)[source]

Get an ADC reading (IIR filter input X0) in machine units.

This method does not advance the timeline but consumes all slack.

Parameters:adc – ADC channel number (0-7)
Returns:17 bit signed X0
get_status()[source]

Get current SU Servo status.

This method does not advance the timeline but consumes all slack.

The done bit indicates that a SU Servo cycle has completed. It is pulsed for one RTIO cycle every SU Servo cycle and asserted continuously when the servo is not enabled and the pipeline has drained (the last DDS update is done).

This method returns and clears the clip indicator for all channels. An asserted clip indicator corresponds to the servo having encountered an input signal on an active channel that would have resulted in the IIR state exceeding the output range.

Returns:Status. Bit 0: enabled, bit 1: done, bits 8-15: channel clip indicators.
init()[source]

Initialize the servo, Sampler and both Urukuls.

Leaves the servo disabled (see set_config()), resets and configures all DDS.

Urukul initialization is performed blindly as there is no readback from the DDS or the CPLDs.

This method does not alter the profile configuration memory or the channel controls.

read(addr)[source]

Read from servo memory.

This method does not advance the timeline but consumes all slack.

Parameters:addr – Memory location address.
set_config(enable)[source]

Set SU Servo configuration.

This method advances the timeline by one servo memory access. It does not support RTIO event replacement.

Parameters:(int) (enable) – Enable servo operation. Enabling starts servo iterations beginning with the ADC sampling stage. The first DDS update will happen about two servo cycles (~2.3 µs) after enabling the servo. The delay is deterministic. This also provides a mean for synchronization of servo updates to other RTIO activity. Disabling takes up to two servo cycles (~2.3 µs) to clear the processing pipeline.
set_pgia_mu(channel, gain)[source]

Set instrumentation amplifier gain of a ADC channel.

The four gain settings (0, 1, 2, 3) corresponds to gains of (1, 10, 100, 1000) respectively.

Parameters:
  • channel – Channel index
  • gain – Gain setting
write(addr, value)[source]

Write to servo memory.

This method advances the timeline by one coarse RTIO cycle.

Parameters:
  • addr – Memory location address.
  • value – Data to be written.
artiq.coredevice.suservo.adc_mu_to_volts(x, gain)[source]

Convert servo ADC data from machine units to Volt.

artiq.coredevice.suservo.y_mu_to_full_scale(y)[source]

Convert servo Y data from machine units to units of full scale.

artiq.coredevice.grabber module

class artiq.coredevice.grabber.Grabber(dmgr, channel_base, res_width=12, count_shift=0, core_device='core')[source]

Driver for the Grabber camera interface.

gate_roi(mask)[source]

Defines which ROI engines produce input events.

At the end of each video frame, the output from each ROI engine that has been enabled by the mask is enqueued into the RTIO input FIFO.

This function sets the mask at the current position of the RTIO time cursor.

Setting the mask using this function is atomic; in other words, if the system is in the middle of processing a frame and the mask is changed, the processing will complete using the value of the mask that it started with.

Parameters:mask – bitmask enabling or disabling each ROI engine.
gate_roi_pulse(mask, dt)[source]

Sets a temporary mask for the specified duration (in seconds), before disabling all ROI engines.

input_mu(data)[source]

Retrieves the accumulated values for one frame from the ROI engines. Blocks until values are available.

The input list must be a list of integers of the same length as there are enabled ROI engines. This method replaces the elements of the input list with the outputs of the enabled ROI engines, sorted by number.

If the number of elements in the list does not match the number of ROI engines that produced output, an exception will be raised during this call or the next.

setup_roi(n, x0, y0, x1, y1)[source]

Defines the coordinates of a ROI.

The coordinates are set around the current position of the RTIO time cursor.

The user must keep the ROI engine disabled for the duration of more than one video frame after calling this function, as the output generated for that video frame is undefined.

Advances the timeline by 4 coarse RTIO cycles.

exception artiq.coredevice.grabber.OutOfSyncException[source]

Raised when an incorrect number of ROI engine outputs has been retrieved from the RTIO input FIFO.