Backport meatpack feature from upstream

This commit is contained in:
Ashley Sommer
2021-08-20 13:45:16 +10:00
parent b3f4dcb2d1
commit 92bfd1b495
13 changed files with 491 additions and 111 deletions

View File

@@ -43,6 +43,10 @@ GCodeQueue queue;
#include "../feature/binary_protocol.h"
#endif
#if ENABLED(MEATPACK)
#include "../feature/meatpack.h"
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
#include "../feature/powerloss.h"
#endif
@@ -73,7 +77,7 @@ char GCodeQueue::command_buffer[BUFSIZE][MAX_CMD_SIZE];
* The port that the command was received on
*/
#if NUM_SERIAL > 1
int16_t GCodeQueue::port[BUFSIZE];
serial_index_t GCodeQueue::port[BUFSIZE];
#endif
/**
@@ -116,12 +120,12 @@ void GCodeQueue::clear() {
*/
void GCodeQueue::_commit_command(bool say_ok
#if NUM_SERIAL > 1
, int16_t p/*=-1*/
, serial_index_t serial_ind/*=-1*/
#endif
) {
send_ok[index_w] = say_ok;
#if NUM_SERIAL > 1
port[index_w] = p;
port[index_w] = serial_ind;
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
recovery.commit_sdpos(index_w);
@@ -137,14 +141,14 @@ void GCodeQueue::_commit_command(bool say_ok
*/
bool GCodeQueue::_enqueue(const char* cmd, bool say_ok/*=false*/
#if NUM_SERIAL > 1
, int16_t pn/*=-1*/
, serial_index_t serial_ind/*=-1*/
#endif
) {
if (*cmd == ';' || length >= BUFSIZE) return false;
strcpy(command_buffer[index_w], cmd);
_commit_command(say_ok
#if NUM_SERIAL > 1
, pn
, serial_ind
#endif
);
return true;
@@ -256,9 +260,9 @@ void GCodeQueue::enqueue_now_P(PGM_P const pgcode) {
*/
void GCodeQueue::ok_to_send() {
#if NUM_SERIAL > 1
const int16_t pn = port[index_r];
if (pn < 0) return;
PORT_REDIRECT(pn); // Reply to the serial port that sent the command
const serial_index_t serial_ind = command_port();
if (serial_ind < 0) return; // Never mind. Command came from SD or Flash Drive
PORT_REDIRECT(serial_ind); // Reply to the serial port that sent the command
#endif
if (!send_ok[index_r]) return;
SERIAL_ECHOPGM(STR_OK);
@@ -282,9 +286,9 @@ void GCodeQueue::ok_to_send() {
*/
void GCodeQueue::flush_and_request_resend() {
#if NUM_SERIAL > 1
const int16_t pn = port[index_r];
if (pn < 0) return;
PORT_REDIRECT(pn); // Reply to the serial port that sent the command
const serial_index_t serial_ind = port[index_r];
if (serial_ind < 0) return;
PORT_REDIRECT(serial_ind); // Reply to the serial port that sent the command
#endif
SERIAL_FLUSH();
SERIAL_ECHOPGM(STR_RESEND);
@@ -311,14 +315,14 @@ inline int read_serial(const uint8_t index) {
}
}
void GCodeQueue::gcode_line_error(PGM_P const err, const int8_t pn) {
PORT_REDIRECT(pn); // Reply to the serial port that sent the command
void GCodeQueue::gcode_line_error(PGM_P const err, const serial_index_t serial_ind) {
PORT_REDIRECT(serial_ind); // Reply to the serial port that sent the command
SERIAL_ERROR_START();
serialprintPGM(err);
SERIAL_ECHOLN(last_N);
while (read_serial(pn) != -1); // Clear out the RX buffer
while (read_serial(serial_ind) != -1); // Clear out the RX buffer
flush_and_request_resend();
serial_count[pn] = 0;
serial_count[serial_ind] = 0;
}
FORCE_INLINE bool is_M29(const char * const cmd) { // matches "M29" & "M29 ", but not "M290", etc
@@ -383,11 +387,14 @@ inline void process_stream_char(const char c, uint8_t &sis, char (&buff)[MAX_CMD
* keep sensor readings going and watchdog alive.
*/
inline bool process_line_done(uint8_t &sis, char (&buff)[MAX_CMD_SIZE], int &ind) {
sis = PS_NORMAL;
buff[ind] = 0;
if (ind) { ind = 0; return false; }
thermalManager.manage_heater();
return true;
sis = PS_NORMAL; // "Normal" Serial Input State
buff[ind] = '\0'; // Of course, I'm a Terminator.
const bool is_empty = (ind == 0); // An empty line?
if (is_empty)
thermalManager.manage_heater(); // Keep sensors satisfied
else
ind = 0; // Start a new line
return is_empty; // Inform the caller
}
/**
@@ -427,105 +434,114 @@ void GCodeQueue::get_serial_commands() {
* Loop while serial characters are incoming and the queue is not full
*/
while (length < BUFSIZE && serial_data_available()) {
LOOP_L_N(i, NUM_SERIAL) {
LOOP_L_N(p, NUM_SERIAL) {
const int c = read_serial(i);
const int c = read_serial(p);
if (c < 0) continue;
const char serial_char = c;
#if ENABLED(MEATPACK)
meatpack.handle_rx_char(uint8_t(c), p);
char c_res[2] = { 0, 0 };
const uint8_t char_count = meatpack.get_result_char(c_res);
#else
constexpr uint8_t char_count = 1;
#endif
if (ISEOL(serial_char)) {
LOOP_L_N(char_index, char_count) {
const char serial_char = TERN(MEATPACK, c_res[char_index], c);
// Reset our state, continue if the line was empty
if (process_line_done(serial_input_state[i], serial_line_buffer[i], serial_count[i]))
continue;
if (ISEOL(serial_char)) {
char* command = serial_line_buffer[i];
// Reset our state, continue if the line was empty
if (process_line_done(serial_input_state[p], serial_line_buffer[p], serial_count[p]))
continue;
while (*command == ' ') command++; // Skip leading spaces
char *npos = (*command == 'N') ? command : nullptr; // Require the N parameter to start the line
char* command = serial_line_buffer[p];
if (npos) {
while (*command == ' ') command++; // Skip leading spaces
char *npos = (*command == 'N') ? command : nullptr; // Require the N parameter to start the line
bool M110 = strstr_P(command, PSTR("M110")) != nullptr;
if (npos) {
if (M110) {
char* n2pos = strchr(command + 4, 'N');
if (n2pos) npos = n2pos;
bool M110 = strstr_P(command, PSTR("M110")) != nullptr;
if (M110) {
char* n2pos = strchr(command + 4, 'N');
if (n2pos) npos = n2pos;
}
gcode_N = strtol(npos + 1, nullptr, 10);
if (gcode_N != last_N + 1 && !M110)
return gcode_line_error(PSTR(STR_ERR_LINE_NO), p);
char *apos = strrchr(command, '*');
if (apos) {
uint8_t checksum = 0, count = uint8_t(apos - command);
while (count) checksum ^= command[--count];
if (strtol(apos + 1, nullptr, 10) != checksum)
return gcode_line_error(PSTR(STR_ERR_CHECKSUM_MISMATCH), p);
}
else
return gcode_line_error(PSTR(STR_ERR_NO_CHECKSUM), p);
last_N = gcode_N;
}
#if ENABLED(SDSUPPORT)
// Pronterface "M29" and "M29 " has no line number
else if (card.flag.saving && !is_M29(command))
return gcode_line_error(PSTR(STR_ERR_NO_CHECKSUM), p);
#endif
gcode_N = strtol(npos + 1, nullptr, 10);
//
// Movement commands give an alert when the machine is stopped
//
if (gcode_N != last_N + 1 && !M110)
return gcode_line_error(PSTR(STR_ERR_LINE_NO), i);
char *apos = strrchr(command, '*');
if (apos) {
uint8_t checksum = 0, count = uint8_t(apos - command);
while (count) checksum ^= command[--count];
if (strtol(apos + 1, nullptr, 10) != checksum)
return gcode_line_error(PSTR(STR_ERR_CHECKSUM_MISMATCH), i);
}
else
return gcode_line_error(PSTR(STR_ERR_NO_CHECKSUM), i);
last_N = gcode_N;
}
#if ENABLED(SDSUPPORT)
// Pronterface "M29" and "M29 " has no line number
else if (card.flag.saving && !is_M29(command))
return gcode_line_error(PSTR(STR_ERR_NO_CHECKSUM), i);
#endif
//
// Movement commands give an alert when the machine is stopped
//
if (IsStopped()) {
char* gpos = strchr(command, 'G');
if (gpos) {
switch (strtol(gpos + 1, nullptr, 10)) {
case 0: case 1:
#if ENABLED(ARC_SUPPORT)
case 2: case 3:
#endif
#if ENABLED(BEZIER_CURVE_SUPPORT)
case 5:
#endif
PORT_REDIRECT(i); // Reply to the serial port that sent the command
SERIAL_ECHOLNPGM(STR_ERR_STOPPED);
LCD_MESSAGEPGM(MSG_STOPPED);
break;
if (IsStopped()) {
char* gpos = strchr(command, 'G');
if (gpos) {
switch (strtol(gpos + 1, nullptr, 10)) {
case 0: case 1:
#if ENABLED(ARC_SUPPORT)
case 2: case 3:
#endif
#if ENABLED(BEZIER_CURVE_SUPPORT)
case 5:
#endif
PORT_REDIRECT(p); // Reply to the serial port that sent the command
SERIAL_ECHOLNPGM(STR_ERR_STOPPED);
LCD_MESSAGEPGM(MSG_STOPPED);
break;
}
}
}
}
#if DISABLED(EMERGENCY_PARSER)
// Process critical commands early
if (strcmp(command, "M108") == 0) {
wait_for_heatup = false;
#if HAS_LCD_MENU
wait_for_user = false;
#endif
}
if (strcmp(command, "M112") == 0) kill(M112_KILL_STR, nullptr, true);
if (strcmp(command, "M410") == 0) quickstop_stepper();
#endif
#if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
last_command_time = ms;
#endif
// Add the command to the queue
_enqueue(serial_line_buffer[i], true
#if NUM_SERIAL > 1
, i
#if DISABLED(EMERGENCY_PARSER)
// Process critical commands early
if (strcmp(command, "M108") == 0) {
wait_for_heatup = false;
#if HAS_LCD_MENU
wait_for_user = false;
#endif
}
if (strcmp(command, "M112") == 0) kill(M112_KILL_STR, nullptr, true);
if (strcmp(command, "M410") == 0) quickstop_stepper();
#endif
);
}
else
process_stream_char(serial_char, serial_input_state[i], serial_line_buffer[i], serial_count[i]);
#if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
last_command_time = ms;
#endif
// Add the command to the queue
_enqueue(serial_line_buffer[p], true
#if NUM_SERIAL > 1
, p
#endif
);
}
else
process_stream_char(serial_char, serial_input_state[p], serial_line_buffer[p], serial_count[p]);
} // char_count loop
} // for NUM_SERIAL
} // queue has space, serial has data
}