|
@@ -57,6 +57,9 @@
|
|
|
|
|
|
#include <avr/wdt.h>
|
|
|
|
|
|
+#include "Dcodes.h"
|
|
|
+
|
|
|
+
|
|
|
#ifdef SWSPI
|
|
|
#include "swspi.h"
|
|
|
#endif //SWSPI
|
|
@@ -96,6 +99,8 @@
|
|
|
|
|
|
#include "ultralcd.h"
|
|
|
|
|
|
+#include "cmdqueue.h"
|
|
|
+
|
|
|
// Macros for bit masks
|
|
|
#define BIT(b) (1<<(b))
|
|
|
#define TEST(n,b) (((n)&BIT(b))!=0)
|
|
@@ -240,8 +245,6 @@
|
|
|
CardReader card;
|
|
|
#endif
|
|
|
|
|
|
-unsigned long TimeSent = millis();
|
|
|
-unsigned long TimeNow = millis();
|
|
|
unsigned long PingTime = millis();
|
|
|
union Data
|
|
|
{
|
|
@@ -417,58 +420,11 @@ static float delta[3] = {0.0, 0.0, 0.0};
|
|
|
static float offset[3] = {0.0, 0.0, 0.0};
|
|
|
static bool home_all_axis = true;
|
|
|
static float feedrate = 1500.0, next_feedrate, saved_feedrate;
|
|
|
-static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
|
|
|
|
|
|
// Determines Absolute or Relative Coordinates.
|
|
|
// Also there is bool axis_relative_modes[] per axis flag.
|
|
|
static bool relative_mode = false;
|
|
|
|
|
|
-// String circular buffer. Commands may be pushed to the buffer from both sides:
|
|
|
-// Chained commands will be pushed to the front, interactive (from LCD menu)
|
|
|
-// and printing commands (from serial line or from SD card) are pushed to the tail.
|
|
|
-// First character of each entry indicates the type of the entry:
|
|
|
-#define CMDBUFFER_CURRENT_TYPE_UNKNOWN 0
|
|
|
-// Command in cmdbuffer was sent over USB.
|
|
|
-#define CMDBUFFER_CURRENT_TYPE_USB 1
|
|
|
-// Command in cmdbuffer was read from SDCARD.
|
|
|
-#define CMDBUFFER_CURRENT_TYPE_SDCARD 2
|
|
|
-// Command in cmdbuffer was generated by the UI.
|
|
|
-#define CMDBUFFER_CURRENT_TYPE_UI 3
|
|
|
-// Command in cmdbuffer was generated by another G-code.
|
|
|
-#define CMDBUFFER_CURRENT_TYPE_CHAINED 4
|
|
|
-
|
|
|
-// How much space to reserve for the chained commands
|
|
|
-// of type CMDBUFFER_CURRENT_TYPE_CHAINED,
|
|
|
-// which are pushed to the front of the queue?
|
|
|
-// Maximum 5 commands of max length 20 + null terminator.
|
|
|
-#define CMDBUFFER_RESERVE_FRONT (5*21)
|
|
|
-// Reserve BUFSIZE lines of length MAX_CMD_SIZE plus CMDBUFFER_RESERVE_FRONT.
|
|
|
-static char cmdbuffer[BUFSIZE * (MAX_CMD_SIZE + 1) + CMDBUFFER_RESERVE_FRONT];
|
|
|
-// Head of the circular buffer, where to read.
|
|
|
-static int bufindr = 0;
|
|
|
-// Tail of the buffer, where to write.
|
|
|
-static int bufindw = 0;
|
|
|
-// Number of lines in cmdbuffer.
|
|
|
-static int buflen = 0;
|
|
|
-// Flag for processing the current command inside the main Arduino loop().
|
|
|
-// If a new command was pushed to the front of a command buffer while
|
|
|
-// processing another command, this replaces the command on the top.
|
|
|
-// Therefore don't remove the command from the queue in the loop() function.
|
|
|
-static bool cmdbuffer_front_already_processed = false;
|
|
|
-
|
|
|
-// Type of a command, which is to be executed right now.
|
|
|
-#define CMDBUFFER_CURRENT_TYPE (cmdbuffer[bufindr])
|
|
|
-// String of a command, which is to be executed right now.
|
|
|
-#define CMDBUFFER_CURRENT_STRING (cmdbuffer+bufindr+CMDHDRSIZE)
|
|
|
-
|
|
|
-// Enable debugging of the command buffer.
|
|
|
-// Debugging information will be sent to serial line.
|
|
|
-//#define CMDBUFFER_DEBUG
|
|
|
-
|
|
|
-static int serial_count = 0; //index of character read from serial line
|
|
|
-static boolean comment_mode = false;
|
|
|
-static char *strchr_pointer; // just a pointer to find chars in the command string like X, Y, Z, E, etc
|
|
|
-
|
|
|
const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42
|
|
|
|
|
|
//static float tt = 0;
|
|
@@ -537,315 +493,6 @@ void serial_echopair_P(const char *s_P, unsigned long v)
|
|
|
}
|
|
|
#endif //!SDSUPPORT
|
|
|
|
|
|
-// Pop the currently processed command from the queue.
|
|
|
-// It is expected, that there is at least one command in the queue.
|
|
|
-bool cmdqueue_pop_front()
|
|
|
-{
|
|
|
- if (buflen > 0) {
|
|
|
-#ifdef CMDBUFFER_DEBUG
|
|
|
- SERIAL_ECHOPGM("Dequeing ");
|
|
|
- SERIAL_ECHO(cmdbuffer+bufindr+CMDHDRSIZE);
|
|
|
- SERIAL_ECHOLNPGM("");
|
|
|
- SERIAL_ECHOPGM("Old indices: buflen ");
|
|
|
- SERIAL_ECHO(buflen);
|
|
|
- SERIAL_ECHOPGM(", bufindr ");
|
|
|
- SERIAL_ECHO(bufindr);
|
|
|
- SERIAL_ECHOPGM(", bufindw ");
|
|
|
- SERIAL_ECHO(bufindw);
|
|
|
- SERIAL_ECHOPGM(", serial_count ");
|
|
|
- SERIAL_ECHO(serial_count);
|
|
|
- SERIAL_ECHOPGM(", bufsize ");
|
|
|
- SERIAL_ECHO(sizeof(cmdbuffer));
|
|
|
- SERIAL_ECHOLNPGM("");
|
|
|
-#endif /* CMDBUFFER_DEBUG */
|
|
|
- if (-- buflen == 0) {
|
|
|
- // Empty buffer.
|
|
|
- if (serial_count == 0)
|
|
|
- // No serial communication is pending. Reset both pointers to zero.
|
|
|
- bufindw = 0;
|
|
|
- bufindr = bufindw;
|
|
|
- } else {
|
|
|
- // There is at least one ready line in the buffer.
|
|
|
- // First skip the current command ID and iterate up to the end of the string.
|
|
|
-// for (++ bufindr; cmdbuffer[bufindr] != 0; ++ bufindr) ;
|
|
|
- for (bufindr += CMDHDRSIZE; cmdbuffer[bufindr] != 0; ++ bufindr) ;
|
|
|
- // Second, skip the end of string null character and iterate until a nonzero command ID is found.
|
|
|
- for (++ bufindr; bufindr < sizeof(cmdbuffer) && cmdbuffer[bufindr] == 0; ++ bufindr) ;
|
|
|
- // If the end of the buffer was empty,
|
|
|
- if (bufindr == sizeof(cmdbuffer)) {
|
|
|
- // skip to the start and find the nonzero command.
|
|
|
- for (bufindr = 0; cmdbuffer[bufindr] == 0; ++ bufindr) ;
|
|
|
- }
|
|
|
-#ifdef CMDBUFFER_DEBUG
|
|
|
- SERIAL_ECHOPGM("New indices: buflen ");
|
|
|
- SERIAL_ECHO(buflen);
|
|
|
- SERIAL_ECHOPGM(", bufindr ");
|
|
|
- SERIAL_ECHO(bufindr);
|
|
|
- SERIAL_ECHOPGM(", bufindw ");
|
|
|
- SERIAL_ECHO(bufindw);
|
|
|
- SERIAL_ECHOPGM(", serial_count ");
|
|
|
- SERIAL_ECHO(serial_count);
|
|
|
- SERIAL_ECHOPGM(" new command on the top: ");
|
|
|
- SERIAL_ECHO(cmdbuffer+bufindr+CMDHDRSIZE);
|
|
|
- SERIAL_ECHOLNPGM("");
|
|
|
-#endif /* CMDBUFFER_DEBUG */
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-void cmdqueue_reset()
|
|
|
-{
|
|
|
- while (cmdqueue_pop_front()) ;
|
|
|
-}
|
|
|
-
|
|
|
-// How long a string could be pushed to the front of the command queue?
|
|
|
-// If yes, adjust bufindr to the new position, where the new command could be enqued.
|
|
|
-// len_asked does not contain the zero terminator size.
|
|
|
-bool cmdqueue_could_enqueue_front(int len_asked)
|
|
|
-{
|
|
|
- // MAX_CMD_SIZE has to accommodate the zero terminator.
|
|
|
- if (len_asked >= MAX_CMD_SIZE)
|
|
|
- return false;
|
|
|
- // Remove the currently processed command from the queue.
|
|
|
- if (! cmdbuffer_front_already_processed) {
|
|
|
- cmdqueue_pop_front();
|
|
|
- cmdbuffer_front_already_processed = true;
|
|
|
- }
|
|
|
- if (bufindr == bufindw && buflen > 0)
|
|
|
- // Full buffer.
|
|
|
- return false;
|
|
|
- // Adjust the end of the write buffer based on whether a partial line is in the receive buffer.
|
|
|
- int endw = (serial_count > 0) ? (bufindw + MAX_CMD_SIZE + 1) : bufindw;
|
|
|
- if (bufindw < bufindr) {
|
|
|
- int bufindr_new = bufindr - len_asked - (1 + CMDHDRSIZE);
|
|
|
- // Simple case. There is a contiguous space between the write buffer and the read buffer.
|
|
|
- if (endw <= bufindr_new) {
|
|
|
- bufindr = bufindr_new;
|
|
|
- return true;
|
|
|
- }
|
|
|
- } else {
|
|
|
- // Otherwise the free space is split between the start and end.
|
|
|
- if (len_asked + (1 + CMDHDRSIZE) <= bufindr) {
|
|
|
- // Could fit at the start.
|
|
|
- bufindr -= len_asked + (1 + CMDHDRSIZE);
|
|
|
- return true;
|
|
|
- }
|
|
|
- int bufindr_new = sizeof(cmdbuffer) - len_asked - (1 + CMDHDRSIZE);
|
|
|
- if (endw <= bufindr_new) {
|
|
|
- memset(cmdbuffer, 0, bufindr);
|
|
|
- bufindr = bufindr_new;
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-// Could one enqueue a command of lenthg len_asked into the buffer,
|
|
|
-// while leaving CMDBUFFER_RESERVE_FRONT at the start?
|
|
|
-// If yes, adjust bufindw to the new position, where the new command could be enqued.
|
|
|
-// len_asked does not contain the zero terminator size.
|
|
|
-bool cmdqueue_could_enqueue_back(int len_asked)
|
|
|
-{
|
|
|
- // MAX_CMD_SIZE has to accommodate the zero terminator.
|
|
|
- if (len_asked >= MAX_CMD_SIZE)
|
|
|
- return false;
|
|
|
-
|
|
|
- if (bufindr == bufindw && buflen > 0)
|
|
|
- // Full buffer.
|
|
|
- return false;
|
|
|
-
|
|
|
- if (serial_count > 0) {
|
|
|
- // If there is some data stored starting at bufindw, len_asked is certainly smaller than
|
|
|
- // the allocated data buffer. Try to reserve a new buffer and to move the already received
|
|
|
- // serial data.
|
|
|
- // How much memory to reserve for the commands pushed to the front?
|
|
|
- // End of the queue, when pushing to the end.
|
|
|
- int endw = bufindw + len_asked + (1 + CMDHDRSIZE);
|
|
|
- if (bufindw < bufindr)
|
|
|
- // Simple case. There is a contiguous space between the write buffer and the read buffer.
|
|
|
- return endw + CMDBUFFER_RESERVE_FRONT <= bufindr;
|
|
|
- // Otherwise the free space is split between the start and end.
|
|
|
- if (// Could one fit to the end, including the reserve?
|
|
|
- endw + CMDBUFFER_RESERVE_FRONT <= sizeof(cmdbuffer) ||
|
|
|
- // Could one fit to the end, and the reserve to the start?
|
|
|
- (endw <= sizeof(cmdbuffer) && CMDBUFFER_RESERVE_FRONT <= bufindr))
|
|
|
- return true;
|
|
|
- // Could one fit both to the start?
|
|
|
- if (len_asked + (1 + CMDHDRSIZE) + CMDBUFFER_RESERVE_FRONT <= bufindr) {
|
|
|
- // Mark the rest of the buffer as used.
|
|
|
- memset(cmdbuffer+bufindw, 0, sizeof(cmdbuffer)-bufindw);
|
|
|
- // and point to the start.
|
|
|
- bufindw = 0;
|
|
|
- return true;
|
|
|
- }
|
|
|
- } else {
|
|
|
- // How much memory to reserve for the commands pushed to the front?
|
|
|
- // End of the queue, when pushing to the end.
|
|
|
- int endw = bufindw + len_asked + (1 + CMDHDRSIZE);
|
|
|
- if (bufindw < bufindr)
|
|
|
- // Simple case. There is a contiguous space between the write buffer and the read buffer.
|
|
|
- return endw + CMDBUFFER_RESERVE_FRONT <= bufindr;
|
|
|
- // Otherwise the free space is split between the start and end.
|
|
|
- if (// Could one fit to the end, including the reserve?
|
|
|
- endw + CMDBUFFER_RESERVE_FRONT <= sizeof(cmdbuffer) ||
|
|
|
- // Could one fit to the end, and the reserve to the start?
|
|
|
- (endw <= sizeof(cmdbuffer) && CMDBUFFER_RESERVE_FRONT <= bufindr))
|
|
|
- return true;
|
|
|
- // Could one fit both to the start?
|
|
|
- if (len_asked + (1 + CMDHDRSIZE) + CMDBUFFER_RESERVE_FRONT <= bufindr) {
|
|
|
- // Mark the rest of the buffer as used.
|
|
|
- memset(cmdbuffer+bufindw, 0, sizeof(cmdbuffer)-bufindw);
|
|
|
- // and point to the start.
|
|
|
- bufindw = 0;
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-#ifdef CMDBUFFER_DEBUG
|
|
|
-static void cmdqueue_dump_to_serial_single_line(int nr, const char *p)
|
|
|
-{
|
|
|
- SERIAL_ECHOPGM("Entry nr: ");
|
|
|
- SERIAL_ECHO(nr);
|
|
|
- SERIAL_ECHOPGM(", type: ");
|
|
|
- SERIAL_ECHO(int(*p));
|
|
|
- SERIAL_ECHOPGM(", cmd: ");
|
|
|
- SERIAL_ECHO(p+1);
|
|
|
- SERIAL_ECHOLNPGM("");
|
|
|
-}
|
|
|
-
|
|
|
-static void cmdqueue_dump_to_serial()
|
|
|
-{
|
|
|
- if (buflen == 0) {
|
|
|
- SERIAL_ECHOLNPGM("The command buffer is empty.");
|
|
|
- } else {
|
|
|
- SERIAL_ECHOPGM("Content of the buffer: entries ");
|
|
|
- SERIAL_ECHO(buflen);
|
|
|
- SERIAL_ECHOPGM(", indr ");
|
|
|
- SERIAL_ECHO(bufindr);
|
|
|
- SERIAL_ECHOPGM(", indw ");
|
|
|
- SERIAL_ECHO(bufindw);
|
|
|
- SERIAL_ECHOLNPGM("");
|
|
|
- int nr = 0;
|
|
|
- if (bufindr < bufindw) {
|
|
|
- for (const char *p = cmdbuffer + bufindr; p < cmdbuffer + bufindw; ++ nr) {
|
|
|
- cmdqueue_dump_to_serial_single_line(nr, p);
|
|
|
- // Skip the command.
|
|
|
- for (++p; *p != 0; ++ p);
|
|
|
- // Skip the gaps.
|
|
|
- for (++p; p < cmdbuffer + bufindw && *p == 0; ++ p);
|
|
|
- }
|
|
|
- } else {
|
|
|
- for (const char *p = cmdbuffer + bufindr; p < cmdbuffer + sizeof(cmdbuffer); ++ nr) {
|
|
|
- cmdqueue_dump_to_serial_single_line(nr, p);
|
|
|
- // Skip the command.
|
|
|
- for (++p; *p != 0; ++ p);
|
|
|
- // Skip the gaps.
|
|
|
- for (++p; p < cmdbuffer + sizeof(cmdbuffer) && *p == 0; ++ p);
|
|
|
- }
|
|
|
- for (const char *p = cmdbuffer; p < cmdbuffer + bufindw; ++ nr) {
|
|
|
- cmdqueue_dump_to_serial_single_line(nr, p);
|
|
|
- // Skip the command.
|
|
|
- for (++p; *p != 0; ++ p);
|
|
|
- // Skip the gaps.
|
|
|
- for (++p; p < cmdbuffer + bufindw && *p == 0; ++ p);
|
|
|
- }
|
|
|
- }
|
|
|
- SERIAL_ECHOLNPGM("End of the buffer.");
|
|
|
- }
|
|
|
-}
|
|
|
-#endif /* CMDBUFFER_DEBUG */
|
|
|
-
|
|
|
-//adds an command to the main command buffer
|
|
|
-//thats really done in a non-safe way.
|
|
|
-//needs overworking someday
|
|
|
-// Currently the maximum length of a command piped through this function is around 20 characters
|
|
|
-void enquecommand(const char *cmd, bool from_progmem)
|
|
|
-{
|
|
|
- int len = from_progmem ? strlen_P(cmd) : strlen(cmd);
|
|
|
- // Does cmd fit the queue while leaving sufficient space at the front for the chained commands?
|
|
|
- // If it fits, it may move bufindw, so it points to a contiguous buffer, which fits cmd.
|
|
|
- if (cmdqueue_could_enqueue_back(len)) {
|
|
|
- // This is dangerous if a mixing of serial and this happens
|
|
|
- // This may easily be tested: If serial_count > 0, we have a problem.
|
|
|
- cmdbuffer[bufindw] = CMDBUFFER_CURRENT_TYPE_UI;
|
|
|
- if (from_progmem)
|
|
|
- strcpy_P(cmdbuffer + bufindw + CMDHDRSIZE, cmd);
|
|
|
- else
|
|
|
- strcpy(cmdbuffer + bufindw + CMDHDRSIZE, cmd);
|
|
|
- SERIAL_ECHO_START;
|
|
|
- SERIAL_ECHORPGM(MSG_Enqueing);
|
|
|
- SERIAL_ECHO(cmdbuffer + bufindw + CMDHDRSIZE);
|
|
|
- SERIAL_ECHOLNPGM("\"");
|
|
|
- bufindw += len + (CMDHDRSIZE + 1);
|
|
|
- if (bufindw == sizeof(cmdbuffer))
|
|
|
- bufindw = 0;
|
|
|
- ++ buflen;
|
|
|
-#ifdef CMDBUFFER_DEBUG
|
|
|
- cmdqueue_dump_to_serial();
|
|
|
-#endif /* CMDBUFFER_DEBUG */
|
|
|
- } else {
|
|
|
- SERIAL_ERROR_START;
|
|
|
- SERIAL_ECHORPGM(MSG_Enqueing);
|
|
|
- if (from_progmem)
|
|
|
- SERIAL_PROTOCOLRPGM(cmd);
|
|
|
- else
|
|
|
- SERIAL_ECHO(cmd);
|
|
|
- SERIAL_ECHOLNPGM("\" failed: Buffer full!");
|
|
|
-#ifdef CMDBUFFER_DEBUG
|
|
|
- cmdqueue_dump_to_serial();
|
|
|
-#endif /* CMDBUFFER_DEBUG */
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void enquecommand_front(const char *cmd, bool from_progmem)
|
|
|
-{
|
|
|
- int len = from_progmem ? strlen_P(cmd) : strlen(cmd);
|
|
|
- // Does cmd fit the queue? This call shall move bufindr, so the command may be copied.
|
|
|
- if (cmdqueue_could_enqueue_front(len)) {
|
|
|
- cmdbuffer[bufindr] = CMDBUFFER_CURRENT_TYPE_UI;
|
|
|
- if (from_progmem)
|
|
|
- strcpy_P(cmdbuffer + bufindr + CMDHDRSIZE, cmd);
|
|
|
- else
|
|
|
- strcpy(cmdbuffer + bufindr + CMDHDRSIZE, cmd);
|
|
|
- ++ buflen;
|
|
|
- SERIAL_ECHO_START;
|
|
|
- SERIAL_ECHOPGM("Enqueing to the front: \"");
|
|
|
- SERIAL_ECHO(cmdbuffer + bufindr + CMDHDRSIZE);
|
|
|
- SERIAL_ECHOLNPGM("\"");
|
|
|
-#ifdef CMDBUFFER_DEBUG
|
|
|
- cmdqueue_dump_to_serial();
|
|
|
-#endif /* CMDBUFFER_DEBUG */
|
|
|
- } else {
|
|
|
- SERIAL_ERROR_START;
|
|
|
- SERIAL_ECHOPGM("Enqueing to the front: \"");
|
|
|
- if (from_progmem)
|
|
|
- SERIAL_PROTOCOLRPGM(cmd);
|
|
|
- else
|
|
|
- SERIAL_ECHO(cmd);
|
|
|
- SERIAL_ECHOLNPGM("\" failed: Buffer full!");
|
|
|
-#ifdef CMDBUFFER_DEBUG
|
|
|
- cmdqueue_dump_to_serial();
|
|
|
-#endif /* CMDBUFFER_DEBUG */
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// Mark the command at the top of the command queue as new.
|
|
|
-// Therefore it will not be removed from the queue.
|
|
|
-void repeatcommand_front()
|
|
|
-{
|
|
|
- cmdbuffer_front_already_processed = true;
|
|
|
-}
|
|
|
-
|
|
|
-bool is_buffer_empty()
|
|
|
-{
|
|
|
- if (buflen == 0) return true;
|
|
|
- else return false;
|
|
|
-}
|
|
|
-
|
|
|
void setup_killpin()
|
|
|
{
|
|
|
#if defined(KILL_PIN) && KILL_PIN > -1
|
|
@@ -1520,287 +1167,6 @@ void loop()
|
|
|
#endif //TMC2130
|
|
|
}
|
|
|
|
|
|
-void get_command()
|
|
|
-{
|
|
|
- // Test and reserve space for the new command string.
|
|
|
- if (!cmdqueue_could_enqueue_back(MAX_CMD_SIZE - 1))
|
|
|
- return;
|
|
|
-
|
|
|
- bool rx_buffer_full = false; //flag that serial rx buffer is full
|
|
|
-
|
|
|
- while (MYSERIAL.available() > 0) {
|
|
|
- if (MYSERIAL.available() == RX_BUFFER_SIZE - 1) { //compare number of chars buffered in rx buffer with rx buffer size
|
|
|
- SERIAL_ECHOLNPGM("Full RX Buffer"); //if buffer was full, there is danger that reading of last gcode will not be completed
|
|
|
- rx_buffer_full = true; //sets flag that buffer was full
|
|
|
- }
|
|
|
- char serial_char = MYSERIAL.read();
|
|
|
- if (selectedSerialPort == 1)
|
|
|
- {
|
|
|
- selectedSerialPort = 0;
|
|
|
- MYSERIAL.write(serial_char);
|
|
|
- selectedSerialPort = 1;
|
|
|
- }
|
|
|
- TimeSent = millis();
|
|
|
- TimeNow = millis();
|
|
|
-
|
|
|
- if (serial_char < 0)
|
|
|
- // Ignore extended ASCII characters. These characters have no meaning in the G-code apart from the file names
|
|
|
- // and Marlin does not support such file names anyway.
|
|
|
- // Serial characters with a highest bit set to 1 are generated when the USB cable is unplugged, leading
|
|
|
- // to a hang-up of the print process from an SD card.
|
|
|
- continue;
|
|
|
- if(serial_char == '\n' ||
|
|
|
- serial_char == '\r' ||
|
|
|
- (serial_char == ':' && comment_mode == false) ||
|
|
|
- serial_count >= (MAX_CMD_SIZE - 1) )
|
|
|
- {
|
|
|
- if(!serial_count) { //if empty line
|
|
|
- comment_mode = false; //for new command
|
|
|
- return;
|
|
|
- }
|
|
|
- cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0; //terminate string
|
|
|
- if(!comment_mode){
|
|
|
- comment_mode = false; //for new command
|
|
|
- if ((strchr_pointer = strstr(cmdbuffer+bufindw+CMDHDRSIZE, "PRUSA")) == NULL && (strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, 'N')) != NULL) {
|
|
|
- if ((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, 'N')) != NULL)
|
|
|
- {
|
|
|
- // Line number met. When sending a G-code over a serial line, each line may be stamped with its index,
|
|
|
- // and Marlin tests, whether the successive lines are stamped with an increasing line number ID.
|
|
|
- gcode_N = (strtol(strchr_pointer+1, NULL, 10));
|
|
|
- if(gcode_N != gcode_LastN+1 && (strstr_P(cmdbuffer+bufindw+CMDHDRSIZE, PSTR("M110")) == NULL) ) {
|
|
|
- // M110 - set current line number.
|
|
|
- // Line numbers not sent in succession.
|
|
|
- SERIAL_ERROR_START;
|
|
|
- SERIAL_ERRORRPGM(MSG_ERR_LINE_NO);
|
|
|
- SERIAL_ERRORLN(gcode_LastN);
|
|
|
- //Serial.println(gcode_N);
|
|
|
- FlushSerialRequestResend();
|
|
|
- serial_count = 0;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*')) != NULL)
|
|
|
- {
|
|
|
- byte checksum = 0;
|
|
|
- char *p = cmdbuffer+bufindw+CMDHDRSIZE;
|
|
|
- while (p != strchr_pointer)
|
|
|
- checksum = checksum^(*p++);
|
|
|
- if (int(strtol(strchr_pointer+1, NULL, 10)) != int(checksum)) {
|
|
|
- SERIAL_ERROR_START;
|
|
|
- SERIAL_ERRORRPGM(MSG_ERR_CHECKSUM_MISMATCH);
|
|
|
- SERIAL_ERRORLN(gcode_LastN);
|
|
|
- FlushSerialRequestResend();
|
|
|
- serial_count = 0;
|
|
|
- return;
|
|
|
- }
|
|
|
- // If no errors, remove the checksum and continue parsing.
|
|
|
- *strchr_pointer = 0;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- SERIAL_ERROR_START;
|
|
|
- SERIAL_ERRORRPGM(MSG_ERR_NO_CHECKSUM);
|
|
|
- SERIAL_ERRORLN(gcode_LastN);
|
|
|
- FlushSerialRequestResend();
|
|
|
- serial_count = 0;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- gcode_LastN = gcode_N;
|
|
|
- //if no errors, continue parsing
|
|
|
- } // end of 'N' command
|
|
|
- }
|
|
|
- else // if we don't receive 'N' but still see '*'
|
|
|
- {
|
|
|
- if((strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*') != NULL))
|
|
|
- {
|
|
|
- SERIAL_ERROR_START;
|
|
|
- SERIAL_ERRORRPGM(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM);
|
|
|
- SERIAL_ERRORLN(gcode_LastN);
|
|
|
- serial_count = 0;
|
|
|
- return;
|
|
|
- }
|
|
|
- } // end of '*' command
|
|
|
- if ((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, 'G')) != NULL) {
|
|
|
- if (! IS_SD_PRINTING) {
|
|
|
- usb_printing_counter = 10;
|
|
|
- is_usb_printing = true;
|
|
|
- }
|
|
|
- if (Stopped == true) {
|
|
|
- int gcode = strtol(strchr_pointer+1, NULL, 10);
|
|
|
- if (gcode >= 0 && gcode <= 3) {
|
|
|
- SERIAL_ERRORLNRPGM(MSG_ERR_STOPPED);
|
|
|
- LCD_MESSAGERPGM(MSG_STOPPED);
|
|
|
- }
|
|
|
- }
|
|
|
- } // end of 'G' command
|
|
|
-
|
|
|
- //If command was e-stop process now
|
|
|
- if(strcmp(cmdbuffer+bufindw+CMDHDRSIZE, "M112") == 0)
|
|
|
- kill("", 2);
|
|
|
-
|
|
|
- // Store the current line into buffer, move to the next line.
|
|
|
- cmdbuffer[bufindw] = CMDBUFFER_CURRENT_TYPE_USB;
|
|
|
-#ifdef CMDBUFFER_DEBUG
|
|
|
- SERIAL_ECHO_START;
|
|
|
- SERIAL_ECHOPGM("Storing a command line to buffer: ");
|
|
|
- SERIAL_ECHO(cmdbuffer+bufindw+CMDHDRSIZE);
|
|
|
- SERIAL_ECHOLNPGM("");
|
|
|
-#endif /* CMDBUFFER_DEBUG */
|
|
|
- bufindw += strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
|
|
|
- if (bufindw == sizeof(cmdbuffer))
|
|
|
- bufindw = 0;
|
|
|
- ++ buflen;
|
|
|
-#ifdef CMDBUFFER_DEBUG
|
|
|
- SERIAL_ECHOPGM("Number of commands in the buffer: ");
|
|
|
- SERIAL_ECHO(buflen);
|
|
|
- SERIAL_ECHOLNPGM("");
|
|
|
-#endif /* CMDBUFFER_DEBUG */
|
|
|
- } // end of 'not comment mode'
|
|
|
- serial_count = 0; //clear buffer
|
|
|
- // Don't call cmdqueue_could_enqueue_back if there are no characters waiting
|
|
|
- // in the queue, as this function will reserve the memory.
|
|
|
- if (MYSERIAL.available() == 0 || ! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1))
|
|
|
- return;
|
|
|
- } // end of "end of line" processing
|
|
|
- else {
|
|
|
- // Not an "end of line" symbol. Store the new character into a buffer.
|
|
|
- if(serial_char == ';') comment_mode = true;
|
|
|
- if(!comment_mode) cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
|
|
|
- }
|
|
|
- } // end of serial line processing loop
|
|
|
-
|
|
|
- if(farm_mode){
|
|
|
- TimeNow = millis();
|
|
|
- if ( ((TimeNow - TimeSent) > 800) && (serial_count > 0) ) {
|
|
|
- cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0;
|
|
|
-
|
|
|
- bufindw += strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
|
|
|
- if (bufindw == sizeof(cmdbuffer))
|
|
|
- bufindw = 0;
|
|
|
- ++ buflen;
|
|
|
-
|
|
|
- serial_count = 0;
|
|
|
-
|
|
|
- SERIAL_ECHOPGM("TIMEOUT:");
|
|
|
- //memset(cmdbuffer, 0 , sizeof(cmdbuffer));
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- //add comment
|
|
|
- if (rx_buffer_full == true && serial_count > 0) { //if rx buffer was full and string was not properly terminated
|
|
|
- rx_buffer_full = false;
|
|
|
- bufindw = bufindw - serial_count; //adjust tail of the buffer to prepare buffer for writing new command
|
|
|
- serial_count = 0;
|
|
|
- }
|
|
|
-
|
|
|
- #ifdef SDSUPPORT
|
|
|
- if(!card.sdprinting || serial_count!=0){
|
|
|
- // If there is a half filled buffer from serial line, wait until return before
|
|
|
- // continuing with the serial line.
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- //'#' stops reading from SD to the buffer prematurely, so procedural macro calls are possible
|
|
|
- // if it occurs, stop_buffering is triggered and the buffer is ran dry.
|
|
|
- // this character _can_ occur in serial com, due to checksums. however, no checksums are used in SD printing
|
|
|
-
|
|
|
- static bool stop_buffering=false;
|
|
|
- if(buflen==0) stop_buffering=false;
|
|
|
- unsigned char sd_count = 0;
|
|
|
- // Reads whole lines from the SD card. Never leaves a half-filled line in the cmdbuffer.
|
|
|
- while( !card.eof() && !stop_buffering) {
|
|
|
- int16_t n=card.get();
|
|
|
- sd_count++;
|
|
|
- char serial_char = (char)n;
|
|
|
- if(serial_char == '\n' ||
|
|
|
- serial_char == '\r' ||
|
|
|
- (serial_char == '#' && comment_mode == false) ||
|
|
|
- (serial_char == ':' && comment_mode == false) ||
|
|
|
- serial_count >= (MAX_CMD_SIZE - 1)||n==-1)
|
|
|
- {
|
|
|
- if(card.eof()){
|
|
|
- SERIAL_PROTOCOLLNRPGM(MSG_FILE_PRINTED);
|
|
|
- stoptime=millis();
|
|
|
- char time[30];
|
|
|
- unsigned long t=(stoptime-starttime-pause_time)/1000;
|
|
|
- pause_time = 0;
|
|
|
- int hours, minutes;
|
|
|
- minutes=(t/60)%60;
|
|
|
- hours=t/60/60;
|
|
|
- save_statistics(total_filament_used, t);
|
|
|
- sprintf_P(time, PSTR("%i hours %i minutes"),hours, minutes);
|
|
|
- SERIAL_ECHO_START;
|
|
|
- SERIAL_ECHOLN(time);
|
|
|
- lcd_setstatus(time);
|
|
|
- card.printingHasFinished();
|
|
|
- card.checkautostart(true);
|
|
|
-
|
|
|
- if (farm_mode)
|
|
|
- {
|
|
|
- prusa_statistics(6);
|
|
|
- lcd_commands_type = LCD_COMMAND_FARM_MODE_CONFIRM;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- if(serial_char=='#')
|
|
|
- stop_buffering=true;
|
|
|
-
|
|
|
- if(!serial_count)
|
|
|
- {
|
|
|
- comment_mode = false; //for new command
|
|
|
- return; //if empty line
|
|
|
- }
|
|
|
- cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0; //terminate string
|
|
|
- cmdbuffer[bufindw] = CMDBUFFER_CURRENT_TYPE_SDCARD;
|
|
|
- cmdbuffer[bufindw+1] = sd_count;
|
|
|
-/* SERIAL_ECHOPGM("SD cmd(");
|
|
|
- MYSERIAL.print(sd_count, DEC);
|
|
|
- SERIAL_ECHOPGM(") ");
|
|
|
- SERIAL_ECHOLN(cmdbuffer+bufindw+CMDHDRSIZE);*/
|
|
|
-// SERIAL_ECHOPGM("cmdbuffer:");
|
|
|
-// MYSERIAL.print(cmdbuffer);
|
|
|
- ++ buflen;
|
|
|
-// SERIAL_ECHOPGM("buflen:");
|
|
|
-// MYSERIAL.print(buflen);
|
|
|
- bufindw += strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
|
|
|
- if (bufindw == sizeof(cmdbuffer))
|
|
|
- bufindw = 0;
|
|
|
- comment_mode = false; //for new command
|
|
|
- serial_count = 0; //clear buffer
|
|
|
- // The following line will reserve buffer space if available.
|
|
|
- if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1))
|
|
|
- return;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if(serial_char == ';') comment_mode = true;
|
|
|
- if(!comment_mode) cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- #endif //SDSUPPORT
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-// Return True if a character was found
|
|
|
-static inline bool code_seen(char code) { return (strchr_pointer = strchr(CMDBUFFER_CURRENT_STRING, code)) != NULL; }
|
|
|
-static inline bool code_seen(const char *code) { return (strchr_pointer = strstr(CMDBUFFER_CURRENT_STRING, code)) != NULL; }
|
|
|
-static inline float code_value() { return strtod(strchr_pointer+1, NULL);}
|
|
|
-static inline long code_value_long() { return strtol(strchr_pointer+1, NULL, 10); }
|
|
|
-static inline int16_t code_value_short() { return int16_t(strtol(strchr_pointer+1, NULL, 10)); };
|
|
|
-static inline uint8_t code_value_uint8() { return uint8_t(strtol(strchr_pointer+1, NULL, 10)); };
|
|
|
-
|
|
|
-static inline float code_value_float() {
|
|
|
- char* e = strchr(strchr_pointer, 'E');
|
|
|
- if (!e) return strtod(strchr_pointer + 1, NULL);
|
|
|
- *e = 0;
|
|
|
- float ret = strtod(strchr_pointer + 1, NULL);
|
|
|
- *e = 'E';
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
#define DEFINE_PGM_READ_ANY(type, reader) \
|
|
|
static inline type pgm_read_any(const type *p) \
|
|
|
{ return pgm_read_##reader##_near(p); }
|
|
@@ -6207,57 +5573,30 @@ case 404: //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
|
|
|
switch((int)code_value())
|
|
|
{
|
|
|
case 0: // D0 - Reset
|
|
|
- if (*(strchr_pointer + 1) == 0) break;
|
|
|
- MYSERIAL.println("D0 - Reset");
|
|
|
- asm volatile("jmp 0x00000");
|
|
|
- break;
|
|
|
-/* MYSERIAL.println("D0 - Reset");
|
|
|
- cli(); //disable interrupts
|
|
|
- wdt_reset(); //reset watchdog
|
|
|
- WDTCSR = (1<<WDCE) | (1<<WDE); //enable watchdog
|
|
|
- WDTCSR = (1<<WDE) | (1<<WDP0); //30ms prescaler
|
|
|
- while(1); //wait for reset*/
|
|
|
+ dcode_0(); break;
|
|
|
case 1: // D1 - Clear EEPROM
|
|
|
+ dcode_1(); break;
|
|
|
+ case 2: // D2 - Read/Write RAM
|
|
|
+ dcode_2(); break;
|
|
|
+ case 3: // D3 - Read/Write EEPROM
|
|
|
+ dcode_3(); break;
|
|
|
+ case 4: // D4 - Read/Write PIN
|
|
|
+ dcode_4(); break;
|
|
|
+/* case 4:
|
|
|
{
|
|
|
- MYSERIAL.println("D1 - Clear EEPROM");
|
|
|
- cli();
|
|
|
- for (int i = 0; i < 4096; i++)
|
|
|
- eeprom_write_byte((unsigned char*)i, (unsigned char)0);
|
|
|
- sei();
|
|
|
- }
|
|
|
- break;
|
|
|
- case 2: // D2 - Read/Write PIN
|
|
|
- {
|
|
|
- if (code_seen('P')) // Pin (0-255)
|
|
|
+ MYSERIAL.println("D4 - Test");
|
|
|
+ uint8_t data[16];
|
|
|
+ int cnt = parse_hex(strchr_pointer + 2, data, 16);
|
|
|
+ MYSERIAL.println(cnt, DEC);
|
|
|
+ for (int i = 0; i < cnt; i++)
|
|
|
{
|
|
|
- int pin = (int)code_value();
|
|
|
- if ((pin >= 0) && (pin <= 255))
|
|
|
- {
|
|
|
- if (code_seen('F')) // Function in/out (0/1)
|
|
|
- {
|
|
|
- int fnc = (int)code_value();
|
|
|
- if (fnc == 0) pinMode(pin, INPUT);
|
|
|
- else if (fnc == 1) pinMode(pin, OUTPUT);
|
|
|
- }
|
|
|
- if (code_seen('V')) // Value (0/1)
|
|
|
- {
|
|
|
- int val = (int)code_value();
|
|
|
- if (val == 0) digitalWrite(pin, LOW);
|
|
|
- else if (val == 1) digitalWrite(pin, HIGH);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- int val = (digitalRead(pin) != LOW)?1:0;
|
|
|
- MYSERIAL.print("PIN");
|
|
|
- MYSERIAL.print(pin);
|
|
|
- MYSERIAL.print("=");
|
|
|
- MYSERIAL.println(val);
|
|
|
- }
|
|
|
- }
|
|
|
+ serial_print_hex_byte(data[i]);
|
|
|
+ MYSERIAL.write(' ');
|
|
|
}
|
|
|
+ MYSERIAL.write('\n');
|
|
|
}
|
|
|
break;
|
|
|
- case 3:
|
|
|
+/* case 3:
|
|
|
if (code_seen('L')) // lcd pwm (0-255)
|
|
|
{
|
|
|
lcdSoftPwm = (int)code_value();
|
|
@@ -6272,14 +5611,14 @@ case 404: //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
|
|
|
fsensor_enable();
|
|
|
#endif*/
|
|
|
break;
|
|
|
- case 4:
|
|
|
+// case 4:
|
|
|
// lcdBlinkDelay = 10;
|
|
|
/* MYSERIAL.print("fsensor_disable()");
|
|
|
#ifdef PAT9125
|
|
|
fsensor_disable();
|
|
|
#endif
|
|
|
break;*/
|
|
|
- break;
|
|
|
+// break;
|
|
|
case 5:
|
|
|
{
|
|
|
/* MYSERIAL.print("tmc2130_rd_MSCNT(0)=");
|
|
@@ -7352,7 +6691,7 @@ void serialecho_temperatures() {
|
|
|
|
|
|
|
|
|
void uvlo_() {
|
|
|
- //SERIAL_ECHOLNPGM("UVLO");
|
|
|
+ //SERIAL_ECHOLNPGM("UVLO");
|
|
|
save_print_to_eeprom();
|
|
|
float current_position_bckp[2];
|
|
|
int feedrate_bckp = feedrate;
|