From 4bc7b4ec2f8e77e65fd8bb115a181cb56cd5d383 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 26 Jan 2024 12:26:47 +0100 Subject: [PATCH] Add ESP32 support for DS18x20 on Shelly Plus Add-On (#20580) --- CHANGELOG.md | 1 + RELEASENOTES.md | 9 +- lib/lib_basic/OneWire-Stickbreaker/OneWire.h | 560 ------------------ .../OneWire.cpp | 346 +++++++++-- lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.h | 171 ++++++ .../README.md | 0 .../DS18x20_Temperature.pde | 0 .../examples/DS2408_Switch/DS2408_Switch.pde | 0 .../examples/DS250x_PROM/DS250x_PROM.pde | 0 .../keywords.txt | 0 .../library.json | 0 .../library.properties | 0 tasmota/include/tasmota_template.h | 2 - .../xsns_05_esp32_ds18x20.ino | 6 +- 14 files changed, 471 insertions(+), 624 deletions(-) delete mode 100644 lib/lib_basic/OneWire-Stickbreaker/OneWire.h rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/OneWire.cpp (70%) create mode 100644 lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.h rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/README.md (100%) rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/examples/DS18x20_Temperature/DS18x20_Temperature.pde (100%) rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/examples/DS2408_Switch/DS2408_Switch.pde (100%) rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/examples/DS250x_PROM/DS250x_PROM.pde (100%) rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/keywords.txt (100%) rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/library.json (100%) rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/library.properties (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76e5dbab7..b14cdd4dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - HASPmota support for `min` and `max` attribute in `slider` (#20582) - ESP32-C3 support for GPIO11 (#18350) +- ESP32 support for DS18x20 on Shelly Plus Add-On (#20580) ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index d69d460b4..eda83d6f7 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -119,20 +119,21 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ## Changelog v13.3.0.4 ### Added - Command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|OFF]`` -- Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213) -- Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) - Display of active drivers using command ``status 4`` - GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER - GPIO Viewer user selection of assets website now defaults to `https://ota.tasmota.com/tasmota|tasmota32/gpio_viewer/assets` -- NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) +- Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213) +- Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) - Support negative power on BL0942 using index 5..8 [#20322](https://github.com/arendst/Tasmota/issues/20322) - Support for pipsolar inverter [#20408](https://github.com/arendst/Tasmota/issues/20408) - Support for HardwareSerial invert [#15461](https://github.com/arendst/Tasmota/issues/15461) +- NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) - SML support for IM350 [#20474](https://github.com/arendst/Tasmota/issues/20474) - GUI sensor separators [#20495](https://github.com/arendst/Tasmota/issues/20495) - ESP32 used UART information -- ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled +- ESP32 support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled - ESP32 MI BLE support for Xiaomi LYWSD02MMC [#20381](https://github.com/arendst/Tasmota/issues/20381) +- ESP32 support for DS18x20 on Shelly Plus Add-On [#20580](https://github.com/arendst/Tasmota/issues/20580) - ESP32-C3 support for GPIO11 [#18350](https://github.com/arendst/Tasmota/issues/18350) - Berry GPIO viewer initial version using async webserver [#20416](https://github.com/arendst/Tasmota/issues/20416) - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) diff --git a/lib/lib_basic/OneWire-Stickbreaker/OneWire.h b/lib/lib_basic/OneWire-Stickbreaker/OneWire.h deleted file mode 100644 index 77910ecb9..000000000 --- a/lib/lib_basic/OneWire-Stickbreaker/OneWire.h +++ /dev/null @@ -1,560 +0,0 @@ -#ifndef OneWire_h -#define OneWire_h - -#include - -#if defined(__AVR__) -#include -#endif - -#if ARDUINO >= 100 -#include "Arduino.h" // for delayMicroseconds, digitalPinToBitMask, etc -#else -#include "WProgram.h" // for delayMicroseconds -#include "pins_arduino.h" // for digitalPinToBitMask, etc -#endif - -// You can exclude certain features from OneWire. In theory, this -// might save some space. In practice, the compiler automatically -// removes unused code (technically, the linker, using -fdata-sections -// and -ffunction-sections when compiling, and Wl,--gc-sections -// when linking), so most of these will not result in any code size -// reduction. Well, unless you try to use the missing features -// and redesign your program to not need them! ONEWIRE_CRC8_TABLE -// is the exception, because it selects a fast but large algorithm -// or a small but slow algorithm. - -// you can exclude onewire_search by defining that to 0 -#ifndef ONEWIRE_SEARCH -#define ONEWIRE_SEARCH 1 -#endif - -// You can exclude CRC checks altogether by defining this to 0 -#ifndef ONEWIRE_CRC -#define ONEWIRE_CRC 1 -#endif - -// Select the table-lookup method of computing the 8-bit CRC -// by setting this to 1. The lookup table enlarges code size by -// about 250 bytes. It does NOT consume RAM (but did in very -// old versions of OneWire). If you disable this, a slower -// but very compact algorithm is used. -#ifndef ONEWIRE_CRC8_TABLE -#define ONEWIRE_CRC8_TABLE 0 -#endif - -// You can allow 16-bit CRC checks by defining this to 1 -// (Note that ONEWIRE_CRC must also be 1.) -#ifndef ONEWIRE_CRC16 -#define ONEWIRE_CRC16 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif - -// Platform specific I/O definitions - -#if defined(__AVR__) -#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin))) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint8_t -#define IO_REG_BASE_ATTR asm("r30") -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0) -#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask)) -#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask)) -#define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask)) -#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask)) - -#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__) -#define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) -#define PIN_TO_BITMASK(pin) (1) -#define IO_REG_TYPE uint8_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR __attribute__ ((unused)) -#define DIRECT_READ(base, mask) (*((base)+512)) -#define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0) -#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1) -#define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1) -#define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1) - -#elif defined(__MKL26Z64__) -#define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint8_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, mask) ((*((base)+16) & (mask)) ? 1 : 0) -#define DIRECT_MODE_INPUT(base, mask) (*((base)+20) &= ~(mask)) -#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+20) |= (mask)) -#define DIRECT_WRITE_LOW(base, mask) (*((base)+8) = (mask)) -#define DIRECT_WRITE_HIGH(base, mask) (*((base)+4) = (mask)) - -#elif defined(__SAM3X8E__) || defined(__SAM3A8C__) || defined(__SAM3A4C__) -// Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due. -// http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268 -// If you have trouble with OneWire on Arduino Due, please check the -// status of delayMicroseconds() before reporting a bug in OneWire! -#define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->PIO_PER)) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0) -#define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask)) -#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask)) -#define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask)) -#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask)) -#ifndef PROGMEM -#define PROGMEM -#endif -#ifndef pgm_read_byte -#define pgm_read_byte(addr) (*(const uint8_t *)(addr)) -#endif - -#elif defined(__PIC32MX__) -#define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin))) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) //PORTX + 0x10 -#define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) //TRISXSET + 0x08 -#define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) //TRISXCLR + 0x04 -#define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) //LATXCLR + 0x24 -#define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) //LATXSET + 0x28 - -#elif defined(ARDUINO_ARCH_ESP8266) -// Special note: I depend on the ESP community to maintain these definitions and -// submit good pull requests. I can not answer any ESP questions or help you -// resolve any problems related to ESP chips. Please do not contact me and please -// DO NOT CREATE GITHUB ISSUES for ESP support. All ESP questions must be asked -// on ESP community forums. -#define PIN_TO_BASEREG(pin) ((volatile uint32_t*) GPO) -#define PIN_TO_BITMASK(pin) (1 << pin) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, mask) ((GPI & (mask)) ? 1 : 0) //GPIO_IN_ADDRESS -#define DIRECT_MODE_INPUT(base, mask) (GPE &= ~(mask)) //GPIO_ENABLE_W1TC_ADDRESS -#define DIRECT_MODE_OUTPUT(base, mask) (GPE |= (mask)) //GPIO_ENABLE_W1TS_ADDRESS -#define DIRECT_WRITE_LOW(base, mask) (GPOC = (mask)) //GPIO_OUT_W1TC_ADDRESS -#define DIRECT_WRITE_HIGH(base, mask) (GPOS = (mask)) //GPIO_OUT_W1TS_ADDRESS - -#elif defined(ARDUINO_ARCH_ESP32) -#include -#if ESP_IDF_VERSION_MAJOR >= 5 -#include "soc/gpio_periph.h" -#endif // ESP_IDF_VERSION_MAJOR >= 5 -#define PIN_TO_BASEREG(pin) (0) -#define PIN_TO_BITMASK(pin) (pin) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR - -static inline __attribute__((always_inline)) -IO_REG_TYPE directRead(IO_REG_TYPE pin) -{ -// return digitalRead(pin); // Works most of the time -// return gpio_ll_get_level(&GPIO, pin); // The hal is not public api, don't use in application code - -//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 -#if SOC_GPIO_PIN_COUNT <= 32 - return (GPIO.in.val >> pin) & 0x1; -#else // ESP32 with over 32 gpios - if ( pin < 32 ) - return (GPIO.in >> pin) & 0x1; - else - return (GPIO.in1.val >> (pin - 32)) & 0x1; -#endif - return 0; - -} - -static inline __attribute__((always_inline)) -void directWriteLow(IO_REG_TYPE pin) -{ -// digitalWrite(pin, 0); // Works most of the time -// gpio_ll_set_level(&GPIO, pin, 0); // The hal is not public api, don't use in application code - -//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 -#if SOC_GPIO_PIN_COUNT <= 32 - GPIO.out_w1tc.val = ((uint32_t)1 << pin); -#else // ESP32 with over 32 gpios - if ( pin < 32 ) - GPIO.out_w1tc = ((uint32_t)1 << pin); - else - GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32)); -#endif -} - -static inline __attribute__((always_inline)) -void directWriteHigh(IO_REG_TYPE pin) -{ -// digitalWrite(pin, 1); // Works most of the time -// gpio_ll_set_level(&GPIO, pin, 1); // The hal is not public api, don't use in application code - -//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 -#if SOC_GPIO_PIN_COUNT <= 32 - GPIO.out_w1ts.val = ((uint32_t)1 << pin); -#else // ESP32 with over 32 gpios - if ( pin < 32 ) - GPIO.out_w1ts = ((uint32_t)1 << pin); - else - GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32)); -#endif - -} - -static inline __attribute__((always_inline)) -void directModeInput(IO_REG_TYPE pin) -{ -// pinMode(pin, INPUT); // Too slow - doesn't work -// gpio_ll_output_disable(&GPIO, pin); // The hal is not public api, don't use in application code - - if ( digitalPinIsValid(pin) ) - { - // Input -//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 -#if SOC_GPIO_PIN_COUNT <= 32 - GPIO.enable_w1tc.val = ((uint32_t)1 << (pin)); -#else // ESP32 with over 32 gpios - if ( pin < 32 ) - GPIO.enable_w1tc = ((uint32_t)1 << pin); - else - GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32)); -#endif - } - -} - -static inline __attribute__((always_inline)) -void directModeOutput(IO_REG_TYPE pin) -{ -// pinMode(pin, OUTPUT); // Too slow - doesn't work -// gpio_ll_output_enable(&GPIO, pin); // The hal is not public api, don't use in application code - - if ( digitalPinCanOutput(pin) ) - { - // Output -//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 -#if SOC_GPIO_PIN_COUNT <= 32 - GPIO.enable_w1ts.val = ((uint32_t)1 << (pin)); -#else // ESP32 with over 32 gpios - if ( pin < 32 ) - GPIO.enable_w1ts = ((uint32_t)1 << pin); - else - GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32)); -#endif - } - -} - -#define DIRECT_READ(base, pin) directRead(pin) -#define DIRECT_WRITE_LOW(base, pin) directWriteLow(pin) -#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(pin) -#define DIRECT_MODE_INPUT(base, pin) directModeInput(pin) -#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(pin) - -#elif defined(__SAMD21G18A__) -#define PIN_TO_BASEREG(pin) portModeRegister(digitalPinToPort(pin)) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, mask) (((*((base)+8)) & (mask)) ? 1 : 0) -#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) = (mask)) -#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+2)) = (mask)) -#define DIRECT_WRITE_LOW(base, mask) ((*((base)+5)) = (mask)) -#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+6)) = (mask)) - -#elif defined(RBL_NRF51822) -#define PIN_TO_BASEREG(pin) (0) -#define PIN_TO_BITMASK(pin) (pin) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, pin) nrf_gpio_pin_read(pin) -#define DIRECT_WRITE_LOW(base, pin) nrf_gpio_pin_clear(pin) -#define DIRECT_WRITE_HIGH(base, pin) nrf_gpio_pin_set(pin) -#define DIRECT_MODE_INPUT(base, pin) nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL) -#define DIRECT_MODE_OUTPUT(base, pin) nrf_gpio_cfg_output(pin) - -#elif defined(__arc__) /* Arduino101/Genuino101 specifics */ - -#include "scss_registers.h" -#include "portable.h" -#include "avr/pgmspace.h" - -#define GPIO_ID(pin) (g_APinDescription[pin].ulGPIOId) -#define GPIO_TYPE(pin) (g_APinDescription[pin].ulGPIOType) -#define GPIO_BASE(pin) (g_APinDescription[pin].ulGPIOBase) -#define DIR_OFFSET_SS 0x01 -#define DIR_OFFSET_SOC 0x04 -#define EXT_PORT_OFFSET_SS 0x0A -#define EXT_PORT_OFFSET_SOC 0x50 - -/* GPIO registers base address */ -#define PIN_TO_BASEREG(pin) ((volatile uint32_t *)g_APinDescription[pin].ulGPIOBase) -#define PIN_TO_BITMASK(pin) pin -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR - -static inline __attribute__((always_inline)) -IO_REG_TYPE directRead(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - IO_REG_TYPE ret; - if (SS_GPIO == GPIO_TYPE(pin)) { - ret = READ_ARC_REG(((IO_REG_TYPE)base + EXT_PORT_OFFSET_SS)); - } else { - ret = MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, EXT_PORT_OFFSET_SOC); - } - return ((ret >> GPIO_ID(pin)) & 0x01); -} - -static inline __attribute__((always_inline)) -void directModeInput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - if (SS_GPIO == GPIO_TYPE(pin)) { - WRITE_ARC_REG(READ_ARC_REG((((IO_REG_TYPE)base) + DIR_OFFSET_SS)) & ~(0x01 << GPIO_ID(pin)), - ((IO_REG_TYPE)(base) + DIR_OFFSET_SS)); - } else { - MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) &= ~(0x01 << GPIO_ID(pin)); - } -} - -static inline __attribute__((always_inline)) -void directModeOutput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - if (SS_GPIO == GPIO_TYPE(pin)) { - WRITE_ARC_REG(READ_ARC_REG(((IO_REG_TYPE)(base) + DIR_OFFSET_SS)) | (0x01 << GPIO_ID(pin)), - ((IO_REG_TYPE)(base) + DIR_OFFSET_SS)); - } else { - MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) |= (0x01 << GPIO_ID(pin)); - } -} - -static inline __attribute__((always_inline)) -void directWriteLow(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - if (SS_GPIO == GPIO_TYPE(pin)) { - WRITE_ARC_REG(READ_ARC_REG(base) & ~(0x01 << GPIO_ID(pin)), base); - } else { - MMIO_REG_VAL(base) &= ~(0x01 << GPIO_ID(pin)); - } -} - -static inline __attribute__((always_inline)) -void directWriteHigh(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - if (SS_GPIO == GPIO_TYPE(pin)) { - WRITE_ARC_REG(READ_ARC_REG(base) | (0x01 << GPIO_ID(pin)), base); - } else { - MMIO_REG_VAL(base) |= (0x01 << GPIO_ID(pin)); - } -} - -#define DIRECT_READ(base, pin) directRead(base, pin) -#define DIRECT_MODE_INPUT(base, pin) directModeInput(base, pin) -#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(base, pin) -#define DIRECT_WRITE_LOW(base, pin) directWriteLow(base, pin) -#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(base, pin) - -#elif defined(__riscv) - -/* - * Tested on highfive1 - * - * Stable results are achieved operating in the - * two high speed modes of the highfive1. It - * seems to be less reliable in slow mode. - */ -#define PIN_TO_BASEREG(pin) (0) -#define PIN_TO_BITMASK(pin) digitalPinToBitMask(pin) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR - -static inline __attribute__((always_inline)) -IO_REG_TYPE directRead(IO_REG_TYPE mask) -{ - return ((GPIO_REG(GPIO_INPUT_VAL) & mask) != 0) ? 1 : 0; -} - -static inline __attribute__((always_inline)) -void directModeInput(IO_REG_TYPE mask) -{ - GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask; - GPIO_REG(GPIO_IOF_EN) &= ~mask; - - GPIO_REG(GPIO_INPUT_EN) |= mask; - GPIO_REG(GPIO_OUTPUT_EN) &= ~mask; -} - -static inline __attribute__((always_inline)) -void directModeOutput(IO_REG_TYPE mask) -{ - GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask; - GPIO_REG(GPIO_IOF_EN) &= ~mask; - - GPIO_REG(GPIO_INPUT_EN) &= ~mask; - GPIO_REG(GPIO_OUTPUT_EN) |= mask; -} - -static inline __attribute__((always_inline)) -void directWriteLow(IO_REG_TYPE mask) -{ - GPIO_REG(GPIO_OUTPUT_VAL) &= ~mask; -} - -static inline __attribute__((always_inline)) -void directWriteHigh(IO_REG_TYPE mask) -{ - GPIO_REG(GPIO_OUTPUT_VAL) |= mask; -} - -#define DIRECT_READ(base, mask) directRead(mask) -#define DIRECT_WRITE_LOW(base, mask) directWriteLow(mask) -#define DIRECT_WRITE_HIGH(base, mask) directWriteHigh(mask) -#define DIRECT_MODE_INPUT(base, mask) directModeInput(mask) -#define DIRECT_MODE_OUTPUT(base, mask) directModeOutput(mask) - -#else -#define PIN_TO_BASEREG(pin) (0) -#define PIN_TO_BITMASK(pin) (pin) -#define IO_REG_TYPE unsigned int -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, pin) digitalRead(pin) -#define DIRECT_WRITE_LOW(base, pin) digitalWrite(pin, LOW) -#define DIRECT_WRITE_HIGH(base, pin) digitalWrite(pin, HIGH) -#define DIRECT_MODE_INPUT(base, pin) pinMode(pin,INPUT) -#define DIRECT_MODE_OUTPUT(base, pin) pinMode(pin,OUTPUT) -#warning "OneWire. Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite. Operation of this library is not guaranteed on this architecture." - -#endif - - -class OneWire -{ - private: - IO_REG_TYPE bitmask; - volatile IO_REG_TYPE *baseReg; - -#if ONEWIRE_SEARCH - // global search state - unsigned char ROM_NO[8]; - uint8_t LastDiscrepancy; - uint8_t LastFamilyDiscrepancy; - uint8_t LastDeviceFlag; -#endif - - public: - OneWire( uint8_t pin); - - // Perform a 1-Wire reset cycle. Returns 1 if a device responds - // with a presence pulse. Returns 0 if there is no device or the - // bus is shorted or otherwise held low for more than 250uS - uint8_t reset(void); - - // Issue a 1-Wire rom select command, you do the reset first. - void select(const uint8_t rom[8]); - - // Issue a 1-Wire rom skip command, to address all on bus. - void skip(void); - - // Write a byte. If 'power' is one then the wire is held high at - // the end for parasitically powered devices. You are responsible - // for eventually depowering it by calling depower() or doing - // another read or write. - void write(uint8_t v, uint8_t power = 0); - - void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0); - - // Read a byte. - uint8_t read(void); - - void read_bytes(uint8_t *buf, uint16_t count); - - // Write a bit. The bus is always left powered at the end, see - // note in write() about that. - void write_bit(uint8_t v); - - // Read a bit. - uint8_t read_bit(void); - - // Stop forcing power onto the bus. You only need to do this if - // you used the 'power' flag to write() or used a write_bit() call - // and aren't about to do another read or write. You would rather - // not leave this powered if you don't have to, just in case - // someone shorts your bus. - void depower(void); - -#if ONEWIRE_SEARCH - // Clear the search state so that if will start from the beginning again. - void reset_search(); - - // Setup the search to find the device type 'family_code' on the next call - // to search(*newAddr) if it is present. - void target_search(uint8_t family_code); - - // Look for the next device. Returns 1 if a new address has been - // returned. A zero might mean that the bus is shorted, there are - // no devices, or you have already retrieved all of them. It - // might be a good idea to check the CRC to make sure you didn't - // get garbage. The order is deterministic. You will always get - // the same devices in the same order. - uint8_t search(uint8_t *newAddr, bool search_mode = true); -#endif - -#if ONEWIRE_CRC - // Compute a Dallas Semiconductor 8 bit CRC, these are used in the - // ROM and scratchpad registers. - static uint8_t crc8(const uint8_t *addr, uint8_t len); - -#if ONEWIRE_CRC16 - // Compute the 1-Wire CRC16 and compare it against the received CRC. - // Example usage (reading a DS2408): - // // Put everything in a buffer so we can compute the CRC easily. - // uint8_t buf[13]; - // buf[0] = 0xF0; // Read PIO Registers - // buf[1] = 0x88; // LSB address - // buf[2] = 0x00; // MSB address - // WriteBytes(net, buf, 3); // Write 3 cmd bytes - // ReadBytes(net, buf+3, 10); // Read 6 data bytes, 2 0xFF, 2 CRC16 - // if (!CheckCRC16(buf, 11, &buf[11])) { - // // Handle error. - // } - // - // @param input - Array of bytes to checksum. - // @param len - How many bytes to use. - // @param inverted_crc - The two CRC16 bytes in the received data. - // This should just point into the received data, - // *not* at a 16-bit integer. - // @param crc - The crc starting value (optional) - // @return True, iff the CRC matches. - static bool check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc = 0); - - // Compute a Dallas Semiconductor 16 bit CRC. This is required to check - // the integrity of data received from many 1-Wire devices. Note that the - // CRC computed here is *not* what you'll get from the 1-Wire network, - // for two reasons: - // 1) The CRC is transmitted bitwise inverted. - // 2) Depending on the endian-ness of your processor, the binary - // representation of the two-byte return value may have a different - // byte order than the two bytes you get from 1-Wire. - // @param input - Array of bytes to checksum. - // @param len - How many bytes to use. - // @param crc - The crc starting value (optional) - // @return The CRC16, as defined by Dallas Semiconductor. - static uint16_t crc16(const uint8_t* input, uint16_t len, uint16_t crc = 0); -#endif -#endif -}; - -#endif diff --git a/lib/lib_basic/OneWire-Stickbreaker/OneWire.cpp b/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.cpp similarity index 70% rename from lib/lib_basic/OneWire-Stickbreaker/OneWire.cpp rename to lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.cpp index 404e8b272..01c65d3d4 100644 --- a/lib/lib_basic/OneWire-Stickbreaker/OneWire.cpp +++ b/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.cpp @@ -33,6 +33,12 @@ OneWire is now very mature code. No changes other than adding definitions for newer hardware support are anticipated. ======= +Version 2.3.3 Tasmota 26JAN2024 + Add support for Shelly Add-On by Theo Arends + +Version 2.3.3 Tasmota 15AUG2023 + Add support for ESP32 Arduino core 3 by @Jason2866 + Version 2.3.3 ESP32 Stickbreaker 06MAY2019 Add a #ifdef to isolate ESP32 mods Version 2.3.1 ESP32 everslick 30APR2018 @@ -152,19 +158,180 @@ sample code bearing this copyright. #include "OneWire.h" -#ifdef ESP32 +// Platform specific I/O definitions + +#if defined(ARDUINO_ARCH_ESP8266) +// Special note: I depend on the ESP community to maintain these definitions and +// submit good pull requests. I can not answer any ESP questions or help you +// resolve any problems related to ESP chips. Please do not contact me and please +// DO NOT CREATE GITHUB ISSUES for ESP support. All ESP questions must be asked +// on ESP community forums. +#define PIN_TO_BASEREG(pin) ((volatile uint32_t*) GPO) +#define PIN_TO_BITMASK(pin) (1UL << pin) +#define IO_REG_TYPE uint32_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR + +static inline __attribute__((always_inline)) +void directModeInput(IO_REG_TYPE mask) +{ + if(mask > 0x8000) + { + GP16FFS(GPFFS_GPIO(16)); + GPC16 = 0; + GP16E &= ~1; + } + else + { + GPE &= ~(mask); + } +} + +static inline __attribute__((always_inline)) +void directModeOutput(IO_REG_TYPE mask) +{ + if(mask > 0x8000) + { + GP16FFS(GPFFS_GPIO(16)); + GPC16 = 0; + GP16E |= 1; + } + else + { + GPE |= (mask); + } +} + +static inline __attribute__((always_inline)) +bool directRead(IO_REG_TYPE mask) +{ + if(mask > 0x8000) + return GP16I & 0x01; + else + return ((GPI & (mask)) ? true : false); +} + +#define DIRECT_READ(base, mask) directRead(mask) +#define DIRECT_MODE_INPUT(base, mask) directModeInput(mask) +#define DIRECT_MODE_OUTPUT(base, mask) directModeOutput(mask) +#define DIRECT_WRITE_LOW(base, mask) (mask > 0x8000) ? GP16O &= ~1 : (GPOC = (mask)) +#define DIRECT_WRITE_HIGH(base, mask) (mask > 0x8000) ? GP16O |= 1 : (GPOS = (mask)) + +#define CRIT_TIMING #define t_noInterrupts() {portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;portENTER_CRITICAL(&mux) #define t_interrupts() portEXIT_CRITICAL(&mux);} -#else -#define t_noInterrupts noInterrupts -#define t_interrupts interrupts + +#elif defined(ARDUINO_ARCH_ESP32) +#include +#if ESP_IDF_VERSION_MAJOR >= 5 +#include "soc/gpio_periph.h" +#endif // ESP_IDF_VERSION_MAJOR >= 5 +#define PIN_TO_BASEREG(pin) (0) +#define PIN_TO_BITMASK(pin) (pin) +#define IO_REG_TYPE uint32_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR + +static inline __attribute__((always_inline)) +IO_REG_TYPE directRead(IO_REG_TYPE pin) +{ +#if SOC_GPIO_PIN_COUNT <= 32 + return (GPIO.in.val >> pin) & 0x1; +#else // ESP32 with over 32 gpios + if ( pin < 32 ) + return (GPIO.in >> pin) & 0x1; + else + return (GPIO.in1.val >> (pin - 32)) & 0x1; +#endif + return 0; + +} + +static inline __attribute__((always_inline)) +void directWriteLow(IO_REG_TYPE pin) +{ +#if SOC_GPIO_PIN_COUNT <= 32 + GPIO.out_w1tc.val = ((uint32_t)1 << pin); +#else // ESP32 with over 32 gpios + if ( pin < 32 ) + GPIO.out_w1tc = ((uint32_t)1 << pin); + else + GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32)); +#endif +} + +static inline __attribute__((always_inline)) +void directWriteHigh(IO_REG_TYPE pin) +{ +#if SOC_GPIO_PIN_COUNT <= 32 + GPIO.out_w1ts.val = ((uint32_t)1 << pin); +#else // ESP32 with over 32 gpios + if ( pin < 32 ) + GPIO.out_w1ts = ((uint32_t)1 << pin); + else + GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32)); #endif -OneWire::OneWire(uint8_t pin) +} + +static inline __attribute__((always_inline)) +void directModeInput(IO_REG_TYPE pin) { + if ( digitalPinIsValid(pin) ) + { + // Input +#if SOC_GPIO_PIN_COUNT <= 32 + GPIO.enable_w1tc.val = ((uint32_t)1 << (pin)); +#else // ESP32 with over 32 gpios + if ( pin < 32 ) + GPIO.enable_w1tc = ((uint32_t)1 << pin); + else + GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32)); +#endif + } + +} + +static inline __attribute__((always_inline)) +void directModeOutput(IO_REG_TYPE pin) +{ + if ( digitalPinCanOutput(pin) ) + { + // Output +#if SOC_GPIO_PIN_COUNT <= 32 + GPIO.enable_w1ts.val = ((uint32_t)1 << (pin)); +#else // ESP32 with over 32 gpios + if ( pin < 32 ) + GPIO.enable_w1ts = ((uint32_t)1 << pin); + else + GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32)); +#endif + } + +} + +#define DIRECT_READ(base, pin) directRead(pin) +#define DIRECT_WRITE_LOW(base, pin) directWriteLow(pin) +#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(pin) +#define DIRECT_MODE_INPUT(base, pin) directModeInput(pin) +#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(pin) + +#define CRIT_TIMING IRAM_ATTR +#define t_noInterrupts noInterrupts +#define t_interrupts interrupts + +#endif + +OneWire::OneWire(uint8_t pin, int8_t pin_out) { pinMode(pin, INPUT); bitmask = PIN_TO_BITMASK(pin); baseReg = PIN_TO_BASEREG(pin); + dual_mode = (pin_out > -1); + if (dual_mode) { + pinMode(pin_out, OUTPUT); + bitmask_out = PIN_TO_BITMASK(pin_out); + baseReg_out = PIN_TO_BASEREG(pin_out); + } #if ONEWIRE_SEARCH reset_search(); #endif @@ -177,19 +344,19 @@ OneWire::OneWire(uint8_t pin) // // Returns 1 if a device asserted a presence pulse, 0 otherwise. // -#ifdef ARDUINO_ARCH_ESP32 -uint8_t IRAM_ATTR OneWire::reset(void) -#else -uint8_t OneWire::reset(void) -#endif +uint8_t CRIT_TIMING OneWire::reset(void) { - IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; - volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; - uint8_t r; - uint8_t retries = 125; + IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; + volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; + + uint8_t r; + uint8_t retries = 125; + + if (!dual_mode) { t_noInterrupts(); DIRECT_MODE_INPUT(reg, mask); t_interrupts(); + // wait until the wire is high... just in case do { if (--retries == 0) return 0; @@ -204,7 +371,33 @@ uint8_t OneWire::reset(void) delayMicroseconds(70); r = !DIRECT_READ(reg, mask); t_interrupts(); + delayMicroseconds(410); + } else { + IO_REG_TYPE mask_out IO_REG_MASK_ATTR = bitmask_out; + volatile IO_REG_TYPE *reg_out IO_REG_BASE_ATTR = baseReg_out; + + t_noInterrupts(); + DIRECT_WRITE_HIGH(reg_out, mask_out); + t_interrupts(); + + // wait until the wire is high... just in case + do { + if (--retries == 0) return 0; + delayMicroseconds(2); + } while ( !DIRECT_READ(reg, mask)); + + t_noInterrupts(); + DIRECT_WRITE_LOW(reg_out, mask_out); + delayMicroseconds(480); + DIRECT_WRITE_HIGH(reg_out, mask_out); + delayMicroseconds(70); + r = !DIRECT_READ(reg, mask); + t_interrupts(); + + delayMicroseconds(410); + } + return r; } @@ -212,57 +405,84 @@ uint8_t OneWire::reset(void) // Write a bit. Port and bit is used to cut lookup time and provide // more certain timing. // -#ifdef ARDUINO_ARCH_ESP32 -void IRAM_ATTR OneWire::write_bit(uint8_t v) -#else -void OneWire::write_bit(uint8_t v) -#endif +void CRIT_TIMING OneWire::write_bit(uint8_t v) { IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; - if (v & 1) { - t_noInterrupts(); - DIRECT_WRITE_LOW(reg, mask); - DIRECT_MODE_OUTPUT(reg, mask); // drive output low - delayMicroseconds(10); - DIRECT_WRITE_HIGH(reg, mask); // drive output high - t_interrupts(); - delayMicroseconds(55); - } else { - t_noInterrupts(); - DIRECT_WRITE_LOW(reg, mask); - DIRECT_MODE_OUTPUT(reg, mask); // drive output low - delayMicroseconds(65); - DIRECT_WRITE_HIGH(reg, mask); // drive output high - t_interrupts(); - delayMicroseconds(5); - } + if (!dual_mode) { + if (v & 1) { + t_noInterrupts(); + DIRECT_WRITE_LOW(reg, mask); + DIRECT_MODE_OUTPUT(reg, mask); // drive output low + delayMicroseconds(10); + DIRECT_WRITE_HIGH(reg, mask); // drive output high + t_interrupts(); + delayMicroseconds(55); + } else { + t_noInterrupts(); + DIRECT_WRITE_LOW(reg, mask); + DIRECT_MODE_OUTPUT(reg, mask); // drive output low + delayMicroseconds(65); + DIRECT_WRITE_HIGH(reg, mask); // drive output high + t_interrupts(); + delayMicroseconds(5); + } + } else { + IO_REG_TYPE mask_out IO_REG_MASK_ATTR = bitmask_out; + volatile IO_REG_TYPE *reg_out IO_REG_BASE_ATTR = baseReg_out; + + if (v & 1) { + t_noInterrupts(); + DIRECT_WRITE_LOW(reg_out, mask_out); + delayMicroseconds(10); + DIRECT_WRITE_HIGH(reg_out, mask_out); // drive output high + t_interrupts(); + delayMicroseconds(55); + } else { + t_noInterrupts(); + DIRECT_WRITE_LOW(reg_out, mask_out); + delayMicroseconds(65); + DIRECT_WRITE_HIGH(reg_out, mask_out); // drive output high + t_interrupts(); + delayMicroseconds(5); + } + } } // // Read a bit. Port and bit is used to cut lookup time and provide // more certain timing. // -#ifdef ARDUINO_ARCH_ESP32 -uint8_t IRAM_ATTR OneWire::read_bit(void) -#else -uint8_t OneWire::read_bit(void) -#endif +uint8_t CRIT_TIMING OneWire::read_bit(void) { IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; uint8_t r; - t_noInterrupts(); - DIRECT_MODE_OUTPUT(reg, mask); - DIRECT_WRITE_LOW(reg, mask); - delayMicroseconds(3); - DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise - delayMicroseconds(10); - r = DIRECT_READ(reg, mask); - t_interrupts(); - delayMicroseconds(53); + if (!dual_mode) { + t_noInterrupts(); + DIRECT_MODE_OUTPUT(reg, mask); + DIRECT_WRITE_LOW(reg, mask); + delayMicroseconds(3); + DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise + delayMicroseconds(10); + r = DIRECT_READ(reg, mask); + t_interrupts(); + delayMicroseconds(53); + } else { + IO_REG_TYPE mask_out IO_REG_MASK_ATTR = bitmask_out; + volatile IO_REG_TYPE *reg_out IO_REG_BASE_ATTR = baseReg_out; + + t_noInterrupts(); + DIRECT_WRITE_LOW(reg_out, mask_out); + delayMicroseconds(3); + DIRECT_WRITE_HIGH(reg_out, mask_out); + delayMicroseconds(10); + r = DIRECT_READ(reg, mask); + t_interrupts(); + delayMicroseconds(53); + } return r; } @@ -280,10 +500,16 @@ void OneWire::write(uint8_t v, uint8_t power /* = 0 */) { OneWire::write_bit( (bitMask & v)?1:0); } if ( !power) { + if (!dual_mode) { t_noInterrupts(); DIRECT_MODE_INPUT(baseReg, bitmask); DIRECT_WRITE_LOW(baseReg, bitmask); t_interrupts(); + } else { +// t_noInterrupts(); +// DIRECT_WRITE_LOW(baseReg_out, bitmask_out); +// t_interrupts(); + } } } @@ -291,10 +517,16 @@ void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 for (uint16_t i = 0 ; i < count ; i++) write(buf[i]); if (!power) { - t_noInterrupts(); - DIRECT_MODE_INPUT(baseReg, bitmask); - DIRECT_WRITE_LOW(baseReg, bitmask); - t_interrupts(); + if (!dual_mode) { + t_noInterrupts(); + DIRECT_MODE_INPUT(baseReg, bitmask); + DIRECT_WRITE_LOW(baseReg, bitmask); + t_interrupts(); + } else { +// t_noInterrupts(); +// DIRECT_WRITE_LOW(baseReg_out, bitmask_out); +// t_interrupts(); + } } } @@ -338,9 +570,9 @@ void OneWire::skip() void OneWire::depower() { - t_noInterrupts(); - DIRECT_MODE_INPUT(baseReg, bitmask); - t_interrupts(); +// t_noInterrupts(); +// DIRECT_MODE_INPUT(baseReg, bitmask); +// t_interrupts(); } #if ONEWIRE_SEARCH diff --git a/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.h b/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.h new file mode 100644 index 000000000..fcef2bd20 --- /dev/null +++ b/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.h @@ -0,0 +1,171 @@ +#ifndef OneWire_h +#define OneWire_h + +#include +#include "Arduino.h" // for delayMicroseconds, digitalPinToBitMask, etc + +// You can exclude certain features from OneWire. In theory, this +// might save some space. In practice, the compiler automatically +// removes unused code (technically, the linker, using -fdata-sections +// and -ffunction-sections when compiling, and Wl,--gc-sections +// when linking), so most of these will not result in any code size +// reduction. Well, unless you try to use the missing features +// and redesign your program to not need them! ONEWIRE_CRC8_TABLE +// is the exception, because it selects a fast but large algorithm +// or a small but slow algorithm. + +// you can exclude onewire_search by defining that to 0 +#ifndef ONEWIRE_SEARCH +#define ONEWIRE_SEARCH 1 +#endif + +// You can exclude CRC checks altogether by defining this to 0 +#ifndef ONEWIRE_CRC +#define ONEWIRE_CRC 1 +#endif + +// Select the table-lookup method of computing the 8-bit CRC +// by setting this to 1. The lookup table enlarges code size by +// about 250 bytes. It does NOT consume RAM (but did in very +// old versions of OneWire). If you disable this, a slower +// but very compact algorithm is used. +#ifndef ONEWIRE_CRC8_TABLE +#define ONEWIRE_CRC8_TABLE 0 +#endif + +// You can allow 16-bit CRC checks by defining this to 1 +// (Note that ONEWIRE_CRC must also be 1.) +#ifndef ONEWIRE_CRC16 +#define ONEWIRE_CRC16 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +#define IO_REG_TYPE uint32_t + +class OneWire +{ + private: + IO_REG_TYPE bitmask; + volatile IO_REG_TYPE *baseReg; + bool dual_mode; + IO_REG_TYPE bitmask_out; + volatile IO_REG_TYPE *baseReg_out; + +#if ONEWIRE_SEARCH + // global search state + unsigned char ROM_NO[8]; + uint8_t LastDiscrepancy; + uint8_t LastFamilyDiscrepancy; + uint8_t LastDeviceFlag; +#endif + + public: + OneWire(uint8_t pin, int8_t pin_out = -1); + + // Perform a 1-Wire reset cycle. Returns 1 if a device responds + // with a presence pulse. Returns 0 if there is no device or the + // bus is shorted or otherwise held low for more than 250uS + uint8_t reset(void); + + // Issue a 1-Wire rom select command, you do the reset first. + void select(const uint8_t rom[8]); + + // Issue a 1-Wire rom skip command, to address all on bus. + void skip(void); + + // Write a byte. If 'power' is one then the wire is held high at + // the end for parasitically powered devices. You are responsible + // for eventually depowering it by calling depower() or doing + // another read or write. + void write(uint8_t v, uint8_t power = 0); + + void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0); + + // Read a byte. + uint8_t read(void); + + void read_bytes(uint8_t *buf, uint16_t count); + + // Write a bit. The bus is always left powered at the end, see + // note in write() about that. + void write_bit(uint8_t v); + + // Read a bit. + uint8_t read_bit(void); + + // Stop forcing power onto the bus. You only need to do this if + // you used the 'power' flag to write() or used a write_bit() call + // and aren't about to do another read or write. You would rather + // not leave this powered if you don't have to, just in case + // someone shorts your bus. + void depower(void); + +#if ONEWIRE_SEARCH + // Clear the search state so that if will start from the beginning again. + void reset_search(); + + // Setup the search to find the device type 'family_code' on the next call + // to search(*newAddr) if it is present. + void target_search(uint8_t family_code); + + // Look for the next device. Returns 1 if a new address has been + // returned. A zero might mean that the bus is shorted, there are + // no devices, or you have already retrieved all of them. It + // might be a good idea to check the CRC to make sure you didn't + // get garbage. The order is deterministic. You will always get + // the same devices in the same order. + uint8_t search(uint8_t *newAddr, bool search_mode = true); +#endif + +#if ONEWIRE_CRC + // Compute a Dallas Semiconductor 8 bit CRC, these are used in the + // ROM and scratchpad registers. + static uint8_t crc8(const uint8_t *addr, uint8_t len); + +#if ONEWIRE_CRC16 + // Compute the 1-Wire CRC16 and compare it against the received CRC. + // Example usage (reading a DS2408): + // // Put everything in a buffer so we can compute the CRC easily. + // uint8_t buf[13]; + // buf[0] = 0xF0; // Read PIO Registers + // buf[1] = 0x88; // LSB address + // buf[2] = 0x00; // MSB address + // WriteBytes(net, buf, 3); // Write 3 cmd bytes + // ReadBytes(net, buf+3, 10); // Read 6 data bytes, 2 0xFF, 2 CRC16 + // if (!CheckCRC16(buf, 11, &buf[11])) { + // // Handle error. + // } + // + // @param input - Array of bytes to checksum. + // @param len - How many bytes to use. + // @param inverted_crc - The two CRC16 bytes in the received data. + // This should just point into the received data, + // *not* at a 16-bit integer. + // @param crc - The crc starting value (optional) + // @return True, iff the CRC matches. + static bool check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc = 0); + + // Compute a Dallas Semiconductor 16 bit CRC. This is required to check + // the integrity of data received from many 1-Wire devices. Note that the + // CRC computed here is *not* what you'll get from the 1-Wire network, + // for two reasons: + // 1) The CRC is transmitted bitwise inverted. + // 2) Depending on the endian-ness of your processor, the binary + // representation of the two-byte return value may have a different + // byte order than the two bytes you get from 1-Wire. + // @param input - Array of bytes to checksum. + // @param len - How many bytes to use. + // @param crc - The crc starting value (optional) + // @return The CRC16, as defined by Dallas Semiconductor. + static uint16_t crc16(const uint8_t* input, uint16_t len, uint16_t crc = 0); +#endif +#endif +}; + +#endif diff --git a/lib/lib_basic/OneWire-Stickbreaker/README.md b/lib/lib_basic/TasmotaOneWire-2.3.3/README.md similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/README.md rename to lib/lib_basic/TasmotaOneWire-2.3.3/README.md diff --git a/lib/lib_basic/OneWire-Stickbreaker/examples/DS18x20_Temperature/DS18x20_Temperature.pde b/lib/lib_basic/TasmotaOneWire-2.3.3/examples/DS18x20_Temperature/DS18x20_Temperature.pde similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/examples/DS18x20_Temperature/DS18x20_Temperature.pde rename to lib/lib_basic/TasmotaOneWire-2.3.3/examples/DS18x20_Temperature/DS18x20_Temperature.pde diff --git a/lib/lib_basic/OneWire-Stickbreaker/examples/DS2408_Switch/DS2408_Switch.pde b/lib/lib_basic/TasmotaOneWire-2.3.3/examples/DS2408_Switch/DS2408_Switch.pde similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/examples/DS2408_Switch/DS2408_Switch.pde rename to lib/lib_basic/TasmotaOneWire-2.3.3/examples/DS2408_Switch/DS2408_Switch.pde diff --git a/lib/lib_basic/OneWire-Stickbreaker/examples/DS250x_PROM/DS250x_PROM.pde b/lib/lib_basic/TasmotaOneWire-2.3.3/examples/DS250x_PROM/DS250x_PROM.pde similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/examples/DS250x_PROM/DS250x_PROM.pde rename to lib/lib_basic/TasmotaOneWire-2.3.3/examples/DS250x_PROM/DS250x_PROM.pde diff --git a/lib/lib_basic/OneWire-Stickbreaker/keywords.txt b/lib/lib_basic/TasmotaOneWire-2.3.3/keywords.txt similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/keywords.txt rename to lib/lib_basic/TasmotaOneWire-2.3.3/keywords.txt diff --git a/lib/lib_basic/OneWire-Stickbreaker/library.json b/lib/lib_basic/TasmotaOneWire-2.3.3/library.json similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/library.json rename to lib/lib_basic/TasmotaOneWire-2.3.3/library.json diff --git a/lib/lib_basic/OneWire-Stickbreaker/library.properties b/lib/lib_basic/TasmotaOneWire-2.3.3/library.properties similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/library.properties rename to lib/lib_basic/TasmotaOneWire-2.3.3/library.properties diff --git a/tasmota/include/tasmota_template.h b/tasmota/include/tasmota_template.h index 340d1ab21..212bf3cdd 100644 --- a/tasmota/include/tasmota_template.h +++ b/tasmota/include/tasmota_template.h @@ -731,9 +731,7 @@ const uint16_t kGpioNiceList[] PROGMEM = { #endif #ifdef USE_DS18x20 AGPIO(GPIO_DSB) + MAX_DSB, // Single wire DS18B20 or DS18S20 -#ifdef ESP8266 AGPIO(GPIO_DSB_OUT) + MAX_DSB, // Pseudo Single wire DS18B20 or DS18S20 -#endif // ESP8266 #endif // USE_DS18x20 #ifdef USE_LMT01 AGPIO(GPIO_LMT01), // LMT01, count pulses on GPIO diff --git a/tasmota/tasmota_xsns_sensor/xsns_05_esp32_ds18x20.ino b/tasmota/tasmota_xsns_sensor/xsns_05_esp32_ds18x20.ino index 95b5776df..80b6f3c6f 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_05_esp32_ds18x20.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_05_esp32_ds18x20.ino @@ -86,7 +86,11 @@ void Ds18x20Init(void) { DS18X20Data.gpios = 0; for (uint32_t pins = 0; pins < MAX_DSB; pins++) { if (PinUsed(GPIO_DSB, pins)) { - ds18x20_gpios[pins] = new OneWire(Pin(GPIO_DSB, pins)); + int8_t pin_out = -1; + if (PinUsed(GPIO_DSB_OUT, pins)) { + pin_out = Pin(GPIO_DSB_OUT, pins); + } + ds18x20_gpios[pins] = new OneWire(Pin(GPIO_DSB, pins), pin_out); DS18X20Data.gpios++; } }