Commit 08ed259fe65666ab3115fb93848ec0b6b5661f56

Authored by Stéphane Raimbault
1 parent caade94b

Rewrite and extend functions to manipulate float values

doc/modbus_get_float.txt
... ... @@ -11,6 +11,8 @@ SYNOPSIS
11 11 --------
12 12 *float modbus_get_float(const uint16_t *'src');*
13 13  
  14 +Warning, this function is *deprecated* since libmodbus v3.2.0 and has been
  15 +replaced by *modbus_get_float_dcba()*.
14 16  
15 17 DESCRIPTION
16 18 -----------
... ...
doc/modbus_get_float_dcba.txt
... ... @@ -15,9 +15,9 @@ SYNOPSIS
15 15 DESCRIPTION
16 16 -----------
17 17 The *modbus_get_float_dcba()* function shall get a float from 4 bytes in
18   -inversed Modbus format (DCBA order). The _src_ array must be pointer on two 16
19   -bits values, for example, if the first word is set to 0x9a22 and the second to
20   -0x6544, the float value read will be 916.540649.
  18 +inversed Modbus format (DCBA order instead of ABCD). The _src_ array must be
  19 +pointer on two 16 bits values, for example, if the first word is set to 0x9a22
  20 +and the second to 0x6544, the float value read will be 916.540649.
21 21  
22 22  
23 23 RETURN VALUE
... ... @@ -28,8 +28,6 @@ The function shall return a float.
28 28 SEE ALSO
29 29 --------
30 30 linkmb:modbus_set_float_dcba[3]
31   -linkmb:modbus_set_float[3]
32   -linkmb:modbus_get_float[3]
33 31  
34 32  
35 33 AUTHORS
... ...
doc/modbus_set_float.txt
1 1 modbus_set_float(3)
2 2 ===================
3 3  
4   -
5 4 NAME
6 5 ----
7 6 modbus_set_float - set a float value from 2 registers
... ... @@ -11,6 +10,8 @@ SYNOPSIS
11 10 --------
12 11 *void modbus_set_float(float 'f', uint16_t *'dest');*
13 12  
  13 +Warning, this function is *deprecated* since libmodbus v3.2.0 and has been
  14 +replaced by *modbus_set_float_dcba()*.
14 15  
15 16 DESCRIPTION
16 17 -----------
... ... @@ -26,9 +27,8 @@ There is no return values.
26 27  
27 28 SEE ALSO
28 29 --------
29   -linkmb:modbus_set_float[3]
  30 +linkmb:modbus_get_float[3]
30 31 linkmb:modbus_set_float_dcba[3]
31   -linkmb:modbus_get_float_dcba[3]
32 32  
33 33 AUTHORS
34 34 -------
... ...
src/modbus-data.c
1 1 /*
2   - * Copyright © 2010-2011 Stéphane Raimbault <stephane.raimbault@gmail.com>
  2 + * Copyright © 2010-2014 Stéphane Raimbault <stephane.raimbault@gmail.com>
3 3 *
4 4 * SPDX-License-Identifier: LGPL-2.1+
5 5 */
... ... @@ -13,6 +13,12 @@
13 13 #include <string.h>
14 14 #include <assert.h>
15 15  
  16 +#if defined(_WIN32)
  17 +# include <winsock2.h>
  18 +#else
  19 +# include <arpa/inet.h>
  20 +#endif
  21 +
16 22 #include "modbus.h"
17 23  
18 24 #if defined(HAVE_BYTESWAP_H)
... ... @@ -96,47 +102,116 @@ uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx,
96 102 return value;
97 103 }
98 104  
99   -/* Get a float from 4 bytes in Modbus format (ABCD) */
100   -float modbus_get_float(const uint16_t *src)
  105 +/* Get a float from 4 bytes (Modbus) without any conversion (ABCD) */
  106 +float modbus_get_float_abcd(const uint16_t *src)
101 107 {
102 108 float f;
103 109 uint32_t i;
104 110  
105   - i = (((uint32_t)src[1]) << 16) + src[0];
  111 + i = ntohl(((uint32_t)src[0] << 16) + src[1]);
106 112 memcpy(&f, &i, sizeof(float));
107 113  
108 114 return f;
109 115 }
110 116  
111   -/* Get a float from 4 bytes in inversed Modbus format (DCBA) */
  117 +/* Get a float from 4 bytes (Modbus) with byte and word swap conversion (DCBA) */
112 118 float modbus_get_float_dcba(const uint16_t *src)
113 119 {
114 120 float f;
115 121 uint32_t i;
116 122  
117   - i = bswap_32((((uint32_t)src[1]) << 16) + src[0]);
  123 + i = ntohl(bswap_32((((uint32_t)src[0]) << 16) + src[1]));
118 124 memcpy(&f, &i, sizeof(float));
119 125  
120 126 return f;
121 127 }
122 128  
123   -/* Set a float to 4 bytes in Modbus format (ABCD) */
124   -void modbus_set_float(float f, uint16_t *dest)
  129 +/* Get a float from 4 bytes (Modbus) with byte swap conversion (BADC) */
  130 +float modbus_get_float_badc(const uint16_t *src)
  131 +{
  132 + float f;
  133 + uint32_t i;
  134 +
  135 + i = ntohl((uint32_t)(bswap_16(src[0]) << 16) + bswap_16(src[1]));
  136 + memcpy(&f, &i, sizeof(float));
  137 +
  138 + return f;
  139 +}
  140 +
  141 +/* Get a float from 4 bytes (Modbus) in the format CDAB */
  142 +float modbus_get_float_cdab(const uint16_t *src)
  143 +{
  144 + float f;
  145 + uint32_t i;
  146 +
  147 + i = ntohl((((uint32_t)src[1]) << 16) + src[0]);
  148 + memcpy(&f, &i, sizeof(float));
  149 +
  150 + return f;
  151 +}
  152 +
  153 +/* DEPRECATED - Get a float from 4 bytes in sort of Modbus format */
  154 +float modbus_get_float(const uint16_t *src)
  155 +{
  156 + float f;
  157 + uint32_t i;
  158 +
  159 + i = (((uint32_t)src[1]) << 16) + src[0];
  160 + memcpy(&f, &i, sizeof(float));
  161 +
  162 + return f;
  163 +}
  164 +
  165 +/* Set a float to 4 bytes for Modbus w/o any conversion (ABCD) */
  166 +void modbus_set_float_abcd(float f, uint16_t *dest)
  167 +{
  168 + uint32_t i;
  169 +
  170 + memcpy(&i, &f, sizeof(uint32_t));
  171 + i = htonl(i);
  172 + dest[0] = (uint16_t)(i >> 16);
  173 + dest[1] = (uint16_t)i;
  174 +}
  175 +
  176 +/* Set a float to 4 bytes for Modbus with byte and word swap conversion (DCBA) */
  177 +void modbus_set_float_dcba(float f, uint16_t *dest)
125 178 {
126 179 uint32_t i;
127 180  
128 181 memcpy(&i, &f, sizeof(uint32_t));
  182 + i = bswap_32(htonl(i));
  183 + dest[0] = (uint16_t)(i >> 16);
  184 + dest[1] = (uint16_t)i;
  185 +}
  186 +
  187 +/* Set a float to 4 bytes for Modbus with byte swap conversion (BADC) */
  188 +void modbus_set_float_badc(float f, uint16_t *dest)
  189 +{
  190 + uint32_t i;
  191 +
  192 + memcpy(&i, &f, sizeof(uint32_t));
  193 + i = htonl(i);
  194 + dest[0] = (uint16_t)bswap_16(i >> 16);
  195 + dest[1] = (uint16_t)bswap_16(i & 0xFFFF);
  196 +}
  197 +
  198 +/* Set a float to 4 bytes for Modbus with word swap conversion (CDAB) */
  199 +void modbus_set_float_cdab(float f, uint16_t *dest)
  200 +{
  201 + uint32_t i;
  202 +
  203 + memcpy(&i, &f, sizeof(uint32_t));
  204 + i = htonl(i);
129 205 dest[0] = (uint16_t)i;
130 206 dest[1] = (uint16_t)(i >> 16);
131 207 }
132 208  
133   -/* Set a float to 4 bytes in inversed Modbus format (DCBA) */
134   -void modbus_set_float_dcba(float f, uint16_t *dest)
  209 +/* DEPRECATED - Set a float to 4 bytes in a sort of Modbus format! */
  210 +void modbus_set_float(float f, uint16_t *dest)
135 211 {
136 212 uint32_t i;
137 213  
138 214 memcpy(&i, &f, sizeof(uint32_t));
139   - i = bswap_32(i);
140 215 dest[0] = (uint16_t)i;
141 216 dest[1] = (uint16_t)(i >> 16);
142 217 }
... ...
src/modbus.h
... ... @@ -268,9 +268,16 @@ MODBUS_API void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int
268 268 const uint8_t *tab_byte);
269 269 MODBUS_API uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx, unsigned int nb_bits);
270 270 MODBUS_API float modbus_get_float(const uint16_t *src);
  271 +MODBUS_API float modbus_get_float_abcd(const uint16_t *src);
271 272 MODBUS_API float modbus_get_float_dcba(const uint16_t *src);
  273 +MODBUS_API float modbus_get_float_badc(const uint16_t *src);
  274 +MODBUS_API float modbus_get_float_cdab(const uint16_t *src);
  275 +
272 276 MODBUS_API void modbus_set_float(float f, uint16_t *dest);
  277 +MODBUS_API void modbus_set_float_abcd(float f, uint16_t *dest);
273 278 MODBUS_API void modbus_set_float_dcba(float f, uint16_t *dest);
  279 +MODBUS_API void modbus_set_float_badc(float f, uint16_t *dest);
  280 +MODBUS_API void modbus_set_float_cdab(float f, uint16_t *dest);
274 281  
275 282 #include "modbus-tcp.h"
276 283 #include "modbus-rtu.h"
... ...
tests/unit-test-client.c
... ... @@ -24,6 +24,7 @@ int send_crafted_request(modbus_t *ctx, int function,
24 24 uint8_t *req, int req_size,
25 25 uint16_t max_value, uint16_t bytes,
26 26 int backend_length, int backend_offset);
  27 +int equal_dword(uint16_t *tab_reg, const uint32_t value);
27 28  
28 29 #define BUG_REPORT(_cond, _format, _args ...) \
29 30 printf("\nLine %d: assertion error for '%s': " _format "\n", __LINE__, # _cond, ## _args)
... ... @@ -37,6 +38,10 @@ int send_crafted_request(modbus_t *ctx, int function,
37 38 } \
38 39 };
39 40  
  41 +int equal_dword(uint16_t *tab_reg, const uint32_t value) {
  42 + return ((tab_reg[0] == (value >> 16)) && (tab_reg[1] == (value & 0xFFFF)));
  43 +}
  44 +
40 45 int main(int argc, char *argv[])
41 46 {
42 47 const int NB_REPORT_SLAVE_ID = 10;
... ... @@ -49,7 +54,6 @@ int main(int argc, char *argv[])
49 54 int nb_points;
50 55 int rc;
51 56 float real;
52   - uint32_t ireal;
53 57 uint32_t old_response_to_sec;
54 58 uint32_t old_response_to_usec;
55 59 uint32_t new_response_to_sec;
... ... @@ -267,38 +271,6 @@ int main(int argc, char *argv[])
267 271 tab_rp_registers[i], UT_INPUT_REGISTERS_TAB[i]);
268 272 }
269 273  
270   - printf("\nTEST FLOATS\n");
271   - /** FLOAT **/
272   - printf("1/4 Set float: ");
273   - modbus_set_float(UT_REAL, tab_rp_registers);
274   - if (tab_rp_registers[1] == (UT_IREAL >> 16) &&
275   - tab_rp_registers[0] == (UT_IREAL & 0xFFFF)) {
276   - printf("OK\n");
277   - } else {
278   - /* Avoid *((uint32_t *)tab_rp_registers)
279   - * https://github.com/stephane/libmodbus/pull/104 */
280   - ireal = (uint32_t) tab_rp_registers[0] & 0xFFFF;
281   - ireal |= (uint32_t) tab_rp_registers[1] << 16;
282   - printf("FAILED (%x != %x)\n", ireal, UT_IREAL);
283   - goto close;
284   - }
285   -
286   - printf("2/4 Get float: ");
287   - real = modbus_get_float(tab_rp_registers);
288   - ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL);
289   -
290   - printf("3/4 Set float in DBCA order: ");
291   - modbus_set_float_dcba(UT_REAL, tab_rp_registers);
292   - ireal = (uint32_t) tab_rp_registers[0] & 0xFFFF;
293   - ireal |= (uint32_t) tab_rp_registers[1] << 16;
294   - ASSERT_TRUE(tab_rp_registers[1] == (UT_IREAL_DCBA >> 16) &&
295   - tab_rp_registers[0] == (UT_IREAL_DCBA & 0xFFFF),
296   - "FAILED (%x != %x)\n", ireal, UT_IREAL_DCBA);
297   -
298   - printf("4/4 Get float in DCBA order: ");
299   - real = modbus_get_float_dcba(tab_rp_registers);
300   - ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL);
301   -
302 274 /* MASKS */
303 275 printf("1/1 Write mask: ");
304 276 rc = modbus_write_register(ctx, UT_REGISTERS_ADDRESS, 0x12);
... ... @@ -309,6 +281,32 @@ int main(int argc, char *argv[])
309 281 "FAILED (%0X != %0X)\n",
310 282 tab_rp_registers[0], 0x17);
311 283  
  284 + printf("\nTEST FLOATS\n");
  285 + /** FLOAT **/
  286 + printf("1/4 Set/get float ABCD: ");
  287 + modbus_set_float_abcd(UT_REAL, tab_rp_registers);
  288 + ASSERT_TRUE(equal_dword(tab_rp_registers, UT_IREAL_ABCD), "FAILED Set float ABCD");
  289 + real = modbus_get_float_abcd(tab_rp_registers);
  290 + ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL);
  291 +
  292 + printf("2/4 Set/get float DCBA: ");
  293 + modbus_set_float_dcba(UT_REAL, tab_rp_registers);
  294 + ASSERT_TRUE(equal_dword(tab_rp_registers, UT_IREAL_DCBA), "FAILED Set float DCBA");
  295 + real = modbus_get_float_dcba(tab_rp_registers);
  296 + ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL);
  297 +
  298 + printf("3/4 Set/get float BADC: ");
  299 + modbus_set_float_badc(UT_REAL, tab_rp_registers);
  300 + ASSERT_TRUE(equal_dword(tab_rp_registers, UT_IREAL_BADC), "FAILED Set float BADC");
  301 + real = modbus_get_float_badc(tab_rp_registers);
  302 + ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL);
  303 +
  304 + printf("4/4 Set/get float CDAB: ");
  305 + modbus_set_float_cdab(UT_REAL, tab_rp_registers);
  306 + ASSERT_TRUE(equal_dword(tab_rp_registers, UT_IREAL_CDAB), "FAILED Set float CDAB");
  307 + real = modbus_get_float_cdab(tab_rp_registers);
  308 + ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL);
  309 +
312 310 printf("\nAt this point, error messages doesn't mean the test has failed\n");
313 311  
314 312 /** ILLEGAL DATA ADDRESS **/
... ...
tests/unit-test.h.in
... ... @@ -55,8 +55,16 @@ const uint16_t UT_INPUT_REGISTERS_ADDRESS = 0x108;
55 55 const uint16_t UT_INPUT_REGISTERS_NB = 0x1;
56 56 const uint16_t UT_INPUT_REGISTERS_TAB[] = { 0x000A };
57 57  
58   -const float UT_REAL = 916.540649;
59   -const uint32_t UT_IREAL = 0x4465229a;
60   -const uint32_t UT_IREAL_DCBA = 0x9a226544;
  58 +const float UT_REAL = 123456.00;
  59 +
  60 +const uint32_t UT_IREAL_ABCD = 0x0020F147;
  61 +const uint32_t UT_IREAL_DCBA = 0x47F12000;
  62 +const uint32_t UT_IREAL_BADC = 0x200047F1;
  63 +const uint32_t UT_IREAL_CDAB = 0xF1470020;
  64 +
  65 +/* const uint32_t UT_IREAL_ABCD = 0x47F12000);
  66 +const uint32_t UT_IREAL_DCBA = 0x0020F147;
  67 +const uint32_t UT_IREAL_BADC = 0xF1470020;
  68 +const uint32_t UT_IREAL_CDAB = 0x200047F1;*/
61 69  
62 70 #endif /* _UNIT_TEST_H_ */
... ...