Compare commits
5 changed files with 44 additions and 106 deletions
|
|
@ -3,6 +3,7 @@
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
mode=${1:-help}
|
mode=${1:-help}
|
||||||
|
wasm_target="--chrome --headless"
|
||||||
extended=${2:-false}
|
extended=${2:-false}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -18,7 +19,6 @@ features_more=(
|
||||||
spat,gnss_ubx,screen,ble,cam_tx
|
spat,gnss_ubx,screen,ble,cam_tx
|
||||||
spat,gnss_ubx,screen,cam,denm
|
spat,gnss_ubx,screen,cam,denm
|
||||||
spat,gnss_ubx,screen,cam_tx,cam,denm
|
spat,gnss_ubx,screen,cam_tx,cam,denm
|
||||||
gnss_ubx,screen,cam_tx,cam,denm
|
|
||||||
)
|
)
|
||||||
features_test=(
|
features_test=(
|
||||||
spat,cam,denm,uart
|
spat,cam,denm,uart
|
||||||
|
|
|
||||||
13
src/ble.rs
13
src/ble.rs
|
|
@ -120,9 +120,20 @@ pub async fn run(
|
||||||
..
|
..
|
||||||
} = stack.build();
|
} = stack.build();
|
||||||
|
|
||||||
|
let mut features = alloc::vec![];
|
||||||
|
if cfg!(feature = "cam") {
|
||||||
|
features.push("cam");
|
||||||
|
}
|
||||||
|
if cfg!(feature = "denm") {
|
||||||
|
features.push("denm");
|
||||||
|
}
|
||||||
|
if cfg!(feature = "spat") {
|
||||||
|
features.push("mapem");
|
||||||
|
features.push("spatem");
|
||||||
|
}
|
||||||
info!(
|
info!(
|
||||||
"Starting advertising and GATT service for {}",
|
"Starting advertising and GATT service for {}",
|
||||||
crate::util::get_rx_feature_list().join(",")
|
features.join(",")
|
||||||
);
|
);
|
||||||
let server = Server::new_with_config(GapConfig::Peripheral(PeripheralConfig {
|
let server = Server::new_with_config(GapConfig::Peripheral(PeripheralConfig {
|
||||||
name: &name,
|
name: &name,
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,6 @@ mod io;
|
||||||
mod screen;
|
mod screen;
|
||||||
#[cfg(feature = "gnss_ubx")]
|
#[cfg(feature = "gnss_ubx")]
|
||||||
mod ubx;
|
mod ubx;
|
||||||
mod util;
|
|
||||||
|
|
||||||
const WIFI_CHANNEL: radio::Channel = 180;
|
const WIFI_CHANNEL: radio::Channel = 180;
|
||||||
const WIFI_TXPOWER: i8 = 10; // dBm, 2..20
|
const WIFI_TXPOWER: i8 = 10; // dBm, 2..20
|
||||||
|
|
|
||||||
103
src/screen.rs
103
src/screen.rs
|
|
@ -3,7 +3,6 @@
|
||||||
use embedded_graphics::prelude::*;
|
use embedded_graphics::prelude::*;
|
||||||
use embedded_graphics::{geometry, mono_font, pixelcolor, primitives, text};
|
use embedded_graphics::{geometry, mono_font, pixelcolor, primitives, text};
|
||||||
|
|
||||||
#[cfg(feature = "spat")]
|
|
||||||
use crate::applogic;
|
use crate::applogic;
|
||||||
|
|
||||||
pub struct DisplaySize {
|
pub struct DisplaySize {
|
||||||
|
|
@ -84,7 +83,6 @@ where
|
||||||
primitives::PrimitiveStyleBuilder::new()
|
primitives::PrimitiveStyleBuilder::new()
|
||||||
.fill_color(pixelcolor::Rgb565::new(10, 50, 0))
|
.fill_color(pixelcolor::Rgb565::new(10, 50, 0))
|
||||||
.build();
|
.build();
|
||||||
#[cfg(feature = "spat")]
|
|
||||||
const BLANK_SIGNAL_STYLE: primitives::PrimitiveStyle<pixelcolor::Rgb565> =
|
const BLANK_SIGNAL_STYLE: primitives::PrimitiveStyle<pixelcolor::Rgb565> =
|
||||||
primitives::PrimitiveStyleBuilder::new()
|
primitives::PrimitiveStyleBuilder::new()
|
||||||
.fill_color(pixelcolor::Rgb565::CSS_GRAY)
|
.fill_color(pixelcolor::Rgb565::CSS_GRAY)
|
||||||
|
|
@ -120,11 +118,8 @@ where
|
||||||
if self.prev_state != state {
|
if self.prev_state != state {
|
||||||
match &state {
|
match &state {
|
||||||
ScreenState::Uninitialized | ScreenState::Initial => self.draw_slash_screen()?,
|
ScreenState::Uninitialized | ScreenState::Initial => self.draw_slash_screen()?,
|
||||||
#[cfg(feature = "spat")]
|
|
||||||
ScreenState::GlosaSearching(_glosa_searching) => self.draw_glosa_searching()?,
|
ScreenState::GlosaSearching(_glosa_searching) => self.draw_glosa_searching()?,
|
||||||
#[cfg(feature = "spat")]
|
|
||||||
ScreenState::GlosaFound(glosa_found) => self.draw_glosa_found(glosa_found)?,
|
ScreenState::GlosaFound(glosa_found) => self.draw_glosa_found(glosa_found)?,
|
||||||
#[cfg(feature = "spat")]
|
|
||||||
ScreenState::GlosaLocked(glosa_data) => {
|
ScreenState::GlosaLocked(glosa_data) => {
|
||||||
let prev_glosa_data =
|
let prev_glosa_data =
|
||||||
if let ScreenState::GlosaLocked(prev_glosa_data) = &self.prev_state {
|
if let ScreenState::GlosaLocked(prev_glosa_data) = &self.prev_state {
|
||||||
|
|
@ -288,7 +283,7 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "spat")]
|
#[allow(unused)]
|
||||||
fn draw_glosa_searching(&mut self) -> Result<(), D::Error> {
|
fn draw_glosa_searching(&mut self) -> Result<(), D::Error> {
|
||||||
// clear whole display and draw text
|
// clear whole display and draw text
|
||||||
self.clear()?;
|
self.clear()?;
|
||||||
|
|
@ -304,7 +299,7 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "spat")]
|
#[allow(unused)]
|
||||||
fn draw_glosa_found(&mut self, data: &applogic::GlosaFound) -> Result<(), D::Error> {
|
fn draw_glosa_found(&mut self, data: &applogic::GlosaFound) -> Result<(), D::Error> {
|
||||||
// clear whole display and draw text
|
// clear whole display and draw text
|
||||||
self.clear()?;
|
self.clear()?;
|
||||||
|
|
@ -329,8 +324,7 @@ where
|
||||||
// uses full screen width and height
|
// uses full screen width and height
|
||||||
// - from 0 to 105+67 = 172 pixels for small screens
|
// - from 0 to 105+67 = 172 pixels for small screens
|
||||||
// - from 0 to 105+67+20 = 192 pixels for big screens
|
// - from 0 to 105+67+20 = 192 pixels for big screens
|
||||||
#[cfg(feature = "spat")]
|
#[allow(unused, clippy::too_many_lines)]
|
||||||
#[allow(clippy::too_many_lines)]
|
|
||||||
fn draw_glosa(
|
fn draw_glosa(
|
||||||
&mut self,
|
&mut self,
|
||||||
data: &applogic::GlosaSignalInfo,
|
data: &applogic::GlosaSignalInfo,
|
||||||
|
|
@ -344,7 +338,7 @@ where
|
||||||
&& prev.signal_groups.len() != num_signals
|
&& prev.signal_groups.len() != num_signals
|
||||||
{
|
{
|
||||||
// clear everything if number of signals has changed
|
// clear everything if number of signals has changed
|
||||||
self.clear()?;
|
self.clear();
|
||||||
} else {
|
} else {
|
||||||
// only clear maneuver and timing area otherwise (lane type will clear itself)
|
// only clear maneuver and timing area otherwise (lane type will clear itself)
|
||||||
let sig_total_height = 67 + if is_big_height { 20 } else { 0 };
|
let sig_total_height = 67 + if is_big_height { 20 } else { 0 };
|
||||||
|
|
@ -479,83 +473,50 @@ where
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn draw_slash_screen(&mut self) -> Result<(), D::Error> {
|
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()?;
|
self.clear_all()?;
|
||||||
|
|
||||||
let centerline = i32::from(self.size.width) / 2;
|
let sig_width = i32::from(self.size.width) / 3;
|
||||||
|
let circle_dia = 50;
|
||||||
|
let circle_margin = (sig_width - circle_dia) / 2;
|
||||||
|
|
||||||
if cfg!(feature = "spat") {
|
for (idx, style) in [Self::RD_STYLE, Self::YE_STYLE, Self::GN_STYLE]
|
||||||
let sig_width = i32::from(self.size.width) / 3;
|
.iter()
|
||||||
let circle_dia = 50;
|
.enumerate()
|
||||||
let circle_margin = (sig_width - circle_dia) / 2;
|
{
|
||||||
|
#[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
|
||||||
|
let offset = (idx as i32) * sig_width;
|
||||||
|
|
||||||
for (idx, style) in [Self::RD_STYLE, Self::YE_STYLE, Self::GN_STYLE]
|
primitives::Circle::new(
|
||||||
.iter()
|
geometry::Point::new(offset + circle_margin, 15 + self.size.offset_top),
|
||||||
.enumerate()
|
circle_dia.cast_unsigned(),
|
||||||
{
|
|
||||||
#[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(&mut self.target)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// print enabled features
|
// draw welcome text
|
||||||
text::Text::with_alignment(
|
let centerline = i32::from(self.size.width) / 2;
|
||||||
&alloc::format!(
|
|
||||||
"Features:\n{}",
|
embedded_graphics::image::Image::new(
|
||||||
crate::util::get_rx_feature_list().join(",")
|
&self.bike_image,
|
||||||
),
|
geometry::Point::new(centerline - (45 / 2) + 1, 75 + self.size.offset_top),
|
||||||
geometry::Point::new(centerline, 190 + self.size.offset_top),
|
|
||||||
Self::SMALL_TEXT_STYLE,
|
|
||||||
text::Alignment::Center,
|
|
||||||
)
|
)
|
||||||
.draw(&mut self.target)?;
|
.draw(&mut self.target)?;
|
||||||
|
|
||||||
let tx_features = crate::util::get_tx_feature_list();
|
text::Text::with_alignment(
|
||||||
if !tx_features.is_empty() {
|
"C-ITS Signal Phase\nWaiting for GNSS...",
|
||||||
text::Text::with_alignment(
|
geometry::Point::new(centerline, 130 + self.size.offset_top),
|
||||||
&tx_features.join(","),
|
text_style,
|
||||||
geometry::Point::new(centerline, 225 + self.size.offset_top),
|
text::Alignment::Center,
|
||||||
Self::SMALL_TEXT_STYLE,
|
)
|
||||||
text::Alignment::Center,
|
.draw(&mut self.target)?;
|
||||||
)
|
|
||||||
.draw(&mut self.target)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "spat")]
|
|
||||||
fn maneuver_to_str(value: applogic::v2x::map::Maneuvers) -> alloc::string::String {
|
fn maneuver_to_str(value: applogic::v2x::map::Maneuvers) -> alloc::string::String {
|
||||||
alloc::format!(
|
alloc::format!(
|
||||||
"{}{}{}",
|
"{}{}{}",
|
||||||
|
|
|
||||||
33
src/util.rs
33
src/util.rs
|
|
@ -1,33 +0,0 @@
|
||||||
//! Some stuff used at several places
|
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn get_rx_feature_list() -> Vec<&'static str> {
|
|
||||||
let mut features = alloc::vec![];
|
|
||||||
if cfg!(feature = "cam") {
|
|
||||||
features.push("cam");
|
|
||||||
}
|
|
||||||
if cfg!(feature = "denm") {
|
|
||||||
features.push("denm");
|
|
||||||
}
|
|
||||||
if cfg!(feature = "spat") {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue