Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Thu Jan 25 19:23:30 2018 +0000
Revision:
28:b4aa41fdeb68
Parent:
26:0421132e6eaf
Child:
32:f915ccb1ece3
Corrected PPS problem

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