#[derive(Debug, Clone, Copy)]
pub struct Scaling {
pub(crate) int8: f32,
pub(crate) int16: f32,
pub(crate) int32: f32,
}
pub const POSITION: Scaling = Scaling {
int8: 0.01,
int16: 0.0001,
int32: 0.00001,
};
pub const VELOCITY: Scaling = Scaling {
int8: 0.1,
int16: 0.00025,
int32: 0.00001,
};
pub const ACCELERATION: Scaling = Scaling {
int8: 0.05,
int16: 0.001,
int32: 0.00001,
};
pub const TORQUE: Scaling = Scaling {
int8: 0.5,
int16: 0.01,
int32: 0.001,
};
pub const PWM: Scaling = Scaling {
int8: 1.0 / 127.0,
int16: 1.0 / 32767.0,
int32: 1.0 / 2147483647.0,
};
pub const VOLTAGE: Scaling = Scaling {
int8: 0.5,
int16: 0.1,
int32: 0.001,
};
pub const TEMPERATURE: Scaling = Scaling {
int8: 1.0,
int16: 0.1,
int32: 0.001,
};
pub const TIME: Scaling = Scaling {
int8: 0.01,
int16: 0.001,
int32: 0.000001,
};
pub const CURRENT: Scaling = Scaling {
int8: 1.0,
int16: 0.1,
int32: 0.001,
};
pub const POWER: Scaling = Scaling {
int8: 10.0,
int16: 0.05,
int32: 0.0001,
};
pub const INT: Scaling = Scaling {
int8: 1.0,
int16: 1.0,
int32: 1.0,
};
#[inline]
pub fn saturate_i8(value: f32, scale: f32) -> i8 {
if !value.is_finite() {
return i8::MIN;
}
let scaled = value / scale;
if scaled < -127.0 {
-127
} else if scaled > 127.0 {
127
} else {
scaled as i8
}
}
#[inline]
pub fn saturate_i16(value: f32, scale: f32) -> i16 {
if !value.is_finite() {
return i16::MIN;
}
let scaled = value / scale;
if scaled < -32767.0 {
-32767
} else if scaled > 32767.0 {
32767
} else {
scaled as i16
}
}
#[inline]
pub fn saturate_i32(value: f32, scale: f32) -> i32 {
if !value.is_finite() {
return i32::MIN;
}
let scaled = value / scale;
let max = i32::MAX as f32;
if scaled < -max {
-(i32::MAX)
} else if scaled > max {
i32::MAX
} else {
scaled as i32
}
}
#[inline]
pub fn nanify_i8(value: i8) -> f32 {
if value == i8::MIN {
f32::NAN
} else {
value as f32
}
}
#[inline]
pub fn nanify_i16(value: i16) -> f32 {
if value == i16::MIN {
f32::NAN
} else {
value as f32
}
}
#[inline]
pub fn nanify_i32(value: i32) -> f32 {
if value == i32::MIN {
f32::NAN
} else {
value as f32
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_saturate_i8() {
assert_eq!(saturate_i8(0.5, 0.01), 50);
assert_eq!(saturate_i8(2.0, 0.01), 127); assert_eq!(saturate_i8(-2.0, 0.01), -127); assert_eq!(saturate_i8(f32::NAN, 0.01), i8::MIN); assert_eq!(saturate_i8(f32::INFINITY, 0.01), i8::MIN);
}
#[test]
fn test_saturate_i16() {
assert_eq!(saturate_i16(0.5, 0.0001), 5000);
assert_eq!(saturate_i16(10.0, 0.0001), 32767); }
#[test]
fn test_saturate_i32() {
assert_eq!(saturate_i32(500.0, 0.01), 50000);
assert_eq!(saturate_i32(f32::NAN, 0.01), i32::MIN); assert_eq!(saturate_i32(f32::INFINITY, 0.01), i32::MIN);
}
#[test]
fn test_nanify() {
assert!(nanify_i8(i8::MIN).is_nan());
assert_eq!(nanify_i8(0), 0.0);
assert_eq!(nanify_i8(100), 100.0);
assert!(nanify_i16(i16::MIN).is_nan());
assert_eq!(nanify_i16(1000), 1000.0);
assert!(nanify_i32(i32::MIN).is_nan());
assert_eq!(nanify_i32(100000), 100000.0);
}
}