use crate::hal::{
gpio::{Output, Pin, PushPull},
prelude::*,
};
use crate::gpio::{DisplayPins, NUM_COLS, NUM_ROWS};
use embedded_hal::blocking::delay::DelayUs;
#[allow(clippy::upper_case_acronyms)]
pub(crate) type LED = Pin<Output<PushPull>>;
const DEFAULT_DELAY_MS: u32 = 2;
#[cfg(feature = "v1")]
const LED_LAYOUT: [[(usize, usize); 5]; 5] = [
[(0, 0), (1, 3), (0, 1), (1, 4), (0, 2)],
[(2, 3), (2, 4), (2, 5), (2, 6), (2, 7)],
[(1, 1), (0, 8), (1, 2), (2, 8), (1, 0)],
[(0, 7), (0, 6), (0, 5), (0, 4), (0, 3)],
[(2, 2), (1, 6), (2, 0), (1, 5), (2, 1)],
];
pub struct Display {
delay_ms: u32,
rows: [LED; NUM_ROWS],
cols: [LED; NUM_COLS],
}
impl Display {
pub fn new(pins: DisplayPins) -> Self {
let (cols, rows) = pins.degrade();
Display {
delay_ms: DEFAULT_DELAY_MS,
rows,
cols,
}
}
pub fn clear(&mut self) {
for row in &mut self.rows {
row.set_low().ok();
}
for col in &mut self.cols {
col.set_high().ok();
}
}
pub fn set_delay_ms(&mut self, delay_ms: u32) {
self.delay_ms = delay_ms;
}
pub fn set_refresh_rate(&mut self, freq_hz: u32) {
self.delay_ms = 1000 / freq_hz / 3;
}
#[cfg(feature = "v1")]
fn image2matrix(led_image: [[u8; 5]; 5]) -> [[u8; 9]; 3] {
let mut led_matrix: [[u8; 9]; 3] = [[0; 9]; 3];
for (led_image_row, layout_row) in led_image.iter().zip(LED_LAYOUT.iter()) {
for (led_image_val, layout_loc) in led_image_row.iter().zip(layout_row) {
led_matrix[layout_loc.0][layout_loc.1] = *led_image_val;
}
}
led_matrix
}
pub fn show<D: DelayUs<u32>>(
&mut self,
delay: &mut D,
led_display: [[u8; 5]; 5],
duration_ms: u32,
) {
#[cfg(feature = "v1")]
{
let led_matrix = Display::image2matrix(led_display);
self.show_inner(delay, led_matrix, duration_ms);
}
#[cfg(feature = "v2")]
self.show_inner(delay, led_display, duration_ms);
}
fn show_inner<D: DelayUs<u32>>(
&mut self,
delay: &mut D,
led_matrix: [[u8; NUM_COLS]; NUM_ROWS],
duration_ms: u32,
) {
let loops = duration_ms / (self.rows.len() as u32 * self.delay_ms);
for _ in 0..loops {
for (row_line, led_matrix_row) in self.rows.iter_mut().zip(led_matrix.iter()) {
row_line.set_high().ok();
for (col_line, led_matrix_val) in self.cols.iter_mut().zip(led_matrix_row.iter()) {
if *led_matrix_val > 0 {
col_line.set_low().ok();
}
}
delay.delay_us(self.delay_ms * 1000);
for col_line in &mut self.cols {
col_line.set_high().ok();
}
row_line.set_low().ok();
}
}
}
}