From 9eb8523f200b7d591a95e84ef9707864313da0df Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Thu, 31 Jul 2025 20:37:58 +0200 Subject: [PATCH 1/2] Add settings --- macros/Cargo.toml | 2 +- macros/src/args.rs | 104 ++++- macros/src/lib.rs | 58 ++- macros/src/symbol.rs | 61 ++- probe-plotter-tools/Cargo.lock | 647 ++++---------------------- probe-plotter-tools/Cargo.toml | 11 +- probe-plotter-tools/src/bin/viewer.rs | 114 +++++ probe-plotter-tools/src/gui.rs | 79 ++++ probe-plotter-tools/src/lib.rs | 108 +++++ probe-plotter-tools/src/main.rs | 152 +----- probe-plotter-tools/src/metric.rs | 52 +++ probe-plotter-tools/src/setting.rs | 56 +++ probe-plotter-tools/src/symbol.rs | 54 +++ probe-plotter/src/lib.rs | 51 +- probe-plotter/src/metric.rs | 47 ++ probe-plotter/src/setting.rs | 28 ++ 16 files changed, 862 insertions(+), 762 deletions(-) create mode 100644 probe-plotter-tools/src/bin/viewer.rs create mode 100644 probe-plotter-tools/src/gui.rs create mode 100644 probe-plotter-tools/src/lib.rs create mode 100644 probe-plotter-tools/src/metric.rs create mode 100644 probe-plotter-tools/src/setting.rs create mode 100644 probe-plotter-tools/src/symbol.rs create mode 100644 probe-plotter/src/metric.rs create mode 100644 probe-plotter/src/setting.rs diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 11cdffc..708eec7 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -6,7 +6,7 @@ edition = "2024" [dependencies] proc-macro2 = "1.0.95" quote = "1.0.40" -syn = "2" +syn = { version = "2", features = ["full"] } [lib] proc-macro = true diff --git a/macros/src/args.rs b/macros/src/args.rs index 41510df..52b3e5c 100644 --- a/macros/src/args.rs +++ b/macros/src/args.rs @@ -1,23 +1,23 @@ // Based on defmt -use proc_macro2::Span; use syn::{ - LitStr, Token, + LitStr, RangeLimits, Token, parse::{self, Parse, ParseStream}, + spanned::Spanned, }; //FOO: i32 = 0, "x * 3.0" //FOO: i32 = 0 // defaults to "x" -pub(crate) struct Args { +pub(crate) struct MetricArgs { pub(crate) name: syn::Ident, pub(crate) ty: syn::Ident, pub(crate) initial_val: syn::Expr, pub(crate) expression_string: syn::LitStr, } -impl Parse for Args { +impl Parse for MetricArgs { fn parse(input: ParseStream) -> parse::Result { - let name = input.parse()?; + let name: syn::Ident = input.parse()?; let _comma: Token![:] = input.parse()?; let ty = input.parse()?; let _comma: Token![=] = input.parse()?; @@ -29,7 +29,7 @@ impl Parse for Args { let expression_string = match (comma, expression_string) { (Ok(_), Ok(expr)) => expr, (Ok(_), Err(e)) => return Err(e), - (Err(_), _) => LitStr::new("x", Span::mixed_site()), + (Err(_), _) => LitStr::new(&name.to_string(), name.span()), }; Ok(Self { @@ -40,3 +40,95 @@ impl Parse for Args { }) } } + +// FOO: i32 = 0, 0..=10, 2 +// FOO: i32 = 0, 0..=10, // Step size defaults to 1 +// FOO: i32 = 0 // range defaults to the types full range +// TODO Implement the defaults +pub(crate) struct SettingArgs { + pub(crate) name: syn::Ident, + pub(crate) ty: syn::Ident, + pub(crate) initial_val: syn::Expr, + pub(crate) range_start: syn::LitFloat, + pub(crate) range_end: syn::LitFloat, + pub(crate) step_size: syn::LitFloat, +} + +impl Parse for SettingArgs { + fn parse(input: ParseStream) -> parse::Result { + let name = input.parse()?; + let _colon: Token![:] = input.parse()?; + let ty = input.parse()?; + let _eq: Token![=] = input.parse()?; + let initial_val = input.parse()?; + + let _comma: parse::Result = input.parse(); + let range: syn::Expr = input.parse()?; + + let syn::Expr::Range(range) = range else { + panic!("Invalid range") + }; + + let range_start = range + .start + .expect("Only inclusive ranges with both a start and end are supported"); + let range_end = range + .end + .expect("Only inclusive ranges with both a start and end are supported"); + assert!( + matches!(range.limits, RangeLimits::Closed(_)), + "Only inclusive ranges with both a start and end are supported" + ); + + let _comma: parse::Result = input.parse(); + let step_size: syn::Lit = input.parse()?; + + let step_size = match step_size { + syn::Lit::Int(i) => syn::LitFloat::new(&format!("{}.0", i.base10_digits()), i.span()), + syn::Lit::Float(f) => f, + x => return Err(syn::Error::new(x.span(), "expected float or int literal")), + }; + + Ok(Self { + name, + ty, + initial_val, + range_start: expr_to_float_lit(*range_start)?, + range_end: expr_to_float_lit(*range_end)?, + step_size, + }) + } +} + +// TODO: Clean up this mess +fn expr_to_float_lit(e: syn::Expr) -> Result { + let error_msg = "expected float or int literal"; + Ok(match e { + syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Float(f), + .. + }) => f, + syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Int(i), + .. + }) => syn::LitFloat::new(&format!("{}.0", i.base10_digits()), i.span()), + syn::Expr::Unary(syn::ExprUnary { + op: syn::UnOp::Neg(_), + expr, + .. + }) => match *expr { + syn::Expr::Lit(syn::ExprLit { lit, .. }) => match lit { + // TODO: Is there a better way to handle the minus sign? + syn::Lit::Int(i) => { + syn::LitFloat::new(&format!("-{}.0", i.base10_digits()), i.span()) + } + syn::Lit::Float(f) => { + syn::LitFloat::new(&format!("-{}", f.base10_digits()), f.span()) + } + x => return Err(syn::Error::new(x.span(), error_msg)), + }, + x => return Err(syn::Error::new(x.span(), error_msg)), + }, + x => return Err(syn::Error::new(x.span(), error_msg)), + }) +} diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 328d7c5..8673eeb 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -7,7 +7,7 @@ use proc_macro::{Span, TokenStream}; use quote::quote; use syn::parse_macro_input; -use crate::symbol::Symbol; +use crate::symbol::{MetricsSymbol, SettingSymbol}; mod args; mod cargo; @@ -28,9 +28,9 @@ mod symbol; /// ``` #[proc_macro] pub fn make_metric(args: TokenStream) -> TokenStream { - let args = parse_macro_input!(args as args::Args); + let args = parse_macro_input!(args as args::MetricArgs); - let sym_name = Symbol::new( + let sym_name = MetricsSymbol::new( args.ty.to_string(), args.name.to_string(), args.expression_string.value(), @@ -64,6 +64,58 @@ pub fn make_metric(args: TokenStream) -> TokenStream { .into() } +/// Create a Setting instance that will be shown as a slider in the probe-plotter utility +/// +/// ``` +/// make_setting!(NAME_AS_SHOWN_NEXT_TO_SLIDER: DataType = defalt_value, min_value..=max_value, step_size) +/// ``` +/// +/// Note that similar to `cortex_m::singleton!`, this should only be called once per setting. The macro will only return Some() the first time, then None. +/// +/// ``` +/// let mut setting_foo = probe_plotter::make_setting!(FOO: i32 = 0, 0..=10, 1.0).unwrap(); +/// +/// let value = setting_foo.get(); +/// ``` +#[proc_macro] +pub fn make_setting(args: TokenStream) -> TokenStream { + let args = parse_macro_input!(args as args::SettingArgs); + + let sym_name = SettingSymbol::new( + args.ty.to_string(), + args.name.to_string(), + args.range_start.base10_parse().unwrap()..=args.range_end.base10_parse().unwrap(), + args.step_size.base10_parse().unwrap(), + ) + .mangle(); + + let name = args.name; + let ty = args.ty; + let initial_value = args.initial_val; + + quote!( + cortex_m::interrupt::free(|_| { + #[unsafe(export_name = #sym_name)] + static mut #name: (#ty, bool) = + (0, false); + + #[allow(unsafe_code)] + let used = unsafe { #name.1 }; + if used { + None + } else { + #[allow(unsafe_code)] + unsafe { + #name.1 = true; + #name.0 = #initial_value; + Some(::probe_plotter::Setting::new(&mut #name.0)) + } + } + }) + ) + .into() +} + pub(crate) fn crate_local_disambiguator() -> u64 { // We want a deterministic, but unique-per-macro-invocation identifier. For that we // hash the call site `Span`'s debug representation, which contains a counter that diff --git a/macros/src/symbol.rs b/macros/src/symbol.rs index fc41089..86fe30c 100644 --- a/macros/src/symbol.rs +++ b/macros/src/symbol.rs @@ -1,8 +1,10 @@ // Based on defmt +use std::ops::RangeInclusive; + use crate::cargo; -pub struct Symbol { +pub struct MetricsSymbol { /// Name of the Cargo package in which the symbol is being instantiated. Used for avoiding /// symbol name collisions. package: String, @@ -23,7 +25,7 @@ pub struct Symbol { crate_name: String, } -impl Symbol { +impl MetricsSymbol { pub fn new(ty: String, name: String, expr: String) -> Self { Self { // `CARGO_PKG_NAME` is set to the invoking package's name. @@ -38,7 +40,7 @@ impl Symbol { pub fn mangle(&self) -> String { format!( - r#"{{"package":"{}","ty":"{}","name":"{}","expr": "{}","disambiguator":"{}","crate_name":"{}"}}"#, + r#"{{"type":"Metric","package":"{}","ty":"{}","name":"{}","expr":"{}","disambiguator":"{}","crate_name":"{}"}}"#, json_escape(&self.package), json_escape(&self.ty), json_escape(&self.name), @@ -49,6 +51,59 @@ impl Symbol { } } +pub struct SettingSymbol { + /// Name of the Cargo package in which the symbol is being instantiated. Used for avoiding + /// symbol name collisions. + package: String, + + /// Unique identifier that disambiguates otherwise equivalent invocations in the same crate. + disambiguator: u64, + + /// Underlaying data type + ty: String, + + /// Variable name + name: String, + + /// Range of valid values + range: RangeInclusive, + + /// Step size + step_size: f64, + + /// Crate name obtained via CARGO_CRATE_NAME (added since a Cargo package can contain many crates). + crate_name: String, +} + +impl SettingSymbol { + pub fn new(ty: String, name: String, range: RangeInclusive, step_size: f64) -> Self { + Self { + // `CARGO_PKG_NAME` is set to the invoking package's name. + package: cargo::package_name(), + disambiguator: super::crate_local_disambiguator(), + ty, + name, + range, + step_size, + crate_name: cargo::crate_name(), + } + } + + pub fn mangle(&self) -> String { + format!( + r#"{{"type":"Setting","package":"{}","ty":"{}","name":"{}","range":{{"start":{},"end":{}}},"step_size":{},"disambiguator":"{}","crate_name":"{}"}}"#, + json_escape(&self.package), + json_escape(&self.ty), + json_escape(&self.name), + self.range.start(), + self.range.end(), + self.step_size, + self.disambiguator, + json_escape(&self.crate_name), + ) + } +} + fn json_escape(string: &str) -> String { use std::fmt::Write; diff --git a/probe-plotter-tools/Cargo.lock b/probe-plotter-tools/Cargo.lock index f0711b6..ee28a5f 100644 --- a/probe-plotter-tools/Cargo.lock +++ b/probe-plotter-tools/Cargo.lock @@ -261,15 +261,6 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - [[package]] name = "arboard" version = "3.6.0" @@ -524,12 +515,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" -[[package]] -name = "ascii" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" - [[package]] name = "ash" version = "0.38.0+1.3.281" @@ -918,12 +903,6 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -1154,33 +1133,6 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" -[[package]] -name = "cacache" -version = "13.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5063741c7b2e260bbede781cf4679632dd90e2718e99f7715e46824b65670b" -dependencies = [ - "digest", - "either", - "futures", - "hex", - "libc", - "memmap2 0.5.10", - "miette 5.10.0", - "reflink-copy", - "serde", - "serde_derive", - "serde_json", - "sha1", - "sha2", - "ssri", - "tempfile", - "thiserror 1.0.69", - "tokio", - "tokio-stream", - "walkdir", -] - [[package]] name = "calloop" version = "0.13.0" @@ -1254,9 +1206,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.30" +version = "1.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" +checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" dependencies = [ "jobserver", "libc", @@ -1326,12 +1278,6 @@ dependencies = [ "phf 0.12.1", ] -[[package]] -name = "chunked_transfer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" - [[package]] name = "clang-format" version = "0.3.0" @@ -2367,7 +2313,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", - "serde", ] [[package]] @@ -2951,7 +2896,7 @@ dependencies = [ "libc", "log", "md-5", - "miette 7.6.0", + "miette", "serde", "sha2", "strum", @@ -3260,17 +3205,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "geo-types" -version = "0.7.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ddb1950450d67efee2bbc5e429c68d052a822de3aad010d28b351fbb705224" -dependencies = [ - "approx", - "num-traits", - "serde", -] - [[package]] name = "gethostname" version = "0.4.3" @@ -3327,9 +3261,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.30.4" +version = "0.30.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50a99dbe56b72736564cfa4b85bf9a33079f16ae8b74983ab06af3b1a3696b11" +checksum = "f2d1aab06663bdce00d6ca5e5ed586ec8d18033a771906c993a1e3755b368d85" dependencies = [ "bytemuck", "serde", @@ -3577,8 +3511,6 @@ version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" dependencies = [ - "allocator-api2", - "equivalent", "foldhash", ] @@ -3708,61 +3640,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "http-cache" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e883defacf53960c7717d9e928dc8667be9501d9f54e6a8b7703d7a30320e9c" -dependencies = [ - "async-trait", - "bincode 1.3.3", - "cacache", - "http", - "http-cache-semantics", - "httpdate", - "serde", - "url", -] - -[[package]] -name = "http-cache-reqwest" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076afd9d376f09073b515ce95071b29393687d98ed521948edb899195595ddf" -dependencies = [ - "anyhow", - "async-trait", - "http", - "http-cache", - "http-cache-semantics", - "reqwest", - "reqwest-middleware", - "serde", - "url", -] - -[[package]] -name = "http-cache-semantics" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92baf25cf0b8c9246baecf3a444546360a97b569168fdf92563ee6a47829920c" -dependencies = [ - "http", - "http-serde", - "serde", - "time", -] - -[[package]] -name = "http-serde" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f056c8559e3757392c8d091e796416e4649d8e49e88b8d76df6c002f05027fd" -dependencies = [ - "http", - "serde", -] - [[package]] name = "httparse" version = "1.10.1" @@ -3802,23 +3679,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.27.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" -dependencies = [ - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", - "webpki-roots 1.0.2", -] - [[package]] name = "hyper-timeout" version = "0.5.2" @@ -3834,11 +3694,10 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f66d5bd4c6f02bf0542fad85d626775bab9258cf795a4256dcaf3161114d1df" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" dependencies = [ - "base64 0.22.1", "bytes", "futures-channel", "futures-core", @@ -3846,11 +3705,9 @@ dependencies = [ "http", "http-body", "hyper", - "ipnet", "libc", - "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.0", "tokio", "tower-service", "tracing", @@ -4123,22 +3980,6 @@ dependencies = [ "libc", ] -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -4419,7 +4260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.53.2", + "windows-targets 0.53.3", ] [[package]] @@ -4428,15 +4269,25 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "libmimalloc-sys" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88cd67e9de251c1781dbe2f641a1a3ad66eaae831b8a2c38fbdc5ddae16d4d" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "libredox" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0" +checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" dependencies = [ "bitflags 2.9.1", "libc", - "redox_syscall 0.5.15", + "redox_syscall 0.5.17", ] [[package]] @@ -4475,9 +4326,9 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "litrs" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" +checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" [[package]] name = "lock_api" @@ -4505,21 +4356,6 @@ dependencies = [ "log", ] -[[package]] -name = "lru" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0281c2e25e62316a5c9d98f2d2e9e95a37841afdaf4383c177dbb5c1dfab0568" -dependencies = [ - "hashbrown 0.15.4", -] - -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - [[package]] name = "lz4_flex" version = "0.11.5" @@ -4596,15 +4432,6 @@ version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" -[[package]] -name = "memmap2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] - [[package]] name = "memmap2" version = "0.9.7" @@ -4648,18 +4475,6 @@ dependencies = [ "paste", ] -[[package]] -name = "miette" -version = "5.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" -dependencies = [ - "miette-derive 5.10.0", - "once_cell", - "thiserror 1.0.69", - "unicode-width 0.1.14", -] - [[package]] name = "miette" version = "7.6.0" @@ -4667,15 +4482,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" dependencies = [ "cfg-if", - "miette-derive 7.6.0", + "miette-derive", "unicode-width 0.1.14", ] [[package]] name = "miette-derive" -version = "5.10.0" +version = "7.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", @@ -4683,14 +4498,12 @@ dependencies = [ ] [[package]] -name = "miette-derive" -version = "7.6.0" +name = "mimalloc" +version = "0.1.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +checksum = "b1791cbe101e95af5764f06f20f6760521f7158f69dbf9d6baf941ee1bf6bc40" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", + "libmimalloc-sys", ] [[package]] @@ -5368,9 +5181,9 @@ dependencies = [ [[package]] name = "object" -version = "0.37.1" +version = "0.37.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fd943161069e1768b4b3d050890ba48730e590f57e56d4aa04e7e090e61b4a" +checksum = "b3e3d0a7419f081f4a808147e845310313a39f322d7ae1f996b7f001d6cbed04" dependencies = [ "flate2", "memchr", @@ -5464,9 +5277,9 @@ dependencies = [ [[package]] name = "owned_ttf_parser" -version = "0.25.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" dependencies = [ "ttf-parser", ] @@ -5495,7 +5308,7 @@ checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.15", + "redox_syscall 0.5.17", "smallvec", "windows-targets 0.52.6", ] @@ -5813,9 +5626,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.35" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" +checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" dependencies = [ "proc-macro2", "syn 2.0.104", @@ -5827,7 +5640,8 @@ version = "0.1.0" dependencies = [ "defmt", "goblin", - "object 0.37.1", + "mimalloc", + "object 0.37.2", "probe-rs", "rerun", "serde", @@ -6066,61 +5880,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "quinn" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash 2.1.1", - "rustls", - "socket2", - "thiserror 2.0.12", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" -dependencies = [ - "bytes", - "getrandom 0.3.3", - "lru-slab", - "rand 0.9.2", - "ring", - "rustc-hash 2.1.1", - "rustls", - "rustls-pki-types", - "slab", - "thiserror 2.0.12", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.59.0", -] - [[package]] name = "quote" version = "1.0.40" @@ -6252,28 +6011,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "re_analytics" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df56d03319f8dbc658e78fd75cfabe59dee7567db7fd49f9a03d5958ac816fa9" -dependencies = [ - "crossbeam", - "directories", - "ehttp", - "re_build_info", - "re_build_tools", - "re_log", - "serde", - "serde_json", - "sha2", - "thiserror 1.0.69", - "time", - "url", - "uuid", - "web-sys", -] - [[package]] name = "re_arrow_util" version = "0.24.0" @@ -6520,7 +6257,6 @@ dependencies = [ "itertools 0.14.0", "libc", "parking_lot", - "re_analytics", "re_build_info", ] @@ -7170,7 +6906,6 @@ dependencies = [ "re_build_tools", "re_byte_size", "re_chunk", - "re_data_loader", "re_grpc_client", "re_grpc_server", "re_log", @@ -7618,32 +7353,6 @@ dependencies = [ "re_viewport_blueprint", ] -[[package]] -name = "re_view_map" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96b615c4eb17431152f01ac02af6448c156d00a5e49663b2948e4975bb522da" -dependencies = [ - "bytemuck", - "egui", - "glam", - "itertools 0.14.0", - "macaw", - "re_data_ui", - "re_entity_db", - "re_log", - "re_log_types", - "re_query", - "re_renderer", - "re_tracing", - "re_types", - "re_ui", - "re_view", - "re_viewer_context", - "re_viewport_blueprint", - "walkers", -] - [[package]] name = "re_view_spatial" version = "0.24.0" @@ -7804,7 +7513,6 @@ dependencies = [ "parking_lot", "percent-encoding", "poll-promise", - "re_analytics", "re_auth", "re_blueprint_tree", "re_build_info", @@ -7841,7 +7549,6 @@ dependencies = [ "re_view_bar_chart", "re_view_dataframe", "re_view_graph", - "re_view_map", "re_view_spatial", "re_view_tensor", "re_view_text_document", @@ -7979,19 +7686,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "re_web_viewer_server" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42baaf4ad4556b7a5627a9c518979f724c1e0737a47bbcd497485782cc5255b" -dependencies = [ - "document-features", - "re_analytics", - "re_log", - "thiserror 1.0.69", - "tiny_http", -] - [[package]] name = "recursive" version = "0.1.1" @@ -8023,9 +7717,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.15" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8af0dde094006011e6a740d4879319439489813bd0bcdc7d821beaeeff48ec" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ "bitflags 2.9.1", ] @@ -8041,18 +7735,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "reflink-copy" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c81d000a2c524133cc00d2f92f019d399e57906c3b7119271a2495354fe895" -dependencies = [ - "cfg-if", - "libc", - "rustix 1.0.8", - "windows 0.61.3", -] - [[package]] name = "regex" version = "1.11.1" @@ -8088,59 +7770,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" -[[package]] -name = "reqwest" -version = "0.12.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-core", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-rustls", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots 1.0.2", -] - -[[package]] -name = "reqwest-middleware" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57f17d28a6e6acfe1733fe24bcd30774d13bffa4b8a22535b4c8c98423088d4e" -dependencies = [ - "anyhow", - "async-trait", - "http", - "reqwest", - "serde", - "thiserror 1.0.69", - "tower-service", -] - [[package]] name = "rerun" version = "0.24.0" @@ -8153,21 +7782,17 @@ dependencies = [ "camino", "crossbeam", "document-features", - "env_filter", "indexmap", "indicatif", "itertools 0.14.0", - "log", "puffin", "rayon", - "re_analytics", "re_build_info", "re_build_tools", "re_byte_size", "re_capabilities", "re_chunk", "re_crash_handler", - "re_dataframe", "re_entity_db", "re_error", "re_format", @@ -8187,7 +7812,6 @@ dependencies = [ "re_uri", "re_video", "re_viewer", - "re_web_viewer_server", "similar-asserts", "tokio", ] @@ -8318,9 +7942,9 @@ checksum = "60e7c00b6c3bf5e38a880eec01d7e829d12ca682079f8238a464def3c4b31627" [[package]] name = "rustc-demangle" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -8371,9 +7995,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.29" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ "log", "once_cell", @@ -8402,7 +8026,6 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ - "web-time", "zeroize", ] @@ -8577,9 +8200,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.141" +version = "1.0.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" +checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" dependencies = [ "itoa", "memchr", @@ -8616,18 +8239,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - [[package]] name = "serde_with" version = "3.14.0" @@ -8675,28 +8286,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "sha-1" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "sha2" version = "0.10.9" @@ -8840,7 +8429,7 @@ dependencies = [ "cursor-icon", "libc", "log", - "memmap2 0.9.7", + "memmap2", "rustix 0.38.44", "thiserror 1.0.69", "wayland-backend", @@ -8889,6 +8478,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "spirv" version = "0.3.0+sdk-1.3.268.0" @@ -8920,23 +8519,6 @@ dependencies = [ "syn 2.0.104", ] -[[package]] -name = "ssri" -version = "9.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da7a2b3c2bc9693bcb40870c4e9b5bf0d79f9cb46273321bf855ec513e919082" -dependencies = [ - "base64 0.21.7", - "digest", - "hex", - "miette 5.10.0", - "serde", - "sha-1", - "sha2", - "thiserror 1.0.69", - "xxhash-rust", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -9058,9 +8640,6 @@ name = "sync_wrapper" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] [[package]] name = "synstructure" @@ -9246,18 +8825,6 @@ dependencies = [ "strict-num", ] -[[package]] -name = "tiny_http" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389915df6413a2e74fb181895f933386023c71110878cd0825588928e64cdc82" -dependencies = [ - "ascii", - "chunked_transfer", - "httpdate", - "log", -] - [[package]] name = "tinystr" version = "0.8.1" @@ -9300,9 +8867,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.46.1" +version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", "bytes", @@ -9312,9 +8879,9 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "slab", - "socket2", + "socket2 0.6.0", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -9430,7 +8997,7 @@ dependencies = [ "pin-project", "prost", "rustls-native-certs", - "socket2", + "socket2 0.5.10", "tokio", "tokio-rustls", "tokio-stream", @@ -9510,12 +9077,8 @@ checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ "bitflags 2.9.1", "bytes", - "futures-util", "http", - "http-body", - "iri-string", "pin-project-lite", - "tower", "tower-layer", "tower-service", ] @@ -9820,27 +9383,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "walkers" -version = "0.43.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1959f265e0ea31bfb2293639cb6a61fc656c63cee8b93f4db5db03ba2691e555" -dependencies = [ - "egui", - "egui_extras", - "futures", - "geo-types", - "http-cache-reqwest", - "image", - "log", - "lru", - "reqwest", - "reqwest-middleware", - "thiserror 2.0.12", - "tokio", - "wasm-bindgen-futures", -] - [[package]] name = "want" version = "0.3.1" @@ -9951,13 +9493,13 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121" +checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" dependencies = [ "cc", "downcast-rs", - "rustix 0.38.44", + "rustix 1.0.8", "scoped-tls", "smallvec", "wayland-sys", @@ -9965,12 +9507,12 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.10" +version = "0.31.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61" +checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" dependencies = [ "bitflags 2.9.1", - "rustix 0.38.44", + "rustix 1.0.8", "wayland-backend", "wayland-scanner", ] @@ -9988,20 +9530,20 @@ dependencies = [ [[package]] name = "wayland-cursor" -version = "0.31.10" +version = "0.31.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a65317158dec28d00416cb16705934070aef4f8393353d41126c54264ae0f182" +checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29" dependencies = [ - "rustix 0.38.44", + "rustix 1.0.8", "wayland-client", "xcursor", ] [[package]] name = "wayland-protocols" -version = "0.32.8" +version = "0.32.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "779075454e1e9a521794fed15886323ea0feda3f8b0fc1390f5398141310422a" +checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" dependencies = [ "bitflags 2.9.1", "wayland-backend", @@ -10011,9 +9553,9 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fd38cdad69b56ace413c6bcc1fbf5acc5e2ef4af9d5f8f1f9570c0c83eae175" +checksum = "a07a14257c077ab3279987c4f8bb987851bf57081b93710381daea94f2c2c032" dependencies = [ "bitflags 2.9.1", "wayland-backend", @@ -10024,9 +9566,9 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cb6cdc73399c0e06504c437fe3cf886f25568dd5454473d565085b36d6a8bbf" +checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec" dependencies = [ "bitflags 2.9.1", "wayland-backend", @@ -10037,9 +9579,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.6" +version = "0.31.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484" +checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" dependencies = [ "proc-macro2", "quick-xml 0.37.5", @@ -10048,9 +9590,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.31.6" +version = "0.31.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615" +checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142" dependencies = [ "dlib", "log", @@ -10529,7 +10071,7 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.2", + "windows-targets 0.53.3", ] [[package]] @@ -10580,10 +10122,11 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.2" +version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ + "windows-link", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", @@ -10785,9 +10328,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winit" -version = "0.30.11" +version = "0.30.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4409c10174df8779dc29a4788cac85ed84024ccbc1743b776b21a520ee1aaf4" +checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" dependencies = [ "ahash", "android-activity", @@ -10804,7 +10347,7 @@ dependencies = [ "dpi", "js-sys", "libc", - "memmap2 0.9.7", + "memmap2", "ndk", "objc2 0.5.2", "objc2-app-kit 0.2.2", @@ -10969,12 +10512,6 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32ac00cd3f8ec9c1d33fb3e7958a82df6989c42d747bd326c822b1d625283547" -[[package]] -name = "xxhash-rust" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" - [[package]] name = "yoke" version = "0.8.0" @@ -11211,9 +10748,9 @@ checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" [[package]] name = "zune-jpeg" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9e525af0a6a658e031e95f14b7f889976b74a11ba0eca5a5fc9ac8a1c43a6a" +checksum = "fc1f7e205ce79eb2da3cd71c5f55f3589785cb7c79f6a03d1c8d1491bda5d089" dependencies = [ "zune-core", ] diff --git a/probe-plotter-tools/Cargo.toml b/probe-plotter-tools/Cargo.toml index 598f474..5679a25 100644 --- a/probe-plotter-tools/Cargo.toml +++ b/probe-plotter-tools/Cargo.toml @@ -9,8 +9,13 @@ defmt = "1.0.1" goblin = "0.10.0" object = "0.37.1" probe-rs = "0.29.1" -rerun = "0.24.0" +rerun = { version = "0.24.0", default-features = false, features = [ + "native_viewer", + "sdk", + "server", +] } serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.141" -shunting = "0.1.2" - +# mimalloc is a much faster allocator: +mimalloc = "0.1.43" +shunting = "0.1.2" \ No newline at end of file diff --git a/probe-plotter-tools/src/bin/viewer.rs b/probe-plotter-tools/src/bin/viewer.rs new file mode 100644 index 0000000..caf31bf --- /dev/null +++ b/probe-plotter-tools/src/bin/viewer.rs @@ -0,0 +1,114 @@ +// A custom rerun viewer capable of showing and editing settings + +use std::{sync::mpsc, thread, time::Duration}; + +use probe_plotter_tools::{gui::MyApp, metric::Status, parse_elf_file, setting::Setting}; +use rerun::external::{eframe, re_crash_handler, re_grpc_server, re_log, re_viewer, tokio}; +use shunting::MathContext; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let elf_path = std::env::args() + .nth(1) + .expect("Usage: \nprobe-plotter /path/to/elf chip"); + + let target = std::env::args() + .nth(2) + .unwrap_or_else(|| "stm32g474retx".to_owned()); + + let (mut metrics, mut settings) = parse_elf_file(&elf_path); + + let main_thread_token = rerun::MainThreadToken::i_promise_i_am_on_the_main_thread(); + + // Direct calls using the `log` crate to stderr. Control with `RUST_LOG=debug` etc. + re_log::setup_logging(); + + // Install handlers for panics and crashes that prints to stderr and send + // them to Rerun analytics (if the `analytics` feature is on in `Cargo.toml`). + re_crash_handler::install_crash_handlers(rerun::build_info()); + + // Listen for gRPC connections from Rerun's logging SDKs. + // There are other ways of "feeding" the viewer though - all you need is a `re_smart_channel::Receiver`. + let (rx, _) = re_grpc_server::spawn_with_recv( + "0.0.0.0:9876".parse().unwrap(), + "75%".parse().unwrap(), + re_grpc_server::shutdown::never(), + ); + + let (settings_update_sender, settings_update_receiver) = mpsc::channel::(); + + let mut native_options = re_viewer::native::eframe_options(None); + native_options.viewport = native_options.viewport.with_app_id("probe-plotter"); + + let startup_options = re_viewer::StartupOptions::default(); + + // This is used for analytics, if the `analytics` feature is on in `Cargo.toml` + let app_env = re_viewer::AppEnvironment::Custom("probe-plotter-tools".to_owned()); + + let (initial_settings_sender, initial_settings_receiver) = mpsc::channel(); + + // probe-thread + thread::spawn(move || { + let mut session = probe_rs::Session::auto_attach(target, Default::default()).unwrap(); + let mut core = session.core(0).unwrap(); + + let rec = rerun::RecordingStreamBuilder::new("probe-plotter") + .spawn() + .unwrap(); + + // Load initial values from device + for setting in &mut settings { + setting.read(&mut core).unwrap(); + } + + // Send initial settings back to main thread + initial_settings_sender.send(settings).unwrap(); + + let mut math_ctx = MathContext::new(); + loop { + for mut setting in settings_update_receiver.try_iter() { + setting.write(setting.value, &mut core).unwrap(); + } + + for m in &mut metrics { + m.read(&mut core, &mut math_ctx).unwrap(); + let (x, s) = m.compute(&mut math_ctx); + if let Status::New = s { + rec.log(m.name.clone(), &rerun::Scalars::single(x)).unwrap(); + } else { + std::thread::sleep(Duration::from_millis(1)); + } + } + } + }); + + // Receive initial settings from to probe-thread thread + let settings = initial_settings_receiver.recv().unwrap(); + + let window_title = "probe-plotter"; + eframe::run_native( + window_title, + native_options, + Box::new(move |cc| { + re_viewer::customize_eframe_and_setup_renderer(cc)?; + + let mut rerun_app = re_viewer::App::new( + main_thread_token, + re_viewer::build_info(), + &app_env, + startup_options, + cc, + None, + re_viewer::AsyncRuntimeHandle::from_current_tokio_runtime_or_wasmbindgen()?, + ); + rerun_app.add_log_receiver(rx); + Ok(Box::new(MyApp::new( + rerun_app, + settings, + settings_update_sender, + ))) + }), + )?; + + Ok(()) +} diff --git a/probe-plotter-tools/src/gui.rs b/probe-plotter-tools/src/gui.rs new file mode 100644 index 0000000..00cf44a --- /dev/null +++ b/probe-plotter-tools/src/gui.rs @@ -0,0 +1,79 @@ +//! This example shows how to wrap the Rerun Viewer in your own GUI. + +use std::sync::mpsc; + +use rerun::external::{eframe, egui, re_memory, re_viewer}; + +use crate::setting::Setting; + +// By using `re_memory::AccountingAllocator` Rerun can keep track of exactly how much memory it is using, +// and prune the data store when it goes above a certain limit. +// By using `mimalloc` we get faster allocations. +#[global_allocator] +static GLOBAL: re_memory::AccountingAllocator = + re_memory::AccountingAllocator::new(mimalloc::MiMalloc); + +pub struct MyApp { + rerun_app: re_viewer::App, + settings: Vec, + + /// Send settigns here to apply them + settings_channel: mpsc::Sender, +} + +impl MyApp { + pub fn new( + rerun_app: re_viewer::App, + settings: Vec, + settings_channel: mpsc::Sender, + ) -> Self { + Self { + rerun_app, + settings, + settings_channel, + } + } +} + +impl eframe::App for MyApp { + fn save(&mut self, storage: &mut dyn eframe::Storage) { + // Store viewer state on disk + self.rerun_app.save(storage); + } + + /// Called whenever we need repainting, which could be 60 Hz. + fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { + // First add our panel(s): + egui::SidePanel::right("my_side_panel") + .default_width(200.0) + .show(ctx, |ui| { + self.ui(ui); + }); + + // Now show the Rerun Viewer in the remaining space: + self.rerun_app.update(ctx, frame); + } +} + +impl MyApp { + fn ui(&mut self, ui: &mut egui::Ui) { + ui.add_space(4.0); + ui.vertical_centered(|ui| { + ui.strong("Settings"); + }); + ui.separator(); + + for setting in &mut self.settings { + if ui + .add( + egui::Slider::new(&mut setting.value, setting.range.clone()) + .step_by(setting.step_size) + .text(&setting.name), + ) + .changed() + { + self.settings_channel.send(setting.clone()).unwrap(); + } + } + } +} diff --git a/probe-plotter-tools/src/lib.rs b/probe-plotter-tools/src/lib.rs new file mode 100644 index 0000000..dad1840 --- /dev/null +++ b/probe-plotter-tools/src/lib.rs @@ -0,0 +1,108 @@ +pub mod gui; +pub mod metric; +pub mod setting; +pub mod symbol; + +use std::io::Read; + +use object::{Object, ObjectSymbol}; +use probe_rs::{Core, MemoryInterface}; +use serde::Deserialize; +use shunting::{MathContext, ShuntingParser}; + +use crate::{metric::Metric, setting::Setting, symbol::Symbol}; + +pub fn read_value(core: &mut Core, address: u64, ty: Type) -> Result { + let x = match ty { + Type::u8 => core.read_word_8(address)? as f64, + Type::u16 => core.read_word_16(address)? as f64, + Type::u32 => core.read_word_32(address)? as f64, + + Type::i8 => core.read_word_8(address)? as i8 as f64, + Type::i16 => core.read_word_16(address)? as i16 as f64, + Type::i32 => core.read_word_32(address)? as i32 as f64, + + Type::f32 => f32::from_bits(core.read_word_32(address)?) as f64, + }; + + Ok(x) +} + +#[allow(non_camel_case_types)] +#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Hash, Eq)] +pub enum Type { + u8, + u16, + u32, + i8, + i16, + i32, + f32, +} + +// Most of this is taken from https://github.com/knurling-rs/defmt/blob/8e517f8d7224237893e39337a61de8ef98b341f2/decoder/src/elf2table/mod.rs and modified +pub fn parse(elf_bytes: &[u8]) -> (Vec, Vec) { + let elf = object::File::parse(elf_bytes).unwrap(); + + let mut metrics = Vec::new(); + let mut settings = Vec::new(); + + for entry in elf.symbols() { + let Ok(name) = entry.name() else { + continue; + }; + + let Ok(sym) = Symbol::demangle(name) else { + continue; + }; + + // TODO: Why does this assert not succeed? + //assert_eq!(entry.size(), 4); + match sym { + Symbol::Metric { name, expr, ty } => { + let expr = ShuntingParser::parse_str(&expr).unwrap(); + let math_ctx = MathContext::new(); + math_ctx.setvar(&name, shunting::MathOp::Number(0.0)); + math_ctx + .eval(&expr) + .expect("Use the metrics name as name for the value in the expression"); + metrics.push(Metric { + name, + expr, + ty, + address: entry.address(), + last_value: f64::NAN, + }); + } + Symbol::Setting { + name, + ty, + range, + step_size, + } => { + settings.push(Setting { + name, + ty, + address: entry.address(), + value: f64::NAN, + range, + step_size, + }); + } + } + } + + (metrics, settings) +} + +pub fn parse_elf_file(elf_path: &str) -> (Vec, Vec) { + let mut buffer = Vec::new(); + std::fs::File::open(elf_path) + .unwrap() + .read_to_end(&mut buffer) + .unwrap(); + + let (metrics, settings) = parse(&buffer); + + (metrics, settings) +} diff --git a/probe-plotter-tools/src/main.rs b/probe-plotter-tools/src/main.rs index 4e46beb..851a117 100644 --- a/probe-plotter-tools/src/main.rs +++ b/probe-plotter-tools/src/main.rs @@ -1,10 +1,6 @@ -use core::fmt; -use std::{io::Read, time::Duration}; - -use object::{Object, ObjectSymbol}; -use probe_rs::{Core, MemoryInterface}; -use serde::Deserialize; -use shunting::{MathContext, RPNExpr, ShuntingParser}; +use probe_plotter_tools::{metric::Status, parse_elf_file}; +use shunting::MathContext; +use std::time::Duration; fn main() { let elf_path = std::env::args() @@ -14,16 +10,11 @@ fn main() { let target = std::env::args() .nth(2) .unwrap_or_else(|| "stm32g474retx".to_owned()); + let mut session = probe_rs::Session::auto_attach(target, Default::default()).unwrap(); let mut core = session.core(0).unwrap(); - let mut buffer = Vec::new(); - std::fs::File::open(elf_path) - .unwrap() - .read_to_end(&mut buffer) - .unwrap(); - - let mut metrics = parse(&buffer); + let (mut metrics, _settings) = parse_elf_file(&elf_path); for m in &metrics { println!("{}: {}", m.name, m.address); } @@ -36,9 +27,11 @@ fn main() { .spawn() .unwrap(); + let mut math_ctx = MathContext::new(); loop { for m in &mut metrics { - let (x, s) = m.read(&mut core).unwrap(); + m.read(&mut core, &mut math_ctx).unwrap(); + let (x, s) = m.compute(&mut math_ctx); if let Status::New = s { rec.log(m.name.clone(), &rerun::Scalars::single(x)).unwrap(); } else { @@ -47,132 +40,3 @@ fn main() { } } } - -#[derive(Debug)] -enum Type { - U8, - U16, - U32, - I8, - I16, - I32, - F32, -} - -struct Metric { - name: String, - expr: RPNExpr, - ty: Type, - address: u64, - math_ctx: MathContext, - pub last_value: f64, -} - -impl fmt::Debug for Metric { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Metric") - .field("name", &self.name) - .field("expr", &self.expr) - .field("ty", &self.ty) - .field("address", &self.address) - .finish() - } -} - -enum Status { - SameAsLast, - New, -} - -impl Metric { - pub fn read(&mut self, core: &mut Core) -> Result<(f64, Status), probe_rs::Error> { - let x = match self.ty { - Type::U8 => core.read_word_8(self.address)? as f64, - Type::U16 => core.read_word_16(self.address)? as f64, - Type::U32 => core.read_word_32(self.address)? as f64, - - Type::I8 => core.read_word_8(self.address)? as i8 as f64, - Type::I16 => core.read_word_16(self.address)? as i16 as f64, - Type::I32 => core.read_word_32(self.address)? as i32 as f64, - - Type::F32 => f32::from_bits(core.read_word_32(self.address)?) as f64, - }; - - self.math_ctx.setvar("x", shunting::MathOp::Number(x)); - let new = self.math_ctx.eval(&self.expr).unwrap(); - let status = if new == self.last_value { - Status::SameAsLast - } else { - Status::New - }; - self.last_value = new; - Ok((new, status)) - } -} - -// Most of this is taken from https://github.com/knurling-rs/defmt/blob/8e517f8d7224237893e39337a61de8ef98b341f2/decoder/src/elf2table/mod.rs and modified -fn parse(elf_bytes: &[u8]) -> Vec { - let elf = object::File::parse(elf_bytes).unwrap(); - - let mut v = Vec::new(); - - for entry in elf.symbols() { - let Ok(name) = entry.name() else { - continue; - }; - - let Ok(sym) = Symbol::demangle(name) else { - continue; - }; - - // TODO: Why does this assert not succeed? - //assert_eq!(entry.size(), 4); - let ty = match sym.ty.as_str() { - "u8" => Type::U8, - "u16" => Type::U16, - "u32" => Type::U32, - - "i8" => Type::I8, - "i16" => Type::I16, - "i32" => Type::I32, - - "f32" => Type::F32, - t => { - eprintln!("Invalid type: '{t}' for value '{name}'"); - continue; - } - }; - - let expr = ShuntingParser::parse_str(&sym.expr).unwrap(); - let math_ctx = MathContext::new(); - math_ctx.setvar("x", shunting::MathOp::Number(0.0)); - math_ctx.eval(&expr).expect("Use `x` as name for the value"); - - v.push(Metric { - name: sym.name, - expr, - ty, - address: entry.address(), - last_value: f64::NAN, - math_ctx, - }); - } - - v -} - -#[derive(Deserialize, PartialEq, Eq, Hash)] -struct Symbol { - name: String, - expr: String, - ty: String, -} - -#[derive(Debug)] -struct InvalidSymbolError; - -impl Symbol { - pub fn demangle(raw: &str) -> Result { - serde_json::from_str(raw).map_err(|_| InvalidSymbolError) - } -} diff --git a/probe-plotter-tools/src/metric.rs b/probe-plotter-tools/src/metric.rs new file mode 100644 index 0000000..80e656b --- /dev/null +++ b/probe-plotter-tools/src/metric.rs @@ -0,0 +1,52 @@ +use shunting::MathContext; +use std::fmt; + +use crate::{Type, read_value}; + +pub struct Metric { + pub name: String, + pub expr: shunting::RPNExpr, + pub ty: Type, + pub address: u64, + pub last_value: f64, +} + +impl fmt::Debug for Metric { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Metric") + .field("name", &self.name) + .field("expr", &self.expr) + .field("ty", &self.ty) + .field("address", &self.address) + .finish() + } +} + +pub enum Status { + SameAsLast, + New, +} + +impl Metric { + pub fn read( + &mut self, + core: &mut probe_rs::Core, + math_ctx: &mut MathContext, + ) -> Result<(), probe_rs::Error> { + let x = read_value(core, self.address, self.ty)?; + math_ctx.setvar(&self.name, shunting::MathOp::Number(x)); + + Ok(()) + } + + pub fn compute(&mut self, math_ctx: &mut MathContext) -> (f64, Status) { + let new = math_ctx.eval(&self.expr).unwrap(); + let status = if new == self.last_value { + Status::SameAsLast + } else { + Status::New + }; + self.last_value = new; + (new, status) + } +} diff --git a/probe-plotter-tools/src/setting.rs b/probe-plotter-tools/src/setting.rs new file mode 100644 index 0000000..ad564d6 --- /dev/null +++ b/probe-plotter-tools/src/setting.rs @@ -0,0 +1,56 @@ +use std::ops::RangeInclusive; + +use probe_rs::MemoryInterface; + +use crate::{Type, read_value}; + +#[derive(Clone, Debug)] +pub struct Setting { + pub name: String, + pub ty: Type, + pub address: u64, + pub value: f64, + pub range: RangeInclusive, + pub step_size: f64, +} + +impl Setting { + pub fn read(&mut self, core: &mut probe_rs::Core) -> Result<(), probe_rs::Error> { + self.value = read_value(core, self.address, self.ty)?; + Ok(()) + } + + pub fn write(&mut self, x: f64, core: &mut probe_rs::Core) -> Result<(), probe_rs::Error> { + match self.ty { + Type::u8 => core.write_word_8( + self.address, + x.round().clamp(u8::MIN as _, u8::MAX as _) as u8, + )?, + Type::u16 => core.write_word_16( + self.address, + x.round().clamp(u16::MIN as _, u16::MAX as _) as u16, + )?, + Type::u32 => core.write_word_32( + self.address, + x.round().clamp(u32::MIN as _, u32::MAX as _) as u32, + )?, + + Type::i8 => core.write_word_8( + self.address, + x.round().clamp(i8::MIN as _, i8::MAX as _) as u8, + )?, + Type::i16 => core.write_word_16( + self.address, + x.round().clamp(i16::MIN as _, i16::MAX as _) as u16, + )?, + Type::i32 => core.write_word_32( + self.address, + x.round().clamp(i32::MIN as _, i32::MAX as _) as u32, + )?, + + Type::f32 => core.write_word_32(self.address, (x as f32).to_bits())?, + }; + + Ok(()) + } +} diff --git a/probe-plotter-tools/src/symbol.rs b/probe-plotter-tools/src/symbol.rs new file mode 100644 index 0000000..618b56c --- /dev/null +++ b/probe-plotter-tools/src/symbol.rs @@ -0,0 +1,54 @@ +use serde::Deserialize; +use std::ops::RangeInclusive; + +use crate::Type; + +#[derive(Deserialize, PartialEq)] +#[serde(tag = "type")] +pub enum Symbol { + Metric { + name: String, + + /// Exproession to apply before plotting + expr: String, + + /// Type of value, i32, u8 etc. + ty: Type, + }, + Setting { + name: String, + + /// Type of value, i32, u8 etc. + ty: Type, + + /// Range of valid values + range: RangeInclusive, + + /// Step size + step_size: f64, + }, +} + +impl Symbol { + pub fn name(&self) -> &str { + match self { + Symbol::Metric { name, .. } => name, + Symbol::Setting { name, .. } => name, + } + } + pub fn ty(&self) -> Type { + match self { + Symbol::Metric { ty, .. } => *ty, + Symbol::Setting { ty, .. } => *ty, + } + } +} + +#[derive(Debug)] +pub struct InvalidSymbolError; + +impl Symbol { + pub fn demangle(raw: &str) -> Result { + serde_json::from_str(raw).map_err(|_| InvalidSymbolError) + } +} diff --git a/probe-plotter/src/lib.rs b/probe-plotter/src/lib.rs index c6719d7..7883029 100644 --- a/probe-plotter/src/lib.rs +++ b/probe-plotter/src/lib.rs @@ -1,50 +1,7 @@ #![no_std] -// TODO: Adjust size constraints for targets other than 32bit +pub mod metric; +pub mod setting; -pub trait Metricable: Sized {} -impl Metricable for i8 {} -impl Metricable for i16 {} -impl Metricable for i32 {} -impl Metricable for u8 {} -impl Metricable for u16 {} -impl Metricable for u32 {} - -// TODO: Add f32? - -pub use macros::make_metric; - -pub struct Metric { - x: *mut T, -} - -/// Create using [make_metric] -/// -/// ``` -/// let mut metric_foo = macros::make_metric!(FOO: i32 = 0, "x * 3.0").unwrap(); -/// metric_foo.set(42); -/// ``` -/// -/// Will create a metric which on the host side will be called `FOO` and it -/// will be presented as 3 times the value set in metric_foo.set(x); -/// -/// This library currently uses the `shunting` library for parsing the expression for the formula. -/// Check the documentation for that lib for the syntax to use. -impl Metric { - /// # Safety - /// Internal use only by [make_metric] - pub const unsafe fn new(x: *mut T) -> Self { - Metric { x } - } - - pub fn set(&mut self, x: T) { - unsafe { - // TODO: Is volatile the right thing to use here? - self.x.write_volatile(x); - } - } - - pub fn get(&mut self) -> T { - unsafe { self.x.read_volatile() } - } -} +pub use metric::{Metric, make_metric}; +pub use setting::{Setting, make_setting}; diff --git a/probe-plotter/src/metric.rs b/probe-plotter/src/metric.rs new file mode 100644 index 0000000..23fdf8c --- /dev/null +++ b/probe-plotter/src/metric.rs @@ -0,0 +1,47 @@ +// TODO: Adjust size constraints for targets other than 32bit + +pub trait Metricable: Sized {} +impl Metricable for i8 {} +impl Metricable for i16 {} +impl Metricable for i32 {} +impl Metricable for u8 {} +impl Metricable for u16 {} +impl Metricable for u32 {} +impl Metricable for f32 {} + +pub use macros::make_metric; + +pub struct Metric { + x: *mut T, +} + +/// Create using [make_metric] +/// +/// ``` +/// let mut metric_foo = macros::make_metric!(FOO: i32 = 0, "x * 3.0").unwrap(); +/// metric_foo.set(42); +/// ``` +/// +/// Will create a metric which on the host side will be called `FOO` and it +/// will be presented as 3 times the value set in metric_foo.set(x); +/// +/// This library currently uses the `shunting` library for parsing the expression for the formula. +/// Check the documentation for that lib for the syntax to use. +impl Metric { + /// # Safety + /// Internal use only by [make_metric] + pub const unsafe fn new(x: *mut T) -> Self { + Metric { x } + } + + pub fn set(&mut self, x: T) { + unsafe { + // TODO: Is volatile the right thing to use here? + self.x.write_volatile(x); + } + } + + pub fn get(&mut self) -> T { + unsafe { self.x.read_volatile() } + } +} diff --git a/probe-plotter/src/setting.rs b/probe-plotter/src/setting.rs new file mode 100644 index 0000000..bd5d976 --- /dev/null +++ b/probe-plotter/src/setting.rs @@ -0,0 +1,28 @@ +pub use macros::make_setting; + +use crate::metric::Metricable; + +pub struct Setting { + x: *mut T, +} + +/// Create using [make_setting] +/// +/// ``` +/// let mut setting_foo = macros::make_setting!(FOO: i32 = 3, 0..=10).unwrap(); +/// let current value = setting_foo.get(); +/// ``` +/// +/// Will create a setting which on will show as a slider on the host side with the range +/// 0..=10. The initial value will be 3. +impl Setting { + /// # Safety + /// Internal use only by [make_setting] + pub const unsafe fn new(x: *mut T) -> Self { + Setting { x } + } + + pub fn get(&mut self) -> T { + unsafe { self.x.read_volatile() } + } +} From c85ed6a6860b543064c0b23f7bb75bc1e8f81395 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 2 Aug 2025 00:13:03 +0200 Subject: [PATCH 2/2] Update examples --- README.md | 20 ++++++++++++++------ examples/simple/src/main.rs | 16 +++++++++++++--- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 6e7e8db..b5036aa 100644 --- a/README.md +++ b/README.md @@ -10,21 +10,29 @@ A set of tools to plot values from the target to graph in rerun with minimal per #![no_main] use cortex_m_rt::entry; -use panic_halt as _; +use probe_plotter::{make_metric, make_setting}; #[entry] fn main() -> ! { - use probe_plotter::make_metric; - let mut sawtooth = make_metric!(SAWTOOTH: i32 = 42, "(x / 10) % 100").unwrap(); - let mut sine = make_metric!(SINE: i32 = 42, "100 * sin(2 * pi * x / 4000)").unwrap(); + let mut sawtooth = make_metric!(SAWTOOTH: i32 = 42, "(SAWTOOTH / 10) % 100").unwrap(); + let mut sine = make_metric!(SINE: i32 = 42, "100 * sin(2 * pi * SINE / 4000)").unwrap(); + + let mut setting_roundtrip = + make_metric!(SETTING_ROUNDTRIP: i8 = 0, "SETTING_ROUNDTRIP").unwrap(); + + // Allow values -1..=7, step by 2, so {-1, 1, 3, 5, 7} + let mut setting = make_setting!(SETTING: i8 = 42, -1..=7, 2).unwrap(); + loop { for i in 0..i32::MAX { sawtooth.set(i); sine.set(i); - cortex_m::asm::delay(100_000); + + setting_roundtrip.set(setting.get()); } } } + ``` The formulas seen in the `make_metric` macro invocation are computed by the host and will thus have zero impact on the targets performance. The `set` method on the metrics object is simply a volatile store which is quite cheap. The host will then read that value using the debug probe at regular intervals and update the graph on any changes. @@ -50,4 +58,4 @@ cargo run ../examples/simple/target/thumbv7em-none-eabihf/debug/simple stm32g474 # Rerun will open with a graph showing all created metrics objects ``` -Screenshot +image diff --git a/examples/simple/src/main.rs b/examples/simple/src/main.rs index 6651401..a79b1e2 100644 --- a/examples/simple/src/main.rs +++ b/examples/simple/src/main.rs @@ -5,18 +5,28 @@ use cortex_m_rt::entry; use defmt_rtt as _; use panic_halt as _; +use probe_plotter::{make_metric, make_setting}; #[entry] fn main() -> ! { - use probe_plotter::make_metric; defmt::println!("Running..."); - let mut sawtooth = make_metric!(SAWTOOTH: i32 = 42, "(x / 10) % 100").unwrap(); + let mut sawtooth = make_metric!(SAWTOOTH: i32 = 42, "(SAWTOOTH / 10) % 100").unwrap(); defmt::println!("foo initialized to: {}", sawtooth.get()); - let mut sine = make_metric!(SINE: i32 = 42, "100 * sin(2 * pi * x / 4000)").unwrap(); + let mut sine = make_metric!(SINE: i32 = 42, "100 * sin(2 * pi * SINE / 4000)").unwrap(); + + let mut setting_roundtrip = + make_metric!(SETTING_ROUNDTRIP: i8 = 0, "SETTING_ROUNDTRIP").unwrap(); + + // Allow values -1..=7, step by 2, so {-1, 1, 3, 5, 7} + let mut setting = make_setting!(SETTING: i8 = 42, -1..=7, 2).unwrap(); + loop { for i in 0..i32::MAX { sawtooth.set(i); sine.set(i); + + setting_roundtrip.set(setting.get()); + cortex_m::asm::delay(100_000); } }