ad9910: fix RTIO fine timestamp nudging

Previously the TSC was truncated to an even coarse RTIO periods before doing
the setting SPI xfer. Afterwards the the IO update pulse would introduce
at least one but less than two RTIO cycles. Ultimately the RTIO TSC was
truncated again to even. If the SPI xfer takes an odd number of RTIO
periods, then a subsequent xfer would collide.

close #1229

Signed-off-by: Robert Jördens <rj@quartiq.de>
This commit is contained in:
Robert Jördens 2019-01-09 17:08:11 +00:00
parent 51239ebdb6
commit 41a816fd16
1 changed files with 10 additions and 8 deletions

View File

@ -285,8 +285,9 @@ class AD9910:
""" """
if phase_mode == _PHASE_MODE_DEFAULT: if phase_mode == _PHASE_MODE_DEFAULT:
phase_mode = self.phase_mode phase_mode = self.phase_mode
# Align to coarse RTIO which aligns SYNC_CLK # Align to coarse RTIO which aligns SYNC_CLK. I.e. clear fine TSC
at_mu(now_mu() & ~0xf) # This will not cause a collision or sequence error.
at_mu(now_mu() & ~7)
if phase_mode != PHASE_MODE_CONTINUOUS: if phase_mode != PHASE_MODE_CONTINUOUS:
# Auto-clear phase accumulator on IO_UPDATE. # Auto-clear phase accumulator on IO_UPDATE.
# This is active already for the next IO_UPDATE # This is active already for the next IO_UPDATE
@ -302,8 +303,8 @@ class AD9910:
pow += dt*ftw*self.sysclk_per_mu >> 16 pow += dt*ftw*self.sysclk_per_mu >> 16
self.write64(_AD9910_REG_PROFILE0 + profile, (asf << 16) | pow, ftw) self.write64(_AD9910_REG_PROFILE0 + profile, (asf << 16) | pow, ftw)
delay_mu(int64(self.io_update_delay)) delay_mu(int64(self.io_update_delay))
self.cpld.io_update.pulse_mu(8) # assumes 8 mu > t_SYSCLK self.cpld.io_update.pulse_mu(8) # assumes 8 mu > t_SYN_CCLK
at_mu(now_mu() & ~0xf) at_mu(now_mu() & ~7) # clear fine TSC again
if phase_mode != PHASE_MODE_CONTINUOUS: if phase_mode != PHASE_MODE_CONTINUOUS:
self.write32(_AD9910_REG_CFR1, 0x00000002) self.write32(_AD9910_REG_CFR1, 0x00000002)
# future IO_UPDATE will activate # future IO_UPDATE will activate
@ -496,16 +497,17 @@ class AD9910:
self.write32(_AD9910_REG_RAMP_RATE, 0x00010000) self.write32(_AD9910_REG_RAMP_RATE, 0x00010000)
# dFTW = 1, (work around negative slope) # dFTW = 1, (work around negative slope)
self.write64(_AD9910_REG_RAMP_STEP, -1, 0) self.write64(_AD9910_REG_RAMP_STEP, -1, 0)
# delay io_update after RTIO/2 edge # delay io_update after RTIO edge
t = now_mu() + 0x10 & ~0xf t = now_mu() + 8 & ~7
at_mu(t + delay_start) at_mu(t + delay_start)
self.cpld.io_update.pulse_mu(32 - delay_start) # realign # assumes a maximum t_SYNC_CLK period
self.cpld.io_update.pulse_mu(16 - delay_start) # realign
# disable DRG autoclear and LRR on io_update # disable DRG autoclear and LRR on io_update
self.write32(_AD9910_REG_CFR1, 0x00000002) self.write32(_AD9910_REG_CFR1, 0x00000002)
# stop DRG # stop DRG
self.write64(_AD9910_REG_RAMP_STEP, 0, 0) self.write64(_AD9910_REG_RAMP_STEP, 0, 0)
at_mu(t + 0x1000 + delay_stop) at_mu(t + 0x1000 + delay_stop)
self.cpld.io_update.pulse_mu(32 - delay_stop) # realign self.cpld.io_update.pulse_mu(16 - delay_stop) # realign
ftw = self.read32(_AD9910_REG_FTW) # read out effective FTW ftw = self.read32(_AD9910_REG_FTW) # read out effective FTW
delay(100*us) # slack delay(100*us) # slack
# disable DRG # disable DRG