7 #include <satcat5/ntp_client.h>
16 using satcat5::udp::PORT_NTP_SERVER;
19 static constexpr
unsigned DEBUG_VERBOSE = 0;
26 #ifndef SATCAT5_UTC_OFFSET
27 #define SATCAT5_UTC_OFFSET 37
35 constexpr u64 NTP_OFFSET_SEC = 2208988800ull - SATCAT5_UTC_OFFSET;
44 , m_leap(
Header::LEAP_NONE)
48 m_iface.udp()->
add(
this);
51 #if SATCAT5_ALLOW_DELETION
53 m_iface.udp()->
remove(
this);
58 if (DEBUG_VERBOSE > 0)
Log(DEBUG,
"NtpClient: client_connect").
write(server);
59 m_iface.
connect(server, PORT_NTP_SERVER, PORT_NTP_SERVER);
64 if (DEBUG_VERBOSE > 0)
Log(DEBUG,
"NtpClient: client_close").
write(m_iface.dstaddr());
76 if (DEBUG_VERBOSE > 1)
Log(DEBUG,
"NtpClient: frame_rcvd").
write(rxtime);
82 if (msg.
vn() < Header::VERSION_3)
return;
83 if (msg.
vn() > Header::VERSION_4)
return;
86 if (msg.
mode() == Header::MODE_SERVER) {
89 if (m_iface.udp()->reply_ip() == m_iface.dstaddr())
90 rcvd_reply(msg, rxtime);
91 }
else if (msg.
mode() == Header::MODE_CLIENT) {
93 if (m_stratum) send_reply(msg, rxtime);
102 void Client::rcvd_reply(
const Header& msg, u64 rxtime) {
103 if (DEBUG_VERBOSE > 0)
Log(DEBUG,
"NtpClient: rcvd_reply").
write(msg.
stratum);
124 bool Client::send_reply(
const Header& query, u64 rxtime) {
125 if (DEBUG_VERBOSE > 0)
Log(DEBUG,
"NtpClient: send_reply");
131 msg.
lvm = m_leap | query.
vn() | Header::MODE_SERVER;
143 ok = wr->write_finalize();
144 }
else if (DEBUG_VERBOSE > 1) {
145 Log(DEBUG,
"NtpClient: send_reply blocked");
150 bool Client::send_query() {
151 if (DEBUG_VERBOSE > 0)
Log(DEBUG,
"NtpClient: send_query");
157 msg.
lvm = m_leap | Header::VERSION_4 | Header::MODE_CLIENT;
169 ok = wr->write_finalize();
170 }
else if (DEBUG_VERBOSE > 1) {
171 Log(DEBUG,
"NtpClient: send_query blocked");
183 u64 sec = u64(t.
round_secs()) + NTP_OFFSET_SEC;
184 u64 frac = u64(t.
round_nsec()) * 18446744073ull;
185 return (sec << 32) + (frac >> 32);
190 s64 secs = s64((t >> 32) - NTP_OFFSET_SEC);
191 u64 nsec = ((t & 0xFFFFFFFFu) * 1000000000ull) >> 32;
194 const s64 ROLLOVER = (1ull << 32);
196 s64 era = satcat5::util::div_round(ref - secs, ROLLOVER);
198 return Time(secs + era * ROLLOVER, nsec);
Limited read of next N bytes.
The Log class creates and formats one log message.
Log & write(const char *str)
Formatting methods for various data types.
void add(satcat5::net::Protocol *proto)
Register a Protocol object.
void remove(satcat5::net::Protocol *proto)
Unregister a Protocol object.
Client and/or server for the Network Time Protocol (NTP).
void client_connect(const satcat5::ip::Addr &server, s8 poll_rate=satcat5::ntp::Header::TIME_1MIN)
Enable client mode by connecting to the specified server.
void timer_event() override
Child class MUST override this method.
void client_close()
Close the connection to a remote server.
void client_set_rate(s8 poll_rate)
Set the client polling rate.
satcat5::ptp::Time to_ptp(u64 t) const
Convert NTP timestamp to PTP format.
u64 to_ntp(const satcat5::ptp::Time &t) const
Convert any PTP timestamp to NTP format.
u64 ntp_now() const
Get the current time in NTP format.
void frame_rcvd(satcat5::io::LimitedRead &src) override
Dispatch calls frame_rcvd(...) for each incoming frame with with a matching net::Type value.
void timer_every(unsigned msec)
Configure a repeating notification every X milliseconds.
void notify_callbacks(const satcat5::ptp::Measurement &meas)
Notify all Callback objects of a new Measurement.
High-precision timestamp for use with PTP / IEEE1588.
s64 field_secs() const
Read the "seconds" field without intermediate rounding.
u32 round_nsec() const
Return "nanoseconds" field after rounding to the nearest nanosecond.
s64 round_secs() const
Return "seconds" field after rounding to the nearest nanosecond.
Generic interface to a numerically-controlled reference clock.
virtual satcat5::ptp::Time clock_now()=0
Return the current time if available, TIME_ZERO otherwise.
satcat5::io::Writeable * open_write(unsigned len) override
Open a new frame to the designated address and type.
void connect(const satcat5::udp::Addr &dstaddr, const satcat5::eth::MacAddr &dstmac, const satcat5::udp::Port &dstport, const satcat5::udp::Port &srcport=satcat5::udp::PORT_NONE, const satcat5::eth::VlanTag &vtag=satcat5::eth::VTAG_NONE)
Manual address resolution (user supplies IP + MAC).
void close() override
Close any open connections and revert to idle.
Dispatcher sorts incoming UDP messages by port index.
satcat5::io::Writeable * open_reply(const satcat5::net::Type &type, unsigned nbytes) override
Reply to the sender of the most recent received message.
Diagnostic logging to UART and/or Ethernet ports.
constexpr s8 DEBUG
Define basic priority codes for log messages.
Closed-loop time-tracking clocks and tracking control.
IPv4 address is a 32-bit unsigned integer.
u32 value
Raw access to the underlying representation.
u16 value
Raw access to the underlying representation.
Multipurpose filter for matching fields in network packets.
Timestamps and metadata for a two-way time-transfer handshake.
satcat5::ptp::Time t1
Timestamp T1 (A to B / Tx)
satcat5::ptp::Time t2
Timestamp T2 (A to B / Rx)
satcat5::ptp::Time t4
Timestamp T4 (B to A / Rx)
satcat5::ptp::Time t3
Timestamp T3 (B to A / Tx)
Miscellaneous mathematical utility functions.