Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Tue Jul 04 15:04:26 2017 +0000
Revision:
5:a3e37ce4975d
Parent:
4:095dfd4a316b
Child:
6:d8a6235486b7
Better saved the ppb state

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 4:095dfd4a316b 1 #include "mbed.h"
andrewboyson 4:095dfd4a316b 2 #include "log.h"
andrewboyson 4:095dfd4a316b 3 #include "tick.h"
andrewboyson 4:095dfd4a316b 4 #include "time.h"
andrewboyson 4:095dfd4a316b 5 #include "settings.h"
andrewboyson 0:33686e88f09a 6
andrewboyson 0:33686e88f09a 7 #define ONE_BILLION 1000000000
andrewboyson 0:33686e88f09a 8 #define ONE_MILLION 1000000
andrewboyson 0:33686e88f09a 9
andrewboyson 2:55f070f05a43 10 #define DEBUG true
andrewboyson 2:55f070f05a43 11
andrewboyson 0:33686e88f09a 12 bool SyncedTime = false;
andrewboyson 0:33686e88f09a 13 bool SyncedRate = false;
andrewboyson 0:33686e88f09a 14
andrewboyson 0:33686e88f09a 15 static void setSlew(int64_t diff)
andrewboyson 0:33686e88f09a 16 {
andrewboyson 0:33686e88f09a 17 int64_t absDiff = llabs(diff);
andrewboyson 4:095dfd4a316b 18 int64_t limit = GetClockSyncedLimitNs();
andrewboyson 4:095dfd4a316b 19 int64_t hysterisis = GetClockSyncedHysterisNs();
andrewboyson 0:33686e88f09a 20
andrewboyson 3:92cfc43d493a 21 if (absDiff < limit - hysterisis) SyncedTime = true;
andrewboyson 3:92cfc43d493a 22 if (absDiff > limit + hysterisis) SyncedTime = false;
andrewboyson 0:33686e88f09a 23
andrewboyson 4:095dfd4a316b 24 int64_t slew = -diff / GetClockSlewDivisor();
andrewboyson 4:095dfd4a316b 25 int32_t slewMaxNs = GetClockSlewMaxMs() * ONE_MILLION;
andrewboyson 0:33686e88f09a 26
andrewboyson 0:33686e88f09a 27 if (slew > slewMaxNs) slew = slewMaxNs;
andrewboyson 0:33686e88f09a 28 if (slew < -slewMaxNs) slew = -slewMaxNs;
andrewboyson 0:33686e88f09a 29
andrewboyson 5:a3e37ce4975d 30 TickSetSlew(slew);
andrewboyson 5:a3e37ce4975d 31
andrewboyson 5:a3e37ce4975d 32 if (DEBUG) LogTimeF("Sync setSlew diff %lld gives slew %lld gives TickSlew %ld\r\n", diff, slew, TickGetSlew());
andrewboyson 0:33686e88f09a 33 }
andrewboyson 0:33686e88f09a 34 static void setPpb(int64_t diff)
andrewboyson 2:55f070f05a43 35 {
andrewboyson 2:55f070f05a43 36
andrewboyson 0:33686e88f09a 37 int64_t absDiff = llabs(diff);
andrewboyson 4:095dfd4a316b 38 int64_t limit = GetClockSyncedLimitPpb();
andrewboyson 4:095dfd4a316b 39 int64_t hysterisis = GetClockSyncedHysterisPpb();
andrewboyson 0:33686e88f09a 40
andrewboyson 3:92cfc43d493a 41 if (absDiff < limit - hysterisis) SyncedRate = true;
andrewboyson 3:92cfc43d493a 42 if (absDiff > limit + hysterisis) SyncedRate = false;
andrewboyson 0:33686e88f09a 43
andrewboyson 4:095dfd4a316b 44 int64_t toAdd = diff / GetClockPpbDivisor();
andrewboyson 4:095dfd4a316b 45 int32_t maxAdd = GetClockPpbChangeMax();
andrewboyson 0:33686e88f09a 46
andrewboyson 3:92cfc43d493a 47 if (toAdd > maxAdd) toAdd = maxAdd;
andrewboyson 3:92cfc43d493a 48 if (toAdd < -maxAdd) toAdd = -maxAdd;
andrewboyson 2:55f070f05a43 49
andrewboyson 5:a3e37ce4975d 50 TickAddPpb(-toAdd);
andrewboyson 2:55f070f05a43 51
andrewboyson 5:a3e37ce4975d 52 if (DEBUG) LogTimeF("Sync setPpb diff %lld gives toAdd %lld gives TickPpb %ld\r\n", diff, toAdd, TickGetPpb());
andrewboyson 0:33686e88f09a 53 }
andrewboyson 0:33686e88f09a 54
andrewboyson 0:33686e88f09a 55
andrewboyson 0:33686e88f09a 56 void SyncPpsI()
andrewboyson 0:33686e88f09a 57 {
andrewboyson 0:33686e88f09a 58 TickSaveSnapshotI();
andrewboyson 0:33686e88f09a 59 }
andrewboyson 0:33686e88f09a 60
andrewboyson 0:33686e88f09a 61 void SyncPpsN(time_t t)
andrewboyson 2:55f070f05a43 62 {
andrewboyson 2:55f070f05a43 63 int64_t thisExtClock = t * (int64_t)ONE_BILLION; //Make sure one of the RHS is cast to 64 bit
andrewboyson 0:33686e88f09a 64 static int64_t lastIntClock = 0;
andrewboyson 0:33686e88f09a 65 static int64_t lastExtClock = 0;
andrewboyson 0:33686e88f09a 66
andrewboyson 5:a3e37ce4975d 67 if (!TickIsSet()) //Cold start - only ever true if the RTC was not set.
andrewboyson 0:33686e88f09a 68 {
andrewboyson 0:33686e88f09a 69 LogTimeF("Cold start of clock\r\n");
andrewboyson 0:33686e88f09a 70 TickSet(thisExtClock);
andrewboyson 0:33686e88f09a 71 lastIntClock = 0;
andrewboyson 0:33686e88f09a 72 lastExtClock = 0;
andrewboyson 0:33686e88f09a 73 return;
andrewboyson 0:33686e88f09a 74 }
andrewboyson 0:33686e88f09a 75
andrewboyson 0:33686e88f09a 76 //Get the time at the time of the interrupt
andrewboyson 0:33686e88f09a 77 int64_t thisIntClock;
andrewboyson 0:33686e88f09a 78 int64_t thisAbsClock;
andrewboyson 0:33686e88f09a 79 TickRetrieveSnapshot(&thisIntClock, &thisAbsClock);
andrewboyson 0:33686e88f09a 80
andrewboyson 0:33686e88f09a 81 //Calulate the time error
andrewboyson 0:33686e88f09a 82 int64_t absDiff = thisAbsClock - thisExtClock;
andrewboyson 4:095dfd4a316b 83 if (abs(absDiff) > GetClockMaxOffsetSecs() * (int64_t)ONE_BILLION)
andrewboyson 0:33686e88f09a 84 {
andrewboyson 0:33686e88f09a 85 TickSet(thisExtClock);
andrewboyson 0:33686e88f09a 86 lastIntClock = 0;
andrewboyson 0:33686e88f09a 87 lastExtClock = 0;
andrewboyson 0:33686e88f09a 88 return;
andrewboyson 0:33686e88f09a 89 }
andrewboyson 0:33686e88f09a 90 setSlew(absDiff);
andrewboyson 0:33686e88f09a 91
andrewboyson 0:33686e88f09a 92 //Calculate the rate error
andrewboyson 0:33686e88f09a 93 if (lastExtClock)
andrewboyson 0:33686e88f09a 94 {
andrewboyson 0:33686e88f09a 95 int64_t extPeriod = thisExtClock - lastExtClock;
andrewboyson 0:33686e88f09a 96
andrewboyson 0:33686e88f09a 97 int64_t intPeriod = thisIntClock - lastIntClock;
andrewboyson 0:33686e88f09a 98 int64_t periodDiff = intPeriod - extPeriod;
andrewboyson 4:095dfd4a316b 99 if (extPeriod < ONE_BILLION + GetClockMaxPpsDifference() &&
andrewboyson 4:095dfd4a316b 100 extPeriod > ONE_BILLION - GetClockMaxPpsDifference())
andrewboyson 0:33686e88f09a 101 {
andrewboyson 0:33686e88f09a 102 setPpb(periodDiff);
andrewboyson 0:33686e88f09a 103 }
andrewboyson 0:33686e88f09a 104 }
andrewboyson 0:33686e88f09a 105
andrewboyson 0:33686e88f09a 106 //Save last values
andrewboyson 0:33686e88f09a 107 lastIntClock = thisIntClock;
andrewboyson 0:33686e88f09a 108 lastExtClock = thisExtClock;
andrewboyson 0:33686e88f09a 109
andrewboyson 0:33686e88f09a 110 }
andrewboyson 1:f3746f3cc345 111 void SyncNs(int64_t ns)
andrewboyson 1:f3746f3cc345 112 {
andrewboyson 2:55f070f05a43 113 int64_t thisExtClock = ns;
andrewboyson 2:55f070f05a43 114 static int64_t lastIntClock = 0;
andrewboyson 2:55f070f05a43 115 static int64_t lastExtClock = 0;
andrewboyson 2:55f070f05a43 116
andrewboyson 5:a3e37ce4975d 117 if (!TickIsSet()) //Cold start - only ever true if the RTC was not set.
andrewboyson 2:55f070f05a43 118 {
andrewboyson 2:55f070f05a43 119 LogTimeF("Cold start of clock\r\n");
andrewboyson 2:55f070f05a43 120 TickSet(thisExtClock);
andrewboyson 2:55f070f05a43 121 lastIntClock = 0;
andrewboyson 2:55f070f05a43 122 lastExtClock = 0;
andrewboyson 2:55f070f05a43 123 return;
andrewboyson 2:55f070f05a43 124 }
andrewboyson 2:55f070f05a43 125
andrewboyson 2:55f070f05a43 126 //Get the time at the time of the interrupt
andrewboyson 2:55f070f05a43 127 TickSaveSnapshotI();
andrewboyson 2:55f070f05a43 128 int64_t thisIntClock;
andrewboyson 2:55f070f05a43 129 int64_t thisAbsClock;
andrewboyson 2:55f070f05a43 130 TickRetrieveSnapshot(&thisIntClock, &thisAbsClock);
andrewboyson 2:55f070f05a43 131
andrewboyson 2:55f070f05a43 132 //Calulate the time error
andrewboyson 2:55f070f05a43 133 int64_t absDiff = thisAbsClock - thisExtClock;
andrewboyson 4:095dfd4a316b 134 if (abs(absDiff) > GetClockMaxOffsetSecs() * (int64_t)ONE_BILLION)
andrewboyson 2:55f070f05a43 135 {
andrewboyson 4:095dfd4a316b 136 if (DEBUG) LogTimeF("Sync - offset is greater than %d seconds so resetting Tick time and rate\r\n", GetClockMaxOffsetSecs());
andrewboyson 2:55f070f05a43 137 TickSet(thisExtClock);
andrewboyson 2:55f070f05a43 138 lastIntClock = 0;
andrewboyson 2:55f070f05a43 139 lastExtClock = 0;
andrewboyson 2:55f070f05a43 140 return;
andrewboyson 2:55f070f05a43 141 }
andrewboyson 2:55f070f05a43 142 setSlew(absDiff);
andrewboyson 2:55f070f05a43 143
andrewboyson 2:55f070f05a43 144 //Calculate the rate error
andrewboyson 2:55f070f05a43 145 if (lastExtClock)
andrewboyson 2:55f070f05a43 146 {
andrewboyson 2:55f070f05a43 147 int64_t extPeriod = thisExtClock - lastExtClock;
andrewboyson 2:55f070f05a43 148
andrewboyson 2:55f070f05a43 149 int64_t intPeriod = thisIntClock - lastIntClock;
andrewboyson 2:55f070f05a43 150 int64_t periodDiff = intPeriod - extPeriod;
andrewboyson 2:55f070f05a43 151
andrewboyson 2:55f070f05a43 152 int64_t ppb = periodDiff * ONE_BILLION / extPeriod;
andrewboyson 2:55f070f05a43 153 setPpb(ppb);
andrewboyson 2:55f070f05a43 154 }
andrewboyson 2:55f070f05a43 155
andrewboyson 2:55f070f05a43 156 //Save last values
andrewboyson 2:55f070f05a43 157 lastIntClock = thisIntClock;
andrewboyson 2:55f070f05a43 158 lastExtClock = thisExtClock;
andrewboyson 2:55f070f05a43 159
andrewboyson 1:f3746f3cc345 160 }