#![cfg(feature = "battery")]
#![allow(unused)]
use core::ops::{Index, IndexMut};
#[cfg(feature = "serde")]
use {
postcard::experimental::max_size::MaxSize,
sequential_storage::map::PostcardValue,
serde::{Deserialize, Serialize},
};
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub enum BatteryState {
#[default]
Ok,
Warning,
Critical,
NotPresent,
Init,
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, MaxSize))]
pub struct BatteryProfile {
pub max_cell_voltage_v_x100: u16,
pub min_cell_voltage_v_x100: u16,
pub warning_cell_voltage_v_x100: u16,
pub full_cell_voltage_v_x100: u16,
pub battery_capacity_mah: u16,
pub force_battery_cell_count: u8,
pub consumption_warning_percentage: u8,
pub profile_name: [u8; Self::MAX_NAME_LENGTH],
}
#[cfg(feature = "serde")]
impl PostcardValue<'_> for BatteryProfile {}
impl Default for BatteryProfile {
fn default() -> Self {
Self::new()
}
}
impl BatteryProfile {
pub const COUNT: usize = 3;
pub const MAX_NAME_LENGTH: usize = 8;
pub const CELL_VOLTAGE_RANGE_MIN: u16 = 100;
pub const CELL_VOLTAGE_RANGE_MAX: u16 = 500;
pub const CELL_VOLTAGE_DEFAULT_MIN: u16 = 330;
pub const fn new() -> Self {
Self {
max_cell_voltage_v_x100: Self::CELL_VOLTAGE_RANGE_MAX,
min_cell_voltage_v_x100: Self::CELL_VOLTAGE_RANGE_MIN,
warning_cell_voltage_v_x100: 350,
full_cell_voltage_v_x100: 410,
battery_capacity_mah: 0,
force_battery_cell_count: 0,
consumption_warning_percentage: 10,
profile_name: [0u8; Self::MAX_NAME_LENGTH],
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, MaxSize))]
pub struct BatteryProfiles {
pub profiles: [BatteryProfile; Self::COUNT],
}
#[cfg(feature = "serde")]
impl PostcardValue<'_> for BatteryProfiles {}
impl Default for BatteryProfiles {
fn default() -> Self {
Self::new()
}
}
impl BatteryProfiles {
pub const MAX: u8 = 2;
pub const COUNT: usize = 3;
pub const fn new() -> Self {
Self { profiles: [BatteryProfile::new(); Self::COUNT] }
}
}
impl Index<usize> for BatteryProfiles {
type Output = BatteryProfile;
#[inline]
fn index(&self, index: usize) -> &BatteryProfile {
&self.profiles[index]
}
}
impl IndexMut<usize> for BatteryProfiles {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut BatteryProfile {
&mut self.profiles[index]
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, MaxSize))]
pub struct BatteryConfig {
pub vbat_not_present_cell_voltage: u16, pub lvc_percentage: u8,
pub voltage_meter_source: u8, pub current_meter_source: u8,
pub use_vbat_alerts: u8, pub use_consumption_alerts: u8, pub vbat_hysteresis: u8,
pub vbat_display_lpf_period: u8, pub vbat_sag_lpf_period: u8, pub ibat_lpf_period: u8,
pub vbat_duration_for_warning: u8, pub vbat_duration_for_critical: u8, }
#[cfg(feature = "serde")]
impl PostcardValue<'_> for BatteryConfig {}
impl Default for BatteryConfig {
fn default() -> Self {
Self::new()
}
}
impl BatteryConfig {
pub const fn new() -> Self {
Self {
vbat_not_present_cell_voltage: 300,
lvc_percentage: 100, voltage_meter_source: VoltageMeterReading::SOURCE_NONE,
current_meter_source: CurrentMeterReading::SOURCE_NONE,
use_vbat_alerts: 1,
use_consumption_alerts: 0,
vbat_hysteresis: 1,
vbat_display_lpf_period: 30,
vbat_sag_lpf_period: 2,
ibat_lpf_period: 10,
vbat_duration_for_warning: 0,
vbat_duration_for_critical: 0,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct VoltageMeterReading {
pub display_filtered_x100: u16,
pub voltage_stable_previous_filtered_x100: u16,
pub voltage_stable_last_update_ms: u32,
pub voltage_stable_bits: u16,
pub unfiltered_x100: u16,
pub sag_filtered_x100: u16,
pub low_voltage_cutoff: bool,
}
impl Default for VoltageMeterReading {
fn default() -> Self {
Self::new()
}
}
impl VoltageMeterReading {
pub const SOURCE_NONE: u8 = 0;
pub const SOURCE_ADC: u8 = 1;
pub const SOURCE_ESC: u8 = 2;
pub const SOURCE_MAX: u8 = 2;
pub const SOURCE_COUNT: usize = 3;
pub const SOURCE_NAMES: [&str; Self::SOURCE_COUNT] = ["NONE", "ADC", "ESC"];
pub const fn new() -> Self {
Self {
display_filtered_x100: 0,
voltage_stable_previous_filtered_x100: 0,
voltage_stable_last_update_ms: 0,
voltage_stable_bits: 0,
unfiltered_x100: 0,
sag_filtered_x100: 0,
low_voltage_cutoff: false,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct CurrentMeterReading {
pub amperage_x100: i32,
pub amperage_latest_x100: i32,
pub mah_drawn: i32,
pub mah_drawn_offset: i32,
}
impl Default for CurrentMeterReading {
fn default() -> Self {
Self::new()
}
}
impl CurrentMeterReading {
pub const SOURCE_NONE: u8 = 0;
pub const SOURCE_ADC: u8 = 1;
pub const SOURCE_VIRTUAL: u8 = 2;
pub const SOURCE_ESC: u8 = 3;
pub const SOURCE_MSP: u8 = 4;
pub const SOURCE_MAX: u8 = 4;
pub const SOURCE_COUNT: usize = 5;
pub const SOURCE_NAMES: [&str; Self::SOURCE_COUNT] = ["NONE", "ADC", "VIRTUAL", "ESC", "MSP"];
pub const fn new() -> Self {
Self { amperage_x100: 0, amperage_latest_x100: 0, mah_drawn: 0, mah_drawn_offset: 0 }
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct BatteryMessage {
pub voltage: VoltageMeterReading,
pub current: CurrentMeterReading,
pub state: BatteryState,
}
impl Default for BatteryMessage {
fn default() -> Self {
Self::new()
}
}
impl BatteryMessage {
pub fn new() -> Self {
Self {
voltage: VoltageMeterReading::new(),
current: CurrentMeterReading::new(),
state: BatteryState::default(),
}
}
}
#[cfg(test)]
mod test_traits {
use super::*;
fn _is_normal<T: Sized + Send + Sync + Unpin>() {}
fn is_full<T: Sized + Send + Sync + Unpin + Copy + Clone + Default + PartialEq>() {}
#[cfg(feature = "serde")]
fn is_config<T: Serialize + MaxSize + for<'a> Deserialize<'a> + for<'a> PostcardValue<'a>>() {}
#[test]
fn normal_types() {
is_full::<BatteryState>();
is_full::<BatteryConfig>();
is_full::<BatteryProfile>();
is_full::<BatteryProfiles>();
is_full::<BatteryMessage>();
#[cfg(feature = "serde")]
is_config::<BatteryConfig>();
#[cfg(feature = "serde")]
is_config::<BatteryProfile>();
#[cfg(feature = "serde")]
is_config::<BatteryProfiles>();
}
}
mod tests {
use super::*;
#[test]
fn test_new() {
let config = BatteryConfig::new();
assert_eq!(300, config.vbat_not_present_cell_voltage);
}
}