Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Sat Dec 16 14:51:41 2017 +0000
Revision:
16:933cbe190bb0
Parent:
14:7ef557918bb1
Made a few variables volatile if they were adjusted within an interrupt.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 14:7ef557918bb1 1 #include "mbed.h"
andrewboyson 14:7ef557918bb1 2 #include "rtc.h"
andrewboyson 14:7ef557918bb1 3 #include "time.h"
andrewboyson 14:7ef557918bb1 4 #include "tick.h"
andrewboyson 16:933cbe190bb0 5 #include "io.h"
andrewboyson 0:33686e88f09a 6
andrewboyson 0:33686e88f09a 7 #define ONE_BILLION 1000000000
andrewboyson 0:33686e88f09a 8
andrewboyson 16:933cbe190bb0 9 static volatile int64_t nsTickCount;
andrewboyson 16:933cbe190bb0 10 static volatile int64_t nsFreqCount;
andrewboyson 16:933cbe190bb0 11 static volatile int64_t nsTimeCount;
andrewboyson 16:933cbe190bb0 12
andrewboyson 5:a3e37ce4975d 13 static bool nsCountIsSet = false;
andrewboyson 5:a3e37ce4975d 14 bool TickIsSet() { return nsCountIsSet; }
andrewboyson 5:a3e37ce4975d 15 void TickSet(int64_t extClock)
andrewboyson 5:a3e37ce4975d 16 {
andrewboyson 5:a3e37ce4975d 17 nsTickCount = 0;
andrewboyson 5:a3e37ce4975d 18 nsFreqCount = 0;
andrewboyson 5:a3e37ce4975d 19 nsTimeCount = extClock;
andrewboyson 5:a3e37ce4975d 20 LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
andrewboyson 5:a3e37ce4975d 21 LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC.
andrewboyson 5:a3e37ce4975d 22 nsCountIsSet = true;
andrewboyson 5:a3e37ce4975d 23 }
andrewboyson 0:33686e88f09a 24
andrewboyson 16:933cbe190bb0 25 static volatile int32_t slew = 0; //ns - up to +/- 2.147s of slew
andrewboyson 5:a3e37ce4975d 26 int32_t TickGetSlew() { return slew; }
andrewboyson 5:a3e37ce4975d 27 void TickSetSlew(int32_t value) { slew = value; }
andrewboyson 5:a3e37ce4975d 28
andrewboyson 16:933cbe190bb0 29 static volatile int32_t ppb = 0;
andrewboyson 5:a3e37ce4975d 30 int32_t TickGetPpb () { return ppb; }
andrewboyson 5:a3e37ce4975d 31 void TickSetPpb (int32_t value) { ppb = value; LPC_RTC->GPREG0 = ppb; }
andrewboyson 5:a3e37ce4975d 32 void TickAddPpb (int32_t value) { ppb += value; LPC_RTC->GPREG0 = ppb; }
andrewboyson 0:33686e88f09a 33
andrewboyson 0:33686e88f09a 34 #define CLOCK_TIC 0
andrewboyson 0:33686e88f09a 35 #define CLOCK_INT 1
andrewboyson 0:33686e88f09a 36 #define CLOCK_ABS 2
andrewboyson 0:33686e88f09a 37
andrewboyson 9:cd30749dfa3d 38 static void tick(void)
andrewboyson 9:cd30749dfa3d 39 {//Checked the number of counts and this routine takes 46 counts or about 0.5us
andrewboyson 9:cd30749dfa3d 40
andrewboyson 0:33686e88f09a 41 //Reset the timer interrupt
andrewboyson 0:33686e88f09a 42 LPC_TIM1->IR |= 1;
andrewboyson 0:33686e88f09a 43
andrewboyson 0:33686e88f09a 44 //reset the tick timer
andrewboyson 0:33686e88f09a 45 LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
andrewboyson 0:33686e88f09a 46 LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC
andrewboyson 0:33686e88f09a 47
andrewboyson 0:33686e88f09a 48 //Calculate the new counts
andrewboyson 0:33686e88f09a 49 nsTickCount += ONE_BILLION;
andrewboyson 5:a3e37ce4975d 50 nsFreqCount += ppb;
andrewboyson 5:a3e37ce4975d 51 nsTimeCount += slew;
andrewboyson 0:33686e88f09a 52
andrewboyson 0:33686e88f09a 53 //Feedback the amount slewed
andrewboyson 5:a3e37ce4975d 54 slew = 0;
andrewboyson 0:33686e88f09a 55 }
andrewboyson 0:33686e88f09a 56 static volatile int64_t nsTickSnapshot;
andrewboyson 0:33686e88f09a 57 static volatile int64_t nsFreqSnapshot;
andrewboyson 0:33686e88f09a 58 static volatile int64_t nsTimeSnapshot;
andrewboyson 0:33686e88f09a 59 static volatile int32_t timerSnapshot;
andrewboyson 0:33686e88f09a 60
andrewboyson 0:33686e88f09a 61 void TickSaveSnapshotI()
andrewboyson 0:33686e88f09a 62 {
andrewboyson 0:33686e88f09a 63 timerSnapshot = LPC_TIM1->TC;
andrewboyson 0:33686e88f09a 64 nsTickSnapshot = nsTickCount;
andrewboyson 0:33686e88f09a 65 nsFreqSnapshot = nsFreqCount;
andrewboyson 0:33686e88f09a 66 nsTimeSnapshot = nsTimeCount;
andrewboyson 0:33686e88f09a 67 }
andrewboyson 14:7ef557918bb1 68 static void makeTimesFromCounts(int32_t timerCount, int64_t tickNs, int64_t freqNs, int64_t timeNs, int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 16:933cbe190bb0 69 {
andrewboyson 16:933cbe190bb0 70 int64_t fraction = timerCount;
andrewboyson 16:933cbe190bb0 71 fraction <<= 32;
andrewboyson 16:933cbe190bb0 72 fraction /= TICK_COUNT_PER_SECOND;
andrewboyson 16:933cbe190bb0 73
andrewboyson 0:33686e88f09a 74 int64_t nsFraction;
andrewboyson 0:33686e88f09a 75
andrewboyson 14:7ef557918bb1 76 int64_t nsBase = tickNs;
andrewboyson 0:33686e88f09a 77 int64_t nsPerTick = ONE_BILLION;
andrewboyson 16:933cbe190bb0 78
andrewboyson 14:7ef557918bb1 79 nsBase += freqNs;
andrewboyson 5:a3e37ce4975d 80 nsPerTick += ppb;
andrewboyson 0:33686e88f09a 81 nsFraction = (nsPerTick * fraction) >> 32;
andrewboyson 0:33686e88f09a 82 *pNsInt = nsBase + nsFraction;
andrewboyson 0:33686e88f09a 83
andrewboyson 14:7ef557918bb1 84 nsBase += timeNs;
andrewboyson 5:a3e37ce4975d 85 nsPerTick += slew;
andrewboyson 0:33686e88f09a 86 nsFraction = (nsPerTick * fraction) >> 32;
andrewboyson 0:33686e88f09a 87 *pNsAbs = nsBase + nsFraction;
andrewboyson 0:33686e88f09a 88 }
andrewboyson 14:7ef557918bb1 89 void TickRetrieveSnapshot(int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 14:7ef557918bb1 90 {
andrewboyson 14:7ef557918bb1 91 makeTimesFromCounts(timerSnapshot, nsTickSnapshot, nsFreqSnapshot, nsTimeSnapshot, pNsInt, pNsAbs);
andrewboyson 14:7ef557918bb1 92 }
andrewboyson 6:d8a6235486b7 93 void TickGetTimes(int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 0:33686e88f09a 94 {
andrewboyson 14:7ef557918bb1 95 int32_t timerCount;
andrewboyson 14:7ef557918bb1 96 int64_t tickNs;
andrewboyson 14:7ef557918bb1 97 int64_t freqNs;
andrewboyson 14:7ef557918bb1 98 int64_t timeNs;
andrewboyson 14:7ef557918bb1 99
andrewboyson 0:33686e88f09a 100 __disable_irq();
andrewboyson 14:7ef557918bb1 101 timerCount = LPC_TIM1->TC;
andrewboyson 14:7ef557918bb1 102 tickNs = nsTickCount;
andrewboyson 14:7ef557918bb1 103 freqNs = nsFreqCount;
andrewboyson 14:7ef557918bb1 104 timeNs = nsTimeCount;
andrewboyson 0:33686e88f09a 105 __enable_irq();
andrewboyson 6:d8a6235486b7 106
andrewboyson 14:7ef557918bb1 107 makeTimesFromCounts(timerCount, tickNs, freqNs, timeNs, pNsInt, pNsAbs);
andrewboyson 0:33686e88f09a 108 }
andrewboyson 0:33686e88f09a 109
andrewboyson 0:33686e88f09a 110 int TickInit(void)
andrewboyson 0:33686e88f09a 111 {
andrewboyson 0:33686e88f09a 112 nsTickCount = 0;
andrewboyson 0:33686e88f09a 113 nsFreqCount = 0;
andrewboyson 0:33686e88f09a 114 nsTimeCount = 0;
andrewboyson 0:33686e88f09a 115
andrewboyson 5:a3e37ce4975d 116 ppb = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated
andrewboyson 5:a3e37ce4975d 117 slew = 0;
andrewboyson 5:a3e37ce4975d 118 nsCountIsSet = false;
andrewboyson 0:33686e88f09a 119
andrewboyson 14:7ef557918bb1 120 LPC_SC->PCLKSEL0 &= ~0x20; // 4.7.3 Peripheral Clock Selection - PCLK_peripheral PCLK_TIMER1 01xxxx = CCLK - reset bit 5
andrewboyson 14:7ef557918bb1 121 LPC_SC->PCLKSEL0 |= 0x10; // set bit 4
andrewboyson 14:7ef557918bb1 122 LPC_SC->PCONP |= 4; // 4.8.9 Power Control for Peripherals register - Timer1 Power On
andrewboyson 14:7ef557918bb1 123 LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
andrewboyson 14:7ef557918bb1 124 LPC_TIM1->CTCR = 0; // 21.6.3 Count Control Register - Timer mode
andrewboyson 14:7ef557918bb1 125 LPC_TIM1->PR = 0; // 21.6.5 Prescale register - Don't prescale 96MHz clock (divide by PR+1).
andrewboyson 14:7ef557918bb1 126 LPC_TIM1->MR0 = TICK_COUNT_PER_SECOND; // 21.6.7 Match Register 0 - Match count
andrewboyson 14:7ef557918bb1 127 LPC_TIM1->MCR = 1; // 21.6.8 Match Control Register - interrupt on match
andrewboyson 14:7ef557918bb1 128 LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC
andrewboyson 0:33686e88f09a 129
andrewboyson 0:33686e88f09a 130 NVIC_SetVector(TIMER1_IRQn, (uint32_t)&tick);
andrewboyson 0:33686e88f09a 131 NVIC_EnableIRQ(TIMER1_IRQn);
andrewboyson 0:33686e88f09a 132
andrewboyson 0:33686e88f09a 133 return 0;
andrewboyson 0:33686e88f09a 134 }
andrewboyson 14:7ef557918bb1 135 int32_t TickElapsed(int32_t* pLastTime)
andrewboyson 14:7ef557918bb1 136 {
andrewboyson 14:7ef557918bb1 137 int32_t thisTime = LPC_TIM1->TC;
andrewboyson 14:7ef557918bb1 138
andrewboyson 14:7ef557918bb1 139 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
andrewboyson 14:7ef557918bb1 140 int32_t elapsed = thisTime - *pLastTime;
andrewboyson 14:7ef557918bb1 141
andrewboyson 14:7ef557918bb1 142 *pLastTime = thisTime;
andrewboyson 14:7ef557918bb1 143 return elapsed;
andrewboyson 14:7ef557918bb1 144 }
andrewboyson 14:7ef557918bb1 145 bool Ticked(int32_t* pLastTime)
andrewboyson 14:7ef557918bb1 146 {
andrewboyson 14:7ef557918bb1 147 int thisTime = LPC_TIM1->TC;
andrewboyson 14:7ef557918bb1 148
andrewboyson 14:7ef557918bb1 149 bool ticked = thisTime < *pLastTime;
andrewboyson 14:7ef557918bb1 150
andrewboyson 14:7ef557918bb1 151 *pLastTime = thisTime;
andrewboyson 14:7ef557918bb1 152 return ticked;
andrewboyson 14:7ef557918bb1 153 }