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