diff --git a/src/application/mod.rs b/src/application/mod.rs index 998aec1..a0699e1 100644 --- a/src/application/mod.rs +++ b/src/application/mod.rs @@ -1,10 +1,12 @@ -use cortex_m::prelude::*; +use cortex_m::{asm::wfi, prelude::*}; use embedded_hal::digital::v2::{OutputPin, ToggleableOutputPin}; use nb::{self, block}; use nmea0183::{ParseResult, Parser}; use stm32f1xx_hal::{ delay::Delay, - gpio::{gpiob, gpioc, Alternate, Floating, Input, Output, PushPull}, + gpio::{gpiob, gpioc, Alternate, Floating, Input, OpenDrain, Output, PushPull}, + i2c::BlockingI2c, + pac::I2C1, prelude::*, serial::Serial, stm32, @@ -18,6 +20,28 @@ pub use setup::setup; use crate::si5153; use crate::time; +use crate::wspr; + +pub struct App { + delay: Delay, + board_led: gpioc::PC13>, + serial: Serial< + stm32::USART3, + ( + gpiob::PB10>, + gpiob::PB11>, + ), + >, + i2c: BlockingI2c< + I2C1, + ( + gpiob::PB6>, + gpiob::PB7>, + ), + >, + gps_parser: Parser, + locator: arrayvec::ArrayString<6>, +} // For PLL with 800MHz const WSPR_SYMBOLS: [si5153::PllParams; 4] = [ @@ -51,28 +75,62 @@ const WSPR_SYMBOLS: [si5153::PllParams; 4] = [ }, ]; -pub struct App { - delay: Delay, - board_led: gpioc::PC13>, - serial: Serial< - stm32::USART3, - ( - gpiob::PB10>, - gpiob::PB11>, - ), - >, - gps_parser: Parser, - locator: arrayvec::ArrayString<6>, -} - impl App { pub fn run(mut self) -> ! { + let callsign = arrayvec::ArrayString::<6>::from("DL1SSK").unwrap(); + defmt::info!("Application Startup!"); - let mut last_ts = 0; + let mut si_pll = si5153::Si5153::new(&self.i2c); + si_pll.init(&mut self.i2c, 25000000, 800000000, 800000000); + si_pll.set_ms_source(&mut self.i2c, si5153::Multisynth::MS0, si5153::PLL::A); + + defmt::info!("PLL setup complete."); + + let mut transmitting = false; + let mut symbol_start = time::get(); + let mut symbol_idx: usize = 0; + let mut message: [u8; 162] = [0; 162]; loop { self.poll_gps(); + + if !transmitting { + let ts = time::get(); + if self.locator.len() > 0 + && ts.minutes % 2 == 0 + && ts.seconds > 1.0 + && ts.seconds < 2.0 + { + defmt::info!("Starting tranmission"); + message = wspr::encode_message(&callsign, &self.locator, 27); + symbol_start = ts; + symbol_idx = 0; + si_pll.write_synth_params( + &mut self.i2c, + si5153::Multisynth::MS0, + &WSPR_SYMBOLS[message[symbol_idx] as usize], + ); + si_pll.enable_ms_output(&mut self.i2c, si5153::Multisynth::MS0); + } + } else { + let ts = time::get(); + if (ts.seconds - symbol_start.seconds) >= 0.683 { + symbol_start = ts; + symbol_idx += 1; + if symbol_idx < 162 { + si_pll.write_synth_params( + &mut self.i2c, + si5153::Multisynth::MS0, + &WSPR_SYMBOLS[message[symbol_idx] as usize], + ); + } else { + si_pll.disable_ms_output(&mut self.i2c, si5153::Multisynth::MS0); + transmitting = false; + } + } + } + wfi(); } //exit(); diff --git a/src/application/setup.rs b/src/application/setup.rs index 42f57ef..d8a1974 100644 --- a/src/application/setup.rs +++ b/src/application/setup.rs @@ -1,5 +1,6 @@ use stm32f1xx_hal::{ delay::Delay, + i2c, pac::Interrupt, prelude::*, serial::{Config, Serial}, @@ -59,12 +60,30 @@ pub fn setup(cp: cortex_m::peripheral::Peripherals, dp: stm32::Peripherals) -> A let gps_parser = Parser::new(); + let scl = gpiob.pb6.into_alternate_open_drain(&mut gpiob.crl); + let sda = gpiob.pb7.into_alternate_open_drain(&mut gpiob.crl); + let mut i2c = i2c::BlockingI2c::i2c1( + dp.I2C1, + (scl, sda), + &mut afio.mapr, + i2c::Mode::Standard { + frequency: 400_000.hz(), + }, + clocks, + &mut rcc.apb1, + 5, + 1, + 5, + 5, + ); + time::setup(dp.TIM2, &clocks, &mut rcc.apb1); App { delay, board_led, serial, + i2c, gps_parser, locator: arrayvec::ArrayString::new(), } diff --git a/src/si5153.rs b/src/si5153.rs index b327448..b077da2 100644 --- a/src/si5153.rs +++ b/src/si5153.rs @@ -150,7 +150,7 @@ where } } - pub fn write_params(&self, i2c: &mut I2C, base: u8, params: &PllParams) { + fn write_params(&self, i2c: &mut I2C, base: u8, params: &PllParams) { let data: [u8; 9] = [ base, ((params.p3 & 0x00FF00) >> 8) as u8, @@ -168,4 +168,8 @@ where panic!("i2c write failed. regAdder: {}", base) } } + + pub fn write_synth_params(&self, i2c: &mut I2C, synth: Multisynth, params: &PllParams) { + self.write_params(i2c, synth.base_address(), params); + } } diff --git a/src/wspr.rs b/src/wspr.rs index cefd7d6..7e0eaeb 100644 --- a/src/wspr.rs +++ b/src/wspr.rs @@ -128,7 +128,7 @@ fn add_sync(symbols: &mut [u8; WSPR_LENGTH]) { } } -pub fn endcode_message( +pub fn encode_message( call_sign: &arrayvec::ArrayString<6>, locator: &arrayvec::ArrayString<6>, power: u8, diff --git a/testsuite/tests/wspr.rs b/testsuite/tests/wspr.rs index e364062..87759fa 100644 --- a/testsuite/tests/wspr.rs +++ b/testsuite/tests/wspr.rs @@ -15,7 +15,7 @@ mod tests { fn test_encoding() { let call_sign = ArrayString::<6>::from(" K1ABC").unwrap(); let loc = ArrayString::<6>::from("FN42").unwrap(); - let symbols = wspr::endcode_message(&call_sign, &loc, 37); + let symbols = wspr::encode_message(&call_sign, &loc, 37); let expected_symbols: [u8; 162] = [ 3, 3, 0, 0, 2, 0, 0, 0, 1, 0, 2, 0, 1, 3, 1, 2, 2, 2, 1, 0, 0, 3, 2, 3, 1, 3, 3, 2, 2,