use crate::{
payload::{EsbHeader, PayloadR, PayloadW},
Error,
};
use bbq2::{
queue::BBQueue,
traits::{coordination::cas::AtomicCoord, notifier::maitake::MaiNotSpsc, storage::Inline},
};
use core::default::Default;
use cortex_m::peripheral::NVIC;
use nrf_pac::Interrupt;
pub(crate) type FramedProducer<const N: usize> = bbq2::prod_cons::framed::FramedProducer<
&'static BBQueue<Inline<N>, AtomicCoord, MaiNotSpsc>,
Inline<N>,
AtomicCoord,
MaiNotSpsc,
u16,
>;
pub(crate) type FramedConsumer<const N: usize> = bbq2::prod_cons::framed::FramedConsumer<
&'static BBQueue<Inline<N>, AtomicCoord, MaiNotSpsc>,
Inline<N>,
AtomicCoord,
MaiNotSpsc,
u16,
>;
pub struct EsbApp<const OUT: usize, const IN: usize> {
pub(crate) prod_to_radio: FramedProducer<OUT>,
pub(crate) cons_from_radio: FramedConsumer<IN>,
pub(crate) maximum_payload: u8,
}
pub struct EsbAppSender<const OUT: usize> {
pub(crate) prod_to_radio: FramedProducer<OUT>,
pub(crate) maximum_payload: u8,
}
impl<const OUT: usize> EsbAppSender<OUT> {
pub fn grant_packet(&mut self, header: EsbHeader) -> Result<PayloadW<OUT>, Error> {
if header.length > self.maximum_payload {
return Err(Error::MaximumPacketExceeded);
}
let grant_result = self
.prod_to_radio
.grant(header.payload_len() + EsbHeader::header_size());
let grant = grant_result.map_err(|err| match err {
_ => Error::InternalError,
})?;
Ok(PayloadW::new_from_app(grant, header))
}
pub async fn wait_grant_packet(&mut self, header: EsbHeader) -> Result<PayloadW<OUT>, Error> {
if header.length > self.maximum_payload {
return Err(Error::MaximumPacketExceeded);
}
let grant = self
.prod_to_radio
.wait_grant(header.payload_len() + EsbHeader::header_size()).await;
Ok(PayloadW::new_from_app(grant, header))
}
#[inline]
pub fn start_tx(&mut self) {
NVIC::pend(Interrupt::RADIO)
}
#[inline]
pub fn maximum_payload_size(&self) -> usize {
self.maximum_payload.into()
}
}
pub struct EsbAppReceiver<const IN: usize> {
pub(crate) cons_from_radio: FramedConsumer<IN>,
pub(crate) maximum_payload: u8,
}
impl<const IN: usize> EsbAppReceiver<IN> {
pub fn msg_ready(&mut self) -> bool {
self.cons_from_radio.read().is_ok()
}
pub fn read_packet(&mut self) -> Option<PayloadR<IN>> {
self.cons_from_radio.read().ok().map(PayloadR::new)
}
pub async fn wait_read_packet(&mut self) -> PayloadR<IN> {
PayloadR::new(self.cons_from_radio.wait_read().await)
}
#[inline]
pub fn maximum_payload_size(&self) -> usize {
self.maximum_payload.into()
}
}
impl<const OUT: usize, const IN: usize> EsbApp<OUT, IN> {
pub fn split(self) -> (EsbAppSender<OUT>, EsbAppReceiver<IN>) {
let EsbApp { prod_to_radio, cons_from_radio, maximum_payload } = self;
(
EsbAppSender { prod_to_radio, maximum_payload },
EsbAppReceiver { cons_from_radio, maximum_payload },
)
}
pub fn grant_packet(&mut self, header: EsbHeader) -> Result<PayloadW<OUT>, Error> {
if header.length > self.maximum_payload {
return Err(Error::MaximumPacketExceeded);
}
let grant_result = self
.prod_to_radio
.grant(header.payload_len() + EsbHeader::header_size());
let grant = grant_result.map_err(|err| match err {
_ => Error::InternalError,
})?;
Ok(PayloadW::new_from_app(grant, header))
}
#[inline]
pub fn start_tx(&mut self) {
NVIC::pend(Interrupt::RADIO)
}
pub fn msg_ready(&mut self) -> bool {
self.cons_from_radio.read().is_ok()
}
pub fn read_packet(&mut self) -> Option<PayloadR<IN>> {
self.cons_from_radio.read().ok().map(PayloadR::new)
}
pub async fn wait_read_packet(&mut self) -> PayloadR<IN> {
PayloadR::new(self.cons_from_radio.wait_read().await)
}
#[inline]
pub fn maximum_payload_size(&self) -> usize {
self.maximum_payload.into()
}
}
pub struct Addresses {
pub(crate) base0: [u8; 4],
pub(crate) base1: [u8; 4],
pub(crate) prefixes0: [u8; 4],
pub(crate) prefixes1: [u8; 4],
pub(crate) rf_channel: u8,
}
impl Addresses {
pub fn new(
base0: [u8; 4],
base1: [u8; 4],
prefixes0: [u8; 4],
prefixes1: [u8; 4],
rf_channel: u8,
) -> Result<Self, Error> {
if rf_channel > 100 {
return Err(Error::InvalidParameters);
}
Ok(Self {
base0,
base1,
prefixes0,
prefixes1,
rf_channel,
})
}
}
impl Default for Addresses {
fn default() -> Self {
Self {
base0: [0xE7, 0xE7, 0xE7, 0xE7],
base1: [0xC2, 0xC2, 0xC2, 0xC2],
prefixes0: [0xE7, 0xC2, 0xC3, 0xC4],
prefixes1: [0xC5, 0xC6, 0xC7, 0xC8],
rf_channel: 2,
}
}
}