#[cfg(feature = "defmt")]
use defmt::Format;
pub const MS4525DO_ADDR: u8 = 0x28;
pub const DATA_SIZE: usize = 4;
pub const PSI_TO_PA: f32 = 6894.76;
pub const READ_MR: u8 = 0x00;
pub const BRIDGE_MASK: u8 = 0b0011_1111;
pub const TEMPERATURE_MASK: u8 = 0b1110_0000;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(Format))]
pub enum Status {
NormalOperation = 0b00,
Reserved = 0b01,
StaleData = 0b10,
FaultDetected = 0b11,
}
impl From<u8> for Status {
fn from(value: u8) -> Self {
match value & 0b11 {
0b00 => Status::NormalOperation,
0b01 => Status::Reserved,
0b10 => Status::StaleData,
0b11 => Status::FaultDetected,
_ => unreachable!(),
}
}
}
#[inline]
pub fn extract_bridge_data(data: &[u8]) -> u16 {
let bridge_msb = data[0] & BRIDGE_MASK;
let bridge_lsb = data[1];
((bridge_msb as u16) << 8) | (bridge_lsb as u16)
}
#[inline]
pub fn read_temperature(data: &[u8]) -> u16 {
(((data[2] as u16) << 8) | ((data[3] & TEMPERATURE_MASK) as u16)) >> 5
}
pub fn calculate_pressure_differential_pa(bridge_data: u16) -> f32 {
let diff_press_psi = -((bridge_data as f32 - 0.1 * 16383.0) * 2.0 / (0.8 * 16383.0) - 1.0);
diff_press_psi * PSI_TO_PA
}
pub fn calculate_temperature_deg_c(temperature_counts: u16) -> f32 {
(200.0 * temperature_counts as f32 / 2047.0) - 50.0
}
pub fn calculate_airspeed(pressure_pa: f32, temp_c: f32) -> f32 {
let temp_k = temp_c + 273.15;
let air_density = 101325.0 / (287.05 * temp_k);
libm::sqrtf(2.0 * pressure_pa.abs() / air_density)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_status_conversion() {
assert_eq!(Status::from(0b00), Status::NormalOperation);
assert_eq!(Status::from(0b01), Status::Reserved);
assert_eq!(Status::from(0b10), Status::StaleData);
assert_eq!(Status::from(0b11), Status::FaultDetected);
}
#[test]
fn test_extract_bridge_data() {
let data = [0x3F, 0xFF, 0x80, 0x00];
let bridge_data = extract_bridge_data(&data);
assert_eq!(bridge_data, 0x3FFF, "Incorrect bridge data extraction");
}
#[test]
fn test_read_temperature() {
let data = [0x00, 0x00, 0x80, 0xE0];
let temp = read_temperature(&data);
assert_eq!(temp, 0x0407, "Incorrect temperature extraction");
}
#[test]
fn test_calculate_pressure_differential_pa() {
let bridge_data = 8192; let pressure_pa = calculate_pressure_differential_pa(bridge_data);
assert!(
(pressure_pa - 0.0).abs() < 1.0,
"Pressure calculation incorrect: {}",
pressure_pa
);
}
#[test]
fn test_calculate_temperature_deg_c() {
let test_cases = [(0x0000, -50.0), (0x0266, 10.0), (0x03FF, 50.0)];
for (digital_counts, expected_temp_c) in test_cases {
let temp_c = calculate_temperature_deg_c(digital_counts);
assert!(
(temp_c - expected_temp_c).abs() < 0.05,
"Temperature calculation incorrect: {} (expected {})",
temp_c,
expected_temp_c
);
}
}
#[test]
fn test_calculate_airspeed() {
let pressure = 50.0; let temp = 20.0; let airspeed = calculate_airspeed(pressure, temp);
assert!(
airspeed > 8.0 && airspeed < 10.0,
"Airspeed calculation seems incorrect: {}",
airspeed
);
}
}