//! CW output using PWM on PA8, TIM1 CH1 use stm32f1xx_hal::{ prelude::*, timer, pac::TIM1, gpio::gpioa::*, gpio::{Alternate, PushPull}, afio::MAPR, pwm, }; const SIDETONE_FREQ : u32 = 1000; 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, SIDETONE_FREQ.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); } } #[derive(PartialEq, Eq, Clone, Copy)] enum MorseSign { Dot, Dash } impl MorseSign { fn length(&self) -> u32 { match self { Self::Dot => 1, Self::Dash => 3, } } fn other(&self) -> Self { match self { Self::Dot => Self::Dash, Self::Dash => Self::Dot, } } } fn other_pressed(sign: MorseSign, dot_pressed: bool, dash_pressed: bool) -> bool { match sign { MorseSign::Dot => dash_pressed, MorseSign::Dash => dot_pressed, } } #[derive(Eq, Clone, Copy)] enum KeyerState { Idle, Beep{current: MorseSign, next: Option}, Pause{current: MorseSign, next: Option}, LastPause{next: Option}, } impl PartialEq for KeyerState { fn eq(&self, rhs: &Self) -> bool { match (self, rhs) { (Self::Idle, Self::Idle) => true, (Self::Beep{current : c1, next : _}, Self::Beep{current : c2, next : _}) => c1 == c2, (Self::Pause{current : c1, next : _}, Self::Pause{current : c2, next : _}) => c1 == c2, (Self::LastPause{next : _}, Self::LastPause{next : _}) => true, _ => false, } } } pub struct Keyer { // All durations are in ticks dot_length : u32, state : KeyerState, time_last_state_change : u32, } impl Keyer { pub fn new(wpm : u32, ticks_per_s: u32) -> Keyer { /* PARIS standard: 20 words per minute = dot length of 60 ms, inversely proportional: * 1 wpm = 1200 ms, 2 wpm = 600 ms */ Keyer{ dot_length : 1200 * ticks_per_s / (1000 * wpm), state : KeyerState::Idle, time_last_state_change : 0, } } pub fn set_speed(&mut self, wpm : u32, ticks_per_s: u32) { self.dot_length = 1200 * ticks_per_s / (1000 * wpm) } pub fn tick(&mut self, ticks_now: u32, dot_pressed: bool, dash_pressed: bool) -> bool { let mut transmit = false; let next_state = match self.state { KeyerState::Idle => { if dot_pressed { transmit = true; KeyerState::Beep{current: MorseSign::Dot, next: None} } else if dash_pressed { transmit = true; KeyerState::Beep{current: MorseSign::Dash, next: None} } else { KeyerState::Idle } }, KeyerState::Beep{current, next} => { transmit = true; let next = if other_pressed(current, dot_pressed, dash_pressed) { Some(current.other()) } else { next }; if self.time_last_state_change + self.dot_length * current.length() <= ticks_now { KeyerState::Pause{current, next} } else { KeyerState::Beep{current, next} } }, KeyerState::Pause{current, next} => { let next = if other_pressed(current, dot_pressed, dash_pressed) { Some(current.other()) } else { next }; if self.time_last_state_change + self.dot_length <= ticks_now { match next { Some(state) => { transmit = true; KeyerState::Beep{current: state, next: None} }, None => KeyerState::LastPause{next: None} } } else { KeyerState::Pause{current, next} } }, KeyerState::LastPause{next} => { let next = if dot_pressed { Some(MorseSign::Dot) } else if dash_pressed { Some(MorseSign::Dash) } else { next }; if self.time_last_state_change + self.dot_length <= ticks_now { KeyerState::LastPause{next} } else { match next { Some(MorseSign::Dot) => { transmit = true; KeyerState::Beep{current: MorseSign::Dot, next: None} }, Some(MorseSign::Dash) => { transmit = true; KeyerState::Beep{current: MorseSign::Dash, next: None} }, None => { KeyerState::Idle }, } } }, }; if next_state != self.state { self.time_last_state_change = ticks_now; } self.state = next_state; transmit } }