tick_conversion.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016 Eistec AB
3  *
4  * This file is subject to the terms and conditions of the GNU Lesser
5  * General Public License v2.1. See the file LICENSE in the top level
6  * directory for more details.
7  */
8 
18 #ifndef XTIMER_TICK_CONVERSION_H
19 #define XTIMER_TICK_CONVERSION_H
20 
21 #ifndef XTIMER_H
22 #error "Do not include this file directly! Use xtimer.h instead"
23 #endif
24 
25 #include "div.h"
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 /* Some optimizations for common timer frequencies */
32 #if (XTIMER_SHIFT != 0)
33 #if (XTIMER_HZ % 15625 != 0)
34 #error XTIMER_HZ must be a multiple of 15625 (5^6) when using XTIMER_SHIFT
35 #endif
36 #if (XTIMER_HZ > 1000000ul)
37 #if (XTIMER_HZ != (1000000ul << XTIMER_SHIFT))
38 #error XTIMER_HZ != (1000000ul << XTIMER_SHIFT)
39 #endif
40 /* XTIMER_HZ is a power-of-two multiple of 1 MHz */
41 /* e.g. cc2538 uses a 16 MHz timer */
42 static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
43  return (usec << XTIMER_SHIFT); /* multiply by power of two */
44 }
45 
46 static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
47  return (usec << XTIMER_SHIFT); /* multiply by power of two */
48 }
49 
50 static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
51  return (ticks >> XTIMER_SHIFT); /* divide by power of two */
52 }
53 
54 static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) {
55  return (ticks >> XTIMER_SHIFT); /* divide by power of two */
56 }
57 
58 #else /* !(XTIMER_HZ > 1000000ul) */
59 #if ((XTIMER_HZ << XTIMER_SHIFT) != 1000000ul)
60 #error (XTIMER_HZ << XTIMER_SHIFT) != 1000000ul
61 #endif
62 /* 1 MHz is a power-of-two multiple of XTIMER_HZ */
63 /* e.g. ATmega2560 uses a 250 kHz timer */
64 static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
65  return (usec >> XTIMER_SHIFT); /* divide by power of two */
66 }
67 
68 static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
69  return (usec >> XTIMER_SHIFT); /* divide by power of two */
70 }
71 
72 static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
73  return (ticks << XTIMER_SHIFT); /* multiply by power of two */
74 }
75 
76 static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) {
77  return (ticks << XTIMER_SHIFT); /* multiply by power of two */
78 }
79 #endif /* defined(XTIMER_SHIFT) && (XTIMER_SHIFT != 0) */
80 #elif (XTIMER_HZ == (1000000ul)) || defined(MODULE_XTIMER_ON_ZTIMER)
81 /* This is the most straightforward as the xtimer API is based around
82  * microseconds for representing time values. */
83 static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
84  return ticks; /* no-op */
85 }
86 
87 static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) {
88  return ticks; /* no-op */
89 }
90 
91 static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
92  return usec; /* no-op */
93 }
94 
95 static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
96  return usec; /* no-op */
97 }
98 
99 #elif XTIMER_HZ == (32768ul)
100 /* This is a common frequency for RTC crystals. We use the fact that the
101  * greatest common divisor between 32768 and 1000000 is 64, so instead of
102  * multiplying by the fraction (32768 / 1000000), we will instead use
103  * (512 / 15625), which reduces the truncation caused by the integer widths */
104 static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
105  return div_u32_by_15625div512(usec);
106 }
107 
108 static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
109  return div_u64_by_15625div512(usec);
110 }
111 
112 static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
113  /* return (usec * 15625) / 512; */
114  /* Using 64 bit multiplication to avoid truncating the top 9 bits */
115  uint64_t usec = (uint64_t)ticks * 15625ul;
116  return (usec >> 9); /* equivalent to (usec / 512) */
117 }
118 
119 static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) {
120  /* return (usec * 15625) / 512; */
121  uint64_t usec = (uint64_t)ticks * 15625ul;
122  return (usec >> 9); /* equivalent to (usec / 512) */
123 }
124 
125 #else
126 /* No matching implementation found, try to give meaningful error messages */
127 #if ((XTIMER_HZ % 15625) == 0)
128 #error Unsupported hardware timer frequency (XTIMER_HZ), missing XTIMER_SHIFT in board.h? See xtimer.h documentation for more info
129 #else
130 #error Unknown hardware timer frequency (XTIMER_HZ), check board.h and/or add an implementation in sys/include/xtimer/tick_conversion.h
131 #endif
132 #endif
133 
134 #ifdef __cplusplus
135 }
136 #endif
137 
138 #endif /* XTIMER_TICK_CONVERSION_H */
div.h
div_u64_by_15625div512
static uint64_t div_u64_by_15625div512(uint64_t val)
Divide val by (15625/512)
Definition: div.h:144
div_u32_by_15625div512
static uint32_t div_u32_by_15625div512(uint32_t val)
Divide val by (15625/512)
Definition: div.h:130