SD card: initial shoehorning of SD code, part 2.
Part 2 is to implement M23: select file. That's more than just a few lines, as we also have to teach the gcode-parser to collect strings. For now the file is simply tested for successful opening, no actual printing, yet. About build size: during development there was another implementation, which didn't abstract SD card functions into sd.c/.h, but put them into gcode_process.c directly. At the feature completeness of this commit, the other implementation used 70 bytes flash less, but also 23 bytes more RAM. So I decided for the more abstracted/encapsulated version. --Traumflug Also, this adds 14 bytes binary size even without SD card support. A lot more #ifdefs around each use of next_target.read_string would remove this, but after all we do care a bit about readability of the source code, so let's sacrify these 14 bytes to it. --Traumflug
This commit is contained in:
parent
8f2e1e59ac
commit
983bcfdd46
|
|
@ -18,6 +18,7 @@
|
||||||
#include "simulator.h"
|
#include "simulator.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/// current or previous gcode word
|
/// current or previous gcode word
|
||||||
/// for working out what to do with data just received
|
/// for working out what to do with data just received
|
||||||
uint8_t last_field = 0;
|
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
|
/// 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;
|
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:
|
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;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
next_target.M = read_digit.mantissa;
|
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))
|
if (DEBUG_ECHO && (debug_flags & DEBUG_ECHO))
|
||||||
serwrite_uint8(next_target.M);
|
serwrite_uint8(next_target.M);
|
||||||
break;
|
break;
|
||||||
|
|
@ -202,8 +216,11 @@ void gcode_parse_char(uint8_t c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip comments
|
// Skip comments and strings.
|
||||||
if (next_target.seen_semi_comment == 0 && next_target.seen_parens_comment == 0) {
|
if (next_target.seen_semi_comment == 0 &&
|
||||||
|
next_target.seen_parens_comment == 0 &&
|
||||||
|
next_target.read_string == 0
|
||||||
|
) {
|
||||||
// new field?
|
// new field?
|
||||||
if ((c >= 'A' && c <= 'Z') || c == '*') {
|
if ((c >= 'A' && c <= 'Z') || c == '*') {
|
||||||
last_field = 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_P = next_target.seen_T = next_target.seen_N = \
|
||||||
next_target.seen_G = next_target.seen_M = next_target.seen_checksum = \
|
next_target.seen_G = next_target.seen_M = next_target.seen_checksum = \
|
||||||
next_target.seen_semi_comment = next_target.seen_parens_comment = \
|
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
|
// last_field and read_digit are reset above already
|
||||||
|
|
||||||
if (next_target.option_all_relative) {
|
if (next_target.option_all_relative) {
|
||||||
|
|
@ -381,6 +399,20 @@ void gcode_parse_char(uint8_t c) {
|
||||||
next_target.target.axis[E] = 0;
|
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 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
/***************************************************************************\
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "dda.h"
|
#include "dda.h"
|
||||||
|
#include "sd.h"
|
||||||
|
|
||||||
// wether to insist on N line numbers
|
// wether to insist on N line numbers
|
||||||
// if not defined, N's are completely ignored
|
// 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_checksum :1; ///< seen a checksum?
|
||||||
uint8_t seen_semi_comment :1; ///< seen a semicolon?
|
uint8_t seen_semi_comment :1; ///< seen a semicolon?
|
||||||
uint8_t seen_parens_comment :1; ///< seen an open parenthesis
|
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_all_relative :1; ///< relative or absolute coordinates?
|
||||||
uint8_t option_e_relative :1; ///< same for e axis (M82/M83)
|
uint8_t option_e_relative :1; ///< same for e axis (M82/M83)
|
||||||
uint8_t option_inches :1; ///< inches or millimeters?
|
uint8_t option_inches :1; ///< inches or millimeters?
|
||||||
|
|
@ -62,6 +64,11 @@ typedef struct {
|
||||||
/// the command being processed
|
/// the command being processed
|
||||||
extern GCODE_COMMAND next_target;
|
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);
|
void gcode_init(void);
|
||||||
|
|
||||||
/// accept the next character and process it
|
/// accept the next character and process it
|
||||||
|
|
|
||||||
|
|
@ -398,6 +398,14 @@ void process_gcode_command() {
|
||||||
//? inserted.
|
//? inserted.
|
||||||
sd_unmount();
|
sd_unmount();
|
||||||
break;
|
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 */
|
#endif /* SD */
|
||||||
|
|
||||||
case 82:
|
case 82:
|
||||||
|
|
|
||||||
19
sd.c
19
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 */
|
#endif /* SD */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue