discrete_count_core/lib.rs
1#![no_std]
2#![warn(clippy::pedantic)]
3#![allow(clippy::missing_errors_doc)]
4
5#[allow(type_alias_bounds)]
6pub type CountRaw<C: Counter> = <<C as Counter>::Reader as CountReader>::RawData;
7/// Encapsulates the types and operations assosciated with a count-oriented driver.
8pub trait Counter {
9 type Reader: CountReader;
10 /// Encapsulates the magnitude of what is being measured for each count.
11 ///
12 /// E.g.:
13 /// - `(typenum::U1, typenum::U10000)` for a 10khz oscilator.
14 /// - a 1024 PPR AB encoder has tau/4096 resolution, ~= 1/652 radians:
15 /// `(typenum::U1, typenum::U652)`
16 type Resolution;
17
18 /// Encapsulates what is being measured. Some possible measures:
19 ///
20 /// - Degrees
21 /// - arc-seconds
22 /// - Radians
23 /// - Milliseconds
24 /// - Meters
25 ///
26 /// E.g.
27 /// ```rust ignore
28 ///
29 /// // Basic, short-life 1khz resolution time-measure
30 /// struct MilliSeconds(u32);
31 ///
32 /// // a 1024ppr encoder has log_2(1024 * 4) = 12 bits of information.
33 /// // Fixing the fractional measure to be 12 bits encapsulates this precision.
34 /// // A typical valve rarely makes a full rotation, so the smaller bit-count
35 /// // does not matter, and 16 bits is the smallest that can hold 12 fractional bits.
36 /// //
37 /// // We use Tau in its name, because we are thinking in terms of full-rotations,
38 /// // and `Tau` radians is one full rotation
39 /// struct ValveTau(discrete_count::re_exports::fixed::types::I6F12);
40 ///
41 /// // Advanced manufacturing equipment might need rotary stages that need to track
42 /// // up to 2^16 rotations, with pricesion up to 2^-16 radians.
43 /// struct RotaryStageTau(discrete_count::re_exports::fixed::types::I16F16);
44 ///
45 /// // Encapsulate 32-bit POSIX timestamps
46 /// struct Seconds(u32);
47 ///
48 /// // Encapsulate 64-bit POSIX timestamps
49 /// struct BigSeconds(u64);
50 /// ```
51 type Measure;
52
53
54 fn update_count_state(&mut self, count: CountRaw<Self>) -> Result<(), <Self::Reader as CountReader>::ReadErr>;
55 fn read_count_state(&self) -> &CountRaw<Self>;
56 /// Updates the internal count state.
57 /// # Errors
58 ///
59 /// If the internal count-read errors out, the implementation should return an error,
60 /// and not update the count.
61 fn try_update_count(&mut self) -> Result<(), <Self::Reader as CountReader>::ReadErr>;
62 /// Reads the count, applying scale to read measure.
63 /// # Errors
64 ///
65 /// If the internal count-read errors out, the implementation should return an error.
66 fn try_read_measure(
67 &self,
68 ) -> Result<Self::Measure, <Self::Reader as CountReader>::ReadErr>;
69 fn measure_count_state(&self) -> Self::Measure;
70 /// Derive the magnitude being measured. E.g.
71 /// ```rust ignore
72 /// let stage_rotation = Count::measure(&stage, stage.try_read_measure()?);
73 /// let rotation_count = stage_rotation.int();
74 /// let rotation_angle = stage_rotation.frac();
75 /// ```
76 fn try_update_and_measure(&mut self, count: &CountRaw<Self>) -> Result<Self::Measure, <Self::Reader as CountReader>::ReadErr>;
77 fn direct_measure() -> Result<Self::Measure, <Self::Reader as CountReader>::ReadErr> {
78 Ok(Self::measure_count(&<Self::Reader as CountReader>::read()?))
79 }
80 fn measure_count(count: &CountRaw<Self>) -> Self::Measure;
81}
82
83/// Used to interface directly with the source of a count.
84/// Typical implementation is to read directly from the relevant hardware register.
85pub trait CountReader {
86 type ReadErr;
87 type RawData;
88 fn read() -> Result<Self::RawData, Self::ReadErr>;
89}