Browse Source

Add support for multiple devices on single 1-Wire bus.

main
David Antliff 8 years ago
parent
commit
33a03fd31f
  1. 232
      main/ds18b20.c
  2. 91
      main/ds18b20_main.c
  3. 8
      main/ds18b20_static.h
  4. 610
      main/owb.c
  5. 23
      main/owb.h
  6. 8
      main/owb_static.h

232
main/ds18b20.c

@ -29,143 +29,145 @@
struct _DS18B20_Info struct _DS18B20_Info
{ {
bool init; bool init;
bool use_crc; bool use_crc;
OneWireBus * bus; OneWireBus * bus;
uint64_t rom_code; uint64_t rom_code;
}; };
static bool _is_init(const DS18B20_Info * ds18b20_info) static bool _is_init(const DS18B20_Info * ds18b20_info)
{ {
bool ok = false; bool ok = false;
if (ds18b20_info != NULL) if (ds18b20_info != NULL)
{ {
if (ds18b20_info->init) if (ds18b20_info->init)
{ {
// OK // OK
ok = true; ok = true;
} }
else else
{ {
ESP_LOGE(TAG, "ds18b20_info is not initialised"); ESP_LOGE(TAG, "ds18b20_info is not initialised");
} }
} }
else else
{ {
ESP_LOGE(TAG, "ds18b20_info is NULL"); ESP_LOGE(TAG, "ds18b20_info is NULL");
} }
return ok; return ok;
} }
DS18B20_Info * ds18b20_malloc(void) DS18B20_Info * ds18b20_malloc(void)
{ {
DS18B20_Info * ds18b20_info = malloc(sizeof(*ds18b20_info)); DS18B20_Info * ds18b20_info = malloc(sizeof(*ds18b20_info));
if (ds18b20_info != NULL) if (ds18b20_info != NULL)
{ {
memset(ds18b20_info, 0, sizeof(*ds18b20_info)); memset(ds18b20_info, 0, sizeof(*ds18b20_info));
ESP_LOGD(TAG, "malloc %p", ds18b20_info); ESP_LOGD(TAG, "malloc %p", ds18b20_info);
} }
else else
{ {
ESP_LOGE(TAG, "malloc failed"); ESP_LOGE(TAG, "malloc failed");
} }
return ds18b20_info; return ds18b20_info;
} }
void ds18b20_free(DS18B20_Info ** ds18b20_info) void ds18b20_free(DS18B20_Info ** ds18b20_info)
{ {
if (ds18b20_info != NULL && (*ds18b20_info != NULL)) if (ds18b20_info != NULL && (*ds18b20_info != NULL))
{ {
ESP_LOGD(TAG, "free %p", *ds18b20_info); ESP_LOGD(TAG, "free %p", *ds18b20_info);
free(*ds18b20_info); free(*ds18b20_info);
*ds18b20_info = NULL; *ds18b20_info = NULL;
} }
} }
void ds18b20_init(DS18B20_Info * ds18b20_info, OneWireBus * bus, uint64_t rom_code) void ds18b20_init(DS18B20_Info * ds18b20_info, OneWireBus * bus, uint64_t rom_code)
{ {
if (ds18b20_info != NULL) if (ds18b20_info != NULL)
{ {
ds18b20_info->bus = bus; ds18b20_info->bus = bus;
ds18b20_info->rom_code = rom_code; ds18b20_info->rom_code = rom_code;
ds18b20_info->use_crc = false; ds18b20_info->use_crc = false;
ds18b20_info->init = true; ds18b20_info->init = true;
} }
else else
{ {
ESP_LOGE(TAG, "ds18b20_info is NULL"); ESP_LOGE(TAG, "ds18b20_info is NULL");
} }
} }
void ds18b20_use_crc(DS18B20_Info * ds18b20_info, bool use_crc) void ds18b20_use_crc(DS18B20_Info * ds18b20_info, bool use_crc)
{ {
if (_is_init(ds18b20_info)) if (_is_init(ds18b20_info))
{ {
ds18b20_info->use_crc = use_crc; ds18b20_info->use_crc = use_crc;
ESP_LOGD(TAG, "use_crc %d", ds18b20_info->use_crc); ESP_LOGD(TAG, "use_crc %d", ds18b20_info->use_crc);
} }
} }
float ds18b20_get_temp(DS18B20_Info * ds18b20_info) float ds18b20_get_temp(DS18B20_Info * ds18b20_info)
{ {
float temp = 0.0f; float temp = 0.0f;
if (_is_init(ds18b20_info)) if (_is_init(ds18b20_info))
{ {
OneWireBus * bus = ds18b20_info->bus; OneWireBus * bus = ds18b20_info->bus;
if (owb_reset(bus)) if (owb_reset(bus))
{ {
//owb_write_byte(bus, OWB_ROM_SKIP); //owb_write_byte(bus, OWB_ROM_SKIP);
owb_write_byte(bus, OWB_ROM_MATCH); owb_write_byte(bus, OWB_ROM_MATCH);
owb_write_rom_code(bus, ds18b20_info->rom_code); owb_write_rom_code(bus, ds18b20_info->rom_code);
owb_write_byte(bus, DS18B20_FUNCTION_TEMP_CONVERT); owb_write_byte(bus, DS18B20_FUNCTION_TEMP_CONVERT);
vTaskDelay(750 / portTICK_PERIOD_MS); vTaskDelay(750 / portTICK_PERIOD_MS);
// reset // reset
owb_reset(bus); owb_reset(bus);
owb_write_byte(bus, OWB_ROM_SKIP); //owb_write_byte(bus, OWB_ROM_SKIP);
owb_write_byte(bus, DS18B20_FUNCTION_SCRATCHPAD_READ); owb_write_byte(bus, OWB_ROM_MATCH);
owb_write_rom_code(bus, ds18b20_info->rom_code);
uint8_t temp_LSB = 0; owb_write_byte(bus, DS18B20_FUNCTION_SCRATCHPAD_READ);
uint8_t temp_MSB = 0;
if (ds18b20_info->use_crc) uint8_t temp_LSB = 0;
{ uint8_t temp_MSB = 0;
// Without CRC: if (ds18b20_info->use_crc)
temp_LSB = owb_read_byte(bus); {
temp_MSB = owb_read_byte(bus); // Without CRC:
owb_reset(bus); // terminate early temp_LSB = owb_read_byte(bus);
} temp_MSB = owb_read_byte(bus);
else owb_reset(bus); // terminate early
{ }
// with CRC: else
uint8_t buffer[9]; {
owb_read_bytes(bus, buffer, 9); // with CRC:
uint8_t buffer[9];
temp_LSB = buffer[0]; owb_read_bytes(bus, buffer, 9);
temp_MSB = buffer[1];
temp_LSB = buffer[0];
uint8_t crc = 0; temp_MSB = buffer[1];
for (int i = 0; i < 9; ++i)
{ uint8_t crc = 0;
crc = owb_crc8(crc, buffer[i]); for (int i = 0; i < 9; ++i)
} {
ESP_LOGD(TAG, "crc 0x%02x", crc); crc = owb_crc8(crc, buffer[i]);
}
if (crc != 0) ESP_LOGD(TAG, "crc 0x%02x", crc);
{
ESP_LOGE(TAG, "CRC failed"); if (crc != 0)
temp_LSB = temp_MSB = 0; {
} ESP_LOGE(TAG, "CRC failed");
} temp_LSB = temp_MSB = 0;
}
ESP_LOGD(TAG, "temp_LSB 0x%02x, temp_MSB 0x%02x", temp_LSB, temp_MSB); }
temp = (float)(((temp_MSB << 8) + temp_LSB) >> 4);
} ESP_LOGD(TAG, "temp_LSB 0x%02x, temp_MSB 0x%02x", temp_LSB, temp_MSB);
else temp = (float)(((temp_MSB << 8) + temp_LSB) >> 4);
{ }
ESP_LOGE(TAG, "ds18b20 device not responding"); else
} {
} ESP_LOGE(TAG, "ds18b20 device not responding");
}
return temp; }
return temp;
} }

91
main/ds18b20_main.c

@ -4,6 +4,7 @@
#include "freertos/task.h" #include "freertos/task.h"
#include "esp_system.h" #include "esp_system.h"
// Uncomment to enable static (stack-based) allocation of instances and avoid malloc/free.
//#define USE_STATIC 1 //#define USE_STATIC 1
#ifdef USE_STATIC #ifdef USE_STATIC
@ -16,44 +17,90 @@
#define GPIO_DS18B20_0 (GPIO_NUM_4) #define GPIO_DS18B20_0 (GPIO_NUM_4)
#define MAX_DEVICES (8)
void app_main() void app_main()
{ {
// Create a 1-Wire bus // Create a 1-Wire bus
#ifdef USE_STATIC #ifdef USE_STATIC
OneWireBus_Static owb_static; // static allocation OneWireBus_Static owb_static; // static allocation
OneWireBus * owb = &owb_static; OneWireBus * owb = &owb_static;
#else #else
OneWireBus * owb = owb_malloc(); // heap allocation OneWireBus * owb = owb_malloc(); // heap allocation
#endif #endif
owb_init(owb, GPIO_DS18B20_0); owb_init(owb, GPIO_DS18B20_0);
owb_use_crc(owb, true); // enable CRC check for ROM code owb_use_crc(owb, true); // enable CRC check for ROM code
//owb_search(); // find all connected devices // find all connected devices
//OneWireBusROMCode rom_code = 0x1162e87ccee28; uint8_t device_rom_codes[8][MAX_DEVICES] = {0};
uint64_t rom_code = owb_read_rom(owb); int num_devices = 0;
printf("1-Wire ROM code 0x%08" PRIx64 "\n", rom_code); OneWireBus_SearchState search_state = {0};
bool found = owb_search_first(owb, &search_state);
while (found)
{
printf("Device %d found: ", num_devices);
for (int i = 7; i >= 0; i--)
{
device_rom_codes[num_devices][i] = search_state.rom_code[i];
printf("%02x", search_state.rom_code[i]);
}
printf("\n");
++num_devices;
found = owb_search_next(owb, &search_state);
}
//uint64_t rom_code = 0x0001162e87ccee28; // pink
//uint64_t rom_code = 0xf402162c6149ee28; // green
//uint64_t rom_code = 0x1502162ca5b2ee28; // orange
//uint64_t rom_code = owb_read_rom(owb);
//printf("1-Wire ROM code 0x%08" PRIx64 "\n", rom_code);
// Create a DS18B20 device on the 1-Wire bus // Create a DS18B20 device on the 1-Wire bus
#ifdef USE_STATIC #ifdef USE_STATIC
DS18B20_Info_Static ds18b20_info_static; // static allocation DS18B20_Info_Static ds18b20_info_static; // static allocation
DS18B20_Info * ds18b20_info = &ds18b20_info_static; DS18B20_Info * ds18b20_info = &ds18b20_info_static;
DS18B20_Info devices_static[MAX_DEVICES] = {0};
DS18B20_Info * devices[MAX_DEVICES] = {0};
for (int i = 0; i < MAX_DEVICES; ++i)
{
devices[i] = &(devices_static[i]);
}
#else #else
DS18B20_Info * ds18b20_info = ds18b20_malloc(); // heap allocation DS18B20_Info * ds18b20_info = ds18b20_malloc(); // heap allocation
DS18B20_Info * devices[MAX_DEVICES] = {0};
#endif #endif
ds18b20_init(ds18b20_info, owb, rom_code); // associate with bus and device for (int i = 0; i < num_devices; ++i)
//ds18b20_init_solo(ds18b20_info, owb); // only one device on bus {
ds18b20_use_crc(ds18b20_info, true); // enable CRC check for temperature readings #ifdef USE_STATIC
DS18B20_Info * ds18b20_info = devices[i];
#else
DS18B20_Info * ds18b20_info = ds18b20_malloc(); // heap allocation
devices[i] = ds18b20_info;
#endif
uint64_t rom_code = 0;
for (int j = 7; j >= 0; --j)
{
rom_code |= ((uint64_t)device_rom_codes[i][j] << (8 * j));
}
printf("1-Wire ROM code 0x%08" PRIx64 "\n", rom_code);
ds18b20_init(ds18b20_info, owb, rom_code); // associate with bus and device
//ds18b20_init_solo(ds18b20_info, owb); // only one device on bus
ds18b20_use_crc(ds18b20_info, true); // enable CRC check for temperature readings
}
while (1) while (1)
{ {
float temp = ds18b20_get_temp(ds18b20_info); for (int i = 0; i < num_devices; ++i)
printf("Temp %.1f degrees C\n", temp); {
float temp = ds18b20_get_temp(devices[i]);
printf("Temp %d: %.1f degrees C\n", i, temp);
}
vTaskDelay(1000 / portTICK_PERIOD_MS); vTaskDelay(1000 / portTICK_PERIOD_MS);
} }
for (int i = 10; i >= 0; i--) { for (int i = 10; i >= 0; i--) {
printf("Restarting in %d seconds...\n", i); printf("Restarting in %d seconds...\n", i);
@ -61,7 +108,7 @@ void app_main()
} }
ds18b20_free(&ds18b20_info); ds18b20_free(&ds18b20_info);
owb_free(&owb); owb_free(&owb);
printf("Restarting now.\n"); printf("Restarting now.\n");
fflush(stdout); fflush(stdout);

8
main/ds18b20_static.h

@ -14,10 +14,10 @@ extern "C" {
struct _DS18B20_Info struct _DS18B20_Info
{ {
bool init; bool init;
bool use_crc; bool use_crc;
OneWireBus * bus; OneWireBus * bus;
uint64_t rom_code; uint64_t rom_code;
}; };
typedef struct _DS18B20_Info DS18B20_Info_Static; typedef struct _DS18B20_Info DS18B20_Info_Static;

610
main/owb.c

@ -12,64 +12,54 @@
#define TAG "owb" #define TAG "owb"
struct _OneWireBus_Timing struct _OneWireBus_Timing
{ {
int A, B, C, D, E, F, G, H, I, J; int A, B, C, D, E, F, G, H, I, J;
}; };
// 1-Wire timing delays (standard) in ticks (quarter-microseconds). // 1-Wire timing delays (standard) in ticks (quarter-microseconds).
static const struct _OneWireBus_Timing _StandardTiming = { static const struct _OneWireBus_Timing _StandardTiming = {
6 * 4, 6 * 4,
64 * 4, 64 * 4,
60 * 4, 60 * 4,
10 * 4, 10 * 4,
9 * 4, 9 * 4,
55 * 4, 55 * 4,
0, // G 0, // G
480 * 4, // H 480 * 4, // H
70 * 4, // I 70 * 4, // I
410 * 4, // J 410 * 4, // J
}; };
//struct _OneWireBus
//{
// bool init;
// int gpio;
// const struct _OneWireBus_Timing * timing;
// bool use_crc;
//};
static void _tick_delay(int ticks) static void _tick_delay(int ticks)
{ {
// Each tick is 0.25 microseconds. // Each tick is 0.25 microseconds.
float time_us = ticks / 4.0; float time_us = ticks / 4.0;
ets_delay_us(time_us); ets_delay_us(time_us);
} }
static bool _is_init(const OneWireBus * bus) bool _is_init(const OneWireBus * bus)
{ {
bool ok = false; bool ok = false;
if (bus != NULL) if (bus != NULL)
{ {
if (bus->init) if (bus->init)
{ {
// OK // OK
ok = true; ok = true;
} }
else else
{ {
ESP_LOGE(TAG, "bus is not initialised"); ESP_LOGE(TAG, "bus is not initialised");
} }
} }
else else
{ {
ESP_LOGE(TAG, "bus is NULL"); ESP_LOGE(TAG, "bus is NULL");
} }
return ok; return ok;
} }
/** /**
* @brief Generate a 1-Wire reset. * @brief Generate a 1-Wire reset.
* @param[in] bus Initialised bus instance. * @param[in] bus Initialised bus instance.
@ -77,26 +67,26 @@ static bool _is_init(const OneWireBus * bus)
*/ */
static bool _reset(const OneWireBus * bus) static bool _reset(const OneWireBus * bus)
{ {
bool present = false; bool present = false;
if (_is_init(bus)) if (_is_init(bus))
{ {
gpio_set_direction(bus->gpio, GPIO_MODE_OUTPUT); gpio_set_direction(bus->gpio, GPIO_MODE_OUTPUT);
_tick_delay(bus->timing->G); _tick_delay(bus->timing->G);
gpio_set_level(bus->gpio, 0); // Drive DQ low gpio_set_level(bus->gpio, 0); // Drive DQ low
_tick_delay(bus->timing->H); _tick_delay(bus->timing->H);
gpio_set_level(bus->gpio, 1); // Release the bus gpio_set_level(bus->gpio, 1); // Release the bus
_tick_delay(bus->timing->I); _tick_delay(bus->timing->I);
gpio_set_direction(bus->gpio, GPIO_MODE_INPUT); gpio_set_direction(bus->gpio, GPIO_MODE_INPUT);
int level1 = gpio_get_level(bus->gpio); int level1 = gpio_get_level(bus->gpio);
_tick_delay(bus->timing->J); // Complete the reset sequence recovery _tick_delay(bus->timing->J); // Complete the reset sequence recovery
int level2 = gpio_get_level(bus->gpio); int level2 = gpio_get_level(bus->gpio);
present = (level1 == 0) && (level2 == 1); // Sample for presence pulse from slave present = (level1 == 0) && (level2 == 1); // Sample for presence pulse from slave
ESP_LOGD(TAG, "reset: level1 0x%x, level2 0x%x, present %d", level1, level2, present); ESP_LOGD(TAG, "reset: level1 0x%x, level2 0x%x, present %d", level1, level2, present);
} }
return present; return present;
} }
/** /**
@ -106,16 +96,16 @@ static bool _reset(const OneWireBus * bus)
*/ */
static void _write_bit(const OneWireBus * bus, int bit) static void _write_bit(const OneWireBus * bus, int bit)
{ {
if (_is_init(bus)) if (_is_init(bus))
{ {
int delay1 = bit ? bus->timing->A : bus->timing->C; int delay1 = bit ? bus->timing->A : bus->timing->C;
int delay2 = bit ? bus->timing->B : bus->timing->D; int delay2 = bit ? bus->timing->B : bus->timing->D;
gpio_set_direction(bus->gpio, GPIO_MODE_OUTPUT); gpio_set_direction(bus->gpio, GPIO_MODE_OUTPUT);
gpio_set_level(bus->gpio, 0); // Drive DQ low gpio_set_level(bus->gpio, 0); // Drive DQ low
_tick_delay(delay1); _tick_delay(delay1);
gpio_set_level(bus->gpio, 1); // Release the bus gpio_set_level(bus->gpio, 1); // Release the bus
_tick_delay(delay2); _tick_delay(delay2);
} }
} }
/** /**
@ -124,21 +114,21 @@ static void _write_bit(const OneWireBus * bus, int bit)
*/ */
static int _read_bit(const OneWireBus * bus) static int _read_bit(const OneWireBus * bus)
{ {
int result = 0; int result = 0;
if (_is_init(bus)) if (_is_init(bus))
{ {
gpio_set_direction(bus->gpio, GPIO_MODE_OUTPUT); gpio_set_direction(bus->gpio, GPIO_MODE_OUTPUT);
gpio_set_level(bus->gpio, 0); // Drive DQ low gpio_set_level(bus->gpio, 0); // Drive DQ low
_tick_delay(bus->timing->A); _tick_delay(bus->timing->A);
gpio_set_level(bus->gpio, 1); // Release the bus gpio_set_level(bus->gpio, 1); // Release the bus
_tick_delay(bus->timing->E); _tick_delay(bus->timing->E);
gpio_set_direction(bus->gpio, GPIO_MODE_INPUT); gpio_set_direction(bus->gpio, GPIO_MODE_INPUT);
int level = gpio_get_level(bus->gpio); int level = gpio_get_level(bus->gpio);
_tick_delay(bus->timing->F); // Complete the timeslot and 10us recovery _tick_delay(bus->timing->F); // Complete the timeslot and 10us recovery
result = level & 0x01; result = level & 0x01;
} }
return result; return result;
} }
/** /**
@ -148,15 +138,15 @@ static int _read_bit(const OneWireBus * bus)
*/ */
static void _write_byte(const OneWireBus * bus, uint8_t data) static void _write_byte(const OneWireBus * bus, uint8_t data)
{ {
if (_is_init(bus)) if (_is_init(bus))
{ {
ESP_LOGD(TAG, "write 0x%02x", data); ESP_LOGD(TAG, "write 0x%02x", data);
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
{ {
_write_bit(bus, data & 0x01); _write_bit(bus, data & 0x01);
data >>= 1; data >>= 1;
} }
} }
} }
/** /**
@ -166,20 +156,20 @@ static void _write_byte(const OneWireBus * bus, uint8_t data)
*/ */
static uint8_t _read_byte(const OneWireBus * bus) static uint8_t _read_byte(const OneWireBus * bus)
{ {
uint8_t result = 0; uint8_t result = 0;
if (_is_init(bus)) if (_is_init(bus))
{ {
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
{ {
result >>= 1; result >>= 1;
if (_read_bit(bus)) if (_read_bit(bus))
{ {
result |= 0x80; result |= 0x80;
} }
} }
ESP_LOGD(TAG, "read 0x%02x", result); ESP_LOGD(TAG, "read 0x%02x", result);
} }
return result; return result;
} }
/** /**
@ -191,11 +181,11 @@ static uint8_t _read_byte(const OneWireBus * bus)
*/ */
static uint8_t * _read_block(const OneWireBus * bus, uint8_t * buffer, unsigned int len) static uint8_t * _read_block(const OneWireBus * bus, uint8_t * buffer, unsigned int len)
{ {
for (int i = 0; i < len; ++i) for (int i = 0; i < len; ++i)
{ {
*buffer++ = _read_byte(bus); *buffer++ = _read_byte(bus);
} }
return buffer; return buffer;
} }
/** /**
@ -207,11 +197,11 @@ static uint8_t * _read_block(const OneWireBus * bus, uint8_t * buffer, unsigned
*/ */
static const uint8_t * _write_block(const OneWireBus * bus, const uint8_t * buffer, unsigned int len) static const uint8_t * _write_block(const OneWireBus * bus, const uint8_t * buffer, unsigned int len)
{ {
for (int i = 0; i < len; ++i) for (int i = 0; i < len; ++i)
{ {
_write_byte(bus, buffer[i]); _write_byte(bus, buffer[i]);
} }
return buffer; return buffer;
} }
/** /**
@ -222,27 +212,148 @@ static const uint8_t * _write_block(const OneWireBus * bus, const uint8_t * buff
*/ */
static uint8_t _calc_crc(uint8_t crc, uint8_t data) static uint8_t _calc_crc(uint8_t crc, uint8_t data)
{ {
// https://www.maximintegrated.com/en/app-notes/index.mvp/id/27 // https://www.maximintegrated.com/en/app-notes/index.mvp/id/27
static const uint8_t table[256] = { static const uint8_t table[256] = {
0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7, 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154, 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36, 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205, 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80, 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238, 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22, 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53
}; };
return table[crc ^ data]; return table[crc ^ data];
}
static bool _search(const OneWireBus * bus, OneWireBus_SearchState * state)
{
// Based on https://www.maximintegrated.com/en/app-notes/index.mvp/id/187
// initialize for search
int id_bit_number = 1;
int last_zero = 0;
int rom_byte_number = 0;
int id_bit = 0;
int cmp_id_bit = 0;
uint8_t rom_byte_mask = 1;
uint8_t search_direction = 0;
bool search_result = false;
uint8_t crc8 = 0;
if (_is_init(bus))
{
// if the last call was not the last one
if (!state->last_device_flag)
{
// 1-Wire reset
if (!_reset(bus))
{
// reset the search
state->last_discrepancy = 0;
state->last_device_flag = false;
state->last_family_discrepancy = 0;
return false;
}
// issue the search command
_write_byte(bus, OWB_ROM_SEARCH);
// loop to do the search
do
{
// read a bit and its complement
id_bit = _read_bit(bus);
cmp_id_bit = _read_bit(bus);
// 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 < state->last_discrepancy)
search_direction = ((state->rom_code[rom_byte_number] & rom_byte_mask) > 0);
else
// if equal to last pick 1, if not then pick 0
search_direction = (id_bit_number == state->last_discrepancy);
// 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)
state->last_family_discrepancy = last_zero;
}
}
// set or clear the bit in the ROM byte rom_byte_number
// with mask rom_byte_mask
if (search_direction == 1)
state->rom_code[rom_byte_number] |= rom_byte_mask;
else
state->rom_code[rom_byte_number] &= ~rom_byte_mask;
// serial number search direction write bit
_write_bit(bus, 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)
{
crc8 = _calc_crc(crc8, state->rom_code[rom_byte_number]); // accumulate the CRC
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) || (crc8 != 0)))
{
// search successful so set LastDiscrepancy,LastDeviceFlag,search_result
state->last_discrepancy = last_zero;
// check for last device
if (state->last_discrepancy == 0)
state->last_device_flag = true;
search_result = true;
}
}
// if no device found then reset counters so next 'search' will be like a first
if (!search_result || !state->rom_code[0])
{
state->last_discrepancy = 0;
state->last_device_flag = false;
state->last_family_discrepancy = 0;
search_result = false;
}
}
return search_result;
} }
@ -250,145 +361,176 @@ static uint8_t _calc_crc(uint8_t crc, uint8_t data)
OneWireBus * owb_malloc() OneWireBus * owb_malloc()
{ {
OneWireBus * bus = malloc(sizeof(*bus)); OneWireBus * bus = malloc(sizeof(*bus));
if (bus != NULL) if (bus != NULL)
{ {
memset(bus, 0, sizeof(*bus)); memset(bus, 0, sizeof(*bus));
ESP_LOGD(TAG, "malloc %p", bus); ESP_LOGD(TAG, "malloc %p", bus);
} }
else else
{ {
ESP_LOGE(TAG, "malloc failed"); ESP_LOGE(TAG, "malloc failed");
} }
return bus; return bus;
} }
void owb_free(OneWireBus ** bus) void owb_free(OneWireBus ** bus)
{ {
if (bus != NULL && (*bus != NULL)) if (bus != NULL && (*bus != NULL))
{ {
ESP_LOGD(TAG, "free %p", *bus); ESP_LOGD(TAG, "free %p", *bus);
free(*bus); free(*bus);
*bus = NULL; *bus = NULL;
} }
} }
void owb_init(OneWireBus * bus, int gpio) void owb_init(OneWireBus * bus, int gpio)
{ {
if (bus != NULL) if (bus != NULL)
{ {
bus->gpio = gpio; bus->gpio = gpio;
bus->timing = &_StandardTiming; bus->timing = &_StandardTiming;
bus->init = true; bus->init = true;
// platform specific: // platform specific:
gpio_pad_select_gpio(bus->gpio); gpio_pad_select_gpio(bus->gpio);
} }
else else
{ {
ESP_LOGE(TAG, "bus is NULL"); ESP_LOGE(TAG, "bus is NULL");
} }
} }
void owb_use_crc(OneWireBus * bus, bool use_crc) void owb_use_crc(OneWireBus * bus, bool use_crc)
{ {
if (_is_init(bus)) if (_is_init(bus))
{ {
bus->use_crc = use_crc; bus->use_crc = use_crc;
ESP_LOGD(TAG, "use_crc %d", bus->use_crc); ESP_LOGD(TAG, "use_crc %d", bus->use_crc);
} }
} }
int owb_rom_search(OneWireBus * bus) int owb_rom_search(OneWireBus * bus)
{ {
// TODO // TODO
return 0; return 0;
} }
uint64_t owb_read_rom(const OneWireBus * bus) uint64_t owb_read_rom(const OneWireBus * bus)
{ {
uint64_t rom_code = 0; uint64_t rom_code = 0;
if (_is_init(bus)) if (_is_init(bus))
{ {
if (_reset(bus)) if (_reset(bus))
{ {
uint8_t buffer[8] = { 0 }; uint8_t buffer[8] = { 0 };
_write_byte(bus, OWB_ROM_READ); _write_byte(bus, OWB_ROM_READ);
_read_block(bus, buffer, 8); _read_block(bus, buffer, 8);
// device provides LSB first // device provides LSB first
for (int i = 7; i >= 0; --i) for (int i = 7; i >= 0; --i)
{ {
// watch out for integer promotion // watch out for integer promotion
rom_code |= ((uint64_t)buffer[i] << (8 * i)); rom_code |= ((uint64_t)buffer[i] << (8 * i));
} }
if (bus->use_crc) if (bus->use_crc)
{ {
// check CRC // check CRC
uint8_t crc = 0; uint8_t crc = 0;
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
{ {
crc = _calc_crc(crc, buffer[i]); crc = _calc_crc(crc, buffer[i]);
} }
ESP_LOGD(TAG, "crc 0x%02x", crc); ESP_LOGD(TAG, "crc 0x%02x", crc);
if (crc != 0) if (crc != 0)
{ {
ESP_LOGE(TAG, "CRC failed"); ESP_LOGE(TAG, "CRC failed");
rom_code = 0; rom_code = 0;
} }
ESP_LOGD(TAG, "rom_code 0x%08" PRIx64, rom_code); ESP_LOGD(TAG, "rom_code 0x%08" PRIx64, rom_code);
} }
} }
else else
{ {
ESP_LOGE(TAG, "ds18b20 device not responding"); ESP_LOGE(TAG, "ds18b20 device not responding");
} }
} }
return rom_code; return rom_code;
} }
bool owb_reset(const OneWireBus * bus) bool owb_reset(const OneWireBus * bus)
{ {
return _reset(bus); return _reset(bus);
} }
void owb_write_byte(const OneWireBus * bus, uint8_t data) void owb_write_byte(const OneWireBus * bus, uint8_t data)
{ {
_write_byte(bus, data); _write_byte(bus, data);
} }
uint8_t owb_read_byte(const OneWireBus * bus) uint8_t owb_read_byte(const OneWireBus * bus)
{ {
return _read_byte(bus); return _read_byte(bus);
} }
uint8_t * owb_read_bytes(const OneWireBus * bus, uint8_t * buffer, unsigned int len) uint8_t * owb_read_bytes(const OneWireBus * bus, uint8_t * buffer, unsigned int len)
{ {
return _read_block(bus, buffer, len); return _read_block(bus, buffer, len);
} }
const uint8_t * owb_write_bytes(const OneWireBus * bus, const uint8_t * buffer, unsigned int len) const uint8_t * owb_write_bytes(const OneWireBus * bus, const uint8_t * buffer, unsigned int len)
{ {
return _write_block(bus, buffer, len); return _write_block(bus, buffer, len);
} }
void owb_write_rom_code(const OneWireBus * bus, uint64_t rom_code) void owb_write_rom_code(const OneWireBus * bus, uint64_t rom_code)
{ {
uint8_t buffer[sizeof(uint64_t)] = {0}; uint8_t buffer[sizeof(uint64_t)] = {0};
for (int i = 0; i < sizeof(buffer); ++i) for (int i = 0; i < sizeof(buffer); ++i)
{ {
// LSB first // LSB first
buffer[i] = rom_code & 0xFF; buffer[i] = rom_code & 0xFF;
rom_code >>= 8; rom_code >>= 8;
} }
_write_block(bus, buffer, sizeof(buffer)); _write_block(bus, buffer, sizeof(buffer));
} }
uint8_t owb_crc8(uint8_t crc, uint8_t data) uint8_t owb_crc8(uint8_t crc, uint8_t data)
{ {
return _calc_crc(crc, data); return _calc_crc(crc, data);
} }
bool owb_search_first(const OneWireBus * bus, OneWireBus_SearchState * state)
{
bool result = false;
if (state != NULL)
{
memset(state->rom_code, 0, sizeof(state->rom_code));
state->last_discrepancy = 0;
state->last_family_discrepancy = 0;
state->last_device_flag = false;
result = _search(bus, state);
}
else
{
ESP_LOGE(TAG, "state is NULL");
}
return result;
}
bool owb_search_next(const OneWireBus * bus, OneWireBus_SearchState * state)
{
bool result = false;
if (state != NULL)
{
result = _search(bus, state);
}
else
{
ESP_LOGE(TAG, "state is NULL");
}
return result;
}

23
main/owb.h

@ -2,6 +2,7 @@
#define ONE_WIRE_BUS_H #define ONE_WIRE_BUS_H
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -54,6 +55,9 @@ void owb_use_crc(OneWireBus * bus, bool use_crc);
*/ */
uint64_t owb_read_rom(const OneWireBus * bus); uint64_t owb_read_rom(const OneWireBus * bus);
// TODO
bool owb_verify_rom(const OneWireBus * bus, uint64_t rom_code);
/** /**
* @brief Reset the 1-Wire bus. * @brief Reset the 1-Wire bus.
* @param[in] bus Pointer to initialised bus instance. * @param[in] bus Pointer to initialised bus instance.
@ -100,13 +104,28 @@ const uint8_t * owb_write_bytes(const OneWireBus * bus, const uint8_t * buffer,
*/ */
void owb_write_rom_code(const OneWireBus * bus, uint64_t rom_code); void owb_write_rom_code(const OneWireBus * bus, uint64_t rom_code);
/** /**
* @brief 1-Wire 8-bit CRC lookup. * @brief 1-Wire 8-bit CRC lookup.
* @param[in] crc Starting CRC value. Pass in prior CRC to accumulate. * @param[in] crc Starting CRC value. Pass in prior CRC to accumulate.
* @param[in] data Byte to feed into CRC. * @param[in] data Byte to feed into CRC.
* @return Resultant CRC value. * @return Resultant CRC value.
*/ */
uint8_t owb_crc8(uint8_t crc, uint8_t data); uint8_t owb_crc8(uint8_t crc, uint8_t data);
// Search API
struct OneWireBus_SearchState
{
uint8_t rom_code[8];
int last_discrepancy;
int last_family_discrepancy;
int last_device_flag;
};
typedef struct OneWireBus_SearchState OneWireBus_SearchState;
bool owb_search_first(const OneWireBus * bus, OneWireBus_SearchState * state);
bool owb_search_next(const OneWireBus * bus, OneWireBus_SearchState * state);
#ifdef __cplusplus #ifdef __cplusplus

8
main/owb_static.h

@ -13,10 +13,10 @@ extern "C" {
struct _OneWireBus struct _OneWireBus
{ {
bool init; bool init;
int gpio; int gpio;
const struct _OneWireBus_Timing * timing; const struct _OneWireBus_Timing * timing;
bool use_crc; bool use_crc;
}; };
typedef struct _OneWireBus OneWireBus_Static; typedef struct _OneWireBus OneWireBus_Static;

Loading…
Cancel
Save