Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Mon Jun 26 09:59:21 2017 +0000
Revision:
0:33686e88f09a
Child:
1:f3746f3cc345
Created as stand alone library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 0:33686e88f09a 1 #include "mbed.h"
andrewboyson 0:33686e88f09a 2 #include "log.h"
andrewboyson 0:33686e88f09a 3 #include "tick.h"
andrewboyson 0:33686e88f09a 4 #include "rtc.h"
andrewboyson 0:33686e88f09a 5 #include "time.h"
andrewboyson 0:33686e88f09a 6 #include "state.h"
andrewboyson 0:33686e88f09a 7
andrewboyson 0:33686e88f09a 8 #define ONE_BILLION 1000000000
andrewboyson 0:33686e88f09a 9 #define ONE_MILLION 1000000
andrewboyson 0:33686e88f09a 10
andrewboyson 0:33686e88f09a 11 #define SLEW_DIVISOR 10
andrewboyson 0:33686e88f09a 12 #define SLEW_MAX_MS 20
andrewboyson 0:33686e88f09a 13
andrewboyson 0:33686e88f09a 14 #define PPB_DIVISOR 1000
andrewboyson 0:33686e88f09a 15 #define PPB_CHANGE_MAX 10000000
andrewboyson 0:33686e88f09a 16
andrewboyson 0:33686e88f09a 17 #define MAX_PERIOD_DIFFERENCE 1000000
andrewboyson 0:33686e88f09a 18
andrewboyson 0:33686e88f09a 19 #define SYNCED_LIMIT_NS 100000
andrewboyson 0:33686e88f09a 20 #define SYNCED_LIMIT_PPB 100000
andrewboyson 0:33686e88f09a 21
andrewboyson 0:33686e88f09a 22 #define MAX_OFFSET_SECS 3
andrewboyson 0:33686e88f09a 23
andrewboyson 0:33686e88f09a 24 bool SyncedTime = false;
andrewboyson 0:33686e88f09a 25 bool SyncedRate = false;
andrewboyson 0:33686e88f09a 26
andrewboyson 0:33686e88f09a 27 static void setSlew(int64_t diff)
andrewboyson 0:33686e88f09a 28 {
andrewboyson 0:33686e88f09a 29 int64_t absDiff = llabs(diff);
andrewboyson 0:33686e88f09a 30 int64_t hysterisis = SYNCED_LIMIT_NS >> 3;
andrewboyson 0:33686e88f09a 31
andrewboyson 0:33686e88f09a 32 if (absDiff < SYNCED_LIMIT_NS - hysterisis) SyncedTime = true;
andrewboyson 0:33686e88f09a 33 if (absDiff > SYNCED_LIMIT_NS + hysterisis) SyncedTime = false;
andrewboyson 0:33686e88f09a 34
andrewboyson 0:33686e88f09a 35 int64_t slew = -diff / SLEW_DIVISOR;
andrewboyson 0:33686e88f09a 36 int32_t slewMaxNs = SLEW_MAX_MS * ONE_MILLION;
andrewboyson 0:33686e88f09a 37
andrewboyson 0:33686e88f09a 38 if (slew > slewMaxNs) slew = slewMaxNs;
andrewboyson 0:33686e88f09a 39 if (slew < -slewMaxNs) slew = -slewMaxNs;
andrewboyson 0:33686e88f09a 40
andrewboyson 0:33686e88f09a 41 TickSlew = slew;
andrewboyson 0:33686e88f09a 42 }
andrewboyson 0:33686e88f09a 43 static void setPpb(int64_t diff)
andrewboyson 0:33686e88f09a 44 {
andrewboyson 0:33686e88f09a 45 int64_t absDiff = llabs(diff);
andrewboyson 0:33686e88f09a 46 int64_t hysterisis = SYNCED_LIMIT_PPB >> 6;
andrewboyson 0:33686e88f09a 47
andrewboyson 0:33686e88f09a 48 if (absDiff < SYNCED_LIMIT_PPB - hysterisis) SyncedRate = true;
andrewboyson 0:33686e88f09a 49 if (absDiff > SYNCED_LIMIT_PPB + hysterisis) SyncedRate = false;
andrewboyson 0:33686e88f09a 50
andrewboyson 0:33686e88f09a 51 int64_t toAdd = diff / PPB_DIVISOR;
andrewboyson 0:33686e88f09a 52
andrewboyson 0:33686e88f09a 53 if (toAdd > PPB_CHANGE_MAX) toAdd = PPB_CHANGE_MAX;
andrewboyson 0:33686e88f09a 54 if (toAdd < -PPB_CHANGE_MAX) toAdd = -PPB_CHANGE_MAX;
andrewboyson 0:33686e88f09a 55
andrewboyson 0:33686e88f09a 56 TickPpb -= toAdd;
andrewboyson 0:33686e88f09a 57 StateSavePpb(TickPpb);
andrewboyson 0:33686e88f09a 58 }
andrewboyson 0:33686e88f09a 59
andrewboyson 0:33686e88f09a 60
andrewboyson 0:33686e88f09a 61 void SyncPpsI()
andrewboyson 0:33686e88f09a 62 {
andrewboyson 0:33686e88f09a 63 TickSaveSnapshotI();
andrewboyson 0:33686e88f09a 64 }
andrewboyson 0:33686e88f09a 65
andrewboyson 0:33686e88f09a 66 void SyncPpsN(time_t t)
andrewboyson 0:33686e88f09a 67 { int64_t thisExtClock = t * (int64_t)ONE_BILLION; //Make sure one of the RHS is cast to 64 bit
andrewboyson 0:33686e88f09a 68 static int64_t lastIntClock = 0;
andrewboyson 0:33686e88f09a 69 static int64_t lastExtClock = 0;
andrewboyson 0:33686e88f09a 70
andrewboyson 0:33686e88f09a 71 if (!TickIsSet) //Cold start - only ever true if the RTC was not set.
andrewboyson 0:33686e88f09a 72 {
andrewboyson 0:33686e88f09a 73 LogTimeF("Cold start of clock\r\n");
andrewboyson 0:33686e88f09a 74 TickSet(thisExtClock);
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 0:33686e88f09a 83 TickRetrieveSnapshot(&thisIntClock, &thisAbsClock);
andrewboyson 0:33686e88f09a 84
andrewboyson 0:33686e88f09a 85 //Calulate the time error
andrewboyson 0:33686e88f09a 86 int64_t absDiff = thisAbsClock - thisExtClock;
andrewboyson 0:33686e88f09a 87 if (abs(absDiff) > MAX_OFFSET_SECS * (int64_t)ONE_BILLION)
andrewboyson 0:33686e88f09a 88 {
andrewboyson 0:33686e88f09a 89 TickSet(thisExtClock);
andrewboyson 0:33686e88f09a 90 lastIntClock = 0;
andrewboyson 0:33686e88f09a 91 lastExtClock = 0;
andrewboyson 0:33686e88f09a 92 return;
andrewboyson 0:33686e88f09a 93 }
andrewboyson 0:33686e88f09a 94 setSlew(absDiff);
andrewboyson 0:33686e88f09a 95
andrewboyson 0:33686e88f09a 96 //Calculate the rate error
andrewboyson 0:33686e88f09a 97 if (lastExtClock)
andrewboyson 0:33686e88f09a 98 {
andrewboyson 0:33686e88f09a 99 int64_t extPeriod = thisExtClock - lastExtClock;
andrewboyson 0:33686e88f09a 100
andrewboyson 0:33686e88f09a 101 int64_t intPeriod = thisIntClock - lastIntClock;
andrewboyson 0:33686e88f09a 102 int64_t periodDiff = intPeriod - extPeriod;
andrewboyson 0:33686e88f09a 103 if (extPeriod < ONE_BILLION + MAX_PERIOD_DIFFERENCE &&
andrewboyson 0:33686e88f09a 104 extPeriod > ONE_BILLION - MAX_PERIOD_DIFFERENCE)
andrewboyson 0:33686e88f09a 105 {
andrewboyson 0:33686e88f09a 106 setPpb(periodDiff);
andrewboyson 0:33686e88f09a 107 }
andrewboyson 0:33686e88f09a 108 }
andrewboyson 0:33686e88f09a 109
andrewboyson 0:33686e88f09a 110 //Save the time in the RTC
andrewboyson 0:33686e88f09a 111 struct tm tm;
andrewboyson 0:33686e88f09a 112 TimeToTmUtc(t, &tm);
andrewboyson 0:33686e88f09a 113 RtcSetTm(&tm);
andrewboyson 0:33686e88f09a 114
andrewboyson 0:33686e88f09a 115 //Save last values
andrewboyson 0:33686e88f09a 116 lastIntClock = thisIntClock;
andrewboyson 0:33686e88f09a 117 lastExtClock = thisExtClock;
andrewboyson 0:33686e88f09a 118
andrewboyson 0:33686e88f09a 119 }