split gcode parse/process into separate files for readability
This commit is contained in:
parent
dd8a5cd377
commit
56c355c5bd
2
Makefile
2
Makefile
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
PROGRAM = mendel
|
PROGRAM = mendel
|
||||||
|
|
||||||
SOURCES = $(PROGRAM).c serial.c dda.c gcode.c timer.c clock.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c
|
SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c clock.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# #
|
# #
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,14 @@
|
||||||
#include "gcode.h"
|
#include "gcode_parse.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
#include "sermsg.h"
|
#include "sermsg.h"
|
||||||
#include "temp.h"
|
|
||||||
#include "timer.h"
|
|
||||||
#include "dda_queue.h"
|
#include "dda_queue.h"
|
||||||
#include "dda.h"
|
|
||||||
#include "clock.h"
|
|
||||||
#include "watchdog.h"
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "heater.h"
|
#include "heater.h"
|
||||||
#include "sersendf.h"
|
|
||||||
#include "delay.h"
|
#include "gcode_process.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Switch user friendly values to coding friendly values
|
Switch user friendly values to coding friendly values
|
||||||
|
|
@ -124,7 +118,7 @@ void SpecialMoveE(int32_t e, uint32_t f) {
|
||||||
* *
|
* *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void scan_char(uint8_t c) {
|
void gcode_parse_char(uint8_t c) {
|
||||||
#ifdef ASTERISK_IN_CHECKSUM_INCLUDED
|
#ifdef ASTERISK_IN_CHECKSUM_INCLUDED
|
||||||
if (next_target.seen_checksum == 0)
|
if (next_target.seen_checksum == 0)
|
||||||
next_target.checksum_calculated = crc(next_target.checksum_calculated, c);
|
next_target.checksum_calculated = crc(next_target.checksum_calculated, c);
|
||||||
|
|
@ -245,6 +239,7 @@ void scan_char(uint8_t c) {
|
||||||
// process character
|
// process character
|
||||||
switch (c) {
|
switch (c) {
|
||||||
// each currently known command is either G or M, so preserve previous G/M unless a new one has appeared
|
// each currently known command is either G or M, so preserve previous G/M unless a new one has appeared
|
||||||
|
// FIXME: same for T command
|
||||||
case 'G':
|
case 'G':
|
||||||
next_target.seen_G = 1;
|
next_target.seen_G = 1;
|
||||||
next_target.seen_M = 0;
|
next_target.seen_M = 0;
|
||||||
|
|
@ -294,7 +289,7 @@ void scan_char(uint8_t c) {
|
||||||
// now for some numeracy
|
// now for some numeracy
|
||||||
case '-':
|
case '-':
|
||||||
read_digit.sign = 1;
|
read_digit.sign = 1;
|
||||||
// force sign to be at start of number
|
// force sign to be at start of number, so 1-2 = -2 instead of -12
|
||||||
read_digit.exponent = 0;
|
read_digit.exponent = 0;
|
||||||
read_digit.mantissa = 0;
|
read_digit.mantissa = 0;
|
||||||
break;
|
break;
|
||||||
|
|
@ -343,11 +338,11 @@ void scan_char(uint8_t c) {
|
||||||
serial_writechar(c);
|
serial_writechar(c);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
#ifdef REQUIRE_LINENUMBER
|
#ifdef REQUIRE_LINENUMBER
|
||||||
((next_target.N >= next_target.N_expected) && (next_target.seen_N == 1))
|
(next_target.N >= next_target.N_expected) && (next_target.seen_N == 1)
|
||||||
#else
|
#else
|
||||||
1
|
1
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
#ifdef REQUIRE_CHECKSUM
|
#ifdef REQUIRE_CHECKSUM
|
||||||
|
|
@ -357,7 +352,7 @@ void scan_char(uint8_t c) {
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
// process
|
// process
|
||||||
process_gcode_command(&next_target);
|
process_gcode_command();
|
||||||
serial_writestr_P(PSTR("ok\n"));
|
serial_writestr_P(PSTR("ok\n"));
|
||||||
|
|
||||||
// expect next line number
|
// expect next line number
|
||||||
|
|
@ -387,9 +382,11 @@ void scan_char(uint8_t c) {
|
||||||
next_target.checksum_calculated = 0;
|
next_target.checksum_calculated = 0;
|
||||||
last_field = 0;
|
last_field = 0;
|
||||||
read_digit.sign = read_digit.mantissa = read_digit.exponent = 0;
|
read_digit.sign = read_digit.mantissa = read_digit.exponent = 0;
|
||||||
|
|
||||||
// assume a G1 by default
|
// assume a G1 by default
|
||||||
next_target.seen_G = 1;
|
next_target.seen_G = 1;
|
||||||
next_target.G = 1;
|
next_target.G = 1;
|
||||||
|
|
||||||
if (next_target.option_relative) {
|
if (next_target.option_relative) {
|
||||||
next_target.target.X = next_target.target.Y = next_target.target.Z = 0;
|
next_target.target.X = next_target.target.Y = next_target.target.Z = 0;
|
||||||
next_target.target.E = 0;
|
next_target.target.E = 0;
|
||||||
|
|
@ -397,384 +394,6 @@ void scan_char(uint8_t c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* *
|
|
||||||
* Command Received - process it *
|
|
||||||
* *
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
void process_gcode_command(GCODE_COMMAND *gcmd) {
|
|
||||||
uint32_t backup_f;
|
|
||||||
|
|
||||||
// convert relative to absolute
|
|
||||||
if (gcmd->option_relative) {
|
|
||||||
gcmd->target.X += startpoint.X;
|
|
||||||
gcmd->target.Y += startpoint.Y;
|
|
||||||
gcmd->target.Z += startpoint.Z;
|
|
||||||
}
|
|
||||||
// E ALWAYS relative, otherwise we overflow our registers after only a few layers
|
|
||||||
// gcmd->target.E += startpoint.E;
|
|
||||||
// easier way to do this
|
|
||||||
// startpoint.E = 0;
|
|
||||||
// moved to dda.c, end of dda_create() and dda_queue.c, next_move()
|
|
||||||
|
|
||||||
if (gcmd->seen_G) {
|
|
||||||
switch (gcmd->G) {
|
|
||||||
// G0 - rapid, unsynchronised motion
|
|
||||||
// since it would be a major hassle to force the dda to not synchronise, just provide a fast feedrate and hope it's close enough to what host expects
|
|
||||||
case 0:
|
|
||||||
backup_f = gcmd->target.F;
|
|
||||||
gcmd->target.F = MAXIMUM_FEEDRATE_X * 2;
|
|
||||||
enqueue(&gcmd->target);
|
|
||||||
gcmd->target.F = backup_f;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// G1 - synchronised motion
|
|
||||||
case 1:
|
|
||||||
enqueue(&gcmd->target);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// G2 - Arc Clockwise
|
|
||||||
// unimplemented
|
|
||||||
|
|
||||||
// G3 - Arc Counter-clockwise
|
|
||||||
// unimplemented
|
|
||||||
|
|
||||||
// G4 - Dwell
|
|
||||||
case 4:
|
|
||||||
// wait for all moves to complete
|
|
||||||
for (;queue_empty() == 0;)
|
|
||||||
wd_reset();
|
|
||||||
// delay
|
|
||||||
delay_ms(gcmd->P);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// G20 - inches as units
|
|
||||||
case 20:
|
|
||||||
gcmd->option_inches = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// G21 - mm as units
|
|
||||||
case 21:
|
|
||||||
gcmd->option_inches = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// G30 - go home via point
|
|
||||||
case 30:
|
|
||||||
enqueue(&gcmd->target);
|
|
||||||
// no break here, G30 is move and then go home
|
|
||||||
|
|
||||||
// G28 - go home
|
|
||||||
case 28:
|
|
||||||
/*
|
|
||||||
Home XY first
|
|
||||||
*/
|
|
||||||
// hit endstops, no acceleration- we don't care about skipped steps
|
|
||||||
startpoint.F = MAXIMUM_FEEDRATE_X;
|
|
||||||
SpecialMoveXY(-250L * STEPS_PER_MM_X, -250L * STEPS_PER_MM_Y, MAXIMUM_FEEDRATE_X);
|
|
||||||
startpoint.X = startpoint.Y = 0;
|
|
||||||
|
|
||||||
// move forward a bit
|
|
||||||
SpecialMoveXY(5 * STEPS_PER_MM_X, 5 * STEPS_PER_MM_Y, SEARCH_FEEDRATE_X);
|
|
||||||
|
|
||||||
// move back in to endstops slowly
|
|
||||||
SpecialMoveXY(-20 * STEPS_PER_MM_X, -20 * STEPS_PER_MM_Y, SEARCH_FEEDRATE_X);
|
|
||||||
|
|
||||||
// wait for queue to complete
|
|
||||||
for (;queue_empty() == 0;)
|
|
||||||
wd_reset();
|
|
||||||
|
|
||||||
// this is our home point
|
|
||||||
startpoint.X = startpoint.Y = current_position.X = current_position.Y = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Home Z
|
|
||||||
*/
|
|
||||||
// hit endstop, no acceleration- we don't care about skipped steps
|
|
||||||
startpoint.F = MAXIMUM_FEEDRATE_Z;
|
|
||||||
SpecialMoveZ(-250L * STEPS_PER_MM_Z, MAXIMUM_FEEDRATE_Z);
|
|
||||||
startpoint.Z = 0;
|
|
||||||
|
|
||||||
// move forward a bit
|
|
||||||
SpecialMoveZ(5 * STEPS_PER_MM_Z, SEARCH_FEEDRATE_Z);
|
|
||||||
|
|
||||||
// move back into endstop slowly
|
|
||||||
SpecialMoveZ(-20L * STEPS_PER_MM_Z, SEARCH_FEEDRATE_Z);
|
|
||||||
|
|
||||||
// wait for queue to complete
|
|
||||||
for (;queue_empty() == 0;)
|
|
||||||
wd_reset();
|
|
||||||
|
|
||||||
// this is our home point
|
|
||||||
startpoint.Z = current_position.Z = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Home E
|
|
||||||
*/
|
|
||||||
// extruder only runs one way and we have no "endstop", just set this point as home
|
|
||||||
startpoint.E = current_position.E = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Home F
|
|
||||||
*/
|
|
||||||
|
|
||||||
// F has been left at SEARCH_FEEDRATE_Z by the last move, this is a usable "home"
|
|
||||||
// uncomment the following or substitute if you prefer a different default feedrate
|
|
||||||
// startpoint.F = SEARCH_FEEDRATE_Z
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
// G90 - absolute positioning
|
|
||||||
case 90:
|
|
||||||
gcmd->option_relative = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// G91 - relative positioning
|
|
||||||
case 91:
|
|
||||||
gcmd->option_relative = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// G92 - set home
|
|
||||||
case 92:
|
|
||||||
startpoint.X = startpoint.Y = startpoint.Z = startpoint.E =
|
|
||||||
current_position.X = current_position.Y = current_position.Z = current_position.E = 0;
|
|
||||||
startpoint.F =
|
|
||||||
current_position.F = SEARCH_FEEDRATE_Z;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// unknown gcode: spit an error
|
|
||||||
default:
|
|
||||||
serial_writestr_P(PSTR("E: Bad G-code "));
|
|
||||||
serwrite_uint8(gcmd->G);
|
|
||||||
serial_writechar('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (gcmd->seen_M) {
|
|
||||||
switch (gcmd->M) {
|
|
||||||
// M101- extruder on
|
|
||||||
case 101:
|
|
||||||
if (temp_achieved() == 0) {
|
|
||||||
enqueue(NULL);
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
// backup feedrate, move E very quickly then restore feedrate
|
|
||||||
backup_f = startpoint.F;
|
|
||||||
startpoint.F = MAXIMUM_FEEDRATE_E;
|
|
||||||
SpecialMoveE(E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E);
|
|
||||||
startpoint.F = backup_f;
|
|
||||||
} while (0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// M102- extruder reverse
|
|
||||||
|
|
||||||
// M103- extruder off
|
|
||||||
case 103:
|
|
||||||
do {
|
|
||||||
// backup feedrate, move E very quickly then restore feedrate
|
|
||||||
backup_f = startpoint.F;
|
|
||||||
startpoint.F = MAXIMUM_FEEDRATE_E;
|
|
||||||
SpecialMoveE(-E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E);
|
|
||||||
startpoint.F = backup_f;
|
|
||||||
} while (0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// M104- set temperature
|
|
||||||
case 104:
|
|
||||||
temp_set(gcmd->S);
|
|
||||||
if (gcmd->S) {
|
|
||||||
enable_heater();
|
|
||||||
power_on();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
disable_heater();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// M105- get temperature
|
|
||||||
case 105:
|
|
||||||
temp_print();
|
|
||||||
break;
|
|
||||||
|
|
||||||
// M106- fan on
|
|
||||||
#ifdef FAN_PIN
|
|
||||||
case 106:
|
|
||||||
enable_fan();
|
|
||||||
break;
|
|
||||||
// M107- fan off
|
|
||||||
case 107:
|
|
||||||
disable_fan();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// M109- set temp and wait
|
|
||||||
case 109:
|
|
||||||
temp_set(gcmd->S);
|
|
||||||
if (gcmd->S) {
|
|
||||||
enable_heater();
|
|
||||||
power_on();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
disable_heater();
|
|
||||||
}
|
|
||||||
enqueue(NULL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// M110- set line number
|
|
||||||
case 110:
|
|
||||||
gcmd->N_expected = gcmd->S - 1;
|
|
||||||
break;
|
|
||||||
// M111- set debug level
|
|
||||||
#ifdef DEBUG
|
|
||||||
case 111:
|
|
||||||
debug_flags = gcmd->S;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
// M112- immediate stop
|
|
||||||
case 112:
|
|
||||||
disableTimerInterrupt();
|
|
||||||
power_off();
|
|
||||||
break;
|
|
||||||
// M113- extruder PWM
|
|
||||||
// M114- report XYZEF to host
|
|
||||||
case 114:
|
|
||||||
sersendf_P("X:%ld,Y:%ld,Z:%ld,E:%ld,F:%ld\n", current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F);
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifdef HEATER_PIN
|
|
||||||
// M130- heater P factor
|
|
||||||
case 130:
|
|
||||||
if (gcmd->seen_S)
|
|
||||||
p_factor = gcmd->S;
|
|
||||||
break;
|
|
||||||
// M131- heater I factor
|
|
||||||
case 131:
|
|
||||||
if (gcmd->seen_S)
|
|
||||||
i_factor = gcmd->S;
|
|
||||||
break;
|
|
||||||
// M132- heater D factor
|
|
||||||
case 132:
|
|
||||||
if (gcmd->seen_S)
|
|
||||||
d_factor = gcmd->S;
|
|
||||||
break;
|
|
||||||
// M133- heater I limit
|
|
||||||
case 133:
|
|
||||||
if (gcmd->seen_S)
|
|
||||||
i_limit = gcmd->S;
|
|
||||||
break;
|
|
||||||
// M134- save PID settings to eeprom
|
|
||||||
case 134:
|
|
||||||
heater_save_settings();
|
|
||||||
break;
|
|
||||||
#endif /* HEATER_PIN */
|
|
||||||
|
|
||||||
// M190- power on
|
|
||||||
case 190:
|
|
||||||
power_on();
|
|
||||||
#ifdef X_ENABLE_PIN
|
|
||||||
WRITE(X_ENABLE_PIN, 0);
|
|
||||||
#endif
|
|
||||||
#ifdef Y_ENABLE_PIN
|
|
||||||
WRITE(Y_ENABLE_PIN, 0);
|
|
||||||
#endif
|
|
||||||
#ifdef Z_ENABLE_PIN
|
|
||||||
WRITE(Z_ENABLE_PIN, 0);
|
|
||||||
#endif
|
|
||||||
steptimeout = 0;
|
|
||||||
break;
|
|
||||||
// M191- power off
|
|
||||||
case 191:
|
|
||||||
#ifdef X_ENABLE_PIN
|
|
||||||
WRITE(X_ENABLE_PIN, 1);
|
|
||||||
#endif
|
|
||||||
#ifdef Y_ENABLE_PIN
|
|
||||||
WRITE(Y_ENABLE_PIN, 1);
|
|
||||||
#endif
|
|
||||||
#ifdef Z_ENABLE_PIN
|
|
||||||
WRITE(Z_ENABLE_PIN, 1);
|
|
||||||
#endif
|
|
||||||
power_off();
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
// M140- echo off
|
|
||||||
case 140:
|
|
||||||
debug_flags &= ~DEBUG_ECHO;
|
|
||||||
serial_writestr_P(PSTR("Echo off\n"));
|
|
||||||
break;
|
|
||||||
// M141- echo on
|
|
||||||
case 141:
|
|
||||||
debug_flags |= DEBUG_ECHO;
|
|
||||||
serial_writestr_P(PSTR("Echo on\n"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
// DEBUG: return current position
|
|
||||||
case 250:
|
|
||||||
serial_writestr_P(PSTR("{X:"));
|
|
||||||
serwrite_int32(current_position.X);
|
|
||||||
serial_writestr_P(PSTR(",Y:"));
|
|
||||||
serwrite_int32(current_position.Y);
|
|
||||||
serial_writestr_P(PSTR(",Z:"));
|
|
||||||
serwrite_int32(current_position.Z);
|
|
||||||
serial_writestr_P(PSTR(",E:"));
|
|
||||||
serwrite_int32(current_position.E);
|
|
||||||
serial_writestr_P(PSTR(",F:"));
|
|
||||||
serwrite_int32(current_position.F);
|
|
||||||
serial_writestr_P(PSTR(",c:"));
|
|
||||||
serwrite_uint32(movebuffer[mb_tail].c);
|
|
||||||
serial_writestr_P(PSTR("}\n"));
|
|
||||||
|
|
||||||
serial_writestr_P(PSTR("{X:"));
|
|
||||||
serwrite_int32(movebuffer[mb_tail].endpoint.X);
|
|
||||||
serial_writestr_P(PSTR(",Y:"));
|
|
||||||
serwrite_int32(movebuffer[mb_tail].endpoint.Y);
|
|
||||||
serial_writestr_P(PSTR(",Z:"));
|
|
||||||
serwrite_int32(movebuffer[mb_tail].endpoint.Z);
|
|
||||||
serial_writestr_P(PSTR(",E:"));
|
|
||||||
serwrite_int32(movebuffer[mb_tail].endpoint.E);
|
|
||||||
serial_writestr_P(PSTR(",F:"));
|
|
||||||
serwrite_int32(movebuffer[mb_tail].endpoint.F);
|
|
||||||
serial_writestr_P(PSTR(",c:"));
|
|
||||||
#ifdef ACCELERATION_REPRAP
|
|
||||||
serwrite_uint32(movebuffer[mb_tail].end_c);
|
|
||||||
#else
|
|
||||||
serwrite_uint32(movebuffer[mb_tail].c);
|
|
||||||
#endif
|
|
||||||
serial_writestr_P(PSTR("}\n"));
|
|
||||||
|
|
||||||
print_queue();
|
|
||||||
break;
|
|
||||||
|
|
||||||
// DEBUG: read arbitrary memory location
|
|
||||||
case 253:
|
|
||||||
if (gcmd->seen_P == 0)
|
|
||||||
gcmd->P = 1;
|
|
||||||
for (; gcmd->P; gcmd->P--) {
|
|
||||||
serwrite_hex8(*(volatile uint8_t *)(gcmd->S));
|
|
||||||
gcmd->S++;
|
|
||||||
}
|
|
||||||
serial_writechar('\n');
|
|
||||||
break;
|
|
||||||
|
|
||||||
// DEBUG: write arbitrary memory locatiom
|
|
||||||
case 254:
|
|
||||||
serwrite_hex8(gcmd->S);
|
|
||||||
serial_writechar(':');
|
|
||||||
serwrite_hex8(*(volatile uint8_t *)(gcmd->S));
|
|
||||||
serial_writestr_P(PSTR("->"));
|
|
||||||
serwrite_hex8(gcmd->P);
|
|
||||||
serial_writechar('\n');
|
|
||||||
(*(volatile uint8_t *)(gcmd->S)) = gcmd->P;
|
|
||||||
break;
|
|
||||||
#endif /* DEBUG */
|
|
||||||
// unknown mcode: spit an error
|
|
||||||
default:
|
|
||||||
serial_writestr_P(PSTR("E: Bad M-code "));
|
|
||||||
serwrite_uint8(gcmd->M);
|
|
||||||
serial_writechar('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* *
|
* *
|
||||||
* Request a resend of the current line - used from various places. *
|
* Request a resend of the current line - used from various places. *
|
||||||
|
|
@ -784,12 +403,7 @@ void process_gcode_command(GCODE_COMMAND *gcmd) {
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void request_resend(void) {
|
void request_resend(void) {
|
||||||
#if defined REPRAP_HOST_COMPATIBILITY && REPRAP_HOST_COMPATIBILITY >= 20100806
|
|
||||||
serial_writestr_P(PSTR("rs "));
|
serial_writestr_P(PSTR("rs "));
|
||||||
#else
|
|
||||||
serial_writestr_P(PSTR("Resend:"));
|
|
||||||
#endif
|
|
||||||
serwrite_uint8(next_target.N);
|
serwrite_uint8(next_target.N);
|
||||||
serial_writechar('\n');
|
serial_writechar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _GCODE_H
|
#ifndef _GCODE_PARSE_H
|
||||||
#define _GCODE_H
|
#define _GCODE_PARSE_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
@ -69,12 +69,9 @@ void SpecialMoveZ(int32_t z, uint32_t f);
|
||||||
void SpecialMoveE(int32_t e, uint32_t f);
|
void SpecialMoveE(int32_t e, uint32_t f);
|
||||||
|
|
||||||
// accept the next character and process it
|
// accept the next character and process it
|
||||||
void scan_char(uint8_t c);
|
void gcode_parse_char(uint8_t c);
|
||||||
|
|
||||||
// when we have a whole line, feed it to this
|
|
||||||
void process_gcode_command(GCODE_COMMAND *gcmd);
|
|
||||||
|
|
||||||
// uses the global variable next_target.N
|
// uses the global variable next_target.N
|
||||||
void request_resend(void);
|
void request_resend(void);
|
||||||
|
|
||||||
#endif /* _GCODE_H */
|
#endif /* _GCODE_PARSE_H */
|
||||||
|
|
@ -0,0 +1,393 @@
|
||||||
|
#include "gcode_process.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gcode_parse.h"
|
||||||
|
|
||||||
|
#include "dda_queue.h"
|
||||||
|
#include "watchdog.h"
|
||||||
|
#include "delay.h"
|
||||||
|
#include "serial.h"
|
||||||
|
#include "sermsg.h"
|
||||||
|
#include "temp.h"
|
||||||
|
#include "heater.h"
|
||||||
|
#include "timer.h"
|
||||||
|
#include "sersendf.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* *
|
||||||
|
* Command Received - process it *
|
||||||
|
* *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void process_gcode_command() {
|
||||||
|
uint32_t backup_f;
|
||||||
|
|
||||||
|
// convert relative to absolute
|
||||||
|
if (next_target.option_relative) {
|
||||||
|
next_target.target.X += startpoint.X;
|
||||||
|
next_target.target.Y += startpoint.Y;
|
||||||
|
next_target.target.Z += startpoint.Z;
|
||||||
|
}
|
||||||
|
// E ALWAYS relative, otherwise we overflow our registers after only a few layers
|
||||||
|
// next_target.target.E += startpoint.E;
|
||||||
|
// easier way to do this
|
||||||
|
// startpoint.E = 0;
|
||||||
|
// moved to dda.c, end of dda_create() and dda_queue.c, next_move()
|
||||||
|
|
||||||
|
if (next_target.seen_G) {
|
||||||
|
switch (next_target.G) {
|
||||||
|
// G0 - rapid, unsynchronised motion
|
||||||
|
// since it would be a major hassle to force the dda to not synchronise, just provide a fast feedrate and hope it's close enough to what host expects
|
||||||
|
case 0:
|
||||||
|
backup_f = next_target.target.F;
|
||||||
|
next_target.target.F = MAXIMUM_FEEDRATE_X * 2;
|
||||||
|
enqueue(&next_target.target);
|
||||||
|
next_target.target.F = backup_f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// G1 - synchronised motion
|
||||||
|
case 1:
|
||||||
|
enqueue(&next_target.target);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// G2 - Arc Clockwise
|
||||||
|
// unimplemented
|
||||||
|
|
||||||
|
// G3 - Arc Counter-clockwise
|
||||||
|
// unimplemented
|
||||||
|
|
||||||
|
// G4 - Dwell
|
||||||
|
case 4:
|
||||||
|
// wait for all moves to complete
|
||||||
|
for (;queue_empty() == 0;)
|
||||||
|
wd_reset();
|
||||||
|
// delay
|
||||||
|
delay_ms(next_target.P);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// G20 - inches as units
|
||||||
|
case 20:
|
||||||
|
next_target.option_inches = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// G21 - mm as units
|
||||||
|
case 21:
|
||||||
|
next_target.option_inches = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// G30 - go home via point
|
||||||
|
case 30:
|
||||||
|
enqueue(&next_target.target);
|
||||||
|
// no break here, G30 is move and then go home
|
||||||
|
|
||||||
|
// G28 - go home
|
||||||
|
case 28:
|
||||||
|
/*
|
||||||
|
Home XY first
|
||||||
|
*/
|
||||||
|
// hit endstops, no acceleration- we don't care about skipped steps
|
||||||
|
startpoint.F = MAXIMUM_FEEDRATE_X;
|
||||||
|
SpecialMoveXY(-250L * STEPS_PER_MM_X, -250L * STEPS_PER_MM_Y, MAXIMUM_FEEDRATE_X);
|
||||||
|
startpoint.X = startpoint.Y = 0;
|
||||||
|
|
||||||
|
// move forward a bit
|
||||||
|
SpecialMoveXY(5 * STEPS_PER_MM_X, 5 * STEPS_PER_MM_Y, SEARCH_FEEDRATE_X);
|
||||||
|
|
||||||
|
// move back in to endstops slowly
|
||||||
|
SpecialMoveXY(-20 * STEPS_PER_MM_X, -20 * STEPS_PER_MM_Y, SEARCH_FEEDRATE_X);
|
||||||
|
|
||||||
|
// wait for queue to complete
|
||||||
|
for (;queue_empty() == 0;)
|
||||||
|
wd_reset();
|
||||||
|
|
||||||
|
// this is our home point
|
||||||
|
startpoint.X = startpoint.Y = current_position.X = current_position.Y = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Home Z
|
||||||
|
*/
|
||||||
|
// hit endstop, no acceleration- we don't care about skipped steps
|
||||||
|
startpoint.F = MAXIMUM_FEEDRATE_Z;
|
||||||
|
SpecialMoveZ(-250L * STEPS_PER_MM_Z, MAXIMUM_FEEDRATE_Z);
|
||||||
|
startpoint.Z = 0;
|
||||||
|
|
||||||
|
// move forward a bit
|
||||||
|
SpecialMoveZ(5 * STEPS_PER_MM_Z, SEARCH_FEEDRATE_Z);
|
||||||
|
|
||||||
|
// move back into endstop slowly
|
||||||
|
SpecialMoveZ(-20L * STEPS_PER_MM_Z, SEARCH_FEEDRATE_Z);
|
||||||
|
|
||||||
|
// wait for queue to complete
|
||||||
|
for (;queue_empty() == 0;)
|
||||||
|
wd_reset();
|
||||||
|
|
||||||
|
// this is our home point
|
||||||
|
startpoint.Z = current_position.Z = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Home E
|
||||||
|
*/
|
||||||
|
// extruder only runs one way and we have no "endstop", just set this point as home
|
||||||
|
startpoint.E = current_position.E = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Home F
|
||||||
|
*/
|
||||||
|
|
||||||
|
// F has been left at SEARCH_FEEDRATE_Z by the last move, this is a usable "home"
|
||||||
|
// uncomment the following or substitute if you prefer a different default feedrate
|
||||||
|
// startpoint.F = SEARCH_FEEDRATE_Z
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// G90 - absolute positioning
|
||||||
|
case 90:
|
||||||
|
next_target.option_relative = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// G91 - relative positioning
|
||||||
|
case 91:
|
||||||
|
next_target.option_relative = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// G92 - set home
|
||||||
|
case 92:
|
||||||
|
startpoint.X = startpoint.Y = startpoint.Z = startpoint.E =
|
||||||
|
current_position.X = current_position.Y = current_position.Z = current_position.E = 0;
|
||||||
|
startpoint.F =
|
||||||
|
current_position.F = SEARCH_FEEDRATE_Z;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// unknown gcode: spit an error
|
||||||
|
default:
|
||||||
|
serial_writestr_P(PSTR("E: Bad G-code "));
|
||||||
|
serwrite_uint8(next_target.G);
|
||||||
|
serial_writechar('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (next_target.seen_M) {
|
||||||
|
switch (next_target.M) {
|
||||||
|
// M101- extruder on
|
||||||
|
case 101:
|
||||||
|
if (temp_achieved() == 0) {
|
||||||
|
enqueue(NULL);
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
// backup feedrate, move E very quickly then restore feedrate
|
||||||
|
backup_f = startpoint.F;
|
||||||
|
startpoint.F = MAXIMUM_FEEDRATE_E;
|
||||||
|
SpecialMoveE(E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E);
|
||||||
|
startpoint.F = backup_f;
|
||||||
|
} while (0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// M102- extruder reverse
|
||||||
|
|
||||||
|
// M103- extruder off
|
||||||
|
case 103:
|
||||||
|
do {
|
||||||
|
// backup feedrate, move E very quickly then restore feedrate
|
||||||
|
backup_f = startpoint.F;
|
||||||
|
startpoint.F = MAXIMUM_FEEDRATE_E;
|
||||||
|
SpecialMoveE(-E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E);
|
||||||
|
startpoint.F = backup_f;
|
||||||
|
} while (0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// M104- set temperature
|
||||||
|
case 104:
|
||||||
|
temp_set(next_target.S);
|
||||||
|
if (next_target.S) {
|
||||||
|
enable_heater();
|
||||||
|
power_on();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
disable_heater();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// M105- get temperature
|
||||||
|
case 105:
|
||||||
|
temp_print();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// M106- fan on
|
||||||
|
#ifdef FAN_PIN
|
||||||
|
case 106:
|
||||||
|
enable_fan();
|
||||||
|
break;
|
||||||
|
// M107- fan off
|
||||||
|
case 107:
|
||||||
|
disable_fan();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// M109- set temp and wait
|
||||||
|
case 109:
|
||||||
|
temp_set(next_target.S);
|
||||||
|
if (next_target.S) {
|
||||||
|
enable_heater();
|
||||||
|
power_on();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
disable_heater();
|
||||||
|
}
|
||||||
|
enqueue(NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// M110- set line number
|
||||||
|
case 110:
|
||||||
|
next_target.N_expected = next_target.S - 1;
|
||||||
|
break;
|
||||||
|
// M111- set debug level
|
||||||
|
#ifdef DEBUG
|
||||||
|
case 111:
|
||||||
|
debug_flags = next_target.S;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
// M112- immediate stop
|
||||||
|
case 112:
|
||||||
|
disableTimerInterrupt();
|
||||||
|
power_off();
|
||||||
|
break;
|
||||||
|
// M113- extruder PWM
|
||||||
|
// M114- report XYZEF to host
|
||||||
|
case 114:
|
||||||
|
sersendf_P("X:%ld,Y:%ld,Z:%ld,E:%ld,F:%ld\n", current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef HEATER_PIN
|
||||||
|
// M130- heater P factor
|
||||||
|
case 130:
|
||||||
|
if (next_target.seen_S)
|
||||||
|
p_factor = next_target.S;
|
||||||
|
break;
|
||||||
|
// M131- heater I factor
|
||||||
|
case 131:
|
||||||
|
if (next_target.seen_S)
|
||||||
|
i_factor = next_target.S;
|
||||||
|
break;
|
||||||
|
// M132- heater D factor
|
||||||
|
case 132:
|
||||||
|
if (next_target.seen_S)
|
||||||
|
d_factor = next_target.S;
|
||||||
|
break;
|
||||||
|
// M133- heater I limit
|
||||||
|
case 133:
|
||||||
|
if (next_target.seen_S)
|
||||||
|
i_limit = next_target.S;
|
||||||
|
break;
|
||||||
|
// M134- save PID settings to eeprom
|
||||||
|
case 134:
|
||||||
|
heater_save_settings();
|
||||||
|
break;
|
||||||
|
#endif /* HEATER_PIN */
|
||||||
|
|
||||||
|
// M190- power on
|
||||||
|
case 190:
|
||||||
|
power_on();
|
||||||
|
#ifdef X_ENABLE_PIN
|
||||||
|
WRITE(X_ENABLE_PIN, 0);
|
||||||
|
#endif
|
||||||
|
#ifdef Y_ENABLE_PIN
|
||||||
|
WRITE(Y_ENABLE_PIN, 0);
|
||||||
|
#endif
|
||||||
|
#ifdef Z_ENABLE_PIN
|
||||||
|
WRITE(Z_ENABLE_PIN, 0);
|
||||||
|
#endif
|
||||||
|
steptimeout = 0;
|
||||||
|
break;
|
||||||
|
// M191- power off
|
||||||
|
case 191:
|
||||||
|
#ifdef X_ENABLE_PIN
|
||||||
|
WRITE(X_ENABLE_PIN, 1);
|
||||||
|
#endif
|
||||||
|
#ifdef Y_ENABLE_PIN
|
||||||
|
WRITE(Y_ENABLE_PIN, 1);
|
||||||
|
#endif
|
||||||
|
#ifdef Z_ENABLE_PIN
|
||||||
|
WRITE(Z_ENABLE_PIN, 1);
|
||||||
|
#endif
|
||||||
|
power_off();
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
// M140- echo off
|
||||||
|
case 140:
|
||||||
|
debug_flags &= ~DEBUG_ECHO;
|
||||||
|
serial_writestr_P(PSTR("Echo off\n"));
|
||||||
|
break;
|
||||||
|
// M141- echo on
|
||||||
|
case 141:
|
||||||
|
debug_flags |= DEBUG_ECHO;
|
||||||
|
serial_writestr_P(PSTR("Echo on\n"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
// DEBUG: return current position
|
||||||
|
case 250:
|
||||||
|
serial_writestr_P(PSTR("{X:"));
|
||||||
|
serwrite_int32(current_position.X);
|
||||||
|
serial_writestr_P(PSTR(",Y:"));
|
||||||
|
serwrite_int32(current_position.Y);
|
||||||
|
serial_writestr_P(PSTR(",Z:"));
|
||||||
|
serwrite_int32(current_position.Z);
|
||||||
|
serial_writestr_P(PSTR(",E:"));
|
||||||
|
serwrite_int32(current_position.E);
|
||||||
|
serial_writestr_P(PSTR(",F:"));
|
||||||
|
serwrite_int32(current_position.F);
|
||||||
|
serial_writestr_P(PSTR(",c:"));
|
||||||
|
serwrite_uint32(movebuffer[mb_tail].c);
|
||||||
|
serial_writestr_P(PSTR("}\n"));
|
||||||
|
|
||||||
|
serial_writestr_P(PSTR("{X:"));
|
||||||
|
serwrite_int32(movebuffer[mb_tail].endpoint.X);
|
||||||
|
serial_writestr_P(PSTR(",Y:"));
|
||||||
|
serwrite_int32(movebuffer[mb_tail].endpoint.Y);
|
||||||
|
serial_writestr_P(PSTR(",Z:"));
|
||||||
|
serwrite_int32(movebuffer[mb_tail].endpoint.Z);
|
||||||
|
serial_writestr_P(PSTR(",E:"));
|
||||||
|
serwrite_int32(movebuffer[mb_tail].endpoint.E);
|
||||||
|
serial_writestr_P(PSTR(",F:"));
|
||||||
|
serwrite_int32(movebuffer[mb_tail].endpoint.F);
|
||||||
|
serial_writestr_P(PSTR(",c:"));
|
||||||
|
#ifdef ACCELERATION_REPRAP
|
||||||
|
serwrite_uint32(movebuffer[mb_tail].end_c);
|
||||||
|
#else
|
||||||
|
serwrite_uint32(movebuffer[mb_tail].c);
|
||||||
|
#endif
|
||||||
|
serial_writestr_P(PSTR("}\n"));
|
||||||
|
|
||||||
|
print_queue();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// DEBUG: read arbitrary memory location
|
||||||
|
case 253:
|
||||||
|
if (next_target.seen_P == 0)
|
||||||
|
next_target.P = 1;
|
||||||
|
for (; next_target.P; next_target.P--) {
|
||||||
|
serwrite_hex8(*(volatile uint8_t *)(next_target.S));
|
||||||
|
next_target.S++;
|
||||||
|
}
|
||||||
|
serial_writechar('\n');
|
||||||
|
break;
|
||||||
|
|
||||||
|
// DEBUG: write arbitrary memory locatiom
|
||||||
|
case 254:
|
||||||
|
serwrite_hex8(next_target.S);
|
||||||
|
serial_writechar(':');
|
||||||
|
serwrite_hex8(*(volatile uint8_t *)(next_target.S));
|
||||||
|
serial_writestr_P(PSTR("->"));
|
||||||
|
serwrite_hex8(next_target.P);
|
||||||
|
serial_writechar('\n');
|
||||||
|
(*(volatile uint8_t *)(next_target.S)) = next_target.P;
|
||||||
|
break;
|
||||||
|
#endif /* DEBUG */
|
||||||
|
// unknown mcode: spit an error
|
||||||
|
default:
|
||||||
|
serial_writestr_P(PSTR("E: Bad M-code "));
|
||||||
|
serwrite_uint8(next_target.M);
|
||||||
|
serial_writechar('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef _GCODE_PROCESS_H
|
||||||
|
#define _GCODE_PROCESS_H
|
||||||
|
|
||||||
|
#include "gcode_parse.h"
|
||||||
|
|
||||||
|
// when we have a whole line, feed it to this
|
||||||
|
void process_gcode_command(void);
|
||||||
|
|
||||||
|
#endif /* _GCODE_PROCESS_H */
|
||||||
4
mendel.c
4
mendel.c
|
|
@ -7,7 +7,7 @@
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
#include "dda_queue.h"
|
#include "dda_queue.h"
|
||||||
#include "dda.h"
|
#include "dda.h"
|
||||||
#include "gcode.h"
|
#include "gcode_parse.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "temp.h"
|
#include "temp.h"
|
||||||
|
|
@ -151,7 +151,7 @@ int main (void)
|
||||||
// if queue is full, no point in reading chars- host will just have to wait
|
// if queue is full, no point in reading chars- host will just have to wait
|
||||||
if ((serial_rxchars() != 0) && (queue_full() == 0)) {
|
if ((serial_rxchars() != 0) && (queue_full() == 0)) {
|
||||||
uint8_t c = serial_popchar();
|
uint8_t c = serial_popchar();
|
||||||
scan_char(c);
|
gcode_parse_char(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
ifclock(CLOCK_FLAG_250MS) {
|
ifclock(CLOCK_FLAG_250MS) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue