From bb00e90e2499cd44d65fe581c8d806ffe3227189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Thu, 1 Feb 2018 11:38:41 +0100 Subject: [PATCH] added checksum support --- main.c | 5 +++-- ow_search.c | 45 +++++++++++++++++++++++++++++++++++++++++---- ow_search.h | 17 ++++++++++++++++- 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/main.c b/main.c index b08d029..a52cd37 100644 --- a/main.c +++ b/main.c @@ -16,7 +16,7 @@ int main(void) // than could fit in the address buffer. struct ow_search_state search_state; - ow_search_init(&search_state, 0xF0); // SEARCH_ROM + ow_search_init(&search_state, 0xF0 /* SEARCH_ROM */, false /* checksums */); // Buffer for the found addresses - can have up to 65536 rows // Keep in mind that each address uses 8 bytes @@ -57,7 +57,7 @@ struct owunit { int state; }; -#define UNITS_COUNT 12 +#define UNITS_COUNT 13 struct owunit units[UNITS_COUNT] = { {.romcode = {0b00000000}},//00 {.romcode = {0b00000001}},//01 @@ -71,6 +71,7 @@ struct owunit units[UNITS_COUNT] = { {.romcode = {0b11110111}},//f7 {.romcode = {0xFF,0x00,0xFF,0x00,0x55,0x00,0xAA,0x00}}, {.romcode = {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0}}, + {.romcode = {0x10,0x76,0xc7,0x04,0x01,0x08,0x00,0x71}}, // this is from a real 1-wire thermometer - checksum should be OK }; void rom_device_reset(struct owunit *device) diff --git a/ow_search.c b/ow_search.c index aca62be..b2d606a 100644 --- a/ow_search.c +++ b/ow_search.c @@ -10,13 +10,47 @@ #include "ow_search.h" -void ow_search_init(struct ow_search_state *state, uint8_t command) +// -------- CHECKSUM -------- + +static inline uint8_t crc8_bits(uint8_t data) +{ + uint8_t crc = 0; + if(data & 1) crc ^= 0x5e; + if(data & 2) crc ^= 0xbc; + if(data & 4) crc ^= 0x61; + if(data & 8) crc ^= 0xc2; + if(data & 0x10) crc ^= 0x9d; + if(data & 0x20) crc ^= 0x23; + if(data & 0x40) crc ^= 0x46; + if(data & 0x80) crc ^= 0x8c; + return crc; +} + +static uint8_t crc8_add(uint8_t cksum, uint8_t byte) +{ + return crc8_bits(byte ^ cksum); +} + +uint8_t ow_checksum(const uint8_t *buff, uint16_t len) +{ + uint8_t cksum = 0; + for(uint16_t i = 0; i < len; i++) { + cksum = crc8_add(cksum, buff[i]); + } + return cksum; +} + +// ----------------------------- + + +void ow_search_init(struct ow_search_state *state, uint8_t command, bool test_checksums) { state->prev_last_fork = 64; memset(state->prev_code, 0, 8); state->status = OW_SEARCH_MORE; state->command = command; state->first = true; + state->test_checksums = test_checksums; } uint16_t ow_search_run(struct ow_search_state *state, ow_romcode_t *codes, uint16_t capacity) @@ -77,10 +111,13 @@ uint16_t ow_search_run(struct ow_search_state *state, ow_romcode_t *codes, uint1 } } - // Record a found address memcpy(state->prev_code, code, 8); - memcpy(codes[found_devices], code, 8); - found_devices++; + + if (!state->test_checksums || 0 == ow_checksum(code, 8)) { + // Record a found address + memcpy(codes[found_devices], code, 8); + found_devices++; + } // Stop condition if (last_fork == -1) { diff --git a/ow_search.h b/ow_search.h index a706428..efdbfb6 100644 --- a/ow_search.h +++ b/ow_search.h @@ -75,6 +75,7 @@ struct ow_search_state { uint8_t command; enum ow_search_result status; bool first; + bool test_checksums; }; /** @@ -82,8 +83,9 @@ struct ow_search_state { * * @param[out] state - inited struct * @param[in] command - command to send for requesting the search (e.g. SEARCH_ROM) + * @param[in] test_checksums - verify checksums of all read romcodes */ -void ow_search_init(struct ow_search_state *state, uint8_t command); +void ow_search_init(struct ow_search_state *state, uint8_t command, bool test_checksums); /** * Perform a search of the 1-wire bus, with a state struct pre-inited @@ -101,4 +103,17 @@ void ow_search_init(struct ow_search_state *state, uint8_t command); */ uint16_t ow_search_run(struct ow_search_state *state, ow_romcode_t *codes, uint16_t capacity); +/** + * Compute a 1-wire type checksum. + * If the buffer includes the checksum, the result should be 0. + * + * (this function may be used externally, or you can delete the implementation + * from the c file if another implementation is already available) + * + * @param[in] buf - buffer of bytes to verify + * @param[in] len - buffer length + * @return checksum + */ +uint8_t ow_checksum(const uint8_t *buf, uint16_t len); + #endif //OW_SEARCH_H