diff --git a/config.h b/config.h index 84eff6f..88109d3 100644 --- a/config.h +++ b/config.h @@ -28,6 +28,10 @@ #ifndef config_h #define config_h +// Allows GRBL to tranck and report gcode line numbers. Enabling this means that the planning buffer +// goes from 18 or 16 to make room for the additional line number data in the plan_block_t struct +#define USE_LINE_NUMBERS + // Default settings. Used when resetting EEPROM. Change to desired name in defaults.h #define DEFAULTS_SHERLINE_5400 diff --git a/gcode.c b/gcode.c index 3306abb..450f9af 100644 --- a/gcode.c +++ b/gcode.c @@ -101,6 +101,7 @@ uint8_t gc_execute_line(char *line) float target[N_AXIS]; clear_vector(target); // XYZ(ABC) axes parameters. + uint32_t line_number = 0; gc.arc_radius = 0; clear_vector(gc.arc_offset); // IJK Arc offsets are incremental. Value of zero indicates no change. @@ -215,7 +216,7 @@ uint8_t gc_execute_line(char *line) char_counter = 0; while(next_statement(&letter, &value, line, &char_counter)) { switch(letter) { - case 'G': case 'M': case 'N': break; // Ignore command statements and line numbers + case 'G': case 'M': break; // Ignore command statements and line numbers case 'F': if (value <= 0) { FAIL(STATUS_INVALID_STATEMENT); } // Must be greater than zero if (gc.inverse_feed_rate_mode) { @@ -226,6 +227,7 @@ uint8_t gc_execute_line(char *line) break; case 'I': case 'J': case 'K': gc.arc_offset[letter-'I'] = to_millimeters(value); break; case 'L': l = trunc(value); break; + case 'N': line_number = trunc(value); break; case 'P': p = value; break; case 'R': gc.arc_radius = to_millimeters(value); break; case 'S': @@ -329,7 +331,7 @@ uint8_t gc_execute_line(char *line) target[idx] = gc.position[idx]; } } - mc_line(target, -1.0, false); + mc_line(target, -1.0, false, line_number); } // Retreive G28/30 go-home position data (in machine coordinates) from EEPROM float coord_data[N_AXIS]; @@ -338,7 +340,7 @@ uint8_t gc_execute_line(char *line) } else { if (!settings_read_coord_data(SETTING_INDEX_G30,coord_data)) { return(STATUS_SETTING_READ_FAIL); } } - mc_line(coord_data, -1.0, false); + mc_line(coord_data, -1.0, false, line_number); memcpy(gc.position, coord_data, sizeof(coord_data)); // gc.position[] = coord_data[]; axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags. break; @@ -409,7 +411,7 @@ uint8_t gc_execute_line(char *line) break; case MOTION_MODE_SEEK: if (!axis_words) { FAIL(STATUS_INVALID_STATEMENT);} - else { mc_line(target, -1.0, false); } + else { mc_line(target, -1.0, false, line_number); } break; case MOTION_MODE_LINEAR: // TODO: Inverse time requires F-word with each statement. Need to do a check. Also need @@ -417,7 +419,7 @@ uint8_t gc_execute_line(char *line) // and after an inverse time move and then check for non-zero feed rate each time. This // should be efficient and effective. if (!axis_words) { FAIL(STATUS_INVALID_STATEMENT);} - else { mc_line(target, (gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode); } + else { mc_line(target, (gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode, line_number); } break; case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC: // Check if at least one of the axes of the selected plane has been specified. If in center @@ -441,7 +443,7 @@ uint8_t gc_execute_line(char *line) // Trace the arc mc_arc(gc.position, target, gc.arc_offset, gc.plane_axis_0, gc.plane_axis_1, gc.plane_axis_2, (gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode, - gc.arc_radius, isclockwise); + gc.arc_radius, isclockwise, line_number); } break; } diff --git a/limits.c b/limits.c index 1660ec4..10f0311 100644 --- a/limits.c +++ b/limits.c @@ -83,13 +83,13 @@ void limits_disable() // moves in the planner and serial buffers are all cleared and newly sent blocks will be // locked out until a homing cycle or a kill lock command. Allows the user to disable the hard // limit setting if their limits are constantly triggering after a reset and move their axes. - if (sys.state != STATE_ALARM) { + if (sys.state != STATE_ALARM) { if (bit_isfalse(sys.execute,EXEC_ALARM)) { - mc_reset(); // Initiate system kill. - sys.execute |= EXEC_CRIT_EVENT; // Indicate hard limit critical event + mc_reset(); // Initiate system kill. + sys.execute |= EXEC_CRIT_EVENT; // Indicate hard limit critical event + } } } - } #else // OPTIONAL: Software debounce limit pin routine. // Upon limit pin change, enable watchdog timer to create a short delay. ISR(LIMIT_INT_vect) { if (!(WDTCSR & (1<millimeters = 0; block->direction_bits = 0; block->acceleration = SOME_LARGE_VALUE; // Scaled down to maximum acceleration later - +#ifdef USE_LINE_NUMBERS + block->line_number = line_number; +#endif // Compute and store initial move distance data. // TODO: After this for-loop, we don't touch the stepper algorithm data. Might be a good idea // to try to keep these types of things completely separate from the planner for portability. diff --git a/planner.h b/planner.h index 535291e..29b571b 100644 --- a/planner.h +++ b/planner.h @@ -26,7 +26,11 @@ // The number of linear motions that can be in the plan at any give time #ifndef BLOCK_BUFFER_SIZE - #define BLOCK_BUFFER_SIZE 18 + #ifdef USE_LINE_NUMBERS + #define BLOCK_BUFFER_SIZE 16 + #else + #define BLOCK_BUFFER_SIZE 18 + #endif #endif // This struct stores a linear movement of a g-code block motion with its critical "nominal" values @@ -47,6 +51,9 @@ typedef struct { float acceleration; // Axis-limit adjusted line acceleration in (mm/min^2) float millimeters; // The remaining distance for this block to be executed in (mm) // uint8_t max_override; // Maximum override value based on axis speed limits +#ifdef USE_LINE_NUMBERS + uint32_t line_number; +#endif } plan_block_t; @@ -56,7 +63,7 @@ void plan_reset(); // Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position // in millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed // rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes. -void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate); +void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate, uint32_t line_number); // Called when the current block is no longer needed. Discards the block and makes the memory // availible for new blocks. diff --git a/report.c b/report.c index 5416651..e17b6a9 100644 --- a/report.c +++ b/report.c @@ -32,6 +32,7 @@ #include "settings.h" #include "gcode.h" #include "coolant_control.h" +#include "planner.h" #include "spindle_control.h" @@ -261,9 +262,9 @@ void report_gcode_modes() } switch (gc.spindle_direction) { - case SPINDLE_ENABLE_CW : printPgmString(PSTR(" M3")); break; - case SPINDLE_ENABLE_CCW : printPgmString(PSTR(" M4")); break; - case SPINDLE_DISABLE : printPgmString(PSTR(" M5")); break; + case 1 : printPgmString(PSTR(" M3")); break; + case -1 : printPgmString(PSTR(" M4")); break; + case 0 : printPgmString(PSTR(" M5")); break; } switch (gc.coolant_mode) { @@ -350,5 +351,17 @@ void report_realtime_status() if (i < (N_AXIS-1)) { printPgmString(PSTR(",")); } } +#ifdef USE_LINE_NUMBERS + // Report current line number + printPgmString(PSTR(",")); + printPgmString(PSTR("Ln:")); + uint32_t ln=0; + plan_block_t * pb = plan_get_current_block(); + if(pb != NULL) { + ln = pb->line_number; + } + printInteger(ln); +#endif + printPgmString(PSTR(">\r\n")); }