SZSPTP ez430-RF2480 1.0

ZigBee Sensor Network with synchronized time and time-stamped measurements.
ptp_util.c
Go to the documentation of this file.
1 /*
2  * ptp_util.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 
21 #include <stdlib.h>
22 
23 /*
24  * ======== Includes ========
25  */
26 
27 #include "ptp_util.h"
28 #include "ptp.h"
29 #include "ptp_const.h"
30 #include "ptp_cfg.h"
31 #include "ptp_types.h"
32 #include "ptp_messages.h"
33 #include "clock.h"
34 #include "nwk.h"
35 
36 /*
37  * ======== Constants ========
38  */
39 
40 /*
41  * ======== Macros ========
42  */
43 
44 /*
45  * ======== Types ========
46  */
47 
48 /*
49  * ======== Global Variables ========
50  */
51 
52 /*
53  * ======== Local Variables ========
54  */
55 
64 
65 /*
66  * ======== Local Functions ========
67  */
68 
69 void ptp_bmc();
70 void ptp_portUpdateDS();
72 
73 /*
74  * ================
75  */
76 
86 // // old code used to write return value on a variable, It didn't return a pointer
87 // ptp_integer64 tmp;
88 // tmp = PTP_OUI; // Get OUI, 24 bits
89 // tmp <<= 40; // put OUI on place
90 // tmp |= PTP_EXTENSION_IDENTIFIER; // include extension identifier (40 bits)
91 // memcpy(result, &tmp, 8);
93 }
94 
105  clock_getTime((void *) dest);
106 }
107 
119  static ptp_uinteger8 adjustTryAgain = 0;
120  ptp_integer64 offsetFromMaster;
121 
122  // If apparent offset is greater than 30s, just set the clock to the received
123  // time. Moreover, there would be division to adjust the clock above 32s, an
124  // expensive task. Precise adjustments will be done later.
125  offsetFromMaster = t2->secondsField.secondsHigh;
126  offsetFromMaster -= t1->secondsField.secondsHigh;
127  offsetFromMaster <<= 32;
128  offsetFromMaster += t2->secondsField.secondsLow;
129  offsetFromMaster -= t1->secondsField.secondsLow; // offset is seconds
130 
131 // if (t2->secondsField.secondsHigh != t1.secondsField.secondsHigh) {
132 // offsetFromMaster = t2->secondsField.secondsHigh
133 // - t1.secondsField.secondsHigh;
134 // offsetFromMaster <<= 32;
135 // offsetFromMaster += offsetFromMasterLow;
136 // } else {
137 // offsetFromMaster = offsetFromMasterLow;
138 // }
139 
140  if ((offsetFromMaster < -30) || (offsetFromMaster > 30)) {
141  adjustTryAgain = 0; // Next adjust will be done even if apparent offset > 4s.
142  // set time
143  clock_setTime((void *) t1); // Expects PTP_TimeStamp and clock_timeStamp to be bit compatible
144  // get time stamp (t2) again, that will be invalid after setting the clock.
145  ptp_getCurrentTime(t2);
146  } else {
147  // time is within ~30s.
148 
149  // offset is calculated in ns.
150  offsetFromMaster = clock_timeDiff((void*) t1, (void *) t2); // Expects PTP_TimeStamp and clock_timeStamp to be bit compatible
151  // offsetFromMaster doesn't count on ptp_meanPathDelay at this point, to save processing
152 
153  // If offset is larger than 4s, do not adjust the clock
154  // but if it repeat 3 times, adjust it anyway.
155  if (adjustTryAgain
156  && ((offsetFromMaster > 2000000000)
157  || (-offsetFromMaster > 2000000000))) {
158  adjustTryAgain--;
159  ptp_lastAdjust = 0;
160  ptp_getCurrentTime(&ptp_lastAdjustTime);
161  } else {
162  adjustTryAgain = 2;
163  ptp_meanDelayAtLastAdjust = ptp_meanPathDelay[portIndex] >> 16;
164  offsetFromMaster -= ptp_meanDelayAtLastAdjust;
165  // to send to adjust, offset must have inverted signal
166  offsetFromMaster = -offsetFromMaster;
167  clock_adjTime(&offsetFromMaster);
168  ptp_getCurrentTime(&ptp_lastAdjustTime);
169  ptp_lastAdjust = offsetFromMaster;
170  // adjust time stamp t2 to the same offset, as it would become invalid
171  // after adjusting the clock
172  clock_adjTimeValues(&offsetFromMaster, (void *) t2); // Expects PTP_TimeStamp and clock_timeStamp to be bit compatible
173  }
174  }
175 }
176 
188  return clock_timeDiff((void *) t1, (void *) t2) << 16;
189 }
190 
202  ptp_uinteger8 i = 8; // little endian, last byte is most significant, compare it first
203  while (i) {
204  i--;
205  if (A[i] > B[i]) {
206  return 1;
207  } else if (A[i] < B[i]) {
208  return -1;
209  }
210  }
211  return 0;
212 }
213 
225  ptp_uinteger8 portIndex;
226 
228  ptpClock.defaultDS.numberPorts = 1;
229  portIndex = ptpClock.defaultDS.numberPorts;
230  while (portIndex) {
231  portIndex--;
233  ptp_foreignMaster[portIndex][0].clockIdentity);
235  ptp_announce[portIndex].grandMasterIdentity);
236  ptpClock.portDS[portIndex].portState = PTP_PS_LISTENING;
237  }
238 }
239 
249 
250  // run BMC
251  ptp_bmc();
252 
253  // update data sets - all ports
255 
256  // state changes - all ports
258 
259 }
260 
274 void ptp_bmc() {
275  ptp_uinteger8 portNumber;
276  ptp_uinteger8 portIndex;
277  ptp_uinteger8 iEbest;
278  ptp_boolean Dbetter;
279  ptp_boolean byTopology;
280 
281  // Each port "r" compute Erbest. IEC 61588-2009 / IEEE 1588-2008 9.3.2.2 b)
282  // On this program, each port stores only one message.
283 
284  // Choose Ebest from all Erbest. IEC 61588-2009 / IEEE 1588-2008 9.3.2.2 c)
285  iEbest = 0; // if no announces are found, iEbest will remain 0
286  portNumber = ptpClock.defaultDS.numberPorts;
287  while (portNumber) {
288  if (nwk_getNeighborAddress(portNumber) != 0xFFFF)
289  ptp_dataSetComparisonEE(&iEbest, &byTopology,
290  &(ptp_announce[iEbest - 1]),
291  &(ptp_announce[portNumber - 1]), iEbest, portNumber);
292  portNumber--;
293  };
294  if (iEbest != 0)
296  ptp_announce[iEbest - 1u].grandMasterIdentity, PTP_ZEROSEQ64)
297  == 0)
298  iEbest = 0;
299 
300  // state decision algorithm 9.3.3
301  portNumber = ptpClock.defaultDS.numberPorts;
302  while (portNumber) {
303  portIndex = portNumber - 1;
305  ptp_announce[portIndex].grandMasterIdentity, PTP_ZEROSEQ64) == 0)
306  && (ptpClock.portDS[portNumber].portState == PTP_BMC_LISTENING))
308  else {
309  Dbetter = PTP_TRUE;
310  ptp_dataSetComparisonDE(&Dbetter, &ptpClock,
311  &(ptp_announce[portIndex]), portNumber);
312  if (ptpClock.defaultDS.clockQuality.clockClass < 128) {
313  if (Dbetter)
315  else
317  } else {
318  if (Dbetter)
320  else if (portNumber == iEbest)
322  else {
323  ptp_dataSetComparisonEE(&iEbest, &byTopology,
324  &(ptp_announce[iEbest - 1]),
325  &(ptp_announce[portIndex]), iEbest, portNumber);
326  if (byTopology)
328  else
330  }
331  }
332  }
333  portNumber--;
334  }
335 }
336 
345  ptp_uinteger8 portIndex;
346 
347  portIndex = ptpClock.defaultDS.numberPorts;
348  while (portIndex) {
349  portIndex--;
350  if (nwk_getNeighborAddress(portIndex + 1) != 0xFFFF) {
351  switch (ptp_portRecommendedState[portIndex]) {
352  case PTP_BMC_M1:
353  case PTP_BMC_M2:
354  // table 13
355  ptpClock.currentDS.stepsRemoved = 0;
356  ptpClock.currentDS.offsetFromMaster.scalatedNanoseconds = 0;
357  ptpClock.currentDS.meanPathDelay.scalatedNanoseconds = 0;
358  ptpClock.parentDS.parentPortIdentity.clockIdentity =
359  ptpClock.defaultDS.clockIdentity;
360  ptpClock.parentDS.parentPortIdentity.portNumber = 0;
361  ptpClock.parentDS.grandMasterIdentity =
362  ptpClock.defaultDS.clockIdentity;
363  ptpClock.parentDS.grandMasterclockQuality.clockAccuracy =
364  ptpClock.defaultDS.clockQuality.clockAccuracy;
365  ptpClock.parentDS.grandMasterclockQuality.clockClass =
366  ptpClock.defaultDS.clockQuality.clockClass;
367  ptpClock.parentDS.grandMasterclockQuality.offsetScaledLogVariance =
368  ptpClock.defaultDS.clockQuality.offsetScaledLogVariance;
369  ptpClock.parentDS.grandMasterPriority1 =
370  ptpClock.defaultDS.priority1;
371  ptpClock.parentDS.grandMasterPriority2 =
372  ptpClock.defaultDS.priority2;
373  ptpClock.timePropertiesDS.currentUtcOffset =
374  PTP_DESIGNTIME_UTCOFFSET; // 9.3.5, 9.4, 7.2.3
375  ptpClock.timePropertiesDS.currentUtcOffsetValid = PTP_FALSE; // 9.3.5, 9.4
376  ptpClock.timePropertiesDS.leap59 = PTP_FALSE; // 9.3.5, 9.4
377  ptpClock.timePropertiesDS.leap61 = PTP_FALSE; // 9.3.5, 9.4
378  ptpClock.timePropertiesDS.timeTraceable = PTP_FALSE; // 9.3.5, 9.4
379  ptpClock.timePropertiesDS.frequencyTraceable = PTP_FALSE; // 9.3.5, 9.4
380  ptpClock.timePropertiesDS.ptpTimescale = PTP_FALSE; // 9.3.5, 9.4
381  // ptpClock.timePropertiesDS.timeSource = PTP_TS_INTERNAL_OSCILLATOR;
382  // 9.3.5, 9.4, Could be gathered from device time source.
383  // this is set on ptp_clock_initialize, ptp_proccess, ptp_setNetTime, or when state is PTP_BMC_S1
384  portIndex = 0; // to interrupt processing, as all ports will result in this same code being run.
385  break;
386  case PTP_BMC_M3:
387  // table 14
388 
389  break;
390  case PTP_BMC_P1:
391  case PTP_BMC_P2:
392  // table 15
393 
394  break;
395  case PTP_BMC_S1:
396  // table 16
397  ptpClock.currentDS.stepsRemoved =
398  ptp_announce[portIndex].stepsRemoved + 1;
399  ptpClock.parentDS.parentPortIdentity.clockIdentity =
400  &(ptp_foreignMaster[portIndex][0].clockIdentity);
401  ptpClock.parentDS.parentPortIdentity.portNumber =
402  nwk_getNeighborForeignPort(portIndex + 1);
403  ptpClock.parentDS.grandMasterIdentity =
404  &(ptp_announce[portIndex].grandMasterIdentity);
405  ptpClock.parentDS.grandMasterclockQuality.clockAccuracy =
406  ptp_announce[portIndex].grandMasterClockQuality.clockAccuracy;
407  ptpClock.parentDS.grandMasterclockQuality.clockClass =
408  ptp_announce[portIndex].grandMasterClockQuality.clockClass;
409  ptpClock.parentDS.grandMasterclockQuality.offsetScaledLogVariance =
410  ptp_announce[portIndex].grandMasterClockQuality.offsetScaledLogVariance;
411  ptpClock.parentDS.grandMasterPriority1 =
412  ptp_announce[portIndex].grandMasterPriority1;
413  ptpClock.parentDS.grandMasterPriority2 =
414  ptp_announce[portIndex].grandMasterPriority1;
415  ptpClock.timePropertiesDS.currentUtcOffset =
416  ptp_announce[portIndex].currentUtcOffset;
417  ptpClock.timePropertiesDS.currentUtcOffsetValid =
418  ptp_announce[portIndex].currentUtcOffsetValid;
419  ptpClock.timePropertiesDS.leap59 =
420  ptp_announce[portIndex].leap59;
421  ptpClock.timePropertiesDS.leap61 =
422  ptp_announce[portIndex].leap61;
423  ptpClock.timePropertiesDS.timeTraceable =
424  ptp_announce[portIndex].timeTraceable;
425  ptpClock.timePropertiesDS.frequencyTraceable =
426  ptp_announce[portIndex].frequencyTraceable;
427  ptpClock.timePropertiesDS.ptpTimescale =
428  ptp_announce[portIndex].ptpTimescale;
429  ptpClock.timePropertiesDS.timeSource =
430  ptp_announce[portIndex].timeSource;
431  break;
432  default:
433  break;
434  }
435  }
436  }
437 }
438 
446  ptp_uinteger8 i;
447  i = ptpClock.defaultDS.numberPorts;
448  while (i) {
449  i--;
450  switch (ptp_portRecommendedState[i]) {
451  case PTP_BMC_M1:
452  case PTP_BMC_M2:
453  case PTP_BMC_M3:
454  if (ptpClock.portDS[i].portState == PTP_PS_LISTENING
455  || ptpClock.portDS[i].portState == PTP_PS_UNCALIBRATED
456  || ptpClock.portDS[i].portState == PTP_PS_SLAVE
457  || ptpClock.portDS[i].portState == PTP_PS_PASSIVE) {
458  ptpClock.portDS[i].portState = PTP_PS_PRE_MASTER;
459  }
460  break;
461  case PTP_BMC_S1:
462  if (ptpClock.portDS[i].portState == PTP_PS_LISTENING
463  || ptpClock.portDS[i].portState == PTP_PS_UNCALIBRATED
464  || ptpClock.portDS[i].portState == PTP_PS_PRE_MASTER
465  || ptpClock.portDS[i].portState == PTP_PS_MASTER
466  || ptpClock.portDS[i].portState == PTP_PS_PASSIVE) {
467  ptpClock.portDS[i].portState = PTP_PS_UNCALIBRATED;
468  }
469  break;
470  case PTP_BMC_P1:
471  case PTP_BMC_P2:
472  if (ptpClock.portDS[i].portState == PTP_PS_LISTENING
473  || ptpClock.portDS[i].portState == PTP_PS_UNCALIBRATED
474  || ptpClock.portDS[i].portState == PTP_PS_SLAVE
475  || ptpClock.portDS[i].portState == PTP_PS_PRE_MASTER
476  || ptpClock.portDS[i].portState == PTP_PS_MASTER) {
477  ptpClock.portDS[i].portState = PTP_PS_PASSIVE;
478  }
479  break;
480  default:
481  break;
482  }
483  }
484 }
485 
502  ptp_boolean *byTopology, PTP_announceDS *E1, PTP_announceDS *E2,
503  ptp_uinteger8 i1, ptp_uinteger8 i2) {
504  *byTopology = PTP_FALSE;
505 
506  // check for empty
507  if (i1)
508  if (ptp_clockIdentityCompare(E1->grandMasterIdentity, PTP_ZEROSEQ64)
509  == 0)
510  i1 = 0;
511  if (i2)
512  if (ptp_clockIdentityCompare(E2->grandMasterIdentity, PTP_ZEROSEQ64)
513  == 0)
514  i2 = 0;
515  if ((i1 == 0) && (i2 == 0))
516  return 3; // not on standard
517  else if (i1 == 0) {
518  *iBetter = i2;
519  return 0;
520  } else if (i2 == 0) {
521  *iBetter = i1;
522  return 0;
523  }
524 
525  // check for same grand master
526  if (ptp_clockIdentityCompare(E1->grandMasterIdentity,
527  E2->grandMasterIdentity) == 0) {
528  // steps removed
529  if (E1->stepsRemoved > (E2->stepsRemoved + 1)) {
530  *iBetter = i2;
531  return 0;
532  } else if ((E1->stepsRemoved + 1) < E2->stepsRemoved) {
533  *iBetter = i1;
534  return 0;
535  }
536  // E1->stepsRemoved within 1 of E2->stepsRemoved
537  if (E1->stepsRemoved > E2->stepsRemoved) {
538  switch (ptp_clockIdentityCompare(
539  *(ptpClock.defaultDS.clockIdentity),
540  ptp_foreignMaster[i1 - 1u][0].clockIdentity)) {
541  case -1:
542  // if receiver Identity of E1 < sender Identity of E1, E2 is better
543  *iBetter = i2;
544  return 0;
545  case 1:
546  // if receiver Identity of E1 > sender Identity of E1, E2 is better by topology
547  *iBetter = i2;
548  *byTopology = PTP_TRUE;
549  return 0;
550  default:
551  break;
552  }
553  // if receiver Identity of E1 = sender Identity of E1, error 1
554  return 1;
555  } else if (E1->stepsRemoved < E2->stepsRemoved) {
556  switch (ptp_clockIdentityCompare(
557  *(ptpClock.defaultDS.clockIdentity),
558  ptp_foreignMaster[i2 - 1u][0].clockIdentity)) {
559  case -1:
560  // if receiver Identity of E2 < sender Identity of E2, E1 is better
561  *iBetter = i1;
562  return 0;
563  case 1:
564  // if receiver Identity of E2 > sender Identity of E2, E1 is better by topology
565  *iBetter = i1;
566  *byTopology = PTP_TRUE;
567  return 0;
568  default:
569  break;
570  }
571  // if receiver Identity of E2 = sender Identity of E2, error 1
572  return -1;
573  }
574  // Identities of senders
575  switch (ptp_clockIdentityCompare(
576  ptp_foreignMaster[i1 - 1u][0].clockIdentity,
577  ptp_foreignMaster[i2 - 1u][0].clockIdentity)) {
578  case 1:
579  *iBetter = i2;
580  *byTopology = PTP_TRUE;
581  return 0;
582  case -1:
583  *iBetter = i1;
584  *byTopology = PTP_TRUE;
585  return 0;
586  default:
587  break;
588  }
589  // port numbers of receivers
590  if (i1 > i2) {
591  // E2 better by topology
592  *iBetter = i2;
593  *byTopology = PTP_TRUE;
594  return 0;
595  } else if (i1 < i2) {
596  // E1 better by topology
597  *iBetter = i1;
598  *byTopology = PTP_TRUE;
599  return 0;
600  }
601  } else {
602  // Compare grand master clocks.
603  // priority1
604  if (E1->grandMasterPriority1 > E2->grandMasterPriority1) {
605  *iBetter = i2;
606  return 0;
607  } else if (E1->grandMasterPriority1 < E2->grandMasterPriority1) {
608  *iBetter = i1;
609  return 0;
610  }
611  // class
612  if (E1->grandMasterClockQuality.clockClass
613  > E2->grandMasterClockQuality.clockClass) {
614  *iBetter = i2;
615  return 0;
616  } else if (E1->grandMasterClockQuality.clockClass
617  < E2->grandMasterClockQuality.clockClass) {
618  *iBetter = i1;
619  return 0;
620  }
621  // accuracy
622  if (E1->grandMasterClockQuality.clockAccuracy
623  > E2->grandMasterClockQuality.clockAccuracy) {
624  *iBetter = i2;
625  return 0;
626  } else if (E1->grandMasterClockQuality.clockAccuracy
627  < E2->grandMasterClockQuality.clockAccuracy) {
628  *iBetter = i1;
629  return 0;
630  }
631  // offsetScaledLogVariance
632  if (E1->grandMasterClockQuality.offsetScaledLogVariance
633  > E2->grandMasterClockQuality.offsetScaledLogVariance) {
634  *iBetter = i2;
635  return 0;
636  } else if (E1->grandMasterClockQuality.offsetScaledLogVariance
637  < E2->grandMasterClockQuality.offsetScaledLogVariance) {
638  *iBetter = i1;
639  return 0;
640  }
641  // priority2
642  if (E1->grandMasterPriority2 > E2->grandMasterPriority2) {
643  *iBetter = i2;
644  return 0;
645  } else if (E1->grandMasterPriority2 < E2->grandMasterPriority2) {
646  *iBetter = i1;
647  return 0;
648  }
649  // Identity
650  switch (ptp_clockIdentityCompare(E1->grandMasterIdentity,
651  E2->grandMasterIdentity)) {
652  case 1:
653  *iBetter = i2;
654  return 0;
655  case -1:
656  *iBetter = i1;
657  return 0;
658  default:
659  break;
660  }
661  }
662  return 2;
663 }
664 
678  PTP_announceDS *E, ptp_uinteger8 portNumber) {
679  ptp_uinteger8 portIndex;
680 
681  // check for no address (empty set)
682  if (portNumber) {
683  if (ptp_clockIdentityCompare(E->grandMasterIdentity, PTP_ZEROSEQ64)
684  == 0)
685  portNumber = 0;
686  }
687  if (!portNumber) {
688  *Dbetter = PTP_TRUE;
689  return 0;
690  }
691 
692  if (ptp_clockIdentityCompare(*(D->defaultDS.clockIdentity),
693  E->grandMasterIdentity) == 0) {
694 // steps removed
695 // this will never happen
696 // if (0 > (E->stepsRemoved + 1)) {
697 // *Dbetter = PTP_FALSE;
698 // return 0;
699 // } else
700  if (1 < E->stepsRemoved) {
701  *Dbetter = PTP_TRUE;
702  return 0;
703  }
704  portIndex = portNumber - 1;
705 // D->stepsRemoved within 1 of E->stepsRemoved
706 // stepsRemoved is an unsigned integer, (0 > E->stepsRemoved) is always false.
707 // if (0 > E->stepsRemoved) {
708 // if receiver Identity of D < sender Identity of D, E is better
709 // This should not apply because D is the data sets of the clock,
710 // there is no sender or receiver.
711 //
712 // if Identity of receiver of D > Identity of sender of D, E is better by topology
713 // This should not apply because D is the data sets of the clock,
714 // there is no sender or receiver.
715 //
716 // if Identity of receiver of E1 = Identity of sender of E1, error 1
717 // *Dbetter = PTP_FALSE;
718 // return 0;
719 //
720 // } else
721  // (0 < E->stepsRemoved) becomes (0 != E->stepsRemoved)
722  if (0 != E->stepsRemoved) {
723  switch (ptp_clockIdentityCompare(*(D->defaultDS.clockIdentity),
724  ptp_foreignMaster[portIndex][0].clockIdentity)) {
725  case -1:
726  // if Identity of receiver of E < Identity of sender of E, D is better
727  *Dbetter = PTP_TRUE;
728  return 0;
729  case 1:
730  // if Identity of receiver of E > Identity of sender of E, D is better by topology
731  *Dbetter = PTP_TRUE;
732  return 0;
733  default:
734  break;
735  }
736  // if receiver Identity of E = sender Identity of E, error 1
737  return 1;
738  }
739  // Identities of senders
740  switch (ptp_clockIdentityCompare(*(D->defaultDS.clockIdentity),
741  ptp_foreignMaster[portIndex][0].clockIdentity)) {
742  case 1:
743  // D better by topology
744  *Dbetter = PTP_FALSE;
745  return 0;
746  case -1:
747  // E better by topology
748  *Dbetter = PTP_TRUE;
749  return 0;
750  default:
751  break;
752  }
753  // port numbers of receivers
754  // D0 port number is always 0.
755  // D0 port number < E port Number : D0 is better by topology
756  *Dbetter = PTP_TRUE;
757  return 0;
758  } else {
759  // Compare grand master clocks.
760  // priority1
761  if (D->defaultDS.priority1 > E->grandMasterPriority1) {
762  *Dbetter = PTP_FALSE;
763  return 0;
764  } else if (D->defaultDS.priority1 < E->grandMasterPriority1) {
765  *Dbetter = PTP_TRUE;
766  return 0;
767  }
768  // class
769  if (D->defaultDS.clockQuality.clockClass
770  > E->grandMasterClockQuality.clockClass) {
771  *Dbetter = PTP_FALSE;
772  return 0;
773  } else if (D->defaultDS.clockQuality.clockClass
774  < E->grandMasterClockQuality.clockClass) {
775  *Dbetter = PTP_TRUE;
776  return 0;
777  }
778  // accuracy
779  if (D->defaultDS.clockQuality.clockAccuracy
780  > E->grandMasterClockQuality.clockAccuracy) {
781  *Dbetter = PTP_FALSE;
782  return 0;
783  } else if (D->defaultDS.clockQuality.clockAccuracy
784  < E->grandMasterClockQuality.clockAccuracy) {
785  *Dbetter = PTP_TRUE;
786  return 0;
787  }
788  // offsetScaledLogVariance
789  if (D->defaultDS.clockQuality.offsetScaledLogVariance
790  > E->grandMasterClockQuality.offsetScaledLogVariance) {
791  *Dbetter = PTP_FALSE;
792  return 0;
793  } else if (D->defaultDS.clockQuality.offsetScaledLogVariance
794  < E->grandMasterClockQuality.offsetScaledLogVariance) {
795  *Dbetter = PTP_TRUE;
796  return 0;
797  }
798  // priority2
799  if (D->defaultDS.priority2 > E->grandMasterPriority2) {
800  *Dbetter = PTP_FALSE;
801  return 0;
802  } else if (D->defaultDS.priority2 < E->grandMasterPriority2) {
803  *Dbetter = PTP_TRUE;
804  return 0;
805  }
806  // Identity
807  switch (ptp_clockIdentityCompare(*(D->defaultDS.clockIdentity),
808  E->grandMasterIdentity)) {
809  case 1:
810  *Dbetter = PTP_FALSE;
811  return 0;
812  case -1:
813  *Dbetter = PTP_TRUE;
814  return 0;
815  default:
816  break;
817  }
818  }
819  return 2;
820 }
821 
834  UInt8 portIndex;
835 
836  portIndex = portNumber - 1;
837  // only one foreign master is recorded in this program, to save memory
838 
839  // If message from current master clocks
840  if ((ptp_clockIdentityCompare(ptp_foreignMaster[portIndex][0].clockIdentity,
841  &(pBuf[20])) == 0)
842  && !(~ptp_foreignMaster[portIndex][0].foreignMasterAnnounceMessages)) {
843  // Foreign master is registered
844  ptp_foreignMaster[portIndex][0].foreignMasterAnnounceMessages++;
845  } else {
846  // Foreign master is not registered.
847  // Normal behavior would be register if there is resources, ignore if there isn't.
848  // On this program, each port connects with only one other device, if a packet
849  // from another device was received, only that device is accessible, only one record
850  // exists on the foreignMasterDS.
851  ptp_rcvOctets(8, &(pBuf[20]),
852  ptp_foreignMaster[portIndex][0].clockIdentity);
853  ptp_foreignMaster[portIndex][0].foreignMasterAnnounceMessages = 0;
854  };
855 
856  // the following data set is used to store data that will be used on BMC algorithm
857  ptp_announce[portIndex].grandMasterPriority1 = ptp_rcvUInt8(&(pBuf[47]));
858  ptp_rcvOctets(8, &(pBuf[53]), ptp_announce[portIndex].grandMasterIdentity);
859  ptp_announce[portIndex].grandMasterClockQuality.clockClass = ptp_rcvUInt8(
860  &(pBuf[48]));
861  ptp_announce[portIndex].grandMasterClockQuality.clockAccuracy =
862  (ptp_clockAccuracy) ptp_rcvUInt8(&(pBuf[49]));
863  ptp_announce[portIndex].grandMasterClockQuality.offsetScaledLogVariance =
864  ptp_rcvUInt16(&(pBuf[50]));
865  ptp_announce[portIndex].grandMasterPriority2 = ptp_rcvUInt8(&(pBuf[52]));
866  ptp_announce[portIndex].stepsRemoved = ptp_rcvUInt16(&(pBuf[61]));
867  ptp_announce[portIndex].currentUtcOffset = ptp_rcvUInt16(&(pBuf[44]));
868  ptp_announce[portIndex].currentUtcOffsetValid = (pBuf[6] >> 2) & 0x01;
869  ptp_announce[portIndex].leap59 = (pBuf[6] >> 1) & 0x01;
870  ptp_announce[portIndex].leap61 = pBuf[6] & 0x01;
871  ptp_announce[portIndex].timeTraceable = (pBuf[6] >> 4) & 0x01;
872  ptp_announce[portIndex].frequencyTraceable = (pBuf[6] >> 5) & 0x01;
873  ptp_announce[portIndex].ptpTimescale = (pBuf[6] >> 3) & 0x01;
874  ptp_announce[portIndex].timeSource = (ptp_timeSource) ptp_rcvUInt8(
875  &(pBuf[63]));
876 }
877 
890  return nwk_startFrame(destination, NWK_CMDIDPTP, 1, len);
891 }
892 
907  return nwk_snd(len, pBuf);
908 }
909 
916 void ptp_endFrame() {
917  nwk_endFrame(TRUE);
918 }
919 
931  return nwk_sndUInt8(v);
932 }
933 
945  return nwk_sndUInt16(v);
946 }
947 
959  return nwk_sndUInt32(p);
960 }
961 
973  return nwk_sndUInt48(p);
974 }
975 
987  if (nwk_sndUInt32(&(p->secondsLow)))
988  return nwk_sndUInt16(p->secondsHigh);
989  else
990  return FALSE;
991 }
992 
1004  return nwk_sndUInt64(p);
1005 }
1006 
1018  return nwk_sndInt64(p);
1019 }
1020 
1031  return pBuf[0];
1032 }
1033 
1044  ptp_uinteger32 r;
1045  ((char *) &r)[0] = pBuf[0];
1046  ((char *) &r)[1] = pBuf[1];
1047  return r;
1048 }
1049 
1060  ptp_uinteger32 r;
1061  ((char *) &r)[0] = pBuf[0];
1062  ((char *) &r)[1] = pBuf[1];
1063  ((char *) &r)[2] = pBuf[2];
1064  ((char *) &r)[3] = pBuf[3];
1065  return r;
1066 }
1067 
1078  ptp_uinteger48 r;
1079  ((char *) &r)[0] = pBuf[0];
1080  ((char *) &r)[1] = pBuf[1];
1081  ((char *) &r)[2] = pBuf[2];
1082  ((char *) &r)[3] = pBuf[3];
1083  ((char *) &r)[4] = pBuf[4];
1084  ((char *) &r)[5] = pBuf[5];
1085  ((char *) &r)[6] = 0;
1086  ((char *) &r)[7] = 0;
1087  return r;
1088 }
1089 
1099  ((char *) &(p->secondsLow))[0] = pBuf[0];
1100  ((char *) &(p->secondsLow))[1] = pBuf[1];
1101  ((char *) &(p->secondsLow))[2] = pBuf[2];
1102  ((char *) &(p->secondsLow))[3] = pBuf[3];
1103  ((char *) &(p->secondsHigh))[0] = pBuf[4];
1104  ((char *) &(p->secondsHigh))[1] = pBuf[5];
1105 }
1106 
1117  ptp_uinteger64 r;
1118  ((char *) &r)[0] = pBuf[0];
1119  ((char *) &r)[1] = pBuf[1];
1120  ((char *) &r)[2] = pBuf[2];
1121  ((char *) &r)[3] = pBuf[3];
1122  ((char *) &r)[4] = pBuf[4];
1123  ((char *) &r)[5] = pBuf[5];
1124  ((char *) &r)[6] = pBuf[6];
1125  ((char *) &r)[7] = pBuf[7];
1126  return r;
1127 }
1128 
1139  ptp_integer64 r;
1140  ((char *) &r)[0] = pBuf[0];
1141  ((char *) &r)[1] = pBuf[1];
1142  ((char *) &r)[2] = pBuf[2];
1143  ((char *) &r)[3] = pBuf[3];
1144  ((char *) &r)[4] = pBuf[4];
1145  ((char *) &r)[5] = pBuf[5];
1146  ((char *) &r)[6] = pBuf[6];
1147  ((char *) &r)[7] = pBuf[7];
1148  return r;
1149 }
1150 
1163  ptp_copyOctets(len, pBuf, dest);
1164 }
1165 
1178  while (len) {
1179  len--;
1180  *dest++ = *source++;
1181  };
1182 }
ptp_uinteger64 ptp_rcvUInt64(ptp_octet *pBuf)
Receive unsigned 64 bits integer.
Definition: ptp_util.c:1116
Network functions interface.
uint64_t * nwk_getPIeeeAddress()
Get pointer to the IEEE address.
Definition: nwk.c:1245
PTP messages interface.
unsigned char ptp_boolean
Definition: ptp_types.h:68
ptp_uinteger8 ptp_sndInt64(ptp_integer64 *p)
Send 64 bits integer.
Definition: ptp_util.c:1017
UInt8 nwk_sndInt64(int64_t *p)
Send signed 64 bits integer.
Definition: nwk.c:1394
void clock_adjTimeValues(int64_t *adjValue, clock_timeStamp *time)
Adjust time values.
Definition: clock.c:304
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_rcvUInt8(ptp_octet *pBuf)
Receive unsigned 8 bits integer.
Definition: ptp_util.c:1030
UInt8 nwk_sndUInt64(uint64_t *p)
Send unsigned 64 bits integer.
Definition: nwk.c:1380
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
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_integer8 ptp_dataSetComparisonDE(ptp_boolean *Dbetter, ptp_clock *D, PTP_announceDS *E, ptp_uinteger8 portNumber)
Data set comparison self clock/announce message.
Definition: ptp_util.c:677
ptp_uinteger8 ptp_sndUInt8(ptp_uinteger8 v)
Send unsigned 8 bits integer.
Definition: ptp_util.c:930
ptp_uinteger8 ptp_sndUInt48(ptp_uinteger48 *p)
Send unsigned 48 bits integer.
Definition: ptp_util.c:972
PTP clock structure.
Definition: ptp_clock.h:65
UInt8 nwk_sndUInt48(uint64_t *p)
Send unsigned 48 bits integer.
Definition: nwk.c:1366
unsigned long long ptp_uinteger64
Definition: ptp_types.h:125
ptp_integer8 ptp_clockIdentityCompare(ptp_clockIdentity A, ptp_clockIdentity B)
Clock identity compare.
Definition: ptp_util.c:201
Master on clockClass 1 ~ 127 and grandMaster.
Definition: ptp_types.h:296
Slave.
Definition: ptp_types.h:299
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
Master on clockClass > 128 and grandMaster.
Definition: ptp_types.h:297
void ptp_copyOctets(ptp_uinteger8 len, ptp_octet *source, ptp_octet *dest)
Copy octets.
Definition: ptp_util.c:1177
void ptp_bmc()
Best master clock.
Definition: ptp_util.c:274
Clock interface.
PTP_announceDS ptp_announce[PTP_NUMBERPORTS]
Last announce message received for each port.
Definition: ptp_util.c:63
UInt8 nwk_sndUInt32(UInt32 *p)
Send unsigned 32 bits integer.
Definition: nwk.c:1349
unsigned long ptp_uinteger32
Definition: ptp_types.h:110
ptp_timeSource
Definition: ptp_types.h:244
ptp_clockIdentity * ptp_getClockIdentity()
Get clock identity.
Definition: ptp_util.c:85
UInt8 nwk_sndUInt16(UInt16 v)
Send unsigned 16 bits integer.
Definition: nwk.c:1333
PTP interface.
#define NWK_CMDIDPTP
Command id for PTP messages.
Definition: nwk.h:169
When port have no connection, keep listening state.
Definition: ptp_types.h:302
#define PTP_DESIGNTIME_UTCOFFSET
Definition: ptp_cfg.h:77
UInt8 nwk_sndUInt8(UInt8 v)
Send unsigned 8 bits integer.
Definition: nwk.c:1317
PTP functions specific to the implementation.
void ptp_state_decision_event()
State decision event.
Definition: ptp_util.c:248
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
int64_t clock_timeDiff(clock_timeStamp *t1, clock_timeStamp *t2)
Time difference.
Definition: clock.c:533
void ptp_portUpdateStatus()
Port update status.
Definition: ptp_util.c:445
clockClass > 128 and is PASSIVE to break a timing loop
Definition: ptp_types.h:301
#define PTP_NUMBERPORTS
Definition: ptp_cfg.h:100
ptp_octet ptp_clockIdentity[8]
Definition: ptp_types.h:322
unsigned char ptp_uinteger8
Definition: ptp_types.h:90
nwk_devType nwk_getDeviceType()
This function gets the device type.
Definition: nwk.c:535
unsigned long long ptp_uinteger48
Definition: ptp_types.h:115
void ptp_portsSetListening()
Ports set listening.
Definition: ptp_util.c:224
ptp_clockAccuracy
Definition: ptp_types.h:170
ptp_recommendedState ptp_portRecommendedState[PTP_NUMBERPORTS]
Recommended portState set by BMC (Best Master Clock) Algorithm.
Definition: ptp_util.c:59
ptp_uinteger8 ptp_sndUInt64(ptp_uinteger64 *p)
Send unsigned 64 bits integer.
Definition: ptp_util.c:1003
UInt8 nwk_startFrame(UInt16 destination, UInt16 cmdId, UInt8 radius, UInt8 len)
Start Frame.
Definition: nwk.c:1264
ptp_integer64 ptp_timeDiff(PTP_TimeStamp *t1, PTP_TimeStamp *t2)
Time difference.
Definition: ptp_util.c:187
End device.
Definition: nwk.h:225
void ptp_rcvUInt48sc(ptp_octet *pBuf, PTP_SecondsCount *p)
Receive seconds count value.
Definition: ptp_util.c:1098
UInt8 nwk_snd(UInt8 len, void *pBuf)
Send data.
Definition: nwk.c:1285
void ptp_portUpdateDS()
Port update data set.
Definition: ptp_util.c:344
void ptp_getCurrentTime(PTP_TimeStamp *dest)
Get cuttent time.
Definition: ptp_util.c:104
Master and NOT grandMaster.
Definition: ptp_types.h:298
char ptp_octet
Definition: ptp_types.h:137
PTP constants that should not need to be modified.
ptp_integer64 ptp_rcvInt64(ptp_octet *pBuf)
Receive 64 bits integer.
Definition: ptp_util.c:1138
ptp_recommendedState
Definition: ptp_types.h:295
ptp_uinteger8 ptp_sndUInt48sc(PTP_SecondsCount *p)
Send a seconds count value.
Definition: ptp_util.c:986
void nwk_endFrame(UInt8 forwardToSerial)
End frame.
Definition: nwk.c:1300
ptp_uinteger48 ptp_rcvUInt48(ptp_octet *pBuf)
Receive unsigned 48 bits integer.
Definition: ptp_util.c:1077
PTP data types specifications.
PTP configuration values to compile.
ptp_integer8 ptp_dataSetComparisonEE(ptp_uinteger8 *iBetter, ptp_boolean *byTopology, PTP_announceDS *E1, PTP_announceDS *E2, ptp_uinteger8 i1, ptp_uinteger8 i2)
Data set comparison.
Definition: ptp_util.c:501
clockClass 1 ~ 127 and NOT grandMaster or is PASSIVE to break a timing loop
Definition: ptp_types.h:300
UInt16 nwk_getNeighborAddress(UInt8 portNumber)
Get neighbor address.
Definition: nwk.c:1578
void clock_setTime(clock_timeStamp *sourceTime)
Set time.
Definition: clock.c:237
#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 clock_adjTime(int64_t *adjValue)
Adjust time.
Definition: clock.c:256
unsigned short ptp_uinteger16
Definition: ptp_types.h:100
void clock_getTime(clock_timeStamp *destTime)
Get time.
Definition: clock.c:218
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