Merge pull request #121 from foogod/ds18b20-updates
DS18B20 API Improvements
This commit is contained in:
		
						commit
						83c5f91bc0
					
				
					 6 changed files with 830 additions and 483 deletions
				
			
		| 
						 | 
				
			
			@ -19,15 +19,14 @@
 | 
			
		|||
 | 
			
		||||
// DS18B20 driver
 | 
			
		||||
#include "ds18b20/ds18b20.h"
 | 
			
		||||
// Onewire init
 | 
			
		||||
#include "onewire/onewire.h"
 | 
			
		||||
 | 
			
		||||
void broadcast_temperature(void *pvParameters)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    uint8_t amount = 0;
 | 
			
		||||
    uint8_t sensors = 2;
 | 
			
		||||
    ds_sensor_t t[sensors];
 | 
			
		||||
    uint8_t sensors = 1;
 | 
			
		||||
    ds18b20_addr_t addrs[sensors];
 | 
			
		||||
    float results[sensors];
 | 
			
		||||
    
 | 
			
		||||
    // Use GPIO 13 as one wire pin. 
 | 
			
		||||
    uint8_t GPIO_FOR_ONE_WIRE = 13;
 | 
			
		||||
| 
						 | 
				
			
			@ -36,8 +35,6 @@ void broadcast_temperature(void *pvParameters)
 | 
			
		|||
 | 
			
		||||
    // Broadcaster part
 | 
			
		||||
    err_t err;
 | 
			
		||||
    // Initialize one wire bus.
 | 
			
		||||
    onewire_init(GPIO_FOR_ONE_WIRE);
 | 
			
		||||
 | 
			
		||||
    while(1) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -66,18 +63,17 @@ void broadcast_temperature(void *pvParameters)
 | 
			
		|||
 | 
			
		||||
        for(;;) {
 | 
			
		||||
            // Search all DS18B20, return its amount and feed 't' structure with result data.
 | 
			
		||||
            amount = ds18b20_read_all(GPIO_FOR_ONE_WIRE, t);
 | 
			
		||||
            amount = ds18b20_scan_devices(GPIO_FOR_ONE_WIRE, addrs, sensors);
 | 
			
		||||
 | 
			
		||||
            if (amount < sensors){
 | 
			
		||||
                printf("Something is wrong, I expect to see %d sensors \nbut just %d was detected!\n", sensors, amount);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < amount; ++i)
 | 
			
		||||
            ds18b20_measure_and_read_multi(GPIO_FOR_ONE_WIRE, addrs, sensors, results);
 | 
			
		||||
            for (int i = 0; i < sensors; ++i)
 | 
			
		||||
            {
 | 
			
		||||
                int intpart = (int)t[i].value;
 | 
			
		||||
                int fraction = (int)((t[i].value - intpart) * 100);
 | 
			
		||||
                // Multiple "" here is just to satisfy compiler and don`t raise 'hex escape sequence out of range' warning.
 | 
			
		||||
                sprintf(msg, "Sensor %d report: %d.%02d ""\xC2""\xB0""C\n",t[i].id, intpart, fraction);
 | 
			
		||||
                // ("\xC2\xB0" is the degree character (U+00B0) in UTF-8)
 | 
			
		||||
                sprintf(msg, "Sensor %08x%08x reports: %f \xC2\xB0""C\n", (uint32_t)(addrs[i] >> 32), (uint32_t)addrs[i], results[i]);
 | 
			
		||||
                printf("%s", msg);
 | 
			
		||||
 | 
			
		||||
                struct netbuf* buf = netbuf_new();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,59 +1,78 @@
 | 
			
		|||
/* ds18b20 - Retrieves temperature from ds18b20 sensors and print it out.
 | 
			
		||||
/* ds18b20_onewire.c - Retrieves readings from one or more DS18B20 temperature
 | 
			
		||||
 * sensors, and prints the results to stdout.
 | 
			
		||||
 *
 | 
			
		||||
 * This sample code is in the public domain.,
 | 
			
		||||
 */
 | 
			
		||||
#include "espressif/esp_common.h"
 | 
			
		||||
#include "esp/uart.h"
 | 
			
		||||
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
#include "task.h"
 | 
			
		||||
#include "timers.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "esp/uart.h"
 | 
			
		||||
 | 
			
		||||
// DS18B20 driver
 | 
			
		||||
#include "ds18b20/ds18b20.h"
 | 
			
		||||
// Onewire init
 | 
			
		||||
#include "onewire/onewire.h"
 | 
			
		||||
 
 | 
			
		||||
void print_temperature(void *pvParameters)
 | 
			
		||||
{
 | 
			
		||||
    int delay = 500;
 | 
			
		||||
    uint8_t amount = 0;
 | 
			
		||||
    // Declare amount of sensors
 | 
			
		||||
    uint8_t sensors = 2;
 | 
			
		||||
    ds_sensor_t t[sensors];
 | 
			
		||||
    
 | 
			
		||||
    // Use GPIO 13 as one wire pin. 
 | 
			
		||||
    uint8_t GPIO_FOR_ONE_WIRE = 13;
 | 
			
		||||
    
 | 
			
		||||
    onewire_init(GPIO_FOR_ONE_WIRE);
 | 
			
		||||
#define SENSOR_GPIO 13
 | 
			
		||||
#define MAX_SENSORS 8
 | 
			
		||||
#define RESCAN_INTERVAL 8
 | 
			
		||||
#define LOOP_DELAY_MS 250
 | 
			
		||||
 | 
			
		||||
void print_temperature(void *pvParameters) {
 | 
			
		||||
    ds18b20_addr_t addrs[MAX_SENSORS];
 | 
			
		||||
    float temps[MAX_SENSORS];
 | 
			
		||||
    int sensor_count;
 | 
			
		||||
    
 | 
			
		||||
    // There is no special initialization required before using the ds18b20
 | 
			
		||||
    // routines.  However, we make sure that the internal pull-up resistor is
 | 
			
		||||
    // enabled on the GPIO pin so that one can connect up a sensor without
 | 
			
		||||
    // needing an external pull-up (Note: The internal (~47k) pull-ups of the
 | 
			
		||||
    // ESP8266 do appear to work, at least for simple setups (one or two sensors
 | 
			
		||||
    // connected with short leads), but do not technically meet the pull-up
 | 
			
		||||
    // requirements from the DS18B20 datasheet and may not always be reliable.
 | 
			
		||||
    // For a real application, a proper 4.7k external pull-up resistor is
 | 
			
		||||
    // recommended instead!)
 | 
			
		||||
 | 
			
		||||
    gpio_set_pullup(SENSOR_GPIO, true, true);
 | 
			
		||||
 | 
			
		||||
    while(1) {
 | 
			
		||||
        // Search all DS18B20, return its amount and feed 't' structure with result data.
 | 
			
		||||
        amount = ds18b20_read_all(GPIO_FOR_ONE_WIRE, t);
 | 
			
		||||
        // Every RESCAN_INTERVAL samples, check to see if the sensors connected
 | 
			
		||||
        // to our bus have changed.
 | 
			
		||||
        sensor_count = ds18b20_scan_devices(SENSOR_GPIO, addrs, MAX_SENSORS);
 | 
			
		||||
 | 
			
		||||
        if (amount < sensors){
 | 
			
		||||
            printf("Something is wrong, I expect to see %d sensors \nbut just %d was detected!\n", sensors, amount);
 | 
			
		||||
        }
 | 
			
		||||
        if (sensor_count < 1) {
 | 
			
		||||
            printf("\nNo sensors detected!\n");
 | 
			
		||||
        } else {
 | 
			
		||||
            printf("\n%d sensors detected:\n", sensor_count);
 | 
			
		||||
            // If there were more sensors found than we have space to handle,
 | 
			
		||||
            // just report the first MAX_SENSORS..
 | 
			
		||||
            if (sensor_count > MAX_SENSORS) sensor_count = MAX_SENSORS;
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < amount; ++i)
 | 
			
		||||
        {
 | 
			
		||||
            int intpart = (int)t[i].value;
 | 
			
		||||
            int fraction = (int)((t[i].value - intpart) * 100);
 | 
			
		||||
            // Multiple "" here is just to satisfy compiler and don`t raise 'hex escape sequence out of range' warning.
 | 
			
		||||
            printf("Sensor %d report: %d.%02d ""\xC2""\xB0""C\n",t[i].id, intpart, fraction);
 | 
			
		||||
            // Do a number of temperature samples, and print the results.
 | 
			
		||||
            for (int i = 0; i < RESCAN_INTERVAL; i++) {
 | 
			
		||||
                ds18b20_measure_and_read_multi(SENSOR_GPIO, addrs, sensor_count, temps);
 | 
			
		||||
                for (int j = 0; j < sensor_count; j++) {
 | 
			
		||||
                    // The DS18B20 address is a 64-bit integer, but newlib-nano
 | 
			
		||||
                    // printf does not support printing 64-bit values, so we
 | 
			
		||||
                    // split it up into two 32-bit integers and print them
 | 
			
		||||
                    // back-to-back to make it look like one big hex number.
 | 
			
		||||
                    uint32_t addr0 = addrs[j] >> 32;
 | 
			
		||||
                    uint32_t addr1 = addrs[j];
 | 
			
		||||
                    float temp_c = temps[j];
 | 
			
		||||
                    float temp_f = (temp_c * 1.8) + 32;
 | 
			
		||||
                    printf("  Sensor %08x%08x reports %f deg C (%f deg F)\n", addr0, addr1, temp_c, temp_f);
 | 
			
		||||
                }
 | 
			
		||||
                printf("\n");
 | 
			
		||||
 | 
			
		||||
                // Wait for a little bit between each sample (note that the
 | 
			
		||||
                // ds18b20_measure_and_read_multi operation already takes at
 | 
			
		||||
                // least 750ms to run, so this is on top of that delay).
 | 
			
		||||
                vTaskDelay(LOOP_DELAY_MS / portTICK_RATE_MS);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        printf("\n");
 | 
			
		||||
        vTaskDelay(delay / portTICK_RATE_MS);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void user_init(void)
 | 
			
		||||
{
 | 
			
		||||
void user_init(void) {
 | 
			
		||||
    uart_set_baud(0, 115200);
 | 
			
		||||
 | 
			
		||||
    printf("SDK version:%s\n", sdk_system_get_sdk_version());
 | 
			
		||||
 | 
			
		||||
    xTaskCreate(&print_temperature, (signed char *)"print_temperature", 256, NULL, 2, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,43 +1,47 @@
 | 
			
		|||
#include "FreeRTOS.h"
 | 
			
		||||
#include "task.h"
 | 
			
		||||
#include "math.h"
 | 
			
		||||
 | 
			
		||||
#include "onewire/onewire.h"
 | 
			
		||||
#include "ds18b20.h"
 | 
			
		||||
 | 
			
		||||
#define DS1820_WRITE_SCRATCHPAD 0x4E
 | 
			
		||||
#define DS1820_READ_SCRATCHPAD  0xBE
 | 
			
		||||
#define DS1820_COPY_SCRATCHPAD  0x48
 | 
			
		||||
#define DS1820_READ_EEPROM      0xB8
 | 
			
		||||
#define DS1820_READ_PWRSUPPLY   0xB4
 | 
			
		||||
#define DS1820_SEARCHROM        0xF0
 | 
			
		||||
#define DS1820_SKIP_ROM         0xCC
 | 
			
		||||
#define DS1820_READROM          0x33
 | 
			
		||||
#define DS1820_MATCHROM         0x55
 | 
			
		||||
#define DS1820_ALARMSEARCH      0xEC
 | 
			
		||||
#define DS1820_CONVERT_T        0x44
 | 
			
		||||
#define DS18B20_WRITE_SCRATCHPAD 0x4E
 | 
			
		||||
#define DS18B20_READ_SCRATCHPAD  0xBE
 | 
			
		||||
#define DS18B20_COPY_SCRATCHPAD  0x48
 | 
			
		||||
#define DS18B20_READ_EEPROM      0xB8
 | 
			
		||||
#define DS18B20_READ_PWRSUPPLY   0xB4
 | 
			
		||||
#define DS18B20_SEARCHROM        0xF0
 | 
			
		||||
#define DS18B20_SKIP_ROM         0xCC
 | 
			
		||||
#define DS18B20_READROM          0x33
 | 
			
		||||
#define DS18B20_MATCHROM         0x55
 | 
			
		||||
#define DS18B20_ALARMSEARCH      0xEC
 | 
			
		||||
#define DS18B20_CONVERT_T        0x44
 | 
			
		||||
 | 
			
		||||
#define os_sleep_ms(x) vTaskDelay(((x) + portTICK_RATE_MS - 1) / portTICK_RATE_MS)
 | 
			
		||||
 | 
			
		||||
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, DS18B20_CONVERT_T);
 | 
			
		||||
        
 | 
			
		||||
        onewire_power(pin);
 | 
			
		||||
        vTaskDelay(750 / portTICK_RATE_MS);
 | 
			
		||||
        
 | 
			
		||||
        onewire_reset(pin);
 | 
			
		||||
        onewire_select(pin, addr);
 | 
			
		||||
        onewire_write(pin, DS1820_READ_SCRATCHPAD, ONEWIRE_DEFAULT_POWER);
 | 
			
		||||
        onewire_write(pin, DS18B20_READ_SCRATCHPAD);
 | 
			
		||||
 | 
			
		||||
        uint8_t get[10];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -71,15 +75,15 @@ uint8_t ds18b20_read_all(uint8_t pin, ds_sensor_t *result) {
 | 
			
		|||
float ds18b20_read_single(uint8_t pin) {
 | 
			
		||||
  
 | 
			
		||||
    onewire_reset(pin);
 | 
			
		||||
    onewire_skip_rom(pin);
 | 
			
		||||
    onewire_write(pin, DS18B20_CONVERT_T);
 | 
			
		||||
 | 
			
		||||
    onewire_write(pin, DS1820_SKIP_ROM, ONEWIRE_DEFAULT_POWER);
 | 
			
		||||
    onewire_write(pin, DS1820_CONVERT_T, ONEWIRE_DEFAULT_POWER);
 | 
			
		||||
 | 
			
		||||
    onewire_power(pin);
 | 
			
		||||
    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, DS18B20_READ_SCRATCHPAD);
 | 
			
		||||
    
 | 
			
		||||
    uint8_t get[10];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -106,3 +110,114 @@ float ds18b20_read_single(uint8_t pin) {
 | 
			
		|||
    return temperature;
 | 
			
		||||
    //printf("Got a DS18B20 Reading: %d.%02d\n", (int)temperature, (int)(temperature - (int)temperature) * 100);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ds18b20_measure(int pin, ds18b20_addr_t addr, bool wait) {
 | 
			
		||||
    if (!onewire_reset(pin)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (addr == DS18B20_ANY) {
 | 
			
		||||
        onewire_skip_rom(pin);
 | 
			
		||||
    } else {
 | 
			
		||||
        onewire_select(pin, addr);
 | 
			
		||||
    }
 | 
			
		||||
    taskENTER_CRITICAL();
 | 
			
		||||
    onewire_write(pin, DS18B20_CONVERT_T);
 | 
			
		||||
    // For parasitic devices, power must be applied within 10us after issuing
 | 
			
		||||
    // the convert command.
 | 
			
		||||
    onewire_power(pin);
 | 
			
		||||
    taskEXIT_CRITICAL();
 | 
			
		||||
 | 
			
		||||
    if (wait) {
 | 
			
		||||
        os_sleep_ms(750);
 | 
			
		||||
        onewire_depower(pin);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ds18b20_read_scratchpad(int pin, ds18b20_addr_t addr, uint8_t *buffer) {
 | 
			
		||||
    uint8_t crc;
 | 
			
		||||
    uint8_t expected_crc;
 | 
			
		||||
 | 
			
		||||
    if (!onewire_reset(pin)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (addr == DS18B20_ANY) {
 | 
			
		||||
        onewire_skip_rom(pin);
 | 
			
		||||
    } else {
 | 
			
		||||
        onewire_select(pin, addr);
 | 
			
		||||
    }
 | 
			
		||||
    onewire_write(pin, DS18B20_READ_SCRATCHPAD);
 | 
			
		||||
    
 | 
			
		||||
    for (int i = 0; i < 8; i++) {
 | 
			
		||||
        buffer[i] = onewire_read(pin);
 | 
			
		||||
    }
 | 
			
		||||
    crc = onewire_read(pin);
 | 
			
		||||
 | 
			
		||||
    expected_crc = onewire_crc8(buffer, 8);
 | 
			
		||||
    if (crc != expected_crc) {
 | 
			
		||||
        printf("CRC check failed reading scratchpad: %02x %02x %02x %02x %02x %02x %02x %02x : %02x (expected %02x)\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], crc, expected_crc);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float ds18b20_read_temperature(int pin, ds18b20_addr_t addr) {
 | 
			
		||||
    uint8_t scratchpad[8];
 | 
			
		||||
    int temp;
 | 
			
		||||
 | 
			
		||||
    if (!ds18b20_read_scratchpad(pin, addr, scratchpad)) {
 | 
			
		||||
        return NAN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    temp = scratchpad[1] << 8 | scratchpad[0];
 | 
			
		||||
    
 | 
			
		||||
    return ((float)temp * 625.0)/10000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float ds18b20_measure_and_read(int pin, ds18b20_addr_t addr) {
 | 
			
		||||
    if (!ds18b20_measure(pin, addr, true)) {
 | 
			
		||||
        return NAN;
 | 
			
		||||
    }
 | 
			
		||||
    return ds18b20_read_temperature(pin, addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ds18b20_measure_and_read_multi(int pin, ds18b20_addr_t *addr_list, int addr_count, float *result_list) {
 | 
			
		||||
    if (!ds18b20_measure(pin, DS18B20_ANY, true)) {
 | 
			
		||||
        for (int i=0; i < addr_count; i++) {
 | 
			
		||||
            result_list[i] = NAN;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return ds18b20_read_temp_multi(pin, addr_list, addr_count, result_list);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ds18b20_scan_devices(int pin, ds18b20_addr_t *addr_list, int addr_count) {
 | 
			
		||||
    onewire_search_t search;
 | 
			
		||||
    onewire_addr_t addr;
 | 
			
		||||
    int found = 0;
 | 
			
		||||
 | 
			
		||||
    onewire_search_start(&search);
 | 
			
		||||
    while ((addr = onewire_search_next(&search, pin)) != ONEWIRE_NONE) {
 | 
			
		||||
        if (found < addr_count) {
 | 
			
		||||
            addr_list[found] = addr;
 | 
			
		||||
        }
 | 
			
		||||
        found++;
 | 
			
		||||
    }
 | 
			
		||||
    return found;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ds18b20_read_temp_multi(int pin, ds18b20_addr_t *addr_list, int addr_count, float *result_list) {
 | 
			
		||||
    bool result = true;
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < addr_count; i++) {
 | 
			
		||||
        result_list[i] = ds18b20_read_temperature(pin, addr_list[i]);
 | 
			
		||||
        if (isnan(result_list[i])) {
 | 
			
		||||
            result = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,139 @@
 | 
			
		|||
#ifndef DRIVER_DS18B20_H_
 | 
			
		||||
#define DRIVER_DS18B20_H_
 | 
			
		||||
 | 
			
		||||
#include "onewire/onewire.h"
 | 
			
		||||
 | 
			
		||||
/** @file ds18b20.h
 | 
			
		||||
 *
 | 
			
		||||
 *  Communicate with the DS18B20 family of one-wire temperature sensor ICs.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef onewire_addr_t ds18b20_addr_t;
 | 
			
		||||
 | 
			
		||||
/** An address value which can be used to indicate "any device on the bus" */
 | 
			
		||||
#define DS18B20_ANY ONEWIRE_NONE
 | 
			
		||||
 | 
			
		||||
/** Find the addresses of all DS18B20 devices on the bus.
 | 
			
		||||
 *
 | 
			
		||||
 *  Scans the bus for all devices and places their addresses in the supplied
 | 
			
		||||
 *  array.  If there are more than `addr_count` devices on the bus, only the
 | 
			
		||||
 *  first `addr_count` are recorded.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin         The GPIO pin connected to the DS18B20 bus
 | 
			
		||||
 *  @param addr_list   A pointer to an array of ds18b20_addr_t values.  This
 | 
			
		||||
 *                     will be populated with the addresses of the found
 | 
			
		||||
 *                     devices.
 | 
			
		||||
 *  @param addr_count  Number of slots in the `addr_list` array.  At most this
 | 
			
		||||
 *                     many addresses will be returned.
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns The number of devices found.  Note that this may be less than,
 | 
			
		||||
 *  equal to, or more than `addr_count`, depending on how many DS18B20 devices
 | 
			
		||||
 *  are attached to the bus.
 | 
			
		||||
 */
 | 
			
		||||
int ds18b20_scan_devices(int pin, ds18b20_addr_t *addr_list, int addr_count);
 | 
			
		||||
 | 
			
		||||
/** Tell one or more sensors to perform a temperature measurement and
 | 
			
		||||
 *  conversion (CONVERT_T) operation.  This operation can take up to 750ms to
 | 
			
		||||
 *  complete.
 | 
			
		||||
 *
 | 
			
		||||
 *  If `wait=true`, this routine will automatically drive the pin high for the
 | 
			
		||||
 *  necessary 750ms after issuing the command to ensure parasitically-powered
 | 
			
		||||
 *  devices have enough power to perform the conversion operation (for
 | 
			
		||||
 *  non-parasitically-powered devices, this is not necessary but does not
 | 
			
		||||
 *  hurt).  If `wait=false`, this routine will drive the pin high, but will
 | 
			
		||||
 *  then return immediately.  It is up to the caller to wait the requisite time
 | 
			
		||||
 *  and then depower the bus using onewire_depower() or by issuing another
 | 
			
		||||
 *  command once conversion is done.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin   The GPIO pin connected to the DS18B20 device
 | 
			
		||||
 *  @param addr  The 64-bit address of the device on the bus.  This can be set
 | 
			
		||||
 *               to ::DS18B20_ANY to send the command to all devices on the bus
 | 
			
		||||
 *               at the same time.
 | 
			
		||||
 *  @param wait  Whether to wait for the necessary 750ms for the DS18B20 to
 | 
			
		||||
 *               finish performing the conversion before returning to the
 | 
			
		||||
 *               caller (You will normally want to do this).
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns `true` if the command was successfully issued, or `false` on error.
 | 
			
		||||
 */
 | 
			
		||||
bool ds18b20_measure(int pin, ds18b20_addr_t addr, bool wait);
 | 
			
		||||
 | 
			
		||||
/** Read the value from the last CONVERT_T operation.
 | 
			
		||||
 *
 | 
			
		||||
 *  This should be called after ds18b20_measure() to fetch the result of the
 | 
			
		||||
 *  temperature measurement.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin     The GPIO pin connected to the DS18B20 device
 | 
			
		||||
 *  @param addr    The 64-bit address of the device to read.  This can be set
 | 
			
		||||
 *                 to ::DS18B20_ANY to read any device on the bus (but note
 | 
			
		||||
 *                 that this will only work if there is exactly one device
 | 
			
		||||
 *                 connected, or they will corrupt each others' transmissions)
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns The temperature in degrees Celsius, or NaN if there was an error.
 | 
			
		||||
 */
 | 
			
		||||
float ds18b20_read_temperature(int pin, ds18b20_addr_t addr);
 | 
			
		||||
 | 
			
		||||
/** Read the value from the last CONVERT_T operation for multiple devices.
 | 
			
		||||
 *
 | 
			
		||||
 *  This should be called after ds18b20_measure() to fetch the result of the
 | 
			
		||||
 *  temperature measurement.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin         The GPIO pin connected to the DS18B20 bus
 | 
			
		||||
 *  @param addr_list   A list of addresses for devices to read.
 | 
			
		||||
 *  @param addr_count  The number of entries in `addr_list`.
 | 
			
		||||
 *  @param result_list An array of floats to hold the returned temperature
 | 
			
		||||
 *                     values.  It should have at least `addr_count` entries.
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns `true` if all temperatures were fetched successfully, or `false`
 | 
			
		||||
 *  if one or more had errors (the temperature for erroring devices will be
 | 
			
		||||
 *  returned as NaN).
 | 
			
		||||
 */
 | 
			
		||||
bool ds18b20_read_temp_multi(int pin, ds18b20_addr_t *addr_list, int addr_count, float *result_list);
 | 
			
		||||
 | 
			
		||||
/** Perform a ds18b20_measure() followed by ds18b20_read_temperature()
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin     The GPIO pin connected to the DS18B20 device
 | 
			
		||||
 *  @param addr    The 64-bit address of the device to read.  This can be set
 | 
			
		||||
 *                 to ::DS18B20_ANY to read any device on the bus (but note
 | 
			
		||||
 *                 that this will only work if there is exactly one device
 | 
			
		||||
 *                 connected, or they will corrupt each others' transmissions)
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns The temperature in degrees Celsius, or NaN if there was an error.
 | 
			
		||||
 */
 | 
			
		||||
float ds18b20_measure_and_read(int pin, ds18b20_addr_t addr);
 | 
			
		||||
 | 
			
		||||
/** Perform a ds18b20_measure() followed by ds18b20_read_temp_multi()
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin         The GPIO pin connected to the DS18B20 bus
 | 
			
		||||
 *  @param addr_list   A list of addresses for devices to read.
 | 
			
		||||
 *  @param addr_count  The number of entries in `addr_list`.
 | 
			
		||||
 *  @param result_list An array of floats to hold the returned temperature
 | 
			
		||||
 *                     values.  It should have at least `addr_count` entries.
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns `true` if all temperatures were fetched successfully, or `false`
 | 
			
		||||
 *  if one or more had errors (the temperature for erroring devices will be
 | 
			
		||||
 *  returned as NaN).
 | 
			
		||||
 */
 | 
			
		||||
bool ds18b20_measure_and_read_multi(int pin, ds18b20_addr_t *addr_list, int addr_count, float *result_list);
 | 
			
		||||
 | 
			
		||||
/** Read the scratchpad data for a particular DS18B20 device.
 | 
			
		||||
 *
 | 
			
		||||
 *  This is not generally necessary to do directly.  It is done automatically
 | 
			
		||||
 *  as part of ds18b20_read_temperature().
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin     The GPIO pin connected to the DS18B20 device
 | 
			
		||||
 *  @param addr    The 64-bit address of the device to read.  This can be set
 | 
			
		||||
 *                 to ::DS18B20_ANY to read any device on the bus (but note
 | 
			
		||||
 *                 that this will only work if there is exactly one device
 | 
			
		||||
 *                 connected, or they will corrupt each others' transmissions)
 | 
			
		||||
 *  @param buffer  An 8-byte buffer to hold the read data.
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns `true` if the data was read successfully, or `false` on error.
 | 
			
		||||
 */
 | 
			
		||||
bool ds18b20_read_scratchpad(int pin, ds18b20_addr_t addr, uint8_t *buffer);
 | 
			
		||||
 | 
			
		||||
// The following are obsolete/deprecated APIs
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t id;
 | 
			
		||||
    float value;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,206 +1,207 @@
 | 
			
		|||
#include "onewire.h"
 | 
			
		||||
#include "string.h"
 | 
			
		||||
#include "task.h"
 | 
			
		||||
#include "esp/gpio.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];
 | 
			
		||||
#define ONEWIRE_SELECT_ROM 0x55
 | 
			
		||||
#define ONEWIRE_SKIP_ROM   0xcc
 | 
			
		||||
#define ONEWIRE_SEARCH     0xf0
 | 
			
		||||
 | 
			
		||||
void onewire_init(uint8_t pin)
 | 
			
		||||
{
 | 
			
		||||
  gpio_enable(pin, GPIO_INPUT);  
 | 
			
		||||
  onewire_reset_search(pin);
 | 
			
		||||
// Waits up to `max_wait` microseconds for the specified pin to go high.
 | 
			
		||||
// Returns true if successful, false if the bus never comes high (likely
 | 
			
		||||
// shorted).
 | 
			
		||||
static inline bool _onewire_wait_for_bus(int pin, int max_wait) {
 | 
			
		||||
    bool state;
 | 
			
		||||
    for (int i = 0; i < ((max_wait + 4) / 5); i++) {
 | 
			
		||||
        if (gpio_read(pin)) break;
 | 
			
		||||
        sdk_os_delay_us(5);
 | 
			
		||||
    }
 | 
			
		||||
    state = gpio_read(pin);
 | 
			
		||||
    // Wait an extra 1us to make sure the devices have an adequate recovery
 | 
			
		||||
    // time before we drive things low again.
 | 
			
		||||
    sdk_os_delay_us(1);
 | 
			
		||||
    return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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;
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
    if (!_onewire_wait_for_bus(pin, 250)) 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
 | 
			
		||||
    if (!_onewire_wait_for_bus(pin, 410)) return false;
 | 
			
		||||
 | 
			
		||||
    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 bool _onewire_write_bit(int pin, bool v) {
 | 
			
		||||
    if (!_onewire_wait_for_bus(pin, 10)) return false;
 | 
			
		||||
    if (v) {
 | 
			
		||||
        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);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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;
 | 
			
		||||
    if (!_onewire_wait_for_bus(pin, 10)) return -1;
 | 
			
		||||
    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;
 | 
			
		||||
bool 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) {
 | 
			
		||||
        if (!_onewire_write_bit(pin, (bitMask & v))) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
  }
 | 
			
		||||
bool onewire_write_bytes(int pin, const uint8_t *buf, size_t count) {
 | 
			
		||||
    size_t i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0 ; i < count ; i++) {
 | 
			
		||||
        if (!onewire_write(pin, buf[i])) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read a byte
 | 
			
		||||
//
 | 
			
		||||
uint8_t onewire_read(uint8_t pin) {
 | 
			
		||||
  uint8_t bitMask;
 | 
			
		||||
  uint8_t r = 0;
 | 
			
		||||
int onewire_read(int pin) {
 | 
			
		||||
    uint8_t bitMask;
 | 
			
		||||
    int r = 0;
 | 
			
		||||
    int bit;
 | 
			
		||||
 | 
			
		||||
  for (bitMask = 0x01; bitMask; bitMask <<= 1) {
 | 
			
		||||
  	if (onewire_read_bit(pin)) r |= bitMask;
 | 
			
		||||
  }
 | 
			
		||||
  return r;
 | 
			
		||||
    for (bitMask = 0x01; bitMask; bitMask <<= 1) {
 | 
			
		||||
        bit = _onewire_read_bit(pin);
 | 
			
		||||
        if (bit < 0) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        } else if (bit) {
 | 
			
		||||
            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);
 | 
			
		||||
bool onewire_read_bytes(int pin, uint8_t *buf, size_t count) {
 | 
			
		||||
    size_t i;
 | 
			
		||||
    int b;
 | 
			
		||||
 | 
			
		||||
    for (i = 0 ; i < count ; i++) {
 | 
			
		||||
        b = onewire_read(pin);
 | 
			
		||||
        if (b < 0) return false;
 | 
			
		||||
        buf[i] = b;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Do a ROM select
 | 
			
		||||
//
 | 
			
		||||
void onewire_select(uint8_t pin, const uint8_t rom[8])
 | 
			
		||||
{
 | 
			
		||||
bool onewire_select(int pin, onewire_addr_t addr) {
 | 
			
		||||
    uint8_t i;
 | 
			
		||||
 | 
			
		||||
    onewire_write(pin, 0x55, ONEWIRE_DEFAULT_POWER);           // Choose ROM
 | 
			
		||||
    if (!onewire_write(pin, ONEWIRE_SELECT_ROM)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < 8; i++) onewire_write(pin, rom[i], ONEWIRE_DEFAULT_POWER);
 | 
			
		||||
    for (i = 0; i < 8; i++) {
 | 
			
		||||
        if (!onewire_write(pin, addr & 0xff)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        addr >>= 8;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Do a ROM skip
 | 
			
		||||
//
 | 
			
		||||
void onewire_skip(uint8_t pin)
 | 
			
		||||
{
 | 
			
		||||
    onewire_write(pin, 0xCC, ONEWIRE_DEFAULT_POWER);           // Skip ROM
 | 
			
		||||
bool onewire_skip_rom(int pin) {
 | 
			
		||||
    return onewire_write(pin, ONEWIRE_SKIP_ROM);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void onewire_depower(uint8_t pin)
 | 
			
		||||
{
 | 
			
		||||
	noInterrupts();
 | 
			
		||||
	DIRECT_MODE_INPUT(pin);
 | 
			
		||||
	interrupts();
 | 
			
		||||
bool onewire_power(int pin) {
 | 
			
		||||
    // Make sure the bus is not being held low before driving it high, or we
 | 
			
		||||
    // may end up shorting ourselves out.
 | 
			
		||||
    if (!_onewire_wait_for_bus(pin, 10)) return false;
 | 
			
		||||
 | 
			
		||||
    gpio_enable(pin, GPIO_OUTPUT);
 | 
			
		||||
    gpio_write(pin, 1);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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_start(onewire_search_t *search) {
 | 
			
		||||
    // reset the search state
 | 
			
		||||
    memset(search, 0, sizeof(*search));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
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 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 +211,119 @@ 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) {
 | 
			
		||||
    //TODO: add more checking for read/write errors
 | 
			
		||||
    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;
 | 
			
		||||
    bool 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, ONEWIRE_SEARCH);
 | 
			
		||||
 | 
			
		||||
      // 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 < 0) || (cmp_id_bit < 0)) {
 | 
			
		||||
                // Read error
 | 
			
		||||
                break;
 | 
			
		||||
            } else 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) {
 | 
			
		||||
                        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) {
 | 
			
		||||
                    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 +362,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 +411,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 +428,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 +450,4 @@ uint16_t onewire_crc16(const uint8_t* input, uint16_t len, uint16_t crc)
 | 
			
		|||
      crc ^= cdata;
 | 
			
		||||
    }
 | 
			
		||||
    return crc;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,135 +4,232 @@
 | 
			
		|||
#include <espressif/esp_misc.h> // sdk_os_delay_us
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
 | 
			
		||||
// 1 for keeping the parasitic power on H
 | 
			
		||||
#define ONEWIRE_DEFAULT_POWER 1
 | 
			
		||||
/** @file onewire.h
 | 
			
		||||
 *
 | 
			
		||||
 *  Routines to access devices using the Dallas Semiconductor 1-Wire(tm)
 | 
			
		||||
 *  protocol.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// Maximum number of devices.
 | 
			
		||||
#define ONEWIRE_NUM 20
 | 
			
		||||
 | 
			
		||||
// You can exclude certain features from OneWire.  In theory, this
 | 
			
		||||
// might save some space.  In practice, the compiler automatically
 | 
			
		||||
// removes unused code (technically, the linker, using -fdata-sections
 | 
			
		||||
// and -ffunction-sections when compiling, and Wl,--gc-sections
 | 
			
		||||
// when linking), so most of these will not result in any code size
 | 
			
		||||
// reduction.  Well, unless you try to use the missing features
 | 
			
		||||
// and redesign your program to not need them!  ONEWIRE_CRC8_TABLE
 | 
			
		||||
// is the exception, because it selects a fast but large algorithm
 | 
			
		||||
// or a small but slow algorithm.
 | 
			
		||||
 | 
			
		||||
// Select the table-lookup method of computing the 8-bit CRC
 | 
			
		||||
// by setting this to 1.  The lookup table enlarges code size by
 | 
			
		||||
// about 250 bytes.  It does NOT consume RAM (but did in very
 | 
			
		||||
// old versions of OneWire).  If you disable this, a slower
 | 
			
		||||
// but very compact algorithm is used.
 | 
			
		||||
/** Select the table-lookup method of computing the 8-bit CRC
 | 
			
		||||
 *  by setting this to 1 during compilation.  The lookup table enlarges code
 | 
			
		||||
 *  size by about 250 bytes.  By default, a slower but very compact algorithm
 | 
			
		||||
 *  is used.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef ONEWIRE_CRC8_TABLE
 | 
			
		||||
#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
 | 
			
		||||
/** Type used to hold all 1-Wire device ROM addresses (64-bit) */
 | 
			
		||||
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)
 | 
			
		||||
/** Structure to contain the current state for onewire_search_next(), etc */
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t rom_no[8];
 | 
			
		||||
    uint8_t last_discrepancy;
 | 
			
		||||
    bool last_device_found;
 | 
			
		||||
} onewire_search_t;
 | 
			
		||||
 | 
			
		||||
void onewire_init(uint8_t pin);
 | 
			
		||||
/** ::ONEWIRE_NONE 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);
 | 
			
		||||
/** Perform a 1-Wire reset cycle.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin  The GPIO pin connected to the 1-Wire bus.
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns `true` if at least one device responds with a presence pulse,
 | 
			
		||||
 *           `false` if no devices were detected (or the bus is shorted, etc)
 | 
			
		||||
 */
 | 
			
		||||
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]);
 | 
			
		||||
/** Issue a 1-Wire rom select command to select a particular device.
 | 
			
		||||
 *
 | 
			
		||||
 *  It is necessary to call onewire_reset() before calling this function.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin   The GPIO pin connected to the 1-Wire bus.
 | 
			
		||||
 *  @param addr  The ROM address of the device to select
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns `true` if the "ROM select" command could be succesfully issued,
 | 
			
		||||
 *           `false` if there was an error.
 | 
			
		||||
 */
 | 
			
		||||
bool onewire_select(int pin, const onewire_addr_t addr);
 | 
			
		||||
 | 
			
		||||
// Issue a 1-Wire rom skip command, to address all on bus.
 | 
			
		||||
void onewire_skip(uint8_t pin);
 | 
			
		||||
/** Issue a 1-Wire "skip ROM" command to select *all* devices on the bus.
 | 
			
		||||
 *
 | 
			
		||||
 *  It is necessary to call onewire_reset() before calling this function.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin   The GPIO pin connected to the 1-Wire bus.
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns `true` if the "skip ROM" command could be succesfully issued,
 | 
			
		||||
 *           `false` if there was an error.
 | 
			
		||||
 */
 | 
			
		||||
bool 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 on the onewire bus.
 | 
			
		||||
 *
 | 
			
		||||
 *  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.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin   The GPIO pin connected to the 1-Wire bus.
 | 
			
		||||
 *  @param v     The byte value to write
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns `true` if successful, `false` on error.
 | 
			
		||||
 */
 | 
			
		||||
bool onewire_write(int pin, uint8_t v);
 | 
			
		||||
 | 
			
		||||
void onewire_write_bytes(uint8_t pin, const uint8_t *buf, uint16_t count, bool power);
 | 
			
		||||
/** Write multiple bytes on the 1-Wire bus.
 | 
			
		||||
 *
 | 
			
		||||
 *  See onewire_write() for more info.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin    The GPIO pin connected to the 1-Wire bus.
 | 
			
		||||
 *  @param buf    A pointer to the buffer of bytes to be written
 | 
			
		||||
 *  @param count  Number of bytes to write
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns `true` if all bytes written successfully, `false` on error.
 | 
			
		||||
 */
 | 
			
		||||
bool onewire_write_bytes(int pin, const uint8_t *buf, size_t count);
 | 
			
		||||
 | 
			
		||||
// Read a byte.
 | 
			
		||||
uint8_t onewire_read(uint8_t pin);
 | 
			
		||||
/** Read a byte from a 1-Wire device.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin    The GPIO pin connected to the 1-Wire bus.
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns the read byte on success, negative value on error.
 | 
			
		||||
 */
 | 
			
		||||
int onewire_read(int pin);
 | 
			
		||||
 | 
			
		||||
void onewire_read_bytes(uint8_t pin, uint8_t *buf, uint16_t count);
 | 
			
		||||
/** Read multiple bytes from a 1-Wire device.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin    The GPIO pin connected to the 1-Wire bus.
 | 
			
		||||
 *  @param buf    A pointer to the buffer to contain the read bytes
 | 
			
		||||
 *  @param count  Number of bytes to read
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns `true` on success, `false` on error.
 | 
			
		||||
 */
 | 
			
		||||
bool 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);
 | 
			
		||||
/** Actively drive the bus high to provide extra power for certain operations
 | 
			
		||||
 *  of parasitically-powered devices.
 | 
			
		||||
 *
 | 
			
		||||
 *  For parasitically-powered devices which need more power than can be
 | 
			
		||||
 *  provided via the normal pull-up resistor, it may be necessary for some
 | 
			
		||||
 *  operations to drive the bus actively high.  This function can be used to
 | 
			
		||||
 *  perform that operation.
 | 
			
		||||
 *
 | 
			
		||||
 *  The bus can be depowered once it is no longer needed by calling
 | 
			
		||||
 *  onewire_depower(), or it will be depowered automatically the next time
 | 
			
		||||
 *  onewire_reset() is called to start another command.
 | 
			
		||||
 *
 | 
			
		||||
 *  Note: Make sure the device(s) you are powering will not pull more current
 | 
			
		||||
 *  than the ESP8266 is able to supply via its GPIO pins (this is especially
 | 
			
		||||
 *  important when multiple devices are on the same bus and they are all
 | 
			
		||||
 *  performing a power-intensive operation at the same time (i.e. multiple
 | 
			
		||||
 *  DS18B20 sensors, which have all been given a "convert T" operation by using
 | 
			
		||||
 *  onewire_skip_rom())).
 | 
			
		||||
 *
 | 
			
		||||
 *  Note: This routine will check to make sure that the bus is already high
 | 
			
		||||
 *  before driving it, to make sure it doesn't attempt to drive it high while
 | 
			
		||||
 *  something else is pulling it low (which could cause a reset or damage the
 | 
			
		||||
 *  ESP8266).
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin    The GPIO pin connected to the 1-Wire bus.
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns `true` on success, `false` on error.
 | 
			
		||||
 */
 | 
			
		||||
bool onewire_power(int pin);
 | 
			
		||||
 | 
			
		||||
// Read a bit.
 | 
			
		||||
// uint8_t onewire_read_bit(uint8_t pin);
 | 
			
		||||
/** Stop forcing power onto the bus.
 | 
			
		||||
 *
 | 
			
		||||
 *  You only need to do this if 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.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param pin    The GPIO pin connected to the 1-Wire bus.
 | 
			
		||||
 */
 | 
			
		||||
void onewire_depower(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);
 | 
			
		||||
/** Clear the search state so that it will start from the beginning on the next
 | 
			
		||||
 *  call to onewire_search_next().
 | 
			
		||||
 *
 | 
			
		||||
 *  @param search  The onewire_search_t structure to reset.
 | 
			
		||||
 */
 | 
			
		||||
void onewire_search_start(onewire_search_t *search);
 | 
			
		||||
 | 
			
		||||
// Clear the search state so that if will start from the beginning again.
 | 
			
		||||
void onewire_reset_search(uint8_t pin);
 | 
			
		||||
/** Setup the search to search for devices with the specified "family code".
 | 
			
		||||
 *
 | 
			
		||||
 *  @param search       The onewire_search_t structure to update.
 | 
			
		||||
 *  @param family_code  The "family code" to search for.
 | 
			
		||||
 */
 | 
			
		||||
void onewire_search_prefix(onewire_search_t *search, uint8_t family_code);
 | 
			
		||||
 | 
			
		||||
// 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);
 | 
			
		||||
/** Search for the next device on the bus.
 | 
			
		||||
 *
 | 
			
		||||
 *  The order of returned device addresses is deterministic. You will always
 | 
			
		||||
 *  get the same devices in the same order.
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns the address of the next device on the bus, or ::ONEWIRE_NONE if
 | 
			
		||||
 *  there is no next address.  ::ONEWIRE_NONE might also 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.
 | 
			
		||||
 */
 | 
			
		||||
onewire_addr_t onewire_search_next(onewire_search_t *search, int pin);
 | 
			
		||||
 | 
			
		||||
// 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);
 | 
			
		||||
/** Compute a Dallas Semiconductor 8 bit CRC.
 | 
			
		||||
 *
 | 
			
		||||
 *  These are used in the ROM address and scratchpad registers to verify the
 | 
			
		||||
 *  transmitted data is correct.
 | 
			
		||||
 */
 | 
			
		||||
uint8_t onewire_crc8(const uint8_t *data, uint8_t len);
 | 
			
		||||
 | 
			
		||||
// 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);
 | 
			
		||||
/** Compute the 1-Wire CRC16 and compare it against the received CRC.
 | 
			
		||||
 *
 | 
			
		||||
 *  Example usage (reading a DS2408):
 | 
			
		||||
 *  @code
 | 
			
		||||
 *      // 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
 | 
			
		||||
 *      buf[2] = 0x00;    // MSB address
 | 
			
		||||
 *      onewire_write_bytes(pin, buf, 3);    // Write 3 cmd bytes
 | 
			
		||||
 *      onewire_read_bytes(pin, buf+3, 10);  // Read 6 data bytes, 2 0xFF, 2 CRC16
 | 
			
		||||
 *      if (!onewire_check_crc16(buf, 11, &buf[11])) {
 | 
			
		||||
 *          // TODO: Handle error.
 | 
			
		||||
 *      }     
 | 
			
		||||
 *  @endcode
 | 
			
		||||
 *           
 | 
			
		||||
 *  @param input         Array of bytes to checksum.
 | 
			
		||||
 *  @param len           Number of bytes in `input`
 | 
			
		||||
 *  @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_iv        The crc starting value (optional)
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns `true` if the CRC matches, `false` otherwise.
 | 
			
		||||
 */
 | 
			
		||||
bool onewire_check_crc16(const uint8_t* input, size_t len, const uint8_t* inverted_crc, uint16_t crc_iv);
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
//    uint8_t buf[13];
 | 
			
		||||
//    buf[0] = 0xF0;    // Read PIO Registers
 | 
			
		||||
//    buf[1] = 0x88;    // LSB address
 | 
			
		||||
//    buf[2] = 0x00;    // MSB address
 | 
			
		||||
//    WriteBytes(net, buf, 3);    // Write 3 cmd bytes
 | 
			
		||||
//    ReadBytes(net, buf+3, 10);  // Read 6 data bytes, 2 0xFF, 2 CRC16
 | 
			
		||||
//    if (!CheckCRC16(buf, 11, &buf[11])) {
 | 
			
		||||
//        // Handle error.
 | 
			
		||||
//    }     
 | 
			
		||||
//          
 | 
			
		||||
// @param input - Array of bytes to checksum.
 | 
			
		||||
// @param len - How many bytes to use.
 | 
			
		||||
// @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)
 | 
			
		||||
// @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);
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
// CRC computed here is *not* what you'll get from the 1-Wire network,
 | 
			
		||||
// for two reasons:
 | 
			
		||||
//   1) The CRC is transmitted bitwise inverted.
 | 
			
		||||
//   2) Depending on the endian-ness of your processor, the binary
 | 
			
		||||
//      representation of the two-byte return value may have a different
 | 
			
		||||
//      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)
 | 
			
		||||
// @return The CRC16, as defined by Dallas Semiconductor.
 | 
			
		||||
uint16_t onewire_crc16(const uint8_t* input, uint16_t len, uint16_t crc);
 | 
			
		||||
/** 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 CRC computed here is *not* what you'll get from the
 | 
			
		||||
 *  1-Wire network, for two reasons:
 | 
			
		||||
 *    1. The CRC is transmitted bitwise inverted.
 | 
			
		||||
 *    2. Depending on the endian-ness of your processor, the binary
 | 
			
		||||
 *       representation of the two-byte return value may have a different
 | 
			
		||||
 *       byte order than the two bytes you get from 1-Wire.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param input   Array of bytes to checksum.
 | 
			
		||||
 *  @param len     How many bytes are in `input`.
 | 
			
		||||
 *  @param crc_iv  The crc starting value (optional)
 | 
			
		||||
 *
 | 
			
		||||
 *  @returns the CRC16, as defined by Dallas Semiconductor.
 | 
			
		||||
 */
 | 
			
		||||
uint16_t onewire_crc16(const uint8_t* input, size_t len, uint16_t crc_iv);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue