use num_enum::{IntoPrimitive, TryFromPrimitive};
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, IntoPrimitive, TryFromPrimitive)]
#[repr(u8)]
pub enum Mode {
#[default]
Stopped = 0,
Fault = 1,
Enabling = 2,
Calibrating = 3,
CalibrationComplete = 4,
Pwm = 5,
Voltage = 6,
VoltageFoc = 7,
VoltageDq = 8,
Current = 9,
Position = 10,
Timeout = 11,
ZeroVelocity = 12,
StayWithin = 13,
MeasureInd = 14,
Brake = 15,
}
impl core::fmt::Display for Mode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Mode::Stopped => write!(f, "stopped"),
Mode::Fault => write!(f, "fault"),
Mode::Enabling => write!(f, "enabling"),
Mode::Calibrating => write!(f, "calibrating"),
Mode::CalibrationComplete => write!(f, "calibration complete"),
Mode::Pwm => write!(f, "pwm"),
Mode::Voltage => write!(f, "voltage"),
Mode::VoltageFoc => write!(f, "voltage foc"),
Mode::VoltageDq => write!(f, "voltage dq"),
Mode::Current => write!(f, "current"),
Mode::Position => write!(f, "position"),
Mode::Timeout => write!(f, "timeout"),
Mode::ZeroVelocity => write!(f, "zero velocity"),
Mode::StayWithin => write!(f, "stay within"),
Mode::MeasureInd => write!(f, "measure inductance"),
Mode::Brake => write!(f, "brake"),
}
}
}
impl Mode {
pub fn is_error(&self) -> bool {
matches!(self, Mode::Fault | Mode::Timeout)
}
pub fn is_active(&self) -> bool {
matches!(
self,
Mode::Position
| Mode::Current
| Mode::VoltageFoc
| Mode::ZeroVelocity
| Mode::StayWithin
| Mode::Brake
)
}
}
impl From<Mode> for i8 {
fn from(mode: Mode) -> i8 {
let v: u8 = mode.into();
v as i8
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, IntoPrimitive, TryFromPrimitive)]
#[repr(u8)]
pub enum HomeState {
#[default]
Relative = 0,
Rotor = 1,
Output = 2,
}
impl core::fmt::Display for HomeState {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
HomeState::Relative => write!(f, "relative"),
HomeState::Rotor => write!(f, "rotor"),
HomeState::Output => write!(f, "output"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mode_try_from() {
assert_eq!(Mode::try_from(0), Ok(Mode::Stopped));
assert_eq!(Mode::try_from(10), Ok(Mode::Position));
assert!(Mode::try_from(255).is_err());
}
#[test]
fn test_mode_into() {
let v: u8 = Mode::Position.into();
assert_eq!(v, 10);
}
#[test]
fn test_mode_is_error() {
assert!(Mode::Fault.is_error());
assert!(Mode::Timeout.is_error());
assert!(!Mode::Position.is_error());
assert!(!Mode::Stopped.is_error());
}
#[test]
fn test_mode_is_active() {
assert!(Mode::Position.is_active());
assert!(Mode::Current.is_active());
assert!(Mode::Brake.is_active());
assert!(!Mode::Stopped.is_active());
assert!(!Mode::Fault.is_active());
}
#[test]
fn test_home_state_try_from() {
assert_eq!(HomeState::try_from(0), Ok(HomeState::Relative));
assert_eq!(HomeState::try_from(2), Ok(HomeState::Output));
assert!(HomeState::try_from(3).is_err());
}
#[test]
fn test_home_state_into() {
let v: u8 = HomeState::Output.into();
assert_eq!(v, 2);
}
}