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