#![no_std]
#![deny(missing_docs)]
use embedded_hal::digital::v2::OutputPin;
use embedded_hal::digital::v2::PinState::{self, High, Low};
#[derive(Copy, Clone, Debug)]
enum State {
State0,
State1,
State2,
State3,
State4,
State5,
State6,
State7,
State8,
}
fn get_pin_states(s: State) -> [PinState; 4] {
match s {
State::State0 => [Low, Low, Low, Low],
State::State1 => [Low, Low, Low, High],
State::State2 => [Low, Low, High, High],
State::State3 => [Low, Low, High, Low],
State::State4 => [Low, High, High, Low],
State::State5 => [Low, High, Low, Low],
State::State6 => [High, High, Low, Low],
State::State7 => [High, Low, Low, Low],
State::State8 => [High, Low, Low, High],
}
}
fn get_next_state(s: State) -> State {
match s {
State::State0 => State::State1,
State::State1 => State::State2,
State::State2 => State::State3,
State::State3 => State::State4,
State::State4 => State::State5,
State::State5 => State::State6,
State::State6 => State::State7,
State::State7 => State::State8,
State::State8 => State::State1,
}
}
fn get_prev_state(s: State) -> State {
match s {
State::State0 => State::State8,
State::State1 => State::State8,
State::State2 => State::State1,
State::State3 => State::State2,
State::State4 => State::State3,
State::State5 => State::State4,
State::State6 => State::State5,
State::State7 => State::State6,
State::State8 => State::State7,
}
}
pub struct ULN2003<P1: OutputPin, P2: OutputPin, P3: OutputPin, P4: OutputPin> {
in1: P1,
in2: P2,
in3: P3,
in4: P4,
state: State,
dir: Direction,
}
impl<P1: OutputPin, P2: OutputPin, P3: OutputPin, P4: OutputPin> ULN2003<P1, P2, P3, P4> {
pub fn new(in1: P1, in2: P2, in3: P3, in4: P4) -> Self {
Self {
in1,
in2,
in3,
in4,
state: State::State0,
dir: Direction::Normal,
}
}
}
#[derive(Debug)]
pub struct StepError;
impl<P1: OutputPin, P2: OutputPin, P3: OutputPin, P4: OutputPin> StepperMotor
for ULN2003<P1, P2, P3, P4>
{
fn step(&mut self) -> Result<(), StepError> {
let states = get_pin_states(self.state);
set_state(&mut self.in1, states[0])?;
set_state(&mut self.in2, states[1])?;
set_state(&mut self.in3, states[2])?;
set_state(&mut self.in4, states[3])?;
match self.dir {
Direction::Normal => self.state = get_next_state(self.state),
Direction::Reverse => self.state = get_prev_state(self.state),
}
Ok(())
}
fn set_direction(&mut self, dir: Direction) {
self.dir = dir;
}
}
fn set_state<P: OutputPin>(pin: &mut P, state: PinState) -> Result<(), StepError> {
match pin.set_state(state) {
Ok(_) => Ok(()),
Err(_) => Err(StepError),
}
}
pub trait StepperMotor {
fn step(&mut self) -> Result<(), StepError>;
fn set_direction(&mut self, dir: Direction);
}
pub enum Direction {
Normal,
Reverse,
}