Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

M808 Repeat Markers #20084

Merged
merged 1 commit into from
Nov 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,8 @@
//#define SD_IGNORE_AT_STARTUP // Don't mount the SD card when starting up
//#define SDCARD_READONLY // Read-only SD card (to save over 2K of flash)

//#define GCODE_REPEAT_MARKERS // Enable G-code M808 to set repeat markers and do looping

#define SD_PROCEDURE_DEPTH 1 // Increase if you need more nested M32 calls

#define SD_FINISHED_STEPPERRELEASE true // Disable steppers when SD Print is finished
Expand Down
5 changes: 5 additions & 0 deletions Marlin/src/MarlinCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@
#include "feature/pause.h"
#endif

#if ENABLED(GCODE_REPEAT_MARKERS)
#include "feature/repeat.h"
#endif

#if ENABLED(POWER_LOSS_RECOVERY)
#include "feature/powerloss.h"
#endif
Expand Down Expand Up @@ -435,6 +439,7 @@ bool printingIsPaused() {

void startOrResumeJob() {
if (!printingIsPaused()) {
TERN_(GCODE_REPEAT_MARKERS, repeat.reset());
TERN_(CANCEL_OBJECTS, cancelable.reset());
TERN_(LCD_SHOW_E_TOTAL, e_move_accumulator = 0);
#if BOTH(LCD_SET_PROGRESS_MANUALLY, USE_M73_REMAINING_TIME)
Expand Down
3 changes: 3 additions & 0 deletions Marlin/src/feature/powerloss.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=0*/
info.current_position = current_position;
info.feedrate = uint16_t(feedrate_mm_s * 60.0f);
info.zraise = zraise;

TERN_(GCODE_REPEAT_MARKERS, info.stored_repeat = repeat);
TERN_(HAS_HOME_OFFSET, info.home_offset = home_offset);
TERN_(HAS_POSITION_SHIFT, info.position_shift = position_shift);

Expand Down Expand Up @@ -507,6 +509,7 @@ void PrintJobRecovery::resume() {
sprintf_P(cmd, PSTR("G92.9 E%s"), dtostrf(info.current_position.e, 1, 3, str_1));
gcode.process_subcommands_now(cmd);

TERN_(GCODE_REPEAT_MARKERS, repeat = info.stored_repeat);
TERN_(HAS_HOME_OFFSET, home_offset = info.home_offset);
TERN_(HAS_POSITION_SHIFT, position_shift = info.position_shift);
#if HAS_HOME_OFFSET || HAS_POSITION_SHIFT
Expand Down
6 changes: 6 additions & 0 deletions Marlin/src/feature/powerloss.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@

#include "../inc/MarlinConfig.h"

#if ENABLED(GCODE_REPEAT_MARKERS)
#include "../feature/repeat.h"
#endif

#if ENABLED(MIXING_EXTRUDER)
#include "../feature/mixing.h"
#endif
Expand All @@ -50,6 +54,8 @@ typedef struct {
uint16_t feedrate;
float zraise;

// Repeat information
TERN_(GCODE_REPEAT_MARKERS, Repeat stored_repeat);

TERN_(HAS_HOME_OFFSET, xyz_pos_t home_offset);
TERN_(HAS_POSITION_SHIFT, xyz_pos_t position_shift);
Expand Down
81 changes: 81 additions & 0 deletions Marlin/src/feature/repeat.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../inc/MarlinConfig.h"

#if ENABLED(GCODE_REPEAT_MARKERS)

//#define DEBUG_GCODE_REPEAT_MARKERS

#include "repeat.h"

#include "../gcode/gcode.h"
#include "../sd/cardreader.h"

#define DEBUG_OUT ENABLED(DEBUG_GCODE_REPEAT_MARKERS)
#include "../core/debug_out.h"

repeat_marker_t Repeat::marker[MAX_REPEAT_NESTING];
uint8_t Repeat::index;

void Repeat::add_marker(const uint32_t sdpos, const uint16_t count) {
if (index >= MAX_REPEAT_NESTING)
SERIAL_ECHO_MSG("!Too many markers.");
else {
marker[index].sdpos = sdpos;
marker[index].counter = count ?: -1;
index++;
DEBUG_ECHOLNPAIR("Add Marker ", int(index), " at ", sdpos, " (", count, ")");
}
}

void Repeat::loop() {
if (!index) // No marker?
SERIAL_ECHO_MSG("!No marker set."); // Inform the user.
else {
const uint8_t ind = index - 1; // Active marker's index
if (!marker[ind].counter) { // Did its counter run out?
DEBUG_ECHOLNPAIR("Pass Marker ", int(index));
index--; // Carry on. Previous marker on the next 'M808'.
}
else {
card.setIndex(marker[ind].sdpos); // Loop back to the marker.
if (marker[ind].counter > 0) // Ignore a negative (or zero) counter.
--marker[ind].counter; // Decrement the counter. If zero this 'M808' will be skipped next time.
DEBUG_ECHOLNPAIR("Goto Marker ", int(index), " at ", marker[ind].sdpos, " (", marker[ind].counter, ")");
}
}
}

void Repeat::cancel() { LOOP_L_N(i, index) marker[i].counter = 0; }

void Repeat::early_parse_M808(char * const cmd) {
if (is_command_M808(cmd)) {
DEBUG_ECHOLNPAIR("Parsing \"", cmd, "\"");
parser.parse(cmd);
if (parser.seen('L'))
add_marker(card.getIndex(), parser.value_ushort());
else
Repeat::loop();
}
}

#endif // GCODE_REPEAT_MARKERS
49 changes: 49 additions & 0 deletions Marlin/src/feature/repeat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once

#include "../inc/MarlinConfigPre.h"
#include "../gcode/parser.h"

#include <stdint.h>

#define MAX_REPEAT_NESTING 10

typedef struct {
uint32_t sdpos; // The repeat file position
int16_t counter; // The counter for looping
} repeat_marker_t;

class Repeat {
private:
static repeat_marker_t marker[MAX_REPEAT_NESTING];
static uint8_t index;
public:
static inline void reset() { index = 0; }
static bool is_command_M808(char * const cmd) { return cmd[0] == 'M' && cmd[1] == '8' && cmd[2] == '0' && cmd[3] == '8' && !NUMERIC(cmd[4]); }
static void early_parse_M808(char * const cmd);
static void add_marker(const uint32_t sdpos, const uint16_t count);
static void loop();
static void cancel();
};

extern Repeat repeat;
4 changes: 4 additions & 0 deletions Marlin/src/gcode/gcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 800: parser.debug(); break; // M800: GCode Parser Test for M
#endif

#if ENABLED(GCODE_REPEAT_MARKERS)
case 808: M808(); break; // M808: Set / Goto repeat markers
#endif

#if ENABLED(I2C_POSITION_ENCODERS)
case 860: M860(); break; // M860: Report encoder module position
case 861: M861(); break; // M861: Report encoder module status
Expand Down
3 changes: 3 additions & 0 deletions Marlin/src/gcode/gcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@
* M672 - Set/Reset Duet Smart Effector's sensitivity. (Requires DUET_SMART_EFFECTOR and SMART_EFFECTOR_MOD_PIN)
* M701 - Load filament (Requires FILAMENT_LOAD_UNLOAD_GCODES)
* M702 - Unload filament (Requires FILAMENT_LOAD_UNLOAD_GCODES)
* M808 - Set or Goto a Repeat Marker (Requires GCODE_REPEAT_MARKERS)
* M810-M819 - Define/execute a G-code macro (Requires GCODE_MACROS)
* M851 - Set Z probe's XYZ offsets in current units. (Negative values: X=left, Y=front, Z=below)
* M852 - Set skew factors: "M852 [I<xy>] [J<xz>] [K<yz>]". (Requires SKEW_CORRECTION_GCODE, and SKEW_CORRECTION_FOR_Z for IJ)
Expand Down Expand Up @@ -807,6 +808,8 @@ class GcodeSuite {
static void M702();
#endif

TERN_(GCODE_REPEAT_MARKERS, static void M808());

TERN_(GCODE_MACROS, static void M810_819());

TERN_(HAS_BED_PROBE, static void M851());
Expand Down
3 changes: 3 additions & 0 deletions Marlin/src/gcode/host/M115.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ void GcodeSuite::M115() {
// SDCARD (M20, M23, M24, etc.)
cap_line(PSTR("SDCARD"), ENABLED(SDSUPPORT));

// REPEAT (M808)
cap_line(PSTR("REPEAT"), ENABLED(GCODE_REPEAT_MARKERS));

// AUTOREPORT_SD_STATUS (M27 extension)
cap_line(PSTR("AUTOREPORT_SD_STATUS"), ENABLED(AUTO_REPORT_SD_STATUS));

Expand Down
23 changes: 15 additions & 8 deletions Marlin/src/gcode/queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ GCodeQueue queue;
#include "../feature/powerloss.h"
#endif

#if ENABLED(GCODE_REPEAT_MARKERS)
#include "../feature/repeat.h"
#endif

/**
* GCode line number handling. Hosts may opt to include line numbers when
* sending commands to Marlin, and lines will be checked for sequentiality.
Expand Down Expand Up @@ -578,10 +582,9 @@ void GCodeQueue::get_serial_commands() {
if (!IS_SD_PRINTING()) return;

int sd_count = 0;
bool card_eof = card.eof();
while (length < BUFSIZE && !card_eof) {
while (length < BUFSIZE && !card.eof()) {
const int16_t n = card.get();
card_eof = card.eof();
const bool card_eof = card.eof();
if (n < 0 && !card_eof) { SERIAL_ERROR_MSG(STR_SD_ERR_READ); continue; }

const char sd_char = (char)n;
Expand All @@ -591,17 +594,21 @@ void GCodeQueue::get_serial_commands() {
// Reset stream state, terminate the buffer, and commit a non-empty command
if (!is_eol && sd_count) ++sd_count; // End of file with no newline
if (!process_line_done(sd_input_state, command_buffer[index_w], sd_count)) {

// M808 S saves the sdpos of the next line. M808 loops to a new sdpos.
TERN_(GCODE_REPEAT_MARKERS, repeat.early_parse_M808(command_buffer[index_w]));

// Put the new command into the buffer (no "ok" sent)
_commit_command(false);
#if ENABLED(POWER_LOSS_RECOVERY)
recovery.cmd_sdpos = card.getIndex(); // Prime for the NEXT _commit_command
#endif

// Prime Power-Loss Recovery for the NEXT _commit_command
TERN_(POWER_LOSS_RECOVERY, recovery.cmd_sdpos = card.getIndex());
}

if (card_eof) card.fileHasFinished(); // Handle end of file reached
if (card.eof()) card.fileHasFinished(); // Handle end of file reached
}
else
process_stream_char(sd_char, sd_input_state, command_buffer[index_w], sd_count);

}
}

Expand Down
51 changes: 51 additions & 0 deletions Marlin/src/gcode/sd/M808.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

#include "../../inc/MarlinConfig.h"

#if ENABLED(GCODE_REPEAT_MARKERS)

#include "../gcode.h"
#include "../../feature/repeat.h"

/**
* M808: Set / Goto a repeat marker
*
* L<count> - Set a repeat marker with 'count' repetitions. If omitted, infinity.
*
* Examples:
*
* M808 L ; Set a loop marker with a count of infinity
thinkyhead marked this conversation as resolved.
Show resolved Hide resolved
* M808 L2 ; Set a loop marker with a count of 2
* M808 ; Decrement and loop if not zero.
*/
void GcodeSuite::M808() {

// Handled early and ignored here in the queue.
// Allowed to go into the queue for logging purposes.

// M808 K sent from the host to cancel all loops
if (parser.seen('K')) repeat.cancel();

}

#endif // GCODE_REPEAT_MARKERS
3 changes: 1 addition & 2 deletions Marlin/src/sd/cardreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -699,8 +699,7 @@ void CardReader::removeFile(const char * const name) {

void CardReader::report_status() {
if (isPrinting()) {
SERIAL_ECHOPGM(STR_SD_PRINTING_BYTE);
SERIAL_ECHO(sdpos);
SERIAL_ECHOPAIR(STR_SD_PRINTING_BYTE, sdpos);
SERIAL_CHAR('/');
SERIAL_ECHOLN(filesize);
}
Expand Down
7 changes: 4 additions & 3 deletions Marlin/src/sd/cardreader.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,9 @@ class CardReader {
static inline uint32_t getIndex() { return sdpos; }
static inline uint32_t getFileSize() { return filesize; }
static inline bool eof() { return sdpos >= filesize; }
static inline void setIndex(const uint32_t index) { sdpos = index; file.seekSet(index); }
static inline void setIndex(const uint32_t index) { file.seekSet((sdpos = index)); }
static inline char* getWorkDirName() { workDir.getDosName(filename); return filename; }
static inline int16_t get() { sdpos = file.curPosition(); return (int16_t)file.read(); }
static inline int16_t get() { int16_t out = (int16_t)file.read(); sdpos = file.curPosition(); return out; }
static inline int16_t read(void* buf, uint16_t nbyte) { return file.isOpen() ? file.read(buf, nbyte) : -1; }
static inline int16_t write(void* buf, uint16_t nbyte) { return file.isOpen() ? file.write(buf, nbyte) : -1; }

Expand Down Expand Up @@ -244,7 +244,8 @@ class CardReader {
static SdVolume volume;
static SdFile file;

static uint32_t filesize, sdpos;
static uint32_t filesize, // Total size of the current file, in bytes
sdpos; // Index most recently read (one behind file.getPos)

//
// Procedure calls to other files
Expand Down
16 changes: 16 additions & 0 deletions buildroot/test-gcode/M808-loops.gcode
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
;
; M808 Repeat Marker Test
;

M808 L3 ; Marker at 54

M118 Outer Loop
M300 S220 P100

M808 L5 ; Marker at 111

M118 Inner Loop
M300 S110 P100

M808
M808
2 changes: 1 addition & 1 deletion buildroot/tests/mega2560-tests
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ restore_configs
opt_set MOTHERBOARD BOARD_MEGACONTROLLER
opt_set LCD_LANGUAGE de
opt_enable EEPROM_SETTINGS EEPROM_CHITCHAT \
MINIPANEL SDSUPPORT PCA9632 LCD_INFO_MENU SOUND_MENU_ITEM \
MINIPANEL SDSUPPORT PCA9632 LCD_INFO_MENU SOUND_MENU_ITEM GCODE_REPEAT_MARKERS \
AUTO_BED_LEVELING_BILINEAR PROBE_MANUALLY LCD_BED_LEVELING G26_MESH_VALIDATION MESH_EDIT_MENU \
LIN_ADVANCE EXTRA_LIN_ADVANCE_K \
INCH_MODE_SUPPORT TEMPERATURE_UNITS_SUPPORT EXPERIMENTAL_I2CBUS M100_FREE_MEMORY_WATCHER \
Expand Down
Loading