forked from M-Labs/artiq
sawg: cleanup
This commit is contained in:
parent
fb58f31c9d
commit
ed6d1e73cc
|
@ -1,7 +1,7 @@
|
||||||
from numpy import int32, int64
|
from numpy import int32, int64
|
||||||
from artiq.language.core import kernel, now_mu, portable, delay
|
from artiq.language.core import kernel, now_mu, portable, delay
|
||||||
from artiq.coredevice.rtio import rtio_output, rtio_output_wide
|
from artiq.coredevice.rtio import rtio_output, rtio_output_wide
|
||||||
from artiq.language.types import TInt32, TInt64, TFloat, TList
|
from artiq.language.types import TInt32, TInt64, TFloat
|
||||||
|
|
||||||
|
|
||||||
class Spline:
|
class Spline:
|
||||||
|
@ -44,18 +44,18 @@ class Spline:
|
||||||
"""
|
"""
|
||||||
rtio_output(now_mu(), self.channel, 0, self.to_mu(value))
|
rtio_output(now_mu(), self.channel, 0, self.to_mu(value))
|
||||||
|
|
||||||
@kernel
|
@kernel(flags={"fast-math"})
|
||||||
def set64(self, value: TFloat):
|
def set64(self, value: TFloat):
|
||||||
"""Set spline value.
|
"""Set spline value.
|
||||||
|
|
||||||
:param value: Spline value relative to full-scale.
|
:param value: Spline value relative to full-scale.
|
||||||
"""
|
"""
|
||||||
v = self.to_mu64(value)
|
l = [int32(0)] * 2
|
||||||
l = [int32(v), int32(v >> 32)]
|
self.pack_coeff_mu([self.to_mu64(value)], l)
|
||||||
rtio_output_wide(now_mu(), self.channel, 0, l)
|
rtio_output_wide(now_mu(), self.channel, 0, l)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_coeff_mu(self, value):
|
def set_coeff_mu(self, value): # TList(TInt32)
|
||||||
"""Set spline raw values.
|
"""Set spline raw values.
|
||||||
|
|
||||||
:param value: Spline packed raw values.
|
:param value: Spline packed raw values.
|
||||||
|
@ -63,7 +63,7 @@ class Spline:
|
||||||
rtio_output_wide(now_mu(), self.channel, 0, value)
|
rtio_output_wide(now_mu(), self.channel, 0, value)
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def pack_coeff_mu(self, coeff, packed):
|
def pack_coeff_mu(self, coeff, packed): # TList(TInt64), TList(TInt32)
|
||||||
pos = 0
|
pos = 0
|
||||||
for i in range(len(coeff)):
|
for i in range(len(coeff)):
|
||||||
wi = self.width + i*self.time_width
|
wi = self.width + i*self.time_width
|
||||||
|
@ -74,13 +74,16 @@ class Spline:
|
||||||
avail = 32 - used
|
avail = 32 - used
|
||||||
if avail > wi:
|
if avail > wi:
|
||||||
avail = wi
|
avail = wi
|
||||||
packed[j] |= int32(ci & ((1 << avail) - 1)) << used
|
cij = int32(ci)
|
||||||
|
if avail != 32:
|
||||||
|
cij &= (1 << avail) - 1
|
||||||
|
packed[j] |= cij << used
|
||||||
ci >>= avail
|
ci >>= avail
|
||||||
wi -= avail
|
wi -= avail
|
||||||
pos += avail
|
pos += avail
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def coeff_to_mu(self, coeff, coeff64):
|
def coeff_to_mu(self, coeff, coeff64): # TList(TFloat), TList(TInt64)
|
||||||
for i in range(len(coeff)):
|
for i in range(len(coeff)):
|
||||||
vi = coeff[i] * self.scale
|
vi = coeff[i] * self.scale
|
||||||
for j in range(i):
|
for j in range(i):
|
||||||
|
@ -94,18 +97,31 @@ class Spline:
|
||||||
coeff64[2] += ci >> self.time_width
|
coeff64[2] += ci >> self.time_width
|
||||||
coeff64[1] += ci // 6 >> 2*self.time_width
|
coeff64[1] += ci // 6 >> 2*self.time_width
|
||||||
|
|
||||||
@kernel
|
def coeff_as_packed_mu(self, coeff64):
|
||||||
def set_coeff(self, value):
|
n = len(coeff64)
|
||||||
|
width = n*self.width + (n - 1)*n//2*self.time_width
|
||||||
|
packed = [int32(0)] * ((width + 31)//32)
|
||||||
|
self.pack_coeff_mu(coeff64, packed)
|
||||||
|
return packed
|
||||||
|
|
||||||
|
def coeff_as_packed(self, coeff):
|
||||||
|
coeff64 = [int64(0)] * len(coeff)
|
||||||
|
self.coeff_to_mu(coeff, coeff64)
|
||||||
|
return self.coeff_as_packed_mu(coeff64)
|
||||||
|
|
||||||
|
@kernel(flags={"fast-math"})
|
||||||
|
def set_coeff(self, coeff): # TList(TFloat)
|
||||||
"""Set spline coefficients.
|
"""Set spline coefficients.
|
||||||
|
|
||||||
:param value: List of floating point spline knot coefficients,
|
:param value: List of floating point spline knot coefficients,
|
||||||
lowest order (constant) coefficient first.
|
lowest order (constant) coefficient first. Units are the
|
||||||
|
unit of this spline's value times increasing powers of 1/s.
|
||||||
"""
|
"""
|
||||||
n = len(value)
|
n = len(coeff)
|
||||||
width = n*self.width + (n - 1)*n//2*self.time_width
|
|
||||||
coeff64 = [int64(0)] * n
|
coeff64 = [int64(0)] * n
|
||||||
|
self.coeff_to_mu(coeff, coeff64)
|
||||||
|
width = n*self.width + (n - 1)*n//2*self.time_width
|
||||||
packed = [int32(0)] * ((width + 31)//32)
|
packed = [int32(0)] * ((width + 31)//32)
|
||||||
self.coeff_to_mu(value, coeff64)
|
|
||||||
self.pack_coeff_mu(coeff64, packed)
|
self.pack_coeff_mu(coeff64, packed)
|
||||||
self.set_coeff_mu(packed)
|
self.set_coeff_mu(packed)
|
||||||
|
|
||||||
|
@ -132,15 +148,15 @@ class Spline:
|
||||||
and 3 are valid: step, linear, cubic.
|
and 3 are valid: step, linear, cubic.
|
||||||
"""
|
"""
|
||||||
if order == 0:
|
if order == 0:
|
||||||
delay(duration/2)
|
delay(duration/2.)
|
||||||
self.set_coeff([stop])
|
self.set_coeff([stop])
|
||||||
delay(duration/2)
|
delay(duration/2.)
|
||||||
elif order == 1:
|
elif order == 1:
|
||||||
self.set_coeff([start, (stop - start)/duration])
|
self.set_coeff([start, (stop - start)/duration])
|
||||||
delay(duration)
|
delay(duration)
|
||||||
elif order == 3:
|
elif order == 3:
|
||||||
v2 = 6*(stop - start)/(duration*duration)
|
v2 = 6.*(stop - start)/(duration*duration)
|
||||||
self.set_coeff([start, 0., v2, -2*v2/duration])
|
self.set_coeff([start, 0., v2, -2.*v2/duration])
|
||||||
delay(duration)
|
delay(duration)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid interpolation order. "
|
raise ValueError("Invalid interpolation order. "
|
||||||
|
@ -153,14 +169,14 @@ class SAWG:
|
||||||
|
|
||||||
oscillators = exp(2j*pi*(frequency0*t + phase0))*(
|
oscillators = exp(2j*pi*(frequency0*t + phase0))*(
|
||||||
amplitude1*exp(2j*pi*(frequency1*t + phase1)) +
|
amplitude1*exp(2j*pi*(frequency1*t + phase1)) +
|
||||||
amplitude2*exp(2j*pi*(frequency2*t + phase2))
|
amplitude2*exp(2j*pi*(frequency2*t + phase2)))
|
||||||
|
|
||||||
output = (offset +
|
output = (offset +
|
||||||
i_enable*Re(oscillators) +
|
i_enable*Re(oscillators) +
|
||||||
q_enable*Im(buddy_oscillators))
|
q_enable*Im(buddy_oscillators))
|
||||||
|
|
||||||
Where:
|
Where:
|
||||||
* offset, amplitude1, amplitude1: in units of full scale
|
* offset, amplitude1, amplitude2: in units of full scale
|
||||||
* phase0, phase1, phase2: in units of turns
|
* phase0, phase1, phase2: in units of turns
|
||||||
* frequency0, frequency1, frequency2: in units of Hz
|
* frequency0, frequency1, frequency2: in units of Hz
|
||||||
|
|
||||||
|
@ -184,13 +200,13 @@ class SAWG:
|
||||||
self.amplitude1 = Spline(width, time_width, channel_base + 2,
|
self.amplitude1 = Spline(width, time_width, channel_base + 2,
|
||||||
self.core, 1/(2*cordic_gain**2))
|
self.core, 1/(2*cordic_gain**2))
|
||||||
self.frequency1 = Spline(3*width, time_width, channel_base + 3,
|
self.frequency1 = Spline(3*width, time_width, channel_base + 3,
|
||||||
self.core, 1/self.core.coarse_ref_period)
|
self.core, self.core.coarse_ref_period)
|
||||||
self.phase1 = Spline(width, time_width, channel_base + 4,
|
self.phase1 = Spline(width, time_width, channel_base + 4,
|
||||||
self.core, 1.)
|
self.core, 1.)
|
||||||
self.amplitude2 = Spline(width, time_width, channel_base + 5,
|
self.amplitude2 = Spline(width, time_width, channel_base + 5,
|
||||||
self.core, 1/(2*cordic_gain**2))
|
self.core, 1/(2*cordic_gain**2))
|
||||||
self.frequency2 = Spline(3*width, time_width, channel_base + 6,
|
self.frequency2 = Spline(3*width, time_width, channel_base + 6,
|
||||||
self.core, 1/self.core.coarse_ref_period)
|
self.core, self.core.coarse_ref_period)
|
||||||
self.phase2 = Spline(width, time_width, channel_base + 7,
|
self.phase2 = Spline(width, time_width, channel_base + 7,
|
||||||
self.core, 1.)
|
self.core, 1.)
|
||||||
self.frequency0 = Spline(2*width, time_width, channel_base + 8,
|
self.frequency0 = Spline(2*width, time_width, channel_base + 8,
|
||||||
|
|
|
@ -110,13 +110,9 @@ class SAWGTest(unittest.TestCase):
|
||||||
# [.1, .01, -.00001], [.1, .01, .00001, -.000000001]
|
# [.1, .01, -.00001], [.1, .01, .00001, -.000000001]
|
||||||
for v in [-.1], [.1, -.01]:
|
for v in [-.1], [.1, -.01]:
|
||||||
ch = self.driver.offset
|
ch = self.driver.offset
|
||||||
q = [0] * len(v)
|
p = ch.coeff_as_packed(v)
|
||||||
ch.coeff_to_mu(v, q)
|
|
||||||
n = len(v)
|
|
||||||
t = ch.time_width
|
t = ch.time_width
|
||||||
w = ch.width
|
w = ch.width
|
||||||
p = [0] * ((n*w + (n - 1)*n//2*t + 31)//32)
|
|
||||||
ch.pack_coeff_mu(q, p)
|
|
||||||
p = [_ & 0xffffffff for _ in p]
|
p = [_ & 0xffffffff for _ in p]
|
||||||
p0 = [int(round(vi*ch.scale*ch.time_scale**i))
|
p0 = [int(round(vi*ch.scale*ch.time_scale**i))
|
||||||
for i, vi in enumerate(v)]
|
for i, vi in enumerate(v)]
|
||||||
|
@ -143,30 +139,19 @@ class SAWGTest(unittest.TestCase):
|
||||||
self.assertEqual(out[i], [v, v])
|
self.assertEqual(out[i], [v, v])
|
||||||
self.assertEqual(out[-1], [0, 0])
|
self.assertEqual(out[-1], [0, 0])
|
||||||
|
|
||||||
def pack(self, v):
|
|
||||||
n = len(v)
|
|
||||||
ch = self.driver.offset
|
|
||||||
t = ch.time_width
|
|
||||||
w = ch.width
|
|
||||||
p = [0] * ((n*w + (n - 1)*n//2*t + 31)//32)
|
|
||||||
ch.pack_coeff_mu(v, p)
|
|
||||||
p = [_ & 0xffffffff for _ in p]
|
|
||||||
return p
|
|
||||||
|
|
||||||
def test_pack(self):
|
def test_pack(self):
|
||||||
self.assertEqual(self.pack([1]), [1])
|
ch = self.driver.offset
|
||||||
self.assertEqual(self.pack([1, 1 << 16]), [1, 1])
|
self.assertEqual(ch.coeff_as_packed_mu([1]), [1])
|
||||||
self.assertEqual(self.pack([1, 1 << 32]), [1, 0])
|
self.assertEqual(ch.coeff_as_packed_mu([1, 1 << 16]), [1, 1])
|
||||||
self.assertEqual(self.pack([0x1234, 0xa5a5a5a5]),
|
self.assertEqual(ch.coeff_as_packed_mu([1, 1 << 32]), [1, 0])
|
||||||
|
self.assertEqual(ch.coeff_as_packed_mu([0x1234, 0xa5a5a5a5]),
|
||||||
[0xa5a51234, 0xa5a5])
|
[0xa5a51234, 0xa5a5])
|
||||||
self.assertEqual(self.pack([1, 2, 3, 4]),
|
self.assertEqual(ch.coeff_as_packed_mu([1, 2, 3, 4]),
|
||||||
[0x20001, 0x30000, 0, 4, 0])
|
[0x20001, 0x30000, 0, 4, 0])
|
||||||
self.assertEqual(self.pack([-1, -2, -3, -4]),
|
self.assertEqual(ch.coeff_as_packed_mu([-1, -2, -3, -4]),
|
||||||
[0xfffeffff, 0xfffdffff, 0xffffffff,
|
[0xfffeffff, 0xfffdffff, -1, -4, -1])
|
||||||
0xfffffffc, 0xffffffff])
|
self.assertEqual(ch.coeff_as_packed_mu([0, -1, 0, -1]),
|
||||||
self.assertEqual(self.pack([0, -1, 0, -1]),
|
[0xffff0000, 0x0000ffff, 0, -1, -1])
|
||||||
[0xffff0000, 0x0000ffff, 0,
|
|
||||||
0xffffffff, 0xffffffff])
|
|
||||||
|
|
||||||
def test_smooth_linear(self):
|
def test_smooth_linear(self):
|
||||||
ch = self.driver.offset
|
ch = self.driver.offset
|
||||||
|
@ -190,11 +175,13 @@ class SAWGTest(unittest.TestCase):
|
||||||
delay_mu(1)
|
delay_mu(1)
|
||||||
out = self.run_channel(self.rtio_manager.outputs)
|
out = self.run_channel(self.rtio_manager.outputs)
|
||||||
out = sum(out, [])
|
out = sum(out, [])
|
||||||
# import matplotlib.pyplot as plt
|
if False:
|
||||||
# plt.plot(out)
|
import matplotlib.pyplot as plt
|
||||||
# plt.show()
|
plt.plot(out)
|
||||||
|
plt.show()
|
||||||
|
|
||||||
@unittest.skip("needs sim.time.TimeManager tweak for timeline jumps")
|
# @unittest.skip("needs artiq.sim.time.TimeManager tweak for "
|
||||||
|
# "reverse timeline jumps")
|
||||||
def test_demo_2tone(self):
|
def test_demo_2tone(self):
|
||||||
MHz = 1e-3
|
MHz = 1e-3
|
||||||
ns = 1.
|
ns = 1.
|
||||||
|
@ -227,6 +214,7 @@ class SAWGTest(unittest.TestCase):
|
||||||
|
|
||||||
out = self.run_channel(self.rtio_manager.outputs)
|
out = self.run_channel(self.rtio_manager.outputs)
|
||||||
out = sum(out, [])
|
out = sum(out, [])
|
||||||
# import matplotlib.pyplot as plt
|
if True:
|
||||||
# plt.plot(out)
|
import matplotlib.pyplot as plt
|
||||||
# plt.show()
|
plt.plot(out)
|
||||||
|
plt.show()
|
||||||
|
|
Loading…
Reference in New Issue