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, down_signal: Option, } pub struct Display { matrix: LedMatrix, column_statuses: HashMap, } 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, down_signal: Option, ) { 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); } }