1 /*
2 * Copyright (c) 2024 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_CLC_DRV_H
9 #define HPM_CLC_DRV_H
10
11 #include "hpm_common.h"
12 #include "hpm_clc_regs.h"
13
14 /**
15 * @brief CLC driver APIs
16 * @defgroup clc_interface CLC driver APIs
17 * @ingroup motor_interfaces
18 * @{
19 */
20
21 /**
22 * @brief clc channel
23 */
24 typedef enum {
25 clc_vd_chn = CLC_VDVQ_CHAN_VD,
26 clc_vq_chn = CLC_VDVQ_CHAN_VQ,
27 } clc_chn_t; /**< clc_chn_t */
28
29 /**
30 * @brief clc coefficient zone
31 */
32 typedef enum {
33 clc_coeff_zone_0 = CLC_COEFF_0,
34 clc_coeff_zone_1 = CLC_COEFF_1,
35 clc_coeff_zone_2 = CLC_COEFF_2,
36 } clc_coeff_zone_t; /**< clc_coeff_zone_t */
37
38 /**
39 * @brief clc irq mask bit
40 */
41 typedef enum {
42 clc_irq_calc_done = BIT0_MASK,
43 clc_irq_eadc_setting_err = BIT1_MASK,
44 clc_irq_2p2z_clamp_setting_err = BIT2_MASK,
45 clc_irq_2p2z_over_hi = BIT3_MASK,
46 clc_irq_2p2z_over_lo = BIT4_MASK,
47 clc_irq_2p2z_over_sf = BIT5_MASK,
48 clc_irq_3p3z_clamp_setting_err = BIT6_MASK,
49 clc_irq_3p3z_over_hi = BIT7_MASK,
50 clc_irq_3p3z_over_lo = BIT8_MASK,
51 clc_irq_forb_setting_err = BIT9_MASK,
52 clc_irq_data_in_forbid = BIT10_MASK
53 } clc_irq_mask_t;
54
55 /**
56 * @brief clc parameter configuration
57 */
58 typedef struct {
59 int32_t eadc_lowth;
60 int32_t eadc_mid_lowth;
61 int32_t eadc_mid_highth;
62 int32_t eadc_highth;
63 int32_t _2p2z_clamp_lowth;
64 int32_t _2p2z_clamp_highth;
65 int32_t _3p3z_clamp_lowth;
66 int32_t _3p3z_clamp_highth;
67 int32_t output_forbid_lowth;
68 int32_t output_forbid_mid;
69 int32_t output_forbid_highth;
70 } clc_param_config_t; /**< clc_param_config_t */
71
72 /**
73 * @brief clc coefficient configuration
74 */
75 typedef struct {
76 float b0;
77 float b1;
78 float b2;
79 float b3;
80 float a0;
81 float a1;
82 float a2;
83 } clc_coeff_config_t; /**< clc_coeff_config_t */
84
85 #ifdef __cplusplus
86 extern "C" {
87 #endif
88
89 /**
90 * @brief CLC enable or disable
91 *
92 * @param[in] clc CLC base address
93 * @param[in] chn CLC channel, @ref clc_chn_t
94 * @param[in] enable true-enable, false-disable
95 */
clc_set_enable(CLC_Type * clc,clc_chn_t chn,bool enable)96 static inline void clc_set_enable(CLC_Type *clc, clc_chn_t chn, bool enable)
97 {
98 if (enable) {
99 clc->VDVQ_CHAN[chn].MODE |= CLC_VDVQ_CHAN_MODE_ENABLE_CLC_MASK;
100 } else {
101 clc->VDVQ_CHAN[chn].MODE &= ~CLC_VDVQ_CHAN_MODE_ENABLE_CLC_MASK;
102 }
103 }
104
105 /**
106 * @brief CLC keep working even if bad irq status ocurred
107 *
108 * @param[in] clc CLC base address
109 * @param[in] chn CLC channel, @ref clc_chn_t
110 * @param[in] enable true-enable, false-disable
111 */
clc_set_mask_mode_enable(CLC_Type * clc,clc_chn_t chn,bool enable)112 static inline void clc_set_mask_mode_enable(CLC_Type *clc, clc_chn_t chn, bool enable)
113 {
114 if (enable) {
115 clc->VDVQ_CHAN[chn].MODE |= CLC_VDVQ_CHAN_MODE_MASK_MODE_MASK;
116 } else {
117 clc->VDVQ_CHAN[chn].MODE &= ~CLC_VDVQ_CHAN_MODE_MASK_MODE_MASK;
118 }
119 }
120
121 /**
122 * @brief CLC set software inject dq work mode
123 *
124 * @param[in] clc CLC base address
125 * @param[in] chn CLC channel, @ref clc_chn_t
126 * @param[in] enable true-if the ADC value comes from software injection and the VD/VQ channel is required for joint use.
127 */
clc_set_sw_inject_dq_mode_enable(CLC_Type * clc,clc_chn_t chn,bool enable)128 static inline void clc_set_sw_inject_dq_mode_enable(CLC_Type *clc, clc_chn_t chn, bool enable)
129 {
130 if (enable) {
131 clc->VDVQ_CHAN[chn].MODE |= CLC_VDVQ_CHAN_MODE_DQ_MODE_MASK;
132 } else {
133 clc->VDVQ_CHAN[chn].MODE &= ~CLC_VDVQ_CHAN_MODE_DQ_MODE_MASK;
134 }
135 }
136
137 /**
138 * @brief CLC set irq enable or disable
139 * @param[in] clc CLC base address
140 * @param[in] chn CLC channel, @ref clc_chn_t
141 * @param[in] irq_mask irq mask, @ref clc_irq_mask_t
142 * @param[in] enable enable or disable
143 * @arg true enable
144 * @arg false disable
145 */
clc_set_irq_enable(CLC_Type * clc,clc_chn_t chn,uint32_t irq_mask,bool enable)146 static inline void clc_set_irq_enable(CLC_Type *clc, clc_chn_t chn, uint32_t irq_mask, bool enable)
147 {
148 if (enable) {
149 clc->VDVQ_CHAN[chn].MODE |= CLC_VDVQ_CHAN_MODE_ENABLE_IRQ_SET(irq_mask);
150 } else {
151 clc->VDVQ_CHAN[chn].MODE &= ~CLC_VDVQ_CHAN_MODE_ENABLE_IRQ_SET(irq_mask);
152 }
153 }
154
155 /**
156 * @brief CLC get irq status
157 * @param[in] clc CLC base address
158 * @param[in] chn CLC channel, @ref clc_chn_t
159
160 * @retval irq status.
161 */
clc_get_irq_status(CLC_Type * clc,clc_chn_t chn)162 static inline uint32_t clc_get_irq_status(CLC_Type *clc, clc_chn_t chn)
163 {
164 return CLC_VDVQ_CHAN_STATUS_STATUS_GET(clc->VDVQ_CHAN[chn].STATUS);
165 }
166
167 /**
168 * @brief CLC clear irq status
169 * @param[in] clc CLC base address
170 * @param[in] chn CLC channel, @ref clc_chn_t
171 * @param[in] irq_mask irq mask, @ref clc_irq_mask_t
172 */
clc_clear_irq_status(CLC_Type * clc,clc_chn_t chn,uint32_t irq_mask)173 static inline void clc_clear_irq_status(CLC_Type *clc, clc_chn_t chn, uint32_t irq_mask)
174 {
175 clc->VDVQ_CHAN[chn].STATUS = CLC_VDVQ_CHAN_STATUS_STATUS_SET(irq_mask);
176 }
177
178 /**
179 * @brief CLC check irq request flag
180 * @param[in] clc CLC base address
181 * @param[in] chn CLC channel, @ref clc_chn_t
182 * @param[in] irq_mask irq mask, @ref clc_irq_mask_t
183
184 * @retval true-has irq req, false-no irq req.
185 */
clc_get_irq_flag(CLC_Type * clc,clc_chn_t chn,uint32_t irq_mask)186 static inline bool clc_get_irq_flag(CLC_Type *clc, clc_chn_t chn, uint32_t irq_mask)
187 {
188 return ((clc->VDVQ_CHAN[chn].STATUS & irq_mask) == irq_mask) ? true : false;
189 }
190
191 /**
192 * @brief CLC set adc channel
193 * @param[in] clc CLC base address
194 * @param[in] chn CLC channel, @ref clc_chn_t
195 * @param[in] adc_chn adc channel for ADC0~3 or SDM_ADC0~7, adc from VSC must be set to 0.
196 * @param[in] adc_offset adc offset for ADC0~3 or SDM_ADC0~7, adc from VSC must be set to 0.
197 */
clc_set_adc_chn_offset(CLC_Type * clc,clc_chn_t chn,uint32_t adc_chn,uint32_t adc_offset)198 static inline void clc_set_adc_chn_offset(CLC_Type *clc, clc_chn_t chn, uint32_t adc_chn, uint32_t adc_offset)
199 {
200 clc->VDVQ_CHAN[chn].ADC_CHAN = adc_chn;
201 clc->VDVQ_CHAN[chn].ADC_OFFSET = adc_offset;
202 }
203
204 /**
205 * @brief CLC set pwm period
206 * @param[in] clc CLC base address
207 * @param[in] chn CLC channel, @ref clc_chn_t
208 * @param[in] pwm_period 0-clc dac output pwm duty ratio, else-clc dac output pwm period, number of clock cycles.
209 */
clc_set_pwm_period(CLC_Type * clc,clc_chn_t chn,uint32_t pwm_period)210 static inline void clc_set_pwm_period(CLC_Type *clc, clc_chn_t chn, uint32_t pwm_period)
211 {
212 clc->VDVQ_CHAN[chn].PWM_PERIOD = pwm_period;
213 }
214
215 /**
216 * @brief CLC set pwm period
217 * @param[in] clc CLC base address
218 * @param[in] chn CLC channel, @ref clc_chn_t
219 * @retval pwm period
220 */
clc_get_pwm_period(CLC_Type * clc,clc_chn_t chn)221 static inline uint32_t clc_get_pwm_period(CLC_Type *clc, clc_chn_t chn)
222 {
223 return clc->VDVQ_CHAN[chn].PWM_PERIOD;
224 }
225
226 /**
227 * @brief CLC get output caculated value
228 * @param[in] clc CLC base address
229 * @param[in] chn CLC channel, @ref clc_chn_t
230 * @retval CLC output caculated value
231 */
clc_get_output_value(CLC_Type * clc,clc_chn_t chn)232 static inline uint32_t clc_get_output_value(CLC_Type *clc, clc_chn_t chn)
233 {
234 return clc->VDVQ_CHAN[chn].OUTPUT_VALUE;
235 }
236
237 /**
238 * @brief CLC get timestamp
239 * @param[in] clc CLC base address
240 * @param[in] chn CLC channel, @ref clc_chn_t
241 * @retval CLC adc timestamp
242 */
clc_get_timestamp(CLC_Type * clc,clc_chn_t chn)243 static inline uint32_t clc_get_timestamp(CLC_Type *clc, clc_chn_t chn)
244 {
245 return clc->VDVQ_CHAN[chn].TIMESTAMP;
246 }
247
248 /**
249 * @brief CLC get error adc latest value
250 * @param[in] clc CLC base address
251 * @param[in] chn CLC channel, @ref clc_chn_t
252 * @retval CLC error adc latest value
253 */
clc_get_eadc_current_value(CLC_Type * clc,clc_chn_t chn)254 static inline int32_t clc_get_eadc_current_value(CLC_Type *clc, clc_chn_t chn)
255 {
256 return (int32_t)clc->VDVQ_CHAN[chn].EADC_CURR;
257 }
258
259 /**
260 * @brief CLC get error adc previous0 value
261 * @param[in] clc CLC base address
262 * @param[in] chn CLC channel, @ref clc_chn_t
263 * @retval CLC error adc previous0 value
264 */
clc_get_eadc_previous0_value(CLC_Type * clc,clc_chn_t chn)265 static inline int32_t clc_get_eadc_previous0_value(CLC_Type *clc, clc_chn_t chn)
266 {
267 return (int32_t)clc->VDVQ_CHAN[chn].EADC_PRE0;
268 }
269
270 /**
271 * @brief CLC software inject error adc previous0 value
272 * @param[in] clc CLC base address
273 * @param[in] chn CLC channel, @ref clc_chn_t
274 * @param[in] value CLC error adc previous0 value
275 */
clc_sw_inject_eadc_previous0_value(CLC_Type * clc,clc_chn_t chn,int32_t value)276 static inline void clc_sw_inject_eadc_previous0_value(CLC_Type *clc, clc_chn_t chn, int32_t value)
277 {
278 clc->VDVQ_CHAN[chn].EADC_PRE0 = (uint32_t)value;
279 }
280
281 /**
282 * @brief CLC get error adc previous1 value
283 * @param[in] clc CLC base address
284 * @param[in] chn CLC channel, @ref clc_chn_t
285 * @retval CLC error adc previous1 value
286 */
clc_get_eadc_previous1_value(CLC_Type * clc,clc_chn_t chn)287 static inline int32_t clc_get_eadc_previous1_value(CLC_Type *clc, clc_chn_t chn)
288 {
289 return (int32_t)clc->VDVQ_CHAN[chn].EADC_PRE1;
290 }
291
292 /**
293 * @brief CLC software inject error adc previous1 value
294 * @param[in] clc CLC base address
295 * @param[in] chn CLC channel, @ref clc_chn_t
296 * @param[in] value CLC error adc previous1 value
297 */
clc_sw_inject_eadc_previous1_value(CLC_Type * clc,clc_chn_t chn,int32_t value)298 static inline void clc_sw_inject_eadc_previous1_value(CLC_Type *clc, clc_chn_t chn, int32_t value)
299 {
300 clc->VDVQ_CHAN[chn].EADC_PRE1 = (uint32_t)value;
301 }
302
303 /**
304 * @brief CLC get 2p2z last value
305 * @param[in] clc CLC base address
306 * @param[in] chn CLC channel, @ref clc_chn_t
307 * @retval CLC 2p2z last value
308 */
clc_get_2p2z_current_value(CLC_Type * clc,clc_chn_t chn)309 static inline int32_t clc_get_2p2z_current_value(CLC_Type *clc, clc_chn_t chn)
310 {
311 return (int32_t)clc->VDVQ_CHAN[chn].P2Z2_CURR;
312 }
313
314 /**
315 * @brief CLC software inject 2p2z last value
316 * @param[in] clc CLC base address
317 * @param[in] chn CLC channel, @ref clc_chn_t
318 * @param[in] value CLC 2p2z last value
319 */
clc_sw_inject_2p2z_current_value(CLC_Type * clc,clc_chn_t chn,int32_t value)320 static inline void clc_sw_inject_2p2z_current_value(CLC_Type *clc, clc_chn_t chn, int32_t value)
321 {
322 clc->VDVQ_CHAN[chn].P2Z2_CURR = (uint32_t)value;
323 }
324
325 /**
326 * @brief CLC get 2p2z previous0 value
327 * @param[in] clc CLC base address
328 * @param[in] chn CLC channel, @ref clc_chn_t
329 * @retval CLC 2p2z previous0 value
330 */
clc_get_2p2z_previous0_value(CLC_Type * clc,clc_chn_t chn)331 static inline int32_t clc_get_2p2z_previous0_value(CLC_Type *clc, clc_chn_t chn)
332 {
333 return (int32_t)clc->VDVQ_CHAN[chn].P2Z2_PRE0;
334 }
335
336 /**
337 * @brief CLC software inject 2p2z previous0 value
338 * @param[in] clc CLC base address
339 * @param[in] chn CLC channel, @ref clc_chn_t
340 * @param[in] value CLC 2p2z previous0 value
341 */
clc_sw_inject_2p2z_previous0_value(CLC_Type * clc,clc_chn_t chn,int32_t value)342 static inline void clc_sw_inject_2p2z_previous0_value(CLC_Type *clc, clc_chn_t chn, int32_t value)
343 {
344 clc->VDVQ_CHAN[chn].P2Z2_PRE0 = (uint32_t)value;
345 }
346
347 /**
348 * @brief CLC get 3p3z last value
349 * @param[in] clc CLC base address
350 * @param[in] chn CLC channel, @ref clc_chn_t
351 * @retval CLC 3p3z last value
352 */
clc_get_3p3z_current_value(CLC_Type * clc,clc_chn_t chn)353 static inline int32_t clc_get_3p3z_current_value(CLC_Type *clc, clc_chn_t chn)
354 {
355 return (int32_t)clc->VDVQ_CHAN[chn].P3Z3_CURR;
356 }
357
358 /**
359 * @brief CLC software inject 3p3z last value
360 * @param[in] clc CLC base address
361 * @param[in] chn CLC channel, @ref clc_chn_t
362 * @param[in] value CLC 3p3z last value
363 */
clc_sw_inject_3p3z_current_value(CLC_Type * clc,clc_chn_t chn,int32_t value)364 static inline void clc_sw_inject_3p3z_current_value(CLC_Type *clc, clc_chn_t chn, int32_t value)
365 {
366 clc->VDVQ_CHAN[chn].P3Z3_CURR = (uint32_t)value;
367 }
368
369 /**
370 * @brief CLC set expected adc value
371 * @param[in] clc CLC base address
372 * @param[in] chn CLC channel, @ref clc_chn_t
373 * @param[in] expect expected adc value
374 */
clc_set_expect_adc_value(CLC_Type * clc,clc_chn_t chn,int32_t expect)375 static inline void clc_set_expect_adc_value(CLC_Type *clc, clc_chn_t chn, int32_t expect)
376 {
377 clc->VDVQ_CHAN[chn].ADC_EXPECT = (uint32_t)expect;
378 }
379
380 /**
381 * @brief CLC software inject adc value. If it's not dq mode, this will trig clc calculation.
382 * @param[in] clc CLC base address
383 * @param[in] chn CLC channel, @ref clc_chn_t
384 * @param[in] value CLC adc value
385 */
clc_sw_inject_adc_value(CLC_Type * clc,clc_chn_t chn,uint32_t value)386 static inline void clc_sw_inject_adc_value(CLC_Type *clc, clc_chn_t chn, uint32_t value)
387 {
388 clc->VDVQ_CHAN[chn].ADC_SW = value;
389 }
390
391 /**
392 * @brief CLC set software inject dq adc value ready, this will trig clc calculation.
393 * @param[in] clc CLC base address
394 */
clc_set_sw_inject_dq_adc_value_ready(CLC_Type * clc)395 static inline void clc_set_sw_inject_dq_adc_value_ready(CLC_Type *clc)
396 {
397 clc->DQ_ADC_SW_READY = CLC_DQ_ADC_SW_READY_DQ_ADC_SW_READY_MASK;
398 }
399
400 /**
401 * @brief CLC parameter configuration
402 * @param[in] clc CLC base address
403 * @param[in] chn CLC channel, @ref clc_chn_t
404 * @param[in] param @ref clc_param_config_t.
405 */
406 void clc_config_param(CLC_Type *clc, clc_chn_t chn, clc_param_config_t *param);
407
408 /**
409 * @brief CLC coefficient configuration
410 * @param[in] clc CLC base address
411 * @param[in] chn CLC channel, @ref clc_chn_t
412 * @param[in] zone CLC coefficient zone, @ref clc_coeff_zone_t
413 * @param[in] coeff @ref clc_param_config_t.
414 *
415 * @retval status_invalid_argument some parameters are invalid
416 * @retval status_success operation is successful
417 */
418 hpm_stat_t clc_config_coeff(CLC_Type *clc, clc_chn_t chn, clc_coeff_zone_t zone, clc_coeff_config_t *coeff);
419
420 /**
421 * @brief CLC software inject dq adc value
422 * @param[in] clc CLC base address
423 * @param[in] d_value CLC d adc value
424 * @param[in] q_value CLC q adc value
425 */
426 void clc_sw_inject_dq_adc_value(CLC_Type *clc, uint32_t d_value, uint32_t q_value);
427
428
429 #ifdef __cplusplus
430 }
431 #endif
432 /**
433 * @}
434 */
435 #endif /* HPM_CLC_DRV_H */
436