From a2b9d688ea1cd66d46618a26062ccf8ada225328 Mon Sep 17 00:00:00 2001 From: Alex Stewart Date: Mon, 14 Mar 2016 21:59:39 -0700 Subject: [PATCH] Multiple cleanups/tweaks for onewire driver Use onewire_addr_t for onewire addresses Move internal defines out of onewire.h Remove global variables for search state use taskENTER_CRITICAL instead of portDISABLE_INTERRUPTS remove unnecessary onewire_init function Remove unnecessary critical sections Use GPIO_OUT_OPEN_DRAIN reformat/style cleanup --- examples/ds18b20_onewire/ds18b20_onewire.c | 4 - extras/ds18b20/ds18b20.c | 28 +- extras/onewire/onewire.c | 542 ++++++++++----------- extras/onewire/onewire.h | 89 ++-- 4 files changed, 304 insertions(+), 359 deletions(-) diff --git a/examples/ds18b20_onewire/ds18b20_onewire.c b/examples/ds18b20_onewire/ds18b20_onewire.c index 78d13bf..e152b10 100644 --- a/examples/ds18b20_onewire/ds18b20_onewire.c +++ b/examples/ds18b20_onewire/ds18b20_onewire.c @@ -12,8 +12,6 @@ // DS18B20 driver #include "ds18b20/ds18b20.h" -// Onewire init -#include "onewire/onewire.h" void print_temperature(void *pvParameters) { @@ -26,8 +24,6 @@ void print_temperature(void *pvParameters) // Use GPIO 13 as one wire pin. uint8_t GPIO_FOR_ONE_WIRE = 13; - onewire_init(GPIO_FOR_ONE_WIRE); - while(1) { // Search all DS18B20, return its amount and feed 't' structure with result data. amount = ds18b20_read_all(GPIO_FOR_ONE_WIRE, t); diff --git a/extras/ds18b20/ds18b20.c b/extras/ds18b20/ds18b20.c index dc028fc..9814018 100644 --- a/extras/ds18b20/ds18b20.c +++ b/extras/ds18b20/ds18b20.c @@ -17,27 +17,28 @@ #define DS1820_CONVERT_T 0x44 uint8_t ds18b20_read_all(uint8_t pin, ds_sensor_t *result) { - - uint8_t addr[8]; + onewire_addr_t addr; + onewire_search_t search; uint8_t sensor_id = 0; - onewire_reset_search(pin); + + onewire_search_start(&search); - while(onewire_search(pin, addr)){ - uint8_t crc = onewire_crc8(addr, 7); - if (crc != addr[7]){ - printf("CRC check failed: %02X %02X\n", addr[7], crc); + while ((addr = onewire_search_next(&search, pin)) != ONEWIRE_NONE) { + uint8_t crc = onewire_crc8((uint8_t *)&addr, 7); + if (crc != (addr >> 56)){ + printf("CRC check failed: %02X %02X\n", (unsigned)(addr >> 56), crc); return 0; } onewire_reset(pin); onewire_select(pin, addr); - onewire_write(pin, DS1820_CONVERT_T, ONEWIRE_DEFAULT_POWER); + onewire_write(pin, DS1820_CONVERT_T); vTaskDelay(750 / portTICK_RATE_MS); onewire_reset(pin); onewire_select(pin, addr); - onewire_write(pin, DS1820_READ_SCRATCHPAD, ONEWIRE_DEFAULT_POWER); + onewire_write(pin, DS1820_READ_SCRATCHPAD); uint8_t get[10]; @@ -71,15 +72,14 @@ uint8_t ds18b20_read_all(uint8_t pin, ds_sensor_t *result) { float ds18b20_read_single(uint8_t pin) { onewire_reset(pin); - - onewire_write(pin, DS1820_SKIP_ROM, ONEWIRE_DEFAULT_POWER); - onewire_write(pin, DS1820_CONVERT_T, ONEWIRE_DEFAULT_POWER); + onewire_skip_rom(pin); + onewire_write(pin, DS1820_CONVERT_T); vTaskDelay(750 / portTICK_RATE_MS); onewire_reset(pin); - onewire_write(pin, DS1820_SKIP_ROM, ONEWIRE_DEFAULT_POWER); - onewire_write(pin, DS1820_READ_SCRATCHPAD, ONEWIRE_DEFAULT_POWER); + onewire_skip_rom(pin); + onewire_write(pin, DS1820_READ_SCRATCHPAD); uint8_t get[10]; diff --git a/extras/onewire/onewire.c b/extras/onewire/onewire.c index 3a946ba..8962f26 100644 --- a/extras/onewire/onewire.c +++ b/extras/onewire/onewire.c @@ -1,206 +1,176 @@ #include "onewire.h" - -// global search state -static unsigned char ROM_NO[ONEWIRE_NUM][8]; -static uint8_t LastDiscrepancy[ONEWIRE_NUM]; -static uint8_t LastFamilyDiscrepancy[ONEWIRE_NUM]; -static uint8_t LastDeviceFlag[ONEWIRE_NUM]; - -void onewire_init(uint8_t pin) -{ - gpio_enable(pin, GPIO_INPUT); - onewire_reset_search(pin); -} +#include "string.h" +#include "task.h" +#include "esp/gpio.h" // Perform the onewire reset function. We will wait up to 250uS for // the bus to come high, if it doesn't then it is broken or shorted -// and we return a 0; +// and we return false; // -// Returns 1 if a device asserted a presence pulse, 0 otherwise. +// Returns true if a device asserted a presence pulse, false otherwise. // -uint8_t onewire_reset(uint8_t pin) -{ - uint8_t r; - uint8_t retries = 125; +bool onewire_reset(int pin) { + bool r; + const int retries = 50; - noInterrupts(); - DIRECT_MODE_INPUT(pin); - interrupts(); - // wait until the wire is high... just in case - do { - if (--retries == 0) return 0; - delayMicroseconds(2); - } while ( !DIRECT_READ(pin)); + gpio_enable(pin, GPIO_OUT_OPEN_DRAIN); + gpio_write(pin, 1); + // wait until the wire is high... just in case + for (int i = 0; i < retries; i++) { + if (gpio_read(pin)) break; + sdk_os_delay_us(5); + } + if (!gpio_read(pin)) { + // Bus shorted? + return false; + } - noInterrupts(); - DIRECT_WRITE_LOW(pin); - DIRECT_MODE_OUTPUT(pin); // drive output low - interrupts(); - delayMicroseconds(480); - noInterrupts(); - DIRECT_MODE_INPUT(pin); // allow it to float - delayMicroseconds(70); - r = !DIRECT_READ(pin); - interrupts(); - delayMicroseconds(410); - return r; + gpio_write(pin, 0); + sdk_os_delay_us(480); + + taskENTER_CRITICAL(); + gpio_write(pin, 1); // allow it to float + sdk_os_delay_us(70); + r = !gpio_read(pin); + taskEXIT_CRITICAL(); + + // Wait for all devices to finish pulling the bus low before returning + for (int i = 0; i < retries; i++) { + if (gpio_read(pin)) break; + sdk_os_delay_us(5); + } + sdk_os_delay_us(2); + + return r; } -// Write a bit. Port and bit is used to cut lookup time and provide -// more certain timing. -// -static void onewire_write_bit(uint8_t pin, uint8_t v) -{ - if (v & 1) { - noInterrupts(); - DIRECT_WRITE_LOW(pin); - DIRECT_MODE_OUTPUT(pin); // drive output low - delayMicroseconds(10); - DIRECT_WRITE_HIGH(pin); // drive output high - interrupts(); - delayMicroseconds(55); - } else { - noInterrupts(); - DIRECT_WRITE_LOW(pin); - DIRECT_MODE_OUTPUT(pin); // drive output low - delayMicroseconds(65); - DIRECT_WRITE_HIGH(pin); // drive output high - interrupts(); - delayMicroseconds(5); - } +static void onewire_write_bit(int pin, uint8_t v) { + //TODO: should verify that the bus is high before starting + if (v & 1) { + taskENTER_CRITICAL(); + gpio_write(pin, 0); // drive output low + sdk_os_delay_us(10); + gpio_write(pin, 1); // allow output high + taskEXIT_CRITICAL(); + sdk_os_delay_us(55); + } else { + taskENTER_CRITICAL(); + gpio_write(pin, 0); // drive output low + sdk_os_delay_us(65); + gpio_write(pin, 1); // allow output high + taskEXIT_CRITICAL(); + } + sdk_os_delay_us(1); } -// Read a bit. Port and bit is used to cut lookup time and provide -// more certain timing. -// -static uint8_t onewire_read_bit(uint8_t pin) -{ - uint8_t r; +static int onewire_read_bit(int pin) { + int r; - noInterrupts(); - DIRECT_MODE_OUTPUT(pin); - DIRECT_WRITE_LOW(pin); - delayMicroseconds(3); - DIRECT_MODE_INPUT(pin); // let pin float, pull up will raise - delayMicroseconds(10); - r = DIRECT_READ(pin); - interrupts(); - delayMicroseconds(53); - return r; + //TODO: should verify that the bus is high before starting + taskENTER_CRITICAL(); + gpio_write(pin, 0); + sdk_os_delay_us(2); + gpio_write(pin, 1); // let pin float, pull up will raise + sdk_os_delay_us(11); + r = gpio_read(pin); // Must sample within 15us of start + taskEXIT_CRITICAL(); + sdk_os_delay_us(48); + + return r; } -// Write a byte. The writing code uses the active drivers to raise the -// pin high, if you need power after the write (e.g. DS18S20 in -// parasite power mode) then set 'power' to 1, otherwise the pin will -// go tri-state at the end of the write to avoid heating in a short or -// other mishap. +// Write a byte. The writing code uses open-drain mode and expects the pullup +// resistor to pull the line high when not driven low. If you need strong +// power after the write (e.g. DS18B20 in parasite power mode) then call +// onewire_power() after this is complete to actively drive the line high. // -void onewire_write(uint8_t pin, uint8_t v, uint8_t power /* = 0 */) { - uint8_t bitMask; +void onewire_write(int pin, uint8_t v) { + uint8_t bitMask; - for (bitMask = 0x01; bitMask; bitMask <<= 1) { - onewire_write_bit(pin, (bitMask & v)?1:0); - } - if ( !power) { - noInterrupts(); - DIRECT_MODE_INPUT(pin); - DIRECT_WRITE_LOW(pin); - interrupts(); - } + for (bitMask = 0x01; bitMask; bitMask <<= 1) { + onewire_write_bit(pin, (bitMask & v)?1:0); + } } -void onewire_write_bytes(uint8_t pin, const uint8_t *buf, uint16_t count, bool power /* = 0 */) { - uint16_t i; - for (i = 0 ; i < count ; i++) - onewire_write(pin, buf[i], ONEWIRE_DEFAULT_POWER); - if (!power) { - noInterrupts(); - DIRECT_MODE_INPUT(pin); - DIRECT_WRITE_LOW(pin); - interrupts(); - } +void onewire_write_bytes(int pin, const uint8_t *buf, size_t count) { + size_t i; + + for (i = 0 ; i < count ; i++) { + onewire_write(pin, buf[i]); + } } // Read a byte // -uint8_t onewire_read(uint8_t pin) { - uint8_t bitMask; - uint8_t r = 0; +uint8_t onewire_read(int pin) { + uint8_t bitMask; + uint8_t r = 0; - for (bitMask = 0x01; bitMask; bitMask <<= 1) { - if (onewire_read_bit(pin)) r |= bitMask; - } - return r; + for (bitMask = 0x01; bitMask; bitMask <<= 1) { + if (onewire_read_bit(pin)) r |= bitMask; + } + return r; } -void onewire_read_bytes(uint8_t pin, uint8_t *buf, uint16_t count) { - uint16_t i; - for (i = 0 ; i < count ; i++) - buf[i] = onewire_read(pin); +void onewire_read_bytes(int pin, uint8_t *buf, size_t count) { + size_t i; + + for (i = 0 ; i < count ; i++) { + buf[i] = onewire_read(pin); + } } // Do a ROM select // -void onewire_select(uint8_t pin, const uint8_t rom[8]) -{ +void onewire_select(int pin, onewire_addr_t rom) { uint8_t i; - onewire_write(pin, 0x55, ONEWIRE_DEFAULT_POWER); // Choose ROM + onewire_write(pin, 0x55); // Choose ROM - for (i = 0; i < 8; i++) onewire_write(pin, rom[i], ONEWIRE_DEFAULT_POWER); + for (i = 0; i < 8; i++) { + onewire_write(pin, rom & 0xff); + rom >>= 8; + } } // Do a ROM skip // -void onewire_skip(uint8_t pin) -{ - onewire_write(pin, 0xCC, ONEWIRE_DEFAULT_POWER); // Skip ROM +void onewire_skip_rom(int pin) { + onewire_write(pin, 0xCC); // Skip ROM } -void onewire_depower(uint8_t pin) -{ - noInterrupts(); - DIRECT_MODE_INPUT(pin); - interrupts(); +void onewire_power(int pin) { + gpio_enable(pin, GPIO_OUTPUT); + gpio_write(pin, 1); } -// You need to use this function to start a search again from the beginning. -// You do not need to do it for the first search, though you could. -// -void onewire_reset_search(uint8_t pin) -{ - // reset the search state - LastDiscrepancy[pin] = 0; - LastDeviceFlag[pin] = 0; - LastFamilyDiscrepancy[pin] = 0; - int i; - for(i = 7; ; i--) { - ROM_NO[pin][i] = 0; - if ( i == 0) break; - } +void onewire_depower(int pin) { + gpio_enable(pin, GPIO_OUT_OPEN_DRAIN); +} + +void onewire_search_start(onewire_search_t *search) { + // reset the search state + memset(search, 0, sizeof(*search)); } // Setup the search to find the device type 'family_code' on the next call // to search(*newAddr) if it is present. // -void onewire_target_search(uint8_t pin, uint8_t family_code) -{ - // set the search state to find SearchFamily type devices - ROM_NO[pin][0] = family_code; - uint8_t i; - for (i = 1; i < 8; i++) - ROM_NO[pin][i] = 0; - LastDiscrepancy[pin] = 64; - LastFamilyDiscrepancy[pin] = 0; - LastDeviceFlag[pin] = 0; +void onewire_search_prefix(onewire_search_t *search, uint8_t family_code) { + uint8_t i; + + search->rom_no[0] = family_code; + for (i = 1; i < 8; i++) { + search->rom_no[i] = 0; + } + search->last_discrepancy = 64; + search->last_device_found = false; } -// Perform a search. If this function returns a '1' then it has -// enumerated the next device and you may retrieve the ROM from the -// OneWire::address variable. If there are no devices, no further +// Perform a search. If the next device has been successfully enumerated, its +// ROM address will be returned. If there are no devices, no further // devices, or something horrible happens in the middle of the -// enumeration then a 0 is returned. If a new device is found then -// its address is copied to newAddr. Use OneWire::reset_search() to +// enumeration then ONEWIRE_NONE is returned. Use OneWire::reset_search() to // start over. // // --- Replaced by the one from the Dallas Semiconductor web site --- @@ -210,129 +180,115 @@ void onewire_target_search(uint8_t pin, uint8_t family_code) // Return 1 : device found, ROM number in ROM_NO buffer // 0 : device not found, end of search // -uint8_t onewire_search(uint8_t pin, uint8_t *newAddr) -{ - uint8_t id_bit_number; - uint8_t last_zero, rom_byte_number, search_result; - uint8_t id_bit, cmp_id_bit; +onewire_addr_t onewire_search_next(onewire_search_t *search, int pin) { + uint8_t id_bit_number; + uint8_t last_zero, search_result; + int rom_byte_number; + uint8_t id_bit, cmp_id_bit; + onewire_addr_t addr; - unsigned char rom_byte_mask, search_direction; + unsigned char rom_byte_mask, search_direction; - // initialize for search - id_bit_number = 1; - last_zero = 0; - rom_byte_number = 0; - rom_byte_mask = 1; - search_result = 0; + // initialize for search + id_bit_number = 1; + last_zero = 0; + rom_byte_number = 0; + rom_byte_mask = 1; + search_result = 0; - // if the last call was not the last one - if (!LastDeviceFlag[pin]) - { - // 1-Wire reset - if (!onewire_reset(pin)) - { - // reset the search - LastDiscrepancy[pin] = 0; - LastDeviceFlag[pin] = 0; - LastFamilyDiscrepancy[pin] = 0; - return 0; - } + // if the last call was not the last one + if (!search->last_device_found) { + // 1-Wire reset + if (!onewire_reset(pin)) { + // reset the search + search->last_discrepancy = 0; + search->last_device_found = false; + return ONEWIRE_NONE; + } - // issue the search command - onewire_write(pin, 0xF0, ONEWIRE_DEFAULT_POWER); + // issue the search command + onewire_write(pin, 0xF0); - // loop to do the search - do - { - // read a bit and its complement - id_bit = onewire_read_bit(pin); - cmp_id_bit = onewire_read_bit(pin); + // loop to do the search + do { + // read a bit and its complement + id_bit = onewire_read_bit(pin); + cmp_id_bit = onewire_read_bit(pin); - // check for no devices on 1-wire - if ((id_bit == 1) && (cmp_id_bit == 1)) - break; - else - { - // all devices coupled have 0 or 1 - if (id_bit != cmp_id_bit) - search_direction = id_bit; // bit write value for search - else - { - // if this discrepancy if before the Last Discrepancy - // on a previous next then pick the same as last time - if (id_bit_number < LastDiscrepancy[pin]) - search_direction = ((ROM_NO[pin][rom_byte_number] & rom_byte_mask) > 0); - else - // if equal to last pick 1, if not then pick 0 - search_direction = (id_bit_number == LastDiscrepancy[pin]); + // check for no devices on 1-wire + if ((id_bit == 1) && (cmp_id_bit == 1)) { + break; + } else { + // all devices coupled have 0 or 1 + if (id_bit != cmp_id_bit) { + search_direction = id_bit; // bit write value for search + } else { + // if this discrepancy if before the Last Discrepancy + // on a previous next then pick the same as last time + if (id_bit_number < search->last_discrepancy) { + search_direction = ((search->rom_no[rom_byte_number] & rom_byte_mask) > 0); + } else { + // if equal to last pick 1, if not then pick 0 + search_direction = (id_bit_number == search->last_discrepancy); + } - // if 0 was picked then record its position in LastZero - if (search_direction == 0) - { - last_zero = id_bit_number; + // if 0 was picked then record its position in LastZero + if (search_direction == 0) { + last_zero = id_bit_number; + } + } - // check for Last discrepancy in family - if (last_zero < 9) - LastFamilyDiscrepancy[pin] = last_zero; - } + // set or clear the bit in the ROM byte rom_byte_number + // with mask rom_byte_mask + if (search_direction == 1) { + search->rom_no[rom_byte_number] |= rom_byte_mask; + } else { + search->rom_no[rom_byte_number] &= ~rom_byte_mask; + } + + // serial number search direction write bit + onewire_write_bit(pin, search_direction); + + // increment the byte counter id_bit_number + // and shift the mask rom_byte_mask + id_bit_number++; + rom_byte_mask <<= 1; + + // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask + if (rom_byte_mask == 0) { + rom_byte_number++; + rom_byte_mask = 1; + } + } + } while (rom_byte_number < 8); // loop until through all ROM bytes 0-7 + + // if the search was successful then + if (!(id_bit_number < 65)) { + // search successful so set last_discrepancy,last_device_found,search_result + search->last_discrepancy = last_zero; + + // check for last device + if (search->last_discrepancy == 0) { + search->last_device_found = true; } - // set or clear the bit in the ROM byte rom_byte_number - // with mask rom_byte_mask - if (search_direction == 1) - ROM_NO[pin][rom_byte_number] |= rom_byte_mask; - else - ROM_NO[pin][rom_byte_number] &= ~rom_byte_mask; + search_result = 1; + } + } - // serial number search direction write bit - onewire_write_bit(pin, search_direction); - - // increment the byte counter id_bit_number - // and shift the mask rom_byte_mask - id_bit_number++; - rom_byte_mask <<= 1; - - // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask - if (rom_byte_mask == 0) - { - rom_byte_number++; - rom_byte_mask = 1; - } - } - } - while(rom_byte_number < 8); // loop until through all ROM bytes 0-7 - - // if the search was successful then - if (!(id_bit_number < 65)) - { - // search successful so set LastDiscrepancy,LastDeviceFlag,search_result - LastDiscrepancy[pin] = last_zero; - - // check for last device - if (LastDiscrepancy[pin] == 0) - LastDeviceFlag[pin] = 1; - - search_result = 1; - } - } - - // if no device found then reset counters so next 'search' will be like a first - if (!search_result || !ROM_NO[pin][0]) - { - LastDiscrepancy[pin] = 0; - LastDeviceFlag[pin] = 0; - LastFamilyDiscrepancy[pin] = 0; - search_result = 0; - } - else - { - for (rom_byte_number = 0; rom_byte_number < 8; rom_byte_number++) - { - newAddr[rom_byte_number] = ROM_NO[pin][rom_byte_number]; - //printf("Ok I found something at %d - %x...\n",rom_byte_number, newAddr[rom_byte_number]); - } - } - return search_result; + // if no device found then reset counters so next 'search' will be like a first + if (!search_result || !search->rom_no[0]) { + search->last_discrepancy = 0; + search->last_device_found = false; + return ONEWIRE_NONE; + } else { + addr = 0; + for (rom_byte_number = 7; rom_byte_number >= 0; rom_byte_number--) { + addr = (addr << 8) | search->rom_no[rom_byte_number]; + } + //printf("Ok I found something at %08x%08x...\n", (uint32_t)(addr >> 32), (uint32_t)addr); + } + return addr; } // The 1-Wire CRC scheme is described in Maxim Application Note 27: @@ -371,41 +327,38 @@ static const uint8_t dscrc_table[] = { // compared to all those delayMicrosecond() calls. But I got // confused, so I use this table from the examples.) // -uint8_t onewire_crc8(const uint8_t *addr, uint8_t len) -{ - uint8_t crc = 0; +uint8_t onewire_crc8(const uint8_t *data, uint8_t len) { + uint8_t crc = 0; - while (len--) { - crc = pgm_read_byte(dscrc_table + (crc ^ *addr++)); - } - return crc; + while (len--) { + crc = pgm_read_byte(dscrc_table + (crc ^ *data++)); + } + return crc; } #else // // Compute a Dallas Semiconductor 8 bit CRC directly. // this is much slower, but much smaller, than the lookup table. // -uint8_t onewire_crc8(const uint8_t *addr, uint8_t len) -{ - uint8_t crc = 0; - - while (len--) { - uint8_t inbyte = *addr++; - uint8_t i; - for (i = 8; i; i--) { - uint8_t mix = (crc ^ inbyte) & 0x01; - crc >>= 1; - if (mix) crc ^= 0x8C; - inbyte >>= 1; - } - } - return crc; +uint8_t onewire_crc8(const uint8_t *data, uint8_t len) { + uint8_t crc = 0; + + while (len--) { + uint8_t inbyte = *data++; + for (int i = 8; i; i--) { + uint8_t mix = (crc ^ inbyte) & 0x01; + crc >>= 1; + if (mix) crc ^= 0x8C; + inbyte >>= 1; + } + } + return crc; } #endif // Compute the 1-Wire CRC16 and compare it against the received CRC. // Example usage (reading a DS2408): - // // Put everything in a buffer so we can compute the CRC easily. +// // Put everything in a buffer so we can compute the CRC easily. // uint8_t buf[13]; // buf[0] = 0xF0; // Read PIO Registers // buf[1] = 0x88; // LSB address @@ -423,9 +376,8 @@ uint8_t onewire_crc8(const uint8_t *addr, uint8_t len) // *not* at a 16-bit integer. // @param crc - The crc starting value (optional) // @return 1, iff the CRC matches. -bool onewire_check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc) -{ - crc = ~onewire_crc16(input, len, crc); +bool onewire_check_crc16(const uint8_t* input, size_t len, const uint8_t* inverted_crc, uint16_t crc_iv) { + uint16_t crc = ~onewire_crc16(input, len, crc_iv); return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1]; } @@ -441,8 +393,8 @@ bool onewire_check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inve // @param len - How many bytes to use. // @param crc - The crc starting value (optional) // @return The CRC16, as defined by Dallas Semiconductor. -uint16_t onewire_crc16(const uint8_t* input, uint16_t len, uint16_t crc) -{ +uint16_t onewire_crc16(const uint8_t* input, size_t len, uint16_t crc_iv) { + uint16_t crc = crc_iv; static const uint8_t oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; @@ -463,4 +415,4 @@ uint16_t onewire_crc16(const uint8_t* input, uint16_t len, uint16_t crc) crc ^= cdata; } return crc; -} \ No newline at end of file +} diff --git a/extras/onewire/onewire.h b/extras/onewire/onewire.h index 1a0b15d..4ee314b 100644 --- a/extras/onewire/onewire.h +++ b/extras/onewire/onewire.h @@ -29,75 +29,72 @@ #define ONEWIRE_CRC8_TABLE 0 #endif -// Platform specific I/O definitions -#define noInterrupts portDISABLE_INTERRUPTS -#define interrupts portENABLE_INTERRUPTS -#define delayMicroseconds sdk_os_delay_us +typedef uint64_t onewire_addr_t; -#define DIRECT_READ(pin) gpio_read(pin) -#define DIRECT_MODE_INPUT(pin) gpio_enable(pin, GPIO_INPUT) -#define DIRECT_MODE_OUTPUT(pin) gpio_enable(pin, GPIO_OUTPUT) -#define DIRECT_WRITE_LOW(pin) gpio_write(pin, 0) -#define DIRECT_WRITE_HIGH(pin) gpio_write(pin, 1) +typedef struct { + uint8_t rom_no[8]; + uint8_t last_discrepancy; + bool last_device_found; +} onewire_search_t; -void onewire_init(uint8_t pin); +// The following is an invalid ROM address that will never occur in a device +// (CRC mismatch), and so can be useful as an indicator for "no-such-device", +// etc. +#define ONEWIRE_NONE ((onewire_addr_t)(0xffffffffffffffffLL)) // Perform a 1-Wire reset cycle. Returns 1 if a device responds // with a presence pulse. Returns 0 if there is no device or the // bus is shorted or otherwise held low for more than 250uS -uint8_t onewire_reset(uint8_t pin); +bool onewire_reset(int pin); // Issue a 1-Wire rom select command, you do the reset first. -void onewire_select(uint8_t pin, const uint8_t rom[8]); +void onewire_select(int pin, const onewire_addr_t rom); // Issue a 1-Wire rom skip command, to address all on bus. -void onewire_skip(uint8_t pin); +void onewire_skip_rom(int pin); -// Write a byte. If 'power' is one then the wire is held high at -// the end for parasitically powered devices. You are responsible -// for eventually depowering it by calling depower() or doing -// another read or write. -void onewire_write(uint8_t pin, uint8_t v, uint8_t power); +// Write a byte. The writing code uses open-drain mode and expects the pullup +// resistor to pull the line high when not driven low. If you need strong +// power after the write (e.g. DS18B20 in parasite power mode) then call +// onewire_power() after this is complete to actively drive the line high. +void onewire_write(int pin, uint8_t v); -void onewire_write_bytes(uint8_t pin, const uint8_t *buf, uint16_t count, bool power); +void onewire_write_bytes(int pin, const uint8_t *buf, size_t count); // Read a byte. -uint8_t onewire_read(uint8_t pin); +uint8_t onewire_read(int pin); -void onewire_read_bytes(uint8_t pin, uint8_t *buf, uint16_t count); +void onewire_read_bytes(int pin, uint8_t *buf, size_t count); -// Write a bit. The bus is always left powered at the end, see -// note in write() about that. -// void onewire_write_bit(uint8_t pin, uint8_t v); - -// Read a bit. -// uint8_t onewire_read_bit(uint8_t pin); +// Actively drive the bus high to provide extra power for certain operations of +// parasitically-powered devices. +void onewire_power(int pin); // Stop forcing power onto the bus. You only need to do this if -// you used the 'power' flag to write() or used a write_bit() call -// and aren't about to do another read or write. You would rather -// not leave this powered if you don't have to, just in case -// someone shorts your bus. -void onewire_depower(uint8_t pin); +// you previously called onewire_power() to drive the bus high and now want to +// allow it to float instead. Note that onewire_reset() will also +// automatically depower the bus first, so you do not need to call this first +// if you just want to start a new operation. +void onewire_depower(int pin); // Clear the search state so that if will start from the beginning again. -void onewire_reset_search(uint8_t pin); +void onewire_search_start(onewire_search_t *search); // Setup the search to find the device type 'family_code' on the next call // to search(*newAddr) if it is present. -void onewire_target_search(uint8_t pin, uint8_t family_code); +void onewire_search_prefix(onewire_search_t *search, uint8_t family_code); -// Look for the next device. Returns 1 if a new address has been -// returned. A zero might mean that the bus is shorted, there are -// no devices, or you have already retrieved all of them. It -// might be a good idea to check the CRC to make sure you didn't -// get garbage. The order is deterministic. You will always get -// the same devices in the same order. -uint8_t onewire_search(uint8_t pin, uint8_t *newAddr); +// Look for the next device. Returns the address of the next device on the bus, +// or ONEWIRE_NONE if there is no next address. ONEWIRE_NONE might mean that +// the bus is shorted, there are no devices, or you have already retrieved all +// of them. It might be a good idea to check the CRC to make sure you didn't +// get garbage. The order is deterministic. You will always get the same +// devices in the same order. +onewire_addr_t onewire_search_next(onewire_search_t *search, int pin); // Compute a Dallas Semiconductor 8 bit CRC, these are used in the // ROM and scratchpad registers. -uint8_t onewire_crc8(const uint8_t *addr, uint8_t len); +uint8_t onewire_crc8(const uint8_t *data, uint8_t len); // Compute the 1-Wire CRC16 and compare it against the received CRC. // Example usage (reading a DS2408): @@ -117,9 +114,9 @@ uint8_t onewire_crc8(const uint8_t *addr, uint8_t len); // @param inverted_crc - The two CRC16 bytes in the received data. // This should just point into the received data, // *not* at a 16-bit integer. -// @param crc - The crc starting value (optional) +// @param crc_iv - The crc starting value (optional) // @return True, iff the CRC matches. -bool onewire_check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc); +bool onewire_check_crc16(const uint8_t* input, size_t len, const uint8_t* inverted_crc, uint16_t crc_iv); // Compute a Dallas Semiconductor 16 bit CRC. This is required to check // the integrity of data received from many 1-Wire devices. Note that the @@ -131,8 +128,8 @@ bool onewire_check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inve // byte order than the two bytes you get from 1-Wire. // @param input - Array of bytes to checksum. // @param len - How many bytes to use. -// @param crc - The crc starting value (optional) +// @param crc_iv - The crc starting value (optional) // @return The CRC16, as defined by Dallas Semiconductor. -uint16_t onewire_crc16(const uint8_t* input, uint16_t len, uint16_t crc); +uint16_t onewire_crc16(const uint8_t* input, size_t len, uint16_t crc_iv); #endif