#![cfg(feature = "osd")]
use simple_bitset::BitSet64;
use vqm::Quaternionf32;
use crate::{
flight::ArmingFlags,
osd::{Osd, OsdDrawContext},
tasks::{
gyro_pid_task::{GyroPidReceiver, SetpointReceiver},
init::DisplayPortMutex,
},
};
#[cfg(feature = "optical_flow")]
use crate::tasks::optical_flow_task::OpticalFlowSubscriber;
#[cfg(feature = "rangefinder")]
use crate::tasks::rangefinder_task::RangefinderSubscriber;
#[cfg(feature = "barometer")]
use crate::tasks::barometer_task::BarometerSubscriber;
#[cfg(feature = "battery")]
use crate::{sensors::BatteryMessage, tasks::battery_task::BatterySubscriber};
#[cfg(feature = "gps")]
use crate::tasks::gps_task::GpsSubscriber;
#[allow(unused)]
pub struct OsdContext {
pub gyro_pid_receiver: GyroPidReceiver,
pub setpoint_receiver: SetpointReceiver,
#[cfg(feature = "barometer")]
pub barometer_subscriber: BarometerSubscriber,
#[cfg(feature = "battery")]
pub battery_subscriber: BatterySubscriber,
#[cfg(feature = "gps")]
pub gps_subscriber: GpsSubscriber,
#[cfg(feature = "optical_flow")]
pub optical_flow_subscriber: OpticalFlowSubscriber,
#[cfg(feature = "rangefinder")]
pub rangefinder_subscriber: RangefinderSubscriber,
pub osd: Osd,
}
impl OsdContext {
#[rustfmt::skip]
pub fn new(
gyro_pid_receiver: GyroPidReceiver,
setpoint_receiver: SetpointReceiver,
#[cfg(feature = "barometer")] barometer_subscriber: BarometerSubscriber,
#[cfg(feature = "battery")] battery_subscriber: BatterySubscriber,
#[cfg(feature = "gps")] gps_subscriber: GpsSubscriber,
#[cfg(feature = "optical_flow")] optical_flow_subscriber: OpticalFlowSubscriber,
#[cfg(feature = "rangefinder")] rangefinder_subscriber: RangefinderSubscriber,
) -> Self {
Self {
gyro_pid_receiver,
setpoint_receiver,
#[cfg(feature = "barometer")] barometer_subscriber,
#[cfg(feature = "battery")] battery_subscriber,
#[cfg(feature = "gps")] gps_subscriber,
#[cfg(feature = "optical_flow")] optical_flow_subscriber,
#[cfg(feature = "rangefinder")] rangefinder_subscriber,
osd: Osd::new(),
}
}
}
#[embassy_executor::task]
pub async fn osd_task(ctx: &'static mut OsdContext, display_port_mutex: &'static DisplayPortMutex) {
let mut ticker = embassy_time::Ticker::every(embassy_time::Duration::from_hz(50));
let mut loop_count: u32 = 0;
#[cfg(feature = "battery")]
let mut battery_message = BatteryMessage::new();
let mut orientation = Quaternionf32::default();
log::info!(" OSD: task started");
loop {
ticker.next().await;
let osd_enabled = true;
if osd_enabled {
let mut display_port_guard = display_port_mutex.lock().await;
let arming_flags = ArmingFlags::new();
if let Some(gyro_pid_message) = ctx.gyro_pid_receiver.try_get() {
orientation = gyro_pid_message.orientation;
}
#[cfg(feature = "battery")]
if let Some(wait_result) = ctx.battery_subscriber.try_next_message()
&& let embassy_sync::pubsub::WaitResult::Message(battery_data) = wait_result
{
battery_message = battery_data;
}
let mut draw_context = OsdDrawContext {
display_port: &mut *display_port_guard,
orientation,
arming_flags,
active_modes: BitSet64::new(),
#[cfg(feature = "battery")]
battery_message,
};
#[allow(clippy::cast_possible_truncation)]
let time_microseconds = embassy_time::Instant::now().as_micros() as u32;
ctx.osd.update_display(&mut draw_context, time_microseconds).await;
}
if loop_count.is_multiple_of(10) {
log::info!(" OSD: loop {loop_count}");
}
loop_count = loop_count.wrapping_add(1); }
}