Newer
Older
use rf4463::{config::RADIO_CONFIG_CATS, error::TransferError, Rf4463};
use crate::{app::monotonics::MyMono::now, config::Config, MAX_PACKET_LEN, SYS_TICK_FREQ};
type SdnPin = gpio::Pin<'B', 12, gpio::Output>;
type CsPin = gpio::Pin<'A', 8, gpio::Output>;
type MyDelay = Delay<TIM5, 1000000>;
type Radio = Rf4463<Spi<SPI1>, SdnPin, CsPin, MyDelay>;
pub struct RadioManager<'a> {
}
impl<'a> RadioManager<'a> {
pub fn new(
spi: Spi<SPI1>,
sdn: SdnPin,
cs: CsPin,
delay: MyDelay,
buf: &'a mut [u8; MAX_PACKET_LEN],
) -> Option<Self> {
let mut radio = Rf4463::new(spi, sdn, cs, delay, &mut RADIO_CONFIG_CATS.clone()).ok()?;
// sets us up for the default CATS frequency, 430.500 MHz
radio.set_channel(20);
let enable_digipeating = config.enable_digipeating;
let seed = rand_seed_from_str(&config.callsign) ^ u64::from(config.ssid);
let rng = SmallRng::seed_from_u64(seed);
})
}
// call me every 20-ish ms
// technically needs to be every 100ms, tops
// digipeats only if ident is Some,
// otherwise the packet is discarded
pub fn tick<P: OutputPin, M: Mutex<T = P>>(
&mut self,
led: &mut M,
ident: Option<(&str, u8)>,
) -> Result<(), TransferError<spi::Error>> {
if let Some(data) = self
.radio
.finish_rx(self.buf)
.map_err(TransferError::SpiError)?
{
if self.enable_digipeating {
if let Some((callsign, ssid)) = ident {
// digipeats only if ident is Some,
// otherwise the rx'd packet is discarded
pub fn tx<P: OutputPin, M: Mutex<T = P>>(
&mut self,
led: &mut M,
data: &[u8],
ident: Option<(&str, u8)>,
) -> Option<()> {
// ensures we don't tx over a packet,
// and adds some random delay so that every node
// if offset slightly
self.tx_delay(led, ident)?;
self.radio.start_tx(data).ok()?;
while !self.radio.is_idle() {
self.radio.interrupt(None, Some(data)).ok();
}
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
fn tx_delay<P: OutputPin, M: Mutex<T = P>>(
&mut self,
led: &mut M,
ident: Option<(&str, u8)>,
) -> Option<()> {
loop {
let delay_ms = self.rng.gen_range(0..50);
let mut rx = false;
let thres = now() + Duration::<u64, 1, { SYS_TICK_FREQ }>::millis(delay_ms);
while now() < thres {
self.tick(led, ident).ok()?;
while self.radio.is_busy_rxing().ok()? {
rx = true;
self.tick(led, ident).ok()?;
}
if rx {
// if we rx'd a packet, we need to draw a new random time and start again
break;
}
}
if !rx {
// didn't an rx packet, so we're safe to leave
break Some(());
}
}
}
fn handle_packet_rx<P: OutputPin, M: Mutex<T = P>>(
&mut self,
led: &mut M,
mut packet: Packet<MAX_PACKET_LEN>,
callsign: &str,
ssid: u8,
) {
if packet.should_digipeat(callsign, ssid).is_ok() {
if packet.append_to_route(callsign, ssid).is_err() {
let mut buf = [0; MAX_PACKET_LEN];
let mut buf = Buffer::new_empty(&mut buf);
if packet.fully_encode(&mut buf).is_ok() {
self.tx(led, &buf, None);