Skip to content

Commit 8e769e7

Browse files
committed
Revert "Fixes float encoding/decoding for both big and little endian (fixes #665, #694)"
This reverts commit 13bd584.
1 parent 3d34a64 commit 8e769e7

File tree

1 file changed

+112
-54
lines changed

1 file changed

+112
-54
lines changed

src/modbus-data.c

Lines changed: 112 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,50 @@
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
2973
// clang-format on
3074

3175
/* Sets many bits from a single byte value (all 8 bits of the byte value are
@@ -80,29 +124,17 @@ uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx, unsigned int nb_b
80124
/* Get a float from 4 bytes (Modbus) without any conversion (ABCD) */
81125
float modbus_get_float_abcd(const uint16_t *src)
82126
{
83-
/* Suppose the modbus byte stream contained the 32-bit float 0x10203040 - abcd.
84-
On big endian systems, the memory starting at src contains two 16-bit registers 0x1020 and 0x3040
85-
On little endian system, the 16-bit registers memory holds 0x2010 and 0x4030
86-
87-
To convert the data to float32 on big-endian we only need to cast the pointer and we are done.
88-
On little endian systems, we need to swap the bytes in each word again and then assemble
89-
an integer via shift operations and finally cast to float32.
90-
91-
A portable way is to retrieve low and high bytes of both words using shift operations, then assemble
92-
the 32-bit integer.
93-
*/
94-
95127
float f;
128+
uint32_t i;
96129
uint8_t a, b, c, d;
97130

98-
a = (src[0] >> 8) & 0xFF; // high byte if first word
99-
b = (src[0] >> 0) & 0xFF; // low byte if first word
100-
c = (src[1] >> 8) & 0xFF; // high byte if second word
101-
d = (src[1] >> 0) & 0xFF; // low byte if second word
131+
a = (src[0] >> 8) & 0xFF;
132+
b = (src[0] >> 0) & 0xFF;
133+
c = (src[1] >> 8) & 0xFF;
134+
d = (src[1] >> 0) & 0xFF;
102135

103-
// assemble in memory location of float
104-
// from right to left: get address of float, interpret as address to uint32, dereference and write uint32
105-
*(uint32_t *)&f = (a << 24) | (b << 16) | (c << 8) | (d << 0);
136+
i = (a << 24) | (b << 16) | (c << 8) | (d << 0);
137+
memcpy(&f, &i, 4);
106138

107139
return f;
108140
}
@@ -111,16 +143,16 @@ float modbus_get_float_abcd(const uint16_t *src)
111143
float modbus_get_float_dcba(const uint16_t *src)
112144
{
113145
float f;
146+
uint32_t i;
114147
uint8_t a, b, c, d;
115148

116-
d = (src[0] >> 8) & 0xFF;
117-
c = (src[0] >> 0) & 0xFF;
118-
b = (src[1] >> 8) & 0xFF;
119-
a = (src[1] >> 0) & 0xFF;
149+
a = (src[0] >> 8) & 0xFF;
150+
b = (src[0] >> 0) & 0xFF;
151+
c = (src[1] >> 8) & 0xFF;
152+
d = (src[1] >> 0) & 0xFF;
120153

121-
// assemble in memory location of float
122-
// from right to left: get address of float, interpret as address to uint32, dereference and write uint32
123-
*(uint32_t *)&f = (a << 24) | (b << 16) | (c << 8) | (d << 0);
154+
i = (d << 24) | (c << 16) | (b << 8) | (a << 0);
155+
memcpy(&f, &i, 4);
124156

125157
return f;
126158
}
@@ -129,16 +161,16 @@ float modbus_get_float_dcba(const uint16_t *src)
129161
float modbus_get_float_badc(const uint16_t *src)
130162
{
131163
float f;
164+
uint32_t i;
132165
uint8_t a, b, c, d;
133166

134-
b = (src[0] >> 8) & 0xFF;
135-
a = (src[0] >> 0) & 0xFF;
136-
d = (src[1] >> 8) & 0xFF;
137-
c = (src[1] >> 0) & 0xFF;
167+
a = (src[0] >> 8) & 0xFF;
168+
b = (src[0] >> 0) & 0xFF;
169+
c = (src[1] >> 8) & 0xFF;
170+
d = (src[1] >> 0) & 0xFF;
138171

139-
// assemble in memory location of float
140-
// from right to left: get address of float, interpret as address to uint32, dereference and write uint32
141-
*(uint32_t *)&f = (a << 24) | (b << 16) | (c << 8) | (d << 0);
172+
i = (b << 24) | (a << 16) | (d << 8) | (c << 0);
173+
memcpy(&f, &i, 4);
142174

143175
return f;
144176
}
@@ -147,88 +179,114 @@ float modbus_get_float_badc(const uint16_t *src)
147179
float modbus_get_float_cdab(const uint16_t *src)
148180
{
149181
float f;
182+
uint32_t i;
150183
uint8_t a, b, c, d;
151184

152-
c = (src[0] >> 8) & 0xFF;
153-
d = (src[0] >> 0) & 0xFF;
154-
a = (src[1] >> 8) & 0xFF;
155-
b = (src[1] >> 0) & 0xFF;
185+
a = (src[0] >> 8) & 0xFF;
186+
b = (src[0] >> 0) & 0xFF;
187+
c = (src[1] >> 8) & 0xFF;
188+
d = (src[1] >> 0) & 0xFF;
156189

157-
// assemble in memory location of float
158-
// from right to left: get address of float, interpret as address to uint32, dereference and write uint32
159-
*(uint32_t *)&f = (a << 24) | (b << 16) | (c << 8) | (d << 0);
190+
i = (c << 24) | (d << 16) | (a << 8) | (b << 0);
191+
memcpy(&f, &i, 4);
160192

161193
return f;
162194
}
163195

164196
/* DEPRECATED - Get a float from 4 bytes in sort of Modbus format */
165197
float modbus_get_float(const uint16_t *src)
166198
{
167-
return modbus_get_float_cdab(src);
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;
168206
}
169207

170208
/* Set a float to 4 bytes for Modbus w/o any conversion (ABCD) */
171209
void modbus_set_float_abcd(float f, uint16_t *dest)
172210
{
173-
uint32_t i = *(uint32_t*)(&f);
211+
uint32_t i;
212+
uint8_t *out = (uint8_t *) dest;
174213
uint8_t a, b, c, d;
175214

215+
memcpy(&i, &f, sizeof(uint32_t));
176216
a = (i >> 24) & 0xFF;
177217
b = (i >> 16) & 0xFF;
178218
c = (i >> 8) & 0xFF;
179219
d = (i >> 0) & 0xFF;
180220

181-
dest[0] = (a << 8) | b;
182-
dest[1] = (c << 8) | d;
221+
out[0] = a;
222+
out[1] = b;
223+
out[2] = c;
224+
out[3] = d;
183225
}
184226

185227
/* Set a float to 4 bytes for Modbus with byte and word swap conversion (DCBA) */
186228
void modbus_set_float_dcba(float f, uint16_t *dest)
187229
{
188-
uint32_t i = *(uint32_t*)(&f);
230+
uint32_t i;
231+
uint8_t *out = (uint8_t *) dest;
189232
uint8_t a, b, c, d;
190233

234+
memcpy(&i, &f, sizeof(uint32_t));
191235
a = (i >> 24) & 0xFF;
192236
b = (i >> 16) & 0xFF;
193237
c = (i >> 8) & 0xFF;
194238
d = (i >> 0) & 0xFF;
195239

196-
dest[0] = (d << 8) | c;
197-
dest[1] = (b << 8) | a;
240+
out[0] = d;
241+
out[1] = c;
242+
out[2] = b;
243+
out[3] = a;
198244
}
199245

200246
/* Set a float to 4 bytes for Modbus with byte swap conversion (BADC) */
201247
void modbus_set_float_badc(float f, uint16_t *dest)
202248
{
203-
uint32_t i = *(uint32_t*)(&f);
249+
uint32_t i;
250+
uint8_t *out = (uint8_t *) dest;
204251
uint8_t a, b, c, d;
205252

253+
memcpy(&i, &f, sizeof(uint32_t));
206254
a = (i >> 24) & 0xFF;
207255
b = (i >> 16) & 0xFF;
208256
c = (i >> 8) & 0xFF;
209257
d = (i >> 0) & 0xFF;
210258

211-
dest[0] = (b << 8) | a;
212-
dest[1] = (d << 8) | c;
259+
out[0] = b;
260+
out[1] = a;
261+
out[2] = d;
262+
out[3] = c;
213263
}
214264

215265
/* Set a float to 4 bytes for Modbus with word swap conversion (CDAB) */
216266
void modbus_set_float_cdab(float f, uint16_t *dest)
217267
{
218-
uint32_t i = *(uint32_t*)(&f);
268+
uint32_t i;
269+
uint8_t *out = (uint8_t *) dest;
219270
uint8_t a, b, c, d;
220271

272+
memcpy(&i, &f, sizeof(uint32_t));
221273
a = (i >> 24) & 0xFF;
222274
b = (i >> 16) & 0xFF;
223275
c = (i >> 8) & 0xFF;
224276
d = (i >> 0) & 0xFF;
225277

226-
dest[0] = (c << 8) | d;
227-
dest[1] = (a << 8) | b;
278+
out[0] = c;
279+
out[1] = d;
280+
out[2] = a;
281+
out[3] = b;
228282
}
229283

230284
/* DEPRECATED - Set a float to 4 bytes in a sort of Modbus format! */
231285
void modbus_set_float(float f, uint16_t *dest)
232286
{
233-
return modbus_set_float_cdab(f, dest);
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);
234292
}

0 commit comments

Comments
 (0)