Expand description
§Blinksy
Blinksy is a no-std, no-alloc LED control library designed for 1D, 2D, and 3D LED setups, inspired by FastLED and WLED.
§How Blinksy works
- Define your LED
layoutin 1D, 2D, or 3D space - Create your visual
pattern(effect), or choose from our built-inpatternslibrary- The pattern will compute colors for each LED based on its position
- Setup a
driverto send each frame of colors to yourleds
§Features
- No-std, no-alloc: Designed for embedded targets.
- Spatial in 1D, 2D, or 3D: Map out the shape of your LEDs in space.
- Async support: Supports blocking or asynchronous execution.
- Full color support: Supports modern and classic color spaces.
- Global settings: Control overall brightness and color correction.
- Desktop simulation: Simulate your LEDs on your desktop to play with ideas.
- RGB+W support: Supports RGB + White color channels
§LED Support
§Clockless: One-wire (only data, no clock)
§Clocked: Two-wire (data and clock)
- APA102: High-FPS RGB LED, aka DotStar
If you want help to support a new LED chipset, make an issue!
§Pattern (Effect) Library:
If you want help to port a pattern from FastLED / WLED to Rust, make an issue!
§Microcontroller Family Support
Clocked LED support (e.g. APA102):
| Micro | HAL | Blinksy | Recommended Writer | Backup Writer |
|---|---|---|---|---|
| ALL | embedded-hal | blinksy | embedded_hal::spi::SpiBus / embedded_hal_async::spi::SpiBus | Delay |
Clockless LED support (e.g. WS2812):
| Micro | HAL | Blinksy | Recommended Driver | Backup Driver |
|---|---|---|---|---|
| ALL | embedded-hal | blinksy | - | TODO Spi #12 |
| ESP32 | esp-hal | blinksy-esp | Rmt | - |
| RP (2040/2350) | rp-hal | TODO | TODO #36 | - |
| STM32 | stm32-hal | TODO | TODO #78 | - |
| nRF | nrf-hal | TODO | TODO #77 | - |
| atsamd | atsamd | TODO | TODO #67 | - |
| AVR (Arduino) | avr-hal | TODO | TODO #79 | - |
| CH32 | ch32-hal | TODO | TODO #80 | - |
| ??? | - | - | - | - |
If you want help to support a new microcontroller family, make an issue!
§Board Support Packages
- Gledopto: A great LED controller available on AliExpress: Gledopto GL-C-016WL-D
- (TODO) QuinLED: The best DIY and pre-assembled LED controller boards
If you want help to support a new target, make an issue!
§Quick Start
To quickstart a project, see:
To start using the library, see control.
§1D Strip with Rainbow Pattern (Blocking)
§1D Strip with Rainbow Pattern (Blocking)
ⓘ
// Define a 1D layout with 60 LEDs
layout1d!(Layout, 60);
let mut control = ControlBuilder::new_1d()
.with_layout::<Layout, { Layout::PIXEL_COUNT }>()
.with_pattern::<Rainbow>(RainbowParams::default())
.with_driver(/* Insert your LED driver here */)
.with_frame_buffer_size::</* Length of frame buffer */>()
.build();
control.set_brightness(0.5);
loop {
control.tick(/* current time in milliseconds */).unwrap();
}§1D Strip with Rainbow Pattern (Async)
ⓘ
// Define a 1D layout with 60 LEDs
layout1d!(Layout, 60);
let mut control = ControlBuilder::new_1d_async()
.with_layout::<Layout, { Layout::PIXEL_COUNT }>()
.with_pattern::<Rainbow>(RainbowParams::default())
.with_driver(/* Insert your LED driver here */)
.with_frame_buffer_size::</* Length of frame buffer */>()
.build();
control.set_brightness(0.5);
loop {
control.tick(/* current time in milliseconds */).await.unwrap();
}§2D Grid with Noise Pattern (Blocking)
ⓘ
layout2d!(
Layout,
[Shape2d::Grid {
start: Vec2::new(-1., -1.),
horizontal_end: Vec2::new(1., -1.),
vertical_end: Vec2::new(-1., 1.),
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
}]
);
let mut control = ControlBuilder::new_2d()
.with_layout::<Layout, { Layout::PIXEL_COUNT }>()
.with_pattern::<Noise2d<noise_fns::Perlin>>(NoiseParams::default())
.with_driver(/* Insert your LED driver here */)
.with_frame_buffer_size::</* Length of frame buffer */>()
.build();
control.set_brightness(0.5);
loop {
control.tick(/* current time in milliseconds */).unwrap();
}§3D Cube with Noise Pattern (Blocking)
ⓘ
layout3d!(
Layout,
[
// bottom face
Shape3d::Grid {
start: Vec3::new(1., -1., 1.), // right bottom front
horizontal_end: Vec3::new(-1., -1., 1.), // left bottom front
vertical_end: Vec3::new(1., -1., -1.), // right bottom back
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
},
// back face
Shape3d::Grid {
start: Vec3::new(-1., -1., -1.), // left bottom back
horizontal_end: Vec3::new(-1., 1., -1.), // left top back
vertical_end: Vec3::new(1., -1., -1.), // right bottom back
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
},
// right face
Shape3d::Grid {
start: Vec3::new(1., 1., -1.), // right top back
horizontal_end: Vec3::new(1., 1., 1.), // right top front
vertical_end: Vec3::new(1., -1., -1.), // right bottom back
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
},
// front face
Shape3d::Grid {
start: Vec3::new(-1., -1., 1.), // left bottom front
horizontal_end: Vec3::new(1., -1., 1.), // right bottom front
vertical_end: Vec3::new(-1., 1., 1.), // left top front
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
},
// left face
Shape3d::Grid {
horizontal_end: Vec3::new(-1., -1., -1.), // left bottom back
vertical_end: Vec3::new(-1., 1., 1.), // left top front
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
},
// top face
Shape3d::Grid {
start: Vec3::new(1., 1., 1.), // right top front
horizontal_end: Vec3::new(1., 1., -1.), // right top back
vertical_end: Vec3::new(-1., 1., 1.), // left top front
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
}
]
);
let mut control = ControlBuilder::new_3d()
.with_layout::<Layout, { Layout::PIXEL_COUNT }>()
.with_pattern::<Noise3d<noise_fns::Perlin>>(NoiseParams::default())
.with_driver(/* Insert your LED driver here */)
.with_frame_buffer_size::</* Length of frame buffer */>()
.build();
control.set_brightness(0.2);
loop {
control.tick(/* current time in milliseconds */).unwrap();
}§2D Grid with Noise Pattern (Blocking)
ⓘ
layout2d!(
Layout,
[Shape2d::Grid {
start: Vec2::new(-1., -1.),
horizontal_end: Vec2::new(1., -1.),
vertical_end: Vec2::new(-1., 1.),
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
}]
);
let mut control = ControlBuilder::new_2d()
.with_layout::<Layout, { Layout::PIXEL_COUNT }>()
.with_pattern::<Noise2d<noise_fns::Perlin>>(NoiseParams::default())
.with_driver(/* Insert your LED driver here */)
.build();
control.set_brightness(0.5);
loop {
control.tick(/* current time in milliseconds */).unwrap();
}§3D Cube with Noise Pattern (Blocking)
ⓘ
layout3d!(
Layout,
[
// bottom face
Shape3d::Grid {
start: Vec3::new(1., -1., 1.), // right bottom front
horizontal_end: Vec3::new(-1., -1., 1.), // left bottom front
vertical_end: Vec3::new(1., -1., -1.), // right bottom back
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
},
// back face
Shape3d::Grid {
start: Vec3::new(-1., -1., -1.), // left bottom back
horizontal_end: Vec3::new(-1., 1., -1.), // left top back
vertical_end: Vec3::new(1., -1., -1.), // right bottom back
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
},
// right face
Shape3d::Grid {
start: Vec3::new(1., 1., -1.), // right top back
horizontal_end: Vec3::new(1., 1., 1.), // right top front
vertical_end: Vec3::new(1., -1., -1.), // right bottom back
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
},
// front face
Shape3d::Grid {
start: Vec3::new(-1., -1., 1.), // left bottom front
horizontal_end: Vec3::new(1., -1., 1.), // right bottom front
vertical_end: Vec3::new(-1., 1., 1.), // left top front
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
},
// left face
Shape3d::Grid {
start: Vec3::new(-1., 1., -1.), // left top back
horizontal_end: Vec3::new(-1., -1., -1.), // left bottom back
vertical_end: Vec3::new(-1., 1., 1.), // left top front
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
},
// top face
Shape3d::Grid {
start: Vec3::new(1., 1., 1.), // right top front
horizontal_end: Vec3::new(1., 1., -1.), // right top back
vertical_end: Vec3::new(-1., 1., 1.), // left top front
horizontal_pixel_count: 16,
vertical_pixel_count: 16,
serpentine: true,
}
]
);
let mut control = ControlBuilder::new_3d()
.with_layout::<Layout, { Layout::PIXEL_COUNT }>()
.with_pattern::<Noise3d<noise_fns::Perlin>>(NoiseParams::default())
.with_driver(/* Insert your LED driver here */)
.build();
control.set_brightness(0.2);
loop {
control.tick(/* current time in milliseconds */).unwrap();
}Re-exports§
pub use self::control::*;
Modules§
- color
- Color Types and Utilities
- control
- Control System
- driver
- Driver Interface
- layout
- LED Layouts
- leds
- LED Chipsets
- markers
- Type Markers
- pattern
- Pattern Interface
- patterns
- Pattern Implementations
- time
- Time Library
- util