diff --git a/gcode_parse.c b/gcode_parse.c index 6a1e771..bb5ca6e 100644 --- a/gcode_parse.c +++ b/gcode_parse.c @@ -18,6 +18,7 @@ #include "simulator.h" #endif + /// current or previous gcode word /// for working out what to do with data just received uint8_t last_field = 0; @@ -31,6 +32,12 @@ decfloat BSS read_digit; /// this is where we store all the data for the current command before we work out what to do with it GCODE_COMMAND BSS next_target; +#ifdef SD + #define STR_BUF_LEN 13 + char gcode_str_buf[STR_BUF_LEN]; + static uint8_t str_buf_ptr = 0; +#endif + /* decfloat_to_int() is the weakest subject to variable overflow. For evaluation, we assume a build room of +-1000 mm and STEPS_PER_MM_x between 1.000 and 4096. Accordingly for metric units: @@ -117,6 +124,13 @@ void gcode_parse_char(uint8_t c) { break; case 'M': next_target.M = read_digit.mantissa; + #ifdef SD + if (next_target.M == 23) { + // SD card command with a filename. + next_target.read_string = 1; // Reset by string handler or EOL. + str_buf_ptr = 0; + } + #endif if (DEBUG_ECHO && (debug_flags & DEBUG_ECHO)) serwrite_uint8(next_target.M); break; @@ -202,8 +216,11 @@ void gcode_parse_char(uint8_t c) { } } - // skip comments - if (next_target.seen_semi_comment == 0 && next_target.seen_parens_comment == 0) { + // Skip comments and strings. + if (next_target.seen_semi_comment == 0 && + next_target.seen_parens_comment == 0 && + next_target.read_string == 0 + ) { // new field? if ((c >= 'A' && c <= 'Z') || c == '*') { last_field = c; @@ -371,7 +388,8 @@ void gcode_parse_char(uint8_t c) { next_target.seen_P = next_target.seen_T = next_target.seen_N = \ next_target.seen_G = next_target.seen_M = next_target.seen_checksum = \ next_target.seen_semi_comment = next_target.seen_parens_comment = \ - next_target.checksum_read = next_target.checksum_calculated = 0; + next_target.read_string = next_target.checksum_read = \ + next_target.checksum_calculated = 0; // last_field and read_digit are reset above already if (next_target.option_all_relative) { @@ -381,6 +399,20 @@ void gcode_parse_char(uint8_t c) { next_target.target.axis[E] = 0; } } + + #ifdef SD + // Handle string reading. After checking for EOL. + if (next_target.read_string) { + if (c == ' ' || c == '*') { + next_target.read_string = 0; + } + else if (str_buf_ptr < STR_BUF_LEN) { + gcode_str_buf[str_buf_ptr] = c; + str_buf_ptr++; + gcode_str_buf[str_buf_ptr] = '\0'; + } + } + #endif /* SD */ } /***************************************************************************\ diff --git a/gcode_parse.h b/gcode_parse.h index d15716d..5b19b90 100644 --- a/gcode_parse.h +++ b/gcode_parse.h @@ -4,6 +4,7 @@ #include #include "dda.h" +#include "sd.h" // wether to insist on N line numbers // if not defined, N's are completely ignored @@ -38,6 +39,7 @@ typedef struct { uint8_t seen_checksum :1; ///< seen a checksum? uint8_t seen_semi_comment :1; ///< seen a semicolon? uint8_t seen_parens_comment :1; ///< seen an open parenthesis + uint8_t read_string :1; ///< Currently reading a string. uint8_t option_all_relative :1; ///< relative or absolute coordinates? uint8_t option_e_relative :1; ///< same for e axis (M82/M83) uint8_t option_inches :1; ///< inches or millimeters? @@ -62,6 +64,11 @@ typedef struct { /// the command being processed extern GCODE_COMMAND next_target; +#ifdef SD + /// For storing incoming strings. Currently the only use is SD card filename. + extern char gcode_str_buf[]; +#endif + void gcode_init(void); /// accept the next character and process it diff --git a/gcode_process.c b/gcode_process.c index 3a29400..25910cf 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -398,6 +398,14 @@ void process_gcode_command() { //? inserted. sd_unmount(); break; + + case 23: + //? --- M23: select file. --- + //? + //? This opens a file for reading. This file is valid up to M22 or up + //? to the next M23. + sd_open(gcode_str_buf); + break; #endif /* SD */ case 82: diff --git a/sd.c b/sd.c index 9339a30..6fe93d1 100644 --- a/sd.c +++ b/sd.c @@ -69,4 +69,23 @@ void sd_list(const char* path) { } } +/** Open a file for reading. + + \param filename Name of the file to open and to read G-code from. + + Before too long this will cause the printer to read G-code from this file + until done or until stopped by G-code coming in over the serial line. +*/ +void sd_open(const char* filename) { + result = pf_open(filename); + if (result == FR_OK) { + // To demonstrate this works, open the file and show its size. + // Actually, the file name isn't stored, so we can't read it back :-) + sersendf_P(PSTR("Successfully opened file with %lu bytes."), sdfile.fsize); + } + else { + sersendf_P(PSTR("E: failed to open file. (%su)"), result); + } +} + #endif /* SD */ diff --git a/sd.h b/sd.h index df4a39b..7252add 100644 --- a/sd.h +++ b/sd.h @@ -23,6 +23,8 @@ void sd_unmount(void); void sd_list(const char* path); +void sd_open(const char* filename); + #endif /* SD_CARD_SELECT_PIN */ #endif /* _SD_H */