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.c@32:f915ccb1ece3, 2018-11-29 (annotated)
- Committer:
- andrewboyson
- Date:
- Thu Nov 29 18:43:27 2018 +0000
- Revision:
- 32:f915ccb1ece3
- Parent:
- 28:b4aa41fdeb68
- Child:
- 33:b9e3c06e7dab
Renamed Tick to Time
Who changed what in which revision?
| User | Revision | Line number | New 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 "time.h" |
| andrewboyson | 13:0200519c9bbf | 6 | #include "clock.h" |
| andrewboyson | 0:33686e88f09a | 7 | |
| andrewboyson | 18:207dd1474cd9 | 8 | bool SyncTrace = false; |
| andrewboyson | 2:55f070f05a43 | 9 | |
| andrewboyson | 18:207dd1474cd9 | 10 | bool SyncedTime = false; |
| andrewboyson | 18:207dd1474cd9 | 11 | bool SyncedRate = false; |
| andrewboyson | 12:3f338e85750f | 12 | static void setSyncedTime(int64_t diff) |
| andrewboyson | 0:33686e88f09a | 13 | { |
| andrewboyson | 0:33686e88f09a | 14 | int64_t absDiff = llabs(diff); |
| andrewboyson | 13:0200519c9bbf | 15 | int64_t limit = ClockSyncedLimitNs; |
| andrewboyson | 13:0200519c9bbf | 16 | int64_t hysterisis = ClockSyncedHysterisNs; |
| andrewboyson | 0:33686e88f09a | 17 | |
| andrewboyson | 18:207dd1474cd9 | 18 | if (absDiff < limit - hysterisis) SyncedTime = true; |
| andrewboyson | 18:207dd1474cd9 | 19 | if (absDiff > limit + hysterisis) SyncedTime = false; |
| andrewboyson | 12:3f338e85750f | 20 | } |
| andrewboyson | 12:3f338e85750f | 21 | static void setSyncedRate(int64_t diff) |
| andrewboyson | 12:3f338e85750f | 22 | { |
| andrewboyson | 12:3f338e85750f | 23 | |
| andrewboyson | 12:3f338e85750f | 24 | int64_t absDiff = llabs(diff); |
| andrewboyson | 13:0200519c9bbf | 25 | int64_t limit = ClockSyncedLimitPpb; |
| andrewboyson | 13:0200519c9bbf | 26 | int64_t hysterisis = ClockSyncedHysterisPpb; |
| andrewboyson | 12:3f338e85750f | 27 | |
| andrewboyson | 18:207dd1474cd9 | 28 | if (absDiff < limit - hysterisis) SyncedRate = true; |
| andrewboyson | 18:207dd1474cd9 | 29 | if (absDiff > limit + hysterisis) SyncedRate = false; |
| andrewboyson | 12:3f338e85750f | 30 | } |
| andrewboyson | 0:33686e88f09a | 31 | |
| andrewboyson | 12:3f338e85750f | 32 | static void setSlew(int64_t diff) |
| andrewboyson | 12:3f338e85750f | 33 | { |
| andrewboyson | 13:0200519c9bbf | 34 | int64_t slew = -diff / ClockSlewDivisor; |
| andrewboyson | 26:0421132e6eaf | 35 | int32_t slewMaxTicks = ClockSlewMaxMs << 20; |
| andrewboyson | 0:33686e88f09a | 36 | |
| andrewboyson | 26:0421132e6eaf | 37 | if (slew > slewMaxTicks) slew = slewMaxTicks; |
| andrewboyson | 26:0421132e6eaf | 38 | if (slew < -slewMaxTicks) slew = -slewMaxTicks; |
| andrewboyson | 0:33686e88f09a | 39 | |
| andrewboyson | 32:f915ccb1ece3 | 40 | TimeSetSlew(slew); |
| andrewboyson | 5:a3e37ce4975d | 41 | |
| andrewboyson | 32:f915ccb1ece3 | 42 | if (SyncTrace) LogTimeF("Sync setSlew diff %lld gives slew %lld gives TickSlew %ld\r\n", diff, slew, TimeGetSlew()); |
| andrewboyson | 0:33686e88f09a | 43 | } |
| andrewboyson | 10:19ed22b94c99 | 44 | static void adjustPpb(int64_t diff) |
| andrewboyson | 12:3f338e85750f | 45 | { |
| andrewboyson | 13:0200519c9bbf | 46 | int64_t toAdd = diff / ClockPpbDivisor; |
| andrewboyson | 13:0200519c9bbf | 47 | int32_t maxAdd = ClockPpbChangeMax; |
| andrewboyson | 0:33686e88f09a | 48 | |
| andrewboyson | 3:92cfc43d493a | 49 | if (toAdd > maxAdd) toAdd = maxAdd; |
| andrewboyson | 3:92cfc43d493a | 50 | if (toAdd < -maxAdd) toAdd = -maxAdd; |
| andrewboyson | 2:55f070f05a43 | 51 | |
| andrewboyson | 32:f915ccb1ece3 | 52 | TimeAddPpb(-toAdd); |
| andrewboyson | 2:55f070f05a43 | 53 | |
| andrewboyson | 32:f915ccb1ece3 | 54 | if (SyncTrace) LogTimeF("Sync setPpb diff %lld gives toAdd %lld gives TickPpb %ld\r\n", diff, toAdd, TimeGetPpb()); |
| andrewboyson | 0:33686e88f09a | 55 | } |
| andrewboyson | 0:33686e88f09a | 56 | |
| andrewboyson | 13:0200519c9bbf | 57 | static int64_t lastIntClock = -1; //-1 indicates invalid value. 0 is a valid value. |
| andrewboyson | 13:0200519c9bbf | 58 | static int64_t lastExtClock = -1; |
| andrewboyson | 13:0200519c9bbf | 59 | static void reset(int64_t thisExtClock) |
| andrewboyson | 0:33686e88f09a | 60 | { |
| andrewboyson | 32:f915ccb1ece3 | 61 | TimeSet(thisExtClock); |
| andrewboyson | 32:f915ccb1ece3 | 62 | TimeSetPpb(0); |
| andrewboyson | 13:0200519c9bbf | 63 | lastIntClock = 0; |
| andrewboyson | 13:0200519c9bbf | 64 | lastExtClock = 0; |
| andrewboyson | 0:33686e88f09a | 65 | } |
| andrewboyson | 0:33686e88f09a | 66 | |
| andrewboyson | 12:3f338e85750f | 67 | static void sync(int64_t thisExtClock) |
| andrewboyson | 2:55f070f05a43 | 68 | { |
| andrewboyson | 13:0200519c9bbf | 69 | |
| andrewboyson | 32:f915ccb1ece3 | 70 | if (!TimeIsSet()) //Cold start - only ever true if the RTC was not set. |
| andrewboyson | 0:33686e88f09a | 71 | { |
| andrewboyson | 13:0200519c9bbf | 72 | LogTimeF("Sync - cold start of clock so resetting\r\n"); |
| andrewboyson | 13:0200519c9bbf | 73 | reset(thisExtClock); |
| andrewboyson | 0:33686e88f09a | 74 | return; |
| andrewboyson | 0:33686e88f09a | 75 | } |
| andrewboyson | 0:33686e88f09a | 76 | |
| andrewboyson | 0:33686e88f09a | 77 | //Get the time at the time of the interrupt |
| andrewboyson | 0:33686e88f09a | 78 | int64_t thisIntClock; |
| andrewboyson | 0:33686e88f09a | 79 | int64_t thisAbsClock; |
| andrewboyson | 32:f915ccb1ece3 | 80 | TimesGetFromSnapshot(&thisIntClock, &thisAbsClock); |
| andrewboyson | 12:3f338e85750f | 81 | |
| andrewboyson | 0:33686e88f09a | 82 | //Calulate the time error |
| andrewboyson | 0:33686e88f09a | 83 | int64_t absDiff = thisAbsClock - thisExtClock; |
| andrewboyson | 32:f915ccb1ece3 | 84 | if (llabs(absDiff) > ((int64_t)ClockMaxOffsetSecs << TIME_ONE_SECOND_SHIFT)) |
| andrewboyson | 0:33686e88f09a | 85 | { |
| andrewboyson | 13:0200519c9bbf | 86 | LogTimeF("Sync - offset is greater than %d seconds so resetting\r\n", ClockMaxOffsetSecs); |
| andrewboyson | 13:0200519c9bbf | 87 | reset(thisExtClock); |
| andrewboyson | 0:33686e88f09a | 88 | return; |
| andrewboyson | 0:33686e88f09a | 89 | } |
| andrewboyson | 0:33686e88f09a | 90 | setSlew(absDiff); |
| andrewboyson | 12:3f338e85750f | 91 | setSyncedTime(absDiff); |
| andrewboyson | 2:55f070f05a43 | 92 | |
| andrewboyson | 2:55f070f05a43 | 93 | //Calculate the rate error |
| andrewboyson | 10:19ed22b94c99 | 94 | if (lastExtClock > -1) |
| andrewboyson | 2:55f070f05a43 | 95 | { |
| andrewboyson | 2:55f070f05a43 | 96 | int64_t extPeriod = thisExtClock - lastExtClock; |
| andrewboyson | 2:55f070f05a43 | 97 | |
| andrewboyson | 2:55f070f05a43 | 98 | int64_t intPeriod = thisIntClock - lastIntClock; |
| andrewboyson | 2:55f070f05a43 | 99 | int64_t periodDiff = intPeriod - extPeriod; |
| andrewboyson | 2:55f070f05a43 | 100 | |
| andrewboyson | 12:3f338e85750f | 101 | int64_t ppb; |
| andrewboyson | 32:f915ccb1ece3 | 102 | if (extPeriod == TIME_ONE_SECOND) ppb = periodDiff; //This saves a 64bit shift and division for PPS |
| andrewboyson | 32:f915ccb1ece3 | 103 | else ppb = (periodDiff << TIME_ONE_SECOND_SHIFT) / extPeriod; |
| andrewboyson | 12:3f338e85750f | 104 | |
| andrewboyson | 10:19ed22b94c99 | 105 | adjustPpb(ppb); |
| andrewboyson | 12:3f338e85750f | 106 | setSyncedRate(ppb); |
| andrewboyson | 2:55f070f05a43 | 107 | } |
| andrewboyson | 2:55f070f05a43 | 108 | |
| andrewboyson | 2:55f070f05a43 | 109 | //Save last values |
| andrewboyson | 2:55f070f05a43 | 110 | lastIntClock = thisIntClock; |
| andrewboyson | 2:55f070f05a43 | 111 | lastExtClock = thisExtClock; |
| andrewboyson | 12:3f338e85750f | 112 | } |
| andrewboyson | 32:f915ccb1ece3 | 113 | void SyncPpsI ( ) { TimeSaveSnapshot(); } |
| andrewboyson | 32:f915ccb1ece3 | 114 | void SyncPpsN (time_t t ) { int64_t ticks = (int64_t)t << TIME_ONE_SECOND_SHIFT; sync(ticks); } |
| andrewboyson | 32:f915ccb1ece3 | 115 | void SyncTicks(int64_t ticks) { TimeSaveSnapshot(); sync(ticks); } |