modbus-data.c 5.2 KB

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