diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fd561c7b..b3d0237fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - Support for ESP32 Two-Wire Automotive Interface (TWAI) or Controller Area Network (CAN) busses - Support for Senseair S88 CO2 sensor (#22733) +- TasmotaLED change dynamically the number of pixels ### Breaking Changed diff --git a/lib/lib_basic/TasmotaLED/src/TasmotaLED.cpp b/lib/lib_basic/TasmotaLED/src/TasmotaLED.cpp index d323c20ab..c64aff9db 100644 --- a/lib/lib_basic/TasmotaLED/src/TasmotaLED.cpp +++ b/lib/lib_basic/TasmotaLED/src/TasmotaLED.cpp @@ -109,6 +109,22 @@ TasmotaLED::~TasmotaLED() { _buf_show = nullptr; } +void TasmotaLED::SetPixelCount(uint16_t num_leds) { + if (num_leds != _pixel_count) { + _pixel_count = num_leds; + delete _buf_work; + _buf_work = new uint8_t[_pixel_count * _pixel_size]; + memset(_buf_work, 0, _pixel_count * _pixel_size); + delete _buf_show; + _buf_show = new uint8_t[_pixel_count * _pixel_size]; + memset(_buf_show, 0, _pixel_count * _pixel_size); + if (_pusher) { + _pusher->SetPixelCount(_pixel_count); + } + } +} + + // Color is passed as 0xWWRRGGBB and copied as WWRRGGBB in _buf_work void TasmotaLED::ClearTo(uint32_t wrgb, int32_t first, int32_t last) { // adjust first and last to be in range of 0 to _pixel_count-1 diff --git a/lib/lib_basic/TasmotaLED/src/TasmotaLED.h b/lib/lib_basic/TasmotaLED/src/TasmotaLED.h index dd2fb8dc9..e31c8b826 100644 --- a/lib/lib_basic/TasmotaLED/src/TasmotaLED.h +++ b/lib/lib_basic/TasmotaLED/src/TasmotaLED.h @@ -91,6 +91,8 @@ public: TasmotaLED(uint16_t type, uint16_t num_leds); ~TasmotaLED(); + void SetPixelCount(uint16_t num_leds); + bool Begin(void); void SetPusher(TasmotaLEDPusher *pusher); // needs to be called before `Begin()`, sets the hardware implementation void Show(void); // pushes the pixels to the LED strip diff --git a/lib/lib_basic/TasmotaLED/src/TasmotaLEDPusher.h b/lib/lib_basic/TasmotaLED/src/TasmotaLEDPusher.h index 89b402997..f25b06cf5 100644 --- a/lib/lib_basic/TasmotaLED/src/TasmotaLEDPusher.h +++ b/lib/lib_basic/TasmotaLED/src/TasmotaLEDPusher.h @@ -93,6 +93,7 @@ public: } virtual bool Push(uint8_t *buf) = 0; virtual bool CanShow(void) = 0; + virtual bool SetPixelCount(uint16_t pixel_count) = 0; static uint32_t ResolveHardware(uint32_t hw); // convert to the appropriate hardware acceleration based on capacities of the SOC static TasmotaLEDPusher * Create(uint32_t hw, int8_t gpio); // create instance for the provided type, or nullptr if failed @@ -118,6 +119,7 @@ public: ~TasmotaLEDPusherRMT(); bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) override; + bool SetPixelCount(uint16_t pixel_count) override; bool Push(uint8_t *buf) override; bool CanShow(void) override; @@ -152,6 +154,7 @@ public: ~TasmotaLEDPusherSPI(); bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) override; + bool SetPixelCount(uint16_t pixel_count) override; bool Push(uint8_t *buf) override; bool CanShow(void) override; diff --git a/lib/lib_basic/TasmotaLED/src/TasmotaLEDPusherRMT.cpp b/lib/lib_basic/TasmotaLED/src/TasmotaLEDPusherRMT.cpp index d6ca12197..592efc047 100644 --- a/lib/lib_basic/TasmotaLED/src/TasmotaLEDPusherRMT.cpp +++ b/lib/lib_basic/TasmotaLED/src/TasmotaLEDPusherRMT.cpp @@ -213,6 +213,15 @@ bool TasmotaLEDPusherRMT::Begin(uint16_t pixel_count, uint16_t pixel_size, const return true; } +bool TasmotaLEDPusherRMT::SetPixelCount(uint16_t pixel_count) { + if (!_initialized) { return false; } + if (pixel_count > 0 && _pixel_count != pixel_count) { + _pixel_count = pixel_count; + return true; + } + return true; +} + bool TasmotaLEDPusherRMT::CanShow(void) { if (_channel && _initialized) { return (ESP_OK == rmt_tx_wait_all_done(_channel, 0)); diff --git a/lib/lib_basic/TasmotaLED/src/TasmotaLEDPusherSPI.cpp b/lib/lib_basic/TasmotaLED/src/TasmotaLEDPusherSPI.cpp index 74366ebb8..c2ebb2eb0 100644 --- a/lib/lib_basic/TasmotaLED/src/TasmotaLEDPusherSPI.cpp +++ b/lib/lib_basic/TasmotaLED/src/TasmotaLEDPusherSPI.cpp @@ -104,7 +104,7 @@ TasmotaLEDPusherSPI::TasmotaLEDPusherSPI(int8_t pin) : _pin(pin) { .sclk_io_num = -1, .quadwp_io_num = -1, .quadhd_io_num = -1, - .max_transfer_sz = _pixel_count * _pixel_size * SPI_BYTES_PER_COLOR_BYTE, + .max_transfer_sz = 0, // _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); if (_err == ESP_OK) { @@ -176,6 +176,39 @@ err: return false; } +bool TasmotaLEDPusherSPI::SetPixelCount(uint16_t pixel_count) { + if (!_initialized) { return false; } + if (pixel_count > 0 && _pixel_count != pixel_count) { + _pixel_count = pixel_count; + + if (_spi_strip.pixel_buf) { + heap_caps_free(_spi_strip.pixel_buf); + _spi_strip.pixel_buf = nullptr; + } + + _spi_strip.strip_len = _pixel_count; + uint32_t mem_caps = MALLOC_CAP_DEFAULT; + 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")); + if (_spi_strip.spi_device) { + spi_bus_remove_device(_spi_strip.spi_device); + } + if (_spi_strip.spi_host) { + spi_bus_free(_spi_strip.spi_host); + } + _initialized = false; + return false; + } + return true; + } + return true; +} + bool TasmotaLEDPusherSPI::CanShow(void) { return _initialized; // TODO }