ok
Dependencies: LPC1114_WakeInterruptIn
Fork of WakeUp by
Diff: Device/WakeUp_Freescale.cpp
- Revision:
- 16:f3adba7cf7c4
- Parent:
- 7:bb411115f814
- Child:
- 18:13aed323e040
diff -r b2a710aca356 -r f3adba7cf7c4 Device/WakeUp_Freescale.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Device/WakeUp_Freescale.cpp Sun Sep 14 06:45:51 2014 +0000 @@ -0,0 +1,115 @@ +#if defined(TARGET_Freescale) + +#include "WakeUp.h" +#include "us_ticker_api.h" + +FunctionPointer WakeUp::callback; +float WakeUp::cycles_per_ms = 1.0; + +static uint16_t remainder_count; +static uint32_t oldvector; +static uint8_t oldPSR; + +void restore(void); + +void WakeUp::set_ms(uint32_t ms) +{ + /* Clock the timer */ + SIM->SCGC5 |= 0x1u; + + //Check if it is running, in that case, store current values + remainder_count = 0; + if (NVIC_GetVector(LPTimer_IRQn) != (uint32_t)WakeUp::irq_handler) { + oldvector = NVIC_GetVector(LPTimer_IRQn); + oldPSR = LPTMR0->PSR; + + if (LPTMR0->CSR & LPTMR_CSR_TIE_MASK) { + //Write first to sync value + LPTMR0->CNR = 0; + uint16_t countval = LPTMR0->CNR; + if (countval < LPTMR0->CMR) + remainder_count = countval - LPTMR0->CMR; + } + } + + LPTMR0->CSR = 0; + + if (ms != 0) { + //Clock from the 1kHz LPO + LPTMR0->PSR = LPTMR_PSR_PCS(1); + + /* Set interrupt handler */ + NVIC_SetVector(LPTimer_IRQn, (uint32_t)WakeUp::irq_handler); + NVIC_EnableIRQ(LPTimer_IRQn); + + uint32_t counts = (uint32_t)((float)ms * cycles_per_ms); + + //If no prescaler is needed + if (counts <= 0xFFFF) + LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK; + else { //Otherwise increase prescaler until it fits + counts >>= 1; + uint32_t prescaler = 0; + while (counts > 0xFFFF) { + counts >>= 1; + prescaler++; + } + LPTMR0->PSR |= LPTMR_PSR_PRESCALE(prescaler); + } + LPTMR0->CMR = counts; + + LPTMR0->CSR = LPTMR_CSR_TIE_MASK; + LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; + } else { + restore(); + } + +} + + +void WakeUp::irq_handler(void) +{ + // write 1 to TCF to clear the LPT timer compare flag + LPTMR0->CSR |= LPTMR_CSR_TCF_MASK; + restore(); + callback.call(); +} + +void WakeUp::calibrate(void) +{ + wait_us(1); //Otherwise next wait might overwrite our settings + cycles_per_ms = 1.0; + set_ms(1100); + wait_ms(100); + + //Write first to sync value + LPTMR0->CNR = 0; + uint32_t ticks = LPTMR0->CNR; + cycles_per_ms = ticks / 100.0; + set_ms(0); +} + +void restore(void){ + /* Reset */ + LPTMR0->CSR = 0; + + /* Set interrupt handler */ + NVIC_SetVector(LPTimer_IRQn, oldvector); + NVIC_EnableIRQ(LPTimer_IRQn); + + /* Clock at (1)MHz -> (1)tick/us */ + LPTMR0->PSR = oldPSR; + + if (remainder_count) { + /* Set the compare register */ + LPTMR0->CMR = remainder_count; + + /* Enable interrupt */ + LPTMR0->CSR |= LPTMR_CSR_TIE_MASK; + + /* Start the timer */ + LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; + } +} + +#endif \ No newline at end of file