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