diff --git a/Marlin/src/HAL/NATIVE_SIM/pinsDebug.h b/Marlin/src/HAL/NATIVE_SIM/pinsDebug.h index 2aeeb52e92..7ba14574d0 100644 --- a/Marlin/src/HAL/NATIVE_SIM/pinsDebug.h +++ b/Marlin/src/HAL/NATIVE_SIM/pinsDebug.h @@ -21,6 +21,8 @@ * Support routines for X86_64 */ +#pragma once + /** * Translation of routines & variables used by pinsDebug.h */ @@ -37,16 +39,16 @@ #define MULTI_NAME_PAD 16 // space needed to be pretty if not first name assigned to a pin // active ADC function/mode/code values for PINSEL registers -constexpr int8_t ADC_pin_mode(pin_t pin) { +inline constexpr int8_t ADC_pin_mode(pin_t pin) { return (-1); } -int8_t get_pin_mode(pin_t pin) { +inline int8_t get_pin_mode(pin_t pin) { if (!VALID_PIN(pin)) return -1; return 0; } -bool GET_PINMODE(pin_t pin) { +inline bool GET_PINMODE(pin_t pin) { int8_t pin_mode = get_pin_mode(pin); if (pin_mode == -1 || pin_mode == ADC_pin_mode(pin)) // found an invalid pin or active analog pin return false; @@ -54,6 +56,6 @@ bool GET_PINMODE(pin_t pin) { return (Gpio::getMode(pin) != 0); //input/output state } -bool GET_ARRAY_IS_DIGITAL(pin_t pin) { +inline bool GET_ARRAY_IS_DIGITAL(pin_t pin) { return (!IS_ANALOG(pin) || get_pin_mode(pin) != ADC_pin_mode(pin)); } diff --git a/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_st7920_sw_spi.cpp b/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_st7920_sw_spi.cpp index e95c6ebfbd..c77c3d30f0 100644 --- a/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_st7920_sw_spi.cpp +++ b/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_st7920_sw_spi.cpp @@ -59,7 +59,7 @@ #if ENABLED(U8GLIB_ST7920) -#include +#include #include "../../shared/Delay.h" #undef SPI_SPEED diff --git a/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_sw_spi.cpp b/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_sw_spi.cpp index 8e0ac9c7df..085954803c 100644 --- a/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_sw_spi.cpp +++ b/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_sw_spi.cpp @@ -63,7 +63,7 @@ #define SPI_SPEED 2 // About 2 MHz #include -#include +#include #ifdef __cplusplus extern "C" { @@ -209,7 +209,7 @@ uint8_t u8g_com_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_pt #endif #elif !ANY(TFT_COLOR_UI, TFT_CLASSIC_UI, TFT_LVGL_UI, HAS_MARLINUI_HD44780) && HAS_MARLINUI_U8GLIB - #include + #include uint8_t u8g_com_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {return 0;} #endif // HAS_MARLINUI_U8GLIB && !U8GLIB_ST7920 #endif // __PLAT_NATIVE_SIM__ diff --git a/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp b/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp index 124f0b7c43..edaed9abf8 100644 --- a/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp +++ b/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp @@ -322,7 +322,7 @@ void hook_cpu_exceptions() { unsigned long *vecAddr = (unsigned long*)get_vtor(); SERIAL_ECHOPGM("Vector table addr: "); - SERIAL_PRINTLN(get_vtor(), HEX); + SERIAL_PRINTLN(get_vtor(), PrintBase::Hex); #ifdef VECTOR_TABLE_SIZE uint32_t vec_size = VECTOR_TABLE_SIZE; @@ -349,7 +349,7 @@ void hook_cpu_exceptions() { alignas(128) static unsigned long vectable[VECTOR_TABLE_SENTINEL]; SERIAL_ECHOPGM("Detected vector table size: "); - SERIAL_PRINTLN(vec_size, HEX); + SERIAL_PRINTLN(vec_size, PrintBase::Hex); #endif uint32_t defaultFaultHandler = vecAddr[(unsigned)7]; diff --git a/Marlin/src/core/serial.cpp b/Marlin/src/core/serial.cpp index 2e3a39b66a..50cc50ad57 100644 --- a/Marlin/src/core/serial.cpp +++ b/Marlin/src/core/serial.cpp @@ -76,17 +76,6 @@ void serialprintPGM(PGM_P str) { void serial_echo_start() { static PGMSTR(echomagic, "echo:"); serialprintPGM(echomagic); } void serial_error_start() { static PGMSTR(errormagic, "Error:"); serialprintPGM(errormagic); } -void serial_echopair_PGM(PGM_P const s_P, serial_char_t v) { serialprintPGM(s_P); SERIAL_CHAR(v.c); } -void serial_echopair_PGM(PGM_P const s_P, const char *v) { serialprintPGM(s_P); SERIAL_ECHO(v); } -void serial_echopair_PGM(PGM_P const s_P, char v) { serialprintPGM(s_P); SERIAL_ECHO(v); } -void serial_echopair_PGM(PGM_P const s_P, int v) { serialprintPGM(s_P); SERIAL_ECHO(v); } -void serial_echopair_PGM(PGM_P const s_P, long v) { serialprintPGM(s_P); SERIAL_ECHO(v); } -void serial_echopair_PGM(PGM_P const s_P, float v) { serialprintPGM(s_P); SERIAL_DECIMAL(v); } -void serial_echopair_PGM(PGM_P const s_P, double v) { serialprintPGM(s_P); SERIAL_DECIMAL(v); } -void serial_echopair_PGM(PGM_P const s_P, unsigned char v) { serialprintPGM(s_P); SERIAL_ECHO(v); } -void serial_echopair_PGM(PGM_P const s_P, unsigned int v) { serialprintPGM(s_P); SERIAL_ECHO(v); } -void serial_echopair_PGM(PGM_P const s_P, unsigned long v) { serialprintPGM(s_P); SERIAL_ECHO(v); } - void serial_spaces(uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) SERIAL_CHAR(' '); } void serial_ternary(const bool onoff, PGM_P const pre, PGM_P const on, PGM_P const off, PGM_P const post/*=nullptr*/) { diff --git a/Marlin/src/core/serial.h b/Marlin/src/core/serial.h index 7f96a30d6f..dfcf23ddb6 100644 --- a/Marlin/src/core/serial.h +++ b/Marlin/src/core/serial.h @@ -177,8 +177,8 @@ void SERIAL_ECHOLN(T x) { SERIAL_IMPL.println(x); } template void SERIAL_PRINT(T x, U y) { SERIAL_IMPL.print(x, y); } -template -void SERIAL_PRINTLN(T x, U y) { SERIAL_IMPL.println(x, y); } +template +void SERIAL_PRINTLN(T x, PrintBase y) { SERIAL_IMPL.println(x, y); } // Flush the serial port inline void SERIAL_FLUSH() { SERIAL_IMPL.flush(); } @@ -293,21 +293,18 @@ void serialprintPGM(PGM_P str); // // Functions for serial printing from PROGMEM. (Saves loads of SRAM.) // -void serial_echopair_PGM(PGM_P const s_P, serial_char_t v); -void serial_echopair_PGM(PGM_P const s_P, const char *v); -void serial_echopair_PGM(PGM_P const s_P, char v); -void serial_echopair_PGM(PGM_P const s_P, int v); -void serial_echopair_PGM(PGM_P const s_P, long v); -void serial_echopair_PGM(PGM_P const s_P, float v); -void serial_echopair_PGM(PGM_P const s_P, double v); -void serial_echopair_PGM(PGM_P const s_P, unsigned char v); -void serial_echopair_PGM(PGM_P const s_P, unsigned int v); -void serial_echopair_PGM(PGM_P const s_P, unsigned long v); +inline void serial_echopair_PGM(PGM_P const s_P, serial_char_t v) { serialprintPGM(s_P); SERIAL_CHAR(v.c); } + +inline void serial_echopair_PGM(PGM_P const s_P, float v) { serialprintPGM(s_P); SERIAL_DECIMAL(v); } +inline void serial_echopair_PGM(PGM_P const s_P, double v) { serialprintPGM(s_P); SERIAL_DECIMAL(v); } +inline void serial_echopair_PGM(PGM_P const s_P, const char *v) { serialprintPGM(s_P); SERIAL_ECHO(v); } + +// Default implementation for types without a specialization. Handles integers. +template +void serial_echopair_PGM(PGM_P const s_P, T v) { serialprintPGM(s_P); SERIAL_ECHO(v); } + inline void serial_echopair_PGM(PGM_P const s_P, bool v) { serial_echopair_PGM(s_P, (int)v); } inline void serial_echopair_PGM(PGM_P const s_P, void *v) { serial_echopair_PGM(s_P, (uintptr_t)v); } -#if __INTPTR_WIDTH__ != __SIZE_WIDTH__ - inline void serial_echopair_PGM(PGM_P const s_P, size_t v) { serial_echopair_PGM(s_P, (long int)v); } -#endif void serial_echo_start(); void serial_error_start(); diff --git a/Marlin/src/core/serial_base.h b/Marlin/src/core/serial_base.h index d8090eb83a..a5abd67d87 100644 --- a/Marlin/src/core/serial_base.h +++ b/Marlin/src/core/serial_base.h @@ -74,12 +74,12 @@ CALL_IF_EXISTS_IMPL(SerialFeature, features, SerialFeature::None); // for any type other than double/float. For double/float, a conversion exists so the call will be invisible. struct EnsureDouble { double a; - FORCE_INLINE operator double() { return a; } + operator double() { return a; } // If the compiler breaks on ambiguity here, it's likely because print(X, base) is called with X not a double/float, and // a base that's not a PrintBase value. This code is made to detect the error. You MUST set a base explicitly like this: // SERIAL_PRINT(v, PrintBase::Hex) - FORCE_INLINE EnsureDouble(double a) : a(a) {} - FORCE_INLINE EnsureDouble(float a) : a(a) {} + EnsureDouble(double a) : a(a) {} + EnsureDouble(float a) : a(a) {} }; // Using Curiously-Recurring Template Pattern here to avoid virtual table cost when compiling. @@ -136,70 +136,90 @@ struct SerialBase { void flushTX() { CALL_IF_EXISTS(void, SerialChild, flushTX); } // Glue code here - FORCE_INLINE void write(const char *str) { while (*str) write(*str++); } - FORCE_INLINE void write(const uint8_t *buffer, size_t size) { while (size--) write(*buffer++); } - FORCE_INLINE void print(const char *str) { write(str); } + void write(const char *str) { while (*str) write(*str++); } + void write(const uint8_t *buffer, size_t size) { while (size--) write(*buffer++); } + void print(char *str) { write(str); } + void print(const char *str) { write(str); } // No default argument to avoid ambiguity - NO_INLINE void print(char c, PrintBase base) { printNumber((signed long)c, (uint8_t)base); } - NO_INLINE void print(unsigned char c, PrintBase base) { printNumber((unsigned long)c, (uint8_t)base); } - NO_INLINE void print(int c, PrintBase base) { printNumber((signed long)c, (uint8_t)base); } - NO_INLINE void print(unsigned int c, PrintBase base) { printNumber((unsigned long)c, (uint8_t)base); } - void print(unsigned long c, PrintBase base) { printNumber((unsigned long)c, (uint8_t)base); } - void print(long c, PrintBase base) { printNumber((signed long)c, (uint8_t)base); } - void print(EnsureDouble c, int digits) { printFloat(c, digits); } + + // Define print for every fundamental integer type, to ensure that all redirect properly + // to the correct underlying implementation. + + // Prints are performed with a single size, to avoid needing multiple print functions. + // The fixed integer size used for prints will be the larger of long or a pointer. + #if __LONG_WIDTH__ >= __INTPTR_WIDTH__ + typedef long int_fixed_print_t; + typedef unsigned long uint_fixed_print_t; + #else + typedef intptr_t int_fixed_print_t; + typedef uintptr_t uint_fixed_print_t; + + FORCE_INLINE void print(intptr_t c, PrintBase base) { printNumber_signed(c, base); } + FORCE_INLINE void print(uintptr_t c, PrintBase base) { printNumber_unsigned(c, base); } + #endif + + FORCE_INLINE void print(char c, PrintBase base) { printNumber_signed(c, base); } + FORCE_INLINE void print(short c, PrintBase base) { printNumber_signed(c, base); } + FORCE_INLINE void print(int c, PrintBase base) { printNumber_signed(c, base); } + FORCE_INLINE void print(long c, PrintBase base) { printNumber_signed(c, base); } + FORCE_INLINE void print(unsigned char c, PrintBase base) { printNumber_unsigned(c, base); } + FORCE_INLINE void print(unsigned short c, PrintBase base) { printNumber_unsigned(c, base); } + FORCE_INLINE void print(unsigned int c, PrintBase base) { printNumber_unsigned(c, base); } + FORCE_INLINE void print(unsigned long c, PrintBase base) { printNumber_unsigned(c, base); } + + + void print(EnsureDouble c, int digits) { printFloat(c, digits); } // Forward the call to the former's method - FORCE_INLINE void print(char c) { print(c, PrintBase::Dec); } - FORCE_INLINE void print(unsigned char c) { print(c, PrintBase::Dec); } - FORCE_INLINE void print(int c) { print(c, PrintBase::Dec); } - FORCE_INLINE void print(unsigned int c) { print(c, PrintBase::Dec); } - FORCE_INLINE void print(unsigned long c) { print(c, PrintBase::Dec); } - FORCE_INLINE void print(long c) { print(c, PrintBase::Dec); } - FORCE_INLINE void print(double c) { print(c, 2); } - FORCE_INLINE void println(const char s[]) { print(s); println(); } - FORCE_INLINE void println(char c, PrintBase base) { print(c, base); println(); } - FORCE_INLINE void println(unsigned char c, PrintBase base) { print(c, base); println(); } - FORCE_INLINE void println(int c, PrintBase base) { print(c, base); println(); } - FORCE_INLINE void println(unsigned int c, PrintBase base) { print(c, base); println(); } - FORCE_INLINE void println(long c, PrintBase base) { print(c, base); println(); } - FORCE_INLINE void println(unsigned long c, PrintBase base) { print(c, base); println(); } - FORCE_INLINE void println(double c, int digits) { print(c, digits); println(); } - FORCE_INLINE void println() { write('\r'); write('\n'); } + // Default implementation for anything without a specialization + // This handles integers since they are the most common + template + void print(T c) { print(c, PrintBase::Dec); } + + void print(float c) { print(c, 2); } + void print(double c) { print(c, 2); } + + void println(char *s) { print(s); println(); } + void println(const char *s) { print(s); println(); } + void println(float c, int digits) { print(c, digits); println(); } + void println(double c, int digits) { print(c, digits); println(); } + void println() { write('\r'); write('\n'); } + + // Default implementations for types without a specialization. Handles integers. + template + void println(T c, PrintBase base) { print(c, base); println(); } + + template + void println(T c) { println(c, PrintBase::Dec); } // Forward the call to the former's method - FORCE_INLINE void println(char c) { println(c, PrintBase::Dec); } - FORCE_INLINE void println(unsigned char c) { println(c, PrintBase::Dec); } - FORCE_INLINE void println(int c) { println(c, PrintBase::Dec); } - FORCE_INLINE void println(unsigned int c) { println(c, PrintBase::Dec); } - FORCE_INLINE void println(unsigned long c) { println(c, PrintBase::Dec); } - FORCE_INLINE void println(long c) { println(c, PrintBase::Dec); } - FORCE_INLINE void println(double c) { println(c, 2); } + void println(float c) { println(c, 2); } + void println(double c) { println(c, 2); } // Print a number with the given base - NO_INLINE void printNumber(unsigned long n, const uint8_t base) { - if (!base) return; // Hopefully, this should raise visible bug immediately - + NO_INLINE void printNumber_unsigned(uint_fixed_print_t n, PrintBase base) { if (n) { unsigned char buf[8 * sizeof(long)]; // Enough space for base 2 int8_t i = 0; while (n) { - buf[i++] = n % base; - n /= base; + buf[i++] = n % (uint_fixed_print_t)base; + n /= (uint_fixed_print_t)base; } while (i--) write((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10))); } else write('0'); } - void printNumber(signed long n, const uint8_t base) { - if (base == 10 && n < 0) { + + NO_INLINE void printNumber_signed(int_fixed_print_t n, PrintBase base) { + if (base == PrintBase::Dec && n < 0) { n = -n; // This works because all platforms Marlin's builds on are using 2-complement encoding for negative number // On such CPU, changing the sign of a number is done by inverting the bits and adding one, so if n = 0x80000000 = -2147483648 then // -n = 0x7FFFFFFF + 1 => 0x80000000 = 2147483648 (if interpreted as unsigned) or -2147483648 if interpreted as signed. // On non 2-complement CPU, there would be no possible representation for 2147483648. write('-'); } - printNumber((unsigned long)n , base); + printNumber_unsigned((uint_fixed_print_t)n , base); } // Print a decimal number @@ -218,7 +238,7 @@ struct SerialBase { // Extract the integer part of the number and print it unsigned long int_part = (unsigned long)number; double remainder = number - (double)int_part; - printNumber(int_part, 10); + printNumber_unsigned(int_part, PrintBase::Dec); // Print the decimal point, but only if there are digits beyond if (digits) { @@ -227,7 +247,7 @@ struct SerialBase { while (digits--) { remainder *= 10.0; unsigned long toPrint = (unsigned long)remainder; - printNumber(toPrint, 10); + printNumber_unsigned(toPrint, PrintBase::Dec); remainder -= toPrint; } } diff --git a/Marlin/src/feature/tmc_util.cpp b/Marlin/src/feature/tmc_util.cpp index 48b26cc101..99cfd996c8 100644 --- a/Marlin/src/feature/tmc_util.cpp +++ b/Marlin/src/feature/tmc_util.cpp @@ -208,7 +208,7 @@ #if ENABLED(STOP_ON_ERROR) void report_driver_error(const TMC_driver_data &data) { SERIAL_ECHOPGM(" driver error detected: 0x"); - SERIAL_PRINTLN(data.drv_status, HEX); + SERIAL_PRINTLN(data.drv_status, PrintBase::Hex); if (data.is_ot) SERIAL_ECHOLNPGM("overtemperature"); if (data.is_s2g) SERIAL_ECHOLNPGM("coil short circuit"); TERN_(TMC_DEBUG, tmc_report_all()); diff --git a/Marlin/src/feature/tmc_util.h b/Marlin/src/feature/tmc_util.h index c878d86fae..87780486eb 100644 --- a/Marlin/src/feature/tmc_util.h +++ b/Marlin/src/feature/tmc_util.h @@ -330,7 +330,7 @@ void tmc_print_current(TMC &st) { void tmc_print_sgt(TMC &st) { st.printLabel(); SERIAL_ECHOPGM(" homing sensitivity: "); - SERIAL_PRINTLN(st.homing_threshold(), DEC); + SERIAL_PRINTLN(st.homing_threshold(), PrintBase::Dec); } #endif diff --git a/ini/native.ini b/ini/native.ini index b40ea836da..548e791f5a 100644 --- a/ini/native.ini +++ b/ini/native.ini @@ -120,11 +120,11 @@ build_unflags = ${simulator_macos.build_unflags} # Simulator for Windows 10 # # MSYS2 mingw-w64-x86_64 with these packages: -# pacman -S --needed base-devel mingw-w64-x86_64-toolchain mingw64/mingw-w64-x86_64-glm mingw64/mingw-w64-x86_64-SDL2 mingw64/mingw-w64-x86_64-SDL2_net +# pacman -S --needed base-devel mingw-w64-x86_64-toolchain mingw64/mingw-w64-x86_64-glm mingw64/mingw-w64-x86_64-SDL2 mingw64/mingw-w64-x86_64-SDL2_net mingw-w64-x86_64-dlfcn # [env:simulator_windows] platform = ${simulator_common.platform} extends = simulator_common src_build_flags = ${simulator_common.src_build_flags} -fpermissive -build_flags = ${simulator_common.build_flags} ${simulator_common.debug_build_flags} -fno-stack-protector -Wl,-subsystem,windows -ldl -lmingw32 -lSDL2main -lSDL2 -lSDL2_net -lopengl32 -lssp +build_flags = ${simulator_common.build_flags} ${simulator_common.debug_build_flags} -IC:\\msys64\\mingw64\\include\\SDL2 -fno-stack-protector -Wl,-subsystem,windows -ldl -lmingw32 -lSDL2main -lSDL2 -lSDL2_net -lopengl32 -lssp build_type = debug