FIFO array? Ring buffer?

I am trying to work through creating a morse code keyer. I know there are many examples out there, but I have not been able to find what I am interested in yet. In particular, I want to go through this project on my own, keep it simple, and focus on learning how to deal with timing issues on an Arduino.

So, my thought is to separate the input from the key from the output to the speaker. I'd like to be able to record input at any speed and output it at a controlled speed. For example, an expert is able to send morse code at 20 words per minute but I would like to play that back at 5 words per minute.

To do this, I'd like to record all inputs on a pin and store that value in a FIFO buffer (terminology?) so I don't miss any input. Then, I'd like to empty the FIFO buffer at a timed interval that matches the slower speed. This way, I don't miss anything coming in, and I have a chance to test myself as I record the slower speed from the speaker. Think master-slave setup in a classroom (which is what it will be used for)

I have found the SimpleFIFO example, but can't get this to work at all. I am thinking of doing something like the following:

  • Every 500ms, read the first entry from the FIFO buffer
  • If the entry is a zero in the buffer, do nothing
  • If the entry is a one, output a dot
  • Advance the buffer one index (terminology?)
  • If the entry is a two, output a dash
  • Advance the buffer one index (terminology?)

At the same time, record the inputs from the key as fast as possible so I don't miss anything.

I have to be honest, I have lots of experience wiring things, but am self-taught and have no idea how to code something like this. I don't even know what the right words to search for are.

Any help would be greatly appreciated.

Many many thanks,

Ryan

For example, an expert is able to send morse code at 20 words per minute but I would like to play that back at 5 words per minute.

You need to think in terms of characters/unit of time, not words/unit of time. Word lengths differ.

To do this, I'd like to record all inputs on a pin

What kind of inputs? Are you building a device that receives Morse code, too?

I have found the SimpleFIFO example, but can't get this to work at all.

Why not?

I am thinking of doing something like the following:

Why not store the characters to be output?

Your terminology is correct. Advancing a buffer one index just means incrementing the index used to access one element of an array.

byte index = -1;
char array[] = "Send this";

while(char c = array[index++])
{
   Send(c);
}

Thanks Paul,

First, the words per minute apparently refers to the number of times you can type PARIS or CODEX in a minute. It's a standard way of measuring morse code speed. So, that's where that came from.

Second, my input is from a standard morse code key. A "dot" is made when the tip of the ⅛" wire coming from the back goes to ground. A "dash" is made when the ring goes to ground.

All of the FIFO buffer examples I have found require the array size to be known. I don't know how many elements it will have, so it would be hard to count... I think. I also don't want it to miss any inputs while it is outputting... so, I need something like multithreading of sorts.

Here's the general functionality:

  • Read the input from the morse code key as often as possible
  • Store the sequence of dots and dashes in a buffer regardless of what speed they were recorded at
  • Read the array when either a pause is encountered or the input ceases for a set amount of time
  • Output the sequence retrieved from the array to a speaker WHILE at the same time recording any new input

The real goal is to separate my crappy timing coming from my hand and output perfectly timed dots and dashes. If my hand spaces the dots 21, 33, 55, and 42 ms apart ... store those as 4 dots and output them at a corrected 50ms apart while not missing any inputs coming in.

Sorry, I tried to hook up your example to my code, but I really need something that appends an element to the end of an array, and something that can push the first element out. I am having a hard time sorting out how this is done. Damn my lack of CS degree!

Thanks for your help. I am coding now to see if I can get an example pulled together.

Best,

R

81Pantah:
Second, my input is from a standard Morse code key. A "dot" is made when the tip of the ⅛" wire coming from the back goes to ground. A "dash" is made when the ring goes to ground.

That's not a "standard Morse code key". You are referring to a Paddle or "bug".

The most tricky part of your code will always be the part that decodes what you are sending. Even using a paddle.

81Pantah:
Here's the general functionality:

  • Read the input from the morse code key as often as possible
  • Store the sequence of dots and dashes in a buffer regardless of what speed they were recorded at
  • Read the array when either a pause is encountered or the input ceases for a set amount of time
  • Output the sequence retrieved from the array to a speaker WHILE at the same time recording any new input

The real goal is to separate my crappy timing coming from my hand and output perfectly timed dots and dashes. If my hand spaces the dots 21, 33, 55, and 42 ms apart ... store those as 4 dots and output them at a corrected 50ms apart while not missing any inputs coming in.

Did you already try to use one of the already existing "morse decoder" sketches for Arduino?
Or do you want to create one "from scratch"?

I think that a "morse decoder" has to do two tasks at the same time.

1st task:
Adaptive keying speed reading. That tasks reads the duration of each dot and dash, and then uses an algorithm to find out the "split time". Every signal shorter than "split time" is then handled as a dot and every signal with longer duration is handled as a dash.

2nd task: Decode dots and dashes and gaps into letters and words.

If you then also need an output in perfect timing, there will also be a
3rd task: Output letters/words in perfect timing.

I've just looked up morse code timing in Wikipedia Morse code - Wikipedia

The inter-element gap between the dots and dashes within a character is one dot duration.
The inter-letters gap between two letters is one dash duration

So the same "split time" that makes the decision between "dot" and "dash" can also be used to make the decision between "inter-element gap" and "inter-letters gap".

And every gap which is longer than two times the "split time" must be a gap seperating two words.

So first step would be to find the "split time" between "dot duration" and "dash duration" accordingly to the current keying speed.

Do you already have some code to find out the current keying speed / speed limits for dots and dashes?

Do you want to use the final Arduino sketch as some kind of "morse trainer"?
If you just want to send out morse code in perfect timing, it would be much easier to code a "morse encoder" which just reads the serial input line from the Serial monitor than to code a "morse decoder and encoder".