//! CW output using PWM on PA8, TIM1 CH1 use stm32f1xx_hal::{ timer, pac::TIM1, }; /* const CW_MAPPING : [u8; 50] = [ //{{{ // Read bits from right to left 0b110101, //+ ASCII 43 0b110101, //, ASCII 44 0b1011110, //- ASCII 45 0b1010101, //., ASCII 46 0b110110, // / ASCII 47 0b100000, // 0, ASCII 48 0b100001, // 1 0b100011, 0b100111, 0b101111, 0b111111, 0b111110, 0b111100, 0b111000, 0b110000, // 9, ASCII 57 // The following are mostly invalid, but // required to fill the gap in ASCII between // numerals and capital letters 0b10, // : 0b10, // ; 0b10, // < 0b101110, // = 0b10, // > 0b1110011, // ? 0b1101001, //@ 0b101, // A ASCII 65 0b11110, 0b11010, 0b1110, 0b11, 0b11011, 0b1100, 0b11111, 0b111, 0b10001, 0b1010, 0b11101, 0b100, //M 0b110, 0b1000, 0b11001, 0b10100, 0b1101, 0b1111, 0b10, 0b1011, 0b10111, 0b1001, 0b10110, 0b10010, 0b11100, // Z 0b101010, //Start, ASCII [ 0b1010111, // SK , ASCII '\' ]; //}}} const CW_MACRO : &[u8; 28] = b"CQ DE HB9EGM HB9EGM HB9EGM K"; */ pub const SIDETONE_FREQ : u32 = 800; pub struct CWPWM { channel : timer::pwm::PwmChannel, } impl CWPWM { pub fn new(mut channel: timer::pwm::PwmChannel) -> Self { 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 } }