Skip to main content

tag_cal_write/
tag-cal-write.rs

1//! `tag-cal-write`: write an identity (no-op) magnetometer calibration.
2//!
3//! Port of `host/commandline/tag-cal-write.cc`. Writes `M' = A(M - V)` with
4//! A = identity and V = 0, and a zero accelerometer offset. Several
5//! CompassTag-family state handlers refuse to start a run until at least one
6//! calibration entry is stored ("Device must be calibrated"), which a
7//! mass-erase reflash wipes; this unblocks power and lifecycle testing on a
8//! freshly reflashed board. Readings taken under it are NOT calibrated: run
9//! tag-cal or qtcalibrate before trusting compass output from the board.
10//!
11//! Usage: `tag-cal-write [-d] [-b BUS:DEVICE]`.
12//!
13//! # Exit status
14//!
15//! 0 when the constants were written; 1 if no base matches, the attach fails
16//! or `WriteCalibration` fails. Option errors exit 2 (clap).
17//!
18//! # Hardware side effects
19//!
20//! The attach resets the tag. The firmware stores the constants as a new
21//! calibration entry, so the tag will then start a run with an uncalibrated
22//! compass; overwrite it with a real calibration before trusting the data.
23
24use std::process::ExitCode;
25
26use clap::Parser;
27use tag_tools::{BaseArgs, init_logging, select_base};
28use tagcore::Tag;
29use tagcore::proto::{CalibrationConstants, calibration_constants};
30
31/// write an identity (no-op) calibration constant set, to unblock a tag that
32/// refuses to start with "Device must be calibrated" after a mass-erase
33/// reflash -- NOT a substitute for real calibration
34#[derive(Parser)]
35#[command(name = "tag-cal-write")]
36struct Cli {
37    /// The shared `--debug` and `--base` options.
38    #[command(flatten)]
39    base: BaseArgs,
40}
41
42/// Identity magnetometer constants and a zero accelerometer offset.
43fn identity_constants() -> CalibrationConstants {
44    CalibrationConstants {
45        timestamp: 0,
46        magnetometer: Some(calibration_constants::MagConstants {
47            a00: 1.0,
48            a11: 1.0,
49            a22: 1.0,
50            ..Default::default()
51        }),
52        accelerometer: Some(calibration_constants::AccelConstants::default()),
53    }
54}
55
56/// Attaches (resetting the tag) and writes [`identity_constants`].
57fn main() -> ExitCode {
58    let cli = Cli::parse();
59    init_logging(&cli.base);
60
61    let tag = Tag::new();
62    let dev = select_base::<Cli>(&tag, &cli.base);
63    if !tag.attach(&dev) {
64        eprintln!("Attach failed");
65        return ExitCode::FAILURE;
66    }
67
68    if tag.write_calibration(&identity_constants()).is_err() {
69        eprintln!("WriteCalibration failed: {}", tag.debug_message());
70        return ExitCode::FAILURE;
71    }
72    println!(
73        "wrote identity calibration constants (placeholder only -- not a real calibration; \
74         compass output will not be accurate until tag-cal/qtcalibrate is run)"
75    );
76    ExitCode::SUCCESS
77}