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 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
use core::task::Poll;
use embedded_hal::digital::blocking::OutputPin;
use embedded_hal::digital::ErrorType;
use fugit::TimerDurationU32 as TimerDuration;
use fugit_timer::Timer as TimerTrait;
use crate::traits::Step;
use super::SignalError;
/// The "future" returned by [`Stepper::step`]
///
/// 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::step`]: crate::Stepper::step
#[must_use]
pub struct StepFuture<Driver, Timer, const TIMER_HZ: u32> {
driver: Driver,
timer: Timer,
state: State,
}
impl<Driver, Timer, const TIMER_HZ: u32> StepFuture<Driver, Timer, TIMER_HZ>
where
Driver: Step,
Timer: TimerTrait<TIMER_HZ>,
{
/// Create new instance of `StepFuture`
///
/// This constructor is public to provide maximum flexibility for
/// non-standard use cases. Most users can ignore this and just use
/// [`Stepper::step`] instead.
///
/// [`Stepper::step`]: crate::Stepper::step
pub fn new(driver: Driver, timer: Timer) -> Self {
Self {
driver,
timer,
state: State::Initial,
}
}
/// 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<
(),
SignalError<
Driver::Error,
<Driver::Step as ErrorType>::Error,
Timer::Error,
>,
>,
> {
match self.state {
State::Initial => {
// Start step pulse
self.driver
.step()
.map_err(|err| SignalError::PinUnavailable(err))?
.set_high()
.map_err(|err| SignalError::Pin(err))?;
let ticks: TimerDuration<TIMER_HZ> =
Driver::PULSE_LENGTH.convert();
self.timer
.start(ticks)
.map_err(|err| SignalError::Timer(err))?;
self.state = State::PulseStarted;
Poll::Pending
}
State::PulseStarted => {
match self.timer.wait() {
Ok(()) => {
// End step pulse
self.driver
.step()
.map_err(|err| SignalError::PinUnavailable(err))?
.set_low()
.map_err(|err| SignalError::Pin(err))?;
self.state = State::Finished;
Poll::Ready(Ok(()))
}
Err(nb::Error::Other(err)) => {
self.state = State::Finished;
Poll::Ready(Err(SignalError::Timer(err)))
}
Err(nb::Error::WouldBlock) => Poll::Pending,
}
}
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<
(),
SignalError<
Driver::Error,
<Driver::Step as ErrorType>::Error,
Timer::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, Timer) {
(self.driver, self.timer)
}
}
enum State {
Initial,
PulseStarted,
Finished,
}