RTI Connext Micro
Version 2.4.1.0
Main Page
RTI Connext Micro Documentation
Data Structures
Files
File List
Globals
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;
78
}
OSAPI_NtpTime
;
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