/*Copyright 2016 Benjamin Vedder benjamin@vedder.seThis file is part of the VESC firmware.The VESC firmware is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.The VESC firmware is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program. If not, see <http://www.gnu.org/licenses/>.*/#include "buffer.h"#include <math.h>#include <stdbool.h>void buffer_append_int16(uint8_t* buffer, int16_t number, int32_t *index) {buffer[(*index)++] = number >> 8;buffer[(*index)++] = number;}void buffer_append_uint16(uint8_t* buffer, uint16_t number, int32_t *index) {buffer[(*index)++] = number >> 8;buffer[(*index)++] = number;}void buffer_append_int32(uint8_t* buffer, int32_t number, int32_t *index) {buffer[(*index)++] = number >> 24;buffer[(*index)++] = number >> 16;buffer[(*index)++] = number >> 8;buffer[(*index)++] = number;}void buffer_append_uint32(uint8_t* buffer, uint32_t number, int32_t *index) {buffer[(*index)++] = number >> 24;buffer[(*index)++] = number >> 16;buffer[(*index)++] = number >> 8;buffer[(*index)++] = number;}void buffer_append_float16(uint8_t* buffer, float number, float scale, int32_t *index) {buffer_append_int16(buffer, (int16_t)(number * scale), index);}void buffer_append_float32(uint8_t* buffer, float number, float scale, int32_t *index) {buffer_append_int32(buffer, (int32_t)(number * scale), index);}/** See my question:* http://stackoverflow.com/questions/40416682/portable-way-to-serialize-float-as-32-bit-integer** Regarding the float32_auto functions:** Noticed that frexp and ldexp fit the format of the IEEE float representation, so* they should be quite fast. They are (more or less) equivalent with the following:** float frexp_slow(float f, int *e) {* if (f == 0.0) {* *e = 0;* return 0.0;* }** *e = ceilf(log2f(fabsf(f)));* float res = f / powf(2.0, (float)*e);** if (res >= 1.0) {* res -= 0.5;* *e += 1;* }** if (res <= -1.0) {* res += 0.5;* *e += 1;* }** return res;* }** float ldexp_slow(float f, int e) {* return f * powf(2.0, (float)e);* }** 8388608.0 is 2^23, which scales the result to fit within 23 bits if sig_abs < 1.0.** This should be a relatively fast and efficient way to serialize* floating point numbers in a fully defined manner.*/void buffer_append_float32_auto(uint8_t* buffer, float number, int32_t *index) {int e = 0;float sig = frexpf(number, &e);float sig_abs = fabsf(sig);uint32_t sig_i = 0;if (sig_abs >= 0.5) {sig_i = (uint32_t)((sig_abs - 0.5f) * 2.0f * 8388608.0f);e += 126;}uint32_t res = ((e & 0xFF) << 23) | (sig_i & 0x7FFFFF);if (sig < 0) {res |= 1U << 31;}buffer_append_uint32(buffer, res, index);}int16_t buffer_get_int16(const uint8_t *buffer, int32_t *index) {int16_t res = ((uint16_t) buffer[*index]) << 8 |((uint16_t) buffer[*index + 1]);*index += 2;return res;}uint16_t buffer_get_uint16(const uint8_t *buffer, int32_t *index) {uint16_t res = ((uint16_t) buffer[*index]) << 8 |((uint16_t) buffer[*index + 1]);*index += 2;return res;}int32_t buffer_get_int32(const uint8_t *buffer, int32_t *index) {int32_t res = ((uint32_t) buffer[*index]) << 24 |((uint32_t) buffer[*index + 1]) << 16 |((uint32_t) buffer[*index + 2]) << 8 |((uint32_t) buffer[*index + 3]);*index += 4;return res;}uint32_t buffer_get_uint32(const uint8_t *buffer, int32_t *index) {uint32_t res = ((uint32_t) buffer[*index]) << 24 |((uint32_t) buffer[*index + 1]) << 16 |((uint32_t) buffer[*index + 2]) << 8 |((uint32_t) buffer[*index + 3]);*index += 4;return res;}float buffer_get_float16(const uint8_t *buffer, float scale, int32_t *index) {return (float)buffer_get_int16(buffer, index) / scale;}float buffer_get_float32(const uint8_t *buffer, float scale, int32_t *index) {return (float)buffer_get_int32(buffer, index) / scale;}float buffer_get_float32_auto(const uint8_t *buffer, int32_t *index) {uint32_t res = buffer_get_uint32(buffer, index);int e = (res >> 23) & 0xFF;uint32_t sig_i = res & 0x7FFFFF;bool neg = res & (1U << 31);float sig = 0.0;if (e != 0 || sig_i != 0) {sig = (float)sig_i / (8388608.0 * 2.0) + 0.5;e -= 126;}if (neg) {sig = -sig;}return ldexpf(sig, e);}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。