Cmdqueue code in separate files, debug codes for read/write eeprom and ram, PWM amplitude for Y axis stealtchop mode increased to 210.
This commit is contained in:
parent
14519aa7ee
commit
9105de073c
8 changed files with 939 additions and 699 deletions
192
Firmware/Dcodes.cpp
Normal file
192
Firmware/Dcodes.cpp
Normal file
|
@ -0,0 +1,192 @@
|
|||
#include "Dcodes.h"
|
||||
#include "Marlin.h"
|
||||
#include "cmdqueue.h"
|
||||
|
||||
inline void serial_print_hex_nibble(uint8_t val)
|
||||
{
|
||||
MYSERIAL.write((val > 9)?(val - 10 + 'a'):(val + '0'));
|
||||
}
|
||||
|
||||
void serial_print_hex_byte(uint8_t val)
|
||||
{
|
||||
serial_print_hex_nibble(val >> 4);
|
||||
serial_print_hex_nibble(val & 15);
|
||||
}
|
||||
|
||||
void serial_print_hex_word(uint16_t val)
|
||||
{
|
||||
serial_print_hex_byte(val >> 8);
|
||||
serial_print_hex_byte(val & 255);
|
||||
}
|
||||
|
||||
int parse_hex(char* hex, uint8_t* data, int count)
|
||||
{
|
||||
int parsed = 0;
|
||||
while (*hex)
|
||||
{
|
||||
if (count && (parsed >= count)) break;
|
||||
char c = *(hex++);
|
||||
if (c == ' ') continue;
|
||||
if (c == '\n') break;
|
||||
uint8_t val = 0x00;
|
||||
if ((c >= '0') && (c <= '9')) val |= ((c - '0') << 4);
|
||||
else if ((c >= 'a') && (c <= 'f')) val |= ((c - 'a' + 10) << 4);
|
||||
else return -parsed;
|
||||
c = *(hex++);
|
||||
if ((c >= '0') && (c <= '9')) val |= (c - '0');
|
||||
else if ((c >= 'a') && (c <= 'f')) val |= (c - 'a' + 10);
|
||||
else return -parsed;
|
||||
data[parsed] = val;
|
||||
parsed++;
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
void dcode_0()
|
||||
{
|
||||
if (*(strchr_pointer + 1) == 0) return;
|
||||
MYSERIAL.println("D0 - Reset");
|
||||
if (code_seen('B')) //bootloader
|
||||
asm volatile("jmp 0x1e000");
|
||||
else //reset
|
||||
asm volatile("jmp 0x00000");
|
||||
/*
|
||||
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
|
||||
*/
|
||||
}
|
||||
|
||||
void dcode_1()
|
||||
{
|
||||
MYSERIAL.println("D1 - Clear EEPROM");
|
||||
cli();
|
||||
for (int i = 0; i < 4096; i++)
|
||||
eeprom_write_byte((unsigned char*)i, (unsigned char)0);
|
||||
sei();
|
||||
}
|
||||
|
||||
void dcode_2()
|
||||
{
|
||||
MYSERIAL.println("D2 - Read/Write RAM");
|
||||
uint16_t address = 0x0000; //default 0x0000
|
||||
uint16_t count = 0x2000; //default 0x2000 (entire ram)
|
||||
if (code_seen('A')) // Address (0x0000-0x1fff)
|
||||
address = (strchr_pointer[1] == 'x')?strtol(strchr_pointer + 2, 0, 16):(int)code_value();
|
||||
if (code_seen('C')) // Count (0x0001-0x2000)
|
||||
count = (int)code_value();
|
||||
address &= 0x1fff;
|
||||
if (count > 0x2000) count = 0x2000;
|
||||
if ((address + count) > 0x2000) count = 0x2000 - address;
|
||||
if (code_seen('X')) // Data
|
||||
{
|
||||
uint8_t data[16];
|
||||
count = parse_hex(strchr_pointer + 1, data, 16);
|
||||
if (count > 0)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
*((uint8_t*)(address + i)) = data[i];
|
||||
MYSERIAL.print(count, DEC);
|
||||
MYSERIAL.println(" bytes written to RAM at addres ");
|
||||
serial_print_hex_word(address);
|
||||
MYSERIAL.write('\n');
|
||||
}
|
||||
else
|
||||
count = 0;
|
||||
}
|
||||
while (count)
|
||||
{
|
||||
serial_print_hex_word(address);
|
||||
MYSERIAL.write(' ');
|
||||
uint8_t countperline = 16;
|
||||
while (count && countperline)
|
||||
{
|
||||
uint8_t data = *((uint8_t*)address++);
|
||||
MYSERIAL.write(' ');
|
||||
serial_print_hex_byte(data);
|
||||
countperline--;
|
||||
count--;
|
||||
}
|
||||
MYSERIAL.write('\n');
|
||||
}
|
||||
}
|
||||
void dcode_3()
|
||||
{
|
||||
MYSERIAL.println("D3 - Read/Write EEPROM");
|
||||
uint16_t address = 0x0000; //default 0x0000
|
||||
uint16_t count = 0x2000; //default 0x2000 (entire eeprom)
|
||||
if (code_seen('A')) // Address (0x0000-0x1fff)
|
||||
address = (strchr_pointer[1] == 'x')?strtol(strchr_pointer + 2, 0, 16):(int)code_value();
|
||||
if (code_seen('C')) // Count (0x0001-0x2000)
|
||||
count = (int)code_value();
|
||||
address &= 0x1fff;
|
||||
if (count > 0x2000) count = 0x2000;
|
||||
if ((address + count) > 0x2000) count = 0x2000 - address;
|
||||
if (code_seen('X')) // Data
|
||||
{
|
||||
uint8_t data[16];
|
||||
count = parse_hex(strchr_pointer + 1, data, 16);
|
||||
if (count > 0)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
eeprom_write_byte((uint8_t*)(address + i), data[i]);
|
||||
MYSERIAL.print(count, DEC);
|
||||
MYSERIAL.println(" bytes written to EEPROM at addres ");
|
||||
serial_print_hex_word(address);
|
||||
MYSERIAL.write('\n');
|
||||
}
|
||||
else
|
||||
count = 0;
|
||||
}
|
||||
while (count)
|
||||
{
|
||||
serial_print_hex_word(address);
|
||||
MYSERIAL.write(' ');
|
||||
uint8_t countperline = 16;
|
||||
while (count && countperline)
|
||||
{
|
||||
uint8_t data = eeprom_read_byte((uint8_t*)address++);
|
||||
MYSERIAL.write(' ');
|
||||
serial_print_hex_byte(data);
|
||||
countperline--;
|
||||
count--;
|
||||
}
|
||||
MYSERIAL.write('\n');
|
||||
}
|
||||
}
|
||||
|
||||
void dcode_4()
|
||||
{
|
||||
MYSERIAL.println("D4 - Read/Write PIN");
|
||||
if (code_seen('P')) // Pin (0-255)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
11
Firmware/Dcodes.h
Normal file
11
Firmware/Dcodes.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef DCODES_H
|
||||
#define DCODES_H
|
||||
|
||||
extern void dcode_0();
|
||||
extern void dcode_1();
|
||||
extern void dcode_2();
|
||||
extern void dcode_3();
|
||||
extern void dcode_4();
|
||||
|
||||
|
||||
#endif //DCODES_H
|
|
@ -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)=");
|
||||
|
|
603
Firmware/cmdqueue.cpp
Normal file
603
Firmware/cmdqueue.cpp
Normal file
|
@ -0,0 +1,603 @@
|
|||
#include "cmdqueue.h"
|
||||
#include "cardreader.h"
|
||||
#include "ultralcd.h"
|
||||
|
||||
extern bool Stopped;
|
||||
|
||||
// Reserve BUFSIZE lines of length MAX_CMD_SIZE plus CMDBUFFER_RESERVE_FRONT.
|
||||
char cmdbuffer[BUFSIZE * (MAX_CMD_SIZE + 1) + CMDBUFFER_RESERVE_FRONT];
|
||||
// Head of the circular buffer, where to read.
|
||||
int bufindr = 0;
|
||||
// Tail of the buffer, where to write.
|
||||
int bufindw = 0;
|
||||
// Number of lines in cmdbuffer.
|
||||
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.
|
||||
bool cmdbuffer_front_already_processed = false;
|
||||
|
||||
int serial_count = 0; //index of character read from serial line
|
||||
boolean comment_mode = false;
|
||||
char *strchr_pointer; // just a pointer to find chars in the command string like X, Y, Z, E, etc
|
||||
|
||||
unsigned long TimeSent = millis();
|
||||
unsigned long TimeNow = millis();
|
||||
|
||||
long gcode_N = 0;
|
||||
long gcode_LastN = 0;
|
||||
long Stopped_gcode_LastN = 0;
|
||||
|
||||
|
||||
// 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
|
||||
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("");
|
||||
}
|
||||
|
||||
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 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
|
||||
}
|
85
Firmware/cmdqueue.h
Normal file
85
Firmware/cmdqueue.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
#ifndef CMDQUEUE_H
|
||||
#define CMDQUEUE_H
|
||||
|
||||
#include "Marlin.h"
|
||||
#include "language_all.h"
|
||||
|
||||
|
||||
// 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)
|
||||
|
||||
extern char cmdbuffer[BUFSIZE * (MAX_CMD_SIZE + 1) + CMDBUFFER_RESERVE_FRONT];
|
||||
extern int bufindr;
|
||||
extern int bufindw;
|
||||
extern int buflen;
|
||||
extern bool cmdbuffer_front_already_processed;
|
||||
|
||||
// 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
|
||||
|
||||
extern int serial_count;
|
||||
extern boolean comment_mode;
|
||||
extern char *strchr_pointer;
|
||||
|
||||
extern unsigned long TimeSent;
|
||||
extern unsigned long TimeNow;
|
||||
|
||||
extern long gcode_N;
|
||||
extern long gcode_LastN;
|
||||
extern long Stopped_gcode_LastN;
|
||||
|
||||
extern bool cmdqueue_pop_front();
|
||||
extern void cmdqueue_reset();
|
||||
extern bool cmdqueue_could_enqueue_front(int len_asked);
|
||||
extern bool cmdqueue_could_enqueue_back(int len_asked);
|
||||
extern void cmdqueue_dump_to_serial_single_line(int nr, const char *p);
|
||||
extern void cmdqueue_dump_to_serial();
|
||||
extern void enquecommand(const char *cmd, bool from_progmem);
|
||||
extern void enquecommand_front(const char *cmd, bool from_progmem);
|
||||
extern void repeatcommand_front();
|
||||
extern bool is_buffer_empty();
|
||||
extern void get_command();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
#endif //CMDQUEUE_H
|
|
@ -28,13 +28,13 @@ uint8_t tmc2130_current_r[4] = TMC2130_CURRENTS_R;
|
|||
uint8_t tmc2130_axis_stalled[3] = {0, 0, 0};
|
||||
|
||||
//pwm_ampl
|
||||
uint8_t tmc2130_pwm_ampl[2] = {TMC2130_PWM_AMPL_XY, TMC2130_PWM_AMPL_XY};
|
||||
uint8_t tmc2130_pwm_ampl[2] = {TMC2130_PWM_AMPL_X, TMC2130_PWM_AMPL_Y};
|
||||
//pwm_grad
|
||||
uint8_t tmc2130_pwm_grad[2] = {TMC2130_PWM_GRAD_XY, TMC2130_PWM_GRAD_XY};
|
||||
uint8_t tmc2130_pwm_grad[2] = {TMC2130_PWM_GRAD_X, TMC2130_PWM_GRAD_Y};
|
||||
//pwm_auto
|
||||
uint8_t tmc2130_pwm_auto[2] = {TMC2130_PWM_AUTO_XY, TMC2130_PWM_AUTO_XY};
|
||||
uint8_t tmc2130_pwm_auto[2] = {TMC2130_PWM_AUTO_X, TMC2130_PWM_AUTO_Y};
|
||||
//pwm_freq
|
||||
uint8_t tmc2130_pwm_freq[2] = {TMC2130_PWM_FREQ_XY, TMC2130_PWM_FREQ_XY};
|
||||
uint8_t tmc2130_pwm_freq[2] = {TMC2130_PWM_FREQ_X, TMC2130_PWM_FREQ_Y};
|
||||
|
||||
|
||||
uint8_t tmc2131_axis_sg_thr[3] = {TMC2130_SG_THRS_X, TMC2130_SG_THRS_Y, TMC2130_SG_THRS_Z};
|
||||
|
|
|
@ -109,10 +109,15 @@ const bool Z_MIN_ENDSTOP_INVERTING = false; // set to true to invert the logic o
|
|||
#define TMC2130_INTPOL_Z 1 // extrapolate 256 for Z axis
|
||||
#define TMC2130_INTPOL_E 1 // extrapolate 256 for E axis
|
||||
|
||||
#define TMC2130_PWM_GRAD_XY 4 // PWMCONF
|
||||
#define TMC2130_PWM_AMPL_XY 200 // PWMCONF
|
||||
#define TMC2130_PWM_AUTO_XY 1 // PWMCONF
|
||||
#define TMC2130_PWM_FREQ_XY 2 // PWMCONF
|
||||
#define TMC2130_PWM_GRAD_X 4 // PWMCONF
|
||||
#define TMC2130_PWM_AMPL_X 200 // PWMCONF
|
||||
#define TMC2130_PWM_AUTO_X 1 // PWMCONF
|
||||
#define TMC2130_PWM_FREQ_X 2 // PWMCONF
|
||||
|
||||
#define TMC2130_PWM_GRAD_Y 4 // PWMCONF
|
||||
#define TMC2130_PWM_AMPL_Y 210 // PWMCONF
|
||||
#define TMC2130_PWM_AUTO_Y 1 // PWMCONF
|
||||
#define TMC2130_PWM_FREQ_Y 2 // PWMCONF
|
||||
|
||||
/* //not used
|
||||
#define TMC2130_PWM_GRAD_Z 4 // PWMCONF
|
||||
|
|
|
@ -109,10 +109,15 @@ const bool Z_MIN_ENDSTOP_INVERTING = false; // set to true to invert the logic o
|
|||
#define TMC2130_INTPOL_Z 1 // extrapolate 256 for Z axis
|
||||
#define TMC2130_INTPOL_E 1 // extrapolate 256 for E axis
|
||||
|
||||
#define TMC2130_PWM_GRAD_XY 4 // PWMCONF
|
||||
#define TMC2130_PWM_AMPL_XY 200 // PWMCONF
|
||||
#define TMC2130_PWM_AUTO_XY 1 // PWMCONF
|
||||
#define TMC2130_PWM_FREQ_XY 2 // PWMCONF
|
||||
#define TMC2130_PWM_GRAD_X 4 // PWMCONF
|
||||
#define TMC2130_PWM_AMPL_X 200 // PWMCONF
|
||||
#define TMC2130_PWM_AUTO_X 1 // PWMCONF
|
||||
#define TMC2130_PWM_FREQ_X 2 // PWMCONF
|
||||
|
||||
#define TMC2130_PWM_GRAD_Y 4 // PWMCONF
|
||||
#define TMC2130_PWM_AMPL_Y 210 // PWMCONF
|
||||
#define TMC2130_PWM_AUTO_Y 1 // PWMCONF
|
||||
#define TMC2130_PWM_FREQ_Y 2 // PWMCONF
|
||||
|
||||
/* //not used
|
||||
#define TMC2130_PWM_GRAD_Z 4 // PWMCONF
|
||||
|
|
Loading…
Reference in a new issue