0
0
Fork 0
Find a file
2026-08-03 11:17:51 +02:00
.cargo initial commit 2026-07-31 15:51:10 +02:00
src WIP rx: Add basic CAM and DENM evaluation 2026-08-03 11:17:51 +02:00
.clippy.toml initial commit 2026-07-31 15:51:10 +02:00
.gitignore initial commit 2026-07-31 15:51:10 +02:00
Cargo.toml initial commit 2026-07-31 15:51:10 +02:00
Readme.md initial commit 2026-07-31 15:51:10 +02:00
rustfmt.toml initial commit 2026-07-31 15:51:10 +02:00

ESP32-C5 C-ITS Core

Common data structures and helper functions to receive and send C-ITS (V2X) data on an ESP32-C5.

Usage

Communicate with C-ITS Devices

Setup the connection like this in your main function:

// 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(
    peripherals.WIFI,
    esp_radio::wifi::ControllerConfig::default(),
)
.expect("Failed to initialize Wi-Fi controller");

if let Err(err) = wifi_controller.set_band_mode(esp_radio::wifi::BandMode::_5G) {
    println!("Failed to set WiFi to 5GHz only: {err}");
}
if let Err(err) = wifi_controller.set_max_tx_power(WIFI_TXPOWER * 4) {
    println!("Failed to set WiFi TX power: {err}");
}

critical_section::with(|cs| {
    WIFI_RX_QUEUE.borrow(cs).replace(Some(ArrayQueue::new(2)));
});
let mut wlan_iface = interfaces.sniffer;
radio::setup_wifi_sniffer(WIFI_CHANNEL, &mut wlan_iface, handle_frame)
    .expect("Fatal error initializing 802.11p sniffer");

println!("WiFi promiscuous mode on channel {WIFI_CHANNEL} running");

let mac = esp_hal::efuse::base_mac_address();
println!("WiFi MAC: {mac}");

With a frame handler like this:

fn handle_frame(frame: esp_radio::wifi::sniffer::PromiscuousPkt<'_>) {
  match esp32_cits_core::rx::is_broadcast_frame(&frame) {
    Err(err) => {
        warn!("{err}");
        return;
    }
    Ok(false) => {
        // drop frame
        return;
    }
    Ok(true) => {
        // continue
    }
}

  println!("Received frame with {} bytes", frame.len);

  // parse message
  match c_its_parser::de::decode(frame.data, c_its_parser::Headers::IEEE802LlcGnBtp) {
      Ok(its_message) => {
          println!("New message: {its_message:?}");

          // do something with the data
      },
      Err(err) => println!("Failed to parse ITS message: {err}"),
  }
}

Sending

Implement tx::GnItsPayload and then call encode_packet(). Then send frame with radio::send_80211_bcast_frame().

Run Unit Tests on Host

The unit tests in this project are meant to be run on the host:

cargo test --target host-tuple --no-default-features -F std