1#if defined(ARDUINO_ARCH_SILABS)
3#include <pinDefinitions.h>
10static CMU_Clock_TypeDef _getTimerClock(TIMER_TypeDef *timer) {
11#if defined(_CMU_HFCLKSEL_MASK) || defined(_CMU_CMD_HFCLKSEL_MASK)
12 CMU_Clock_TypeDef timerClock = cmuClock_HF;
13#elif defined(_CMU_SYSCLKCTRL_MASK)
14 CMU_Clock_TypeDef timerClock = cmuClock_SYSCLK;
16#error "Unknown root of clock tree"
19 switch ((uint32_t)timer) {
20#if defined(TIMER0_BASE)
22 timerClock = cmuClock_TIMER0;
25#if defined(TIMER1_BASE)
27 timerClock = cmuClock_TIMER1;
30#if defined(TIMER2_BASE)
32 timerClock = cmuClock_TIMER2;
35#if defined(TIMER3_BASE)
37 timerClock = cmuClock_TIMER3;
40#if defined(TIMER4_BASE)
42 timerClock = cmuClock_TIMER4;
45#if defined(TIMER5_BASE)
47 timerClock = cmuClock_TIMER5;
50#if defined(TIMER6_BASE)
52 timerClock = cmuClock_TIMER6;
55#if defined(WTIMER0_BASE)
57 timerClock = cmuClock_WTIMER0;
60#if defined(WTIMER1_BASE)
62 timerClock = cmuClock_WTIMER1;
65#if defined(WTIMER2_BASE)
67 timerClock = cmuClock_WTIMER2;
70#if defined(WTIMER3_BASE)
72 timerClock = cmuClock_WTIMER3;
82 EFR32PwmInstance *inst,
89 inst->h.timer = timer;
90 inst->h.port = getSilabsPortFromArduinoPin(pinToPinName(pin));
91 inst->h.pin = getSilabsPinFromArduinoPin(pinToPinName(pin));
92 inst->h.channel = channel;
96 EFR32PwmInstance *inst,
97 EFR32PwmConfig *config,
101 if (!inst || !config)
return;
104 CMU_Clock_TypeDef timerClock = _getTimerClock(inst->h.timer);
105 CMU_ClockEnable(timerClock,
true);
108 CMU_ClockEnable(cmuClock_GPIO,
true);
109 GPIO_PinModeSet((GPIO_Port_TypeDef)inst->h.port,
115 TIMER_InitCC_TypeDef initCC = TIMER_INITCC_DEFAULT;
116 initCC.mode = timerCCModePWM;
117 if (config->outInvert) initCC.outInvert =
true;
118 if (fn) fn(&initCC,
params);
120 TIMER_InitCC(inst->h.timer, inst->h.channel, &initCC);
122 volatile uint32_t *routeRegister = &GPIO->TIMERROUTE[TIMER_NUM(inst->h.timer)].CC0ROUTE;
123 routeRegister += inst->h.channel;
124 *routeRegister = (inst->h.port << _GPIO_TIMER_CC0ROUTE_PORT_SHIFT)
125 | (inst->h.pin << _GPIO_TIMER_CC0ROUTE_PIN_SHIFT);
128 uint32_t top = (CMU_ClockFreqGet(timerClock) / (config->frequency)) - 1U;
129 TIMER_TopSet(inst->h.timer, top);
132 TIMER_CompareSet(inst->h.timer, inst->h.channel, 0U);
136 EFR32PwmInstance *inst
142 volatile uint32_t *routeRegister = &GPIO->TIMERROUTE[TIMER_NUM(inst->h.timer)].CC0ROUTE;
143 routeRegister += inst->h.channel;
146 TIMER_Reset(inst->h.timer);
147 GPIO_PinModeSet((GPIO_Port_TypeDef)inst->h.port,
151 CMU_Clock_TypeDef timerClock = _getTimerClock(inst->h.timer);
152 CMU_ClockEnable(timerClock,
false);
156 EFR32PwmInstance *inst
159 GPIO->TIMERROUTE_SET[TIMER_NUM(inst->h.timer)].ROUTEEN = 1 << (inst->h.channel + _GPIO_TIMER_ROUTEEN_CC0PEN_SHIFT);
163 EFR32PwmInstance *inst
166 GPIO->TIMERROUTE_CLR[TIMER_NUM(inst->h.timer)].ROUTEEN = 1 << (inst->h.channel + _GPIO_TIMER_ROUTEEN_CC0PEN_SHIFT);
169void pwmHiSetDutyCycle(
170 EFR32PwmInstance *inst,
173 if (!inst || (percent > 100.0f))
return;
174 uint32_t top = TIMER_TopGet(inst->h.timer);
175 volatile bool outInvert = inst->h.timer->CC[inst->h.channel].CTRL & TIMER_CC_CTRL_OUTINV;
176 if (outInvert) percent = 100 - percent;
177 TIMER_CompareBufSet(inst->h.timer, inst->h.channel, (uint32_t) (top * percent) / 100);
180float pwmHiGetDutyCycle(
181 EFR32PwmInstance *inst
184 uint32_t top = TIMER_TopGet(inst->h.timer);
185 uint32_t compare = TIMER_CaptureGet(inst->h.timer, inst->h.channel);
186 volatile bool outInvert = inst->h.timer->CC[inst->h.channel].CTRL & TIMER_CC_CTRL_OUTINV;
187 float percent = (float)((compare * 100) / top);
188 return outInvert ? (100 - percent) : percent;
192 EFR32PwmInstance *inst,
196 inst->l.port = getSilabsPortFromArduinoPin(pinToPinName(pin));
197 inst->l.pin = getSilabsPinFromArduinoPin(pinToPinName(pin));
201 EFR32PwmInstance *inst
206 CMU_ClockEnable(cmuClock_GPIO,
true);
207 GPIO_PinModeSet((GPIO_Port_TypeDef)inst->l.port,
212 volatile uint32_t *routeRegister = &GPIO->TIMERROUTE[TIMER_NUM(inst->h.timer)].CDTI0ROUTE;
213 routeRegister += inst->h.channel;
214 *routeRegister = (inst->l.port << _GPIO_TIMER_CDTI0ROUTE_PORT_SHIFT)
215 | (inst->l.pin << _GPIO_TIMER_CDTI0ROUTE_PIN_SHIFT);
219 EFR32PwmInstance *inst
225 volatile uint32_t *routeRegister = &GPIO->TIMERROUTE[TIMER_NUM(inst->h.timer)].CDTI0ROUTE;
226 routeRegister += inst->h.channel;
229 GPIO_PinModeSet((GPIO_Port_TypeDef)inst->l.port,
236 EFR32PwmInstance *inst
239 GPIO->TIMERROUTE_SET[TIMER_NUM(inst->h.timer)].ROUTEEN |= 1 << (inst->h.channel + _GPIO_TIMER_ROUTEEN_CCC0PEN_SHIFT);
243 EFR32PwmInstance *inst
246 GPIO->TIMERROUTE_CLR[TIMER_NUM(inst->h.timer)].ROUTEEN |= 1 << (inst->h.channel + _GPIO_TIMER_ROUTEEN_CCC0PEN_SHIFT);
250 EFR32PwmInstance *inst,
251 EFR32PwmConfig *config,
252 prevTimerInitCCFn fn,
255 if (!inst || !config)
return;
256 pwmHiInit(inst, config, fn,
params);
261 EFR32PwmInstance *inst
268void pwmOff(EFR32PwmInstance *inst) {
274void pwmOn(EFR32PwmInstance *inst) {
280void pwmStart(EFR32PwmInstance *inst, prevTimerInitFn fn,
void *
params) {
284 TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT;
285 if (fn) fn(&timerInit,
params);
286 TIMER_Init(inst->h.timer, &timerInit);
290 EFR32PwmInstance *inst,
291 EFR32PwmDeadTimeConfig *config
293 if (!inst || !config)
return;
296 CMU_Clock_TypeDef timerClock = _getTimerClock(inst->h.timer);
297 CMU_ClockEnable(timerClock,
true);
299 unsigned int dtiTime = (CMU_ClockFreqGet(timerClock) / 1e3f) * config->deadTimeNs / 1e6f;
300 if (dtiTime > 64) dtiTime = SILABBS_DEFAULT_DEAD_TIME;
302 TIMER_InitDTI_TypeDef initDTI = TIMER_INITDTI_DEFAULT;
303 initDTI.riseTime = dtiTime;
304 initDTI.fallTime = dtiTime;
305 initDTI.outputsEnableMask = config->outputMask;
307 TIMER_InitDTI(inst->h.timer, &initDTI);
GenericCurrentSenseParams * params