SZSPTP ez430-RF2480 1.0

ZigBee Sensor Network with synchronized time and time-stamped measurements.
clock.c
Go to the documentation of this file.
1 /*
2  * clock.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 
20 /*
21  * ======== Standard MSP430 includes ========
22  */
23 #include <msp430f2274.h>
24 
25 /*
26  * ======== Includes ========
27  */
28 
29 #include "clock.h"
30 #include "im.h"
31 
32 /*
33  * ======== Constants ========
34  */
35 
39 #define CLOCK_DEFAULT_TICK_SIZE 250000
40 
43 #define CLOCK_TICK_SIZE_MAX 500000
44 
47 #define CLOCK_NS_IN_ONE_S 1000000000
48 
49 /*
50  * ======== Macros ========
51  */
52 
56 #define CLOCK_FLAGADJUSTING 1
57 
60 #define CLOCK_FLAGCALLTICK 2
61 
65 #define CLOCK_GETADJUSTING clock_runningFlags & CLOCK_FLAGADJUSTING
66 
69 #define CLOCK_SETADJUSTING clock_runningFlags |= CLOCK_FLAGADJUSTING
70 
73 #define CLOCK_CLEARADJUSTING clock_runningFlags &= ~CLOCK_FLAGADJUSTING
74 
78 #define CLOCK_GETCALLTICK clock_runningFlags & CLOCK_FLAGCALLTICK
79 
82 #define CLOCK_SETCALLTICK clock_runningFlags |= CLOCK_FLAGCALLTICK
83 
86 #define CLOCK_CLEARCALLTICK clock_runningFlags &= ~CLOCK_FLAGCALLTICK
87 
88 /*
89  * ======== Types ========
90  */
91 
92 /*
93  * ======== Global Variables ========
94  */
95 
103 
104 /*
105  * ======== Local Variables ========
106  */
107 
112 
117 
125 
133 
134 /*
135  * ======== Local Functions ========
136  */
137 
138 /*
139  * ================
140  */
141 
148 void clock_init() {
150 
151  P2OUT &= ~BIT2;
152 
153  clock_ticksSinceSint = 0xFFFF;
155  clock_time.seconds.secondsLow = 0;
156  clock_time.seconds.secondsHigh = 0;
157  clock_time.nanoSeconds = 0;
161 
163 }
164 
171 void clock_tick() {
172  if (CLOCK_GETADJUSTING) { // If clock is adjusting, do not count tick and set to call again later
174  return;
175  }
176  clock_time.nanoSeconds += clock_tickSize;
177  if (clock_time.nanoSeconds >= CLOCK_NS_IN_ONE_S) {
178  clock_time.nanoSeconds -= CLOCK_NS_IN_ONE_S;
179  clock_time.seconds.secondsLow += 1;
180  if (!clock_time.seconds.secondsLow) {
181  clock_time.seconds.secondsHigh += 1;
182  }
183 
184  // Square wave for measurements, 0 for even s, 1 for odd s.
185  if (clock_time.seconds.secondsLow & 0x01) {
186  P2OUT |= BIT2;
187  } else {
188  P2OUT &= ~BIT2;
189  }
190 
191  }
192  if (clock_ticksSinceSint != 0xFFFF)
194 }
195 
203  if (CLOCK_GETCALLTICK) {
205  clock_tick();
206  }
207 }
208 
220  destTime->nanoSeconds = clock_time.nanoSeconds;
221  destTime->seconds.secondsLow = clock_time.seconds.secondsLow;
222  destTime->seconds.secondsHigh = clock_time.seconds.secondsHigh;
225 }
226 
237 void clock_setTime(clock_timeStamp *sourceTime) {
239  clock_time.seconds.secondsLow = sourceTime->seconds.secondsLow;
240  clock_time.seconds.secondsHigh = sourceTime->seconds.secondsHigh;
241  clock_time.nanoSeconds = sourceTime->nanoSeconds;
244 }
245 
256 void clock_adjTime(int64_t *adjValue) {
257  Int32 tickAdj;
258 
259  if (clock_ticksSinceSint == 0xFFFF) {
260  clock_ticksSinceSint = 0; // begin adjust cycle
262  } else {
263  if ((((*adjValue) < 3000000000) // if adjust is not too big
264  && (-(*adjValue) < 3000000000))) {
265  clock_adjSumSinceSint += *adjValue; // add this adjust to the sum
266 
267  if ((clock_ticksSinceSint & 0x8000)
268  || ((!(clock_adjSumSinceSint & 0x8000000000000000)) // positive
269  && (clock_adjSumSinceSint & 0x0000000200000000)) // more than half
270  || ((clock_adjSumSinceSint & 0x8000000000000000) // negative
271  && !(clock_adjSumSinceSint & 0xfffffffe00000000))) {
272  // after more than half capacity of the counter or the adjust, for better precision
273  if (clock_adjSumSinceSint) { // But not if the current adjust is 0
274  // The adjust is the error divided by the number of ticks since last syntonization.
275  // the >> 2 and << 2 makes possible a 32bits arithmetics and serves as a tolerance,
276  // no adjust is done if precision is (2^2)ns or better per tick.
277  // the limitation is that the adjust can not be larger than ~17s.
278  tickAdj = clock_adjSumSinceSint >> 2;
279  tickAdj /= clock_ticksSinceSint;
280  tickAdj <<= 2;
281  clock_adjTick(tickAdj);
282  }
283  clock_ticksSinceSint = 0xFFFF; // reset tick adjust
284  }
285  } else { // adjust is too big
286  clock_ticksSinceSint = 0xFFFF; // reset tick adjust
287  }
288  }
289 
290  // adjust the time
291  clock_adjTimeValues(adjValue, &clock_time);
292 }
293 
304 void clock_adjTimeValues(int64_t *adjValue, clock_timeStamp *time) {
305  int64_t adjSeconds = 0;
306  Int32 adjNanoseconds;
307  int64_t tmpInt64;
308 
309  // range check - Value cannot be larger than (+ or -) (2^31) seconds, that is ~ 68 years
310  if ((*adjValue >= 2147483647000000000)
311  || (*adjValue < -2147483648000000000))
312  return;
313 
314  if (*adjValue) {
315  // If adjValueis less than 32s, avoid division and multiplication, use while inside else
316  // Thats because the while loop will use about 96 c lines on the worst
317  // case, and the division by itself will use 88 c lines all the times.
318  if (((*adjValue > 0) && (((*adjValue) >> 5) >= CLOCK_NS_IN_ONE_S))
319  || ((*adjValue < 0)
320  && (((-*adjValue) >> 5) >= CLOCK_NS_IN_ONE_S))) {
321  // adjSeconds = *adjValue / CLOCK_NS_IN_ONE_S;
322  // Horner's Method, slaa329
323  // adjSeconds = *adjValue * 1 / CLOCK_NS_IN_ONE_S;
324  // 1/CLOCK_NS_IN_ONE_S =
325  // .00000000000000000000000000000100010010111000001011111010000010011011010110100101001011001011100110001011010000000101010001000111b ->
326  // .0000000000000000000000000000010001001100-100000110000-1010000010011011010110100101001011001100-10011000101101000000010101000100100-1csd
327  // csd would cause complications to subtraction/shift right, it could be done with an arithmetic shift right
328  adjSeconds = *adjValue;
329  adjSeconds >>= 1;
330  adjSeconds += *adjValue;
331  adjSeconds >>= 1;
332  adjSeconds += *adjValue;
333  adjSeconds >>= 4;
334  adjSeconds += *adjValue;
335  adjSeconds >>= 4;
336  adjSeconds += *adjValue;
337  adjSeconds >>= 2;
338  adjSeconds += *adjValue;
339  adjSeconds >>= 2;
340  adjSeconds += *adjValue;
341  adjSeconds >>= 8;
342  adjSeconds += *adjValue;
343  adjSeconds >>= 2;
344  adjSeconds += *adjValue;
345  adjSeconds >>= 1;
346  adjSeconds += *adjValue;
347  adjSeconds >>= 2;
348  adjSeconds += *adjValue;
349  adjSeconds >>= 4;
350  adjSeconds += *adjValue;
351  adjSeconds >>= 1;
352  adjSeconds += *adjValue;
353  adjSeconds >>= 3;
354  adjSeconds += *adjValue;
355  adjSeconds >>= 1;
356  adjSeconds += *adjValue;
357  adjSeconds >>= 1;
358  adjSeconds += *adjValue;
359  adjSeconds >>= 2;
360  adjSeconds += *adjValue;
361  adjSeconds >>= 3;
362  adjSeconds += *adjValue;
363  adjSeconds >>= 1;
364  adjSeconds += *adjValue;
365  adjSeconds >>= 2;
366  adjSeconds += *adjValue;
367  adjSeconds >>= 3;
368  adjSeconds += *adjValue;
369  adjSeconds >>= 2;
370  adjSeconds += *adjValue;
371  adjSeconds >>= 3;
372  adjSeconds += *adjValue;
373  adjSeconds >>= 2;
374  adjSeconds += *adjValue;
375  adjSeconds >>= 1;
376  adjSeconds += *adjValue;
377  adjSeconds >>= 2;
378  adjSeconds += *adjValue;
379  adjSeconds >>= 2;
380  adjSeconds += *adjValue;
381  adjSeconds >>= 1;
382  adjSeconds += *adjValue;
383  adjSeconds >>= 2;
384  adjSeconds += *adjValue;
385  adjSeconds >>= 1;
386  adjSeconds += *adjValue;
387  adjSeconds >>= 3;
388  adjSeconds += *adjValue;
389  adjSeconds >>= 6;
390  adjSeconds += *adjValue;
391  adjSeconds >>= 2;
392  adjSeconds += *adjValue;
393  adjSeconds >>= 1;
394  adjSeconds += *adjValue;
395  adjSeconds >>= 1;
396  adjSeconds += *adjValue;
397  adjSeconds >>= 1;
398  adjSeconds += *adjValue;
399  adjSeconds >>= 1;
400  adjSeconds += *adjValue;
401  adjSeconds >>= 2;
402  adjSeconds += *adjValue;
403  adjSeconds >>= 6;
404  adjSeconds += *adjValue;
405  adjSeconds >>= 1;
406  adjSeconds += *adjValue;
407  adjSeconds >>= 1;
408  adjSeconds += *adjValue;
409  adjSeconds >>= 2;
410  adjSeconds += *adjValue;
411  adjSeconds >>= 3;
412  adjSeconds += *adjValue;
413  adjSeconds >>= 4;
414  adjSeconds += *adjValue;
415  adjSeconds >>= 30;
416 
417  // get the seconds part in ns. (ns = s * 1e9)
418  tmpInt64 = adjSeconds;
419  tmpInt64 <<= 4;
420  tmpInt64 -= adjSeconds;
421  tmpInt64 <<= 3;
422  tmpInt64 -= adjSeconds;
423  tmpInt64 <<= 3;
424  tmpInt64 += adjSeconds;
425  tmpInt64 <<= 1;
426  tmpInt64 += adjSeconds;
427  tmpInt64 <<= 2;
428  tmpInt64 += adjSeconds;
429  tmpInt64 <<= 2;
430  tmpInt64 += adjSeconds;
431  tmpInt64 <<= 1;
432  tmpInt64 += adjSeconds;
433  tmpInt64 <<= 3;
434  tmpInt64 += adjSeconds;
435  tmpInt64 <<= 2;
436  tmpInt64 += adjSeconds;
437  tmpInt64 <<= 9;
438 
439  adjNanoseconds = *adjValue - tmpInt64;
440  // The result of the division above has been 1 less than it should in several
441  // tests, the loops bellow must fix it.
442  // Number of seconds, calculated by loops
443  while (adjNanoseconds >= CLOCK_NS_IN_ONE_S) {
444  adjNanoseconds -= CLOCK_NS_IN_ONE_S;
445  adjSeconds += 1;
446  }
447  while (adjNanoseconds <= -CLOCK_NS_IN_ONE_S) {
448  adjNanoseconds += CLOCK_NS_IN_ONE_S;
449  adjSeconds -= 1;
450  }
451  } else {
452  adjSeconds = 0;
453  tmpInt64 = *adjValue;
454  while (tmpInt64 >= CLOCK_NS_IN_ONE_S) {
455  tmpInt64 -= CLOCK_NS_IN_ONE_S;
456  adjSeconds += 1;
457  }
458  while (tmpInt64 <= -CLOCK_NS_IN_ONE_S) {
459  tmpInt64 += CLOCK_NS_IN_ONE_S;
460  adjSeconds -= 1;
461  }
462  adjNanoseconds = tmpInt64;
463  }
464  // If adjusting the clock, begin adjusting phase
465  if (time == &clock_time) {
467  }
468  // Adjust seconds if != 0
469  if (adjSeconds) {
470  if (adjSeconds < 0) {
471  if (time->seconds.secondsLow < (UInt32) -adjSeconds)
472  time->seconds.secondsHigh -= 1;
473  time->seconds.secondsLow += adjSeconds;
474  } else {
475  time->seconds.secondsLow += adjSeconds;
476  if (time->seconds.secondsLow < (UInt32) adjSeconds)
477  time->seconds.secondsHigh += 1;
478  }
479  }
480  if ((adjNanoseconds < 0)
481  && (time->nanoSeconds < (UInt32) -adjNanoseconds)) {
482  if (!time->seconds.secondsLow)
483  time->seconds.secondsHigh -= 1;
484  time->seconds.secondsLow -= 1;
485  time->nanoSeconds += CLOCK_NS_IN_ONE_S + adjNanoseconds;
486  } else {
487  time->nanoSeconds += adjNanoseconds;
488  while (time->nanoSeconds >= CLOCK_NS_IN_ONE_S) {
489  time->seconds.secondsLow += 1;
490  if (!time->seconds.secondsLow)
491  time->seconds.secondsHigh += 1;
492  time->nanoSeconds -= CLOCK_NS_IN_ONE_S;
493  }
494  }
495  // if adjusting the clock, end adjusting phase
496  if (time == &clock_time) {
499  }
500  }
501 }
502 
511 void clock_adjTick(Int32 adjValue) {
512  if ((adjValue < 0) && (-adjValue >= clock_tickSize)) {
513  clock_tickSize = 1;
514  } else {
515  clock_tickSize += adjValue;
518  }
519  }
520 }
521 
534  int64_t r;
535  int64_t x;
536  if (t2->seconds.secondsHigh != t1->seconds.secondsHigh) {
537  r = -t1->seconds.secondsHigh;
538  r += t2->seconds.secondsHigh;
539  r <<= 32;
540  } else {
541  r = 0;
542  }
543  r -= t1->seconds.secondsLow;
544  r += t2->seconds.secondsLow; // r unit is s.
545  // On values within less than 1s delay, on transition from one second to another the
546  // subtraction may result in 1 or -1, avoid multiplication if able.
547  if (r == 1)
548  r = 1000000000;
549  else if (r == -1)
550  r = -1000000000;
551  else if (r) { // if not zero
552  // r *= 1e9;
553  // Horner's Method, slaa329
554  // r * 1000000000; 1000000000 = 111011100110101100101000000000b ->
555  // -> 1000-100-100110101100101000000000csd
556  x = r;
557  r <<= 4;
558  r -= x;
559  r <<= 3;
560  r -= x;
561  r <<= 3;
562  r += x;
563  r <<= 1;
564  r += x;
565  r <<= 2;
566  r += x;
567  r <<= 2;
568  r += x;
569  r <<= 1;
570  r += x;
571  r <<= 3;
572  r += x;
573  r <<= 2;
574  r += x;
575  r <<= 9;
576  }
577  // now r unit is ns.
578  r -= t1->nanoSeconds;
579  r += t2->nanoSeconds; // add ns fields to r.
580  return r;
581 }
582 
#define CLOCK_GETADJUSTING
Macro to test if clock is adjusting.
Definition: clock.c:65
void clock_adjTimeValues(int64_t *adjValue, clock_timeStamp *time)
Adjust time values.
Definition: clock.c:304
int64_t clock_adjSumSinceSint
Adjust sum since Sintonization.
Definition: clock.c:132
Interruption management (enable/disable) interface.
void clock_tick()
Clock tick.
Definition: clock.c:171
#define CLOCK_TICK_SIZE_MAX
Maximum value that tick size can be adjusted to (ns).
Definition: clock.c:43
#define CLOCK_SETADJUSTING
Macro to set adjusting flag.
Definition: clock.c:69
UInt32 clock_tickSize
Tick size (ns)
Definition: clock.c:102
Time stamp.
Definition: clock.h:75
Clock interface.
void im_disable_interrupt()
Disable interrupt.
Definition: im.c:162
void clock_init()
Clock Initialization.
Definition: clock.c:148
#define CLOCK_DEFAULT_TICK_SIZE
Default tick size (ns) this may be changed as needed by the application.
Definition: clock.c:39
void im_enable_interrupt()
Enable interrupt.
Definition: im.c:222
#define CLOCK_CLEARADJUSTING
Macro to clear adjusting flag.
Definition: clock.c:73
clock_timeStamp clock_time
Clock time.
Definition: clock.c:111
UInt16 clock_ticksSinceSint
Ticks since Sintonization.
Definition: clock.c:124
void clock_adjTick(Int32 adjValue)
Adjust tick.
Definition: clock.c:511
int64_t clock_timeDiff(clock_timeStamp *t1, clock_timeStamp *t2)
Time difference.
Definition: clock.c:533
UInt8 clock_runningFlags
Flags for internal use.
Definition: clock.c:116
#define CLOCK_GETCALLTICK
Macro to test if clock delayed tick is set.
Definition: clock.c:78
#define CLOCK_CLEARCALLTICK
Macro to clear delayed tick flag.
Definition: clock.c:86
void clock_checkDelayedTick()
Check delayed tick.
Definition: clock.c:202
#define CLOCK_NS_IN_ONE_S
Alias to avoid mistyping.
Definition: clock.c:47
#define CLOCK_SETCALLTICK
Macro to set delayed tick flag.
Definition: clock.c:82
void clock_setTime(clock_timeStamp *sourceTime)
Set time.
Definition: clock.c:237
void clock_adjTime(int64_t *adjValue)
Adjust time.
Definition: clock.c:256
void clock_getTime(clock_timeStamp *destTime)
Get time.
Definition: clock.c:218