aboutsummaryrefslogtreecommitdiffstats
path: root/sw/picardy/src/main.rs
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2021-01-31 20:41:01 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2021-01-31 20:41:01 +0100
commit536f36abca366d24ff863c3781b5a037c408c35b (patch)
tree438dad2ff550e8fad07a558f52909703f3420dcc /sw/picardy/src/main.rs
parent4c506aadc3f709d5bcc424630fa46ea50a840dfd (diff)
downloadpicardy-536f36abca366d24ff863c3781b5a037c408c35b.tar.gz
picardy-536f36abca366d24ff863c3781b5a037c408c35b.tar.bz2
picardy-536f36abca366d24ff863c3781b5a037c408c35b.zip
Add CW keyer
Diffstat (limited to 'sw/picardy/src/main.rs')
-rw-r--r--sw/picardy/src/main.rs160
1 files changed, 98 insertions, 62 deletions
diff --git a/sw/picardy/src/main.rs b/sw/picardy/src/main.rs
index ffe5a47..a6a3e4a 100644
--- a/sw/picardy/src/main.rs
+++ b/sw/picardy/src/main.rs
@@ -60,14 +60,18 @@ struct SharedWithISR {
state : State,
last_sequence_state_change : u32,
cw_ptt_timestamp : u32,
+ cw_key_n : gpio::gpioa::PA15<gpio::Output<gpio::OpenDrain>>,
ui : ui::UI,
cw_pwm: cw::CWPWM,
+ cw_keyer: cw::Keyer,
cw_paddle_tip: gpio::gpiob::PB8<gpio::Input<gpio::PullUp>>,
+ cw_paddle_ring: gpio::gpiob::PB9<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>>,
+ led : gpio::gpiob::PB14<gpio::Output<gpio::PushPull>>,
}
static mut SHARED: MaybeUninit<SharedWithISR> = MaybeUninit::uninit();
@@ -114,14 +118,15 @@ fn main() -> ! {
let adc1 = dp.ADC1;
let ui = ui::UI::new(mic_sw1, mic_sw2, pb0, pb1, adc1, &mut rcc.apb2, &clocks, pb12, pb13, pc15);
- let (cw_pwm, cw_paddle_tip) = {
+ let cw_pwm = {
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 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
- (cw_pwm, cw_paddle_tip)
+ cw::CWPWM::new(pa8, tim1, &mut afio.mapr)
};
+ let cw_paddle_tip = gpiob.pb8.into_pull_up_input(&mut gpiob.crh); // CW paddle tip
+ let cw_paddle_ring = gpiob.pb9.into_pull_up_input(&mut gpiob.crh); // CW paddle ring
+
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;
@@ -131,7 +136,7 @@ fn main() -> ! {
led.set_low().unwrap();
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 cw_key_n = pa15.into_open_drain_output_with_state(&mut gpioa.crh, gpio::State::High);
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);
@@ -215,9 +220,11 @@ fn main() -> ! {
state : State::new(),
last_sequence_state_change : 0,
cw_ptt_timestamp : 0,
+ cw_key_n,
ui,
cw_pwm,
- cw_paddle_tip, seq0n, seq1_pa, seq2_switch, mute_spkr, mute_micn
+ cw_keyer : cw::Keyer::new(12, TICKS_PER_SECOND),
+ cw_paddle_tip, cw_paddle_ring, seq0n, seq1_pa, seq2_switch, mute_spkr, mute_micn, led
};
si_clock::SiClock::new(i2c_busmanager.acquire_i2c(), shared.state.bfo(), shared.state.vfo())
@@ -243,15 +250,15 @@ fn main() -> ! {
unsafe { pac::NVIC::unmask(pac::Interrupt::TIM2); }
let mut last_disp_update_counter = 1;
+ let mut previous_vfo = 0;
+ let mut previous_bfo = 0;
+
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();
-
let encoder_count : u16 = qei.count();
if encoder_count != last_encoder_count {
let delta = encoder_count.wrapping_sub(last_encoder_count);
@@ -259,7 +266,11 @@ fn main() -> ! {
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)
+ let r = shared.ui.update_encoder(&mut shared.state, delta);
+ if let Mode::CW(CWMode::Iambic) = shared.state.mode {
+ shared.cw_keyer.set_speed(shared.state.cw_wpm, TICKS_PER_SECOND)
+ }
+ r
});
if require_bfo_update {
@@ -269,23 +280,17 @@ fn main() -> ! {
update_disp_required = true;
}
- if previous_bfo != state.bfo() {
- bfo_tune_fail = !siclock.set_bfo(state.bfo()).is_ok();
+ let bfo = state.bfo();
+ if previous_bfo != bfo {
+ bfo_tune_fail = !siclock.set_bfo(bfo).is_ok();
}
+ previous_bfo = bfo;
- if previous_vfo != state.vfo() {
- siclock.set_vfo(state.vfo());
- }
-
- match state.sequence_state {
- SequenceState::Rx => {
- led.set_high().unwrap();
- },
- SequenceState::Switching => {}
- SequenceState::Tx => {
- led.set_low().unwrap();
- }
+ let vfo = state.vfo();
+ if previous_vfo != vfo {
+ siclock.set_vfo(vfo);
}
+ previous_vfo = vfo;
let s_meter_value: u16 = adc2.read(&mut s_meter).unwrap();
@@ -333,22 +338,27 @@ fn TIM2() {
}
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_paddle_ring_low = shared.cw_paddle_ring.is_low().unwrap();
+
+ let cw_ptt_delay : u32 = TICKS_PER_SECOND * 800 / 1000;
+ let cw_ptt = match shared.state.mode {
+ Mode::CW(_) => {
+ if cw_paddle_tip_low || cw_paddle_ring_low {
+ shared.cw_ptt_timestamp = *ticks;
+ true
+ }
+ else {
+ shared.cw_ptt_timestamp + cw_ptt_delay > *ticks
+ }
+ },
+ _ => false,
};
- let cw_beep = shared.state.mode == Mode::CW && cw_paddle_tip_low;
+ let cw_beep = match shared.state.mode {
+ Mode::CW(CWMode::StraightKey) => cw_paddle_tip_low,
+ Mode::CW(CWMode::Iambic) => shared.cw_keyer.tick(*ticks, cw_paddle_tip_low, cw_paddle_ring_low),
+ _ => false,
+ };
let next_state = match shared.state.sequence_state {
SequenceState::Rx => {
@@ -356,60 +366,86 @@ fn TIM2() {
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
+ if button_result.ptt {
+ SequenceState::SwitchingSSB
+ }
+ else if cw_ptt {
+ SequenceState::SwitchingCW
}
else {
SequenceState::Rx
}
},
- SequenceState::Switching => {
+ SequenceState::SwitchingSSB => {
shared.mute_spkr.set_high().unwrap();
shared.seq2_switch.set_high().unwrap();
shared.seq0n.set_low().unwrap();
shared.seq1_pa.set_low().unwrap();
+ shared.mute_micn.set_high().unwrap();
- if cw_beep {
- shared.cw_pwm.on();
+ if button_result.ptt {
+ SequenceState::TxSSB
}
else {
- shared.cw_pwm.off();
- }
-
- if button_result.ptt {
- shared.mute_micn.set_high().unwrap();
- SequenceState::Tx
+ SequenceState::Rx
}
- else if cw_ptt {
- shared.mute_micn.set_low().unwrap();
- SequenceState::Tx
+ },
+ SequenceState::SwitchingCW => {
+ shared.mute_spkr.set_high().unwrap();
+ shared.seq2_switch.set_high().unwrap();
+ shared.seq0n.set_low().unwrap();
+ shared.seq1_pa.set_low().unwrap();
+ shared.mute_micn.set_low().unwrap();
+ if cw_ptt {
+ SequenceState::TxCW
}
else {
SequenceState::Rx
}
},
- SequenceState::Tx => {
+ SequenceState::TxSSB => {
shared.seq1_pa.set_high().unwrap();
- if cw_beep {
- shared.cw_pwm.on();
+ if button_result.ptt {
+ SequenceState::TxSSB
}
else {
- shared.cw_pwm.off();
+ SequenceState::SwitchingSSB
}
+ },
+ SequenceState::TxCW => {
+ shared.seq1_pa.set_high().unwrap();
- if button_result.ptt || cw_ptt {
- SequenceState::Tx
+ if cw_ptt {
+ SequenceState::TxCW
}
else {
- SequenceState::Switching
+ SequenceState::SwitchingCW
}
},
};
- const SWITCHING_DELAY : u32 = TICKS_PER_SECOND * 20 / 1000;
+ match shared.state.sequence_state {
+ SequenceState::TxCW => {
+ if cw_beep {
+ shared.led.set_low().unwrap();
+ shared.cw_pwm.on();
+ shared.cw_key_n.set_low().unwrap();
+ }
+ else {
+ shared.led.set_high().unwrap();
+ shared.cw_pwm.off();
+ shared.cw_key_n.set_high().unwrap();
+ }
+ },
+ _ => {
+ shared.led.set_high().unwrap();
+ shared.cw_pwm.off();
+ shared.cw_key_n.set_high().unwrap();
+ },
+ }
+
+ const SWITCHING_DELAY : u32 = TICKS_PER_SECOND * 40 / 1000;
if shared.state.sequence_state != next_state &&
shared.last_sequence_state_change + SWITCHING_DELAY <= *ticks {
shared.state.sequence_state = next_state;