3131#define FOLLOW_UP_LEN 44
3232#define DELAY_REQ_LEN 44
3333#define DELAY_RESP_LEN 54
34+ #define ANNOUNCE_LEN 64
3435
3536// --- Structs ---
3637typedef struct __attribute__((packed )) {
@@ -70,6 +71,19 @@ typedef struct __attribute__((packed)) {
7071 uint8_t requestingPortIdentity [10 ];
7172} PTPDelayResp ;
7273
74+ typedef struct __attribute__((packed )) {
75+ PTPHeader header ;
76+ uint16_t originTimestamp [5 ];
77+ int16_t currentUtcOffset ;
78+ uint8_t reserved ;
79+ uint8_t grandmasterPriority1 ;
80+ uint8_t grandmasterClockQuality [4 ];
81+ uint8_t grandmasterPriority2 ;
82+ uint8_t grandmasterIdentity [8 ];
83+ uint16_t stepsRemoved ;
84+ uint8_t timeSource ;
85+ } PTPAnnounce ;
86+
7387// --- Globals ---
7488int sock_evt , sock_gen ;
7589struct sockaddr_in mcast_addr_evt , mcast_addr_gen ;
@@ -179,6 +193,9 @@ void run_master() {
179193 printf ("Starting PTP Master on %s...\n" , interface_ip );
180194
181195 while (1 ) {
196+ struct timespec loop_start ;
197+ clock_gettime (CLOCK_MONOTONIC , & loop_start );
198+
182199 struct timespec ts ;
183200 get_time (& ts );
184201 uint16_t seq = sequence_id ++ ;
@@ -200,37 +217,78 @@ void run_master() {
200217 sendto (sock_gen , & follow , sizeof (follow ), 0 , (struct sockaddr * )& mcast_addr_gen , sizeof (mcast_addr_gen ));
201218 printf ("[Primary] Sent FollowUp Seq=%d Time=%ld.%09ld\n" , seq , ts .tv_sec , ts .tv_nsec );
202219
203- // Check for DelayReq (Non-blocking check would be better, but simple select here)
204- fd_set fds ;
205- struct timeval tv = {0 , 900000 }; // Wait remainder of second
206- FD_ZERO (& fds );
207- FD_SET (sock_evt , & fds );
220+ // 3. Send Announce (General Port) - Every second (logMessageInterval = 0)
221+ PTPAnnounce announce ;
222+ init_header (& announce .header , MSG_ANNOUNCE , ANNOUNCE_LEN , seq , 0x0000 );
223+ announce .header .logMessageInterval = 0 ; // 1 second
208224
209- if (select (sock_evt + 1 , & fds , NULL , NULL , & tv ) > 0 ) {
210- uint8_t buf [1024 ];
211- struct sockaddr_in src_addr ;
212- socklen_t addrlen = sizeof (src_addr );
213- int len = recvfrom (sock_evt , buf , sizeof (buf ), 0 , (struct sockaddr * )& src_addr , & addrlen );
225+ memset (announce .originTimestamp , 0 , sizeof (announce .originTimestamp ));
226+ timespec_to_ptp (& ts , announce .originTimestamp );
227+
228+ announce .currentUtcOffset = htons (37 ); // Current UTC offset
229+ announce .reserved = 0 ;
230+ announce .grandmasterPriority1 = 128 ;
231+ announce .grandmasterClockQuality [0 ] = 248 ; // Class
232+ announce .grandmasterClockQuality [1 ] = 0xFE ; // Accuracy
233+ announce .grandmasterClockQuality [2 ] = 0xFF ; // Variance
234+ announce .grandmasterClockQuality [3 ] = 0xFF ; // Variance
235+ announce .grandmasterPriority2 = 128 ;
236+ memcpy (announce .grandmasterIdentity , my_clock_id , 8 );
237+ announce .stepsRemoved = 0 ;
238+ announce .timeSource = 0xA0 ; // Internal Oscillator
239+
240+ sendto (sock_gen , & announce , sizeof (announce ), 0 , (struct sockaddr * )& mcast_addr_gen , sizeof (mcast_addr_gen ));
241+ printf ("[Primary] Sent Announce Seq=%d\n" , seq );
242+
243+ // Handle DelayReqs for the rest of the second
244+ while (1 ) {
245+ struct timespec now ;
246+ clock_gettime (CLOCK_MONOTONIC , & now );
214247
215- if (len >= HEADER_LEN ) {
216- PTPHeader * h = (PTPHeader * )buf ;
217- if ((h -> transportSpecific_msgType & 0x0F ) == MSG_DELAY_REQ ) {
218- struct timespec rx_ts ;
219- get_time (& rx_ts );
220- uint16_t req_seq = ntohs (h -> sequenceId );
221- printf ("[Primary] Received DelayReq Seq=%d from %s\n" , req_seq , inet_ntoa (src_addr .sin_addr ));
222-
223- // Send DelayResp
224- PTPDelayResp resp ;
225- init_header (& resp .header , MSG_DELAY_RESP , DELAY_RESP_LEN , req_seq , 0 );
226- timespec_to_ptp (& rx_ts , resp .receiveTimestamp );
227- memcpy (resp .requestingPortIdentity , h -> clockIdentity , 8 );
228- memcpy (resp .requestingPortIdentity + 8 , & h -> sourcePortId , 2 ); // Actually portId is 2 bytes
229-
230- // Send unicast back to requester
231- sendto (sock_gen , & resp , sizeof (resp ), 0 , (struct sockaddr * )& src_addr , addrlen );
232- printf ("[Primary] Sent DelayResp Seq=%d\n" , req_seq );
248+ long long elapsed_us = (now .tv_sec - loop_start .tv_sec ) * 1000000LL +
249+ (now .tv_nsec - loop_start .tv_nsec ) / 1000LL ;
250+ long long remaining_us = 1000000LL - elapsed_us ; // 1 second interval
251+
252+ if (remaining_us <= 0 ) break ;
253+
254+ struct timeval tv ;
255+ tv .tv_sec = remaining_us / 1000000 ;
256+ tv .tv_usec = remaining_us % 1000000 ;
257+
258+ fd_set fds ;
259+ FD_ZERO (& fds );
260+ FD_SET (sock_evt , & fds );
261+
262+ int ret = select (sock_evt + 1 , & fds , NULL , NULL , & tv );
263+
264+ if (ret > 0 ) {
265+ uint8_t buf [1024 ];
266+ struct sockaddr_in src_addr ;
267+ socklen_t addrlen = sizeof (src_addr );
268+ int len = recvfrom (sock_evt , buf , sizeof (buf ), 0 , (struct sockaddr * )& src_addr , & addrlen );
269+
270+ if (len >= HEADER_LEN ) {
271+ PTPHeader * h = (PTPHeader * )buf ;
272+ if ((h -> transportSpecific_msgType & 0x0F ) == MSG_DELAY_REQ ) {
273+ struct timespec rx_ts ;
274+ get_time (& rx_ts );
275+ uint16_t req_seq = ntohs (h -> sequenceId );
276+ printf ("[Primary] Received DelayReq Seq=%d from %s\n" , req_seq , inet_ntoa (src_addr .sin_addr ));
277+
278+ // Send DelayResp
279+ PTPDelayResp resp ;
280+ init_header (& resp .header , MSG_DELAY_RESP , DELAY_RESP_LEN , req_seq , 0 );
281+ timespec_to_ptp (& rx_ts , resp .receiveTimestamp );
282+ memcpy (resp .requestingPortIdentity , h -> clockIdentity , 8 );
283+ memcpy (resp .requestingPortIdentity + 8 , & h -> sourcePortId , 2 ); // Actually portId is 2 bytes
284+
285+ // Send unicast back to requester
286+ sendto (sock_gen , & resp , sizeof (resp ), 0 , (struct sockaddr * )& src_addr , addrlen );
287+ printf ("[Primary] Sent DelayResp Seq=%d\n" , req_seq );
288+ }
233289 }
290+ } else {
291+ break ; // Timeout
234292 }
235293 }
236294 }
0 commit comments