Loading...
Searching...
No Matches
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
16
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
24extern "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 */
38static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
39 return (usec << XTIMER_SHIFT); /* multiply by power of two */
40}
41
42static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
43 return (usec << XTIMER_SHIFT); /* multiply by power of two */
44}
45
46static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
47 return (ticks >> XTIMER_SHIFT); /* divide by power of two */
48}
49
50static 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 */
60static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
61 return (usec >> XTIMER_SHIFT); /* divide by power of two */
62}
63
64static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
65 return (usec >> XTIMER_SHIFT); /* divide by power of two */
66}
67
68static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
69 return (ticks << XTIMER_SHIFT); /* multiply by power of two */
70}
71
72static 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. */
79static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
80 return ticks; /* no-op */
81}
82
83static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) {
84 return ticks; /* no-op */
85}
86
87static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
88 return usec; /* no-op */
89}
90
91static 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 */
100static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
101 return div_u32_by_15625div512(usec);
102}
103
104static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
105 return div_u64_by_15625div512(usec);
106}
107
108static 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
115static 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:641