forked from M-Labs/artiq
1
0
Fork 0

add set_window(), clean up api

This commit is contained in:
Robert Jördens 2022-09-06 15:42:05 +00:00
parent 27e3c044ed
commit c5c5c30617
1 changed files with 44 additions and 22 deletions

View File

@ -51,6 +51,9 @@ PHASER_ADDR_SERVO_DATA_BASE = 0x32
PHASER_ADDR_MIQRO_MEM_ADDR = 0x72 PHASER_ADDR_MIQRO_MEM_ADDR = 0x72
PHASER_ADDR_MIQRO_MEM_DATA = 0x74 PHASER_ADDR_MIQRO_MEM_DATA = 0x74
# Miqro profile memory select
PHASER_MIQRO_SEL_PROFILE = 1 << 14
PHASER_SEL_DAC = 1 << 0 PHASER_SEL_DAC = 1 << 0
PHASER_SEL_TRF0 = 1 << 1 PHASER_SEL_TRF0 = 1 << 1
PHASER_SEL_TRF1 = 1 << 2 PHASER_SEL_TRF1 = 1 << 2
@ -1405,8 +1408,7 @@ class Miqro:
for pro in range(32): for pro in range(32):
self.set_profile_mu(osc, pro, 0, 0, 0) self.set_profile_mu(osc, pro, 0, 0, 0)
delay(20*us) delay(20*us)
self.set_window_mu( self.set_window_mu(start=0, iq=[0], rate=1, shift=0, order=0, head=0, tail=1)
start=0, data=[[0, 0]], rate=1, shift=0, order=0, head=0, tail=1)
self.pulse(window=0, profiles=[0]) self.pulse(window=0, profiles=[0])
@kernel @kernel
@ -1416,8 +1418,8 @@ class Miqro:
if profile >= 32: if profile >= 32:
raise ValueError("invalid profile index") raise ValueError("invalid profile index")
self.channel.phaser.write16(PHASER_ADDR_MIQRO_MEM_ADDR, self.channel.phaser.write16(PHASER_ADDR_MIQRO_MEM_ADDR,
(self.channel.index << 15) | (1 << 14) | (oscillator << 6) | (self.channel.index << 15) | PHASER_MIQRO_SEL_PROFILE |
(profile << 1)) (oscillator << 6) | (profile << 1))
self.channel.phaser.write32(PHASER_ADDR_MIQRO_MEM_DATA, ftw) self.channel.phaser.write32(PHASER_ADDR_MIQRO_MEM_DATA, ftw)
self.channel.phaser.write32(PHASER_ADDR_MIQRO_MEM_DATA, self.channel.phaser.write32(PHASER_ADDR_MIQRO_MEM_DATA,
(asf & 0xffff) | (pow << 16)) (asf & 0xffff) | (pow << 16))
@ -1433,10 +1435,10 @@ class Miqro:
self.set_profile_mu(oscillator, profile, ftw, asf, pow) self.set_profile_mu(oscillator, profile, ftw, asf, pow)
@kernel @kernel
def set_window_mu(self, start, data, rate=1, shift=0, order=0, head=0, tail=0): def set_window_mu(self, start, iq, rate=1, shift=0, order=3, head=1, tail=1):
if start >= 1 << 10: if start >= 1 << 10:
raise ValueError("start out of bouncs") raise ValueError("start out of bouncs")
if len(data) >= 1 << 10: if len(iq) >= 1 << 10:
raise ValueError("window length out of bounds") raise ValueError("window length out of bounds")
if rate < 1 or rate > 1 << 12: if rate < 1 or rate > 1 << 12:
raise ValueError("rate out of bounds") raise ValueError("rate out of bounds")
@ -1447,18 +1449,35 @@ class Miqro:
self.channel.phaser.write16(PHASER_ADDR_MIQRO_MEM_ADDR, self.channel.phaser.write16(PHASER_ADDR_MIQRO_MEM_ADDR,
(self.channel.index << 15) | start) (self.channel.index << 15) | start)
self.channel.phaser.write32(PHASER_ADDR_MIQRO_MEM_DATA, self.channel.phaser.write32(PHASER_ADDR_MIQRO_MEM_DATA,
((start + 1 + len(data)) & 0x3ff) ((start + 1 + len(iq)) & 0x3ff) |
| ((rate - 1) << 10) ((rate - 1) << 10) |
| (shift << 22) (shift << 22) |
| (order << 28) (order << 28) |
| ((head & 1) << 30) ((head & 1) << 30) |
| ((tail & 1) << 31) ((tail & 1) << 31)
) )
for d in data: for iqi in iq:
self.channel.phaser.write32(PHASER_ADDR_MIQRO_MEM_DATA, self.channel.phaser.write32(PHASER_ADDR_MIQRO_MEM_DATA, iqi)
(d[0] & 0xffff) | (d[1] << 16)) delay(10*us) # slack for long windows
delay(10*us) return (start + 1 + len(iq)) & 0x3ff
return (start + 1 + len(data)) & 0x3ff
@kernel
def set_window(self, start, iq, period=4*ns, order=3, head=1, tail=1):
rate = int32(round(period/(4*ns)))
gain = 1.
for _ in range(order):
gain *= rate
shift = 0
while gain >= 2.:
shift += 1
gain *= .5
scale = ((1 << 15) - 1)/gain
iq_mu = [
(int32(round(iqi[0]*scale)) & 0xffff) |
(int32(round(iqi[1]*scale)) << 16)
for iqi in iq
]
self.set_window_mu(start, iq_mu, rate, shift, order, head, tail)
@kernel @kernel
def encode(self, window, profiles, data): def encode(self, window, profiles, data):
@ -1477,17 +1496,20 @@ class Miqro:
idx = 0 idx = 0
data[word] |= profile << idx data[word] |= profile << idx
idx += 5 idx += 5
return word return word + 1
@kernel @kernel
def pulse_mu(self, data): def pulse_mu(self, data):
for word in range(len(data) - 1, -1, -1): word = len(data)
rtio_output(self.base_addr + word, data[word]) delay_mu(-8*word) # back shift to align
while word > 0:
delay_mu(8) delay_mu(8)
word -= 1
# final write sets pulse stb
rtio_output(self.base_addr + word, data[word])
@kernel @kernel
def pulse(self, window, profiles): def pulse(self, window, profiles):
data = [0, 0, 0] data = [0, 0, 0]
words = self.encode(window, profiles, data) words = self.encode(window, profiles, data)
delay_mu(-8*words) self.pulse_mu(data[:words])
self.pulse_mu(data[:words + 1])