Skip to main content

Crate esp_hub75

Crate esp_hub75 

Source
Expand description

§ESP-HUB75

A no-std Rust driver for HUB75-style LED matrix panels on ESP32-series microcontrollers. HUB75 is a standard interface for driving large, bright, and colorful RGB LED displays, commonly used in digital signage and art installations.

This library provides a high-performance implementation that uses Direct Memory Access (DMA) to drive the display with minimal CPU overhead. It is designed to work with a variety of ESP32 models, using the most efficient peripheral available on each chip:

  • ESP32-S3: Uses the LCD_CAM peripheral
  • ESP32-C6: Uses the PARL_IO peripheral
  • ESP32: Uses the I2S peripheral in parallel mode

§Usage

Here is an example of how to initialize the driver for an ESP32-S3:

//! Example for using the LCD/CAM driver with a HUB75 LED matrix display
//!
//! This example demonstrates how to use the LCD/CAM driver to drive a HUB75 LED
//! matrix display. It uses the ESP32's LCD/CAM peripheral in I8080 mode to send
//! data to the display.

#![no_std]
#![no_main]
#![allow(clippy::uninlined_format_args)]

#[cfg(feature = "defmt")]
use defmt_rtt as _;
use embedded_graphics::geometry::Point;
use embedded_graphics::mono_font::ascii::FONT_5X7;
use embedded_graphics::mono_font::MonoTextStyleBuilder;
use embedded_graphics::prelude::RgbColor;
use embedded_graphics::text::Alignment;
use embedded_graphics::text::Text;
use embedded_graphics::Drawable;
use esp_backtrace as _;
use esp_hal::clock::CpuClock;
use esp_hal::gpio::Pin;
use esp_hal::main;
use esp_hal::time::Rate;
use esp_hub75::framebuffer::compute_frame_count;
use esp_hub75::framebuffer::compute_rows;
use esp_hub75::framebuffer::plain::DmaFrameBuffer;
use esp_hub75::Color;
use esp_hub75::Hub75;
use esp_hub75::Hub75Pins16;

esp_bootloader_esp_idf::esp_app_desc!();

const ROWS: usize = 32;
const COLS: usize = 64;
const BITS: u8 = 4;
const NROWS: usize = compute_rows(ROWS);
const FRAME_COUNT: usize = compute_frame_count(BITS);

type FBType = DmaFrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>;

#[main]
fn main() -> ! {
    let peripherals = esp_hal::init(esp_hal::Config::default().with_cpu_clock(CpuClock::max()));

    let (_, tx_descriptors) = esp_hal::dma_descriptors!(0, FBType::dma_buffer_size_bytes());

    let pins = Hub75Pins16 {
        red1: peripherals.GPIO38.degrade(),
        grn1: peripherals.GPIO42.degrade(),
        blu1: peripherals.GPIO48.degrade(),
        red2: peripherals.GPIO47.degrade(),
        grn2: peripherals.GPIO2.degrade(),
        blu2: peripherals.GPIO21.degrade(),
        addr0: peripherals.GPIO14.degrade(),
        addr1: peripherals.GPIO46.degrade(),
        addr2: peripherals.GPIO13.degrade(),
        addr3: peripherals.GPIO9.degrade(),
        addr4: peripherals.GPIO3.degrade(),
        blank: peripherals.GPIO11.degrade(),
        clock: peripherals.GPIO12.degrade(),
        latch: peripherals.GPIO10.degrade(),
    };

    let mut hub75 = Hub75::new_async(
        peripherals.LCD_CAM,
        pins,
        peripherals.DMA_CH0,
        tx_descriptors,
        Rate::from_mhz(20),
    )
    .expect("failed to create Hub75!");

    let mut fb = FBType::new();
    let text_style = MonoTextStyleBuilder::new()
        .font(&FONT_5X7)
        .text_color(Color::YELLOW)
        .background_color(Color::BLACK)
        .build();
    let point = Point::new(32, 31);
    Text::with_alignment("Hello, World!", point, text_style, Alignment::Center)
        .draw(&mut fb)
        .expect("failed to draw text");
    loop {
        let xfer = hub75
            .render(&fb)
            .map_err(|(e, _hub75)| e)
            .expect("failed to start render!");
        let (result, new_hub75) = xfer.wait();
        hub75 = new_hub75;
        result.expect("transfer failed");
    }
}

§Crate Features

  • esp32: Enable support for the ESP32
  • esp32s3: Enable support for the ESP32-S3
  • esp32c6: Enable support for the ESP32-C6
  • defmt: Enable logging with defmt
  • log: Enable logging with the log crate
  • invert-blank: Invert the blank signal, required for some controller boards.
  • invert-clock: Invert the clock signal. By default the driver outputs data that changes on the falling edge of CLK so that it is stable when the panel latches on the rising edge. Enable this feature if your panel requires the opposite polarity.
  • skip-black-pixels: Forwards to the hub75-framebuffer crate, enabling an optimization that skips writing black pixels to the framebuffer.
  • iram: Place the driver’s hot-path (render / DMA wait functions) in Instruction RAM (IRAM) to avoid flash-cache stalls (for example during Wi-Fi, PSRAM, or SPI-flash activity) that can cause visible flicker. Enabling this feature consumes roughly 5–10 KiB of IRAM.

§Safety

This crate uses unsafe code to interface with hardware peripherals, but it exposes a safe, high-level API.

Re-exports§

pub use hub75_framebuffer as framebuffer;

Structs§

Hub75
HUB75 LED matrix display driver
Hub75Pins8
Pin configuration for a HUB75 panel with an external address latch.
Hub75Pins16
Pin configuration for a HUB75 panel without an external address latch.
Hub75Transfer
Represents an in-progress transfer to the HUB75 display

Enums§

Hub75Error
Represents errors that can occur during HUB75 driver operations.

Traits§

Hub75Pins
A trait for converting a set of HUB75 pins into the required format for a specific ESP32 peripheral.

Type Aliases§

Color
The color type used by the HUB75 driver. Color type used in the framebuffer