Эх сурвалжийг харах

Rewrite and extend functions to manipulate float values

Stéphane Raimbault 11 жил өмнө
parent
commit
08ed259fe6

+ 2 - 0
doc/modbus_get_float.txt

@@ -11,6 +11,8 @@ SYNOPSIS
 --------
 *float modbus_get_float(const uint16_t *'src');*
 
+Warning, this function is *deprecated* since libmodbus v3.2.0 and has been
+replaced by *modbus_get_float_dcba()*.
 
 DESCRIPTION
 -----------

+ 3 - 5
doc/modbus_get_float_dcba.txt

@@ -15,9 +15,9 @@ SYNOPSIS
 DESCRIPTION
 -----------
 The *modbus_get_float_dcba()* function shall get a float from 4 bytes in
-inversed Modbus format (DCBA order). The _src_ array must be pointer on two 16
-bits values, for example, if the first word is set to 0x9a22 and the second to
-0x6544, the float value read will be 916.540649.
+inversed Modbus format (DCBA order instead of ABCD). The _src_ array must be
+pointer on two 16 bits values, for example, if the first word is set to 0x9a22
+and the second to 0x6544, the float value read will be 916.540649.
 
 
 RETURN VALUE
@@ -28,8 +28,6 @@ The function shall return a float.
 SEE ALSO
 --------
 linkmb:modbus_set_float_dcba[3]
-linkmb:modbus_set_float[3]
-linkmb:modbus_get_float[3]
 
 
 AUTHORS

+ 3 - 3
doc/modbus_set_float.txt

@@ -1,7 +1,6 @@
 modbus_set_float(3)
 ===================
 
-
 NAME
 ----
 modbus_set_float - set a float value from 2 registers
@@ -11,6 +10,8 @@ SYNOPSIS
 --------
 *void modbus_set_float(float 'f', uint16_t *'dest');*
 
+Warning, this function is *deprecated* since libmodbus v3.2.0 and has been
+replaced by *modbus_set_float_dcba()*.
 
 DESCRIPTION
 -----------
@@ -26,9 +27,8 @@ There is no return values.
 
 SEE ALSO
 --------
-linkmb:modbus_set_float[3]
+linkmb:modbus_get_float[3]
 linkmb:modbus_set_float_dcba[3]
-linkmb:modbus_get_float_dcba[3]
 
 AUTHORS
 -------

+ 86 - 11
src/modbus-data.c

@@ -1,5 +1,5 @@
 /*
- * Copyright © 2010-2011 Stéphane Raimbault <stephane.raimbault@gmail.com>
+ * Copyright © 2010-2014 Stéphane Raimbault <stephane.raimbault@gmail.com>
  *
  * SPDX-License-Identifier: LGPL-2.1+
  */
@@ -13,6 +13,12 @@
 #include <string.h>
 #include <assert.h>
 
+#if defined(_WIN32)
+# include <winsock2.h>
+#else
+# include <arpa/inet.h>
+#endif
+
 #include "modbus.h"
 
 #if defined(HAVE_BYTESWAP_H)
@@ -96,47 +102,116 @@ uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx,
     return value;
 }
 
-/* Get a float from 4 bytes in Modbus format (ABCD) */
-float modbus_get_float(const uint16_t *src)
+/* Get a float from 4 bytes (Modbus) without any conversion (ABCD) */
+float modbus_get_float_abcd(const uint16_t *src)
 {
     float f;
     uint32_t i;
 
-    i = (((uint32_t)src[1]) << 16) + src[0];
+    i = ntohl(((uint32_t)src[0] << 16) + src[1]);
     memcpy(&f, &i, sizeof(float));
 
     return f;
 }
 
-/* Get a float from 4 bytes in inversed Modbus format (DCBA) */
+/* Get a float from 4 bytes (Modbus) with byte and word swap conversion (DCBA) */
 float modbus_get_float_dcba(const uint16_t *src)
 {
     float f;
     uint32_t i;
 
-    i = bswap_32((((uint32_t)src[1]) << 16) + src[0]);
+    i = ntohl(bswap_32((((uint32_t)src[0]) << 16) + src[1]));
     memcpy(&f, &i, sizeof(float));
 
     return f;
 }
 
-/* Set a float to 4 bytes in Modbus format (ABCD) */
-void modbus_set_float(float f, uint16_t *dest)
+/* Get a float from 4 bytes (Modbus) with byte swap conversion (BADC) */
+float modbus_get_float_badc(const uint16_t *src)
+{
+    float f;
+    uint32_t i;
+
+    i = ntohl((uint32_t)(bswap_16(src[0]) << 16) + bswap_16(src[1]));
+    memcpy(&f, &i, sizeof(float));
+
+    return f;
+}
+
+/* Get a float from 4 bytes (Modbus) in the format CDAB */
+float modbus_get_float_cdab(const uint16_t *src)
+{
+    float f;
+    uint32_t i;
+
+    i = ntohl((((uint32_t)src[1]) << 16) + src[0]);
+    memcpy(&f, &i, sizeof(float));
+
+    return f;
+}
+
+/* DEPRECATED - Get a float from 4 bytes in sort of Modbus format */
+float modbus_get_float(const uint16_t *src)
+{
+    float f;
+    uint32_t i;
+
+    i = (((uint32_t)src[1]) << 16) + src[0];
+    memcpy(&f, &i, sizeof(float));
+
+    return f;
+}
+
+/* Set a float to 4 bytes for Modbus w/o any conversion (ABCD) */
+void modbus_set_float_abcd(float f, uint16_t *dest)
+{
+    uint32_t i;
+
+    memcpy(&i, &f, sizeof(uint32_t));
+    i = htonl(i);
+    dest[0] = (uint16_t)(i >> 16);
+    dest[1] = (uint16_t)i;
+}
+
+/* Set a float to 4 bytes for Modbus with byte and word swap conversion (DCBA) */
+void modbus_set_float_dcba(float f, uint16_t *dest)
 {
     uint32_t i;
 
     memcpy(&i, &f, sizeof(uint32_t));
+    i = bswap_32(htonl(i));
+    dest[0] = (uint16_t)(i >> 16);
+    dest[1] = (uint16_t)i;
+}
+
+/* Set a float to 4 bytes for Modbus with byte swap conversion (BADC) */
+void modbus_set_float_badc(float f, uint16_t *dest)
+{
+    uint32_t i;
+
+    memcpy(&i, &f, sizeof(uint32_t));
+    i = htonl(i);
+    dest[0] = (uint16_t)bswap_16(i >> 16);
+    dest[1] = (uint16_t)bswap_16(i & 0xFFFF);
+}
+
+/* Set a float to 4 bytes for Modbus with word swap conversion (CDAB) */
+void modbus_set_float_cdab(float f, uint16_t *dest)
+{
+    uint32_t i;
+
+    memcpy(&i, &f, sizeof(uint32_t));
+    i = htonl(i);
     dest[0] = (uint16_t)i;
     dest[1] = (uint16_t)(i >> 16);
 }
 
-/* Set a float to 4 bytes in inversed Modbus format (DCBA) */
-void modbus_set_float_dcba(float f, uint16_t *dest)
+/* DEPRECATED - Set a float to 4 bytes in a sort of Modbus format! */
+void modbus_set_float(float f, uint16_t *dest)
 {
     uint32_t i;
 
     memcpy(&i, &f, sizeof(uint32_t));
-    i = bswap_32(i);
     dest[0] = (uint16_t)i;
     dest[1] = (uint16_t)(i >> 16);
 }

+ 7 - 0
src/modbus.h

@@ -268,9 +268,16 @@ MODBUS_API void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int
                                        const uint8_t *tab_byte);
 MODBUS_API uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx, unsigned int nb_bits);
 MODBUS_API float modbus_get_float(const uint16_t *src);
+MODBUS_API float modbus_get_float_abcd(const uint16_t *src);
 MODBUS_API float modbus_get_float_dcba(const uint16_t *src);
+MODBUS_API float modbus_get_float_badc(const uint16_t *src);
+MODBUS_API float modbus_get_float_cdab(const uint16_t *src);
+
 MODBUS_API void modbus_set_float(float f, uint16_t *dest);
+MODBUS_API void modbus_set_float_abcd(float f, uint16_t *dest);
 MODBUS_API void modbus_set_float_dcba(float f, uint16_t *dest);
+MODBUS_API void modbus_set_float_badc(float f, uint16_t *dest);
+MODBUS_API void modbus_set_float_cdab(float f, uint16_t *dest);
 
 #include "modbus-tcp.h"
 #include "modbus-rtu.h"

+ 31 - 33
tests/unit-test-client.c

@@ -24,6 +24,7 @@ int send_crafted_request(modbus_t *ctx, int function,
                          uint8_t *req, int req_size,
                          uint16_t max_value, uint16_t bytes,
                          int backend_length, int backend_offset);
+int equal_dword(uint16_t *tab_reg, const uint32_t value);
 
 #define BUG_REPORT(_cond, _format, _args ...) \
     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,
     }                                             \
 };
 
+int equal_dword(uint16_t *tab_reg, const uint32_t value) {
+    return ((tab_reg[0] == (value >> 16)) && (tab_reg[1] == (value & 0xFFFF)));
+}
+
 int main(int argc, char *argv[])
 {
     const int NB_REPORT_SLAVE_ID = 10;
@@ -49,7 +54,6 @@ int main(int argc, char *argv[])
     int nb_points;
     int rc;
     float real;
-    uint32_t ireal;
     uint32_t old_response_to_sec;
     uint32_t old_response_to_usec;
     uint32_t new_response_to_sec;
@@ -267,38 +271,6 @@ int main(int argc, char *argv[])
                     tab_rp_registers[i], UT_INPUT_REGISTERS_TAB[i]);
     }
 
-    printf("\nTEST FLOATS\n");
-    /** FLOAT **/
-    printf("1/4 Set float: ");
-    modbus_set_float(UT_REAL, tab_rp_registers);
-    if (tab_rp_registers[1] == (UT_IREAL >> 16) &&
-        tab_rp_registers[0] == (UT_IREAL & 0xFFFF)) {
-        printf("OK\n");
-    } else {
-        /* Avoid *((uint32_t *)tab_rp_registers)
-         * https://github.com/stephane/libmodbus/pull/104 */
-        ireal = (uint32_t) tab_rp_registers[0] & 0xFFFF;
-        ireal |= (uint32_t) tab_rp_registers[1] << 16;
-        printf("FAILED (%x != %x)\n", ireal, UT_IREAL);
-        goto close;
-    }
-
-    printf("2/4 Get float: ");
-    real = modbus_get_float(tab_rp_registers);
-    ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL);
-
-    printf("3/4 Set float in DBCA order: ");
-    modbus_set_float_dcba(UT_REAL, tab_rp_registers);
-    ireal = (uint32_t) tab_rp_registers[0] & 0xFFFF;
-    ireal |= (uint32_t) tab_rp_registers[1] << 16;
-    ASSERT_TRUE(tab_rp_registers[1] == (UT_IREAL_DCBA >> 16) &&
-                tab_rp_registers[0] == (UT_IREAL_DCBA & 0xFFFF),
-                "FAILED (%x != %x)\n", ireal, UT_IREAL_DCBA);
-
-    printf("4/4 Get float in DCBA order: ");
-    real = modbus_get_float_dcba(tab_rp_registers);
-    ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL);
-
     /* MASKS */
     printf("1/1 Write mask: ");
     rc = modbus_write_register(ctx, UT_REGISTERS_ADDRESS, 0x12);
@@ -309,6 +281,32 @@ int main(int argc, char *argv[])
                 "FAILED (%0X != %0X)\n",
                 tab_rp_registers[0], 0x17);
 
+    printf("\nTEST FLOATS\n");
+    /** FLOAT **/
+    printf("1/4 Set/get float ABCD: ");
+    modbus_set_float_abcd(UT_REAL, tab_rp_registers);
+    ASSERT_TRUE(equal_dword(tab_rp_registers, UT_IREAL_ABCD), "FAILED Set float ABCD");
+    real = modbus_get_float_abcd(tab_rp_registers);
+    ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL);
+
+    printf("2/4 Set/get float DCBA: ");
+    modbus_set_float_dcba(UT_REAL, tab_rp_registers);
+    ASSERT_TRUE(equal_dword(tab_rp_registers, UT_IREAL_DCBA), "FAILED Set float DCBA");
+    real = modbus_get_float_dcba(tab_rp_registers);
+    ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL);
+
+    printf("3/4 Set/get float BADC: ");
+    modbus_set_float_badc(UT_REAL, tab_rp_registers);
+    ASSERT_TRUE(equal_dword(tab_rp_registers, UT_IREAL_BADC), "FAILED Set float BADC");
+    real = modbus_get_float_badc(tab_rp_registers);
+    ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL);
+
+    printf("4/4 Set/get float CDAB: ");
+    modbus_set_float_cdab(UT_REAL, tab_rp_registers);
+    ASSERT_TRUE(equal_dword(tab_rp_registers, UT_IREAL_CDAB), "FAILED Set float CDAB");
+    real = modbus_get_float_cdab(tab_rp_registers);
+    ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL);
+
     printf("\nAt this point, error messages doesn't mean the test has failed\n");
 
     /** ILLEGAL DATA ADDRESS **/

+ 11 - 3
tests/unit-test.h.in

@@ -55,8 +55,16 @@ const uint16_t UT_INPUT_REGISTERS_ADDRESS = 0x108;
 const uint16_t UT_INPUT_REGISTERS_NB = 0x1;
 const uint16_t UT_INPUT_REGISTERS_TAB[] = { 0x000A };
 
-const float UT_REAL = 916.540649;
-const uint32_t UT_IREAL = 0x4465229a;
-const uint32_t UT_IREAL_DCBA = 0x9a226544;
+const float UT_REAL = 123456.00;
+
+const uint32_t UT_IREAL_ABCD = 0x0020F147;
+const uint32_t UT_IREAL_DCBA = 0x47F12000;
+const uint32_t UT_IREAL_BADC = 0x200047F1;
+const uint32_t UT_IREAL_CDAB = 0xF1470020;
+
+/* const uint32_t UT_IREAL_ABCD = 0x47F12000);
+const uint32_t UT_IREAL_DCBA = 0x0020F147;
+const uint32_t UT_IREAL_BADC = 0xF1470020;
+const uint32_t UT_IREAL_CDAB = 0x200047F1;*/
 
 #endif /* _UNIT_TEST_H_ */