add morse code
This commit is contained in:
parent
bcf1030226
commit
9f6d05a9e4
5 changed files with 158 additions and 66 deletions
13
Makefile
13
Makefile
|
@ -16,12 +16,13 @@ CFLAGS = -Wall $(TGT) -Oz -gdwarf-3 -I./$(TARGET) -ffunction-sections -fdata-sec
|
||||||
LFLAGS = -nostart-files --gc-sections -Map=example.map
|
LFLAGS = -nostart-files --gc-sections -Map=example.map
|
||||||
MFLAGS = $(CFLAGS) -fmodules -fprebuilt-module-path=.
|
MFLAGS = $(CFLAGS) -fmodules -fprebuilt-module-path=.
|
||||||
VFLAGS = -std=c++20 -fno-rtti
|
VFLAGS = -std=c++20 -fno-rtti
|
||||||
|
PFLAGS = c++-module $(TGT) -I./$(TARGET) -fprebuilt-module-path=. -fno-exceptions
|
||||||
|
|
||||||
VPATH = . ./$(TARGET)
|
VPATH = . ./$(TARGET)
|
||||||
|
|
||||||
# zdrojaky -> objekty
|
# zdrojaky -> objekty
|
||||||
OBJS = STM32L4x2_startup.o system.o
|
OBJS = STM32L4x2_startup.o system.o
|
||||||
MOBJS = main.o io.o sys.o
|
MOBJS = morse.o io.o sys.o main.o
|
||||||
|
|
||||||
BOBJS = $(addprefix $(BLD),$(OBJS))
|
BOBJS = $(addprefix $(BLD),$(OBJS))
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ all: $(BLD) $(PRJ).elf
|
||||||
# -include $(BLD)*.d
|
# -include $(BLD)*.d
|
||||||
# linker
|
# linker
|
||||||
$(PRJ).elf: $(BOBJS) $(MOBJS)
|
$(PRJ).elf: $(BOBJS) $(MOBJS)
|
||||||
-@echo [LD $(TARGET)] $@
|
-@echo [LLD $(TARGET)] $@
|
||||||
@$(LD) $(LFLAGS) -o $(PRJ).elf $(BOBJS) $(MOBJS) $(LDLIBS)
|
@$(LD) $(LFLAGS) -o $(PRJ).elf $(BOBJS) $(MOBJS) $(LDLIBS)
|
||||||
-@echo "size:"
|
-@echo "size:"
|
||||||
@$(SIZE) $(PRJ).elf
|
@$(SIZE) $(PRJ).elf
|
||||||
|
@ -40,7 +41,7 @@ $(PRJ).elf: $(BOBJS) $(MOBJS)
|
||||||
-@echo "OK."
|
-@echo "OK."
|
||||||
# preloz co je potreba
|
# preloz co je potreba
|
||||||
$(BLD)%.o: %.c
|
$(BLD)%.o: %.c
|
||||||
-@echo [CC $(TARGET)] $@
|
-@echo [CCC $(TARGET)] $@
|
||||||
@$(CC) -c $(CFLAGS) $< -o $@
|
@$(CC) -c $(CFLAGS) $< -o $@
|
||||||
$(BLD)%.o: %.cpp
|
$(BLD)%.o: %.cpp
|
||||||
-@echo [CXX $(TARGET)] $@
|
-@echo [CXX $(TARGET)] $@
|
||||||
|
@ -48,13 +49,15 @@ $(BLD)%.o: %.cpp
|
||||||
$(BLD):
|
$(BLD):
|
||||||
mkdir $(BLD)
|
mkdir $(BLD)
|
||||||
# MODULES #
|
# MODULES #
|
||||||
main.o: main.cpp io.pcm sys.pcm
|
main.o: main.cpp morse.pcm
|
||||||
|
morse.o: morse.cpp io.pcm sys.pcm
|
||||||
|
morse.pcm: morse.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 $@
|
||||||
%.pcm: %.cpp
|
%.pcm: %.cpp
|
||||||
-@echo [PRE $(TARGET)] $@
|
-@echo [PRE $(TARGET)] $@
|
||||||
@$(CXX) $(VFLAGS) -x c++-module $(TGT) -I./$(TARGET) -fno-exceptions $< --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 *~
|
||||||
|
|
|
@ -6,5 +6,11 @@ použít C++ moduly i v bare metal. Sice se to musí kompilovat
|
||||||
clang ve verzi 18. (a asi i vyšší), postup je poměrně komplikovaný
|
clang ve verzi 18. (a asi i vyšší), postup je poměrně komplikovaný
|
||||||
a nepochopitelný, ale funguje to. Zjevně je to hodně experimentální.
|
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ý
|
||||||
|
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
|
||||||
se to mohlo ujmout.
|
se to mohlo ujmout. Třeba v Arduinu.
|
||||||
|
|
44
io.cpp
44
io.cpp
|
@ -8,57 +8,57 @@ struct GpioAssocPort {
|
||||||
uint32_t clkMask;
|
uint32_t clkMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
namespace io {
|
||||||
|
/**
|
||||||
* @brief GPIO Configuration Mode enumeration
|
* @brief GPIO Configuration Mode enumeration
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
enum GPIOMode_TypeDef {
|
||||||
GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */
|
GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */
|
||||||
GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */
|
GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */
|
||||||
GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */
|
GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */
|
||||||
GPIO_Mode_AN = 0x03 /*!< GPIO Analog Mode */
|
GPIO_Mode_AN = 0x03 /*!< GPIO Analog Mode */
|
||||||
}GPIOMode_TypeDef;
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief GPIO Output type enumeration
|
* @brief GPIO Output type enumeration
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
enum GPIOOType_TypeDef {
|
||||||
GPIO_OType_PP = 0x00,
|
GPIO_OType_PP = 0x00,
|
||||||
GPIO_OType_OD = 0x01
|
GPIO_OType_OD = 0x01
|
||||||
}GPIOOType_TypeDef;
|
};
|
||||||
/**
|
/**
|
||||||
* @brief GPIO Output Maximum frequency enumeration
|
* @brief GPIO Output Maximum frequency enumeration
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
enum GPIOSpeed_TypeDef {
|
||||||
GPIO_Speed_LS = 0x00, /*!< Low speed */
|
GPIO_Speed_LS = 0x00, /*!< Low speed */
|
||||||
GPIO_Speed_MS = 0x01, /*!< Medium speed */
|
GPIO_Speed_MS = 0x01, /*!< Medium speed */
|
||||||
GPIO_Speed_FS = 0x02, /*!< Fast speed */
|
GPIO_Speed_FS = 0x02, /*!< Fast speed */
|
||||||
GPIO_Speed_HS = 0x03 /*!< Very High speed */
|
GPIO_Speed_HS = 0x03 /*!< Very High speed */
|
||||||
}GPIOSpeed_TypeDef;
|
};
|
||||||
/**
|
/**
|
||||||
* @brief GPIO Configuration PullUp PullDown enumeration
|
* @brief GPIO Configuration PullUp PullDown enumeration
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
enum GPIOPuPd_TypeDef {
|
||||||
GPIO_PuPd_NOPULL = 0x00,
|
GPIO_PuPd_NOPULL = 0x00,
|
||||||
GPIO_PuPd_UP = 0x01,
|
GPIO_PuPd_UP = 0x01,
|
||||||
GPIO_PuPd_DOWN = 0x02
|
GPIO_PuPd_DOWN = 0x02
|
||||||
}GPIOPuPd_TypeDef;
|
};
|
||||||
|
|
||||||
/** Vstupní parametry metod */
|
/** Vstupní parametry metod */
|
||||||
typedef enum {
|
enum GPIODir_TypeDef {
|
||||||
GPIO_Dir_Mode_IN = 0x00, /*!< GPIO Input Mode */
|
GPIO_Dir_Mode_IN = 0x00, /*!< GPIO Input Mode */
|
||||||
GPIO_Dir_Mode_OUT = 0x01, /*!< GPIO Output Mode */
|
GPIO_Dir_Mode_OUT = 0x01, /*!< GPIO Output Mode */
|
||||||
} GPIODir_TypeDef;
|
};
|
||||||
|
|
||||||
/// Enum pro PortNumber
|
/// Enum pro PortNumber
|
||||||
typedef enum {
|
enum GpioPortNum {
|
||||||
GpioPortA,
|
GpioPortA = 0,
|
||||||
GpioPortB,
|
GpioPortB,
|
||||||
GpioPortC,
|
GpioPortC,
|
||||||
GpioPortD,
|
GpioPortD,
|
||||||
GpioPortE,
|
GpioPortE,
|
||||||
GpioPortH,
|
GpioPortH,
|
||||||
} GpioPortNum;
|
};
|
||||||
namespace io {
|
|
||||||
/** @file
|
/** @file
|
||||||
* @brief Obecný GPIO pin.
|
* @brief Obecný GPIO pin.
|
||||||
*
|
*
|
||||||
|
@ -76,8 +76,8 @@ namespace io {
|
||||||
GpioClass (GpioPortNum const port, const uint32_t no, const GPIOMode_TypeDef type = GPIO_Mode_OUT);
|
GpioClass (GpioPortNum const port, const uint32_t no, const GPIOMode_TypeDef type = GPIO_Mode_OUT);
|
||||||
/// Nastav pin @param b na tuto hodnotu
|
/// Nastav pin @param b na tuto hodnotu
|
||||||
const GpioClass& operator<< (const bool b) const {
|
const GpioClass& operator<< (const bool b) const {
|
||||||
if (b) io->BSRR.R = (uint32_t) pos;
|
const uint32_t sh = b ? pos : pos << 16;
|
||||||
else io->BSRR.R = (uint32_t) pos << 16;
|
io->BSRR.R = sh;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
/// Nastav pin na log. H
|
/// Nastav pin na log. H
|
||||||
|
|
10
main.cpp
10
main.cpp
|
@ -1,14 +1,10 @@
|
||||||
/* SIMPLE EXAMPLE: LED blinking */
|
/* SIMPLE EXAMPLE: LED blinking */
|
||||||
import io; // use module !!!
|
import morse; // use module !!!
|
||||||
import sys;
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
static io::GpioClass led (GpioPortA, 10);
|
|
||||||
|
|
||||||
int main () {
|
int main () {
|
||||||
sys::init ();
|
Morse morse (330);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
~led; // change status - unary ~
|
morse << "Hello world";
|
||||||
sys::delay ();
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
87
morse.cpp
Normal file
87
morse.cpp
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
module;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Morse {
|
||||||
|
const unsigned unit;
|
||||||
|
const io::GpioClass led;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Morse (const unsigned ms = 100) noexcept : unit (ms), led (io::GpioPortA, 10) {
|
||||||
|
sys::init ();
|
||||||
|
}
|
||||||
|
void operator<< (const char * text) const;
|
||||||
|
protected:
|
||||||
|
void out (const char * text) 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;
|
||||||
|
if (c < '\x20') {
|
||||||
|
mp = morse_code [0];
|
||||||
|
} else if (c < '`') {
|
||||||
|
const int i = c - '\x20';
|
||||||
|
mp = morse_code [i];
|
||||||
|
} else if (c == '`') {
|
||||||
|
mp = morse_code [0];
|
||||||
|
} else if (c <= 'z') {
|
||||||
|
const int i = c - '\x40';
|
||||||
|
mp = morse_code [i];
|
||||||
|
} else {
|
||||||
|
mp = morse_code [0];
|
||||||
|
}
|
||||||
|
if (!mp) return;
|
||||||
|
out (mp);
|
||||||
|
}
|
||||||
|
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
|
||||||
|
* */
|
||||||
|
void Morse::out (const char * text) const {
|
||||||
|
const unsigned len = slen(text);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
led << false;
|
||||||
|
}
|
||||||
|
sys::delay (3 * unit);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue