diff --git a/.gitignore b/.gitignore index 66ce983..4203675 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ bld/* *.map *.bin *.elf +tabgen +table.cpp diff --git a/Makefile b/Makefile index b0f593c..e111972 100644 --- a/Makefile +++ b/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 diff --git a/README.md b/README.md index 1cb7a32..8edc3cb 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/morse.cpp b/morse.cpp index 5a5b98d..3249cd0 100644 --- a/morse.cpp +++ b/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 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 +#include +#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