// // Created by MightyPork on 2018/02/01. // MIT license // #include #include #include #include #include "ow_search.h" // -------- 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) { if (state->status != OW_SEARCH_MORE) return 0; uint16_t found_devices = 0; while (found_devices < capacity) { uint8_t index = 0; ow_romcode_t code = {}; int8_t last_fork = -1; // Start a new transaction. Devices respond to reset if (!ow_reset()) { state->status = OW_SEARCH_FAILED; goto done; } // Send the search command (SEARCH_ROM, SEARCH_ALARM) ow_write_u8(state->command); uint8_t *code_byte = &code[0]; bool p, n; while (index != 64) { // Read a bit and its complement p = ow_read_bit(); n = ow_read_bit(); if (!p && !n) { // A fork: there are devices on the bus with different bit value // (the bus is open-drain, in both cases one device pulls it low) if ((found_devices > 0 || !state->first) && index < state->prev_last_fork) { // earlier than the last fork, take the same turn as before p = ow_code_getbit(state->prev_code, index); if (!p) last_fork = index; // remember for future runs, 1 not explored yet } else if (index == state->prev_last_fork) { p = 1; // both forks are now exhausted } else { // a new fork last_fork = index; } } else if (p && n) { // No devices left connected - this doesn't normally happen state->status = OW_SEARCH_FAILED; goto done; } // All devices have a matching bit here, or it was resolved in a fork if (p) *code_byte |= (1 << (index & 7)); ow_write_bit(p); index++; if((index & 7) == 0) { code_byte++; } } memcpy(state->prev_code, code, 8); 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) { state->status = OW_SEARCH_DONE; goto done; } state->prev_last_fork = last_fork; } done: state->first = false; return found_devices; }