Keisuke Sehara
/
STM32_Whisking
fast-feedback virtual target task code on STM Nucleo
Diff: core/config.cpp
- Revision:
- 26:b4421d1ee57a
- Parent:
- 8:973dcd190672
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/config.cpp Thu Jul 05 20:15:37 2018 +0000 @@ -0,0 +1,200 @@ +#include "config.h" +#include "IO.h" + +namespace config { + + struct HelpResponder: public CommandResponder + { + virtual ~HelpResponder() { } + + virtual bool parse(const char& c) + { + if (c != CMD_CHAR_HELP) { + return false; + } + writeSettingsToSerial(); + return true; + } + + virtual bool writeSettings() { + return false; + } + + virtual void echoback() { + // do nothing + } + }; + + HelpResponder* help_ = 0; + + struct CallbackHandler + { + char command; + CommandResponder* responder; + + CallbackHandler* prev; + CallbackHandler* next; + + + private: + + CallbackHandler(const char& command, CommandResponder* resp): + command(command), responder(resp), prev(0), next(0) { } + + static void append(CallbackHandler** list, CallbackHandler* item) { + + if ((*list) == 0) { + // no content + (*list) = item; + item->prev = 0; + item->next = 0; + + } else { + // search the end of the list + CallbackHandler* current = *list; + while(current->next != 0) { + current = current->next; + } + + current->next = item; + item->prev = current; + item->next = 0; + } + } + + static void drop(CallbackHandler** head, CallbackHandler* item) { + + if (item == 0) { + return; + } + + if (item == *head) { + *head = item->next; + } else { + item->prev->next = item->next; + } + if (item->next != 0) { + item->next->prev = item->prev; + } + + delete item; + } + + public: + + static void append(CallbackHandler** list, const char& command, CommandResponder* resp) { + append(list, new CallbackHandler(command, resp)); + } + + static void drop(CallbackHandler** head, const char& command) { + CallbackHandler* current = *head; + + // check for `command` from the head to the tail + while( current != 0 ){ + if (current->command == command) { + // drop this + drop(head, current); + return; + } + + current = current->next; + } + } + + static CallbackHandler* helpCommand(const char& command) { + return new CallbackHandler(command, help_); + } + }; + + + CallbackHandler* handlers_ = 0; + + void initialize_() { + help_ = new HelpResponder(); + CallbackHandler::append(&handlers_, CMD_CHAR_HELP, help_); + } + + void addCommand(const char& command, CommandResponder* resp) + { + if (handlers_ == 0) { + initialize_(); + } + CallbackHandler::append(&handlers_, command, resp); + } + + void removeCommand(const char& command) + { + if (handlers_ == 0) { + initialize_(); + } + CallbackHandler::drop(&handlers_, command); + } + + void handleSerial() + { + char in = IO::getc(); + + if (isWhitespace(in)) { + return; + } + + CallbackHandler* current = handlers_; + while(current != 0) { + + if ( current->responder->parse(in) ) { + // the handler accepted the input character + break; + } + current = current->next; + } + + if (current != 0) { + current->responder->echoback(); + + } else { + // no matched handler + IO::error("%c",in); + } + } + + void writeSettingsToSerial() { + IO::write(IO::CONFIG_HEADER); + + CallbackHandler* current = handlers_; + + while (current != 0) { + if (current->responder->writeSettings()) { + // some output occurred + IO::write(STR_DELIMITER); + } + current = current->next; + } + IO::write(STR_NEWLINE); + } +} + +Action::Action(const char& command, Callback<void()> f): + command_(command), handler_(f) +{ + config::addCommand(command_, this); +} + +Action::~Action() +{ + config::removeCommand(command_); +} + +bool Action::parse(const char& c) +{ + if (c != command_) { + return false; + } + handler_(); + return true; +} + +bool Action::writeSettings() { return false; } + +void Action::echoback() { + // IO::result("done"); +}