/* * Copyright © 2010-2011 Stéphane Raimbault * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #ifndef _MSC_VER #include #else #include "stdint.h" #endif #include #include #include #include "modbus.h" /* Sets many bits from a single byte value (all 8 bits of the byte value are set) */ void modbus_set_bits_from_byte(uint8_t *dest, int index, const uint8_t value) { int i; for (i=0; i < 8; i++) { dest[index+i] = (value & (1 << i)) ? 1 : 0; } } /* Sets many bits from a table of bytes (only the bits between index and index + nb_bits are set) */ void modbus_set_bits_from_bytes(uint8_t *dest, int index, unsigned int nb_bits, const uint8_t *tab_byte) { unsigned int i; int shift = 0; for (i = index; i < index + nb_bits; i++) { dest[i] = tab_byte[(i - index) / 8] & (1 << shift) ? 1 : 0; /* gcc doesn't like: shift = (++shift) % 8; */ shift++; shift %= 8; } } /* Gets the byte value from many bits. To obtain a full byte, set nb_bits to 8. */ uint8_t modbus_get_byte_from_bits(const uint8_t *src, int index, unsigned int nb_bits) { unsigned int i; uint8_t value = 0; if (nb_bits > 8) { /* Assert is ignored if NDEBUG is set */ assert(nb_bits < 8); nb_bits = 8; } for (i=0; i < nb_bits; i++) { value |= (src[index+i] << i); } return value; } /* Get a float from 4 bytes in Modbus format (ABCD) */ 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; } /* Get a float from 4 bytes in swapped Modbus format (DCBA) */ float modbus_get_float_swapped(const uint16_t *src) { float f; uint32_t i; i = bswap_32((((uint32_t)src[1]) << 16) + src[0]); 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) { uint32_t i; memcpy(&i, &f, sizeof(uint32_t)); dest[0] = (uint16_t)i; dest[1] = (uint16_t)(i >> 16); } /* Set a float to 4 bytes in swapped Modbus format (DCBA) */ void modbus_set_float_swapped(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); }