diff --git a/CHANGELOG.md b/CHANGELOG.md index 162127dd8..2c55cc975 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. - I2C bus2 support to SI1145/6/7 Ultra violet index and light sensor - I2C bus2 support to LM75AD temperature sensor - Command ``GpioRead`` to show input state (#19810) +- ESP32 core v3 auto TasConsole USB or Serial connection by @staars ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index cd1fed94f..37a9e5d40 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -122,6 +122,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - I2C bus2 support to SI1145/6/7 Ultra violet index and light sensor - I2C bus2 support to LM75AD temperature sensor - Experimental support for ESP32-C2 and ESP32-C6 using Arduino core v3 +- ESP32 core v3 auto TasConsole USB or Serial connection by @staars ### Breaking Changed diff --git a/tasmota/include/tasconsole.h b/tasmota/include/tasconsole.h new file mode 100644 index 000000000..ccb3ea93e --- /dev/null +++ b/tasmota/include/tasconsole.h @@ -0,0 +1,110 @@ +/* + tasconsole.h - ESP32 tasconsole driver for Tasmota + + SPDX-FileCopyrightText: 2023 Christian Baars (@staars) + + SPDX-License-Identifier: GPL-3.0-only +*/ + +#include + +class TASCONSOLE { + + struct Concept { + virtual ~Concept() = default; + virtual int available() = 0; + virtual void begin(uint32_t) = 0; + virtual void flush() = 0; + virtual size_t println() = 0; + virtual size_t print(char *) = 0; + virtual size_t printf(const char*, char *, const char*&, const char*&, const char*&) = 0; + virtual size_t printf(char *) = 0; + virtual size_t read() = 0; + virtual size_t setRxBufferSize(size_t) = 0; + }; + +public: + template + TASCONSOLE(T&& obj){ + object = std::make_unique>(std::forward(obj)); + } + + int available() { + return object->available(); + } + + void begin(uint32_t baud) { + object->begin(baud); + } + + void flush() { + object->flush(); + } + + size_t println() { + return object->println(); + } + + size_t print(char * string) { + return object->print(string); + } + + size_t printf(char *format) { + return object->printf(format); + } + + size_t printf(const char* a, char * b, const char*& c, const char*& d, const char*& f){ + return object->printf(a,b,c,d,f); + } + + size_t read() { + return object->read(); + } + + size_t setRxBufferSize(size_t rx_queue_len) { + return object->setRxBufferSize(rx_queue_len); + } + + template< typename T > + struct Model : Concept { + Model(T const& t) : object(t) {} + int available() override { + return object.available(); + } + + void begin(uint32_t baud) override { + object.begin(baud); + } + + void flush() override { + object.flush(); + } + + size_t println() override { + return object.println(); + } + size_t print(char * string) override { + return object.print(string); + } + + size_t printf(char *format) override { + return object.printf(format); + } + + size_t printf(const char* a, char * b, const char*& c, const char*& d, const char*& f) override { + return object.printf(a,b,c,d,f); + } + + size_t read() override { + return object.read(); + } + + size_t setRxBufferSize(size_t size) override { + return object.setRxBufferSize(size); + } + private: + T object; + }; + + std::unique_ptr object; +}; diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 39a48aff1..dfd56dc2b 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -91,6 +91,14 @@ #endif // ESP32 #endif // USE_UFILESYS +#if ESP_IDF_VERSION_MAJOR >= 5 +#include "include/tasconsole.h" +#if SOC_USB_SERIAL_JTAG_SUPPORTED +#include "hal/usb_serial_jtag_ll.h" +#include "esp_private/rtc_clk.h" +#endif // SOC_USB_SERIAL_JTAG_SUPPORTED +#endif // ESP_IDF_VERSION_MAJOr + // Structs #include "include/tasmota_types.h" @@ -198,6 +206,45 @@ struct XDRVMAILBOX { WiFiUDP PortUdp; // UDP Syslog and Alexa #ifdef ESP32 +#if ESP_IDF_VERSION_MAJOR >= 5 + +/* +#if CONFIG_IDF_TARGET_ESP32C3 || // support USB via HWCDC using JTAG interface + CONFIG_IDF_TARGET_ESP32C6 || // support USB via HWCDC using JTAG interface + CONFIG_IDF_TARGET_ESP32S2 || // support USB via USBCDC + CONFIG_IDF_TARGET_ESP32S3 // support USB via HWCDC using JTAG interface or USBCDC +*/ +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 + +//#if CONFIG_TINYUSB_CDC_ENABLED // This define is not recognized here so use USE_USB_CDC_CONSOLE +#ifdef USE_USB_CDC_CONSOLE +//#warning **** TasConsole use USB **** +bool tasconsole_serial = false; + +#if ARDUINO_USB_MODE +//#warning **** TasConsole ARDUINO_USB_MODE **** +TASCONSOLE TasConsole{USBSerial}; // ESP32C3/C6/S3 embedded USB using JTAG interface +//#warning **** TasConsole uses HWCDC **** +#else // No ARDUINO_USB_MODE +#include "USB.h" +#include "USBCDC.h" +TASCONSOLE TasConsole{USBSerial}; // ESP32Sx embedded USB interface +//#warning **** TasConsole uses USBCDC **** +#endif // ARDUINO_USB_MODE + +#else // No USE_USB_CDC_CONSOLE +TASCONSOLE TasConsole{Serial}; +bool tasconsole_serial = true; +//#warning **** TasConsole uses Serial **** +#endif // USE_USB_CDC_CONSOLE +#else // No ESP32C3, S2 or S3 +TASCONSOLE TasConsole{Serial}; +bool tasconsole_serial = true; +//#warning **** TasConsole uses Serial **** +#endif // ESP32C3, S2 or S3 + +#else // ESP_IDF_VERSION_MAJOR < 5 + /* #if CONFIG_IDF_TARGET_ESP32C3 || // support USB via HWCDC using JTAG interface CONFIG_IDF_TARGET_ESP32C6 || // support USB via HWCDC using JTAG interface @@ -235,6 +282,8 @@ bool tasconsole_serial = true; //#warning **** TasConsole uses Serial **** #endif // ESP32C3, S2 or S3 +#endif // ESP_IDF_VERSION_MAJOR >= 5 + #else // No ESP32 HardwareSerial TasConsole = Serial; // Only serial interface #endif // ESP32 @@ -478,11 +527,64 @@ void setup(void) { Settings = (TSettings*)malloc(sizeof(TSettings)); } +#ifdef ESP32 +#if ESP_IDF_VERSION_MAJOR >= 5 + +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#ifdef USE_USB_CDC_CONSOLE + bool is_connected_to_USB = false; + +#if SOC_USB_SERIAL_JTAG_SUPPORTED // Not S2 + rtc_clk_bbpll_add_consumer(); // Maybe unneeded + usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SOF); + usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SOF); + // First check if USB cable is connected - maybe add a new SetOption to prevent this + for (uint32_t i = 0; i < 1000; i++) { // Allow the host to send at least one SOF packet, 1ms should be enough but let's be very conservative here - maybe unneeded + is_connected_to_USB = ((usb_serial_jtag_ll_get_intraw_mask() & USB_SERIAL_JTAG_INTR_SOF) != 0); + if (is_connected_to_USB) { break; } + delay(1); + } + rtc_clk_bbpll_remove_consumer(); +#endif // SOC_USB_SERIAL_JTAG_SUPPORTED + + if (is_connected_to_USB) { + TasConsole.setRxBufferSize(INPUT_BUFFER_SIZE); + // TasConsole.setTxBufferSize(INPUT_BUFFER_SIZE); + TasConsole.begin(115200); // Will always be 115200 bps +#if !ARDUINO_USB_MODE + USB.begin(); // This needs a serial console with DTR/DSR support +#endif // No ARDUINO_USB_MODE + TasConsole.println(); + AddLog(LOG_LEVEL_INFO, PSTR("CMD: Using USB CDC")); + } else { + // Init command serial console preparing for AddLog use + Serial.begin(TasmotaGlobal.baudrate); + Serial.println(); + TasConsole = Serial; // Fallback + tasconsole_serial = true; + AddLog(LOG_LEVEL_INFO, PSTR("CMD: Fall back to serial port, no SOF packet detected on USB port")); + } +#else // No USE_USB_CDC_CONSOLE + // Init command serial console preparing for AddLog use + Serial.begin(TasmotaGlobal.baudrate); + Serial.println(); +// Serial.setRxBufferSize(INPUT_BUFFER_SIZE); // Default is 256 chars + TasConsole = Serial; +#endif // USE_USB_CDC_CONSOLE +#else // No ESP32C3, S2 or S3 + // Init command serial console preparing for AddLog use + Serial.begin(TasmotaGlobal.baudrate); + Serial.println(); +// Serial.setRxBufferSize(INPUT_BUFFER_SIZE); // Default is 256 chars + TasConsole = Serial; +#endif // ESP32C3, S2 or S3 + +#else // ESP_IDF_VERSION_MAJOR < 5 + // Init command console (either serial or USB) preparing for AddLog use Serial.begin(TasmotaGlobal.baudrate); Serial.println(); // Serial.setRxBufferSize(INPUT_BUFFER_SIZE); // Default is 256 chars -#ifdef ESP32 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #ifdef USE_USB_CDC_CONSOLE TasConsole.setRxBufferSize(INPUT_BUFFER_SIZE); @@ -499,7 +601,14 @@ void setup(void) { #else // No ESP32C3, S2 or S3 TasConsole = Serial; #endif // ESP32C3, S2 or S3 + +#endif // ESP_IDF_VERSION_MAJOR >= 5 + #else // No ESP32 + // Init command serial console preparing for AddLog use + Serial.begin(TasmotaGlobal.baudrate); + Serial.println(); +// Serial.setRxBufferSize(INPUT_BUFFER_SIZE); // Default is 256 chars TasConsole = Serial; #endif // ESP32