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
//! DQ542MA Driver
//!
//! Platform-agnostic driver API for the DQ542MA stepper motor driver. Can be
//! used on any platform for which implementations of the required
//! [embedded-hal] traits are available.
//!
//! For the most part, users are not expected to use this API directly. Please
//! check out [`Stepper`](crate::Stepper) instead.
//!
//! [embedded-hal]: https://crates.io/crates/embedded-hal

use core::convert::Infallible;

use embedded_hal::digital::blocking::OutputPin;
use fugit::NanosDurationU32 as Nanoseconds;

use crate::traits::{
    EnableDirectionControl, EnableStepControl, SetDirection, Step as StepTrait,
};

/// The DQ542MA driver API
///
/// Users are not expected to use this API directly, except to create an
/// instance using [`DQ542MA::new`]. Please check out
/// [`Stepper`](crate::Stepper) instead.
pub struct DQ542MA<Enable, Step, Dir> {
    enable: Enable,
    step: Step,
    dir: Dir,
}

impl DQ542MA<(), (), ()> {
    /// Create a new instance of `DQ542MA`
    pub fn new() -> Self {
        Self {
            enable: (),
            step: (),
            dir: (),
        }
    }
}

impl<Step, Dir, OutputPinError> EnableDirectionControl<Dir>
    for DQ542MA<(), Step, ()>
where
    Dir: OutputPin<Error = OutputPinError>,
{
    type WithDirectionControl = DQ542MA<(), Step, Dir>;

    fn enable_direction_control(self, dir: Dir) -> Self::WithDirectionControl {
        DQ542MA {
            enable: self.enable,
            step: self.step,
            dir,
        }
    }
}

impl<Step, Dir, OutputPinError> SetDirection for DQ542MA<(), Step, Dir>
where
    Dir: OutputPin<Error = OutputPinError>,
{
    // https://wiki.linuxcnc.org/cgi-bin/wiki.pl?Stepper_Drive_Timing
    const SETUP_TIME: Nanoseconds = Nanoseconds::from_ticks(500);

    type Dir = Dir;
    type Error = Infallible;

    fn dir(&mut self) -> Result<&mut Self::Dir, Self::Error> {
        Ok(&mut self.dir)
    }
}

impl<Step, Dir, OutputPinError> EnableStepControl<Step> for DQ542MA<(), (), Dir>
where
    Step: OutputPin<Error = OutputPinError>,
{
    type WithStepControl = DQ542MA<(), Step, Dir>;

    fn enable_step_control(self, step: Step) -> Self::WithStepControl {
        DQ542MA {
            enable: self.enable,
            step,
            dir: self.dir,
        }
    }
}

impl<Step, Dir, OutputPinError> StepTrait for DQ542MA<(), Step, Dir>
where
    Step: OutputPin<Error = OutputPinError>,
{
    // https://wiki.linuxcnc.org/cgi-bin/wiki.pl?Stepper_Drive_Timing
    const PULSE_LENGTH: Nanoseconds = Nanoseconds::from_ticks(5050);

    type Step = Step;
    type Error = Infallible;

    fn step(&mut self) -> Result<&mut Self::Step, Self::Error> {
        Ok(&mut self.step)
    }
}