//! Screen Output use alloc::vec; use embedded_graphics::prelude::*; use embedded_graphics::{geometry, mono_font, pixelcolor, primitives, text}; use crate::applogic; pub const WIDTH: u16 = 320; pub const HEIGHT: u16 = 172; #[allow(unused)] pub fn clear(target: &mut D) -> Result<(), D::Error> where D: DrawTarget, { let style = primitives::PrimitiveStyleBuilder::new() .fill_color(pixelcolor::Rgb565::BLACK) .build(); primitives::Rectangle::new( geometry::Point::new(0, 0), geometry::Size::new(WIDTH.into(), HEIGHT.into()), ) .into_styled(style) .draw(target)?; Ok(()) } #[allow(unused)] pub fn test_img(target: &mut D) -> Result<(), D::Error> where D: DrawTarget, C: RgbColor, { mipidsi::TestImage::new().draw(target)?; Ok(()) } #[allow(unused)] pub fn draw_glosa(target: &mut D, data: &[applogic::SignalGroupData]) -> Result<(), D::Error> where D: DrawTarget, { let num_signals = data.len(); if num_signals == 0 { return clear(target); } #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)] let sig_width = (WIDTH as i32) / (num_signals as i32); let text_style = mono_font::MonoTextStyle::new(&profont::PROFONT_24_POINT, pixelcolor::Rgb565::WHITE); let blank_style = primitives::PrimitiveStyleBuilder::new() .fill_color(pixelcolor::Rgb565::CSS_GRAY) .build(); let rd_style = primitives::PrimitiveStyleBuilder::new() .fill_color(pixelcolor::Rgb565::CSS_RED) .build(); let ye_style = primitives::PrimitiveStyleBuilder::new() .fill_color(pixelcolor::Rgb565::CSS_YELLOW) // TODO: select nicer color .build(); let gn_style = primitives::PrimitiveStyleBuilder::new() .fill_color(pixelcolor::Rgb565::CSS_GREEN) .build(); // clear maneuver and timing area let style = primitives::PrimitiveStyleBuilder::new() .fill_color(pixelcolor::Rgb565::BLACK) .build(); primitives::Rectangle::new( geometry::Point::new(0, 105), geometry::Size::new(WIDTH.into(), 67), ) .into_styled(style) .draw(target)?; for (idx, sig) in data.iter().enumerate() { #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)] let offset = (idx as i32) * sig_width; let circle_dia = 50; let circle_margin = (sig_width - circle_dia) / 2; let centerline = offset + (sig_width / 2); // draw phase color let style = match sig.phase { applogic::SignalPhase::Unknown => blank_style, applogic::SignalPhase::Red => rd_style, applogic::SignalPhase::Green => gn_style, applogic::SignalPhase::RedYellow | applogic::SignalPhase::Yellow => ye_style, }; primitives::Circle::new( geometry::Point::new(offset + circle_margin, 10), circle_dia as u32, ) .into_styled(style) .draw(target)?; // TODO: draw lane type? // draw maneuver text::Text::with_alignment( &alloc::format!("{}", maneuver_to_str(&sig.maneuver)), geometry::Point::new(centerline, 130), text_style, text::Alignment::Center, ) .draw(target)?; // draw timing indicator if let Some(min_end_sec) = sig.min_end_sec { text::Text::with_alignment( &alloc::format!("{min_end_sec}s"), geometry::Point::new(centerline, 160), text_style, text::Alignment::Center, ) .draw(target)?; } } Ok(()) } #[allow(unused)] pub fn draw_slash_screen(target: &mut D) -> Result<(), D::Error> where D: DrawTarget, { let text_style = mono_font::MonoTextStyle::new(&profont::PROFONT_18_POINT, pixelcolor::Rgb565::WHITE); let blank_style = primitives::PrimitiveStyleBuilder::new() .fill_color(pixelcolor::Rgb565::CSS_GRAY) .build(); let rd_style = primitives::PrimitiveStyleBuilder::new() .fill_color(pixelcolor::Rgb565::CSS_RED) .build(); let ye_style = primitives::PrimitiveStyleBuilder::new() .fill_color(pixelcolor::Rgb565::CSS_YELLOW) // TODO: select nicer color .build(); let gn_style = primitives::PrimitiveStyleBuilder::new() .fill_color(pixelcolor::Rgb565::CSS_GREEN) .build(); clear(target)?; let sig_width = (WIDTH as i32) / 3; let circle_dia = 50; let circle_margin = (sig_width - circle_dia) / 2; for (idx, style) in vec![rd_style, ye_style, gn_style].iter().enumerate() { #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)] let offset = (idx as i32) * sig_width; primitives::Circle::new( geometry::Point::new(offset + circle_margin, 10), circle_dia as u32, ) .into_styled(*style) .draw(target)?; } // draw welcome text let centerline = (WIDTH as i32) / 2; text::Text::with_alignment( "C-ITS Signal Phase Display\nWaiting for GNSS fix...", geometry::Point::new(centerline, 130), text_style, text::Alignment::Center, ) .draw(target)?; Ok(()) } fn maneuver_to_str(value: &applogic::v2x::map::Maneuvers) -> alloc::string::String { alloc::format!( "{}{}{}", if value.left_allowed { "<" } else { " " }, if value.staight_allowed { "^" } else { " " }, if value.right_allowed { ">" } else { " " }, ) }