Skip to main content

no_std_generated_fixtures/
no_std_generated_fixtures.rs

1//! Compile representative generated fixtures as `no_std` firmware artifacts.
2//!
3//! CI and `scripts/local-ci.ps1` build this example on the repository's
4//! no-std and core-only target matrix so generated tables cannot silently
5//! pick up `std`, `alloc`, or floating-point types.
6
7#![no_std]
8#![allow(dead_code)]
9
10use ph_curves::{
11    AffineCalibration, AffineTransform, FilterOutput, Hysteresis, InverseTransferFunction,
12    MonotonicDirection, MovingAverage, PiecewiseLinearTransfer, TemporalFilter, TransferFunction,
13};
14
15static SMOKE_INPUTS: [u16; 2] = [0, u16::MAX];
16static SMOKE_OUTPUTS: [i32; 2] = [-1_000, 1_000];
17
18/// Compile the headline runtime APIs into every no-std/core-only matrix target.
19///
20/// The example is a library artifact, so CI does not execute this function;
21/// compiling its body proves transfer conversion/inversion, both affine forms,
22/// and `u32` temporal state stay on the core-only path.
23pub fn runtime_api_smoke(code: u16, sample: u32) -> (i32, u16, u32, bool) {
24    let transfer = PiecewiseLinearTransfer::new(
25        &SMOKE_INPUTS,
26        &SMOKE_OUTPUTS,
27        MonotonicDirection::Increasing,
28    );
29    let calibrated = match AffineCalibration::new(transfer, 1_001, 0, 1_000) {
30        Ok(value) => value,
31        Err(_) => unreachable!(),
32    };
33    let physical = calibrated.convert(code).unwrap_or_default();
34    let inverse = calibrated.invert(physical).unwrap_or_default();
35
36    let affine = match AffineTransform::new(1_001, 0, 1_000) {
37        Ok(value) => value,
38        Err(_) => unreachable!(),
39    };
40    let _ = affine
41        .apply(physical)
42        .and_then(|value| affine.unapply(value));
43
44    let mut average = MovingAverage::<u32, 1>::new();
45    let filtered = match average.update(sample) {
46        FilterOutput::Ready(value) => value,
47        FilterOutput::WarmingUp { .. } => unreachable!(),
48    };
49    let mut latch = Hysteresis::<u32>::new(100, 200);
50    (physical, inverse, filtered, latch.update(filtered))
51}
52
53/// Mixed family-acceptance fixture: curve LUT plus sparse transfers.
54pub mod family_acceptance {
55    include!("../tests/fixtures/family_acceptance_generated.rs");
56}
57
58/// Reference NTC transfer fixture.
59pub mod ntc {
60    include!("../tests/fixtures/ntc_generated.rs");
61}
62
63/// Standalone and family observation-guard fixture.
64pub mod observation_guards {
65    include!("../tests/fixtures/observation_guards_generated.rs");
66}