feat: add display UI with splash screen, dashboard, and RSSI sparkline
Implement full SSD1306 OLED display support: - Splash screen on boot (1.5s) with project name, version, board - Dashboard showing radio state, config, counters, RSSI/SNR - RSSI history sparkline (64-sample ring buffer, 2px-wide bars) - DisplayOn/DisplayOff host commands routed via dedicated channel - Pure render functions against generic DrawTarget (no hardware coupling) - Display on/off control bypasses radio task entirely Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
17624 files changed
+4564928
-38
No files matched your search
@@ -0,0 +1,90 @@
|
||||
use defmt_parser::Level;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, punctuated::Punctuated};
|
||||
|
||||
use crate::{construct, function_like::log};
|
||||
|
||||
use self::args::Args;
|
||||
|
||||
mod args;
|
||||
|
||||
pub(crate) fn eq(args: TokenStream) -> TokenStream {
|
||||
expand(args, BinOp::Eq)
|
||||
}
|
||||
|
||||
pub(crate) fn ne(args: TokenStream) -> TokenStream {
|
||||
expand(args, BinOp::Ne)
|
||||
}
|
||||
|
||||
fn expand(args: TokenStream, binop: BinOp) -> TokenStream {
|
||||
let args = parse_macro_input!(args as Args);
|
||||
|
||||
let left = args.left;
|
||||
let right = args.right;
|
||||
|
||||
let mut formatting_args = Punctuated::new();
|
||||
|
||||
let extra_string = if let Some(log_args) = args.log_args {
|
||||
if let Some(args) = log_args.formatting_args {
|
||||
formatting_args.extend(args);
|
||||
}
|
||||
format!(": {}", log_args.format_string.value())
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
let vals = match binop {
|
||||
BinOp::Eq => &["left_val", "right_val"][..],
|
||||
BinOp::Ne => &["left_val"][..],
|
||||
};
|
||||
|
||||
for val in vals {
|
||||
formatting_args.push(construct::variable(val));
|
||||
}
|
||||
|
||||
let panic_msg = match binop {
|
||||
BinOp::Eq => format!(
|
||||
"panicked at 'assertion failed: `(left == right)`{}'
|
||||
left: `{{:?}}`
|
||||
right: `{{:?}}`",
|
||||
extra_string
|
||||
),
|
||||
BinOp::Ne => format!(
|
||||
"panicked at 'assertion failed: `(left != right)`{}'
|
||||
left/right: `{{:?}}`",
|
||||
extra_string
|
||||
),
|
||||
};
|
||||
|
||||
let log_args = log::Args {
|
||||
format_string: construct::string_literal(&panic_msg),
|
||||
formatting_args: Some(formatting_args),
|
||||
};
|
||||
let log_stmt = log::expand_parsed(Level::Error, log_args);
|
||||
|
||||
let mut cond = quote!(*left_val == *right_val);
|
||||
if binop == BinOp::Eq {
|
||||
cond = quote!(!(#cond));
|
||||
}
|
||||
|
||||
quote!(
|
||||
// evaluate arguments first
|
||||
match (&(#left), &(#right)) {
|
||||
(left_val, right_val) => {
|
||||
// following `core::assert_eq!`
|
||||
if #cond {
|
||||
#log_stmt;
|
||||
defmt::export::panic()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum BinOp {
|
||||
Eq,
|
||||
Ne,
|
||||
}
|
||||
Reference in new issue
Block a user