1 /*
2  * Copyright 2021 MindMotion Microelectronics Co., Ltd.
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "hal_tim_adv.h"
9 
TIM_ADV_Init(TIM_ADV_Type * TIMx,TIM_ADV_Init_Type * init)10 bool TIM_ADV_Init(TIM_ADV_Type * TIMx, TIM_ADV_Init_Type * init)
11 {
12     uint32_t cr1 = TIMx->CR1 &~ ( TIM_ADV_CR1_OPM_MASK
13                                 | TIM_ADV_CR1_APRE_MASK
14                                 | TIM_ADV_CR1_CMS_MASK
15                                 | TIM_ADV_CR1_DIR_MASK
16                                 );
17     cr1 |= TIM_ADV_CR1_OPM(init->PeriodMode);
18     cr1 |= ((init->EnablePreloadPeriod) ? TIM_ADV_CR1_APRE_MASK: 0u);
19     switch ( init->CountMode )
20     {
21         case TIM_ADV_CountMode_Increasing:
22             break;
23         case TIM_ADV_CountMode_Decreasing:
24             cr1 |= TIM_ADV_CR1_DIR_MASK;
25             break;
26         case TIM_ADV_CountMode_CenterAligned1:
27             cr1 |= TIM_ADV_CR1_CMS(1u);
28             break;
29         case TIM_ADV_CountMode_CenterAligned2:
30             cr1 |= TIM_ADV_CR1_CMS(2u);
31             break;
32         case TIM_ADV_CountMode_CenterAligned3:
33             cr1 |= TIM_ADV_CR1_CMS(3u);
34             break;
35         default:
36             break;
37     }
38     TIMx->CR1 = cr1;
39     /* Check the vadility of StepFreqHz. */
40     if ( (init->StepFreqHz == 0u) || (init->StepFreqHz > init->ClockFreqHz) )
41     {
42         return false;
43     }
44     /* Calculate the prescaler. */
45     TIMx->PSC = init->ClockFreqHz / init->StepFreqHz - 1u;
46     TIMx->ARR = init->Period;
47     return true;
48 }
49 
TIM_ADV_Start(TIM_ADV_Type * TIMx)50 void TIM_ADV_Start(TIM_ADV_Type * TIMx)
51 {
52     TIMx->CR1 |= TIM_ADV_CR1_CEN_MASK;
53 }
54 
TIM_ADV_Stop(TIM_ADV_Type * TIMx)55 void TIM_ADV_Stop(TIM_ADV_Type * TIMx)
56 {
57     TIMx->CR1 &= ~TIM_ADV_CR1_CEN_MASK;
58 }
59 
TIM_ADV_GetCounterValue(TIM_ADV_Type * TIMx)60 uint32_t TIM_ADV_GetCounterValue(TIM_ADV_Type * TIMx)
61 {
62     return TIMx->CNT;
63 }
64 
TIM_ADV_ClearCounterValue(TIM_ADV_Type * TIMx)65 void TIM_ADV_ClearCounterValue(TIM_ADV_Type * TIMx)
66 {
67     TIMx->CNT = 0u;
68 }
69 
TIM_ADV_EnableInterrupts(TIM_ADV_Type * TIMx,uint32_t interrupts,bool enable)70 void TIM_ADV_EnableInterrupts(TIM_ADV_Type * TIMx, uint32_t interrupts, bool enable)
71 {
72     if (enable)
73     {
74         TIMx->DIER |= interrupts;
75     }
76     else
77     {
78         TIMx->DIER &= ~interrupts;
79     }
80 }
81 
TIM_ADV_EnableDMA(TIM_ADV_Type * TIMx,uint32_t dmas,bool enable)82 void TIM_ADV_EnableDMA(TIM_ADV_Type * TIMx, uint32_t dmas, bool enable)
83 {
84     if (enable)
85     {
86         TIMx->DIER |= dmas;
87     }
88     else
89     {
90         TIMx->DIER &= ~dmas;
91     }
92 }
93 
TIM_ADV_DoSwTrigger(TIM_ADV_Type * TIMx,uint32_t swtrgs)94 void TIM_ADV_DoSwTrigger(TIM_ADV_Type * TIMx, uint32_t swtrgs)
95 {
96     TIMx->EGR = swtrgs;
97 }
98 
TIM_ADV_GetInterruptStatus(TIM_ADV_Type * TIMx)99 uint32_t TIM_ADV_GetInterruptStatus(TIM_ADV_Type * TIMx)
100 {
101     return TIMx->SR;
102 }
103 
TIM_ADV_ClearInterruptStatus(TIM_ADV_Type * TIMx,uint32_t status)104 void TIM_ADV_ClearInterruptStatus(TIM_ADV_Type * TIMx, uint32_t status)
105 {
106     TIMx->SR &= ~status;
107 }
108 
109 /*******************************/
_TIM_ADV_WriteChannelCtrlReg(TIM_ADV_Type * TIMx,uint32_t channel,uint32_t regval)110 static void _TIM_ADV_WriteChannelCtrlReg(TIM_ADV_Type * TIMx, uint32_t channel, uint32_t regval)
111 {
112     switch (channel)
113     {
114     case TIM_ADV_CHN_1:
115         TIMx->CCMR1 = (TIMx->CCMR1 & ~(0xFF)) | (regval & 0xFF);
116         break;
117     case TIM_ADV_CHN_2:
118         TIMx->CCMR1 = (TIMx->CCMR1 & ~(0xFF00)) | ((regval & 0xFF) << 8u);
119         break;
120     case TIM_ADV_CHN_3:
121         TIMx->CCMR2 = (TIMx->CCMR2 & ~(0xFF)) | (regval & 0xFF);
122         break;
123     case TIM_ADV_CHN_4:
124         TIMx->CCMR2 = (TIMx->CCMR2 & ~(0xFF00)) | ((regval & 0xFF) << 8u);
125         break;
126     default:
127         break;
128     }
129 }
130 
_TIM_ADV_EnableChannel5OutputCompare(TIM_ADV_Type * TIMx,TIM_ADV_OutputCompareConf_Type * conf)131 static void _TIM_ADV_EnableChannel5OutputCompare(TIM_ADV_Type * TIMx, TIM_ADV_OutputCompareConf_Type * conf)
132 {
133     TIMx->CCMR3 = ( TIMx->CCMR3 & ~(0xFF) )
134                 | ( (conf->EnableFastOutput) ? TIM_ADV_CCMR3_OC5FE_MASK : 0u )
135                 | ( (conf->EnablePreLoadChannelValue) ? TIM_ADV_CCMR3_OC5PE_MASK : 0u )
136                 | TIM_ADV_CCMR3_OC5M(conf->RefOutMode);
137     TIM_ADV_PutChannelValue(TIMx, TIM_ADV_CHN_5, conf->ChannelValue);
138 }
139 
TIM_ADV_EnableOutputCompare(TIM_ADV_Type * TIMx,uint32_t channel,TIM_ADV_OutputCompareConf_Type * conf)140 void TIM_ADV_EnableOutputCompare(TIM_ADV_Type * TIMx, uint32_t channel, TIM_ADV_OutputCompareConf_Type * conf)
141 {
142     if ( channel == TIM_ADV_CHN_5)
143     {
144         _TIM_ADV_EnableChannel5OutputCompare(TIMx, conf);
145     }
146     else
147     {
148         uint32_t regval = TIM_ADV_CCMR1_CC1S(TIM_ADV_ChannelIOMode_Out) /* output compare mode. */
149                 | ( (conf->EnableFastOutput) ? TIM_ADV_CCMR1_OC1FE_MASK : 0u ) /* fast output. */
150                 | ( (conf->EnablePreLoadChannelValue) ? TIM_ADV_CCMR1_OC1PE_MASK : 0u) /* preload of channel value. */
151                 | TIM_ADV_CCMR1_OC1M(conf->RefOutMode) /* output compare comparison mode. */
152                 | ( (conf->ClearRefOutOnExtTrigger) ? TIM_ADV_CCMR1_OC1CE_MASK : 0u) /* external trigger clear ref. */
153                 ;
154 
155         _TIM_ADV_WriteChannelCtrlReg(TIMx, channel, regval);
156 
157         TIM_ADV_PutChannelValue(TIMx, channel, conf->ChannelValue);
158 
159         switch (conf->PinPolarity)
160         {
161             case TIM_ADV_PinPolarity_Disable:
162                 TIMx->CCER &= ~( ( TIM_ADV_CCER_CC1E_MASK
163                                  | TIM_ADV_CCER_CC1NE_MASK
164                                  ) << (channel<<2u) ); /* Disable both channel. */
165                 break;
166 
167             case TIM_ADV_PinPolarity_Rising:
168                 TIMx->CCER = ( ( TIMx->CCER & ~(0xF << (channel<<2u)) )
169                            | ( ( TIM_ADV_CCER_CC1E_MASK ) /* Enable the pin output / input. */
170                            | ( ( conf->COMPPinPolarity == TIM_ADV_PinPolarity_Falling) ? TIM_ADV_CCER_CC1NP_MASK : 0u )
171                            | ( ( conf->COMPPinPolarity != TIM_ADV_PinPolarity_Disable) ? TIM_ADV_CCER_CC1NE_MASK : 0u )
172                            ) << (channel<<2u));
173                 break;
174 
175             case TIM_ADV_PinPolarity_Falling:
176                 TIMx->CCER = ( TIMx->CCER & ~(0xF << (channel<<2u)) )
177                            | (( TIM_ADV_CCER_CC1E_MASK /* Enable the pin output / input. */
178                            |    TIM_ADV_CCER_CC1P_MASK /* Set output active polarity. */
179                            | ( ( conf->COMPPinPolarity == TIM_ADV_PinPolarity_Falling) ? TIM_ADV_CCER_CC1NP_MASK : 0u )
180                            | ( ( conf->COMPPinPolarity != TIM_ADV_PinPolarity_Disable) ? TIM_ADV_CCER_CC1NE_MASK : 0u )
181                            ) << (channel<<2u));
182                 break;
183 
184             default:
185                 break;
186         }
187     }
188 }
189 
TIM_ADV_EnableOutputCompareSwitch(TIM_ADV_Type * TIMx,bool enable)190 void TIM_ADV_EnableOutputCompareSwitch(TIM_ADV_Type * TIMx, bool enable)
191 {
192     if (enable)
193     {
194         TIMx->BDTR |= TIM_ADV_BDTR_MOE_MASK;
195     }
196     else
197     {
198         TIMx->BDTR &= ~ TIM_ADV_BDTR_MOE_MASK;
199     }
200 }
201 
TIM_ADV_EnableInputCapture(TIM_ADV_Type * TIMx,uint32_t channel,TIM_ADV_InputCaptureConf_Type * conf)202 void TIM_ADV_EnableInputCapture(TIM_ADV_Type * TIMx, uint32_t channel, TIM_ADV_InputCaptureConf_Type * conf)
203 {
204     uint32_t regval = TIM_ADV_CCMR1_CC1S(TIM_ADV_ChannelIOMode_In) /* input capture mode. */
205                     | TIM_ADV_CCMR1_IC1PSC(conf->InDiv)
206                     | TIM_ADV_CCMR1_IC1F(conf->InFilter)
207                     ;
208 
209     _TIM_ADV_WriteChannelCtrlReg(TIMx, channel, regval);
210 
211     switch (conf->PinPolarity)
212     {
213         case TIM_ADV_PinPolarity_Disable:
214             TIMx->CCER &= ~(TIM_ADV_CCER_CC1E_MASK << (channel<<2u));
215             break;
216         case TIM_ADV_PinPolarity_Rising:
217             TIMx->CCER = (TIMx->CCER & ~(0xF << (channel<<2u)) )
218                        | (( TIM_ADV_CCER_CC1E_MASK /* Enable the pin output / input */
219                        ) << (channel<<2u) );
220             break;
221         case TIM_ADV_PinPolarity_Falling:
222             TIMx->CCER = ( TIMx->CCER & ~(0xF << (channel<<2u)) )
223                        | (( TIM_ADV_CCER_CC1E_MASK /* Enable the pin output / input */
224                        |    TIM_ADV_CCER_CC1P_MASK /* Set active input edge. */
225                        ) << (channel<<2u) );
226             break;
227         case TIM_ADV_PinPolarity_RisingOrFalling:
228             TIMx->CCER = ( TIMx->CCER & ~(0xF << (channel<<2u)) )
229                        | (( TIM_ADV_CCER_CC1E_MASK /* Enable the pin output / input */
230                        |    TIM_ADV_CCER_CC1P_MASK /* Set active input edge. */
231                        |    TIM_ADV_CCER_CC1NP_MASK
232                        ) << (channel<<2u) );
233             break;
234         default:
235             break;
236     }
237 }
238 
TIM_ADV_GetChannelValue(TIM_ADV_Type * TIMx,uint32_t channel)239 uint16_t TIM_ADV_GetChannelValue(TIM_ADV_Type * TIMx, uint32_t channel)
240 {
241     return TIMx->CCR[channel];
242 }
243 
TIM_ADV_PutChannelValue(TIM_ADV_Type * TIMx,uint32_t channel,uint16_t value)244 void TIM_ADV_PutChannelValue(TIM_ADV_Type * TIMx, uint32_t channel, uint16_t value)
245 {
246     if ( channel == TIM_ADV_CHN_5 )
247     {
248         TIMx->CCR5 = value;
249     }
250     else
251     {
252         TIMx->CCR[channel] = value;
253     }
254 }
255 
TIM_ADV_EnableDeadArea(TIM_ADV_Type * TIMx,TIM_ADV_DeadAreaConf_Type * conf)256 void TIM_ADV_EnableDeadArea(TIM_ADV_Type * TIMx, TIM_ADV_DeadAreaConf_Type * conf)
257 {
258     TIMx->CR1 = ( TIMx->CR1 &~ TIM_ADV_CR1_CKD_MASK )
259               | ( TIM_ADV_CR1_CKD(conf->StepFreqHz) ); /* set the frequncy ratio. */
260     TIMx->BDTR = ( TIMx->BDTR &~ TIM_ADV_BDTR_DTG_MASK )
261                | ( TIM_ADV_BDTR_DTG(conf->DeadAreaCoef) ); /* set the coefficient. */
262 }
263 
TIM_ADV_EnableMasterMode(TIM_ADV_Type * TIMx,TIM_ADV_MasterModeConf_Type * conf)264 void TIM_ADV_EnableMasterMode(TIM_ADV_Type * TIMx, TIM_ADV_MasterModeConf_Type * conf)
265 {
266     TIMx->CR2 = ( TIMx->CR2 &~ TIM_ADV_CR2_MMS_MASK )
267               | ( TIM_ADV_CR2_MMS(conf->Out) ); /* Set master mode output. */
268 
269     uint32_t smcr = TIMx->SMCR &~ TIM_ADV_SMCR_MSM_MASK;
270     if (conf->EnableSync) /* synchronize with slave timers. */
271     {
272         smcr |= TIM_ADV_SMCR_MSM_MASK;
273     }
274     TIMx->SMCR = smcr;
275 }
276 
TIM_ADV_EnableSlaveMode(TIM_ADV_Type * TIMx,TIM_ADV_SlaveModeConf_Type * conf)277 void TIM_ADV_EnableSlaveMode(TIM_ADV_Type * TIMx, TIM_ADV_SlaveModeConf_Type * conf)
278 {
279     if ( conf->Resp != TIM_ADV_SlaveResp_Disable )
280     {
281         TIMx->SMCR = ( TIMx->SMCR &~ ( TIM_ADV_SMCR_TS_MASK
282                                      | TIM_ADV_SMCR_SMS_MASK
283                                      ) )
284                    | TIM_ADV_SMCR_TS(conf->In) /* set input trigger source. */
285                    | TIM_ADV_SMCR_SMS(conf->Resp); /* set response to the source */
286     }
287     else
288     {
289         TIMx->SMCR &= ~ TIM_ADV_SMCR_SMS_MASK;
290     }
291 }
292 
TIM_ADV_EnableExtTriggerIn(TIM_ADV_Type * TIMx,TIM_ADV_ExtTriggerInConf_Type * conf)293 void TIM_ADV_EnableExtTriggerIn(TIM_ADV_Type * TIMx, TIM_ADV_ExtTriggerInConf_Type * conf)
294 {
295     uint32_t smcr = TIMx->SMCR &~ ( TIM_ADV_SMCR_ETPS_MASK
296                                   | TIM_ADV_SMCR_ETF_MASK
297                                   | TIM_ADV_SMCR_ECE_MASK
298                                   | TIM_ADV_SMCR_ETP_MASK
299                                   );
300     switch (conf->PinPolarity)
301     {
302         case TIM_ADV_PinPolarity_Disable:
303             break;
304         case TIM_ADV_PinPolarity_Rising:
305             smcr |= TIM_ADV_SMCR_ECE_MASK; /* enable external trigger input. */
306             break;
307         case TIM_ADV_PinPolarity_Falling:
308             smcr |= TIM_ADV_SMCR_ETP_MASK; /* falling edge active. */
309             smcr |= TIM_ADV_SMCR_ECE_MASK; /* enable external trigger input. */
310             break;
311         default:
312             break;
313     }
314     smcr |= TIM_ADV_SMCR_ETPS( conf->InDiv ); /* division to the input external trigger. */
315     smcr |= TIM_ADV_SMCR_ETF( conf->InFilter ); /* set filter. */
316     TIMx->SMCR = smcr;
317 }
318 
TIM_ADV_EnableDMABurst(TIM_ADV_Type * TIMx,TIM_ADV_DMABurstConf_Type * conf)319 uint32_t TIM_ADV_EnableDMABurst(TIM_ADV_Type * TIMx, TIM_ADV_DMABurstConf_Type * conf)
320 {
321     TIMx->DCR = TIM_ADV_DCR_DBA(conf->BaseAddr) | TIM_ADV_DCR_DBL(conf->Length);
322     return (uint32_t)(&(TIMx->DMAR));
323 }
324 
TIM_ADV_GetEncoder(TIM_ADV_Type * TIMx,uint32_t * value)325 TIM_ADV_EncoderDirection_Type TIM_ADV_GetEncoder(TIM_ADV_Type * TIMx, uint32_t * value)
326 {
327     if (value)
328     {
329         * value = TIM_ADV_GetCounterValue(TIMx);
330     }
331 
332     if ( (TIMx->CR1 & TIM_ADV_CR1_DIR_MASK) != 0u )
333     {
334         return TIM_ADV_EncoderDirection_Backward;
335     }
336     else
337     {
338         return TIM_ADV_EncoderDirection_Forward;
339     }
340 }
341 
TIM_ADV_SetRepCounter(TIM_ADV_Type * TIMx,uint8_t value)342 void TIM_ADV_SetRepCounter(TIM_ADV_Type * TIMx, uint8_t value)
343 {
344     TIMx->RCR = TIM_ADV_RCR_REP(value);
345 }
346 
TIM_ADV_GetRepCounterValue(TIM_ADV_Type * TIMx)347 uint8_t TIM_ADV_GetRepCounterValue(TIM_ADV_Type * TIMx)
348 {
349     return TIMx->RCR >> TIM_ADV_RCR_REPCNT_SHIFT;
350 }
351 
TIM_ADV_EnableIdleOut(TIM_ADV_Type * TIMx,uint32_t channel,TIM_ADV_IdleOut_Type * conf)352 void TIM_ADV_EnableIdleOut(TIM_ADV_Type * TIMx, uint32_t channel, TIM_ADV_IdleOut_Type * conf)
353 {
354     uint32_t cr2 = TIMx->CR2 & ~ ( ( TIM_ADV_CR2_OIS1_MASK
355                                    | TIM_ADV_CR2_OIS1N_MASK
356                                    ) << ( channel << 1u )
357                                  );
358     if ( conf->PinPolarity == TIM_ADV_PinPolarity_Rising )
359     {
360         cr2 |= ( TIM_ADV_CR2_OIS1_MASK << ( channel << 1u ) );
361     }
362     if ( conf->COMPPinPolarity == TIM_ADV_PinPolarity_Rising )
363     {
364         cr2 |= ( TIM_ADV_CR2_OIS1N_MASK << ( channel << 1u ) );
365     }
366     TIMx->CR2 = cr2;
367 }
368 
TIM_ADV_EnableLock(TIM_ADV_Type * TIMx,TIM_ADV_LockLevel_Type lock)369 void TIM_ADV_EnableLock(TIM_ADV_Type * TIMx, TIM_ADV_LockLevel_Type lock)
370 {
371     TIMx->BDTR = ( TIMx->BDTR & ~ TIM_ADV_BDTR_LOCK_MASK )
372                  | TIM_ADV_BDTR_LOCK(lock);
373 }
374 
TIM_ADV_EnableBreakIn(TIM_ADV_Type * TIMx,TIM_ADV_BreakIn_Type * conf)375 void TIM_ADV_EnableBreakIn(TIM_ADV_Type * TIMx, TIM_ADV_BreakIn_Type * conf)
376 {
377     uint32_t bdtr = TIMx->BDTR &~ ( TIM_ADV_BDTR_BKE_MASK
378                                   | TIM_ADV_BDTR_BKP_MASK
379                                   | TIM_ADV_BDTR_AOE_MASK
380                                   | TIM_ADV_BDTR_DOE_MASK
381                                   );
382     switch (conf->PinPolarity)
383     {
384         case TIM_ADV_PinPolarity_Disable:
385             break;
386         case TIM_ADV_PinPolarity_Rising:
387             bdtr |= ( TIM_ADV_BDTR_BKE_MASK
388                     | TIM_ADV_BDTR_BKP_MASK
389                     | ( conf->AutoSwitchOutput ? TIM_ADV_BDTR_AOE_MASK : 0u )
390                     | ( conf->DirectIdleOutput ? TIM_ADV_BDTR_DOE_MASK : 0u )
391                     );
392             break;
393         case TIM_ADV_PinPolarity_Falling:
394             bdtr |= ( TIM_ADV_BDTR_BKE_MASK
395                     | ( conf->AutoSwitchOutput ? TIM_ADV_BDTR_AOE_MASK : 0u )
396                     | ( conf->DirectIdleOutput ? TIM_ADV_BDTR_DOE_MASK : 0u )
397                     );
398             break;
399         default:
400             break;
401     }
402 }
403 
TIM_ADV_EnablePWMShift(TIM_ADV_Type * TIMx,uint32_t channel,uint16_t value)404 void TIM_ADV_EnablePWMShift(TIM_ADV_Type * TIMx, uint32_t channel, uint16_t value)
405 {
406     if ( value == TIM_ADV_GetChannelValue(TIMx, channel) )
407     {
408         TIMx->PDER &= ~( TIM_ADV_PDER_CCR1SHIFTEN_MASK << channel );
409     }
410     else
411     {
412         TIMx->PDER |= ( TIM_ADV_PDER_CCR1SHIFTEN_MASK << channel );
413         TIMx->CCRFALL[channel] = value;
414     }
415 }
416 
417 /* EOF. */
418 
419