Watch
0
0
Fork
You've already forked esp32-c_its-companion
0

screen: Make screen feature work without spat, update splash screen

This commit is contained in:
Jannik Beyerstedt 2026-09-25 13:22:56 +02:00
commit 0bf9e552ff
3 changed files with 86 additions and 34 deletions

View file

@ -3,7 +3,6 @@
set -eu
mode=${1:-help}
wasm_target="--chrome --headless"
extended=${2:-false}
@ -19,6 +18,7 @@ features_more=(
spat,gnss_ubx,screen,ble,cam_tx
spat,gnss_ubx,screen,cam,denm
spat,gnss_ubx,screen,cam_tx,cam,denm
gnss_ubx,screen,cam_tx,cam,denm
)
features_test=(
spat,cam,denm,uart

View file

@ -3,6 +3,7 @@
use embedded_graphics::prelude::*;
use embedded_graphics::{geometry, mono_font, pixelcolor, primitives, text};
#[cfg(feature = "spat")]
use crate::applogic;
pub struct DisplaySize {
@ -83,6 +84,7 @@ where
primitives::PrimitiveStyleBuilder::new()
.fill_color(pixelcolor::Rgb565::new(10, 50, 0))
.build();
#[cfg(feature = "spat")]
const BLANK_SIGNAL_STYLE: primitives::PrimitiveStyle<pixelcolor::Rgb565> =
primitives::PrimitiveStyleBuilder::new()
.fill_color(pixelcolor::Rgb565::CSS_GRAY)
@ -118,8 +120,11 @@ where
if self.prev_state != state {
match &state {
ScreenState::Uninitialized | ScreenState::Initial => self.draw_slash_screen()?,
#[cfg(feature = "spat")]
ScreenState::GlosaSearching(_glosa_searching) => self.draw_glosa_searching()?,
#[cfg(feature = "spat")]
ScreenState::GlosaFound(glosa_found) => self.draw_glosa_found(glosa_found)?,
#[cfg(feature = "spat")]
ScreenState::GlosaLocked(glosa_data) => {
let prev_glosa_data =
if let ScreenState::GlosaLocked(prev_glosa_data) = &self.prev_state {
@ -283,7 +288,7 @@ where
Ok(())
}
#[allow(unused)]
#[cfg(feature = "spat")]
fn draw_glosa_searching(&mut self) -> Result<(), D::Error> {
// clear whole display and draw text
self.clear()?;
@ -299,7 +304,7 @@ where
Ok(())
}
#[allow(unused)]
#[cfg(feature = "spat")]
fn draw_glosa_found(&mut self, data: &applogic::GlosaFound) -> Result<(), D::Error> {
// clear whole display and draw text
self.clear()?;
@ -324,7 +329,8 @@ where
// uses full screen width and height
// - from 0 to 105+67 = 172 pixels for small screens
// - from 0 to 105+67+20 = 192 pixels for big screens
#[allow(unused, clippy::too_many_lines)]
#[cfg(feature = "spat")]
#[allow(clippy::too_many_lines)]
fn draw_glosa(
&mut self,
data: &applogic::GlosaSignalInfo,
@ -338,7 +344,7 @@ where
&& prev.signal_groups.len() != num_signals
{
// clear everything if number of signals has changed
self.clear();
self.clear()?;
} else {
// only clear maneuver and timing area otherwise (lane type will clear itself)
let sig_total_height = 67 + if is_big_height { 20 } else { 0 };
@ -473,50 +479,83 @@ where
#[allow(unused)]
fn draw_slash_screen(&mut self) -> Result<(), D::Error> {
let text_style = mono_font::MonoTextStyle::new(&profont::PROFONT_18_POINT, Self::COLOR_FG);
self.clear_all()?;
let sig_width = i32::from(self.size.width) / 3;
let circle_dia = 50;
let circle_margin = (sig_width - circle_dia) / 2;
let centerline = i32::from(self.size.width) / 2;
for (idx, style) in [Self::RD_STYLE, Self::YE_STYLE, Self::GN_STYLE]
.iter()
.enumerate()
{
#[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
let offset = (idx as i32) * sig_width;
if cfg!(feature = "spat") {
let sig_width = i32::from(self.size.width) / 3;
let circle_dia = 50;
let circle_margin = (sig_width - circle_dia) / 2;
primitives::Circle::new(
geometry::Point::new(offset + circle_margin, 15 + self.size.offset_top),
circle_dia.cast_unsigned(),
for (idx, style) in [Self::RD_STYLE, Self::YE_STYLE, Self::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, 15 + self.size.offset_top),
circle_dia.cast_unsigned(),
)
.into_styled(*style)
.draw(&mut self.target)?;
}
// draw welcome text
#[cfg(feature = "spat")]
embedded_graphics::image::Image::new(
&self.bike_image,
geometry::Point::new(centerline - (45 / 2) + 1, 75 + self.size.offset_top),
)
.draw(&mut self.target)?;
text::Text::with_alignment(
"C-ITS Signal Phase\nWaiting for GNSS...",
geometry::Point::new(centerline, 130 + self.size.offset_top),
Self::MID_TEXT_STYLE,
text::Alignment::Center,
)
.draw(&mut self.target)?;
} else {
text::Text::with_alignment(
"C-ITS Companion",
geometry::Point::new(centerline, 130 + self.size.offset_top),
Self::DEFAULT_TEXT_STYLE,
text::Alignment::Center,
)
.into_styled(*style)
.draw(&mut self.target)?;
}
// draw welcome text
let centerline = i32::from(self.size.width) / 2;
embedded_graphics::image::Image::new(
&self.bike_image,
geometry::Point::new(centerline - (45 / 2) + 1, 75 + self.size.offset_top),
)
.draw(&mut self.target)?;
// print enabled features
text::Text::with_alignment(
"C-ITS Signal Phase\nWaiting for GNSS...",
geometry::Point::new(centerline, 130 + self.size.offset_top),
text_style,
&alloc::format!(
"Features:\n{}",
crate::util::get_rx_feature_list().join(",")
),
geometry::Point::new(centerline, 190 + self.size.offset_top),
Self::SMALL_TEXT_STYLE,
text::Alignment::Center,
)
.draw(&mut self.target)?;
let tx_features = crate::util::get_tx_feature_list();
if !tx_features.is_empty() {
text::Text::with_alignment(
&tx_features.join(","),
geometry::Point::new(centerline, 225 + self.size.offset_top),
Self::SMALL_TEXT_STYLE,
text::Alignment::Center,
)
.draw(&mut self.target)?;
}
Ok(())
}
}
#[cfg(feature = "spat")]
fn maneuver_to_str(value: applogic::v2x::map::Maneuvers) -> alloc::string::String {
alloc::format!(
"{}{}{}",

View file

@ -12,8 +12,21 @@ pub(crate) fn get_rx_feature_list() -> Vec<&'static str> {
features.push("denm");
}
if cfg!(feature = "spat") {
features.push("mapem");
features.push("spatem");
features.push("map");
features.push("spat");
}
features
}
#[allow(unused)]
pub(crate) fn get_tx_feature_list() -> Vec<&'static str> {
let mut features = alloc::vec![];
if cfg!(feature = "cam_tx") {
features.push("auto-cam");
}
if cfg!(feature = "uart") {
features.push("uart-tx");
}
features