OpenMicroManipulator/firmware/MotionControllerRP/src/command_parser/command_parser.cpp
0x23 dc0278ea2b * improved hw_config file
* added retract angle to homing
* v1.0.3
2025-10-22 19:09:09 +02:00

172 lines
4.5 KiB
C++

//*** INCLUDE ***************************************************************************
#include "command_parser.h"
#include <cstring>
//*** CLASS *****************************************************************************
//--- GCodeCommand ----------------------------------------------------------------------
GCodeCommand::GCodeCommand() {
reset();
}
void GCodeCommand::set_command(const char* cmd) {
if (cmd) {
command = cmd;
} else {
command = "";
}
}
const std::string& GCodeCommand::get_command() const {
return command;
}
void GCodeCommand::reset() {
// Initialize all word values to NaN to represent "not set"
for (float& value : word_values) {
value = std::numeric_limits<float>::quiet_NaN();
}
command[0] = 0;
}
void GCodeCommand::set_value(char word, float value) {
if (word >= 'A' && word <= 'Z') {
word_values[word-'A'] = value;
}
}
float GCodeCommand::get_value(char word) const {
return get_value(word, std::numeric_limits<float>::quiet_NaN());
}
float GCodeCommand::get_value(char word, float default_value) const {
if (word >= 'A' && word <= 'Z') {
float value = word_values[word-'A'];
return std::isnan(value) ? default_value : value;
}
return default_value;
}
bool GCodeCommand::has_word(char word) const {
if (word >= 'A' && word <= 'Z') {
return !std::isnan(word_values[word-'A']);
}
return false;
}
int GCodeCommand::get_word_count() const {
int c = 0;
for(int i=0; i<LETTER_COUNT; i++) {
if(std::isnan(word_values[i]))
c++;
}
return c;
}
bool GCodeCommand::contains_unsupported_words(const std::string& supported_words_str) const {
// Parse supported words from the string into a fixed-size lookup table
bool supported[LETTER_COUNT] = {false};
// Parse the supported letters from the comma-separated string
for (size_t i = 0; i < supported_words_str.length(); ++i) {
char c = supported_words_str[i];
if (c >= 'A' && c <= 'Z')
supported[c - 'A'] = true;
}
// Now check which words are used in the command and not supported
for (int i = 0; i < LETTER_COUNT; ++i) {
char word = 'A' + i;
if (has_word(word) && !supported[i]) {
return true; // Found an unsupported word
}
}
return false; // All words used in command are supported
}
//--- CommandParser ---------------------------------------------------------------------
CommandParser::CommandParser() : buffer_index(0), command_processor(nullptr) {
}
void CommandParser::set_command_processor(ICommandProcessor* cp) {
command_processor = cp;
}
void CommandParser::update() {
if(command_processor == nullptr)
return;
if(command_ready == false)
return;
// Call user callback with parsed command
if(command_processor->can_process_command(command)) {
std::string reply;
command_processor->process_command(command, reply);
command_processor->send_reply(reply.c_str());
// mark command as processed
command_ready = false;
}
}
// Feed input chars one by one
void CommandParser::add_input_character(char c) {
if (c == '\n' || c == '\r') {
if (buffer_index > 0) {
buffer[buffer_index] = '\0';
parse_line(buffer);
buffer_index = 0;
}
} else if (buffer_index < sizeof(buffer) - 1) {
buffer[buffer_index++] = c;
}
}
bool CommandParser::parse_line(const char* line) {
command_ready = false;
// Copy line into a mutable buffer
char line_copy[256];
strncpy(line_copy, line, sizeof(line_copy));
line_copy[sizeof(line_copy) - 1] = '\0';
// Tokenize the first word (e.g., G0, M3, T1)
char* saveptr = nullptr;
char* token = strtok_r(line_copy, " ", &saveptr);
if (!token || token[0] < 'A' || token[0] > 'Z') {
command_processor->send_reply("error: malformed command\n");
return false;
}
command.reset();
command.set_command(token);
// Parse remaining words (e.g., X1.0, Y2.5, F200)
while ((token = strtok_r(nullptr, " ", &saveptr))) {
if (token[0] >= 'A' && token[0] <= 'Z') {
if(token[1] == '\0')
command.set_value(token[0], 0.0f);
else
command.set_value(token[0], strtof(token + 1, nullptr));
} else {
command_processor->send_reply("error: invalid parameter\n");
return false;
}
}
command_ready = true;
return true;
}
// returns false if the command could not yet be processed.
// The function will be called witht the same command later to try again.
bool CommandParser::handle_gcode_command(const GCodeCommand& cmd) {
return false;
}