Multiple cleanups/tweaks for onewire driver

Use onewire_addr_t for onewire addresses
Move internal defines out of onewire.h
Remove global variables for search state
use taskENTER_CRITICAL instead of portDISABLE_INTERRUPTS
remove unnecessary onewire_init function
Remove unnecessary critical sections
Use GPIO_OUT_OPEN_DRAIN
reformat/style cleanup
This commit is contained in:
Alex Stewart 2016-03-14 21:59:39 -07:00
parent 02c35d8a71
commit a2b9d688ea
4 changed files with 304 additions and 359 deletions

View file

@ -12,8 +12,6 @@
// DS18B20 driver // DS18B20 driver
#include "ds18b20/ds18b20.h" #include "ds18b20/ds18b20.h"
// Onewire init
#include "onewire/onewire.h"
void print_temperature(void *pvParameters) void print_temperature(void *pvParameters)
{ {
@ -26,8 +24,6 @@ void print_temperature(void *pvParameters)
// Use GPIO 13 as one wire pin. // Use GPIO 13 as one wire pin.
uint8_t GPIO_FOR_ONE_WIRE = 13; uint8_t GPIO_FOR_ONE_WIRE = 13;
onewire_init(GPIO_FOR_ONE_WIRE);
while(1) { while(1) {
// Search all DS18B20, return its amount and feed 't' structure with result data. // Search all DS18B20, return its amount and feed 't' structure with result data.
amount = ds18b20_read_all(GPIO_FOR_ONE_WIRE, t); amount = ds18b20_read_all(GPIO_FOR_ONE_WIRE, t);

View file

@ -17,27 +17,28 @@
#define DS1820_CONVERT_T 0x44 #define DS1820_CONVERT_T 0x44
uint8_t ds18b20_read_all(uint8_t pin, ds_sensor_t *result) { uint8_t ds18b20_read_all(uint8_t pin, ds_sensor_t *result) {
onewire_addr_t addr;
uint8_t addr[8]; onewire_search_t search;
uint8_t sensor_id = 0; uint8_t sensor_id = 0;
onewire_reset_search(pin);
onewire_search_start(&search);
while(onewire_search(pin, addr)){ while ((addr = onewire_search_next(&search, pin)) != ONEWIRE_NONE) {
uint8_t crc = onewire_crc8(addr, 7); uint8_t crc = onewire_crc8((uint8_t *)&addr, 7);
if (crc != addr[7]){ if (crc != (addr >> 56)){
printf("CRC check failed: %02X %02X\n", addr[7], crc); printf("CRC check failed: %02X %02X\n", (unsigned)(addr >> 56), crc);
return 0; return 0;
} }
onewire_reset(pin); onewire_reset(pin);
onewire_select(pin, addr); onewire_select(pin, addr);
onewire_write(pin, DS1820_CONVERT_T, ONEWIRE_DEFAULT_POWER); onewire_write(pin, DS1820_CONVERT_T);
vTaskDelay(750 / portTICK_RATE_MS); vTaskDelay(750 / portTICK_RATE_MS);
onewire_reset(pin); onewire_reset(pin);
onewire_select(pin, addr); onewire_select(pin, addr);
onewire_write(pin, DS1820_READ_SCRATCHPAD, ONEWIRE_DEFAULT_POWER); onewire_write(pin, DS1820_READ_SCRATCHPAD);
uint8_t get[10]; uint8_t get[10];
@ -71,15 +72,14 @@ uint8_t ds18b20_read_all(uint8_t pin, ds_sensor_t *result) {
float ds18b20_read_single(uint8_t pin) { float ds18b20_read_single(uint8_t pin) {
onewire_reset(pin); onewire_reset(pin);
onewire_skip_rom(pin);
onewire_write(pin, DS1820_SKIP_ROM, ONEWIRE_DEFAULT_POWER); onewire_write(pin, DS1820_CONVERT_T);
onewire_write(pin, DS1820_CONVERT_T, ONEWIRE_DEFAULT_POWER);
vTaskDelay(750 / portTICK_RATE_MS); vTaskDelay(750 / portTICK_RATE_MS);
onewire_reset(pin); onewire_reset(pin);
onewire_write(pin, DS1820_SKIP_ROM, ONEWIRE_DEFAULT_POWER); onewire_skip_rom(pin);
onewire_write(pin, DS1820_READ_SCRATCHPAD, ONEWIRE_DEFAULT_POWER); onewire_write(pin, DS1820_READ_SCRATCHPAD);
uint8_t get[10]; uint8_t get[10];

View file

@ -1,206 +1,176 @@
#include "onewire.h" #include "onewire.h"
#include "string.h"
// global search state #include "task.h"
static unsigned char ROM_NO[ONEWIRE_NUM][8]; #include "esp/gpio.h"
static uint8_t LastDiscrepancy[ONEWIRE_NUM];
static uint8_t LastFamilyDiscrepancy[ONEWIRE_NUM];
static uint8_t LastDeviceFlag[ONEWIRE_NUM];
void onewire_init(uint8_t pin)
{
gpio_enable(pin, GPIO_INPUT);
onewire_reset_search(pin);
}
// Perform the onewire reset function. We will wait up to 250uS for // 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 // 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) bool onewire_reset(int pin) {
{ bool r;
uint8_t r; const int retries = 50;
uint8_t retries = 125;
noInterrupts(); gpio_enable(pin, GPIO_OUT_OPEN_DRAIN);
DIRECT_MODE_INPUT(pin); gpio_write(pin, 1);
interrupts(); // wait until the wire is high... just in case
// wait until the wire is high... just in case for (int i = 0; i < retries; i++) {
do { if (gpio_read(pin)) break;
if (--retries == 0) return 0; sdk_os_delay_us(5);
delayMicroseconds(2); }
} while ( !DIRECT_READ(pin)); if (!gpio_read(pin)) {
// Bus shorted?
return false;
}
noInterrupts(); gpio_write(pin, 0);
DIRECT_WRITE_LOW(pin); sdk_os_delay_us(480);
DIRECT_MODE_OUTPUT(pin); // drive output low
interrupts(); taskENTER_CRITICAL();
delayMicroseconds(480); gpio_write(pin, 1); // allow it to float
noInterrupts(); sdk_os_delay_us(70);
DIRECT_MODE_INPUT(pin); // allow it to float r = !gpio_read(pin);
delayMicroseconds(70); taskEXIT_CRITICAL();
r = !DIRECT_READ(pin);
interrupts(); // Wait for all devices to finish pulling the bus low before returning
delayMicroseconds(410); for (int i = 0; i < retries; i++) {
return r; if (gpio_read(pin)) break;
sdk_os_delay_us(5);
}
sdk_os_delay_us(2);
return r;
} }
// Write a bit. Port and bit is used to cut lookup time and provide static void onewire_write_bit(int pin, uint8_t v) {
// more certain timing. //TODO: should verify that the bus is high before starting
// if (v & 1) {
static void onewire_write_bit(uint8_t pin, uint8_t v) taskENTER_CRITICAL();
{ gpio_write(pin, 0); // drive output low
if (v & 1) { sdk_os_delay_us(10);
noInterrupts(); gpio_write(pin, 1); // allow output high
DIRECT_WRITE_LOW(pin); taskEXIT_CRITICAL();
DIRECT_MODE_OUTPUT(pin); // drive output low sdk_os_delay_us(55);
delayMicroseconds(10); } else {
DIRECT_WRITE_HIGH(pin); // drive output high taskENTER_CRITICAL();
interrupts(); gpio_write(pin, 0); // drive output low
delayMicroseconds(55); sdk_os_delay_us(65);
} else { gpio_write(pin, 1); // allow output high
noInterrupts(); taskEXIT_CRITICAL();
DIRECT_WRITE_LOW(pin); }
DIRECT_MODE_OUTPUT(pin); // drive output low sdk_os_delay_us(1);
delayMicroseconds(65);
DIRECT_WRITE_HIGH(pin); // drive output high
interrupts();
delayMicroseconds(5);
}
} }
// Read a bit. Port and bit is used to cut lookup time and provide static int onewire_read_bit(int pin) {
// more certain timing. int r;
//
static uint8_t onewire_read_bit(uint8_t pin)
{
uint8_t r;
noInterrupts(); //TODO: should verify that the bus is high before starting
DIRECT_MODE_OUTPUT(pin); taskENTER_CRITICAL();
DIRECT_WRITE_LOW(pin); gpio_write(pin, 0);
delayMicroseconds(3); sdk_os_delay_us(2);
DIRECT_MODE_INPUT(pin); // let pin float, pull up will raise gpio_write(pin, 1); // let pin float, pull up will raise
delayMicroseconds(10); sdk_os_delay_us(11);
r = DIRECT_READ(pin); r = gpio_read(pin); // Must sample within 15us of start
interrupts(); taskEXIT_CRITICAL();
delayMicroseconds(53); sdk_os_delay_us(48);
return r;
return r;
} }
// Write a byte. The writing code uses the active drivers to raise the // Write a byte. The writing code uses open-drain mode and expects the pullup
// pin high, if you need power after the write (e.g. DS18S20 in // resistor to pull the line high when not driven low. If you need strong
// parasite power mode) then set 'power' to 1, otherwise the pin will // power after the write (e.g. DS18B20 in parasite power mode) then call
// go tri-state at the end of the write to avoid heating in a short or // onewire_power() after this is complete to actively drive the line high.
// other mishap.
// //
void onewire_write(uint8_t pin, uint8_t v, uint8_t power /* = 0 */) { void onewire_write(int pin, uint8_t v) {
uint8_t bitMask; uint8_t bitMask;
for (bitMask = 0x01; bitMask; bitMask <<= 1) { for (bitMask = 0x01; bitMask; bitMask <<= 1) {
onewire_write_bit(pin, (bitMask & v)?1:0); onewire_write_bit(pin, (bitMask & v)?1:0);
} }
if ( !power) {
noInterrupts();
DIRECT_MODE_INPUT(pin);
DIRECT_WRITE_LOW(pin);
interrupts();
}
} }
void onewire_write_bytes(uint8_t pin, const uint8_t *buf, uint16_t count, bool power /* = 0 */) { void onewire_write_bytes(int pin, const uint8_t *buf, size_t count) {
uint16_t i; size_t i;
for (i = 0 ; i < count ; i++)
onewire_write(pin, buf[i], ONEWIRE_DEFAULT_POWER); for (i = 0 ; i < count ; i++) {
if (!power) { onewire_write(pin, buf[i]);
noInterrupts(); }
DIRECT_MODE_INPUT(pin);
DIRECT_WRITE_LOW(pin);
interrupts();
}
} }
// Read a byte // Read a byte
// //
uint8_t onewire_read(uint8_t pin) { uint8_t onewire_read(int pin) {
uint8_t bitMask; uint8_t bitMask;
uint8_t r = 0; uint8_t r = 0;
for (bitMask = 0x01; bitMask; bitMask <<= 1) { for (bitMask = 0x01; bitMask; bitMask <<= 1) {
if (onewire_read_bit(pin)) r |= bitMask; if (onewire_read_bit(pin)) r |= bitMask;
} }
return r; return r;
} }
void onewire_read_bytes(uint8_t pin, uint8_t *buf, uint16_t count) { void onewire_read_bytes(int pin, uint8_t *buf, size_t count) {
uint16_t i; size_t i;
for (i = 0 ; i < count ; i++)
buf[i] = onewire_read(pin); for (i = 0 ; i < count ; i++) {
buf[i] = onewire_read(pin);
}
} }
// Do a ROM select // Do a ROM select
// //
void onewire_select(uint8_t pin, const uint8_t rom[8]) void onewire_select(int pin, onewire_addr_t rom) {
{
uint8_t i; uint8_t i;
onewire_write(pin, 0x55, ONEWIRE_DEFAULT_POWER); // Choose ROM onewire_write(pin, 0x55); // Choose ROM
for (i = 0; i < 8; i++) onewire_write(pin, rom[i], ONEWIRE_DEFAULT_POWER); for (i = 0; i < 8; i++) {
onewire_write(pin, rom & 0xff);
rom >>= 8;
}
} }
// Do a ROM skip // Do a ROM skip
// //
void onewire_skip(uint8_t pin) void onewire_skip_rom(int pin) {
{ onewire_write(pin, 0xCC); // Skip ROM
onewire_write(pin, 0xCC, ONEWIRE_DEFAULT_POWER); // Skip ROM
} }
void onewire_depower(uint8_t pin) void onewire_power(int pin) {
{ gpio_enable(pin, GPIO_OUTPUT);
noInterrupts(); gpio_write(pin, 1);
DIRECT_MODE_INPUT(pin);
interrupts();
} }
// You need to use this function to start a search again from the beginning. void onewire_depower(int pin) {
// You do not need to do it for the first search, though you could. gpio_enable(pin, GPIO_OUT_OPEN_DRAIN);
// }
void onewire_reset_search(uint8_t pin)
{ void onewire_search_start(onewire_search_t *search) {
// reset the search state // reset the search state
LastDiscrepancy[pin] = 0; memset(search, 0, sizeof(*search));
LastDeviceFlag[pin] = 0;
LastFamilyDiscrepancy[pin] = 0;
int i;
for(i = 7; ; i--) {
ROM_NO[pin][i] = 0;
if ( i == 0) break;
}
} }
// Setup the search to find the device type 'family_code' on the next call // Setup the search to find the device type 'family_code' on the next call
// to search(*newAddr) if it is present. // to search(*newAddr) if it is present.
// //
void onewire_target_search(uint8_t pin, uint8_t family_code) void onewire_search_prefix(onewire_search_t *search, uint8_t family_code) {
{ uint8_t i;
// set the search state to find SearchFamily type devices
ROM_NO[pin][0] = family_code; search->rom_no[0] = family_code;
uint8_t i; for (i = 1; i < 8; i++) {
for (i = 1; i < 8; i++) search->rom_no[i] = 0;
ROM_NO[pin][i] = 0; }
LastDiscrepancy[pin] = 64; search->last_discrepancy = 64;
LastFamilyDiscrepancy[pin] = 0; search->last_device_found = false;
LastDeviceFlag[pin] = 0;
} }
// Perform a search. If this function returns a '1' then it has // Perform a search. If the next device has been successfully enumerated, its
// enumerated the next device and you may retrieve the ROM from the // ROM address will be returned. If there are no devices, no further
// OneWire::address variable. If there are no devices, no further
// devices, or something horrible happens in the middle of the // devices, or something horrible happens in the middle of the
// enumeration then a 0 is returned. If a new device is found then // enumeration then ONEWIRE_NONE is returned. Use OneWire::reset_search() to
// its address is copied to newAddr. Use OneWire::reset_search() to
// start over. // start over.
// //
// --- Replaced by the one from the Dallas Semiconductor web site --- // --- Replaced by the one from the Dallas Semiconductor web site ---
@ -210,129 +180,115 @@ void onewire_target_search(uint8_t pin, uint8_t family_code)
// Return 1 : device found, ROM number in ROM_NO buffer // Return 1 : device found, ROM number in ROM_NO buffer
// 0 : device not found, end of search // 0 : device not found, end of search
// //
uint8_t onewire_search(uint8_t pin, uint8_t *newAddr) onewire_addr_t onewire_search_next(onewire_search_t *search, int pin) {
{ uint8_t id_bit_number;
uint8_t id_bit_number; uint8_t last_zero, search_result;
uint8_t last_zero, rom_byte_number, search_result; int rom_byte_number;
uint8_t id_bit, cmp_id_bit; uint8_t id_bit, cmp_id_bit;
onewire_addr_t addr;
unsigned char rom_byte_mask, search_direction; unsigned char rom_byte_mask, search_direction;
// initialize for search // initialize for search
id_bit_number = 1; id_bit_number = 1;
last_zero = 0; last_zero = 0;
rom_byte_number = 0; rom_byte_number = 0;
rom_byte_mask = 1; rom_byte_mask = 1;
search_result = 0; search_result = 0;
// if the last call was not the last one // if the last call was not the last one
if (!LastDeviceFlag[pin]) if (!search->last_device_found) {
{ // 1-Wire reset
// 1-Wire reset if (!onewire_reset(pin)) {
if (!onewire_reset(pin)) // reset the search
{ search->last_discrepancy = 0;
// reset the search search->last_device_found = false;
LastDiscrepancy[pin] = 0; return ONEWIRE_NONE;
LastDeviceFlag[pin] = 0; }
LastFamilyDiscrepancy[pin] = 0;
return 0;
}
// issue the search command // issue the search command
onewire_write(pin, 0xF0, ONEWIRE_DEFAULT_POWER); onewire_write(pin, 0xF0);
// loop to do the search // loop to do the search
do do {
{ // read a bit and its complement
// read a bit and its complement id_bit = onewire_read_bit(pin);
id_bit = onewire_read_bit(pin); cmp_id_bit = onewire_read_bit(pin);
cmp_id_bit = onewire_read_bit(pin);
// check for no devices on 1-wire // check for no devices on 1-wire
if ((id_bit == 1) && (cmp_id_bit == 1)) if ((id_bit == 1) && (cmp_id_bit == 1)) {
break; break;
else } else {
{ // all devices coupled have 0 or 1
// all devices coupled have 0 or 1 if (id_bit != cmp_id_bit) {
if (id_bit != cmp_id_bit) search_direction = id_bit; // bit write value for search
search_direction = id_bit; // bit write value for search } else {
else // if this discrepancy if before the Last Discrepancy
{ // on a previous next then pick the same as last time
// if this discrepancy if before the Last Discrepancy if (id_bit_number < search->last_discrepancy) {
// on a previous next then pick the same as last time search_direction = ((search->rom_no[rom_byte_number] & rom_byte_mask) > 0);
if (id_bit_number < LastDiscrepancy[pin]) } else {
search_direction = ((ROM_NO[pin][rom_byte_number] & rom_byte_mask) > 0); // if equal to last pick 1, if not then pick 0
else search_direction = (id_bit_number == search->last_discrepancy);
// if equal to last pick 1, if not then pick 0 }
search_direction = (id_bit_number == LastDiscrepancy[pin]);
// if 0 was picked then record its position in LastZero // if 0 was picked then record its position in LastZero
if (search_direction == 0) if (search_direction == 0) {
{ last_zero = id_bit_number;
last_zero = id_bit_number; }
}
// check for Last discrepancy in family // set or clear the bit in the ROM byte rom_byte_number
if (last_zero < 9) // with mask rom_byte_mask
LastFamilyDiscrepancy[pin] = last_zero; if (search_direction == 1) {
} search->rom_no[rom_byte_number] |= rom_byte_mask;
} else {
search->rom_no[rom_byte_number] &= ~rom_byte_mask;
}
// serial number search direction write bit
onewire_write_bit(pin, search_direction);
// increment the byte counter id_bit_number
// and shift the mask rom_byte_mask
id_bit_number++;
rom_byte_mask <<= 1;
// if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
if (rom_byte_mask == 0) {
rom_byte_number++;
rom_byte_mask = 1;
}
}
} while (rom_byte_number < 8); // loop until through all ROM bytes 0-7
// if the search was successful then
if (!(id_bit_number < 65)) {
// search successful so set last_discrepancy,last_device_found,search_result
search->last_discrepancy = last_zero;
// check for last device
if (search->last_discrepancy == 0) {
search->last_device_found = true;
} }
// set or clear the bit in the ROM byte rom_byte_number search_result = 1;
// 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;
// serial number search direction write bit // if no device found then reset counters so next 'search' will be like a first
onewire_write_bit(pin, search_direction); if (!search_result || !search->rom_no[0]) {
search->last_discrepancy = 0;
// increment the byte counter id_bit_number search->last_device_found = false;
// and shift the mask rom_byte_mask return ONEWIRE_NONE;
id_bit_number++; } else {
rom_byte_mask <<= 1; addr = 0;
for (rom_byte_number = 7; rom_byte_number >= 0; rom_byte_number--) {
// if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask addr = (addr << 8) | search->rom_no[rom_byte_number];
if (rom_byte_mask == 0) }
{ //printf("Ok I found something at %08x%08x...\n", (uint32_t)(addr >> 32), (uint32_t)addr);
rom_byte_number++; }
rom_byte_mask = 1; return addr;
}
}
}
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;
} }
// The 1-Wire CRC scheme is described in Maxim Application Note 27: // The 1-Wire CRC scheme is described in Maxim Application Note 27:
@ -371,41 +327,38 @@ static const uint8_t dscrc_table[] = {
// compared to all those delayMicrosecond() calls. But I got // compared to all those delayMicrosecond() calls. But I got
// confused, so I use this table from the examples.) // confused, so I use this table from the examples.)
// //
uint8_t onewire_crc8(const uint8_t *addr, uint8_t len) uint8_t onewire_crc8(const uint8_t *data, uint8_t len) {
{ uint8_t crc = 0;
uint8_t crc = 0;
while (len--) { while (len--) {
crc = pgm_read_byte(dscrc_table + (crc ^ *addr++)); crc = pgm_read_byte(dscrc_table + (crc ^ *data++));
} }
return crc; return crc;
} }
#else #else
// //
// Compute a Dallas Semiconductor 8 bit CRC directly. // Compute a Dallas Semiconductor 8 bit CRC directly.
// this is much slower, but much smaller, than the lookup table. // this is much slower, but much smaller, than the lookup table.
// //
uint8_t onewire_crc8(const uint8_t *addr, uint8_t len) uint8_t onewire_crc8(const uint8_t *data, uint8_t len) {
{ uint8_t crc = 0;
uint8_t crc = 0;
while (len--) {
while (len--) { uint8_t inbyte = *data++;
uint8_t inbyte = *addr++; for (int i = 8; i; i--) {
uint8_t i; uint8_t mix = (crc ^ inbyte) & 0x01;
for (i = 8; i; i--) { crc >>= 1;
uint8_t mix = (crc ^ inbyte) & 0x01; if (mix) crc ^= 0x8C;
crc >>= 1; inbyte >>= 1;
if (mix) crc ^= 0x8C; }
inbyte >>= 1; }
} return crc;
}
return crc;
} }
#endif #endif
// Compute the 1-Wire CRC16 and compare it against the received CRC. // Compute the 1-Wire CRC16 and compare it against the received CRC.
// Example usage (reading a DS2408): // 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]; // uint8_t buf[13];
// buf[0] = 0xF0; // Read PIO Registers // buf[0] = 0xF0; // Read PIO Registers
// buf[1] = 0x88; // LSB address // buf[1] = 0x88; // LSB address
@ -423,9 +376,8 @@ uint8_t onewire_crc8(const uint8_t *addr, uint8_t len)
// *not* at a 16-bit integer. // *not* at a 16-bit integer.
// @param crc - The crc starting value (optional) // @param crc - The crc starting value (optional)
// @return 1, iff the CRC matches. // @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) 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);
crc = ~onewire_crc16(input, len, crc);
return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1]; return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1];
} }
@ -441,8 +393,8 @@ bool onewire_check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inve
// @param len - How many bytes to use. // @param len - How many bytes to use.
// @param crc - The crc starting value (optional) // @param crc - The crc starting value (optional)
// @return The CRC16, as defined by Dallas Semiconductor. // @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] = static const uint8_t oddparity[16] =
{ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
@ -463,4 +415,4 @@ uint16_t onewire_crc16(const uint8_t* input, uint16_t len, uint16_t crc)
crc ^= cdata; crc ^= cdata;
} }
return crc; return crc;
} }

View file

@ -29,75 +29,72 @@
#define ONEWIRE_CRC8_TABLE 0 #define ONEWIRE_CRC8_TABLE 0
#endif #endif
// Platform specific I/O definitions typedef uint64_t onewire_addr_t;
#define noInterrupts portDISABLE_INTERRUPTS
#define interrupts portENABLE_INTERRUPTS
#define delayMicroseconds sdk_os_delay_us
#define DIRECT_READ(pin) gpio_read(pin) typedef struct {
#define DIRECT_MODE_INPUT(pin) gpio_enable(pin, GPIO_INPUT) uint8_t rom_no[8];
#define DIRECT_MODE_OUTPUT(pin) gpio_enable(pin, GPIO_OUTPUT) uint8_t last_discrepancy;
#define DIRECT_WRITE_LOW(pin) gpio_write(pin, 0) bool last_device_found;
#define DIRECT_WRITE_HIGH(pin) gpio_write(pin, 1) } onewire_search_t;
void onewire_init(uint8_t pin); // The following is an invalid ROM address that will never occur in a device
// (CRC mismatch), and so can be useful as an indicator for "no-such-device",
// etc.
#define ONEWIRE_NONE ((onewire_addr_t)(0xffffffffffffffffLL))
// Perform a 1-Wire reset cycle. Returns 1 if a device responds // 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 // with a presence pulse. Returns 0 if there is no device or the
// bus is shorted or otherwise held low for more than 250uS // bus is shorted or otherwise held low for more than 250uS
uint8_t onewire_reset(uint8_t pin); bool onewire_reset(int pin);
// Issue a 1-Wire rom select command, you do the reset first. // Issue a 1-Wire rom select command, you do the reset first.
void onewire_select(uint8_t pin, const uint8_t rom[8]); void onewire_select(int pin, const onewire_addr_t rom);
// Issue a 1-Wire rom skip command, to address all on bus. // Issue a 1-Wire rom skip command, to address all on bus.
void onewire_skip(uint8_t pin); void onewire_skip_rom(int pin);
// Write a byte. If 'power' is one then the wire is held high at // Write a byte. The writing code uses open-drain mode and expects the pullup
// the end for parasitically powered devices. You are responsible // resistor to pull the line high when not driven low. If you need strong
// for eventually depowering it by calling depower() or doing // power after the write (e.g. DS18B20 in parasite power mode) then call
// another read or write. // onewire_power() after this is complete to actively drive the line high.
void onewire_write(uint8_t pin, uint8_t v, uint8_t power); void onewire_write(int pin, uint8_t v);
void onewire_write_bytes(uint8_t pin, const uint8_t *buf, uint16_t count, bool power); void onewire_write_bytes(int pin, const uint8_t *buf, size_t count);
// Read a byte. // Read a byte.
uint8_t onewire_read(uint8_t pin); uint8_t onewire_read(int pin);
void onewire_read_bytes(uint8_t pin, uint8_t *buf, uint16_t count); void onewire_read_bytes(int pin, uint8_t *buf, size_t count);
// Write a bit. The bus is always left powered at the end, see // Actively drive the bus high to provide extra power for certain operations of
// note in write() about that. // parasitically-powered devices.
// void onewire_write_bit(uint8_t pin, uint8_t v); void 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 // 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 // you previously called onewire_power() to drive the bus high and now want to
// and aren't about to do another read or write. You would rather // allow it to float instead. Note that onewire_reset() will also
// not leave this powered if you don't have to, just in case // automatically depower the bus first, so you do not need to call this first
// someone shorts your bus. // if you just want to start a new operation.
void onewire_depower(uint8_t pin); void onewire_depower(int pin);
// Clear the search state so that if will start from the beginning again. // Clear the search state so that if will start from the beginning again.
void onewire_reset_search(uint8_t pin); void onewire_search_start(onewire_search_t *search);
// Setup the search to find the device type 'family_code' on the next call // Setup the search to find the device type 'family_code' on the next call
// to search(*newAddr) if it is present. // to search(*newAddr) if it is present.
void onewire_target_search(uint8_t pin, uint8_t family_code); void onewire_search_prefix(onewire_search_t *search, uint8_t family_code);
// Look for the next device. Returns 1 if a new address has been // Look for the next device. Returns the address of the next device on the bus,
// returned. A zero might mean that the bus is shorted, there are // or ONEWIRE_NONE if there is no next address. ONEWIRE_NONE might mean that
// no devices, or you have already retrieved all of them. It // the bus is shorted, there are no devices, or you have already retrieved all
// might be a good idea to check the CRC to make sure you didn't // 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 // get garbage. The order is deterministic. You will always get the same
// the same devices in the same order. // devices in the same order.
uint8_t onewire_search(uint8_t pin, uint8_t *newAddr); onewire_addr_t onewire_search_next(onewire_search_t *search, int pin);
// Compute a Dallas Semiconductor 8 bit CRC, these are used in the // Compute a Dallas Semiconductor 8 bit CRC, these are used in the
// ROM and scratchpad registers. // ROM and scratchpad registers.
uint8_t onewire_crc8(const uint8_t *addr, uint8_t len); uint8_t onewire_crc8(const uint8_t *data, uint8_t len);
// Compute the 1-Wire CRC16 and compare it against the received CRC. // Compute the 1-Wire CRC16 and compare it against the received CRC.
// Example usage (reading a DS2408): // Example usage (reading a DS2408):
@ -117,9 +114,9 @@ uint8_t onewire_crc8(const uint8_t *addr, uint8_t len);
// @param inverted_crc - The two CRC16 bytes in the received data. // @param inverted_crc - The two CRC16 bytes in the received data.
// This should just point into the received data, // This should just point into the received data,
// *not* at a 16-bit integer. // *not* at a 16-bit integer.
// @param crc - The crc starting value (optional) // @param crc_iv - The crc starting value (optional)
// @return True, iff the CRC matches. // @return True, iff the CRC matches.
bool onewire_check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc); bool onewire_check_crc16(const uint8_t* input, size_t len, const uint8_t* inverted_crc, uint16_t crc_iv);
// Compute a Dallas Semiconductor 16 bit CRC. This is required to check // 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 // the integrity of data received from many 1-Wire devices. Note that the
@ -131,8 +128,8 @@ bool onewire_check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inve
// byte order than the two bytes you get from 1-Wire. // byte order than the two bytes you get from 1-Wire.
// @param input - Array of bytes to checksum. // @param input - Array of bytes to checksum.
// @param len - How many bytes to use. // @param len - How many bytes to use.
// @param crc - The crc starting value (optional) // @param crc_iv - The crc starting value (optional)
// @return The CRC16, as defined by Dallas Semiconductor. // @return The CRC16, as defined by Dallas Semiconductor.
uint16_t onewire_crc16(const uint8_t* input, uint16_t len, uint16_t crc); uint16_t onewire_crc16(const uint8_t* input, size_t len, uint16_t crc_iv);
#endif #endif