FastLED 3.10.9
Loading...
Searching...
No Matches

◆ transmitBatch()

bool fl::SpiChannelEngineAdapter::transmitBatch ( fl::span< const ChannelDataPtr > channels)
private

Transmit a batch of channels sharing one SPI configuration.

Parameters
channelsChannels to transmit (must have matching pins, host, and rate)
Returns
true on success, false on error

Definition at line 343 of file spi_channel_adapter.cpp.hpp.

343 {
344 if (channels.empty()) {
345 return true;
346 }
347
348 // Extract clock pin and data pin from first channel (all same in batch)
349 const auto& chipset = channels[0]->getChipset();
350 if (!chipset.is<SpiChipsetConfig>()) {
351 FL_WARN("SpiChannelEngineAdapter: Non-SPI chipset in transmitBatch");
352 return false;
353 }
354
355 const SpiChipsetConfig& spiConfig = chipset.get<SpiChipsetConfig>();
356 int clockPin = spiConfig.clockPin;
357 int dataPin = channels[0]->getPin(); // MOSI pin from channel config
358
359 // Select controller for this clock pin
360 int controllerIndex = selectControllerForClockPin(clockPin, spiConfig.spiBus);
361 if (controllerIndex < 0) {
362 FL_WARN("SpiChannelEngineAdapter: No available controller for clock pin " << clockPin);
363 return false;
364 }
365
366 ControllerInfo& ctrl = mControllers[controllerIndex];
367
368 // Initialize controller if needed
369 if (!initializeControllerIfNeeded(ctrl, clockPin, dataPin,
370 spiConfig.timing.clock_hz)) {
371 return false;
372 }
373
374 // Transmit using selected controller
375 for (const auto& channel : channels) {
376 if (!channel) {
377 continue;
378 }
379
380 // Mark channel as in use
381 channel->setInUse(true);
382
383 // Get encoded data
384 const auto& data = channel->getData();
385 if (data.empty()) {
386 FL_WARN("SpiChannelEngineAdapter: Empty channel data");
387 channel->setInUse(false);
388 continue;
389 }
390
391 FL_DBG("SpiChannelEngineAdapter: Transmitting channel via " << ctrl.name << " (pin " << channel->getPin() << ", " << data.size() << " bytes)");
392
393 // Acquire DMA buffer
394 DMABuffer dmaBuffer = ctrl.controller->acquireDMABuffer(data.size());
395 if (!dmaBuffer.ok()) {
396 FL_WARN("SpiChannelEngineAdapter: Failed to acquire DMA buffer (error " << (static_cast<int>(dmaBuffer.error())) << ")");
397 channel->setInUse(false);
398 return false;
399 }
400
401 // Copy data to DMA buffer
402 fl::span<u8> buffer = dmaBuffer.data();
403 if (buffer.size() < data.size()) {
404 FL_WARN("SpiChannelEngineAdapter: DMA buffer too small (" << buffer.size() << " < " << data.size() << ")");
405 channel->setInUse(false);
406 return false;
407 }
408
409 fl::memcpy(buffer.data(), data.data(), data.size());
410
411 // Transmit (async mode for non-blocking operation)
412 if (!ctrl.controller->transmit(TransmitMode::ASYNC)) {
413 FL_WARN("SpiChannelEngineAdapter: Transmission failed");
414 channel->setInUse(false);
415 return false;
416 }
417
418 FL_DBG("SpiChannelEngineAdapter: Transmission queued successfully");
419 }
420
421 // Wait for transmission to complete (synchronous for now)
422 // TODO: Make fully async by returning BUSY state and polling in poll()
423 if (!ctrl.controller->waitComplete(1000)) { // 1 second timeout
424 FL_WARN("SpiChannelEngineAdapter: Transmission timeout");
425 return false;
426 }
427
428 FL_DBG("SpiChannelEngineAdapter: Batch transmission complete");
429 return true;
430}
fl::vector< ControllerInfo > mControllers
All managed controllers.
bool initializeControllerIfNeeded(ControllerInfo &ctrl, int clockPin, int dataPin, u32 clockSpeedHz) FL_NO_EXCEPT
Initialize controller if needed for this clock pin.
int selectControllerForClockPin(int clockPin, Esp32SpiBus requestedBus) FL_NO_EXCEPT
Select best controller for a given clock pin.
constexpr bool empty() const FL_NO_EXCEPT
Definition span.h:535
const T * data() const FL_NO_EXCEPT
Definition span.h:486
constexpr fl::size size() const FL_NO_EXCEPT
Definition span.h:483
#define FL_WARN(...)
Definition log.h:437
#define FL_DBG
Definition log.h:553
FASTLED_FORCE_INLINE void * memcpy(void *dest, const void *src, size_t n) FL_NO_EXCEPT
Definition cstring.h:136
Information about a registered SPI hardware controller.

References fl::SpiEncoder::clock_hz, fl::SpiChipsetConfig::clockPin, fl::SpiChannelEngineAdapter::ControllerInfo::controller, fl::span< T, Extent >::data(), FL_DBG, fl::FL_NO_EXCEPT, FL_WARN, initializeControllerIfNeeded(), mControllers, fl::memcpy(), fl::SpiChannelEngineAdapter::ControllerInfo::name, selectControllerForClockPin(), fl::basic_string::size(), fl::span< T, Extent >::size(), fl::SpiChipsetConfig::spiBus, and fl::SpiChipsetConfig::timing.

Referenced by show().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: