Merge branch 'bugfix-2.0.x' of https://github.com/MarlinFirmware/Marlin into bugfix-2.0.x

This commit is contained in:
InsanityAutomation
2021-05-16 14:18:43 -04:00
157 changed files with 5240 additions and 1420 deletions
+2
View File
@@ -72,6 +72,7 @@ jobs:
# STM32 (ST) Environments
- STM32F103RC_btt_stm32
- STM32F407VE_black
- STM32F401VE_STEVAL
- BIGTREE_BTT002
@@ -86,6 +87,7 @@ jobs:
- FLYF407ZG
- rumba32
- LERDGEX
- LERDGEK
- mks_robin_nano35_stm32
- NUCLEO_F767ZI
- REMRAM_V1
+9 -2
View File
@@ -35,7 +35,7 @@
*
* Advanced settings can be found in Configuration_adv.h
*/
#define CONFIGURATION_H_VERSION 020008
#define CONFIGURATION_H_VERSION 02000801
//===========================================================================
//============================= Getting Started =============================
@@ -111,6 +111,13 @@
*/
//#define SERIAL_PORT_2 -1
/**
* Select a third serial port on the board to use for communication with the host.
* Currently only supported for AVR, DUE, LPC1768/9 and STM32/STM32F1
* :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
//#define SERIAL_PORT_3 1
/**
* This setting determines the communication speed of the printer.
*
@@ -2564,7 +2571,7 @@
//#define DWIN_CREALITY_LCD
//
// ADS7843/XPT2046 ADC Touchscreen such as ILI9341 2.8
// Touch Screen Settings
//
//#define TOUCH_SCREEN
#if ENABLED(TOUCH_SCREEN)
+27 -11
View File
@@ -30,7 +30,7 @@
*
* Basic settings can be found in Configuration.h
*/
#define CONFIGURATION_ADV_H_VERSION 020008
#define CONFIGURATION_ADV_H_VERSION 02000801
//===========================================================================
//============================= Thermal Settings ============================
@@ -1486,8 +1486,8 @@
#if ENABLED(MULTI_VOLUME)
#define VOLUME_SD_ONBOARD
#define VOLUME_USB_FLASH_DRIVE
#define DEFAULT_VOLUME SD_ONBOARD
#define DEFAULT_SHARED_VOLUME USB_FLASH_DRIVE
#define DEFAULT_VOLUME SV_SD_ONBOARD
#define DEFAULT_SHARED_VOLUME SV_USB_FLASH_DRIVE
#endif
#endif // SDSUPPORT
@@ -2301,14 +2301,15 @@
#endif // HAS_MULTI_EXTRUDER
/**
* Advanced Pause
* Experimental feature for filament change support and for parking the nozzle when paused.
* Adds the GCode M600 for initiating filament change.
* If PARK_HEAD_ON_PAUSE enabled, adds the GCode M125 to pause printing and park the nozzle.
* Advanced Pause for Filament Change
* - Adds the G-code M600 Filament Change to initiate a filament change.
* - This feature is required for the default FILAMENT_RUNOUT_SCRIPT.
*
* Requires an LCD display.
* Requires NOZZLE_PARK_FEATURE.
* This feature is required for the default FILAMENT_RUNOUT_SCRIPT.
* Requirements:
* - For Filament Change parking enable and configure NOZZLE_PARK_FEATURE.
* - For user interaction enable an LCD display, HOST_PROMPT_SUPPORT, or EMERGENCY_PARSER.
*
* Enable PARK_HEAD_ON_PAUSE to add the G-code M125 Pause and Park.
*/
//#define ADVANCED_PAUSE_FEATURE
#if ENABLED(ADVANCED_PAUSE_FEATURE)
@@ -3415,6 +3416,11 @@
*/
#define AUTO_REPORT_TEMPERATURES
/**
* Auto-report position with M154 S<seconds>
*/
//#define AUTO_REPORT_POSITION
/**
* Include capabilities in M115 output
*/
@@ -3484,7 +3490,7 @@
#define PROPORTIONAL_FONT_RATIO 1.0
/**
* Spend 28 bytes of SRAM to optimize the GCode parser
* Spend 28 bytes of SRAM to optimize the G-code parser
*/
#define FASTER_GCODE_PARSER
@@ -3780,6 +3786,16 @@
#define GANTRY_CALIBRATION_COMMANDS_POST "G28" // G28 highly recommended to ensure an accurate position
#endif
/**
* Instant freeze / unfreeze functionality
* Specified pin has pullup and connecting to ground will instantly pause motion.
* Potentially useful for emergency stop that allows being resumed.
*/
//#define FREEZE_FEATURE
#if ENABLED(FREEZE_FEATURE)
//#define FREEZE_PIN 41 // Override the default (KILL) pin here
#endif
/**
* MAX7219 Debug Matrix
*
+11 -4
View File
@@ -93,28 +93,35 @@ typedef int8_t pin_t;
#define MYSERIAL1 TERN(BLUETOOTH, btSerial, MSerial0)
#else
#if !WITHIN(SERIAL_PORT, -1, 3)
#error "SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#error "SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
#endif
#define MYSERIAL1 customizedSerial1
#ifdef SERIAL_PORT_2
#if !WITHIN(SERIAL_PORT_2, -1, 3)
#error "SERIAL_PORT_2 must be from 0 to 3. You can also use -1 if the board supports Native USB."
#error "SERIAL_PORT_2 must be from 0 to 3, or -1 for USB Serial."
#endif
#define MYSERIAL2 customizedSerial2
#endif
#ifdef SERIAL_PORT_3
#if !WITHIN(SERIAL_PORT_3, -1, 3)
#error "SERIAL_PORT_3 must be from 0 to 3, or -1 for USB Serial."
#endif
#define MYSERIAL3 customizedSerial3
#endif
#endif
#ifdef MMU2_SERIAL_PORT
#if !WITHIN(MMU2_SERIAL_PORT, -1, 3)
#error "MMU2_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#error "MMU2_SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
#endif
#define MMU2_SERIAL mmuSerial
#endif
#ifdef LCD_SERIAL_PORT
#if !WITHIN(LCD_SERIAL_PORT, -1, 3)
#error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#error "LCD_SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
#endif
#define LCD_SERIAL lcdSerial
#if HAS_DGUS_LCD
+20 -4
View File
@@ -567,7 +567,7 @@ ISR(SERIAL_REGNAME(USART, SERIAL_PORT, _UDRE_vect)) {
// Because of the template definition above, it's required to instantiate the template to have all methods generated
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT> >;
MSerialT customizedSerial1(MSerialT::HasEmergencyParser);
MSerialT1 customizedSerial1(MSerialT1::HasEmergencyParser);
#ifdef SERIAL_PORT_2
@@ -585,6 +585,22 @@ MSerialT customizedSerial1(MSerialT::HasEmergencyParser);
#endif // SERIAL_PORT_2
#ifdef SERIAL_PORT_3
// Hookup ISR handlers
ISR(SERIAL_REGNAME(USART, SERIAL_PORT_3, _RX_vect)) {
MarlinSerial<MarlinSerialCfg<SERIAL_PORT_3>>::store_rxd_char();
}
ISR(SERIAL_REGNAME(USART, SERIAL_PORT_3, _UDRE_vect)) {
MarlinSerial<MarlinSerialCfg<SERIAL_PORT_3>>::_tx_udr_empty_irq();
}
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> >;
MSerialT3 customizedSerial3(MSerialT3::HasEmergencyParser);
#endif // SERIAL_PORT_3
#ifdef MMU2_SERIAL_PORT
ISR(SERIAL_REGNAME(USART, MMU2_SERIAL_PORT, _RX_vect)) {
@@ -596,7 +612,7 @@ MSerialT customizedSerial1(MSerialT::HasEmergencyParser);
}
template class MarlinSerial< MMU2SerialCfg<MMU2_SERIAL_PORT> >;
MSerialT3 mmuSerial(MSerialT3::HasEmergencyParser);
MSerialMMU2 mmuSerial(MSerialMMU2::HasEmergencyParser);
#endif // MMU2_SERIAL_PORT
@@ -611,7 +627,7 @@ MSerialT customizedSerial1(MSerialT::HasEmergencyParser);
}
template class MarlinSerial< LCDSerialCfg<LCD_SERIAL_PORT> >;
MSerialT4 lcdSerial(MSerialT4::HasEmergencyParser);
MSerialLCD lcdSerial(MSerialLCD::HasEmergencyParser);
#if HAS_DGUS_LCD
template<typename Cfg>
@@ -630,7 +646,7 @@ MSerialT customizedSerial1(MSerialT::HasEmergencyParser);
// For AT90USB targets use the UART for BT interfacing
#if defined(USBCON) && ENABLED(BLUETOOTH)
MSerialT5 bluetoothSerial(false);
MSerialBT bluetoothSerial(false);
#endif
#endif // __AVR__
+13 -8
View File
@@ -238,14 +238,19 @@
static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED);
};
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT;
extern MSerialT customizedSerial1;
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT1;
extern MSerialT1 customizedSerial1;
#ifdef SERIAL_PORT_2
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
extern MSerialT2 customizedSerial2;
#endif
#ifdef SERIAL_PORT_3
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> > > MSerialT3;
extern MSerialT3 customizedSerial3;
#endif
#endif // !USBCON
#ifdef MMU2_SERIAL_PORT
@@ -262,8 +267,8 @@
static constexpr bool RX_OVERRUNS = false;
};
typedef Serial1Class< MarlinSerial< MMU2SerialCfg<MMU2_SERIAL_PORT> > > MSerialT3;
extern MSerialT3 mmuSerial;
typedef Serial1Class< MarlinSerial< MMU2SerialCfg<MMU2_SERIAL_PORT> > > MSerialMMU2;
extern MSerialMMU2 mmuSerial;
#endif
#ifdef LCD_SERIAL_PORT
@@ -281,12 +286,12 @@
static constexpr bool RX_OVERRUNS = BOTH(HAS_DGUS_LCD, SERIAL_STATS_RX_BUFFER_OVERRUNS);
};
typedef Serial1Class< MarlinSerial< LCDSerialCfg<LCD_SERIAL_PORT> > > MSerialT4;
extern MSerialT4 lcdSerial;
typedef Serial1Class< MarlinSerial< LCDSerialCfg<LCD_SERIAL_PORT> > > MSerialLCD;
extern MSerialLCD lcdSerial;
#endif
// Use the UART for Bluetooth in AT90USB configurations
#if defined(USBCON) && ENABLED(BLUETOOTH)
typedef Serial1Class<HardwareSerial> MSerialT5;
extern MSerialT5 bluetoothSerial;
typedef Serial1Class<HardwareSerial> MSerialBT;
extern MSerialBT bluetoothSerial;
#endif
+14 -7
View File
@@ -50,13 +50,12 @@ extern DefaultSerial4 MSerial3;
#define _MSERIAL(X) MSerial##X
#define MSERIAL(X) _MSERIAL(X)
// Define MYSERIAL1/2 before MarlinSerial includes!
#if SERIAL_PORT == -1 || ENABLED(EMERGENCY_PARSER)
#define MYSERIAL1 customizedSerial1
#elif WITHIN(SERIAL_PORT, 0, 3)
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
#error "The required SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#error "The required SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
#endif
#ifdef SERIAL_PORT_2
@@ -65,7 +64,17 @@ extern DefaultSerial4 MSerial3;
#elif WITHIN(SERIAL_PORT_2, 0, 3)
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
#error "SERIAL_PORT_2 must be from 0 to 3. You can also use -1 if the board supports Native USB."
#error "SERIAL_PORT_2 must be from 0 to 3, or -1 for USB Serial."
#endif
#endif
#ifdef SERIAL_PORT_3
#if SERIAL_PORT_3 == -1 || ENABLED(EMERGENCY_PARSER)
#define MYSERIAL3 customizedSerial3
#elif WITHIN(SERIAL_PORT_3, 0, 3)
#define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
#else
#error "SERIAL_PORT_3 must be from 0 to 3, or -1 for USB Serial."
#endif
#endif
@@ -78,12 +87,10 @@ extern DefaultSerial4 MSerial3;
#endif
#ifdef LCD_SERIAL_PORT
#if LCD_SERIAL_PORT == -1
#define LCD_SERIAL lcdSerial
#elif WITHIN(LCD_SERIAL_PORT, 0, 3)
#if WITHIN(LCD_SERIAL_PORT, 0, 3)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
#error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#error "LCD_SERIAL_PORT must be from 0 to 3."
#endif
#endif
+6 -1
View File
@@ -478,7 +478,7 @@ void MarlinSerial<Cfg>::flushTX() {
// If not using the USB port as serial port
#if defined(SERIAL_PORT) && SERIAL_PORT >= 0
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT> >;
MSerialT customizedSerial1(MarlinSerialCfg<SERIAL_PORT>::EMERGENCYPARSER);
MSerialT1 customizedSerial1(MarlinSerialCfg<SERIAL_PORT>::EMERGENCYPARSER);
#endif
#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
@@ -486,4 +486,9 @@ void MarlinSerial<Cfg>::flushTX() {
MSerialT2 customizedSerial2(MarlinSerialCfg<SERIAL_PORT_2>::EMERGENCYPARSER);
#endif
#if defined(SERIAL_PORT_3) && SERIAL_PORT_3 >= 0
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> >;
MSerialT3 customizedSerial3(MarlinSerialCfg<SERIAL_PORT_3>::EMERGENCYPARSER);
#endif
#endif // ARDUINO_ARCH_SAM
+7 -2
View File
@@ -141,11 +141,16 @@ struct MarlinSerialCfg {
};
#if defined(SERIAL_PORT) && SERIAL_PORT >= 0
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT;
extern MSerialT customizedSerial1;
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT1;
extern MSerialT1 customizedSerial1;
#endif
#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
extern MSerialT2 customizedSerial2;
#endif
#if defined(SERIAL_PORT_3) && SERIAL_PORT_3 >= 0
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> > > MSerialT3;
extern MSerialT3 customizedSerial3;
#endif
+8 -5
View File
@@ -19,13 +19,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef ARDUINO_ARCH_SAM
/**
* MarlinSerial_Due.cpp - Hardware serial library for Arduino DUE
* Copyright (c) 2017 Eduardo José Tagle. All right reserved
* Based on MarlinSerial for AVR, copyright (c) 2006 Nicholas Zambetti. All right reserved.
*/
#ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h"
@@ -65,7 +65,7 @@ int MarlinSerialUSB::peek() {
pending_char = udi_cdc_getc();
TERN_(EMERGENCY_PARSER, emergency_parser.update(static_cast<MSerialT*>(this)->emergency_state, (char)pending_char));
TERN_(EMERGENCY_PARSER, emergency_parser.update(static_cast<MSerialT1*>(this)->emergency_state, (char)pending_char));
return pending_char;
}
@@ -87,7 +87,7 @@ int MarlinSerialUSB::read() {
int c = udi_cdc_getc();
TERN_(EMERGENCY_PARSER, emergency_parser.update(static_cast<MSerialT*>(this)->emergency_state, (char)c));
TERN_(EMERGENCY_PARSER, emergency_parser.update(static_cast<MSerialT1*>(this)->emergency_state, (char)c));
return c;
}
@@ -129,10 +129,13 @@ size_t MarlinSerialUSB::write(const uint8_t c) {
// Preinstantiate
#if SERIAL_PORT == -1
MSerialT customizedSerial1(TERN0(EMERGENCY_PARSER, true));
MSerialT1 customizedSerial1(TERN0(EMERGENCY_PARSER, true));
#endif
#if SERIAL_PORT_2 == -1
MSerialT customizedSerial2(TERN0(EMERGENCY_PARSER, true));
MSerialT2 customizedSerial2(TERN0(EMERGENCY_PARSER, true));
#endif
#if SERIAL_PORT_3 == -1
MSerialT3 customizedSerial3(TERN0(EMERGENCY_PARSER, true));
#endif
#endif // HAS_USB_SERIAL
+9 -7
View File
@@ -27,11 +27,9 @@
*/
#include "../../inc/MarlinConfig.h"
#if HAS_USB_SERIAL
#include <WString.h>
#include "../../core/serial_hook.h"
#include <WString.h>
struct MarlinSerialUSB {
void begin(const long);
@@ -50,14 +48,18 @@ struct MarlinSerialUSB {
FORCE_INLINE int rxMaxEnqueued() { return 0; }
#endif
};
typedef Serial1Class<MarlinSerialUSB> MSerialT;
#if SERIAL_PORT == -1
extern MSerialT customizedSerial1;
typedef Serial1Class<MarlinSerialUSB> MSerialT1;
extern MSerialT1 customizedSerial1;
#endif
#if SERIAL_PORT_2 == -1
extern MSerialT customizedSerial2;
typedef Serial1Class<MarlinSerialUSB> MSerialT2;
extern MSerialT2 customizedSerial2;
#endif
#endif // HAS_USB_SERIAL
#if SERIAL_PORT_3 == -1
typedef Serial1Class<MarlinSerialUSB> MSerialT3;
extern MSerialT3 customizedSerial3;
#endif
+1 -1
View File
@@ -29,7 +29,7 @@
#include "wifi.h"
#include <ESPAsyncWebServer.h>
MSerialT webSocketSerial(false);
MSerialWebSocketT webSocketSerial(false);
AsyncWebSocket ws("/ws"); // TODO Move inside the class.
// RingBuffer impl
+2 -2
View File
@@ -81,5 +81,5 @@ public:
#endif
};
typedef Serial1Class<WebSocketSerial> MSerialT;
extern MSerialT webSocketSerial;
typedef Serial1Class<WebSocketSerial> MSerialWebSocketT;
extern MSerialWebSocketT webSocketSerial;
+10
View File
@@ -84,6 +84,16 @@ extern DefaultSerial1 USBSerial;
#endif
#endif
#ifdef SERIAL_PORT_3
#if SERIAL_PORT_3 == -1
#define MYSERIAL3 USBSerial
#elif WITHIN(SERIAL_PORT_3, 0, 3)
#define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
#else
#error "SERIAL_PORT_3 must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef MMU2_SERIAL_PORT
#if MMU2_SERIAL_PORT == -1
#define MMU2_SERIAL USBSerial
+4 -4
View File
@@ -26,9 +26,9 @@
#include "../../inc/MarlinConfig.h"
#if USING_HW_SERIAL0
MarlinSerial _MSerial(LPC_UART0);
MSerialT MSerial0(true, _MSerial);
extern "C" void UART0_IRQHandler() { _MSerial.IRQHandler(); }
MarlinSerial _MSerial0(LPC_UART0);
MSerialT MSerial0(true, _MSerial0);
extern "C" void UART0_IRQHandler() { _MSerial0.IRQHandler(); }
#endif
#if USING_HW_SERIAL1
MarlinSerial _MSerial1((LPC_UART_TypeDef *) LPC_UART1);
@@ -52,7 +52,7 @@
// Need to figure out which serial port we are and react in consequence (Marlin does not have CONTAINER_OF macro)
if (false) {}
#if USING_HW_SERIAL0
else if (this == &_MSerial) emergency_parser.update(MSerial0.emergency_state, c);
else if (this == &_MSerial0) emergency_parser.update(MSerial0.emergency_state, c);
#endif
#if USING_HW_SERIAL1
else if (this == &_MSerial1) emergency_parser.update(MSerial1.emergency_state, c);
+1 -1
View File
@@ -22,7 +22,7 @@
#include "../../../inc/MarlinConfig.h"
#if HAS_TFT_XPT2046 || HAS_TOUCH_BUTTONS
#if HAS_TFT_XPT2046 || HAS_RES_TOUCH_BUTTONS
#include "xpt2046.h"
#include <SPI.h>
-2
View File
@@ -43,8 +43,6 @@
extern DefaultSerial4 MSerial3;
extern DefaultSerial5 MSerial4;
// MYSERIAL1 required before MarlinSerial includes!
#define __MSERIAL(X) MSerial##X
#define _MSERIAL(X) __MSERIAL(X)
#define MSERIAL(X) _MSERIAL(INCREMENT(X))
+6
View File
@@ -96,6 +96,12 @@ void HAL_init() {
#if HAS_SD_HOST_DRIVE
MSC_SD_init(); // Enable USB SD card access
#endif
#if PIN_EXISTS(USB_CONNECT)
OUT_WRITE(USB_CONNECT_PIN, !USB_CONNECT_INVERTING); // USB clear connection
delay(1000); // Give OS time to notice
WRITE(USB_CONNECT_PIN, USB_CONNECT_INVERTING);
#endif
}
// HAL idle task
+13 -3
View File
@@ -37,6 +37,9 @@
#include <stdint.h>
//
// Serial Ports
//
#ifdef USBCON
#include <USBSerial.h>
#include "../../core/serial_hook.h"
@@ -44,9 +47,6 @@
extern DefaultSerial1 MSerial0;
#endif
// ------------------------
// Defines
// ------------------------
#define _MSERIAL(X) MSerial##X
#define MSERIAL(X) _MSERIAL(X)
@@ -68,6 +68,16 @@
#endif
#endif
#ifdef SERIAL_PORT_3
#if SERIAL_PORT_3 == -1
#define MYSERIAL3 MSerial0
#elif WITHIN(SERIAL_PORT_3, 1, 6)
#define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
#else
#error "SERIAL_PORT_3 must be from 1 to 6. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef MMU2_SERIAL_PORT
#if MMU2_SERIAL_PORT == -1
#define MMU2_SERIAL MSerial0
+202
View File
@@ -0,0 +1,202 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
*
*/
#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
#include "../../../inc/MarlinConfig.h"
#if ENABLED(TFT_TOUCH_DEVICE_GT911)
#include "gt911.h"
#include "pinconfig.h"
SW_IIC::SW_IIC(uint16_t sda, uint16_t scl) {
scl_pin = scl;
sda_pin = sda;
}
// Software I2C hardware io init
void SW_IIC::init() {
OUT_WRITE(scl_pin, HIGH);
OUT_WRITE(sda_pin, HIGH);
}
// Software I2C start signal
void SW_IIC::start() {
write_sda(HIGH); // SDA = 1
write_scl(HIGH); // SCL = 1
iic_delay(2);
write_sda(LOW); // SDA = 0
iic_delay(1);
write_scl(LOW); // SCL = 0 // keep SCL low, avoid false stop caused by level jump caused by SDA switching IN/OUT
}
// Software I2C stop signal
void SW_IIC::stop() {
write_scl(LOW); // SCL = 0
iic_delay(2);
write_sda(LOW); // SDA = 0
iic_delay(2);
write_scl(HIGH); // SCL = 1
iic_delay(2);
write_sda(HIGH); // SDA = 1
}
// Software I2C sends ACK or NACK signal
void SW_IIC::send_ack(bool ack) {
write_sda(ack ? LOW : HIGH); // SDA = !ack
iic_delay(2);
write_scl(HIGH); // SCL = 1
iic_delay(2);
write_scl(LOW); // SCL = 0
}
// Software I2C read ACK or NACK signal
bool SW_IIC::read_ack() {
bool error = 0;
set_sda_in();
iic_delay(2);
write_scl(HIGH); // SCL = 1
error = read_sda();
iic_delay(2);
write_scl(LOW); // SCL = 0
set_sda_out();
return error;
}
void SW_IIC::send_byte(uint8_t txd) {
LOOP_L_N(i, 8) {
write_sda(txd & 0x80); // write data bit
txd <<= 1;
iic_delay(1);
write_scl(HIGH); // SCL = 1
iic_delay(2);
write_scl(LOW); // SCL = 0
iic_delay(1);
}
read_ack(); // wait ack
}
uint8_t SW_IIC::read_byte(bool ack) {
uint8_t data = 0;
set_sda_in();
LOOP_L_N(i, 8) {
write_scl(HIGH); // SCL = 1
iic_delay(1);
data <<= 1;
if (read_sda()) data++;
write_scl(LOW); // SCL = 0
iic_delay(2);
}
set_sda_out();
send_ack(ack);
return data;
}
GT911_REG_MAP GT911::reg;
SW_IIC GT911::sw_iic = SW_IIC(GT911_SW_I2C_SDA_PIN, GT911_SW_I2C_SCL_PIN);
void GT911::write_reg(uint16_t reg, uint8_t reg_len, uint8_t* w_data, uint8_t w_len) {
sw_iic.start();
sw_iic.send_byte(gt911_slave_address); // Set IIC Slave address
LOOP_L_N(i, reg_len) { // Set reg address
uint8_t r = (reg >> (8 * (reg_len - 1 - i))) & 0xFF;
sw_iic.send_byte(r);
}
LOOP_L_N(i, w_len) { // Write data to reg
sw_iic.send_byte(w_data[i]);
}
sw_iic.stop();
}
void GT911::read_reg(uint16_t reg, uint8_t reg_len, uint8_t* r_data, uint8_t r_len) {
sw_iic.start();
sw_iic.send_byte(gt911_slave_address); // Set IIC Slave address
LOOP_L_N(i, reg_len) { // Set reg address
uint8_t r = (reg >> (8 * (reg_len - 1 - i))) & 0xFF;
sw_iic.send_byte(r);
}
sw_iic.start();
sw_iic.send_byte(gt911_slave_address + 1); // Set read mode
LOOP_L_N(i, r_len) {
r_data[i] = sw_iic.read_byte(1); // Read data from reg
}
sw_iic.stop();
}
void GT911::Init() {
OUT_WRITE(GT911_RST_PIN, LOW);
OUT_WRITE(GT911_INT_PIN, LOW);
delay(20);
WRITE(GT911_RST_PIN, HIGH);
SET_INPUT(GT911_INT_PIN);
sw_iic.init();
uint8_t clear_reg = 0x0000;
write_reg(0x814E, 2, &clear_reg, 2); // Reset to 0 for start
}
bool GT911::getFirstTouchPoint(int16_t *x, int16_t *y) {
read_reg(0x814E, 2, &reg.REG.status, 1);
if (reg.REG.status & 0x80) {
uint8_t clear_reg = 0x00;
write_reg(0x814E, 2, &clear_reg, 1); // Reset to 0 for start
read_reg(0x8150, 2, reg.map + 2, 8 * (reg.REG.status & 0x0F));
// First touch point
*x = ((reg.REG.point[0].xh & 0x0F) << 8) | reg.REG.point[0].xl;
*y = ((reg.REG.point[0].yh & 0x0F) << 8) | reg.REG.point[0].yl;
return true;
}
return false;
}
bool GT911::getPoint(int16_t *x, int16_t *y) {
static bool touched = 0;
static int16_t read_x = 0, read_y = 0;
static millis_t next_time = 0;
if (ELAPSED(millis(), next_time)) {
touched = getFirstTouchPoint(&read_x, &read_y);
next_time = millis() + 20;
}
*x = read_x;
*y = read_y;
return touched;
}
#endif // TFT_TOUCH_DEVICE_GT911
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
+120
View File
@@ -0,0 +1,120 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../../inc/MarlinConfig.h"
#define GT911_SLAVE_ADDRESS 0xBA
#if !PIN_EXISTS(GT911_RST)
#error "GT911_RST_PIN is not defined."
#elif !PIN_EXISTS(GT911_INT)
#error "GT911_INT_PIN is not defined."
#elif !PIN_EXISTS(GT911_SW_I2C_SCL)
#error "GT911_SW_I2C_SCL_PIN is not defined."
#elif !PIN_EXISTS(GT911_SW_I2C_SDA)
#error "GT911_SW_I2C_SDA_PIN is not defined."
#endif
class SW_IIC {
private:
uint16_t scl_pin;
uint16_t sda_pin;
void write_scl(bool level)
{
WRITE(scl_pin, level);
}
void write_sda(bool level)
{
WRITE(sda_pin, level);
}
bool read_sda()
{
return READ(sda_pin);
}
void set_sda_out()
{
SET_OUTPUT(sda_pin);
}
void set_sda_in()
{
SET_INPUT_PULLUP(sda_pin);
}
static void iic_delay(uint8_t t)
{
delayMicroseconds(t);
}
public:
SW_IIC(uint16_t sda, uint16_t scl);
// setSCL/SDA have to be called before begin()
void setSCL(uint16_t scl)
{
scl_pin = scl;
};
void setSDA(uint16_t sda)
{
sda_pin = sda;
};
void init(); // Initialize the IO port of IIC
void start(); // Send IIC start signal
void stop(); // Send IIC stop signal
void send_byte(uint8_t txd); // IIC sends a byte
uint8_t read_byte(bool ack); // IIC reads a byte
void send_ack(bool ack); // IIC sends ACK or NACK signal
bool read_ack();
};
typedef struct __attribute__((__packed__)) {
uint8_t xl;
uint8_t xh;
uint8_t yl;
uint8_t yh;
uint8_t sizel;
uint8_t sizeh;
uint8_t reserved;
uint8_t track_id;
} GT911_POINT;
typedef union __attribute__((__packed__)) {
uint8_t map[42];
struct {
uint8_t status; // 0x814E
uint8_t track_id; // 0x814F
GT911_POINT point[5]; // [0]:0x8150 - 0x8157 / [1]:0x8158 - 0x815F / [2]:0x8160 - 0x8167 / [3]:0x8168 - 0x816F / [4]:0x8170 - 0x8177
} REG;
} GT911_REG_MAP;
class GT911 {
private:
static const uint8_t gt911_slave_address = GT911_SLAVE_ADDRESS;
static GT911_REG_MAP reg;
static SW_IIC sw_iic;
static void write_reg(uint16_t reg, uint8_t reg_len, uint8_t* w_data, uint8_t w_len);
static void read_reg(uint16_t reg, uint8_t reg_len, uint8_t* r_data, uint8_t r_len);
public:
static void Init();
static bool getFirstTouchPoint(int16_t *x, int16_t *y);
static bool getPoint(int16_t *x, int16_t *y);
};
+1 -1
View File
@@ -312,7 +312,7 @@ void TFT_LTDC::DrawImage(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uin
uint16_t offline = TFT_WIDTH - (ex - sx);
uint32_t addr = (uint32_t)&framebuffer[(TFT_WIDTH * sy) + sx];
CBI(DMA2D->CR, 0)
CBI(DMA2D->CR, 0);
DMA2D->CR = 0 << 16;
DMA2D->FGPFCCR = 0X02;
DMA2D->FGOR = 0;
+1 -1
View File
@@ -23,7 +23,7 @@
#include "../../../inc/MarlinConfig.h"
#if HAS_TFT_XPT2046 || HAS_TOUCH_BUTTONS
#if HAS_TFT_XPT2046 || HAS_RES_TOUCH_BUTTONS
#include "xpt2046.h"
#include "pinconfig.h"
+1 -1
View File
@@ -293,7 +293,7 @@ void HAL_init() {
#if PIN_EXISTS(USB_CONNECT)
OUT_WRITE(USB_CONNECT_PIN, !USB_CONNECT_INVERTING); // USB clear connection
delay(1000); // Give OS time to notice
OUT_WRITE(USB_CONNECT_PIN, USB_CONNECT_INVERTING);
WRITE(USB_CONNECT_PIN, USB_CONNECT_INVERTING);
#endif
TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the minimal serial handler
}
+18 -25
View File
@@ -36,7 +36,6 @@
#include "fastio.h"
#include "watchdog.h"
#include <stdint.h>
#include <util/atomic.h>
@@ -63,11 +62,10 @@
#ifdef SERIAL_USB
typedef ForwardSerial1Class< USBSerial > DefaultSerial1;
extern DefaultSerial1 MSerial0;
#if !HAS_SD_HOST_DRIVE
#define UsbSerial MSerial0
#else
#if HAS_SD_HOST_DRIVE
#define UsbSerial MarlinCompositeSerial
#else
#define UsbSerial MSerial0
#endif
#endif
@@ -86,11 +84,7 @@
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
#define MYSERIAL1 MSERIAL(1) // dummy port
#if NUM_UARTS == 5
#error "SERIAL_PORT must be from 1 to 5. You can also use -1 if the board supports Native USB."
#else
#error "SERIAL_PORT must be from 1 to 3. You can also use -1 if the board supports Native USB."
#endif
static_assert(false, "SERIAL_PORT must be from 1 to " STRINGIFY(NUM_UARTS) ". You can also use -1 if the board supports Native USB.")
#endif
#ifdef SERIAL_PORT_2
@@ -100,11 +94,18 @@
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
#define MYSERIAL2 MSERIAL(1) // dummy port
#if NUM_UARTS == 5
#error "SERIAL_PORT_2 must be from 1 to 5. You can also use -1 if the board supports Native USB."
#else
#error "SERIAL_PORT_2 must be from 1 to 3. You can also use -1 if the board supports Native USB."
#endif
static_assert(false, "SERIAL_PORT_2 must be from 1 to " STRINGIFY(NUM_UARTS) ". You can also use -1 if the board supports Native USB.")
#endif
#endif
#ifdef SERIAL_PORT_3
#if SERIAL_PORT_3 == -1
#define MYSERIAL3 UsbSerial
#elif WITHIN(SERIAL_PORT_3, 1, NUM_UARTS)
#define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
#else
#define MYSERIAL3 MSERIAL(1) // dummy port
static_assert(false, "SERIAL_PORT_3 must be from 1 to " STRINGIFY(NUM_UARTS) ". You can also use -1 if the board supports Native USB.")
#endif
#endif
@@ -115,11 +116,7 @@
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
#else
#define MMU2_SERIAL MSERIAL(1) // dummy port
#if NUM_UARTS == 5
#error "MMU2_SERIAL_PORT must be from 1 to 5. You can also use -1 if the board supports Native USB."
#else
#error "MMU2_SERIAL_PORT must be from 1 to 3. You can also use -1 if the board supports Native USB."
#endif
static_assert(false, "MMU2_SERIAL_PORT must be from 1 to " STRINGIFY(NUM_UARTS) ". You can also use -1 if the board supports Native USB.")
#endif
#endif
@@ -130,11 +127,7 @@
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
#define LCD_SERIAL MSERIAL(1) // dummy port
#if NUM_UARTS == 5
#error "LCD_SERIAL_PORT must be from 1 to 5. You can also use -1 if the board supports Native USB."
#else
#error "LCD_SERIAL_PORT must be from 1 to 3. You can also use -1 if the board supports Native USB."
#endif
static_assert(false, "LCD_SERIAL_PORT must be from 1 to " STRINGIFY(NUM_UARTS) ". You can also use -1 if the board supports Native USB.")
#endif
#if HAS_DGUS_LCD
#define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite()
+1 -1
View File
@@ -22,7 +22,7 @@
#include "../../../inc/MarlinConfig.h"
#if HAS_TFT_XPT2046 || HAS_TOUCH_BUTTONS
#if HAS_TFT_XPT2046 || HAS_RES_TOUCH_BUTTONS
#include "xpt2046.h"
#include <SPI.h>
+2
View File
@@ -68,6 +68,8 @@ extern USBSerialType USBSerial;
#elif WITHIN(SERIAL_PORT, 0, 3)
DECLARE_SERIAL(SERIAL_PORT);
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
#error "The required SERIAL_PORT must be from 0 to 3, or -1 for Native USB."
#endif
#define HAL_SERVO_LIB libServo
+8 -2
View File
@@ -30,11 +30,17 @@
#if ENABLED(I2C_EEPROM)
#include "eeprom_if.h"
#include <Wire.h>
#if ENABLED(SOFT_I2C_EEPROM)
#include <SlowSoftWire.h>
SlowSoftWire Wire = SlowSoftWire(I2C_SDA_PIN, I2C_SCL_PIN, true);
#else
#include <Wire.h>
#endif
void eeprom_init() {
Wire.begin(
#if PINS_EXIST(I2C_SCL, I2C_SDA)
#if PINS_EXIST(I2C_SCL, I2C_SDA) && DISABLED(SOFT_I2C_EEPROM)
uint8_t(I2C_SDA_PIN), uint8_t(I2C_SCL_PIN)
#endif
);
+23 -13
View File
@@ -331,18 +331,14 @@ void disable_all_steppers() {
}
/**
* A Print Job exists when the timer is running or SD printing
* A Print Job exists when the timer is running or SD is printing
*/
bool printJobOngoing() {
return print_job_timer.isRunning() || IS_SD_PRINTING();
}
bool printJobOngoing() { return print_job_timer.isRunning() || IS_SD_PRINTING(); }
/**
* Printing is active when the print job timer is running
* Printing is active when a job is underway but not paused
*/
bool printingIsActive() {
return !did_pause_print && (print_job_timer.isRunning() || IS_SD_PRINTING());
}
bool printingIsActive() { return !did_pause_print && printJobOngoing(); }
/**
* Printing is paused according to SD or host indicators
@@ -367,7 +363,7 @@ void startOrResumeJob() {
inline void abortSDPrinting() {
IF_DISABLED(NO_SD_AUTOSTART, card.autofile_cancel());
card.endFilePrint(TERN_(SD_RESORT, true));
card.abortFilePrintNow(TERN_(SD_RESORT, true));
queue.clear();
quickstop_stepper();
@@ -390,8 +386,8 @@ void startOrResumeJob() {
}
inline void finishSDPrinting() {
if (queue.enqueue_one_P(PSTR("M1001"))) {
marlin_state = MF_RUNNING;
if (queue.enqueue_one_P(PSTR("M1001"))) { // Keep trying until it gets queued
marlin_state = MF_RUNNING; // Signal to stop trying
TERN_(PASSWORD_AFTER_SD_PRINT_END, password.lock_machine());
TERN_(DGUS_LCD_UI_MKS, ScreenHandler.SDPrintingFinished());
}
@@ -487,6 +483,10 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) {
}
#endif
#if HAS_FREEZE_PIN
Stepper::frozen = !READ(FREEZE_PIN);
#endif
#if HAS_HOME
// Handle a standalone HOME button
constexpr millis_t HOME_DEBOUNCE_DELAY = 1000UL;
@@ -748,7 +748,7 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) {
// Handle Power-Loss Recovery
#if ENABLED(POWER_LOSS_RECOVERY) && PIN_EXISTS(POWER_LOSS)
if (printJobOngoing()) recovery.outage();
if (IS_SD_PRINTING()) recovery.outage();
#endif
// Run StallGuard endstop checks
@@ -796,6 +796,7 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) {
if (!gcode.autoreport_paused) {
TERN_(AUTO_REPORT_TEMPERATURES, thermalManager.auto_reporter.tick());
TERN_(AUTO_REPORT_SD_STATUS, card.auto_reporter.tick());
TERN_(AUTO_REPORT_POSITION, position_auto_reporter.tick());
}
#endif
@@ -901,7 +902,7 @@ void stop() {
thermalManager.set_fans_paused(false); // Un-pause fans for safety
#endif
if (IsRunning()) {
if (!IsStopped()) {
SERIAL_ERROR_MSG(STR_ERR_STOPPED);
LCD_MESSAGEPGM(MSG_STOPPED);
safe_delay(350); // allow enough time for messages to get out before stopping
@@ -1075,6 +1076,11 @@ void setup() {
MYSERIAL2.begin(BAUDRATE);
serial_connect_timeout = millis() + 1000UL;
while (!MYSERIAL2.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
#ifdef SERIAL_PORT_3
MYSERIAL3.begin(BAUDRATE);
serial_connect_timeout = millis() + 1000UL;
while (!MYSERIAL3.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
#endif
#endif
SERIAL_ECHOLNPGM("start");
@@ -1088,6 +1094,10 @@ void setup() {
#endif
#endif
#if HAS_FREEZE_PIN
SET_INPUT_PULLUP(FREEZE_PIN);
#endif
#if HAS_SUICIDE
SETUP_LOG("SUICIDE_PIN");
OUT_WRITE(SUICIDE_PIN, !SUICIDE_PIN_INVERTING);
+10 -9
View File
@@ -56,20 +56,21 @@ void minkill(const bool steppers_off=false);
// Global State of the firmware
enum MarlinState : uint8_t {
MF_INITIALIZING = 0,
MF_RUNNING = _BV(0),
MF_PAUSED = _BV(1),
MF_WAITING = _BV(2),
MF_STOPPED = _BV(3),
MF_SD_COMPLETE = _BV(4),
MF_KILLED = _BV(7)
MF_INITIALIZING = 0,
MF_STOPPED,
MF_KILLED,
MF_RUNNING,
MF_SD_COMPLETE,
MF_PAUSED,
MF_WAITING,
};
extern MarlinState marlin_state;
inline bool IsRunning() { return marlin_state == MF_RUNNING; }
inline bool IsStopped() { return marlin_state != MF_RUNNING; }
inline bool IsRunning() { return marlin_state >= MF_RUNNING; }
inline bool IsStopped() { return marlin_state == MF_STOPPED; }
bool printingIsActive();
bool printJobOngoing();
bool printingIsPaused();
void startOrResumeJob();
+16 -14
View File
@@ -370,20 +370,22 @@
#define BOARD_BTT_SKR_V2_0_REV_A 4211 // BigTreeTech SKR v2.0 Rev A (STM32F407VGT6)
#define BOARD_BTT_SKR_V2_0_REV_B 4212 // BigTreeTech SKR v2.0 Rev B (STM32F407VGT6)
#define BOARD_BTT_GTR_V1_0 4213 // BigTreeTech GTR v1.0 (STM32F407IGT)
#define BOARD_LERDGE_K 4214 // Lerdge K (STM32F407ZG)
#define BOARD_LERDGE_S 4215 // Lerdge S (STM32F407VE)
#define BOARD_LERDGE_X 4216 // Lerdge X (STM32F407VE)
#define BOARD_VAKE403D 4217 // VAkE 403D (STM32F446VET6)
#define BOARD_FYSETC_S6 4218 // FYSETC S6 (STM32F446VET6)
#define BOARD_FYSETC_S6_V2_0 4219 // FYSETC S6 v2.0 (STM32F446VET6)
#define BOARD_FYSETC_SPIDER 4220 // FYSETC Spider (STM32F446VET6)
#define BOARD_FLYF407ZG 4221 // FLYF407ZG (STM32F407ZG)
#define BOARD_MKS_ROBIN2 4222 // MKS_ROBIN2 (STM32F407ZE)
#define BOARD_MKS_ROBIN_PRO_V2 4223 // MKS Robin Pro V2 (STM32F407VE)
#define BOARD_MKS_ROBIN_NANO_V3 4224 // MKS Robin Nano V3 (STM32F407VG)
#define BOARD_ANET_ET4 4225 // ANET ET4 V1.x (STM32F407VGT6)
#define BOARD_ANET_ET4P 4226 // ANET ET4P V1.x (STM32F407VGT6)
#define BOARD_FYSETC_CHEETAH_V20 4227 // FYSETC Cheetah V2.0
#define BOARD_BTT_OCTOPUS_V1_0 4214 // BigTreeTech Octopus v1.0 (STM32F446ZET6)
#define BOARD_LERDGE_K 4215 // Lerdge K (STM32F407ZG)
#define BOARD_LERDGE_S 4216 // Lerdge S (STM32F407VE)
#define BOARD_LERDGE_X 4217 // Lerdge X (STM32F407VE)
#define BOARD_VAKE403D 4218 // VAkE 403D (STM32F446VET6)
#define BOARD_FYSETC_S6 4219 // FYSETC S6 (STM32F446VET6)
#define BOARD_FYSETC_S6_V2_0 4220 // FYSETC S6 v2.0 (STM32F446VET6)
#define BOARD_FYSETC_SPIDER 4221 // FYSETC Spider (STM32F446VET6)
#define BOARD_FLYF407ZG 4222 // FLYF407ZG (STM32F407ZG)
#define BOARD_MKS_ROBIN2 4223 // MKS_ROBIN2 (STM32F407ZE)
#define BOARD_MKS_ROBIN_PRO_V2 4224 // MKS Robin Pro V2 (STM32F407VE)
#define BOARD_MKS_ROBIN_NANO_V3 4225 // MKS Robin Nano V3 (STM32F407VG)
#define BOARD_ANET_ET4 4226 // ANET ET4 V1.x (STM32F407VGT6)
#define BOARD_ANET_ET4P 4227 // ANET ET4P V1.x (STM32F407VGT6)
#define BOARD_FYSETC_CHEETAH_V20 4228 // FYSETC Cheetah V2.0
//
// ARM Cortex M7
+53 -22
View File
@@ -237,6 +237,38 @@
memcpy(&a[0],&b[0],_MIN(sizeof(a),sizeof(b))); \
}while(0)
#define CODE_9( A,B,C,D,E,F,G,H,I,...) A; B; C; D; E; F; G; H; I
#define CODE_8( A,B,C,D,E,F,G,H,...) A; B; C; D; E; F; G; H
#define CODE_7( A,B,C,D,E,F,G,...) A; B; C; D; E; F; G
#define CODE_6( A,B,C,D,E,F,...) A; B; C; D; E; F
#define CODE_5( A,B,C,D,E,...) A; B; C; D; E
#define CODE_4( A,B,C,D,...) A; B; C; D
#define CODE_3( A,B,C,...) A; B; C
#define CODE_2( A,B,...) A; B
#define CODE_1( A,...) A
#define _CODE_N(N,V...) CODE_##N(V)
#define CODE_N(N,V...) _CODE_N(N,V)
#define GANG_16(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,...) A B C D E F G H I J K L M N O P
#define GANG_15(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,...) A B C D E F G H I J K L M N O
#define GANG_14(A,B,C,D,E,F,G,H,I,J,K,L,M,N,...) A B C D E F G H I J K L M N
#define GANG_13(A,B,C,D,E,F,G,H,I,J,K,L,M...) A B C D E F G H I J K L M
#define GANG_12(A,B,C,D,E,F,G,H,I,J,K,L...) A B C D E F G H I J K L
#define GANG_11(A,B,C,D,E,F,G,H,I,J,K,...) A B C D E F G H I J K
#define GANG_10(A,B,C,D,E,F,G,H,I,J,...) A B C D E F G H I J
#define GANG_9( A,B,C,D,E,F,G,H,I,...) A B C D E F G H I
#define GANG_8( A,B,C,D,E,F,G,H,...) A B C D E F G H
#define GANG_7( A,B,C,D,E,F,G,...) A B C D E F G
#define GANG_6( A,B,C,D,E,F,...) A B C D E F
#define GANG_5( A,B,C,D,E,...) A B C D E
#define GANG_4( A,B,C,D,...) A B C D
#define GANG_3( A,B,C,...) A B C
#define GANG_2( A,B,...) A B
#define GANG_1( A,...) A
#define _GANG_N(N,V...) GANG_##N(V)
#define GANG_N(N,V...) _GANG_N(N,V)
#define GANG_N_1(N,K) _GANG_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K)
// Macros for initializing arrays
#define LIST_16(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
#define LIST_15(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O
@@ -254,10 +286,13 @@
#define LIST_3( A,B,C,...) A,B,C
#define LIST_2( A,B,...) A,B
#define LIST_1( A,...) A
#define LIST_0(...)
#define _LIST_N(N,V...) LIST_##N(V)
#define LIST_N(N,V...) _LIST_N(N,V)
#define LIST_N_1(N,K) _LIST_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K)
#define ARRAY_N(N,V...) { _LIST_N(N,V) }
#define ARRAY_N_1(N,K) { LIST_N_1(N,K) }
#define _JOIN_1(O) (O)
#define JOIN_N(N,C,V...) (DO(JOIN,C,LIST_N(N,V)))
@@ -301,8 +336,12 @@
#define HYPOT(x,y) SQRT(HYPOT2(x,y))
// Use NUM_ARGS(__VA_ARGS__) to get the number of variadic arguments
#define _NUM_ARGS(_,Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A,OUT,...) OUT
#define NUM_ARGS(V...) _NUM_ARGS(0,V,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
#define _NUM_ARGS(_,n,m,l,k,j,i,h,g,f,e,d,c,b,a,Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A,OUT,...) OUT
#define NUM_ARGS(V...) _NUM_ARGS(0,V,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
// Use TWO_ARGS(__VA_ARGS__) to get whether there are 1, 2, or >2 arguments
#define _TWO_ARGS(_,n,m,l,k,j,i,h,g,f,e,d,c,b,a,Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A,OUT,...) OUT
#define TWO_ARGS(V...) _TWO_ARGS(0,V,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,1,0)
#ifdef __cplusplus
@@ -414,31 +453,19 @@
#else
#define MIN_2(a,b) ((a)<(b)?(a):(b))
#define MIN_3(a,V...) MIN_2(a,MIN_2(V))
#define MIN_4(a,V...) MIN_2(a,MIN_3(V))
#define MIN_5(a,V...) MIN_2(a,MIN_4(V))
#define MIN_6(a,V...) MIN_2(a,MIN_5(V))
#define MIN_7(a,V...) MIN_2(a,MIN_6(V))
#define MIN_8(a,V...) MIN_2(a,MIN_7(V))
#define MIN_9(a,V...) MIN_2(a,MIN_8(V))
#define MIN_10(a,V...) MIN_2(a,MIN_9(V))
#define __MIN_N(N,V...) MIN_##N(V)
#define _MIN_N(N,V...) __MIN_N(N,V)
#define _MIN(V...) _MIN_N(NUM_ARGS(V), V)
#define _MIN_N_REF() _MIN_N
#define _MIN(V...) EVAL(_MIN_N(TWO_ARGS(V),V))
#define MIN_2(a,b) ((a)<(b)?(a):(b))
#define MIN_3(a,V...) MIN_2(a,DEFER2(_MIN_N_REF)()(TWO_ARGS(V),V))
#define MAX_2(a,b) ((a)>(b)?(a):(b))
#define MAX_3(a,V...) MAX_2(a,MAX_2(V))
#define MAX_4(a,V...) MAX_2(a,MAX_3(V))
#define MAX_5(a,V...) MAX_2(a,MAX_4(V))
#define MAX_6(a,V...) MAX_2(a,MAX_5(V))
#define MAX_7(a,V...) MAX_2(a,MAX_6(V))
#define MAX_8(a,V...) MAX_2(a,MAX_7(V))
#define MAX_9(a,V...) MAX_2(a,MAX_8(V))
#define MAX_10(a,V...) MAX_2(a,MAX_9(V))
#define __MAX_N(N,V...) MAX_##N(V)
#define _MAX_N(N,V...) __MAX_N(N,V)
#define _MAX(V...) _MAX_N(NUM_ARGS(V), V)
#define _MAX_N_REF() _MAX_N
#define _MAX(V...) EVAL(_MAX_N(TWO_ARGS(V),V))
#define MAX_2(a,b) ((a)>(b)?(a):(b))
#define MAX_3(a,V...) MAX_2(a,DEFER2(_MAX_N_REF)()(TWO_ARGS(V),V))
#endif
@@ -473,6 +500,9 @@
#define ADD8(N) ADD4(ADD4(N))
#define ADD9(N) ADD4(ADD5(N))
#define ADD10(N) ADD5(ADD5(N))
#define SUM(A,B) _CAT(ADD,A)(B)
#define DOUBLE_(n) ADD##n(n)
#define DOUBLE(n) DOUBLE_(n)
// Macros for subtracting
#define DEC_0 0
@@ -581,6 +611,7 @@
// Repeat a macro passing S...N-1.
#define REPEAT_S(S,N,OP) EVAL(_REPEAT(S,SUB##S(N),OP))
#define REPEAT(N,OP) REPEAT_S(0,N,OP)
#define REPEAT_1(N,OP) REPEAT_S(1,INCREMENT(N),OP)
// Repeat a macro passing 0...N-1 plus additional arguments.
#define REPEAT2_S(S,N,OP,V...) EVAL(_REPEAT2(S,SUB##S(N),OP,V))
+11 -1
View File
@@ -44,6 +44,9 @@ PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMST
#if ENABLED(MEATPACK_ON_SERIAL_PORT_2)
SerialLeafT2 mpSerial2(false, _SERIAL_LEAF_2);
#endif
#if ENABLED(MEATPACK_ON_SERIAL_PORT_3)
SerialLeafT3 mpSerial3(false, _SERIAL_LEAF_3);
#endif
// Step 2: For multiserial, handle the second serial port as well
#if HAS_MULTI_SERIAL
@@ -52,7 +55,14 @@ PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMST
SerialLeafT2 msSerial2(ethernet.have_telnet_client, MYSERIAL2, false);
#endif
SerialOutputT multiSerial(SERIAL_LEAF_1, SERIAL_LEAF_2);
#define __S_LEAF(N) ,SERIAL_LEAF_##N
#define _S_LEAF(N) __S_LEAF(N)
SerialOutputT multiSerial( SERIAL_LEAF_1 REPEAT_S(2, INCREMENT(NUM_SERIAL), _S_LEAF) );
#undef __S_LEAF
#undef _S_LEAF
#endif
void serialprintPGM(PGM_P str) {
+60 -139
View File
@@ -87,18 +87,17 @@ extern uint8_t marlin_debug_flags;
// If we have a catchall, use that directly
#ifdef SERIAL_CATCHALL
#define _SERIAL_LEAF_2 SERIAL_CATCHALL
#elif HAS_ETHERNET
typedef ConditionalSerial<decltype(MYSERIAL2)> SerialLeafT2; // We need to create an instance here
extern SerialLeafT2 msSerial2;
#define _SERIAL_LEAF_2 msSerial2
#else
#if HAS_ETHERNET
// We need to create an instance here
typedef ConditionalSerial<decltype(MYSERIAL2)> SerialLeafT2;
extern SerialLeafT2 msSerial2;
#define _SERIAL_LEAF_2 msSerial2
#else
// Don't create a useless instance here, directly use the existing instance
#define _SERIAL_LEAF_2 MYSERIAL2
#endif
#define _SERIAL_LEAF_2 MYSERIAL2 // Don't create a useless instance here, directly use the existing instance
#endif
// Nothing complicated here
#define _SERIAL_LEAF_3 MYSERIAL3
// Hook Meatpack if it's enabled on the second leaf
#if ENABLED(MEATPACK_ON_SERIAL_PORT_2)
typedef MeatpackSerial<decltype(_SERIAL_LEAF_2)> SerialLeafT2;
@@ -108,7 +107,23 @@ extern uint8_t marlin_debug_flags;
#define SERIAL_LEAF_2 _SERIAL_LEAF_2
#endif
typedef MultiSerial<decltype(SERIAL_LEAF_1), decltype(SERIAL_LEAF_2), 0> SerialOutputT;
// Hook Meatpack if it's enabled on the third leaf
#if ENABLED(MEATPACK_ON_SERIAL_PORT_3)
typedef MeatpackSerial<decltype(_SERIAL_LEAF_3)> SerialLeafT3;
extern SerialLeafT3 mpSerial3;
#define SERIAL_LEAF_3 mpSerial3
#else
#define SERIAL_LEAF_3 _SERIAL_LEAF_3
#endif
#define __S_MULTI(N) decltype(SERIAL_LEAF_##N),
#define _S_MULTI(N) __S_MULTI(N)
typedef MultiSerial< REPEAT_1(NUM_SERIAL, _S_MULTI) 0> SerialOutputT;
#undef __S_MULTI
#undef _S_MULTI
extern SerialOutputT multiSerial;
#define SERIAL_IMPL multiSerial
#else
@@ -167,139 +182,45 @@ inline void SERIAL_FLUSHTX() { SERIAL_IMPL.flushTX(); }
// Print a single PROGMEM string to serial
void serialprintPGM(PGM_P str);
// SERIAL_ECHOPAIR / SERIAL_ECHOPAIR_P is used to output a key value pair. The key must be a string and the value can be anything
// Print up to 12 pairs of values. Odd elements auto-wrapped in PSTR().
#define __SEP_N(N,V...) _SEP_##N(V)
#define _SEP_N(N,V...) __SEP_N(N,V)
#define _SEP_1(PRE) SERIAL_ECHOPGM(PRE)
#define _SEP_2(PRE,V) serial_echopair_PGM(PSTR(PRE),V)
#define _SEP_3(a,b,c) do{ _SEP_2(a,b); SERIAL_ECHOPGM(c); }while(0)
#define _SEP_4(a,b,V...) do{ _SEP_2(a,b); _SEP_2(V); }while(0)
#define _SEP_5(a,b,V...) do{ _SEP_2(a,b); _SEP_3(V); }while(0)
#define _SEP_6(a,b,V...) do{ _SEP_2(a,b); _SEP_4(V); }while(0)
#define _SEP_7(a,b,V...) do{ _SEP_2(a,b); _SEP_5(V); }while(0)
#define _SEP_8(a,b,V...) do{ _SEP_2(a,b); _SEP_6(V); }while(0)
#define _SEP_9(a,b,V...) do{ _SEP_2(a,b); _SEP_7(V); }while(0)
#define _SEP_10(a,b,V...) do{ _SEP_2(a,b); _SEP_8(V); }while(0)
#define _SEP_11(a,b,V...) do{ _SEP_2(a,b); _SEP_9(V); }while(0)
#define _SEP_12(a,b,V...) do{ _SEP_2(a,b); _SEP_10(V); }while(0)
#define _SEP_13(a,b,V...) do{ _SEP_2(a,b); _SEP_11(V); }while(0)
#define _SEP_14(a,b,V...) do{ _SEP_2(a,b); _SEP_12(V); }while(0)
#define _SEP_15(a,b,V...) do{ _SEP_2(a,b); _SEP_13(V); }while(0)
#define _SEP_16(a,b,V...) do{ _SEP_2(a,b); _SEP_14(V); }while(0)
#define _SEP_17(a,b,V...) do{ _SEP_2(a,b); _SEP_15(V); }while(0)
#define _SEP_18(a,b,V...) do{ _SEP_2(a,b); _SEP_16(V); }while(0)
#define _SEP_19(a,b,V...) do{ _SEP_2(a,b); _SEP_17(V); }while(0)
#define _SEP_20(a,b,V...) do{ _SEP_2(a,b); _SEP_18(V); }while(0)
#define _SEP_21(a,b,V...) do{ _SEP_2(a,b); _SEP_19(V); }while(0)
#define _SEP_22(a,b,V...) do{ _SEP_2(a,b); _SEP_20(V); }while(0)
#define _SEP_23(a,b,V...) do{ _SEP_2(a,b); _SEP_21(V); }while(0)
#define _SEP_24(a,b,V...) do{ _SEP_2(a,b); _SEP_22(V); }while(0)
//
// SERIAL_ECHOPAIR... macros are used to output string-value pairs.
//
#define SERIAL_ECHOPAIR(V...) _SEP_N(NUM_ARGS(V),V)
// Print up to 20 pairs of values. Odd elements must be literal strings.
#define __SEP_N(N,V...) _SEP_##N(V)
#define _SEP_N(N,V...) __SEP_N(N,V)
#define _SEP_N_REF() _SEP_N
#define _SEP_1(s) SERIAL_ECHOPGM(s);
#define _SEP_2(s,v) serial_echopair_PGM(PSTR(s),v);
#define _SEP_3(s,v,V...) _SEP_2(s,v); DEFER2(_SEP_N_REF)()(TWO_ARGS(V),V);
#define SERIAL_ECHOPAIR(V...) do{ EVAL(_SEP_N(TWO_ARGS(V),V)); }while(0)
// Print up to 12 pairs of values. Odd elements must be PSTR pointers.
#define __SEP_N_P(N,V...) _SEP_##N##_P(V)
#define _SEP_N_P(N,V...) __SEP_N_P(N,V)
#define _SEP_1_P(PRE) serialprintPGM(PRE)
#define _SEP_2_P(PRE,V) serial_echopair_PGM(PRE,V)
#define _SEP_3_P(a,b,c) do{ _SEP_2_P(a,b); serialprintPGM(c); }while(0)
#define _SEP_4_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_2_P(V); }while(0)
#define _SEP_5_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_3_P(V); }while(0)
#define _SEP_6_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_4_P(V); }while(0)
#define _SEP_7_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_5_P(V); }while(0)
#define _SEP_8_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_6_P(V); }while(0)
#define _SEP_9_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_7_P(V); }while(0)
#define _SEP_10_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_8_P(V); }while(0)
#define _SEP_11_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_9_P(V); }while(0)
#define _SEP_12_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_10_P(V); }while(0)
#define _SEP_13_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_11_P(V); }while(0)
#define _SEP_14_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_12_P(V); }while(0)
#define _SEP_15_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_13_P(V); }while(0)
#define _SEP_16_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_14_P(V); }while(0)
#define _SEP_17_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_15_P(V); }while(0)
#define _SEP_18_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_16_P(V); }while(0)
#define _SEP_19_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_17_P(V); }while(0)
#define _SEP_20_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_18_P(V); }while(0)
#define _SEP_21_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_19_P(V); }while(0)
#define _SEP_22_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_20_P(V); }while(0)
#define _SEP_23_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_21_P(V); }while(0)
#define _SEP_24_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_22_P(V); }while(0)
// Print up to 20 pairs of values followed by newline. Odd elements must be literal strings.
#define __SELP_N(N,V...) _SELP_##N(V)
#define _SELP_N(N,V...) __SELP_N(N,V)
#define _SELP_N_REF() _SELP_N
#define _SELP_1(s) SERIAL_ECHOLNPGM(s);
#define _SELP_2(s,v) serial_echopair_PGM(PSTR(s),v); SERIAL_EOL();
#define _SELP_3(s,v,V...) _SEP_2(s,v); DEFER2(_SELP_N_REF)()(TWO_ARGS(V),V);
#define SERIAL_ECHOLNPAIR(V...) do{ EVAL(_SELP_N(TWO_ARGS(V),V)); }while(0)
// SERIAL_ECHOPAIR_P is used to output a key value pair. Unlike SERIAL_ECHOPAIR, the key must be a PGM string already and the value can be anything
#define SERIAL_ECHOPAIR_P(V...) _SEP_N_P(NUM_ARGS(V),V)
// Print up to 20 pairs of values. Odd elements must be PSTR pointers.
#define __SEP_N_P(N,V...) _SEP_##N##_P(V)
#define _SEP_N_P(N,V...) __SEP_N_P(N,V)
#define _SEP_N_P_REF() _SEP_N_P
#define _SEP_1_P(s) serialprintPGM(s);
#define _SEP_2_P(s,v) serial_echopair_PGM(s,v);
#define _SEP_3_P(s,v,V...) _SEP_2_P(s,v); DEFER2(_SEP_N_P_REF)()(TWO_ARGS(V),V);
#define SERIAL_ECHOPAIR_P(V...) do{ EVAL(_SEP_N_P(TWO_ARGS(V),V)); }while(0)
// Print up to 12 pairs of values followed by newline
#define __SELP_N(N,V...) _SELP_##N(V)
#define _SELP_N(N,V...) __SELP_N(N,V)
#define _SELP_1(PRE) SERIAL_ECHOLNPGM(PRE)
#define _SELP_2(PRE,V) do{ serial_echopair_PGM(PSTR(PRE),V); SERIAL_EOL(); }while(0)
#define _SELP_3(a,b,c) do{ _SEP_2(a,b); SERIAL_ECHOLNPGM(c); }while(0)
#define _SELP_4(a,b,V...) do{ _SEP_2(a,b); _SELP_2(V); }while(0)
#define _SELP_5(a,b,V...) do{ _SEP_2(a,b); _SELP_3(V); }while(0)
#define _SELP_6(a,b,V...) do{ _SEP_2(a,b); _SELP_4(V); }while(0)
#define _SELP_7(a,b,V...) do{ _SEP_2(a,b); _SELP_5(V); }while(0)
#define _SELP_8(a,b,V...) do{ _SEP_2(a,b); _SELP_6(V); }while(0)
#define _SELP_9(a,b,V...) do{ _SEP_2(a,b); _SELP_7(V); }while(0)
#define _SELP_10(a,b,V...) do{ _SEP_2(a,b); _SELP_8(V); }while(0)
#define _SELP_11(a,b,V...) do{ _SEP_2(a,b); _SELP_9(V); }while(0)
#define _SELP_12(a,b,V...) do{ _SEP_2(a,b); _SELP_10(V); }while(0)
#define _SELP_13(a,b,V...) do{ _SEP_2(a,b); _SELP_11(V); }while(0)
#define _SELP_14(a,b,V...) do{ _SEP_2(a,b); _SELP_12(V); }while(0)
#define _SELP_15(a,b,V...) do{ _SEP_2(a,b); _SELP_13(V); }while(0)
#define _SELP_16(a,b,V...) do{ _SEP_2(a,b); _SELP_14(V); }while(0)
#define _SELP_17(a,b,V...) do{ _SEP_2(a,b); _SELP_15(V); }while(0)
#define _SELP_18(a,b,V...) do{ _SEP_2(a,b); _SELP_16(V); }while(0)
#define _SELP_19(a,b,V...) do{ _SEP_2(a,b); _SELP_17(V); }while(0)
#define _SELP_20(a,b,V...) do{ _SEP_2(a,b); _SELP_18(V); }while(0)
#define _SELP_21(a,b,V...) do{ _SEP_2(a,b); _SELP_19(V); }while(0)
#define _SELP_22(a,b,V...) do{ _SEP_2(a,b); _SELP_20(V); }while(0)
#define _SELP_23(a,b,V...) do{ _SEP_2(a,b); _SELP_21(V); }while(0)
#define _SELP_24(a,b,V...) do{ _SEP_2(a,b); _SELP_22(V); }while(0)
#define _SELP_25(a,b,V...) do{ _SEP_2(a,b); _SELP_23(V); }while(0)
#define _SELP_26(a,b,V...) do{ _SEP_2(a,b); _SELP_24(V); }while(0)
#define _SELP_27(a,b,V...) do{ _SEP_2(a,b); _SELP_25(V); }while(0)
#define _SELP_28(a,b,V...) do{ _SEP_2(a,b); _SELP_26(V); }while(0)
#define _SELP_29(a,b,V...) do{ _SEP_2(a,b); _SELP_27(V); }while(0)
#define _SELP_30(a,b,V...) do{ _SEP_2(a,b); _SELP_28(V); }while(0) // Eat two args, pass the rest up
#define SERIAL_ECHOLNPAIR(V...) _SELP_N(NUM_ARGS(V),V)
// Print up to 12 pairs of values followed by newline
#define __SELP_N_P(N,V...) _SELP_##N##_P(V)
#define _SELP_N_P(N,V...) __SELP_N_P(N,V)
#define _SELP_1_P(PRE) serialprintPGM(PRE)
#define _SELP_2_P(PRE,V) do{ serial_echopair_PGM(PRE,V); SERIAL_EOL(); }while(0)
#define _SELP_3_P(a,b,c) do{ _SEP_2_P(a,b); serialprintPGM(c); }while(0)
#define _SELP_4_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_2_P(V); }while(0)
#define _SELP_5_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_3_P(V); }while(0)
#define _SELP_6_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_4_P(V); }while(0)
#define _SELP_7_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_5_P(V); }while(0)
#define _SELP_8_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_6_P(V); }while(0)
#define _SELP_9_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_7_P(V); }while(0)
#define _SELP_10_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_8_P(V); }while(0)
#define _SELP_11_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_9_P(V); }while(0)
#define _SELP_12_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_10_P(V); }while(0)
#define _SELP_13_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_11_P(V); }while(0)
#define _SELP_14_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_12_P(V); }while(0)
#define _SELP_15_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_13_P(V); }while(0)
#define _SELP_16_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_14_P(V); }while(0)
#define _SELP_17_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_15_P(V); }while(0)
#define _SELP_18_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_16_P(V); }while(0)
#define _SELP_19_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_17_P(V); }while(0)
#define _SELP_20_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_18_P(V); }while(0)
#define _SELP_21_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_19_P(V); }while(0)
#define _SELP_22_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_20_P(V); }while(0)
#define _SELP_23_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_21_P(V); }while(0)
#define _SELP_24_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_22_P(V); }while(0)
#define _SELP_25_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_23_P(V); }while(0)
#define _SELP_26_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_24_P(V); }while(0)
#define _SELP_27_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_25_P(V); }while(0)
#define _SELP_28_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_26_P(V); }while(0)
#define _SELP_29_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_27_P(V); }while(0)
#define _SELP_30_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_28_P(V); }while(0) // Eat two args, pass the rest up
#define SERIAL_ECHOLNPAIR_P(V...) _SELP_N_P(NUM_ARGS(V),V)
// Print up to 20 pairs of values followed by newline. Odd elements must be PSTR pointers.
#define __SELP_N_P(N,V...) _SELP_##N##_P(V)
#define _SELP_N_P(N,V...) __SELP_N_P(N,V)
#define _SELP_N_P_REF() _SELP_N_P
#define _SELP_1_P(s) { serialprintPGM(s); SERIAL_EOL(); }
#define _SELP_2_P(s,v) { serial_echopair_PGM(s,v); SERIAL_EOL(); }
#define _SELP_3_P(s,v,V...) { _SEP_2_P(s,v); DEFER2(_SELP_N_P_REF)()(TWO_ARGS(V),V); }
#define SERIAL_ECHOLNPAIR_P(V...) do{ EVAL(_SELP_N_P(TWO_ARGS(V),V)); }while(0)
#ifdef AllowDifferentTypeInList
+67 -42
View File
@@ -195,54 +195,71 @@ struct RuntimeSerial : public SerialBase< RuntimeSerial<SerialT> >, public Seria
RuntimeSerial(const bool e, Args... args) : BaseClassT(e), SerialT(args...), writeHook(0), eofHook(0), userPointer(0) {}
};
// A class that duplicates its output conditionally to 2 serial interfaces
template <class Serial0T, class Serial1T, const uint8_t offset = 0, const uint8_t step = 1>
struct MultiSerial : public SerialBase< MultiSerial<Serial0T, Serial1T, offset, step> > {
typedef SerialBase< MultiSerial<Serial0T, Serial1T, offset, step> > BaseClassT;
#define _S_CLASS(N) class Serial##N##T,
#define _S_NAME(N) Serial##N##T,
template < REPEAT(NUM_SERIAL, _S_CLASS) const uint8_t offset=0, const uint8_t step=1 >
struct MultiSerial : public SerialBase< MultiSerial< REPEAT(NUM_SERIAL, _S_NAME) offset, step > > {
typedef SerialBase< MultiSerial< REPEAT(NUM_SERIAL, _S_NAME) offset, step > > BaseClassT;
#undef _S_CLASS
#undef _S_NAME
SerialMask portMask;
Serial0T & serial0;
Serial1T & serial1;
static constexpr uint8_t Usage = ((1 << step) - 1); // A bit mask containing as many bits as step
static constexpr uint8_t FirstOutput = (Usage << offset);
static constexpr uint8_t SecondOutput = (Usage << (offset + step));
static constexpr uint8_t Both = FirstOutput | SecondOutput;
#define _S_DECLARE(N) Serial##N##T & serial##N;
REPEAT(NUM_SERIAL, _S_DECLARE);
#undef _S_DECLARE
static constexpr uint8_t Usage = _BV(step) - 1; // A bit mask containing 'step' bits
#define _OUT_PORT(N) (Usage << (offset + (step * N))),
static constexpr uint8_t output[] = { REPEAT(NUM_SERIAL, _OUT_PORT) };
#undef _OUT_PORT
#define _OUT_MASK(N) | output[N]
static constexpr uint8_t ALL = 0 REPEAT(NUM_SERIAL, _OUT_MASK);
#undef _OUT_MASK
NO_INLINE void write(uint8_t c) {
if (portMask.enabled(FirstOutput)) serial0.write(c);
if (portMask.enabled(SecondOutput)) serial1.write(c);
#define _S_WRITE(N) if (portMask.enabled(output[N])) serial##N.write(c);
REPEAT(NUM_SERIAL, _S_WRITE);
#undef _S_WRITE
}
NO_INLINE void msgDone() {
if (portMask.enabled(FirstOutput)) serial0.msgDone();
if (portMask.enabled(SecondOutput)) serial1.msgDone();
#define _S_DONE(N) if (portMask.enabled(output[N])) serial##N.msgDone();
REPEAT(NUM_SERIAL, _S_DONE);
#undef _S_DONE
}
int available(serial_index_t index) {
if (index.within(0 + offset, step + offset - 1))
return serial0.available(index);
else if (index.within(step + offset, 2 * step + offset - 1))
return serial1.available(index);
uint8_t pos = offset;
#define _S_AVAILABLE(N) if (index.within(pos, pos + step - 1)) return serial##N.available(index); else pos += step;
REPEAT(NUM_SERIAL, _S_AVAILABLE);
#undef _S_AVAILABLE
return false;
}
int read(serial_index_t index) {
if (index.within(0 + offset, step + offset - 1))
return serial0.read(index);
else if (index.within(step + offset, 2 * step + offset - 1))
return serial1.read(index);
uint8_t pos = offset;
#define _S_READ(N) if (index.within(pos, pos + step - 1)) return serial##N.read(index); else pos += step;
REPEAT(NUM_SERIAL, _S_READ);
#undef _S_READ
return -1;
}
void begin(const long br) {
if (portMask.enabled(FirstOutput)) serial0.begin(br);
if (portMask.enabled(SecondOutput)) serial1.begin(br);
#define _S_BEGIN(N) if (portMask.enabled(output[N])) serial##N.begin(br);
REPEAT(NUM_SERIAL, _S_BEGIN);
#undef _S_BEGIN
}
void end() {
if (portMask.enabled(FirstOutput)) serial0.end();
if (portMask.enabled(SecondOutput)) serial1.end();
#define _S_END(N) if (portMask.enabled(output[N])) serial##N.end();
REPEAT(NUM_SERIAL, _S_END);
#undef _S_END
}
bool connected() {
bool ret = true;
if (portMask.enabled(FirstOutput)) ret = CALL_IF_EXISTS(bool, &serial0, connected);
if (portMask.enabled(SecondOutput)) ret = ret && CALL_IF_EXISTS(bool, &serial1, connected);
#define _S_CONNECTED(N) if (portMask.enabled(output[N]) && !CALL_IF_EXISTS(bool, &serial##N, connected)) ret = false;
REPEAT(NUM_SERIAL, _S_CONNECTED);
#undef _S_CONNECTED
return ret;
}
@@ -250,27 +267,32 @@ struct MultiSerial : public SerialBase< MultiSerial<Serial0T, Serial1T, offset,
using BaseClassT::read;
// Redirect flush
NO_INLINE void flush() {
if (portMask.enabled(FirstOutput)) serial0.flush();
if (portMask.enabled(SecondOutput)) serial1.flush();
NO_INLINE void flush() {
#define _S_FLUSH(N) if (portMask.enabled(output[N])) serial##N.flush();
REPEAT(NUM_SERIAL, _S_FLUSH);
#undef _S_FLUSH
}
NO_INLINE void flushTX() {
if (portMask.enabled(FirstOutput)) CALL_IF_EXISTS(void, &serial0, flushTX);
if (portMask.enabled(SecondOutput)) CALL_IF_EXISTS(void, &serial1, flushTX);
NO_INLINE void flushTX() {
#define _S_FLUSHTX(N) if (portMask.enabled(output[N])) CALL_IF_EXISTS(void, &serial0, flushTX);
REPEAT(NUM_SERIAL, _S_FLUSHTX);
#undef _S_FLUSHTX
}
// Forward feature queries
SerialFeature features(serial_index_t index) const {
if (index.within(0 + offset, step + offset - 1))
return serial0.features(index);
else if (index.within(step + offset, 2 * step + offset - 1))
return serial1.features(index);
SerialFeature features(serial_index_t index) const {
uint8_t pos = offset;
#define _S_FEATURES(N) if (index.within(pos, pos + step - 1)) return serial##N.features(index); else pos += step;
REPEAT(NUM_SERIAL, _S_FEATURES);
#undef _S_FEATURES
return SerialFeature::None;
}
MultiSerial(Serial0T & serial0, Serial1T & serial1, const SerialMask mask = Both, const bool e = false) :
BaseClassT(e),
portMask(mask), serial0(serial0), serial1(serial1) {}
#define _S_REFS(N) Serial##N##T & serial##N,
#define _S_INIT(N) ,serial##N (serial##N)
MultiSerial(REPEAT(NUM_SERIAL, _S_REFS) const SerialMask mask = ALL, const bool e = false)
: BaseClassT(e), portMask(mask) REPEAT(NUM_SERIAL, _S_INIT) {}
};
// Build the actual serial object depending on current configuration
@@ -278,4 +300,7 @@ struct MultiSerial : public SerialBase< MultiSerial<Serial0T, Serial1T, offset,
#define ForwardSerial1Class TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, ForwardSerial)
#ifdef HAS_MULTI_SERIAL
#define Serial2Class ConditionalSerial
#if NUM_SERIAL >= 3
#define Serial3Class ConditionalSerial
#endif
#endif
+1 -1
View File
@@ -32,7 +32,7 @@
#define UBL_OK false
#define UBL_ERR true
enum MeshPointType : char { INVALID, REAL, SET_IN_BITMAP };
enum MeshPointType : char { INVALID, REAL, SET_IN_BITMAP, CLOSEST };
// External references
+22 -22
View File
@@ -306,7 +306,7 @@ void unified_bed_leveling::G29() {
if (G29_parse_parameters()) return; // Abort on parameter error
const int8_t p_val = parser.intval('P', -1);
const bool may_move = p_val == 1 || p_val == 2 || p_val == 4 || parser.seen('J');
const bool may_move = p_val == 1 || p_val == 2 || p_val == 4 || parser.seen_test('J');
#if ENABLED(HAS_MULTI_HOTEND)
const uint8_t old_tool_index = active_extruder;
#endif
@@ -315,7 +315,7 @@ void unified_bed_leveling::G29() {
if (may_move) {
planner.synchronize();
// Send 'N' to force homing before G29 (internal only)
if (axes_should_home() || parser.seen('N')) gcode.home_all_axes();
if (axes_should_home() || parser.seen_test('N')) gcode.home_all_axes();
TERN_(HAS_MULTI_HOTEND, if (active_extruder) tool_change(0));
}
@@ -380,7 +380,7 @@ void unified_bed_leveling::G29() {
// Allow the user to specify the height because 10mm is a little extreme in some cases.
for (uint8_t x = (GRID_MAX_POINTS_X) / 3; x < 2 * (GRID_MAX_POINTS_X) / 3; x++) // Create a rectangular raised area in
for (uint8_t y = (GRID_MAX_POINTS_Y) / 3; y < 2 * (GRID_MAX_POINTS_Y) / 3; y++) { // the center of the bed
z_values[x][y] += parser.seen('C') ? param.C_constant : 9.99f;
z_values[x][y] += parser.seen_test('C') ? param.C_constant : 9.99f;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
}
break;
@@ -389,7 +389,7 @@ void unified_bed_leveling::G29() {
#if HAS_BED_PROBE
if (parser.seen('J')) {
if (parser.seen_test('J')) {
save_ubl_active_state_and_disable();
tilt_mesh_based_on_probed_grid(param.J_grid_size == 0); // Zero size does 3-Point
restore_ubl_active_state_and_leave();
@@ -402,7 +402,7 @@ void unified_bed_leveling::G29() {
#endif // HAS_BED_PROBE
if (parser.seen('P')) {
if (parser.seen_test('P')) {
if (WITHIN(param.P_phase, 0, 1) && storage_slot == -1) {
storage_slot = 0;
SERIAL_ECHOLNPGM("Default storage slot 0 selected.");
@@ -423,7 +423,7 @@ void unified_bed_leveling::G29() {
//
// Invalidate Entire Mesh and Automatically Probe Mesh in areas that can be reached by the probe
//
if (!parser.seen('C')) {
if (!parser.seen_test('C')) {
invalidate();
SERIAL_ECHOLNPGM("Mesh invalidated. Probing mesh.");
}
@@ -433,7 +433,7 @@ void unified_bed_leveling::G29() {
SERIAL_DECIMAL(param.XY_pos.y);
SERIAL_ECHOLNPGM(").\n");
}
probe_entire_mesh(param.XY_pos, parser.seen('T'), parser.seen('E'), parser.seen('U'));
probe_entire_mesh(param.XY_pos, parser.seen_test('T'), parser.seen_test('E'), parser.seen_test('U'));
report_current_position();
probe_deployed = true;
@@ -449,7 +449,7 @@ void unified_bed_leveling::G29() {
SERIAL_ECHOLNPGM("Manually probing unreachable points.");
do_z_clearance(Z_CLEARANCE_BETWEEN_PROBES);
if (parser.seen('C') && !param.XY_seen) {
if (parser.seen_test('C') && !param.XY_seen) {
/**
* Use a good default location for the path.
@@ -483,7 +483,7 @@ void unified_bed_leveling::G29() {
}
const float height = parser.floatval('H', Z_CLEARANCE_BETWEEN_PROBES);
manually_probe_remaining_mesh(param.XY_pos, height, param.B_shim_thickness, parser.seen('T'));
manually_probe_remaining_mesh(param.XY_pos, height, param.B_shim_thickness, parser.seen_test('T'));
SERIAL_ECHOLNPGM("G29 P2 finished.");
@@ -555,7 +555,7 @@ void unified_bed_leveling::G29() {
case 4: // Fine Tune (i.e., Edit) the Mesh
#if HAS_LCD_MENU
fine_tune_mesh(param.XY_pos, parser.seen('T'));
fine_tune_mesh(param.XY_pos, parser.seen_test('T'));
#else
SERIAL_ECHOLNPGM("?P4 is only available when an LCD is present.");
return;
@@ -574,14 +574,14 @@ void unified_bed_leveling::G29() {
// Much of the 'What?' command can be eliminated. But until we are fully debugged, it is
// good to have the extra information. Soon... we prune this to just a few items
//
if (parser.seen('W')) g29_what_command();
if (parser.seen_test('W')) g29_what_command();
//
// When we are fully debugged, this may go away. But there are some valid
// use cases for the users. So we can wait and see what to do with it.
//
if (parser.seen('K')) // Kompare Current Mesh Data to Specified Stored Mesh
if (parser.seen_test('K')) // Kompare Current Mesh Data to Specified Stored Mesh
g29_compare_current_mesh_to_stored_mesh();
#endif // UBL_DEVEL_DEBUGGING
@@ -640,7 +640,7 @@ void unified_bed_leveling::G29() {
SERIAL_ECHOLNPGM("Done.");
}
if (parser.seen('T'))
if (parser.seen_test('T'))
display_map(param.T_map_type);
LEAVE:
@@ -915,7 +915,7 @@ void set_message_with_feedback(PGM_P const msg_P) {
if (do_ubl_mesh_map) display_map(param.T_map_type); // Show user where we're probing
if (parser.seen('B')) {
if (parser.seen_test('B')) {
SERIAL_ECHOPGM_P(GET_TEXT(MSG_UBL_BC_INSERT));
LCD_MESSAGEPGM(MSG_UBL_BC_INSERT);
}
@@ -954,7 +954,7 @@ void set_message_with_feedback(PGM_P const msg_P) {
* NOTE: Blocks the G-code queue and captures Marlin UI during use.
*/
void unified_bed_leveling::fine_tune_mesh(const xy_pos_t &pos, const bool do_ubl_mesh_map) {
if (!parser.seen('R')) // fine_tune_mesh() is special. If no repetition count flag is specified
if (!parser.seen_test('R')) // fine_tune_mesh() is special. If no repetition count flag is specified
param.R_repetition = 1; // do exactly one mesh location. Otherwise use what the parser decided.
#if ENABLED(UBL_MESH_EDIT_MOVES_Z)
@@ -1091,7 +1091,7 @@ bool unified_bed_leveling::G29_parse_parameters() {
}
}
param.V_verbosity = parser.seen('V') ? parser.value_int() : 0;
param.V_verbosity = parser.intval('V');
if (!WITHIN(param.V_verbosity, 0, 4)) {
SERIAL_ECHOLNPGM("?(V)erbose level implausible (0-4).\n");
err_flag = true;
@@ -1153,15 +1153,15 @@ bool unified_bed_leveling::G29_parse_parameters() {
* Leveling is being enabled here with old data, possibly
* none. Error handling should disable for safety...
*/
if (parser.seen('A')) {
if (parser.seen('D')) {
if (parser.seen_test('A')) {
if (parser.seen_test('D')) {
SERIAL_ECHOLNPGM("?Can't activate and deactivate at the same time.\n");
return UBL_ERR;
}
set_bed_leveling_enabled(true);
report_state();
}
else if (parser.seen('D')) {
else if (parser.seen_test('D')) {
set_bed_leveling_enabled(false);
report_state();
}
@@ -1282,7 +1282,7 @@ mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() {
static bool test_func(uint8_t i, uint8_t j, void *data) {
find_closest_t *d = (find_closest_t*)data;
if ( (d->type == (isnan(ubl.z_values[i][j]) ? INVALID : REAL))
if ( d->type == CLOSEST || d->type == (isnan(ubl.z_values[i][j]) ? INVALID : REAL)
|| (d->type == SET_IN_BITMAP && !d->done_flags->marked(i, j))
) {
// Found a Mesh Point of the specified type!
@@ -1326,7 +1326,7 @@ mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const Mesh
float best_so_far = 99999.99f;
GRID_LOOP(i, j) {
if ( (type == (isnan(z_values[i][j]) ? INVALID : REAL))
if ( type == CLOSEST || type == (isnan(z_values[i][j]) ? INVALID : REAL)
|| (type == SET_IN_BITMAP && !done_flags->marked(i, j))
) {
// Found a Mesh Point of the specified type!
@@ -1520,7 +1520,7 @@ void unified_bed_leveling::smart_fill_mesh() {
SERIAL_ECHOLNPAIR("Tilting mesh point ", point_num, "/", total_points, "\n");
TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " %i/%i"), GET_TEXT(MSG_LCD_TILTING_MESH), point_num, total_points));
measured_z = probe.probe_at_point(rpos, parser.seen('E') ? PROBE_PT_STOW : PROBE_PT_RAISE, param.V_verbosity); // TODO: Needs error handling
measured_z = probe.probe_at_point(rpos, parser.seen_test('E') ? PROBE_PT_STOW : PROBE_PT_RAISE, param.V_verbosity); // TODO: Needs error handling
abort_flag = isnan(measured_z);
+1 -1
View File
@@ -66,7 +66,7 @@ uint8_t MCP4728::analogWrite(const uint8_t channel, const uint16_t value) {
}
/**
* Write all input resistor values to EEPROM using SequencialWrite method.
* Write all input resistor values to EEPROM using SequentialWrite method.
* This will update both input register and EEPROM value
* This will also write current Vref, PowerDown, Gain settings to EEPROM
*/
+7 -7
View File
@@ -819,11 +819,11 @@ int8_t I2CPositionEncodersMgr::parse() {
void I2CPositionEncodersMgr::M860() {
if (parse()) return;
const bool hasU = parser.seen('U'), hasO = parser.seen('O');
const bool hasU = parser.seen_test('U'), hasO = parser.seen_test('O');
if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
if (!I2CPE_anyaxis || parser.seen_test(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) report_position(idx, hasU, hasO);
}
@@ -956,10 +956,10 @@ void I2CPositionEncodersMgr::M864() {
return;
}
else {
if (parser.seen('X')) newAddress = I2CPE_PRESET_ADDR_X;
else if (parser.seen('Y')) newAddress = I2CPE_PRESET_ADDR_Y;
else if (parser.seen('Z')) newAddress = I2CPE_PRESET_ADDR_Z;
else if (parser.seen('E')) newAddress = I2CPE_PRESET_ADDR_E;
if (parser.seen_test('X')) newAddress = I2CPE_PRESET_ADDR_X;
else if (parser.seen_test('Y')) newAddress = I2CPE_PRESET_ADDR_Y;
else if (parser.seen_test('Z')) newAddress = I2CPE_PRESET_ADDR_Z;
else if (parser.seen_test('E')) newAddress = I2CPE_PRESET_ADDR_E;
else return;
}
@@ -1012,7 +1012,7 @@ void I2CPositionEncodersMgr::M865() {
void I2CPositionEncodersMgr::M866() {
if (parse()) return;
const bool hasR = parser.seen('R');
const bool hasR = parser.seen_test('R');
if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) {
+7 -7
View File
@@ -212,10 +212,10 @@ void FWRetract::retract(const bool retracting
*/
void FWRetract::M207() {
if (!parser.seen("FSWZ")) return M207_report();
if (parser.seen('S')) settings.retract_length = parser.value_axis_units(E_AXIS);
if (parser.seen('F')) settings.retract_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
if (parser.seen('Z')) settings.retract_zraise = parser.value_linear_units();
if (parser.seen('W')) settings.swap_retract_length = parser.value_axis_units(E_AXIS);
if (parser.seenval('S')) settings.retract_length = parser.value_axis_units(E_AXIS);
if (parser.seenval('F')) settings.retract_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
if (parser.seenval('Z')) settings.retract_zraise = parser.value_linear_units();
if (parser.seenval('W')) settings.swap_retract_length = parser.value_axis_units(E_AXIS);
}
void FWRetract::M207_report(const bool forReplay/*=false*/) {
@@ -238,10 +238,10 @@ void FWRetract::M207_report(const bool forReplay/*=false*/) {
*/
void FWRetract::M208() {
if (!parser.seen("FSRW")) return M208_report();
if (parser.seen('S')) settings.retract_recover_extra = parser.value_axis_units(E_AXIS);
if (parser.seen('F')) settings.retract_recover_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
if (parser.seen('S')) settings.retract_recover_extra = parser.value_axis_units(E_AXIS);
if (parser.seen('F')) settings.retract_recover_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
if (parser.seen('R')) settings.swap_retract_recover_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
if (parser.seen('W')) settings.swap_retract_recover_extra = parser.value_axis_units(E_AXIS);
if (parser.seen('W')) settings.swap_retract_recover_extra = parser.value_axis_units(E_AXIS);
}
void FWRetract::M208_report(const bool forReplay/*=false*/) {
+1 -6
View File
@@ -164,12 +164,7 @@ Joystick joystick;
xyz_float_t move_dist{0};
float hypot2 = 0;
LOOP_XYZ(i) if (norm_jog[i]) {
move_dist[i] = seg_time * norm_jog[i] *
#if ENABLED(EXTENSIBLE_UI)
manual_feedrate_mm_s[i];
#else
planner.settings.max_feedrate_mm_s[i];
#endif
move_dist[i] = seg_time * norm_jog[i] * TERN(EXTENSIBLE_UI, manual_feedrate_mm_s, planner.settings.max_feedrate_mm_s)[i];
hypot2 += sq(move_dist[i]);
}
+1 -1
View File
@@ -159,7 +159,7 @@ void MMU2::mmu_loop() {
MMU2_COMMAND("S1"); // Read Version
state = -2;
}
else if (millis() > 3000000) {
else if (millis() > 30000) { // 30sec after reset disable MMU
SERIAL_ECHOLNPGM("MMU not responding - DISABLED");
state = 0;
}
+14 -5
View File
@@ -406,6 +406,15 @@ bool pause_print(const_float_t retract, const xyz_pos_t &park_point, const bool
// Save current position
resume_position = current_position;
// Will the nozzle be parking?
const bool do_park = !axes_should_home();
#if ENABLED(POWER_LOSS_RECOVERY)
// Save PLR info in case the power goes out while parked
const float park_raise = do_park ? nozzle.park_mode_0_height(park_point.z) - current_position.z : POWER_LOSS_ZRAISE;
if (was_sd_printing && recovery.enabled) recovery.save(true, park_raise, do_park);
#endif
// Wait for buffered blocks to complete
planner.synchronize();
@@ -419,9 +428,8 @@ bool pause_print(const_float_t retract, const xyz_pos_t &park_point, const bool
unscaled_e_move(retract, PAUSE_PARK_RETRACT_FEEDRATE);
}
// Park the nozzle by doing a Minimum Z Raise followed by an XY Move
if (!axes_should_home())
nozzle.park(0, park_point);
// If axes don't need to home then the nozzle can park
if (do_park) nozzle.park(0, park_point); // Park the nozzle by doing a Minimum Z Raise followed by an XY Move
#if ENABLED(DUAL_X_CARRIAGE)
const int8_t saved_ext = active_extruder;
@@ -429,7 +437,8 @@ bool pause_print(const_float_t retract, const xyz_pos_t &park_point, const bool
set_duplication_enabled(false, DXC_ext);
#endif
if (unload_length) // Unload the filament
// Unload the filament, if specified
if (unload_length)
unload_filament(unload_length, show_lcd, PAUSE_MODE_CHANGE_FILAMENT);
#if ENABLED(DUAL_X_CARRIAGE)
@@ -649,7 +658,7 @@ void resume_print(const_float_t slow_load_length/*=0*/, const_float_t fast_load_
#if ENABLED(SDSUPPORT)
if (did_pause_print) {
--did_pause_print;
card.startFileprint();
card.startOrResumeFilePrinting();
// Write PLR now to update the z axis value
TERN_(POWER_LOSS_RECOVERY, if (recovery.enabled) recovery.save(true));
}
+132 -70
View File
@@ -66,9 +66,6 @@ PrintJobRecovery recovery;
#ifndef POWER_LOSS_PURGE_LEN
#define POWER_LOSS_PURGE_LEN 0
#endif
#ifndef POWER_LOSS_ZRAISE
#define POWER_LOSS_ZRAISE 2 // Move on loss with backup power, or on resume without it
#endif
#if DISABLED(BACKUP_POWER_SUPPLY)
#undef POWER_LOSS_RETRACT_LEN // No retract at outage without backup power
@@ -140,14 +137,14 @@ void PrintJobRecovery::load() {
* Set info fields that won't change
*/
void PrintJobRecovery::prepare() {
card.getAbsFilename(info.sd_filename); // SD filename
card.getAbsFilenameInCWD(info.sd_filename); // SD filename
cmd_sdpos = 0;
}
/**
* Save the current machine state to the power-loss recovery file
*/
void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=0*/) {
void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POWER_LOSS_ZRAISE*/, const bool raised/*=false*/) {
// We don't check IS_SD_PRINTING here so a save may occur during a pause
@@ -184,14 +181,12 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=0*/
info.current_position = current_position;
info.feedrate = uint16_t(MMS_TO_MMM(feedrate_mm_s));
info.zraise = zraise;
info.flag.raised = raised; // Was Z raised before power-off?
TERN_(GCODE_REPEAT_MARKERS, info.stored_repeat = repeat);
TERN_(HAS_HOME_OFFSET, info.home_offset = home_offset);
TERN_(HAS_POSITION_SHIFT, info.position_shift = position_shift);
#if HAS_MULTI_EXTRUDER
info.active_extruder = active_extruder;
#endif
TERN_(HAS_MULTI_EXTRUDER, info.active_extruder = active_extruder);
#if DISABLED(NO_VOLUMETRICS)
info.flag.volumetric_enabled = parser.volumetric_enabled;
@@ -256,7 +251,7 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=0*/
// Raise the Z axis now
if (zraise) {
char cmd[20], str_1[16];
sprintf_P(cmd, PSTR("G0 Z%s"), dtostrf(zraise, 1, 3, str_1));
sprintf_P(cmd, PSTR("G0Z%s"), dtostrf(zraise, 1, 3, str_1));
gcode.process_subcommands_now(cmd);
}
#else
@@ -292,8 +287,9 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=0*/
constexpr float zraise = 0;
#endif
// Save, including the limited Z raise
if (IS_SD_PRINTING()) save(true, zraise);
// Save the current position, distance that Z was (or should be) raised,
// and a flag whether the raise was already done here.
if (IS_SD_PRINTING()) save(true, zraise, ENABLED(BACKUP_POWER_SUPPLY));
// Disable all heaters to reduce power loss
thermalManager.disable_all_heaters();
@@ -348,57 +344,78 @@ void PrintJobRecovery::resume() {
const celsius_t bt = info.target_temperature_bed;
if (bt) {
// Restore the bed temperature
sprintf_P(cmd, PSTR("M190 S%i"), bt);
sprintf_P(cmd, PSTR("M190S%i"), bt);
gcode.process_subcommands_now(cmd);
}
#endif
// Restore all hotend temperatures
// Heat hotend enough to soften material
#if HAS_HOTEND
HOTEND_LOOP() {
const celsius_t et = info.target_temperature[e];
const celsius_t et = _MAX(info.target_temperature[e], 180);
if (et) {
#if HAS_MULTI_HOTEND
sprintf_P(cmd, PSTR("T%i S"), e);
sprintf_P(cmd, PSTR("T%iS"), e);
gcode.process_subcommands_now(cmd);
#endif
sprintf_P(cmd, PSTR("M109 S%i"), et);
sprintf_P(cmd, PSTR("M109S%i"), et);
gcode.process_subcommands_now(cmd);
}
}
#endif
// Interpret the saved Z according to flags
const float z_print = info.current_position.z,
z_raised = z_print + info.zraise;
//
// Home the axes that can safely be homed, and
// establish the current position as best we can
// establish the current position as best we can.
//
gcode.process_subcommands_now_P(PSTR("G92.9E0")); // Reset E to 0
#if Z_HOME_DIR > 0
// If Z homing goes to max...
gcode.process_subcommands_now_P(PSTR(
"G92.9 E0\n" // Reset E to 0
"G28R0" // Home all axes (no raise)
));
float z_now = z_raised;
#else // "G92.9 E0 ..."
// If a Z raise occurred at outage restore Z, otherwise raise Z now
sprintf_P(cmd, PSTR("G92.9 E0 " TERN(BACKUP_POWER_SUPPLY, "Z%s", "Z0\nG1Z%s")), dtostrf(info.zraise, 1, 3, str_1));
// If Z homing goes to max then just move back to the "raised" position
sprintf_P(cmd, PSTR(
"G28R0\n" // Home all axes (no raise)
"G1Z%sF1200" // Move Z down to (raised) height
), dtostrf(z_now, 1, 3, str_1));
gcode.process_subcommands_now(cmd);
// Home safely with no Z raise
gcode.process_subcommands_now_P(PSTR(
"G28R0" // No raise during G28
#if IS_CARTESIAN && (DISABLED(POWER_LOSS_RECOVER_ZHOME) || defined(POWER_LOSS_ZHOME_POS))
"XY" // Don't home Z on Cartesian unless overridden
#endif
));
#else
#if ENABLED(POWER_LOSS_RECOVER_ZHOME) && defined(POWER_LOSS_ZHOME_POS)
#define HOMING_Z_DOWN 1
#else
#define HOME_XY_ONLY 1
#endif
float z_now = info.flag.raised ? z_raised : z_print;
// Reset E to 0 and set Z to the real position
#if HOME_XY_ONLY
sprintf_P(cmd, PSTR("G92.9Z%s"), dtostrf(z_now, 1, 3, str_1));
gcode.process_subcommands_now(cmd);
#endif
// Does Z need to be raised now? It should be raised before homing XY.
if (z_raised > z_now) {
z_now = z_raised;
sprintf_P(cmd, PSTR("G1Z%sF600"), dtostrf(z_now, 1, 3, str_1));
gcode.process_subcommands_now(cmd);
}
// Home XY with no Z raise, and also home Z here if Z isn't homing down below.
gcode.process_subcommands_now_P(PSTR("G28R0" TERN_(HOME_XY_ONLY, "XY"))); // No raise during G28
#endif
#if ENABLED(POWER_LOSS_RECOVER_ZHOME) && defined(POWER_LOSS_ZHOME_POS)
// Move to a safe XY position where Z can home while avoiding the print.
// If Z_SAFE_HOMING is enabled, its position must also be outside the print area!
#if HOMING_Z_DOWN
// Move to a safe XY position and home Z while avoiding the print.
constexpr xy_pos_t p = POWER_LOSS_ZHOME_POS;
sprintf_P(cmd, PSTR("G1X%sY%sF1000\nG28Z"), dtostrf(p.x, 1, 3, str_1), dtostrf(p.y, 1, 3, str_2));
gcode.process_subcommands_now(cmd);
@@ -407,9 +424,24 @@ void PrintJobRecovery::resume() {
// Mark all axes as having been homed (no effect on current_position)
set_all_homed();
#if HAS_LEVELING
// Restore Z fade and possibly re-enable bed leveling compensation.
// Leveling may already be enabled due to the ENABLE_LEVELING_AFTER_G28 option.
// TODO: Add a G28 parameter to leave leveling disabled.
sprintf_P(cmd, PSTR("M420S%cZ%s"), '0' + (char)info.flag.leveling, dtostrf(info.fade, 1, 1, str_1));
gcode.process_subcommands_now(cmd);
#if HOME_XY_ONLY
// The physical Z was adjusted at power-off so undo the M420S1 correction to Z with G92.9.
sprintf_P(cmd, PSTR("G92.9Z%s"), dtostrf(z_now, 1, 1, str_1));
gcode.process_subcommands_now(cmd);
#endif
#endif
#if ENABLED(POWER_LOSS_RECOVER_ZHOME)
// Z was homed. Now move Z back up to the saved Z height, plus the POWER_LOSS_ZRAISE.
sprintf_P(cmd, PSTR("G1Z%sF500"), dtostrf(info.current_position.z + POWER_LOSS_ZRAISE, 1, 3, str_1));
// Z was homed down to the bed, so move up to the raised height.
z_now = z_raised;
sprintf_P(cmd, PSTR("G1Z%sF600"), dtostrf(z_now, 1, 3, str_1));
gcode.process_subcommands_now(cmd);
#endif
@@ -432,8 +464,23 @@ void PrintJobRecovery::resume() {
#endif
#endif
// Select the previously active tool (with no_move)
#if HAS_MULTI_EXTRUDER
// Restore all hotend temperatures
#if HAS_HOTEND
HOTEND_LOOP() {
const celsius_t et = info.target_temperature[e];
if (et) {
#if HAS_MULTI_HOTEND
sprintf_P(cmd, PSTR("T%iS"), e);
gcode.process_subcommands_now(cmd);
#endif
sprintf_P(cmd, PSTR("M109S%i"), et);
gcode.process_subcommands_now(cmd);
}
}
#endif
// Restore the previously active tool (with no_move)
#if HAS_MULTI_EXTRUDER || HAS_MULTI_HOTEND
sprintf_P(cmd, PSTR("T%i S"), info.active_extruder);
gcode.process_subcommands_now(cmd);
#endif
@@ -460,22 +507,13 @@ void PrintJobRecovery::resume() {
fwretract.current_hop = info.retract_hop;
#endif
#if HAS_LEVELING
// Restore leveling state before 'G92 Z' to ensure
// the Z stepper count corresponds to the native Z.
if (info.fade || info.flag.leveling) {
sprintf_P(cmd, PSTR("M420S%cZ%s"), '0' + (char)info.flag.leveling, dtostrf(info.fade, 1, 1, str_1));
gcode.process_subcommands_now(cmd);
}
#endif
#if ENABLED(GRADIENT_MIX)
memcpy(&mixer.gradient, &info.gradient, sizeof(info.gradient));
#endif
// Un-retract if there was a retract at outage
#if ENABLED(BACKUP_POWER_SUPPLY) && POWER_LOSS_RETRACT_LEN > 0
gcode.process_subcommands_now_P(PSTR("G1 E" STRINGIFY(POWER_LOSS_RETRACT_LEN) " F3000"));
gcode.process_subcommands_now_P(PSTR("G1E" STRINGIFY(POWER_LOSS_RETRACT_LEN) "F3000"));
#endif
// Additional purge on resume if configured
@@ -488,29 +526,23 @@ void PrintJobRecovery::resume() {
gcode.process_subcommands_now_P(PSTR("G12"));
#endif
// Move back to the saved XY
sprintf_P(cmd, PSTR("G1 X%s Y%s F3000"),
// Move back over to the saved XY
sprintf_P(cmd, PSTR("G1X%sY%sF3000"),
dtostrf(info.current_position.x, 1, 3, str_1),
dtostrf(info.current_position.y, 1, 3, str_2)
);
gcode.process_subcommands_now(cmd);
// Move back to the saved Z
dtostrf(info.current_position.z, 1, 3, str_1);
#if Z_HOME_DIR > 0 || ENABLED(POWER_LOSS_RECOVER_ZHOME)
sprintf_P(cmd, PSTR("G1 Z%s F500"), str_1);
#else
gcode.process_subcommands_now_P(PSTR("G1 Z0 F200"));
sprintf_P(cmd, PSTR("G92.9 Z%s"), str_1);
#endif
// Move back down to the saved Z for printing
sprintf_P(cmd, PSTR("G1Z%sF600"), dtostrf(z_print, 1, 3, str_1));
gcode.process_subcommands_now(cmd);
// Restore the feedrate
sprintf_P(cmd, PSTR("G1 F%d"), info.feedrate);
sprintf_P(cmd, PSTR("G1F%d"), info.feedrate);
gcode.process_subcommands_now(cmd);
// Restore E position with G92.9
sprintf_P(cmd, PSTR("G92.9 E%s"), dtostrf(info.current_position.e, 1, 3, str_1));
sprintf_P(cmd, PSTR("G92.9E%s"), dtostrf(info.current_position.e, 1, 3, str_1));
gcode.process_subcommands_now(cmd);
TERN_(GCODE_REPEAT_MARKERS, repeat = info.stored_repeat);
@@ -535,7 +567,7 @@ void PrintJobRecovery::resume() {
char *fn = info.sd_filename;
sprintf_P(cmd, M23_STR, fn);
gcode.process_subcommands_now(cmd);
sprintf_P(cmd, PSTR("M24 S%ld T%ld"), resume_sdpos, info.print_job_elapsed);
sprintf_P(cmd, PSTR("M24S%ldT%ld"), resume_sdpos, info.print_job_elapsed);
gcode.process_subcommands_now(cmd);
TERN_(DEBUG_POWER_LOSS_RECOVERY, marlin_debug_flags = old_flags);
@@ -555,7 +587,15 @@ void PrintJobRecovery::resume() {
}
DEBUG_EOL();
DEBUG_ECHOLNPAIR("zraise: ", info.zraise);
DEBUG_ECHOLNPAIR("feedrate: ", info.feedrate);
DEBUG_ECHOLNPAIR("zraise: ", info.zraise, " ", info.flag.raised ? "(before)" : "");
#if ENABLED(GCODE_REPEAT_MARKERS)
DEBUG_ECHOLNPAIR("repeat index: ", info.stored_repeat.index);
LOOP_L_N(i, info.stored_repeat.index)
DEBUG_ECHOLNPAIR("..... sdpos: ", info.stored_repeat.marker.sdpos, " count: ", info.stored_repeat.marker.counter);
#endif
#if HAS_HOME_OFFSET
DEBUG_ECHOPGM("home_offset: ");
@@ -575,12 +615,16 @@ void PrintJobRecovery::resume() {
DEBUG_EOL();
#endif
DEBUG_ECHOLNPAIR("feedrate: ", info.feedrate);
#if HAS_MULTI_EXTRUDER
DEBUG_ECHOLNPAIR("active_extruder: ", info.active_extruder);
#endif
#if DISABLED(NO_VOLUMETRICS)
DEBUG_ECHOPGM("filament_size:");
LOOP_L_N(i, EXTRUDERS) DEBUG_ECHOLNPAIR(" ", info.filament_size[i]);
DEBUG_EOL();
#endif
#if HAS_HOTEND
DEBUG_ECHOPGM("target_temperature: ");
HOTEND_LOOP() {
@@ -604,8 +648,9 @@ void PrintJobRecovery::resume() {
#endif
#if HAS_LEVELING
DEBUG_ECHOLNPAIR("leveling: ", info.flag.leveling, " fade: ", info.fade);
DEBUG_ECHOLNPAIR("leveling: ", info.flag.leveling ? "ON" : "OFF", " fade: ", info.fade);
#endif
#if ENABLED(FWRETRACT)
DEBUG_ECHOPGM("retract: ");
for (int8_t e = 0; e < EXTRUDERS; e++) {
@@ -615,11 +660,28 @@ void PrintJobRecovery::resume() {
DEBUG_EOL();
DEBUG_ECHOLNPAIR("retract_hop: ", info.retract_hop);
#endif
// Mixing extruder and gradient
#if BOTH(MIXING_EXTRUDER, GRADIENT_MIX)
DEBUG_ECHOLNPAIR("gradient: ", info.gradient.enabled ? "ON" : "OFF");
#endif
DEBUG_ECHOLNPAIR("sd_filename: ", info.sd_filename);
DEBUG_ECHOLNPAIR("sdpos: ", info.sdpos);
DEBUG_ECHOLNPAIR("print_job_elapsed: ", info.print_job_elapsed);
DEBUG_ECHOLNPAIR("dryrun: ", AS_DIGIT(info.flag.dryrun));
DEBUG_ECHOLNPAIR("allow_cold_extrusion: ", info.flag.allow_cold_extrusion);
DEBUG_ECHOPGM("axis_relative:");
if (TEST(info.axis_relative, REL_X)) DEBUG_ECHOPGM(" REL_X");
if (TEST(info.axis_relative, REL_Y)) DEBUG_ECHOPGM(" REL_Y");
if (TEST(info.axis_relative, REL_Z)) DEBUG_ECHOPGM(" REL_Z");
if (TEST(info.axis_relative, REL_E)) DEBUG_ECHOPGM(" REL_E");
if (TEST(info.axis_relative, E_MODE_ABS)) DEBUG_ECHOPGM(" E_MODE_ABS");
if (TEST(info.axis_relative, E_MODE_REL)) DEBUG_ECHOPGM(" E_MODE_REL");
DEBUG_EOL();
DEBUG_ECHOLNPAIR("flag.dryrun: ", AS_DIGIT(info.flag.dryrun));
DEBUG_ECHOLNPAIR("flag.allow_cold_extrusion: ", AS_DIGIT(info.flag.allow_cold_extrusion));
DEBUG_ECHOLNPAIR("flag.volumetric_enabled: ", AS_DIGIT(info.flag.volumetric_enabled));
}
else
DEBUG_ECHOLNPGM("INVALID DATA");
+15 -3
View File
@@ -42,6 +42,10 @@
#define POWER_LOSS_STATE HIGH
#endif
#ifndef POWER_LOSS_ZRAISE
#define POWER_LOSS_ZRAISE 2
#endif
//#define DEBUG_POWER_LOSS_RECOVERY
//#define SAVE_EACH_CMD_MODE
//#define SAVE_INFO_INTERVAL_MS 0
@@ -52,6 +56,7 @@ typedef struct {
// Machine state
xyze_pos_t current_position;
uint16_t feedrate;
float zraise;
// Repeat information
@@ -112,6 +117,7 @@ typedef struct {
// Misc. Marlin flags
struct {
bool raised:1; // Raised before saved
bool dryrun:1; // M111 S8
bool allow_cold_extrusion:1; // M302 P1
#if ENABLED(HAS_LEVELING)
@@ -177,12 +183,18 @@ class PrintJobRecovery {
static inline void cancel() { purge(); IF_DISABLED(NO_SD_AUTOSTART, card.autofile_begin()); }
static void load();
static void save(const bool force=ENABLED(SAVE_EACH_CMD_MODE), const float zraise=0);
static void save(const bool force=ENABLED(SAVE_EACH_CMD_MODE), const float zraise=POWER_LOSS_ZRAISE, const bool raised=false);
#if PIN_EXISTS(POWER_LOSS)
static inline void outage() {
if (enabled && READ(POWER_LOSS_PIN) == POWER_LOSS_STATE)
_outage();
static constexpr uint8_t OUTAGE_THRESHOLD = 3;
static uint8_t outage_counter = 0;
if (enabled && READ(POWER_LOSS_PIN) == POWER_LOSS_STATE) {
outage_counter++;
if (outage_counter >= OUTAGE_THRESHOLD) _outage();
}
else
outage_counter = 0;
}
#endif
+1 -1
View File
@@ -207,7 +207,7 @@ class FilamentSensorBase {
// Return a bitmask of runout pin states
static inline uint8_t poll_runout_pins() {
#define _OR_RUNOUT(N) | (READ(FIL_RUNOUT##N##_PIN) ? _BV((N) - 1) : 0)
return (0 REPEAT_S(1, INCREMENT(NUM_RUNOUT_SENSORS), _OR_RUNOUT));
return (0 REPEAT_1(NUM_RUNOUT_SENSORS, _OR_RUNOUT));
#undef _OR_RUNOUT
}
+4 -4
View File
@@ -648,12 +648,12 @@ void GcodeSuite::G26() {
#if HAS_LCD_MENU
g26_repeats = parser.intval('R', GRID_MAX_POINTS + 1);
#else
if (!parser.seen('R')) {
if (parser.seen('R'))
g26_repeats = parser.has_value() ? parser.value_int() : GRID_MAX_POINTS + 1;
else {
SERIAL_ECHOLNPGM("?(R)epeat must be specified when not using an LCD.");
return;
}
else
g26_repeats = parser.has_value() ? parser.value_int() : GRID_MAX_POINTS + 1;
#endif
if (g26_repeats < 1) {
SERIAL_ECHOLNPGM("?(R)epeat value not plausible; must be at least 1.");
@@ -671,7 +671,7 @@ void GcodeSuite::G26() {
/**
* Wait until all parameters are verified before altering the state!
*/
set_bed_leveling_enabled(!parser.seen('D'));
set_bed_leveling_enabled(!parser.seen_test('D'));
do_z_clearance(Z_CLEARANCE_BETWEEN_PROBES);
+1 -1
View File
@@ -133,7 +133,7 @@ void GcodeSuite::M420() {
#endif // AUTO_BED_LEVELING_UBL
const bool seenV = parser.seen('V');
const bool seenV = parser.seen_test('V');
#if HAS_MESH
+6 -6
View File
@@ -223,7 +223,7 @@ G29_TYPE GcodeSuite::G29() {
reset_stepper_timeout();
const bool seenQ = EITHER(DEBUG_LEVELING_FEATURE, PROBE_MANUALLY) && parser.seen('Q');
const bool seenQ = EITHER(DEBUG_LEVELING_FEATURE, PROBE_MANUALLY) && parser.seen_test('Q');
// G29 Q is also available if debugging
#if ENABLED(DEBUG_LEVELING_FEATURE)
@@ -235,7 +235,7 @@ G29_TYPE GcodeSuite::G29() {
if (DISABLED(PROBE_MANUALLY) && seenQ) G29_RETURN(false);
#endif
const bool seenA = TERN0(PROBE_MANUALLY, parser.seen('A')),
const bool seenA = TERN0(PROBE_MANUALLY, parser.seen_test('A')),
no_action = seenA || seenQ,
faux = ENABLED(DEBUG_LEVELING_FEATURE) && DISABLED(PROBE_MANUALLY) ? parser.boolval('C') : no_action;
@@ -245,7 +245,7 @@ G29_TYPE GcodeSuite::G29() {
}
// Send 'N' to force homing before G29 (internal only)
if (parser.seen('N'))
if (parser.seen_test('N'))
process_subcommands_now_P(TERN(G28_L0_ENSURES_LEVELING_OFF, PSTR("G28L0"), G28_STR));
// Don't allow auto-leveling without homing first
@@ -275,7 +275,7 @@ G29_TYPE GcodeSuite::G29() {
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
const bool seen_w = parser.seen('W');
const bool seen_w = parser.seen_test('W');
if (seen_w) {
if (!leveling_is_valid()) {
SERIAL_ERROR_MSG("No bilinear grid");
@@ -308,7 +308,7 @@ G29_TYPE GcodeSuite::G29() {
if (abl.reenable) report_current_position();
}
G29_RETURN(false);
} // parser.seen('W')
} // parser.seen_test('W')
#else
@@ -317,7 +317,7 @@ G29_TYPE GcodeSuite::G29() {
#endif
// Jettison bed leveling data
if (!seen_w && parser.seen('J')) {
if (!seen_w && parser.seen_test('J')) {
reset_bed_level();
G29_RETURN(false);
}
+1 -1
View File
@@ -87,7 +87,7 @@ void GcodeSuite::G29() {
mbl.reset();
mbl_probe_index = 0;
if (!ui.wait_for_move) {
queue.inject_P(parser.seen('N') ? PSTR("G28" TERN(G28_L0_ENSURES_LEVELING_OFF, "L0", "") "\nG29S2") : PSTR("G29S2"));
queue.inject_P(parser.seen_test('N') ? PSTR("G28" TERN(G28_L0_ENSURES_LEVELING_OFF, "L0", "") "\nG29S2") : PSTR("G29S2"));
return;
}
state = MeshNext;
+15 -12
View File
@@ -21,7 +21,7 @@
*/
/**
* unified.cpp - Unified Bed Leveling
* M421.cpp - Unified Bed Leveling
*/
#include "../../../inc/MarlinConfig.h"
@@ -39,31 +39,34 @@
* M421: Set a single Mesh Bed Leveling Z coordinate
*
* Usage:
* M421 I<xindex> J<yindex> Z<linear>
* M421 I<xindex> J<yindex> Q<offset>
* M421 I<xindex> J<yindex> N
* M421 C Z<linear>
* M421 C Q<offset>
* M421 I<xindex> J<yindex> Z<linear> : Set the Mesh Point IJ to the Z value
* M421 I<xindex> J<yindex> Q<offset> : Add the Q value to the Mesh Point IJ
* M421 I<xindex> J<yindex> N : Set the Mesh Point IJ to NAN (not set)
* M421 C Z<linear> : Set the closest Mesh Point to the Z value
* M421 C Q<offset> : Add the Q value to the closest Mesh Point
*/
void GcodeSuite::M421() {
xy_int8_t ij = { int8_t(parser.intval('I', -1)), int8_t(parser.intval('J', -1)) };
const bool hasI = ij.x >= 0,
hasJ = ij.y >= 0,
hasC = parser.seen('C'),
hasN = parser.seen('N'),
hasC = parser.seen_test('C'),
hasN = parser.seen_test('N'),
hasZ = parser.seen('Z'),
hasQ = !hasZ && parser.seen('Q');
if (hasC) ij = ubl.find_closest_mesh_point_of_type(REAL, current_position);
if (hasC) ij = ubl.find_closest_mesh_point_of_type(CLOSEST, current_position);
// Test for bad parameter combinations
if (int(hasC) + int(hasI && hasJ) != 1 || !(hasZ || hasQ || hasN))
SERIAL_ERROR_MSG(STR_ERR_M421_PARAMETERS);
// Test for I J out of range
else if (!WITHIN(ij.x, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(ij.y, 0, GRID_MAX_POINTS_Y - 1))
SERIAL_ERROR_MSG(STR_ERR_MESH_XY);
else {
float &zval = ubl.z_values[ij.x][ij.y];
zval = hasN ? NAN : parser.value_linear_units() + (hasQ ? zval : 0);
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ij.x, ij.y, zval));
float &zval = ubl.z_values[ij.x][ij.y]; // Altering this Mesh Point
zval = hasN ? NAN : parser.value_linear_units() + (hasQ ? zval : 0); // N=NAN, Z=NEWVAL, or Q=ADDVAL
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ij.x, ij.y, zval)); // Ping ExtUI in case it's showing the mesh
}
}
+3 -3
View File
@@ -219,7 +219,7 @@ void GcodeSuite::G28() {
#endif
#if ENABLED(MARLIN_DEV_MODE)
if (parser.seen('S')) {
if (parser.seen_test('S')) {
LOOP_XYZ(a) set_axis_is_at_home((AxisEnum)a);
sync_plan_position();
SERIAL_ECHOLNPGM("Simulated Homing");
@@ -321,10 +321,10 @@ void GcodeSuite::G28() {
#else
const bool homeZ = parser.seen('Z'),
const bool homeZ = parser.seen_test('Z'),
needX = homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(X_AXIS))),
needY = homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(Y_AXIS))),
homeX = needX || parser.seen('X'), homeY = needY || parser.seen('Y'),
homeX = needX || parser.seen_test('X'), homeY = needY || parser.seen_test('Y'),
home_all = homeX == homeY && homeX == homeZ, // All or None
doX = home_all || homeX, doY = home_all || homeY, doZ = home_all || homeZ;
+2 -2
View File
@@ -395,7 +395,7 @@ void GcodeSuite::G33() {
return;
}
const bool towers_set = !parser.seen('T');
const bool towers_set = !parser.seen_test('T');
const float calibration_precision = parser.floatval('C', 0.0f);
if (calibration_precision < 0) {
@@ -415,7 +415,7 @@ void GcodeSuite::G33() {
return;
}
const bool stow_after_each = parser.seen('E');
const bool stow_after_each = parser.seen_test('E');
const bool _0p_calibration = probe_points == 0,
_1p_calibration = probe_points == 1 || probe_points == -1,
+3 -2
View File
@@ -48,10 +48,11 @@ void GcodeSuite::G60() {
#if ENABLED(SAVED_POSITIONS_DEBUG)
const xyze_pos_t &pos = stored_position[slot];
DEBUG_ECHOPAIR_F(STR_SAVED_POS " S", slot);
DEBUG_ECHOPAIR(STR_SAVED_POS " S", slot);
DEBUG_ECHOPAIR_F(" : X", pos.x);
DEBUG_ECHOPAIR_F_P(SP_Y_STR, pos.y);
DEBUG_ECHOLNPAIR_F_P(SP_Z_STR, pos.z);
DEBUG_ECHOPAIR_F_P(SP_Z_STR, pos.z);
DEBUG_ECHOLNPAIR_F_P(SP_E_STR, pos.e);
#endif
}
+34 -13
View File
@@ -27,6 +27,10 @@
#include "../../../module/planner.h"
#include "../../gcode.h"
#include "../../../module/motion.h"
#include "../../../module/planner.h"
#define DEBUG_OUT ENABLED(SAVED_POSITIONS_DEBUG)
#include "../../../core/debug_out.h"
/**
* G61: Return to saved position
@@ -34,11 +38,16 @@
* F<rate> - Feedrate (optional) for the move back.
* S<slot> - Slot # (0-based) to restore from (default 0).
* X Y Z - Axes to restore. At least one is required.
* E - Restore extruder position
*
* If XYZE are not given, default restore uses the smart blocking move.
*/
void GcodeSuite::G61(void) {
const uint8_t slot = parser.byteval('S');
#define SYNC_E(POINT) planner.set_e_position_mm((destination.e = current_position.e = (POINT)))
#if SAVED_POSITIONS < 256
if (slot >= SAVED_POSITIONS) {
SERIAL_ERROR_MSG(STR_INVALID_POS_SLOT STRINGIFY(SAVED_POSITIONS));
@@ -47,25 +56,37 @@ void GcodeSuite::G61(void) {
#endif
// No saved position? No axes being restored?
if (!TEST(saved_slots[slot >> 3], slot & 0x07) || !parser.seen("XYZ")) return;
SERIAL_ECHOPAIR(STR_RESTORING_POS " S", slot);
LOOP_XYZ(i) {
destination[i] = parser.seen(XYZ_CHAR(i))
? stored_position[slot][i] + parser.value_axis_units((AxisEnum)i)
: current_position[i];
SERIAL_CHAR(' ', XYZ_CHAR(i));
SERIAL_ECHO_F(destination[i]);
}
SERIAL_EOL();
if (!TEST(saved_slots[slot >> 3], slot & 0x07)) return;
// Apply any given feedrate over 0.0
feedRate_t saved_feedrate = feedrate_mm_s;
const float fr = parser.linearval('F');
if (fr > 0.0) feedrate_mm_s = MMM_TO_MMS(fr);
// Move to the saved position
prepare_line_to_destination();
if (!parser.seen_axis()) {
DEBUG_ECHOLNPGM("Default position restore");
do_blocking_move_to(stored_position[slot], feedrate_mm_s);
SYNC_E(stored_position[slot].e);
}
else {
if (parser.seen("XYZ")) {
DEBUG_ECHOPAIR(STR_RESTORING_POS " S", slot);
LOOP_XYZ(i) {
destination[i] = parser.seen(XYZ_CHAR(i))
? stored_position[slot][i] + parser.value_axis_units((AxisEnum)i)
: current_position[i];
DEBUG_CHAR(' ', XYZ_CHAR(i));
DEBUG_ECHO_F(destination[i]);
}
DEBUG_EOL();
// Move to the saved position
prepare_line_to_destination();
}
if (parser.seen_test('E')) {
DEBUG_ECHOLNPAIR(STR_RESTORING_POS " S", slot, " E", current_position.e, "=>", stored_position[slot].e);
SYNC_E(stored_position[slot].e);
}
}
feedrate_mm_s = saved_feedrate;
}
+2 -4
View File
@@ -56,7 +56,7 @@
*/
void GcodeSuite::M125() {
// Initial retract before move to filament change position
const float retract = -ABS(parser.seen('L') ? parser.value_axis_units(E_AXIS) : (PAUSE_PARK_RETRACT_LENGTH));
const float retract = -ABS(parser.axisunitsval('L', E_AXIS, PAUSE_PARK_RETRACT_LENGTH));
xyz_pos_t park_point = NOZZLE_PARK_POINT;
@@ -78,10 +78,8 @@ void GcodeSuite::M125() {
// If possible, show an LCD prompt with the 'P' flag
const bool show_lcd = TERN0(HAS_LCD_MENU, parser.boolval('P'));
TERN_(POWER_LOSS_RECOVERY, if (recovery.enabled) recovery.save(true));
if (pause_print(retract, park_point, show_lcd, 0)) {
if (ENABLED(EXTENSIBLE_UI) || !sd_printing || show_lcd) {
if (ENABLED(EXTENSIBLE_UI) || BOTH(EMERGENCY_PARSER, HOST_PROMPT_SUPPORT) || !sd_printing || show_lcd) {
wait_for_confirmation(false, 0);
resume_print(0, 0, -retract, 0);
}
+5 -9
View File
@@ -81,8 +81,8 @@ void GcodeSuite::M600() {
#if ENABLED(DUAL_X_CARRIAGE)
int8_t DXC_ext = target_extruder;
if (!parser.seen('T')) { // If no tool index is specified, M600 was (probably) sent in response to filament runout.
// In this case, for duplicating modes set DXC_ext to the extruder that ran out.
if (!parser.seen_test('T')) { // If no tool index is specified, M600 was (probably) sent in response to filament runout.
// In this case, for duplicating modes set DXC_ext to the extruder that ran out.
#if MULTI_FILAMENT_SENSOR
if (idex_is_duplicating())
DXC_ext = (READ(FIL_RUNOUT2_PIN) == FIL_RUNOUT2_STATE) ? 1 : 0;
@@ -110,7 +110,7 @@ void GcodeSuite::M600() {
#endif
// Initial retract before move to filament change position
const float retract = -ABS(parser.seen('E') ? parser.value_axis_units(E_AXIS) : (PAUSE_PARK_RETRACT_LENGTH));
const float retract = -ABS(parser.axisunitsval('E', E_AXIS, PAUSE_PARK_RETRACT_LENGTH));
xyz_pos_t park_point NOZZLE_PARK_POINT;
@@ -132,15 +132,11 @@ void GcodeSuite::M600() {
fast_load_length = 0.0f;
#else
// Unload filament
const float unload_length = -ABS(parser.seen('U') ? parser.value_axis_units(E_AXIS)
: fc_settings[active_extruder].unload_length);
const float unload_length = -ABS(parser.axisunitsval('U', E_AXIS, fc_settings[active_extruder].unload_length));
// Slow load filament
constexpr float slow_load_length = FILAMENT_CHANGE_SLOW_LOAD_LENGTH;
// Fast load filament
const float fast_load_length = ABS(parser.seen('L') ? parser.value_axis_units(E_AXIS)
: fc_settings[active_extruder].load_length);
const float fast_load_length = ABS(parser.axisunitsval('L', E_AXIS, fc_settings[active_extruder].load_length));
#endif
const int beep_count = parser.intval('B', -1
+2 -2
View File
@@ -59,7 +59,7 @@ inline void plr_error(PGM_P const prefix) {
void GcodeSuite::M1000() {
if (recovery.valid()) {
if (parser.seen('S')) {
if (parser.seen_test('S')) {
#if HAS_LCD_MENU
ui.goto_screen(menu_job_recovery);
#elif ENABLED(DWIN_CREALITY_LCD)
@@ -70,7 +70,7 @@ void GcodeSuite::M1000() {
SERIAL_ECHO_MSG("Resume requires LCD.");
#endif
}
else if (parser.seen('C')) {
else if (parser.seen_test('C')) {
#if HAS_LCD_MENU
lcd_power_loss_recovery_cancel();
#else
+6 -6
View File
@@ -48,14 +48,14 @@ void GcodeSuite::M413() {
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
if (parser.seen("RL")) recovery.load();
if (parser.seen('W')) recovery.save(true);
if (parser.seen('P')) recovery.purge();
if (parser.seen('D')) recovery.debug(PSTR("M413"));
if (parser.seen_test('W')) recovery.save(true);
if (parser.seen_test('P')) recovery.purge();
if (parser.seen_test('D')) recovery.debug(PSTR("M413"));
#if PIN_EXISTS(POWER_LOSS)
if (parser.seen('O')) recovery._outage();
if (parser.seen_test('O')) recovery._outage();
#endif
if (parser.seen('E')) SERIAL_ECHOPGM_P(recovery.exists() ? PSTR("PLR Exists\n") : PSTR("No PLR\n"));
if (parser.seen('V')) SERIAL_ECHOPGM_P(recovery.valid() ? PSTR("Valid\n") : PSTR("Invalid\n"));
if (parser.seen_test('E')) SERIAL_ECHOPGM_P(recovery.exists() ? PSTR("PLR Exists\n") : PSTR("No PLR\n"));
if (parser.seen_test('V')) SERIAL_ECHOPGM_P(recovery.valid() ? PSTR("Valid\n") : PSTR("Invalid\n"));
#endif
}
+1 -1
View File
@@ -44,7 +44,7 @@ void GcodeSuite::M412() {
#if ENABLED(HOST_ACTION_COMMANDS)
if (parser.seen('H')) runout.host_handling = parser.value_bool();
#endif
const bool seenR = parser.seen('R'), seenS = parser.seen('S');
const bool seenR = parser.seen_test('R'), seenS = parser.seen('S');
if (seenR || seenS) runout.reset();
if (seenS) runout.enabled = parser.value_bool();
#if HAS_FILAMENT_RUNOUT_DISTANCE
+3 -2
View File
@@ -32,7 +32,8 @@
* M122: Debug TMC drivers
*/
void GcodeSuite::M122() {
xyze_bool_t print_axis = { false, false, false, false };
xyze_bool_t print_axis = ARRAY_N_1(XYZE, false);
bool print_all = true;
LOOP_XYZE(i) if (parser.seen(axis_codes[i])) { print_axis[i] = true; print_all = false; }
@@ -48,7 +49,7 @@ void GcodeSuite::M122() {
tmc_set_report_interval(interval);
#endif
if (parser.seen('V'))
if (parser.seen_test('V'))
tmc_get_registers(print_axis.x, print_axis.y, print_axis.z, print_axis.e);
else
tmc_report_all(print_axis.x, print_axis.y, print_axis.z, print_axis.e);
+10 -2
View File
@@ -211,7 +211,7 @@ void GcodeSuite::dwell(millis_t time) {
* When G29_RETRY_AND_RECOVER is enabled, call G29() in
* a loop with recovery and retry handling.
*/
#if BOTH(HAS_LEVELING, G29_RETRY_AND_RECOVER)
#if ENABLED(G29_RETRY_AND_RECOVER)
void GcodeSuite::event_probe_recover() {
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_INFO, PSTR("G29 Retrying"), DISMISS_STR));
@@ -223,6 +223,10 @@ void GcodeSuite::dwell(millis_t time) {
#endif
}
#if ENABLED(G29_HALT_ON_FAILURE)
#include "../lcd/marlinui.h"
#endif
void GcodeSuite::event_probe_failure() {
#ifdef ACTION_ON_G29_FAILURE
host_action(PSTR(ACTION_ON_G29_FAILURE));
@@ -262,7 +266,7 @@ void GcodeSuite::dwell(millis_t time) {
#endif
}
#endif // HAS_LEVELING && G29_RETRY_AND_RECOVER
#endif // G29_RETRY_AND_RECOVER
/**
* Process the parsed command and dispatch it to its handler
@@ -561,6 +565,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 193: M193(); break; // M193: Wait for cooler temperature to reach target
#endif
#if ENABLED(AUTO_REPORT_POSITION)
case 154: M154(); break; // M155: Set position auto-report interval
#endif
#if BOTH(AUTO_REPORT_TEMPERATURES, HAS_TEMP_SENSOR)
case 155: M155(); break; // M155: Set temperature auto-report interval
#endif
+5
View File
@@ -159,6 +159,7 @@
* M145 - Set heatup values for materials on the LCD. H<hotend> B<bed> F<fan speed> for S<material> (0=PLA, 1=ABS)
* M149 - Set temperature units. (Requires TEMPERATURE_UNITS_SUPPORT)
* M150 - Set Status LED Color as R<red> U<green> B<blue> W<white> P<bright>. Values 0-255. (Requires BLINKM, RGB_LED, RGBW_LED, NEOPIXEL_LED, PCA9533, or PCA9632).
* M154 - Auto-report position with interval of S<seconds>. (Requires AUTO_REPORT_POSITION)
* M155 - Auto-report temperatures with interval of S<seconds>. (Requires AUTO_REPORT_TEMPERATURES)
* M163 - Set a single proportion for a mixing extruder. (Requires MIXING_EXTRUDER)
* M164 - Commit the mix and save to a virtual tool (current, or as specified by 'S'). (Requires MIXING_EXTRUDER)
@@ -721,6 +722,10 @@ private:
static void M150();
#endif
#if ENABLED(AUTO_REPORT_POSITION)
static void M154();
#endif
#if BOTH(AUTO_REPORT_TEMPERATURES, HAS_TEMP_SENSOR)
static void M155();
#endif
+1 -1
View File
@@ -52,7 +52,7 @@
break;
case 10:
kill(PSTR("D10"), PSTR("KILL TEST"), parser.seen('P'));
kill(PSTR("D10"), PSTR("KILL TEST"), parser.seen_test('P'));
break;
case 1: {
+3 -3
View File
@@ -193,7 +193,7 @@
void GcodeSuite::M114() {
#if ENABLED(M114_DETAIL)
if (parser.seen('D')) {
if (parser.seen_test('D')) {
#if DISABLED(M114_LEGACY)
planner.synchronize();
#endif
@@ -201,14 +201,14 @@ void GcodeSuite::M114() {
report_current_position_detail();
return;
}
if (parser.seen('E')) {
if (parser.seen_test('E')) {
SERIAL_ECHOLNPAIR("Count E:", stepper.position(E_AXIS));
return;
}
#endif
#if ENABLED(M114_REALTIME)
if (parser.seen('R')) { report_real_position(); return; }
if (parser.seen_test('R')) { report_real_position(); return; }
#endif
TERN_(M114_LEGACY, planner.synchronize());
+3
View File
@@ -82,6 +82,9 @@ void GcodeSuite::M115() {
// Volumetric Extrusion (M200)
cap_line(PSTR("VOLUMETRIC"), DISABLED(NO_VOLUMETRICS));
// AUTOREPORT_POS (M154)
cap_line(PSTR("AUTOREPORT_POS"), ENABLED(AUTO_REPORT_POSITION));
// AUTOREPORT_TEMP (M155)
cap_line(PSTR("AUTOREPORT_TEMP"), ENABLED(AUTO_REPORT_TEMPERATURES));
+40
View File
@@ -0,0 +1,40 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
*
*/
#include "../../inc/MarlinConfigPre.h"
#if ENABLED(AUTO_REPORT_POSITION)
#include "../gcode.h"
#include "../../module/motion.h"
/**
* M154: Set position auto-report interval. M154 S<seconds>
*/
void GcodeSuite::M154() {
if (parser.seenval('S'))
position_auto_reporter.set_interval(parser.value_byte());
}
#endif // AUTO_REPORT_POSITION
+3 -3
View File
@@ -49,9 +49,9 @@ void GcodeSuite::G0_G1(TERN_(HAS_FAST_MOVES, const bool fast_move/*=false*/)) {
if (IsRunning()
#if ENABLED(NO_MOTION_BEFORE_HOMING)
&& !homing_needed_error(
(parser.seen('X') ? _BV(X_AXIS) : 0)
| (parser.seen('Y') ? _BV(Y_AXIS) : 0)
| (parser.seen('Z') ? _BV(Z_AXIS) : 0) )
(parser.seen_test('X') ? _BV(X_AXIS) : 0)
| (parser.seen_test('Y') ? _BV(Y_AXIS) : 0)
| (parser.seen_test('Z') ? _BV(Z_AXIS) : 0) )
#endif
) {
TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(M_RUNNING));
+2 -2
View File
@@ -74,7 +74,7 @@ void GcodeSuite::M290() {
const float offs = constrain(parser.value_axis_units((AxisEnum)a), -2, 2);
babystep.add_mm((AxisEnum)a, offs);
#if ENABLED(BABYSTEP_ZPROBE_OFFSET)
if (a == Z_AXIS && (!parser.seen('P') || parser.value_bool())) mod_probe_offset(offs);
if (a == Z_AXIS && parser.boolval('P', true)) mod_probe_offset(offs);
#endif
}
#else
@@ -82,7 +82,7 @@ void GcodeSuite::M290() {
const float offs = constrain(parser.value_axis_units(Z_AXIS), -2, 2);
babystep.add_mm(Z_AXIS, offs);
#if ENABLED(BABYSTEP_ZPROBE_OFFSET)
if (!parser.seen('P') || parser.value_bool()) mod_probe_offset(offs);
if (parser.boolval('P', true)) mod_probe_offset(offs);
#endif
}
#endif
+50 -46
View File
@@ -150,12 +150,30 @@ void GCodeParser::parse(char *p) {
#endif
/**
* Screen for good command letters. G, M, and T are always accepted.
* With Motion Modes enabled any axis letter can come first.
* Screen for good command letters.
* With Realtime Reporting, commands S000, P000, and R000 are allowed.
*/
#if ENABLED(REALTIME_REPORTING_COMMANDS)
switch (letter) {
case 'P': case 'R' ... 'S': {
uint8_t digits = 0;
char *a = p;
while (*a++ == '0') digits++; // Count up '0' characters
if (digits == 3) { // Three '0' digits is a good command
codenum = 0;
command_letter = letter;
return;
}
}
}
#endif
/**
* Screen for good command letters. G, M, and T are always accepted.
* With Motion Modes enabled any axis letter can come first.
*/
switch (letter) {
case 'G': case 'M': case 'T': TERN_(MARLIN_DEV_MODE, case 'D':)
case 'G': case 'M': case 'T': TERN_(MARLIN_DEV_MODE, case 'D':) {
// Skip spaces to get the numeric part
while (*p == ' ') p++;
@@ -177,20 +195,18 @@ void GCodeParser::parse(char *p) {
// A '?' signifies an unknown command
command_letter = letter;
{
#if ENABLED(SIGNED_CODENUM)
int sign = 1; // Allow for a negative code like D-1 or T-1
if (*p == '-') { sign = -1; ++p; }
#endif
#if ENABLED(SIGNED_CODENUM)
int sign = 1; // Allow for a negative code like D-1 or T-1
if (*p == '-') { sign = -1; ++p; }
#endif
// Get the code number - integer digits only
codenum = 0;
// Get the code number - integer digits only
codenum = 0;
do { codenum = codenum * 10 + *p++ - '0'; } while (NUMERIC(*p));
do { codenum = codenum * 10 + *p++ - '0'; } while (NUMERIC(*p));
// Apply the sign, if any
TERN_(SIGNED_CODENUM, codenum *= sign);
}
// Apply the sign, if any
TERN_(SIGNED_CODENUM, codenum *= sign);
// Allow for decimal point in command
#if USE_GCODE_SUBCODES
@@ -213,39 +229,33 @@ void GCodeParser::parse(char *p) {
}
#endif
break;
} break;
#if ENABLED(GCODE_MOTION_MODES)
#if ENABLED(ARC_SUPPORT)
case 'I' ... 'J':
if (motion_mode_codenum != 2 && motion_mode_codenum != 3) return;
#if EITHER(BEZIER_CURVE_SUPPORT, ARC_SUPPORT)
case 'I' ... 'J': case 'P':
if (TERN1(BEZIER_CURVE_SUPPORT, motion_mode_codenum != 5)
&& TERN1(ARC_P_CIRCLES, !WITHIN(motion_mode_codenum, 2, 3))
) return;
#endif
case 'Q':
if (motion_mode_codenum != 5) return;
#if ENABLED(BEZIER_CURVE_SUPPORT)
case 'Q': if (motion_mode_codenum != 5) return;
#endif
#if ENABLED(ARC_SUPPORT)
case 'R': if (!WITHIN(motion_mode_codenum, 2, 3)) return;
#endif
case 'X' ... 'Z': case 'E' ... 'F':
if (motion_mode_codenum < 0) return;
command_letter = 'G';
codenum = motion_mode_codenum;
TERN_(USE_GCODE_SUBCODES, subcode = motion_mode_subcode);
p--; // Back up one character to use the current parameter
break;
#endif
break;
#if ENABLED(REALTIME_REPORTING_COMMANDS)
case 'P': case 'R': {
if (letter == 'R') {
#if ENABLED(GCODE_MOTION_MODES)
if (ENABLED(ARC_SUPPORT) && !WITHIN(motion_mode_codenum, 2, 3)) return;
#endif
}
else if (TERN0(GCODE_MOTION_MODES, motion_mode_codenum != 5)) return;
} // fall-thru
case 'S': {
codenum = 0; // The only valid codenum is 0
uint8_t digits = 0;
while (*p++ == '0') digits++; // Count up '0' characters
command_letter = (digits == 3) ? letter : '?'; // Three '0' digits is a good command
} return; // No parameters needed, so return now
#endif
default: return;
@@ -253,18 +263,12 @@ void GCodeParser::parse(char *p) {
// The command parameters (if any) start here, for sure!
#if DISABLED(FASTER_GCODE_PARSER)
command_args = p; // Scan for parameters in seen()
#endif
IF_DISABLED(FASTER_GCODE_PARSER, command_args = p); // Scan for parameters in seen()
// Only use string_arg for these M codes
if (letter == 'M') switch (codenum) {
#if ENABLED(GCODE_MACROS)
case 810 ... 819:
#endif
#if ENABLED(EXPECTED_PRINTER_CHECK)
case 16:
#endif
TERN_(GCODE_MACROS, case 810 ... 819:)
TERN_(EXPECTED_PRINTER_CHECK, case 16:)
case 23: case 28: case 30: case 117 ... 118: case 928:
string_arg = unescape_string(p);
return;
+2
View File
@@ -408,6 +408,8 @@ public:
static inline int32_t longval(const char c, const int32_t dval=0) { return seenval(c) ? value_long() : dval; }
static inline uint32_t ulongval(const char c, const uint32_t dval=0) { return seenval(c) ? value_ulong() : dval; }
static inline float linearval(const char c, const float dval=0) { return seenval(c) ? value_linear_units() : dval; }
static inline float axisunitsval(const char c, const AxisEnum a, const float dval=0)
{ return seenval(c) ? value_axis_units(a) : dval; }
static inline celsius_t celsiusval(const char c, const float dval=0) { return seenval(c) ? value_celsius() : dval; }
#if ENABLED(MARLIN_DEV_MODE)
+5 -8
View File
@@ -501,13 +501,9 @@ void GCodeQueue::get_serial_commands() {
char* gpos = strchr(command, 'G');
if (gpos) {
switch (strtol(gpos + 1, nullptr, 10)) {
case 0: case 1:
#if ENABLED(ARC_SUPPORT)
case 2: case 3:
#endif
#if ENABLED(BEZIER_CURVE_SUPPORT)
case 5:
#endif
case 0 ... 1:
TERN_(ARC_SUPPORT, case 2 ... 3:)
TERN_(BEZIER_CURVE_SUPPORT, case 5:)
PORT_REDIRECT(SERIAL_PORTMASK(p)); // Reply to the serial port that sent the command
SERIAL_ECHOLNPGM(STR_ERR_STOPPED);
LCD_MESSAGEPGM(MSG_STOPPED);
@@ -554,7 +550,8 @@ void GCodeQueue::get_serial_commands() {
inline void GCodeQueue::get_sdcard_commands() {
static uint8_t sd_input_state = PS_NORMAL;
if (!IS_SD_PRINTING()) return;
// Get commands if there are more in the file
if (!IS_SD_FETCHING()) return;
int sd_count = 0;
while (!ring_buffer.full() && !card.eof()) {
+7 -4
View File
@@ -25,11 +25,9 @@
#if ENABLED(SDSUPPORT)
#include "../gcode.h"
#include "../../module/planner.h"
#include "../../module/printcounter.h"
#if DISABLED(NO_SD_AUTOSTART)
#include "../../sd/cardreader.h"
#endif
#include "../../sd/cardreader.h"
#ifdef SD_FINISHED_RELEASECOMMAND
#include "../queue.h"
@@ -64,6 +62,11 @@
* M1001: Execute actions for SD print completion
*/
void GcodeSuite::M1001() {
planner.synchronize();
// SD Printing is finished when the queue reaches M1001
card.flag.sdprinting = card.flag.sdprintdone = false;
// If there's another auto#.g file to run...
if (TERN(NO_SD_AUTOSTART, false, card.autofile_check())) return;
+2 -2
View File
@@ -70,7 +70,7 @@ void GcodeSuite::M24() {
#endif
if (card.isFileOpen()) {
card.startFileprint(); // SD card will now be read for commands
card.startOrResumeFilePrinting(); // SD card will now be read for commands
startOrResumeJob(); // Start (or resume) the print job timer
TERN_(POWER_LOSS_RECOVERY, recovery.prepare());
}
@@ -105,7 +105,7 @@ void GcodeSuite::M25() {
if (IS_SD_PRINTING()) card.pauseSDPrint();
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
#if ENABLED(POWER_LOSS_RECOVERY) && DISABLED(DGUS_LCD_UI_MKS)
if (recovery.enabled) recovery.save(true);
#endif
+2 -2
View File
@@ -33,9 +33,9 @@
* OR, with 'C' get the current filename.
*/
void GcodeSuite::M27() {
if (parser.seen('C')) {
if (parser.seen_test('C')) {
SERIAL_ECHOPGM("Current file: ");
card.printFilename();
card.printSelectedFilename();
return;
}
+1 -1
View File
@@ -49,7 +49,7 @@ void GcodeSuite::M32() {
if (parser.seenval('S')) card.setIndex(parser.value_long());
card.startFileprint();
card.startOrResumeFilePrinting();
// Procedure calls count as normal print time.
if (!call_procedure) startOrResumeJob();
+1 -1
View File
@@ -33,7 +33,7 @@
void GcodeSuite::M524() {
if (IS_SD_PRINTING())
card.flag.abort_sd_printing = true;
card.abortFilePrintSoon();
else if (card.isMounted())
card.closefile();
+1 -1
View File
@@ -44,7 +44,7 @@ void GcodeSuite::M808() {
// Allowed to go into the queue for logging purposes.
// M808 K sent from the host to cancel all loops
if (parser.seen('K')) repeat.cancel();
if (parser.seen_test('K')) repeat.cancel();
}
+1 -1
View File
@@ -68,7 +68,7 @@ void GcodeSuite::M106() {
if (t > 0) return thermalManager.set_temp_fan_speed(pfan, t);
#endif
const uint16_t dspeed = parser.seen('A') ? thermalManager.fan_speed[active_extruder] : 255;
const uint16_t dspeed = parser.seen_test('A') ? thermalManager.fan_speed[active_extruder] : 255;
uint16_t speed = dspeed;
+1 -1
View File
@@ -47,7 +47,7 @@
void GcodeSuite::M303() {
#if ANY(PID_DEBUG, PID_BED_DEBUG, PID_CHAMBER_DEBUG)
if (parser.seen('D')) {
if (parser.seen_test('D')) {
thermalManager.pid_debug_flag ^= true;
SERIAL_ECHO_START();
SERIAL_ECHOPGM("PID Debug ");
+31 -9
View File
@@ -617,9 +617,9 @@
// Helper macros for extruder and hotend arrays
#define HOTEND_LOOP() for (int8_t e = 0; e < HOTENDS; e++)
#define ARRAY_BY_EXTRUDERS(V...) ARRAY_N(EXTRUDERS, V)
#define ARRAY_BY_EXTRUDERS1(v1) ARRAY_BY_EXTRUDERS(v1, v1, v1, v1, v1, v1, v1, v1)
#define ARRAY_BY_EXTRUDERS1(v1) ARRAY_N_1(EXTRUDERS, v1)
#define ARRAY_BY_HOTENDS(V...) ARRAY_N(HOTENDS, V)
#define ARRAY_BY_HOTENDS1(v1) ARRAY_BY_HOTENDS(v1, v1, v1, v1, v1, v1, v1, v1)
#define ARRAY_BY_HOTENDS1(v1) ARRAY_N_1(HOTENDS, v1)
#if ENABLED(SWITCHING_EXTRUDER) && (DISABLED(SWITCHING_NOZZLE) || SWITCHING_EXTRUDER_SERVO_NR != SWITCHING_NOZZLE_SERVO_NR)
#define DO_SWITCH_EXTRUDER 1
@@ -870,6 +870,7 @@
#if !HAS_LEVELING
#undef RESTORE_LEVELING_AFTER_G28
#undef ENABLE_LEVELING_AFTER_G28
#undef G29_RETRY_AND_RECOVER
#endif
#if !HAS_LEVELING || EITHER(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL)
#undef PROBE_MANUALLY
@@ -955,15 +956,19 @@
// Serial Port Info
//
#ifdef SERIAL_PORT_2
#define NUM_SERIAL 2
#define HAS_MULTI_SERIAL 1
#ifdef SERIAL_PORT_3
#define NUM_SERIAL 3
#else
#define NUM_SERIAL 2
#endif
#elif defined(SERIAL_PORT)
#define NUM_SERIAL 1
#else
#define NUM_SERIAL 0
#undef BAUD_RATE_GCODE
#endif
#if SERIAL_PORT == -1 || SERIAL_PORT_2 == -1
#if SERIAL_PORT == -1 || SERIAL_PORT_2 == -1 || SERIAL_PORT_3 == -1
#define HAS_USB_SERIAL 1
#endif
#if SERIAL_PORT_2 == -2
@@ -1127,6 +1132,9 @@
#define TFT_DEFAULT_ORIENTATION (TFT_EXCHANGE_XY)
#define TFT_RES_1024x600
#define TFT_INTERFACE_LTDC
#if ENABLED(TOUCH_SCREEN)
#define TFT_TOUCH_DEVICE_GT911
#endif
#elif ENABLED(TFT_GENERIC)
#define TFT_DEFAULT_ORIENTATION (TFT_EXCHANGE_XY | TFT_INVERT_X | TFT_INVERT_Y)
#if NONE(TFT_RES_320x240, TFT_RES_480x272, TFT_RES_480x320)
@@ -1215,16 +1223,30 @@
#define HAS_UI_1024x600 1
#endif
#if ANY(HAS_UI_320x240, HAS_UI_480x320, HAS_UI_480x272)
#define LCD_HEIGHT TERN(TOUCH_SCREEN, 6, 7) // Fewer lines with touch buttons onscreen
#define LCD_HEIGHT TERN(TOUCH_SCREEN, 6, 7) // Fewer lines with touch buttons onscreen
#elif HAS_UI_1024x600
#define LCD_HEIGHT TERN(TOUCH_SCREEN, 12, 13) // Fewer lines with touch buttons onscreen
#endif
// This emulated DOGM has 'touch/xpt2046', not 'tft/xpt2046'
#if ENABLED(TOUCH_SCREEN) && !HAS_GRAPHICAL_TFT
#undef TOUCH_SCREEN
#if ENABLED(TFT_CLASSIC_UI)
#define HAS_TOUCH_BUTTONS 1
#if ENABLED(TOUCH_SCREEN)
#if NONE(TFT_TOUCH_DEVICE_GT911, TFT_TOUCH_DEVICE_XPT2046)
#define TFT_TOUCH_DEVICE_XPT2046 // ADS7843/XPT2046 ADC Touchscreen such as ILI9341 2.8
#endif
#if ENABLED(TFT_TOUCH_DEVICE_GT911) // GT911 Capacitive touch screen such as BIQU_BX_TFT70
#undef TOUCH_SCREEN_CALIBRATION
#undef TOUCH_CALIBRATION_AUTO_SAVE
#endif
#if !HAS_GRAPHICAL_TFT
#undef TOUCH_SCREEN
#if ENABLED(TFT_CLASSIC_UI)
#define HAS_TOUCH_BUTTONS 1
#if ENABLED(TFT_TOUCH_DEVICE_GT911)
#define HAS_CAP_TOUCH_BUTTONS 1
#else
#define HAS_RES_TOUCH_BUTTONS 1
#endif
#endif
#endif
#endif
+2 -2
View File
@@ -371,13 +371,13 @@
#endif
// Full Touch Screen needs 'tft/xpt2046'
#if EITHER(TOUCH_SCREEN, HAS_TFT_LVGL_UI)
#if EITHER(TFT_TOUCH_DEVICE_XPT2046, HAS_TFT_LVGL_UI)
#define HAS_TFT_XPT2046 1
#endif
// Touch Screen or "Touch Buttons" need XPT2046 pins
// but they use different components
#if EITHER(HAS_TFT_XPT2046, HAS_TOUCH_BUTTONS)
#if HAS_TFT_XPT2046 || HAS_RES_TOUCH_BUTTONS
#define NEED_TOUCH_PINS 1
#endif
+25 -18
View File
@@ -330,11 +330,6 @@
*/
#if ENABLED(SDSUPPORT)
// Extender cable doesn't support SD_DETECT_PIN
#if ENABLED(NO_SD_DETECT)
#undef SD_DETECT_PIN
#endif
#if HAS_SD_HOST_DRIVE && SD_CONNECTION_IS(ONBOARD)
//
// The external SD card is not used. Hardware SPI is used to access the card.
@@ -345,18 +340,20 @@
#define HAS_SHARED_MEDIA 1
#endif
#if PIN_EXISTS(SD_DETECT)
#if HAS_LCD_MENU && (SD_CONNECTION_IS(LCD) || !defined(SDCARD_CONNECTION))
#undef SD_DETECT_STATE
#if ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
#define SD_DETECT_STATE HIGH
#endif
#endif
#ifndef SD_DETECT_STATE
// Set SD_DETECT_STATE based on hardware if not overridden
#if PIN_EXISTS(SD_DETECT) && !defined(SD_DETECT_STATE)
#if BOTH(HAS_LCD_MENU, ELB_FULL_GRAPHIC_CONTROLLER) && (SD_CONNECTION_IS(LCD) || !defined(SDCARD_CONNECTION))
#define SD_DETECT_STATE HIGH
#else
#define SD_DETECT_STATE LOW
#endif
#endif
// Extender cable doesn't support SD_DETECT_PIN
#if ENABLED(NO_SD_DETECT)
#undef SD_DETECT_PIN
#endif
#if DISABLED(USB_FLASH_DRIVE_SUPPORT) || BOTH(MULTI_VOLUME, VOLUME_SD_ONBOARD)
#if ENABLED(SDIO_SUPPORT)
#define NEED_SD2CARD_SDIO 1
@@ -1859,6 +1856,7 @@
// Flag the indexed hardware serial ports in use
#define CONF_SERIAL_IS(N) ( (defined(SERIAL_PORT) && SERIAL_PORT == N) \
|| (defined(SERIAL_PORT_2) && SERIAL_PORT_2 == N) \
|| (defined(SERIAL_PORT_3) && SERIAL_PORT_3 == N) \
|| (defined(MMU2_SERIAL_PORT) && MMU2_SERIAL_PORT == N) \
|| (defined(LCD_SERIAL_PORT) && LCD_SERIAL_PORT == N) )
@@ -1949,7 +1947,6 @@
#undef _SERIAL_ID
#undef _TMC_UART_IS
#undef TMC_UART_IS
#undef CONF_SERIAL_IS
#undef ANY_SERIAL_IS
//
@@ -2234,7 +2231,7 @@
#if !HAS_TEMP_SENSOR
#undef AUTO_REPORT_TEMPERATURES
#endif
#if EITHER(AUTO_REPORT_TEMPERATURES, AUTO_REPORT_SD_STATUS)
#if ANY(AUTO_REPORT_TEMPERATURES, AUTO_REPORT_SD_STATUS, AUTO_REPORT_POSITION)
#define HAS_AUTO_REPORTING 1
#endif
@@ -2321,12 +2318,22 @@
#endif
// User Interface
#if ENABLED(FREEZE_FEATURE)
#if !PIN_EXISTS(FREEZE) && PIN_EXISTS(KILL)
#define FREEZE_PIN KILL_PIN
#endif
#if PIN_EXISTS(FREEZE)
#define HAS_FREEZE_PIN 1
#endif
#else
#undef FREEZE_PIN
#endif
#if PIN_EXISTS(KILL) && TERN1(FREEZE_FEATURE, KILL_PIN != FREEZE_PIN)
#define HAS_KILL 1
#endif
#if PIN_EXISTS(HOME)
#define HAS_HOME 1
#endif
#if PIN_EXISTS(KILL)
#define HAS_KILL 1
#endif
#if PIN_EXISTS(SUICIDE)
#define HAS_SUICIDE 1
#endif
+36 -17
View File
@@ -607,6 +607,14 @@
#error "SERIAL_PORT must be defined."
#elif defined(SERIAL_PORT_2) && SERIAL_PORT_2 == SERIAL_PORT
#error "SERIAL_PORT_2 cannot be the same as SERIAL_PORT."
#elif defined(SERIAL_PORT_3)
#ifndef SERIAL_PORT_2
#error "Use SERIAL_PORT_2 before using SERIAL_PORT_3"
#elif SERIAL_PORT_3 == SERIAL_PORT
#error "SERIAL_PORT_3 cannot be the same as SERIAL_PORT."
#elif SERIAL_PORT_3 == SERIAL_PORT_2
#error "SERIAL_PORT_3 cannot be the same as SERIAL_PORT_2."
#endif
#endif
#if !(defined(__AVR__) && defined(USBCON))
#if ENABLED(SERIAL_XON_XOFF) && RX_BUFFER_SIZE < 1024
@@ -752,6 +760,13 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#error "LIGHTWEIGHT_UI requires a U8GLIB_ST7920-based display."
#endif
/**
* SD Card Settings
*/
#if ALL(SDSUPPORT, ELB_FULL_GRAPHIC_CONTROLLER, HAS_LCD_MENU) && PIN_EXISTS(SD_DETECT) && SD_DETECT_STATE != HIGH && (SD_CONNECTION_IS(LCD) || !defined(SDCARD_CONNECTION))
#error "SD_DETECT_STATE must be set HIGH for SD on the ELB_FULL_GRAPHIC_CONTROLLER."
#endif
/**
* SD File Sorting
*/
@@ -2796,23 +2811,30 @@ constexpr float sanity_arr_1[] = DEFAULT_AXIS_STEPS_PER_UNIT,
sanity_arr_3[] = DEFAULT_MAX_ACCELERATION;
#define _ARR_TEST(N,I) (sanity_arr_##N[_MIN(I,int(COUNT(sanity_arr_##N))-1)] > 0)
#if HAS_MULTI_EXTRUDER
#define _EXTRA_NOTE " (Did you forget to enable DISTINCT_E_FACTORS?)"
#elif EXTRUDERS == 0
#define _EXTRA_NOTE " (Note: EXTRUDERS is set to 0.)"
#else
#define _EXTRA_NOTE ""
#endif
static_assert(COUNT(sanity_arr_1) >= XYZE, "DEFAULT_AXIS_STEPS_PER_UNIT requires X, Y, Z and E elements.");
static_assert(COUNT(sanity_arr_1) <= XYZE_N, "DEFAULT_AXIS_STEPS_PER_UNIT has too many elements. (Did you forget to enable DISTINCT_E_FACTORS?)");
static_assert(COUNT(sanity_arr_1) <= XYZE_N, "DEFAULT_AXIS_STEPS_PER_UNIT has too many elements." _EXTRA_NOTE);
static_assert( _ARR_TEST(1,0) && _ARR_TEST(1,1) && _ARR_TEST(1,2)
&& _ARR_TEST(1,3) && _ARR_TEST(1,4) && _ARR_TEST(1,5)
&& _ARR_TEST(1,6) && _ARR_TEST(1,7) && _ARR_TEST(1,8),
"DEFAULT_AXIS_STEPS_PER_UNIT values must be positive.");
static_assert(COUNT(sanity_arr_2) >= XYZE, "DEFAULT_MAX_FEEDRATE requires X, Y, Z and E elements.");
static_assert(COUNT(sanity_arr_2) <= XYZE_N, "DEFAULT_MAX_FEEDRATE has too many elements. (Did you forget to enable DISTINCT_E_FACTORS?)");
static_assert(COUNT(sanity_arr_2) <= XYZE_N, "DEFAULT_MAX_FEEDRATE has too many elements." _EXTRA_NOTE);
static_assert( _ARR_TEST(2,0) && _ARR_TEST(2,1) && _ARR_TEST(2,2)
&& _ARR_TEST(2,3) && _ARR_TEST(2,4) && _ARR_TEST(2,5)
&& _ARR_TEST(2,6) && _ARR_TEST(2,7) && _ARR_TEST(2,8),
"DEFAULT_MAX_FEEDRATE values must be positive.");
static_assert(COUNT(sanity_arr_3) >= XYZE, "DEFAULT_MAX_ACCELERATION requires X, Y, Z and E elements.");
static_assert(COUNT(sanity_arr_3) <= XYZE_N, "DEFAULT_MAX_ACCELERATION has too many elements. (Did you forget to enable DISTINCT_E_FACTORS?)");
static_assert(COUNT(sanity_arr_3) <= XYZE_N, "DEFAULT_MAX_ACCELERATION has too many elements." _EXTRA_NOTE);
static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
&& _ARR_TEST(3,3) && _ARR_TEST(3,4) && _ARR_TEST(3,5)
&& _ARR_TEST(3,6) && _ARR_TEST(3,7) && _ARR_TEST(3,8),
@@ -2855,6 +2877,7 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
#endif
#undef _ARR_TEST
#undef _EXTRA_NOTE
#if BOTH(CNC_COORDINATE_SYSTEMS, NO_WORKSPACE_OFFSETS)
#error "CNC_COORDINATE_SYSTEMS is incompatible with NO_WORKSPACE_OFFSETS."
@@ -2895,6 +2918,8 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
#error "POWER_LOSS_RECOVER_ZHOME cannot be used with Z_SAFE_HOMING."
#elif BOTH(POWER_LOSS_PULLUP, POWER_LOSS_PULLDOWN)
#error "You can't enable POWER_LOSS_PULLUP and POWER_LOSS_PULLDOWN at the same time."
#elif ENABLED(POWER_LOSS_RECOVER_ZHOME) && Z_HOME_DIR > 0
#error "POWER_LOSS_RECOVER_ZHOME is not needed on a machine that homes to ZMAX."
#elif BOTH(IS_CARTESIAN, POWER_LOSS_RECOVER_ZHOME) && Z_HOME_DIR < 0 && !defined(POWER_LOSS_ZHOME_POS)
#error "POWER_LOSS_RECOVER_ZHOME requires POWER_LOSS_ZHOME_POS for a Cartesian that homes to ZMIN."
#endif
@@ -3172,21 +3197,11 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
#endif
/**
* Touch Buttons
* Touch Screen Calibration
*/
#if ENABLED(TOUCH_SCREEN) && DISABLED(TOUCH_SCREEN_CALIBRATION)
#ifndef TOUCH_CALIBRATION_X
#error "TOUCH_CALIBRATION_X must be defined with TOUCH_SCREEN."
#endif
#ifndef TOUCH_CALIBRATION_Y
#error "TOUCH_CALIBRATION_Y must be defined with TOUCH_SCREEN."
#endif
#ifndef TOUCH_OFFSET_X
#error "TOUCH_OFFSET_X must be defined with TOUCH_SCREEN."
#endif
#ifndef TOUCH_OFFSET_Y
#error "TOUCH_OFFSET_Y must be defined with TOUCH_SCREEN."
#endif
#if ENABLED(TFT_TOUCH_DEVICE_XPT2046) && DISABLED(TOUCH_SCREEN_CALIBRATION) \
&& (!defined(TOUCH_CALIBRATION_X) || !defined(TOUCH_CALIBRATION_Y) || !defined(TOUCH_OFFSET_X) || !defined(TOUCH_OFFSET_Y))
#error "TOUCH_CALIBRATION_[XY] and TOUCH_OFFSET_[XY] are required for resistive touch screens with TOUCH_SCREEN_CALIBRATION disabled."
#endif
/**
@@ -3292,3 +3307,7 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
// Misc. Cleanup
#undef _TEST_PWM
#if ENABLED(FREEZE_FEATURE) && !PIN_EXISTS(FREEZE)
#error "FREEZE_FEATURE requires a FREEZE_PIN to be defined."
#endif
+2 -2
View File
@@ -42,7 +42,7 @@
* version was tagged.
*/
#ifndef STRING_DISTRIBUTION_DATE
#define STRING_DISTRIBUTION_DATE "2021-05-06"
#define STRING_DISTRIBUTION_DATE "2021-05-16"
#endif
/**
@@ -52,7 +52,7 @@
* to alert users to major changes.
*/
#define MARLIN_HEX_VERSION 020008
#define MARLIN_HEX_VERSION 02000801
#ifndef REQUIRED_CONFIGURATION_H_VERSION
#define REQUIRED_CONFIGURATION_H_VERSION MARLIN_HEX_VERSION
#endif
+2 -2
View File
@@ -755,7 +755,7 @@ inline uint8_t draw_elapsed_or_remaining_time(uint8_t timepos, const bool blink)
char buffer[14];
#if ENABLED(SHOW_REMAINING_TIME)
const bool show_remain = TERN1(ROTATE_PROGRESS_DISPLAY, blink) && (printingIsActive() || marlin_state == MF_SD_COMPLETE);
const bool show_remain = TERN1(ROTATE_PROGRESS_DISPLAY, blink) && printingIsActive();
if (show_remain) {
#if ENABLED(USE_M73_REMAINING_TIME)
duration_t remaining = ui.get_remaining_time();
@@ -889,7 +889,7 @@ void MarlinUI::draw_status_screen() {
#else // !HAS_DUAL_MIXING
const bool show_e_total = TERN0(LCD_SHOW_E_TOTAL, printingIsActive() || marlin_state == MF_SD_COMPLETE);
const bool show_e_total = TERN0(LCD_SHOW_E_TOTAL, printingIsActive());
if (show_e_total) {
#if ENABLED(LCD_SHOW_E_TOTAL)
+267 -7
View File
@@ -25,16 +25,21 @@
// lcd/dogm/status/hotend.h - Status Screen Hotends bitmaps
//
#define STATUS_HOTEND1_WIDTH 16
#define MAX_HOTEND_BITMAPS 5
#if HOTENDS > MAX_HOTEND_BITMAPS
#define STATUS_HOTEND_BITMAPS MAX_HOTEND_BITMAPS
#if HAS_MMU
#define STATUS_HOTEND_BITMAPS EXTRUDERS
#define MAX_HOTEND_BITMAPS 8
#else
#define STATUS_HOTEND_BITMAPS HOTENDS
#define MAX_HOTEND_BITMAPS 5
#endif
#if STATUS_HOTEND_BITMAPS > MAX_HOTEND_BITMAPS
#undef STATUS_HOTEND_BITMAPS
#define STATUS_HOTEND_BITMAPS MAX_HOTEND_BITMAPS
#endif
#if HOTENDS == 1 || ENABLED(STATUS_HOTEND_NUMBERLESS)
#define STATUS_HOTEND1_WIDTH 16
#if STATUS_HOTEND_BITMAPS == 1 || ENABLED(STATUS_HOTEND_NUMBERLESS)
const unsigned char status_hotend_a_bmp[] PROGMEM = {
B00011111,B11100000,
@@ -70,7 +75,7 @@
#endif
#elif HOTENDS >= 2
#elif STATUS_HOTEND_BITMAPS > 1
#ifdef STATUS_HOTEND_ANIM
@@ -483,4 +488,259 @@
#endif
#if STATUS_HOTEND_BITMAPS >= 6
#ifdef STATUS_HOTEND_ANIM
const unsigned char status_hotend6_a_bmp[] PROGMEM = {
B00011111,B11100000,
B00111111,B11110000,
#if LCD_FIRST_TOOL == 0
B00111000,B01110000,
B00111011,B11110000,
B00011000,B11100000,
B00011111,B01100000,
B00111111,B01110000,
B00111011,B01110000,
B00111100,B11110000,
#else
B00111100,B01110000,
B00111011,B11110000,
B00011011,B11100000,
B00011000,B11100000,
B00111011,B01110000,
B00111011,B01110000,
B00111100,B11110000,
#endif
B00001111,B11000000,
B00000111,B10000000,
B00000011,B00000000
};
const unsigned char status_hotend6_b_bmp[] PROGMEM = {
B00011111,B11100000,
B00100000,B00010000,
#if LCD_FIRST_TOOL == 0
B00100111,B10010000,
B00100100,B00010000,
B00010111,B00100000,
B00010000,B10100000,
B00100000,B10010000,
B00100100,B10010000,
B00110011,B00110000,
#else
B00100011,B10010000,
B00100100,B00010000,
B00010100,B00100000,
B00010111,B00100000,
B00100100,B10010000,
B00100100,B10010000,
B00110011,B00110000,
#endif
B00001000,B01000000,
B00000100,B10000000,
B00000011,B00000000
};
#else
const unsigned char status_hotend6_a_bmp[] PROGMEM = {
B00011111,B11100000,
#if LCD_FIRST_TOOL == 0
B00111000,B01110000,
B00111011,B11110000,
B00111000,B11110000,
B00011111,B01100000,
B00011111,B01100000,
B00111011,B01110000,
B00111100,B11110000,
#else
B00111100,B01110000,
B00111011,B11110000,
B00111011,B11110000,
B00011000,B11100000,
B00011011,B01100000,
B00111011,B01110000,
B00111100,B11110000,
#endif
B00111111,B11110000,
B00001111,B11000000,
B00000111,B10000000,
B00000011,B00000000
};
#endif
#endif
#if STATUS_HOTEND_BITMAPS >= 7
#ifdef STATUS_HOTEND_ANIM
const unsigned char status_hotend7_a_bmp[] PROGMEM = {
B00011111,B11100000,
B00111111,B11110000,
#if LCD_FIRST_TOOL == 0
B00111100,B01110000,
B00111011,B11110000,
B00011011,B11100000,
B00011000,B11100000,
B00111011,B01110000,
B00111011,B01110000,
B00111100,B11110000,
#else
B00111000,B01110000,
B00111011,B01110000,
B00011111,B01100000,
B00011110,B11100000,
B00111110,B11110000,
B00111101,B11110000,
B00111101,B11110000,
#endif
B00001111,B11000000,
B00000111,B10000000,
B00000011,B00000000
};
const unsigned char status_hotend7_b_bmp[] PROGMEM = {
B00011111,B11100000,
B00100000,B00010000,
#if LCD_FIRST_TOOL == 0
B00100011,B10010000,
B00100100,B00010000,
B00010100,B00100000,
B00010111,B00100000,
B00100100,B10010000,
B00100100,B10010000,
B00110011,B00110000,
#else
B00100111,B10010000,
B00100100,B10010000,
B00010000,B10100000,
B00010001,B00100000,
B00100001,B00010000,
B00100010,B00010000,
B00110010,B00110000,
#endif
B00001000,B01000000,
B00000100,B10000000,
B00000011,B00000000
};
#else
const unsigned char status_hotend7_a_bmp[] PROGMEM = {
B00011111,B11100000,
#if LCD_FIRST_TOOL == 0
B00111100,B01110000,
B00111011,B11110000,
B00111011,B11110000,
B00011000,B11100000,
B00011011,B01100000,
B00111011,B01110000,
B00111100,B11110000,
#else
B00111000,B01110000,
B00111011,B01110000,
B00111111,B01110000,
B00011110,B11100000,
B00011110,B11100000,
B00111101,B11110000,
B00111101,B11110000,
#endif
B00111111,B11110000,
B00001111,B11000000,
B00000111,B10000000,
B00000011,B00000000
};
#endif
#endif
#if STATUS_HOTEND_BITMAPS >= 8
#ifdef STATUS_HOTEND_ANIM
const unsigned char status_hotend8_a_bmp[] PROGMEM = {
B00011111,B11100000,
B00111111,B11110000,
#if LCD_FIRST_TOOL == 0
B00111000,B01110000,
B00111011,B01110000,
B00011111,B01100000,
B00011110,B11100000,
B00111110,B11110000,
B00111101,B11110000,
B00111101,B11110000,
#else
B00111100,B11110000,
B00111011,B01110000,
B00011011,B01100000,
B00011100,B11100000,
B00111011,B01110000,
B00111011,B01110000,
B00111100,B11110000,
#endif
B00001111,B11000000,
B00000111,B10000000,
B00000011,B00000000
};
const unsigned char status_hotend8_b_bmp[] PROGMEM = {
B00011111,B11100000,
B00100000,B00010000,
#if LCD_FIRST_TOOL == 0
B00100111,B10010000,
B00100100,B10010000,
B00010000,B10100000,
B00010001,B00100000,
B00100001,B00010000,
B00100010,B00010000,
B00110010,B00110000,
#else
B00100011,B00010000,
B00100100,B10010000,
B00010100,B10100000,
B00010011,B00100000,
B00100100,B10010000,
B00100100,B10010000,
B00110011,B00110000,
#endif
B00001000,B01000000,
B00000100,B10000000,
B00000011,B00000000
};
#else
const unsigned char status_hotend8_a_bmp[] PROGMEM = {
B00011111,B11100000,
#if LCD_FIRST_TOOL == 0
B00111000,B01110000,
B00111011,B01110000,
B00111111,B01110000,
B00011110,B11100000,
B00011110,B11100000,
B00111101,B11110000,
B00111101,B11110000,
#else
B00111100,B11110000,
B00111011,B01110000,
B00111011,B01110000,
B00011100,B11100000,
B00011011,B01100000,
B00111011,B01110000,
B00111100,B11110000,
#endif
B00111111,B11110000,
B00001111,B11000000,
B00000111,B10000000,
B00000011,B00000000
};
#endif
#endif
#endif
+9 -7
View File
@@ -41,7 +41,7 @@
#include "../../gcode/parser.h" // for units (and volumetric)
#if ENABLED(LCD_SHOW_E_TOTAL)
#include "../../MarlinCore.h" // for printingIsActive(), marlin_state and MF_SD_COMPLETE
#include "../../MarlinCore.h" // for printingIsActive()
#endif
#if ENABLED(FILAMENT_LCD_DISPLAY)
@@ -243,9 +243,11 @@ FORCE_INLINE void _draw_centered_temp(const celsius_t temp, const uint8_t tx, co
#endif
#if STATUS_HOTEND_BITMAPS > 1
static const unsigned char* const status_hotend_gfx[STATUS_HOTEND_BITMAPS] PROGMEM = ARRAY_N(STATUS_HOTEND_BITMAPS, OFF_BMP(1), OFF_BMP(2), OFF_BMP(3), OFF_BMP(4), OFF_BMP(5), OFF_BMP(6));
#define _OFF_BMP(N) OFF_BMP(N),
#define _ON_BMP(N) ON_BMP(N),
static const unsigned char* const status_hotend_gfx[STATUS_HOTEND_BITMAPS] PROGMEM = { REPEAT_1(STATUS_HOTEND_BITMAPS, _OFF_BMP) };
#if ANIM_HOTEND
static const unsigned char* const status_hotend_on_gfx[STATUS_HOTEND_BITMAPS] PROGMEM = ARRAY_N(STATUS_HOTEND_BITMAPS, ON_BMP(1), ON_BMP(2), ON_BMP(3), ON_BMP(4), ON_BMP(5), ON_BMP(6));
static const unsigned char* const status_hotend_on_gfx[STATUS_HOTEND_BITMAPS] PROGMEM = { REPEAT_1(STATUS_HOTEND_BITMAPS, _ON_BMP) };
#define HOTEND_BITMAP(N,S) (unsigned char*)pgm_read_ptr((S) ? &status_hotend_on_gfx[(N) % (STATUS_HOTEND_BITMAPS)] : &status_hotend_gfx[(N) % (STATUS_HOTEND_BITMAPS)])
#else
#define HOTEND_BITMAP(N,S) (unsigned char*)pgm_read_ptr(&status_hotend_gfx[(N) % (STATUS_HOTEND_BITMAPS)])
@@ -272,12 +274,12 @@ FORCE_INLINE void _draw_centered_temp(const celsius_t temp, const uint8_t tx, co
#if ENABLED(STATUS_HEAT_PERCENT)
if (isHeat && tall <= BAR_TALL) {
const uint8_t ph = STATUS_HEATERS_HEIGHT - 1 - tall;
u8g.drawBitmapP(hx, STATUS_HEATERS_Y, bw, ph, HOTEND_BITMAP(heater_id, false));
u8g.drawBitmapP(hx, STATUS_HEATERS_Y + ph, bw, tall + 1, HOTEND_BITMAP(heater_id, true) + ph * bw);
u8g.drawBitmapP(hx, STATUS_HEATERS_Y, bw, ph, HOTEND_BITMAP(TERN(HAS_MMU, active_extruder, heater_id), false));
u8g.drawBitmapP(hx, STATUS_HEATERS_Y + ph, bw, tall + 1, HOTEND_BITMAP(TERN(HAS_MMU, active_extruder, heater_id), true) + ph * bw);
}
else
#endif
u8g.drawBitmapP(hx, STATUS_HEATERS_Y, bw, STATUS_HEATERS_HEIGHT, HOTEND_BITMAP(heater_id, isHeat));
u8g.drawBitmapP(hx, STATUS_HEATERS_Y, bw, STATUS_HEATERS_HEIGHT, HOTEND_BITMAP(TERN(HAS_MMU, active_extruder, heater_id), isHeat));
#endif
} // PAGE_CONTAINS
@@ -462,7 +464,7 @@ void MarlinUI::draw_status_screen() {
#endif
#endif
const bool show_e_total = TERN0(LCD_SHOW_E_TOTAL, printingIsActive() || marlin_state == MF_SD_COMPLETE);
const bool show_e_total = TERN0(LCD_SHOW_E_TOTAL, printingIsActive());
// At the first page, generate new display values
if (first_page) {
+21 -19
View File
@@ -815,8 +815,6 @@ void Draw_Control_Menu() {
if (CVISI(CONTROL_CASE_ADVSET)) {
DWIN_Draw_Label(CLINE(CONTROL_CASE_ADVSET), GET_TEXT_F(MSG_ADVANCED_SETTINGS)); // Advanced Settings
Draw_More_Icon(CSCROL(CONTROL_CASE_ADVSET));
Draw_Menu_Line(CSCROL(CONTROL_CASE_ADVSET), ICON_AdvSet);
}
if (CVISI(CONTROL_CASE_INFO)) Item_Control_Info(CLINE(CONTROL_CASE_INFO));
@@ -825,23 +823,26 @@ void Draw_Control_Menu() {
Draw_Menu_Cursor(CSCROL(select_control.now));
// Draw icons and lines
uint8_t i = 0;
#define _TEMP_ICON(N) do{ ++i; if (CVISI(i)) Draw_Menu_Line(CSCROL(i), ICON_Temperature + (N) - 1); }while(0)
#define _TEMP_ICON(N, I, M) do { \
if (CVISI(N)) { \
Draw_Menu_Line(CSCROL(N), I); \
if (M) { \
Draw_More_Icon(CSCROL(N)); \
} \
} \
} while(0)
_TEMP_ICON(CONTROL_CASE_TEMP);
if (CVISI(i)) Draw_More_Icon(CSCROL(i));
_TEMP_ICON(CONTROL_CASE_MOVE);
Draw_More_Icon(CSCROL(i));
_TEMP_ICON(CONTROL_CASE_TEMP, ICON_Temperature, true);
_TEMP_ICON(CONTROL_CASE_MOVE, ICON_Motion, true);
#if ENABLED(EEPROM_SETTINGS)
_TEMP_ICON(CONTROL_CASE_SAVE);
_TEMP_ICON(CONTROL_CASE_LOAD);
_TEMP_ICON(CONTROL_CASE_RESET);
_TEMP_ICON(CONTROL_CASE_SAVE, ICON_WriteEEPROM, false);
_TEMP_ICON(CONTROL_CASE_LOAD, ICON_ReadEEPROM, false);
_TEMP_ICON(CONTROL_CASE_RESET, ICON_ResumeEEPROM, false);
#endif
_TEMP_ICON(CONTROL_CASE_INFO);
if (CVISI(CONTROL_CASE_INFO)) Draw_More_Icon(CSCROL(i));
_TEMP_ICON(CONTROL_CASE_ADVSET, ICON_AdvSet, true);
_TEMP_ICON(CONTROL_CASE_INFO, ICON_Info, true);
}
void Draw_Tune_Menu() {
@@ -1890,7 +1891,7 @@ void HMI_SDCardUpdate() {
else if (checkkey == PrintProcess || checkkey == Tune || printingIsActive()) {
// TODO: Move card removed abort handling
// to CardReader::manage_media.
card.flag.abort_sd_printing = true;
card.abortFilePrintSoon();
wait_for_heatup = wait_for_user = false;
dwin_abort_flag = true; // Reset feedrate, return to Home
}
@@ -2310,7 +2311,7 @@ void HMI_PauseOrStop() {
checkkey = Back_Main;
if (HMI_flag.home_flag) planner.synchronize(); // Wait for planner moves to finish!
wait_for_heatup = wait_for_user = false; // Stop waiting for heating/user
card.flag.abort_sd_printing = true; // Let the main loop handle SD abort
card.abortFilePrintSoon(); // Let the main loop handle SD abort
dwin_abort_flag = true; // Reset feedrate, return to Home
#ifdef ACTION_ON_CANCEL
host_action_cancel();
@@ -2653,11 +2654,12 @@ void HMI_Control() {
Scroll_Menu(DWIN_SCROLL_UP);
switch (index_control) { // Last menu items
case CONTROL_CASE_ADVSET: // Advance Settings >
case CONTROL_CASE_ADVSET: // Advanced Settings >
Draw_Menu_Item(MROWS, ICON_AdvSet, GET_TEXT(MSG_ADVANCED_SETTINGS), true);
break;
case CONTROL_CASE_INFO: // Info >
Draw_Menu_Item(MROWS, ICON_Info, GET_TEXT(MSG_INFO_SCREEN), true);
Item_Control_Info(MBASE(MROWS));
Draw_Menu_Icon(MROWS, ICON_Info);
break;
default: break;
}
@@ -2721,7 +2723,7 @@ void HMI_Control() {
HMI_AudioFeedback();
break;
#endif
case CONTROL_CASE_ADVSET: // Advance Settings
case CONTROL_CASE_ADVSET: // Advanced Settings
checkkey = AdvSet;
select_advset.reset();
Draw_AdvSet_Menu();
@@ -39,6 +39,10 @@
#include "../../../../module/stepper/trinamic.h"
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
#include "../../../../../feature/powerloss.h"
#endif
#if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
uint16_t distanceToMove = 10;
#endif
@@ -78,8 +82,13 @@ constexpr feedRate_t park_speed_xy = TERN(NOZZLE_PARK_FEATURE, NOZZLE_PARK_XY_FE
void MKS_pause_print_move() {
queue.exhaust();
position_before_pause = current_position;
// Save the current position, the raise amount, and 'already raised'
TERN_(POWER_LOSS_RECOVERY, if (recovery.enabled) recovery.save(true, mks_park_pos.z, true));
destination.z = _MIN(current_position.z + mks_park_pos.z, Z_MAX_POS);
prepare_internal_move_to_destination(park_speed_z);
destination.set(X_MIN_POS + mks_park_pos.x, Y_MIN_POS + mks_park_pos.y);
prepare_internal_move_to_destination(park_speed_xy);
}
@@ -89,6 +98,7 @@ void MKS_resume_print_move() {
prepare_internal_move_to_destination(park_speed_xy);
destination.z = position_before_pause.z;
prepare_internal_move_to_destination(park_speed_z);
TERN_(POWER_LOSS_RECOVERY, if (recovery.enabled) recovery.save(true));
}
float z_offset_add = 0;
@@ -289,7 +289,7 @@ void DGUSScreenHandler::ScreenChangeHook(DGUS_VP_Variable &var, void *val_ptr) {
// if robin nano is printing. when it is, dgus will enter the printing
// page to continue print;
//
//if (print_job_timer.isRunning() || print_job_timer.isPaused()) {
//if (printJobOngoing() || printingIsPaused()) {
// if (target == MKSLCD_PAUSE_SETTING_MOVE || target == MKSLCD_PAUSE_SETTING_EX
// || target == MKSLCD_SCREEN_PRINT || target == MKSLCD_SCREEN_PAUSE
// ) {
@@ -324,7 +324,7 @@ void DGUSScreenHandler::ScreenBackChange(DGUS_VP_Variable &var, void *val_ptr) {
void DGUSScreenHandler::ZoffsetConfirm(DGUS_VP_Variable &var, void *val_ptr) {
settings.save();
if (print_job_timer.isRunning())
if (printJobOngoing())
GotoScreen(MKSLCD_SCREEN_PRINT);
else if (print_job_timer.isPaused)
GotoScreen(MKSLCD_SCREEN_PAUSE);
@@ -1442,8 +1442,7 @@ bool DGUSScreenHandler::loop() {
}
#if ENABLED(DGUS_MKS_RUNOUT_SENSOR)
if (booted && (IS_SD_PRINTING() || IS_SD_PAUSED()))
DGUS_Runout_Idle();
if (booted && printingIsActive()) DGUS_Runout_Idle();
#endif
#endif // SHOW_BOOTSCREEN
@@ -1477,7 +1476,7 @@ void DGUSScreenHandler::DGUS_ExtrudeLoadInit(void) {
void DGUSScreenHandler::DGUS_RunoutInit(void) {
#if PIN_EXISTS(MT_DET_1)
pinMode(MT_DET_1_PIN, INPUT_PULLUP);
SET_INPUT_PULLUP(MT_DET_1_PIN);
#endif
runout_mks.de_count = 0;
runout_mks.de_times = 10;
@@ -1496,7 +1495,7 @@ void DGUSScreenHandler::DGUS_Runout_Idle(void) {
GotoScreen(MKSLCD_SCREEN_PAUSE);
sendinfoscreen(PSTR("NOTICE"), nullptr, PSTR("Please change filament!"), nullptr, true, true, true, true);
// SetupConfirmAction(nullptr);
//SetupConfirmAction(nullptr);
GotoScreen(DGUSLCD_SCREEN_POPUP);
break;
+5 -5
View File
@@ -91,8 +91,8 @@ static void btn_ok_event_cb(lv_obj_t *btn, lv_event_t event) {
cur_name = strrchr(list_file.file_name[sel_id], '/');
SdFile file, *curDir;
card.endFilePrint();
const char * const fname = card.diveToFile(true, curDir, cur_name);
card.abortFilePrintNow();
const char * const fname = card.diveToFile(false, curDir, cur_name);
if (!fname) return;
if (file.open(curDir, fname, O_READ)) {
gCfgItems.curFilesize = file.fileSize();
@@ -108,7 +108,7 @@ static void btn_ok_event_cb(lv_obj_t *btn, lv_event_t event) {
planner.flow_percentage[1] = 100;
planner.e_factor[1] = planner.flow_percentage[1] * 0.01f;
#endif
card.startFileprint();
card.startOrResumeFilePrinting();
#if ENABLED(POWER_LOSS_RECOVERY)
recovery.prepare();
#endif
@@ -124,8 +124,8 @@ static void btn_ok_event_cb(lv_obj_t *btn, lv_event_t event) {
lv_draw_ready_print();
#if ENABLED(SDSUPPORT)
uiCfg.print_state = IDLE;
card.flag.abort_sd_printing = true;
uiCfg.print_state = IDLE;
card.abortFilePrintSoon();
#endif
}
else if (DIALOG_IS(TYPE_FINISH_PRINT)) {
+5 -9
View File
@@ -374,7 +374,7 @@ void tft_style_init() {
style_sel_text.body.grad_color = LV_COLOR_BACKGROUND;
style_sel_text.text.color = LV_COLOR_YELLOW;
style_sel_text.text.sel_color = LV_COLOR_YELLOW;
style_sel_text.text.font = &gb2312_puhui32;
style_sel_text.text.font = TERN(HAS_SPI_FLASH_FONT, &gb2312_puhui32, LV_FONT_DEFAULT);
style_sel_text.line.width = 0;
style_sel_text.text.letter_space = 0;
style_sel_text.text.line_space = -5;
@@ -638,21 +638,18 @@ char *creat_title_text() {
W25QXX.SPI_FLASH_BufferWrite(bmp_public_buf, BAK_VIEW_ADDR_TFT35 + row * 400, 400);
#endif
row++;
card.abortFilePrintNow();
if (row >= 200) {
size = 809;
row = 0;
gcode_preview_over = false;
card.closefile();
char *cur_name;
cur_name = strrchr(list_file.file_name[sel_id], '/');
char *cur_name = strrchr(list_file.file_name[sel_id], '/');
SdFile file;
SdFile *curDir;
card.endFilePrint();
const char * const fname = card.diveToFile(true, curDir, cur_name);
const char * const fname = card.diveToFile(false, curDir, cur_name);
if (!fname) return;
if (file.open(curDir, fname, O_READ)) {
gCfgItems.curFilesize = file.fileSize();
@@ -669,13 +666,12 @@ char *creat_title_text() {
planner.flow_percentage[1] = 100;
planner.e_factor[1] = planner.flow_percentage[1] * 0.01;
#endif
card.startFileprint();
card.startOrResumeFilePrinting();
TERN_(POWER_LOSS_RECOVERY, recovery.prepare());
once_flag = false;
}
return;
}
card.closefile();
#endif // SDSUPPORT
}
+13 -19
View File
@@ -505,7 +505,7 @@ int write_to_file(char *buf, int len) {
if (res == -1) {
upload_file.close();
const char * const fname = card.diveToFile(true, upload_curDir, saveFilePath);
const char * const fname = card.diveToFile(false, upload_curDir, saveFilePath);
if (upload_file.open(upload_curDir, fname, O_WRITE)) {
upload_file.setpos(&pos);
@@ -732,12 +732,10 @@ static void wifi_gcode_exec(uint8_t *cmd_line) {
if (!gcode_preview_over) {
char *cur_name = strrchr(list_file.file_name[sel_id], '/');
card.endFilePrint();
SdFile file;
SdFile *curDir;
card.endFilePrint();
const char * const fname = card.diveToFile(true, curDir, cur_name);
card.abortFilePrintNow();
const char * const fname = card.diveToFile(false, curDir, cur_name);
if (!fname) return;
if (file.open(curDir, fname, O_READ)) {
gCfgItems.curFilesize = file.fileSize();
@@ -754,7 +752,7 @@ static void wifi_gcode_exec(uint8_t *cmd_line) {
planner.flow_percentage[1] = 100;
planner.e_factor[1] = planner.flow_percentage[1] * 0.01f;
#endif
card.startFileprint();
card.startOrResumeFilePrinting();
TERN_(POWER_LOSS_RECOVERY, recovery.prepare());
once_flag = false;
}
@@ -814,7 +812,7 @@ static void wifi_gcode_exec(uint8_t *cmd_line) {
clear_cur_ui();
#if ENABLED(SDSUPPORT)
uiCfg.print_state = IDLE;
card.flag.abort_sd_printing = true;
card.abortFilePrintSoon();
#endif
lv_draw_ready_print();
@@ -1317,7 +1315,7 @@ static void file_first_msg_handle(uint8_t * msg, uint16_t msgLen) {
card.cdroot();
upload_file.close();
const char * const fname = card.diveToFile(true, upload_curDir, saveFilePath);
const char * const fname = card.diveToFile(false, upload_curDir, saveFilePath);
if (!upload_file.open(upload_curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) {
clear_cur_ui();
@@ -1370,7 +1368,7 @@ static void file_fragment_msg_handle(uint8_t * msg, uint16_t msgLen) {
int res = upload_file.write(public_buf, file_writer.write_index);
if (res == -1) {
upload_file.close();
const char * const fname = card.diveToFile(true, upload_curDir, saveFilePath);
const char * const fname = card.diveToFile(false, upload_curDir, saveFilePath);
if (upload_file.open(upload_curDir, fname, O_WRITE)) {
upload_file.setpos(&pos);
res = upload_file.write(public_buf, file_writer.write_index);
@@ -1378,7 +1376,7 @@ static void file_fragment_msg_handle(uint8_t * msg, uint16_t msgLen) {
}
upload_file.close();
SdFile file, *curDir;
const char * const fname = card.diveToFile(true, curDir, saveFilePath);
const char * const fname = card.diveToFile(false, curDir, saveFilePath);
if (file.open(curDir, fname, O_RDWR)) {
gCfgItems.curFilesize = file.fileSize();
file.close();
@@ -1744,7 +1742,7 @@ void mks_wifi_firmware_update() {
if (wifi_upload(0) >= 0) {
card.removeFile((char *)ESP_FIRMWARE_FILE_RENAME);
SdFile file, *curDir;
const char * const fname = card.diveToFile(true, curDir, ESP_FIRMWARE_FILE);
const char * const fname = card.diveToFile(false, curDir, ESP_FIRMWARE_FILE);
if (file.open(curDir, fname, O_READ)) {
file.rename(curDir, (char *)ESP_FIRMWARE_FILE_RENAME);
file.close();
@@ -1789,18 +1787,14 @@ void get_wifi_commands() {
char* command = wifi_line_buffer;
while (*command == ' ') command++; // skip any leading spaces
// Movement commands alert when stopped
if (IsStopped()) {
// Movement commands alert when stopped
if (IsStopped()) {
char* gpos = strchr(command, 'G');
if (gpos) {
switch (strtol(gpos + 1, nullptr, 10)) {
case 0 ... 1:
#if ENABLED(ARC_SUPPORT)
case 2 ... 3:
#endif
#if ENABLED(BEZIER_CURVE_SUPPORT)
case 5:
#endif
TERN_(ARC_SUPPORT, case 2 ... 3:)
TERN_(BEZIER_CURVE_SUPPORT, case 5:)
SERIAL_ECHOLNPGM(STR_ERR_STOPPED);
LCD_MESSAGEPGM(MSG_STOPPED);
break;
+1 -1
View File
@@ -625,7 +625,7 @@ void upload_spin() {
// Try to upload the given file at the given address
void SendUpdateFile(const char *file, uint32_t address) {
const char * const fname = card.diveToFile(true, update_curDir, ESP_FIRMWARE_FILE);
const char * const fname = card.diveToFile(false, update_curDir, ESP_FIRMWARE_FILE);
if (!update_file.open(update_curDir, fname, O_READ)) return;
esp_upload.fileSize = update_file.fileSize();
@@ -26,12 +26,12 @@
* Nextion TFT support for Marlin
*/
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(NEXTION_TFT)
#include "ui_api.h"
#include "lib/nextion/nextion_tft.h"
#include "../ui_api.h"
#include "nextion_tft.h"
namespace ExtUI {
+5 -5
View File
@@ -645,6 +645,9 @@ void NextionTFT::UpdateOnChange() {
last_flow_speed = getFlow_percent(getActiveTool());
}
// tmppage Axis
static float last_get_axis_position_mmX = 999, last_get_axis_position_mmY = 999, last_get_axis_position_mmZ = 999;
// tmppage Progress + Layer + Time
if (isPrinting()) {
@@ -679,9 +682,6 @@ void NextionTFT::UpdateOnChange() {
}
}
// tmppage Axis
static float last_get_axis_position_mmX = 999, last_get_axis_position_mmY = 999, last_get_axis_position_mmZ = 999;
if (!WITHIN(last_get_axis_position_mmX - getAxisPosition_mm(X), -0.1, 0.1)) {
if (ELAPSED(ms, next_event_ms)) {
next_event_ms = ms + 30;
@@ -723,9 +723,9 @@ void NextionTFT::UpdateOnChange() {
last_homedZ = isAxisPositionKnown(Z);
}
// tmppage IDEX Mode
static uint8_t last_IDEX_Mode = 99;
#if ENABLED(DUAL_X_CARRIAGE)
// tmppage IDEX Mode
static uint8_t last_IDEX_Mode = 99;
if (last_IDEX_Mode != getIDEX_Mode()) {
SEND_VAL("tmppage.idexmode", getIDEX_Mode());
last_IDEX_Mode = getIDEX_Mode();
+5 -17
View File
@@ -54,6 +54,7 @@
#include "../../module/printcounter.h"
#include "../../libs/duration_t.h"
#include "../../HAL/shared/Delay.h"
#include "../../MarlinCore.h"
#include "../../sd/cardreader.h"
#if ENABLED(PRINTCOUNTER)
@@ -106,9 +107,6 @@ namespace ExtUI {
#if ENABLED(JOYSTICK)
uint8_t jogging : 1;
#endif
#if ENABLED(SDSUPPORT)
uint8_t was_sd_printing : 1;
#endif
} flags;
#ifdef __SAM3X8E__
@@ -1017,27 +1015,17 @@ namespace ExtUI {
void setUserConfirmed() { TERN_(HAS_RESUME_CONTINUE, wait_for_user = false); }
void printFile(const char *filename) {
UNUSED(filename);
TERN_(SDSUPPORT, card.openAndPrintFile(filename));
TERN(SDSUPPORT, card.openAndPrintFile(filename), UNUSED(filename));
}
bool isPrintingFromMediaPaused() {
return TERN0(SDSUPPORT, isPrintingFromMedia() && !IS_SD_PRINTING());
return TERN0(SDSUPPORT, isPrintingFromMedia() && printingIsPaused());
}
bool isPrintingFromMedia() {
#if ENABLED(SDSUPPORT)
// Account for when IS_SD_PRINTING() reports the end of the
// print when there is still SD card data in the planner.
flags.was_sd_printing = card.isFileOpen() || (flags.was_sd_printing && commandsInQueue());
return flags.was_sd_printing;
#else
return false;
#endif
}
bool isPrintingFromMedia() { return IS_SD_PRINTING(); }
bool isPrinting() {
return (commandsInQueue() || isPrintingFromMedia() || TERN0(SDSUPPORT, IS_SD_PRINTING())) || print_job_timer.isRunning() || print_job_timer.isPaused();
return commandsInQueue() || isPrintingFromMedia() || printJobOngoing() || printingIsPaused();
}
bool isPrintingPaused() {
+3 -3
View File
@@ -114,8 +114,8 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;
PGM_P MarlinUI::get_preheat_label(const uint8_t m) {
#define _PDEF(N) static PGMSTR(preheat_##N##_label, PREHEAT_##N##_LABEL);
#define _PLBL(N) preheat_##N##_label,
REPEAT_S(1, INCREMENT(PREHEAT_COUNT), _PDEF);
static PGM_P const preheat_labels[PREHEAT_COUNT] PROGMEM = { REPEAT_S(1, INCREMENT(PREHEAT_COUNT), _PLBL) };
REPEAT_1(PREHEAT_COUNT, _PDEF);
static PGM_P const preheat_labels[PREHEAT_COUNT] PROGMEM = { REPEAT_1(PREHEAT_COUNT, _PLBL) };
return (PGM_P)pgm_read_ptr(&preheat_labels[m]);
}
#endif
@@ -1487,7 +1487,7 @@ void MarlinUI::update() {
void MarlinUI::abort_print() {
#if ENABLED(SDSUPPORT)
wait_for_heatup = wait_for_user = false;
card.flag.abort_sd_printing = true;
card.abortFilePrintSoon();
#endif
#ifdef ACTION_ON_CANCEL
host_action_cancel();
+15 -10
View File
@@ -257,18 +257,23 @@ void Touch::hold(touch_control_t *control, millis_t delay) {
}
bool Touch::get_point(int16_t *x, int16_t *y) {
#if ENABLED(TOUCH_SCREEN_CALIBRATION)
bool is_touched = (touch_calibration.calibration.orientation == TOUCH_PORTRAIT ? io.getRawPoint(y, x) : io.getRawPoint(x, y));
#if ENABLED(TFT_TOUCH_DEVICE_XPT2046)
#if ENABLED(TOUCH_SCREEN_CALIBRATION)
bool is_touched = (touch_calibration.calibration.orientation == TOUCH_PORTRAIT ? io.getRawPoint(y, x) : io.getRawPoint(x, y));
if (is_touched && touch_calibration.calibration.orientation != TOUCH_ORIENTATION_NONE) {
*x = int16_t((int32_t(*x) * touch_calibration.calibration.x) >> 16) + touch_calibration.calibration.offset_x;
*y = int16_t((int32_t(*y) * touch_calibration.calibration.y) >> 16) + touch_calibration.calibration.offset_y;
}
#else
bool is_touched = (TOUCH_ORIENTATION == TOUCH_PORTRAIT ? io.getRawPoint(y, x) : io.getRawPoint(x, y));
*x = uint16_t((uint32_t(*x) * TOUCH_CALIBRATION_X) >> 16) + TOUCH_OFFSET_X;
*y = uint16_t((uint32_t(*y) * TOUCH_CALIBRATION_Y) >> 16) + TOUCH_OFFSET_Y;
if (is_touched && touch_calibration.calibration.orientation != TOUCH_ORIENTATION_NONE) {
*x = int16_t((int32_t(*x) * touch_calibration.calibration.x) >> 16) + touch_calibration.calibration.offset_x;
*y = int16_t((int32_t(*y) * touch_calibration.calibration.y) >> 16) + touch_calibration.calibration.offset_y;
}
#else
bool is_touched = (TOUCH_ORIENTATION == TOUCH_PORTRAIT ? io.getRawPoint(y, x) : io.getRawPoint(x, y));
*x = uint16_t((uint32_t(*x) * TOUCH_CALIBRATION_X) >> 16) + TOUCH_OFFSET_X;
*y = uint16_t((uint32_t(*y) * TOUCH_CALIBRATION_Y) >> 16) + TOUCH_OFFSET_Y;
#endif
#elif ENABLED(TFT_TOUCH_DEVICE_GT911)
bool is_touched = (TOUCH_ORIENTATION == TOUCH_PORTRAIT ? io.getPoint(y, x) : io.getPoint(x, y));
#endif
return is_touched;
}
Touch touch;

Some files were not shown because too many files have changed in this diff Show More