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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WakeUp_Freescale.cpp Source File

WakeUp_Freescale.cpp

00001 #if defined(TARGET_Freescale)
00002 
00003 #include "WakeUp.h"
00004 #include "us_ticker_api.h"
00005 
00006 Callback<void()> WakeUp::callback;
00007 float WakeUp::cycles_per_ms = 1.0;
00008 
00009 static uint16_t remainder_count;
00010 static uint32_t oldvector;
00011 static uint8_t oldPSR;
00012 
00013 //See if we have a 32kHz crystal on the clock input
00014 //Check if the DMX32 bit is set, not perfect, but most cases will work
00015 static inline bool is32kXtal(void) {
00016     return (MCG->C4 & MCG_C4_DMX32_MASK);
00017 }
00018 
00019 void restore(void);
00020 
00021 void WakeUp::set_ms(uint32_t ms)
00022 {
00023     /* Clock the timer */
00024     SIM->SCGC5 |= 0x1u;
00025     
00026     //Check if it is running, in that case, store current values
00027     remainder_count = 0;
00028     if (NVIC_GetVector(LPTimer_IRQn) != (uint32_t)WakeUp::irq_handler) {
00029         oldvector = NVIC_GetVector(LPTimer_IRQn);
00030         oldPSR = LPTMR0->PSR;
00031         
00032         if (LPTMR0->CSR & LPTMR_CSR_TIE_MASK) {
00033             //Write first to sync value
00034             LPTMR0->CNR = 0;
00035             uint16_t countval = LPTMR0->CNR;
00036             if (countval < LPTMR0->CMR)
00037                 remainder_count = countval - LPTMR0->CMR;
00038         }
00039     }
00040     
00041     LPTMR0->CSR = 0;
00042 
00043     if (ms != 0) {
00044         /* Set interrupt handler */
00045         NVIC_SetVector(LPTimer_IRQn, (uint32_t)WakeUp::irq_handler);
00046         NVIC_EnableIRQ(LPTimer_IRQn);
00047         
00048         uint32_t counts;
00049         //Set clock
00050         if (is32kXtal()) {
00051             SIM->SOPT1 &= ~SIM_SOPT1_OSC32KSEL_MASK;    //Put RTC/LPTMR on 32kHz external. 
00052             #ifdef OSC0
00053             OSC0->CR |= OSC_CR_EREFSTEN_MASK;
00054             #else
00055             OSC->CR |= OSC_CR_EREFSTEN_MASK;
00056             #endif
00057             LPTMR0->PSR = LPTMR_PSR_PCS(2);
00058             counts = (uint32_t)((float)ms * 32.768f);
00059         } else {
00060             //Clock from the 1kHz LPO
00061             LPTMR0->PSR = LPTMR_PSR_PCS(1);
00062             counts = (uint32_t)((float)ms * cycles_per_ms);
00063         }
00064         
00065         //If no prescaler is needed
00066         if (counts <= 0xFFFF) 
00067             LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK;
00068         else {        //Otherwise increase prescaler until it fits
00069             counts >>= 1;
00070             uint32_t prescaler = 0;
00071             while (counts > 0xFFFF) {
00072                 counts >>= 1;
00073                 prescaler++;
00074             }
00075             LPTMR0->PSR |= LPTMR_PSR_PRESCALE(prescaler);
00076         }
00077         LPTMR0->CMR = counts;        
00078 
00079         LPTMR0->CSR = LPTMR_CSR_TIE_MASK;
00080         LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
00081     } else {
00082         restore();
00083     }
00084 
00085 }
00086 
00087 
00088 void WakeUp::irq_handler(void)
00089 {
00090     // write 1 to TCF to clear the LPT timer compare flag
00091     LPTMR0->CSR |= LPTMR_CSR_TCF_MASK;
00092     restore();
00093     callback.call();
00094 }
00095 
00096 void WakeUp::calibrate(void)
00097 {
00098     if (!is32kXtal()) {
00099         wait_us(1);     //Otherwise next wait might overwrite our settings
00100         cycles_per_ms = 1.0;
00101         set_ms(1100);
00102         wait_ms(100);
00103     
00104         //Write first to sync value
00105         LPTMR0->CNR = 0;
00106         uint32_t ticks = LPTMR0->CNR;
00107         cycles_per_ms = ticks / 100.0;
00108         set_ms(0);
00109     }
00110 }
00111 
00112 void restore(void){
00113     /* Reset */
00114     LPTMR0->CSR = 0;
00115     
00116     /* Set interrupt handler */
00117     NVIC_SetVector(LPTimer_IRQn, oldvector);
00118     NVIC_EnableIRQ(LPTimer_IRQn);
00119     
00120     /* Clock at (1)MHz -> (1)tick/us */
00121     LPTMR0->PSR = oldPSR;
00122 
00123     if (remainder_count) {  
00124         /* Set the compare register */
00125         LPTMR0->CMR = remainder_count;
00126         
00127         /* Enable interrupt */
00128         LPTMR0->CSR |= LPTMR_CSR_TIE_MASK;
00129         
00130         /* Start the timer */
00131         LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
00132     }
00133 }
00134 
00135 #endif