forked from M-Labs/artiq
Coredevice Input Validation (#1447)
* Input validation and masking of SI -> mu conversions (close #1446) Signed-off-by: Marius Weber <marius.weber@physics.ox.ac.uk> * Update RELEASE_NOTES Signed-off-by: Marius Weber <marius.weber@physics.ox.ac.uk> Co-authored-by: Robert Jördens <rj@quartiq.de>
This commit is contained in:
parent
b3b6cb8efe
commit
2538840756
|
@ -11,6 +11,7 @@ Highlights:
|
||||||
* Performance improvements:
|
* Performance improvements:
|
||||||
- #1432: SERDES TTL inputs can now detect edges on pulses that are shorter
|
- #1432: SERDES TTL inputs can now detect edges on pulses that are shorter
|
||||||
than the RTIO period
|
than the RTIO period
|
||||||
|
* Coredevice SI to mu conversions now always return valid codes, or raise a `ValueError`.
|
||||||
* Zotino now exposes `voltage_to_mu()`
|
* Zotino now exposes `voltage_to_mu()`
|
||||||
|
|
||||||
Breaking changes:
|
Breaking changes:
|
||||||
|
|
|
@ -553,7 +553,7 @@ class AD9910:
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def frequency_to_ftw(self, frequency):
|
def frequency_to_ftw(self, frequency):
|
||||||
"""Return the frequency tuning word corresponding to the given
|
"""Return the 32-bit frequency tuning word corresponding to the given
|
||||||
frequency.
|
frequency.
|
||||||
"""
|
"""
|
||||||
return int32(round(self.ftw_per_hz*frequency))
|
return int32(round(self.ftw_per_hz*frequency))
|
||||||
|
@ -567,9 +567,9 @@ class AD9910:
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def turns_to_pow(self, turns):
|
def turns_to_pow(self, turns):
|
||||||
"""Return the phase offset word corresponding to the given phase
|
"""Return the 16-bit phase offset word corresponding to the given phase
|
||||||
in turns."""
|
in turns."""
|
||||||
return int32(round(turns*0x10000))
|
return int32(round(turns*0x10000)) & 0xffff
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def pow_to_turns(self, pow_):
|
def pow_to_turns(self, pow_):
|
||||||
|
@ -579,9 +579,12 @@ class AD9910:
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def amplitude_to_asf(self, amplitude):
|
def amplitude_to_asf(self, amplitude):
|
||||||
"""Return amplitude scale factor corresponding to given fractional
|
"""Return 14-bit amplitude scale factor corresponding to given
|
||||||
amplitude."""
|
fractional amplitude."""
|
||||||
return int32(round(amplitude*0x3ffe))
|
code = int32(round(amplitude * 0x3ffe))
|
||||||
|
if code < 0 or code > (1 << 14) - 1:
|
||||||
|
raise ValueError("Invalid AD9910 fractional amplitude!")
|
||||||
|
return code
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def asf_to_amplitude(self, asf):
|
def asf_to_amplitude(self, asf):
|
||||||
|
|
|
@ -157,10 +157,10 @@ class AD9912:
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def frequency_to_ftw(self, frequency):
|
def frequency_to_ftw(self, frequency):
|
||||||
"""Returns the frequency tuning word corresponding to the given
|
"""Returns the 48-bit frequency tuning word corresponding to the given
|
||||||
frequency.
|
frequency.
|
||||||
"""
|
"""
|
||||||
return int64(round(self.ftw_per_hz*frequency))
|
return int64(round(self.ftw_per_hz*frequency)) & ((int64(1) << 48) - 1)
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def ftw_to_frequency(self, ftw):
|
def ftw_to_frequency(self, ftw):
|
||||||
|
@ -171,10 +171,10 @@ class AD9912:
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def turns_to_pow(self, phase):
|
def turns_to_pow(self, phase):
|
||||||
"""Returns the phase offset word corresponding to the given
|
"""Returns the 16-bit phase offset word corresponding to the given
|
||||||
phase.
|
phase.
|
||||||
"""
|
"""
|
||||||
return int32(round((1 << 14)*phase))
|
return int32(round((1 << 14)*phase)) & 0xffff
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set(self, frequency, phase=0.0):
|
def set(self, frequency, phase=0.0):
|
||||||
|
|
|
@ -236,10 +236,10 @@ class AD9914:
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def frequency_to_ftw(self, frequency):
|
def frequency_to_ftw(self, frequency):
|
||||||
"""Returns the frequency tuning word corresponding to the given
|
"""Returns the 32-bit frequency tuning word corresponding to the given
|
||||||
frequency.
|
frequency.
|
||||||
"""
|
"""
|
||||||
return round(float(int64(2)**32*frequency/self.sysclk))
|
return int32(round(float(int64(2)**32*frequency/self.sysclk)))
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def ftw_to_frequency(self, ftw):
|
def ftw_to_frequency(self, ftw):
|
||||||
|
@ -250,9 +250,9 @@ class AD9914:
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def turns_to_pow(self, turns):
|
def turns_to_pow(self, turns):
|
||||||
"""Returns the phase offset word corresponding to the given phase
|
"""Returns the 16-bit phase offset word corresponding to the given
|
||||||
in turns."""
|
phase in turns."""
|
||||||
return round(float(turns*2**16))
|
return round(float(turns*2**16)) & 0xffff
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def pow_to_turns(self, pow):
|
def pow_to_turns(self, pow):
|
||||||
|
@ -262,8 +262,12 @@ class AD9914:
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def amplitude_to_asf(self, amplitude):
|
def amplitude_to_asf(self, amplitude):
|
||||||
"""Returns amplitude scale factor corresponding to given amplitude."""
|
"""Returns 12-bit amplitude scale factor corresponding to given
|
||||||
return round(float(amplitude*0x0fff))
|
amplitude."""
|
||||||
|
code = round(float(amplitude * 0x0fff))
|
||||||
|
if code < 0 or code > 0xfff:
|
||||||
|
raise ValueError("Invalid AD9914 amplitude!")
|
||||||
|
return code
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def asf_to_amplitude(self, asf):
|
def asf_to_amplitude(self, asf):
|
||||||
|
@ -314,10 +318,11 @@ class AD9914:
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def frequency_to_xftw(self, frequency):
|
def frequency_to_xftw(self, frequency):
|
||||||
"""Returns the frequency tuning word corresponding to the given
|
"""Returns the 63-bit frequency tuning word corresponding to the given
|
||||||
frequency (extended resolution mode).
|
frequency (extended resolution mode).
|
||||||
"""
|
"""
|
||||||
return int64(round(2.0*float(int64(2)**62)*frequency/self.sysclk))
|
return int64(round(2.0*float(int64(2)**62)*frequency/self.sysclk)) & (
|
||||||
|
(int64(1) << 63) - 1)
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def xftw_to_frequency(self, xftw):
|
def xftw_to_frequency(self, xftw):
|
||||||
|
|
|
@ -558,5 +558,7 @@ class Channel:
|
||||||
:param y: IIR state in units of full scale
|
:param y: IIR state in units of full scale
|
||||||
"""
|
"""
|
||||||
y_mu = int(round(y * Y_FULL_SCALE_MU))
|
y_mu = int(round(y * Y_FULL_SCALE_MU))
|
||||||
|
if y_mu < 0 or y_mu > (1 << 17) - 1:
|
||||||
|
raise ValueError("Invalid SUServo y-value!")
|
||||||
self.set_y_mu(profile, y_mu)
|
self.set_y_mu(profile, y_mu)
|
||||||
return y_mu
|
return y_mu
|
||||||
|
|
|
@ -292,7 +292,7 @@ class CPLD:
|
||||||
:meth:`get_att_mu` to retrieve the hardware state set in previous experiments.
|
:meth:`get_att_mu` to retrieve the hardware state set in previous experiments.
|
||||||
|
|
||||||
:param channel: Attenuator channel (0-3).
|
:param channel: Attenuator channel (0-3).
|
||||||
:param att: Digital attenuation setting:
|
:param att: 8-bit digital attenuation setting:
|
||||||
255 minimum attenuation, 0 maximum attenuation (31.5 dB)
|
255 minimum attenuation, 0 maximum attenuation (31.5 dB)
|
||||||
"""
|
"""
|
||||||
a = self.att_reg & ~(0xff << (channel * 8))
|
a = self.att_reg & ~(0xff << (channel * 8))
|
||||||
|
@ -325,7 +325,10 @@ class CPLD:
|
||||||
attenuation. Minimum attenuation is 0*dB, maximum attenuation is
|
attenuation. Minimum attenuation is 0*dB, maximum attenuation is
|
||||||
31.5*dB.
|
31.5*dB.
|
||||||
"""
|
"""
|
||||||
self.set_att_mu(channel, 255 - int32(round(att*8)))
|
code = 255 - int32(round(att*8))
|
||||||
|
if code < 0 or code > 255:
|
||||||
|
raise ValueError("Invalid urukul.CPLD attenuation!")
|
||||||
|
self.set_att_mu(channel, code)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def get_att_mu(self):
|
def get_att_mu(self):
|
||||||
|
|
Loading…
Reference in New Issue