holiday-lights/morse.cpp

185 lines
4.1 KiB
C++

#include "morse.h"
struct MorseSign {
// Length of this sign. If Length is 0, Bits is the duration of a pause.
uint8_t Length;
uint8_t Bits;
};
const struct MorseSign GetMorseSign(char c) {
switch (c) {
case 3: // ETX - End of Text
return (struct MorseSign){8, 0b01010101};
case 4: // EOT - End of Transmission
return (struct MorseSign){0, MORSE_PAUSE_TRANSMISSION};
case ' ':
return (struct MorseSign){0, MORSE_PAUSE_WORD};
case '0':
return (struct MorseSign){5, 0b11111};
case '1':
return (struct MorseSign){5, 0b01111};
case '2':
return (struct MorseSign){5, 0b00111};
case '3':
return (struct MorseSign){5, 0b00011};
case '4':
return (struct MorseSign){5, 0b00001};
case 5:
return (struct MorseSign){5, 0b00000};
case 6:
return (struct MorseSign){5, 0b10000};
case 7:
return (struct MorseSign){5, 0b11000};
case 8:
return (struct MorseSign){5, 0b11100};
case 9:
return (struct MorseSign){5, 0b11110};
case 'a':
case 'A':
return (struct MorseSign){2, 0b01};
case 'b':
case 'B':
return (struct MorseSign){4, 0b1000};
case 'c':
case 'C':
return (struct MorseSign){4, 0b1010};
case 'd':
case 'D':
return (struct MorseSign){3, 0b100};
case 'e':
case 'E':
return (struct MorseSign){1, 0b0};
case 'f':
case 'F':
return (struct MorseSign){4, 0b0010};
case 'g':
case 'G':
return (struct MorseSign){3, 0b110};
case 'h':
case 'H':
return (struct MorseSign){4, 0b0000};
case 'i':
case 'I':
return (struct MorseSign){2, 0b00};
case 'j':
case 'J':
return (struct MorseSign){4, 0b0111};
case 'k':
case 'K':
return (struct MorseSign){3, 0b101};
case 'l':
case 'L':
return (struct MorseSign){4, 0b0100};
case 'm':
case 'M':
return (struct MorseSign){2, 0b11};
case 'n':
case 'N':
return (struct MorseSign){2, 0b10};
case 'o':
case 'O':
return (struct MorseSign){3, 0b111};
case 'p':
case 'P':
return (struct MorseSign){4, 0b0110};
case 'q':
case 'Q':
return (struct MorseSign){4, 0b1101};
case 'r':
case 'R':
return (struct MorseSign){3, 0b010};
case 's':
case 'S':
return (struct MorseSign){3, 0b000};
case 't':
case 'T':
return (struct MorseSign){1, 0b1};
case 'u':
case 'U':
return (struct MorseSign){3, 0b001};
case 'v':
case 'V':
return (struct MorseSign){4, 0b0001};
case 'w':
case 'W':
return (struct MorseSign){3, 0b011};
case 'x':
case 'X':
return (struct MorseSign){4, 0b1001};
case 'y':
case 'Y':
return (struct MorseSign){4, 0b1011};
case 'z':
case 'Z':
return (struct MorseSign){4, 0b1100};
default:
return (struct MorseSign){0, 0};
}
}
MorseEncoder::MorseEncoder() {
SetText("");
}
MorseEncoder::MorseEncoder(const char *s) {
SetText(s);
}
void MorseEncoder::SetText(const char *s) {
p = s;
bit = 0;
ticksLeft = 0;
Transmitting = false;
}
void MorseEncoder::Quiet(int ticks) {
Transmitting = false;
ticksLeft = ticks;
}
bool MorseEncoder::Tick() {
--ticksLeft;
if (ticksLeft > 0) {
return true;
}
// We're out of ticks
if (!p || !*p) {
return false;
}
// If we were just transmitting, we have to stop for at least one dit
if (Transmitting) {
Transmitting = false;
ticksLeft = MORSE_DIT;
return true;
}
const struct MorseSign sign = GetMorseSign(*p);
if (sign.Length == 0) {
// Pause
Transmitting = false;
ticksLeft = sign.Bits - (MORSE_PAUSE_LETTER - MORSE_DIT);
++p;
bit = 0;
} else if (bit == sign.Length) {
// All done with that sign!
Transmitting = false;
ticksLeft = MORSE_PAUSE_LETTER;
++p;
bit = 0;
} else {
// Sign
uint8_t bitMask = 1 << (sign.Length - bit - 1);
Transmitting = true;
if (sign.Bits & bitMask) {
ticksLeft = MORSE_DAH;
} else {
ticksLeft = MORSE_DIT;
}
++bit;
}
return true;
}