Add missing SVN eol-style property to files where it was missing.
[pub/USBasp.git] / LUFA / Common / Endianness.h
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2011.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29 */
30
31 /** \file
32 * \brief Endianness and Byte Ordering macros and functions.
33 *
34 * \copydetails Group_Endianness
35 */
36
37 /** \ingroup Group_Endianness
38 * \defgroup Group_ByteSwapping Byte Reordering
39 * \brief Macros and functions for forced byte reordering.
40 */
41
42 /** \ingroup Group_Endianness
43 * \defgroup Group_EndianConversion Endianness Conversion
44 * \brief Macros and functions for automatic endianness conversion.
45 */
46
47 /** \ingroup Group_Common
48 * \defgroup Group_Endianness Endianness and Byte Ordering
49 * \brief Convenience macros and functions relating to byte (re-)ordering
50 *
51 * Common library convenience macros and functions relating to byte (re-)ordering.
52 *
53 * @{
54 */
55
56 #ifndef __LUFA_ENDIANNESS_H__
57 #define __LUFA_ENDIANNESS_H__
58
59 /* Preprocessor Checks: */
60 #if !defined(__INCLUDE_FROM_COMMON_H)
61 #error Do not include this file directly. Include LUFA/Common/Common.h instead to gain this functionality.
62 #endif
63
64 #if !(defined(ARCH_BIG_ENDIAN) || defined(ARCH_LITTLE_ENDIAN))
65 #error ARCH_BIG_ENDIAN or ARCH_LITTLE_ENDIAN not set for the specified architecture.
66 #endif
67
68 /* Public Interface - May be used in end-application: */
69 /* Macros: */
70 /** Swaps the byte ordering of a 16-bit value at compile-time. Do not use this macro for swapping byte orderings
71 * of dynamic values computed at runtime, use \ref SwapEndian_16() instead. The result of this macro can be used
72 * inside struct or other variable initializers outside of a function, something that is not possible with the
73 * inline function variant.
74 *
75 * \ingroup Group_ByteSwapping
76 *
77 * \param[in] x 16-bit value whose byte ordering is to be swapped.
78 *
79 * \return Input value with the byte ordering reversed.
80 */
81 #define SWAPENDIAN_16(x) (uint16_t)((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8))
82
83 /** Swaps the byte ordering of a 32-bit value at compile-time. Do not use this macro for swapping byte orderings
84 * of dynamic values computed at runtime- use \ref SwapEndian_32() instead. The result of this macro can be used
85 * inside struct or other variable initializers outside of a function, something that is not possible with the
86 * inline function variant.
87 *
88 * \ingroup Group_ByteSwapping
89 *
90 * \param[in] x 32-bit value whose byte ordering is to be swapped.
91 *
92 * \return Input value with the byte ordering reversed.
93 */
94 #define SWAPENDIAN_32(x) (uint32_t)((((x) & 0xFF000000UL) >> 24UL) | (((x) & 0x00FF0000UL) >> 8UL) | \
95 (((x) & 0x0000FF00UL) << 8UL) | (((x) & 0x000000FFUL) << 24UL))
96
97 #if defined(ARCH_BIG_ENDIAN) && !defined(le16_to_cpu)
98 #define le16_to_cpu(x) SwapEndian_16(x)
99 #define le32_to_cpu(x) SwapEndian_32(x)
100 #define be16_to_cpu(x) x
101 #define be32_to_cpu(x) x
102 #define cpu_to_le16(x) SwapEndian_16(x)
103 #define cpu_to_le32(x) SwapEndian_32(x)
104 #define cpu_to_be16(x) x
105 #define cpu_to_be32(x) x
106 #define LE16_TO_CPU(x) SWAPENDIAN_16(x)
107 #define LE32_TO_CPU(x) SWAPENDIAN_32(x)
108 #define BE16_TO_CPU(x) x
109 #define BE32_TO_CPU(x) x
110 #define CPU_TO_LE16(x) SWAPENDIAN_16(x)
111 #define CPU_TO_LE32(x) SWAPENDIAN_32(x)
112 #define CPU_TO_BE16(x) x
113 #define CPU_TO_BE32(x) x
114 #elif !defined(le16_to_cpu)
115 /** \name Run-time endianness conversion */
116 //@{
117
118 /** Performs a conversion between a Little Endian encoded 16-bit piece of data and the
119 * Endianness of the currently selected CPU architecture.
120 *
121 * On little endian architectures, this macro does nothing.
122 *
123 * \note This macro is designed for run-time conversion of data - for compile-time endianness
124 * conversion, use \ref LE16_TO_CPU instead.
125 *
126 * \ingroup Group_EndianConversion
127 *
128 * \param[in] x Data to perform the endianness conversion on.
129 *
130 * \return Endian corrected version of the input value.
131 */
132 #define le16_to_cpu(x) x
133
134 /** Performs a conversion between a Little Endian encoded 32-bit piece of data and the
135 * Endianness of the currently selected CPU architecture.
136 *
137 * On little endian architectures, this macro does nothing.
138 *
139 * \note This macro is designed for run-time conversion of data - for compile-time endianness
140 * conversion, use \ref LE32_TO_CPU instead.
141 *
142 * \ingroup Group_EndianConversion
143 *
144 * \param[in] x Data to perform the endianness conversion on.
145 *
146 * \return Endian corrected version of the input value.
147 */
148 #define le32_to_cpu(x) x
149
150 /** Performs a conversion between a Big Endian encoded 16-bit piece of data and the
151 * Endianness of the currently selected CPU architecture.
152 *
153 * On big endian architectures, this macro does nothing.
154 *
155 * \note This macro is designed for run-time conversion of data - for compile-time endianness
156 * conversion, use \ref BE16_TO_CPU instead.
157 *
158 * \ingroup Group_EndianConversion
159 *
160 * \param[in] x Data to perform the endianness conversion on.
161 *
162 * \return Endian corrected version of the input value.
163 */
164 #define be16_to_cpu(x) SwapEndian_16(x)
165
166 /** Performs a conversion between a Big Endian encoded 32-bit piece of data and the
167 * Endianness of the currently selected CPU architecture.
168 *
169 * On big endian architectures, this macro does nothing.
170 *
171 * \note This macro is designed for run-time conversion of data - for compile-time endianness
172 * conversion, use \ref BE32_TO_CPU instead.
173 *
174 * \ingroup Group_EndianConversion
175 *
176 * \param[in] x Data to perform the endianness conversion on.
177 *
178 * \return Endian corrected version of the input value.
179 */
180 #define be32_to_cpu(x) SwapEndian_32(x)
181
182 /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
183 * is in Little Endian format regardless of the currently selected CPU architecture.
184 *
185 * On little endian architectures, this macro does nothing.
186 *
187 * \note This macro is designed for run-time conversion of data - for compile-time endianness
188 * conversion, use \ref CPU_TO_LE16 instead.
189 *
190 * \ingroup Group_EndianConversion
191 *
192 * \param[in] x Data to perform the endianness conversion on.
193 *
194 * \return Endian corrected version of the input value.
195 */
196 #define cpu_to_le16(x) x
197
198 /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
199 * is in Little Endian format regardless of the currently selected CPU architecture.
200 *
201 * On little endian architectures, this macro does nothing.
202 *
203 * \note This macro is designed for run-time conversion of data - for compile-time endianness
204 * conversion, use \ref CPU_TO_LE32 instead.
205 *
206 * \ingroup Group_EndianConversion
207 *
208 * \param[in] x Data to perform the endianness conversion on.
209 *
210 * \return Endian corrected version of the input value.
211 */
212 #define cpu_to_le32(x) x
213
214 /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
215 * is in Big Endian format regardless of the currently selected CPU architecture.
216 *
217 * On big endian architectures, this macro does nothing.
218 *
219 * \note This macro is designed for run-time conversion of data - for compile-time endianness
220 * conversion, use \ref CPU_TO_BE16 instead.
221 *
222 * \ingroup Group_EndianConversion
223 *
224 * \param[in] x Data to perform the endianness conversion on.
225 *
226 * \return Endian corrected version of the input value.
227 */
228 #define cpu_to_be16(x) SwapEndian_16(x)
229
230 /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
231 * is in Big Endian format regardless of the currently selected CPU architecture.
232 *
233 * On big endian architectures, this macro does nothing.
234 *
235 * \note This macro is designed for run-time conversion of data - for compile-time endianness
236 * conversion, use \ref CPU_TO_BE32 instead.
237 *
238 * \ingroup Group_EndianConversion
239 *
240 * \param[in] x Data to perform the endianness conversion on.
241 *
242 * \return Endian corrected version of the input value.
243 */
244 #define cpu_to_be32(x) SwapEndian_32(x)
245
246 //@}
247
248 /** \name Compile-time endianness conversion */
249 //@{
250
251 /** Performs a conversion between a Little Endian encoded 16-bit piece of data and the
252 * Endianness of the currently selected CPU architecture.
253 *
254 * On little endian architectures, this macro does nothing.
255 *
256 * \note This macro is designed for compile-time conversion of data - for run time endianness
257 * conversion, use \ref le16_to_cpu instead.
258 *
259 * \ingroup Group_EndianConversion
260 *
261 * \param[in] x Data to perform the endianness conversion on.
262 *
263 * \return Endian corrected version of the input value.
264 */
265 #define LE16_TO_CPU(x) x
266
267 /** Performs a conversion between a Little Endian encoded 32-bit piece of data and the
268 * Endianness of the currently selected CPU architecture.
269 *
270 * On little endian architectures, this macro does nothing.
271 *
272 * \note This macro is designed for compile-time conversion of data - for run time endianness
273 * conversion, use \ref le32_to_cpu instead.
274 *
275 * \ingroup Group_EndianConversion
276 *
277 * \param[in] x Data to perform the endianness conversion on.
278 *
279 * \return Endian corrected version of the input value.
280 */
281 #define LE32_TO_CPU(x) x
282
283 /** Performs a conversion between a Big Endian encoded 16-bit piece of data and the
284 * Endianness of the currently selected CPU architecture.
285 *
286 * On big endian architectures, this macro does nothing.
287 *
288 * \note This macro is designed for compile-time conversion of data - for run-time endianness
289 * conversion, use \ref be16_to_cpu instead.
290 *
291 * \ingroup Group_EndianConversion
292 *
293 * \param[in] x Data to perform the endianness conversion on.
294 *
295 * \return Endian corrected version of the input value.
296 */
297 #define BE16_TO_CPU(x) SWAPENDIAN_16(x)
298
299 /** Performs a conversion between a Big Endian encoded 32-bit piece of data and the
300 * Endianness of the currently selected CPU architecture.
301 *
302 * On big endian architectures, this macro does nothing.
303 *
304 * \note This macro is designed for compile-time conversion of data - for run-time endianness
305 * conversion, use \ref be32_to_cpu instead.
306 *
307 * \ingroup Group_EndianConversion
308 *
309 * \param[in] x Data to perform the endianness conversion on.
310 *
311 * \return Endian corrected version of the input value.
312 */
313 #define BE32_TO_CPU(x) SWAPENDIAN_32(x)
314
315 /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
316 * is in Little Endian format regardless of the currently selected CPU architecture.
317 *
318 * On little endian architectures, this macro does nothing.
319 *
320 * \note This macro is designed for compile-time conversion of data - for run-time endianness
321 * conversion, use \ref cpu_to_le16 instead.
322 *
323 * \ingroup Group_EndianConversion
324 *
325 * \param[in] x Data to perform the endianness conversion on.
326 *
327 * \return Endian corrected version of the input value.
328 */
329 #define CPU_TO_LE16(x) x
330
331 /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
332 * is in Little Endian format regardless of the currently selected CPU architecture.
333 *
334 * On little endian architectures, this macro does nothing.
335 *
336 * \note This macro is designed for compile-time conversion of data - for run-time endianness
337 * conversion, use \ref cpu_to_le32 instead.
338 *
339 * \ingroup Group_EndianConversion
340 *
341 * \param[in] x Data to perform the endianness conversion on.
342 *
343 * \return Endian corrected version of the input value.
344 */
345 #define CPU_TO_LE32(x) x
346
347 /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
348 * is in Big Endian format regardless of the currently selected CPU architecture.
349 *
350 * On big endian architectures, this macro does nothing.
351 *
352 * \note This macro is designed for compile-time conversion of data - for run-time endianness
353 * conversion, use \ref cpu_to_be16 instead.
354 *
355 * \ingroup Group_EndianConversion
356 *
357 * \param[in] x Data to perform the endianness conversion on.
358 *
359 * \return Endian corrected version of the input value.
360 */
361 #define CPU_TO_BE16(x) SWAPENDIAN_16(x)
362
363 /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
364 * is in Big Endian format regardless of the currently selected CPU architecture.
365 *
366 * On big endian architectures, this macro does nothing.
367 *
368 * \note This macro is designed for compile-time conversion of data - for run-time endianness
369 * conversion, use \ref cpu_to_be32 instead.
370 *
371 * \ingroup Group_EndianConversion
372 *
373 * \param[in] x Data to perform the endianness conversion on.
374 *
375 * \return Endian corrected version of the input value.
376 */
377 #define CPU_TO_BE32(x) SWAPENDIAN_32(x)
378
379 //! @}
380 #endif
381
382 /* Inline Functions: */
383 /** Function to reverse the byte ordering of the individual bytes in a 16 bit value.
384 *
385 * \ingroup Group_ByteSwapping
386 *
387 * \param[in] Word Word of data whose bytes are to be swapped.
388 */
389 static inline uint16_t SwapEndian_16(const uint16_t Word) ATTR_WARN_UNUSED_RESULT ATTR_CONST;
390 static inline uint16_t SwapEndian_16(const uint16_t Word)
391 {
392 uint8_t Temp;
393
394 union
395 {
396 uint16_t Word;
397 uint8_t Bytes[2];
398 } Data;
399
400 Data.Word = Word;
401
402 Temp = Data.Bytes[0];
403 Data.Bytes[0] = Data.Bytes[1];
404 Data.Bytes[1] = Temp;
405
406 return Data.Word;
407 }
408
409 /** Function to reverse the byte ordering of the individual bytes in a 32 bit value.
410 *
411 * \ingroup Group_ByteSwapping
412 *
413 * \param[in] DWord Double word of data whose bytes are to be swapped.
414 */
415 static inline uint32_t SwapEndian_32(const uint32_t DWord) ATTR_WARN_UNUSED_RESULT ATTR_CONST;
416 static inline uint32_t SwapEndian_32(const uint32_t DWord)
417 {
418 uint8_t Temp;
419
420 union
421 {
422 uint32_t DWord;
423 uint8_t Bytes[4];
424 } Data;
425
426 Data.DWord = DWord;
427
428 Temp = Data.Bytes[0];
429 Data.Bytes[0] = Data.Bytes[3];
430 Data.Bytes[3] = Temp;
431
432 Temp = Data.Bytes[1];
433 Data.Bytes[1] = Data.Bytes[2];
434 Data.Bytes[2] = Temp;
435
436 return Data.DWord;
437 }
438
439 /** Function to reverse the byte ordering of the individual bytes in a n byte value.
440 *
441 * \ingroup Group_ByteSwapping
442 *
443 * \param[in,out] Data Pointer to a number containing an even number of bytes to be reversed.
444 * \param[in] Length Length of the data in bytes.
445 */
446 static inline void SwapEndian_n(void* const Data,
447 uint8_t Length) ATTR_NON_NULL_PTR_ARG(1);
448 static inline void SwapEndian_n(void* const Data,
449 uint8_t Length)
450 {
451 uint8_t* CurrDataPos = (uint8_t*)Data;
452
453 while (Length > 1)
454 {
455 uint8_t Temp = *CurrDataPos;
456 *CurrDataPos = *(CurrDataPos + Length - 1);
457 *(CurrDataPos + Length - 1) = Temp;
458
459 CurrDataPos++;
460 Length -= 2;
461 }
462 }
463
464 #endif
465
466 /** @} */