use embassy_sync::{
blocking_mutex::raw::CriticalSectionRawMutex,
mutex::Mutex,
pubsub::{PubSubChannel, Publisher, Subscriber},
};
use imu_sensors::ImuDeviceConfig;
use motor_mixers::{MixerConfig, MotorConfig, MotorDeviceConfig};
use radio_controllers::{FailsafeConfig, RatesConfig, RcControlsConfig, RcModes, RxConfig};
use crate::{
autopilot::{AutopilotConfig, PositionHoldConfig},
battery_sensors::{CurrentSensorAdcConfig, CurrentSensorVirtualConfig},
config::{ImuConfig, SensorFlags, SystemConfig, profiles::SchemaVersion},
flight::{
AntiGravityConfig, ArmingConfig, CrashFlipConfig, CrashRecoveryConfig, DMaxConfig, FeatureFlags,
FlightControllerFiltersConfig, GyroConfig, ImuFilterBankConfig, PidConfig, TpaConfig, YawSpinRecoveryConfig,
},
};
#[cfg(feature = "barometer")]
use crate::barometer_sensors::BarometerConfig;
#[cfg(feature = "battery")]
use crate::battery_sensors::{BatteryConfig, BatteryProfiles};
#[cfg(feature = "blackbox")]
use blackbox_logger::BlackboxConfig;
#[cfg(feature = "gps")]
use crate::gps::{GpsConfig, GpsRescueConfig};
#[cfg(feature = "magnetometer")]
use crate::magnetometer_sensors::MagnetometerConfig;
#[cfg(feature = "optical_flow")]
use crate::optical_flow_sensors::OpticalFlowConfig;
#[cfg(feature = "osd")]
use crate::osd::{OsdConfig, OsdElementsConfig, OsdStatsConfig, PilotConfig};
#[cfg(feature = "rangefinder")]
use crate::rangefinder_sensors::RangefinderConfig;
#[cfg(feature = "rpm_filters")]
use motor_mixers::RpmNotchFilterBankConfig;
#[cfg(feature = "vtx")]
use crate::vtx::VtxConfig;
pub static GLOBAL_CONFIG: Mutex<CriticalSectionRawMutex, GlobalConfig> = Mutex::new(GlobalConfig::new());
const MAX_CONFIG_SUBSCRIBER_COUNT: usize = 8;
const CONFIG_PUBLISHER_COUNT: usize = 2;
const CONFIG_CAPACITY: usize = 8;
static CONFIG_PUB_SUB_CHANNEL: PubSubChannel<
CriticalSectionRawMutex,
ConfigItem,
CONFIG_CAPACITY,
MAX_CONFIG_SUBSCRIBER_COUNT,
CONFIG_PUBLISHER_COUNT,
> = PubSubChannel::new();
pub type ConfigPublisher = Publisher<
'static,
CriticalSectionRawMutex,
ConfigItem,
CONFIG_CAPACITY,
MAX_CONFIG_SUBSCRIBER_COUNT,
CONFIG_PUBLISHER_COUNT,
>;
#[allow(unused)]
#[allow(clippy::expect_used)]
pub fn config_publisher() -> ConfigPublisher {
CONFIG_PUB_SUB_CHANNEL.publisher().expect("config_publisher failed")
}
pub type ConfigSubscriber = Subscriber<
'static,
CriticalSectionRawMutex,
ConfigItem,
CONFIG_CAPACITY,
MAX_CONFIG_SUBSCRIBER_COUNT,
CONFIG_PUBLISHER_COUNT,
>;
#[allow(clippy::expect_used)]
pub fn config_subscriber() -> ConfigSubscriber {
CONFIG_PUB_SUB_CHANNEL.subscriber().expect("config_subscriber failed")
}
const FAST_CONFIG_SUBSCRIBER_COUNT: usize = 1;
const FAST_CONFIG_PUBLISHER_COUNT: usize = 2;
const FAST_CONFIG_CAPACITY: usize = 4;
static FAST_CONFIG_PUB_SUB_CHANNEL: PubSubChannel<
CriticalSectionRawMutex,
FastConfigItem,
FAST_CONFIG_CAPACITY,
FAST_CONFIG_SUBSCRIBER_COUNT,
FAST_CONFIG_PUBLISHER_COUNT,
> = PubSubChannel::new();
pub type FastConfigPublisher = Publisher<
'static,
CriticalSectionRawMutex,
FastConfigItem,
FAST_CONFIG_CAPACITY,
FAST_CONFIG_SUBSCRIBER_COUNT,
FAST_CONFIG_PUBLISHER_COUNT,
>;
#[allow(unused)]
#[allow(clippy::expect_used)]
pub fn fast_config_publisher() -> FastConfigPublisher {
FAST_CONFIG_PUB_SUB_CHANNEL.publisher().expect("fast_config_publisher failed")
}
pub type FastConfigSubscriber = Subscriber<
'static,
CriticalSectionRawMutex,
FastConfigItem,
FAST_CONFIG_CAPACITY,
FAST_CONFIG_SUBSCRIBER_COUNT,
FAST_CONFIG_PUBLISHER_COUNT,
>;
#[allow(clippy::expect_used)]
pub fn fast_config_subscriber() -> FastConfigSubscriber {
FAST_CONFIG_PUB_SUB_CHANNEL.subscriber().expect("fast_config_subscriber failed")
}
macro_rules! define_configs {
(
general: [ $( $(#[$g_meta:meta])* ($g_enum:ident, $g_field:ident, $g_type:ty)),* $(,)?],
fast: [ $( $(#[$p_meta:meta])* ($p_enum:ident, $p_field:ident, $p_type:ty)),* $(,)?]
) => {
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct GlobalConfig {
$(
$(#[$g_meta])*
pub $g_field: $g_type,
)*
$(
$(#[$p_meta])*
pub $p_field: $p_type,
)*
}
impl GlobalConfig {
pub const fn new() -> Self {
Self {
$(
$(#[$g_meta])*
$g_field: <$g_type>::new(),
)*
$(
$(#[$p_meta])*
$p_field: <$p_type>::new(),
)*
}
}
}
impl Default for GlobalConfig {
fn default() -> Self {
Self::new()
}
}
#[allow(unused)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ConfigItem {
$(
$(#[$g_meta])*
$g_enum($g_type)
),*
}
#[allow(unused)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum FastConfigItem {
$(
$(#[$p_meta])*
$p_enum($p_type)
),*
}
};
}
define_configs!(
general: [
(System, system, SystemConfig),
(Schema, schema_version, SchemaVersion),
(Rates, rates, RatesConfig),
(Failsafe, failsafe, FailsafeConfig),
(FlightControlFilters, flight_control_filters, FlightControllerFiltersConfig),
(ImuFilters, imu_filter_bank, ImuFilterBankConfig),
(Gyro, gyro, GyroConfig),
(Mixer, mixer, MixerConfig),
(Motor, motor, MotorConfig),
(MotorDevice, motor_device, MotorDeviceConfig),
(Tpa, tpa, TpaConfig),
(YawSpinRecovery, yaw_spin_recovery, YawSpinRecoveryConfig),
(CrashFlip, crash_flip, CrashFlipConfig),
(CrashRecovery, crash_recovery, CrashRecoveryConfig),
(AntiGravity, anti_gravity, AntiGravityConfig),
(DMax, dmax, DMaxConfig),
(Rx, rx, RxConfig),
(RcModes, rc_modes, RcModes),
(RcControls, rc_controls, RcControlsConfig),
(Arming, arming, ArmingConfig),
(Features, features, FeatureFlags),
(Imu, imu, ImuConfig),
(ImuDevice, imu_device, ImuDeviceConfig),
(Sensors, sensors, SensorFlags),
(CurrentSensorAdc, current_sensor_adc, CurrentSensorAdcConfig),
(CurrentSensorVirtual, current_sensor_virtual, CurrentSensorVirtualConfig),
(Autopilot, autopilot, AutopilotConfig),
(PositionHold, position_hold, PositionHoldConfig),
#[cfg(feature = "barometer")]
(Barometer, barometer, BarometerConfig),
#[cfg(feature = "battery")]
(Battery, battery, BatteryConfig),
#[cfg(feature = "battery")]
(BatteryProfile, battery_profiles, BatteryProfiles),
#[cfg(feature = "blackbox")]
(Blackbox, blackbox, BlackboxConfig),
#[cfg(feature = "gps")]
(Gps, gps, GpsConfig),
#[cfg(feature = "gps")]
(GpsRescue, gps_rescue, GpsRescueConfig),
#[cfg(feature = "magnetometer")]
(Magnetometer, magnetometer, MagnetometerConfig),
#[cfg(feature = "osd")]
(Osd, osd, OsdConfig),
#[cfg(feature = "osd")]
(OsdElements, osd_elements, OsdElementsConfig),
#[cfg(feature = "osd")]
(OsdStats, osd_stats, OsdStatsConfig),
#[cfg(feature = "osd")]
(Pilot, pilot, PilotConfig),
#[cfg(feature = "optical_flow")]
(OpticalFlow, optical_flow, OpticalFlowConfig),
#[cfg(feature = "rangefinder")]
(Rangefinder, rangefinder, RangefinderConfig),
#[cfg(feature = "rpm_filters")]
(RpmNotchFilterBank, rpm_notch_filter_bank, RpmNotchFilterBankConfig),
#[cfg(feature = "vtx")]
(Vtx, vtx, VtxConfig),
],
fast: [
(RollRate, pid_roll_rate, PidConfig),
(PitchRate, pid_pitch_rate, PidConfig),
(YawRate, pid_yaw_rate, PidConfig),
(RollAngle, pid_roll_angle, PidConfig),
(PitchAngle, pid_pitch_angle, PidConfig),
]
);
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "serde")]
use {
sequential_storage::map::PostcardValue,
serde::{Deserialize, Serialize},
};
fn _is_normal<T: Sized + Send + Sync + Unpin>() {}
fn is_full<T: Sized + Send + Sync + Unpin + Copy + Clone + Default + PartialEq>() {}
fn is_full_no_default<T: Sized + Send + Sync + Unpin + Copy + Clone + PartialEq>() {}
#[cfg(feature = "serde")]
fn _is_config<T: Serialize + for<'a> Deserialize<'a> + for<'a> PostcardValue<'a>>() {}
#[test]
fn normal_types() {
is_full::<GlobalConfig>();
is_full_no_default::<ConfigItem>();
is_full_no_default::<FastConfigItem>();
}
#[test]
fn global_config_new() {
let _config = GlobalConfig::new();
}
}