1 ; **********************************************************************************
 
    2 ;  SDK Version: PowerSmartâ„¢ Digital Control Library Designer v0.9.12.672
 
    3 ;  CGS Version: Code Generator Script v3.0.7 (03/07/2021)
 
    5 ;  Date/Time:   03/08/2021 12:42:58
 
    6 ; **********************************************************************************
 
    7 ;  4P4Z Control Library File (Fast Floating Point Coefficient 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 pointer to first element of error history array
 
   42     mov [w0 + #ptrErrorHistory], w10        ; load pointer address into working register
 
   44 ;------------------------------------------------------------------------------
 
   45 ; Update error history (move error one tick down the delay line)
 
   46     mov [w10 + #6], w6                      ; move entry (n-4) into buffer
 
   47     mov w6, [w10 + #8]                      ; move buffered value one tick down the delay line
 
   48     mov [w10 + #4], w6                      ; move entry (n-3) into buffer
 
   49     mov w6, [w10 + #6]                      ; move buffered value one tick down the delay line
 
   50     mov [w10 + #2], w6                      ; move entry (n-2) into buffer
 
   51     mov w6, [w10 + #4]                      ; move buffered value one tick down the delay line
 
   52     mov [w10 + #0], w6                      ; move entry (n-1) into buffer
 
   53     mov w6, [w10 + #2]                      ; move buffered value one tick down the delay line
 
   55 ;------------------------------------------------------------------------------
 
   56 ; Read data from input source
 
   57     mov [w0 + #ptrSourceRegister], w2       ; load pointer to input source register
 
   58     mov [w2], w1                            ; move value from input source into working register
 
   59     mov [w0 + #ptrDProvControlInputComp], w2 ; load pointer address of target buffer of most recent, compensated controller input from data structure
 
   60     mov w1, [w2]                            ; copy most recent controller input value to given data buffer target
 
   62 ;------------------------------------------------------------------------------
 
   63 ; Load reference and calculate error input to transfer function
 
   64     mov [w0 + #ptrControlReference], w2     ; move pointer to control reference into working register
 
   65     subr w1, [w2], w1                       ; calculate error (=reference - input)
 
   66     mov [w0 + #normPreShift], w2            ; move error input scaler into working register
 
   67     sl w1, w2, w1                           ; normalize error result to fractional number format
 
   69 ;------------------------------------------------------------------------------
 
   70 ; Setup pointers to B-Term data arrays
 
   71     mov [w0 + #ptrBCoefficients], w8        ; load pointer to first index of B coefficients array
 
   72     mov w1, [w10]                           ; add most recent error input to history array
 
   74 ;------------------------------------------------------------------------------
 
   75 ; Compute compensation filter B-term
 
   76     clr b, [w8]+=2, w5                      ; clear accumulator B and prefetch first error operand
 
   77     clr a, [w8]+=4, w4, [w10]+=2, w6        ; clear accumulator A and prefetch first coefficient operand including number scaler
 
   78     mpy w4*w6, a, [w8]+=4, w4, [w10]+=2, w6 ; multiply first control output of the delay line with first coefficient
 
   79     sftac a, w5                             ; shift accumulator to post-scale floating number
 
   80     add b                                   ; add accumulator a to accumulator b
 
   81     mov [w8 - #6], w5                       ; load scaler into working register
 
   82     mpy w4*w6, a, [w8]+=4, w4, [w10]+=2, w6 ; multiply control output (n-1) from the delay line with coefficient B1
 
   83     sftac a, w5                             ; shift accumulator to post-scale floating number
 
   84     add b                                   ; add accumulator a to accumulator b
 
   85     mov [w8 - #6], w5                       ; load scaler into working register
 
   86     mpy w4*w6, a, [w8]+=4, w4, [w10]+=2, w6 ; multiply control output (n-2) from the delay line with coefficient B2
 
   87     sftac a, w5                             ; shift accumulator to post-scale floating number
 
   88     add b                                   ; add accumulator a to accumulator b
 
   89     mov [w8 - #6], w5                       ; load scaler into working register
 
   90     mpy w4*w6, a, [w8]+=4, w4, [w10]+=2, w6 ; multiply control output (n-3) from the delay line with coefficient B3
 
   91     sftac a, w5                             ; shift accumulator to post-scale floating number
 
   92     add b                                   ; add accumulator a to accumulator b
 
   93     mov [w8 - #6], w5                       ; load scaler into working register
 
   94     mpy w4*w6, a                            ; multiply & accumulate last control output with coefficient of the delay line (no more prefetch)
 
   95     sftac a, w5                             ; shift accumulator to post-scale floating number
 
   96     add b                                   ; add accumulator a to accumulator b
 
   98 ;------------------------------------------------------------------------------
 
   99 ; Setup pointers to A-Term data arrays
 
  100     mov [w0 + #ptrACoefficients], w8        ; load pointer to first index of A coefficients array
 
  102 ;------------------------------------------------------------------------------
 
  103 ; Load pointer to first element of control history array
 
  104     mov [w0 + #ptrControlHistory], w10      ; load pointer address into working register
 
  106 ;------------------------------------------------------------------------------
 
  107 ; Compute compensation filter A-term
 
  108     movsac b, [w8]+=2, w5                   ; leave contents of accumulator B unchanged
 
  109     clr a, [w8]+=4, w4, [w10]+=2, w6        ; clear accumulator A and prefetch first coefficient operand including number scaler
 
  110     mpy w4*w6, a, [w8]+=4, w4, [w10]+=2, w6 ; multiply first control output of the delay line with first coefficient
 
  111     sftac a, w5                             ; shift accumulator to post-scale floating number
 
  112     add b                                   ; add accumulator a to accumulator b
 
  113     mov [w8 - #6], w5                       ; load scaler into working register
 
  114     mpy w4*w6, a, [w8]+=4, w4, [w10]+=2, w6 ; multiply control output (n-2) from the delay line with coefficient A2
 
  115     sftac a, w5                             ; shift accumulator to post-scale floating number
 
  116     add b                                   ; add accumulator a to accumulator b
 
  117     mov [w8 - #6], w5                       ; load scaler into working register
 
  118     mpy w4*w6, a, [w8]+=4, w4, [w10]+=2, w6 ; multiply control output (n-3) from the delay line with coefficient A3
 
  119     sftac a, w5                             ; shift accumulator to post-scale floating number
 
  120     add b                                   ; add accumulator a to accumulator b
 
  121     mov [w8 - #6], w5                       ; load scaler into working register
 
  122     mpy w4*w6, a                            ; multiply & accumulate last control output with coefficient of the delay line (no more prefetch)
 
  123     sftac a, w5                             ; shift accumulator to post-scale floating number
 
  124     add b                                   ; add accumulator a to accumulator b
 
  125     sac.r b, w4                             ; store most recent accumulator result in working register
 
  127 ;------------------------------------------------------------------------------
 
  128 ; Controller Anti-Windup (control output value clamping)
 
  130 ; Check for lower limit violation
 
  131     mov [w0 + #MinOutput], w6               ; load lower limit value
 
  132     cpsgt w4, w6                            ; compare values and skip next instruction if control output is within operating range (control output > lower limit)
 
  133     mov w6, w4                              ; override controller output
 
  134     V_LOOP_CLAMP_MIN_EXIT:
 
  136 ; Check for upper limit violation
 
  137     mov [w0 + #MaxOutput], w6               ; load upper limit value
 
  138     cpslt w4, w6                            ; compare values and skip next instruction if control output is within operating range (control output < upper limit)
 
  139     mov w6, w4                              ; override controller output
 
  140     V_LOOP_CLAMP_MAX_EXIT:
 
  142 ;------------------------------------------------------------------------------
 
  143 ; Write control output value to target
 
  144     mov [w0 + #ptrTargetRegister], w8       ; capture pointer to target in working register
 
  145     mov w4, [w8]                            ; move control output to target address
 
  146     mov [w0 + #ptrDProvControlOutput], w2   ; load pointer address of target buffer of most recent controller output value from data structure
 
  147     mov w4, [w2]                            ; copy most recent controller output value to given data buffer target
 
  149 ;------------------------------------------------------------------------------
 
  150 ; Update ADC trigger locations
 
  151     asr w4, #1, w6                          ; half control output by shifting value one bit to the right
 
  152     ; Update ADC trigger B position
 
  153     mov [w0 + #ADCTriggerBOffset], w8       ; load user-defined ADC trigger B offset value into working register
 
  154     add w6, w8, w10                         ; add user-defined ADC trigger B offset to half of control output
 
  155     mov [w0 + #ptrADCTriggerBRegister], w8  ; load pointer to ADC trigger B register into working register
 
  156     mov w10, [w8]                           ; push new ADC trigger value to ADC trigger B register
 
  157     ; Update ADC trigger A position
 
  158     mov [w0 + #ADCTriggerAOffset], w8       ; load user-defined ADC trigger A offset value into working register
 
  159     add w6, w8, w10                         ; add user-defined ADC trigger A offset to half of control output
 
  160     mov [w0 + #ptrADCTriggerARegister], w8  ; load pointer to ADC trigger A register into working register
 
  161     mov w10, [w8]                           ; push new ADC trigger value to ADC trigger A register
 
  163 ;------------------------------------------------------------------------------
 
  164 ; Load pointer to first element of control history array
 
  165     mov [w0 + #ptrControlHistory], w10      ; load pointer address into working register
 
  167 ;------------------------------------------------------------------------------
 
  168 ; Update control output history (move entries one tick down the delay line)
 
  169     mov [w10 + #4], w6                      ; move entry (n-3) one tick down the delay line
 
  171     mov [w10 + #2], w6                      ; move entry (n-2) one tick down the delay line
 
  173     mov [w10 + #0], w6                      ; move entry (n-1) one tick down the delay line
 
  175     mov w4, [w10]                           ; add most recent control output to history
 
  177 ;------------------------------------------------------------------------------
 
  178 ; Enable/Disable bypass branch target with dummy read of source buffer
 
  179     goto V_LOOP_LOOP_EXIT                   ; when enabled, step over dummy read and go straight to EXIT
 
  180     V_LOOP_LOOP_BYPASS:                     ; Enable/Disable bypass branch target to perform dummy read of source to clear the source buffer
 
  181     mov [w0 + #ptrSourceRegister], w2       ; load pointer to input source register
 
  182     mov [w2], w1                            ; move value from input source into working register
 
  183     mov [w0 + #ptrDProvControlInputComp], w2 ; load pointer address of target buffer of most recent, compensated controller input from data structure
 
  184     mov w1, [w2]                            ; copy most recent controller input value to given data buffer target
 
  185     mov [w0 + #ptrDProvControlOutput], w2   ; load pointer address of target buffer of most recent controller output value from data structure
 
  186     clr [w2]                                ; copy most recent controller output value to given data buffer target
 
  187     V_LOOP_LOOP_EXIT:                       ; Exit control loop branch target
 
  189 ;------------------------------------------------------------------------------
 
  191     return                                  ; end of function; return to caller
 
  193 ;------------------------------------------------------------------------------
 
  196 ;------------------------------------------------------------------------------
 
  197 ; Global function declaration v_loop_Reset
 
  198 ; This function clears control and error histories enforcing a reset
 
  199 ;------------------------------------------------------------------------------
 
  201     .global _v_loop_Reset                   ; provide global scope to routine
 
  202     _v_loop_Reset:                          ; local function label
 
  204 ;------------------------------------------------------------------------------
 
  205 ; Clear control history array
 
  206     push w0                                 ; save contents of working register WREG0
 
  207     mov [w0 + #ptrControlHistory], w0       ; set pointer to the base address of control history array
 
  208     clr [w0++]                              ; clear next address of control history array
 
  209     clr [w0++]                              ; clear next address of control history array
 
  210     clr [w0++]                              ; clear next address of control history array
 
  211     clr [w0]                                ; clear last address of control history array
 
  212     pop w0                                  ; restore contents of working register WREG0
 
  214 ;------------------------------------------------------------------------------
 
  215 ; Clear error history array
 
  216     push w0                                 ; save contents of working register WREG0
 
  217     mov [w0 + #ptrErrorHistory], w0         ; set pointer to the base 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 next address of error history array
 
  221     clr [w0++]                              ; Clear next address of error history array
 
  222     clr [w0]                                ; clear last address of error history array
 
  223     pop w0                                  ; restore contents of working register WREG0
 
  225 ;------------------------------------------------------------------------------
 
  227     return                                  ; end of function; return to caller
 
  229 ;------------------------------------------------------------------------------
 
  232 ;------------------------------------------------------------------------------
 
  233 ; Global function declaration v_loop_Precharge
 
  234 ; This function loads user-defined default values into control and error histories
 
  235 ;------------------------------------------------------------------------------
 
  237     .global _v_loop_Precharge               ; provide global scope to routine
 
  238     _v_loop_Precharge:                      ; local function label
 
  240 ;------------------------------------------------------------------------------
 
  241 ; Charge error history array with defined value
 
  242     push w0                                 ; save contents of working register WREG0
 
  243     push w1                                 ; save contents of working register WREG1
 
  244     mov  [w0 + #ptrErrorHistory], w0        ; set pointer to the base 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 next address of error history array
 
  248     mov w1, [w0++]                          ; Load user value into next address of error history array
 
  249     mov w1, [w0]                            ; load user value into last address of error history array
 
  250     pop w1                                  ; restore contents of working register WREG1
 
  251     pop w0                                  ; restore contents of working register WREG0
 
  253 ;------------------------------------------------------------------------------
 
  254 ; Charge control history array with defined value
 
  255     push w0                                 ; save contents of working register WREG0
 
  256     push w2                                 ; save contents of working register WREG2
 
  257     mov  [w0 + #ptrControlHistory], w0      ; set pointer to the base 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 next address of control history array
 
  260     mov w2, [w0++]                          ; Load user value into next address of control history array
 
  261     mov w2, [w0]                            ; Load user value into last address of control history array
 
  262     pop w2                                  ; restore contents of working register WREG2
 
  263     pop w0                                  ; restore contents of working register WREG0
 
  265 ;------------------------------------------------------------------------------
 
  267     return                                  ; end of function; return to caller
 
  269 ;------------------------------------------------------------------------------
 
  272 ;------------------------------------------------------------------------------
 
  273 ; Global function declaration v_loop_PTermUpdate
 
  274 ; This function executes a P-Term based control loop used for plant measurements only.
 
  275 ; THIS LOOP IS NOT SUITED FOR STABLE OPERATION
 
  276 ;------------------------------------------------------------------------------
 
  278     .global _v_loop_PTermUpdate             ; provide global scope to routine
 
  279     _v_loop_PTermUpdate:                    ; local function label
 
  281 ;------------------------------------------------------------------------------
 
  282 ; Check status word for Enable/Disable flag and bypass computation when disabled
 
  283     btss [w0], #NPNZ16_STATUS_ENABLED       ; check ENABLED bit state, skip (do not execute) next instruction if set
 
  284     bra V_LOOP_PTERM_LOOP_BYPASS            ; if ENABLED bit is cleared, jump to end of control code
 
  286 ;------------------------------------------------------------------------------
 
  287 ; Read data from input source
 
  288     mov [w0 + #ptrSourceRegister], w2       ; load pointer to input source register
 
  289     mov [w2], w1                            ; move value from input source into working register
 
  290     mov [w0 + #ptrDProvControlInputComp], w2 ; load pointer address of target buffer of most recent, compensated controller input from data structure
 
  291     mov w1, [w2]                            ; copy most recent controller input value to given data buffer target
 
  293 ;------------------------------------------------------------------------------
 
  294 ; Load reference and calculate error input to transfer function
 
  295     mov [w0 + #ptrControlReference], w2     ; move pointer to control reference into working register
 
  296     subr w1, [w2], w1                       ; calculate error (=reference - input)
 
  297     mov [w0 + #normPreShift], w2            ; move error input scaler into working register
 
  298     sl w1, w2, w1                           ; normalize error result to fractional number format
 
  300 ;------------------------------------------------------------------------------
 
  301 ; Load P-gain factor from data structure
 
  302     mov [w0 + #PTermFactor], w6             ; move P-coefficient fractional into working register
 
  303     mov [w0 + #PTermScaler], w2             ; move P-coefficient scaler into working register
 
  304     mov w1, w4                              ; move error to MPY working register
 
  305     ; calculate P-control result
 
  306     mpy w4*w6, a                            ; multiply most recent error with P-coefficient
 
  307     sftac a, w2                             ; shift accumulator to post-scale floating number
 
  308     sac.r a, w4                             ; store accumulator result to working register
 
  310 ;------------------------------------------------------------------------------
 
  311 ; Controller Anti-Windup (control output value clamping)
 
  313 ; Check for lower limit violation
 
  314     mov [w0 + #MinOutput], w6               ; load lower limit value
 
  315     cpsgt w4, w6                            ; compare values and skip next instruction if control output is within operating range (control output > lower limit)
 
  316     mov w6, w4                              ; override controller output
 
  317     V_LOOP_PTERM_CLAMP_MIN_EXIT:
 
  319 ; Check for upper limit violation
 
  320     mov [w0 + #MaxOutput], w6               ; load upper limit value
 
  321     cpslt w4, w6                            ; compare values and skip next instruction if control output is within operating range (control output < upper limit)
 
  322     mov w6, w4                              ; override controller output
 
  323     V_LOOP_PTERM_CLAMP_MAX_EXIT:
 
  325 ;------------------------------------------------------------------------------
 
  326 ; Write control output value to target
 
  327     mov [w0 + #ptrTargetRegister], w8       ; capture pointer to target in working register
 
  328     mov w4, [w8]                            ; move control output to target address
 
  329     mov [w0 + #ptrDProvControlOutput], w2   ; load pointer address of target buffer of most recent controller output value from data structure
 
  330     mov w4, [w2]                            ; copy most recent controller output value to given data buffer target
 
  332 ;------------------------------------------------------------------------------
 
  333 ; Update ADC trigger locations
 
  334     asr w4, #1, w6                          ; half control output by shifting value one bit to the right
 
  335     ; Update ADC trigger B position
 
  336     mov [w0 + #ADCTriggerBOffset], w8       ; load user-defined ADC trigger B offset value into working register
 
  337     add w6, w8, w10                         ; add user-defined ADC trigger B offset to half of control output
 
  338     mov [w0 + #ptrADCTriggerBRegister], w8  ; load pointer to ADC trigger B register into working register
 
  339     mov w10, [w8]                           ; push new ADC trigger value to ADC trigger B register
 
  340     ; Update ADC trigger A position
 
  341     mov [w0 + #ADCTriggerAOffset], w8       ; load user-defined ADC trigger A offset value into working register
 
  342     add w6, w8, w10                         ; add user-defined ADC trigger A offset to half of control output
 
  343     mov [w0 + #ptrADCTriggerARegister], w8  ; load pointer to ADC trigger A register into working register
 
  344     mov w10, [w8]                           ; push new ADC trigger value to ADC trigger A register
 
  346 ;------------------------------------------------------------------------------
 
  347 ; Enable/Disable bypass branch target with dummy read of source buffer
 
  348     goto V_LOOP_PTERM_LOOP_EXIT             ; when enabled, step over dummy read and go straight to EXIT
 
  349     V_LOOP_PTERM_LOOP_BYPASS:               ; Enable/Disable bypass branch target to perform dummy read of source to clear the source buffer
 
  350     mov [w0 + #ptrSourceRegister], w2       ; load pointer to input source register
 
  351     mov [w2], w1                            ; move value from input source into working register
 
  352     mov [w0 + #ptrDProvControlInputComp], w2 ; load pointer address of target buffer of most recent, compensated controller input from data structure
 
  353     mov w1, [w2]                            ; copy most recent controller input value to given data buffer target
 
  354     mov [w0 + #ptrDProvControlOutput], w2   ; load pointer address of target buffer of most recent controller output value from data structure
 
  355     clr [w2]                                ; copy most recent controller output value to given data buffer target
 
  356     V_LOOP_PTERM_LOOP_EXIT:                 ; Exit P-Term control loop branch target
 
  358 ;------------------------------------------------------------------------------
 
  360     return                                  ; end of function; return to caller
 
  362 ;------------------------------------------------------------------------------
 
  365 ;------------------------------------------------------------------------------
 
  367     .end                                    ; end of file v_loop_asm.s
 
  369 ;------------------------------------------------------------------------------
 
  372 ; **********************************************************************************
 
  373 ;  Download latest version of this tool here: https://areiter128.github.io/DCLD
 
  374 ; **********************************************************************************