85 lines
2.2 KiB
Rust
85 lines
2.2 KiB
Rust
|
//! Driver for the micro:bit led display.
|
||
|
|
||
|
use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive};
|
||
|
use embassy_time::Timer;
|
||
|
|
||
|
use crate::{patterns::PATTERN_START, state};
|
||
|
|
||
|
pub const ROWS: usize = 5;
|
||
|
pub const COLS: usize = 5;
|
||
|
|
||
|
pub type Matrix = [[u8; COLS]; ROWS];
|
||
|
|
||
|
pub struct Display<'a> {
|
||
|
rows: [Output<'a>; ROWS],
|
||
|
cols: [Output<'a>; COLS],
|
||
|
matrix: Matrix,
|
||
|
}
|
||
|
|
||
|
/// Create a low Output from an AnyPin instance.
|
||
|
fn pin_to_output<'a>(x: AnyPin) -> Output<'a> {
|
||
|
Output::new(x, Level::Low, OutputDrive::Standard)
|
||
|
}
|
||
|
|
||
|
impl<'a> Display<'a> {
|
||
|
/// Initialize the display with the provided pins.
|
||
|
pub fn new(rows: [AnyPin; ROWS], cols: [AnyPin; COLS]) -> Self {
|
||
|
let rows = rows.map(pin_to_output);
|
||
|
let cols = cols.map(pin_to_output);
|
||
|
|
||
|
Self {
|
||
|
rows,
|
||
|
cols,
|
||
|
matrix: [[0; COLS]; ROWS],
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Set which leds are active.
|
||
|
pub fn set(&mut self, matrix: Matrix) {
|
||
|
self.matrix = matrix;
|
||
|
}
|
||
|
|
||
|
/// Show the defined pattern on the leds.
|
||
|
pub async fn show(&mut self) {
|
||
|
for (i, row) in self.matrix.iter().enumerate() {
|
||
|
self.rows[i].set_high();
|
||
|
|
||
|
for (j, cell) in row.iter().enumerate() {
|
||
|
if *cell > 0 {
|
||
|
self.cols[j].set_low();
|
||
|
}
|
||
|
}
|
||
|
// TODO: instead of waiting for a set time, try
|
||
|
// implementing some kind of constant refresh rate
|
||
|
Timer::after_micros(10).await;
|
||
|
|
||
|
for col in &mut self.cols {
|
||
|
col.set_high();
|
||
|
}
|
||
|
|
||
|
self.rows[i].set_low();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Show the active pattern on the led screen.
|
||
|
/// React on new pattern messages by showing the new pattern.
|
||
|
#[embassy_executor::task]
|
||
|
pub async fn task(rows: [AnyPin; ROWS], cols: [AnyPin; COLS]) {
|
||
|
let mut state_sub = state::STATE.subscriber().unwrap();
|
||
|
|
||
|
let mut display = Display::new(rows, cols);
|
||
|
display.set(PATTERN_START);
|
||
|
|
||
|
loop {
|
||
|
if let Some(msg) = state_sub.try_next_message_pure() {
|
||
|
if let state::StateChange::Pattern(new_pattern) = msg {
|
||
|
display.set(new_pattern);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
display.show().await;
|
||
|
Timer::after_micros(10).await;
|
||
|
}
|
||
|
}
|