summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--Makefile5
-rw-r--r--src/bitfield/bitfield.h8
-rw-r--r--src/canutil/read.h16
-rw-r--r--src/canutil/write.c12
-rw-r--r--src/canutil/write.h16
-rw-r--r--tests/read_tests.c36
-rwxr-xr-xtests/tests.binbin24728 -> 0 bytes
-rw-r--r--tests/write_tests.c40
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
diff --git a/Makefile b/Makefile
index 8385c3ac..49e22f2c 100644
--- a/Makefile
+++ b/Makefile
@@ -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
deleted file mode 100755
index 5fd0916e..00000000
--- a/tests/tests.bin
+++ /dev/null
Binary files differ
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;
+}