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
9#pragma once
10
19
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
27extern "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 */
41static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
42 return (usec << XTIMER_SHIFT); /* multiply by power of two */
43}
44
45static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
46 return (usec << XTIMER_SHIFT); /* multiply by power of two */
47}
48
49static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
50 return (ticks >> XTIMER_SHIFT); /* divide by power of two */
51}
52
53static 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 */
63static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
64 return (usec >> XTIMER_SHIFT); /* divide by power of two */
65}
66
67static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
68 return (usec >> XTIMER_SHIFT); /* divide by power of two */
69}
70
71static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
72 return (ticks << XTIMER_SHIFT); /* multiply by power of two */
73}
74
75static 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. */
82static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
83 return ticks; /* no-op */
84}
85
86static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) {
87 return ticks; /* no-op */
88}
89
90static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
91 return usec; /* no-op */
92}
93
94static 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 */
103static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
104 return div_u32_by_15625div512(usec);
105}
106
107static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
108 return div_u64_by_15625div512(usec);
109}
110
111static 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
118static 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