@brief Clockless-over-SPI IChannelDriver implementation ⚠️ This is a CLOCKLESS LED driver using SPI hardware, NOT a true SPI chipset driver! Consolidates clockless LED strip functionality using SPI peripheral as bit-banger: - Implements clockless protocols (WS2812, SK6812, etc.) via SPI bit patterns - Direct ESP-IDF SPI master driver integration - Wave8 encoding (SPI clock from chipset timing, 8
| 186 | /// |
| 187 | /// Managed by ChannelManager which handles frame lifecycle events. |
| 188 | class ChannelEngineSpi : public IChannelDriver { |
| 189 | public: |
| 190 | ChannelEngineSpi() FL_NOEXCEPT; |
| 191 | ~ChannelEngineSpi() override; |
| 192 | |
| 193 | /// @brief Configure multi-lane SPI pins for a specific data pin |
| 194 | /// @param pinConfig Multi-lane pin configuration |
| 195 | /// |
| 196 | /// Example usage: |
| 197 | /// @code |
| 198 | /// // Dual-lane SPI (2x throughput) |
| 199 | /// driver.configureMultiLanePins(MultiLanePinConfig(23, 19)); |
| 200 | /// |
| 201 | /// // Quad-lane SPI (4x throughput, ESP32/S2/S3 only) |
| 202 | /// driver.configureMultiLanePins(MultiLanePinConfig(23, 19, 18, 5)); |
| 203 | /// @endcode |
| 204 | void configureMultiLanePins(const MultiLanePinConfig& pinConfig) FL_NOEXCEPT; |
| 205 | |
| 206 | // IChannelDriver interface implementation |
| 207 | void enqueue(ChannelDataPtr channelData) FL_NOEXCEPT override; |
| 208 | void show() FL_NOEXCEPT override; |
| 209 | DriverState poll() FL_NOEXCEPT override; |
| 210 | |
| 211 | /// @brief Get the driver name for affinity binding |
| 212 | /// @return "SPI" |
| 213 | fl::string getName() const FL_NOEXCEPT override { return fl::string::from_literal("SPI"); } |
| 214 | |
| 215 | /// @brief Get driver capabilities (CLOCKLESS protocols only) |
| 216 | /// @return Capabilities with supportsClockless=true, supportsSpi=false |
| 217 | /// @note This is a clockless-over-SPI driver, not a true SPI LED driver |
| 218 | Capabilities getCapabilities() const FL_NOEXCEPT override { |
| 219 | return Capabilities(true, false); // Clockless only |
| 220 | } |
| 221 | |
| 222 | /// @brief Check if this driver can handle the given channel data |
| 223 | /// @param data Channel data to check |
| 224 | /// @return true for CLOCKLESS chipsets (WS2812, SK6812, etc.), false for true SPI chipsets |
| 225 | /// |
| 226 | /// This driver is a CLOCKLESS-over-SPI driver: |
| 227 | /// - Returns true for clockless protocols (WS2812, SK6812, etc.) |
| 228 | /// - Returns false for true SPI protocols (APA102, SK9822, etc.) |
| 229 | bool canHandle(const ChannelDataPtr& data) const FL_NOEXCEPT override; |
| 230 | |
| 231 | private: |
| 232 | /// @brief Begin LED data transmission with internal batching (internal helper) |
| 233 | /// @param channelData Span of channel data to transmit |
| 234 | /// |
| 235 | /// Groups channels by timing compatibility and batches them when N > K, |
| 236 | /// where N = number of channels with compatible timings and K = available lanes. |
| 237 | void beginBatchedTransmission(fl::span<const ChannelDataPtr> channelData) FL_NOEXCEPT; |
| 238 | |
| 239 | /// @brief Begin LED data transmission for all channels (internal helper) |
| 240 | /// @param channelData Span of channel data to transmit |
| 241 | void beginTransmission(fl::span<const ChannelDataPtr> channelData) FL_NOEXCEPT; |
| 242 | |
| 243 | /// @brief Determine maximum parallel transmission capacity |
| 244 | /// @param channels Channels in a timing group (unused, for future extension) |
| 245 | /// @return Number of SPI hosts available (2 for ESP32/S2/S3/P4, 1 for ESP32-C3) |
no test coverage detected