Mark Gottscho / HardwareTimersLib

Fork of HardwareTimersLib by Mark Gottscho

Revision:
7:78f6ee57d324
Parent:
2:5056ec8c52e8
Child:
8:23c04123395c
--- a/Timer_LPTMR.cpp	Mon Mar 10 20:35:21 2014 +0000
+++ b/Timer_LPTMR.cpp	Tue Mar 11 00:52:13 2014 +0000
@@ -5,56 +5,92 @@
  */
 
 #include "mbed.h"
-#include "HardwareTimer.h"
 #include "Timer_LPTMR.h"
 #include "PreciseTime.h"
 
-//Init class static variable
-bool Timer_LPTMR::__initialized_lptmr = false;
-uint16_t Timer_LPTMR::__rolloverValue = 0xFFFF;
-uint32_t Timer_LPTMR::__count = 0;
+
+//Init Timer_LPTMR class variables
+bool Timer_LPTMR::__lptmr_used = false;
+Timer_LPTMR *Timer_LPTMR::__obj = NULL;
 
-Timer_LPTMR::Timer_LPTMR(float tickValue) :
-            HardwareTimer(tickValue)
-            {
+Timer_LPTMR::Timer_LPTMR() :
+        HardwareTimer(0xFFFF, 1, HardwareTimer::ms) //LPTMR has 16-bit counter. And at 1 KHz, each clock cycle is 1 ms
+        {   
+    if (__lptmr_used)
+        __valid = false;
+    else {
+        __valid = true;
+        __lptmr_used = true;
+        __obj = this;
+    }
 }
 
-Timer_LPTMR::~Timer_LPTMR() {}
-
-void Timer_LPTMR::disableTimer() {
-    if (!__valid)
-        return;
-        
-    LPTMR0->CSR = 0; //Reset the LPTMR timer control/status register
-    __enabled = false;
+Timer_LPTMR::~Timer_LPTMR() {
+    if (__valid) {
+        __lptmr_used = false; //free the hardware LPTMR resource
+        __obj = NULL;
+    }
 }
 
 uint32_t Timer_LPTMR::getTick() {
     if (!__valid)
         return 0;
         
-    //Get the raw time
-    __disable_irq();
+    // CRITICAL SECTION
+    NVIC_DisableIRQ(LPTimer_IRQn);
     LPTMR0->CNR = 0; //need to write to the register in order to read it due to buffering
     uint16_t ticks = LPTMR0->CNR;
     uint32_t count = __count;
-    __enable_irq();
+    NVIC_EnableIRQ(LPTimer_IRQn);
+    // END CRITICAL SECTION
     
     //Convert to ticks
-    return (uint32_t) ((count * __rolloverValue) + ticks);
+    return (uint32_t) count * __rolloverValue + ticks;
 }
 
+void Timer_LPTMR::__init_timer() {    
+    //MCG clocks  
+    MCG->C2 &= ~MCG_C2_IRCS_MASK; //Set slow internal reference clk (32 KHz)
+    MCG->C1 |= MCG_C1_IRCLKEN_MASK; //Enable internal reference clk (MCGIRCLK)
+   // MCG->C1 |= MCG_C1_IREFSTEN_MASK; //Enable internal reference clk (MCGIRCLK) to work in stop mode
+    
+    //Timer clock gating
+    SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK; //Disable clock gating the timer
+    
+    //Timer prescaling and clock selection
+    LPTMR0->PSR = LPTMR_PSR_PCS(0); //Set LPTMR0 to use MCGIRCLK --> 32 KHz
+    LPTMR0->PSR |= LPTMR_PSR_PRESCALE(4); // divide by 32 to get 1 KHz
+    
+    //Status reset
+    LPTMR0->CSR = 0; //Reset the timer control/status register
+    
+    //Set interrupt handler
+    NVIC_SetVector(LPTimer_IRQn, (uint32_t) __lptmr_isr_wrapper);
+    NVIC_EnableIRQ(LPTimer_IRQn);
+    
+    //Good to go!
+}
 
-void Timer_LPTMR::__isr_lptmr() {
+void Timer_LPTMR::__start_timer() {
+    LPTMR0->CSR = 0; //Reset the timer control/status register
+    LPTMR0->CMR = __rolloverValue; //Set the compare register
+    LPTMR0->CSR |= LPTMR_CSR_TIE_MASK; //Enable interrupt
+    LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; //Start the timer
+}
+
+void Timer_LPTMR::__stop_timer() {
+    LPTMR0->CSR = 0; //Reset the LPTMR timer control/status register
+}
+
+void Timer_LPTMR::__timer_isr() {
     LPTMR0->CSR |= LPTMR_CSR_TCF_MASK;  //Write 1 to TCF to clear the LPT timer compare flag
-    __set_lptmr(__rolloverValue); //Set timer again
+    if ((__periodic || __call_user_function) && __user_fptr != NULL) { //user callback
+        __user_fptr->call();
+        __call_user_function = false;
+    }   
     __count++;
 }
 
-void Timer_LPTMR::__set_lptmr(uint16_t count) {
-    LPTMR0->CSR = 0; //Reset the timer control/status register
-    LPTMR0->CMR = count; //Set the compare register
-    LPTMR0->CSR |= LPTMR_CSR_TIE_MASK; //Enable interrupt
-   // LPTMR0->CSR |= LPTMR_CSR_TFC_MASK; //Set free-running mode
-    LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; //Start the timer
+void Timer_LPTMR::__lptmr_isr_wrapper() {
+    __obj->__timer_isr();   
 }
\ No newline at end of file