qcm_seq1.q1asm#

qcm_seq1.q1asm#
  1    .DEF  T_TOTAL         {T_TOTAL}
  2    .DEF  START_ALIGN     {START_ALIGN}
  3
  4    .DEF  IQ_ID           {IQ_ID}
  5    .DEF  DELAY_ID        {DELAY_ID}
  6    .DEF  GAIN_ID         {GAIN_ID}
  7
  8    .DEF  WAIT_FOR_IQ     {WAIT_FOR_IQ}
  9    .DEF  FB_SEND_WAIT    {FB_SEND_WAIT}     # ns, RT wait after fb_com_data
 10    .DEF  MEAS_DELTA      {MEAS_DELTA}  # ns, separation between the two sample points
 11    .DEF  WAIT_CALC       1000
 12
 13    .DEF  SIGN_BIT            0x80000000    # detect negative values
 14
 15    # Tracking parameter limits
 16    .DEF  INIT_MEAS_DELAY     {INIT_MEAS_DELAY}
 17    .DEF  INIT_STEP           16
 18    .DEF  MIN_STEP            4
 19    .DEF  MIN_DELAY           200
 20    .DEF  MAX_DELAY           {MAX_DELAY}
 21
 22    # Cursor gain shaping (tune for visibility)
 23    .DEF  CURSOR_GAIN_BASE    2000       # keeps cursor visible even for small I
 24    .DEF  CURSOR_GAIN_SHIFT   0          # additional right shift applied on QCM before sending gain
 25    .DEF  MAX_GAIN            32767
 26
 27    # Register naming
 28    .DEF  ZERO                R0
 29    .DEF  I1                  R1
 30    .DEF  Q1                  R2         # dummy
 31    .DEF  I2                  R3
 32    .DEF  Q2                  R4         # dummy
 33
 34    .DEF  D                   R5         # derivative estimate (non-negative)
 35    .DEF  D_PREV              R6
 36    .DEF  DELTA_D             R7         # D - D_PREV (unsigned)
 37    .DEF  MEAS_DELAY          R8
 38    .DEF  STEP                R9
 39    .DEF  DIR                 R10        # 0 = forward (+STEP), 1 = backward (-STEP)
 40    .DEF  CURSOR_GAIN         R11
 41    .DEF  TMP                 R12
 42    .DEF  POST_WAIT           R13
 43
 44    # --- init ---
 45    wait_sync 4
 46
 47    move  0,  $ZERO                       # ZERO = 0
 48    move  $INIT_MEAS_DELAY, $MEAS_DELAY   # MEAS_DELAY = INIT_MEAS_DELAY
 49    move  $INIT_STEP,       $STEP         # STEP = INIT_STEP
 50    move  0,                $D_PREV       # D_PREV = 0
 51    move  0,                $DIR          # DIR = 0
 52
 53    ## POST_WAIT = T_TOTAL - WAIT_FOR_IQ - MEAS_DELTA - WAIT_CALC - 2 * FB_SEND_WAIT
 54    move  $T_TOTAL, $POST_WAIT
 55    nop
 56    sub   $POST_WAIT, $WAIT_FOR_IQ, $POST_WAIT
 57    nop
 58    sub   $POST_WAIT, $MEAS_DELTA,  $POST_WAIT
 59    nop
 60    sub   $POST_WAIT, $WAIT_CALC, $POST_WAIT
 61    nop
 62    sub   $POST_WAIT, $FB_SEND_WAIT,  $POST_WAIT
 63    nop
 64    sub   $POST_WAIT, $FB_SEND_WAIT,  $POST_WAIT
 65
 66    wait  $START_ALIGN
 67
 68    brain_loop:
 69        wait_trigger    1, 8 # marker M1, timeout 8 ns (minimum is 8 ns)
 70        ## QRM acquisition + IQ arrives + Q1 core pop & compute + fb_com_data
 71        wait $WAIT_FOR_IQ
 72
 73        ## -------------------------------------------------------------------------
 74        ## Receive Acquisition (I1, Q1, I2, Q2)
 75        ## -------------------------------------------------------------------------
 76        fb_pop_data  $IQ_ID, $I1
 77        fb_pop_data  $IQ_ID, $Q1  # dummy
 78        
 79        wait $MEAS_DELTA
 80        
 81        fb_pop_data  $IQ_ID, $I2
 82        fb_pop_data  $IQ_ID, $Q2  # dummy
 83
 84        # if I1 negative: set it to 0.
 85        nop
 86        jge   $I1, $SIGN_BIT, @i1_neg
 87        nop
 88        jmp   @i1_ok
 89    i1_neg:
 90        move  0, $I1 # not interested in negative slope
 91    i1_ok:
 92        jge $I2, $SIGN_BIT, @i2_neg
 93        jmp @i2_ok
 94    i2_neg:
 95        move  0, $I2 # not interested in negative slope
 96    i2_ok:
 97
 98        # -------------------------------------------------------------------------
 99        # Compute finite-difference derivative d = max(I2 - I1, 0)
100        # negative result = a huge number
101        # -------------------------------------------------------------------------
102        sub   $I2, $I1, $D # D = I2-I1 = derivative
103        nop
104        jge   $D, $SIGN_BIT, @d_neg
105        jmp   @d_ok
106    d_neg:
107        move  0, $D
108        move  1, $DIR
109    d_ok:
110
111        # -------------------------------------------------------------------------
112        # Compare d to d_prev (delta_d = d - d_prev)
113        # If underflow => d < d_prev => got worse.
114        # -------------------------------------------------------------------------
115        sub   $D, $D_PREV, $DELTA_D # DELTA_D = D-D_PREV
116        nop
117        jge   $DELTA_D, $SIGN_BIT, @got_worse # if DELTA_D >= SIGN_BIT, goto d_got_worse
118        jmp   @after_compare
119
120    got_worse:
121        # Flip direction (0<->1) so we step the other way next shot
122        xor   $DIR, 1, $DIR # DIR = DIR xor 1
123
124        # Reduce step (STEP = STEP/2), clamp to MIN_STEP
125        asr   $STEP, 1, $STEP # STEP = STEP/2; maybe reducing too much?
126        nop
127        jlt   $STEP, $MIN_STEP, @step_min # if STEP < MIN_STEP, goto step_to_min
128        jmp   @after_step
129    step_min:
130        move  $MIN_STEP, $STEP # STEP = MIN_STEP
131    after_step:
132
133    after_compare:
134        # -------------------------------------------------------------------------
135        # Update MEAS_DELAY for next shot based on DIR
136        # DIR=0 => MEAS_DELAY += STEP
137        # DIR=1 => MEAS_DELAY -= STEP  (with underflow protection)
138        # -------------------------------------------------------------------------
139        jlt   $DIR, 1, @dir_forward # if DIR < 1, goto dir_forward
140
141        # dir_backward:
142        sub   $MEAS_DELAY, $STEP, $TMP # TMP = MEAS_DELAY - STEP
143        nop
144        jge   $TMP, $SIGN_BIT, @delay_under # if TMP >= SIGN_BIT, goto delay_underflow
145
146        move  $TMP, $MEAS_DELAY # MEAS_DELAY = TMP
147        jmp   @after_dir
148    delay_under:
149        move  $MIN_DELAY, $MEAS_DELAY # MEAS_DELAY = MIN_DELAY
150        jmp   @after_dir
151
152    dir_forward:
153        add   $MEAS_DELAY, $STEP, $MEAS_DELAY # MEAS_DELAY = MEAS_DELAY + STEP
154        nop
155    after_dir:
156        # Clamp MEAS_DELAY into [MIN_DELAY, MAX_DELAY]
157        jlt   $MEAS_DELAY, $MIN_DELAY, @clamp_min # if MEAS_DELAY < MIN_DELAY, goto clamp_delay_min
158        jmp   @check_max
159    clamp_min:
160        move  $MIN_DELAY, $MEAS_DELAY # MEAS_DELAY = MIN_DELAY
161        nop
162    check_max:
163        jge   $MEAS_DELAY, $MAX_DELAY, @clamp_max # if MEAS_DELAY >= MAX_DELAY, goto clamp_delay_max
164        jmp   @after_clamp
165    clamp_max:
166        move  $MAX_DELAY, $MEAS_DELAY # MEAS_DELAY = MAX_DELAY
167    after_clamp:
168        # Update stored previous derivative for next iteration
169        move  $D, $D_PREV # D_PREV = D
170
171        # -------------------------------------------------------------------------
172        # CURSOR_GAIN = (I1 >> CURSOR_GAIN_SHIFT) + CURSOR_GAIN_BASE
173        # Clamp to MAX_GAIN.
174        # -------------------------------------------------------------------------
175        move  $I1, $CURSOR_GAIN # CURSOR_GAIN = I1
176        nop
177        asr   $CURSOR_GAIN, $CURSOR_GAIN_SHIFT, $CURSOR_GAIN
178        nop
179        add   $CURSOR_GAIN, $CURSOR_GAIN_BASE,  $CURSOR_GAIN
180        nop
181        jge   $CURSOR_GAIN, $MAX_GAIN, @clamp_gain
182        jmp   @gain_ok
183    clamp_gain:
184        move  $MAX_GAIN, $CURSOR_GAIN
185    gain_ok:
186        fb_com_data  $DELAY_ID, $MEAS_DELAY,  $FB_SEND_WAIT # send: set id, set value, wait
187        fb_com_data  $GAIN_ID,  $CURSOR_GAIN, $FB_SEND_WAIT # send: set id, set value, wait
188
189        wait $POST_WAIT
190
191        jmp  @brain_loop