From 591a7986f54ce62268d878d84cc9606f5f4b67b7 Mon Sep 17 00:00:00 2001 From: Evan Felix Date: Fri, 31 May 2024 10:31:08 -0700 Subject: [PATCH 01/14] Fix No Integer restore in G61 This Fixes the case where no Integers were specified on the G61 command: ``` G60 G0 X100 Y100 Z20 G61 X Y ``` does not return to the last location as : ``` G60 G0 X100 Y100 Z20 G61 X0 Y0 ``` does. this matches what the spec says: https://marlinfw.org/docs/gcode/G061.html which does not even document you can put an integer after the axis letters. --- Marlin/src/gcode/feature/pause/G61.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/gcode/feature/pause/G61.cpp b/Marlin/src/gcode/feature/pause/G61.cpp index 068e0b0e40ee..9767b9255d8b 100644 --- a/Marlin/src/gcode/feature/pause/G61.cpp +++ b/Marlin/src/gcode/feature/pause/G61.cpp @@ -86,7 +86,7 @@ void GcodeSuite::G61() { LOOP_NUM_AXES(i) { destination[i] = parser.seen(AXIS_CHAR(i)) ? stored_position[slot][i] + parser.value_axis_units((AxisEnum)i) - : current_position[i]; + : stored_position[slot][i]; DEBUG_ECHO(C(' '), C(AXIS_CHAR(i)), p_float_t(destination[i], 2)); } DEBUG_EOL(); From e75f3a645e55343fc0bc53af700e95e6c121e327 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Wed, 17 Jul 2024 23:04:48 -0500 Subject: [PATCH 02/14] G60 Q, etc. --- Marlin/src/gcode/feature/pause/G60.cpp | 6 +++++- Marlin/src/gcode/feature/pause/G61.cpp | 20 +++++++++++--------- Marlin/src/gcode/gcode.h | 2 +- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Marlin/src/gcode/feature/pause/G60.cpp b/Marlin/src/gcode/feature/pause/G60.cpp index aa74a57596d1..1585a1591ce2 100644 --- a/Marlin/src/gcode/feature/pause/G60.cpp +++ b/Marlin/src/gcode/feature/pause/G60.cpp @@ -34,15 +34,19 @@ * G60: Save current position * * S - Memory slot # (0-based) to save into (default 0) + * Q - Memory slot # (0-based) to restore. (default none) */ void GcodeSuite::G60() { - const uint8_t slot = parser.byteval('S'); + const bool seenQ = parser.seenval('Q'); + const uint8_t slot = seenQ ? parser.value_byte() : parser.byteval('S'); if (slot >= SAVED_POSITIONS) { SERIAL_ERROR_MSG(STR_INVALID_POS_SLOT STRINGIFY(SAVED_POSITIONS)); return; } + if (seenQ) return G61(slot); + stored_position[slot] = current_position; SBI(saved_slots[slot >> 3], slot & 0x07); diff --git a/Marlin/src/gcode/feature/pause/G61.cpp b/Marlin/src/gcode/feature/pause/G61.cpp index 9767b9255d8b..7adc89cbdb17 100644 --- a/Marlin/src/gcode/feature/pause/G61.cpp +++ b/Marlin/src/gcode/feature/pause/G61.cpp @@ -54,9 +54,9 @@ * * If no axes are specified then all axes are restored. */ -void GcodeSuite::G61() { +void GcodeSuite::G61(int8_t slot/*=-1*/) { - const uint8_t slot = parser.byteval('S'); + if (slot < 0) slot = parser.byteval('S'); #define SYNC_E(POINT) TERN_(HAS_EXTRUDERS, planner.set_e_position_mm((destination.e = current_position.e = (POINT)))) @@ -83,20 +83,22 @@ void GcodeSuite::G61() { else { if (parser.seen(STR_AXES_MAIN)) { DEBUG_ECHOPGM(STR_RESTORING_POS " S", slot); + destination = current_position; LOOP_NUM_AXES(i) { - destination[i] = parser.seen(AXIS_CHAR(i)) - ? stored_position[slot][i] + parser.value_axis_units((AxisEnum)i) - : stored_position[slot][i]; - DEBUG_ECHO(C(' '), C(AXIS_CHAR(i)), p_float_t(destination[i], 2)); + if (parser.seen(AXIS_CHAR(i))) { + destination[i] = stored_position[slot][i] + parser.value_axis_units((AxisEnum)i); + DEBUG_ECHO(C(' '), C(AXIS_CHAR(i)), p_float_t(destination[i], 2)); + } } DEBUG_EOL(); // Move to the saved position prepare_line_to_destination(); } #if HAS_EXTRUDERS - if (parser.seen_test('E')) { - DEBUG_ECHOLNPGM(STR_RESTORING_POS " S", slot, " E", current_position.e, "=>", stored_position[slot].e); - SYNC_E(stored_position[slot].e); + if (parser.seen('E')) { + const float epos = stored_position[slot].e + parser.value_axis_units((AxisEnum)i); + DEBUG_ECHOLNPGM(STR_RESTORING_POS " S", slot, " E", current_position.e, "=>", epos); + SYNC_E(epos); } #endif } diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h index 144d724cd9cd..4277dbc15665 100644 --- a/Marlin/src/gcode/gcode.h +++ b/Marlin/src/gcode/gcode.h @@ -605,7 +605,7 @@ class GcodeSuite { #if SAVED_POSITIONS static void G60(); - static void G61(); + static void G61(int8_t slot=-1); #endif #if ENABLED(GCODE_MOTION_MODES) From f8f590fecce399aed80ceffc9400bac29fda4d1e Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 18 Jul 2024 00:37:14 -0500 Subject: [PATCH 03/14] =?UTF-8?q?=E2=80=A6and=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Marlin/src/gcode/feature/pause/G61.cpp | 50 ++++++++++++++------------ 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/Marlin/src/gcode/feature/pause/G61.cpp b/Marlin/src/gcode/feature/pause/G61.cpp index 7adc89cbdb17..60f611e17869 100644 --- a/Marlin/src/gcode/feature/pause/G61.cpp +++ b/Marlin/src/gcode/feature/pause/G61.cpp @@ -58,7 +58,7 @@ void GcodeSuite::G61(int8_t slot/*=-1*/) { if (slot < 0) slot = parser.byteval('S'); - #define SYNC_E(POINT) TERN_(HAS_EXTRUDERS, planner.set_e_position_mm((destination.e = current_position.e = (POINT)))) + #define SYNC_E(E) planner.set_e_position_mm(current_position.e = (E)) #if SAVED_POSITIONS < 256 if (slot >= SAVED_POSITIONS) { @@ -75,33 +75,39 @@ void GcodeSuite::G61(int8_t slot/*=-1*/) { const float fr = parser.linearval('F'); if (fr > 0.0) feedrate_mm_s = MMM_TO_MMS(fr); + // No XYZ...E parameters, move to stored position + float epos = stored_position[slot].e; if (!parser.seen_axis()) { - DEBUG_ECHOLNPGM("Default position restore"); + DEBUG_ECHOLNPGM(STR_RESTORING_POS " (all axes)"); + // Move to the saved position, all axes except E do_blocking_move_to(stored_position[slot], feedrate_mm_s); - SYNC_E(stored_position[slot].e); + // Just set E to the saved position without moving it + TERN_(HAS_EXTRUDERS, SYNC_E(stored_position[slot].e)); + return; } - else { - if (parser.seen(STR_AXES_MAIN)) { - DEBUG_ECHOPGM(STR_RESTORING_POS " S", slot); - destination = current_position; - LOOP_NUM_AXES(i) { - if (parser.seen(AXIS_CHAR(i))) { - destination[i] = stored_position[slot][i] + parser.value_axis_units((AxisEnum)i); - DEBUG_ECHO(C(' '), C(AXIS_CHAR(i)), p_float_t(destination[i], 2)); - } + + // Any axes specified, + if (parser.seen(STR_AXES_MAIN)) { + DEBUG_ECHOPGM(STR_RESTORING_POS " S", slot); + destination = current_position; + LOOP_NUM_AXES(i) { + if (parser.seen(AXIS_CHAR(i))) { + destination[i] = stored_position[slot][i] + parser.value_axis_units((AxisEnum)i); + DEBUG_ECHO(C(' '), C(AXIS_CHAR(i)), p_float_t(destination[i], 2)); } - DEBUG_EOL(); - // Move to the saved position - prepare_line_to_destination(); } - #if HAS_EXTRUDERS - if (parser.seen('E')) { - const float epos = stored_position[slot].e + parser.value_axis_units((AxisEnum)i); - DEBUG_ECHOLNPGM(STR_RESTORING_POS " S", slot, " E", current_position.e, "=>", epos); - SYNC_E(epos); - } - #endif + DEBUG_EOL(); + // Move to the saved position + prepare_line_to_destination(); } + + #if HAS_EXTRUDERS + if (parser.seen('E')) { + epos += parser.value_axis_units(E_AXIS); + DEBUG_ECHOLNPGM(STR_RESTORING_POS " S", slot, " E", current_position.e, "=>", epos); + SYNC_E(epos); + } + #endif } #endif // SAVED_POSITIONS From 570ec1f95ea91470014a3c575505171797439ca0 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 18 Jul 2024 09:54:24 -0500 Subject: [PATCH 04/14] =?UTF-8?q?=E2=80=A6etc=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Marlin/src/gcode/feature/pause/G60.cpp | 4 ++-- Marlin/src/gcode/feature/pause/G61.cpp | 13 ++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Marlin/src/gcode/feature/pause/G60.cpp b/Marlin/src/gcode/feature/pause/G60.cpp index 1585a1591ce2..4c26f699b541 100644 --- a/Marlin/src/gcode/feature/pause/G60.cpp +++ b/Marlin/src/gcode/feature/pause/G60.cpp @@ -40,13 +40,13 @@ void GcodeSuite::G60() { const bool seenQ = parser.seenval('Q'); const uint8_t slot = seenQ ? parser.value_byte() : parser.byteval('S'); + if (seenQ) return G61(slot); + if (slot >= SAVED_POSITIONS) { SERIAL_ERROR_MSG(STR_INVALID_POS_SLOT STRINGIFY(SAVED_POSITIONS)); return; } - if (seenQ) return G61(slot); - stored_position[slot] = current_position; SBI(saved_slots[slot >> 3], slot & 0x07); diff --git a/Marlin/src/gcode/feature/pause/G61.cpp b/Marlin/src/gcode/feature/pause/G61.cpp index 60f611e17869..df59d64e65f8 100644 --- a/Marlin/src/gcode/feature/pause/G61.cpp +++ b/Marlin/src/gcode/feature/pause/G61.cpp @@ -76,6 +76,7 @@ void GcodeSuite::G61(int8_t slot/*=-1*/) { if (fr > 0.0) feedrate_mm_s = MMM_TO_MMS(fr); // No XYZ...E parameters, move to stored position + float epos = stored_position[slot].e; if (!parser.seen_axis()) { DEBUG_ECHOLNPGM(STR_RESTORING_POS " (all axes)"); @@ -86,9 +87,11 @@ void GcodeSuite::G61(int8_t slot/*=-1*/) { return; } - // Any axes specified, + // With XYZ...E return specified axes + optional offset + + DEBUG_ECHOPGM(STR_RESTORING_POS " S", slot); + if (parser.seen(STR_AXES_MAIN)) { - DEBUG_ECHOPGM(STR_RESTORING_POS " S", slot); destination = current_position; LOOP_NUM_AXES(i) { if (parser.seen(AXIS_CHAR(i))) { @@ -96,18 +99,18 @@ void GcodeSuite::G61(int8_t slot/*=-1*/) { DEBUG_ECHO(C(' '), C(AXIS_CHAR(i)), p_float_t(destination[i], 2)); } } - DEBUG_EOL(); - // Move to the saved position prepare_line_to_destination(); } #if HAS_EXTRUDERS if (parser.seen('E')) { epos += parser.value_axis_units(E_AXIS); - DEBUG_ECHOLNPGM(STR_RESTORING_POS " S", slot, " E", current_position.e, "=>", epos); + DEBUG_ECHOPGM(" E", epos); SYNC_E(epos); } #endif + + DEBUG_EOL(); } #endif // SAVED_POSITIONS From 29faabe90809aa65abbdfbd00aef616ff228e157 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 18 Jul 2024 10:05:32 -0500 Subject: [PATCH 05/14] help hosts --- Marlin/src/gcode/feature/pause/G61.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Marlin/src/gcode/feature/pause/G61.cpp b/Marlin/src/gcode/feature/pause/G61.cpp index df59d64e65f8..abb99b69d1b0 100644 --- a/Marlin/src/gcode/feature/pause/G61.cpp +++ b/Marlin/src/gcode/feature/pause/G61.cpp @@ -111,6 +111,8 @@ void GcodeSuite::G61(int8_t slot/*=-1*/) { #endif DEBUG_EOL(); + + report_current_position(); } #endif // SAVED_POSITIONS From fda089cf23ee89b1e8ebbcaaaf3411abb015f44e Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Fri, 19 Jul 2024 00:33:13 -0500 Subject: [PATCH 06/14] Parity with wiki --- Marlin/src/core/language.h | 2 +- Marlin/src/gcode/feature/pause/G60.cpp | 61 ++++++++++++++++++++++---- Marlin/src/gcode/feature/pause/G61.cpp | 12 +++-- Marlin/src/module/motion.cpp | 2 +- Marlin/src/module/motion.h | 2 +- 5 files changed, 61 insertions(+), 18 deletions(-) diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index ad84966453f1..a3ea6164536c 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -162,7 +162,7 @@ #define STR_SOFT_MIN " Min: " #define STR_SOFT_MAX " Max: " -#define STR_SAVED_POS "Position saved" +#define STR_SAVED_POS "Saved position #" #define STR_RESTORING_POS "Restoring position" #define STR_INVALID_POS_SLOT "Invalid slot. Total: " #define STR_DONE "Done." diff --git a/Marlin/src/gcode/feature/pause/G60.cpp b/Marlin/src/gcode/feature/pause/G60.cpp index 4c26f699b541..89f8097243ac 100644 --- a/Marlin/src/gcode/feature/pause/G60.cpp +++ b/Marlin/src/gcode/feature/pause/G60.cpp @@ -31,29 +31,74 @@ #include "../../../core/debug_out.h" /** - * G60: Save current position + * G60: Saved Positions * - * S - Memory slot # (0-based) to save into (default 0) - * Q - Memory slot # (0-based) to restore. (default none) + * S - Save to a memory slot. (default 0) + * Q - Restore from a memory slot. (default 0) + * D - Delete a memory slot. With no number, delete all. */ void GcodeSuite::G60() { - const bool seenQ = parser.seenval('Q'); - const uint8_t slot = seenQ ? parser.value_byte() : parser.byteval('S'); + // With no parameters report any saved positions + if (!parser.seen_any()) { + for (uint8_t s = 0; s < SAVED_POSITIONS; ++s) { + if (!did_save_position[s]) continue; + const xyze_pos_t &pos = stored_position[s]; + SERIAL_ECHOPGM("Saved position #", s, ": "); + #if NUM_AXES + SERIAL_ECHOPGM_P( + LIST_N(DOUBLE(NUM_AXES), + SP_X_LBL, pos.x, SP_Y_LBL, pos.y, SP_Z_LBL, pos.z, + SP_I_LBL, pos.i, SP_J_LBL, pos.j, SP_K_LBL, pos.k, + SP_U_LBL, pos.u, SP_V_LBL, pos.v, SP_W_LBL, pos.w + ) + ); + #endif + #if HAS_EXTRUDERS + SERIAL_ECHOPGM_P(SP_E_LBL, pos.e); + #endif + SERIAL_EOL(); + } + return; + } + + // Only one of these parameters is permitted + const uint8_t seenD = parser.seen_test('D'), + seenQ = parser.seen_test('Q'), + seenS = parser.seen_test('S'); + if (seenD + seenQ + seenS > 1) return; + + // G60 D : Delete all saved positions + if (seenD && !parser.seenval('D')) { + did_save_position.reset(); + return; + } + + // G60 Dn / Q / S : Get the slot value + const uint8_t slot = parser.byteval(seenD ? 'D' : seenQ ? 'Q' : 'S'); + // G60 Q : Redirect to G61(slot) if (seenQ) return G61(slot); - if (slot >= SAVED_POSITIONS) { + // Valid slot number? + if (SAVED_POSITIONS < 256 && slot >= SAVED_POSITIONS) { SERIAL_ERROR_MSG(STR_INVALID_POS_SLOT STRINGIFY(SAVED_POSITIONS)); return; } + // G60 Dn + if (seenD) { + did_save_position.clear(slot); + return; + } + + // G60 S stored_position[slot] = current_position; - SBI(saved_slots[slot >> 3], slot & 0x07); + did_save_position.set(slot); #if ENABLED(SAVED_POSITIONS_DEBUG) { const xyze_pos_t &pos = stored_position[slot]; - DEBUG_ECHOPGM(STR_SAVED_POS " S", slot, " :"); + DEBUG_ECHOPGM(STR_SAVED_POS, slot, ": "); #if NUM_AXES DEBUG_ECHOPGM_P( LIST_N(DOUBLE(NUM_AXES), diff --git a/Marlin/src/gcode/feature/pause/G61.cpp b/Marlin/src/gcode/feature/pause/G61.cpp index abb99b69d1b0..b78fd78256cf 100644 --- a/Marlin/src/gcode/feature/pause/G61.cpp +++ b/Marlin/src/gcode/feature/pause/G61.cpp @@ -60,15 +60,13 @@ void GcodeSuite::G61(int8_t slot/*=-1*/) { #define SYNC_E(E) planner.set_e_position_mm(current_position.e = (E)) - #if SAVED_POSITIONS < 256 - if (slot >= SAVED_POSITIONS) { - SERIAL_ERROR_MSG(STR_INVALID_POS_SLOT STRINGIFY(SAVED_POSITIONS)); - return; - } - #endif + if (SAVED_POSITIONS < 256 && slot >= SAVED_POSITIONS) { + SERIAL_ERROR_MSG(STR_INVALID_POS_SLOT STRINGIFY(SAVED_POSITIONS)); + return; + } // No saved position? No axes being restored? - if (!TEST(saved_slots[slot >> 3], slot & 0x07)) return; + if (!did_save_position[slot]) return; // Apply any given feedrate over 0.0 REMEMBER(saved, feedrate_mm_s); diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index 473d54cc382b..0e743d56b6d7 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -104,7 +104,7 @@ xyze_pos_t destination; // {0} // G60/G61 Position Save and Return #if SAVED_POSITIONS - uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; + Flags did_save_position; xyze_pos_t stored_position[SAVED_POSITIONS]; #endif diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index f9748871f5c8..54a9642e6f73 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -50,7 +50,7 @@ extern xyze_pos_t current_position, // High-level current tool position // G60/G61 Position Save and Return #if SAVED_POSITIONS - extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; // TODO: Add support for HAS_I_AXIS + extern Flags did_save_position; extern xyze_pos_t stored_position[SAVED_POSITIONS]; #endif From b3ead0a8689921810afdb28f480b1960283ea771 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Fri, 19 Jul 2024 01:03:56 -0500 Subject: [PATCH 07/14] unlimited flags --- Marlin/src/core/types.h | 46 +++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index f5dc23128909..344c9b752313 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -166,24 +166,38 @@ template struct IF { typedef L type; }; // General Flags for some number of states template struct Flags { - typedef bits_t(N) flagbits_t; - typedef struct { bool b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1; } N8; - typedef struct { bool b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1, b8:1, b9:1, b10:1, b11:1, b12:1, b13:1, b14:1, b15:1; } N16; - typedef struct { bool b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1, b8:1, b9:1, b10:1, b11:1, b12:1, b13:1, b14:1, b15:1, - b16:1, b17:1, b18:1, b19:1, b20:1, b21:1, b22:1, b23:1, b24:1, b25:1, b26:1, b27:1, b28:1, b29:1, b30:1, b31:1; } N32; - union { - flagbits_t b; - typename IF<(N>16), N32, typename IF<(N>8), N16, N8>::type>::type flag; + uint8_t bitmask[(N+7)>>3]; + // Proxy class for handling bit assignment + class BitProxy { + public: + BitProxy(uint8_t data[], int n) : data_(data[n>>3]), bit_(n&7) {} + + // Assignment operator + BitProxy& operator=(const bool value) { + if (value) + data_ |= _BV(bit_); + else + data_ &= ~_BV(bit_); + return *this; + } + + // Conversion operator to bool + operator bool() const { return TEST(data_, bit_); } + + private: + uint8_t& data_; + uint8_t bit_; }; - FI void reset() { b = 0; } + + FI void reset() { for (uint8_t b = 0; b < sizeof(bitmask); ++b) bitmask[b] = 0; } FI void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); } - FI void set(const int n) { b |= (flagbits_t)_BV(n); } - FI void clear(const int n) { b &= ~(flagbits_t)_BV(n); } - FI bool test(const int n) const { return TEST(b, n); } - FI bool operator[](const int n) { return test(n); } + FI void set(const int n) { bitmask[n>>3] |= _BV(n&7); } + FI void clear(const int n) { bitmask[n>>3] &= ~_BV(n&7); } + FI bool test(const int n) const { return TEST(bitmask[n>>3], n&7); } + FI BitProxy operator[](const int n) { return BitProxy(bitmask, n); } FI bool operator[](const int n) const { return test(n); } - FI int size() const { return sizeof(b); } - FI operator bool() const { return b; } + FI int size() const { return sizeof(bitmask); } + FI operator bool() const { for (uint8_t b : bitmask) if (b) return true; return false; } }; // Specialization for a single bool flag @@ -218,7 +232,7 @@ typedef struct { FI bool operator[](const int n) { return flags[n]; } FI bool operator[](const int n) const { return flags[n]; } FI int size() const { return sizeof(flags); } - FI operator bool() const { return flags; } + FI operator bool() const { return (bool)flags; } } AxisFlags; // From 4bc093fc38793118d6a91619919a98c8e2195fd1 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sun, 21 Jul 2024 21:29:04 -0500 Subject: [PATCH 08/14] optimal specialization --- Marlin/src/core/macros.h | 2 +- Marlin/src/core/types.h | 48 +++++++++++++++++++++++++++++--- Marlin/tests/core/test_types.cpp | 29 +++++++++++++++++++ 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/Marlin/src/core/macros.h b/Marlin/src/core/macros.h index 5d2f4f0de179..325d1c71f0a9 100644 --- a/Marlin/src/core/macros.h +++ b/Marlin/src/core/macros.h @@ -67,7 +67,7 @@ // Macros for bit masks #undef _BV -#define _BV(n) (1<<(n)) +#define _BV(b) (1 << (b)) #define TEST(n,b) (!!((n)&_BV(b))) #define SET_BIT_TO(N,B,TF) do{ if (TF) SBI(N,B); else CBI(N,B); }while(0) #ifndef SBI diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index 344c9b752313..ef0f2d4da4a2 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -159,13 +159,53 @@ template struct IF { typedef L type; }; #define FI FORCE_INLINE // Define types based on largest bit width stored value required -#define bits_t(W) typename IF<((W)> 16), uint32_t, typename IF<((W)> 8), uint16_t, uint8_t>::type>::type +#define bits_t(W) typename IF<((W)> 32), uint64_t, typename IF<((W)> 16), uint32_t, typename IF<((W)>8), uint16_t, uint8_t>::type>::type>::type #define uvalue_t(V) typename IF<((V)>65535), uint32_t, typename IF<((V)>255), uint16_t, uint8_t>::type>::type #define value_t(V) typename IF<((V)>32767), int32_t, typename IF<((V)>127), int16_t, int8_t>::type>::type -// General Flags for some number of states +// Define a template for a bit field of N bits, using the smallest type that can hold N bits +template 64)> +struct Flags; + +// Flag bits for <= 64 states +template +struct Flags { + typedef bits_t(N) flagbits_t; + flagbits_t b; + + class BitProxy { + public: + BitProxy(flagbits_t& data, int bit) : data_(data), bit_(bit) {} + + BitProxy& operator=(const bool value) { + if (value) + data_ |= (flagbits_t)_BV(bit_); + else + data_ &= ~(flagbits_t)_BV(bit_); + return *this; + } + + operator bool() const { return TEST(data_, bit_); } + + private: + flagbits_t& data_; + uint8_t bit_; + }; + + FI void reset() { b = 0; } + FI void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); } + FI void set(const int n) { b |= (flagbits_t)_BV(n); } + FI void clear(const int n) { b &= ~(flagbits_t)_BV(n); } + FI bool test(const int n) const { return TEST(b, n); } + FI BitProxy operator[](const int n) { return BitProxy(b, n); } + FI bool operator[](const int n) const { return test(n); } + FI int size() const { return sizeof(b); } + FI operator bool() const { return b != 0; } +}; + +// Flag bits for more than 64 states template -struct Flags { +struct Flags { uint8_t bitmask[(N+7)>>3]; // Proxy class for handling bit assignment class BitProxy { @@ -202,7 +242,7 @@ struct Flags { // Specialization for a single bool flag template<> -struct Flags<1> { +struct Flags<1, false> { bool b; FI void reset() { b = false; } FI void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); } diff --git a/Marlin/tests/core/test_types.cpp b/Marlin/tests/core/test_types.cpp index 865d35de158c..79db72b2aa2e 100644 --- a/Marlin/tests/core/test_types.cpp +++ b/Marlin/tests/core/test_types.cpp @@ -532,6 +532,35 @@ MARLIN_TEST(types, Flags_32) { TEST_ASSERT_EQUAL(4, flags.size()); } +MARLIN_TEST(types, Flags_64) { + Flags<64> flags; + + flags.reset(); + TEST_ASSERT_EQUAL(0, flags.b); + + flags.set(0, true); + flags.set(63, true); + TEST_ASSERT_EQUAL(9223372036854775809ULL, flags.b); + + flags.clear(0); + flags.clear(63); + TEST_ASSERT_EQUAL(0, flags.b); + + flags.set(0, true); + flags.set(63, true); + TEST_ASSERT_EQUAL(true, flags.test(0)); + TEST_ASSERT_EQUAL(true, flags.test(63)); + TEST_ASSERT_EQUAL(false, flags.test(1)); + TEST_ASSERT_EQUAL(false, flags.test(62)); + + TEST_ASSERT_EQUAL(true, flags[0]); + TEST_ASSERT_EQUAL(true, flags[63]); + TEST_ASSERT_EQUAL(false, flags[1]); + TEST_ASSERT_EQUAL(false, flags[62]); + + TEST_ASSERT_EQUAL(8, flags.size()); +} + MARLIN_TEST(types, AxisFlags_const_as_bools) { const AxisFlags axis_flags_const_false = {0}; TEST_ASSERT_FALSE(axis_flags_const_false); From fc4cee263b824c4dbfb4bf16bb0dc19e88343262 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 22 Jul 2024 14:51:56 -0500 Subject: [PATCH 09/14] more bits --- Marlin/src/core/types.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index ef0f2d4da4a2..1b2c9b851da8 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -179,9 +179,9 @@ struct Flags { BitProxy& operator=(const bool value) { if (value) - data_ |= (flagbits_t)_BV(bit_); + data_ |= flagbits_t(1) << bit_; else - data_ &= ~(flagbits_t)_BV(bit_); + data_ &= ~flagbits_t(1) << bit_; return *this; } @@ -194,8 +194,8 @@ struct Flags { FI void reset() { b = 0; } FI void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); } - FI void set(const int n) { b |= (flagbits_t)_BV(n); } - FI void clear(const int n) { b &= ~(flagbits_t)_BV(n); } + FI void set(const int n) { b |= flagbits_t(1) << n; } + FI void clear(const int n) { b &= ~flagbits_t(1) << n; } FI bool test(const int n) const { return TEST(b, n); } FI BitProxy operator[](const int n) { return BitProxy(b, n); } FI bool operator[](const int n) const { return test(n); } @@ -215,7 +215,7 @@ struct Flags { // Assignment operator BitProxy& operator=(const bool value) { if (value) - data_ |= _BV(bit_); + data_ |= _BV(bit_); else data_ &= ~_BV(bit_); return *this; From 0917de45a2d6837bfdb22504efc746a3f9eefc8a Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 22 Jul 2024 15:39:41 -0500 Subject: [PATCH 10/14] test more bits --- Marlin/src/core/types.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index 1b2c9b851da8..9618e334ba1e 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -185,7 +185,7 @@ struct Flags { return *this; } - operator bool() const { return TEST(data_, bit_); } + operator bool() const { return bool(data_ & (flagbits_t(1) << bit_)); } private: flagbits_t& data_; @@ -196,7 +196,7 @@ struct Flags { FI void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); } FI void set(const int n) { b |= flagbits_t(1) << n; } FI void clear(const int n) { b &= ~flagbits_t(1) << n; } - FI bool test(const int n) const { return TEST(b, n); } + FI bool test(const int n) const { return bool(b & (flagbits_t(1) << bit_)); } FI BitProxy operator[](const int n) { return BitProxy(b, n); } FI bool operator[](const int n) const { return test(n); } FI int size() const { return sizeof(b); } @@ -210,7 +210,7 @@ struct Flags { // Proxy class for handling bit assignment class BitProxy { public: - BitProxy(uint8_t data[], int n) : data_(data[n>>3]), bit_(n&7) {} + BitProxy(uint8_t data[], int n) : data_(data[n >> 3]), bit_(n & 7) {} // Assignment operator BitProxy& operator=(const bool value) { @@ -231,9 +231,9 @@ struct Flags { FI void reset() { for (uint8_t b = 0; b < sizeof(bitmask); ++b) bitmask[b] = 0; } FI void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); } - FI void set(const int n) { bitmask[n>>3] |= _BV(n&7); } - FI void clear(const int n) { bitmask[n>>3] &= ~_BV(n&7); } - FI bool test(const int n) const { return TEST(bitmask[n>>3], n&7); } + FI void set(const int n) { bitmask[n >> 3] |= _BV(n & 7); } + FI void clear(const int n) { bitmask[n >> 3] &= ~_BV(n & 7); } + FI bool test(const int n) const { return TEST(bitmask[n >> 3], n & 7); } FI BitProxy operator[](const int n) { return BitProxy(bitmask, n); } FI bool operator[](const int n) const { return test(n); } FI int size() const { return sizeof(bitmask); } From de2ff5e12a3ce09940da1e1096c581a815965b0c Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 23 Jul 2024 21:20:19 -0500 Subject: [PATCH 11/14] sleep --- Marlin/src/core/types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index 9618e334ba1e..08808b693288 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -196,7 +196,7 @@ struct Flags { FI void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); } FI void set(const int n) { b |= flagbits_t(1) << n; } FI void clear(const int n) { b &= ~flagbits_t(1) << n; } - FI bool test(const int n) const { return bool(b & (flagbits_t(1) << bit_)); } + FI bool test(const int n) const { return bool(b & (flagbits_t(1) << n)); } FI BitProxy operator[](const int n) { return BitProxy(b, n); } FI bool operator[](const int n) const { return test(n); } FI int size() const { return sizeof(b); } From b9ad23fce994d270ac9409b0698d98ab0f94b2e3 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 23 Jul 2024 22:40:39 -0500 Subject: [PATCH 12/14] better --- Marlin/src/gcode/feature/pause/G60.cpp | 5 ++++- Marlin/src/gcode/feature/pause/G61.cpp | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Marlin/src/gcode/feature/pause/G60.cpp b/Marlin/src/gcode/feature/pause/G60.cpp index 89f8097243ac..15857c5e39f2 100644 --- a/Marlin/src/gcode/feature/pause/G60.cpp +++ b/Marlin/src/gcode/feature/pause/G60.cpp @@ -40,10 +40,12 @@ void GcodeSuite::G60() { // With no parameters report any saved positions if (!parser.seen_any()) { + uint8_t count = 0; for (uint8_t s = 0; s < SAVED_POSITIONS; ++s) { if (!did_save_position[s]) continue; + ++count; const xyze_pos_t &pos = stored_position[s]; - SERIAL_ECHOPGM("Saved position #", s, ": "); + SERIAL_ECHO(STR_SAVED_POS, s, C(':')); #if NUM_AXES SERIAL_ECHOPGM_P( LIST_N(DOUBLE(NUM_AXES), @@ -58,6 +60,7 @@ void GcodeSuite::G60() { #endif SERIAL_EOL(); } + if (!count) SERIAL_ECHOLNPGM("No Saved Positions"); return; } diff --git a/Marlin/src/gcode/feature/pause/G61.cpp b/Marlin/src/gcode/feature/pause/G61.cpp index b78fd78256cf..42daa6dd50d6 100644 --- a/Marlin/src/gcode/feature/pause/G61.cpp +++ b/Marlin/src/gcode/feature/pause/G61.cpp @@ -82,6 +82,7 @@ void GcodeSuite::G61(int8_t slot/*=-1*/) { do_blocking_move_to(stored_position[slot], feedrate_mm_s); // Just set E to the saved position without moving it TERN_(HAS_EXTRUDERS, SYNC_E(stored_position[slot].e)); + report_current_position(); return; } From 58f592a94def24406a90b07b390bce0ae37ebb36 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Wed, 24 Jul 2024 02:38:09 -0500 Subject: [PATCH 13/14] update set/clear --- Marlin/src/core/types.h | 8 ++++---- Marlin/src/gcode/feature/pause/G60.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index 08808b693288..4bc50b56c70b 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -179,9 +179,9 @@ struct Flags { BitProxy& operator=(const bool value) { if (value) - data_ |= flagbits_t(1) << bit_; + data_ |= (flagbits_t(1) << bit_); else - data_ &= ~flagbits_t(1) << bit_; + data_ &= ~(flagbits_t(1) << bit_); return *this; } @@ -194,8 +194,8 @@ struct Flags { FI void reset() { b = 0; } FI void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); } - FI void set(const int n) { b |= flagbits_t(1) << n; } - FI void clear(const int n) { b &= ~flagbits_t(1) << n; } + FI void set(const int n) { b |= (flagbits_t(1) << n); } + FI void clear(const int n) { b &= ~(flagbits_t(1) << n); } FI bool test(const int n) const { return bool(b & (flagbits_t(1) << n)); } FI BitProxy operator[](const int n) { return BitProxy(b, n); } FI bool operator[](const int n) const { return test(n); } diff --git a/Marlin/src/gcode/feature/pause/G60.cpp b/Marlin/src/gcode/feature/pause/G60.cpp index 15857c5e39f2..7143637bcf92 100644 --- a/Marlin/src/gcode/feature/pause/G60.cpp +++ b/Marlin/src/gcode/feature/pause/G60.cpp @@ -101,7 +101,7 @@ void GcodeSuite::G60() { #if ENABLED(SAVED_POSITIONS_DEBUG) { const xyze_pos_t &pos = stored_position[slot]; - DEBUG_ECHOPGM(STR_SAVED_POS, slot, ": "); + DEBUG_ECHO(STR_SAVED_POS, slot, C(':')); #if NUM_AXES DEBUG_ECHOPGM_P( LIST_N(DOUBLE(NUM_AXES), From 3ac3712033ae10e6442a3bae070a44b21c605ed6 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Wed, 24 Jul 2024 03:02:40 -0500 Subject: [PATCH 14/14] report on save --- Marlin/src/core/language.h | 4 +- Marlin/src/gcode/feature/pause/G60.cpp | 63 ++++++++++---------------- Marlin/src/gcode/feature/pause/G61.cpp | 4 +- 3 files changed, 28 insertions(+), 43 deletions(-) diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index 0654e57c19fd..2736a7833ed5 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -162,8 +162,8 @@ #define STR_SOFT_MIN " Min: " #define STR_SOFT_MAX " Max: " -#define STR_SAVED_POS "Saved position #" -#define STR_RESTORING_POS "Restoring position" +#define STR_SAVED_POSITION "Saved position #" +#define STR_RESTORING_POSITION "Restoring position #" #define STR_INVALID_POS_SLOT "Invalid slot. Total: " #define STR_DONE "Done." diff --git a/Marlin/src/gcode/feature/pause/G60.cpp b/Marlin/src/gcode/feature/pause/G60.cpp index 7143637bcf92..fe085200a9ca 100644 --- a/Marlin/src/gcode/feature/pause/G60.cpp +++ b/Marlin/src/gcode/feature/pause/G60.cpp @@ -30,6 +30,26 @@ #define DEBUG_OUT ENABLED(SAVED_POSITIONS_DEBUG) #include "../../../core/debug_out.h" +bool report_stored_position(const uint8_t slot) { + if (!did_save_position[slot]) return false; + const xyze_pos_t &pos = stored_position[slot]; + SERIAL_ECHO(STR_SAVED_POSITION, slot, C(':')); + #if NUM_AXES + SERIAL_ECHOPGM_P( + LIST_N(DOUBLE(NUM_AXES), + SP_X_LBL, pos.x, SP_Y_LBL, pos.y, SP_Z_LBL, pos.z, + SP_I_LBL, pos.i, SP_J_LBL, pos.j, SP_K_LBL, pos.k, + SP_U_LBL, pos.u, SP_V_LBL, pos.v, SP_W_LBL, pos.w + ) + ); + #endif + #if HAS_EXTRUDERS + SERIAL_ECHOPGM_P(SP_E_LBL, pos.e); + #endif + SERIAL_EOL(); + return true; +} + /** * G60: Saved Positions * @@ -41,25 +61,8 @@ void GcodeSuite::G60() { // With no parameters report any saved positions if (!parser.seen_any()) { uint8_t count = 0; - for (uint8_t s = 0; s < SAVED_POSITIONS; ++s) { - if (!did_save_position[s]) continue; - ++count; - const xyze_pos_t &pos = stored_position[s]; - SERIAL_ECHO(STR_SAVED_POS, s, C(':')); - #if NUM_AXES - SERIAL_ECHOPGM_P( - LIST_N(DOUBLE(NUM_AXES), - SP_X_LBL, pos.x, SP_Y_LBL, pos.y, SP_Z_LBL, pos.z, - SP_I_LBL, pos.i, SP_J_LBL, pos.j, SP_K_LBL, pos.k, - SP_U_LBL, pos.u, SP_V_LBL, pos.v, SP_W_LBL, pos.w - ) - ); - #endif - #if HAS_EXTRUDERS - SERIAL_ECHOPGM_P(SP_E_LBL, pos.e); - #endif - SERIAL_EOL(); - } + for (uint8_t s = 0; s < SAVED_POSITIONS; ++s) + if (report_stored_position(s)) ++count; if (!count) SERIAL_ECHOLNPGM("No Saved Positions"); return; } @@ -90,6 +93,7 @@ void GcodeSuite::G60() { // G60 Dn if (seenD) { + SERIAL_ECHOLNPGM(STR_SAVED_POSITION, slot, ": DELETED"); did_save_position.clear(slot); return; } @@ -97,26 +101,7 @@ void GcodeSuite::G60() { // G60 S stored_position[slot] = current_position; did_save_position.set(slot); - - #if ENABLED(SAVED_POSITIONS_DEBUG) - { - const xyze_pos_t &pos = stored_position[slot]; - DEBUG_ECHO(STR_SAVED_POS, slot, C(':')); - #if NUM_AXES - DEBUG_ECHOPGM_P( - LIST_N(DOUBLE(NUM_AXES), - SP_X_LBL, pos.x, SP_Y_LBL, pos.y, SP_Z_LBL, pos.z, - SP_I_LBL, pos.i, SP_J_LBL, pos.j, SP_K_LBL, pos.k, - SP_U_LBL, pos.u, SP_V_LBL, pos.v, SP_W_LBL, pos.w - ) - ); - #endif - #if HAS_EXTRUDERS - DEBUG_ECHOPGM_P(SP_E_LBL, pos.e); - #endif - DEBUG_EOL(); - } - #endif + report_stored_position(slot); } #endif // SAVED_POSITIONS diff --git a/Marlin/src/gcode/feature/pause/G61.cpp b/Marlin/src/gcode/feature/pause/G61.cpp index 42daa6dd50d6..08b4a99b7de5 100644 --- a/Marlin/src/gcode/feature/pause/G61.cpp +++ b/Marlin/src/gcode/feature/pause/G61.cpp @@ -77,7 +77,7 @@ void GcodeSuite::G61(int8_t slot/*=-1*/) { float epos = stored_position[slot].e; if (!parser.seen_axis()) { - DEBUG_ECHOLNPGM(STR_RESTORING_POS " (all axes)"); + DEBUG_ECHOLNPGM(STR_RESTORING_POSITION, slot, " (all axes)"); // Move to the saved position, all axes except E do_blocking_move_to(stored_position[slot], feedrate_mm_s); // Just set E to the saved position without moving it @@ -88,7 +88,7 @@ void GcodeSuite::G61(int8_t slot/*=-1*/) { // With XYZ...E return specified axes + optional offset - DEBUG_ECHOPGM(STR_RESTORING_POS " S", slot); + DEBUG_ECHOPGM(STR_RESTORING_POSITION " S", slot); if (parser.seen(STR_AXES_MAIN)) { destination = current_position;