use embassy_futures::select::{Either3, select3};
use embassy_net_driver_channel::driver::LinkState;
use embassy_net_driver_channel::{self as ch};
use embassy_time::{Duration, Ticker};
use crate::radio::InterruptHandler;
use crate::radio::ieee802154::{Packet, Radio};
use crate::{self as nrf, interrupt};
pub const MTU: usize = Packet::CAPACITY as usize;
pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>;
pub struct State<const N_RX: usize, const N_TX: usize> {
ch_state: ch::State<MTU, N_RX, N_TX>,
}
impl<const N_RX: usize, const N_TX: usize> State<N_RX, N_TX> {
pub const fn new() -> Self {
Self {
ch_state: ch::State::new(),
}
}
}
pub struct Runner<'d> {
radio: nrf::radio::ieee802154::Radio<'d>,
ch: ch::Runner<'d, MTU>,
}
impl<'d> Runner<'d> {
pub async fn run(mut self) -> ! {
let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split();
let mut tick = Ticker::every(Duration::from_millis(500));
let mut packet = Packet::new();
state_chan.set_link_state(LinkState::Up);
loop {
match select3(
async {
let rx_buf = rx_chan.rx_buf().await;
self.radio.receive(&mut packet).await.ok().map(|_| rx_buf)
},
tx_chan.tx_buf(),
tick.next(),
)
.await
{
Either3::First(Some(rx_buf)) => {
let len = rx_buf.len().min(packet.len() as usize);
(&mut rx_buf[..len]).copy_from_slice(&*packet);
rx_chan.rx_done(len);
}
Either3::Second(tx_buf) => {
let len = tx_buf.len().min(Packet::CAPACITY as usize);
packet.copy_from_slice(&tx_buf[..len]);
self.radio.try_send(&mut packet).await.ok().unwrap();
tx_chan.tx_done();
}
_ => {}
}
}
}
}
pub async fn new<'a, const N_RX: usize, const N_TX: usize, T: nrf::radio::Instance, Irq>(
mac_addr: [u8; 8],
radio: nrf::Peri<'a, T>,
irq: Irq,
state: &'a mut State<N_RX, N_TX>,
) -> Result<(Device<'a>, Runner<'a>), ()>
where
Irq: interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'a,
{
let radio = Radio::new(radio, irq);
let (runner, device) = ch::new(&mut state.ch_state, ch::driver::HardwareAddress::Ieee802154(mac_addr));
Ok((device, Runner { ch: runner, radio }))
}