#![cfg(feature = "osd")]
#[cfg(feature = "serde")]
use {
postcard::experimental::max_size::MaxSize,
sequential_storage::map::PostcardValue,
serde::{Deserialize, Serialize},
};
use crate::{
display::{DisplayPortBackground, DisplayPortDeviceType},
osd::{Osd, elements::OsdElements, fixed_buf::FixedBuf},
};
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, MaxSize))]
pub struct OsdConfig {
pub profile: [[u8; Osd::PROFILE_COUNT]; Osd::PROFILE_NAME_LENGTH + 2], pub rc_channels: [i8; Osd::RC_CHANNELS_COUNT], pub timers: [u16; Osd::TIMER_COUNT],
pub enabled_warnings_flags: u32,
pub enabled_stats_flags: u32,
pub framerate_hz: u16,
pub cap_alarm: u16,
pub alt_alarm: u16,
pub link_quality_alarm: u16,
pub rssi_dbm_alarm: i16,
pub rsnr_alarm: i16,
pub distance_alarm: u16,
pub esc_rpm_alarm: i16,
pub esc_current_alarm: i16,
pub esc_temperature_alarm: u8,
pub core_temperature_alarm: u8,
pub rssi_alarm: u8,
pub units: u8,
pub aux_scale: u16,
pub aux_channel: u8,
pub aux_symbol: u8,
pub logo_on_arming: u8,
pub logo_on_arming_duration: u8, pub arming_logo_attribute: u8,
pub ah_max_pitch: u8,
pub ah_max_roll: u8,
pub ah_invert: u8,
pub osd_profile_index: u8,
pub overlay_radio_mode: u8,
pub gps_sats_show_pdop: u8,
pub camera_frame_width: u8,
pub camera_frame_height: u8,
pub cms_background_type: u8, pub stats_show_cell_value: u8,
pub osd_craft_name_messages: u8, pub display_port_device_type: u8,
pub canvas_column_count: u8,
pub canvas_row_count: u8,
pub osd_use_quick_menu: u8,
pub osd_show_spec_prearm: u8,
}
#[cfg(feature = "serde")]
impl PostcardValue<'_> for OsdConfig {}
impl Default for OsdConfig {
fn default() -> Self {
Self::new()
}
}
impl OsdConfig {
pub const fn new() -> Self {
Self {
profile: [[0u8; Osd::PROFILE_COUNT]; Osd::PROFILE_NAME_LENGTH + 2], rc_channels: [0i8; Osd::RC_CHANNELS_COUNT],
timers: [0u16; Osd::TIMER_COUNT],
enabled_warnings_flags: 0,
enabled_stats_flags: 0,
framerate_hz: Osd::FRAMERATE_DEFAULT_HZ,
cap_alarm: 2200,
alt_alarm: 100, link_quality_alarm: 80,
rssi_dbm_alarm: -60,
rsnr_alarm: 4,
distance_alarm: 0,
esc_rpm_alarm: Osd::ESC_RPM_ALARM_OFF,
esc_current_alarm: Osd::ESC_CURRENT_ALARM_OFF,
esc_temperature_alarm: Osd::ESC_TEMPERATURE_ALARM_OFF,
core_temperature_alarm: 70, rssi_alarm: 20,
units: Osd::UNITS_METRIC,
aux_scale: 200,
aux_channel: 1,
aux_symbol: b'A',
logo_on_arming: Osd::LOGO_ARMING_OFF,
logo_on_arming_duration: 5, arming_logo_attribute: 0,
ah_max_pitch: 20, ah_max_roll: 40, ah_invert: 0,
osd_profile_index: 0,
overlay_radio_mode: 2,
gps_sats_show_pdop: 0,
camera_frame_width: 24,
camera_frame_height: 11,
cms_background_type: DisplayPortBackground::Transparent as u8,
stats_show_cell_value: 0,
osd_craft_name_messages: 0, display_port_device_type: DisplayPortDeviceType::Auto as u8,
canvas_column_count: Osd::SD_COLS,
canvas_row_count: Osd::SD_ROWS,
osd_use_quick_menu: 0,
osd_show_spec_prearm: 0,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, MaxSize))]
pub struct OsdStatsConfig {
pub total_flights: u32,
pub total_time_s: u32,
pub total_distance_m: u32,
pub mah_used: u32,
pub min_armed_time_s: i8,
pub save_move_limit: u8, }
#[cfg(feature = "serde")]
impl PostcardValue<'_> for OsdStatsConfig {}
impl Default for OsdStatsConfig {
fn default() -> Self {
Self::new()
}
}
impl OsdStatsConfig {
pub const fn new() -> Self {
Self {
total_flights: 0,
total_time_s: 0,
total_distance_m: 0,
mah_used: 0,
min_armed_time_s: 0,
save_move_limit: 0, }
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, MaxSize))]
pub struct OsdElementsConfig {
pub positions: [u16; OsdElements::COUNT],
}
#[cfg(feature = "serde")]
impl PostcardValue<'_> for OsdElementsConfig {}
impl Default for OsdElementsConfig {
fn default() -> Self {
Self::new()
}
}
impl OsdElementsConfig {
pub const fn new() -> Self {
Self { positions: [0u16; OsdElements::COUNT] }
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, MaxSize))]
pub struct PilotConfig {
pub craft_name: FixedBuf<{ PilotConfig::MAX_NAME_LENGTH }>,
pub pilot_name: FixedBuf<{ PilotConfig::MAX_NAME_LENGTH }>,
pub message: [FixedBuf<{ PilotConfig::MAX_NAME_LENGTH }>; PilotConfig::CUSTOM_MESSAGE_COUNT],
}
#[cfg(feature = "serde")]
impl PostcardValue<'_> for PilotConfig {}
impl Default for PilotConfig {
fn default() -> Self {
Self::new()
}
}
impl PilotConfig {
pub const MAX_NAME_LENGTH: usize = 16;
pub const CUSTOM_MESSAGE_COUNT: usize = 5;
pub const fn new() -> Self {
Self {
craft_name: FixedBuf::new(),
pilot_name: FixedBuf::new(),
message: [FixedBuf::new(); Self::CUSTOM_MESSAGE_COUNT],
}
}
}
#[cfg(test)]
mod tests {
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::<OsdConfig>();
#[cfg(feature = "serde")]
is_config::<OsdConfig>();
is_full::<OsdStatsConfig>();
#[cfg(feature = "serde")]
is_config::<OsdStatsConfig>();
is_full::<OsdElementsConfig>();
#[cfg(feature = "serde")]
is_config::<OsdElementsConfig>();
is_full::<PilotConfig>();
#[cfg(feature = "serde")]
is_config::<PilotConfig>();
}
#[test]
fn test_new() {
let config = OsdConfig::new();
assert_eq!(2200, config.cap_alarm);
}
}