### Ws2812bTiming Usage Example Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/timing.md Example of using `Ws2812bTiming` with `RmtSmartLeds` for a standard RGB LED strip with GRB color order. ```rust type StandardRgb = RmtSmartLeds< { buffer_size::(30) }, _, RGB8, color_order::Grb, Ws2812bTiming // WS2812B is safest choice >; ``` -------------------------------- ### Async LED Control with Embassy Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md This example demonstrates asynchronous control of addressable LEDs using Embassy. It's suitable for applications requiring non-blocking operations. This example controls 1 RGB8 LED. ```rust use embassy_executor::Spawner; use embassy_time::Timer; use esp_hal::{rmt::Rmt, time::Rate}; use esp_hal_smartled::{RmtSmartLeds, Ws2812Timing, buffer_size, color_order}; use smart_leds::{RGB8, SmartLedsWriteAsync, brightness}; #[esp_rtos::main] async fn main(_spawner: Spawner) -> ! { let peripherals = esp_hal::init(esp_hal::Config::default()); // Initialize RMT in async mode let rmt = Rmt::new(peripherals.RMT, Rate::from_mhz(80)) .expect("Failed to initialize RMT") .into_async(); // Create async LED driver let mut led_driver = RmtSmartLeds::< { buffer_size::(1) }, _, RGB8, color_order::Grb, Ws2812Timing >::new(rmt.channel0, peripherals.GPIO2) .expect("Failed to create LED driver"); let mut color = RGB8 { r: 255, g: 0, b: 0 }; loop { // Prepare data asynchronously let fut = led_driver.write(brightness([color].iter().cloned(), 50)); // Wait with timeout or do other work Timer::after_millis(100).await; // Await the transmission fut.await.expect("Failed to write LEDs"); // Rotate color (color.r, color.g, color.b) = (color.g, color.b, color.r); } } ``` -------------------------------- ### RmtSmartLeds write Method Example Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/trait-implementations.md Demonstrates how to use the write method with different color sources like arrays, vectors, and iterators, including applying brightness filters and gamma correction. Ensure necessary imports are included. ```rust use smart_leds::{RGB8, SmartLedsWrite, brightness}; // Direct array let colors = [RGB8 { r: 255, g: 0, b: 0 }; 10]; led_driver.write(colors.iter().cloned())?; // With brightness filter led_driver.write(brightness(colors.iter().cloned(), 100))?; // With gamma correction use smart_leds::gamma; led_driver.write(gamma(colors.iter().cloned()))?; // From vec or slice let color_vec = vec![RGB8 { r: 255, g: 0, b: 0 }; 5]; led_driver.write(color_vec.iter().cloned())?; ``` -------------------------------- ### Writing Monochrome White Brightness Levels Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md Example of writing an array of single-channel White color values to control the brightness of monochrome LEDs. ```rust use smart_leds::White; let brightness_levels = [ White(255), White(200), White(100), White(50), ]; led_driver.write(brightness_levels.iter().cloned())?; ``` -------------------------------- ### Sk68xxTiming Usage Examples Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/timing.md Demonstrates using `Sk68xxTiming` for both RGB and RGBW SK6812 variants with `RmtSmartLeds`. ```rust // RGB version type Sk68xxRgb = RmtSmartLeds< { buffer_size::(20) }, _, RGB8, color_order::Grb, Sk68xxTiming >; // RGBW version (pre-configured) type Sk68xxRgbw = Sk68xxRgbwSmartLeds<{ buffer_size::>(20) }, Blocking>; ``` -------------------------------- ### Configure RMT Memory for Large LED Strips Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md Increase RMT memory allocation for handling LED strips with more than 10-20 LEDs. This example shows how to calculate buffer size and initialize the driver with custom memory size. ```rust use esp_hal_smartled::{RmtSmartLeds, Ws2812Timing, buffer_size, color_order}; use smart_leds::RGB8; // 100 RGB8 LEDs requires ~2.4 KB buffer (approximately 2-3 RMT blocks) const NUM_LEDS: usize = 100; const BUFFER: usize = buffer_size::(NUM_LEDS); let mut led_driver = RmtSmartLeds::< BUFFER, _, RGB8, color_order::Grb, Ws2812Timing >::new_with_memsize(rmt.channel0, gpio_pin, 3)?; ``` -------------------------------- ### Basic Blocking LED Control Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md Use this for simple, blocking control of addressable LEDs. Ensure RMT and GPIO are correctly initialized. This example controls 10 RGB8 LEDs. ```rust use esp_hal::{rmt::Rmt, time::Rate}; use esp_hal_smartled::{RmtSmartLeds, Ws2812Timing, buffer_size, color_order}; use smart_leds::{RGB8, SmartLedsWrite, brightness}; fn main() -> ! { let peripherals = esp_hal::init(esp_hal::Config::default()); // Initialize RMT peripheral let rmt = Rmt::new(peripherals.RMT, Rate::from_mhz(80)) .expect("Failed to initialize RMT"); // Create LED driver with 10 RGB8 LEDs let mut led_driver = RmtSmartLeds::< { buffer_size::(10) }, _, RGB8, color_order::Grb, Ws2812Timing >::new(rmt.channel0, peripherals.GPIO2) .expect("Failed to create LED driver"); // Send color data let colors = [ RGB8 { r: 255, g: 0, b: 0 }, // Red RGB8 { r: 0, g: 255, b: 0 }, // Green RGB8 { r: 0, g: 0, b: 255 }, // Blue ]; // Brightness filter and send led_driver.write(brightness(colors.iter().cloned(), 100)) .expect("Failed to write LEDs"); loop { // Update LEDs periodically } } ``` -------------------------------- ### Example Usage of Grb Color Order Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/color-order.md Demonstrates how to use the Grb color order implementation to extract channel data from an RGB8 color. This is common for WS2812 LEDs. ```rust use smart_leds::RGB8; use esp_hal_smartled::color_order::{ColorOrder, Grb}; let color = RGB8 { r: 100, g: 200, b: 50 }; // Using Grb color order (common for WS2812) let first_byte = Grb::get_channel_data(&color, 0); // 200 (green) let second_byte = Grb::get_channel_data(&color, 1); // 100 (red) let third_byte = Grb::get_channel_data(&color, 2); // 50 (blue) ``` -------------------------------- ### RmtSmartLeds::new() Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/configuration.md Constructor for standard RMT driver setup with a single RMT memory block. It initializes the RMT driver with the specified channel and pin. ```APIDOC ## RmtSmartLeds::new() ### Description Constructor for standard RMT driver setup with single RMT memory block. ### Signature ```rust pub fn new(channel: Ch, pin: P) -> Result where Ch: TxChannelCreator<'d, Mode>, P: PeripheralOutput<'d>, ``` ### Parameters #### Path Parameters - **channel** (TxChannelCreator<'d, Mode>) - Required - RMT transmit channel from esp-hal (either blocking or async) - **pin** (PeripheralOutput<'d>) - Required - GPIO pin connected to LED data line (must be valid for RMT) ### Implicit Configuration - RMT clock divider: 1 (uses APB clock directly, typically 80 MHz) - Idle output level: Low - Carrier modulation: Disabled - Idle output: Enabled - RMT memory blocks: 1 (fixed) ``` -------------------------------- ### Detecting BufferSizeExceeded Error Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/errors.md Example demonstrating how to detect and handle the BufferSizeExceeded error when writing LED data. This occurs when the number of LEDs exceeds the configured buffer capacity. ```rust use esp_hal_smartled::{RmtSmartLeds, buffer_size}; use smart_leds::{RGB8, SmartLedsWrite}; // Buffer configured for 10 LEDs type Driver = RmtSmartLeds<{ buffer_size::(10) }, _, RGB8, _, _>; // This will succeed — exactly 10 colors led_driver.write([RGB8::new(255, 0, 0); 10]).unwrap(); // This will fail with BufferSizeExceeded — 11 colors in 10-LED buffer let result = led_driver.write([RGB8::new(255, 0, 0); 11]); match result { Err(AdapterError::BufferSizeExceeded) => { eprintln!("Error: wrote too many LEDs"); } _ => {} } ``` -------------------------------- ### Writing RGB8 Color Data Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md Example of creating and writing an array of RGB8 color values to the LED driver. This is the most common color format for RGB LEDs. ```rust use smart_leds::RGB8; let red = RGB8 { r: 255, g: 0, b: 0 }; let green = RGB8 { r: 0, g: 255, b: 0 }; let blue = RGB8 { r: 0, g: 0, b: 255 }; let white = RGB8 { r: 255, g: 255, b: 255 }; let colors = [red, green, blue]; led_driver.write(colors.iter().cloned())?; ``` -------------------------------- ### Grb Color Order Implementation Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/color-order.md Green-Red-Blue color order, the most common order used by WS2812 family LEDs. Explicit usage example provided. ```rust pub enum Grb {} impl ColorOrder> for Grb where T: Copy + Unsigned + Into, { fn get_channel_data(color: &RGB, channel: u8) -> T { match channel { 0 => color.g, 1 => color.r, 2 => color.b, _ => unreachable!(), } } } ``` ```rust // Most common configuration for WS2812 LEDs type Ws2812Driver = Ws2812SmartLeds<_, Blocking>; // Grb is built-in // Explicit usage type ExplicitGrb = RmtSmartLeds<_, _, RGB8, color_order::Grb, Ws2812Timing>; ``` -------------------------------- ### Define Custom LED Timing Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/timing.md Implement the `Timing` trait to define custom high and low pulse durations for non-standard LED controllers. This example shows a hypothetical LED with unusual timing values. ```rust use esp_hal_smartled::Timing; /// Timing for hypothetical LED with unusual timing pub enum CustomTiming {} impl Timing for CustomTiming { const TIME_0_HIGH: u16 = 300; const TIME_0_LOW: u16 = 900; // Total: 1200 const TIME_1_HIGH: u16 = 700; const TIME_1_LOW: u16 = 500; // Total: 1200 } // Use it: type CustomDriver = RmtSmartLeds< { buffer_size::(10) }, _, RGB8, color_order::Grb, CustomTiming >; ``` -------------------------------- ### Implement Custom Color Order Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/color-order.md Implement the `ColorOrder` trait for custom color orderings when standard options are insufficient. This example shows a custom mapping for a specific hardware requirement. ```rust use esp_hal_smartled::color_order::ColorOrder; use smart_leds::RGB8; /// Custom order for specific hardware pub enum CustomOrder {} impl ColorOrder for CustomOrder { fn get_channel_data(color: &RGB8, channel: u8) -> u8 { // Your custom mapping logic match channel { 0 => color.b, // Custom order 1 => color.g, 2 => color.r, _ => unreachable!(), } } } // Use it: type Driver = RmtSmartLeds<_, _, RGB8, CustomOrder, Ws2812Timing>; ``` -------------------------------- ### Pre-configured Type Aliases for SmartLEDs Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md Define convenient type aliases for common smart LED configurations, including WS2812, SK68XX RGBW, and single-channel white LEDs. These aliases simplify setup by pre-configuring buffer sizes and LED timings. ```rust use esp_hal_smartled::{Ws2812SmartLeds, Sk68xxRgbwSmartLeds, WhiteSmartLeds}; use smart_leds::RGB8; // WS2812 with defaults (GRB, WS2812 timings) type SimpleWs2812 = Ws2812SmartLeds<{ buffer_size::(20) }, Blocking>; // SK68XX RGBW with pre-configured colors and timing type RgbwDriver = Sk68xxRgbwSmartLeds<{ buffer_size::>(10) }, Blocking>; // Single-channel white LED type WhiteLeds = WhiteSmartLeds<{ buffer_size::>(30) }, Blocking, Ws2812Timing>; ``` -------------------------------- ### RmtSmartLeds Constructor (Standard) Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/configuration.md Use this constructor for a standard RMT driver setup with a single RMT memory block. It requires specifying the RMT transmit channel and the GPIO pin for the LED data line. ```rust pub fn new(channel: Ch, pin: P) -> Result where Ch: TxChannelCreator<'d, Mode>, P: PeripheralOutput<'d>, ``` -------------------------------- ### Test Common Color Orders Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/color-order.md Start with the most common GRB order and systematically try others if colors appear incorrect. This snippet demonstrates how to define the driver type for different color orders. ```rust type Driver = Ws2812SmartLeds<_, Blocking>; // If colors are wrong, try RGB type Driver = RmtSmartLeds<_, _, RGB8, color_order::Rgb, Ws2812Timing>; ``` -------------------------------- ### Writing RGBW Color Data Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md Example of creating and writing an array of RGBW color values, which includes a dedicated white channel. This allows for richer color mixing and brighter whites. ```rust use smart_leds::{RGBW, White}; let color = RGBW { r: 255, g: 128, b: 0, a: White(100), // White channel }; let colors = [color]; led_driver.write(colors.iter().cloned())?; ``` -------------------------------- ### Async LED Write Preparation and Dispatch Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/trait-implementations.md Demonstrates how to prepare an asynchronous LED write operation without immediate transmission, allowing other tasks to run concurrently. It also shows how to dispatch the transmission and handle potential errors. ```rust use smart_leds::{RGB8, SmartLedsWriteAsync, brightness}; use embassy_futures::join::join; // Prepare (doesn't transmit yet) let fut = led_driver.write(brightness(colors.iter().cloned(), 100)); // Do other work while transmission is prepared perform_other_task().await; // Dispatch transmission fut.await?; // Or parallelize multiple writes let fut1 = led_driver1.write(colors1.iter().cloned()); let fut2 = led_driver2.write(colors2.iter().cloned()); let (res1, res2) = join(fut1, fut2).await; res1?; res2?; ``` -------------------------------- ### RmtSmartLeds::new() Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/INDEX.md Creates a new RmtSmartLeds driver instance with default settings. This is the simplest way to initialize the LED driver. ```APIDOC ## RmtSmartLeds::new() ### Description Create driver with default settings. ### Method associated function ### Parameters None ``` -------------------------------- ### Configure Large LED Strip with Async Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/configuration.md Use this for large LED strips (up to 100 LEDs) when asynchronous operation is required. The buffer size is set to 100. ```rust type LargeStripAsync = Ws2812SmartLeds<{ buffer_size::(100) }, Async>; let mut driver = LargeStripAsync::new(rmt_async.channel0, gpio_pin)?; ``` -------------------------------- ### write (Async Mode - SmartLedsWriteAsync) Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/rmt-smartleds.md Asynchronously prepares color data for transmission. The actual RMT transmission is deferred until the returned future is awaited, allowing for parallel preparation of multiple LED buffers before dispatching transmission. ```APIDOC ## write (Async Mode - SmartLedsWriteAsync) ### Description Async variant of write. Prepares color data for transmission when called, but defers actual RMT transmission until the future is awaited. This allows preparing multiple LED buffers in parallel before dispatching transmission. ### Method `write` ### Parameters #### Request Body - `iterator` (IntoIterator>) - Required - Iterator of color values to send ### Returns `impl Future>` ### Errors - `AdapterError::BufferSizeExceeded` if iterator provides more items than BUFFER_SIZE allows - `AdapterError::TransmissionError(RmtError)` if RMT transmission fails ### Request Example ```rust use smart_leds::{RGB8, SmartLedsWriteAsync, brightness}; use embassy_futures::join::join; let data = [RGB8 { r: 255, g: 0, b: 0 }]; // Prepare transmission (non-blocking) let fut = led_driver.write(brightness(data.iter().cloned(), 100)); // Do other work while transmission is being set up let (_, result) = join(some_other_async_operation(), fut).await; result?; ``` ``` -------------------------------- ### RGBW LEDs with Async Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/README.md Initializes an RMT peripheral and an SK68xx-compatible RGBW LED driver in asynchronous mode. This is suitable for applications requiring concurrent operations, allowing LED updates without blocking the main thread. ```rust use esp_rtos::main; use esp_hal::{rmt::Rmt, time::Rate}; use esp_hal_smartled::Sk68xxRgbwSmartLeds; use smart_leds::{RGBW, White, SmartLedsWriteAsync, brightness}; #[esp_rtos::main] async fn main(_spawner: Spawner) -> ! { let peripherals = esp_hal::init(esp_hal::Config::default()); let rmt = Rmt::new(peripherals.RMT, Rate::from_mhz(80))? .into_async(); let mut led_driver = Sk68xxRgbwSmartLeds::< { buffer_size::>(10) }, Async >::new(rmt.channel0, peripherals.GPIO2)?; let color = RGBW { r: 255, g: 128, b: 64, a: White(100), }; led_driver.write([color].iter().cloned()).await?; loop {} } ``` -------------------------------- ### Configure Medium LED Strip (10-20 LEDs) Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/configuration.md This configuration is suitable for medium-sized LED strips. The buffer size is set to 15. ```rust type MediumStrip = Ws2812SmartLeds<{ buffer_size::(15) }, Blocking>; let mut driver = MediumStrip::new(rmt.channel0, gpio_pin)?; ``` -------------------------------- ### Configure Very Large Strip (100+ LEDs) Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/configuration.md This configuration is for very large LED strips (200+ LEDs). It uses a specified memory size for the buffer. ```rust type VeryLargeStrip = Ws2812SmartLeds<{ buffer_size::(200) }, Blocking>; let mut driver = VeryLargeStrip::new_with_memsize(rmt.channel0, gpio_pin, 4?); ``` -------------------------------- ### Configure RGBW LEDs (with white channel) Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/configuration.md This configuration is for RGBW LEDs that include a dedicated white channel. The buffer size is set to 30. ```rust type RgbwDriver = Sk68xxRgbwSmartLeds<{ buffer_size::>(30) }, Blocking>; let mut driver = RgbwDriver::new(rmt.channel0, gpio_pin)?; ``` -------------------------------- ### Write LED Data (Async Mode) Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/rmt-smartleds.md Asynchronously prepares color data for transmission. The actual RMT transmission is deferred until the returned future is awaited. Allows preparing multiple buffers in parallel before dispatching transmission. Implemented when `Mode = Async`. ```rust use smart_leds::{RGB8, SmartLedsWriteAsync, brightness}; use embassy_futures::join::join; let data = [RGB8 { r: 255, g: 0, b: 0 }]; // Prepare transmission (non-blocking) let fut = led_driver.write(brightness(data.iter().cloned(), 100)); // Do other work while transmission is being set up let (_, result) = join(some_other_async_operation(), fut).await; result?; ``` -------------------------------- ### Configure Small Single LED Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/configuration.md Use this configuration for a single LED. Ensure the buffer size is set to 1. ```rust type SmallLed = Ws2812SmartLeds<{ buffer_size::(1) }, Blocking>; let mut driver = SmallLed::new(rmt.channel0, gpio_pin)?; ``` -------------------------------- ### Basic RGB LED Strip (Blocking) Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/README.md Initializes an RMT peripheral and a WS2812-compatible LED driver in blocking mode. Use this for simple, sequential LED control where blocking is acceptable. ```rust use esp_hal::{rmt::Rmt, time::Rate}; use esp_hal_smartled::{RmtSmartLeds, Ws2812Timing, buffer_size, color_order}; use smart_leds::{RGB8, SmartLedsWrite, brightness}; fn main() -> ! { let peripherals = esp_hal::init(esp_hal::Config::default()); let rmt = Rmt::new(peripherals.RMT, Rate::from_mhz(80))?; let mut led_driver = RmtSmartLeds::< { buffer_size::(10) }, _, RGB8, color_order::Grb, Ws2812Timing >::new(rmt.channel0, peripherals.GPIO2)?; let colors = [RGB8 { r: 255, g: 0, b: 0 }; 10]; led_driver.write(brightness(colors.iter().cloned(), 100))?; loop {} } ``` -------------------------------- ### Error Handling for LED Updates Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md Demonstrates how to handle potential errors when writing color data to smart LEDs. This includes catching buffer size overflows and transmission errors, providing specific advice for each case. ```rust use esp_hal_smartled::AdapterError; match led_driver.write(colors) { Ok(()) => { defmt::info!("LEDs updated successfully"); } Err(AdapterError::BufferSizeExceeded) => { defmt::error!("LED buffer size exceeded"); // Fix: recalculate buffer_size with actual LED count } Err(AdapterError::TransmissionError(e)) => { defmt::error!("RMT transmission failed: {:?}", e); // Rare condition, likely hardware issue } } ``` -------------------------------- ### Import Color Order for SmartLEDs Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/configuration.md Import specific color order definitions from the `color_order` module. This is essential for ensuring colors are displayed correctly on the LEDs. ```rust use color_order::Rgb; ``` ```rust use color_order::Grb; ``` ```rust use color_order::Rbg; ``` ```rust use color_order::Brg; ``` ```rust use color_order::Bgr; ``` ```rust use color_order::Gbr; ``` ```rust use color_order::Rgbw; ``` ```rust use color_order::SingleChannel; ``` -------------------------------- ### Timing Trait and Implementations Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/DOCUMENTATION_MAP.md Documentation for the Timing trait and its common implementations for various LED types. ```APIDOC ## Timing Trait ### Description Defines the precise timing specifications required for controlling specific types of smart LEDs. ### Implementations - **Ws2812Timing**: Timing for the original WS2812 LEDs. - **Ws2812bTiming**: Timing for the WS2812B LEDs (most common). - **Sk68xxTiming**: Timing for SK6812 and SK8612 LEDs (RGBW support). - **Ws2811Timing**: High-speed timing for WS2811 LEDs. - **Ws2811LowSpeedTiming**: Low-speed timing for WS2811 LEDs. Each implementation provides the necessary nanosecond values for the high and low periods of the data signal. ``` -------------------------------- ### Test LED Strip Colors Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md This snippet demonstrates how to test individual LED colors (Red, Green, Blue) and then all white. Ensure the correct ColorOrder is used if colors appear incorrect. Check power and GPIO configuration if LEDs do not light up. ```rust use smart_leds::RGB8; // Test 1: Red led_driver.write([RGB8 { r: 255, g: 0, b: 0 }].iter().cloned())?; Timer::delay(1000); // Test 2: Green led_driver.write([RGB8 { r: 0, g: 255, b: 0 }].iter().cloned())?; Timer::delay(1000); // Test 3: Blue led_driver.write([RGB8 { r: 0, g: 0, b: 255 }].iter().cloned())?; Timer::delay(1000); // Test 4: All white led_driver.write([RGB8 { r: 255, g: 255, b: 255 }].iter().cloned())?; ``` -------------------------------- ### Ws2812bTiming Implementation Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/timing.md Implements the `Timing` trait for the WS2812B LED controller IC, which is common in most modern addressable RGB LED strips. This timing is generally the safest choice. ```rust pub enum Ws2812bTiming {} impl Timing for Ws2812bTiming { const TIME_0_HIGH: u16 = 400; // 0-bit high: 400 ns const TIME_0_LOW: u16 = 800; // 0-bit low: 800 ns (total: 1200 ns) const TIME_1_HIGH: u16 = 850; // 1-bit high: 850 ns const TIME_1_LOW: u16 = 450; // 1-bit low: 450 ns (total: 1300 ns) } ``` -------------------------------- ### buffer_size() Function Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/DOCUMENTATION_MAP.md Documentation for the buffer_size function, used to calculate the required buffer size for LED data. ```APIDOC ## buffer_size() Function ### Description Calculates the required buffer size in bytes for a given number of LEDs and color type. ### Usage `buffer_size(num_leds: usize) -> usize` ### Parameters - **num_leds** (usize): The number of LEDs in the strip. ### Returns (usize): The calculated buffer size in bytes. ``` -------------------------------- ### Correct Buffer Size Calculation Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md Ensure the buffer size is calculated correctly using the `buffer_size` function to match the number of LEDs. Using an arbitrary size can lead to errors. ```rust // WRONG - arbitrary buffer size type Driver = RmtSmartLeds<1024, _, RGB8, _, _>; // CORRECT - use buffer_size function type Driver = RmtSmartLeds<{ buffer_size::(20) }, _, RGB8, _, _>; ``` -------------------------------- ### Import Color Types for SmartLEDs Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/configuration.md Import necessary color type definitions from the `smart_leds_trait` crate. These types define the structure and channels for different LED configurations. ```rust use smart_leds_trait::{RGB8, RGBW, RGBCCT, White, CctWhite}; ``` -------------------------------- ### Perform Parallel Async Writes with Embassy Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md Dispatch multiple LED driver updates concurrently using Embassy's join functionality. This is useful for processing several LED operations simultaneously. ```rust use embassy_futures::join::join; // Prepare two separate LED operations let fut1 = led_driver1.write(colors1.iter().cloned()); let fut2 = led_driver2.write(colors2.iter().cloned()); // Dispatch both simultaneously let (res1, res2) = join(fut1, fut2).await; res1?; res2?; ``` -------------------------------- ### RmtSmartLeds Struct and Constructors Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/DOCUMENTATION_MAP.md Documentation for the RmtSmartLeds struct, its type parameters, and its constructor methods. This is the main entry point for using the RMT driver. ```APIDOC ## RmtSmartLeds Struct ### Description The main driver struct for controlling smart LEDs using the RMT peripheral. ### Type Parameters - `T`: Represents the timing configuration for the LEDs. - `C`: Represents the color type. - `O`: Represents the color channel order. - `P`: Represents the platform-specific peripheral configuration. ### Constructor Methods #### `new(rmt_channel: P::RmtChannel, led_buffer: &'a mut [C]) -> Self` Initializes a new `RmtSmartLeds` instance with the specified RMT channel and LED buffer. This is a blocking constructor. #### `new_with_memsize(rmt_channel: P::RmtChannel, buffer_size: usize) -> Self` Initializes a new `RmtSmartLeds` instance with the specified RMT channel and a calculated buffer size. This constructor allocates memory for the LED buffer internally. ``` -------------------------------- ### Async Error Propagation Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/errors.md Shows how to handle errors when writing to LEDs asynchronously using standard Future error handling patterns. ```rust use smart_leds::SmartLedsWriteAsync; match led_driver.write(colors).await { Ok(()) => { /* success */ }, Err(e) => defmt::error!("Async LED write failed: {:?}", e), } ``` -------------------------------- ### Single-Channel Color Order Implementation Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/color-order.md Provides a trivial color order for single-channel white LEDs. It ignores the channel parameter and always returns the single brightness value. Suitable for dimmable white LED strips. ```rust pub enum SingleChannel {} impl ColorOrder> for SingleChannel where T: Copy + Unsigned + Into, { fn get_channel_data(color: &White, _channel: u8) -> T { color.0 } } ``` ```rust type WhiteDriver = WhiteSmartLeds< { buffer_size::>(20) }, Blocking, Ws2812Timing >; let mut driver = WhiteDriver::new(rmt.channel0, gpio_pin)?; // Send brightness values let brightness = [White(255), White(200), White(100)]; driver.write(brightness)?; ``` -------------------------------- ### SmartLedsWrite and SmartLedsWriteAsync Traits Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/DOCUMENTATION_MAP.md Documentation for the SmartLedsWrite and SmartLedsWriteAsync traits, which define the methods for writing LED data. ```APIDOC ## SmartLedsWrite Trait ### Description Provides a blocking interface for writing color data to the LEDs. ### Methods #### `write(&mut self, colors: &[C]) -> Result<(), Self::Error>` Writes a slice of colors to the LED strip. This operation is blocking. ## SmartLedsWriteAsync Trait ### Description Provides an asynchronous interface for writing color data to the LEDs. ### Methods #### `write_async(&mut self, colors: &[C]) -> impl Future>` Writes a slice of colors to the LED strip asynchronously. This operation is non-blocking. ``` -------------------------------- ### Handle Initialization Errors (Non-Recoverable) Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/errors.md Shows how to handle non-recoverable initialization errors for RmtSmartLeds. This pattern uses a match statement to either unwrap the driver or panic if configuration fails. ```rust let driver = match RmtSmartLeds::new(channel, pin) { Ok(d) => d, Err(e) => { defmt::error!("RMT configuration failed: {:?}", e); panic!("Cannot recover from initialization error"); } }; ``` -------------------------------- ### Flush LED Data (Blocking Mode) Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/rmt-smartleds.md Resends previously prepared LED data without re-creating it. Useful for retransmitting data when `Mode = Blocking`. ```rust led_driver.write(brightness(data.iter().cloned(), 50))?; // Later, retransmit the same data led_driver.flush()?; ``` -------------------------------- ### RmtSmartLeds Constructor (Custom Memory Size) Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/configuration.md Use this constructor when you need to allocate a custom amount of RMT memory. This allows for larger LED strips but consumes more RMT channels. Specify the RMT channel, GPIO pin, and the desired memory size (number of RMT memory blocks). ```rust pub fn new_with_memsize(channel: Ch, pin: P, memsize: u8) -> Result where Ch: TxChannelCreator<'d, Mode>, P: PeripheralOutput<'d>, ``` -------------------------------- ### RmtSmartLeds::new Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/rmt-smartleds.md Creates a new RmtSmartLeds driver with default RMT memory size (1 block). This is the standard initialization path for most applications. ```APIDOC ## RmtSmartLeds::new ### Description Creates a new RmtSmartLeds driver with default RMT memory size (1 block). This is the standard initialization path for most applications. ### Method `new` ### Parameters #### Path Parameters - `channel` (TxChannelCreator<'d, Mode>) - Required - RMT transmit channel (blocking or async) - `pin` (PeripheralOutput<'d>) - Required - GPIO pin connected to LED data line ### Returns `Result` ### Errors - `RmtConfigError::InvalidMemSize` if invalid RMT configuration - `RmtConfigError::InvalidClockSource` if clock configuration fails ### Request Example ```rust use esp_hal::{rmt::Rmt, time::Rate, peripherals}; use esp_hal_smartled::{RmtSmartLeds, Ws2812Timing, buffer_size, color_order}; use smart_leds::RGB8; let rmt = Rmt::new(peripherals.RMT, Rate::from_mhz(80))?; let mut led_driver = RmtSmartLeds::<{ buffer_size::(10) }, _, RGB8, color_order::Grb, Ws2812Timing>::new( rmt.channel0, peripherals.GPIO2 )?; ``` ``` -------------------------------- ### Initialize RmtSmartLeds with Default Memory Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/rmt-smartleds.md Creates a new RmtSmartLeds driver using the default RMT memory size (1 block). This is the standard initialization for most applications. Ensure RMT and the target GPIO pin are correctly configured. ```rust use esp_hal::{rmt::Rmt, time::Rate, peripherals}; use esp_hal_smartled::{RmtSmartLeds, Ws2812Timing, buffer_size, color_order}; use smart_leds::RGB8; let rmt = Rmt::new(peripherals.RMT, Rate::from_mhz(80))?; let mut led_driver = RmtSmartLeds::<{ buffer_size::(10) }, _, RGB8, color_order::Grb, Ws2812Timing>::new( rmt.channel0, peripherals.GPIO2 )?; ``` -------------------------------- ### Handle Transmission Errors (Rare) Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/errors.md Illustrates how to catch and log rare transmission errors from the LED driver. These errors typically indicate hardware issues or timing violations and are logged but not necessarily fatal. ```rust match led_driver.write(colors) { Ok(()) => defmt::info!("LEDs updated"), Err(AdapterError::TransmissionError(e)) => { defmt::warn!("LED transmission failed: {:?}", e); // Log but continue — may be transient } Err(AdapterError::BufferSizeExceeded) => { defmt::error!("Buffer size exceeded — fix LED count"); // Fatal error requiring code change } } ``` -------------------------------- ### Write Correct Number of LEDs Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md The number of colors provided to the `write` function must exactly match the buffer size configured for the number of LEDs. Mismatches will result in an error. ```rust // Buffer configured for 10 LEDs const BUFFER: usize = buffer_size::(10); // WRONG - 11 colors let colors = [RGB8::new(255, 0, 0); 11]; driver.write(colors.iter().cloned())?; // Error! // CORRECT - exactly 10 colors let colors = [RGB8::new(255, 0, 0); 10]; driver.write(colors.iter().cloned())?; // OK ``` -------------------------------- ### Rgb Color Order Implementation Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/color-order.md Standard RGB color order. Used by some discrete RGB LED controllers. ```rust pub enum Rgb {} impl ColorOrder> for Rgb where T: Copy + Unsigned + Into, { fn get_channel_data(color: &RGB, channel: u8) -> T { match channel { 0 => color.r, 1 => color.g, 2 => color.b, _ => unreachable!(), } } } ``` ```rust type RgbDriver = RmtSmartLeds<_, _, RGB8, color_order::Rgb, Ws2812Timing>; ``` -------------------------------- ### Use Correct Timing for LED Type Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md Select the timing configuration that matches the specific LED type being used. Using incorrect timing, such as WS2812 timing for SK68XX LEDs, will prevent them from working correctly. ```rust // WRONG - SK68XX LED with WS2812 timing type Driver = RmtSmartLeds<_, _, RGB8, _, Ws2812Timing>; // Won't work! // CORRECT - SK68XX LED with SK68XX timing type Driver = RmtSmartLeds<_, _, RGB8, _, Sk68xxTiming>; // Works ``` -------------------------------- ### Ws2812Timing Implementation Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/timing.md Implements the `Timing` trait for the original WS2812 LED controller IC. This timing is more forgiving and suitable for older WS2812 chips and some clones. ```rust pub enum Ws2812Timing {} impl Timing for Ws2812Timing { const TIME_0_HIGH: u16 = 350; // 0-bit high: 350 ns const TIME_0_LOW: u16 = 700; // 0-bit low: 700 ns (total: 1050 ns) const TIME_1_HIGH: u16 = 800; // 1-bit high: 800 ns const TIME_1_LOW: u16 = 600; // 1-bit low: 600 ns (total: 1400 ns) } ``` -------------------------------- ### Brg Color Order Implementation Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/color-order.md Blue-Red-Green color order. Rare, check LED datasheet. ```rust pub enum Brg {} impl ColorOrder> for Brg where T: Copy + Unsigned + Into, { fn get_channel_data(color: &RGB, channel: u8) -> T { match channel { 0 => color.b, 1 => color.r, 2 => color.g, _ => unreachable!(), } } } ``` -------------------------------- ### SingleChannel Color Order Implementation Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/types.md Single-channel color order for monochrome white LEDs. Channel 0 = brightness. Used for single-channel LED control. ```rust pub enum SingleChannel {} impl ColorOrder> for SingleChannel where T: Copy + Unsigned + Into, ``` -------------------------------- ### Enable defmt Support Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md Add the 'defmt' feature to your Cargo.toml to enable defmt logging. This allows for structured logging output, useful for debugging. ```toml [dependencies] esp-hal-smartled = { version = "0.28.2", features = ["defmt"] } ``` ```rust // Then use defmt logging: defmt::info!("LED configuration complete"); match led_driver.write(colors) { Ok(()) => defmt::info!("LEDs updated"), Err(e) => defmt::error!("LED error: {}", e), } ``` -------------------------------- ### Write LED Data (Blocking Mode) Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/rmt-smartleds.md Converts color data to RMT pulse format and transmits to LEDs, blocking until transmission completes. Implemented when `Mode = Blocking`. ```rust use smart_leds::{RGB8, SmartLedsWrite, brightness}; let data = [ RGB8 { r: 255, g: 0, b: 0 }, // Red RGB8 { r: 0, g: 255, b: 0 }, // Green RGB8 { r: 0, g: 0, b: 255 }, // Blue ]; led_driver.write(brightness(data.iter().cloned(), 100))?; ``` -------------------------------- ### RGBCCT Implementation Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/trait-implementations.md Implementation of the Color trait for RGBCCT color type, supporting 5 channels (Red, Green, Blue, Cold-white, Warm-white) for tunable white LEDs. ```APIDOC #### RGBCCT ```rust impl Color for RGBCCT where T: Unsigned + Into, { const CHANNELS: u8 = 5; type ChannelType = T; } ``` **Characteristics**: - 5 channels: Red, Green, Blue, Cold-white, Warm-white - Used for tunable white (color temperature) LEDs ``` -------------------------------- ### buffer_size() function Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/INDEX.md Calculates the required RMT buffer size for a given number of LEDs. This is useful for pre-allocating memory. ```APIDOC ## buffer_size() function ### Description Calculate RMT buffer requirements. ### Method free function ### Parameters - **num_leds** (usize) - The number of LEDs to drive. ``` -------------------------------- ### Control LED Brightness and Gamma Correction Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/usage-guide.md Apply brightness adjustments and gamma correction to LED colors using utility functions from the smart-leds crate. Ensure RGB8 is imported. ```rust use smart_leds::{brightness, gamma}; let colors = [ RGB8 { r: 255, g: 0, b: 0 }, RGB8 { r: 0, g: 255, b: 0 }, ]; // Apply 50% brightness led_driver.write(brightness(colors.iter().cloned(), 128))?; // Apply gamma correction (makes colors appear more natural) led_driver.write(gamma(colors.iter().cloned()))?; // Combine: gamma correction + brightness led_driver.write(brightness(gamma(colors.iter().cloned()), 100))?; ``` -------------------------------- ### Logging LED Errors with Defmt Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/errors.md When the `defmt` feature is enabled, `AdapterError` can be logged using `defmt::error!`. Ensure the `defmt` feature is active in your project. ```rust #[cfg(feature = "defmt")] { defmt::error!("LED error: {}", led_error); // Works with defmt } ``` -------------------------------- ### Module Structure Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/INDEX.md This diagram illustrates the module structure of the esp-hal-smartled library, showing the organization of structs, type aliases, enums, traits, and functions. ```text esp_hal_smartled ├── RmtSmartLeds (struct) ├── Rgb8RmtSmartLeds (type alias) ├── Ws2812SmartLeds (type alias) ├── Sk68xxRgbwSmartLeds (type alias) ├── WhiteSmartLeds (type alias) ├── AdapterError (enum) ├── Timing (trait) │ ├── Ws2812Timing │ ├── Ws2812bTiming │ ├── Sk68xxTiming │ ├── Ws2811Timing │ └── Ws2811LowSpeedTiming ├── Color (trait) ├── ColorOrder (trait) ├── buffer_size (function) └── color_order (module) ├── Rgb ├── Rbg ├── Grb ├── Gbr ├── Brg ├── Bgr ├── Rgbw └── SingleChannel ``` -------------------------------- ### Initialize RMT with 80 MHz Clock Source Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/configuration.md Initialize the RMT peripheral with an 80 MHz clock source. This is the default for ESP32/ESP32-S3 and matches the APB clock. This configuration is passed to Rmt::new() and cannot be changed after driver creation. ```rust let rmt = Rmt::new(peripherals.RMT, Rate::from_mhz(80))?; ``` -------------------------------- ### SmartLedsWriteAsync Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/functions.md Async interface for LED control, provided by the `smart_leds_trait`. ```APIDOC ## SmartLedsWriteAsync ### Description Async interface for LED control. Implemented by `RmtSmartLeds`. ### Method Signature ```rust fn write(&mut self, iterator: T) -> impl Future> where T: IntoIterator, I: Into; ``` ### Type Parameters - `Error`: The error type associated with writing to the LEDs asynchronously. - `Color`: The color type used for the LEDs. ### Parameters - **iterator**: An iterator that yields items convertible into the `Color` type. ### Returns - `impl Future>`: A future that resolves to Ok if the write operation was successful, or an error if it failed. ``` -------------------------------- ### Timing trait Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/INDEX.md Specifies the precise timing requirements for different LED models. This trait is crucial for reliable LED control. ```APIDOC ## Timing trait ### Description LED timing specification. Crucial for reliable LED control across different models. ### Type trait ``` -------------------------------- ### White Implementation Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/trait-implementations.md Implementation of the Color trait for White color type, supporting a single channel for brightness, used for monochrome white LEDs. ```APIDOC #### White ```rust impl Color for White where T: Unsigned + Into, { const CHANNELS: u8 = 1; type ChannelType = T; } ``` **Characteristics**: - 1 channel: Brightness only - Used for monochrome white LEDs ``` -------------------------------- ### Usage of AdapterError conversion Source: https://github.com/kleinesfilmroellchen/esp-hal-smartled/blob/main/_autodocs/api-reference/trait-implementations.md Demonstrates how to use the .into() method to convert an RMT error into an AdapterError. This is useful for handling errors from RMT operations. ```rust let result: Result<(), AdapterError> = rmt_operation.map_err(|e| e.into()); ```