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,6 +11,8 @@ SYNOPSIS
11 -------- 11 --------
12 *float modbus_get_float(const uint16_t *'src');* 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 DESCRIPTION 17 DESCRIPTION
16 ----------- 18 -----------
doc/modbus_get_float_dcba.txt
@@ -15,9 +15,9 @@ SYNOPSIS @@ -15,9 +15,9 @@ SYNOPSIS
15 DESCRIPTION 15 DESCRIPTION
16 ----------- 16 -----------
17 The *modbus_get_float_dcba()* function shall get a float from 4 bytes in 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 RETURN VALUE 23 RETURN VALUE
@@ -28,8 +28,6 @@ The function shall return a float. @@ -28,8 +28,6 @@ The function shall return a float.
28 SEE ALSO 28 SEE ALSO
29 -------- 29 --------
30 linkmb:modbus_set_float_dcba[3] 30 linkmb:modbus_set_float_dcba[3]
31 -linkmb:modbus_set_float[3]  
32 -linkmb:modbus_get_float[3]  
33 31
34 32
35 AUTHORS 33 AUTHORS
doc/modbus_set_float.txt
1 modbus_set_float(3) 1 modbus_set_float(3)
2 =================== 2 ===================
3 3
4 -  
5 NAME 4 NAME
6 ---- 5 ----
7 modbus_set_float - set a float value from 2 registers 6 modbus_set_float - set a float value from 2 registers
@@ -11,6 +10,8 @@ SYNOPSIS @@ -11,6 +10,8 @@ SYNOPSIS
11 -------- 10 --------
12 *void modbus_set_float(float 'f', uint16_t *'dest');* 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 DESCRIPTION 16 DESCRIPTION
16 ----------- 17 -----------
@@ -26,9 +27,8 @@ There is no return values. @@ -26,9 +27,8 @@ There is no return values.
26 27
27 SEE ALSO 28 SEE ALSO
28 -------- 29 --------
29 -linkmb:modbus_set_float[3] 30 +linkmb:modbus_get_float[3]
30 linkmb:modbus_set_float_dcba[3] 31 linkmb:modbus_set_float_dcba[3]
31 -linkmb:modbus_get_float_dcba[3]  
32 32
33 AUTHORS 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 * SPDX-License-Identifier: LGPL-2.1+ 4 * SPDX-License-Identifier: LGPL-2.1+
5 */ 5 */
@@ -13,6 +13,12 @@ @@ -13,6 +13,12 @@
13 #include <string.h> 13 #include <string.h>
14 #include <assert.h> 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 #include "modbus.h" 22 #include "modbus.h"
17 23
18 #if defined(HAVE_BYTESWAP_H) 24 #if defined(HAVE_BYTESWAP_H)
@@ -96,47 +102,116 @@ uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx, @@ -96,47 +102,116 @@ uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx,
96 return value; 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 float f; 108 float f;
103 uint32_t i; 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 memcpy(&f, &i, sizeof(float)); 112 memcpy(&f, &i, sizeof(float));
107 113
108 return f; 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 float modbus_get_float_dcba(const uint16_t *src) 118 float modbus_get_float_dcba(const uint16_t *src)
113 { 119 {
114 float f; 120 float f;
115 uint32_t i; 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 memcpy(&f, &i, sizeof(float)); 124 memcpy(&f, &i, sizeof(float));
119 125
120 return f; 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 uint32_t i; 179 uint32_t i;
127 180
128 memcpy(&i, &f, sizeof(uint32_t)); 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 dest[0] = (uint16_t)i; 205 dest[0] = (uint16_t)i;
130 dest[1] = (uint16_t)(i >> 16); 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 uint32_t i; 212 uint32_t i;
137 213
138 memcpy(&i, &f, sizeof(uint32_t)); 214 memcpy(&i, &f, sizeof(uint32_t));
139 - i = bswap_32(i);  
140 dest[0] = (uint16_t)i; 215 dest[0] = (uint16_t)i;
141 dest[1] = (uint16_t)(i >> 16); 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,9 +268,16 @@ MODBUS_API void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int
268 const uint8_t *tab_byte); 268 const uint8_t *tab_byte);
269 MODBUS_API uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx, unsigned int nb_bits); 269 MODBUS_API uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx, unsigned int nb_bits);
270 MODBUS_API float modbus_get_float(const uint16_t *src); 270 MODBUS_API float modbus_get_float(const uint16_t *src);
  271 +MODBUS_API float modbus_get_float_abcd(const uint16_t *src);
271 MODBUS_API float modbus_get_float_dcba(const uint16_t *src); 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 MODBUS_API void modbus_set_float(float f, uint16_t *dest); 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 MODBUS_API void modbus_set_float_dcba(float f, uint16_t *dest); 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 #include "modbus-tcp.h" 282 #include "modbus-tcp.h"
276 #include "modbus-rtu.h" 283 #include "modbus-rtu.h"
tests/unit-test-client.c
@@ -24,6 +24,7 @@ int send_crafted_request(modbus_t *ctx, int function, @@ -24,6 +24,7 @@ int send_crafted_request(modbus_t *ctx, int function,
24 uint8_t *req, int req_size, 24 uint8_t *req, int req_size,
25 uint16_t max_value, uint16_t bytes, 25 uint16_t max_value, uint16_t bytes,
26 int backend_length, int backend_offset); 26 int backend_length, int backend_offset);
  27 +int equal_dword(uint16_t *tab_reg, const uint32_t value);
27 28
28 #define BUG_REPORT(_cond, _format, _args ...) \ 29 #define BUG_REPORT(_cond, _format, _args ...) \
29 printf("\nLine %d: assertion error for '%s': " _format "\n", __LINE__, # _cond, ## _args) 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,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 int main(int argc, char *argv[]) 45 int main(int argc, char *argv[])
41 { 46 {
42 const int NB_REPORT_SLAVE_ID = 10; 47 const int NB_REPORT_SLAVE_ID = 10;
@@ -49,7 +54,6 @@ int main(int argc, char *argv[]) @@ -49,7 +54,6 @@ int main(int argc, char *argv[])
49 int nb_points; 54 int nb_points;
50 int rc; 55 int rc;
51 float real; 56 float real;
52 - uint32_t ireal;  
53 uint32_t old_response_to_sec; 57 uint32_t old_response_to_sec;
54 uint32_t old_response_to_usec; 58 uint32_t old_response_to_usec;
55 uint32_t new_response_to_sec; 59 uint32_t new_response_to_sec;
@@ -267,38 +271,6 @@ int main(int argc, char *argv[]) @@ -267,38 +271,6 @@ int main(int argc, char *argv[])
267 tab_rp_registers[i], UT_INPUT_REGISTERS_TAB[i]); 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 /* MASKS */ 274 /* MASKS */
303 printf("1/1 Write mask: "); 275 printf("1/1 Write mask: ");
304 rc = modbus_write_register(ctx, UT_REGISTERS_ADDRESS, 0x12); 276 rc = modbus_write_register(ctx, UT_REGISTERS_ADDRESS, 0x12);
@@ -309,6 +281,32 @@ int main(int argc, char *argv[]) @@ -309,6 +281,32 @@ int main(int argc, char *argv[])
309 "FAILED (%0X != %0X)\n", 281 "FAILED (%0X != %0X)\n",
310 tab_rp_registers[0], 0x17); 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 printf("\nAt this point, error messages doesn't mean the test has failed\n"); 310 printf("\nAt this point, error messages doesn't mean the test has failed\n");
313 311
314 /** ILLEGAL DATA ADDRESS **/ 312 /** ILLEGAL DATA ADDRESS **/
tests/unit-test.h.in
@@ -55,8 +55,16 @@ const uint16_t UT_INPUT_REGISTERS_ADDRESS = 0x108; @@ -55,8 +55,16 @@ const uint16_t UT_INPUT_REGISTERS_ADDRESS = 0x108;
55 const uint16_t UT_INPUT_REGISTERS_NB = 0x1; 55 const uint16_t UT_INPUT_REGISTERS_NB = 0x1;
56 const uint16_t UT_INPUT_REGISTERS_TAB[] = { 0x000A }; 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 #endif /* _UNIT_TEST_H_ */ 70 #endif /* _UNIT_TEST_H_ */