Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Fri Jan 19 19:59:43 2018 +0000
Revision:
22:df0b906bda26
Parent:
21:48fe75bcde84
Child:
23:07b19cd5f6d0
Corrected the tick to occur on the second

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 18:207dd1474cd9 1 #include <stdint.h>
andrewboyson 18:207dd1474cd9 2 #include <stdbool.h>
andrewboyson 18:207dd1474cd9 3
andrewboyson 17:927fc1eceb9d 4 #include "peripherals.h"
andrewboyson 14:7ef557918bb1 5 #include "rtc.h"
andrewboyson 14:7ef557918bb1 6 #include "time.h"
andrewboyson 14:7ef557918bb1 7 #include "tick.h"
andrewboyson 18:207dd1474cd9 8 #include "led.h"
andrewboyson 18:207dd1474cd9 9 #include "log.h"
andrewboyson 0:33686e88f09a 10
andrewboyson 0:33686e88f09a 11 #define ONE_BILLION 1000000000
andrewboyson 0:33686e88f09a 12
andrewboyson 16:933cbe190bb0 13 static volatile int64_t nsTickCount;
andrewboyson 16:933cbe190bb0 14 static volatile int64_t nsFreqCount;
andrewboyson 16:933cbe190bb0 15 static volatile int64_t nsTimeCount;
andrewboyson 18:207dd1474cd9 16 static bool nsCountIsSet = false;
andrewboyson 18:207dd1474cd9 17 bool TickIsSet() { return nsCountIsSet; }
andrewboyson 0:33686e88f09a 18
andrewboyson 16:933cbe190bb0 19 static volatile int32_t slew = 0; //ns - up to +/- 2.147s of slew
andrewboyson 5:a3e37ce4975d 20 int32_t TickGetSlew() { return slew; }
andrewboyson 5:a3e37ce4975d 21 void TickSetSlew(int32_t value) { slew = value; }
andrewboyson 5:a3e37ce4975d 22
andrewboyson 16:933cbe190bb0 23 static volatile int32_t ppb = 0;
andrewboyson 5:a3e37ce4975d 24 int32_t TickGetPpb () { return ppb; }
andrewboyson 5:a3e37ce4975d 25 void TickSetPpb (int32_t value) { ppb = value; LPC_RTC->GPREG0 = ppb; }
andrewboyson 5:a3e37ce4975d 26 void TickAddPpb (int32_t value) { ppb += value; LPC_RTC->GPREG0 = ppb; }
andrewboyson 0:33686e88f09a 27
andrewboyson 20:62e0760cae13 28 bool TickTicked = false;
andrewboyson 20:62e0760cae13 29
andrewboyson 20:62e0760cae13 30 /*
andrewboyson 20:62e0760cae13 31 +---------+---------------+
andrewboyson 20:62e0760cae13 32 | Seconds | Base count |
andrewboyson 20:62e0760cae13 33 +---------+---------------+
andrewboyson 20:62e0760cae13 34 | 0 | 0 |
andrewboyson 20:62e0760cae13 35 | 1 | 96,000,000 |
andrewboyson 20:62e0760cae13 36 | ... | ... |
andrewboyson 20:62e0760cae13 37 | 44 | 4,224,000,000 |
andrewboyson 20:62e0760cae13 38 | 44.74 | 2^32 |
andrewboyson 20:62e0760cae13 39 | 45 | 25,032,704 |
andrewboyson 20:62e0760cae13 40 | ... | ... |
andrewboyson 20:62e0760cae13 41 +---------+---------------+
andrewboyson 20:62e0760cae13 42 */
andrewboyson 20:62e0760cae13 43 static uint32_t secondsBaseCount = 0;
andrewboyson 20:62e0760cae13 44
andrewboyson 20:62e0760cae13 45 void TickSet(int64_t extClock)
andrewboyson 20:62e0760cae13 46 {
andrewboyson 21:48fe75bcde84 47 uint32_t tc = LPC_TIM0->TC;
andrewboyson 20:62e0760cae13 48 uint32_t seconds = tc / TICK_COUNT_PER_SECOND; //0 to 44
andrewboyson 20:62e0760cae13 49 uint32_t base = seconds * TICK_COUNT_PER_SECOND; //0 to 2^32
andrewboyson 20:62e0760cae13 50 uint32_t fraction = tc % TICK_COUNT_PER_SECOND; //0 to 96,000,000
andrewboyson 20:62e0760cae13 51 uint32_t fractionNs = fraction / 96 * 1000; //0 to 1,000,000,000 which fits into 32 bits
andrewboyson 20:62e0760cae13 52 int64_t ns = extClock - fractionNs;
andrewboyson 20:62e0760cae13 53
andrewboyson 20:62e0760cae13 54 __disable_irq();
andrewboyson 20:62e0760cae13 55 nsTickCount = ns;
andrewboyson 20:62e0760cae13 56 nsFreqCount = 0;
andrewboyson 20:62e0760cae13 57 nsTimeCount = 0;
andrewboyson 20:62e0760cae13 58 secondsBaseCount = base;
andrewboyson 20:62e0760cae13 59 __enable_irq();
andrewboyson 20:62e0760cae13 60
andrewboyson 20:62e0760cae13 61 nsCountIsSet = true;
andrewboyson 20:62e0760cae13 62 }
andrewboyson 18:207dd1474cd9 63 void TickMain()
andrewboyson 18:207dd1474cd9 64 {
andrewboyson 21:48fe75bcde84 65 uint32_t sincesecondsBaseCount = LPC_TIM0->TC - secondsBaseCount;
andrewboyson 20:62e0760cae13 66 if (sincesecondsBaseCount > TICK_COUNT_PER_SECOND)
andrewboyson 18:207dd1474cd9 67 {
andrewboyson 18:207dd1474cd9 68 __disable_irq();
andrewboyson 20:62e0760cae13 69 secondsBaseCount += TICK_COUNT_PER_SECOND;
andrewboyson 20:62e0760cae13 70 nsTickCount += ONE_BILLION;
andrewboyson 20:62e0760cae13 71 nsFreqCount += ppb;
andrewboyson 20:62e0760cae13 72 nsTimeCount += slew;
andrewboyson 18:207dd1474cd9 73 __enable_irq();
andrewboyson 20:62e0760cae13 74 slew = 0;
andrewboyson 18:207dd1474cd9 75 }
andrewboyson 0:33686e88f09a 76 }
andrewboyson 18:207dd1474cd9 77 static volatile int64_t nsTickSnapshot;
andrewboyson 18:207dd1474cd9 78 static volatile int64_t nsFreqSnapshot;
andrewboyson 18:207dd1474cd9 79 static volatile int64_t nsTimeSnapshot;
andrewboyson 18:207dd1474cd9 80 static volatile uint32_t timerSnapshot;
andrewboyson 0:33686e88f09a 81
andrewboyson 22:df0b906bda26 82 void TickSaveSnapshot()
andrewboyson 0:33686e88f09a 83 {
andrewboyson 21:48fe75bcde84 84 timerSnapshot = LPC_TIM0->TC - secondsBaseCount;
andrewboyson 0:33686e88f09a 85 nsTickSnapshot = nsTickCount;
andrewboyson 0:33686e88f09a 86 nsFreqSnapshot = nsFreqCount;
andrewboyson 0:33686e88f09a 87 nsTimeSnapshot = nsTimeCount;
andrewboyson 0:33686e88f09a 88 }
andrewboyson 18:207dd1474cd9 89 static void makeTimesFromCounts(uint32_t timerCount, int64_t tickNs, int64_t freqNs, int64_t timeNs, int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 16:933cbe190bb0 90 {
andrewboyson 16:933cbe190bb0 91 int64_t fraction = timerCount;
andrewboyson 16:933cbe190bb0 92 fraction <<= 32;
andrewboyson 16:933cbe190bb0 93 fraction /= TICK_COUNT_PER_SECOND;
andrewboyson 16:933cbe190bb0 94
andrewboyson 0:33686e88f09a 95 int64_t nsFraction;
andrewboyson 0:33686e88f09a 96
andrewboyson 14:7ef557918bb1 97 int64_t nsBase = tickNs;
andrewboyson 0:33686e88f09a 98 int64_t nsPerTick = ONE_BILLION;
andrewboyson 16:933cbe190bb0 99
andrewboyson 14:7ef557918bb1 100 nsBase += freqNs;
andrewboyson 5:a3e37ce4975d 101 nsPerTick += ppb;
andrewboyson 0:33686e88f09a 102 nsFraction = (nsPerTick * fraction) >> 32;
andrewboyson 0:33686e88f09a 103 *pNsInt = nsBase + nsFraction;
andrewboyson 0:33686e88f09a 104
andrewboyson 14:7ef557918bb1 105 nsBase += timeNs;
andrewboyson 5:a3e37ce4975d 106 nsPerTick += slew;
andrewboyson 0:33686e88f09a 107 nsFraction = (nsPerTick * fraction) >> 32;
andrewboyson 0:33686e88f09a 108 *pNsAbs = nsBase + nsFraction;
andrewboyson 0:33686e88f09a 109 }
andrewboyson 22:df0b906bda26 110 void TickGetTimesFromSnapshot(int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 14:7ef557918bb1 111 {
andrewboyson 14:7ef557918bb1 112 makeTimesFromCounts(timerSnapshot, nsTickSnapshot, nsFreqSnapshot, nsTimeSnapshot, pNsInt, pNsAbs);
andrewboyson 14:7ef557918bb1 113 }
andrewboyson 6:d8a6235486b7 114 void TickGetTimes(int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 0:33686e88f09a 115 {
andrewboyson 18:207dd1474cd9 116 uint32_t timerCount;
andrewboyson 18:207dd1474cd9 117 int64_t tickNs;
andrewboyson 18:207dd1474cd9 118 int64_t freqNs;
andrewboyson 18:207dd1474cd9 119 int64_t timeNs;
andrewboyson 14:7ef557918bb1 120
andrewboyson 21:48fe75bcde84 121 timerCount = LPC_TIM0->TC - secondsBaseCount;
andrewboyson 20:62e0760cae13 122 tickNs = nsTickCount;
andrewboyson 20:62e0760cae13 123 freqNs = nsFreqCount;
andrewboyson 20:62e0760cae13 124 timeNs = nsTimeCount;
andrewboyson 6:d8a6235486b7 125
andrewboyson 14:7ef557918bb1 126 makeTimesFromCounts(timerCount, tickNs, freqNs, timeNs, pNsInt, pNsAbs);
andrewboyson 0:33686e88f09a 127 }
andrewboyson 0:33686e88f09a 128
andrewboyson 17:927fc1eceb9d 129 void TickInit(void)
andrewboyson 0:33686e88f09a 130 {
andrewboyson 0:33686e88f09a 131 nsTickCount = 0;
andrewboyson 0:33686e88f09a 132 nsFreqCount = 0;
andrewboyson 0:33686e88f09a 133 nsTimeCount = 0;
andrewboyson 0:33686e88f09a 134
andrewboyson 5:a3e37ce4975d 135 ppb = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated
andrewboyson 5:a3e37ce4975d 136 slew = 0;
andrewboyson 18:207dd1474cd9 137 nsCountIsSet = false;
andrewboyson 0:33686e88f09a 138
andrewboyson 21:48fe75bcde84 139 LPC_TIM0->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
andrewboyson 21:48fe75bcde84 140 LPC_TIM0->CTCR = 0; // 21.6.3 Count Control Register - Timer mode
andrewboyson 21:48fe75bcde84 141 LPC_TIM0->PR = 0; // 21.6.5 Prescale register - Don't prescale 96MHz clock (divide by PR+1).
andrewboyson 21:48fe75bcde84 142 LPC_TIM0->MCR = 0; // 21.6.8 Match Control Register - no interrupt or reset
andrewboyson 21:48fe75bcde84 143 LPC_TIM0->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC
andrewboyson 0:33686e88f09a 144 }
andrewboyson 18:207dd1474cd9 145 uint32_t TickElapsed(uint32_t* pLastTime)
andrewboyson 14:7ef557918bb1 146 {
andrewboyson 21:48fe75bcde84 147 uint32_t thisTime = LPC_TIM0->TC;
andrewboyson 18:207dd1474cd9 148 uint32_t elapsed = thisTime - *pLastTime;
andrewboyson 14:7ef557918bb1 149 *pLastTime = thisTime;
andrewboyson 14:7ef557918bb1 150 return elapsed;
andrewboyson 14:7ef557918bb1 151 }
andrewboyson 19:e537bacd1478 152 uint32_t TickTimerStart()
andrewboyson 19:e537bacd1478 153 {
andrewboyson 21:48fe75bcde84 154 return LPC_TIM0->TC;
andrewboyson 19:e537bacd1478 155 }
andrewboyson 19:e537bacd1478 156 uint32_t TickTimerCount(uint32_t startCount)
andrewboyson 19:e537bacd1478 157 {
andrewboyson 21:48fe75bcde84 158 uint32_t thisCount = LPC_TIM0->TC;
andrewboyson 19:e537bacd1478 159 return thisCount - startCount;
andrewboyson 19:e537bacd1478 160 }
andrewboyson 19:e537bacd1478 161 uint32_t TickTimerMs(uint32_t startCount)
andrewboyson 19:e537bacd1478 162 {
andrewboyson 19:e537bacd1478 163 uint32_t count = TickTimerCount(startCount);
andrewboyson 19:e537bacd1478 164 return count / 96000;
andrewboyson 19:e537bacd1478 165 }