#![cfg(feature = "osd")]
use static_cell::StaticCell;
use vqm::Quaternionf32;
use super::{
gyro_pid::{GyroPidReceiver, SetpointReceiver, gyro_pid_receiver, setpoint_receiver},
rx::{RxMessageReceiver, rx_message_receiver},
};
use crate::{
config::GLOBAL_CONFIG,
display::{Display, DisplayPortLayer, DisplayPortMutex},
flight::{ArmingFlags, RxMessage},
osd::{Osd, OsdDrawContext, OsdElements, OsdState},
};
#[cfg(feature = "optical_flow")]
use super::optical_flow::{OpticalFlowSubscriber, optical_flow_subscriber};
#[cfg(feature = "rangefinder")]
use super::rangefinder::{RangefinderSubscriber, rangefinder_subscriber};
#[cfg(feature = "barometer")]
use super::barometer::{BarometerSubscriber, barometer_subscriber};
#[cfg(feature = "battery")]
use crate::{
battery_sensors::BatteryMessage,
tasks::battery::{BatterySubscriber, battery_subscriber},
};
#[cfg(feature = "gps")]
use super::gps::{GpsSubscriber, gps_subscriber};
static OSD_CTX: StaticCell<OsdContext> = StaticCell::new();
#[allow(unused)]
pub struct OsdContext {
pub gyro_pid_receiver: GyroPidReceiver,
pub setpoint_receiver: SetpointReceiver,
pub rx_receiver: RxMessageReceiver,
#[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,
pub osd_state: OsdState,
pub osd_elements: OsdElements,
pub display_port_mutex: &'static DisplayPortMutex,
}
pub async fn init(display_port_mutex: &'static DisplayPortMutex) -> &'static mut OsdContext {
let display_port = display_port_mutex.lock().await;
let background_layer_supported = display_port.layer_supported(DisplayPortLayer::Background);
#[rustfmt::skip]
let ctx = OsdContext {
gyro_pid_receiver: gyro_pid_receiver(),
setpoint_receiver: setpoint_receiver(),
rx_receiver: rx_message_receiver(),
#[cfg(feature = "barometer")] barometer_subscriber: barometer_subscriber(),
#[cfg(feature = "battery")] battery_subscriber: battery_subscriber(),
#[cfg(feature = "gps")] gps_subscriber: gps_subscriber(),
#[cfg(feature = "optical_flow")] optical_flow_subscriber: optical_flow_subscriber(),
#[cfg(feature = "rangefinder")] rangefinder_subscriber: rangefinder_subscriber(),
osd: Osd::new(),
osd_state: OsdState::default(),
osd_elements: OsdElements::new(background_layer_supported),
display_port_mutex,
};
OSD_CTX.init(ctx)
}
#[embassy_executor::task]
pub async fn run(ctx: &'static mut OsdContext) {
const TASK_FREQUENCY_HZ: u64 = 50;
let mut ticker = embassy_time::Ticker::every(embassy_time::Duration::from_hz(TASK_FREQUENCY_HZ));
let mut loop_count: u32 = 0;
#[cfg(feature = "battery")]
let mut battery_message = BatteryMessage::new();
let mut orientation = Quaternionf32::default();
let mut rx_message = RxMessage::new();
log::info!(" OSD: task started");
loop {
ticker.next().await;
let osd_enabled = true;
if osd_enabled {
let arming_flags = ArmingFlags::new();
#[cfg(feature = "battery")]
if let Some(embassy_sync::pubsub::WaitResult::Message(battery_data)) =
ctx.battery_subscriber.try_next_message()
{
battery_message = battery_data;
}
if let Some(gyro_pid_message) = ctx.gyro_pid_receiver.try_get() {
orientation = gyro_pid_message.orientation;
}
if let Some(rx) = ctx.rx_receiver.try_get() {
rx_message = rx;
}
if ctx.osd_state.start_frame() {
let draw_context = OsdDrawContext {
orientation,
arming_flags,
rx_message,
#[cfg(feature = "battery")]
battery_message,
};
let osd_config = {
let global_config = GLOBAL_CONFIG.lock().await;
global_config.osd
};
while ctx.osd_state != OsdState::Idle {
#[allow(clippy::cast_possible_truncation)]
let time_us = embassy_time::Instant::now().as_micros();
ctx.osd_state
.update_display_iteration(
&mut ctx.osd_elements,
&draw_context,
ctx.display_port_mutex,
&osd_config,
time_us,
)
.await;
}
}
}
if loop_count.is_multiple_of(50) {
log::info!(" OSD: loop {loop_count}");
}
loop_count = loop_count.wrapping_add(1);
}
}