u8 ow_reset() { u8 flag; u8 result = 0; init_onewire(); ow_assert_low(); delay_us(480); flag = disable_interrupts(); ow_bus_float(); delay_us(66); if (ow_read()) { /* No presence pulse */ result = 1; } delay_us(414); if (result==0 && ow_read() == 0) { /* bus is shorted */ result = 2; } restore_flags(flag); return result; }
int8_t ow_temp_power(ow_rom_code_t *rom) { #if ONEWIRE_BUSCOUNT > 1 uint8_t busmask = 1 << (ONEWIRE_STARTPIN); // FIXME: currently only on 1st bus #else uint8_t busmask = ONEWIRE_BUSMASK; #endif int8_t ret; if (rom == NULL) ret = ow_skip_rom(); else { if (!ow_temp_sensor(rom)) return -2; ret = ow_match_rom(rom); } if (ret < 0) return ret; /* transmit command byte */ ow_write_byte(busmask, OW_FUNC_READ_POWER); return (int8_t)(ow_read(busmask)); }
u8 ow_bit_io(u8 b) { u8 flags; flags = disable_interrupts(); ow_assert_low(); delay_us(1); if (b) { ow_bus_float(); } delay_us(14); b = ow_read(); delay_us(45); ow_bus_float(); restore_flags(flags); return b; }
static int8_t ow_read_bit(uint8_t i) { uint8_t bit; /* >= 1usec recovery time. */ ow_release(); _delay_us(1); /* >= 1 usec pull low to start read slot. */ /* The read slot is time critical to a few usec, so disable interrupts. */ cli(); ow_low(); _delay_us(1); ow_release(); /* We must read the bus within at most 15 usec from pulling the bus low. The later we read, the more margin. But let's keep a couple usec to account for delays outside of _delay_us(). */ _delay_us(12); bit= ow_read(); sei(); if ((i % 8) == 0) ow_read_buf[i / 8] = 0; if (bit) ow_read_buf[i / 8] |= (1 << (i % 8)); /* Total read slot >= 60 usec. */ ow_delay_us(60-1-12); return 0; }
uint8_t noinline ow_read_byte(uint8_t busmask) { uint8_t data = 0; for (uint8_t i = 0; i < 8; i++) { data |= (uint8_t)(ow_read(busmask) << i); } return data; }
static int8_t ow_init(uint8_t i) { if (i == 0) { /* Reset pulse: low for >= 480 usec. */ ow_low(); ow_delay_us(480); } else if (i == 1) { /* Presence detect 60 usec <= T <= 240 usec. */ ow_release(); ow_delay_us(60); } else { /* Total presence pulse 480 usec. */ ow_presence= !ow_read(); ow_delay_us(480-60); } return 0; }
uint8_t ds18b20_ping(void) { uint8_t i; uint8_t n = 0; int16_t v; if (!ow_read()) return 0; for (i = 0; i < ow_n_addrs; i++) { if (ow_addr(i)[0] == DS18B20_FAMILY_CODE) { ow_reset(); ow_match_rom(i); ow_write_byte(DS18B20_CMD_READ_SCRATCHPAD); v = ow_read_byte(); v |= ow_read_byte() << 8; if (ds18b20_temps[n]) { ds18b20_temps[n] -= ds18b20_temps[n] >> 4; ds18b20_temps[n] += v; } else { ds18b20_temps[n] = v << 4; } }
int8_t ow_temp_start_convert(ow_rom_code_t *rom, uint8_t wait) { int8_t ret; if (rom == NULL) ret = ow_skip_rom(); else { /* check for known family code */ if (!ow_temp_sensor(rom)) return -2; ret = ow_match_rom(rom); } if (ret < 0) return ret; /* transmit command byte */ ow_write_byte(ONEWIRE_BUSMASK, OW_FUNC_CONVERT); OW_CONFIG_OUTPUT(ONEWIRE_BUSMASK); OW_HIGH(ONEWIRE_BUSMASK); if (!wait) return 0; _delay_ms(800); /* The specification say, that we have to wait at least 500ms in parasite mode to wait for the end of the conversion. 800ms works more reliably */ while(!ow_read(ONEWIRE_BUSMASK)); return 1; }
/* high-level functions */ int8_t noinline ow_search_rom(uint8_t busmask, uint8_t first) { /* reset discover state machine */ if (first) { ow_global.last_discrepancy = -1; /* reset rom code */ for (uint8_t i = 0; i < 8; i++) ow_global.current_rom.bytewise[i] = 0; } else { /* if last_discrepancy is below zero, discovery is done */ if (ow_global.last_discrepancy < 0) return 0; } int8_t discrepancy = -1; /* reset the bus */ if (!reset_onewire(busmask)) return -1; /* transmit command byte */ ow_write_byte(busmask, OW_ROM_SEARCH_ROM); for (uint8_t i = 0; i <64; i++) { /* read bits */ uint8_t bit1 = ow_read(busmask); uint8_t bits = (uint8_t)((ow_read(busmask) << 1) | bit1); if (bits == 3) { /* no devices, just return */ return 0; } else if (bits == 0) { if (i == ow_global.last_discrepancy) { /* set one */ ow_set_address_bit(&ow_global.current_rom, i, 1); /* transmit one next time */ bit1 = 1; } else if (i > ow_global.last_discrepancy) { /* set zero */ ow_set_address_bit(&ow_global.current_rom, i, 0); discrepancy = (int8_t)i; } else { uint8_t rom_bit = (uint8_t)(ow_global.current_rom.bytewise[i / 8] & _BV(i % 8)); if (rom_bit == 0) discrepancy = (int8_t)i; /* transmit last bit next time */ bit1 = rom_bit; } } else { /* normal case, no discrepancy */ ow_set_address_bit(&ow_global.current_rom, i, bit1); } OW_CONFIG_OUTPUT(busmask); /* select next bit */ ow_write(busmask, bit1); } ow_global.last_discrepancy = discrepancy; /* new device discovered */ return 1; }