1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18
19 /********************************************************************************************************
20 * @file pwm.h
21 *
22 * @brief This is the header file for B91
23 *
24 * @author Driver Group
25 *
26 *******************************************************************************************************/
27 #ifndef PWM_H_
28 #define PWM_H_
29 #include "gpio.h"
30 #include "dma.h"
31 #include "reg_include/register_b91.h"
32
33 #define get_pwmid(gpio) ((gpio==PWM_PWM0_PB4) ? 0 : ( \
34 (gpio==PWM_PWM0_PC0) ? 0 : ( \
35 (gpio==PWM_PWM0_PE3) ? 0 : ( \
36 (gpio==PWM_PWM0_N_PD0) ? 0 : ( \
37 (gpio==PWM_PWM1_PB5) ? 1 : ( \
38 (gpio==PWM_PWM1_PE1) ? 1 : ( \
39 (gpio==PWM_PWM1_N_PD1) ? 1 : ( \
40 (gpio==PWM_PWM2_PB7) ? 2 : ( \
41 (gpio==PWM_PWM2_PE2) ? 2 : ( \
42 (gpio==PWM_PWM2_N_PD2) ? 2 : ( \
43 (gpio==PWM_PWM2_N_PE6) ? 2 : ( \
44 (gpio==PWM_PWM3_PB1) ? 3 : ( \
45 (gpio==PWM_PWM3_PE0) ? 3 : ( \
46 (gpio==PWM_PWM3_N_PD3) ? 3 : ( \
47 (gpio==PWM_PWM3_N_PE7) ? 3 : ( \
48 (gpio==PWM_PWM4_PD7) ? 4 : ( \
49 (gpio==PWM_PWM4_PE4) ? 4 : ( \
50 (gpio==PWM_PWM4_N_PD4) ? 4 : ( \
51 (gpio==PWM_PWM5_PB0) ? 5 : ( \
52 (gpio==PWM_PWM5_PE5) ? 5 : ( \
53 (gpio==PWM_PWM5_N_PD5) ? 5 : 0 \
54 )))))))))))))))))))))
55
56 #define get_pwm_invert_val(gpio) ((gpio==PWM_PWM0_N_PD0) || \
57 (gpio==PWM_PWM1_N_PD1) || \
58 (gpio==PWM_PWM2_N_PD2) || \
59 (gpio==PWM_PWM2_N_PE6) || \
60 (gpio==PWM_PWM3_N_PD3) || \
61 (gpio==PWM_PWM3_N_PE7) || \
62 (gpio==PWM_PWM4_N_PD4) || \
63 (gpio==PWM_PWM5_N_PD5))
64
65 /**
66 * @brief enum variable, the number of PWM channels supported
67 */
68 typedef enum {
69 PWM0_ID = 0,
70 PWM1_ID,
71 PWM2_ID,
72 PWM3_ID,
73 PWM4_ID,
74 PWM5_ID,
75 }pwm_id_e;
76
77
78 /**
79 * @brief enum variable, represents the PWM mode.
80 */
81 typedef enum{
82 PWM_NORMAL_MODE = 0x00,
83 PWM_COUNT_MODE = 0x01,
84 PWM_IR_MODE = 0x03,
85 PWM_IR_FIFO_MODE = 0x07,
86 PWM_IR_DMA_FIFO_MODE = 0x0F,
87 }pwm_mode_e;
88
89
90 /**
91 * @brief enum variable, represents Selection of PWM pin.
92 */
93 typedef enum{
94 PWM_PWM0_PB4 = GPIO_PB4,
95 PWM_PWM0_PC0 = GPIO_PC0,
96 PWM_PWM0_PE3 = GPIO_PE3,
97 PWM_PWM0_N_PD0 = GPIO_PD0,
98
99 PWM_PWM1_PB5 = GPIO_PB5,
100 PWM_PWM1_PE1 = GPIO_PE1,
101 PWM_PWM1_N_PD1 = GPIO_PD1,
102
103 PWM_PWM2_PB7 = GPIO_PB7,
104 PWM_PWM2_PE2 = GPIO_PE2,
105 PWM_PWM2_N_PD2 = GPIO_PD2,
106 PWM_PWM2_N_PE6 = GPIO_PE6,
107
108 PWM_PWM3_PB1 = GPIO_PB1,
109 PWM_PWM3_PE0 = GPIO_PE0,
110 PWM_PWM3_N_PD3 = GPIO_PD3,
111 PWM_PWM3_N_PE7 = GPIO_PE7,
112
113 PWM_PWM4_PD7 = GPIO_PD7,
114 PWM_PWM4_PE4 = GPIO_PE4,
115 PWM_PWM4_N_PD4 = GPIO_PD4,
116
117 PWM_PWM5_PB0 = GPIO_PB0,
118 PWM_PWM5_PE5 = GPIO_PE5,
119 PWM_PWM5_N_PD5 = GPIO_PD5,
120 }pwm_pin_e;
121
122
123
124
125 /**
126 * @brief Select the 32K clock source of pwm.
127 */
128 typedef enum {
129
130 PWM_CLOCK_32K_CHN_PWM0 = 0x01,
131 PWM_CLOCK_32K_CHN_PWM1 = 0x02,
132 PWM_CLOCK_32K_CHN_PWM2 = 0x04,
133 PWM_CLOCK_32K_CHN_PWM3 = 0x08,
134 PWM_CLOCK_32K_CHN_PWM4 = 0x10,
135 PWM_CLOCK_32K_CHN_PWM5 = 0x20
136
137 }pwm_clk_32k_en_chn_e;
138
139
140
141
142
143
144 /**
145 * @brief This function servers to set pwm clock frequency, when pwm clock source is pclk.
146 * @param[in] pwm_clk_div - variable of the pwm clock.
147 * PWM frequency = System_clock / (pwm_clk_div+1).
148 * @return none.
149 */
pwm_set_clk(unsigned char pwm_clk_div)150 static inline void pwm_set_clk(unsigned char pwm_clk_div){
151
152 reg_pwm_clkdiv = pwm_clk_div;
153 }
154
155 /**
156 * @brief This function servers to set pwm clock source is 32K.
157 * If you use 32K as the PWM clock source, you can work in suspend mode.
158 * but the 32K clock source cannot be divided and can only work in continuous mode and counting mode
159 * @param[in] pwm_32K_en_chn - This variable is used to select the specific PWM channel.
160 * @return none.
161 */
162
pwm_32k_chn_en(pwm_clk_32k_en_chn_e pwm_32K_en_chn)163 static inline void pwm_32k_chn_en(pwm_clk_32k_en_chn_e pwm_32K_en_chn){
164
165 reg_pwm_mode32k |= pwm_32K_en_chn;
166
167 }
168
169
170 /**
171 * @brief This fuction servers to set pin as pwm0
172 * @param[in] pin - selected pin
173 * @return none.
174 */
175 void pwm_set_pin(pwm_pin_e pin);
176
177
178
179
180 /**
181 * @brief This function servers to set pwm count status(CMP) time.
182 * @param[in] id - variable of enum to select the pwm number.
183 * @param[in] tcmp - variable of the CMP.
184 * @return none.
185 */
pwm_set_tcmp(pwm_id_e id,unsigned short tcmp)186 static inline void pwm_set_tcmp(pwm_id_e id, unsigned short tcmp)
187 {
188 reg_pwm_cmp(id) = tcmp;
189 }
190
191
192 /**
193 * @brief This function servers to set pwm cycle time.
194 * @param[in] id - variable of enum to select the pwm number.
195 * @param[in] tmax - variable of the cycle time.
196 * @return none.
197 */
pwm_set_tmax(pwm_id_e id,unsigned short tmax)198 static inline void pwm_set_tmax(pwm_id_e id, unsigned short tmax){
199 reg_pwm_max(id) = tmax;
200 }
201
202 /*
203 *@brief This function servers to update the duty cycle in 32K
204 *@return none.
205 */
pwm_32k_chn_update_duty_cycle(void)206 static inline void pwm_32k_chn_update_duty_cycle(void){
207 reg_pwm_cnt5_l |= FLD_PWM_32K_DUTY_CYCLE_UPDATE;
208 }
209
210 /**
211 * @brief This function servers to start the pwm.
212 * @param[in] id - variable of enum to select the pwm number.
213 * @return none.
214 */
pwm_start(pwm_id_e id)215 static inline void pwm_start(pwm_id_e id){
216 if(PWM0_ID == id){
217 BM_SET(reg_pwm0_enable, BIT(0));
218 }
219 else{
220 BM_SET(reg_pwm_enable, BIT(id));
221 }
222 }
223
224
225 /**
226 * @brief This function servers to stop the pwm.
227 * @param[in] id - variable of enum to select the pwm number.
228 * @return none.
229 */
pwm_stop(pwm_id_e id)230 static inline void pwm_stop(pwm_id_e id){
231 if(PWM0_ID == id){
232 BM_CLR(reg_pwm0_enable, BIT(0));
233 }
234 else{
235 BM_CLR(reg_pwm_enable, BIT(id));
236 }
237 }
238
239
240 /**
241 * @brief This function servers to revert the PWMx.
242 * @param[in] id - variable of enum to select the pwm number.
243 * @return none.
244 */
pwm_invert_en(pwm_id_e id)245 static inline void pwm_invert_en(pwm_id_e id){
246 reg_pwm_invert |= BIT(id);
247 }
248
249
250 /**
251 * @brief This function servers to disable the PWM revert function.
252 * @param[in] id - variable of enum to select the pwm number.
253 * @return none.
254 */
pwm_invert_dis(pwm_id_e id)255 static inline void pwm_invert_dis(pwm_id_e id){
256 BM_CLR(reg_pwm_invert, BIT(id));
257 }
258
259
260 /**
261 * @brief This function servers to revert the PWMx_N.
262 * @param[in] id - variable of enum to select the pwm number.
263 * @return none.
264 */
pwm_n_invert_en(pwm_id_e id)265 static inline void pwm_n_invert_en(pwm_id_e id){
266 reg_pwm_n_invert |= BIT(id);
267 }
268
269
270 /**
271 * @brief This function servers to disable the PWM revert function.
272 * @param[in] id - variable of enum to select the pwm number.
273 * @return none.
274 */
pwm_n_invert_dis(pwm_id_e id)275 static inline void pwm_n_invert_dis(pwm_id_e id){
276 BM_CLR(reg_pwm_n_invert, BIT(id));
277 }
278
279
280 /**
281 * @brief This function servers to enable the pwm polarity.
282 * @param[in] id - variable of enum to select the pwm number.
283 * @return none.
284 */
pwm_set_polarity_en(pwm_id_e id)285 static inline void pwm_set_polarity_en(pwm_id_e id){
286 BM_SET(reg_pwm_pol, BIT(id));
287 }
288
289
290 /**
291 * @brief This function servers to disable the pwm polarity.
292 * @param[in] id - variable of enum to select the pwm number.
293 * @return none.
294 */
pwm_set_polarity_dis(pwm_id_e id)295 static inline void pwm_set_polarity_dis(pwm_id_e id){
296 BM_CLR(reg_pwm_pol, BIT(id));
297 }
298
299
300 /**
301 * @brief This function servers to enable the pwm interrupt.
302 * @param[in] mask - variable of enum to select the pwm interrupt source.
303 * @return none.
304 */
pwm_set_irq_mask(pwm_irq_e mask)305 static inline void pwm_set_irq_mask(pwm_irq_e mask){
306
307 if(mask==FLD_PWM0_IR_FIFO_IRQ)
308 {
309 BM_SET(reg_pwm_irq_mask(1), BIT(0));
310 }
311 else
312 {
313 BM_SET(reg_pwm_irq_mask(0), mask);
314 }
315
316 }
317
318
319 /**
320 * @brief This function servers to disable the pwm interrupt function.
321 * @param[in] mask - variable of enum to select the pwm interrupt source.
322 * @return none.
323 */
pwm_clr_irq_mask(pwm_irq_e mask)324 static inline void pwm_clr_irq_mask(pwm_irq_e mask){
325
326 if(mask==FLD_PWM0_IR_FIFO_IRQ)
327 {
328 BM_SET(reg_pwm_irq_mask(1), BIT(0));
329 }
330 else
331 {
332 BM_SET(reg_pwm_irq_mask(0), mask);
333 }
334
335 }
336
337
338 /**
339 * @brief This function servers to get the pwm interrupt status.
340 * @param[in] status - variable of enum to select the pwm interrupt source.
341 * @return none.
342 */
pwm_get_irq_status(pwm_irq_e status)343 static inline unsigned char pwm_get_irq_status(pwm_irq_e status){
344
345 if(status==FLD_PWM0_IR_FIFO_IRQ)
346 {
347 return (reg_pwm_irq_sta(1) & BIT(0));
348 }
349 else
350 {
351 return (reg_pwm_irq_sta(0) & status);
352 }
353
354 }
355
356
357 /**
358 * @brief This function servers to clear the pwm interrupt.When a PWM interrupt occurs, the corresponding interrupt flag bit needs to be cleared manually.
359 * @param[in] status - variable of enum to select the pwm interrupt source.
360 * @return none.
361 */
pwm_clr_irq_status(pwm_irq_e status)362 static inline void pwm_clr_irq_status(pwm_irq_e status){
363
364 if(status==FLD_PWM0_IR_FIFO_IRQ)
365 {
366 BM_SET(reg_pwm_irq_sta(1), BIT(0));
367 }
368 else
369 {
370 BM_SET(reg_pwm_irq_sta(0), status);
371 }
372
373 }
374
375
376 /**
377 * @brief This function servers to set pwm0 mode.
378 * @param[in] mode - variable of enum to indicates the pwm mode.
379 * @return none.
380 */
pwm_set_pwm0_mode(pwm_mode_e mode)381 static inline void pwm_set_pwm0_mode(pwm_mode_e mode){
382 reg_pwm0_mode = mode; //only PWM0 has count/IR/fifo IR mode
383 }
384
385
386 /**
387 * @brief This function servers to set pwm cycle time & count status.
388 * @param[in] max_tick - variable of the cycle time.
389 * @param[in] cmp_tick - variable of the CMP.
390 * @return none.
391 */
pwm_set_pwm0_tcmp_and_tmax_shadow(unsigned short max_tick,unsigned short cmp_tick)392 static inline void pwm_set_pwm0_tcmp_and_tmax_shadow(unsigned short max_tick, unsigned short cmp_tick)
393 {
394 reg_pwm_tcmp0_shadow = cmp_tick;
395 reg_pwm_tmax0_shadow = max_tick;
396 }
397
398
399 /**
400 * @brief This function servers to set the pwm0 pulse number.
401 * @param[in] pulse_num - variable of the pwm pulse number.The maximum bits is 14bits.
402 * @return none.
403 */
pwm_set_pwm0_pulse_num(unsigned short pulse_num)404 static inline void pwm_set_pwm0_pulse_num(unsigned short pulse_num){
405 reg_pwm0_pulse_num0 = pulse_num;
406 reg_pwm0_pulse_num1 = pulse_num>>8;
407 }
408
409
410 /**
411 * @brief This function serves to set trigger level of interrupt for IR FiFo mode
412 * @param[in] trig_level - FIFO num int trigger level.When fifo numbers is less than this value.It's will take effect.
413 * @return none
414 */
pwm_set_pwm0_ir_fifo_irq_trig_level(unsigned char trig_level)415 static inline void pwm_set_pwm0_ir_fifo_irq_trig_level(unsigned char trig_level)
416 {
417 reg_pwm_ir_fifo_irq_trig_level = trig_level;
418 }
419
420
421 /**
422 * @brief This function serves to clear data in fifo. Only when pwm is in not active mode,
423 * it is possible to clear data in fifo.
424 * @return none
425 */
pwm_clr_pwm0_ir_fifo(void)426 static inline void pwm_clr_pwm0_ir_fifo(void)
427 {
428 reg_pwm_ir_clr_fifo_data |= FLD_PWM0_IR_FIFO_CLR_DATA;
429 }
430
431
432 /**
433 * @brief This function serves to get the number of data in fifo.
434 * @return the number of data in fifo
435 */
pwm_get_pwm0_ir_fifo_data_num(void)436 static inline unsigned char pwm_get_pwm0_ir_fifo_data_num(void)//????TODO
437 {
438 return (reg_pwm_ir_fifo_data_status & FLD_PWM0_IR_FIFO_DATA_NUM);
439 }
440
441
442 /**
443 * @brief This function serves to determine whether data in fifo is empty.
444 * @return yes: 1 ,no: 0;
445 */
pwm_get_pwm0_ir_fifo_is_empty(void)446 static inline unsigned char pwm_get_pwm0_ir_fifo_is_empty(void)
447 {
448 return (reg_pwm_ir_fifo_data_status & FLD_PWM0_IR_FIFO_EMPTY);
449 }
450
451
452 /**
453 * @brief This function serves to determine whether data in fifo is full.
454 * @return yes: 1 ,no: 0;
455 */
pwm_get_pwm0_ir_fifo_is_full(void)456 static inline unsigned char pwm_get_pwm0_ir_fifo_is_full(void)
457 {
458 return (reg_pwm_ir_fifo_data_status&FLD_PWM0_IR_FIFO_FULL);
459 }
460
461
462 /**
463 * @brief This function serves to configure the pwm's dma wave form.
464 * @param[in] pulse_num - the number of pulse.
465 * @param[in] shadow_en - whether enable shadow mode.
466 * @param[in] carrier_en - must 1 or 0.
467 * @return none.
468 */
pwm_cal_pwm0_ir_fifo_cfg_data(unsigned short pulse_num,unsigned char shadow_en,unsigned char carrier_en)469 static inline unsigned short pwm_cal_pwm0_ir_fifo_cfg_data(unsigned short pulse_num, unsigned char shadow_en, unsigned char carrier_en)
470 {
471 return ( carrier_en<<15 | (shadow_en<<14) | (pulse_num & 0x3fff) );
472 }
473
474
475 /**
476 * @brief This function serves to write data into FiFo
477 * @param[in] pulse_num - the number of pulse
478 * @param[in] use_shadow - determine whether the configuration of shadow cmp and shadow max is used
479 * 1: use shadow, 0: not use
480 * @param[in] carrier_en - enable sending carrier, 1: enable, 0: disable
481 * @return none
482 */
pwm_set_pwm0_ir_fifo_cfg_data(unsigned short pulse_num,unsigned char use_shadow,unsigned char carrier_en)483 static inline void pwm_set_pwm0_ir_fifo_cfg_data(unsigned short pulse_num, unsigned char use_shadow, unsigned char carrier_en)
484 {
485 static unsigned char index=0;
486 unsigned short cfg_data = pwm_cal_pwm0_ir_fifo_cfg_data(pulse_num,use_shadow,carrier_en);
487 while(pwm_get_pwm0_ir_fifo_is_full());
488 reg_pwm_ir_fifo_dat(index) = cfg_data;
489 index++;
490 index&=0x01;
491 }
492
493
494 /**
495 * @brief This function servers to configure DMA channel and some configures.
496 * @param[in] chn - to select the DMA channel.
497 * @return none
498 */
499 void pwm_set_dma_config(dma_chn_e chn);
500
501
502 /**
503 * @brief This function servers to configure DMA channel address and length.
504 * @param[in] chn - to select the DMA channel.
505 * @param[in] buf_addr - the address where DMA need to get data from SRAM.
506 * @param[in] len - the length of data in SRAM.
507 * @return none
508 */
509 void pwm_set_dma_buf(dma_chn_e chn,unsigned int buf_addr,unsigned int len);
510
511
512 /**
513 * @brief This function servers to enable DMA channel.
514 * @param[in] chn - to select the DMA channel.
515 * @return none
516 */
517 void pwm_ir_dma_mode_start(dma_chn_e chn);
518
519
520
521 /**
522 * @brief This function servers to configure DMA head node.
523 * @param[in] chn - to select the DMA channel.
524 * @param[in] src_addr - to configure DMA source address.
525 * @param[in] data_len - to configure DMA length.
526 * @param[in] head_of_list - to configure the address of the next node configure.
527 * @return none
528 */
529 void pwm_set_dma_chain_llp(dma_chn_e chn,unsigned short * src_addr, unsigned int data_len,dma_chain_config_t * head_of_list);
530
531
532
533
534 /**
535 * @brief This function servers to configure DMA cycle chain node.
536 * @param[in] chn - to select the DMA channel.
537 * @param[in] config_addr - to servers to configure the address of the current node.
538 * @param[in] llponit - to configure the address of the next node configure.
539 * @param[in] src_addr - to configure DMA source address.
540 * @param[in] data_len - to configure DMA length.
541 * @return none
542 */
543 void pwm_set_tx_dma_add_list_element(dma_chn_e chn,dma_chain_config_t *config_addr,dma_chain_config_t *llponit ,unsigned short * src_addr,unsigned int data_len);
544
545
546 /**
547 * @brief This function servers to disable pwm clock source 32K.
548 * If you use 32K as the PWM clock source, you can work in suspend mode.
549 * but the 32K clock source cannot be divided and can only work in continuous mode and counting mode
550 * @param[in] pwm_32K_en_chn - This variable is used to select the specific PWM channel.
551 * @return none.
552 */
553
pwm_32k_chn_dis(pwm_clk_32k_en_chn_e pwm_32K_en_chn)554 static inline void pwm_32k_chn_dis(pwm_clk_32k_en_chn_e pwm_32K_en_chn)
555 {
556 BM_CLR(reg_pwm_mode32k, pwm_32K_en_chn);
557 }
558
559
560 #endif
561
562
563
564
565
566