Loading...
Searching...
No Matches
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
28extern "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 */
42static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
43 return (usec << XTIMER_SHIFT); /* multiply by power of two */
44}
45
46static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
47 return (usec << XTIMER_SHIFT); /* multiply by power of two */
48}
49
50static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
51 return (ticks >> XTIMER_SHIFT); /* divide by power of two */
52}
53
54static 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 */
64static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
65 return (usec >> XTIMER_SHIFT); /* divide by power of two */
66}
67
68static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
69 return (usec >> XTIMER_SHIFT); /* divide by power of two */
70}
71
72static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
73 return (ticks << XTIMER_SHIFT); /* multiply by power of two */
74}
75
76static 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. */
83static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
84 return ticks; /* no-op */
85}
86
87static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) {
88 return ticks; /* no-op */
89}
90
91static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
92 return usec; /* no-op */
93}
94
95static 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 */
104static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
105 return div_u32_by_15625div512(usec);
106}
107
108static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
109 return div_u64_by_15625div512(usec);
110}
111
112static 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
119static 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 */
static uint32_t div_u32_by_15625div512(uint32_t val)
Divide val by (15625/512)
Definition div.h:130
static uint64_t div_u64_by_15625div512(uint64_t val)
Divide val by (15625/512)
Definition div.h:144
#define XTIMER_SHIFT
xtimer prescaler value
Definition xtimer.h:655