/***************************************************************************//** * @brief * Activate the hardware timer used to pace the 1 millisecond timer system. * * @details * Call this function whenever the HFPERCLK frequency is changed. * This function is initially called by HOST and DEVICE stack xxxx_Init() * functions. ******************************************************************************/ void USBTIMER_Init( void ) { uint32_t freq; TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT; TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT; freq = CMU_ClockFreqGet( cmuClock_HFPER ); ticksPrMs = ( freq + 500 ) / 1000; ticksPr1us = ( freq + 500000 ) / 1000000; ticksPr10us = ( freq + 50000 ) / 100000; ticksPr100us = ( freq + 5000 ) / 10000; timerCCInit.mode = timerCCModeCompare; CMU_ClockEnable( TIMER_CLK, true ); TIMER_TopSet( TIMER, 0xFFFF ); TIMER_InitCC( TIMER, 0, &timerCCInit ); TIMER_Init( TIMER, &timerInit ); #if ( NUM_QTIMERS > 0 ) TIMER_IntClear( TIMER, 0xFFFFFFFF ); TIMER_IntEnable( TIMER, TIMER_IEN_CC0 ); TIMER_CompareSet( TIMER, 0, TIMER_CounterGet( TIMER ) + ticksPrMs ); NVIC_ClearPendingIRQ( TIMER_IRQ ); NVIC_EnableIRQ( TIMER_IRQ ); #endif /* ( NUM_QTIMERS > 0 ) */ }
//================================================================================ // TIMER1_enter_DefaultMode_from_RESET //================================================================================ extern void TIMER1_enter_DefaultMode_from_RESET(void) { // $[TIMER1 initialization] TIMER_Init_TypeDef init = TIMER_INIT_DEFAULT; init.enable = 0;//初始化完成后不使能 init.debugRun = 0; init.dmaClrAct = 0; init.sync = 0; init.clkSel = timerClkSelHFPerClk;//HFPERCLK时钟 init.prescale = timerPrescale2; //2分频 init.fallAction = timerInputActionNone; init.riseAction = timerInputActionNone; init.mode = timerModeUp; init.quadModeX4 = 0; init.oneShot = 0; // [TIMER1 initialization]$ // $[TIMER1 CC0 init] TIMER_InitCC_TypeDef initCC0 = TIMER_INITCC_DEFAULT; initCC0.prsInput = false; initCC0.edge = timerEdgeBoth; initCC0.mode = timerCCModePWM; initCC0.eventCtrl = timerEventEveryEdge; initCC0.filter = 0; initCC0.cofoa = timerOutputActionNone; initCC0.cufoa = timerOutputActionNone; initCC0.cmoa = timerOutputActionToggle; initCC0.coist = 0; initCC0.outInvert = 0; TIMER_InitCC(TIMER1, 0, &initCC0); // [TIMER1 CC0 init]$ /* Route CC0 to location 0 (PC11) and enable pin */ TIMER1->ROUTE |= (TIMER_ROUTE_CC0PEN | TIMER_ROUTE_LOCATION_LOC0); /* Set Top Value */ TIMER_TopSet(TIMER0, 8000000/PWM_FREQ); //PWM频率设定,此处8M是HFPERCLK频率,待定 /* Set compare value starting at 0 - it will be incremented in the interrupt handler */ TIMER_CompareBufSet(TIMER0, 0, 0); /* Enable overflow interrupt */ TIMER_IntEnable(TIMER0, TIMER_IF_OF); /* Enable TIMER0 interrupt vector in NVIC */ NVIC_EnableIRQ(TIMER0_IRQn); TIMER_Init(TIMER1, &init); }
void fd_led_wake(void) { fd_lp55231_power_on(); fd_lp55231_wake(); CMU_ClockEnable(cmuClock_TIMER0, true); TIMER_InitCC_TypeDef timer_initcc = TIMER_INITCC_DEFAULT; timer_initcc.cmoa = timerOutputActionToggle; timer_initcc.mode = timerCCModePWM; TIMER_InitCC(TIMER0, /* channel */ 1, &timer_initcc); TIMER_InitCC(TIMER0, /* channel */ 2, &timer_initcc); TIMER0->ROUTE = TIMER_ROUTE_CC1PEN | TIMER_ROUTE_CC2PEN | TIMER_ROUTE_LOCATION_LOC4; TIMER_TopSet(TIMER0, TOP); TIMER_CompareSet(TIMER0, /* channel */ 1, TOP); TIMER_CompareSet(TIMER0, /* channel */ 2, TOP); TIMER_Init_TypeDef timer_init = TIMER_INIT_DEFAULT; TIMER_Init(TIMER0, &timer_init); CMU_ClockEnable(cmuClock_TIMER3, true); TIMER_InitCC(TIMER3, /* channel */ 1, &timer_initcc); TIMER_InitCC(TIMER3, /* channel */ 2, &timer_initcc); TIMER3->ROUTE = TIMER_ROUTE_CC2PEN | TIMER_ROUTE_LOCATION_LOC0; TIMER_TopSet(TIMER3, TOP); TIMER_CompareSet(TIMER3, /* channel */ 1, TOP); TIMER_CompareSet(TIMER3, /* channel */ 2, TOP); TIMER_IntEnable(TIMER3, TIMER_IF_CC1 | TIMER_IF_OF); NVIC_EnableIRQ(TIMER3_IRQn); TIMER_Init(TIMER3, &timer_init); }
static void init_analog_switches(void) { CMU_ClockEnable(cmuClock_GPIO, true); CMU_ClockEnable(cmuClock_TIMER1, true); port_init(analog_switches, sizeof(analog_switches)/sizeof(port_init_t)); TIMER_Init(T2_TIMER, & t2_timer_init); TIMER_InitCC(T2_TIMER, T2_TIMER_CC, & t2_timer_cc_init); T2_TIMER->ROUTE = TIMER_ROUTE_CC1PEN | (T2_TIMER_LOC << _TIMER_ROUTE_LOCATION_SHIFT); T2_TIMER->CTRL |= TIMER_CTRL_RSSCOIST; uint16_t t1_to_t2_delay = ROUND_F_TO_I(T1_TO_T2_DELAY * CMU_ClockFreqGet(cmuClock_TIMER1)); uint16_t timer_max_count = ROUND_F_TO_I((T1_TO_T2_DELAY + T2_PULSE_TIME) * CMU_ClockFreqGet(cmuClock_TIMER1)); #if 0 printf("t1_to_t2_delay: %" PRIu16 "\r\n", t1_to_t2_delay); printf("timer_max_count: %" PRIu16 "\r\n", timer_max_count); #endif TIMER_CompareSet(T2_TIMER, T2_TIMER_CC, t1_to_t2_delay); TIMER_TopSet(T2_TIMER, timer_max_count); }
/***************************************************************************//** * @brief * Start the TIMER1 to generate a 50% duty cycle output. * * @param[in] frequency * The output frequency in Hz. ******************************************************************************/ void TD_TIMER_Start(uint32_t frequency) { uint32_t top; top = CMU_ClockFreqGet(cmuClock_TIMER1); top = top / frequency; // Enable clock for TIMER1 module CMU_ClockEnable(cmuClock_TIMER1, true); // Configure CC channel 0 TIMER_InitCC(TIMER1, 0, &timerCCInit); // Route CC0 to location 0 (PC13) and enable pin //TIMER1->ROUTE |= (TIMER_ROUTE_CC0PEN | TIMER_ROUTE_LOCATION_LOC0); // Set Top Value TIMER_TopSet(TIMER1, top); // Set compare value starting at 0 - it will be incremented in the interrupt handler TIMER_CompareBufSet(TIMER1, 0, top >> 1); // Configure timer TIMER_Init(TIMER1, &timerInit); // Enable overflow interrupt TIMER_IntEnable(TIMER1, TIMER_IF_OF); // Disable interrupts //TIMER_IntDisable(TIMER1, TIMER_IF_OF); // Enable TIMER1 interrupt vector in NVIC NVIC_EnableIRQ(TIMER1_IRQn); // Enable timer TIMER_Enable(TIMER1, true); TD_TIMER_Enabled = true; }
/***************************************************************************//** * @brief * Configure the compare channel for the HiJack. ******************************************************************************/ static void HIJACK_CompareConfig(HIJACK_OutputMode_t outputMode) { TIMER_InitCC_TypeDef txTimerCapComChConf = { timerEventEveryEdge, /* Event on every capture. */ timerEdgeRising, /* Input capture edge on rising edge. */ timerPRSSELCh0, /* Not used by default, select PRS channel 0. */ timerOutputActionNone, /* No action on underflow. */ timerOutputActionNone, /* No action on overflow. */ timerOutputActionSet, /* No action on match. */ timerCCModeCompare, /* Configure capture channel. */ false, /* Disable filter. */ false, /* Select TIMERnCCx input. */ true, /* Output high when counter disabled. */ false /* Do not invert output. */ }; if (hijackOutputModeSet == outputMode) { txTimerCapComChConf.cmoa = timerOutputActionSet; } else if (hijackOutputModeClear == outputMode) { txTimerCapComChConf.cmoa = timerOutputActionClear; } else if (hijackOutputModeToggle == outputMode) { txTimerCapComChConf.cmoa = timerOutputActionToggle; } else { /* Config error. */ txTimerCapComChConf.cmoa = timerOutputActionNone; } TIMER_InitCC(HIJACK_TX_TIMER, 0, &txTimerCapComChConf); }
/***************************************************************************//** * @brief * Configure the capture channel for the HiJack. ******************************************************************************/ static void HIJACK_CaptureConfig(HIJACK_EdgeMode_t edgeMode) { TIMER_InitCC_TypeDef rxTimerCapComChConf = { timerEventEveryEdge, /* Event on every capture. */ timerEdgeRising, /* Input capture edge on rising edge. */ timerPRSSELCh0, /* Not used by default, select PRS channel 0. */ timerOutputActionNone, /* No action on underflow. */ timerOutputActionNone, /* No action on overflow. */ timerOutputActionNone, /* No action on match. */ timerCCModeCapture, /* Configure capture channel. */ false, /* Disable filter. */ false, /* Select TIMERnCCx input. */ false, /* Clear output when counter disabled. */ false /* Do not invert output. */ }; if (hijackEdgeModeRising == edgeMode) { rxTimerCapComChConf.edge = timerEdgeRising; } else if (hijackEdgeModeFalling == edgeMode) { rxTimerCapComChConf.edge = timerEdgeFalling; } else if (hijackEdgeModeBoth == edgeMode) { rxTimerCapComChConf.edge = timerEdgeBoth; } else { /* Config error. */ rxTimerCapComChConf.edge = timerEdgeNone; } TIMER_InitCC(HIJACK_RX_TIMER, 1, &rxTimerCapComChConf); }
void us_ticker_init(void) { if (us_ticker_inited) { /* calling init again should cancel current interrupt */ us_ticker_disable_interrupt(); return; } us_ticker_inited = true; /* Enable clock for TIMERs */ CMU_ClockEnable(US_TICKER_TIMER_CLOCK, true); if (REFERENCE_FREQUENCY > 24000000) { US_TICKER_TIMER->CTRL = (US_TICKER_TIMER->CTRL & ~_TIMER_CTRL_PRESC_MASK) | (4 << _TIMER_CTRL_PRESC_SHIFT); } else { US_TICKER_TIMER->CTRL = (US_TICKER_TIMER->CTRL & ~_TIMER_CTRL_PRESC_MASK) | (3 << _TIMER_CTRL_PRESC_SHIFT); } /* Clear TIMER counter value */ TIMER_CounterSet(US_TICKER_TIMER, 0); /* Start TIMER */ TIMER_Enable(US_TICKER_TIMER, true); /* Select Compare Channel parameters */ TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT; timerCCInit.mode = timerCCModeCompare; /* Configure Compare Channel 0 */ TIMER_InitCC(US_TICKER_TIMER, 0, &timerCCInit); /* Enable interrupt vector in NVIC */ TIMER_IntClear(US_TICKER_TIMER, TIMER_IEN_CC0); NVIC_SetVector(US_TICKER_TIMER_IRQ, (uint32_t) us_ticker_irq_handler); NVIC_EnableIRQ(US_TICKER_TIMER_IRQ); }
/**************************************************************************//** * @brief TIMER0_setup * Configures the TIMER *****************************************************************************/ void TIMER_setup(void) { /* Enable necessary clocks */ CMU_ClockEnable(cmuClock_TIMER0, true); CMU_ClockEnable(cmuClock_PRS, true); /* Select CC channel parameters */ TIMER_InitCC_TypeDef timerCCInit = { .eventCtrl = timerEventEveryEdge, /* Input capture event control */ .edge = timerEdgeBoth, /* Input capture on falling edge */ .prsSel = timerPRSSELCh5, /* Prs channel select channel 5*/ .cufoa = timerOutputActionNone, /* No action on counter underflow */ .cofoa = timerOutputActionNone, /* No action on counter overflow */ .cmoa = timerOutputActionNone, /* No action on counter match */ .mode = timerCCModeCapture, /* CC channel mode capture */ .filter = false, /* No filter */ .prsInput = true, /* CC channel PRS input */ .coist = false, /* Comparator output initial state */ .outInvert = false, /* No output invert */ }; /* Initialize TIMER0 CC0 channel */ TIMER_InitCC(HIJACK_RX_TIMER, 0, &timerCCInit); /* Select timer parameters */ const TIMER_Init_TypeDef timerInit = { .enable = false, /* Do not start counting when init complete */ .debugRun = false, /* Counter not running on debug halt */ .prescale = HIJACK_TIMER_RESOLUTION, /* Prescaler of 1 */ .clkSel = timerClkSelHFPerClk, /* TIMER0 clocked by the HFPERCLK */ .fallAction = timerInputActionReloadStart, /* Stop counter on falling edge */ .riseAction = timerInputActionReloadStart, /* Reload and start on rising edge */ .mode = timerModeUp, /* Counting up */ .dmaClrAct = false, /* No DMA */ .quadModeX4 = false, /* No quad decoding */ .oneShot = false, /* Counting up constinuously */ .sync = false, /* No start/stop/reload by other timers */ }; /* Initialize TIMER0 */ TIMER_Init(HIJACK_RX_TIMER, &timerInit); /* PRS setup */ /* Select ACMP as source and ACMP0OUT (ACMP0 OUTPUT) as signal */ PRS_SourceSignalSet(5, PRS_CH_CTRL_SOURCESEL_ACMP0, PRS_CH_CTRL_SIGSEL_ACMP0OUT, prsEdgeOff); /* Enable CC0 interrupt */ TIMER_IntEnable(HIJACK_RX_TIMER, TIMER_IF_CC0); /* Enable TIMER0 interrupt vector in NVIC */ NVIC_EnableIRQ(TIMER0_IRQn); } /**************************************************************************//** * @brief ACMP_setup * Configures and starts the ACMP *****************************************************************************/ static void ACMP_setup(void) { /* Enable necessary clocks */ CMU_ClockEnable(HIJACK_RX_ACMPCLK, true); CMU_ClockEnable(cmuClock_GPIO, true); /* Configure ACMP input pin. */ GPIO_PinModeSet(HIJACK_RX_GPIO_PORT, HIJACK_RX_GPIO_PIN, gpioModeInput, 0); /* Analog comparator parameters */ const ACMP_Init_TypeDef acmpInit = { .fullBias = false, /* No full bias current*/ .halfBias = true, /* No half bias current */ .biasProg = 2, /* Biasprog current 1.4 uA */ .interruptOnFallingEdge = false, /* Disable interrupt for falling edge */ .interruptOnRisingEdge = false, /* Disable interrupt for rising edge */ .warmTime = acmpWarmTime256, /* Warm-up time in clock cycles, should be >140 cycles for >10us warm-up @ 14MHz */ .hysteresisLevel = acmpHysteresisLevel7, /* Hysteresis level 0 - no hysteresis */ .inactiveValue = 1, /* Inactive comparator output value */ .lowPowerReferenceEnabled = false, /* Low power reference mode disabled */ .vddLevel = HIJACK_RX_ACMP_LEVEL, /* Vdd reference scaling of 32 */ }; /* Use ACMP0 output, PD6 . */ //GPIO_PinModeSet(gpioPortD, 6, gpioModePushPull, 0); //ACMP_GPIOSetup(ACMP0, 2, true, false); /* Init ACMP and set ACMP channel 4 as positive input and scaled Vdd as negative input */ ACMP_Init(HIJACK_RX_ACMP, &acmpInit); ACMP_ChannelSet(HIJACK_RX_ACMP, HIJACK_RX_ACMP_NEG, HIJACK_RX_ACMP_CH); ACMP_Enable(HIJACK_RX_ACMP); } /** * @brief calculate whether cnt is in 500us region * ticker = 64Mhz/128 = 2us * 475us < cnt < 510us * */ static chk_result_t IsTime2Detect(uint32_t inv) { chk_result_t ret; if( inv < HIJACK_DEC_NUM_TICKS_MIN){ offset = inv; ret = pass; } else if ( ( inv <= HIJACK_DEC_NUM_TICKS_MAX ) && ( inv >= HIJACK_DEC_NUM_TICKS_MIN ) ) { offset = 0; inv = 0; ret = suit; } else{ offset = 0; inv = 0; ret = error; } return ret; } /* * Find phase remain or phase reversal. */ static void dec_parser(uint8_t bit_msk, state_t state) { if ( ( suit == IsTime2Detect(inv) ) ){ //it's time to determine if( falling == cur_edge ){ dec.data &= ~(1 << bit_msk); #if DEC_DEBUG == 1 uartPutChar( '+' ) ; uartPutChar( '_' ) ; #endif//DEC_DEBUG == 1 } else{ dec.data |= (1 << bit_msk); #if DEC_DEBUG == 1 uartPutChar( '_' ) ; uartPutChar( '+' ) ; #endif//DEC_DEBUG == 1 dec.odd++; } dec.state = state; //state switch } else if ( error == IsTime2Detect(inv) ){ //wait for edge detection time dec.state = Waiting; //state switch } } /**************************************************************************//** * @brief decode state machine * Invoke in TIMER_ISR for decoding. *****************************************************************************/ void decode_machine(void) { inv = offset + cur_stamp; //update offset #if 0 if( dec.state > Waiting ){ USART_printHexBy16u(inv); if(cur_edge == rising){ uartPutChar( '\\' ) ; } else{ uartPutChar( '/' ) ; } } #endif switch (dec.state){ case Waiting: /* go to start bit if rising edge exist. */ if (rising == cur_edge) { dec.state = Sta0; offset = 0; inv = 0; } break; // case Sta0: if( ( suit == IsTime2Detect(inv) ) && ( falling == cur_edge ) ){ dec.data = 0; //clear data field for store new potential data dec.odd = 0; //clear odd field parity counter dec.state = Bit0; #if DEC_DEBUG == 1 uartPutChar( 'S' ) ; uartPutChar( '+' ) ; uartPutChar( '_' ) ; #endif } else{ dec.state = Waiting; } break; // case Bit0: #if DEC_DEBUG == 1 uartPutChar( '0' ) ; #endif dec_parser(BIT0, Bit1); break; // case Bit1: #if DEC_DEBUG == 1 uartPutChar( '1' ) ; #endif dec_parser(BIT1, Bit2); break; // case Bit2: #if DEC_DEBUG == 1 uartPutChar( '2' ) ; #endif dec_parser(BIT2, Bit3); break; // case Bit3: #if DEC_DEBUG == 1 uartPutChar( '3' ) ; #endif dec_parser(BIT3, Bit4); break; // case Bit4: #if DEC_DEBUG == 1 uartPutChar( '4' ) ; #endif dec_parser(BIT4, Bit5); break; // case Bit5: #if DEC_DEBUG == 1 uartPutChar( '5' ) ; #endif dec_parser(BIT5, Bit6); break; // case Bit6: #if DEC_DEBUG == 1 uartPutChar( '6' ) ; #endif dec_parser(BIT6, Bit7); break; // case Bit7: #if DEC_DEBUG == 1 uartPutChar( '7' ) ; #endif dec_parser(BIT7, Parity); break; // case Parity: if ( ( suit == IsTime2Detect(inv) ) ){ //it's time to determine if( rising == cur_edge ){ dec.odd++; #if DEC_DEBUG == 1 uartPutChar( '_' ) ; uartPutChar( '+' ) ; #endif } else{ #if DEC_DEBUG == 1 uartPutChar( '+' ) ; uartPutChar( '_' ) ; #endif } #if DEC_DEBUG == 1 uartPutChar( dec.odd + 0x30) ; #endif if( 1 == (dec.odd%2)){ //parity pass dec.state = Sto0; } else{ //parity failed dec.state = Waiting; } } else if ( error == IsTime2Detect(inv) ){ //wait for edge detection time dec.state = Waiting; } break; // case Sto0: if ( ( suit == IsTime2Detect(inv) ) ){ //it's time to determine if( rising == cur_edge ){ //stop bit is rising edge USART_txByte(dec.data); #if DEC_DEBUG == 1 uartPutChar( '_' ) ; uartPutChar( '+' ) ; #endif HIJACKPutData(&dec.data, &decBuf, sizeof(uint8_t)); } else{ #if DEC_DEBUG == 1 uartPutChar( '+' ) ; uartPutChar( '_' ) ; #endif } dec.state = Waiting; #if DEC_DEBUG == 1 uartPutChar( '\r' ) ; uartPutChar( '\n' ) ; #endif } else if ( error == IsTime2Detect(inv) ){ //wait for edge detection time dec.state = Waiting; } break; // default: break; // } }
void initPWM() // Brightness should be less than TIMER_TOP (1024) { /* Enable clocks */ CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_GPIO; CMU_ClockEnable(cmuClock_TIMER1, true); /* Set pins */ GPIO_PinModeSet(gpioPortE,10,gpioModePushPull,1); GPIO_PinModeSet(gpioPortE,11,gpioModePushPull,1); /* Select CC channel parameters */ TIMER_InitCC_TypeDef timerCCInit = { .eventCtrl = timerEventEveryEdge, .edge = timerEdgeBoth, .prsSel = timerPRSSELCh0, .cufoa = timerOutputActionNone, .cofoa = timerOutputActionNone, .cmoa = timerOutputActionToggle, .mode = timerCCModePWM, .filter = false, .prsInput = false, .coist = false, .outInvert = false, }; /* Configure CC channels */ TIMER_InitCC(TIMER1, 0, &timerCCInit); TIMER_InitCC(TIMER1, 1, &timerCCInit); /* Set which pins will be set by the timer */ TIMER1->ROUTE = TIMER_ROUTE_CC0PEN | TIMER_ROUTE_CC1PEN | TIMER_ROUTE_LOCATION_LOC1; /* Set Top Value */ TIMER_TopSet(TIMER1, TIMER_TOP); /* Set compare value starting at top - it will be incremented in the interrupt handler */ TIMER_CompareBufSet(TIMER1, 0, TIMER_TOP + 1); TIMER_CompareBufSet(TIMER1, 1, TIMER_TOP + 1); /* Select timer parameters */ TIMER_Init_TypeDef timerInit = { .enable = true, .debugRun = false, .prescale = timerPrescale16, .clkSel = timerClkSelHFPerClk, .fallAction = timerInputActionNone, .riseAction = timerInputActionNone, .mode = timerModeUp, .dmaClrAct = false, .quadModeX4 = false, .oneShot = false, .sync = false, }; /* Enable overflow interrupt */ TIMER_IntEnable(TIMER1, TIMER_IF_OF); TIMER_IntClear(TIMER1, TIMER_IF_OF); /* Enable TIMER1 interrupt vector in NVIC */ NVIC_EnableIRQ(TIMER1_IRQn); /* Configure timer */ TIMER_Init(TIMER1, &timerInit); }
void InitAudioPWM(void) { CMU_ClockEnable(cmuClock_TIMER1, true); /* Select CC channel parameters */ TIMER_InitCC_TypeDef timerCCInit = { .eventCtrl = timerEventEveryEdge, .edge = timerEdgeBoth, .prsSel = timerPRSSELCh0, .cufoa = timerOutputActionNone, .cofoa = timerOutputActionNone, .cmoa = timerOutputActionToggle, .mode = timerCCModePWM, .filter = false, .prsInput = false, .coist = false, .outInvert = false, }; /* Configure CC channel 0 */ TIMER_InitCC(TIMER1, 0, &timerCCInit); TIMER_InitCC(TIMER1, 1, &timerCCInit); //TIMER_InitCC(TIMER0, 2, &timerCCInit); // TIMER3->ROUTE |= (TIMER_ROUTE_CC0PEN | TIMER_ROUTE_CC1PEN | TIMER_ROUTE_CC2PEN | TIMER_ROUTE_LOCATION_LOC0); TIMER1->ROUTE = TIMER_ROUTE_CC0PEN | TIMER_ROUTE_CC1PEN | TIMER_ROUTE_LOCATION_LOC1; /* Set Top Value */ TIMER_TopSet(TIMER1, 255);//384 /* Set compare value starting at top - it will be incremented in the interrupt handler */ TIMER_CompareBufSet(TIMER1, 0, 256);//385 TIMER_CompareBufSet(TIMER1, 1, 256);//385 //TIMER_CompareBufSet(TIMER3, 2, RGB_PWM_TIMER_TOP + 1); /* Select timer parameters */ TIMER_Init_TypeDef timerInit = { .enable = true, .debugRun = false, .prescale = timerPrescale8, .clkSel = timerClkSelHFPerClk, .fallAction = timerInputActionNone, .riseAction = timerInputActionNone, .mode = timerModeUp, .dmaClrAct = false, .quadModeX4 = false, .oneShot = false, .sync = false, }; ///* Enable overflow interrupt */ TIMER_IntEnable(TIMER1, TIMER_IF_OF); TIMER_IntClear(TIMER1, TIMER_IF_OF); /* Enable TIMER0 interrupt vector in NVIC */ NVIC_EnableIRQ(TIMER1_IRQn); /* Configure timer */ TIMER_Init(TIMER1, &timerInit); } void TIMER1_IRQHandler(void) { int audio_Sample = 0; if(toPlay > 0) { audio_Sample = buff[(iterator = next(iterator))]; toPlay--; } else { audio_Sample = 0; } TIMER_CompareBufSet(TIMER1, 0, (audio_Sample)); TIMER_IntClear(TIMER1, TIMER_IF_OF); }
//================================================================================ // TIMER1_enter_DefaultMode_from_RESET //================================================================================ extern void TIMER1_enter_DefaultMode_from_RESET(void) { // $[TIMER1 I/O setup] /* Set up CC0 */ TIMER1->ROUTELOC0 = (TIMER1->ROUTELOC0 & (~_TIMER_ROUTELOC0_CC0LOC_MASK)) | TIMER_ROUTELOC0_CC0LOC_LOC0; TIMER1->ROUTEPEN = TIMER1->ROUTEPEN | TIMER_ROUTEPEN_CC0PEN; /* Set up CC1 */ TIMER1->ROUTELOC0 = (TIMER1->ROUTELOC0 & (~_TIMER_ROUTELOC0_CC1LOC_MASK)) | TIMER_ROUTELOC0_CC1LOC_LOC0; TIMER1->ROUTEPEN = TIMER1->ROUTEPEN | TIMER_ROUTEPEN_CC1PEN; /* Set up CC2 */ TIMER1->ROUTELOC0 = (TIMER1->ROUTELOC0 & (~_TIMER_ROUTELOC0_CC2LOC_MASK)) | TIMER_ROUTELOC0_CC2LOC_LOC21; TIMER1->ROUTEPEN = TIMER1->ROUTEPEN | TIMER_ROUTEPEN_CC2PEN; /* Set up CC3 */ TIMER1->ROUTELOC0 = (TIMER1->ROUTELOC0 & (~_TIMER_ROUTELOC0_CC3LOC_MASK)) | TIMER_ROUTELOC0_CC3LOC_LOC19; TIMER1->ROUTEPEN = TIMER1->ROUTEPEN | TIMER_ROUTEPEN_CC3PEN; // [TIMER1 I/O setup]$ // $[TIMER1 initialization] TIMER_Init_TypeDef init = TIMER_INIT_DEFAULT; init.enable = 1; init.debugRun = 0; init.dmaClrAct = 0; init.sync = 0; init.clkSel = timerClkSelHFPerClk; init.prescale = timerPrescale1; init.fallAction = timerInputActionNone; init.riseAction = timerInputActionNone; init.mode = timerModeUp; init.quadModeX4 = 0; init.oneShot = 0; init.count2x = 0; init.ati = 0; TIMER_Init(TIMER1, &init); // [TIMER1 initialization]$ // $[TIMER1 CC0 init] TIMER_InitCC_TypeDef initCC0 = TIMER_INITCC_DEFAULT; initCC0.prsInput = false; initCC0.prsSel = timerPRSSELCh0; initCC0.edge = timerEdgeRising; initCC0.mode = timerCCModePWM; initCC0.eventCtrl = timerEventEveryEdge; initCC0.filter = 0; initCC0.cofoa = timerOutputActionNone; initCC0.cufoa = timerOutputActionNone; initCC0.cmoa = timerOutputActionNone; initCC0.coist = 0; initCC0.outInvert = 0; TIMER_InitCC(TIMER1, 0, &initCC0); // [TIMER1 CC0 init]$ // $[TIMER1 CC1 init] TIMER_InitCC_TypeDef initCC1 = TIMER_INITCC_DEFAULT; initCC1.prsInput = false; initCC1.prsSel = timerPRSSELCh0; initCC1.edge = timerEdgeRising; initCC1.mode = timerCCModePWM; initCC1.eventCtrl = timerEventEveryEdge; initCC1.filter = 0; initCC1.cofoa = timerOutputActionNone; initCC1.cufoa = timerOutputActionNone; initCC1.cmoa = timerOutputActionNone; initCC1.coist = 0; initCC1.outInvert = 0; TIMER_InitCC(TIMER1, 1, &initCC1); // [TIMER1 CC1 init]$ // $[TIMER1 CC2 init] TIMER_InitCC_TypeDef initCC2 = TIMER_INITCC_DEFAULT; initCC2.prsInput = false; initCC2.prsSel = timerPRSSELCh0; initCC2.edge = timerEdgeRising; initCC2.mode = timerCCModePWM; initCC2.eventCtrl = timerEventEveryEdge; initCC2.filter = 0; initCC2.cofoa = timerOutputActionNone; initCC2.cufoa = timerOutputActionNone; initCC2.cmoa = timerOutputActionNone; initCC2.coist = 0; initCC2.outInvert = 0; TIMER_InitCC(TIMER1, 2, &initCC2); // [TIMER1 CC2 init]$ // $[TIMER1 CC3 init] TIMER_InitCC_TypeDef initCC3 = TIMER_INITCC_DEFAULT; initCC3.prsInput = false; initCC3.prsSel = timerPRSSELCh0; initCC3.edge = timerEdgeRising; initCC3.mode = timerCCModePWM; initCC3.eventCtrl = timerEventEveryEdge; initCC3.filter = 0; initCC3.cofoa = timerOutputActionNone; initCC3.cufoa = timerOutputActionNone; initCC3.cmoa = timerOutputActionNone; initCC3.coist = 0; initCC3.outInvert = 0; TIMER_InitCC(TIMER1, 3, &initCC3); // [TIMER1 CC3 init]$ }
/**************************************************************************//** * @brief Main function * Main is called from __iar_program_start, see assembly startup file *****************************************************************************/ int motor_init(void) { uint32_t top_value = 0; /* Enable clock for GPIO module */ CMU_ClockEnable(cmuClock_GPIO, true); /* Enable clock for TIMER0 module */ CMU_ClockEnable(cmuClock_TIMER0, true); /* Set CC1 location 3 pin (PD2) as output */ //Left wheel GPIO_PinModeSet(gpioPortD, 2, gpioModePushPull, 0); /* Set CC2 location 3 pin (PD3) as output */ //Right wheel GPIO_PinModeSet(gpioPortD, 3, gpioModePushPull, 0); /* Select CC channel parameters */ TIMER_InitCC_TypeDef timerCCInit = { .eventCtrl = timerEventEveryEdge, .edge = timerEdgeBoth, .prsSel = timerPRSSELCh0, .cufoa = timerOutputActionNone, .cofoa = timerOutputActionNone, .cmoa = timerOutputActionToggle, .mode = timerCCModePWM, .filter = false, .prsInput = false, .coist = false, .outInvert = false, }; /* Configure CC channel 0 */ TIMER_InitCC(TIMER0, 1, &timerCCInit); TIMER_InitCC(TIMER0, 2, &timerCCInit); /* Route CC0 to location 3 (PD1) and enable pin */ TIMER0->ROUTE |= (TIMER_ROUTE_CC2PEN | TIMER_ROUTE_CC1PEN | TIMER_ROUTE_LOCATION_LOC3); /* Set Top Value */ TIMER_TopSet(TIMER0, CMU_ClockFreqGet(cmuClock_HFPER)/PWM_FREQ); top_value = CMU_ClockFreqGet(cmuClock_HFPER)/PWM_FREQ; forward_value = ((18*top_value)/200); backward_value = ((12*top_value)/200); steady_value = ((15*top_value)/200); /* Set compare value starting at 0 - it will be incremented in the interrupt handler */ TIMER_CompareBufSet(TIMER0, 1, 0); TIMER_CompareBufSet(TIMER0, 2, 0); /* Select timer parameters */ TIMER_Init_TypeDef timerInit = { .enable = true, .debugRun = true, .prescale = timerPrescale64, .clkSel = timerClkSelHFPerClk, .fallAction = timerInputActionNone, .riseAction = timerInputActionNone, .mode = timerModeUp, .dmaClrAct = false, .quadModeX4 = false, .oneShot = false, .sync = false, }; /* Enable overflow interrupt */ TIMER_IntEnable(TIMER0, TIMER_IF_OF); /* Enable TIMER0 interrupt vector in NVIC */ NVIC_EnableIRQ(TIMER0_IRQn); /* Configure timer */ TIMER_Init(TIMER0, &timerInit); return 0; }
void backlight_init() { /*init and setup PA9(Backlight) and PA8(Motor) to GPIO output and PWM*/ /* Enable clock for TIMER0 module */ CMU_ClockEnable(cmuClock_TIMER2, true); /* Set location 4 pin (PD7) as output */ GPIO_PinModeSet(gpioPortA, 8, gpioModePushPull, 0); GPIO_PinModeSet(gpioPortA, 9, gpioModePushPull, 0); /*PA8 PA9 at TIMER2 Location0 CC0(PA8) and CC1(PA9)*/ /* Select CC channel parameters */ TIMER_InitCC_TypeDef timerCCInit = { .eventCtrl = timerEventEveryEdge, .edge = timerEdgeBoth, .prsSel = timerPRSSELCh0, .cufoa = timerOutputActionNone, .cofoa = timerOutputActionNone, .cmoa = timerOutputActionToggle, .mode = timerCCModePWM, .filter = false, .prsInput = false, .coist = false, .outInvert = false, }; /* Configure CC channel 0 CC0 for PA8 */ TIMER_InitCC(TIMER2, 0, &timerCCInit); /* Configure CC channel 1 CC0 for PA9 */ timerCCInit.prsSel = timerPRSSELCh1; TIMER_InitCC(TIMER2, 1, &timerCCInit); /* Route CC0/CC1 to location 0 (PA8/PA9) and enable pin */ TIMER2->ROUTE |= (TIMER_ROUTE_CC0PEN | TIMER_ROUTE_CC1PEN | TIMER_ROUTE_LOCATION_LOC0); /* Set Top Value */ TIMER_TopSet(TIMER2, TOP); /*Set CCVB = 0 to TIMER2_CC0 and TIMER2_CC1 */ TIMER_CompareBufSet(TIMER2, 0, 0); TIMER_CompareBufSet(TIMER2, 1, 0); /* Select timer parameters */ TIMER_Init_TypeDef timerInit = { .enable = true, .debugRun = true, .prescale = timerPrescale64, .clkSel = timerClkSelHFPerClk, .fallAction = timerInputActionNone, .riseAction = timerInputActionNone, .mode = timerModeUp, .dmaClrAct = false, .quadModeX4 = false, .oneShot = false, .sync = false, }; /* Enable overflow interrupt */ TIMER_IntEnable(TIMER2, TIMER_IF_OF); /* Enable TIMER2 interrupt vector in NVIC */ NVIC_EnableIRQ(TIMER2_IRQn); /* Configure timer */ TIMER_Init(TIMER2, &timerInit); light_state = MOTOR_ON | LIGHT_ON; LIGHTLEVEL = 0; } void backlight_shutdown() { TIMER_CompareBufSet(TIMER2, 0, 0); TIMER_CompareBufSet(TIMER2, 1, 0); GPIO_PinOutClear(gpioPortA, 8); GPIO_PinOutClear(gpioPortA, 9); light_state = 0; TIMER_Enable(TIMER2,false); CMU_ClockEnable(cmuClock_TIMER2, false); } void light_stop(void *ptr) { if (LIGHTLEVEL > 2) { LIGHTLEVEL--; clock_time_t length = (clock_time_t)ptr; ctimer_set(&light_timer, length, light_stop, (void*)length); } else { TIMER_CompareBufSet(TIMER2, 1, 0); GPIO_PinOutClear(gpioPortA, 9); light_state &= ~LIGHT_ON; if(light_state == 0) { TIMER_Enable(TIMER2,false); CMU_ClockEnable(cmuClock_TIMER2, false); } } } void backlight_on(uint8_t level, clock_time_t length) { CMU_ClockEnable(cmuClock_TIMER2, true); TIMER_Enable(TIMER2,true); if (level > 8) level = 8; if (level == 0) { TIMER_CompareBufSet(TIMER2, 1, 0); } else { LIGHTLEVEL = level * 2; TIMER_CompareBufSet(TIMER2, 1, ( LIGHTLEVEL * 100)); if (length > 0) ctimer_set(&light_timer, length, light_stop, (void*)(CLOCK_SECOND/8)); } }
int main(void) { CHIP_Init(); CMU_ClockEnable(cmuClock_GPIO, true); CMU_ClockEnable(cmuClock_TIMER1, true); CMU_ClockEnable(cmuClock_TIMER3, true); // Set up TIMER1 for timekeeping TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT; timerInit.prescale = timerPrescale1024; TIMER_IntEnable(TIMER1, TIMER_IF_OF); // Enable TIMER1 interrupt vector in NVIC NVIC_EnableIRQ(TIMER1_IRQn); // Set TIMER Top value TIMER_TopSet(TIMER1, ONE_SECOND_TIMER_COUNT); TIMER_Init(TIMER1, &timerInit); // Wait for the timer to get going while (TIMER1->CNT == 0) ; // Enable LED output GPIO_PinModeSet(LED_PORT, LED_PIN, gpioModePushPull, 0); // Create the object initializer for LED PWM TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT; timerCCInit.mode = timerCCModePWM; timerCCInit.cmoa = timerOutputActionToggle; // Configure TIMER3 CC channel 2 TIMER_InitCC(TIMER3, TIMER_CHANNEL, &timerCCInit); // Route CC2 to location 1 (PE3) and enable pin for cc2 TIMER3->ROUTE |= (TIMER_ROUTE_CC2PEN | TIMER_ROUTE_LOCATION_LOC1); // Set Top Value TIMER_TopSet(TIMER3, TIMER_TOP); // Set the PWM duty cycle here! TIMER_CompareBufSet(TIMER3, TIMER_CHANNEL, 0); // Create a timerInit object, based on the API default TIMER_Init_TypeDef timerInit2 = TIMER_INIT_DEFAULT; timerInit2.prescale = timerPrescale256; TIMER_Init(TIMER3, &timerInit2); enum mode_values { RAMPING_UP, HIGH, RAMPING_DOWN, LOW}; // Check for properly sized constants uint16_t delta = MAX_BRIGHTNESS - MIN_BRIGHTNESS; if ( delta == 0 || RAMP_UP_TIME_MS % delta || RAMP_DOWN_TIME_MS % delta) { DEBUG_BREAK } // Set the initial condition uint16_t mode = RAMPING_UP; uint32_t time_step = RAMP_UP_TIME_MS / delta; uint16_t brightness = MIN_BRIGHTNESS; TIMER_CompareBufSet(TIMER3, TIMER_CHANNEL, brightness); uint64_t mode_timeout = set_ms_timeout(RAMP_UP_TIME_MS); while (1) { switch (mode) { case RAMPING_UP: delay_ms(time_step); brightness++; TIMER_CompareBufSet(TIMER3, TIMER_CHANNEL, brightness); if (expired_ms(mode_timeout)) { mode = HIGH; mode_timeout = set_ms_timeout(HIGH_DURATION_MS); } break; case HIGH: if (expired_ms(mode_timeout)) { mode = RAMPING_DOWN; time_step = RAMP_DOWN_TIME_MS / delta; mode_timeout = set_ms_timeout(RAMP_DOWN_TIME_MS); } break; case RAMPING_DOWN: delay_ms(time_step); brightness--; TIMER_CompareBufSet(TIMER3, TIMER_CHANNEL, brightness); if (expired_ms(mode_timeout)) { mode = LOW; mode_timeout = set_ms_timeout(LOW_DURATION_MS); } break; case LOW: if (expired_ms(mode_timeout)) { mode = RAMPING_UP; time_step = RAMP_UP_TIME_MS / delta; mode_timeout = set_ms_timeout(RAMP_UP_TIME_MS); } break; } } }
/**************************************************************************//** * @brief ACMP_setup * Configures and starts the ACMP *****************************************************************************/ void ACMP_setup(void) { /* Enable necessary clocks */ CMU_ClockEnable(cmuClock_ACMP0, true); CMU_ClockEnable(cmuClock_GPIO, true); /* Configure PC4 as input with pull down for ACMP channel 4 input */ GPIO_PinModeSet(gpioPortC, 4, gpioModeInputPullFilter, 0); /* Analog comparator parameters */ const ACMP_Init_TypeDef acmpInit = { .fullBias = false, /* no full bias current*/ .halfBias = false, /* no half bias current */ .biasProg = 7, /* Biasprog current 1.4 uA */ .interruptOnFallingEdge = false, /* disable interrupt for falling edge */ .interruptOnRisingEdge = false, /* disable interrupt for rising edge */ .warmTime = acmpWarmTime256, /* Warm-up time in clock cycles, should be >140 cycles for >10us warm-up @ 14MHz */ .hysteresisLevel = acmpHysteresisLevel0, /* Hysteresis level 0 - no hysteresis */ .inactiveValue = 0, /* Inactive comparator output value */ .lowPowerReferenceEnabled = false, /* Low power reference mode disabled */ .vddLevel = 32, /* Vdd reference scaling of 32 */ }; /* Init ACMP and set ACMP channel 4 as positive input and scaled Vdd as negative input */ ACMP_Init(ACMP0, &acmpInit); ACMP_ChannelSet(ACMP0, acmpChannelVDD, acmpChannel4); ACMP_Enable(ACMP0); } /**************************************************************************//** * @brief PRS_ScanChannel * Waits for activity on a selected PRS channel and writes on the LCD when activity occurs * * @param[in] timer * Pointer to TIMER peripheral register block. * * @param[in] prsCh * PRS Channel to be monitored * * @param[in] edgeType * Signal edge to be monitored/captured *****************************************************************************/ void PRS_ScanChannel(TIMER_TypeDef *timer, TIMER_PRSSEL_TypeDef prsCh, TIMER_Edge_TypeDef edgeType) { /* enable the clock for the correct timer */ #define TIMER_Clock(T) (T==TIMER0 ? cmuClock_TIMER0 : \ T==TIMER1 ? cmuClock_TIMER1 : 0) /* Enable necessary clocks */ CMU_ClockEnable((CMU_Clock_TypeDef)TIMER_Clock(timer), true); /* Initialize LCD */ SegmentLCD_Init(false); /* Select CC channel parameters */ const TIMER_InitCC_TypeDef timerCCInit = { .eventCtrl = timerEventFalling, /* input capture event control */ .edge = edgeType, /* input capture on falling edge */ .prsSel = prsCh, /* prs channel select channel 5*/ .cufoa = timerOutputActionNone, /* no action on counter underflow */ .cofoa = timerOutputActionNone, /* no action on counter overflow */ .cmoa = timerOutputActionNone, /* no action on counter match */ .mode = timerCCModeCapture, /* CC channel mode capture */ .filter = false, /* no filter */ .prsInput = true, /* CC channel PRS input */ .coist = false, /* comparator output initial state */ .outInvert = false, /* no output invert */ }; /* Initialize TIMER0 CC0 */ TIMER_InitCC(timer, 0, &timerCCInit); /* Select timer parameters */ const TIMER_Init_TypeDef timerInit = { .enable = true, /* start counting when init complete */ .debugRun = false, /* counter not running on debug halt */ .prescale = timerPrescale1024, /* prescaler of 64 */ .clkSel = timerClkSelHFPerClk, /* TIMER0 clocked by the HFPERCLK */ .fallAction = timerInputActionNone, /* stop counter on falling edge */ .riseAction = timerInputActionNone, /* reload and start on rising edge */ .mode = timerModeUp, /* counting up */ .dmaClrAct = false, /* no DMA */ .quadModeX4 = false, /* no quad decoding */ .oneShot = false, /* counting up constinuously */ .sync = false, /* no start/stop/reload by other timers */ }; /* Initialize TIMER0 */ TIMER_Init(timer, &timerInit); /* Poll the Input Capture Valid flag in the Status register The program will hang at this point waiting for activity on this channel */ while(!((TIMER0->STATUS & _TIMER_STATUS_ICV0_MASK )>>16)); } /**************************************************************************//** * @brief Main function * Main is called from __iar_program_start, see assembly startup file *****************************************************************************/ int main(void) { /* Align different chip revisions*/ CHIP_Init(); /* Initialise the ACMP */ ACMP_setup(); /* PRS setup */ /* Enable clock for PRS and select ACMP as source and ACMP0OUT (ACMP0 OUTPUT) as signal for channel 5 */ CMU_ClockEnable(cmuClock_PRS, true); PRS_SourceSignalSet(5, PRS_CH_CTRL_SOURCESEL_ACMP0, PRS_CH_CTRL_SIGSEL_ACMP0OUT, prsEdgeOff); /* Start PRS scan This function will halt the program while there is no PRS activity This function assumes that the PRS has been setup previously */ PRS_ScanChannel(TIMER0, timerPRSSELCh5, timerEdgeFalling); /* Write PRS and channel number on the LCD to acknowledge PRS activity */ SegmentLCD_Write("PRS"); SegmentLCD_Number((int)timerPRSSELCh5); while(1) { /* Enter EM1 while waiting for capture. */ EMU_EnterEM1(); } }
void PWM_Init(PWM_Settings_t PWM_Settings) { /* enable TIMER0 peripheral clock */ CMU_ClockEnable(cmuClock_TIMER0, true); /* Setup Timer Channel Configuration for PWM */ TIMER_InitCC_TypeDef TimerCCInit = { .eventCtrl = timerEventEveryEdge, /* this value will be ignored since we aren't using input capture */ .edge = timerEdgeNone, /* this value will be ignored since we aren't using input capture */ .prsSel = timerPRSSELCh0, /* this value will be ignored since we aren't using PRS */ .cufoa = timerOutputActionNone, /* no action on underflow (up-count mode) */ .cofoa = timerOutputActionSet, /* on overflow, we want the output to go high, but in PWM mode this should happen automatically */ .cmoa = timerOutputActionClear, /* on compare match, we want output to clear, but in PWM mode this should happen automatically */ .mode = timerCCModePWM, /* set timer channel to run in PWM mode */ .filter = false, /* not using input, so don't need a filter */ .prsInput = false, /* not using PRS */ .coist = false, /* initial state for PWM is high when timer is enabled */ .outInvert = false, /* non-inverted output */ }; /* Setup Timer Configuration for PWM */ TIMER_Init_TypeDef TimerPWMSetup = { .enable = true, /* start timer upon configuration */ .debugRun = true, /* run timer in debug mode */ .prescale = timerPrescale1, /* set prescaler to 1 */ .clkSel = timerClkSelHFPerClk, /* set clock source as HFPERCLK */ .fallAction = timerInputActionNone, /* no action from inputs */ .riseAction = timerInputActionNone, /* no action from inputs */ .mode = timerModeUp, /* use up-count mode */ .dmaClrAct = false, /* not using DMA */ .quadModeX4 = false, /* not using Quad Dec. mode */ .oneShot = false, /* not using one shot mode */ .sync = false, /* not synchronizing timer3 with other timers */ }; /* by default */ PWM_SetPeriod(1000ULL, 10000000ULL); TIMER_CounterSet(TIMER0, 0); /* start counter at 0 (up-count mode) */ for (uint8_t CCx = 0; CCx < PWM_NUMBER_OF_CC_CHANNELS; CCx++) { PWM_SetDuty(CCx, 0); TIMER_InitCC(TIMER0, CCx, &TimerCCInit); /* apply channel configuration to Timer0 channel 0 */ } TIMER0->ROUTE = (PWM_Settings.location << _TIMER_ROUTE_LOCATION_SHIFT); if (PWM_Settings.CC0_enable == true) { TIMER0->ROUTE |= TIMER_ROUTE_CC0PEN; } if (PWM_Settings.CC1_enable == true) { TIMER0->ROUTE |= TIMER_ROUTE_CC1PEN; } if (PWM_Settings.CC2_enable == true) { TIMER0->ROUTE |= TIMER_ROUTE_CC2PEN; } TIMER_Init(TIMER0, &TimerPWMSetup); /* apply PWM configuration to timer1 */ } void PWM_TurnOff(PWM_CC_Channel CCx) { TIMER_CompareSet(TIMER0, CCx, 0); TIMER_CompareBufSet(TIMER0, CCx, 0); g_PWM_dutyCycle[CCx] = 0; } void PWM_SetDuty(PWM_CC_Channel CCx, uint32_t duty_miliPercents) { uint32_t duty = (uint32_t)(((uint64_t)g_PWM_Period * (uint64_t)duty_miliPercents) / 10000ULL); TIMER_CompareSet(TIMER0, CCx, 0); TIMER_CompareBufSet(TIMER0, CCx, duty); g_PWM_dutyCycle[CCx] = duty; }