diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 3127d59e8b..4dbc2a8c11 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1751,6 +1751,21 @@ //#define V_HOME_DIR -1 //#define W_HOME_DIR -1 +/** + * Safety Stops + * If an axis has endstops on both ends the one specified above is used for + * homing, while the other can be used for things like SD_ABORT_ON_ENDSTOP_HIT. + */ +//#define X_SAFETY_STOP +//#define Y_SAFETY_STOP +//#define Z_SAFETY_STOP +//#define I_SAFETY_STOP +//#define J_SAFETY_STOP +//#define K_SAFETY_STOP +//#define U_SAFETY_STOP +//#define V_SAFETY_STOP +//#define W_SAFETY_STOP + // @section geometry // The size of the printable area @@ -3108,7 +3123,7 @@ * - Download https://github.com/InsanityAutomation/Marlin/raw/CrealityDwin_2.0/TM3D_Combined480272_Landscape_V7.7z * - Copy the downloaded DWIN_SET folder to the SD card. * - * E3S1PRO (T5UID1) + * E3S1PRO (T5L) * - Download https://github.com/CrealityOfficial/Ender-3S1/archive/3S1_Plus_Screen.zip * - Copy the downloaded DWIN_SET folder to the SD card. * diff --git a/Marlin/Version.h b/Marlin/Version.h index 37e76fbecd..f93128f200 100644 --- a/Marlin/Version.h +++ b/Marlin/Version.h @@ -41,7 +41,7 @@ * here we define this default string as the date where the latest release * version was tagged. */ -//#define STRING_DISTRIBUTION_DATE "2023-07-24" +//#define STRING_DISTRIBUTION_DATE "2023-08-04" /** * Defines a generic printer name to be output to the LCD after booting Marlin. diff --git a/Marlin/src/HAL/AVR/HAL.cpp b/Marlin/src/HAL/AVR/HAL.cpp index b3dcfbdf59..407a570cde 100644 --- a/Marlin/src/HAL/AVR/HAL.cpp +++ b/Marlin/src/HAL/AVR/HAL.cpp @@ -61,23 +61,40 @@ void save_reset_reason() { wdt_disable(); } +#include "registers.h" + +MarlinHAL::MarlinHAL() { + TERN_(HAL_AVR_DIRTY_INIT, _ATmega_resetperipherals()); // Clean-wipe the device state. +} + void MarlinHAL::init() { // Init Servo Pins - #define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW) #if HAS_SERVO_0 - INIT_SERVO(0); + OUT_WRITE(SERVO0_PIN, LOW); #endif #if HAS_SERVO_1 - INIT_SERVO(1); + OUT_WRITE(SERVO1_PIN, LOW); #endif #if HAS_SERVO_2 - INIT_SERVO(2); + OUT_WRITE(SERVO2_PIN, LOW); #endif #if HAS_SERVO_3 - INIT_SERVO(3); + OUT_WRITE(SERVO3_PIN, LOW); #endif init_pwm_timers(); // Init user timers to default frequency - 1000HZ + + #if PIN_EXISTS(BEEPER) && ENABLED(HAL_AVR_DIRTY_INIT) && DISABLED(ATMEGA_NO_BEEPFIX) + // Make sure no alternative is locked onto the BEEPER. + // This fixes the issue where the ATmega is constantly beeping. + // Might disable other peripherals using the pin; to circumvent that please undefine one of the above things! + // The true culprit is the AVR ArduinoCore that enables peripherals redundantly. + // (USART1 on the GeeeTech GT2560) + // https://www.youtube.com/watch?v=jMgCvRXkexk + _ATmega_savePinAlternate(BEEPER_PIN); + + OUT_WRITE(BEEPER_PIN, LOW); + #endif } void MarlinHAL::reboot() { diff --git a/Marlin/src/HAL/AVR/HAL.h b/Marlin/src/HAL/AVR/HAL.h index 16878a8ab8..7d5e1000d7 100644 --- a/Marlin/src/HAL/AVR/HAL.h +++ b/Marlin/src/HAL/AVR/HAL.h @@ -187,7 +187,7 @@ class MarlinHAL { public: // Earliest possible init, before setup() - MarlinHAL() {} + MarlinHAL(); // Watchdog static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {}); diff --git a/Marlin/src/HAL/AVR/endstop_interrupts.h b/Marlin/src/HAL/AVR/endstop_interrupts.h index ac827f1842..2532624d39 100644 --- a/Marlin/src/HAL/AVR/endstop_interrupts.h +++ b/Marlin/src/HAL/AVR/endstop_interrupts.h @@ -160,7 +160,7 @@ void setup_endstop_interrupts() { pciSetup(Z_MAX_PIN); #endif #endif - #if HAS_Z_MIN_PIN + #if USE_Z_MIN #if (digitalPinToInterrupt(Z_MIN_PIN) != NOT_AN_INTERRUPT) _ATTACH(Z_MIN_PIN); #else diff --git a/Marlin/src/HAL/AVR/inc/SanityCheck.h b/Marlin/src/HAL/AVR/inc/SanityCheck.h index 6a7e172889..85ee683685 100644 --- a/Marlin/src/HAL/AVR/inc/SanityCheck.h +++ b/Marlin/src/HAL/AVR/inc/SanityCheck.h @@ -33,13 +33,13 @@ * Check for common serial pin conflicts */ #define CHECK_SERIAL_PIN(N) ( \ - X_STOP_PIN == N || Y_STOP_PIN == N || Z_STOP_PIN == N \ - || X_MIN_PIN == N || Y_MIN_PIN == N || Z_MIN_PIN == N \ - || X_MAX_PIN == N || Y_MAX_PIN == N || Z_MAX_PIN == N \ - || X_STEP_PIN == N || Y_STEP_PIN == N || Z_STEP_PIN == N \ - || X_DIR_PIN == N || Y_DIR_PIN == N || Z_DIR_PIN == N \ - || X_ENA_PIN == N || Y_ENA_PIN == N || Z_ENA_PIN == N \ - || BTN_EN1 == N || BTN_EN2 == N \ + X_STOP_PIN == N || Y_STOP_PIN == N || Z_STOP_PIN == N \ + || X_MIN_PIN == N || Y_MIN_PIN == N || Z_MIN_PIN == N \ + || X_MAX_PIN == N || Y_MAX_PIN == N || Z_MAX_PIN == N \ + || X_STEP_PIN == N || Y_STEP_PIN == N || Z_STEP_PIN == N \ + || X_DIR_PIN == N || Y_DIR_PIN == N || Z_DIR_PIN == N \ + || X_ENA_PIN == N || Y_ENA_PIN == N || Z_ENA_PIN == N \ + || BTN_EN1 == N || BTN_EN2 == N || LCD_PINS_EN == N \ ) #if SERIAL_IN_USE(0) // D0-D1. No known conflicts. diff --git a/Marlin/src/HAL/AVR/registers.cpp b/Marlin/src/HAL/AVR/registers.cpp new file mode 100644 index 0000000000..08a74c952a --- /dev/null +++ b/Marlin/src/HAL/AVR/registers.cpp @@ -0,0 +1,979 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * 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 + * along with this program. If not, see . + * + */ + +#ifdef __AVR__ + +#include "../../inc/MarlinConfigPre.h" + +#if ENABLED(HAL_AVR_DIRTY_INIT) + +#include "registers.h" + +// Since the compiler could be creating multiple copies of function code-graphs for each header inline-inclusion, +// we want to off-load the function definitions that define static memory into this solitary compilation unit. +// This way the ROM is NOT bloated (who knows if the compiler is optimizing same-content constant objects into one?) + +ATmegaPinFunctions _ATmega_getPinFunctions(int pin) { + if (pin < 0) return {}; + + ATmegaPinInfo info = _ATmega_getPinInfo((unsigned int)pin); + + #ifdef __AVR_TRM01__ + if (info.port == eATmegaPort::PORT_A) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD7 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD6 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD5 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD4 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD3 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD2 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD1 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD0 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_B) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC0A, eATmegaPinFunc::TOC1C, eATmegaPinFunc::PCI7 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC1B, eATmegaPinFunc::PCI6 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC1A, eATmegaPinFunc::PCI5 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC2A, eATmegaPinFunc::PCI4 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_MISO, eATmegaPinFunc::PCI3 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_MOSI, eATmegaPinFunc::PCI2 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_SCK, eATmegaPinFunc::PCI1 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_CS, eATmegaPinFunc::PCI0 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_C) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD15 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD14 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD13 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD12 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD11 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD10 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD9 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD8 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_D) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER0_CLKI }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER1_CLKI }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART1_CLK }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER1_ICP }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT3, eATmegaPinFunc::USART1_TXD }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT2, eATmegaPinFunc::USART1_RXD }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT1, eATmegaPinFunc::TWI_SDA }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT0, eATmegaPinFunc::TWI_CLK }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_E) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT7, eATmegaPinFunc::TIMER3_ICP, eATmegaPinFunc::CLKO }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT6, eATmegaPinFunc::TIMER3_CLKI }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT5, eATmegaPinFunc::TOC3C }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT4, eATmegaPinFunc::TOC3B }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::AIN1, eATmegaPinFunc::TOC3A }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::AIN0, eATmegaPinFunc::USART0_CLK }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PDO, eATmegaPinFunc::USART0_TXD }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PDI, eATmegaPinFunc::USART0_RXD, eATmegaPinFunc::PCI8 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_F) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC7 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC6 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC5 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC4 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC3 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC2 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC1 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC0 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_G) { + if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC0B }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOSC1 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3 ) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOSC2 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_ALE }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_RD }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_WR }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_H) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER4_CLKI }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC2B }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC4C }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC4B }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC4A }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART2_CLK }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART2_TXD }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART2_RXD }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_J) { + if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI15 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI14 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI13 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI12 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART3_CLK, eATmegaPinFunc::PCI11 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART3_TXD, eATmegaPinFunc::PCI10 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART3_RXD, eATmegaPinFunc::PCI9 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_K) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC15, eATmegaPinFunc::PCI23 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC14, eATmegaPinFunc::PCI22 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC13, eATmegaPinFunc::PCI21 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC12, eATmegaPinFunc::PCI20 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC11, eATmegaPinFunc::PCI19 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC10, eATmegaPinFunc::PCI18 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC9, eATmegaPinFunc::PCI17 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC8, eATmegaPinFunc::PCI16 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_L) { + if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC5C }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC5B }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC5A }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER5_CLKI }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER5_ICP }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER4_ICP }; + return { funcs, countof(funcs) }; + } + } + #elif defined(__AVR_TRM02__) + if (info.port == eATmegaPort::PORT_A) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI7, eATmegaPinFunc::ADC7 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI6, eATmegaPinFunc::ADC6 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI5, eATmegaPinFunc::ADC5 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI4, eATmegaPinFunc::ADC4 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI3, eATmegaPinFunc::ADC3 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI2, eATmegaPinFunc::ADC2 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI1, eATmegaPinFunc::ADC1 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI0, eATmegaPinFunc::ADC0 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_B) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_SCK, eATmegaPinFunc::TOC3B, eATmegaPinFunc::PCI15 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_MISO, eATmegaPinFunc::TOC3A, eATmegaPinFunc::PCI14 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_MOSI, eATmegaPinFunc::TIMER3_ICP, eATmegaPinFunc::PCI13 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_CS, eATmegaPinFunc::TOC0B, eATmegaPinFunc::PCI12 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::AIN1, eATmegaPinFunc::TOC0A, eATmegaPinFunc::PCI11 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::AIN0, eATmegaPinFunc::EINT2, eATmegaPinFunc::PCI10 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER1_ECI, eATmegaPinFunc::CLKO, eATmegaPinFunc::PCI9 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER0_ECI, eATmegaPinFunc::USART0_CLK, eATmegaPinFunc::PCI8 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_C) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOSC2, eATmegaPinFunc::PCI23 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOSC1, eATmegaPinFunc::PCI22 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI21 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI20 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI19 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI18 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI17, eATmegaPinFunc::TWI_SDA }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TWI_CLK, eATmegaPinFunc::PCI16 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_D) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC2A, eATmegaPinFunc::PCI31 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER1_ICP, eATmegaPinFunc::TOC2B, eATmegaPinFunc::PCI30 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC1A, eATmegaPinFunc::PCI29 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC1B, eATmegaPinFunc::USART1_CLK, eATmegaPinFunc::PCI28 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT1, eATmegaPinFunc::USART1_TXD, eATmegaPinFunc::PCI27 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT0, eATmegaPinFunc::USART1_RXD, eATmegaPinFunc::PCI26 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART0_TXD, eATmegaPinFunc::PCI25 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART0_TXD, eATmegaPinFunc::PCI24, eATmegaPinFunc::TIMER3_ECI }; + return { funcs, countof(funcs) }; + } + } + #elif defined(__AVR_TRM03__) + if (info.port == eATmegaPort::PORT_B) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::XTAL2, eATmegaPinFunc::TOSC2, eATmegaPinFunc::PCI7 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::XTAL1, eATmegaPinFunc::TOSC1, eATmegaPinFunc::PCI6 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_SCK, eATmegaPinFunc::PCI5 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_MISO, eATmegaPinFunc::PCI4 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_MOSI, eATmegaPinFunc::TOC2A, eATmegaPinFunc::PCI3 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_CS, eATmegaPinFunc::TOC1B, eATmegaPinFunc::PCI2 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC1A, eATmegaPinFunc::PCI1 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER1_ICP, eATmegaPinFunc::CLKO, eATmegaPinFunc::PCI0 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_C) { + if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI14 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC5, eATmegaPinFunc::TWI_CLK, eATmegaPinFunc::PCI13 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC4, eATmegaPinFunc::TWI_SDA, eATmegaPinFunc::PCI12 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC3, eATmegaPinFunc::PCI11 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC2, eATmegaPinFunc::PCI10 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC1, eATmegaPinFunc::PCI9 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC0, eATmegaPinFunc::PCI8 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_D) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::AIN1, eATmegaPinFunc::PCI23 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::AIN0, eATmegaPinFunc::TOC0A, eATmegaPinFunc::PCI22 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER1_ECI, eATmegaPinFunc::TOC0B, eATmegaPinFunc::PCI21 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART_CLK, eATmegaPinFunc::TIMER0_ECI, eATmegaPinFunc::PCI20 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT1, eATmegaPinFunc::TOC2B, eATmegaPinFunc::PCI19 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT0, eATmegaPinFunc::PCI18 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART_TXD, eATmegaPinFunc::PCI17 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART_RXD, eATmegaPinFunc::PCI16 }; + return { funcs, countof(funcs) }; + } + } + #elif defined(__AVR_TRM04__) + if (info.port == eATmegaPort::PORT_A) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD7 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD6 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD5 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD4 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD3 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD2 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD1 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD0 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_B) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC0A, eATmegaPinFunc::TOC1C, eATmegaPinFunc::PCI7 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC1B, eATmegaPinFunc::PCI6 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC1A, eATmegaPinFunc::PCI5 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC2A, eATmegaPinFunc::PCI4 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PDO, eATmegaPinFunc::SPI_MISO, eATmegaPinFunc::PCI3 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PDI, eATmegaPinFunc::SPI_MOSI, eATmegaPinFunc::PCI2 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_SCK, eATmegaPinFunc::PCI1 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_CS, eATmegaPinFunc::PCI0 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_C) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD15, eATmegaPinFunc::TIMER3_ICP, eATmegaPinFunc::CLKO }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD14, eATmegaPinFunc::TOC3A }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD13, eATmegaPinFunc::TOC3B }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD12, eATmegaPinFunc::TOC3C }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD11, eATmegaPinFunc::TIMER3_CLKI }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD10 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD9 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_AD8 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_D) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER0_CLKI }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER1_CLKI }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART1_CLK }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER1_ICP }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT3, eATmegaPinFunc::USART1_TXD }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT2, eATmegaPinFunc::USART1_RXD }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT1, eATmegaPinFunc::TWI_SDA, eATmegaPinFunc::TOC2B }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT0, eATmegaPinFunc::TWI_CLK, eATmegaPinFunc::TOC0B }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_E) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT7, eATmegaPinFunc::AIN1, eATmegaPinFunc::UVCON }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT6, eATmegaPinFunc::AIN0 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT5, eATmegaPinFunc::TOSC2 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT4, eATmegaPinFunc::TOSC2 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::UID }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_ALE }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_RD }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EXTMEM_WR }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_F) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC7 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC6 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC5 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC4 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC3 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC2 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC1 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC0 }; + return { funcs, countof(funcs) }; + } + } + #elif defined(__AVR_TRM05__) + if (info.port == eATmegaPort::PORT_A) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC7, eATmegaPinFunc::PCI7 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC6, eATmegaPinFunc::PCI6 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC5, eATmegaPinFunc::PCI5 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC4, eATmegaPinFunc::PCI4 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC3, eATmegaPinFunc::PCI3 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC2, eATmegaPinFunc::PCI2 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC1, eATmegaPinFunc::PCI1 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::ADC0, eATmegaPinFunc::PCI0 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_B) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_SCK, eATmegaPinFunc::PCI15 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_MISO, eATmegaPinFunc::PCI14 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_MOSI, eATmegaPinFunc::PCI13 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::SPI_CS, eATmegaPinFunc::TOC0B, eATmegaPinFunc::PCI12 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::AIN1, eATmegaPinFunc::TOC0A, eATmegaPinFunc::PCI11 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::AIN0, eATmegaPinFunc::EINT2, eATmegaPinFunc::PCI10 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER1_ECI, eATmegaPinFunc::CLKO, eATmegaPinFunc::PCI9 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER0_ECI, eATmegaPinFunc::USART0_CLK, eATmegaPinFunc::PCI8 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_C) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOSC2, eATmegaPinFunc::PCI23 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOSC1, eATmegaPinFunc::PCI22 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI21 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI20 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI19 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::PCI18 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TWI_SDA, eATmegaPinFunc::PCI17 }; + return { funcs, countof(funcs) }; + } + else if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TWI_CLK, eATmegaPinFunc::PCI16 }; + return { funcs, countof(funcs) }; + } + } + else if (info.port == eATmegaPort::PORT_D) { + if (info.pinidx == 7) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC2A, eATmegaPinFunc::PCI31 }; + return { funcs, countof(funcs) }; + } + if (info.pinidx == 6) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TIMER1_ICP, eATmegaPinFunc::TOC2B, eATmegaPinFunc::PCI30 }; + return { funcs, countof(funcs) }; + } + if (info.pinidx == 5) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC1A, eATmegaPinFunc::PCI29 }; + return { funcs, countof(funcs) }; + } + if (info.pinidx == 4) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::TOC1B, eATmegaPinFunc::USART1_CLK, eATmegaPinFunc::PCI28 }; + return { funcs, countof(funcs) }; + } + if (info.pinidx == 3) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT1, eATmegaPinFunc::USART1_TXD, eATmegaPinFunc::PCI27 }; + return { funcs, countof(funcs) }; + } + if (info.pinidx == 2) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::EINT0, eATmegaPinFunc::USART1_RXD, eATmegaPinFunc::PCI26 }; + return { funcs, countof(funcs) }; + } + if (info.pinidx == 1) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART0_TXD, eATmegaPinFunc::PCI25 }; + return { funcs, countof(funcs) }; + } + if (info.pinidx == 0) { + static const eATmegaPinFunc funcs[] = { eATmegaPinFunc::USART0_RXD, eATmegaPinFunc::PCI24 }; + return { funcs, countof(funcs) }; + } + } + #endif + + return ATmegaPinFunctions(); // default and empty. +} + +#endif // HAL_AVR_DIRTY_INIT +#endif // __AVR__ diff --git a/Marlin/src/HAL/AVR/registers.h b/Marlin/src/HAL/AVR/registers.h new file mode 100644 index 0000000000..64c0955c3e --- /dev/null +++ b/Marlin/src/HAL/AVR/registers.h @@ -0,0 +1,5080 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * 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 + * along with this program. If not, see . + * + */ +#pragma once + +#include + +// This volatile-nonsense has to be done due to the C++ platform language specialization that specifies, for it's own compiler ideology, +// that memory writes and reads can be optimized across easily-reachable code spaces. This is in contrast to MSVC which specifies that +// memory writes and reads are holy. + +// OVERVIEW OF PREPROCESSOR DEFINITIONS: +// __AVR_ATmega2560__ +// __AVR_ATmega1284P__ +// __AVR_ATmega1280__ +// __AVR_ATmega644__ +// __AVR_ATmega644P__ +// __AVR_ATmega2561__ + +// Contributed by Martin Turski, company owner of EirDev, on the 29th of November, 2022 +// Contact E-Mail: turningtides@outlook.de +// Created specifically for the Marlin FW for AVR backwards-compatibility. +// Please expand this file with details of every supported AVR implementation. +// 1) download the latest technical reference manual +// 2) add the new technical reference manual below using a set of __AVR_*__ preprocessor definitions and a new __AVR_TRM*__ incrementing define +// 3) check which of the existing AVR registers exist on the new implementation and enable them +// 4) add any new register definitions +// 5) add the register memory layout below the definitions +// 6) extend the _ATmega_resetperipherals functions +// 7) extend the _ATmega_savePinAlternate function +// 8) copy the extension idea to _ATmega_restorePinAlternate and finish implementing it +// You need to adjust the eATmegaPort enumeration aswell. + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + #error "Fatal error: __AVR_TRMn__ already defined! (n: 01|02|03|04|05)" +#endif + +#if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega640__) + // ATmega2560 technical reference manual date: 28th of November, 2022 + // ATmega640-1280-1281-2560-2561-Datasheet-DS40002211A.pdf + #define __AVR_TRM01__ +#elif defined(__AVR_ATmega164A__) || defined(__AVR_ATmega164PA__) || defined(__AVR_ATmega324A__) || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) + // ATmega1284 technical reference manual date: 29th of November, 2022 + // ATmega164A_PA-324A_PA-644A_PA-1284_P_Data-Sheet-40002070B.pdf + #define __AVR_TRM02__ +#elif defined(__AVR_ATmega48A__) || defined(__AVR_ATmega48PA__) || defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88PA__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) + // ATmega328 technical reference manual date: 29th of November, 2022 + // ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061B.pdf + #define __AVR_TRM03__ +#elif defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1286P__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB646P__) || defined(__AVR_AT90USB647__) + // AT90USB1287 technical reference manual ID: 7593D–AVR–07/06 + // Preliminary. + #define __AVR_TRM04__ +#elif defined(__AVR_ATmega164P__) || defined(__AVR_ATmega164V__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324V__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644V__) + // ATmega644P technical reference manual date: 14th of February, 2023 + // ATmega164P-324P-644P-Data-Sheet-40002071A.pdf + #define __AVR_TRM05__ +#endif + +/** + * HELPER FUNCTIONS + */ +namespace AVRHelpers { + + template + struct no_volatile { + typedef T type; + }; + + template + struct no_volatile : public no_volatile {}; + + template + struct voltype { + typedef T type; + }; + template + struct voltype { + typedef uint8_t type; + }; + template + struct voltype { + typedef uint16_t type; + }; + template + struct voltype { + typedef uint32_t type; + }; + + template + inline void dwrite(volatile T& v, const T& V) noexcept { + (volatile typename voltype ::type&)v = (const typename voltype ::type&)V; + } + +} // namespace AVRHelpers + +// As old as the ATmega series of CPU is, the worse the actual libraries making +// use of the MCU likely are. + +// These registers as references do not take program space since they are purely references. + +// It would be great if the old AVR definitions could be wasted in favor of these +// and code be rewritten to use the following more robust definitions. + +struct _bit_reg_t { + uint8_t val; + + bool getValue(uint8_t idx) const volatile { + return ( val & (1 << idx) ); + } + void setValue(uint8_t idx, bool value) volatile { + if (value) + val |= (1 << idx); + else + val &= ~(1 << idx); + } +}; + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + + typedef _bit_reg_t PIN_reg_t; + typedef _bit_reg_t DDR_reg_t; + typedef _bit_reg_t PORT_reg_t; + + struct PORT_dev_t { + PIN_reg_t _PIN; + DDR_reg_t _DDR; + PORT_reg_t _PORT; + + inline void operator = ( const PORT_dev_t& r ) volatile { + using namespace AVRHelpers; + dwrite(this->_PIN, r._PIN); + dwrite(this->_DDR, r._DDR); + dwrite(this->_PORT, r._PORT); + } + }; + static_assert(sizeof(PORT_dev_t) == 3, "invalid size of ATmega2560 GPIO_dev_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM02__ || __AVR_TRM03__ || __AVR_TRM04__ || __AVR_TRM05__ + +#ifdef __AVR_TRM01__ + + struct _bitG_reg_t { + uint8_t val : 6; + uint8_t reserved1 : 2; + + bool getValue(uint8_t idx) const volatile { + return val & (1 << idx); + } + void setValue(uint8_t idx, bool value) volatile { + if (value) + val |= (1 << idx); + else + val &= ~(1 << idx); + } + }; + typedef _bitG_reg_t PING_reg_t; + typedef _bitG_reg_t DDRG_reg_t; + typedef _bitG_reg_t PORTG_reg_t; + + struct PORTG_dev_t { + PING_reg_t _PIN; + DDRG_reg_t _DDR; + PORTG_reg_t _PORT; + + inline void operator = ( const PORTG_dev_t& r ) volatile { + using namespace AVRHelpers; + dwrite(this->_PIN, r._PIN); + dwrite(this->_DDR, r._DDR); + dwrite(this->_PORT, r._PORT); + } + }; + +#endif + +#ifdef __AVR_TRM03__ + + struct _bitC_reg_t { + uint8_t val : 7; + uint8_t reserved1 : 1; + + bool getValue(uint8_t idx) const volatile { + return ( val & (1 << idx) ); + } + void setValue(uint8_t idx, bool value) volatile { + if (value) + val |= (1 << idx); + else + val &= ~(1 << idx); + } + }; + typedef _bitC_reg_t PINC_reg_t; + typedef _bitC_reg_t DDRC_reg_t; + typedef _bitC_reg_t PORTC_reg_t; + + struct PORTC_dev_t { + PINC_reg_t _PIN; + DDRC_reg_t _DDR; + PORTC_reg_t _PORT; + + inline void operator = ( const PORTC_dev_t& r ) volatile { + this->_PIN = r._PIN; + this->_DDR = r._DDR; + this->_PORT = r._PORT; + } + }; + +#endif + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + + struct TIFR0_reg_t { + uint8_t _TOV0 : 1; + uint8_t _OCF0A : 1; + uint8_t _OCF0B : 1; + uint8_t reserved1 : 5; + }; + static_assert(sizeof(TIFR0_reg_t) == 1, "invalid size of ATmega2560 TIFR0_reg_t"); + + struct TIFR1_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + uint8_t _TOV1 : 1; + uint8_t _OCF1A : 1; + uint8_t _OCF1B : 1; + uint8_t _OCF1C : 1; + uint8_t reserved1 : 1; + uint8_t _ICF1 : 1; + uint8_t reserved2 : 2; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM05__) + uint8_t _TOV1 : 1; + uint8_t _OCF1A : 1; + uint8_t _OCF1B : 1; + uint8_t reserved1 : 2; + uint8_t _ICF1 : 1; + uint8_t reserved2 : 2; + #endif + }; + static_assert(sizeof(TIFR1_reg_t) == 1, "invalid size of ATmega2560 TIFR1_reg_t"); + + struct TIFR2_reg_t { + uint8_t _TOV2 : 1; + uint8_t _OCF2A : 1; + uint8_t _OCF2B : 1; + uint8_t reserved1 : 5; + }; + static_assert(sizeof(TIFR2_reg_t) == 1, "invalid size of ATmega2560 TIFR2_reg_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM02__ || __AVR_TRM03__ || __AVR_TRM04__ || __AVR_TRM05__ + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) + + struct TIFR3_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + uint8_t _TOV3 : 1; + uint8_t _OCF3A : 1; + uint8_t _OCF3B : 1; + uint8_t _OCF3C : 1; + uint8_t reserved1 : 1; + uint8_t _ICF3 : 1; + uint8_t reserved2 : 2; + #elif defined(__AVR_TRM02__) + uint8_t _TOV3 : 1; + uint8_t _OCF3A : 1; + uint8_t _OCF3B : 1; + uint8_t reserved1 : 2; + uint8_t _ICF3 : 1; + uint8_t reserved2 : 2; + #endif + }; + static_assert(sizeof(TIFR3_reg_t) == 1, "invalid size of ATmega2560 TIFR3_reg_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM02__ || __AVR_TRM04__ + +#ifdef __AVR_TRM01__ + + struct TIFR4_reg_t { + uint8_t _TOV4 : 1; + uint8_t _OCF4A : 1; + uint8_t _OCF4B : 1; + uint8_t _OCF4C : 1; + uint8_t reserved1 : 1; + uint8_t _ICF4 : 1; + uint8_t reserved2 : 2; + }; + static_assert(sizeof(TIFR4_reg_t) == 1, "invalid size of ATmega2560 TIFR4_reg_t"); + + struct TIFR5_reg_t { + uint8_t _TOV5 : 1; + uint8_t _OCF5A : 1; + uint8_t _OCF5B : 1; + uint8_t _OCF5C : 1; + uint8_t reserved1 : 1; + uint8_t _ICF5 : 1; + uint8_t reserved2 : 2; + }; + static_assert(sizeof(TIFR5_reg_t) == 1, "invalid size of ATmega2560 TIFR5_reg_t"); + +#endif // __AVR_TRM01__ + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + + struct PCIFR_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM03__) + uint8_t _PCIF0 : 1; + uint8_t _PCIF1 : 1; + uint8_t _PCIF2 : 1; + uint8_t reserved1 : 5; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + uint8_t _PCIF0 : 1; + uint8_t _PCIF1 : 1; + uint8_t _PCIF2 : 1; + uint8_t _PCIF3 : 1; + uint8_t reserved1 : 4; + #elif defined(__AVR_TRM04__) + uint8_t _PCIF0 : 1; + uint8_t reserved1 : 7; + #endif + }; + static_assert(sizeof(PCIFR_reg_t) == 1, "invalid size of ATmega2560 PCIFR_reg_t"); + + struct EIFR_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + uint8_t _INTF0 : 1; + uint8_t _INTF1 : 1; + uint8_t _INTF2 : 1; + uint8_t _INTF3 : 1; + uint8_t _INTF4 : 1; + uint8_t _INTF5 : 1; + uint8_t _INTF6 : 1; + uint8_t _INTF7 : 1; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + uint8_t _INTF0 : 1; + uint8_t _INTF1 : 1; + uint8_t _INTF2 : 1; + uint8_t reserved1 : 5; + #elif defined(__AVR_TRM03__) + uint8_t _INTF0 : 1; + uint8_t _INTF1 : 1; + uint8_t reserved1 : 6; + #endif + }; + static_assert(sizeof(EIFR_reg_t) == 1, "invalid size of ATmega2560 EIFR_reg_t"); + + struct EIMSK_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + uint8_t _INT0 : 1; + uint8_t _INT1 : 1; + uint8_t _INT2 : 1; + uint8_t _INT3 : 1; + uint8_t _INT4 : 1; + uint8_t _INT5 : 1; + uint8_t _INT6 : 1; + uint8_t _INT7 : 1; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + uint8_t _INT0 : 1; + uint8_t _INT1 : 1; + uint8_t _INT2 : 1; + uint8_t reserved1 : 5; + #elif defined(__AVR_TRM03__) + uint8_t _INT0 : 1; + uint8_t _INT1 : 1; + uint8_t reserved1 : 6; + #endif + }; + static_assert(sizeof(EIMSK_reg_t) == 1, "invalid size of ATmega2560 EIMSK_reg_t"); + + struct EECR_reg_t { + uint8_t _EERE : 1; + uint8_t _EEPE : 1; + uint8_t _EEMPE : 1; + uint8_t _EERIE : 1; + uint8_t _EEPM0 : 1; + uint8_t _EEPM1 : 1; + uint8_t reserved1 : 2; + }; + static_assert(sizeof(EECR_reg_t) == 1, "invalid size of ATmega2560 EECR_reg_t"); + + struct EEAR_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + uint16_t _EEAR : 12; + uint16_t reserved1 : 4; + #elif defined(__AVR_TRM03__) + #if defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88PA__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega328P__) + uint16_t _EEAR : 16; + #else + uint8_t _EEAR : 8; + uint8_t reserved1 : 8; + #endif + #endif + }; + static_assert(sizeof(EEAR_reg_t) == 2, "invalid size of ATmega2560 EEAR_reg_t"); + + struct GTCCR_reg_t { + uint8_t _PSRSYNC : 1; + uint8_t _PSRASY : 1; + uint8_t reserved1 : 5; + uint8_t _TSM : 1; + }; + static_assert(sizeof(GTCCR_reg_t) == 1, "invalid size of ATmega2560 GTCCR_reg_t"); + + struct SPCR_reg_t { + uint8_t _SPR : 2; + uint8_t _CPHA : 1; + uint8_t _CPOL : 1; + uint8_t _MSTR : 1; + uint8_t _DORD : 1; + uint8_t _SPE : 1; + uint8_t _SPIE : 1; + }; + static_assert(sizeof(SPCR_reg_t) == 1, "invalid size of ATmega2560 SPCR_reg_t"); + + struct SPSR_reg_t { + uint8_t _SPI2X : 1; + uint8_t reserved1 : 5; + uint8_t _WCOL : 1; + uint8_t _SPIF : 1; + }; + static_assert(sizeof(SPSR_reg_t) == 1, "invalid size of ATmega2560 SPSR_reg_t"); + + struct ACSR_reg_t { + uint8_t _ACIS : 2; + uint8_t _ACIC : 1; + uint8_t _ACIE : 1; + uint8_t _ACI : 1; + uint8_t _ACO : 1; + uint8_t _ACBG : 1; + uint8_t _ACD : 1; + }; + static_assert(sizeof(ACSR_reg_t) == 1, "invalid size of ATmega2560 ACSR_reg_t"); + + struct SMCR_reg_t { + uint8_t _SE : 1; + uint8_t _SM : 3; + uint8_t reserved1 : 4; + }; + static_assert(sizeof(SMCR_reg_t) == 1, "invalid size of ATmega2560 SMCR_reg_t"); + + struct MCUSR_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + uint8_t _PORF : 1; + uint8_t _EXTRF : 1; + uint8_t _BORF : 1; + uint8_t _WDRF : 1; + uint8_t _JTRF : 1; + uint8_t reserved1 : 3; + #elif defined(__AVR_TRM03__) + uint8_t _PORF : 1; + uint8_t _EXTRF : 1; + uint8_t _BORF : 1; + uint8_t _WDRF : 1; + uint8_t reserved1 : 4; + #endif + }; + static_assert(sizeof(MCUSR_reg_t) == 1, "invalid size of ATmega2560 MCUSR_reg_t"); + + struct MCUCR_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + uint8_t _IVCE : 1; + uint8_t _IVSEL : 1; + uint8_t reserved1 : 2; + uint8_t _PUD : 1; + uint8_t reserved2 : 2; + uint8_t _JTD : 1; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + uint8_t _IVCE : 1; + uint8_t _IVSEL : 1; + uint8_t reserved1 : 2; + uint8_t _PUD : 1; + uint8_t _BODSE : 1; + uint8_t _BODS : 1; + uint8_t _JTD : 1; + #elif defined(__AVR_TRM03__) + uint8_t _IVCE : 1; + uint8_t _IVSEL : 1; + uint8_t reserved1 : 2; + uint8_t _PUD : 1; + uint8_t _BODSE : 1; + uint8_t _BODS : 1; + uint8_t reserved2 : 1; + #endif + }; + static_assert(sizeof(MCUCR_reg_t) == 1, "invalid size of ATmega2560 MCUCR_reg_t"); + + struct SPMCSR_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + uint8_t _SPMEN : 1; + uint8_t _PGERS : 1; + uint8_t _PGWRT : 1; + uint8_t _BLBSET : 1; + uint8_t _RWWSRE : 1; + uint8_t _SIGRD : 1; + uint8_t _RWWSB : 1; + uint8_t _SPMIE : 1; + #elif defined(__AVR_TRM03__) + #if defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88PA__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega328P__) + uint8_t _SPMEN : 1; + uint8_t _PGERS : 1; + uint8_t _PGWRT : 1; + uint8_t _BLBSET : 1; + uint8_t _RWWSRE : 1; + uint8_t _SIGRD : 1; + uint8_t _RWWSB : 1; + uint8_t _SPMIE : 1; + #else + uint8_t _SPMEN : 1; + uint8_t _PGERS : 1; + uint8_t _PGWRT : 1; + uint8_t _BLBSET : 1; + uint8_t reserved1 : 1; + uint8_t _SIGRD : 1; + uint8_t reserved2 : 1; + uint8_t _SPMIE : 1; + #endif + #endif + }; + static_assert(sizeof(SPMCSR_reg_t) == 1, "invalid size of ATmega2560 SPMCSR_reg_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM02__ || __AVR_TRM03__ || __AVR_TRM04__ + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + + struct RAMPZ_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) + uint8_t _RAMPZ : 2; + uint8_t reserved1 : 6; + #elif defined(__AVR_TRM05__) + uint8_t _RAMPZ : 1; + uint8_t reserved1 : 7; + #endif + }; + static_assert(sizeof(RAMPZ_reg_t) == 1, "invalid size of ATmega2560 RAMPZ_reg_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM02__ || __AVR_TRM04__ || __AVR_TRM05__ + +#ifdef __AVR_TRM01__ + + struct EIND_reg_t { + uint8_t _EIND0 : 1; + uint8_t reserved1 : 7; + }; + static_assert(sizeof(EIND_reg_t) == 1, "invalid size of ATmega2560 EIND_reg_t"); + +#endif // __AVR_TRM01__ + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + + struct SP_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + uint16_t _SP; + #elif defined(__AVR_TRM03__) + #if defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88PA__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega328P__) + uint16_t _SP : 11; + uint16_t reserved1 : 5; + #else + uint16_t _SP : 10; + uint16_t reserved1 : 6; + #endif + #endif + }; + static_assert(sizeof(SP_reg_t) == 2, "invalid size of ATmega2560 SP_reg_t"); + + struct SREG_reg_t { + uint8_t _C : 1; + uint8_t _Z : 1; + uint8_t _N : 1; + uint8_t _V : 1; + uint8_t _S : 1; + uint8_t _H : 1; + uint8_t _T : 1; + uint8_t _I : 1; + }; + static_assert(sizeof(SREG_reg_t) == 1, "invalid size of ATmega2560 SREG_reg_t"); + + struct WDTCSR_reg_t { + uint8_t _WDP0 : 1; + uint8_t _WDP1 : 1; + uint8_t _WDP2 : 1; + uint8_t _WDE : 1; + uint8_t _WDCE : 1; + uint8_t _WDP3 : 1; + uint8_t _WDIE : 1; + uint8_t _WDIF : 1; + }; + static_assert(sizeof(WDTCSR_reg_t) == 1, "invalid size of ATmega2560 WDTCSR_reg_t"); + + struct CLKPR_reg_t { + uint8_t _CLKPS : 4; + uint8_t reserved1 : 3; + uint8_t _CLKPCE : 1; + }; + static_assert(sizeof(CLKPR_reg_t) == 1, "invalid size of ATmega2560 CLKPR_reg_t"); + + struct PRR0_reg_t { + #ifdef __AVR_TRM01__ + uint8_t _PRADC : 1; + uint8_t _PRUSART0 : 1; + uint8_t _PRSPI : 1; + uint8_t _PRTIM1 : 1; + uint8_t reserved1 : 1; + uint8_t _PRTIM0 : 1; + uint8_t _PRTIM2 : 1; + uint8_t _PRTWI : 1; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + uint8_t _PRADC : 1; + uint8_t _PRUSART0 : 1; + uint8_t _PRSPI : 1; + uint8_t _PRTIM1 : 1; + uint8_t _PRUSART1 : 1; + uint8_t _PRTIM0 : 1; + uint8_t _PRTIM2 : 1; + uint8_t _PRTWI : 1; + #elif defined(__AVR_TRM03__) + uint8_t _PRADC : 1; + uint8_t _PRUSART0 : 1; + uint8_t _PRSPI : 1; + uint8_t _PRTIM1 : 1; + uint8_t reserved1 : 1; + uint8_t _PRTIM0 : 1; + uint8_t _PRTIM2 : 1; + uint8_t _PRTWI : 1; + #elif defined(__AVR_TRM04__) + uint8_t _PRADC : 1; + uint8_t reserved1 : 1; + uint8_t _PRSPI : 1; + uint8_t _PRTIM1 : 1; + uint8_t reserved2 : 1; + uint8_t _PRTIM0 : 1; + uint8_t _PRTIM2 : 1; + uint8_t _PRTWI : 1; + #endif + }; + static_assert(sizeof(PRR0_reg_t) == 1, "invalid size of ATmega2560 PRR0_reg_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM02__ || __AVR_TRM03__ || __AVR_TRM04__ || __AVR_TRM05__ + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) + + struct PRR1_reg_t { + #ifdef __AVR_TRM01__ + uint8_t _PRUSART1 : 1; + uint8_t _PRUSART2 : 1; + uint8_t _PRUSART3 : 1; + uint8_t _PRTIM3 : 1; + uint8_t _PRTIM4 : 1; + uint8_t _PRTIM5 : 1; + uint8_t reserved1 : 2; + #elif defined(__AVR_TRM02__) + uint8_t _PRTIM3 : 1; + uint8_t reserved1 : 7; + #elif defined(__AVR_TRM04__) + uint8_t _PRUSART1 : 1; + uint8_t reserved1 : 2; + uint8_t _PRTIM3 : 1; + uint8_t reserved2 : 3; + uint8_t _PRUSB : 1; + #endif + }; + static_assert(sizeof(PRR1_reg_t) == 1, "invalid size of ATmega2560 PRR1_reg_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM02__ || __AVR_TRM04__ + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + + struct PCICR_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM03__) + uint8_t _PCIE0 : 1; + uint8_t _PCIE1 : 1; + uint8_t _PCIE2 : 1; + uint8_t reserved1 : 5; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + uint8_t _PCIE0 : 1; + uint8_t _PCIE1 : 1; + uint8_t _PCIE2 : 1; + uint8_t _PCIE3 : 1; + uint8_t reserved1 : 4; + #elif defined(__AVR_TRM04__) + uint8_t _PCIE0 : 1; + uint8_t reserved1 : 7; + #endif + }; + static_assert(sizeof(PCICR_reg_t) == 1, "invalid size of ATmega2560 PCICR_reg_t"); + + struct EICRA_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + uint8_t _ISC0 : 2; + uint8_t _ISC1 : 2; + uint8_t _ISC2 : 2; + uint8_t _ISC3 : 2; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + uint8_t _ISC0 : 2; + uint8_t _ISC1 : 2; + uint8_t _ISC2 : 2; + uint8_t reserved1 : 2; + #elif defined(__AVR_TRM03__) + uint8_t _ISC0 : 2; + uint8_t _ISC1 : 2; + uint8_t reserved1 : 4; + #endif + }; + static_assert(sizeof(EICRA_reg_t) == 1, "invalid size of ATmega2560 EICRA_reg_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM02__ || __AVR_TRM03__ || __AVR_TRM04__ || __AVR_TRM05__ + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + + struct EICRB_reg_t { + uint8_t _ISC4 : 2; + uint8_t _ISC5 : 2; + uint8_t _ISC6 : 2; + uint8_t _ISC7 : 2; + }; + static_assert(sizeof(EICRB_reg_t) == 1, "invalid size of ATmega2560 EICRB_reg_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM04__ + +#if defined(__AVR_TRM03__) + + struct _bitPCMSK1_reg_t { + uint8_t val : 7; + uint8_t reserved1 : 1; + + bool getValue(uint8_t idx) { return val & (1 << idx); } + void setValue(uint8_t idx, bool value) { + if (value) + val |= (1 << idx); + else + val &= ~(1 << idx); + } + }; + +#endif // __AVR_TRM03__ + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + + struct TIMSK0_reg_t { + #ifdef __AVR_TRM01__ + uint8_t _TOIE0 : 1; + uint8_t _OCIE0A : 1; + uint8_t _OCIE0B : 1; + uint8_t _OCIE0C : 1; + uint8_t reserved1 : 1; + uint8_t _ICIE0 : 1; + uint8_t reserved2 : 2; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + uint8_t _TOIE0 : 1; + uint8_t _OCIE0A : 1; + uint8_t _OCIE0B : 1; + uint8_t reserved1 : 5; + #endif + }; + static_assert(sizeof(TIMSK0_reg_t) == 1, "invalid size of ATmega2560 TIMSK0_reg_t"); + + struct TIMSK1_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + uint8_t _TOIE1 : 1; + uint8_t _OCIE1A : 1; + uint8_t _OCIE1B : 1; + uint8_t _OCIE1C : 1; + uint8_t reserved1 : 1; + uint8_t _ICIE1: 1; + uint8_t reserved2 : 2; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM05__) + uint8_t _TOIE1 : 1; + uint8_t _OCIE1A : 1; + uint8_t _OCIE1B : 1; + uint8_t reserved1 : 2; + uint8_t _ICIE1: 1; + uint8_t reserved2 : 2; + #endif + }; + static_assert(sizeof(TIMSK1_reg_t) == 1, "invalid size of ATmega2560 TIMSK1_reg_t"); + + struct TIMSK2_reg_t { + uint8_t _TOIE2 : 1; + uint8_t _OCIE2A : 1; + uint8_t _OCIE2B : 1; + uint8_t reserved1 : 5; + }; + static_assert(sizeof(TIMSK2_reg_t) == 1, "invalid size of ATmega2560 TIMSK2_reg_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM02__ || __AVR_TRM03__ || __AVR_TRM04__ || __AVR_TRM05__ + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) + + struct TIMSK3_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + uint8_t _TOIE3 : 1; + uint8_t _OCIE3A : 1; + uint8_t _OCIE3B : 1; + uint8_t _OCIE3C : 1; + uint8_t reserved1 : 1; + uint8_t _ICIE3 : 1; + uint8_t reserved2 : 2; + #elif defined(__AVR_TRM02__) + uint8_t _TOIE3 : 1; + uint8_t _OCIE3A : 1; + uint8_t _OCIE3B : 1; + uint8_t reserved1 : 2; + uint8_t _ICIE3 : 1; + uint8_t reserved2 : 2; + #endif + }; + static_assert(sizeof(TIMSK3_reg_t) == 1, "invalid size of ATmega2560 TIMSK3_reg_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM02__ || __AVR_TRM04__ + +#ifdef __AVR_TRM01__ + + struct TIMSK4_reg_t { + uint8_t _TOIE4 : 1; + uint8_t _OCIE4A : 1; + uint8_t _OCIE4B : 1; + uint8_t _OCIE4C : 1; + uint8_t reserved1 : 1; + uint8_t _ICIE4 : 1; + uint8_t reserved2 : 2; + }; + static_assert(sizeof(TIMSK4_reg_t) == 1, "invalid size of ATmega2560 TIMSK4_reg_t"); + + struct TIMSK5_reg_t { + uint8_t _TOIE5 : 1; + uint8_t _OCIE5A : 1; + uint8_t _OCIE5B : 1; + uint8_t _OCIE5C : 1; + uint8_t reserved1 : 1; + uint8_t _ICIE5 : 1; + uint8_t reserved2 : 2; + }; + static_assert(sizeof(TIMSK5_reg_t) == 1, "invalid size of ATmega2560 TIMSK5_reg_t"); + +#endif // __AVR_TRM01__ + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + + struct XMCRA_reg_t { + uint8_t _SRW0 : 2; + uint8_t _SRW1 : 2; + uint8_t _SRL : 3; + uint8_t _SRE : 1; + }; + static_assert(sizeof(XMCRA_reg_t) == 1, "invalid size of ATmega2560 XMCRA_reg_t"); + + struct XMCRB_reg_t { + uint8_t _XMM : 3; + uint8_t reserved1 : 4; + uint8_t _XMBK : 1; + }; + static_assert(sizeof(XMCRB_reg_t) == 1, "invalid size of ATmega2560 XMCRB_reg_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM04__ + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + + struct ADCSRA_reg_t { + uint8_t _ADPS : 3; + uint8_t _ADIE : 1; + uint8_t _ADIF : 1; + uint8_t _ADATE : 1; + uint8_t _ADSC : 1; + uint8_t _ADEN : 1; + }; + static_assert(sizeof(ADCSRA_reg_t) == 1, "invalid size of ATmega2560 ADCSRA_reg_t"); + + struct ADCSRB_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + uint8_t _ADTS : 3; + uint8_t _MUX5 : 1; + uint8_t reserved1 : 2; + uint8_t _ACME : 1; + uint8_t reserved2 : 1; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM05__) + uint8_t _ADTS : 3; + uint8_t reserved1 : 3; + uint8_t _ACME : 1; + uint8_t reserved2 : 1; + #endif + }; + static_assert(sizeof(ADCSRB_reg_t) == 1, "invalid size of ATmega2560 ADCSRB_reg_t"); + + struct ADMUX_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + uint8_t _MUX0 : 1; + uint8_t _MUX1 : 1; + uint8_t _MUX2 : 1; + uint8_t _MUX3 : 1; + uint8_t _MUX4 : 1; + uint8_t _ADLAR : 1; + uint8_t _REFS0 : 1; + uint8_t _REFS1 : 1; + #elif defined(__AVR_TRM03__) + uint8_t _MUX0 : 1; + uint8_t _MUX1 : 1; + uint8_t _MUX2 : 1; + uint8_t _MUX3 : 1; + uint8_t reserved1 : 1; + uint8_t _ADLAR : 1; + uint8_t _REFS0 : 1; + uint8_t _REFS1 : 1; + #endif + }; + static_assert(sizeof(ADMUX_reg_t) == 1, "invalid size of ATmega2560 ADMUX_reg_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM02__ || __AVR_TRM03__ || __AVR_TRM04__ + +#ifdef __AVR_TRM01__ + + struct DIDR2_reg_t { + uint8_t _ADC8D : 1; + uint8_t _ADC9D : 1; + uint8_t _ADC10D : 1; + uint8_t _ADC11D : 1; + uint8_t _ADC12D : 1; + uint8_t _ADC13D : 1; + uint8_t _ADC14D : 1; + uint8_t _ADC15D : 1; + }; + static_assert(sizeof(DIDR2_reg_t) == 1, "invalid size of ATmega2560 DIDR2_reg_t"); + +#endif // __AVR_TRM01__ + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + + struct DIDR0_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + uint8_t _ADC0D : 1; + uint8_t _ADC1D : 1; + uint8_t _ADC2D : 1; + uint8_t _ADC3D : 1; + uint8_t _ADC4D : 1; + uint8_t _ADC5D : 1; + uint8_t _ADC6D : 1; + uint8_t _ADC7D : 1; + #elif defined(__AVR_TRM03__) + uint8_t _ADC0D : 1; + uint8_t _ADC1D : 1; + uint8_t _ADC2D : 1; + uint8_t _ADC3D : 1; + uint8_t _ADC4D : 1; + uint8_t _ADC5D : 1; + uint8_t reserved1 : 2; + #endif + }; + static_assert(sizeof(DIDR0_reg_t) == 1, "invalid size of ATmega2560 DIDR0_reg_t"); + + struct DIDR1_reg_t { + uint8_t _AIN0D : 1; + uint8_t _AIN1D : 1; + uint8_t reserved1 : 6; + }; + static_assert(sizeof(DIDR1_reg_t) == 1, "invalid size of ATmega2560 DIDR1_reg_t"); + + struct TCCRnA_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + uint8_t _WGMn0 : 1; + uint8_t _WGMn1 : 1; + uint8_t _COMnC : 2; + uint8_t _COMnB : 2; + uint8_t _COMnA : 2; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM05__) + uint8_t _WGMn0 : 1; + uint8_t _WGMn1 : 1; + uint8_t reserved1 : 2; + uint8_t _COMnB : 2; + uint8_t _COMnA : 2; + #endif + }; + static_assert(sizeof(TCCRnA_reg_t) == 1, "invalid size of ATmega2560 TCCRnA_reg_t"); + + struct TCCRnB_reg_t { + uint8_t _CSn : 3; + uint8_t _WGMn2 : 1; + uint8_t _WGMn3 : 1; + uint8_t reserved1 : 1; + uint8_t _ICESn : 1; + uint8_t _ICNCn : 1; + }; + static_assert(sizeof(TCCRnB_reg_t) == 1, "invalid size of ATmega2560 TCCRnB_reg_t"); + + struct TCCRnC_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + uint8_t reserved1 : 5; + uint8_t _FOCnC : 1; + uint8_t _FOCnB : 1; + uint8_t _FOCnA : 1; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM05__) + uint8_t reserved1 : 6; + uint8_t _FOCnB : 1; + uint8_t _FOCnA : 1; + #endif + }; + static_assert(sizeof(TCCRnC_reg_t) == 1, "invalid size of ATmega2560 TCCRnC_reg_t"); + + struct TIMER_dev_t { + TCCRnA_reg_t _TCCRnA; + TCCRnB_reg_t _TCCRnB; + TCCRnC_reg_t _TCCRnC; + uint8_t reserved1; + uint16_t _TCNTn; + uint16_t _ICRn; + uint16_t _OCRnA; + uint16_t _OCRnB; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + uint16_t _OCRnC; + #endif + + inline void operator = ( const TIMER_dev_t& r ) volatile { + using namespace AVRHelpers; + dwrite(this->_TCCRnA, r._TCCRnA); + dwrite(this->_TCCRnB, r._TCCRnB); + dwrite(this->_TCCRnC, r._TCCRnC); + this->reserved1 = r.reserved1; + this->_TCNTn = r._TCNTn; + this->_ICRn = r._ICRn; + this->_OCRnA = r._OCRnA; + this->_OCRnB = r._OCRnB; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + this->_OCRnC = r._OCRnC; + #endif + } + }; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + static_assert(sizeof(TIMER_dev_t) == 14, "invalid size of ATmega2560 TIMER_dev_t"); + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM05__) + static_assert(sizeof(TIMER_dev_t) == 12, "invalid size of ATmega1284 TIMER_dev_t"); + #endif + + struct TCCRnA_8bit_reg_t { + uint8_t _WGMn0 : 1; + uint8_t _WGMn1 : 1; + uint8_t reserved1 : 2; + uint8_t _COMnB : 2; + uint8_t _COMnA : 2; + }; + static_assert(sizeof(TCCRnA_8bit_reg_t) == 1, "invalid size of ATmega2560 TCCRnA_8bit_reg_t"); + + struct TCCRnB_8bit_reg_t { + uint8_t _CSn : 3; + uint8_t _WGMn2 : 1; + uint8_t reserved1 : 2; + uint8_t _FOCnB : 1; + uint8_t _FOCnA : 1; + }; + static_assert(sizeof(TCCRnB_8bit_reg_t) == 1, "invalid size of ATmega2560 TCCRnB_8bit_reg_t"); + + struct TIMER_8bit_dev_t { + TCCRnA_8bit_reg_t _TCCRnA; + TCCRnB_8bit_reg_t _TCCRnB; + uint8_t _TCNTn; + uint8_t _OCRnA; + uint8_t _OCRnB; + + inline void operator = ( const TIMER_8bit_dev_t& r ) volatile { + using namespace AVRHelpers; + dwrite(this->_TCCRnA, r._TCCRnA); + dwrite(this->_TCCRnB, r._TCCRnB); + this->_TCNTn = r._TCNTn; + this->_OCRnA = r._OCRnA; + this->_OCRnB = r._OCRnB; + } + }; + static_assert(sizeof(TIMER_8bit_dev_t) == 5, "invalid size of ATmega2560 TIMER_8bit_dev_t"); + + struct ASSR_reg_t { + uint8_t _TCR2BUB : 1; + uint8_t _TCR2AUB : 1; + uint8_t _OCR2BUB : 1; + uint8_t _OCR2AUB : 1; + uint8_t _TCN2UB : 1; + uint8_t _AS2 : 1; + uint8_t _EXCLK : 1; + uint8_t reserved1 : 1; + }; + static_assert(sizeof(ASSR_reg_t) == 1, "invalid size of ATmega2560 ASSR_reg_t"); + + struct TWSR_reg_t { + uint8_t _TWPS0 : 1; + uint8_t _TWPS1 : 1; + uint8_t reserved1 : 1; + uint8_t _TWS3 : 1; + uint8_t _TWS4 : 1; + uint8_t _TWS5 : 1; + uint8_t _TWS6 : 1; + uint8_t _TWS7 : 1; + }; + static_assert(sizeof(TWSR_reg_t) == 1, "invalid size of ATmega2560 TWSR_reg_t"); + + struct TWAR_reg_t { + uint8_t _TWGCE : 1; + uint8_t _TWA : 7; + }; + static_assert(sizeof(TWAR_reg_t) == 1, "invalid size of ATmega2560 TWAR_reg_t"); + + struct TWCR_reg_t { + uint8_t _TWIE : 1; + uint8_t reserved1 : 1; + uint8_t _TWEN : 1; + uint8_t _TWWC : 1; + uint8_t _TWSTO : 1; + uint8_t _TWSTA : 1; + uint8_t _TWEA : 1; + uint8_t _TWINT : 1; + }; + static_assert(sizeof(TWCR_reg_t) == 1, "invalid size of ATmega2560 TWCR_reg_t"); + + struct TWAMR_reg_t { + uint8_t reserved1 : 1; + uint8_t _TWAM : 7; + }; + static_assert(sizeof(TWAMR_reg_t) == 1, "invalid size of ATmega2560 TWAMR_reg_t"); + + struct UBRRn_reg_t { + uint16_t _UBRR : 12; + uint16_t reserved1 : 4; + }; + static_assert(sizeof(UBRRn_reg_t) == 2, "invalid size of ATmega2560 UBRRn_reg_t)"); + + struct UCSRnC_reg_t { + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) + uint8_t _UCPOL : 1; + uint8_t _UCSZn0 : 1; + uint8_t _UCSZn1 : 1; + uint8_t _USBS : 1; + uint8_t _UPM : 2; + uint8_t _UMSEL : 2; + #elif defined(__AVR_TRM05__) + uint8_t _UCPOL : 1; + uint8_t _UCPHA : 1; + uint8_t _UDORD : 1; + uint8_t reserved1 : 3; + uint8_t _UMSEL : 2; + #endif + }; + static_assert(sizeof(UCSRnC_reg_t) == 1, "invalid size of ATmega2560 UCSRnC_reg_t"); + + struct UCSRnB_reg_t { + uint8_t _TXB8 : 1; + uint8_t _RXB8 : 1; + uint8_t _UCSZn2 : 1; + uint8_t _TXEN : 1; + uint8_t _RXEN : 1; + uint8_t _UDRIE : 1; + uint8_t _TXCIE : 1; + uint8_t _RXCIE : 1; + }; + static_assert(sizeof(UCSRnB_reg_t) == 1, "invalid size of ATmega2560 UCSRnB_reg_t"); + + struct UCSRnA_reg_t { + uint8_t _MPCM : 1; + uint8_t _U2X : 1; + uint8_t _UPE : 1; + uint8_t _DOR : 1; + uint8_t _FE : 1; + uint8_t _UDRE : 1; + uint8_t _TXC : 1; + uint8_t _RXC : 1; + }; + static_assert(sizeof(UCSRnA_reg_t) == 1, "invalid size of ATmega2560 UCSRnA_reg_t"); + + struct USART_dev_t { + UCSRnA_reg_t _UCSRnA; + UCSRnB_reg_t _UCSRnB; + UCSRnC_reg_t _UCSRnC; + uint8_t reserved1; + UBRRn_reg_t _UBRRn; + uint8_t _UDRn; + + inline void operator = ( const USART_dev_t& r ) volatile { + using namespace AVRHelpers; + dwrite(this->_UCSRnA, r._UCSRnA); + dwrite(this->_UCSRnB, r._UCSRnB); + dwrite(this->_UCSRnC, r._UCSRnC); + dwrite(this->reserved1, r.reserved1); + dwrite(this->_UBRRn, r._UBRRn); + dwrite(this->_UDRn, r._UDRn); + } + }; + static_assert(sizeof(USART_dev_t) == 7, "invalid size of ATmega2560 USART_dev_t"); + +#endif // __AVR_TRM01__ || __AVR_TRM02__ || __AVR_TRM03__ || __AVR_TRM04__ + +#ifdef __AVR_TRM04__ + + struct UHCON_reg_t { + uint8_t _SOFEN : 1; + uint8_t _RESET : 1; + uint8_t _RESUME : 1; + uint8_t reserved1 : 5; + }; + static_assert(sizeof(UHCON_reg_t) == 1, "invalid size of ATUSB90 UHCON_reg_t"); + + struct UHINT_reg_t { + uint8_t _DCONNI : 1; + uint8_t _DDISCI : 1; + uint8_t _RSTI : 1; + uint8_t _RSMEDI : 1; + uint8_t _RXRSMI : 1; + uint8_t _HSOFI : 1; + uint8_t _HWUPI : 1; + uint8_t reserved1 : 1; + }; + static_assert(sizeof(UHINT_reg_t) == 1, "invalid size of ATUSB90 UHINT_reg_t"); + + struct UHIEN_reg_t { + uint8_t _SUSPE : 1; + uint8_t _MSOFE : 1; + uint8_t _SOFE : 1; + uint8_t _EORSTE : 1; + uint8_t _WAKEUPE : 1; + uint8_t _EORSME : 1; + uint8_t _UPRSME : 1; + uint8_t reserved1 : 1; + }; + static_assert(sizeof(UHIEN_reg_t) == 1, "invalid size of ATUSB90 UHIEN_reg_t"); + + struct UHADDR_reg_t { + uint8_t _HADD : 7; + uint8_t reserved1 : 1; + }; + static_assert(sizeof(UHADDR_reg_t) == 1, "invalid size of ATUSB90 UHADDR_reg_t"); + + struct UHFNUM_reg_t { + uint16_t _FNUM : 11; + uint16_t reserved1 : 5; + }; + static_assert(sizeof(UHFNUM_reg_t) == 2, "invalid size of ATUSB90 UHFNUM_reg_t"); + + struct UPINTX_reg_t { + uint8_t _RXINI : 1; + uint8_t _RXSTALLI : 1; + uint8_t _TXOUTI : 1; + uint8_t _TXSTPI : 1; + uint8_t _PERRI : 1; + uint8_t _RWAL : 1; + uint8_t _NAKEDI : 1; + uint8_t _FIFOCON : 1; + }; + static_assert(sizeof(UPINTX_reg_t) == 1, "invalid size of ATUSB90 UPINTX_reg_t"); + + struct UPNUM_reg_t { + uint8_t _PNUM : 3; + uint8_t reserved1 : 5; + }; + static_assert(sizeof(UPNUM_reg_t) == 1, "invalid size of ATUSB90 UPNUM_reg_t"); + + struct UPRST_reg_t { + uint8_t _PRST : 7; + uint8_t reserved1 : 1; + }; + static_assert(sizeof(UPRST_reg_t) == 1, "invalid size of ATUSB90 UPRST_reg_t"); + + struct UPCONX_reg_t { + uint8_t _PEN : 1; + uint8_t reserved1 : 2; + uint8_t _RSTDT : 1; + uint8_t _AUTOSW : 1; + uint8_t _INMODE : 1; + uint8_t _PFREEZE : 1; + uint8_t reserved2 : 1; + }; + static_assert(sizeof(UPCONX_reg_t) == 1, "invalid size of ATUSB90 UPCONX_reg_t"); + + struct UPCFG0X_reg_t { + uint8_t _PEPNUM : 4; + uint8_t _PTOKEN : 2; + uint8_t _PTYPE : 2; + }; + static_assert(sizeof(UPCFG0X_reg_t) == 1, "invalid size of ATUSB90 UPCFG0_reg_t"); + + struct UPCFG1X_reg_t { + uint8_t reserved1 : 1; + uint8_t _ALLOC : 1; + uint8_t _PBK : 2; + uint8_t _PSIZE : 3; + uint8_t reserved2 : 1; + }; + static_assert(sizeof(UPCFG1X_reg_t) == 1, "invalid size of ATUSB90 UPCFG1X_reg_t"); + + struct UPSTAX_reg_t { + uint8_t _NBUSYBK : 2; + uint8_t _DTSEQ : 2; + uint8_t reserved1 : 1; + uint8_t _UNDERFI : 1; + uint8_t _OVERFI : 1; + uint8_t _CFGOK : 1; + }; + static_assert(sizeof(UPSTAX_reg_t) == 1, "invalid size of ATUSB90 UPSTAX_reg_t"); + + struct UPIENX_reg_t { + uint8_t _RXINE : 1; + uint8_t _RXSTALLE : 1; + uint8_t _TXOUTE : 1; + uint8_t _TXSTPE : 1; + uint8_t _PERRE : 1; + uint8_t reserved1 : 1; + uint8_t _NAKEDE : 1; + uint8_t _FLERRE : 1; + }; + static_assert(sizeof(UPIENX_reg_t) == 1, "invalid size of ATUSB90 UPIENX_reg_t"); + + struct UHWCON_reg_t { + uint8_t _UVREGE : 1; + uint8_t reserved1 : 3; + uint8_t _UVCONE : 1; + uint8_t reserved2 : 1; + uint8_t _UIDE : 1; + uint8_t _UIMOD : 1; + }; + static_assert(sizeof(UHWCON_reg_t) == 1, "invalid size of ATUSB90 UHWCON_reg_t"); + + struct USBCON_reg_t { + uint8_t _VBUSTE : 1; + uint8_t _IDTE : 1; + uint8_t reserved1 : 2; + uint8_t _OTGPADE : 1; + uint8_t _FRZCLK : 1; + uint8_t _HOST : 1; + uint8_t _USBE : 1; + }; + static_assert(sizeof(USBCON_reg_t) == 1, "invalid size of ATUSB90 USBCON_reg_t"); + + struct USBSTA_reg_t { + uint8_t _VBUS : 1; + uint8_t _ID : 1; + uint8_t reserved1 : 1; + uint8_t _SPEED : 1; + uint8_t reserved2 : 4; + }; + static_assert(sizeof(USBSTA_reg_t) == 1, "invalid size of ATUSB90 USBSTA_reg_t"); + + struct USBINT_reg_t { + uint8_t _VBUSTI : 1; + uint8_t _IDTI : 1; + uint8_t reserved1 : 6; + }; + static_assert(sizeof(USBINT_reg_t) == 1, "invalid size of ATUSB90 USBINT_reg_t"); + + struct UDPADD_reg_t { + uint16_t _DPADD : 11; + uint16_t reserved1 : 4; + uint16_t _DPACC : 1; + }; + static_assert(sizeof(UDPADD_reg_t) == 2, "invalid size of ATUSB90 UDPADD_reg_t"); + + struct OTGCON_reg_t { + uint8_t _VBUSRQC : 1; + uint8_t _VBUSREQ : 1; + uint8_t _VBUSHWC : 1; + uint8_t _SRPSEL : 1; + uint8_t _SRPREQ : 1; + uint8_t _HNPREQ : 1; + uint8_t reserved1 : 1; + uint8_t _zero : 1; + }; + static_assert(sizeof(OTGCON_reg_t) == 1, "invalid size of ATUSB90 OTGCON_reg_t"); + + struct OTGIEN_reg_t { + uint8_t _SRPE : 1; + uint8_t _VBERRE : 1; + uint8_t _BCERRE : 1; + uint8_t _ROLEEXE : 1; + uint8_t _HNPERRE : 1; + uint8_t _STOE : 1; + uint8_t reserved1 : 2; + }; + static_assert(sizeof(OTGIEN_reg_t) == 1, "invalid size of ATUSB90 OTGIEN_reg_t"); + + struct OTGINT_reg_t { + uint8_t _SRPI : 1; + uint8_t _VBERRI : 1; + uint8_t _BCERRI : 1; + uint8_t _ROLEEXI : 1; + uint8_t _HNPERRI : 1; + uint8_t _STOI : 1; + uint8_t reserved1 : 2; + }; + static_assert(sizeof(OTGINT_reg_t) == 1, "invalid size of ATUSB90 OTGINT_reg_t"); + + struct UDCON_reg_t { + uint8_t _DETACH : 1; + uint8_t _RMWKUP : 1; + uint8_t _LSM : 1; + uint8_t reserved1 : 5; + }; + static_assert(sizeof(UDCON_reg_t) == 1, "invalid size of ATUSB90 UDCON_reg_t"); + + struct UDINT_reg_t { + uint8_t _SUSPI : 1; + uint8_t _MSOFI : 1; + uint8_t _SOFI : 1; + uint8_t _EORSTI : 1; + uint8_t _WAKEUPI : 1; + uint8_t _EORSMI : 1; + uint8_t _UPRSMI : 1; + uint8_t reserved1 : 1; + }; + static_assert(sizeof(UDINT_reg_t) == 1, "invalid size of ATUSB90 UDINT_reg_t"); + + struct UDIEN_reg_t { + uint8_t _SUSPE : 1; + uint8_t _MSOFE : 1; + uint8_t _SOFE : 1; + uint8_t _EORSTE : 1; + uint8_t _WAKEUPE : 1; + uint8_t _EORSME : 1; + uint8_t _UPRSME : 1; + uint8_t reserved1 : 1; + }; + static_assert(sizeof(UDIEN_reg_t) == 1, "invalid size of ATUSB90 UDIEN_reg_t"); + + struct UDADDR_reg_t { + uint8_t _UADD : 7; + uint8_t _ADDEN : 1; + }; + static_assert(sizeof(UDADDR_reg_t) == 1, "invalid size of ATUSB90 UADDR_reg_t"); + + struct UDFNUM_reg_t { + uint16_t _FNUM : 11; + uint16_t reserved1 : 5; + }; + static_assert(sizeof(UDFNUM_reg_t) == 2, "invalid size of ATUSB90 UDFNUM_reg_t"); + + struct UDMFN_reg_t { + uint8_t reserved1 : 4; + uint8_t _FNCERR : 1; + uint8_t reserved2 : 3; + }; + static_assert(sizeof(UDMFN_reg_t) == 1, "invalid size of ATUSB90 UDMFN_reg_t"); + + struct UDTST_reg_t { + uint8_t reserved1 : 2; + uint8_t _TSTJ : 1; + uint8_t _TSTK : 1; + uint8_t _TSTPCKT : 1; + uint8_t _OPMODE2 : 1; + uint8_t reserved2 : 2; + }; + static_assert(sizeof(UDTST_reg_t) == 1, "invalid size of ATUSB90 UDTST_reg_t"); + + struct UEINTX_reg_t { + uint8_t _TXINI : 1; + uint8_t _STALLEDI : 1; + uint8_t _RXOUTI : 1; + uint8_t _RXSTPI : 1; + uint8_t _NAKOUTI : 1; + uint8_t _RWAL : 1; + uint8_t _NAKINI : 1; + uint8_t _FIFOCON : 1; + }; + static_assert(sizeof(UEINTX_reg_t) == 1, "invalid size of ATUSB90 UEINTX_reg_t"); + + struct UENUM_reg_t { + uint8_t _EPNUM : 3; + uint8_t reserved1 : 5; + }; + static_assert(sizeof(UENUM_reg_t) == 1, "invalid size of ATUSB90 UENUM_reg_t"); + + struct UERST_reg_t { + uint8_t _EPRST : 7; + uint8_t reserved1 : 1; + }; + static_assert(sizeof(UERST_reg_t) == 1, "invalid size of ATUSB90 UERST_reg_t"); + + struct UECONX_reg_t { + uint8_t _EPEN : 1; + uint8_t reserved1 : 2; + uint8_t _RSTDT : 1; + uint8_t _STALLRQC : 1; + uint8_t _STALLRQ : 1; + uint8_t reserved2 : 2; + }; + static_assert(sizeof(UECONX_reg_t) == 1, "invalid size of ATUSB90 UECONX_reg_t"); + + struct UECFG0X_reg_t { + uint8_t _EPDIR : 1; + uint8_t _NYETSDIS : 1; + uint8_t _AUTOSW : 1; + uint8_t _ISOSW : 1; + uint8_t reserved1 : 2; + uint8_t _EPTYPE : 2; + }; + static_assert(sizeof(UECFG0X_reg_t) == 1, "invalid size of ATUSB90 UECFG0X_reg_t"); + + struct UECFG1X_reg_t { + uint8_t reserved1 : 1; + uint8_t _ALLOC : 1; + uint8_t _EPBK : 2; + uint8_t _EPSIZE : 3; + uint8_t reserved2 : 1; + }; + static_assert(sizeof(UECFG1X_reg_t) == 1, "invalid size of ATUSB90 UECFG1X_reg_t"); + + struct UESTA0X_reg_t { + uint8_t _NBUSYBK : 2; + uint8_t _DTSEQ : 2; + uint8_t _ZLPSEEN : 1; + uint8_t _UNDERFI : 1; + uint8_t _OVERFI : 1; + uint8_t _CFGOK : 1; + }; + static_assert(sizeof(UESTA0X_reg_t) == 1, "invalid size of ATUSB90 UESTA0X_reg_t"); + + struct UESTA1X_reg_t { + uint8_t _CURRBK : 2; + uint8_t _CTRLDIR : 1; + uint8_t reserved1 : 5; + }; + static_assert(sizeof(UESTA1X_reg_t) == 1, "invalid size of ATUSB90 UESTA1X_reg_t"); + + struct UEIENX_reg_t { + uint8_t _TXINE : 1; + uint8_t _STALLEDE : 1; + uint8_t _RXOUTE : 1; + uint8_t _RXSTPE : 1; + uint8_t _NAKOUTE : 1; + uint8_t reserved1 : 1; + uint8_t _NAKINE : 1; + uint8_t _FLERRE : 1; + }; + static_assert(sizeof(UEIENX_reg_t) == 1, "invalid size of ATUSB90 UEIENX_reg_t"); + + struct UEBCX_reg_t { + uint16_t _BYCT : 11; + uint16_t reserved1 : 5; + }; + static_assert(sizeof(UEBCX_reg_t) == 2, "invalid size of ATUSB90 UEBCX_reg_t"); + + struct UEINT_reg_t { + uint8_t _EPINT : 7; + uint8_t reserved1 : 1; + }; + static_assert(sizeof(UEINT_reg_t) == 1, "invalid size of ATUSB90 UEINT_reg_t"); + + struct UPERRX_reg_t { + uint8_t _DATATGL : 1; + uint8_t _DATAPID : 1; + uint8_t _PID : 1; + uint8_t _TIMEOUT : 1; + uint8_t _CRC16 : 1; + uint8_t _COUNTER : 2; + uint8_t reserved1 : 1; + }; + static_assert(sizeof(UPERRX_reg_t) == 1, "invalid size of ATUSB90 UPERRX_reg_t"); + + struct UPBCX_reg_t { + uint16_t _PBYCT : 11; + uint16_t reserved1 : 5; + }; + static_assert(sizeof(UPBCX_reg_t) == 2, "invalid size of ATUSB90 UPBCX_reg_t"); + + struct OTGTCON_reg_t { + uint8_t _VALUE : 2; + uint8_t reserved1 : 3; + uint8_t _PAGE : 2; + uint8_t _one : 1; + }; + static_assert(sizeof(OTGTCON_reg_t) == 1, "invalid size of ATUSB90 OTGTCON_reg_t"); + + struct PLLCSR_reg_t { + uint8_t _PLOCK : 1; + uint8_t _PLLE : 1; + uint8_t _PLLP : 3; + uint8_t reserved1 : 3; + }; + static_assert(sizeof(PLLCSR_reg_t) == 1, "invalid size of ATUSB90 PLLCSR_reg_t"); + +#endif // __AVR_TRM04__ + +/** + * REGISTER MEMORY MAP + */ + +#define __AVR_DEFREG(tn,n,a) static volatile tn& n = *(tn*)a +#define _AVR_DEFREG(n,a) __AVR_DEFREG(n##_reg_t, _##n, a) + +#ifdef __AVR_TRM01__ + // page 399ff of ATmega640-1280-1281-2560-2561-Datasheet-DS40002211A.pdf + + __AVR_DEFREG(PORT_dev_t, _PORTA, 0x20); + __AVR_DEFREG(PORT_dev_t, _PORTB, 0x23); + __AVR_DEFREG(PORT_dev_t, _PORTC, 0x26); + __AVR_DEFREG(PORT_dev_t, _PORTD, 0x29); + __AVR_DEFREG(PORT_dev_t, _PORTE, 0x2C); + __AVR_DEFREG(PORT_dev_t, _PORTF, 0x2F); + __AVR_DEFREG(PORTG_dev_t, _PORTG, 0x32); + __AVR_DEFREG(PORT_dev_t, _PORTH, 0x100); + __AVR_DEFREG(PORT_dev_t, _PORTJ, 0x103); + __AVR_DEFREG(PORT_dev_t, _PORTK, 0x106); + __AVR_DEFREG(PORT_dev_t, _PORTL, 0x109); + __AVR_DEFREG(TIFR0_reg_t, _TIFR0, 0x35); + __AVR_DEFREG(TIFR1_reg_t, _TIFR1, 0x36); + __AVR_DEFREG(TIFR2_reg_t, _TIFR2, 0x37); + __AVR_DEFREG(TIFR3_reg_t, _TIFR3, 0x38); + __AVR_DEFREG(TIFR4_reg_t, _TIFR4, 0x39); + __AVR_DEFREG(TIFR5_reg_t, _TIFR5, 0x3A); + __AVR_DEFREG(PCIFR_reg_t, _PCIFR, 0x3B); + __AVR_DEFREG(EIFR_reg_t, _EIFR, 0x3C); + __AVR_DEFREG(EIMSK_reg_t, _EIMSK, 0x3D); + __AVR_DEFREG(_bit_reg_t, _GPIOR0, 0x3E); + __AVR_DEFREG(EECR_reg_t, _EECR, 0x3F); + __AVR_DEFREG(uint8_t, _EEDR, 0x40); + __AVR_DEFREG(EEAR_reg_t, _EEAR, 0x41); + __AVR_DEFREG(GTCCR_reg_t, _GTCCR, 0x43); + __AVR_DEFREG(TIMER_8bit_dev_t, TIMER0, 0x44); + __AVR_DEFREG(_bit_reg_t, _GPIOR1, 0x4A); + __AVR_DEFREG(_bit_reg_t, _GPIOR2, 0x4B); + __AVR_DEFREG(SPCR_reg_t, _SPCR, 0x4C); + __AVR_DEFREG(SPSR_reg_t, _SPSR, 0x4D); + __AVR_DEFREG(uint8_t, _SPDR, 0x4E); + __AVR_DEFREG(ACSR_reg_t, _ACSR, 0x50); + __AVR_DEFREG(_bit_reg_t, _OCDR, 0x51); + __AVR_DEFREG(SMCR_reg_t, _SMCR, 0x53); + __AVR_DEFREG(MCUSR_reg_t, _MCUSR, 0x54); + __AVR_DEFREG(MCUCR_reg_t, _MCUCR, 0x55); + __AVR_DEFREG(SPMCSR_reg_t, _SPMCSR, 0x57); + __AVR_DEFREG(RAMPZ_reg_t, _RAMPZ, 0x5B); + __AVR_DEFREG(EIND_reg_t, _EIND, 0x5C); + __AVR_DEFREG(SP_reg_t, _SP, 0x5D); + __AVR_DEFREG(SREG_reg_t, _SREG, 0x5F); + __AVR_DEFREG(WDTCSR_reg_t, _WDTCSR, 0x60); + __AVR_DEFREG(CLKPR_reg_t, _CLKPR, 0x61); + __AVR_DEFREG(PRR0_reg_t, _PRR0, 0x64); + __AVR_DEFREG(PRR1_reg_t, _PRR1, 0x65); + __AVR_DEFREG(uint8_t, _OSCCAL, 0x66); + __AVR_DEFREG(PCICR_reg_t, _PCICR, 0x68); + __AVR_DEFREG(EICRA_reg_t, _EICRA, 0x69); + __AVR_DEFREG(EICRB_reg_t, _EICRB, 0x6A); + __AVR_DEFREG(_bit_reg_t, _PCMSK0, 0x6B); + __AVR_DEFREG(_bit_reg_t, _PCMSK1, 0x6C); + __AVR_DEFREG(_bit_reg_t, _PCMSK2, 0x6D); + __AVR_DEFREG(TIMSK0_reg_t, _TIMSK0, 0x6E); + __AVR_DEFREG(TIMSK1_reg_t, _TIMSK1, 0x6F); + __AVR_DEFREG(TIMSK2_reg_t, _TIMSK2, 0x70); + __AVR_DEFREG(TIMSK3_reg_t, _TIMSK3, 0x71); + __AVR_DEFREG(TIMSK4_reg_t, _TIMSK4, 0x72); + __AVR_DEFREG(TIMSK5_reg_t, _TIMSK5, 0x73); + __AVR_DEFREG(XMCRA_reg_t, _XMCRA, 0x74); + __AVR_DEFREG(XMCRB_reg_t, _XMCRB, 0x75); + __AVR_DEFREG(uint16_t, _ADC, 0x78); + __AVR_DEFREG(ADCSRA_reg_t, _ADCSRA, 0x7A); + __AVR_DEFREG(ADCSRB_reg_t, _ADCSRB, 0x7B); + __AVR_DEFREG(ADMUX_reg_t, _ADMUX, 0x7C); + __AVR_DEFREG(DIDR2_reg_t, _DIDR2, 0x7D); + __AVR_DEFREG(DIDR0_reg_t, _DIDR0, 0x7E); + __AVR_DEFREG(DIDR1_reg_t, _DIDR1, 0x7F); + __AVR_DEFREG(TIMER_dev_t, TIMER1, 0x80); + __AVR_DEFREG(TIMER_dev_t, TIMER3, 0x90); + __AVR_DEFREG(TIMER_dev_t, TIMER4, 0xA0); + __AVR_DEFREG(TIMER_dev_t, TIMER5, 0x120); + __AVR_DEFREG(TIMER_8bit_dev_t, _TIMER2, 0xB0); + __AVR_DEFREG(ASSR_reg_t, _ASSR, 0xB6); + __AVR_DEFREG(uint8_t, _TWBR, 0xB8); + __AVR_DEFREG(TWSR_reg_t, _TWSR, 0xB9); + __AVR_DEFREG(TWAR_reg_t, _TWAR, 0xBA); + __AVR_DEFREG(uint8_t, _TWDR, 0xBB); + __AVR_DEFREG(TWCR_reg_t, _TWCR, 0xBC); + __AVR_DEFREG(TWAMR_reg_t, _TWAMR, 0xBD); + __AVR_DEFREG(USART_dev_t, USART0, 0xC0); + __AVR_DEFREG(USART_dev_t, USART1, 0xC8); + __AVR_DEFREG(USART_dev_t, USART2, 0xD0); + __AVR_DEFREG(USART_dev_t, USART3, 0x130); + +#elif defined(__AVR_TRM02__) + // page 637ff of ATmega164A_PA-324A_PA-644A_PA-1284_P_Data-Sheet-40002070B.pdf + __AVR_DEFREG(PORT_dev_t, _PORTA, 0x20); + __AVR_DEFREG(PORT_dev_t, _PORTB, 0x23); + __AVR_DEFREG(PORT_dev_t, _PORTC, 0x26); + __AVR_DEFREG(PORT_dev_t, _PORTD, 0x29); + __AVR_DEFREG(TIFR0_reg_t, _TIFR0, 0x35); + __AVR_DEFREG(TIFR1_reg_t, _TIFR1, 0x36); + __AVR_DEFREG(TIFR2_reg_t, _TIFR2, 0x37); + __AVR_DEFREG(TIFR3_reg_t, _TIFR3, 0x38); + __AVR_DEFREG(PCIFR_reg_t, _PCIFR, 0x3B); + __AVR_DEFREG(EIFR_reg_t, _EIFR, 0x3C); + __AVR_DEFREG(EIMSK_reg_t, _EIMSK, 0x3D); + __AVR_DEFREG(_bit_reg_t, _GPIOR0, 0x3E); + __AVR_DEFREG(EECR_reg_t, _EECR, 0x3F); + __AVR_DEFREG(uint8_t, _EEDR, 0x40); + __AVR_DEFREG(EEAR_reg_t, _EEAR, 0x41); + __AVR_DEFREG(GTCCR_reg_t, _GTCCR, 0x43); + __AVR_DEFREG(TIMER_8bit_dev_t, TIMER0, 0x44); + __AVR_DEFREG(_bit_reg_t, _GPIOR1, 0x4A); + __AVR_DEFREG(_bit_reg_t, _GPIOR2, 0x4B); + __AVR_DEFREG(SPCR_reg_t, _SPCR, 0x4C); + __AVR_DEFREG(SPSR_reg_t, _SPSR, 0x4D); + __AVR_DEFREG(uint8_t, _SPDR, 0x4E); + __AVR_DEFREG(ACSR_reg_t, _ACSR, 0x50); + __AVR_DEFREG(SMCR_reg_t, _SMCR, 0x53); + __AVR_DEFREG(MCUSR_reg_t, _MSUSR, 0x54); + __AVR_DEFREG(MCUCR_reg_t, _MCUCR, 0x55); + __AVR_DEFREG(SPMCSR_reg_t, _SPMCSR, 0x57); + __AVR_DEFREG(SP_reg_t, _SP, 0x5D); + __AVR_DEFREG(SREG_reg_t, _SREG, 0x5F); + __AVR_DEFREG(WDTCSR_reg_t, _WDTCSR, 0x60); + __AVR_DEFREG(CLKPR_reg_t, _CLKPR, 0x61); + __AVR_DEFREG(PRR0_reg_t, _PRR0, 0x64); + __AVR_DEFREG(PRR1_reg_t, _PRR1, 0x65); + __AVR_DEFREG(uint8_t, _OSCCAL, 0x66); + __AVR_DEFREG(PCICR_reg_t, _PCICR, 0x68); + __AVR_DEFREG(EICRA_reg_t, _EICRA, 0x69); + __AVR_DEFREG(_bit_reg_t, _PCMSK0, 0x6B); + __AVR_DEFREG(_bit_reg_t, _PCMSK1, 0x6C); + __AVR_DEFREG(_bit_reg_t, _PCMSK2, 0x6D); + __AVR_DEFREG(TIMSK0_reg_t, _TIMSK0, 0x6E); + __AVR_DEFREG(TIMSK1_reg_t, _TIMSK1, 0x6F); + __AVR_DEFREG(TIMSK2_reg_t, _TIMSK2, 0x70); + __AVR_DEFREG(TIMSK3_reg_t, _TIMSK3, 0x71); + __AVR_DEFREG(_bit_reg_t, _PCMSK3, 0x73); + __AVR_DEFREG(uint16_t, _ADC, 0x78); + __AVR_DEFREG(ADCSRA_reg_t, _ADCSRA, 0x7A); + __AVR_DEFREG(ADCSRB_reg_t, _ADCSRB, 0x7B); + __AVR_DEFREG(ADMUX_reg_t, _ADMUX, 0x7C); + __AVR_DEFREG(DIDR0_reg_t, _DIDR0, 0x7E); + __AVR_DEFREG(DIDR1_reg_t, _DIDR1, 0x7F); + __AVR_DEFREG(TIMER_dev_t, TIMER1, 0x80); + __AVR_DEFREG(TIMER_dev_t, TIMER3, 0x90); + __AVR_DEFREG(TIMER_8bit_dev_t, _TIMER2, 0xB0); + __AVR_DEFREG(ASSR_reg_t, _ASSR, 0xB6); + __AVR_DEFREG(uint8_t, _TWBR, 0xB8); + __AVR_DEFREG(TWSR_reg_t, _TWSR, 0xB9); + __AVR_DEFREG(TWAR_reg_t, _TWAR, 0xBA); + __AVR_DEFREG(uint8_t, _TWDR, 0xBB); + __AVR_DEFREG(TWCR_reg_t, _TWCR, 0xBC); + __AVR_DEFREG(TWAMR_reg_t, _TWAMR, 0xBD); + __AVR_DEFREG(USART_dev_t, USART0, 0xC0); + __AVR_DEFREG(USART_dev_t, USART1, 0xC8); + +#elif defined(__AVR_TRM03__) + // page 621ff of ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061B.pdf + __AVR_DEFREG(PORT_dev_t, _PORTB, 0x23); + __AVR_DEFREG(PORTC_dev_t, _PORTC, 0x26); + __AVR_DEFREG(PORT_dev_t, _PORTD, 0x29); + __AVR_DEFREG(TIFR0_reg_t, _TIFR0, 0x35); + __AVR_DEFREG(TIFR1_reg_t, _TIFR1, 0x36); + __AVR_DEFREG(TIFR2_reg_t, _TIFR2, 0x37); + __AVR_DEFREG(PCIFR_reg_t, _PCIFR, 0x3B); + __AVR_DEFREG(EIFR_reg_t, _EIFR, 0x3C); + __AVR_DEFREG(EIMSK_reg_t, _EIMSK, 0x3D); + __AVR_DEFREG(_bit_reg_t, _GPIOR0, 0x3E); + __AVR_DEFREG(EECR_reg_t, _EECR, 0x3F); + __AVR_DEFREG(uint8_t, _EEDR, 0x40); + __AVR_DEFREG(EEAR_reg_t, _EEAR, 0x41); + __AVR_DEFREG(GTCCR_reg_t, _GTCCR, 0x43); + __AVR_DEFREG(TIMER_8bit_dev_t, TIMER0, 0x44); + __AVR_DEFREG(_bit_reg_t, _GPIOR1, 0x4A); + __AVR_DEFREG(_bit_reg_t, _GPIOR2, 0x4B); + __AVR_DEFREG(SPCR_reg_t, _SPCR, 0x4C); + __AVR_DEFREG(SPSR_reg_t, _SPSR, 0x4D); + __AVR_DEFREG(uint8_t, _SPDR, 0x4E); + __AVR_DEFREG(ACSR_reg_t, _ACSR, 0x50); + __AVR_DEFREG(SMCR_reg_t, _SMCR, 0x53); + __AVR_DEFREG(MCUSR_reg_t, _MSUCR, 0x54); + __AVR_DEFREG(MCUCR_reg_t, _MCUCR, 0x55); + __AVR_DEFREG(SPMCSR_reg_t, _SPMCSR, 0x57); + __AVR_DEFREG(SP_reg_t, _SP, 0x5D); + __AVR_DEFREG(SREG_reg_t, _SREG, 0x5F); + __AVR_DEFREG(WDTCSR_reg_t, _WDTCSR, 0x60); + __AVR_DEFREG(CLKPR_reg_t, _CLKPR, 0x61); + __AVR_DEFREG(PRR0_reg_t, _PRR0, 0x64); + __AVR_DEFREG(uint8_t, _OSCCAL, 0x66); + __AVR_DEFREG(PCICR_reg_t, _PCICR, 0x68); + __AVR_DEFREG(EICRA_reg_t, _EICRA, 0x69); + __AVR_DEFREG(_bit_reg_t, _PCMSK0, 0x6B); + __AVR_DEFREG(_bitPCMSK1_reg_t, _PCMSK1, 0x6C); + __AVR_DEFREG(_bit_reg_t, _PCMSK2, 0x6D); + __AVR_DEFREG(TIMSK0_reg_t, _TIMSK0, 0x6E); + __AVR_DEFREG(TIMSK1_reg_t, _TIMSK1, 0x6F); + __AVR_DEFREG(TIMSK2_reg_t, _TIMSK2, 0x70); + __AVR_DEFREG(uint16_t, _ADC, 0x78); + __AVR_DEFREG(ADCSRA_reg_t, _ADCSRA, 0x7A); + __AVR_DEFREG(ADCSRB_reg_t, _ADCSRB, 0x7B); + __AVR_DEFREG(ADMUX_reg_t, _ADMUX, 0x7C); + __AVR_DEFREG(DIDR0_reg_t, _DIDR0, 0x7E); + __AVR_DEFREG(DIDR1_reg_t, _DIDR1, 0x7F); + __AVR_DEFREG(TIMER_dev_t, TIMER1, 0x80); + __AVR_DEFREG(TIMER_8bit_dev_t, _TIMER2, 0xB0); + __AVR_DEFREG(ASSR_reg_t, _ASSR, 0xB6); + __AVR_DEFREG(uint8_t, _TWBR, 0xB8); + __AVR_DEFREG(TWSR_reg_t, _TWSR, 0xB9); + __AVR_DEFREG(TWAR_reg_t, _TWAR, 0xBA); + __AVR_DEFREG(uint8_t, _TWDR, 0xBB); + __AVR_DEFREG(TWCR_reg_t, _TWCR, 0xBC); + __AVR_DEFREG(TWAMR_reg_t, _TWAMR, 0xBD); + __AVR_DEFREG(USART_dev_t, USART0, 0xC0); + +#elif defined(__AVR_TRM04__) + __AVR_DEFREG(PORT_dev_t, _PORTA, 0x20); + __AVR_DEFREG(PORT_dev_t, _PORTB, 0x23); + __AVR_DEFREG(PORT_dev_t, _PORTC, 0x26); + __AVR_DEFREG(PORT_dev_t, _PORTD, 0x29); + __AVR_DEFREG(PORT_dev_t, _PORTE, 0x2C); + __AVR_DEFREG(PORT_dev_t, _PORTF, 0x2F); + __AVR_DEFREG(TIFR0_reg_t, _TIFR0, 0x35); + __AVR_DEFREG(TIFR1_reg_t, _TIFR1, 0x36); + __AVR_DEFREG(TIFR2_reg_t, _TIFR2, 0x37); + __AVR_DEFREG(TIFR3_reg_t, _TIFR3, 0x38); + __AVR_DEFREG(PCIFR_reg_t, _PCIFR, 0x3B); + __AVR_DEFREG(EIFR_reg_t, _EIFR, 0x3C); + __AVR_DEFREG(EIMSK_reg_t, _EIMSK, 0x3D); + __AVR_DEFREG(_bit_reg_t, _GPIOR0, 0x3E); + __AVR_DEFREG(EECR_reg_t, _EECR, 0x3F); + __AVR_DEFREG(uint8_t, _EEDR, 0x40); + __AVR_DEFREG(EEAR_reg_t, _EEAR, 0x41); + __AVR_DEFREG(GTCCR_reg_t, _GTCCR, 0x43); + __AVR_DEFREG(TIMER_8bit_dev_t, TIMER0, 0x44); + __AVR_DEFREG(PLLCSR_reg_t, _PLLCSR, 0x49); + __AVR_DEFREG(_bit_reg_t, _GPIOR1, 0x4A); + __AVR_DEFREG(_bit_reg_t, _GPIOR2, 0x4B); + __AVR_DEFREG(SPCR_reg_t, _SPCR, 0x4C); + __AVR_DEFREG(SPSR_reg_t, _SPSR, 0x4D); + __AVR_DEFREG(uint8_t, _SPDR, 0x4E); + __AVR_DEFREG(ACSR_reg_t, _ACSR, 0x50); + __AVR_DEFREG(uint8_t, _OCDR, 0x51); + __AVR_DEFREG(SMCR_reg_t, _SMCR, 0x53); + __AVR_DEFREG(MCUSR_reg_t, _MCUSR, 0x54); + __AVR_DEFREG(MCUCR_reg_t, _MCUCR, 0x55); + __AVR_DEFREG(SPMCSR_reg_t, _SPMCSR, 0x57); + __AVR_DEFREG(RAMPZ_reg_t, _RAMPZ, 0x5B); + __AVR_DEFREG(SP_reg_t, _SP, 0x5D); + __AVR_DEFREG(SREG_reg_t, _SREG, 0x5F); + __AVR_DEFREG(WDTCSR_reg_t, _WDTCSR, 0x60); + __AVR_DEFREG(CLKPR_reg_t, _CLKPR, 0x61); + __AVR_DEFREG(PRR0_reg_t, _PRR0, 0x64); + __AVR_DEFREG(PRR1_reg_t, _PRR1, 0x65); + __AVR_DEFREG(uint8_t, _OSCCAL, 0x66); + __AVR_DEFREG(PCICR_reg_t, _PCICR, 0x68); + __AVR_DEFREG(EICRA_reg_t, _EICRA, 0x69); + __AVR_DEFREG(EICRB_reg_t, _EICRB, 0x6A); + __AVR_DEFREG(_bit_reg_t, _PCMSK0, 0x6B); + __AVR_DEFREG(TIMSK0_reg_t, _TIMSK0, 0x6E); + __AVR_DEFREG(TIMSK1_reg_t, _TIMSK1, 0x6F); + __AVR_DEFREG(TIMSK2_reg_t, _TIMSK2, 0x70); + __AVR_DEFREG(TIMSK3_reg_t, _TIMSK3, 0x71); + __AVR_DEFREG(XMCRA_reg_t, _XMCRA, 0x74); + __AVR_DEFREG(XMCRB_reg_t, _XMCRB, 0x75); + __AVR_DEFREG(uint16_t, _ADC, 0x78); + __AVR_DEFREG(ADCSRA_reg_t, _ADCSRA, 0x7A); + __AVR_DEFREG(ADCSRB_reg_t, _ADCSRB, 0x7B); + __AVR_DEFREG(ADMUX_reg_t, _ADMUX, 0x7C); + __AVR_DEFREG(DIDR0_reg_t, _DIDR0, 0x7E); + __AVR_DEFREG(DIDR1_reg_t, _DIDR1, 0x7F); + __AVR_DEFREG(TIMER_dev_t, TIMER1, 0x80); + __AVR_DEFREG(TIMER_dev_t, TIMER3, 0x90); + __AVR_DEFREG(UHCON_reg_t, _UHCON, 0x9E); + __AVR_DEFREG(UHINT_reg_t, _UHINT, 0x9F); + __AVR_DEFREG(UHIEN_reg_t, _UHIEN, 0xA0); + __AVR_DEFREG(UHADDR_reg_t, _UHADDR, 0xA1); + __AVR_DEFREG(UHFNUM_reg_t, _UHFNUM, 0xA2); + __AVR_DEFREG(uint8_t, _UHFLEN, 0xA4); + __AVR_DEFREG(uint8_t, _UPINRQX, 0xA5); + __AVR_DEFREG(UPINTX_reg_t, _UPINTX, 0xA6); + __AVR_DEFREG(UPNUM_reg_t, _UPNUM, 0xA7); + __AVR_DEFREG(UPRST_reg_t, _UPRST, 0xA8); + __AVR_DEFREG(UPCONX_reg_t, _UPCONX, 0xA9); + _AVR_DEFREG(UPCFG0X, 0xAA); + _AVR_DEFREG(UPCFG1X, 0xAB); + _AVR_DEFREG(UPSTAX, 0xAC); + __AVR_DEFREG(uint8_t, _UPCFG2X, 0xAD); + _AVR_DEFREG(UPIENX, 0xAE); + __AVR_DEFREG(uint8_t, _UPDATX, 0xAF); + __AVR_DEFREG(TIMER_8bit_dev_t, _TIMER2, 0xB0); + __AVR_DEFREG(ASSR_reg_t, _ASSR, 0xB6); + __AVR_DEFREG(uint8_t, _TWBR, 0xB8); + __AVR_DEFREG(TWSR_reg_t, _TWSR, 0xB9); + __AVR_DEFREG(TWAR_reg_t, _TWAR, 0xBA); + __AVR_DEFREG(uint8_t, _TWDR, 0xBB); + __AVR_DEFREG(TWCR_reg_t, _TWCR, 0xBC); + __AVR_DEFREG(TWAMR_reg_t, _TWAMR, 0xBD); + __AVR_DEFREG(USART_dev_t, USART1, 0xC8); + _AVR_DEFREG(UHWCON, 0xD7); + _AVR_DEFREG(USBCON, 0xD8); + _AVR_DEFREG(USBSTA, 0xD9); + _AVR_DEFREG(USBINT, 0xDA); + _AVR_DEFREG(UDPADD, 0xDB); + _AVR_DEFREG(OTGCON, 0xDD); + _AVR_DEFREG(OTGIEN, 0xDE); + _AVR_DEFREG(OTGINT, 0xDF); + _AVR_DEFREG(UDCON, 0xE0); + _AVR_DEFREG(UDINT, 0xE1); + _AVR_DEFREG(UDIEN, 0xE2); + _AVR_DEFREG(UDADDR, 0xE3); + _AVR_DEFREG(UDFNUM, 0xE4); + _AVR_DEFREG(UDMFN, 0xE6); + _AVR_DEFREG(UDTST, 0xE7); + _AVR_DEFREG(UEINTX, 0xE8); + _AVR_DEFREG(UENUM, 0xE9); + _AVR_DEFREG(UERST, 0xEA); + _AVR_DEFREG(UECONX, 0xEB); + _AVR_DEFREG(UECFG0X, 0xEC); + _AVR_DEFREG(UECFG1X, 0xED); + _AVR_DEFREG(UESTA0X, 0xEE); + _AVR_DEFREG(UESTA1X, 0xEF); + _AVR_DEFREG(UEIENX, 0xF0); + __AVR_DEFREG(uint8_t, _UEDATx, 0xF1); + _AVR_DEFREG(UEBCX, 0xF2); + _AVR_DEFREG(UEINT, 0xF4); + _AVR_DEFREG(UPERRX, 0xF5); + _AVR_DEFREG(UPBCX, 0xF6); + __AVR_DEFREG(uint8_t, _UPINT, 0xF8); + _AVR_DEFREG(OTGTCON, 0xF9); +#elif defined(__AVR_TRM05__) + // page 476ff. of ATmega164P-324P-644P-Data-Sheet-40002071A.pdf + __AVR_DEFREG(PORT_dev_t, _PORTA, 0x20); + __AVR_DEFREG(PORT_dev_t, _PORTB, 0x23); + __AVR_DEFREG(PORT_dev_t, _PORTC, 0x26); + __AVR_DEFREG(PORT_dev_t, _PORTD, 0x29); + __AVR_DEFREG(TIFR0_reg_t, _TIFR0, 0x35); + __AVR_DEFREG(TIFR1_reg_t, _TIFR1, 0x36); + __AVR_DEFREG(TIFR2_reg_t, _TIFR2, 0x37); + __AVR_DEFREG(PCIFR_reg_t, _PCIFR, 0x3B); + __AVR_DEFREG(EIFR_reg_t, _EIFR, 0x3C); + __AVR_DEFREG(EIMSK_reg_t, _EIMSK, 0x3D); + __AVR_DEFREG(_bit_reg_t, _GPIOR0, 0x3E); + __AVR_DEFREG(EECR_reg_t, _EECR, 0x3F); + __AVR_DEFREG(uint8_t, _EEDR, 0x40); + __AVR_DEFREG(EEAR_reg_t, _EEAR, 0x41); + __AVR_DEFREG(GTCCR_reg_t, _GTCCR, 0x43); + __AVR_DEFREG(TIMER_8bit_dev_t, TIMER0, 0x44); + __AVR_DEFREG(_bit_reg_t, _GPIOR1, 0x4A); + __AVR_DEFREG(_bit_reg_t, _GPIOR2, 0x4B); + __AVR_DEFREG(SPCR_reg_t, _SPCR, 0x4C); + __AVR_DEFREG(SPSR_reg_t, _SPSR, 0x4D); + __AVR_DEFREG(uint8_t, _SPDR, 0x4E); + __AVR_DEFREG(ACSR_reg_t, _ACSR, 0x50); + __AVR_DEFREG(uint8_t, _OCDR, 0x51); + __AVR_DEFREG(SMCR_reg_t, _SMCR, 0x53); + __AVR_DEFREG(MCUSR_reg_t, _MCUSR, 0x54); + __AVR_DEFREG(MCUCR_reg_t, _MCUCR, 0x55); + __AVR_DEFREG(SPMCSR_reg_t, _SPMCSR, 0x57); + __AVR_DEFREG(RAMPZ_reg_t, _RAMPZ, 0x5B); + __AVR_DEFREG(SP_reg_t, _SP, 0x5D); + __AVR_DEFREG(SREG_reg_t, _SREG, 0x5F); + __AVR_DEFREG(WDTCSR_reg_t, _WDTCSR, 0x60); + __AVR_DEFREG(CLKPR_reg_t, _CLKPR, 0x61); + __AVR_DEFREG(PRR0_reg_t, _PRR0, 0x64); + __AVR_DEFREG(uint8_t, _OSCCAL, 0x66); + __AVR_DEFREG(PCICR_reg_t, _PCICR, 0x68); + __AVR_DEFREG(EICRA_reg_t, _EICRA, 0x69); + __AVR_DEFREG(_bit_reg_t, _PCMSK0, 0x6B); + __AVR_DEFREG(_bit_reg_t, _PCMSK1, 0x6C); + __AVR_DEFREG(_bit_reg_t, _PCMSK2, 0x6D); + __AVR_DEFREG(TIMSK0_reg_t, _TIMSK0, 0x6E); + __AVR_DEFREG(TIMSK1_reg_t, _TIMSK1, 0x6F); + __AVR_DEFREG(TIMSK2_reg_t, _TIMSK2, 0x70); + __AVR_DEFREG(_bit_reg_t, _PCMKS3, 0x73); + __AVR_DEFREG(uint16_t, _ADC, 0x78); + __AVR_DEFREG(ADCSRA_reg_t, _ADCSRA, 0x7A); + __AVR_DEFREG(ADCSRB_reg_t, _ADCSRB, 0x7B); + __AVR_DEFREG(ADMUX_reg_t, _ADMUX, 0x7C); + __AVR_DEFREG(DIDR0_reg_t, _DIDR0, 0x7E); + __AVR_DEFREG(DIDR1_reg_t, _DIDR1, 0x7F); + __AVR_DEFREG(TIMER_dev_t, TIMER1, 0x80); + __AVR_DEFREG(TIMER_8bit_dev_t, _TIMER2, 0xB0); + __AVR_DEFREG(ASSR_reg_t, _ASSR, 0xB6); + __AVR_DEFREG(uint8_t, _TWBR, 0xB8); + __AVR_DEFREG(TWSR_reg_t, _TWSR, 0xB8); + __AVR_DEFREG(TWAR_reg_t, _TWAR, 0xBA); + __AVR_DEFREG(uint8_t, _TWDR, 0xBB); + __AVR_DEFREG(TWCR_reg_t, _TWCR, 0xBC); + __AVR_DEFREG(TWAMR_reg_t, _TWAMR, 0xBD); + __AVR_DEFREG(USART_dev_t, USART0, 0xC0); + __AVR_DEFREG(USART_dev_t, USART1, 0xC8); +#endif + +inline void _ATmega_resetperipherals() { + using namespace AVRHelpers; + + // Due to BOOTLOADER or other board inconsistencies we could get launched into Marlin FW + // with configuration that does not match the reset state in the documentation. That is why + // we should clean-reset the entire device. + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + SREG_reg_t __SREG; + __SREG._C = false; + __SREG._Z = false; + __SREG._N = false; + __SREG._V = false; + __SREG._S = false; + __SREG._H = false; + __SREG._T = false; + __SREG._I = false; + dwrite(_SREG, __SREG); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + _RAMPZ._RAMPZ = 0; + #endif + #ifdef __AVR_TRM01__ + _EIND._EIND0 = false; + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM05__) + _EEAR._EEAR = 0; + dwrite(_EEDR, (uint8_t)0u); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + EECR_reg_t __EECR; + __EECR._EERE = false; + __EECR._EEPE = false; + __EECR._EEMPE = false; + __EECR._EERIE = false; + __EECR._EEPM0 = 0; + __EECR._EEPM1 = 0; + __EECR.reserved1 = 0; + dwrite(_EECR, __EECR); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + _GPIOR2.val = 0; + _GPIOR1.val = 0; + _GPIOR0.val = 0; + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + XMCRA_reg_t __XMCRA; + __XMCRA._SRW0 = 0; + __XMCRA._SRW1 = 0; + __XMCRA._SRL = 0; + __XMCRA._SRE = 0; + dwrite(_XMCRA, __XMCRA); + + XMCRB_reg_t __XMCRB; + __XMCRB._XMM = 0; + __XMCRB.reserved1 = 0; + __XMCRB._XMBK = false; + dwrite(_XMCRB, __XMCRB); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + SMCR_reg_t __SMCR; + __SMCR._SE = false; + __SMCR._SM = 0; + __SMCR.reserved1 = 0; + dwrite(_SMCR, __SMCR); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + PRR0_reg_t __PRR0; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM03__) + __PRR0._PRADC = false; + __PRR0._PRUSART0 = false; + __PRR0._PRSPI = false; + __PRR0._PRTIM1 = false; + __PRR0.reserved1 = false; + __PRR0._PRTIM0 = false; + __PRR0._PRTIM2 = false; + __PRR0._PRTWI = false; + #elif defined(__AVR_TRM02__) + __PRR0._PRADC = false; + __PRR0._PRUSART0 = false; + __PRR0._PRSPI = false; + __PRR0._PRTIM1 = false; + __PRR0._PRUSART1 = false; + __PRR0._PRTIM0 = false; + __PRR0._PRTIM2 = false; + __PRR0._PRTWI = false; + #elif defined(__AVR_TRM04__) + __PRR0._PRADC = false; + __PRR0.reserved1 = false; + __PRR0._PRSPI = false; + __PRR0._PRTIM1 = false; + __PRR0.reserved2 = false; + __PRR0._PRTIM0 = false; + __PRR0._PRTIM2 = false; + __PRR0._PRTWI = false; + #endif + dwrite(_PRR0, __PRR0); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) + PRR1_reg_t __PRR1; + #ifdef __AVR_TRM01__ + __PRR1._PRUSART1 = false; + __PRR1._PRUSART2 = false; + __PRR1._PRUSART3 = false; + __PRR1._PRTIM3 = false; + __PRR1._PRTIM4 = false; + __PRR1._PRTIM5 = false; + __PRR1.reserved1 = 0; + #elif defined(__AVR_TRM02__) + __PRR1._PRTIM3 = false; + __PRR1.reserved1 = 0; + #elif defined(__AVR_TRM04__) + __PRR1._PRUSART1 = false; + __PRR1.reserved1 = 0; + #endif + dwrite(_PRR1, __PRR1); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + WDTCSR_reg_t __WDTCSR; + __WDTCSR._WDP0 = 0; + __WDTCSR._WDP1 = 0; + __WDTCSR._WDP2 = 0; + __WDTCSR._WDE = false; + __WDTCSR._WDCE = false; + __WDTCSR._WDP3 = 0; + __WDTCSR._WDIE = false; + __WDTCSR._WDIF = false; + dwrite(_WDTCSR, __WDTCSR); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + _MCUCR._PUD = false; + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + PORT_dev_t __PORT; + __PORT._PIN.val = 0; + __PORT._DDR.val = 0; + __PORT._PORT.val = 0; + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + dwrite(_PORTA, __PORT); + dwrite(_PORTC, __PORT); + #endif + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + dwrite(_PORTB, __PORT); + dwrite(_PORTD, __PORT); + #endif + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + dwrite(_PORTE, __PORT); + dwrite(_PORTF, __PORT); + #endif + + #ifdef __AVR_TRM01__ + PORTG_dev_t __PORTG; + __PORTG._PIN.val = 0; + __PORTG._PIN.reserved1 = 0; + __PORTG._DDR.val = 0; + __PORTG._DDR.reserved1 = 0; + __PORTG._PORT.val = 0; + __PORTG._PORT.reserved1 = 0; + dwrite(_PORTG, __PORTG); + #endif + + #ifdef __AVR_TRM03__ + PORTC_dev_t __PORTC; + __PORTC._PIN.val = 0; + __PORTC._PIN.reserved1 = 0; + __PORTC._DDR.val = 0; + __PORTC._DDR.reserved1 = 0; + __PORTC._PORT.val = 0; + __PORTC._PORT.reserved1 = 0; + dwrite(_PORTC, __PORTC); + #endif + + #ifdef __AVR_TRM01__ + dwrite(_PORTH, __PORT); + dwrite(_PORTJ, __PORT); + dwrite(_PORTK, __PORT); + dwrite(_PORTL, __PORT); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + EICRA_reg_t __EICRA; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + __EICRA._ISC0 = 0; + __EICRA._ISC1 = 0; + __EICRA._ISC2 = 0; + __EICRA._ISC3 = 0; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + __EICRA._ISC0 = 0; + __EICRA._ISC1 = 0; + __EICRA._ISC2 = 0; + __EICRA.reserved1 = 0; + #elif defined(__AVR_TRM03__) + __EICRA._ISC0 = 0; + __EICRA._ISC1 = 0; + __EICRA.reserved1 = 0; + #endif + dwrite(_EICRA, __EICRA); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + EICRB_reg_t __EICRB; + __EICRB._ISC4 = 0; + __EICRB._ISC5 = 0; + __EICRB._ISC6 = 0; + __EICRB._ISC7 = 0; + dwrite(_EICRB, __EICRB); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + EIMSK_reg_t __EIMSK; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + __EIMSK._INT0 = false; + __EIMSK._INT1 = false; + __EIMSK._INT2 = false; + __EIMSK._INT3 = false; + __EIMSK._INT4 = false; + __EIMSK._INT5 = false; + __EIMSK._INT6 = false; + __EIMSK._INT7 = false; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + __EIMSK._INT0 = false; + __EIMSK._INT1 = false; + __EIMSK._INT2 = false; + __EIMSK.reserved1 = 0; + #elif defined(__AVR_TRM03__) + __EIMSK._INT0 = false; + __EIMSK._INT1 = false; + __EIMSK.reserved1 = 0; + #endif + dwrite(_EIMSK, __EIMSK); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + EIFR_reg_t __EIFR; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + __EIFR._INTF0 = false; + __EIFR._INTF1 = false; + __EIFR._INTF2 = false; + __EIFR._INTF3 = false; + __EIFR._INTF4 = false; + __EIFR._INTF5 = false; + __EIFR._INTF6 = false; + __EIFR._INTF7 = false; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + __EIFR._INTF0 = false; + __EIFR._INTF1 = false; + __EIFR._INTF2 = false; + __EIFR.reserved1 = 0; + #elif defined(__AVR_TRM03__) + __EIFR._INTF0 = false; + __EIFR._INTF1 = false; + __EIFR.reserved1 = 0; + #endif + dwrite(_EIFR, __EIFR); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + PCICR_reg_t __PCICR; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM03__) + __PCICR._PCIE0 = false; + __PCICR._PCIE1 = false; + __PCICR._PCIE2 = false; + __PCICR.reserved1 = 0; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + __PCICR._PCIE0 = false; + __PCICR._PCIE1 = false; + __PCICR._PCIE2 = false; + __PCICR._PCIE3 = false; + __PCICR.reserved1 = 0; + #elif defined(__AVR_TRM04__) + __PCICR._PCIE0 = false; + __PCICR.reserved1 = 0; + #endif + dwrite(_PCICR, __PCICR); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + PCIFR_reg_t __PCIFR; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM03__) + __PCIFR._PCIF0 = false; + __PCIFR._PCIF1 = false; + __PCIFR._PCIF2 = false; + __PCIFR.reserved1 = 0; + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + __PCIFR._PCIF0 = false; + __PCIFR._PCIF1 = false; + __PCIFR._PCIF2 = false; + __PCIFR._PCIF3 = false; + __PCIFR.reserved1 = 0; + #elif defined(__AVR_TRM04__) + __PCIFR._PCIF0 = false; + __PCIFR.reserved1 = 0; + #endif + dwrite(_PCIFR, __PCIFR); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + _PCMSK0.val = 0; + #endif + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM05__) + _PCMSK1.val = 0; + _PCMSK2.val = 0; + #endif + #if defined(__AVR_TRM03__) + _PCMSK1.reserved1 = 0; + #endif + #if defined(__AVR_TRM02__) + _PCMSK3.val = 0; + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + TIMER_8bit_dev_t __TIMER_8bit; + __TIMER_8bit._TCCRnA._WGMn0 = 0; + __TIMER_8bit._TCCRnA._WGMn1 = 0; + __TIMER_8bit._TCCRnA.reserved1 = 0; + __TIMER_8bit._TCCRnA._COMnB = 0; + __TIMER_8bit._TCCRnA._COMnA = 0; + __TIMER_8bit._TCCRnB._CSn = 0; + __TIMER_8bit._TCCRnB._WGMn2 = 0; + __TIMER_8bit._TCCRnB.reserved1 = 0; + __TIMER_8bit._TCCRnB._FOCnB = false; + __TIMER_8bit._TCCRnB._FOCnA = false, + __TIMER_8bit._TCNTn = 0; + __TIMER_8bit._OCRnA = 0; + __TIMER_8bit._OCRnB = 0; + dwrite(TIMER0, __TIMER_8bit); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + TIMSK0_reg_t __TIMSK0; + __TIMSK0._TOIE0 = false; + __TIMSK0._OCIE0A = false; + __TIMSK0._OCIE0B = false; + __TIMSK0.reserved1 = 0; + dwrite(_TIMSK0, __TIMSK0); + + TIFR0_reg_t __TIFR0; + __TIFR0._TOV0 = false; + __TIFR0._OCF0A = false; + __TIFR0._OCF0B = false; + __TIFR0.reserved1 = 0; + dwrite(_TIFR0, __TIFR0); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + TIMER_dev_t TIMER; + TIMER._TCCRnA._WGMn0 = 0; + TIMER._TCCRnA._WGMn1 = 0; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + TIMER._TCCRnA._COMnC = 0; + #endif + TIMER._TCCRnA._COMnB = 0; + TIMER._TCCRnA._COMnA = 0; + TIMER._TCCRnB._CSn = 0; + TIMER._TCCRnB._WGMn2 = 0; + TIMER._TCCRnB.reserved1 = 0; + TIMER._TCCRnB._ICESn = 0; + TIMER._TCCRnB._ICNCn = 0; + TIMER._TCCRnC.reserved1 = 0; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + TIMER._TCCRnC._FOCnC = false; + #endif + TIMER._TCCRnC._FOCnB = false; + TIMER._TCCRnC._FOCnA = false; + TIMER._TCNTn = 0; + TIMER._OCRnA = 0; + TIMER._OCRnB = 0; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + TIMER._OCRnC = 0; + #endif + TIMER._ICRn = 0; + dwrite(TIMER1, TIMER); + #endif + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) + dwrite(TIMER3, TIMER); + #endif + #ifdef __AVR_TRM01__ + dwrite(TIMER4, TIMER); + dwrite(TIMER5, TIMER); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + TIMSK1_reg_t __TIMSK1; + __TIMSK1._TOIE1 = false; + __TIMSK1._OCIE1A = false; + __TIMSK1._OCIE1B = false; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + __TIMSK1._OCIE1C = false; + #endif + __TIMSK1.reserved1 = 0; + __TIMSK1._ICIE1 = false; + __TIMSK1.reserved2 = 0; + dwrite(_TIMSK1, __TIMSK1); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) + TIMSK3_reg_t __TIMSK3; + __TIMSK3._TOIE3 = false; + __TIMSK3._OCIE3A = false; + __TIMSK3._OCIE3B = false; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + __TIMSK3._OCIE3C = false; + #endif + __TIMSK3.reserved1 = 0; + __TIMSK3._ICIE3 = false; + __TIMSK3.reserved2 = 0; + dwrite(_TIMSK3, __TIMSK3); + #endif + + #ifdef __AVR_TRM01__ + TIMSK4_reg_t __TIMSK4; + __TIMSK4._TOIE4 = false; + __TIMSK4._OCIE4A = false; + __TIMSK4._OCIE4B = false; + __TIMSK4._OCIE4C = false; + __TIMSK4.reserved1 = false; + __TIMSK4._ICIE4 = false; + __TIMSK4.reserved2 = false; + dwrite(_TIMSK4, __TIMSK4); + + TIMSK5_reg_t __TIMSK5; + __TIMSK5._TOIE5 = false; + __TIMSK5._OCIE5A = false; + __TIMSK5._OCIE5B = false; + __TIMSK5._OCIE5C = false; + __TIMSK5.reserved1 = 0; + __TIMSK5._ICIE5 = false; + __TIMSK5.reserved2 = 0; + dwrite(_TIMSK5, __TIMSK5); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + TIFR1_reg_t __TIFR1; + __TIFR1._TOV1 = false; + __TIFR1._OCF1A = false; + __TIFR1._OCF1B = false; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + __TIFR1._OCF1C = false; + #endif + __TIFR1.reserved1 = 0; + __TIFR1._ICF1 = false; + __TIFR1.reserved2 = 0; + dwrite(_TIFR1, __TIFR1); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) + TIFR3_reg_t __TIFR3; + __TIFR3._TOV3 = false; + __TIFR3._OCF3A = false; + __TIFR3._OCF3B = false; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + __TIFR3._OCF3C = false; + #endif + __TIFR3.reserved1 = 0; + __TIFR3._ICF3 = false; + __TIFR3.reserved2 = 0; + dwrite(_TIFR3, __TIFR3); + #endif + + #ifdef __AVR_TRM01__ + TIFR4_reg_t __TIFR4; + __TIFR4._TOV4 = false; + __TIFR4._OCF4A = false; + __TIFR4._OCF4B = false; + __TIFR4._OCF4C = false; + __TIFR4.reserved1 = 0; + __TIFR4._ICF4 = false; + __TIFR4.reserved2 = 0; + dwrite(_TIFR4, __TIFR4); + + TIFR5_reg_t __TIFR5; + __TIFR5._TOV5 = false; + __TIFR5._OCF5A = false; + __TIFR5._OCF5B = false; + __TIFR5._OCF5C = false; + __TIFR5.reserved1 = 0; + __TIFR5._ICF5 = false; + __TIFR5.reserved2 = 0; + dwrite(_TIFR5, __TIFR5); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + dwrite(_TIMER2, __TIMER_8bit); + #endif + + #if defined(__AV_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + ASSR_reg_t __ASSR; + __ASSR._TCR2BUB = false; + __ASSR._TCR2AUB = false; + __ASSR._OCR2BUB = false; + __ASSR._OCR2AUB = false; + __ASSR._TCN2UB = false; + __ASSR._AS2 = false; + __ASSR._EXCLK = false; + __ASSR.reserved1 = 0; + dwrite(_ASSR, __ASSR); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + TIMSK2_reg_t __TIMSK2; + __TIMSK2._TOIE2 = false; + __TIMSK2._OCIE2A = false; + __TIMSK2._OCIE2B = false; + __TIMSK2.reserved1 = 0; + dwrite(_TIMSK2, __TIMSK2); + + TIFR2_reg_t __TIFR2; + __TIFR2._TOV2 = false; + __TIFR2._OCF2A = false; + __TIFR2._OCF2B = false; + __TIFR2.reserved1 = 0; + dwrite(_TIFR2, __TIFR2); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + SPCR_reg_t __SPCR; + __SPCR._SPR = 0; + __SPCR._CPHA = 0; + __SPCR._CPOL = 0; + __SPCR._MSTR = 0; + __SPCR._DORD = 0; + __SPCR._SPE = false; + __SPCR._SPIE = false; + dwrite(_SPCR, __SPCR); + + SPSR_reg_t __SPSR; + __SPSR._SPI2X = false; + __SPSR.reserved1 = 0; + __SPSR._WCOL = false; + __SPSR._SPIF = false; + dwrite(_SPSR, __SPSR); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + USART_dev_t USART; + USART._UDRn = 0; + USART._UCSRnA._MPCM = false; + USART._UCSRnA._U2X = false; + USART._UCSRnA._UPE = false; + USART._UCSRnA._DOR = false; + USART._UCSRnA._FE = false; + USART._UCSRnA._UDRE = true; + USART._UCSRnA._TXC = false; + USART._UCSRnA._RXC = false; + USART._UCSRnB._TXB8 = false; + USART._UCSRnB._RXB8 = false; + USART._UCSRnB._UCSZn2 = false; + USART._UCSRnB._TXEN = false; + USART._UCSRnB._RXEN = false; + USART._UCSRnB._UDRIE = false; + USART._UCSRnB._TXCIE = false; + USART._UCSRnB._RXCIE = false; + USART._UCSRnC._UCPOL = false; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) + USART._UCSRnC._UCSZn0 = 1; + USART._UCSRnC._UCSZn1 = 1; + USART._UCSRnC._USBS = false; + USART._UCSRnC._UPM = 0; + USART._UCSRnC._UPM = 0; + USART._UCSRnC._UMSEL = 0; + #elif defined(__AVR_TRM05__) + USART._UCSRnC._UCPOL = 0; + USART._UCSRnC._UCPHA = 0; + USART._UCSRnC._UDORD = 0; + USART._UCSRnC.reserved1 = 0; + USART._UCSRnC._UMSEL = 0; + #endif + USART._UBRRn._UBRR = 0; + USART._UBRRn.reserved1 = 0; + #endif + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM05__) + dwrite(USART0, USART); + #endif + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + dwrite(USART1, USART); + #endif + #ifdef __AVR_TRM01__ + dwrite(USART2, USART); + dwrite(USART3, USART); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + dwrite(_TWBR, (uint8_t)0); + + TWCR_reg_t __TWCR; + __TWCR._TWIE = false; + __TWCR.reserved1 = 0; + __TWCR._TWEN = false; + __TWCR._TWWC = false; + __TWCR._TWSTO = false; + __TWCR._TWSTA = false; + __TWCR._TWEA = false; + __TWCR._TWINT = false; + dwrite(_TWCR, __TWCR); + + TWSR_reg_t __TWSR; + __TWSR._TWPS0 = false; + __TWSR._TWPS1 = false; + __TWSR.reserved1 = 0; + __TWSR._TWS3 = 1; + __TWSR._TWS4 = 1; + __TWSR._TWS5 = 1; + __TWSR._TWS6 = 1; + __TWSR._TWS7 = 1; + dwrite(_TWSR, __TWSR); + + dwrite(_TWDR, (uint8_t)0xFF); + + TWAR_reg_t __TWAR; + __TWAR._TWGCE = false; + __TWAR._TWA = 0x7F; + dwrite(_TWAR, __TWAR); + + TWAMR_reg_t __TWAMR; + __TWAMR.reserved1 = false; + __TWAMR._TWAM = 0; + dwrite(_TWAMR, __TWAMR); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + ADCSRB_reg_t __ADCSRB; + __ADCSRB._ADTS = 0; + #ifdef __AVR_TRM01__ + __ADCSRB._MUX5 = 0; + #endif + __ADCSRB.reserved1 = 0; + __ADCSRB._ACME = false; + __ADCSRB.reserved2 = 0; + dwrite(_ADCSRB, __ADCSRB); + + ACSR_reg_t __ACSR; + __ACSR._ACIS = 0; + __ACSR._ACIC = false; + __ACSR._ACIE = false; + __ACSR._ACI = false; + __ACSR._ACO = false; + __ACSR._ACBG = false; + __ACSR._ACD = false; + dwrite(_ACSR, __ACSR); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + DIDR1_reg_t __DIDR1; + __DIDR1._AIN0D = false; + __DIDR1._AIN1D = false; + __DIDR1.reserved1 = false; + dwrite(_DIDR1, __DIDR1); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + ADMUX_reg_t __ADMUX; + __ADMUX._MUX0 = 0; + __ADMUX._MUX1 = 0; + __ADMUX._MUX2 = 0; + __ADMUX._MUX3 = 0; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + __ADMUX._MUX4 = 0; + #elif defined(__AVR_TRM03__) + __ADMUX.reserved1 = 0; + #endif + __ADMUX._ADLAR = 0; + __ADMUX._REFS0 = 0; + __ADMUX._REFS1 = 0; + dwrite(_ADMUX, __ADMUX); + + ADCSRA_reg_t __ADCSRA; + __ADCSRA._ADPS = 0; + __ADCSRA._ADIE = false; + __ADCSRA._ADIF = false; + __ADCSRA._ADATE = false; + __ADCSRA._ADSC = false; + __ADCSRA._ADEN = false; + dwrite(_ADCSRA, __ADCSRA); + + dwrite(_ADC, (uint16_t)0); + #endif + + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + SPMCSR_reg_t __SPMCSR; + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + __SPMCSR._SPMEN = false; + __SPMCSR._PGERS = false; + __SPMCSR._PGWRT = false; + __SPMCSR._BLBSET = false; + __SPMCSR._RWWSRE = false; + __SPMCSR._SIGRD = false; + __SPMCSR._RWWSB = false; + __SPMCSR._SPMIE = false; + #elif defined(__AVR_TRM03__) + #if defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88PA__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega328P__) + __SPMCSR._SPMEN = false; + __SPMCSR._PGERS = false; + __SPMCSR._PGWRT = false; + __SPMCSR._BLBSET = false; + __SPMCSR._RWWSRE = false; + __SPMCSR._SIGRD = false; + __SPMCSR._RWWSB = false; + __SPMCSR._SPMIE = false; + #else + __SPMCSR._SPMEN = false; + __SPMCSR._PGERS = false; + __SPMCSR._PGWRT = false; + __SPMCSR._BLBSET = false; + __SPMCSR.reserved1 = false; + __SPMCSR._SIGRD = false; + __SPMCSR.reserved2 = false; + __SPMCSR._SPMIE = false; + #endif + #endif + dwrite(_SPMCSR, __SPMCSR); + #endif + + // TODO: add the __AVR_TRM04__ initializations, if required (mostly USB related) +} + +struct pin_dev_state_t { + #ifdef __AVR_TRM01__ + uint8_t _SRE : 1; // port A + uint8_t _COM0B : 2; + uint8_t _COM1A : 2; + uint8_t _COM1B : 2; + uint8_t _COM1C : 2; + uint8_t _COM2A : 2; + uint8_t _COM2B : 2; + uint8_t _COM3A : 2; + uint8_t _COM3B : 2; + uint8_t _COM3C : 2; + uint8_t _COM4A : 2; + uint8_t _COM4B : 2; + uint8_t _COM4C : 2; + uint8_t _COM5A : 2; + uint8_t _COM5B : 2; + uint8_t _COM5C : 2; + uint8_t _PCIE0 : 1; + uint8_t _PCIE1 : 1; // INTn + uint8_t _PCIE2 : 1; + uint8_t _SPE : 1; + uint8_t _USART0_RXEN : 1; + uint8_t _USART0_TXEN : 1; + uint8_t _USART1_RXEN : 1; + uint8_t _USART1_TXEN : 1; + uint8_t _USART2_RXEN : 1; + uint8_t _USART2_TXEN : 1; + uint8_t _USART3_RXEN : 1; + uint8_t _USART3_TXEN : 1; + //uint8_t _JTAGEN : 1; + uint8_t _AS2 : 1; + #elif defined(__AVR_TRM02__) + uint8_t _PCIE0 : 1; + uint8_t _PCIE1 : 1; + uint8_t _PCIE2 : 1; + uint8_t _PCIE3 : 1; + uint8_t _ADC7D : 1; + uint8_t _ADC6D : 1; + uint8_t _ADC5D : 1; + uint8_t _ADC4D : 1; + uint8_t _ADC3D : 1; + uint8_t _ADC2D : 1; + uint8_t _ADC1D : 1; + uint8_t _ADC0D : 1; + uint8_t _SPE : 1; + uint8_t _COM0A : 2; + uint8_t _COM0B : 2; + uint8_t _COM2A : 2; + uint8_t _COM2B : 2; + uint8_t _COM1A : 2; + uint8_t _COM1B : 2; + //uint8_t _JTAGEN : 1; + uint8_t _AS2 : 1; + uint8_t _TWEN : 1; + uint8_t _USART1_TXEN : 1; + uint8_t _USART1_RXEN : 1; + uint8_t _USART0_TXEN : 1; + uint8_t _USART0_RXEN : 1; + #elif defined(__AVR_TRM03__) + uint8_t _AS2 : 1; + uint8_t _PCIE0 : 1; + uint8_t _PCIE1 : 1; + uint8_t _PCIE2 : 1; + uint8_t _SPE : 1; + uint8_t _COM2B : 2; + uint8_t _COM2A : 2; + uint8_t _COM1B : 2; + uint8_t _COM1A : 2; + uint8_t _COM0A : 2; + uint8_t _COM0B : 2; + uint8_t _TWEN : 1; + uint8_t _ADC7D : 1; + uint8_t _ADC6D : 1; + uint8_t _ADC5D : 1; + uint8_t _ADC4D : 1; + uint8_t _ADC3D : 1; + uint8_t _ADC2D : 1; + uint8_t _ADC1D : 1; + uint8_t _ADC0D : 1; + uint8_t _UMSEL : 2; + uint8_t _USART0_TXEN : 1; + uint8_t _USART0_RXEN : 1; + #elif defined(__AVR_TRM04__) + uint8_t _SRE : 1; + uint8_t _SPE : 1; + uint8_t _COM0B : 2; + uint8_t _COM1C : 2; + uint8_t _COM1B : 2; + uint8_t _COM1A : 2; + uint8_t _COM2A : 2; + uint8_t _COM2B : 2; + uint8_t _PCIE0 : 1; + uint8_t _USART1_RXEN : 1; + uint8_t _USART1_TXEN : 1; + uint8_t _TWEN : 1; + uint8_t _INT7 : 1; + uint8_t _INT6 : 1; + uint8_t _INT5 : 1; + uint8_t _INT4 : 1; + uint8_t _INT3 : 1; + uint8_t _INT2 : 1; + uint8_t _INT1 : 1; + uint8_t _INT0; + uint8_t _UVCONE : 1; + uint8_t _UIDE : 1; + //uint8_t _JTAGEN : 1; + #elif defined(__AVR_TRM05__) + uint8_t _ADC7D : 1; + uint8_t _ADC6D : 1; + uint8_t _ADC5D : 1; + uint8_t _ADC4D : 1; + uint8_t _ADC3D : 1; + uint8_t _ADC2D : 1; + uint8_t _ADC1D : 1; + uint8_t _ADC0D : 1; + uint8_t _PCIE0 : 1; + uint8_t _PCIE1 : 1; + uint8_t _PCIE2 : 1; + uint8_t _PCIE3 : 1; + uint8_t _SPE : 1; + uint8_t _COM0A : 2; + uint8_t _COM0B : 2; + uint8_t _COM2A : 2; + uint8_t _COM2B : 2; + uint8_t _COM1A : 2; + uint8_t _COM1B : 2; + uint8_t _AS2 : 1; + uint8_t _TWEN : 1; + uint8_t _TXEN1 : 1; + uint8_t _RXEN1 : 1; + uint8_t _TXEN0 : 1; + uint8_t _RXEN0 : 1; + uint8_t _INT2 : 1; + uint8_t _INT1 : 1; + uint8_t _INT0 : 1; + //uint8_t _JTAGEN : 1; + #endif +}; + +// AVR ArduinoCore is written like a hack-job (random peripherals enabled all-the-time). + +enum class eATmegaPort { + #ifdef __AVR_TRM01__ + PORT_A, PORT_B, PORT_C, PORT_D, PORT_E, PORT_F, PORT_G, PORT_H, PORT_J, PORT_K, PORT_L + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + PORT_A, PORT_B, PORT_C, PORT_D + #elif defined(__AVR_TRM03__) + PORT_B, PORT_C, PORT_D + #elif defined(__AVR_TRM04__) + PORT_A, PORT_B, PORT_C, PORT_D, PORT_E, PORT_F + #endif +}; + +struct ATmegaPinInfo { + eATmegaPort port; + uint8_t pinidx; +}; + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + #define _SPA_DIO_DDRA (eATmegaPort::PORT_A) +#endif +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM03__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + #define _SPA_DIO_DDRB (eATmegaPort::PORT_B) + #define _SPA_DIO_DDRC (eATmegaPort::PORT_C) + #define _SPA_DIO_DDRD (eATmegaPort::PORT_D) +#endif +#if defined(__AVR_TRM01__) || defined(__AVR_TRM04__) + #define _SPA_DIO_DDRE (eATmegaPort::PORT_E) + #define _SPA_DIO_DDRF (eATmegaPort::PORT_F) +#endif +#ifdef __AVR_TRM01__ + #define _SPA_DIO_DDRG (eATmegaPort::PORT_G) + #define _SPA_DIO_DDRH (eATmegaPort::PORT_H) + #define _SPA_DIO_DDRJ (eATmegaPort::PORT_J) + #define _SPA_DIO_DDRK (eATmegaPort::PORT_K) + #define _SPA_DIO_DDRL (eATmegaPort::PORT_L) +#endif + +#define __SPA_IFPORT_STMT(dr) if (ddrp == &D##dr) port = _SPA_DIO_D##dr; + +#ifdef _SPA_DIO_DDRA + #define _SPA_IFPORT_PORTA __SPA_IFPORT_STMT(DRA) +#else + #define _SPA_IFPORT_PORTA +#endif +#ifdef _SPA_DIO_DDRB + #define _SPA_IFPORT_PORTB __SPA_IFPORT_STMT(DRB) +#else + #define _SPA_IFPORT_PORTB +#endif +#ifdef _SPA_DIO_DDRC + #define _SPA_IFPORT_PORTC __SPA_IFPORT_STMT(DRC) +#else + #define _SPA_IFPORT_PORTC +#endif +#ifdef _SPA_DIO_DDRD + #define _SPA_IFPORT_PORTD __SPA_IFPORT_STMT(DRD) +#else + #define _SPA_IFPORT_PORTD +#endif +#ifdef _SPA_DIO_DDRE + #define _SPA_IFPORT_PORTE __SPA_IFPORT_STMT(DRE) +#else + #define _SPA_IFPORT_PORTE +#endif +#ifdef _SPA_DIO_DDRF + #define _SPA_IFPORT_PORTF __SPA_IFPORT_STMT(DRF) +#else + #define _SPA_IFPORT_PORTF +#endif +#ifdef _SPA_DIO_DDRG + #define _SPA_IFPORT_PORTG __SPA_IFPORT_STMT(DRG) +#else + #define _SPA_IFPORT_PORTG +#endif +#ifdef _SPA_DIO_DDRH + #define _SPA_IFPORT_PORTH __SPA_IFPORT_STMT(DRH) +#else + #define _SPA_IFPORT_PORTH +#endif +#ifdef _SPA_DIO_DDRJ + #define _SPA_IFPORT_PORTJ __SPA_IFPORT_STMT(DRJ) +#else + #define _SPA_IFPORT_PORTJ +#endif +#ifdef _SPA_DIO_DDRK + #define _SPA_IFPORT_PORTK __SPA_IFPORT_STMT(DRK) +#else + #define _SPA_IFPORT_PORTK +#endif +#ifdef _SPA_DIO_DDRL + #define _SPA_IFPORT_PORTL __SPA_IFPORT_STMT(DRL) +#else + #define _SPA_IFPORT_PORTL +#endif + +#define _SPA_RESOLVE_DIO(ddr) _SPA_DIO_##ddr +#define _SPA_DIOn_PORTRET(val, n) if (val == n) { \ + auto *ddrp = &DIO##n##_DDR; \ + eATmegaPort port; \ + _SPA_IFPORT_PORTA \ + _SPA_IFPORT_PORTB \ + _SPA_IFPORT_PORTC \ + _SPA_IFPORT_PORTD \ + _SPA_IFPORT_PORTE \ + _SPA_IFPORT_PORTF \ + _SPA_IFPORT_PORTG \ + _SPA_IFPORT_PORTH \ + _SPA_IFPORT_PORTJ \ + _SPA_IFPORT_PORTK \ + _SPA_IFPORT_PORTL \ + return { port, DIO##n##_PIN }; \ + } + +inline ATmegaPinInfo _ATmega_getPinInfo(uint8_t pin) { + #if DIO_NUM > 0 + _SPA_DIOn_PORTRET(pin, 0) + #endif + #if DIO_NUM > 1 + _SPA_DIOn_PORTRET(pin, 1) + #endif + #if DIO_NUM > 2 + _SPA_DIOn_PORTRET(pin, 2) + #endif + #if DIO_NUM > 3 + _SPA_DIOn_PORTRET(pin, 3) + #endif + #if DIO_NUM > 4 + _SPA_DIOn_PORTRET(pin, 4) + #endif + #if DIO_NUM > 5 + _SPA_DIOn_PORTRET(pin, 5) + #endif + #if DIO_NUM > 6 + _SPA_DIOn_PORTRET(pin, 6) + #endif + #if DIO_NUM > 7 + _SPA_DIOn_PORTRET(pin, 7) + #endif + #if DIO_NUM > 8 + _SPA_DIOn_PORTRET(pin, 8) + #endif + #if DIO_NUM > 9 + _SPA_DIOn_PORTRET(pin, 9) + #endif + + #if DIO_NUM > 10 + _SPA_DIOn_PORTRET(pin, 10) + #endif + #if DIO_NUM > 11 + _SPA_DIOn_PORTRET(pin, 11) + #endif + #if DIO_NUM > 12 + _SPA_DIOn_PORTRET(pin, 12) + #endif + #if DIO_NUM > 13 + _SPA_DIOn_PORTRET(pin, 13) + #endif + #if DIO_NUM > 14 + _SPA_DIOn_PORTRET(pin, 14) + #endif + #if DIO_NUM > 15 + _SPA_DIOn_PORTRET(pin, 15) + #endif + #if DIO_NUM > 16 + _SPA_DIOn_PORTRET(pin, 16) + #endif + #if DIO_NUM > 17 + _SPA_DIOn_PORTRET(pin, 17) + #endif + #if DIO_NUM > 18 + _SPA_DIOn_PORTRET(pin, 18) + #endif + #if DIO_NUM > 19 + _SPA_DIOn_PORTRET(pin, 19) + #endif + + #if DIO_NUM > 20 + _SPA_DIOn_PORTRET(pin, 20) + #endif + #if DIO_NUM > 21 + _SPA_DIOn_PORTRET(pin, 21) + #endif + #if DIO_NUM > 22 + _SPA_DIOn_PORTRET(pin, 22) + #endif + #if DIO_NUM > 23 + _SPA_DIOn_PORTRET(pin, 23) + #endif + #if DIO_NUM > 24 + _SPA_DIOn_PORTRET(pin, 24) + #endif + #if DIO_NUM > 25 + _SPA_DIOn_PORTRET(pin, 25) + #endif + #if DIO_NUM > 26 + _SPA_DIOn_PORTRET(pin, 26) + #endif + #if DIO_NUM > 27 + _SPA_DIOn_PORTRET(pin, 27) + #endif + #if DIO_NUM > 28 + _SPA_DIOn_PORTRET(pin, 28) + #endif + #if DIO_NUM > 29 + _SPA_DIOn_PORTRET(pin, 29) + #endif + + #if DIO_NUM > 30 + _SPA_DIOn_PORTRET(pin, 30) + #endif + #if DIO_NUM > 31 + _SPA_DIOn_PORTRET(pin, 31) + #endif + #if DIO_NUM > 32 + _SPA_DIOn_PORTRET(pin, 32) + #endif + #if DIO_NUM > 33 + _SPA_DIOn_PORTRET(pin, 33) + #endif + #if DIO_NUM > 34 + _SPA_DIOn_PORTRET(pin, 34) + #endif + #if DIO_NUM > 35 + _SPA_DIOn_PORTRET(pin, 35) + #endif + #if DIO_NUM > 36 + _SPA_DIOn_PORTRET(pin, 36) + #endif + #if DIO_NUM > 37 + _SPA_DIOn_PORTRET(pin, 37) + #endif + #if DIO_NUM > 38 + _SPA_DIOn_PORTRET(pin, 38) + #endif + #if DIO_NUM > 39 + _SPA_DIOn_PORTRET(pin, 39) + #endif + + #if DIO_NUM > 40 + _SPA_DIOn_PORTRET(pin, 40) + #endif + #if DIO_NUM > 41 + _SPA_DIOn_PORTRET(pin, 41) + #endif + #if DIO_NUM > 42 + _SPA_DIOn_PORTRET(pin, 42) + #endif + #if DIO_NUM > 43 + _SPA_DIOn_PORTRET(pin, 43) + #endif + #if DIO_NUM > 44 + _SPA_DIOn_PORTRET(pin, 44) + #endif + #if DIO_NUM > 45 + _SPA_DIOn_PORTRET(pin, 45) + #endif + #if DIO_NUM > 46 + _SPA_DIOn_PORTRET(pin, 46) + #endif + #if DIO_NUM > 47 + _SPA_DIOn_PORTRET(pin, 47) + #endif + #if DIO_NUM > 48 + _SPA_DIOn_PORTRET(pin, 48) + #endif + #if DIO_NUM > 49 + _SPA_DIOn_PORTRET(pin, 49) + #endif + + #if DIO_NUM > 50 + _SPA_DIOn_PORTRET(pin, 50) + #endif + #if DIO_NUM > 51 + _SPA_DIOn_PORTRET(pin, 51) + #endif + #if DIO_NUM > 52 + _SPA_DIOn_PORTRET(pin, 52) + #endif + #if DIO_NUM > 53 + _SPA_DIOn_PORTRET(pin, 53) + #endif + #if DIO_NUM > 54 + _SPA_DIOn_PORTRET(pin, 54) + #endif + #if DIO_NUM > 55 + _SPA_DIOn_PORTRET(pin, 55) + #endif + #if DIO_NUM > 56 + _SPA_DIOn_PORTRET(pin, 56) + #endif + #if DIO_NUM > 57 + _SPA_DIOn_PORTRET(pin, 57) + #endif + #if DIO_NUM > 58 + _SPA_DIOn_PORTRET(pin, 58) + #endif + #if DIO_NUM > 59 + _SPA_DIOn_PORTRET(pin, 59) + #endif + + #if DIO_NUM > 60 + _SPA_DIOn_PORTRET(pin, 60) + #endif + #if DIO_NUM > 61 + _SPA_DIOn_PORTRET(pin, 61) + #endif + #if DIO_NUM > 62 + _SPA_DIOn_PORTRET(pin, 62) + #endif + #if DIO_NUM > 63 + _SPA_DIOn_PORTRET(pin, 63) + #endif + #if DIO_NUM > 64 + _SPA_DIOn_PORTRET(pin, 64) + #endif + #if DIO_NUM > 65 + _SPA_DIOn_PORTRET(pin, 65) + #endif + #if DIO_NUM > 66 + _SPA_DIOn_PORTRET(pin, 66) + #endif + #if DIO_NUM > 67 + _SPA_DIOn_PORTRET(pin, 67) + #endif + #if DIO_NUM > 68 + _SPA_DIOn_PORTRET(pin, 68) + #endif + #if DIO_NUM > 69 + _SPA_DIOn_PORTRET(pin, 69) + #endif + + #if DIO_NUM > 70 + _SPA_DIOn_PORTRET(pin, 70) + #endif + #if DIO_NUM > 71 + _SPA_DIOn_PORTRET(pin, 71) + #endif + #if DIO_NUM > 72 + _SPA_DIOn_PORTRET(pin, 72) + #endif + #if DIO_NUM > 73 + _SPA_DIOn_PORTRET(pin, 73) + #endif + #if DIO_NUM > 74 + _SPA_DIOn_PORTRET(pin, 74) + #endif + #if DIO_NUM > 75 + _SPA_DIOn_PORTRET(pin, 75) + #endif + #if DIO_NUM > 76 + _SPA_DIOn_PORTRET(pin, 76) + #endif + #if DIO_NUM > 77 + _SPA_DIOn_PORTRET(pin, 77) + #endif + #if DIO_NUM > 78 + _SPA_DIOn_PORTRET(pin, 78) + #endif + #if DIO_NUM > 79 + _SPA_DIOn_PORTRET(pin, 79) + #endif + + #if DIO_NUM > 80 + _SPA_DIOn_PORTRET(pin, 80) + #endif + #if DIO_NUM > 81 + _SPA_DIOn_PORTRET(pin, 81) + #endif + #if DIO_NUM > 82 + _SPA_DIOn_PORTRET(pin, 82) + #endif + #if DIO_NUM > 83 + _SPA_DIOn_PORTRET(pin, 83) + #endif + #if DIO_NUM > 84 + _SPA_DIOn_PORTRET(pin, 84) + #endif + #if DIO_NUM > 85 + _SPA_DIOn_PORTRET(pin, 85) + #endif + #if DIO_NUM > 86 + _SPA_DIOn_PORTRET(pin, 86) + #endif + #if DIO_NUM > 87 + _SPA_DIOn_PORTRET(pin, 87) + #endif + #if DIO_NUM > 88 + _SPA_DIOn_PORTRET(pin, 88) + #endif + #if DIO_NUM > 89 + _SPA_DIOn_PORTRET(pin, 89) + #endif + + // Default. + #if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) || defined(__AVR_TRM04__) || defined(__AVR_TRM05__) + return { eATmegaPort::PORT_A, 0 }; + #elif defined(__AVR_TRM03__) + return { eATmegaPort::PORT_B, 0 }; + #endif +} + +enum class eATmegaPeripheral { + UNDEFINED, + #ifdef __AVR_TRM01__ + PADC, PUSART0, PSPI, PTIM1, PTIM0, PTIM2, PTWI, PUSART1, PUSART2, PUSART3, PTIM3, PTIM4, PTIM5 + #elif defined(__AVR_TRM02__) + PADC, PUSART0, PSPI, PTIM1, PUSART1, PTIM0, PTIM2, PTWI, PTIM3 + #elif defined(__AVR_TRM03__) + PADC, PUSART0, PSPI, PTIM1, PTIM0, PTIM2, PTWI + #elif defined(__AVR_TRM04__) + PADC, PSPI, PTIM1, PTIM0, PTIM2, PTWI, PUSART1, PTIM3, PUSB + #elif defined(__AVR_TRM05__) + PADC, PUSART0, PSPI, PTIM1, PUSART1, PTIM0, PTIM2, PTWI + #endif + , NUM_PERIPHERALS +}; + +enum class eATmegaPinFunc : uint8_t { + #ifdef __AVR_TRM01__ + EXTMEM_AD15, EXTMEM_AD14, EXTMEM_AD13, EXTMEM_AD12, EXTMEM_AD11, EXTMEM_AD10, EXTMEM_AD9, EXTMEM_AD8, + EXTMEM_AD7, EXTMEM_AD6, EXTMEM_AD5, EXTMEM_AD4, EXTMEM_AD3, EXTMEM_AD2, EXTMEM_AD1, EXTMEM_AD0, + EXTMEM_ALE, EXTMEM_RD, EXTMEM_WR, + TOC0A, TOC0B, TOC1A, TOC1B, TOC1C, TOC2A, TOC2B, TOC3C, TOC3B, TOC3A, TOC4C, TOC4B, TOC4A, TOC5C, TOC5B, TOC5A, + EINT7, EINT6, EINT5, EINT4, EINT3, EINT2, EINT1, EINT0, + PCI0, PCI1, PCI2, PCI3, PCI4, PCI5, PCI6, PCI7, + PCI8, PCI9, PCI10, PCI11, PCI12, PCI13, PCI14, PCI15, + PCI16, PCI17, PCI18, PCI19, PCI20, PCI21, PCI22, PCI23, + SPI_MISO, SPI_MOSI, SPI_SCK, SPI_CS, + TOSC1, TOSC2, + TIMER0_CLKI, TIMER1_CLKI, TIMER3_CLKI, TIMER4_CLKI, TIMER5_CLKI, + TIMER1_ICP, TIMER3_ICP, TIMER5_ICP, TIMER4_ICP, + USART0_CLK, USART1_CLK, USART2_CLK, USART3_CLK, + USART0_TXD, USART0_RXD, USART1_TXD, USART1_RXD, USART2_TXD, USART2_RXD, USART3_TXD, USART3_RXD, + TWI_SDA, TWI_CLK, + CLKO, PDO, PDI, + AIN0, AIN1, + ADC15, ADC14, ADC13, ADC12, ADC11, ADC10, ADC9, ADC8, + ADC7, ADC6, ADC5, ADC4, ADC3, ADC2, ADC1, ADC0 + #elif defined(__AVR_TRM02__) + ADC7, ADC6, ADC5, ADC4, ADC3, ADC2, ADC1, ADC0, + SPI_SCK, SPI_MISO, SPI_MOSI, SPI_CS, + PCI31, PCI30, PCI29, PCI28, PCI27, PCI26, PCI25, PCI24, + PCI23, PCI22, PCI21, PCI20, PCI19, PCI18, PCI17, PCI16, + PCI15, PCI14, PCI13, PCI12, PCI11, PCI10, PCI9, PCI8, + PCI7, PCI6, PCI5, PCI4, PCI3, PCI2, PCI1, PCI0, + EINT2, EINT1, EINT0, + TIMER3_ICP, + TIMER3_ECI, TIMER1_ECI, TIMER0_ECI, + TIMER1_ICP, + TOC3B, TOC3A, TOC2A, TOC2B, TOC1A, TOC1B, TOC0B, TOC0A, + AIN1, AIN0, + USART0_CLK, USART1_CLK, + USART0_TXD, USART0_RXD, USART1_TXD, USART1_RXD, + CLKO, + TOSC2, TOSC1, + TWI_SDA, TWI_CLK + #elif defined(__AVR_TRM03__) + ADC5, ADC4, ADC3, ADC2, ADC1, ADC0, + XTAL2, XTAL1, + TOSC2, TOSC1, + SPI_SCK, SPI_MISO, SPI_MOSI, SPI_CS, + TOC2B, TOC2A, TOC1B, TOC1A, TOC0A, TOC0B, + TIMER1_ICP, + TIMER1_ECI, TIMER0_ECI, + TWI_CLK, TWI_SDA, + PCI23, PCI22, PCI21, PCI20, PCI19, PCI18, PCI17, PCI16, + PCI14, PCI13, PCI12, PCI11, PCI10, PCI9, PCI8, + PCI7, PCI6, PCI5, PCI4, PCI3, PCI2, PCI1, PCI0, + CLKO, + AIN1, AIN0, + USART_CLK, + USART_TXD, USART_RXD, + EINT1, EINT0 + #elif defined(__AVR_TRM04__) + EXTMEM_AD15, EXTMEM_AD14, EXTMEM_AD13, EXTMEM_AD12, EXTMEM_AD11, EXTMEM_AD10, EXTMEM_AD9, EXTMEM_AD8, + EXTMEM_AD7, EXTMEM_AD6, EXTMEM_AD5, EXTMEM_AD4, EXTMEM_AD3, EXTMEM_AD2, EXTMEM_AD1, EXTMEM_AD0, + EXTMEM_ALE, EXTMEM_RD, EXTMEM_WR, + TOC0B, TOC0A, TOC1C, TOC1B, TOC1A, TOC2B, TOC2A, TOC3A, TOC3B, TOC3C, + CLKO, PDO, PDI, + SPI_MISO, SPI_MOSI, SPI_SCK, SPI_CS, + TIMER3_ICP, TIMER1_ICP, + TIMER3_CLKI, TIMER0_CLKI, TIMER1_CLKI, + USART1_CLK, USART1_TXD, USART1_RXD, + EINT7, EINT6, EINT5, EINT4, EINT3, EINT2, EINT1, EINT0, + PCI7, PCI6, PCI5, PCI4, PCI3, PCI2, PCI1, PCI0, + TWI_SDA, TWI_CLK, + AIN1, AIN0, + TOSC2, + UID, UVCON, + ADC7, ADC6, ADC5, ADC4, ADC3, ADC2, ADC1, ADC0 + #elif defined(__AVR_TRM05__) + ADC7, ADC6, ADC5, ADC4, ADC3, ADC2, ADC1, ADC0, + PCI31, PCI30, PCI29, PCI28, PCI27, PCI26, PCI25, PCI24, + PCI23, PCI22, PCI21, PCI20, PCI19, PCI18, PCI17, PCI16, + PCI15, PCI14, PCI13, PCI12, PCI11, PCI10, PCI9, PCI8, + PCI7, PCI6, PCI5, PCI4, PCI3, PCI2, PCI1, PCI0, + SPI_SCK, SPI_MISO, SPI_MOSI, SPI_CS, + AIN1, AIN0, + TIMER1_ICP, TIMER0_ICP, + TIMER1_ECI, TIMER0_ECI, + TOC0B, TOC0A, TOC2A, TOC2B, TOC1A, TOC1B, + TOSC2, TOSC1, + //JTAG_TDI, JTAG_TDO, JTAG_TMS, JTAG_TCK, + TWI_CLK, TWI_SDA, + EINT2, EINT1, EINT0, + CLKO, + USART0_CLK, USART0_TXD, USART0_RXD, + USART1_CLK, USART1_TXD, USART1_RXD + #endif + , NUM_FUNCS +}; + +#ifndef countof + #define countof(x) (sizeof(x) / sizeof(*x)) +#endif + +struct ATmegaPinFunctions { + inline ATmegaPinFunctions(const eATmegaPinFunc *funcs, uint8_t cnt) noexcept : funcs(funcs), cnt(cnt) {} + inline ATmegaPinFunctions() = default; + inline ATmegaPinFunctions(const ATmegaPinFunctions&) = default; + + const eATmegaPinFunc *funcs = nullptr; + uint8_t cnt = 0; + + inline bool hasFunc(eATmegaPinFunc query) const { + for (uint8_t n = 0; n < this->cnt; n++) { + eATmegaPinFunc func = this->funcs[n]; + if (func == query) return true; + } + return false; + } + template + inline bool hasFunc(eATmegaPinFunc func, otherItemType&&... items) const { + return hasFunc(func) || hasFunc(((otherItemType&&)items)...); + } + + template + inline void iterate(callbackType&& cb) const { + for (uint8_t n = 0; n < this->cnt; n++) { + eATmegaPinFunc func = this->funcs[n]; + cb(func); + } + } +}; + +ATmegaPinFunctions _ATmega_getPinFunctions(int pin); + +struct ATmegaPinFuncSet { + inline ATmegaPinFuncSet() noexcept { + for (bool& f : this->funcs) f = false; + } + template + inline ATmegaPinFuncSet(eATmegaPinFunc func, funcItemType&&... items) noexcept : ATmegaPinFuncSet() { + add(func, ((funcItemType&&)items)...); + } + template + inline ATmegaPinFuncSet(int pin, funcItemType&&... items) noexcept : ATmegaPinFuncSet() { + addFromPin(pin, ((funcItemType&&)items)...); + } + inline ATmegaPinFuncSet(const ATmegaPinFuncSet&) = default; + + inline void add(eATmegaPinFunc value) noexcept { + this->funcs[(uint8_t)value] = true; + } + template + inline void add(eATmegaPinFunc value, funcItemType&&... items) { + add(value); + add(((eATmegaPinFunc&&)items)...); + } + + inline void addFromPin(int pin) noexcept { + ATmegaPinFunctions funcs = _ATmega_getPinFunctions(pin); + funcs.iterate( + [this]( eATmegaPinFunc func ) noexcept { this->add(func); } + ); + } + template + inline void addFromPin(int pin, itemType&&... items) noexcept { + addFromPin(pin); + addFromPin(((itemType&&)items)...); + } + + inline bool hasFunc(eATmegaPinFunc value) const noexcept { + return this->funcs[(uint8_t)value]; + } + + inline bool hasAnyFunc() const noexcept { return false; } + template + inline bool hasAnyFunc(funcItem&& item, otherFuncItem&&... funcs) const noexcept { + return hasFunc(item) || hasAnyFunc(((otherFuncItem&&)funcs)...); + } + + template + inline void iterate(callbackType&& cb) const { + for (uint8_t n = 1; n < countof(this->funcs); n++) { + const bool& f = this->funcs[n]; + if (f) cb((eATmegaPinFunc)n); + } + } + +private: + bool funcs[(uint8_t)eATmegaPinFunc::NUM_FUNCS]; +}; + +inline void _ATmega_setPeripheralPower(eATmegaPeripheral peri, bool fullPower) { + bool reducePower = (fullPower == false); + switch(peri) { + #ifdef __AVR_TRM01__ + case eATmegaPeripheral::PADC: _PRR0._PRADC = reducePower; break; + case eATmegaPeripheral::PUSART0: _PRR0._PRUSART0 = reducePower; break; + case eATmegaPeripheral::PSPI: _PRR0._PRSPI = reducePower; break; + case eATmegaPeripheral::PTIM1: _PRR0._PRTIM1 = reducePower; break; + case eATmegaPeripheral::PTIM0: _PRR0._PRTIM0 = reducePower; break; + case eATmegaPeripheral::PTIM2: _PRR0._PRTIM2 = reducePower; break; + case eATmegaPeripheral::PTWI: _PRR0._PRTWI = reducePower; break; + case eATmegaPeripheral::PUSART1: _PRR1._PRUSART1 = reducePower; break; + case eATmegaPeripheral::PUSART2: _PRR1._PRUSART2 = reducePower; break; + case eATmegaPeripheral::PUSART3: _PRR1._PRUSART3 = reducePower; break; + case eATmegaPeripheral::PTIM3: _PRR1._PRTIM3 = reducePower; break; + case eATmegaPeripheral::PTIM4: _PRR1._PRTIM4 = reducePower; break; + case eATmegaPeripheral::PTIM5: _PRR1._PRTIM5 = reducePower; break; + #elif defined(__AVR_TRM02__) + case eATmegaPeripheral::PADC: _PRR0._PRADC = reducePower; break; + case eATmegaPeripheral::PUSART0: _PRR0._PRUSART0 = reducePower; break; + case eATmegaPeripheral::PSPI: _PRR0._PRSPI = reducePower; break; + case eATmegaPeripheral::PTIM1: _PRR0._PRTIM1 = reducePower; break; + case eATmegaPeripheral::PUSART1: _PRR0._PRUSART1 = reducePower; break; + case eATmegaPeripheral::PTIM0: _PRR0._PRTIM0 = reducePower; break; + case eATmegaPeripheral::PTIM2: _PRR0._PRTIM2 = reducePower; break; + case eATmegaPeripheral::PTWI: _PRR0._PRTWI = reducePower; break; + case eATmegaPeripheral::PTIM3: _PRR1._PRTIM3 = reducePower; break; + #elif defined(__AVR_TRM03__) + case eATmegaPeripheral::PADC: _PRR0._PRADC = reducePower; break; + case eATmegaPeripheral::PUSART0: _PRR0._PRUSART0 = reducePower; break; + case eATmegaPeripheral::PSPI: _PRR0._PRSPI = reducePower; break; + case eATmegaPeripheral::PTIM1: _PRR0._PRTIM1 = reducePower; break; + case eATmegaPeripheral::PTIM0: _PRR0._PRTIM0 = reducePower; break; + case eATmegaPeripheral::PTIM2: _PRR0._PRTIM2 = reducePower; break; + case eATmegaPeripheral::PTWI: _PRR0._PRTWI = reducePower; break; + #elif defined(__AVR_TRM04__) + case eATmegaPeripheral::PADC: _PRR0._PRADC = reducePower; break; + case eATmegaPeripheral::PSPI: _PRR0._PRSPI = reducePower; break; + case eATmegaPeripheral::PTIM1: _PRR0._PRTIM1 = reducePower; break; + case eATmegaPeripheral::PTIM0: _PRR0._PRTIM0 = reducePower; break; + case eATmegaPeripheral::PTIM2: _PRR0._PRTIM2 = reducePower; break; + case eATmegaPeripheral::PTWI: _PRR0._PRTWI = reducePower; break; + case eATmegaPeripheral::PUSART1: _PRR1._PRUSART1 = reducePower; break; + case eATmegaPeripheral::PTIM3: _PRR1._PRTIM3 = reducePower; break; + case eATmegaPeripheral::PUSB: _PRR1._PRUSB = reducePower; break; + #elif defined(__AVR_TRM05__) + case eATmegaPeripheral::PADC: _PRR0._PRADC = reducePower; break; + case eATmegaPeripheral::PUSART0: _PRR0._PRUSART0 = reducePower; break; + case eATmegaPeripheral::PSPI: _PRR0._PRSPI = reducePower; break; + case eATmegaPeripheral::PTIM1: _PRR0._PRTIM1 = reducePower; break; + case eATmegaPeripheral::PUSART1: _PRR0._PRUSART1 = reducePower; break; + case eATmegaPeripheral::PTIM0: _PRR0._PRTIM0 = reducePower; break; + case eATmegaPeripheral::PTIM2: _PRR0._PRTIM2 = reducePower; break; + case eATmegaPeripheral::PTWI: _PRR0._PRTWI = reducePower; break; + #endif + case eATmegaPeripheral::UNDEFINED: case eATmegaPeripheral::NUM_PERIPHERALS: break; + } +} + +inline bool _ATmega_getPeripheralPower(eATmegaPeripheral peri) { + switch(peri) { + #ifdef __AVR_TRM01__ + case eATmegaPeripheral::PADC: return _PRR0._PRADC == false; + case eATmegaPeripheral::PUSART0: return _PRR0._PRUSART0 == false; + case eATmegaPeripheral::PSPI: return _PRR0._PRSPI == false; + case eATmegaPeripheral::PTIM1: return _PRR0._PRTIM1 == false; + case eATmegaPeripheral::PTIM0: return _PRR0._PRTIM0 == false; + case eATmegaPeripheral::PTIM2: return _PRR0._PRTIM2 == false; + case eATmegaPeripheral::PTWI: return _PRR0._PRTWI == false; + case eATmegaPeripheral::PUSART1: return _PRR1._PRUSART1 == false; + case eATmegaPeripheral::PUSART2: return _PRR1._PRUSART2 == false; + case eATmegaPeripheral::PUSART3: return _PRR1._PRUSART3 == false; + case eATmegaPeripheral::PTIM3: return _PRR1._PRTIM3 == false; + case eATmegaPeripheral::PTIM4: return _PRR1._PRTIM4 == false; + case eATmegaPeripheral::PTIM5: return _PRR1._PRTIM5 == false; + #elif defined(__AVR_TRM02__) + case eATmegaPeripheral::PADC: return _PRR0._PRADC == false; + case eATmegaPeripheral::PUSART0: return _PRR0._PRUSART0 == false; + case eATmegaPeripheral::PSPI: return _PRR0._PRSPI == false; + case eATmegaPeripheral::PTIM1: return _PRR0._PRTIM1 == false; + case eATmegaPeripheral::PUSART1: return _PRR0._PRUSART1 == false; + case eATmegaPeripheral::PTIM0: return _PRR0._PRTIM0 == false; + case eATmegaPeripheral::PTIM2: return _PRR0._PRTIM2 == false; + case eATmegaPeripheral::PTWI: return _PRR0._PRTWI == false; + case eATmegaPeripheral::PTIM3: return _PRR1._PRTIM3 == false; + #elif defined(__AVR_TRM03__) + case eATmegaPeripheral::PADC: return _PRR0._PRADC == false; + case eATmegaPeripheral::PUSART0: return _PRR0._PRUSART0 == false; + case eATmegaPeripheral::PSPI: return _PRR0._PRSPI == false; + case eATmegaPeripheral::PTIM1: return _PRR0._PRTIM1 == false; + case eATmegaPeripheral::PTIM0: return _PRR0._PRTIM0 == false; + case eATmegaPeripheral::PTIM2: return _PRR0._PRTIM2 == false; + case eATmegaPeripheral::PTWI: return _PRR0._PRTWI == false; + #elif defined(__AVR_TRM04__) + case eATmegaPeripheral::PADC: return _PRR0._PRADC == false; + case eATmegaPeripheral::PSPI: return _PRR0._PRSPI == false; + case eATmegaPeripheral::PTIM1: return _PRR0._PRTIM1 == false; + case eATmegaPeripheral::PTIM0: return _PRR0._PRTIM0 == false; + case eATmegaPeripheral::PTIM2: return _PRR0._PRTIM2 == false; + case eATmegaPeripheral::PTWI: return _PRR0._PRTWI == false; + case eATmegaPeripheral::PUSART1: return _PRR1._PRUSART1 == false; + case eATmegaPeripheral::PTIM3: return _PRR1._PRTIM3 == false; + case eATmegaPeripheral::PUSB: return _PRR1._PRUSB == false; + #elif defined(__AVR_TRM05__) + case eATmegaPeripheral::PADC: return _PRR0._PRADC == false; + case eATmegaPeripheral::PUSART0: return _PRR0._PRUSART0 == false; + case eATmegaPeripheral::PSPI: return _PRR0._PRSPI == false; + case eATmegaPeripheral::PTIM1: return _PRR0._PRTIM1 == false; + case eATmegaPeripheral::PUSART1: return _PRR0._PRUSART1 == false; + case eATmegaPeripheral::PTIM0: return _PRR0._PRTIM0 == false; + case eATmegaPeripheral::PTIM2: return _PRR0._PRTIM2 == false; + case eATmegaPeripheral::PTWI: return _PRR0._PRTWI == false; + #endif + case eATmegaPeripheral::UNDEFINED: case eATmegaPeripheral::NUM_PERIPHERALS: break; + } + return false; +} + +inline eATmegaPeripheral _ATmega_getPeripheralForFunc( eATmegaPinFunc func ) { + // In C++20 there is the "using-enum" statement. I wish we had C++20 over here... + //using enum eATmegaPinFunc; + switch(func) { + #ifdef __AVR_TRM01__ + case eATmegaPinFunc::TOC0A: case eATmegaPinFunc::TOC0B: return eATmegaPeripheral::PTIM0; + case eATmegaPinFunc::TOC1A: case eATmegaPinFunc::TOC1B: case eATmegaPinFunc::TOC1C: return eATmegaPeripheral::PTIM1; + case eATmegaPinFunc::TOC2A: case eATmegaPinFunc::TOC2B: return eATmegaPeripheral::PTIM2; + case eATmegaPinFunc::TOC3A: case eATmegaPinFunc::TOC3B: case eATmegaPinFunc::TOC3C: return eATmegaPeripheral::PTIM3; + case eATmegaPinFunc::TOC4A: case eATmegaPinFunc::TOC4B: case eATmegaPinFunc::TOC4C: return eATmegaPeripheral::PTIM4; + case eATmegaPinFunc::TOC5A: case eATmegaPinFunc::TOC5B: case eATmegaPinFunc::TOC5C: return eATmegaPeripheral::PTIM5; + case eATmegaPinFunc::SPI_MISO: case eATmegaPinFunc::SPI_MOSI: case eATmegaPinFunc::SPI_SCK: case eATmegaPinFunc::SPI_CS: return eATmegaPeripheral::PSPI; + case eATmegaPinFunc::TIMER0_CLKI: return eATmegaPeripheral::PTIM0; + case eATmegaPinFunc::TIMER1_CLKI: case eATmegaPinFunc::TIMER1_ICP: return eATmegaPeripheral::PTIM1; + case eATmegaPinFunc::TIMER3_CLKI: case eATmegaPinFunc::TIMER3_ICP: return eATmegaPeripheral::PTIM3; + case eATmegaPinFunc::TIMER4_CLKI: case eATmegaPinFunc::TIMER4_ICP: return eATmegaPeripheral::PTIM4; + case eATmegaPinFunc::TIMER5_CLKI: case eATmegaPinFunc::TIMER5_ICP: return eATmegaPeripheral::PTIM5; + case eATmegaPinFunc::USART0_CLK: case eATmegaPinFunc::USART0_TXD: case eATmegaPinFunc::USART0_RXD: return eATmegaPeripheral::PUSART0; + case eATmegaPinFunc::USART1_CLK: case eATmegaPinFunc::USART1_TXD: case eATmegaPinFunc::USART1_RXD: return eATmegaPeripheral::PUSART1; + case eATmegaPinFunc::USART2_CLK: case eATmegaPinFunc::USART2_TXD: case eATmegaPinFunc::USART2_RXD: return eATmegaPeripheral::PUSART2; + case eATmegaPinFunc::USART3_CLK: case eATmegaPinFunc::USART3_TXD: case eATmegaPinFunc::USART3_RXD: return eATmegaPeripheral::PUSART3; + case eATmegaPinFunc::TWI_SDA: case eATmegaPinFunc::TWI_CLK: return eATmegaPeripheral::PTWI; + case eATmegaPinFunc::ADC15: case eATmegaPinFunc::ADC14: case eATmegaPinFunc::ADC13: case eATmegaPinFunc::ADC12: case eATmegaPinFunc::ADC11: case eATmegaPinFunc::ADC10: case eATmegaPinFunc::ADC9: case eATmegaPinFunc::ADC8: + case eATmegaPinFunc::ADC7: case eATmegaPinFunc::ADC6: case eATmegaPinFunc::ADC5: case eATmegaPinFunc::ADC4: case eATmegaPinFunc::ADC3: case eATmegaPinFunc::ADC2: case eATmegaPinFunc::ADC1: case eATmegaPinFunc::ADC0: + return eATmegaPeripheral::PADC; + #elif defined(__AVR_TRM02__) + case eATmegaPinFunc::ADC7: case eATmegaPinFunc::ADC6: case eATmegaPinFunc::ADC5: case eATmegaPinFunc::ADC4: case eATmegaPinFunc::ADC3: case eATmegaPinFunc::ADC2: case eATmegaPinFunc::ADC1: case eATmegaPinFunc::ADC0: + return eATmegaPeripheral::PADC; + case eATmegaPinFunc::SPI_SCK: case eATmegaPinFunc::SPI_MISO: case eATmegaPinFunc::SPI_MOSI: case eATmegaPinFunc::SPI_CS: return eATmegaPeripheral::PSPI; + case eATmegaPinFunc::TIMER3_ICP: case eATmegaPinFunc::TIMER3_ECI: return eATmegaPeripheral::PTIM3; + case eATmegaPinFunc::TIMER1_ECI: case eATmegaPinFunc::TIMER1_ICP: return eATmegaPeripheral::PTIM1; + case eATmegaPinFunc::TIMER0_ECI: return eATmegaPeripheral::PTIM0; + case eATmegaPinFunc::TOC3B: case eATmegaPinFunc::TOC3A: return eATmegaPeripheral::PTIM3; + case eATmegaPinFunc::TOC2A: case eATmegaPinFunc::TOC2B: return eATmegaPeripheral::PTIM2; + case eATmegaPinFunc::TOC1A: case eATmegaPinFunc::TOC1B: return eATmegaPeripheral::PTIM1; + case eATmegaPinFunc::TOC0B: case eATmegaPinFunc::TOC0A: return eATmegaPeripheral::PTIM0; + case eATmegaPinFunc::USART0_CLK: case eATmegaPinFunc::USART0_TXD: case eATmegaPinFunc::USART0_RXD: return eATmegaPeripheral::PUSART0; + case eATmegaPinFunc::USART1_CLK: case eATmegaPinFunc::USART1_TXD: case eATmegaPinFunc::USART1_RXD: return eATmegaPeripheral::PUSART1; + case eATmegaPinFunc::TWI_SDA: case eATmegaPinFunc::TWI_CLK: return eATmegaPeripheral::PTWI; + #elif defined(__AVR_TRM03__) + case eATmegaPinFunc::ADC5: case eATmegaPinFunc::ADC4: case eATmegaPinFunc::ADC3: case eATmegaPinFunc::ADC2: case eATmegaPinFunc::ADC1: case eATmegaPinFunc::ADC0: + return eATmegaPeripheral::PADC; + case eATmegaPinFunc::SPI_SCK: case eATmegaPinFunc::SPI_MISO: case eATmegaPinFunc::SPI_MOSI: case eATmegaPinFunc::SPI_CS: return eATmegaPeripheral::PSPI; + case eATmegaPinFunc::TOC2B: case eATmegaPinFunc::TOC2A: return eATmegaPeripheral::PTIM2; + case eATmegaPinFunc::TOC1B: case eATmegaPinFunc::TOC1A: return eATmegaPeripheral::PTIM1; + case eATmegaPinFunc::TOC0A: case eATmegaPinFunc::TOC0B: return eATmegaPeripheral::PTIM0; + case eATmegaPinFunc::TIMER1_ICP: case eATmegaPinFunc::TIMER1_ECI: return eATmegaPeripheral::PTIM1; + case eATmegaPinFunc::TIMER0_ECI: return eATmegaPeripheral::PTIM0; + case eATmegaPinFunc::TWI_CLK: case eATmegaPinFunc::TWI_SDA: return eATmegaPeripheral::PTWI; + case eATmegaPinFunc::USART_CLK: case eATmegaPinFunc::USART_TXD: case eATmegaPinFunc::USART_RXD: return eATmegaPeripheral::PUSART0; + #elif defined(__AVR_TRM04__) + case eATmegaPinFunc::TOC0B: case eATmegaPinFunc::TOC0A: return eATmegaPeripheral::PTIM0; + case eATmegaPinFunc::TOC1C: case eATmegaPinFunc::TOC1B: case eATmegaPinFunc::TOC1A: return eATmegaPeripheral::PTIM1; + case eATmegaPinFunc::TOC2B: case eATmegaPinFunc::TOC2A: return eATmegaPeripheral::PTIM2; + case eATmegaPinFunc::TOC3A: case eATmegaPinFunc::TOC3B: case eATmegaPinFunc::TOC3C: return eATmegaPeripheral::PTIM3; + case eATmegaPinFunc::SPI_MISO: case eATmegaPinFunc::SPI_MOSI: case eATmegaPinFunc::SPI_SCK: case eATmegaPinFunc::SPI_CS: return eATmegaPeripheral::PSPI; + case eATmegaPinFunc::TIMER3_ICP: case eATmegaPinFunc::TIMER3_CLKI: return eATmegaPeripheral::PTIM3; + case eATmegaPinFunc::TIMER1_ICP: case eATmegaPinFunc::TIMER1_CLKI: return eATmegaPeripheral::PTIM1; + case eATmegaPinFunc::TIMER0_CLKI: return eATmegaPeripheral::PTIM0; + case eATmegaPinFunc::USART1_CLK: case eATmegaPinFunc::USART1_TXD: case eATmegaPinFunc::USART1_RXD: return eATmegaPeripheral::PUSART1; + case eATmegaPinFunc::TWI_SDA: case eATmegaPinFunc::TWI_CLK: return eATmegaPeripheral::PTWI; + case eATmegaPinFunc::UID: case eATmegaPinFunc::UVCON: return eATmegaPeripheral::PUSB; + case eATmegaPinFunc::ADC7: case eATmegaPinFunc::ADC6: case eATmegaPinFunc::ADC5: case eATmegaPinFunc::ADC4: case eATmegaPinFunc::ADC3: case eATmegaPinFunc::ADC2: case eATmegaPinFunc::ADC1: case eATmegaPinFunc::ADC0: + return eATmegaPeripheral::PADC; + #elif defined(__AVR_TRM05__) + case eATmegaPinFunc::ADC7: case eATmegaPinFunc::ADC6: case eATmegaPinFunc::ADC5: case eATmegaPinFunc::ADC4: case eATmegaPinFunc::ADC3: case eATmegaPinFunc::ADC2: case eATmegaPinFunc::ADC1: case eATmegaPinFunc::ADC0: + return eATmegaPeripheral::PADC; + case eATmegaPinFunc::SPI_MISO: case eATmegaPinFunc::SPI_MOSI: case eATmegaPinFunc::SPI_SCK: case eATmegaPinFunc::SPI_CS: return eATmegaPeripheral::PSPI; + case eATmegaPinFunc::TIMER1_ICP: case eATmegaPinFunc::TIMER1_ECI: return eATmegaPeripheral::PTIM1; + case eATmegaPinFunc::TIMER0_ICP: case eATmegaPinFunc::TIMER0_ECI: return eATmegaPeripheral::PTIM0; + case eATmegaPinFunc::TOC0B: case eATmegaPinFunc::TOC0A: return eATmegaPeripheral::PTIM0; + case eATmegaPinFunc::TOC1A: case eATmegaPinFunc::TOC1B: return eATmegaPeripheral::PTIM1; + case eATmegaPinFunc::TOC2A: case eATmegaPinFunc::TOC2B: return eATmegaPeripheral::PTIM2; + case eATmegaPinFunc::TWI_CLK: case eATmegaPinFunc::TWI_SDA: return eATmegaPeripheral::PTWI; + case eATmegaPinFunc::USART0_CLK: case eATmegaPinFunc::USART0_TXD: case eATmegaPinFunc::USART0_RXD: return eATmegaPeripheral::PUSART0; + case eATmegaPinFunc::USART1_CLK: case eATmegaPinFunc::USART1_TXD: case eATmegaPinFunc::USART1_RXD: return eATmegaPeripheral::PUSART1; + #endif + // There are quite some pin functions that have no peripheral assignment, and that is OK! + default: break; + } + return eATmegaPeripheral::UNDEFINED; +} + +struct ATmegaPeripheralSet { + inline ATmegaPeripheralSet() noexcept { + for (bool& f : this->funcs) f = false; + } + template + inline ATmegaPeripheralSet(funcItemType&&... items) noexcept : ATmegaPinFuncSet() { + add(((eATmegaPinFunc&&)items)...); + } + inline ATmegaPeripheralSet(const ATmegaPeripheralSet&) = default; + + inline void add(eATmegaPeripheral value) noexcept { + this->funcs[(uint8_t)value] = true; + } + template + inline void add(eATmegaPeripheral value, funcItemType&&... items) noexcept { + add(value); + add(((funcItemType&&)items)...); + } + + inline bool hasItem(eATmegaPeripheral value) const noexcept { + return this->funcs[(uint8_t)value]; + } + template + inline bool hasItem(eATmegaPeripheral&& item, otherFuncItem&&... funcs) const noexcept { + return hasItem(item) || hasItem(((otherFuncItem&&)funcs)...); + } + + template + inline void iterate(callbackType&& cb) const { + for (uint8_t n = 1; n < countof(funcs); n++) { + const bool& f = this->funcs[n]; + if (f) cb( (eATmegaPeripheral)n ); + } + } + + inline void fromPinFuncs(const ATmegaPinFuncSet& funcSet) { + funcSet.iterate( + [this]( eATmegaPinFunc func ) noexcept { + this->add( _ATmega_getPeripheralForFunc(func) ); + } + ); + } + +private: + bool funcs[(uint8_t)eATmegaPeripheral::NUM_PERIPHERALS]; +}; + +struct ATmegaPeripheralPowerGate { + inline ATmegaPeripheralPowerGate(ATmegaPeripheralSet& periSet) noexcept : periSet(periSet) { + periSet.iterate( + [this]( eATmegaPeripheral peri ) noexcept { + this->states[(uint8_t)peri] = _ATmega_getPeripheralPower(peri); + _ATmega_setPeripheralPower(peri, true); + } + ); + } + inline ATmegaPeripheralPowerGate(const ATmegaPeripheralPowerGate&) = delete; + + inline ~ATmegaPeripheralPowerGate() { + periSet.iterate( + [this]( eATmegaPeripheral peri ) noexcept { + _ATmega_setPeripheralPower(peri, this->states[(uint8_t)peri]); + } + ); + } + + inline ATmegaPeripheralPowerGate& operator = (const ATmegaPeripheralPowerGate&) = delete; + +private: + ATmegaPeripheralSet& periSet; + bool states[(uint8_t)eATmegaPeripheral::NUM_PERIPHERALS]; +}; + +inline pin_dev_state_t _ATmega_savePinAlternates(const ATmegaPinFuncSet& funcSet) { + // TODO: the manual states that registers of power-reduced peripherals cannot be read or written, and that + // the resources (GPIO pins) remain occupied during power-reduction. This is a serious problem and we should + // add power-reduction awareness to this logic! + + pin_dev_state_t state; + + ATmegaPeripheralSet periSet; + periSet.fromPinFuncs(funcSet); + + ATmegaPeripheralPowerGate pgate(periSet); + + #ifdef __AVR_TRM01__ + // See page 75ff of ATmega2560 technical reference manual. + if (funcSet.hasAnyFunc( + eATmegaPinFunc::EXTMEM_AD15, eATmegaPinFunc::EXTMEM_AD14, eATmegaPinFunc::EXTMEM_AD13, eATmegaPinFunc::EXTMEM_AD12, eATmegaPinFunc::EXTMEM_AD11, eATmegaPinFunc::EXTMEM_AD10, eATmegaPinFunc::EXTMEM_AD9, eATmegaPinFunc::EXTMEM_AD8, + eATmegaPinFunc::EXTMEM_AD7, eATmegaPinFunc::EXTMEM_AD6, eATmegaPinFunc::EXTMEM_AD5, eATmegaPinFunc::EXTMEM_AD4, eATmegaPinFunc::EXTMEM_AD3, eATmegaPinFunc::EXTMEM_AD2, eATmegaPinFunc::EXTMEM_AD1, eATmegaPinFunc::EXTMEM_AD0, + eATmegaPinFunc::EXTMEM_ALE, eATmegaPinFunc::EXTMEM_RD, eATmegaPinFunc::EXTMEM_WR + )) { + state._SRE = _XMCRA._SRE; + _XMCRA._SRE = false; + } + if (funcSet.hasAnyFunc( + eATmegaPinFunc::PCI0, eATmegaPinFunc::PCI1, eATmegaPinFunc::PCI2, eATmegaPinFunc::PCI3, eATmegaPinFunc::PCI4, eATmegaPinFunc::PCI5, eATmegaPinFunc::PCI6, eATmegaPinFunc::PCI7 + )) { + state._PCIE0 = _PCICR._PCIE0; + _PCICR._PCIE0 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1C)) { + state._COM1C = TIMER1._TCCRnA._COMnC; + TIMER1._TCCRnA._COMnC = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1B)) { + state._COM1B = TIMER1._TCCRnA._COMnB; + TIMER1._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1A)) { + state._COM1A = TIMER1._TCCRnA._COMnA; + TIMER1._TCCRnA._COMnA = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2A)) { + state._COM2A = _TIMER2._TCCRnA._COMnA; + _TIMER2._TCCRnA._COMnA = 0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART1_TXD, eATmegaPinFunc::USART1_CLK)) { + state._USART1_TXEN = USART1._UCSRnB._TXEN; + USART1._UCSRnB._TXEN = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART1_RXD, eATmegaPinFunc::USART1_CLK)) { + state._USART1_RXEN = USART1._UCSRnB._RXEN; + USART1._UCSRnB._RXEN = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC3C)) { + state._COM3C = TIMER3._TCCRnA._COMnC; + TIMER3._TCCRnA._COMnC = 0; + } + // There is an error in the technical reference manual signal mapping table + // of ATmega2560 where is says that pin 3 is mapped to OC3B, but the list + // says OC3A. + if (funcSet.hasFunc(eATmegaPinFunc::TOC3B)) { + state._COM3B = TIMER3._TCCRnA._COMnB; + TIMER3._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC3A)) { + state._COM3A = TIMER3._TCCRnA._COMnA; + TIMER3._TCCRnA._COMnA = 0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART0_RXD, eATmegaPinFunc::USART0_CLK)) { + state._USART0_RXEN = USART0._UCSRnB._RXEN; + USART0._UCSRnB._RXEN = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART0_TXD, eATmegaPinFunc::USART0_CLK)) { + state._USART0_TXEN = USART0._UCSRnB._TXEN; + USART0._UCSRnB._TXEN = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI15, eATmegaPinFunc::PCI14, eATmegaPinFunc::PCI13, eATmegaPinFunc::PCI12, eATmegaPinFunc::PCI11, eATmegaPinFunc::PCI10, eATmegaPinFunc::PCI9, eATmegaPinFunc::PCI8)) { + state._PCIE1 = _PCICR._PCIE1; + _PCICR._PCIE1 = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TOC0B)) { + state._COM0B = TIMER0._TCCRnA._COMnB; + TIMER0._TCCRnA._COMnB = 0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TOSC1, eATmegaPinFunc::TOSC2)) { + state._AS2 = _ASSR._AS2; + _ASSR._AS2 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2B)) { + state._COM2B = _TIMER2._TCCRnA._COMnB; + _TIMER2._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC4C)) { + state._COM4C = TIMER4._TCCRnA._COMnC; + TIMER4._TCCRnA._COMnC = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC4B)) { + state._COM4B = TIMER4._TCCRnA._COMnB; + TIMER4._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC4A)) { + state._COM4A = TIMER4._TCCRnA._COMnA; + TIMER4._TCCRnA._COMnA = 0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART2_RXD, eATmegaPinFunc::USART2_CLK)) { + state._USART2_RXEN = USART2._UCSRnB._RXEN; + USART2._UCSRnB._RXEN = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART2_TXD, eATmegaPinFunc::USART2_CLK)) { + state._USART2_TXEN = USART2._UCSRnB._TXEN; + USART2._UCSRnB._TXEN = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART3_TXD, eATmegaPinFunc::USART3_CLK)) { + state._USART3_RXEN = USART3._UCSRnB._RXEN; + USART3._UCSRnB._RXEN = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART3_TXD, eATmegaPinFunc::USART3_CLK)) { + state._USART3_TXEN = USART3._UCSRnB._TXEN; + USART3._UCSRnB._TXEN = false; + } + if (funcSet.hasAnyFunc( + eATmegaPinFunc::PCI23, eATmegaPinFunc::PCI22, eATmegaPinFunc::PCI21, eATmegaPinFunc::PCI20, eATmegaPinFunc::PCI19, eATmegaPinFunc::PCI18, eATmegaPinFunc::PCI17, eATmegaPinFunc::PCI16 + )) { + state._PCIE2 = _PCICR._PCIE2; + _PCICR._PCIE2 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC5C)) { + state._COM5C = TIMER5._TCCRnA._COMnC; + TIMER5._TCCRnA._COMnC = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC5B)) { + state._COM5B = TIMER5._TCCRnA._COMnB; + TIMER5._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC5A)) { + state._COM5A = TIMER5._TCCRnA._COMnA; + TIMER5._TCCRnA._COMnA = 0; + } + #elif defined(__AVR_TRM02__) + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI7, eATmegaPinFunc::PCI6, eATmegaPinFunc::PCI5, eATmegaPinFunc::PCI4, eATmegaPinFunc::PCI3, eATmegaPinFunc::PCI2, eATmegaPinFunc::PCI1, eATmegaPinFunc::PCI0)) { + state._PCIE0 = _PCICR._PCIE0; + _PCICR._PCIE0 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC7)) { + state._ADC7D = _DIDR0._ADC7D; + _DIDR0._ADC7D = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC6)) { + state._ADC6D = _DIDR0._ADC6D; + _DIDR0._ADC6D = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC5)) { + state._ADC5D = _DIDR0._ADC5D; + _DIDR0._ADC5D = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC4)) { + state._ADC4D = _DIDR0._ADC4D; + _DIDR0._ADC4D = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC3)) { + state._ADC3D = _DIDR0._ADC3D; + _DIDR0._ADC3D = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC2)) { + state._ADC2D = _DIDR0._ADC2D; + _DIDR0._ADC2D = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC1)) { + state._ADC1D = _DIDR0._ADC1D; + _DIDR0._ADC1D = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC0)) { + state._ADC0D = _DIDR0._ADC0D; + _DIDR0._ADC0D = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI15, eATmegaPinFunc::PCI14, eATmegaPinFunc::PCI13, eATmegaPinFunc::PCI12, eATmegaPinFunc::PCI11, eATmegaPinFunc::PCI10, eATmegaPinFunc::PCI9, eATmegaPinFunc::PCI8)) { + state._PCIE1 = _PCICR._PCIE1; + _PCICR._PCIE1 = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::SPI_SCK, eATmegaPinFunc::SPI_MISO, eATmegaPinFunc::SPI_MOSI, eATmegaPinFunc::SPI_CS)) { + state._SPE = _SPCR._SPE; + _SPCR._SPE = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0A)) { + state._COM0A = TIMER0._TCCRnA._COMnA; + TIMER0._TCCRnA._COMnA = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0B)) { + state._COM0B = TIMER0._TCCRnA._COMnB; + TIMER0._TCCRnA._COMnB = 0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TOSC1, eATmegaPinFunc::TOSC2)) { + state._AS2 = _ASSR._AS2; + _ASSR._AS2 = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI23, eATmegaPinFunc::PCI22, eATmegaPinFunc::PCI21, eATmegaPinFunc::PCI20, eATmegaPinFunc::PCI19, eATmegaPinFunc::PCI18, eATmegaPinFunc::PCI17, eATmegaPinFunc::PCI16)) { + state._PCIE2 = _PCICR._PCIE2; + _PCICR._PCIE2 = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI31, eATmegaPinFunc::PCI30, eATmegaPinFunc::PCI29, eATmegaPinFunc::PCI28, eATmegaPinFunc::PCI27, eATmegaPinFunc::PCI26, eATmegaPinFunc::PCI25, eATmegaPinFunc::PCI24)) { + state._PCIE3 = _PCICR._PCIE3; + _PCICR._PCIE3 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2A)) { + state._COM2A = _TIMER2._TCCRnA._COMnA; + _TIMER2._TCCRnA._COMnA = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2B)) { + state._COM2B = _TIMER2._TCCRnA._COMnB; + _TIMER2._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1A)) { + state._COM1A = TIMER1._TCCRnA._COMnA; + TIMER1._TCCRnA._COMnA = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1B)) { + state._COM1B = TIMER1._TCCRnA._COMnB; + TIMER1._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::USART1_TXD)) { + state._USART1_TXEN = USART1._UCSRnB._TXEN; + USART1._UCSRnB._TXEN = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::USART1_RXD)) { + state._USART1_RXEN = USART1._UCSRnB._RXEN; + USART1._UCSRnB._RXEN = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::USART0_TXD)) { + state._USART0_TXEN = USART0._UCSRnB._TXEN; + USART0._UCSRnB._TXEN = false; + } + // There is a bug in the ATmega164A technical reference manual where + // it says that pin 0 is mapped to USART1 RXD in the signal mapping table + // but the associated list says USART0 RXD. + if (funcSet.hasFunc(eATmegaPinFunc::USART0_RXD)) { + state._USART0_RXEN = USART0._UCSRnB._RXEN; + USART0._UCSRnB._RXEN = false; + } + #elif defined(__AVR_TRM03__) + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI7, eATmegaPinFunc::PCI6, eATmegaPinFunc::PCI5, eATmegaPinFunc::PCI4, eATmegaPinFunc::PCI3, eATmegaPinFunc::PCI2, eATmegaPinFunc::PCI1, eATmegaPinFunc::PCI0)) { + state._PCIE0 = _PCICR._PCIE0; + _PCICR._PCIE0 = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TOSC1, eATmegaPinFunc::TOSC2)) { + state._AS2 = _ASSR._AS2; + _ASSR._AS2 = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::SPI_SCK, eATmegaPinFunc::SPI_MISO, eATmegaPinFunc::SPI_MOSI, eATmegaPinFunc::SPI_CS)) { + state._SPE = _SPCR._SPE; + _SPCR._SPE = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2A)) { + state._COM2A = _TIMER2._TCCRnA._COMnA; + _TIMER2._TCCRnA._COMnA = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1B)) { + state._COM1B = TIMER1._TCCRnA._COMnB; + TIMER1._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1A)) { + state._COM1A = TIMER1._TCCRnA._COMnA; + TIMER1._TCCRnA._COMnA = 0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI14, eATmegaPinFunc::PCI13, eATmegaPinFunc::PCI12, eATmegaPinFunc::PCI11, eATmegaPinFunc::PCI10, eATmegaPinFunc::PCI9, eATmegaPinFunc::PCI8)) { + state._PCIE1 = _PCICR._PCIE1; + _PCICR._PCIE1 = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TWI_CLK, eATmegaPinFunc::TWI_SDA)) { + state._TWEN = _TWCR._TWEN; + _TWCR._TWEN = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC5)) { + state._ADC5D = _DIDR0._ADC5D; + _DIDR0._ADC5D = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC4)) { + state._ADC4D = _DIDR0._ADC4D; + _DIDR0._ADC4D = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC3)) { + state._ADC3D = _DIDR0._ADC3D; + _DIDR0._ADC3D = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC2)) { + state._ADC2D = _DIDR0._ADC2D; + _DIDR0._ADC2D = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC1)) { + state._ADC1D = _DIDR0._ADC1D; + _DIDR0._ADC1D = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC0)) { + state._ADC0D = _DIDR0._ADC0D; + _DIDR0._ADC0D = false; + } + // There is a bug in the ATmega48A technical reference manual where pin 2 + // is said to be mapped to PCIE1 but logically it should be PCIE2 instead. + // The real mapping can be read in the documentation of the PCICR register. + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI23, eATmegaPinFunc::PCI22, eATmegaPinFunc::PCI21, eATmegaPinFunc::PCI20, eATmegaPinFunc::PCI19, eATmegaPinFunc::PCI18, eATmegaPinFunc::PCI17, eATmegaPinFunc::PCI16)) { + state._PCIE2 = _PCICR._PCIE2; + _PCICR._PCIE2 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0A)) { + state._COM0A = TIMER0._TCCRnA._COMnA; + TIMER0._TCCRnA._COMnA = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0B)) { + state._COM0B = TIMER0._TCCRnA._COMnB; + TIMER0._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::USART_CLK)) { + state._UMSEL = USART0._UCSRnC._UMSEL; + USART0._UCSRnC._UMSEL = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2B)) { + state._COM2B = _TIMER2._TCCRnA._COMnB; + _TIMER2._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::USART_TXD)) { + state._USART0_TXEN = USART0._UCSRnB._TXEN; + USART0._UCSRnB._TXEN = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::USART_RXD)) { + state._USART0_RXEN = USART0._UCSRnB._RXEN; + USART0._UCSRnB._RXEN = false; + } + #elif defined(__AVR_TRM04__) + if (funcSet.hasAnyFunc( + eATmegaPinFunc::EXTMEM_AD15, eATmegaPinFunc::EXTMEM_AD14, eATmegaPinFunc::EXTMEM_AD13, eATmegaPinFunc::EXTMEM_AD12, eATmegaPinFunc::EXTMEM_AD11, eATmegaPinFunc::EXTMEM_AD10, eATmegaPinFunc::EXTMEM_AD9, eATmegaPinFunc::EXTMEM_AD8, + eATmegaPinFunc::EXTMEM_AD7, eATmegaPinFunc::EXTMEM_AD6, eATmegaPinFunc::EXTMEM_AD5, eATmegaPinFunc::EXTMEM_AD4, eATmegaPinFunc::EXTMEM_AD3, eATmegaPinFunc::EXTMEM_AD2, eATmegaPinFunc::EXTMEM_AD1, eATmegaPinFunc::EXTMEM_AD0, + eATmegaPinFunc::EXTMEM_ALE, eATmegaPinFunc::EXTMEM_RD, eATmegaPinFunc::EXTMEM_WR + )) { + state._SRE = _XMCRA._SRE; + _XMCRA._SRE = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1C)) { + state._COM1C = TIMER1._TCCRnA._COMnC; + TIMER1._TCCRnA._COMnC = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1B)) { + state._COM1B = TIMER1._TCCRnA._COMnB; + TIMER1._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1A)) { + state._COM1A = TIMER1._TCCRnA._COMnA; + TIMER1._TCCRnA._COMnA = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2A)) { + state._COM2A = _TIMER2._TCCRnA._COMnA; + _TIMER2._TCCRnA._COMnA = 0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::SPI_MISO, eATmegaPinFunc::SPI_MOSI, eATmegaPinFunc::SPI_SCK, eATmegaPinFunc::SPI_CS)) { + state._SPE = _SPCR._SPE; + _SPCR._SPE = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI7, eATmegaPinFunc::PCI6, eATmegaPinFunc::PCI5, eATmegaPinFunc::PCI4, eATmegaPinFunc::PCI3, eATmegaPinFunc::PCI2, eATmegaPinFunc::PCI1, eATmegaPinFunc::PCI0)) { + state._PCIE0 = _PCICR._PCIE0; + _PCICR._PCIE0 = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART1_CLK, eATmegaPinFunc::USART1_TXD)) { + state._USART1_TXEN = USART1._UCSRnB._TXEN; + USART1._UCSRnB._TXEN = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART1_CLK, eATmegaPinFunc::USART1_RXD)) { + state._USART1_RXEN = USART1._UCSRnB._RXEN; + USART1._UCSRnB._RXEN = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TWI_SDA, eATmegaPinFunc::TWI_CLK)) { + state._TWEN = _TWCR._TWEN; + _TWCR._TWEN = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2B)) { + state._COM2B = _TIMER2._TCCRnA._COMnB; + _TIMER2._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0B)) { + state._COM0B = TIMER0._TCCRnA._COMnB; + TIMER0._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT3)) { + state._INT3 = _EIMSK._INT3; + _EIMSK._INT3 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT2)) { + state._INT2 = _EIMSK._INT2; + _EIMSK._INT2 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT1)) { + state._INT1 = _EIMSK._INT1; + _EIMSK._INT1 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT0)) { + state._INT0 = _EIMSK._INT0; + _EIMSK._INT0 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::UVCON)) { + state._UVCONE = _UHWCON._UVCONE; + _UHWCON._UVCONE = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::UID)) { + state._UIDE = _UHWCON._UIDE; + _UHWCON._UIDE = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT7)) { + state._INT7 = _EIMSK._INT7; + _EIMSK._INT7 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT6)) { + state._INT6 = _EIMSK._INT6; + _EIMSK._INT6 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT5)) { + state._INT5 = _EIMSK._INT5; + _EIMSK._INT5 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT4)) { + state._INT4 = _EIMSK._INT4; + _EIMSK._INT4 = false; + } + #elif defined(__AVR_TRM05__) + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI7, eATmegaPinFunc::PCI6, eATmegaPinFunc::PCI5, eATmegaPinFunc::PCI4, eATmegaPinFunc::PCI3, eATmegaPinFunc::PCI2, eATmegaPinFunc::PCI1, eATmegaPinFunc::PCI0)) { + state._PCIE0 = _PCICR._PCIE0; + _PCICR._PCIE0 = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI15, eATmegaPinFunc::PCI14, eATmegaPinFunc::PCI13, eATmegaPinFunc::PCI12, eATmegaPinFunc::PCI11, eATmegaPinFunc::PCI10, eATmegaPinFunc::PCI9, eATmegaPinFunc::PCI8)) { + state._PCIE1 = _PCICR._PCIE1; + _PCICR._PCIE1 = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI23, eATmegaPinFunc::PCI22, eATmegaPinFunc::PCI21, eATmegaPinFunc::PCI20, eATmegaPinFunc::PCI19, eATmegaPinFunc::PCI18, eATmegaPinFunc::PCI17, eATmegaPinFunc::PCI16)) { + state._PCIE2 = _PCICR._PCIE2; + _PCICR._PCIE2 = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI31, eATmegaPinFunc::PCI30, eATmegaPinFunc::PCI29, eATmegaPinFunc::PCI28, eATmegaPinFunc::PCI27, eATmegaPinFunc::PCI26, eATmegaPinFunc::PCI25, eATmegaPinFunc::PCI24)) { + state._PCIE3 = _PCICR._PCIE3; + _PCICR._PCIE3 = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::SPI_SCK, eATmegaPinFunc::SPI_MISO, eATmegaPinFunc::SPI_MOSI, eATmegaPinFunc::SPI_CS)) { + state._SPE = _SPCR._SPE; + _SPCR._SPE = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0B)) { + state._COM0B = TIMER0._TCCRnA._COMnB; + TIMER0._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0A)) { + state._COM0A = TIMER0._TCCRnA._COMnA; + TIMER0._TCCRnA._COMnA = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2A)) { + state._COM2A = _TIMER2._TCCRnA._COMnA; + _TIMER2._TCCRnA._COMnA = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2B)) { + state._COM2B = _TIMER2._TCCRnA._COMnB; + _TIMER2._TCCRnA._COMnB = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1A)) { + state._COM1A = TIMER1._TCCRnA._COMnA; + TIMER1._TCCRnA._COMnA = 0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1B)) { + state._COM1B = TIMER1._TCCRnA._COMnB; + TIMER1._TCCRnA._COMnB = 0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TWI_CLK, eATmegaPinFunc::TWI_SDA)) { + state._TWEN = _TWCR._TWEN; + _TWCR._TWEN = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT2)) { + state._INT2 = _EIMSK._INT2; + _EIMSK._INT2 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT1)) { + state._INT1 = _EIMSK._INT1; + _EIMSK._INT1 = false; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT0)) { + state._INT0 = _EIMSK._INT0; + _EIMSK._INT0 = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART0_CLK, eATmegaPinFunc::USART0_TXD)) { + state._TXEN0 = USART0._UCSRnB._TXEN; + USART0._UCSRnB._TXEN = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART0_CLK, eATmegaPinFunc::USART0_RXD)) { + state._RXEN0 = USART0._UCSRnB._RXEN; + USART0._UCSRnB._RXEN = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART1_CLK, eATmegaPinFunc::USART1_TXD)) { + state._TXEN1 = USART1._UCSRnB._TXEN; + USART1._UCSRnB._TXEN = false; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART1_CLK, eATmegaPinFunc::USART1_RXD)) { + state._RXEN1 = USART1._UCSRnB._RXEN; + USART1._UCSRnB._RXEN = false; + } + #endif + + return state; +} + +inline void _ATmega_restorePinAlternates(const ATmegaPinFuncSet& funcSet, const pin_dev_state_t& state) { + ATmegaPeripheralSet periSet; + periSet.fromPinFuncs(funcSet); + + ATmegaPeripheralPowerGate pgate(periSet); + + #ifdef __AVR_TRM01__ + // See page 75ff of ATmega2560 technical reference manual. + if (funcSet.hasAnyFunc( + eATmegaPinFunc::EXTMEM_AD15, eATmegaPinFunc::EXTMEM_AD14, eATmegaPinFunc::EXTMEM_AD13, eATmegaPinFunc::EXTMEM_AD12, eATmegaPinFunc::EXTMEM_AD11, eATmegaPinFunc::EXTMEM_AD10, eATmegaPinFunc::EXTMEM_AD9, eATmegaPinFunc::EXTMEM_AD8, + eATmegaPinFunc::EXTMEM_AD7, eATmegaPinFunc::EXTMEM_AD6, eATmegaPinFunc::EXTMEM_AD5, eATmegaPinFunc::EXTMEM_AD4, eATmegaPinFunc::EXTMEM_AD3, eATmegaPinFunc::EXTMEM_AD2, eATmegaPinFunc::EXTMEM_AD1, eATmegaPinFunc::EXTMEM_AD0, + eATmegaPinFunc::EXTMEM_ALE, eATmegaPinFunc::EXTMEM_RD, eATmegaPinFunc::EXTMEM_WR + )) { + _XMCRA._SRE = state._SRE; + } + if (funcSet.hasAnyFunc( + eATmegaPinFunc::PCI0, eATmegaPinFunc::PCI1, eATmegaPinFunc::PCI2, eATmegaPinFunc::PCI3, eATmegaPinFunc::PCI4, eATmegaPinFunc::PCI5, eATmegaPinFunc::PCI6, eATmegaPinFunc::PCI7 + )) { + _PCICR._PCIE0 = state._PCIE0; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1C)) { + TIMER1._TCCRnA._COMnC = state._COM1C; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1B)) { + TIMER1._TCCRnA._COMnB = state._COM1B; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1A)) { + TIMER1._TCCRnA._COMnA = state._COM1A; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2A)) { + _TIMER2._TCCRnA._COMnA = state._COM2A; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART1_TXD, eATmegaPinFunc::USART1_CLK)) { + USART1._UCSRnB._TXEN = state._USART1_TXEN; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART1_RXD, eATmegaPinFunc::USART1_CLK)) { + USART1._UCSRnB._RXEN = state._USART1_RXEN; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC3C)) { + TIMER3._TCCRnA._COMnC = state._COM3C; + } + // There is an error in the technical reference manual signal mapping table + // of ATmega2560 where is says that pin 3 is mapped to OC3B, but the list + // says OC3A. + if (funcSet.hasFunc(eATmegaPinFunc::TOC3B)) { + TIMER3._TCCRnA._COMnB = state._COM3B; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC3A)) { + TIMER3._TCCRnA._COMnA = state._COM3A; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART0_RXD, eATmegaPinFunc::USART0_CLK)) { + USART0._UCSRnB._RXEN = state._USART0_RXEN; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART0_TXD, eATmegaPinFunc::USART0_CLK)) { + USART0._UCSRnB._TXEN = state._USART0_TXEN; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI15, eATmegaPinFunc::PCI14, eATmegaPinFunc::PCI13, eATmegaPinFunc::PCI12, eATmegaPinFunc::PCI11, eATmegaPinFunc::PCI10, eATmegaPinFunc::PCI9, eATmegaPinFunc::PCI8)) { + _PCICR._PCIE1 = state._PCIE1; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TOC0B)) { + TIMER0._TCCRnA._COMnB = state._COM0B; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TOSC1, eATmegaPinFunc::TOSC2)) { + _ASSR._AS2 = state._AS2; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2B)) { + _TIMER2._TCCRnA._COMnB = state._COM2B; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC4C)) { + TIMER4._TCCRnA._COMnC = state._COM4C; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC4B)) { + TIMER4._TCCRnA._COMnB = state._COM4B; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC4A)) { + TIMER4._TCCRnA._COMnA = state._COM4A; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART2_RXD, eATmegaPinFunc::USART2_CLK)) { + USART2._UCSRnB._RXEN = state._USART2_RXEN; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART2_TXD, eATmegaPinFunc::USART2_CLK)) { + USART2._UCSRnB._TXEN = state._USART2_TXEN; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART3_TXD, eATmegaPinFunc::USART3_CLK)) { + USART3._UCSRnB._RXEN = state._USART3_RXEN; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART3_TXD, eATmegaPinFunc::USART3_CLK)) { + USART3._UCSRnB._TXEN = state._USART3_TXEN; + } + if (funcSet.hasAnyFunc( + eATmegaPinFunc::PCI23, eATmegaPinFunc::PCI22, eATmegaPinFunc::PCI21, eATmegaPinFunc::PCI20, eATmegaPinFunc::PCI19, eATmegaPinFunc::PCI18, eATmegaPinFunc::PCI17, eATmegaPinFunc::PCI16 + )) { + _PCICR._PCIE2 = state._PCIE2; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC5C)) { + TIMER5._TCCRnA._COMnC = state._COM5C; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC5B)) { + TIMER5._TCCRnA._COMnB = state._COM5B; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC5A)) { + TIMER5._TCCRnA._COMnA = state._COM5A; + } + #elif defined(__AVR_TRM02__) + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI7, eATmegaPinFunc::PCI6, eATmegaPinFunc::PCI5, eATmegaPinFunc::PCI4, eATmegaPinFunc::PCI3, eATmegaPinFunc::PCI2, eATmegaPinFunc::PCI1, eATmegaPinFunc::PCI0)) { + _PCICR._PCIE0 = state._PCIE0; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC7)) { + _DIDR0._ADC7D = state._ADC7D; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC6)) { + _DIDR0._ADC6D = state._ADC6D; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC5)) { + _DIDR0._ADC5D = state._ADC5D; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC4)) { + _DIDR0._ADC4D = state._ADC4D; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC3)) { + _DIDR0._ADC3D = state._ADC3D; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC2)) { + _DIDR0._ADC2D = state._ADC2D; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC1)) { + _DIDR0._ADC1D = state._ADC1D; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC0)) { + _DIDR0._ADC0D = state._ADC0D; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI15, eATmegaPinFunc::PCI14, eATmegaPinFunc::PCI13, eATmegaPinFunc::PCI12, eATmegaPinFunc::PCI11, eATmegaPinFunc::PCI10, eATmegaPinFunc::PCI9, eATmegaPinFunc::PCI8)) { + _PCICR._PCIE1 = state._PCIE1; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::SPI_SCK, eATmegaPinFunc::SPI_MISO, eATmegaPinFunc::SPI_MOSI, eATmegaPinFunc::SPI_CS)) { + _SPCR._SPE = state._SPE; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0A)) { + TIMER0._TCCRnA._COMnA = state._COM0A; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0B)) { + TIMER0._TCCRnA._COMnB = state._COM0B; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TOSC1, eATmegaPinFunc::TOSC2)) { + _ASSR._AS2 = state._AS2; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI23, eATmegaPinFunc::PCI22, eATmegaPinFunc::PCI21, eATmegaPinFunc::PCI20, eATmegaPinFunc::PCI19, eATmegaPinFunc::PCI18, eATmegaPinFunc::PCI17, eATmegaPinFunc::PCI16)) { + _PCICR._PCIE2 = state._PCIE2; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI31, eATmegaPinFunc::PCI30, eATmegaPinFunc::PCI29, eATmegaPinFunc::PCI28, eATmegaPinFunc::PCI27, eATmegaPinFunc::PCI26, eATmegaPinFunc::PCI25, eATmegaPinFunc::PCI24)) { + _PCICR._PCIE3 = state._PCIE3; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2A)) { + _TIMER2._TCCRnA._COMnA = state._COM2A; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2B)) { + _TIMER2._TCCRnA._COMnB = state._COM2B; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1A)) { + TIMER1._TCCRnA._COMnA = state._COM1A; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1B)) { + TIMER1._TCCRnA._COMnB = state._COM1B; + } + if (funcSet.hasFunc(eATmegaPinFunc::USART1_TXD)) { + USART1._UCSRnB._TXEN = state._USART1_TXEN; + } + if (funcSet.hasFunc(eATmegaPinFunc::USART1_RXD)) { + USART1._UCSRnB._RXEN = state._USART1_RXEN; + } + if (funcSet.hasFunc(eATmegaPinFunc::USART0_TXD)) { + USART0._UCSRnB._TXEN = state._USART0_TXEN; + } + // There is a bug in the ATmega164A technical reference manual where + // it says that pin 0 is mapped to USART1 RXD in the signal mapping table + // but the associated list says USART0 RXD. + if (funcSet.hasFunc(eATmegaPinFunc::USART0_RXD)) { + USART0._UCSRnB._RXEN = state._USART0_RXEN; + } + #elif defined(__AVR_TRM03__) + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI7, eATmegaPinFunc::PCI6, eATmegaPinFunc::PCI5, eATmegaPinFunc::PCI4, eATmegaPinFunc::PCI3, eATmegaPinFunc::PCI2, eATmegaPinFunc::PCI1, eATmegaPinFunc::PCI0)) { + _PCICR._PCIE0 = state._PCIE0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TOSC1, eATmegaPinFunc::TOSC2)) { + _ASSR._AS2 = state._AS2; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::SPI_SCK, eATmegaPinFunc::SPI_MISO, eATmegaPinFunc::SPI_MOSI, eATmegaPinFunc::SPI_CS)) { + _SPCR._SPE = state._SPE; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2A)) { + _TIMER2._TCCRnA._COMnA = state._COM2A; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1B)) { + TIMER1._TCCRnA._COMnB = state._COM1B; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1A)) { + TIMER1._TCCRnA._COMnA = state._COM1A; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI14, eATmegaPinFunc::PCI13, eATmegaPinFunc::PCI12, eATmegaPinFunc::PCI11, eATmegaPinFunc::PCI10, eATmegaPinFunc::PCI9, eATmegaPinFunc::PCI8)) { + _PCICR._PCIE1 = state._PCIE1; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TWI_CLK, eATmegaPinFunc::TWI_SDA)) { + _TWCR._TWEN = state._TWEN; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC5)) { + _DIDR0._ADC5D = state._ADC5D; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC4)) { + _DIDR0._ADC4D = state._ADC4D; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC3)) { + _DIDR0._ADC3D = state._ADC3D; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC2)) { + _DIDR0._ADC2D = state._ADC2D; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC1)) { + _DIDR0._ADC1D = state._ADC1D; + } + if (funcSet.hasFunc(eATmegaPinFunc::ADC0)) { + _DIDR0._ADC0D = state._ADC0D; + } + // There is a bug in the ATmega48A technical reference manual where pin 2 + // is said to be mapped to PCIE1 but logically it should be PCIE2 instead. + // The real mapping can be read in the documentation of the PCICR register. + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI23, eATmegaPinFunc::PCI22, eATmegaPinFunc::PCI21, eATmegaPinFunc::PCI20, eATmegaPinFunc::PCI19, eATmegaPinFunc::PCI18, eATmegaPinFunc::PCI17, eATmegaPinFunc::PCI16)) { + _PCICR._PCIE2 = state._PCIE2; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0A)) { + TIMER0._TCCRnA._COMnA = state._COM0A; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0B)) { + TIMER0._TCCRnA._COMnB = state._COM0B; + } + if (funcSet.hasFunc(eATmegaPinFunc::USART_CLK)) { + USART0._UCSRnC._UMSEL = state._UMSEL; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2B)) { + _TIMER2._TCCRnA._COMnB = state._COM2B; + } + if (funcSet.hasFunc(eATmegaPinFunc::USART_TXD)) { + USART0._UCSRnB._TXEN = state._USART0_TXEN; + } + if (funcSet.hasFunc(eATmegaPinFunc::USART_RXD)) { + USART0._UCSRnB._RXEN = state._USART0_RXEN; + } + #elif defined(__AVR_TRM04__) + if (funcSet.hasAnyFunc( + eATmegaPinFunc::EXTMEM_AD15, eATmegaPinFunc::EXTMEM_AD14, eATmegaPinFunc::EXTMEM_AD13, eATmegaPinFunc::EXTMEM_AD12, eATmegaPinFunc::EXTMEM_AD11, eATmegaPinFunc::EXTMEM_AD10, eATmegaPinFunc::EXTMEM_AD9, eATmegaPinFunc::EXTMEM_AD8, + eATmegaPinFunc::EXTMEM_AD7, eATmegaPinFunc::EXTMEM_AD6, eATmegaPinFunc::EXTMEM_AD5, eATmegaPinFunc::EXTMEM_AD4, eATmegaPinFunc::EXTMEM_AD3, eATmegaPinFunc::EXTMEM_AD2, eATmegaPinFunc::EXTMEM_AD1, eATmegaPinFunc::EXTMEM_AD0, + eATmegaPinFunc::EXTMEM_ALE, eATmegaPinFunc::EXTMEM_RD, eATmegaPinFunc::EXTMEM_WR + )) { + _XMCRA._SRE = state._SRE; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1C)) { + TIMER1._TCCRnA._COMnC = state._COM1C; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1B)) { + TIMER1._TCCRnA._COMnB = state._COM1B; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1A)) { + TIMER1._TCCRnA._COMnA = state._COM1A; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2A)) { + _TIMER2._TCCRnA._COMnA = state._COM2A; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::SPI_MISO, eATmegaPinFunc::SPI_MOSI, eATmegaPinFunc::SPI_SCK, eATmegaPinFunc::SPI_CS)) { + _SPCR._SPE = state._SPE; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI7, eATmegaPinFunc::PCI6, eATmegaPinFunc::PCI5, eATmegaPinFunc::PCI4, eATmegaPinFunc::PCI3, eATmegaPinFunc::PCI2, eATmegaPinFunc::PCI1, eATmegaPinFunc::PCI0)) { + _PCICR._PCIE0 = state._PCIE0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART1_CLK, eATmegaPinFunc::USART1_TXD)) { + USART1._UCSRnB._TXEN = state._USART1_TXEN; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART1_CLK, eATmegaPinFunc::USART1_RXD)) { + USART1._UCSRnB._RXEN = state._USART1_RXEN; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TWI_SDA, eATmegaPinFunc::TWI_CLK)) { + _TWCR._TWEN = state._TWEN; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2B)) { + _TIMER2._TCCRnA._COMnB = state._COM2B; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0B)) { + TIMER0._TCCRnA._COMnB = state._COM0B; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT3)) { + _EIMSK._INT3 = state._INT3; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT2)) { + _EIMSK._INT2 = state._INT2; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT1)) { + _EIMSK._INT1 = state._INT1; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT0)) { + _EIMSK._INT0 = state._INT0; + } + if (funcSet.hasFunc(eATmegaPinFunc::UVCON)) { + _UHWCON._UVCONE = state._UVCONE; + } + if (funcSet.hasFunc(eATmegaPinFunc::UID)) { + _UHWCON._UIDE = state._UIDE; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT7)) { + _EIMSK._INT7 = state._INT7; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT6)) { + _EIMSK._INT6 = state._INT6; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT5)) { + _EIMSK._INT5 = state._INT5; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT4)) { + _EIMSK._INT4 = state._INT4; + } + #elif defined(__AVR_TRM05__) + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI7, eATmegaPinFunc::PCI6, eATmegaPinFunc::PCI5, eATmegaPinFunc::PCI4, eATmegaPinFunc::PCI3, eATmegaPinFunc::PCI2, eATmegaPinFunc::PCI1, eATmegaPinFunc::PCI0)) { + _PCICR._PCIE0 = state._PCIE0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI15, eATmegaPinFunc::PCI14, eATmegaPinFunc::PCI13, eATmegaPinFunc::PCI12, eATmegaPinFunc::PCI11, eATmegaPinFunc::PCI10, eATmegaPinFunc::PCI9, eATmegaPinFunc::PCI8)) { + _PCICR._PCIE1 = state._PCIE1; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI23, eATmegaPinFunc::PCI22, eATmegaPinFunc::PCI21, eATmegaPinFunc::PCI20, eATmegaPinFunc::PCI19, eATmegaPinFunc::PCI18, eATmegaPinFunc::PCI17, eATmegaPinFunc::PCI16)) { + _PCICR._PCIE2 = state._PCIE2; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::PCI31, eATmegaPinFunc::PCI30, eATmegaPinFunc::PCI29, eATmegaPinFunc::PCI28, eATmegaPinFunc::PCI27, eATmegaPinFunc::PCI26, eATmegaPinFunc::PCI25, eATmegaPinFunc::PCI24)) { + _PCICR._PCIE3 = state._PCIE3; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::SPI_SCK, eATmegaPinFunc::SPI_MISO, eATmegaPinFunc::SPI_MOSI, eATmegaPinFunc::SPI_CS)) { + _SPCR._SPE = state._SPE; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0B)) { + TIMER0._TCCRnA._COMnB = state._COM0B; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC0A)) { + TIMER0._TCCRnA._COMnA = state._COM0A; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2A)) { + _TIMER2._TCCRnA._COMnA = state._COM2A; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC2B)) { + _TIMER2._TCCRnA._COMnB = state._COM2B; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1A)) { + TIMER1._TCCRnA._COMnA = state._COM1A; + } + if (funcSet.hasFunc(eATmegaPinFunc::TOC1B)) { + TIMER1._TCCRnA._COMnB = state._COM1B; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::TWI_CLK, eATmegaPinFunc::TWI_SDA)) { + _TWCR._TWEN = state._TWEN; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT2)) { + _EIMSK._INT2 = state._INT2; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT1)) { + _EIMSK._INT1 = state._INT1; + } + if (funcSet.hasFunc(eATmegaPinFunc::EINT0)) { + _EIMSK._INT0 = state._INT0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART0_CLK, eATmegaPinFunc::USART0_TXD)) { + USART0._UCSRnB._TXEN = state._TXEN0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART0_CLK, eATmegaPinFunc::USART0_RXD)) { + USART0._UCSRnB._RXEN = state._RXEN0; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART1_CLK, eATmegaPinFunc::USART1_TXD)) { + USART1._UCSRnB._TXEN = state._TXEN1; + } + if (funcSet.hasAnyFunc(eATmegaPinFunc::USART1_CLK, eATmegaPinFunc::USART1_RXD)) { + USART1._UCSRnB._RXEN = state._RXEN1; + } + #endif +} + +inline pin_dev_state_t _ATmega_savePinAlternate(uint8_t pin) { + return _ATmega_savePinAlternates({pin}); +} + +inline void _ATmega_restorePinAlternate(uint8_t pin, const pin_dev_state_t& state) { + _ATmega_restorePinAlternate({pin}, state); +} + +#ifndef LOW + #define LOW 0 +#endif +#ifndef HIGH + #define HIGH 1 +#endif + +inline void _ATmega_digitalWrite(int pin, int state) { + if (pin < 0) return; + + ATmegaPinInfo info = _ATmega_getPinInfo((unsigned int)pin); + + #ifdef __AVR_TRM01__ + if (info.port == eATmegaPort::PORT_A) { + _PORTA._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_B) { + _PORTB._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_C) { + _PORTC._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_D) { + _PORTD._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_E) { + _PORTE._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_F) { + _PORTF._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_G) { + _PORTG._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_H) { + _PORTH._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_J) { + _PORTJ._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_K) { + _PORTK._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_L) { + _PORTL._PORT.setValue(info.pinidx, state == HIGH); + } + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + if (info.port == eATmegaPort::PORT_A) { + _PORTA._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_B) { + _PORTB._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_C) { + _PORTC._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_D) { + _PORTD._PORT.setValue(info.pinidx, state == HIGH); + } + #elif defined(__AVR_TRM03__) + if (info.port == eATmegaPort::PORT_B) { + _PORTB._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_C) { + _PORTC._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_D) { + _PORTD._PORT.setValue(info.pinidx, state == HIGH); + } + #elif defined(__AVR_TRM04__) + if (info.port == eATmegaPort::PORT_A) { + _PORTA._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_B) { + _PORTB._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_C) { + _PORTC._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_D) { + _PORTD._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_E) { + _PORTE._PORT.setValue(info.pinidx, state == HIGH); + } + else if (info.port == eATmegaPort::PORT_F) { + _PORTF._PORT.setValue(info.pinidx, state == HIGH); + } + #endif +} + +inline int _ATmega_digitalRead(int pin) { + int value = LOW; + + if (pin < 0) return value; + + ATmegaPinInfo info = _ATmega_getPinInfo((unsigned int)pin); + + #ifdef __AVR_TRM01__ + if (info.port == eATmegaPort::PORT_A) { + value = _PORTA._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_B) { + value = _PORTB._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_C) { + value = _PORTC._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_D) { + value = _PORTD._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_E) { + value = _PORTE._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_F) { + value = _PORTF._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_G) { + value = _PORTG._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_H) { + value = _PORTH._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_J) { + value = _PORTJ._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_K) { + value = _PORTK._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_L) { + value = _PORTL._PIN.getValue(info.pinidx); + } + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + if (info.port == eATmegaPort::PORT_A) { + value = _PORTA._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_B) { + value = _PORTB._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_C) { + value = _PORTC._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_D) { + value = _PORTD._PIN.getValue(info.pinidx); + } + #elif defined(__AVR_TRM03__) + if (info.port == eATmegaPort::PORT_B) { + value = _PORTB._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_C) { + value = _PORTC._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_D) { + value = _PORTD._PIN.getValue(info.pinidx); + } + #elif defined(__AVR_TRM04__) + if (info.port == eATmegaPort::PORT_A) { + value = _PORTA._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_B) { + value = _PORTB._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_C) { + value = _PORTC._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_D) { + value = _PORTD._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_E) { + value = _PORTE._PIN.getValue(info.pinidx); + } + else if (info.port == eATmegaPort::PORT_F) { + value = _PORTF._PIN.getValue(info.pinidx); + } + #endif + + return value; +} + +#ifndef OUTPUT + #define OUTPUT 1 +#endif +#ifndef INPUT + #define INPUT 0 +#endif + +inline void _ATmega_pinMode(int pin, int mode) { + if (pin < 0) return; + + ATmegaPinInfo info = _ATmega_getPinInfo((unsigned int)pin); + + #ifdef __AVR_TRM01__ + if (info.port == eATmegaPort::PORT_A) { + _PORTA._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_B) { + _PORTB._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_C) { + _PORTC._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_D) { + _PORTD._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_E) { + _PORTE._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_F) { + _PORTF._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_G) { + _PORTG._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_H) { + _PORTH._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_J) { + _PORTJ._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_K) { + _PORTK._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_L) { + _PORTL._DDR.setValue(info.pinidx, mode == OUTPUT); + } + #elif defined(__AVR_TRM02__) || defined(__AVR_TRM05__) + if (info.port == eATmegaPort::PORT_A) { + _PORTA._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_B) { + _PORTB._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_C) { + _PORTC._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_D) { + _PORTD._DDR.setValue(info.pinidx, mode == OUTPUT); + } + #elif defined(__AVR_TRM03__) + if (info.port == eATmegaPort::PORT_B) { + _PORTB._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_C) { + _PORTC._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_D) { + _PORTD._DDR.setValue(info.pinidx, mode == OUTPUT); + } + #elif defined(__AVR_TRM04__) + if (info.port == eATmegaPort::PORT_A) { + _PORTA._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_B) { + _PORTB._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_C) { + _PORTC._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_D) { + _PORTD._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_E) { + _PORTE._DDR.setValue(info.pinidx, mode == OUTPUT); + } + else if (info.port == eATmegaPort::PORT_F) { + _PORTF._DDR.setValue(info.pinidx, mode == OUTPUT); + } + #endif +} + +#if defined(__AVR_TRM01__) || defined(__AVR_TRM02__) + struct _ATmega_efuse { + uint8_t _BODLEVEL : 3; + uint8_t reserved1 : 5; + }; + + struct _ATmega_hfuse { + uint8_t _BOOTRST : 1; + uint8_t _BOOTSZ : 2; + uint8_t _EESAVE : 1; + uint8_t _WDTON : 1; + uint8_t _SPIEN : 1; + uint8_t _JTAGEN : 1; + uint8_t _OCDEN : 1; + }; + + struct _ATmega_lfuse { + uint8_t _CKSEL : 4; + uint8_t _SUT0 : 1; + uint8_t _SUT1 : 1; + uint8_t _CKOUT : 1; + uint8_t _CKDIV8 : 1; + }; + + #ifndef AVR_DEFAULT_LFUSE_VALUE + #define AVR_DEFAULT_LFUSE_VALUE 0xFF + #endif + #ifndef AVR_DEFAULT_HFUSE_VALUE + #define AVR_DEFAULT_HFUSE_VALUE 0x99 + #endif + #ifndef AVR_DEFAULT_LFUSE_VALUE + #define AVR_DEFAULT_LFUSE_VALUE 0x62 + #endif + +#elif defined(__AVR_TRM03__) + #if defined(__AVR_ATmega48A__) || defined(__AVR_ATmega48PA__) + struct _ATmega_efuse { + uint8_t _SELFPRGEN : 1; + uint8_t reserved1 : 7; + }; + + #ifndef AVR_DEFAULT_EFUSE_VALUE + #define AVR_DEFAULT_EFUSE_VALUE 0xFF + #endif + + #elif defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88PA__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__) + struct _ATmega_efuse { + uint8_t _BOOTRST : 1; + uint8_t _BOOTSZ : 2; + uint8_t reserved1 : 5; + }; + + #ifndef AVR_DEFAULT_EFUSE_VALUE + #define AVR_DEFAULT_EFUSE_VALUE 0xF9 + #endif + + #else // defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) + struct _ATmega_efuse { + uint8_t _BODLEVEL : 3; + uint8_t reserved1 : 5; + }; + + #ifndef AVR_DEFAULT_EFUSE_VALUE + #define AVR_DEFAULT_EFUSE_VALUE 0xFF + #endif + + #endif + + #if defined(__AVR_ATmega48A__) || defined(__AVR_ATmega48PA__) || defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88PA__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__) + struct _ATmega_hfuse { + uint8_t _BODLEVEL : 3; + uint8_t _EESAVE : 1; + uint8_t _WDTON : 1; + uint8_t _SPIEN : 1; + uint8_t _DWEN : 1; + uint8_t _RSTDISBL : 1; + }; + + #ifndef AVR_DEFAULT_HFUSE_VALUE + #define AVR_DEFAULT_HFUSE_VALUE 0xCF + #endif + + #else // defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) + struct _ATmega_hfuse { + uint8_t _BOOTRST : 1; + uint8_t _BOOTSZ : 2; + uint8_t _EESAVE : 1; + uint8_t _WDTON : 1; + uint8_t _SPIEN : 1; + uint8_t _DWEN : 1; + uint8_t _RSTDISBL : 1; + }; + + #ifndef AVR_DEFAULT_HFUSE_VALUE + #define AVR_DEFAULT_HFUSE_VALUE 0xC9 + #endif + + #endif + + struct _ATmega_lfuse { + uint8_t _CKSEL : 4; + uint8_t _SUT0 : 1; + uint8_t _SUT1 : 1; + uint8_t _CKOUT : 1; + uint8_t _CKDIV8 : 1; + }; + + #ifndef AVR_DEFAULT_LFUSE_VALUE + #define AVR_DEFAULT_LFUSE_VALUE 0xC9 + #endif + +#elif defined(__AVR_TRM04__) + struct _ATmega_efuse { + uint8_t _BODLEVEL : 3; + uint8_t _HWBE : 1; + uint8_t reserved1 : 4; + }; + + struct _ATmega_hfuse { + uint8_t _BOOTRST : 1; + uint8_t _BOOTSZ : 2; + uint8_t _EESAVE : 1; + uint8_t _WDTON : 1; + uint8_t _SPIEN : 1; + uint8_t _JTAGEN : 1; + uint8_t _OCDEN : 1; + }; + + struct _ATmega_lfuse { + uint8_t _CKSEL : 4; + uint8_t _SUT0 : 1; + uint8_t _SUT1 : 1; + uint8_t _CKOUT : 1; + uint8_t _CKDIV8 : 1; + }; + + // Default values if not already defined. + #ifndef AVR_DEFAULT_EFUSE_VALUE + #define AVR_DEFAULT_EFUSE_VALUE 0xF3 + #endif + #ifndef AVR_DEFAULT_HFUSE_VALUE + #define AVR_DEFAULT_HFUSE_VALUE 0x99 + #endif + #ifndef AVR_DEFAULT_LFUSE_VALUE + #define AVR_DEFAULT_LFUSE_VALUE 0x62 + #endif + +#elif defined(__AVR_TRM05__) + struct _ATmega_efuse { + uint8_t _BODLEVEL0 : 1; + uint8_t _BODLEVEL1 : 1; + uint8_t _BODLEVEL2 : 1; + uint8_t reserved1 : 5; + }; + + struct _ATmega_hfuse { + uint8_t _BOOTRST : 1; + uint8_t _BOOTSZ : 2; + uint8_t _EESAVE : 1; + uint8_t _WDTON : 1; + uint8_t _SPIEN : 1; + uint8_t _JTAGEN : 1; + uint8_t _OCDEN : 1; + }; + + struct _ATmega_lfuse { + uint8_t _CKSEL : 4; + uint8_t _SUT0 : 1; + uint8_t _SUT1 : 1; + uint8_t _CKOUT : 1; + uint8_t _CKDIV8 : 1; + }; + + #ifndef AVR_DEFAULT_EFUSE_VALUE + #define AVR_DEFAULT_EFUSE_VALUE 0xFF + #endif + #ifndef AVR_DEFAULT_HFUSE_VALUE + #define AVR_DEFAULT_HFUSE_VALUE 0x88 + #endif + #ifndef AVR_DEFAULT_LFUSE_VALUE + #define AVR_DEFAULT_LFUSE_VALUE 0x62 + #endif +#endif + +struct ATmega_efuse : public _ATmega_efuse { + inline ATmega_efuse(uint8_t val = 0) { *(uint8_t*)this = val; } + inline ATmega_efuse(const ATmega_efuse&) = default; +}; +struct ATmega_hfuse : public _ATmega_hfuse { + inline ATmega_hfuse(uint8_t val = 0) { *(uint8_t*)this = val; } + inline ATmega_hfuse(const ATmega_hfuse&) = default; +}; +struct ATmega_lfuse : public _ATmega_lfuse { + inline ATmega_lfuse(uint8_t val = 0) { *(uint8_t*)this = val; } + inline ATmega_lfuse(const ATmega_lfuse&) = default; +}; diff --git a/Marlin/src/HAL/DUE/endstop_interrupts.h b/Marlin/src/HAL/DUE/endstop_interrupts.h index 28510fb508..954eb625a5 100644 --- a/Marlin/src/HAL/DUE/endstop_interrupts.h +++ b/Marlin/src/HAL/DUE/endstop_interrupts.h @@ -52,7 +52,7 @@ void setup_endstop_interrupts() { TERN_(USE_Y_MAX, _ATTACH(Y_MAX_PIN)); TERN_(USE_Y_MIN, _ATTACH(Y_MIN_PIN)); TERN_(USE_Z_MAX, _ATTACH(Z_MAX_PIN)); - TERN_(HAS_Z_MIN_PIN, _ATTACH(Z_MIN_PIN)); + TERN_(USE_Z_MIN, _ATTACH(Z_MIN_PIN)); TERN_(USE_X2_MAX, _ATTACH(X2_MAX_PIN)); TERN_(USE_X2_MIN, _ATTACH(X2_MIN_PIN)); TERN_(USE_Y2_MAX, _ATTACH(Y2_MAX_PIN)); diff --git a/Marlin/src/HAL/ESP32/endstop_interrupts.h b/Marlin/src/HAL/ESP32/endstop_interrupts.h index 43f4975d46..1377345992 100644 --- a/Marlin/src/HAL/ESP32/endstop_interrupts.h +++ b/Marlin/src/HAL/ESP32/endstop_interrupts.h @@ -47,7 +47,7 @@ void setup_endstop_interrupts() { TERN_(USE_Y_MAX, _ATTACH(Y_MAX_PIN)); TERN_(USE_Y_MIN, _ATTACH(Y_MIN_PIN)); TERN_(USE_Z_MAX, _ATTACH(Z_MAX_PIN)); - TERN_(HAS_Z_MIN_PIN, _ATTACH(Z_MIN_PIN)); + TERN_(USE_Z_MIN, _ATTACH(Z_MIN_PIN)); TERN_(USE_X2_MAX, _ATTACH(X2_MAX_PIN)); TERN_(USE_X2_MIN, _ATTACH(X2_MIN_PIN)); TERN_(USE_Y2_MAX, _ATTACH(Y2_MAX_PIN)); diff --git a/Marlin/src/HAL/LPC1768/HAL.cpp b/Marlin/src/HAL/LPC1768/HAL.cpp index 746f43a2a4..6fada12486 100644 --- a/Marlin/src/HAL/LPC1768/HAL.cpp +++ b/Marlin/src/HAL/LPC1768/HAL.cpp @@ -23,7 +23,17 @@ #include "../../inc/MarlinConfig.h" #include "../shared/Delay.h" -#include "../../../gcode/parser.h" +#include "../../core/millis_t.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include DefaultSerial1 USBSerial(false, UsbSerial); @@ -49,6 +59,132 @@ int freeMemory() { return result; } +extern "C" { + #include + int isLPC1769(); + void disk_timerproc(); +} + +extern uint32_t MSC_SD_Init(uint8_t pdrv); + +void SysTick_Callback() { disk_timerproc(); } + +TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial()); + +void MarlinHAL::init() { + + // Init LEDs + #if PIN_EXISTS(LED) + SET_DIR_OUTPUT(LED_PIN); + WRITE_PIN_CLR(LED_PIN); + #if PIN_EXISTS(LED2) + SET_DIR_OUTPUT(LED2_PIN); + WRITE_PIN_CLR(LED2_PIN); + #if PIN_EXISTS(LED3) + SET_DIR_OUTPUT(LED3_PIN); + WRITE_PIN_CLR(LED3_PIN); + #if PIN_EXISTS(LED4) + SET_DIR_OUTPUT(LED4_PIN); + WRITE_PIN_CLR(LED4_PIN); + #endif + #endif + #endif + + // Flash status LED 3 times to indicate Marlin has started booting + for (uint8_t i = 0; i < 6; ++i) { + TOGGLE(LED_PIN); + delay(100); + } + #endif + + // Init Servo Pins + #define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW) + #if HAS_SERVO_0 + INIT_SERVO(0); + #endif + #if HAS_SERVO_1 + INIT_SERVO(1); + #endif + #if HAS_SERVO_2 + INIT_SERVO(2); + #endif + #if HAS_SERVO_3 + INIT_SERVO(3); + #endif + + //debug_frmwrk_init(); + //_DBG("\n\nDebug running\n"); + // Initialize the SD card chip select pins as soon as possible + #if PIN_EXISTS(SD_SS) + OUT_WRITE(SD_SS_PIN, HIGH); + #endif + + #if PIN_EXISTS(ONBOARD_SD_CS) && ONBOARD_SD_CS_PIN != SD_SS_PIN + OUT_WRITE(ONBOARD_SD_CS_PIN, HIGH); + #endif + + #ifdef LPC1768_ENABLE_CLKOUT_12M + /** + * CLKOUTCFG register + * bit 8 (CLKOUT_EN) = enables CLKOUT signal. Disabled for now to prevent glitch when enabling GPIO. + * bits 7:4 (CLKOUTDIV) = set to 0 for divider setting of /1 + * bits 3:0 (CLKOUTSEL) = set to 1 to select main crystal oscillator as CLKOUT source + */ + LPC_SC->CLKOUTCFG = (0<<8)|(0<<4)|(1<<0); + // set P1.27 pin to function 01 (CLKOUT) + PINSEL_CFG_Type PinCfg; + PinCfg.Portnum = 1; + PinCfg.Pinnum = 27; + PinCfg.Funcnum = 1; // function 01 (CLKOUT) + PinCfg.OpenDrain = 0; // not open drain + PinCfg.Pinmode = 2; // no pull-up/pull-down + PINSEL_ConfigPin(&PinCfg); + // now set CLKOUT_EN bit + SBI(LPC_SC->CLKOUTCFG, 8); + #endif + + USB_Init(); // USB Initialization + USB_Connect(false); // USB clear connection + delay(1000); // Give OS time to notice + USB_Connect(true); + + TERN_(HAS_SD_HOST_DRIVE, MSC_SD_Init(0)); // Enable USB SD card access + + const millis_t usb_timeout = millis() + 2000; + while (!USB_Configuration && PENDING(millis(), usb_timeout)) { + delay(50); + idletask(); + #if PIN_EXISTS(LED) + TOGGLE(LED_PIN); // Flash quickly during USB initialization + #endif + } + + HAL_timer_init(); + + TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler +} + +#include "../../sd/cardreader.h" + +// HAL idle task +void MarlinHAL::idletask() { + #if HAS_SHARED_MEDIA + // If Marlin is using the SD card we need to lock it to prevent access from + // a PC via USB. + // Other HALs use IS_SD_PRINTING() and IS_SD_FILE_OPEN() to check for access but + // this will not reliably detect delete operations. To be safe we will lock + // the disk if Marlin has it mounted. Unfortunately there is currently no way + // to unmount the disk from the LCD menu. + // if (IS_SD_PRINTING() || IS_SD_FILE_OPEN()) + if (card.isMounted()) + MSC_Aquire_Lock(); + else + MSC_Release_Lock(); + #endif + // Perform USB stack housekeeping + MSC_RunDeferredCommands(); +} + void MarlinHAL::reboot() { NVIC_SystemReset(); } uint8_t MarlinHAL::get_reset_source() { @@ -113,6 +249,8 @@ void flashFirmware(const int16_t) { #endif // USE_WATCHDOG +#include "../../../gcode/parser.h" + // For M42/M43, scan command line for pin code // return index into pin map array if found and the pin is valid. // return dval if not found or not a valid pin. diff --git a/Marlin/src/HAL/LPC1768/endstop_interrupts.h b/Marlin/src/HAL/LPC1768/endstop_interrupts.h index cd9de25477..7a67b958b4 100644 --- a/Marlin/src/HAL/LPC1768/endstop_interrupts.h +++ b/Marlin/src/HAL/LPC1768/endstop_interrupts.h @@ -74,7 +74,7 @@ void setup_endstop_interrupts() { #endif _ATTACH(Z_MAX_PIN); #endif - #if HAS_Z_MIN_PIN + #if USE_Z_MIN #if !LPC1768_PIN_INTERRUPT_M(Z_MIN_PIN) #error "Z_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue." #endif diff --git a/Marlin/src/HAL/LPC1768/main.cpp b/Marlin/src/HAL/LPC1768/main.cpp deleted file mode 100644 index 15518c3d86..0000000000 --- a/Marlin/src/HAL/LPC1768/main.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/** - * Marlin 3D Printer Firmware - * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] - * - * Based on Sprinter and grbl. - * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm - * - * 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 - * along with this program. If not, see . - * - */ -#ifdef TARGET_LPC1768 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../inc/MarlinConfig.h" -#include "../../core/millis_t.h" - -#include "../../sd/cardreader.h" - -extern uint32_t MSC_SD_Init(uint8_t pdrv); - -extern "C" { - #include - extern "C" int isLPC1769(); - extern "C" void disk_timerproc(); -} - -void SysTick_Callback() { disk_timerproc(); } - -TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial()); - -void MarlinHAL::init() { - - // Init LEDs - #if PIN_EXISTS(LED) - SET_DIR_OUTPUT(LED_PIN); - WRITE_PIN_CLR(LED_PIN); - #if PIN_EXISTS(LED2) - SET_DIR_OUTPUT(LED2_PIN); - WRITE_PIN_CLR(LED2_PIN); - #if PIN_EXISTS(LED3) - SET_DIR_OUTPUT(LED3_PIN); - WRITE_PIN_CLR(LED3_PIN); - #if PIN_EXISTS(LED4) - SET_DIR_OUTPUT(LED4_PIN); - WRITE_PIN_CLR(LED4_PIN); - #endif - #endif - #endif - - // Flash status LED 3 times to indicate Marlin has started booting - for (uint8_t i = 0; i < 6; ++i) { - TOGGLE(LED_PIN); - delay(100); - } - #endif - - // Init Servo Pins - #define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW) - #if HAS_SERVO_0 - INIT_SERVO(0); - #endif - #if HAS_SERVO_1 - INIT_SERVO(1); - #endif - #if HAS_SERVO_2 - INIT_SERVO(2); - #endif - #if HAS_SERVO_3 - INIT_SERVO(3); - #endif - - //debug_frmwrk_init(); - //_DBG("\n\nDebug running\n"); - // Initialize the SD card chip select pins as soon as possible - #if PIN_EXISTS(SD_SS) - OUT_WRITE(SD_SS_PIN, HIGH); - #endif - - #if PIN_EXISTS(ONBOARD_SD_CS) && ONBOARD_SD_CS_PIN != SD_SS_PIN - OUT_WRITE(ONBOARD_SD_CS_PIN, HIGH); - #endif - - #ifdef LPC1768_ENABLE_CLKOUT_12M - /** - * CLKOUTCFG register - * bit 8 (CLKOUT_EN) = enables CLKOUT signal. Disabled for now to prevent glitch when enabling GPIO. - * bits 7:4 (CLKOUTDIV) = set to 0 for divider setting of /1 - * bits 3:0 (CLKOUTSEL) = set to 1 to select main crystal oscillator as CLKOUT source - */ - LPC_SC->CLKOUTCFG = (0<<8)|(0<<4)|(1<<0); - // set P1.27 pin to function 01 (CLKOUT) - PINSEL_CFG_Type PinCfg; - PinCfg.Portnum = 1; - PinCfg.Pinnum = 27; - PinCfg.Funcnum = 1; // function 01 (CLKOUT) - PinCfg.OpenDrain = 0; // not open drain - PinCfg.Pinmode = 2; // no pull-up/pull-down - PINSEL_ConfigPin(&PinCfg); - // now set CLKOUT_EN bit - SBI(LPC_SC->CLKOUTCFG, 8); - #endif - - USB_Init(); // USB Initialization - USB_Connect(false); // USB clear connection - delay(1000); // Give OS time to notice - USB_Connect(true); - - TERN_(HAS_SD_HOST_DRIVE, MSC_SD_Init(0)); // Enable USB SD card access - - const millis_t usb_timeout = millis() + 2000; - while (!USB_Configuration && PENDING(millis(), usb_timeout)) { - delay(50); - idletask(); - #if PIN_EXISTS(LED) - TOGGLE(LED_PIN); // Flash quickly during USB initialization - #endif - } - - HAL_timer_init(); - - TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler -} - -// HAL idle task -void MarlinHAL::idletask() { - #if HAS_SHARED_MEDIA - // If Marlin is using the SD card we need to lock it to prevent access from - // a PC via USB. - // Other HALs use IS_SD_PRINTING() and IS_SD_FILE_OPEN() to check for access but - // this will not reliably detect delete operations. To be safe we will lock - // the disk if Marlin has it mounted. Unfortunately there is currently no way - // to unmount the disk from the LCD menu. - // if (IS_SD_PRINTING() || IS_SD_FILE_OPEN()) - if (card.isMounted()) - MSC_Aquire_Lock(); - else - MSC_Release_Lock(); - #endif - // Perform USB stack housekeeping - MSC_RunDeferredCommands(); -} - -#endif // TARGET_LPC1768 diff --git a/Marlin/src/HAL/SAMD21/endstop_interrupts.h b/Marlin/src/HAL/SAMD21/endstop_interrupts.h index 31414a39e3..37fdb7504b 100644 --- a/Marlin/src/HAL/SAMD21/endstop_interrupts.h +++ b/Marlin/src/HAL/SAMD21/endstop_interrupts.h @@ -54,34 +54,34 @@ #include "../../module/endstops.h" #define MATCH_EILINE(P1,P2) (P1 != P2 && PIN_TO_EILINE(P1) == PIN_TO_EILINE(P2)) -#define MATCH_X_MAX_EILINE(P) TERN0(USE_X_MAX, DEFER4(MATCH_EILINE)(P, X_MAX_PIN)) -#define MATCH_X_MIN_EILINE(P) TERN0(USE_X_MIN, DEFER4(MATCH_EILINE)(P, X_MIN_PIN)) -#define MATCH_Y_MAX_EILINE(P) TERN0(USE_Y_MAX, DEFER4(MATCH_EILINE)(P, Y_MAX_PIN)) -#define MATCH_Y_MIN_EILINE(P) TERN0(USE_Y_MIN, DEFER4(MATCH_EILINE)(P, Y_MIN_PIN)) -#define MATCH_Z_MAX_EILINE(P) TERN0(USE_Z_MAX, DEFER4(MATCH_EILINE)(P, Z_MAX_PIN)) -#define MATCH_Z_MIN_EILINE(P) TERN0(HAS_Z_MIN_PIN, DEFER4(MATCH_EILINE)(P, Z_MIN_PIN)) -#define MATCH_I_MAX_EILINE(P) TERN0(USE_I_MAX, DEFER4(MATCH_EILINE)(P, I_MAX_PIN)) -#define MATCH_I_MIN_EILINE(P) TERN0(USE_I_MIN, DEFER4(MATCH_EILINE)(P, I_MIN_PIN)) -#define MATCH_J_MAX_EILINE(P) TERN0(USE_J_MAX, DEFER4(MATCH_EILINE)(P, J_MAX_PIN)) -#define MATCH_J_MIN_EILINE(P) TERN0(USE_J_MIN, DEFER4(MATCH_EILINE)(P, J_MIN_PIN)) -#define MATCH_K_MAX_EILINE(P) TERN0(USE_K_MAX, DEFER4(MATCH_EILINE)(P, K_MAX_PIN)) -#define MATCH_K_MIN_EILINE(P) TERN0(USE_K_MIN, DEFER4(MATCH_EILINE)(P, K_MIN_PIN)) -#define MATCH_U_MAX_EILINE(P) TERN0(USE_U_MAX, DEFER4(MATCH_EILINE)(P, U_MAX_PIN)) -#define MATCH_U_MIN_EILINE(P) TERN0(USE_U_MIN, DEFER4(MATCH_EILINE)(P, U_MIN_PIN)) -#define MATCH_V_MAX_EILINE(P) TERN0(USE_V_MAX, DEFER4(MATCH_EILINE)(P, V_MAX_PIN)) -#define MATCH_V_MIN_EILINE(P) TERN0(USE_V_MIN, DEFER4(MATCH_EILINE)(P, V_MIN_PIN)) -#define MATCH_W_MAX_EILINE(P) TERN0(USE_W_MAX, DEFER4(MATCH_EILINE)(P, W_MAX_PIN)) -#define MATCH_W_MIN_EILINE(P) TERN0(USE_W_MIN, DEFER4(MATCH_EILINE)(P, W_MIN_PIN)) -#define MATCH_X2_MAX_EILINE(P) TERN0(USE_X2_MAX, DEFER4(MATCH_EILINE)(P, X2_MAX_PIN)) -#define MATCH_X2_MIN_EILINE(P) TERN0(USE_X2_MIN, DEFER4(MATCH_EILINE)(P, X2_MIN_PIN)) -#define MATCH_Y2_MAX_EILINE(P) TERN0(USE_Y2_MAX, DEFER4(MATCH_EILINE)(P, Y2_MAX_PIN)) -#define MATCH_Y2_MIN_EILINE(P) TERN0(USE_Y2_MIN, DEFER4(MATCH_EILINE)(P, Y2_MIN_PIN)) -#define MATCH_Z2_MAX_EILINE(P) TERN0(USE_Z2_MAX, DEFER4(MATCH_EILINE)(P, Z2_MAX_PIN)) -#define MATCH_Z2_MIN_EILINE(P) TERN0(USE_Z2_MIN, DEFER4(MATCH_EILINE)(P, Z2_MIN_PIN)) -#define MATCH_Z3_MAX_EILINE(P) TERN0(USE_Z3_MAX, DEFER4(MATCH_EILINE)(P, Z3_MAX_PIN)) -#define MATCH_Z3_MIN_EILINE(P) TERN0(USE_Z3_MIN, DEFER4(MATCH_EILINE)(P, Z3_MIN_PIN)) -#define MATCH_Z4_MAX_EILINE(P) TERN0(USE_Z4_MAX, DEFER4(MATCH_EILINE)(P, Z4_MAX_PIN)) -#define MATCH_Z4_MIN_EILINE(P) TERN0(USE_Z4_MIN, DEFER4(MATCH_EILINE)(P, Z4_MIN_PIN)) +#define MATCH_X_MAX_EILINE(P) TERN0(USE_X_MAX, DEFER4(MATCH_EILINE)(P, X_MAX_PIN)) +#define MATCH_X_MIN_EILINE(P) TERN0(USE_X_MIN, DEFER4(MATCH_EILINE)(P, X_MIN_PIN)) +#define MATCH_Y_MAX_EILINE(P) TERN0(USE_Y_MAX, DEFER4(MATCH_EILINE)(P, Y_MAX_PIN)) +#define MATCH_Y_MIN_EILINE(P) TERN0(USE_Y_MIN, DEFER4(MATCH_EILINE)(P, Y_MIN_PIN)) +#define MATCH_Z_MAX_EILINE(P) TERN0(USE_Z_MAX, DEFER4(MATCH_EILINE)(P, Z_MAX_PIN)) +#define MATCH_Z_MIN_EILINE(P) TERN0(USE_Z_MIN, DEFER4(MATCH_EILINE)(P, Z_MIN_PIN)) +#define MATCH_I_MAX_EILINE(P) TERN0(USE_I_MAX, DEFER4(MATCH_EILINE)(P, I_MAX_PIN)) +#define MATCH_I_MIN_EILINE(P) TERN0(USE_I_MIN, DEFER4(MATCH_EILINE)(P, I_MIN_PIN)) +#define MATCH_J_MAX_EILINE(P) TERN0(USE_J_MAX, DEFER4(MATCH_EILINE)(P, J_MAX_PIN)) +#define MATCH_J_MIN_EILINE(P) TERN0(USE_J_MIN, DEFER4(MATCH_EILINE)(P, J_MIN_PIN)) +#define MATCH_K_MAX_EILINE(P) TERN0(USE_K_MAX, DEFER4(MATCH_EILINE)(P, K_MAX_PIN)) +#define MATCH_K_MIN_EILINE(P) TERN0(USE_K_MIN, DEFER4(MATCH_EILINE)(P, K_MIN_PIN)) +#define MATCH_U_MAX_EILINE(P) TERN0(USE_U_MAX, DEFER4(MATCH_EILINE)(P, U_MAX_PIN)) +#define MATCH_U_MIN_EILINE(P) TERN0(USE_U_MIN, DEFER4(MATCH_EILINE)(P, U_MIN_PIN)) +#define MATCH_V_MAX_EILINE(P) TERN0(USE_V_MAX, DEFER4(MATCH_EILINE)(P, V_MAX_PIN)) +#define MATCH_V_MIN_EILINE(P) TERN0(USE_V_MIN, DEFER4(MATCH_EILINE)(P, V_MIN_PIN)) +#define MATCH_W_MAX_EILINE(P) TERN0(USE_W_MAX, DEFER4(MATCH_EILINE)(P, W_MAX_PIN)) +#define MATCH_W_MIN_EILINE(P) TERN0(USE_W_MIN, DEFER4(MATCH_EILINE)(P, W_MIN_PIN)) +#define MATCH_X2_MAX_EILINE(P) TERN0(USE_X2_MAX, DEFER4(MATCH_EILINE)(P, X2_MAX_PIN)) +#define MATCH_X2_MIN_EILINE(P) TERN0(USE_X2_MIN, DEFER4(MATCH_EILINE)(P, X2_MIN_PIN)) +#define MATCH_Y2_MAX_EILINE(P) TERN0(USE_Y2_MAX, DEFER4(MATCH_EILINE)(P, Y2_MAX_PIN)) +#define MATCH_Y2_MIN_EILINE(P) TERN0(USE_Y2_MIN, DEFER4(MATCH_EILINE)(P, Y2_MIN_PIN)) +#define MATCH_Z2_MAX_EILINE(P) TERN0(USE_Z2_MAX, DEFER4(MATCH_EILINE)(P, Z2_MAX_PIN)) +#define MATCH_Z2_MIN_EILINE(P) TERN0(USE_Z2_MIN, DEFER4(MATCH_EILINE)(P, Z2_MIN_PIN)) +#define MATCH_Z3_MAX_EILINE(P) TERN0(USE_Z3_MAX, DEFER4(MATCH_EILINE)(P, Z3_MAX_PIN)) +#define MATCH_Z3_MIN_EILINE(P) TERN0(USE_Z3_MIN, DEFER4(MATCH_EILINE)(P, Z3_MIN_PIN)) +#define MATCH_Z4_MAX_EILINE(P) TERN0(USE_Z4_MAX, DEFER4(MATCH_EILINE)(P, Z4_MAX_PIN)) +#define MATCH_Z4_MIN_EILINE(P) TERN0(USE_Z4_MIN, DEFER4(MATCH_EILINE)(P, Z4_MIN_PIN)) #define MATCH_Z_MIN_PROBE_EILINE(P) TERN0(USE_Z_MIN_PROBE, DEFER4(MATCH_EILINE)(P, Z_MIN_PROBE_PIN)) #define AVAILABLE_EILINE(P) ( PIN_TO_EILINE(P) != -1 \ @@ -136,7 +136,7 @@ void setup_endstop_interrupts() { #endif _ATTACH(Z_MAX_PIN); #endif - #if HAS_Z_MIN_PIN + #if USE_Z_MIN #if !AVAILABLE_EILINE(Z_MIN_PIN) #error "Z_MIN_PIN has no EXTINT line available. Disable ENDSTOP_INTERRUPTS_FEATURE to continue." #endif diff --git a/Marlin/src/HAL/SAMD51/endstop_interrupts.h b/Marlin/src/HAL/SAMD51/endstop_interrupts.h index 40f78baf87..84b6c46da9 100644 --- a/Marlin/src/HAL/SAMD51/endstop_interrupts.h +++ b/Marlin/src/HAL/SAMD51/endstop_interrupts.h @@ -53,34 +53,34 @@ #include "../../module/endstops.h" #define MATCH_EILINE(P1,P2) (P1 != P2 && PIN_TO_EILINE(P1) == PIN_TO_EILINE(P2)) -#define MATCH_X_MAX_EILINE(P) TERN0(USE_X_MAX, DEFER4(MATCH_EILINE)(P, X_MAX_PIN)) -#define MATCH_X_MIN_EILINE(P) TERN0(USE_X_MIN, DEFER4(MATCH_EILINE)(P, X_MIN_PIN)) -#define MATCH_Y_MAX_EILINE(P) TERN0(USE_Y_MAX, DEFER4(MATCH_EILINE)(P, Y_MAX_PIN)) -#define MATCH_Y_MIN_EILINE(P) TERN0(USE_Y_MIN, DEFER4(MATCH_EILINE)(P, Y_MIN_PIN)) -#define MATCH_Z_MAX_EILINE(P) TERN0(USE_Z_MAX, DEFER4(MATCH_EILINE)(P, Z_MAX_PIN)) -#define MATCH_Z_MIN_EILINE(P) TERN0(HAS_Z_MIN_PIN, DEFER4(MATCH_EILINE)(P, Z_MIN_PIN)) -#define MATCH_I_MAX_EILINE(P) TERN0(USE_I_MAX, DEFER4(MATCH_EILINE)(P, I_MAX_PIN)) -#define MATCH_I_MIN_EILINE(P) TERN0(USE_I_MIN, DEFER4(MATCH_EILINE)(P, I_MIN_PIN)) -#define MATCH_J_MAX_EILINE(P) TERN0(USE_J_MAX, DEFER4(MATCH_EILINE)(P, J_MAX_PIN)) -#define MATCH_J_MIN_EILINE(P) TERN0(USE_J_MIN, DEFER4(MATCH_EILINE)(P, J_MIN_PIN)) -#define MATCH_K_MAX_EILINE(P) TERN0(USE_K_MAX, DEFER4(MATCH_EILINE)(P, K_MAX_PIN)) -#define MATCH_K_MIN_EILINE(P) TERN0(USE_K_MIN, DEFER4(MATCH_EILINE)(P, K_MIN_PIN)) -#define MATCH_U_MAX_EILINE(P) TERN0(USE_U_MAX, DEFER4(MATCH_EILINE)(P, U_MAX_PIN)) -#define MATCH_U_MIN_EILINE(P) TERN0(USE_U_MIN, DEFER4(MATCH_EILINE)(P, U_MIN_PIN)) -#define MATCH_V_MAX_EILINE(P) TERN0(USE_V_MAX, DEFER4(MATCH_EILINE)(P, V_MAX_PIN)) -#define MATCH_V_MIN_EILINE(P) TERN0(USE_V_MIN, DEFER4(MATCH_EILINE)(P, V_MIN_PIN)) -#define MATCH_W_MAX_EILINE(P) TERN0(USE_W_MAX, DEFER4(MATCH_EILINE)(P, W_MAX_PIN)) -#define MATCH_W_MIN_EILINE(P) TERN0(USE_W_MIN, DEFER4(MATCH_EILINE)(P, W_MIN_PIN)) -#define MATCH_X2_MAX_EILINE(P) TERN0(USE_X2_MAX, DEFER4(MATCH_EILINE)(P, X2_MAX_PIN)) -#define MATCH_X2_MIN_EILINE(P) TERN0(USE_X2_MIN, DEFER4(MATCH_EILINE)(P, X2_MIN_PIN)) -#define MATCH_Y2_MAX_EILINE(P) TERN0(USE_Y2_MAX, DEFER4(MATCH_EILINE)(P, Y2_MAX_PIN)) -#define MATCH_Y2_MIN_EILINE(P) TERN0(USE_Y2_MIN, DEFER4(MATCH_EILINE)(P, Y2_MIN_PIN)) -#define MATCH_Z2_MAX_EILINE(P) TERN0(USE_Z2_MAX, DEFER4(MATCH_EILINE)(P, Z2_MAX_PIN)) -#define MATCH_Z2_MIN_EILINE(P) TERN0(USE_Z2_MIN, DEFER4(MATCH_EILINE)(P, Z2_MIN_PIN)) -#define MATCH_Z3_MAX_EILINE(P) TERN0(USE_Z3_MAX, DEFER4(MATCH_EILINE)(P, Z3_MAX_PIN)) -#define MATCH_Z3_MIN_EILINE(P) TERN0(USE_Z3_MIN, DEFER4(MATCH_EILINE)(P, Z3_MIN_PIN)) -#define MATCH_Z4_MAX_EILINE(P) TERN0(USE_Z4_MAX, DEFER4(MATCH_EILINE)(P, Z4_MAX_PIN)) -#define MATCH_Z4_MIN_EILINE(P) TERN0(USE_Z4_MIN, DEFER4(MATCH_EILINE)(P, Z4_MIN_PIN)) +#define MATCH_X_MAX_EILINE(P) TERN0(USE_X_MAX, DEFER4(MATCH_EILINE)(P, X_MAX_PIN)) +#define MATCH_X_MIN_EILINE(P) TERN0(USE_X_MIN, DEFER4(MATCH_EILINE)(P, X_MIN_PIN)) +#define MATCH_Y_MAX_EILINE(P) TERN0(USE_Y_MAX, DEFER4(MATCH_EILINE)(P, Y_MAX_PIN)) +#define MATCH_Y_MIN_EILINE(P) TERN0(USE_Y_MIN, DEFER4(MATCH_EILINE)(P, Y_MIN_PIN)) +#define MATCH_Z_MAX_EILINE(P) TERN0(USE_Z_MAX, DEFER4(MATCH_EILINE)(P, Z_MAX_PIN)) +#define MATCH_Z_MIN_EILINE(P) TERN0(USE_Z_MIN, DEFER4(MATCH_EILINE)(P, Z_MIN_PIN)) +#define MATCH_I_MAX_EILINE(P) TERN0(USE_I_MAX, DEFER4(MATCH_EILINE)(P, I_MAX_PIN)) +#define MATCH_I_MIN_EILINE(P) TERN0(USE_I_MIN, DEFER4(MATCH_EILINE)(P, I_MIN_PIN)) +#define MATCH_J_MAX_EILINE(P) TERN0(USE_J_MAX, DEFER4(MATCH_EILINE)(P, J_MAX_PIN)) +#define MATCH_J_MIN_EILINE(P) TERN0(USE_J_MIN, DEFER4(MATCH_EILINE)(P, J_MIN_PIN)) +#define MATCH_K_MAX_EILINE(P) TERN0(USE_K_MAX, DEFER4(MATCH_EILINE)(P, K_MAX_PIN)) +#define MATCH_K_MIN_EILINE(P) TERN0(USE_K_MIN, DEFER4(MATCH_EILINE)(P, K_MIN_PIN)) +#define MATCH_U_MAX_EILINE(P) TERN0(USE_U_MAX, DEFER4(MATCH_EILINE)(P, U_MAX_PIN)) +#define MATCH_U_MIN_EILINE(P) TERN0(USE_U_MIN, DEFER4(MATCH_EILINE)(P, U_MIN_PIN)) +#define MATCH_V_MAX_EILINE(P) TERN0(USE_V_MAX, DEFER4(MATCH_EILINE)(P, V_MAX_PIN)) +#define MATCH_V_MIN_EILINE(P) TERN0(USE_V_MIN, DEFER4(MATCH_EILINE)(P, V_MIN_PIN)) +#define MATCH_W_MAX_EILINE(P) TERN0(USE_W_MAX, DEFER4(MATCH_EILINE)(P, W_MAX_PIN)) +#define MATCH_W_MIN_EILINE(P) TERN0(USE_W_MIN, DEFER4(MATCH_EILINE)(P, W_MIN_PIN)) +#define MATCH_X2_MAX_EILINE(P) TERN0(USE_X2_MAX, DEFER4(MATCH_EILINE)(P, X2_MAX_PIN)) +#define MATCH_X2_MIN_EILINE(P) TERN0(USE_X2_MIN, DEFER4(MATCH_EILINE)(P, X2_MIN_PIN)) +#define MATCH_Y2_MAX_EILINE(P) TERN0(USE_Y2_MAX, DEFER4(MATCH_EILINE)(P, Y2_MAX_PIN)) +#define MATCH_Y2_MIN_EILINE(P) TERN0(USE_Y2_MIN, DEFER4(MATCH_EILINE)(P, Y2_MIN_PIN)) +#define MATCH_Z2_MAX_EILINE(P) TERN0(USE_Z2_MAX, DEFER4(MATCH_EILINE)(P, Z2_MAX_PIN)) +#define MATCH_Z2_MIN_EILINE(P) TERN0(USE_Z2_MIN, DEFER4(MATCH_EILINE)(P, Z2_MIN_PIN)) +#define MATCH_Z3_MAX_EILINE(P) TERN0(USE_Z3_MAX, DEFER4(MATCH_EILINE)(P, Z3_MAX_PIN)) +#define MATCH_Z3_MIN_EILINE(P) TERN0(USE_Z3_MIN, DEFER4(MATCH_EILINE)(P, Z3_MIN_PIN)) +#define MATCH_Z4_MAX_EILINE(P) TERN0(USE_Z4_MAX, DEFER4(MATCH_EILINE)(P, Z4_MAX_PIN)) +#define MATCH_Z4_MIN_EILINE(P) TERN0(USE_Z4_MIN, DEFER4(MATCH_EILINE)(P, Z4_MIN_PIN)) #define MATCH_Z_MIN_PROBE_EILINE(P) TERN0(USE_Z_MIN_PROBE, DEFER4(MATCH_EILINE)(P, Z_MIN_PROBE_PIN)) #define AVAILABLE_EILINE(P) ( PIN_TO_EILINE(P) != -1 \ @@ -135,7 +135,7 @@ void setup_endstop_interrupts() { #endif _ATTACH(Z_MAX_PIN); #endif - #if HAS_Z_MIN_PIN + #if USE_Z_MIN #if !AVAILABLE_EILINE(Z_MIN_PIN) #error "Z_MIN_PIN has no EXTINT line available. Disable ENDSTOP_INTERRUPTS_FEATURE to continue." #endif diff --git a/Marlin/src/HAL/STM32/HAL.h b/Marlin/src/HAL/STM32/HAL.h index 013390fcaf..37a718b08d 100644 --- a/Marlin/src/HAL/STM32/HAL.h +++ b/Marlin/src/HAL/STM32/HAL.h @@ -57,61 +57,61 @@ #define _MSERIAL(X) MSerial##X #define MSERIAL(X) _MSERIAL(X) -#if WITHIN(SERIAL_PORT, 1, 6) +#if WITHIN(SERIAL_PORT, 1, 9) #define MYSERIAL1 MSERIAL(SERIAL_PORT) #elif !defined(USBCON) - #error "SERIAL_PORT must be from 1 to 6." + #error "SERIAL_PORT must be from 1 to 9." #elif SERIAL_PORT == -1 #define MYSERIAL1 MSerialUSB #else - #error "SERIAL_PORT must be from 1 to 6, or -1 for Native USB." + #error "SERIAL_PORT must be from 1 to 9, or -1 for Native USB." #endif #ifdef SERIAL_PORT_2 - #if WITHIN(SERIAL_PORT_2, 1, 6) + #if WITHIN(SERIAL_PORT_2, 1, 9) #define MYSERIAL2 MSERIAL(SERIAL_PORT_2) #elif !defined(USBCON) - #error "SERIAL_PORT_2 must be from 1 to 6." + #error "SERIAL_PORT_2 must be from 1 to 9." #elif SERIAL_PORT_2 == -1 #define MYSERIAL2 MSerialUSB #else - #error "SERIAL_PORT_2 must be from 1 to 6, or -1 for Native USB." + #error "SERIAL_PORT_2 must be from 1 to 9, or -1 for Native USB." #endif #endif #ifdef SERIAL_PORT_3 - #if WITHIN(SERIAL_PORT_3, 1, 6) + #if WITHIN(SERIAL_PORT_3, 1, 9) #define MYSERIAL3 MSERIAL(SERIAL_PORT_3) #elif !defined(USBCON) - #error "SERIAL_PORT_3 must be from 1 to 6." + #error "SERIAL_PORT_3 must be from 1 to 9." #elif SERIAL_PORT_3 == -1 #define MYSERIAL3 MSerialUSB #else - #error "SERIAL_PORT_3 must be from 1 to 6, or -1 for Native USB." + #error "SERIAL_PORT_3 must be from 1 to 9, or -1 for Native USB." #endif #endif #ifdef MMU2_SERIAL_PORT - #if WITHIN(MMU2_SERIAL_PORT, 1, 6) + #if WITHIN(MMU2_SERIAL_PORT, 1, 9) #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT) #elif !defined(USBCON) - #error "MMU2_SERIAL_PORT must be from 1 to 6." + #error "MMU2_SERIAL_PORT must be from 1 to 9." #elif MMU2_SERIAL_PORT == -1 #define MMU2_SERIAL MSerialUSB #else - #error "MMU2_SERIAL_PORT must be from 1 to 6, or -1 for Native USB." + #error "MMU2_SERIAL_PORT must be from 1 to 9, or -1 for Native USB." #endif #endif #ifdef LCD_SERIAL_PORT - #if WITHIN(LCD_SERIAL_PORT, 1, 6) + #if WITHIN(LCD_SERIAL_PORT, 1, 9) #define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT) #elif !defined(USBCON) - #error "LCD_SERIAL_PORT must be from 1 to 6." + #error "LCD_SERIAL_PORT must be from 1 to 9." #elif LCD_SERIAL_PORT == -1 #define LCD_SERIAL MSerialUSB #else - #error "LCD_SERIAL_PORT must be from 1 to 6, or -1 for Native USB." + #error "LCD_SERIAL_PORT must be from 1 to 9, or -1 for Native USB." #endif #if HAS_DGUS_LCD #define LCD_SERIAL_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite() diff --git a/Marlin/src/HAL/STM32/MarlinSerial.cpp b/Marlin/src/HAL/STM32/MarlinSerial.cpp index 37a8f40fd0..9f0b003a31 100644 --- a/Marlin/src/HAL/STM32/MarlinSerial.cpp +++ b/Marlin/src/HAL/STM32/MarlinSerial.cpp @@ -37,6 +37,15 @@ #ifndef USART5 #define USART5 UART5 #endif +#ifndef USART7 + #define USART7 UART7 +#endif +#ifndef USART8 + #define USART8 UART8 +#endif +#ifndef USART9 + #define USART9 UART9 +#endif #define DECLARE_SERIAL_PORT(ser_num) \ void _rx_complete_irq_ ## ser_num (serial_t * obj); \ diff --git a/Marlin/src/HAL/STM32/MinSerial.cpp b/Marlin/src/HAL/STM32/MinSerial.cpp index c2260f4f26..f1fc806acb 100644 --- a/Marlin/src/HAL/STM32/MinSerial.cpp +++ b/Marlin/src/HAL/STM32/MinSerial.cpp @@ -45,7 +45,7 @@ struct USARTMin { volatile uint32_t CR2; }; -#if WITHIN(SERIAL_PORT, 1, 6) +#if WITHIN(SERIAL_PORT, 1, 9) // Depending on the CPU, the serial port is different for USART1 static const uintptr_t regsAddr[] = { TERN(STM32F1xx, 0x40013800, 0x40011000), // USART1 @@ -54,6 +54,9 @@ struct USARTMin { 0x40004C00, // UART4_BASE 0x40005000, // UART5_BASE 0x40011400 // USART6 + 0x40007800 // UART7_BASE + 0x40007C00 // UART8_BASE + 0x40011800 // UART9_BASE }; static USARTMin * regs = (USARTMin*)regsAddr[SERIAL_PORT - 1]; #endif @@ -116,7 +119,7 @@ static void TXBegin() { // A SW memory barrier, to ensure GCC does not overoptimize loops #define sw_barrier() __asm__ volatile("": : :"memory"); static void TX(char c) { - #if WITHIN(SERIAL_PORT, 1, 6) + #if WITHIN(SERIAL_PORT, 1, 9) constexpr uint32_t usart_sr_txe = _BV(7); while (!(regs->SR & usart_sr_txe)) { hal.watchdog_refresh(); diff --git a/Marlin/src/HAL/STM32/endstop_interrupts.h b/Marlin/src/HAL/STM32/endstop_interrupts.h index 5ae228d3f8..0c92053d42 100644 --- a/Marlin/src/HAL/STM32/endstop_interrupts.h +++ b/Marlin/src/HAL/STM32/endstop_interrupts.h @@ -34,7 +34,7 @@ void setup_endstop_interrupts() { TERN_(USE_Y_MAX, _ATTACH(Y_MAX_PIN)); TERN_(USE_Y_MIN, _ATTACH(Y_MIN_PIN)); TERN_(USE_Z_MAX, _ATTACH(Z_MAX_PIN)); - TERN_(HAS_Z_MIN_PIN, _ATTACH(Z_MIN_PIN)); + TERN_(USE_Z_MIN, _ATTACH(Z_MIN_PIN)); TERN_(USE_X2_MAX, _ATTACH(X2_MAX_PIN)); TERN_(USE_X2_MIN, _ATTACH(X2_MIN_PIN)); TERN_(USE_Y2_MAX, _ATTACH(Y2_MAX_PIN)); diff --git a/Marlin/src/HAL/STM32F1/endstop_interrupts.h b/Marlin/src/HAL/STM32F1/endstop_interrupts.h index 6febcec5d0..6ed920183b 100644 --- a/Marlin/src/HAL/STM32F1/endstop_interrupts.h +++ b/Marlin/src/HAL/STM32F1/endstop_interrupts.h @@ -59,7 +59,7 @@ void setup_endstop_interrupts() { TERN_(USE_Y_MAX, _ATTACH(Y_MAX_PIN)); TERN_(USE_Y_MIN, _ATTACH(Y_MIN_PIN)); TERN_(USE_Z_MAX, _ATTACH(Z_MAX_PIN)); - TERN_(HAS_Z_MIN_PIN, _ATTACH(Z_MIN_PIN)); + TERN_(USE_Z_MIN, _ATTACH(Z_MIN_PIN)); TERN_(USE_X2_MAX, _ATTACH(X2_MAX_PIN)); TERN_(USE_X2_MIN, _ATTACH(X2_MIN_PIN)); TERN_(USE_Y2_MAX, _ATTACH(Y2_MAX_PIN)); diff --git a/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h b/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h index 28510fb508..954eb625a5 100644 --- a/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h +++ b/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h @@ -52,7 +52,7 @@ void setup_endstop_interrupts() { TERN_(USE_Y_MAX, _ATTACH(Y_MAX_PIN)); TERN_(USE_Y_MIN, _ATTACH(Y_MIN_PIN)); TERN_(USE_Z_MAX, _ATTACH(Z_MAX_PIN)); - TERN_(HAS_Z_MIN_PIN, _ATTACH(Z_MIN_PIN)); + TERN_(USE_Z_MIN, _ATTACH(Z_MIN_PIN)); TERN_(USE_X2_MAX, _ATTACH(X2_MAX_PIN)); TERN_(USE_X2_MIN, _ATTACH(X2_MIN_PIN)); TERN_(USE_Y2_MAX, _ATTACH(Y2_MAX_PIN)); diff --git a/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h b/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h index 505434cd89..bc8e177fb7 100644 --- a/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h +++ b/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h @@ -51,7 +51,7 @@ void setup_endstop_interrupts() { TERN_(USE_Y_MAX, _ATTACH(Y_MAX_PIN)); TERN_(USE_Y_MIN, _ATTACH(Y_MIN_PIN)); TERN_(USE_Z_MAX, _ATTACH(Z_MAX_PIN)); - TERN_(HAS_Z_MIN_PIN, _ATTACH(Z_MIN_PIN)); + TERN_(USE_Z_MIN, _ATTACH(Z_MIN_PIN)); TERN_(USE_X2_MAX, _ATTACH(X2_MAX_PIN)); TERN_(USE_X2_MIN, _ATTACH(X2_MIN_PIN)); TERN_(USE_Y2_MAX, _ATTACH(Y2_MAX_PIN)); diff --git a/Marlin/src/HAL/TEENSY40_41/endstop_interrupts.h b/Marlin/src/HAL/TEENSY40_41/endstop_interrupts.h index 325d97daeb..722912c890 100644 --- a/Marlin/src/HAL/TEENSY40_41/endstop_interrupts.h +++ b/Marlin/src/HAL/TEENSY40_41/endstop_interrupts.h @@ -51,7 +51,7 @@ void setup_endstop_interrupts() { TERN_(USE_Y_MAX, _ATTACH(Y_MAX_PIN)); TERN_(USE_Y_MIN, _ATTACH(Y_MIN_PIN)); TERN_(USE_Z_MAX, _ATTACH(Z_MAX_PIN)); - TERN_(HAS_Z_MIN_PIN, _ATTACH(Z_MIN_PIN)); + TERN_(USE_Z_MIN, _ATTACH(Z_MIN_PIN)); TERN_(USE_X2_MAX, _ATTACH(X2_MAX_PIN)); TERN_(USE_X2_MIN, _ATTACH(X2_MIN_PIN)); TERN_(USE_Y2_MAX, _ATTACH(Y2_MAX_PIN)); diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index b76a3d301c..649f05cf69 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -249,6 +249,8 @@ #define STR_LASER_TEMP "laser temperature" #define STR_STOPPED_HEATER ", system stopped! Heater_ID: " +#define STR_DETECTED_TEMP_B " (temp: " +#define STR_DETECTED_TEMP_E ")" #define STR_REDUNDANCY "Heater switched off. Temperature difference between temp sensors is too high !" #define STR_T_HEATING_FAILED "Heating failed" #define STR_T_THERMAL_RUNAWAY "Thermal Runaway" diff --git a/Marlin/src/feature/hotend_idle.cpp b/Marlin/src/feature/hotend_idle.cpp index f64fe7e3cf..050898e3b5 100644 --- a/Marlin/src/feature/hotend_idle.cpp +++ b/Marlin/src/feature/hotend_idle.cpp @@ -55,15 +55,15 @@ void HotendIdleProtection::check_hotends(const millis_t &ms) { if (!do_prot) next_protect_ms = 0; // No hotends are hot so cancel timeout else if (!next_protect_ms) // Timeout is possible? - next_protect_ms = ms + cfg.timeout * 1000; // Start timeout if not already set + next_protect_ms = ms + 1000UL * cfg.timeout; // Start timeout if not already set } void HotendIdleProtection::check_e_motion(const millis_t &ms) { static float old_e_position = 0; if (old_e_position != current_position.e) { - old_e_position = current_position.e; // Track filament motion - if (next_protect_ms) // If some heater is on then... - next_protect_ms = ms + cfg.timeout * 1000; // ...delay the timeout till later + old_e_position = current_position.e; // Track filament motion + if (next_protect_ms) // If some heater is on then... + next_protect_ms = ms + 1000UL * cfg.timeout; // ...delay the timeout till later } } diff --git a/Marlin/src/feature/runout.cpp b/Marlin/src/feature/runout.cpp index 7c7d61e7eb..90d3d2fd65 100644 --- a/Marlin/src/feature/runout.cpp +++ b/Marlin/src/feature/runout.cpp @@ -47,7 +47,7 @@ bool FilamentMonitorBase::enabled = true, #if HAS_FILAMENT_RUNOUT_DISTANCE float RunoutResponseDelayed::runout_distance_mm = FILAMENT_RUNOUT_DISTANCE_MM; - volatile countdown_t RunoutResponseDelayed::mm_countdown; + countdown_t RunoutResponseDelayed::mm_countdown; #if ENABLED(FILAMENT_MOTION_SENSOR) uint8_t FilamentSensorEncoder::motion_detected; #endif diff --git a/Marlin/src/feature/runout.h b/Marlin/src/feature/runout.h index a001459e9d..847413d25a 100644 --- a/Marlin/src/feature/runout.h +++ b/Marlin/src/feature/runout.h @@ -30,7 +30,8 @@ #include "../module/planner.h" #include "../module/stepper.h" // for block_t #include "../gcode/queue.h" -#include "../feature/pause.h" +#include "../feature/pause.h" // for did_pause_print +#include "../MarlinCore.h" // for printingIsActive() #include "../inc/MarlinConfig.h" @@ -50,9 +51,16 @@ #define HAS_FILAMENT_SWITCH 1 #endif -typedef Flags<8> runout_flags_t; +typedef Flags< + #if NUM_MOTION_SENSORS > NUM_RUNOUT_SENSORS + NUM_MOTION_SENSORS + #else + NUM_RUNOUT_SENSORS + #endif + > runout_flags_t; void event_filament_runout(const uint8_t extruder); +inline bool should_monitor_runout() { return did_pause_print || printingIsActive(); } template class TFilamentMonitor; @@ -128,7 +136,7 @@ class TFilamentMonitor : public FilamentMonitorBase { // Give the response a chance to update its counter. static void run() { - if (enabled && !filament_ran_out && (printingIsActive() || did_pause_print)) { + if (enabled && !filament_ran_out && should_monitor_runout()) { TERN_(HAS_FILAMENT_RUNOUT_DISTANCE, cli()); // Prevent RunoutResponseDelayed::block_completed from accumulating here response.run(); sensor.run(); @@ -340,8 +348,10 @@ class FilamentSensorBase { typedef struct { float runout[NUM_RUNOUT_SENSORS]; + Flags runout_reset; // Reset runout later #if ENABLED(FILAMENT_SWITCH_AND_MOTION) float motion[NUM_MOTION_SENSORS]; + Flags motion_reset; // Reset motion later #endif } countdown_t; @@ -350,7 +360,7 @@ class FilamentSensorBase { // during a runout condition. class RunoutResponseDelayed { private: - static volatile countdown_t mm_countdown; + static countdown_t mm_countdown; public: static float runout_distance_mm; @@ -389,26 +399,56 @@ class FilamentSensorBase { } static void filament_present(const uint8_t extruder) { - mm_countdown.runout[extruder] = runout_distance_mm; + if (mm_countdown.runout[extruder] < runout_distance_mm || did_pause_print) { + // Reset runout only if it is smaller than runout_distance or printing is paused. + // On Bowden systems retract may be larger than runout_distance_mm, so if retract + // was added leave it in place, or the following unretract will cause runout event. + mm_countdown.runout[extruder] = runout_distance_mm; + mm_countdown.runout_reset.clear(extruder); + } + else { + // If runout is larger than runout distance, we cannot reset right now, as Bowden and retract + // distance larger than runout_distance_mm leads to negative runout right after unretract. + // But we cannot ignore filament_present event. After unretract, runout will become smaller + // than runout_distance_mm and should be reset after that. So activate delayed reset. + mm_countdown.runout_reset.set(extruder); + } } #if ENABLED(FILAMENT_SWITCH_AND_MOTION) static void filament_motion_present(const uint8_t extruder) { - mm_countdown.motion[extruder] = runout_distance_mm; + // Same logic as filament_present + if (mm_countdown.motion[extruder] < runout_distance_mm || did_pause_print) { + mm_countdown.motion[extruder] = runout_distance_mm; + mm_countdown.motion_reset.clear(extruder); + } + else + mm_countdown.motion_reset.set(extruder); } #endif static void block_completed(const block_t * const b) { - if (b->steps.x || b->steps.y || b->steps.z || did_pause_print) { // Allow pause purge move to re-trigger runout state - // Only trigger on extrusion with XYZ movement to allow filament change and retract/recover. - const uint8_t e = b->extruder; - const int32_t steps = b->steps.e; - const float mm = (b->direction_bits.e ? steps : -steps) * planner.mm_per_step[E_AXIS_N(e)]; - if (e < NUM_RUNOUT_SENSORS) mm_countdown.runout[e] -= mm; - #if ENABLED(FILAMENT_SWITCH_AND_MOTION) - if (e < NUM_MOTION_SENSORS) mm_countdown.motion[e] -= mm; - #endif + const int32_t esteps = b->steps.e; + if (!esteps) return; + + // No calculation unless paused or printing + if (!should_monitor_runout()) return; + + // No need to ignore retract/unretract movement since they complement each other + const uint8_t e = b->extruder; + const float mm = (b->direction_bits.e ? esteps : -esteps) * planner.mm_per_step[E_AXIS_N(e)]; + + if (e < NUM_RUNOUT_SENSORS) { + mm_countdown.runout[e] -= mm; + if (mm_countdown.runout_reset[e]) filament_present(e); // Reset pending. Try to reset. } + + #if ENABLED(FILAMENT_SWITCH_AND_MOTION) + if (e < NUM_MOTION_SENSORS) { + mm_countdown.motion[e] -= mm; + if (mm_countdown.motion_reset[e]) filament_motion_present(e); // Reset pending. Try to reset. + } + #endif } }; diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp index b364c0382c..fd034f0ba6 100644 --- a/Marlin/src/gcode/calibrate/G28.cpp +++ b/Marlin/src/gcode/calibrate/G28.cpp @@ -254,69 +254,67 @@ void GcodeSuite::G28() { // Reset to the XY plane TERN_(CNC_WORKSPACE_PLANES, workspace_plane = PLANE_XY); - #define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT) - #if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(X2) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Y2) || (ENABLED(DELTA) && 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 _OR_HAS_CURR_HOME(N) HAS_CURRENT_HOME(N) || + #if MAIN_AXIS_MAP(_OR_HAS_CURR_HOME) MAP(_OR_HAS_CURR_HOME, X2, Y2, Z2, Z3, Z4) 0 #define HAS_HOMING_CURRENT 1 #endif #if HAS_HOMING_CURRENT - auto debug_current = [](FSTR_P const s, const int16_t a, const int16_t b) { - DEBUG_ECHOLN(s, F(" current: "), a, F(" -> "), b); - }; + + #if ENABLED(DEBUG_LEVELING_FEATURE) + auto debug_current = [](FSTR_P const s, const int16_t a, const int16_t b) { + if (DEBUGGING(LEVELING)) { DEBUG_ECHOF(s); DEBUG_ECHOLNPGM(" current: ", a, " -> ", b); } + }; + #else + #define debug_current(...) + #endif + + #define _SAVE_SET_CURRENT(A) \ + const int16_t saved_current_##A = stepper##A.getMilliamps(); \ + stepper##A.rms_current(A##_CURRENT_HOME); \ + debug_current(F(STR_##A), saved_current_##A, A##_CURRENT_HOME) + #if HAS_CURRENT_HOME(X) - const int16_t tmc_save_current_X = stepperX.getMilliamps(); - stepperX.rms_current(X_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_X), tmc_save_current_X, X_CURRENT_HOME); + _SAVE_SET_CURRENT(X); #endif #if HAS_CURRENT_HOME(X2) - const int16_t tmc_save_current_X2 = stepperX2.getMilliamps(); - stepperX2.rms_current(X2_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_X2), tmc_save_current_X2, X2_CURRENT_HOME); + _SAVE_SET_CURRENT(X2); #endif #if HAS_CURRENT_HOME(Y) - const int16_t tmc_save_current_Y = stepperY.getMilliamps(); - stepperY.rms_current(Y_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_Y), tmc_save_current_Y, Y_CURRENT_HOME); + _SAVE_SET_CURRENT(Y); #endif #if HAS_CURRENT_HOME(Y2) - const int16_t tmc_save_current_Y2 = stepperY2.getMilliamps(); - stepperY2.rms_current(Y2_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_Y2), tmc_save_current_Y2, Y2_CURRENT_HOME); + _SAVE_SET_CURRENT(Y2); #endif - #if HAS_CURRENT_HOME(Z) && ENABLED(DELTA) - const int16_t tmc_save_current_Z = stepperZ.getMilliamps(); - stepperZ.rms_current(Z_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_Z), tmc_save_current_Z, Z_CURRENT_HOME); + #if HAS_CURRENT_HOME(Z) + _SAVE_SET_CURRENT(Z); + #endif + #if HAS_CURRENT_HOME(Z2) + _SAVE_SET_CURRENT(Z2); + #endif + #if HAS_CURRENT_HOME(Z3) + _SAVE_SET_CURRENT(Z3); + #endif + #if HAS_CURRENT_HOME(Z4) + _SAVE_SET_CURRENT(Z4); #endif #if HAS_CURRENT_HOME(I) - const int16_t tmc_save_current_I = stepperI.getMilliamps(); - stepperI.rms_current(I_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_I), tmc_save_current_I, I_CURRENT_HOME); + _SAVE_SET_CURRENT(I); #endif #if HAS_CURRENT_HOME(J) - const int16_t tmc_save_current_J = stepperJ.getMilliamps(); - stepperJ.rms_current(J_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_J), tmc_save_current_J, J_CURRENT_HOME); + _SAVE_SET_CURRENT(J); #endif #if HAS_CURRENT_HOME(K) - const int16_t tmc_save_current_K = stepperK.getMilliamps(); - stepperK.rms_current(K_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_K), tmc_save_current_K, K_CURRENT_HOME); + _SAVE_SET_CURRENT(K); #endif #if HAS_CURRENT_HOME(U) - const int16_t tmc_save_current_U = stepperU.getMilliamps(); - stepperU.rms_current(U_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_U), tmc_save_current_U, U_CURRENT_HOME); + _SAVE_SET_CURRENT(U); #endif #if HAS_CURRENT_HOME(V) - const int16_t tmc_save_current_V = stepperV.getMilliamps(); - stepperV.rms_current(V_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_V), tmc_save_current_V, V_CURRENT_HOME); + _SAVE_SET_CURRENT(V); #endif #if HAS_CURRENT_HOME(W) - const int16_t tmc_save_current_W = stepperW.getMilliamps(); - stepperW.rms_current(W_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_W), tmc_save_current_W, W_CURRENT_HOME); + _SAVE_SET_CURRENT(W); #endif #if SENSORLESS_STALLGUARD_DELAY safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle @@ -577,37 +575,46 @@ void GcodeSuite::G28() { #if HAS_HOMING_CURRENT if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Restore driver current..."); #if HAS_CURRENT_HOME(X) - stepperX.rms_current(tmc_save_current_X); + stepperX.rms_current(saved_current_X); #endif #if HAS_CURRENT_HOME(X2) - stepperX2.rms_current(tmc_save_current_X2); + stepperX2.rms_current(saved_current_X2); #endif #if HAS_CURRENT_HOME(Y) - stepperY.rms_current(tmc_save_current_Y); + stepperY.rms_current(saved_current_Y); #endif #if HAS_CURRENT_HOME(Y2) - stepperY2.rms_current(tmc_save_current_Y2); + stepperY2.rms_current(saved_current_Y2); #endif - #if HAS_CURRENT_HOME(Z) && ENABLED(DELTA) - stepperZ.rms_current(tmc_save_current_Z); + #if HAS_CURRENT_HOME(Z) + stepperZ.rms_current(saved_current_Z); + #endif + #if HAS_CURRENT_HOME(Z2) + stepperZ2.rms_current(saved_current_Z2); + #endif + #if HAS_CURRENT_HOME(Z3) + stepperZ3.rms_current(saved_current_Z3); + #endif + #if HAS_CURRENT_HOME(Z4) + stepperZ4.rms_current(saved_current_Z4); #endif #if HAS_CURRENT_HOME(I) - stepperI.rms_current(tmc_save_current_I); + stepperI.rms_current(saved_current_I); #endif #if HAS_CURRENT_HOME(J) - stepperJ.rms_current(tmc_save_current_J); + stepperJ.rms_current(saved_current_J); #endif #if HAS_CURRENT_HOME(K) - stepperK.rms_current(tmc_save_current_K); + stepperK.rms_current(saved_current_K); #endif #if HAS_CURRENT_HOME(U) - stepperU.rms_current(tmc_save_current_U); + stepperU.rms_current(saved_current_U); #endif #if HAS_CURRENT_HOME(V) - stepperV.rms_current(tmc_save_current_V); + stepperV.rms_current(saved_current_V); #endif #if HAS_CURRENT_HOME(W) - stepperW.rms_current(tmc_save_current_W); + stepperW.rms_current(saved_current_W); #endif #if SENSORLESS_STALLGUARD_DELAY safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle diff --git a/Marlin/src/gcode/calibrate/G33.cpp b/Marlin/src/gcode/calibrate/G33.cpp index 7530737dde..10f5afca2d 100644 --- a/Marlin/src/gcode/calibrate/G33.cpp +++ b/Marlin/src/gcode/calibrate/G33.cpp @@ -67,9 +67,9 @@ float lcd_probe_pt(const xy_pos_t &xy); void ac_home() { endstops.enable(true); - TERN_(SENSORLESS_HOMING, endstops.set_homing_current(true)); + TERN_(SENSORLESS_HOMING, endstops.set_z_sensorless_current(true)); home_delta(); - TERN_(SENSORLESS_HOMING, endstops.set_homing_current(false)); + TERN_(SENSORLESS_HOMING, endstops.set_z_sensorless_current(false)); endstops.not_homing(); } diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h index 084a3d74e9..b069e2d2b1 100644 --- a/Marlin/src/inc/Conditionals_LCD.h +++ b/Marlin/src/inc/Conditionals_LCD.h @@ -1422,24 +1422,26 @@ * Conditionals based on the type of Bed Probe */ #if HAS_BED_PROBE + #if ALL(DELTA, SENSORLESS_PROBING) + #define HAS_DELTA_SENSORLESS_PROBING 1 + #else + #define HAS_REAL_BED_PROBE 1 + #endif + #if HAS_REAL_BED_PROBE && NONE(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, Z_SPI_SENSORLESS) + #define NEED_Z_MIN_PROBE_PIN 1 + #endif + #if Z_HOME_TO_MIN && (!NEED_Z_MIN_PROBE_PIN || ENABLED(USE_PROBE_FOR_Z_HOMING)) + #define HOMING_Z_WITH_PROBE 1 + #endif #if DISABLED(NOZZLE_AS_PROBE) #define HAS_PROBE_XY_OFFSET 1 #endif - #if ALL(DELTA, SENSORLESS_PROBING) - #define HAS_DELTA_SENSORLESS_PROBING 1 - #endif - #if NONE(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, HAS_DELTA_SENSORLESS_PROBING) - #define USE_Z_MIN_PROBE 1 - #endif - #if Z_HOME_TO_MIN && (DISABLED(USE_Z_MIN_PROBE) || ENABLED(USE_PROBE_FOR_Z_HOMING)) - #define HOMING_Z_WITH_PROBE 1 + #if ANY(Z_PROBE_ALLEN_KEY, MAG_MOUNTED_PROBE) + #define PROBE_TRIGGERED_WHEN_STOWED_TEST 1 // Extra test for Allen Key Probe #endif #ifndef Z_PROBE_LOW_POINT #define Z_PROBE_LOW_POINT -5 #endif - #if ANY(Z_PROBE_ALLEN_KEY, MAG_MOUNTED_PROBE) - #define PROBE_TRIGGERED_WHEN_STOWED_TEST 1 // Extra test for Allen Key Probe - #endif #if MULTIPLE_PROBING > 1 #if EXTRA_PROBING > 0 #define TOTAL_PROBING (MULTIPLE_PROBING + EXTRA_PROBING) diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index 442fcfbafd..13f20114e5 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -1424,13 +1424,13 @@ #if AXIS_IS_TMC(X) #if defined(X_STALL_SENSITIVITY) && AXIS_HAS_STALLGUARD(X) #define X_SENSORLESS 1 + #if ENABLED(SPI_ENDSTOPS) && AXIS_HAS_SPI(X) + #define X_SPI_SENSORLESS 1 + #endif #endif #if AXIS_HAS_STEALTHCHOP(X) #define X_HAS_STEALTHCHOP 1 #endif - #if ENABLED(SPI_ENDSTOPS) - #define X_SPI_SENSORLESS X_SENSORLESS - #endif #ifndef X_INTERPOLATE #define X_INTERPOLATE INTERPOLATE #endif @@ -1462,13 +1462,13 @@ #if AXIS_IS_TMC(Y) #if defined(Y_STALL_SENSITIVITY) && AXIS_HAS_STALLGUARD(Y) #define Y_SENSORLESS 1 + #if ENABLED(SPI_ENDSTOPS) && AXIS_HAS_SPI(Y) + #define Y_SPI_SENSORLESS 1 + #endif #endif #if AXIS_HAS_STEALTHCHOP(Y) #define Y_HAS_STEALTHCHOP 1 #endif - #if ENABLED(SPI_ENDSTOPS) - #define Y_SPI_SENSORLESS Y_SENSORLESS - #endif #ifndef Y_INTERPOLATE #define Y_INTERPOLATE INTERPOLATE #endif @@ -1500,13 +1500,13 @@ #if AXIS_IS_TMC(Z) #if defined(Z_STALL_SENSITIVITY) && AXIS_HAS_STALLGUARD(Z) #define Z_SENSORLESS 1 + #if ENABLED(SPI_ENDSTOPS) && AXIS_HAS_SPI(Z) + #define Z_SPI_SENSORLESS 1 + #endif #endif #if AXIS_HAS_STEALTHCHOP(Z) #define Z_HAS_STEALTHCHOP 1 #endif - #if ENABLED(SPI_ENDSTOPS) - #define Z_SPI_SENSORLESS Z_SENSORLESS - #endif #ifndef Z_INTERPOLATE #define Z_INTERPOLATE INTERPOLATE #endif @@ -1572,13 +1572,13 @@ #if AXIS_IS_TMC(I) #if defined(I_STALL_SENSITIVITY) && AXIS_HAS_STALLGUARD(I) #define I_SENSORLESS 1 + #if ENABLED(SPI_ENDSTOPS) && AXIS_HAS_SPI(I) + #define I_SPI_SENSORLESS 1 + #endif #endif #if AXIS_HAS_STEALTHCHOP(I) #define I_HAS_STEALTHCHOP 1 #endif - #if ENABLED(SPI_ENDSTOPS) - #define I_SPI_SENSORLESS I_SENSORLESS - #endif #ifndef I_INTERPOLATE #define I_INTERPOLATE INTERPOLATE #endif @@ -1593,13 +1593,13 @@ #if AXIS_IS_TMC(J) #if defined(J_STALL_SENSITIVITY) && AXIS_HAS_STALLGUARD(J) #define J_SENSORLESS 1 + #if ENABLED(SPI_ENDSTOPS) && AXIS_HAS_SPI(J) + #define J_SPI_SENSORLESS 1 + #endif #endif #if AXIS_HAS_STEALTHCHOP(J) #define J_HAS_STEALTHCHOP 1 #endif - #if ENABLED(SPI_ENDSTOPS) - #define J_SPI_SENSORLESS J_SENSORLESS - #endif #ifndef J_INTERPOLATE #define J_INTERPOLATE INTERPOLATE #endif @@ -1614,13 +1614,13 @@ #if AXIS_IS_TMC(K) #if defined(K_STALL_SENSITIVITY) && AXIS_HAS_STALLGUARD(K) #define K_SENSORLESS 1 + #if ENABLED(SPI_ENDSTOPS) && AXIS_HAS_SPI(K) + #define K_SPI_SENSORLESS 1 + #endif #endif #if AXIS_HAS_STEALTHCHOP(K) #define K_HAS_STEALTHCHOP 1 #endif - #if ENABLED(SPI_ENDSTOPS) - #define K_SPI_SENSORLESS K_SENSORLESS - #endif #ifndef K_INTERPOLATE #define K_INTERPOLATE INTERPOLATE #endif @@ -1635,13 +1635,13 @@ #if AXIS_IS_TMC(U) #if defined(U_STALL_SENSITIVITY) && AXIS_HAS_STALLGUARD(U) #define U_SENSORLESS 1 + #if ENABLED(SPI_ENDSTOPS) && AXIS_HAS_SPI(U) + #define U_SPI_SENSORLESS 1 + #endif #endif #if AXIS_HAS_STEALTHCHOP(U) #define U_HAS_STEALTHCHOP 1 #endif - #if ENABLED(SPI_ENDSTOPS) - #define U_SPI_SENSORLESS U_SENSORLESS - #endif #ifndef U_INTERPOLATE #define U_INTERPOLATE INTERPOLATE #endif @@ -1656,13 +1656,13 @@ #if AXIS_IS_TMC(V) #if defined(V_STALL_SENSITIVITY) && AXIS_HAS_STALLGUARD(V) #define V_SENSORLESS 1 + #if ENABLED(SPI_ENDSTOPS) && AXIS_HAS_SPI(V) + #define V_SPI_SENSORLESS 1 + #endif #endif #if AXIS_HAS_STEALTHCHOP(V) #define V_HAS_STEALTHCHOP 1 #endif - #if ENABLED(SPI_ENDSTOPS) - #define V_SPI_SENSORLESS V_SENSORLESS - #endif #ifndef V_INTERPOLATE #define V_INTERPOLATE INTERPOLATE #endif @@ -1677,13 +1677,13 @@ #if AXIS_IS_TMC(W) #if defined(W_STALL_SENSITIVITY) && AXIS_HAS_STALLGUARD(W) #define W_SENSORLESS 1 + #if ENABLED(SPI_ENDSTOPS) && AXIS_HAS_SPI(W) + #define W_SPI_SENSORLESS 1 + #endif #endif #if AXIS_HAS_STEALTHCHOP(W) #define W_HAS_STEALTHCHOP 1 #endif - #if ENABLED(SPI_ENDSTOPS) - #define W_SPI_SENSORLESS W_SENSORLESS - #endif #ifndef W_INTERPOLATE #define W_INTERPOLATE INTERPOLATE #endif @@ -1948,11 +1948,18 @@ #endif #endif -// -// Endstops and bed probe -// - -#define _USE_STOP(A,N,M,C) ((A##_HOME_TO_##M || (C+0)) && PIN_EXISTS(A##N##_##M)) +/** + * Endstop and probe flags + * - Set USE_(AXIS)_(MIN|MAX) flags for each used endstop that has a pin, including those for DIAG0 state. + * - Note: Dual X Carriage uses "X" and "X2" steppers, but X_MIN and X_MAX endstop states (i.e., not X2_MAX). + * - Set a HAS_(AXIS)_(MIN|MAX)_STATE flag for each endstop that has a state, including SPI Sensorless which don't use a pin. + * - Set a HAS_(AXIS)_STATE flag for each axis that has at least one state. + * - Consider (AXIS)_SAFETY_STOP for the case where the axis has a second endstop. + * Currently this must be distinct, but we can add a mechanism to use the same pin for sensorless + * or switches wired to the same pin, or for the single SPI stall state on the axis. + */ +#define _USE_STOP(A,N,M,C) ((ANY(A##_HOME_TO_##M, A##N##_SAFETY_STOP) || (C+0)) && PIN_EXISTS(A##N##_##M) && !A##_SPI_SENSORLESS) +#define _HAS_STATE(A,N,M) (USE_##A##N##_##M || (ANY(A##_HOME_TO_##M, A##N##_SAFETY_STOP) && A##_SPI_SENSORLESS)) #if _USE_STOP(X,,MIN,) #define USE_X_MIN 1 @@ -1960,139 +1967,239 @@ #if _USE_STOP(X,,MAX,ENABLED(DUAL_X_CARRIAGE)) #define USE_X_MAX 1 #endif -#if USE_X_MIN || USE_X_MAX - #define HAS_X_ENDSTOP 1 +#if _HAS_STATE(X,,MIN) + #define HAS_X_MIN_STATE 1 +#endif +#if _HAS_STATE(X,,MAX) + #define HAS_X_MAX_STATE 1 +#endif +#if HAS_X_MIN_STATE || HAS_X_MAX_STATE + #define HAS_X_STATE 1 #endif #if _USE_STOP(Y,,MIN,) #define USE_Y_MIN 1 -#elif _USE_STOP(Y,,MAX,) +#endif +#if _USE_STOP(Y,,MAX,) #define USE_Y_MAX 1 #endif -#if USE_Y_MIN || USE_Y_MAX - #define HAS_Y_ENDSTOP 1 +#if _HAS_STATE(Y,,MIN) + #define HAS_Y_MIN_STATE 1 +#endif +#if _HAS_STATE(Y,,MAX) + #define HAS_Y_MAX_STATE 1 +#endif +#if HAS_Y_MIN_STATE || HAS_Y_MAX_STATE + #define HAS_Y_STATE 1 #endif -#if _USE_STOP(Z,,MIN,ANY(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, HAS_DELTA_SENSORLESS_PROBING)) +#if _USE_STOP(Z,,MIN,ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)) #define USE_Z_MIN 1 - #if !HAS_DELTA_SENSORLESS_PROBING - #define HAS_Z_MIN_PIN 1 - #endif #endif #if _USE_STOP(Z,,MAX,) #define USE_Z_MAX 1 #endif -#if USE_Z_MIN || USE_Z_MAX - #define HAS_Z_ENDSTOP 1 +#if _HAS_STATE(Z,,MIN) + #define HAS_Z_MIN_STATE 1 +#endif +#if _HAS_STATE(Z,,MAX) + #define HAS_Z_MAX_STATE 1 +#endif +#if HAS_Z_MIN_STATE || HAS_Z_MAX_STATE + #define HAS_Z_STATE 1 #endif #if _USE_STOP(I,,MIN,) #define USE_I_MIN 1 -#elif _USE_STOP(I,,MAX,) +#endif +#if _USE_STOP(I,,MAX,) #define USE_I_MAX 1 #endif -#if USE_I_MIN || USE_I_MAX - #define HAS_I_ENDSTOP 1 +#if _HAS_STATE(I,,MIN) + #define HAS_I_MIN_STATE 1 +#endif +#if _HAS_STATE(I,,MAX) + #define HAS_I_MAX_STATE 1 +#endif +#if HAS_I_MIN_STATE || HAS_I_MAX_STATE + #define HAS_I_STATE 1 #endif #if _USE_STOP(J,,MIN,) #define USE_J_MIN 1 -#elif _USE_STOP(J,,MAX,) +#endif +#if _USE_STOP(J,,MAX,) #define USE_J_MAX 1 #endif -#if USE_J_MIN || USE_J_MAX - #define HAS_J_ENDSTOP 1 +#if _HAS_STATE(J,,MIN) + #define HAS_J_MIN_STATE 1 +#endif +#if _HAS_STATE(J,,MAX) + #define HAS_J_MAX_STATE 1 +#endif +#if HAS_J_MIN_STATE || HAS_J_MAX_STATE + #define HAS_J_STATE 1 #endif #if _USE_STOP(K,,MIN,) #define USE_K_MIN 1 -#elif _USE_STOP(K,,MAX,) +#endif +#if _USE_STOP(K,,MAX,) #define USE_K_MAX 1 #endif -#if USE_K_MIN || USE_K_MAX - #define HAS_K_ENDSTOP 1 +#if _HAS_STATE(K,,MIN) + #define HAS_K_MIN_STATE 1 +#endif +#if _HAS_STATE(K,,MAX) + #define HAS_K_MAX_STATE 1 +#endif +#if HAS_K_MIN_STATE || HAS_K_MAX_STATE + #define HAS_K_STATE 1 #endif #if _USE_STOP(U,,MIN,) #define USE_U_MIN 1 -#elif _USE_STOP(U,,MAX,) +#endif +#if _USE_STOP(U,,MAX,) #define USE_U_MAX 1 #endif -#if USE_U_MIN || USE_U_MAX - #define HAS_U_ENDSTOP 1 +#if _HAS_STATE(U,,MIN) + #define HAS_U_MIN_STATE 1 +#endif +#if _HAS_STATE(U,,MAX) + #define HAS_U_MAX_STATE 1 +#endif +#if HAS_U_MIN_STATE || HAS_U_MAX_STATE + #define HAS_U_STATE 1 #endif #if _USE_STOP(V,,MIN,) #define USE_V_MIN 1 -#elif _USE_STOP(V,,MAX,) +#endif +#if _USE_STOP(V,,MAX,) #define USE_V_MAX 1 #endif -#if USE_V_MIN || USE_V_MAX - #define HAS_V_ENDSTOP 1 +#if _HAS_STATE(V,,MIN) + #define HAS_V_MIN_STATE 1 +#endif +#if _HAS_STATE(V,,MAX) + #define HAS_V_MAX_STATE 1 +#endif +#if HAS_V_MIN_STATE || HAS_V_MAX_STATE + #define HAS_V_STATE 1 #endif #if _USE_STOP(W,,MIN,) #define USE_W_MIN 1 -#elif _USE_STOP(W,,MAX,) +#endif +#if _USE_STOP(W,,MAX,) #define USE_W_MAX 1 #endif -#if USE_W_MIN || USE_W_MAX - #define HAS_W_ENDSTOP 1 +#if _HAS_STATE(W,,MIN) + #define HAS_W_MIN_STATE 1 +#endif +#if _HAS_STATE(W,,MAX) + #define HAS_W_MAX_STATE 1 +#endif +#if HAS_W_MIN_STATE || HAS_W_MAX_STATE + #define HAS_W_STATE 1 #endif -#if ANY(DUAL_X_CARRIAGE, X_DUAL_ENDSTOPS) +#if ENABLED(X_DUAL_ENDSTOPS) #if _USE_STOP(X,2,MIN,) #define USE_X2_MIN 1 - #elif _USE_STOP(X,2,MAX,) + #endif + #if _USE_STOP(X,2,MAX,) #define USE_X2_MAX 1 #endif - #if USE_X2_MIN || USE_X2_MAX - #define HAS_X2_ENDSTOP 1 + #if _HAS_STATE(X,2,MIN) || HAS_X_MIN_STATE + #define HAS_X2_MIN_STATE 1 + #endif + #if _HAS_STATE(X,2,MAX) || HAS_X_MAX_STATE + #define HAS_X2_MAX_STATE 1 + #endif + #if HAS_X2_MIN_STATE || HAS_X2_MAX_STATE + #define HAS_X2_STATE 1 #endif #endif #if ENABLED(Y_DUAL_ENDSTOPS) #if _USE_STOP(Y,2,MIN,) #define USE_Y2_MIN 1 - #elif _USE_STOP(Y,2,MAX,) + #endif + #if _USE_STOP(Y,2,MAX,) #define USE_Y2_MAX 1 #endif - #if USE_Y2_MIN || USE_Y2_MAX - #define HAS_Y2_ENDSTOP 1 + #if _HAS_STATE(Y,2,MIN) || HAS_Y_MIN_STATE + #define HAS_Y2_MIN_STATE 1 + #endif + #if _HAS_STATE(Y,2,MAX) || HAS_Y_MAX_STATE + #define HAS_Y2_MAX_STATE 1 + #endif + #if HAS_Y2_MIN_STATE || HAS_Y2_MAX_STATE + #define HAS_Y2_STATE 1 #endif #endif #if ENABLED(Z_MULTI_ENDSTOPS) #if _USE_STOP(Z,2,MIN,) #define USE_Z2_MIN 1 - #elif _USE_STOP(Z,2,MAX,) + #endif + #if _USE_STOP(Z,2,MAX,) #define USE_Z2_MAX 1 #endif - #if USE_Z2_MIN || USE_Z2_MAX - #define HAS_Z2_ENDSTOP 1 + #if _HAS_STATE(Z,2,MIN) || HAS_Z_MIN_STATE + #define HAS_Z2_MIN_STATE 1 + #endif + #if _HAS_STATE(Z,2,MAX) || HAS_Z_MAX_STATE + #define HAS_Z2_MAX_STATE 1 + #endif + #if HAS_Z2_MIN_STATE || HAS_Z2_MAX_STATE + #define HAS_Z2_STATE 1 #endif #if NUM_Z_STEPPERS >= 3 #if _USE_STOP(Z,3,MIN,) #define USE_Z3_MIN 1 - #elif _USE_STOP(Z,3,MAX,) + #endif + #if _USE_STOP(Z,3,MAX,) #define USE_Z3_MAX 1 #endif - #if USE_Z3_MIN || USE_Z3_MAX - #define HAS_Z3_ENDSTOP 1 + #if _HAS_STATE(Z,3,MIN) || HAS_Z_MIN_STATE + #define HAS_Z3_MIN_STATE 1 + #endif + #if _HAS_STATE(Z,3,MAX) || HAS_Z_MAX_STATE + #define HAS_Z3_MAX_STATE 1 + #endif + #if HAS_Z3_MIN_STATE || HAS_Z3_MAX_STATE + #define HAS_Z3_STATE 1 #endif #endif #if NUM_Z_STEPPERS >= 4 #if _USE_STOP(Z,4,MIN,) #define USE_Z4_MIN 1 - #elif _USE_STOP(Z,4,MAX,) + #endif + #if _USE_STOP(Z,4,MAX,) #define USE_Z4_MAX 1 #endif - #if USE_Z4_MIN || USE_Z4_MAX - #define HAS_Z4_ENDSTOP 1 + #if _HAS_STATE(Z,4,MIN) || HAS_Z_MIN_STATE + #define HAS_Z4_MIN_STATE 1 + #endif + #if _HAS_STATE(Z,4,MAX) || HAS_Z_MAX_STATE + #define HAS_Z4_MAX_STATE 1 + #endif + #if HAS_Z4_MIN_STATE || HAS_Z4_MAX_STATE + #define HAS_Z4_STATE 1 #endif #endif #endif +#if NEED_Z_MIN_PROBE_PIN && PIN_EXISTS(Z_MIN_PROBE) + #define USE_Z_MIN_PROBE 1 +#endif +#if HAS_REAL_BED_PROBE + #define HAS_Z_PROBE_STATE 1 +#endif + #undef _USE_STOP /** @@ -2111,7 +2218,7 @@ #if USE_Y_MAX #define ENDSTOPPULLUP_YMAX #endif - #if HAS_Z_MIN_PIN + #if USE_Z_MIN #define ENDSTOPPULLUP_ZMIN #endif #if USE_Z_MAX diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 8eb8662c32..5933c8c396 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -1388,19 +1388,13 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L /** * Require pin options and pins to be defined */ - #if ENABLED(SENSORLESS_PROBING) - #if ENABLED(DELTA) && !(X_SENSORLESS && Y_SENSORLESS && Z_SENSORLESS) - #error "SENSORLESS_PROBING requires TMC2130/2160/2209/5130/5160 drivers on X, Y, and Z and {X|Y|Z}_STALL_SENSITIVITY." - #elif !Z_SENSORLESS - #error "SENSORLESS_PROBING requires a TMC2130/2160/2209/5130/5160 driver on Z and Z_STALL_SENSITIVITY." - #endif - #elif ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) - #if !HAS_Z_MIN_PIN + #if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) + #if !USE_Z_MIN #error "Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN requires the Z_MIN_PIN to be defined." #elif Z_MIN_PROBE_ENDSTOP_HIT_STATE != Z_MIN_ENDSTOP_HIT_STATE #error "Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN requires Z_MIN_ENDSTOP_HIT_STATE to match Z_MIN_PROBE_ENDSTOP_HIT_STATE." #endif - #elif !USE_Z_MIN_PROBE + #elif !PIN_EXISTS(Z_MIN_PROBE) #error "Z_MIN_PROBE_PIN must be defined if Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN is not enabled." #endif @@ -2323,53 +2317,53 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L /** * Endstop Tests */ -#if HAS_ENDSTOPS - // Delta and Cartesian use 3 homing endstops - #if NONE(IS_SCARA, SPI_ENDSTOPS) - #if X_HOME_TO_MIN && !PIN_EXISTS(X_MIN) - #error "X_MIN_PIN (or X_STOP_PIN) is required for X axis homing." - #elif X_HOME_TO_MAX && !PIN_EXISTS(X_MAX) - #error "X_MAX_PIN (or X_STOP_PIN) is required for X axis homing." - #elif Y_HOME_TO_MIN && !PIN_EXISTS(Y_MIN) - #error "Y_MIN_PIN (or Y_STOP_PIN) is required for Y axis homing." - #elif Y_HOME_TO_MAX && !PIN_EXISTS(Y_MAX) - #error "Y_MAX_PIN (or Y_STOP_PIN) is required for Y axis homing." - #elif I_HOME_TO_MIN && !PIN_EXISTS(I_MIN) - #error "I_MIN_PIN (or I_STOP_PIN) is required for I axis homing." - #elif I_HOME_TO_MAX && !PIN_EXISTS(I_MAX) - #error "I_MAX_PIN (or I_STOP_PIN) is required for I axis homing." - #elif J_HOME_TO_MIN && !PIN_EXISTS(J_MIN) - #error "J_MIN_PIN (or J_STOP_PIN) is required for J axis homing." - #elif J_HOME_TO_MAX && !PIN_EXISTS(J_MAX) - #error "J_MAX_PIN (or J_STOP_PIN) is required for J axis homing." - #elif K_HOME_TO_MIN && !PIN_EXISTS(K_MIN) - #error "K_MIN_PIN (or K_STOP_PIN) is required for K axis homing." - #elif K_HOME_TO_MAX && !PIN_EXISTS(K_MAX) - #error "K_MAX_PIN (or K_STOP_PIN) is required for K axis homing." - #elif U_HOME_TO_MIN && !PIN_EXISTS(U_MIN) - #error "U_MIN_PIN (or U_STOP_PIN) is required for U axis homing." - #elif U_HOME_TO_MAX && !PIN_EXISTS(U_MAX) - #error "U_MAX_PIN (or U_STOP_PIN) is required for U axis homing." - #elif V_HOME_TO_MIN && !PIN_EXISTS(V_MIN) - #error "V_MIN_PIN (or V_STOP_PIN) is required for V axis homing." - #elif V_HOME_TO_MAX && !PIN_EXISTS(V_MAX) - #error "V_MAX_PIN (or V_STOP_PIN) is required for V axis homing." - #elif W_HOME_TO_MIN && !PIN_EXISTS(W_MIN) - #error "W_MIN_PIN (or W_STOP_PIN) is required for W axis homing." - #elif W_HOME_TO_MAX && !PIN_EXISTS(W_MAX) - #error "W_MAX_PIN (or W_STOP_PIN) is required for W axis homing." - #endif - #endif - - // Z homing requirements - #if Z_HOME_TO_MAX && ENABLED(USE_PROBE_FOR_Z_HOMING) - #error "Z_HOME_DIR must be -1 when homing Z with the probe." - #elif ALL(HOMING_Z_WITH_PROBE, Z_MULTI_ENDSTOPS) - #error "Z_MULTI_ENDSTOPS is incompatible with USE_PROBE_FOR_Z_HOMING." +#if !IS_SCARA + // Delta and Cartesian require some kind of endstop + #if X_HOME_TO_MIN && !HAS_X_MIN_STATE + #error "X_MIN_PIN, X_STOP_PIN, or X_SPI_SENSORLESS is required for X axis homing." + #elif X_HOME_TO_MAX && !HAS_X_MAX_STATE + #error "X_MAX_PIN, X_STOP_PIN, or X_SPI_SENSORLESS is required for X axis homing." + #elif Y_HOME_TO_MIN && !HAS_Y_MIN_STATE + #error "Y_MIN_PIN, Y_STOP_PIN, or Y_SPI_SENSORLESS is required for Y axis homing." + #elif Y_HOME_TO_MAX && !HAS_Y_MAX_STATE + #error "Y_MAX_PIN, Y_STOP_PIN, or Y_SPI_SENSORLESS is required for Y axis homing." + #elif Z_HOME_TO_MIN && !HAS_Z_MIN_STATE + #error "Z_MIN_PIN, Z_STOP_PIN, or Z_SPI_SENSORLESS is required for Y axis homing." + #elif Z_HOME_TO_MAX && !HAS_Z_MAX_STATE + #error "Z_MAX_PIN, Z_STOP_PIN, or Z_SPI_SENSORLESS is required for Y axis homing." + #elif I_HOME_TO_MIN && !HAS_I_MIN_STATE + #error "I_MIN_PIN, I_STOP_PIN, or I_SPI_SENSORLESS is required for I axis homing." + #elif I_HOME_TO_MAX && !HAS_I_MAX_STATE + #error "I_MAX_PIN, I_STOP_PIN, or I_SPI_SENSORLESS is required for I axis homing." + #elif J_HOME_TO_MIN && !HAS_J_MIN_STATE + #error "J_MIN_PIN, J_STOP_PIN, or J_SPI_SENSORLESS is required for J axis homing." + #elif J_HOME_TO_MAX && !HAS_J_MAX_STATE + #error "J_MAX_PIN, J_STOP_PIN, or J_SPI_SENSORLESS is required for J axis homing." + #elif K_HOME_TO_MIN && !HAS_K_MIN_STATE + #error "K_MIN_PIN, K_STOP_PIN, or K_SPI_SENSORLESS is required for K axis homing." + #elif K_HOME_TO_MAX && !HAS_K_MAX_STATE + #error "K_MAX_PIN, K_STOP_PIN, or K_SPI_SENSORLESS is required for K axis homing." + #elif U_HOME_TO_MIN && !HAS_U_MIN_STATE + #error "U_MIN_PIN, U_STOP_PIN, or U_SPI_SENSORLESS is required for U axis homing." + #elif U_HOME_TO_MAX && !HAS_U_MAX_STATE + #error "U_MAX_PIN, U_STOP_PIN, or U_SPI_SENSORLESS is required for U axis homing." + #elif V_HOME_TO_MIN && !HAS_V_MIN_STATE + #error "V_MIN_PIN, V_STOP_PIN, or V_SPI_SENSORLESS is required for V axis homing." + #elif V_HOME_TO_MAX && !HAS_V_MAX_STATE + #error "V_MAX_PIN, V_STOP_PIN, or V_SPI_SENSORLESS is required for V axis homing." + #elif W_HOME_TO_MIN && !HAS_W_MIN_STATE + #error "W_MIN_PIN, W_STOP_PIN, or W_SPI_SENSORLESS is required for W axis homing." + #elif W_HOME_TO_MAX && !HAS_W_MAX_STATE + #error "W_MAX_PIN, W_STOP_PIN, or W_SPI_SENSORLESS is required for W axis homing." #endif #endif -#if ALL(HOME_Z_FIRST, USE_PROBE_FOR_Z_HOMING) +// Z homing with probe requirements +#if ALL(HOMING_Z_WITH_PROBE, Z_MULTI_ENDSTOPS) + #error "Z_MULTI_ENDSTOPS is incompatible with USE_PROBE_FOR_Z_HOMING (i.e., Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)." +#elif ALL(USE_PROBE_FOR_Z_HOMING, Z_HOME_TO_MAX) + #error "Z_HOME_DIR must be -1 when homing Z with the probe." +#elif ALL(USE_PROBE_FOR_Z_HOMING, HOME_Z_FIRST) #error "HOME_Z_FIRST can't be used when homing Z with a probe." #endif @@ -2381,26 +2375,32 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L #if ENABLED(X_DUAL_ENDSTOPS) #if ENABLED(DELTA) #error "X_DUAL_ENDSTOPS is not compatible with DELTA." - #elif !HAS_X2_ENDSTOP - #error "X2 Endstop Pin must be defined for X_DUAL_ENDSTOPS." + #elif !HAS_X2_STATE + #error "Some kind of X2 Endstop must be defined for X_DUAL_ENDSTOPS." + #elif X_SPI_SENSORLESS && !AXIS_HAS_SPI(X2) + #error "All X Stepper Drivers must be SPI-capable to use SPI Endstops on X." #endif #endif #if ENABLED(Y_DUAL_ENDSTOPS) #if ENABLED(DELTA) #error "Y_DUAL_ENDSTOPS is not compatible with DELTA." - #elif !HAS_Y2_ENDSTOP - #error "Y2 Endstop Pin must be defined for Y_DUAL_ENDSTOPS." + #elif !HAS_Y2_STATE + #error "Some kind of Y2 Endstop must be defined for Y_DUAL_ENDSTOPS." + #elif Y_SPI_SENSORLESS && !AXIS_HAS_SPI(Y2) + #error "All Y Stepper Drivers must be SPI-capable to use SPI Endstops on Y." #endif #endif #if ENABLED(Z_MULTI_ENDSTOPS) #if ENABLED(DELTA) #error "Z_MULTI_ENDSTOPS is not compatible with DELTA." - #elif !HAS_Z2_ENDSTOP - #error "Z2 Endstop Pin must be defined for Z_MULTI_ENDSTOPS." - #elif NUM_Z_STEPPERS >= 3 && !HAS_Z3_ENDSTOP - #error "Z3 Endstop Pin must be defined for Z_MULTI_ENDSTOPS and Z3_DRIVER_TYPE." - #elif NUM_Z_STEPPERS >= 4 && !HAS_Z4_ENDSTOP - #error "Z4 Endstop Pin must be defined for Z_MULTI_ENDSTOPS and Z4_DRIVER_TYPE." + #elif !HAS_Z2_STATE + #error "Some kind of Z2 Endstop must be defined for Z_MULTI_ENDSTOPS." + #elif NUM_Z_STEPPERS >= 3 && !HAS_Z3_STATE + #error "Some kind of Z3 Endstop must be defined for Z_MULTI_ENDSTOPS and Z3_DRIVER_TYPE." + #elif NUM_Z_STEPPERS >= 4 && !HAS_Z4_STATE + #error "Some kind of Z4 Endstop must be defined for Z_MULTI_ENDSTOPS and Z4_DRIVER_TYPE." + #elif Z_SPI_SENSORLESS && !(AXIS_HAS_SPI(Z2) && (NUM_Z_STEPPERS < 3 || AXIS_HAS_SPI(Z3)) && (NUM_Z_STEPPERS < 4 || AXIS_HAS_SPI(Z4))) + #error "All Z Stepper Drivers must be SPI-capable to use SPI Endstops on Z." #endif #endif diff --git a/Marlin/src/inc/Version.h b/Marlin/src/inc/Version.h index f2ea158af9..a1df5fe90a 100644 --- a/Marlin/src/inc/Version.h +++ b/Marlin/src/inc/Version.h @@ -42,7 +42,7 @@ * version was tagged. */ #ifndef STRING_DISTRIBUTION_DATE - #define STRING_DISTRIBUTION_DATE "2023-07-24" + #define STRING_DISTRIBUTION_DATE "2023-08-04" #endif /** diff --git a/Marlin/src/lcd/HD44780/lcdprint_hd44780.cpp b/Marlin/src/lcd/HD44780/lcdprint_hd44780.cpp index 48f5f97133..b05a8e81d9 100644 --- a/Marlin/src/lcd/HD44780/lcdprint_hd44780.cpp +++ b/Marlin/src/lcd/HD44780/lcdprint_hd44780.cpp @@ -1043,7 +1043,7 @@ int lcd_put_lchar_max(const lchar_t &c, const pixel_len_t max_length) { * @param cb_read_byte : the callback function to read one byte from the utf8_str (from RAM or ROM) * @param max_length : the pixel length of the string allowed (or number of slots in HD44780) * - * @return the number of pixels advanced + * @return the number of characters emitted * * Draw a UTF-8 string */ diff --git a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp index b59ec150a1..897070c4dd 100644 --- a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp +++ b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp @@ -1212,7 +1212,8 @@ void MarlinUI::draw_status_screen() { void MenuEditItemBase::draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char * const inStr, const bool pgm) { const uint8_t vlen = inStr ? (pgm ? utf8_strlen_P(inStr) : utf8_strlen(inStr)) : 0; lcd_put_lchar(0, row, sel ? LCD_STR_ARROW_RIGHT[0] : ' '); - uint8_t n = lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, LCD_WIDTH - 2 - vlen); + uint8_t n = LCD_WIDTH - 2 - vlen; + n -= lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, n); if (vlen) { lcd_put_u8str(F(":")); for (; n; --n) lcd_put_u8str(F(" ")); diff --git a/Marlin/src/lcd/TFTGLCD/lcdprint_TFTGLCD.cpp b/Marlin/src/lcd/TFTGLCD/lcdprint_TFTGLCD.cpp index e681ff0a91..666ad2bbc1 100644 --- a/Marlin/src/lcd/TFTGLCD/lcdprint_TFTGLCD.cpp +++ b/Marlin/src/lcd/TFTGLCD/lcdprint_TFTGLCD.cpp @@ -1041,7 +1041,7 @@ int lcd_put_lchar_max(const lchar_t &c, const pixel_len_t max_length) { * @param cb_read_byte : the callback function to read one byte from the utf8_str (from RAM or ROM) * @param max_length : the pixel length of the string allowed (or number of slots in HD44780) * - * @return the number of pixels advanced + * @return the number of characters emitted * * Draw a UTF-8 string */ diff --git a/Marlin/src/lcd/dogm/lcdprint_u8g.cpp b/Marlin/src/lcd/dogm/lcdprint_u8g.cpp index ea0db357b6..a615c21766 100644 --- a/Marlin/src/lcd/dogm/lcdprint_u8g.cpp +++ b/Marlin/src/lcd/dogm/lcdprint_u8g.cpp @@ -26,7 +26,7 @@ void lcd_moveto(const lcd_uint_t col, const lcd_uint_t row) { u8g.setPrintPos(co void lcd_put_int(const int i) { u8g.print(i); } // return < 0 on error -// return the advanced pixels +// return the number of pixels advanced int lcd_put_lchar_max(const lchar_t &c, const pixel_len_t max_length) { if (c < 256) { u8g.print((char)c); diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index 7aa9b1760d..2c52b0cabc 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -3437,20 +3437,22 @@ void drawMotionMenu() { updateMenu(motionMenu); } -#if HAS_PREHEAT - void drawPreheatHotendMenu() { - checkkey = ID_Menu; - if (SET_MENU(preheatHotendMenu, MSG_PREHEAT_HOTEND, 1 + PREHEAT_COUNT)) { - BACK_ITEM(drawFilamentManMenu); - #define _ITEM_PREHEAT_HE(N) MENU_ITEM(ICON_Preheat##N, MSG_PREHEAT_##N, onDrawMenuItem, DoPreheatHotend##N); - REPEAT_1(PREHEAT_COUNT, _ITEM_PREHEAT_HE) - } - updateMenu(preheatHotendMenu); - } -#endif - #if ENABLED(ADVANCED_PAUSE_FEATURE) + #if HAS_PREHEAT + + void drawPreheatHotendMenu() { + checkkey = ID_Menu; + if (SET_MENU(preheatHotendMenu, MSG_PREHEAT_HOTEND, 1 + PREHEAT_COUNT)) { + BACK_ITEM(drawFilamentManMenu); + #define _ITEM_PREHEAT_HE(N) MENU_ITEM(ICON_Preheat##N, MSG_PREHEAT_##N, onDrawMenuItem, DoPreheatHotend##N); + REPEAT_1(PREHEAT_COUNT, _ITEM_PREHEAT_HE) + } + updateMenu(preheatHotendMenu); + } + + #endif + void drawFilamentManMenu() { checkkey = ID_Menu; if (SET_MENU(filamentMenu, MSG_FILAMENT_MAN, 6)) { diff --git a/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp b/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp index 4dd3d7a369..d76c10dfdb 100644 --- a/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp +++ b/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp @@ -70,9 +70,9 @@ void ESDiag::draw() { DWINUI::drawButton(BTN_Continue, 86, 250); DWINUI::cursor.y = 80; #define ES_LABEL(S) draw_es_label(F(STR_##S)) - TERN_(USE_X_MIN, ES_LABEL(X_MIN)); TERN_(USE_X_MAX, ES_LABEL(X_MAX)); - TERN_(USE_Y_MIN, ES_LABEL(Y_MIN)); TERN_(USE_Y_MAX, ES_LABEL(Y_MAX)); - TERN_(HAS_Z_MIN_PIN, ES_LABEL(Z_MIN)); TERN_(USE_Z_MAX, ES_LABEL(Z_MAX)); + TERN_(USE_X_MIN, ES_LABEL(X_MIN)); TERN_(USE_X_MAX, ES_LABEL(X_MAX)); + TERN_(USE_Y_MIN, ES_LABEL(Y_MIN)); TERN_(USE_Y_MAX, ES_LABEL(Y_MAX)); + TERN_(USE_Z_MIN, ES_LABEL(Z_MIN)); TERN_(USE_Z_MAX, ES_LABEL(Z_MAX)); TERN_(HAS_FILAMENT_SENSOR, draw_es_label(F(STR_FILAMENT))); update(); } @@ -80,9 +80,9 @@ void ESDiag::draw() { void ESDiag::update() { DWINUI::cursor.y = 80; #define ES_REPORT(S) draw_es_state(READ(S##_PIN) == S##_ENDSTOP_HIT_STATE) - TERN_(USE_X_MIN, ES_REPORT(X_MIN)); TERN_(USE_X_MAX, ES_REPORT(X_MAX)); - TERN_(USE_Y_MIN, ES_REPORT(Y_MIN)); TERN_(USE_Y_MAX, ES_REPORT(Y_MAX)); - TERN_(HAS_Z_MIN_PIN, ES_REPORT(Z_MIN)); TERN_(USE_Z_MAX, ES_REPORT(Z_MAX)); + TERN_(USE_X_MIN, ES_REPORT(X_MIN)); TERN_(USE_X_MAX, ES_REPORT(X_MAX)); + TERN_(USE_Y_MIN, ES_REPORT(Y_MIN)); TERN_(USE_Y_MAX, ES_REPORT(Y_MAX)); + TERN_(USE_Z_MIN, ES_REPORT(Z_MIN)); TERN_(USE_Z_MAX, ES_REPORT(Z_MAX)); TERN_(HAS_FILAMENT_SENSOR, draw_es_state(READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE)); dwinUpdateLCD(); } diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/endstop_state_screen.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/endstop_state_screen.cpp index 1d81649444..6105591d15 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/endstop_state_screen.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/endstop_state_screen.cpp @@ -79,7 +79,7 @@ void EndstopStatesScreen::onRedraw(draw_mode_t) { #else PIN_DISABLED(3, 3, PSTR(STR_Y_MIN), Y_MIN) #endif - #if HAS_Z_MIN_PIN + #if USE_Z_MIN PIN_ENABLED (5, 3, PSTR(STR_Z_MIN), Z_MIN, Z_MIN_ENDSTOP_HIT_STATE) #else PIN_DISABLED(5, 3, PSTR(STR_Z_MIN), Z_MIN) diff --git a/Marlin/src/lcd/extui/mks_ui/mks_hardware.cpp b/Marlin/src/lcd/extui/mks_ui/mks_hardware.cpp index c46a532d9a..a759f8677e 100644 --- a/Marlin/src/lcd/extui/mks_ui/mks_hardware.cpp +++ b/Marlin/src/lcd/extui/mks_ui/mks_hardware.cpp @@ -45,36 +45,56 @@ #if PIN_EXISTS(MT_DET_2) bool mt_det2_sta; #endif - #if HAS_X_ENDSTOP - bool endstopx1_sta; + #if USE_X_MIN + bool endstopx1_min; #else - constexpr static bool endstopx1_sta = true; + constexpr static bool endstopx1_min = true; #endif - #if HAS_X2_ENDSTOP + #if USE_X_MAX + bool endstopx1_max; + #else + constexpr static bool endstopx1_max = true; + #endif + #if USE_X2_MIN bool endstopx2_sta; #else constexpr static bool endstopx2_sta = true; #endif - #if HAS_Y_ENDSTOP + #if USE_Y_MIN bool endstopy1_sta; #else constexpr static bool endstopy1_sta = true; #endif - #if HAS_Y2_ENDSTOP + #if USE_Y2_MIN bool endstopy2_sta; #else constexpr static bool endstopy2_sta = true; #endif - #if HAS_Z_ENDSTOP - bool endstopz1_sta; + #if USE_Z_MIN + bool endstopz1_min; #else - constexpr static bool endstopz1_sta = true; + constexpr static bool endstopz1_min = true; #endif - #if HAS_Z2_ENDSTOP + #if USE_Z_MAX + bool endstopz1_max; + #else + constexpr static bool endstopz1_max = true; + #endif + #if USE_Z2_MIN || USE_Z2_MAX bool endstopz2_sta; #else constexpr static bool endstopz2_sta = true; #endif + #if USE_Z3_MIN || USE_Z3_MAX + bool endstopz3_sta; + #else + constexpr static bool endstopz3_sta = true; + #endif + #if USE_Z4_MIN || USE_Z4_MAX + bool endstopz4_sta; + #else + constexpr static bool endstopz4_sta = true; + #endif #define ESTATE(S) (READ(S##_PIN) == S##_ENDSTOP_HIT_STATE) @@ -87,12 +107,28 @@ #if PIN_EXISTS(MT_DET_2) mt_det2_sta = (READ(MT_DET_2_PIN) == LOW); #endif - TERN_(HAS_X_ENDSTOP, endstopx1_sta = ESTATE(TERN(USE_X_MIN, X_MIN, X_MAX))); - TERN_(HAS_X2_ENDSTOP, endstopx2_sta = ESTATE(TERN(USE_X2_MIN, X2_MIN, X2_MAX))); - TERN_(HAS_Y_ENDSTOP, endstopy1_sta = ESTATE(TERN(USE_Y_MIN, Y_MIN, Y_MAX))); - TERN_(HAS_Y2_ENDSTOP, endstopy2_sta = ESTATE(TERN(USE_Y2_MIN, Y2_MIN, Y2_MAX))); - TERN_(HAS_Z_ENDSTOP, endstopz1_sta = ESTATE(TERN(HAS_Z_MIN_PIN, Z_MIN, Z_MAX))); - TERN_(HAS_Z2_ENDSTOP, endstopz2_sta = ESTATE(TERN(USE_Z2_MIN, Z2_MIN, Z2_MAX))); + TERN_(USE_X_MIN, endstopx1_min = ESTATE(X_MIN)); + TERN_(USE_X_MAX, endstopx1_max = ESTATE(X_MAX)); + #if USE_X2_MIN || USE_X2_MAX + endstopx2_sta = ESTATE(TERN(USE_X2_MIN, X2_MIN, X2_MAX)); + #endif + #if USE_Y_MIN || USE_Y_MAX + endstopy1_sta = ESTATE(TERN(USE_Y_MIN, Y_MIN, Y_MAX)); + #endif + #if USE_Y2_MIN || USE_Y2_MAX + endstopy2_sta = ESTATE(TERN(USE_Y2_MIN, Y2_MIN, Y2_MAX)); + #endif + TERN_(USE_Z_MIN, endstopz1_min = ESTATE(Z_MIN)); + TERN_(USE_Z_MAX, endstopz1_max = ESTATE(Z_MAX)); + #if USE_Z2_MIN || USE_Z2_MAX + endstopz2_sta = ESTATE(TERN(USE_Z2_MIN, Z2_MIN, Z2_MAX)); + #endif + #if USE_Z3_MIN || USE_Z3_MAX + endstopz3_sta = ESTATE(TERN(USE_Z3_MIN, Z3_MIN, Z3_MAX)); + #endif + #if USE_Z4_MIN || USE_Z4_MAX + endstopz4_sta = ESTATE(TERN(USE_Z4_MIN, Z4_MIN, Z4_MAX)); + #endif } void test_gpio_readlevel_H() { @@ -104,12 +140,28 @@ #if PIN_EXISTS(MT_DET_2) mt_det2_sta = (READ(MT_DET_2_PIN) == HIGH); #endif - TERN_(HAS_X_ENDSTOP, endstopx1_sta = !ESTATE(TERN(USE_X_MIN, X_MIN, X_MAX))); - TERN_(HAS_X2_ENDSTOP, endstopx2_sta = !ESTATE(TERN(USE_X2_MIN, X2_MIN, X2_MAX))); - TERN_(HAS_Y_ENDSTOP, endstopy1_sta = !ESTATE(TERN(USE_Y_MIN, Y_MIN, Y_MAX))); - TERN_(HAS_Y2_ENDSTOP, endstopy2_sta = !ESTATE(TERN(USE_Y2_MIN, Y2_MIN, Y2_MAX))); - TERN_(HAS_Z_ENDSTOP, endstopz1_sta = !ESTATE(TERN(HAS_Z_MIN_PIN, Z_MIN, Z_MAX))); - TERN_(HAS_Z2_ENDSTOP, endstopz2_sta = !ESTATE(TERN(USE_Z2_MIN, Z2_MIN, Z2_MAX))); + TERN_(USE_X_MIN, endstopx1_min = !ESTATE(X_MIN)); + TERN_(USE_X_MAX, endstopx1_max = !ESTATE(X_MAX)); + #if USE_X2_MIN || USE_X2_MAX + endstopx2_sta = !ESTATE(TERN(USE_X2_MIN, X2_MIN, X2_MAX)); + #endif + #if USE_Y_MIN || USE_Y_MAX + endstopy1_sta = !ESTATE(TERN(USE_Y_MIN, Y_MIN, Y_MAX)); + #endif + #if USE_Y2_MIN || USE_Y2_MAX + endstopy2_sta = !ESTATE(TERN(USE_Y2_MIN, Y2_MIN, Y2_MAX)); + #endif + TERN_(USE_Z_MIN, endstopz1_min = !ESTATE(Z_MIN)); + TERN_(USE_Z_MAX, endstopz1_max = !ESTATE(Z_MAX)); + #if USE_Z2_MIN || USE_Z2_MAX + endstopz2_sta = !ESTATE(TERN(USE_Z2_MIN, Z2_MIN, Z2_MAX)); + #endif + #if USE_Z3_MIN || USE_Z3_MAX + endstopz3_sta = !ESTATE(TERN(USE_Z3_MIN, Z3_MIN, Z3_MAX)); + #endif + #if USE_Z4_MIN || USE_Z4_MAX + endstopz4_sta = !ESTATE(TERN(USE_Z4_MIN, Z4_MIN, Z4_MAX)); + #endif } #include "../../../libs/buzzer.h" @@ -185,7 +237,7 @@ else disp_det_error(); - if (endstopx1_sta && endstopy1_sta && endstopz1_sta && endstopz2_sta) + if (endstopx1_min && endstopx1_max && endstopy1_sta && endstopz1_min && endstopz1_max && endstopz2_sta && endstopz3_sta && endstopz4_sta) disp_Limit_ok(); else disp_Limit_error(); @@ -247,7 +299,9 @@ #endif } - if (endstopx1_sta && endstopx2_sta && endstopy1_sta && endstopy2_sta && endstopz1_sta && endstopz2_sta) { + if ( endstopx1_min && endstopx1_max && endstopx2_sta && endstopy1_sta && endstopy2_sta + && endstopz1_min && endstopz1_max && endstopz2_sta && endstopz3_sta && endstopz4_sta + ) { // nothing here } else { diff --git a/Marlin/src/lcd/lcdprint.cpp b/Marlin/src/lcd/lcdprint.cpp index 162f01a12c..912344c14f 100644 --- a/Marlin/src/lcd/lcdprint.cpp +++ b/Marlin/src/lcd/lcdprint.cpp @@ -41,6 +41,8 @@ * ~ displays '1'....'11' for indexes 0 - 10 * * displays 'E1'...'E11' for indexes 0 - 10 (By default. Uses LCD_FIRST_TOOL) * @ displays an axis name such as XYZUVW, or E for an extruder + * + * Return the given maxlen minus the number of characters emitted, i.e., the number of unused columns */ lcd_uint_t lcd_put_u8str_P(PGM_P const ptpl, const int8_t ind, const char *cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/, const lcd_uint_t maxlen/*=LCD_WIDTH*/) { const uint8_t prop = USE_WIDE_GLYPH ? 2 : 1; diff --git a/Marlin/src/lcd/menu/menu_configuration.cpp b/Marlin/src/lcd/menu/menu_configuration.cpp index 4e9b302263..edbf78ed76 100644 --- a/Marlin/src/lcd/menu/menu_configuration.cpp +++ b/Marlin/src/lcd/menu/menu_configuration.cpp @@ -102,9 +102,10 @@ void menu_advanced_settings(); #if ENABLED(LCD_ENDSTOP_TEST) - #define __STOP_ITEM(F,S) PSTRING_ITEM_F_P(F, TEST(stops, S) ? PSTR(STR_ENDSTOP_HIT) : PSTR(STR_ENDSTOP_OPEN), SS_FULL) + #define __STOP_ITEM(F,S) PSTRING_ITEM_F_P(F, TEST(stops, S) ? PSTR(STR_ENDSTOP_HIT) : PSTR(STR_ENDSTOP_OPEN), SS_FULL); #define _STOP_ITEM(L,S) __STOP_ITEM(F(L), S) - #define STOP_ITEM(A,I) _STOP_ITEM(STRINGIFY(A) STRINGIFY(I) " " TERN(A##_HOME_TO_MAX, "Max", "Min"), A##I##_ENDSTOP) + #define STOP_ITEM(A,I,M,L) TERN(HAS_##A##I##_##M_STATE, _STOP_ITEM, _IF_1_ELSE)(STRINGIFY(A) STRINGIFY(I) " " STRINGIFY(L), A##I##_##M) + #define STOP_MINMAX(A,I) STOP_ITEM(A,,MIN,"Min") STOP_ITEM(A,,MAX,"Max") #define FIL_ITEM(N) PSTRING_ITEM_N_P(N-1, MSG_FILAMENT_EN, (READ(FIL_RUNOUT##N##_PIN) != FIL_RUNOUT##N##_STATE) ? PSTR("PRESENT") : PSTR("out"), SS_FULL); static void endstop_test() { @@ -120,48 +121,12 @@ void menu_advanced_settings(); START_SCREEN(); STATIC_ITEM_F(GET_TEXT_F(MSG_ENDSTOP_TEST), SS_DEFAULT|SS_INVERT); - #if HAS_X_ENDSTOP - STOP_ITEM(X,); - #if ENABLED(X_DUAL_ENDSTOPS) - STOP_ITEM(X,2); - #endif - #endif - #if HAS_Y_ENDSTOP - STOP_ITEM(Y,); - #if ENABLED(Y_DUAL_ENDSTOPS) - STOP_ITEM(Y,2); - #endif - #endif - #if HAS_Z_ENDSTOP - STOP_ITEM(Z,); - #if ENABLED(Z_MULTI_ENDSTOPS) - STOP_ITEM(Z,2); - #if NUM_Z_STEPPERS >= 3 - STOP_ITEM(Z,3); - #if NUM_Z_STEPPERS >= 4 - STOP_ITEM(Z,4); - #endif - #endif - #endif - #endif - #if HAS_I_ENDSTOP - STOP_ITEM(I,); - #endif - #if HAS_J_ENDSTOP - STOP_ITEM(J,); - #endif - #if HAS_K_ENDSTOP - STOP_ITEM(K,); - #endif - #if HAS_U_ENDSTOP - STOP_ITEM(U,); - #endif - #if HAS_V_ENDSTOP - STOP_ITEM(V,); - #endif - #if HAS_W_ENDSTOP - STOP_ITEM(W,); - #endif + STOP_MINMAX(X,) STOP_MINMAX(X,2) + STOP_MINMAX(Y,) STOP_MINMAX(Y,2) + STOP_MINMAX(Z,) STOP_MINMAX(Z,2) STOP_MINMAX(Z,3) STOP_MINMAX(Z,4) + STOP_MINMAX(I,) STOP_MINMAX(J,) STOP_MINMAX(K,) + STOP_MINMAX(U,) STOP_MINMAX(V,) STOP_MINMAX(W,) + #if HAS_BED_PROBE && !HAS_DELTA_SENSORLESS_PROBING __STOP_ITEM(GET_TEXT_F(MSG_Z_PROBE), Z_MIN_PROBE); #endif diff --git a/Marlin/src/module/endstops.cpp b/Marlin/src/module/endstops.cpp index 3c1fcc72a9..0f060f5720 100644 --- a/Marlin/src/module/endstops.cpp +++ b/Marlin/src/module/endstops.cpp @@ -138,7 +138,7 @@ void Endstops::init() { #if USE_Y2_MAX _INIT_ENDSTOP(MAX,Y,2); #endif - #if HAS_Z_MIN_PIN + #if USE_Z_MIN _INIT_ENDSTOP(MIN,Z,); #endif #if USE_Z_MAX @@ -315,7 +315,7 @@ void Endstops::event_handler() { SERIAL_ECHOPGM(" " STRINGIFY(A) ":", planner.triggered_position_mm(_AXIS(A))); _SET_STOP_CHAR(A,C); }while(0) #define _ENDSTOP_HIT_TEST(A,C) \ - if (TERN0(USE_##A##_MIN, TEST(hit_state, ES_ENUM(A,MIN))) || TERN0(USE_##A##_MAX, TEST(hit_state, ES_ENUM(A,MAX)))) \ + if (TERN0(HAS_##A##_MIN_STATE, TEST(hit_state, ES_ENUM(A,MIN))) || TERN0(HAS_##A##_MAX_STATE, TEST(hit_state, ES_ENUM(A,MAX)))) \ _ENDSTOP_HIT_ECHO(A,C) #define ENDSTOP_HIT_TEST_X() _ENDSTOP_HIT_TEST(X,'X') @@ -504,11 +504,6 @@ void __O2 Endstops::report_states() { } // Endstops::report_states -#define __ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX -#define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_## MINMAX ##_PIN -#define _ENDSTOP_HIT_STATE(AXIS, MINMAX) AXIS ##_## MINMAX ##_ENDSTOP_HIT_STATE -#define _ENDSTOP(AXIS, MINMAX) __ENDSTOP(AXIS, MINMAX) - /** * Called from interrupt context by the Endstop ISR or Stepper ISR! * Read endstops to get their current states, register hits for all @@ -521,7 +516,9 @@ void Endstops::update() { #endif // Macros to update / copy the live_state - #define UPDATE_LIVE_STATE(AXIS, MINMAX) SET_BIT_TO(live_state, _ENDSTOP(AXIS, MINMAX), (READ_ENDSTOP(_ENDSTOP_PIN(AXIS, MINMAX)) == _ENDSTOP_HIT_STATE(AXIS, MINMAX))) + #define _ES_PIN(A,M) A##_##M##_PIN + #define _ES_HIT(A,M) A##_##M##_ENDSTOP_HIT_STATE + #define UPDATE_LIVE_STATE(AXIS, MINMAX) SET_BIT_TO(live_state, ES_ENUM(AXIS, MINMAX), (READ_ENDSTOP(_ES_PIN(AXIS, MINMAX)) == _ES_HIT(AXIS, MINMAX))) #define COPY_LIVE_STATE(SRC_BIT, DST_BIT) SET_BIT_TO(live_state, DST_BIT, TEST(live_state, SRC_BIT)) #if ENABLED(G38_PROBE_TARGET) @@ -560,7 +557,7 @@ void Endstops::update() { /** * Check and update endstops */ - #if USE_X_MIN && !X_SPI_SENSORLESS + #if USE_X_MIN UPDATE_LIVE_STATE(X, MIN); #if ENABLED(X_DUAL_ENDSTOPS) #if USE_X2_MIN @@ -571,7 +568,7 @@ void Endstops::update() { #endif #endif - #if USE_X_MAX && !X_SPI_SENSORLESS + #if USE_X_MAX UPDATE_LIVE_STATE(X, MAX); #if ENABLED(X_DUAL_ENDSTOPS) #if USE_X2_MAX @@ -582,7 +579,7 @@ void Endstops::update() { #endif #endif - #if USE_Y_MIN && !Y_SPI_SENSORLESS + #if USE_Y_MIN UPDATE_LIVE_STATE(Y, MIN); #if ENABLED(Y_DUAL_ENDSTOPS) #if USE_Y2_MIN @@ -593,7 +590,7 @@ void Endstops::update() { #endif #endif - #if USE_Y_MAX && !Y_SPI_SENSORLESS + #if USE_Y_MAX UPDATE_LIVE_STATE(Y, MAX); #if ENABLED(Y_DUAL_ENDSTOPS) #if USE_Y2_MAX @@ -605,159 +602,84 @@ void Endstops::update() { #endif #if USE_Z_MIN && NONE(Z_SPI_SENSORLESS, Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) - #if HAS_Z_MIN_PIN - UPDATE_LIVE_STATE(Z, MIN); - #endif - #if ENABLED(Z_MULTI_ENDSTOPS) - #if USE_Z2_MIN - UPDATE_LIVE_STATE(Z2, MIN); - #else - COPY_LIVE_STATE(Z_MIN, Z2_MIN); - #endif - #if NUM_Z_STEPPERS >= 3 - #if USE_Z3_MIN - UPDATE_LIVE_STATE(Z3, MIN); - #else - COPY_LIVE_STATE(Z_MIN, Z3_MIN); - #endif - #endif - #if NUM_Z_STEPPERS >= 4 - #if USE_Z4_MIN - UPDATE_LIVE_STATE(Z4, MIN); - #else - COPY_LIVE_STATE(Z_MIN, Z4_MIN); - #endif - #endif - #endif + UPDATE_LIVE_STATE(Z, MIN); + #endif + #if USE_Z2_MIN + UPDATE_LIVE_STATE(Z2, MIN); + #elif HAS_Z2_MIN_STATE + COPY_LIVE_STATE(Z_MIN, Z2_MIN); + #endif + #if USE_Z3_MIN + UPDATE_LIVE_STATE(Z3, MIN); + #elif HAS_Z3_MIN_STATE + COPY_LIVE_STATE(Z_MIN, Z3_MIN); + #endif + #if USE_Z4_MIN + UPDATE_LIVE_STATE(Z4, MIN); + #elif HAS_Z4_MIN_STATE + COPY_LIVE_STATE(Z_MIN, Z4_MIN); #endif - #if HAS_BED_PROBE + #if HAS_REAL_BED_PROBE // When closing the gap check the enabled probe if (probe_switch_activated()) UPDATE_LIVE_STATE(Z, TERN(USE_Z_MIN_PROBE, MIN_PROBE, MIN)); #endif - #if USE_Z_MAX && !Z_SPI_SENSORLESS - // Check both Z dual endstops - #if ENABLED(Z_MULTI_ENDSTOPS) - UPDATE_LIVE_STATE(Z, MAX); - #if USE_Z2_MAX - UPDATE_LIVE_STATE(Z2, MAX); - #else - COPY_LIVE_STATE(Z_MAX, Z2_MAX); - #endif - #if NUM_Z_STEPPERS >= 3 - #if USE_Z3_MAX - UPDATE_LIVE_STATE(Z3, MAX); - #else - COPY_LIVE_STATE(Z_MAX, Z3_MAX); - #endif - #endif - #if NUM_Z_STEPPERS >= 4 - #if USE_Z4_MAX - UPDATE_LIVE_STATE(Z4, MAX); - #else - COPY_LIVE_STATE(Z_MAX, Z4_MAX); - #endif - #endif - #elif TERN1(USE_Z_MIN_PROBE, Z_MAX_PIN != Z_MIN_PROBE_PIN) - // If this pin isn't the bed probe it's the Z endstop - UPDATE_LIVE_STATE(Z, MAX); - #endif + #if USE_Z_MAX + UPDATE_LIVE_STATE(Z, MAX); + #endif + #if USE_Z2_MAX + UPDATE_LIVE_STATE(Z2, MAX); + #elif HAS_Z2_MAX_STATE + COPY_LIVE_STATE(Z_MAX, Z2_MAX); + #endif + #if USE_Z3_MAX + UPDATE_LIVE_STATE(Z3, MAX); + #elif HAS_Z3_MAX_STATE + COPY_LIVE_STATE(Z_MAX, Z3_MAX); + #endif + #if USE_Z4_MAX + UPDATE_LIVE_STATE(Z4, MAX); + #elif HAS_Z4_MAX_STATE + COPY_LIVE_STATE(Z_MAX, Z4_MAX); #endif - #if USE_I_MIN && !I_SPI_SENSORLESS - #if ENABLED(I_DUAL_ENDSTOPS) - UPDATE_LIVE_STATE(I, MIN); - #else - UPDATE_LIVE_STATE(I, MIN); - #endif + #if USE_I_MIN + UPDATE_LIVE_STATE(I, MIN); #endif - - #if USE_I_MAX && !I_SPI_SENSORLESS - #if ENABLED(I_DUAL_ENDSTOPS) - UPDATE_LIVE_STATE(I, MAX); - #else - UPDATE_LIVE_STATE(I, MAX); - #endif + #if USE_I_MAX + UPDATE_LIVE_STATE(I, MAX); #endif - - #if USE_J_MIN && !J_SPI_SENSORLESS - #if ENABLED(J_DUAL_ENDSTOPS) - UPDATE_LIVE_STATE(J, MIN); - #else - UPDATE_LIVE_STATE(J, MIN); - #endif + #if USE_J_MIN + UPDATE_LIVE_STATE(J, MIN); #endif - - #if USE_J_MAX && !J_SPI_SENSORLESS - #if ENABLED(J_DUAL_ENDSTOPS) - UPDATE_LIVE_STATE(J, MAX); - #else - UPDATE_LIVE_STATE(J, MAX); - #endif + #if USE_J_MAX + UPDATE_LIVE_STATE(J, MAX); #endif - - #if USE_K_MIN && !K_SPI_SENSORLESS - #if ENABLED(K_DUAL_ENDSTOPS) - UPDATE_LIVE_STATE(K, MIN); - #else - UPDATE_LIVE_STATE(K, MIN); - #endif + #if USE_K_MIN + UPDATE_LIVE_STATE(K, MIN); #endif - - #if USE_K_MAX && !K_SPI_SENSORLESS - #if ENABLED(K_DUAL_ENDSTOPS) - UPDATE_LIVE_STATE(K, MAX); - #else - UPDATE_LIVE_STATE(K, MAX); - #endif + #if USE_K_MAX + UPDATE_LIVE_STATE(K, MAX); #endif - - #if USE_U_MIN && !U_SPI_SENSORLESS - #if ENABLED(U_DUAL_ENDSTOPS) - UPDATE_LIVE_STATE(U, MIN); - #else - UPDATE_LIVE_STATE(U, MIN); - #endif + #if USE_U_MIN + UPDATE_LIVE_STATE(U, MIN); #endif - - #if USE_U_MAX && !U_SPI_SENSORLESS - #if ENABLED(U_DUAL_ENDSTOPS) - UPDATE_LIVE_STATE(U, MAX); - #else - UPDATE_LIVE_STATE(U, MAX); - #endif + #if USE_U_MAX + UPDATE_LIVE_STATE(U, MAX); #endif - - #if USE_V_MIN && !V_SPI_SENSORLESS - #if ENABLED(V_DUAL_ENDSTOPS) - UPDATE_LIVE_STATE(V, MIN); - #else - UPDATE_LIVE_STATE(V, MIN); - #endif + #if USE_V_MIN + UPDATE_LIVE_STATE(V, MIN); #endif - #if USE_V_MAX && !V_SPI_SENSORLESS - #if ENABLED(O_DUAL_ENDSTOPS) - UPDATE_LIVE_STATE(V, MAX); - #else - UPDATE_LIVE_STATE(V, MAX); - #endif + #if USE_V_MAX + UPDATE_LIVE_STATE(V, MAX); #endif - - #if USE_W_MIN && !W_SPI_SENSORLESS - #if ENABLED(W_DUAL_ENDSTOPS) - UPDATE_LIVE_STATE(W, MIN); - #else - UPDATE_LIVE_STATE(W, MIN); - #endif + #if USE_W_MIN + UPDATE_LIVE_STATE(W, MIN); #endif - #if USE_W_MAX && !W_SPI_SENSORLESS - #if ENABLED(W_DUAL_ENDSTOPS) - UPDATE_LIVE_STATE(W, MAX); - #else - UPDATE_LIVE_STATE(W, MAX); - #endif + #if USE_W_MAX + UPDATE_LIVE_STATE(W, MAX); #endif #if ENDSTOP_NOISE_THRESHOLD @@ -788,11 +710,11 @@ void Endstops::update() { #define TEST_ENDSTOP(ENDSTOP) (TEST(state(), ENDSTOP)) // Record endstop was hit - #define _ENDSTOP_HIT(AXIS, MINMAX) SBI(hit_state, _ENDSTOP(AXIS, MINMAX)) + #define _ENDSTOP_HIT(AXIS, MINMAX) SBI(hit_state, ES_ENUM(AXIS, MINMAX)) // Call the endstop triggered routine for single endstops #define PROCESS_ENDSTOP(AXIS, MINMAX) do { \ - if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX))) { \ + if (TEST_ENDSTOP(ES_ENUM(AXIS, MINMAX))) { \ _ENDSTOP_HIT(AXIS, MINMAX); \ planner.endstop_triggered(_AXIS(AXIS)); \ } \ @@ -801,7 +723,7 @@ void Endstops::update() { // Core Sensorless Homing needs to test an Extra Pin #define CORE_DIAG(QQ,A,MM) (CORE_IS_##QQ && A##_SENSORLESS && !A##_SPI_SENSORLESS && USE_##A##_##MM) #define PROCESS_CORE_ENDSTOP(A1,M1,A2,M2) do { \ - if (TEST_ENDSTOP(_ENDSTOP(A1,M1))) { \ + if (TEST_ENDSTOP(ES_ENUM(A1,M1))) { \ _ENDSTOP_HIT(A2,M2); \ planner.endstop_triggered(_AXIS(A2)); \ } \ @@ -809,7 +731,7 @@ void Endstops::update() { // Call the endstop triggered routine for dual endstops #define PROCESS_DUAL_ENDSTOP(A, MINMAX) do { \ - const byte dual_hit = TEST_ENDSTOP(_ENDSTOP(A, MINMAX)) | (TEST_ENDSTOP(_ENDSTOP(A##2, MINMAX)) << 1); \ + const byte dual_hit = TEST_ENDSTOP(ES_ENUM(A, MINMAX)) | (TEST_ENDSTOP(ES_ENUM(A##2, MINMAX)) << 1); \ if (dual_hit) { \ _ENDSTOP_HIT(A, MINMAX); \ /* if not performing home or if both endstops were triggered during homing... */ \ @@ -819,7 +741,7 @@ void Endstops::update() { }while(0) #define PROCESS_TRIPLE_ENDSTOP(A, MINMAX) do { \ - const byte triple_hit = TEST_ENDSTOP(_ENDSTOP(A, MINMAX)) | (TEST_ENDSTOP(_ENDSTOP(A##2, MINMAX)) << 1) | (TEST_ENDSTOP(_ENDSTOP(A##3, MINMAX)) << 2); \ + const byte triple_hit = TEST_ENDSTOP(ES_ENUM(A, MINMAX)) | (TEST_ENDSTOP(ES_ENUM(A##2, MINMAX)) << 1) | (TEST_ENDSTOP(ES_ENUM(A##3, MINMAX)) << 2); \ if (triple_hit) { \ _ENDSTOP_HIT(A, MINMAX); \ /* if not performing home or if both endstops were triggered during homing... */ \ @@ -829,7 +751,7 @@ void Endstops::update() { }while(0) #define PROCESS_QUAD_ENDSTOP(A, MINMAX) do { \ - const byte quad_hit = TEST_ENDSTOP(_ENDSTOP(A, MINMAX)) | (TEST_ENDSTOP(_ENDSTOP(A##2, MINMAX)) << 1) | (TEST_ENDSTOP(_ENDSTOP(A##3, MINMAX)) << 2) | (TEST_ENDSTOP(_ENDSTOP(A##4, MINMAX)) << 3); \ + const byte quad_hit = TEST_ENDSTOP(ES_ENUM(A, MINMAX)) | (TEST_ENDSTOP(ES_ENUM(A##2, MINMAX)) << 1) | (TEST_ENDSTOP(ES_ENUM(A##3, MINMAX)) << 2) | (TEST_ENDSTOP(ES_ENUM(A##4, MINMAX)) << 3); \ if (quad_hit) { \ _ENDSTOP_HIT(A, MINMAX); \ /* if not performing home or if both endstops were triggered during homing... */ \ @@ -876,7 +798,7 @@ void Endstops::update() { #if HAS_X_AXIS if (stepper.axis_is_moving(X_AXIS)) { if (!stepper.motor_direction(X_AXIS_HEAD)) { // -direction - #if USE_X_MIN || (X_SPI_SENSORLESS && X_HOME_TO_MIN) + #if HAS_X_MIN_STATE PROCESS_ENDSTOP_X(MIN); #if CORE_DIAG(XY, Y, MIN) PROCESS_CORE_ENDSTOP(Y,MIN,X,MIN); @@ -890,7 +812,7 @@ void Endstops::update() { #endif } else { // +direction - #if USE_X_MAX || (X_SPI_SENSORLESS && X_HOME_TO_MAX) + #if HAS_X_MAX_STATE PROCESS_ENDSTOP_X(MAX); #if CORE_DIAG(XY, Y, MIN) PROCESS_CORE_ENDSTOP(Y,MIN,X,MAX); @@ -909,7 +831,7 @@ void Endstops::update() { #if HAS_Y_AXIS if (stepper.axis_is_moving(Y_AXIS)) { if (!stepper.motor_direction(Y_AXIS_HEAD)) { // -direction - #if USE_Y_MIN || (Y_SPI_SENSORLESS && Y_HOME_TO_MIN) + #if HAS_Y_MIN_STATE PROCESS_ENDSTOP_Y(MIN); #if CORE_DIAG(XY, X, MIN) PROCESS_CORE_ENDSTOP(X,MIN,Y,MIN); @@ -923,7 +845,7 @@ void Endstops::update() { #endif } else { // +direction - #if USE_Y_MAX || (Y_SPI_SENSORLESS && Y_HOME_TO_MAX) + #if HAS_Y_MAX_STATE PROCESS_ENDSTOP_Y(MAX); #if CORE_DIAG(XY, X, MIN) PROCESS_CORE_ENDSTOP(X,MIN,Y,MAX); @@ -942,34 +864,34 @@ void Endstops::update() { #if HAS_Z_AXIS if (stepper.axis_is_moving(Z_AXIS)) { if (!stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up. - - #if USE_Z_MIN || (Z_SPI_SENSORLESS && Z_HOME_TO_MIN) - if ( TERN1(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, z_probe_enabled) - && TERN1(USE_Z_MIN_PROBE, !z_probe_enabled) - ) PROCESS_ENDSTOP_Z(MIN); - #if CORE_DIAG(XZ, X, MIN) - PROCESS_CORE_ENDSTOP(X,MIN,Z,MIN); - #elif CORE_DIAG(XZ, X, MAX) - PROCESS_CORE_ENDSTOP(X,MAX,Z,MIN); - #elif CORE_DIAG(YZ, Y, MIN) - PROCESS_CORE_ENDSTOP(Y,MIN,Z,MIN); - #elif CORE_DIAG(YZ, Y, MAX) - PROCESS_CORE_ENDSTOP(Y,MAX,Z,MIN); - #endif + #if HAS_Z_MIN_STATE + // If the Z_MIN_PIN is being used for the probe there's no + // separate Z_MIN endstop. But a Z endstop could be wired + // in series, so someone might find this useful. + if ( TERN1(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, z_probe_enabled) // When Z_MIN is the probe, the probe must be enabled + && TERN1(USE_Z_MIN_PROBE, !z_probe_enabled) // When Z_MIN isn't the probe, Z MIN is ignored while probing + ) { + PROCESS_ENDSTOP_Z(MIN); + #if CORE_DIAG(XZ, X, MIN) + PROCESS_CORE_ENDSTOP(X,MIN,Z,MIN); + #elif CORE_DIAG(XZ, X, MAX) + PROCESS_CORE_ENDSTOP(X,MAX,Z,MIN); + #elif CORE_DIAG(YZ, Y, MIN) + PROCESS_CORE_ENDSTOP(Y,MIN,Z,MIN); + #elif CORE_DIAG(YZ, Y, MAX) + PROCESS_CORE_ENDSTOP(Y,MAX,Z,MIN); + #endif + } #endif - // When closing the gap check the enabled probe + // When closing the gap use the probe trigger state #if USE_Z_MIN_PROBE if (z_probe_enabled) PROCESS_ENDSTOP(Z, MIN_PROBE); #endif } else { // Z +direction. Gantry up, bed down. - #if USE_Z_MAX || (Z_SPI_SENSORLESS && Z_HOME_TO_MAX) - #if ENABLED(Z_MULTI_ENDSTOPS) - PROCESS_ENDSTOP_Z(MAX); - #elif TERN1(USE_Z_MIN_PROBE, Z_MAX_PIN != Z_MIN_PROBE_PIN) // No probe or probe is Z_MIN || Probe is not Z_MAX - PROCESS_ENDSTOP(Z, MAX); - #endif + #if HAS_Z_MAX_STATE + PROCESS_ENDSTOP_Z(MAX); #if CORE_DIAG(XZ, X, MIN) PROCESS_CORE_ENDSTOP(X,MIN,Z,MAX); #elif CORE_DIAG(XZ, X, MAX) @@ -987,12 +909,12 @@ void Endstops::update() { #if HAS_I_AXIS if (stepper.axis_is_moving(I_AXIS)) { if (!stepper.motor_direction(I_AXIS_HEAD)) { // -direction - #if USE_I_MIN || (I_SPI_SENSORLESS && I_HOME_TO_MIN) + #if HAS_I_MIN_STATE PROCESS_ENDSTOP(I, MIN); #endif } else { // +direction - #if USE_I_MAX || (I_SPI_SENSORLESS && I_HOME_TO_MAX) + #if HAS_I_MAX_STATE PROCESS_ENDSTOP(I, MAX); #endif } @@ -1002,12 +924,12 @@ void Endstops::update() { #if HAS_J_AXIS if (stepper.axis_is_moving(J_AXIS)) { if (!stepper.motor_direction(J_AXIS_HEAD)) { // -direction - #if USE_J_MIN || (J_SPI_SENSORLESS && J_HOME_TO_MIN) + #if HAS_J_MIN_STATE PROCESS_ENDSTOP(J, MIN); #endif } else { // +direction - #if USE_J_MAX || (J_SPI_SENSORLESS && J_HOME_TO_MAX) + #if HAS_J_MAX_STATE PROCESS_ENDSTOP(J, MAX); #endif } @@ -1017,12 +939,12 @@ void Endstops::update() { #if HAS_K_AXIS if (stepper.axis_is_moving(K_AXIS)) { if (!stepper.motor_direction(K_AXIS_HEAD)) { // -direction - #if USE_K_MIN || (K_SPI_SENSORLESS && K_HOME_TO_MIN) + #if HAS_K_MIN_STATE PROCESS_ENDSTOP(K, MIN); #endif } else { // +direction - #if USE_K_MAX || (K_SPI_SENSORLESS && K_HOME_TO_MAX) + #if HAS_K_MAX_STATE PROCESS_ENDSTOP(K, MAX); #endif } @@ -1032,12 +954,12 @@ void Endstops::update() { #if HAS_U_AXIS if (stepper.axis_is_moving(U_AXIS)) { if (!stepper.motor_direction(U_AXIS_HEAD)) { // -direction - #if USE_U_MIN || (U_SPI_SENSORLESS && U_HOME_TO_MIN) + #if HAS_U_MIN_STATE PROCESS_ENDSTOP(U, MIN); #endif } else { // +direction - #if USE_U_MAX || (U_SPI_SENSORLESS && U_HOME_TO_MAX) + #if HAS_U_MAX_STATE PROCESS_ENDSTOP(U, MAX); #endif } @@ -1047,12 +969,12 @@ void Endstops::update() { #if HAS_V_AXIS if (stepper.axis_is_moving(V_AXIS)) { if (!stepper.motor_direction(V_AXIS_HEAD)) { // -direction - #if USE_V_MIN || (V_SPI_SENSORLESS && V_HOME_TO_MIN) + #if HAS_V_MIN_STATE PROCESS_ENDSTOP(V, MIN); #endif } else { // +direction - #if USE_V_MAX || (V_SPI_SENSORLESS && V_HOME_TO_MAX) + #if HAS_V_MAX_STATE PROCESS_ENDSTOP(V, MAX); #endif } @@ -1062,17 +984,18 @@ void Endstops::update() { #if HAS_W_AXIS if (stepper.axis_is_moving(W_AXIS)) { if (!stepper.motor_direction(W_AXIS_HEAD)) { // -direction - #if USE_W_MIN || (W_SPI_SENSORLESS && W_HOME_TO_MIN) + #if HAS_W_MIN_STATE PROCESS_ENDSTOP(W, MIN); #endif } else { // +direction - #if USE_W_MAX || (W_SPI_SENSORLESS && W_HOME_TO_MAX) + #if HAS_W_MAX_STATE PROCESS_ENDSTOP(W, MAX); #endif } } #endif // HAS_W_AXIS + } // Endstops::update() #if ENABLED(SPI_ENDSTOPS) @@ -1080,39 +1003,67 @@ void Endstops::update() { // Called from idle() to read Trinamic stall states bool Endstops::tmc_spi_homing_check() { bool hit = false; + #if X_SPI_SENSORLESS - if (tmc_spi_homing.x && (stepperX.test_stall_status() - #if Y_SPI_SENSORLESS && ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) - || stepperY.test_stall_status() - #elif Z_SPI_SENSORLESS && CORE_IS_XZ - || stepperZ.test_stall_status() + if (tmc_spi_homing.x) { + #if ENABLED(DUAL_X_CARRIAGE) + const bool ismin = X_MIN_TEST(); #endif - )) { SBI(live_state, X_ENDSTOP); hit = true; } - #if ENABLED(X_DUAL_ENDSTOPS) - if (tmc_spi_homing.x && stepperX2.test_stall_status()) { SBI(live_state, X2_ENDSTOP); hit = true; } - #endif + const bool xhit = ( + #if ENABLED(DUAL_X_CARRIAGE) + ismin ? stepperX.test_stall_status() : stepperX2.test_stall_status() + #else + stepperX.test_stall_status() + #if Y_SPI_SENSORLESS && ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) + || stepperY.test_stall_status() + #elif Z_SPI_SENSORLESS && CORE_IS_XZ + || stepperZ.test_stall_status() + #endif + #endif + ); + if (xhit) { SBI(live_state, TERN(DUAL_X_CARRIAGE, ismin ? X_MIN : X_MAX, X_ENDSTOP)); hit = true; } + #if ENABLED(X_DUAL_ENDSTOPS) + if (stepperX2.test_stall_status()) { SBI(live_state, X2_ENDSTOP); hit = true; } + #endif + } #endif + #if Y_SPI_SENSORLESS - if (tmc_spi_homing.y && (stepperY.test_stall_status() - #if X_SPI_SENSORLESS && ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) - || stepperX.test_stall_status() - #elif Z_SPI_SENSORLESS && CORE_IS_YZ - || stepperZ.test_stall_status() + if (tmc_spi_homing.y) { + if (stepperY.test_stall_status() + #if X_SPI_SENSORLESS && ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) + || stepperX.test_stall_status() + #elif Z_SPI_SENSORLESS && CORE_IS_YZ + || stepperZ.test_stall_status() + #endif + ) { SBI(live_state, Y_ENDSTOP); hit = true; } + #if ENABLED(Y_DUAL_ENDSTOPS) + if (stepperY2.test_stall_status()) { SBI(live_state, Y2_ENDSTOP); hit = true; } #endif - )) { SBI(live_state, Y_ENDSTOP); hit = true; } - #if ENABLED(Y_DUAL_ENDSTOPS) - if (tmc_spi_homing.y && stepperY2.test_stall_status()) { SBI(live_state, Y2_ENDSTOP); hit = true; } - #endif + } #endif + #if Z_SPI_SENSORLESS - if (tmc_spi_homing.z && (stepperZ.test_stall_status() - #if X_SPI_SENSORLESS && CORE_IS_XZ - || stepperX.test_stall_status() - #elif Y_SPI_SENSORLESS && CORE_IS_YZ - || stepperY.test_stall_status() + if (tmc_spi_homing.z) { + if (stepperZ.test_stall_status() + #if X_SPI_SENSORLESS && CORE_IS_XZ + || stepperX.test_stall_status() + #elif Y_SPI_SENSORLESS && CORE_IS_YZ + || stepperY.test_stall_status() + #endif + ) { SBI(live_state, Z_ENDSTOP); hit = true; } + #if ENABLED(Z_MULTI_ENDSTOPS) + if (stepperZ2.test_stall_status()) { SBI(live_state, Z2_ENDSTOP); hit = true; } + #if NUM_Z_STEPPERS >= 3 + if (stepperZ3.test_stall_status()) { SBI(live_state, Z3_ENDSTOP); hit = true; } + #if NUM_Z_STEPPERS >= 4 + if (stepperZ4.test_stall_status()) { SBI(live_state, Z4_ENDSTOP); hit = true; } + #endif + #endif #endif - )) { SBI(live_state, Z_ENDSTOP); hit = true; } + } #endif + #if I_SPI_SENSORLESS if (tmc_spi_homing.i && stepperI.test_stall_status()) { SBI(live_state, I_ENDSTOP); hit = true; } #endif @@ -1147,6 +1098,15 @@ void Endstops::update() { CBI(live_state, Y2_ENDSTOP); #endif TERN_(Z_SPI_SENSORLESS, CBI(live_state, Z_ENDSTOP)); + #if ALL(Z_SPI_SENSORLESS, Z_MULTI_ENDSTOPS) + CBI(live_state, Z2_ENDSTOP); + #if NUM_Z_STEPPERS >= 3 + CBI(live_state, Z3_ENDSTOP); + #if NUM_Z_STEPPERS >= 4 + CBI(live_state, Z4_ENDSTOP); + #endif + #endif + #endif TERN_(I_SPI_SENSORLESS, CBI(live_state, I_ENDSTOP)); TERN_(J_SPI_SENSORLESS, CBI(live_state, J_ENDSTOP)); TERN_(K_SPI_SENSORLESS, CBI(live_state, K_ENDSTOP)); @@ -1190,7 +1150,7 @@ void Endstops::update() { #if USE_Y_MAX ES_GET_STATE(Y_MAX); #endif - #if HAS_Z_MIN_PIN + #if USE_Z_MIN ES_GET_STATE(Z_MIN); #endif #if USE_Z_MAX @@ -1266,7 +1226,7 @@ void Endstops::update() { ES_GET_STATE(W_MIN); #endif - uint16_t endstop_change = live_state_local ^ old_live_state_local; + const uint16_t endstop_change = live_state_local ^ old_live_state_local; #define ES_REPORT_CHANGE(S) if (TEST(endstop_change, S)) SERIAL_ECHOPGM(" " STRINGIFY(S) ":", TEST(live_state_local, S)) if (endstop_change) { @@ -1371,52 +1331,80 @@ void Endstops::update() { /** * Change TMC driver currents to N##_CURRENT_HOME, saving the current configuration of each. */ - void Endstops::set_homing_current(const bool onoff) { - #define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT) - #define HAS_DELTA_X_CURRENT (ENABLED(DELTA) && HAS_CURRENT_HOME(X)) - #define HAS_DELTA_Y_CURRENT (ENABLED(DELTA) && HAS_CURRENT_HOME(Y)) - #if HAS_DELTA_X_CURRENT || HAS_DELTA_Y_CURRENT || HAS_CURRENT_HOME(Z) + void Endstops::set_z_sensorless_current(const bool onoff) { + #if ENABLED(DELTA) && HAS_CURRENT_HOME(X) + #define HAS_DELTA_X_CURRENT 1 + #endif + #if ENABLED(DELTA) && HAS_CURRENT_HOME(Y) + #define HAS_DELTA_Y_CURRENT 1 + #endif + #if HAS_DELTA_X_CURRENT || HAS_DELTA_Y_CURRENT || HAS_CURRENT_HOME(Z) || HAS_CURRENT_HOME(Z2) || HAS_CURRENT_HOME(Z3) || HAS_CURRENT_HOME(Z4) #if HAS_DELTA_X_CURRENT - static int16_t saved_current_x; + static int16_t saved_current_X; #endif #if HAS_DELTA_Y_CURRENT - static int16_t saved_current_y; + static int16_t saved_current_Y; #endif #if HAS_CURRENT_HOME(Z) - static int16_t saved_current_z; + static int16_t saved_current_Z; #endif - auto debug_current_on = [](PGM_P const s, const int16_t a, const int16_t b) { - if (DEBUGGING(LEVELING)) { DEBUG_ECHOPGM_P(s); DEBUG_ECHOLNPGM(" current: ", a, " -> ", b); } - }; + #if HAS_CURRENT_HOME(Z2) + static int16_t saved_current_Z2; + #endif + #if HAS_CURRENT_HOME(Z3) + static int16_t saved_current_Z3; + #endif + #if HAS_CURRENT_HOME(Z4) + static int16_t saved_current_Z4; + #endif + + #if ENABLED(DEBUG_LEVELING_FEATURE) + auto debug_current = [](FSTR_P const s, const int16_t a, const int16_t b) { + if (DEBUGGING(LEVELING)) { DEBUG_ECHOF(s); DEBUG_ECHOLNPGM(" current: ", a, " -> ", b); } + }; + #else + #define debug_current(...) + #endif + + #define _SAVE_SET_CURRENT(A) \ + saved_current_##A = stepper##A.getMilliamps(); \ + stepper##A.rms_current(A##_CURRENT_HOME); \ + debug_current(F(STR_##A), saved_current_##A, A##_CURRENT_HOME) + + #define _RESTORE_CURRENT(A) \ + stepper##A.rms_current(saved_current_##A); \ + debug_current(F(STR_##A), saved_current_##A, A##_CURRENT_HOME) + if (onoff) { - #if HAS_DELTA_X_CURRENT - saved_current_x = stepperX.getMilliamps(); - stepperX.rms_current(X_CURRENT_HOME); - debug_current_on(PSTR("X"), saved_current_x, X_CURRENT_HOME); - #endif - #if HAS_DELTA_Y_CURRENT - saved_current_y = stepperY.getMilliamps(); - stepperY.rms_current(Y_CURRENT_HOME); - debug_current_on(PSTR("Y"), saved_current_y, Y_CURRENT_HOME); - #endif + TERN_(HAS_DELTA_X_CURRENT, _SAVE_SET_CURRENT(X)); + TERN_(HAS_DELTA_Y_CURRENT, _SAVE_SET_CURRENT(Y)); #if HAS_CURRENT_HOME(Z) - saved_current_z = stepperZ.getMilliamps(); - stepperZ.rms_current(Z_CURRENT_HOME); - debug_current_on(PSTR("Z"), saved_current_z, Z_CURRENT_HOME); + _SAVE_SET_CURRENT(Z); + #endif + #if HAS_CURRENT_HOME(Z2) + _SAVE_SET_CURRENT(Z2); + #endif + #if HAS_CURRENT_HOME(Z3) + _SAVE_SET_CURRENT(Z3); + #endif + #if HAS_CURRENT_HOME(Z4) + _SAVE_SET_CURRENT(Z4); #endif } else { - #if HAS_DELTA_X_CURRENT - stepperX.rms_current(saved_current_x); - debug_current_on(PSTR("X"), X_CURRENT_HOME, saved_current_x); - #endif - #if HAS_DELTA_Y_CURRENT - stepperY.rms_current(saved_current_y); - debug_current_on(PSTR("Y"), Y_CURRENT_HOME, saved_current_y); - #endif + TERN_(HAS_DELTA_X_CURRENT, _RESTORE_CURRENT(X)); + TERN_(HAS_DELTA_Y_CURRENT, _RESTORE_CURRENT(Y)); #if HAS_CURRENT_HOME(Z) - stepperZ.rms_current(saved_current_z); - debug_current_on(PSTR("Z"), Z_CURRENT_HOME, saved_current_z); + _RESTORE_CURRENT(Z); + #endif + #if HAS_CURRENT_HOME(Z2) + _RESTORE_CURRENT(Z2); + #endif + #if HAS_CURRENT_HOME(Z3) + _RESTORE_CURRENT(Z3); + #endif + #if HAS_CURRENT_HOME(Z4) + _RESTORE_CURRENT(Z4); #endif } diff --git a/Marlin/src/module/endstops.h b/Marlin/src/module/endstops.h index d348e58ab7..bbdb0bc77b 100644 --- a/Marlin/src/module/endstops.h +++ b/Marlin/src/module/endstops.h @@ -32,7 +32,12 @@ #define ES_ENUM(A,M) _ES_ENUM(A,M) #define _ES_ITEM(N) N, -#define ES_ITEM(K,N) TERN_(K,DEFER4(_ES_ITEM)(N)) +#define ES_ITEM(K,N) TERN(K,_ES_ITEM,_IF_1_ELSE)(N) + +#define _ESN_ITEM(K,A,M) ES_ITEM(K,ES_ENUM(A,M)) +#define ES_MINMAX(A) ES_ITEM(HAS_##A##_MIN_STATE, ES_ENUM(A,MIN)) ES_ITEM(HAS_##A##_MAX_STATE, ES_ENUM(A,MAX)) + +#define HAS_CURRENT_HOME(N) ((N##_CURRENT_HOME > 0) && (N##_CURRENT_HOME != N##_CURRENT)) /** * Basic Endstop Flag Bits: @@ -54,90 +59,71 @@ */ enum EndstopEnum : char { // Common XYZ (ABC) endstops. - ES_ITEM(USE_X_MIN, X_MIN) ES_ITEM(USE_X_MAX, X_MAX) - ES_ITEM(USE_Y_MIN, Y_MIN) ES_ITEM(USE_Y_MAX, Y_MAX) - ES_ITEM(USE_Z_MIN, Z_MIN) ES_ITEM(USE_Z_MAX, Z_MAX) - ES_ITEM(USE_I_MIN, I_MIN) ES_ITEM(USE_I_MAX, I_MAX) - ES_ITEM(USE_J_MIN, J_MIN) ES_ITEM(USE_J_MAX, J_MAX) - ES_ITEM(USE_K_MIN, K_MIN) ES_ITEM(USE_K_MAX, K_MAX) - ES_ITEM(USE_U_MIN, U_MIN) ES_ITEM(USE_U_MAX, U_MAX) - ES_ITEM(USE_V_MIN, V_MIN) ES_ITEM(USE_V_MAX, V_MAX) - ES_ITEM(USE_W_MIN, W_MIN) ES_ITEM(USE_W_MAX, W_MAX) + ES_MINMAX(X) ES_MINMAX(Y) ES_MINMAX(Z) + ES_MINMAX(I) ES_MINMAX(J) ES_MINMAX(K) + ES_MINMAX(U) ES_MINMAX(V) ES_MINMAX(W) // Extra Endstops for XYZ - #if ENABLED(X_DUAL_ENDSTOPS) - ES_ITEM(USE_X_MIN, X2_MIN) ES_ITEM(USE_X_MAX, X2_MAX) - #endif - #if ENABLED(Y_DUAL_ENDSTOPS) - ES_ITEM(USE_Y_MIN, Y2_MIN) ES_ITEM(USE_Y_MAX, Y2_MAX) - #endif - #if ENABLED(Z_MULTI_ENDSTOPS) - ES_ITEM(USE_Z_MIN, Z2_MIN) ES_ITEM(USE_Z_MAX, Z2_MAX) - #if NUM_Z_STEPPERS >= 3 - ES_ITEM(USE_Z_MIN, Z3_MIN) ES_ITEM(USE_Z_MAX, Z3_MAX) - #if NUM_Z_STEPPERS >= 4 - ES_ITEM(USE_Z_MIN, Z4_MIN) ES_ITEM(USE_Z_MAX, Z4_MAX) - #endif - #endif - #endif + ES_MINMAX(X2) ES_MINMAX(Y2) ES_MINMAX(Z2) ES_MINMAX(Z3) ES_MINMAX(Z4) // Bed Probe state is distinct or shared with Z_MIN (i.e., when the probe is the only Z endstop) - #if !HAS_DELTA_SENSORLESS_PROBING - ES_ITEM(HAS_BED_PROBE, Z_MIN_PROBE IF_DISABLED(USE_Z_MIN_PROBE, = Z_MIN)) - #endif + ES_ITEM(HAS_Z_PROBE_STATE, Z_MIN_PROBE IF_DISABLED(USE_Z_MIN_PROBE, = Z_MIN)) // The total number of states NUM_ENDSTOP_STATES - // Endstop aliased to MIN or MAX - #if HAS_X_ENDSTOP + // Endstop aliases + #if HAS_X_STATE , X_ENDSTOP = TERN(X_HOME_TO_MAX, X_MAX, X_MIN) - #if ENABLED(X_DUAL_ENDSTOPS) - , X2_ENDSTOP = TERN(X_HOME_TO_MAX, X2_MAX, X2_MIN) - #endif #endif - #if HAS_Y_ENDSTOP + #if HAS_X2_STATE + , X2_ENDSTOP = TERN(X_HOME_TO_MAX, X2_MAX, X2_MIN) + #endif + #if HAS_Y_STATE , Y_ENDSTOP = TERN(Y_HOME_TO_MAX, Y_MAX, Y_MIN) - #if ENABLED(Y_DUAL_ENDSTOPS) - , Y2_ENDSTOP = TERN(Y_HOME_TO_MAX, Y2_MAX, Y2_MIN) - #endif #endif + #if HAS_Y2_STATE + , Y2_ENDSTOP = TERN(Y_HOME_TO_MAX, Y2_MAX, Y2_MIN) + #endif + #if HOMING_Z_WITH_PROBE - , Z_ENDSTOP = Z_MIN_PROBE - #elif HAS_Z_ENDSTOP + , Z_ENDSTOP = Z_MIN_PROBE // "Z" endstop alias when homing with the probe + #elif HAS_Z_STATE , Z_ENDSTOP = TERN(Z_HOME_TO_MAX, Z_MAX, Z_MIN) - #if ENABLED(Z_MULTI_ENDSTOPS) - , Z2_ENDSTOP = TERN(Z_HOME_TO_MAX, Z2_MAX, Z2_MIN) - #if NUM_Z_STEPPERS >= 3 - , Z3_ENDSTOP = TERN(Z_HOME_TO_MAX, Z3_MAX, Z3_MIN) - #if NUM_Z_STEPPERS >= 4 - , Z4_ENDSTOP = TERN(Z_HOME_TO_MAX, Z4_MAX, Z4_MIN) - #endif - #endif - #endif #endif - #if HAS_I_ENDSTOP + #if HAS_Z2_STATE + , Z2_ENDSTOP = TERN(Z_HOME_TO_MAX, Z2_MAX, Z2_MIN) + #endif + #if HAS_Z3_STATE + , Z3_ENDSTOP = TERN(Z_HOME_TO_MAX, Z3_MAX, Z3_MIN) + #endif + #if HAS_Z4_STATE + , Z4_ENDSTOP = TERN(Z_HOME_TO_MAX, Z4_MAX, Z4_MIN) + #endif + #if HAS_I_STATE , I_ENDSTOP = TERN(I_HOME_TO_MAX, I_MAX, I_MIN) #endif - #if HAS_J_ENDSTOP + #if HAS_J_STATE , J_ENDSTOP = TERN(J_HOME_TO_MAX, J_MAX, J_MIN) #endif - #if HAS_K_ENDSTOP + #if HAS_K_STATE , K_ENDSTOP = TERN(K_HOME_TO_MAX, K_MAX, K_MIN) #endif - #if HAS_U_ENDSTOP + #if HAS_U_STATE , U_ENDSTOP = TERN(U_HOME_TO_MAX, U_MAX, U_MIN) #endif - #if HAS_V_ENDSTOP + #if HAS_V_STATE , V_ENDSTOP = TERN(V_HOME_TO_MAX, V_MAX, V_MIN) #endif - #if HAS_W_ENDSTOP + #if HAS_W_STATE , W_ENDSTOP = TERN(W_HOME_TO_MAX, W_MAX, W_MIN) #endif }; #undef _ES_ITEM #undef ES_ITEM +#undef _ESN_ITEM +#undef ES_MINMAX class Endstops { public: @@ -288,7 +274,7 @@ class Endstops { public: // Basic functions for Sensorless Homing #if USE_SENSORLESS - static void set_homing_current(const bool onoff); + static void set_z_sensorless_current(const bool onoff); #endif }; diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index cd768d9e40..80729df759 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -1718,38 +1718,36 @@ void prepare_line_to_destination() { #endif } - #if ENABLED(SPI_ENDSTOPS) - switch (axis) { - #if HAS_X_AXIS - case X_AXIS: if (ENABLED(X_SPI_SENSORLESS)) endstops.tmc_spi_homing.x = true; break; - #endif - #if HAS_Y_AXIS - case Y_AXIS: if (ENABLED(Y_SPI_SENSORLESS)) endstops.tmc_spi_homing.y = true; break; - #endif - #if HAS_Z_AXIS - case Z_AXIS: if (ENABLED(Z_SPI_SENSORLESS)) endstops.tmc_spi_homing.z = true; break; - #endif - #if HAS_I_AXIS - case I_AXIS: if (ENABLED(I_SPI_SENSORLESS)) endstops.tmc_spi_homing.i = true; break; - #endif - #if HAS_J_AXIS - case J_AXIS: if (ENABLED(J_SPI_SENSORLESS)) endstops.tmc_spi_homing.j = true; break; - #endif - #if HAS_K_AXIS - case K_AXIS: if (ENABLED(K_SPI_SENSORLESS)) endstops.tmc_spi_homing.k = true; break; - #endif - #if HAS_U_AXIS - case U_AXIS: if (ENABLED(U_SPI_SENSORLESS)) endstops.tmc_spi_homing.u = true; break; - #endif - #if HAS_V_AXIS - case V_AXIS: if (ENABLED(V_SPI_SENSORLESS)) endstops.tmc_spi_homing.v = true; break; - #endif - #if HAS_W_AXIS - case W_AXIS: if (ENABLED(W_SPI_SENSORLESS)) endstops.tmc_spi_homing.w = true; break; - #endif - default: break; - } - #endif + switch (axis) { + #if X_SPI_SENSORLESS + case X_AXIS: endstops.tmc_spi_homing.x = true; break; + #endif + #if Y_SPI_SENSORLESS + case Y_AXIS: endstops.tmc_spi_homing.y = true; break; + #endif + #if Z_SPI_SENSORLESS + case Z_AXIS: endstops.tmc_spi_homing.z = true; break; + #endif + #if I_SPI_SENSORLESS + case I_AXIS: endstops.tmc_spi_homing.i = true; break; + #endif + #if J_SPI_SENSORLESS + case J_AXIS: endstops.tmc_spi_homing.j = true; break; + #endif + #if K_SPI_SENSORLESS + case K_AXIS: endstops.tmc_spi_homing.k = true; break; + #endif + #if U_SPI_SENSORLESS + case U_AXIS: endstops.tmc_spi_homing.u = true; break; + #endif + #if V_SPI_SENSORLESS + case V_AXIS: endstops.tmc_spi_homing.v = true; break; + #endif + #if W_SPI_SENSORLESS + case W_AXIS: endstops.tmc_spi_homing.w = true; break; + #endif + default: break; + } TERN_(IMPROVE_HOMING_RELIABILITY, sg_guard_period = millis() + default_sg_guard_duration); @@ -1814,38 +1812,36 @@ void prepare_line_to_destination() { #endif } - #if ENABLED(SPI_ENDSTOPS) - switch (axis) { - #if HAS_X_AXIS - case X_AXIS: if (ENABLED(X_SPI_SENSORLESS)) endstops.tmc_spi_homing.x = false; break; - #endif - #if HAS_Y_AXIS - case Y_AXIS: if (ENABLED(Y_SPI_SENSORLESS)) endstops.tmc_spi_homing.y = false; break; - #endif - #if HAS_Z_AXIS - case Z_AXIS: if (ENABLED(Z_SPI_SENSORLESS)) endstops.tmc_spi_homing.z = false; break; - #endif - #if HAS_I_AXIS - case I_AXIS: if (ENABLED(I_SPI_SENSORLESS)) endstops.tmc_spi_homing.i = false; break; - #endif - #if HAS_J_AXIS - case J_AXIS: if (ENABLED(J_SPI_SENSORLESS)) endstops.tmc_spi_homing.j = false; break; - #endif - #if HAS_K_AXIS - case K_AXIS: if (ENABLED(K_SPI_SENSORLESS)) endstops.tmc_spi_homing.k = false; break; - #endif - #if HAS_U_AXIS - case U_AXIS: if (ENABLED(U_SPI_SENSORLESS)) endstops.tmc_spi_homing.u = false; break; - #endif - #if HAS_V_AXIS - case V_AXIS: if (ENABLED(V_SPI_SENSORLESS)) endstops.tmc_spi_homing.v = false; break; - #endif - #if HAS_W_AXIS - case W_AXIS: if (ENABLED(W_SPI_SENSORLESS)) endstops.tmc_spi_homing.w = false; break; - #endif - default: break; - } - #endif + switch (axis) { + #if X_SPI_SENSORLESS + case X_AXIS: endstops.tmc_spi_homing.x = false; break; + #endif + #if Y_SPI_SENSORLESS + case Y_AXIS: endstops.tmc_spi_homing.y = false; break; + #endif + #if Z_SPI_SENSORLESS + case Z_AXIS: endstops.tmc_spi_homing.z = false; break; + #endif + #if I_SPI_SENSORLESS + case I_AXIS: endstops.tmc_spi_homing.i = false; break; + #endif + #if J_SPI_SENSORLESS + case J_AXIS: endstops.tmc_spi_homing.j = false; break; + #endif + #if K_SPI_SENSORLESS + case K_AXIS: endstops.tmc_spi_homing.k = false; break; + #endif + #if U_SPI_SENSORLESS + case U_AXIS: endstops.tmc_spi_homing.u = false; break; + #endif + #if V_SPI_SENSORLESS + case V_AXIS: endstops.tmc_spi_homing.v = false; break; + #endif + #if W_SPI_SENSORLESS + case W_AXIS: endstops.tmc_spi_homing.w = false; break; + #endif + default: break; + } } #endif // SENSORLESS_HOMING @@ -2118,7 +2114,7 @@ void prepare_line_to_destination() { // Only Z homing (with probe) is permitted if (axis != Z_AXIS) { BUZZ(100, 880); return; } #else - #define _CAN_HOME(A) (axis == _AXIS(A) && (ANY(A##_SPI_SENSORLESS, HAS_##A##_ENDSTOP) || TERN0(HOMING_Z_WITH_PROBE, _AXIS(A) == Z_AXIS))) + #define _CAN_HOME(A) (axis == _AXIS(A) && (ANY(A##_SPI_SENSORLESS, HAS_##A##_STATE) || TERN0(HOMING_Z_WITH_PROBE, _AXIS(A) == Z_AXIS))) #define _ANDCANT(N) && !_CAN_HOME(N) if (true MAIN_AXIS_MAP(_ANDCANT)) return; #endif diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp index 8c13da36f9..68fcfd00e0 100644 --- a/Marlin/src/module/probe.cpp +++ b/Marlin/src/module/probe.cpp @@ -610,8 +610,19 @@ bool Probe::probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s) { if (test_sensitivity.x) stealth_states.x = tmc_enable_stallguard(stepperX); // Delta watches all DIAG pins for a stall if (test_sensitivity.y) stealth_states.y = tmc_enable_stallguard(stepperY); #endif - if (test_sensitivity.z) stealth_states.z = tmc_enable_stallguard(stepperZ); // All machines will check Z-DIAG for stall - endstops.set_homing_current(true); // The "homing" current also applies to probing + if (test_sensitivity.z) { + stealth_states.z = tmc_enable_stallguard(stepperZ); // All machines will check Z-DIAG for stall + #if ENABLED(Z_MULTI_ENDSTOPS) + stealth_states.z2 = tmc_enable_stallguard(stepperZ2); + #if NUM_Z_STEPPERS >= 3 + stealth_states.z3 = tmc_enable_stallguard(stepperZ3); + #if NUM_Z_STEPPERS >= 4 + stealth_states.z4 = tmc_enable_stallguard(stepperZ4); + #endif + #endif + #endif + } + endstops.set_z_sensorless_current(true); // The "homing" current also applies to probing endstops.enable(true); #endif // SENSORLESS_PROBING @@ -643,9 +654,20 @@ bool Probe::probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s) { if (test_sensitivity.x) tmc_disable_stallguard(stepperX, stealth_states.x); if (test_sensitivity.y) tmc_disable_stallguard(stepperY, stealth_states.y); #endif - if (test_sensitivity.z) tmc_disable_stallguard(stepperZ, stealth_states.z); - endstops.set_homing_current(false); - #endif + if (test_sensitivity.z) { + tmc_disable_stallguard(stepperZ, stealth_states.z); + #if ENABLED(Z_MULTI_ENDSTOPS) + tmc_disable_stallguard(stepperZ2, stealth_states.z2); + #if NUM_Z_STEPPERS >= 3 + tmc_disable_stallguard(stepperZ3, stealth_states.z3); + #if NUM_Z_STEPPERS >= 4 + tmc_disable_stallguard(stepperZ4, stealth_states.z4); + #endif + #endif + #endif + } + endstops.set_z_sensorless_current(false); + #endif // SENSORLESS_PROBING #if ENABLED(BLTOUCH) if (probe_triggered && !bltouch.high_speed_mode && bltouch.stow()) diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index d7c764540b..1f9928f88e 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -839,10 +839,10 @@ volatile bool Temperature::raw_temps_ready = false; if (current_temp > watch_temp_target) heated = true; // - Flag if target temperature reached } else if (ELAPSED(ms, temp_change_ms)) // Watch timer expired - _temp_error(heater_id, FPSTR(str_t_heating_failed), GET_TEXT_F(MSG_HEATING_FAILED_LCD)); + _TEMP_ERROR(heater_id, FPSTR(str_t_heating_failed), MSG_HEATING_FAILED_LCD, current_temp); } else if (current_temp < target - (MAX_OVERSHOOT_PID_AUTOTUNE)) // Heated, then temperature fell too far? - _temp_error(heater_id, FPSTR(str_t_thermal_runaway), GET_TEXT_F(MSG_THERMAL_RUNAWAY)); + _TEMP_ERROR(heater_id, FPSTR(str_t_thermal_runaway), MSG_THERMAL_RUNAWAY, current_temp); } #endif } // every 2 seconds @@ -1467,8 +1467,10 @@ inline void loud_kill(FSTR_P const lcd_msg, const heater_id_t heater_id) { kill(lcd_msg, HEATER_FSTR(heater_id)); } -void Temperature::_temp_error(const heater_id_t heater_id, FSTR_P const serial_msg, FSTR_P const lcd_msg) { - +void Temperature::_temp_error( + const heater_id_t heater_id, FSTR_P const serial_msg, FSTR_P const lcd_msg + OPTARG(ERR_INCLUDE_TEMP, const celsius_float_t deg) +) { static uint8_t killed = 0; if (IsRunning() && TERN1(BOGUS_TEMPERATURE_GRACE_PERIOD, killed == 2)) { @@ -1493,10 +1495,13 @@ void Temperature::_temp_error(const heater_id_t heater_id, FSTR_P const serial_m OPTCODE(HAS_TEMP_CHAMBER, case H_CHAMBER: SERIAL_ECHOPGM(STR_HEATER_CHAMBER); break) OPTCODE(HAS_TEMP_BED, case H_BED: SERIAL_ECHOPGM(STR_HEATER_BED); break) default: - if (real_heater_id >= 0) - SERIAL_ECHOLNPGM("E", real_heater_id); + if (real_heater_id >= 0) SERIAL_ECHO('E', real_heater_id); } - SERIAL_EOL(); + #if ENABLED(ERR_INCLUDE_TEMP) + SERIAL_ECHOLNPGM(STR_DETECTED_TEMP_B, deg, STR_DETECTED_TEMP_E); + #else + SERIAL_EOL(); + #endif } disable_all_heaters(); // always disable (even for bogus temp) @@ -1525,18 +1530,18 @@ void Temperature::_temp_error(const heater_id_t heater_id, FSTR_P const serial_m #endif } -void Temperature::maxtemp_error(const heater_id_t heater_id) { +void Temperature::maxtemp_error(const heater_id_t heater_id OPTARG(ERR_INCLUDE_TEMP, const celsius_float_t deg)) { #if HAS_DWIN_E3V2_BASIC && (HAS_HOTEND || HAS_HEATED_BED) dwinPopupTemperature(1); #endif - _temp_error(heater_id, F(STR_T_MAXTEMP), GET_TEXT_F(MSG_ERR_MAXTEMP)); + _TEMP_ERROR(heater_id, F(STR_T_MAXTEMP), MSG_ERR_MAXTEMP, deg); } -void Temperature::mintemp_error(const heater_id_t heater_id) { +void Temperature::mintemp_error(const heater_id_t heater_id OPTARG(ERR_INCLUDE_TEMP, const celsius_float_t deg)) { #if HAS_DWIN_E3V2_BASIC && (HAS_HOTEND || HAS_HEATED_BED) dwinPopupTemperature(0); #endif - _temp_error(heater_id, F(STR_T_MINTEMP), GET_TEXT_F(MSG_ERR_MINTEMP)); + _TEMP_ERROR(heater_id, F(STR_T_MINTEMP), MSG_ERR_MINTEMP, deg); } #if HAS_PID_DEBUG @@ -1736,7 +1741,10 @@ void Temperature::mintemp_error(const heater_id_t heater_id) { void Temperature::manage_hotends(const millis_t &ms) { HOTEND_LOOP() { #if ENABLED(THERMAL_PROTECTION_HOTENDS) - if (degHotend(e) > temp_range[e].maxtemp) maxtemp_error((heater_id_t)e); + { + const auto deg = degHotend(e); + if (deg > temp_range[e].maxtemp) MAXTEMP_ERROR(e, deg); + } #endif TERN_(HEATER_IDLE_HANDLER, heater_idle[e].update(ms)); @@ -1746,16 +1754,18 @@ void Temperature::mintemp_error(const heater_id_t heater_id) { tr_state_machine[e].run(temp_hotend[e].celsius, temp_hotend[e].target, (heater_id_t)e, THERMAL_PROTECTION_PERIOD, THERMAL_PROTECTION_HYSTERESIS); #endif - temp_hotend[e].soft_pwm_amount = (temp_hotend[e].celsius > temp_range[e].mintemp || is_hotend_preheating(e)) && temp_hotend[e].celsius < temp_range[e].maxtemp ? (int)get_pid_output_hotend(e) >> 1 : 0; + temp_hotend[e].soft_pwm_amount = (temp_hotend[e].celsius > temp_range[e].mintemp || is_hotend_preheating(e)) + && temp_hotend[e].celsius < temp_range[e].maxtemp ? (int)get_pid_output_hotend(e) >> 1 : 0; #if WATCH_HOTENDS // Make sure temperature is increasing if (watch_hotend[e].elapsed(ms)) { // Enabled and time to check? - if (watch_hotend[e].check(degHotend(e))) // Increased enough? + auto temp = degHotend(e); + if (watch_hotend[e].check(temp)) // Increased enough? start_watching_hotend(e); // If temp reached, turn off elapsed check else { TERN_(HAS_DWIN_E3V2_BASIC, dwinPopupTemperature(0)); - _temp_error((heater_id_t)e, FPSTR(str_t_heating_failed), GET_TEXT_F(MSG_HEATING_FAILED_LCD)); + _TEMP_ERROR(e, FPSTR(str_t_heating_failed), MSG_HEATING_FAILED_LCD, temp); } } #endif @@ -1770,19 +1780,25 @@ void Temperature::mintemp_error(const heater_id_t heater_id) { void Temperature::manage_heated_bed(const millis_t &ms) { #if ENABLED(THERMAL_PROTECTION_BED) - if (degBed() > BED_MAXTEMP) maxtemp_error(H_BED); + { + const auto deg = degBed(); + if (deg > BED_MAXTEMP) MAXTEMP_ERROR(H_BED, deg); + } #endif #if WATCH_BED + { // Make sure temperature is increasing if (watch_bed.elapsed(ms)) { // Time to check the bed? - if (watch_bed.check(degBed())) // Increased enough? + const auto deg = degBed(); + if (watch_bed.check(deg)) // Increased enough? start_watching_bed(); // If temp reached, turn off elapsed check else { TERN_(HAS_DWIN_E3V2_BASIC, dwinPopupTemperature(0)); - _temp_error(H_BED, FPSTR(str_t_heating_failed), GET_TEXT_F(MSG_HEATING_FAILED_LCD)); + _TEMP_ERROR(H_BED, FPSTR(str_t_heating_failed), MSG_HEATING_FAILED_LCD, deg); } } + } #endif // WATCH_BED #if ALL(PROBING_HEATERS_OFF, BED_LIMIT_SWITCHING) @@ -1860,17 +1876,23 @@ void Temperature::mintemp_error(const heater_id_t heater_id) { #endif #if ENABLED(THERMAL_PROTECTION_CHAMBER) - if (degChamber() > (CHAMBER_MAXTEMP)) maxtemp_error(H_CHAMBER); + { + const auto deg = degChamber(); + if (deg > CHAMBER_MAXTEMP) MAXTEMP_ERROR(H_CHAMBER, deg); + } #endif #if WATCH_CHAMBER + { // Make sure temperature is increasing if (watch_chamber.elapsed(ms)) { // Time to check the chamber? - if (watch_chamber.check(degChamber())) // Increased enough? Error below. + const auto deg = degChamber(); + if (watch_chamber.check(deg)) // Increased enough? Error below. start_watching_chamber(); // If temp reached, turn off elapsed check. else - _temp_error(H_CHAMBER, FPSTR(str_t_heating_failed), GET_TEXT_F(MSG_HEATING_FAILED_LCD)); + _TEMP_ERROR(H_CHAMBER, FPSTR(str_t_heating_failed), MSG_HEATING_FAILED_LCD, deg); } + } #endif #if ANY(CHAMBER_FAN, CHAMBER_VENT) || DISABLED(PIDTEMPCHAMBER) @@ -1986,16 +2008,20 @@ void Temperature::mintemp_error(const heater_id_t heater_id) { #endif #if ENABLED(THERMAL_PROTECTION_COOLER) - if (degCooler() > COOLER_MAXTEMP) maxtemp_error(H_COOLER); + { + const auto deg = degCooler(); + if (deg > COOLER_MAXTEMP) MAXTEMP_ERROR(H_COOLER, deg); + } #endif #if WATCH_COOLER // Make sure temperature is decreasing if (watch_cooler.elapsed(ms)) { // Time to check the cooler? - if (degCooler() > watch_cooler.target) // Failed to decrease enough? - _temp_error(H_COOLER, GET_TEXT_F(MSG_COOLING_FAILED), GET_TEXT_F(MSG_COOLING_FAILED)); + const auto deg = degCooler(); + if (deg > watch_cooler.target) // Failed to decrease enough? + _TEMP_ERROR(H_COOLER, GET_TEXT_F(MSG_COOLING_FAILED), MSG_COOLING_FAILED, deg); else - start_watching_cooler(); // Start again if the target is still far off + start_watching_cooler(); // Start again if the target is still far off } #endif @@ -2076,20 +2102,32 @@ void Temperature::task() { #if DISABLED(IGNORE_THERMOCOUPLE_ERRORS) #if TEMP_SENSOR_IS_MAX_TC(0) - if (degHotend(0) > _MIN(HEATER_0_MAXTEMP, TEMP_SENSOR_0_MAX_TC_TMAX - 1.0)) maxtemp_error(H_E0); - if (degHotend(0) < _MAX(HEATER_0_MINTEMP, TEMP_SENSOR_0_MAX_TC_TMIN + .01)) mintemp_error(H_E0); + { + const auto deg = degHotend(0); + if (deg > _MIN(HEATER_0_MAXTEMP, TEMP_SENSOR_0_MAX_TC_TMAX - 1.0)) MAXTEMP_ERROR(H_E0, deg); + if (deg < _MAX(HEATER_0_MINTEMP, TEMP_SENSOR_0_MAX_TC_TMIN + .01)) MINTEMP_ERROR(H_E0, deg); + } #endif #if TEMP_SENSOR_IS_MAX_TC(1) - if (degHotend(1) > _MIN(HEATER_1_MAXTEMP, TEMP_SENSOR_1_MAX_TC_TMAX - 1.0)) maxtemp_error(H_E1); - if (degHotend(1) < _MAX(HEATER_1_MINTEMP, TEMP_SENSOR_1_MAX_TC_TMIN + .01)) mintemp_error(H_E1); + { + const auto deg = degHotend(1); + if (deg > _MIN(HEATER_1_MAXTEMP, TEMP_SENSOR_1_MAX_TC_TMAX - 1.0)) MAXTEMP_ERROR(H_E1, deg); + if (deg < _MAX(HEATER_1_MINTEMP, TEMP_SENSOR_1_MAX_TC_TMIN + .01)) MINTEMP_ERROR(H_E1, deg); + } #endif #if TEMP_SENSOR_IS_MAX_TC(2) - if (degHotend(2) > _MIN(HEATER_2_MAXTEMP, TEMP_SENSOR_2_MAX_TC_TMAX - 1.0)) maxtemp_error(H_E2); - if (degHotend(2) < _MAX(HEATER_2_MINTEMP, TEMP_SENSOR_2_MAX_TC_TMIN + .01)) mintemp_error(H_E2); + { + const auto deg = degHotend(2); + if (deg > _MIN(HEATER_2_MAXTEMP, TEMP_SENSOR_2_MAX_TC_TMAX - 1.0)) MAXTEMP_ERROR(H_E2, deg); + if (deg < _MAX(HEATER_2_MINTEMP, TEMP_SENSOR_2_MAX_TC_TMIN + .01)) MINTEMP_ERROR(H_E2, deg); + } #endif #if TEMP_SENSOR_IS_MAX_TC(REDUNDANT) - if (degRedundant() > TEMP_SENSOR_REDUNDANT_MAX_TC_TMAX - 1.0) maxtemp_error(H_REDUNDANT); - if (degRedundant() < TEMP_SENSOR_REDUNDANT_MAX_TC_TMIN + .01) mintemp_error(H_REDUNDANT); + { + const auto deg = degRedundant(); + if (deg > TEMP_SENSOR_REDUNDANT_MAX_TC_TMAX - 1.0) MAXTEMP_ERROR(H_REDUNDANT, deg); + if (deg < TEMP_SENSOR_REDUNDANT_MAX_TC_TMIN + .01) MINTEMP_ERROR(H_REDUNDANT, deg); + } #endif #else #warning "Safety Alert! Disable IGNORE_THERMOCOUPLE_ERRORS for the final build!" @@ -2101,9 +2139,12 @@ void Temperature::task() { TERN_(HAS_HOTEND, manage_hotends(ms)); #if HAS_TEMP_REDUNDANT + { + const auto deg = degRedundant(); // Make sure measured temperatures are close together - if (ABS(degRedundantTarget() - degRedundant()) > TEMP_SENSOR_REDUNDANT_MAX_DIFF) - _temp_error((heater_id_t)HEATER_ID(TEMP_SENSOR_REDUNDANT_TARGET), F(STR_REDUNDANCY), GET_TEXT_F(MSG_ERR_REDUNDANT_TEMP)); + if (ABS(degRedundantTarget() - deg) > TEMP_SENSOR_REDUNDANT_MAX_DIFF) + _TEMP_ERROR(HEATER_ID(TEMP_SENSOR_REDUNDANT_TARGET), F(STR_REDUNDANCY), MSG_ERR_REDUNDANT_TEMP, deg); + } #endif // Manage extruder auto fans and/or read fan tachometers @@ -2616,7 +2657,7 @@ void Temperature::updateTemperaturesFromRawValues() { const raw_adc_t r = temp_hotend[e].getraw(); const bool neg = temp_dir[e] < 0, pos = temp_dir[e] > 0; if ((neg && r < temp_range[e].raw_max) || (pos && r > temp_range[e].raw_max)) - maxtemp_error((heater_id_t)e); + MAXTEMP_ERROR(e, temp_hotend[e].celsius); /** // DEBUG PREHEATING TIME @@ -2628,7 +2669,7 @@ void Temperature::updateTemperaturesFromRawValues() { const bool heater_on = temp_hotend[e].target > 0; if (heater_on && !is_hotend_preheating(e) && ((neg && r > temp_range[e].raw_min) || (pos && r < temp_range[e].raw_min))) { if (TERN1(MULTI_MAX_CONSECUTIVE_LOW_TEMP_ERR, ++consecutive_low_temperature_error[e] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED)) - mintemp_error((heater_id_t)e); + MINTEMP_ERROR(e, temp_hotend[e].celsius); } else { TERN_(MULTI_MAX_CONSECUTIVE_LOW_TEMP_ERR, consecutive_low_temperature_error[e] = 0); @@ -2639,27 +2680,27 @@ void Temperature::updateTemperaturesFromRawValues() { #define TP_CMP(S,A,B) (TEMPDIR(S) < 0 ? ((A)<(B)) : ((A)>(B))) #if ENABLED(THERMAL_PROTECTION_BED) - if (TP_CMP(BED, temp_bed.getraw(), maxtemp_raw_BED)) maxtemp_error(H_BED); - if (temp_bed.target > 0 && !is_bed_preheating() && TP_CMP(BED, mintemp_raw_BED, temp_bed.getraw())) mintemp_error(H_BED); + if (TP_CMP(BED, temp_bed.getraw(), maxtemp_raw_BED)) MAXTEMP_ERROR(H_BED, temp_bed.celsius); + if (temp_bed.target > 0 && !is_bed_preheating() && TP_CMP(BED, mintemp_raw_BED, temp_bed.getraw())) MINTEMP_ERROR(H_BED, temp_bed.celsius); #endif #if ALL(HAS_HEATED_CHAMBER, THERMAL_PROTECTION_CHAMBER) - if (TP_CMP(CHAMBER, temp_chamber.getraw(), maxtemp_raw_CHAMBER)) maxtemp_error(H_CHAMBER); - if (temp_chamber.target > 0 && TP_CMP(CHAMBER, mintemp_raw_CHAMBER, temp_chamber.getraw())) mintemp_error(H_CHAMBER); + if (TP_CMP(CHAMBER, temp_chamber.getraw(), maxtemp_raw_CHAMBER)) MAXTEMP_ERROR(H_CHAMBER, temp_chamber.celsius); + if (temp_chamber.target > 0 && TP_CMP(CHAMBER, mintemp_raw_CHAMBER, temp_chamber.getraw())) MINTEMP_ERROR(H_CHAMBER, temp_chamber.celsius); #endif #if ALL(HAS_COOLER, THERMAL_PROTECTION_COOLER) - if (cutter.unitPower > 0 && TP_CMP(COOLER, temp_cooler.getraw(), maxtemp_raw_COOLER)) maxtemp_error(H_COOLER); - if (TP_CMP(COOLER, mintemp_raw_COOLER, temp_cooler.getraw())) mintemp_error(H_COOLER); + if (cutter.unitPower > 0 && TP_CMP(COOLER, temp_cooler.getraw(), maxtemp_raw_COOLER)) MAXTEMP_ERROR(H_COOLER, temp_cooler.celsius); + if (TP_CMP(COOLER, mintemp_raw_COOLER, temp_cooler.getraw())) MINTEMP_ERROR(H_COOLER, temp_cooler.celsius); #endif #if ALL(HAS_TEMP_BOARD, THERMAL_PROTECTION_BOARD) - if (TP_CMP(BOARD, temp_board.getraw(), maxtemp_raw_BOARD)) maxtemp_error(H_BOARD); - if (TP_CMP(BOARD, mintemp_raw_BOARD, temp_board.getraw())) mintemp_error(H_BOARD); + if (TP_CMP(BOARD, temp_board.getraw(), maxtemp_raw_BOARD)) MAXTEMP_ERROR(H_BOARD, temp_board.celsius); + if (TP_CMP(BOARD, mintemp_raw_BOARD, temp_board.getraw())) MINTEMP_ERROR(H_BOARD, temp_board.celsius); #endif #if ALL(HAS_TEMP_SOC, THERMAL_PROTECTION_SOC) - if (TP_CMP(SOC, temp_soc.getraw(), maxtemp_raw_SOC)) maxtemp_error(H_SOC); + if (TP_CMP(SOC, temp_soc.getraw(), maxtemp_raw_SOC)) MAXTEMP_ERROR(H_SOC, temp_soc.celsius); #endif #undef TP_CMP @@ -3178,12 +3219,12 @@ void Temperature::init() { case TRRunaway: TERN_(HAS_DWIN_E3V2_BASIC, dwinPopupTemperature(0)); - _temp_error(heater_id, FPSTR(str_t_thermal_runaway), GET_TEXT_F(MSG_THERMAL_RUNAWAY)); + _TEMP_ERROR(heater_id, FPSTR(str_t_thermal_runaway), MSG_THERMAL_RUNAWAY, current); #if ENABLED(THERMAL_PROTECTION_VARIANCE_MONITOR) case TRMalfunction: TERN_(HAS_DWIN_E3V2_BASIC, dwinPopupTemperature(0)); - _temp_error(heater_id, FPSTR(str_t_temp_malfunction), GET_TEXT_F(MSG_TEMP_MALFUNCTION)); + _TEMP_ERROR(heater_id, FPSTR(str_t_temp_malfunction), MSG_TEMP_MALFUNCTION, current); #endif } } diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index a8873bf2af..d5a27a8671 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -41,6 +41,8 @@ #include "../feature/fancheck.h" #endif +//#define ERR_INCLUDE_TEMP + #define HOTEND_INDEX TERN(HAS_MULTI_HOTEND, e, 0) #define E_NAME TERN_(HAS_MULTI_HOTEND, e) @@ -1360,9 +1362,13 @@ class Temperature { static float get_pid_output_chamber(); #endif - static void _temp_error(const heater_id_t e, FSTR_P const serial_msg, FSTR_P const lcd_msg); - static void mintemp_error(const heater_id_t e); - static void maxtemp_error(const heater_id_t e); + static void _temp_error(const heater_id_t e, FSTR_P const serial_msg, FSTR_P const lcd_msg OPTARG(ERR_INCLUDE_TEMP, const celsius_float_t deg)); + static void mintemp_error(const heater_id_t e OPTARG(ERR_INCLUDE_TEMP, const celsius_float_t deg)); + static void maxtemp_error(const heater_id_t e OPTARG(ERR_INCLUDE_TEMP, const celsius_float_t deg)); + + #define _TEMP_ERROR(e, m, l, d) _temp_error(heater_id_t(e), m, GET_TEXT_F(l) OPTARG(ERR_INCLUDE_TEMP, d)) + #define MINTEMP_ERROR(e, d) mintemp_error(heater_id_t(e) OPTARG(ERR_INCLUDE_TEMP, d)) + #define MAXTEMP_ERROR(e, d) maxtemp_error(heater_id_t(e) OPTARG(ERR_INCLUDE_TEMP, d)) #define HAS_THERMAL_PROTECTION ANY(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_CHAMBER, THERMAL_PROTECTION_BED, THERMAL_PROTECTION_COOLER) diff --git a/buildroot/share/PlatformIO/scripts/generic_create_variant.py b/buildroot/share/PlatformIO/scripts/generic_create_variant.py index 49d4c98d3e..2dd65399bb 100644 --- a/buildroot/share/PlatformIO/scripts/generic_create_variant.py +++ b/buildroot/share/PlatformIO/scripts/generic_create_variant.py @@ -5,7 +5,8 @@ # the appropriate framework variants folder, so that its contents # will be picked up by PlatformIO just like any other variant. # -import pioutil +import pioutil, re +marlin_variant_pattern = re.compile("marlin_.*") if pioutil.is_pio_build(): import shutil,marlin from pathlib import Path @@ -32,7 +33,7 @@ if pioutil.is_pio_build(): else: platform_name = PackageSpec(platform_packages[0]).name - if platform_name in [ "usb-host-msc", "usb-host-msc-cdc-msc", "usb-host-msc-cdc-msc-2", "usb-host-msc-cdc-msc-3", "tool-stm32duino", "biqu-bx-workaround", "main" ]: + if platform_name in [ "Arduino_Core_STM32", "usb-host-msc", "usb-host-msc-cdc-msc", "usb-host-msc-cdc-msc-2", "usb-host-msc-cdc-msc-3", "tool-stm32duino", "biqu-bx-workaround", "main" ]: platform_name = "framework-arduinoststm32" FRAMEWORK_DIR = Path(platform.get_package_dir(platform_name)) @@ -44,15 +45,20 @@ if pioutil.is_pio_build(): variant = board.get("build.variant") #series = mcu_type[:7].upper() + "xx" - # Prepare a new empty folder at the destination - variant_dir = FRAMEWORK_DIR / "variants" / variant - if variant_dir.is_dir(): - shutil.rmtree(variant_dir) - if not variant_dir.is_dir(): - variant_dir.mkdir() + # Only prepare a new variant if the PlatformIO configuration provides it (board_build.variant). + # This check is important to avoid deleting official board config variants. + if marlin_variant_pattern.match(str(variant).lower()): + # Prepare a new empty folder at the destination + variant_dir = FRAMEWORK_DIR / "variants" / variant + if variant_dir.is_dir(): + shutil.rmtree(variant_dir) + if not variant_dir.is_dir(): + variant_dir.mkdir() - # Source dir is a local variant sub-folder - source_dir = Path("buildroot/share/PlatformIO/variants", variant) - assert source_dir.is_dir() + # Source dir is a local variant sub-folder + source_dir = Path("buildroot/share/PlatformIO/variants", variant) + assert source_dir.is_dir() - marlin.copytree(source_dir, variant_dir) + print("Copying variant " + str(variant) + " to framework directory...") + + marlin.copytree(source_dir, variant_dir) diff --git a/buildroot/tests/BIGTREE_BTT002 b/buildroot/tests/BIGTREE_BTT002 index 7288c5ef52..5398d30fea 100755 --- a/buildroot/tests/BIGTREE_BTT002 +++ b/buildroot/tests/BIGTREE_BTT002 @@ -12,8 +12,8 @@ set -e restore_configs opt_set MOTHERBOARD BOARD_BTT_BTT002_V1_0 \ SERIAL_PORT 1 \ - X_DRIVER_TYPE TMC2209 \ - Y_DRIVER_TYPE TMC2130 + X_DRIVER_TYPE TMC2209 Y_DRIVER_TYPE TMC2130 +opt_enable SENSORLESS_HOMING X_STALL_SENSITIVITY Y_STALL_SENSITIVITY SPI_ENDSTOPS exec_test $1 $2 "BigTreeTech BTT002 Default Configuration plus TMC steppers" "$3" # diff --git a/buildroot/tests/FYSETC_F6 b/buildroot/tests/FYSETC_F6 index 314e207c58..713408b550 100755 --- a/buildroot/tests/FYSETC_F6 +++ b/buildroot/tests/FYSETC_F6 @@ -50,9 +50,16 @@ opt_set MOTHERBOARD BOARD_FYSETC_F6_13 \ opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER \ MARLIN_BRICKOUT MARLIN_INVADERS MARLIN_SNAKE \ MONITOR_DRIVER_STATUS STEALTHCHOP_XY STEALTHCHOP_Z STEALTHCHOP_E HYBRID_THRESHOLD \ - SENSORLESS_HOMING TMC_DEBUG M114_DETAIL + SENSORLESS_HOMING X_STALL_SENSITIVITY Y_STALL_SENSITIVITY TMC_DEBUG M114_DETAIL exec_test $1 $2 "Mixed TMC | Sensorless | RRDFGSC | Games" "$3" +# +# Delta Config (FLSUN AC because it's complex) +# +use_example_configs delta/FLSUN/auto_calibrate +opt_set MOTHERBOARD BOARD_FYSETC_F6_13 +exec_test $1 $2 "RAMPS 1.3 | DELTA | FLSUN AC Config" "$3" + # # SCARA with Mixed TMC # @@ -64,7 +71,7 @@ opt_set MOTHERBOARD BOARD_FYSETC_F6_13 \ X_HARDWARE_SERIAL Serial2 opt_enable FIX_MOUNTED_PROBE AUTO_BED_LEVELING_BILINEAR PAUSE_BEFORE_DEPLOY_STOW \ FYSETC_242_OLED_12864 EEPROM_SETTINGS EEPROM_CHITCHAT M114_DETAIL Z_SAFE_HOMING \ - STEALTHCHOP_XY STEALTHCHOP_Z STEALTHCHOP_E HYBRID_THRESHOLD SENSORLESS_HOMING EDGE_STEPPING + STEALTHCHOP_XY STEALTHCHOP_Z STEALTHCHOP_E HYBRID_THRESHOLD SENSORLESS_HOMING X_STALL_SENSITIVITY Y_STALL_SENSITIVITY EDGE_STEPPING exec_test $1 $2 "SCARA | Mixed TMC | EEPROM" "$3" # clean up diff --git a/buildroot/tests/LPC1769 b/buildroot/tests/LPC1769 index a7348bffe9..9987d155ad 100755 --- a/buildroot/tests/LPC1769 +++ b/buildroot/tests/LPC1769 @@ -53,14 +53,15 @@ opt_set MOTHERBOARD BOARD_COHESION3D_REMIX \ HOMING_FEEDRATE_MM_M '{ (50*60), (50*60), (4*60), (50*60) }' \ HOMING_BUMP_MM '{ 0, 0, 0, 0 }' HOMING_BUMP_DIVISOR '{ 1, 1, 1, 1 }' \ NOZZLE_TO_PROBE_OFFSET '{ 0, 0, 0, 0 }' \ - I_MIN_PIN P1_25 + I_MIN_PIN P1_25 \ + X_CURRENT_HOME 750 Y_CURRENT_HOME 750 Z_CURRENT_HOME 750 opt_enable AUTO_BED_LEVELING_BILINEAR EEPROM_SETTINGS EEPROM_CHITCHAT MECHANICAL_GANTRY_CALIBRATION \ TMC_USE_SW_SPI MONITOR_DRIVER_STATUS STEALTHCHOP_XY STEALTHCHOP_Z HYBRID_THRESHOLD \ - SENSORLESS_PROBING Z_SAFE_HOMING X_STALL_SENSITIVITY Y_STALL_SENSITIVITY Z_STALL_SENSITIVITY TMC_DEBUG \ + SENSORLESS_PROBING SENSORLESS_HOMING Z_SAFE_HOMING X_STALL_SENSITIVITY Y_STALL_SENSITIVITY Z_STALL_SENSITIVITY TMC_DEBUG \ AXIS4_ROTATES I_MIN_POS I_MAX_POS I_HOME_DIR I_ENABLE_ON INVERT_I_DIR \ EXPERIMENTAL_I2CBUS opt_disable PSU_CONTROL Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN -exec_test $1 $2 "Cohesion3D Remix DELTA + ABL Bilinear + EEPROM + SENSORLESS_PROBING + I Axis" "$3" +exec_test $1 $2 "Cohesion3D Remix DELTA | ABL Bilinear | EEPROM | Sensorless Homing/Probing | I Axis" "$3" # clean up restore_configs diff --git a/buildroot/tests/SAMD21_minitronics20 b/buildroot/tests/SAMD21_minitronics20 index f4a75afafe..ae9fa55ea4 100755 --- a/buildroot/tests/SAMD21_minitronics20 +++ b/buildroot/tests/SAMD21_minitronics20 @@ -25,8 +25,7 @@ opt_enable ENDSTOP_INTERRUPTS_FEATURE BLTOUCH Z_MIN_PROBE_REPEATABILITY_TEST \ LONG_FILENAME_HOST_SUPPORT CUSTOM_FIRMWARE_UPLOAD M20_TIMESTAMP_SUPPORT \ SCROLL_LONG_FILENAMES BABYSTEPPING DOUBLECLICK_FOR_Z_BABYSTEPPING \ MOVE_Z_WHEN_IDLE BABYSTEP_ZPROBE_OFFSET BABYSTEP_GFX_OVERLAY \ - LIN_ADVANCE ADVANCED_PAUSE_FEATURE PARK_HEAD_ON_PAUSE MONITOR_DRIVER_STATUS SENSORLESS_HOMING \ - EDGE_STEPPING + LIN_ADVANCE ADVANCED_PAUSE_FEATURE PARK_HEAD_ON_PAUSE MONITOR_DRIVER_STATUS exec_test $1 $2 "Minitronics 2.0 with assorted features" "$3" # clean up diff --git a/buildroot/tests/SAMD51_grandcentral_m4 b/buildroot/tests/SAMD51_grandcentral_m4 index 72996e7b7f..312bd627ba 100755 --- a/buildroot/tests/SAMD51_grandcentral_m4 +++ b/buildroot/tests/SAMD51_grandcentral_m4 @@ -25,7 +25,8 @@ opt_enable ENDSTOP_INTERRUPTS_FEATURE S_CURVE_ACCELERATION BLTOUCH Z_MIN_PROBE_R LONG_FILENAME_HOST_SUPPORT CUSTOM_FIRMWARE_UPLOAD M20_TIMESTAMP_SUPPORT \ SCROLL_LONG_FILENAMES BABYSTEPPING DOUBLECLICK_FOR_Z_BABYSTEPPING \ MOVE_Z_WHEN_IDLE BABYSTEP_ZPROBE_OFFSET BABYSTEP_GFX_OVERLAY \ - LIN_ADVANCE ADVANCED_PAUSE_FEATURE PARK_HEAD_ON_PAUSE MONITOR_DRIVER_STATUS SENSORLESS_HOMING \ + LIN_ADVANCE ADVANCED_PAUSE_FEATURE PARK_HEAD_ON_PAUSE MONITOR_DRIVER_STATUS \ + SENSORLESS_HOMING X_STALL_SENSITIVITY Y_STALL_SENSITIVITY Z_STALL_SENSITIVITY Z2_STALL_SENSITIVITY \ EDGE_STEPPING TMC_DEBUG exec_test $1 $2 "Grand Central M4 with assorted features" "$3" diff --git a/buildroot/tests/mega1280 b/buildroot/tests/mega1280 index 53016e8406..7e99ee4a60 100755 --- a/buildroot/tests/mega1280 +++ b/buildroot/tests/mega1280 @@ -41,6 +41,7 @@ opt_set MOTHERBOARD BOARD_ZRIB_V52 \ LCD_LANGUAGE pt REPRAPWORLD_KEYPAD_MOVE_STEP 10.0 \ EXTRUDERS 2 TEMP_SENSOR_1 1 X2_DRIVER_TYPE A4988 opt_enable DUAL_X_CARRIAGE REPRAPWORLD_KEYPAD +opt_add DEBUG_DXC_MODE exec_test $1 $2 "ZRIB_V52 | DUAL_X_CARRIAGE" "$3" # diff --git a/buildroot/tests/teensy35 b/buildroot/tests/teensy35 index 959a207aee..4a752c7f5a 100755 --- a/buildroot/tests/teensy35 +++ b/buildroot/tests/teensy35 @@ -85,9 +85,10 @@ exec_test $1 $2 "Mixing Extruder" "$3" restore_configs opt_set MOTHERBOARD BOARD_TEENSY35_36 \ X_DRIVER_TYPE TMC5160 Y_DRIVER_TYPE TMC5160 \ + X_CURRENT_HOME 750 Y_CURRENT_HOME 750 \ X_MIN_ENDSTOP_HIT_STATE LOW Y_MIN_ENDSTOP_HIT_STATE LOW \ X_CS_PIN 46 Y_CS_PIN 47 -opt_enable COREXY MONITOR_DRIVER_STATUS SENSORLESS_HOMING +opt_enable COREXY MONITOR_DRIVER_STATUS SENSORLESS_HOMING X_STALL_SENSITIVITY Y_STALL_SENSITIVITY exec_test $1 $2 "Teensy 3.5/3.6 COREXY" "$3" # diff --git a/ini/renamed.ini b/ini/renamed.ini index 9d2706e3b3..91ac55f5b2 100644 --- a/ini/renamed.ini +++ b/ini/renamed.ini @@ -21,6 +21,12 @@ board = genericSTM32F103RE # List of environment names that are no longer used # +[env:megaatmega1280] ;=> mega1280 +extends = renamed + +[env:megaatmega2560] ;=> mega2560 +extends = renamed + [env:STM32F103RET6_creality_maple] ;=> STM32F103RE_creality_maple extends = renamed