From 63f298d020069aab725e688fc929adee6d0b7851 Mon Sep 17 00:00:00 2001 From: Stephen D <webmaster@scd31.com> Date: Wed, 29 Nov 2023 17:51:57 -0400 Subject: [PATCH] add random delays before txing --- Cargo.lock | 12 +++++++++- Cargo.toml | 3 ++- src/main.rs | 8 +++---- src/radio.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd0b5a9..d39bb5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -84,6 +84,7 @@ dependencies = [ "nmea", "num-traits", "panic-semihosting", + "rand", "rf4463", "stm32f4xx-hal", "systick-monotonic", @@ -306,7 +307,7 @@ dependencies = [ [[package]] name = "ham-cats" version = "0.1.0" -source = "git+https://gitlab.scd31.com/cats/ham-cats/#81e90ddc21a4aa0e56acd05a18edb658593cf434" +source = "git+https://gitlab.scd31.com/cats/ham-cats#81e90ddc21a4aa0e56acd05a18edb658593cf434" dependencies = [ "arrayvec", "bitvec", @@ -515,6 +516,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + [[package]] name = "rand_core" version = "0.6.4" diff --git a/Cargo.toml b/Cargo.toml index a888f86..fd23dba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ panic-semihosting = "0.6" rf4463 = { git = "https://gitlab.scd31.com/stephen/rf4463-lib" } #rf4463 = { path = "../../rf4463" } systick-monotonic = "1.0.1" -ham-cats = { git = "https://gitlab.scd31.com/cats/ham-cats/" } +ham-cats = { git = "https://gitlab.scd31.com/cats/ham-cats" } half = { version = "2.3.1", default-features = false } # TODO can get rid of some of these features nmea = { version = "0.6.0", default-features = false, features = ["VTG", "GGA", "RMC", "GNS", "GLL"] } @@ -32,4 +32,5 @@ usb-device = "0.2.9" crc = "3.0.1" embedded-storage = "0.2.0" num-traits = { version = "0.2.17", default-features = false, features = ["libm"] } +rand = { version = "0.8", default_features = false, features = ["small_rng"] } # TODO need to add panic-reset at some point \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 626bfe5..661aa2f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ mod status; mod voltage; pub const MAX_PACKET_LEN: usize = 8191; +pub const SYS_TICK_FREQ: u32 = 1000; #[rtic::app(device = stm32f4xx_hal::pac, peripherals = true, dispatchers = [USART6])] mod app { @@ -45,7 +46,7 @@ mod app { shell::Shell, status::Status, voltage::VoltMeter, - MAX_PACKET_LEN, + MAX_PACKET_LEN, SYS_TICK_FREQ, }; const SYS_CLK: u32 = 84_000_000; @@ -59,7 +60,7 @@ mod app { }; #[monotonic(binds = SysTick, default = true)] - type MyMono = Systick<10_000>; + type MyMono = Systick<{ SYS_TICK_FREQ }>; #[local] struct Local { @@ -117,7 +118,6 @@ mod app { green.set_low(); // setup volt meter - let volt_pin = gpioc.pc0.into_analog(); let volt_adc = Adc::adc1(dp.ADC1, true, AdcConfig::default()); let volt_meter = VoltMeter::new(volt_pin, volt_adc); @@ -145,7 +145,7 @@ mod app { let spi = Spi::new(dp.SPI1, (sclk, miso, mosi), MODE, 10.MHz(), &clocks); let buf = singleton!(: [u8; MAX_PACKET_LEN] = [0; MAX_PACKET_LEN]).unwrap(); - let radio = RadioManager::new(spi, sdn, cs, delay, buf, config.enable_digipeating); + let radio = RadioManager::new(spi, sdn, cs, delay, buf, &config); radio }; diff --git a/src/radio.rs b/src/radio.rs index fcc6692..69af6e4 100644 --- a/src/radio.rs +++ b/src/radio.rs @@ -1,4 +1,5 @@ use ham_cats::{buffer::Buffer, packet::Packet}; +use rand::{rngs::SmallRng, Rng, SeedableRng}; use rf4463::{config::RADIO_CONFIG_CATS, error::TransferError, Rf4463}; use rtic::Mutex; use stm32f4xx_hal::{ @@ -8,8 +9,9 @@ use stm32f4xx_hal::{ spi::{self, Spi}, timer::Delay, }; +use systick_monotonic::fugit::Duration; -use crate::MAX_PACKET_LEN; +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>; @@ -20,6 +22,7 @@ pub struct RadioManager<'a> { radio: Radio, buf: &'a mut [u8; MAX_PACKET_LEN], enable_digipeating: bool, + rng: SmallRng, } impl<'a> RadioManager<'a> { @@ -29,7 +32,7 @@ impl<'a> RadioManager<'a> { cs: CsPin, delay: MyDelay, buf: &'a mut [u8; MAX_PACKET_LEN], - enable_digipeating: bool, + config: &Config, ) -> Option<Self> { let mut radio = Rf4463::new(spi, sdn, cs, delay, &mut RADIO_CONFIG_CATS.clone()).ok()?; @@ -38,10 +41,15 @@ impl<'a> RadioManager<'a> { radio.start_rx(None, false).ok()?; + 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); + Some(Self { radio, buf, enable_digipeating, + rng, }) } @@ -92,10 +100,10 @@ impl<'a> RadioManager<'a> { data: &[u8], ident: Option<(&str, u8)>, ) -> Option<()> { - // don't want to transmit on top of a packet - while self.radio.is_busy_rxing().ok()? { - self.tick(led, ident).ok()?; - } + // 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)?; led.lock(|l| l.set_high().ok()); self.radio.start_tx(data).ok()?; @@ -108,6 +116,37 @@ impl<'a> RadioManager<'a> { Some(()) } + 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, @@ -128,3 +167,16 @@ impl<'a> RadioManager<'a> { } } } + +fn rand_seed_from_str(s: &str) -> u64 { + let mut out = 0; + + for (i, &b) in s.as_bytes().iter().enumerate() { + let i = i % 4; + let b: u64 = b.into(); + + out ^= b << (i * 8); + } + + out +} -- GitLab