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