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
clk/clkutc.c@58:ad2bfd0345de, 2019-02-21 (annotated)
- Committer:
- andrewboyson
- Date:
- Thu Feb 21 21:19:57 2019 +0000
- Revision:
- 58:ad2bfd0345de
- Parent:
- 57:4daf2e423b27
- Child:
- 67:c44c5c90e35a
Forgot to rename the end of some conversion routines from 'XxxxTimeT' to 'XxxxTime64'.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| andrewboyson | 46:d3d56cb47940 | 1 | #include <stdint.h> |
| andrewboyson | 47:fd2af868c10a | 2 | |
| andrewboyson | 46:d3d56cb47940 | 3 | #include "clktime.h" |
| andrewboyson | 47:fd2af868c10a | 4 | #include "tm.h" |
| andrewboyson | 47:fd2af868c10a | 5 | |
| andrewboyson | 47:fd2af868c10a | 6 | #define GPREG1 (*((volatile unsigned *) 0x40024048)) |
| andrewboyson | 47:fd2af868c10a | 7 | |
| andrewboyson | 47:fd2af868c10a | 8 | /* |
| andrewboyson | 47:fd2af868c10a | 9 | +----+----+----+----+----+----+----+----+ |
| andrewboyson | 47:fd2af868c10a | 10 | |Flgs| Leap months | Leap count | |
| andrewboyson | 47:fd2af868c10a | 11 | |UUDE| 12 bits | 16 bits | |
| andrewboyson | 47:fd2af868c10a | 12 | +----+----+----+----+----+----+----+----+ |
| andrewboyson | 47:fd2af868c10a | 13 | |
| andrewboyson | 47:fd2af868c10a | 14 | Leap months: 12 bits will hold 4096 months or 341 years |
| andrewboyson | 47:fd2af868c10a | 15 | |
| andrewboyson | 47:fd2af868c10a | 16 | Leap count: 16 bits will hold enough leaps seconds for 60,000 years |
| andrewboyson | 47:fd2af868c10a | 17 | |
| andrewboyson | 47:fd2af868c10a | 18 | Flgs |
| andrewboyson | 47:fd2af868c10a | 19 | U = unused |
| andrewboyson | 47:fd2af868c10a | 20 | D = direction: 1 to subtract; 0 to add |
| andrewboyson | 47:fd2af868c10a | 21 | E = Enable: 1 if leap to take into account at the start of the leap month; 0 if already taken or to be ignored |
| andrewboyson | 47:fd2af868c10a | 22 | */ |
| andrewboyson | 47:fd2af868c10a | 23 | |
| andrewboyson | 47:fd2af868c10a | 24 | //Leap seconds |
| andrewboyson | 55:e18983651004 | 25 | static int epochOffset = 0; //12 bits holds enough leap seconds for at least 300 years. |
| andrewboyson | 57:4daf2e423b27 | 26 | static clktime epochOffset64 = 0; |
| andrewboyson | 51:826c58fbfaed | 27 | int ClkUtcGetEpochOffset() { return epochOffset; } |
| andrewboyson | 51:826c58fbfaed | 28 | void ClkUtcSetEpochOffset(int value) |
| andrewboyson | 47:fd2af868c10a | 29 | { |
| andrewboyson | 55:e18983651004 | 30 | epochOffset = value; |
| andrewboyson | 57:4daf2e423b27 | 31 | epochOffset64 = (clktime)epochOffset << CLK_TIME_ONE_SECOND_SHIFT; |
| andrewboyson | 47:fd2af868c10a | 32 | GPREG1 = GPREG1 & 0xFFFF0000 | value & 0x0000FFFF; |
| andrewboyson | 47:fd2af868c10a | 33 | } |
| andrewboyson | 51:826c58fbfaed | 34 | void ClkUtcAddEpochOffset(int value) |
| andrewboyson | 47:fd2af868c10a | 35 | { |
| andrewboyson | 51:826c58fbfaed | 36 | ClkUtcSetEpochOffset(epochOffset + value); |
| andrewboyson | 47:fd2af868c10a | 37 | } |
| andrewboyson | 46:d3d56cb47940 | 38 | |
| andrewboyson | 47:fd2af868c10a | 39 | //Next leap second |
| andrewboyson | 51:826c58fbfaed | 40 | static int nextEpochMonth1970 = 0; |
| andrewboyson | 57:4daf2e423b27 | 41 | static clktime nextEpochUtc = 0; |
| andrewboyson | 51:826c58fbfaed | 42 | int ClkUtcGetNextEpochMonth1970() { return nextEpochMonth1970; } |
| andrewboyson | 57:4daf2e423b27 | 43 | clktime ClkUtcGetNextEpoch () { return nextEpochUtc; } |
| andrewboyson | 51:826c58fbfaed | 44 | static void makeNextEpochUtc() |
| andrewboyson | 47:fd2af868c10a | 45 | { |
| andrewboyson | 51:826c58fbfaed | 46 | int year = nextEpochMonth1970 / 12 + 1970; |
| andrewboyson | 51:826c58fbfaed | 47 | int month = nextEpochMonth1970 % 12 + 1; |
| andrewboyson | 47:fd2af868c10a | 48 | struct tm tm; |
| andrewboyson | 47:fd2af868c10a | 49 | TmFromInteger(year, month, 1, 0, 0, 0, &tm); |
| andrewboyson | 58:ad2bfd0345de | 50 | time64 t = TmUtcToTime64(&tm); |
| andrewboyson | 57:4daf2e423b27 | 51 | nextEpochUtc = (clktime)t << CLK_TIME_ONE_SECOND_SHIFT; |
| andrewboyson | 47:fd2af868c10a | 52 | } |
| andrewboyson | 51:826c58fbfaed | 53 | void ClkUtcSetNextEpochMonth1970(int value) |
| andrewboyson | 47:fd2af868c10a | 54 | { |
| andrewboyson | 51:826c58fbfaed | 55 | nextEpochMonth1970 = value; |
| andrewboyson | 51:826c58fbfaed | 56 | makeNextEpochUtc(); |
| andrewboyson | 47:fd2af868c10a | 57 | GPREG1 = GPREG1 & 0xF000FFFF | (uint32_t)value << 16 & 0x0FFF0000; //Precedence order: shifts then ands then ors. |
| andrewboyson | 47:fd2af868c10a | 58 | } |
| andrewboyson | 47:fd2af868c10a | 59 | |
| andrewboyson | 51:826c58fbfaed | 60 | static bool nextLeapEnable = false; |
| andrewboyson | 51:826c58fbfaed | 61 | static bool nextLeapForward = true; |
| andrewboyson | 51:826c58fbfaed | 62 | bool ClkUtcGetNextLeapEnable () { return nextLeapEnable; } |
| andrewboyson | 51:826c58fbfaed | 63 | bool ClkUtcGetNextLeapForward() { return nextLeapForward; } |
| andrewboyson | 47:fd2af868c10a | 64 | void ClkUtcSetNextLeapEnable(bool value) |
| andrewboyson | 47:fd2af868c10a | 65 | { |
| andrewboyson | 51:826c58fbfaed | 66 | nextLeapEnable = value; |
| andrewboyson | 47:fd2af868c10a | 67 | if (value) GPREG1 |= 0x10000000; |
| andrewboyson | 47:fd2af868c10a | 68 | else GPREG1 &= 0xEFFFFFFF; |
| andrewboyson | 47:fd2af868c10a | 69 | } |
| andrewboyson | 51:826c58fbfaed | 70 | void ClkUtcSetNextLeapForward(bool value) |
| andrewboyson | 47:fd2af868c10a | 71 | { |
| andrewboyson | 51:826c58fbfaed | 72 | nextLeapForward = value; |
| andrewboyson | 47:fd2af868c10a | 73 | if (value) GPREG1 |= 0x20000000; |
| andrewboyson | 47:fd2af868c10a | 74 | else GPREG1 &= 0xDFFFFFFF; |
| andrewboyson | 47:fd2af868c10a | 75 | } |
| andrewboyson | 51:826c58fbfaed | 76 | void ClkUtcTglNextLeapEnable () { ClkUtcSetNextLeapEnable (!nextLeapEnable ); } |
| andrewboyson | 51:826c58fbfaed | 77 | void ClkUtcTglNextLeapForward() { ClkUtcSetNextLeapForward(!nextLeapForward); } |
| andrewboyson | 47:fd2af868c10a | 78 | |
| andrewboyson | 48:b0f38e523552 | 79 | void ClkUtcInit(void) |
| andrewboyson | 47:fd2af868c10a | 80 | { |
| andrewboyson | 55:e18983651004 | 81 | epochOffset = GPREG1 & 0x0000FFFF; |
| andrewboyson | 57:4daf2e423b27 | 82 | epochOffset64 = (clktime)epochOffset << CLK_TIME_ONE_SECOND_SHIFT; |
| andrewboyson | 55:e18983651004 | 83 | nextEpochMonth1970 = (GPREG1 & 0x0FFF0000) >> 16; |
| andrewboyson | 51:826c58fbfaed | 84 | makeNextEpochUtc(); |
| andrewboyson | 55:e18983651004 | 85 | nextLeapEnable = GPREG1 & 0x10000000; |
| andrewboyson | 55:e18983651004 | 86 | nextLeapForward = GPREG1 & 0x20000000; |
| andrewboyson | 47:fd2af868c10a | 87 | } |
| andrewboyson | 47:fd2af868c10a | 88 | |
| andrewboyson | 47:fd2af868c10a | 89 | |
| andrewboyson | 57:4daf2e423b27 | 90 | clktime ClkUtcFromTai(clktime tai) { return tai - epochOffset64; } |
| andrewboyson | 57:4daf2e423b27 | 91 | clktime ClkUtcToTai (clktime utc) { return utc + epochOffset64; } |
| andrewboyson | 46:d3d56cb47940 | 92 | |
| andrewboyson | 57:4daf2e423b27 | 93 | void ClkUtcCheckAdjustLeapSecondCount(clktime tai) |
| andrewboyson | 46:d3d56cb47940 | 94 | { |
| andrewboyson | 51:826c58fbfaed | 95 | if (!nextLeapEnable) return; //Do nothing if leaps are disabled |
| andrewboyson | 49:e4424cc18bcb | 96 | |
| andrewboyson | 57:4daf2e423b27 | 97 | clktime utc = ClkUtcFromTai(tai); |
| andrewboyson | 57:4daf2e423b27 | 98 | clktime epochEnd = ClkUtcGetNextEpoch() - (nextLeapForward ? 0 : 1); |
| andrewboyson | 49:e4424cc18bcb | 99 | |
| andrewboyson | 51:826c58fbfaed | 100 | if (utc < epochEnd) return; //Do nothing until reached the end of the current epoch |
| andrewboyson | 49:e4424cc18bcb | 101 | |
| andrewboyson | 51:826c58fbfaed | 102 | if (nextLeapForward) ClkUtcAddEpochOffset(+1); //repeat 59 |
| andrewboyson | 51:826c58fbfaed | 103 | else ClkUtcAddEpochOffset(-1); //skip 59 |
| andrewboyson | 49:e4424cc18bcb | 104 | |
| andrewboyson | 49:e4424cc18bcb | 105 | ClkUtcSetNextLeapEnable(false); |
| andrewboyson | 49:e4424cc18bcb | 106 | |
| andrewboyson | 46:d3d56cb47940 | 107 | } |