added prescaler for 16 bit pwm in LPC1347 target
Fork of mbed-dev by
Diff: targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c
- Revision:
- 50:a417edff4437
- Parent:
- 0:9b334a45a8ff
- Child:
- 144:ef7eb2e8f9f7
--- a/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c Wed Jan 13 12:45:11 2016 +0000 +++ b/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c Fri Jan 15 07:45:16 2016 +0000 @@ -35,18 +35,46 @@ #include "rtc_api_HAL.h" #include "lp_ticker_api.h" +#include "em_int.h" +#if (defined RTCC_COUNT) && (RTCC_COUNT > 0) +#include "em_rtcc.h" +#endif + +static int rtc_reserved = 0; + void lp_ticker_init() { - rtc_init_real(RTC_INIT_LPTIMER); - rtc_set_comp0_handler((uint32_t)lp_ticker_irq_handler); + if(!rtc_reserved) { + INT_Disable(); + rtc_init_real(RTC_INIT_LPTIMER); + rtc_set_comp0_handler((uint32_t)lp_ticker_irq_handler); + rtc_reserved = 1; + INT_Enable(); + } } +void lp_ticker_free() +{ + if(rtc_reserved) { + INT_Disable(); + rtc_free_real(RTC_INIT_LPTIMER); + rtc_reserved = 0; + INT_Enable(); + } +} + +#ifndef RTCC_COUNT + +/* RTC API */ + void lp_ticker_set_interrupt(timestamp_t timestamp) { uint64_t timestamp_ticks; uint64_t current_ticks = RTC_CounterGet(); timestamp_t current_time = ((uint64_t)(current_ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)); + /* Initialize RTC */ + lp_ticker_init(); /* calculate offset value */ timestamp_t offset = timestamp - current_time; @@ -73,6 +101,7 @@ inline void lp_ticker_disable_interrupt() { RTC_IntDisable(RTC_IF_COMP0); + lp_ticker_free(); } inline void lp_ticker_clear_interrupt() @@ -82,6 +111,8 @@ timestamp_t lp_ticker_read() { + lp_ticker_init(); + uint64_t ticks_temp; uint64_t ticks = RTC_CounterGet(); @@ -94,4 +125,75 @@ return (timestamp_t) (ticks_temp & 0xFFFFFFFF); } +#else + +/* RTCC API */ + +void lp_ticker_set_interrupt(timestamp_t timestamp) +{ + uint64_t timestamp_ticks; + uint64_t current_ticks = RTCC_CounterGet(); + timestamp_t current_time = ((uint64_t)(current_ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)); + + /* Initialize RTC */ + lp_ticker_init(); + + /* calculate offset value */ + timestamp_t offset = timestamp - current_time; + if(offset > 0xEFFFFFFF) offset = 100; + + /* map offset to RTC value */ + // ticks = offset * RTC frequency div 1000000 + timestamp_ticks = ((uint64_t)offset * (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) / 1000000; + // checking the rounding. If timeout is wanted between RTCC ticks, irq should be configured to + // trigger in the latter RTCC-tick. Otherwise ticker-api fails to send timer event to its client + if(((timestamp_ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) < offset){ + timestamp_ticks++; + } + + timestamp_ticks += current_ticks; + + /* RTCC has 32 bit resolution */ + timestamp_ticks &= 0xFFFFFFFF; + + /* check for RTCC limitation */ + if((timestamp_ticks - RTCC_CounterGet()) >= 0x80000000) timestamp_ticks = RTCC_CounterGet() + 2; + + /* init channel */ + RTCC_CCChConf_TypeDef ccchConf = RTCC_CH_INIT_COMPARE_DEFAULT; + RTCC_ChannelInit(0,&ccchConf); + /* Set callback */ + RTCC_ChannelCCVSet(0, (uint32_t)timestamp_ticks); + RTCC_IntEnable(RTCC_IF_CC0); +} + +inline void lp_ticker_disable_interrupt() +{ + RTCC_IntDisable(RTCC_IF_CC0); + lp_ticker_free(); +} + +inline void lp_ticker_clear_interrupt() +{ + RTCC_IntClear(RTCC_IF_CC0); +} + +timestamp_t lp_ticker_read() +{ + lp_ticker_init(); + + uint64_t ticks_temp; + uint64_t ticks = RTCC_CounterGet(); + + /* ticks = counter tick value + * timestamp = value in microseconds + * timestamp = ticks * 1.000.000 / RTC frequency + */ + + ticks_temp = (ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT); + return (timestamp_t) (ticks_temp & 0xFFFFFFFF); +} + +#endif /* RTCC */ + #endif