2626
2727#include "modbus.h"
2828
29- #if defined(HAVE_BYTESWAP_H )
30- # include <byteswap.h>
31- #endif
32-
33- #if defined(__APPLE__ )
34- # include <libkern/OSByteOrder.h>
35- # define bswap_16 OSSwapInt16
36- # define bswap_32 OSSwapInt32
37- # define bswap_64 OSSwapInt64
38- #endif
39-
40- #if defined(__GNUC__ )
41- # define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10)
42- # if GCC_VERSION >= 430
43- // Since GCC >= 4.30, GCC provides __builtin_bswapXX() alternatives so we switch to them
44- # undef bswap_32
45- # define bswap_32 __builtin_bswap32
46- # endif
47- # if GCC_VERSION >= 480
48- # undef bswap_16
49- # define bswap_16 __builtin_bswap16
50- # endif
51- #endif
52-
53- #if defined(_MSC_VER ) && (_MSC_VER >= 1400 )
54- # define bswap_32 _byteswap_ulong
55- # define bswap_16 _byteswap_ushort
56- #endif
57-
58- #if !defined(bswap_16 )
59- # warning "Fallback on C functions for bswap_16"
60- static inline uint16_t bswap_16 (uint16_t x )
61- {
62- return (x >> 8 ) | (x << 8 );
63- }
64- #endif
65-
66- #if !defined(bswap_32 )
67- # warning "Fallback on C functions for bswap_32"
68- static inline uint32_t bswap_32 (uint32_t x )
69- {
70- return (bswap_16 (x & 0xffff ) << 16 ) | (bswap_16 (x >> 16 ));
71- }
72- #endif
7329// clang-format on
7430
7531/* Sets many bits from a single byte value (all 8 bits of the byte value are
@@ -128,11 +84,14 @@ float modbus_get_float_abcd(const uint16_t *src)
12884 uint32_t i ;
12985 uint8_t a , b , c , d ;
13086
131- a = (src [0 ] >> 8 ) & 0xFF ;
132- b = (src [0 ] >> 0 ) & 0xFF ;
133- c = (src [1 ] >> 8 ) & 0xFF ;
134- d = (src [1 ] >> 0 ) & 0xFF ;
87+ // Mind: src contains 16-bit numbers in processor-endianness, hence
88+ // we use shift operations and do not access memory directly
89+ a = (src [0 ] >> 8 ) & 0xFF ; // high byte of first word
90+ b = (src [0 ] >> 0 ) & 0xFF ; // low byte of first word
91+ c = (src [1 ] >> 8 ) & 0xFF ; // high byte of second word
92+ d = (src [1 ] >> 0 ) & 0xFF ; // low byte of second word
13593
94+ // we assemble 32bit integer always in abcd order via shift operations
13695 i = (a << 24 ) | (b << 16 ) | (c << 8 ) | (d << 0 );
13796 memcpy (& f , & i , 4 );
13897
@@ -146,12 +105,14 @@ float modbus_get_float_dcba(const uint16_t *src)
146105 uint32_t i ;
147106 uint8_t a , b , c , d ;
148107
149- a = (src [0 ] >> 8 ) & 0xFF ;
150- b = (src [0 ] >> 0 ) & 0xFF ;
151- c = (src [1 ] >> 8 ) & 0xFF ;
152- d = (src [1 ] >> 0 ) & 0xFF ;
108+ // byte order is defined when reading from src: dcba
109+ d = (src [0 ] >> 8 ) & 0xFF ;
110+ c = (src [0 ] >> 0 ) & 0xFF ;
111+ b = (src [1 ] >> 8 ) & 0xFF ;
112+ a = (src [1 ] >> 0 ) & 0xFF ;
153113
154- i = (d << 24 ) | (c << 16 ) | (b << 8 ) | (a << 0 );
114+ // we assemble 32bit integer always in abcd order via shift operations
115+ i = (a << 24 ) | (b << 16 ) | (c << 8 ) | (d << 0 );
155116 memcpy (& f , & i , 4 );
156117
157118 return f ;
@@ -164,12 +125,14 @@ float modbus_get_float_badc(const uint16_t *src)
164125 uint32_t i ;
165126 uint8_t a , b , c , d ;
166127
167- a = (src [0 ] >> 8 ) & 0xFF ;
168- b = (src [0 ] >> 0 ) & 0xFF ;
169- c = (src [1 ] >> 8 ) & 0xFF ;
170- d = (src [1 ] >> 0 ) & 0xFF ;
128+ // byte order is defined when reading from src: badc
129+ b = (src [0 ] >> 8 ) & 0xFF ;
130+ a = (src [0 ] >> 0 ) & 0xFF ;
131+ d = (src [1 ] >> 8 ) & 0xFF ;
132+ c = (src [1 ] >> 0 ) & 0xFF ;
171133
172- i = (b << 24 ) | (a << 16 ) | (d << 8 ) | (c << 0 );
134+ // we assemble 32bit integer always in abcd order via shift operations
135+ i = (a << 24 ) | (b << 16 ) | (c << 8 ) | (d << 0 );
173136 memcpy (& f , & i , 4 );
174137
175138 return f ;
@@ -182,12 +145,14 @@ float modbus_get_float_cdab(const uint16_t *src)
182145 uint32_t i ;
183146 uint8_t a , b , c , d ;
184147
185- a = (src [0 ] >> 8 ) & 0xFF ;
186- b = (src [0 ] >> 0 ) & 0xFF ;
187- c = (src [1 ] >> 8 ) & 0xFF ;
188- d = (src [1 ] >> 0 ) & 0xFF ;
148+ // byte order is defined when reading from src: cdab
149+ c = (src [0 ] >> 8 ) & 0xFF ;
150+ d = (src [0 ] >> 0 ) & 0xFF ;
151+ a = (src [1 ] >> 8 ) & 0xFF ;
152+ b = (src [1 ] >> 0 ) & 0xFF ;
189153
190- i = (c << 24 ) | (d << 16 ) | (a << 8 ) | (b << 0 );
154+ // we assemble 32bit integer always in abcd order via shift operations
155+ i = (a << 24 ) | (b << 16 ) | (c << 8 ) | (d << 0 );
191156 memcpy (& f , & i , 4 );
192157
193158 return f ;
@@ -196,97 +161,81 @@ float modbus_get_float_cdab(const uint16_t *src)
196161/* DEPRECATED - Get a float from 4 bytes in sort of Modbus format */
197162float modbus_get_float (const uint16_t * src )
198163{
199- float f ;
200- uint32_t i ;
201-
202- i = (((uint32_t ) src [1 ]) << 16 ) + src [0 ];
203- memcpy (& f , & i , sizeof (float ));
204-
205- return f ;
164+ return modbus_get_float_cdab (src );
206165}
207166
208167/* Set a float to 4 bytes for Modbus w/o any conversion (ABCD) */
209168void modbus_set_float_abcd (float f , uint16_t * dest )
210169{
211- uint32_t i ;
212- uint8_t * out = (uint8_t * ) dest ;
170+ // The straight-forward type conversion won't work because of type-punned pointer aliasing warning
171+ // uint32_t i = *(uint32_t*)(&f);
172+ float * fptr = & f ;
173+ uint32_t * iptr = (uint32_t * )fptr ;
174+ uint32_t i = * iptr ;
213175 uint8_t a , b , c , d ;
214176
215- memcpy (& i , & f , sizeof (uint32_t ));
216177 a = (i >> 24 ) & 0xFF ;
217178 b = (i >> 16 ) & 0xFF ;
218179 c = (i >> 8 ) & 0xFF ;
219180 d = (i >> 0 ) & 0xFF ;
220181
221- out [0 ] = a ;
222- out [1 ] = b ;
223- out [2 ] = c ;
224- out [3 ] = d ;
182+ dest [0 ] = (a << 8 ) | b ;
183+ dest [1 ] = (c << 8 ) | d ;
225184}
226185
227186/* Set a float to 4 bytes for Modbus with byte and word swap conversion (DCBA) */
228187void modbus_set_float_dcba (float f , uint16_t * dest )
229188{
230- uint32_t i ;
231- uint8_t * out = (uint8_t * ) dest ;
189+ float * fptr = & f ;
190+ uint32_t * iptr = (uint32_t * )fptr ;
191+ uint32_t i = * iptr ;
232192 uint8_t a , b , c , d ;
233193
234- memcpy (& i , & f , sizeof (uint32_t ));
235194 a = (i >> 24 ) & 0xFF ;
236195 b = (i >> 16 ) & 0xFF ;
237196 c = (i >> 8 ) & 0xFF ;
238197 d = (i >> 0 ) & 0xFF ;
239198
240- out [0 ] = d ;
241- out [1 ] = c ;
242- out [2 ] = b ;
243- out [3 ] = a ;
199+ dest [0 ] = (d << 8 ) | c ;
200+ dest [1 ] = (b << 8 ) | a ;
244201}
245202
246203/* Set a float to 4 bytes for Modbus with byte swap conversion (BADC) */
247204void modbus_set_float_badc (float f , uint16_t * dest )
248205{
249- uint32_t i ;
250- uint8_t * out = (uint8_t * ) dest ;
206+ float * fptr = & f ;
207+ uint32_t * iptr = (uint32_t * )fptr ;
208+ uint32_t i = * iptr ;
251209 uint8_t a , b , c , d ;
252210
253- memcpy (& i , & f , sizeof (uint32_t ));
254211 a = (i >> 24 ) & 0xFF ;
255212 b = (i >> 16 ) & 0xFF ;
256213 c = (i >> 8 ) & 0xFF ;
257214 d = (i >> 0 ) & 0xFF ;
258215
259- out [0 ] = b ;
260- out [1 ] = a ;
261- out [2 ] = d ;
262- out [3 ] = c ;
216+ dest [0 ] = (b << 8 ) | a ;
217+ dest [1 ] = (d << 8 ) | c ;
263218}
264219
265220/* Set a float to 4 bytes for Modbus with word swap conversion (CDAB) */
266221void modbus_set_float_cdab (float f , uint16_t * dest )
267222{
268- uint32_t i ;
269- uint8_t * out = (uint8_t * ) dest ;
223+ float * fptr = & f ;
224+ uint32_t * iptr = (uint32_t * )fptr ;
225+ uint32_t i = * iptr ;
270226 uint8_t a , b , c , d ;
271227
272- memcpy (& i , & f , sizeof (uint32_t ));
273228 a = (i >> 24 ) & 0xFF ;
274229 b = (i >> 16 ) & 0xFF ;
275230 c = (i >> 8 ) & 0xFF ;
276231 d = (i >> 0 ) & 0xFF ;
277232
278- out [0 ] = c ;
279- out [1 ] = d ;
280- out [2 ] = a ;
281- out [3 ] = b ;
233+ dest [0 ] = (c << 8 ) | d ;
234+ dest [1 ] = (a << 8 ) | b ;
282235}
283236
284237/* DEPRECATED - Set a float to 4 bytes in a sort of Modbus format! */
285238void modbus_set_float (float f , uint16_t * dest )
286239{
287- uint32_t i ;
288-
289- memcpy (& i , & f , sizeof (uint32_t ));
290- dest [0 ] = (uint16_t ) i ;
291- dest [1 ] = (uint16_t ) (i >> 16 );
240+ modbus_set_float_cdab (f , dest );
292241}
0 commit comments