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 17:927fc1eceb9d, committed 2018-01-11
- Comitter:
- andrewboyson
- Date:
- Thu Jan 11 17:39:36 2018 +0000
- Parent:
- 16:933cbe190bb0
- Child:
- 18:207dd1474cd9
- Commit message:
- Removed dependence on Mbed OS
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/clock-ntp.c Thu Jan 11 17:39:36 2018 +0000
@@ -0,0 +1,43 @@
+#include <stdint.h>
+
+
+#define SECONDS_BETWEEN_1900_AND_1970 2208988800ULL
+#define ONE_BILLION 1000000000LL
+
+#define ERA_BASE_LOW 1 //Adjust this from 0 to 1 between 1968 and 2036; 1 to 2 between 2104 and 2168
+#define ERA_BASE_HGH 0 //Adjust this from 0 to 1 between 2036 and 2104; 1 to 2 between 2172 and 2240
+
+#define ERA_LOW_SECS ERA_BASE_LOW * (1LL << 32)
+#define ERA_HGH_SECS ERA_BASE_HGH * (1LL << 32)
+#define ERA_LOW_NS ERA_LOW_SECS * ONE_BILLION
+#define ERA_HGH_NS ERA_HGH_SECS * ONE_BILLION
+
+uint64_t ClockNtpTimeStampFromNs(int64_t ns)
+{
+ uint64_t timestamp = ns << 2;
+ timestamp /= 1000; timestamp <<= 10;
+ timestamp /= 1000; timestamp <<= 10;
+ timestamp /= 1000; timestamp <<= 10;
+
+ timestamp += SECONDS_BETWEEN_1900_AND_1970 << 32; //This should just wrap around the unsigned timestamp removing the unwanted era.
+
+ return timestamp;
+}
+int64_t ClockNtpTimeStampToNs(uint64_t timestamp)
+{
+ int isHigh = (timestamp & (1ULL << 63)) != 0;
+
+ int64_t ns = timestamp - (SECONDS_BETWEEN_1900_AND_1970 << 32);
+ ns >>= 10; ns *= 1000;
+ ns >>= 10; ns *= 1000;
+ ns >>= 10; ns *= 1000;
+
+ ns >>= 2;
+
+ //Correct for era
+ if (isHigh) ns += ERA_HGH_NS;
+ else ns += ERA_LOW_NS;
+
+ return ns;
+}
+
--- a/clock-ntp.cpp Sat Dec 16 14:51:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#include "mbed.h"
-
-#define SECONDS_BETWEEN_1900_AND_1970 2208988800ULL
-#define ONE_BILLION 1000000000LL
-
-#define ERA_BASE_LOW 1 //Adjust this from 0 to 1 between 1968 and 2036; 1 to 2 between 2104 and 2168
-#define ERA_BASE_HGH 0 //Adjust this from 0 to 1 between 2036 and 2104; 1 to 2 between 2172 and 2240
-
-const int64_t ERA_LOW_SECS = ERA_BASE_LOW * (1LL << 32);
-const int64_t ERA_HGH_SECS = ERA_BASE_HGH * (1LL << 32);
-const int64_t ERA_LOW_NS = ERA_LOW_SECS * ONE_BILLION;
-const int64_t ERA_HGH_NS = ERA_HGH_SECS * ONE_BILLION;
-
-uint64_t ClockNtpTimeStampFromNs(int64_t ns)
-{
- uint64_t timestamp = ns << 2;
- timestamp /= 1000; timestamp <<= 10;
- timestamp /= 1000; timestamp <<= 10;
- timestamp /= 1000; timestamp <<= 10;
-
- timestamp += SECONDS_BETWEEN_1900_AND_1970 << 32; //This should just wrap around the unsigned timestamp removing the unwanted era.
-
- return timestamp;
-}
-int64_t ClockNtpTimeStampToNs(uint64_t timestamp)
-{
- bool isHigh = timestamp & 0x8000000000000000;
-
- int64_t ns = timestamp - (SECONDS_BETWEEN_1900_AND_1970 << 32);
- ns >>= 10; ns *= 1000;
- ns >>= 10; ns *= 1000;
- ns >>= 10; ns *= 1000;
-
- ns >>= 2;
-
- //Correct for era
- if (isHigh) ns += ERA_HGH_NS;
- else ns += ERA_LOW_NS;
-
- return ns;
-}
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/clock.c Thu Jan 11 17:39:36 2018 +0000
@@ -0,0 +1,136 @@
+#include <stdint.h>
+#include <stdio.h>
+
+#include "log.h"
+#include "tick.h"
+#include "sync.h"
+#include "time.h"
+#include "rtc.h"
+
+#define ONE_BILLION 1000000000
+
+void ClockNsToTmUtc (int64_t ns, struct tm* ptm)
+{
+ time_t t = ns / ONE_BILLION;
+ TimeToTmUtc(t, ptm);
+}
+int64_t ClockNsFromTmUtc(struct tm* ptm)
+{
+ time_t t = TimeFromTmUtc(ptm);
+ return t * ONE_BILLION;
+}
+
+int ClockSlewDivisor = 10;
+int ClockSlewMaxMs = 10;
+int ClockPpbDivisor = 10;
+int ClockPpbChangeMax = 1000;
+int ClockSyncedLimitNs = 10000000;
+int ClockSyncedHysterisNs = 1000000;
+int ClockSyncedLimitPpb = 1000;
+int ClockSyncedHysterisPpb = 100;
+int ClockMaxOffsetSecs = 3;
+
+static int64_t nowNs = 0;
+static time_t nowT = 0;
+static void calculateTimes()
+{
+ int64_t nsInt;
+ TickGetTimes(&nsInt, &nowNs);
+ nowT = nowNs / ONE_BILLION;
+}
+
+static int64_t refNs = 0;
+int64_t ClockRefNs()
+{
+ return refNs;
+}
+int ClockIsSet()
+{
+ return TickIsSet();
+}
+int ClockIsSynced()
+{
+ return SyncedRate && SyncedTime;
+}
+
+int64_t ClockNowNs()
+{
+ return nowNs;
+}
+
+void ClockTmLocal(struct tm* ptm)
+{
+ TimeToTmLocal(nowT, ptm);
+}
+void ClockTmUtc(struct tm* ptm)
+{
+ TimeToTmUtc(nowT, ptm);
+}
+
+void ClockAscii(char* p)
+{
+ struct tm tm;
+ TimeToTmUtc(nowT, &tm);
+ sprintf(p, "%d-%02d-%02d %02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
+void ClockInit()
+{
+ RtcInit();
+ TickInit();
+}
+
+int ClockTicked = 0; //Set to true for one scan each time the second changes
+
+void ClockMain()
+{
+ //Calculate ns and time_t
+ calculateTimes();
+
+ static int lastSyncedRate = 0;
+ static int lastSyncedTime = 0;
+
+ if ( SyncedRate && !lastSyncedRate) LogTimeF("Rate sync acquired\r\n");
+ if (!SyncedRate && lastSyncedRate) LogTimeF("Rate sync lost\r\n");
+ if ( SyncedTime && !lastSyncedTime) LogTimeF("Time sync acquired\r\n");
+ if (!SyncedTime && lastSyncedTime) LogTimeF("Time sync lost\r\n");
+
+ lastSyncedRate = SyncedRate;
+ lastSyncedTime = SyncedTime;
+
+ //Record the time the clock started
+ if (SyncedTime && SyncedRate) refNs = nowNs;
+
+ //Set a one shot memory for having had a tick
+ static time_t lastT = 0;
+ ClockTicked = lastT > 0 && lastT != nowT;
+ lastT = nowT;
+
+ if (TickIsSet())
+ {
+ //Save the time to the RTC on the second
+ if (ClockTicked)
+ {
+ struct tm tm;
+ ClockTmUtc(&tm);
+ RtcSetTm(&tm);
+ }
+ }
+ else
+ {
+ //Start the clock from the RTC if not started
+ if (RtcIsSet())
+ {
+ static int lastRtcSecond = -1;
+ struct tm tm;
+ RtcGetTm(&tm);
+ if (lastRtcSecond > 0 && tm.tm_sec != lastRtcSecond)
+ {
+ time_t t = TimeFromTmUtc(&tm);
+ TickSet(t * (int64_t)ONE_BILLION);
+ calculateTimes();
+ LogTimeF("Clock set from RTC\r\n");
+ }
+ lastRtcSecond = tm.tm_sec;
+ }
+ }
+}
\ No newline at end of file
--- a/clock.cpp Sat Dec 16 14:51:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-#include "mbed.h"
-#include "io.h"
-#include "log.h"
-#include "tick.h"
-#include "sync.h"
-#include "time.h"
-#include "rtc.h"
-
-#define ONE_BILLION 1000000000
-
-
-void ClockNsToTmUtc (int64_t ns, struct tm* ptm)
-{
- time_t t = ns / ONE_BILLION;
- TimeToTmUtc(t, ptm);
-}
-int64_t ClockNsFromTmUtc(struct tm* ptm)
-{
- time_t t = TimeFromTmUtc(ptm);
- return t * ONE_BILLION;
-}
-
-int ClockSlewDivisor = 10;
-int ClockSlewMaxMs = 10;
-int ClockPpbDivisor = 10;
-int ClockPpbChangeMax = 1000;
-int ClockSyncedLimitNs = 10000000;
-int ClockSyncedHysterisNs = 1000000;
-int ClockSyncedLimitPpb = 1000;
-int ClockSyncedHysterisPpb = 100;
-int ClockMaxOffsetSecs = 3;
-
-
-static int64_t nowNs = 0;
-static time_t nowT = 0;
-static void calculateTimes()
-{
- int64_t nsInt;
- TickGetTimes(&nsInt, &nowNs);
- nowT = nowNs / ONE_BILLION;
-}
-
-static int64_t refNs = 0;
-int64_t ClockRefNs()
-{
- return refNs;
-}
-bool ClockIsSet()
-{
- return TickIsSet();
-}
-bool ClockIsSynced()
-{
- return SyncedRate && SyncedTime;
-}
-
-int64_t ClockNowNs()
-{
- return nowNs;
-}
-
-void ClockTmLocal(struct tm* ptm)
-{
- TimeToTmLocal(nowT, ptm);
-}
-void ClockTmUtc(struct tm* ptm)
-{
- TimeToTmUtc(nowT, ptm);
-}
-
-void ClockAscii(char* p)
-{
- struct tm tm;
- TimeToTmUtc(nowT, &tm);
- sprintf(p, "%d-%02d-%02d %02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
-}
-int ClockInit()
-{
- RtcInit();
- TickInit();
- return 0;
-}
-
-bool ClockTicked = false; //Set to true for one scan each time the second changes
-
-
-int ClockMain()
-{
- //Calculate ns and time_t
- calculateTimes();
-
- static bool lastSyncedRate = false;
- static bool lastSyncedTime = false;
-
- if ( SyncedRate && !lastSyncedRate) LogTimeF("Rate sync acquired\r\n");
- if (!SyncedRate && lastSyncedRate) LogTimeF("Rate sync lost\r\n");
- if ( SyncedTime && !lastSyncedTime) LogTimeF("Time sync acquired\r\n");
- if (!SyncedTime && lastSyncedTime) LogTimeF("Time sync lost\r\n");
-
- lastSyncedRate = SyncedRate;
- lastSyncedTime = SyncedTime;
-
- //Record the time the clock started
- if (SyncedTime && SyncedRate) refNs = nowNs;
-
- //Set a one shot memory for having had a tick
- static time_t lastT = 0;
- ClockTicked = lastT > 0 && lastT != nowT;
- lastT = nowT;
-
-
- if (TickIsSet())
- {
- //Save the time to the RTC on the second
- if (ClockTicked)
- {
- struct tm tm;
- ClockTmUtc(&tm);
- RtcSetTm(&tm);
- }
- }
- else
- {
- //Start the clock from the RTC if not started
- if (RtcIsSet())
- {
- static int lastRtcSecond = -1;
- struct tm tm;
- RtcGetTm(&tm);
- if (lastRtcSecond > 0 && tm.tm_sec != lastRtcSecond)
- {
- time_t t = TimeFromTmUtc(&tm);
- TickSet(t * (int64_t)ONE_BILLION);
- calculateTimes();
- LogTimeF("Clock set from RTC\r\n");
- }
- lastRtcSecond = tm.tm_sec;
- }
- }
-
- return 0;
-}
\ No newline at end of file
--- a/clock.h Sat Dec 16 14:51:41 2017 +0000 +++ b/clock.h Thu Jan 11 17:39:36 2018 +0000 @@ -1,3 +1,6 @@ +#include <stdint.h> +#include <time.h> + extern void ClockNsToTmUtc (int64_t clk, struct tm* ptm); extern int64_t ClockNsFromTmUtc(struct tm* ptm); @@ -11,13 +14,13 @@ extern int ClockSyncedHysterisPpb; extern int ClockMaxOffsetSecs ; -extern int64_t ClockRefNs(); -extern bool ClockIsSet(); -extern bool ClockIsSynced(); -extern int64_t ClockNowNs(); +extern int64_t ClockRefNs(void); +extern int ClockIsSet(void); +extern int ClockIsSynced(void); +extern int64_t ClockNowNs(void); extern void ClockTmLocal(struct tm* ptm); extern void ClockTmUtc (struct tm* ptm); -extern bool ClockTicked; -extern int ClockInit(); -extern int ClockMain(); \ No newline at end of file +extern int ClockTicked; +extern void ClockInit(void); +extern void ClockMain(void); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rtc.c Thu Jan 11 17:39:36 2018 +0000
@@ -0,0 +1,40 @@
+#include <time.h>
+#include "peripherals.h"
+
+int RtcIsSet() { return !(LPC_RTC->RTC_AUX & 0x10); } //27.6.2.5 RTC Auxiliary control register - RTC Oscillator Fail detect flag
+
+void RtcGetTm(struct tm* ptm)
+{
+ ptm->tm_sec = LPC_RTC->SEC;
+ ptm->tm_min = LPC_RTC->MIN;
+ ptm->tm_hour = LPC_RTC->HOUR;
+ ptm->tm_mday = LPC_RTC->DOM;
+ ptm->tm_mon = LPC_RTC->MONTH - 1;
+ ptm->tm_year = LPC_RTC->YEAR - 1900;
+ ptm->tm_wday = LPC_RTC->DOW;
+ ptm->tm_yday = LPC_RTC->DOY - 1;
+ ptm->tm_isdst = -1; // -ve should signify that dst data is not available but it is used here to denote UTC
+}
+void RtcSetTm(struct tm* ptm)
+{
+ LPC_RTC->CCR = 2; //Stop and reset the divider (CTCRST bit 1 = 1)
+ LPC_RTC->SEC = ptm->tm_sec; // 0 --> 59
+ LPC_RTC->MIN = ptm->tm_min; // 0 --> 59
+ LPC_RTC->HOUR = ptm->tm_hour; // 0 --> 23
+ LPC_RTC->DOM = ptm->tm_mday; // 1 --> 31
+ LPC_RTC->MONTH = ptm->tm_mon + 1; // rtc 1 --> 12; tm 0 --> 11
+ LPC_RTC->YEAR = ptm->tm_year + 1900; // rtc 1900 --> 2100; tm 0 --> 200
+ LPC_RTC->DOW = ptm->tm_wday; // 0 --> 6 where 0 == Sunday
+ LPC_RTC->DOY = ptm->tm_yday + 1; // rtc 1 --> 366; tm 0 --> 365
+ LPC_RTC->RTC_AUX = 0x10; //27.6.2.5 RTC Auxiliary control register - RTC Oscillator Fail detect flag - Writing a 1 to this bit clears the flag.
+ LPC_RTC->CCR = 1; //Release the divider (CTCRST bit 1 = 0)
+}
+void RtcInit()
+{
+ LPC_RTC->CCR = 1; //27.6.2.2 Clock Control Register - enable the time counters (CLKEN bit 0 = 1); no reset (CTCRST bit 1 = 0); enable calibration counter (CCALEN bit 4 = 0)
+ LPC_RTC->CIIR = 0; //27.6.2.3 Counter Increment Interrupt Register - set to not interrupt
+ LPC_RTC->AMR = 0xFF; //27.6.2.4 Alarm Mask Register - mask all alarms
+ LPC_RTC->RTC_AUXEN = 0; //27.6.2.6 RTC Auxiliary Enable register - mask the oscillator stopped interrupt
+ LPC_RTC->ILR = 3; //27.6.2.1 Interrupt Location Register - Clear all interrupts
+
+}
--- a/rtc.cpp Sat Dec 16 14:51:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-#include "mbed.h"
-
-bool RtcIsSet() { return !(LPC_RTC->RTC_AUX & 0x10); } //27.6.2.5 RTC Auxiliary control register - RTC Oscillator Fail detect flag
-
-void RtcGetTm(struct tm* ptm)
-{
- ptm->tm_sec = LPC_RTC->SEC;
- ptm->tm_min = LPC_RTC->MIN;
- ptm->tm_hour = LPC_RTC->HOUR;
- ptm->tm_mday = LPC_RTC->DOM;
- ptm->tm_mon = LPC_RTC->MONTH - 1;
- ptm->tm_year = LPC_RTC->YEAR - 1900;
- ptm->tm_wday = LPC_RTC->DOW;
- ptm->tm_yday = LPC_RTC->DOY - 1;
- ptm->tm_isdst = -1; // -ve should signify that dst data is not available but it is used here to denote UTC
-}
-void RtcSetTm(struct tm* ptm)
-{
- LPC_RTC->CCR = 2; //Stop and reset the divider (CTCRST bit 1 = 1)
- LPC_RTC->SEC = ptm->tm_sec; // 0 --> 59
- LPC_RTC->MIN = ptm->tm_min; // 0 --> 59
- LPC_RTC->HOUR = ptm->tm_hour; // 0 --> 23
- LPC_RTC->DOM = ptm->tm_mday; // 1 --> 31
- LPC_RTC->MONTH = ptm->tm_mon + 1; // rtc 1 --> 12; tm 0 --> 11
- LPC_RTC->YEAR = ptm->tm_year + 1900; // rtc 1900 --> 2100; tm 0 --> 200
- LPC_RTC->DOW = ptm->tm_wday; // 0 --> 6 where 0 == Sunday
- LPC_RTC->DOY = ptm->tm_yday + 1; // rtc 1 --> 366; tm 0 --> 365
- LPC_RTC->RTC_AUX = 0x10; //27.6.2.5 RTC Auxiliary control register - RTC Oscillator Fail detect flag - Writing a 1 to this bit clears the flag.
- LPC_RTC->CCR = 1; //Release the divider (CTCRST bit 1 = 0)
-}
-void RtcInit()
-{
- LPC_RTC->CCR = 1; //27.6.2.2 Clock Control Register - enable the time counters (CLKEN bit 0 = 1); no reset (CTCRST bit 1 = 0); enable calibration counter (CCALEN bit 4 = 0)
- LPC_RTC->CIIR = 0; //27.6.2.3 Counter Increment Interrupt Register - set to not interrupt
- LPC_RTC->AMR = 0xFF; //27.6.2.4 Alarm Mask Register - mask all alarms
- LPC_RTC->RTC_AUXEN = 0; //27.6.2.6 RTC Auxiliary Enable register - mask the oscillator stopped interrupt
- LPC_RTC->ILR = 3; //27.6.2.1 Interrupt Location Register - Clear all interrupts
-
-}
--- a/rtc.h Sat Dec 16 14:51:41 2017 +0000 +++ b/rtc.h Thu Jan 11 17:39:36 2018 +0000 @@ -1,6 +1,8 @@ -extern bool RtcIsSet(); +#include <time.h> + +extern int RtcIsSet(void); extern void RtcGetTm(struct tm* ptm); extern void RtcSetTm(struct tm* ptm); -extern void RtcInit(); \ No newline at end of file +extern void RtcInit(void); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sync.c Thu Jan 11 17:39:36 2018 +0000
@@ -0,0 +1,121 @@
+#include <stdlib.h>
+
+#include "log.h"
+#include "tick.h"
+#include "time.h"
+#include "clock.h"
+
+#define ONE_BILLION 1000000000LL //Make sure ONE_BILLION is 64 bit by putting LL on the end
+#define ONE_MILLION 1000000
+
+#define TRUE 1
+#define FALSE 0
+
+int SyncTrace = FALSE;
+
+int SyncedTime = FALSE;
+int SyncedRate = FALSE;
+static void setSyncedTime(int64_t diff)
+{
+ int64_t absDiff = llabs(diff);
+ int64_t limit = ClockSyncedLimitNs;
+ int64_t hysterisis = ClockSyncedHysterisNs;
+
+ if (absDiff < limit - hysterisis) SyncedTime = TRUE;
+ if (absDiff > limit + hysterisis) SyncedTime = FALSE;
+}
+static void setSyncedRate(int64_t diff)
+{
+
+ int64_t absDiff = llabs(diff);
+ int64_t limit = ClockSyncedLimitPpb;
+ int64_t hysterisis = ClockSyncedHysterisPpb;
+
+ if (absDiff < limit - hysterisis) SyncedRate = TRUE;
+ if (absDiff > limit + hysterisis) SyncedRate = FALSE;
+}
+
+static void setSlew(int64_t diff)
+{
+ int64_t slew = -diff / ClockSlewDivisor;
+ int32_t slewMaxNs = ClockSlewMaxMs * ONE_MILLION;
+
+ if (slew > slewMaxNs) slew = slewMaxNs;
+ if (slew < -slewMaxNs) slew = -slewMaxNs;
+
+ TickSetSlew(slew);
+
+ if (SyncTrace) LogTimeF("Sync setSlew diff %lld gives slew %lld gives TickSlew %ld\r\n", diff, slew, TickGetSlew());
+}
+static void adjustPpb(int64_t diff)
+{
+ int64_t toAdd = diff / ClockPpbDivisor;
+ int32_t maxAdd = ClockPpbChangeMax;
+
+ if (toAdd > maxAdd) toAdd = maxAdd;
+ if (toAdd < -maxAdd) toAdd = -maxAdd;
+
+ TickAddPpb(-toAdd);
+
+ if (SyncTrace) LogTimeF("Sync setPpb diff %lld gives toAdd %lld gives TickPpb %ld\r\n", diff, toAdd, TickGetPpb());
+}
+
+static int64_t lastIntClock = -1; //-1 indicates invalid value. 0 is a valid value.
+static int64_t lastExtClock = -1;
+static void reset(int64_t thisExtClock)
+{
+ TickSet(thisExtClock);
+ TickSetPpb(0);
+ lastIntClock = 0;
+ lastExtClock = 0;
+}
+
+static void sync(int64_t thisExtClock)
+{
+
+ if (!TickIsSet()) //Cold start - only ever true if the RTC was not set.
+ {
+ LogTimeF("Sync - cold start of clock so resetting\r\n");
+ reset(thisExtClock);
+ return;
+ }
+
+ //Get the time at the time of the interrupt
+ int64_t thisIntClock;
+ int64_t thisAbsClock;
+ TickRetrieveSnapshot(&thisIntClock, &thisAbsClock);
+
+ //Calulate the time error
+ int64_t absDiff = thisAbsClock - thisExtClock;
+ if (llabs(absDiff) > ClockMaxOffsetSecs * ONE_BILLION)
+ {
+ LogTimeF("Sync - offset is greater than %d seconds so resetting\r\n", ClockMaxOffsetSecs);
+ reset(thisExtClock);
+ return;
+ }
+ setSlew(absDiff);
+ setSyncedTime(absDiff);
+
+ //Calculate the rate error
+ if (lastExtClock > -1)
+ {
+ int64_t extPeriod = thisExtClock - lastExtClock;
+
+ int64_t intPeriod = thisIntClock - lastIntClock;
+ int64_t periodDiff = intPeriod - extPeriod;
+
+ int64_t ppb;
+ if (extPeriod == ONE_BILLION) ppb = periodDiff; //This saves a 64bit multiplication and division for PPS
+ else ppb = periodDiff * ONE_BILLION / extPeriod;
+
+ adjustPpb(ppb);
+ setSyncedRate(ppb);
+ }
+
+ //Save last values
+ lastIntClock = thisIntClock;
+ lastExtClock = thisExtClock;
+}
+void SyncPpsI( ) { TickSaveSnapshotI(); }
+void SyncPpsN(time_t t ) { int64_t ns = t * ONE_BILLION; sync(ns); }
+void SyncNs (int64_t ns) { TickSaveSnapshotI(); sync(ns); }
--- a/sync.cpp Sat Dec 16 14:51:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-#include "mbed.h"
-#include "log.h"
-#include "tick.h"
-#include "time.h"
-#include "clock.h"
-
-#define ONE_BILLION 1000000000LL //Make sure ONE_BILLION is 64 bit by putting LL on the end
-#define ONE_MILLION 1000000
-
-bool SyncTrace = false;
-
-bool SyncedTime = false;
-bool SyncedRate = false;
-static void setSyncedTime(int64_t diff)
-{
- int64_t absDiff = llabs(diff);
- int64_t limit = ClockSyncedLimitNs;
- int64_t hysterisis = ClockSyncedHysterisNs;
-
- if (absDiff < limit - hysterisis) SyncedTime = true;
- if (absDiff > limit + hysterisis) SyncedTime = false;
-}
-static void setSyncedRate(int64_t diff)
-{
-
- int64_t absDiff = llabs(diff);
- int64_t limit = ClockSyncedLimitPpb;
- int64_t hysterisis = ClockSyncedHysterisPpb;
-
- if (absDiff < limit - hysterisis) SyncedRate = true;
- if (absDiff > limit + hysterisis) SyncedRate = false;
-}
-
-static void setSlew(int64_t diff)
-{
- int64_t slew = -diff / ClockSlewDivisor;
- int32_t slewMaxNs = ClockSlewMaxMs * ONE_MILLION;
-
- if (slew > slewMaxNs) slew = slewMaxNs;
- if (slew < -slewMaxNs) slew = -slewMaxNs;
-
- TickSetSlew(slew);
-
- if (SyncTrace) LogTimeF("Sync setSlew diff %lld gives slew %lld gives TickSlew %ld\r\n", diff, slew, TickGetSlew());
-}
-static void adjustPpb(int64_t diff)
-{
- int64_t toAdd = diff / ClockPpbDivisor;
- int32_t maxAdd = ClockPpbChangeMax;
-
- if (toAdd > maxAdd) toAdd = maxAdd;
- if (toAdd < -maxAdd) toAdd = -maxAdd;
-
- TickAddPpb(-toAdd);
-
- if (SyncTrace) LogTimeF("Sync setPpb diff %lld gives toAdd %lld gives TickPpb %ld\r\n", diff, toAdd, TickGetPpb());
-}
-
-static int64_t lastIntClock = -1; //-1 indicates invalid value. 0 is a valid value.
-static int64_t lastExtClock = -1;
-static void reset(int64_t thisExtClock)
-{
- TickSet(thisExtClock);
- TickSetPpb(0);
- lastIntClock = 0;
- lastExtClock = 0;
-}
-
-static void sync(int64_t thisExtClock)
-{
-
- if (!TickIsSet()) //Cold start - only ever true if the RTC was not set.
- {
- LogTimeF("Sync - cold start of clock so resetting\r\n");
- reset(thisExtClock);
- return;
- }
-
- //Get the time at the time of the interrupt
- int64_t thisIntClock;
- int64_t thisAbsClock;
- TickRetrieveSnapshot(&thisIntClock, &thisAbsClock);
-
- //Calulate the time error
- int64_t absDiff = thisAbsClock - thisExtClock;
- if (abs(absDiff) > ClockMaxOffsetSecs * ONE_BILLION)
- {
- LogTimeF("Sync - offset is greater than %d seconds so resetting\r\n", ClockMaxOffsetSecs);
- reset(thisExtClock);
- return;
- }
- setSlew(absDiff);
- setSyncedTime(absDiff);
-
- //Calculate the rate error
- if (lastExtClock > -1)
- {
- int64_t extPeriod = thisExtClock - lastExtClock;
-
- int64_t intPeriod = thisIntClock - lastIntClock;
- int64_t periodDiff = intPeriod - extPeriod;
-
- int64_t ppb;
- if (extPeriod == ONE_BILLION) ppb = periodDiff; //This saves a 64bit multiplication and division for PPS
- else ppb = periodDiff * ONE_BILLION / extPeriod;
-
- adjustPpb(ppb);
- setSyncedRate(ppb);
- }
-
- //Save last values
- lastIntClock = thisIntClock;
- lastExtClock = thisExtClock;
-}
-void SyncPpsI( ) { TickSaveSnapshotI(); }
-void SyncPpsN(time_t t ) { int64_t ns = t * ONE_BILLION; sync(ns); }
-void SyncNs (int64_t ns) { TickSaveSnapshotI(); sync(ns); }
--- a/sync.h Sat Dec 16 14:51:41 2017 +0000 +++ b/sync.h Thu Jan 11 17:39:36 2018 +0000 @@ -1,9 +1,11 @@ -extern bool SyncTrace; +#include <time.h> + +extern int SyncTrace; -extern bool SyncedTime; -extern bool SyncedRate; +extern int SyncedTime; +extern int SyncedRate; -extern void SyncPpsI(); +extern void SyncPpsI(void); extern void SyncPpsN(time_t t); extern void SyncNs(int64_t ns); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tick.c Thu Jan 11 17:39:36 2018 +0000
@@ -0,0 +1,152 @@
+#include "peripherals.h"
+#include "rtc.h"
+#include "time.h"
+#include "tick.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define ONE_BILLION 1000000000
+
+static volatile int64_t nsTickCount;
+static volatile int64_t nsFreqCount;
+static volatile int64_t nsTimeCount;
+
+static int nsCountIsSet = FALSE;
+int TickIsSet() { return nsCountIsSet; }
+void TickSet(int64_t extClock)
+{
+ nsTickCount = 0;
+ nsFreqCount = 0;
+ nsTimeCount = extClock;
+ LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
+ LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC.
+ nsCountIsSet = TRUE;
+}
+
+static volatile int32_t slew = 0; //ns - up to +/- 2.147s of slew
+int32_t TickGetSlew() { return slew; }
+void TickSetSlew(int32_t value) { slew = value; }
+
+static volatile int32_t ppb = 0;
+int32_t TickGetPpb () { return ppb; }
+void TickSetPpb (int32_t value) { ppb = value; LPC_RTC->GPREG0 = ppb; }
+void TickAddPpb (int32_t value) { ppb += value; LPC_RTC->GPREG0 = ppb; }
+
+#define CLOCK_TIC 0
+#define CLOCK_INT 1
+#define CLOCK_ABS 2
+
+__irq void TickHandler(void)
+{//Checked the number of counts and this routine takes 46 counts or about 0.5us
+
+ //Reset the timer interrupt
+ LPC_TIM1->IR |= 1;
+
+ //reset the tick timer
+ LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
+ LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC
+
+ //Calculate the new counts
+ nsTickCount += ONE_BILLION;
+ nsFreqCount += ppb;
+ nsTimeCount += slew;
+
+ //Feedback the amount slewed
+ slew = 0;
+}
+static volatile int64_t nsTickSnapshot;
+static volatile int64_t nsFreqSnapshot;
+static volatile int64_t nsTimeSnapshot;
+static volatile int32_t timerSnapshot;
+
+void TickSaveSnapshotI()
+{
+ timerSnapshot = LPC_TIM1->TC;
+ nsTickSnapshot = nsTickCount;
+ nsFreqSnapshot = nsFreqCount;
+ nsTimeSnapshot = nsTimeCount;
+}
+static void makeTimesFromCounts(int32_t timerCount, int64_t tickNs, int64_t freqNs, int64_t timeNs, int64_t* pNsInt, int64_t* pNsAbs)
+{
+ int64_t fraction = timerCount;
+ fraction <<= 32;
+ fraction /= TICK_COUNT_PER_SECOND;
+
+ int64_t nsFraction;
+
+ int64_t nsBase = tickNs;
+ int64_t nsPerTick = ONE_BILLION;
+
+ nsBase += freqNs;
+ nsPerTick += ppb;
+ nsFraction = (nsPerTick * fraction) >> 32;
+ *pNsInt = nsBase + nsFraction;
+
+ nsBase += timeNs;
+ nsPerTick += slew;
+ nsFraction = (nsPerTick * fraction) >> 32;
+ *pNsAbs = nsBase + nsFraction;
+}
+void TickRetrieveSnapshot(int64_t* pNsInt, int64_t* pNsAbs)
+{
+ makeTimesFromCounts(timerSnapshot, nsTickSnapshot, nsFreqSnapshot, nsTimeSnapshot, pNsInt, pNsAbs);
+}
+void TickGetTimes(int64_t* pNsInt, int64_t* pNsAbs)
+{
+ int32_t timerCount;
+ int64_t tickNs;
+ int64_t freqNs;
+ int64_t timeNs;
+
+ __disable_irq();
+ timerCount = LPC_TIM1->TC;
+ tickNs = nsTickCount;
+ freqNs = nsFreqCount;
+ timeNs = nsTimeCount;
+ __enable_irq();
+
+ makeTimesFromCounts(timerCount, tickNs, freqNs, timeNs, pNsInt, pNsAbs);
+}
+
+void TickInit(void)
+{
+ nsTickCount = 0;
+ nsFreqCount = 0;
+ nsTimeCount = 0;
+
+ ppb = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated
+ slew = 0;
+ nsCountIsSet = FALSE;
+
+ LPC_SC->PCLKSEL0 &= ~0x20; // 4.7.3 Peripheral Clock Selection - PCLK_peripheral PCLK_TIMER1 01xxxx = CCLK - reset bit 5
+ LPC_SC->PCLKSEL0 |= 0x10; // set bit 4
+ LPC_SC->PCONP |= 4; // 4.8.9 Power Control for Peripherals register - Timer1 Power On
+ LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
+ LPC_TIM1->CTCR = 0; // 21.6.3 Count Control Register - Timer mode
+ LPC_TIM1->PR = 0; // 21.6.5 Prescale register - Don't prescale 96MHz clock (divide by PR+1).
+ LPC_TIM1->MR0 = TICK_COUNT_PER_SECOND; // 21.6.7 Match Register 0 - Match count
+ LPC_TIM1->MCR = 1; // 21.6.8 Match Control Register - interrupt on match
+ LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC
+
+ NVIC->ISER[0] |= 0x04; // 6.5.1 bit2 == Interrupt set enable for timer 1.
+}
+int32_t TickElapsed(int32_t* pLastTime)
+{
+ int32_t thisTime = LPC_TIM1->TC;
+
+ if (thisTime < *pLastTime) *pLastTime -= TICK_COUNT_PER_SECOND; //lastCount could be 96 000 002 and thisTime could be 00 000 100 which should give 98
+ int32_t elapsed = thisTime - *pLastTime;
+
+ *pLastTime = thisTime;
+ return elapsed;
+}
+int Ticked(int32_t* pLastTime)
+{
+ int thisTime = LPC_TIM1->TC;
+
+ int ticked = thisTime < *pLastTime;
+
+ *pLastTime = thisTime;
+ return ticked;
+}
--- a/tick.cpp Sat Dec 16 14:51:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-#include "mbed.h"
-#include "rtc.h"
-#include "time.h"
-#include "tick.h"
-#include "io.h"
-
-#define ONE_BILLION 1000000000
-
-static volatile int64_t nsTickCount;
-static volatile int64_t nsFreqCount;
-static volatile int64_t nsTimeCount;
-
-static bool nsCountIsSet = false;
-bool TickIsSet() { return nsCountIsSet; }
-void TickSet(int64_t extClock)
-{
- nsTickCount = 0;
- nsFreqCount = 0;
- nsTimeCount = extClock;
- LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
- LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC.
- nsCountIsSet = true;
-}
-
-static volatile int32_t slew = 0; //ns - up to +/- 2.147s of slew
-int32_t TickGetSlew() { return slew; }
-void TickSetSlew(int32_t value) { slew = value; }
-
-static volatile int32_t ppb = 0;
-int32_t TickGetPpb () { return ppb; }
-void TickSetPpb (int32_t value) { ppb = value; LPC_RTC->GPREG0 = ppb; }
-void TickAddPpb (int32_t value) { ppb += value; LPC_RTC->GPREG0 = ppb; }
-
-#define CLOCK_TIC 0
-#define CLOCK_INT 1
-#define CLOCK_ABS 2
-
-static void tick(void)
-{//Checked the number of counts and this routine takes 46 counts or about 0.5us
-
- //Reset the timer interrupt
- LPC_TIM1->IR |= 1;
-
- //reset the tick timer
- LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
- LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC
-
- //Calculate the new counts
- nsTickCount += ONE_BILLION;
- nsFreqCount += ppb;
- nsTimeCount += slew;
-
- //Feedback the amount slewed
- slew = 0;
-}
-static volatile int64_t nsTickSnapshot;
-static volatile int64_t nsFreqSnapshot;
-static volatile int64_t nsTimeSnapshot;
-static volatile int32_t timerSnapshot;
-
-void TickSaveSnapshotI()
-{
- timerSnapshot = LPC_TIM1->TC;
- nsTickSnapshot = nsTickCount;
- nsFreqSnapshot = nsFreqCount;
- nsTimeSnapshot = nsTimeCount;
-}
-static void makeTimesFromCounts(int32_t timerCount, int64_t tickNs, int64_t freqNs, int64_t timeNs, int64_t* pNsInt, int64_t* pNsAbs)
-{
- int64_t fraction = timerCount;
- fraction <<= 32;
- fraction /= TICK_COUNT_PER_SECOND;
-
- int64_t nsFraction;
-
- int64_t nsBase = tickNs;
- int64_t nsPerTick = ONE_BILLION;
-
- nsBase += freqNs;
- nsPerTick += ppb;
- nsFraction = (nsPerTick * fraction) >> 32;
- *pNsInt = nsBase + nsFraction;
-
- nsBase += timeNs;
- nsPerTick += slew;
- nsFraction = (nsPerTick * fraction) >> 32;
- *pNsAbs = nsBase + nsFraction;
-}
-void TickRetrieveSnapshot(int64_t* pNsInt, int64_t* pNsAbs)
-{
- makeTimesFromCounts(timerSnapshot, nsTickSnapshot, nsFreqSnapshot, nsTimeSnapshot, pNsInt, pNsAbs);
-}
-void TickGetTimes(int64_t* pNsInt, int64_t* pNsAbs)
-{
- int32_t timerCount;
- int64_t tickNs;
- int64_t freqNs;
- int64_t timeNs;
-
- __disable_irq();
- timerCount = LPC_TIM1->TC;
- tickNs = nsTickCount;
- freqNs = nsFreqCount;
- timeNs = nsTimeCount;
- __enable_irq();
-
- makeTimesFromCounts(timerCount, tickNs, freqNs, timeNs, pNsInt, pNsAbs);
-}
-
-int TickInit(void)
-{
- nsTickCount = 0;
- nsFreqCount = 0;
- nsTimeCount = 0;
-
- ppb = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated
- slew = 0;
- nsCountIsSet = false;
-
- LPC_SC->PCLKSEL0 &= ~0x20; // 4.7.3 Peripheral Clock Selection - PCLK_peripheral PCLK_TIMER1 01xxxx = CCLK - reset bit 5
- LPC_SC->PCLKSEL0 |= 0x10; // set bit 4
- LPC_SC->PCONP |= 4; // 4.8.9 Power Control for Peripherals register - Timer1 Power On
- LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
- LPC_TIM1->CTCR = 0; // 21.6.3 Count Control Register - Timer mode
- LPC_TIM1->PR = 0; // 21.6.5 Prescale register - Don't prescale 96MHz clock (divide by PR+1).
- LPC_TIM1->MR0 = TICK_COUNT_PER_SECOND; // 21.6.7 Match Register 0 - Match count
- LPC_TIM1->MCR = 1; // 21.6.8 Match Control Register - interrupt on match
- LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC
-
- NVIC_SetVector(TIMER1_IRQn, (uint32_t)&tick);
- NVIC_EnableIRQ(TIMER1_IRQn);
-
- return 0;
-}
-int32_t TickElapsed(int32_t* pLastTime)
-{
- int32_t thisTime = LPC_TIM1->TC;
-
- if (thisTime < *pLastTime) *pLastTime -= TICK_COUNT_PER_SECOND; //lastCount could be 96 000 002 and thisTime could be 00 000 100 which should give 98
- int32_t elapsed = thisTime - *pLastTime;
-
- *pLastTime = thisTime;
- return elapsed;
-}
-bool Ticked(int32_t* pLastTime)
-{
- int thisTime = LPC_TIM1->TC;
-
- bool ticked = thisTime < *pLastTime;
-
- *pLastTime = thisTime;
- return ticked;
-}
--- a/tick.h Sat Dec 16 14:51:41 2017 +0000 +++ b/tick.h Thu Jan 11 17:39:36 2018 +0000 @@ -1,17 +1,19 @@ -extern void TickSaveSnapshotI(); +#include <stdint.h> + +extern void TickSaveSnapshotI(void); extern void TickRetrieveSnapshot(int64_t* pNsInt, int64_t* pNsAbs); extern void TickGetTimes (int64_t* pNsInt, int64_t* pNsAbs); extern void TickSet(int64_t extClock); -extern int32_t TickGetSlew(); extern void TickSetSlew(int32_t value); -extern int32_t TickGetPpb (); extern void TickSetPpb (int32_t value); extern void TickAddPpb(int32_t value); -extern bool TickIsSet(); +extern int32_t TickGetSlew(void); extern void TickSetSlew(int32_t value); +extern int32_t TickGetPpb (void); extern void TickSetPpb (int32_t value); extern void TickAddPpb(int32_t value); +extern int TickIsSet(void); extern int32_t TickElapsed(int32_t* pLastCount); -extern int Ticked(); +extern int Ticked(int32_t* pLastTime); -extern int TickInit(); +extern void TickInit(void); -const int TICK_COUNT_PER_SECOND = 96000000; -const int TICK_COUNT_PER_MS = TICK_COUNT_PER_SECOND / 1000; -const int TICK_COUNT_PER_US = TICK_COUNT_PER_MS / 1000; +#define TICK_COUNT_PER_SECOND 96000000 +#define TICK_COUNT_PER_MS TICK_COUNT_PER_SECOND / 1000; +#define TICK_COUNT_PER_US TICK_COUNT_PER_MS / 1000;