Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Fri Jan 19 18:38:15 2018 +0000
Revision:
21:48fe75bcde84
Parent:
20:62e0760cae13
Child:
22:df0b906bda26
Swapped timer from TIM1 to TIM0

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 20:62e0760cae13 75 TickTicked = true;
andrewboyson 20:62e0760cae13 76 }
andrewboyson 20:62e0760cae13 77 else
andrewboyson 20:62e0760cae13 78 {
andrewboyson 20:62e0760cae13 79 TickTicked = false;
andrewboyson 18:207dd1474cd9 80 }
andrewboyson 0:33686e88f09a 81 }
andrewboyson 18:207dd1474cd9 82 static volatile int64_t nsTickSnapshot;
andrewboyson 18:207dd1474cd9 83 static volatile int64_t nsFreqSnapshot;
andrewboyson 18:207dd1474cd9 84 static volatile int64_t nsTimeSnapshot;
andrewboyson 18:207dd1474cd9 85 static volatile uint32_t timerSnapshot;
andrewboyson 0:33686e88f09a 86
andrewboyson 0:33686e88f09a 87 void TickSaveSnapshotI()
andrewboyson 0:33686e88f09a 88 {
andrewboyson 21:48fe75bcde84 89 timerSnapshot = LPC_TIM0->TC - secondsBaseCount;
andrewboyson 0:33686e88f09a 90 nsTickSnapshot = nsTickCount;
andrewboyson 0:33686e88f09a 91 nsFreqSnapshot = nsFreqCount;
andrewboyson 0:33686e88f09a 92 nsTimeSnapshot = nsTimeCount;
andrewboyson 0:33686e88f09a 93 }
andrewboyson 18:207dd1474cd9 94 static void makeTimesFromCounts(uint32_t timerCount, int64_t tickNs, int64_t freqNs, int64_t timeNs, int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 16:933cbe190bb0 95 {
andrewboyson 16:933cbe190bb0 96 int64_t fraction = timerCount;
andrewboyson 16:933cbe190bb0 97 fraction <<= 32;
andrewboyson 16:933cbe190bb0 98 fraction /= TICK_COUNT_PER_SECOND;
andrewboyson 16:933cbe190bb0 99
andrewboyson 0:33686e88f09a 100 int64_t nsFraction;
andrewboyson 0:33686e88f09a 101
andrewboyson 14:7ef557918bb1 102 int64_t nsBase = tickNs;
andrewboyson 0:33686e88f09a 103 int64_t nsPerTick = ONE_BILLION;
andrewboyson 16:933cbe190bb0 104
andrewboyson 14:7ef557918bb1 105 nsBase += freqNs;
andrewboyson 5:a3e37ce4975d 106 nsPerTick += ppb;
andrewboyson 0:33686e88f09a 107 nsFraction = (nsPerTick * fraction) >> 32;
andrewboyson 0:33686e88f09a 108 *pNsInt = nsBase + nsFraction;
andrewboyson 0:33686e88f09a 109
andrewboyson 14:7ef557918bb1 110 nsBase += timeNs;
andrewboyson 5:a3e37ce4975d 111 nsPerTick += slew;
andrewboyson 0:33686e88f09a 112 nsFraction = (nsPerTick * fraction) >> 32;
andrewboyson 0:33686e88f09a 113 *pNsAbs = nsBase + nsFraction;
andrewboyson 0:33686e88f09a 114 }
andrewboyson 14:7ef557918bb1 115 void TickRetrieveSnapshot(int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 14:7ef557918bb1 116 {
andrewboyson 14:7ef557918bb1 117 makeTimesFromCounts(timerSnapshot, nsTickSnapshot, nsFreqSnapshot, nsTimeSnapshot, pNsInt, pNsAbs);
andrewboyson 14:7ef557918bb1 118 }
andrewboyson 6:d8a6235486b7 119 void TickGetTimes(int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 0:33686e88f09a 120 {
andrewboyson 18:207dd1474cd9 121 uint32_t timerCount;
andrewboyson 18:207dd1474cd9 122 int64_t tickNs;
andrewboyson 18:207dd1474cd9 123 int64_t freqNs;
andrewboyson 18:207dd1474cd9 124 int64_t timeNs;
andrewboyson 14:7ef557918bb1 125
andrewboyson 21:48fe75bcde84 126 timerCount = LPC_TIM0->TC - secondsBaseCount;
andrewboyson 20:62e0760cae13 127 tickNs = nsTickCount;
andrewboyson 20:62e0760cae13 128 freqNs = nsFreqCount;
andrewboyson 20:62e0760cae13 129 timeNs = nsTimeCount;
andrewboyson 6:d8a6235486b7 130
andrewboyson 14:7ef557918bb1 131 makeTimesFromCounts(timerCount, tickNs, freqNs, timeNs, pNsInt, pNsAbs);
andrewboyson 0:33686e88f09a 132 }
andrewboyson 0:33686e88f09a 133
andrewboyson 17:927fc1eceb9d 134 void TickInit(void)
andrewboyson 0:33686e88f09a 135 {
andrewboyson 0:33686e88f09a 136 nsTickCount = 0;
andrewboyson 0:33686e88f09a 137 nsFreqCount = 0;
andrewboyson 0:33686e88f09a 138 nsTimeCount = 0;
andrewboyson 0:33686e88f09a 139
andrewboyson 5:a3e37ce4975d 140 ppb = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated
andrewboyson 5:a3e37ce4975d 141 slew = 0;
andrewboyson 18:207dd1474cd9 142 nsCountIsSet = false;
andrewboyson 0:33686e88f09a 143
andrewboyson 21:48fe75bcde84 144 LPC_TIM0->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
andrewboyson 21:48fe75bcde84 145 LPC_TIM0->CTCR = 0; // 21.6.3 Count Control Register - Timer mode
andrewboyson 21:48fe75bcde84 146 LPC_TIM0->PR = 0; // 21.6.5 Prescale register - Don't prescale 96MHz clock (divide by PR+1).
andrewboyson 21:48fe75bcde84 147 LPC_TIM0->MCR = 0; // 21.6.8 Match Control Register - no interrupt or reset
andrewboyson 21:48fe75bcde84 148 LPC_TIM0->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC
andrewboyson 0:33686e88f09a 149 }
andrewboyson 18:207dd1474cd9 150 uint32_t TickElapsed(uint32_t* pLastTime)
andrewboyson 14:7ef557918bb1 151 {
andrewboyson 21:48fe75bcde84 152 uint32_t thisTime = LPC_TIM0->TC;
andrewboyson 18:207dd1474cd9 153 uint32_t elapsed = thisTime - *pLastTime;
andrewboyson 14:7ef557918bb1 154 *pLastTime = thisTime;
andrewboyson 14:7ef557918bb1 155 return elapsed;
andrewboyson 14:7ef557918bb1 156 }
andrewboyson 19:e537bacd1478 157 uint32_t TickTimerStart()
andrewboyson 19:e537bacd1478 158 {
andrewboyson 21:48fe75bcde84 159 return LPC_TIM0->TC;
andrewboyson 19:e537bacd1478 160 }
andrewboyson 19:e537bacd1478 161 uint32_t TickTimerCount(uint32_t startCount)
andrewboyson 19:e537bacd1478 162 {
andrewboyson 21:48fe75bcde84 163 uint32_t thisCount = LPC_TIM0->TC;
andrewboyson 19:e537bacd1478 164 return thisCount - startCount;
andrewboyson 19:e537bacd1478 165 }
andrewboyson 19:e537bacd1478 166 uint32_t TickTimerMs(uint32_t startCount)
andrewboyson 19:e537bacd1478 167 {
andrewboyson 19:e537bacd1478 168 uint32_t count = TickTimerCount(startCount);
andrewboyson 19:e537bacd1478 169 return count / 96000;
andrewboyson 19:e537bacd1478 170 }