Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Fri Oct 13 11:42:13 2017 +0000
Revision:
12:3f338e85750f
Parent:
10:19ed22b94c99
Child:
13:0200519c9bbf
Made the bulk of the logic common between syncing from PPS or non PPS. Also removed the check on whether the clock and the PPS were in close agreement.

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 12:3f338e85750f 7 #define ONE_BILLION 1000000000LL //Make sure ONE_BILLION is 64 bit by putting LL on the end
andrewboyson 0:33686e88f09a 8 #define ONE_MILLION 1000000
andrewboyson 0:33686e88f09a 9
andrewboyson 10:19ed22b94c99 10 bool SyncTrace = false;
andrewboyson 2:55f070f05a43 11
andrewboyson 0:33686e88f09a 12 bool SyncedTime = false;
andrewboyson 0:33686e88f09a 13 bool SyncedRate = false;
andrewboyson 12:3f338e85750f 14 static void setSyncedTime(int64_t diff)
andrewboyson 0:33686e88f09a 15 {
andrewboyson 0:33686e88f09a 16 int64_t absDiff = llabs(diff);
andrewboyson 4:095dfd4a316b 17 int64_t limit = GetClockSyncedLimitNs();
andrewboyson 4:095dfd4a316b 18 int64_t hysterisis = GetClockSyncedHysterisNs();
andrewboyson 0:33686e88f09a 19
andrewboyson 3:92cfc43d493a 20 if (absDiff < limit - hysterisis) SyncedTime = true;
andrewboyson 3:92cfc43d493a 21 if (absDiff > limit + hysterisis) SyncedTime = false;
andrewboyson 12:3f338e85750f 22 }
andrewboyson 12:3f338e85750f 23 static void setSyncedRate(int64_t diff)
andrewboyson 12:3f338e85750f 24 {
andrewboyson 12:3f338e85750f 25
andrewboyson 12:3f338e85750f 26 int64_t absDiff = llabs(diff);
andrewboyson 12:3f338e85750f 27 int64_t limit = GetClockSyncedLimitPpb();
andrewboyson 12:3f338e85750f 28 int64_t hysterisis = GetClockSyncedHysterisPpb();
andrewboyson 12:3f338e85750f 29
andrewboyson 12:3f338e85750f 30 if (absDiff < limit - hysterisis) SyncedRate = true;
andrewboyson 12:3f338e85750f 31 if (absDiff > limit + hysterisis) SyncedRate = false;
andrewboyson 12:3f338e85750f 32 }
andrewboyson 0:33686e88f09a 33
andrewboyson 12:3f338e85750f 34 static void setSlew(int64_t diff)
andrewboyson 12:3f338e85750f 35 {
andrewboyson 4:095dfd4a316b 36 int64_t slew = -diff / GetClockSlewDivisor();
andrewboyson 4:095dfd4a316b 37 int32_t slewMaxNs = GetClockSlewMaxMs() * ONE_MILLION;
andrewboyson 0:33686e88f09a 38
andrewboyson 0:33686e88f09a 39 if (slew > slewMaxNs) slew = slewMaxNs;
andrewboyson 0:33686e88f09a 40 if (slew < -slewMaxNs) slew = -slewMaxNs;
andrewboyson 0:33686e88f09a 41
andrewboyson 5:a3e37ce4975d 42 TickSetSlew(slew);
andrewboyson 5:a3e37ce4975d 43
andrewboyson 10:19ed22b94c99 44 if (SyncTrace) LogTimeF("Sync setSlew diff %lld gives slew %lld gives TickSlew %ld\r\n", diff, slew, TickGetSlew());
andrewboyson 0:33686e88f09a 45 }
andrewboyson 10:19ed22b94c99 46 static void adjustPpb(int64_t diff)
andrewboyson 12:3f338e85750f 47 {
andrewboyson 4:095dfd4a316b 48 int64_t toAdd = diff / GetClockPpbDivisor();
andrewboyson 4:095dfd4a316b 49 int32_t maxAdd = GetClockPpbChangeMax();
andrewboyson 0:33686e88f09a 50
andrewboyson 3:92cfc43d493a 51 if (toAdd > maxAdd) toAdd = maxAdd;
andrewboyson 3:92cfc43d493a 52 if (toAdd < -maxAdd) toAdd = -maxAdd;
andrewboyson 2:55f070f05a43 53
andrewboyson 5:a3e37ce4975d 54 TickAddPpb(-toAdd);
andrewboyson 2:55f070f05a43 55
andrewboyson 10:19ed22b94c99 56 if (SyncTrace) LogTimeF("Sync setPpb diff %lld gives toAdd %lld gives TickPpb %ld\r\n", diff, toAdd, TickGetPpb());
andrewboyson 0:33686e88f09a 57 }
andrewboyson 0:33686e88f09a 58
andrewboyson 0:33686e88f09a 59
andrewboyson 0:33686e88f09a 60 void SyncPpsI()
andrewboyson 0:33686e88f09a 61 {
andrewboyson 0:33686e88f09a 62 TickSaveSnapshotI();
andrewboyson 0:33686e88f09a 63 }
andrewboyson 0:33686e88f09a 64
andrewboyson 12:3f338e85750f 65 static void sync(int64_t thisExtClock)
andrewboyson 2:55f070f05a43 66 {
andrewboyson 12:3f338e85750f 67 static int64_t lastIntClock = -1; //-1 indicates invalid value. 0 is a valid value.
andrewboyson 10:19ed22b94c99 68 static int64_t lastExtClock = -1;
andrewboyson 0:33686e88f09a 69
andrewboyson 5:a3e37ce4975d 70 if (!TickIsSet()) //Cold start - only ever true if the RTC was not set.
andrewboyson 0:33686e88f09a 71 {
andrewboyson 0:33686e88f09a 72 LogTimeF("Cold start of clock\r\n");
andrewboyson 0:33686e88f09a 73 TickSet(thisExtClock);
andrewboyson 10:19ed22b94c99 74 TickSetPpb(0);
andrewboyson 0:33686e88f09a 75 lastIntClock = 0;
andrewboyson 0:33686e88f09a 76 lastExtClock = 0;
andrewboyson 0:33686e88f09a 77 return;
andrewboyson 0:33686e88f09a 78 }
andrewboyson 0:33686e88f09a 79
andrewboyson 0:33686e88f09a 80 //Get the time at the time of the interrupt
andrewboyson 0:33686e88f09a 81 int64_t thisIntClock;
andrewboyson 0:33686e88f09a 82 int64_t thisAbsClock;
andrewboyson 12:3f338e85750f 83 TickGetTimes(&thisIntClock, &thisAbsClock);
andrewboyson 12:3f338e85750f 84
andrewboyson 0:33686e88f09a 85 //Calulate the time error
andrewboyson 0:33686e88f09a 86 int64_t absDiff = thisAbsClock - thisExtClock;
andrewboyson 12:3f338e85750f 87 if (abs(absDiff) > GetClockMaxOffsetSecs() * ONE_BILLION)
andrewboyson 0:33686e88f09a 88 {
andrewboyson 10:19ed22b94c99 89 if (SyncTrace) LogTimeF("Sync - offset is greater than %d seconds so resetting Tick time and rate\r\n", GetClockMaxOffsetSecs());
andrewboyson 0:33686e88f09a 90 TickSet(thisExtClock);
andrewboyson 10:19ed22b94c99 91 TickSetPpb(0);
andrewboyson 0:33686e88f09a 92 lastIntClock = 0;
andrewboyson 0:33686e88f09a 93 lastExtClock = 0;
andrewboyson 0:33686e88f09a 94 return;
andrewboyson 0:33686e88f09a 95 }
andrewboyson 0:33686e88f09a 96 setSlew(absDiff);
andrewboyson 12:3f338e85750f 97 setSyncedTime(absDiff);
andrewboyson 2:55f070f05a43 98
andrewboyson 2:55f070f05a43 99 //Calculate the rate error
andrewboyson 10:19ed22b94c99 100 if (lastExtClock > -1)
andrewboyson 2:55f070f05a43 101 {
andrewboyson 2:55f070f05a43 102 int64_t extPeriod = thisExtClock - lastExtClock;
andrewboyson 2:55f070f05a43 103
andrewboyson 2:55f070f05a43 104 int64_t intPeriod = thisIntClock - lastIntClock;
andrewboyson 2:55f070f05a43 105 int64_t periodDiff = intPeriod - extPeriod;
andrewboyson 2:55f070f05a43 106
andrewboyson 12:3f338e85750f 107 int64_t ppb;
andrewboyson 12:3f338e85750f 108 if (extPeriod == ONE_BILLION) ppb = periodDiff; //This saves a 64bit multiplication and division for PPS
andrewboyson 12:3f338e85750f 109 else ppb = periodDiff * ONE_BILLION / extPeriod;
andrewboyson 12:3f338e85750f 110
andrewboyson 10:19ed22b94c99 111 adjustPpb(ppb);
andrewboyson 12:3f338e85750f 112 setSyncedRate(ppb);
andrewboyson 2:55f070f05a43 113 }
andrewboyson 2:55f070f05a43 114
andrewboyson 2:55f070f05a43 115 //Save last values
andrewboyson 2:55f070f05a43 116 lastIntClock = thisIntClock;
andrewboyson 2:55f070f05a43 117 lastExtClock = thisExtClock;
andrewboyson 12:3f338e85750f 118 }
andrewboyson 12:3f338e85750f 119 void SyncPpsN(time_t t)
andrewboyson 12:3f338e85750f 120 {
andrewboyson 12:3f338e85750f 121 int64_t ns = t * ONE_BILLION;
andrewboyson 12:3f338e85750f 122 sync(ns);
andrewboyson 12:3f338e85750f 123 }
andrewboyson 12:3f338e85750f 124 void SyncNs(int64_t ns)
andrewboyson 12:3f338e85750f 125 {
andrewboyson 12:3f338e85750f 126 TickSaveSnapshotI();
andrewboyson 12:3f338e85750f 127 sync(ns);
andrewboyson 12:3f338e85750f 128 }