A Rust library for controlling the Pimoroni Unicorn HAT (8x8 LED matrix) on Raspberry Pi.
Note: This project was developed using Claude Code.
This repository is organized as a Cargo workspace:
unicorn-hat/- Core library for hardware control and drawing primitivesunicorn-hat-extras/- High-level convenience features (fonts, text scrolling, animations)
Most users will want to use the core unicorn-hat crate. The unicorn-hat-extras crate provides optional high-level features like text rendering and scrolling animations.
- Coordinate-based pixel control (x, y) and raw index access
- RGB and HSV color models with conversion
- Display rotation (0°, 90°, 180°, 270°)
- Brightness control (0-255)
- Drawing primitives (lines, rectangles)
- Gradients (horizontal, vertical)
- Color palettes and value-to-color mapping
- Hardware abstraction (BGR format and zigzag mapping handled internally)
- Bitmap font rendering (5×5 font for small displays)
- Text rendering with automatic clipping
- Scrolling text (4 directions: left, right, up, down)
- Frame buffers for double-buffering and smooth animations
- Ticker-tape and notification effects
- Pimoroni Unicorn HAT (8x8, NOT the HD version)
- Raspberry Pi (any model with 40-pin GPIO header)
- Root/sudo privileges or CAP_SYS_RAWIO capability (see Permissions section)
Install required development libraries:
sudo apt-get update
sudo apt-get install -y libclang-dev llvm-devEnable SPI (if not already enabled):
sudo raspi-config
# Navigate to: Interface Options -> SPI -> EnableAdd to your Cargo.toml:
[dependencies]
unicorn-hat = "0.1"For high-level features (text rendering, scrolling, frame buffers), also add:
[dependencies]
unicorn-hat = "0.1"
unicorn-hat-extras = "0.1"use unicorn_hat::{UnicornHat, RGB8};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize the HAT
let mut hat = UnicornHat::new()?;
// Set some pixels
hat.set_pixel(0, 0, RGB8::RED)?;
hat.set_pixel(7, 0, RGB8::GREEN)?;
hat.set_pixel(0, 7, RGB8::BLUE)?;
hat.set_pixel(7, 7, RGB8::YELLOW)?;
// Display changes
hat.display()?;
Ok(())
}Run with sudo:
sudo cargo runuse unicorn_hat::{UnicornHat, HSV};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut hat = UnicornHat::new()?;
// Create a rainbow gradient
for x in 0..8 {
let hue = (x as f32 / 8.0) * 360.0;
let hsv = HSV::new(hue, 1.0, 1.0);
let rgb = hsv.into();
for y in 0..8 {
hat.set_pixel(x, y, rgb)?;
}
}
hat.display()?;
Ok(())
}use unicorn_hat::{UnicornHat, RGB8};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut hat = UnicornHat::new()?;
// Fill with white
hat.fill(RGB8::WHITE);
// Set brightness to 25%
hat.set_brightness(64);
hat.display()?;
Ok(())
}use unicorn_hat::{UnicornHat, Rotate, RGB8};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut hat = UnicornHat::new()?;
// Rotate display 90° clockwise
hat.set_rotation(Rotate::RotCW90);
// Set top-left corner (logical coordinates)
hat.set_pixel(0, 0, RGB8::RED)?;
hat.display()?;
Ok(())
}use unicorn_hat::{UnicornHat, RGB8};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut hat = UnicornHat::new()?;
// Use web-style hex colors
hat.fill(RGB8::from_hex(0xFF69B4)); // Hot pink
hat.display()?;
Ok(())
}The unicorn-hat/examples/ directory contains several runnable programs:
simple.rs- Basic pixel control with colored cornersrainbow.rs- Animated HSV rainbow gradientstatus_monitor.rs- Service health monitoring visualizationgradients.rs- Horizontal and vertical gradient demonstrationsdrawing_demo.rs- Drawing primitives (lines, rectangles)
Additional hardware test and diagnostic examples are also available. See unicorn-hat/examples/README.md for the complete list.
The unicorn-hat-extras/examples/ directory contains examples for high-level features:
double_buffer.rs- Frame buffer and double-buffering demonstrationticker_tape.rs- Horizontal scrolling text (ticker-tape effects)vertical_scroll.rs- Vertical scrolling text demonstrations
Run examples with:
sudo cargo run --example simple
sudo cargo run -p unicorn-hat-extras --example ticker_tapeOr from the workspace root with full package specification:
sudo cargo run -p unicorn-hat --example simple
sudo cargo run -p unicorn-hat-extras --example ticker_tapeUnicornHat- Main controller structRGB8- 8-bit RGB color (0-255 per channel)HSV- Hue/Saturation/Value color modelRotate- Rotation modes (None, 90°, 180°, 270°)
// Initialization
let mut hat = UnicornHat::new()?;
// Pixel control
hat.set_pixel(x, y, color)?; // Set by coordinate
hat.set_pixel_raw(index, color)?; // Set by raw index
hat.get_pixel(x, y)?; // Read pixel
hat.fill(color); // Fill all pixels
hat.clear(); // Clear to black
// Display
hat.display()?; // Render to hardware
// Configuration
hat.set_brightness(128); // 0-255 (default: 128)
hat.set_rotation(Rotate::RotCW90); // Rotate display
// Bulk operations
hat.set_all(&grid)?; // Set from 2D array
let grid = hat.get_all()?; // Read as 2D arrayRGB8::BLACK, RGB8::WHITE, RGB8::RED, RGB8::GREEN, RGB8::BLUE,
RGB8::YELLOW, RGB8::CYAN, RGB8::MAGENTA, RGB8::ORANGE, RGB8::PURPLE(0,0) ──────────► (7,0)
│ │
│ 8x8 Grid │
│ │
▼ ▼
(0,7) ──────────► (7,7)
- Origin
(0,0)is top-left - X increases right (0-7)
- Y increases down (0-7)
- Rotation transforms coordinates before mapping to physical LEDs
The library requires hardware access to control PWM for WS2812 LEDs. On Raspberry Pi, /dev/mem access requires special privileges.
sudo cargo runThis is the simplest approach and works reliably during development.
For production deployments, you can set capabilities on compiled binaries to avoid sudo:
-
Build your program in release mode:
cargo build --release
-
Set the CAP_SYS_RAWIO capability:
sudo setcap cap_sys_rawio=ep target/release/your-program
-
Run without sudo:
./target/release/your-program
Important: Capabilities are tied to specific binaries. If you rebuild, you must set capabilities again.
On Raspberry Pi, accessing /dev/mem requires:
- Read/write permissions (handled by udev rules + gpio group)
- The
CAP_SYS_RAWIOcapability (requires root or setcap)
During development, using sudo is simpler because cargo rebuilds binaries frequently, which clears capabilities. For production binaries that don't change, setting capabilities once is the better approach.
Note: The included 99-ws2812.rules file sets up /dev/mem group permissions, but capabilities must still be set per-binary.
- Audio Conflict: PWM on GPIO 18 conflicts with analog audio output (3.5mm jack). Use HDMI audio or USB audio instead.
- Single Instance: Only one process can control the HAT at a time.
- Brightness: Default brightness is 50% (128/255) for safety. Adjust as needed.
This library has been tested and verified with the following configuration:
- GPIO Pin: 18 (PWM)
- DMA Channel: 10
- LED Type: WS2812
- LED Count: 64 (8×8)
- Frequency: 800 kHz
- Color Format: BGR (handled internally)
- Pixel Mapping: Zigzag pattern (handled internally)
The library automatically handles the physical LED wiring pattern and BGR color format - you always work with logical coordinates and RGB colors.
Generate and view the full API documentation:
cargo doc --no-deps --opencargo testRuns unit tests, doc tests, and automated integration tests.
./scripts/test-hw.shRuns hardware integration tests. The script automatically handles building, setting capabilities, and running tests single-threaded.
First-time setup (optional, avoids password prompts):
sudo visudo
# Add: pp4 ALL=(root) NOPASSWD: /usr/sbin/setcapSee TESTING.md for details.
Run hardware verification examples:
cargo run --example core_test
cargo run --example rotation_test
cargo run --example color_test(Use sudo prefix if permissions not configured)
MIT License - see LICENSE file for details.
This library was developed for personal use but is shared in case it's useful to others.
For details about the development process, architecture decisions, and testing strategy, see docs/DEVELOPMENT.md.
- Built on the
rs_ws281xcrate for WS2812 LED control - Inspired by the official Python library from Pimoroni
- Hardware testing confirmed pixel mapping and color format
Note: This library is specifically for the 8x8 Unicorn HAT. For the 16x16 Unicorn HAT HD, see unicorn-hat-hd-rs.