Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "morse-codec"
version = "0.4.2"
version = "0.4.30"
edition = "2024"
authors = ["Barış Ürüm"]
license = "MIT"
Expand Down
18 changes: 16 additions & 2 deletions src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ pub struct Decoder<const MSG_MAX: usize> {
reference_short_ms: MilliSeconds,
message: Message<MSG_MAX>,
// Internal stuff
is_calibrated: bool,
current_character: MorseCodeArray,
signal_pos: usize,
signal_buffer: SignalBuffer,
Expand All @@ -144,6 +145,7 @@ impl<const MSG_MAX: usize> Decoder<MSG_MAX> {
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],
Expand Down Expand Up @@ -242,8 +244,10 @@ impl<const MSG_MAX: usize> Decoder<MSG_MAX> {
/// 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
}
Expand Down Expand Up @@ -276,6 +280,7 @@ impl<const MSG_MAX: usize> Decoder<MSG_MAX> {
signal_tolerance,
reference_short_ms,
message,
is_calibrated,
current_character,
signal_pos,
signal_buffer,
Expand All @@ -288,6 +293,7 @@ impl<const MSG_MAX: usize> Decoder<MSG_MAX> {
signal_tolerance,
reference_short_ms,
message,
is_calibrated,
current_character,
signal_pos,
signal_buffer,
Expand All @@ -308,6 +314,7 @@ pub struct MorseDecoder<const MSG_MAX: usize> {
reference_short_ms: MilliSeconds,
pub message: Message<MSG_MAX>,
// Internal stuff
is_calibrated: bool,
current_character: MorseCodeArray,
signal_pos: usize,
signal_buffer: SignalBuffer,
Expand Down Expand Up @@ -455,13 +462,19 @@ impl<const MSG_MAX: usize> MorseDecoder<MSG_MAX> {
impl<const MSG_MAX: usize> MorseDecoder<MSG_MAX> {
/// 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 {
Expand Down Expand Up @@ -572,9 +585,10 @@ impl<const MSG_MAX: usize> MorseDecoder<MSG_MAX> {
// 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);
Expand Down
13 changes: 13 additions & 0 deletions src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,19 @@ impl<const MSG_MAX: usize> Message<MSG_MAX> {
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<Character> {
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];
Expand Down
46 changes: 46 additions & 0 deletions tests/test-message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<MESSAGE_MAX_LENGTH>::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());
}