SZSPTP ez430-RF2480 1.0

ZigBee Sensor Network with synchronized time and time-stamped measurements.
ptp_messages.c
Go to the documentation of this file.
1 /*
2  * ptp_messages.c
3  *
4  * Date: 19/06/2014
5  * Author: Fernando Biazi Nascimento
6  * Copyright © 2014 Fernando Biazi Nascimento. All rights reserved.
7  *
8  * License of use and copy on file license.txt
9  *
10  */
11 
23 /*
24  * ======== Standard MSP430 includes ========
25  */
26 #include <msp430.h>
27 
28 /*
29  * ======== Includes ========
30  */
31 #include "ptp_messages.h"
32 #include "ptp_util.h"
33 #include "ptp_cfg.h"
34 #include "ptp.h"
35 #include "ptp_const.h"
36 #include "clock.h"
37 
38 /*
39  * ======== Constants ========
40  */
41 
42 /*
43  * ======== Macros ========
44  */
45 
46 /*
47  * ======== Types ========
48  */
49 
50 /*
51  * ======== Global Variables ========
52  */
53 
54 /*
55  * ======== Local Variables ========
56  */
57 
88 
89 /*
90  * ======== Local Functions ========
91  */
92 
93 /*
94  * ================
95  */
96 
111 void ptp_MsgHeaderSnd(ptp_uinteger16 sourcePortNumber, ptp_msgType msgType,
112  ptp_uinteger16 messageLength, ptp_uinteger8 domainNumber,
113  ptp_boolean unicast, ptp_integer64 correctionField,
114  ptp_uinteger16 sequenceId) {
115  ptp_uinteger16 uv16;
116  ptp_integer8 v8;
117  ptp_uinteger8 portIndex;
118 
119  if ((sourcePortNumber == 0xFFFF) || (!sourcePortNumber))
120  portIndex = 0;
121  else
122  portIndex = sourcePortNumber - 1;
123 
124  // Comments are Header Field (number of Octets) session on the standard.
125 
126  ptp_sndUInt8(PTP_MSG_FIELDTRANSPORTSPECIFICVALUE | msgType); // transportSpecific + messageType (.5 + .5 = 1) 13.3.2.1 + 13.3.2.2
127  ptp_sndUInt8(ptpClock.portDS[portIndex].versionNumber); // reserved + versionPTP (.5 + .5 = 1) 13.3.2.3
128  ptp_sndUInt16(messageLength); // messageLength (2) 13.3.2.4
129  // To add support to P2P transparent clocks, domainNumber must have the value defined in 11.4.3
130  ptp_sndUInt8(domainNumber); // domainNumber (1) 13.3.2.5
131  ptp_sndUInt8(0x00); // reserved (1)
132 
133  // flagField (2) 13.3.2.6 :
134  // 0: No alternative masters
135  uv16 = 0;
136  if ((msgType == PTP_MSGTYPE_SYNC) || (msgType == PTP_MSGTYPE_PDELAY_RESP))
137  uv16 |= ptpClock.defaultDS.twoStepFlag << 1;
138  uv16 |= (unicast != 0) << 2;
139  if (msgType == PTP_MSGTYPE_ANNOUNCE)
140  uv16 |= (ptpClock.timePropertiesDS.leap61 << 8)
141  | (ptpClock.timePropertiesDS.leap61 << 9)
142  | (ptpClock.timePropertiesDS.currentUtcOffsetValid << 10)
143  | (ptpClock.timePropertiesDS.ptpTimescale << 11)
144  | (ptpClock.timePropertiesDS.timeTraceable << 12)
145  | (ptpClock.timePropertiesDS.frequencyTraceable << 13);
146  ptp_sndUInt16(uv16);
147  // end - flagField (2) 13.3.2.6
148 
149  ptp_sndInt64(&correctionField); // correctionField (8) 13.3.2.7
150  ptp_snd(4, PTP_ZEROSEQ64); // reserved (4)
151  ptp_snd(8, *ptpClock.defaultDS.clockIdentity); // sourcePortIdentity (10) 13.3.2.8
152  ptp_sndUInt16(sourcePortNumber);
153  ptp_sndUInt16(sequenceId); // sequenceId (2) 13.3.2.9
154 
155  // controlField (1) 13.3.2.10:
156  switch (msgType) {
157  case PTP_MSGTYPE_SYNC:
158  v8 = 0;
159  break;
161  v8 = 1;
162  break;
164  v8 = 2;
165  break;
167  v8 = 3;
168  break;
170  v8 = 4;
171  break;
172  default:
173  v8 = 5;
174  }
175  ptp_sndUInt8(v8);
176  // end - controlField (1) 13.3.2.10
177 
178  // logMessageInterval (1) 13.3.2.11:
179  switch (msgType) {
181  v8 = ptpClock.portDS[portIndex].logAnnounceInterval;
182  break;
183  case PTP_MSGTYPE_SYNC:
185  if (unicast)
186  v8 = 0x7F;
187  else
188  v8 = ptpClock.portDS[portIndex].logAnnounceInterval;
189  break;
191  if (unicast)
192  v8 = 0x7F;
193  else
194  v8 = ptpClock.portDS[portIndex].logMinDelayReqInterval;
195  break;
196  default:
197  v8 = 0x7F;
198  }
199  ptp_sndUInt8(v8);
200  // end - logMessageInterval (1) 13.3.2.11
201 }
202 
203 // Not useful right now, but left for possible future use
205 // *
206 // * @brief .
207 // *
208 // * @param[in] pBuf Pointer to the data to parse
209 // */
210 //void ptp_MsgHeaderRcv(void *pBuf) {
211 //}
212 
213 // Not useful right now, but left for possible future use
215 // * @brief Zero suffix
216 // *
217 // * This function adds a sequence of zeros at the end of the message.
218 // *
219 // * @param[in] size Size of suffix to add
220 // */
221 //void ptp_MsgSuffixZeroSnd(ptp_uinteger8 size) {
222 //}
223 
224 // Not useful right now, but left for possible future use
226 // *
227 // * @brief .
228 // *
229 // * @param[in] pBuf Pointer to the data to parse
230 // */
231 //void ptp_MsgSuffixZeroRcv(void *pBuf) {
232 //}
233 
241 }
242 
252 }
253 
261 }
262 
272 }
273 
285 
286  if (ptp_startFrame(nwk_getNeighborAddress(portNumber), 54)) {
287  portNumber--; // portIndex from here
288  ptp_sequencePDelayReqId[portNumber]++;
289  // header
290  ptp_getCurrentTime(&(ptp_P2Pt1));
291  ptp_MsgHeaderSnd(portNumber + 1, PTP_MSGTYPE_PDELAY_REQ, 54, 0,
292  PTP_FALSE, 0, ptp_sequencePDelayReqId[portNumber]);
293  ptp_sndUInt48sc(&(ptp_P2Pt1.secondsField));
294  ptp_sndUInt32(&(ptp_P2Pt1.nanoSecondsField));
295  ptp_snd(8, PTP_ZEROSEQ64); // 10 bytes reserved
297  ptp_endFrame();
298  return 1;
299  }
300  return 0;
301 }
302 
314  ptp_uinteger8 portNumber) {
315  PTP_TimeStamp t1;
316 
317  // If message is from master and there is a registered ptp_meanPathDelay, synchronize the time
318  portNumber--; // portIndex from here
319  if (ptp_MustAdjustAtPDelayReq && ptp_meanPathDelay[portNumber]
320  && (((ptp_uinteger32) (ptp_meanPathDelay[portNumber] >> 16))
321  < 1000000000u)
322  && (ptpClock.parentDS.parentPortIdentity.clockIdentity
323  == &(ptp_foreignMaster[portNumber][0].clockIdentity))) {
324  ptp_MustAdjustAtPDelayReq = PTP_FALSE;
325  ptp_rcvUInt48sc(&(pBuf[34]), &(t1.secondsField));
326  t1.nanoSecondsField = ptp_rcvUInt32(&(pBuf[40]));
327 
328  ptp_adjTime(&t1, t2, portNumber);
329  }
330 
331  // if there isn't space on the queue, ignore
334  && (ptp_P2PDelayReqQueueRead == 0)))
335  return;
336 
337  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueWrite].localPortNumber =
338  portNumber + 1;
339  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueWrite].t2.secondsField.secondsLow =
340  t2->secondsField.secondsLow;
341  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueWrite].t2.secondsField.secondsHigh =
342  t2->secondsField.secondsHigh;
343  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueWrite].t2.nanoSecondsField =
344  t2->nanoSecondsField;
345  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueWrite].sequenceId = ptp_rcvUInt16(
346  &(pBuf[30]));
347  ptp_rcvOctets(8, &(pBuf[20]),
348  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueWrite].clockIdentity);
349  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueWrite].domain = ptp_rcvUInt16(
350  &(pBuf[4]));
351  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueWrite].correctionField =
352  ptp_rcvInt64(&(pBuf[8]));
353 
357  }
358 }
359 
368  }
369 }
370 
380  PTP_TimeStamp t3;
381 
382  if (ptp_startFrame(
384  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueRead].localPortNumber),
385  54)) {
386  ptp_getCurrentTime(&t3);
388  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueRead].localPortNumber,
390  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueRead].domain,
391  PTP_FALSE,
392  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueRead].correctionField
393  + ptp_timeDiff(
394  &(ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueRead].t2),
395  &t3),
396  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueRead].sequenceId);
397  ptp_sndUInt48sc(&(t3.secondsField));
398  ptp_sndUInt32(&(t3.nanoSecondsField));
399  ptp_snd(8,
400  &(ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueRead].clockIdentity));
403  ptp_P2PPDelayReqQueue[ptp_P2PDelayReqQueueRead].localPortNumber));
404  ptp_endFrame();
405 
409  }
410  return 1;
411  }
412  return 0;
413 }
414 
426  ptp_uinteger8 portNumber) {
427  PTP_TimeStamp t3;
428 
429  // test for 2 step flag (13.3.1, 13.3.2.6)
430  if (ptp_rcvUInt16(&(pBuf[6])) & 0x0002)
431  ; // no support for 2 step clock
432  else {
433  portNumber--; // portIndex from here
434  // if doesn't match last sequenceId, ignore
435  if (ptp_rcvUInt16(&(pBuf[30])) != ptp_sequencePDelayReqId[portNumber])
436  return;
437  ptp_meanPathDelay[portNumber] = ptp_timeDiff(&ptp_P2Pt1, t4);
438  ptp_meanPathDelay[portNumber] -= (ptp_rcvInt64(&(pBuf[8])));
439  ptp_meanPathDelay[portNumber] >>= 1;
440 
441  // If received message have a timestamp, use it to adjust the clock,
442  // else request the adjust to be done at next PdelayReq
443  ptp_rcvUInt48sc(&(pBuf[34]), &(t3.secondsField));
444  t3.nanoSecondsField = ptp_rcvUInt32(&(pBuf[40]));
445  if ((t3.secondsField.secondsLow == 0) && (t3.nanoSecondsField == 0)) {
446  // there no timestamp, adjust the clock at PdelayReq
447  ptp_MustAdjustAtPDelayReq = PTP_TRUE;
448  } else {
449  // there is a timestamp, adjust the clock here
450  if ((((ptp_uinteger32) (ptp_meanPathDelay[portNumber] >> 16))
451  < 1000000000u)
452  && (ptpClock.parentDS.parentPortIdentity.clockIdentity
453  == &(ptp_foreignMaster[portNumber][0].clockIdentity))) {
454  ptp_adjTime(&t3, t4, portNumber);
455  }
456  }
457  }
458 }
459 
470  static ptp_uinteger16 sequenceId = 0;
471  PTP_TimeStamp ts;
472 
473  if (ptp_startFrame(0xFFFF, 64)) {
474  // header
475  // The portNumber 0xFFFF indicates "all ports" for management and signaling messages.
476  // This is not in the standard.
477  ptp_MsgHeaderSnd(0xFFFF, PTP_MSGTYPE_ANNOUNCE, 64, 0, PTP_FALSE, 0,
478  sequenceId);
479 
480  // originTimeStamp 10:
481  ptp_getCurrentTime(&ts);
482  ptp_sndUInt48sc(&(ts.secondsField));
483  ptp_sndUInt32(&(ts.nanoSecondsField));
484  // originTimeStamp 10
485 
486  ptp_sndUInt16(ptpClock.timePropertiesDS.currentUtcOffset); // currentUtcOffset 2
487  ptp_sndUInt8(0); // reserved 1
488  ptp_sndUInt8(ptpClock.parentDS.grandMasterPriority1); // grandmasterPriority1 1
489 
490  // grandmasterClockQuality 4:
491  ptp_sndUInt8(ptpClock.parentDS.grandMasterclockQuality.clockClass);
492  ptp_sndUInt8(ptpClock.parentDS.grandMasterclockQuality.clockAccuracy);
494  ptpClock.parentDS.grandMasterclockQuality.offsetScaledLogVariance);
495  // grandmasterClockQuality 4
496 
497  ptp_sndUInt8(ptpClock.parentDS.grandMasterPriority2); // grandmasterPriority2 1
498  ptp_snd(8, ptpClock.parentDS.grandMasterIdentity); // grandmasterIdentity 8
499  ptp_sndUInt16(ptpClock.currentDS.stepsRemoved); // stepsRemoved 2
500  ptp_sndUInt8(ptpClock.timePropertiesDS.timeSource); // timeSource 1
501 
502  // Message is send in broadcast
503  ptp_endFrame();
504  sequenceId++;
505  return 1;
506  }
507  return 0;
508 }
509 
519 void ptp_MsgAnnounceRcv(ptp_octet *pBuf, ptp_uinteger8 portNumber) {
520 
521  //Check state of the port
522  if ((ptpClock.portDS[0].portState == PTP_PS_INITIALIZING)
523  || (ptpClock.portDS[0].portState == PTP_PS_DISABLED))
524  return;
525  if (ptpClock.portDS[0].portState == PTP_PS_FAULTY)
526  return;
527 
528  // store foreign master or update if its known
529  ptp_storeForeignMaster(pBuf, portNumber);
530 
531 }
532 
540 }
541 
551 }
552 
560 }
561 
571 }
572 
580 }
581 
591 }
592 
600 }
601 
611 }
612 
620 }
621 
631 }
632 
PTP messages interface.
unsigned char ptp_boolean
Definition: ptp_types.h:68
ptp_msgType
PTP_MSGTYPE.
Definition: ptp_messages.h:59
ptp_uinteger8 ptp_sndInt64(ptp_integer64 *p)
Send 64 bits integer.
Definition: ptp_util.c:1017
ptp_uinteger8 ptp_startFrame(ptp_uinteger16 destination, ptp_uinteger8 len)
Start Frame.
Definition: ptp_util.c:889
ptp_uinteger8 ptp_sndUInt32(ptp_uinteger32 *p)
Send unsigned 32 bits integer.
Definition: ptp_util.c:958
ptp_uinteger8 ptp_MsgPdelayRespSnd()
Send Pdelay_Resp message.
Definition: ptp_messages.c:379
ptp_uinteger8 ptp_snd(ptp_uinteger8 len, void *pBuf)
Send data.
Definition: ptp_util.c:906
ptp_uinteger8 ptp_sndUInt16(ptp_uinteger16 v)
Send unsigned 16 bits integer.
Definition: ptp_util.c:944
ptp_uinteger8 ptp_MsgAnnounceSnd()
Send Announce message.
Definition: ptp_messages.c:469
UInt8 nwk_getNeighborForeignPort(UInt8 portNumber)
Get neighbor foreign port.
Definition: nwk.c:1562
void ptp_rcvOctets(ptp_uinteger8 len, ptp_octet *pBuf, ptp_octet *dest)
Receive octets.
Definition: ptp_util.c:1162
ptp_uinteger8 ptp_sndUInt8(ptp_uinteger8 v)
Send unsigned 8 bits integer.
Definition: ptp_util.c:930
ptp_boolean ptp_MustAdjustAtPDelayReq
Definition: ptp_messages.c:87
void ptp_MsgDelayRespSnd()
Send Delay_Resp message.
Definition: ptp_messages.c:559
Pdelay_Req message.
Definition: ptp_messages.h:72
void ptp_MsgPdelayReqRcv(ptp_octet *pBuf, PTP_TimeStamp *t2, ptp_uinteger8 portNumber)
Receive PDelay_Req message.
Definition: ptp_messages.c:313
void ptp_MsgAnnounceRcv(ptp_octet *pBuf, ptp_uinteger8 portNumber)
Receive Announce message.
Definition: ptp_messages.c:519
void ptp_adjTime(PTP_TimeStamp *t1, PTP_TimeStamp *t2, ptp_uinteger8 portIndex)
Adjust the clock.
Definition: ptp_util.c:118
long long ptp_integer64
Definition: ptp_types.h:120
Follow_Up message.
Definition: ptp_messages.h:81
Delay_Resp message.
Definition: ptp_messages.h:85
Clock interface.
void ptp_MsgPdelayRespFollowUpSnd()
Send Pdelay_Resp_Follow_Up message.
Definition: ptp_messages.c:579
unsigned long ptp_uinteger32
Definition: ptp_types.h:110
ptp_uinteger16 ptp_sequencePDelayReqId[PTP_NUMBERPORTS]
Definition: ptp_messages.c:69
PTP interface.
void ptp_MsgSyncRcv(ptp_octet *pBuf)
Receive Sync message.
Definition: ptp_messages.c:251
void ptp_MsgDelayReqRcv(ptp_octet *pBuf)
Receive Delay_Req message.
Definition: ptp_messages.c:271
void ptp_MsgPdelayRespFollowUpRcv(ptp_octet *pBuf)
Receive Pdelay_Resp_Follow_Up message.
Definition: ptp_messages.c:590
Announce message.
Definition: ptp_messages.h:93
PTP functions specific to the implementation.
PTP_P2PPDelayReqDS ptp_P2PPDelayReqQueue[PTP_P2PPDELAYREQQUEUESIZE]
Definition: ptp_messages.c:75
void ptp_MsgSyncSnd()
Definition: ptp_messages.c:240
ptp_uinteger8 ptp_P2PDelayReqQueueWrite
Definition: ptp_messages.c:79
Management message.
Definition: ptp_messages.h:101
void ptp_MsgDelayRespRcv(ptp_octet *pBuf)
Receive Delay_Resp message.
Definition: ptp_messages.c:570
signed char ptp_integer8
Definition: ptp_types.h:85
void ptp_storeForeignMaster(ptp_octet *pBuf, ptp_uinteger8 portNumber)
Store foreign master.
Definition: ptp_util.c:833
void ptp_MsgHeaderSnd(ptp_uinteger16 sourcePortNumber, ptp_msgType msgType, ptp_uinteger16 messageLength, ptp_uinteger8 domainNumber, ptp_boolean unicast, ptp_integer64 correctionField, ptp_uinteger16 sequenceId)
Send message header.
Definition: ptp_messages.c:111
#define PTP_P2PPDELAYREQQUEUESIZE
Definition: ptp_cfg.h:105
#define PTP_MSG_FIELDTRANSPORTSPECIFICVALUE
Definition: ptp_cfg.h:137
Sync message.
Definition: ptp_messages.h:64
#define PTP_NUMBERPORTS
Definition: ptp_cfg.h:100
unsigned char ptp_uinteger8
Definition: ptp_types.h:90
void ptp_MsgFollowUpRcv(ptp_octet *pBuf)
Receive Follow_Up message.
Definition: ptp_messages.c:550
PTP_TimeStamp ptp_P2Pt1
Definition: ptp_messages.c:63
void ptp_MsgManagementRcv(ptp_octet *pBuf)
Receive Management message.
Definition: ptp_messages.c:610
ptp_integer64 ptp_timeDiff(PTP_TimeStamp *t1, PTP_TimeStamp *t2)
Time difference.
Definition: ptp_util.c:187
void ptp_MsgPdelayReqCheck()
Check for PDelay_Req message.
Definition: ptp_messages.c:365
void ptp_MsgManagementSnd()
Send Management message.
Definition: ptp_messages.c:599
void ptp_rcvUInt48sc(ptp_octet *pBuf, PTP_SecondsCount *p)
Receive seconds count value.
Definition: ptp_util.c:1098
void ptp_getCurrentTime(PTP_TimeStamp *dest)
Get cuttent time.
Definition: ptp_util.c:104
ptp_uinteger8 ptp_MsgPdelayReqSnd(ptp_uinteger8 portNumber)
Send PDelay_Req message.
Definition: ptp_messages.c:284
char ptp_octet
Definition: ptp_types.h:137
PTP constants that should not need to be modified.
void ptp_MsgSignalingRcv(ptp_octet *pBuf)
Receive Signaling message.
Definition: ptp_messages.c:630
ptp_integer64 ptp_rcvInt64(ptp_octet *pBuf)
Receive 64 bits integer.
Definition: ptp_util.c:1138
ptp_uinteger8 ptp_sndUInt48sc(PTP_SecondsCount *p)
Send a seconds count value.
Definition: ptp_util.c:986
Pdelay_Resp message.
Definition: ptp_messages.h:76
void ptp_MsgDelayReqSnd()
Send Delay_Req message.
Definition: ptp_messages.c:260
PTP configuration values to compile.
UInt16 nwk_getNeighborAddress(UInt8 portNumber)
Get neighbor address.
Definition: nwk.c:1578
void ptp_MsgFollowUpSnd()
Send Follow_Up message.
Definition: ptp_messages.c:539
Delay_Req message.
Definition: ptp_messages.h:68
void ptp_MsgPdelayRespRcv(ptp_octet *pBuf, PTP_TimeStamp *t4, ptp_uinteger8 portNumber)
Receive Pdelay_Resp message.
Definition: ptp_messages.c:425
#define PTP_ZEROSEQ64
Definition: ptp_const.h:58
ptp_uinteger16 ptp_rcvUInt16(ptp_octet *pBuf)
Receive unsigned 16 bits integer.
Definition: ptp_util.c:1043
void ptp_MsgSignalingSnd()
Send Signaling message.
Definition: ptp_messages.c:619
unsigned short ptp_uinteger16
Definition: ptp_types.h:100
ptp_uinteger8 ptp_P2PDelayReqQueueRead
Definition: ptp_messages.c:83
ptp_uinteger32 ptp_rcvUInt32(ptp_octet *pBuf)
Receive unsigned 32 bits integer.
Definition: ptp_util.c:1059
void ptp_endFrame()
End frame.
Definition: ptp_util.c:916