diff options
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | src/bitfield/bitfield.h | 8 | ||||
-rw-r--r-- | src/canutil/read.h | 16 | ||||
-rw-r--r-- | src/canutil/write.c | 12 | ||||
-rw-r--r-- | src/canutil/write.h | 16 | ||||
-rw-r--r-- | tests/read_tests.c | 36 | ||||
-rwxr-xr-x | tests/tests.bin | bin | 24728 -> 0 bytes | |||
-rw-r--r-- | tests/write_tests.c | 40 |
9 files changed, 125 insertions, 12 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b4225c09 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +.DS_Store +*~ +*.bin @@ -19,15 +19,16 @@ SRC = $(wildcard src/**/*.c) OBJS = $(SRC:.c=.o) TEST_SRC = $(wildcard $(TEST_DIR)/*.c) TEST_OBJS = $(TEST_SRC:.c=.o) +TESTS=$(patsubst %.c,%.bin,$(TEST_SRC)) all: $(OBJS) -test: $(TEST_DIR)/tests.bin +test: $(TESTS) @set -o $(TEST_SET_OPTS) >/dev/null 2>&1 @export SHELLOPTS @sh runtests.sh $(TEST_DIR) -$(TEST_DIR)/tests.bin: $(TEST_OBJS) $(OBJS) +$(TEST_DIR)/%.bin: $(TEST_DIR)/%.o $(OBJS) @mkdir -p $(dir $@) $(CC) $(LDFLAGS) $(CC_SYMBOLS) $(INCLUDES) -o $@ $^ $(LDLIBS) diff --git a/src/bitfield/bitfield.h b/src/bitfield/bitfield.h index 27766733..7d9f3995 100644 --- a/src/bitfield/bitfield.h +++ b/src/bitfield/bitfield.h @@ -4,6 +4,10 @@ #include <stdint.h> #include <stdbool.h> +#ifdef __cplusplus +extern "C" { +#endif + /* Public: Reads a subset of bits from a byte array. * * data - the bytes in question. @@ -55,4 +59,8 @@ void setBitField(uint64_t* data, uint64_t value, int startPos, int numBits); */ uint8_t nthByte(uint64_t source, int byteNum); +#ifdef __cplusplus +} +#endif + #endif // __BITFIELD_H__ diff --git a/src/canutil/read.h b/src/canutil/read.h index 815f26b0..6ac4eebe 100644 --- a/src/canutil/read.h +++ b/src/canutil/read.h @@ -4,10 +4,26 @@ #include <stdint.h> #include <stdbool.h> +#ifdef __cplusplus +extern "C" { +#endif + +/* 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. + * + * Returns the final, transformed value of the signal. + */ float parseFloat(uint64_t data, uint8_t bitPosition, uint8_t bitSize, float factor, float offset); bool parseBoolean(uint64_t data, uint8_t bitPosition, uint8_t bitSize, float factor, float offset); +#ifdef __cplusplus +} +#endif + #endif // __READ_H__ diff --git a/src/canutil/write.c b/src/canutil/write.c index fdcba1f5..741778c7 100644 --- a/src/canutil/write.c +++ b/src/canutil/write.c @@ -1,18 +1,18 @@ #include "write.h" -uint64_t encodeFloat(float value, float offset, float factor, uint8_t bitPosition, - uint8_t bitSize) { +uint64_t encodeFloat(float value, uint8_t bitPosition, uint8_t bitSize, + float factor, float offset) { float rawValue = (value - offset) / factor; if(rawValue > 0) { // round up to avoid losing precision when we cast to an int rawValue += 0.5; } uint64_t result = 0; - setBitField(&result, rawValue, bitPosition, bitSize); + setBitField(&result, (uint64_t)rawValue, bitPosition, bitSize); return result; } -uint64_t encodeBoolean(bool value, float offset, float factor, - uint8_t bitPosition, uint8_t bitSize) { - return encodeFloat(value, offset, factor, bitPosition, bitSize); +uint64_t encodeBoolean(bool value, uint8_t bitPosition, uint8_t bitSize, + float factor, float offset) { + return encodeFloat(value, offset, factor, bitPosition, bitSize); } diff --git a/src/canutil/write.h b/src/canutil/write.h index 85a5c1a0..1b086dbe 100644 --- a/src/canutil/write.h +++ b/src/canutil/write.h @@ -4,10 +4,18 @@ #include <stdint.h> #include <stdbool.h> -uint64_t encodeFloat(float value, float offset, float factor, uint8_t bitPosition, - uint8_t bitSize); +#ifdef __cplusplus +extern "C" { +#endif -uint64_t encodeBoolean(bool value, float offset, float factor, - uint8_t bitPosition, uint8_t bitSize); +uint64_t encodeFloat(float value, uint8_t bitPosition, uint8_t bitSize, + float factor, float offset); + +uint64_t encodeBoolean(bool value, uint8_t bitPosition, uint8_t bitSize, + float factor, float offset); + +#ifdef __cplusplus +} +#endif #endif // __WRITE_H__ diff --git a/tests/read_tests.c b/tests/read_tests.c new file mode 100644 index 00000000..f5f0f0c3 --- /dev/null +++ b/tests/read_tests.c @@ -0,0 +1,36 @@ +#include <check.h> +#include <stdint.h> +#include <canutil/read.h> + +const uint64_t BIG_ENDIAN_TEST_DATA = __builtin_bswap64(0xEB00000000000000); + +START_TEST (test_parse_float) +{ + float result = parseFloat(BIG_ENDIAN_TEST_DATA, 2, 4, 1001.0, -30000.0); + float correctResult = 0xA * 1001.0 - 30000.0; + fail_unless(result == correctResult, + "parse is incorrect: %f but should be %f", result, correctResult); +} +END_TEST + +Suite* canreadSuite(void) { + Suite* s = suite_create("read"); + TCase *tc_core = tcase_create("core"); + tcase_add_checked_fixture(tc_core, NULL, NULL); + tcase_add_test(tc_core, test_parse_float); + suite_add_tcase(s, tc_core); + + return s; +} + +int main(void) { + int numberFailed; + Suite* s = canreadSuite(); + SRunner *sr = srunner_create(s); + // Don't fork so we can actually use gdb + srunner_set_fork_status(sr, CK_NOFORK); + srunner_run_all(sr, CK_NORMAL); + numberFailed = srunner_ntests_failed(sr); + srunner_free(sr); + return (numberFailed == 0) ? 0 : 1; +} diff --git a/tests/tests.bin b/tests/tests.bin Binary files differdeleted file mode 100755 index 5fd0916e..00000000 --- a/tests/tests.bin +++ /dev/null diff --git a/tests/write_tests.c b/tests/write_tests.c new file mode 100644 index 00000000..da5ee89c --- /dev/null +++ b/tests/write_tests.c @@ -0,0 +1,40 @@ +#include <canutil/write.h> +#include <check.h> +#include <stdint.h> + +START_TEST (test_encode_can_signal) +{ + uint64_t value = encodeFloat(0, 1, 3, 1, 0); + ck_assert_int_eq(value, 0); +} +END_TEST + +START_TEST (test_encode_can_signal_rounding_precision) +{ + uint64_t value = encodeFloat(50, 2, 19, 0.001, 0); + ck_assert_int_eq(value, 0x061a800000000000LLU); +} +END_TEST + +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_can_signal_rounding_precision); + suite_add_tcase(s, tc_core); + + return s; +} + +int main(void) { + int numberFailed; + Suite* s = canwriteSuite(); + SRunner *sr = srunner_create(s); + // Don't fork so we can actually use gdb + srunner_set_fork_status(sr, CK_NOFORK); + srunner_run_all(sr, CK_NORMAL); + numberFailed = srunner_ntests_failed(sr); + srunner_free(sr); + return (numberFailed == 0) ? 0 : 1; +} |