9 namespace date = satcat5::datetime;
10 namespace ptp = satcat5::ptp;
19 constexpr s64 PTP_EPOCH = 1000LL * 315964819;
27 s64 secs = s64((time + PTP_EPOCH) / 1000);
28 u32 msec = u32((time + PTP_EPOCH) % 1000);
29 return ptp::Time(secs, msec * ptp::NSEC_PER_MSEC);
34 : satcat5::poll::Timer()
35 , m_tref(SATCAT5_CLOCK->now())
50 m_tref = SATCAT5_CLOCK->now();
51 if (full) {m_tcount = 0; m_gps = 0;}
56 m_tref = SATCAT5_CLOCK->now();
63 if (m_tref.
clk != SATCAT5_CLOCK)
reset();
70 if (m_gps) m_gps += incr;
75 static constexpr s64 RTC_EPOCH =
79 static inline constexpr u8 bcd2int(u8 bcd)
80 {
return 10 * (bcd >> 4) + (bcd & 0x0F); }
81 static inline constexpr u8 int2bcd(u8 x)
82 {
return 16 * (x / 10) + (x % 10); }
86 u8 bcd_convert_24hr(u8 val) {
88 if (val & date::RTC_MIL_BIT)
89 return bcd2int(val & 0x7F);
103 case 0x10:
return 10;
104 case 0x11:
return 11;
105 case 0x32:
return 12;
106 case 0x21:
return 13;
107 case 0x22:
return 14;
108 case 0x23:
return 15;
109 case 0x24:
return 16;
110 case 0x25:
return 17;
111 case 0x26:
return 18;
112 case 0x27:
return 19;
113 case 0x28:
return 20;
114 case 0x29:
return 21;
115 case 0x30:
return 22;
116 case 0x31:
return 23;
124 static inline bool is_leap_year(u8 ct, u8 yy) {
125 return (yy % 4 == 0) && ((yy > 0) || (ct % 4 == 0));
129 static inline unsigned days_per_century(u8 ct) {
131 return is_leap_year(ct, 0) ? 36525 : 36524;
135 static inline unsigned days_per_year(u8 ct, u8 yy) {
136 return is_leap_year(ct, yy) ? 366 : 365;
140 static unsigned days_per_month(u8 ct, u8 yy, u8 mm) {
142 if ((mm == 2) && is_leap_year(ct, yy))
149 case 4:
case 6:
case 9:
case 11:
161 for (
unsigned c = 20 ; c <
ct ; ++c)
162 total += days_per_century(c);
165 for (
unsigned y = 0 ; y <
yr ; ++y)
166 total += days_per_year(
ct, y);
169 for (u32 m = 1 ; m <
mo ; ++m)
170 total += days_per_month(
ct,
yr, m);
173 return total +
dt - 1;
179 return 10*
ss + 1000*
sc + 60000*
mn + 3600000*
hr;
204 if ((time < 0) || (days >= 2921940))
208 u8 dw = (u8)((days + 6) % 7);
212 while (days >= days_per_century(ct))
213 days -= days_per_century(ct++);
217 while (days >= days_per_year(ct, yr))
218 days -= days_per_year(ct, yr++);
222 while (days >= days_per_month(ct, yr, mo))
223 days -= days_per_month(ct, yr, mo++);
226 u8 dt = (u8)(days + 1);
230 u8 ss = (u8)(rem % 100); rem /= 100;
231 u8 sc = (u8)(rem % 60); rem /= 60;
232 u8 mn = (u8)(rem % 60); rem /= 60;
236 return RtcTime {dw, ct, yr, mo, dt, hr, mn, sc, ss};
242 if ((days < UINT32_MAX) && (msec < UINT32_MAX))
253 wkn = (s32)rd->read_u32();
254 tow = rd->read_u32();
258 bool GpsTime::operator<(
const GpsTime& other)
const {
259 if (
wkn < other.
wkn)
return true;
260 if (
wkn > other.
wkn)
return false;
264 bool GpsTime::operator==(
const GpsTime& other)
const {
269 return (
ss < 100) && (
sc < 60) && (
mn < 60) && (
hr < 24)
270 && (
dt > 0) && (
dt <= days_per_month(
ct,
yr,
mo))
271 && (
mo > 0) && (
mo <= 12) && (
yr < 100)
272 && (
ct >= 20) && (
ct < 100) && (
dw < 7);
279 temp[0] = int2bcd(
ss);
280 temp[1] = int2bcd(
sc);
281 temp[2] = int2bcd(
mn);
283 temp[4] = int2bcd(
dt);
284 temp[5] = int2bcd(
mo);
285 temp[6] = int2bcd(
yr);
286 temp[7] = int2bcd(
dw);
298 ss = bcd2int(temp[0] & 0xFF);
299 sc = bcd2int(temp[1] & 0x7F);
300 mn = bcd2int(temp[2] & 0x7F);
301 hr = bcd_convert_24hr(temp[3]);
302 dt = bcd2int(temp[4] & 0x3F);
303 mo = bcd2int(temp[5] & 0x1F);
304 yr = bcd2int(temp[6] & 0xFF);
306 dw = bcd2int(temp[7] & 0x07);
317 u32 year = 100*
ct +
yr;
334 bool RtcTime::operator<(
const RtcTime& other)
const {
336 if (
ct < other.
ct)
return true;
337 if (
ct > other.
ct)
return false;
338 if (
yr < other.
yr)
return true;
339 if (
yr > other.
yr)
return false;
340 if (
mo < other.
mo)
return true;
341 if (
mo > other.
mo)
return false;
342 if (
dt < other.
dt)
return true;
343 if (
dt > other.
dt)
return false;
344 if (
hr < other.
hr)
return true;
345 if (
hr > other.
hr)
return false;
346 if (
mn < other.
mn)
return true;
347 if (
mn > other.
mn)
return false;
348 if (
sc < other.
sc)
return true;
349 if (
sc > other.
sc)
return false;
350 return ss < other.
ss;
353 bool RtcTime::operator==(
const RtcTime& other)
const {
355 return (
yr == other.
yr)
Real-time clock for tracking date/time.
void set(s64 gps)
Set current GPS time.
satcat5::datetime::GpsTime gps() const
Current time as GPS week number and time-of-week.
void reset(bool full=false)
Reset internals after changes to SATCAT5_CLOCK.
u32 uptime_usec() const
Get elapsed time since startup, in microseconds.
void timer_event() override
Child class MUST override this method.
Abstract API for reading byte-streams and packets.
virtual bool read_bytes(unsigned nbytes, void *dst)
Read 0 or more bytes into a buffer.
virtual unsigned get_read_ready() const =0
How many bytes can be read without blocking?
Abstract API for writing byte-streams and packets.
virtual void write_bytes(unsigned nbytes, const void *src)
Write 0 or more bytes from a buffer.
Internal buffer used by the Log class.
void wr_str(const char *str)
Write a null-terminated UTF-8 string.
void wr_d32(u32 val, unsigned zpad=0)
Write an unsigned integer (u32) in decimal format.
void timer_every(unsigned msec)
Configure a repeating notification every X milliseconds.
High-precision timestamp for use with PTP / IEEE1588.
s64 delta_msec() const
Convert time-differences to the designated unit.
Real-time clock conversion functions.
static const u8 RTC_MIL_BIT
Bit-flag in HR field indicating 24-HOUR clock format.
static constexpr u32 ONE_WEEK
Common time-related constants, measured in milliseconds.
static constexpr s64 TIME_ERROR
A date/time of zero indicates an error.
satcat5::ptp::Time to_ptp(s64 time)
Convert an internal timestamp into the designated format.
static constexpr u32 ONE_DAY
Common time-related constants, measured in milliseconds.
s64 from_rtc(const satcat5::datetime::RtcTime &time)
Convert the designated format into an internal timestamp.
satcat5::datetime::RtcTime to_rtc(s64 time)
Convert an internal timestamp into the designated format.
satcat5::datetime::Clock clock
Global instance of the datetime::Clock class.
static const datetime::RtcTime RTC_ERROR
Special datetime::RtcTime value indicating an error.
satcat5::datetime::GpsTime to_gps(s64 time)
Convert an internal timestamp into the designated format.
s64 from_ptp(const satcat5::ptp::Time &time)
Convert the designated format into an internal timestamp.
s64 from_gps(const satcat5::datetime::GpsTime &time)
Convert the designated format into an internal timestamp.
Diagnostic logging to UART and/or Ethernet ports.
GPS week-number and time-of-week.
Hardware RTC (e.g., Renesas ISL12082).
u8 hr
Hour (0-23) + MIL bit.
u8 ct
Century (20 = year 20xx)
u8 dw
Day of week (0-6, 0 = Sunday)
void write_to(satcat5::io::Writeable *wr) const
Write legacy binary format (Deprecated).
bool read_from(satcat5::io::Readable *rd)
Read legacy binary format (Deprecated).
u32 days_since_epoch() const
Days since 2000 Jan 1 (a Saturday).
void log_to(satcat5::log::LogBuffer &wr) const
Format as an ISO8601 / RFC3339 timestamp.
bool validate() const
Are current contents valid?
u32 msec_since_midnight() const
Milliseconds since midnight (0 - 86.4M).
unsigned elapsed_usec() const
Elapsed time in microseconds.
TimeRef * clk
Pointer to the parent time reference.
unsigned increment_msec()
Measure elapsed time in milliseconds, then increment by the returned quantized value.