use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, watch::Watch};
use embassy_time::Duration;
use radio_controllers::{RadioControlMessage, Rates, RcModes, RxFrame};
use log::info;
use static_cell::StaticCell;
use crate::{
config::{CONFIG_PUB_SUB_CHANNEL, ConfigItem, ConfigSubscriber, GYRO_PID_PUB_SUB_CHANNEL},
flight::RcAdjustments,
};
pub(crate) static RADIO_CTX: StaticCell<RadioContext> = StaticCell::new();
const RADIO_WATCH_COUNT: usize = 1;
static RADIO_WATCH: Watch<CriticalSectionRawMutex, RadioControlMessage, RADIO_WATCH_COUNT> = Watch::new();
pub type RadioSender =
embassy_sync::watch::Sender<'static, CriticalSectionRawMutex, RadioControlMessage, RADIO_WATCH_COUNT>;
pub fn radio_sender() -> RadioSender {
RADIO_WATCH.sender()
}
pub type RadioReceiver =
embassy_sync::watch::Receiver<'static, CriticalSectionRawMutex, RadioControlMessage, RADIO_WATCH_COUNT>;
pub fn radio_receiver() -> RadioReceiver {
RADIO_WATCH.receiver().expect("radio receiver failed")
}
pub struct RadioContext<'a> {
pub radio_sender: RadioSender,
pub config_subscriber: ConfigSubscriber<'a>,
pub rc_modes: RcModes,
pub rates: Rates,
pub rc_adjustments: RcAdjustments,
}
#[embassy_executor::task]
pub async fn radio_task(ctx: &'static mut RadioContext<'static>) {
let config_publisher = CONFIG_PUB_SUB_CHANNEL.publisher().expect("failed to create Radio config publisher");
let gyro_pid_publisher = GYRO_PID_PUB_SUB_CHANNEL.publisher().expect("failed to create Radio gyro_pid publisher");
let mut ticker = embassy_time::Ticker::every(Duration::from_millis(20));
let mut loop_count: u32 = 0;
info!(" RADIO: task started");
loop {
ticker.next().await;
let rx_frame = RxFrame::new();
let failsafe = 0;
while let Some(wait_result) = ctx.config_subscriber.try_next_message() {
if let embassy_sync::pubsub::WaitResult::Message(ConfigItem::Rates(config)) = wait_result {
ctx.rates.set(config);
}
}
ctx.rc_modes.update_activated_modes(&rx_frame);
ctx.rc_adjustments.process_adjustments(&config_publisher, &gyro_pid_publisher).await;
let radio_control_message =
RadioControlMessage::new_from(&rx_frame, &ctx.rates, &ctx.rc_modes, loop_count, failsafe);
ctx.radio_sender.send(radio_control_message);
if loop_count.is_multiple_of(5) {
info!(" RADIO: loop {loop_count}");
}
loop_count = loop_count.wrapping_add(1); }
}