diff options
Diffstat (limited to 'sw/picardy/src/main.rs')
-rw-r--r-- | sw/picardy/src/main.rs | 238 |
1 files changed, 160 insertions, 78 deletions
diff --git a/sw/picardy/src/main.rs b/sw/picardy/src/main.rs index 6d1d803..ffe5a47 100644 --- a/sw/picardy/src/main.rs +++ b/sw/picardy/src/main.rs @@ -43,7 +43,6 @@ use stm32f1xx_hal::{ }; use embedded_hal::digital::v2::OutputPin; -#[cfg(feature = "cw")] use embedded_hal::digital::v2::InputPin; use hd44780_driver::{Cursor, CursorBlink, Display, DisplayMode, HD44780}; @@ -55,8 +54,23 @@ pub mod log10f; use state::*; -const TICKS_PER_SECOND : u32 = 50; +const TICKS_PER_SECOND : u32 = 100; + +struct SharedWithISR { + state : State, + last_sequence_state_change : u32, + cw_ptt_timestamp : u32, + ui : ui::UI, + cw_pwm: cw::CWPWM, + cw_paddle_tip: gpio::gpiob::PB8<gpio::Input<gpio::PullUp>>, + seq0n: gpio::gpiob::PB3<gpio::Output<gpio::PushPull>>, + seq1_pa: gpio::gpiob::PB4<gpio::Output<gpio::PushPull>>, + seq2_switch: gpio::gpiob::PB5<gpio::Output<gpio::PushPull>>, + mute_spkr : gpio::gpioa::PA2<gpio::Output<gpio::PushPull>>, + mute_micn : gpio::gpioa::PA1<gpio::Output<gpio::PushPull>>, +} +static mut SHARED: MaybeUninit<SharedWithISR> = MaybeUninit::uninit(); static mut CLOCK_TIMER: MaybeUninit<CountDownTimer<pac::TIM2>> = MaybeUninit::uninit(); static mut TICK_COUNTER: MaybeUninit<u32> = MaybeUninit::uninit(); @@ -64,10 +78,14 @@ fn ticks_now() -> u32 { cortex_m::interrupt::free(|_cs| unsafe { *TICK_COUNTER.as_ptr() }) } +fn get_state_copy() -> State { + cortex_m::interrupt::free(|_cs| unsafe { + (*SHARED.as_ptr()).state.clone() + }) +} + #[cortex_m_rt::entry] fn main() -> ! { - let mut state = State::new(); - let cp = cortex_m::Peripherals::take().unwrap(); let dp = pac::Peripherals::take().unwrap(); @@ -94,22 +112,19 @@ fn main() -> ! { let pb13 = gpiob.pb13.into_pull_up_input(&mut gpiob.crh); // BTN3 Button G let pc15 = gpioc.pc15.into_pull_up_input(&mut gpioc.crh); let adc1 = dp.ADC1; - let mut ui = ui::UI::new(mic_sw1, mic_sw2, pb0, pb1, adc1, &mut rcc.apb2, &clocks, pb12, pb13, pc15); + let ui = ui::UI::new(mic_sw1, mic_sw2, pb0, pb1, adc1, &mut rcc.apb2, &clocks, pb12, pb13, pc15); - -#[cfg(feature = "cw")] - let (mut cwpwm, cw_paddle_tip) = { + let (cw_pwm, cw_paddle_tip) = { let pa8 = gpioa.pa8.into_alternate_push_pull(&mut gpioa.crh); // CW PWM output using TIM1 Ch1 let tim1 = Timer::tim1(dp.TIM1, &clocks, &mut rcc.apb2); - let cwpwm = cw::CWPWM::new(pa8, tim1, &mut afio.mapr); + let cw_pwm = cw::CWPWM::new(pa8, tim1, &mut afio.mapr); let cw_paddle_tip = gpiob.pb8.into_pull_up_input(&mut gpiob.crh); // CW paddle tip - (cwpwm, cw_paddle_tip) + (cw_pwm, cw_paddle_tip) }; let mut s_meter = gpioa.pa5.into_analog(&mut gpioa.crl); let mut adc2 = adc::Adc::adc2(dp.ADC2, &mut rcc.apb2, clocks); let mut last_s_meter_update_time = 0; - let mut last_sequence_state_change = 0; // Configure PB14 as output. (LED) let mut led = gpiob.pb14.into_push_pull_output(&mut gpiob.crh); @@ -117,12 +132,13 @@ fn main() -> ! { let (pa15, pb3, pb4) = afio.mapr.disable_jtag(gpioa.pa15, gpiob.pb3, gpiob.pb4); let _cw_key_n = pa15.into_push_pull_output_with_state(&mut gpioa.crh, gpio::State::High); // TODO output - let mut seq0n = pb3.into_push_pull_output_with_state(&mut gpiob.crl, gpio::State::High); - let mut seq1_pa = pb4.into_push_pull_output_with_state(&mut gpiob.crl, gpio::State::Low); - let mut seq2_switch = gpiob.pb5.into_push_pull_output_with_state(&mut gpiob.crl, gpio::State::Low); - let mut mute_spkr = gpioa.pa2.into_push_pull_output_with_state(&mut gpioa.crl, gpio::State::Low); - let mut mute_micn = gpioa.pa1.into_push_pull_output_with_state(&mut gpioa.crl, gpio::State::Low); + let seq0n = pb3.into_push_pull_output_with_state(&mut gpiob.crl, gpio::State::High); + let seq1_pa = pb4.into_push_pull_output_with_state(&mut gpiob.crl, gpio::State::Low); + let seq2_switch = gpiob.pb5.into_push_pull_output_with_state(&mut gpiob.crl, gpio::State::Low); + + let mute_spkr = gpioa.pa2.into_push_pull_output_with_state(&mut gpioa.crl, gpio::State::Low); + let mute_micn = gpioa.pa1.into_push_pull_output_with_state(&mut gpioa.crl, gpio::State::Low); let c1 = gpioa.pa6; let c2 = gpioa.pa7; @@ -192,10 +208,23 @@ fn main() -> ! { ); let i2c_busmanager = shared_bus::BusManagerSimple::new(i2c); - let mut siclock = si_clock::SiClock::new(i2c_busmanager.acquire_i2c(), state.bfo(), state.vfo()); + + let mut siclock = { + let shared = unsafe { &mut *SHARED.as_mut_ptr() }; + *shared = SharedWithISR { + state : State::new(), + last_sequence_state_change : 0, + cw_ptt_timestamp : 0, + ui, + cw_pwm, + cw_paddle_tip, seq0n, seq1_pa, seq2_switch, mute_spkr, mute_micn + }; + + si_clock::SiClock::new(i2c_busmanager.acquire_i2c(), shared.state.bfo(), shared.state.vfo()) + }; let mut last_s_meter_value = 0; - ui::update_disp(&mut lcd, &state, &mut delay, last_s_meter_value); + ui::update_disp(&mut lcd, &get_state_copy(), &mut delay, last_s_meter_value, false); let mut last_encoder_count = qei.count(); @@ -213,8 +242,12 @@ fn main() -> ! { unsafe { pac::NVIC::unmask(pac::Interrupt::TIM2); } + let mut last_disp_update_counter = 1; loop { let mut update_disp_required = false; + let mut bfo_tune_fail = false; + + let state = get_state_copy(); let previous_vfo = state.vfo(); let previous_bfo = state.bfo(); @@ -223,75 +256,35 @@ fn main() -> ! { if encoder_count != last_encoder_count { let delta = encoder_count.wrapping_sub(last_encoder_count); let delta = if delta > 0x7FFF { delta as i32 - 0x10000 } else { delta as i32 }; - let require_bfo_update = ui.update_encoder(&mut state, delta); + + let require_bfo_update = cortex_m::interrupt::free(|_cs| { + let shared = unsafe { &mut *SHARED.as_mut_ptr() }; + shared.ui.update_encoder(&mut shared.state, delta) + }); + if require_bfo_update { - state.bfo_tune_fail = !siclock.set_bfo(state.bfo()).is_ok(); + bfo_tune_fail = !siclock.set_bfo(state.bfo()).is_ok(); } siclock.set_vfo(state.vfo()); update_disp_required = true; } - let button_result = ui.handle_buttons(&mut state); - if previous_bfo != state.bfo() { - state.bfo_tune_fail = !siclock.set_bfo(state.bfo()).is_ok(); + bfo_tune_fail = !siclock.set_bfo(state.bfo()).is_ok(); } if previous_vfo != state.vfo() { siclock.set_vfo(state.vfo()); } - update_disp_required |= button_result.display_update; - - let next_state = match state.sequence_state { + match state.sequence_state { SequenceState::Rx => { led.set_high().unwrap(); - - mute_spkr.set_low().unwrap(); - mute_micn.set_low().unwrap(); - seq2_switch.set_low().unwrap(); - seq0n.set_high().unwrap(); - - if button_result.ptt { - SequenceState::Switching - } - else { - SequenceState::Rx - } - }, - SequenceState::Switching => { - mute_spkr.set_high().unwrap(); - mute_micn.set_high().unwrap(); - seq2_switch.set_high().unwrap(); - seq0n.set_low().unwrap(); - seq1_pa.set_low().unwrap(); - - if button_result.ptt { - SequenceState::Tx - } - else { - SequenceState::Rx - } }, + SequenceState::Switching => {} SequenceState::Tx => { led.set_low().unwrap(); - - seq1_pa.set_high().unwrap(); - if button_result.ptt { - SequenceState::Tx - } - else { - SequenceState::Switching - } - }, - }; - - let t_now = ticks_now(); - const SWITCHING_DELAY : u32 = TICKS_PER_SECOND * 200 / 1000; - if state.sequence_state != next_state && - last_sequence_state_change + SWITCHING_DELAY <= t_now { - state.sequence_state = next_state; - last_sequence_state_change = t_now; + } } let s_meter_value: u16 = adc2.read(&mut s_meter).unwrap(); @@ -302,26 +295,24 @@ fn main() -> ! { // ADC is 12-bit, convert to dB full-scale let s_meter_value = 10f32 * log10f::log10f(f32::from(s_meter_value) / 4092f32); let s_meter_value = s_meter_value as i32; + let t_now = ticks_now(); if last_s_meter_update_time + 10 < t_now { update_disp_required = s_meter_value != last_s_meter_value; last_s_meter_value = s_meter_value; last_s_meter_update_time = t_now; } + if last_disp_update_counter != state.update_disp_counter { + update_disp_required = true; + last_disp_update_counter = state.update_disp_counter; + } + if update_disp_required { - ui::update_disp(&mut lcd, &state, &mut delay, s_meter_value); + ui::update_disp(&mut lcd, &state, &mut delay, s_meter_value, bfo_tune_fail); } last_encoder_count = encoder_count; -#[cfg(feature = "cw")] - if cw_paddle_tip.is_low().unwrap() { - cwpwm.on(); - } - else { - cwpwm.off(); - } - cortex_m::asm::wfi(); } } @@ -333,6 +324,97 @@ fn TIM2() { let ticks = unsafe { &mut *TICK_COUNTER.as_mut_ptr() }; *ticks += 1; + + let mut shared = unsafe { &mut *SHARED.as_mut_ptr() }; + let button_result = shared.ui.handle_buttons(&mut shared.state); + + if button_result.display_update { + shared.state.update_disp_counter += 1; + } + + let cw_paddle_tip_low = shared.cw_paddle_tip.is_low().unwrap(); + + const CW_PTT_DELAY : u32 = TICKS_PER_SECOND * 800 / 1000; + let cw_ptt = if shared.state.mode == Mode::CW { + if cw_paddle_tip_low { + shared.cw_ptt_timestamp = *ticks; + true + } + else { + shared.cw_ptt_timestamp + CW_PTT_DELAY > *ticks + } + } + else { + false + }; + + let cw_beep = shared.state.mode == Mode::CW && cw_paddle_tip_low; + + let next_state = match shared.state.sequence_state { + SequenceState::Rx => { + shared.mute_spkr.set_low().unwrap(); + shared.mute_micn.set_low().unwrap(); + shared.seq2_switch.set_low().unwrap(); + shared.seq0n.set_high().unwrap(); + shared.cw_pwm.off(); + + if button_result.ptt || cw_ptt { + SequenceState::Switching + } + else { + SequenceState::Rx + } + }, + SequenceState::Switching => { + shared.mute_spkr.set_high().unwrap(); + shared.seq2_switch.set_high().unwrap(); + shared.seq0n.set_low().unwrap(); + shared.seq1_pa.set_low().unwrap(); + + if cw_beep { + shared.cw_pwm.on(); + } + else { + shared.cw_pwm.off(); + } + + if button_result.ptt { + shared.mute_micn.set_high().unwrap(); + SequenceState::Tx + } + else if cw_ptt { + shared.mute_micn.set_low().unwrap(); + SequenceState::Tx + } + else { + SequenceState::Rx + } + }, + SequenceState::Tx => { + shared.seq1_pa.set_high().unwrap(); + + if cw_beep { + shared.cw_pwm.on(); + } + else { + shared.cw_pwm.off(); + } + + if button_result.ptt || cw_ptt { + SequenceState::Tx + } + else { + SequenceState::Switching + } + }, + }; + + const SWITCHING_DELAY : u32 = TICKS_PER_SECOND * 20 / 1000; + if shared.state.sequence_state != next_state && + shared.last_sequence_state_change + SWITCHING_DELAY <= *ticks { + shared.state.sequence_state = next_state; + shared.last_sequence_state_change = *ticks; + } } #[cortex_m_rt::exception] |