From e3bb578a0b11a25b0ae4c805fb7b98b724103b6f Mon Sep 17 00:00:00 2001 From: Christopher Peplin Date: Sun, 29 Dec 2013 13:57:37 -0500 Subject: Test all canutil functions and document in README. --- README.mkd | 28 ++++++++++++++++++++++++---- src/canutil/read.h | 22 +++++++++++++++------- src/canutil/write.c | 10 ++++++---- src/canutil/write.h | 28 ++++++++++++++++++++++++++-- tests/write_tests.c | 14 ++++++++++++++ 5 files changed, 85 insertions(+), 17 deletions(-) diff --git a/README.mkd b/README.mkd index 8f6ac5f..b96d587 100644 --- a/README.mkd +++ b/README.mkd @@ -3,26 +3,46 @@ CAN Message Utilities for C ## Bitfield Manipulation + uint8_t data[4] = {0x12, 0x34, 0x56, 0x78}; + uint8_t result = getByte(data, sizeof(data), 0); + uint8_t result = getNibble(data, sizeof(data), 0); + fail_unless(copyBitsRightAligned(data, 4, 4, 12, result, 4)); + +## 8 Byte Bitfield Manipulation + +TODO setting bit fields is just copying +TODO bring back old uint64_t implementation of getBitField if it's faster / + simpler + ## CAN Signal Encoding +The library supports encoding floating point CAN signals as well as booleans +into a uint64_t payload. + + uint64_t payload = bitfield_encode_float(1, 1, 3, 1, 0) + // payload == 0x1000000000000000 + + payload = bitfield_encode_bool(true, 1, 3); + // payload == 0x1000000000000000 + ## CAN Signal Decoding The library supports parsing floating point CAN signals as well as booleans. uint64_t payload = 0xeb00000000000000; - float result = bitfield_parse_float(payload, + float float_result = bitfield_parse_float(payload, 2, // starting bit 4, // width of the signal's field 1001.0, // transformation factor for the signal value -30000.0); // transformation offset for the signal value - // result == -19990.0 + // float_result == -19990.0 - bool result = bitfield_parse_bool(payload, + bool bool_result = bitfield_parse_bool(payload, 0, // starting bit 1, // width of the signal's field 1.0, // transformation factor for the signal value 0); // transformation offset for the signal value - // result == true + // bool_result == true ## Testing diff --git a/src/canutil/read.h b/src/canutil/read.h index 028b03a..865bb27 100644 --- a/src/canutil/read.h +++ b/src/canutil/read.h @@ -10,20 +10,28 @@ extern "C" { /* Public: Parse a CAN signal from a message and apply required transformation. * - * signal - The details of the signal to decode and forward. - * data - The raw bytes of the CAN message that contains the signal, assumed - * to be in big-endian byte order from CAN. + * data - 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 final, transformed value of the signal. + * Returns the decoded and transformed value of the signal. */ float bitfield_parse_float(uint64_t data, uint8_t bit_offset, uint8_t bit_size, float factor, float offset); /* Public: Parse a CAN signal from a message and interpret it as a boolean. * - * signal - The details of the signal to decode and forward. - * data - The raw bytes of the CAN message that contains the signal, assumed - * to be in big-endian byte order from CAN. + * data - 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. */ diff --git a/src/canutil/write.c b/src/canutil/write.c index 14d2a44..583c251 100644 --- a/src/canutil/write.c +++ b/src/canutil/write.c @@ -9,11 +9,13 @@ uint64_t bitfield_encode_float(float value, uint8_t bit_offset, uint8_t bit_size raw += 0.5; } uint64_t result = 0; - set_bit_field(&result, (uint64_t)raw, bit_offset, bit_size); + if(!set_bit_field(&result, (uint64_t)raw, bit_offset, bit_size)) { + // debug("%f will not fit in a %d bit field", value, bit_size); + } return result; } -uint64_t bitfield_encode_bool(bool value, uint8_t bit_offset, uint8_t bit_size, - float factor, float offset) { - return bitfield_encode_float(value, offset, factor, bit_offset, bit_size); +uint64_t bitfield_encode_bool(const bool value, const uint8_t bit_offset, + const uint8_t bit_size) { + return bitfield_encode_float(value, bit_offset, bit_size, 1.0, 0); } diff --git a/src/canutil/write.h b/src/canutil/write.h index 3d13b1d..f117a06 100644 --- a/src/canutil/write.h +++ b/src/canutil/write.h @@ -8,11 +8,35 @@ 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 bitfield_encode_float(float value, uint8_t bit_offset, uint8_t bit_size, float factor, float offset); -uint64_t bitfield_encode_bool(bool value, uint8_t bit_offset, uint8_t bit_size, - float factor, float offset); +/* 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 bitfield_encode_bool(const bool value, const uint8_t bit_offset, const uint8_t bit_size); #ifdef __cplusplus } diff --git a/tests/write_tests.c b/tests/write_tests.c index ed555f6..8cc35e2 100644 --- a/tests/write_tests.c +++ b/tests/write_tests.c @@ -6,6 +6,9 @@ START_TEST (test_encode_can_signal) { uint64_t value = bitfield_encode_float(0, 1, 3, 1, 0); ck_assert_int_eq(value, 0); + + value = bitfield_encode_float(1, 1, 3, 1, 0); + ck_assert_int_eq(value, 0x1000000000000000LLU); } END_TEST @@ -16,11 +19,22 @@ START_TEST (test_encode_can_signal_rounding_precision) } END_TEST +START_TEST (test_encode_bool) +{ + uint64_t value = bitfield_encode_bool(true, 1, 3); + ck_assert_int_eq(value, 0x1000000000000000LLU); + value = bitfield_encode_bool(false, 1, 3); + ck_assert_int_eq(value, 0x0000000000000000LLU); +} +END_TEST +// TODO test encode bool + Suite* canwriteSuite(void) { Suite* s = suite_create("write"); TCase *tc_core = tcase_create("core"); tcase_add_checked_fixture(tc_core, NULL, NULL); tcase_add_test(tc_core, test_encode_can_signal); + tcase_add_test(tc_core, test_encode_bool); tcase_add_test(tc_core, test_encode_can_signal_rounding_precision); suite_add_tcase(s, tc_core); -- cgit 1.2.3-korg