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