/
utils.h
208 lines (187 loc) · 5.15 KB
/
utils.h
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/*
* atMETEO - An ATmega based weather station
* Copyright (C) 2014-2015 Christian Fetzer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
/*!
* \defgroup libsensors_utils Utilities
* \ingroup libsensors
*
* \brief Bit manipulation utilities.
*
* \note All functions are kept as small as possible allowing inlining.
*/
/*!
* \file
* \ingroup libsensors_utils
* \copydoc libsensors_utils
*/
#include <inttypes.h> // AVR toolchain doesn't offer cinttypes header
namespace Sensors
{
/*!
* \addtogroup libsensors_utils
* \{
*/
/*!
* \brief Sets the \p bit in the given \p value to `1`.
* \tparam T Data type of the \p value to operate on.
* \param value Memory location of the \p value where the bit should be set.
* \param bit Bit position within the \p value.
*/
template <typename T>
inline void bitSet(T &value, uint8_t bit)
{
value |= (1 << bit);
}
/*!
* \brief Sets the \p bit in the given \p value to `0`.
* \tparam T Data type of the \p value to operate on.
* \param value Memory location of the \p value where the bit should be
* cleared.
* \param bit Bit position within the \p value.
*/
template <typename T>
inline void bitClear(T &value, uint8_t bit)
{
value &= ~(1 << bit);
}
/*!
* \brief Flips the \p bit in the given \p value.
* \tparam T Data type of the \p value to operate on.
* \param value Memory location of the \p value where bit should be flipped.
* \param bit Bit position within the \p value.
*/
template <typename T>
inline void bitFlip(T &value, uint8_t bit)
{
value ^= (1 << bit);
}
/*!
* \brief Returns the \p bit in the given \p value.
* \tparam T Data type of the \p value to operate on.
* \param value Memory location of the \p value where the bit should be read.
* \param bit Bit position within the \p value.
* \return Specified bit in the given \p value.
*/
template <typename T>
inline bool bitRead(T &value, uint8_t bit)
{
return (value >> bit) & 0x01;
}
/*!
* \brief Writes the \p bit in the given \p value.
* \tparam T Data type of the \p value to operate on.
* \param value Memory location of the \p value where the bit should be
* written.
* \param bit Number of the bit to write.
* \param bitValue Value to write into bit position.
*/
template <typename T>
inline void bitWrite(T &value, uint8_t bit, bool bitValue)
{
bitValue ? bitSet(value, bit) : bitClear(value, bit);
}
/*!
* \brief Returns the byte \p x in reversed bit order.
* \param x The input byte.
* \return Byte with bits reversed.
*/
inline uint8_t byteReverse(uint8_t x)
{
x = ((x >> 1) & 0x55) | ((x << 1) & 0xaa);
x = ((x >> 2) & 0x33) | ((x << 2) & 0xcc);
x = ((x >> 4) & 0x0f) | ((x << 4) & 0xf0);
return x;
}
/*!
* \brief Returns the byte \p x in reversed bit order (nibble wise).
* \param x The input byte.
* \return Byte with bits nibble wise reversed.
*/
inline uint8_t nibbleReverse(uint8_t x)
{
x = byteReverse(x);
x = ((x >> 4) & 0x0F) | ((x << 4) & 0xF0);
return x;
}
/*!
* \brief Returns the byte's \p x high nibble.
* \param x The input byte.
* \return High nibble of byte \p x.
*/
inline uint8_t highNibble(uint8_t x)
{
return x >> 4;
}
/*!
* \brief Returns the byte's \p x low nibble.
* \param x The input byte.
* \return Low nibble of byte \p x.
*/
inline uint8_t lowNibble(uint8_t x)
{
return x & 0x0F;
}
/*!
* \brief Converts two bytes to a word.
* \param highByte The leftmost byte of the word.
* \param lowByte The rightmost byte of the word.
* \return Word from \p highByte and \p lowByte.
*/
inline uint16_t word(uint8_t highByte, uint8_t lowByte)
{
return highByte << 8 | lowByte;
}
/*!
* \brief Returns the even parity for the byte \p x.
*
* Even parity: Number of set bits modulo 2.
*
* \param x The input byte.
* \return Even parity for the byte \p x.
*/
inline bool parity(int x)
{
return __builtin_parity(x);
}
/*!
* \brief Returns the minimum of the two values \p a and \p b.
* \tparam T Data type of the values to operate on.
* \param a First value.
* \param b Second value.
* \return Minimum of the two values \p a and \p b.
*/
template<typename T>
inline T min(T a, T b)
{
return a < b ? a : b;
}
/*!
* \brief Returns the maximum of the two values \p a and \p b.
* \tparam T Data type of the values to operate on.
* \param a First value.
* \param b Second value.
* \return Maximum of the two values \p a and \p b.
*/
template<typename T>
inline T max(T a, T b)
{
return a > b ? a : b;
}
/*! \} */ // \addtogroup libsensors_utils
} // namespace Sensors