Blame view

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