modbus-data.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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_16
  35. # define bswap_16 __builtin_bswap16
  36. # undef bswap_32
  37. # define bswap_32 __builtin_bswap32
  38. # endif
  39. #endif
  40. #if defined(_MSC_VER) && (_MSC_VER >= 1400)
  41. # define bswap_32 _byteswap_ulong
  42. # define bswap_16 _byteswap_ushort
  43. #endif
  44. #if !defined(__CYGWIN__) && !defined(bswap_16)
  45. # warning "Fallback on C functions for bswap_16"
  46. static inline uint16_t bswap_16(uint16_t x)
  47. {
  48. return (x >> 8) | (x << 8);
  49. }
  50. #endif
  51. #if !defined(bswap_32)
  52. # warning "Fallback on C functions for bswap_32"
  53. static inline uint32_t bswap_32(uint32_t x)
  54. {
  55. return (bswap_16(x & 0xffff) << 16) | (bswap_16(x >> 16));
  56. }
  57. #endif
  58. /* Sets many bits from a single byte value (all 8 bits of the byte value are
  59. set) */
  60. void modbus_set_bits_from_byte(uint8_t *dest, int idx, const uint8_t value)
  61. {
  62. int i;
  63. for (i=0; i < 8; i++) {
  64. dest[idx+i] = (value & (1 << i)) ? 1 : 0;
  65. }
  66. }
  67. /* Sets many bits from a table of bytes (only the bits between idx and
  68. idx + nb_bits are set) */
  69. void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int nb_bits,
  70. const uint8_t *tab_byte)
  71. {
  72. unsigned int i;
  73. int shift = 0;
  74. for (i = idx; i < idx + nb_bits; i++) {
  75. dest[i] = tab_byte[(i - idx) / 8] & (1 << shift) ? 1 : 0;
  76. /* gcc doesn't like: shift = (++shift) % 8; */
  77. shift++;
  78. shift %= 8;
  79. }
  80. }
  81. /* Gets the byte value from many bits.
  82. To obtain a full byte, set nb_bits to 8. */
  83. uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx,
  84. unsigned int nb_bits)
  85. {
  86. unsigned int i;
  87. uint8_t value = 0;
  88. if (nb_bits > 8) {
  89. /* Assert is ignored if NDEBUG is set */
  90. assert(nb_bits < 8);
  91. nb_bits = 8;
  92. }
  93. for (i=0; i < nb_bits; i++) {
  94. value |= (src[idx+i] << i);
  95. }
  96. return value;
  97. }
  98. /* Get a float from 4 bytes (Modbus) without any conversion (ABCD) */
  99. float modbus_get_float_abcd(const uint16_t *src)
  100. {
  101. float f;
  102. uint32_t i;
  103. i = ntohl(((uint32_t)src[0] << 16) + src[1]);
  104. memcpy(&f, &i, sizeof(float));
  105. return f;
  106. }
  107. /* Get a float from 4 bytes (Modbus) in inversed format (DCBA) */
  108. float modbus_get_float_dcba(const uint16_t *src)
  109. {
  110. float f;
  111. uint32_t i;
  112. i = ntohl(bswap_32((((uint32_t)src[0]) << 16) + src[1]));
  113. memcpy(&f, &i, sizeof(float));
  114. return f;
  115. }
  116. /* Get a float from 4 bytes (Modbus) with swapped bytes (BADC) */
  117. float modbus_get_float_badc(const uint16_t *src)
  118. {
  119. float f;
  120. uint32_t i;
  121. i = ntohl((uint32_t)(bswap_16(src[0]) << 16) + bswap_16(src[1]));
  122. memcpy(&f, &i, sizeof(float));
  123. return f;
  124. }
  125. /* Get a float from 4 bytes (Modbus) with swapped words (CDAB) */
  126. float modbus_get_float_cdab(const uint16_t *src)
  127. {
  128. float f;
  129. uint32_t i;
  130. i = ntohl((((uint32_t)src[1]) << 16) + src[0]);
  131. memcpy(&f, &i, sizeof(float));
  132. return f;
  133. }
  134. /* DEPRECATED - Get a float from 4 bytes in sort of Modbus format */
  135. float modbus_get_float(const uint16_t *src)
  136. {
  137. float f;
  138. uint32_t i;
  139. i = (((uint32_t)src[1]) << 16) + src[0];
  140. memcpy(&f, &i, sizeof(float));
  141. return f;
  142. }
  143. /* Set a float to 4 bytes for Modbus w/o any conversion (ABCD) */
  144. void modbus_set_float_abcd(float f, uint16_t *dest)
  145. {
  146. uint32_t i;
  147. memcpy(&i, &f, sizeof(uint32_t));
  148. i = htonl(i);
  149. dest[0] = (uint16_t)(i >> 16);
  150. dest[1] = (uint16_t)i;
  151. }
  152. /* Set a float to 4 bytes for Modbus with byte and word swap conversion (DCBA) */
  153. void modbus_set_float_dcba(float f, uint16_t *dest)
  154. {
  155. uint32_t i;
  156. memcpy(&i, &f, sizeof(uint32_t));
  157. i = bswap_32(htonl(i));
  158. dest[0] = (uint16_t)(i >> 16);
  159. dest[1] = (uint16_t)i;
  160. }
  161. /* Set a float to 4 bytes for Modbus with byte swap conversion (BADC) */
  162. void modbus_set_float_badc(float f, uint16_t *dest)
  163. {
  164. uint32_t i;
  165. memcpy(&i, &f, sizeof(uint32_t));
  166. i = htonl(i);
  167. dest[0] = (uint16_t)bswap_16(i >> 16);
  168. dest[1] = (uint16_t)bswap_16(i & 0xFFFF);
  169. }
  170. /* Set a float to 4 bytes for Modbus with word swap conversion (CDAB) */
  171. void modbus_set_float_cdab(float f, uint16_t *dest)
  172. {
  173. uint32_t i;
  174. memcpy(&i, &f, sizeof(uint32_t));
  175. i = htonl(i);
  176. dest[0] = (uint16_t)i;
  177. dest[1] = (uint16_t)(i >> 16);
  178. }
  179. /* DEPRECATED - Set a float to 4 bytes in a sort of Modbus format! */
  180. void modbus_set_float(float f, uint16_t *dest)
  181. {
  182. uint32_t i;
  183. memcpy(&i, &f, sizeof(uint32_t));
  184. dest[0] = (uint16_t)i;
  185. dest[1] = (uint16_t)(i >> 16);
  186. }