1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2; (c) 2013 Microchip Technology Inc.
4; MICROCHIP SOFTWARE NOTICE AND DISCLAIMER: You may use this software, and any
5; derivatives created by any person or entity by or on your behalf, exclusively with
6; Microchip?s products. Microchip and its licensors retain all ownership and intellectual
7; property rights in the accompanying software and in all derivatives here to.
9; This software and any accompanying information is for suggestion only. It does not
10; modify Microchip?s standard warranty for its products. You agree that you are solely
11; responsible for testing the software and determining its suitability. Microchip has
12; no obligation to modify, test, certify, or support the software.
14; THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
15; OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF NON-INFRINGEMENT,
16; MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE, ITS INTERACTION
17; WITH MICROCHIP?S PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.
19; IN NO EVENT, WILL MICROCHIP BE LIABLE, WHETHER IN CONTRACT, WARRANTY, TORT
20; (INCLUDING NEGLIGENCE OR BREACH OF STATUTORY DUTY), STRICT LIABILITY, INDEMNITY,
21; CONTRIBUTION, OR OTHERWISE, FOR ANY INDIRECT, SPECIAL, PUNITIVE, EXEMPLARY, INCIDENTAL
22; OR CONSEQUENTIAL LOSS, DAMAGE, FOR COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
23; SOFTWARE, HOWSOEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR
24; THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT ALLOWABLE BY LAW, MICROCHIP'S TOTAL
25; LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES,
26; IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
28; MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE TERMS.
30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
36; Define data structure address offsets
37 .equ offsetabcCoefficients, 0
38 .equ offsetErrorHistory, 2
39 .equ offsetControlHistory, 4
40 .equ offsetPostScaler, 6
41 .equ offsetPreShift, 8
42 .equ offsetPostShift, 10
43 .equ offsetMinOutput, 12
44 .equ offsetMaxOutput, 14
47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
49 ; .section .libdsp, code ; use this section type when used as hidden library file
50 .section .text ; use this section type for debugging
52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
56; void SMPS_ControllerPIDUpdate(SMPS_PID_T* controllerData,
57; volatile uint16_t* controllerInputRegister,int16_t reference,
58; volatile uint16_t* controllerOutputRegister);
63; ---------------| Kp |-----------------
67;Input --- | -------------- Integral | + | Control -------
68; --------| + | Control | | Ki | Output | | Output | |
69; | |----------|----------| ------------ |----------| + |----------| Plant |--
70; -----| - |Difference| | 1 - Z^(-1) | | | | | |
71; | --- (error) | -------------- | + | ------- |
73; | Measured | ------------------- Deriv | |
74; | Outut | | | Output | |
75; | --------| Kd * (1 - Z^(-1)) |--------- |
77; | ------------------- |
80; -----------------------------------------------------------------------------------
82; controlOutput[n] = controlHistory[n-1]
83; + ErrorHistory[n] * abcCoefficients[0]
84; + ErrorHistory[n-1] * abcCoefficients[1]
85; + ErrorHistory[n-2] * abcCoefficients[2]
88; abcCoefficients[0] = Kp + Ki + Kd
89; abcCoefficients[1] = -(Kp + 2*Kd)
90; abcCoefficients[2] = Kd
91; ErrorHistory[n] = referenceInput[n] - measuredInput[n]
92; controlHistory = > control calculated output[n-1]
93; preShift = prsft => pre scaling factor for Q15 normalization purposes
94; postShift = posft => post scaling factor for normalization purposes
95; postScaler = postScaler => post scaling coefficient for normalization purpose
97; Function call inputs:
98; sourceRegister = ADBUFx => measured feedback input
99; controlReference = V_ref => reference voltage
100; targetRegister = PDCx => output duty cycle
103; abcCoefficients, controlHistory, controlOutput, controlInput and controlReference
104; are all members of the data structure SMPS_PID_T.
107; w0 = Address of SMPS_PID_T data structure
108; w1 = Address of the Source Register (Input)
109; w2 = Control Reference
110; w3 = Address of the Target Register (Output)
112; w0 = Address of SMPS_PID_T data structure
113; w1 = Address of the Source Register (Input)
114; w2 = Control Reference
115; w3 = Address of the Target Register (Output)
117; System resources usage:
118; {w4..w5} used, not restored
119; {w8,w10} saved, used, restored
120; AccA used, not restored
121; CORCON saved, used, restored
124; This function requires CORCON register to be setup in a certain state
125; in order to operate correctly. Due to this requirement, this function
126; will save the CORCON register on the stack in the beginning of the
127; function and restore it before the function return.
128; After saving the CORCON register, this function writes to all bits of
129; the CORCON register. Thus, for the brief duration when this function is
130; executing, the state of CORCON register may be different from its state
131; as set by the function caller. This may change the CPU core behaviour with
132; respect to exception processing latency, DO loop termination, CPU interrupt
133; priority level and DSP-engine behaviour.
134;............................................................................
137 .global _SMPS_ControllerPIDUpdate ; provide global scope to routine
138_SMPS_ControllerPIDUpdate:
140 ; Save working registers.
141 push w4 ; Save register W4
142 push w5 ; Save register W5
143 push w8 ; Save register W8
144 push w10 ; Save register W10
145 push CORCON ; Save CORCON as it will be modified for fractional computation
147 ; Set up DSP core for signed fractional operation, saturation on accumulator A
148 ; and for write-back instructions from ACCx to WREGx,
149 ; accumulator saturation mode is 1.31
151 mov #0x00A0, w4 ; Load literal value 0x00A0 to CORCON register: 0b 0000 0000 1010 0000
154 ; Initialize source input, reference, error history and normalization variables
156 mov [w0 + #offsetErrorHistory], w10 ; w10 = Address of _ErrorHistory array (state/delay line)
157 mov [w0 + #offsetPreShift], w8 ; Load error amplifier normalization bit-shift step
159 ; Calculate most recent error with normalization,
161 sub w2, [w1], w5 ; w5 = Reference - inputSource
162 sl w5, w8, w5 ; shift error by PRE_SHIFT bit to the left (Q15 scaling)
164 ; Store most recent error to error history array
165 mov w5, [w10] ; controllerPID.errorHistory[n] = w5
167 ; Initialize coefficients and history array
169 mov [w0 + #offsetabcCoefficients], w8 ; w8 = Base Address of _abcCoefficients array [(Kp+Ki+Kd), -(Kp+2Kd), Kd]
170 mov [w0 + #offsetControlHistory], w2 ; w1=ControlOutput[n-1], load previous control output
172 ; Calculate PID Control Output
173 clr a, [w8]+=2, w4, [w10]+=2, w5 ; w4 = (Kp+Ki+Kd), w5 = _ErrorHistory[n]
174 lac w2, a ; A = ErrorOutput[n-1]
175 mac w4*w5, a, [w8]+=2, w4, [w10]+=2, w5 ; A += (Kp+Ki+Kd) * _ErrorHistory[n]
176 ; w4 = -(Kp+2Kd), w5 = _ErrorHistory[n-1]
177 mac w4*w5, a, [w8], w4, [w10]-=2, w5 ; A += -(Kp+2Kd) * _ErrorHistory[n-1]
178 ; w4 = Kd, w5 = _ErrorHistory[n-2]
179 mac w4*w5, a, [w10]-=2, w5 ; A += Kd * _ErrorHistory[n-2]
180 ; w5 = _ErrorHistory[n-1]
181 ; w10 = &_ErrorHistory[n-2]
182 sac.r a, w5 ; ControlOutput[n] = Sat(Rnd(A))
184 ; Copy control output to structure (non-array)
185 mov w5, [w0 + #offsetControlHistory]
187 ; Initialize Scale-factor and multiply
188 sac.r a, w4 ; w4 = Sat(Rnd(ACCAH))
189 mov [w0 + #offsetPostScaler], w5 ; w5 = postScaler
190 mpy w4*w5, a ; Multiply control output and scale-factor
193 ; Backwards normalization & write back
194 mov [w0 + #offsetPostShift], w8 ; w8 = Normalization Shift to compensate coefficient scaling
195 sftac a, w8 ; Backward normalization to compensate coefficient scaling
196 sac.r a, w4 ; w4 = Sat(Rnd(ACCAH))
200 ; Clamp controller output to min/max values if needed
201; must comment out to get also neg. values
202; mov [w0 + #offsetMinOutput], w5
205; mov [w0 + #offsetMaxOutput], w5
209 ; Controller write back into target register
210 mov w4, [w3] ; write result into target register
212 ;Update control output history on the delay line
213 mov [w10 + #2], w5 ; W5 = ErrorHistory[n-1]
214 mov w5, [w10 + #4] ; ErrorHistory[n-2] = W5
215 mov [w10], w5 ; W5 = ErrorHistory[n]
216 mov w5, [w10 + #2] ; ErrorHistory[n-1] = W5
219 pop CORCON ; restore CORCON.
220 pop w10 ; Restore working registers.
230;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
232;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
233; _SMPS_ControllerPIDInitialize:
236; void SMPS_PIDInitialize( SMPS_PID_T *controller_data )
238; Operation: This routine clears the delay line elements in the arrays
239; _ControlHistory and _ErrorHistory, as well as clears the current
240; control output element, _ControlOutput
243; w0 = Address of data structure SMPS_PID_T (type defined in smps_control.h)
248; System resources usage:
249; w0 saved, used, restored
251;............................................................................
253 .global _SMPS_ControllerPIDInitialize ; provide global scope to routine
255_SMPS_ControllerPIDInitialize:
257 ; Clean up most recent controller output
259 add #offsetControlHistory, w0 ;clear controlOutput
263 ; Clean up errorHistory variables
264 push w0 ;Set up pointer to the base of
265 mov [w0 + #offsetErrorHistory], w0 ; w0 = Address of _ErrorHistory array (e[n], e[n-1], e[n-2])
266 clr [w0++] ; ErrorHistory[n] = 0
267 clr [w0++] ; ErrorHistory[n-1] = 0
268 clr [w0] ; ErrorHistory[n-2] = 0
269 pop w0 ;Restore pointer to base of SMPS_PID_T
272;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
276;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;