diff --git a/Cargo.lock b/Cargo.lock index 6966f31..1fd8c09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,7 +21,7 @@ checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "morse-codec" -version = "0.4.2" +version = "0.4.30" dependencies = [ "keyboard_query", ] diff --git a/Cargo.toml b/Cargo.toml index 1860f99..46a8a9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "morse-codec" -version = "0.4.2" +version = "0.4.30" edition = "2024" authors = ["Barış Ürüm"] license = "MIT" diff --git a/src/decoder.rs b/src/decoder.rs index f8b1f11..5069cb3 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -122,6 +122,7 @@ pub struct Decoder { reference_short_ms: MilliSeconds, message: Message, // Internal stuff + is_calibrated: bool, current_character: MorseCodeArray, signal_pos: usize, signal_buffer: SignalBuffer, @@ -144,6 +145,7 @@ impl Decoder { reference_short_ms: 0, message: Message::default(), // Internal stuff + is_calibrated: false, current_character: MORSE_DEFAULT_CHAR, signal_pos: 0, signal_buffer: [SDEmpty; SIGNAL_BUFFER_LENGTH], @@ -242,8 +244,10 @@ impl Decoder { /// determine long signals and very long word separator signals. /// Default value of 0 means MorseDecoder will try to calculate the reference short duration /// from incoming signals. This might not work well if the message starts with a 'T'. + /// Once decoder is calibrated, reference short duration can be changed manually with `set_reference_short` method. pub fn with_reference_short_ms(mut self, reference_short_ms: MilliSeconds) -> Self { self.reference_short_ms = reference_short_ms; + self.is_calibrated = true; self } @@ -276,6 +280,7 @@ impl Decoder { signal_tolerance, reference_short_ms, message, + is_calibrated, current_character, signal_pos, signal_buffer, @@ -288,6 +293,7 @@ impl Decoder { signal_tolerance, reference_short_ms, message, + is_calibrated, current_character, signal_pos, signal_buffer, @@ -308,6 +314,7 @@ pub struct MorseDecoder { reference_short_ms: MilliSeconds, pub message: Message, // Internal stuff + is_calibrated: bool, current_character: MorseCodeArray, signal_pos: usize, signal_buffer: SignalBuffer, @@ -455,13 +462,19 @@ impl MorseDecoder { impl MorseDecoder { /// Returns currently resolved reference short signal duration. /// - /// Reference short signal is resolved continuously by the decoder as signal events pour in. + /// Reference short signal might be resolved and calibrated by the decoder + /// if it wasn't set initally by the builder via `with_reference_short_ms` method. /// As longer signal durations are calculated by multiplying this value, /// it might be useful for the client code. pub fn get_reference_short(&self) -> MilliSeconds { self.reference_short_ms } + /// Manually change the reference short signal duration. + pub fn set_reference_short(&mut self, reference_short: MilliSeconds) { + self.update_reference_short_ms(reference_short); + } + /// Returns the current signal entry speed in /// Words Per Minute format. pub fn get_wpm(&self) -> u16 { @@ -572,9 +585,10 @@ impl MorseDecoder { // 3. It's a very long signal (x7 or more) to divide two words in the message. So // we check the signal buffer and add the character, as well as a space after it. _pos if !is_high => { - if duration_ms < self.reference_short_ms && !tolerance_range.contains(&self.reference_short_ms) { + if !self.is_calibrated && duration_ms < self.reference_short_ms && !tolerance_range.contains(&self.reference_short_ms) { //println!("Updating reference short to {}", duration_ms); self.update_reference_short_ms(duration_ms); + self.is_calibrated = true; } let resolved_duration = self.resolve_signal_duration(duration_ms, &tolerance_range, is_high); diff --git a/src/message.rs b/src/message.rs index 09f5a2c..cd77768 100644 --- a/src/message.rs +++ b/src/message.rs @@ -348,6 +348,19 @@ impl Message { Utf8Charray(self.chars[..self.len()].as_ref()) } + /// Pop the last character from the message and return it + /// deleting it from the message in the process. + pub fn pop(&mut self) -> Option { + if self.len() > 0 { + let last = self.chars[self.len() - 1]; + self.chars[self.len() - 1] = FILLER; + + Some(last) + } else { + None + } + } + /// Clear the message and start over. pub fn clear(&mut self) { self.chars = [FILLER; MSG_MAX]; diff --git a/tests/test-message.rs b/tests/test-message.rs index 316581c..619d670 100644 --- a/tests/test-message.rs +++ b/tests/test-message.rs @@ -65,3 +65,49 @@ fn message_iter() { } } +#[test] +fn message_pop() { + println!("TEST decoder with 'SOS', then popping the last character."); + println!(); + + use morse_codec::MorseSignal::{Long as L, Short as S}; + + const MESSAGE_MAX_LENGTH: usize = 3; + + let mut decoder = Decoder::::new().build(); + + decoder.add_signal_to_character(Some(S)); + decoder.add_signal_to_character(Some(S)); + decoder.add_signal_to_character(Some(S)); + + decoder.add_current_char_to_message(); + + decoder.add_signal_to_character(Some(L)); + decoder.add_signal_to_character(Some(L)); + decoder.add_signal_to_character(Some(L)); + + decoder.add_current_char_to_message(); + + decoder.add_signal_to_character(Some(S)); + decoder.add_signal_to_character(Some(S)); + decoder.add_signal_to_character(Some(S)); + + decoder.add_current_char_to_message(); + + let msg = decoder.message.as_str(); + + println!("Message before popping the last char: {}", msg); + if let Some(char) = decoder.message.pop() { + println!("Last character is: {}", char as char); + println!("Message after popping: {}", decoder.message.as_str()); + } + + println!(); + println!("Popping till empty"); + while let Some(char) = decoder.message.pop() { + println!("Last character is: {}", char as char); + } + + assert!(decoder.message.is_empty()); +} +