#![cfg(feature = "gps")]
use embassy_sync::{
pubsub::{PubSubChannel, Publisher, Subscriber},
{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal},
};
use crate::{
gps::{Geodetic, GeographicCoordinate, GpsSolutionData},
gps::{
GpsMessage, {GpsData, GpsPositionMeters, GpsYawHeadingMessage},
},
};
const MAX_GPS_SUBSCRIBER_COUNT: usize = 4;
const GPS_PUBLISHER_COUNT: usize = 1;
const GPS_PUB_SUB_CAPACITY: usize = 4;
static GPS_PUB_SUB_CHANNEL: PubSubChannel<
CriticalSectionRawMutex,
GpsMessage,
GPS_PUB_SUB_CAPACITY,
MAX_GPS_SUBSCRIBER_COUNT,
GPS_PUBLISHER_COUNT,
> = PubSubChannel::new();
pub type GpsPublisher = Publisher<
'static,
CriticalSectionRawMutex,
GpsMessage,
GPS_PUB_SUB_CAPACITY,
MAX_GPS_SUBSCRIBER_COUNT,
GPS_PUBLISHER_COUNT,
>;
#[allow(clippy::expect_used)]
pub fn gps_publisher() -> GpsPublisher {
GPS_PUB_SUB_CHANNEL.publisher().expect("gps_publisher failed")
}
pub type GpsSubscriber = Subscriber<
'static,
CriticalSectionRawMutex,
GpsMessage,
GPS_PUB_SUB_CAPACITY,
MAX_GPS_SUBSCRIBER_COUNT,
GPS_PUBLISHER_COUNT,
>;
#[allow(clippy::expect_used)]
pub fn gps_subscriber() -> GpsSubscriber {
GPS_PUB_SUB_CHANNEL.subscriber().expect("gps_subscriber failed")
}
pub static GPS_YAW_HEADING_SIGNAL: Signal<CriticalSectionRawMutex, GpsYawHeadingMessage> = Signal::new();
pub struct GpsContext {
pub gps_publisher: GpsPublisher,
pub home: Geodetic,
}
impl GpsContext {
pub const fn new(gps_publisher: GpsPublisher) -> Self {
Self { gps_publisher, home: Geodetic::new() }
}
}
#[embassy_executor::task]
pub async fn gps_task(ctx: &'static mut GpsContext) {
let mut ticker = embassy_time::Ticker::every(embassy_time::Duration::from_hz(10));
let mut loop_count: u32 = 0;
log::info!(" GPS: task started");
loop {
ticker.next().await;
let gps_data = GpsData::default();
let gps_solution = GpsSolutionData { satellite_count: 4, ..Default::default() };
ctx.gps_publisher.publish_immediate(GpsMessage::Gps(gps_data));
ctx.gps_publisher.publish_immediate(GpsMessage::GpsSolution(gps_solution));
let geographic_coordinate = GeographicCoordinate::from(gps_data.position);
let gps_position = GpsPositionMeters { position: ctx.home.distance_from_home_meters(geographic_coordinate) };
ctx.gps_publisher.publish_immediate(GpsMessage::GpsPositionMeters(gps_position));
if gps_data.ground_speed_cmps > 150 {
let gps_yaw_heading_message = GpsYawHeadingMessage {
yaw_heading_radians: (f32::from(gps_data.heading_deci_degrees) * 0.1).to_radians(),
delta_t: 0.1,
};
GPS_YAW_HEADING_SIGNAL.signal(gps_yaw_heading_message);
}
if loop_count.is_multiple_of(10) {
log::info!(" GPS: loop {loop_count}");
}
loop_count = loop_count.wrapping_add(1); }
}