1 // Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 /*******************************************************************************
16 * NOTICE
17 * The hal is not public api, don't use in application code.
18 * See readme.md in hal/include/hal/readme.md
19 ******************************************************************************/
20
21 // The LL layer for ESP32 MCPWM register operations
22
23 #pragma once
24
25 #include "soc/soc_caps.h"
26 #include <soc/mcpwm_periph.h>
27 #include "soc/mcpwm_periph.h"
28 #include "hal/mcpwm_types.h"
29 #include "hal/hal_defs.h"
30
31 #include "esp_types.h"
32
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36
37 /// Get the address of peripheral registers
38 #define MCPWM_LL_GET_HW(ID) (((ID)==0)? &MCPWM0: &MCPWM1)
39
40
41 /********************* Global *******************/
42 /**
43 * Initialize common registers.
44 *
45 * @param mcpwm Address of the MCPWM peripheral registers.
46 */
mcpwm_ll_init(mcpwm_dev_t * mcpwm)47 static inline void mcpwm_ll_init(mcpwm_dev_t *mcpwm)
48 {
49 mcpwm->update_cfg.global_up_en = 1;
50 mcpwm->update_cfg.global_force_up = 1;
51 mcpwm->update_cfg.global_force_up = 0;
52 }
53
54 /**
55 * Set the prescale of the PWM main clock to the input clock.
56 *
57 * Input clock is 160MHz, PWM main clock cycle = 6.25ns*(prescale + 1).
58 *
59 * @param mcpwm Address of the MCPWM peripheral registers.
60 * @param prescale Prescale factor, 0-255.
61 */
mcpwm_ll_set_clock_prescale(mcpwm_dev_t * mcpwm,int prescale)62 static inline void mcpwm_ll_set_clock_prescale(mcpwm_dev_t *mcpwm, int prescale)
63 {
64 mcpwm->clk_cfg.prescale = prescale;
65 }
66
67 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_LL_INTR_CAP0, MCPWM_CAP0_INT_RAW);
68 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_LL_INTR_CAP1, MCPWM_CAP1_INT_RAW);
69 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_LL_INTR_CAP2, MCPWM_CAP2_INT_RAW);
70
71 /**
72 * Get raw interrupt status.
73 *
74 * @param mcpwm Address of the MCPWM peripheral registers.
75 * @return The triggered interrupts, ORed by active interrupts.
76 */
mcpwm_ll_get_intr(mcpwm_dev_t * mcpwm)77 static inline mcpwm_intr_t mcpwm_ll_get_intr(mcpwm_dev_t *mcpwm)
78 {
79 return mcpwm->int_raw.val;
80 }
81
82 /**
83 * Clear the interrupts.
84 *
85 * @param mcpwm Address of the MCPWM peripheral registers.
86 * @param intr Bitwise ORed interrupts to clear.
87 */
mcpwm_ll_clear_intr(mcpwm_dev_t * mcpwm,mcpwm_intr_t intr)88 static inline void mcpwm_ll_clear_intr(mcpwm_dev_t* mcpwm, mcpwm_intr_t intr)
89 {
90 mcpwm->int_clr.val = intr;
91 }
92
93 /********************* Timer *******************/
94 /**
95 * Set the prescale of the Timer_x clock to the PWM main clock.
96 *
97 * Timer clock frequency = PWM main clock frequency/(prescale + 1).
98 *
99 * @param mcpwm Address of the MCPWM peripheral registers.
100 * @param timer The timer to set the prescale, 0-2.
101 * @param prescale Prescale factor, 0-255.
102 */
mcpwm_ll_timer_set_prescale(mcpwm_dev_t * mcpwm,int timer,uint32_t prescale)103 static inline void mcpwm_ll_timer_set_prescale(mcpwm_dev_t* mcpwm, int timer, uint32_t prescale)
104 {
105 mcpwm->timer[timer].period.prescale = prescale;
106 }
107
108
109 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_UP_COUNTER, 1);
110 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_DOWN_COUNTER, 2);
111 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_UP_DOWN_COUNTER, 3);
112
113 /**
114 * Set the counting mode for the PWM timer.
115 *
116 * @param mcpwm Address of the MCPWM peripheral registers.
117 * @param timer The timer to change counting mode, 0-2.
118 * @param mode Counting mode to use.
119 */
mcpwm_ll_timer_set_count_mode(mcpwm_dev_t * mcpwm,int timer,mcpwm_counter_type_t mode)120 static inline void mcpwm_ll_timer_set_count_mode(mcpwm_dev_t *mcpwm, int timer, mcpwm_counter_type_t mode)
121 {
122 mcpwm->timer[timer].mode.mode = mode;
123 }
124
125 /**
126 * Start a timer.
127 *
128 * @param mcpwm Address of the MCPWM peripheral registers.
129 * @param timer The timer to start, 0-2.
130 */
mcpwm_ll_timer_start(mcpwm_dev_t * mcpwm,int timer)131 static inline void mcpwm_ll_timer_start(mcpwm_dev_t *mcpwm, int timer)
132 {
133 mcpwm->timer[timer].mode.start = 2;
134 }
135
136 /**
137 * Stop a timer.
138 *
139 * @param mcpwm Address of the MCPWM peripheral registers.
140 * @param timer The timer to stop, 0-2.
141 */
mcpwm_ll_timer_stop(mcpwm_dev_t * mcpwm,int timer)142 static inline void mcpwm_ll_timer_stop(mcpwm_dev_t *mcpwm, int timer)
143 {
144 mcpwm->timer[timer].mode.start = 0;
145 }
146
147 /**
148 * Set the overflow period of a timer.
149 *
150 * The overflow rate will be Frequency of timer / period.
151 *
152 * @param mcpwm Address of the MCPWM peripheral registers.
153 * @param timer The timer to set period, 0-2.
154 * @param period Total timer count of each period, 0-65535.
155 */
mcpwm_ll_timer_set_period(mcpwm_dev_t * mcpwm,int timer,uint32_t period)156 static inline void mcpwm_ll_timer_set_period(mcpwm_dev_t *mcpwm, int timer, uint32_t period)
157 {
158
159 mcpwm->timer[timer].period.period = period - 1;
160 mcpwm->timer[timer].period.upmethod = 0;
161 }
162
163 /**
164 * Get the period setting of a timer.
165 *
166 * @param mcpwm Address of the MCPWM peripheral registers.
167 * @param timer The timer to get the period, 0-2.
168 * @return Period setting value.
169 */
mcpwm_ll_timer_get_period(mcpwm_dev_t * mcpwm,int timer)170 static inline uint32_t mcpwm_ll_timer_get_period(mcpwm_dev_t *mcpwm, int timer)
171 {
172 return mcpwm->timer[timer].period.period + 1;
173 }
174
175 /********************* Sync *******************/
176 /**
177 * Enable the synchronization feature for a timer.
178 *
179 * @param mcpwm Address of the MCPWM peripheral registers.
180 * @param timer Timer to set, 0-2.
181 * @param enable true to enable, otherwise false.
182 */
mcpwm_ll_sync_enable(mcpwm_dev_t * mcpwm,int timer,bool enable)183 static inline void mcpwm_ll_sync_enable(mcpwm_dev_t *mcpwm, int timer, bool enable)
184 {
185 if (enable) {
186 mcpwm->timer[timer].sync.out_sel = 0;
187 mcpwm->timer[timer].sync.in_en = 1;
188 } else {
189 mcpwm->timer[timer].sync.in_en = 0;
190 }
191 }
192
193 /**
194 * Set the phase (counter value) to reload when the sync signal triggers.
195 *
196 * @param mcpwm Address of the MCPWM peripheral registers.
197 * @param timer Timer to set, 0-2.
198 * @param reload_val The reloaded value.
199 */
mcpwm_ll_sync_set_phase(mcpwm_dev_t * mcpwm,int timer,uint32_t reload_val)200 static inline void mcpwm_ll_sync_set_phase(mcpwm_dev_t *mcpwm, int timer, uint32_t reload_val)
201 {
202 mcpwm->timer[timer].sync.timer_phase = reload_val;
203 }
204
205 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_SELECT_SYNC0, 4);
206 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_SELECT_SYNC1, 5);
207 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_SELECT_SYNC2, 6);
208 /**
209 * Set the sync signal source for a timer.
210 *
211 * @param mcpwm Address of the MCPWM peripheral registers.
212 * @param timer The timer to set, 0-2.
213 * @param sync_sig The synchronization signal to use.
214 */
mcpwm_ll_sync_set_input(mcpwm_dev_t * mcpwm,int timer,mcpwm_sync_signal_t sync_sig)215 static inline void mcpwm_ll_sync_set_input(mcpwm_dev_t *mcpwm, int timer, mcpwm_sync_signal_t sync_sig)
216 {
217 if (timer == 0) {
218 mcpwm->timer_synci_cfg.t0_in_sel = sync_sig;
219 } else if (timer == 1) {
220 mcpwm->timer_synci_cfg.t1_in_sel = sync_sig;
221 } else { //MCPWM_TIMER_2
222 mcpwm->timer_synci_cfg.t2_in_sel = sync_sig;
223 }
224 }
225
226 /********************* Comparator *******************/
227 /**
228 * Select a timer for the specified operator to use.
229 *
230 * @param mcpwm Address of the MCPWM peripheral registers.
231 * @param op The operator to choose timer, 0-2.
232 * @param timer The timer to use, 0-2.
233 */
mcpwm_ll_operator_select_timer(mcpwm_dev_t * mcpwm,int op,int timer)234 static inline void mcpwm_ll_operator_select_timer(mcpwm_dev_t *mcpwm, int op, int timer)
235 {
236 if (op == 0) {
237 mcpwm->timer_sel.operator0_sel = timer;
238 } else if (op == 1) {
239 mcpwm->timer_sel.operator1_sel = timer;
240 } else {
241 mcpwm->timer_sel.operator2_sel = timer;
242 }
243 }
244
245 /**
246 * Set the update method of the compare value of a timer
247 *
248 * @param mcpwm Address of the MCPWM peripheral registers.
249 * @param op Operator to set, 0-2.
250 */
mcpwm_ll_operator_set_compare_upmethod(mcpwm_dev_t * mcpwm,int op)251 static inline void mcpwm_ll_operator_set_compare_upmethod(mcpwm_dev_t *mcpwm, int op)
252 {
253 mcpwm->channel[op].cmpr_cfg.a_upmethod = BIT(0);
254 mcpwm->channel[op].cmpr_cfg.b_upmethod = BIT(0);
255 }
256
257 /**
258 * Get one of the compare value of a timer.
259 *
260 * @param mcpwm Address of the MCPWM peripheral registers.
261 * @param op The operator to get, 0-2.
262 * @param cmp_n Comparer id to get, 0-1.
263 * @return The set compare value.
264 */
mcpwm_ll_operator_get_compare(mcpwm_dev_t * mcpwm,int op,int cmp_n)265 static inline uint32_t mcpwm_ll_operator_get_compare(mcpwm_dev_t *mcpwm, int op, int cmp_n)
266 {
267 return (mcpwm->channel[op].cmpr_value[cmp_n].cmpr_val);
268 }
269
270 /**
271 * Set one of the compare value of a timer.
272 *
273 * @param mcpwm Address of the MCPWM peripheral registers.
274 * @param op The operator to set, 0-2.
275 * @param cmp_n The comparer to set value, 0-1.
276 * @param compare The compare value, 0-65535.
277 */
mcpwm_ll_operator_set_compare(mcpwm_dev_t * mcpwm,int op,int cmp_n,uint32_t compare)278 static inline void mcpwm_ll_operator_set_compare(mcpwm_dev_t *mcpwm, int op, int cmp_n, uint32_t compare)
279 {
280 mcpwm->channel[op].cmpr_value[cmp_n].cmpr_val = compare;
281 }
282
283 /********************* Generator *******************/
284
285 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_ACTION_NO_CHANGE, 0);
286 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_ACTION_FORCE_LOW, 1);
287 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_ACTION_FORCE_HIGH, 2);
288 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_ACTION_TOGGLE, 3);
289 /**
290 * Set the action will be taken by a operator when its timer counts to zero.
291 *
292 * @param mcpwm Address of the MCPWM peripheral registers.
293 * @param op The operator to set action, 0-2.
294 * @param gen One generator of the operator to take the action, 0-1.
295 * @param action Action to take.
296 */
mcpwm_ll_gen_set_zero_action(mcpwm_dev_t * mcpwm,int op,int gen,mcpwm_output_action_t action)297 static inline void mcpwm_ll_gen_set_zero_action(mcpwm_dev_t *mcpwm, int op, int gen, mcpwm_output_action_t action)
298 {
299 mcpwm->channel[op].generator[gen].utez = action;
300 mcpwm->channel[op].generator[gen].dtez = action;
301 }
302
303 /**
304 * Set the action will be taken by a operator when its timer counts to the period value.
305 *
306 * @param mcpwm Address of the MCPWM peripheral registers.
307 * @param op The operator to set action, 0-2.
308 * @param gen One generator of the operator to take the action, 0-1.
309 * @param action Action to take.
310 */
mcpwm_ll_gen_set_period_action(mcpwm_dev_t * mcpwm,int op,int gen,mcpwm_output_action_t action)311 static inline void mcpwm_ll_gen_set_period_action(mcpwm_dev_t *mcpwm, int op, int gen, mcpwm_output_action_t action)
312 {
313 mcpwm->channel[op].generator[gen].utep = action;
314 mcpwm->channel[op].generator[gen].dtep = action;
315 }
316
317 /**
318 * Set the action will be taken by a operator when its timer counts to the compare value.
319 *
320 * @param mcpwm Address of the MCPWM peripheral registers.
321 * @param op The operator to set action, 0-2.
322 * @param gen One generator of the operator to take the action, 0-1.
323 * @param cmp_n The comparer to use.
324 * @param up_action The action to take when the counter is counting up.
325 * @param down_action The action to take when the counter is counting down.
326 */
mcpwm_ll_gen_set_cmp_action(mcpwm_dev_t * mcpwm,int op,int gen,int cmp_n,mcpwm_output_action_t up_action,mcpwm_output_action_t down_action)327 static inline void mcpwm_ll_gen_set_cmp_action(mcpwm_dev_t *mcpwm, int op, int gen,
328 int cmp_n, mcpwm_output_action_t up_action, mcpwm_output_action_t down_action)
329 {
330 if (cmp_n == 0) {
331 mcpwm->channel[op].generator[gen].utea = up_action;
332 mcpwm->channel[op].generator[gen].dtea = down_action;
333 } else {
334 mcpwm->channel[op].generator[gen].uteb = up_action;
335 mcpwm->channel[op].generator[gen].dteb = down_action;
336 }
337 }
338
339 /********************* Fault *******************/
340 /**
341 * Enable the fault detection feature for an input signal.
342 *
343 * @param mcpwm Address of the MCPWM peripheral registers.
344 * @param fault_sig One of the signals to select, 0-2.
345 * @param level The active level of the fault-detection signal.
346 */
mcpwm_ll_fault_enable(mcpwm_dev_t * mcpwm,int fault_sig,bool level)347 static inline void mcpwm_ll_fault_enable(mcpwm_dev_t *mcpwm, int fault_sig, bool level)
348 {
349 if (fault_sig == 0) {
350 mcpwm->fault_detect.f0_en = 1;
351 mcpwm->fault_detect.f0_pole = level;
352 } else if (fault_sig == 1) {
353 mcpwm->fault_detect.f1_en = 1;
354 mcpwm->fault_detect.f1_pole = level;
355 } else { //MCPWM_SELECT_F2
356 mcpwm->fault_detect.f2_en = 1;
357 mcpwm->fault_detect.f2_pole = level;
358 }
359 }
360
361 /**
362 * Disable the fault detection of an input signal.
363 * @param mcpwm Address of the MCPWM peripheral registers.
364 * @param fault_sig The signal to disable, 0-2.
365 */
mcpwm_ll_fault_disable(mcpwm_dev_t * mcpwm,int fault_sig)366 static inline void mcpwm_ll_fault_disable(mcpwm_dev_t *mcpwm, int fault_sig)
367 {
368 if (fault_sig == 0) {
369 mcpwm->fault_detect.f0_en = 0;
370 } else if (fault_sig == 1) {
371 mcpwm->fault_detect.f1_en = 0;
372 } else { //MCPWM_SELECT_F2
373 mcpwm->fault_detect.f2_en = 0;
374 }
375 }
376
377 /**
378 * Clear the oneshot fault status of an operator.
379 *
380 * @param mcpwm Address of the MCPWM peripheral registers.
381 * @param op The operator to clear, 0-2.
382 */
mcpwm_ll_fault_clear_ost(mcpwm_dev_t * mcpwm,int op)383 static inline void mcpwm_ll_fault_clear_ost(mcpwm_dev_t *mcpwm, int op)
384 {
385 mcpwm->channel[op].tz_cfg1.clr_ost = 1;
386 mcpwm->channel[op].tz_cfg1.clr_ost = 0;
387 }
388
389 /**
390 * Use the oneshot mode to handle the fault when it occurs
391 *
392 * @param mcpwm Address of the MCPWM peripheral registers.
393 * @param op The operator to handle the fault signal, 0-2.
394 * @param signal The fault signal to set, 0-2.
395 * @param enable true to enable oneshot, otherwise false.
396 */
mcpwm_ll_fault_oneshot_enable_signal(mcpwm_dev_t * mcpwm,int op,int signal,bool enable)397 static inline void mcpwm_ll_fault_oneshot_enable_signal(mcpwm_dev_t *mcpwm, int op, int signal, bool enable)
398 {
399 if (signal == 0) {
400 mcpwm->channel[op].tz_cfg0.f0_ost = enable;
401 } else if (signal == 1) {
402 mcpwm->channel[op].tz_cfg0.f1_ost = enable;
403 } else { //MCPWM_SELECT_F2
404 mcpwm->channel[op].tz_cfg0.f2_ost = enable;
405 }
406 }
407
408 /**
409 * @brief Get the oneshot enabled status of the operator
410 *
411 * @param mcpwm Address of the MCPWM peripheral registers.
412 * @param op The operator to check, 0-2.
413 * @param signal The fault signal to get, 0-2.
414 */
mcpwm_ll_fault_oneshot_signal_enabled(mcpwm_dev_t * mcpwm,int op,int signal)415 static inline bool mcpwm_ll_fault_oneshot_signal_enabled(mcpwm_dev_t *mcpwm, int op, int signal)
416 {
417 if (signal == 0) {
418 return mcpwm->channel[op].tz_cfg0.f0_ost;
419 } else if (signal == 1) {
420 return mcpwm->channel[op].tz_cfg0.f1_ost;
421 } else { //MCPWM_SELECT_F2
422 return mcpwm->channel[op].tz_cfg0.f2_ost;
423 }
424 }
425
426 /**
427 * Use the CBC (cycle-by-cycle) mode to handle the fault when it occurs.
428 *
429 * @param mcpwm Address of the MCPWM peripheral registers.
430 * @param op The operator to handle the fault signal, 0-2.
431 * @param signal The fault signal to set, 0-2.
432 * @param enable true to enable cbc mode, otherwise false.
433 */
mcpwm_ll_fault_cbc_enable_signal(mcpwm_dev_t * mcpwm,int op,int signal,bool enable)434 static inline void mcpwm_ll_fault_cbc_enable_signal(mcpwm_dev_t *mcpwm, int op, int signal, bool enable)
435 {
436 if (signal == 0) {
437 mcpwm->channel[op].tz_cfg0.f0_cbc = enable;
438 } else if (signal == 1) {
439 mcpwm->channel[op].tz_cfg0.f1_cbc = enable;
440 } else { //MCPWM_SELECT_F2
441 mcpwm->channel[op].tz_cfg0.f2_cbc = enable;
442 }
443 }
444
445 /**
446 * Set the action that will be taken when the fault is handled by oneshot.
447 *
448 * @param mcpwm Address of the MCPWM peripheral registers.
449 * @param op The operator to handle the fault signal, 0-2.
450 * @param gen The generator to take the action, 0-1.
451 * @param up_action Action to take when fault happens when counting up.
452 * @param down_action Action to take when fault happens when counting down.
453 */
mcpwm_ll_fault_set_oneshot_action(mcpwm_dev_t * mcpwm,int op,int gen,mcpwm_output_action_t up_action,mcpwm_output_action_t down_action)454 static inline void mcpwm_ll_fault_set_oneshot_action(mcpwm_dev_t *mcpwm, int op, int gen,
455 mcpwm_output_action_t up_action, mcpwm_output_action_t down_action)
456 {
457 if (gen == 0) {
458 mcpwm->channel[op].tz_cfg0.a_ost_u = up_action;
459 mcpwm->channel[op].tz_cfg0.a_ost_d = down_action;
460 } else {
461 mcpwm->channel[op].tz_cfg0.b_ost_u = up_action;
462 mcpwm->channel[op].tz_cfg0.b_ost_d = down_action;
463 }
464 }
465
466 /**
467 * Set the action that will be taken when the fault is handled cycle by cycle.
468 *
469 * @param mcpwm Address of the MCPWM peripheral registers.
470 * @param op The operator to handle the fault signal, 0-2.
471 * @param gen The generator to take the action, 0-1.
472 * @param up_action Action to take when fault happens when counting up.
473 * @param down_action Action to take when fault happens when counting down.
474 */
mcpwm_ll_fault_set_cyc_action(mcpwm_dev_t * mcpwm,int op,int gen,mcpwm_output_action_t up_action,mcpwm_output_action_t down_action)475 static inline void mcpwm_ll_fault_set_cyc_action(mcpwm_dev_t *mcpwm, int op, int gen,
476 mcpwm_output_action_t up_action, mcpwm_output_action_t down_action)
477 {
478 mcpwm->channel[op].tz_cfg1.cbcpulse = BIT(0); //immediately
479 if (gen == 0) {
480 mcpwm->channel[op].tz_cfg0.a_cbc_u = up_action;
481 mcpwm->channel[op].tz_cfg0.a_cbc_d = down_action;
482 } else {
483 mcpwm->channel[op].tz_cfg0.b_cbc_u = up_action;
484 mcpwm->channel[op].tz_cfg0.b_cbc_d = down_action;
485 }
486 }
487
488 /********************* Dead Zone (deadtime) *******************/
489 /**
490 * Initialize the dead zone feature.
491 *
492 * @param mcpwm Address of the MCPWM peripheral registers.
493 * @param op The operator to initialize, 0-2.
494 */
mcpwm_ll_deadtime_init(mcpwm_dev_t * mcpwm,int op)495 static inline void mcpwm_ll_deadtime_init(mcpwm_dev_t *mcpwm, int op)
496 {
497 mcpwm->channel[op].db_cfg.fed_upmethod = BIT(0);
498 mcpwm->channel[op].db_cfg.red_upmethod = BIT(0);
499 mcpwm->channel[op].db_cfg.clk_sel = 0;
500 }
501
502 /**
503 * Set the output dead zone mode applying to the outputs of a timer.
504 *
505 * If the desired internal connection is not provided, you can write your own inside this function.
506 *
507 * @param mcpwm Address of the MCPWM peripheral registers.
508 * @param op The operator to set, 0-2.
509 * @param mode Dead zone mode to use.
510 */
mcpwm_ll_set_deadtime_mode(mcpwm_dev_t * mcpwm,int op,mcpwm_deadtime_type_t mode)511 static inline void mcpwm_ll_set_deadtime_mode(mcpwm_dev_t *mcpwm,
512 int op, mcpwm_deadtime_type_t mode)
513 {
514 #define MCPWM_LL_DEADTIME_REG_MASK (MCPWM_DT0_DEB_MODE_M | MCPWM_DT0_A_OUTSWAP_M | MCPWM_DT0_B_OUTSWAP_M | \
515 MCPWM_DT0_RED_INSEL_M | MCPWM_DT0_FED_INSEL_M | MCPWM_DT0_RED_OUTINVERT_M | MCPWM_DT0_FED_OUTINVERT_M | \
516 MCPWM_DT0_A_OUTBYPASS_M | MCPWM_DT0_B_OUTBYPASS_M)
517
518 static uint32_t deadtime_mode_settings[MCPWM_DEADTIME_TYPE_MAX] = {
519 [MCPWM_BYPASS_RED] = 0b010010000 << MCPWM_DT0_DEB_MODE_S,
520 [MCPWM_BYPASS_FED] = 0b100000000 << MCPWM_DT0_DEB_MODE_S,
521 [MCPWM_ACTIVE_HIGH_MODE] = 0b000010000 << MCPWM_DT0_DEB_MODE_S,
522 [MCPWM_ACTIVE_LOW_MODE] = 0b001110000 << MCPWM_DT0_DEB_MODE_S,
523 [MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE] = 0b001010000 << MCPWM_DT0_DEB_MODE_S,
524 [MCPWM_ACTIVE_LOW_COMPLIMENT_MODE] = 0b000101000 << MCPWM_DT0_DEB_MODE_S,
525 [MCPWM_ACTIVE_RED_FED_FROM_PWMXA] = 0b000000011 << MCPWM_DT0_DEB_MODE_S,
526 [MCPWM_ACTIVE_RED_FED_FROM_PWMXB] = 0b000001011 << MCPWM_DT0_DEB_MODE_S,
527 [MCPWM_DEADTIME_BYPASS] = 0b110000000 << MCPWM_DT0_DEB_MODE_S,
528 };
529 mcpwm->channel[op].db_cfg.val =
530 (mcpwm->channel[op].db_cfg.val & (~MCPWM_LL_DEADTIME_REG_MASK)) | deadtime_mode_settings[mode];
531
532 #undef MCPWM_LL_DEADTIME_REG_MASK
533 }
534
535 /**
536 * Set the delay of the falling edge on the output.
537 *
538 * @param mcpwm Address of the MCPWM peripheral registers.
539 * @param op The operator to set, 0-2.
540 * @param fed Falling delay, by PWM main clock.
541 */
mcpwm_ll_deadtime_set_falling_delay(mcpwm_dev_t * mcpwm,int op,uint32_t fed)542 static inline void mcpwm_ll_deadtime_set_falling_delay(mcpwm_dev_t *mcpwm, int op, uint32_t fed)
543 {
544 mcpwm->channel[op].db_fed_cfg.fed = fed;
545 }
546
547 /**
548 * Set the delay of the rising edge on the output.
549 *
550 * @param mcpwm Address of the MCPWM peripheral registers.
551 * @param op The operator to set, 0-2.
552 * @param fed Rising delay, by PWM main clock.
553 */
mcpwm_ll_deadtime_set_rising_delay(mcpwm_dev_t * mcpwm,int op,uint32_t red)554 static inline void mcpwm_ll_deadtime_set_rising_delay(mcpwm_dev_t *mcpwm, int op, uint32_t red)
555 {
556 mcpwm->channel[op].db_red_cfg.red = red;
557 }
558
559 /**
560 * Disable (bypass) the dead zone feature.
561 *
562 * @param mcpwm Address of the MCPWM peripheral registers.
563 * @param op The operator to set, 0-2.
564 */
mcpwm_ll_deadtime_bypass(mcpwm_dev_t * mcpwm,int op)565 static inline void mcpwm_ll_deadtime_bypass(mcpwm_dev_t *mcpwm, int op)
566 {
567 mcpwm_ll_set_deadtime_mode(mcpwm, op, MCPWM_DEADTIME_BYPASS);
568 }
569
570 /********************* Carrier *******************/
571 /**
572 * Initialize the carrier feature.
573 *
574 * @param mcpwm Address of the MCPWM peripheral registers.
575 * @param op The operator to set, 0-2.
576 */
mcpwm_ll_carrier_init(mcpwm_dev_t * mcpwm,int op)577 static inline void mcpwm_ll_carrier_init(mcpwm_dev_t *mcpwm, int op)
578 {
579 mcpwm->channel[op].carrier_cfg.in_invert = 0;
580 }
581
582 /**
583 * Enable the carrier feature for a timer.
584 *
585 * @param mcpwm Address of the MCPWM peripheral registers.
586 * @param op The operator to set, 0-2.
587 * @param enable true to enable, otherwise false.
588 */
mcpwm_ll_carrier_enable(mcpwm_dev_t * mcpwm,int op,bool enable)589 static inline void mcpwm_ll_carrier_enable(mcpwm_dev_t *mcpwm, int op, bool enable)
590 {
591 mcpwm->channel[op].carrier_cfg.en = enable;
592 }
593
594 /**
595 * Set the prescale of the carrier timer.
596 *
597 * The carrier period will be Frequency of PWM main clock/(carrier_period+1).
598 *
599 * @param mcpwm Address of the MCPWM peripheral registers.
600 * @param op The operator to set, 0-2.
601 * @param carrier_period The prescale of the carrier clock, 0-15.
602 */
mcpwm_ll_carrier_set_prescale(mcpwm_dev_t * mcpwm,int op,uint8_t carrier_period)603 static inline void mcpwm_ll_carrier_set_prescale(mcpwm_dev_t *mcpwm, int op, uint8_t carrier_period)
604 {
605 mcpwm->channel[op].carrier_cfg.prescale = carrier_period;
606 }
607
608 /**
609 * Set the duty rate of the carrier.
610 *
611 * @param mcpwm Address of the MCPWM peripheral registers.
612 * @param op The operator to set, 0-2.
613 * @param carrier_duty Duty rate will be (carrier_duty/8)*100%. 0-7.
614 */
mcpwm_ll_carrier_set_duty(mcpwm_dev_t * mcpwm,int op,uint8_t carrier_duty)615 static inline void mcpwm_ll_carrier_set_duty(mcpwm_dev_t *mcpwm, int op, uint8_t carrier_duty)
616 {
617 mcpwm->channel[op].carrier_cfg.duty = carrier_duty;
618 }
619
620 /**
621 * Invert output of the carrier.
622 *
623 * @param mcpwm Address of the MCPWM peripheral registers.
624 * @param op The operator to set, 0-2.
625 * @param invert true to invert, otherwise false.
626 */
mcpwm_ll_carrier_out_invert(mcpwm_dev_t * mcpwm,int op,bool invert)627 static inline void mcpwm_ll_carrier_out_invert(mcpwm_dev_t *mcpwm, int op, bool invert)
628 {
629 mcpwm->channel[op].carrier_cfg.out_invert = invert;
630 }
631
632 /**
633 * Set the oneshot pulse width of the carrier.
634 *
635 * @param mcpwm Address of the MCPWM peripheral registers.
636 * @param op The operator to set, 0-2.
637 * @param pulse_width The width of the oneshot pulse, by carrier period. 0 to disable the oneshot pulse.
638 */
mcpwm_ll_carrier_set_oneshot_width(mcpwm_dev_t * mcpwm,int op,uint8_t pulse_width)639 static inline void mcpwm_ll_carrier_set_oneshot_width(mcpwm_dev_t *mcpwm, int op, uint8_t pulse_width)
640 {
641 mcpwm->channel[op].carrier_cfg.oshtwth = pulse_width;
642 }
643
644 /********************* Capture *******************/
645 /**
646 * Enable the capture feature for a signal
647 *
648 * @param mcpwm Address of the MCPWM peripheral registers.
649 * @param cap_sig Signal to enable, 0-2.
650 * @param enable true to enable, otherwise false.
651 */
mcpwm_ll_capture_enable(mcpwm_dev_t * mcpwm,int cap_sig,int enable)652 static inline void mcpwm_ll_capture_enable(mcpwm_dev_t *mcpwm, int cap_sig, int enable)
653 {
654 if (enable) {
655 mcpwm->cap_timer_cfg.timer_en = 1;
656 mcpwm->cap_cfg_ch[cap_sig].en = 1;
657 } else {
658 mcpwm->cap_cfg_ch[cap_sig].en = 0;
659 }
660 }
661
662 /**
663 * Get the captured value.
664 *
665 * @param mcpwm Address of the MCPWM peripheral registers.
666 * @param cap_sig Of which signal to get the captured value.
667 * @return The captured value
668 */
mcpwm_ll_get_capture_val(mcpwm_dev_t * mcpwm,int cap_sig)669 static inline uint32_t mcpwm_ll_get_capture_val(mcpwm_dev_t *mcpwm, int cap_sig)
670 {
671 return mcpwm->cap_val_ch[cap_sig];
672 }
673
674 /**
675 * Get the set capture edge.
676 *
677 * @param mcpwm Address of the MCPWM peripheral registers.
678 * @param cap_sig Which signal the edge capture is applied.
679 * @return Capture signal edge: 1 - positive edge, 2 - negtive edge
680 */
mcpwm_ll_get_captured_edge(mcpwm_dev_t * mcpwm,int cap_sig)681 static inline mcpwm_capture_on_edge_t mcpwm_ll_get_captured_edge(mcpwm_dev_t *mcpwm, int cap_sig)
682 {
683 bool edge;
684 if (cap_sig == 0) {
685 edge = mcpwm->cap_status.cap0_edge;
686 } else if (cap_sig == 1) {
687 edge = mcpwm->cap_status.cap1_edge;
688 } else { //2
689 edge = mcpwm->cap_status.cap2_edge;
690 }
691 return (edge? MCPWM_NEG_EDGE: MCPWM_POS_EDGE);
692 }
693
694 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_NEG_EDGE, BIT(0));
695 STATIC_HAL_REG_CHECK(MCPWM, MCPWM_POS_EDGE, BIT(1));
696
697 /**
698 * Select the edge to capture.
699 *
700 * @param mcpwm Address of the MCPWM peripheral registers.
701 * @param cap_sig The signal to capture, 0-2.
702 * @param cap_edge The edge to capture, bitwise.
703 */
mcpwm_ll_capture_select_edge(mcpwm_dev_t * mcpwm,int cap_sig,mcpwm_capture_on_edge_t cap_edge)704 static inline void mcpwm_ll_capture_select_edge(mcpwm_dev_t *mcpwm, int cap_sig,
705 mcpwm_capture_on_edge_t cap_edge)
706 {
707 mcpwm->cap_cfg_ch[cap_sig].mode = cap_edge;
708 }
709
710 /**
711 * Set the prescale of the input signal to capture.
712 *
713 * @param mcpwm Address of the MCPWM peripheral registers.
714 * @param cap_sig The prescaled signal to capture, 0-2.
715 * @param prescale Prescal value, 0 to disable.
716 */
mcpwm_ll_capture_set_prescale(mcpwm_dev_t * mcpwm,int cap_sig,uint32_t prescale)717 static inline void mcpwm_ll_capture_set_prescale(mcpwm_dev_t *mcpwm, int cap_sig, uint32_t prescale)
718 {
719 mcpwm->cap_cfg_ch[cap_sig].prescale = prescale;
720 }
721
722 /**
723 * Utility function, get the `mcpwm_intr_t` interrupt enum of a specific capture signal.
724 *
725 * @param bit x for CAPx.
726 * @return the corresponding `mcpwm_intr_t`.
727 */
mcpwm_ll_get_cap_intr_def(int bit)728 static inline mcpwm_intr_t mcpwm_ll_get_cap_intr_def(int bit)
729 {
730 return BIT(bit+MCPWM_CAP0_INT_RAW_S);
731 }
732
733 #ifdef __cplusplus
734 }
735 #endif
736