mirror of
https://github.com/synthetos/g2.git
synced 2026-09-23 12:14:09 +08:00
More Marlin compatibility work
This commit is contained in:
+2
-1
@@ -195,7 +195,8 @@ typedef uint16_t index_t; // use this if there are > 255 indexed o
|
||||
typedef enum {
|
||||
TEXT_MODE = 0, // sticky text mode
|
||||
JSON_MODE, // sticky JSON mode
|
||||
AUTO_MODE // auto-configure communications mode
|
||||
AUTO_MODE, // auto-configure communications mode
|
||||
MARLIN_COMM_MODE, // sticky marlin-compatibility mode (if compiled in)
|
||||
} commMode;
|
||||
|
||||
typedef enum {
|
||||
|
||||
+29
-1
@@ -48,6 +48,10 @@
|
||||
|
||||
#include "MotatePower.h"
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
#include "marlin_compatibility.h"
|
||||
#endif
|
||||
|
||||
/***********************************************************************************
|
||||
**** STRUCTURE ALLOCATIONS *********************************************************
|
||||
***********************************************************************************/
|
||||
@@ -221,7 +225,15 @@ static void _dispatch_kernel(const devflags_t flags)
|
||||
// It's possible to let some stuff through, but that's not happening yet.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
if (marlin_handle_fake_stk500(cs.bufp)) {
|
||||
cs.comm_mode = MARLIN_COMM_MODE;
|
||||
js.json_mode = MARLIN_COMM_MODE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
while ((*cs.bufp == SPC) || (*cs.bufp == TAB)) { // position past any leading whitespace
|
||||
cs.bufp++;
|
||||
}
|
||||
@@ -262,6 +274,12 @@ static void _dispatch_kernel(const devflags_t flags)
|
||||
cs.comm_request_mode = TEXT_MODE; // mode of this command
|
||||
text_response(gcode_parser(cs.bufp), cs.saved_buf);
|
||||
}
|
||||
#endif
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
else if (js.json_mode == MARLIN_COMM_MODE) { // handle marlin-specific protocol gcode
|
||||
cs.comm_request_mode = MARLIN_COMM_MODE; // mode of this command
|
||||
marlin_response(gcode_parser(cs.bufp), cs.saved_buf);
|
||||
}
|
||||
#endif
|
||||
else { // anything else is interpreted as Gcode
|
||||
cs.comm_request_mode = JSON_MODE; // mode of this command
|
||||
@@ -272,6 +290,16 @@ static void _dispatch_kernel(const devflags_t flags)
|
||||
nv_copy_string(nv, cs.bufp); // copy the Gcode line
|
||||
nv->valuetype = TYPE_STRING;
|
||||
status = gcode_parser(cs.bufp);
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
if (js.json_mode == MARLIN_COMM_MODE) { // in case a marlin-specific M-code was found
|
||||
cs.comm_request_mode = MARLIN_COMM_MODE; // mode of this command
|
||||
// We ae switching to marlin_comm_mode, kill status reports and queue reports
|
||||
sr.status_report_verbosity = SR_OFF;
|
||||
qr.queue_report_verbosity = QR_OFF;
|
||||
marlin_response(gcode_parser(cs.bufp), cs.saved_buf);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
nv_print_list(status, TEXT_NO_PRINT, JSON_RESPONSE_FORMAT);
|
||||
sr_request_status_report(SR_REQUEST_TIMED); // generate incremental status report to show any changes
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
#include "marlin_compatibility.h"
|
||||
#include "json_parser.h" // so we can switch js.comm_mode on a marlin M-code
|
||||
#endif
|
||||
|
||||
// Structures used by Gcode parser
|
||||
@@ -71,6 +72,11 @@ typedef struct GCodeInputValue { // Gcode inputs - meaning depends on context
|
||||
bool mfo_control; // M50 feedrate override control
|
||||
bool mto_control; // M50.1 traverse override control
|
||||
bool sso_control; // M51 spindle speed override control
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
bool marlin_temp_requested; // M105 temperature report request (Marlin-only)
|
||||
bool marlin_position_requested; // M114 position report request (Marlin-only)
|
||||
#endif
|
||||
} GCodeValue_t;
|
||||
|
||||
typedef struct GCodeFlags { // Gcode input flags
|
||||
@@ -110,6 +116,11 @@ typedef struct GCodeFlags { // Gcode input flags
|
||||
bool mfo_control;
|
||||
bool mto_control;
|
||||
bool sso_control;
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
bool marlin_temp_requested;
|
||||
bool marlin_position_requested;
|
||||
#endif
|
||||
} GCodeFlag_t;
|
||||
|
||||
typedef struct GCodeParser {
|
||||
@@ -684,6 +695,13 @@ stat_t _parse_gcode_block(char *buf, char *active_comment)
|
||||
case 51: SET_MODAL (MODAL_GROUP_M9, sso_control, true);
|
||||
case 100: SET_NON_MODAL (next_action, NEXT_ACTION_JSON_COMMAND_SYNC);
|
||||
case 101: SET_NON_MODAL (next_action, NEXT_ACTION_JSON_WAIT);
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
#warning MARLIN_COMPAT_ENABLED
|
||||
case 105: SET_NON_MODAL (marlin_temp_requested, true);
|
||||
case 114: SET_NON_MODAL (marlin_position_requested, true);
|
||||
#endif // MARLIN_COMPAT_ENABLED
|
||||
|
||||
default: status = STAT_MCODE_COMMAND_UNSUPPORTED;
|
||||
}
|
||||
break;
|
||||
@@ -865,6 +883,20 @@ stat_t _execute_gcode_block(char *active_comment)
|
||||
}
|
||||
}
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
// Handle Marlin specifics
|
||||
if (gf.marlin_temp_requested) { // spindle speed override
|
||||
js.json_mode = MARLIN_COMM_MODE; // we use M105 to know when to switch
|
||||
ritorno(marlin_request_temperature_report());
|
||||
}
|
||||
if (gf.marlin_position_requested) { // spindle speed override
|
||||
js.json_mode = MARLIN_COMM_MODE; // we use M105 to know when to switch
|
||||
ritorno(marlin_request_position_report());
|
||||
}
|
||||
#endif // MARLIN_COMPAT_ENABLED
|
||||
|
||||
|
||||
|
||||
// do the program stops and ends : M0, M1, M2, M30, M60
|
||||
if (gf.program_flow == true) {
|
||||
if (gv.program_flow == PROGRAM_STOP) {
|
||||
|
||||
@@ -28,8 +28,28 @@
|
||||
#include "canonical_machine.h"
|
||||
#include "util.h"
|
||||
#include "xio.h" // for char definitions
|
||||
#include "json_parser.h"
|
||||
|
||||
// Structures used
|
||||
enum STK500 {
|
||||
// Success
|
||||
STATUS_CMD_OK = 0x00,
|
||||
|
||||
// Warnings
|
||||
STATUS_CMD_TOUT = 0x80,
|
||||
STATUS_RDY_BSY_TOUT = 0x81,
|
||||
STATUS_SET_PARAM_MISSING = 0x82,
|
||||
|
||||
// Errors
|
||||
STATUS_CMD_FAILED = 0xC0,
|
||||
STATUS_CKSUM_ERROR = 0xC1,
|
||||
STATUS_CMD_UNKNOWN = 0xC9,
|
||||
};
|
||||
|
||||
// Local variables
|
||||
|
||||
bool temperature_requested = false;
|
||||
bool position_requested = false;
|
||||
|
||||
// local helper functions and macros
|
||||
|
||||
@@ -37,6 +57,7 @@
|
||||
* marlin_verify_checksum() - check to see if we have a line number (cheaply) and a valid checksum
|
||||
*/
|
||||
|
||||
|
||||
stat_t marlin_verify_checksum(char *str)
|
||||
{
|
||||
if (*str != 'N') { return STAT_OK; } // we only check if we have a line number
|
||||
@@ -56,6 +77,58 @@ stat_t marlin_verify_checksum(char *str)
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
void _marlin_fake_stk500_response(char *resp, uint16_t length)
|
||||
{
|
||||
char *str = resp;
|
||||
|
||||
str[2] = (length >> 8) & 0xFF;
|
||||
str[3] = (length) & 0xFF;
|
||||
|
||||
uint8_t crc = 0;
|
||||
|
||||
for (uint16_t i = length + 5; i>0; i--) {
|
||||
crc ^= *resp++;
|
||||
}
|
||||
|
||||
*resp = crc;
|
||||
|
||||
xio_write(str, length + 6);
|
||||
}
|
||||
|
||||
/*
|
||||
* marlin_handle_fake_stk500() - returns true if it handled something (IOW, don't futher process the line)
|
||||
*/
|
||||
bool marlin_handle_fake_stk500(char *str)
|
||||
{
|
||||
char *resp = str;
|
||||
if (*str != 0x1B) { return false; }
|
||||
|
||||
// we handle only a handful of messages ... poorly
|
||||
// for example: this is where we should validate the checksum, but we are going to not for now.
|
||||
|
||||
str += 1 + 1 + 2 + 1; // 1 for 0x1B, 1 for sequence, 2 for length, 1 for 0x0E
|
||||
|
||||
char c = *str++;
|
||||
|
||||
if ((c == 0x01) || // CMD_SIGN_ON
|
||||
(c == 0x10) || // CMD_ENTER_PROGMODE_ISP
|
||||
(c == 0x11) // CMD_LEAVE_PROGMODE_ISP
|
||||
)
|
||||
{
|
||||
*str = STATUS_CMD_OK;
|
||||
_marlin_fake_stk500_response(resp, 2);
|
||||
|
||||
if (c == 0x11) { // CMD_LEAVE_PROGMODE_ISP
|
||||
xio_exit_fake_bootloader();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
*str = STATUS_CMD_UNKNOWN;
|
||||
_marlin_fake_stk500_response(resp, 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
@@ -63,6 +136,133 @@ stat_t marlin_verify_checksum(char *str)
|
||||
* Functions to get and set variables from the cfgArray table
|
||||
***********************************************************************************/
|
||||
|
||||
stat_t marlin_request_temperature_report() // M105
|
||||
{
|
||||
uint8_t tool = cm.gm.tool_select;
|
||||
if (tool > 1) {
|
||||
return STAT_INPUT_VALUE_RANGE_ERROR;
|
||||
}
|
||||
|
||||
temperature_requested = true;
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
stat_t marlin_request_position_report() // M114
|
||||
{
|
||||
position_requested = true;
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
nvObj_t *_get_spcific_nv(const char *key) {
|
||||
nvObj_t *nv = nv_reset_nv_list(); // returns first object in the body
|
||||
|
||||
strncpy(nv->token, key, TOKEN_LEN);
|
||||
|
||||
// validate and post-process the token
|
||||
if ((nv->index = nv_get_index((const char *)"", nv->token)) == NO_MATCH) { // get index or fail it
|
||||
// since we JUST provided the keys, this should never happen
|
||||
return nullptr;
|
||||
}
|
||||
strcpy(nv->group, cfgArray[nv->index].group); // capture the group string if there is one
|
||||
|
||||
nv_get(nv);
|
||||
|
||||
return nv;
|
||||
}
|
||||
|
||||
void _report_temperatures(char *(&str)) {
|
||||
// Tool 0 is extruder 1
|
||||
uint8_t tool = cm.gm.tool_select;
|
||||
|
||||
nvObj_t *nv = nullptr;
|
||||
|
||||
if (tool == 0) {
|
||||
nv = _get_spcific_nv("he1t");
|
||||
} else if (tool == 1) {
|
||||
nv = _get_spcific_nv("he2t");
|
||||
} else {
|
||||
return; // we have no way of reporting errors here, ATM
|
||||
}
|
||||
if (!nv) { return; }
|
||||
str += sprintf(str, " T:%.2f", (float)nv->value);
|
||||
|
||||
if (tool == 0) {
|
||||
nv = _get_spcific_nv("he1st");
|
||||
} else if (tool == 1) {
|
||||
nv = _get_spcific_nv("he2st");
|
||||
} else {
|
||||
return; // we have no way of reporting errors here, ATM
|
||||
}
|
||||
if (!nv) { return; }
|
||||
str += sprintf(str, " /%.2f", (float)nv->value);
|
||||
|
||||
nv = _get_spcific_nv("he3t");
|
||||
if (!nv) { return; }
|
||||
str += sprintf(str, " B:%.2f", (float)nv->value);
|
||||
|
||||
nv = _get_spcific_nv("he3st");
|
||||
if (!nv) { return; }
|
||||
str += sprintf(str, " /%.2f", (float)nv->value);
|
||||
}
|
||||
|
||||
void _report_position(char *(&str)) {
|
||||
//
|
||||
// Tool 0 is extruder 1
|
||||
uint8_t tool = cm.gm.tool_select;
|
||||
|
||||
str += sprintf(str, " X:%.2f", cm_get_work_position(ACTIVE_MODEL, 0));
|
||||
str += sprintf(str, " Y:%.2f", cm_get_work_position(ACTIVE_MODEL, 1));
|
||||
str += sprintf(str, " Z:%.2f", cm_get_work_position(ACTIVE_MODEL, 2));
|
||||
|
||||
if (tool == 0) {
|
||||
str += sprintf(str, " E:%.2f", cm_get_work_position(ACTIVE_MODEL, 3));
|
||||
} else if (tool == 1) {
|
||||
str += sprintf(str, " E:%.2f", cm_get_work_position(ACTIVE_MODEL, 4));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* marlin_response() - marlin mirror if text_response()
|
||||
*/
|
||||
void marlin_response(const stat_t status, char *buf)
|
||||
{
|
||||
char buffer[128];
|
||||
char *str = buffer;
|
||||
|
||||
if ((status == STAT_OK) || (status == STAT_EAGAIN) || (status == STAT_NOOP)) {
|
||||
strncpy(str, "ok", 2);
|
||||
str += 2;
|
||||
|
||||
if (temperature_requested) {
|
||||
_report_temperatures(str);
|
||||
}
|
||||
|
||||
if (position_requested) {
|
||||
_report_position(str);
|
||||
}
|
||||
|
||||
// nvObj_t *nv = nv_body+1;
|
||||
//
|
||||
// if (nv_get_type(nv) == NV_TYPE_MESSAGE) {
|
||||
// p += sprintf(p, (char *)*nv->stringp);
|
||||
// }
|
||||
// sprintf(p, "\n");
|
||||
|
||||
} else {
|
||||
// str += sprintf(p, "echo:M%d %s", (int)status, get_status_message(status), buf);
|
||||
str += sprintf(str, "Error:[%d] %s", (int)status, get_status_message(status));
|
||||
}
|
||||
|
||||
*str++ = '\n';
|
||||
*str++ = 0;
|
||||
|
||||
// reset requests
|
||||
temperature_requested = false;
|
||||
position_requested = false;
|
||||
|
||||
xio_writeline(buffer);
|
||||
}
|
||||
|
||||
//stat_t gc_get_gc(nvObj_t *nv)
|
||||
//{
|
||||
// ritorno(nv_copy_string(nv, cs.saved_buf));
|
||||
|
||||
@@ -29,5 +29,11 @@
|
||||
*/
|
||||
|
||||
stat_t marlin_verify_checksum(char *str);
|
||||
bool marlin_handle_fake_stk500(char *str);
|
||||
|
||||
stat_t marlin_request_temperature_report(); // M105
|
||||
stat_t marlin_request_position_report(); // M114
|
||||
|
||||
void marlin_response(const stat_t status, char *buf);
|
||||
|
||||
#endif // End of include guard: MARLIN_COMPAT_H_ONCE
|
||||
|
||||
+2
-1
@@ -111,7 +111,8 @@ void rpt_print_loading_configs_message(void)
|
||||
|
||||
void rpt_print_system_ready_message(void)
|
||||
{
|
||||
_startup_helper(STAT_OK, "SYSTEM READY");
|
||||
#warning DEAL WITH STARTUP MESSAGE
|
||||
//_startup_helper(STAT_OK, "SYSTEM READY");
|
||||
if (cs.comm_mode == TEXT_MODE) { text_response(STAT_OK, (char *)"");}// prompt
|
||||
}
|
||||
|
||||
|
||||
@@ -57,8 +57,10 @@
|
||||
|
||||
// Communications and reporting settings
|
||||
|
||||
#define MARLIN_COMPAT_ENABLED true // enable marlin compatibility mode
|
||||
#define COMM_MODE JSON_MODE // one of: TEXT_MODE, JSON_MODE
|
||||
#define XIO_ENABLE_FLOW_CONTROL FLOW_CONTROL_RTS // FLOW_CONTROL_OFF, FLOW_CONTROL_RTS
|
||||
#define XIO_UART_MUTES_WHEN_USB_CONNECTED 1 // Mute the UART when USB connects
|
||||
|
||||
#define TEXT_VERBOSITY TV_VERBOSE // one of: TV_SILENT, TV_VERBOSE
|
||||
#define JSON_VERBOSITY JV_LINENUM // one of: JV_SILENT, JV_FOOTER, JV_CONFIGS, JV_MESSAGES, JV_LINENUM, JV_VERBOSE
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#define MARLIN_COMPAT_ENABLED true // enable marlin compatibility mode
|
||||
#define COMM_MODE JSON_MODE // one of: TEXT_MODE, JSON_MODE
|
||||
#define XIO_ENABLE_FLOW_CONTROL FLOW_CONTROL_RTS // FLOW_CONTROL_OFF, FLOW_CONTROL_RTS
|
||||
#define XIO_UART_MUTES_WHEN_USB_CONNECTED 1 // Mute the UART when USB connects
|
||||
|
||||
#define TEXT_VERBOSITY TV_VERBOSE // one of: TV_SILENT, TV_VERBOSE
|
||||
#define JSON_VERBOSITY JV_MESSAGES // one of: JV_SILENT, JV_FOOTER, JV_CONFIGS, JV_MESSAGES, JV_LINENUM, JV_VERBOSE
|
||||
|
||||
@@ -57,8 +57,10 @@
|
||||
|
||||
// Communications and reporting settings
|
||||
|
||||
#define MARLIN_COMPAT_ENABLED true // enable marlin compatibility mode
|
||||
#define COMM_MODE JSON_MODE // one of: TEXT_MODE, JSON_MODE
|
||||
#define XIO_ENABLE_FLOW_CONTROL FLOW_CONTROL_RTS // FLOW_CONTROL_OFF, FLOW_CONTROL_RTS
|
||||
#define XIO_UART_MUTES_WHEN_USB_CONNECTED 1 // Mute the UART when USB connects
|
||||
|
||||
#define TEXT_VERBOSITY TV_VERBOSE // one of: TV_SILENT, TV_VERBOSE
|
||||
#define JSON_VERBOSITY JV_MESSAGES // one of: JV_SILENT, JV_FOOTER, JV_CONFIGS, JV_MESSAGES, JV_LINENUM, JV_VERBOSE
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
|
||||
// Communications and reporting settings
|
||||
|
||||
#define MARLIN_COMPAT_ENABLED true // enable marlin compatibility mode
|
||||
#define COMM_MODE JSON_MODE // one of: TEXT_MODE, JSON_MODE
|
||||
#define XIO_ENABLE_FLOW_CONTROL FLOW_CONTROL_RTS // FLOW_CONTROL_OFF, FLOW_CONTROL_RTS
|
||||
#define XIO_UART_MUTES_WHEN_USB_CONNECTED 1 // Mute the UART when USB connects
|
||||
|
||||
+123
@@ -173,6 +173,10 @@ struct xioDeviceWrapperBase { // C++ base class for device primit
|
||||
virtual int16_t write(const char *buffer, int16_t len) { return -1; };
|
||||
|
||||
virtual char *readline(devflags_t limit_flags, uint16_t &size) { return nullptr; };
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
virtual void exitFakeBootloaderMode() {};
|
||||
#endif
|
||||
};
|
||||
|
||||
// Here we create the xio_t class, which has convenience methods to handle cross-device actions as a whole.
|
||||
@@ -397,6 +401,14 @@ struct xio_t {
|
||||
return (NULL);
|
||||
};
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
void exitFakeBootloaderMode() {
|
||||
for (int8_t i = 0; i < _dev_count; ++i) {
|
||||
DeviceWrappers[i]->exitFakeBootloaderMode();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
uint16_t magic_end;
|
||||
};
|
||||
|
||||
@@ -447,6 +459,32 @@ struct LineRXBuffer : RXBuffer<_size, owner_type, char> {
|
||||
|
||||
bool _last_returned_a_control = false;
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
enum class STK500V2_State {
|
||||
Done, // not in the faked stk500v2 bootloader
|
||||
Timeout, // timeout period, waiting for a start character
|
||||
Start, // waiting for 0x1B
|
||||
Sequence, // waiting for sequence byte
|
||||
Length_0, // waiting for MSB of length
|
||||
Length_1, // waiting for LSB of length
|
||||
Header_End,// waiting for 0x0E
|
||||
Data, // waiting for more data
|
||||
Checksum // waiting for checksum byte
|
||||
};
|
||||
STK500V2_State _stk_parser_state;
|
||||
uint16_t _stk_packet_data_length;
|
||||
Motate::Timeout _stk_timeout;
|
||||
|
||||
void startFakeBootloaderMode() {
|
||||
_stk_parser_state = STK500V2_State::Timeout;
|
||||
_stk_timeout.set(2000); // two seconds
|
||||
}
|
||||
|
||||
void exitFakeBootloaderMode() {
|
||||
_stk_parser_state = STK500V2_State::Done;
|
||||
}
|
||||
#endif
|
||||
|
||||
LineRXBuffer(owner_type owner) : parent_type{owner} {};
|
||||
|
||||
void init() {
|
||||
@@ -610,6 +648,70 @@ struct LineRXBuffer : RXBuffer<_size, owner_type, char> {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
// it's possible something will try to talk stk500v2 to us.
|
||||
// See https://github.com/synthetos/g2/wiki/Marlin-Compatibility#stk500v2
|
||||
if (_stk_parser_state >= STK500V2_State::Timeout)
|
||||
{
|
||||
if (_stk_parser_state == STK500V2_State::Timeout) {
|
||||
if (_stk_timeout.isPast()) {
|
||||
_stk_parser_state = STK500V2_State::Done;
|
||||
// start over, outside of stk500v2 mode
|
||||
continue;
|
||||
}
|
||||
// if we got something before the timeout, then we're in stk500v2 mode
|
||||
// we'll look at what we got and maybe exit anyway
|
||||
_stk_parser_state = STK500V2_State::Start;
|
||||
}
|
||||
if (_stk_parser_state == STK500V2_State::Start) {
|
||||
if (c == 0x1B) {
|
||||
_stk_parser_state = STK500V2_State::Sequence;
|
||||
|
||||
// this is the start of this "line" and we can "read" (skip) everything up to here.
|
||||
_read_offset = _scan_offset;
|
||||
_line_start_offset = _scan_offset;
|
||||
}
|
||||
else if ((c == '{') || (c == '\n') || (c == '\r') || (c == 'G') || (c == 'M')) {
|
||||
// jump out of bootloader mode
|
||||
_stk_parser_state = STK500V2_State::Done;
|
||||
continue;
|
||||
}
|
||||
|
||||
} else if (_stk_parser_state == STK500V2_State::Sequence) {
|
||||
// we ignore the sequence
|
||||
_stk_parser_state = STK500V2_State::Length_0;
|
||||
} else if (_stk_parser_state == STK500V2_State::Length_0) {
|
||||
_stk_packet_data_length = c << 8;
|
||||
_stk_parser_state = STK500V2_State::Length_1;
|
||||
} else if (_stk_parser_state == STK500V2_State::Length_1) {
|
||||
_stk_packet_data_length |= c;
|
||||
_stk_parser_state = STK500V2_State::Header_End;
|
||||
} else if (_stk_parser_state == STK500V2_State::Header_End) {
|
||||
if (c == 0x0E) {
|
||||
_stk_parser_state = STK500V2_State::Data;
|
||||
} else {
|
||||
// end-of-header marker was corrupt, start over
|
||||
_stk_packet_data_length = 0;
|
||||
_stk_parser_state = STK500V2_State::Start;
|
||||
}
|
||||
} else if (_stk_parser_state == STK500V2_State::Data) {
|
||||
|
||||
// we don't read the data here, just return it
|
||||
if (--_stk_packet_data_length == 0) {
|
||||
_stk_parser_state = STK500V2_State::Checksum;
|
||||
}
|
||||
} else if (_stk_parser_state == STK500V2_State::Checksum) {
|
||||
// we do NOT check the checksum, since if it's corrupt, we
|
||||
// need to reply, and we can't reply here.
|
||||
|
||||
// at this point, we at least have a complete packet
|
||||
// we will use the "control" return machanism to handle this
|
||||
// since controls don't have to be \r\n-terminated
|
||||
is_control = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
// Look for line endings
|
||||
if (c == '\r' || c == '\n') {
|
||||
if (!_at_start_of_line) { // We only mark ends_line for the first end-line char, and if
|
||||
@@ -1003,6 +1105,10 @@ struct xioDeviceWrapper : xioDeviceWrapperBase { // describes a device for re
|
||||
|
||||
setAsConnectedAndReady();
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
_rx_buffer.startFakeBootloaderMode();
|
||||
#endif
|
||||
|
||||
if (isAlwaysDataAndCtrl()) {
|
||||
// Case 1 (ignoring others)
|
||||
setActive();
|
||||
@@ -1087,6 +1193,13 @@ struct xioDeviceWrapper : xioDeviceWrapperBase { // describes a device for re
|
||||
} // flags & DEV_IS_CONNECTED
|
||||
}
|
||||
};
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
void exitFakeBootloaderMode() override {
|
||||
_rx_buffer.exitFakeBootloaderMode();
|
||||
};
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1289,6 +1402,16 @@ void xio_flush_to_command() {
|
||||
return xio.flushToCommand();
|
||||
}
|
||||
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
/*
|
||||
* xio_end_fake_bootloader() - end the fake bootloader mode
|
||||
*/
|
||||
|
||||
void xio_exit_fake_bootloader() {
|
||||
return xio.exitFakeBootloaderMode();
|
||||
}
|
||||
#endif
|
||||
|
||||
/***********************************************************************************
|
||||
* newlib-nano support functions
|
||||
* Here we wire printf to xio
|
||||
|
||||
+5
-1
@@ -49,8 +49,9 @@
|
||||
#define XIO_H_ONCE
|
||||
|
||||
//#include "g2core.h" // not required if used in g2core project
|
||||
#include "config.h" // required for nvObj typedef
|
||||
#include "config.h" // required for nvObj typedef
|
||||
#include "canonical_machine.h" // needed for cm_has_hold()
|
||||
#include "settings.h" // needed for MARLIN_COMPAT_ENABLED
|
||||
|
||||
/**** Defines, Macros, and Assorted Parameters ****/
|
||||
|
||||
@@ -122,6 +123,9 @@ char *xio_readline(devflags_t &flags, uint16_t &size);
|
||||
int16_t xio_writeline(const char *buffer, bool only_to_muted = false);
|
||||
bool xio_connected();
|
||||
void xio_flush_to_command();
|
||||
#if MARLIN_COMPAT_ENABLED == true
|
||||
void xio_exit_fake_bootloader();
|
||||
#endif
|
||||
|
||||
stat_t xio_set_spi(nvObj_t *nv);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user