🧑‍💻 General and Axis-based bitfield flags (#23989)

This commit is contained in:
Scott Lahteine 2022-04-03 16:14:02 -05:00 committed by Scott Lahteine
parent d5f472a6cf
commit d235bc9e1c
14 changed files with 106 additions and 51 deletions

View file

@ -66,6 +66,59 @@ struct IF<true, L, R> { typedef L type; };
#define AXIS_COLLISION(L) (AXIS4_NAME == L || AXIS5_NAME == L || AXIS6_NAME == L)
// General Flags for some number of states
template<size_t N>
struct Flags {
typedef typename IF<(N>8), uint16_t, uint8_t>::type bits_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;
union {
bits_t b;
typename IF<(N>8), N16, N8>::type flag;
};
void reset() { b = 0; }
void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); }
void set(const int n) { b |= (bits_t)_BV(n); }
void clear(const int n) { b &= ~(bits_t)_BV(n); }
bool test(const int n) const { return TEST(b, n); }
bool operator[](const int n) { return test(n); }
const bool operator[](const int n) const { return test(n); }
const int size() const { return sizeof(b); }
};
// Specialization for a single bool flag
template<>
struct Flags<1> {
bool b;
void reset() { b = false; }
void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); }
void set(const int) { b = true; }
void clear(const int) { b = false; }
bool test(const int) const { return b; }
bool operator[](const int) { return b; }
const bool operator[](const int) const { return b; }
const int size() const { return sizeof(b); }
};
typedef Flags<8> flags_8_t;
typedef Flags<16> flags_16_t;
// Flags for some axis states, with per-axis aliases xyzijkuvwe
typedef struct AxisFlags {
union {
struct Flags<LOGICAL_AXES> flags;
struct { bool LOGICAL_AXIS_LIST(e:1, x:1, y:1, z:1, i:1, j:1, k:1, u:1, v:1, w:1); };
};
void reset() { flags.reset(); }
void set(const int n) { flags.set(n); }
void set(const int n, const bool onoff) { flags.set(n, onoff); }
void clear(const int n) { flags.clear(n); }
bool test(const int n) const { return flags.test(n); }
bool operator[](const int n) { return flags[n]; }
const bool operator[](const int n) const { return flags[n]; }
const int size() const { return sizeof(flags); }
} axis_flags_t;
//
// Enumerated axis indices
//

View file

@ -34,7 +34,7 @@
#if HAS_AUTO_FAN && EXTRUDER_AUTO_FAN_SPEED != 255 && DISABLED(FOURWIRES_FANS)
bool FanCheck::measuring = false;
#endif
bool FanCheck::tacho_state[TACHO_COUNT];
Flags<TACHO_COUNT> FanCheck::tacho_state;
uint16_t FanCheck::edge_counter[TACHO_COUNT];
uint8_t FanCheck::rps[TACHO_COUNT];
FanCheck::TachoError FanCheck::error = FanCheck::TachoError::NONE;
@ -103,7 +103,7 @@ void FanCheck::update_tachometers() {
if (status != tacho_state[f]) {
if (measuring) ++edge_counter[f];
tacho_state[f] = status;
tacho_state.set(f, status);
}
}
}

View file

@ -51,7 +51,7 @@ class FanCheck {
#else
static constexpr bool measuring = true;
#endif
static bool tacho_state[TACHO_COUNT];
static Flags<TACHO_COUNT> tacho_state;
static uint16_t edge_counter[TACHO_COUNT];
static uint8_t rps[TACHO_COUNT];
static TachoError error;

View file

@ -45,7 +45,7 @@ FWRetract fwretract; // Single instance - this calls the constructor
// private:
#if HAS_MULTI_EXTRUDER
bool FWRetract::retracted_swap[EXTRUDERS]; // Which extruders are swap-retracted
Flags<EXTRUDERS> FWRetract::retracted_swap; // Which extruders are swap-retracted
#endif
// public:
@ -56,7 +56,7 @@ fwretract_settings_t FWRetract::settings; // M207 S F Z W, M208 S F
bool FWRetract::autoretract_enabled; // M209 S - Autoretract switch
#endif
bool FWRetract::retracted[EXTRUDERS]; // Which extruders are currently retracted
Flags<EXTRUDERS> FWRetract::retracted; // Which extruders are currently retracted
float FWRetract::current_retract[EXTRUDERS], // Retract value used by planner
FWRetract::current_hop;
@ -73,9 +73,9 @@ void FWRetract::reset() {
settings.swap_retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE_SWAP;
current_hop = 0.0;
retracted.reset();
EXTRUDER_LOOP() {
retracted[e] = false;
E_TERN_(retracted_swap[e] = false);
E_TERN_(retracted_swap.clear(e));
current_retract[e] = 0.0;
}
}
@ -173,11 +173,11 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/))
TERN_(RETRACT_SYNC_MIXING, mixer.T(old_mixing_tool)); // Restore original mixing tool
retracted[active_extruder] = retracting; // Active extruder now retracted / recovered
retracted.set(active_extruder, retracting); // Active extruder now retracted / recovered
// If swap retract/recover update the retracted_swap flag too
#if HAS_MULTI_EXTRUDER
if (swapping) retracted_swap[active_extruder] = retracting;
if (swapping) retracted_swap.set(active_extruder, retracting);
#endif
/* // debugging

View file

@ -43,7 +43,7 @@ typedef struct {
class FWRetract {
private:
#if HAS_MULTI_EXTRUDER
static bool retracted_swap[EXTRUDERS]; // Which extruders are swap-retracted
static Flags<EXTRUDERS> retracted_swap; // Which extruders are swap-retracted
#endif
public:
@ -55,7 +55,7 @@ public:
static constexpr bool autoretract_enabled = false;
#endif
static bool retracted[EXTRUDERS]; // Which extruders are currently retracted
static Flags<EXTRUDERS> retracted; // Which extruders are currently retracted
static float current_retract[EXTRUDERS], // Retract value used by planner
current_hop; // Hop value used by planner
@ -63,9 +63,7 @@ public:
static void reset();
static void refresh_autoretract() {
EXTRUDER_LOOP() retracted[e] = false;
}
static void refresh_autoretract() { retracted.reset(); }
static void enable_autoretract(const bool enable) {
#if ENABLED(FWRETRACT_AUTORETRACT)

View file

@ -519,7 +519,7 @@ void PrintJobRecovery::resume() {
EXTRUDER_LOOP() {
if (info.retract[e] != 0.0) {
fwretract.current_retract[e] = info.retract[e];
fwretract.retracted[e] = true;
fwretract.retracted.set(e);
}
}
fwretract.current_hop = info.retract_hop;

View file

@ -33,8 +33,8 @@
#include "../../core/debug_out.h"
#include "../../libs/hex_print.h"
inline axis_flags_t selected_axis_bits() {
axis_flags_t selected{0};
inline stepper_flags_t selected_axis_bits() {
stepper_flags_t selected{0};
#if HAS_EXTRUDERS
if (parser.seen('E')) {
if (E_TERN0(parser.has_value())) {
@ -58,7 +58,7 @@ inline axis_flags_t selected_axis_bits() {
}
// Enable specified axes and warn about other affected axes
void do_enable(const axis_flags_t to_enable) {
void do_enable(const stepper_flags_t to_enable) {
const ena_mask_t was_enabled = stepper.axis_enabled.bits,
shall_enable = to_enable.bits & ~was_enabled;
@ -141,7 +141,7 @@ void GcodeSuite::M17() {
}
}
void try_to_disable(const axis_flags_t to_disable) {
void try_to_disable(const stepper_flags_t to_disable) {
ena_mask_t still_enabled = to_disable.bits & stepper.axis_enabled.bits;
DEBUG_ECHOLNPGM("Enabled: ", hex_word(stepper.axis_enabled.bits), " To Disable: ", hex_word(to_disable.bits), " | ", hex_word(still_enabled));

View file

@ -44,7 +44,7 @@
#include "../../core/debug_out.h"
static float z_measured[G35_PROBE_COUNT];
static bool z_isvalid[G35_PROBE_COUNT];
static Flags<G35_PROBE_COUNT> z_isvalid;
static uint8_t tram_index = 0;
static int8_t reference_index; // = 0
@ -61,7 +61,10 @@ static bool probe_single_point() {
move_to_tramming_wait_pos();
DEBUG_ECHOLNPGM("probe_single_point(", tram_index, ") = ", z_probed_height, "mm");
return (z_isvalid[tram_index] = !isnan(z_probed_height));
const bool v = !isnan(z_probed_height);
z_isvalid.set(tram_index, v);
return v;
}
static void _menu_single_probe() {
@ -95,7 +98,7 @@ void goto_tramming_wizard() {
ui.defer_status_screen();
// Initialize measured point flags
ZERO(z_isvalid);
z_isvalid.reset();
reference_index = -1;
// Inject G28, wait for homing to complete,

View file

@ -178,11 +178,12 @@
#endif
#define _EN_ITEM(N) , E##N
#define _EN1_ITEM(N) , E##N:1
typedef struct { uint16_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_stepper_current_t;
typedef struct { uint32_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_hybrid_threshold_t;
typedef struct { int16_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4; } tmc_sgt_t;
typedef struct { bool LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_stealth_enabled_t;
typedef struct { uint16_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } per_stepper_uint16_t;
typedef struct { uint32_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } per_stepper_uint32_t;
typedef struct { int16_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4; } mot_stepper_int16_t;
typedef struct { bool LINEAR_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1), X2:1, Y2:1, Z2:1, Z3:1, Z4:1 REPEAT(E_STEPPERS, _EN1_ITEM); } per_stepper_bool_t;
#undef _EN_ITEM
@ -430,10 +431,10 @@ typedef struct SettingsDataStruct {
//
// HAS_TRINAMIC_CONFIG
//
tmc_stepper_current_t tmc_stepper_current; // M906 X Y Z...
tmc_hybrid_threshold_t tmc_hybrid_threshold; // M913 X Y Z...
tmc_sgt_t tmc_sgt; // M914 X Y Z...
tmc_stealth_enabled_t tmc_stealth_enabled; // M569 X Y Z...
per_stepper_uint16_t tmc_stepper_current; // M906 X Y Z...
per_stepper_uint32_t tmc_hybrid_threshold; // M913 X Y Z...
mot_stepper_int16_t tmc_sgt; // M914 X Y Z...
per_stepper_bool_t tmc_stealth_enabled; // M569 X Y Z...
//
// LIN_ADVANCE
@ -1213,7 +1214,7 @@ void MarlinSettings::postprocess() {
{
_FIELD_TEST(tmc_stepper_current);
tmc_stepper_current_t tmc_stepper_current{0};
per_stepper_uint16_t tmc_stepper_current{0};
#if HAS_TRINAMIC_CONFIG
#if AXIS_IS_TMC(X)
@ -1284,7 +1285,7 @@ void MarlinSettings::postprocess() {
_FIELD_TEST(tmc_hybrid_threshold);
#if ENABLED(HYBRID_THRESHOLD)
tmc_hybrid_threshold_t tmc_hybrid_threshold{0};
per_stepper_uint32_t tmc_hybrid_threshold{0};
TERN_(X_HAS_STEALTHCHOP, tmc_hybrid_threshold.X = stepperX.get_pwm_thrs());
TERN_(Y_HAS_STEALTHCHOP, tmc_hybrid_threshold.Y = stepperY.get_pwm_thrs());
TERN_(Z_HAS_STEALTHCHOP, tmc_hybrid_threshold.Z = stepperZ.get_pwm_thrs());
@ -1306,7 +1307,7 @@ void MarlinSettings::postprocess() {
TERN_(E7_HAS_STEALTHCHOP, tmc_hybrid_threshold.E7 = stepperE7.get_pwm_thrs());
#else
#define _EN_ITEM(N) , .E##N = 30
const tmc_hybrid_threshold_t tmc_hybrid_threshold = {
const per_stepper_uint32_t tmc_hybrid_threshold = {
LINEAR_AXIS_LIST(.X = 100, .Y = 100, .Z = 3, .I = 3, .J = 3, .K = 3),
.X2 = 100, .Y2 = 100, .Z2 = 3, .Z3 = 3, .Z4 = 3
REPEAT(E_STEPPERS, _EN_ITEM)
@ -1320,7 +1321,7 @@ void MarlinSettings::postprocess() {
// TMC StallGuard threshold
//
{
tmc_sgt_t tmc_sgt{0};
mot_stepper_int16_t tmc_sgt{0};
#if USE_SENSORLESS
LINEAR_AXIS_CODE(
TERN_(X_SENSORLESS, tmc_sgt.X = stepperX.homing_threshold()),
@ -1345,7 +1346,7 @@ void MarlinSettings::postprocess() {
{
_FIELD_TEST(tmc_stealth_enabled);
tmc_stealth_enabled_t tmc_stealth_enabled = { false };
per_stepper_bool_t tmc_stealth_enabled = { false };
TERN_(X_HAS_STEALTHCHOP, tmc_stealth_enabled.X = stepperX.get_stored_stealthChop());
TERN_(Y_HAS_STEALTHCHOP, tmc_stealth_enabled.Y = stepperY.get_stored_stealthChop());
TERN_(Z_HAS_STEALTHCHOP, tmc_stealth_enabled.Z = stepperZ.get_stored_stealthChop());
@ -2135,7 +2136,7 @@ void MarlinSettings::postprocess() {
{
_FIELD_TEST(tmc_stepper_current);
tmc_stepper_current_t currents;
per_stepper_uint16_t currents;
EEPROM_READ(currents);
#if HAS_TRINAMIC_CONFIG
@ -2205,7 +2206,7 @@ void MarlinSettings::postprocess() {
// TMC Hybrid Threshold
{
tmc_hybrid_threshold_t tmc_hybrid_threshold;
per_stepper_uint32_t tmc_hybrid_threshold;
_FIELD_TEST(tmc_hybrid_threshold);
EEPROM_READ(tmc_hybrid_threshold);
@ -2238,7 +2239,7 @@ void MarlinSettings::postprocess() {
// TMC StallGuard threshold.
//
{
tmc_sgt_t tmc_sgt;
mot_stepper_int16_t tmc_sgt;
_FIELD_TEST(tmc_sgt);
EEPROM_READ(tmc_sgt);
#if USE_SENSORLESS
@ -2264,7 +2265,7 @@ void MarlinSettings::postprocess() {
{
_FIELD_TEST(tmc_stealth_enabled);
tmc_stealth_enabled_t tmc_stealth_enabled;
per_stepper_bool_t tmc_stealth_enabled;
EEPROM_READ(tmc_stealth_enabled);
#if HAS_TRINAMIC_CONFIG

View file

@ -153,7 +153,7 @@ Stepper stepper; // Singleton
#endif
#endif
axis_flags_t Stepper::axis_enabled; // {0}
stepper_flags_t Stepper::axis_enabled; // {0}
// private:

View file

@ -252,7 +252,7 @@ typedef struct {
};
constexpr ena_mask_t linear_bits() { return _BV(LINEAR_AXES) - 1; }
constexpr ena_mask_t e_bits() { return (_BV(EXTRUDERS) - 1) << LINEAR_AXES; }
} axis_flags_t;
} stepper_flags_t;
// All the stepper enable pins
constexpr pin_t ena_pins[] = {
@ -587,7 +587,7 @@ class Stepper {
static void refresh_motor_power();
#endif
static axis_flags_t axis_enabled; // Axis stepper(s) ENABLED states
static stepper_flags_t axis_enabled; // Axis stepper(s) ENABLED states
static bool axis_is_enabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
return TEST(axis_enabled.bits, INDEX_OF_AXIS(axis, eindex));

View file

@ -1092,7 +1092,7 @@ void Temperature::min_temp_error(const heater_id_t heater_id) {
static hotend_pid_t work_pid[HOTENDS];
static float temp_iState[HOTENDS] = { 0 },
temp_dState[HOTENDS] = { 0 };
static bool pid_reset[HOTENDS] = { false };
static Flags<HOTENDS> pid_reset;
const float pid_error = temp_hotend[ee].target - temp_hotend[ee].celsius;
float pid_output;
@ -1102,17 +1102,17 @@ void Temperature::min_temp_error(const heater_id_t heater_id) {
|| TERN0(HEATER_IDLE_HANDLER, heater_idle[ee].timed_out)
) {
pid_output = 0;
pid_reset[ee] = true;
pid_reset.set(ee);
}
else if (pid_error > PID_FUNCTIONAL_RANGE) {
pid_output = BANG_MAX;
pid_reset[ee] = true;
pid_reset.set(ee);
}
else {
if (pid_reset[ee]) {
temp_iState[ee] = 0.0;
work_pid[ee].Kd = 0.0;
pid_reset[ee] = false;
pid_reset.clear(ee);
}
work_pid[ee].Kd = work_pid[ee].Kd + PID_K2 * (PID_PARAM(Kd, ee) * (temp_dState[ee] - temp_hotend[ee].celsius) - work_pid[ee].Kd);

View file

@ -46,7 +46,7 @@
#endif
#if ENABLED(TOOLCHANGE_FS_INIT_BEFORE_SWAP)
bool toolchange_extruder_ready[EXTRUDERS];
Flags<EXTRUDERS> toolchange_extruder_ready;
#endif
#if EITHER(MAGNETIC_PARKING_EXTRUDER, TOOL_SENSOR) \
@ -1047,7 +1047,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
if (new_tool == old_tool && !first_tool_is_primed && enable_first_prime) {
tool_change_prime();
first_tool_is_primed = true;
TERN_(TOOLCHANGE_FS_INIT_BEFORE_SWAP, toolchange_extruder_ready[old_tool] = true); // Primed and initialized
TERN_(TOOLCHANGE_FS_INIT_BEFORE_SWAP, toolchange_extruder_ready.set(old_tool)); // Primed and initialized
}
#endif
@ -1196,7 +1196,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
#if ENABLED(TOOLCHANGE_FS_INIT_BEFORE_SWAP)
if (!toolchange_extruder_ready[new_tool]) {
toolchange_extruder_ready[new_tool] = true;
toolchange_extruder_ready.set(new_tool);
fr = toolchange_settings.prime_speed; // Next move is a prime
unscaled_e_move(0, MMM_TO_MMS(fr)); // Init planner with 0 length move
}
@ -1381,7 +1381,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
// Migrate the retracted state
#if ENABLED(FWRETRACT)
fwretract.retracted[migration_extruder] = fwretract.retracted[active_extruder];
fwretract.retracted.set(migration_extruder, fwretract.retracted[active_extruder]);
#endif
// Migrate the temperature to the new hotend

View file

@ -50,7 +50,7 @@
#endif
#if ENABLED(TOOLCHANGE_FS_INIT_BEFORE_SWAP)
extern bool toolchange_extruder_ready[EXTRUDERS];
extern Flags<EXTRUDERS> toolchange_extruder_ready;
#endif
#if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)