2016-03-25 06:19:46 +00:00
/**
2016-03-24 18:01:20 +00:00
* Marlin 3 D Printer Firmware
2020-02-03 14:00:57 +00:00
* Copyright ( c ) 2020 MarlinFirmware [ https : //github.com/MarlinFirmware/Marlin]
2016-03-24 18:01:20 +00:00
*
* Based on Sprinter and grbl .
2019-06-28 04:57:50 +00:00
* Copyright ( c ) 2011 Camiel Gubbels / Erik van der Zalm
2016-03-24 18:01:20 +00:00
*
* 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
2020-07-23 03:20:14 +00:00
* along with this program . If not , see < https : //www.gnu.org/licenses/>.
2016-03-24 18:01:20 +00:00
*
*/
2018-09-30 09:59:14 +00:00
# pragma once
2020-03-22 04:31:02 +00:00
# if !defined(__has_include)
# define __has_include(...) 1
# endif
2018-02-04 06:26:05 +00:00
# define ABCE 4
2016-08-21 01:07:42 +00:00
# define XYZE 4
# define ABC 3
# define XYZ 3
2019-09-29 09:25:39 +00:00
# define XY 2
2016-08-03 02:36:58 +00:00
2018-05-13 08:44:24 +00:00
# define _AXIS(A) (A##_AXIS)
2020-01-30 09:24:57 +00:00
# define _XMIN_ 100
# define _YMIN_ 200
# define _ZMIN_ 300
# define _XMAX_ 101
# define _YMAX_ 201
# define _ZMAX_ 301
# define _XDIAG_ 102
# define _YDIAG_ 202
# define _ZDIAG_ 302
# define _E0DIAG_ 400
# define _E1DIAG_ 401
# define _E2DIAG_ 402
# define _E3DIAG_ 403
# define _E4DIAG_ 404
# define _E5DIAG_ 405
# define _E6DIAG_ 406
# define _E7DIAG_ 407
2018-10-03 03:09:41 +00:00
# define _FORCE_INLINE_ __attribute__((__always_inline__)) __inline__
# define FORCE_INLINE __attribute__((always_inline)) inline
2021-01-29 01:59:16 +00:00
# define NO_INLINE __attribute__((noinline))
2018-10-03 03:09:41 +00:00
# define _UNUSED __attribute__((unused))
# define _O0 __attribute__((optimize("O0")))
# define _Os __attribute__((optimize("Os")))
# define _O1 __attribute__((optimize("O1")))
# define _O2 __attribute__((optimize("O2")))
# define _O3 __attribute__((optimize("O3")))
2021-02-06 04:43:51 +00:00
# define IS_CONSTEXPR(...) __builtin_constant_p(__VA_ARGS__) // Only valid solution with C++14. Should use std::is_constant_evaluated() in C++20 instead
2019-09-17 05:05:12 +00:00
# ifndef UNUSED
2020-11-26 06:37:18 +00:00
# define UNUSED(x) ((void)(x))
2019-09-17 05:05:12 +00:00
# endif
2017-04-11 16:11:17 +00:00
// Clock speed factors
2018-02-20 09:09:53 +00:00
# if !defined(CYCLES_PER_MICROSECOND) && !defined(__STM32F1__)
2018-10-26 08:53:06 +00:00
# define CYCLES_PER_MICROSECOND (F_CPU / 1000000UL) // 16 or 20 on AVR
2018-02-11 02:08:48 +00:00
# endif
2016-09-24 04:59:16 +00:00
2018-05-12 13:34:04 +00:00
// Nanoseconds per cycle
# define NANOSECONDS_PER_CYCLE (1000000000.0 / F_CPU)
2017-04-11 07:33:46 +00:00
2018-10-03 03:09:41 +00:00
// Macros to make a string from a macro
# define STRINGIFY_(M) #M
# define STRINGIFY(M) STRINGIFY_(M)
2018-05-08 10:10:27 +00:00
# define A(CODE) " " CODE "\n\t"
# define L(CODE) CODE ":\n\t"
2015-07-22 22:39:23 +00:00
// Macros for bit masks
2019-08-30 21:09:57 +00:00
# undef _BV
# define _BV(n) (1<<(n))
2019-09-16 21:49:46 +00:00
# define TEST(n,b) (!!((n)&_BV(b)))
2018-05-24 05:04:47 +00:00
# define SET_BIT_TO(N,B,TF) do{ if (TF) SBI(N,B); else CBI(N,B); }while(0)
2019-07-09 04:42:29 +00:00
# ifndef SBI
2021-01-17 01:03:06 +00:00
# define SBI(A,B) (A |= _BV(B))
2019-07-09 04:42:29 +00:00
# endif
# ifndef CBI
2021-01-17 01:03:06 +00:00
# define CBI(A,B) (A &= ~_BV(B))
2019-07-09 04:42:29 +00:00
# endif
2020-06-18 20:23:03 +00:00
# define TBI(N,B) (N ^= _BV(B))
2018-10-03 03:09:41 +00:00
# define _BV32(b) (1UL << (b))
# define TEST32(n,b) !!((n)&_BV32(b))
# define SBI32(n,b) (n |= _BV32(b))
# define CBI32(n,b) (n &= ~_BV32(b))
2020-06-18 20:23:03 +00:00
# define TBI32(N,B) (N ^= _BV32(B))
2018-10-03 03:09:41 +00:00
2020-05-12 06:01:16 +00:00
# define cu(x) ({__typeof__(x) _x = (x); (_x)*(_x)*(_x);})
2018-07-01 20:20:28 +00:00
# define RADIANS(d) ((d)*float(M_PI) / 180.0f)
# define DEGREES(r) ((r)*180.0f / float(M_PI))
2016-09-12 02:02:37 +00:00
# define HYPOT2(x,y) (sq(x)+sq(y))
2021-03-03 23:46:32 +00:00
# define NORMSQ(x,y,z) (sq(x)+sq(y)+sq(z))
2015-07-22 22:39:23 +00:00
2018-07-01 20:20:28 +00:00
# define CIRCLE_AREA(R) (float(M_PI) * sq(float(R)))
# define CIRCLE_CIRC(R) (2 * float(M_PI) * float(R))
2017-09-06 11:28:32 +00:00
2020-05-12 06:01:16 +00:00
# define SIGN(a) ({__typeof__(a) _a = (a); (_a>0)-(_a<0);})
2018-10-03 03:09:41 +00:00
# define IS_POWER_OF_2(x) ((x) && !((x) & ((x) - 1)))
2017-06-09 12:06:23 +00:00
2018-10-03 03:09:41 +00:00
// Macros to constrain values
2018-05-16 20:16:07 +00:00
# ifdef __cplusplus
2018-10-03 03:09:41 +00:00
// C++11 solution that is standards compliant.
template < class V , class N > static inline constexpr void NOLESS ( V & v , const N n ) {
2019-09-19 06:28:31 +00:00
if ( n > v ) v = n ;
2018-10-03 03:09:41 +00:00
}
template < class V , class N > static inline constexpr void NOMORE ( V & v , const N n ) {
2019-09-19 06:28:31 +00:00
if ( n < v ) v = n ;
2018-10-03 03:09:41 +00:00
}
template < class V , class N1 , class N2 > static inline constexpr void LIMIT ( V & v , const N1 n1 , const N2 n2 ) {
2019-09-19 06:28:31 +00:00
if ( n1 > v ) v = n1 ;
else if ( n2 < v ) v = n2 ;
2018-05-16 20:16:07 +00:00
}
# else
# define NOLESS(v, n) \
2019-08-16 23:34:13 +00:00
do { \
2021-02-09 03:27:00 +00:00
__typeof__ ( v ) _n = ( n ) ; \
2019-09-19 06:28:31 +00:00
if ( _n > v ) v = _n ; \
2019-08-16 23:34:13 +00:00
} while ( 0 )
2018-05-16 20:16:07 +00:00
# define NOMORE(v, n) \
2019-08-16 23:34:13 +00:00
do { \
2021-02-09 03:27:00 +00:00
__typeof__ ( v ) _n = ( n ) ; \
2019-09-19 06:28:31 +00:00
if ( _n < v ) v = _n ; \
2019-08-16 23:34:13 +00:00
} while ( 0 )
2018-05-16 20:16:07 +00:00
# define LIMIT(v, n1, n2) \
2019-08-16 23:34:13 +00:00
do { \
2021-02-09 03:27:00 +00:00
__typeof__ ( v ) _n1 = ( n1 ) ; \
__typeof__ ( v ) _n2 = ( n2 ) ; \
2019-09-19 06:28:31 +00:00
if ( _n1 > v ) v = _n1 ; \
else if ( _n2 < v ) v = _n2 ; \
2019-08-16 23:34:13 +00:00
} while ( 0 )
2018-05-16 20:16:07 +00:00
# endif
2015-07-22 22:39:23 +00:00
2020-12-22 12:51:29 +00:00
// Macros to chain up to 14 conditions
2019-03-17 04:43:06 +00:00
# define _DO_1(W,C,A) (_##W##_1(A))
# define _DO_2(W,C,A,B) (_##W##_1(A) C _##W##_1(B))
# define _DO_3(W,C,A,V...) (_##W##_1(A) C _DO_2(W,C,V))
# define _DO_4(W,C,A,V...) (_##W##_1(A) C _DO_3(W,C,V))
# define _DO_5(W,C,A,V...) (_##W##_1(A) C _DO_4(W,C,V))
# define _DO_6(W,C,A,V...) (_##W##_1(A) C _DO_5(W,C,V))
# define _DO_7(W,C,A,V...) (_##W##_1(A) C _DO_6(W,C,V))
# define _DO_8(W,C,A,V...) (_##W##_1(A) C _DO_7(W,C,V))
# define _DO_9(W,C,A,V...) (_##W##_1(A) C _DO_8(W,C,V))
# define _DO_10(W,C,A,V...) (_##W##_1(A) C _DO_9(W,C,V))
# define _DO_11(W,C,A,V...) (_##W##_1(A) C _DO_10(W,C,V))
# define _DO_12(W,C,A,V...) (_##W##_1(A) C _DO_11(W,C,V))
2020-12-22 12:51:29 +00:00
# define _DO_13(W,C,A,V...) (_##W##_1(A) C _DO_12(W,C,V))
# define _DO_14(W,C,A,V...) (_##W##_1(A) C _DO_13(W,C,V))
2021-01-25 14:32:58 +00:00
# define _DO_15(W,C,A,V...) (_##W##_1(A) C _DO_14(W,C,V))
2019-03-17 04:43:06 +00:00
# define __DO_N(W,C,N,V...) _DO_##N(W,C,V)
# define _DO_N(W,C,N,V...) __DO_N(W,C,N,V)
2020-10-15 08:00:27 +00:00
# define DO(W,C,V...) (_DO_N(W,C,NUM_ARGS(V),V))
2019-03-17 04:43:06 +00:00
2018-10-03 03:09:41 +00:00
// Macros to support option testing
2019-03-17 04:43:06 +00:00
# define _CAT(a,V...) a##V
2019-11-09 23:59:04 +00:00
# define CAT(a,V...) _CAT(a,V)
2020-03-08 04:20:41 +00:00
# define _ISENA_ ~,1
# define _ISENA_1 ~,1
# define _ISENA_0x1 ~,1
# define _ISENA_true ~,1
# define _ISENA(V...) IS_PROBE(V)
# define _ENA_1(O) _ISENA(CAT(_IS,CAT(ENA_, O)))
# define _DIS_1(O) NOT(_ENA_1(O))
2019-03-17 04:43:06 +00:00
# define ENABLED(V...) DO(ENA,&&,V)
# define DISABLED(V...) DO(DIS,&&,V)
2020-10-15 08:00:27 +00:00
# define COUNT_ENABLED(V...) DO(ENA,+,V)
2019-03-17 04:43:06 +00:00
2020-03-13 00:26:09 +00:00
# define TERN(O,A,B) _TERN(_ENA_1(O),B,A) // OPTION converted to '0' or '1'
2020-03-31 17:50:30 +00:00
# define TERN0(O,A) _TERN(_ENA_1(O),0,A) // OPTION converted to A or '0'
# define TERN1(O,A) _TERN(_ENA_1(O),1,A) // OPTION converted to A or '1'
# define TERN_(O,A) _TERN(_ENA_1(O),,A) // OPTION converted to A or '<nul>'
2020-03-08 04:20:41 +00:00
# define _TERN(E,V...) __TERN(_CAT(T_,E),V) // Prepend 'T_' to get 'T_0' or 'T_1'
# define __TERN(T,V...) ___TERN(_CAT(_NO,T),V) // Prepend '_NO' to get '_NOT_0' or '_NOT_1'
# define ___TERN(P,V...) THIRD(P,V) // If first argument has a comma, A. Else B.
2020-11-08 00:28:29 +00:00
# define IF_ENABLED TERN_
# define IF_DISABLED(O,A) TERN(O,,A)
2019-03-17 04:43:06 +00:00
# define ANY(V...) !DISABLED(V)
# define NONE(V...) DISABLED(V)
# define ALL(V...) ENABLED(V)
# define BOTH(V1,V2) ALL(V1,V2)
# define EITHER(V1,V2) ANY(V1,V2)
2020-10-15 08:00:27 +00:00
# define MANY(V...) (COUNT_ENABLED(V) > 1)
2019-03-17 04:43:06 +00:00
// Macros to support pins/buttons exist testing
2020-02-04 07:24:11 +00:00
# define PIN_EXISTS(PN) (defined(PN##_PIN) && PN##_PIN >= 0)
# define _PINEX_1 PIN_EXISTS
# define PINS_EXIST(V...) DO(PINEX,&&,V)
2019-03-17 04:43:06 +00:00
# define ANY_PIN(V...) DO(PINEX,||,V)
2020-02-04 07:24:11 +00:00
# define BUTTON_EXISTS(BN) (defined(BTN_##BN) && BTN_##BN >= 0)
# define _BTNEX_1 BUTTON_EXISTS
# define BUTTONS_EXIST(V...) DO(BTNEX,&&,V)
2019-03-17 04:43:06 +00:00
# define ANY_BUTTON(V...) DO(BTNEX,||,V)
# define WITHIN(N,L,H) ((N) >= (L) && (N) <= (H))
2020-12-29 04:07:11 +00:00
# define ISEOL(C) ((C) == '\n' || (C) == '\r')
2019-03-17 04:43:06 +00:00
# define NUMERIC(a) WITHIN(a, '0', '9')
# define DECIMAL(a) (NUMERIC(a) || a == '.')
2020-10-09 11:25:23 +00:00
# define HEXCHR(a) (NUMERIC(a) ? (a) - '0' : WITHIN(a, 'a', 'f') ? ((a) - 'a' + 10) : WITHIN(a, 'A', 'F') ? ((a) - 'A' + 10) : -1)
2019-03-17 04:43:06 +00:00
# define NUMERIC_SIGNED(a) (NUMERIC(a) || (a) == '-' || (a) == '+')
# define DECIMAL_SIGNED(a) (DECIMAL(a) || (a) == '-' || (a) == '+')
# define COUNT(a) (sizeof(a) / sizeof(*a))
# define ZERO(a) memset(a,0,sizeof(a))
2019-02-04 11:41:40 +00:00
# define COPY(a,b) do{ \
static_assert ( sizeof ( a [ 0 ] ) = = sizeof ( b [ 0 ] ) , " COPY: ' " STRINGIFY ( a ) " ' and ' " STRINGIFY ( b ) " ' types (sizes) don't match! " ) ; \
2019-07-05 23:01:21 +00:00
memcpy ( & a [ 0 ] , & b [ 0 ] , _MIN ( sizeof ( a ) , sizeof ( b ) ) ) ; \
2019-02-04 11:41:40 +00:00
} while ( 0 )
2015-07-22 22:50:20 +00:00
2018-10-03 03:09:41 +00:00
// Macros for initializing arrays
2019-09-29 00:02:34 +00:00
# define LIST_16(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
# define LIST_15(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O
# define LIST_14(A,B,C,D,E,F,G,H,I,J,K,L,M,N,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N
# define LIST_13(A,B,C,D,E,F,G,H,I,J,K,L,M,...) A,B,C,D,E,F,G,H,I,J,K,L,M
# define LIST_12(A,B,C,D,E,F,G,H,I,J,K,L,...) A,B,C,D,E,F,G,H,I,J,K,L
# define LIST_11(A,B,C,D,E,F,G,H,I,J,K,...) A,B,C,D,E,F,G,H,I,J,K
# define LIST_10(A,B,C,D,E,F,G,H,I,J,...) A,B,C,D,E,F,G,H,I,J
# define LIST_9( A,B,C,D,E,F,G,H,I,...) A,B,C,D,E,F,G,H,I
# define LIST_8( A,B,C,D,E,F,G,H,...) A,B,C,D,E,F,G,H
# define LIST_7( A,B,C,D,E,F,G,...) A,B,C,D,E,F,G
# define LIST_6( A,B,C,D,E,F,...) A,B,C,D,E,F
# define LIST_5( A,B,C,D,E,...) A,B,C,D,E
# define LIST_4( A,B,C,D,...) A,B,C,D
# define LIST_3( A,B,C,...) A,B,C
# define LIST_2( A,B,...) A,B
# define LIST_1( A,...) A
# define _LIST_N(N,V...) LIST_##N(V)
# define LIST_N(N,V...) _LIST_N(N,V)
# define ARRAY_N(N,V...) { _LIST_N(N,V) }
2018-10-03 03:09:41 +00:00
2019-10-03 23:48:31 +00:00
# define _JOIN_1(O) (O)
# define JOIN_N(N,C,V...) (DO(JOIN,C,LIST_N(N,V)))
2020-03-14 04:18:16 +00:00
# define LOOP_S_LE_N(VAR, S, N) for (uint8_t VAR=(S); VAR<=(N); VAR++)
# define LOOP_S_L_N(VAR, S, N) for (uint8_t VAR=(S); VAR<(N); VAR++)
# define LOOP_LE_N(VAR, N) LOOP_S_LE_N(VAR, 0, N)
# define LOOP_L_N(VAR, N) LOOP_S_L_N(VAR, 0, N)
2018-11-18 23:54:00 +00:00
# define NOOP (void(0))
2016-07-14 23:07:34 +00:00
# define CEILING(x,y) (((x) + (y) - 1) / (y))
2016-04-29 00:59:52 +00:00
2018-10-03 03:09:41 +00:00
# undef ABS
# ifdef __cplusplus
template < class T > static inline constexpr const T ABS ( const T v ) { return v > = 0 ? v : - v ; }
# else
# define ABS(a) ({__typeof__(a) _a = (a); _a >= 0 ? _a : -_a;})
# endif
2018-07-01 20:20:28 +00:00
# define UNEAR_ZERO(x) ((x) < 0.000001f)
# define NEAR_ZERO(x) WITHIN(x, -0.000001f, 0.000001f)
2016-09-12 02:02:37 +00:00
# define NEAR(x,y) NEAR_ZERO((x)-(y))
2018-07-01 20:20:28 +00:00
# define RECIPROCAL(x) (NEAR_ZERO(x) ? 0 : (1 / float(x)))
2020-06-23 02:12:45 +00:00
# define FIXFLOAT(f) ({__typeof__(f) _f = (f); _f + (_f < 0 ? -0.0000005f : 0.0000005f);})
2016-11-12 20:33:07 +00:00
2017-06-20 03:39:23 +00:00
//
// Maths macros that can be overridden by HAL
//
2019-11-30 14:57:34 +00:00
# define ACOS(x) acosf(x)
2018-07-01 20:20:28 +00:00
# define ATAN2(y, x) atan2f(y, x)
# define POW(x, y) powf(x, y)
# define SQRT(x) sqrtf(x)
2019-10-24 19:57:20 +00:00
# define RSQRT(x) (1.0f / sqrtf(x))
2018-07-01 20:20:28 +00:00
# define CEIL(x) ceilf(x)
# define FLOOR(x) floorf(x)
2020-12-24 00:19:48 +00:00
# define TRUNC(x) truncf(x)
2018-07-01 20:20:28 +00:00
# define LROUND(x) lroundf(x)
# define FMOD(x, y) fmodf(x, y)
2017-06-20 03:39:23 +00:00
# define HYPOT(x,y) SQRT(HYPOT2(x,y))
2019-02-20 12:26:36 +00:00
2019-07-09 04:42:29 +00:00
// Use NUM_ARGS(__VA_ARGS__) to get the number of variadic arguments
2019-09-27 09:30:48 +00:00
# define _NUM_ARGS(_,Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A,OUT,...) OUT
# define NUM_ARGS(V...) _NUM_ARGS(0,V,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
2019-07-09 04:42:29 +00:00
# ifdef __cplusplus
# ifndef _MINMAX_H_
# define _MINMAX_H_
extern " C++ " {
// C++11 solution that is standards compliant. Return type is deduced automatically
template < class L , class R > static inline constexpr auto _MIN ( const L lhs , const R rhs ) - > decltype ( lhs + rhs ) {
return lhs < rhs ? lhs : rhs ;
}
template < class L , class R > static inline constexpr auto _MAX ( const L lhs , const R rhs ) - > decltype ( lhs + rhs ) {
return lhs > rhs ? lhs : rhs ;
}
template < class T , class . . . Ts > static inline constexpr const T _MIN ( T V , Ts . . . Vs ) { return _MIN ( V , _MIN ( Vs . . . ) ) ; }
template < class T , class . . . Ts > static inline constexpr const T _MAX ( T V , Ts . . . Vs ) { return _MAX ( V , _MAX ( Vs . . . ) ) ; }
}
# endif
2021-01-28 08:02:06 +00:00
// C++11 solution that is standard compliant. <type_traits> is not available on all platform
namespace Private {
template < bool , typename _Tp = void > struct enable_if { } ;
template < typename _Tp > struct enable_if < true , _Tp > { typedef _Tp type ; } ;
2021-02-08 06:37:24 +00:00
template < typename T , typename U > struct is_same { enum { value = false } ; } ;
template < typename T > struct is_same < T , T > { enum { value = true } ; } ;
template < typename T , typename . . . Args > struct first_type_of { typedef T type ; } ;
template < typename T > struct first_type_of < T > { typedef T type ; } ;
2021-01-28 08:02:06 +00:00
}
2021-02-01 00:18:39 +00:00
// C++11 solution using SFINAE to detect the existance of a member in a class at compile time.
// It creates a HasMember<Type> structure containing 'value' set to true if the member exists
2021-01-28 08:02:06 +00:00
# define HAS_MEMBER_IMPL(Member) \
namespace Private { \
template < typename Type , typename Yes = char , typename No = long > struct HasMember_ # # Member { \
template < typename C > static Yes & test ( decltype ( & C : : Member ) ) ; \
template < typename C > static No & test ( . . . ) ; \
enum { value = sizeof ( test < Type > ( 0 ) ) = = sizeof ( Yes ) } ; } ; \
}
// Call the method if it exists, but do nothing if it does not. The method is detected at compile time.
// If the method exists, this is inlined and does not cost anything. Else, an "empty" wrapper is created, returning a default value
# define CALL_IF_EXISTS_IMPL(Return, Method, ...) \
HAS_MEMBER_IMPL ( Method ) \
namespace Private { \
template < typename T , typename . . . Args > FORCE_INLINE typename enable_if < HasMember_ # # Method < T > : : value , Return > : : type Call_ # # Method ( T * t , Args . . . a ) { return static_cast < Return > ( t - > Method ( a . . . ) ) ; } \
_UNUSED static Return Call_ # # Method ( . . . ) { return __VA_ARGS__ ; } \
}
# define CALL_IF_EXISTS(Return, That, Method, ...) \
static_cast < Return > ( Private : : Call_ # # Method ( That , # # __VA_ARGS__ ) )
2021-02-26 22:54:46 +00:00
// Compile-time string manipulation
namespace CompileTimeString {
// Simple compile-time parser to find the position of the end of a string
constexpr const char * findStringEnd ( const char * str ) {
return * str ? findStringEnd ( str + 1 ) : str ;
}
// Check whether a string contains a slash
constexpr bool containsSlash ( const char * str ) {
return * str = = ' / ' ? true : ( * str ? containsSlash ( str + 1 ) : false ) ;
}
// Find the last position of the slash
constexpr const char * findLastSlashPos ( const char * str ) {
return * str = = ' / ' ? ( str + 1 ) : findLastSlashPos ( str - 1 ) ;
}
// Compile-time evaluation of the last part of a file path
// Typically used to shorten the path to file in compiled strings
// CompileTimeString::baseName(__FILE__) returns "macros.h" and not /path/to/Marlin/src/core/macros.h
constexpr const char * baseName ( const char * str ) {
return containsSlash ( str ) ? findLastSlashPos ( findStringEnd ( str ) ) : str ;
}
}
# define ONLY_FILENAME CompileTimeString::baseName(__FILE__)
2019-07-09 04:42:29 +00:00
# else
# define MIN_2(a,b) ((a)<(b)?(a):(b))
2019-09-27 09:30:48 +00:00
# define MIN_3(a,V...) MIN_2(a,MIN_2(V))
# define MIN_4(a,V...) MIN_2(a,MIN_3(V))
# define MIN_5(a,V...) MIN_2(a,MIN_4(V))
# define MIN_6(a,V...) MIN_2(a,MIN_5(V))
# define MIN_7(a,V...) MIN_2(a,MIN_6(V))
# define MIN_8(a,V...) MIN_2(a,MIN_7(V))
# define MIN_9(a,V...) MIN_2(a,MIN_8(V))
# define MIN_10(a,V...) MIN_2(a,MIN_9(V))
# define __MIN_N(N,V...) MIN_##N(V)
# define _MIN_N(N,V...) __MIN_N(N,V)
# define _MIN(V...) _MIN_N(NUM_ARGS(V), V)
2019-07-09 04:42:29 +00:00
# define MAX_2(a,b) ((a)>(b)?(a):(b))
2019-09-27 09:30:48 +00:00
# define MAX_3(a,V...) MAX_2(a,MAX_2(V))
# define MAX_4(a,V...) MAX_2(a,MAX_3(V))
# define MAX_5(a,V...) MAX_2(a,MAX_4(V))
# define MAX_6(a,V...) MAX_2(a,MAX_5(V))
# define MAX_7(a,V...) MAX_2(a,MAX_6(V))
# define MAX_8(a,V...) MAX_2(a,MAX_7(V))
# define MAX_9(a,V...) MAX_2(a,MAX_8(V))
# define MAX_10(a,V...) MAX_2(a,MAX_9(V))
# define __MAX_N(N,V...) MAX_##N(V)
# define _MAX_N(N,V...) __MAX_N(N,V)
# define _MAX(V...) _MAX_N(NUM_ARGS(V), V)
2019-07-09 04:42:29 +00:00
# endif
2019-11-09 23:59:04 +00:00
// Macros for adding
2020-08-09 01:00:42 +00:00
# define INC_0 1
# define INC_1 2
# define INC_2 3
# define INC_3 4
# define INC_4 5
# define INC_5 6
# define INC_6 7
# define INC_7 8
# define INC_8 9
# define INC_9 10
# define INC_10 11
# define INC_11 12
# define INC_12 13
# define INC_13 14
# define INC_14 15
# define INC_15 16
2019-11-09 23:59:04 +00:00
# define INCREMENT_(n) INC_##n
# define INCREMENT(n) INCREMENT_(n)
# define ADD0(N) N
# define ADD1(N) INCREMENT_(N)
# define ADD2(N) ADD1(ADD1(N))
# define ADD3(N) ADD1(ADD2(N))
# define ADD4(N) ADD2(ADD2(N))
# define ADD5(N) ADD2(ADD3(N))
# define ADD6(N) ADD3(ADD3(N))
# define ADD7(N) ADD3(ADD4(N))
# define ADD8(N) ADD4(ADD4(N))
# define ADD9(N) ADD4(ADD5(N))
# define ADD10(N) ADD5(ADD5(N))
// Macros for subtracting
2020-08-09 01:00:42 +00:00
# define DEC_0 0
# define DEC_1 0
# define DEC_2 1
# define DEC_3 2
# define DEC_4 3
# define DEC_5 4
# define DEC_6 5
# define DEC_7 6
# define DEC_8 7
# define DEC_9 8
# define DEC_10 9
# define DEC_11 10
# define DEC_12 11
# define DEC_13 12
# define DEC_14 13
# define DEC_15 14
2019-11-09 23:59:04 +00:00
# define DECREMENT_(n) DEC_##n
# define DECREMENT(n) DECREMENT_(n)
# define SUB0(N) N
# define SUB1(N) DECREMENT_(N)
# define SUB2(N) SUB1(SUB1(N))
# define SUB3(N) SUB1(SUB2(N))
# define SUB4(N) SUB2(SUB2(N))
# define SUB5(N) SUB2(SUB3(N))
# define SUB6(N) SUB3(SUB3(N))
# define SUB7(N) SUB3(SUB4(N))
# define SUB8(N) SUB4(SUB4(N))
# define SUB9(N) SUB4(SUB5(N))
# define SUB10(N) SUB5(SUB5(N))
//
// Primitives supporting precompiler REPEAT
//
2020-03-08 04:20:41 +00:00
# define FIRST(a,...) a
# define SECOND(a,b,...) b
# define THIRD(a,b,c,...) c
2019-11-09 23:59:04 +00:00
// Defer expansion
# define EMPTY()
# define DEFER(M) M EMPTY()
# define DEFER2(M) M EMPTY EMPTY()()
# define DEFER3(M) M EMPTY EMPTY EMPTY()()()
# define DEFER4(M) M EMPTY EMPTY EMPTY EMPTY()()()()
// Force define expansion
# define EVAL(V...) EVAL16(V)
# define EVAL1024(V...) EVAL512(EVAL512(V))
# define EVAL512(V...) EVAL256(EVAL256(V))
# define EVAL256(V...) EVAL128(EVAL128(V))
# define EVAL128(V...) EVAL64(EVAL64(V))
# define EVAL64(V...) EVAL32(EVAL32(V))
# define EVAL32(V...) EVAL16(EVAL16(V))
# define EVAL16(V...) EVAL8(EVAL8(V))
# define EVAL8(V...) EVAL4(EVAL4(V))
# define EVAL4(V...) EVAL2(EVAL2(V))
# define EVAL2(V...) EVAL1(EVAL1(V))
# define EVAL1(V...) V
# define IS_PROBE(V...) SECOND(V, 0) // Get the second item passed, or 0
# define PROBE() ~, 1 // Second item will be 1 if this is passed
# define _NOT_0 PROBE()
# define NOT(x) IS_PROBE(_CAT(_NOT_, x)) // NOT('0') gets '1'. Anything else gets '0'.
# define _BOOL(x) NOT(NOT(x)) // NOT('0') gets '0'. Anything else gets '1'.
# define IF_ELSE(TF) _IF_ELSE(_BOOL(TF))
# define _IF_ELSE(TF) _CAT(_IF_, TF)
# define _IF_1(V...) V _IF_1_ELSE
# define _IF_0(...) _IF_0_ELSE
# define _IF_1_ELSE(...)
# define _IF_0_ELSE(V...) V
# define HAS_ARGS(V...) _BOOL(FIRST(_END_OF_ARGUMENTS_ V)())
# define _END_OF_ARGUMENTS_() 0
2020-10-12 21:38:07 +00:00
// Simple Inline IF Macros, friendly to use in other macro definitions
# define IF(O, A, B) ((O) ? (A) : (B))
# define IF_0(O, A) IF(O, A, 0)
# define IF_1(O, A) IF(O, A, 1)
2019-11-09 23:59:04 +00:00
//
// REPEAT core macros. Recurse N times with ascending I.
//
// Call OP(I) N times with ascending counter.
# define _REPEAT(_RPT_I,_RPT_N,_RPT_OP) \
_RPT_OP ( _RPT_I ) \
IF_ELSE ( SUB1 ( _RPT_N ) ) \
( DEFER2 ( __REPEAT ) ( ) ( ADD1 ( _RPT_I ) , SUB1 ( _RPT_N ) , _RPT_OP ) ) \
( /* Do nothing */ )
# define __REPEAT() _REPEAT
// Call OP(I, ...) N times with ascending counter.
# define _REPEAT2(_RPT_I,_RPT_N,_RPT_OP,V...) \
_RPT_OP ( _RPT_I , V ) \
IF_ELSE ( SUB1 ( _RPT_N ) ) \
( DEFER2 ( __REPEAT2 ) ( ) ( ADD1 ( _RPT_I ) , SUB1 ( _RPT_N ) , _RPT_OP , V ) ) \
( /* Do nothing */ )
# define __REPEAT2() _REPEAT2
// Repeat a macro passing S...N-1.
# define REPEAT_S(S,N,OP) EVAL(_REPEAT(S,SUB##S(N),OP))
# define REPEAT(N,OP) REPEAT_S(0,N,OP)
// Repeat a macro passing 0...N-1 plus additional arguments.
# define REPEAT2_S(S,N,OP,V...) EVAL(_REPEAT2(S,SUB##S(N),OP,V))
# define REPEAT2(N,OP,V...) REPEAT2_S(0,N,OP,V)
2020-02-02 03:00:53 +00:00
// Use RREPEAT macros with REPEAT macros for nesting
# define _RREPEAT(_RPT_I,_RPT_N,_RPT_OP) \
_RPT_OP ( _RPT_I ) \
IF_ELSE ( SUB1 ( _RPT_N ) ) \
( DEFER2 ( __RREPEAT ) ( ) ( ADD1 ( _RPT_I ) , SUB1 ( _RPT_N ) , _RPT_OP ) ) \
( /* Do nothing */ )
# define __RREPEAT() _RREPEAT
# define _RREPEAT2(_RPT_I,_RPT_N,_RPT_OP,V...) \
_RPT_OP ( _RPT_I , V ) \
IF_ELSE ( SUB1 ( _RPT_N ) ) \
( DEFER2 ( __RREPEAT2 ) ( ) ( ADD1 ( _RPT_I ) , SUB1 ( _RPT_N ) , _RPT_OP , V ) ) \
( /* Do nothing */ )
# define __RREPEAT2() _RREPEAT2
2020-03-01 23:37:16 +00:00
# define RREPEAT_S(S,N,OP) EVAL1024(_RREPEAT(S,SUB##S(N),OP))
2020-02-02 03:00:53 +00:00
# define RREPEAT(N,OP) RREPEAT_S(0,N,OP)
2020-03-01 23:37:16 +00:00
# define RREPEAT2_S(S,N,OP,V...) EVAL1024(_RREPEAT2(S,SUB##S(N),OP,V))
2020-02-02 03:00:53 +00:00
# define RREPEAT2(N,OP,V...) RREPEAT2_S(0,N,OP,V)
2020-05-12 06:41:10 +00:00
// 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))