#![cfg(feature = "msp")]
#![allow(unused)]
use {
static_cell::StaticCell,
stream_buf::{StreamBufReader, StreamBufWriter},
};
use crate::{
config::{ConfigPublisher, FastConfigPublisher, config_publisher, fast_config_publisher},
multiwii_serial_protocol::{Msp, MspSensorData, MspStream},
};
#[cfg(feature = "barometer")]
use crate::tasks::barometer::{BarometerSubscriber, barometer_subscriber};
#[cfg(feature = "battery")]
use crate::tasks::battery::{BatterySubscriber, battery_subscriber};
#[cfg(feature = "gps")]
use crate::{
gps::GpsMessage,
tasks::gps::{GpsSubscriber, gps_subscriber},
};
#[cfg(feature = "magnetometer")]
use crate::tasks::magnetometer::{MagnetometerSubscriber, magnetometer_subscriber};
#[cfg(feature = "optical_flow")]
use crate::tasks::optical_flow::{OpticalFlowSubscriber, optical_flow_subscriber};
#[cfg(feature = "rangefinder")]
use crate::tasks::rangefinder::{RangefinderSubscriber, rangefinder_subscriber};
static MSP_CTX: StaticCell<MspContext> = StaticCell::new();
pub struct MspContext {
pub fast_config_publisher: FastConfigPublisher,
pub config_publisher: ConfigPublisher,
#[cfg(feature = "barometer")]
pub barometer_subscriber: BarometerSubscriber,
#[cfg(feature = "battery")]
pub battery_subscriber: BatterySubscriber,
#[cfg(feature = "gps")]
pub gps_subscriber: GpsSubscriber,
#[cfg(feature = "magnetometer")]
pub magnetometer_subscriber: MagnetometerSubscriber,
#[cfg(feature = "optical_flow")]
pub optical_flow_subscriber: OpticalFlowSubscriber,
#[cfg(feature = "rangefinder")]
pub rangefinder_subscriber: RangefinderSubscriber,
pub msp: Msp,
pub read_buf: [u8; Self::READ_BUF_SIZE],
pub write_buf: [u8; Self::WRITE_BUF_SIZE],
}
impl MspContext {
const READ_BUF_SIZE: usize = 256;
const WRITE_BUF_SIZE: usize = 512;
}
impl MspContext {
pub fn reader(&'_ mut self) -> StreamBufReader<'_> {
StreamBufReader::new(&self.read_buf)
}
pub fn writer(&'_ mut self) -> StreamBufWriter<'_> {
StreamBufWriter::new(&mut self.write_buf)
}
}
pub fn init() -> &'static mut MspContext {
#[rustfmt::skip]
let ctx = MspContext {
msp: Msp::new(),
fast_config_publisher: fast_config_publisher(),
config_publisher: config_publisher(),
#[cfg(feature = "barometer")] barometer_subscriber: barometer_subscriber(),
#[cfg(feature = "battery")] battery_subscriber: battery_subscriber(),
#[cfg(feature = "gps")] gps_subscriber: gps_subscriber(),
#[cfg(feature = "magnetometer")] magnetometer_subscriber: magnetometer_subscriber(),
#[cfg(feature = "optical_flow")] optical_flow_subscriber: optical_flow_subscriber(),
#[cfg(feature = "rangefinder")] rangefinder_subscriber: rangefinder_subscriber(),
read_buf: [0u8; MspContext::READ_BUF_SIZE],
write_buf: [0u8; MspContext::WRITE_BUF_SIZE],
};
MSP_CTX.init(ctx)
}
#[embassy_executor::task]
pub async fn run(ctx: &'static mut MspContext) {
let mut ticker = embassy_time::Ticker::every(embassy_time::Duration::from_millis(200));
let mut loop_count: u32 = 0;
let mut msp_sensor_data = MspSensorData::new();
log::info!(" MSP: task started");
loop {
ticker.next().await;
#[cfg(feature = "barometer")]
if let Some(wait_result) = ctx.barometer_subscriber.try_next_message()
&& let embassy_sync::pubsub::WaitResult::Message(barometer_data) = wait_result
{
#[allow(clippy::cast_possible_truncation)]
{
msp_sensor_data.barometer_altitude_cm = ((barometer_data.altitude_m * 100.0) as i32).cast_unsigned();
}
}
#[cfg(feature = "rangefinder")]
if let Some(wait_result) = ctx.rangefinder_subscriber.try_next_message()
&& let embassy_sync::pubsub::WaitResult::Message(rangefinder_message) = wait_result
{
#[allow(clippy::cast_possible_truncation)]
{
msp_sensor_data.rangefinder_altitude_cm =
((rangefinder_message.distance_m * 100.0) as i32).cast_unsigned();
}
}
#[cfg(feature = "gps")]
if let Some(wait_result) = ctx.gps_subscriber.try_next_message()
&& let embassy_sync::pubsub::WaitResult::Message(event) = wait_result
&& let GpsMessage::Data(gps_data) = event
{
msp_sensor_data.gps_solution.longitude_degrees_x1e7 = gps_data.longitude_degrees_x1e7;
msp_sensor_data.gps_solution.satellite_count = gps_data.satellite_count;
#[allow(clippy::cast_sign_loss)]
{
msp_sensor_data.gps_solution.ground_speed_cmps = gps_data.ground_speed_cmps as u16;
msp_sensor_data.gps_solution.ground_course_degrees_x10 = gps_data.heading_deci_degrees as u16;
}
msp_sensor_data.gps_solution.pdop = gps_data.pdop_x100;
}
let mut src = StreamBufReader::new(&ctx.read_buf);
let cmd_msp = Msp::SET_FAILSAFE_CONFIG;
let _result =
Msp::process_read_command(cmd_msp, &mut src, &ctx.config_publisher, &ctx.fast_config_publisher).await;
if loop_count.is_multiple_of(10) {
log::info!(" MSP: loop {loop_count}");
}
loop_count = loop_count.wrapping_add(1);
}
}