1 ; **********************************************************************************
2 ; SDK Version: PowerSmartâ„¢ Digital Control Library Designer v0.9.14.676
3 ; CGS Version: Code Generator Script v3.0.8 (03/12/2021)
5 ; Date/Time: 04/02/2021 00:19:31
6 ; **********************************************************************************
7 ; 4P4Z Control Library File (Dual Bitshift-Scaling Mode)
8 ; **********************************************************************************
10 ;------------------------------------------------------------------------------
12 .nolist ; (no external dependencies)
13 .list ; list of all external dependencies
15 ;------------------------------------------------------------------------------
17 .section .data ; place constant data in the data section
19 ;------------------------------------------------------------------------------
20 ;include NPNZ16b_s data structure and global constants.
21 .include "./sources/power_control/drivers/npnz16b.inc" ; include NPNZ16b_s object data structure value offsets and status flag labels
23 ;------------------------------------------------------------------------------
25 .section .text ; place code in the text section
27 ;------------------------------------------------------------------------------
28 ; Global function declaration
29 ; This function calls the z-domain controller processing the latest data point input
30 ;------------------------------------------------------------------------------
32 .global _v_loop_Update ; provide global scope to routine
33 _v_loop_Update: ; local function label
35 ;------------------------------------------------------------------------------
36 ; Check status word for Enable/Disable flag and bypass computation, if disabled
37 btss [w0], #NPNZ16_STATUS_ENABLED ; check ENABLED bit state, skip (do not execute) next instruction if set
38 bra V_LOOP_LOOP_BYPASS ; if ENABLED bit is cleared, jump to end of control code
40 ;------------------------------------------------------------------------------
41 ; Setup pointers to A-Term data arrays
42 mov [w0 + #ptrACoefficients], w8 ; load pointer to first index of A coefficients array
44 ;------------------------------------------------------------------------------
45 ; Load pointer to first element of control history array
46 mov [w0 + #ptrControlHistory], w10 ; load pointer address into working register
48 ;------------------------------------------------------------------------------
49 ; Compute compensation filter term
50 clr a, [w8]+=4, w4, [w10]+=2, w6 ; clear accumulator A and prefetch first operands
51 mac w4*w6, a, [w8]+=4, w4, [w10]+=2, w6 ; multiply control output (n-1) from the delay line with coefficient A1
52 mac w4*w6, a, [w8]+=4, w4, [w10]+=2, w6 ; multiply control output (n-2) from the delay line with coefficient A2
53 mac w4*w6, a, [w8]+=4, w4, [w10]+=2, w6 ; multiply control output (n-3) from the delay line with coefficient A3
54 mac w4*w6, a ; multiply & accumulate last control output with coefficient of the delay line (no more prefetch)
56 ;------------------------------------------------------------------------------
57 ; Backward normalization of recent result
58 mov [w0 + #normPostShiftA], w6 ; load A-coefficients post bit-shift scaler value into working register
59 sftac a, w6 ; shift accumulator A by number of bits loaded in working register
61 ;------------------------------------------------------------------------------
62 ; Update error history (move error one tick down the delay line)
63 mov [w10 + #6], w6 ; move entry (n-4) into buffer
64 mov w6, [w10 + #8] ; move buffered value one tick down the delay line
65 mov [w10 + #4], w6 ; move entry (n-3) into buffer
66 mov w6, [w10 + #6] ; move buffered value one tick down the delay line
67 mov [w10 + #2], w6 ; move entry (n-2) into buffer
68 mov w6, [w10 + #4] ; move buffered value one tick down the delay line
69 mov [w10 + #0], w6 ; move entry (n-1) into buffer
70 mov w6, [w10 + #2] ; move buffered value one tick down the delay line
72 ;------------------------------------------------------------------------------
73 ; Read data from input source
74 mov [w0 + #ptrSourceRegister], w2 ; load pointer to input source register
75 mov [w2], w1 ; move value from input source into working register
76 mov [w0 + #ptrDProvControlInputComp], w2 ; load pointer address of target buffer of most recent, compensated controller input from data structure
77 mov w1, [w2] ; copy most recent controller input value to given data buffer target
79 ;------------------------------------------------------------------------------
80 ; Load reference and calculate error input to transfer function
81 mov [w0 + #ptrControlReference], w2 ; move pointer to control reference into working register
82 subr w1, [w2], w1 ; calculate error (=reference - input)
83 mov [w0 + #normPreShift], w2 ; move error input scaler into working register
84 sl w1, w2, w1 ; normalize error result to fractional number format
86 ;------------------------------------------------------------------------------
87 ; Setup pointers to B-Term data arrays
88 mov [w0 + #ptrBCoefficients], w8 ; load pointer to first index of B coefficients array
89 mov w1, [w10] ; add most recent error input to history array
91 ;------------------------------------------------------------------------------
92 ; Compute B-Term of the compensation filter
93 clr b, [w8]+=4, w4, [w10]+=2, w6 ; clear accumulator B and prefetch first operands
94 mac w4*w6, b, [w8]+=4, w4, [w10]+=2, w6 ; multiply & accumulate error input (n-0) from the delay line with coefficient B0 and prefetch next operands
95 mac w4*w6, b, [w8]+=4, w4, [w10]+=2, w6 ; multiply & accumulate error input (n-1) from the delay line with coefficient B1 and prefetch next operands
96 mac w4*w6, b, [w8]+=4, w4, [w10]+=2, w6 ; multiply & accumulate error input (n-2) from the delay line with coefficient B2 and prefetch next operands
97 mac w4*w6, b, [w8]+=4, w4, [w10]+=2, w6 ; multiply & accumulate error input (n-3) from the delay line with coefficient B3 and prefetch next operands
98 mac w4*w6, b ; multiply & accumulate last error input with coefficient of the delay line (no more prefetch)
100 ;------------------------------------------------------------------------------
101 ; Backward normalization of recent result
102 mov [w0 + #normPostShiftB], w6 ; load B-coefficients post bit-shift scaler value into working register
103 sftac b, w6 ; shift accumulator B by number of bits loaded in working register
105 ;------------------------------------------------------------------------------
106 ; Adaptive Loop Gain Modulation
107 mov #ACCBH, w2 ; capture address of accumulator B high word and store it in working register
108 fbcl [w2], w3 ; find first bit change from left in accumulator B and store position in working register
109 sftac b, w3 ; shift accumulator by 'n' bits to scale contents into ACCH window
110 sac.r b, w6 ; store result of accumulator B in working register
111 mov [w0 + ptrAgcObserverFunction], w1 ; load function pointer to observer function
112 call w1 ; call extern observer function to update gain modulation factor
113 mov [w0 + #AgcFactor], w4 ; load AGC modulation factor into working register
114 mov [w0 + #AgcScaler], w2 ; load AGC modulation factor scaler into working register
115 mpy w4*w6, b ; multiply accumulator B result with AGC modulation factor
116 neg w3, w3 ; negate previously stored accumulator shift value
117 add w3, w2, w2 ; add post scaler bit-shift scaler and accumulator scaler
118 sftac b, w2 ; shift result by AGC scaler with accumulator scaling
120 ;------------------------------------------------------------------------------
121 ; Add accumulators finalizing LDE computation
122 add a ; add accumulator b to accumulator a
123 sac.r a, w4 ; store most recent accumulator result in working register
125 ;------------------------------------------------------------------------------
126 ; Controller Anti-Windup (control output value clamping)
128 ; Check for lower limit violation
129 mov [w0 + #MinOutput], w6 ; load lower limit value
130 cpsgt w4, w6 ; compare values and skip next instruction if control output is within operating range (control output > lower limit)
131 mov w6, w4 ; override most recent controller output
132 V_LOOP_CLAMP_MIN_EXIT:
134 ; Check for upper limit violation
135 mov [w0 + #MaxOutput], w6 ; load upper limit value
136 cpslt w4, w6 ; compare values and skip next instruction if control output is within operating range (control output < upper limit)
137 mov w6, w4 ; override most recent controller output
138 V_LOOP_CLAMP_MAX_EXIT:
140 ;------------------------------------------------------------------------------
141 ; Write control output value to target
142 mov [w0 + #ptrTargetRegister], w8 ; capture pointer to target in working register
143 mov w4, [w8] ; move control output to target address
144 mov [w0 + #ptrDProvControlOutput], w2 ; load pointer address of target buffer of most recent controller output value from data structure
145 mov w4, [w2] ; copy most recent controller output value to given data buffer target
147 ;------------------------------------------------------------------------------
148 ; Update ADC trigger locations
149 asr w4, #1, w6 ; half control output by shifting value one bit to the right
150 ; Update ADC trigger B position
151 mov [w0 + #ADCTriggerBOffset], w8 ; load user-defined ADC trigger B offset value into working register
152 add w6, w8, w10 ; add user-defined ADC trigger B offset to half of control output
153 mov [w0 + #ptrADCTriggerBRegister], w8 ; load pointer to ADC trigger B register into working register
154 mov w10, [w8] ; push new ADC trigger value to ADC trigger B register
155 ; Update ADC trigger A position
156 mov [w0 + #ADCTriggerAOffset], w8 ; load user-defined ADC trigger A offset value into working register
157 add w6, w8, w10 ; add user-defined ADC trigger A offset to half of control output
158 mov [w0 + #ptrADCTriggerARegister], w8 ; load pointer to ADC trigger A register into working register
159 mov w10, [w8] ; push new ADC trigger value to ADC trigger A register
161 ;------------------------------------------------------------------------------
162 ; Load pointer to first element of control history array
163 mov [w0 + #ptrControlHistory], w10 ; load pointer address into working register
165 ;------------------------------------------------------------------------------
166 ; Update control output history (move entries one tick down the delay line)
167 mov [w10 + #4], w6 ; move entry (n-3) one tick down the delay line
169 mov [w10 + #2], w6 ; move entry (n-2) one tick down the delay line
171 mov [w10 + #0], w6 ; move entry (n-1) one tick down the delay line
173 mov w4, [w10] ; add most recent control output to history
175 ;------------------------------------------------------------------------------
176 ; Enable/Disable bypass branch target with dummy read of source buffer
177 goto V_LOOP_LOOP_EXIT ; when enabled, step over dummy read and go straight to EXIT
178 V_LOOP_LOOP_BYPASS: ; Enable/Disable bypass branch target to perform dummy read of source to clear the source buffer
179 mov [w0 + #ptrSourceRegister], w2 ; load pointer to input source register
180 mov [w2], w1 ; move value from input source into working register
181 mov [w0 + #ptrDProvControlInputComp], w2 ; load pointer address of target buffer of most recent, compensated controller input from data structure
182 mov w1, [w2] ; copy most recent controller input value to given data buffer target
183 mov [w0 + #ptrDProvControlOutput], w2 ; load pointer address of target buffer of most recent controller output value from data structure
184 clr [w2] ; copy most recent controller output value to given data buffer target
185 V_LOOP_LOOP_EXIT: ; Exit control loop branch target
187 ;------------------------------------------------------------------------------
189 return ; end of function; return to caller
191 ;------------------------------------------------------------------------------
194 ;------------------------------------------------------------------------------
195 ; Global function declaration v_loop_Reset
196 ; This function clears control and error histories enforcing a reset
197 ;------------------------------------------------------------------------------
199 .global _v_loop_Reset ; provide global scope to routine
200 _v_loop_Reset: ; local function label
202 ;------------------------------------------------------------------------------
203 ; Clear control history array
204 push w0 ; save contents of working register WREG0
205 mov [w0 + #ptrControlHistory], w0 ; set pointer to the base address of control history array
206 clr [w0++] ; clear next address of control history array
207 clr [w0++] ; clear next address of control history array
208 clr [w0++] ; clear next address of control history array
209 clr [w0] ; clear last address of control history array
210 pop w0 ; restore contents of working register WREG0
212 ;------------------------------------------------------------------------------
213 ; Clear error history array
214 push w0 ; save contents of working register WREG0
215 mov [w0 + #ptrErrorHistory], w0 ; set pointer to the base address of error history array
216 clr [w0++] ; Clear next address of error history array
217 clr [w0++] ; Clear next address of error history array
218 clr [w0++] ; Clear next address of error history array
219 clr [w0++] ; Clear next address of error history array
220 clr [w0] ; clear last address of error history array
221 pop w0 ; restore contents of working register WREG0
223 ;------------------------------------------------------------------------------
225 return ; end of function; return to caller
227 ;------------------------------------------------------------------------------
230 ;------------------------------------------------------------------------------
231 ; Global function declaration v_loop_Precharge
232 ; This function loads user-defined default values into control and error histories
233 ;------------------------------------------------------------------------------
235 .global _v_loop_Precharge ; provide global scope to routine
236 _v_loop_Precharge: ; local function label
238 ;------------------------------------------------------------------------------
239 ; Charge error history array with defined value
240 push w0 ; save contents of working register WREG0
241 push w1 ; save contents of working register WREG1
242 mov [w0 + #ptrErrorHistory], w0 ; set pointer to the base address of error history array
243 mov w1, [w0++] ; Load user value into next address of error history array
244 mov w1, [w0++] ; Load user value into next address of error history array
245 mov w1, [w0++] ; Load user value into next address of error history array
246 mov w1, [w0++] ; Load user value into next address of error history array
247 mov w1, [w0] ; load user value into last address of error history array
248 pop w1 ; restore contents of working register WREG1
249 pop w0 ; restore contents of working register WREG0
251 ;------------------------------------------------------------------------------
252 ; Charge control history array with defined value
253 push w0 ; save contents of working register WREG0
254 push w2 ; save contents of working register WREG2
255 mov [w0 + #ptrControlHistory], w0 ; set pointer to the base address of control history array
256 mov w2, [w0++] ; Load user value into next address of control history array
257 mov w2, [w0++] ; Load user value into next address of control history array
258 mov w2, [w0++] ; Load user value into next address of control history array
259 mov w2, [w0] ; Load user value into last address of control history array
260 pop w2 ; restore contents of working register WREG2
261 pop w0 ; restore contents of working register WREG0
263 ;------------------------------------------------------------------------------
265 return ; end of function; return to caller
267 ;------------------------------------------------------------------------------
270 ;------------------------------------------------------------------------------
271 ; Global function declaration v_loop_PTermUpdate
272 ; This function executes a P-Term based control loop used for plant measurements only.
273 ; THIS LOOP IS NOT SUITED FOR STABLE OPERATION
274 ;------------------------------------------------------------------------------
276 .global _v_loop_PTermUpdate ; provide global scope to routine
277 _v_loop_PTermUpdate: ; local function label
279 ;------------------------------------------------------------------------------
280 ; Check status word for Enable/Disable flag and bypass computation when disabled
281 btss [w0], #NPNZ16_STATUS_ENABLED ; check ENABLED bit state, skip (do not execute) next instruction if set
282 bra V_LOOP_PTERM_LOOP_BYPASS ; if ENABLED bit is cleared, jump to end of control code
284 ;------------------------------------------------------------------------------
285 ; Read data from input source
286 mov [w0 + #ptrSourceRegister], w2 ; load pointer to input source register
287 mov [w2], w1 ; move value from input source into working register
288 mov [w0 + #ptrDProvControlInputComp], w2 ; load pointer address of target buffer of most recent, compensated controller input from data structure
289 mov w1, [w2] ; copy most recent controller input value to given data buffer target
291 ;------------------------------------------------------------------------------
292 ; Load reference and calculate error input to transfer function
293 mov [w0 + #ptrControlReference], w2 ; move pointer to control reference into working register
294 subr w1, [w2], w1 ; calculate error (=reference - input)
295 mov [w0 + #normPreShift], w2 ; move error input scaler into working register
296 sl w1, w2, w1 ; normalize error result to fractional number format
298 ;------------------------------------------------------------------------------
299 ; Load P-gain factor from data structure
300 mov [w0 + #PTermFactor], w6 ; move P-coefficient fractional into working register
301 mov [w0 + #PTermScaler], w2 ; move P-coefficient scaler into working register
302 mov w1, w4 ; move error to MPY working register
303 ; calculate P-control result
304 mpy w4*w6, a ; multiply most recent error with P-coefficient
305 sftac a, w2 ; shift accumulator to post-scale floating number
306 sac.r a, w4 ; store accumulator result to working register
308 ;------------------------------------------------------------------------------
309 ; Controller Anti-Windup (control output value clamping)
311 ; Check for lower limit violation
312 mov [w0 + #MinOutput], w6 ; load lower limit value
313 cpsgt w4, w6 ; compare values and skip next instruction if control output is within operating range (control output > lower limit)
314 mov w6, w4 ; override most recent controller output
315 V_LOOP_PTERM_CLAMP_MIN_EXIT:
317 ; Check for upper limit violation
318 mov [w0 + #MaxOutput], w6 ; load upper limit value
319 cpslt w4, w6 ; compare values and skip next instruction if control output is within operating range (control output < upper limit)
320 mov w6, w4 ; override most recent controller output
321 V_LOOP_PTERM_CLAMP_MAX_EXIT:
323 ;------------------------------------------------------------------------------
324 ; Write control output value to target
325 mov [w0 + #ptrTargetRegister], w8 ; capture pointer to target in working register
326 mov w4, [w8] ; move control output to target address
327 mov [w0 + #ptrDProvControlOutput], w2 ; load pointer address of target buffer of most recent controller output value from data structure
328 mov w4, [w2] ; copy most recent controller output value to given data buffer target
330 ;------------------------------------------------------------------------------
331 ; Update ADC trigger locations
332 asr w4, #1, w6 ; half control output by shifting value one bit to the right
333 ; Update ADC trigger B position
334 mov [w0 + #ADCTriggerBOffset], w8 ; load user-defined ADC trigger B offset value into working register
335 add w6, w8, w10 ; add user-defined ADC trigger B offset to half of control output
336 mov [w0 + #ptrADCTriggerBRegister], w8 ; load pointer to ADC trigger B register into working register
337 mov w10, [w8] ; push new ADC trigger value to ADC trigger B register
338 ; Update ADC trigger A position
339 mov [w0 + #ADCTriggerAOffset], w8 ; load user-defined ADC trigger A offset value into working register
340 add w6, w8, w10 ; add user-defined ADC trigger A offset to half of control output
341 mov [w0 + #ptrADCTriggerARegister], w8 ; load pointer to ADC trigger A register into working register
342 mov w10, [w8] ; push new ADC trigger value to ADC trigger A register
344 ;------------------------------------------------------------------------------
345 ; Enable/Disable bypass branch target with dummy read of source buffer
346 goto V_LOOP_PTERM_LOOP_EXIT ; when enabled, step over dummy read and go straight to EXIT
347 V_LOOP_PTERM_LOOP_BYPASS: ; Enable/Disable bypass branch target to perform dummy read of source to clear the source buffer
348 mov [w0 + #ptrSourceRegister], w2 ; load pointer to input source register
349 mov [w2], w1 ; move value from input source into working register
350 mov [w0 + #ptrDProvControlInputComp], w2 ; load pointer address of target buffer of most recent, compensated controller input from data structure
351 mov w1, [w2] ; copy most recent controller input value to given data buffer target
352 mov [w0 + #ptrDProvControlOutput], w2 ; load pointer address of target buffer of most recent controller output value from data structure
353 clr [w2] ; copy most recent controller output value to given data buffer target
354 V_LOOP_PTERM_LOOP_EXIT: ; Exit P-Term control loop branch target
356 ;------------------------------------------------------------------------------
358 return ; end of function; return to caller
360 ;------------------------------------------------------------------------------
363 ;------------------------------------------------------------------------------
365 .end ; end of file v_loop_asm.s
367 ;------------------------------------------------------------------------------
370 ; **********************************************************************************
371 ; Download latest version of this tool here: https://areiter128.github.io/DCLD
372 ; **********************************************************************************