/** * @brief Collision handler for 'search ROM' procedure. * @details You can find algorithm details in APPNOTE 187 * "1-Wire Search Algorithm" from Maxim * * @param[in,out] sr pointer to the @p onewire_search_rom_t helper structure */ static uint8_t collision_handler(onewire_search_rom_t *sr) { uint8_t bit; switch(sr->reg.search_iter) { case ONEWIRE_SEARCH_ROM_NEXT: if ((int)sr->reg.rombit < sr->last_zero_branch) { bit = extract_path_bit(sr->prev_path, sr->reg.rombit); if (0 == bit) { sr->prev_zero_branch = sr->reg.rombit; sr->reg.result = ONEWIRE_SEARCH_ROM_SUCCESS; } store_bit(sr, bit); return bit; } else if ((int)sr->reg.rombit == sr->last_zero_branch) { sr->last_zero_branch = sr->prev_zero_branch; store_bit(sr, 1); return 1; } else { /* found next branch some levels deeper */ sr->prev_zero_branch = sr->last_zero_branch; sr->last_zero_branch = sr->reg.rombit; store_bit(sr, 0); sr->reg.result = ONEWIRE_SEARCH_ROM_SUCCESS; return 0; } break; case ONEWIRE_SEARCH_ROM_FIRST: /* always take 0-branch */ sr->prev_zero_branch = sr->last_zero_branch; sr->last_zero_branch = sr->reg.rombit; store_bit(sr, 0); sr->reg.result = ONEWIRE_SEARCH_ROM_SUCCESS; return 0; break; default: osalSysHalt("Unhandled case"); return 0; /* warning supressor */ break; } }
int main(void) { // Allocate a bit vector no larger than MAX_BITS in size. const size_t bit_vector_size = MAX_BITS / CHAR_BIT * sizeof(unsigned char); unsigned char* bits = malloc(bit_vector_size); if (!bits) { fprintf(stderr, "unable to allocate %lu bytes: %s\n", bit_vector_size, strerror(errno)); exit(EXIT_FAILURE); } for (int pass = 0; pass < 2; pass++) { memset(bits, 0, MAX_BITS / CHAR_BIT); int offset = (pass == 0) ? 0 : -(MAX_BITS / CHAR_BIT); char buffer[BUFSIZ]; while (fgets(buffer, sizeof(buffer), stdin) != NULL) { int n = atoi(buffer); if (pass == 0 && n < MAX_BITS) store_bit(n, bits, offset); else if (pass == 1 && n >= MAX_BITS) store_bit(n, bits, offset); } for (int i = (pass == 0) ? 0 : MAX_BITS, j = (pass == 0) ? MAX_BITS : MAX_VALUE; i < j; i++) { int byte = (i / CHAR_BIT) + offset; int bit = i % CHAR_BIT; if (bits[byte] & 1 << bit) { fprintf(stdout, "%07d\n", i); } } } free(bits); return 0; }
/** * @brief 1-wire search ROM callback. * @note Must be called from PWM's ISR. * * @param[in] pwmp pointer to the @p PWMDriver object * @param[in] owp pointer to the @p onewireDriver object * * @notapi */ static void ow_search_rom_cb(PWMDriver *pwmp, onewireDriver *owp) { onewire_search_rom_t *sr = &owp->search_rom; if (0 == sr->reg.bit_step) { /* read direct bit */ sr->reg.bit_buf |= ow_read_bit(owp); sr->reg.bit_step++; } else if (1 == sr->reg.bit_step) { /* read complement bit */ sr->reg.bit_buf |= ow_read_bit(owp) << 1; sr->reg.bit_step++; switch(sr->reg.bit_buf){ case 0b11: /* no one device on bus or any other fail happened */ sr->reg.result = ONEWIRE_SEARCH_ROM_ERROR; goto THE_END; break; case 0b01: /* all slaves have 1 in this position */ store_bit(sr, 1); ow_write_bit_I(owp, 1); break; case 0b10: /* all slaves have 0 in this position */ store_bit(sr, 0); ow_write_bit_I(owp, 0); break; case 0b00: /* collision */ sr->reg.single_device = false; ow_write_bit_I(owp, collision_handler(sr)); break; } } else { /* start next step */ #if !ONEWIRE_SYNTH_SEARCH_TEST ow_write_bit_I(owp, 1); #endif sr->reg.bit_step = 0; sr->reg.bit_buf = 0; } /* one ROM successfully discovered */ if (64 == sr->reg.rombit) { sr->reg.devices_found++; sr->reg.search_iter = ONEWIRE_SEARCH_ROM_NEXT; if (true == sr->reg.single_device) sr->reg.result = ONEWIRE_SEARCH_ROM_LAST; goto THE_END; } return; /* next search bit iteration */ THE_END: #if ONEWIRE_SYNTH_SEARCH_TEST (void)pwmp; return; #else osalSysLockFromISR(); pwmDisableChannelI(pwmp, owp->config->master_channel); pwmDisableChannelI(pwmp, owp->config->sample_channel); osalThreadResumeI(&(owp)->thread, MSG_OK); osalSysUnlockFromISR(); #endif }