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
```
-
+
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);
}
}
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() }
+ }
+}