use crate::model::NodeView;
#[cfg(any(feature = "esp32c5", feature = "esp32c6"))]
use crate::model::Mode;
use esp_radio::wifi::csi::CsiConfig as RadioCsiConfig;
use esp_radio::wifi::{Protocol, Protocols, WifiController};
pub trait RadioProfile: Sync {
fn wants_bringup(&self, _node: NodeView<'_>, _protocol: Option<Protocol>) -> bool {
false
}
fn tune_protocols(
&self,
_node: NodeView<'_>,
_protocol: Protocol,
base: Protocols,
) -> Protocols {
base
}
fn apply_bandwidth(&self, _controller: &mut WifiController<'_>) {}
fn before_sta_config(&self) {}
fn before_ap_config(&self) {}
fn apply_protocols_post(&self, _controller: &mut WifiController<'_>) {}
fn apply_sniffer_radio(&self, _controller: &mut WifiController<'_>) {}
fn tune_csi_acquisition(&self, _raw: &mut RadioCsiConfig) {}
}
pub struct StandardProfile;
#[cfg(any(feature = "esp32c5", feature = "esp32c6"))]
mod he20 {
use esp_radio::wifi::{Bandwidth, Protocol, Protocols, WifiController};
use crate::emitter::phy::{WIFI_PHY_MODE_HE20, force_tx_ap, force_tx_sta_before_start};
pub(super) fn protocols() -> Protocols {
let p = Protocols::default().with_2_4(Protocol::N | Protocol::AX);
#[cfg(feature = "esp32c5")]
{
return p.with_5(Protocol::A | Protocol::N | Protocol::AX);
}
#[cfg(not(feature = "esp32c5"))]
p
}
pub(super) fn protocols_post() -> Protocols {
let p = Protocols::default().with_2_4(Protocol::B | Protocol::G | Protocol::N | Protocol::AX);
#[cfg(feature = "esp32c5")]
{
return p.with_5(Protocol::A | Protocol::N | Protocol::AX);
}
#[cfg(not(feature = "esp32c5"))]
p
}
pub(super) fn lock_20mhz(controller: &mut WifiController<'_>) {
if let Ok(bw) = controller.bandwidths() {
let _ = controller.set_bandwidths(bw.with_2_4(Bandwidth::_20MHz));
}
}
pub(super) fn force_sta() {
let _ = force_tx_sta_before_start(WIFI_PHY_MODE_HE20);
}
pub(super) fn force_ap() {
let _ = force_tx_ap(WIFI_PHY_MODE_HE20);
}
}
impl RadioProfile for StandardProfile {
#[cfg(any(feature = "esp32c5", feature = "esp32c6"))]
fn wants_bringup(&self, node: NodeView<'_>, protocol: Option<Protocol>) -> bool {
protocol == Some(Protocol::AX)
&& match node.mode() {
Mode::AccessPoint(c) => c.secondary_channel().is_none(),
Mode::Station(_) | Mode::Sniffer(_) => true,
Mode::Emitter(_)
| Mode::EspNow(_)
| Mode::EspNowSimplex(_) => false,
}
}
fn tune_protocols(
&self,
node: NodeView<'_>,
_protocol: Protocol,
base: Protocols,
) -> Protocols {
#[cfg(any(feature = "esp32c5", feature = "esp32c6"))]
if _protocol == Protocol::AX
&& matches!(
node.mode(),
Mode::Station(_) | Mode::AccessPoint(_)
)
{
return he20::protocols();
}
#[cfg(feature = "esp32c5")]
{
if matches!(
node.mode(),
Mode::Station(_) | Mode::AccessPoint(_)
) {
return base.with_5(Protocol::A | Protocol::N);
}
}
let _ = node;
base
}
#[cfg(any(feature = "esp32c5", feature = "esp32c6"))]
fn apply_bandwidth(&self, controller: &mut WifiController<'_>) {
he20::lock_20mhz(controller);
}
#[cfg(any(feature = "esp32c5", feature = "esp32c6"))]
fn before_sta_config(&self) {
he20::force_sta();
}
#[cfg(any(feature = "esp32c5", feature = "esp32c6"))]
fn before_ap_config(&self) {
he20::force_ap();
}
#[cfg(any(feature = "esp32c5", feature = "esp32c6"))]
fn apply_protocols_post(&self, controller: &mut WifiController<'_>) {
let _ = controller.set_protocols(he20::protocols_post());
}
#[cfg(any(feature = "esp32c5", feature = "esp32c6"))]
fn apply_sniffer_radio(&self, controller: &mut WifiController<'_>) {
he20::lock_20mhz(controller);
let _ = controller.set_protocols(he20::protocols_post());
}
}