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
|
*.map
|
||||||
*.bin
|
*.bin
|
||||||
*.elf
|
*.elf
|
||||||
|
tabgen
|
||||||
|
table.cpp
|
||||||
|
|
10
Makefile
10
Makefile
|
@ -48,10 +48,14 @@ $(BLD)%.o: %.cpp
|
||||||
@$(CXX) $(VFLAGS) -c $(CFLAGS) $< -o $@
|
@$(CXX) $(VFLAGS) -c $(CFLAGS) $< -o $@
|
||||||
$(BLD):
|
$(BLD):
|
||||||
mkdir $(BLD)
|
mkdir $(BLD)
|
||||||
|
tabgen: tabgen.cpp
|
||||||
|
$(CXX) -Oz tabgen.cpp -o tabgen
|
||||||
|
table.cpp: tabgen
|
||||||
|
./tabgen
|
||||||
# MODULES #
|
# MODULES #
|
||||||
main.o: main.cpp morse.pcm
|
main.o: main.cpp morse.pcm
|
||||||
morse.o: morse.cpp io.pcm sys.pcm
|
morse.o: morse.cpp table.cpp io.pcm sys.pcm
|
||||||
morse.pcm: morse.cpp io.pcm sys.pcm
|
morse.pcm: morse.cpp table.cpp io.pcm sys.pcm
|
||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
-@echo [CXM $(TARGET)] $@
|
-@echo [CXM $(TARGET)] $@
|
||||||
@$(CXX) $(VFLAGS) -c $(MFLAGS) $< -o $@
|
@$(CXX) $(VFLAGS) -c $(MFLAGS) $< -o $@
|
||||||
|
@ -60,5 +64,5 @@ morse.pcm: morse.cpp io.pcm sys.pcm
|
||||||
@$(CXX) $(VFLAGS) -x $(PFLAGS) $< --precompile -o $@
|
@$(CXX) $(VFLAGS) -x $(PFLAGS) $< --precompile -o $@
|
||||||
# vycisti
|
# vycisti
|
||||||
clean:
|
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
|
.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
|
Moduly mohou mít hierarchickou strukturu a opravdu nejsou potřeba
|
||||||
něco jako hlavičky. Ovšem distribuovat takto knihovny jednoduše
|
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
|
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.
|
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
|
Připadá mi to složité a k ničemu, ale to je právě důvod, proč by
|
||||||
|
|
68
morse.cpp
68
morse.cpp
|
@ -3,27 +3,26 @@ import sys;
|
||||||
import io;
|
import io;
|
||||||
export module morse;
|
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) {
|
static unsigned slen (const char * str) {
|
||||||
unsigned n = 0;
|
unsigned n = 0;
|
||||||
while (*str++) n++;
|
while (*str++) n++;
|
||||||
return 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 {
|
export class Morse {
|
||||||
const unsigned unit;
|
const unsigned unit;
|
||||||
const io::GpioClass led;
|
const io::GpioClass led;
|
||||||
|
@ -34,28 +33,24 @@ export class Morse {
|
||||||
}
|
}
|
||||||
void operator<< (const char * text) const;
|
void operator<< (const char * text) const;
|
||||||
protected:
|
protected:
|
||||||
void out (const char * text) const;
|
void out (const morse_byte mb) const;
|
||||||
};
|
};
|
||||||
void Morse::operator<< (const char * text) const {
|
void Morse::operator<< (const char * text) const {
|
||||||
const unsigned len = slen (text);
|
const unsigned len = slen (text);
|
||||||
for (unsigned n=0; n<len; n++) {
|
for (unsigned n=0; n<len; n++) {
|
||||||
const char c = text [n];
|
const char c = text [n];
|
||||||
const char * mp = nullptr;
|
morse_byte mb;
|
||||||
if (c < '\x20') {
|
if (c < '\x20') {
|
||||||
mp = morse_code [0];
|
|
||||||
} else if (c < '`') {
|
} else if (c < '`') {
|
||||||
const int i = c - '\x20';
|
const int i = c - '\x20';
|
||||||
mp = morse_code [i];
|
mb.byte = compressed_table [i];
|
||||||
} else if (c == '`') {
|
} else if (c == '`') {
|
||||||
mp = morse_code [0];
|
|
||||||
} else if (c <= 'z') {
|
} else if (c <= 'z') {
|
||||||
const int i = c - '\x40';
|
const int i = c - '\x40';
|
||||||
mp = morse_code [i];
|
mb.byte = compressed_table [i];
|
||||||
} else {
|
} else {
|
||||||
mp = morse_code [0];
|
|
||||||
}
|
}
|
||||||
if (!mp) return;
|
out (mb);
|
||||||
out (mp);
|
|
||||||
}
|
}
|
||||||
sys::delay (10 * unit);
|
sys::delay (10 * unit);
|
||||||
}
|
}
|
||||||
|
@ -65,21 +60,22 @@ void Morse::operator<< (const char * text) const {
|
||||||
* mezera mezi znaky => 3 x unit
|
* mezera mezi znaky => 3 x unit
|
||||||
* mezera mezi slovy => 7 x unit
|
* mezera mezi slovy => 7 x unit
|
||||||
* */
|
* */
|
||||||
void Morse::out (const char * text) const {
|
void Morse::out (const morse_byte mb) const {
|
||||||
const unsigned len = slen(text);
|
/* 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++) {
|
for (unsigned n=0; n<len; n++) {
|
||||||
led << false;
|
led << false;
|
||||||
sys::delay (unit);
|
sys::delay (unit);
|
||||||
const char c = text [n];
|
const unsigned v = (1u << n) & mb.bits;
|
||||||
if (c == '.') {
|
const unsigned d = v ? 3u : 1u;
|
||||||
led << true;
|
led << true;
|
||||||
sys::delay (1 * unit);
|
sys::delay (d * unit);
|
||||||
} else if (c == '-') {
|
|
||||||
led << true;
|
|
||||||
sys::delay (3 * unit);
|
|
||||||
} else {
|
|
||||||
sys::delay (4 * unit);
|
|
||||||
}
|
|
||||||
led << false;
|
led << false;
|
||||||
}
|
}
|
||||||
sys::delay (3 * unit);
|
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