Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: oldheating gps motorhome heating
sync.cpp@2:55f070f05a43, 2017-07-03 (annotated)
- Committer:
- andrewboyson
- Date:
- Mon Jul 03 07:07:48 2017 +0000
- Revision:
- 2:55f070f05a43
- Parent:
- 1:f3746f3cc345
- Child:
- 3:92cfc43d493a
Pulled out state module which is now expected to be found in the application
Who changed what in which revision?
| User | Revision | Line number | New 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 | 2:55f070f05a43 | 24 | #define DEBUG true |
| andrewboyson | 2:55f070f05a43 | 25 | |
| andrewboyson | 0:33686e88f09a | 26 | bool SyncedTime = false; |
| andrewboyson | 0:33686e88f09a | 27 | bool SyncedRate = false; |
| andrewboyson | 0:33686e88f09a | 28 | |
| andrewboyson | 0:33686e88f09a | 29 | static void setSlew(int64_t diff) |
| andrewboyson | 0:33686e88f09a | 30 | { |
| andrewboyson | 0:33686e88f09a | 31 | int64_t absDiff = llabs(diff); |
| andrewboyson | 0:33686e88f09a | 32 | int64_t hysterisis = SYNCED_LIMIT_NS >> 3; |
| andrewboyson | 0:33686e88f09a | 33 | |
| andrewboyson | 0:33686e88f09a | 34 | if (absDiff < SYNCED_LIMIT_NS - hysterisis) SyncedTime = true; |
| andrewboyson | 0:33686e88f09a | 35 | if (absDiff > SYNCED_LIMIT_NS + hysterisis) SyncedTime = false; |
| andrewboyson | 0:33686e88f09a | 36 | |
| andrewboyson | 0:33686e88f09a | 37 | int64_t slew = -diff / SLEW_DIVISOR; |
| andrewboyson | 0:33686e88f09a | 38 | int32_t slewMaxNs = SLEW_MAX_MS * ONE_MILLION; |
| andrewboyson | 0:33686e88f09a | 39 | |
| andrewboyson | 0:33686e88f09a | 40 | if (slew > slewMaxNs) slew = slewMaxNs; |
| andrewboyson | 0:33686e88f09a | 41 | if (slew < -slewMaxNs) slew = -slewMaxNs; |
| andrewboyson | 0:33686e88f09a | 42 | |
| andrewboyson | 0:33686e88f09a | 43 | TickSlew = slew; |
| andrewboyson | 0:33686e88f09a | 44 | } |
| andrewboyson | 0:33686e88f09a | 45 | static void setPpb(int64_t diff) |
| andrewboyson | 2:55f070f05a43 | 46 | { |
| andrewboyson | 2:55f070f05a43 | 47 | if (DEBUG) LogTimeF("Sync setPpb diff %lld against TickPpb %ld\r\n", diff, TickPpb); |
| andrewboyson | 2:55f070f05a43 | 48 | |
| andrewboyson | 0:33686e88f09a | 49 | int64_t absDiff = llabs(diff); |
| andrewboyson | 0:33686e88f09a | 50 | int64_t hysterisis = SYNCED_LIMIT_PPB >> 6; |
| andrewboyson | 0:33686e88f09a | 51 | |
| andrewboyson | 0:33686e88f09a | 52 | if (absDiff < SYNCED_LIMIT_PPB - hysterisis) SyncedRate = true; |
| andrewboyson | 0:33686e88f09a | 53 | if (absDiff > SYNCED_LIMIT_PPB + hysterisis) SyncedRate = false; |
| andrewboyson | 0:33686e88f09a | 54 | |
| andrewboyson | 0:33686e88f09a | 55 | int64_t toAdd = diff / PPB_DIVISOR; |
| andrewboyson | 0:33686e88f09a | 56 | |
| andrewboyson | 0:33686e88f09a | 57 | if (toAdd > PPB_CHANGE_MAX) toAdd = PPB_CHANGE_MAX; |
| andrewboyson | 0:33686e88f09a | 58 | if (toAdd < -PPB_CHANGE_MAX) toAdd = -PPB_CHANGE_MAX; |
| andrewboyson | 2:55f070f05a43 | 59 | |
| andrewboyson | 0:33686e88f09a | 60 | TickPpb -= toAdd; |
| andrewboyson | 2:55f070f05a43 | 61 | |
| andrewboyson | 2:55f070f05a43 | 62 | if (DEBUG) LogTimeF("Sync setPpb toAdd %lld gives TickPpb %ld\r\n", toAdd, TickPpb); |
| andrewboyson | 2:55f070f05a43 | 63 | |
| andrewboyson | 0:33686e88f09a | 64 | StateSavePpb(TickPpb); |
| andrewboyson | 0:33686e88f09a | 65 | } |
| andrewboyson | 0:33686e88f09a | 66 | |
| andrewboyson | 0:33686e88f09a | 67 | |
| andrewboyson | 0:33686e88f09a | 68 | void SyncPpsI() |
| andrewboyson | 0:33686e88f09a | 69 | { |
| andrewboyson | 0:33686e88f09a | 70 | TickSaveSnapshotI(); |
| andrewboyson | 0:33686e88f09a | 71 | } |
| andrewboyson | 0:33686e88f09a | 72 | |
| andrewboyson | 0:33686e88f09a | 73 | void SyncPpsN(time_t t) |
| andrewboyson | 2:55f070f05a43 | 74 | { |
| andrewboyson | 2:55f070f05a43 | 75 | int64_t thisExtClock = t * (int64_t)ONE_BILLION; //Make sure one of the RHS is cast to 64 bit |
| andrewboyson | 0:33686e88f09a | 76 | static int64_t lastIntClock = 0; |
| andrewboyson | 0:33686e88f09a | 77 | static int64_t lastExtClock = 0; |
| andrewboyson | 0:33686e88f09a | 78 | |
| andrewboyson | 0:33686e88f09a | 79 | if (!TickIsSet) //Cold start - only ever true if the RTC was not set. |
| andrewboyson | 0:33686e88f09a | 80 | { |
| andrewboyson | 0:33686e88f09a | 81 | LogTimeF("Cold start of clock\r\n"); |
| andrewboyson | 0:33686e88f09a | 82 | TickSet(thisExtClock); |
| andrewboyson | 0:33686e88f09a | 83 | lastIntClock = 0; |
| andrewboyson | 0:33686e88f09a | 84 | lastExtClock = 0; |
| andrewboyson | 0:33686e88f09a | 85 | return; |
| andrewboyson | 0:33686e88f09a | 86 | } |
| andrewboyson | 0:33686e88f09a | 87 | |
| andrewboyson | 0:33686e88f09a | 88 | //Get the time at the time of the interrupt |
| andrewboyson | 0:33686e88f09a | 89 | int64_t thisIntClock; |
| andrewboyson | 0:33686e88f09a | 90 | int64_t thisAbsClock; |
| andrewboyson | 0:33686e88f09a | 91 | TickRetrieveSnapshot(&thisIntClock, &thisAbsClock); |
| andrewboyson | 0:33686e88f09a | 92 | |
| andrewboyson | 0:33686e88f09a | 93 | //Calulate the time error |
| andrewboyson | 0:33686e88f09a | 94 | int64_t absDiff = thisAbsClock - thisExtClock; |
| andrewboyson | 0:33686e88f09a | 95 | if (abs(absDiff) > MAX_OFFSET_SECS * (int64_t)ONE_BILLION) |
| andrewboyson | 0:33686e88f09a | 96 | { |
| andrewboyson | 0:33686e88f09a | 97 | TickSet(thisExtClock); |
| andrewboyson | 0:33686e88f09a | 98 | lastIntClock = 0; |
| andrewboyson | 0:33686e88f09a | 99 | lastExtClock = 0; |
| andrewboyson | 0:33686e88f09a | 100 | return; |
| andrewboyson | 0:33686e88f09a | 101 | } |
| andrewboyson | 0:33686e88f09a | 102 | setSlew(absDiff); |
| andrewboyson | 0:33686e88f09a | 103 | |
| andrewboyson | 0:33686e88f09a | 104 | //Calculate the rate error |
| andrewboyson | 0:33686e88f09a | 105 | if (lastExtClock) |
| andrewboyson | 0:33686e88f09a | 106 | { |
| andrewboyson | 0:33686e88f09a | 107 | int64_t extPeriod = thisExtClock - lastExtClock; |
| andrewboyson | 0:33686e88f09a | 108 | |
| andrewboyson | 0:33686e88f09a | 109 | int64_t intPeriod = thisIntClock - lastIntClock; |
| andrewboyson | 0:33686e88f09a | 110 | int64_t periodDiff = intPeriod - extPeriod; |
| andrewboyson | 0:33686e88f09a | 111 | if (extPeriod < ONE_BILLION + MAX_PERIOD_DIFFERENCE && |
| andrewboyson | 0:33686e88f09a | 112 | extPeriod > ONE_BILLION - MAX_PERIOD_DIFFERENCE) |
| andrewboyson | 0:33686e88f09a | 113 | { |
| andrewboyson | 0:33686e88f09a | 114 | setPpb(periodDiff); |
| andrewboyson | 0:33686e88f09a | 115 | } |
| andrewboyson | 0:33686e88f09a | 116 | } |
| andrewboyson | 0:33686e88f09a | 117 | |
| andrewboyson | 0:33686e88f09a | 118 | //Save the time in the RTC |
| andrewboyson | 0:33686e88f09a | 119 | struct tm tm; |
| andrewboyson | 0:33686e88f09a | 120 | TimeToTmUtc(t, &tm); |
| andrewboyson | 0:33686e88f09a | 121 | RtcSetTm(&tm); |
| andrewboyson | 0:33686e88f09a | 122 | |
| andrewboyson | 0:33686e88f09a | 123 | //Save last values |
| andrewboyson | 0:33686e88f09a | 124 | lastIntClock = thisIntClock; |
| andrewboyson | 0:33686e88f09a | 125 | lastExtClock = thisExtClock; |
| andrewboyson | 0:33686e88f09a | 126 | |
| andrewboyson | 0:33686e88f09a | 127 | } |
| andrewboyson | 1:f3746f3cc345 | 128 | void SyncNs(int64_t ns) |
| andrewboyson | 1:f3746f3cc345 | 129 | { |
| andrewboyson | 2:55f070f05a43 | 130 | int64_t thisExtClock = ns; |
| andrewboyson | 2:55f070f05a43 | 131 | static int64_t lastIntClock = 0; |
| andrewboyson | 2:55f070f05a43 | 132 | static int64_t lastExtClock = 0; |
| andrewboyson | 2:55f070f05a43 | 133 | |
| andrewboyson | 2:55f070f05a43 | 134 | if (!TickIsSet) //Cold start - only ever true if the RTC was not set. |
| andrewboyson | 2:55f070f05a43 | 135 | { |
| andrewboyson | 2:55f070f05a43 | 136 | LogTimeF("Cold start of clock\r\n"); |
| andrewboyson | 2:55f070f05a43 | 137 | TickSet(thisExtClock); |
| andrewboyson | 2:55f070f05a43 | 138 | lastIntClock = 0; |
| andrewboyson | 2:55f070f05a43 | 139 | lastExtClock = 0; |
| andrewboyson | 2:55f070f05a43 | 140 | return; |
| andrewboyson | 2:55f070f05a43 | 141 | } |
| andrewboyson | 2:55f070f05a43 | 142 | |
| andrewboyson | 2:55f070f05a43 | 143 | //Get the time at the time of the interrupt |
| andrewboyson | 2:55f070f05a43 | 144 | TickSaveSnapshotI(); |
| andrewboyson | 2:55f070f05a43 | 145 | int64_t thisIntClock; |
| andrewboyson | 2:55f070f05a43 | 146 | int64_t thisAbsClock; |
| andrewboyson | 2:55f070f05a43 | 147 | TickRetrieveSnapshot(&thisIntClock, &thisAbsClock); |
| andrewboyson | 2:55f070f05a43 | 148 | |
| andrewboyson | 2:55f070f05a43 | 149 | //Calulate the time error |
| andrewboyson | 2:55f070f05a43 | 150 | int64_t absDiff = thisAbsClock - thisExtClock; |
| andrewboyson | 2:55f070f05a43 | 151 | if (abs(absDiff) > MAX_OFFSET_SECS * (int64_t)ONE_BILLION) |
| andrewboyson | 2:55f070f05a43 | 152 | { |
| andrewboyson | 2:55f070f05a43 | 153 | if (DEBUG) LogTimeF("Sync - offset is greater than %d seconds so resetting Tick time and rate\r\n", MAX_OFFSET_SECS); |
| andrewboyson | 2:55f070f05a43 | 154 | TickSet(thisExtClock); |
| andrewboyson | 2:55f070f05a43 | 155 | TickPpb = 0; |
| andrewboyson | 2:55f070f05a43 | 156 | lastIntClock = 0; |
| andrewboyson | 2:55f070f05a43 | 157 | lastExtClock = 0; |
| andrewboyson | 2:55f070f05a43 | 158 | return; |
| andrewboyson | 2:55f070f05a43 | 159 | } |
| andrewboyson | 2:55f070f05a43 | 160 | setSlew(absDiff); |
| andrewboyson | 2:55f070f05a43 | 161 | |
| andrewboyson | 2:55f070f05a43 | 162 | //Calculate the rate error |
| andrewboyson | 2:55f070f05a43 | 163 | if (lastExtClock) |
| andrewboyson | 2:55f070f05a43 | 164 | { |
| andrewboyson | 2:55f070f05a43 | 165 | int64_t extPeriod = thisExtClock - lastExtClock; |
| andrewboyson | 2:55f070f05a43 | 166 | |
| andrewboyson | 2:55f070f05a43 | 167 | int64_t intPeriod = thisIntClock - lastIntClock; |
| andrewboyson | 2:55f070f05a43 | 168 | int64_t periodDiff = intPeriod - extPeriod; |
| andrewboyson | 2:55f070f05a43 | 169 | |
| andrewboyson | 2:55f070f05a43 | 170 | int64_t ppb = periodDiff * ONE_BILLION / extPeriod; |
| andrewboyson | 2:55f070f05a43 | 171 | setPpb(ppb); |
| andrewboyson | 2:55f070f05a43 | 172 | } |
| andrewboyson | 2:55f070f05a43 | 173 | |
| andrewboyson | 2:55f070f05a43 | 174 | //Save the time in the RTC |
| andrewboyson | 2:55f070f05a43 | 175 | time_t t = ns / ONE_BILLION; |
| andrewboyson | 2:55f070f05a43 | 176 | struct tm tm; |
| andrewboyson | 2:55f070f05a43 | 177 | TimeToTmUtc(t, &tm); |
| andrewboyson | 2:55f070f05a43 | 178 | RtcSetTm(&tm); |
| andrewboyson | 2:55f070f05a43 | 179 | |
| andrewboyson | 2:55f070f05a43 | 180 | //Save last values |
| andrewboyson | 2:55f070f05a43 | 181 | lastIntClock = thisIntClock; |
| andrewboyson | 2:55f070f05a43 | 182 | lastExtClock = thisExtClock; |
| andrewboyson | 2:55f070f05a43 | 183 | |
| andrewboyson | 1:f3746f3cc345 | 184 | } |