atomiq.components.sinara.urukul =============================== .. py:module:: atomiq.components.sinara.urukul Classes ------- .. autoapisummary:: atomiq.components.sinara.urukul.Urukul atomiq.components.sinara.urukul.UrukulChannel Module Contents --------------- .. py:class:: Urukul(cpld, default_profile = 7, *args, **kwargs) Bases: :py:obj:`atomiq.components.primitives.Component` Sinara Urukul 4 Channel DDS This class represents the Sinara Urukul 4 channel DDS RF source. :param cpld: The ARTIQ cpld device from the `device_db`, e.g. `@urukul0_cpld`. :param default_profile: Which profile in the Urukul CPLD to use by default, i.e. if no profile is given (default 7) .. py:attribute:: kernel_invariants .. py:attribute:: cpld .. py:attribute:: profile :value: 7 .. py:method:: _prerun() Specify here what should be done for this component before the run starts. In contrast to the _build() method, the _prerun() routine is executed on the core device before the actual experiment starts. .. py:method:: _set_profile_artiq9(profile = ad9910.DEFAULT_PROFILE, trigger = True) Set the Urukul to the given profile. :param TInt32 profile: profile :param TBool trigger: pulse io_update .. py:method:: set_profile(profile = ad9910.DEFAULT_PROFILE, trigger = True) Set the Urukul to the given profile. :param TInt32 profile: profile :param TBool trigger: pulse io_update .. py:class:: UrukulChannel(urukul, device, ttl=None, default_attenuation=19.0, profile_arb = 0, use_drg = True, auto_sync_drg = 0, read_delay = np.int64(8000), write_delay = np.int64(8000), calc_delay_modifier = np.int64(7), *args, **kwargs) Bases: :py:obj:`atomiq.components.electronics.rfsource.RFSource`, :py:obj:`atomiq.components.primitives.Switchable` Single DDS Channel of a Sinara Urukul :param urukul: The Urukul component this channel belongs to :param device: The ARTIQ device from the `device_db` representing the Urukul channel, e.g. `@urukul0_ch0` :param ttl: The ARTIQ device from the `device_db` representing the Urukul fast RF switch, e.g. `@ttl_urukul0_sw0` :param default_attenuation: Default attenuation to set for the channel on startup. (default -19dBm) :param profile_arb: Profile on the DDS to use for arbitrary function generation. (default 0) :param use_drg: Use the DRG for amplitude or frequency ramps (recommended). (default True) :param auto_sync_drg: Defined if the drg is synced to either frequency (1) or amplitude (2) in the prepare phase. Default is not synced (0). Syncing is recommended in combination with :attr:`blind` if continuous operation is required. :param read_delay: Delay necessary for read operations of 64bit in mu. This is hardware specific and can be obtained from :meth:`calibrate_read_write_delays`.The default value is conservative but fine for most uses. If you need to for example run drg ramps in quick succession you should adjust this. :param write_delay: Delay necessary for write operations of 64bit in mu. See :attr:`read_delay` for more info. :param calc_delay_modifier: Multiplier for delays inserted into function code to accommodate for CPU calculation time and avoid underflow. If necessary you can try to reduce the conservative default value. Specifically for Kasli SoC, the necessary multiplier is smaller. .. tip:: The :meth:`ramp` method can be used in combination with the :code:`blind` component argument. This allows for generating continous, jump-free ramps between experiments. This makes it possible to use the dds output to generate a lock signal for a laser cavity lock. .. attention:: Setting parameters before the DRG is synced with the python object would break the continuity. Run :meth:`sync_drg` before setting amplitude, frequency or phase parameters or use :attr:`auto_sync_drg`. .. py:attribute:: kernel_invariants .. py:attribute:: urukul .. py:attribute:: device .. py:attribute:: attenuation :value: 19.0 .. py:attribute:: profile_arb :value: 0 .. py:attribute:: profile_default :value: 7 .. py:attribute:: use_drg :value: True .. py:attribute:: auto_sync_drg :value: 0 .. py:attribute:: read_delay .. py:attribute:: write_delay .. py:attribute:: calc_delay_modifier .. py:method:: init() Initialize the urukul channel. Necessary only once after power on. .. warning:: This function is not called automatically as it is slow and resets the device leading to a frequency/amplitude jump. .. py:method:: _prerun() Specify here what should be done for this component before the run starts. In contrast to the _build() method, the _prerun() routine is executed on the core device before the actual experiment starts. .. py:method:: _prerun_blind() .. py:method:: set(frequency = float('nan'), amplitude = float('nan'), phase = 0.0, profile = -1) Set the frequency and amplitude. Frequency/amplitude are set to the last known value if ``float("nan")`` is passed (default). :param frequency: Frequency in Hz (``float("nan")`` to use previous value) :param amplitude: Amplitude in units of full scale (``float("nan")`` to use previous value) :param phase: Phase tuning word in turns :param profile: DDS Profile (``-1`` to keep current profile) .. py:method:: set_att(attenuation) Set the hardware attenuation for this urukul channel via CPLD. :param attenuation: channel attenuation (0. to 31.0 in 0.5 increments) [dB] .. py:method:: _set_frequency(frequency) .. py:method:: _set_amplitude(amplitude) .. py:method:: _set_phase(phase) .. py:method:: on() Turn on via ttl. :return .. py:method:: off() Turn off via ttl. :return .. py:method:: _on_cpld() .. py:method:: _off_cpld() .. py:method:: calibrate_read_write_delays(security_factor = 1.4) Helper function to calibrate the delays necessary in high level functions when writing and reading registers from the DDS to avoid underflows. The default values for the component arguments `read_delay` and `write_delay` are conservative and should generally work. If you need fast successive drg ramps you can obtain your hardware specific values with this method and try to lower the delays in your components db. :param security_factor: Factor with which the returned delay values are multiplied. Since the CPU is non-deterministic the real calculation time can vary, which is compensated by the security factor. :returns: The read (0) and write (1) delays in machine units. :rtype: tuple[TInt64, TInt64] .. attention:: This method turns off the urukul output writes into the drg registers and therefore brings the drg out of sync. It is generally not meant to run within a real experiment but for one-time callibration. .. py:method:: amplitude_to_drg_step(val) .. py:method:: read64_32(addr) Read two 32-bit values from 64-bit register. Advances time cursor by 8640ns and removes all slack :param addr: Register address :returns: Tuple of two 32-bit integer register values .. py:method:: _drg_write_registers(ramp_low, ramp_high, step_word) Writes the registers for drg ramp limits and step size. Advances time cursor by 2496ns .. py:method:: sync_drg(target) Synchronises the python object with the current register values of the DRG. Advances time cursor by 25us. :param target: Target to synchronise to. 1 for frequency, 2 for amplitude. .. py:method:: _write_drg_ramp(ramp_rate, end_val, old_low, old_high, step) .. py:method:: _amplitude_ramp_drg(duration, amplitude_start, amplitude_end, ramp_timestep = 0.0002) .. py:method:: _frequency_ramp_drg(duration, frequency_start, frequency_end, ramp_timestep) .. py:method:: _ramp(duration, frequency_start, frequency_end, amplitude_start, amplitude_end, ramp_timestep = 5e-05) 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 RFSource .. py:method:: ramp(duration, frequency_start = float('nan'), frequency_end = float('nan'), amplitude_start = float('nan'), amplitude_end = float('nan'), ramp_timestep = float('nan'), ramp_steps = -1) Ramp frequency and amplitude over a given duration. Parameters default to ``-1`` or ``nan`` to indicate no change. If the start frequency/amplitude is set to ``nan``, the ramp starts from the last frequency/amplitude which was set. This method advances the timeline by ´duration´ .. tip:: This method can be used in combination with the :code:`blind` component argument. This allows for generating continuous, jump-free ramps between experiments. This makes it possible to use the dds output to generate a lock signal for a laser cavity lock. Note that in this mode using amplitude *and* frequency ramps leads to undefined behavior when switching between them. As the DRG can only address either amplitude or frequency, parallel ramps of both parameters are ramped in a simple step by step way. Usage of the DRG can be avoided by setting the component attribute :code:`use_drg` to False. .. attention:: When using the DRG, this method always advances the timeline by at least 10us, even if the ramp is shorter. Reading and writing of DDS registers is scheduled in the past, this means no drg changes should be made in the ~100us (dependent on :code:`read_delay` and :code:`write_delay`) before this function is called. :param duration: ramp duration [s] :param frequency_start: initial frequency [Hz] :param frequency_end: end frequency [Hz] :param amplitude_start: initial amplitude [0..1] :param amplitude_end: end amplitude [0..1] :param ramp_timesteps: time between steps in the ramp [s] :param ramp_steps: number of steps the whole ramp should have. This takes precedence over `ramp_timesteps` .. py:method:: _write_ram(data, transform=identity_float_int32) Write data to RAM. .. note:: This is copied from upstream artiq to fix a bug, where the data is written into the RAM in reversed order. Once this is fixed upstream, we can remove this The profile to write to and the step, start, and end address need to be configured before and separately using :meth:`set_profile_ram` and the parent CPLD `set_profile`. :param data: Data to be written to RAM. .. py:method:: _arb(duration, samples_amp, samples_freq, samples_phase, repetitions = 1, prepare_only = False, run_prepared = False, transform_amp=identity_float, transform_freq=identity_float, transform_phase=identity_float) .. py:method:: _prepare_arb(samples, t_step, repeat = False, ram_offset = 0, profile = 0, transform=identity_float_int32) Prepare a RAM profile for arbitrary amplitude modulation with amplitude values and equidistant time steps. :param samples: List of sample values in units im machine units. Maximum lenght is 1024 samples. :param t_step: Time that should pass between the samples of the amplitudes list in units of s. :param repeat: Should the sequence of samples be repeated? If not the last value is hold. (default False) :param ram_offset: Address offset of the RAM storage address. (default 0) :param profile: Profile of the DDS to use for the RAM mode. If none is given, profile 0 is used. .. py:method:: _run_arb(duration, ram_destination, trigger = True, profile = -1, start_time = 0) .. py:method:: arb(duration, samples_amp = [], samples_freq = [], samples_phase = [], repetitions = 1, prepare_only = False, run_prepared = False, transform_amp=identity_float, transform_freq=identity_float, transform_phase=identity_float) Play Arbitrary Samples from a List This method allows to set the output amplitude, frequency an phase according to the values specified in respective lists. The whole sequence is played in the specified duration. The pattern store in the sample list can also be repeated. .. tip:: We supports a scheme to prepare the arb function before it is actually used. If that is needed, run this function with :code:`prepapre_only = True` when the arb should be prepared and with :code:`run_prepared = True` when the prepared arb should be played. In both calls the other parameters have to be passed. .. attention:: This method always advances the timeline by at least 1.5us, even if the arb sample is shorter. Reading and writing of DDS registers is scheduled in the past, this means no drg changes should be made in ~5us (for :code:`run_prepared=True`, if wrtiting to RAM, this time is longer) before the function call. :param samples_amp: List of amplitude samples. If this list is empty (default), the amplitude is not modified. :param samples_freq: List of frequency samples. If this list is empty (default), the frequency is not modified. :param samples_phase: List of phase samples. If this list is empty (default), the phase is not modified. :param duration: The time in which the whole sequence of samples should be played back [s]. :param repetitions: Number of times the sequence of all samples should be played. (default 1) :param prepare_only: Only write the sequence to RAM, don't play it. :param run_prepared: Play arb sequence previously prepared with :code:`prepare_only`. :param transform_amp: Function to transform amplitude samples, must take a single argument of type :type:`TFloat` and return a single :type:`TFloat`. :param transform_freq: Function to transform frequency samples (see :code:`transform_amp`). :param transform_phase: Function to transform phase samples (see :code:`transform_amp`).