Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Mon Jul 03 13:56:06 2017 +0000
Revision:
3:92cfc43d493a
Parent:
2:55f070f05a43
Child:
4:095dfd4a316b
Moved all settings out to the main application

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 2:55f070f05a43 11 #define DEBUG true
andrewboyson 2:55f070f05a43 12
andrewboyson 0:33686e88f09a 13 bool SyncedTime = false;
andrewboyson 0:33686e88f09a 14 bool SyncedRate = false;
andrewboyson 0:33686e88f09a 15
andrewboyson 0:33686e88f09a 16 static void setSlew(int64_t diff)
andrewboyson 0:33686e88f09a 17 {
andrewboyson 0:33686e88f09a 18 int64_t absDiff = llabs(diff);
andrewboyson 3:92cfc43d493a 19 int64_t limit = StateGetClockSyncedLimitNs();
andrewboyson 3:92cfc43d493a 20 int64_t hysterisis = StateGetClockSyncedHysterisNs();
andrewboyson 0:33686e88f09a 21
andrewboyson 3:92cfc43d493a 22 if (absDiff < limit - hysterisis) SyncedTime = true;
andrewboyson 3:92cfc43d493a 23 if (absDiff > limit + hysterisis) SyncedTime = false;
andrewboyson 0:33686e88f09a 24
andrewboyson 3:92cfc43d493a 25 int64_t slew = -diff / StateGetClockSlewDivisor();
andrewboyson 3:92cfc43d493a 26 int32_t slewMaxNs = StateGetClockSlewMaxMs() * ONE_MILLION;
andrewboyson 0:33686e88f09a 27
andrewboyson 0:33686e88f09a 28 if (slew > slewMaxNs) slew = slewMaxNs;
andrewboyson 0:33686e88f09a 29 if (slew < -slewMaxNs) slew = -slewMaxNs;
andrewboyson 0:33686e88f09a 30
andrewboyson 0:33686e88f09a 31 TickSlew = slew;
andrewboyson 0:33686e88f09a 32 }
andrewboyson 0:33686e88f09a 33 static void setPpb(int64_t diff)
andrewboyson 2:55f070f05a43 34 {
andrewboyson 2:55f070f05a43 35 if (DEBUG) LogTimeF("Sync setPpb diff %lld against TickPpb %ld\r\n", diff, TickPpb);
andrewboyson 2:55f070f05a43 36
andrewboyson 0:33686e88f09a 37 int64_t absDiff = llabs(diff);
andrewboyson 3:92cfc43d493a 38 int64_t limit = StateGetClockSyncedLimitPpb();
andrewboyson 3:92cfc43d493a 39 int64_t hysterisis = StateGetClockSyncedHysterisPpb();
andrewboyson 0:33686e88f09a 40
andrewboyson 3:92cfc43d493a 41 if (absDiff < limit - hysterisis) SyncedRate = true;
andrewboyson 3:92cfc43d493a 42 if (absDiff > limit + hysterisis) SyncedRate = false;
andrewboyson 0:33686e88f09a 43
andrewboyson 3:92cfc43d493a 44 int64_t toAdd = diff / StateGetClockPpbDivisor();
andrewboyson 3:92cfc43d493a 45 int32_t maxAdd = StateGetClockPpbChangeMax();
andrewboyson 0:33686e88f09a 46
andrewboyson 3:92cfc43d493a 47 if (toAdd > maxAdd) toAdd = maxAdd;
andrewboyson 3:92cfc43d493a 48 if (toAdd < -maxAdd) toAdd = -maxAdd;
andrewboyson 2:55f070f05a43 49
andrewboyson 0:33686e88f09a 50 TickPpb -= toAdd;
andrewboyson 2:55f070f05a43 51
andrewboyson 2:55f070f05a43 52 if (DEBUG) LogTimeF("Sync setPpb toAdd %lld gives TickPpb %ld\r\n", toAdd, TickPpb);
andrewboyson 2:55f070f05a43 53
andrewboyson 3:92cfc43d493a 54 StateSetClockPpb(TickPpb);
andrewboyson 0:33686e88f09a 55 }
andrewboyson 0:33686e88f09a 56
andrewboyson 0:33686e88f09a 57
andrewboyson 0:33686e88f09a 58 void SyncPpsI()
andrewboyson 0:33686e88f09a 59 {
andrewboyson 0:33686e88f09a 60 TickSaveSnapshotI();
andrewboyson 0:33686e88f09a 61 }
andrewboyson 0:33686e88f09a 62
andrewboyson 0:33686e88f09a 63 void SyncPpsN(time_t t)
andrewboyson 2:55f070f05a43 64 {
andrewboyson 2:55f070f05a43 65 int64_t thisExtClock = t * (int64_t)ONE_BILLION; //Make sure one of the RHS is cast to 64 bit
andrewboyson 0:33686e88f09a 66 static int64_t lastIntClock = 0;
andrewboyson 0:33686e88f09a 67 static int64_t lastExtClock = 0;
andrewboyson 0:33686e88f09a 68
andrewboyson 0:33686e88f09a 69 if (!TickIsSet) //Cold start - only ever true if the RTC was not set.
andrewboyson 0:33686e88f09a 70 {
andrewboyson 0:33686e88f09a 71 LogTimeF("Cold start of clock\r\n");
andrewboyson 0:33686e88f09a 72 TickSet(thisExtClock);
andrewboyson 0:33686e88f09a 73 lastIntClock = 0;
andrewboyson 0:33686e88f09a 74 lastExtClock = 0;
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 0:33686e88f09a 81 TickRetrieveSnapshot(&thisIntClock, &thisAbsClock);
andrewboyson 0:33686e88f09a 82
andrewboyson 0:33686e88f09a 83 //Calulate the time error
andrewboyson 0:33686e88f09a 84 int64_t absDiff = thisAbsClock - thisExtClock;
andrewboyson 3:92cfc43d493a 85 if (abs(absDiff) > StateGetClockMaxOffsetSecs() * (int64_t)ONE_BILLION)
andrewboyson 0:33686e88f09a 86 {
andrewboyson 0:33686e88f09a 87 TickSet(thisExtClock);
andrewboyson 0:33686e88f09a 88 lastIntClock = 0;
andrewboyson 0:33686e88f09a 89 lastExtClock = 0;
andrewboyson 0:33686e88f09a 90 return;
andrewboyson 0:33686e88f09a 91 }
andrewboyson 0:33686e88f09a 92 setSlew(absDiff);
andrewboyson 0:33686e88f09a 93
andrewboyson 0:33686e88f09a 94 //Calculate the rate error
andrewboyson 0:33686e88f09a 95 if (lastExtClock)
andrewboyson 0:33686e88f09a 96 {
andrewboyson 0:33686e88f09a 97 int64_t extPeriod = thisExtClock - lastExtClock;
andrewboyson 0:33686e88f09a 98
andrewboyson 0:33686e88f09a 99 int64_t intPeriod = thisIntClock - lastIntClock;
andrewboyson 0:33686e88f09a 100 int64_t periodDiff = intPeriod - extPeriod;
andrewboyson 3:92cfc43d493a 101 if (extPeriod < ONE_BILLION + StateGetClockMaxPpsDifference() &&
andrewboyson 3:92cfc43d493a 102 extPeriod > ONE_BILLION - StateGetClockMaxPpsDifference())
andrewboyson 0:33686e88f09a 103 {
andrewboyson 0:33686e88f09a 104 setPpb(periodDiff);
andrewboyson 0:33686e88f09a 105 }
andrewboyson 0:33686e88f09a 106 }
andrewboyson 0:33686e88f09a 107
andrewboyson 0:33686e88f09a 108 //Save the time in the RTC
andrewboyson 0:33686e88f09a 109 struct tm tm;
andrewboyson 0:33686e88f09a 110 TimeToTmUtc(t, &tm);
andrewboyson 0:33686e88f09a 111 RtcSetTm(&tm);
andrewboyson 0:33686e88f09a 112
andrewboyson 0:33686e88f09a 113 //Save last values
andrewboyson 0:33686e88f09a 114 lastIntClock = thisIntClock;
andrewboyson 0:33686e88f09a 115 lastExtClock = thisExtClock;
andrewboyson 0:33686e88f09a 116
andrewboyson 0:33686e88f09a 117 }
andrewboyson 1:f3746f3cc345 118 void SyncNs(int64_t ns)
andrewboyson 1:f3746f3cc345 119 {
andrewboyson 2:55f070f05a43 120 int64_t thisExtClock = ns;
andrewboyson 2:55f070f05a43 121 static int64_t lastIntClock = 0;
andrewboyson 2:55f070f05a43 122 static int64_t lastExtClock = 0;
andrewboyson 2:55f070f05a43 123
andrewboyson 2:55f070f05a43 124 if (!TickIsSet) //Cold start - only ever true if the RTC was not set.
andrewboyson 2:55f070f05a43 125 {
andrewboyson 2:55f070f05a43 126 LogTimeF("Cold start of clock\r\n");
andrewboyson 2:55f070f05a43 127 TickSet(thisExtClock);
andrewboyson 2:55f070f05a43 128 lastIntClock = 0;
andrewboyson 2:55f070f05a43 129 lastExtClock = 0;
andrewboyson 2:55f070f05a43 130 return;
andrewboyson 2:55f070f05a43 131 }
andrewboyson 2:55f070f05a43 132
andrewboyson 2:55f070f05a43 133 //Get the time at the time of the interrupt
andrewboyson 2:55f070f05a43 134 TickSaveSnapshotI();
andrewboyson 2:55f070f05a43 135 int64_t thisIntClock;
andrewboyson 2:55f070f05a43 136 int64_t thisAbsClock;
andrewboyson 2:55f070f05a43 137 TickRetrieveSnapshot(&thisIntClock, &thisAbsClock);
andrewboyson 2:55f070f05a43 138
andrewboyson 2:55f070f05a43 139 //Calulate the time error
andrewboyson 2:55f070f05a43 140 int64_t absDiff = thisAbsClock - thisExtClock;
andrewboyson 3:92cfc43d493a 141 if (abs(absDiff) > StateGetClockMaxOffsetSecs() * (int64_t)ONE_BILLION)
andrewboyson 2:55f070f05a43 142 {
andrewboyson 3:92cfc43d493a 143 if (DEBUG) LogTimeF("Sync - offset is greater than %d seconds so resetting Tick time and rate\r\n", StateGetClockMaxOffsetSecs());
andrewboyson 2:55f070f05a43 144 TickSet(thisExtClock);
andrewboyson 2:55f070f05a43 145 TickPpb = 0;
andrewboyson 2:55f070f05a43 146 lastIntClock = 0;
andrewboyson 2:55f070f05a43 147 lastExtClock = 0;
andrewboyson 2:55f070f05a43 148 return;
andrewboyson 2:55f070f05a43 149 }
andrewboyson 2:55f070f05a43 150 setSlew(absDiff);
andrewboyson 2:55f070f05a43 151
andrewboyson 2:55f070f05a43 152 //Calculate the rate error
andrewboyson 2:55f070f05a43 153 if (lastExtClock)
andrewboyson 2:55f070f05a43 154 {
andrewboyson 2:55f070f05a43 155 int64_t extPeriod = thisExtClock - lastExtClock;
andrewboyson 2:55f070f05a43 156
andrewboyson 2:55f070f05a43 157 int64_t intPeriod = thisIntClock - lastIntClock;
andrewboyson 2:55f070f05a43 158 int64_t periodDiff = intPeriod - extPeriod;
andrewboyson 2:55f070f05a43 159
andrewboyson 2:55f070f05a43 160 int64_t ppb = periodDiff * ONE_BILLION / extPeriod;
andrewboyson 2:55f070f05a43 161 setPpb(ppb);
andrewboyson 2:55f070f05a43 162 }
andrewboyson 2:55f070f05a43 163
andrewboyson 2:55f070f05a43 164 //Save the time in the RTC
andrewboyson 2:55f070f05a43 165 time_t t = ns / ONE_BILLION;
andrewboyson 2:55f070f05a43 166 struct tm tm;
andrewboyson 2:55f070f05a43 167 TimeToTmUtc(t, &tm);
andrewboyson 2:55f070f05a43 168 RtcSetTm(&tm);
andrewboyson 2:55f070f05a43 169
andrewboyson 2:55f070f05a43 170 //Save last values
andrewboyson 2:55f070f05a43 171 lastIntClock = thisIntClock;
andrewboyson 2:55f070f05a43 172 lastExtClock = thisExtClock;
andrewboyson 2:55f070f05a43 173
andrewboyson 1:f3746f3cc345 174 }