Browse Source

M808 Repeat Markers (#20084)

Scott Lahteine 3 years ago
parent
commit
b6a32500c4
No account linked to committer's email address

+ 2
- 0
Marlin/Configuration_adv.h View File

@@ -1186,6 +1186,8 @@
1186 1186
   //#define SD_IGNORE_AT_STARTUP            // Don't mount the SD card when starting up
1187 1187
   //#define SDCARD_READONLY                 // Read-only SD card (to save over 2K of flash)
1188 1188
 
1189
+  //#define GCODE_REPEAT_MARKERS            // Enable G-code M808 to set repeat markers and do looping
1190
+
1189 1191
   #define SD_PROCEDURE_DEPTH 1              // Increase if you need more nested M32 calls
1190 1192
 
1191 1193
   #define SD_FINISHED_STEPPERRELEASE true   // Disable steppers when SD Print is finished

+ 5
- 0
Marlin/src/MarlinCore.cpp View File

@@ -173,6 +173,10 @@
173 173
   #include "feature/pause.h"
174 174
 #endif
175 175
 
176
+#if ENABLED(GCODE_REPEAT_MARKERS)
177
+  #include "feature/repeat.h"
178
+#endif
179
+
176 180
 #if ENABLED(POWER_LOSS_RECOVERY)
177 181
   #include "feature/powerloss.h"
178 182
 #endif
@@ -435,6 +439,7 @@ bool printingIsPaused() {
435 439
 
436 440
 void startOrResumeJob() {
437 441
   if (!printingIsPaused()) {
442
+    TERN_(GCODE_REPEAT_MARKERS, repeat.reset());
438 443
     TERN_(CANCEL_OBJECTS, cancelable.reset());
439 444
     TERN_(LCD_SHOW_E_TOTAL, e_move_accumulator = 0);
440 445
     #if BOTH(LCD_SET_PROGRESS_MANUALLY, USE_M73_REMAINING_TIME)

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

@@ -182,6 +182,8 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=0*/
182 182
     info.current_position = current_position;
183 183
     info.feedrate = uint16_t(feedrate_mm_s * 60.0f);
184 184
     info.zraise = zraise;
185
+
186
+    TERN_(GCODE_REPEAT_MARKERS, info.stored_repeat = repeat);
185 187
     TERN_(HAS_HOME_OFFSET, info.home_offset = home_offset);
186 188
     TERN_(HAS_POSITION_SHIFT, info.position_shift = position_shift);
187 189
 
@@ -507,6 +509,7 @@ void PrintJobRecovery::resume() {
507 509
   sprintf_P(cmd, PSTR("G92.9 E%s"), dtostrf(info.current_position.e, 1, 3, str_1));
508 510
   gcode.process_subcommands_now(cmd);
509 511
 
512
+  TERN_(GCODE_REPEAT_MARKERS, repeat = info.stored_repeat);
510 513
   TERN_(HAS_HOME_OFFSET, home_offset = info.home_offset);
511 514
   TERN_(HAS_POSITION_SHIFT, position_shift = info.position_shift);
512 515
   #if HAS_HOME_OFFSET || HAS_POSITION_SHIFT

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

@@ -30,6 +30,10 @@
30 30
 
31 31
 #include "../inc/MarlinConfig.h"
32 32
 
33
+#if ENABLED(GCODE_REPEAT_MARKERS)
34
+  #include "../feature/repeat.h"
35
+#endif
36
+
33 37
 #if ENABLED(MIXING_EXTRUDER)
34 38
   #include "../feature/mixing.h"
35 39
 #endif
@@ -50,6 +54,8 @@ typedef struct {
50 54
   uint16_t feedrate;
51 55
   float zraise;
52 56
 
57
+  // Repeat information
58
+  TERN_(GCODE_REPEAT_MARKERS, Repeat stored_repeat);
53 59
 
54 60
   TERN_(HAS_HOME_OFFSET,    xyz_pos_t home_offset);
55 61
   TERN_(HAS_POSITION_SHIFT, xyz_pos_t position_shift);

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

@@ -0,0 +1,81 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+#include "../inc/MarlinConfig.h"
23
+
24
+#if ENABLED(GCODE_REPEAT_MARKERS)
25
+
26
+//#define DEBUG_GCODE_REPEAT_MARKERS
27
+
28
+#include "repeat.h"
29
+
30
+#include "../gcode/gcode.h"
31
+#include "../sd/cardreader.h"
32
+
33
+#define DEBUG_OUT ENABLED(DEBUG_GCODE_REPEAT_MARKERS)
34
+#include "../core/debug_out.h"
35
+
36
+repeat_marker_t Repeat::marker[MAX_REPEAT_NESTING];
37
+uint8_t Repeat::index;
38
+
39
+void Repeat::add_marker(const uint32_t sdpos, const uint16_t count) {
40
+  if (index >= MAX_REPEAT_NESTING)
41
+    SERIAL_ECHO_MSG("!Too many markers.");
42
+  else {
43
+    marker[index].sdpos = sdpos;
44
+    marker[index].counter = count ?: -1;
45
+    index++;
46
+    DEBUG_ECHOLNPAIR("Add Marker ", int(index), " at ", sdpos, " (", count, ")");
47
+  }
48
+}
49
+
50
+void Repeat::loop() {
51
+  if (!index)                           // No marker?
52
+    SERIAL_ECHO_MSG("!No marker set."); //  Inform the user.
53
+  else {
54
+    const uint8_t ind = index - 1;      // Active marker's index
55
+    if (!marker[ind].counter) {         // Did its counter run out?
56
+      DEBUG_ECHOLNPAIR("Pass Marker ", int(index));
57
+      index--;                          //  Carry on. Previous marker on the next 'M808'.
58
+    }
59
+    else {
60
+      card.setIndex(marker[ind].sdpos); // Loop back to the marker.
61
+      if (marker[ind].counter > 0)      // Ignore a negative (or zero) counter.
62
+        --marker[ind].counter;          // Decrement the counter. If zero this 'M808' will be skipped next time.
63
+      DEBUG_ECHOLNPAIR("Goto Marker ", int(index), " at ", marker[ind].sdpos, " (", marker[ind].counter, ")");
64
+    }
65
+  }
66
+}
67
+
68
+void Repeat::cancel() { LOOP_L_N(i, index) marker[i].counter = 0; }
69
+
70
+void Repeat::early_parse_M808(char * const cmd) {
71
+  if (is_command_M808(cmd)) {
72
+    DEBUG_ECHOLNPAIR("Parsing \"", cmd, "\"");
73
+    parser.parse(cmd);
74
+    if (parser.seen('L'))
75
+      add_marker(card.getIndex(), parser.value_ushort());
76
+    else
77
+      Repeat::loop();
78
+  }
79
+}
80
+
81
+#endif // GCODE_REPEAT_MARKERS

+ 49
- 0
Marlin/src/feature/repeat.h View File

@@ -0,0 +1,49 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+#pragma once
23
+
24
+#include "../inc/MarlinConfigPre.h"
25
+#include "../gcode/parser.h"
26
+
27
+#include <stdint.h>
28
+
29
+#define MAX_REPEAT_NESTING 10
30
+
31
+typedef struct {
32
+  uint32_t sdpos;   // The repeat file position
33
+  int16_t counter;  // The counter for looping
34
+} repeat_marker_t;
35
+
36
+class Repeat {
37
+private:
38
+  static repeat_marker_t marker[MAX_REPEAT_NESTING];
39
+  static uint8_t index;
40
+public:
41
+  static inline void reset() { index = 0; }
42
+  static bool is_command_M808(char * const cmd) { return cmd[0] == 'M' && cmd[1] == '8' && cmd[2] == '0' && cmd[3] == '8' && !NUMERIC(cmd[4]); }
43
+  static void early_parse_M808(char * const cmd);
44
+  static void add_marker(const uint32_t sdpos, const uint16_t count);
45
+  static void loop();
46
+  static void cancel();
47
+};
48
+
49
+extern Repeat repeat;

+ 4
- 0
Marlin/src/gcode/gcode.cpp View File

@@ -882,6 +882,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
882 882
         case 800: parser.debug(); break;                          // M800: GCode Parser Test for M
883 883
       #endif
884 884
 
885
+      #if ENABLED(GCODE_REPEAT_MARKERS)
886
+        case 808: M808(); break;                                  // M808: Set / Goto repeat markers
887
+      #endif
888
+
885 889
       #if ENABLED(I2C_POSITION_ENCODERS)
886 890
         case 860: M860(); break;                                  // M860: Report encoder module position
887 891
         case 861: M861(); break;                                  // M861: Report encoder module status

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

@@ -242,6 +242,7 @@
242 242
  * M672 - Set/Reset Duet Smart Effector's sensitivity. (Requires DUET_SMART_EFFECTOR and SMART_EFFECTOR_MOD_PIN)
243 243
  * M701 - Load filament (Requires FILAMENT_LOAD_UNLOAD_GCODES)
244 244
  * M702 - Unload filament (Requires FILAMENT_LOAD_UNLOAD_GCODES)
245
+ * M808 - Set or Goto a Repeat Marker (Requires GCODE_REPEAT_MARKERS)
245 246
  * M810-M819 - Define/execute a G-code macro (Requires GCODE_MACROS)
246 247
  * M851 - Set Z probe's XYZ offsets in current units. (Negative values: X=left, Y=front, Z=below)
247 248
  * 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:
807 808
     static void M702();
808 809
   #endif
809 810
 
811
+  TERN_(GCODE_REPEAT_MARKERS, static void M808());
812
+
810 813
   TERN_(GCODE_MACROS, static void M810_819());
811 814
 
812 815
   TERN_(HAS_BED_PROBE, static void M851());

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

@@ -117,6 +117,9 @@ void GcodeSuite::M115() {
117 117
     // SDCARD (M20, M23, M24, etc.)
118 118
     cap_line(PSTR("SDCARD"), ENABLED(SDSUPPORT));
119 119
 
120
+    // REPEAT (M808)
121
+    cap_line(PSTR("REPEAT"), ENABLED(GCODE_REPEAT_MARKERS));
122
+
120 123
     // AUTOREPORT_SD_STATUS (M27 extension)
121 124
     cap_line(PSTR("AUTOREPORT_SD_STATUS"), ENABLED(AUTO_REPORT_SD_STATUS));
122 125
 

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

@@ -51,6 +51,10 @@ GCodeQueue queue;
51 51
   #include "../feature/powerloss.h"
52 52
 #endif
53 53
 
54
+#if ENABLED(GCODE_REPEAT_MARKERS)
55
+  #include "../feature/repeat.h"
56
+#endif
57
+
54 58
 /**
55 59
  * GCode line number handling. Hosts may opt to include line numbers when
56 60
  * sending commands to Marlin, and lines will be checked for sequentiality.
@@ -577,10 +581,9 @@ void GCodeQueue::get_serial_commands() {
577 581
     if (!IS_SD_PRINTING()) return;
578 582
 
579 583
     int sd_count = 0;
580
-    bool card_eof = card.eof();
581
-    while (length < BUFSIZE && !card_eof) {
584
+    while (length < BUFSIZE && !card.eof()) {
582 585
       const int16_t n = card.get();
583
-      card_eof = card.eof();
586
+      const bool card_eof = card.eof();
584 587
       if (n < 0 && !card_eof) { SERIAL_ERROR_MSG(STR_SD_ERR_READ); continue; }
585 588
 
586 589
       const char sd_char = (char)n;
@@ -590,17 +593,21 @@ void GCodeQueue::get_serial_commands() {
590 593
         // Reset stream state, terminate the buffer, and commit a non-empty command
591 594
         if (!is_eol && sd_count) ++sd_count;          // End of file with no newline
592 595
         if (!process_line_done(sd_input_state, command_buffer[index_w], sd_count)) {
596
+
597
+          // M808 S saves the sdpos of the next line. M808 loops to a new sdpos.
598
+          TERN_(GCODE_REPEAT_MARKERS, repeat.early_parse_M808(command_buffer[index_w]));
599
+
600
+          // Put the new command into the buffer (no "ok" sent)
593 601
           _commit_command(false);
594
-          #if ENABLED(POWER_LOSS_RECOVERY)
595
-            recovery.cmd_sdpos = card.getIndex();     // Prime for the NEXT _commit_command
596
-          #endif
602
+
603
+          // Prime Power-Loss Recovery for the NEXT _commit_command
604
+          TERN_(POWER_LOSS_RECOVERY, recovery.cmd_sdpos = card.getIndex());
597 605
         }
598 606
 
599
-        if (card_eof) card.fileHasFinished();         // Handle end of file reached
607
+        if (card.eof()) card.fileHasFinished();         // Handle end of file reached
600 608
       }
601 609
       else
602 610
         process_stream_char(sd_char, sd_input_state, command_buffer[index_w], sd_count);
603
-
604 611
     }
605 612
   }
606 613
 

+ 51
- 0
Marlin/src/gcode/sd/M808.cpp View File

@@ -0,0 +1,51 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+#include "../../inc/MarlinConfig.h"
24
+
25
+#if ENABLED(GCODE_REPEAT_MARKERS)
26
+
27
+#include "../gcode.h"
28
+#include "../../feature/repeat.h"
29
+
30
+/**
31
+ * M808: Set / Goto a repeat marker
32
+ *
33
+ *  L<count> - Set a repeat marker with 'count' repetitions. If omitted, infinity.
34
+ *
35
+ * Examples:
36
+ *
37
+ *    M808 L   ; Set a loop marker with a count of infinity
38
+ *    M808 L2  ; Set a loop marker with a count of 2
39
+ *    M808     ; Decrement and loop if not zero.
40
+ */
41
+void GcodeSuite::M808() {
42
+
43
+  // Handled early and ignored here in the queue.
44
+  // Allowed to go into the queue for logging purposes.
45
+
46
+  // M808 K sent from the host to cancel all loops
47
+  if (parser.seen('K')) repeat.cancel();
48
+
49
+}
50
+
51
+#endif // GCODE_REPEAT_MARKERS

+ 1
- 2
Marlin/src/sd/cardreader.cpp View File

@@ -699,8 +699,7 @@ void CardReader::removeFile(const char * const name) {
699 699
 
700 700
 void CardReader::report_status() {
701 701
   if (isPrinting()) {
702
-    SERIAL_ECHOPGM(STR_SD_PRINTING_BYTE);
703
-    SERIAL_ECHO(sdpos);
702
+    SERIAL_ECHOPAIR(STR_SD_PRINTING_BYTE, sdpos);
704 703
     SERIAL_CHAR('/');
705 704
     SERIAL_ECHOLN(filesize);
706 705
   }

+ 4
- 3
Marlin/src/sd/cardreader.h View File

@@ -159,9 +159,9 @@ public:
159 159
   static inline uint32_t getIndex() { return sdpos; }
160 160
   static inline uint32_t getFileSize() { return filesize; }
161 161
   static inline bool eof() { return sdpos >= filesize; }
162
-  static inline void setIndex(const uint32_t index) { sdpos = index; file.seekSet(index); }
162
+  static inline void setIndex(const uint32_t index) { file.seekSet((sdpos = index)); }
163 163
   static inline char* getWorkDirName() { workDir.getDosName(filename); return filename; }
164
-  static inline int16_t get() { sdpos = file.curPosition(); return (int16_t)file.read(); }
164
+  static inline int16_t get() { int16_t out = (int16_t)file.read(); sdpos = file.curPosition(); return out; }
165 165
   static inline int16_t read(void* buf, uint16_t nbyte) { return file.isOpen() ? file.read(buf, nbyte) : -1; }
166 166
   static inline int16_t write(void* buf, uint16_t nbyte) { return file.isOpen() ? file.write(buf, nbyte) : -1; }
167 167
 
@@ -244,7 +244,8 @@ private:
244 244
   static SdVolume volume;
245 245
   static SdFile file;
246 246
 
247
-  static uint32_t filesize, sdpos;
247
+  static uint32_t filesize, // Total size of the current file, in bytes
248
+                  sdpos;    // Index most recently read (one behind file.getPos)
248 249
 
249 250
   //
250 251
   // Procedure calls to other files

+ 16
- 0
buildroot/test-gcode/M808-loops.gcode View File

@@ -0,0 +1,16 @@
1
+;
2
+; M808 Repeat Marker Test
3
+;
4
+
5
+M808 L3 ; Marker at 54
6
+
7
+M118 Outer Loop
8
+M300 S220 P100
9
+
10
+M808 L5 ; Marker at 111
11
+
12
+M118 Inner Loop
13
+M300 S110 P100
14
+
15
+M808
16
+M808

+ 1
- 1
buildroot/tests/mega2560-tests View File

@@ -107,7 +107,7 @@ restore_configs
107 107
 opt_set MOTHERBOARD BOARD_MEGACONTROLLER
108 108
 opt_set LCD_LANGUAGE de
109 109
 opt_enable EEPROM_SETTINGS EEPROM_CHITCHAT \
110
-           MINIPANEL SDSUPPORT PCA9632 LCD_INFO_MENU SOUND_MENU_ITEM \
110
+           MINIPANEL SDSUPPORT PCA9632 LCD_INFO_MENU SOUND_MENU_ITEM GCODE_REPEAT_MARKERS \
111 111
            AUTO_BED_LEVELING_BILINEAR PROBE_MANUALLY LCD_BED_LEVELING G26_MESH_VALIDATION MESH_EDIT_MENU \
112 112
            LIN_ADVANCE EXTRA_LIN_ADVANCE_K \
113 113
            INCH_MODE_SUPPORT TEMPERATURE_UNITS_SUPPORT EXPERIMENTAL_I2CBUS M100_FREE_MEMORY_WATCHER \

+ 4
- 1
platformio.ini View File

@@ -101,6 +101,7 @@ default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared>
101 101
   -<src/feature/power_monitor.cpp> -<src/gcode/feature/power_monitor>
102 102
   -<src/feature/powerloss.cpp> -<src/gcode/feature/powerloss>
103 103
   -<src/feature/probe_temp_comp.cpp>
104
+  -<src/feature/repeat.cpp>
104 105
   -<src/feature/runout.cpp> -<src/gcode/feature/runout>
105 106
   -<src/feature/solenoid.cpp> -<src/gcode/control/M380_M381.cpp>
106 107
   -<src/feature/spindle_laser.cpp> -<src/gcode/control/M3-M5.cpp>
@@ -182,6 +183,7 @@ default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared>
182 183
   -<src/gcode/scara>
183 184
   -<src/gcode/sd>
184 185
   -<src/gcode/sd/M32.cpp>
186
+  -<src/gcode/sd/M808.cpp>
185 187
   -<src/gcode/temp/M104_M109.cpp>
186 188
   -<src/gcode/temp/M155.cpp>
187 189
   -<src/gcode/units/G20_G21.cpp>
@@ -374,6 +376,7 @@ G38_PROBE_TARGET        = src_filter=+<src/gcode/probe/G38.cpp>
374 376
 MAGNETIC_PARKING_EXTRUDER = src_filter=+<src/gcode/probe/M951.cpp>
375 377
 SDSUPPORT               = src_filter=+<src/gcode/sd>
376 378
 HAS_MEDIA_SUBCALLS      = src_filter=+<src/gcode/sd/M32.cpp>
379
+GCODE_REPEAT_MARKERS    = src_filter=+<src/feature/repeat.cpp> +<src/gcode/sd/M808.cpp>
377 380
 HAS_EXTRUDERS           = src_filter=+<src/gcode/temp/M104_M109.cpp> +<src/gcode/config/M221.cpp>
378 381
 AUTO_REPORT_TEMPERATURES = src_filter=+<src/gcode/temp/M155.cpp>
379 382
 INCH_MODE_SUPPORT       = src_filter=+<src/gcode/units/G20_G21.cpp>
@@ -402,7 +405,7 @@ framework     = arduino
402 405
 extra_scripts = ${common.extra_scripts}
403 406
 build_flags   = ${common.build_flags}
404 407
 lib_deps      = ${common.lib_deps}
405
-monitor_speed = 250000
408
+monitor_speed = 115200
406 409
 monitor_flags =
407 410
   --quiet
408 411
   --echo

Loading…
Cancel
Save