add the implementation of LP1768 wakeup based on the old WakeUp library

Dependencies:   LPC1114_WakeInterruptIn

Fork of WakeUp by steven niu

Files at this revision

API Documentation at this revision

Comitter:
Sissors
Date:
Sat Dec 07 11:21:15 2013 +0000
Parent:
1:92f4c2b52771
Child:
3:2c62a668f265
Commit message:
KL25 should now play nicely with mbed

Changed in this revision

WakeUp.h Show annotated file Show diff for this revision Revisions of this file
WakeUp_KL25Z.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/WakeUp.h	Thu Dec 05 21:32:11 2013 +0000
+++ b/WakeUp.h	Sat Dec 07 11:21:15 2013 +0000
@@ -1,17 +1,14 @@
 #include "mbed.h"
 
 /**
-* Class to make use of the LPC81x's low power wake-up timer.
+* Class to make use of the LPC81x's and KL25Zs low power wake-up timer.
 *
 * One of the methods of waking up from deepsleep/powerdown is using the wake-up timer.
-* This is an ultra low-power timer that can run from an always-on 10kHz clock source.
+* This is an ultra low-power timer that can run from an always-on clock source.
 * So while normal timers are shut-down, this one still runs, consuming only roughly 1uA.
 * If the timer does not need to run everything is shut down again by the library.
 *
-* This class can also be used as general purpose interrupt timer, although just using 
-* the default Timer library is probably a better idea for that.
-*
-* Example program: http://mbed.org/users/Sissors/code/LPC812_Sleep_HelloWorld/
+* Example program for the LPC812: http://mbed.org/users/Sissors/code/LPC812_Sleep_HelloWorld/
 */
 class WakeUp
 {
--- a/WakeUp_KL25Z.cpp	Thu Dec 05 21:32:11 2013 +0000
+++ b/WakeUp_KL25Z.cpp	Sat Dec 07 11:21:15 2013 +0000
@@ -1,29 +1,64 @@
 #ifdef TARGET_KL25Z
 
 #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;
+
+void restore(void);
+
 void WakeUp::set_ms(uint32_t ms)
 {
     /* Clock the timer */
     SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK;
+    
+    //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);
+        
+    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 directly from the 1kHz LPO
+        //Clock from the 1kHz LPO
         LPTMR0->PSR = LPTMR_PSR_PCS(1);
-        LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK;
 
         /* 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);
 
-        LPTMR0->CMR = (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();
     }
 
 }
@@ -33,6 +68,7 @@
 {
     // write 1 to TCF to clear the LPT timer compare flag
     LPTMR0->CSR |= LPTMR_CSR_TCF_MASK;
+    restore();
     callback.call();
 }
 
@@ -47,8 +83,31 @@
     LPTMR0->CNR = 0;
     uint32_t ticks = LPTMR0->CNR;
     cycles_per_ms = ticks / 100.0;
+    set_ms(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 = LPTMR_PSR_PCS(3);       // OSCERCLK -> 8MHz
+    LPTMR0->PSR |= LPTMR_PSR_PRESCALE(2); // divide by 8
+
+    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;
+    }
 }
 
 
@@ -56,5 +115,4 @@
 
 
 
-
 #endif
\ No newline at end of file