Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Revision:
17:927fc1eceb9d
Parent:
16:933cbe190bb0
Child:
18:207dd1474cd9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tick.c	Thu Jan 11 17:39:36 2018 +0000
@@ -0,0 +1,152 @@
+#include "peripherals.h"
+#include  "rtc.h"
+#include "time.h"
+#include "tick.h"
+
+#define TRUE  1
+#define FALSE 0
+
+#define ONE_BILLION 1000000000
+
+static volatile int64_t nsTickCount;
+static volatile int64_t nsFreqCount;
+static volatile int64_t nsTimeCount;
+
+static int nsCountIsSet = FALSE;
+int  TickIsSet() { return nsCountIsSet; }
+void TickSet(int64_t extClock)
+{
+    nsTickCount   = 0;
+    nsFreqCount   = 0;
+    nsTimeCount   = extClock;
+    LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset  TC and PC.
+    LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC.
+    nsCountIsSet = TRUE;
+}
+
+static volatile int32_t slew = 0; //ns     - up to +/- 2.147s of slew
+int32_t TickGetSlew() { return slew; }
+void    TickSetSlew(int32_t value) { slew = value; }
+
+static volatile int32_t ppb  = 0;
+int32_t TickGetPpb () { return ppb;  }
+void    TickSetPpb (int32_t value) { ppb  = value; LPC_RTC->GPREG0 = ppb; }
+void    TickAddPpb (int32_t value) { ppb += value; LPC_RTC->GPREG0 = ppb; }
+
+#define CLOCK_TIC 0
+#define CLOCK_INT 1
+#define CLOCK_ABS 2
+
+__irq void TickHandler(void)
+{//Checked the number of counts and this routine takes 46 counts or about 0.5us
+
+    //Reset the timer interrupt
+    LPC_TIM1->IR |= 1;
+    
+    //reset the tick timer
+    LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset  TC and PC.
+    LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC
+    
+    //Calculate the new counts
+    nsTickCount += ONE_BILLION;
+    nsFreqCount += ppb;
+    nsTimeCount += slew;
+    
+    //Feedback the amount slewed
+    slew = 0;
+}
+static volatile int64_t nsTickSnapshot;
+static volatile int64_t nsFreqSnapshot;
+static volatile int64_t nsTimeSnapshot;
+static volatile int32_t  timerSnapshot;
+
+void TickSaveSnapshotI()
+{
+     timerSnapshot = LPC_TIM1->TC;
+    nsTickSnapshot = nsTickCount;
+    nsFreqSnapshot = nsFreqCount;
+    nsTimeSnapshot = nsTimeCount;
+}
+static void makeTimesFromCounts(int32_t timerCount, int64_t tickNs, int64_t freqNs, int64_t timeNs, int64_t* pNsInt, int64_t* pNsAbs)
+{
+    int64_t   fraction = timerCount;
+              fraction <<= 32;
+              fraction /= TICK_COUNT_PER_SECOND;
+
+    int64_t nsFraction;
+    
+    int64_t nsBase     = tickNs;
+    int64_t nsPerTick  = ONE_BILLION;
+     
+    nsBase    += freqNs;
+    nsPerTick += ppb;
+    nsFraction = (nsPerTick * fraction) >> 32;
+    *pNsInt = nsBase + nsFraction;
+
+    nsBase    += timeNs;
+    nsPerTick += slew;
+    nsFraction = (nsPerTick * fraction) >> 32;
+    *pNsAbs = nsBase + nsFraction;
+}
+void TickRetrieveSnapshot(int64_t* pNsInt, int64_t* pNsAbs)
+{
+    makeTimesFromCounts(timerSnapshot, nsTickSnapshot, nsFreqSnapshot, nsTimeSnapshot, pNsInt, pNsAbs);
+}
+void TickGetTimes(int64_t* pNsInt, int64_t* pNsAbs)
+{
+    int32_t timerCount;
+    int64_t tickNs;
+    int64_t freqNs;
+    int64_t timeNs;
+    
+    __disable_irq();
+        timerCount = LPC_TIM1->TC;
+         tickNs    = nsTickCount;
+         freqNs    = nsFreqCount;
+         timeNs    = nsTimeCount;
+    __enable_irq();
+    
+    makeTimesFromCounts(timerCount, tickNs, freqNs, timeNs, pNsInt, pNsAbs);
+}
+
+void TickInit(void)
+{
+    nsTickCount = 0;
+    nsFreqCount = 0;
+    nsTimeCount = 0;
+    
+    ppb  = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated
+    slew = 0;
+    nsCountIsSet = FALSE;
+    
+    LPC_SC->PCLKSEL0 &= ~0x20; //  4.7.3 Peripheral Clock Selection - PCLK_peripheral PCLK_TIMER1 01xxxx = CCLK - reset bit 5
+    LPC_SC->PCLKSEL0 |=  0x10; //                                                                                   set bit 4
+    LPC_SC->PCONP    |=     4; //  4.8.9 Power Control for Peripherals register - Timer1 Power On
+    LPC_TIM1->TCR     =     2; // 21.6.2 Timer Control Register - Reset TC and PC.
+    LPC_TIM1->CTCR    =     0; // 21.6.3 Count Control Register - Timer mode
+    LPC_TIM1->PR      =     0; // 21.6.5 Prescale register      - Don't prescale 96MHz clock (divide by PR+1).
+    LPC_TIM1->MR0     = TICK_COUNT_PER_SECOND; // 21.6.7 Match Register 0       - Match count
+    LPC_TIM1->MCR     =     1; // 21.6.8 Match Control Register - interrupt on match
+    LPC_TIM1->TCR     =     1; // 21.6.2 Timer Control Register - Enable TC and PC
+    
+    NVIC->ISER[0] |= 0x04;     //  6.5.1 bit2 == Interrupt set enable for timer 1.
+}
+int32_t TickElapsed(int32_t* pLastTime)
+{
+    int32_t thisTime = LPC_TIM1->TC;
+    
+    if (thisTime < *pLastTime) *pLastTime -= TICK_COUNT_PER_SECOND; //lastCount could be 96 000 002 and thisTime could be 00 000 100 which should give 98
+    int32_t elapsed = thisTime - *pLastTime;
+    
+    *pLastTime = thisTime;
+    return elapsed;
+}
+int Ticked(int32_t* pLastTime)
+{
+    int thisTime = LPC_TIM1->TC;
+    
+    int ticked = thisTime < *pLastTime;
+    
+    *pLastTime = thisTime;
+    return ticked;
+}