Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Fri Jan 19 19:59:43 2018 +0000
Revision:
22:df0b906bda26
Parent:
18:207dd1474cd9
Child:
26:0421132e6eaf
Corrected the tick to occur on the second

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