aboutsummaryrefslogtreecommitdiffstats
path: root/sw/picardy/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'sw/picardy/src/main.rs')
-rw-r--r--sw/picardy/src/main.rs238
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]