mirror of https://github.com/m-labs/artiq.git
shuttler: port to NAC3
This commit is contained in:
parent
fc082b62de
commit
24c3a2fd0a
|
@ -1,20 +1,21 @@
|
||||||
import numpy
|
from numpy import int32, int64
|
||||||
|
|
||||||
from artiq.language.core import *
|
from artiq.language.core import nac3, Kernel, KernelInvariant, kernel, portable, Option, none
|
||||||
from artiq.language.types import *
|
|
||||||
from artiq.coredevice.rtio import rtio_output, rtio_input_data
|
from artiq.coredevice.rtio import rtio_output, rtio_input_data
|
||||||
from artiq.coredevice import spi2 as spi
|
from artiq.coredevice.core import Core
|
||||||
|
from artiq.coredevice.spi2 import *
|
||||||
from artiq.language.units import us
|
from artiq.language.units import us
|
||||||
|
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def shuttler_volt_to_mu(volt):
|
def shuttler_volt_to_mu(volt: float) -> int32:
|
||||||
"""Return the equivalent DAC code. Valid input range is from -10 to
|
"""Return the equivalent DAC code. Valid input range is from -10 to
|
||||||
10 - LSB.
|
10 - LSB.
|
||||||
"""
|
"""
|
||||||
return round((1 << 16) * (volt / 20.0)) & 0xffff
|
return round(float(1 << 16) * (volt / 20.0)) & 0xffff
|
||||||
|
|
||||||
|
|
||||||
|
@nac3
|
||||||
class Config:
|
class Config:
|
||||||
"""Shuttler configuration registers interface.
|
"""Shuttler configuration registers interface.
|
||||||
|
|
||||||
|
@ -30,10 +31,13 @@ class Config:
|
||||||
:param channel: RTIO channel number of this interface.
|
:param channel: RTIO channel number of this interface.
|
||||||
:param core_device: Core device name.
|
:param core_device: Core device name.
|
||||||
"""
|
"""
|
||||||
kernel_invariants = {
|
core: KernelInvariant[Core]
|
||||||
"core", "channel", "target_base", "target_read",
|
channel: KernelInvariant[int32]
|
||||||
"target_gain", "target_offset", "target_clr"
|
target_base: KernelInvariant[int32]
|
||||||
}
|
target_read: KernelInvariant[int32]
|
||||||
|
target_gain: KernelInvariant[int32]
|
||||||
|
target_offset: KernelInvariant[int32]
|
||||||
|
target_clr: KernelInvariant[int32]
|
||||||
|
|
||||||
def __init__(self, dmgr, channel, core_device="core"):
|
def __init__(self, dmgr, channel, core_device="core"):
|
||||||
self.core = dmgr.get(core_device)
|
self.core = dmgr.get(core_device)
|
||||||
|
@ -45,7 +49,7 @@ class Config:
|
||||||
self.target_clr = 1 * (1 << 5)
|
self.target_clr = 1 * (1 << 5)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_clr(self, clr):
|
def set_clr(self, clr: int32):
|
||||||
"""Set/Unset waveform phase clear bits.
|
"""Set/Unset waveform phase clear bits.
|
||||||
|
|
||||||
Each bit corresponds to a Shuttler waveform generator core. Setting a
|
Each bit corresponds to a Shuttler waveform generator core. Setting a
|
||||||
|
@ -59,7 +63,7 @@ class Config:
|
||||||
rtio_output(self.target_base | self.target_clr, clr)
|
rtio_output(self.target_base | self.target_clr, clr)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_gain(self, channel, gain):
|
def set_gain(self, channel: int32, gain: int32):
|
||||||
"""Set the 16-bits pre-DAC gain register of a Shuttler Core channel.
|
"""Set the 16-bits pre-DAC gain register of a Shuttler Core channel.
|
||||||
|
|
||||||
The `gain` parameter represents the decimal portion of the gain
|
The `gain` parameter represents the decimal portion of the gain
|
||||||
|
@ -72,7 +76,7 @@ class Config:
|
||||||
rtio_output(self.target_base | self.target_gain | channel, gain)
|
rtio_output(self.target_base | self.target_gain | channel, gain)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def get_gain(self, channel):
|
def get_gain(self, channel: int32) -> int32:
|
||||||
"""Return the pre-DAC gain value of a Shuttler Core channel.
|
"""Return the pre-DAC gain value of a Shuttler Core channel.
|
||||||
|
|
||||||
:param channel: The Shuttler Core channel.
|
:param channel: The Shuttler Core channel.
|
||||||
|
@ -83,7 +87,7 @@ class Config:
|
||||||
return rtio_input_data(self.channel)
|
return rtio_input_data(self.channel)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_offset(self, channel, offset):
|
def set_offset(self, channel: int32, offset: int32):
|
||||||
"""Set the 16-bits pre-DAC offset register of a Shuttler Core channel.
|
"""Set the 16-bits pre-DAC offset register of a Shuttler Core channel.
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
@ -95,7 +99,7 @@ class Config:
|
||||||
rtio_output(self.target_base | self.target_offset | channel, offset)
|
rtio_output(self.target_base | self.target_offset | channel, offset)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def get_offset(self, channel):
|
def get_offset(self, channel: int32) -> int32:
|
||||||
"""Return the pre-DAC offset value of a Shuttler Core channel.
|
"""Return the pre-DAC offset value of a Shuttler Core channel.
|
||||||
|
|
||||||
:param channel: The Shuttler Core channel.
|
:param channel: The Shuttler Core channel.
|
||||||
|
@ -106,6 +110,7 @@ class Config:
|
||||||
return rtio_input_data(self.channel)
|
return rtio_input_data(self.channel)
|
||||||
|
|
||||||
|
|
||||||
|
@nac3
|
||||||
class Volt:
|
class Volt:
|
||||||
"""Shuttler Core cubic DC-bias spline.
|
"""Shuttler Core cubic DC-bias spline.
|
||||||
|
|
||||||
|
@ -127,7 +132,9 @@ class Volt:
|
||||||
:param channel: RTIO channel number of this DC-bias spline interface.
|
:param channel: RTIO channel number of this DC-bias spline interface.
|
||||||
:param core_device: Core device name.
|
:param core_device: Core device name.
|
||||||
"""
|
"""
|
||||||
kernel_invariants = {"core", "channel", "target_o"}
|
core: KernelInvariant[Core]
|
||||||
|
channel: KernelInvariant[int32]
|
||||||
|
target_o: KernelInvariant[int32]
|
||||||
|
|
||||||
def __init__(self, dmgr, channel, core_device="core"):
|
def __init__(self, dmgr, channel, core_device="core"):
|
||||||
self.core = dmgr.get(core_device)
|
self.core = dmgr.get(core_device)
|
||||||
|
@ -135,7 +142,7 @@ class Volt:
|
||||||
self.target_o = channel << 8
|
self.target_o = channel << 8
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_waveform(self, a0: TInt32, a1: TInt32, a2: TInt64, a3: TInt64):
|
def set_waveform(self, a0: int32, a1: int32, a2: int64, a3: int64):
|
||||||
"""Set the DC-bias spline waveform.
|
"""Set the DC-bias spline waveform.
|
||||||
|
|
||||||
Given `a(t)` as defined in :class:`Volt`, the coefficients should be
|
Given `a(t)` as defined in :class:`Volt`, the coefficients should be
|
||||||
|
@ -168,12 +175,12 @@ class Volt:
|
||||||
a0,
|
a0,
|
||||||
a1,
|
a1,
|
||||||
a1 >> 16,
|
a1 >> 16,
|
||||||
a2 & 0xFFFF,
|
int32(a2 & int64(0xFFFF)),
|
||||||
(a2 >> 16) & 0xFFFF,
|
int32((a2 >> int64(16)) & int64(0xFFFF)),
|
||||||
(a2 >> 32) & 0xFFFF,
|
int32((a2 >> int64(32)) & int64(0xFFFF)),
|
||||||
a3 & 0xFFFF,
|
int32(a3 & int64(0xFFFF)),
|
||||||
(a3 >> 16) & 0xFFFF,
|
int32((a3 >> int64(16)) & int64(0xFFFF)),
|
||||||
(a3 >> 32) & 0xFFFF,
|
int32((a3 >> int64(32)) & int64(0xFFFF)),
|
||||||
]
|
]
|
||||||
|
|
||||||
for i in range(len(coef_words)):
|
for i in range(len(coef_words)):
|
||||||
|
@ -181,6 +188,7 @@ class Volt:
|
||||||
delay_mu(int64(self.core.ref_multiplier))
|
delay_mu(int64(self.core.ref_multiplier))
|
||||||
|
|
||||||
|
|
||||||
|
@nac3
|
||||||
class Dds:
|
class Dds:
|
||||||
"""Shuttler Core DDS spline.
|
"""Shuttler Core DDS spline.
|
||||||
|
|
||||||
|
@ -206,7 +214,9 @@ class Dds:
|
||||||
:param channel: RTIO channel number of this DC-bias spline interface.
|
:param channel: RTIO channel number of this DC-bias spline interface.
|
||||||
:param core_device: Core device name.
|
:param core_device: Core device name.
|
||||||
"""
|
"""
|
||||||
kernel_invariants = {"core", "channel", "target_o"}
|
core: KernelInvariant[Core]
|
||||||
|
channel: KernelInvariant[int32]
|
||||||
|
target_o: KernelInvariant[int32]
|
||||||
|
|
||||||
def __init__(self, dmgr, channel, core_device="core"):
|
def __init__(self, dmgr, channel, core_device="core"):
|
||||||
self.core = dmgr.get(core_device)
|
self.core = dmgr.get(core_device)
|
||||||
|
@ -214,8 +224,8 @@ class Dds:
|
||||||
self.target_o = channel << 8
|
self.target_o = channel << 8
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_waveform(self, b0: TInt32, b1: TInt32, b2: TInt64, b3: TInt64,
|
def set_waveform(self, b0: int32, b1: int32, b2: int64, b3: int64,
|
||||||
c0: TInt32, c1: TInt32, c2: TInt32):
|
c0: int32, c1: int32, c2: int32):
|
||||||
"""Set the DDS spline waveform.
|
"""Set the DDS spline waveform.
|
||||||
|
|
||||||
Given `b(t)` and `c(t)` as defined in :class:`Dds`, the coefficients
|
Given `b(t)` and `c(t)` as defined in :class:`Dds`, the coefficients
|
||||||
|
@ -258,12 +268,12 @@ class Dds:
|
||||||
b0,
|
b0,
|
||||||
b1,
|
b1,
|
||||||
b1 >> 16,
|
b1 >> 16,
|
||||||
b2 & 0xFFFF,
|
int32(b2 & int64(0xFFFF)),
|
||||||
(b2 >> 16) & 0xFFFF,
|
int32((b2 >> int64(16)) & int64(0xFFFF)),
|
||||||
(b2 >> 32) & 0xFFFF,
|
int32((b2 >> int64(32)) & int64(0xFFFF)),
|
||||||
b3 & 0xFFFF,
|
int32(b3 & int64(0xFFFF)),
|
||||||
(b3 >> 16) & 0xFFFF,
|
int32((b3 >> int64(16)) & int64(0xFFFF)),
|
||||||
(b3 >> 32) & 0xFFFF,
|
int32((b3 >> int64(32)) & int64(0xFFFF)),
|
||||||
c0,
|
c0,
|
||||||
c1,
|
c1,
|
||||||
c1 >> 16,
|
c1 >> 16,
|
||||||
|
@ -276,13 +286,16 @@ class Dds:
|
||||||
delay_mu(int64(self.core.ref_multiplier))
|
delay_mu(int64(self.core.ref_multiplier))
|
||||||
|
|
||||||
|
|
||||||
|
@nac3
|
||||||
class Trigger:
|
class Trigger:
|
||||||
"""Shuttler Core spline coefficients update trigger.
|
"""Shuttler Core spline coefficients update trigger.
|
||||||
|
|
||||||
:param channel: RTIO channel number of the trigger interface.
|
:param channel: RTIO channel number of the trigger interface.
|
||||||
:param core_device: Core device name.
|
:param core_device: Core device name.
|
||||||
"""
|
"""
|
||||||
kernel_invariants = {"core", "channel", "target_o"}
|
core: KernelInvariant[Core]
|
||||||
|
channel: KernelInvariant[int32]
|
||||||
|
target_o: KernelInvariant[int32]
|
||||||
|
|
||||||
def __init__(self, dmgr, channel, core_device="core"):
|
def __init__(self, dmgr, channel, core_device="core"):
|
||||||
self.core = dmgr.get(core_device)
|
self.core = dmgr.get(core_device)
|
||||||
|
@ -290,7 +303,7 @@ class Trigger:
|
||||||
self.target_o = channel << 8
|
self.target_o = channel << 8
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def trigger(self, trig_out):
|
def trigger(self, trig_out: int32):
|
||||||
"""Triggers coefficient update of (a) Shuttler Core channel(s).
|
"""Triggers coefficient update of (a) Shuttler Core channel(s).
|
||||||
|
|
||||||
Each bit corresponds to a Shuttler waveform generator core. Setting
|
Each bit corresponds to a Shuttler waveform generator core. Setting
|
||||||
|
@ -304,15 +317,15 @@ class Trigger:
|
||||||
rtio_output(self.target_o, trig_out)
|
rtio_output(self.target_o, trig_out)
|
||||||
|
|
||||||
|
|
||||||
RELAY_SPI_CONFIG = (0*spi.SPI_OFFLINE | 1*spi.SPI_END |
|
RELAY_SPI_CONFIG = (0*SPI_OFFLINE | 1*SPI_END |
|
||||||
0*spi.SPI_INPUT | 0*spi.SPI_CS_POLARITY |
|
0*SPI_INPUT | 0*SPI_CS_POLARITY |
|
||||||
0*spi.SPI_CLK_POLARITY | 0*spi.SPI_CLK_PHASE |
|
0*SPI_CLK_POLARITY | 0*SPI_CLK_PHASE |
|
||||||
0*spi.SPI_LSB_FIRST | 0*spi.SPI_HALF_DUPLEX)
|
0*SPI_LSB_FIRST | 0*SPI_HALF_DUPLEX)
|
||||||
|
|
||||||
ADC_SPI_CONFIG = (0*spi.SPI_OFFLINE | 0*spi.SPI_END |
|
ADC_SPI_CONFIG = (0*SPI_OFFLINE | 0*SPI_END |
|
||||||
0*spi.SPI_INPUT | 0*spi.SPI_CS_POLARITY |
|
0*SPI_INPUT | 0*SPI_CS_POLARITY |
|
||||||
1*spi.SPI_CLK_POLARITY | 1*spi.SPI_CLK_PHASE |
|
1*SPI_CLK_POLARITY | 1*SPI_CLK_PHASE |
|
||||||
0*spi.SPI_LSB_FIRST | 0*spi.SPI_HALF_DUPLEX)
|
0*SPI_LSB_FIRST | 0*SPI_HALF_DUPLEX)
|
||||||
|
|
||||||
# SPI clock write and read dividers
|
# SPI clock write and read dividers
|
||||||
# CS should assert at least 9.5 ns after clk pulse
|
# CS should assert at least 9.5 ns after clk pulse
|
||||||
|
@ -335,6 +348,7 @@ _AD4115_REG_CH0 = 0x10
|
||||||
_AD4115_REG_SETUPCON0 = 0x20
|
_AD4115_REG_SETUPCON0 = 0x20
|
||||||
|
|
||||||
|
|
||||||
|
@nac3
|
||||||
class Relay:
|
class Relay:
|
||||||
"""Shuttler AFE relay switches.
|
"""Shuttler AFE relay switches.
|
||||||
|
|
||||||
|
@ -349,7 +363,8 @@ class Relay:
|
||||||
:param spi_device: SPI bus device name.
|
:param spi_device: SPI bus device name.
|
||||||
:param core_device: Core device name.
|
:param core_device: Core device name.
|
||||||
"""
|
"""
|
||||||
kernel_invariant = {"core", "bus"}
|
core: KernelInvariant[Core]
|
||||||
|
bus: KernelInvariant[SPIMaster]
|
||||||
|
|
||||||
def __init__(self, dmgr, spi_device, core_device="core"):
|
def __init__(self, dmgr, spi_device, core_device="core"):
|
||||||
self.core = dmgr.get(core_device)
|
self.core = dmgr.get(core_device)
|
||||||
|
@ -366,7 +381,7 @@ class Relay:
|
||||||
RELAY_SPI_CONFIG, 16, SPIT_RELAY_WR, CS_RELAY | CS_LED)
|
RELAY_SPI_CONFIG, 16, SPIT_RELAY_WR, CS_RELAY | CS_LED)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def enable(self, en: TInt32):
|
def enable(self, en: int32):
|
||||||
"""Enable/Disable relay switches of corresponding channels.
|
"""Enable/Disable relay switches of corresponding channels.
|
||||||
|
|
||||||
Each bit corresponds to the relay switch of a channel. Asserting a bit
|
Each bit corresponds to the relay switch of a channel. Asserting a bit
|
||||||
|
@ -379,20 +394,22 @@ class Relay:
|
||||||
self.bus.write(en << 16)
|
self.bus.write(en << 16)
|
||||||
|
|
||||||
|
|
||||||
|
@nac3
|
||||||
class ADC:
|
class ADC:
|
||||||
"""Shuttler AFE ADC (AD4115) driver.
|
"""Shuttler AFE ADC (AD4115) driver.
|
||||||
|
|
||||||
:param spi_device: SPI bus device name.
|
:param spi_device: SPI bus device name.
|
||||||
:param core_device: Core device name.
|
:param core_device: Core device name.
|
||||||
"""
|
"""
|
||||||
kernel_invariant = {"core", "bus"}
|
core: KernelInvariant[Core]
|
||||||
|
bus: KernelInvariant[SPIMaster]
|
||||||
|
|
||||||
def __init__(self, dmgr, spi_device, core_device="core"):
|
def __init__(self, dmgr, spi_device, core_device="core"):
|
||||||
self.core = dmgr.get(core_device)
|
self.core = dmgr.get(core_device)
|
||||||
self.bus = dmgr.get(spi_device)
|
self.bus = dmgr.get(spi_device)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def read_id(self) -> TInt32:
|
def read_id(self) -> int32:
|
||||||
"""Read the product ID of the ADC.
|
"""Read the product ID of the ADC.
|
||||||
|
|
||||||
The expected return value is 0x38DX, the 4 LSbs are don't cares.
|
The expected return value is 0x38DX, the 4 LSbs are don't cares.
|
||||||
|
@ -414,86 +431,86 @@ class ADC:
|
||||||
after the transfer appears to interrupt the start-up sequence.
|
after the transfer appears to interrupt the start-up sequence.
|
||||||
"""
|
"""
|
||||||
self.bus.set_config_mu(ADC_SPI_CONFIG, 32, SPIT_ADC_WR, CS_ADC)
|
self.bus.set_config_mu(ADC_SPI_CONFIG, 32, SPIT_ADC_WR, CS_ADC)
|
||||||
self.bus.write(0xffffffff)
|
self.bus.write(-1)
|
||||||
self.bus.write(0xffffffff)
|
self.bus.write(-1)
|
||||||
self.bus.set_config_mu(
|
self.bus.set_config_mu(
|
||||||
ADC_SPI_CONFIG | spi.SPI_END, 32, SPIT_ADC_WR, CS_ADC)
|
ADC_SPI_CONFIG | SPI_END, 32, SPIT_ADC_WR, CS_ADC)
|
||||||
self.bus.write(0xffffffff)
|
self.bus.write(-1)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def read8(self, addr: TInt32) -> TInt32:
|
def read8(self, addr: int32) -> int32:
|
||||||
"""Read from 8 bit register.
|
"""Read from 8 bit register.
|
||||||
|
|
||||||
:param addr: Register address.
|
:param addr: Register address.
|
||||||
:return: Read-back register content.
|
:return: Read-back register content.
|
||||||
"""
|
"""
|
||||||
self.bus.set_config_mu(
|
self.bus.set_config_mu(
|
||||||
ADC_SPI_CONFIG | spi.SPI_END | spi.SPI_INPUT,
|
ADC_SPI_CONFIG | SPI_END | SPI_INPUT,
|
||||||
16, SPIT_ADC_RD, CS_ADC)
|
16, SPIT_ADC_RD, CS_ADC)
|
||||||
self.bus.write((addr | 0x40) << 24)
|
self.bus.write((addr | 0x40) << 24)
|
||||||
return self.bus.read() & 0xff
|
return self.bus.read() & 0xff
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def read16(self, addr: TInt32) -> TInt32:
|
def read16(self, addr: int32) -> int32:
|
||||||
"""Read from 16 bit register.
|
"""Read from 16 bit register.
|
||||||
|
|
||||||
:param addr: Register address.
|
:param addr: Register address.
|
||||||
:return: Read-back register content.
|
:return: Read-back register content.
|
||||||
"""
|
"""
|
||||||
self.bus.set_config_mu(
|
self.bus.set_config_mu(
|
||||||
ADC_SPI_CONFIG | spi.SPI_END | spi.SPI_INPUT,
|
ADC_SPI_CONFIG | SPI_END | SPI_INPUT,
|
||||||
24, SPIT_ADC_RD, CS_ADC)
|
24, SPIT_ADC_RD, CS_ADC)
|
||||||
self.bus.write((addr | 0x40) << 24)
|
self.bus.write((addr | 0x40) << 24)
|
||||||
return self.bus.read() & 0xffff
|
return self.bus.read() & 0xffff
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def read24(self, addr: TInt32) -> TInt32:
|
def read24(self, addr: int32) -> int32:
|
||||||
"""Read from 24 bit register.
|
"""Read from 24 bit register.
|
||||||
|
|
||||||
:param addr: Register address.
|
:param addr: Register address.
|
||||||
:return: Read-back register content.
|
:return: Read-back register content.
|
||||||
"""
|
"""
|
||||||
self.bus.set_config_mu(
|
self.bus.set_config_mu(
|
||||||
ADC_SPI_CONFIG | spi.SPI_END | spi.SPI_INPUT,
|
ADC_SPI_CONFIG | SPI_END | SPI_INPUT,
|
||||||
32, SPIT_ADC_RD, CS_ADC)
|
32, SPIT_ADC_RD, CS_ADC)
|
||||||
self.bus.write((addr | 0x40) << 24)
|
self.bus.write((addr | 0x40) << 24)
|
||||||
return self.bus.read() & 0xffffff
|
return self.bus.read() & 0xffffff
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def write8(self, addr: TInt32, data: TInt32):
|
def write8(self, addr: int32, data: int32):
|
||||||
"""Write to 8 bit register.
|
"""Write to 8 bit register.
|
||||||
|
|
||||||
:param addr: Register address.
|
:param addr: Register address.
|
||||||
:param data: Data to be written.
|
:param data: Data to be written.
|
||||||
"""
|
"""
|
||||||
self.bus.set_config_mu(
|
self.bus.set_config_mu(
|
||||||
ADC_SPI_CONFIG | spi.SPI_END, 16, SPIT_ADC_WR, CS_ADC)
|
ADC_SPI_CONFIG | SPI_END, 16, SPIT_ADC_WR, CS_ADC)
|
||||||
self.bus.write(addr << 24 | (data & 0xff) << 16)
|
self.bus.write(addr << 24 | (data & 0xff) << 16)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def write16(self, addr: TInt32, data: TInt32):
|
def write16(self, addr: int32, data: int32):
|
||||||
"""Write to 16 bit register.
|
"""Write to 16 bit register.
|
||||||
|
|
||||||
:param addr: Register address.
|
:param addr: Register address.
|
||||||
:param data: Data to be written.
|
:param data: Data to be written.
|
||||||
"""
|
"""
|
||||||
self.bus.set_config_mu(
|
self.bus.set_config_mu(
|
||||||
ADC_SPI_CONFIG | spi.SPI_END, 24, SPIT_ADC_WR, CS_ADC)
|
ADC_SPI_CONFIG | SPI_END, 24, SPIT_ADC_WR, CS_ADC)
|
||||||
self.bus.write(addr << 24 | (data & 0xffff) << 8)
|
self.bus.write(addr << 24 | (data & 0xffff) << 8)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def write24(self, addr: TInt32, data: TInt32):
|
def write24(self, addr: int32, data: int32):
|
||||||
"""Write to 24 bit register.
|
"""Write to 24 bit register.
|
||||||
|
|
||||||
:param addr: Register address.
|
:param addr: Register address.
|
||||||
:param data: Data to be written.
|
:param data: Data to be written.
|
||||||
"""
|
"""
|
||||||
self.bus.set_config_mu(
|
self.bus.set_config_mu(
|
||||||
ADC_SPI_CONFIG | spi.SPI_END, 32, SPIT_ADC_WR, CS_ADC)
|
ADC_SPI_CONFIG | SPI_END, 32, SPIT_ADC_WR, CS_ADC)
|
||||||
self.bus.write(addr << 24 | (data & 0xffffff))
|
self.bus.write(addr << 24 | (data & 0xffffff))
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def read_ch(self, channel: TInt32) -> TFloat:
|
def read_ch(self, channel: int32) -> float:
|
||||||
"""Sample a Shuttler channel on the AFE.
|
"""Sample a Shuttler channel on the AFE.
|
||||||
|
|
||||||
It performs a single conversion using profile 0 and setup 0, on the
|
It performs a single conversion using profile 0 and setup 0, on the
|
||||||
|
@ -507,9 +524,9 @@ class ADC:
|
||||||
self.write16(_AD4115_REG_SETUPCON0, 0x1300)
|
self.write16(_AD4115_REG_SETUPCON0, 0x1300)
|
||||||
self.single_conversion()
|
self.single_conversion()
|
||||||
|
|
||||||
delay(100*us)
|
self.core.delay(100.*us)
|
||||||
adc_code = self.read24(_AD4115_REG_DATA)
|
adc_code = self.read24(_AD4115_REG_DATA)
|
||||||
return ((adc_code / (1 << 23)) - 1) * 2.5 / 0.1
|
return ((float(adc_code) / float(1 << 23)) - 1.) * 2.5 / 0.1
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def single_conversion(self):
|
def single_conversion(self):
|
||||||
|
@ -560,10 +577,10 @@ class ADC:
|
||||||
self.reset()
|
self.reset()
|
||||||
# Although the datasheet claims 500 us reset wait time, only waiting
|
# Although the datasheet claims 500 us reset wait time, only waiting
|
||||||
# for ~500 us can result in DOUT pin stuck in high
|
# for ~500 us can result in DOUT pin stuck in high
|
||||||
delay(2500*us)
|
self.core.delay(2500.*us)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def calibrate(self, volts, trigger, config, samples=[-5.0, 0.0, 5.0]):
|
def calibrate(self, volts: list[Volt], trigger: Trigger, config: Config, samples: Option[list[float]] = none):
|
||||||
"""Calibrate the Shuttler waveform generator using the ADC on the AFE.
|
"""Calibrate the Shuttler waveform generator using the ADC on the AFE.
|
||||||
|
|
||||||
It finds the average slope rate and average offset by samples, and
|
It finds the average slope rate and average offset by samples, and
|
||||||
|
@ -588,33 +605,35 @@ class ADC:
|
||||||
:param samples: A list of sample voltages for calibration. There must
|
:param samples: A list of sample voltages for calibration. There must
|
||||||
be at least 2 samples to perform slope rate calculation.
|
be at least 2 samples to perform slope rate calculation.
|
||||||
"""
|
"""
|
||||||
assert len(volts) == 16
|
samples_l = samples.unwrap() if samples.is_some() else [-5.0, 0.0, 5.0]
|
||||||
assert len(samples) > 1
|
|
||||||
|
|
||||||
measurements = [0.0] * len(samples)
|
assert len(volts) == 16
|
||||||
|
assert len(samples_l) > 1
|
||||||
|
|
||||||
|
measurements = [0.0 for _ in range(len(samples_l))]
|
||||||
|
|
||||||
for ch in range(16):
|
for ch in range(16):
|
||||||
# Find the average slope rate and offset
|
# Find the average slope rate and offset
|
||||||
for i in range(len(samples)):
|
for i in range(len(samples_l)):
|
||||||
self.core.break_realtime()
|
self.core.break_realtime()
|
||||||
volts[ch].set_waveform(
|
volts[ch].set_waveform(
|
||||||
shuttler_volt_to_mu(samples[i]), 0, 0, 0)
|
shuttler_volt_to_mu(samples_l[i]), 0, int64(0), int64(0))
|
||||||
trigger.trigger(1 << ch)
|
trigger.trigger(1 << ch)
|
||||||
measurements[i] = self.read_ch(ch)
|
measurements[i] = self.read_ch(ch)
|
||||||
|
|
||||||
# Find the average output slope
|
# Find the average output slope
|
||||||
slope_sum = 0.0
|
slope_sum = 0.0
|
||||||
for i in range(len(samples) - 1):
|
for i in range(len(samples_l) - 1):
|
||||||
slope_sum += (measurements[i+1] - measurements[i])/(samples[i+1] - samples[i])
|
slope_sum += (measurements[i+1] - measurements[i])/(samples_l[i+1] - samples_l[i])
|
||||||
slope_avg = slope_sum / (len(samples) - 1)
|
slope_avg = slope_sum / float(len(samples_l) - 1)
|
||||||
|
|
||||||
gain_code = int32(1 / slope_avg * (2 ** 16)) & 0xffff
|
gain_code = int32(1. / slope_avg * float(2 ** 16)) & 0xffff
|
||||||
|
|
||||||
# Scale the measurements by 1/slope, find average offset
|
# Scale the measurements by 1/slope, find average offset
|
||||||
offset_sum = 0.0
|
offset_sum = 0.0
|
||||||
for i in range(len(samples)):
|
for i in range(len(samples_l)):
|
||||||
offset_sum += (measurements[i] / slope_avg) - samples[i]
|
offset_sum += (measurements[i] / slope_avg) - samples_l[i]
|
||||||
offset_avg = offset_sum / len(samples)
|
offset_avg = offset_sum / float(len(samples_l))
|
||||||
|
|
||||||
offset_code = shuttler_volt_to_mu(-offset_avg)
|
offset_code = shuttler_volt_to_mu(-offset_avg)
|
||||||
|
|
||||||
|
|
|
@ -1,61 +1,82 @@
|
||||||
from artiq.experiment import *
|
from numpy import int32, int64
|
||||||
from artiq.coredevice.shuttler import shuttler_volt_to_mu
|
|
||||||
|
|
||||||
DAC_Fs_MHZ = 125
|
from artiq.experiment import *
|
||||||
|
from artiq.coredevice.core import Core
|
||||||
|
from artiq.coredevice.ttl import TTLOut
|
||||||
|
from artiq.coredevice.shuttler import (
|
||||||
|
shuttler_volt_to_mu,
|
||||||
|
Config as ShuttlerConfig,
|
||||||
|
Trigger as ShuttlerTrigger,
|
||||||
|
Volt as ShuttlerDCBias,
|
||||||
|
Dds as ShuttlerDDS,
|
||||||
|
Relay as ShuttlerRelay,
|
||||||
|
ADC as ShuttlerADC)
|
||||||
|
|
||||||
|
|
||||||
|
DAC_Fs_MHZ = 125.
|
||||||
CORDIC_GAIN = 1.64676
|
CORDIC_GAIN = 1.64676
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def shuttler_phase_offset(offset_degree):
|
def shuttler_phase_offset(offset_degree: float) -> int32:
|
||||||
return round(offset_degree / 360 * (2 ** 16))
|
return round(offset_degree / 360. * float(2 ** 16))
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def shuttler_freq_mu(freq_mhz):
|
def shuttler_freq_mu(freq_mhz: float) -> int32:
|
||||||
return round(float(2) ** 32 / DAC_Fs_MHZ * freq_mhz)
|
return round(float(2) ** 32 / DAC_Fs_MHZ * freq_mhz)
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def shuttler_chirp_rate_mu(freq_mhz_per_us):
|
def shuttler_chirp_rate_mu(freq_mhz_per_us: float) -> int32:
|
||||||
return round(float(2) ** 32 * freq_mhz_per_us / (DAC_Fs_MHZ ** 2))
|
return round(float(2) ** 32 * freq_mhz_per_us / (DAC_Fs_MHZ ** 2))
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def shuttler_freq_sweep(start_f_MHz, end_f_MHz, time_us):
|
def shuttler_freq_sweep(start_f_MHz: float, end_f_MHz: float, time_us: float) -> int32:
|
||||||
return shuttler_chirp_rate_mu((end_f_MHz - start_f_MHz)/(time_us))
|
return shuttler_chirp_rate_mu((end_f_MHz - start_f_MHz)/time_us)
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def shuttler_volt_amp_mu(volt):
|
def shuttler_volt_amp_mu(volt: float) -> int32:
|
||||||
return shuttler_volt_to_mu(volt)
|
return shuttler_volt_to_mu(volt)
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def shuttler_volt_damp_mu(volt_per_us):
|
def shuttler_volt_damp_mu(volt_per_us: float) -> int32:
|
||||||
return round(float(2) ** 32 * (volt_per_us / 20) / DAC_Fs_MHZ)
|
return round(float(2) ** 32 * (volt_per_us / 20.) / DAC_Fs_MHZ)
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def shuttler_volt_ddamp_mu(volt_per_us_square):
|
def shuttler_volt_ddamp_mu(volt_per_us_square: float) -> int64:
|
||||||
return round(float(2) ** 48 * (volt_per_us_square / 20) * 2 / (DAC_Fs_MHZ ** 2))
|
return round64(float(2) ** 48 * (volt_per_us_square / 20.) * 2. / (DAC_Fs_MHZ ** 2))
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def shuttler_volt_dddamp_mu(volt_per_us_cube):
|
def shuttler_volt_dddamp_mu(volt_per_us_cube: float) -> int64:
|
||||||
return round(float(2) ** 48 * (volt_per_us_cube / 20) * 6 / (DAC_Fs_MHZ ** 3))
|
return round64(float(2) ** 48 * (volt_per_us_cube / 20.) * 6. / (DAC_Fs_MHZ ** 3))
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def shuttler_dds_amp_mu(volt):
|
def shuttler_dds_amp_mu(volt: float) -> int32:
|
||||||
return shuttler_volt_amp_mu(volt / CORDIC_GAIN)
|
return shuttler_volt_amp_mu(volt / CORDIC_GAIN)
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def shuttler_dds_damp_mu(volt_per_us):
|
def shuttler_dds_damp_mu(volt_per_us: float) -> int32:
|
||||||
return shuttler_volt_damp_mu(volt_per_us / CORDIC_GAIN)
|
return shuttler_volt_damp_mu(volt_per_us / CORDIC_GAIN)
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def shuttler_dds_ddamp_mu(volt_per_us_square):
|
def shuttler_dds_ddamp_mu(volt_per_us_square: float) -> int64:
|
||||||
return shuttler_volt_ddamp_mu(volt_per_us_square / CORDIC_GAIN)
|
return shuttler_volt_ddamp_mu(volt_per_us_square / CORDIC_GAIN)
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def shuttler_dds_dddamp_mu(volt_per_us_cube):
|
def shuttler_dds_dddamp_mu(volt_per_us_cube: float) -> int64:
|
||||||
return shuttler_volt_dddamp_mu(volt_per_us_cube / CORDIC_GAIN)
|
return shuttler_volt_dddamp_mu(volt_per_us_cube / CORDIC_GAIN)
|
||||||
|
|
||||||
|
@nac3
|
||||||
class Shuttler(EnvExperiment):
|
class Shuttler(EnvExperiment):
|
||||||
|
core: KernelInvariant[Core]
|
||||||
|
shuttler0_leds: KernelInvariant[list[TTLOut]]
|
||||||
|
shuttler0_config: KernelInvariant[ShuttlerConfig]
|
||||||
|
shuttler0_trigger: KernelInvariant[ShuttlerTrigger]
|
||||||
|
shuttler0_volt: KernelInvariant[list[ShuttlerDCBias]]
|
||||||
|
shuttler0_dds: KernelInvariant[list[ShuttlerDDS]]
|
||||||
|
shuttler0_relay: KernelInvariant[ShuttlerRelay]
|
||||||
|
shuttler0_adc: KernelInvariant[ShuttlerADC]
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
self.setattr_device("core")
|
self.setattr_device("core")
|
||||||
self.setattr_device("core_dma")
|
|
||||||
self.setattr_device("scheduler")
|
self.setattr_device("scheduler")
|
||||||
self.shuttler0_leds = [ self.get_device("shuttler0_led{}".format(i)) for i in range(2) ]
|
self.shuttler0_leds = [ self.get_device("shuttler0_led{}".format(i)) for i in range(2) ]
|
||||||
self.setattr_device("shuttler0_config")
|
self.setattr_device("shuttler0_config")
|
||||||
|
@ -64,12 +85,6 @@ class Shuttler(EnvExperiment):
|
||||||
self.shuttler0_dds = [ self.get_device("shuttler0_dds{}".format(i)) for i in range(16) ]
|
self.shuttler0_dds = [ self.get_device("shuttler0_dds{}".format(i)) for i in range(16) ]
|
||||||
self.setattr_device("shuttler0_relay")
|
self.setattr_device("shuttler0_relay")
|
||||||
self.setattr_device("shuttler0_adc")
|
self.setattr_device("shuttler0_adc")
|
||||||
|
|
||||||
|
|
||||||
@kernel
|
|
||||||
def record(self):
|
|
||||||
with self.core_dma.record("example_waveform"):
|
|
||||||
self.example_waveform()
|
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def init(self):
|
def init(self):
|
||||||
|
@ -84,35 +99,33 @@ class Shuttler(EnvExperiment):
|
||||||
self.core.break_realtime()
|
self.core.break_realtime()
|
||||||
self.init()
|
self.init()
|
||||||
|
|
||||||
self.record()
|
print_rpc("Example Waveforms are on OUT0 and OUT1")
|
||||||
example_waveform_handle = self.core_dma.get_handle("example_waveform")
|
|
||||||
|
|
||||||
print("Example Waveforms are on OUT0 and OUT1")
|
|
||||||
self.core.break_realtime()
|
self.core.break_realtime()
|
||||||
while not(self.scheduler.check_termination()):
|
#while not(self.scheduler.check_termination()):
|
||||||
delay(1*s)
|
while True:
|
||||||
self.core_dma.playback_handle(example_waveform_handle)
|
self.core.delay(1.*s)
|
||||||
|
self.example_waveform()
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def shuttler_reset(self):
|
def shuttler_reset(self):
|
||||||
for i in range(16):
|
for i in range(16):
|
||||||
self.shuttler_channel_reset(i)
|
self.shuttler_channel_reset(i)
|
||||||
# To avoid RTIO Underflow
|
# To avoid RTIO Underflow
|
||||||
delay(50*us)
|
self.core.delay(50.*us)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def shuttler_channel_reset(self, ch):
|
def shuttler_channel_reset(self, ch: int32):
|
||||||
self.shuttler0_volt[ch].set_waveform(
|
self.shuttler0_volt[ch].set_waveform(
|
||||||
a0=0,
|
a0=0,
|
||||||
a1=0,
|
a1=0,
|
||||||
a2=0,
|
a2=int64(0),
|
||||||
a3=0,
|
a3=int64(0),
|
||||||
)
|
)
|
||||||
self.shuttler0_dds[ch].set_waveform(
|
self.shuttler0_dds[ch].set_waveform(
|
||||||
b0=0,
|
b0=0,
|
||||||
b1=0,
|
b1=0,
|
||||||
b2=0,
|
b2=int64(0),
|
||||||
b3=0,
|
b3=int64(0),
|
||||||
c0=0,
|
c0=0,
|
||||||
c1=0,
|
c1=0,
|
||||||
c2=0,
|
c2=0,
|
||||||
|
@ -163,13 +176,13 @@ class Shuttler(EnvExperiment):
|
||||||
## Step 2 ##
|
## Step 2 ##
|
||||||
start_f_MHz = 0.01
|
start_f_MHz = 0.01
|
||||||
end_f_MHz = 0.05
|
end_f_MHz = 0.05
|
||||||
duration_us = 500
|
duration_us = 500.
|
||||||
# OUT0 and OUT1 have their frequency and phase aligned at 500us
|
# OUT0 and OUT1 have their frequency and phase aligned at 500us
|
||||||
self.shuttler0_dds[0].set_waveform(
|
self.shuttler0_dds[0].set_waveform(
|
||||||
b0=shuttler_dds_amp_mu(1.0),
|
b0=shuttler_dds_amp_mu(1.0),
|
||||||
b1=0,
|
b1=0,
|
||||||
b2=0,
|
b2=int64(0),
|
||||||
b3=0,
|
b3=int64(0),
|
||||||
c0=0,
|
c0=0,
|
||||||
c1=shuttler_freq_mu(start_f_MHz),
|
c1=shuttler_freq_mu(start_f_MHz),
|
||||||
c2=shuttler_freq_sweep(start_f_MHz, end_f_MHz, duration_us),
|
c2=shuttler_freq_sweep(start_f_MHz, end_f_MHz, duration_us),
|
||||||
|
@ -177,22 +190,22 @@ class Shuttler(EnvExperiment):
|
||||||
self.shuttler0_dds[1].set_waveform(
|
self.shuttler0_dds[1].set_waveform(
|
||||||
b0=shuttler_dds_amp_mu(1.0),
|
b0=shuttler_dds_amp_mu(1.0),
|
||||||
b1=0,
|
b1=0,
|
||||||
b2=0,
|
b2=int64(0),
|
||||||
b3=0,
|
b3=int64(0),
|
||||||
c0=0,
|
c0=0,
|
||||||
c1=shuttler_freq_mu(end_f_MHz),
|
c1=shuttler_freq_mu(end_f_MHz),
|
||||||
c2=0,
|
c2=0,
|
||||||
)
|
)
|
||||||
self.shuttler0_trigger.trigger(0b11)
|
self.shuttler0_trigger.trigger(0b11)
|
||||||
delay(500*us)
|
self.core.delay(500.*us)
|
||||||
|
|
||||||
## Step 3 ##
|
## Step 3 ##
|
||||||
# OUT0 and OUT1 has 180 degree phase difference
|
# OUT0 and OUT1 has 180 degree phase difference
|
||||||
self.shuttler0_dds[0].set_waveform(
|
self.shuttler0_dds[0].set_waveform(
|
||||||
b0=shuttler_dds_amp_mu(1.0),
|
b0=shuttler_dds_amp_mu(1.0),
|
||||||
b1=0,
|
b1=0,
|
||||||
b2=0,
|
b2=int64(0),
|
||||||
b3=0,
|
b3=int64(0),
|
||||||
c0=shuttler_phase_offset(180.0),
|
c0=shuttler_phase_offset(180.0),
|
||||||
c1=shuttler_freq_mu(end_f_MHz),
|
c1=shuttler_freq_mu(end_f_MHz),
|
||||||
c2=0,
|
c2=0,
|
||||||
|
@ -200,7 +213,7 @@ class Shuttler(EnvExperiment):
|
||||||
# Phase and Output Setting of OUT1 is retained
|
# Phase and Output Setting of OUT1 is retained
|
||||||
# if the channel is not triggered or config is not cleared
|
# if the channel is not triggered or config is not cleared
|
||||||
self.shuttler0_trigger.trigger(0b1)
|
self.shuttler0_trigger.trigger(0b1)
|
||||||
delay(500*us)
|
self.core.delay(500.*us)
|
||||||
|
|
||||||
## Step 4 ##
|
## Step 4 ##
|
||||||
# b(0) = 0, b(250) = 8.545, b(500) = 0
|
# b(0) = 0, b(250) = 8.545, b(500) = 0
|
||||||
|
@ -208,7 +221,7 @@ class Shuttler(EnvExperiment):
|
||||||
b0=0,
|
b0=0,
|
||||||
b1=shuttler_dds_damp_mu(0.06835937),
|
b1=shuttler_dds_damp_mu(0.06835937),
|
||||||
b2=shuttler_dds_ddamp_mu(-0.0001367187),
|
b2=shuttler_dds_ddamp_mu(-0.0001367187),
|
||||||
b3=0,
|
b3=int64(0),
|
||||||
c0=0,
|
c0=0,
|
||||||
c1=shuttler_freq_mu(end_f_MHz),
|
c1=shuttler_freq_mu(end_f_MHz),
|
||||||
c2=0,
|
c2=0,
|
||||||
|
@ -217,26 +230,26 @@ class Shuttler(EnvExperiment):
|
||||||
b0=0,
|
b0=0,
|
||||||
b1=shuttler_dds_damp_mu(0.06835937),
|
b1=shuttler_dds_damp_mu(0.06835937),
|
||||||
b2=shuttler_dds_ddamp_mu(-0.0001367187),
|
b2=shuttler_dds_ddamp_mu(-0.0001367187),
|
||||||
b3=0,
|
b3=int64(0),
|
||||||
c0=0,
|
c0=0,
|
||||||
c1=0,
|
c1=0,
|
||||||
c2=0,
|
c2=0,
|
||||||
)
|
)
|
||||||
self.shuttler0_trigger.trigger(0b11)
|
self.shuttler0_trigger.trigger(0b11)
|
||||||
delay(500*us)
|
self.core.delay(500.*us)
|
||||||
|
|
||||||
## Step 5 ##
|
## Step 5 ##
|
||||||
self.shuttler0_volt[0].set_waveform(
|
self.shuttler0_volt[0].set_waveform(
|
||||||
a0=shuttler_volt_amp_mu(-5.0),
|
a0=shuttler_volt_amp_mu(-5.0),
|
||||||
a1=int32(shuttler_volt_damp_mu(0.01)),
|
a1=int32(shuttler_volt_damp_mu(0.01)),
|
||||||
a2=0,
|
a2=int64(0),
|
||||||
a3=0,
|
a3=int64(0),
|
||||||
)
|
)
|
||||||
self.shuttler0_dds[0].set_waveform(
|
self.shuttler0_dds[0].set_waveform(
|
||||||
b0=shuttler_dds_amp_mu(1.0),
|
b0=shuttler_dds_amp_mu(1.0),
|
||||||
b1=0,
|
b1=0,
|
||||||
b2=0,
|
b2=int64(0),
|
||||||
b3=0,
|
b3=int64(0),
|
||||||
c0=0,
|
c0=0,
|
||||||
c1=shuttler_freq_mu(end_f_MHz),
|
c1=shuttler_freq_mu(end_f_MHz),
|
||||||
c2=0,
|
c2=0,
|
||||||
|
@ -244,59 +257,59 @@ class Shuttler(EnvExperiment):
|
||||||
self.shuttler0_volt[1].set_waveform(
|
self.shuttler0_volt[1].set_waveform(
|
||||||
a0=shuttler_volt_amp_mu(-5.0),
|
a0=shuttler_volt_amp_mu(-5.0),
|
||||||
a1=int32(shuttler_volt_damp_mu(0.01)),
|
a1=int32(shuttler_volt_damp_mu(0.01)),
|
||||||
a2=0,
|
a2=int64(0),
|
||||||
a3=0,
|
a3=int64(0),
|
||||||
)
|
)
|
||||||
self.shuttler0_dds[1].set_waveform(
|
self.shuttler0_dds[1].set_waveform(
|
||||||
b0=0,
|
b0=0,
|
||||||
b1=0,
|
b1=0,
|
||||||
b2=0,
|
b2=int64(0),
|
||||||
b3=0,
|
b3=int64(0),
|
||||||
c0=0,
|
c0=0,
|
||||||
c1=0,
|
c1=0,
|
||||||
c2=0,
|
c2=0,
|
||||||
)
|
)
|
||||||
self.shuttler0_trigger.trigger(0b11)
|
self.shuttler0_trigger.trigger(0b11)
|
||||||
delay(1000*us)
|
self.core.delay(1000.*us)
|
||||||
|
|
||||||
## Step 6 ##
|
## Step 6 ##
|
||||||
self.shuttler0_volt[0].set_waveform(
|
self.shuttler0_volt[0].set_waveform(
|
||||||
a0=shuttler_volt_amp_mu(-2.5),
|
a0=shuttler_volt_amp_mu(-2.5),
|
||||||
a1=int32(shuttler_volt_damp_mu(0.01)),
|
a1=int32(shuttler_volt_damp_mu(0.01)),
|
||||||
a2=0,
|
a2=int64(0),
|
||||||
a3=0,
|
a3=int64(0),
|
||||||
)
|
)
|
||||||
self.shuttler0_dds[0].set_waveform(
|
self.shuttler0_dds[0].set_waveform(
|
||||||
b0=0,
|
b0=0,
|
||||||
b1=shuttler_dds_damp_mu(0.06835937),
|
b1=shuttler_dds_damp_mu(0.06835937),
|
||||||
b2=shuttler_dds_ddamp_mu(-0.0001367187),
|
b2=shuttler_dds_ddamp_mu(-0.0001367187),
|
||||||
b3=0,
|
b3=int64(0),
|
||||||
c0=0,
|
c0=0,
|
||||||
c1=shuttler_freq_mu(start_f_MHz),
|
c1=shuttler_freq_mu(start_f_MHz),
|
||||||
c2=shuttler_freq_sweep(start_f_MHz, end_f_MHz, duration_us),
|
c2=shuttler_freq_sweep(start_f_MHz, end_f_MHz, duration_us),
|
||||||
)
|
)
|
||||||
self.shuttler0_trigger.trigger(0b1)
|
self.shuttler0_trigger.trigger(0b1)
|
||||||
self.shuttler_channel_reset(1)
|
self.shuttler_channel_reset(1)
|
||||||
delay(500*us)
|
self.core.delay(500.*us)
|
||||||
|
|
||||||
## Step 7 ##
|
## Step 7 ##
|
||||||
self.shuttler0_volt[0].set_waveform(
|
self.shuttler0_volt[0].set_waveform(
|
||||||
a0=shuttler_volt_amp_mu(2.5),
|
a0=shuttler_volt_amp_mu(2.5),
|
||||||
a1=int32(shuttler_volt_damp_mu(-0.01)),
|
a1=int32(shuttler_volt_damp_mu(-0.01)),
|
||||||
a2=0,
|
a2=int64(0),
|
||||||
a3=0,
|
a3=int64(0),
|
||||||
)
|
)
|
||||||
self.shuttler0_dds[0].set_waveform(
|
self.shuttler0_dds[0].set_waveform(
|
||||||
b0=0,
|
b0=0,
|
||||||
b1=shuttler_dds_damp_mu(-0.06835937),
|
b1=shuttler_dds_damp_mu(-0.06835937),
|
||||||
b2=shuttler_dds_ddamp_mu(0.0001367187),
|
b2=shuttler_dds_ddamp_mu(0.0001367187),
|
||||||
b3=0,
|
b3=int64(0),
|
||||||
c0=shuttler_phase_offset(180.0),
|
c0=shuttler_phase_offset(180.0),
|
||||||
c1=shuttler_freq_mu(end_f_MHz),
|
c1=shuttler_freq_mu(end_f_MHz),
|
||||||
c2=shuttler_freq_sweep(end_f_MHz, start_f_MHz, duration_us),
|
c2=shuttler_freq_sweep(end_f_MHz, start_f_MHz, duration_us),
|
||||||
)
|
)
|
||||||
self.shuttler0_trigger.trigger(0b1)
|
self.shuttler0_trigger.trigger(0b1)
|
||||||
delay(500*us)
|
self.core.delay(500.*us)
|
||||||
|
|
||||||
## Step 8 ##
|
## Step 8 ##
|
||||||
self.shuttler0_relay.enable(0)
|
self.shuttler0_relay.enable(0)
|
||||||
|
@ -308,7 +321,7 @@ class Shuttler(EnvExperiment):
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
for j in range(3):
|
for j in range(3):
|
||||||
self.shuttler0_leds[i].pulse(.1*s)
|
self.shuttler0_leds[i].pulse(.1*s)
|
||||||
delay(.1*s)
|
self.core.delay(.1*s)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def relay_init(self):
|
def relay_init(self):
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"min_artiq_version": "9.0",
|
"min_artiq_version": "9.0",
|
||||||
"variant": "nac3devices",
|
"variant": "nac3devices",
|
||||||
"hw_rev": "v2.0",
|
"hw_rev": "v2.0",
|
||||||
"base": "standalone",
|
"drtio_role": "master",
|
||||||
"core_addr": "192.168.1.70",
|
"core_addr": "192.168.1.70",
|
||||||
"peripherals": [
|
"peripherals": [
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,10 @@
|
||||||
{
|
{
|
||||||
"type": "phaser",
|
"type": "phaser",
|
||||||
"ports": [10]
|
"ports": [10]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "shuttler",
|
||||||
|
"ports": [11]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ from artiq.coredevice.edge_counter import EdgeCounter
|
||||||
from artiq.coredevice.grabber import Grabber
|
from artiq.coredevice.grabber import Grabber
|
||||||
from artiq.coredevice.fastino import Fastino
|
from artiq.coredevice.fastino import Fastino
|
||||||
from artiq.coredevice.phaser import Phaser
|
from artiq.coredevice.phaser import Phaser
|
||||||
|
from artiq.coredevice.shuttler import Volt as ShuttlerDCBias, Dds as ShuttlerDDS
|
||||||
|
|
||||||
|
|
||||||
@nac3
|
@nac3
|
||||||
|
@ -34,6 +35,8 @@ class NAC3Devices(EnvExperiment):
|
||||||
grabber0: KernelInvariant[Grabber]
|
grabber0: KernelInvariant[Grabber]
|
||||||
fastino0: KernelInvariant[Fastino]
|
fastino0: KernelInvariant[Fastino]
|
||||||
phaser0: KernelInvariant[Phaser]
|
phaser0: KernelInvariant[Phaser]
|
||||||
|
shuttler0_volt0: KernelInvariant[ShuttlerDCBias]
|
||||||
|
shuttler0_dds0: KernelInvariant[ShuttlerDDS]
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
self.setattr_device("core")
|
self.setattr_device("core")
|
||||||
|
@ -52,6 +55,8 @@ class NAC3Devices(EnvExperiment):
|
||||||
self.setattr_device("grabber0")
|
self.setattr_device("grabber0")
|
||||||
self.setattr_device("fastino0")
|
self.setattr_device("fastino0")
|
||||||
self.setattr_device("phaser0")
|
self.setattr_device("phaser0")
|
||||||
|
self.setattr_device("shuttler0_volt0")
|
||||||
|
self.setattr_device("shuttler0_dds0")
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
Loading…
Reference in New Issue