Scott Lahteine 4 лет назад
Родитель
Сommit
b6a32500c4

+ 2 - 0
Marlin/Configuration_adv.h

@@ -1186,6 +1186,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

+ 5 - 0
Marlin/src/MarlinCore.cpp

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

+ 3 - 0
Marlin/src/feature/powerloss.cpp

@@ -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);
 
@@ -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

+ 6 - 0
Marlin/src/feature/powerloss.h

@@ -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
@@ -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);

+ 81 - 0
Marlin/src/feature/repeat.cpp

@@ -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 - 0
Marlin/src/feature/repeat.h

@@ -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 - 0
Marlin/src/gcode/gcode.cpp

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

+ 3 - 0
Marlin/src/gcode/gcode.h

@@ -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)
@@ -807,6 +808,8 @@ private:
     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());

+ 3 - 0
Marlin/src/gcode/host/M115.cpp

@@ -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));
 

+ 15 - 8
Marlin/src/gcode/queue.cpp

@@ -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.
@@ -577,10 +581,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;
@@ -590,17 +593,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);
-
     }
   }
 

Некоторые файлы не были показаны из-за большого количества измененных файлов