2024-01-18 11:42:56 +01:00
|
|
|
module;
|
|
|
|
import sys;
|
|
|
|
import io;
|
|
|
|
export module morse;
|
|
|
|
|
|
|
|
static unsigned slen (const char * str) {
|
|
|
|
unsigned n = 0;
|
|
|
|
while (*str++) n++;
|
|
|
|
return n;
|
|
|
|
}
|
2024-01-19 13:04:24 +01:00
|
|
|
union morse_byte {
|
|
|
|
struct {
|
|
|
|
unsigned char bits : 5;
|
|
|
|
unsigned char mlen : 3;
|
|
|
|
};
|
|
|
|
unsigned char byte;
|
|
|
|
explicit constexpr morse_byte () noexcept : byte (0u) {}
|
|
|
|
};
|
|
|
|
/* Použijeme vygenerovanou tabulku,
|
|
|
|
* je naprosto nečitelná, ale z čitelného kódu.
|
|
|
|
*
|
|
|
|
* Jsme v bare metal, tak ušetříme každý byte,
|
|
|
|
* ať to stojí co chce (je to cca 500 bytů).
|
|
|
|
*/
|
|
|
|
#include "table.cpp"
|
2024-01-18 11:42:56 +01:00
|
|
|
export class Morse {
|
2024-01-19 15:52:53 +01:00
|
|
|
const unsigned unit;
|
|
|
|
const io::GpioClass & led;
|
2024-01-18 11:42:56 +01:00
|
|
|
|
|
|
|
public:
|
2024-01-19 15:52:53 +01:00
|
|
|
explicit Morse (const io::GpioClass & pin, const unsigned ms = 100) noexcept
|
|
|
|
: unit (ms), led (pin) {
|
2024-01-18 11:42:56 +01:00
|
|
|
sys::init ();
|
|
|
|
}
|
|
|
|
void operator<< (const char * text) const;
|
|
|
|
protected:
|
2024-01-19 13:04:24 +01:00
|
|
|
void out (const morse_byte mb) const;
|
2024-01-18 11:42:56 +01:00
|
|
|
};
|
|
|
|
void Morse::operator<< (const char * text) const {
|
|
|
|
const unsigned len = slen (text);
|
|
|
|
for (unsigned n=0; n<len; n++) {
|
|
|
|
const char c = text [n];
|
2024-01-19 13:04:24 +01:00
|
|
|
morse_byte mb;
|
2024-01-18 11:42:56 +01:00
|
|
|
if (c < '\x20') {
|
|
|
|
} else if (c < '`') {
|
|
|
|
const int i = c - '\x20';
|
2024-01-19 13:04:24 +01:00
|
|
|
mb.byte = compressed_table [i];
|
2024-01-18 11:42:56 +01:00
|
|
|
} else if (c == '`') {
|
|
|
|
} else if (c <= 'z') {
|
|
|
|
const int i = c - '\x40';
|
2024-01-19 13:04:24 +01:00
|
|
|
mb.byte = compressed_table [i];
|
2024-01-18 11:42:56 +01:00
|
|
|
} else {
|
|
|
|
}
|
2024-01-19 13:04:24 +01:00
|
|
|
out (mb);
|
2024-01-18 11:42:56 +01:00
|
|
|
}
|
|
|
|
sys::delay (10 * unit);
|
|
|
|
}
|
|
|
|
/* . => 1 x unit
|
|
|
|
* - => 3 x unit
|
|
|
|
* mezera mezi značkami => 1 x unit
|
|
|
|
* mezera mezi znaky => 3 x unit
|
|
|
|
* mezera mezi slovy => 7 x unit
|
|
|
|
* */
|
2024-01-19 13:04:24 +01:00
|
|
|
void Morse::out (const morse_byte mb) const {
|
|
|
|
/* Finta je v tom, že i když se pole mlen a bits překrývají,
|
|
|
|
* nevadí to - maximální délka je 6, takže v nejnižším bitu
|
|
|
|
* mlen může být obsažen 1 bit 6.bitového znaku.
|
|
|
|
* Takhle napsáno to běhá jen na malém indiánu, přepisovat
|
|
|
|
* to do bitových posunů nebudu, i když by to bylo čistší.
|
|
|
|
* */
|
|
|
|
const unsigned len = mb.mlen > 6u ? 6u : mb.mlen;
|
|
|
|
if (!len) { sys::delay (4 * unit); return; }
|
2024-01-18 11:42:56 +01:00
|
|
|
for (unsigned n=0; n<len; n++) {
|
|
|
|
led << false;
|
|
|
|
sys::delay (unit);
|
2024-01-19 13:04:24 +01:00
|
|
|
const unsigned v = (1u << n) & mb.bits;
|
|
|
|
const unsigned d = v ? 3u : 1u;
|
|
|
|
led << true;
|
|
|
|
sys::delay (d * unit);
|
2024-01-18 11:42:56 +01:00
|
|
|
led << false;
|
|
|
|
}
|
|
|
|
sys::delay (3 * unit);
|
|
|
|
}
|
|
|
|
|