use num_enum::{IntoPrimitive, TryFromPrimitive};
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
#[repr(u16)]
pub enum Register {
Mode = 0x000,
Position = 0x001,
Velocity = 0x002,
Torque = 0x003,
QCurrent = 0x004,
DCurrent = 0x005,
AbsPosition = 0x006,
Power = 0x007,
MotorTemperature = 0x00a,
TrajectoryComplete = 0x00b,
HomeState = 0x00c,
Voltage = 0x00d,
Temperature = 0x00e,
Fault = 0x00f,
PwmPhaseA = 0x010,
PwmPhaseB = 0x011,
PwmPhaseC = 0x012,
VoltagePhaseA = 0x014,
VoltagePhaseB = 0x015,
VoltagePhaseC = 0x016,
VFocTheta = 0x018,
VFocVoltage = 0x019,
VoltageDqD = 0x01a,
VoltageDqQ = 0x01b,
CommandQCurrent = 0x01c,
CommandDCurrent = 0x01d,
VFocThetaRate = 0x01e,
CommandPosition = 0x020,
CommandVelocity = 0x021,
CommandFeedforwardTorque = 0x022,
CommandKpScale = 0x023,
CommandKdScale = 0x024,
CommandPositionMaxTorque = 0x025,
CommandStopPosition = 0x026,
CommandTimeout = 0x027,
CommandVelocityLimit = 0x028,
CommandAccelLimit = 0x029,
CommandFixedVoltageOverride = 0x02a,
CommandIlimitScale = 0x02b,
CommandFixedCurrentOverride = 0x02c,
CommandIgnorePositionBounds = 0x02d,
PositionKp = 0x030,
PositionKi = 0x031,
PositionKd = 0x032,
PositionFeedforward = 0x033,
PositionCommand = 0x034,
ControlPosition = 0x038,
ControlVelocity = 0x039,
ControlTorque = 0x03a,
ControlPositionError = 0x03b,
ControlVelocityError = 0x03c,
ControlTorqueError = 0x03d,
CommandStayWithinLowerBound = 0x040,
CommandStayWithinUpperBound = 0x041,
CommandStayWithinFeedforwardTorque = 0x042,
CommandStayWithinKpScale = 0x043,
CommandStayWithinKdScale = 0x044,
CommandStayWithinPositionMaxTorque = 0x045,
CommandStayWithinTimeout = 0x046,
CommandStayWithinIlimitScale = 0x047,
CommandStayWithinIgnorePositionBounds = 0x048,
Encoder0Position = 0x050,
Encoder0Velocity = 0x051,
Encoder1Position = 0x052,
Encoder1Velocity = 0x053,
Encoder2Position = 0x054,
Encoder2Velocity = 0x055,
EncoderValidity = 0x058,
Aux1GpioCommand = 0x05c,
Aux2GpioCommand = 0x05d,
Aux1GpioStatus = 0x05e,
Aux2GpioStatus = 0x05f,
Aux1AnalogIn1 = 0x060,
Aux1AnalogIn2 = 0x061,
Aux1AnalogIn3 = 0x062,
Aux1AnalogIn4 = 0x063,
Aux1AnalogIn5 = 0x064,
Aux2AnalogIn1 = 0x068,
Aux2AnalogIn2 = 0x069,
Aux2AnalogIn3 = 0x06a,
Aux2AnalogIn4 = 0x06b,
Aux2AnalogIn5 = 0x06c,
MillisecondCounter = 0x070,
ClockTrim = 0x071,
Aux1PwmInputPeriod = 0x072,
Aux1PwmInputDutyCycle = 0x073,
Aux2PwmInputPeriod = 0x074,
Aux2PwmInputDutyCycle = 0x075,
Aux1Pwm1 = 0x076,
Aux1Pwm2 = 0x077,
Aux1Pwm3 = 0x078,
Aux1Pwm4 = 0x079,
Aux1Pwm5 = 0x07a,
Aux2Pwm1 = 0x07b,
Aux2Pwm2 = 0x07c,
Aux2Pwm3 = 0x07d,
Aux2Pwm4 = 0x07e,
Aux2Pwm5 = 0x07f,
ModelNumber = 0x100,
FirmwareVersion = 0x101,
RegisterMapVersion = 0x102,
MultiplexId = 0x110,
SerialNumber1 = 0x120,
SerialNumber2 = 0x121,
SerialNumber3 = 0x122,
SetOutputNearest = 0x130,
SetOutputExact = 0x131,
RequireReindex = 0x132,
RecapturePositionVelocity = 0x133,
DriverFault1 = 0x140,
DriverFault2 = 0x141,
Uuid1 = 0x150,
Uuid2 = 0x151,
Uuid3 = 0x152,
Uuid4 = 0x153,
UuidMask1 = 0x154,
UuidMask2 = 0x155,
UuidMask3 = 0x156,
UuidMask4 = 0x157,
UuidMaskCapable = 0x158,
}
impl core::fmt::Display for Register {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(self, f)
}
}
impl Register {
#[inline]
pub const fn address(self) -> u16 {
self as u16
}
pub fn from_address(addr: u16) -> Option<Register> {
Self::try_from(addr).ok()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_register_addresses() {
assert_eq!(Register::Mode.address(), 0x000);
assert_eq!(Register::Position.address(), 0x001);
assert_eq!(Register::Fault.address(), 0x00f);
assert_eq!(Register::CommandPosition.address(), 0x020);
}
#[test]
fn test_register_from_address() {
assert_eq!(Register::from_address(0x000), Some(Register::Mode));
assert_eq!(Register::from_address(0x001), Some(Register::Position));
assert_eq!(Register::from_address(0xfff), None);
}
}