Implement UART I/O protocol
This commit is contained in:
parent
ba71e718df
commit
4d7bef58a1
11 changed files with 610 additions and 36 deletions
114
src/main.rs
114
src/main.rs
|
|
@ -7,6 +7,13 @@
|
|||
)]
|
||||
// #![deny(clippy::large_stack_frames)]
|
||||
|
||||
// we can't use UART I/O and GNSS at the same time
|
||||
#[cfg(all(feature = "uart", feature = "gnss"))]
|
||||
compile_error!("feature \"uart\" and feature \"gnss\" cannot be enabled at the same time");
|
||||
// autonomous CAM generation need a time and position source (aka _gnss)
|
||||
#[cfg(all(feature = "cam_tx", not(feature = "_gnss")))]
|
||||
compile_error!("feature \"cam_tx\" needs a time and position source (either GNSS or UART)");
|
||||
|
||||
use alloc::string::ToString as _;
|
||||
use alloc::vec::Vec;
|
||||
use core::cell::RefCell;
|
||||
|
|
@ -35,17 +42,18 @@ extern crate alloc;
|
|||
mod applogic;
|
||||
mod cache;
|
||||
mod geo_alg;
|
||||
#[cfg(feature = "uart")]
|
||||
mod io;
|
||||
mod radio;
|
||||
#[cfg(feature = "screen")]
|
||||
mod screen;
|
||||
#[cfg(feature = "cam_tx")]
|
||||
#[cfg(any(feature = "cam_tx", feature = "uart"))]
|
||||
mod v2x_tx;
|
||||
|
||||
const WIFI_CHANNEL: radio::Channel = 180;
|
||||
#[cfg(feature = "spat")]
|
||||
const SPAT_RATE_LIMIT: u8 = 5; // keep every n-th message
|
||||
#[cfg(feature = "cam_tx")]
|
||||
#[cfg(any(feature = "cam_tx", feature = "uart"))]
|
||||
const GN_IS_MOBILE: bool = true;
|
||||
#[cfg(feature = "cam_tx")]
|
||||
const OWN_STATION_TYPE: ItsStationType = ItsStationType::Cyclist;
|
||||
|
|
@ -60,7 +68,7 @@ const SERIAL_FIFO_SIZE_THLD: u8 = 100; // hardware has max. 128 byte
|
|||
// For more information see: <https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/app_image_format.html#application-description>
|
||||
esp_bootloader_esp_idf::esp_app_desc!();
|
||||
|
||||
#[cfg(feature = "gnss")]
|
||||
#[cfg(feature = "_gnss")]
|
||||
static GNSS_UPDATE: Mutex<RefCell<Option<applogic::GnssFix>>> = Mutex::new(RefCell::new(None));
|
||||
static WIFI_RX_QUEUE: Mutex<RefCell<Option<ArrayQueue<Vec<u8>>>>> = Mutex::new(RefCell::new(None));
|
||||
#[cfg(feature = "_uart")]
|
||||
|
|
@ -136,6 +144,18 @@ async fn main(spawner: Spawner) -> ! {
|
|||
screen
|
||||
};
|
||||
|
||||
// Setup UART I/O channel
|
||||
#[cfg(feature = "uart")]
|
||||
setup_uart0(
|
||||
115_200,
|
||||
Some(b'\n'),
|
||||
peripherals.GPIO12,
|
||||
peripherals.GPIO11,
|
||||
peripherals.UART0,
|
||||
serial_handler,
|
||||
)
|
||||
.expect("Failed to initialize UART");
|
||||
|
||||
// Setup WiFi
|
||||
// sadly, it doesn't work any more when we move `esp_radio::wifi::new` to `setup_wifi_sniffer`
|
||||
let (mut wifi_controller, interfaces) = esp_radio::wifi::new(
|
||||
|
|
@ -178,24 +198,29 @@ async fn main(spawner: Spawner) -> ! {
|
|||
#[cfg(feature = "gnss")]
|
||||
info!("GNSS task started, waiting for GNSS fix...");
|
||||
|
||||
let mut state = applogic::State::new();
|
||||
#[cfg(feature = "cam_tx")]
|
||||
let (mut seq_no, mut cam, mac_bytes) = {
|
||||
let station_id = v2x_tx::make_station_id(mac);
|
||||
info!("V2X Station ID: {station_id}");
|
||||
|
||||
#[cfg(any(feature = "cam_tx", feature = "uart"))]
|
||||
let (mut seq_no, mac_bytes) = {
|
||||
// unwrap is fine since [`esp_hal::efuse::MacAddress`] is just an `[u8; 6]`
|
||||
let mac_bytes = mac.as_bytes().try_into().unwrap();
|
||||
|
||||
let cam = applogic::cam_tx::CamState::new(
|
||||
(0, mac_bytes)
|
||||
};
|
||||
|
||||
let mut state = applogic::State::new();
|
||||
#[cfg(feature = "cam_tx")]
|
||||
let mut cam = {
|
||||
let station_id = v2x_tx::make_station_id(mac);
|
||||
info!("V2X Station ID: {station_id}");
|
||||
|
||||
applogic::cam_tx::CamState::new(
|
||||
station_id,
|
||||
OWN_STATION_TYPE,
|
||||
OWN_VEHICLE_LENGTH,
|
||||
OWN_VEHICLE_WIDTH,
|
||||
);
|
||||
|
||||
(0, cam, mac_bytes)
|
||||
)
|
||||
};
|
||||
#[cfg(feature = "uart")]
|
||||
let mut uart_input = io::Parser::default();
|
||||
loop {
|
||||
embassy_time::Timer::after(embassy_time::Duration::from_millis(1)).await;
|
||||
|
||||
|
|
@ -214,11 +239,56 @@ async fn main(spawner: Spawner) -> ! {
|
|||
});
|
||||
|
||||
if let Some(data) = new_data {
|
||||
warn!("TODO: New UART data: {data:x?}");
|
||||
#[cfg(feature = "uart")]
|
||||
{
|
||||
for msg in uart_input.parse(&data) {
|
||||
match msg.payload {
|
||||
Some(io::msg::serial_input_msg::Payload::Position(fix)) => {
|
||||
let pos_state = fix.into();
|
||||
|
||||
critical_section::with(|cs| {
|
||||
let gnss_update_ref = GNSS_UPDATE.borrow(cs);
|
||||
gnss_update_ref.replace(Some(pos_state));
|
||||
});
|
||||
}
|
||||
Some(io::msg::serial_input_msg::Payload::TxMsg(tx_request)) => {
|
||||
use v2x_tx::GnItsPayload as _;
|
||||
|
||||
info!(
|
||||
"UART: Got new TX message: Type {} with {} bytes",
|
||||
tx_request.message_type,
|
||||
tx_request.payload.len()
|
||||
);
|
||||
let own_position = state.pos();
|
||||
let time = state.time().and_utc();
|
||||
|
||||
match tx_request.encode_packet(
|
||||
mac_bytes,
|
||||
own_position,
|
||||
time,
|
||||
GN_IS_MOBILE,
|
||||
&mut seq_no,
|
||||
) {
|
||||
Ok(data) => {
|
||||
if let Err(err) = radio::send_80211_bcast_frame(
|
||||
&mut wlan_iface,
|
||||
&mac_bytes.clone(),
|
||||
&data,
|
||||
) {
|
||||
warn!("Failed to send 802.11 frame: {err}");
|
||||
}
|
||||
}
|
||||
Err(err) => warn!("Failed to create GN message: {err}"),
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gnss")]
|
||||
#[cfg(feature = "_gnss")]
|
||||
{
|
||||
let mut new_position = false;
|
||||
critical_section::with(|cs| {
|
||||
|
|
@ -245,7 +315,7 @@ async fn main(spawner: Spawner) -> ! {
|
|||
Ok(data) => {
|
||||
if let Err(err) = radio::send_80211_bcast_frame(
|
||||
&mut wlan_iface,
|
||||
mac.as_bytes(),
|
||||
&mac_bytes.clone(),
|
||||
&data,
|
||||
) {
|
||||
warn!("Failed to send 802.11 frame: {err}");
|
||||
|
|
@ -472,6 +542,18 @@ fn handle_frame(frame: wifi::sniffer::PromiscuousPkt<'_>) {
|
|||
error!("V2X RX queue is full");
|
||||
}
|
||||
});
|
||||
|
||||
// Send data to UART
|
||||
#[cfg(feature = "uart")]
|
||||
{
|
||||
let message = io::msg::RawMsgRx {
|
||||
msg_type: message_id.as_u8().into(),
|
||||
payload: frame.data.to_vec(),
|
||||
}
|
||||
.serialize_uart_proto();
|
||||
|
||||
send_uart0(&message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue