Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Mon Jan 22 18:54:23 2018 +0000
Revision:
25:81014a201736
Parent:
24:6c9833e2a049
Child:
26:0421132e6eaf
Moved timer defines from tick to timer

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 24:6c9833e2a049 5 #include "rtc.h"
andrewboyson 14:7ef557918bb1 6 #include "time.h"
andrewboyson 14:7ef557918bb1 7 #include "tick.h"
andrewboyson 24:6c9833e2a049 8 #include "timer.h"
andrewboyson 18:207dd1474cd9 9 #include "led.h"
andrewboyson 18:207dd1474cd9 10 #include "log.h"
andrewboyson 0:33686e88f09a 11
andrewboyson 0:33686e88f09a 12 #define ONE_BILLION 1000000000
andrewboyson 0:33686e88f09a 13
andrewboyson 16:933cbe190bb0 14 static volatile int64_t nsTickCount;
andrewboyson 23:07b19cd5f6d0 15 static volatile int64_t nsSlewCount;
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 24:6c9833e2a049 45 int64_t TickTime = 0; //30th bit is one second
andrewboyson 24:6c9833e2a049 46
andrewboyson 20:62e0760cae13 47 void TickSet(int64_t extClock)
andrewboyson 20:62e0760cae13 48 {
andrewboyson 24:6c9833e2a049 49 uint32_t tc = TimerNowCount();
andrewboyson 25:81014a201736 50 uint32_t seconds = tc / TIMER_COUNT_PER_SECOND; //0 to 44
andrewboyson 25:81014a201736 51 uint32_t base = seconds * TIMER_COUNT_PER_SECOND; //0 to 2^32
andrewboyson 25:81014a201736 52 uint32_t fraction = tc % TIMER_COUNT_PER_SECOND; //0 to 96,000,000
andrewboyson 20:62e0760cae13 53 uint32_t fractionNs = fraction / 96 * 1000; //0 to 1,000,000,000 which fits into 32 bits
andrewboyson 20:62e0760cae13 54 int64_t ns = extClock - fractionNs;
andrewboyson 20:62e0760cae13 55
andrewboyson 20:62e0760cae13 56 __disable_irq();
andrewboyson 20:62e0760cae13 57 nsTickCount = ns;
andrewboyson 23:07b19cd5f6d0 58 nsSlewCount = 0;
andrewboyson 20:62e0760cae13 59 secondsBaseCount = base;
andrewboyson 20:62e0760cae13 60 __enable_irq();
andrewboyson 20:62e0760cae13 61
andrewboyson 20:62e0760cae13 62 nsCountIsSet = true;
andrewboyson 20:62e0760cae13 63 }
andrewboyson 18:207dd1474cd9 64 void TickMain()
andrewboyson 18:207dd1474cd9 65 {
andrewboyson 24:6c9833e2a049 66 uint32_t sinceSecondsBaseCount = TimerSinceCount(secondsBaseCount);
andrewboyson 24:6c9833e2a049 67
andrewboyson 24:6c9833e2a049 68 //Update the times whenever there has been a system second
andrewboyson 25:81014a201736 69 if (sinceSecondsBaseCount > TIMER_COUNT_PER_SECOND)
andrewboyson 18:207dd1474cd9 70 {
andrewboyson 18:207dd1474cd9 71 __disable_irq();
andrewboyson 25:81014a201736 72 secondsBaseCount += TIMER_COUNT_PER_SECOND;
andrewboyson 23:07b19cd5f6d0 73 nsTickCount += ONE_BILLION + ppb;
andrewboyson 23:07b19cd5f6d0 74 nsSlewCount += slew;
andrewboyson 24:6c9833e2a049 75 slew = 0;
andrewboyson 18:207dd1474cd9 76 __enable_irq();
andrewboyson 25:81014a201736 77 sinceSecondsBaseCount -= TIMER_COUNT_PER_SECOND;
andrewboyson 18:207dd1474cd9 78 }
andrewboyson 24:6c9833e2a049 79
andrewboyson 24:6c9833e2a049 80 //Update TickTime
andrewboyson 24:6c9833e2a049 81 int64_t fraction = sinceSecondsBaseCount;
andrewboyson 24:6c9833e2a049 82 fraction <<= 32;
andrewboyson 25:81014a201736 83 fraction /= TIMER_COUNT_PER_SECOND;
andrewboyson 24:6c9833e2a049 84
andrewboyson 24:6c9833e2a049 85 int64_t nsBase = nsTickCount + nsSlewCount;
andrewboyson 24:6c9833e2a049 86 int64_t nsPerTick = ONE_BILLION + ppb + slew;
andrewboyson 24:6c9833e2a049 87 int64_t nsFraction = (nsPerTick * fraction) >> 32;
andrewboyson 24:6c9833e2a049 88 TickTime = nsBase + nsFraction;
andrewboyson 24:6c9833e2a049 89
andrewboyson 24:6c9833e2a049 90 //Update the ticked flag
andrewboyson 24:6c9833e2a049 91 static bool lastTick = false;
andrewboyson 24:6c9833e2a049 92 bool thisTick = TickTime & (1ULL << 30);
andrewboyson 24:6c9833e2a049 93 TickTicked = thisTick && !lastTick;
andrewboyson 24:6c9833e2a049 94 lastTick = TickTicked;
andrewboyson 24:6c9833e2a049 95
andrewboyson 0:33686e88f09a 96 }
andrewboyson 18:207dd1474cd9 97 static volatile int64_t nsTickSnapshot;
andrewboyson 23:07b19cd5f6d0 98 static volatile int64_t nsSlewSnapshot;
andrewboyson 18:207dd1474cd9 99 static volatile uint32_t timerSnapshot;
andrewboyson 0:33686e88f09a 100
andrewboyson 22:df0b906bda26 101 void TickSaveSnapshot()
andrewboyson 0:33686e88f09a 102 {
andrewboyson 24:6c9833e2a049 103 timerSnapshot = TimerSinceCount(secondsBaseCount);
andrewboyson 0:33686e88f09a 104 nsTickSnapshot = nsTickCount;
andrewboyson 23:07b19cd5f6d0 105 nsSlewSnapshot = nsSlewCount;
andrewboyson 0:33686e88f09a 106 }
andrewboyson 23:07b19cd5f6d0 107 static void makeTimesFromCounts(uint32_t timerCount, int64_t tickNs, int64_t slewNs, int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 16:933cbe190bb0 108 {
andrewboyson 16:933cbe190bb0 109 int64_t fraction = timerCount;
andrewboyson 16:933cbe190bb0 110 fraction <<= 32;
andrewboyson 25:81014a201736 111 fraction /= TIMER_COUNT_PER_SECOND;
andrewboyson 16:933cbe190bb0 112
andrewboyson 0:33686e88f09a 113 int64_t nsFraction;
andrewboyson 0:33686e88f09a 114
andrewboyson 14:7ef557918bb1 115 int64_t nsBase = tickNs;
andrewboyson 23:07b19cd5f6d0 116 int64_t nsPerTick = ONE_BILLION + ppb;
andrewboyson 0:33686e88f09a 117 nsFraction = (nsPerTick * fraction) >> 32;
andrewboyson 0:33686e88f09a 118 *pNsInt = nsBase + nsFraction;
andrewboyson 0:33686e88f09a 119
andrewboyson 23:07b19cd5f6d0 120 nsBase += slewNs;
andrewboyson 5:a3e37ce4975d 121 nsPerTick += slew;
andrewboyson 0:33686e88f09a 122 nsFraction = (nsPerTick * fraction) >> 32;
andrewboyson 0:33686e88f09a 123 *pNsAbs = nsBase + nsFraction;
andrewboyson 0:33686e88f09a 124 }
andrewboyson 22:df0b906bda26 125 void TickGetTimesFromSnapshot(int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 14:7ef557918bb1 126 {
andrewboyson 23:07b19cd5f6d0 127 makeTimesFromCounts(timerSnapshot, nsTickSnapshot, nsSlewSnapshot, pNsInt, pNsAbs);
andrewboyson 14:7ef557918bb1 128 }
andrewboyson 6:d8a6235486b7 129 void TickGetTimes(int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 23:07b19cd5f6d0 130 {
andrewboyson 24:6c9833e2a049 131 makeTimesFromCounts(TimerSinceCount(secondsBaseCount), nsTickCount, nsSlewCount, pNsInt, pNsAbs);
andrewboyson 0:33686e88f09a 132 }
andrewboyson 17:927fc1eceb9d 133 void TickInit(void)
andrewboyson 0:33686e88f09a 134 {
andrewboyson 0:33686e88f09a 135 nsTickCount = 0;
andrewboyson 23:07b19cd5f6d0 136 nsSlewCount = 0;
andrewboyson 0:33686e88f09a 137
andrewboyson 5:a3e37ce4975d 138 ppb = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated
andrewboyson 5:a3e37ce4975d 139 slew = 0;
andrewboyson 18:207dd1474cd9 140 nsCountIsSet = false;
andrewboyson 24:6c9833e2a049 141 }