Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Thu Jan 11 17:39:36 2018 +0000
Revision:
17:927fc1eceb9d
Parent:
sync.cpp@14:7ef557918bb1
Child:
18:207dd1474cd9
Removed dependence on Mbed OS

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 17:927fc1eceb9d 1 #include <stdlib.h>
andrewboyson 17:927fc1eceb9d 2
andrewboyson 13:0200519c9bbf 3 #include "log.h"
andrewboyson 13:0200519c9bbf 4 #include "tick.h"
andrewboyson 13:0200519c9bbf 5 #include "time.h"
andrewboyson 13:0200519c9bbf 6 #include "clock.h"
andrewboyson 0:33686e88f09a 7
andrewboyson 12:3f338e85750f 8 #define ONE_BILLION 1000000000LL //Make sure ONE_BILLION is 64 bit by putting LL on the end
andrewboyson 0:33686e88f09a 9 #define ONE_MILLION 1000000
andrewboyson 0:33686e88f09a 10
andrewboyson 17:927fc1eceb9d 11 #define TRUE 1
andrewboyson 17:927fc1eceb9d 12 #define FALSE 0
andrewboyson 2:55f070f05a43 13
andrewboyson 17:927fc1eceb9d 14 int SyncTrace = FALSE;
andrewboyson 17:927fc1eceb9d 15
andrewboyson 17:927fc1eceb9d 16 int SyncedTime = FALSE;
andrewboyson 17:927fc1eceb9d 17 int SyncedRate = FALSE;
andrewboyson 12:3f338e85750f 18 static void setSyncedTime(int64_t diff)
andrewboyson 0:33686e88f09a 19 {
andrewboyson 0:33686e88f09a 20 int64_t absDiff = llabs(diff);
andrewboyson 13:0200519c9bbf 21 int64_t limit = ClockSyncedLimitNs;
andrewboyson 13:0200519c9bbf 22 int64_t hysterisis = ClockSyncedHysterisNs;
andrewboyson 0:33686e88f09a 23
andrewboyson 17:927fc1eceb9d 24 if (absDiff < limit - hysterisis) SyncedTime = TRUE;
andrewboyson 17:927fc1eceb9d 25 if (absDiff > limit + hysterisis) SyncedTime = FALSE;
andrewboyson 12:3f338e85750f 26 }
andrewboyson 12:3f338e85750f 27 static void setSyncedRate(int64_t diff)
andrewboyson 12:3f338e85750f 28 {
andrewboyson 12:3f338e85750f 29
andrewboyson 12:3f338e85750f 30 int64_t absDiff = llabs(diff);
andrewboyson 13:0200519c9bbf 31 int64_t limit = ClockSyncedLimitPpb;
andrewboyson 13:0200519c9bbf 32 int64_t hysterisis = ClockSyncedHysterisPpb;
andrewboyson 12:3f338e85750f 33
andrewboyson 17:927fc1eceb9d 34 if (absDiff < limit - hysterisis) SyncedRate = TRUE;
andrewboyson 17:927fc1eceb9d 35 if (absDiff > limit + hysterisis) SyncedRate = FALSE;
andrewboyson 12:3f338e85750f 36 }
andrewboyson 0:33686e88f09a 37
andrewboyson 12:3f338e85750f 38 static void setSlew(int64_t diff)
andrewboyson 12:3f338e85750f 39 {
andrewboyson 13:0200519c9bbf 40 int64_t slew = -diff / ClockSlewDivisor;
andrewboyson 13:0200519c9bbf 41 int32_t slewMaxNs = ClockSlewMaxMs * ONE_MILLION;
andrewboyson 0:33686e88f09a 42
andrewboyson 0:33686e88f09a 43 if (slew > slewMaxNs) slew = slewMaxNs;
andrewboyson 0:33686e88f09a 44 if (slew < -slewMaxNs) slew = -slewMaxNs;
andrewboyson 0:33686e88f09a 45
andrewboyson 5:a3e37ce4975d 46 TickSetSlew(slew);
andrewboyson 5:a3e37ce4975d 47
andrewboyson 10:19ed22b94c99 48 if (SyncTrace) LogTimeF("Sync setSlew diff %lld gives slew %lld gives TickSlew %ld\r\n", diff, slew, TickGetSlew());
andrewboyson 0:33686e88f09a 49 }
andrewboyson 10:19ed22b94c99 50 static void adjustPpb(int64_t diff)
andrewboyson 12:3f338e85750f 51 {
andrewboyson 13:0200519c9bbf 52 int64_t toAdd = diff / ClockPpbDivisor;
andrewboyson 13:0200519c9bbf 53 int32_t maxAdd = ClockPpbChangeMax;
andrewboyson 0:33686e88f09a 54
andrewboyson 3:92cfc43d493a 55 if (toAdd > maxAdd) toAdd = maxAdd;
andrewboyson 3:92cfc43d493a 56 if (toAdd < -maxAdd) toAdd = -maxAdd;
andrewboyson 2:55f070f05a43 57
andrewboyson 5:a3e37ce4975d 58 TickAddPpb(-toAdd);
andrewboyson 2:55f070f05a43 59
andrewboyson 10:19ed22b94c99 60 if (SyncTrace) LogTimeF("Sync setPpb diff %lld gives toAdd %lld gives TickPpb %ld\r\n", diff, toAdd, TickGetPpb());
andrewboyson 0:33686e88f09a 61 }
andrewboyson 0:33686e88f09a 62
andrewboyson 13:0200519c9bbf 63 static int64_t lastIntClock = -1; //-1 indicates invalid value. 0 is a valid value.
andrewboyson 13:0200519c9bbf 64 static int64_t lastExtClock = -1;
andrewboyson 13:0200519c9bbf 65 static void reset(int64_t thisExtClock)
andrewboyson 0:33686e88f09a 66 {
andrewboyson 13:0200519c9bbf 67 TickSet(thisExtClock);
andrewboyson 13:0200519c9bbf 68 TickSetPpb(0);
andrewboyson 13:0200519c9bbf 69 lastIntClock = 0;
andrewboyson 13:0200519c9bbf 70 lastExtClock = 0;
andrewboyson 0:33686e88f09a 71 }
andrewboyson 0:33686e88f09a 72
andrewboyson 12:3f338e85750f 73 static void sync(int64_t thisExtClock)
andrewboyson 2:55f070f05a43 74 {
andrewboyson 13:0200519c9bbf 75
andrewboyson 5:a3e37ce4975d 76 if (!TickIsSet()) //Cold start - only ever true if the RTC was not set.
andrewboyson 0:33686e88f09a 77 {
andrewboyson 13:0200519c9bbf 78 LogTimeF("Sync - cold start of clock so resetting\r\n");
andrewboyson 13:0200519c9bbf 79 reset(thisExtClock);
andrewboyson 0:33686e88f09a 80 return;
andrewboyson 0:33686e88f09a 81 }
andrewboyson 0:33686e88f09a 82
andrewboyson 0:33686e88f09a 83 //Get the time at the time of the interrupt
andrewboyson 0:33686e88f09a 84 int64_t thisIntClock;
andrewboyson 0:33686e88f09a 85 int64_t thisAbsClock;
andrewboyson 14:7ef557918bb1 86 TickRetrieveSnapshot(&thisIntClock, &thisAbsClock);
andrewboyson 12:3f338e85750f 87
andrewboyson 0:33686e88f09a 88 //Calulate the time error
andrewboyson 0:33686e88f09a 89 int64_t absDiff = thisAbsClock - thisExtClock;
andrewboyson 17:927fc1eceb9d 90 if (llabs(absDiff) > ClockMaxOffsetSecs * ONE_BILLION)
andrewboyson 0:33686e88f09a 91 {
andrewboyson 13:0200519c9bbf 92 LogTimeF("Sync - offset is greater than %d seconds so resetting\r\n", ClockMaxOffsetSecs);
andrewboyson 13:0200519c9bbf 93 reset(thisExtClock);
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 13:0200519c9bbf 119 void SyncPpsI( ) { TickSaveSnapshotI(); }
andrewboyson 13:0200519c9bbf 120 void SyncPpsN(time_t t ) { int64_t ns = t * ONE_BILLION; sync(ns); }
andrewboyson 13:0200519c9bbf 121 void SyncNs (int64_t ns) { TickSaveSnapshotI(); sync(ns); }