diff --git a/.vscode/settings.json b/.vscode/settings.json index e671987b..b45f4589 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "rust-analyzer.check.allTargets": false + "rust-analyzer.check.allTargets": false, + "rust-analyzer.showUnlinkedFileNotification": false } \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index c956f2f9..0eacaeb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ embedded-hal-async = "1.0.0-rc.1" embedded-hal-bus = { version = "0.1.0-rc.1", features = ["async"] } embedded-io = { version = "0.4", features = ["async"] } embedded-menu = "0.4.0" -embedded-svc = { version = "0.25", default-features = false, features = [] } +embedded-svc = { version = "0.25", default-features = false } embassy-net = { version = "0.1.0", features = [ "nightly", "tcp", @@ -32,11 +32,14 @@ log = { version = "0.4.18", default-features = false, features = [ "max_level_info", "release_max_level_info", ] } +logger = { path = "logger" } +signal-processing = { path = "signal-processing" } norfs = { git = "https://github.com/card-io-ecg/norfs.git", features = [ "esp32s3", ] } object-chain = "0.1.3" bad-server = { path = "bad-server" } +defmt = { version = "=0.3.5" } [dependencies] embassy-futures = { version = "0.1.0" } @@ -58,20 +61,19 @@ esp32s3-hal = { version = "0.12.0", optional = true, features = [ esp-backtrace = { version = "0.8.0", features = [ "panic-handler", "exception-handler", -] } # add "halt-cores" +] } esp-println = { version = "0.6.0", default-features = false, features = [ "critical-section", - "colors", - "log", ] } esp-alloc = { version = "0.3.0" } -esp-wifi = { git = "https://github.com/esp-rs/esp-wifi.git", rev = "02239f9", features = [ +esp-wifi = { git = "https://github.com/esp-rs/esp-wifi.git", rev = "15e5a55", default-features = false, features = [ "phy-enable-usb", "ps-min-modem", "wifi", "embedded-svc", "async", "embassy-net", + "utils" ] } display-interface = { git = "https://github.com/therealprof/display-interface.git", branch = "master" } @@ -90,15 +92,16 @@ critical-section = "1.1" device-descriptor = { path = "device-descriptor" } register-access = { path = "register-access" } gui = { path = "gui" } -ads129x = { path = "ads129x" } macros = { path = "macros" } embassy-alloc-taskpool = { path = "embassy-alloc-taskpool" } +ads129x = { path = "ads129x" } max17055 = { path = "max17055", optional = true } -signal-processing = { path = "signal-processing", features = ["nostd"] } +signal-processing = { workspace = true, features = ["nostd"] } replace_with = { version = "0.1", default-features = false, features = [ "nightly", ] } static_cell = { version = "1.2.0", features = ["nightly"] } +bad-server = { path = "bad-server", features = ["embassy"] } embedded-graphics = { workspace = true } embedded-hal = { workspace = true } @@ -112,14 +115,14 @@ embassy-sync = { workspace = true } norfs = { workspace = true } heapless = { workspace = true } -log = { workspace = true } object-chain = { workspace = true } -[patch.'https://github.com/esp-rs/esp-wifi'] -esp-wifi = { git = "https://github.com/bugadani/esp-wifi.git", branch = "dev" } +logger = { workspace = true } +log = { workspace = true, optional = true } +defmt = { workspace = true, optional = true } [features] -default = ["esp32s3"] +default = ["esp32s3", "defmt"] battery_adc = [] battery_max17055 = ["dep:max17055"] @@ -133,14 +136,51 @@ esp32s3 = [ "dep:esp32s3-hal", "esp-backtrace/esp32s3", "esp-println/esp32s3", - "jtag_serial", + "uart", # print via uart, serial_jtag seems to lose bytes "esp-wifi/esp32s3", ] # Print options +uart = ["esp-backtrace/print-uart", "esp-println/uart"] jtag_serial = ["esp-backtrace/print-jtag-serial", "esp-println/jtag_serial"] rtt = ["esp-backtrace/print-rtt", "esp-println/rtt"] +log = [ + "dep:log", + "norfs/log", + "esp-println/log", + "esp-println/colors", + "esp-wifi/log", + "esp32s3-hal/log", + + "logger/log", + "config-site/log", + "ads129x/log", + "max17055?/log", + "bad-server/log", + "gui/log", + "signal-processing/log", +] + +defmt = [ + "dep:defmt", + "embassy-net/defmt", + "norfs/defmt", + "embedded-io/defmt", + "embedded-svc/defmt", + "esp-println/defmt", + "esp-wifi/defmt", + "esp32s3-hal/defmt", + + "logger/defmt", + "config-site/defmt", + "ads129x/defmt", + "max17055?/defmt", + "bad-server/defmt", + "gui/defmt", + "signal-processing/defmt", +] + [package.metadata.espflash] partition_table = "partitions.csv" format = "esp-bootloader" diff --git a/ads129x/Cargo.toml b/ads129x/Cargo.toml index b44855df..49374716 100644 --- a/ads129x/Cargo.toml +++ b/ads129x/Cargo.toml @@ -10,5 +10,12 @@ byteorder = { version = "1.4.3", default-features = false } device-descriptor = { path = "../device-descriptor" } embedded-hal = { workspace = true } embedded-hal-async = { workspace = true } -log = { workspace = true } register-access = { path = "../register-access" } +logger = { workspace = true } +log = { workspace = true, optional = true } +defmt = { workspace = true, optional = true } + +[features] +default = [] +defmt = ["dep:defmt", "logger/defmt", "device-descriptor/defmt"] +log = ["dep:log", "logger/log"] diff --git a/ads129x/src/lib.rs b/ads129x/src/lib.rs index d43d2cf6..9a98eedf 100644 --- a/ads129x/src/lib.rs +++ b/ads129x/src/lib.rs @@ -2,6 +2,9 @@ #![feature(async_fn_in_trait)] #![allow(incomplete_features)] +#[macro_use] +extern crate logger; + use byteorder::{BigEndian, ByteOrder}; use device_descriptor::{ReadOnlyRegister, ReaderProxy, Register}; use embedded_hal::{ @@ -16,6 +19,7 @@ use crate::descriptors::*; pub mod descriptors; #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { InvalidState, UnexpectedDeviceId, @@ -23,7 +27,8 @@ pub enum Error { Transfer(SpiE), } -#[derive(Copy, Clone, Debug, Default)] +#[derive(Copy, Clone, Default, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ConfigRegisters { pub config1: Config1, pub config2: Config2, @@ -99,10 +104,9 @@ impl ConfigRegisters { if config_bytes == readback { Ok(()) } else { - log::warn!( + warn!( "Verification failed: received: {:?}, expected: {:?}", - readback, - config_bytes + readback, config_bytes ); Err(Error::Verification) } @@ -263,11 +267,11 @@ where where RESET: OutputPin, { - reset.set_high().unwrap(); + unwrap!(reset.set_high().ok()); delay.delay_ms(Self::MIN_T_POR); - reset.set_low().unwrap(); + unwrap!(reset.set_low().ok()); delay.delay_ms(Self::MIN_T_RST); - reset.set_high().unwrap(); + unwrap!(reset.set_high().ok()); delay.delay_ms(Self::MIN_RST_WAIT); } } @@ -295,9 +299,9 @@ where .await .map_err(Error::Transfer)?; - Ok(AdsData::new_single_channel( - buffer[bytes..bytes + 6].try_into().unwrap(), - )) + Ok(AdsData::new_single_channel(unwrap!(buffer + [bytes..bytes + 6] + .try_into()))) } pub async fn read_data_2ch_async_rdatac(&mut self) -> Result> { @@ -319,7 +323,7 @@ where .await .map_err(Error::Transfer)?; - Ok(AdsData::new(buffer[bytes..bytes + 9].try_into().unwrap())) + Ok(AdsData::new(unwrap!(buffer[bytes..bytes + 9].try_into()))) } pub async fn write_command_async( @@ -343,10 +347,7 @@ where match read_result.read() { Some(id) => Ok(id), None => { - log::warn!( - "Read unknown device id: {:?}", - read_result.read_field_bits() - ); + warn!("Read unknown device id: {}", read_result.read_field_bits()); Err(Error::UnexpectedDeviceId) } } @@ -367,18 +368,19 @@ where where RESET: OutputPin, { - reset.set_high().unwrap(); + unwrap!(reset.set_high().ok()); delay.delay_ms(Self::MIN_T_POR).await; - reset.set_low().unwrap(); + unwrap!(reset.set_low().ok()); delay.delay_ms(Self::MIN_T_RST).await; - reset.set_high().unwrap(); + unwrap!(reset.set_high().ok()); delay.delay_ms(Self::MIN_RST_WAIT).await; self.write_command_async(Command::SDATAC, &mut []).await } } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Sample { sample: i32, } @@ -395,6 +397,8 @@ impl Sample { } } +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AdsData { status: LoffStat, ch1: Sample, @@ -414,16 +418,16 @@ impl AdsData { pub fn new(buffer: [u8; 9]) -> Self { Self { - status: Self::read_status(buffer[0..3].try_into().unwrap()), - ch1: Self::read_channel(buffer[3..6].try_into().unwrap()), - ch2: Self::read_channel(buffer[6..9].try_into().unwrap()), + status: Self::read_status(unwrap!(buffer[0..3].try_into())), + ch1: Self::read_channel(unwrap!(buffer[3..6].try_into())), + ch2: Self::read_channel(unwrap!(buffer[6..9].try_into())), } } pub fn new_single_channel(buffer: [u8; 6]) -> Self { Self { - status: Self::read_status(buffer[0..3].try_into().unwrap()), - ch1: Self::read_channel(buffer[3..6].try_into().unwrap()), + status: Self::read_status(unwrap!(buffer[0..3].try_into())), + ch1: Self::read_channel(unwrap!(buffer[3..6].try_into())), ch2: Sample { sample: 0 }, } } diff --git a/bad-server/Cargo.toml b/bad-server/Cargo.toml index 215573c2..ac5636fa 100644 --- a/bad-server/Cargo.toml +++ b/bad-server/Cargo.toml @@ -7,12 +7,14 @@ edition = "2021" [dependencies] async-io = { version = "1", optional = true } +defmt = { workspace = true, optional = true } embassy-net = { workspace = true, optional = true } embedded-io = { workspace = true } embedded-svc = { workspace = true } heapless = { workspace = true } httparse = { version = "1.8", default-features = false } -log = { workspace = true } +logger = { workspace = true } +log = { workspace = true, optional = true } smol = { version = "1", optional = true } object-chain = { workspace = true } const-fnv1a-hash = "1.1" @@ -25,7 +27,9 @@ simple_logger = "4.1" default = [] std = ["async-io", "smol"] embassy = ["embassy-net"] +log = ["dep:log", "logger/log"] +defmt = ["dep:defmt", "logger/defmt"] [[example]] name = "simple" -required-features = ["std"] +required-features = ["std", "log"] diff --git a/bad-server/src/connector.rs b/bad-server/src/connector.rs index e6256a39..cc3840bf 100644 --- a/bad-server/src/connector.rs +++ b/bad-server/src/connector.rs @@ -3,6 +3,9 @@ use core::fmt::Debug; use embedded_io::asynch::{Read, Write}; pub trait Connection: Read + Write { + #[cfg(feature = "defmt")] + type AcceptError: Debug + defmt::Format; + #[cfg(not(feature = "defmt"))] type AcceptError: Debug; // TODO: separate listener and socket @@ -13,6 +16,7 @@ pub trait Connection: Read + Write { #[cfg(feature = "embassy")] pub mod embassy_net_compat { + use super::*; use embassy_net::{ tcp::{AcceptError, TcpSocket}, @@ -29,7 +33,7 @@ pub mod embassy_net_compat { fn close(&mut self) { TcpSocket::close(self); TcpSocket::abort(self); - log::debug!("Socket closed"); + debug!("Socket closed"); } } } @@ -118,7 +122,7 @@ pub mod std_compat { let socket = socket.into_inner().unwrap(); socket.shutdown(std::net::Shutdown::Both).unwrap(); - log::debug!("Socket closed"); + debug!("Socket closed"); } } } diff --git a/bad-server/src/handler.rs b/bad-server/src/handler.rs index 575d20a4..7218fb50 100644 --- a/bad-server/src/handler.rs +++ b/bad-server/src/handler.rs @@ -64,7 +64,7 @@ impl<'a> StaticHandler<'a> { let hash = fnv1a_hash_32(body, None); let hash = match const_base::encode(&hash.to_le_bytes(), const_base::Config::B64) { Ok(hash) => hash, - Err(_err) => panic!("Failed to base64-encode hash"), + Err(_err) => ::core::panic!("Failed to base64-encode hash"), }; Self { diff --git a/bad-server/src/lib.rs b/bad-server/src/lib.rs index 9abbc7ba..a6b921c7 100644 --- a/bad-server/src/lib.rs +++ b/bad-server/src/lib.rs @@ -3,6 +3,9 @@ #![feature(impl_trait_projections)] #![allow(incomplete_features)] +#[macro_use] +extern crate logger; + use core::{fmt::Debug, marker::PhantomData}; use embedded_io::{ @@ -149,6 +152,37 @@ where } } +#[cfg(feature = "defmt")] +impl defmt::Format for HandleError +where + C: Io, + C::Error: defmt::Format, +{ + fn format(&self, f: defmt::Formatter) { + match self { + HandleError::Read(f0) => defmt::write!(f, "Read({})", f0), + HandleError::Write(f0) => defmt::write!(f, "Write({})", f0), + HandleError::TooManyHeaders => defmt::write!(f, "TooManyHeaders"), + HandleError::InternalError => defmt::write!(f, "InternalError"), + HandleError::RequestParse(f0) => { + defmt::write!( + f, + "RequestParse({})", + match f0 { + httparse::Error::HeaderName => defmt::intern!("HeaderName"), + httparse::Error::HeaderValue => defmt::intern!("HeaderValue"), + httparse::Error::NewLine => defmt::intern!("NewLine"), + httparse::Error::Status => defmt::intern!("Status"), + httparse::Error::Token => defmt::intern!("Token"), + httparse::Error::TooManyHeaders => defmt::intern!("TooManyHeaders"), + httparse::Error::Version => defmt::intern!("Version"), + } + ) + } + } + } +} + impl BadServer where H: Handler, @@ -197,28 +231,30 @@ where pub async fn listen(&mut self, socket: &mut H::Connection, port: u16) { loop { - log::info!("Wait for connection"); + info!("Wait for connection"); if let Err(e) = socket.listen(port).await { - log::warn!("Connect error: {:?}", e); + warn!("Connect error: {:?}", e); socket.close(); continue; } - log::info!("Connected"); + info!("Connected"); let handle_result = self.handle(socket).await; - if let Err(e) = socket.flush().await { - log::warn!("Flush error: {:?}", e); + if let Err(_e) = socket.flush().await { + warn!("Flush error"); + //warn!("Flush error: {:?}", e); } // Handle errors after flushing - if let Err(e) = handle_result { - log::warn!("Handle error: {:?}", e); + if let Err(_e) = handle_result { + warn!("Handle error"); + //warn!("Handle error: {:?}", e); } socket.close(); - log::info!("Done"); + info!("Done"); } } @@ -232,17 +268,18 @@ where Ok(0) => { // We're here because the previous read wasn't a complete request. Reading 0 // means the request will not ever be completed. - log::warn!("read EOF"); + warn!("read EOF"); return Err(HandleError::Read(ReadError::UnexpectedEof)); } Ok(len) => pos += len, Err(e) => { - log::warn!("read error: {:?}", e); + warn!("read error"); + //warn!("read error: {:?}", e); return Err(HandleError::Read(ReadError::Io(e))); } } - log::debug!("Buffer size: {pos}"); + debug!("Buffer size: {}", pos); let mut headers = [httparse::EMPTY_HEADER; MAX_HEADERS]; let mut req = httparse::Request::new(&mut headers); @@ -256,7 +293,8 @@ where // We need to read more } Err(e) => { - log::warn!("Parsing request failed: {e}"); + warn!("Parsing request failed"); + //warn!("Parsing request failed: {}", e); return Err(HandleError::RequestParse(e)); } }; diff --git a/bad-server/src/method.rs b/bad-server/src/method.rs index 7a006dac..eff5c320 100644 --- a/bad-server/src/method.rs +++ b/bad-server/src/method.rs @@ -1,4 +1,5 @@ #[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Method { Delete, Get, diff --git a/bad-server/src/request.rs b/bad-server/src/request.rs index e07d2bd6..1ed5b0c0 100644 --- a/bad-server/src/request.rs +++ b/bad-server/src/request.rs @@ -21,16 +21,16 @@ impl<'req, 's, C: Connection> Request<'req, 's, C> { body: RequestBody<'req, 's, C>, ) -> Result { let Some(path) = req.path else { - log::warn!("Path not set"); + warn!("Path not set"); return Err(ResponseStatus::BadRequest); }; let Some(method) = req.method.and_then(Method::new) else { - log::warn!("Unknown method: {:?}", req.method); + warn!("Unknown method: {:?}", req.method); return Err(ResponseStatus::BadRequest); }; - log::info!("[{}] {path}", method.as_str()); + info!("[{}] {}", method.as_str(), path); Ok(Self { method, @@ -54,7 +54,7 @@ impl<'req, 's, C: Connection> Request<'req, 's, C> { while !self.is_complete() && !buffer.is_empty() { read += self.read(&mut buffer[read..]).await?; } - log::debug!("Read {read} bytes"); + debug!("Read {} bytes", read); Ok(&mut buffer[..read]) } diff --git a/bad-server/src/request_body.rs b/bad-server/src/request_body.rs index 09752494..a86ce72a 100644 --- a/bad-server/src/request_body.rs +++ b/bad-server/src/request_body.rs @@ -183,7 +183,10 @@ impl<'buf, 's, C: Connection> ContentLengthReader<'buf, 's, C> { } } -pub enum ReadError { +pub enum ReadError +where + C: Io, +{ Io(C::Error), Encoding, UnexpectedEof, @@ -202,6 +205,21 @@ where } } +#[cfg(feature = "defmt")] +impl defmt::Format for ReadError +where + C: Io, + C::Error: defmt::Format, +{ + fn format(&self, f: defmt::Formatter) { + match self { + ReadError::Io(f0) => defmt::write!(f, "Io({})", f0), + ReadError::Encoding => defmt::write!(f, "Encoding"), + ReadError::UnexpectedEof => defmt::write!(f, "UnexpectedEof"), + } + } +} + pub type ReadResult = Result>; #[derive(Clone, Copy, PartialEq, Eq)] diff --git a/bad-server/src/response.rs b/bad-server/src/response.rs index ba89045e..6a4ae29e 100644 --- a/bad-server/src/response.rs +++ b/bad-server/src/response.rs @@ -5,6 +5,7 @@ use httparse::Header; use crate::{connector::Connection, HandleError}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ResponseStatus { Ok = 200, NotModified = 304, @@ -76,7 +77,7 @@ impl<'s, C: Connection> Response<'s, C, Initial> { .await .map_err(HandleError::Write)?; - log::debug!("Response status: {}", status as u16); + debug!("Response status: {}", status as u16); let mut status_code = heapless::Vec::::new(); if write!(&mut status_code, "{}", status as u16).is_err() { diff --git a/build.rs b/build.rs index 57a7496b..772bc5e8 100644 --- a/build.rs +++ b/build.rs @@ -37,4 +37,8 @@ fn main() { panic!("Can't select more than one of: hw_v1, hw_v2"); } + + if cfg!(feature = "defmt") { + println!("cargo:rustc-link-arg=-Tdefmt.x"); + } } diff --git a/config-site/Cargo.toml b/config-site/Cargo.toml index 9f0d9fe6..2171822b 100644 --- a/config-site/Cargo.toml +++ b/config-site/Cargo.toml @@ -7,10 +7,12 @@ edition = "2021" [dependencies] bad-server = { workspace = true } +defmt = { workspace = true, optional = true } embassy-sync = { workspace = true, optional = true } embedded-io = { workspace = true, optional = true } heapless = { workspace = true } -log = { workspace = true } +logger = { workspace = true } +log = { workspace = true, optional = true } norfs = { git = "https://github.com/card-io-ecg/norfs.git", optional = true } smol = { version = "1.3", optional = true } @@ -20,7 +22,7 @@ minify-html = "0.11.1" [[example]] name = "simple" -required-features = ["bad-server/std"] +required-features = ["bad-server/std", "bad-server/log"] [dev-dependencies] simple_logger = "4.1" @@ -30,3 +32,5 @@ smol = "1" default = [] embedded = ["dep:norfs", "dep:embassy-sync", "dep:embedded-io", "bad-server/embassy"] std = ["dep:smol", "bad-server/std"] +log = ["dep:log", "bad-server/log"] +defmt = ["dep:defmt", "bad-server/defmt"] diff --git a/config-site/src/data/network.rs b/config-site/src/data/network.rs index bda1d99e..782d9107 100644 --- a/config-site/src/data/network.rs +++ b/config-site/src/data/network.rs @@ -4,6 +4,7 @@ use embedded_io::asynch::{Read, Write}; use norfs::storable::{LoadError, Loadable, Storable}; #[derive(Clone, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct WifiNetwork { pub ssid: heapless::String<32>, pub pass: heapless::String<64>, diff --git a/config-site/src/handlers/add_new_network.rs b/config-site/src/handlers/add_new_network.rs index ef7d50a2..5204fee2 100644 --- a/config-site/src/handlers/add_new_network.rs +++ b/config-site/src/handlers/add_new_network.rs @@ -18,7 +18,7 @@ impl<'a> AddNewNetwork<'a> { status: ResponseStatus, message: &str, ) -> Result<(), HandleError> { - log::warn!("Request error: {status:?}, {message}"); + warn!("Request error: {:?}, {}", status, message); request .send_response(status) .await? @@ -33,7 +33,7 @@ impl RequestHandler for AddNewNetwork<'_> { async fn handle(&self, mut request: Request<'_, '_, C>) -> Result<(), HandleError> { let mut buf = [0u8; 100]; - log::debug!("Reading POST data"); + debug!("Reading POST data"); let post_data = request.read_all(&mut buf).await?; if !request.is_complete() { @@ -48,8 +48,9 @@ impl RequestHandler for AddNewNetwork<'_> { let post_body = match core::str::from_utf8(post_data) { Ok(body) => body, - Err(err) => { - log::warn!("Invalid UTF-8 in POST body: {err}"); + Err(_err) => { + warn!("Invalid UTF-8 in POST body: {:?}", post_data); + // warn!("Invalid UTF-8 in POST body: {}", err); return self .request_error( request, @@ -59,7 +60,7 @@ impl RequestHandler for AddNewNetwork<'_> { .await; } }; - log::debug!("POST body: {post_body:?}"); + debug!("POST body: {:?}", post_body); let (ssid, pass) = post_body.split_once('\n').unwrap_or((post_body, "")); diff --git a/config-site/src/handlers/change_backend_url.rs b/config-site/src/handlers/change_backend_url.rs index 498087e4..a775d88d 100644 --- a/config-site/src/handlers/change_backend_url.rs +++ b/config-site/src/handlers/change_backend_url.rs @@ -2,6 +2,7 @@ use bad_server::{ connector::Connection, handler::RequestHandler, request::Request, response::ResponseStatus, HandleError, }; +use logger::{debug, warn}; use crate::data::SharedWebContext; @@ -16,7 +17,7 @@ impl<'a> ChangeBackendUrl<'a> { status: ResponseStatus, message: &str, ) -> Result<(), HandleError> { - log::warn!("Request error: {status:?}, {message}"); + warn!("Request error: {:?}, {}", status, message); request .send_response(status) .await? @@ -31,7 +32,7 @@ impl RequestHandler for ChangeBackendUrl<'_> { async fn handle(&self, mut request: Request<'_, '_, C>) -> Result<(), HandleError> { let mut buf = [0u8; 100]; - log::debug!("Reading POST data"); + debug!("Reading POST data"); let post_data = request.read_all(&mut buf).await?; if !request.is_complete() { @@ -46,8 +47,8 @@ impl RequestHandler for ChangeBackendUrl<'_> { let post_body = match core::str::from_utf8(post_data) { Ok(body) => body, - Err(err) => { - log::warn!("Invalid UTF-8 in POST body: {err}"); + Err(_err) => { + warn!("Invalid UTF-8 in POST body: {:?}", post_data); return self .request_error( request, @@ -57,7 +58,7 @@ impl RequestHandler for ChangeBackendUrl<'_> { .await; } }; - log::debug!("POST body: {post_body:?}"); + debug!("POST body: {:?}", post_body); if !validate_url(post_body) { return self diff --git a/config-site/src/handlers/delete_network.rs b/config-site/src/handlers/delete_network.rs index bba9ab4e..a0ec9330 100644 --- a/config-site/src/handlers/delete_network.rs +++ b/config-site/src/handlers/delete_network.rs @@ -18,7 +18,7 @@ impl<'a> DeleteNetwork<'a> { status: ResponseStatus, message: &str, ) -> Result<(), HandleError> { - log::warn!("Request error: {status:?}, {message}"); + warn!("Request error: {:?}, {}", status, message); request .send_response(status) .await? @@ -33,7 +33,7 @@ impl RequestHandler for DeleteNetwork<'_> { async fn handle(&self, mut request: Request<'_, '_, C>) -> Result<(), HandleError> { let mut buf = [0u8; 100]; - log::debug!("Reading POST data"); + debug!("Reading POST data"); let post_data = request.read_all(&mut buf).await?; if !request.is_complete() { @@ -48,8 +48,9 @@ impl RequestHandler for DeleteNetwork<'_> { let post_body = match core::str::from_utf8(post_data) { Ok(body) => body, - Err(err) => { - log::warn!("Invalid UTF-8 in POST body: {err}"); + Err(_err) => { + warn!("Invalid UTF-8 in POST body: {:?}", post_data); + //warn!("Invalid UTF-8 in POST body: {}", err); return self .request_error( request, @@ -59,12 +60,13 @@ impl RequestHandler for DeleteNetwork<'_> { .await; } }; - log::debug!("POST body: {post_body:?}"); + debug!("POST body: {:?}", post_body); let index = match usize::from_str(post_body) { Ok(index) => index, - Err(err) => { - log::warn!("Invalid index in POST body: {err}"); + Err(_err) => { + warn!("Invalid index in POST body: {:?}", post_body); + //warn!("Invalid index in POST body: {}", err); return self .request_error( request, diff --git a/config-site/src/lib.rs b/config-site/src/lib.rs index 44539fb6..5c0b00a4 100644 --- a/config-site/src/lib.rs +++ b/config-site/src/lib.rs @@ -19,6 +19,9 @@ use crate::{ }, }; +#[macro_use] +extern crate logger; + pub mod data; pub mod handlers; diff --git a/device-descriptor/Cargo.toml b/device-descriptor/Cargo.toml index 0ad923f1..f85acf7c 100644 --- a/device-descriptor/Cargo.toml +++ b/device-descriptor/Cargo.toml @@ -6,3 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +defmt = { workspace = true, optional = true } + +[features] +default = [] +defmt = ["dep:defmt"] diff --git a/device-descriptor/src/lib.rs b/device-descriptor/src/lib.rs index 5bfb268c..4c24bb4f 100644 --- a/device-descriptor/src/lib.rs +++ b/device-descriptor/src/lib.rs @@ -165,7 +165,8 @@ macro_rules! define_register_type { $name:ident = $value:expr ),+ }) => { - #[derive(Debug, PartialEq, Copy, Clone)] + #[derive(PartialEq, Copy, Clone, Debug)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum $type { $( $(#[$variant_attr])* @@ -201,7 +202,8 @@ macro_rules! register { $($(#[$field_meta:meta])* $field:ident @ $range:expr => $type:ty ),* } ) => { $(#[$meta])* - #[derive(Debug, Copy, Clone)] + #[derive(Copy, Clone, Debug)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[must_use] #[allow(non_camel_case_types)] pub struct $reg { diff --git a/gui/Cargo.toml b/gui/Cargo.toml index 5fb33a15..378b1def 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -15,9 +15,17 @@ embedded-text = "0.6" embedded-layout = "0.3" tinybmp = "0.5" -signal-processing = { path = "../signal-processing" } +signal-processing = { workspace = true } +logger = { workspace = true } + +defmt = { workspace = true, optional = true } +log = { workspace = true, optional = true } itertools = { version = "0.11.0", default-features = false } [dev-dependencies] embedded-graphics-simulator = "0.5.0" + +[features] +log = ["dep:log", "logger/log"] +defmt = ["dep:defmt", "logger/defmt"] diff --git a/gui/src/lib.rs b/gui/src/lib.rs index 8e5c8af8..196d1f87 100644 --- a/gui/src/lib.rs +++ b/gui/src/lib.rs @@ -3,6 +3,9 @@ #![feature(generic_const_exprs)] // norfs needs this #![allow(incomplete_features)] // generic_const_exprs +#[macro_use] +extern crate logger; + extern crate alloc; pub mod screens; diff --git a/gui/src/screens/init.rs b/gui/src/screens/init.rs index 1e2bf564..dcc519b1 100644 --- a/gui/src/screens/init.rs +++ b/gui/src/screens/init.rs @@ -27,7 +27,7 @@ impl Drawable for StartupScreen<'_> { .draw(display)?; let logo = include_bytes!("../static/logo.bmp"); - let bmp = Bmp::from_slice(logo).unwrap(); + let bmp = unwrap!(Bmp::from_slice(logo).ok()); Image::new(&bmp, Point::new(1, 12)).draw(display)?; diff --git a/gui/src/screens/measure.rs b/gui/src/screens/measure.rs index 11e66e05..a8e64979 100644 --- a/gui/src/screens/measure.rs +++ b/gui/src/screens/measure.rs @@ -212,7 +212,7 @@ impl Drawable for EcgScreen { let (min, max) = self.limits(); - let scaler = self.camera.borrow_mut().update(min, max, display); + let scaler = unwrap!(self.camera.try_borrow_mut()).update(min, max, display); const LINE_STYLE: PrimitiveStyle = PrimitiveStyle::with_stroke(BinaryColor::On, 1); diff --git a/logger/Cargo.toml b/logger/Cargo.toml new file mode 100644 index 00000000..a06b6bb1 --- /dev/null +++ b/logger/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "logger" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +defmt = { workspace = true, optional = true } +log = { workspace = true, optional = true } + +[features] +log = ["dep:log"] +defmt = ["dep:defmt"] diff --git a/logger/src/lib.rs b/logger/src/lib.rs new file mode 100644 index 00000000..48d7987b --- /dev/null +++ b/logger/src/lib.rs @@ -0,0 +1,241 @@ +#![no_std] +#![allow(unused_macros)] + +#[cfg(all(feature = "defmt", feature = "log"))] +compile_error!("You may not enable both `defmt` and `log` features."); + +#[macro_export] +macro_rules! assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert!($($x)*); + } + }; +} + +#[macro_export] +macro_rules! assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_eq!($($x)*); + } + }; +} + +#[macro_export] +macro_rules! assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_ne!($($x)*); + } + }; +} + +#[macro_export] +macro_rules! debug_assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert!($($x)*); + } + }; +} + +#[macro_export] +macro_rules! debug_assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_eq!($($x)*); + } + }; +} + +#[macro_export] +macro_rules! debug_assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_ne!($($x)*); + } + }; +} + +#[macro_export] +macro_rules! todo { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::todo!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::todo!($($x)*); + } + }; +} + +#[macro_export] +macro_rules! unreachable { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } + }; +} + +#[macro_export] +macro_rules! panic { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::panic!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::panic!($($x)*); + } + }; +} + +#[macro_export] +macro_rules! trace { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::trace!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::trace!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[macro_export] +macro_rules! debug { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::debug!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::debug!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[macro_export] +macro_rules! info { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::info!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::info!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[macro_export] +macro_rules! warn { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::warn!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::warn!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[macro_export] +macro_rules! error { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::error!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::error!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[cfg(feature = "defmt")] +#[macro_export] +macro_rules! unwrap { + ($($x:tt)*) => { + ::defmt::unwrap!($($x)*) + }; +} + +#[cfg(not(feature = "defmt"))] +#[macro_export] +macro_rules! unwrap { + ($arg:expr) => { + match ::logger::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); + } + } + }; + ($arg:expr, $($msg:expr),+ $(,)? ) => { + match ::logger::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); + } + } + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct NoneError; + +pub trait Try { + type Ok; + type Error; + fn into_result(self) -> Result; +} + +impl Try for Option { + type Ok = T; + type Error = NoneError; + + #[inline] + fn into_result(self) -> Result { + self.ok_or(NoneError) + } +} + +impl Try for Result { + type Ok = T; + type Error = E; + + #[inline] + fn into_result(self) -> Self { + self + } +} diff --git a/max17055/Cargo.toml b/max17055/Cargo.toml index 4ae1a5bd..49caf08a 100644 --- a/max17055/Cargo.toml +++ b/max17055/Cargo.toml @@ -10,5 +10,12 @@ byte-slice-cast = { version = "1", default-features = false } device-descriptor = { path = "../device-descriptor" } embedded-hal = { workspace = true } embedded-hal-async = { workspace = true } -log = { workspace = true } register-access = { path = "../register-access" } +defmt = { workspace = true, optional = true } +log = { workspace = true, optional = true } +logger = { workspace = true } + +[features] +default = [] +defmt = ["dep:defmt", "device-descriptor/defmt", "logger/defmt"] +log = ["dep:log", "logger/log"] diff --git a/max17055/src/lib.rs b/max17055/src/lib.rs index b11ef1cc..f53aa3ae 100644 --- a/max17055/src/lib.rs +++ b/max17055/src/lib.rs @@ -2,6 +2,9 @@ #![feature(async_fn_in_trait)] #![allow(incomplete_features)] +#[macro_use] +extern crate logger; + use byte_slice_cast::AsMutByteSlice; use device_descriptor::{ReadOnlyRegister, ReaderProxy, Register}; use embedded_hal::i2c::I2c; @@ -13,12 +16,14 @@ use crate::descriptors::*; pub mod descriptors; #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { Transfer(I2cE), Verify, } #[derive(Clone, Copy, Default, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DesignData { /// Design capacity /// LSB = 5μVH/r_sense @@ -256,7 +261,7 @@ impl Max17055 { const DEVICE_ADDR: u8 = 0x36; pub fn new(i2c: I2C, config: DesignData) -> Self { - log::debug!("Design data: {config:?}"); + debug!("Design data: {:?}", config); Self { i2c, config } } @@ -332,15 +337,15 @@ where &mut self, delay: &mut impl AsyncDelayUs, ) -> Result<(), Error> { - log::trace!("Loading initial configuration"); + trace!("Loading initial configuration"); let por_status = self.read_register_async::().await?; if por_status.por().read() != Some(PowerOnReset::Reset) { - log::debug!("No power-on reset"); + debug!("No power-on reset"); return Ok(()); } - log::debug!("Power-on reset, initializing"); + debug!("Power-on reset, initializing"); self.poll_async::(delay, |reg| reg.dnr().read() == Some(DataNotReady::Ready)) .await?; @@ -404,7 +409,7 @@ where .await?; if config.v_charge > CHG_THRESHOLD { - log::debug!("Configuring 4.4V battery"); + debug!("Configuring 4.4V battery"); self.write_register_async(dPAcc::new(|w| { w.percentage().write((CHG_V_HIGH / 32) as u16) })) @@ -419,7 +424,7 @@ where })) .await?; } else { - log::debug!("Configuring 4.2V battery"); + debug!("Configuring 4.2V battery"); self.write_register_async(dPAcc::new(|w| { w.percentage().write((CHG_V_LOW / 32) as u16) })) diff --git a/signal-processing/Cargo.toml b/signal-processing/Cargo.toml index f32715af..8819b2c2 100644 --- a/signal-processing/Cargo.toml +++ b/signal-processing/Cargo.toml @@ -9,6 +9,12 @@ micromath = { version = "2.0.0", optional = true } num-complex = { version = "0.4.3", default-features = false } qrs_detector = { git = "https://github.com/bugadani/QrsDetector.git" } macros = { path = "../macros" } +logger = { workspace = true } + +defmt = { workspace = true, optional = true } +log = { workspace = true, optional = true } [features] -nostd = ["micromath"] \ No newline at end of file +nostd = ["micromath"] +log = ["dep:log", "logger/log"] +defmt = ["dep:defmt", "logger/defmt"] diff --git a/signal-processing/src/filter/median.rs b/signal-processing/src/filter/median.rs index ab12b986..c1e52644 100644 --- a/signal-processing/src/filter/median.rs +++ b/signal-processing/src/filter/median.rs @@ -43,7 +43,7 @@ impl Filter for MedianFilter { let mut iter = self.buffer.iter(); let mut copy: [f32; N] = [0.0; N]; - copy.fill_with(|| iter.next().unwrap()); + copy.fill_with(|| unwrap!(iter.next())); debug_assert!(iter.next().is_none()); Some(Self::nth(&mut copy, N / 2)) diff --git a/signal-processing/src/lib.rs b/signal-processing/src/lib.rs index b803a06c..d62f3907 100644 --- a/signal-processing/src/lib.rs +++ b/signal-processing/src/lib.rs @@ -1,5 +1,8 @@ #![cfg_attr(feature = "nostd", no_std)] +#[macro_use] +extern crate logger; + pub mod battery; pub mod buffer; pub mod compressing_buffer; diff --git a/src/board/drivers/battery_adc.rs b/src/board/drivers/battery_adc.rs index 74e81d7e..a2509c26 100644 --- a/src/board/drivers/battery_adc.rs +++ b/src/board/drivers/battery_adc.rs @@ -17,7 +17,7 @@ use embassy_futures::yield_now; use embassy_time::{Duration, Ticker}; use embedded_hal_old::adc::{Channel, OneShot}; -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, defmt::Format)] pub struct BatteryAdcData { pub voltage: u16, pub charge_current: u16, @@ -56,7 +56,7 @@ where current_in: adc_config .enable_pin_with_cal(current_in.into(), Attenuation::Attenuation11dB), enable: enable.into(), - adc: ADC::adc(adc, adc_config).unwrap(), + adc: unwrap!(ADC::adc(adc, adc_config)), } } @@ -99,9 +99,9 @@ pub async fn monitor_task_adc( task_control .run_cancellable(async { let mut timer = Ticker::every(Duration::from_millis(10)); - log::info!("ADC monitor started"); + info!("ADC monitor started"); - battery.lock().await.enable.set_high().unwrap(); + unwrap!(battery.lock().await.enable.set_high().ok()); let mut voltage_accumulator = 0; let mut current_accumulator = 0; @@ -111,7 +111,7 @@ pub async fn monitor_task_adc( const AVG_SAMPLE_COUNT: u32 = 128; loop { - let data = battery.lock().await.read_data().await.unwrap(); + let data = unwrap!(battery.lock().await.read_data().await); voltage_accumulator += data.voltage as u32; current_accumulator += data.charge_current as u32; @@ -125,7 +125,7 @@ pub async fn monitor_task_adc( }; state.data = Some(average); - log::debug!("Battery data: {average:?}"); + debug!("Battery data: {:?}", average); sample_count = 0; @@ -140,7 +140,7 @@ pub async fn monitor_task_adc( }) .await; - battery.lock().await.enable.set_low().unwrap(); + unwrap!(battery.lock().await.enable.set_low().ok()); - log::info!("Monitor exited"); + info!("Monitor exited"); } diff --git a/src/board/drivers/battery_fg.rs b/src/board/drivers/battery_fg.rs index 59fe1ff1..3c454f73 100644 --- a/src/board/drivers/battery_fg.rs +++ b/src/board/drivers/battery_fg.rs @@ -8,6 +8,7 @@ use crate::{ }; #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct BatteryFgData { pub voltage: u16, pub percentage: u8, @@ -28,14 +29,14 @@ where } pub async fn enable(&mut self, delay: &mut D) { - self.enable.set_high().unwrap(); + unwrap!(self.enable.set_high().ok()); delay.delay_ms(10).await; - self.fg.load_initial_config_async(delay).await.unwrap(); + unwrap!(self.fg.load_initial_config_async(delay).await.ok()); } pub async fn read_data(&mut self) -> Result { - let voltage_uv = self.fg.read_vcell().await.unwrap(); - let percentage = self.fg.read_reported_soc().await.unwrap(); + let voltage_uv = unwrap!(self.fg.read_vcell().await.ok()); + let percentage = unwrap!(self.fg.read_reported_soc().await.ok()); Ok(BatteryFgData { voltage: (voltage_uv / 1000) as u16, // mV @@ -44,7 +45,7 @@ where } pub fn disable(&mut self) { - self.enable.set_low().unwrap(); + unwrap!(self.enable.set_low().ok()); } } @@ -57,18 +58,18 @@ pub async fn monitor_task_fg( task_control .run_cancellable(async { let mut timer = Ticker::every(Duration::from_secs(1)); - log::info!("Fuel gauge monitor started"); + info!("Fuel gauge monitor started"); fuel_gauge.lock().await.enable(&mut Delay).await; loop { - let data = fuel_gauge.lock().await.read_data().await.unwrap(); + let data = unwrap!(fuel_gauge.lock().await.read_data().await); { let mut state = battery_state.lock().await; state.data = Some(data); } - log::debug!("Battery data: {data:?}"); + debug!("Battery data: {:?}", data); timer.next().await; } @@ -76,5 +77,5 @@ pub async fn monitor_task_fg( .await; fuel_gauge.lock().await.disable(); - log::info!("Monitor exited"); + info!("Monitor exited"); } diff --git a/src/board/drivers/battery_monitor.rs b/src/board/drivers/battery_monitor.rs index b07a32ca..2345aaee 100644 --- a/src/board/drivers/battery_monitor.rs +++ b/src/board/drivers/battery_monitor.rs @@ -76,11 +76,11 @@ impl BatteryMonitor { } pub fn is_plugged(&self) -> bool { - self.vbus_detect.is_high().unwrap() + unwrap!(self.vbus_detect.is_high().ok()) } pub fn is_charging(&self) -> bool { - self.charger_status.is_low().unwrap() + unwrap!(self.charger_status.is_low().ok()) } #[allow(unused)] diff --git a/src/board/drivers/display.rs b/src/board/drivers/display.rs index 7053627e..291dfa88 100644 --- a/src/board/drivers/display.rs +++ b/src/board/drivers/display.rs @@ -42,10 +42,11 @@ where } pub async fn enable(mut self) -> Result, DisplayError> { - self.display + unwrap!(self + .display .reset_async::<_, Delay>(&mut self.reset, &mut Delay) .await - .unwrap(); + .ok()); self.display .init_with_addr_mode_async(AddrMode::Horizontal) @@ -84,7 +85,7 @@ impl DrawTarget for PoweredDisplay { } impl PoweredDisplay { - pub async fn frame( + async fn frame_impl( &mut self, render: impl FnOnce(&mut Self) -> Result<(), DisplayError>, ) -> Result<(), DisplayError> { @@ -95,6 +96,10 @@ impl PoweredDisplay { self.flush().await } + pub async fn frame(&mut self, render: impl FnOnce(&mut Self) -> Result<(), DisplayError>) { + unwrap!(self.frame_impl(render).await.ok()); + } + pub async fn flush(&mut self) -> Result<(), DisplayError> { self.display.display.flush_async().await } @@ -112,7 +117,7 @@ where RESET: OutputPin, { pub fn shut_down(mut self) -> Display { - self.display.reset.set_low().unwrap(); + unwrap!(self.display.reset.set_low().ok()); self.display } } diff --git a/src/board/drivers/frontend.rs b/src/board/drivers/frontend.rs index aab324b5..2d068e11 100644 --- a/src/board/drivers/frontend.rs +++ b/src/board/drivers/frontend.rs @@ -133,14 +133,14 @@ where } pub fn is_touched(&self) -> bool { - self.touch.is_low().unwrap() + unwrap!(self.touch.is_low().ok()) } pub async fn wait_for_release(&mut self) where TOUCH: Wait, { - self.touch.wait_for_high().await.unwrap(); + unwrap!(self.touch.wait_for_high().await.ok()); } pub fn split(self) -> (S, DRDY, RESET, TOUCH) { @@ -178,7 +178,7 @@ where S: AsyncSpiDevice, { async fn enable(&mut self) -> Result<(), Error> { - self.frontend.clken.set_high().unwrap(); + unwrap!(self.frontend.clken.set_high().ok()); Timer::after(Duration::from_millis(1)).await; @@ -191,7 +191,7 @@ where self.frontend.device_id = Some(device_id); - log::info!("ADC device id: {:?}", device_id); + info!("ADC device id: {:?}", device_id); let config = self.frontend.config(); self.frontend.adc.apply_configuration_async(&config).await?; @@ -214,7 +214,7 @@ where pub async fn read_clksel(&mut self) -> Result> { let register = self.frontend.adc.read_register_async::().await?; - Ok(register.d2().read().unwrap()) + Ok(unwrap!(register.d2().read())) } pub async fn enable_fast_clock(&mut self) -> Result<(), Error> { @@ -230,7 +230,7 @@ where where DRDY: Wait, { - self.frontend.drdy.wait_for_falling_edge().await.unwrap(); + unwrap!(self.frontend.drdy.wait_for_falling_edge().await.ok()); let sample = self.frontend.adc.read_data_1ch_async().await?; self.touched = sample.ch1_negative_lead_connected(); @@ -255,13 +255,13 @@ where .write_command_async(Command::RESET, &mut []) .await; - self.frontend.reset.set_low().unwrap(); + unwrap!(self.frontend.reset.set_low().ok()); // Datasheet says to wait 2^10 clock cycles to enter power down mode. We give it a bit of // extra time. Timer::after(Duration::from_millis(5)).await; - self.frontend.clken.set_low().unwrap(); + unwrap!(self.frontend.clken.set_low().ok()); self.frontend } diff --git a/src/board/hardware/v2.rs b/src/board/hardware/v2.rs index 9f2643e5..a5c1f880 100644 --- a/src/board/hardware/v2.rs +++ b/src/board/hardware/v2.rs @@ -154,11 +154,10 @@ impl super::startup::StartupResources { &clocks, ); - interrupt::enable( + unwrap!(interrupt::enable( peripherals::Interrupt::I2C_EXT0, interrupt::Priority::Priority1, - ) - .unwrap(); + )); // MCP73832T-2ACI/OT // - ITerm/Ireg = 7.5% diff --git a/src/board/initialized.rs b/src/board/initialized.rs index 0dd1c7dd..781029f6 100644 --- a/src/board/initialized.rs +++ b/src/board/initialized.rs @@ -48,7 +48,7 @@ impl Board { return; } - log::info!("Saving config"); + info!("Saving config"); self.config_changed = false; if let Some(storage) = self.storage.as_mut() { @@ -56,10 +56,10 @@ impl Board { .store_writer("config", self.config, OnCollision::Overwrite) .await { - log::error!("Failed to save config: {e:?}"); + error!("Failed to save config: {:?}", e); } } else { - log::warn!("Storage unavailable"); + warn!("Storage unavailable"); } } diff --git a/src/board/startup.rs b/src/board/startup.rs index 4de3ea8d..3f964972 100644 --- a/src/board/startup.rs +++ b/src/board/startup.rs @@ -29,6 +29,7 @@ use crate::{ }, heap::init_heap, }; +#[cfg(feature = "log")] use esp_println::logger::init_logger; pub static WIFI_DRIVER: StaticCell = StaticCell::new(); @@ -51,6 +52,7 @@ pub struct StartupResources { impl StartupResources { pub(super) fn common_init() { + #[cfg(feature = "log")] init_logger(log::LevelFilter::Trace); // we let the compile-time log level filter do the work init_heap(); } @@ -70,8 +72,14 @@ impl StartupResources { pcc: &mut PeripheralClockControl, clocks: &Clocks, ) -> Display { - interrupt::enable(dma_in_interrupt, interrupt::Priority::Priority1).unwrap(); - interrupt::enable(dma_out_interrupt, interrupt::Priority::Priority1).unwrap(); + unwrap!(interrupt::enable( + dma_in_interrupt, + interrupt::Priority::Priority1 + )); + unwrap!(interrupt::enable( + dma_out_interrupt, + interrupt::Priority::Priority1 + )); let mut display_cs: DisplayChipSelect = display_cs.into(); @@ -123,12 +131,18 @@ impl StartupResources { pcc: &mut PeripheralClockControl, clocks: &Clocks, ) -> EcgFrontend { - interrupt::enable(dma_in_interrupt, interrupt::Priority::Priority1).unwrap(); - interrupt::enable(dma_out_interrupt, interrupt::Priority::Priority1).unwrap(); + unwrap!(interrupt::enable( + dma_in_interrupt, + interrupt::Priority::Priority1 + )); + unwrap!(interrupt::enable( + dma_out_interrupt, + interrupt::Priority::Priority1 + )); let mut adc_cs: AdcChipSelect = adc_cs.into(); - adc_cs.set_high().unwrap(); + unwrap!(adc_cs.set_high().ok()); static mut ADC_SPI_DESCRIPTORS: [u32; 3] = [0; 3]; static mut ADC_SPI_RX_DESCRIPTORS: [u32; 3] = [0; 3]; diff --git a/src/board/wifi/ap.rs b/src/board/wifi/ap.rs index 93c4bff2..c1f7b09d 100644 --- a/src/board/wifi/ap.rs +++ b/src/board/wifi/ap.rs @@ -81,10 +81,10 @@ impl ApState { resources: &'static mut StackResources<3>, mut rng: Rng, ) -> Self { - log::info!("Configuring AP"); + info!("Configuring AP"); let (wifi_interface, controller) = - esp_wifi::wifi::new_with_mode(&init, wifi, WifiMode::Ap).unwrap(); + unwrap!(esp_wifi::wifi::new_with_mode(&init, wifi, WifiMode::Ap)); let lower = rng.random() as u64; let upper = rng.random() as u64; @@ -108,16 +108,16 @@ impl ApState { pub(super) async fn start(&mut self) -> Ap { if !self.started { - log::info!("Starting AP"); + info!("Starting AP"); let spawner = Spawner::for_current_executor().await; - log::info!("Starting AP task"); + info!("Starting AP task"); spawner.must_spawn(ap_task( self.controller.clone(), self.connection_task_control.token(), self.client_count.clone(), )); - log::info!("Starting NET task"); + info!("Starting NET task"); spawner.must_spawn(net_task(self.stack.clone(), self.net_task_control.token())); self.started = true; @@ -131,7 +131,7 @@ impl ApState { pub(super) async fn stop(&mut self) { if self.started { - log::info!("Stopping AP"); + info!("Stopping AP"); let _ = join( self.connection_task_control.stop_from_outside(), self.net_task_control.stop_from_outside(), @@ -139,10 +139,10 @@ impl ApState { .await; if matches!(self.controller.lock().await.is_started(), Ok(true)) { - self.controller.lock().await.stop().await.unwrap(); + unwrap!(self.controller.lock().await.stop().await); } - log::info!("Stopped AP"); + info!("Stopped AP"); self.started = false; } } @@ -160,26 +160,18 @@ pub(super) async fn ap_task( ) { task_control .run_cancellable(async { - log::info!("Start connection task"); - log::debug!( - "Device capabilities: {:?}", - controller.lock().await.get_capabilities() - ); + info!("Start connection task"); let client_config = Configuration::AccessPoint(AccessPointConfiguration { ssid: "Card/IO".into(), max_connections: 1, ..Default::default() }); - controller - .lock() - .await - .set_configuration(&client_config) - .unwrap(); - log::info!("Starting wifi"); + unwrap!(controller.lock().await.set_configuration(&client_config)); + info!("Starting wifi"); - controller.lock().await.start().await.unwrap(); - log::info!("Wifi started!"); + unwrap!(controller.lock().await.start().await); + info!("Wifi started!"); loop { if let WifiStackState::ApStart @@ -199,18 +191,18 @@ pub(super) async fn ap_task( if events.contains(WifiEvent::ApStaconnected) { let old_count = client_count.fetch_add(1, Ordering::Release); - log::info!("Client connected, {} total", old_count + 1); + info!("Client connected, {} total", old_count + 1); } if events.contains(WifiEvent::ApStadisconnected) { let old_count = client_count.fetch_sub(1, Ordering::Release); - log::info!("Client disconnected, {} left", old_count - 1); + info!("Client disconnected, {} left", old_count - 1); } if events.contains(WifiEvent::ApStop) { - log::info!("AP stopped"); + info!("AP stopped"); return; } - log::info!("Event processing done"); + info!("Event processing done"); } } }) diff --git a/src/board/wifi/mod.rs b/src/board/wifi/mod.rs index 48058b34..1dd6735e 100644 --- a/src/board/wifi/mod.rs +++ b/src/board/wifi/mod.rs @@ -55,21 +55,18 @@ enum WifiDriverState { impl WifiDriverState { fn initialize(&mut self, clocks: &Clocks<'_>) { if let WifiDriverState::Uninitialized(_) = self { - log::info!("Initializing Wifi driver"); + info!("Initializing Wifi driver"); // The replacement value doesn't matter as we immediately overwrite it, // but we need to move out of the resources if let WifiDriverState::Uninitialized(resources) = self.replace_with(WifiMode::Ap) { - *self = WifiDriverState::Initialized( - esp_wifi::initialize( - EspWifiInitFor::Wifi, - resources.timer, - resources.rng, - resources.rcc, - clocks, - ) - .unwrap(), - ); - log::info!("Wifi driver initialized"); + *self = WifiDriverState::Initialized(unwrap!(esp_wifi::initialize( + EspWifiInitFor::Wifi, + resources.timer, + resources.rng, + resources.rcc, + clocks, + ))); + info!("Wifi driver initialized"); } else { unsafe { unreachable_unchecked() } } diff --git a/src/board/wifi/sta.rs b/src/board/wifi/sta.rs index 58ea7e54..2cda5eb7 100644 --- a/src/board/wifi/sta.rs +++ b/src/board/wifi/sta.rs @@ -109,10 +109,10 @@ impl StaState { resources: &'static mut StackResources<3>, mut rng: Rng, ) -> Self { - log::info!("Configuring STA"); + info!("Configuring STA"); let (wifi_interface, controller) = - esp_wifi::wifi::new_with_mode(&init, wifi, WifiMode::Sta).unwrap(); + unwrap!(esp_wifi::wifi::new_with_mode(&init, wifi, WifiMode::Sta)); let lower = rng.random() as u64; let upper = rng.random() as u64; @@ -138,7 +138,7 @@ impl StaState { pub(super) async fn stop(&mut self) { if self.started { - log::info!("Stopping STA"); + info!("Stopping STA"); let _ = join( self.connection_task_control.stop_from_outside(), self.net_task_control.stop_from_outside(), @@ -146,20 +146,20 @@ impl StaState { .await; if matches!(self.controller.lock().await.is_started(), Ok(true)) { - self.controller.lock().await.stop().await.unwrap(); + unwrap!(self.controller.lock().await.stop().await); } - log::info!("Stopped STA"); + info!("Stopped STA"); self.started = false; } } pub(super) async fn start(&mut self) -> Sta { if !self.started { - log::info!("Starting STA"); + info!("Starting STA"); let spawner = Spawner::for_current_executor().await; - log::info!("Starting STA task"); + info!("Starting STA task"); spawner.must_spawn(sta_task( self.controller.clone(), self.networks.clone(), @@ -168,7 +168,7 @@ impl StaState { self.stack.clone(), self.connection_task_control.token(), )); - log::info!("Starting NET task"); + info!("Starting NET task"); spawner.must_spawn(net_task(self.stack.clone(), self.net_task_control.token())); self.started = true; @@ -201,20 +201,20 @@ pub(super) async fn sta_task( 'scan_and_connect: loop { state.store(ConnectionState::NotConnected, Ordering::Release); if !matches!(controller.lock().await.is_started(), Ok(true)) { - log::info!("Starting wifi"); - controller.lock().await.start().await.unwrap(); - log::info!("Wifi started!"); + info!("Starting wifi"); + unwrap!(controller.lock().await.start().await); + info!("Wifi started!"); } let connect_to = 'select: loop { - log::info!("Scanning..."); + info!("Scanning..."); let mut scan_results = Box::new(controller.lock().await.scan_n::().await); match scan_results.as_mut() { Ok((ref mut visible_networks, network_count)) => { - log::info!("Found {network_count} access points"); + info!("Found {} access points", network_count); // Sort by signal strength, descending visible_networks @@ -247,34 +247,33 @@ pub(super) async fn sta_task( *preference = NetworkPreference::Preferred; } } - Err(err) => log::warn!("Scan failed: {err:?}"), + Err(err) => warn!("Scan failed: {:?}", err), } Timer::after(SCAN_PERIOD).await; }; - log::info!("Connecting to {}...", connect_to.ssid); + info!("Connecting to {}...", connect_to.ssid); state.store(ConnectionState::Connecting, Ordering::Release); - controller + unwrap!(controller .lock() .await .set_configuration(&Configuration::Client(ClientConfiguration { ssid: connect_to.ssid.clone(), password: connect_to.pass, ..Default::default() - })) - .unwrap(); + }))); for _ in 0..CONNECT_RETRY_COUNT { match controller.lock().await.connect().await { Ok(_) => { - log::info!("Waiting to get IP address..."); + info!("Waiting to get IP address..."); let wait_for_ip = async { loop { if let Some(config) = stack.config_v4() { - log::info!("Got IP: {}", config.address); + info!("Got IP: {}", config.address); break; } Timer::after(Duration::from_millis(500)).await; @@ -289,7 +288,7 @@ pub(super) async fn sta_task( match select(wait_for_ip, wait_for_disconnect).await { Either::First(_) => { - log::info!("Wifi connected!"); + info!("Wifi connected!"); state.store(ConnectionState::Connected, Ordering::Release); // keep pending Disconnected event to avoid a race condition @@ -301,18 +300,18 @@ pub(super) async fn sta_task( // TODO: figure out if we should deprioritize, retry or just loop back // to the beginning. Maybe we could use a timer? - log::info!("Wifi disconnected!"); + info!("Wifi disconnected!"); state.store(ConnectionState::NotConnected, Ordering::Release); continue 'scan_and_connect; } Either::Second(_) => { - log::info!("Wifi disconnected!"); + info!("Wifi disconnected!"); state.store(ConnectionState::NotConnected, Ordering::Release); } } } Err(e) => { - log::warn!("Failed to connect to wifi: {e:?}"); + warn!("Failed to connect to wifi: {:?}", e); state.store(ConnectionState::NotConnected, Ordering::Release); Timer::after(CONNECT_RETRY_PERIOD).await; } diff --git a/src/heap.rs b/src/heap.rs index 1591ce0c..a419c63c 100644 --- a/src/heap.rs +++ b/src/heap.rs @@ -11,7 +11,7 @@ pub fn init_heap() { unsafe { let heap_size = HEAP.len(); - log::info!("Heap size: {heap_size}"); + info!("Heap size: {}", heap_size); ALLOCATOR.init(addr_of_mut!(HEAP).cast(), heap_size); } } diff --git a/src/main.rs b/src/main.rs index 60af23da..11b03822 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,8 +9,13 @@ extern crate alloc; +#[macro_use] +extern crate logger; + use core::ptr::addr_of; +use esp_println as _; + use alloc::{boxed::Box, rc::Rc}; use embassy_executor::Spawner; use embassy_sync::{ @@ -73,11 +78,13 @@ pub type Shared = Rc>; pub type SharedGuard<'a, T> = MutexGuard<'a, NoopRawMutex, T>; #[derive(Clone, Copy, Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AppError { Adc, } #[derive(Clone, Copy, Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AppState { AdcSetup, Initialize, @@ -111,10 +118,10 @@ fn main() -> ! { let _stack_protection = stack_protection::StackMonitor::protect((stack_start + 4)..stack_end); #[cfg(feature = "hw_v1")] - log::info!("Hardware version: v1"); + info!("Hardware version: v1"); #[cfg(feature = "hw_v2")] - log::info!("Hardware version: v2"); + info!("Hardware version: v2"); let executor = make_static!(Executor::new()); executor.run(move |spawner| { @@ -130,7 +137,7 @@ async fn setup_storage( let storage = match Storage::mount(unsafe { &mut READ_CACHE }).await { Ok(storage) => Ok(storage), Err(StorageError::NotFormatted) => { - log::info!("Formatting storage"); + info!("Formatting storage"); Storage::format_and_mount(unsafe { &mut READ_CACHE }).await } e => e, @@ -139,7 +146,7 @@ async fn setup_storage( match storage { Ok(storage) => Some(make_static!(storage)), Err(e) => { - log::error!("Failed to mount storage: {:?}", e); + error!("Failed to mount storage: {:?}", e); None } } @@ -152,7 +159,7 @@ where static CONFIG: StaticCell = StaticCell::new(); if let Some(storage) = storage { - log::info!( + info!( "Storage: {} / {} used", storage.capacity() - storage.free_bytes(), storage.capacity() @@ -162,17 +169,17 @@ where Ok(mut config) => match config.read_loadable::(storage).await { Ok(config) => CONFIG.init(config.into_config()), Err(e) => { - log::warn!("Failed to read config file: {e:?}. Reverting to defaults"); + warn!("Failed to read config file: {:?}. Reverting to defaults", e); CONFIG.init(Config::default()) } }, Err(e) => { - log::warn!("Failed to load config: {e:?}. Reverting to defaults"); + warn!("Failed to load config: {:?}. Reverting to defaults", e); CONFIG.init(Config::default()) } } } else { - log::warn!("Storage unavailable. Using default config"); + warn!("Storage unavailable. Using default config"); CONFIG.init(Config::default()) } } @@ -189,15 +196,14 @@ async fn main_task(_spawner: Spawner, resources: StartupResources) { ) .await; - hal::interrupt::enable( + unwrap!(hal::interrupt::enable( hal::peripherals::Interrupt::GPIO, hal::interrupt::Priority::Priority3, - ) - .unwrap(); + )); let mut storage = setup_storage().await; let config = load_config(storage.as_deref_mut()).await; - let mut display = resources.display.enable().await.unwrap(); + let mut display = unwrap!(resources.display.enable().await.ok()); let _ = display .update_brightness_async(config.display_brightness()) @@ -223,7 +229,7 @@ async fn main_task(_spawner: Spawner, resources: StartupResources) { let mut state = AppState::AdcSetup; loop { - log::info!("New app state: {state:?}"); + info!("New app state: {:?}", state); state = match state { AppState::AdcSetup => adc_setup(&mut board).await, AppState::Initialize => initialize(&mut board).await, @@ -274,7 +280,7 @@ fn setup_wakeup_pins<'a, const N: usize>( charger_pin: &'a mut ChargerStatus, is_charging: bool, ) { - wakeup_pins.push((touch, WakeupLevel::Low)).ok().unwrap(); + unwrap!(wakeup_pins.push((touch, WakeupLevel::Low)).ok()); if is_charging { // This is a bit awkward as unplugging then replugging will not wake the @@ -289,10 +295,7 @@ fn setup_wakeup_pins<'a, const N: usize>( charger_pin.rtcio_pad_hold(true); charger_pin.rtcio_pullup(true); - wakeup_pins - .push((charger_pin, WakeupLevel::Low)) - .ok() - .unwrap(); + unwrap!(wakeup_pins.push((charger_pin, WakeupLevel::Low)).ok()); } } @@ -314,6 +317,6 @@ fn setup_wakeup_pins<'a, const N: usize>( WakeupLevel::High }; - wakeup_pins.push((touch, WakeupLevel::Low)).ok().unwrap(); - wakeup_pins.push((charger_pin, charger_level)).ok().unwrap(); + unwrap!(wakeup_pins.push((touch, WakeupLevel::Low)).ok()); + unwrap!(wakeup_pins.push((charger_pin, charger_level)).ok()); } diff --git a/src/stack_protection.rs b/src/stack_protection.rs index 2557b921..f8096090 100644 --- a/src/stack_protection.rs +++ b/src/stack_protection.rs @@ -28,9 +28,9 @@ impl StackMonitor { /// accessing the canary prior to that. However, this is a good enough approximation for our /// purposes. pub fn protect(stack: Range) -> Self { - log::info!( - "StackMonitor::protect({:#x}, {})", - stack.start, + info!( + "StackMonitor::protect({:?}, {})", + stack.start as *const u32, stack.end - stack.start ); let mut assist = conjure(); @@ -53,11 +53,10 @@ impl StackMonitor { ), } - interrupt::enable( + unwrap!(interrupt::enable( peripherals::Interrupt::ASSIST_DEBUG, interrupt::Priority::Priority3, - ) - .unwrap(); + )); Self { assist } } @@ -94,6 +93,6 @@ fn ASSIST_DEBUG() { } if is_overflow { - panic!("Core {cpu:?} stack overflow detected - PC = {pc:#X}"); + panic!("Core {:?} stack overflow detected - PC = {:#X}", cpu, pc); } } diff --git a/src/states/charging.rs b/src/states/charging.rs index 50411809..40c08204 100644 --- a/src/states/charging.rs +++ b/src/states/charging.rs @@ -38,8 +38,7 @@ pub async fn charging(board: &mut Board) -> AppState { board .display .frame(|display| charging_screen.draw(display)) - .await - .unwrap(); + .await; ticker.next().await; } diff --git a/src/states/error.rs b/src/states/error.rs index b78011e7..4cd60022 100644 --- a/src/states/error.rs +++ b/src/states/error.rs @@ -37,8 +37,7 @@ pub async fn app_error(board: &mut Board, error: AppError) -> AppState { } .draw(display) }) - .await - .unwrap(); + .await; ticker.next().await; } diff --git a/src/states/init.rs b/src/states/init.rs index 82907e2e..37c367e3 100644 --- a/src/states/init.rs +++ b/src/states/init.rs @@ -47,8 +47,7 @@ pub async fn initialize(board: &mut Board) -> AppState { board .display .frame(|display| init_screen.draw(display)) - .await - .unwrap(); + .await; ticker.next().await; } diff --git a/src/states/measure.rs b/src/states/measure.rs index 0ad12f7d..f80ec5a6 100644 --- a/src/states/measure.rs +++ b/src/states/measure.rs @@ -136,7 +136,7 @@ async fn measure_impl( let ret = match frontend.read_clksel().await { Ok(PinState::Low) => { - log::info!("CLKSEL low, enabling faster clock speeds"); + info!("CLKSEL low, enabling faster clock speeds"); let result = frontend.enable_fast_clock().await; if result.is_ok() { @@ -221,8 +221,9 @@ async fn measure_impl( } if debug_print_timer.is_elapsed() { - log::debug!( - "Collected {samples} samples in {}ms", + debug!( + "Collected {} samples in {}ms", + samples, debug_print_timer.elapsed().as_millis() ); samples = 0; @@ -253,16 +254,11 @@ async fn measure_impl( board .display .frame(|display| init_screen.draw(display)) - .await - .unwrap(); + .await; } else { screen.status_bar.update_battery_data(battery_data); - board - .display - .frame(|display| screen.draw(display)) - .await - .unwrap(); + board.display.frame(|display| screen.draw(display)).await; } ticker.next().await; @@ -292,7 +288,7 @@ async fn read_ecg( match frontend.read().await { Ok(sample) => { if !frontend.is_touched() { - log::info!("Not touched, stopping"); + info!("Not touched, stopping"); return Ok(()); } @@ -300,7 +296,7 @@ async fn read_ecg( .try_send(Message::Sample(sample.ch1_sample())) .is_err() { - log::warn!("Sample lost"); + warn!("Sample lost"); } } Err(e) => { @@ -315,6 +311,6 @@ async fn read_ecg( } } - log::info!("Stop requested, stopping"); + info!("Stop requested, stopping"); Ok(()) } diff --git a/src/states/menu/about.rs b/src/states/menu/about.rs index 2b17f46b..52b4dfd2 100644 --- a/src/states/menu/about.rs +++ b/src/states/menu/about.rs @@ -65,13 +65,12 @@ pub async fn about_menu(board: &mut Board) -> AppState { #[cfg(feature = "battery_max17055")] { - items + unwrap!(items .push(NavigationItem::new( String::from("Fuel gauge: MAX17055"), AboutMenuEvents::ToBatteryInfo, )) - .ok() - .unwrap(); + .ok()); } let mut menu_screen = Screen { @@ -125,8 +124,7 @@ pub async fn about_menu(board: &mut Board) -> AppState { menu_screen.content.update(display); menu_screen.draw(display) }) - .await - .unwrap(); + .await; ticker.next().await; } diff --git a/src/states/menu/battery_info.rs b/src/states/menu/battery_info.rs index 33053b43..a9422ac7 100644 --- a/src/states/menu/battery_info.rs +++ b/src/states/menu/battery_info.rs @@ -55,35 +55,30 @@ pub async fn battery_info_menu(board: &mut Board) -> AppState { let mut sensor = board.battery_monitor.sensor().await; - let voltage = sensor.fg.read_vcell().await.unwrap(); - items + let voltage = unwrap!(sensor.fg.read_vcell().await.ok()); + unwrap!(items .push(list_item(format!("Voltage: {:>9}mV", voltage / 1000))) - .ok() - .unwrap(); + .ok()); - let current = sensor.fg.read_current().await.unwrap(); - items + let current = unwrap!(sensor.fg.read_current().await.ok()); + unwrap!(items .push(list_item(format!("Current: {:>9}mA", current / 1000))) - .ok() - .unwrap(); + .ok()); - let capacity = sensor.fg.read_design_capacity().await.unwrap(); - items + let capacity = unwrap!(sensor.fg.read_design_capacity().await.ok()); + unwrap!(items .push(list_item(format!("Nominal: {:>8}mAh", capacity / 1000))) - .ok() - .unwrap(); + .ok()); - let capacity = sensor.fg.read_reported_capacity().await.unwrap(); - items + let capacity = unwrap!(sensor.fg.read_reported_capacity().await.ok()); + unwrap!(items .push(list_item(format!("Capacity: {:>7}mAh", capacity / 1000))) - .ok() - .unwrap(); + .ok()); - let charge_cycles = sensor.fg.read_charge_cycles().await.unwrap(); - items + let charge_cycles = unwrap!(sensor.fg.read_charge_cycles().await.ok()); + unwrap!(items .push(list_item(format!("Chg Cycles: {:>8}", charge_cycles))) - .ok() - .unwrap(); + .ok()); } let mut menu_screen = Screen { @@ -127,8 +122,7 @@ pub async fn battery_info_menu(board: &mut Board) -> AppState { menu_screen.content.update(display); menu_screen.draw(display) }) - .await - .unwrap(); + .await; menu_state = menu_screen.content.state(); diff --git a/src/states/menu/display.rs b/src/states/menu/display.rs index 0a267dd7..16050a34 100644 --- a/src/states/menu/display.rs +++ b/src/states/menu/display.rs @@ -79,7 +79,7 @@ pub async fn display_menu(board: &mut Board) -> AppState { } if &menu_values != menu_screen.content.data() { - log::debug!("Settings changed"); + debug!("Settings changed"); let new = *menu_screen.content.data(); if menu_values.brightness != new.brightness { board.config_changed = true; @@ -110,13 +110,12 @@ pub async fn display_menu(board: &mut Board) -> AppState { menu_screen.content.update(display); menu_screen.draw(display) }) - .await - .unwrap(); + .await; ticker.next().await; } - log::info!("Menu timeout"); + info!("Menu timeout"); board.save_config().await; AppState::Shutdown } diff --git a/src/states/menu/main.rs b/src/states/menu/main.rs index 72695f06..cf819275 100644 --- a/src/states/menu/main.rs +++ b/src/states/menu/main.rs @@ -36,36 +36,32 @@ pub async fn main_menu(board: &mut Board) -> AppState { }; let mut exit_timer = Timeout::new(MENU_IDLE_DURATION); - log::info!("Free heap: {} bytes", ALLOCATOR.free()); + info!("Free heap: {} bytes", ALLOCATOR.free()); let builder = Menu::with_style("Main menu", menu_style()); let mut items = heapless::Vec::<_, 4>::new(); - items + unwrap!(items .push(NavigationItem::new( "Display settings", MainMenuEvents::Display, )) - .ok() - .unwrap(); - items + .ok()); + unwrap!(items .push(NavigationItem::new("Device info", MainMenuEvents::About)) - .ok() - .unwrap(); + .ok()); if board.can_enable_wifi() { - items + unwrap!(items .push(NavigationItem::new("Wifi setup", MainMenuEvents::WifiSetup)) - .ok() - .unwrap(); - items + .ok()); + unwrap!(items .push(NavigationItem::new( "Wifi networks", MainMenuEvents::WifiListVisible, )) - .ok() - .unwrap(); + .ok()); } let mut menu_screen = Screen { @@ -122,12 +118,11 @@ pub async fn main_menu(board: &mut Board) -> AppState { menu_screen.content.update(display); menu_screen.draw(display) }) - .await - .unwrap(); + .await; ticker.next().await; } - log::info!("Menu timeout"); + info!("Menu timeout"); AppState::Shutdown } diff --git a/src/states/menu/mod.rs b/src/states/menu/mod.rs index 74eeaeea..837ccc4a 100644 --- a/src/states/menu/mod.rs +++ b/src/states/menu/mod.rs @@ -7,6 +7,7 @@ pub mod wifi_ap; pub mod wifi_sta; #[derive(Clone, Copy, Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AppMenu { Main, Display, diff --git a/src/states/menu/wifi_ap.rs b/src/states/menu/wifi_ap.rs index af146c0e..9e9b5e23 100644 --- a/src/states/menu/wifi_ap.rs +++ b/src/states/menu/wifi_ap.rs @@ -98,11 +98,7 @@ pub async fn wifi_ap(board: &mut Board) -> AppState { break; } - board - .display - .frame(|display| screen.draw(display)) - .await - .unwrap(); + board.display.frame(|display| screen.draw(display)).await; ticker.next().await; } @@ -146,7 +142,7 @@ async fn webserver_task( context: Rc, mut task_control: TaskControlToken<()>, ) { - log::info!("Started webserver task"); + info!("Started webserver task"); task_control .run_cancellable(async { let mut resources = Box::new(WebserverResources { @@ -173,5 +169,5 @@ async fn webserver_task( .await; }) .await; - log::info!("Stopped webserver task"); + info!("Stopped webserver task"); } diff --git a/src/states/menu/wifi_sta.rs b/src/states/menu/wifi_sta.rs index 0f8d0048..68d576ee 100644 --- a/src/states/menu/wifi_sta.rs +++ b/src/states/menu/wifi_sta.rs @@ -91,8 +91,7 @@ pub async fn wifi_sta(board: &mut Board) -> AppState { menu_screen.content.update(display); menu_screen.draw(display) }) - .await - .unwrap(); + .await; menu_state = menu_screen.content.state(); diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 86fa48e4..25dba147 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,3 +1,5 @@ +use std::env; + use anyhow::Result as AnyResult; use clap::{Parser, Subcommand, ValueEnum}; @@ -156,7 +158,13 @@ fn run(hw: HardwareVersion) -> AnyResult<()> { } fn monitor() -> AnyResult<()> { - cargo(&["espflash", "monitor"]).run()?; + cargo(&[ + "espflash", + "monitor", + "-e", + "./target/xtensa-esp32s3-none-elf/release/card_io_fw", + ]) + .run()?; Ok(()) } @@ -224,7 +232,7 @@ fn example(package: String, name: String, watch: bool) -> AnyResult<()> { // Add required features, etc. match (package.as_str(), name.as_str()) { - ("config-site", "simple") => args.extend_from_slice(&["--features=std"]), + ("config-site", "simple") => args.extend_from_slice(&["--features=std,log"]), _ => {} } @@ -257,6 +265,8 @@ fn asm() -> AnyResult<()> { fn main() -> AnyResult<()> { let cli = Cli::parse(); + env::set_var("DEFMT_LOG", "card_io_fw=debug,info"); + match cli.subcommand { Subcommands::Build { hw, variant: opt } => build(hw.unwrap_or_default(), opt), Subcommands::Test => test(),