compress morse code
This commit is contained in:
parent
9f6d05a9e4
commit
f6db62d0cf
5 changed files with 98 additions and 41 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -9,3 +9,5 @@ bld/*
|
|||
*.map
|
||||
*.bin
|
||||
*.elf
|
||||
tabgen
|
||||
table.cpp
|
||||
|
|
10
Makefile
10
Makefile
|
@ -48,10 +48,14 @@ $(BLD)%.o: %.cpp
|
|||
@$(CXX) $(VFLAGS) -c $(CFLAGS) $< -o $@
|
||||
$(BLD):
|
||||
mkdir $(BLD)
|
||||
tabgen: tabgen.cpp
|
||||
$(CXX) -Oz tabgen.cpp -o tabgen
|
||||
table.cpp: tabgen
|
||||
./tabgen
|
||||
# MODULES #
|
||||
main.o: main.cpp morse.pcm
|
||||
morse.o: morse.cpp io.pcm sys.pcm
|
||||
morse.pcm: morse.cpp io.pcm sys.pcm
|
||||
morse.o: morse.cpp table.cpp io.pcm sys.pcm
|
||||
morse.pcm: morse.cpp table.cpp io.pcm sys.pcm
|
||||
%.o: %.cpp
|
||||
-@echo [CXM $(TARGET)] $@
|
||||
@$(CXX) $(VFLAGS) -c $(MFLAGS) $< -o $@
|
||||
|
@ -60,5 +64,5 @@ morse.pcm: morse.cpp io.pcm sys.pcm
|
|||
@$(CXX) $(VFLAGS) -x $(PFLAGS) $< --precompile -o $@
|
||||
# vycisti
|
||||
clean:
|
||||
rm -f $(BLD)* *.o *.lst *.bin *.elf *.map *.pcm *~
|
||||
rm -f $(BLD)* *.o *.lst *.bin *.elf *.map *.pcm *~ table.cpp tabgen
|
||||
.PHONY: all clean
|
||||
|
|
|
@ -9,7 +9,7 @@ a nepochopitelný, ale funguje to. Zjevně je to hodně experimentální.
|
|||
Moduly mohou mít hierarchickou strukturu a opravdu nejsou potřeba
|
||||
něco jako hlavičky. Ovšem distribuovat takto knihovny jednoduše
|
||||
nejde. Prostě musí k tomu být zdrojáky a ty je potřeba přeložit
|
||||
specifickým (a dost komlikovaným) způsobem. Negeneruje to žádný
|
||||
specifickým (a dost komplikovaným) způsobem. Negeneruje to žádný
|
||||
overhead, alespoň v tomto jednoduchém příkladu.
|
||||
|
||||
Připadá mi to složité a k ničemu, ale to je právě důvod, proč by
|
||||
|
|
70
morse.cpp
70
morse.cpp
|
@ -3,27 +3,26 @@ import sys;
|
|||
import io;
|
||||
export module morse;
|
||||
|
||||
static const char * const morse_code [] = { /* nedefinované znaky nahrazeny mezrou */
|
||||
" ", /* */ " ", /*!*/ ".-..-.", /*"*/ " ", /*#*/ " ", /*$*/
|
||||
" ", /*%*/ " ", /*&*/ ".----.", /*'*/ "-.--.", /*(*/ "-.--.-", /*)*/
|
||||
" ", /***/ ".-.-.", /*+*/ "--..--", /*,*/ "-....-", /*-*/ ".-.-.-", /*.*/ "-..-." , /*/*/
|
||||
"-----", /*0*/ ".----", /*1*/ "..---", /*2*/ "...--", /*3*/ "....-", /*4*/
|
||||
".....", /*5*/ "-....", /*6*/ "--...", /*7*/ "---..", /*8*/ "----.", /*9*/
|
||||
"---...", /*:*/ "-.-.-.", /*;*/ " ", /*<*/ "-...-" , /*=*/ " ", /*>*/ "..--..", /*?*/
|
||||
".--.-.", /*@*/
|
||||
".-", /*A*/ "-...", /*B*/ "-.-.", /*C*/ "-..", /*D*/ ".", /*E*/ "..-.", /*F*/
|
||||
"--.", /*G*/ "....", /*H*/ "..", /*I*/ ".---", /*J*/ "-.-", /*K*/ ".-..", /*L*/
|
||||
"--", /*M*/ "-.", /*N*/ "---", /*O*/ ".--.", /*P*/ "--.-", /*Q*/ ".-.", /*R*/
|
||||
"...", /*S*/ "-", /*T*/ "..-", /*U*/ "...-", /*V*/ ".--", /*W*/ "-..-", /*X*/
|
||||
"-.--", /*Y*/ "--..", /*Z*/ " ", " ", " ", " ", "..--.-", /*_*/
|
||||
};
|
||||
|
||||
static unsigned slen (const char * str) {
|
||||
unsigned n = 0;
|
||||
while (*str++) n++;
|
||||
return n;
|
||||
}
|
||||
|
||||
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"
|
||||
export class Morse {
|
||||
const unsigned unit;
|
||||
const io::GpioClass led;
|
||||
|
@ -34,28 +33,24 @@ export class Morse {
|
|||
}
|
||||
void operator<< (const char * text) const;
|
||||
protected:
|
||||
void out (const char * text) const;
|
||||
void out (const morse_byte mb) const;
|
||||
};
|
||||
void Morse::operator<< (const char * text) const {
|
||||
const unsigned len = slen (text);
|
||||
for (unsigned n=0; n<len; n++) {
|
||||
const char c = text [n];
|
||||
const char * mp = nullptr;
|
||||
morse_byte mb;
|
||||
if (c < '\x20') {
|
||||
mp = morse_code [0];
|
||||
} else if (c < '`') {
|
||||
const int i = c - '\x20';
|
||||
mp = morse_code [i];
|
||||
mb.byte = compressed_table [i];
|
||||
} else if (c == '`') {
|
||||
mp = morse_code [0];
|
||||
} else if (c <= 'z') {
|
||||
const int i = c - '\x40';
|
||||
mp = morse_code [i];
|
||||
mb.byte = compressed_table [i];
|
||||
} else {
|
||||
mp = morse_code [0];
|
||||
}
|
||||
if (!mp) return;
|
||||
out (mp);
|
||||
out (mb);
|
||||
}
|
||||
sys::delay (10 * unit);
|
||||
}
|
||||
|
@ -65,21 +60,22 @@ void Morse::operator<< (const char * text) const {
|
|||
* mezera mezi znaky => 3 x unit
|
||||
* mezera mezi slovy => 7 x unit
|
||||
* */
|
||||
void Morse::out (const char * text) const {
|
||||
const unsigned len = slen(text);
|
||||
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; }
|
||||
for (unsigned n=0; n<len; n++) {
|
||||
led << false;
|
||||
sys::delay (unit);
|
||||
const char c = text [n];
|
||||
if (c == '.') {
|
||||
led << true;
|
||||
sys::delay (1 * unit);
|
||||
} else if (c == '-') {
|
||||
led << true;
|
||||
sys::delay (3 * unit);
|
||||
} else {
|
||||
sys::delay (4 * unit);
|
||||
}
|
||||
const unsigned v = (1u << n) & mb.bits;
|
||||
const unsigned d = v ? 3u : 1u;
|
||||
led << true;
|
||||
sys::delay (d * unit);
|
||||
led << false;
|
||||
}
|
||||
sys::delay (3 * unit);
|
||||
|
|
55
tabgen.cpp
Normal file
55
tabgen.cpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#if __BYTE_ORDER__ != 1234
|
||||
#error "BAD ENDIAN"
|
||||
#endif
|
||||
static const char * oname = "table.cpp";
|
||||
static const char * const morse_code [] = { /* nedefinované znaky nahrazeny mezrou */
|
||||
" ", /* */ " ", /*!*/ ".-..-.", /*"*/ " ", /*#*/ " ", /*$*/
|
||||
" ", /*%*/ " ", /*&*/ ".----.", /*'*/ "-.--.", /*(*/ "-.--.-", /*)*/
|
||||
" ", /***/ ".-.-.", /*+*/ "--..--", /*,*/ "-....-", /*-*/ ".-.-.-", /*.*/ "-..-." , /*/*/
|
||||
"-----", /*0*/ ".----", /*1*/ "..---", /*2*/ "...--", /*3*/ "....-", /*4*/
|
||||
".....", /*5*/ "-....", /*6*/ "--...", /*7*/ "---..", /*8*/ "----.", /*9*/
|
||||
"---...", /*:*/ "-.-.-.", /*;*/ " ", /*<*/ "-...-" , /*=*/ " ", /*>*/ "..--..", /*?*/
|
||||
".--.-.", /*@*/
|
||||
".-", /*A*/ "-...", /*B*/ "-.-.", /*C*/ "-..", /*D*/ ".", /*E*/ "..-.", /*F*/
|
||||
"--.", /*G*/ "....", /*H*/ "..", /*I*/ ".---", /*J*/ "-.-", /*K*/ ".-..", /*L*/
|
||||
"--", /*M*/ "-.", /*N*/ "---", /*O*/ ".--.", /*P*/ "--.-", /*Q*/ ".-.", /*R*/
|
||||
"...", /*S*/ "-", /*T*/ "..-", /*U*/ "...-", /*V*/ ".--", /*W*/ "-..-", /*X*/
|
||||
"-.--", /*Y*/ "--..", /*Z*/ " ", " ", " ", " ", "..--.-", /*_*/
|
||||
};
|
||||
union morse_byte {
|
||||
struct {
|
||||
unsigned char bits : 5; // Jednotlivé bity.
|
||||
unsigned char mlen : 3; // A jejich délka - max 6.
|
||||
}; // Pokud je 6 nebo 7, pak je nejnižší bit zároveň součástí bitů
|
||||
unsigned char byte;
|
||||
explicit constexpr morse_byte () noexcept : byte (0u) {}
|
||||
};
|
||||
static morse_byte compress (const unsigned n) {
|
||||
const char * const ptr = morse_code [n];
|
||||
const unsigned len = strlen (ptr);
|
||||
morse_byte mb;
|
||||
if (ptr [0] == ' ') return mb;
|
||||
mb.mlen = len;
|
||||
for (unsigned n=0; n<len; n++) {
|
||||
if (ptr [n] == '-') mb.byte |= (1u << n);
|
||||
}
|
||||
return mb;
|
||||
}
|
||||
/* Generátor komprimované tabulky morse kódů */
|
||||
int main () {
|
||||
FILE * out = fopen(oname, "w");
|
||||
if (!out) return 1;
|
||||
unsigned n = 0u;
|
||||
fprintf(out, "static const unsigned char compressed_table [] = {");
|
||||
for (auto & e: morse_code) {
|
||||
if ((n & 0xf) == 0u) fprintf(out, "\n");
|
||||
fprintf(out, " 0x%02x,", compress(n).byte);
|
||||
n += 1u;
|
||||
}
|
||||
fprintf(out, "\n};\n");
|
||||
|
||||
fclose (out);
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue