diff --git a/plugins/Kaleidoscope-FocusSerial/src/kaleidoscope/plugin/FocusSerial.cpp b/plugins/Kaleidoscope-FocusSerial/src/kaleidoscope/plugin/FocusSerial.cpp index abd7ee6e..f8669d00 100644 --- a/plugins/Kaleidoscope-FocusSerial/src/kaleidoscope/plugin/FocusSerial.cpp +++ b/plugins/Kaleidoscope-FocusSerial/src/kaleidoscope/plugin/FocusSerial.cpp @@ -25,39 +25,59 @@ namespace kaleidoscope { namespace plugin { char FocusSerial::command_[32]; - -void FocusSerial::drain(void) { - if (Runtime.serialPort().available()) - while (Runtime.serialPort().peek() != '\n') - Runtime.serialPort().read(); -} +uint8_t FocusSerial::buf_cursor_ = 0; EventHandlerResult FocusSerial::afterEachCycle() { - if (Runtime.serialPort().available() == 0) + // If the serial buffer is empty, we don't have any work to do + if (Runtime.serialPort().available() == 0) { return EventHandlerResult::OK; + } - uint8_t i = 0; do { - command_[i++] = Runtime.serialPort().read(); + command_[buf_cursor_++] = Runtime.serialPort().read(); + } while (command_[buf_cursor_ - 1] != SEPARATOR + && buf_cursor_ < sizeof(command_) + && Runtime.serialPort().available() + && (Runtime.serialPort().peek() != NEWLINE)); - if (Runtime.serialPort().peek() == '\n') - break; - } while (command_[i - 1] != ' ' && i < 32); - if (command_[i - 1] == ' ') - command_[i - 1] = '\0'; - else - command_[i] = '\0'; - Runtime.onFocusEvent(command_); - - Runtime.serialPort().println(F("\r\n.")); + // If there was no command, there's nothing to do + if (command_[0] == '\0') { + buf_cursor_ = 0; + memset(command_, 0, sizeof(command_)); + return EventHandlerResult::OK; + } - drain(); + if ((command_[buf_cursor_ - 1] != SEPARATOR) && (Runtime.serialPort().peek() != NEWLINE) + && buf_cursor_ < sizeof(command_) + ) { + // We don't have enough command to work with yet. + // Let's leave the buffer around for another cycle + return EventHandlerResult::OK; + } - if (Runtime.serialPort().peek() == '\n') - Runtime.serialPort().read(); + // If this was a command with a space-delimited payload, + // strip the space delimiter off + if ((command_[buf_cursor_ - 1] == SEPARATOR)) { + command_[buf_cursor_ - 1] = '\0'; + } + // Then process the command + Runtime.onFocusEvent(command_); + while (Runtime.serialPort().available()) { + char c = Runtime.serialPort().read(); + if (c == NEWLINE) { + // newline serves as an end-of-command marker + // don't drain the buffer past there + break; + } + } + // End of command processing is signalled with a CRLF followed by a single period + Runtime.serialPort().println(F("\r\n.")); + buf_cursor_ = 0; + memset(command_, 0, sizeof(command_)); return EventHandlerResult::OK; + } bool FocusSerial::handleHelp(const char *command, diff --git a/plugins/Kaleidoscope-FocusSerial/src/kaleidoscope/plugin/FocusSerial.h b/plugins/Kaleidoscope-FocusSerial/src/kaleidoscope/plugin/FocusSerial.h index 0c39937b..231bd2a5 100644 --- a/plugins/Kaleidoscope-FocusSerial/src/kaleidoscope/plugin/FocusSerial.h +++ b/plugins/Kaleidoscope-FocusSerial/src/kaleidoscope/plugin/FocusSerial.h @@ -25,6 +25,10 @@ class FocusSerial : public kaleidoscope::Plugin { public: FocusSerial(void) {} + static constexpr char COMMENT = '#'; + static constexpr char SEPARATOR = ' '; + static constexpr char NEWLINE = '\n'; + bool handleHelp(const char *command, const char *help_message); @@ -83,12 +87,9 @@ class FocusSerial : public kaleidoscope::Plugin { } bool isEOL() { - return Runtime.serialPort().peek() == '\n'; + return Runtime.serialPort().peek() == NEWLINE; } - static constexpr char COMMENT = '#'; - static constexpr char SEPARATOR = ' '; - static constexpr char NEWLINE = '\n'; /* Hooks */ EventHandlerResult afterEachCycle(); @@ -96,8 +97,7 @@ class FocusSerial : public kaleidoscope::Plugin { private: static char command_[32]; - - static void drain(void); + static uint8_t buf_cursor_; static void printBool(bool b); }; }