Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

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?

UserRevisionLine numberNew 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 }