This is the code used on my video series "Hybrid Supercapacitor Car Battery" for my own hardware monitoring system. THe videos can be found on madelectronengineering.com

Dependencies:   BurstSPI Fonts INA219 mbed LPC1114_WakeInterruptIn

Fork of SharpMemoryLCD by Paul Staron

Committer:
madelectroneng
Date:
Tue Dec 26 21:30:09 2017 +0000
Revision:
2:0c49a8f32f6e
Inital setup

Who changed what in which revision?

UserRevisionLine numberNew contents of line
madelectroneng 2:0c49a8f32f6e 1 #if defined(TARGET_Freescale)
madelectroneng 2:0c49a8f32f6e 2
madelectroneng 2:0c49a8f32f6e 3 #include "WakeUp.h"
madelectroneng 2:0c49a8f32f6e 4 #include "us_ticker_api.h"
madelectroneng 2:0c49a8f32f6e 5
madelectroneng 2:0c49a8f32f6e 6 Callback<void()> WakeUp::callback;
madelectroneng 2:0c49a8f32f6e 7 float WakeUp::cycles_per_ms = 1.0;
madelectroneng 2:0c49a8f32f6e 8
madelectroneng 2:0c49a8f32f6e 9 static uint16_t remainder_count;
madelectroneng 2:0c49a8f32f6e 10 static uint32_t oldvector;
madelectroneng 2:0c49a8f32f6e 11 static uint8_t oldPSR;
madelectroneng 2:0c49a8f32f6e 12
madelectroneng 2:0c49a8f32f6e 13 //See if we have a 32kHz crystal on the clock input
madelectroneng 2:0c49a8f32f6e 14 //Check if the DMX32 bit is set, not perfect, but most cases will work
madelectroneng 2:0c49a8f32f6e 15 static inline bool is32kXtal(void) {
madelectroneng 2:0c49a8f32f6e 16 return (MCG->C4 & MCG_C4_DMX32_MASK);
madelectroneng 2:0c49a8f32f6e 17 }
madelectroneng 2:0c49a8f32f6e 18
madelectroneng 2:0c49a8f32f6e 19 void restore(void);
madelectroneng 2:0c49a8f32f6e 20
madelectroneng 2:0c49a8f32f6e 21 void WakeUp::set_ms(uint32_t ms)
madelectroneng 2:0c49a8f32f6e 22 {
madelectroneng 2:0c49a8f32f6e 23 /* Clock the timer */
madelectroneng 2:0c49a8f32f6e 24 SIM->SCGC5 |= 0x1u;
madelectroneng 2:0c49a8f32f6e 25
madelectroneng 2:0c49a8f32f6e 26 //Check if it is running, in that case, store current values
madelectroneng 2:0c49a8f32f6e 27 remainder_count = 0;
madelectroneng 2:0c49a8f32f6e 28 if (NVIC_GetVector(LPTimer_IRQn) != (uint32_t)WakeUp::irq_handler) {
madelectroneng 2:0c49a8f32f6e 29 oldvector = NVIC_GetVector(LPTimer_IRQn);
madelectroneng 2:0c49a8f32f6e 30 oldPSR = LPTMR0->PSR;
madelectroneng 2:0c49a8f32f6e 31
madelectroneng 2:0c49a8f32f6e 32 if (LPTMR0->CSR & LPTMR_CSR_TIE_MASK) {
madelectroneng 2:0c49a8f32f6e 33 //Write first to sync value
madelectroneng 2:0c49a8f32f6e 34 LPTMR0->CNR = 0;
madelectroneng 2:0c49a8f32f6e 35 uint16_t countval = LPTMR0->CNR;
madelectroneng 2:0c49a8f32f6e 36 if (countval < LPTMR0->CMR)
madelectroneng 2:0c49a8f32f6e 37 remainder_count = countval - LPTMR0->CMR;
madelectroneng 2:0c49a8f32f6e 38 }
madelectroneng 2:0c49a8f32f6e 39 }
madelectroneng 2:0c49a8f32f6e 40
madelectroneng 2:0c49a8f32f6e 41 LPTMR0->CSR = 0;
madelectroneng 2:0c49a8f32f6e 42
madelectroneng 2:0c49a8f32f6e 43 if (ms != 0) {
madelectroneng 2:0c49a8f32f6e 44 /* Set interrupt handler */
madelectroneng 2:0c49a8f32f6e 45 NVIC_SetVector(LPTimer_IRQn, (uint32_t)WakeUp::irq_handler);
madelectroneng 2:0c49a8f32f6e 46 NVIC_EnableIRQ(LPTimer_IRQn);
madelectroneng 2:0c49a8f32f6e 47
madelectroneng 2:0c49a8f32f6e 48 uint32_t counts;
madelectroneng 2:0c49a8f32f6e 49 //Set clock
madelectroneng 2:0c49a8f32f6e 50 if (is32kXtal()) {
madelectroneng 2:0c49a8f32f6e 51 SIM->SOPT1 &= ~SIM_SOPT1_OSC32KSEL_MASK; //Put RTC/LPTMR on 32kHz external.
madelectroneng 2:0c49a8f32f6e 52 #ifdef OSC0
madelectroneng 2:0c49a8f32f6e 53 OSC0->CR |= OSC_CR_EREFSTEN_MASK;
madelectroneng 2:0c49a8f32f6e 54 #else
madelectroneng 2:0c49a8f32f6e 55 OSC->CR |= OSC_CR_EREFSTEN_MASK;
madelectroneng 2:0c49a8f32f6e 56 #endif
madelectroneng 2:0c49a8f32f6e 57 LPTMR0->PSR = LPTMR_PSR_PCS(2);
madelectroneng 2:0c49a8f32f6e 58 counts = (uint32_t)((float)ms * 32.768f);
madelectroneng 2:0c49a8f32f6e 59 } else {
madelectroneng 2:0c49a8f32f6e 60 //Clock from the 1kHz LPO
madelectroneng 2:0c49a8f32f6e 61 LPTMR0->PSR = LPTMR_PSR_PCS(1);
madelectroneng 2:0c49a8f32f6e 62 counts = (uint32_t)((float)ms * cycles_per_ms);
madelectroneng 2:0c49a8f32f6e 63 }
madelectroneng 2:0c49a8f32f6e 64
madelectroneng 2:0c49a8f32f6e 65 //If no prescaler is needed
madelectroneng 2:0c49a8f32f6e 66 if (counts <= 0xFFFF)
madelectroneng 2:0c49a8f32f6e 67 LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK;
madelectroneng 2:0c49a8f32f6e 68 else { //Otherwise increase prescaler until it fits
madelectroneng 2:0c49a8f32f6e 69 counts >>= 1;
madelectroneng 2:0c49a8f32f6e 70 uint32_t prescaler = 0;
madelectroneng 2:0c49a8f32f6e 71 while (counts > 0xFFFF) {
madelectroneng 2:0c49a8f32f6e 72 counts >>= 1;
madelectroneng 2:0c49a8f32f6e 73 prescaler++;
madelectroneng 2:0c49a8f32f6e 74 }
madelectroneng 2:0c49a8f32f6e 75 LPTMR0->PSR |= LPTMR_PSR_PRESCALE(prescaler);
madelectroneng 2:0c49a8f32f6e 76 }
madelectroneng 2:0c49a8f32f6e 77 LPTMR0->CMR = counts;
madelectroneng 2:0c49a8f32f6e 78
madelectroneng 2:0c49a8f32f6e 79 LPTMR0->CSR = LPTMR_CSR_TIE_MASK;
madelectroneng 2:0c49a8f32f6e 80 LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
madelectroneng 2:0c49a8f32f6e 81 } else {
madelectroneng 2:0c49a8f32f6e 82 restore();
madelectroneng 2:0c49a8f32f6e 83 }
madelectroneng 2:0c49a8f32f6e 84
madelectroneng 2:0c49a8f32f6e 85 }
madelectroneng 2:0c49a8f32f6e 86
madelectroneng 2:0c49a8f32f6e 87
madelectroneng 2:0c49a8f32f6e 88 void WakeUp::irq_handler(void)
madelectroneng 2:0c49a8f32f6e 89 {
madelectroneng 2:0c49a8f32f6e 90 // write 1 to TCF to clear the LPT timer compare flag
madelectroneng 2:0c49a8f32f6e 91 LPTMR0->CSR |= LPTMR_CSR_TCF_MASK;
madelectroneng 2:0c49a8f32f6e 92 restore();
madelectroneng 2:0c49a8f32f6e 93 callback.call();
madelectroneng 2:0c49a8f32f6e 94 }
madelectroneng 2:0c49a8f32f6e 95
madelectroneng 2:0c49a8f32f6e 96 void WakeUp::calibrate(void)
madelectroneng 2:0c49a8f32f6e 97 {
madelectroneng 2:0c49a8f32f6e 98 if (!is32kXtal()) {
madelectroneng 2:0c49a8f32f6e 99 wait_us(1); //Otherwise next wait might overwrite our settings
madelectroneng 2:0c49a8f32f6e 100 cycles_per_ms = 1.0;
madelectroneng 2:0c49a8f32f6e 101 set_ms(1100);
madelectroneng 2:0c49a8f32f6e 102 wait_ms(100);
madelectroneng 2:0c49a8f32f6e 103
madelectroneng 2:0c49a8f32f6e 104 //Write first to sync value
madelectroneng 2:0c49a8f32f6e 105 LPTMR0->CNR = 0;
madelectroneng 2:0c49a8f32f6e 106 uint32_t ticks = LPTMR0->CNR;
madelectroneng 2:0c49a8f32f6e 107 cycles_per_ms = ticks / 100.0;
madelectroneng 2:0c49a8f32f6e 108 set_ms(0);
madelectroneng 2:0c49a8f32f6e 109 }
madelectroneng 2:0c49a8f32f6e 110 }
madelectroneng 2:0c49a8f32f6e 111
madelectroneng 2:0c49a8f32f6e 112 void restore(void){
madelectroneng 2:0c49a8f32f6e 113 /* Reset */
madelectroneng 2:0c49a8f32f6e 114 LPTMR0->CSR = 0;
madelectroneng 2:0c49a8f32f6e 115
madelectroneng 2:0c49a8f32f6e 116 /* Set interrupt handler */
madelectroneng 2:0c49a8f32f6e 117 NVIC_SetVector(LPTimer_IRQn, oldvector);
madelectroneng 2:0c49a8f32f6e 118 NVIC_EnableIRQ(LPTimer_IRQn);
madelectroneng 2:0c49a8f32f6e 119
madelectroneng 2:0c49a8f32f6e 120 /* Clock at (1)MHz -> (1)tick/us */
madelectroneng 2:0c49a8f32f6e 121 LPTMR0->PSR = oldPSR;
madelectroneng 2:0c49a8f32f6e 122
madelectroneng 2:0c49a8f32f6e 123 if (remainder_count) {
madelectroneng 2:0c49a8f32f6e 124 /* Set the compare register */
madelectroneng 2:0c49a8f32f6e 125 LPTMR0->CMR = remainder_count;
madelectroneng 2:0c49a8f32f6e 126
madelectroneng 2:0c49a8f32f6e 127 /* Enable interrupt */
madelectroneng 2:0c49a8f32f6e 128 LPTMR0->CSR |= LPTMR_CSR_TIE_MASK;
madelectroneng 2:0c49a8f32f6e 129
madelectroneng 2:0c49a8f32f6e 130 /* Start the timer */
madelectroneng 2:0c49a8f32f6e 131 LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
madelectroneng 2:0c49a8f32f6e 132 }
madelectroneng 2:0c49a8f32f6e 133 }
madelectroneng 2:0c49a8f32f6e 134
madelectroneng 2:0c49a8f32f6e 135 #endif