RTI Connext Micro  Version 2.4.1.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
osapi_time.h
Go to the documentation of this file.
1 /*
2  * FILE: osapi_time.h - Definition of Time API
3  *
4  * Copyright 2005-2014 Real-Time Innovations, Inc.
5  *
6  * No duplications, whole or partial, manual or electronic, may be made
7  * without express written permission. Any such copies, or
8  * revisions thereof, must display this notice unaltered.
9  * This code contains trade secrets of Real-Time Innovations, Inc.
10  *
11  * Modification History
12  * --------------------
13  * 20mar2013,tk Updated
14  * 06dec2005,rh Created
15  */
16 /*e \file
17  * \brief Time API definition
18  */
19 #ifndef osapi_time_h
20 #define osapi_time_h
21 
22 #ifndef osapi_types_h
23 #include "osapi/osapi_types.h"
24 #endif
25 
26 #ifdef __cplusplus
27 extern "C"
28 {
29 #endif
30 
31 /*e \defgroup OSAPITimeClass OSAPI Time
32  * \ingroup OSAPIModule
33 */
34 
35 /*e \ingroup OSAPITimeClass
36 
37  \brief NtpTime API.
38 */
39 
40 /* ================================================================= */
41 /* Definition: Time */
42 /* ----------------------------------------------------------------- */
43 
44 /*e \ingroup OSAPITimeClass
45 
46  @brief NTP Time representation.
47 
48  Expresses time in NTP format. The second field is simply an integer
49  expressing seconds. The fraction field expresses 1/2^32 of a second.
50  We strongly urge customers to use our provided macros to convert this
51  format to and from human readable form.
52 
53  OSAPI_NtpTime_init must be called before OSAPI_NtpTime_get. Creating a domain
54  has the side-effect of calling OSAPI_NtpTime_init.
55 
56  \b Example:
57 
58  The following is a simple example on how to prepare a struct OSAPI_NtpTime structure
59  to be 1.5 seconds.
60 
61  \verbatim
62  struct OSAPI_NtpTime ntpTime;
63 
64  OSAPI_NtpTime_packFromMillisec(ntpTime, 1, 500);
65  \endverbatim
66 
67  @see OSAPI_NtpTime_packFromMillisec OSAPI_NtpTime_packFromMicrosec
68  @see OSAPI_NtpTime_packFromNanosec
69  @see OSAPI_NtpTime_unpackFromMillisec OSAPI_NtpTime_unpackFromMicrosec
70  @see OSAPI_NtpTime_unpackFromNanosec
71  */
72 typedef struct OSAPI_NtpTime
73 {
74  /* e Seconds.* */
75  RTI_INT32 sec;
76  /* e fraction of a second in 1/2^32 form. */
77  RTI_UINT32 frac;
79 
80 /*e \ingroup OSAPITimeClass
81  The maximum number of seconds that can be represented using NTP time.
82  */
83 #define OSAPI_NTP_TIME_SEC_MAX ((RTI_INT32)0x7fffffff)
84 
85 /*e \ingroup OSAPITimeClass
86  The largest possible value of the fraction field in NTP time.
87  */
88 #define OSAPI_NTP_TIME_FRAC_MAX ((RTI_UINT32)0xffffffff)
89 
90 /*e \ingroup OSAPITimeClass
91  @brief Set struct OSAPI_NtpTime time to zero.
92 
93  @param time (struct OSAPI_NtpTime*) Pointer to struct OSAPI_NtpTime struct that needs to be
94  set to zero.
95  */
96 #define OSAPI_NtpTime_zero(time) \
97 { \
98  (time)->sec = 0; \
99  (time)->frac = 0; \
100 }
101 
102 /*e \ingroup OSAPITimeClass
103  @brief Set struct OSAPI_NtpTime time to maximum value.
104 
105  @param time (struct OSAPI_NtpTime*) Pointer to struct OSAPI_NtpTime struct that needs to be
106  set to its maximum possible value.
107 
108  The maximum possible value equals:
109 
110  (time).sec = OSAPI_NTP_TIME_SEC_MAX
111  (time).frac = OSAPI_NTP_TIME_FRAC_MAX
112 
113  */
114 #define OSAPI_NtpTime_set_max(time) \
115 { \
116  (time)->sec = OSAPI_NTP_TIME_SEC_MAX; \
117  (time)->frac = OSAPI_NTP_TIME_FRAC_MAX; \
118 }
119 
120 #define OSAPI_NtpTime_to_double(t) \
121  (((double)((t)->frac)/4294967296.0f) + (double)(t)->sec)
122 
123 /*e \ingroup OSAPITimeClass
124 
125  @brief Macro to convert from seconds and milliseconds to struct OSAPI_NtpTime format.
126 
127  @param time (struct OSAPI_NtpTime) contains the answer.
128  @param s (integer) Seconds to convert.
129  @param msec (millisecond) Fraction portion (less than 1000).
130 
131  \verbatim
132  struct OSAPI_NtpTime time;
133  long sec, msec;
134  sec = 10;
135  msec = 577;
136 
137  OSAPI_NtpTime_packFromMillisec(time, sec, msec);
138  \endverbatim
139 
140  After the above call is made, the variable time will contain the equivalent
141  timestamp in struct OSAPI_NtpTime representation.
142 
143  This macro assumes that msec<1000. It is the caller's responsibility
144  to ensure this. This is done for performance reasons (the extra check slows
145  the execution by a factor of 5). If msec may be greater than 1000, you can invoke
146  the macro as follows:
147  \verbatim
148  OSAPI_NtpTime_packFromMillisec(time, sec + msec/1000, msec%1000);
149  \endverbatim
150 
151  This macro only evaluates its arguments once, so it is safe to invoke it
152  with an argument that has side effects; that is, if you write:
153  \verbatim
154  RTI_UINT32 count = 10;
155  OSAPI_NtpTime_packFromMillisec(time, sec, count++)
156  \endverbatim
157  After the macro count is guaranteed to be 11.
158 
159  The accuracy of this conversion over the whole range of millisecond values
160  is 0.013 milliseconds.
161 
162  This is a fairly efficient macro. On a 400MHz Pentium-II Linux box
163  the execution time is about 0.06 usec.
164 
165  \verbatim
166  2^22*time.frac = ms + ms/2^6 + ms/2^7 + ms/2^11 + ms/2^14 + 1.3e-5
167  = ms + ms*393/2^14;
168  time.frac = (ms<<22) + (ms<<16) + (ms<<15) + (ms<<11) + (ms<<8)
169  = (ms<<22) + ((ms*393)<<8)
170  \endverbatim
171 
172  @see struct OSAPI_NtpTime OSAPI_NtpTime_unpackToMillisec
173 */
174 #define OSAPI_NtpTime_from_millisec(time, s, msec) \
175 { \
176  register RTI_UINT32 ms = msec; \
177  (time)->sec = s; \
178  (time)->frac = (ms<<22) + ((ms*393)<<8); \
179 }
180 
181 /*e \ingroup OSAPITimeClass
182 
183  @brief Macro to convert from struct OSAPI_NtpTime to seconds and milliseconds.
184 
185  @param s (integer) Holds the seconds answer.
186  @param msec (integer) Holds the millisecond answer.
187  @param time (struct OSAPI_NtpTime) The time to convert to seconds and milliseconds.
188 
189  This macro does not check for overflow, so for a near-infinite time value,
190  the conversion result may end up being negative. It is the responsibility
191  of the user to avoid passing these large time values.
192 
193  Use as indicated by the following code:
194  \verbatim}
195  struct OSAPI_NtpTime time;
196  long sec, msec;
197 
198  time.sec = 10;
199  time.frac = 577;
200 
201  OSAPI_NtpTime_unpackToMillisec(sec, msec, time);
202  \endverbatim
203 
204  After the above call is made, the variables "sec" and "msec" will
205  contain the equivalent timestamp.
206 
207  The accuracy of this conversion over the whole range of struct OSAPI_NtpTime values
208  is 0.5 milliseconds, except for ntp values above {0x7fffffff, 0x7fffffff},
209  accuracy is up to nearly 1 millisecond.
210 
211  This is a fairly efficient macro. On a 400MHz Pentium-II Linux box
212  the execution time is about 0.08 usec.
213 
214  \verbatim
215  ms/2^22 = frac*1000/1024 = frac*(1 - 24/1024) = frac*(1 - 3/2^7) =
216  frac*(1 - 1/2^6 - 1/2^7)
217  \endverbatim
218 
219  @see struct OSAPI_NtpTime OSAPI_NtpTime_packFromMillisec
220 */
221 #define OSAPI_NtpTime_to_millisec(s, msec, time) \
222 { \
223  *(s) = (time)->sec; \
224  *(msec) = ((time)->frac - ((time)->frac>>6) - ((time)->frac>>7) + (1<<21))>>22; \
225  if( ((*(msec))>=1000)&&((*(s))!=0x7FFFFFFF) ) { (*(msec)) -= 1000; (*(s))++; } \
226 }
227 
228 /*e \ingroup OSAPITimeClass
229 
230  @brief Macro to convert from seconds and microseconds to struct OSAPI_NtpTime format.
231 
232  @param time (struct OSAPI_NtpTime) to contain the answer.
233  @param s (integer) seconds of the time to covert.
234  @param usec (integer) microseconds fraction to convert from.
235 
236  This macro does not check for overflow, so for a near-infinite time value,
237  the conversion result may end up being negative. It is the caller's
238  responsibility to avoid passing these large time values.
239 
240  Use as indicated by the following code:
241  \verbatim
242  struct OSAPI_NtpTime ntp;
243  long sec, usec;
244  sec = 10;
245  usec = 577;
246 
247  OSAPI_NtpTime_packFromMicrosec(ntp, sec, usec);
248  \endverbatim
249 
250  After the above call is made, the variable ntp will contain the equivalent
251  time stamp in struct OSAPI_NtpTime representation.
252 
253  This macro assumes that msec<1000000. It is the caller's responsibility
254  to ensure this. This is done for performance reasons, the extra check
255  slows the execution a factor of 5! If msec may be greater than 1000000,
256  you can invoke the macro as follows:
257  \verbatim
258  OSAPI_NtpTime_packFromMicrosec(ntp, sec + usec/1000000, usec%1000000);
259  \endverbatim
260 
261  This macro only evaluates its arguments once, so it is safe to invoke it
262  with an argument that has side effects; that is, if you write:
263  \verbatim
264  RTI_UINT32 count = 10;
265  OSAPI_NtpTime_packFromMicrosec(ntp, sec, count++)
266  \endverbatim
267 
268  After the macro, count is guaranteed to be 11.
269 
270  The accuracy of this conversion over the whole range of microsecond values
271  is 0.0028 microseconds.
272 
273  This is a fairly efficient macro. On a 400MHz Pentium-II Linux box
274  the execution time is about 0.08 usec.
275 
276  \verbatim
277  2^12 * ntp.frac = us + us/2^5 + us/2^6 + us/2^10 + us/2^11
278  + us/2^13 + us/2^14 + us/2^15 + us/2^16
279  + us/2^18 + us/2^19 + us/2^20 + us/2^21
280  + us/2^23 + 3e-9
281  = us + us*99/2^11 + us*15/2^16 + us*61/2^23
282  ntp.frac = (us<<12) + (us<<7) + (us<<6) + (us<<2) + (us<<1)
283  + (us>>1) + (us>>2) + (us>>3) + (us>>4)
284  + (us>>6) + (us>>7) + (us>>8) + (us>>9) + (us>>11)
285  = (us<<12) + ((us*99)<<1)+ ((us*15)>>4)+ ((us*61)>>11)
286  \endverbatim
287 */
288 #define OSAPI_NtpTime_from_microsec(time, s, usec) \
289 { \
290  register RTI_UINT32 us = usec; \
291  (time)->sec = s; \
292  (time)->frac = (us<<12)+ ((us*99)<<1)+ ((us*15 + ((us*61)>>7))>>4); \
293 }
294 
295 /*e \ingroup OSAPITimeClass
296 
297  @brief Macro to convert from struct OSAPI_NtpTime to seconds and microseconds.
298 
299  @param s (integer) Holds the second portion.
300  @param usec (integer) holds the microsecond fraction.
301  @param time (struct OSAPI_NtpTime) to be converted.
302 
303  This macro does not check for overflow, so for a near-infinite time value,
304  the conversion result may end up being negative. It is the caller's
305  responsibility to avoid passing these large time values.
306 
307  Use as indicated by the following code:
308  \verbatim
309  struct OSAPI_NtpTime ntp;
310  long sec, usec;
311 
312  ntp.sec = 10;
313  ntp.frac = 577;
314 
315  OSAPI_NtpTime_unpackToMicrosec(sec, usec, ntp);
316  \endverbatim
317 
318  After the above call is made, the variables "sec" and "usec" will
319  contain the equivalent timestamp.
320 
321  The accuracy of this conversion over the whole range of struct OSAPI_NtpTime values
322  is 0.5 microseconds, except for ntp value above {0x7fffffff, 0x7fffffff},
323  accuracy is up to nearly 1 millisecond.
324 
325  This is a fairly efficient macro. On a 400MHz Pentium-II Linux box
326  the execution time is about 0.12 usec.
327 
328  \verbatim
329  us = frac*1000000/2^20 = frac*( 1 - 48576/2^20 )
330  = frac*(1 - 47/2^10 - 7/2^14)
331  = frac - ((47*frac)>>10) - ((7*frac)>>14)
332  = frac - (frac>>5)-(frac>>7)-(frac>>8)-(frac>>9)-(frac>>10)
333  - (frac>>12)-(frac>>13)-(frac>>14)
334  \endverbatim
335 */
336 #define OSAPI_NtpTime_to_microsec(s, usec, time) \
337 { \
338  register RTI_UINT32 rtiNtpTemp = (time)->frac; \
339  *(s) = (time)->sec; \
340  *(usec) = ((time)->frac - (rtiNtpTemp>>5)-(rtiNtpTemp>>7)-(rtiNtpTemp>>8)- \
341  (rtiNtpTemp>>9)-(rtiNtpTemp>>10) - (rtiNtpTemp>>12) - \
342  (rtiNtpTemp>>13)-(rtiNtpTemp>>14) + (1<<11)) >> 12; \
343  if( ((*(usec)) >= 1000000) && ((*(s))!=0x7FFFFFFF) ) { \
344  (*(usec)) -= 1000000; \
345  (*(s))++; \
346  } \
347 }
348 
349 /*e \ingroup OSAPITimeClass
350 
351  @brief Macro to convert from seconds and nanoseconds to struct OSAPI_NtpTime format.
352 
353  @param time (struct OSAPI_NtpTime) Holds the answer.
354  @param s (integer) Seconds to convert from.
355  @param nsec (integer) Nanosecond fraction to convert from.
356 
357  Use as indicated by the following code:
358  \verbatim
359  struct OSAPI_NtpTime time;
360  long sec, nsec;
361  sec = 10;
362  nsec = 577;
363 
364  OSAPI_NtpTime_packFromNanosec(time, sec, msec);
365  \endverbatim
366 
367  After the above call is made, the variable time will contain the equivalent
368  timestamp in struct OSAPI_NtpTime representation.
369 
370  This macro assumes that nsec<1000000000. It is the caller's responsibility
371  to ensure this. This is done for performance reasons (the extra check
372  slows the execution a factor of 5). If msec may be greater than 1000000, you
373  can invoke the macro as follows:
374  \verbatim}
375  OSAPI_NtpTime_packFromNanosec(time, sec + nsec/1000000000, nsec%1000000000);
376  \endverbatim
377 
378  This macro only evaluates its arguments once, so it is safe to invoke it
379  with an argument that has side effects; that is, if you write:
380  \verbatim
381  RTI_UINT32 count = 10;
382  OSAPI_NtpTime_packFromNanosec(time, sec, count++)
383  \endverbatim
384  After the macro, count is guaranteed to be 11.
385 
386  The accuracy of this conversion over the whole range of nanosecond values
387  is 0.5 nanoseconds, except for ntp value above {0x7fffffff, 0x7fffffff},
388  accuracy is up to nearly 1 millisecond.
389 
390  This is a fairly efficient macro. On a 400MHz Pentium-II Linux box
391  the execution time is about 0.10 usec.
392 
393  \verbatim
394  2^32/10^9 ns = 4*ns + ns/2^2 + ns/2^5 + ns/2^7 + ns/2^8 + ns/2^9 +
395  ns/2^15 + ns/2^17 + ns/2^18 + ns/2^19 + ns/2^20 +
396  ns/2^21 + ns/2^23 + ns/2^29 + ns/2^32
397 
398  2^32/10^9 ns = 4*ns + (ns + ns/2^3 + ns/2^5 + ns/2^6 + ns/2^7 +
399  ns/2^13 + ns/2^15 + ns/2^16 + ns/2^17 + ns/2^18 +
400  ns/2^19 + ns/2^21 + ns/2^27 + ns/2^30)*(1/2^2)
401  \endverbatim
402 */
403 #define OSAPI_NtpTime_from_nanosec(time, s, nsec) \
404 { \
405  register RTI_UINT32 ns = nsec; \
406  (time)->sec = s; \
407  (time)->frac = (ns<<2) + ((ns + (ns>>3) + (ns>>5) + (ns>>6) + \
408  (ns>>7) + (ns>>13) + (ns>>15) + (ns>>16) + (ns>>17) + \
409  (ns>>18) + (ns>>19) + (ns>>21) + (ns>>27) + (ns>>30))>>2); \
410 }
411 
412 /*e \ingroup OSAPITimeClass
413 
414  @brief Macro to convert from struct OSAPI_NtpTime to seconds and nanoseconds.
415 
416  @param s (integer) Second of the time to covert.
417  @param nsec (integer) Nanosecond fraction to convert.
418  @param time (struct OSAPI_NtpTime) to convert from.
419 
420  Use as indicated by the following code:
421  \verbatim
422  struct OSAPI_NtpTime time;
423  long sec, nsec;
424  time.sec = 10;
425  time.frac = 577;
426 
427  OSAPI_NtpTime_unpackToNanosec(sec, nsec, time);
428  \endverbatim
429  After the above call is made, the variables "sec" and "nsec" will
430  contain the equivalent timestamp.
431 
432  The accuracy of this conversion over the whole range of struct OSAPI_NtpTime values
433  is 0.5 nsec.
434 
435  This is a fairly efficient macro. On a 400MHz Pentium-II Linux
436  box the execution time is about 0.09 usec.
437 
438  Given that 294967296 = 0x1194d800 and:
439  \verbatim
440  4*ns = frac*4000000000/2^32 = frac*(1 - 294967296/2^32)
441  = frac*(1 - 1/2^4 - 1/2^8 - 9/2^12 - 4/2^16 - 13/2^20 - 8/2^24)
442  = frac*(1 - 1>>4 - 1>>8 - 1>>9 - 1>>12 - 1>>14 - 1>>17 - 1>>18 -
443  1>>20 - 1>>21)
444  \endverbatim
445 */
446 #define OSAPI_NtpTime_to_nanosec(s, nsec, time) \
447 { \
448  register RTI_UINT32 rtiNtpTemp = (time)->frac>>1; \
449  register RTI_UINT32 rtiNtpDelta; \
450  *(s) = (time)->sec; \
451  rtiNtpDelta = (rtiNtpTemp) + (rtiNtpTemp>>4) + (rtiNtpTemp>>5) + \
452  (rtiNtpTemp>>8) + (rtiNtpTemp>>10) + (rtiNtpTemp>>13) + \
453  (rtiNtpTemp>>14)+ (rtiNtpTemp>>16) + (rtiNtpTemp>>17); \
454  *(nsec) = ((time)->frac - ((rtiNtpDelta+4)>>3) + 1) >> 2; \
455  if( ((*(nsec))>=1000000000) && ((*(s))!=0x7FFFFFFF) ) { \
456  (*(nsec)) -= 1000000000; \
457  (*(s))++; \
458  } \
459 }
460 
461 
462 /*e \ingroup OSAPITimeClass
463 
464  @brief Precision used in bit manipulation for struct OSAPI_NtpTime fraction
465  conversions.
466 
467  The larger the precision, the more bits you pick up in the long
468  division to get the fraction. If the precision is too large, so that the
469  denominator shifted by the precision bits exceeds the 2^32 limit, the
470  result will be incorrect. For example, if the denominator is 60 (such as for
471  the VxWorks sysClkRate), precision_bits larger than 27 exceed the limit and
472  produce an incorrect result. In general:
473 
474  maximum precision_bits = 32 - (int)log2(denominator_per_sec),
475 
476  where log2(x) can be calculated by:
477 
478  \verbatim
479  int log2answer = 0;
480  while (x >>= 1) {1
481  log2answer++;
482  }
483  \endverbatim
484 
485  For 60 (sysClkRateGet()), this would be 27.
486  For gettimeofday() with microsec resolution, this would be 12.
487 
488  But in practice, that kind of precision is not necessary nor desirable
489  since the conversion would be slower. Instead, the precision is
490  only important relative to the denominator. If your clock frequency
491  is low (e.g., 60 Hz), you only have 16.6 ms resolution anyway. If you are
492  within a tenth of your clock resolution, that is probably good enough.
493 
494  If we generalized too much and tried to handle nanosec resolution "ticks,"
495  we could not guarantee adequate accuracy for all ranges. So internally, we
496  selected a reasonable number that gives us adequate accuracy over large
497  ranges. We wanted a precision that will work well up to 1e6 tick rate
498  (thinking about UNIX gettimeofday()); 7 passed the test.
499 */
500 #define OSAPI_NTP_TIME_PRECISION_BITS_DEFAULT 7
501 
502 /*e \ingroup OSAPITimeClass
503 
504  @brief Macro to convert numerator/denom_per_sec into NTP time.
505 
506  @param time struct OSAPI_NtpTime to contain the result. The existing
507  content of time does not affect the result.
508 
509  @param numerator May be larger than denominator. Since this is a macro
510  and the numerator is evaluated multiple times, you should not specify things
511  like (i++).
512 
513  @param denominator_per_sec Denominator.
514  Physically, this means ticks per sec. Since this is a macro and
515  the denominator is evaluated multiple times, you should not specify things
516  like (i++).
517 */
518 #define OSAPI_NtpTime_from_fraction(time, numerator, denominator_per_sec) \
519  OSAPI_NtpTime_from_fraction_bits((time), (numerator), (denominator_per_sec), \
520  OSAPI_NTP_TIME_PRECISION_BITS_DEFAULT)
521 
522 /*e \ingroup OSAPITimeClass
523 
524  @brief Transforms from struct OSAPI_NtpTime to any integral fraction of a
525  second without using floating point operations.
526 
527  @param numerator RTI_UINT32 where to put the result of the conversion.
528 
529  @param denominator_per_sec The number of units of the fraction contained in
530  a second. For example, this should be 1000 to convert to milliseconds, or
531  60 if you are using the default VxWorks clock rate.
532 
533  @param time struct OSAPI_NtpTime to unpack
534 
535  The algoritm is based on the observation that the time.frac looked at
536  as a sequence of bits: b[1], b[2], b[3], ... represents the
537  following expansion:
538 
539  time_in_sec = b[1]*1/2 + b[1]*1/4 +...+ b[2]*1/8
540  = Sum{i=1..32} b[i]*1/2^i
541 
542  Since we want to obtain the time in units of which there are
543  denominator_per_sec units in a second, the arithmetic is:
544 
545  time_in_units = denominator_per_sec*time_in_sec
546  = denominator_per_sec*time.sec+denominator_per_sec*time.frac
547 
548  And denominator_per_sec*time.frac =
549  Sum{i=1..32} b[i]*(denominator_per_sec/2^i)
550 
551  The key here is that b[i] is easily computed as (1<<31)>>(i-1)
552  and (denominator_per_sec/2^i) is easily computed as denominator_per_sec>>i.
553 
554  Note that each time we compute (denominator_per_sec/2^i) to add it, we may
555  be off by one unit. Therefore, at the end of the computation we may
556  be off by log2(denominator_per_sec) units, which means we should in fact
557  perform each step with an accuracy of log2(2*denominator_per_sec)
558  greater. In other words, we should use units a factor
559  log2(2*denominator_per_sec) greater than the ones we require at the end
560  of the conversion.
561 
562  Another key observation is that the computation can end as soon
563  as (denominator_per_sec<<OSAPI_NTP_TIME_PRECISION_BITS_DEFAULT)>>i becomes
564  zero because that means what is left has a significance of
565  less than one unit>>OSAPI_NTP_TIME_PRECISION_BITS_DEFAULT. This will give a
566  conversion that is strictly smaller than the NTP timestamp. For example,
567  for millisecond conversion log2(1000) = 10, we will do 10 operations so we need a
568  precision of 1/20 or 5 bits (4 bits gives 1/16, 5 gives 1/32).
569 
570  The final operation:
571  (precision_units + (1<<OSAPI_NTP_TIME_PRECISION_BITS_DEFAULT-1))>>
572  OSAPI_NTP_TIME_PRECISION_BITS_DEFAULT;
573  makes sure that the integer division by
574  2^(OSAPI_NTP_TIME_PRECISION_BITS_DEFAULT) is
575  rounded off to the closest number.
576 */
577 #define OSAPI_NtpTime_to_fraction(numerator, denominator_per_sec, time) \
578  OSAPI_NtpTime_to_fraction_bits((numerator), (denominator_per_sec), (time), \
579  OSAPI_NTP_TIME_PRECISION_BITS_DEFAULT)
580 
581 #define OSAPI_NtpTime_from_fraction_bits(time, numerator, denominator_per_sec, \
582  precisionBits) \
583 { \
584  register RTI_UINT32 current_bit = 0x80000000; \
585  register RTI_UINT32 current_units = (denominator_per_sec)<<precisionBits; \
586  register RTI_UINT32 precision_numerator = \
587  ((numerator)%(denominator_per_sec))<< precisionBits; \
588  (time)->sec = (numerator)/(denominator_per_sec); \
589  (time)->frac = 0; \
590  while (current_units >>= 1) { \
591  (time)->frac += \
592  (((precision_numerator) >= current_units) ? \
593  (((precision_numerator) -= current_units), current_bit) : 0); \
594  current_bit >>= 1; \
595  } \
596 }
597 
598 #define OSAPI_NtpTime_to_fraction_bits(numerator, denominator_per_sec, time, \
599  precisionBits) \
600 { \
601  register RTI_UINT32 current_bit = 0x80000000; \
602  register RTI_UINT32 current_units = (*(denominator_per_sec))<<(precisionBits);\
603  register RTI_UINT32 precision_numerator = 0; \
604  numerator = (*(denominator_per_sec))*(time)->sec; \
605  while ((current_units >>= 1)) { \
606  precision_numerator += ((time)->frac & current_bit) ? current_units:0;\
607  current_bit >>= 1; \
608  } \
609  *numerator += (precision_numerator + \
610  (1<<((precisionBits)-1)))>>(precisionBits);\
611 }
612 
613 /*e \ingroup OSAPITimeClass
614 
615  @brief Compare two OSAPI_NtpTimes.
616 
617  @param time1 struct OSAPI_NtpTime, NOT NULL.
618  @param time2 struct OSAPI_NtpTime, NOT NULL.
619 
620  @return If time1 > time2, return 1. If time1 < time2, return -1.
621  If time1 == time2, return 0.
622 */
623 #define OSAPI_NtpTime_compare(time1, time2) \
624 ((((time1)->sec) > ((time2)->sec)) ? 1 : \
625  ((((time1)->sec) < ((time2)->sec)) ? -1 : \
626  ((((time1)->frac) > ((time2)->frac)) ? 1 : \
627  ((((time1)->frac) < ((time2)->frac)) ? -1 : 0))))
628 
629 /*e \ingroup OSAPITimeClass
630 
631  A NULL struct OSAPI_NtpTime pointer is considered infinity. This is consistent
632  with the concept of infinite time on UNIX systems.
633 
634  In addition, if the seconds field equals OSAPI_NTP_TIME_SEC_MAX, the
635  time value is also considered infinite.
636 
637  @param time Pointer to RTITime.
638  @return RTI_TRUE if time is infinite, RTI_FALSE otherwise.
639 
640 */
641 #define OSAPI_NtpTime_is_infinite(time) \
642  (((time)->sec == OSAPI_NTP_TIME_SEC_MAX) ? \
643  RTI_TRUE : RTI_FALSE)
644 
645 /*e \ingroup OSAPITimeClass
646 
647  @brief answer = t1 + t2.
648 
649  This macro does not check for overflow.
650 
651  @param answer struct OSAPI_NtpTime
652  @param t1 struct OSAPI_NtpTime
653  @param t2 struct OSAPI_NtpTime
654 */
655 #define OSAPI_NtpTime_add(answer, t1, t2) \
656 {\
657  (answer)->sec = (t1)->sec + (t2)->sec; \
658  (answer)->frac = (t1)->frac + (t2)->frac; \
659  if (((answer)->frac < (t1)->frac) || ((answer)->frac < (t2)->frac)) { \
660  (answer)->sec++; \
661  } \
662 }
663 
664 /*e \ingroup OSAPITimeClass
665 
666  @brief answer = t1 - t2.
667 
668  @param answer struct OSAPI_NtpTime
669  @param t1 struct OSAPI_NtpTime`
670  @param t2 struct OSAPI_NtpTime
671  */
672 #define OSAPI_NtpTime_subtract(answer, t1, t2) \
673 {\
674  if (OSAPI_NtpTime_is_infinite(t1)) { \
675  *(answer) = *(t1); \
676  } else if (OSAPI_NtpTime_is_infinite(t2)) { \
677  (answer)->sec = 0; \
678  (answer)->frac = 0; \
679  } else { \
680  (answer)->sec = (t1)->sec - (t2)->sec; \
681  (answer)->frac = (t1)->frac - (t2)->frac; \
682  if ((answer)->frac > (t1)->frac) { \
683  (answer)->sec--; \
684  } \
685  }\
686 }
687 
688 /*e \ingroup OSAPITimeClass
689 
690  @brief answer = time << shift.
691 
692  To use this macro for multiplying by num, shift can be calculated
693  as log10(num)/log10(2).
694 
695  @param answer struct OSAPI_NtpTime
696  @param time struct OSAPI_NtpTime
697  @param shift int
698 */
699 #define OSAPI_NtpTime_left_shift(answer, time, shift) \
700 {\
701  register RTI_UINT32 mask = 0xffffffff; \
702  if (shift) { \
703  (answer)->sec = ((time)->sec)<<shift; \
704  mask = mask<<(32 - shift); \
705  mask &= (time)->frac; \
706  mask = mask>>(32 - shift); \
707  (answer)->sec |= mask; \
708  (answer)->frac = ((time)->frac)<<shift; \
709  } \
710  else { \
711  answer = time; \
712  } \
713 }
714 
715 /*e \ingroup OSAPITimeClass
716 
717  @brief answer = time >> shift.
718 
719  To use this macro for dividing by num, shift can be calculated
720  as log10(num)/log10(2).
721 
722  @param answer struct OSAPI_NtpTime
723  @param time struct OSAPI_NtpTime
724  @param shift int
725 */
726 #define OSAPI_NtpTime_right_shift(answer, time, shift) \
727 {\
728  register RTI_UINT32 mask = 0xffffffff; \
729  if (shift) { \
730  (answer)->frac = ((time)->frac)>>shift; \
731  mask = mask>>(32 - shift); \
732  mask &= (time)->sec; \
733  mask = mask<<(32 - shift); \
734  (answer)->frac |= mask; \
735  (answer)->sec = ((time)->sec)>>shift; \
736  } \
737  else { \
738  answer = time; \
739  } \
740 }
741 
742 /*e \ingroup OSAPITimeClass
743 
744  @brief answer += time.
745 
746  This macro does not check for overflow.
747 
748  @param answer struct OSAPI_NtpTime
749  @param time struct OSAPI_NtpTime
750 */
751 #define OSAPI_NtpTime_increment(answer, time) \
752 { \
753  register RTI_UINT32 currentFrac = (answer)->frac; \
754  (answer)->sec += (time)->sec; \
755  (answer)->frac += (time)->frac; \
756  if (((answer)->frac < (time)->frac) || ((answer)->frac < currentFrac)) { \
757  (answer)->sec++; \
758  } \
759 }
760 
761 /*e \ingroup OSAPITimeClass
762 
763  @brief Decrement one struct OSAPI_NtpTime value by another struct OSAPI_NtpTime value.
764 
765  Precondition:
766  Postcondition: answer -= time.
767 
768  @param answer struct OSAPI_NtpTime
769  @param time struct OSAPI_NtpTime
770 
771 */
772 #define OSAPI_NtpTime_decrement(answer, time) \
773 { \
774  register RTI_UINT32 currentFrac = (answer)->frac; \
775  (answer)->sec -= (time)->sec; \
776  (answer)->frac -= (time)->frac; \
777  if (((answer)->frac > currentFrac)) { (answer)->sec--; } \
778 }
779 
780 /*e \ingroup OSAPITimeClass
781 
782  @brief time = time + 1 fraction (~200 picoseconds).
783 
784  This macro does not check for overflow, so time cannot be infinite.
785 
786  @param time
787  @return NO RETURN VALUE => do NOT evaluate this expression; simply call it.
788 */
789 #define OSAPI_NtpTime_increment_infinitesimally(time) \
790  ((++((time)->frac)) == 0) ? ++(time)->sec : 0
791 
792 /*e \ingroup OSAPITimeClass
793 
794  Checks if the time structure represents zero time. Zero time may be useful
795  when getting the sign of the time quantity.
796  @param time Pointer to struct OSAPI_NtpTime. Must not be NULL.
797  @return RTI_TRUE if time is zero, RTI_FALSE otherwise.
798 */
799 #define OSAPI_NtpTime_is_zero(time) (((time) && (time)->sec==0 && \
800  (time)->frac==0) ? \
801  RTI_TRUE : RTI_FALSE)
802 
803 /*e \ingroup OSAPITimeClass
804 
805  @brief Zero time.
806 
807  This global variable is for convenience. It allows you to see if a
808  RTITime variable is negative or positive by comparing against this.
809 
810  @see RtiTimeCompare
811 */
812 #define OSAPI_NTP_TIME_ZERO {0,0}
813 
814 /*e \ingroup OSAPITimeClass
815 
816  Represents the maximum timevalue that can be represented using the
817  NTP time format. For all practical purposes, it can be considered
818  equivalent to infinity.
819 
820 */
821 #define OSAPI_NTP_TIME_MAX {OSAPI_NTP_TIME_SEC_MAX,OSAPI_NTP_TIME_FRAC_MAX}
822 
823 /*e \ingroup OSAPITimeClass
824  The number of nanoseconds per second. 1e9.
825  @see RtiTimePack RtiTimeUnpack
826 */
827 #define OSAPI_NTP_TIME_NSEC_PER_SEC (1000000000)
828 /*e \ingroup OSAPITimeClass
829  The number of microseconds per second. 1e6.
830  @see RtiTimePack RtiTimeUnpack
831 */
832 #define OSAPI_NTP_TIME_USEC_PER_SEC (1000000)
833 /*e \ingroup OSAPITimeClass
834  The number of milliseconds per second. 1e3.
835  @see RtiTimePack RtiTimeUnpack
836  */
837 #define OSAPI_NTP_TIME_MSEC_PER_SEC (1000)
838 /*e \ingroup OSAPITimeClass
839  The number of microseconds per milliseconds. 1e3.
840  @see RtiTimePack RtiTimeUnpack
841  */
842 #define OSAPI_NTP_TIME_NSEC_PER_USEC (1000)
843 /*e \ingroup OSAPITimeClass
844  The number of microseconds per milliseconds. 1e3.
845  @see RtiTimePack RtiTimeUnpack
846 */
847 #define OSAPI_NTP_TIME_USEC_PER_MSEC (1000)
848 /*e \ingroup OSAPITimeClass
849  The number of seconds per second. 1.
850  @see RtiTimePack RtiTimeUnpack
851  */
852 #define OSAPI_NTP_TIME_SEC_PER_SEC (1)
853 
854 /*e \ingroup OSAPITimeClass
855  The number of nano seconds per milli second. 1e6.
856  @see RtiTimePack RtiTimeUnpack
857  */
858 #define OSAPI_NTP_TIME_NSEC_PER_MSEC (1000000)
859 
860 #ifdef __cplusplus
861 } /* extern "C" */
862 #endif
863 
864 #endif /* osapi_time_h */

RTI Connext Micro Version 2.4.1.0 Copyright © Thu Nov 20 2014 Real-Time Innovations, Inc