-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathntp_server.cpp
More file actions
169 lines (130 loc) · 5.4 KB
/
Copy pathntp_server.cpp
File metadata and controls
169 lines (130 loc) · 5.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#include "Arduino.h"
#include "ntp_server.h"
#include <lwip/def.h>
#define NTP_TIMESTAMP_DELTA 2208988800ull
//this will try to get ms since PPS
typedef struct{
uint8_t mode:3; // mode. Three bits. Client will pick mode 3 for client.
uint8_t vn:3; // vn. Three bits. Version number of the protocol.
uint8_t li:2; // li. Two bits. Leap indicator.
}ntp_flags_t;
typedef union {
uint32_t data;
uint8_t byte[4];
char c_str[4];
} refID_t;
typedef struct
{
ntp_flags_t flags;
uint8_t stratum; // Eight bits. Stratum level of the local clock.
uint8_t poll; // Eight bits. Maximum interval between successive messages.
int8_t precision; // Eight bits signed. Precision of the local clock.
uint32_t rootDelay; // 32 bits. Total round trip delay time.
uint32_t rootDispersion; // 32 bits. Max error allowed from primary clock source.
refID_t refId; // 32 bits. Reference clock identifier.
uint32_t refTm_s; // 32 bits. Reference time-stamp seconds.
uint32_t refTm_f; // 32 bits. Reference time-stamp fraction of a second.
uint32_t origTm_s; // 32 bits. Originate time-stamp seconds.
uint32_t origTm_f; // 32 bits. Originate time-stamp fraction of a second.
uint32_t rxTm_s; // 32 bits. Received time-stamp seconds.
uint32_t rxTm_f; // 32 bits. Received time-stamp fraction of a second.
uint32_t txTm_s; // 32 bits and the most important field the client cares about. Transmit time-stamp seconds.
uint32_t txTm_f; // 32 bits. Transmit time-stamp fraction of a second.
} ntp_packet_t;
uint8_t __calloverhead = 0;
AsyncUDP udp;
uint32_t(*fnc_read_utc)(void) = NULL;
uint32_t(*fnc_read_subsecond)(void) = NULL;
NTP_Server::NTP_Server( ){
}
NTP_Server::~NTP_Server(){
}
uint8_t DeterminePrecision( void ){
/* We need to compute the call overhead */
uint32_t utc_read=0;
uint32_t mil_read=0;
if(fnc_read_utc!=NULL){
uint32_t start = micros();
for(uint32_t i=0;i<1024;i++){
utc_read=fnc_read_utc();
mil_read=fnc_read_subsecond();
}
uint32_t end=micros();
double runtime = ( ((double)(end)-(double)(start) ) / ( (double)(1000000.0) * (double)(1024) ) )+((double)(1)) ; // One second as we don't keep track on the fractions
__calloverhead = log2(runtime);
} else {
/* this is a bad one ! */
configASSERT( fnc_read_utc != NULL );
}
return 0;
}
bool NTP_Server::begin(uint16_t port , uint32_t(*fnc_getutc_time)(void) , uint32_t(*fnc_get_subsecond)(void) ){
bool started=false;
fnc_read_utc = fnc_getutc_time;
fnc_read_subsecond = fnc_get_subsecond;
if(udp.listen(port)) {
started=true;
udp.onPacket(NTP_Server::processUDPPacket);
/* udp.onPacket([](AsyncUDPPacket packet) {
Serial.print("UDP Packet Type: ");
Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast");
Serial.print(", From: ");
Serial.print(packet.remoteIP());
Serial.print(":");
Serial.print(packet.remotePort());
Serial.print(", To: ");
Serial.print(packet.localIP());
Serial.print(":");
Serial.print(packet.localPort());
Serial.print(", Length: ");
Serial.print(packet.length());
Serial.print(", Data: ");
Serial.write(packet.data(), packet.length());
Serial.println();
}); */
}
return started;
}
/* static function */
void NTP_Server::processUDPPacket(AsyncUDPPacket& packet) {
uint32_t processing_start = 0;
uint32_t millisec = 0;
ntp_packet_t ntp_req;
if(NULL != fnc_read_subsecond){
millisec = fnc_read_subsecond();
}
if(fnc_read_utc!=NULL){
processing_start=fnc_read_utc()+NTP_TIMESTAMP_DELTA;
} else {
return;
}
if(packet.length() != sizeof(ntp_packet_t)){
/* this is not what we want ! */
return;
}
memcpy(&ntp_req, packet.data(), sizeof(ntp_packet_t));
ntp_req.flags.li = 0; //NONE
ntp_req.flags.vn = 4; // NTP Version 4
ntp_req.flags.mode = 4; // Server
ntp_req.stratum = 1;
// We don't touch ntp_req.poll
ntp_req.precision = __calloverhead;
ntp_req.rootDelay=1;
ntp_req.rootDispersion=1;
strncpy(ntp_req.refId.c_str ,"PPS", sizeof(ntp_req.refId.c_str) );
// Set to network byte order
ntp_req.rootDelay = htonl( ntp_req.rootDelay );
ntp_req.rootDispersion = htonl( ntp_req.rootDispersion );
ntp_req.refId.data = ntohl( ntp_req.refId.data );
ntp_req.origTm_s = ntp_req.txTm_s;
ntp_req.origTm_f = ntp_req.txTm_f;
ntp_req.rxTm_s = htonl(processing_start);
ntp_req.rxTm_f = htonl(millisec * 4294967);
ntp_req.refTm_s = ntp_req.rxTm_s;
ntp_req.refTm_f = ntp_req.rxTm_f;
/* UNIX Start is 1.1.1970 and GPS Start is 1.1.1900 */
ntp_req.txTm_s = fnc_read_utc()+NTP_TIMESTAMP_DELTA; // We need to add 70 Years
ntp_req.txTm_s = htonl(ntp_req.txTm_s);
ntp_req.txTm_f = htonl(millisec * 4294967);
packet.write((uint8_t*)&ntp_req, sizeof(ntp_packet_t));
}