modbus-data.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Copyright © 2010-2014 Stéphane Raimbault <stephane.raimbault@gmail.com>
  3. *
  4. * SPDX-License-Identifier: LGPL-2.1+
  5. */
  6. #include <stdlib.h>
  7. #ifndef _MSC_VER
  8. # include <stdint.h>
  9. #else
  10. # include "stdint.h"
  11. #endif
  12. #include <string.h>
  13. #include <assert.h>
  14. #if defined(_WIN32)
  15. # include <winsock2.h>
  16. #else
  17. # include <arpa/inet.h>
  18. #endif
  19. #include <config.h>
  20. #include "modbus.h"
  21. #if defined(HAVE_BYTESWAP_H)
  22. # include <byteswap.h>
  23. #endif
  24. #if defined(__APPLE__)
  25. # include <libkern/OSByteOrder.h>
  26. # define bswap_16 OSSwapInt16
  27. # define bswap_32 OSSwapInt32
  28. # define bswap_64 OSSwapInt64
  29. #endif
  30. #if defined(__GNUC__)
  31. # define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10)
  32. # if GCC_VERSION >= 430
  33. // Since GCC >= 4.30, GCC provides __builtin_bswapXX() alternatives so we switch to them
  34. # undef bswap_32
  35. # define bswap_32 __builtin_bswap32
  36. # endif
  37. #endif
  38. #if defined(_MSC_VER) && (_MSC_VER >= 1400)
  39. # define bswap_32 _byteswap_ulong
  40. # define bswap_16 _byteswap_ushort
  41. #endif
  42. #if !defined(__CYGWIN__) && !defined(bswap_16)
  43. # warning "Fallback on C functions for bswap_16"
  44. static inline uint16_t bswap_16(uint16_t x)
  45. {
  46. return (x >> 8) | (x << 8);
  47. }
  48. #endif
  49. #if !defined(bswap_32)
  50. # warning "Fallback on C functions for bswap_32"
  51. static inline uint32_t bswap_32(uint32_t x)
  52. {
  53. return (bswap_16(x & 0xffff) << 16) | (bswap_16(x >> 16));
  54. }
  55. #endif
  56. /* Sets many bits from a single byte value (all 8 bits of the byte value are
  57. set) */
  58. void modbus_set_bits_from_byte(uint8_t *dest, int idx, const uint8_t value)
  59. {
  60. int i;
  61. for (i=0; i < 8; i++) {
  62. dest[idx+i] = (value & (1 << i)) ? 1 : 0;
  63. }
  64. }
  65. /* Sets many bits from a table of bytes (only the bits between idx and
  66. idx + nb_bits are set) */
  67. void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int nb_bits,
  68. const uint8_t *tab_byte)
  69. {
  70. unsigned int i;
  71. int shift = 0;
  72. for (i = idx; i < idx + nb_bits; i++) {
  73. dest[i] = tab_byte[(i - idx) / 8] & (1 << shift) ? 1 : 0;
  74. /* gcc doesn't like: shift = (++shift) % 8; */
  75. shift++;
  76. shift %= 8;
  77. }
  78. }
  79. /* Gets the byte value from many bits.
  80. To obtain a full byte, set nb_bits to 8. */
  81. uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx,
  82. unsigned int nb_bits)
  83. {
  84. unsigned int i;
  85. uint8_t value = 0;
  86. if (nb_bits > 8) {
  87. /* Assert is ignored if NDEBUG is set */
  88. assert(nb_bits < 8);
  89. nb_bits = 8;
  90. }
  91. for (i=0; i < nb_bits; i++) {
  92. value |= (src[idx+i] << i);
  93. }
  94. return value;
  95. }
  96. /* Get a float from 4 bytes (Modbus) without any conversion (ABCD) */
  97. float modbus_get_float_abcd(const uint16_t *src)
  98. {
  99. float f;
  100. uint32_t i;
  101. i = ntohl(((uint32_t)src[0] << 16) + src[1]);
  102. memcpy(&f, &i, sizeof(float));
  103. return f;
  104. }
  105. /* Get a float from 4 bytes (Modbus) in inversed format (DCBA) */
  106. float modbus_get_float_dcba(const uint16_t *src)
  107. {
  108. float f;
  109. uint32_t i;
  110. i = ntohl(bswap_32((((uint32_t)src[0]) << 16) + src[1]));
  111. memcpy(&f, &i, sizeof(float));
  112. return f;
  113. }
  114. /* Get a float from 4 bytes (Modbus) with swapped bytes (BADC) */
  115. float modbus_get_float_badc(const uint16_t *src)
  116. {
  117. float f;
  118. uint32_t i;
  119. i = ntohl((uint32_t)(bswap_16(src[0]) << 16) + bswap_16(src[1]));
  120. memcpy(&f, &i, sizeof(float));
  121. return f;
  122. }
  123. /* Get a float from 4 bytes (Modbus) with swapped words (CDAB) */
  124. float modbus_get_float_cdab(const uint16_t *src)
  125. {
  126. float f;
  127. uint32_t i;
  128. i = ntohl((((uint32_t)src[1]) << 16) + src[0]);
  129. memcpy(&f, &i, sizeof(float));
  130. return f;
  131. }
  132. /* DEPRECATED - Get a float from 4 bytes in sort of Modbus format */
  133. float modbus_get_float(const uint16_t *src)
  134. {
  135. float f;
  136. uint32_t i;
  137. i = (((uint32_t)src[1]) << 16) + src[0];
  138. memcpy(&f, &i, sizeof(float));
  139. return f;
  140. }
  141. /* Set a float to 4 bytes for Modbus w/o any conversion (ABCD) */
  142. void modbus_set_float_abcd(float f, uint16_t *dest)
  143. {
  144. uint32_t i;
  145. memcpy(&i, &f, sizeof(uint32_t));
  146. i = htonl(i);
  147. dest[0] = (uint16_t)(i >> 16);
  148. dest[1] = (uint16_t)i;
  149. }
  150. /* Set a float to 4 bytes for Modbus with byte and word swap conversion (DCBA) */
  151. void modbus_set_float_dcba(float f, uint16_t *dest)
  152. {
  153. uint32_t i;
  154. memcpy(&i, &f, sizeof(uint32_t));
  155. i = bswap_32(htonl(i));
  156. dest[0] = (uint16_t)(i >> 16);
  157. dest[1] = (uint16_t)i;
  158. }
  159. /* Set a float to 4 bytes for Modbus with byte swap conversion (BADC) */
  160. void modbus_set_float_badc(float f, uint16_t *dest)
  161. {
  162. uint32_t i;
  163. memcpy(&i, &f, sizeof(uint32_t));
  164. i = htonl(i);
  165. dest[0] = (uint16_t)bswap_16(i >> 16);
  166. dest[1] = (uint16_t)bswap_16(i & 0xFFFF);
  167. }
  168. /* Set a float to 4 bytes for Modbus with word swap conversion (CDAB) */
  169. void modbus_set_float_cdab(float f, uint16_t *dest)
  170. {
  171. uint32_t i;
  172. memcpy(&i, &f, sizeof(uint32_t));
  173. i = htonl(i);
  174. dest[0] = (uint16_t)i;
  175. dest[1] = (uint16_t)(i >> 16);
  176. }
  177. /* DEPRECATED - Set a float to 4 bytes in a sort of Modbus format! */
  178. void modbus_set_float(float f, uint16_t *dest)
  179. {
  180. uint32_t i;
  181. memcpy(&i, &f, sizeof(uint32_t));
  182. dest[0] = (uint16_t)i;
  183. dest[1] = (uint16_t)(i >> 16);
  184. }