renderbug/src/inputs/Serial.cpp

173 lines
3.4 KiB
C++
Raw Normal View History

#include "Serial.h"
2023-12-11 06:57:22 +00:00
#include "../Static.h"
#include <LittleFS.h>
#include "../Config.h"
#include "../Sequencer.h"
SerialInput::SerialInput() : InputSource("Serial"),
m_state(ParseState::Normal),
m_logPrinter(this)
{
}
void
SerialInput::redrawPrompt()
{
if (m_canRedraw) {
Serial.print((char)8);
Serial.print((char)27);
Serial.print("[2K");
Serial.print((char)8);
Serial.print((char)27);
Serial.print("[G");
Serial.print('\r');
Serial.print("> ");
Serial.print(m_buf);
}
}
InputEvent
2023-12-11 06:57:22 +00:00
SerialInput::parseNormal(char nextChar)
{
2023-12-11 06:57:22 +00:00
if (nextChar == 27) {
m_state = ParseState::EscapeSequence;
return InputEvent::None;
}
if (nextChar == 13) {
redrawPrompt();
Serial.println();
if (m_buf.length() > 0) {
m_canRedraw = false;
doCommand();
2023-12-11 06:57:22 +00:00
m_canRedraw = true;
m_history.insert(m_buf);
m_buf = "";
2023-12-11 06:57:22 +00:00
}
m_historyOffset = 0;
redrawPrompt();
return InputEvent{};
}
if (nextChar == 8) {
if (m_buf.length() > 0) {
m_buf.remove(m_buf.length() - 1, 1);
}
Serial.print((char)8);
Serial.print((char)27);
Serial.print("[K");
redrawPrompt();
return InputEvent::None;
}
if (nextChar >= 32 && nextChar <= 126) {
m_buf += nextChar;
Serial.print(nextChar);
}
return InputEvent::None;
}
InputEvent
SerialInput::parseEscape(char nextChar)
{
if (nextChar == '[') {
m_state = ParseState::CSI;
} else {
m_state = ParseState::Normal;
}
return InputEvent::None;
}
InputEvent
SerialInput::parseCSI(char nextChar)
{
if (nextChar == 'A') {
if (m_historyOffset < m_history.size()) {
m_historyOffset += 1;
m_buf = m_history.peek(m_historyOffset);
redrawPrompt();
} else {
Serial.print((char)7);
}
} else if (nextChar == 'B') {
if (m_historyOffset > 0) {
m_historyOffset -= 1;
m_buf = m_history.peek(m_historyOffset);
redrawPrompt();
} else {
2023-12-11 06:57:22 +00:00
Serial.print((char)7);
}
} else {
Serial.print((char)7);
}
m_state = ParseState::Normal;
return InputEvent::None;
}
InputEvent
SerialInput::read()
{
while (Serial.available() > 0) {
char nextChar = Serial.read();
InputEvent ret = InputEvent::None;
switch (m_state) {
case ParseState::Normal:
ret = parseNormal(nextChar);break;
case ParseState::EscapeSequence:
ret = parseEscape(nextChar);break;
case ParseState::CSI:
ret = parseCSI(nextChar);break;
}
if (ret != InputEvent::None) {
return ret;
}
}
2023-12-11 06:57:22 +00:00
return InputEvent::None;
}
void
2023-12-11 06:57:22 +00:00
doHelp(Args& args, Print& out)
{
out.println("Available commands:");
auto sched = MainLoop::instance()->scheduler;
for(auto task : sched.tasks) {
for(auto &command : task->commands()) {
out.print(command.name);
out.print(" ");
}
}
out.println();
}
const std::vector<Command> serialCommands = {
{"help", doHelp}
};
const std::vector<Command>&
SerialInput::commands() const
{
return serialCommands;
}
void
SerialInput::doCommand() {
auto sched = MainLoop::instance()->scheduler;
Args args = Args(&m_buf);
const auto cmdName = args[0];
for(auto task : sched.tasks) {
for(auto &command : task->commands()) {
if (cmdName == command.name) {
command.func(args, m_logPrinter);
return;
}
}
}
2023-12-11 06:57:22 +00:00
m_logPrinter.println("Unknown command");
doHelp(args, m_logPrinter);
}
STATIC_ALLOC(SerialInput);
STATIC_TASK(SerialInput);