108 lines
3.2 KiB
Rust
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);
|
|
}
|
|
}
|