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@12:3f338e85750f, 2017-10-13 (annotated)
- Committer:
- andrewboyson
- Date:
- Fri Oct 13 11:42:13 2017 +0000
- Revision:
- 12:3f338e85750f
- Parent:
- 10:19ed22b94c99
- Child:
- 13:0200519c9bbf
Made the bulk of the logic common between syncing from PPS or non PPS. Also removed the check on whether the clock and the PPS were in close agreement.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| andrewboyson | 4:095dfd4a316b | 1 | #include "mbed.h" |
| andrewboyson | 4:095dfd4a316b | 2 | #include "log.h" |
| andrewboyson | 4:095dfd4a316b | 3 | #include "tick.h" |
| andrewboyson | 4:095dfd4a316b | 4 | #include "time.h" |
| andrewboyson | 4:095dfd4a316b | 5 | #include "settings.h" |
| andrewboyson | 0:33686e88f09a | 6 | |
| andrewboyson | 12:3f338e85750f | 7 | #define ONE_BILLION 1000000000LL //Make sure ONE_BILLION is 64 bit by putting LL on the end |
| andrewboyson | 0:33686e88f09a | 8 | #define ONE_MILLION 1000000 |
| andrewboyson | 0:33686e88f09a | 9 | |
| andrewboyson | 10:19ed22b94c99 | 10 | bool SyncTrace = false; |
| andrewboyson | 2:55f070f05a43 | 11 | |
| andrewboyson | 0:33686e88f09a | 12 | bool SyncedTime = false; |
| andrewboyson | 0:33686e88f09a | 13 | bool SyncedRate = false; |
| andrewboyson | 12:3f338e85750f | 14 | static void setSyncedTime(int64_t diff) |
| andrewboyson | 0:33686e88f09a | 15 | { |
| andrewboyson | 0:33686e88f09a | 16 | int64_t absDiff = llabs(diff); |
| andrewboyson | 4:095dfd4a316b | 17 | int64_t limit = GetClockSyncedLimitNs(); |
| andrewboyson | 4:095dfd4a316b | 18 | int64_t hysterisis = GetClockSyncedHysterisNs(); |
| andrewboyson | 0:33686e88f09a | 19 | |
| andrewboyson | 3:92cfc43d493a | 20 | if (absDiff < limit - hysterisis) SyncedTime = true; |
| andrewboyson | 3:92cfc43d493a | 21 | if (absDiff > limit + hysterisis) SyncedTime = false; |
| andrewboyson | 12:3f338e85750f | 22 | } |
| andrewboyson | 12:3f338e85750f | 23 | static void setSyncedRate(int64_t diff) |
| andrewboyson | 12:3f338e85750f | 24 | { |
| andrewboyson | 12:3f338e85750f | 25 | |
| andrewboyson | 12:3f338e85750f | 26 | int64_t absDiff = llabs(diff); |
| andrewboyson | 12:3f338e85750f | 27 | int64_t limit = GetClockSyncedLimitPpb(); |
| andrewboyson | 12:3f338e85750f | 28 | int64_t hysterisis = GetClockSyncedHysterisPpb(); |
| andrewboyson | 12:3f338e85750f | 29 | |
| andrewboyson | 12:3f338e85750f | 30 | if (absDiff < limit - hysterisis) SyncedRate = true; |
| andrewboyson | 12:3f338e85750f | 31 | if (absDiff > limit + hysterisis) SyncedRate = false; |
| andrewboyson | 12:3f338e85750f | 32 | } |
| andrewboyson | 0:33686e88f09a | 33 | |
| andrewboyson | 12:3f338e85750f | 34 | static void setSlew(int64_t diff) |
| andrewboyson | 12:3f338e85750f | 35 | { |
| andrewboyson | 4:095dfd4a316b | 36 | int64_t slew = -diff / GetClockSlewDivisor(); |
| andrewboyson | 4:095dfd4a316b | 37 | int32_t slewMaxNs = GetClockSlewMaxMs() * ONE_MILLION; |
| andrewboyson | 0:33686e88f09a | 38 | |
| andrewboyson | 0:33686e88f09a | 39 | if (slew > slewMaxNs) slew = slewMaxNs; |
| andrewboyson | 0:33686e88f09a | 40 | if (slew < -slewMaxNs) slew = -slewMaxNs; |
| andrewboyson | 0:33686e88f09a | 41 | |
| andrewboyson | 5:a3e37ce4975d | 42 | TickSetSlew(slew); |
| andrewboyson | 5:a3e37ce4975d | 43 | |
| andrewboyson | 10:19ed22b94c99 | 44 | if (SyncTrace) LogTimeF("Sync setSlew diff %lld gives slew %lld gives TickSlew %ld\r\n", diff, slew, TickGetSlew()); |
| andrewboyson | 0:33686e88f09a | 45 | } |
| andrewboyson | 10:19ed22b94c99 | 46 | static void adjustPpb(int64_t diff) |
| andrewboyson | 12:3f338e85750f | 47 | { |
| andrewboyson | 4:095dfd4a316b | 48 | int64_t toAdd = diff / GetClockPpbDivisor(); |
| andrewboyson | 4:095dfd4a316b | 49 | int32_t maxAdd = GetClockPpbChangeMax(); |
| andrewboyson | 0:33686e88f09a | 50 | |
| andrewboyson | 3:92cfc43d493a | 51 | if (toAdd > maxAdd) toAdd = maxAdd; |
| andrewboyson | 3:92cfc43d493a | 52 | if (toAdd < -maxAdd) toAdd = -maxAdd; |
| andrewboyson | 2:55f070f05a43 | 53 | |
| andrewboyson | 5:a3e37ce4975d | 54 | TickAddPpb(-toAdd); |
| andrewboyson | 2:55f070f05a43 | 55 | |
| andrewboyson | 10:19ed22b94c99 | 56 | if (SyncTrace) LogTimeF("Sync setPpb diff %lld gives toAdd %lld gives TickPpb %ld\r\n", diff, toAdd, TickGetPpb()); |
| andrewboyson | 0:33686e88f09a | 57 | } |
| andrewboyson | 0:33686e88f09a | 58 | |
| andrewboyson | 0:33686e88f09a | 59 | |
| andrewboyson | 0:33686e88f09a | 60 | void SyncPpsI() |
| andrewboyson | 0:33686e88f09a | 61 | { |
| andrewboyson | 0:33686e88f09a | 62 | TickSaveSnapshotI(); |
| andrewboyson | 0:33686e88f09a | 63 | } |
| andrewboyson | 0:33686e88f09a | 64 | |
| andrewboyson | 12:3f338e85750f | 65 | static void sync(int64_t thisExtClock) |
| andrewboyson | 2:55f070f05a43 | 66 | { |
| andrewboyson | 12:3f338e85750f | 67 | static int64_t lastIntClock = -1; //-1 indicates invalid value. 0 is a valid value. |
| andrewboyson | 10:19ed22b94c99 | 68 | static int64_t lastExtClock = -1; |
| andrewboyson | 0:33686e88f09a | 69 | |
| andrewboyson | 5:a3e37ce4975d | 70 | if (!TickIsSet()) //Cold start - only ever true if the RTC was not set. |
| andrewboyson | 0:33686e88f09a | 71 | { |
| andrewboyson | 0:33686e88f09a | 72 | LogTimeF("Cold start of clock\r\n"); |
| andrewboyson | 0:33686e88f09a | 73 | TickSet(thisExtClock); |
| andrewboyson | 10:19ed22b94c99 | 74 | TickSetPpb(0); |
| 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 | 12:3f338e85750f | 83 | TickGetTimes(&thisIntClock, &thisAbsClock); |
| andrewboyson | 12:3f338e85750f | 84 | |
| andrewboyson | 0:33686e88f09a | 85 | //Calulate the time error |
| andrewboyson | 0:33686e88f09a | 86 | int64_t absDiff = thisAbsClock - thisExtClock; |
| andrewboyson | 12:3f338e85750f | 87 | if (abs(absDiff) > GetClockMaxOffsetSecs() * ONE_BILLION) |
| andrewboyson | 0:33686e88f09a | 88 | { |
| andrewboyson | 10:19ed22b94c99 | 89 | if (SyncTrace) LogTimeF("Sync - offset is greater than %d seconds so resetting Tick time and rate\r\n", GetClockMaxOffsetSecs()); |
| andrewboyson | 0:33686e88f09a | 90 | TickSet(thisExtClock); |
| andrewboyson | 10:19ed22b94c99 | 91 | TickSetPpb(0); |
| andrewboyson | 0:33686e88f09a | 92 | lastIntClock = 0; |
| andrewboyson | 0:33686e88f09a | 93 | lastExtClock = 0; |
| andrewboyson | 0:33686e88f09a | 94 | return; |
| andrewboyson | 0:33686e88f09a | 95 | } |
| andrewboyson | 0:33686e88f09a | 96 | setSlew(absDiff); |
| andrewboyson | 12:3f338e85750f | 97 | setSyncedTime(absDiff); |
| andrewboyson | 2:55f070f05a43 | 98 | |
| andrewboyson | 2:55f070f05a43 | 99 | //Calculate the rate error |
| andrewboyson | 10:19ed22b94c99 | 100 | if (lastExtClock > -1) |
| andrewboyson | 2:55f070f05a43 | 101 | { |
| andrewboyson | 2:55f070f05a43 | 102 | int64_t extPeriod = thisExtClock - lastExtClock; |
| andrewboyson | 2:55f070f05a43 | 103 | |
| andrewboyson | 2:55f070f05a43 | 104 | int64_t intPeriod = thisIntClock - lastIntClock; |
| andrewboyson | 2:55f070f05a43 | 105 | int64_t periodDiff = intPeriod - extPeriod; |
| andrewboyson | 2:55f070f05a43 | 106 | |
| andrewboyson | 12:3f338e85750f | 107 | int64_t ppb; |
| andrewboyson | 12:3f338e85750f | 108 | if (extPeriod == ONE_BILLION) ppb = periodDiff; //This saves a 64bit multiplication and division for PPS |
| andrewboyson | 12:3f338e85750f | 109 | else ppb = periodDiff * ONE_BILLION / extPeriod; |
| andrewboyson | 12:3f338e85750f | 110 | |
| andrewboyson | 10:19ed22b94c99 | 111 | adjustPpb(ppb); |
| andrewboyson | 12:3f338e85750f | 112 | setSyncedRate(ppb); |
| andrewboyson | 2:55f070f05a43 | 113 | } |
| andrewboyson | 2:55f070f05a43 | 114 | |
| andrewboyson | 2:55f070f05a43 | 115 | //Save last values |
| andrewboyson | 2:55f070f05a43 | 116 | lastIntClock = thisIntClock; |
| andrewboyson | 2:55f070f05a43 | 117 | lastExtClock = thisExtClock; |
| andrewboyson | 12:3f338e85750f | 118 | } |
| andrewboyson | 12:3f338e85750f | 119 | void SyncPpsN(time_t t) |
| andrewboyson | 12:3f338e85750f | 120 | { |
| andrewboyson | 12:3f338e85750f | 121 | int64_t ns = t * ONE_BILLION; |
| andrewboyson | 12:3f338e85750f | 122 | sync(ns); |
| andrewboyson | 12:3f338e85750f | 123 | } |
| andrewboyson | 12:3f338e85750f | 124 | void SyncNs(int64_t ns) |
| andrewboyson | 12:3f338e85750f | 125 | { |
| andrewboyson | 12:3f338e85750f | 126 | TickSaveSnapshotI(); |
| andrewboyson | 12:3f338e85750f | 127 | sync(ns); |
| andrewboyson | 12:3f338e85750f | 128 | } |