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
Revision 44:aa45226d118e, committed 2018-12-29
- Comitter:
- andrewboyson
- Date:
- Sat Dec 29 19:00:39 2018 +0000
- Parent:
- 43:45b11d2c5490
- Child:
- 45:1d8d5b312f72
- Commit message:
- Made TAI with conversion to UTC as required
Changed in this revision
--- a/clock/clkstate.c Wed Dec 05 11:35:16 2018 +0000
+++ b/clock/clkstate.c Sat Dec 29 19:00:39 2018 +0000
@@ -1,13 +1,84 @@
#include <stdint.h>
+#include "clktime.h"
+#include "tm.h"
+
#define GPREG0 (*((volatile unsigned *) 0x40024044))
+#define GPREG1 (*((volatile unsigned *) 0x40024048))
+//Sync states
volatile int32_t ClockSlew = 0; //ns - up to +/- 2.147s of slew
volatile int32_t ClockPpb = 0; //This gets set to the last recorded ppb in TickInit
void ClockSetPpb (int32_t value) { ClockPpb = value; GPREG0 = ClockPpb; }
void ClockAddPpb (int32_t value) { ClockPpb += value; GPREG0 = ClockPpb; }
+/*
++----+----+----+----+----+----+----+----+
+|Flgs| Leap months | Leap count |
+|UUDE| 12 bits | 16 bits |
++----+----+----+----+----+----+----+----+
+
+Leap months: 12 bits will hold 4096 months or 341 years
+
+Leap count: 16 bits will hold enough leaps seconds for 60,000 years
+
+Flgs
+U = unused
+D = direction: 1 to subtract; 0 to add
+E = Enable: 1 if leap to take into account at the start of the leap month; 0 if already taken or to be ignored
+*/
+
+//Leap seconds
+int ClockLeapSecondCount = 0; //12 bits holds enough leap seconds for at least 300 years.
+int64_t ClockLeapSecondCount64 = 0;
+static void makeLeapSecondCount64() { ClockLeapSecondCount64 = ((int64_t)ClockLeapSecondCount) << CLK_TIME_ONE_SECOND_SHIFT; }
+void ClockSetLeapSecondCount(int value)
+{
+ ClockLeapSecondCount = value;
+ makeLeapSecondCount64();
+ GPREG1 = GPREG1 & 0xFFFF0000 | value & 0x0000FFFF;
+}
+void ClockAddLeapSecondCount(int value)
+{
+ ClockSetLeapSecondCount(ClockLeapSecondCount + value);
+}
+
+//Next leap second
+int ClockNextLeapMonth1970 = 0;
+int64_t ClockNextLeapSecondUtc = 0;
+static void makeNextLeapSecondUtc()
+{
+ int year = ClockNextLeapMonth1970 / 12 + 1970;
+ int month = ClockNextLeapMonth1970 % 12 + 1;
+ struct tm tm;
+ TmFromInteger(year, month, 1, 0, 0, 0, &tm);
+ time_t t = TmUtcToTimeT(&tm);
+ ClockNextLeapSecondUtc = (int64_t)t << CLK_TIME_ONE_SECOND_SHIFT;
+}
+void ClockSetNextLeapMonth1970(int value)
+{
+ ClockNextLeapMonth1970 = value;
+ makeNextLeapSecondUtc();
+ GPREG1 = GPREG1 & 0xF000FFFF | (uint32_t)value << 16 & 0x0FFF0000; //Precedence order: shifts then ands then ors.
+}
+
+bool ClockNextLeapEnable = false;
+bool ClockNextLeapBackward = false;
+void ClockSetNextLeapEnable(bool value)
+{
+ ClockNextLeapEnable = value;
+ if (value) GPREG1 |= 0x10000000;
+ else GPREG1 &= 0xEFFFFFFF;
+}
+void ClockSetNextLeapBackward(bool value)
+{
+ ClockNextLeapBackward = value;
+ if (value) GPREG1 |= 0x20000000;
+ else GPREG1 &= 0xDFFFFFFF;
+}
+
+//Clock limits
int ClockSlewDivisor = 10;
int ClockSlewMaxMs = 10;
int ClockPpbDivisor = 10;
@@ -20,5 +91,11 @@
void ClockStateInit(void)
{
- ClockPpb = GPREG0; //This is saved each time Tickppb is updated
+ ClockPpb = GPREG0;
+ ClockLeapSecondCount = GPREG1 & 0x0000FFFF;
+ makeLeapSecondCount64();
+ ClockNextLeapMonth1970 = (GPREG1 & 0x0FFF0000) >> 16;
+ makeNextLeapSecondUtc();
+ ClockNextLeapEnable = GPREG1 & 0x10000000;
+ ClockNextLeapBackward = GPREG1 & 0x20000000;
}
\ No newline at end of file
--- a/clock/clkstate.h Wed Dec 05 11:35:16 2018 +0000 +++ b/clock/clkstate.h Sat Dec 29 19:00:39 2018 +0000 @@ -6,6 +6,20 @@ extern void ClockSetPpb(int32_t value); extern void ClockAddPpb(int32_t value); +extern int ClockLeapSecondCount; +extern int64_t ClockLeapSecondCount64; +extern void ClockSetLeapSecondCount(int value); +extern void ClockAddLeapSecondCount(int value); + +extern int ClockNextLeapMonth1970; //Months since 1970 +extern int64_t ClockNextLeapSecondUtc; +extern void ClockSetNextLeapMonth1970(int value); + +extern bool ClockNextLeapEnable; +extern bool ClockNextLeapBackward; +extern void ClockSetNextLeapEnable (bool value); +extern void ClockSetNextLeapBackward(bool value); + extern int ClockSlewDivisor ; extern int ClockSlewMaxMs ; extern int ClockPpbDivisor ;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/clock/clkutc.c Sat Dec 29 19:00:39 2018 +0000
@@ -0,0 +1,14 @@
+#include <stdint.h>
+#include "clktime.h"
+#include "clkstate.h"
+
+void ClkUtcHandleLeapSecond(int64_t tai)
+{
+ if (ClockNextLeapSecondUtc && tai >= ClockNextLeapSecondUtc + ClockLeapSecondCount64)
+ {
+ ClockAddLeapSecondCount(1);
+ ClockSetNextLeapMonth1970(0); //This resets ClockNextLeapSecondUtc
+ }
+}
+int64_t ClkUtcFromTai(int64_t tai) { return tai - ClockLeapSecondCount64; }
+int64_t ClkUtcToTai (int64_t utc) { return utc + ClockLeapSecondCount64; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clock/clkutc.h Sat Dec 29 19:00:39 2018 +0000 @@ -0,0 +1,4 @@ +#include <stdint.h> + +extern int64_t ClkUtcGet(uint32_t * pLeaps); +extern void ClkUtcSet(int64_t utc, uint32_t leaps);
--- a/tm/tm.c Wed Dec 05 11:35:16 2018 +0000
+++ b/tm/tm.c Sat Dec 29 19:00:39 2018 +0000
@@ -279,6 +279,16 @@
//Fill the day of week and the day of year part of the tm structure
calculateDayOfYearAndWeek(ptm->tm_year, ptm->tm_mon, ptm->tm_mday, &ptm->tm_yday, &ptm->tm_wday);
}
+void TmFromInteger(int year, int month, int mday, int hour, int min, int sec, struct tm* ptm)
+{
+ ptm->tm_year = year - 1900;
+ ptm->tm_mon = month - 1;
+ ptm->tm_mday = mday;
+ calculateDayOfYearAndWeek(ptm->tm_year, ptm->tm_mon, ptm->tm_mday, &ptm->tm_yday, &ptm->tm_wday);
+ ptm->tm_hour = hour;
+ ptm->tm_min = min;
+ ptm->tm_sec = sec;
+}
void TmIncrement(struct tm* ptm)
{
ptm->tm_sec++;
--- a/tm/tm.h Wed Dec 05 11:35:16 2018 +0000 +++ b/tm/tm.h Sat Dec 29 19:00:39 2018 +0000 @@ -6,5 +6,6 @@ extern void TmUtcToLocal(struct tm* ptm); extern void TmFromAsciiDateTime(const char* pDate, const char* pTime, struct tm* ptm); +extern void TmFromInteger(int year, int month, int mday, int hour, int min, int sec, struct tm* ptm); extern int TmSecondsBetween(struct tm* ptmLater, struct tm* ptmEarlier); extern void TmIncrement(struct tm* ptm); \ No newline at end of file