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:
Michael Moon 2011-04-30 00:50:43 +10:00 committed by Markus Hitter
parent 8f2e1e59ac
commit 983bcfdd46
5 changed files with 71 additions and 3 deletions

View File

@ -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 */
}
/***************************************************************************\

View File

@ -4,6 +4,7 @@
#include <stdint.h>
#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

View File

@ -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:

19
sd.c
View File

@ -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 */

2
sd.h
View File

@ -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 */