mirror of
https://github.com/suchmememanyskill/CYD-Klipper.git
synced 2026-03-22 06:03:23 +00:00
161 lines
4.9 KiB
C++
161 lines
4.9 KiB
C++
#include "serial_commands.h"
|
|
#include "../../conf/global_config.h"
|
|
#include <HardwareSerial.h>
|
|
#include <WString.h>
|
|
|
|
#define MAX_COMDLINE_SIZE 80
|
|
#define MAX_WORDS 6
|
|
|
|
namespace serial_console
|
|
{
|
|
bool global_disable_serial_console = false;
|
|
|
|
/*
|
|
* read_string_until: Non-blocking replacement for Serial.readStringUntil()..
|
|
* With delimeter '\n' acts as 'read line'.
|
|
* If input (line) size exceeds provided buffer's size, that entire input (until next delimeter) is silently discarded.
|
|
* Serial.available() can return true without \n being ever in the buffer, so we don't trust it here.
|
|
*/
|
|
|
|
bool read_string_until(char delimiter, char *result, int max_len)
|
|
{
|
|
static int index = 0;
|
|
int c; // read character, -1 if none
|
|
int cnt = 100; // limit on amount of iterations in one go; we're supposed to be non-blocking!
|
|
|
|
while ((c = Serial.read()) != -1 && cnt > 0)
|
|
{
|
|
--cnt;
|
|
|
|
// backspaceF
|
|
if (c == 8)
|
|
{
|
|
if (index > 0)
|
|
{
|
|
if(temporary_config.remote_echo) Serial.print("\x08 \x08"); // overwrite last character with space and move cursor 1 back.
|
|
index--;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if(temporary_config.remote_echo) Serial.print((char)c); // echo
|
|
|
|
// Buffer overflow handling:
|
|
// start treating current buffer as invalid:
|
|
// - stop collecting more data
|
|
// - return false on delimeter, flushing everything collected,
|
|
// - restart collection from scratch after delimeter,
|
|
// - return control as normal.
|
|
|
|
if (index >= max_len - 1)
|
|
{
|
|
if (c == delimiter) // got delimeter: flush buffer quietly, restart collection.
|
|
{
|
|
index = 0;
|
|
return false;
|
|
}
|
|
else
|
|
continue; // discard any data past the end of the buffer, keep reading
|
|
}
|
|
|
|
result[index++] = c;
|
|
|
|
// delimiter was found
|
|
if (c == delimiter)
|
|
{
|
|
result[index] = '\0'; // Null-terminate the string
|
|
index = 0;
|
|
return true; // Success: Delimiter found
|
|
}
|
|
}
|
|
|
|
return false; // still waiting for delimeter
|
|
}
|
|
|
|
// split input into words.
|
|
// assumes input ends with '\n', also ends parsing if found MAX_WORDS already.
|
|
int tokenize(String results[], char *input)
|
|
{
|
|
int index = 0;
|
|
int word_count = 0;
|
|
String word = "";
|
|
do
|
|
{
|
|
if (input[index] == '\t' || (input[index] == ' ' && (index <= 0 || input[index - 1] != '\\')) || input[index] == '\n' || input[index] == '\r' || input[index] == '\0')
|
|
{
|
|
if (word.length() > 0)
|
|
{
|
|
results[word_count] = word;
|
|
++word_count;
|
|
if (word_count >= MAX_WORDS)
|
|
{
|
|
return word_count;
|
|
}
|
|
word = "";
|
|
}
|
|
|
|
if (input[index] == '\n' || input[index] == '\0')
|
|
{
|
|
return word_count;
|
|
}
|
|
index++;
|
|
}
|
|
else
|
|
{
|
|
if (input[index] != '\\')
|
|
{
|
|
word += input[index];
|
|
}
|
|
|
|
index++;
|
|
}
|
|
} while (1);
|
|
}
|
|
|
|
void greet()
|
|
{
|
|
Serial.println("CYD-Klipper " REPO_VERSION);
|
|
Serial.println("Type 'help' for serial console command list");
|
|
Serial.print("> ");
|
|
}
|
|
|
|
bool verify_arg_count(int got, int expected)
|
|
{
|
|
if (got != expected)
|
|
{
|
|
Serial.printf("Command expects %d argument%s, %d given.\n", expected - 1, expected == 2 ? "" : "s", got - 1);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// main "engine": non-blockingly read until newline found, parse, execute.
|
|
void run()
|
|
{
|
|
if (global_disable_serial_console)
|
|
return;
|
|
|
|
static char cmdline[MAX_COMDLINE_SIZE + 1] = {0};
|
|
if (!read_string_until('\n', cmdline, MAX_COMDLINE_SIZE))
|
|
return;
|
|
|
|
String argv[MAX_WORDS];
|
|
int argc = tokenize(argv, cmdline);
|
|
|
|
if (argc > 0)
|
|
{
|
|
do
|
|
{
|
|
int cmd_id = find_command(argv[0]);
|
|
if (cmd_id == -1)
|
|
break;
|
|
if (!verify_arg_count(argc, commandHandlers[cmd_id].argc))
|
|
break;
|
|
commandHandlers[cmd_id].function(argv);
|
|
} while (0);
|
|
}
|
|
|
|
Serial.print("> ");
|
|
}
|
|
|
|
} |