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