summaryrefslogtreecommitdiffstats
path: root/libs/bitfield-c/src/canutil
diff options
context:
space:
mode:
Diffstat (limited to 'libs/bitfield-c/src/canutil')
-rw-r--r--libs/bitfield-c/src/canutil/read.c34
-rw-r--r--libs/bitfield-c/src/canutil/read.h81
-rw-r--r--libs/bitfield-c/src/canutil/write.c48
-rw-r--r--libs/bitfield-c/src/canutil/write.h57
4 files changed, 220 insertions, 0 deletions
diff --git a/libs/bitfield-c/src/canutil/read.c b/libs/bitfield-c/src/canutil/read.c
new file mode 100644
index 00000000..d0cbb71a
--- /dev/null
+++ b/libs/bitfield-c/src/canutil/read.c
@@ -0,0 +1,34 @@
+#include <canutil/read.h>
+#include <bitfield/bitfield.h>
+#include <bitfield/8byte.h>
+
+static float decode_float(uint64_t raw, float factor, float offset) {
+ return raw * factor + offset;
+}
+
+float eightbyte_parse_float(uint64_t data, uint8_t bit_offset, uint8_t bit_size,
+ float factor, float offset) {
+ return decode_float(eightbyte_get_bitfield(data, bit_offset, bit_size,
+ true), factor, offset);
+}
+
+bool eightbyte_parse_bool(uint64_t data, uint8_t bit_offset, uint8_t bit_size,
+ float factor, float offset) {
+ float value = eightbyte_parse_float(data, bit_offset, bit_size, factor, offset);
+ return value == 0.0 ? false : true;
+}
+
+float bitfield_parse_float(const uint8_t source[], const uint16_t source_length,
+ const uint8_t bit_offset, const uint8_t bit_size, const float factor,
+ const float offset) {
+ return decode_float(get_bitfield(source, source_length, bit_offset, bit_size),
+ factor, offset);
+}
+
+bool bitfield_parse_bool(const uint8_t source[], const uint16_t source_length,
+ const uint8_t bit_offset, const uint8_t bit_size, const float factor,
+ const float offset) {
+ float value = bitfield_parse_float(source, source_length, bit_offset,
+ bit_size, factor, offset);
+ return value == 0.0 ? false : true;
+}
diff --git a/libs/bitfield-c/src/canutil/read.h b/libs/bitfield-c/src/canutil/read.h
new file mode 100644
index 00000000..86fea785
--- /dev/null
+++ b/libs/bitfield-c/src/canutil/read.h
@@ -0,0 +1,81 @@
+#ifndef __READ_H__
+#define __READ_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Public: Parse a CAN signal from a message and apply required transformation.
+ *
+ * source - the payload containing the signal.
+ * bit_offset - the starting bit for the signal.
+ * bit_size - the width of the signal.
+ * factor - the transformation factor for the signal value, applied after
+ * pulling out the bit field. Use 1.0 for no factor.
+ * offset - the transformation offset for the signal value, applied after
+ * pulling out the bit field. Use 0 for no offset.
+ *
+ * Returns the decoded and transformed value of the signal.
+ */
+float eightbyte_parse_float(const uint64_t source, const uint8_t bit_offset,
+ const uint8_t bit_size, const float factor, const float offset);
+
+/* Public: Parse a CAN signal from a message storage as a byte array and apply
+ * required transformation.
+ *
+ * source - the payload containing the signal.
+ * source_size - the size of the payload in bytes.
+ * bit_offset - the starting bit for the signal.
+ * bit_size - the width of the signal.
+ * factor - the transformation factor for the signal value, applied after
+ * pulling out the bit field. Use 1.0 for no factor.
+ * offset - the transformation offset for the signal value, applied after
+ * pulling out the bit field. Use 0 for no offset.
+ *
+ * Returns the decoded and transformed value of the signal.
+ */
+float bitfield_parse_float(const uint8_t source[], const uint16_t source_size,
+ const uint8_t bit_offset, const uint8_t bit_size, const float factor,
+ const float offset);
+
+/* Public: Parse a CAN signal from a message and interpret it as a boolean.
+ *
+ * source - the payload containing the signal.
+ * bit_offset - the starting bit for the signal.
+ * bit_size - the width of the signal.
+ * factor - the transformation factor for the signal value, applied after
+ * pulling out the bit field. Use 1.0 for no factor.
+ * offset - the transformation offset for the signal value, applied after
+ * pulling out the bit field. Use 0 for no offset.
+ *
+ * Returns false if the value was 0, otherwise true.
+ */
+bool eightbyte_parse_bool(uint64_t source, uint8_t bit_offset, uint8_t bit_size,
+ float factor, float offset);
+
+/* Public: Parse a CAN signal from a message storage as a byte array and
+ * interpret it as a boolean.
+ *
+ * source - the payload containing the signal.
+ * source_size - the size of the payload in bytes.
+ * bit_offset - the starting bit for the signal.
+ * bit_size - the width of the signal.
+ * factor - the transformation factor for the signal value, applied after
+ * pulling out the bit field. Use 1.0 for no factor.
+ * offset - the transformation offset for the signal value, applied after
+ * pulling out the bit field. Use 0 for no offset.
+ *
+ * Returns false if the value was 0, otherwise true.
+ */
+bool bitfield_parse_bool(const uint8_t source[], const uint16_t source_size,
+ const uint8_t bit_offset, const uint8_t bit_size, const float factor,
+ const float offset);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __READ_H__
diff --git a/libs/bitfield-c/src/canutil/write.c b/libs/bitfield-c/src/canutil/write.c
new file mode 100644
index 00000000..7f3a3e04
--- /dev/null
+++ b/libs/bitfield-c/src/canutil/write.c
@@ -0,0 +1,48 @@
+#include <canutil/write.h>
+#include <bitfield/bitfield.h>
+#include <bitfield/8byte.h>
+
+uint64_t float_to_fixed_point(const float value, const float factor,
+ const float offset) {
+ float raw = (value - offset) / factor;
+ if(raw > 0) {
+ // round up to avoid losing precision when we cast to an int
+ // TODO do we need a way to encode an int back to a signal without any
+ // rounding?
+ raw += 0.5;
+ }
+ return (uint64_t)raw;
+}
+
+uint64_t eightbyte_encode_float(float value, uint8_t bit_offset, uint8_t bit_size,
+ float factor, float offset) {
+ uint64_t result = 0;
+ if(!eightbyte_set_bitfield(float_to_fixed_point(value, factor, offset),
+ bit_offset, bit_size, &result)) {
+ // debug("%f will not fit in a %d bit field", value, bit_size);
+ }
+ return result;
+}
+
+uint64_t eightbyte_encode_bool(const bool value, const uint8_t bit_offset,
+ const uint8_t bit_size) {
+ return eightbyte_encode_float(value, bit_offset, bit_size, 1.0, 0);
+}
+
+bool bitfield_encode_float(const float value, const uint8_t bit_offset,
+ const uint8_t bit_size, const float factor, const float offset,
+ uint8_t destination[], const uint8_t destination_length) {
+ if(!set_bitfield(float_to_fixed_point(value, factor, offset), bit_offset,
+ bit_size, destination, destination_length)) {
+ // debug("%f will not fit in a %d bit field", value, bit_size);
+ return false;
+ }
+ return true;
+}
+
+bool bitfield_encode_bool(const bool value, const uint8_t bit_offset,
+ const uint8_t bit_size, uint8_t destination[],
+ const uint16_t destination_length) {
+ return bitfield_encode_float(value, bit_offset, bit_size, 1.0, 0,
+ destination, destination_length);
+}
diff --git a/libs/bitfield-c/src/canutil/write.h b/libs/bitfield-c/src/canutil/write.h
new file mode 100644
index 00000000..c2bef20e
--- /dev/null
+++ b/libs/bitfield-c/src/canutil/write.h
@@ -0,0 +1,57 @@
+#ifndef __WRITE_H__
+#define __WRITE_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Public: Encode a floating point number into a fixed point, fixed bit width
+ * field in a bit array.
+ *
+ * value - the floating point value to encode.
+ * bit_offset - the starting point for the encoded bits in the returned value.
+ * bit_size - The max width of the field in the resulting bit array. If bit_size
+ * isn't big enough to store the fixed point version of the value, the
+ * bitfeld will *not* be set. TODO some error reporting would be nice.
+ * factor - a factor used to transform from floating to fixed point before
+ * encoding. Use 1.0 for no factor.
+ * offset - an offset used to transform from floating to fixed point before
+ * encoding. Use 0 for no offset.
+ *
+ * Returns a big-endian uint64_t with the value encoded as a bitfield.
+ */
+uint64_t eightbyte_encode_float(float value, uint8_t bit_offset,
+ uint8_t bit_size, float factor, float offset);
+
+uint64_t float_to_fixed_point(const float value, const float factor,
+ const float offset);
+
+bool bitfield_encode_float(const float value, const uint8_t bit_offset,
+ const uint8_t bit_size, const float factor, const float offset,
+ uint8_t destination[], const uint8_t destination_length);
+
+/* Public: Encode a boolean into fixed bit width field in a bit array.
+ *
+ * value - the boolean value to encode - true will be 1, false will be 0.
+ * bit_offset - the starting point for the encoded bits in the returned value.
+ * bit_size - The max width of the field in the resulting bit array. If bit_size
+ * isn't big enough to store the fixed point version of the value, the
+ * bitfeld will *not* be set. TODO some error reporting would be nice.
+ *
+ * Returns a big-endian uint64_t with the value encoded as a bitfield.
+ */
+uint64_t eightbyte_encode_bool(const bool value, const uint8_t bit_offset,
+ const uint8_t bit_size);
+
+bool bitfield_encode_bool(const bool value, const uint8_t bit_offset, const
+ uint8_t bit_size, uint8_t destination[],
+ const uint16_t destination_length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __WRITE_H__