dsn-visualizer/src/matrix/mod.rs

108 lines
3.2 KiB
Rust

use crate::dsn::models::{Signal, Target};
use rpi_led_matrix::{LedCanvas, LedColor, LedMatrix, LedMatrixOptions, LedRuntimeOptions};
use std::collections::HashMap;
struct ColumnStatus {
color: LedColor,
target: Target,
state: i32,
up_signal: Option<Signal>,
down_signal: Option<Signal>,
}
pub struct Display {
matrix: LedMatrix,
column_statuses: HashMap<u32, ColumnStatus>,
}
impl Display {
pub fn new(width: u32, height: u32) -> Self {
let mut matrix_config = LedMatrixOptions::new();
matrix_config.set_cols(width);
matrix_config.set_rows(height);
matrix_config.set_hardware_mapping("adafruit-hat-pwm");
matrix_config.set_pwm_bits(7);
let mut rt_config = LedRuntimeOptions::new();
rt_config.set_gpio_slowdown(0);
let matrix = LedMatrix::new(Some(matrix_config), Some(rt_config)).unwrap();
Self {
matrix,
column_statuses: HashMap::new(),
}
}
pub fn update_status(
&mut self,
color: LedColor,
target: Target,
up_signal: Option<Signal>,
down_signal: Option<Signal>,
) {
self.column_statuses.insert(
target.id,
ColumnStatus {
color,
target,
state: 0,
up_signal,
down_signal,
},
);
}
fn uplink_animation(canvas: &mut LedCanvas, col_status: &mut ColumnStatus, position: i32) {
canvas.draw_line(
col_status.state,
(position) * 2,
col_status.state - 5,
(position) * 2,
&col_status.color,
);
canvas.draw_line(
col_status.state,
(position) * 2 + 1,
col_status.state - 5,
(position) * 2 + 1,
&col_status.color,
);
col_status.state = (col_status.state + 1) % canvas.canvas_size().0;
}
fn downlink_animation(canvas: &mut LedCanvas, col_status: &mut ColumnStatus, position: i32) {
canvas.draw_line(
(canvas.canvas_size().0 - col_status.state) as i32,
(position) * 2,
(canvas.canvas_size().0 - col_status.state + 5) as i32,
(position) * 2,
&col_status.color,
);
canvas.draw_line(
(canvas.canvas_size().0 - col_status.state) as i32,
(position) * 2 + 1,
(canvas.canvas_size().0 - col_status.state + 5) as i32,
(position) * 2 + 1,
&col_status.color,
);
col_status.state = (col_status.state + 1) % canvas.canvas_size().0;
}
pub fn refresh_display(&mut self) {
let mut canvas = self.matrix.offscreen_canvas();
canvas.clear();
let mut pos = 0;
for (_, col_status) in self.column_statuses.iter_mut() {
if let Some(up_signal) = &col_status.up_signal {
Display::uplink_animation(&mut canvas, col_status, pos)
} else if let Some(down_signal) = &col_status.down_signal {
Display::downlink_animation(&mut canvas, col_status, pos)
}
pos += 1
}
self.matrix.swap(canvas);
}
}