mirror of https://github.com/arendst/Tasmota.git
Merge branch 'development' into prerelease-14.4.0
This commit is contained in:
commit
2f4ca9bbe9
|
@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file.
|
||||||
- Command `SetOption162 1` to disable adding export energy to energy today (#22578)
|
- Command `SetOption162 1` to disable adding export energy to energy today (#22578)
|
||||||
- ESP32 support for WPA2/3 Enterprise conditional in core v3.1.0.241206 (#22600)
|
- ESP32 support for WPA2/3 Enterprise conditional in core v3.1.0.241206 (#22600)
|
||||||
- Support for Sonoff POWCT Energy Export Active (#22596)
|
- Support for Sonoff POWCT Energy Export Active (#22596)
|
||||||
|
- Improved auto-selection of LED hardware support (RMT, SPI) (#22618)
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
- ESP32 ArtNet switches from GRB to RGB encoding (#22556)
|
- ESP32 ArtNet switches from GRB to RGB encoding (#22556)
|
||||||
|
|
|
@ -44,10 +44,10 @@ enum TasmotaLEDTypesEncoding : uint16_t {
|
||||||
enum TasmotaLEDHardware : uint32_t {
|
enum TasmotaLEDHardware : uint32_t {
|
||||||
// low-order bits are reserved for channels numbers and hardware flags - currenlty not useds
|
// low-order bits are reserved for channels numbers and hardware flags - currenlty not useds
|
||||||
// bits 16..23
|
// bits 16..23
|
||||||
TasmotaLed_HW_Default = 0x0 << 16,
|
TasmotaLed_HW_Default = 0x000000,
|
||||||
TasmotaLed_RMT = 1 << 16,
|
TasmotaLed_RMT = (1 << 0) << 16,
|
||||||
TasmotaLed_SPI = 2 << 16,
|
TasmotaLed_SPI = (1 << 1) << 16,
|
||||||
TasmotaLed_I2S = 3 << 16,
|
TasmotaLed_I2S = (1 << 2) << 16,
|
||||||
TasmotaLed_HW_None = 0xFF << 16, // indicates that the specified HW is not supported
|
TasmotaLed_HW_None = 0xFF << 16, // indicates that the specified HW is not supported
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,40 +30,33 @@ enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_D
|
||||||
|
|
||||||
|
|
||||||
// convert to the appropriate hardware acceleration based on capacities of the SOC
|
// convert to the appropriate hardware acceleration based on capacities of the SOC
|
||||||
uint32_t TasmotaLEDPusher::ResolveHardware(uint32_t hw) {
|
uint32_t TasmotaLEDPusher::ResolveHardware(uint32_t hw_input) {
|
||||||
uint32_t hw_orig = hw;
|
|
||||||
// Step 1. discard any unsupported hardware, and replace with TasmotaLed_HW_Default
|
// Step 1. discard any unsupported hardware, and replace with TasmotaLed_HW_Default
|
||||||
uint32_t hw_type = hw & 0xFF0000; // discard bits 0..15
|
uint32_t hw = hw_input & 0xFF0000; // discard bits 0..15
|
||||||
#if !TASMOTALED_HARDWARE_RMT
|
#if !TASMOTALED_HARDWARE_RMT
|
||||||
if (hw_type == TasmotaLed_RMT) {
|
hw &= ~TasmotaLed_RMT; // remove RMT flag if not supported by hardware
|
||||||
hw = TasmotaLed_HW_None;
|
|
||||||
}
|
|
||||||
#endif // TASMOTALED_HARDWARE_RMT
|
#endif // TASMOTALED_HARDWARE_RMT
|
||||||
#if !TASMOTALED_HARDWARE_SPI
|
#if !TASMOTALED_HARDWARE_SPI
|
||||||
if (hw_type == TasmotaLed_SPI) {
|
hw &= ~TasmotaLed_SPI; // remove SPI flag if not supported by hardware
|
||||||
hw = TasmotaLed_HW_None;
|
|
||||||
}
|
|
||||||
#endif // TASMOTALED_HARDWARE_SPI
|
#endif // TASMOTALED_HARDWARE_SPI
|
||||||
#if !TASMOTALED_HARDWARE_I2S
|
#if !TASMOTALED_HARDWARE_I2S
|
||||||
if (hw_type == TasmotaLed_I2S) {
|
hw &= ~TasmotaLed_I2S; // remove I2S flag if not supported by hardware
|
||||||
hw = TasmotaLed_HW_None;
|
|
||||||
}
|
|
||||||
#endif // TASMOTALED_HARDWARE_I2S
|
#endif // TASMOTALED_HARDWARE_I2S
|
||||||
|
|
||||||
// Step 2. If TasmotaLed_HW_Default, find a suitable scheme, RMT preferred
|
// Step 2. If TasmotaLed_HW_Default, find a suitable scheme, RMT preferred
|
||||||
#if TASMOTALED_HARDWARE_RMT
|
#if TASMOTALED_HARDWARE_RMT
|
||||||
if ((hw & 0xFF0000) == TasmotaLed_HW_Default) {
|
if (hw == TasmotaLed_HW_Default) {
|
||||||
hw = TasmotaLed_RMT;
|
hw |= TasmotaLed_RMT;
|
||||||
}
|
}
|
||||||
#endif // TASMOTALED_HARDWARE_RMT
|
#endif // TASMOTALED_HARDWARE_RMT
|
||||||
#if TASMOTALED_HARDWARE_I2S
|
#if TASMOTALED_HARDWARE_I2S
|
||||||
if ((hw & 0xFF0000) == TasmotaLed_HW_Default) {
|
if (hw == TasmotaLed_HW_Default) {
|
||||||
hw = TasmotaLed_I2S;
|
hw |= TasmotaLed_I2S;
|
||||||
}
|
}
|
||||||
#endif // TASMOTALED_HARDWARE_I2S
|
#endif // TASMOTALED_HARDWARE_I2S
|
||||||
#if TASMOTALED_HARDWARE_SPI
|
#if TASMOTALED_HARDWARE_SPI
|
||||||
if ((hw & 0xFF0000) == TasmotaLed_HW_Default) {
|
if (hw == TasmotaLed_HW_Default) {
|
||||||
hw = TasmotaLed_SPI;
|
hw |= TasmotaLed_SPI;
|
||||||
}
|
}
|
||||||
#endif // TASMOTALED_HARDWARE_SPI
|
#endif // TASMOTALED_HARDWARE_SPI
|
||||||
return hw;
|
return hw;
|
||||||
|
@ -75,22 +68,30 @@ TasmotaLEDPusher * TasmotaLEDPusher::Create(uint32_t hw, int8_t gpio) {
|
||||||
|
|
||||||
hw = TasmotaLEDPusher::ResolveHardware(hw);
|
hw = TasmotaLEDPusher::ResolveHardware(hw);
|
||||||
|
|
||||||
switch (hw & 0XFF0000) {
|
|
||||||
#if TASMOTALED_HARDWARE_RMT
|
#if TASMOTALED_HARDWARE_RMT
|
||||||
case TasmotaLed_RMT:
|
if (pusher == nullptr && (hw & TasmotaLed_RMT)) {
|
||||||
pusher = new TasmotaLEDPusherRMT(gpio);
|
pusher = new TasmotaLEDPusherRMT(gpio);
|
||||||
|
if (pusher->Initialized()) {
|
||||||
AddLog(LOG_LEVEL_DEBUG, "LED: RMT gpio %i", gpio);
|
AddLog(LOG_LEVEL_DEBUG, "LED: RMT gpio %i", gpio);
|
||||||
break;
|
} else {
|
||||||
|
AddLog(LOG_LEVEL_INFO, "LED: Error create %s bus failed %i err=%i", "RMT", gpio, pusher->Error());
|
||||||
|
delete pusher;
|
||||||
|
pusher = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif // TASMOTALED_HARDWARE_RMT
|
#endif // TASMOTALED_HARDWARE_RMT
|
||||||
#if TASMOTALED_HARDWARE_SPI
|
#if TASMOTALED_HARDWARE_SPI
|
||||||
case TasmotaLed_SPI:
|
if (pusher == nullptr && (hw & TasmotaLed_SPI)) {
|
||||||
pusher = new TasmotaLEDPusherSPI(gpio);
|
pusher = new TasmotaLEDPusherSPI(gpio);
|
||||||
|
if (pusher->Initialized()) {
|
||||||
AddLog(LOG_LEVEL_DEBUG, "LED: SPI gpio %i", gpio);
|
AddLog(LOG_LEVEL_DEBUG, "LED: SPI gpio %i", gpio);
|
||||||
break;
|
} else {
|
||||||
#endif // TASMOTALED_HARDWARE_SPI
|
AddLog(LOG_LEVEL_INFO, "LED: Error create %s bus failed %i err=%i", "SPI", gpio, pusher->Error());
|
||||||
default:
|
delete pusher;
|
||||||
break;
|
pusher = nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif // TASMOTALED_HARDWARE_SPI
|
||||||
return pusher;
|
return pusher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,9 +80,11 @@ typedef struct TasmotaLED_Timing {
|
||||||
\*******************************************************************************************/
|
\*******************************************************************************************/
|
||||||
class TasmotaLEDPusher {
|
class TasmotaLEDPusher {
|
||||||
public:
|
public:
|
||||||
TasmotaLEDPusher() : _pixel_count(0), _pixel_size(0), _led_timing(nullptr) {};
|
TasmotaLEDPusher() : _initialized(false), _err(ESP_OK), _pixel_count(0), _pixel_size(0), _led_timing(nullptr) {};
|
||||||
virtual ~TasmotaLEDPusher() {};
|
virtual ~TasmotaLEDPusher() {};
|
||||||
|
|
||||||
|
bool Initialized(void) const { return _initialized; }
|
||||||
|
esp_err_t Error(void) const { return _err; }
|
||||||
virtual bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) {
|
virtual bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) {
|
||||||
_pixel_count = pixel_count;
|
_pixel_count = pixel_count;
|
||||||
_pixel_size = pixel_size;
|
_pixel_size = pixel_size;
|
||||||
|
@ -96,6 +98,8 @@ public:
|
||||||
static TasmotaLEDPusher * Create(uint32_t hw, int8_t gpio); // create instance for the provided type, or nullptr if failed
|
static TasmotaLEDPusher * Create(uint32_t hw, int8_t gpio); // create instance for the provided type, or nullptr if failed
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool _initialized; // did the hardware got correctly initialized
|
||||||
|
esp_err_t _err;
|
||||||
uint16_t _pixel_count;
|
uint16_t _pixel_count;
|
||||||
uint16_t _pixel_size;
|
uint16_t _pixel_size;
|
||||||
const TasmotaLED_Timing * _led_timing;
|
const TasmotaLED_Timing * _led_timing;
|
||||||
|
@ -110,7 +114,7 @@ protected:
|
||||||
#include "driver/rmt_tx.h"
|
#include "driver/rmt_tx.h"
|
||||||
class TasmotaLEDPusherRMT : public TasmotaLEDPusher {
|
class TasmotaLEDPusherRMT : public TasmotaLEDPusher {
|
||||||
public:
|
public:
|
||||||
TasmotaLEDPusherRMT(int8_t pin) : _pin(pin) {};
|
TasmotaLEDPusherRMT(int8_t pin);
|
||||||
~TasmotaLEDPusherRMT();
|
~TasmotaLEDPusherRMT();
|
||||||
|
|
||||||
bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) override;
|
bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) override;
|
||||||
|
@ -144,7 +148,7 @@ typedef struct led_strip_spi_obj_t {
|
||||||
|
|
||||||
class TasmotaLEDPusherSPI : public TasmotaLEDPusher {
|
class TasmotaLEDPusherSPI : public TasmotaLEDPusher {
|
||||||
public:
|
public:
|
||||||
TasmotaLEDPusherSPI(int8_t pin) : _pin(pin), _spi_strip({}) {};
|
TasmotaLEDPusherSPI(int8_t pin);
|
||||||
~TasmotaLEDPusherSPI();
|
~TasmotaLEDPusherSPI();
|
||||||
|
|
||||||
bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) override;
|
bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) override;
|
||||||
|
@ -154,7 +158,8 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int8_t _pin;
|
int8_t _pin;
|
||||||
struct led_strip_spi_obj_t _spi_strip;
|
struct led_strip_spi_obj_t _spi_strip = {};;
|
||||||
|
const bool _with_dma = true;
|
||||||
};
|
};
|
||||||
#endif // TASMOTALED_HARDWARE_SPI
|
#endif // TASMOTALED_HARDWARE_SPI
|
||||||
|
|
||||||
|
|
|
@ -155,9 +155,7 @@ TasmotaLEDPusherRMT::~TasmotaLEDPusherRMT() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TasmotaLEDPusherRMT::Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) {
|
TasmotaLEDPusherRMT::TasmotaLEDPusherRMT(int8_t pin) : _pin(pin) {
|
||||||
TasmotaLEDPusher::Begin(pixel_count, pixel_size, led_timing);
|
|
||||||
|
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
rmt_tx_channel_config_t config = {};
|
rmt_tx_channel_config_t config = {};
|
||||||
config.clk_src = RMT_CLK_SRC_DEFAULT;
|
config.clk_src = RMT_CLK_SRC_DEFAULT;
|
||||||
|
@ -168,11 +166,15 @@ bool TasmotaLEDPusherRMT::Begin(uint16_t pixel_count, uint16_t pixel_size, const
|
||||||
config.flags.invert_out = false; // do not invert output signal
|
config.flags.invert_out = false; // do not invert output signal
|
||||||
config.flags.with_dma = false; // do not need DMA backend
|
config.flags.with_dma = false; // do not need DMA backend
|
||||||
|
|
||||||
ret = rmt_new_tx_channel(&config, &_channel);
|
_err = rmt_new_tx_channel(&config, &_channel);
|
||||||
if (ret != ESP_OK) {
|
if (_err == ESP_OK) {
|
||||||
AddLog(LOG_LEVEL_INFO, "RMT: cannot initialize Gpio %i err=%i", _pin, ret);
|
_initialized = true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TasmotaLEDPusherRMT::Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) {
|
||||||
|
if (!_initialized) { return false; }
|
||||||
|
TasmotaLEDPusher::Begin(pixel_count, pixel_size, led_timing);
|
||||||
led_strip_encoder_config_t encoder_config = {
|
led_strip_encoder_config_t encoder_config = {
|
||||||
.resolution = RMT_LED_STRIP_RESOLUTION_HZ,
|
.resolution = RMT_LED_STRIP_RESOLUTION_HZ,
|
||||||
};
|
};
|
||||||
|
@ -198,13 +200,13 @@ bool TasmotaLEDPusherRMT::Begin(uint16_t pixel_count, uint16_t pixel_size, const
|
||||||
.level1 = 1,
|
.level1 = 1,
|
||||||
};
|
};
|
||||||
// AddLog(LOG_LEVEL_INFO, "RMT: RmtBit0 0x%08X RmtBit1 0x%08X RmtReset 0x%08X", RmtBit0.val, RmtBit1.val, RmtReset.val);
|
// AddLog(LOG_LEVEL_INFO, "RMT: RmtBit0 0x%08X RmtBit1 0x%08X RmtReset 0x%08X", RmtBit0.val, RmtBit1.val, RmtReset.val);
|
||||||
ret = rmt_new_led_strip_encoder(&encoder_config, &_led_encoder, RmtBit0, RmtBit1, RmtReset);
|
_err = rmt_new_led_strip_encoder(&encoder_config, &_led_encoder, RmtBit0, RmtBit1, RmtReset);
|
||||||
if (ret != ESP_OK) {
|
if (_err != ESP_OK) {
|
||||||
// AddLog(LOG_LEVEL_INFO, "RMT: cannot initialize led strip encoder err=%i", ret);
|
// AddLog(LOG_LEVEL_INFO, "RMT: cannot initialize led strip encoder err=%i", ret);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ret = rmt_enable(_channel);
|
_err = rmt_enable(_channel);
|
||||||
if (ret != ESP_OK) {
|
if (_err != ESP_OK) {
|
||||||
// AddLog(LOG_LEVEL_INFO, "RMT: cannot enable channel err=%i", ret);
|
// AddLog(LOG_LEVEL_INFO, "RMT: cannot enable channel err=%i", ret);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -212,7 +214,7 @@ bool TasmotaLEDPusherRMT::Begin(uint16_t pixel_count, uint16_t pixel_size, const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TasmotaLEDPusherRMT::CanShow(void) {
|
bool TasmotaLEDPusherRMT::CanShow(void) {
|
||||||
if (_channel) {
|
if (_channel && _initialized) {
|
||||||
return (ESP_OK == rmt_tx_wait_all_done(_channel, 0));
|
return (ESP_OK == rmt_tx_wait_all_done(_channel, 0));
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -220,6 +222,7 @@ bool TasmotaLEDPusherRMT::CanShow(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TasmotaLEDPusherRMT::Push(uint8_t *buf) {
|
bool TasmotaLEDPusherRMT::Push(uint8_t *buf) {
|
||||||
|
if (!_initialized) { return false; }
|
||||||
|
|
||||||
// wait for not actively sending data
|
// wait for not actively sending data
|
||||||
// this will time out at 1 second, an arbitrarily long period of time
|
// this will time out at 1 second, an arbitrarily long period of time
|
||||||
|
|
|
@ -95,31 +95,9 @@ TasmotaLEDPusherSPI::~TasmotaLEDPusherSPI() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TasmotaLEDPusherSPI::Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) {
|
TasmotaLEDPusherSPI::TasmotaLEDPusherSPI(int8_t pin) : _pin(pin) {
|
||||||
TasmotaLEDPusher::Begin(pixel_count, pixel_size, led_timing);
|
|
||||||
_spi_strip.bytes_per_pixel = _pixel_size;
|
|
||||||
_spi_strip.strip_len = _pixel_count;
|
|
||||||
|
|
||||||
esp_err_t err = ESP_OK;
|
|
||||||
uint32_t mem_caps = MALLOC_CAP_DEFAULT;
|
|
||||||
// spi_clock_source_t clk_src = SPI_CLK_SRC_DEFAULT;
|
|
||||||
spi_bus_config_t spi_bus_cfg;
|
|
||||||
spi_device_interface_config_t spi_dev_cfg;
|
|
||||||
spi_host_device_t spi_host = SPI2_HOST;
|
spi_host_device_t spi_host = SPI2_HOST;
|
||||||
bool with_dma = true; /// TODO: pass value or compute based on pixelcount
|
spi_bus_config_t spi_bus_cfg = {
|
||||||
int clock_resolution_khz = 0;
|
|
||||||
|
|
||||||
if (with_dma) { // TODO
|
|
||||||
// DMA buffer must be placed in internal SRAM
|
|
||||||
mem_caps |= MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA;
|
|
||||||
}
|
|
||||||
_spi_strip.pixel_buf = (uint8_t *)heap_caps_calloc(1, _pixel_count * _pixel_size * SPI_BYTES_PER_COLOR_BYTE, mem_caps);
|
|
||||||
if (_spi_strip.pixel_buf == nullptr) {
|
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("LED: Error no mem for spi strip"));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
spi_bus_cfg = {
|
|
||||||
.mosi_io_num = _pin,
|
.mosi_io_num = _pin,
|
||||||
//Only use MOSI to generate the signal, set -1 when other pins are not used.
|
//Only use MOSI to generate the signal, set -1 when other pins are not used.
|
||||||
.miso_io_num = -1,
|
.miso_io_num = -1,
|
||||||
|
@ -128,12 +106,35 @@ bool TasmotaLEDPusherSPI::Begin(uint16_t pixel_count, uint16_t pixel_size, const
|
||||||
.quadhd_io_num = -1,
|
.quadhd_io_num = -1,
|
||||||
.max_transfer_sz = _pixel_count * _pixel_size * SPI_BYTES_PER_COLOR_BYTE,
|
.max_transfer_sz = _pixel_count * _pixel_size * SPI_BYTES_PER_COLOR_BYTE,
|
||||||
};
|
};
|
||||||
err = spi_bus_initialize(spi_host, &spi_bus_cfg, with_dma ? SPI_DMA_CH_AUTO : SPI_DMA_DISABLED);
|
_err = spi_bus_initialize(spi_host, &spi_bus_cfg, _with_dma ? SPI_DMA_CH_AUTO : SPI_DMA_DISABLED);
|
||||||
if (err != ESP_OK) {
|
if (_err == ESP_OK) {
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("LED: Error create SPI bus failed"));
|
_spi_strip.spi_host = spi_host; // confirmed working, so keep it's value to free it later
|
||||||
|
_initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TasmotaLEDPusherSPI::Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) {
|
||||||
|
if (!_initialized) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TasmotaLEDPusher::Begin(pixel_count, pixel_size, led_timing);
|
||||||
|
_spi_strip.bytes_per_pixel = _pixel_size;
|
||||||
|
_spi_strip.strip_len = _pixel_count;
|
||||||
|
|
||||||
|
uint32_t mem_caps = MALLOC_CAP_DEFAULT;
|
||||||
|
// spi_clock_source_t clk_src = SPI_CLK_SRC_DEFAULT;
|
||||||
|
spi_device_interface_config_t spi_dev_cfg;
|
||||||
|
int clock_resolution_khz = 0;
|
||||||
|
|
||||||
|
if (_with_dma) { // TODO
|
||||||
|
// DMA buffer must be placed in internal SRAM
|
||||||
|
mem_caps |= MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA;
|
||||||
|
}
|
||||||
|
_spi_strip.pixel_buf = (uint8_t *)heap_caps_calloc(1, _pixel_count * _pixel_size * SPI_BYTES_PER_COLOR_BYTE, mem_caps);
|
||||||
|
if (_spi_strip.pixel_buf == nullptr) {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("LED: Error no mem for spi strip"));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
_spi_strip.spi_host = spi_host; // confirmed working, so keep it's value to free it later
|
|
||||||
|
|
||||||
spi_dev_cfg = {
|
spi_dev_cfg = {
|
||||||
.command_bits = 0,
|
.command_bits = 0,
|
||||||
|
@ -146,14 +147,14 @@ bool TasmotaLEDPusherSPI::Begin(uint16_t pixel_count, uint16_t pixel_size, const
|
||||||
.spics_io_num = -1,
|
.spics_io_num = -1,
|
||||||
.queue_size = LED_STRIP_SPI_DEFAULT_TRANS_QUEUE_SIZE,
|
.queue_size = LED_STRIP_SPI_DEFAULT_TRANS_QUEUE_SIZE,
|
||||||
};
|
};
|
||||||
err = spi_bus_add_device(_spi_strip.spi_host, &spi_dev_cfg, &_spi_strip.spi_device);
|
_err = spi_bus_add_device(_spi_strip.spi_host, &spi_dev_cfg, &_spi_strip.spi_device);
|
||||||
if (err != ESP_OK) {
|
if (_err != ESP_OK) {
|
||||||
// AddLog(LOG_LEVEL_INFO, "LED: Error failed to add spi device");
|
// AddLog(LOG_LEVEL_INFO, "LED: Error failed to add spi device");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
spi_device_get_actual_freq(_spi_strip.spi_device, &clock_resolution_khz);
|
_err = spi_device_get_actual_freq(_spi_strip.spi_device, &clock_resolution_khz);
|
||||||
if (err != ESP_OK) {
|
if (_err != ESP_OK) {
|
||||||
// AddLog(LOG_LEVEL_INFO, "LED: Error failed to get spi frequency");
|
// AddLog(LOG_LEVEL_INFO, "LED: Error failed to get spi frequency");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -163,7 +164,6 @@ bool TasmotaLEDPusherSPI::Begin(uint16_t pixel_count, uint16_t pixel_size, const
|
||||||
// AddLog(LOG_LEVEL_INFO, "LED: Error unsupported clock resolution: %dKHz", clock_resolution_khz);
|
// AddLog(LOG_LEVEL_INFO, "LED: Error unsupported clock resolution: %dKHz", clock_resolution_khz);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
err:
|
err:
|
||||||
if (_spi_strip.spi_device) {
|
if (_spi_strip.spi_device) {
|
||||||
|
@ -172,15 +172,16 @@ err:
|
||||||
if (_spi_strip.spi_host) {
|
if (_spi_strip.spi_host) {
|
||||||
spi_bus_free(_spi_strip.spi_host);
|
spi_bus_free(_spi_strip.spi_host);
|
||||||
}
|
}
|
||||||
|
_initialized = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TasmotaLEDPusherSPI::CanShow(void) {
|
bool TasmotaLEDPusherSPI::CanShow(void) {
|
||||||
return true; // TODO
|
return _initialized; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TasmotaLEDPusherSPI::Push(uint8_t *buf) {
|
bool TasmotaLEDPusherSPI::Push(uint8_t *buf) {
|
||||||
|
if (!_initialized) { return false; }
|
||||||
if (CanShow()) {
|
if (CanShow()) {
|
||||||
led_strip_transmit_buffer(&_spi_strip, buf);
|
led_strip_transmit_buffer(&_spi_strip, buf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ class Matter_UI
|
||||||
# webserver.content_send("<p><form id=ac action='matterc' style='display: block;' method='get'><button>Configure Matter</button></form></p>")
|
# webserver.content_send("<p><form id=ac action='matterc' style='display: block;' method='get'><button>Configure Matter</button></form></p>")
|
||||||
webserver.content_send("<p><form id=ac action='matterc' style='display: block;' method='get'><button>")
|
webserver.content_send("<p><form id=ac action='matterc' style='display: block;' method='get'><button>")
|
||||||
webserver.content_send(matter._LOGO)
|
webserver.content_send(matter._LOGO)
|
||||||
webserver.content_send(" Configure Matter</button></form></p>")
|
webserver.content_send(" Matter</button></form></p>")
|
||||||
end
|
end
|
||||||
|
|
||||||
#- ---------------------------------------------------------------------- -#
|
#- ---------------------------------------------------------------------- -#
|
||||||
|
|
|
@ -191,7 +191,7 @@ static const bvalue be_ktab_class_Matter_UI[232] = {
|
||||||
/* K182 */ be_nested_str_weak(_X3C_X2Ftable_X3E_X3Chr_X3E),
|
/* K182 */ be_nested_str_weak(_X3C_X2Ftable_X3E_X3Chr_X3E),
|
||||||
/* K183 */ be_nested_str_weak(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27matterc_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3E),
|
/* K183 */ be_nested_str_weak(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27matterc_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3E),
|
||||||
/* K184 */ be_nested_str_weak(_LOGO),
|
/* K184 */ be_nested_str_weak(_LOGO),
|
||||||
/* K185 */ be_nested_str_weak(_X20Configure_X20Matter_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E),
|
/* K185 */ be_nested_str_weak(_X20Matter_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E),
|
||||||
/* K186 */ be_nested_str_weak(get_plugin_class_displayname),
|
/* K186 */ be_nested_str_weak(get_plugin_class_displayname),
|
||||||
/* K187 */ be_nested_str_weak(Matter_X20Advanced_X20Configuration),
|
/* K187 */ be_nested_str_weak(Matter_X20Advanced_X20Configuration),
|
||||||
/* K188 */ be_nested_str_weak(show_passcode_form),
|
/* K188 */ be_nested_str_weak(show_passcode_form),
|
||||||
|
|
|
@ -1148,6 +1148,8 @@ int GetCommandCode(char* destination, size_t destination_size, const char* needl
|
||||||
|
|
||||||
bool DecodeCommand(const char* haystack, void (* const MyCommand[])(void), const uint8_t *synonyms = nullptr);
|
bool DecodeCommand(const char* haystack, void (* const MyCommand[])(void), const uint8_t *synonyms = nullptr);
|
||||||
bool DecodeCommand(const char* haystack, void (* const MyCommand[])(void), const uint8_t *synonyms) {
|
bool DecodeCommand(const char* haystack, void (* const MyCommand[])(void), const uint8_t *synonyms) {
|
||||||
|
SHOW_FREE_MEM(PSTR("DecodeCommand"));
|
||||||
|
|
||||||
GetTextIndexed(XdrvMailbox.command, CMDSZ, 0, haystack); // Get prefix if available
|
GetTextIndexed(XdrvMailbox.command, CMDSZ, 0, haystack); // Get prefix if available
|
||||||
int prefix_length = strlen(XdrvMailbox.command);
|
int prefix_length = strlen(XdrvMailbox.command);
|
||||||
if (prefix_length) {
|
if (prefix_length) {
|
||||||
|
@ -2680,9 +2682,7 @@ void AddLogData(uint32_t loglevel, const char* log_data, const char* log_data_pa
|
||||||
}
|
}
|
||||||
snprintf_P(TasmotaGlobal.log_buffer, LOG_BUFFER_SIZE, PSTR("%s%c%c%s%s%s%s\1"),
|
snprintf_P(TasmotaGlobal.log_buffer, LOG_BUFFER_SIZE, PSTR("%s%c%c%s%s%s%s\1"),
|
||||||
TasmotaGlobal.log_buffer, TasmotaGlobal.log_buffer_pointer++, '0'+loglevel, mxtime, log_data, log_data_payload, log_data_retained);
|
TasmotaGlobal.log_buffer, TasmotaGlobal.log_buffer_pointer++, '0'+loglevel, mxtime, log_data, log_data_payload, log_data_retained);
|
||||||
if (too_long) {
|
if (too_long) { free(too_long); }
|
||||||
free(too_long);
|
|
||||||
}
|
|
||||||
TasmotaGlobal.log_buffer_pointer &= 0xFF;
|
TasmotaGlobal.log_buffer_pointer &= 0xFF;
|
||||||
if (!TasmotaGlobal.log_buffer_pointer) {
|
if (!TasmotaGlobal.log_buffer_pointer) {
|
||||||
TasmotaGlobal.log_buffer_pointer++; // Index 0 is not allowed as it is the end of char string
|
TasmotaGlobal.log_buffer_pointer++; // Index 0 is not allowed as it is the end of char string
|
||||||
|
|
|
@ -702,8 +702,7 @@ void MqttPublishLoggingAsync(bool refresh) {
|
||||||
|
|
||||||
void MqttPublishPayload(const char* topic, const char* payload, uint32_t binary_length, bool retained) {
|
void MqttPublishPayload(const char* topic, const char* payload, uint32_t binary_length, bool retained) {
|
||||||
// Publish <topic> payload string or binary when binary_length set with optional retained
|
// Publish <topic> payload string or binary when binary_length set with optional retained
|
||||||
|
SHOW_FREE_MEM(PSTR("MqttPublishPayload"));
|
||||||
SHOW_FREE_MEM(PSTR("MqttPublish"));
|
|
||||||
|
|
||||||
bool binary_data = (binary_length > 0);
|
bool binary_data = (binary_length > 0);
|
||||||
if (!binary_data) {
|
if (!binary_data) {
|
||||||
|
@ -794,14 +793,30 @@ void MqttPublishPayloadPrefixTopic_P(uint32_t prefix, const char* subtopic, cons
|
||||||
prefix 5 = stat using subtopic or RESULT
|
prefix 5 = stat using subtopic or RESULT
|
||||||
prefix 6 = tele using subtopic or RESULT
|
prefix 6 = tele using subtopic or RESULT
|
||||||
*/
|
*/
|
||||||
char romram[64];
|
SHOW_FREE_MEM(PSTR("MqttPublishPayloadPrefixTopic_P"));
|
||||||
|
/*
|
||||||
|
char romram[64]; // Claim 64 bytes from 4k stack
|
||||||
snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings->flag.mqtt_response) ? S_RSLT_RESULT : subtopic); // SetOption4 - Switch between MQTT RESULT or COMMAND
|
snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings->flag.mqtt_response) ? S_RSLT_RESULT : subtopic); // SetOption4 - Switch between MQTT RESULT or COMMAND
|
||||||
UpperCase(romram, romram);
|
UpperCase(romram, romram);
|
||||||
|
|
||||||
prefix &= 3;
|
prefix &= 3;
|
||||||
char stopic[TOPSZ];
|
char stopic[TOPSZ]; // Claim TOPSZ bytes from 4k stack
|
||||||
GetTopic_P(stopic, prefix, TasmotaGlobal.mqtt_topic, romram);
|
GetTopic_P(stopic, prefix, TasmotaGlobal.mqtt_topic, romram);
|
||||||
MqttPublishPayload(stopic, payload, binary_length, retained);
|
MqttPublishPayload(stopic, payload, binary_length, retained);
|
||||||
|
*/
|
||||||
|
// Reduce important stack usage by 200 bytes but adding 52 bytes code
|
||||||
|
char *romram = (char*)malloc(64); // Claim 64 bytes from 20k heap
|
||||||
|
strcpy_P(romram, ((prefix > 3) && !Settings->flag.mqtt_response) ? S_RSLT_RESULT : subtopic);
|
||||||
|
UpperCase(romram, romram);
|
||||||
|
|
||||||
|
prefix &= 3;
|
||||||
|
char *htopic = (char*)malloc(TOPSZ); // Claim TOPSZ bytes from 16k heap
|
||||||
|
GetTopic_P(htopic, prefix, TasmotaGlobal.mqtt_topic, romram);
|
||||||
|
char stopic[strlen_P(htopic) +1]; // Claim only strlen_P bytes from 4k stack
|
||||||
|
strcpy_P(stopic, htopic);
|
||||||
|
free(htopic); // Free 16k heap from TOPSZ bytes
|
||||||
|
free(romram); // Free 16k heap from 64 bytes
|
||||||
|
MqttPublishPayload(stopic, payload, binary_length, retained);
|
||||||
|
|
||||||
#if defined(USE_MQTT_AWS_IOT) || defined(USE_MQTT_AWS_IOT_LIGHT)
|
#if defined(USE_MQTT_AWS_IOT) || defined(USE_MQTT_AWS_IOT_LIGHT)
|
||||||
if ((prefix > 0) && (Settings->flag4.awsiot_shadow) && (Mqtt.connected)) { // placeholder for SetOptionXX
|
if ((prefix > 0) && (Settings->flag4.awsiot_shadow) && (Mqtt.connected)) { // placeholder for SetOptionXX
|
||||||
|
@ -857,6 +872,8 @@ void MqttPublishPayloadPrefixTopicRulesProcess_P(uint32_t prefix, const char* su
|
||||||
|
|
||||||
void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained) {
|
void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained) {
|
||||||
// Publish <prefix>/<device>/<RESULT or <subtopic>> default ResponseData string with optional retained
|
// Publish <prefix>/<device>/<RESULT or <subtopic>> default ResponseData string with optional retained
|
||||||
|
SHOW_FREE_MEM(PSTR("MqttPublishPrefixTopic_P"));
|
||||||
|
|
||||||
MqttPublishPayloadPrefixTopic_P(prefix, subtopic, ResponseData(), 0, retained);
|
MqttPublishPayloadPrefixTopic_P(prefix, subtopic, ResponseData(), 0, retained);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -868,6 +885,8 @@ void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic) {
|
||||||
void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic, bool retained) {
|
void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic, bool retained) {
|
||||||
// Publish <prefix>/<device>/<RESULT or <subtopic>> default ResponseData string with optional retained
|
// Publish <prefix>/<device>/<RESULT or <subtopic>> default ResponseData string with optional retained
|
||||||
// then process rules
|
// then process rules
|
||||||
|
SHOW_FREE_MEM(PSTR("MqttPublishPrefixTopicRulesProcess_P"));
|
||||||
|
|
||||||
MqttPublishPrefixTopic_P(prefix, subtopic, retained);
|
MqttPublishPrefixTopic_P(prefix, subtopic, retained);
|
||||||
XdrvRulesProcess(0);
|
XdrvRulesProcess(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,12 +186,6 @@ extern "C" {
|
||||||
pixels_size = strip->PixelCount() * strip->PixelSize();
|
pixels_size = strip->PixelCount() * strip->PixelSize();
|
||||||
update_completed = strip->CanShow();
|
update_completed = strip->CanShow();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for RMT/I2S to complete fixes distortion due to analogRead
|
|
||||||
// 1ms is needed for 96 bytes
|
|
||||||
if (!update_completed) {
|
|
||||||
SystemBusyDelay((pixels_size + 95) / 96);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3: // # 03 : CanShow void -> bool
|
case 3: // # 03 : CanShow void -> bool
|
||||||
|
|
|
@ -95,20 +95,8 @@ const uint16_t kTasLed_PixelWhite = TasmotaLed_xxxW;
|
||||||
|
|
||||||
const uint16_t kTasLed_Type = kTasLed_PixelSize | kTasLed_PixelOrder | kTasLed_PixelWhite | kTasLed_Timing;
|
const uint16_t kTasLed_Type = kTasLed_PixelSize | kTasLed_PixelOrder | kTasLed_PixelWhite | kTasLed_Timing;
|
||||||
|
|
||||||
// select hardware acceleration - bitbanging is not supported on ESP32 due to interference of interrupts
|
// select hardware acceleration - bitbanging is not supported on ESP32 due to interference of interrupts - use default
|
||||||
#if CONFIG_IDF_TARGET_ESP32C2
|
const uint32_t kTasLed_Hardware = TasmotaLed_HW_Default; // use whatever is available
|
||||||
const uint32_t kTasLed_Hardware = TasmotaLed_SPI; // no I2S for the C2
|
|
||||||
#else // all other ESP32 variants
|
|
||||||
#if defined(USE_WS2812_DMA)
|
|
||||||
const uint32_t kTasLed_Hardware = TasmotaLed_RMT; // default DMA to RMT
|
|
||||||
#elif defined(USE_WS2812_RMT)
|
|
||||||
const uint32_t kTasLed_Hardware = TasmotaLed_RMT; // default DMA to RMT
|
|
||||||
#elif defined(USE_WS2812_I2S)
|
|
||||||
const uint32_t kTasLed_Hardware = TasmotaLed_I2S; // I2S
|
|
||||||
#else
|
|
||||||
const uint32_t kTasLed_Hardware = TasmotaLed_RMT; // default DMA to RMT
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (USE_WS2812_HARDWARE == NEO_HW_P9813)
|
#if (USE_WS2812_HARDWARE == NEO_HW_P9813)
|
||||||
#error "P9813 is not supported by this library"
|
#error "P9813 is not supported by this library"
|
||||||
|
@ -186,12 +174,6 @@ long wsmap(long x, long in_min, long in_max, long out_min, long out_max) {
|
||||||
|
|
||||||
void Ws2812LibStripShow(void) {
|
void Ws2812LibStripShow(void) {
|
||||||
strip->Show();
|
strip->Show();
|
||||||
|
|
||||||
#if defined(USE_WS2812_DMA) || defined(USE_WS2812_RMT) || defined(USE_WS2812_I2S)
|
|
||||||
// Wait for DMA/RMT/I2S to complete fixes distortion due to analogRead
|
|
||||||
// delay((Settings->light_pixels >> 6) +1); // 256 / 64 = 4 +1 = 5
|
|
||||||
SystemBusyDelay( (Settings->light_pixels + 31) >> 5); // (256 + 32) / 32 = 8
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ws2812StripShow(void)
|
void Ws2812StripShow(void)
|
||||||
|
|
|
@ -1105,10 +1105,10 @@ bool XdrvRulesProcess(bool teleperiod) {
|
||||||
|
|
||||||
#ifdef USE_DEBUG_DRIVER
|
#ifdef USE_DEBUG_DRIVER
|
||||||
void ShowFreeMem(const char *where) {
|
void ShowFreeMem(const char *where) {
|
||||||
char stemp[30];
|
char *XdrvMailboxData = XdrvMailbox.data;
|
||||||
snprintf_P(stemp, sizeof(stemp), where);
|
XdrvMailbox.data = (char*)where;
|
||||||
XdrvMailbox.data = stemp;
|
|
||||||
XdrvCall(FUNC_FREE_MEM);
|
XdrvCall(FUNC_FREE_MEM);
|
||||||
|
XdrvMailbox.data = XdrvMailboxData;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue