1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Pure arithmetic for Timer_A input capture (no PAC/HAL types, `//` comments
// only, so unit_tests can `include!` this file and exercise the exact shipping
// code — see CLAUDE.md "Testing").
//
// Everything here turns raw capture-timestamp deltas (timer ticks) into
// physical quantities (Hz, duty permille) or back. All division rounds
// half-away-from-zero via the usual `(num + den/2) / den` trick, and every
// product is widened to `u64` first: at the largest legal inputs (8 MHz tick
// rate, u32 tick spans) the intermediates overflow `u32` by orders of
// magnitude.
/// Frequency in Hz, rounded, of a signal whose `periods` consecutive full
/// periods spanned `total_ticks` timer ticks at `tick_hz`.
///
/// Returns 0 if `total_ticks` is 0 (no span measured — a division guard, not
/// a meaningful frequency).
pub const
/// Duty cycle in permille (0..=1000), rounded, from a high-time of
/// `high_ticks` out of a period of `period_ticks`.
///
/// Returns 0 if `period_ticks` is 0 (guard); clamps to 1000 so a high-time
/// mismeasured slightly past its own period cannot report an impossible duty.
pub const
/// How many whole periods of a `signal_hz` signal fit in `delta_ticks` ticks
/// at `tick_hz`, rounded to the nearest integer.
///
/// This is the "count periods by time" inverse used with
/// `measure_span_ticks`: capture one edge, wait a known-ish time, capture a
/// later edge — the rounded count is exact as long as the *relative* error
/// between the two clocks is under half a period over the span (for an n-period
/// span, a clock error below 1/(2n)). Returns 0 if `tick_hz` is 0 (guard).
pub const
/// The measured-to-ideal ratio, in permille, of a `delta_ticks` span that
/// should cover exactly `periods` periods of `signal_hz` at `tick_hz`.
///
/// 1000 means the two clocks agree perfectly; 1050 means the span measured 5%
/// long (the tick clock runs 5% fast relative to the signal, or vice versa).
/// This is the DCO-versus-crystal verdict in one number: with the signal on
/// the LFXT crystal (exact) and the ticks on the DCO, the deviation from 1000
/// *is* the DCO's frequency error. Returns 0 on a zero denominator (guard).
pub const
/// Whether `actual` lies within `tol_permille` permille of `expected`
/// (i.e. |actual − expected| · 1000 ≤ expected · tol_permille).
pub const