use core::ptr::NonNull;
use esp_hal::{dma::DmaDescriptor, peripherals::WIFI};
pub unsafe fn reload_hw_rx_descriptors() {
let reg = WIFI::regs().rx_ctrl();
reg.modify(|_, w| w.rx_descr_reload().set_bit());
while reg.read().rx_descr_reload().bit() {}
}
pub unsafe fn set_base_rx_descriptor(base_descriptor: Option<NonNull<DmaDescriptor>>) {
let reg = WIFI::regs().rx_dma_list().rx_descr_base();
if let Some(ptr) = base_descriptor {
reg.write(|w| w.bits(ptr.as_ptr() as u32));
} else {
reg.reset();
}
reload_hw_rx_descriptors();
}
pub unsafe fn next_rx_descriptor_raw() -> *mut DmaDescriptor {
WIFI::regs().rx_dma_list().rx_descr_next().read().bits() as *mut DmaDescriptor
}
pub unsafe fn last_rx_descriptor_raw() -> *mut DmaDescriptor {
WIFI::regs().rx_dma_list().rx_descr_last().read().bits() as *mut DmaDescriptor
}
pub unsafe fn last_rx_descriptor() -> Option<NonNull<DmaDescriptor>> {
NonNull::new(last_rx_descriptor_raw())
}
pub unsafe fn set_rx_enabled(enabled: bool) {
WIFI::regs()
.rx_ctrl()
.modify(|_, w| w.rx_enable().bit(enabled));
}
pub unsafe fn init_rx(base_descriptor: NonNull<DmaDescriptor>) {
set_base_rx_descriptor(Some(base_descriptor));
set_rx_enabled(true);
}
pub unsafe fn deinit_rx() {
set_rx_enabled(false);
set_base_rx_descriptor(None);
}
pub fn hw_slot_index(slot: usize) -> usize {
4 - slot
}
pub unsafe fn set_tx_slot_enabled(slot: usize, enabled: bool) {
WIFI::regs()
.tx_slot_config(hw_slot_index(slot))
.plcp0()
.modify(|_, w| w.slot_enabled().bit(enabled));
}
pub unsafe fn set_tx_slot_validity(slot: usize, valid: bool) {
WIFI::regs()
.tx_slot_config(hw_slot_index(slot))
.plcp0()
.modify(|_, w| w.slot_valid().bit(valid));
}
#[inline(always)]
pub unsafe fn process_tx_completions(mut cb: impl FnMut(usize)) {
let wifi = WIFI::regs();
wifi.txq_state()
.tx_complete_status()
.read()
.slot_iter()
.enumerate()
.filter_map(|(slot, r)| r.bit().then_some(slot))
.for_each(|slot| {
wifi.txq_state()
.tx_complete_clear()
.modify(|_, w| w.slot(slot as u8).set_bit());
(cb)(slot);
});
}
#[inline(always)]
pub unsafe fn process_tx_timeouts(mut cb: impl FnMut(usize)) {
let wifi = WIFI::regs();
wifi.txq_state()
.tx_error_status()
.read()
.slot_timeout_iter()
.enumerate()
.filter_map(|(slot, r)| r.bit().then_some(slot))
.for_each(|slot| {
wifi.txq_state()
.tx_error_clear()
.modify(|_, w| w.slot_timeout(slot as u8).set_bit());
(cb)(slot);
});
}
#[inline(always)]
pub unsafe fn process_tx_collisions(mut cb: impl FnMut(usize)) {
let wifi = WIFI::regs();
wifi.txq_state()
.tx_error_status()
.read()
.slot_collision_iter()
.enumerate()
.filter_map(|(slot, r)| r.bit().then_some(slot))
.for_each(|slot| {
wifi.txq_state()
.tx_error_clear()
.modify(|_, w| w.slot_collision(slot as u8).set_bit());
(cb)(slot);
});
}