diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp index 8d135931c..f63690d74 100644 --- a/esp32_marauder/CommandLine.cpp +++ b/esp32_marauder/CommandLine.cpp @@ -1,6 +1,10 @@ #include "CommandLine.h" CommandLine::CommandLine() { + if (!serial_buffer_initialized) { + memset(CommandLine::serial_buffer, '\0', 255); + serial_buffer_initialized = true; + } } void CommandLine::RunSetup() { @@ -25,29 +29,43 @@ String CommandLine::getSerialInput() { if (Serial.available() > 0 && serial_buffer_idx < 255) { bytes_available = Serial.available(); - //Serial.println("Should have bytes available: " + bytes_available); int bytes_to_read = bytes_available < (254 - serial_buffer_idx) ? bytes_available : (254 - serial_buffer_idx); bytes_received = Serial.readBytes(&serial_buffer[serial_buffer_idx], bytes_to_read); - // echo what we just got to the terminal + // Echo what we just got to the terminal for (int i = serial_buffer_idx; i < serial_buffer_idx + bytes_received; i++) { - // support backspace + // Support backspace if (serial_buffer[i] == '\x7f') { - for (int j = i; j < 255; j++) { - if (j == 0) { + // j starts at i + 1 which is the next + // valid character. We skip copying the + // backspace Ox7f character. + for (int j = i + 1; j < 255; j++) { + if (j <= 1) { break; - } else if (j == 254 || j > serial_buffer_idx) { + } else if (j == 254 || j > serial_buffer_idx + bytes_received) { serial_buffer[j] = '\0'; } else { - serial_buffer[j-1] = serial_buffer[j]; + serial_buffer[j-2] = serial_buffer[j]; } } - serial_buffer_idx--; + if (serial_buffer_idx > 0) { + Serial.print('\b'); + Serial.print(' '); + Serial.print('\b'); + } + // This is kinda weird because we decrement serial_buffer_idx ... + // there's a better way to do this I'm sure. TODO(jstockdale): Fix me! + serial_buffer_idx = (serial_buffer_idx >= 1) ? serial_buffer_idx - 2 : (bytes_received == 1) ? -1 : 0; + // send cursor back on serial console, blank previous character, send cursor back once more + } + // Skip printing \n or \r to the terminal + if (serial_buffer[i] != '\n' && serial_buffer[i] != '\r') { + Serial.print(serial_buffer[i]); } - Serial.print(serial_buffer[i]); } - + serial_buffer_idx += bytes_received; + if (serial_buffer_idx < 254) { serial_buffer[serial_buffer_idx+1] = '\0'; } else if (serial_buffer_idx >= 254) { @@ -61,18 +79,20 @@ String CommandLine::getSerialInput() { int index_of_newline = -1; for (int i = 0; i < serial_buffer_idx; i++) { -// Serial.println("Checking character at: " + String(i) + " it appears to be: " + String(serial_buffer[i])); -// Serial.print("Hex value of character: "); -// Serial.print(serial_buffer[i], HEX); -// Serial.println(); - // this is mind boggling but hey. why not. :D + // This is mind boggling that we sometimes + // just get \r and not \n and also not \r\n ... + // but hey. why not. :D I inspected the hex values + // and this is definitely what's coming over the line. + // We try to handle all of the possible combinations. if (serial_buffer[i] == '\n' || serial_buffer[i] == '\r') { //Serial.println("Found \"newline\" at index: " + String(i)); index_of_newline = i; - if (index_of_newline == 0) { - command_buffer[i] = index_of_newline == 0 ? '\n' : '\0'; + if (i == 0) { + command_buffer[0] = '\n'; } + } else if (i == 254) { + command_buffer[i] = '\0'; } else { command_buffer[i] = serial_buffer[i]; } @@ -81,24 +101,30 @@ String CommandLine::getSerialInput() { command_line = command_buffer; if (index_of_newline > -1) { - serial_buffer_idx = 0; - if (serial_buffer[index_of_newline] == '\r' && serial_buffer[index_of_newline+1] == '\n') { - index_of_newline++; - } - + // if we got a \r with a \n, treat the \n as the correct newline + if (serial_buffer[index_of_newline] == '\r' && serial_buffer[index_of_newline+1] == '\n') { + index_of_newline++; + } + // Move the unconsumed portion of the buffer over + // and zero extra bytes. for (int i = index_of_newline + 1; i < 255; i++) { - if(serial_buffer[i] == '\0') { - break; - } else if (i > index_of_newline + 1 || i == 254) { - // Always zero extra bytes and null terminate no matter what - serial_buffer[i]='\0'; - } else { - // Copy any characters we have after the newline - // but before the null terminator. If they exist. - serial_buffer[i - (index_of_newline + 1)] = serial_buffer[i]; - } + // Copy any characters we have after the newline, if they exist + serial_buffer[i - (index_of_newline + 1)] = serial_buffer[i]; + serial_buffer[i] = '\0'; } + // make sure to set correct buffer index for remaining data + serial_buffer_idx = serial_buffer_idx - (index_of_newline + 1); + + command_line.trim(); + return command_line; + } else if (index_of_newline == -1 && serial_buffer_idx == 254) { + // flush buffer if we're full; don't let it overrun + Serial.println("Serial buffer full! Processing command and flushing buffer."); + serial_buffer_idx = 0; + for (int i = 0; i < 255; ++i) { + serial_buffer[i] = '\0'; + } command_line.trim(); return command_line; } else { @@ -109,8 +135,9 @@ String CommandLine::getSerialInput() { void CommandLine::main(uint32_t currentTime) { String input = this->getSerialInput(); - if (input != "\n") + if (input != "\n") { this->runCommand(input); + } if (input != "") Serial.print("> "); @@ -281,7 +308,7 @@ void CommandLine::runCommand(String input) { if (input != STOPSCAN_CMD) return; } else - Serial.println("#" + input); + Serial.println("\r# " + input); LinkedList cmd_args = this->parseCommand(input, " "); diff --git a/esp32_marauder/CommandLine.h b/esp32_marauder/CommandLine.h index 7749e6266..7a76159ba 100644 --- a/esp32_marauder/CommandLine.h +++ b/esp32_marauder/CommandLine.h @@ -152,6 +152,7 @@ class CommandLine { private: static char serial_buffer[255]; static int serial_buffer_idx; + static bool serial_buffer_initialized; String getSerialInput(); LinkedList parseCommand(String input, char* delim); String toLowerCase(String str); @@ -198,7 +199,8 @@ class CommandLine { void main(uint32_t currentTime); }; -int CommandLine::serial_buffer_idx = 0; char CommandLine::serial_buffer[255]; +int CommandLine::serial_buffer_idx = 0; +bool CommandLine::serial_buffer_initialized = false; #endif