class Timer {
public:
void start() { timeStamp = millis(); }
bool operator()(const unsigned long duration) const { return (millis() - timeStamp >= duration) ? true : false; }
private:
unsigned long timeStamp{0};
};
struct Symbols {
const char* letters[26] {
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..",
".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.",
"...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."
};
const char* numbers[10] {
"-----", ".----", "..---", "...--", "....-", ".....",
"-....", "--...", "---..", "----."
};
const char* whitespace[1] {" "};
const char* getCode(char character) const {
switch(character) {
case 'A'...'Z': return letters[character-'A'];
case 'a'...'z': return letters[character-'a'];
case '0'...'9': return numbers[character-'0'];
}
// Any character for which no encoding was stored
// it is treated like a space character (yet)
return whitespace[0];
}
};
enum class Fstm : byte {next, startword, wait, lightup, lightoff, spacing, stop};
constexpr unsigned int DIT {200};
constexpr unsigned int DAH {3 * DIT};
constexpr unsigned int SYMBOL_SPACING {1 * DIT};
constexpr unsigned int LETTER_SPACING {3 * SYMBOL_SPACING};
constexpr unsigned int WORD_SPACING {7 * SYMBOL_SPACING};
// constexpr byte LED_PIN {LED_BUILTIN};
constexpr byte LED_PIN {3};
constexpr Symbols morse;
// This text is translated into Morse code
constexpr char text[] {"Hello can someone please help"};
Timer timer;
void fstm() {
static Fstm state {Fstm::next};
static unsigned long timerValue;
static byte characterIdx {0};
switch(state) {
case Fstm::next:
static byte codeIdx {0};
const char* code;
if (!codeIdx) {Serial.print(text[characterIdx]);}
if (text[characterIdx]) {
code = morse.getCode(text[characterIdx]);
if (*code == 32) { // It's a "non morsable character". Treat it as a word space.
++characterIdx;
state = Fstm::startword;
break;
}
} else {
// If the text has been morst, start from the beginning
// If this should not happen, then set the status Fstm::stop.
characterIdx= 0;
state = Fstm::startword;
Serial.println();
//state = Fstm::stop;
break;
}
timerValue = (code[codeIdx] == '.') ? DIT : DAH;
if(!code[codeIdx++]) {
codeIdx = 0;
++characterIdx;
timerValue = LETTER_SPACING;
state = Fstm::spacing;
timer.start();
} else { state = Fstm::lightup; }
break;
case Fstm::startword:
timerValue = WORD_SPACING;
state = Fstm::spacing;
timer.start();
break;
case Fstm::lightup:
digitalWrite(LED_PIN,HIGH);
state = Fstm::wait;
timer.start();
break;
case Fstm::wait:
if(timer(timerValue)) { state = Fstm::lightoff; }
break;
case Fstm::lightoff:
digitalWrite(LED_PIN,LOW);
timerValue = SYMBOL_SPACING;
state = Fstm::spacing;
timer.start();
break;
case Fstm::spacing:
if(timer(timerValue)) { state = Fstm::next; }
break;
default:
break;
}
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
Serial.print("Morsetext: "); Serial.println(text);
}
void loop() {
fstm();
}