1 /*
2 * Copyright (c) 2024 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_VSC_DRV_H
9 #define HPM_VSC_DRV_H
10
11 #include "hpm_common.h"
12 #include "hpm_vsc_regs.h"
13
14 /**
15 * @brief VSC driver APIs
16 * @defgroup vsc_interface VSC driver APIs
17 * @ingroup motor_interfaces
18 * @{
19 */
20
21 /**
22 * @brief vsc phase mode
23 *
24 */
25 typedef enum vsc_phase_mode {
26 vsc_abc_phase = 0,
27 vsc_ab_phase = 1,
28 } vsc_phase_mode_t; /**< vsc_phase_mode_t */
29
30 /**
31 * @brief vsc data operation mode
32 *
33 */
34 typedef enum vsc_data_opr_mode {
35 vsc_data_opr_plus_mul_1 = 0,
36 vsc_data_opr_plus_mul_2 = 1,
37 vsc_data_opr_plus_div_2 = 5,
38 vsc_data_opr_plus_div_3 = 6,
39 vsc_data_opr_plus_div_4 = 7,
40 vsc_data_opr_minus_mul_1 = 8,
41 vsc_data_opr_minus_mul_2 = 9,
42 vsc_data_opr_minus_div_2 = 13,
43 vsc_data_opr_minus_div_3 = 14,
44 vsc_data_opr_minus_div_4 = 15
45 } vsc_data_opr_mode_t; /**< vsc_data_opr_mode_t */
46
47 /**
48 * @brief vsc select adc instance
49 *
50 */
51 typedef enum vsc_adc_sel {
52 vsc_sel_adc0 = 1,
53 vsc_sel_adc1 = 2,
54 vsc_sel_adc2 = 3
55 } vsc_adc_sel_t; /**< vsc_adc_sel_t */
56
57 /**
58 * @brief vsc position capture mode
59 *
60 */
61 typedef enum vsc_pos_cap_mode {
62 vsc_pos_use_last_data_when_adc_sample_finish = 0,
63 vsc_pos_use_first_data_after_adc_sample_start = 1,
64 vsc_pos_use_last_data_before_adc_sample_start = 2
65 } vsc_pos_cap_mode_t; /**< vsc_pos_cap_mode_t */
66
67 /**
68 * @brief vsc select adc timestamp
69 *
70 */
71 typedef enum vsc_timestamp_sel {
72 vsc_timestamp_sel_value_a = 1,
73 vsc_timestamp_sel_value_b = 2,
74 vsc_timestamp_sel_value_c = 3
75 } vsc_timestamp_sel_t; /**< vsc_timestamp_sel_t */
76
77 /**
78 * @brief vsc irq mask bit
79 *
80 */
81 typedef enum vsc_irq_mask {
82 vsc_irq_convert_done = BIT0_MASK,
83 vsc_irq_abc_over_tolerate = BIT1_MASK,
84 vsc_irq_c_overflow = BIT2_MASK,
85 vsc_irq_b_overflow = BIT3_MASK,
86 vsc_irq_a_overflow = BIT4_MASK,
87 vsc_irq_adc2_cap_not_enough = BIT5_MASK,
88 vsc_irq_adc1_cap_not_enough = BIT6_MASK,
89 vsc_irq_adc0_cap_not_enough = BIT7_MASK,
90 vsc_irq_pos_timeout = BIT8_MASK,
91 vsc_irq_adc2_timeout = BIT9_MASK,
92 vsc_irq_adc1_timeout = BIT10_MASK,
93 vsc_irq_adc0_timeout = BIT11_MASK,
94 vsc_irq_convert_conflict = BIT12_MASK
95 } vsc_irq_mask_t;
96
97 /**
98 * @brief adc config structure
99 */
100 typedef struct {
101 vsc_adc_sel_t adc_sel;
102 uint8_t adc_chn;
103 uint32_t adc_offset;
104 } vsc_adc_config_t;
105
106 /**
107 * @brief vsc config structure
108 */
109 typedef struct {
110 vsc_data_opr_mode_t opr_0;
111 vsc_data_opr_mode_t opr_1;
112 vsc_data_opr_mode_t opr_2;
113 vsc_data_opr_mode_t opr_3;
114 } vsc_data_opr_config_t;
115
116 /**
117 * @brief vsc config structure
118 */
119 typedef struct {
120 vsc_phase_mode_t phase_mode;
121 uint8_t a_data_cnt;
122 uint8_t b_data_cnt;
123 uint8_t c_data_cnt;
124 vsc_data_opr_config_t a_data_opr_config;
125 vsc_data_opr_config_t b_data_opr_config;
126 vsc_data_opr_config_t c_data_opr_config;
127 vsc_adc_config_t a_adc_config;
128 vsc_adc_config_t b_adc_config;
129 vsc_adc_config_t c_adc_config;
130 vsc_pos_cap_mode_t pos_cap_mode;
131 uint16_t pole_pairs;
132 } vsc_config_t;
133
134
135 #ifdef __cplusplus
136 extern "C" {
137 #endif
138
139 /**
140 * @brief vsc enable or disable
141 *
142 * @param[in] vsc VSC base address
143 * @param[in] enable true-enable, false-disable
144 */
vsc_set_enable(VSC_Type * vsc,bool enable)145 static inline void vsc_set_enable(VSC_Type *vsc, bool enable)
146 {
147 if (enable) {
148 vsc->ABC_MODE |= VSC_ABC_MODE_ENABLE_VSC_MASK;
149 } else {
150 vsc->ABC_MODE &= ~VSC_ABC_MODE_ENABLE_VSC_MASK;
151 }
152 }
153
154 /**
155 * @brief vsc config position capture mode
156 *
157 * @param[in] vsc VSC base address
158 * @param[in] mode @ref vsc_pos_cap_mode_t
159 */
vsc_config_pos_capture_mode(VSC_Type * vsc,vsc_pos_cap_mode_t mode)160 static inline void vsc_config_pos_capture_mode(VSC_Type *vsc, vsc_pos_cap_mode_t mode)
161 {
162 vsc->TIMELOCK = (vsc->TIMELOCK & ~(VSC_TIMELOCK_POSITION_CAPTURE_MODE_MASK))
163 | VSC_TIMELOCK_POSITION_CAPTURE_MODE_SET(mode);
164 }
165
166 /**
167 * @brief vsc config adc timestamp
168 *
169 * @param[in] vsc VSC base address
170 * @param[in] select timestamp select from value a/b/c. @ref vsc_timestamp_sel_t
171 * @param[in] num timestamp use which number index of @ref vsc_timestamp_sel_t used.
172 */
vsc_config_adc_timestamp(VSC_Type * vsc,vsc_timestamp_sel_t select,uint8_t num)173 static inline void vsc_config_adc_timestamp(VSC_Type *vsc, vsc_timestamp_sel_t select, uint8_t num)
174 {
175 vsc->TIMELOCK = (vsc->TIMELOCK & ~(VSC_TIMELOCK_ADC_TIMESTAMP_SEL_MASK | VSC_TIMELOCK_VALUE_COUNTER_SEL_MASK))
176 | VSC_TIMELOCK_ADC_TIMESTAMP_SEL_SET(select) | VSC_TIMELOCK_VALUE_COUNTER_SEL_SET(num);
177 }
178
179 /**
180 * @brief vsc set irq enable or disable
181 * @param [in] vsc CLC base address
182 * @param [in] irq_mask irq mask, @ref vsc_irq_mask_t
183 * @param [in] enable enable or disable
184 * @arg true enable
185 * @arg false disable
186 */
vsc_set_irq_enable(VSC_Type * vsc,uint32_t irq_mask,bool enable)187 static inline void vsc_set_irq_enable(VSC_Type *vsc, uint32_t irq_mask, bool enable)
188 {
189 if (enable) {
190 vsc->IRQ_ENABLE |= irq_mask;
191 } else {
192 vsc->IRQ_ENABLE &= ~irq_mask;
193 }
194 }
195
196 /**
197 * @brief vsc get irq status
198 * @param [in] vsc CLC base address
199
200 * @retval irq status.
201 */
vsc_get_irq_status(VSC_Type * vsc)202 static inline uint32_t vsc_get_irq_status(VSC_Type *vsc)
203 {
204 return vsc->IRQ_STATUS;
205 }
206
207 /**
208 * @brief vsc clear irq status
209 * @param [in] vsc CLC base address
210 * @param [in] irq_mask irq mask, @ref vsc_irq_mask_t
211 */
vsc_clear_irq_status(VSC_Type * vsc,uint32_t irq_mask)212 static inline void vsc_clear_irq_status(VSC_Type *vsc, uint32_t irq_mask)
213 {
214 vsc->IRQ_STATUS = irq_mask;
215 }
216
217 /**
218 * @brief vsc check irq request flag
219 * @param [in] vsc CLC base address
220 * @param [in] irq_mask irq mask, @ref vsc_irq_mask_t
221
222 * @retval true-has irq req, false-no irq req.
223 */
vsc_get_irq_flag(VSC_Type * vsc,uint32_t irq_mask)224 static inline bool vsc_get_irq_flag(VSC_Type *vsc, uint32_t irq_mask)
225 {
226 return ((vsc->IRQ_STATUS & irq_mask) == irq_mask) ? true : false;
227 }
228
229 /**
230 * @brief vsc set adc wait cycles
231 * @param [in] vsc CLC base address
232 * @param [in] wait_cycle adc wait cycle for exception
233 */
vsc_set_adc_wait_cycle(VSC_Type * vsc,uint32_t wait_cycle)234 static inline void vsc_set_adc_wait_cycle(VSC_Type *vsc, uint32_t wait_cycle)
235 {
236 vsc->ADC_WAIT_CYCLE = VSC_ADC_WAIT_CYCLE_ADC_WAIT_CYCLE_SET(wait_cycle);
237 }
238
239 /**
240 * @brief vsc set position wait cycles
241 * @param [in] vsc CLC base address
242 * @param [in] wait_cycle position wait cycle for exception
243 */
vsc_set_pos_wait_cycle(VSC_Type * vsc,uint32_t wait_cycle)244 static inline void vsc_set_pos_wait_cycle(VSC_Type *vsc, uint32_t wait_cycle)
245 {
246 vsc->POS_WAIT_CYCLE = VSC_POS_WAIT_CYCLE_POS_WAIT_CYCLE_SET(wait_cycle);
247 }
248
249 /**
250 * @brief vsc set abc phase value tolerate
251 * @param [in] vsc CLC base address
252 * @param [in] tolerate value a/b/c total value tolerate
253 */
vsc_set_adc_tolerate(VSC_Type * vsc,uint32_t tolerate)254 static inline void vsc_set_adc_tolerate(VSC_Type *vsc, uint32_t tolerate)
255 {
256 vsc->ADC_PHASE_TOLERATE = VSC_ADC_PHASE_TOLERATE_ADC_PHASE_TOLERATE_SET(tolerate);
257 }
258
259 /**
260 * @brief vsc set position pole pairs
261 * @param [in] vsc CLC base address
262 * @param [in] pole_pairs pole pairs number
263 */
vsc_set_pos_pole_pairs(VSC_Type * vsc,uint32_t pole_pairs)264 static inline void vsc_set_pos_pole_pairs(VSC_Type *vsc, uint32_t pole_pairs)
265 {
266 vsc->POS_POLE = (vsc->POS_POLE & ~VSC_POS_POLE_POS_POLE_MASK) | VSC_POS_POLE_POS_POLE_SET(pole_pairs);
267 }
268
269 /**
270 * @brief vsc set software trigger in
271 * @param [in] vsc CLC base address
272 */
vsc_set_sw_trig_in(VSC_Type * vsc)273 static inline void vsc_set_sw_trig_in(VSC_Type *vsc)
274 {
275 vsc->TRIGGER_SW = VSC_TRIGGER_SW_TRIGGER_SW_MASK;
276 }
277
278 /**
279 * @brief vsc get d-axis value
280 * @param [in] vsc CLC base address
281 * @param [in] positive_seq true - positive order; false - reverse order
282 * @retval d-axis value
283 */
vsc_get_d_axis_value(VSC_Type * vsc,bool positive_seq)284 static inline int32_t vsc_get_d_axis_value(VSC_Type *vsc, bool positive_seq)
285 {
286 if (positive_seq) {
287 return (int32_t)vsc->ID_POSEDGE;
288 } else {
289 return (int32_t)vsc->ID_NEGEDGE;
290 }
291 }
292
293 /**
294 * @brief vsc get q-axis value
295 * @param [in] vsc CLC base address
296 * @param [in] positive_seq true - positive order; false - reverse order
297 * @retval q-axis value
298 */
vsc_get_q_axis_value(VSC_Type * vsc,bool positive_seq)299 static inline int32_t vsc_get_q_axis_value(VSC_Type *vsc, bool positive_seq)
300 {
301 if (positive_seq) {
302 return (int32_t)vsc->IQ_POSEDGE;
303 } else {
304 return (int32_t)vsc->IQ_NEGEDGE;
305 }
306 }
307
308 /**
309 * @brief vsc get alpha-axis value
310 * @param [in] vsc CLC base address
311 * @param [in] positive_seq true - positive order; false - reverse order
312 * @retval alpha-axis value
313 */
vsc_get_alpha_axis_value(VSC_Type * vsc,bool positive_seq)314 static inline int32_t vsc_get_alpha_axis_value(VSC_Type *vsc, bool positive_seq)
315 {
316 if (positive_seq) {
317 return (int32_t)vsc->ALPHA_POSEDGE;
318 } else {
319 return (int32_t)vsc->ALPHA_NEGEDGE;
320 }
321 }
322
323 /**
324 * @brief vsc get beta-axis value
325 * @param [in] vsc CLC base address
326 * @param [in] positive_seq true - positive order; false - reverse order
327 * @retval beta-axis value
328 */
vsc_get_beta_axis_value(VSC_Type * vsc,bool positive_seq)329 static inline int32_t vsc_get_beta_axis_value(VSC_Type *vsc, bool positive_seq)
330 {
331 if (positive_seq) {
332 return (int32_t)vsc->BETA_POSEDGE;
333 } else {
334 if (vsc->BETA_NEGEDGE == 0x80000000) {
335 return 0x7FFFFFFF;
336 } else {
337 return (int32_t)vsc->BETA_NEGEDGE;
338 }
339 }
340 }
341
342 /**
343 * @brief vsc get adc timestamp value
344 * @param [in] vsc CLC base address
345 * @retval adc timestamp value
346 */
vsc_get_adc_timestamp(VSC_Type * vsc)347 static inline uint32_t vsc_get_adc_timestamp(VSC_Type *vsc)
348 {
349 return vsc->TIMESTAMP_LOCKED;
350 }
351
352 /**
353 * @brief vsc get default config
354 *
355 * @param[in] vsc VSC base address
356 * @param[out] config vsc default config
357 */
358 void vsc_get_default_config(VSC_Type *vsc, vsc_config_t *config);
359
360 /**
361 * @brief vsc config initialization
362 *
363 * @param[in] vsc VSC base address
364 * @param[in] config vsc config struct
365 */
366 void vsc_config_init(VSC_Type *vsc, vsc_config_t *config);
367
368 /**
369 * @brief vsc software inject phase a/b/c value
370 *
371 * @param[in] vsc VSC base address
372 * @param[in] value_a phase a value
373 * @param[in] value_b phase b value
374 * @param[in] value_c phase c value
375 */
376 void vsc_sw_inject_abc_value(VSC_Type *vsc, int32_t value_a, int32_t value_b, int32_t value_c);
377
378 /**
379 * @brief vsc software inject position value
380 *
381 * @param[in] vsc VSC base address
382 * @param[in] pos position value
383 */
384 void vsc_sw_inject_pos_value(VSC_Type *vsc, uint32_t pos);
385
386
387 #ifdef __cplusplus
388 }
389 #endif
390 /**
391 * @}
392 */
393 #endif /* HPM_VSC_DRV_H */
394