#led-display #led-matrix #micro-bit #control #monochrome #direct

no-std tiny-led-matrix

A library for direct control of a small monochrome LED display

4 releases (stable)

1.0.2 Jan 7, 2020
1.0.1 Nov 16, 2019
1.0.0 Apr 27, 2019
0.1.0 Mar 10, 2019

#555 in Embedded development

Download history 326/week @ 2024-07-21 364/week @ 2024-07-28 315/week @ 2024-08-04 443/week @ 2024-08-11 387/week @ 2024-08-18 441/week @ 2024-08-25 445/week @ 2024-09-01 342/week @ 2024-09-08 315/week @ 2024-09-15 329/week @ 2024-09-22 285/week @ 2024-09-29 160/week @ 2024-10-06 466/week @ 2024-10-13 231/week @ 2024-10-20 398/week @ 2024-10-27 262/week @ 2024-11-03

1,363 downloads per month
Used in 9 crates (4 directly)

MIT/Apache

30KB
192 lines

tiny-led-matrix

A Rust library for direct control of a small monochrome LED display.

This is designed to support the micro:bit's 5×5 display, but nothing in this crate is specific to the micro:bit.

Documentation

https://docs.rs/tiny-led-matrix

Changelog

See CHANGELOG.md.

Licence

Copyright 2019 Matthew Woodcraft.

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 licence, shall be dual licensed as above, without any additional terms or conditions.


lib.rs:

A library for direct control of a small monochrome LED display.

This is designed to support the micro:bit's 5×5 display, but nothing in this crate is specific to the micro:bit.

The library assumes the display is internally organised as a two-dimensional matrix of rows and columns, with the individual LEDs addressed directly (typically with one GPIO pin for each row and one for each column).

It isn't designed for the kind of display where you “clock in” the data for an LED row using a smaller number of output pins.

Display model

The LED display must be organised as a two-dimensional array of matrix rows and matrix columns. These describe how the LEDs are wired up, and need not match their visible arrangement.

At any time, LEDs from at most one matrix row of the display are lit; the display driver repeatedly lights LEDs from each row in turn to create the illusion of a stable image.

At present this crate supports at most 16 matrix columns. There's no strict limit on the number of rows, but in practice it must be small so that the LEDs are lit for a reasonable proportion of the time.

Greyscale model

LED brightness levels are described using a scale from 0 (off) to 9 (brightest) inclusive.

These are converted to time slices using the same relative durations as the micro:bit MicroPython port uses.

The time slice for each level above 1 is approximately 1.9× the slice for the previous level.

If there are three matrix rows in the display, an LED with brightness 9 is lit for one third of the time.

Configuring the library for a device.

To use this library, you will have to supply implementations of a number of traits, describing your device and its display.

Matrix

You must supply an implementation of the Matrix trait to describe the matrix dimensions, and how the matrix corresponds to the visible arrangement of LEDs.

Images and Render

The Render trait defines the interface that an image-like type needs to provide in order to be displayed.

The image reports the brightness to use for a given LED, given coordinates according to the visible arrangement.

This crate doesn't supply any implementations of Render; you should define at least one image type of a suitable size and implement Render for it.

Frames

Types implementing Render are used to update a Frame (which is in turn passed to a Display).

A Frame instance is a 'compiled' representation of a greyscale image of the size required by the display, in a form that's more directly usable by the display code.

This is exposed in the public API so that you can construct the Frame representation in code running at a low priority. Then only [Display::set_frame()] has to be called in code that can't be interrupted by the display timer.

You must supply an implementation of the Frame trait.

Timer control

The Display expects to control a single timer which will generate interrupts at appropriate times. [Display::handle_event()] is intended to be called from these interrupts.

You must supply an implementation of the DisplayTimer trait providing the interface that the Display needs to control the timer.

The DisplayTimer implementation determines the refresh rate for the display.

The Display requests an interrupt for the point in time when the next row is due to be lit. When rendering greyscale images, it requests additional interrupts within each row's time period. It only requests interrupts for the greyscale levels which are required for what's currently being displayed.

LED control

The Display expects to be able to light an arbitrary subset of the LEDs in a given matrix row.

You must supply an implementation of the DisplayControl trait to provide the interface that it needs.

Using the library

Display

A Display instance controls the LEDs and programs a timer. There will normally be a single Display instance in a program using this library.

Display is generic over a type implementing Frame, which in turn determines the Matrix in use.

Putting it together

Once you have provided implementations of all the necessary traits, you can use this library as follows:

When your program starts, call [initialise_control()] (passing it the device implementing DisplayControl) and [initialise_timer()] (passing it the device implementing DisplayTimer), and create a Display using your Frame type.

In an interrupt handler for the timer you used for initialise_timer(), call [Display::handle_event()], passing it the same two devices.

To display an image: create a Frame instance, use [Frame::set()] to put the image in it, then call [Display::set_frame()].

You can call set_frame() at any time, so long as you're not interrupting, or interruptable by, handle_event().

Once you've called set_frame(), you are free to reuse the Frame instance.

No runtime deps