refactored handling of settings '$' command out of gcode module and into settings module
This commit is contained in:
parent
6893463e80
commit
9876e14f0b
2
Makefile
2
Makefile
@ -31,7 +31,7 @@ DEVICE = atmega328p
|
|||||||
CLOCK = 16000000
|
CLOCK = 16000000
|
||||||
PROGRAMMER = -c avrisp2 -P usb
|
PROGRAMMER = -c avrisp2 -P usb
|
||||||
OBJECTS = main.o motion_control.o gcode.o spindle_control.o wiring_serial.o protocol.o stepper.o \
|
OBJECTS = main.o motion_control.o gcode.o spindle_control.o wiring_serial.o protocol.o stepper.o \
|
||||||
eeprom.o settings.o planner.o
|
eeprom.o settings.o planner.o nuts_bolts.o
|
||||||
# FUSES = -U hfuse:w:0xd9:m -U lfuse:w:0x24:m
|
# FUSES = -U hfuse:w:0xd9:m -U lfuse:w:0x24:m
|
||||||
FUSES = -U hfuse:w:0xd2:m -U lfuse:w:0xff:m
|
FUSES = -U hfuse:w:0xd2:m -U lfuse:w:0xff:m
|
||||||
# update that line with this when programmer is back up:
|
# update that line with this when programmer is back up:
|
||||||
|
56
gcode.c
56
gcode.c
@ -22,7 +22,6 @@
|
|||||||
by Kramer, Proctor and Messina. */
|
by Kramer, Proctor and Messina. */
|
||||||
|
|
||||||
#include "gcode.h"
|
#include "gcode.h"
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "nuts_bolts.h"
|
#include "nuts_bolts.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@ -63,7 +62,7 @@ typedef struct {
|
|||||||
uint8_t inches_mode; /* 0 = millimeter mode, 1 = inches mode {G20, G21} */
|
uint8_t inches_mode; /* 0 = millimeter mode, 1 = inches mode {G20, G21} */
|
||||||
uint8_t absolute_mode; /* 0 = relative motion, 1 = absolute motion {G90, G91} */
|
uint8_t absolute_mode; /* 0 = relative motion, 1 = absolute motion {G90, G91} */
|
||||||
uint8_t program_flow;
|
uint8_t program_flow;
|
||||||
int spindle_direction;
|
int8_t spindle_direction;
|
||||||
double feed_rate, seek_rate; /* Millimeters/second */
|
double feed_rate, seek_rate; /* Millimeters/second */
|
||||||
double position[3]; /* Where the interpreter considers the tool to be at this point in the code */
|
double position[3]; /* Where the interpreter considers the tool to be at this point in the code */
|
||||||
uint8_t tool;
|
uint8_t tool;
|
||||||
@ -76,11 +75,7 @@ static parser_state_t gc;
|
|||||||
|
|
||||||
#define FAIL(status) gc.status_code = status;
|
#define FAIL(status) gc.status_code = status;
|
||||||
|
|
||||||
int read_double(char *line, // <- string: line of RS274/NGC code being processed
|
int next_statement(char *letter, double *double_ptr, char *line, uint8_t *char_counter);
|
||||||
int *char_counter, // <- pointer to a counter for position on the line
|
|
||||||
double *double_ptr); // <- pointer to double to be read
|
|
||||||
|
|
||||||
int next_statement(char *letter, double *double_ptr, char *line, int *char_counter);
|
|
||||||
|
|
||||||
|
|
||||||
void select_plane(uint8_t axis_0, uint8_t axis_1, uint8_t axis_2)
|
void select_plane(uint8_t axis_0, uint8_t axis_1, uint8_t axis_2)
|
||||||
@ -122,7 +117,7 @@ double theta(double x, double y)
|
|||||||
// Executes one line of 0-terminated G-Code. The line is assumed to contain only uppercase
|
// Executes one line of 0-terminated G-Code. The line is assumed to contain only uppercase
|
||||||
// characters and signed floating point values (no whitespace).
|
// characters and signed floating point values (no whitespace).
|
||||||
uint8_t gc_execute_line(char *line) {
|
uint8_t gc_execute_line(char *line) {
|
||||||
int char_counter = 0;
|
uint8_t char_counter = 0;
|
||||||
char letter;
|
char letter;
|
||||||
double value;
|
double value;
|
||||||
double unit_converted_value;
|
double unit_converted_value;
|
||||||
@ -140,27 +135,12 @@ uint8_t gc_execute_line(char *line) {
|
|||||||
clear_vector(target);
|
clear_vector(target);
|
||||||
clear_vector(offset);
|
clear_vector(offset);
|
||||||
|
|
||||||
gc.status_code = GCSTATUS_OK;
|
gc.status_code = STATUS_OK;
|
||||||
|
|
||||||
// Disregard comments and block delete
|
// Disregard comments and block delete
|
||||||
if (line[0] == '(') { return(gc.status_code); }
|
if (line[0] == '(') { return(gc.status_code); }
|
||||||
if (line[0] == '/') { char_counter++; } // ignore block delete
|
if (line[0] == '/') { char_counter++; } // ignore block delete
|
||||||
|
|
||||||
// If the line starts with an '$' it is a configuration-command
|
|
||||||
if (line[0] == '$') {
|
|
||||||
// Parameter lines are on the form '$4=374.3' or '$' to dump current settings
|
|
||||||
char_counter = 1;
|
|
||||||
if(line[char_counter] == 0) { settings_dump(); return(GCSTATUS_OK); }
|
|
||||||
read_double(line, &char_counter, &p);
|
|
||||||
if(line[char_counter++] != '=') { return(GCSTATUS_UNSUPPORTED_STATEMENT); }
|
|
||||||
read_double(line, &char_counter, &value);
|
|
||||||
if(line[char_counter] != 0) { return(GCSTATUS_UNSUPPORTED_STATEMENT); }
|
|
||||||
settings_store_setting(p, value);
|
|
||||||
return(gc.status_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We'll handle this as g-code. First: parse all statements */
|
|
||||||
|
|
||||||
// Pass 1: Commands
|
// Pass 1: Commands
|
||||||
while(next_statement(&letter, &value, line, &char_counter)) {
|
while(next_statement(&letter, &value, line, &char_counter)) {
|
||||||
int_value = trunc(value);
|
int_value = trunc(value);
|
||||||
@ -184,7 +164,7 @@ uint8_t gc_execute_line(char *line) {
|
|||||||
case 91: gc.absolute_mode = FALSE; break;
|
case 91: gc.absolute_mode = FALSE; break;
|
||||||
case 93: gc.inverse_feed_rate_mode = TRUE; break;
|
case 93: gc.inverse_feed_rate_mode = TRUE; break;
|
||||||
case 94: gc.inverse_feed_rate_mode = FALSE; break;
|
case 94: gc.inverse_feed_rate_mode = FALSE; break;
|
||||||
default: FAIL(GCSTATUS_UNSUPPORTED_STATEMENT);
|
default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -195,7 +175,7 @@ uint8_t gc_execute_line(char *line) {
|
|||||||
case 3: gc.spindle_direction = 1; break;
|
case 3: gc.spindle_direction = 1; break;
|
||||||
case 4: gc.spindle_direction = -1; break;
|
case 4: gc.spindle_direction = -1; break;
|
||||||
case 5: gc.spindle_direction = 0; break;
|
case 5: gc.spindle_direction = 0; break;
|
||||||
default: FAIL(GCSTATUS_UNSUPPORTED_STATEMENT);
|
default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'T': gc.tool = trunc(value); break;
|
case 'T': gc.tool = trunc(value); break;
|
||||||
@ -324,7 +304,7 @@ uint8_t gc_execute_line(char *line) {
|
|||||||
double h_x2_div_d = -sqrt(4 * r*r - x*x - y*y)/hypot(x,y); // == -(h * 2 / d)
|
double h_x2_div_d = -sqrt(4 * r*r - x*x - y*y)/hypot(x,y); // == -(h * 2 / d)
|
||||||
// If r is smaller than d, the arc is now traversing the complex plane beyond the reach of any
|
// If r is smaller than d, the arc is now traversing the complex plane beyond the reach of any
|
||||||
// real CNC, and thus - for practical reasons - we will terminate promptly:
|
// real CNC, and thus - for practical reasons - we will terminate promptly:
|
||||||
if(isnan(h_x2_div_d)) { FAIL(GCSTATUS_FLOATING_POINT_ERROR); return(gc.status_code); }
|
if(isnan(h_x2_div_d)) { FAIL(STATUS_FLOATING_POINT_ERROR); return(gc.status_code); }
|
||||||
// Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below)
|
// Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below)
|
||||||
if (gc.motion_mode == MOTION_MODE_CCW_ARC) { h_x2_div_d = -h_x2_div_d; }
|
if (gc.motion_mode == MOTION_MODE_CCW_ARC) { h_x2_div_d = -h_x2_div_d; }
|
||||||
|
|
||||||
@ -407,40 +387,24 @@ uint8_t gc_execute_line(char *line) {
|
|||||||
// Parses the next statement and leaves the counter on the first character following
|
// Parses the next statement and leaves the counter on the first character following
|
||||||
// the statement. Returns 1 if there was a statements, 0 if end of string was reached
|
// the statement. Returns 1 if there was a statements, 0 if end of string was reached
|
||||||
// or there was an error (check state.status_code).
|
// or there was an error (check state.status_code).
|
||||||
int next_statement(char *letter, double *double_ptr, char *line, int *char_counter) {
|
int next_statement(char *letter, double *double_ptr, char *line, uint8_t *char_counter) {
|
||||||
if (line[*char_counter] == 0) {
|
if (line[*char_counter] == 0) {
|
||||||
return(0); // No more statements
|
return(0); // No more statements
|
||||||
}
|
}
|
||||||
|
|
||||||
*letter = line[*char_counter];
|
*letter = line[*char_counter];
|
||||||
if((*letter < 'A') || (*letter > 'Z')) {
|
if((*letter < 'A') || (*letter > 'Z')) {
|
||||||
FAIL(GCSTATUS_EXPECTED_COMMAND_LETTER);
|
FAIL(STATUS_EXPECTED_COMMAND_LETTER);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
(*char_counter)++;
|
(*char_counter)++;
|
||||||
if (!read_double(line, char_counter, double_ptr)) {
|
if (!read_double(line, char_counter, double_ptr)) {
|
||||||
|
FAIL(STATUS_BAD_NUMBER_FORMAT);
|
||||||
return(0);
|
return(0);
|
||||||
};
|
};
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_double(char *line, //!< string: line of RS274/NGC code being processed
|
|
||||||
int *char_counter, //!< pointer to a counter for position on the line
|
|
||||||
double *double_ptr) //!< pointer to double to be read
|
|
||||||
{
|
|
||||||
char *start = line + *char_counter;
|
|
||||||
char *end;
|
|
||||||
|
|
||||||
*double_ptr = strtod(start, &end);
|
|
||||||
if(end == start) {
|
|
||||||
FAIL(GCSTATUS_BAD_NUMBER_FORMAT);
|
|
||||||
return(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
*char_counter = end - line;
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Intentionally not supported:
|
Intentionally not supported:
|
||||||
|
|
||||||
|
6
gcode.h
6
gcode.h
@ -23,12 +23,6 @@
|
|||||||
#define gcode_h
|
#define gcode_h
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
|
|
||||||
#define GCSTATUS_OK 0
|
|
||||||
#define GCSTATUS_BAD_NUMBER_FORMAT 1
|
|
||||||
#define GCSTATUS_EXPECTED_COMMAND_LETTER 2
|
|
||||||
#define GCSTATUS_UNSUPPORTED_STATEMENT 3
|
|
||||||
#define GCSTATUS_FLOATING_POINT_ERROR 4
|
|
||||||
|
|
||||||
// Initialize the parser
|
// Initialize the parser
|
||||||
void gc_init();
|
void gc_init();
|
||||||
|
|
||||||
|
18
nuts_bolts.c
Normal file
18
nuts_bolts.c
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include "nuts_bolts.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int read_double(char *line, uint8_t *char_counter, double *double_ptr)
|
||||||
|
{
|
||||||
|
char *start = line + *char_counter;
|
||||||
|
char *end;
|
||||||
|
|
||||||
|
*double_ptr = strtod(start, &end);
|
||||||
|
if(end == start) {
|
||||||
|
return(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
*char_counter = end - line;
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
@ -21,6 +21,7 @@
|
|||||||
#ifndef nuts_bolts_h
|
#ifndef nuts_bolts_h
|
||||||
#define nuts_bolts_h
|
#define nuts_bolts_h
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
@ -32,4 +33,6 @@
|
|||||||
#define clear_vector(a) memset(a, 0, sizeof(a))
|
#define clear_vector(a) memset(a, 0, sizeof(a))
|
||||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
int read_double(char *line, uint8_t *char_counter, double *double_ptr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
37
protocol.c
37
protocol.c
@ -33,22 +33,24 @@ static char line[LINE_BUFFER_SIZE];
|
|||||||
static uint8_t char_counter;
|
static uint8_t char_counter;
|
||||||
|
|
||||||
void status_message(int status_code) {
|
void status_message(int status_code) {
|
||||||
switch(status_code) {
|
if (status_code == 0) {
|
||||||
case GCSTATUS_OK:
|
printPgmString(PSTR("ok\n\r"));
|
||||||
printPgmString(PSTR("ok\n\r")); break;
|
} else {
|
||||||
case GCSTATUS_BAD_NUMBER_FORMAT:
|
|
||||||
printPgmString(PSTR("error: Bad number format\n\r")); break;
|
|
||||||
case GCSTATUS_EXPECTED_COMMAND_LETTER:
|
|
||||||
printPgmString(PSTR("error: Expected command letter\n\r")); break;
|
|
||||||
case GCSTATUS_UNSUPPORTED_STATEMENT:
|
|
||||||
printPgmString(PSTR("error: Unsupported statement\n\r")); break;
|
|
||||||
case GCSTATUS_FLOATING_POINT_ERROR:
|
|
||||||
printPgmString(PSTR("error: Floating point error\n\r")); break;
|
|
||||||
default:
|
|
||||||
printPgmString(PSTR("error: "));
|
printPgmString(PSTR("error: "));
|
||||||
|
switch(status_code) {
|
||||||
|
case STATUS_BAD_NUMBER_FORMAT:
|
||||||
|
printPgmString(PSTR("Bad number format\n\r")); break;
|
||||||
|
case STATUS_EXPECTED_COMMAND_LETTER:
|
||||||
|
printPgmString(PSTR("Expected command letter\n\r")); break;
|
||||||
|
case STATUS_UNSUPPORTED_STATEMENT:
|
||||||
|
printPgmString(PSTR("Unsupported statement\n\r")); break;
|
||||||
|
case STATUS_FLOATING_POINT_ERROR:
|
||||||
|
printPgmString(PSTR("Floating point error\n\r")); break;
|
||||||
|
default:
|
||||||
printInteger(status_code);
|
printInteger(status_code);
|
||||||
printPgmString(PSTR("\n\r"));
|
printPgmString(PSTR("\n\r"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void protocol_init()
|
void protocol_init()
|
||||||
@ -58,6 +60,15 @@ void protocol_init()
|
|||||||
printPgmString(PSTR("\r\n"));
|
printPgmString(PSTR("\r\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Executes one line of input according to protocol
|
||||||
|
uint8_t protocol_execute_line(char *line) {
|
||||||
|
if(line[0] == '$') {
|
||||||
|
return(settings_execute_line(line)); // Delegate lines starting with '$' to the settings module
|
||||||
|
} else {
|
||||||
|
return(gc_execute_line(line)); // Everything else is gcode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void protocol_process()
|
void protocol_process()
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
@ -65,7 +76,7 @@ void protocol_process()
|
|||||||
{
|
{
|
||||||
if((char_counter > 0) && ((c == '\n') || (c == '\r'))) { // Line is complete. Then execute!
|
if((char_counter > 0) && ((c == '\n') || (c == '\r'))) { // Line is complete. Then execute!
|
||||||
line[char_counter] = 0; // treminate string
|
line[char_counter] = 0; // treminate string
|
||||||
status_message(gc_execute_line(line));
|
status_message(protocol_execute_line(line));
|
||||||
char_counter = 0; // reset line buffer index
|
char_counter = 0; // reset line buffer index
|
||||||
} else if (c <= ' ') { // Throw away whitepace and control characters
|
} else if (c <= ' ') { // Throw away whitepace and control characters
|
||||||
} else if (c >= 'a' && c <= 'z') { // Upcase lowercase
|
} else if (c >= 'a' && c <= 'z') { // Upcase lowercase
|
||||||
|
@ -20,6 +20,12 @@
|
|||||||
#ifndef serial_h
|
#ifndef serial_h
|
||||||
#define serial_h
|
#define serial_h
|
||||||
|
|
||||||
|
#define STATUS_OK 0
|
||||||
|
#define STATUS_BAD_NUMBER_FORMAT 1
|
||||||
|
#define STATUS_EXPECTED_COMMAND_LETTER 2
|
||||||
|
#define STATUS_UNSUPPORTED_STATEMENT 3
|
||||||
|
#define STATUS_FLOATING_POINT_ERROR 4
|
||||||
|
|
||||||
// Initialize the serial protocol
|
// Initialize the serial protocol
|
||||||
void protocol_init();
|
void protocol_init();
|
||||||
|
|
||||||
@ -27,4 +33,7 @@ void protocol_init();
|
|||||||
// come in. Blocks until the serial buffer is emptied.
|
// come in. Blocks until the serial buffer is emptied.
|
||||||
void protocol_process();
|
void protocol_process();
|
||||||
|
|
||||||
|
// Executes one line of input according to protocol
|
||||||
|
uint8_t protocol_execute_line(char *line);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
23
settings.c
23
settings.c
@ -25,6 +25,7 @@
|
|||||||
#include "eeprom.h"
|
#include "eeprom.h"
|
||||||
#include "wiring_serial.h"
|
#include "wiring_serial.h"
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
|
#include "protocol.h"
|
||||||
|
|
||||||
settings_t settings;
|
settings_t settings;
|
||||||
|
|
||||||
@ -81,6 +82,28 @@ void settings_dump() {
|
|||||||
printPgmString(PSTR("\r\n'$x=value' to set parameter or just '$' to dump current settings\r\n"));
|
printPgmString(PSTR("\r\n'$x=value' to set parameter or just '$' to dump current settings\r\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parameter lines are on the form '$4=374.3' or '$' to dump current settings
|
||||||
|
uint8_t settings_execute_line(char *line) {
|
||||||
|
uint8_t char_counter = 1;
|
||||||
|
double parameter, value;
|
||||||
|
if(line[0] != '$') {
|
||||||
|
return(STATUS_UNSUPPORTED_STATEMENT);
|
||||||
|
}
|
||||||
|
if(line[char_counter] == 0) {
|
||||||
|
settings_dump(); return(STATUS_OK);
|
||||||
|
}
|
||||||
|
read_double(line, &char_counter, ¶meter);
|
||||||
|
if(line[char_counter++] != '=') {
|
||||||
|
return(STATUS_UNSUPPORTED_STATEMENT);
|
||||||
|
}
|
||||||
|
read_double(line, &char_counter, &value);
|
||||||
|
if(line[char_counter] != 0) {
|
||||||
|
return(STATUS_UNSUPPORTED_STATEMENT);
|
||||||
|
}
|
||||||
|
settings_store_setting(parameter, value);
|
||||||
|
return(STATUS_OK);
|
||||||
|
}
|
||||||
|
|
||||||
void write_settings() {
|
void write_settings() {
|
||||||
eeprom_put_char(0, SETTINGS_VERSION);
|
eeprom_put_char(0, SETTINGS_VERSION);
|
||||||
memcpy_to_eeprom_with_checksum(1, (char*)&settings, sizeof(settings_t));
|
memcpy_to_eeprom_with_checksum(1, (char*)&settings, sizeof(settings_t));
|
||||||
|
@ -51,6 +51,9 @@ void settings_init();
|
|||||||
// Print current settings
|
// Print current settings
|
||||||
void settings_dump();
|
void settings_dump();
|
||||||
|
|
||||||
|
// Handle settings command
|
||||||
|
uint8_t settings_execute_line(char *line);
|
||||||
|
|
||||||
// A helper method to set new settings from command line
|
// A helper method to set new settings from command line
|
||||||
void settings_store_setting(int parameter, double value);
|
void settings_store_setting(int parameter, double value);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user