From 8d45f098b818206d3d91152f92175cbea0b56c8e Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Thu, 24 Dec 2020 17:41:49 +0100 Subject: Add disabled CW, replace sequencer, ticks and set VFO/BFO logic --- sw/demo1/src/main.rs | 2 +- sw/picardy/Cargo.toml | 6 +++ sw/picardy/src/cw.rs | 35 +++++++++++++++++ sw/picardy/src/main.rs | 102 ++++++++++++++++++++++++++++++------------------ sw/picardy/src/state.rs | 9 +---- sw/picardy/src/ui.rs | 8 ++-- 6 files changed, 112 insertions(+), 50 deletions(-) create mode 100644 sw/picardy/src/cw.rs (limited to 'sw') diff --git a/sw/demo1/src/main.rs b/sw/demo1/src/main.rs index 4e6e5c6..09f51fa 100644 --- a/sw/demo1/src/main.rs +++ b/sw/demo1/src/main.rs @@ -34,7 +34,7 @@ use stm32f1xx_hal::{ pac, i2c::{BlockingI2c, Mode}, delay::Delay, - timer::{Timer}, + timer::Timer, }; use embedded_hal::digital::v2::{OutputPin, ToggleableOutputPin}; diff --git a/sw/picardy/Cargo.toml b/sw/picardy/Cargo.toml index e773d57..e2192f6 100644 --- a/sw/picardy/Cargo.toml +++ b/sw/picardy/Cargo.toml @@ -5,6 +5,12 @@ authors = ["Matthias P. Braendli "] edition = "2018" license = "MIT" +[features] +default = [] + +# Enable CW transmit +cw = [] + [dependencies] arrayvec = { version = "0.5", default-features = false, features = [] } # alloc-cortex-m = "0.3" # requires nightly diff --git a/sw/picardy/src/cw.rs b/sw/picardy/src/cw.rs new file mode 100644 index 0000000..ce99e39 --- /dev/null +++ b/sw/picardy/src/cw.rs @@ -0,0 +1,35 @@ +//! CW output using PWM on PA8, TIM1 CH1 + +use stm32f1xx_hal::{ + prelude::*, + timer, + pac::TIM1, + gpio::gpioa::*, + gpio::{Alternate, PushPull}, + afio::MAPR, + pwm, +}; + +pub struct CWPWM { + channel : pwm::PwmChannel, +} + +impl CWPWM { + pub fn new(pa8: PA8>, tim1: timer::Timer, mapr: &mut MAPR) -> Self { + let pwm = tim1.pwm(pa8, mapr, 400.hz()); + let mut channel = pwm.split(); + channel.enable(); + channel.set_duty(0); + CWPWM { channel } + } + + pub fn on(&mut self) { + let max = self.channel.get_max_duty(); + self.channel.set_duty(max / 2); + } + + pub fn off(&mut self) { + self.channel.set_duty(0); + } +} + diff --git a/sw/picardy/src/main.rs b/sw/picardy/src/main.rs index b5efbdd..6d1d803 100644 --- a/sw/picardy/src/main.rs +++ b/sw/picardy/src/main.rs @@ -43,20 +43,25 @@ 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}; pub mod ui; +pub mod cw; pub mod state; pub mod si_clock; pub mod log10f; use state::*; +const TICKS_PER_SECOND : u32 = 50; + static mut CLOCK_TIMER: MaybeUninit> = MaybeUninit::uninit(); -static mut DECISECONDS_COUNTER: MaybeUninit = MaybeUninit::uninit(); +static mut TICK_COUNTER: MaybeUninit = MaybeUninit::uninit(); -fn time_now() -> usize { - cortex_m::interrupt::free(|_cs| unsafe { *DECISECONDS_COUNTER.as_ptr() }) +fn ticks_now() -> u32 { + cortex_m::interrupt::free(|_cs| unsafe { *TICK_COUNTER.as_ptr() }) } #[cortex_m_rt::entry] @@ -91,6 +96,16 @@ fn main() -> ! { let adc1 = dp.ADC1; let mut 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 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_paddle_tip = gpiob.pb8.into_pull_up_input(&mut gpiob.crh); // CW paddle tip + (cwpwm, 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; @@ -185,14 +200,14 @@ fn main() -> ! { let mut last_encoder_count = qei.count(); { - let deciseconds_counter = unsafe { &mut *DECISECONDS_COUNTER.as_mut_ptr() }; - *deciseconds_counter = 0; + let ticks = unsafe { &mut *TICK_COUNTER.as_mut_ptr() }; + *ticks = 0; } { let timer = unsafe { &mut *CLOCK_TIMER.as_mut_ptr() }; *timer = Timer::tim2(dp.TIM2, &clocks, &mut rcc.apb1) - .start_count_down(50.hz()); + .start_count_down(TICKS_PER_SECOND.hz()); timer.listen(Event::Update); } @@ -201,6 +216,9 @@ fn main() -> ! { loop { let mut update_disp_required = false; + let previous_vfo = state.vfo(); + let previous_bfo = state.bfo(); + let encoder_count : u16 = qei.count(); if encoder_count != last_encoder_count { let delta = encoder_count.wrapping_sub(last_encoder_count); @@ -215,63 +233,63 @@ fn main() -> ! { let button_result = ui.handle_buttons(&mut state); - if button_result.bfo_update { + if previous_bfo != state.bfo() { state.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 { 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 { - mute_spkr.set_high().unwrap(); - mute_micn.set_high().unwrap(); - seq2_switch.set_high().unwrap(); - SequenceState::ToTxStep1 + SequenceState::Switching } else { - mute_spkr.set_low().unwrap(); - mute_micn.set_low().unwrap(); SequenceState::Rx } }, - SequenceState::ToTxStep1 => { - led.set_low().unwrap(); + SequenceState::Switching => { + mute_spkr.set_high().unwrap(); + mute_micn.set_high().unwrap(); + seq2_switch.set_high().unwrap(); seq0n.set_low().unwrap(); - SequenceState::ToTxStep2 - }, - SequenceState::ToTxStep2 => { - led.set_high().unwrap(); - seq1_pa.set_high().unwrap(); - SequenceState::Tx + seq1_pa.set_low().unwrap(); + + if button_result.ptt { + SequenceState::Tx + } + else { + SequenceState::Rx + } }, SequenceState::Tx => { led.set_low().unwrap(); + + seq1_pa.set_high().unwrap(); if button_result.ptt { SequenceState::Tx } else { - seq1_pa.set_low().unwrap(); - SequenceState::ToRxStep1 + SequenceState::Switching } }, - SequenceState::ToRxStep1 => { - seq0n.set_high().unwrap(); - led.set_high().unwrap(); - SequenceState::ToRxStep2 - }, - SequenceState::ToRxStep2 => { - led.set_low().unwrap(); - seq2_switch.set_low().unwrap(); - SequenceState::Rx - } }; - let t_now = time_now(); + let t_now = ticks_now(); + const SWITCHING_DELAY : u32 = TICKS_PER_SECOND * 200 / 1000; if state.sequence_state != next_state && - last_sequence_state_change + 1 <= t_now { - update_disp_required = true; + last_sequence_state_change + SWITCHING_DELAY <= t_now { state.sequence_state = next_state; last_sequence_state_change = t_now; } @@ -296,6 +314,14 @@ fn main() -> ! { last_encoder_count = encoder_count; +#[cfg(feature = "cw")] + if cw_paddle_tip.is_low().unwrap() { + cwpwm.on(); + } + else { + cwpwm.off(); + } + cortex_m::asm::wfi(); } } @@ -305,8 +331,8 @@ fn TIM2() { let timer = unsafe { &mut *CLOCK_TIMER.as_mut_ptr() }; timer.clear_update_interrupt_flag(); - let deciseconds_counter = unsafe { &mut *DECISECONDS_COUNTER.as_mut_ptr() }; - *deciseconds_counter += 1; + let ticks = unsafe { &mut *TICK_COUNTER.as_mut_ptr() }; + *ticks += 1; } #[cortex_m_rt::exception] diff --git a/sw/picardy/src/state.rs b/sw/picardy/src/state.rs index bfe0212..ed99087 100644 --- a/sw/picardy/src/state.rs +++ b/sw/picardy/src/state.rs @@ -34,18 +34,13 @@ pub enum FilterShift { #[derive(PartialEq, Eq)] pub enum SequenceState { Rx, - ToTxStep1, - ToTxStep2, + Switching, Tx, - ToRxStep1, - ToRxStep2, } impl SequenceState { fn apply_rit(&self) -> bool { - *self == SequenceState::Rx || - *self == SequenceState::ToRxStep1 || - *self == SequenceState::ToRxStep2 + *self == SequenceState::Rx } } diff --git a/sw/picardy/src/ui.rs b/sw/picardy/src/ui.rs index 0d42f88..1133582 100644 --- a/sw/picardy/src/ui.rs +++ b/sw/picardy/src/ui.rs @@ -92,7 +92,6 @@ impl fmt::Display for ButtonState { #[derive(Default)] pub struct ButtonResult { - pub bfo_update : bool, pub display_update : bool, pub ptt : bool, } @@ -206,7 +205,6 @@ impl UI { state.ui_sel = new_ui_sel; state.filter_shift = new_filter_shift; - result.bfo_update = true; result.display_update = true; } @@ -227,7 +225,6 @@ impl UI { }, UISelection::IFShift => { state.filter_shift = FilterShift::USB; - result.bfo_update = true; }, } @@ -273,7 +270,10 @@ pub fn update_disp(lcd: &mut HD44780, state: write!(string, "{:<03}.{:<03} ", disp_freq / 1000, disp_freq % 1000).unwrap(); write!(string, "{}{:<03}", if state.rit >= 0 { "+" } else { "-" }, state.rit.abs()/10).unwrap(); - write!(string, "S{:3}", s_meter_value).unwrap(); + if string.len() <= 16 - 4 { + // Avoids crash when frequency is very negative + write!(string, "S{:3}", s_meter_value).unwrap(); + } lcd.set_cursor_pos(0, delay).unwrap(); lcd.write_str(&string, delay).unwrap(); -- cgit v1.2.3