Mark Gottscho / HardwareTimersLib

Fork of HardwareTimersLib by Mark Gottscho

Revision:
7:78f6ee57d324
Parent:
5:ea14fc749f44
Child:
8:23c04123395c
--- a/Timer_TPM.cpp	Mon Mar 10 20:35:21 2014 +0000
+++ b/Timer_TPM.cpp	Tue Mar 11 00:52:13 2014 +0000
@@ -8,52 +8,81 @@
 #include "HardwareTimer.h"
 #include "Timer_TPM.h"
 
-//Init class static variable
-bool Timer_TPM::__initialized_tpm = false;
-uint16_t Timer_TPM::__rolloverValue = 0xFFFF;
-uint32_t Timer_TPM::__count = 0;
+//Init Timer_TPM class variables
+bool Timer_TPM::__tpm_used = false;
+Timer_TPM *Timer_TPM::__obj = NULL;
 
-
-Timer_TPM::Timer_TPM(float tickValue) :
-        HardwareTimer(tickValue)
+Timer_TPM::Timer_TPM() :
+        HardwareTimer(0xFFFF, 20.833333333, HardwareTimer::ns) //TPM has 16-bit counter. And at 48MHz, each clock cycle is 20.8333333 ns
         {   
+    if (__tpm_used)
+        __valid = false;
+    else {
+        __valid = true;
+        __tpm_used = true;
+        __obj = this;
+    }
 }
 
-Timer_TPM::~Timer_TPM() {}
-
-void Timer_TPM::disableTimer() {
-    if (!__valid)
-        return;
-        
-    TPM0->SC = 0; //Reset TPM
-    __enabled = false;
+Timer_TPM::~Timer_TPM() {
+    if (__valid) {
+        __tpm_used = false; //free the hardware TPM resource
+        __obj = NULL;
+    }
 }
 
 uint32_t Timer_TPM::getTick() {
-    //if (!__valid)
-    //    return 0;
+    if (!__valid)
+        return 0;
         
-    //Get raw time
-    //__disable_irq();
+    // CRITICAL SECTION
+    NVIC_DisableIRQ(TPM0_IRQn);
     TPM0->CNT = 0; //Need to write to the TPM CNT register in order to read it (buffering)
     uint16_t tick = TPM0->CNT;
     uint32_t count = __count;
-    //__enable_irq();
+    NVIC_EnableIRQ(TPM0_IRQn);
+    // END CRITICAL SECTION
     
     //Convert to ticks
     return (uint32_t) count * __rolloverValue + tick;
 }
 
-void Timer_TPM::__set_tpm(uint16_t count) {
-    //TPM0->SC &= ~TPM_SC_CMOD_MASK; //Stop clock
+void Timer_TPM::__init_timer() {    
+    //Set TPM clocks
+    SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); //Set TPM global clock source: MCGFLLCLK
+    SIM->SCGC6 |= SIM_SCGC6_TPM0_MASK; //Enable TPM block (clock gating)
+
+    TPM0->SC = 0; //Reset TPM
+    
+    //Configure TPM prescaler
+    TPM0->SC = TPM_SC_PS(0); //Prescaler set to 1
+    
+    //Set interrupt handler
+    NVIC_SetVector(TPM0_IRQn, (uint32_t) __tpm_isr_wrapper);
+    NVIC_EnableIRQ(TPM0_IRQn);
+}
+
+void Timer_TPM::__start_timer() {
     TPM0->CNT = 0; //Set the count register
-    TPM0->MOD = count; //Set the modulo register
+    TPM0->MOD = (uint16_t) __rolloverValue; //Set the modulo register
     TPM0->SC |= TPM_SC_TOIE_MASK; //Enable interrupt
     TPM0->SC |= TPM_SC_CMOD(1); //Start the timer. Timer will increment on the TPM clock edges, not an external clock
 }
 
-void Timer_TPM::__isr_tpm() {
+void Timer_TPM::__stop_timer() {
+    TPM0->SC = 0; //Reset TPM
+}
+
+void Timer_TPM::__timer_isr() {
     TPM0->SC |= TPM_SC_TOF_MASK;
-    __set_tpm(__rolloverValue);
+    TPM0->MOD = (uint16_t) __rolloverValue; //Set the modulo register
+    if ((__periodic || __call_user_function) && __user_fptr != NULL) { //user callback
+        __user_fptr->call();
+        __call_user_function = false;
+    }   
     __count++;
+}
+
+void Timer_TPM::__tpm_isr_wrapper() {
+    __obj->__timer_isr();   
 }
\ No newline at end of file