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@17:927fc1eceb9d, 2018-01-11 (annotated)
- Committer:
- andrewboyson
- Date:
- Thu Jan 11 17:39:36 2018 +0000
- Revision:
- 17:927fc1eceb9d
- Parent:
- sync.cpp@14:7ef557918bb1
- Child:
- 18:207dd1474cd9
Removed dependence on Mbed OS
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| andrewboyson | 17:927fc1eceb9d | 1 | #include <stdlib.h> |
| andrewboyson | 17:927fc1eceb9d | 2 | |
| andrewboyson | 13:0200519c9bbf | 3 | #include "log.h" |
| andrewboyson | 13:0200519c9bbf | 4 | #include "tick.h" |
| andrewboyson | 13:0200519c9bbf | 5 | #include "time.h" |
| andrewboyson | 13:0200519c9bbf | 6 | #include "clock.h" |
| andrewboyson | 0:33686e88f09a | 7 | |
| andrewboyson | 12:3f338e85750f | 8 | #define ONE_BILLION 1000000000LL //Make sure ONE_BILLION is 64 bit by putting LL on the end |
| andrewboyson | 0:33686e88f09a | 9 | #define ONE_MILLION 1000000 |
| andrewboyson | 0:33686e88f09a | 10 | |
| andrewboyson | 17:927fc1eceb9d | 11 | #define TRUE 1 |
| andrewboyson | 17:927fc1eceb9d | 12 | #define FALSE 0 |
| andrewboyson | 2:55f070f05a43 | 13 | |
| andrewboyson | 17:927fc1eceb9d | 14 | int SyncTrace = FALSE; |
| andrewboyson | 17:927fc1eceb9d | 15 | |
| andrewboyson | 17:927fc1eceb9d | 16 | int SyncedTime = FALSE; |
| andrewboyson | 17:927fc1eceb9d | 17 | int SyncedRate = FALSE; |
| andrewboyson | 12:3f338e85750f | 18 | static void setSyncedTime(int64_t diff) |
| andrewboyson | 0:33686e88f09a | 19 | { |
| andrewboyson | 0:33686e88f09a | 20 | int64_t absDiff = llabs(diff); |
| andrewboyson | 13:0200519c9bbf | 21 | int64_t limit = ClockSyncedLimitNs; |
| andrewboyson | 13:0200519c9bbf | 22 | int64_t hysterisis = ClockSyncedHysterisNs; |
| andrewboyson | 0:33686e88f09a | 23 | |
| andrewboyson | 17:927fc1eceb9d | 24 | if (absDiff < limit - hysterisis) SyncedTime = TRUE; |
| andrewboyson | 17:927fc1eceb9d | 25 | if (absDiff > limit + hysterisis) SyncedTime = FALSE; |
| andrewboyson | 12:3f338e85750f | 26 | } |
| andrewboyson | 12:3f338e85750f | 27 | static void setSyncedRate(int64_t diff) |
| andrewboyson | 12:3f338e85750f | 28 | { |
| andrewboyson | 12:3f338e85750f | 29 | |
| andrewboyson | 12:3f338e85750f | 30 | int64_t absDiff = llabs(diff); |
| andrewboyson | 13:0200519c9bbf | 31 | int64_t limit = ClockSyncedLimitPpb; |
| andrewboyson | 13:0200519c9bbf | 32 | int64_t hysterisis = ClockSyncedHysterisPpb; |
| andrewboyson | 12:3f338e85750f | 33 | |
| andrewboyson | 17:927fc1eceb9d | 34 | if (absDiff < limit - hysterisis) SyncedRate = TRUE; |
| andrewboyson | 17:927fc1eceb9d | 35 | if (absDiff > limit + hysterisis) SyncedRate = FALSE; |
| andrewboyson | 12:3f338e85750f | 36 | } |
| andrewboyson | 0:33686e88f09a | 37 | |
| andrewboyson | 12:3f338e85750f | 38 | static void setSlew(int64_t diff) |
| andrewboyson | 12:3f338e85750f | 39 | { |
| andrewboyson | 13:0200519c9bbf | 40 | int64_t slew = -diff / ClockSlewDivisor; |
| andrewboyson | 13:0200519c9bbf | 41 | int32_t slewMaxNs = ClockSlewMaxMs * ONE_MILLION; |
| andrewboyson | 0:33686e88f09a | 42 | |
| andrewboyson | 0:33686e88f09a | 43 | if (slew > slewMaxNs) slew = slewMaxNs; |
| andrewboyson | 0:33686e88f09a | 44 | if (slew < -slewMaxNs) slew = -slewMaxNs; |
| andrewboyson | 0:33686e88f09a | 45 | |
| andrewboyson | 5:a3e37ce4975d | 46 | TickSetSlew(slew); |
| andrewboyson | 5:a3e37ce4975d | 47 | |
| andrewboyson | 10:19ed22b94c99 | 48 | if (SyncTrace) LogTimeF("Sync setSlew diff %lld gives slew %lld gives TickSlew %ld\r\n", diff, slew, TickGetSlew()); |
| andrewboyson | 0:33686e88f09a | 49 | } |
| andrewboyson | 10:19ed22b94c99 | 50 | static void adjustPpb(int64_t diff) |
| andrewboyson | 12:3f338e85750f | 51 | { |
| andrewboyson | 13:0200519c9bbf | 52 | int64_t toAdd = diff / ClockPpbDivisor; |
| andrewboyson | 13:0200519c9bbf | 53 | int32_t maxAdd = ClockPpbChangeMax; |
| andrewboyson | 0:33686e88f09a | 54 | |
| andrewboyson | 3:92cfc43d493a | 55 | if (toAdd > maxAdd) toAdd = maxAdd; |
| andrewboyson | 3:92cfc43d493a | 56 | if (toAdd < -maxAdd) toAdd = -maxAdd; |
| andrewboyson | 2:55f070f05a43 | 57 | |
| andrewboyson | 5:a3e37ce4975d | 58 | TickAddPpb(-toAdd); |
| andrewboyson | 2:55f070f05a43 | 59 | |
| andrewboyson | 10:19ed22b94c99 | 60 | if (SyncTrace) LogTimeF("Sync setPpb diff %lld gives toAdd %lld gives TickPpb %ld\r\n", diff, toAdd, TickGetPpb()); |
| andrewboyson | 0:33686e88f09a | 61 | } |
| andrewboyson | 0:33686e88f09a | 62 | |
| andrewboyson | 13:0200519c9bbf | 63 | static int64_t lastIntClock = -1; //-1 indicates invalid value. 0 is a valid value. |
| andrewboyson | 13:0200519c9bbf | 64 | static int64_t lastExtClock = -1; |
| andrewboyson | 13:0200519c9bbf | 65 | static void reset(int64_t thisExtClock) |
| andrewboyson | 0:33686e88f09a | 66 | { |
| andrewboyson | 13:0200519c9bbf | 67 | TickSet(thisExtClock); |
| andrewboyson | 13:0200519c9bbf | 68 | TickSetPpb(0); |
| andrewboyson | 13:0200519c9bbf | 69 | lastIntClock = 0; |
| andrewboyson | 13:0200519c9bbf | 70 | lastExtClock = 0; |
| andrewboyson | 0:33686e88f09a | 71 | } |
| andrewboyson | 0:33686e88f09a | 72 | |
| andrewboyson | 12:3f338e85750f | 73 | static void sync(int64_t thisExtClock) |
| andrewboyson | 2:55f070f05a43 | 74 | { |
| andrewboyson | 13:0200519c9bbf | 75 | |
| andrewboyson | 5:a3e37ce4975d | 76 | if (!TickIsSet()) //Cold start - only ever true if the RTC was not set. |
| andrewboyson | 0:33686e88f09a | 77 | { |
| andrewboyson | 13:0200519c9bbf | 78 | LogTimeF("Sync - cold start of clock so resetting\r\n"); |
| andrewboyson | 13:0200519c9bbf | 79 | reset(thisExtClock); |
| andrewboyson | 0:33686e88f09a | 80 | return; |
| andrewboyson | 0:33686e88f09a | 81 | } |
| andrewboyson | 0:33686e88f09a | 82 | |
| andrewboyson | 0:33686e88f09a | 83 | //Get the time at the time of the interrupt |
| andrewboyson | 0:33686e88f09a | 84 | int64_t thisIntClock; |
| andrewboyson | 0:33686e88f09a | 85 | int64_t thisAbsClock; |
| andrewboyson | 14:7ef557918bb1 | 86 | TickRetrieveSnapshot(&thisIntClock, &thisAbsClock); |
| andrewboyson | 12:3f338e85750f | 87 | |
| andrewboyson | 0:33686e88f09a | 88 | //Calulate the time error |
| andrewboyson | 0:33686e88f09a | 89 | int64_t absDiff = thisAbsClock - thisExtClock; |
| andrewboyson | 17:927fc1eceb9d | 90 | if (llabs(absDiff) > ClockMaxOffsetSecs * ONE_BILLION) |
| andrewboyson | 0:33686e88f09a | 91 | { |
| andrewboyson | 13:0200519c9bbf | 92 | LogTimeF("Sync - offset is greater than %d seconds so resetting\r\n", ClockMaxOffsetSecs); |
| andrewboyson | 13:0200519c9bbf | 93 | reset(thisExtClock); |
| 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 | 13:0200519c9bbf | 119 | void SyncPpsI( ) { TickSaveSnapshotI(); } |
| andrewboyson | 13:0200519c9bbf | 120 | void SyncPpsN(time_t t ) { int64_t ns = t * ONE_BILLION; sync(ns); } |
| andrewboyson | 13:0200519c9bbf | 121 | void SyncNs (int64_t ns) { TickSaveSnapshotI(); sync(ns); } |