accel_stepper/
device.rs

1use core::time::Duration;
2use void::Void;
3
4/// An interface to the stepper motor.
5pub trait Device {
6    /// The type of error that may be encountered when taking a step.
7    ///
8    /// Use `!` (or [`void::Void`] on stable) if stepping can never fail.
9    type Error;
10
11    fn step(&mut self, ctx: &StepContext) -> Result<(), Self::Error>;
12}
13
14impl<'a, D: Device> Device for &'a mut D {
15    type Error = D::Error;
16
17    fn step(&mut self, ctx: &StepContext) -> Result<(), Self::Error> {
18        (*self).step(ctx)
19    }
20}
21
22/// Extra contextual information passed to a [`Device`] when its
23/// [`Device::step()`] method is invoked.
24#[derive(Debug, Clone, PartialEq)]
25pub struct StepContext {
26    /// The new position, in steps.
27    pub position: i64,
28    /// The time (as dictated by [`crate::SystemClock::elapsed()`]) this step
29    /// was taken.
30    pub step_time: Duration,
31}
32
33/// A [`Device`] which will call one function for a forward step, and another
34/// for a backward one.
35///
36/// See [`fallible_func_device()`] for a version which accepts fallible
37/// callbacks.
38pub fn func_device<F, B, T>(
39    forward: F,
40    backward: B,
41) -> impl Device<Error = Void>
42where
43    F: FnMut() -> T,
44    B: FnMut() -> T,
45{
46    Infallible {
47        forward,
48        backward,
49        previous_position: 0,
50    }
51}
52
53struct Infallible<F, B> {
54    previous_position: i64,
55    forward: F,
56    backward: B,
57}
58
59impl<F, B, T> Device for Infallible<F, B>
60where
61    F: FnMut() -> T,
62    B: FnMut() -> T,
63{
64    type Error = Void;
65
66    #[inline]
67    fn step(&mut self, ctx: &StepContext) -> Result<(), Self::Error> {
68        let diff = ctx.position - self.previous_position;
69
70        if diff > 0 {
71            (self.forward)();
72        } else if diff < 0 {
73            (self.backward)();
74        }
75
76        self.previous_position = ctx.position;
77        Ok(())
78    }
79}
80
81/// A device which uses callbacks which may fail.
82///
83/// See [`func_device()`] for a version which uses infallible callbacks.
84pub fn fallible_func_device<F, B, T, E>(
85    forward: F,
86    backward: B,
87) -> impl Device<Error = E>
88where
89    F: FnMut() -> Result<T, E>,
90    B: FnMut() -> Result<T, E>,
91{
92    Fallible {
93        forward,
94        backward,
95        previous_position: 0,
96    }
97}
98
99struct Fallible<F, B> {
100    previous_position: i64,
101    forward: F,
102    backward: B,
103}
104
105impl<F, B, T, E> Device for Fallible<F, B>
106where
107    F: FnMut() -> Result<T, E>,
108    B: FnMut() -> Result<T, E>,
109{
110    type Error = E;
111
112    #[inline]
113    fn step(&mut self, ctx: &StepContext) -> Result<(), Self::Error> {
114        let diff = ctx.position - self.previous_position;
115
116        if diff > 0 {
117            (self.forward)()?;
118        } else if diff < 0 {
119            (self.backward)()?;
120        }
121
122        self.previous_position = ctx.position;
123        Ok(())
124    }
125}