initial commit

This commit is contained in:
2026-02-12 00:45:31 -08:00
commit 5f168f370b
3024 changed files with 804889 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
# FastLED Platform: adafruit
Adafruit_NeoPixel integration providing a FastLEDcompatible clockless controller implemented on top of Adafruits driver.
## Files (quick pass)
- `clockless.h`: Adapter layer. Exposes a `ClocklessController` template that marshals FastLED pixel data to an `Adafruit_NeoPixel` instance. Requires `Adafruit_NeoPixel.h` to be available; timing (T1/T2/T3) is managed by the Adafruit library.
## Usage and detection
- Controlled by `FASTLED_USE_ADAFRUIT_NEOPIXEL` (defaults to undefined unless building docs). If enabled but `Adafruit_NeoPixel.h` is missing, the adapter disables itself with an error.
- Color order: FastLEDs `PixelController` applies RGB ordering; the adapter always feeds RGB into Adafruits API.
- Timings: `T1/T2/T3` template params are ignored here; Adafruits driver handles signal generation and timing per platform.
## Notes
- This path is useful when Adafruits platform backends (e.g., some boards/cores) are preferred or more stable for your setup.
- Performance characteristics and memory usage follow Adafruit_NeoPixel; expect different throughput vs native FastLED clockless drivers.
## Optional feature defines
- **`FASTLED_USE_ADAFRUIT_NEOPIXEL`**: Default undefined (unless building docs via `FASTLED_DOXYGEN`). When defined, enables the Adafruit adapter; requires `Adafruit_NeoPixel.h`.
Define before including `FastLED.h`.
## Compatibility and color order
Supported color orders: FastLEDs `PixelController` handles byte reordering before passing data to Adafruit_NeoPixel. Typical orders like GRB/RGB/BRG are supported transparently.
Constraints vs native FastLED timing:
- Timing is wholly delegated to Adafruit_NeoPixel. The `T1/T2/T3` template parameters are ignored; use Adafruits platform timings.
- Throughput and CPU usage may differ from FastLEDs native clockless or RMT/I2S backends. If you need multistrip parallelism or strict ISR windows, consider native drivers instead.

View File

@@ -0,0 +1,8 @@
#include "fl/has_include.h"
#if FL_HAS_INCLUDE(<Adafruit_NeoPixel.h>)
#include "platforms/adafruit/clockless_real.hpp"
#else
#include "platforms/adafruit/clockless_fake.hpp"
#endif

View File

@@ -0,0 +1,73 @@
#pragma once
/// @file clockless.h
/// Adafruit_NeoPixel-based clockless controller implementation
///
/// This header provides a FastLED-compatible clockless controller that uses
/// the Adafruit_NeoPixel library as the underlying driver. This allows users
/// to leverage the proven reliability and platform-specific optimizations
/// of the Adafruit library within the FastLED ecosystem.
///
/// Requirements:
/// - Adafruit_NeoPixel library must be included before FastLED
/// - The controller is only available when Adafruit_NeoPixel.h is detected
#include "fl/memory.h"
#include "fl/unique_ptr.h"
#include "eorder.h"
#include "pixel_controller.h"
#include "platforms/adafruit/driver.h"
namespace fl {
class PixelIterator;
/// WS2812/NeoPixel clockless controller using Adafruit_NeoPixel library as the underlying driver
///
/// This controller provides a simple interface for WS2812/NeoPixel LEDs using the proven
/// Adafruit_NeoPixel library for platform-specific optimizations and reliable output.
/// Supports RGB color order conversion and handles initialization, pixel conversion,
/// and output automatically.
///
/// @tparam DATA_PIN the data pin for the LED strip
/// @tparam RGB_ORDER the RGB ordering for the LEDs (affects input processing, output is always RGB)
/// @see https://github.com/adafruit/Adafruit_NeoPixel
template <int DATA_PIN, EOrder RGB_ORDER = GRB>
class AdafruitWS2812Controller : public CPixelLEDController<RGB_ORDER> {
private:
fl::unique_ptr<fl::IAdafruitNeoPixelDriver> mDriver;
public:
/// Constructor - creates uninitialized controller
AdafruitWS2812Controller(){}
/// Destructor - automatic cleanup
virtual ~AdafruitWS2812Controller() = default;
/// Initialize the controller
virtual void init() override {
// Driver will be initialized when showPixels is first called
}
/// Output pixels to the LED strip
/// Converts FastLED pixel data to Adafruit format and displays
/// @param pixels the pixel controller containing LED data
virtual void showPixels(PixelController<RGB_ORDER> &pixels) override {
// Initialize driver if needed
if (!mDriver) {
mDriver = fl::IAdafruitNeoPixelDriver::create();
mDriver->init(DATA_PIN);
}
// Convert to PixelIterator and send to driver
auto pixelIterator = pixels.as_iterator(this->getRgbw());
mDriver->showPixels(pixelIterator);
}
protected:
/// Get the driver instance (for derived classes)
fl::IAdafruitNeoPixelDriver& getDriver() {
return *mDriver;
}
};
} // namespace fl

View File

@@ -0,0 +1,37 @@
/// @file clockless.cpp
/// Implementation of IAdafruitNeoPixelDriver
///
/// This file contains the actual Adafruit_NeoPixel integration, keeping the
/// dependency isolated from header files to avoid PlatformIO LDF issues.
#include "platforms/adafruit/driver.h"
#include "fl/unused.h"
#include "fl/warn.h"
namespace fl {
// Concrete implementation of IAdafruitNeoPixelDriver
class AdafruitNeoPixelDriverFake : public IAdafruitNeoPixelDriver {
public:
AdafruitNeoPixelDriverFake() {}
~AdafruitNeoPixelDriverFake() override = default;
void init(int dataPin) override {
FL_UNUSED(dataPin);
FL_WARN("Please install adafruit neopixel package to use this api bridge.");
}
void showPixels(PixelIterator& pixelIterator) override {
FL_UNUSED(pixelIterator);
FL_WARN("Please install adafruit neopixel package to use this api bridge.");
}
};
// Static factory method implementation
fl::unique_ptr<IAdafruitNeoPixelDriver> IAdafruitNeoPixelDriver::create() {
return fl::unique_ptr<IAdafruitNeoPixelDriver>(new AdafruitNeoPixelDriverFake());
}
} // namespace fl

View File

@@ -0,0 +1,93 @@
/// @file clockless.cpp
/// Implementation of IAdafruitNeoPixelDriver
///
/// This file contains the actual Adafruit_NeoPixel integration, keeping the
/// dependency isolated from header files to avoid PlatformIO LDF issues.
#include <Adafruit_NeoPixel.h>
#include "fl/unique_ptr.h"
#include "fl/memory.h"
#include "pixel_iterator.h"
#include "platforms/adafruit/driver.h"
namespace fl {
// Concrete implementation of IAdafruitNeoPixelDriver
class AdafruitNeoPixelDriverImpl : public IAdafruitNeoPixelDriver {
private:
unique_ptr<Adafruit_NeoPixel> mNeoPixel;
bool mInitialized;
int mDataPin;
public:
AdafruitNeoPixelDriverImpl()
: mNeoPixel(nullptr), mInitialized(false), mDataPin(-1) {}
~AdafruitNeoPixelDriverImpl() override = default;
void init(int dataPin) override {
if (!mInitialized) {
mDataPin = dataPin;
mInitialized = true;
}
}
void showPixels(PixelIterator& pixelIterator) override {
if (!mInitialized) {
return;
}
// Get pixel count from iterator
int numPixels = pixelIterator.size();
auto rgbw = pixelIterator.get_rgbw();
// Determine the appropriate NeoPixel type based on RGBW mode
uint16_t neoPixelType = NEO_KHZ800;
if (rgbw.active()) {
neoPixelType |= NEO_RGBW; // RGBW mode
} else {
neoPixelType |= NEO_RGB; // RGB mode
}
// Create or recreate NeoPixel instance if needed
if (!mNeoPixel || mNeoPixel->numPixels() != numPixels) {
if (mNeoPixel) {
mNeoPixel.reset();
}
mNeoPixel = fl::make_unique<Adafruit_NeoPixel>(
numPixels, mDataPin, neoPixelType);
mNeoPixel->begin();
}
// Convert pixel data using PixelIterator and send to Adafruit_NeoPixel
if (rgbw.active()) {
// RGBW mode
for (int i = 0; pixelIterator.has(1); ++i) {
fl::u8 r, g, b, w;
pixelIterator.loadAndScaleRGBW(&r, &g, &b, &w);
mNeoPixel->setPixelColor(i, r, g, b, w);
pixelIterator.advanceData();
}
} else {
// RGB mode
for (int i = 0; pixelIterator.has(1); ++i) {
fl::u8 r, g, b;
pixelIterator.loadAndScaleRGB(&r, &g, &b);
mNeoPixel->setPixelColor(i, r, g, b);
pixelIterator.advanceData();
}
}
// Output to LEDs
mNeoPixel->show();
}
};
// Static factory method implementation
fl::unique_ptr<IAdafruitNeoPixelDriver> IAdafruitNeoPixelDriver::create() {
return fl::make_unique<AdafruitNeoPixelDriverImpl>();
}
} // namespace fl

View File

@@ -0,0 +1,25 @@
#include "fl/unique_ptr.h"
#include "pixel_iterator.h"
namespace fl {
class PixelIterator;
/// Interface for Adafruit NeoPixel driver - implementation in clockless.cpp
class IAdafruitNeoPixelDriver {
public:
/// Static factory method to create driver implementation
static unique_ptr<IAdafruitNeoPixelDriver> create();
virtual ~IAdafruitNeoPixelDriver() = default;
/// Initialize the driver with data pin and RGBW mode
virtual void init(int dataPin) = 0;
/// Output pixels to the LED strip
virtual void showPixels(PixelIterator& pixelIterator) = 0;
};
} // namespace fl