Source code for atomiq.components.sinara.dac

from __future__ import annotations

from atomiq.components.electronics.voltagesource import DAC, DACChannel

from artiq.experiment import kernel, delay
from artiq.language.types import TFloat, TBool, TInt64
from artiq.language.core import now_mu

import numpy as np


[docs] class Zotino(DAC): kernel_invariants = {"_zotino_device"} def __init__(self, zotino_device, *args, **kwargs): DAC.__init__(self, num_chan=32, *args, **kwargs) self._zotino_device = zotino_device @kernel def _prerun(self): self._zotino_device.init()
[docs] @kernel def update(self): self._zotino_device.load()
[docs] class ZotinoChannel(DACChannel): @kernel def _set_voltage(self, voltage: TFloat, update_dac: TBool = True): self.dac_device._zotino_device.write_dac(self.channel, voltage) if self.debug_output: self.experiment.log.info(self.identifier + ": Written to channel {0}", [self.channel]) self.experiment.log.info(self.identifier + ": Voltage: {0}", [voltage]) if update_dac: self.dac_device.update()
[docs] class Fastino(DAC): """The Sinara Fast ADC called Fastino Args: fastino_device: The ARTIQ fastino device from the `device_db` parallel_event_delay: Time by which occuring parallel events in ramps are moved [s] (default: 10ns) """ kernel_invariants = {"_fastino_device", "parallel_event_delay"} def __init__(self, fastino_device, parallel_event_delay: TBool = 10e-9, *args, **kwargs): DAC.__init__(self, num_chan=32, *args, **kwargs) self._fastino_device = fastino_device # variables for detecting parallel events self.event_slots = np.array([-1]*32, dtype=np.int64) self.event_slots_max_idx = -1 self.parallel_event_delay = parallel_event_delay @kernel def _prerun(self): # self._fastino_device.init() pass
[docs] @kernel def update(self): pass
[docs] @kernel def register_event(self, time: TInt64) -> TFloat: last_used = self.event_slots_max_idx first_free = last_used + 1 shift_needed = False for i in range(self.event_slots_max_idx, -1, -1): event = self.event_slots[i] # check if the time of the event already passed if event < now_mu(): self.event_slots[i] = -1 if last_used == self.event_slots_max_idx: last_used = i first_free = i # check for collision with the new event if event == time: shift_needed = True self.event_slots_max_idx = last_used if shift_needed: return self.register_event(time + self.core.seconds_to_mu(self.parallel_event_delay)) +\ self.parallel_event_delay else: self.event_slots[first_free] = time if first_free >= last_used: self.event_slots_max_idx = first_free return 0.0
[docs] class FastinoChannel(DACChannel): @kernel(flags={"fast-math"}) def _ramp_voltage(self, duration: TFloat, voltage_start: TFloat, voltage_end: TFloat, ramp_timestep: TFloat = 200e-6, relocate_parallel: TBool = True): """ This method implements a stupid ramp on an abstract level. This will most likely work but be slow. If your hardware has native support for ramping, please override this function when you inherit from VoltageSource """ if relocate_parallel: offset = self.dac_device.register_event(now_mu()) if offset > 0.0: self.experiment.log.warning(self.identifier + ": Found paralell ramp, delaying..") delay(offset) n = int(duration / ramp_timestep) ramp_timestep = duration / float(n) for i in range(n + 1): self._set_voltage(voltage_start + i * (voltage_end - voltage_start) / n, zero_time=True) delay(ramp_timestep) @kernel def _set_voltage(self, voltage: TFloat, zero_time: TBool = False): self.dac_device._fastino_device.set_dac(self.channel, voltage) # self.experiment.log.info(self.identifier + ": setting voltage to {0} V", [voltage]) if not zero_time: delay(0.1e-6)