aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bitfield/8byte.c4
-rw-r--r--src/bitfield/8byte.h4
-rw-r--r--src/bitfield/bitfield.c24
-rw-r--r--src/bitfield/bitfield.h23
-rw-r--r--src/canutil/write.c32
-rw-r--r--src/canutil/write.h9
6 files changed, 79 insertions, 17 deletions
diff --git a/src/bitfield/8byte.c b/src/bitfield/8byte.c
index 72f7e32b..0ae6894b 100644
--- a/src/bitfield/8byte.c
+++ b/src/bitfield/8byte.c
@@ -47,8 +47,8 @@ uint64_t eightbyte_get_bitfield(uint64_t source, const uint16_t offset,
return ret & bitmask(bit_count);
}
-bool eightbyte_set_bitfield(uint64_t* destination, uint64_t value, const uint16_t offset,
- const uint16_t bit_count) {
+bool eightbyte_set_bitfield(uint64_t value, const uint16_t offset,
+ const uint16_t bit_count, uint64_t* destination) {
if(value > bitmask(bit_count)) {
return false;
}
diff --git a/src/bitfield/8byte.h b/src/bitfield/8byte.h
index 2916c218..04512690 100644
--- a/src/bitfield/8byte.h
+++ b/src/bitfield/8byte.h
@@ -74,8 +74,8 @@ uint8_t eightbyte_get_byte(const uint64_t source, const uint8_t byte_index,
* Returns true if the bit_count is enough to fully represent the value, and
* false if it will not fit.
*/
-bool eightbyte_set_bitfield(uint64_t* destination, uint64_t value,
- const uint16_t offset, const uint16_t bit_count);
+bool eightbyte_set_bitfield(uint64_t value,
+ const uint16_t offset, const uint16_t bit_count, uint64_t* destination);
/* Private: Determine the index of the last bit used.
*/
diff --git a/src/bitfield/bitfield.c b/src/bitfield/bitfield.c
index e40ab1ab..b244c9b1 100644
--- a/src/bitfield/bitfield.c
+++ b/src/bitfield/bitfield.c
@@ -34,10 +34,7 @@ uint64_t get_bitfield(const uint8_t source[], const uint8_t source_length,
return 0;
}
- union {
- uint64_t whole;
- uint8_t bytes[sizeof(uint64_t)];
- } combined;
+ ArrayOrBytes combined;
memset(combined.bytes, 0, sizeof(combined.bytes));
copy_bits_right_aligned(source, source_length, offset, bit_count,
combined.bytes, sizeof(combined.bytes));
@@ -53,3 +50,22 @@ bool set_nibble(const uint16_t nibble_index, const uint8_t value,
destination_length, nibble_index * NIBBLE_SIZE);
}
+bool set_bitfield(const uint64_t value, const uint16_t offset,
+ const uint16_t bit_count, uint8_t destination[],
+ uint16_t destination_length) {
+ if(value > bitmask(bit_count)) {
+ return false;
+ }
+
+ ArrayOrBytes combined = {
+ whole: value
+ };
+
+ if(BYTE_ORDER == LITTLE_ENDIAN) {
+ combined.whole = __builtin_bswap64(combined.whole);
+ }
+
+ return copy_bits(combined.bytes, sizeof(combined.bytes),
+ sizeof(combined.bytes) * CHAR_BIT - bit_count, bit_count,
+ destination, destination_length, offset);
+}
diff --git a/src/bitfield/bitfield.h b/src/bitfield/bitfield.h
index a080c866..b3c30f02 100644
--- a/src/bitfield/bitfield.h
+++ b/src/bitfield/bitfield.h
@@ -168,6 +168,22 @@ bool copy_bytes_right_aligned(const uint8_t source[], const uint16_t source_leng
bool set_nibble(const uint16_t nibble_index, const uint8_t value,
uint8_t* destination, const uint16_t destination_length);
+/* Public: Set the bit field in the given data array to the new value.
+ *
+ * value - the value to set in the bit field.
+ * offset - the starting index of the bit field (beginning from 0).
+ * bit_count - the number of bits to set in the data.
+ * destination - the destination array.
+ * destination_length - the total length of the destination array in bytes,
+ * for range checking.
+ *
+ * Returns true if the bit_count is enough to fully represent the value, and
+ * false if it will not fit.
+ */
+bool set_bitfield(const uint64_t value, const uint16_t offset,
+ const uint16_t bit_count, uint8_t destination[],
+ uint16_t destination_length);
+
/* Private:
*/
uint16_t bits_to_bytes(uint32_t bits);
@@ -178,6 +194,13 @@ uint16_t bits_to_bytes(uint32_t bits);
*/
uint64_t bitmask(const uint8_t bit_count);
+/* Private: A union to assist swapping between uint64_t and a uint8_t array.
+ */
+typedef union {
+ uint64_t whole;
+ uint8_t bytes[sizeof(uint64_t)];
+} ArrayOrBytes;
+
#ifdef __cplusplus
}
#endif
diff --git a/src/canutil/write.c b/src/canutil/write.c
index 5b91aaf9..3b3ae25d 100644
--- a/src/canutil/write.c
+++ b/src/canutil/write.c
@@ -2,8 +2,8 @@
#include <bitfield/bitfield.h>
#include <bitfield/8byte.h>
-uint64_t eightbyte_encode_float(float value, uint8_t bit_offset, uint8_t bit_size,
- float factor, float offset) {
+static 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
@@ -11,8 +11,14 @@ uint64_t eightbyte_encode_float(float value, uint8_t bit_offset, uint8_t bit_siz
// 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(&result, (uint64_t)raw, bit_offset, bit_size)) {
+ 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;
@@ -23,8 +29,20 @@ uint64_t eightbyte_encode_bool(const bool value, const uint8_t bit_offset,
return eightbyte_encode_float(value, bit_offset, bit_size, 1.0, 0);
}
-bool bitfield_encode_float(float value, uint8_t bit_offset,
- uint8_t bit_size, float factor, float offset, uint8_t destination[]) {
- // TODO
- return 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/src/canutil/write.h b/src/canutil/write.h
index 8fd18cdb..28b7e052 100644
--- a/src/canutil/write.h
+++ b/src/canutil/write.h
@@ -26,8 +26,9 @@ extern "C" {
uint64_t eightbyte_encode_float(float value, uint8_t bit_offset,
uint8_t bit_size, float factor, float offset);
-bool bitfield_encode_float(float value, uint8_t bit_offset,
- uint8_t bit_size, float factor, float offset, uint8_t destination[]);
+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.
*
@@ -42,6 +43,10 @@ bool bitfield_encode_float(float value, uint8_t bit_offset,
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