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}