/* TasmotaLEDPusher.h - Abstract class for Leds pusher (RMT, SPI, I2S...) Copyright (C) 2024 Stephan Hadinger This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef __TASMOTALEDPUSHER_H__ #define __TASMOTALEDPUSHER_H__ #include // Below are flags to enable of disable each hardware support: RMT, I2S, SPI // By default, only enable RMT support, and SPI is used as fallback if no protocol works // // Use de defines below: // #define TASMOTALED_HARDWARE_RMT 0/1 // #define TASMOTALED_HARDWARE_I2S 0/1 // #define TASMOTALED_HARDWARE_SPI 0/1 // #ifndef TASMOTALED_HARDWARE_RMT #define TASMOTALED_HARDWARE_RMT 1 #endif #ifndef TASMOTALED_HARDWARE_I2S #define TASMOTALED_HARDWARE_I2S 0 #endif #ifndef TASMOTALED_HARDWARE_SPI #define TASMOTALED_HARDWARE_SPI 0 #endif // Disable any hardware if not supported by the SOC #if TASMOTALED_HARDWARE_RMT && !defined(SOC_RMT_SUPPORTED) #undef TASMOTALED_HARDWARE_RMT #define TASMOTALED_HARDWARE_RMT 0 #endif #if TASMOTALED_HARDWARE_I2S && !defined(SOC_I2S_SUPPORTED) #undef TASMOTALED_HARDWARE_I2S #define TASMOTALED_HARDWARE_I2S 0 #endif #if TASMOTALED_HARDWARE_SPI && !defined(SOC_GPSPI_SUPPORTED) #undef TASMOTALED_HARDWARE_SPI #define TASMOTALED_HARDWARE_SPI 0 #endif // if no protocol is defined, use SPI as fallback #if !TASMOTALED_HARDWARE_RMT && !TASMOTALED_HARDWARE_I2S && !TASMOTALED_HARDWARE_SPI #undef TASMOTALED_HARDWARE_SPI #define TASMOTALED_HARDWARE_SPI 1 #endif // Timing structure for LEDS - in nanoseconds // It is passed by TasmotaLed to the pushers typedef struct TasmotaLED_Timing { uint16_t T0H, T0L, T1H, T1L; uint32_t Reset; } TasmotaLED_Timing; /*******************************************************************************************\ * class TasmotaLEDPusher * * This is an virtual abstract class for Leds pusher (RMT, SPI, I2S...) * * Below are interfaces for current implementations \*******************************************************************************************/ class TasmotaLEDPusher { public: TasmotaLEDPusher() : _pixel_count(0), _pixel_size(0), _led_timing(nullptr) {}; virtual ~TasmotaLEDPusher() {}; virtual bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) { _pixel_count = pixel_count; _pixel_size = pixel_size; _led_timing = led_timing; return true; } virtual bool Push(uint8_t *buf) = 0; virtual bool CanShow(void) = 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 protected: uint16_t _pixel_count; uint16_t _pixel_size; const TasmotaLED_Timing * _led_timing; }; /*******************************************************************************************\ * class TasmotaLEDPusherRMT * * Implementation based on RMT driver \*******************************************************************************************/ #if TASMOTALED_HARDWARE_RMT #include "driver/rmt_tx.h" class TasmotaLEDPusherRMT : public TasmotaLEDPusher { public: TasmotaLEDPusherRMT(int8_t pin) : _pin(pin) {}; ~TasmotaLEDPusherRMT(); bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) override; bool Push(uint8_t *buf) override; bool CanShow(void) override; protected: int8_t _pin; rmt_transmit_config_t _tx_config = {}; rmt_channel_handle_t _channel = nullptr;; rmt_encoder_handle_t _led_encoder = nullptr; }; #endif // TASMOTALED_HARDWARE_RMT /*******************************************************************************************\ * class TasmotaLEDPusherSPI * * Implementation based on SPI driver, mandatory for C2 \*******************************************************************************************/ #if TASMOTALED_HARDWARE_SPI #include typedef struct led_strip_spi_obj_t { uint8_t * pixel_buf; uint16_t strip_len; uint8_t bytes_per_pixel; spi_host_device_t spi_host; spi_device_handle_t spi_device; spi_transaction_t tx_conf; // transaction in process if any } led_strip_spi_obj; class TasmotaLEDPusherSPI : public TasmotaLEDPusher { public: TasmotaLEDPusherSPI(int8_t pin) : _pin(pin), _spi_strip({}) {}; ~TasmotaLEDPusherSPI(); bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) override; bool Push(uint8_t *buf) override; bool CanShow(void) override; protected: int8_t _pin; struct led_strip_spi_obj_t _spi_strip; }; #endif // TASMOTALED_HARDWARE_SPI #endif // __TASMOTALEDPUSHER_H__