+struct ds_sensor ds_sensors[DS_NUM_SENSORS];
+
+#if DS_NUM_SENSORS == 1
+
+static void ds_enumerate(void)
+{
+ if (!ds_reset())
+ return;
+
+ ds_send_byte(0x33); // READ_ROM
+ if (!ds_recv_block(8))
+ return;
+
+ DEBUG("DS18B20: Found sensor ");
+ for (uint i = 0; i < 8; i++) {
+ DEBUG("%02x", ds_buf[i]);
+ ds_sensors[0].address[i] = ds_buf[i];
+ }
+ DEBUG("\n");
+}
+
+#else
+
+static void ds_enumerate(void)
+{
+ /*
+ * The enumeration algorithm roughly follows the one described in the
+ * Book of iButton Standards (Maxim Integrated Application Note 937).
+ *
+ * It simulates depth-first search on the trie of all device IDs.
+ * In each pass, it walks the trie from the root and recognizes branching nodes.
+ *
+ * The old_choice variable remembers the deepest left branch taken in the
+ * previous pass, new_choice is the same for the current pass.
+ */
+
+ DEBUG("DS18B20: Enumerate\n");
+
+ uint num_sensors = 0;
+ byte *addr = ds_buf;
+ byte old_choice = 0;
+
+ for (;;) {
+ if (!ds_reset()) {
+ DEBUG("DS18B20: Enumeration found no sensor\n");
+ return;
+ }
+
+ ds_send_byte(0xf0); // SEARCH_ROM
+ byte new_choice = 0;
+ for (byte i=0; i<64; i++) {
+ bool have_one = ds_recv_bit();
+ bool have_zero = ds_recv_bit();
+ bool old_bit = addr[i/8] & (1U << (i%8));
+ bool new_bit;
+ switch (2*have_one + have_zero) {
+ case 3:
+ // This should not happen
+ DEBUG("DS18B20: Enumeration failed\n");
+ return;
+ case 1:
+ // Only 0
+ new_bit = 0;
+ break;
+ case 2:
+ // Only 1
+ new_bit = 1;
+ break;
+ default:
+ // Both
+ if (i == old_choice)
+ new_bit = 1;
+ else if (i > old_choice) {
+ new_bit = 0;
+ new_choice = i;
+ } else {
+ new_bit = old_bit;
+ if (!new_bit)
+ new_choice = i;
+ }
+ }
+ if (new_bit)
+ addr[i/8] |= 1U << (i%8);
+ else
+ addr[i/8] &= ~(1U << (i%8));
+ ds_send_bit(new_bit);
+ }
+
+ if (num_sensors >= DS_NUM_SENSORS) {
+ DEBUG("DS18B20: Too many sensors\n");
+ return;
+ }
+
+ DEBUG("DS18B20: Found sensor #%u: ", num_sensors);
+ for (byte i=0; i<8; i++)
+ DEBUG("%02x", addr[i]);
+ if (ds_crc_block(8)) {
+ DEBUG(" - invalid CRC!\n");
+ } else if (ds_buf[0] == 0x28) {
+ DEBUG("\n");
+ memcpy(ds_sensors[num_sensors].address, ds_buf, 8);
+ num_sensors++;
+ } else {
+ DEBUG(" - wrong type\n");
+ }
+
+ old_choice = new_choice;
+ if (!old_choice)
+ break;
+ }
+}
+
+#endif
+