suservo: clarify timings

close #1027
This commit is contained in:
Robert Jördens 2018-06-01 06:14:30 +00:00
parent a42f774440
commit 22506e849f
1 changed files with 53 additions and 38 deletions

View File

@ -17,13 +17,13 @@ COEFF_SHIFT = 11
@portable
def y_mu_to_full_scale(y):
"""Convert Servo Y data from machine units to units of full scale."""
"""Convert servo Y data from machine units to units of full scale."""
return y*(1./(1 << COEFF_WIDTH - 1))
@portable
def adc_mu_to_volts(x, gain):
"""Convert Servo ADC data from machine units to Volt."""
"""Convert servo ADC data from machine units to Volt."""
val = (x >> 1) & 0xffff
mask = 1 << 15
val = -(val & mask) + (val & ~mask)
@ -36,20 +36,21 @@ class SUServo:
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. SUServo can for example be used to implement intensity
stabilization of laser beams with an AOM and a photodetector.
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 SUServo supports multiple preconfigured profiles per channel
Additionally SU Servo supports multiple preconfigured profiles per channel
and features like automatic integrator hold.
Notes:
* See the SUServo variant of the Kasli target for an example of how to
* 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 SUServo
* 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.)
@ -89,9 +90,10 @@ class SUServo:
@kernel
def init(self):
"""Initialize the Servo, Sampler and both Urukuls.
"""Initialize the servo, Sampler and both Urukuls.
Leaves the Servo disabled (see :meth:`set_config`), resets all DDS.
Leaves the servo disabled (see :meth:`set_config`), resets and
configures all DDS.
Urukul initialization is performed blindly as there is no readback from
the DDS or the CPLDs.
@ -120,7 +122,7 @@ class SUServo:
@kernel
def write(self, addr, value):
"""Write to Servo memory.
"""Write to servo memory.
This method advances the timeline by one coarse RTIO cycle.
@ -132,7 +134,7 @@ class SUServo:
@kernel
def read(self, addr):
"""Read from Servo memory.
"""Read from servo memory.
This method does not advance the timeline but consumes all slack.
@ -145,14 +147,16 @@ class SUServo:
def set_config(self, enable):
"""Set SU Servo configuration.
This method advances the timeline by one Servo memory access.
This method advances the timeline by one servo memory access.
It does not support RTIO event replacement.
:param enable (int): Enable Servo operation. Enabling starts servo
iterations beginning with the ADC sampling stage. This also
provides a mean for synchronization of Servo updates to other RTIO
activity.
Disabling takes up to 2 Servo cycles (~2.2 µs) to clear the
:param enable (int): 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.
"""
self.write(CONFIG_ADDR, enable)
@ -163,8 +167,8 @@ class SUServo:
This method does not advance the timeline but consumes all slack.
The ``done`` bit indicates that a SUServo cycle has completed.
It is pulsed for one RTIO cycle every SUServo cycle and asserted
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).
@ -246,10 +250,13 @@ class Channel:
def set(self, en_out, en_iir=0, profile=0):
"""Operate channel.
This method does not advance the timeline.
Output RF switch setting takes effect immediately.
IIR updates take place once the RF switch has been enabled for the
configured delay and the profile setting has been stable.
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
``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.
:param en_out: RF switch enable
:param en_iir: IIR updates enable
@ -279,7 +286,7 @@ class Channel:
def set_dds(self, profile, frequency, offset, phase=0.):
"""Set profile DDS coefficients.
This method advances the timeline by four Servo memory accesses.
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.
@ -332,7 +339,7 @@ class Channel:
:param b1: 18 bit signed B1 coefficient (old,
X1 coefficient, feed forward, proportional gain)
:param dly: IIR update suppression time. In units of IIR cycles
(~1.2 µs, 0-255)
(~1.2 µs, 0-255).
"""
base = (self.servo_channel << 8) | (profile << 3)
self.servo.write(base + 3, adc | (dly << 8))
@ -344,7 +351,7 @@ class Channel:
def set_iir(self, profile, adc, gain, corner=0., limit=0., delay=0.):
"""Set profile IIR coefficients.
This method advances the timeline by four Servo memory accesses.
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.
@ -374,7 +381,12 @@ class Channel:
:param limit: Integrator gain limit (1). When 0 (the default) the
integrator gain limit is infinite. Positive.
:param delay: Delay (in seconds, 0-300 µs) before allowing IIR updates
after invoking :meth:`set`.
after invoking :meth:`set`. This is rounded to the nearest number
of servo cycles (~1.2 µs). Since the RF switch (:meth:`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
:meth:`set`.
"""
B_NORM = 1 << COEFF_SHIFT + 1
A_NORM = 1 << COEFF_SHIFT
@ -424,11 +436,14 @@ class Channel:
def get_profile_mu(self, profile, data):
"""Retrieve profile data.
The data is returned in the `data` argument as:
`[ftw >> 16, b1, pow, adc | (delay << 8), offset, a1, ftw, b0]`.
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]``.
.. seealso:: The individual fields are described in
:meth:`set_iir_mu` and :meth:`set_dds_mu`.
This method advances the timeline by 32 µs and consumes all slack.
Profile data is returned
:param profile: Profile number (0-31)
:param data: List of 8 integers to write the profile data into
@ -473,11 +488,11 @@ class Channel:
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 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.
This method advances the timeline by one servo memory access.
:param profile: Profile number (0-31)
:param y: 17 bit unsigned Y0
@ -493,11 +508,11 @@ class Channel:
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 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.
This method advances the timeline by one servo memory access.
:param profile: Profile number (0-31)
:param y: IIR state in units of full scale