Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Thu Nov 29 18:43:27 2018 +0000
Revision:
32:f915ccb1ece3
Parent:
28:b4aa41fdeb68
Child:
33:b9e3c06e7dab
Renamed Tick to Time

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 17:927fc1eceb9d 1 #include <stdlib.h>
andrewboyson 18:207dd1474cd9 2 #include <stdbool.h>
andrewboyson 17:927fc1eceb9d 3
andrewboyson 13:0200519c9bbf 4 #include "log.h"
andrewboyson 13:0200519c9bbf 5 #include "time.h"
andrewboyson 13:0200519c9bbf 6 #include "clock.h"
andrewboyson 0:33686e88f09a 7
andrewboyson 18:207dd1474cd9 8 bool SyncTrace = false;
andrewboyson 2:55f070f05a43 9
andrewboyson 18:207dd1474cd9 10 bool SyncedTime = false;
andrewboyson 18:207dd1474cd9 11 bool SyncedRate = false;
andrewboyson 12:3f338e85750f 12 static void setSyncedTime(int64_t diff)
andrewboyson 0:33686e88f09a 13 {
andrewboyson 0:33686e88f09a 14 int64_t absDiff = llabs(diff);
andrewboyson 13:0200519c9bbf 15 int64_t limit = ClockSyncedLimitNs;
andrewboyson 13:0200519c9bbf 16 int64_t hysterisis = ClockSyncedHysterisNs;
andrewboyson 0:33686e88f09a 17
andrewboyson 18:207dd1474cd9 18 if (absDiff < limit - hysterisis) SyncedTime = true;
andrewboyson 18:207dd1474cd9 19 if (absDiff > limit + hysterisis) SyncedTime = false;
andrewboyson 12:3f338e85750f 20 }
andrewboyson 12:3f338e85750f 21 static void setSyncedRate(int64_t diff)
andrewboyson 12:3f338e85750f 22 {
andrewboyson 12:3f338e85750f 23
andrewboyson 12:3f338e85750f 24 int64_t absDiff = llabs(diff);
andrewboyson 13:0200519c9bbf 25 int64_t limit = ClockSyncedLimitPpb;
andrewboyson 13:0200519c9bbf 26 int64_t hysterisis = ClockSyncedHysterisPpb;
andrewboyson 12:3f338e85750f 27
andrewboyson 18:207dd1474cd9 28 if (absDiff < limit - hysterisis) SyncedRate = true;
andrewboyson 18:207dd1474cd9 29 if (absDiff > limit + hysterisis) SyncedRate = false;
andrewboyson 12:3f338e85750f 30 }
andrewboyson 0:33686e88f09a 31
andrewboyson 12:3f338e85750f 32 static void setSlew(int64_t diff)
andrewboyson 12:3f338e85750f 33 {
andrewboyson 13:0200519c9bbf 34 int64_t slew = -diff / ClockSlewDivisor;
andrewboyson 26:0421132e6eaf 35 int32_t slewMaxTicks = ClockSlewMaxMs << 20;
andrewboyson 0:33686e88f09a 36
andrewboyson 26:0421132e6eaf 37 if (slew > slewMaxTicks) slew = slewMaxTicks;
andrewboyson 26:0421132e6eaf 38 if (slew < -slewMaxTicks) slew = -slewMaxTicks;
andrewboyson 0:33686e88f09a 39
andrewboyson 32:f915ccb1ece3 40 TimeSetSlew(slew);
andrewboyson 5:a3e37ce4975d 41
andrewboyson 32:f915ccb1ece3 42 if (SyncTrace) LogTimeF("Sync setSlew diff %lld gives slew %lld gives TickSlew %ld\r\n", diff, slew, TimeGetSlew());
andrewboyson 0:33686e88f09a 43 }
andrewboyson 10:19ed22b94c99 44 static void adjustPpb(int64_t diff)
andrewboyson 12:3f338e85750f 45 {
andrewboyson 13:0200519c9bbf 46 int64_t toAdd = diff / ClockPpbDivisor;
andrewboyson 13:0200519c9bbf 47 int32_t maxAdd = ClockPpbChangeMax;
andrewboyson 0:33686e88f09a 48
andrewboyson 3:92cfc43d493a 49 if (toAdd > maxAdd) toAdd = maxAdd;
andrewboyson 3:92cfc43d493a 50 if (toAdd < -maxAdd) toAdd = -maxAdd;
andrewboyson 2:55f070f05a43 51
andrewboyson 32:f915ccb1ece3 52 TimeAddPpb(-toAdd);
andrewboyson 2:55f070f05a43 53
andrewboyson 32:f915ccb1ece3 54 if (SyncTrace) LogTimeF("Sync setPpb diff %lld gives toAdd %lld gives TickPpb %ld\r\n", diff, toAdd, TimeGetPpb());
andrewboyson 0:33686e88f09a 55 }
andrewboyson 0:33686e88f09a 56
andrewboyson 13:0200519c9bbf 57 static int64_t lastIntClock = -1; //-1 indicates invalid value. 0 is a valid value.
andrewboyson 13:0200519c9bbf 58 static int64_t lastExtClock = -1;
andrewboyson 13:0200519c9bbf 59 static void reset(int64_t thisExtClock)
andrewboyson 0:33686e88f09a 60 {
andrewboyson 32:f915ccb1ece3 61 TimeSet(thisExtClock);
andrewboyson 32:f915ccb1ece3 62 TimeSetPpb(0);
andrewboyson 13:0200519c9bbf 63 lastIntClock = 0;
andrewboyson 13:0200519c9bbf 64 lastExtClock = 0;
andrewboyson 0:33686e88f09a 65 }
andrewboyson 0:33686e88f09a 66
andrewboyson 12:3f338e85750f 67 static void sync(int64_t thisExtClock)
andrewboyson 2:55f070f05a43 68 {
andrewboyson 13:0200519c9bbf 69
andrewboyson 32:f915ccb1ece3 70 if (!TimeIsSet()) //Cold start - only ever true if the RTC was not set.
andrewboyson 0:33686e88f09a 71 {
andrewboyson 13:0200519c9bbf 72 LogTimeF("Sync - cold start of clock so resetting\r\n");
andrewboyson 13:0200519c9bbf 73 reset(thisExtClock);
andrewboyson 0:33686e88f09a 74 return;
andrewboyson 0:33686e88f09a 75 }
andrewboyson 0:33686e88f09a 76
andrewboyson 0:33686e88f09a 77 //Get the time at the time of the interrupt
andrewboyson 0:33686e88f09a 78 int64_t thisIntClock;
andrewboyson 0:33686e88f09a 79 int64_t thisAbsClock;
andrewboyson 32:f915ccb1ece3 80 TimesGetFromSnapshot(&thisIntClock, &thisAbsClock);
andrewboyson 12:3f338e85750f 81
andrewboyson 0:33686e88f09a 82 //Calulate the time error
andrewboyson 0:33686e88f09a 83 int64_t absDiff = thisAbsClock - thisExtClock;
andrewboyson 32:f915ccb1ece3 84 if (llabs(absDiff) > ((int64_t)ClockMaxOffsetSecs << TIME_ONE_SECOND_SHIFT))
andrewboyson 0:33686e88f09a 85 {
andrewboyson 13:0200519c9bbf 86 LogTimeF("Sync - offset is greater than %d seconds so resetting\r\n", ClockMaxOffsetSecs);
andrewboyson 13:0200519c9bbf 87 reset(thisExtClock);
andrewboyson 0:33686e88f09a 88 return;
andrewboyson 0:33686e88f09a 89 }
andrewboyson 0:33686e88f09a 90 setSlew(absDiff);
andrewboyson 12:3f338e85750f 91 setSyncedTime(absDiff);
andrewboyson 2:55f070f05a43 92
andrewboyson 2:55f070f05a43 93 //Calculate the rate error
andrewboyson 10:19ed22b94c99 94 if (lastExtClock > -1)
andrewboyson 2:55f070f05a43 95 {
andrewboyson 2:55f070f05a43 96 int64_t extPeriod = thisExtClock - lastExtClock;
andrewboyson 2:55f070f05a43 97
andrewboyson 2:55f070f05a43 98 int64_t intPeriod = thisIntClock - lastIntClock;
andrewboyson 2:55f070f05a43 99 int64_t periodDiff = intPeriod - extPeriod;
andrewboyson 2:55f070f05a43 100
andrewboyson 12:3f338e85750f 101 int64_t ppb;
andrewboyson 32:f915ccb1ece3 102 if (extPeriod == TIME_ONE_SECOND) ppb = periodDiff; //This saves a 64bit shift and division for PPS
andrewboyson 32:f915ccb1ece3 103 else ppb = (periodDiff << TIME_ONE_SECOND_SHIFT) / extPeriod;
andrewboyson 12:3f338e85750f 104
andrewboyson 10:19ed22b94c99 105 adjustPpb(ppb);
andrewboyson 12:3f338e85750f 106 setSyncedRate(ppb);
andrewboyson 2:55f070f05a43 107 }
andrewboyson 2:55f070f05a43 108
andrewboyson 2:55f070f05a43 109 //Save last values
andrewboyson 2:55f070f05a43 110 lastIntClock = thisIntClock;
andrewboyson 2:55f070f05a43 111 lastExtClock = thisExtClock;
andrewboyson 12:3f338e85750f 112 }
andrewboyson 32:f915ccb1ece3 113 void SyncPpsI ( ) { TimeSaveSnapshot(); }
andrewboyson 32:f915ccb1ece3 114 void SyncPpsN (time_t t ) { int64_t ticks = (int64_t)t << TIME_ONE_SECOND_SHIFT; sync(ticks); }
andrewboyson 32:f915ccb1ece3 115 void SyncTicks(int64_t ticks) { TimeSaveSnapshot(); sync(ticks); }