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
92
93
94
95
96
97
98
99
100
101
102
use core::task::Poll;

use crate::traits::MotionControl;

/// The "future" returned by [`Stepper::move_to_position`]
///
/// Please note that this type provides a custom API and does not implement
/// [`core::future::Future`]. This might change, when using futures for embedded
/// development becomes more practical.
///
/// [`Stepper::move_to_position`]: crate::Stepper::move_to_position
#[must_use]
pub struct MoveToFuture<Driver: MotionControl> {
    driver: Driver,
    state: State<Driver::Velocity>,
}

impl<Driver> MoveToFuture<Driver>
where
    Driver: MotionControl,
{
    /// Create new instance of `MoveToFuture`
    ///
    /// This constructor is public to provide maximum flexibility for
    /// non-standard use cases. Most users can ignore this and just use
    /// [`Stepper::move_to_position`] instead.
    ///
    /// [`Stepper::move_to_position`]: crate::Stepper::move_to_position
    pub fn new(
        driver: Driver,
        max_velocity: Driver::Velocity,
        target_step: i32,
    ) -> Self {
        Self {
            driver,
            state: State::Initial {
                max_velocity,
                target_step,
            },
        }
    }

    /// Poll the future
    ///
    /// The future must be polled for the operation to make progress. The
    /// operation won't start, until this method has been called once. Returns
    /// [`Poll::Pending`], if the operation is not finished yet, or
    /// [`Poll::Ready`], once it is.
    ///
    /// If this method returns [`Poll::Pending`], the user can opt to keep
    /// calling it at a high frequency (see [`Self::wait`]) until the operation
    /// completes, or set up an interrupt that fires once the timer finishes
    /// counting down, and call this method again once it does.
    pub fn poll(&mut self) -> Poll<Result<(), Driver::Error>> {
        match self.state {
            State::Initial {
                max_velocity,
                target_step,
            } => {
                self.driver.move_to_position(max_velocity, target_step)?;
                self.state = State::Moving;
                Poll::Pending
            }
            State::Moving => {
                let still_moving = self.driver.update()?;
                if still_moving {
                    Poll::Pending
                } else {
                    self.state = State::Finished;
                    Poll::Ready(Ok(()))
                }
            }
            State::Finished => Poll::Ready(Ok(())),
        }
    }

    /// Wait until the operation completes
    ///
    /// This method will call [`Self::poll`] in a busy loop until the operation
    /// has finished.
    pub fn wait(&mut self) -> Result<(), Driver::Error> {
        loop {
            if let Poll::Ready(result) = self.poll() {
                return result;
            }
        }
    }

    /// Drop the future and release the resources that were moved into it
    pub fn release(self) -> Driver {
        self.driver
    }
}

enum State<Velocity> {
    Initial {
        max_velocity: Velocity,
        target_step: i32,
    },
    Moving,
    Finished,
}