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:
parent
02c35d8a71
commit
a2b9d688ea
4 changed files with 304 additions and 359 deletions
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
|
|
||||||
while(onewire_search(pin, addr)){
|
onewire_search_start(&search);
|
||||||
uint8_t crc = onewire_crc8(addr, 7);
|
|
||||||
if (crc != addr[7]){
|
while ((addr = onewire_search_next(&search, pin)) != ONEWIRE_NONE) {
|
||||||
printf("CRC check failed: %02X %02X\n", addr[7], crc);
|
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;
|
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];
|
||||||
|
|
||||||
|
|
|
@ -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 = *addr++;
|
uint8_t inbyte = *data++;
|
||||||
uint8_t i;
|
for (int i = 8; i; i--) {
|
||||||
for (i = 8; i; i--) {
|
uint8_t mix = (crc ^ inbyte) & 0x01;
|
||||||
uint8_t mix = (crc ^ inbyte) & 0x01;
|
crc >>= 1;
|
||||||
crc >>= 1;
|
if (mix) crc ^= 0x8C;
|
||||||
if (mix) crc ^= 0x8C;
|
inbyte >>= 1;
|
||||||
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 };
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue