From ad3801a3f0a10ad85e0653ebc9e6fff1489b4113 Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Wed, 4 Aug 2021 21:04:11 -0700 Subject: [PATCH 01/12] Add missing lib to native.ini --- ini/native.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ini/native.ini b/ini/native.ini index b40ea836da8d..84a97be1381d 100644 --- a/ini/native.ini +++ b/ini/native.ini @@ -120,7 +120,7 @@ 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} From 60a98784aa66f567209b3f86c8c6ebcc081c4dc8 Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Wed, 4 Aug 2021 21:20:01 -0700 Subject: [PATCH 02/12] Inlcud u8glib-HAL in simulator --- Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_st7920_sw_spi.cpp | 2 +- Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_sw_spi.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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 e95c6ebfbd03..c77c3d30f09a 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 8e0ac9c7df35..085954803cf2 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__ From c4ae88690b1831be83d9e1b1b521c4206e51995b Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Wed, 4 Aug 2021 22:37:15 -0700 Subject: [PATCH 03/12] Avoid duplicate function definitions in pinsDebug.h for simulator --- Marlin/src/HAL/NATIVE_SIM/pinsDebug.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Marlin/src/HAL/NATIVE_SIM/pinsDebug.h b/Marlin/src/HAL/NATIVE_SIM/pinsDebug.h index 2aeeb52e92d7..7ba14574d0c7 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)); } From 3f49469a9a7fcfdfc43e5de0630f768c127c7e41 Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Wed, 4 Aug 2021 22:41:56 -0700 Subject: [PATCH 04/12] Add default include path to build parameters for Windows simulator --- ini/native.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ini/native.ini b/ini/native.ini index 84a97be1381d..548e791f5a02 100644 --- a/ini/native.ini +++ b/ini/native.ini @@ -126,5 +126,5 @@ build_unflags = ${simulator_macos.build_unflags} 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 From 06e1faaa72fa62797a407a96a7315c83b9bccd1a Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Wed, 4 Aug 2021 22:49:52 -0700 Subject: [PATCH 05/12] Remove integer type assumptions from serial print helpers. Compiling the simulator for Windows is very problematic due to differing type definitions across platforms. Rather than adding a bunch of conditional compilation for different platforms, use templates which can handle any integer width. --- Marlin/src/core/serial.cpp | 11 ----- Marlin/src/core/serial.h | 23 +++++------ Marlin/src/core/serial_base.h | 78 ++++++++++++++++++++--------------- 3 files changed, 54 insertions(+), 58 deletions(-) diff --git a/Marlin/src/core/serial.cpp b/Marlin/src/core/serial.cpp index 2e3a39b66a72..50cc50ad574a 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 7f96a30d6f71..87486b3e5c4a 100644 --- a/Marlin/src/core/serial.h +++ b/Marlin/src/core/serial.h @@ -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 intgers. +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 d8090eb83ad9..8db6bc658842 100644 --- a/Marlin/src/core/serial_base.h +++ b/Marlin/src/core/serial_base.h @@ -22,6 +22,7 @@ #pragma once #include "../inc/MarlinConfigPre.h" +#include #if ENABLED(EMERGENCY_PARSER) #include "../feature/e_parser.h" @@ -138,50 +139,57 @@ struct SerialBase { // 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(char *str) { write(str); } FORCE_INLINE 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); } + NO_INLINE void print(int8_t c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + NO_INLINE void print(uint8_t c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + NO_INLINE void print(int16_t c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + NO_INLINE void print(uint16_t c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + NO_INLINE void print(int32_t c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + NO_INLINE void print(uint32_t c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + NO_INLINE void print(int64_t c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + NO_INLINE void print(uint64_t c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + + void print(unsigned long c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + void print(long c, PrintBase base) { printNumber_signed(c, (uint8_t)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(); } + + // Default implementation for anything without a specialization + // This handles integers since they are the most common + template + FORCE_INLINE void print(T c) { print(c, PrintBase::Dec); } + + FORCE_INLINE void print(float c) { print(c, 2); } + FORCE_INLINE void print(double c) { print(c, 2); } + + FORCE_INLINE void println(char *s) { print(s); println(); } + FORCE_INLINE void println(const char *s) { print(s); println(); } + FORCE_INLINE void println(float c, int digits) { print(c, digits); println(); } FORCE_INLINE void println(double c, int digits) { print(c, digits); println(); } FORCE_INLINE void println() { write('\r'); write('\n'); } + // Default implementations for types without a specialization. Handles integers. + template + FORCE_INLINE void println(T c, PrintBase base) { print(c, base); println(); } + + template + FORCE_INLINE 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(float c) { println(c, 2); } FORCE_INLINE 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) { + template + NO_INLINE void printNumber_unsigned(T n, const uint8_t base) { if (!base) return; // Hopefully, this should raise visible bug immediately if (n) { - unsigned char buf[8 * sizeof(long)]; // Enough space for base 2 + unsigned char buf[8 * sizeof(T)]; // Enough space for base 2 int8_t i = 0; while (n) { buf[i++] = n % base; @@ -191,7 +199,9 @@ struct SerialBase { } else write('0'); } - void printNumber(signed long n, const uint8_t base) { + + template + void printNumber_signed(T n, const uint8_t base) { if (base == 10 && 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 @@ -199,7 +209,7 @@ struct SerialBase { // On non 2-complement CPU, there would be no possible representation for 2147483648. write('-'); } - printNumber((unsigned long)n , base); + printNumber_unsigned((typename std::make_unsigned::type)(n), base); } // Print a decimal number @@ -218,7 +228,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, 10); // Print the decimal point, but only if there are digits beyond if (digits) { @@ -227,7 +237,7 @@ struct SerialBase { while (digits--) { remainder *= 10.0; unsigned long toPrint = (unsigned long)remainder; - printNumber(toPrint, 10); + printNumber_unsigned(toPrint, 10); remainder -= toPrint; } } From 8a4524ca589227b33f419ad47479a642345c4d8d Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Wed, 4 Aug 2021 23:11:25 -0700 Subject: [PATCH 06/12] Define print for long long --- Marlin/src/core/serial_base.h | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Marlin/src/core/serial_base.h b/Marlin/src/core/serial_base.h index 8db6bc658842..d06415e2eae1 100644 --- a/Marlin/src/core/serial_base.h +++ b/Marlin/src/core/serial_base.h @@ -142,17 +142,20 @@ struct SerialBase { FORCE_INLINE void print(char *str) { write(str); } FORCE_INLINE void print(const char *str) { write(str); } // No default argument to avoid ambiguity - NO_INLINE void print(int8_t c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - NO_INLINE void print(uint8_t c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } - NO_INLINE void print(int16_t c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - NO_INLINE void print(uint16_t c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } - NO_INLINE void print(int32_t c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - NO_INLINE void print(uint32_t c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } - NO_INLINE void print(int64_t c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - NO_INLINE void print(uint64_t c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } - - void print(unsigned long c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } - void print(long c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + + // Defint print for every fundamental integer type, to ensure that all redirect properly + // to the underlying templated implementations. + NO_INLINE void print(char c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + NO_INLINE void print(short c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + NO_INLINE void print(int c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + NO_INLINE void print(long c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + NO_INLINE void print(long long c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + NO_INLINE void print(unsigned char c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + NO_INLINE void print(unsigned short c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + NO_INLINE void print(unsigned int c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + NO_INLINE void print(unsigned long c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + NO_INLINE void print(unsigned long long c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + void print(EnsureDouble c, int digits) { printFloat(c, digits); } // Forward the call to the former's method From ad3ee532514d13f4257f7def9284fba6c9412294 Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Wed, 4 Aug 2021 23:51:10 -0700 Subject: [PATCH 07/12] Fix typos --- Marlin/src/core/serial.h | 2 +- Marlin/src/core/serial_base.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Marlin/src/core/serial.h b/Marlin/src/core/serial.h index 87486b3e5c4a..5a3b735578c6 100644 --- a/Marlin/src/core/serial.h +++ b/Marlin/src/core/serial.h @@ -299,7 +299,7 @@ inline void serial_echopair_PGM(PGM_P const s_P, float v) { serialprintP 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 intgers. +// 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); } diff --git a/Marlin/src/core/serial_base.h b/Marlin/src/core/serial_base.h index d06415e2eae1..3ddeaf9c1f70 100644 --- a/Marlin/src/core/serial_base.h +++ b/Marlin/src/core/serial_base.h @@ -143,7 +143,7 @@ struct SerialBase { FORCE_INLINE void print(const char *str) { write(str); } // No default argument to avoid ambiguity - // Defint print for every fundamental integer type, to ensure that all redirect properly + // Define print for every fundamental integer type, to ensure that all redirect properly // to the underlying templated implementations. NO_INLINE void print(char c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } NO_INLINE void print(short c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } From 5b2124703470fa3e69f186406a8ebf0ef7347613 Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Wed, 4 Aug 2021 23:52:21 -0700 Subject: [PATCH 08/12] Remove templates from printNumber_signed and printNumber_unsigned. This eliminates the need for make_unsigned, which is not available on Arduino. --- Marlin/src/core/serial_base.h | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/Marlin/src/core/serial_base.h b/Marlin/src/core/serial_base.h index 3ddeaf9c1f70..72101f9f7dbd 100644 --- a/Marlin/src/core/serial_base.h +++ b/Marlin/src/core/serial_base.h @@ -22,7 +22,6 @@ #pragma once #include "../inc/MarlinConfigPre.h" -#include #if ENABLED(EMERGENCY_PARSER) #include "../feature/e_parser.h" @@ -145,16 +144,29 @@ struct SerialBase { // Define print for every fundamental integer type, to ensure that all redirect properly // to the underlying templated implementations. + + // 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; + + NO_INLINE void print(intptr_t c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + NO_INLINE void print(uintptr_t c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + #endif + NO_INLINE void print(char c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } NO_INLINE void print(short c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } NO_INLINE void print(int c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } NO_INLINE void print(long c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - NO_INLINE void print(long long c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } NO_INLINE void print(unsigned char c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } NO_INLINE void print(unsigned short c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } NO_INLINE void print(unsigned int c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } NO_INLINE void print(unsigned long c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } - NO_INLINE void print(unsigned long long c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + void print(EnsureDouble c, int digits) { printFloat(c, digits); } @@ -185,14 +197,12 @@ struct SerialBase { FORCE_INLINE void println(float c) { println(c, 2); } FORCE_INLINE void println(double c) { println(c, 2); } - // Print a number with the given base - template - NO_INLINE void printNumber_unsigned(T n, const uint8_t base) { + NO_INLINE void printNumber_unsigned(uint_fixed_print_t n, const uint8_t base) { if (!base) return; // Hopefully, this should raise visible bug immediately if (n) { - unsigned char buf[8 * sizeof(T)]; // Enough space for base 2 + unsigned char buf[8 * sizeof(long)]; // Enough space for base 2 int8_t i = 0; while (n) { buf[i++] = n % base; @@ -203,8 +213,7 @@ struct SerialBase { else write('0'); } - template - void printNumber_signed(T n, const uint8_t base) { + NO_INLINE void printNumber_signed(int_fixed_print_t n, const uint8_t base) { if (base == 10 && 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 @@ -212,7 +221,7 @@ struct SerialBase { // On non 2-complement CPU, there would be no possible representation for 2147483648. write('-'); } - printNumber_unsigned((typename std::make_unsigned::type)(n), base); + printNumber_unsigned((uint_fixed_print_t)n , base); } // Print a decimal number From ef2fbb1106a964fe98ec9e7e95e3f90171f5c043 Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Thu, 5 Aug 2021 00:19:53 -0700 Subject: [PATCH 09/12] Cosmetic alignment --- Marlin/src/core/serial_base.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Marlin/src/core/serial_base.h b/Marlin/src/core/serial_base.h index 72101f9f7dbd..a3965091bccd 100644 --- a/Marlin/src/core/serial_base.h +++ b/Marlin/src/core/serial_base.h @@ -180,15 +180,15 @@ struct SerialBase { FORCE_INLINE void print(float c) { print(c, 2); } FORCE_INLINE void print(double c) { print(c, 2); } - FORCE_INLINE void println(char *s) { print(s); println(); } - FORCE_INLINE void println(const char *s) { print(s); println(); } - FORCE_INLINE void println(float c, int digits) { print(c, digits); println(); } - FORCE_INLINE void println(double c, int digits) { print(c, digits); println(); } - FORCE_INLINE void println() { write('\r'); write('\n'); } + FORCE_INLINE void println(char *s) { print(s); println(); } + FORCE_INLINE void println(const char *s) { print(s); println(); } + FORCE_INLINE void println(float c, int digits) { print(c, digits); println(); } + FORCE_INLINE void println(double c, int digits) { print(c, digits); println(); } + FORCE_INLINE void println() { write('\r'); write('\n'); } // Default implementations for types without a specialization. Handles integers. template - FORCE_INLINE void println(T c, PrintBase base) { print(c, base); println(); } + FORCE_INLINE void println(T c, PrintBase base) { print(c, base); println(); } template FORCE_INLINE void println(T c) { println(c, PrintBase::Dec); } From 490377c6815761a3d0b5931b95db52b8071035a2 Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Thu, 5 Aug 2021 00:20:11 -0700 Subject: [PATCH 10/12] Fix ambiguous overloads related to PrintBase. --- Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp | 4 ++-- Marlin/src/core/serial.h | 4 ++-- Marlin/src/feature/tmc_util.cpp | 2 +- Marlin/src/feature/tmc_util.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp b/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp index 9a1b4caf8d8c..0f0f7c480727 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.h b/Marlin/src/core/serial.h index 5a3b735578c6..dfcf23ddb60f 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(); } diff --git a/Marlin/src/feature/tmc_util.cpp b/Marlin/src/feature/tmc_util.cpp index 48b26cc101de..99cfd996c843 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 c878d86faedd..87780486ebaa 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 From 22034f566779fb555783644d4fcf69bc50e05d0b Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Thu, 5 Aug 2021 23:05:45 -0700 Subject: [PATCH 11/12] Remove unnecessary NO_INLINE and FORCE_INLINE attributes in serial_base.h --- Marlin/src/core/serial_base.h | 60 +++++++++++++++++------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/Marlin/src/core/serial_base.h b/Marlin/src/core/serial_base.h index a3965091bccd..f4ec2e30a097 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,14 +136,14 @@ 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(char *str) { write(str); } - 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 // Define print for every fundamental integer type, to ensure that all redirect properly - // to the underlying templated implementations. + // 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. @@ -154,18 +154,18 @@ struct SerialBase { typedef intptr_t int_fixed_print_t; typedef uintptr_t uint_fixed_print_t; - NO_INLINE void print(intptr_t c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - NO_INLINE void print(uintptr_t c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + void print(intptr_t c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + void print(uintptr_t c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } #endif - NO_INLINE void print(char c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - NO_INLINE void print(short c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - NO_INLINE void print(int c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - NO_INLINE void print(long c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - NO_INLINE void print(unsigned char c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } - NO_INLINE void print(unsigned short c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } - NO_INLINE void print(unsigned int c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } - NO_INLINE void print(unsigned long c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + void print(char c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + void print(short c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + void print(int c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + void print(long c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } + void print(unsigned char c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + void print(unsigned short c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + void print(unsigned int c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + void print(unsigned long c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } void print(EnsureDouble c, int digits) { printFloat(c, digits); } @@ -175,27 +175,27 @@ struct SerialBase { // Default implementation for anything without a specialization // This handles integers since they are the most common template - FORCE_INLINE void print(T c) { print(c, PrintBase::Dec); } + void print(T c) { print(c, PrintBase::Dec); } - FORCE_INLINE void print(float c) { print(c, 2); } - FORCE_INLINE void print(double c) { print(c, 2); } + void print(float c) { print(c, 2); } + void print(double c) { print(c, 2); } - FORCE_INLINE void println(char *s) { print(s); println(); } - FORCE_INLINE void println(const char *s) { print(s); println(); } - FORCE_INLINE void println(float c, int digits) { print(c, digits); println(); } - FORCE_INLINE void println(double c, int digits) { print(c, digits); println(); } - FORCE_INLINE void println() { write('\r'); write('\n'); } + 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 - FORCE_INLINE void println(T c, PrintBase base) { print(c, base); println(); } + void println(T c, PrintBase base) { print(c, base); println(); } template - FORCE_INLINE void println(T c) { println(c, PrintBase::Dec); } + void println(T c) { println(c, PrintBase::Dec); } // Forward the call to the former's method - FORCE_INLINE void println(float c) { println(c, 2); } - 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(uint_fixed_print_t n, const uint8_t base) { From 68d161529e7ffd99196dd3720e09b487d344b401 Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Thu, 5 Aug 2021 23:23:36 -0700 Subject: [PATCH 12/12] FORCE_INLINE print functions which simply pass through to another functon call. Use PrintBase in more locations in serial_base --- Marlin/src/core/serial_base.h | 36 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/Marlin/src/core/serial_base.h b/Marlin/src/core/serial_base.h index f4ec2e30a097..a5abd67d8727 100644 --- a/Marlin/src/core/serial_base.h +++ b/Marlin/src/core/serial_base.h @@ -154,18 +154,18 @@ struct SerialBase { typedef intptr_t int_fixed_print_t; typedef uintptr_t uint_fixed_print_t; - void print(intptr_t c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - void print(uintptr_t c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + 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 - void print(char c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - void print(short c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - void print(int c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - void print(long c, PrintBase base) { printNumber_signed(c, (uint8_t)base); } - void print(unsigned char c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } - void print(unsigned short c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } - void print(unsigned int c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } - void print(unsigned long c, PrintBase base) { printNumber_unsigned(c, (uint8_t)base); } + 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); } @@ -198,23 +198,21 @@ struct SerialBase { void println(double c) { println(c, 2); } // Print a number with the given base - NO_INLINE void printNumber_unsigned(uint_fixed_print_t 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'); } - NO_INLINE void printNumber_signed(int_fixed_print_t 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. @@ -240,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_unsigned(int_part, 10); + printNumber_unsigned(int_part, PrintBase::Dec); // Print the decimal point, but only if there are digits beyond if (digits) { @@ -249,7 +247,7 @@ struct SerialBase { while (digits--) { remainder *= 10.0; unsigned long toPrint = (unsigned long)remainder; - printNumber_unsigned(toPrint, 10); + printNumber_unsigned(toPrint, PrintBase::Dec); remainder -= toPrint; } }