Statistics
| Branch: | Tag: | Revision:

root / LUFA / Common / Endianness.h @ 978b99e5

History | View | Annotate | Download (17.9 KB)

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
        /* Enable C linkage for C++ Compilers: */
60
                #if defined(__cplusplus)
61
                        extern "C" {
62
                #endif
63

    
64
        /* Preprocessor Checks: */
65
                #if !defined(__INCLUDE_FROM_COMMON_H)
66
                        #error Do not include this file directly. Include LUFA/Common/Common.h instead to gain this functionality.
67
                #endif
68
                
69
                #if !(defined(ARCH_BIG_ENDIAN) || defined(ARCH_LITTLE_ENDIAN))
70
                        #error ARCH_BIG_ENDIAN or ARCH_LITTLE_ENDIAN not set for the specified architecture.
71
                #endif
72

    
73
        /* Public Interface - May be used in end-application: */
74
                /* Macros: */
75
                        /** Swaps the byte ordering of a 16-bit value at compile-time. Do not use this macro for swapping byte orderings
76
                         *  of dynamic values computed at runtime, use \ref SwapEndian_16() instead. The result of this macro can be used
77
                         *  inside struct or other variable initializers outside of a function, something that is not possible with the
78
                         *  inline function variant.
79
                         *
80
                         *  \ingroup Group_ByteSwapping
81
                         *
82
                         *  \param[in] x  16-bit value whose byte ordering is to be swapped.
83
                         *
84
                         *  \return Input value with the byte ordering reversed.
85
                         */
86
                        #define SWAPENDIAN_16(x)            (uint16_t)((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8))
87

    
88
                        /** Swaps the byte ordering of a 32-bit value at compile-time. Do not use this macro for swapping byte orderings
89
                         *  of dynamic values computed at runtime- use \ref SwapEndian_32() instead. The result of this macro can be used
90
                         *  inside struct or other variable initializers outside of a function, something that is not possible with the
91
                         *  inline function variant.
92
                         *
93
                         *  \ingroup Group_ByteSwapping
94
                         *
95
                         *  \param[in] x  32-bit value whose byte ordering is to be swapped.
96
                         *
97
                         *  \return Input value with the byte ordering reversed.
98
                         */
99
                        #define SWAPENDIAN_32(x)            (uint32_t)((((x) & 0xFF000000UL) >> 24UL) | (((x) & 0x00FF0000UL) >> 8UL) | \
100
                                                                       (((x) & 0x0000FF00UL) << 8UL)  | (((x) & 0x000000FFUL) << 24UL))
101

    
102
                        #if defined(ARCH_BIG_ENDIAN) && !defined(le16_to_cpu)
103
                                #define le16_to_cpu(x)           SwapEndian_16(x)
104
                                #define le32_to_cpu(x)           SwapEndian_32(x)
105
                                #define be16_to_cpu(x)           (x)
106
                                #define be32_to_cpu(x)           (x)
107
                                #define cpu_to_le16(x)           SwapEndian_16(x)
108
                                #define cpu_to_le32(x)           SwapEndian_32(x)
109
                                #define cpu_to_be16(x)           (x)
110
                                #define cpu_to_be32(x)           (x)
111
                                #define LE16_TO_CPU(x)           SWAPENDIAN_16(x)
112
                                #define LE32_TO_CPU(x)           SWAPENDIAN_32(x)
113
                                #define BE16_TO_CPU(x)           (x)
114
                                #define BE32_TO_CPU(x)           (x)
115
                                #define CPU_TO_LE16(x)           SWAPENDIAN_16(x)
116
                                #define CPU_TO_LE32(x)           SWAPENDIAN_32(x)
117
                                #define CPU_TO_BE16(x)           (x)
118
                                #define CPU_TO_BE32(x)           (x)                        
119
                        #elif !defined(le16_to_cpu)
120
                                /** \name Run-time endianness conversion */
121
                                //@{
122
                        
123
                                /** Performs a conversion between a Little Endian encoded 16-bit piece of data and the
124
                                 *  Endianness of the currently selected CPU architecture.
125
                                 *
126
                                 *  On little endian architectures, this macro does nothing.
127
                                 *
128
                                 *  \note This macro is designed for run-time conversion of data - for compile-time endianness
129
                                 *        conversion, use \ref LE16_TO_CPU instead.
130
                                 *
131
                                 *  \ingroup Group_EndianConversion
132
                                 *
133
                                 *  \param[in] x  Data to perform the endianness conversion on.
134
                                 *
135
                                 *  \return Endian corrected version of the input value.
136
                                 */
137
                                #define le16_to_cpu(x)           (x)
138

    
139
                                /** Performs a conversion between a Little Endian encoded 32-bit piece of data and the
140
                                 *  Endianness of the currently selected CPU architecture.
141
                                 *
142
                                 *  On little endian architectures, this macro does nothing.
143
                                 *
144
                                 *  \note This macro is designed for run-time conversion of data - for compile-time endianness
145
                                 *        conversion, use \ref LE32_TO_CPU instead.
146
                                 *
147
                                 *  \ingroup Group_EndianConversion
148
                                 *
149
                                 *  \param[in] x  Data to perform the endianness conversion on.
150
                                 *
151
                                 *  \return Endian corrected version of the input value.
152
                                 */
153
                                #define le32_to_cpu(x)           (x)
154

    
155
                                /** Performs a conversion between a Big Endian encoded 16-bit piece of data and the
156
                                 *  Endianness of the currently selected CPU architecture.
157
                                 *
158
                                 *  On big endian architectures, this macro does nothing.
159
                                 *
160
                                 *  \note This macro is designed for run-time conversion of data - for compile-time endianness
161
                                 *        conversion, use \ref BE16_TO_CPU instead.
162
                                 *
163
                                 *  \ingroup Group_EndianConversion
164
                                 *
165
                                 *  \param[in] x  Data to perform the endianness conversion on.
166
                                 *
167
                                 *  \return Endian corrected version of the input value.
168
                                 */
169
                                #define be16_to_cpu(x)           SwapEndian_16(x)
170

    
171
                                /** Performs a conversion between a Big Endian encoded 32-bit piece of data and the
172
                                 *  Endianness of the currently selected CPU architecture.
173
                                 *
174
                                 *  On big endian architectures, this macro does nothing.
175
                                 *
176
                                 *  \note This macro is designed for run-time conversion of data - for compile-time endianness
177
                                 *        conversion, use \ref BE32_TO_CPU instead.
178
                                 *
179
                                 *  \ingroup Group_EndianConversion
180
                                 *
181
                                 *  \param[in] x  Data to perform the endianness conversion on.
182
                                 *
183
                                 *  \return Endian corrected version of the input value.
184
                                 */
185
                                #define be32_to_cpu(x)           SwapEndian_32(x)
186

    
187
                                /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
188
                                 *  is in Little Endian format regardless of the currently selected CPU architecture.
189
                                 *
190
                                 *  On little endian architectures, this macro does nothing.
191
                                 *
192
                                 *  \note This macro is designed for run-time conversion of data - for compile-time endianness
193
                                 *        conversion, use \ref CPU_TO_LE16 instead.
194
                                 *
195
                                 *  \ingroup Group_EndianConversion
196
                                 *
197
                                 *  \param[in] x  Data to perform the endianness conversion on.
198
                                 *
199
                                 *  \return Endian corrected version of the input value.
200
                                 */
201
                                #define cpu_to_le16(x)           (x)
202

    
203
                                /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
204
                                 *  is in Little Endian format regardless of the currently selected CPU architecture.
205
                                 *
206
                                 *  On little endian architectures, this macro does nothing.
207
                                 *
208
                                 *  \note This macro is designed for run-time conversion of data - for compile-time endianness
209
                                 *        conversion, use \ref CPU_TO_LE32 instead.
210
                                 *
211
                                 *  \ingroup Group_EndianConversion
212
                                 *
213
                                 *  \param[in] x  Data to perform the endianness conversion on.
214
                                 *
215
                                 *  \return Endian corrected version of the input value.
216
                                 */
217
                                #define cpu_to_le32(x)           (x)
218

    
219
                                /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
220
                                 *  is in Big Endian format regardless of the currently selected CPU architecture.
221
                                 *
222
                                 *  On big endian architectures, this macro does nothing.
223
                                 *
224
                                 *  \note This macro is designed for run-time conversion of data - for compile-time endianness
225
                                 *        conversion, use \ref CPU_TO_BE16 instead.
226
                                 *
227
                                 *  \ingroup Group_EndianConversion
228
                                 *
229
                                 *  \param[in] x  Data to perform the endianness conversion on.
230
                                 *
231
                                 *  \return Endian corrected version of the input value.
232
                                 */
233
                                #define cpu_to_be16(x)           SwapEndian_16(x)
234

    
235
                                /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
236
                                 *  is in Big Endian format regardless of the currently selected CPU architecture.
237
                                 *
238
                                 *  On big endian architectures, this macro does nothing.
239
                                 *
240
                                 *  \note This macro is designed for run-time conversion of data - for compile-time endianness
241
                                 *        conversion, use \ref CPU_TO_BE32 instead.
242
                                 *
243
                                 *  \ingroup Group_EndianConversion
244
                                 *
245
                                 *  \param[in] x  Data to perform the endianness conversion on.
246
                                 *
247
                                 *  \return Endian corrected version of the input value.
248
                                 */
249
                                #define cpu_to_be32(x)           SwapEndian_32(x)
250

    
251
                                //@}
252

    
253
                                /** \name Compile-time endianness conversion */
254
                                //@{
255

    
256
                                /** Performs a conversion between a Little Endian encoded 16-bit piece of data and the
257
                                 *  Endianness of the currently selected CPU architecture.
258
                                 *
259
                                 *  On little endian architectures, this macro does nothing.
260
                                 *
261
                                 *  \note This macro is designed for compile-time conversion of data - for run time endianness
262
                                 *        conversion, use \ref le16_to_cpu instead.
263
                                 *
264
                                 *  \ingroup Group_EndianConversion
265
                                 *
266
                                 *  \param[in] x  Data to perform the endianness conversion on.
267
                                 *
268
                                 *  \return Endian corrected version of the input value.
269
                                 */
270
                                #define LE16_TO_CPU(x)           (x)
271

    
272
                                /** Performs a conversion between a Little Endian encoded 32-bit piece of data and the
273
                                 *  Endianness of the currently selected CPU architecture.
274
                                 *
275
                                 *  On little endian architectures, this macro does nothing.
276
                                 *
277
                                 *  \note This macro is designed for compile-time conversion of data - for run time endianness
278
                                 *        conversion, use \ref le32_to_cpu instead.
279
                                 *
280
                                 *  \ingroup Group_EndianConversion
281
                                 *
282
                                 *  \param[in] x  Data to perform the endianness conversion on.
283
                                 *
284
                                 *  \return Endian corrected version of the input value.
285
                                 */
286
                                #define LE32_TO_CPU(x)           (x)
287

    
288
                                /** Performs a conversion between a Big Endian encoded 16-bit piece of data and the
289
                                 *  Endianness of the currently selected CPU architecture.
290
                                 *
291
                                 *  On big endian architectures, this macro does nothing.
292
                                 *
293
                                 *  \note This macro is designed for compile-time conversion of data - for run-time endianness
294
                                 *        conversion, use \ref be16_to_cpu instead.
295
                                 *
296
                                 *  \ingroup Group_EndianConversion
297
                                 *
298
                                 *  \param[in] x  Data to perform the endianness conversion on.
299
                                 *
300
                                 *  \return Endian corrected version of the input value.
301
                                 */
302
                                #define BE16_TO_CPU(x)           SWAPENDIAN_16(x)
303

    
304
                                /** Performs a conversion between a Big Endian encoded 32-bit piece of data and the
305
                                 *  Endianness of the currently selected CPU architecture.
306
                                 *
307
                                 *  On big endian architectures, this macro does nothing.
308
                                 *
309
                                 *  \note This macro is designed for compile-time conversion of data - for run-time endianness
310
                                 *        conversion, use \ref be32_to_cpu instead.
311
                                 *
312
                                 *  \ingroup Group_EndianConversion
313
                                 *
314
                                 *  \param[in] x  Data to perform the endianness conversion on.
315
                                 *
316
                                 *  \return Endian corrected version of the input value.
317
                                 */
318
                                #define BE32_TO_CPU(x)           SWAPENDIAN_32(x)
319

    
320
                                /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
321
                                 *  is in Little Endian format regardless of the currently selected CPU architecture.
322
                                 *
323
                                 *  On little endian architectures, this macro does nothing.
324
                                 *
325
                                 *  \note This macro is designed for compile-time conversion of data - for run-time endianness
326
                                 *        conversion, use \ref cpu_to_le16 instead.
327
                                 *
328
                                 *  \ingroup Group_EndianConversion
329
                                 *
330
                                 *  \param[in] x  Data to perform the endianness conversion on.
331
                                 *
332
                                 *  \return Endian corrected version of the input value.
333
                                 */
334
                                #define CPU_TO_LE16(x)           (x)
335

    
336
                                /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
337
                                 *  is in Little Endian format regardless of the currently selected CPU architecture.
338
                                 *
339
                                 *  On little endian architectures, this macro does nothing.
340
                                 *
341
                                 *  \note This macro is designed for compile-time conversion of data - for run-time endianness
342
                                 *        conversion, use \ref cpu_to_le32 instead.
343
                                 *
344
                                 *  \ingroup Group_EndianConversion
345
                                 *
346
                                 *  \param[in] x  Data to perform the endianness conversion on.
347
                                 *
348
                                 *  \return Endian corrected version of the input value.
349
                                 */
350
                                #define CPU_TO_LE32(x)           (x)
351

    
352
                                /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
353
                                 *  is in Big Endian format regardless of the currently selected CPU architecture.
354
                                 *
355
                                 *  On big endian architectures, this macro does nothing.
356
                                 *
357
                                 *  \note This macro is designed for compile-time conversion of data - for run-time endianness
358
                                 *        conversion, use \ref cpu_to_be16 instead.
359
                                 *
360
                                 *  \ingroup Group_EndianConversion
361
                                 *
362
                                 *  \param[in] x  Data to perform the endianness conversion on.
363
                                 *
364
                                 *  \return Endian corrected version of the input value.
365
                                 */
366
                                #define CPU_TO_BE16(x)           SWAPENDIAN_16(x)
367

    
368
                                /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
369
                                 *  is in Big Endian format regardless of the currently selected CPU architecture.
370
                                 *
371
                                 *  On big endian architectures, this macro does nothing.
372
                                 *
373
                                 *  \note This macro is designed for compile-time conversion of data - for run-time endianness
374
                                 *        conversion, use \ref cpu_to_be32 instead.
375
                                 *
376
                                 *  \ingroup Group_EndianConversion
377
                                 *
378
                                 *  \param[in] x  Data to perform the endianness conversion on.
379
                                 *
380
                                 *  \return Endian corrected version of the input value.
381
                                 */
382
                                #define CPU_TO_BE32(x)           SWAPENDIAN_32(x)
383

    
384
                                //! @}
385
                        #endif
386

    
387
                /* Inline Functions: */
388
                        /** Function to reverse the byte ordering of the individual bytes in a 16 bit value.
389
                         *
390
                         *  \ingroup Group_ByteSwapping
391
                         *
392
                         *  \param[in] Word  Word of data whose bytes are to be swapped.
393
                         *
394
                         *  \return Input data with the individual bytes reversed.
395
                         */
396
                        static inline uint16_t SwapEndian_16(const uint16_t Word) ATTR_WARN_UNUSED_RESULT ATTR_CONST;
397
                        static inline uint16_t SwapEndian_16(const uint16_t Word)
398
                        {
399
                                if (GCC_IS_COMPILE_CONST(Word))
400
                                  return SWAPENDIAN_16(Word);
401
                        
402
                                uint8_t Temp;
403

    
404
                                union
405
                                {
406
                                        uint16_t Word;
407
                                        uint8_t  Bytes[2];
408
                                } Data;
409

    
410
                                Data.Word = Word;
411

    
412
                                Temp = Data.Bytes[0];
413
                                Data.Bytes[0] = Data.Bytes[1];
414
                                Data.Bytes[1] = Temp;
415

    
416
                                return Data.Word;
417
                        }
418

    
419
                        /** Function to reverse the byte ordering of the individual bytes in a 32 bit value.
420
                         *
421
                         *  \ingroup Group_ByteSwapping
422
                         *
423
                         *  \param[in] DWord  Double word of data whose bytes are to be swapped.
424
                         *
425
                         *  \return Input data with the individual bytes reversed.
426
                         */
427
                        static inline uint32_t SwapEndian_32(const uint32_t DWord) ATTR_WARN_UNUSED_RESULT ATTR_CONST;
428
                        static inline uint32_t SwapEndian_32(const uint32_t DWord)
429
                        {
430
                                if (GCC_IS_COMPILE_CONST(DWord))
431
                                  return SWAPENDIAN_32(DWord);
432

    
433
                                uint8_t Temp;
434

    
435
                                union
436
                                {
437
                                        uint32_t DWord;
438
                                        uint8_t  Bytes[4];
439
                                } Data;
440

    
441
                                Data.DWord = DWord;
442

    
443
                                Temp = Data.Bytes[0];
444
                                Data.Bytes[0] = Data.Bytes[3];
445
                                Data.Bytes[3] = Temp;
446

    
447
                                Temp = Data.Bytes[1];
448
                                Data.Bytes[1] = Data.Bytes[2];
449
                                Data.Bytes[2] = Temp;
450

    
451
                                return Data.DWord;
452
                        }
453

    
454
                        /** Function to reverse the byte ordering of the individual bytes in a n byte value.
455
                         *
456
                         *  \ingroup Group_ByteSwapping
457
                         *
458
                         *  \param[in,out] Data    Pointer to a number containing an even number of bytes to be reversed.
459
                         *  \param[in]     Length  Length of the data in bytes.
460
                         *
461
                         *  \return Input data with the individual bytes reversed.
462
                         */
463
                        static inline void SwapEndian_n(void* const Data,
464
                                                        uint8_t Length) ATTR_NON_NULL_PTR_ARG(1);
465
                        static inline void SwapEndian_n(void* const Data,
466
                                                        uint8_t Length)
467
                        {
468
                                uint8_t* CurrDataPos = (uint8_t*)Data;
469

    
470
                                while (Length > 1)
471
                                {
472
                                        uint8_t Temp = *CurrDataPos;
473
                                        *CurrDataPos = *(CurrDataPos + Length - 1);
474
                                        *(CurrDataPos + Length - 1) = Temp;
475

    
476
                                        CurrDataPos++;
477
                                        Length -= 2;
478
                                }
479
                        }
480

    
481
        /* Disable C linkage for C++ Compilers: */
482
                #if defined(__cplusplus)
483
                        }
484
                #endif
485

    
486
#endif
487

    
488
/** @} */