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

🧑‍💻 MAP macro for axis lists, etc. #24191

Merged
merged 1 commit into from
May 22, 2022
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
29 changes: 19 additions & 10 deletions Marlin/src/core/macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -712,13 +712,22 @@
#define RREPEAT2_S(S,N,OP,V...) EVAL1024(_RREPEAT2(S,SUB##S(N),OP,V))
#define RREPEAT2(N,OP,V...) RREPEAT2_S(0,N,OP,V)

// See https://github.com/swansontec/map-macro
#define MAP_OUT
#define MAP_END(...)
#define MAP_GET_END() 0, MAP_END
#define MAP_NEXT0(test, next, ...) next MAP_OUT
#define MAP_NEXT1(test, next) MAP_NEXT0 (test, next, 0)
#define MAP_NEXT(test, next) MAP_NEXT1 (MAP_GET_END test, next)
#define MAP0(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP1) (f, peek, __VA_ARGS__)
#define MAP1(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP0) (f, peek, __VA_ARGS__)
#define MAP(f, ...) EVAL512 (MAP1 (f, __VA_ARGS__, (), 0))
// Call OP(A) with each item as an argument
#define _MAP(_MAP_OP,A,V...) \
_MAP_OP(A) \
IF_ELSE(HAS_ARGS(V)) \
( DEFER2(__MAP)()(_MAP_OP,V) ) \
( /* Do nothing */ )
#define __MAP() _MAP

#define MAP(OP,V...) EVAL(_MAP(OP,V))

// Emit a list of OP(A) with the given items
#define _MAPLIST(_MAP_OP,A,V...) \
_MAP_OP(A) \
IF_ELSE(HAS_ARGS(V)) \
( , DEFER2(__MAPLIST)()(_MAP_OP,V) ) \
( /* Do nothing */ )
#define __MAPLIST() _MAPLIST

#define MAPLIST(OP,V...) EVAL(_MAPLIST(OP,V))
8 changes: 8 additions & 0 deletions Marlin/src/core/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,26 @@ struct IF<true, L, R> { typedef L type; };
#define NUM_AXIS_GANG(V...) GANG_N(NUM_AXES, V)
#define NUM_AXIS_CODE(V...) CODE_N(NUM_AXES, V)
#define NUM_AXIS_LIST(V...) LIST_N(NUM_AXES, V)
#define NUM_AXIS_LIST_1(V) LIST_N_1(NUM_AXES, V)
#define NUM_AXIS_ARRAY(V...) { NUM_AXIS_LIST(V) }
#define NUM_AXIS_ARRAY_1(V) { NUM_AXIS_LIST_1(V) }
#define NUM_AXIS_ARGS(T...) NUM_AXIS_LIST(T x, T y, T z, T i, T j, T k, T u, T v, T w)
#define NUM_AXIS_ELEM(O) NUM_AXIS_LIST(O.x, O.y, O.z, O.i, O.j, O.k, O.u, O.v, O.w)
#define NUM_AXIS_DEFS(T,V) NUM_AXIS_LIST(T x=V, T y=V, T z=V, T i=V, T j=V, T k=V, T u=V, T v=V, T w=V)
#define MAIN_AXIS_NAMES NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W)
#define MAIN_AXIS_MAP(F) MAP(F, MAIN_AXIS_NAMES)

#define LOGICAL_AXIS_GANG(E,V...) NUM_AXIS_GANG(V) GANG_ITEM_E(E)
#define LOGICAL_AXIS_CODE(E,V...) NUM_AXIS_CODE(V) CODE_ITEM_E(E)
#define LOGICAL_AXIS_LIST(E,V...) NUM_AXIS_LIST(V) LIST_ITEM_E(E)
#define LOGICAL_AXIS_LIST_1(V) NUM_AXIS_LIST_1(V) LIST_ITEM_E(V)
#define LOGICAL_AXIS_ARRAY(E,V...) { LOGICAL_AXIS_LIST(E,V) }
#define LOGICAL_AXIS_ARRAY_1(V) { LOGICAL_AXIS_LIST_1(V) }
#define LOGICAL_AXIS_ARGS(T...) LOGICAL_AXIS_LIST(T e, T x, T y, T z, T i, T j, T k, T u, T v, T w)
#define LOGICAL_AXIS_ELEM(O) LOGICAL_AXIS_LIST(O.e, O.x, O.y, O.z, O.i, O.j, O.k, O.u, O.v, O.w)
#define LOGICAL_AXIS_DECL(T,V) LOGICAL_AXIS_LIST(T e=V, T x=V, T y=V, T z=V, T i=V, T j=V, T k=V, T u=V, T v=V, T w=V)
#define LOGICAL_AXIS_NAMES LOGICAL_AXIS_LIST(E, X, Y, Z, I, J, K, U, V, W)
#define LOGICAL_AXIS_MAP(F) MAP(F, LOGICAL_AXIS_NAMES)

#define LOGICAL_AXES_STRING LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)

Expand Down
2 changes: 0 additions & 2 deletions Marlin/src/feature/spindle_laser.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@
#define PCT_TO_PWM(X) ((X) * 255 / 100)
#define PCT_TO_SERVO(X) ((X) * 180 / 100)

// #define _MAP(N,S1,S2,D1,D2) ((N)*_MAX((D2)-(D1),0)/_MAX((S2)-(S1),1)+(D1))

class SpindleLaser {
public:
static const inline uint8_t pct_to_ocr(const_float_t pct) { return uint8_t(PCT_TO_PWM(pct)); }
Expand Down
13 changes: 2 additions & 11 deletions Marlin/src/gcode/calibrate/M425.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,10 @@ void GcodeSuite::M425() {
bool noArgs = true;

auto axis_can_calibrate = [](const uint8_t a) {
#define _CAN_CASE(N) case N##_AXIS: return AXIS_CAN_CALIBRATE(N);
switch (a) {
default: return false;
NUM_AXIS_CODE(
case X_AXIS: return AXIS_CAN_CALIBRATE(X),
case Y_AXIS: return AXIS_CAN_CALIBRATE(Y),
case Z_AXIS: return AXIS_CAN_CALIBRATE(Z),
case I_AXIS: return AXIS_CAN_CALIBRATE(I),
case J_AXIS: return AXIS_CAN_CALIBRATE(J),
case K_AXIS: return AXIS_CAN_CALIBRATE(K),
case U_AXIS: return AXIS_CAN_CALIBRATE(U),
case V_AXIS: return AXIS_CAN_CALIBRATE(V),
case W_AXIS: return AXIS_CAN_CALIBRATE(W)
);
MAIN_AXIS_MAP(_CAN_CASE)
}
};

Expand Down
28 changes: 11 additions & 17 deletions Marlin/src/lcd/menu/menu_advanced.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ void menu_backlash();
LOOP_LOGICAL_AXES(i) driverPercent[i] = stepper_dac.get_current_percent((AxisEnum)i);
START_MENU();
BACK_ITEM(MSG_ADVANCED_SETTINGS);
#define EDIT_DAC_PERCENT(A) EDIT_ITEM(uint8, MSG_DAC_PERCENT_##A, &driverPercent[_AXIS(A)], 0, 100, []{ stepper_dac.set_current_percents(driverPercent); })
LOGICAL_AXIS_CODE(EDIT_DAC_PERCENT(E), EDIT_DAC_PERCENT(A), EDIT_DAC_PERCENT(B), EDIT_DAC_PERCENT(C), EDIT_DAC_PERCENT(I), EDIT_DAC_PERCENT(J), EDIT_DAC_PERCENT(K), EDIT_DAC_PERCENT(U), EDIT_DAC_PERCENT(V), EDIT_DAC_PERCENT(W));
#define EDIT_DAC_PERCENT(A) EDIT_ITEM(uint8, MSG_DAC_PERCENT_##A, &driverPercent[_AXIS(A)], 0, 100, []{ stepper_dac.set_current_percents(driverPercent); });
MAP(EDIT_DAC_PERCENT, LOGICAL_AXIS_LIST(E, A, B, C, I, J, K, U, V, W));
ACTION_ITEM(MSG_DAC_EEPROM_WRITE, stepper_dac.commit_eeprom);
END_MENU();
}
Expand Down Expand Up @@ -415,7 +415,7 @@ void menu_backlash();
#elif ENABLED(LIMITED_MAX_FR_EDITING)
DEFAULT_MAX_FEEDRATE
#else
LOGICAL_AXIS_ARRAY(9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999)
LOGICAL_AXIS_ARRAY_1(9999)
#endif
;
#if ENABLED(LIMITED_MAX_FR_EDITING) && !defined(MAX_FEEDRATE_EDIT_VALUES)
Expand All @@ -427,8 +427,8 @@ void menu_backlash();
START_MENU();
BACK_ITEM(MSG_ADVANCED_SETTINGS);

#define EDIT_VMAX(N) EDIT_ITEM_FAST(float5, MSG_VMAX_##N, &planner.settings.max_feedrate_mm_s[_AXIS(N)], 1, max_fr_edit_scaled[_AXIS(N)])
NUM_AXIS_CODE(EDIT_VMAX(A), EDIT_VMAX(B), EDIT_VMAX(C), EDIT_VMAX(I), EDIT_VMAX(J), EDIT_VMAX(K), EDIT_VMAX(U), EDIT_VMAX(V), EDIT_VMAX(W));
#define EDIT_VMAX(N) EDIT_ITEM_FAST(float5, MSG_VMAX_##N, &planner.settings.max_feedrate_mm_s[_AXIS(N)], 1, max_fr_edit_scaled[_AXIS(N)]);
MAP(EDIT_VMAX, NUM_AXIS_LIST(A, B, C, I, J, K, U, V, W));

#if E_STEPPERS
EDIT_ITEM_FAST(float5, MSG_VMAX_E, &planner.settings.max_feedrate_mm_s[E_AXIS_N(active_extruder)], 1, max_fr_edit_scaled.e);
Expand Down Expand Up @@ -458,7 +458,7 @@ void menu_backlash();
#elif ENABLED(LIMITED_MAX_ACCEL_EDITING)
DEFAULT_MAX_ACCELERATION
#else
LOGICAL_AXIS_ARRAY(99000, 99000, 99000, 99000, 99000, 99000, 99000, 99000, 99000, 99000)
LOGICAL_AXIS_ARRAY_1(99000)
#endif
;
#if ENABLED(LIMITED_MAX_ACCEL_EDITING) && !defined(MAX_ACCEL_EDIT_VALUES)
Expand Down Expand Up @@ -526,12 +526,10 @@ void menu_backlash();
#ifdef MAX_JERK_EDIT_VALUES
MAX_JERK_EDIT_VALUES
#elif ENABLED(LIMITED_JERK_EDITING)
{ LOGICAL_AXIS_LIST((DEFAULT_EJERK) * 2,
(DEFAULT_XJERK) * 2, (DEFAULT_YJERK) * 2, (DEFAULT_ZJERK) * 2,
(DEFAULT_IJERK) * 2, (DEFAULT_JJERK) * 2, (DEFAULT_KJERK) * 2,
(DEFAULT_UJERK) * 2, (DEFAULT_VJERK) * 2, (DEFAULT_WJERK) * 2) }
#define _JERK2(N) DEFAULT_##N##JERK * 2
{ MAPLIST(_JERK2, LOGICAL_AXIS_NAMES) }
#else
{ LOGICAL_AXIS_LIST(990, 990, 990, 990, 990, 990, 990, 990, 990, 990) }
LOGICAL_AXIS_ARRAY_1(990)
#endif
;
#define EDIT_JERK(N) EDIT_ITEM_FAST(float3, MSG_V##N##_JERK, &planner.max_jerk[_AXIS(N)], 1, max_jerk_edit[_AXIS(N)])
Expand Down Expand Up @@ -585,12 +583,8 @@ void menu_advanced_steps_per_mm() {
START_MENU();
BACK_ITEM(MSG_ADVANCED_SETTINGS);

#define EDIT_QSTEPS(Q) EDIT_ITEM_FAST(float61, MSG_##Q##_STEPS, &planner.settings.axis_steps_per_mm[_AXIS(Q)], 5, 9999, []{ planner.refresh_positioning(); })
NUM_AXIS_CODE(
EDIT_QSTEPS(A), EDIT_QSTEPS(B), EDIT_QSTEPS(C),
EDIT_QSTEPS(I), EDIT_QSTEPS(J), EDIT_QSTEPS(K),
EDIT_QSTEPS(U), EDIT_QSTEPS(V), EDIT_QSTEPS(W)
);
#define EDIT_QSTEPS(Q) EDIT_ITEM_FAST(float61, MSG_##Q##_STEPS, &planner.settings.axis_steps_per_mm[_AXIS(Q)], 5, 9999, []{ planner.refresh_positioning(); });
MAP(EDIT_QSTEPS, NUM_AXIS_LIST(A, B, C, I, J, K, U, V, W));

#if ENABLED(DISTINCT_E_FACTORS)
LOOP_L_N(n, E_STEPPERS)
Expand Down
5 changes: 2 additions & 3 deletions Marlin/src/lcd/menu/menu_motion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,8 @@ void _menu_move_distance(const AxisEnum axis, const screenFunc_t func, const int
START_MENU();
if (LCD_HEIGHT >= 4) {
switch (axis) {
case X_AXIS: STATIC_ITEM(MSG_MOVE_X, SS_DEFAULT|SS_INVERT); break;
case Y_AXIS: STATIC_ITEM(MSG_MOVE_Y, SS_DEFAULT|SS_INVERT); break;
case Z_AXIS: STATIC_ITEM(MSG_MOVE_Z, SS_DEFAULT|SS_INVERT); break;
#define _CASE_MOVE(N) case N##_AXIS: STATIC_ITEM(MSG_MOVE_##N, SS_DEFAULT|SS_INVERT); break;
MAIN_AXIS_MAP(_CASE_MOVE)
default:
TERN_(MANUAL_E_MOVES_RELATIVE, manual_move_e_origin = current_position.e);
STATIC_ITEM(MSG_MOVE_E, SS_DEFAULT|SS_INVERT);
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/libs/L64XX/L64XX_Marlin.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
#define HAS_L64XX_EXTRUDER (AXIS_IS_L64XX(E0) || AXIS_IS_L64XX(E1) || AXIS_IS_L64XX(E2) || AXIS_IS_L64XX(E3) || AXIS_IS_L64XX(E4) || AXIS_IS_L64XX(E5) || AXIS_IS_L64XX(E6) || AXIS_IS_L64XX(E7))

#define _EN_ITEM(N) , E##N
enum L64XX_axis_t : uint8_t { NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM), MAX_L64XX };
enum L64XX_axis_t : uint8_t { MAIN_AXIS_NAMES, X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM), MAX_L64XX };
#undef _EN_ITEM

class L64XX_Marlin : public L64XXHelper {
Expand Down
19 changes: 6 additions & 13 deletions Marlin/src/module/motion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,10 +738,12 @@ void restore_feedrate_and_scaling() {
#if HAS_SOFTWARE_ENDSTOPS

// Software Endstops are based on the configured limits.
#define _AMIN(A) A##_MIN_POS
#define _AMAX(A) A##_MAX_POS
soft_endstops_t soft_endstop = {
true, false,
NUM_AXIS_ARRAY(X_MIN_POS, Y_MIN_POS, Z_MIN_POS, I_MIN_POS, J_MIN_POS, K_MIN_POS, U_MIN_POS, V_MIN_POS, W_MIN_POS),
NUM_AXIS_ARRAY(X_MAX_BED, Y_MAX_BED, Z_MAX_POS, I_MAX_POS, J_MAX_POS, K_MAX_POS, U_MAX_POS, V_MAX_POS, W_MAX_POS)
{ MAPLIST(_AMIN, MAIN_AXIS_NAMES) },
{ MAPLIST(_AMAX, MAIN_AXIS_NAMES) },
};

/**
Expand Down Expand Up @@ -1877,17 +1879,8 @@ void prepare_line_to_destination() {
|| TERN0(A##_HOME_TO_MIN, A##_MIN_PIN > -1) \
|| TERN0(A##_HOME_TO_MAX, A##_MAX_PIN > -1) \
))
if (NUM_AXIS_GANG(
!_CAN_HOME(X),
&& !_CAN_HOME(Y),
&& !_CAN_HOME(Z),
&& !_CAN_HOME(I),
&& !_CAN_HOME(J),
&& !_CAN_HOME(K),
&& !_CAN_HOME(U),
&& !_CAN_HOME(V),
&& !_CAN_HOME(W))
) return;
#define _ANDCANT(N) && !_CAN_HOME(N)
if (true MAIN_AXIS_MAP(_ANDCANT)) return;
#endif

if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM(">>> homeaxis(", AS_CHAR(AXIS_CHAR(axis)), ")");
Expand Down
6 changes: 4 additions & 2 deletions Marlin/src/module/probe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -899,8 +899,10 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
* Change the current in the TMC drivers to N##_CURRENT_HOME. And we save the current configuration of each TMC driver.
*/
void Probe::set_homing_current(const bool onoff) {
#define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT)
#if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Z) || HAS_CURRENT_HOME(I) || HAS_CURRENT_HOME(J) || HAS_CURRENT_HOME(K) || HAS_CURRENT_HOME(U) || HAS_CURRENT_HOME(V) || HAS_CURRENT_HOME(W)
#define _defined(N) defined(N)
#define HAS_CURRENT_HOME(N) (N##_CURRENT_HOME > 0 && N##_CURRENT_HOME != N##_CURRENT)
#define _HOME_ELEM(N) HAS_CURRENT_HOME(N) ||
#if MAIN_AXIS_MAP(_HOME_ELEM) 0
#if ENABLED(DELTA)
static int16_t saved_current_X, saved_current_Y;
#endif
Expand Down
6 changes: 3 additions & 3 deletions Marlin/src/module/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,9 @@
#define _EN_ITEM(N) , E##N
#define _EN1_ITEM(N) , E##N:1

typedef struct { uint16_t NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } per_stepper_uint16_t;
typedef struct { uint32_t NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } per_stepper_uint32_t;
typedef struct { int16_t NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4; } mot_stepper_int16_t;
typedef struct { uint16_t MAIN_AXIS_NAMES, X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } per_stepper_uint16_t;
typedef struct { uint32_t MAIN_AXIS_NAMES, X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } per_stepper_uint32_t;
typedef struct { int16_t MAIN_AXIS_NAMES, X2, Y2, Z2, Z3, Z4; } mot_stepper_int16_t;
typedef struct { bool NUM_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1, U:1, V:1, W:1), X2:1, Y2:1, Z2:1, Z3:1, Z4:1 REPEAT(E_STEPPERS, _EN1_ITEM); } per_stepper_bool_t;

#undef _EN_ITEM
Expand Down
12 changes: 2 additions & 10 deletions Marlin/src/module/stepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,11 +498,7 @@ xyze_int8_t Stepper::count_direction{0};
void Stepper::enable_axis(const AxisEnum axis) {
#define _CASE_ENABLE(N) case N##_AXIS: ENABLE_AXIS_##N(); break;
switch (axis) {
NUM_AXIS_CODE(
_CASE_ENABLE(X), _CASE_ENABLE(Y), _CASE_ENABLE(Z),
_CASE_ENABLE(I), _CASE_ENABLE(J), _CASE_ENABLE(K),
_CASE_ENABLE(U), _CASE_ENABLE(V), _CASE_ENABLE(W)
);
MAIN_AXIS_MAP(_CASE_ENABLE)
default: break;
}
mark_axis_enabled(axis);
Expand All @@ -518,11 +514,7 @@ bool Stepper::disable_axis(const AxisEnum axis) {
if (can_disable) {
#define _CASE_DISABLE(N) case N##_AXIS: DISABLE_AXIS_##N(); break;
switch (axis) {
NUM_AXIS_CODE(
_CASE_DISABLE(X), _CASE_DISABLE(Y), _CASE_DISABLE(Z),
_CASE_DISABLE(I), _CASE_DISABLE(J), _CASE_DISABLE(K),
_CASE_DISABLE(U), _CASE_DISABLE(V), _CASE_DISABLE(W)
);
MAIN_AXIS_MAP(_CASE_DISABLE)
default: break;
}
}
Expand Down
32 changes: 9 additions & 23 deletions Marlin/src/module/stepper/trinamic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ enum StealthIndex : uint8_t {
#endif

#define _EN_ITEM(N) , E##N
enum TMCAxis : uint8_t { NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(EXTRUDERS, _EN_ITEM), TOTAL };
enum TMCAxis : uint8_t { MAIN_AXIS_NAMES, X2, Y2, Z2, Z3, Z4 REPEAT(EXTRUDERS, _EN_ITEM), TOTAL };
#undef _EN_ITEM

void tmc_serial_begin() {
Expand Down Expand Up @@ -1023,18 +1023,16 @@ void reset_trinamic_drivers() {
// 2. For each axis in use, static_assert using a constexpr function, which counts the
// number of matching/conflicting axis. If the value is not exactly 1, fail.

#define ALL_AXIS_NAMES X, X2, Y, Y2, Z, Z2, Z3, Z4, I, J, K, U, V, W, E0, E1, E2, E3, E4, E5, E6, E7

#if ANY_AXIS_HAS(HW_SERIAL)
// Hardware serial names are compared as strings, since actually resolving them cannot occur in a constexpr.
// Using a fixed-length character array for the port name allows this to be constexpr compatible.
struct SanityHwSerialDetails { const char port[20]; uint32_t address; };
#define TMC_HW_DETAIL_ARGS(A) TERN(A##_HAS_HW_SERIAL, STRINGIFY(A##_HARDWARE_SERIAL), ""), TERN0(A##_HAS_HW_SERIAL, A##_SLAVE_ADDRESS)
#define TMC_HW_DETAIL(A) { TMC_HW_DETAIL_ARGS(A) }
#define TMC_HW_DETAIL(A) { TMC_HW_DETAIL_ARGS(A) },
constexpr SanityHwSerialDetails sanity_tmc_hw_details[] = {
TMC_HW_DETAIL(X), TMC_HW_DETAIL(X2),
TMC_HW_DETAIL(Y), TMC_HW_DETAIL(Y2),
TMC_HW_DETAIL(Z), TMC_HW_DETAIL(Z2), TMC_HW_DETAIL(Z3), TMC_HW_DETAIL(Z4),
TMC_HW_DETAIL(I), TMC_HW_DETAIL(J), TMC_HW_DETAIL(K), TMC_HW_DETAIL(U), TMC_HW_DETAIL(V), TMC_HW_DETAIL(W),
TMC_HW_DETAIL(E0), TMC_HW_DETAIL(E1), TMC_HW_DETAIL(E2), TMC_HW_DETAIL(E3), TMC_HW_DETAIL(E4), TMC_HW_DETAIL(E5), TMC_HW_DETAIL(E6), TMC_HW_DETAIL(E7)
MAP(TMC_HW_DETAIL, ALL_AXIS_NAMES)
};

// constexpr compatible string comparison
Expand All @@ -1053,23 +1051,15 @@ void reset_trinamic_drivers() {

#define TMC_HWSERIAL_CONFLICT_MSG(A) STRINGIFY(A) "_SLAVE_ADDRESS conflicts with another driver using the same " STRINGIFY(A) "_HARDWARE_SERIAL"
#define SA_NO_TMC_HW_C(A) static_assert(1 >= count_tmc_hw_serial_matches(TMC_HW_DETAIL_ARGS(A), 0, COUNT(sanity_tmc_hw_details)), TMC_HWSERIAL_CONFLICT_MSG(A));
SA_NO_TMC_HW_C(X); SA_NO_TMC_HW_C(X2);
SA_NO_TMC_HW_C(Y); SA_NO_TMC_HW_C(Y2);
SA_NO_TMC_HW_C(Z); SA_NO_TMC_HW_C(Z2); SA_NO_TMC_HW_C(Z3); SA_NO_TMC_HW_C(Z4);
SA_NO_TMC_HW_C(I); SA_NO_TMC_HW_C(J); SA_NO_TMC_HW_C(K); SA_NO_TMC_HW_C(U); SA_NO_TMC_HW_C(V); SA_NO_TMC_HW_C(W);
SA_NO_TMC_HW_C(E0); SA_NO_TMC_HW_C(E1); SA_NO_TMC_HW_C(E2); SA_NO_TMC_HW_C(E3); SA_NO_TMC_HW_C(E4); SA_NO_TMC_HW_C(E5); SA_NO_TMC_HW_C(E6); SA_NO_TMC_HW_C(E7);
MAP(SA_NO_TMC_HW_C, ALL_AXIS_NAMES)
#endif

#if ANY_AXIS_HAS(SW_SERIAL)
struct SanitySwSerialDetails { int32_t txpin; int32_t rxpin; uint32_t address; };
#define TMC_SW_DETAIL_ARGS(A) TERN(A##_HAS_SW_SERIAL, A##_SERIAL_TX_PIN, -1), TERN(A##_HAS_SW_SERIAL, A##_SERIAL_RX_PIN, -1), TERN0(A##_HAS_SW_SERIAL, A##_SLAVE_ADDRESS)
#define TMC_SW_DETAIL(A) TMC_SW_DETAIL_ARGS(A)
#define TMC_SW_DETAIL(A) TMC_SW_DETAIL_ARGS(A),
constexpr SanitySwSerialDetails sanity_tmc_sw_details[] = {
TMC_SW_DETAIL(X), TMC_SW_DETAIL(X2),
TMC_SW_DETAIL(Y), TMC_SW_DETAIL(Y2),
TMC_SW_DETAIL(Z), TMC_SW_DETAIL(Z2), TMC_SW_DETAIL(Z3), TMC_SW_DETAIL(Z4),
TMC_SW_DETAIL(I), TMC_SW_DETAIL(J), TMC_SW_DETAIL(K), TMC_SW_DETAIL(U), TMC_SW_DETAIL(V), TMC_SW_DETAIL(W),
TMC_SW_DETAIL(E0), TMC_SW_DETAIL(E1), TMC_SW_DETAIL(E2), TMC_SW_DETAIL(E3), TMC_SW_DETAIL(E4), TMC_SW_DETAIL(E5), TMC_SW_DETAIL(E6), TMC_SW_DETAIL(E7)
MAP(TMC_SW_DETAIL, ALL_AXIS_NAMES)
};

constexpr bool sc_sw_done(size_t start, size_t end) { return start == end; }
Expand All @@ -1083,11 +1073,7 @@ void reset_trinamic_drivers() {

#define TMC_SWSERIAL_CONFLICT_MSG(A) STRINGIFY(A) "_SLAVE_ADDRESS conflicts with another driver using the same " STRINGIFY(A) "_SERIAL_RX_PIN or " STRINGIFY(A) "_SERIAL_TX_PIN"
#define SA_NO_TMC_SW_C(A) static_assert(1 >= count_tmc_sw_serial_matches(TMC_SW_DETAIL_ARGS(A), 0, COUNT(sanity_tmc_sw_details)), TMC_SWSERIAL_CONFLICT_MSG(A));
SA_NO_TMC_SW_C(X); SA_NO_TMC_SW_C(X2);
SA_NO_TMC_SW_C(Y); SA_NO_TMC_SW_C(Y2);
SA_NO_TMC_SW_C(Z); SA_NO_TMC_SW_C(Z2); SA_NO_TMC_SW_C(Z3); SA_NO_TMC_SW_C(Z4);
SA_NO_TMC_SW_C(I); SA_NO_TMC_SW_C(J); SA_NO_TMC_SW_C(K); SA_NO_TMC_SW_C(U); SA_NO_TMC_SW_C(V); SA_NO_TMC_SW_C(W);
SA_NO_TMC_SW_C(E0); SA_NO_TMC_SW_C(E1); SA_NO_TMC_SW_C(E2); SA_NO_TMC_SW_C(E3); SA_NO_TMC_SW_C(E4); SA_NO_TMC_SW_C(E5); SA_NO_TMC_SW_C(E6); SA_NO_TMC_SW_C(E7);
MAP(SA_NO_TMC_SW_C, ALL_AXIS_NAMES)
#endif

#endif // HAS_TRINAMIC_CONFIG