diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a02e3b..c3b40be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ add_executable(stm32-blinky-f1 stm32f1xx_hal_conf.h ) -set_property(TARGET stm32-blinky-f1 PROPERTY CXX_STANDARD 17) +set_property(TARGET stm32-blinky-f1 PROPERTY CXX_STANDARD 20) target_link_libraries(stm32-blinky-f1 HAL::STM32::F1::UART diff --git a/logging.hpp b/logging.hpp index db3c711..45b6ce5 100644 --- a/logging.hpp +++ b/logging.hpp @@ -59,32 +59,45 @@ class log { return logger_impl.init(); } - static void error(std::string_view message) { - log_impl(LogLevel::ERROR, message); + template + static void error(Args&&... args) { + log_impl_begin(LogLevel::ERROR); + log_impl(std::forward(args)...); } - static void debug(std::string_view message) { - log_impl(LogLevel::DEBUG, message); + template + static void debug(Args&&... args) { + log_impl_begin(LogLevel::DEBUG); + log_impl(std::forward(args)...); } - static void info(std::string_view message) { - log_impl(LogLevel::INFO, message); + template + static void info(Args&&... args) { + log_impl_begin(LogLevel::INFO); + log_impl(std::forward(args)...); } static void set_loglevel(LogLevel level) { log_level = level; } private: - static void log_impl(LogLevel level, std::string_view message) { + static bool log_impl_begin(LogLevel level) { if (log_level < level) { - return; + return false; } - // std::stringstream msg; - // msg << get_loglevel_string(level) << ": " << message; logger->log(get_loglevel_string(level)); logger->log(": "); - logger->log(message); + return true; + } + template + static void log_impl(std::string_view message, Args&&... args) { + logger->log(message); + log_impl(std::forward(args)...); + } + + static void log_impl(std::string_view message) { + logger->log(message); constexpr std::string_view carriage_return{"\r\n"}; logger->log(carriage_return); } diff --git a/main.cpp b/main.cpp index 78892a7..3002c35 100644 --- a/main.cpp +++ b/main.cpp @@ -26,18 +26,25 @@ extern uint8_t LoRa_buff[RH_RF95_FIFO_SIZE]; extern SPI_HandleTypeDef hspi1; void print_version(void) { log::info("running PentaTrack v0.1.3"); } +void print_help(void); +template class cmd_holder { public: typedef void (*functionPointerType)(void); - void add_cmd(std::string_view msg, functionPointerType func) { - commands[amount_cmds++] = std::make_tuple(msg, func); - } + using command_t = + std::tuple; + template + using command_array_t = std::array; - functionPointerType get_func(std::string_view message) const { - for (const auto &[msg, func] : commands) { - if (message == msg) { + template + consteval cmd_holder(Args... command_list) + : commands{std::forward(command_list)...} {} + + constexpr functionPointerType get_func(std::string_view message) const { + for (const auto &[cmd_name, cmd_help, func] : commands) { + if (message == cmd_name) { return func; } } @@ -45,29 +52,35 @@ class cmd_holder { return nullptr; } + void print_help() const { + log::info("Listing available commands:"); + for (const auto &[cmd_name, cmd_help, func] : commands) { + log::info("\t", cmd_name, " - ", cmd_help); + } + } + private: - std::array, 12> commands; - size_t amount_cmds = 0; + std::array commands; }; class cmd_handler { public: - using array_t = std::array; + static constexpr auto MaxCmdLength = 24; + using array_t = std::array; using iterator_t = array_t::iterator; using const_iterator_t = array_t::const_iterator; - cmd_handler() : symbols{}, iterator{symbols.begin()} { - commands.add_cmd("ver", &print_version); - } - - static cmd_handler *get_instance() { - static cmd_handler handler{}; - - return &handler; - } + consteval cmd_handler() + : commands{std::make_tuple("ver", "Prints current version.", + &print_version), + std::make_tuple("help", "Prints available commands", + &print_help)}, + symbols{}, + iterator{symbols.begin()} {} void add_symbol(uint8_t symbol) { - *iterator++ = symbol; + *iterator = symbol; + iterator++; if (iterator == symbols.end()) { iterator = symbols.begin(); } @@ -79,15 +92,45 @@ class cmd_handler { std::distance(symbols.begin(), const_iterator_t{iterator}))}; } - void log_current_command() { log::debug(get_current_cmd()); } + bool exists() const { + return commands.get_func(get_current_cmd()) != nullptr; + } + + void execute() { + const auto current_cmd = get_current_cmd(); + log::debug("Try executing command: ", current_cmd); + const auto func = commands.get_func(current_cmd); + iterator = symbols.begin(); + + if (func == nullptr) { + return; + } + + func(); + } + + void queue_execution() { ShouldExecute = true; } + + void run() { + if (ShouldExecute) { + execute(); + ShouldExecute = false; + } + } + + void print_help_() const { commands.print_help(); } private: - cmd_holder commands; - + cmd_holder<2> commands; array_t symbols; iterator_t iterator; + bool ShouldExecute = false; }; +static cmd_handler commands{}; + +void print_help(void) { commands.print_help_(); } + // cmd_handler::array_t cmd_handler::symbols = cmd_handler::array_t{}; // cmd_handler::iterator_t cmd_handler::iterator = cmd_handler::iterator_t{}; @@ -105,13 +148,15 @@ void USART1_IRQHandler(void) { } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { - const char value = *reinterpret_cast(uart_interface::get_buf()); + const uint8_t value = *uart_interface::get_buf(); if (value == '\r') { + commands.queue_execution(); HAL_GPIO_TogglePin(LED_PORT, LED2_PIN); + return; } - log::debug({&value, 1}); + commands.add_symbol(value); } } @@ -187,8 +232,9 @@ int main(void) { HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); // RF95_Init(); - int i = 0; while (1) { + commands.run(); + // RF95_setModeRx_Continuous(); HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET); // RF95_receive(LoRa_buff);