Compare commits

..

47 Commits

Author SHA1 Message Date
InsanityAutomation 4894f35e39 Merge branch 'Trex_2.0.x_Devel' of https://github.com/InsanityAutomation/Marlin into Trex_2.0.x_Devel 2024-06-26 10:53:20 -04:00
InsanityAutomation 11ae89e290 Bump to current 2024-04-15 14:16:11 -04:00
InsanityAutomation 0e1b62e094 Reduce ram and SPI speed 2022-10-23 12:35:46 -04:00
InsanityAutomation 64ffa0d4f4 Merge branch 'bugfix-2.1.x' into Trex_2.0.x_Devel 2022-10-21 15:29:10 -04:00
InsanityAutomation e6680ddfdf Update menu_advanced.cpp 2022-10-11 11:37:22 -04:00
InsanityAutomation 5c0696b51a updates 2022-10-11 11:36:31 -04:00
InsanityAutomation d438436f0c Merge branch 'bugfix-2.1.x' into Trex_2.0.x_Devel 2022-10-10 16:36:53 -04:00
InsanityAutomation 2f322e8084 Update Configuration.h 2022-04-09 11:22:20 -04:00
InsanityAutomation a3a4da5ff2 Merge branch 'Implement-M591-Configurable-Runout-Sensors' into Trex_2.0.x_Devel 2022-04-05 10:41:19 -04:00
InsanityAutomation bba892e327 Trim output on slim menus 2022-04-03 17:03:52 -04:00
InsanityAutomation 25172b3acf M591Fixes 2022-04-03 14:54:16 -04:00
InsanityAutomation 3226adf2a6 Update Configuration.h 2022-03-08 17:54:24 -05:00
InsanityAutomation 29822ee60e Update Configuration_adv.h 2022-03-08 17:54:22 -05:00
InsanityAutomation 442d28485e Merge branch 'bugfix-2.0.x' into Trex_2.0.x_Devel 2022-03-08 17:32:43 -05:00
InsanityAutomation 29f85afe50 Update settings.cpp 2021-10-14 18:48:59 -04:00
InsanityAutomation c653a0f423 Merge branch 'BLTouch-HS-Mode-EEPROM' into Trex_2.0.x_Devel 2021-10-14 18:33:57 -04:00
InsanityAutomation 9a9a112673 Simplify macro 2021-10-11 22:07:45 -04:00
Scott Lahteine 0977129353 Update planner.cpp 2021-10-11 19:31:52 -04:00
InsanityAutomation ffa8e0ce60 potentially fix multi nozzle duplication as well 2021-10-11 19:31:42 -04:00
InsanityAutomation cbaf1af0fe Followup to IDEX fix 2021-10-10 19:51:56 -04:00
InsanityAutomation b8dfc53693 Return on mode change without deploying 2021-10-09 14:07:02 -04:00
InsanityAutomation a30ae0aeca BLTouch High Speed EEPROM Control 2021-10-09 13:58:45 -04:00
InsanityAutomation 32e8f90271 Fix Delay definitions 2021-10-09 11:58:54 -04:00
InsanityAutomation 8b10b829fd Fix IDEX Mode Positioning 2021-10-09 11:58:45 -04:00
InsanityAutomation eab8ad6b16 Merge branch 'bugfix-2.0.x' into Trex_2.0.x_Devel 2021-10-09 10:58:30 -04:00
InsanityAutomation 35180fedd8 Merge branch 'bugfix-2.0.x' into Trex_2.0.x_Devel 2021-08-28 14:06:37 -04:00
InsanityAutomation 4ddd6d27c1 trim ram 2021-08-08 14:29:24 -04:00
InsanityAutomation 5b6317dd5b Update Configuration_adv.h 2021-08-06 20:11:23 -04:00
InsanityAutomation 125e537dd1 Update Configuration.h 2021-08-06 13:10:05 -04:00
InsanityAutomation 1055cd4efa Merge branch 'bugfix-2.0.x' into Trex_2.0.x_Devel 2021-08-05 22:19:49 -04:00
InsanityAutomation 9b6037515f Update Configuration.h 2021-07-31 14:47:58 -04:00
InsanityAutomation 6bdc99be5f Merge branch 'bugfix-2.0.x' into Trex_2.0.x_Devel 2021-07-31 14:38:43 -04:00
InsanityAutomation d6abfd2523 Fix move directly after G28X 2021-01-01 18:50:47 -05:00
InsanityAutomation 4f0615be7b Merge branch 'bugfix-2.0.x' into Trex_2.0.x_Devel 2021-01-01 18:50:31 -05:00
InsanityAutomation dd345679d3 Add display timings for new supplier 2020-11-21 15:16:47 -05:00
InsanityAutomation b59301894a Merge branch 'bugfix-2.0.x' into Trex_2.0.x_Devel 2020-11-21 15:09:26 -05:00
InsanityAutomation 3165043527 Merge branch 'bugfix-2.0.x' of https://github.com/MarlinFirmware/Marlin into bugfix-2.0.x 2020-11-21 14:33:24 -05:00
Luu Lac cd3bf4c766 Fix "autotune" LCD message (#20127) 2020-11-13 18:48:59 -06:00
Scott Lahteine 30162df320 Optimize M360 2020-11-13 18:47:34 -06:00
InsanityAutomation 2d160b8461 force set directions on all blocks in stepper isr 2020-10-22 09:20:37 -04:00
InsanityAutomation aa5a7f5c13 Add SKR12Pro Support 2020-10-22 09:19:44 -04:00
InsanityAutomation e4e9915d84 Update Configuration_adv.h 2020-10-22 09:18:30 -04:00
InsanityAutomation 8fe3650376 Bump to head, fix compile errors 2020-10-22 09:18:30 -04:00
InsanityAutomation 23d024309e Update runout.cpp 2020-10-22 09:18:30 -04:00
InsanityAutomation 62465cdf23 Disable mesh validation pattern for UBL builds to fit 2020-10-22 09:18:00 -04:00
InsanityAutomation 9eb4fc1cfd Update Configuration_adv.h 2020-10-22 09:18:00 -04:00
InsanityAutomation 40de56b58b Bump to head, fix compile errors 2020-10-22 09:18:00 -04:00
259 changed files with 6698 additions and 25651 deletions
-73
View File
@@ -1,73 +0,0 @@
#
# ci-unit-tests.yml
# Build and execute unit tests to catch functional issues in code
#
name: CI - Unit Tests
on:
pull_request:
branches:
- bugfix-2.1.x
# Cannot be enabled on 2.1.x until it contains the unit test framework
#- 2.1.x
paths-ignore:
- config/**
- data/**
- docs/**
- '**/*.md'
push:
branches:
- bugfix-2.1.x
# Cannot be enabled on 2.1.x until it contains the unit test framework
#- 2.1.x
paths-ignore:
- config/**
- data/**
- docs/**
- '**/*.md'
jobs:
# This runs all unit tests as a single job. While it should be possible to break this up into
# multiple jobs, they currently run quickly and finish long before the compilation tests.
run_unit_tests:
name: Unit Test
# These tests will only be able to run on the bugfix-2.1.x branch, until the next release
# pulls them into additional branches.
if: github.repository == 'MarlinFirmware/Marlin'
runs-on: ubuntu-latest
steps:
- name: Check out the PR
uses: actions/checkout@v4
- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache PlatformIO
uses: actions/cache@v4
with:
path: ~/.platformio
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
- name: Select Python 3.9
uses: actions/setup-python@v5
with:
python-version: '3.9'
architecture: 'x64'
- name: Install PlatformIO
run: |
pip install -U platformio
pio upgrade --dev
pio pkg update --global
- name: Run All Unit Tests
run: |
make unit-test-all-local
@@ -1,9 +1,9 @@
#
# ci-build-tests.yml
# test-builds.yml
# Do test builds to catch compile errors
#
name: CI - Build Tests
name: CI
on:
pull_request:
@@ -27,7 +27,7 @@ on:
jobs:
test_builds:
name: Build Test
name: Run All Tests
if: github.repository == 'MarlinFirmware/Marlin'
runs-on: ubuntu-latest
+4 -30
View File
@@ -12,12 +12,7 @@ help:
@echo "make tests-single-local-docker : Run a single test locally, using docker"
@echo "make tests-all-local : Run all tests locally"
@echo "make tests-all-local-docker : Run all tests locally, using docker"
# @echo "make unit-test-single-ci : Run a single code test from inside the CI"
# @echo "make unit-test-single-local : Run a single code test locally"
# @echo "make unit-test-single-local-docker : Run a single code test locally, using docker-compose"
@echo "make unit-test-all-local : Run all code tests locally"
@echo "make unit-test-all-local-docker : Run all code tests locally, using docker-compose"
@echo "make setup-local-docker : Setup local docker-compose"
@echo "make setup-local-docker : Build the local docker image"
@echo ""
@echo "Options for testing:"
@echo " TEST_TARGET Set when running tests-single-*, to select the"
@@ -48,7 +43,7 @@ tests-single-local:
tests-single-local-docker:
@if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET=<your-module> or use make tests-all-local-docker" ; return 1; fi
@if ! $(CONTAINER_RT_BIN) images -q $(CONTAINER_IMAGE) > /dev/null ; then $(MAKE) setup-local-docker ; fi
$(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) make tests-single-local TEST_TARGET=$(TEST_TARGET) VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD) ONLY_TEST="$(ONLY_TEST)"
$(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) $(MAKE) tests-single-local TEST_TARGET=$(TEST_TARGET) VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD) ONLY_TEST="$(ONLY_TEST)"
tests-all-local:
export PATH="./buildroot/bin/:./buildroot/tests/:${PATH}" \
@@ -57,31 +52,10 @@ tests-all-local:
tests-all-local-docker:
@if ! $(CONTAINER_RT_BIN) images -q $(CONTAINER_IMAGE) > /dev/null ; then $(MAKE) setup-local-docker ; fi
$(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) make tests-all-local VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD)
#unit-test-single-ci:
# export GIT_RESET_HARD=true
# $(MAKE) unit-test-single-local TEST_TARGET=$(TEST_TARGET)
# TODO: How can we limit tests with ONLY_TEST with platformio?
#unit-test-single-local:
# @if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET=<your-module> or use make unit-test-all-local" ; return 1; fi
# platformio run -t marlin_$(TEST_TARGET)
#unit-test-single-local-docker:
# @if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET=<your-module> or use make unit-test-all-local-docker" ; return 1; fi
# @if ! $(CONTAINER_RT_BIN) images -q $(CONTAINER_IMAGE) > /dev/null ; then $(MAKE) setup-local-docker ; fi
# $(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) make unit-test-single-local TEST_TARGET=$(TEST_TARGET) ONLY_TEST="$(ONLY_TEST)"
unit-test-all-local:
platformio run -t test-marlin -e linux_native_test
unit-test-all-local-docker:
@if ! $(CONTAINER_RT_BIN) images -q $(CONTAINER_IMAGE) > /dev/null ; then $(MAKE) setup-local-docker ; fi
$(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) make unit-test-all-local
$(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) $(MAKE) tests-all-local VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD)
setup-local-docker:
$(CONTAINER_RT_BIN) buildx build -t $(CONTAINER_IMAGE) -f docker/Dockerfile .
$(CONTAINER_RT_BIN) build -t $(CONTAINER_IMAGE) -f docker/Dockerfile .
PINS := $(shell find Marlin/src/pins -mindepth 2 -name '*.h')
+524 -1786
View File
File diff suppressed because it is too large Load Diff
+236 -409
View File
File diff suppressed because it is too large Load Diff
+9 -161
View File
@@ -16,7 +16,7 @@
* 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 <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
@@ -28,177 +28,25 @@
/**
* Marlin release version identifier
*/
#define SHORT_BUILD_VERSION "DW7.4.9"
#define SHORT_BUILD_VERSION "2.1.x-TR1"
/**
* Verbose version identifier which should contain a reference to the location
* from where the binary was downloaded or the source code was compiled.
*/
#if(ENABLED(MachineMini))
#define VerChar1 "M"
#elif(ENABLED(MachineEnder2))
#define VerChar1 "E2"
#elif(ENABLED(MachineEnder2Pro))
#define VerChar1 "E2P"
#elif(ENABLED(MachineEnder3))
#define VerChar1 "E3"
#elif ENABLED(MachineEnder3V2)
#define VerChar1 "E3V2"
#elif ENABLED(MachineEnder3S1)
#define VerChar1 "E3S1"
#elif ENABLED(MachineEnder3Max)
#define VerChar1 "E3M"
#elif(ENABLED(MachineEnder4))
#define VerChar1 "E4"
#elif(ENABLED(MachineEnder5))
#define VerChar1 "E5"
#elif(ENABLED(MachineEnder6))
#define VerChar1 "E6"
#elif(ENABLED(MachineEnder7))
#define VerChar1 "E7"
#elif(ENABLED(MachineSermoonD1))
#define VerChar1 "D1"
#elif(ENABLED(MachineEnder5Plus))
#define VerChar1 "E5P"
#elif(ENABLED(MachineCR20))
#define VerChar1 "2"
#elif(ENABLED(MachineCR10Orig))
#define VerChar1 "O"
#elif(ENABLED(MachineCR10Std))
#define VerChar1 "S"
#elif(ENABLED(MachineCRX))
#define VerChar1 "X"
#elif(ENABLED(MachineCR6))
#define VerChar1 "CR6"
#elif(ENABLED(MachineCR5))
#define VerChar1 "CR5"
#elif(ENABLED(MachineCR6Max))
#define VerChar1 "CR6M"
#elif(ENABLED(MachineS4))
#define VerChar1 "4"
#elif(ENABLED(MachineS5) || ENABLED(MachineCR10Max))
#define VerChar1 "5"
#elif ENABLED(MachineCR2020)
#define VerChar1 "20"
#elif(ENABLED(MachineCR30))
#define VerChar1 "CR30"
#endif
#if(ENABLED(HotendStock))
#define VerChar2 "S"
#elif(ENABLED(HotendE3D))
#define VerChar2 "E"
#elif ENABLED(HotendMosquito)
#define VerChar2 "M"
#endif
#if(ENABLED(HotendAllMetal))
#define VerChar3 "M"
#else
#define VerChar3 "S"
#endif
#if(ENABLED(BedAC))
#define VerChar4 "A"
#elif(ENABLED(BedDC))
#define VerChar4 "D"
#else
#define VerChar4 "N"
#endif
#if(ENABLED(ABL_EZABL))
#define VerChar5 "A"
#elif(ENABLED(ABL_BLTOUCH))
#define VerChar5 "B"
#else
#define VerChar5 "N"
#endif
#if(ENABLED(ABL_UBL))
#define VerChar6 "U"
#elif(ENABLED(ABL_BI))
#define VerChar6 "B"
#else
#define VerChar6 "N"
#endif
#define DETAILED_BUILD_VERSION SHORT_BUILD_VERSION " TM3D " VerChar1 VerChar2 VerChar3 VerChar4 VerChar5 VerChar6
#define DETAILED_BUILD_VERSION SHORT_BUILD_VERSION " TM3D"
/**
* The STRING_DISTRIBUTION_DATE represents when the binary file was built,
* here we define this default string as the date where the latest release
* version was tagged.
*/
#define STRING_DISTRIBUTION_DATE "2024-04-08"
//#define STRING_DISTRIBUTION_DATE "2024-04-11"
/**
* Defines a generic printer name to be output to the LCD after booting Marlin.
*/
#if(ENABLED(MachineMini))
#define CUSTOM_MACHINE_NAME "Mini SuPeR"
#elif(ENABLED(MachineCR10Smart))
#define CUSTOM_MACHINE_NAME "TM3D CR10Smart"
#elif(ENABLED(MachineCR10SmartPro))
#define CUSTOM_MACHINE_NAME "TM3D CR10SmartPro"
#elif(ENABLED(MachineEnder2))
#define CUSTOM_MACHINE_NAME "TM3D Ender2"
#elif(ENABLED(MachineEnder2Pro))
#define CUSTOM_MACHINE_NAME "TM3D Ender2 Pro"
#elif(ENABLED(MachineEnder3))
#define CUSTOM_MACHINE_NAME "TM3D Ender3"
#elif(ENABLED(MachineEnder3Max))
#define CUSTOM_MACHINE_NAME "TM3D E3Max"
#elif(ENABLED(MachineEnder6))
#define CUSTOM_MACHINE_NAME "TM3D Ender6"
#elif(ENABLED(MachineEnder7))
#define CUSTOM_MACHINE_NAME "TM3D Ender7"
#elif(ENABLED(MachineEnder3V2))
#define CUSTOM_MACHINE_NAME "TM3D Ender3V2"
#elif(ENABLED(MachineEnder3S1))
#define CUSTOM_MACHINE_NAME "TM3D Ender3S1"
#elif(ENABLED(MachineEnder4))
#define CUSTOM_MACHINE_NAME "TM3D Ender4"
#elif(ENABLED(MachineEnder5))
#define CUSTOM_MACHINE_NAME "TM3D Ender5"
#elif(ENABLED(MachineEnder5Plus))
#define CUSTOM_MACHINE_NAME "TM3D E5 Plus"
#elif(ENABLED(MachineCR20))
#define CUSTOM_MACHINE_NAME "SuPeR CR-20"
#elif(ENABLED(MachineCR10Orig))
#define CUSTOM_MACHINE_NAME "SuPeR CR-10"
#elif(ENABLED(MachineCRX))
#define CUSTOM_MACHINE_NAME "TM3D CR-X"
#elif ENABLED(MachineCR10SProV2)
#define CUSTOM_MACHINE_NAME "TM3D 10SProV2"
#elif(ENABLED(MachineCR10SPro))
#define CUSTOM_MACHINE_NAME "TM3D 10S Pro"
#elif(ENABLED(MachineCR10Max))
#define CUSTOM_MACHINE_NAME "TM3D Max"
#elif(ENABLED(MachineCR10SV3))
#define CUSTOM_MACHINE_NAME "TM3D CR10V3"
#elif(ENABLED(MachineCR10SV2))
#define CUSTOM_MACHINE_NAME "TM3D CR10V2"
#elif(ENABLED(MachineCR10Std))
#define CUSTOM_MACHINE_NAME "300 SuPeR"
#elif(ENABLED(MachineS4))
#define CUSTOM_MACHINE_NAME "400 SuPeR"
#elif(ENABLED(MachineS5))
#define CUSTOM_MACHINE_NAME "500 SuPeR"
#elif ENABLED(MachineCR2020)
#define CUSTOM_MACHINE_NAME "TM3D 2020"
#elif ENABLED(MachineSermoonD1)
#define CUSTOM_MACHINE_NAME "SermoonD1"
#elif ENABLED(MachineCR5)
#define CUSTOM_MACHINE_NAME "CR5 Pro"
#elif ENABLED(MachineCR6)
#define CUSTOM_MACHINE_NAME "CR6"
#elif ENABLED(MachineCR6Max)
#define CUSTOM_MACHINE_NAME "CR6 Max"
#elif ENABLED(MachineCR30)
#define CUSTOM_MACHINE_NAME "CR30 Printmill"
#endif
#define MACHINE_NAME "TM3D Trex"
/**
* The SOURCE_CODE_URL is the location where users will find the Marlin Source
@@ -206,7 +54,7 @@
* has a distinct Github fork— the Source Code URL should just be the main
* Marlin repository.
*/
#define SOURCE_CODE_URL "https://github.com/InsanityAutomation/Marlin/tree/CrealityDwin_2.0"
#define SOURCE_CODE_URL "https://github.com/InsanityAutomation/Marlin/tree/TM_Trex2+_2.0.x"
/**
* Default generic printer UUID.
@@ -223,6 +71,6 @@
* Set the vendor info the serial USB interface, if changable
* Currently only supported by DUE platform
*/
//#define USB_DEVICE_VENDOR_ID 0x0000
//#define USB_DEVICE_PRODUCT_ID 0x0000
//#define USB_DEVICE_MANUFACTURE_NAME WEBSITE_URL
//#define USB_DEVICE_VENDOR_ID 0x0000
//#define USB_DEVICE_PRODUCT_ID 0x0000
//#define USB_DEVICE_MANUFACTURE_NAME WEBSITE_URL
+2 -2
View File
@@ -141,8 +141,8 @@ typedef Servo hal_servo_t;
#error "LCD_SERIAL_PORT must be from 0 to 3."
#endif
#define LCD_SERIAL lcdSerial
#if HAS_DGUS_LCD || ENABLED(DGUS_LCD_UI_CREALITY_TOUCH) || ENABLED(EXTENSIBLE_UI)
#define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.get_tx_buffer_free()
#if HAS_DGUS_LCD
#define LCD_SERIAL_TX_BUFFER_FREE() LCD_SERIAL.get_tx_buffer_free()
#endif
#endif
+1 -1
View File
@@ -629,7 +629,7 @@ MSerialT1 customizedSerial1(MSerialT1::HasEmergencyParser);
template class MarlinSerial< LCDSerialCfg<LCD_SERIAL_PORT> >;
MSerialLCD lcdSerial(MSerialLCD::HasEmergencyParser);
#if HAS_DGUS_LCD || ENABLED(DGUS_LCD_UI_CREALITY_TOUCH) || ENABLED(EXTENSIBLE_UI)
#if HAS_DGUS_LCD
template<typename Cfg>
typename MarlinSerial<Cfg>::ring_buffer_pos_t MarlinSerial<Cfg>::get_tx_buffer_free() {
const ring_buffer_pos_t t = tx_buffer.tail, // next byte to send.
+2 -2
View File
@@ -205,7 +205,7 @@
static ring_buffer_pos_t available();
static void write(const uint8_t c);
static void flushTX();
#if HAS_DGUS_LCD || ENABLED(DGUS_LCD_UI_CREALITY_TOUCH) || ENABLED(EXTENSIBLE_UI)
#if HAS_DGUS_LCD
static ring_buffer_pos_t get_tx_buffer_free();
#endif
@@ -276,7 +276,7 @@
static constexpr bool DROPPED_RX = false;
static constexpr bool RX_FRAMING_ERRORS = false;
static constexpr bool MAX_RX_QUEUED = false;
static constexpr bool RX_OVERRUNS = (ANY(HAS_DGUS_LCD, SERIAL_STATS_RX_BUFFER_OVERRUNS) || ENABLED(DWINOS_4));
static constexpr bool RX_OVERRUNS = ALL(HAS_DGUS_LCD, SERIAL_STATS_RX_BUFFER_OVERRUNS);
};
typedef Serial1Class< MarlinSerial< LCDSerialCfg<LCD_SERIAL_PORT> > > MSerialLCD;
+1 -30
View File
@@ -123,11 +123,6 @@ void MarlinHAL::init() {
// Register min serial
TERN_(POSTMORTEM_DEBUGGING, install_min_serial());
// warn if low memory after init
if (freeMemory() < 1024) {
SERIAL_WARN_MSG("HAL: low memory after init!\n");
}
}
void MarlinHAL::init_board() {}
@@ -152,31 +147,7 @@ void MarlinHAL::delay_ms(const int ms) {
delay(ms);
}
void MarlinHAL::idletask() {
#if ENABLED(MARLIN_DEV_MODE)
// check & print serial RX errors
MSerialT *serials[] = { &MSerial1, &MSerial2 };
for (int serial = 0; serial < 2; serial++) {
usart_receive_error_t err = serials[serial]->getReceiveError();
if (err != usart_receive_error_t::None) {
// "Warning: MSerial[n] RX [Framing|Parity|Overrun] Error"
SERIAL_WARN_START();
SERIAL_ECHOPGM(" MSerial");
SERIAL_ECHO(serial + 1);
SERIAL_ECHOPGM(" RX ");
switch(err) {
case usart_receive_error_t::FramingError: SERIAL_ECHOPGM("Framing"); break;
case usart_receive_error_t::ParityError: SERIAL_ECHOPGM("Parity"); break;
case usart_receive_error_t::OverrunError: SERIAL_ECHOPGM("Overrun"); break;
case usart_receive_error_t::RxDataDropped: SERIAL_ECHOPGM("DataDropped"); break;
default: break;
}
SERIAL_ECHOPGM(" Error");
SERIAL_EOL();
}
}
#endif
}
void MarlinHAL::idletask() {}
uint8_t MarlinHAL::get_reset_source() {
// Query reset cause from RMU
+3 -23
View File
@@ -46,34 +46,14 @@ constexpr bool serial_handles_emergency(int port) {
//
// Define serial ports
//
// serial port where RX and TX use IRQs
#define DEFINE_IRQ_SERIAL_MARLIN(name, n) \
#define DEFINE_HWSERIAL_MARLIN(name, n) \
MSerialT name(serial_handles_emergency(n), \
&USART##n##_config, \
BOARD_USART##n##_TX_PIN, \
BOARD_USART##n##_RX_PIN);
// serial port where RX uses DMA and TX uses IRQs
// all serial ports use DMA1
// since there are 4 USARTs and 4 DMA channels, we can use the USART number as the DMA channel
#define DEFINE_DMA_SERIAL_MARLIN(name, n) \
MSerialT name(serial_handles_emergency(n), \
&USART##n##_config, \
BOARD_USART##n##_TX_PIN, \
BOARD_USART##n##_RX_PIN, \
M4_DMA1, \
((en_dma_channel_t)(n - 1))); // map USART1 to DMA channel 0, USART2 to DMA channel 1, etc.
#define DEFINE_SERIAL_MARLIN(name, n) TERN(SERIAL_DMA, DEFINE_DMA_SERIAL_MARLIN(name, n), DEFINE_IRQ_SERIAL_MARLIN(name, n))
DEFINE_SERIAL_MARLIN(MSerial1, 1);
DEFINE_SERIAL_MARLIN(MSerial2, 2);
// TODO: remove this warning when SERIAL_DMA has been tested some more
#if ENABLED(SERIAL_DMA)
#warning "SERIAL_DMA may be unstable on HC32F460."
#endif
DEFINE_HWSERIAL_MARLIN(MSerial1, 1);
DEFINE_HWSERIAL_MARLIN(MSerial2, 2);
//
// Serial port assertions
+8 -38
View File
@@ -25,42 +25,17 @@
#include <drivers/usart/Usart.h>
// Optionally set uart IRQ priority to reduce overflow errors
//#define UART_RX_IRQ_PRIO 1
//#define UART_TX_IRQ_PRIO 1
//#define UART_RX_DMA_IRQ_PRIO 1
// #define UART_IRQ_PRIO 1
struct MarlinSerial : public Usart {
MarlinSerial(
struct usart_config_t *usart_device,
gpio_pin_t tx_pin,
gpio_pin_t rx_pin
#if ENABLED(SERIAL_DMA)
, M4_DMA_TypeDef *dma_unit = nullptr,
en_dma_channel_t rx_dma_channel = DmaCh0
#endif
) : Usart(usart_device, tx_pin, rx_pin) {
#if ENABLED(SERIAL_DMA)
if (dma_unit != nullptr) {
enableRxDma(dma_unit, rx_dma_channel);
}
#endif
}
MarlinSerial(struct usart_config_t *usart_device, gpio_pin_t tx_pin, gpio_pin_t rx_pin) : Usart(usart_device, tx_pin, rx_pin) {}
#if defined(UART_RX_IRQ_PRIO) || defined(UART_TX_IRQ_PRIO) || defined(UART_RX_DMA_IRQ_PRIO)
#ifdef UART_IRQ_PRIO
void setPriority() {
#if defined(UART_RX_IRQ_PRIO)
NVIC_SetPriority(c_dev()->interrupts.rx_data_available.interrupt_number, UART_RX_IRQ_PRIO);
NVIC_SetPriority(c_dev()->interrupts.rx_error.interrupt_number, UART_RX_IRQ_PRIO);
#endif
#if defined(UART_TX_IRQ_PRIO)
NVIC_SetPriority(c_dev()->interrupts.tx_buffer_empty.interrupt_number, UART_TX_IRQ_PRIO);
NVIC_SetPriority(c_dev()->interrupts.tx_complete.interrupt_number, UART_TX_IRQ_PRIO);
#endif
#if defined(UART_RX_DMA_IRQ_PRIO) && ENABLED(SERIAL_DMA)
NVIC_SetPriority(c_dev()->dma.rx.rx_data_available_dma_btc.interrupt_number, UART_RX_DMA_IRQ_PRIO);
#endif
NVIC_SetPriority(c_dev()->interrupts.rx_data_available.interrupt_number, UART_IRQ_PRIO);
NVIC_SetPriority(c_dev()->interrupts.rx_error.interrupt_number, UART_IRQ_PRIO);
NVIC_SetPriority(c_dev()->interrupts.tx_buffer_empty.interrupt_number, UART_IRQ_PRIO);
NVIC_SetPriority(c_dev()->interrupts.tx_complete.interrupt_number, UART_IRQ_PRIO);
}
void begin(uint32_t baud) {
@@ -72,12 +47,7 @@ struct MarlinSerial : public Usart {
Usart::begin(baud, config);
setPriority();
}
void begin(uint32_t baud, const stc_usart_uart_init_t *config, const bool rxNoiseFilter = true) {
Usart::begin(baud, config, rxNoiseFilter);
setPriority();
}
#endif // UART_RX_IRQ_PRIO || UART_TX_IRQ_PRIO || UART_RX_DMA_IRQ_PRIO
#endif
};
typedef Serial1Class<MarlinSerial> MSerialT;
-70
View File
@@ -1,70 +0,0 @@
/**
* app_config.h is included by the hc32f460 arduino build script for every source file.
* it is used to configure the arduino core (and ddl) automatically according
* to the settings in Configuration.h and Configuration_adv.h.
*/
#pragma once
#ifndef _HC32_APP_CONFIG_H_
#define _HC32_APP_CONFIG_H_
#include "../../inc/MarlinConfigPre.h"
//
// dev mode
//
#if ENABLED(MARLIN_DEV_MODE)
#define __DEBUG 1
#define __CORE_DEBUG 1
#endif
//
// Fault Handlers and Panic
//
#if ENABLED(POSTMORTEM_DEBUGGING)
// disable arduino core fault handler, as we define our own
#define CORE_DISABLE_FAULT_HANDLER 1
#endif
// force-enable panic handler so that we can use our custom one (in MinSerial)
#define PANIC_ENABLE 1
// use short filenames in ddl debug and core panic output
#define __DEBUG_SHORT_FILENAMES 1
#define __PANIC_SHORT_FILENAMES 1
// omit panic messages in core panic output
#define __OMIT_PANIC_MESSAGE 1
//
// Usart
//
// disable serial globals (Serial1, Serial2, ...), as we define our own
#define DISABLE_SERIAL_GLOBALS 1
// increase the size of the Usart buffers (both RX and TX)
// NOTE:
// the heap usage will increase by (SERIAL_BUFFER_SIZE - 64) * "number of serial ports used"
// if running out of heap, the system may become unstable
//#define SERIAL_BUFFER_SIZE 256
// enable support for Usart Clock Divider / Oversampling auto config
#define USART_AUTO_CLKDIV_OS_CONFIG 1
// enable USART_RX_DMA_SUPPORT core option when SERIAL_DMA is enabled
#if ENABLED(SERIAL_DMA)
#define USART_RX_DMA_SUPPORT 1
#endif
//
// Misc.
//
// redirect printf to host serial
#define REDIRECT_PRINTF_TO_SERIAL 1
// FIXME override F_CPU to PCLK1, as marlin freaks out otherwise
#define F_CPU (SYSTEM_CLOCK_FREQUENCIES.pclk1)
#endif // _HC32_APP_CONFIG_H_
-29
View File
@@ -20,20 +20,6 @@
*
*/
#pragma once
#include <core_util.h>
#if !defined(ARDUINO_CORE_VERSION_INT) || !defined(GET_VERSION_INT)
// version macros were introduced in arduino core version 1.1.0
// below that version, we polyfill them
#define GET_VERSION_INT(major, minor, patch) ((major * 100000) + (minor * 1000) + patch)
#define ARDUINO_CORE_VERSION_INT GET_VERSION_INT(1, 0, 0)
#endif
#if ARDUINO_CORE_VERSION_INT < GET_VERSION_INT(1, 1, 0)
// because we use app_config.h introduced in arduino core version 1.1.0, the
// HAL is not compatible with older versions
#error "The HC32 HAL is not compatible with Arduino Core versions < 1.1.0. Consider updating the Arduino Core."
#endif
#ifndef BOARD_XTAL_FREQUENCY
#error "BOARD_XTAL_FREQUENCY is required for HC32F460."
@@ -88,18 +74,3 @@
#error "HC32 HAL uses a custom panic handler. Do not define PANIC_USARTx_TX_PIN."
#endif
#endif
#if ENABLED(SERIAL_DMA)
#if !defined(USART_RX_DMA_SUPPORT)
#error "SERIAL_DMA requires USART_RX_DMA_SUPPORT to be enabled in the arduino core."
#endif
// USART_RX_DMA_SUPPORT does not implement core_hook_usart_rx_irq, which is required for the emergency parser
#if ENABLED(EMERGENCY_PARSER)
#error "EMERGENCY_PARSER is not supported with SERIAL_DMA. Please disable either SERIAL_DMA or EMERGENCY_PARSER."
#endif
#if ARDUINO_CORE_VERSION_INT < GET_VERSION_INT(1, 1, 0)
#error "SERIAL_DMA is not supported with arduino core version < 1.1.0."
#endif
#endif
+17 -26
View File
@@ -54,7 +54,7 @@
fn \
}
stc_sd_handle_t *handle = nullptr;
stc_sd_handle_t *handle;
bool SDIO_Init() {
// Configure SDIO pins
@@ -66,45 +66,36 @@ bool SDIO_Init() {
GPIO_SetFunc(BOARD_SDIO_CMD, Func_Sdio);
GPIO_SetFunc(BOARD_SDIO_DET, Func_Sdio);
// If a handle is already initialized, free it before creating a new one
// otherwise, we will leak memory, which will eventually crash the system
if (handle != nullptr) {
delete handle->pstcDmaInitCfg;
delete handle->pstcCardInitCfg;
delete handle;
handle = nullptr;
}
// Create DMA configuration
stc_sdcard_dma_init_t *dmaConf = new stc_sdcard_dma_init_t;
dmaConf->DMAx = SDIO_DMA_PERIPHERAL;
dmaConf->enDmaCh = SDIO_DMA_CHANNEL;
// Create card configuration
// This should be a fairly safe configuration for most cards
stc_sdcard_init_t *cardConf = new stc_sdcard_init_t;
cardConf->enBusWidth = SdiocBusWidth4Bit;
cardConf->enClkFreq = SdiocClk400K;
cardConf->enSpeedMode = SdiocNormalSpeedMode;
cardConf->pstcInitCfg = nullptr;
// Create handle in DMA mode
handle = new stc_sd_handle_t;
handle->SDIOCx = SDIO_PERIPHERAL;
handle->enDevMode = SdCardDmaMode;
handle->pstcDmaInitCfg = dmaConf;
//handle->pstcCardInitCfg = cardConf; // assigned in SDCARD_Init
// Create card configuration
// This should be a fairly safe configuration for most cards
stc_sdcard_init_t cardConf = {
.enBusWidth = SdiocBusWidth4Bit,
.enClkFreq = SdiocClk400K,
.enSpeedMode = SdiocNormalSpeedMode,
//.pstcInitCfg = NULL,
};
// Initialize sd card
en_result_t rc = SDCARD_Init(handle, cardConf);
en_result_t rc = SDCARD_Init(handle, &cardConf);
if (rc != Ok) printf("SDIO_Init() error (rc=%u)\n", rc);
return rc == Ok;
}
bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
CORE_ASSERT(handle != nullptr, "SDIO not initialized", return false);
CORE_ASSERT(dst != nullptr, "SDIO_ReadBlock dst is NULL", return false);
CORE_ASSERT(handle != NULL, "SDIO not initialized");
CORE_ASSERT(dst != NULL, "SDIO_ReadBlock dst is NULL");
WITH_RETRY(SDIO_READ_RETRIES, {
en_result_t rc = SDCARD_ReadBlocks(handle, block, 1, dst, SDIO_READ_TIMEOUT);
@@ -116,8 +107,8 @@ bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
}
bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
CORE_ASSERT(handle != nullptr, "SDIO not initialized", return false);
CORE_ASSERT(src != nullptr, "SDIO_WriteBlock src is NULL", return false);
CORE_ASSERT(handle != NULL, "SDIO not initialized");
CORE_ASSERT(src != NULL, "SDIO_WriteBlock src is NULL");
WITH_RETRY(SDIO_WRITE_RETRIES, {
en_result_t rc = SDCARD_WriteBlocks(handle, block, 1, (uint8_t *)src, SDIO_WRITE_TIMEOUT);
@@ -129,12 +120,12 @@ bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
}
bool SDIO_IsReady() {
CORE_ASSERT(handle != nullptr, "SDIO not initialized", return false);
CORE_ASSERT(handle != NULL, "SDIO not initialized");
return bool(handle->stcCardStatus.READY_FOR_DATA);
}
uint32_t SDIO_GetCardSize() {
CORE_ASSERT(handle != nullptr, "SDIO not initialized", return 0);
CORE_ASSERT(handle != NULL, "SDIO not initialized");
// Multiply number of blocks with block size to get size in bytes
const uint64_t cardSizeBytes = uint64_t(handle->stcSdCardInfo.u32LogBlockNbr) * uint64_t(handle->stcSdCardInfo.u32LogBlockSize);
+1 -4
View File
@@ -37,10 +37,7 @@ Timer::Timer() {
}
Timer::~Timer() {
if (timerid != 0) {
timer_delete(timerid);
timerid = 0;
}
timer_delete(timerid);
}
void Timer::init(uint32_t sig_id, uint32_t sim_freq, callback_fn* fn) {
-2
View File
@@ -21,7 +21,6 @@
*/
#ifdef __PLAT_LINUX__
#ifndef UNIT_TEST
//#define GPIO_LOGGING // Full GPIO and Positional Logging
@@ -136,5 +135,4 @@ int main() {
read_serial.join();
}
#endif // UNIT_TEST
#endif // __PLAT_LINUX__
+1 -1
View File
@@ -100,7 +100,7 @@ extern DefaultSerial1 USBSerial;
#else
#error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#if HAS_DGUS_LCD || ENABLED(DWINOS_4)
#if HAS_DGUS_LCD
#define LCD_SERIAL_TX_BUFFER_FREE() LCD_SERIAL.available()
#endif
#endif
+1 -1
View File
@@ -112,7 +112,7 @@
#else
#error "LCD_SERIAL_PORT must be from 1 to 9, or -1 for Native USB."
#endif
#if HAS_DGUS_LCD || ENABLED(DGUS_LCD_UI_CREALITY_TOUCH) || ENABLED(EXTENSIBLE_UI)
#if HAS_DGUS_LCD
#define LCD_SERIAL_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite()
#endif
#endif
-3
View File
@@ -43,7 +43,6 @@
#else // Arduino non-DMA
FORCE_INLINE static uint8_t buffer_overruns() { return 0; }
typedef void (*usart_rx_callback_t)(serial_t * obj);
struct MarlinSerial : public HardwareSerial {
@@ -54,8 +53,6 @@
inline void begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
void _rx_complete_irq(serial_t *obj);
FORCE_INLINE static uint8_t buffer_overruns() { return 0; } // Not implemented. Void to avoid platform-dependent code.
FORCE_INLINE uint32_t dropped() { return 0; }
protected:
usart_rx_callback_t _rx_callback;
+1 -1
View File
@@ -138,7 +138,7 @@
#define LCD_SERIAL MSERIAL(1) // dummy port
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 || ENABLED(DGUS_LCD_UI_CREALITY_TOUCH) || ENABLED(DWINOS_4)
#if HAS_DGUS_LCD
#define LCD_SERIAL_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite()
#endif
#endif
+3 -8
View File
@@ -474,16 +474,11 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
#if HAS_KILL
// Check if the kill button was pressed and wait to ensure the signal is not noise
// typically caused by poor insulation and grounding on LCD cables.
// Lower numbers here will increase response time and therefore safety rating.
// It is recommended to set this as low as possibe without false triggers.
// Check if the kill button was pressed and wait just in case it was an accidental
// key kill key press
// -------------------------------------------------------------------------------
#ifndef KILL_DELAY
#define KILL_DELAY 250
#endif
static int killCount = 0; // make the inactivity button a bit less responsive
const int KILL_DELAY = 750;
if (kill_state())
killCount++;
else if (killCount > 0)
-1
View File
@@ -131,7 +131,6 @@
#define BOARD_PXMALION_CORE_I3 1164 // Pxmalion Core I3
#define BOARD_PANOWIN_CUTLASS 1165 // Panowin Cutlass (as found in the Panowin F1)
#define BOARD_KODAMA_BARDO 1166 // Kodama Bardo V1.x (as found in the Kodama Trinus)
#define BOARD_DAGOMA_D6 1167 // Dagoma D6 (as found in the Dagoma DiscoUltimate V2 TMC)
//
// RAMBo and derivatives
+3 -9
View File
@@ -25,10 +25,6 @@
#include "../MarlinCore.h"
#include "../module/temperature.h"
#if ENABLED(MARLIN_DEV_MODE)
MarlinError marlin_error_number; // Error Number - Marlin can beep X times periodically, display, and emit...
#endif
void safe_delay(millis_t ms) {
while (ms > 50) {
ms -= 50;
@@ -80,8 +76,6 @@ void safe_delay(millis_t ms) {
TERN_(Z_PROBE_ALLEN_KEY, "Z_PROBE_ALLEN_KEY")
TERN_(SOLENOID_PROBE, "SOLENOID_PROBE")
TERN_(MAGLEV4, "MAGLEV4")
TERN_(BIQU_MICROPROBE_V1, "BIQU_MICROPROBE_V1")
TERN_(BIQU_MICROPROBE_V2, "BIQU_MICROPROBE_V2")
IF_DISABLED(PROBE_SELECTED, "NONE")
);
@@ -101,9 +95,9 @@ void safe_delay(millis_t ms) {
SERIAL_ECHOPGM(" (Aligned With");
if (probe.offset_xy.y > 0)
SERIAL_ECHO(F(TERN(IS_SCARA, "-Distal", "-Back")));
SERIAL_ECHOPGM(TERN(IS_SCARA, "-Distal", "-Back"));
else if (probe.offset_xy.y < 0)
SERIAL_ECHO(F(TERN(IS_SCARA, "-Proximal", "-Front")));
SERIAL_ECHOPGM(TERN(IS_SCARA, "-Proximal", "-Front"));
else if (probe.offset_xy.x != 0)
SERIAL_ECHOPGM("-Center");
@@ -111,7 +105,7 @@ void safe_delay(millis_t ms) {
#endif
SERIAL_ECHO(probe.offset.z < 0 ? F("Below") : probe.offset.z > 0 ? F("Above") : F("Same Z as"));
SERIAL_ECHOF(probe.offset.z < 0 ? F("Below") : probe.offset.z > 0 ? F("Above") : F("Same Z as"));
SERIAL_ECHOLNPGM(" Nozzle)");
#endif
+96 -97
View File
@@ -76,7 +76,7 @@ MMU2 mmu2;
#define MMU2_NO_TOOL 99
#define MMU_BAUD 115200
bool MMU2::_enabled, MMU2::ready;
bool MMU2::_enabled, MMU2::ready, MMU2::mmu_print_saved;
#if HAS_PRUSA_MMU2S
bool MMU2::mmu2s_triggered;
#endif
@@ -84,6 +84,7 @@ uint8_t MMU2::cmd, MMU2::cmd_arg, MMU2::last_cmd, MMU2::extruder;
int8_t MMU2::state = 0;
volatile int8_t MMU2::finda = 1;
volatile bool MMU2::finda_runout_valid;
int16_t MMU2::version = -1, MMU2::buildnr = -1;
millis_t MMU2::prev_request, MMU2::prev_P0_request;
char MMU2::rx_buffer[MMU_RX_SIZE], MMU2::tx_buffer[MMU_TX_SIZE];
@@ -92,11 +93,14 @@ struct E_Step {
feedRate_t feedRate; //!< feed rate in mm/s
};
inline void unscaled_mmu2_e_move(const float &dist, const feedRate_t fr_mm_s, const bool sync=true) {
current_position.e += dist / planner.e_factor[active_extruder];
line_to_current_position(fr_mm_s);
if (sync) planner.synchronize();
}
static constexpr E_Step
ramming_sequence[] PROGMEM = { MMU2_RAMMING_SEQUENCE }
, load_to_nozzle_sequence[] PROGMEM = { MMU2_LOAD_TO_NOZZLE_SEQUENCE }
#if HAS_PRUSA_MMU2S
, can_load_sequence[] PROGMEM = { MMU2_CAN_LOAD_SEQUENCE }
, can_load_increment_sequence[] PROGMEM = { MMU2_CAN_LOAD_INCREMENT_SEQUENCE }
#endif
;
MMU2::MMU2() {
rx_buffer[0] = '\0';
@@ -132,12 +136,12 @@ void MMU2::reset() {
#endif
}
int8_t MMU2::get_current_tool() { return extruder == MMU2_NO_TOOL ? -1 : extruder; }
uint8_t MMU2::get_current_tool() {
return extruder == MMU2_NO_TOOL ? -1 : extruder;
}
#if ANY(HAS_PRUSA_MMU2S, MMU_EXTRUDER_SENSOR)
#if EITHER(HAS_PRUSA_MMU2S, MMU_EXTRUDER_SENSOR)
#define FILAMENT_PRESENT() (READ(FIL_RUNOUT1_PIN) != runout.out_state())
#else
#define FILAMENT_PRESENT() true
#endif
void mmu2_attn_buzz(const bool two=false) {
@@ -145,7 +149,6 @@ void mmu2_attn_buzz(const bool two=false) {
if (two) { BUZZ(10, 0); BUZZ(200, 404); }
}
// Avoiding sscanf significantly reduces build size
void MMU2::mmu_loop() {
switch (state) {
@@ -160,7 +163,7 @@ void MMU2::mmu_loop() {
MMU2_SEND("S1"); // Read Version
state = -2;
}
else if (ELAPSED(millis(), prev_request + 30000)) { // 30sec after reset disable MMU
else if (millis() > 30000) { // 30sec after reset disable MMU
SERIAL_ECHOLNPGM("MMU not responding - DISABLED");
state = 0;
}
@@ -168,7 +171,7 @@ void MMU2::mmu_loop() {
case -2:
if (rx_ok()) {
const uint16_t version = uint16_t(strtoul(rx_buffer, nullptr, 10));
sscanf(rx_buffer, "%huok\n", &version);
DEBUG_ECHOLNPGM("MMU => ", version, "\nMMU <= 'S2'");
MMU2_SEND("S2"); // Read Build Number
state = -3;
@@ -177,15 +180,17 @@ void MMU2::mmu_loop() {
case -3:
if (rx_ok()) {
const uint16_t buildnr = uint16_t(strtoul(rx_buffer, nullptr, 10));
sscanf(rx_buffer, "%huok\n", &buildnr);
DEBUG_ECHOLNPGM("MMU => ", buildnr);
check_version(buildnr);
check_version();
#if ENABLED(MMU2_MODE_12V)
DEBUG_ECHOLNPGM("MMU <= 'M1'");
MMU2_SEND("M1"); // Stealth Mode
state = -5;
#else
DEBUG_ECHOLNPGM("MMU <= 'P0'");
MMU2_SEND("P0"); // Read FINDA
@@ -195,21 +200,20 @@ void MMU2::mmu_loop() {
break;
#if ENABLED(MMU2_MODE_12V)
case -5:
// response to M1
if (rx_ok()) {
DEBUG_ECHOLNPGM("MMU => ok");
DEBUG_ECHOLNPGM("MMU <= 'P0'");
MMU2_SEND("P0"); // Read FINDA
state = -4;
}
break;
case -5:
// response to M1
if (rx_ok()) {
DEBUG_ECHOLNPGM("MMU => ok");
DEBUG_ECHOLNPGM("MMU <= 'P0'");
MMU2_SEND("P0"); // Read FINDA
state = -4;
}
break;
#endif
case -4:
if (rx_ok()) {
const uint8_t findex = uint8_t(rx_buffer[0] - '0');
if (findex <= 1) finda = findex;
sscanf(rx_buffer, "%hhuok\n", &finda);
DEBUG_ECHOLNPGM("MMU => ", finda, "\nMMU - ENABLED");
@@ -282,11 +286,10 @@ void MMU2::mmu_loop() {
case 2: // response to command P0
if (rx_ok()) {
const uint8_t findex = uint8_t(rx_buffer[0] - '0');
if (findex <= 1) finda = findex;
sscanf(rx_buffer, "%hhuok\n", &finda);
// This is super annoying. Only activate if necessary
//if (finda_runout_valid) DEBUG_ECHOLNPGM("MMU <= 'P0'\nMMU => ", p_float_t(finda, 6));
// if (finda_runout_valid) DEBUG_ECHOLNPAIR_F("MMU <= 'P0'\nMMU => ", finda, 6);
if (!finda && finda_runout_valid) filament_runout();
if (cmd == MMU_CMD_NONE) ready = true;
@@ -403,7 +406,7 @@ void MMU2::tx_str(FSTR_P fstr) {
void MMU2::tx_printf(FSTR_P format, int argument = -1) {
clear_rx_buffer();
const uint8_t len = sprintf_P(tx_buffer, FTOP(format), argument);
for (uint8_t i = 0; i < len; ++i) MMU2_SERIAL.write(tx_buffer[i]);
LOOP_L_N(i, len) MMU2_SERIAL.write(tx_buffer[i]);
prev_request = millis();
}
@@ -413,7 +416,7 @@ void MMU2::tx_printf(FSTR_P format, int argument = -1) {
void MMU2::tx_printf(FSTR_P format, int argument1, int argument2) {
clear_rx_buffer();
const uint8_t len = sprintf_P(tx_buffer, FTOP(format), argument1, argument2);
for (uint8_t i = 0; i < len; ++i) MMU2_SERIAL.write(tx_buffer[i]);
LOOP_L_N(i, len) MMU2_SERIAL.write(tx_buffer[i]);
prev_request = millis();
}
@@ -439,7 +442,7 @@ bool MMU2::rx_ok() {
/**
* Check if MMU has compatible firmware
*/
void MMU2::check_version(const uint16_t buildnr) {
void MMU2::check_version() {
if (buildnr < MMU_REQUIRED_FW_BUILDNR) {
SERIAL_ERROR_MSG("Invalid MMU2 firmware. Version >= " STRINGIFY(MMU_REQUIRED_FW_BUILDNR) " required.");
kill(GET_TEXT_F(MSG_KILL_MMU2_FIRMWARE));
@@ -455,19 +458,12 @@ static void mmu2_not_responding() {
BUZZ(100, 659);
}
inline void beep_bad_cmd() { BUZZ(400, 40); }
#if HAS_PRUSA_MMU2S
/**
* Load filament until the sensor at the gears is triggered
* and give up after a number of attempts set with MMU2_C0_RETRY.
* Each try has a timeout before returning a fail state.
*/
bool MMU2::load_to_gears() {
command(MMU_CMD_C0);
manage_response(true, true);
for (uint8_t i = 0; i < MMU2_C0_RETRY; ++i) { // Keep loading until filament reaches gears
LOOP_L_N(i, MMU2_C0_RETRY) { // Keep loading until filament reaches gears
if (mmu2s_triggered) break;
command(MMU_CMD_C0);
manage_response(true, true);
@@ -488,11 +484,6 @@ inline void beep_bad_cmd() { BUZZ(400, 40); }
set_runout_valid(false);
if (index != extruder) {
if (ENABLED(MMU_IR_UNLOAD_MOVE) && FILAMENT_PRESENT()) {
DEBUG_ECHOLNPGM("Unloading\n");
while (FILAMENT_PRESENT()) // Filament present? Keep unloading.
unscaled_mmu2_e_move(-0.25, MMM_TO_MMS(120)); // 0.25mm is a guessed value. Adjust to preference.
}
stepper.disable_extruder();
ui.status_printf(0, GET_TEXT_F(MSG_MMU2_LOADING_FILAMENT), int(index + 1));
@@ -529,9 +520,9 @@ inline void beep_bad_cmd() { BUZZ(400, 40); }
#if ENABLED(MMU2_MENUS)
const uint8_t index = mmu2_choose_filament();
while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
load_to_nozzle(index);
load_filament_to_nozzle(index);
#else
beep_bad_cmd();
ERR_BUZZ();
#endif
} break;
@@ -550,13 +541,13 @@ inline void beep_bad_cmd() { BUZZ(400, 40); }
active_extruder = 0;
}
#else
beep_bad_cmd();
ERR_BUZZ();
#endif
} break;
case 'c': {
while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
load_to_nozzle_sequence();
load_to_nozzle();
} break;
}
@@ -617,9 +608,9 @@ inline void beep_bad_cmd() { BUZZ(400, 40); }
#if ENABLED(MMU2_MENUS)
uint8_t index = mmu2_choose_filament();
while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
load_to_nozzle(index);
load_filament_to_nozzle(index);
#else
beep_bad_cmd();
ERR_BUZZ();
#endif
} break;
@@ -639,14 +630,14 @@ inline void beep_bad_cmd() { BUZZ(400, 40); }
extruder = index;
active_extruder = 0;
#else
beep_bad_cmd();
ERR_BUZZ();
#endif
} break;
case 'c': {
DEBUG_ECHOLNPGM("case c\n");
while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
load_to_nozzle_sequence();
execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence));
} break;
}
@@ -732,9 +723,9 @@ inline void beep_bad_cmd() { BUZZ(400, 40); }
#if ENABLED(MMU2_MENUS)
uint8_t index = mmu2_choose_filament();
while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
load_to_nozzle(index);
load_filament_to_nozzle(index);
#else
beep_bad_cmd();
ERR_BUZZ();
#endif
} break;
@@ -753,14 +744,14 @@ inline void beep_bad_cmd() { BUZZ(400, 40); }
extruder = index;
active_extruder = 0;
#else
beep_bad_cmd();
ERR_BUZZ();
#endif
} break;
case 'c': {
DEBUG_ECHOLNPGM("case c\n");
while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
load_to_nozzle_sequence();
execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence));
} break;
}
@@ -801,7 +792,8 @@ bool MMU2::get_response() {
void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
constexpr xyz_pos_t park_point = NOZZLE_PARK_POINT;
bool response = false, mmu_print_saved = false;
bool response = false;
mmu_print_saved = false;
xyz_pos_t resume_position;
celsius_t resume_hotend_temp = thermalManager.degTargetHotend(active_extruder);
@@ -823,7 +815,8 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
resume_hotend_temp = thermalManager.degTargetHotend(active_extruder);
resume_position = current_position;
if (move_axes && all_axes_homed()) nozzle.park(0, park_point);
if (move_axes && all_axes_homed())
nozzle.park(0, park_point /*= NOZZLE_PARK_POINT*/);
if (turn_off_nozzle) thermalManager.setTargetHotend(0, active_extruder);
@@ -831,12 +824,13 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
}
}
else if (mmu_print_saved) {
SERIAL_ECHOLNPGM("\nMMU starts responding");
SERIAL_ECHOLNPGM("MMU starts responding\n");
if (turn_off_nozzle && resume_hotend_temp) {
thermalManager.setTargetHotend(resume_hotend_temp, active_extruder);
LCD_MESSAGE(MSG_HEATING);
ERR_BUZZ();
while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(1000);
}
@@ -849,6 +843,7 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
if (move_axes && all_axes_homed()) {
// Move XY to starting position, then Z
do_blocking_move_to_xy(resume_position, feedRate_t(NOZZLE_PARK_XY_FEEDRATE));
// Move Z_AXIS to saved position
do_blocking_move_to_z(resume_position.z, feedRate_t(NOZZLE_PARK_Z_FEEDRATE));
}
@@ -883,24 +878,23 @@ void MMU2::filament_runout() {
}
// Slowly spin the extruder during C0
else {
while (planner.movesplanned() < 3)
unscaled_mmu2_e_move(0.25, MMM_TO_MMS(120), false);
while (planner.movesplanned() < 3) {
current_position.e += 0.25;
line_to_current_position(MMM_TO_MMS(120));
}
}
}
mmu2s_triggered = present;
}
bool MMU2::can_load() {
static const E_Step can_load_sequence[] PROGMEM = { MMU2_CAN_LOAD_SEQUENCE },
can_load_increment_sequence[] PROGMEM = { MMU2_CAN_LOAD_INCREMENT_SEQUENCE };
execute_extruder_sequence(can_load_sequence, COUNT(can_load_sequence));
execute_extruder_sequence((const E_Step *)can_load_sequence, COUNT(can_load_sequence));
int filament_detected_count = 0;
const int steps = (MMU2_CAN_LOAD_RETRACT) / (MMU2_CAN_LOAD_INCREMENT);
DEBUG_ECHOLNPGM("MMU can_load:");
for (uint8_t i = 0; i < steps; ++i) {
execute_extruder_sequence(can_load_increment_sequence, COUNT(can_load_increment_sequence));
LOOP_L_N(i, steps) {
execute_extruder_sequence((const E_Step *)can_load_increment_sequence, COUNT(can_load_increment_sequence));
check_filament(); // Don't trust the idle function
DEBUG_CHAR(mmu2s_triggered ? 'O' : 'o');
if (mmu2s_triggered) ++filament_detected_count;
@@ -918,7 +912,7 @@ void MMU2::filament_runout() {
#endif
// Load filament into MMU2
void MMU2::load_to_feeder(const uint8_t index) {
void MMU2::load_filament(const uint8_t index) {
if (!_enabled) return;
command(MMU_CMD_L0 + index);
@@ -929,7 +923,8 @@ void MMU2::load_to_feeder(const uint8_t index) {
/**
* Switch material and load to nozzle
*/
bool MMU2::load_to_nozzle(const uint8_t index) {
bool MMU2::load_filament_to_nozzle(const uint8_t index) {
if (!_enabled) return false;
if (thermalManager.tooColdToExtrude(active_extruder)) {
@@ -938,13 +933,6 @@ bool MMU2::load_to_nozzle(const uint8_t index) {
return false;
}
if (TERN0(MMU_IR_UNLOAD_MOVE, index != extruder) && FILAMENT_PRESENT()) {
DEBUG_ECHOLNPGM("Unloading\n");
ramming_sequence(); // Unloading instructions from printer side when operating LCD
while (FILAMENT_PRESENT()) // Filament present? Keep unloading.
unscaled_mmu2_e_move(-0.25, MMM_TO_MMS(120)); // 0.25mm is a guessed value. Adjust to preference.
}
stepper.disable_extruder();
command(MMU_CMD_T0 + index);
manage_response(true, true);
@@ -954,12 +942,23 @@ bool MMU2::load_to_nozzle(const uint8_t index) {
mmu_loop();
extruder = index;
active_extruder = 0;
load_to_nozzle_sequence();
load_to_nozzle();
mmu2_attn_buzz();
}
return success;
}
/**
* Load filament to nozzle of multimaterial printer
*
* This function is used only after T? (user select filament) and M600 (change filament).
* It is not used after T0 .. T4 command (select filament), in such case, G-code is responsible for loading
* filament to nozzle.
*/
void MMU2::load_to_nozzle() {
execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence));
}
bool MMU2::eject_filament(const uint8_t index, const bool recover) {
if (!_enabled) return false;
@@ -972,17 +971,20 @@ bool MMU2::eject_filament(const uint8_t index, const bool recover) {
LCD_MESSAGE(MSG_MMU2_EJECTING_FILAMENT);
unscaled_mmu2_e_move(-(MMU2_FILAMENTCHANGE_EJECT_FEED), MMM_TO_MMS(2500));
stepper.enable_extruder();
current_position.e -= MMU2_FILAMENTCHANGE_EJECT_FEED;
line_to_current_position(MMM_TO_MMS(2500));
planner.synchronize();
command(MMU_CMD_E0 + index);
manage_response(false, false);
if (recover) {
LCD_MESSAGE(MSG_MMU2_REMOVE_AND_CLICK);
LCD_MESSAGE(MSG_MMU2_EJECT_RECOVER);
mmu2_attn_buzz();
TERN_(HOST_PROMPT_SUPPORT, hostui.continue_prompt(GET_TEXT_F(MSG_MMU2_EJECT_RECOVER)));
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_MMU2_EJECT_RECOVER)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, F("MMU2 Eject Recover"), FPSTR(CONTINUE_STR)));
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(F("MMU2 Eject Recover")));
TERN_(HAS_RESUME_CONTINUE, wait_for_user_response());
mmu2_attn_buzz();
mmu2_attn_buzz(true);
command(MMU_CMD_R0);
manage_response(false, false);
@@ -1016,7 +1018,7 @@ bool MMU2::unload() {
}
// Unload sequence to optimize shape of the tip of the unloaded filament
ramming_sequence();
execute_extruder_sequence((const E_Step *)ramming_sequence, sizeof(ramming_sequence) / sizeof(E_Step));
command(MMU_CMD_U0);
manage_response(false, true);
@@ -1031,26 +1033,23 @@ bool MMU2::unload() {
return true;
}
void MMU2::ramming_sequence() {
static const E_Step sequence[] PROGMEM = { MMU2_RAMMING_SEQUENCE };
execute_extruder_sequence(sequence, COUNT(sequence));
}
void MMU2::load_to_nozzle_sequence() {
static const E_Step sequence[] PROGMEM = { MMU2_LOAD_TO_NOZZLE_SEQUENCE };
execute_extruder_sequence(sequence, COUNT(sequence));
}
void MMU2::execute_extruder_sequence(const E_Step * sequence, int steps) {
planner.synchronize();
stepper.enable_extruder();
const E_Step *step = sequence;
const E_Step* step = sequence;
for (uint8_t i = 0; i < steps; ++i) {
LOOP_L_N(i, steps) {
const float es = pgm_read_float(&(step->extrude));
const feedRate_t fr_mm_m = pgm_read_float(&(step->feedRate));
DEBUG_ECHO_MSG("E step ", es, "/", fr_mm_m);
unscaled_mmu2_e_move(es, MMM_TO_MMS(fr_mm_m));
current_position.e += es;
line_to_current_position(MMM_TO_MMS(fr_mm_m));
planner.synchronize();
step++;
}
+43 -44
View File
@@ -23,8 +23,6 @@
/**
* feature/pause.cpp - Pause feature support functions
* This may be combined with related G-codes if features are consolidated.
*
* Note: Calls to ui.pause_show_message are passed to either ExtUI or MarlinUI.
*/
#include "../inc/MarlinConfigPre.h"
@@ -62,6 +60,8 @@
#if ENABLED(EXTENSIBLE_UI)
#include "../lcd/extui/ui_api.h"
#elif ENABLED(DWIN_LCD_PROUI)
#include "../lcd/e3v2/proui/dwin.h"
#endif
#include "../lcd/marlinui.h"
@@ -89,11 +89,9 @@ static xyze_pos_t resume_position;
PauseMode pause_mode = PAUSE_MODE_PAUSE_PRINT;
#endif
#if ENABLED(CONFIGURE_FILAMENT_CHANGE)
fil_change_settings_t fc_settings[EXTRUDERS];
#endif
fil_change_settings_t fc_settings[EXTRUDERS];
#if HAS_MEDIA
#if ENABLED(SDSUPPORT)
#include "../sd/cardreader.h"
#endif
@@ -148,7 +146,7 @@ static bool ensure_safe_temperature(const bool wait=true, const PauseMode mode=P
thermalManager.setTargetHotend(thermalManager.extrude_min_temp, active_extruder);
#endif
ui.pause_show_message(PAUSE_MESSAGE_HEATING, mode);
ui.pause_show_message(PAUSE_MESSAGE_HEATING, mode); UNUSED(mode);
if (wait) return thermalManager.wait_for_hotend(active_extruder);
@@ -203,7 +201,7 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load
KEEPALIVE_STATE(PAUSED_FOR_USER);
wait_for_user = true; // LCD click or M108 will clear this
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_FILAMENTLOAD)));
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(F("Load Filament")));
#if ENABLED(HOST_PROMPT_SUPPORT)
const char tool = '0' + TERN0(MULTI_FILAMENT_SENSOR, active_extruder);
@@ -212,7 +210,7 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load
while (wait_for_user) {
impatient_beep(max_beep_count);
#if ALL(FILAMENT_CHANGE_RESUME_ON_INSERT, FILAMENT_RUNOUT_SENSOR)
#if BOTH(FILAMENT_CHANGE_RESUME_ON_INSERT, FILAMENT_RUNOUT_SENSOR)
#if MULTI_FILAMENT_SENSOR
LOOP_S_LE_N(i, 1, NUM_RUNOUT_SENSORS) {
pin_t pin;
@@ -245,8 +243,6 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load
TERN_(BELTPRINTER, do_blocking_move_to_xy(0.00, 50.00));
TERN_(MPCTEMP, MPC::e_paused = true);
// Slow Load filament
if (slow_load_length) unscaled_e_move(slow_load_length, FILAMENT_CHANGE_SLOW_LOAD_FEEDRATE);
@@ -273,7 +269,7 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load
if (show_lcd) ui.pause_show_message(PAUSE_MESSAGE_PURGE);
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE)));
TERN_(HOST_PROMPT_SUPPORT, hostui.continue_prompt(GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE), FPSTR(CONTINUE_STR)));
wait_for_user = true; // A click or M108 breaks the purge_length loop
for (float purge_count = purge_length; purge_count > 0 && wait_for_user; --purge_count)
unscaled_e_move(1, ADVANCED_PAUSE_PURGE_FEEDRATE);
@@ -297,8 +293,8 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load
// Show "Purge More" / "Resume" menu and wait for reply
KEEPALIVE_STATE(PAUSED_FOR_USER);
wait_for_user = false;
#if ANY(HAS_MARLINUI_MENU, EXTENSIBLE_UI)
ui.pause_show_message(PAUSE_MESSAGE_OPTION); // MarlinUI and MKS UI also set PAUSE_RESPONSE_WAIT_FOR
#if EITHER(HAS_MARLINUI_MENU, DWIN_LCD_PROUI)
ui.pause_show_message(PAUSE_MESSAGE_OPTION); // Also sets PAUSE_RESPONSE_WAIT_FOR
#else
pause_menu_response = PAUSE_RESPONSE_WAIT_FOR;
#endif
@@ -310,9 +306,6 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load
} while (TERN0(M600_PURGE_MORE_RESUMABLE, pause_menu_response == PAUSE_RESPONSE_EXTRUDE_MORE));
#endif
TERN_(MPCTEMP, MPC::e_paused = false);
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_end());
return true;
@@ -342,18 +335,18 @@ inline void disable_active_extruder() {
*/
bool unload_filament(const_float_t unload_length, const bool show_lcd/*=false*/,
const PauseMode mode/*=PAUSE_MODE_PAUSE_PRINT*/
#if ALL(FILAMENT_UNLOAD_ALL_EXTRUDERS, MIXING_EXTRUDER)
#if BOTH(FILAMENT_UNLOAD_ALL_EXTRUDERS, MIXING_EXTRUDER)
, const_float_t mix_multiplier/*=1.0*/
#endif
) {
DEBUG_SECTION(uf, "unload_filament", true);
DEBUG_ECHOLNPGM("... unloadlen:", unload_length, " showlcd:", show_lcd, " mode:", mode
#if ALL(FILAMENT_UNLOAD_ALL_EXTRUDERS, MIXING_EXTRUDER)
#if BOTH(FILAMENT_UNLOAD_ALL_EXTRUDERS, MIXING_EXTRUDER)
, " mixmult:", mix_multiplier
#endif
);
#if !ALL(FILAMENT_UNLOAD_ALL_EXTRUDERS, MIXING_EXTRUDER)
#if !BOTH(FILAMENT_UNLOAD_ALL_EXTRUDERS, MIXING_EXTRUDER)
constexpr float mix_multiplier = 1.0f;
#endif
@@ -413,6 +406,8 @@ bool pause_print(const_float_t retract, const xyz_pos_t &park_point, const bool
DEBUG_SECTION(pp, "pause_print", true);
DEBUG_ECHOLNPGM("... park.x:", park_point.x, " y:", park_point.y, " z:", park_point.z, " unloadlen:", unload_length, " showlcd:", show_lcd DXC_SAY);
UNUSED(show_lcd);
if (did_pause_print) return false; // already paused
#if ENABLED(HOST_ACTION_COMMANDS)
@@ -424,12 +419,13 @@ bool pause_print(const_float_t retract, const xyz_pos_t &park_point, const bool
#endif
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_open(PROMPT_INFO, F("Pause"), FPSTR(DISMISS_STR)));
TERN_(DWIN_LCD_PROUI, DWIN_Print_Pause());
// Indicate that the printer is paused
++did_pause_print;
// Pause the print job and timer
#if HAS_MEDIA
#if ENABLED(SDSUPPORT)
const bool was_sd_printing = IS_SD_PRINTING();
if (was_sd_printing) {
card.pauseSDPrint();
@@ -454,7 +450,7 @@ bool pause_print(const_float_t retract, const xyz_pos_t &park_point, const bool
// Wait for buffered blocks to complete
planner.synchronize();
#if ALL(ADVANCED_PAUSE_FANS_PAUSE, HAS_FAN)
#if ENABLED(ADVANCED_PAUSE_FANS_PAUSE) && HAS_FAN
thermalManager.set_fans_paused(true);
#endif
@@ -474,7 +470,6 @@ bool pause_print(const_float_t retract, const xyz_pos_t &park_point, const bool
// 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 (!do_park) LCD_MESSAGE(MSG_PARK_FAILED);
#if ENABLED(DUAL_X_CARRIAGE)
const int8_t saved_ext = active_extruder;
@@ -486,7 +481,9 @@ bool pause_print(const_float_t retract, const xyz_pos_t &park_point, const bool
if (unload_length)
unload_filament(unload_length, show_lcd, PAUSE_MODE_CHANGE_FILAMENT);
TERN_(DUAL_X_CARRIAGE, set_duplication_enabled(saved_ext_dup_mode, saved_ext));
#if ENABLED(DUAL_X_CARRIAGE)
set_duplication_enabled(saved_ext_dup_mode, saved_ext);
#endif
// Disable the Extruder for manual change
disable_active_extruder();
@@ -513,7 +510,7 @@ void show_continue_prompt(const bool is_reload) {
ui.pause_show_message(is_reload ? PAUSE_MESSAGE_INSERT : PAUSE_MESSAGE_WAITING);
SERIAL_ECHO_START();
SERIAL_ECHO(is_reload ? F(_PMSG(STR_FILAMENT_CHANGE_INSERT) "\n") : F(_PMSG(STR_FILAMENT_CHANGE_WAIT) "\n"));
SERIAL_ECHOF(is_reload ? F(_PMSG(STR_FILAMENT_CHANGE_INSERT) "\n") : F(_PMSG(STR_FILAMENT_CHANGE_WAIT) "\n"));
}
void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep_count/*=0*/ DXC_ARGS) {
@@ -539,7 +536,7 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep
// Wait for filament insert by user and press button
KEEPALIVE_STATE(PAUSED_FOR_USER);
TERN_(HOST_PROMPT_SUPPORT, hostui.continue_prompt(GET_TEXT_F(MSG_NOZZLE_PARKED)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_NOZZLE_PARKED), FPSTR(CONTINUE_STR)));
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_NOZZLE_PARKED)));
wait_for_user = true; // LCD click or M108 will clear this
while (wait_for_user) {
@@ -557,17 +554,15 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_HEATER_TIMEOUT), GET_TEXT_F(MSG_REHEAT)));
#if ENABLED(TOUCH_UI_FTDI_EVE)
ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_FTDI_HEATER_TIMEOUT));
#elif ENABLED(EXTENSIBLE_UI)
ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_HEATER_TIMEOUT));
#endif
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_HEATER_TIMEOUT)));
TERN_(HAS_RESUME_CONTINUE, wait_for_user_response(0, true)); // Wait for LCD click or M108
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_INFO, GET_TEXT_F(MSG_REHEATING)));
LCD_MESSAGE(MSG_REHEATING);
TERN_(EXTENSIBLE_UI, ExtUI::onStatusChanged(GET_TEXT_F(MSG_REHEATING)));
TERN_(DWIN_LCD_PROUI, LCD_MESSAGE(MSG_REHEATING));
// Re-enable the heaters if they timed out
HOTEND_LOOP() thermalManager.reset_hotend_idle_timer(e);
@@ -583,12 +578,9 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep
HOTEND_LOOP() thermalManager.heater_idle[e].start(nozzle_timeout);
TERN_(HOST_PROMPT_SUPPORT, hostui.continue_prompt(GET_TEXT_F(MSG_REHEATDONE)));
#if ENABLED(EXTENSIBLE_UI)
ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_REHEATDONE));
#else
LCD_MESSAGE(MSG_REHEATDONE);
#endif
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_REHEATDONE), FPSTR(CONTINUE_STR)));
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_REHEATDONE)));
TERN_(DWIN_LCD_PROUI, LCD_MESSAGE(MSG_REHEATDONE));
IF_DISABLED(PAUSE_REHEAT_FAST_RESUME, wait_for_user = true);
@@ -597,7 +589,9 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep
}
idle_no_sleep();
}
TERN_(DUAL_X_CARRIAGE, set_duplication_enabled(saved_ext_dup_mode, saved_ext));
#if ENABLED(DUAL_X_CARRIAGE)
set_duplication_enabled(saved_ext_dup_mode, saved_ext);
#endif
}
/**
@@ -689,7 +683,7 @@ void resume_print(const_float_t slow_load_length/*=0*/, const_float_t fast_load_
#endif
// If resume_position is negative
//if (resume_position.e < 0) unscaled_e_move(resume_position.e, feedRate_t(PAUSE_PARK_RETRACT_FEEDRATE));
if (resume_position.e < 0) unscaled_e_move(resume_position.e, feedRate_t(PAUSE_PARK_RETRACT_FEEDRATE));
#ifdef ADVANCED_PAUSE_RESUME_PRIME
if (ADVANCED_PAUSE_RESUME_PRIME != 0)
unscaled_e_move(ADVANCED_PAUSE_RESUME_PRIME, feedRate_t(ADVANCED_PAUSE_PURGE_FEEDRATE));
@@ -698,7 +692,7 @@ void resume_print(const_float_t slow_load_length/*=0*/, const_float_t fast_load_
// Now all extrusion positions are resumed and ready to be confirmed
// Set extruder to saved position
planner.set_e_position_mm((destination.e = current_position.e = resume_position.e));
sync_plan_position_e();
ui.pause_show_message(PAUSE_MESSAGE_STATUS);
#ifdef ACTION_ON_RESUMED
@@ -714,7 +708,7 @@ void resume_print(const_float_t slow_load_length/*=0*/, const_float_t fast_load_
// Resume the print job timer if it was running
if (print_job_timer.isPaused()) print_job_timer.start();
#if HAS_MEDIA
#if ENABLED(SDSUPPORT)
if (did_pause_print) {
--did_pause_print;
card.startOrResumeFilePrinting();
@@ -729,8 +723,13 @@ void resume_print(const_float_t slow_load_length/*=0*/, const_float_t fast_load_
TERN_(HAS_FILAMENT_SENSOR, runout.reset());
ui.reset_status();
ui.return_to_status();
#if ENABLED(DWIN_LCD_PROUI)
DWIN_Print_Resume();
HMI_ReturnScreen();
#else
ui.reset_status();
ui.return_to_status();
#endif
}
#endif // ADVANCED_PAUSE_FEATURE
-1
View File
@@ -122,7 +122,6 @@ void Power::power_off() {
TERN_(HAS_SUICIDE, suicide());
if (!psu_on) return;
SERIAL_ECHOLNPGM(STR_POWEROFF);
SERIAL_ECHOLNPGM(STR_POWEROFF);
+24 -28
View File
@@ -40,15 +40,15 @@ RunoutMode FilamentMonitorBase::mode[NUM_RUNOUT_SENSORS]; // Initialized by sett
#endif
#if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
#define DEBUG_TOOLCHANGE_MIGRATION_FEATURE
#include "../module/tool_change.h"
#define DEBUG_OUT ENABLED(DEBUG_TOOLCHANGE_MIGRATION_FEATURE)
#include "../core/debug_out.h"
#endif
float RunoutResponseDelayed::runout_distance_mm[NUM_RUNOUT_SENSORS]; // Initialized by settings.load
countdown_t RunoutResponseDelayed::mm_countdown;
volatile float RunoutResponseDelayed::runout_mm_countdown[NUM_RUNOUT_SENSORS];
uint8_t FilamentSensorCore::motion_detected;
int8_t RunoutResponseDelayed::runout_count[NUM_RUNOUT_SENSORS]; // = 0
//
// Filament Runout event handler
@@ -63,6 +63,8 @@ int8_t RunoutResponseDelayed::runout_count[NUM_RUNOUT_SENSORS]; // = 0
#if ENABLED(EXTENSIBLE_UI)
#include "../lcd/extui/ui_api.h"
#elif ENABLED(DWIN_LCD_PROUI)
#include "../lcd/e3v2/proui/dwin.h"
#endif
void event_filament_runout(const uint8_t extruder) {
@@ -81,6 +83,7 @@ void event_filament_runout(const uint8_t extruder) {
#endif
TERN_(EXTENSIBLE_UI, ExtUI::onFilamentRunout(ExtUI::getTool(extruder)));
TERN_(DWIN_LCD_PROUI, DWIN_FilamentRunout(extruder));
#if ANY(HOST_PROMPT_SUPPORT, HOST_ACTION_COMMANDS, MULTI_FILAMENT_SENSOR)
const char tool = '0' + TERN0(MULTI_FILAMENT_SENSOR, extruder);
@@ -94,16 +97,12 @@ void event_filament_runout(const uint8_t extruder) {
const bool run_runout_script = !runout.host_handling;
#if ENABLED(HOST_ACTION_COMMANDS)
const bool park_or_pause = (false
#ifdef FILAMENT_RUNOUT_SCRIPT
|| strstr(FILAMENT_RUNOUT_SCRIPT, "M600")
if (run_runout_script
&& ( strstr(FILAMENT_RUNOUT_SCRIPT, "M600")
|| strstr(FILAMENT_RUNOUT_SCRIPT, "M125")
|| TERN0(ADVANCED_PAUSE_FEATURE, strstr(FILAMENT_RUNOUT_SCRIPT, "M25"))
#endif
);
if (run_runout_script && park_or_pause) {
)
) {
hostui.paused(false);
}
else {
@@ -120,27 +119,24 @@ void event_filament_runout(const uint8_t extruder) {
SERIAL_ECHOPGM(" " ACTION_REASON_ON_FILAMENT_RUNOUT " ");
SERIAL_CHAR(tool);
SERIAL_EOL();
#endif // HOST_ACTION_COMMANDS
#ifdef FILAMENT_RUNOUT_SCRIPT
if (run_runout_script) {
#if MULTI_FILAMENT_SENSOR
MString<strlen(FILAMENT_RUNOUT_SCRIPT)> script;
script.setf(F(FILAMENT_RUNOUT_SCRIPT), C(tool));
#if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG)
SERIAL_ECHOLNPGM("Runout Command: ", &script);
#endif
queue.inject(&script);
#else
#if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG)
SERIAL_ECHOPGM("Runout Command: ");
SERIAL_ECHOLNPGM(FILAMENT_RUNOUT_SCRIPT);
#endif
queue.inject(F(FILAMENT_RUNOUT_SCRIPT));
if (run_runout_script) {
#if MULTI_FILAMENT_SENSOR
char script[strlen(FILAMENT_RUNOUT_SCRIPT) + 1];
sprintf_P(script, PSTR(FILAMENT_RUNOUT_SCRIPT), tool);
#if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG)
SERIAL_ECHOLNPGM("Runout Command: ", script);
#endif
}
#endif
queue.inject(script);
#else
#if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG)
SERIAL_ECHOPGM("Runout Command: ");
SERIAL_ECHOLNPGM(FILAMENT_RUNOUT_SCRIPT);
#endif
queue.inject(F(FILAMENT_RUNOUT_SCRIPT));
#endif
}
}
#endif // HAS_FILAMENT_SENSOR
+77 -102
View File
@@ -30,8 +30,7 @@
#include "../module/planner.h"
#include "../module/stepper.h" // for block_t
#include "../gcode/queue.h"
#include "../feature/pause.h" // for did_pause_print
#include "../MarlinCore.h" // for printingIsActive()
#include "../feature/pause.h"
#include "../inc/MarlinConfig.h"
@@ -44,17 +43,7 @@
#define FILAMENT_RUNOUT_THRESHOLD 5
#endif
typedef Flags<
#if NUM_MOTION_SENSORS > NUM_RUNOUT_SENSORS
NUM_MOTION_SENSORS
#else
NUM_RUNOUT_SENSORS
#endif
> runout_flags_t;
void event_filament_runout(const uint8_t extruder);
inline bool should_monitor_runout() { return did_pause_print || printingIsActive(); }
template<class RESPONSE_T, class SENSOR_T>
class TFilamentMonitor;
@@ -133,33 +122,43 @@ class TFilamentMonitor : public FilamentMonitorBase {
// Give the response a chance to update its counter.
static void run() {
if (enabled && !filament_ran_out && should_monitor_runout()) {
if (enabled[active_extruder] && mode[active_extruder] != RM_NONE && !filament_ran_out && (printingIsActive() || did_pause_print)) {
cli(); // Prevent RunoutResponseDelayed::block_completed from accumulating here
response.run();
sensor.run();
const runout_flags_t runout_flags = response.has_run_out();
const uint8_t runout_flags = response.has_run_out();
sei();
#if MULTI_FILAMENT_SENSOR
#if ENABLED(WATCH_ALL_RUNOUT_SENSORS)
const bool ran_out = bool(runout_flags); // any sensor triggers
const bool ran_out = !!runout_flags; // any sensor triggers
uint8_t extruder = 0;
if (ran_out) while (!runout_flags.test(extruder)) extruder++;
if (ran_out) {
uint8_t bitmask = runout_flags;
while (!(bitmask & 1)) {
bitmask >>= 1;
extruder++;
}
}
#else
const bool ran_out = runout_flags[active_extruder]; // suppress non active extruders
const bool ran_out = TEST(runout_flags, active_extruder); // suppress non active extruders
uint8_t extruder = active_extruder;
#endif
#else
const bool ran_out = bool(runout_flags);
const bool ran_out = !!runout_flags;
uint8_t extruder = active_extruder;
#endif
if (ran_out) {
#if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG)
#if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG)
if (runout_flags) {
SERIAL_ECHOPGM("Runout Sensors: ");
for (uint8_t i = 0; i < 8; ++i) SERIAL_CHAR('0' + char(runout_flags[i]));
SERIAL_ECHOLNPGM(" -> ", extruder, " RUN OUT");
#endif
LOOP_L_N(i, 8) SERIAL_ECHO('0' + TEST(runout_flags, i));
SERIAL_ECHOPGM(" -> ", extruder);
if (ran_out) SERIAL_ECHOPGM(" RUN OUT");
SERIAL_EOL();
}
#endif
if (ran_out) {
filament_ran_out = true;
event_filament_runout(extruder);
planner.synchronize();
@@ -211,7 +210,7 @@ class FilamentSensorBase {
#undef _INIT_RUNOUT_PIN
#undef INIT_RUNOUT_PIN
}
// Return a bitmask of runout pin states
static uint8_t poll_runout_pins() {
@@ -222,26 +221,10 @@ class FilamentSensorBase {
// Return a bitmask of runout flag states (1 bits always indicates runout)
static uint8_t poll_runout_states() {
#define _INVERT_BIT(N) | (runout.out_state(N-1) ? 0 : _BV(N-1))
return poll_runout_pins() ^ uint8_t(0 REPEAT_1(NUM_RUNOUT_SENSORS, _INVERT_BIT));
#undef _INVERT_BIT
#define _OR_INVERT(N) | (runout.out_state(N-1) ? 0 : _BV(N-1))
return poll_runout_pins() ^ uint8_t(0 REPEAT_1(NUM_RUNOUT_SENSORS, _OR_INVERT));
#undef _OR_INVERT
}
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
// Return a bitmask of motion pin states
static uint8_t poll_motion_pins() {
#define _OR_MOTION(N) | (READ(FIL_MOTION##N##_PIN) ? _BV((N) - 1) : 0)
return (0 REPEAT_1(NUM_MOTION_SENSORS, _OR_MOTION));
#undef _OR_MOTION
}
// Return a bitmask of motion flag states (1 bits always indicates runout)
static uint8_t poll_motion_states() {
#define _OR_MOTION(N) | (FIL_MOTION##N##_STATE ? 0 : _BV(N - 1))
return poll_motion_pins() ^ uint8_t(0 REPEAT_1(NUM_MOTION_SENSORS, _OR_MOTION));
#undef _OR_MOTION
}
#endif
};
class FilamentSensorCore : public FilamentSensorBase {
@@ -249,27 +232,27 @@ class FilamentSensorCore : public FilamentSensorBase {
static uint8_t motion_detected;
static bool poll_runout_state(const uint8_t extruder) {
const uint8_t runout_states = poll_runout_states();
#if MULTI_FILAMENT_SENSOR
if ( !TERN0(DUAL_X_CARRIAGE, idex_is_duplicating())
&& !TERN0(MULTI_NOZZLE_DUPLICATION, extruder_duplication_enabled)
) return TEST(runout_states, extruder); // A specific extruder ran out
#else
UNUSED(extruder);
#endif
return !!runout_states; // Any extruder ran out
}
const uint8_t runout_states = poll_runout_states();
#if MULTI_FILAMENT_SENSOR
if ( !TERN0(DUAL_X_CARRIAGE, idex_is_duplicating())
&& !TERN0(MULTI_NOZZLE_DUPLICATION, extruder_duplication_enabled)
) return TEST(runout_states, extruder); // A specific extruder ran out
#else
UNUSED(extruder);
#endif
return !!runout_states; // Any extruder ran out
}
static void poll_motion_sensor() {
static uint8_t old_state;
const uint8_t new_state = TERN(FILAMENT_SWITCH_AND_MOTION, poll_motion_pins, poll_runout_pins)(),
change = old_state ^ new_state;
old_state = new_state;
static void poll_motion_sensor() {
static uint8_t old_state;
const uint8_t new_state = poll_runout_pins(),
change = old_state ^ new_state;
old_state = new_state;
#if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG)
if (change) {
SERIAL_ECHOPGM("Motion detected:");
for(uint8_t e = 0; e < NUM_RUNOUT_SENSORS; ++e)
LOOP_L_N(e, NUM_RUNOUT_SENSORS)
if (TEST(change, e)) SERIAL_CHAR(' ', '0' + e);
SERIAL_EOL();
}
@@ -278,30 +261,32 @@ class FilamentSensorCore : public FilamentSensorBase {
motion_detected |= change;
}
public:
static void block_completed(const block_t * const b) {
// If the sensor wheel has moved since the last call to
// this method reset the runout counter for the extruder.
if (TEST(motion_detected, b->extruder))
TERN(FILAMENT_SWITCH_AND_MOTION, filament_motion_present, filament_present)(b->extruder);
public:
static void block_completed(const block_t * const b) {
if (runout.mode[active_extruder] != RM_MOTION_SENSOR) return;
// Clear motion triggers for next block
motion_detected = 0;
}
// If the sensor wheel has moved since the last call to
// this method reset the runout counter for the extruder.
if (TEST(motion_detected, b->extruder))
filament_present(b->extruder);
// Clear motion triggers for next block
motion_detected = 0;
}
static void run() {
if (runout.mode[active_extruder] == RM_MOTION_SENSOR) {
poll_motion_sensor();
}
else if (runout.mode[active_extruder] != RM_NONE) {
for(uint8_t s = 0; s < NUM_RUNOUT_SENSORS; ++s) {
LOOP_L_N(s, NUM_RUNOUT_SENSORS) {
const bool out = poll_runout_state(s);
if (!out) filament_present(s);
#if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG)
static uint8_t was_out; // = 0
if (out != TEST(was_out, s)) {
TBI(was_out, s);
SERIAL_ECHOLN(F("Filament Sensor "), AS_DIGIT(s), out ? F(" OUT") : F(" IN"));
SERIAL_ECHOLNF(F("Filament Sensor "), AS_DIGIT(s), out ? F(" OUT") : F(" IN"));
}
#endif
}
@@ -309,34 +294,22 @@ class FilamentSensorCore : public FilamentSensorBase {
}
};
/********************************* RESPONSE TYPE *********************************/
typedef struct {
float runout[NUM_RUNOUT_SENSORS];
Flags<NUM_RUNOUT_SENSORS> runout_reset; // Reset runout later
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
float motion[NUM_MOTION_SENSORS];
Flags<NUM_MOTION_SENSORS> motion_reset; // Reset motion later
#endif
} countdown_t;
/********************************* RESPONSE TYPE *********************************/
// RunoutResponseDelayed triggers a runout event only if the length
// of filament specified by FIL_RUNOUT_DISTANCE_MM has been fed
// during a runout condition.
class RunoutResponseDelayed {
private:
static countdown_t mm_countdown;
static volatile float runout_mm_countdown[NUM_RUNOUT_SENSORS];
public:
static float runout_distance_mm[NUM_RUNOUT_SENSORS];
static int8_t runout_count[NUM_RUNOUT_SENSORS];
static void reset() {
for (uint8_t i = 0; i < NUM_RUNOUT_SENSORS; ++i) filament_present(i);
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
for (uint8_t i = 0; i < NUM_MOTION_SENSORS; ++i) filament_motion_present(i);
#endif
}
static void reset() {
LOOP_L_N(i, NUM_RUNOUT_SENSORS) filament_present(i);
}
static void run() {
#if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG)
@@ -344,27 +317,29 @@ class RunoutResponseDelayed {
const millis_t ms = millis();
if (ELAPSED(ms, t)) {
t = millis() + 1000UL;
for(uint8_t i; i < NUM_RUNOUT_SENSORS; ++i)
SERIAL_ECHO(i ? F(", ") : F("Remaining mm: "), mm_countdown[i]);
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
for (uint8_t i = 0; i < NUM_MOTION_SENSORS; ++i)
SERIAL_ECHO(i ? F(", ") : F("Motion remaining mm: "), mm_countdown.motion[i]);
#endif
LOOP_L_N(i, NUM_RUNOUT_SENSORS)
SERIAL_ECHOF(i ? F(", ") : F("Remaining mm: "), runout_mm_countdown[i]);
SERIAL_EOL();
}
#endif
}
static runout_flags_t has_run_out() {
runout_flags_t runout_flags{0};
for (uint8_t i = 0; i < NUM_RUNOUT_SENSORS; ++i) if (runout_count[i] < 0) runout_flags.set(i);
return runout_flags;
static uint8_t has_run_out() {
uint8_t runout_flags = 0;
LOOP_L_N(i, NUM_RUNOUT_SENSORS) if (runout_mm_countdown[i] < 0) SBI(runout_flags, i);
return runout_flags;
}
static void block_completed(const block_t * const) { }
static void filament_present(const uint8_t extruder) {
runout_mm_countdown[extruder] = runout_distance_mm[extruder];
}
static void filament_present(const uint8_t extruder) {
runout_count[extruder] = runout_distance_mm[extruder];
static void block_completed(const block_t * const b) {
if (b->steps.x || b->steps.y || b->steps.z || did_pause_print) { // Allow pause purge move to re-trigger runout state
// Only trigger on extrusion with XYZ movement to allow filament change and retract/recover.
const uint8_t e = b->extruder;
const int32_t steps = b->steps.e;
runout_mm_countdown[e] -= (TEST(b->direction_bits, E_AXIS) ? -steps : steps) * planner.mm_per_step[E_AXIS_N(e)];
}
};
}
};
-3
View File
@@ -985,9 +985,6 @@ G29_TYPE GcodeSuite::G29() {
process_subcommands_now(F(EVENT_GCODE_AFTER_G29));
#endif
TERN_(HAS_DWIN_E3V2_BASIC, DWIN_LevelingDone());
TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone());
TERN_(HAS_MULTI_HOTEND, if (active_extruder != 0) tool_change(0));
probe.use_probing_tool(false);
report_current_position();
+1 -1
View File
@@ -66,7 +66,7 @@ void GcodeSuite::M111() {
SERIAL_ECHOPGM(STR_DEBUG_OFF);
#if !(defined(__AVR__) && defined(USBCON))
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
//SERIAL_ECHOPGM("\nBuffer Overruns: ", MYSERIAL1.buffer_overruns());
SERIAL_ECHOPGM("\nBuffer Overruns: ", MYSERIAL1.buffer_overruns());
#endif
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
SERIAL_ECHOPGM("\nFraming Errors: ", MYSERIAL1.framing_errors());
@@ -72,7 +72,6 @@ void GcodeSuite::M413_report(const bool forReplay/*=true*/) {
, " B", recovery.bed_temp_threshold
#endif
);
SERIAL_ECHO(" ; ");
serialprintln_onoff(recovery.enabled);
}
+14 -11
View File
@@ -63,23 +63,26 @@ void GcodeSuite::M591() {
}
}
else {
SERIAL_ECHO_START();
SERIAL_ECHOPGM("Filament runout ");
serialprint_onoff(runout.enabled[active_extruder]);
SERIAL_ECHOPGM(" ; Distance ", runout.runout_distance(active_extruder), "mm");
SERIAL_ECHOPGM(" ; Mode ", runout.mode[active_extruder]);
#if ENABLED(HOST_ACTION_COMMANDS)
SERIAL_ECHOPGM(" ; Host handling ");
serialprint_onoff(runout.host_handling);
#if DISABLED(SLIM_LCD_MENUS)
SERIAL_ECHO_START();
SERIAL_ECHOPGM("Filament runout ");
serialprint_onoff(runout.enabled[active_extruder]);
SERIAL_ECHOPGM(" ; Distance ", runout.runout_distance(active_extruder), "mm");
SERIAL_ECHOPGM(" ; Mode ", runout.mode[active_extruder]);
#if ENABLED(HOST_ACTION_COMMANDS)
SERIAL_ECHOPGM(" ; Host handling ");
serialprint_onoff(runout.host_handling);
#endif
SERIAL_EOL();
#else
M591_report(false);
#endif
SERIAL_EOL();
}
}
void GcodeSuite::M591_report(const bool forReplay/*=true*/) {
TERN_(MARLIN_SMALL_BUILD, return);
report_heading_etc(forReplay, F(STR_FILAMENT_RUNOUT_SENSOR));
for(int e=0; e < NUM_RUNOUT_SENSORS; e++)
LOOP_S_L_N(e, 1, NUM_RUNOUT_SENSORS)
SERIAL_ECHOLNPGM(
" M591"
#if MULTI_FILAMENT_SENSOR
+57 -78
View File
@@ -75,14 +75,26 @@ GcodeSuite gcode;
millis_t GcodeSuite::previous_move_ms = 0,
GcodeSuite::max_inactive_time = 0;
#if HAS_DISABLE_IDLE_AXES
millis_t GcodeSuite::stepper_inactive_time = SEC_TO_MS(DEFAULT_STEPPER_TIMEOUT_SEC);
#if HAS_DISABLE_INACTIVE_AXIS
millis_t GcodeSuite::stepper_inactive_time = SEC_TO_MS(DEFAULT_STEPPER_DEACTIVE_TIME);
#endif
// Relative motion mode for each logical axis
relative_t GcodeSuite::axis_relative; // Init in constructor
static constexpr xyze_bool_t ar_init = AXIS_RELATIVE_MODES;
axis_bits_t GcodeSuite::axis_relative = 0 LOGICAL_AXIS_GANG(
| (ar_init.e << REL_E),
| (ar_init.x << REL_X),
| (ar_init.y << REL_Y),
| (ar_init.z << REL_Z),
| (ar_init.i << REL_I),
| (ar_init.j << REL_J),
| (ar_init.k << REL_K),
| (ar_init.u << REL_U),
| (ar_init.v << REL_V),
| (ar_init.w << REL_W)
);
#if ANY(HAS_AUTO_REPORTING, HOST_KEEPALIVE_FEATURE)
#if EITHER(HAS_AUTO_REPORTING, HOST_KEEPALIVE_FEATURE)
bool GcodeSuite::autoreport_paused; // = false
#endif
@@ -105,7 +117,8 @@ void GcodeSuite::report_heading(const bool forReplay, FSTR_P const fstr, const b
if (forReplay) return;
if (fstr) {
SERIAL_ECHO_START();
SERIAL_ECHO(F("; "), fstr);
SERIAL_ECHOPGM("; ");
SERIAL_ECHOF(fstr);
}
if (eol) { SERIAL_CHAR(':'); SERIAL_EOL(); }
}
@@ -122,16 +135,14 @@ void GcodeSuite::say_units() {
* Return -1 if the T parameter is out of range
*/
int8_t GcodeSuite::get_target_extruder_from_command() {
#if HAS_TOOLCHANGE
if (parser.seenval('T')) {
const int8_t e = parser.value_byte();
if (e < EXTRUDERS) return e;
SERIAL_ECHO_START();
SERIAL_CHAR('M'); SERIAL_ECHO(parser.codenum);
SERIAL_ECHOLNPGM(" " STR_INVALID_EXTRUDER " ", e);
return -1;
}
#endif
if (parser.seenval('T')) {
const int8_t e = parser.value_byte();
if (e < EXTRUDERS) return e;
SERIAL_ECHO_START();
SERIAL_CHAR('M'); SERIAL_ECHO(parser.codenum);
SERIAL_ECHOLNPGM(" " STR_INVALID_EXTRUDER " ", e);
return -1;
}
return active_extruder;
}
@@ -155,7 +166,7 @@ int8_t GcodeSuite::get_target_e_stepper_from_command(const int8_t dval/*=-1*/) {
}
/**
* Set XYZ...E destination and feedrate from the current G-Code command
* Set XYZ...E destination and feedrate from the current GCode command
*
* - Set destination from included axis codes
* - Set to current for missing axis codes
@@ -205,13 +216,13 @@ void GcodeSuite::get_destination_from_command() {
TERN_(LASER_FEATURE, cutter.feedrate_mm_m = MMS_TO_MMM(feedrate_mm_s));
}
#if ALL(PRINTCOUNTER, HAS_EXTRUDERS)
#if BOTH(PRINTCOUNTER, HAS_EXTRUDERS)
if (!DEBUGGING(DRYRUN) && !skip_move)
print_job_timer.incFilamentUsed(destination.e - current_position.e);
#endif
// Get ABCDHI mixing factors
#if ALL(MIXING_EXTRUDER, DIRECT_MIXING_IN_G1)
#if BOTH(MIXING_EXTRUDER, DIRECT_MIXING_IN_G1)
M165();
#endif
@@ -443,7 +454,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 61: G61(); break; // G61: Apply/restore saved coordinates.
#endif
#if ALL(PTC_PROBE, PTC_BED)
#if BOTH(PTC_PROBE, PTC_BED)
case 76: G76(); break; // G76: Calibrate first layer compensation values
#endif
@@ -461,7 +472,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
#endif
#if ENABLED(DEBUG_GCODE_PARSER)
case 800: parser.debug(); break; // G800: G-Code Parser Test for G
case 800: parser.debug(); break; // G800: GCode Parser Test for G
#endif
default: parser.unknown_command_warning(); break;
@@ -485,11 +496,11 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 7: M7(); break; // M7: Coolant Mist ON
#endif
#if ANY(AIR_ASSIST, COOLANT_FLOOD)
#if EITHER(AIR_ASSIST, COOLANT_FLOOD)
case 8: M8(); break; // M8: Air Assist / Coolant Flood ON
#endif
#if ANY(AIR_ASSIST, COOLANT_CONTROL)
#if EITHER(AIR_ASSIST, COOLANT_CONTROL)
case 9: M9(); break; // M9: Air Assist / Coolant OFF
#endif
@@ -508,7 +519,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 17: M17(); break; // M17: Enable all stepper motors
#if HAS_MEDIA
#if ENABLED(SDSUPPORT)
case 20: M20(); break; // M20: List SD card
case 21: M21(); break; // M21: Init SD card
case 22: M22(); break; // M22: Release SD card
@@ -529,12 +540,12 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 33: M33(); break; // M33: Get the long full path to a file or folder
#endif
#if ALL(SDCARD_SORT_ALPHA, SDSORT_GCODE)
#if BOTH(SDCARD_SORT_ALPHA, SDSORT_GCODE)
case 34: M34(); break; // M34: Set SD card sorting options
#endif
case 928: M928(); break; // M928: Start SD write
#endif // HAS_MEDIA
#endif // SDSUPPORT
case 31: M31(); break; // M31: Report time since the start of SD print or last M109
@@ -570,7 +581,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 102: M102(); break; // M102: Configure Bed Distance Sensor
#endif
#if HAS_HOTEND
#if HAS_EXTRUDERS
case 104: M104(); break; // M104: Set hot end temperature
case 109: M109(); break; // M109: Wait for hotend temperature to reach target
#endif
@@ -629,7 +640,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 154: M154(); break; // M154: Set position auto-report interval
#endif
#if ALL(AUTO_REPORT_TEMPERATURES, HAS_TEMP_SENSOR)
#if BOTH(AUTO_REPORT_TEMPERATURES, HAS_TEMP_SENSOR)
case 155: M155(); break; // M155: Set temperature auto-report interval
#endif
@@ -660,24 +671,11 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 82: M82(); break; // M82: Set E axis normal mode (same as other axes)
case 83: M83(); break; // M83: Set E axis relative mode
#endif
case 18: case 84: M18_M84(); break; // M18/M84: Disable Steppers / Set Timeout
case 85: M85(); break; // M85: Set inactivity stepper shutdown timeout
#if ENABLED(HOTEND_IDLE_TIMEOUT)
case 86: M86(); break; // M86: Set Hotend Idle Timeout
case 87: M87(); break; // M87: Cancel Hotend Idle Timeout
#endif
#if ENABLED(EDITABLE_STEPS_PER_UNIT)
case 92: M92(); break; // M92: Set the steps-per-unit for one or more axes
#endif
case 92: M92(); break; // M92: Set the steps-per-unit for one or more axes
case 114: M114(); break; // M114: Report current position
#if ENABLED(CAPABILITIES_REPORT)
case 115: M115(); break; // M115: Report capabilities
#endif
case 115: M115(); break; // M115: Report capabilities
case 117: TERN_(HAS_STATUS_MESSAGE, M117()); break; // M117: Set LCD message text, if possible
@@ -723,7 +721,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 204: M204(); break; // M204: Set acceleration
case 205: M205(); break; // M205: Set advanced settings
#if HAS_HOME_OFFSET
#if HAS_M206_COMMAND
case 206: M206(); break; // M206: Set home offsets
#endif
@@ -771,10 +769,6 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
#if ENABLED(BABYSTEPPING)
case 290: M290(); break; // M290: Babystepping
#if ENABLED(EP_BABYSTEPPING)
case 293: IF_DISABLED(EMERGENCY_PARSER, M293()); break; // M293: Babystep up
case 294: IF_DISABLED(EMERGENCY_PARSER, M294()); break; // M294: Babystep down
#endif
#endif
#if HAS_SOUND
@@ -801,7 +795,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 250: M250(); break; // M250: Set LCD contrast
#endif
#if ENABLED(EDITABLE_DISPLAY_TIMEOUT)
#if HAS_GCODE_M255
case 255: M255(); break; // M255: Set LCD Sleep/Backlight Timeout (Minutes)
#endif
@@ -842,7 +836,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 364: if (M364()) return; break; // M364: SCARA Psi pos3 (90 deg to Theta)
#endif
#if ANY(EXT_SOLENOID, MANUAL_SOLENOID_CONTROL)
#if EITHER(EXT_SOLENOID, MANUAL_SOLENOID_CONTROL)
case 380: M380(); break; // M380: Activate solenoid on active (or specified) extruder
case 381: M381(); break; // M381: Disable all solenoids or, if MANUAL_SOLENOID_CONTROL, active (or specified) solenoid
#endif
@@ -885,7 +879,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 425: M425(); break; // M425: Tune backlash compensation
#endif
#if HAS_HOME_OFFSET
#if HAS_M206_COMMAND
case 428: M428(); break; // M428: Apply current_position to home_offset
#endif
@@ -897,10 +891,6 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 486: M486(); break; // M486: Identify and cancel objects
#endif
#if ENABLED(FT_MOTION)
case 493: M493(); break; // M493: Fixed-Time Motion control
#endif
case 500: M500(); break; // M500: Store settings in EEPROM
case 501: M501(); break; // M501: Read settings from EEPROM
case 502: M502(); break; // M502: Revert to default settings
@@ -921,7 +911,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
#endif
#endif
#if HAS_MEDIA
#if ENABLED(SDSUPPORT)
case 524: M524(); break; // M524: Abort the current SD print job
#endif
@@ -944,19 +934,9 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 591: M591(); break; // M591 Configure filament runout detection
#endif
#if ENABLED(NONLINEAR_EXTRUSION)
case 592: M592(); break; // M592: Nonlinear Extrusion control
#endif
#if HAS_ZV_SHAPING
case 593: M593(); break; // M593: Input Shaping control
#endif
#if ENABLED(ADVANCED_PAUSE_FEATURE)
case 600: M600(); break; // M600: Pause for Filament Change
#if ENABLED(CONFIGURE_FILAMENT_CHANGE)
case 603: M603(); break; // M603: Configure Filament Change
#endif
case 603: M603(); break; // M603: Configure Filament Change
#endif
#if HAS_DUPLICATION_MODE
@@ -967,7 +947,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 665: M665(); break; // M665: Set Kinematics parameters
#endif
#if ANY(DELTA, HAS_EXTRA_ENDSTOPS)
#if ENABLED(DELTA) || HAS_EXTRA_ENDSTOPS
case 666: M666(); break; // M666: Set delta or multiple endstop adjustment
#endif
@@ -1008,7 +988,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
#if ANY(HAS_MOTOR_CURRENT_SPI, HAS_MOTOR_CURRENT_PWM, HAS_MOTOR_CURRENT_I2C, HAS_MOTOR_CURRENT_DAC)
case 907: M907(); break; // M907: Set digital trimpot motor current using axis codes.
#if ANY(HAS_MOTOR_CURRENT_SPI, HAS_MOTOR_CURRENT_DAC)
#if EITHER(HAS_MOTOR_CURRENT_SPI, HAS_MOTOR_CURRENT_DAC)
case 908: M908(); break; // M908: Control digital trimpot directly.
#if HAS_MOTOR_CURRENT_DAC
case 909: M909(); break; // M909: Print digipot/DAC current value
@@ -1046,7 +1026,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
#endif
#if ENABLED(DEBUG_GCODE_PARSER)
case 800: parser.debug(); break; // M800: G-Code Parser Test for M
case 800: parser.debug(); break; // M800: GCode Parser Test for M
#endif
#if ENABLED(GCODE_REPEAT_MARKERS)
@@ -1074,11 +1054,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 422: M422(); break; // M422: Set Z Stepper automatic alignment position using probe
#endif
#if ENABLED(OTA_FIRMWARE_UPDATE)
case 936: M936(); break; // M936: OTA update firmware.
#endif
#if SPI_FLASH_BACKUP
#if ALL(SPI_FLASH, SDSUPPORT, MARLIN_DEV_MODE)
case 993: M993(); break; // M993: Backup SPI Flash to SD
case 994: M994(); break; // M994: Load a Backup from SD to SPI Flash
#endif
@@ -1098,11 +1074,11 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 1000: M1000(); break; // M1000: [INTERNAL] Resume from power-loss
#endif
#if HAS_MEDIA
#if ENABLED(SDSUPPORT)
case 1001: M1001(); break; // M1001: [INTERNAL] Handle SD completion
#endif
#if DGUS_LCD_UI_MKS
#if ENABLED(DGUS_LCD_UI_MKS)
case 1002: M1002(); break; // M1002: [INTERNAL] Tool-change and Relative E Move
#endif
@@ -1141,7 +1117,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
if (!no_ok) queue.ok_to_send();
SERIAL_IMPL.msgDone(); // Call the msgDone serial hook to signal command processing done
SERIAL_OUT(msgDone); // Call the msgDone serial hook to signal command processing done
}
#if ENABLED(M100_FREE_MEMORY_DUMPER)
@@ -1188,7 +1164,10 @@ void GcodeSuite::process_subcommands_now(FSTR_P fgcode) {
for (;;) {
PGM_P const delim = strchr_P(pgcode, '\n'); // Get address of next newline
const size_t len = delim ? delim - pgcode : strlen_P(pgcode); // Get the command length
parser.parse(MString<MAX_CMD_SIZE>().setn_P(pgcode, len)); // Parse the command
char cmd[len + 1]; // Allocate a stack buffer
strncpy_P(cmd, pgcode, len); // Copy the command to the stack
cmd[len] = '\0'; // End with a nul
parser.parse(cmd); // Parse the command
process_parsed_command(true); // Process it (no "ok")
if (!delim) break; // Last command?
pgcode = delim + 1; // Get the next command
+1 -1
View File
@@ -258,9 +258,9 @@
* M554 - Get or set IP gateway. (Requires enabled Ethernet port)
* M569 - Enable stealthChop on an axis. (Requires at least one _DRIVER_TYPE to be TMC2130/2160/2208/2209/5130/5160)
* M575 - Change the serial baud rate. (Requires BAUD_RATE_GCODE)
* M591 - Configure Filament Runout Detection. (Requires FILAMENT_RUNOUT_SENSOR)
* M592 - Get or set nonlinear extrusion parameters. (Requires NONLINEAR_EXTRUSION)
* M593 - Get or set input shaping parameters. (Requires INPUT_SHAPING_[XY])
* M591 - Configure Filament Runout Detection. (Requires FILAMENT_RUNOUT_SENSOR)
* M600 - Pause for filament change: "M600 X<pos> Y<pos> Z<raise> E<first_retract> L<later_retract>". (Requires ADVANCED_PAUSE_FEATURE)
* M603 - Configure filament change: "M603 T<tool> U<unload_length> L<load_length>". (Requires ADVANCED_PAUSE_FEATURE)
* M605 - Set Dual X-Carriage movement mode: "M605 S<mode> [X<x_offset>] [R<temp_offset>]". (Requires DUAL_X_CARRIAGE)
-2
View File
@@ -373,8 +373,6 @@ void plan_arc(
planner.apply_leveling(raw);
#endif
hints.curve_radius = i > 1 ? radius : 0;
// calculate safe speed for stopping by the end of the arc
const float arc_mm_remaining = flat_mm - segment_mm * i;
hints.safe_exit_speed_sqr = _MIN(limiting_speed_sqr, 2 * limiting_accel * arc_mm_remaining);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -2902,7 +2902,7 @@
#define HAS_TEMPERATURE 1
#endif
#if HAS_TEMPERATURE && ANY(HAS_MARLINUI_MENU, HAS_DWIN_E3V2, HAS_DGUS_LCD_CLASSIC, DGUS_LCD_UI_CREALITY_TOUCH)
#if HAS_TEMPERATURE && ANY(HAS_MARLINUI_MENU, HAS_DWIN_E3V2, HAS_DGUS_LCD_CLASSIC)
#ifdef PREHEAT_10_LABEL
#define PREHEAT_COUNT 10
#elif defined(PREHEAT_9_LABEL)
+1387 -1408
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -42,7 +42,7 @@
* version was tagged.
*/
#ifndef STRING_DISTRIBUTION_DATE
#define STRING_DISTRIBUTION_DATE "2024-04-15"
#define STRING_DISTRIBUTION_DATE "2024-04-11"
#endif
/**
+1 -1
View File
@@ -99,7 +99,7 @@
#warning "Warning! Don't use dummy thermistors (998/999) for final build!"
#endif
#if NONE(HAS_RESUME_CONTINUE, HOST_PROMPT_SUPPORT, UNIT_TEST)
#if NONE(HAS_RESUME_CONTINUE, HOST_PROMPT_SUPPORT)
#warning "Your Configuration provides no method to acquire user feedback!"
#endif
+1 -7
View File
@@ -377,13 +377,7 @@ void MarlinUI::draw_kill_screen() {
void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
#if HAS_DISPLAY_SLEEP
void MarlinUI::sleep_display(const bool sleep/*=true*/) {
static bool asleep = false;
if (asleep != sleep){
sleep ? u8g.sleepOn() : u8g.sleepOff();
asleep = sleep;
}
}
void MarlinUI::sleep_display(const bool sleep/*=true*/) { sleep ? u8g.sleepOn() : u8g.sleepOff(); }
#endif
#if HAS_LCD_BRIGHTNESS
+3 -7
View File
@@ -2950,11 +2950,7 @@ void hmiControl() {
void hmiLeveling() {
popupWindowLeveling();
dwinUpdateLCD();
#if defined(MAIN_MENU_ITEM_1_GCODE)
queue.inject(F(MAIN_MENU_ITEM_1_GCODE));
#else
queue.inject(F("G28O\nG29\nG28\nG1Z0"));
#endif
queue.inject(F("G28O\nG29"));
}
#endif
@@ -4072,8 +4068,8 @@ void hmiInit() {
hmiSDCardInit();
for (uint16_t t = 0; t <= 100; t += 2) {
dwinIconShow(ICON, ICON_Bar, 15, 450);
dwinDrawRectangle(1, COLOR_BG_BLACK, 15 + t * 242 / 100, 450, 257, 470);
dwinIconShow(ICON, ICON_Bar, 15, 260);
dwinDrawRectangle(1, COLOR_BG_BLACK, 15 + t * 242 / 100, 260, 257, 280);
dwinUpdateLCD();
delay(20);
}
File diff suppressed because it is too large Load Diff
@@ -48,7 +48,6 @@ void dwinStartup() {
dwinFrameClear(COLOR_BG_BLACK); // MarlinUI handles the bootscreen so just clear here
dwinJPGShowAndCache(3);
dwinUpdateLCD();
dwinJPGShowAndCache(3);
}
/*---------------------------------------- Picture related functions ----------------------------------------*/
+2 -2
View File
@@ -108,8 +108,8 @@ void MarlinUI::clear_lcd() {
#define INFO_CENTER ((LCD_PIXEL_WIDTH) - 200 / 2)
#define VERSION_Y 84
#endif
dwinJPGShowAndCache(0); // Ensure DACAI stays on boot screen
dwinDrawString(false, font10x20, COLOR_YELLOW, COLOR_BG_BLACK, INFO_CENTER - (dwin_string.length * 10) / 2, 230, S(dwin_string.string()));
dwinDrawString(false, font10x20, COLOR_YELLOW, COLOR_BG_BLACK, INFO_CENTER - (dwin_string.length * 10) / 2, VERSION_Y, S(dwin_string.string()));
TERN_(SHOW_CUSTOM_BOOTSCREEN, safe_delay(CUSTOM_BOOTSCREEN_TIMEOUT));
clear_lcd();
+6 -11
View File
@@ -199,7 +199,7 @@ typedef struct {
} select_t;
select_t select_page{0}, select_print{0};
#if ENABLED(LCD_BED_TRAMMING) && DISABLED(BED_TRAMMING_USE_PROBE)
#if ENABLED(LCD_BED_TRAMMING)
constexpr float bed_tramming_inset_lfbr[] = BED_TRAMMING_INSET_LFRB;
#endif
@@ -2318,12 +2318,12 @@ void setMoveZ() { hmiValue.axis = Z_AXIS; setPFloatOnClick(Z_MIN_POS, Z_MAX_POS,
#if HAS_FILAMENT_SENSOR
void setRunoutEnable() {
runout.reset();
runout.enabled[0] = !runout.enabled[0];
Draw_Chkb_Line(CurrentMenu->line(), runout.enabled[0]);
DWIN_UpdateLCD();
toggleCheckboxLine(runout.enabled);
}
void ApplyRunoutDistance() { runout.set_runout_distance(MenuData.Value / MINUNITMULT); }
void SetRunoutDistance() { SetFloatOnClick(0, 999, UNITFDIGITS, runout.runout_distance(), ApplyRunoutDistance); }
#if HAS_FILAMENT_RUNOUT_DISTANCE
void applyRunoutDistance() { runout.set_runout_distance(menuData.value / MINUNITMULT); }
void setRunoutDistance() { setFloatOnClick(0, 999, UNITFDIGITS, runout.runout_distance(), applyRunoutDistance); }
#endif
#endif
#if ENABLED(CONFIGURE_FILAMENT_CHANGE)
@@ -2388,11 +2388,6 @@ void setFlow() { setPIntOnClick(FLOW_EDIT_MIN, FLOW_EDIT_MAX, []{ planner.refres
#if ENABLED(LCD_BED_TRAMMING)
void tramXY(const uint8_t point, float &x, float &y) {
#if ENABLED(BED_TRAMMING_USE_PROBE)
float bed_tramming_inset_lfbr[] = {X_MIN_BED + probe.min_x() + 0.01f, Y_MIN_BED + probe.min_y() + 0.01f,
X_MAX_BED - probe.max_x() - 0.01f, Y_MAX_BED - probe.max_y() - 0.01f };
#endif
switch (point) {
case 0:
LCD_MESSAGE(MSG_TRAM_FL);
+47 -27
View File
@@ -23,8 +23,8 @@
/**
* DWIN Endstops diagnostic page for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 1.4.3
* Date: 2023/05/10
* Version: 1.2.2
* Date: 2022/02/24
*/
#include "../../../inc/MarlinConfigPre.h"
@@ -36,9 +36,13 @@
#if HAS_ESDIAG
#include "endstop_diag.h"
#include "../../../core/types.h"
#include "../../marlinui.h"
#include "dwin.h"
#include "dwin_lcd.h"
#include "dwinui.h"
#include "dwin_popup.h"
#include "dwin.h"
#if HAS_FILAMENT_SENSOR
#include "../../../feature/runout.h"
@@ -48,45 +52,61 @@
#include "../../../module/probe.h"
#endif
ESDiag esDiag;
ESDiagClass ESDiag;
void draw_es_label(FSTR_P const flabel=nullptr) {
DWINUI::cursor.x = 40;
if (flabel) DWINUI::drawString(F(flabel));
DWINUI::drawString(F(": "));
DWINUI::moveBy(0, 25);
if (flabel) DWINUI::Draw_String(F(flabel));
DWINUI::Draw_String(F(": "));
DWINUI::MoveBy(0, 25);
}
void draw_es_state(const bool is_hit) {
const uint8_t LM = 130;
DWINUI::cursor.x = LM;
dwinDrawRectangle(1, hmiData.colorPopupBg, LM, DWINUI::cursor.y, LM + 100, DWINUI::cursor.y + 20);
is_hit ? DWINUI::drawString(RGB(31,31,16), F(STR_ENDSTOP_HIT)) : DWINUI::drawString(RGB(16,63,16), F(STR_ENDSTOP_OPEN));
DWINUI::moveBy(0, 25);
DWIN_Draw_Rectangle(1, HMI_data.PopupBg_color, LM, DWINUI::cursor.y, LM + 100, DWINUI::cursor.y + 20);
is_hit ? DWINUI::Draw_String(RGB(31,31,16), F(STR_ENDSTOP_HIT)) : DWINUI::Draw_String(RGB(16,63,16), F(STR_ENDSTOP_OPEN));
DWINUI::MoveBy(0, 25);
}
void ESDiag::draw() {
title.showCaption(GET_TEXT_F(MSG_ENDSTOP_TEST));
DWINUI::clearMainArea();
drawPopupBkgd();
DWINUI::drawButton(BTN_Continue, 86, 250);
void ESDiagClass::Draw() {
Title.ShowCaption(F("End-stops Diagnostic"));
DWINUI::ClearMainArea();
Draw_Popup_Bkgd();
DWINUI::Draw_Button(BTN_Continue, 86, 250);
DWINUI::cursor.y = 80;
#define ES_LABEL(S) draw_es_label(F(STR_##S))
TERN_(USE_X_MIN, ES_LABEL(X_MIN)); TERN_(USE_X_MAX, ES_LABEL(X_MAX));
TERN_(USE_Y_MIN, ES_LABEL(Y_MIN)); TERN_(USE_Y_MAX, ES_LABEL(Y_MAX));
TERN_(USE_Z_MIN, ES_LABEL(Z_MIN)); TERN_(USE_Z_MAX, ES_LABEL(Z_MAX));
TERN_(HAS_FILAMENT_SENSOR, draw_es_label(F(STR_FILAMENT)));
update();
#if HAS_X_MIN
ES_LABEL(X_MIN);
#endif
#if HAS_Y_MIN
ES_LABEL(Y_MIN);
#endif
#if HAS_Z_MIN
ES_LABEL(Z_MIN);
#endif
#if HAS_FILAMENT_SENSOR
draw_es_label(F(STR_FILAMENT));
#endif
Update();
}
void ESDiag::update() {
void ESDiagClass::Update() {
DWINUI::cursor.y = 80;
#define ES_REPORT(S) draw_es_state(READ(S##_PIN) == S##_ENDSTOP_HIT_STATE)
TERN_(USE_X_MIN, ES_REPORT(X_MIN)); TERN_(USE_X_MAX, ES_REPORT(X_MAX));
TERN_(USE_Y_MIN, ES_REPORT(Y_MIN)); TERN_(USE_Y_MAX, ES_REPORT(Y_MAX));
TERN_(USE_Z_MIN, ES_REPORT(Z_MIN)); TERN_(USE_Z_MAX, ES_REPORT(Z_MAX));
TERN_(HAS_FILAMENT_SENSOR, draw_es_state(READ(FIL_RUNOUT1_PIN) != runout.out_state());
dwinUpdateLCD();
#define ES_REPORT(S) draw_es_state(READ(S##_PIN) != S##_ENDSTOP_INVERTING)
#if HAS_X_MIN
ES_REPORT(X_MIN);
#endif
#if HAS_Y_MIN
ES_REPORT(Y_MIN);
#endif
#if HAS_Z_MIN
ES_REPORT(Z_MIN);
#endif
#if HAS_FILAMENT_SENSOR
draw_es_state(READ(FIL_RUNOUT1_PIN) != runout.out_state());
#endif
DWIN_UpdateLCD();
}
#endif // HAS_ESDIAG
@@ -33,7 +33,7 @@
#if ENABLED(ANYCUBIC_LCD_CHIRON)
#include "chiron_tft.h"
#include "../anycubic/Tunes.h"
#include "Tunes.h"
#include "FileNavigator.h"
#include "../../../gcode/queue.h"
@@ -42,13 +42,9 @@
#include "../../../libs/numtostr.h"
#include "../../../MarlinCore.h"
#define DEBUG_OUT ACDEBUGLEVEL
#include "../../../core/debug_out.h"
namespace Anycubic {
ChironTFT chiron;
ChironTFT Chiron;
#if AUTO_DETECT_CHIRON_TFT
panel_type_t ChironTFT::panel_type = AC_panel_unknown;
#endif
@@ -64,7 +60,7 @@ uint8_t ChironTFT::command_len;
float ChironTFT::live_Zoffset;
file_menu_t ChironTFT::file_menu;
void ChironTFT::startup() {
void ChironTFT::Startup() {
selectedfile[0] = '\0';
panel_command[0] = '\0';
command_len = 0;
@@ -76,9 +72,14 @@ void ChironTFT::startup() {
live_Zoffset = 0.0;
file_menu = AC_menu_file;
// Filament runout is handled by Marlin settings in Configuration.h
// opt_set FIL_RUNOUT_STATE HIGH // Pin state indicating that filament is NOT present.
// opt_enable FIL_RUNOUT_PULLUP
// Setup pins for powerloss detection
// Two IO pins are connected on the Trigorilla Board
// On a power interruption the OUTAGECON_PIN goes low.
#if ENABLED(POWER_LOSS_RECOVERY)
OUT_WRITE(OUTAGECON_PIN, HIGH);
#endif
TFTSer.begin(115200);
// Wait for the TFT panel to initialize and finish the animation
@@ -88,76 +89,81 @@ void ChironTFT::startup() {
// So we need to know what we are working with.
// Panel type can be defined otherwise detect it automatically
switch (panel_type) {
case AC_panel_new: SERIAL_ECHOLN(AC_msg_new_panel_set); break;
case AC_panel_standard: SERIAL_ECHOLN(AC_msg_old_panel_set); break;
default: SERIAL_ECHOLN(AC_msg_auto_panel_detection);
detectPanelType();
case AC_panel_new:
SERIAL_ECHOLNF(AC_msg_new_panel_set);
break;
case AC_panel_standard:
SERIAL_ECHOLNF(AC_msg_old_panel_set);
break;
default:
SERIAL_ECHOLNF(AC_msg_auto_panel_detection);
DetectPanelType();
break;
}
// Signal Board has reset
tftSendLn(AC_msg_main_board_has_reset);
SendtoTFTLN(AC_msg_main_board_has_reset);
// Enable leveling and Disable end stops during print
// as Z home places nozzle above the bed so we need to allow it past the end stops
injectCommands(AC_cmnd_enable_leveling);
// startup tunes are defined in Tunes.h
playTune(TERN(AC_DEFAULT_STARTUP_TUNE, Anycubic_PowerOn, GB_PowerOn));
// Startup tunes are defined in Tunes.h
PlayTune(BEEPER_PIN, TERN(AC_DEFAULT_STARTUP_TUNE, Anycubic_PowerOn, GB_PowerOn), 1);
#if ACDEBUGLEVEL
DEBUG_ECHOLNPGM("AC Debug Level ", ACDEBUGLEVEL);
SERIAL_ECHOLNPGM("AC Debug Level ", ACDEBUGLEVEL);
#endif
tftSendLn(AC_msg_ready);
SendtoTFTLN(AC_msg_ready);
}
void ChironTFT::detectPanelType() {
void ChironTFT::DetectPanelType() {
#if AUTO_DETECT_CHIRON_TFT
// Send a query to the TFT
tftSendLn(AC_Test_for_OldPanel); // The panel will respond with 'SXY 480 320'
tftSendLn(AC_Test_for_NewPanel); // the panel will respond with '[0]=0 ' to '[19]=0 '
SendtoTFTLN(AC_Test_for_OldPanel); // The panel will respond with 'SXY 480 320'
SendtoTFTLN(AC_Test_for_NewPanel); // the panel will respond with '[0]=0 ' to '[19]=0 '
#endif
}
void ChironTFT::idleLoop() {
if (readTFTCommand()) {
processPanelRequest();
void ChironTFT::IdleLoop() {
if (ReadTFTCommand()) {
ProcessPanelRequest();
command_len = 0;
}
checkHeaters();
CheckHeaters();
}
void ChironTFT::printerKilled(FSTR_P const error, FSTR_P const component) {
tftSendLn(AC_msg_kill_lcd);
void ChironTFT::PrinterKilled(FSTR_P const error, FSTR_P const component) {
SendtoTFTLN(AC_msg_kill_lcd);
#if ACDEBUG(AC_MARLIN)
DEBUG_ECHOLNPGM("printerKilled()\nerror: ", error , "\ncomponent: ", component);
SERIAL_ECHOLNPGM("PrinterKilled()\nerror: ", error , "\ncomponent: ", component);
#endif
}
void ChironTFT::mediaEvent(media_event_t event) {
void ChironTFT::MediaEvent(media_event_t event) {
#if ACDEBUG(AC_MARLIN)
DEBUG_ECHOLNPGM("ProcessMediaStatus() ", event);
SERIAL_ECHOLNPGM("ProcessMediaStatus() ", event);
#endif
switch (event) {
case AC_media_inserted:
tftSendLn(AC_msg_sd_card_inserted);
SendtoTFTLN(AC_msg_sd_card_inserted);
break;
case AC_media_removed:
tftSendLn(AC_msg_sd_card_removed);
SendtoTFTLN(AC_msg_sd_card_removed);
break;
case AC_media_error:
last_error = AC_error_noSD;
tftSendLn(AC_msg_no_sd_card);
SendtoTFTLN(AC_msg_no_sd_card);
break;
}
}
void ChironTFT::timerEvent(timer_event_t event) {
void ChironTFT::TimerEvent(timer_event_t event) {
#if ACDEBUG(AC_MARLIN)
DEBUG_ECHOLNPGM("timerEvent() ", event);
DEBUG_ECHOLNPGM("Printer State: ", printer_state);
SERIAL_ECHOLNPGM("TimerEvent() ", event);
SERIAL_ECHOLNPGM("Printer State: ", printer_state);
#endif
switch (event) {
@@ -165,44 +171,44 @@ void ChironTFT::timerEvent(timer_event_t event) {
live_Zoffset = 0.0; // reset print offset
setSoftEndstopState(false); // disable endstops to print
printer_state = AC_printer_printing;
tftSendLn(AC_msg_print_from_sd_card);
SendtoTFTLN(AC_msg_print_from_sd_card);
} break;
case AC_timer_paused: {
printer_state = AC_printer_paused;
pause_state = AC_paused_idle;
tftSendLn(AC_msg_paused);
SendtoTFTLN(AC_msg_paused);
} break;
case AC_timer_stopped: {
if (printer_state != AC_printer_idle) {
printer_state = AC_printer_stopping;
tftSendLn(AC_msg_print_complete);
SendtoTFTLN(AC_msg_print_complete);
}
setSoftEndstopState(true); // enable endstops
} break;
}
}
void ChironTFT::filamentRunout() {
void ChironTFT::FilamentRunout() {
#if ACDEBUG(AC_MARLIN)
DEBUG_ECHOLNPGM("filamentRunout() printer_state ", printer_state);
SERIAL_ECHOLNPGM("FilamentRunout() printer_state ", printer_state);
#endif
// 1 Signal filament out
last_error = AC_error_filament_runout;
tftSendLn(isPrintingFromMedia() ? AC_msg_filament_out_alert : AC_msg_filament_out_block);
playTune(FilamentOut);
SendtoTFTLN(isPrintingFromMedia() ? AC_msg_filament_out_alert : AC_msg_filament_out_block);
PlayTune(BEEPER_PIN, FilamentOut, 1);
}
void ChironTFT::confirmationRequest(const char * const msg) {
void ChironTFT::ConfirmationRequest(const char * const msg) {
// M108 continue
#if ACDEBUG(AC_MARLIN)
DEBUG_ECHOLNPGM("confirmationRequest() ", msg, " printer_state:", printer_state);
SERIAL_ECHOLNPGM("ConfirmationRequest() ", msg, " printer_state:", printer_state);
#endif
switch (printer_state) {
case AC_printer_pausing: {
if (strcmp_P(msg, MARLIN_msg_print_paused) == 0 || strcmp_P(msg, MARLIN_msg_nozzle_parked) == 0) {
tftSendLn(AC_msg_paused); // enable continue button
SendtoTFTLN(AC_msg_paused); // enable continue button
printer_state = AC_printer_paused;
}
} break;
@@ -213,18 +219,18 @@ void ChironTFT::confirmationRequest(const char * const msg) {
// Heater timeout, send acknowledgement
if (strcmp_P(msg, MARLIN_msg_heater_timeout) == 0) {
pause_state = AC_paused_heater_timed_out;
tftSendLn(AC_msg_paused); // enable continue button
playTune(HeaterTimeout);
SendtoTFTLN(AC_msg_paused); // enable continue button
PlayTune(BEEPER_PIN,Heater_Timedout,1);
}
// Reheat finished, send acknowledgement
else if (strcmp_P(msg, MARLIN_msg_reheat_done) == 0) {
pause_state = AC_paused_idle;
tftSendLn(AC_msg_paused); // enable continue button
SendtoTFTLN(AC_msg_paused); // enable continue button
}
// Filament Purging, send acknowledgement enter run mode
else if (strcmp_P(msg, MARLIN_msg_filament_purging) == 0) {
pause_state = AC_paused_purging_filament;
tftSendLn(AC_msg_paused); // enable continue button
SendtoTFTLN(AC_msg_paused); // enable continue button
}
} break;
default:
@@ -232,10 +238,10 @@ void ChironTFT::confirmationRequest(const char * const msg) {
}
}
void ChironTFT::statusChange(const char * const msg) {
void ChironTFT::StatusChange(const char * const msg) {
#if ACDEBUG(AC_MARLIN)
DEBUG_ECHOLNPGM("statusChange() ", msg);
DEBUG_ECHOLNPGM("printer_state:", printer_state);
SERIAL_ECHOLNPGM("StatusChange() ", msg);
SERIAL_ECHOLNPGM("printer_state:", printer_state);
#endif
bool msg_matched = false;
// The only way to get printer status is to parse messages
@@ -246,15 +252,15 @@ void ChironTFT::statusChange(const char * const msg) {
// Ignore the custom machine name
if (strcmp_P(msg + strlen(MACHINE_NAME), MARLIN_msg_ready) == 0) {
injectCommands(F("M500\nG27"));
tftSendLn(AC_msg_probing_complete);
SendtoTFTLN(AC_msg_probing_complete);
printer_state = AC_printer_idle;
msg_matched = true;
}
// If probing fails don't save the mesh raise the probe above the bad point
if (strcmp_P(msg, MARLIN_msg_probing_failed) == 0) {
playTune(BeepBeepBeeep);
PlayTune(BEEPER_PIN, BeepBeepBeeep, 1);
injectCommands(F("G1 Z50 F500"));
tftSendLn(AC_msg_probing_complete);
SendtoTFTLN(AC_msg_probing_complete);
printer_state = AC_printer_idle;
msg_matched = true;
}
@@ -262,14 +268,14 @@ void ChironTFT::statusChange(const char * const msg) {
case AC_printer_printing: {
if (strcmp_P(msg, MARLIN_msg_reheating) == 0) {
tftSendLn(AC_msg_paused); // enable continue button
SendtoTFTLN(AC_msg_paused); // enable continue button
msg_matched = true;
}
} break;
case AC_printer_pausing: {
if (strcmp_P(msg, MARLIN_msg_print_paused) == 0) {
tftSendLn(AC_msg_paused);
SendtoTFTLN(AC_msg_paused);
printer_state = AC_printer_paused;
pause_state = AC_paused_idle;
msg_matched = true;
@@ -278,7 +284,7 @@ void ChironTFT::statusChange(const char * const msg) {
case AC_printer_stopping: {
if (strcmp_P(msg, MARLIN_msg_print_aborted) == 0) {
tftSendLn(AC_msg_stop);
SendtoTFTLN(AC_msg_stop);
printer_state = AC_printer_idle;
msg_matched = true;
}
@@ -290,11 +296,11 @@ void ChironTFT::statusChange(const char * const msg) {
// If not matched earlier see if this was a heater message
if (!msg_matched) {
if (strcmp_P(msg, MARLIN_msg_extruder_heating) == 0) {
tftSendLn(AC_msg_nozzle_heating);
SendtoTFTLN(AC_msg_nozzle_heating);
hotend_state = AC_heater_temp_set;
}
else if (strcmp_P(msg, MARLIN_msg_bed_heating) == 0) {
tftSendLn(AC_msg_bed_heating);
SendtoTFTLN(AC_msg_bed_heating);
hotbed_state = AC_heater_temp_set;
}
else if (strcmp_P(msg, MARLIN_msg_EEPROM_version) == 0) {
@@ -303,33 +309,33 @@ void ChironTFT::statusChange(const char * const msg) {
}
}
void ChironTFT::powerLossRecovery() {
void ChironTFT::PowerLossRecovery() {
printer_state = AC_printer_resuming_from_power_outage; // Play tune to notify user we can recover.
last_error = AC_error_powerloss;
playTune(SOS);
SERIAL_ECHOLN(AC_msg_powerloss_recovery);
PlayTune(BEEPER_PIN, SOS, 1);
SERIAL_ECHOLNF(AC_msg_powerloss_recovery);
}
void ChironTFT::printComplete() {
tftSend(AC_msg_print_complete);
void ChironTFT::PrintComplete() {
SendtoTFT(AC_msg_print_complete);
printer_state = AC_printer_idle;
setSoftEndstopState(true); // enable endstops
}
void ChironTFT::tftSend(FSTR_P const fstr/*=nullptr*/) { // A helper to print PROGMEM string to the panel
void ChironTFT::SendtoTFT(FSTR_P const fstr/*=nullptr*/) { // A helper to print PROGMEM string to the panel
#if ACDEBUG(AC_SOME)
DEBUG_ECHO(fstr);
SERIAL_ECHOF(fstr);
#endif
PGM_P str = FTOP(fstr);
while (const char c = pgm_read_byte(str++)) TFTSer.write(c);
}
void ChironTFT::tftSendLn(FSTR_P const fstr/*=nullptr*/) {
void ChironTFT::SendtoTFTLN(FSTR_P const fstr/*=nullptr*/) {
if (fstr) {
#if ACDEBUG(AC_SOME)
DEBUG_ECHOPGM("> ");
SERIAL_ECHOPGM("> ");
#endif
tftSend(fstr);
SendtoTFT(fstr);
#if ACDEBUG(AC_SOME)
SERIAL_EOL();
#endif
@@ -337,7 +343,7 @@ void ChironTFT::tftSendLn(FSTR_P const fstr/*=nullptr*/) {
TFTSer.println();
}
bool ChironTFT::readTFTCommand() {
bool ChironTFT::ReadTFTCommand() {
bool command_ready = false;
while (TFTSer.available() > 0 && command_len < MAX_CMND_LEN) {
panel_command[command_len] = TFTSer.read();
@@ -351,29 +357,29 @@ bool ChironTFT::readTFTCommand() {
if (command_ready || command_len == MAX_CMND_LEN) {
panel_command[command_len] = '\0';
#if ACDEBUG(AC_ALL)
DEBUG_ECHOLNPGM("len(",command_len,") < ", panel_command);
SERIAL_ECHOLNPGM("len(",command_len,") < ", panel_command);
#endif
command_ready = true;
}
return command_ready;
}
int8_t ChironTFT::findToken(char c) {
int8_t ChironTFT::FindToken(char c) {
for (int8_t pos = 0; pos < command_len; pos++) {
if (panel_command[pos] == c) {
#if ACDEBUG(AC_INFO)
DEBUG_ECHOLNPGM("Tpos:", pos, " ", c);
SERIAL_ECHOLNPGM("Tpos:", pos, " ", c);
#endif
return pos;
}
}
#if ACDEBUG(AC_INFO)
DEBUG_ECHOLNPGM("Not found: ", c);
SERIAL_ECHOLNPGM("Not found: ", c);
#endif
return -1;
}
void ChironTFT::checkHeaters() {
void ChironTFT::CheckHeaters() {
uint8_t faultDuration = 0;
// if the hotend temp is abnormal, confirm state before signalling panel
@@ -381,7 +387,7 @@ void ChironTFT::checkHeaters() {
while (!WITHIN(temp, HEATER_0_MINTEMP, HEATER_0_MAXTEMP)) {
faultDuration++;
if (faultDuration >= AC_HEATER_FAULT_VALIDATION_TIME) {
tftSendLn(AC_msg_nozzle_temp_abnormal);
SendtoTFTLN(AC_msg_nozzle_temp_abnormal);
last_error = AC_error_abnormal_temp_t0;
SERIAL_ECHOLNPGM("Extruder temp abnormal! : ", temp);
break;
@@ -396,7 +402,7 @@ void ChironTFT::checkHeaters() {
while (!WITHIN(temp, BED_MINTEMP, BED_MAXTEMP)) {
faultDuration++;
if (faultDuration >= AC_HEATER_FAULT_VALIDATION_TIME) {
tftSendLn(AC_msg_nozzle_temp_abnormal);
SendtoTFTLN(AC_msg_nozzle_temp_abnormal);
last_error = AC_error_abnormal_temp_bed;
SERIAL_ECHOLNPGM("Bed temp abnormal! : ", temp);
break;
@@ -408,7 +414,7 @@ void ChironTFT::checkHeaters() {
// Update panel with hotend heater status
if (hotend_state != AC_heater_temp_reached) {
if (WITHIN(getActualTemp_celsius(E0) - getTargetTemp_celsius(E0), -(TEMP_WINDOW), TEMP_WINDOW)) {
tftSendLn(AC_msg_nozzle_heating_done);
SendtoTFTLN(AC_msg_nozzle_heating_done);
hotend_state = AC_heater_temp_reached;
}
}
@@ -416,84 +422,90 @@ void ChironTFT::checkHeaters() {
// Update panel with bed heater status
if (hotbed_state != AC_heater_temp_reached) {
if (WITHIN(getActualTemp_celsius(BED) - getTargetTemp_celsius(BED), -(TEMP_BED_WINDOW), TEMP_BED_WINDOW)) {
tftSendLn(AC_msg_bed_heating_done);
SendtoTFTLN(AC_msg_bed_heating_done);
hotbed_state = AC_heater_temp_reached;
}
}
}
void ChironTFT::sendFileList(int8_t startindex) {
void ChironTFT::SendFileList(int8_t startindex) {
// Respond to panel request for 4 files starting at index
#if ACDEBUG(AC_INFO)
DEBUG_ECHOLNPGM("## sendFileList ## ", startindex);
SERIAL_ECHOLNPGM("## SendFileList ## ", startindex);
#endif
tftSendLn(F("FN "));
SendtoTFTLN(F("FN "));
filenavigator.getFiles(startindex, panel_type, 4);
tftSendLn(F("END"));
SendtoTFTLN(F("END"));
}
void ChironTFT::selectFile() {
const size_t fnlen = command_len - 4 + (panel_type <= AC_panel_new);
strlcpy(selectedfile, panel_command + 4, fnlen + 1);
void ChironTFT::SelectFile() {
if (panel_type <= AC_panel_new) {
strncpy(selectedfile, panel_command + 4, command_len - 3);
selectedfile[command_len - 4] = '\0';
}
else {
strncpy(selectedfile, panel_command + 4, command_len - 4);
selectedfile[command_len - 5] = '\0';
}
#if ACDEBUG(AC_FILE)
DEBUG_ECHOLNPGM(" Selected File: ", selectedfile);
SERIAL_ECHOLNPGM(" Selected File: ",selectedfile);
#endif
switch (selectedfile[0]) {
case '/': // Valid file selected
tftSendLn(AC_msg_sd_file_open_success);
SendtoTFTLN(AC_msg_sd_file_open_success);
break;
case '<': // .. (go up folder level)
filenavigator.upDIR();
tftSendLn(AC_msg_sd_file_open_failed);
sendFileList( 0 );
SendtoTFTLN(AC_msg_sd_file_open_failed);
SendFileList( 0 );
break;
default: // enter subfolder
// For new panel remove the '.GCO' tag that was added to the end of the path
if (panel_type <= AC_panel_new) selectedfile[fnlen - 4] = '\0';
default: // enter sub folder
// for new panel remove the '.GCO' tag that was added to the end of the path
if (panel_type <= AC_panel_new)
selectedfile[strlen(selectedfile) - 4] = '\0';
filenavigator.changeDIR(selectedfile);
tftSendLn(AC_msg_sd_file_open_failed);
sendFileList( 0 );
SendtoTFTLN(AC_msg_sd_file_open_failed);
SendFileList( 0 );
break;
}
}
void ChironTFT::processPanelRequest() {
void ChironTFT::ProcessPanelRequest() {
// Break these up into logical blocks // as its easier to navigate than one huge switch case!
int8_t tpos = findToken('A');
int8_t tpos = FindToken('A');
// Panel request are 'A0' - 'A36'
if (tpos >= 0) {
const int8_t req = atoi(&panel_command[tpos + 1]);
// Information requests A0 - A8 and A33
if (req <= 8 || req == 33) panelInfo(req);
if (req <= 8 || req == 33) PanelInfo(req);
// Simple Actions A9 - A28
else if (req <= 28) panelAction(req);
else if (req <= 28) PanelAction(req);
// Process Initiation
else if (req <= 36) panelProcess(req);
else if (req <= 36) PanelProcess(req);
}
else {
#if AUTO_DETECT_CHIRON_TFT
// This may be a response to a panel type detection query
if (panel_type == AC_panel_unknown) {
tpos = findToken('S'); // old panel will respond to 'SIZE' with 'SXY 480 320'
tpos = FindToken('S'); // old panel will respond to 'SIZE' with 'SXY 480 320'
if (tpos >= 0) {
if (panel_command[tpos + 1] == 'X' && panel_command[tpos + 2] =='Y') {
panel_type = AC_panel_standard;
SERIAL_ECHOLN(AC_msg_old_panel_detected);
SERIAL_ECHOLNF(AC_msg_old_panel_detected);
}
}
else {
// new panel will respond to 'J200' with '[0]=0'
// it seems only after a power cycle so detection assumes a new panel
tpos = findToken('[');
tpos = FindToken('[');
if (tpos >= 0) {
if (panel_command[tpos + 1] == '0' && panel_command[tpos + 2] ==']') {
panel_type = AC_panel_new;
SERIAL_ECHOLN(AC_msg_new_panel_detected);
SERIAL_ECHOLNF(AC_msg_new_panel_detected);
}
}
}
@@ -501,94 +513,94 @@ void ChironTFT::processPanelRequest() {
}
#endif
tftSendLn(); // Ignore unknown requests
SendtoTFTLN(); // Ignore unknown requests
}
}
void ChironTFT::panelInfo(uint8_t req) {
void ChironTFT::PanelInfo(uint8_t req) {
// information requests A0-A8 and A33
switch (req) {
case 0: // A0 Get HOTEND Temp
tftSend(F("A0V "));
SendtoTFT(F("A0V "));
TFTSer.println(getActualTemp_celsius(E0));
break;
case 1: // A1 Get HOTEND Target Temp
tftSend(F("A1V "));
SendtoTFT(F("A1V "));
TFTSer.println(getTargetTemp_celsius(E0));
break;
case 2: // A2 Get BED Temp
tftSend(F("A2V "));
SendtoTFT(F("A2V "));
TFTSer.println(getActualTemp_celsius(BED));
break;
case 3: // A3 Get BED Target Temp
tftSend(F("A3V "));
SendtoTFT(F("A3V "));
TFTSer.println(getTargetTemp_celsius(BED));
break;
case 4: // A4 Get FAN Speed
tftSend(F("A4V "));
SendtoTFT(F("A4V "));
TFTSer.println(getActualFan_percent(FAN0));
break;
case 5: // A5 Get Current Coordinates
tftSend(F("A5V X: "));
SendtoTFT(F("A5V X: "));
TFTSer.print(getAxisPosition_mm(X));
tftSend(F(" Y: "));
SendtoTFT(F(" Y: "));
TFTSer.print(getAxisPosition_mm(Y));
tftSend(F(" Z: "));
SendtoTFT(F(" Z: "));
TFTSer.println(getAxisPosition_mm(Z));
break;
case 6: // A6 Get printing progress
if (isPrintingFromMedia()) {
tftSend(F("A6V "));
SendtoTFT(F("A6V "));
TFTSer.println(ui8tostr2(getProgress_percent()));
}
else
tftSendLn(F("A6V ---"));
SendtoTFTLN(F("A6V ---"));
break;
case 7: { // A7 Get Printing Time
uint32_t time = getProgress_seconds_elapsed() / 60;
tftSend(F("A7V "));
SendtoTFT(F("A7V "));
TFTSer.print(ui8tostr2(time / 60));
tftSend(F(" H "));
SendtoTFT(F(" H "));
TFTSer.print(ui8tostr2(time % 60));
tftSend(F(" M"));
SendtoTFT(F(" M"));
#if ACDEBUG(AC_ALL)
DEBUG_ECHOLNPGM("Print time ", ui8tostr2(time / 60), ":", ui8tostr2(time % 60));
SERIAL_ECHOLNPGM("Print time ", ui8tostr2(time / 60), ":", ui8tostr2(time % 60));
#endif
} break;
case 8: // A8 Get SD Card list A8 S0
if (!isMediaInserted()) safe_delay(500);
if (!isMediaInserted()) // Make sure the card is removed
tftSendLn(AC_msg_no_sd_card);
SendtoTFTLN(AC_msg_no_sd_card);
else if (panel_command[3] == 'S')
sendFileList( atoi( &panel_command[4] ) );
SendFileList( atoi( &panel_command[4] ) );
break;
case 33: // A33 Get firmware info
tftSend(F("J33 "));
SendtoTFT(F("J33 "));
// If there is an error recorded, show that instead of the FW version
if (!getLastError()) tftSendLn(F(SHORT_BUILD_VERSION));
if (!GetLastError()) SendtoTFTLN(F(SHORT_BUILD_VERSION));
break;
}
}
void ChironTFT::panelAction(uint8_t req) {
void ChironTFT::PanelAction(uint8_t req) {
switch (req) {
case 9: // A9 Pause SD print
if (isPrintingFromMedia()) {
tftSendLn(AC_msg_pause);
SendtoTFTLN(AC_msg_pause);
pausePrint();
printer_state = AC_printer_pausing;
}
else
tftSendLn(AC_msg_stop);
SendtoTFTLN(AC_msg_stop);
break;
case 10: // A10 Resume SD Print
@@ -606,7 +618,7 @@ void ChironTFT::panelAction(uint8_t req) {
else {
if (printer_state == AC_printer_resuming_from_power_outage)
injectCommands(F("M1000 C")); // Cancel recovery
tftSendLn(AC_msg_stop);
SendtoTFTLN(AC_msg_stop);
printer_state = AC_printer_idle;
}
break;
@@ -616,7 +628,7 @@ void ChironTFT::panelAction(uint8_t req) {
break;
case 13: // A13 Select file
selectFile();
SelectFile();
break;
case 14: // A14 Start Printing
@@ -625,9 +637,11 @@ void ChironTFT::panelAction(uint8_t req) {
injectCommands(F("M1000 C")); // Cancel recovery
printer_state = AC_printer_idle;
}
DEBUG_ECHOLNPGM("Print: ", selectedfile);
#if ACDebugLevel >= 1
SERIAL_ECHOLNPGM("Print: ", selectedfile);
#endif
printFile(selectedfile);
tftSendLn(AC_msg_print_from_sd_card);
SendtoTFTLN(AC_msg_print_from_sd_card);
break;
case 15: // A15 Resuming from outage
@@ -662,7 +676,7 @@ void ChironTFT::panelAction(uint8_t req) {
case 19: // A19 Motors off
if (!isPrinting()) {
stepper.disable_all_steppers();
tftSendLn(AC_msg_ready);
SendtoTFTLN(AC_msg_ready);
}
break;
@@ -670,7 +684,7 @@ void ChironTFT::panelAction(uint8_t req) {
if (panel_command[4] == 'S')
setFeedrate_percent(atoi(&panel_command[5]));
else {
tftSend(F("A20V "));
SendtoTFT(F("A20V "));
TFTSer.println(getFeedrate_percent());
}
break;
@@ -698,7 +712,7 @@ void ChironTFT::panelAction(uint8_t req) {
char MoveCmnd[30];
sprintf_P(MoveCmnd, PSTR("G91\nG0%s\nG90"), panel_command + 3);
#if ACDEBUG(AC_ACTION)
DEBUG_ECHOLNPGM("Move: ", MoveCmnd);
SERIAL_ECHOLNPGM("Move: ", MoveCmnd);
#endif
setSoftEndstopState(true); // enable endstops
injectCommands(MoveCmnd);
@@ -711,7 +725,7 @@ void ChironTFT::panelAction(uint8_t req) {
// Temps defined in configuration.h
setTargetTemp_celsius(PREHEAT_1_TEMP_BED, BED);
setTargetTemp_celsius(PREHEAT_1_TEMP_HOTEND, E0);
tftSendLn();
SendtoTFTLN();
hotbed_state = AC_heater_temp_set;
hotend_state = AC_heater_temp_set;
}
@@ -722,7 +736,7 @@ void ChironTFT::panelAction(uint8_t req) {
if (!isPrinting()) {
setTargetTemp_celsius(PREHEAT_2_TEMP_BED, BED);
setTargetTemp_celsius(PREHEAT_2_TEMP_HOTEND, E0);
tftSendLn();
SendtoTFTLN();
hotbed_state = AC_heater_temp_set;
hotend_state = AC_heater_temp_set;
}
@@ -733,7 +747,7 @@ void ChironTFT::panelAction(uint8_t req) {
if (!isPrinting()) {
setTargetTemp_celsius(0, E0);
setTargetTemp_celsius(0, BED);
tftSendLn(AC_msg_ready);
SendtoTFTLN(AC_msg_ready);
hotbed_state = AC_heater_off;
hotend_state = AC_heater_off;
}
@@ -752,21 +766,21 @@ void ChironTFT::panelAction(uint8_t req) {
case 28: // A28 Filament set A28 O/C
// Ignore request if printing
if (isPrinting()) break;
tftSendLn();
SendtoTFTLN();
break;
}
}
void ChironTFT::panelProcess(uint8_t req) {
void ChironTFT::PanelProcess(uint8_t req) {
switch (req) {
case 29: { // A29 Read Mesh Point A29 X1 Y1
xy_uint8_t pos;
float pos_z;
pos.x = atoi(&panel_command[findToken('X')+1]);
pos.y = atoi(&panel_command[findToken('Y')+1]);
pos.x = atoi(&panel_command[FindToken('X')+1]);
pos.y = atoi(&panel_command[FindToken('Y')+1]);
pos_z = getMeshPoint(pos);
tftSend(F("A29V "));
SendtoTFT(F("A29V "));
TFTSer.println(pos_z * 100);
if (!isPrinting()) {
setSoftEndstopState(true); // disable endstops
@@ -777,7 +791,7 @@ void ChironTFT::panelProcess(uint8_t req) {
if (isPositionKnown()) {
#if ACDEBUG(AC_INFO)
DEBUG_ECHOLNPGM("Moving to mesh point at x: ", pos.x, " y: ", pos.y, " z: ", pos_z);
SERIAL_ECHOLNPGM("Moving to mesh point at x: ", pos.x, " y: ", pos.y, " z: ", pos_z);
#endif
// Go up before moving
setAxisPosition_mm(3.0,Z);
@@ -786,7 +800,7 @@ void ChironTFT::panelProcess(uint8_t req) {
setAxisPosition_mm(20 + (93 * pos.y), Y);
setAxisPosition_mm(0.0, Z);
#if ACDEBUG(AC_INFO)
DEBUG_ECHOLNPGM("Current Z: ", getAxisPosition_mm(Z));
SERIAL_ECHOLNPGM("Current Z: ", getAxisPosition_mm(Z));
#endif
}
}
@@ -796,42 +810,42 @@ void ChironTFT::panelProcess(uint8_t req) {
} break;
case 30: // A30 Auto leveling
if (findToken('S') >= 0) { // Start probing New panel adds spaces..
if (FindToken('S') >= 0) { // Start probing New panel adds spaces..
// Ignore request if printing
if (isPrinting())
tftSendLn(AC_msg_probing_not_allowed); // forbid auto leveling
SendtoTFTLN(AC_msg_probing_not_allowed); // forbid auto leveling
else {
tftSendLn(AC_msg_start_probing);
SendtoTFTLN(AC_msg_start_probing);
injectCommands(F("G28\nG29"));
printer_state = AC_printer_probing;
}
}
else
tftSendLn(AC_msg_start_probing); // Just enter levelling menu
SendtoTFTLN(AC_msg_start_probing); // Just enter levelling menu
break;
case 31: // A31 Adjust all Probe Points
// The tokens can occur in different places on the new panel so we need to find it.
if (findToken('C') >= 0) { // Restore and apply original offsets
if (FindToken('C') >= 0) { // Restore and apply original offsets
if (!isPrinting()) {
injectCommands(F("M501\nM420 S1"));
selectedmeshpoint.x = selectedmeshpoint.y = 99;
SERIAL_ECHOLN(AC_msg_mesh_changes_abandoned);
SERIAL_ECHOLNF(AC_msg_mesh_changes_abandoned);
}
}
else if (findToken('D') >= 0) { // Save Z Offset tables and restore leveling state
else if (FindToken('D') >= 0) { // Save Z Offset tables and restore leveling state
if (!isPrinting()) {
setAxisPosition_mm(1.0,Z); // Lift nozzle before any further movements are made
injectCommands(F("M500"));
SERIAL_ECHOLN(AC_msg_mesh_changes_saved);
SERIAL_ECHOLNF(AC_msg_mesh_changes_saved);
selectedmeshpoint.x = selectedmeshpoint.y = 99;
}
}
else if (findToken('G') >= 0) { // Get current offset
tftSend(F("A31V "));
else if (FindToken('G') >= 0) { // Get current offset
SendtoTFT(F("A31V "));
// When printing use the live z Offset position
// we will use babystepping to move the print head
if (isPrinting())
@@ -843,7 +857,7 @@ void ChironTFT::panelProcess(uint8_t req) {
}
else {
int8_t tokenpos = findToken('S');
int8_t tokenpos = FindToken('S');
if (tokenpos >= 0) { // Set offset (adjusts all points by value)
float Zshift = atof(&panel_command[tokenpos+1]);
setSoftEndstopState(false); // disable endstops
@@ -851,22 +865,22 @@ void ChironTFT::panelProcess(uint8_t req) {
// From the leveling panel use the all points UI to adjust the print pos.
if (isPrinting()) {
#if ACDEBUG(AC_INFO)
DEBUG_ECHOLNPGM("Change Zoffset from:", live_Zoffset, " to ", live_Zoffset + Zshift);
SERIAL_ECHOLNPGM("Change Zoffset from:", live_Zoffset, " to ", live_Zoffset + Zshift);
#endif
if (isAxisPositionKnown(Z)) {
#if ACDEBUG(AC_INFO)
const float currZpos = getAxisPosition_mm(Z);
DEBUG_ECHOLNPGM("Nudge Z pos from ", currZpos, " to ", currZpos + constrain(Zshift, -0.05, 0.05));
SERIAL_ECHOLNPGM("Nudge Z pos from ", currZpos, " to ", currZpos + constrain(Zshift, -0.05, 0.05));
#endif
// Use babystepping to adjust the head position
int16_t steps = mmToWholeSteps(constrain(Zshift,-0.05,0.05), Z);
#if ACDEBUG(AC_INFO)
DEBUG_ECHOLNPGM("Steps to move Z: ", steps);
SERIAL_ECHOLNPGM("Steps to move Z: ", steps);
#endif
babystepAxis_steps(steps, Z);
live_Zoffset += Zshift;
}
tftSend(F("A31V "));
SendtoTFT(F("A31V "));
TFTSer.println(live_Zoffset);
}
else {
@@ -875,23 +889,23 @@ void ChironTFT::panelProcess(uint8_t req) {
const float currval = getMeshPoint(pos);
setMeshPoint(pos, constrain(currval + Zshift, AC_LOWEST_MESHPOINT_VAL, 2));
#if ACDEBUG(AC_INFO)
DEBUG_ECHOLNPGM("Change mesh point X", x," Y",y ," from ", currval, " to ", getMeshPoint(pos) );
SERIAL_ECHOLNPGM("Change mesh point X", x," Y",y ," from ", currval, " to ", getMeshPoint(pos) );
#endif
}
const float currZOffset = getZOffset_mm();
#if ACDEBUG(AC_INFO)
DEBUG_ECHOLNPGM("Change probe offset from ", currZOffset, " to ", currZOffset + Zshift);
SERIAL_ECHOLNPGM("Change probe offset from ", currZOffset, " to ", currZOffset + Zshift);
#endif
setZOffset_mm(currZOffset + Zshift);
tftSend(F("A31V "));
SendtoTFT(F("A31V "));
TFTSer.println(getZOffset_mm());
if (isAxisPositionKnown(Z)) {
// Move Z axis
const float currZpos = getAxisPosition_mm(Z);
#if ACDEBUG(AC_INFO)
DEBUG_ECHOLNPGM("Move Z pos from ", currZpos, " to ", currZpos + constrain(Zshift, -0.05, 0.05));
SERIAL_ECHOLNPGM("Move Z pos from ", currZpos, " to ", currZpos + constrain(Zshift, -0.05, 0.05));
#endif
setAxisPosition_mm(currZpos+constrain(Zshift,-0.05,0.05),Z);
}
@@ -907,7 +921,7 @@ void ChironTFT::panelProcess(uint8_t req) {
//TFTSer.println();
break;
// A33 firmware info request see panelInfo()
// A33 firmware info request see PanelInfo()
case 34: // A34 Adjust single mesh point A34 C/S X1 Y1 V123
if (panel_command[3] == 'C') { // Restore original offsets
@@ -923,8 +937,8 @@ void ChironTFT::panelProcess(uint8_t req) {
float currmesh = getMeshPoint(pos);
float newval = atof(&panel_command[11])/100;
#if ACDEBUG(AC_INFO)
DEBUG_ECHOLNPGM("Change mesh point x:", pos.x, " y:", pos.y);
DEBUG_ECHOLNPGM("from ", currmesh, " to ", newval);
SERIAL_ECHOLNPGM("Change mesh point x:", pos.x, " y:", pos.y);
SERIAL_ECHOLNPGM("from ", currmesh, " to ", newval);
#endif
// Update Meshpoint
setMeshPoint(pos,newval);
@@ -935,7 +949,7 @@ void ChironTFT::panelProcess(uint8_t req) {
setSoftEndstopState(false);
float currZpos = getAxisPosition_mm(Z);
#if ACDEBUG(AC_INFO)
DEBUG_ECHOLNPGM("Move Z pos from ", currZpos, " to ", currZpos + constrain(newval - currmesh, -0.05, 0.05));
SERIAL_ECHOLNPGM("Move Z pos from ", currZpos, " to ", currZpos + constrain(newval - currmesh, -0.05, 0.05));
#endif
setAxisPosition_mm(currZpos + constrain(newval - currmesh, -0.05, 0.05), Z);
}
@@ -944,19 +958,19 @@ void ChironTFT::panelProcess(uint8_t req) {
break;
case 36: // A36 Auto leveling for new TFT bet that was a typo in the panel code!
tftSendLn(AC_msg_start_probing);
SendtoTFTLN(AC_msg_start_probing);
break;
}
}
bool ChironTFT::getLastError() {
bool ChironTFT::GetLastError() {
switch (last_error) {
case AC_error_abnormal_temp_bed: tftSendLn(AC_msg_error_bed_temp); break;
case AC_error_abnormal_temp_t0: tftSendLn(AC_msg_error_hotend_temp); break;
case AC_error_noSD: tftSendLn(AC_msg_error_sd_card); break;
case AC_error_powerloss: tftSendLn(AC_msg_power_loss); break;
case AC_error_EEPROM: tftSendLn(AC_msg_eeprom_version); break;
case AC_error_filament_runout: tftSendLn(AC_msg_filament_out); break;
case AC_error_abnormal_temp_bed: SendtoTFTLN(AC_msg_error_bed_temp); break;
case AC_error_abnormal_temp_t0: SendtoTFTLN(AC_msg_error_hotend_temp); break;
case AC_error_noSD: SendtoTFTLN(AC_msg_error_sd_card); break;
case AC_error_powerloss: SendtoTFTLN(AC_msg_power_loss); break;
case AC_error_EEPROM: SendtoTFTLN(AC_msg_eeprom_version); break;
case AC_error_filament_runout: SendtoTFTLN(AC_msg_filament_out); break;
default: return false;
}
last_error = AC_error_none;
@@ -1,357 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/* DGUS implementation written by coldtobi in 2019 for Marlin */
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(DGUS_LCD_UI_CREALITY_TOUCH)
#define DEBUG_ECHOLNPAIR DEBUG_ECHOLNPGM
#if HOTENDS > 2
#error "More than 2 hotends not implemented on the Display UI design."
#endif
#include "../ui_api.h"
#include "../../../MarlinCore.h"
#include "../../../module/temperature.h"
#include "../../../module/motion.h"
#include "../../../gcode/queue.h"
#include "../../../module/planner.h"
#include "../../../sd/cardreader.h"
#include "../../../libs/duration_t.h"
#include "../../../module/printcounter.h"
#if ENABLED(POWER_LOSS_RECOVERY)
#include "../../../feature/powerloss.h"
#endif
#include "DGUSDisplay.h"
#include "DGUSVPVariable.h"
#include "DGUSDisplayDef.h"
// Preamble... 2 Bytes, usually 0x5A 0xA5, but configurable
constexpr uint8_t DGUS_HEADER1 = 0x5A;
constexpr uint8_t DGUS_HEADER2 = 0xA5;
constexpr uint8_t DGUS_CMD_WRITEVAR = 0x82;
constexpr uint8_t DGUS_CMD_READVAR = 0x83;
#if ENABLED(DEBUG_DGUSLCD)
bool dguslcd_local_debug; // = false;
#endif
#define dgusserial LCD_SERIAL
void DGUSDisplay::InitDisplay() {
dgusserial.begin(LCD_BAUDRATE);
/*delay(500); // Attempt to fix possible handshake error
ResetDisplay(); // Reset for firmware update
delay(500); // Attempt to fix possible handshake error
*/
if (true
#if ENABLED(POWER_LOSS_RECOVERY)
&& !recovery.valid()
#endif
)
RequestScreen(
#if ENABLED(SHOW_BOOTSCREEN)
DGUSLCD_SCREEN_BOOT
#else
DGUSLCD_SCREEN_MAIN
#endif
);
}
void DGUSDisplay::ResetDisplay() {
SERIAL_ECHOLN("ResetDisplay");
const unsigned char resetCommand[] = { 0x55, 0xAA, 0x5A, 0xA5 };
WriteVariable(0x04, resetCommand, sizeof(resetCommand));
}
void DGUSDisplay::ReadVariable(uint16_t adr) {
WriteHeader(adr, DGUS_CMD_READVAR, sizeof(uint8_t));
// Specify to read one byte
dgusserial.write(static_cast<uint8_t>(1));
}
void DGUSDisplay::WriteVariable(uint16_t adr, const void* values, uint8_t valueslen, bool isstr, char fillChar) {
const char* myvalues = static_cast<const char*>(values);
bool strend = !myvalues;
WriteHeader(adr, DGUS_CMD_WRITEVAR, valueslen);
while (valueslen--) {
char x;
if (!strend) x = *myvalues++;
if ((isstr && !x) || strend) {
strend = true;
x = fillChar;
}
dgusserial.write(x);
}
}
void DGUSDisplay::WriteVariable(uint16_t adr, uint16_t value) {
value = (value & 0xffU) << 8U | (value >> 8U);
WriteVariable(adr, static_cast<const void*>(&value), sizeof(uint16_t));
}
void DGUSDisplay::WriteVariable(uint16_t adr, int16_t value) {
union { int16_t l; char lb[2]; } endian;
char tmp[2];
endian.l = value;
tmp[0] = endian.lb[1];
tmp[1] = endian.lb[0];
WriteVariable(adr, static_cast<const void*>(&tmp), sizeof(int16_t));
}
void DGUSDisplay::WriteVariable(uint16_t adr, uint8_t value) {
WriteVariable(adr, static_cast<const void*>(&value), sizeof(uint8_t));
}
void DGUSDisplay::WriteVariable(uint16_t adr, int8_t value) {
WriteVariable(adr, static_cast<const void*>(&value), sizeof(int8_t));
}
void DGUSDisplay::WriteVariable(uint16_t adr, long value) {
union { long l; char lb[4]; } endian;
char tmp[4];
endian.l = value;
tmp[0] = endian.lb[3];
tmp[1] = endian.lb[2];
tmp[2] = endian.lb[1];
tmp[3] = endian.lb[0];
WriteVariable(adr, static_cast<const void*>(&tmp), sizeof(long));
}
void DGUSDisplay::WriteVariable(uint16_t adr, float value) {
static_assert(sizeof(float) == 4);
union { float l; char lb[4]; } endian;
char tmp[4];
endian.l = value;
tmp[0] = endian.lb[3];
tmp[1] = endian.lb[2];
tmp[2] = endian.lb[1];
tmp[3] = endian.lb[0];
WriteVariable(adr, static_cast<const void*>(&tmp), sizeof(float));
}
void DGUSDisplay::WriteVariablePGM(uint16_t adr, const void* values, uint8_t valueslen, bool isstr, char fillChar) {
const char* myvalues = static_cast<const char*>(values);
bool strend = !myvalues;
WriteHeader(adr, DGUS_CMD_WRITEVAR, valueslen);
while (valueslen--) {
char x;
if (!strend) x = pgm_read_byte(myvalues++);
if ((isstr && !x) || strend) {
strend = true;
x = fillChar;
}
dgusserial.write(x);
}
}
void DGUSDisplay::SetVariableDisplayColor(uint16_t sp, uint16_t color) {
WriteVariable(sp + 0x03, color);
}
void DGUSDisplay::ProcessRx() {
#if ENABLED(DGUS_SERIAL_STATS_RX_BUFFER_OVERRUNS)
if (!dgusserial.available() && dgusserial.buffer_overruns()) {
// Overrun, but reset the flag only when the buffer is empty
// We want to extract as many as valid datagrams possible...
DEBUG_ECHOPGM("OVFL");
rx_datagram_state = DGUS_IDLE;
//dgusserial.reset_rx_overun();
dgusserial.flush();
}
#endif
uint8_t receivedbyte;
while (dgusserial.available()) {
switch (rx_datagram_state) {
case DGUS_IDLE: // Waiting for the first header byte
receivedbyte = dgusserial.read();
//DEBUGLCDCOMM_ECHOPAIR("< ",receivedbyte);
if (DGUS_HEADER1 == receivedbyte) rx_datagram_state = DGUS_HEADER1_SEEN;
break;
case DGUS_HEADER1_SEEN: // Waiting for the second header byte
receivedbyte = dgusserial.read();
//DEBUGLCDCOMM_ECHOPAIR(" ", receivedbyte);
rx_datagram_state = (DGUS_HEADER2 == receivedbyte) ? DGUS_HEADER2_SEEN : DGUS_IDLE;
break;
case DGUS_HEADER2_SEEN: // Waiting for the length byte
rx_datagram_len = dgusserial.read();
//DEBUGLCDCOMM_ECHOPAIR(" (", rx_datagram_len, ") ");
// Telegram min len is 3 (command and one word of payload)
rx_datagram_state = WITHIN(rx_datagram_len, 3, DGUS_RX_BUFFER_SIZE) ? DGUS_WAIT_TELEGRAM : DGUS_IDLE;
break;
case DGUS_WAIT_TELEGRAM: // wait for complete datagram to arrive.
if (dgusserial.available() < rx_datagram_len) return;
Initialized = true; // We've talked to it, so we defined it as initialized.
uint8_t command = dgusserial.read();
// DEBUGLCDCOMM_ECHOPAIR("# ", command);
uint8_t readlen = rx_datagram_len - 1; // command is part of len.
unsigned char tmp[rx_datagram_len - 1];
unsigned char *ptmp = tmp;
while (readlen--) {
receivedbyte = dgusserial.read();
//DEBUGLCDCOMM_ECHOPAIR(" ", receivedbyte);
*ptmp++ = receivedbyte;
}
//DEBUGLCDCOMM_ECHOPGM(" # ");
// mostly we'll get this: 5A A5 03 82 4F 4B -- ACK on 0x82, so discard it.
if (command == DGUS_CMD_WRITEVAR && 'O' == tmp[0] && 'K' == tmp[1]) {
//DEBUG_ECHOLNPGM(">");
rx_datagram_state = DGUS_IDLE;
break;
}
/* AutoUpload, (and answer to) Command 0x83 :
| tmp[0 1 2 3 4 ... ]
| Example 5A A5 06 83 20 01 01 78 01
| / / | | \ / | \ \
| Header | | | | \_____\_ DATA (Words!)
| DatagramLen / VPAdr |
| Command DataLen (in Words) */
if (command == DGUS_CMD_READVAR) {
const uint16_t vp = tmp[0] << 8 | tmp[1];
//const uint8_t dlen = tmp[2] << 1; // Convert to Bytes. (Display works with words)
//DEBUG_ECHOPAIR(" vp=", vp, " dlen=", dlen);
DGUS_VP_Variable ramcopy;
DEBUG_ECHOLNPAIR("VP received: ", vp , " - val ", tmp[3]);
if (populate_VPVar(vp, &ramcopy)) {
if (ramcopy.set_by_display_handler)
ramcopy.set_by_display_handler(ramcopy, &tmp[3]);
else
DEBUG_ECHOLNPGM(" VPVar found, no handler.");
}
else
DEBUG_ECHOLNPAIR(" VPVar not found:", vp);
rx_datagram_state = DGUS_IDLE;
break;
}
// discard anything else
rx_datagram_state = DGUS_IDLE;
}
}
}
size_t DGUSDisplay::GetFreeTxBuffer() { return SERIAL_GET_TX_BUFFER_FREE(); }
void DGUSDisplay::WriteHeader(uint16_t adr, uint8_t cmd, uint8_t payloadlen) {
dgusserial.write(DGUS_HEADER1);
dgusserial.write(DGUS_HEADER2);
dgusserial.write(payloadlen + 3);
dgusserial.write(cmd);
dgusserial.write(adr >> 8);
dgusserial.write(adr & 0xFF);
}
void DGUSDisplay::WritePGM(const char str[], uint8_t len) {
while (len--) dgusserial.write(pgm_read_byte(str++));
}
void DGUSDisplay::loop() {
// protect against recursion… ProcessRx() may indirectly call idle() when injecting gcode commands.
if (!no_reentrance) {
no_reentrance = true;
ProcessRx();
//Because crappy VPHELPER macros cant take calcs or functions, process updated value here. If we handle only in button handler code, we will miss changes over M290
dgusdisplay.WriteVariable(VP_Z_OFFSET, (int16_t)(100*ExtUI::getZOffset_mm()));
no_reentrance = false;
}
}
void DGUSDisplay::RequestScreen(DGUSLCD_Screens screen) {
displayRequest = screen;
DEBUG_ECHOLNPAIR("GotoScreen ", screen);
const unsigned char gotoscreen[] = { 0x5A, 0x01, (unsigned char) (screen >> 8U), (unsigned char) (screen & 0xFFU) };
WriteVariable(0x84, gotoscreen, sizeof(gotoscreen));
}
void DGUSDisplay::SetTouchScreenConfiguration(bool enable_standby, bool enable_sound, uint8_t standby_brightness, uint8_t brightness, uint16_t standbyTimeSeconds) {
// Main configuration (System_Config)
unsigned char cfg_bits = 0x0;
cfg_bits |= 1UL << 5; // 5: load 22 touch file
cfg_bits |= 1UL << 4; // 4: auto-upload should always be enabled
if (enable_sound) cfg_bits |= 1UL << 3; // 3: audio
if (enable_standby) cfg_bits |= 1UL << 2; // 2: backlight on standby
cfg_bits |= 1UL << 1; // 1 & 0: 270 degrees orientation of display
cfg_bits |= 1UL << 0;
DEBUG_ECHOLNPAIR("Update touch screen config - standby ", enable_standby);
DEBUG_ECHOLNPAIR("Update touch screen config - sound ", enable_sound);
const unsigned char config_set[] = { 0x5A, 0x00, (unsigned char) (cfg_bits >> 8U), (unsigned char) (cfg_bits & 0xFFU) };
WriteVariable(0x80 /*System_Config*/, config_set, sizeof(config_set));
// Standby brightness (LED_Config)
uint16_t dwinStandbyTimeSeconds = 100 * standbyTimeSeconds; /* milliseconds, but divided by 10 (not 5 like the docs say) */
const unsigned char brightness_set[] = {
brightness /*% active*/,
standby_brightness /*% standby*/,
static_cast<uint8_t>(dwinStandbyTimeSeconds >> 8),
static_cast<uint8_t>(dwinStandbyTimeSeconds)
};
WriteVariable(0x82 /*LED_Config*/, brightness_set, sizeof(brightness_set));
}
rx_datagram_state_t DGUSDisplay::rx_datagram_state = DGUS_IDLE;
uint8_t DGUSDisplay::rx_datagram_len = 0;
bool DGUSDisplay::Initialized = false;
bool DGUSDisplay::no_reentrance = false;
DGUSLCD_Screens DGUSDisplay::displayRequest = DGUSLCD_SCREEN_BOOT;
// A SW memory barrier, to ensure GCC does not overoptimize loops
#define sw_barrier() asm volatile("": : :"memory");
bool populate_VPVar(const uint16_t VP, DGUS_VP_Variable * const ramcopy) {
//DEBUG_ECHOLNPAIR("populate_VPVar ", VP);
const DGUS_VP_Variable *pvp = DGUSLCD_FindVPVar(VP);
// DEBUG_ECHOLNPAIR(" pvp ", (uint16_t )pvp);
if (!pvp) return false;
memcpy_P(ramcopy, pvp, sizeof(DGUS_VP_Variable));
return true;
}
#endif // HAS_DGUS_LCD
@@ -1,136 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
//#define DEBUG_DGUSLCD
//#define DEBUG_DGUSLCD_OUTGOING_COMM
/* Creality DGUS implementation written by Sebastiaan Dammann in 2020 for Marlin */
#include "../../../inc/MarlinConfigPre.h"
#include "../../../MarlinCore.h"
#if HAS_BED_PROBE
#include "../../../module/probe.h"
#endif
#include "DGUSVPVariable.h"
enum DGUSLCD_Screens : uint8_t;
#ifndef DEBUG_OUT
#define DEBUG_OUT ENABLED(DEBUG_DGUSLCD)
#endif
#include "../../../core/debug_out.h"
typedef enum : uint8_t {
DGUS_IDLE, //< waiting for DGUS_HEADER1.
DGUS_HEADER1_SEEN, //< DGUS_HEADER1 received
DGUS_HEADER2_SEEN, //< DGUS_HEADER2 received
DGUS_WAIT_TELEGRAM, //< LEN received, Waiting for to receive all bytes.
} rx_datagram_state_t;
typedef void (*UPDATE_CURRENT_SCREEN_CALLBACK)(DGUSLCD_Screens screen);
// Low-Level access to the display.
class DGUSDisplay {
public:
DGUSDisplay() = default;
static void InitDisplay();
static void ResetDisplay();
// Variable access.
static void WriteVariable(uint16_t adr, const void* values, uint8_t valueslen, bool isstr=false, char fillChar = ' ');
static void WriteVariablePGM(uint16_t adr, const void* values, uint8_t valueslen, bool isstr=false, char fillChar = ' ');
static void WriteVariable(uint16_t adr, int16_t value);
static void WriteVariable(uint16_t adr, uint16_t value);
static void WriteVariable(uint16_t adr, uint8_t value);
static void WriteVariable(uint16_t adr, int8_t value);
static void WriteVariable(uint16_t adr, long value);
static void WriteVariable(uint16_t adr, float value);
static void SetVariableDisplayColor(uint16_t sp, uint16_t color);
static void ReadVariable(uint16_t adr);
// Utility functions for bridging ui_api and dgus
template<typename T, float(*Getter)(const T), T selector, typename WireType=uint16_t>
static void SetVariable(DGUS_VP_Variable &var) {
WriteVariable(var.VP, (WireType)Getter(selector));
}
template<typename T, void(*Setter)(const float V, const T), T selector>
static void GetVariable(DGUS_VP_Variable &var, void *val_ptr) {
uint16_t newvalue = swap16(*(uint16_t*)val_ptr);
Setter(newvalue, selector);
}
// Force display into another screen.
// (And trigger update of containing VPs)
// (to implement a pop up message, which may not be nested)
static void RequestScreen(DGUSLCD_Screens screen);
static void SetTouchScreenConfiguration(bool enable_standby, bool enable_sound, uint8_t standby_brightness, uint8_t active_brightness, uint16_t standbyTimeSeconds);
// Periodic tasks, eg. Rx-Queue handling.
static void loop();
public:
// Helper for users of this class to estimate if an interaction would be blocking.
static size_t GetFreeTxBuffer();
// Checks two things: Can we confirm the presence of the display and has we initiliazed it.
// (both boils down that the display answered to our chatting)
static inline bool isInitialized() { return Initialized; }
private:
static void WriteHeader(uint16_t adr, uint8_t cmd, uint8_t payloadlen);
static void WritePGM(const char str[], uint8_t len);
static void ProcessRx();
static inline uint16_t swap16(const uint16_t value) { return (value & 0xffU) << 8U | (value >> 8U); }
static rx_datagram_state_t rx_datagram_state;
static uint8_t rx_datagram_len;
static bool Initialized, no_reentrance;
static DGUSLCD_Screens displayRequest;
};
#define GET_VARIABLE(f, t, V...) (&DGUSDisplay::GetVariable<decltype(t), f, t, ##V>)
#define SET_VARIABLE(f, t, V...) (&DGUSDisplay::SetVariable<decltype(t), f, t, ##V>)
extern DGUSDisplay dgusdisplay;
// compile-time x^y
template<typename T>
constexpr T cpow(const T x, const int y) { return y == 0 ? 1.0 : x * cpow(x, y - 1); }
/// Find the flash address of a DGUS_VP_Variable for the VP.
const DGUS_VP_Variable* DGUSLCD_FindVPVar(const uint16_t vp);
/// Helper to populate a DGUS_VP_Variable for a given VP. Return false if not found.
bool populate_VPVar(const uint16_t VP, DGUS_VP_Variable * const ramcopy);
@@ -1,53 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
/* DGUS implementation written by Sebastiaan Dammann in 2020 for Marlin */
#include "DGUSVPVariable.h"
#include <stdint.h>
// This file defines the interaction between Marlin and the display firmware.
// information on which screen which VP is displayed
// As this is a sparse table, two arrays are needed:
// one to list the VPs of one screen and one to map screens to the lists.
// (Strictly this would not be necessary, but allows to only send data the display needs and reducing load on Marlin)
struct VPMapping {
const uint8_t screen;
const uint16_t *VPList; // The list is null-terminated.
};
extern const struct VPMapping VPMap[];
// List of VPs handled by Marlin / The Display.
extern const struct DGUS_VP_Variable ListOfVP[];
#define DWIN_DEFAULT_FILLER_CHAR ' '
#define DWIN_SCROLLER_FILLER_CHAR 0x0
#include "../../../inc/MarlinConfig.h"
#if ENABLED(DGUS_LCD_UI_CREALITY_TOUCH)
#include "creality_touch/DGUSDisplayDef.h"
#endif
File diff suppressed because it is too large Load Diff
@@ -1,469 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "DGUSDisplay.h"
#include "DGUSVPVariable.h"
#include "../../../inc/MarlinConfig.h"
#if HAS_COLOR_LEDS
#include "../../../feature/leds/leds.h"
#if ENABLED(PRINTER_EVENT_LEDS)
#define HAS_COLOR_LEDS_PREFERENCES 1
#endif
#endif
#include "../../../module/motion.h"
enum DGUSLCD_Screens : uint8_t;
struct creality_dwin_settings_t {
size_t settings_size;
uint8_t settings_version;
bool led_state;
bool display_standby;
bool display_sound;
int16_t standby_screen_brightness;
int16_t screen_brightness;
int16_t standby_time_seconds;
#if HAS_COLOR_LEDS_PREFERENCES
LEDColor LastLEDColor;
#endif
};
class DGUSScreenHandler {
public:
DGUSScreenHandler() = default;
static bool loop();
static void Init();
static void DefaultSettings();
static void LoadSettings(const char* buff);
static void StoreSettings(char* buff);
static void SetTouchScreenConfiguration();
static void KillScreenCalled();
static void OnPowerlossResume();
static void RequestSaveSettings();
// Send all 4 strings that are displayed on the infoscreen, confirmation screen and kill screen
// The bools specifying whether the strings are in RAM or FLASH.
static void sendinfoscreen(const char *line1, const char *line2, const char *line3, const char *line4, bool l1inflash, bool l2inflash, bool l3inflash, bool liinflash);
static inline void sendinfoscreen(FSTR_P const line1, FSTR_P const line2, const char *line3, const char *line4, bool l1inflash, bool l2inflash, bool l3inflash, bool liinflash) {
sendinfoscreen(FTOP(line1), FTOP(line2), line3, line4, l1inflash, l2inflash, l3inflash, liinflash);
}
static inline void sendinfoscreen(FSTR_P const line1, FSTR_P const line2, FSTR_P const line3, FSTR_P const line4, bool l1inflash, bool l2inflash, bool l3inflash, bool liinflash) {
sendinfoscreen(FTOP(line1), FTOP(line2), FTOP(line3), FTOP(line4), l1inflash, l2inflash, l3inflash, liinflash);
}
static void HandleUserConfirmationPopUp(uint16_t ConfirmVP, const char* line1, const char* line2, const char* line3, const char* line4, bool l1inflash, bool l2inflash, bool l3inflash, bool liinflash);
static void HandleDevelopmentTestButton(DGUS_VP_Variable &var, void *val_ptr);
/// "M117" Message -- msg is a RAM ptr.
static void setstatusmessage(const char* msg);
/// The same for messages from Flash
static void setstatusmessagePGM(PGM_P const msg);
// Callback for VP "Display wants to change screen on idle printer"
static void ScreenChangeHookIfIdle(DGUS_VP_Variable &var, void *val_ptr);
// Callback for VP "Screen has been changed"
static void ScreenChangeHook(DGUS_VP_Variable &var, void *val_ptr);
// Callback for VP "All Heaters Off"
static void HandleAllHeatersOff(DGUS_VP_Variable &var, void *val_ptr);
// Hook for "Change this temperature"
static void HandleTemperatureChanged(DGUS_VP_Variable &var, void *val_ptr);
static void HandleFanSpeedChanged(DGUS_VP_Variable &var, void *val_ptr);
// Hook for "Change Flowrate"
static void HandleFlowRateChanged(DGUS_VP_Variable &var, void *val_ptr);
// Hook for manual extrude.
static void HandleManualExtrude(DGUS_VP_Variable &var, void *val_ptr);
// Hook for motor lock and unlook
static void HandleMotorLockUnlock(DGUS_VP_Variable &var, void *val_ptr);
#if ENABLED(POWER_LOSS_RECOVERY)
static void TogglePowerLossRecovery(DGUS_VP_Variable &var, void *val_ptr);
// Hook for power loss recovery.
static void HandlePowerLossRecovery(DGUS_VP_Variable &var, void *val_ptr);
#endif
// Version sanity check
static void HandleScreenVersion(DGUS_VP_Variable &var, void *val_ptr);
// Hook for settings
static void HandleStepPerMMChanged(DGUS_VP_Variable &var, void *val_ptr);
static void HandleStepPerMMExtruderChanged(DGUS_VP_Variable &var, void *val_ptr);
static void HandleFadeHeight(DGUS_VP_Variable &var, void *val_ptr);
// Hook for move to position
static void HandlePositionChange(DGUS_VP_Variable &var, void *val_ptr);
static void HandleToggleTouchScreenMute(DGUS_VP_Variable &var, void *val_ptr);
static void HandleToggleTouchScreenStandbySetting(DGUS_VP_Variable &var, void *val_ptr);
static void HandleTouchScreenBrightnessSetting(DGUS_VP_Variable &var, void *val_ptr);
static void HandleTouchScreenStandbyBrightnessSetting(DGUS_VP_Variable &var, void *val_ptr);
static void HandleTouchScreenStandbyTimeSetting(DGUS_VP_Variable &var, void *val_ptr);
#if HAS_PROBE_SETTINGS
static void HandleToggleProbeHeaters(DGUS_VP_Variable &var, void *val_ptr);
static void HandleToggleProbeTemperatureStabilization(DGUS_VP_Variable &var, void *val_ptr);
static void HandleToggleProbePreheatTemp(DGUS_VP_Variable &var, void *val_ptr);
#endif
#if HAS_PID_HEATING
// Hook for "Change this temperature PID para"
static void HandleTemperaturePIDChanged(DGUS_VP_Variable &var, void *val_ptr);
// Hook for PID autotune
static void HandlePIDAutotune(DGUS_VP_Variable &var, void *val_ptr);
#endif
static void HandleZoffsetChange(DGUS_VP_Variable &var, void *val_ptr);
#if HAS_MESH
// Hook for "Change probe offset z"
static void OnMeshLevelingStart();
static void OnMeshLevelingUpdate(const int8_t x, const int8_t y, const float z);
static void InitMeshValues();
static void ResetMeshValues();
static void UpdateMeshValue(const int8_t x, const int8_t y, const float z);
static void HandleMeshPoint(DGUS_VP_Variable &var, void *val_ptr);
#endif
// LED
#if HAS_COLOR_LEDS
static void HandleLED(DGUS_VP_Variable &var, void *val_ptr);
static void SendLEDToDisplay(DGUS_VP_Variable &var);
#endif
// Hook for live z adjust action
static void HandleLiveAdjustZ(DGUS_VP_Variable &var, void *val_ptr);
// Hook for heater control
static void HandleHeaterControl(DGUS_VP_Variable &var, void *val_ptr);
#if ENABLED(DGUS_PREHEAT_UI)
// Hook for preheat
static void HandlePreheat(DGUS_VP_Variable &var, void *val_ptr);
#endif
#if ENABLED(DGUS_FILAMENT_LOADUNLOAD)
// Hook for filament load and unload filament option
static void HandleFilamentOption(DGUS_VP_Variable &var, void *val_ptr);
// Hook for filament load and unload
static void HandleFilamentLoadUnload(DGUS_VP_Variable &var);
#endif
#if ENABLED(SDSUPPORT)
// Callback for VP "Display wants to change screen when there is a SD card"
static void ScreenChangeHookIfSD(DGUS_VP_Variable &var, void *val_ptr);
/// Scroll buttons on the file listing screen.
static void DGUSLCD_SD_ScrollFilelist(DGUS_VP_Variable &var, void *val_ptr);
/// File touched.
static void DGUSLCD_SD_FileSelected(DGUS_VP_Variable &var, void *val_ptr);
/// start print after confirmation received.
static void DGUSLCD_SD_StartPrint(DGUS_VP_Variable &var, void *val_ptr);
/// Send a single filename to the display.
static void DGUSLCD_SD_SendFilename(DGUS_VP_Variable &var);
/// Marlin informed us that a new SD has been inserted.
static void SDCardInserted();
/// Marlin informed us that the SD Card has been removed().
static void SDCardRemoved();
/// Marlin informed us about a bad SD Card.
static void SDCardError();
static void SetPrintingFromHost();
#endif
static void HandleLEDToggle();
static void HandleFanToggle();
static void FilamentRunout();
static void OnFactoryReset();
#if HAS_BUZZER || ENABLED(SPEAKER)
static void Buzzer(const uint16_t frequency, const uint16_t duration);
#endif
static void OnHomingStart();
static void OnHomingComplete();
static void OnPrintFinished();
// OK Button the Confirm screen.
static void ScreenConfirmedOK(DGUS_VP_Variable &var, void *val_ptr);
// Update data after went to new screen (by display or by GotoScreen)
// remember: store the last-displayed screen, so it can get returned to.
// (e.g for pop up messages)
static void UpdateNewScreen(DGUSLCD_Screens newscreen, bool save_current_screen=true);
// Recall the remembered screen.
static void PopToOldScreen();
static void OnBackButton(DGUS_VP_Variable &var, void *val_ptr);
// Make the display show the screen and update all VPs in it.
static void GotoScreen(DGUSLCD_Screens screen, bool save_current_screen = true);
static void UpdateScreenVPData();
// Helpers to convert and transfer data to the display.
static void DGUSLCD_SendWordValueToDisplay(DGUS_VP_Variable &var);
static void DGUSLCD_SendStringToDisplay(DGUS_VP_Variable &var);
static void DGUSLCD_SendScrollingStringToDisplay(DGUS_VP_Variable &var);
static void DGUSLCD_SendStringToDisplayPGM(DGUS_VP_Variable &var);
static void DGUSLCD_SendScrollingStringToDisplayPGM(DGUS_VP_Variable &var);
static void DGUSLCD_SendTemperaturePID(DGUS_VP_Variable &var);
static void DGUSLCD_SendPercentageToDisplay(DGUS_VP_Variable &var);
static void DGUSLCD_SendPrintProgressToDisplay(DGUS_VP_Variable &var);
static void DGUSLCD_SendPrintTimeToDisplay(DGUS_VP_Variable &var);
static void DGUSLCD_SendPrintTimeWithRemainingToDisplay(DGUS_VP_Variable &var);
static void DGUSLCD_SendPrintTimeRemainingToDisplay(DGUS_VP_Variable &var);
#if ENABLED(PRINTCOUNTER)
static void DGUSLCD_SendPrintAccTimeToDisplay(DGUS_VP_Variable &var);
static void DGUSLCD_SendPrintsTotalToDisplay(DGUS_VP_Variable &var);
#endif
#if HAS_FAN
static void DGUSLCD_SendFanStatusToDisplay(DGUS_VP_Variable &var);
static void DGUSLCD_SendFanSpeedToDisplay(DGUS_VP_Variable &var);
#endif
static void DGUSLCD_SendHeaterStatusToDisplay(DGUS_VP_Variable &var);
#if ENABLED(DGUS_UI_WAITING)
static void DGUSLCD_SendWaitingStatusToDisplay(DGUS_VP_Variable &var);
#endif
static void DGUSLCD_SendAboutFirmwareWebsite(DGUS_VP_Variable &var);
static void DGUSLCD_SendAboutFirmwareVersion(DGUS_VP_Variable &var);
static void DGUSLCD_SendAboutPrintSize(DGUS_VP_Variable &var);
/// Send a value from 0..100 to a variable with a range from 0..255
static void DGUSLCD_PercentageToUint8(DGUS_VP_Variable &var, void *val_ptr);
template<typename T>
static void DGUSLCD_SetValueDirectly(DGUS_VP_Variable &var, void *val_ptr) {
if (!var.memadr) return;
union { unsigned char tmp[sizeof(T)]; T t; } x;
unsigned char *ptr = (unsigned char*)val_ptr;
LOOP_L_N(i, sizeof(T)) x.tmp[i] = ptr[sizeof(T) - i - 1];
*(T*)var.memadr = x.t;
}
template<DGUSLCD_Screens TPage>
static void DGUSLCD_NavigateToPage(DGUS_VP_Variable &var, void *val_ptr) {
GotoScreen(TPage);
}
template<DGUSLCD_Screens TPage, typename Handler>
static void DGUSLCD_NavigateToPage(DGUS_VP_Variable &var, void *val_ptr) {
GotoScreen(TPage);
Handler::Init();
}
/// Send a float value to the display.
/// Display will get a 4-byte integer scaled to the number of digits:
/// Tell the display the number of digits and it cheats by displaying a dot between...
template<unsigned int decimals>
static void DGUSLCD_SendFloatAsLongValueToDisplay(DGUS_VP_Variable &var) {
if (var.memadr) {
double d = static_cast<double>(*(float *)var.memadr);
d *= cpow(10, decimals);
// Round - truncated values look like skipped numbers
static_assert(sizeof(long) == 4, "Assuming long is 4 bytes");
long roundedValue = static_cast<long>(round(d));
dgusdisplay.WriteVariable(var.VP, roundedValue);
}
}
// Receive a float from the display - Display will send a 2-byte integer scaled to the number of digits
template<unsigned int decimals>
static void DGUSLCD_SetFloatAsIntFromDisplay(DGUS_VP_Variable &var, void *val_ptr) {
if (var.memadr) {
uint16_t value_raw = swap16(*(uint16_t*)val_ptr);
float value = static_cast<float>(static_cast<double>(value_raw) /cpow(10, decimals));
*(float *)var.memadr = value;
}
}
// Receive a float from the display - Display will send a 4-byte integer scaled to the number of digits
template<unsigned int decimals>
static void DGUSLCD_SetFloatAsLongFromDisplay(DGUS_VP_Variable &var, void *val_ptr) {
if (var.memadr) {
uint32_t value_raw = uInt32Value(*(uint32_t*)val_ptr);
float value = static_cast<float>(static_cast<double>(value_raw) /cpow(10, decimals));
*(float *)var.memadr = value;
}
}
static void DGUSLCD_SendULongToDisplay(DGUS_VP_Variable &var) {
if (var.memadr) {
// Round - truncated values look like skipped numbers
long roundedValue = *(uint32_t *) var.memadr;
dgusdisplay.WriteVariable(var.VP, roundedValue);
}
}
static void DGUSLCD_ReceiveULongFromDisplay(DGUS_VP_Variable &var, void* val_ptr) {
if (var.memadr) {
// Round - truncated values look like skipped numbers
uint32_t incomingValue = *(uint32_t *) val_ptr;
*(uint32_t*)var.memadr = uInt32Value(incomingValue);
}
}
// Toggle a boolean at the specified memory address
static void DGUSLCD_ToggleBoolean(DGUS_VP_Variable &var, void *val_ptr) {
if (var.memadr) {
SERIAL_ECHOLNPGM("Toggle boolean - ", var.VP);
bool* val = (bool *)var.memadr;
*val = !*val;
}
}
// Send an icon to the display, depending on whether it is true or false
template<unsigned int value_if_true, unsigned int value_if_false>
static void DGUSLCD_SendIconValue(DGUS_VP_Variable &var) {
if (var.memadr) {
bool value = *(bool *)var.memadr;
uint16_t valueToSend = value ? value_if_true : value_if_false;
dgusdisplay.WriteVariable(var.VP, valueToSend);
}
}
/// Send a float value to the display.
/// Display will get a 2-byte integer scaled to the number of digits:
/// Tell the display the number of digits and it cheats by displaying a dot between...
template<unsigned int decimals>
static void DGUSLCD_SendFloatAsIntValueToDisplay(DGUS_VP_Variable &var) {
if (var.memadr) {
double d = static_cast<double>(*(float *)var.memadr);
d *= cpow(10, decimals);
// Round - truncated values look like skipped numbers
int16_t roundedValue = static_cast<int16_t>(round(d));
dgusdisplay.WriteVariable(var.VP, roundedValue);
}
}
template<AxisEnum Axis>
static void SendAxisTrustValue(DGUS_VP_Variable &var) {
bool trust = axis_is_trusted(Axis);
uint16_t color = trust ? 0xFFFF /*White*/ : 0XF800 /*Red*/;
dgusdisplay.SetVariableDisplayColor(var.VP, color);
}
/// Force an update of all VP on the current screen.
static inline void ForceCompleteUpdate() { update_ptr = 0; ScreenComplete = false; }
/// Has all VPs sent to the screen
static inline bool IsScreenComplete() { return ScreenComplete; }
static inline DGUSLCD_Screens getCurrentScreen() { return current_screen; }
static bool HandlePendingUserConfirmation();
static void SetSynchronousOperationStart();
static void SetSynchronousOperationFinish();
static bool HasCurrentSynchronousOperation() { return HasSynchronousOperation; }
static void SendBusyState(DGUS_VP_Variable &var);
static void SetViewMeshLevelState();
static bool fwretract_available;
private:
static void HandleScreenVersionMismatchLEDFlash();
static DGUSLCD_Screens current_screen; ///< currently on screen
static constexpr uint8_t NUM_PAST_SCREENS = 4;
static DGUSLCD_Screens past_screens[NUM_PAST_SCREENS]; ///< LIFO with past screens for the "back" button.
static uint8_t update_ptr; ///< Last sent entry in the VPList for the actual screen.
static uint16_t skipVP; ///< When updating the screen data, skip this one, because the user is interacting with it.
static bool ScreenComplete; ///< All VPs sent to screen?
static uint16_t ConfirmVP; ///< context for confirm screen (VP that will be emulated-sent on "OK").
static uint8_t MeshLevelIndex;
static uint8_t MeshLevelIconIndex;
static bool SaveSettingsRequested;
static bool HasScreenVersionMismatch;
static bool HasSynchronousOperation;
#if ENABLED(SDSUPPORT)
static int16_t top_file; ///< file on top of file chooser
static int16_t file_to_print; ///< touched file to be confirmed
#endif
private:
FORCE_INLINE static DGUSLCD_Screens GetPreviousScreen() {
return past_screens[0];
}
public: // Needed for VP auto-upload
static bool HasRGBSettings;
static creality_dwin_settings_t Settings;
};
extern DGUSScreenHandler ScreenHandler;
struct DGUSSynchronousOperation {
private:
bool is_running;
public:
DGUSSynchronousOperation() : is_running(false) {}
// Don't allow this to be created on the stack
void* operator new (std::size_t size) = delete;
void start() {
is_running = true;
ScreenHandler.SetSynchronousOperationStart();
}
void done() {
is_running = false;
ScreenHandler.SetSynchronousOperationFinish();
}
~DGUSSynchronousOperation() {
if (is_running) {
ScreenHandler.SetSynchronousOperationFinish();
}
}
};
@@ -1,67 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <stdint.h>
/**
* DGUSVPVariable.h
*
* Created on: Feb 9, 2019
* Author: tobi
*/
struct DGUS_VP_Variable {
uint16_t VP;
void* memadr; // If nullptr, the value cannot be uploaded to the display.
uint8_t size;
// Callback that will be called if the display modified the value.
// nullptr makes it readonly for the display.
void (*set_by_display_handler)(DGUS_VP_Variable &var, void *val_ptr);
void (*send_to_display_handler)(DGUS_VP_Variable &var);
template<typename T>
DGUS_VP_Variable& operator =(T &o) {
*(T*)memadr = o; // warning this is not typesafe.
// TODO: Call out the display or mark as dirty for the next update.
return *this;
}
};
// endianness swap
FORCE_INLINE uint16_t swap16(const uint16_t value) { return (value & 0xffU) << 8U | (value >> 8U); }
FORCE_INLINE int16_t swap16(const int16_t value) {
union { int16_t l; char lb[2]; } endian;
endian.l = value;
char tmp = endian.lb[1];
endian.lb[1] = endian.lb[0];
endian.lb[0] = tmp;
return endian.l;
}
FORCE_INLINE uint32_t uInt32Value(const uint32_t value) { return ((value>>24)&0xff) | ((value<<8)&0xff0000) | ((value>>8)&0xff00) | ((value<<24)&0xff000000); }
FORCE_INLINE uint16_t uInt16Value(void *val_ptr) { return swap16(*static_cast<uint16_t*>(val_ptr)); }
@@ -1,230 +0,0 @@
#include "../../../../inc/MarlinConfigPre.h"
#if ENABLED(DGUS_LCD_UI_CREALITY_TOUCH)
#include "../DGUSDisplayDef.h"
#include "../DGUSDisplay.h"
#include "../DGUSScreenHandler.h"
#include "EstepsHandler.h"
#include "AxisSettingsHandler.h"
#include "../../ui_api.h"
#include "../../../marlinui.h"
#include "../../../../module/temperature.h"
#include "../../../../module/settings.h"
#include "../../../../module/planner.h"
#include "../../../../gcode/gcode.h"
#if HAS_TRINAMIC_CONFIG
#include "../../../../feature/tmc_util.h"
#include "../../../../module/stepper/indirection.h"
#endif
AxisEnum AxisSettingsHandler::current_axis;
uint16_t AxisSettingsHandler::axis_settings_title_icon = ICON_AXIS_SETTINGS_TITLE_X;
float AxisSettingsHandler::axis_steps_mm;
uint16_t AxisSettingsHandler::max_acceleration_mm_per_s2;
float AxisSettingsHandler::jerk;
feedRate_t AxisSettingsHandler::max_feedrate;
#if HAS_TRINAMIC_CONFIG
bool AxisSettingsHandler::has_tmc_settings = true;
#else
bool AxisSettingsHandler::has_tmc_settings = false;
#endif
uint16_t AxisSettingsHandler::tmc_current;
bool AxisSettingsHandler::stealthchop;
uint32_t AxisSettingsHandler::hybrid_threshold;
void AxisSettingsHandler::HandleNavigation(DGUS_VP_Variable &var, void *val_ptr) {
switch (uInt16Value(val_ptr)) {
case AXIS_SETTINGS_NAV_BUTTON_VAL_X:
current_axis = X_AXIS;
axis_settings_title_icon = ICON_AXIS_SETTINGS_TITLE_X;
break;
case AXIS_SETTINGS_NAV_BUTTON_VAL_Y:
current_axis = Y_AXIS;
axis_settings_title_icon = ICON_AXIS_SETTINGS_TITLE_Y;
break;
case AXIS_SETTINGS_NAV_BUTTON_VAL_Z:
current_axis = Z_AXIS;
axis_settings_title_icon = ICON_AXIS_SETTINGS_TITLE_Z;
break;
case AXIS_SETTINGS_NAV_BUTTON_VAL_E:
current_axis = E_AXIS;
axis_settings_title_icon = ICON_AXIS_SETTINGS_TITLE_E;
break;
}
// Load settings for axis
axis_steps_mm = planner.settings.axis_steps_per_mm[current_axis];
max_acceleration_mm_per_s2 = static_cast<uint16_t>(planner.settings.max_acceleration_mm_per_s2[current_axis]);
IF_ENABLED(CLASSIC_JERK, jerk = planner.max_jerk[current_axis]);
max_feedrate = planner.settings.max_feedrate_mm_s[current_axis];
#if HAS_TRINAMIC_CONFIG
switch (current_axis){
#if AXIS_IS_TMC(X)
case X_AXIS:
tmc_current = stepperX.getMilliamps();
#if AXIS_HAS_STEALTHCHOP(X)
stealthchop = stepperX.get_stored_stealthChop();
#if ENABLED(HYBRID_THRESHOLD)
hybrid_threshold = static_cast<uint32_t>(stepperX.get_pwm_thrs());
#endif
#endif
break;
#endif
#if AXIS_IS_TMC(Y)
case Y_AXIS:
tmc_current = stepperY.getMilliamps();
#if AXIS_HAS_STEALTHCHOP(Y)
stealthchop = stepperY.get_stored_stealthChop();
#if ENABLED(HYBRID_THRESHOLD)
hybrid_threshold = static_cast<uint32_t>(stepperY.get_pwm_thrs());
#endif
#endif
break;
#endif
#if AXIS_IS_TMC(Z)
case Z_AXIS:
tmc_current = stepperZ.getMilliamps();
#if AXIS_HAS_STEALTHCHOP(Z)
stealthchop = stepperZ.get_stored_stealthChop();
#if ENABLED(HYBRID_THRESHOLD)
hybrid_threshold = static_cast<uint32_t>(stepperZ.get_pwm_thrs());
#endif
#endif
break;
#endif
#if AXIS_IS_TMC(E0)
case E_AXIS:
tmc_current = stepperE0.getMilliamps();
#if AXIS_HAS_STEALTHCHOP(E0)
stealthchop = stepperE0.get_stored_stealthChop();
#if ENABLED(HYBRID_THRESHOLD)
hybrid_threshold = static_cast<uint32_t>(stepperE0.get_pwm_thrs());
#endif
#endif
break;
#endif
default:
// Too bad
break;
}
#endif
// Nav
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_AXIS_SETTINGS_AXIS);
}
void AxisSettingsHandler::HandleBackNavigation(DGUS_VP_Variable &var, void *val_ptr) {
// Save settings for axis
planner.settings.axis_steps_per_mm[current_axis] = axis_steps_mm;
planner.settings.max_acceleration_mm_per_s2[current_axis] = max_acceleration_mm_per_s2;
IF_ENABLED(CLASSIC_JERK, planner.max_jerk[current_axis] = jerk);
planner.settings.max_feedrate_mm_s[current_axis] = max_feedrate;
// If we're handling the E-axis, the back button might end on that screen. Show that we didn't forget the settings.
if (current_axis == E_AXIS) {
EstepsHandler::set_esteps = axis_steps_mm;
EstepsHandler::calculated_esteps = axis_steps_mm;
}
#if HAS_TRINAMIC_CONFIG
switch (current_axis){
#if AXIS_IS_TMC(X)
case X_AXIS:
stepperX.rms_current(tmc_current);
#if AXIS_HAS_STEALTHCHOP(X)
stepperX.set_stealthChop(stealthchop);
#if ENABLED(HYBRID_THRESHOLD)
stepperX.set_pwm_thrs(hybrid_threshold);
#endif
#endif
break;
#endif
#if AXIS_IS_TMC(Y)
case Y_AXIS:
stepperY.rms_current(tmc_current);
#if AXIS_HAS_STEALTHCHOP(Y)
stepperY.set_stealthChop(stealthchop);
#if ENABLED(HYBRID_THRESHOLD)
stepperY.set_pwm_thrs(hybrid_threshold);
#endif
#endif
break;
#endif
#if AXIS_IS_TMC(Z)
case Z_AXIS:
stepperZ.rms_current(tmc_current);
#if AXIS_HAS_STEALTHCHOP(Z)
stepperZ.set_stealthChop(stealthchop);
#if ENABLED(HYBRID_THRESHOLD)
stepperZ.set_pwm_thrs(hybrid_threshold);
#endif
#endif
break;
#endif
#if AXIS_IS_TMC(E0)
case E_AXIS:
stepperE0.rms_current(tmc_current);
#if AXIS_HAS_STEALTHCHOP(E0)
stepperE0.set_stealthChop(stealthchop);
#if ENABLED(HYBRID_THRESHOLD)
stepperE0.set_pwm_thrs(hybrid_threshold);
#endif
#endif
break;
#endif
default:
// Too bad
break;
}
#endif
// Save and pop
ScreenHandler.PopToOldScreen();
settings.save();
}
void AxisSettingsHandler::HandleTMCNavigation(DGUS_VP_Variable &var, void *val_ptr) {
#if HAS_TRINAMIC_CONFIG
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_AXIS_SETTINGS_TMC);
#endif
}
#endif
@@ -1,26 +0,0 @@
#include <cstdint>
class AxisSettingsHandler {
private:
static AxisEnum current_axis;
public:
static uint16_t axis_settings_title_icon;
static float axis_steps_mm;
static uint16_t max_acceleration_mm_per_s2;
static float jerk;
static feedRate_t max_feedrate;
static bool has_tmc_settings;
static uint16_t tmc_current;
static bool stealthchop;
static uint32_t hybrid_threshold;
public:
static void HandleNavigation(DGUS_VP_Variable &var, void *val_ptr);
static void HandleBackNavigation(DGUS_VP_Variable &var, void *val_ptr);
static void HandleTMCNavigation(DGUS_VP_Variable &var, void *val_ptr);
};
@@ -1,796 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/* DGUS implementation written by Sebastiaan Dammann in 2020 for Marlin */
#include "../../../../inc/MarlinConfigPre.h"
#if ENABLED(DGUS_LCD_UI_CREALITY_TOUCH)
#include "../DGUSDisplayDef.h"
#include "../DGUSDisplay.h"
#include "../DGUSScreenHandler.h"
#include "AxisSettingsHandler.h"
#include "EstepsHandler.h"
#include "FilamentLoadUnloadHandler.h"
#include "PIDHandler.h"
#include "MeshValidationHandler.h"
#include "../../../../module/temperature.h"
#include "../../../../module/motion.h"
#include "../../../../module/planner.h"
#include "../../../../feature/caselight.h"
#if ENABLED(BABYSTEPPING)
#include "../../../../feature/babystep.h"
#endif
#if ENABLED(FWRETRACT)
#include "../../../../feature/fwretract.h"
#endif
#if HAS_COLOR_LEDS
#include "../../../../feature/leds/leds.h"
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
#include "../../../../feature/powerloss.h"
#endif
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
#include "../../../../feature/runout.h"
#endif
#include "../../ui_api.h"
#include "../../../marlinui.h"
#include "PageHandlers.h"
#if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
uint16_t distanceToMove = 10;
#endif
using namespace ExtUI;
const char MarlinVersion[] PROGMEM = SHORT_BUILD_VERSION;
// ----- Common var lists
#if HOTENDS >= 1
#define VPList_HeatHotend VP_T_E0_Is, VP_T_E0_Set,
#else
#define VPList_HeatHotend
#endif
#if HAS_HEATED_BED
#define VPList_HeatBed VP_T_Bed_Is, VP_T_Bed_Set,
#else
#define VPList_HeatBed
#endif
#define VPList_Common VP_BACK_BUTTON_STATE, VP_Z_OFFSET, VP_BUTTON_BEDLEVELKEY
#define VPList_CommonWithStatus VPList_HeatHotend VPList_HeatBed VP_Z_OFFSET, VP_Feedrate_Percentage, VP_BACK_BUTTON_STATE
#define VPList_CommonWithHeatOnly VPList_HeatHotend VPList_HeatBed VP_BACK_BUTTON_STATE, VP_Z_OFFSET
// ----- Which variables to auto-update on which screens
const uint16_t VPList_None[] PROGMEM = {
VPList_Common,
0x0000
};
const uint16_t VPList_DialogStop[] PROGMEM = {
VPList_Common,
0x0000
};
const uint16_t VPList_Main[] PROGMEM = {
VPList_CommonWithStatus,
0x0000
};
const uint16_t VPList_SDFileList[] PROGMEM = {
VPList_CommonWithStatus,
VP_SD_FileName0,
VP_SD_FileName1,
VP_SD_FileName2,
VP_SD_FileName3,
VP_SD_FileName4,
VP_SD_FileName5,
0x0000
};
const uint16_t VPList_Control[] PROGMEM = {
VPList_CommonWithStatus,
VP_LED_TOGGLE,
VP_MUTE_ICON,
0x0000
};
const uint16_t VPList_Feed[] PROGMEM = {
VPList_CommonWithStatus,
VP_FILCHANGE_NOZZLE_TEMP,
VP_FILCHANGE_LENGTH,
0x0000
};
const uint16_t VPList_Temp[] PROGMEM = {
VPList_CommonWithStatus,
VP_FAN_TOGGLE,
0x0000
};
const uint16_t VPList_PreheatPLASettings[] PROGMEM = {
VPList_CommonWithStatus,
VP_PREHEAT_PLA_HOTEND_TEMP,
VP_PREHEAT_PLA_BED_TEMP,
0x0000
};
const uint16_t VPList_PreheatABSSettings[] PROGMEM = {
VPList_CommonWithStatus,
VP_PREHEAT_ABS_HOTEND_TEMP,
VP_PREHEAT_ABS_BED_TEMP,
0x0000
};
const uint16_t VPList_PrintPausingError[] PROGMEM = {
VPList_CommonWithStatus,
VP_X_POSITION,
VP_Y_POSITION,
VP_Z_POSITION_PRECISION,
VP_Z_OFFSET,
VP_Fan0_Percentage,
VP_Feedrate_Percentage,
VP_PrintProgress_Percentage,
VP_PrintTimeProgressBar,
VP_PrintTime,
VP_PrintTimeWithRemainingVisible,
VP_PrintTimeRemaining,
VP_LINEAR_ADVANCE_FACTOR,
0x0000
};
const uint16_t VPList_PrintScreen[] PROGMEM = {
VPList_CommonWithStatus,
VP_X_POSITION, VP_Y_POSITION, VP_Z_POSITION, VP_Z_POSITION_PRECISION,
SP_X_POSITION, SP_Y_POSITION, SP_Z_POSITION,
VP_Flowrate_E0,
VP_Fan0_Percentage,
VP_PrintProgress_Percentage,
VP_PrintTimeProgressBar,
VP_PrintTime,
VP_PrintTimeWithRemainingVisible,
VP_PrintTimeRemaining,
VP_LINEAR_ADVANCE_FACTOR,
VP_FWRETRACT_INDICATOR_ICON,
0x0000
};
const uint16_t VPList_Leveling[] PROGMEM = {
VPList_CommonWithStatus,
VP_MESH_LEVEL_TEMP,
0x0000
};
const uint16_t VPList_ZOffsetLevel[] PROGMEM = {
VPList_CommonWithStatus,
0x0000
};
const uint16_t VPList_TuneScreen[] PROGMEM = {
VPList_CommonWithStatus,
VP_PrintTime,
VP_Flowrate_E0,
VP_LED_TOGGLE,
VP_FAN_TOGGLE,
VP_Fan0_Percentage,
0x0000
};
const uint16_t VPList_TuneExtraScreen[] PROGMEM = {
VPList_CommonWithStatus,
VP_LINEAR_ADVANCE_FACTOR,
VP_RGB_NAV_BUTTON_ICON,
0x0000
};
const uint16_t VPList_Prepare[] PROGMEM = {
VPList_CommonWithStatus,
VP_PrintTime,
0x0000
};
const uint16_t VPList_Info[] PROGMEM = {
VPList_CommonWithStatus,
VP_PrintTime,
VP_PRINTER_BEDSIZE,
VP_MARLIN_WEBSITE,
VP_MARLIN_VERSION,
0x0000
};
const uint16_t VPList_EstepsCalibration[] PROGMEM = {
VPList_CommonWithHeatOnly,
VP_ESTEPS_CURRENT,
VP_ESTEPS_CALIBRATION_TEMP,
VP_ESTEPS_CALIBRATION_LENGTH,
VP_ESTEPS_CALIBRATION_LEFTOVER_LENGTH,
VP_ESTEPS_CALIBRATION_MARK_LENGTH,
VP_ESTEPS_CALCULATED_ESTEPS,
0x0000
};
const uint16_t VPList_PidTune[] PROGMEM = {
VPList_CommonWithHeatOnly,
VP_PIDTUNE_TARGET_TEMP,
VP_PIDTUNE_FAN_TOGGLE_ICON,
VP_PIDTUNE_CYCLES,
0x0000
};
const uint16_t VPList_FWRetractTune[] PROGMEM = {
VPList_CommonWithStatus,
VP_FWRETRACT_RETRACT_LENGTH,
VP_FWRETRACT_RETRACT_FEEDRATE,
VP_FWRETRACT_RETRACT_ZHOP,
VP_FWRETRACT_RESTART_LENGTH,
VP_FWRETRACT_RESTART_FEEDRATE,
VP_FWRETRACT_TOGGLE_BUTTON_ICON,
0x0000
};
const uint16_t VPList_LevelingSettings[] PROGMEM = {
VPList_CommonWithStatus,
VP_TOGGLE_PROBING_HEATERS_OFF_ONOFF_ICON,
VP_TOGGLE_PROBE_PREHEAT_HOTEND_TEMP,
VP_TOGGLE_PROBE_PREHEAT_BED_TEMP,
VP_TOGGLE_POST_PROBING_TEMPERATURE_STABILIZATION_ICON,
VP_LEVELING_FADE_HEIGHT,
0x0000
};
const uint16_t VPList_AxisSettingsNav[] PROGMEM = {
VPList_CommonWithStatus,
0x0000
};
const uint16_t VPList_AxisSettingsAxis[] PROGMEM = {
VPList_CommonWithHeatOnly,
VP_AXIS_SETTINGS_TITLE_ICON,
VP_AXIS_SETTINGS_AXIS_STEPSMM,
VP_AXIS_SETTINGS_AXIS_MAX_ACCEL,
VP_AXIS_SETTINGS_AXIS_JERK,
VP_AXIS_SETTINGS_AXIS_FEEDRATE,
VP_AXIS_TMC_NAV_ICON,
0x0000
};
const uint16_t VPList_AxisSettingsTMC[] PROGMEM = {
VPList_CommonWithHeatOnly,
VP_AXIS_SETTINGS_AXIS_TMCCURRENT,
VP_AXIS_SETTINGS_AXIS_TMCSTEALTHCHOP_ICON,
VP_AXIS_SETTINGS_AXIS_TMCHYBRIDTHRESHOLD,
0x0000
};
const uint16_t VPList_AdvMovementSettings[] PROGMEM = {
VPList_CommonWithHeatOnly,
VP_MOV_MINIMUM_SEGMENT_TIME,
VP_MOV_MINIMUM_FEEDRATE,
VP_MOV_NORMAL_ACCELERATION,
VP_MOV_RETRACT_ACCELERATION,
VP_MOV_MINIMUM_TRAVEL_FEEDRATE,
VP_MOV_MINIMUM_TRAVEL_ACCELERATION,
0x0000
};
const uint16_t VPList_MiscSettings[] PROGMEM = {
VPList_CommonWithHeatOnly,
VP_FILAMENTRUNOUT_SENSOR_TOGGLE_ICON,
VP_PLR_TOGGLE_ICON,
VP_STANDBY_BACKLIGHT_ICON,
VP_SCREEN_BACKLIGHT_STANDBY,
VP_SCREEN_BACKLIGHT,
VP_SCREEN_STANDBY_TIME,
VP_RGB_NAV_BUTTON_ICON,
0x0000
};
const uint16_t VPList_MeshValidation[] PROGMEM = {
VPList_CommonWithHeatOnly,
VP_MESHPATTERN_NOZZLE_TEMP,
VP_MESHPATTERN_BED_TEMP,
VP_MESHPATTERN_BUTTON_ICON,
0x0000
};
const uint16_t VPList_Calibrate[] PROGMEM = {
VPList_CommonWithStatus,
0x0000
};
const uint16_t VPList_RGB[] PROGMEM = {
VPList_CommonWithHeatOnly,
VP_RGB_CONTROL_R,
VP_RGB_CONTROL_G,
VP_RGB_CONTROL_B,
VP_RGB_CONTROL_W,
VP_RGB_CONTROL_I,
0x0000
};
// -- Mapping from screen to variable list
const struct VPMapping VPMap[] PROGMEM = {
{ DGUSLCD_SCREEN_BOOT, VPList_None },
{ DGUSLCD_SCREEN_MAIN, VPList_Main },
{ DGUSLCD_SCREEN_SDFILELIST, VPList_SDFileList },
{ DGUSLCD_SCREEN_FILAMENTRUNOUT1, VPList_PrintPausingError },
{ DGUSLCD_SCREEN_FILAMENTRUNOUT2, VPList_PrintPausingError },
{ DGUSLCD_SCREEN_PRINT_FINISH, VPList_PrintScreen },
{ DGUSLCD_SCREEN_PRINT_RUNNING, VPList_PrintScreen },
{ DGUSLCD_SCREEN_PRINT_PAUSED, VPList_PrintScreen },
{ DGUSLCD_SCREEN_TUNING, VPList_TuneScreen },
{ DGUSLCD_SCREEN_TUNING_EXTRA, VPList_TuneExtraScreen },
{ DGUSLCD_SCREEN_PREPARE, VPList_Prepare },
{ DGUSLCD_SCREEN_INFO, VPList_Info },
{ DGUSLCD_SCREEN_MOVE1MM, VPList_PrintScreen },
{ DGUSLCD_SCREEN_MOVE10MM, VPList_PrintScreen },
{ DGUSLCD_SCREEN_MOVE01MM, VPList_PrintScreen },
{ DGUSLCD_SCREEN_FEED, VPList_Feed },
{ DGUSLCD_SCREEN_SETUP, VPList_Control },
{ DGUSLCD_SCREEN_TEMP, VPList_Temp },
{ DGUSLCD_SCREEN_TEMP_PLA, VPList_PreheatPLASettings },
{ DGUSLCD_SCREEN_TEMP_ABS, VPList_PreheatABSSettings },
{ DGUSLCD_SCREEN_INFO, VPList_PrintScreen },
{ DGUSLCD_SCREEN_ZOFFSET_LEVEL, VPList_ZOffsetLevel },
{ DGUSLCD_SCREEN_LEVELING, VPList_Leveling },
{ DGUSLCD_SCREEN_POWER_LOSS, VPList_None },
{ DGUSLCD_SCREEN_THERMAL_RUNAWAY, VPList_None },
{ DGUSLCD_SCREEN_HEATING_FAILED, VPList_None },
{ DGUSLCD_SCREEN_THERMISTOR_ERROR, VPList_None },
{ DGUSLCD_SCREEN_AUTOHOME, VPList_PrintScreen },
{ DGUSLCD_SCREEN_DIALOG_PAUSE, VPList_None },
{ DGUSLCD_SCREEN_DIALOG_STOP, VPList_DialogStop },
{ DGUSLCD_SCREEN_CONFIRM, VPList_None },
{ DGUSLCD_SCREEN_POPUP, VPList_None },
{ DGUSLCD_SCREEN_ESTEPS_CALIBRATION, VPList_EstepsCalibration },
{ DGUSLCD_SCREEN_PIDTUNE_CALIBRATION, VPList_PidTune },
{ DGUSLCD_SCREEN_TUNEFWRETRACT, VPList_FWRetractTune },
{ DGUSLCD_SCREEN_ESTEPS_CALIBRATION_RESULTS, VPList_EstepsCalibration },
{ DGUSLCD_SCREEN_LEVELING_SETTINGS, VPList_LevelingSettings },
{ DGUSLCD_SCREEN_AXIS_SETTINGS_NAV, VPList_AxisSettingsNav },
{ DGUSLCD_SCREEN_AXIS_SETTINGS_AXIS , VPList_AxisSettingsAxis },
{ DGUSLCD_SCREEN_AXIS_SETTINGS_TMC, VPList_AxisSettingsTMC },
{ DGUSLCD_SCREEN_ADV_MOV_SETTINGS, VPList_AdvMovementSettings },
{ DGUSLCD_SCREEN_MISC_SETTINGS, VPList_MiscSettings },
{ DGUSLCD_SCREEN_MESH_VALIDATION, VPList_MeshValidation },
{ DGUSLCD_SCREEN_CALIBRATE, VPList_Calibrate },
{ DGUSLCD_SCREEN_RGB, VPList_RGB},
{ 0 , nullptr } // List is terminated with an nullptr as table entry.
};
// Helper to define a DGUS_VP_Variable for common use cases.
#define VPHELPER(VPADR, VPADRVAR, RXFPTR, TXFPTR ) { .VP=VPADR, .memadr=VPADRVAR, .size=sizeof(VPADRVAR), \
.set_by_display_handler = RXFPTR, .send_to_display_handler = TXFPTR }
// Helper to define a DGUS_VP_Variable when the sizeo of the var cannot be determined automaticalyl (eg. a string)
#define VPHELPER_STR(VPADR, VPADRVAR, STRLEN, RXFPTR, TXFPTR ) { .VP=VPADR, .memadr=VPADRVAR, .size=STRLEN, \
.set_by_display_handler = RXFPTR, .send_to_display_handler = TXFPTR }
const struct DGUS_VP_Variable ListOfVP[] PROGMEM = {
// Back button state
VPHELPER(VP_BACK_BUTTON_STATE, nullptr, nullptr, ScreenHandler.SendBusyState),
// Screen version
VPHELPER(VP_UI_VERSION_MAJOR, nullptr, ScreenHandler.HandleScreenVersion, nullptr),
#if HOTENDS >= 1
VPHELPER(VP_Flowrate_E0, &planner.flow_percentage[ExtUI::extruder_t::E0], ScreenHandler.HandleFlowRateChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_T_E0_Is, &thermalManager.temp_hotend[0].celsius, nullptr, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<0>),
VPHELPER(VP_T_E0_Set, &thermalManager.temp_hotend[0].target, ScreenHandler.HandleTemperatureChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
#endif
#if HAS_HEATED_BED
VPHELPER(VP_T_Bed_Is, &thermalManager.temp_bed.celsius, nullptr, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<0>),
VPHELPER(VP_T_Bed_Set, &thermalManager.temp_bed.target, ScreenHandler.HandleTemperatureChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
#endif
VPHELPER(VP_MESH_LEVEL_TEMP, &thermalManager.temp_hotend[0].target, nullptr, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
// Feedrate
VPHELPER(VP_Feedrate_Percentage, &feedrate_percentage, ScreenHandler.DGUSLCD_SetValueDirectly<int16_t>, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_PrintProgress_Percentage, nullptr, nullptr, ScreenHandler.DGUSLCD_SendPrintProgressToDisplay),
VPHELPER(VP_PrintTimeProgressBar, nullptr, nullptr, ScreenHandler.DGUSLCD_SendPrintProgressToDisplay),
// Calibration
// ... e-steps
VPHELPER(VP_ESTEPS_CURRENT, &EstepsHandler::set_esteps, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_ESTEPS_CALIBRATION_TEMP, &EstepsHandler::calibration_temperature, ScreenHandler.DGUSLCD_SetValueDirectly<uint16_t>, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_ESTEPS_CALIBRATION_LENGTH, &EstepsHandler::filament_to_extrude, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_ESTEPS_CALIBRATION_MARK_LENGTH, &EstepsHandler::mark_filament_mm, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_ESTEPS_CALIBRATION_LEFTOVER_LENGTH, &EstepsHandler::remaining_filament, EstepsHandler::HandleRemainingFilament, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_ESTEPS_CALCULATED_ESTEPS, &EstepsHandler::calculated_esteps, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_ESTEPS_CALIBRATESTART_BUTTON, nullptr, EstepsHandler::HandleStartButton, nullptr),
VPHELPER(VP_ESTEPS_APPLY_BUTTON, nullptr, EstepsHandler::HandleApplyButton, nullptr),
VPHELPER(VP_ESTEPS_BACK_BUTTON, nullptr, EstepsHandler::HandleBackButton, nullptr),
VPHELPER(VP_ESTEP_NAV_BUTTON, nullptr, (ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_ESTEPS_CALIBRATION, EstepsHandler>), nullptr),
// ... PID
VPHELPER(VP_PIDTUNE_TARGET_TEMP, &PIDHandler::calibration_temperature, ScreenHandler.DGUSLCD_SetValueDirectly<uint16_t>, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_PIDTUNE_CYCLES, &PIDHandler::cycles, ScreenHandler.DGUSLCD_SetValueDirectly<uint16_t>, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_PIDTUNE_FAN_TOGGLE, &PIDHandler::fan_on, ScreenHandler.DGUSLCD_ToggleBoolean, nullptr),
VPHELPER(VP_PIDTUNE_FAN_TOGGLE_ICON, &PIDHandler::fan_on, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<ICON_TOGGLE_ON, ICON_TOGGLE_OFF>)),
VPHELPER(VP_PIDTUNE_START_BUTTON, nullptr, PIDHandler::HandleStartButton, nullptr),
VPHELPER(VP_PIDTUNE_NAV_BUTTON, nullptr, (ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_PIDTUNE_CALIBRATION, PIDHandler>), nullptr),
VPHELPER(VP_GENERIC_BACK_BUTTON, nullptr, ScreenHandler.OnBackButton, nullptr),
#if HAS_MESH
// ... Mesh validation
VPHELPER(VP_MESHPATTERN_NOZZLE_TEMP, &MeshValidationHandler::nozzle_temperature, MeshValidationHandler::HandleTemperature, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_MESHPATTERN_BED_TEMP, &MeshValidationHandler::bed_temperature, MeshValidationHandler::HandleTemperature, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_MESHPATTERN_BUTTON_ICON, &MeshValidationHandler::is_running, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<MESHPATTERN_BUTTON_CANCEL, MESHPATTERN_BUTTON_START>)),
VPHELPER(VP_MESHPATTERN_START_BUTTON, nullptr, MeshValidationHandler::HandleStartOrCancelButton, nullptr),
VPHELPER(VP_MESHPATTERN_NAV_BUTTON, nullptr, (ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_MESH_VALIDATION, MeshValidationHandler>), nullptr),
#endif
// Axis settings
VPHELPER(VP_AXIS_SETTINGS_NAV_BUTTON, nullptr, AxisSettingsHandler::HandleNavigation, nullptr),
VPHELPER(VP_AXIS_SETTINGS_TITLE_ICON, &AxisSettingsHandler::axis_settings_title_icon, nullptr, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_AXIS_SETTINGS_AXIS_STEPSMM, &AxisSettingsHandler::axis_steps_mm, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_AXIS_SETTINGS_AXIS_MAX_ACCEL, &AxisSettingsHandler::max_acceleration_mm_per_s2, ScreenHandler.DGUSLCD_SetValueDirectly<uint16_t>, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_AXIS_SETTINGS_AXIS_JERK, &AxisSettingsHandler::jerk, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_AXIS_SETTINGS_AXIS_FEEDRATE, &AxisSettingsHandler::max_feedrate, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_AXIS_SETTINGS_AXIS_TMCCURRENT, &AxisSettingsHandler::tmc_current, ScreenHandler.DGUSLCD_SetValueDirectly<uint16_t>, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_AXIS_SETTINGS_AXIS_TMCSTEALTHCHOP_BUTTON, &AxisSettingsHandler::stealthchop, ScreenHandler.DGUSLCD_ToggleBoolean, nullptr),
VPHELPER(VP_AXIS_SETTINGS_AXIS_TMCSTEALTHCHOP_ICON, &AxisSettingsHandler::stealthchop, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<ICON_TOGGLE_ON, ICON_TOGGLE_OFF>)),
VPHELPER(VP_AXIS_SETTINGS_AXIS_TMCHYBRIDTHRESHOLD, &AxisSettingsHandler::hybrid_threshold, ScreenHandler.DGUSLCD_ReceiveULongFromDisplay, ScreenHandler.DGUSLCD_SendULongToDisplay),
VPHELPER(VP_AXIS_TMC_NAV_ICON, &AxisSettingsHandler::has_tmc_settings, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<AXIS_TMC_NAV_ICON_SHOWING, AXIS_TMC_NAV_ICON_HIDING>)),
VPHELPER(VP_AXIS_SETTINGS_NAV_BACKBUTTON, nullptr, AxisSettingsHandler::HandleBackNavigation, nullptr),
VPHELPER(VP_AXIS_TUNING_NAV_BUTTON, nullptr, (ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_AXIS_SETTINGS_NAV>), nullptr),
VPHELPER(VP_AXIS_TMC_NAV_BUTTON, nullptr, (ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_AXIS_SETTINGS_TMC>), nullptr),
// Advanced movement settings
VPHELPER(VP_MOV_NAV_BUTTON, nullptr, (ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_ADV_MOV_SETTINGS>), nullptr),
VPHELPER(VP_MOV_MINIMUM_SEGMENT_TIME, &planner.settings.min_segment_time_us, ScreenHandler.DGUSLCD_SetValueDirectly<uint16_t>, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_MOV_MINIMUM_FEEDRATE, &planner.settings.min_feedrate_mm_s, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_MOV_NORMAL_ACCELERATION, &planner.settings.acceleration, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_MOV_RETRACT_ACCELERATION, &planner.settings.retract_acceleration, ScreenHandler.DGUSLCD_SetFloatAsLongFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<1>),
VPHELPER(VP_MOV_MINIMUM_TRAVEL_FEEDRATE, &planner.settings.min_travel_feedrate_mm_s, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_MOV_MINIMUM_TRAVEL_ACCELERATION, &planner.settings.travel_acceleration, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
// Misc settings
VPHELPER(VP_MISCSETTINGS_NAV_BUTTON, nullptr, (ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_MISC_SETTINGS>), nullptr),
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
VPHELPER(VP_FILAMENTRUNOUT_SENSOR_TOGGLE_BUTTON, &runout.enabled, ScreenHandler.DGUSLCD_ToggleBoolean, nullptr),
VPHELPER(VP_FILAMENTRUNOUT_SENSOR_TOGGLE_ICON, &runout.enabled, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<ICON_TOGGLE_ON, ICON_TOGGLE_OFF>)),
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
VPHELPER(VP_PLR_TOGGLE_BUTTON, nullptr, ScreenHandler.TogglePowerLossRecovery, nullptr),
VPHELPER(VP_PLR_TOGGLE_ICON, &PrintJobRecovery::enabled, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<ICON_TOGGLE_ON, ICON_TOGGLE_OFF>)),
#endif
// Preheat settings
#ifdef PREHEAT_1_LABEL
VPHELPER(VP_PREHEAT_PLA_HOTEND_TEMP, &ui.material_preset[0].hotend_temp, ScreenHandler.DGUSLCD_SetValueDirectly<int16_t>, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_PREHEAT_PLA_BED_TEMP, &ui.material_preset[0].bed_temp, ScreenHandler.DGUSLCD_SetValueDirectly<int16_t>, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
#endif
#ifdef PREHEAT_2_LABEL
VPHELPER(VP_PREHEAT_ABS_HOTEND_TEMP, &ui.material_preset[1].hotend_temp, ScreenHandler.DGUSLCD_SetValueDirectly<int16_t>, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_PREHEAT_ABS_BED_TEMP, &ui.material_preset[1].bed_temp, ScreenHandler.DGUSLCD_SetValueDirectly<int16_t>, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
#endif
// About info
VPHELPER_STR(VP_MARLIN_WEBSITE, nullptr, VP_MARLIN_WEBSITE_LEN, nullptr, ScreenHandler.DGUSLCD_SendAboutFirmwareWebsite),
VPHELPER_STR(VP_MARLIN_VERSION, nullptr, VP_MARLIN_VERSION_LEN, nullptr, ScreenHandler.DGUSLCD_SendAboutFirmwareVersion),
VPHELPER_STR(VP_PRINTER_BEDSIZE, nullptr, VP_PRINTER_BEDSIZE_LEN, nullptr, ScreenHandler.DGUSLCD_SendAboutPrintSize),
// Position Data
VPHELPER(VP_X_POSITION, &current_position.x, ScreenHandler.HandlePositionChange, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_Y_POSITION, &current_position.y, ScreenHandler.HandlePositionChange, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_Z_POSITION, &current_position.z, ScreenHandler.HandlePositionChange, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_Z_POSITION_PRECISION, &current_position.z, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<2>),
VPHELPER(SP_X_POSITION, nullptr, nullptr, ScreenHandler.SendAxisTrustValue<X_AXIS>),
VPHELPER(SP_Y_POSITION, nullptr, nullptr, ScreenHandler.SendAxisTrustValue<Y_AXIS>),
VPHELPER(SP_Z_POSITION, nullptr, nullptr, ScreenHandler.SendAxisTrustValue<Z_AXIS>),
#if HAS_BED_PROBE
VPHELPER(VP_Z_OFFSET, &probe.offset.z, ScreenHandler.HandleZoffsetChange, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<2>),
#elif ENABLED(BABYSTEP_DISPLAY_TOTAL)
VPHELPER(VP_Z_OFFSET, nullptr, ScreenHandler.HandleZoffsetChange, nullptr),
#endif
VPHELPER(VP_FAN_TOGGLE, &thermalManager.fan_speed[0], nullptr, ScreenHandler.DGUSLCD_SendFanStatusToDisplay),
VPHELPER(VP_Fan0_Percentage, &thermalManager.fan_speed[0], ScreenHandler.HandleFanSpeedChanged, ScreenHandler.DGUSLCD_SendFanSpeedToDisplay),
#if ENABLED(POWER_LOSS_RECOVERY)
VPHELPER(VP_POWER_LOSS_RECOVERY, nullptr, &ScreenHandler.HandlePowerLossRecovery, nullptr),
#endif
VPHELPER_STR(VP_PrintTime, nullptr, VP_PrintTime_LEN, nullptr, ScreenHandler.DGUSLCD_SendPrintTimeToDisplay),
VPHELPER_STR(VP_PrintTimeWithRemainingVisible, nullptr, VP_PrintTime_LEN, nullptr, ScreenHandler.DGUSLCD_SendPrintTimeWithRemainingToDisplay),
VPHELPER_STR(VP_PrintTimeRemaining, nullptr, VP_PrintTimeRemaining_LEN, nullptr, ScreenHandler.DGUSLCD_SendPrintTimeRemainingToDisplay),
VPHELPER(VP_SCREENCHANGE, nullptr, ScreenHandler.ScreenChangeHook, nullptr),
VPHELPER(VP_CONFIRMED, nullptr, ScreenHandler.ScreenConfirmedOK, nullptr),
#if HAS_PROBE_SETTINGS
VPHELPER(VP_TOGGLE_PROBING_HEATERS_OFF_ONOFF_BUTTON, nullptr, ScreenHandler.HandleToggleProbeHeaters, nullptr),
VPHELPER(VP_TOGGLE_PROBING_HEATERS_OFF_ONOFF_ICON, &probe.settings.turn_heaters_off, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<ICON_ACCURACY_TOGGLE_ON, ICON_ACCURACY_TOGGLE_OFF>)),
VPHELPER(VP_TOGGLE_POST_PROBING_TEMPERATURE_STABILIZATION_BUTTON, nullptr, ScreenHandler.HandleToggleProbeTemperatureStabilization, nullptr),
VPHELPER(VP_TOGGLE_POST_PROBING_TEMPERATURE_STABILIZATION_ICON, &probe.settings.stabilize_temperatures_after_probing, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<ICON_POST_PROBE_TEMP_STABILIZATION_TOGGLE_ON, ICON_POST_PROBE_TEMP_STABILIZATION_TOGGLE_OFF>)),
VPHELPER(VP_TOGGLE_PROBE_PREHEAT_HOTEND_TEMP, &probe.settings.preheat_hotend_temp, ScreenHandler.HandleToggleProbePreheatTemp, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_TOGGLE_PROBE_PREHEAT_BED_TEMP, &probe.settings.preheat_bed_temp, ScreenHandler.HandleToggleProbePreheatTemp, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
#endif
#if HAS_MESH
VPHELPER(VP_LEVELING_FADE_HEIGHT, &planner.z_fade_height, ScreenHandler.HandleFadeHeight, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
#endif
VPHELPER(VP_LEVELING_NAV_BUTTON, nullptr, (ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_ZOFFSET_LEVEL>), nullptr),
VPHELPER(VP_LEVELING_EDIT_NAV_BUTTON, nullptr, (ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_LEVELING>), nullptr),
VPHELPER(VP_TOGGLE_PROBE_SETTINGS_NAV_BUTTON, nullptr, (ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_LEVELING_SETTINGS>), nullptr),
// Creality has the same button ID mapped all over the place, so let the generic handler figure it out
VPHELPER(VP_BUTTON_MAINENTERKEY, nullptr, DGUSCrealityDisplay_HandleReturnKeyEvent, nullptr),
VPHELPER(VP_BUTTON_ADJUSTENTERKEY, nullptr, DGUSCrealityDisplay_HandleReturnKeyEvent, nullptr),
VPHELPER(VP_BUTTON_PREPAREENTERKEY, nullptr, DGUSCrealityDisplay_HandleReturnKeyEvent, nullptr),
VPHELPER(VP_BUTTON_RESUMEPRINTKEY, nullptr, DGUSCrealityDisplay_HandleReturnKeyEvent, nullptr),
VPHELPER(VP_BUTTON_SELECTFILEKEY, nullptr, DGUSCrealityDisplay_HandleReturnKeyEvent, nullptr),
VPHELPER(VP_BUTTON_STARTPRINTKEY, nullptr, DGUSCrealityDisplay_HandleReturnKeyEvent, nullptr),
VPHELPER(VP_BUTTON_STOPPRINTKEY, nullptr, DGUSCrealityDisplay_HandleReturnKeyEvent, nullptr),
VPHELPER(VP_BUTTON_PAUSEPRINTKEY, nullptr, DGUSCrealityDisplay_HandleReturnKeyEvent, nullptr),
VPHELPER(VP_BUTTON_COOLDOWN, nullptr, DGUSCrealityDisplay_HandleReturnKeyEvent, nullptr),
VPHELPER(VP_BUTTON_TEMPCONTROL, nullptr, DGUSCrealityDisplay_HandleReturnKeyEvent, nullptr),
VPHELPER(VP_BUTTON_BEDLEVELKEY, nullptr, DGUSCrealityDisplay_HandleReturnKeyEvent, nullptr),
VPHELPER(VP_BUTTON_HEATLOADSTARTKEY, nullptr, DGUSCrealityDisplay_HandleReturnKeyEvent, nullptr),
VPHELPER(VP_BUTTON_MOVEKEY, nullptr, DGUSCrealityDisplay_HandleReturnKeyEvent, nullptr),
// File listing
VPHELPER(VP_SD_ScrollEvent, nullptr, ScreenHandler.DGUSLCD_SD_ScrollFilelist, nullptr),
VPHELPER(VP_SD_FileSelected, nullptr, ScreenHandler.DGUSLCD_SD_FileSelected, nullptr),
VPHELPER(VP_SD_FileSelectConfirm, nullptr, ScreenHandler.DGUSLCD_SD_StartPrint, nullptr),
VPHELPER_STR(VP_SD_FileName0, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename),
VPHELPER_STR(VP_SD_FileName1, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename),
VPHELPER_STR(VP_SD_FileName2, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename),
VPHELPER_STR(VP_SD_FileName3, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename),
VPHELPER_STR(VP_SD_FileName4, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename),
VPHELPER_STR(VP_SD_FileName5, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename),
// Firmware retract
VPHELPER(VP_FWRETRACT_NAV_BUTTON, nullptr, ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_TUNEFWRETRACT>, nullptr),
VPHELPER(VP_FWRETRACT_RETRACT_LENGTH, &fwretract.settings.retract_length, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_FWRETRACT_RETRACT_FEEDRATE, &fwretract.settings.retract_feedrate_mm_s, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_FWRETRACT_RETRACT_ZHOP, &fwretract.settings.retract_zraise, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_FWRETRACT_RESTART_LENGTH, &fwretract.settings.retract_recover_extra, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_FWRETRACT_RESTART_FEEDRATE, &fwretract.settings.retract_recover_feedrate_mm_s, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_FWRETRACT_INDICATOR_ICON, &fwretract.autoretract_enabled, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<ICON_FWRETRACT_AUTO_ENGAGED, ICON_FWRETRACT_AUTO_DISENGAGED>)),
VPHELPER(VP_FWRETRACT_TOGGLE_BUTTON_ICON, &fwretract.autoretract_enabled, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<ICON_FWRETRACT_AUTO_TOGGLE_ON, ICON_FWRETRACT_AUTO_TOGGLE_OFF>)),
VPHELPER(VP_FWRETRACT_TOGGLE_BUTTON, &fwretract.autoretract_enabled, ScreenHandler.DGUSLCD_ToggleBoolean, nullptr),
// Other tuning
#if ENABLED(LIN_ADVANCE)
VPHELPER(VP_LINEAR_ADVANCE_FACTOR, &planner.extruder_advance_K[0], ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<2>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<2>),
#endif
VPHELPER(VP_OTHER_TUNE_NAV_BUTTON, nullptr, (ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_TUNING_EXTRA>), nullptr),
// Additional buttons
VPHELPER(VP_MUTE_TOGGLE, nullptr, ScreenHandler.HandleToggleTouchScreenMute, nullptr),
VPHELPER(VP_STANDBY_BACKLIGHT_TOGGLE, nullptr, ScreenHandler.HandleToggleTouchScreenStandbySetting, nullptr),
// Additional settings
VPHELPER(VP_SCREEN_BACKLIGHT_STANDBY, &ScreenHandler.Settings.standby_screen_brightness, ScreenHandler.HandleTouchScreenStandbyBrightnessSetting, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_SCREEN_BACKLIGHT, &ScreenHandler.Settings.screen_brightness, ScreenHandler.HandleTouchScreenBrightnessSetting, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_SCREEN_STANDBY_TIME, &ScreenHandler.Settings.standby_time_seconds, ScreenHandler.HandleTouchScreenStandbyTimeSetting, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
// RGB
VPHELPER(VP_RGB_NAV_BUTTON_ICON, &ScreenHandler.HasRGBSettings, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<ICON_RGB_SETTINGS_AVAILABLE, ICON_RGB_SETTINGS_UNAVAILABLE>)),
#if HAS_COLOR_LEDS
VPHELPER(VP_RGB_NAV_BUTTON, nullptr, ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_RGB>, nullptr),
VPHELPER(VP_RGB_CONTROL_R, &leds.color.r, ScreenHandler.HandleLED, ScreenHandler.SendLEDToDisplay),
VPHELPER(VP_RGB_CONTROL_G, &leds.color.g, ScreenHandler.HandleLED, ScreenHandler.SendLEDToDisplay),
VPHELPER(VP_RGB_CONTROL_B, &leds.color.b, ScreenHandler.HandleLED, ScreenHandler.SendLEDToDisplay),
#if EITHER(RGBW_LED, NEOPIXEL_LED)
VPHELPER(VP_RGB_CONTROL_W, &leds.color.w, ScreenHandler.HandleLED, ScreenHandler.SendLEDToDisplay),
#if ENABLED(NEOPIXEL_LED)
VPHELPER(VP_RGB_CONTROL_I, &leds.color.i, ScreenHandler.HandleLED, ScreenHandler.SendLEDToDisplay),
#endif
#endif
#endif
// Filament load/unload
VPHELPER(VP_FILCHANGE_NAV_BUTTON, nullptr, (ScreenHandler.DGUSLCD_NavigateToPage<DGUSLCD_SCREEN_FEED, FilamentLoadUnloadHandler>), nullptr),
VPHELPER(VP_FILCHANGE_LENGTH, &FilamentLoadUnloadHandler::length, ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
VPHELPER(VP_FILCHANGE_NOZZLE_TEMP, &FilamentLoadUnloadHandler::nozzle_temperature, FilamentLoadUnloadHandler::HandleTemperature, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_FILCHANGE_ACTION_BUTTON, nullptr, FilamentLoadUnloadHandler::HandleLoadUnloadButton, nullptr),
// Icons
#if ENABLED(CASE_LIGHT_ENABLE)
VPHELPER(VP_LED_TOGGLE, &caselight.on, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<ICON_LED_TOGGLE_ON, ICON_LED_TOGGLE_OFF>)),
#endif
VPHELPER(VP_STANDBY_BACKLIGHT_ICON, &ScreenHandler.Settings.display_standby, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<ICON_TOGGLE_ON, ICON_TOGGLE_OFF>)),
VPHELPER(VP_MUTE_ICON, &ScreenHandler.Settings.display_sound, nullptr, (ScreenHandler.DGUSLCD_SendIconValue<ICON_SOUND_TOGGLE_ON, ICON_SOUND_TOGGLE_OFF>)),
// Development test button
VPHELPER(VP_DEVELOPMENT_HELPER_BUTTON, nullptr, ScreenHandler.HandleDevelopmentTestButton, nullptr),
// Mesh override input
#if MESH_INPUT_SUPPORTED_SIZE == GRID_MAX_POINTS && HAS_MESH
//#define _VPHELPER_GP(N) VPHELPER((VP_MESH_INPUT_X0_Y0 + ( ##N## * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
//REPEAT(MESH_INPUT_SUPPORTED_SIZE, _VPHELPER_GP)
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 0 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 1 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 2 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 3 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 4 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 5 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 6 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 7 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 8 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 9 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 10 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 11 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 12 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 13 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 14 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
VPHELPER((VP_MESH_INPUT_X0_Y0 + ( 15 * MESH_INPUT_DATA_SIZE)), nullptr, ScreenHandler.HandleMeshPoint, nullptr),
#endif
// M117 LCD String (We don't need the string in memory but "just" push it to the display on demand, hence the nullptr
{ .VP = VP_M117, .memadr = nullptr, .size = VP_M117_LEN, .set_by_display_handler = nullptr, .send_to_display_handler =&ScreenHandler.DGUSLCD_SendStringToDisplay },
{ .VP = VP_M117_STATIC, .memadr = nullptr, .size = VP_M117_STATIC_LEN, .set_by_display_handler = nullptr, .send_to_display_handler =&ScreenHandler.DGUSLCD_SendStringToDisplay },
// Messages for the User, shared by the popup and the kill screen. They cant be autouploaded as we do not buffer content.
{ .VP = VP_MSGSTR1, .memadr = nullptr, .size = VP_MSGSTR1_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
{ .VP = VP_MSGSTR2, .memadr = nullptr, .size = VP_MSGSTR2_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
{ .VP = VP_MSGSTR3, .memadr = nullptr, .size = VP_MSGSTR3_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
//{ .VP = VP_MSGSTR4, .memadr = nullptr, .size = VP_MSGSTR4_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
VPHELPER(0, 0, 0, 0) // must be last entry.
};
#endif // DGUS_LCD_UI_ORIGIN
@@ -1,562 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
enum DGUSLCD_Screens : uint8_t {
DGUSLCD_SCREEN_BOOT = 0,
DGUSLCD_SCREEN_MAIN = 28,
DGUSLCD_SCREEN_CONFIRM = 66,
DGUSLCD_SCREEN_SDPRINTMANIPULATION = 37 ,
DGUSLCD_SCREEN_SDPRINTTUNE = 41,
DGUSLCD_SCREEN_SDFILELIST = 67,
DGUSLCD_SCREEN_FILAMENTRUNOUT1 = 34, // DWINTouchPage::ERR_FILAMENTRUNOUT_HOTEND_COLD
DGUSLCD_SCREEN_FILAMENTRUNOUT2 = 35, // DWINTouchPage::ERR_FILAMENTRUNOUT_FILAMENT_LOADED
DGUSLCD_SCREEN_PRINT_FINISH = 36, // DWINTouchPage::PRINT_FINISHED
DGUSLCD_SCREEN_PRINT_RUNNING = 37, // DWINTouchPage::PRINT_PROGRESS_RUNNING
DGUSLCD_SCREEN_PRINT_PAUSED = 39, // DWINTouchPage::PRINT_PROGRESS_PAUSED
DGUSLCD_SCREEN_DIALOG_PAUSE = 38, // DWINTouchPage::DIALOG_PAUSE_PRINTING
DGUSLCD_SCREEN_DIALOG_STOP = 40, // DWINTouchPage::DIALOG_STOP_PRINTING
DGUSLCD_SCREEN_TUNING = 41, // DWINTouchPage::MENU_TUNING
DGUSLCD_SCREEN_TUNING_EXTRA = 79, // (this is a new page)
DGUSLCD_SCREEN_PREPARE = 42, // DWINTouchPage::MENU_PREPARE
DGUSLCD_SCREEN_MOVE10MM = 43, // DWINTouchPage::MOVE_1MM
DGUSLCD_SCREEN_MOVE1MM = 44, // DWINTouchPage::MOVE_10MM
DGUSLCD_SCREEN_MOVE01MM = 45, // DWINTouchPage::MOVE_01MM
DGUSLCD_SCREEN_FEED = 46, // DWINTouchPage::FEED
DGUSLCD_SCREEN_SETUP = 47, // DWINTouchPage::MENU_CONTROL
DGUSLCD_SCREEN_TEMP = 48, // DWINTouchPage::MENU_TEMP
DGUSLCD_SCREEN_TEMP_PLA = 49, // DWINTouchPage::MENU_PLA_TEMP
DGUSLCD_SCREEN_TEMP_ABS = 50, // DWINTouchPage::MENU_ABS_TEMP
DGUSLCD_SCREEN_INFO = 51, // DWINTouchPage::MENU_ABOUT
DGUSLCD_SCREEN_ZOFFSET_LEVEL = 52, // DWINTouchPage::MENU_ZOFFSET_LEVELING
DGUSLCD_SCREEN_LEVELING = 53, // DWINTouchPage::LEVELING
DGUSLCD_SCREEN_POWER_LOSS = 54, // DWINTouchPage::DIALOG_POWER_FAILURE
DGUSLCD_SCREEN_THERMAL_RUNAWAY = 57, // DWINTouchPage::ERR_THERMAL_RUNAWAY
DGUSLCD_SCREEN_HEATING_FAILED = 58, // DWINTouchPage::ERR_HEATING_FAILED
DGUSLCD_SCREEN_THERMISTOR_ERROR = 59, // DWINTouchPage::ERR_THERMISTOR
DGUSLCD_SCREEN_AUTOHOME = 61, // DWINTouchPage::AUTOHOME_IN_PROGRESS
DGUSLCD_SCREEN_POPUP = 63, // NEW - does not exist in original display
DGUSLCD_SCREEN_KILL = 64, // NEW - does not exist in original display
DGUSLCD_SCREEN_PIDTUNE_CALIBRATION = 68,
DGUSLCD_SCREEN_ESTEPS_CALIBRATION = 69,
DGUSLCD_SCREEN_TUNEFWRETRACT = 70,
DGUSLCD_SCREEN_ESTEPS_CALIBRATION_RESULTS = 71,
DGUSLCD_SCREEN_LEVELING_SETTINGS = 72,
DGUSLCD_SCREEN_AXIS_SETTINGS_NAV = 73,
DGUSLCD_SCREEN_AXIS_SETTINGS_AXIS = 74,
DGUSLCD_SCREEN_AXIS_SETTINGS_TMC = 75,
DGUSLCD_SCREEN_ADV_MOV_SETTINGS = 76,
DGUSLCD_SCREEN_MISC_SETTINGS = 77,
DGUSLCD_SCREEN_MESH_VALIDATION = 78,
DGUSLCD_SCREEN_CALIBRATE = 80,
DGUSLCD_SCREEN_RGB = 81
};
// Version checks
constexpr uint16_t VP_UI_VERSION_MAJOR = 0xFFFA;
constexpr uint16_t EXPECTED_UI_VERSION_MAJOR = 61;
constexpr uint16_t VERSION_MISMATCH_BUZZ_AMOUNT = 5;
constexpr uint16_t VERSION_MISMATCH_LED_FLASH_DELAY = 1000;
#define VP_STARTPROGRESSBAR 0x1000
// // Storage space for the Killscreen messages. Reused for the popup.
constexpr uint16_t VP_MSGSTR1 = 0x2010;
constexpr uint8_t VP_MSGSTR1_LEN = 0x20; // might be more place for it...
constexpr uint16_t VP_MSGSTR2 = 0x2030;
constexpr uint8_t VP_MSGSTR2_LEN = 0x40;
constexpr uint16_t VP_MSGSTR3 = 0x2070;
constexpr uint8_t VP_MSGSTR3_LEN = 0x40;
constexpr uint16_t VP_MSGSTR4 = 0x2080;
constexpr uint8_t VP_MSGSTR4_LEN = 0x20;
// // Screenchange request for screens that only make sense when printer is idle.
// // e.g movement is only allowed if printer is not printing.
// // Marlin must confirm by setting the screen manually.
// constexpr uint16_t VP_SCREENCHANGE_ASK = 0x2000;
constexpr uint16_t VP_SCREENCHANGE = 0x219f; // Key-Return button to new menu pressed. Data contains target screen in low byte and info in high byte.
// constexpr uint16_t VP_TEMP_ALL_OFF = 0x2002; // Turn all heaters off. Value arbitrary ;)=
// constexpr uint16_t VP_SCREENCHANGE_WHENSD = 0x2003; // "Print" Button touched -- go only there if there is an SD Card.
constexpr uint16_t VP_CONFIRMED = 0x219E; // OK on confirm screen.
// // Buttons on the SD-Card File listing.
// constexpr uint16_t VP_SD_ScrollEvent = 0x2020; // Data: 0 for "up a directory", numbers are the amount to scroll, e.g -1 one up, 1 one down
// constexpr uint16_t VP_SD_FileSelected = 0x2022; // Number of file field selected.
constexpr uint16_t VP_SD_FileSelectConfirm = 0x2024; // (This is a virtual VP and emulated by the Confirm Screen when a file has been confirmed)
// constexpr uint16_t VP_SD_ResumePauseAbort = 0x2026; // Resume(Data=0), Pause(Data=1), Abort(Data=2) SD Card prints
constexpr uint16_t VP_SD_AbortPrintConfirmed = 0x2028; // Abort print confirmation (virtual, will be injected by the confirm dialog)
// constexpr uint16_t VP_SD_Print_Setting = 0x2040;
// constexpr uint16_t VP_SD_Print_LiveAdjustZ = 0x2050; // Data: 0 down, 1 up
// // Controls for movement (we can't use the incremental / decremental feature of the display at this feature works only with 16 bit values
// // (which would limit us to 655.35mm, which is likely not a problem for common setups, but i don't want to rule out hangprinters support)
// // A word about the coding: The VP will be per axis and the return code will be an signed 16 bit value in 0.01 mm resolution, telling us
// // the relative travel amount t he user wants to do. So eg. if the display sends us VP=2100 with value 100, the user wants us to move X by +1 mm.
constexpr uint16_t VP_MOVE_X = 0x2100;
constexpr uint16_t VP_MOVE_Y = 0x2102;
constexpr uint16_t VP_MOVE_Z = 0x2104;
constexpr uint16_t VP_MOVE_E0 = 0x2110;
// constexpr uint16_t VP_MOVE_E1 = 0x2112;
// //constexpr uint16_t VP_MOVE_E2 = 0x2114;
// //constexpr uint16_t VP_MOVE_E3 = 0x2116;
// //constexpr uint16_t VP_MOVE_E4 = 0x2118;
// //constexpr uint16_t VP_MOVE_E5 = 0x211A;
constexpr uint16_t VP_HOME_ALL = 0x2120;
// constexpr uint16_t VP_MOTOR_LOCK_UNLOK = 0x2130;
// // Power loss recovery
// constexpr uint16_t VP_POWER_LOSS_RECOVERY = 0x2180;
// // Fan Control Buttons , switch between "off" and "on"
// constexpr uint16_t VP_FAN0_CONTROL = 0x2200;
// constexpr uint16_t VP_FAN1_CONTROL = 0x2202;
// //constexpr uint16_t VP_FAN2_CONTROL = 0x2204;
// //constexpr uint16_t VP_FAN3_CONTROL = 0x2206;
// // Heater Control Buttons , triged between "cool down" and "heat PLA" state
constexpr uint16_t VP_E0_CONTROL = 0x2210;
// constexpr uint16_t VP_E1_CONTROL = 0x2212;
// //constexpr uint16_t VP_E2_CONTROL = 0x2214;
// //constexpr uint16_t VP_E3_CONTROL = 0x2216;
// //constexpr uint16_t VP_E4_CONTROL = 0x2218;
// //constexpr uint16_t VP_E5_CONTROL = 0x221A;
constexpr uint16_t VP_BED_CONTROL = 0x221C;
// // Preheat
// constexpr uint16_t VP_E0_BED_PREHEAT = 0x2220;
// constexpr uint16_t VP_E1_BED_CONTROL = 0x2222;
// //constexpr uint16_t VP_E2_BED_CONTROL = 0x2224;
// //constexpr uint16_t VP_E3_BED_CONTROL = 0x2226;
// //constexpr uint16_t VP_E4_BED_CONTROL = 0x2228;
// //constexpr uint16_t VP_E5_BED_CONTROL = 0x222A;
// // Filament load and unload
// constexpr uint16_t VP_E0_FILAMENT_LOAD_UNLOAD = 0x2300;
// constexpr uint16_t VP_E1_FILAMENT_LOAD_UNLOAD = 0x2302;
// // Settings store , reset
// constexpr uint16_t VP_SETTINGS = 0x2400;
// // PID autotune
constexpr uint16_t VP_PID_AUTOTUNE_E0 = 0x2410;
// //constexpr uint16_t VP_PID_AUTOTUNE_E1 = 0x2412;
// //constexpr uint16_t VP_PID_AUTOTUNE_E2 = 0x2414;
// //constexpr uint16_t VP_PID_AUTOTUNE_E3 = 0x2416;
// //constexpr uint16_t VP_PID_AUTOTUNE_E4 = 0x2418;
// //constexpr uint16_t VP_PID_AUTOTUNE_E5 = 0x241A;
constexpr uint16_t VP_PID_AUTOTUNE_BED = 0x2420;
// // Firmware version on the boot screen.
constexpr uint16_t VP_PRINTER_BEDSIZE = 0x1074;
constexpr uint16_t VP_PRINTER_BEDSIZE_LEN = 12;
constexpr uint16_t VP_MARLIN_VERSION = 0x2222;
constexpr uint8_t VP_MARLIN_VERSION_LEN = 32;
constexpr uint16_t VP_MARLIN_WEBSITE = 0x2242;
constexpr uint8_t VP_MARLIN_WEBSITE_LEN = 32;
constexpr uint16_t VP_STANDBY_BACKLIGHT_ICON = 0x2280;
constexpr uint16_t VP_STANDBY_BACKLIGHT_TOGGLE = 0x2282;
constexpr uint16_t VP_MUTE_ICON = 0x2284;
constexpr uint16_t VP_MUTE_TOGGLE = 0x2286;
constexpr uint16_t VP_SCREEN_BACKLIGHT_STANDBY = 0x228D;
constexpr uint16_t VP_SCREEN_BACKLIGHT = 0x2384;
constexpr uint16_t VP_SCREEN_STANDBY_TIME = 0x2386;
// Material preheat settings
constexpr uint16_t VP_PREHEAT_PLA_HOTEND_TEMP = 0x1102;
constexpr uint16_t VP_PREHEAT_PLA_BED_TEMP = 0x1104;
constexpr uint16_t VP_PREHEAT_ABS_HOTEND_TEMP = 0x1108;
constexpr uint16_t VP_PREHEAT_ABS_BED_TEMP = 0x110a;
// Place for status messages.
// ... We have memory space for scrolling messages
constexpr uint16_t VP_M117 = 0x3000 + (3 * 1); // Text Variable Pointer. First three VP must be reserved [a VP is two bytes red.]. Text is saved after the 3rd VP and ended with 0x00 or 0x0F.
constexpr uint8_t VP_M117_LEN = 100;
// ... And memory space for static (short) messages. Note this VPAddr is also the VP of the 5 beta and alpha 4 touch screens.
constexpr uint8_t M117_STATIC_DISPLAY_LEN = 28; // Fits "TFT flashed incorrectly v0" exactly
constexpr uint16_t VP_M117_STATIC = 0x21B3;
constexpr uint8_t VP_M117_STATIC_LEN = 70;
// // Temperatures.
constexpr uint16_t VP_T_E0_Is = 0x1036; // 4 Byte Integer - HEAD_CURRENT_TEMP_VP
constexpr uint16_t VP_T_E0_Set = 0x1034; // 2 Byte Integer - HEAD_SET_TEMP_VP
constexpr uint16_t VP_T_Bed_Is = 0x103c; // 4 Byte Integer - BED_SET_TEMP_VP
constexpr uint16_t VP_T_Bed_Set = 0x103A; // 2 Byte Integer - BED_CURRENT_TEMP_VP
constexpr uint16_t VP_Flowrate_E0 = 0x228A; // 2 Byte Integer
constexpr uint16_t VP_Fan0_Percentage = 0x228F; // 2 Byte Integer (0..100)
constexpr uint16_t VP_Feedrate_Percentage = 0x1006; // 2 Byte Integer (0..100) - PRINT_SPEED_RATE_VP
constexpr uint16_t VP_PrintProgress_Percentage = 0x1016; // 2 Byte Integer (0..100)
constexpr uint16_t VP_PrintTimeProgressBar = 0x100E;
constexpr uint16_t VP_PrintTime = 0x21a0;
constexpr uint16_t VP_PrintTimeWithRemainingVisible = 0x2335;
constexpr uint16_t VP_PrintTime_LEN = 19;
constexpr uint16_t VP_PrintTimeRemaining = 0x231f;
constexpr uint16_t VP_PrintTimeRemaining_LEN = 21;
constexpr uint16_t VP_HideRemainingTime_Ico = 0x2380;
constexpr uint16_t ICON_REMAINING_VISIBLE = 26;
constexpr uint16_t ICON_REMAINING_HIDDEN = 27;
constexpr uint16_t VP_Z_OFFSET = 0x1026;
// // SDCard File Listing
constexpr uint16_t VP_SD_ScrollEvent = 0x20D4; // Data: 0 for "up a directory", numbers are the amount to scroll, e.g -1 one up, 1 one down
constexpr uint16_t VP_SD_FileSelected = 0x2200; // Number of file field selected.
constexpr uint16_t VP_SD_FileName_LEN = 21; // LEN is shared for all entries.
constexpr uint16_t VP_SD_FileName_CNT = 5; // LEN is shared for all entries.
constexpr uint16_t DGUS_SD_FILESPERSCREEN = VP_SD_FileName_CNT; // FIXME move that info to the display and read it from there.
constexpr uint16_t VP_SD_FileName0 = 0x20D5;
constexpr uint16_t VP_SD_FileName1 = VP_SD_FileName0 + VP_SD_FileName_LEN;
constexpr uint16_t VP_SD_FileName2 = VP_SD_FileName1 + VP_SD_FileName_LEN;
constexpr uint16_t VP_SD_FileName3 = VP_SD_FileName2 + VP_SD_FileName_LEN;
constexpr uint16_t VP_SD_FileName4 = VP_SD_FileName3 + VP_SD_FileName_LEN;
constexpr uint16_t VP_SD_FileName5 = VP_SD_FileName4 + VP_SD_FileName_LEN;
constexpr uint16_t VP_SD_Print_ProbeOffsetZ = 0x32A0; //
constexpr uint16_t VP_SD_Print_Filename = 0x2000; //
constexpr uint16_t VP_ICON_OVERLAY_CLEAR = 10;
constexpr uint16_t VP_ICON_OVERLAY_SELECTED = 6;
// // Step per mm
constexpr uint16_t VP_X_STEP_PER_MM = 0x3600;
constexpr uint16_t VP_Y_STEP_PER_MM = 0x3604;
constexpr uint16_t VP_Z_STEP_PER_MM = 0x3608;
constexpr uint16_t VP_E0_STEP_PER_MM = 0x3610;
// // PIDs
constexpr uint16_t VP_E0_PID_P = 0x3700;
constexpr uint16_t VP_E0_PID_I = 0x3702;
constexpr uint16_t VP_E0_PID_D = 0x3704;
constexpr uint16_t VP_BED_PID_P = 0x3710;
constexpr uint16_t VP_BED_PID_I = 0x3712;
constexpr uint16_t VP_BED_PID_D = 0x3714;
// Power loss recovery
constexpr uint16_t VP_POWER_LOSS_RECOVERY = 0x105F;
// Buttons defined by Creality - Don't worry if you're confused by the naming, so am I
constexpr uint16_t VP_BUTTON_MAINENTERKEY = 0x1002;
constexpr uint16_t VP_BUTTON_ADJUSTENTERKEY = 0x1004;
constexpr uint16_t VP_BUTTON_PAUSEPRINTKEY = 0x100A;
constexpr uint16_t VP_BUTTON_TEMPCONTROL = 0x1030;
constexpr uint16_t VP_BUTTON_COOLDOWN = 0x1032;
constexpr uint16_t VP_BUTTON_PREPAREENTERKEY = 0x103E;
constexpr uint16_t VP_BUTTON_SELECTFILEKEY = 0x20D3;
constexpr uint16_t VP_BUTTON_STARTPRINTKEY = 0x20D2;
constexpr uint16_t VP_BUTTON_STOPPRINTKEY = 0x1008;
constexpr uint16_t VP_BUTTON_RESUMEPRINTKEY = 0x100C;
constexpr uint16_t VP_BUTTON_BEDLEVELKEY = 0x1044;
constexpr uint16_t VP_BUTTON_HEATLOADSTARTKEY = 0x1056;
// Additional stuff defined by Creality
constexpr uint16_t VP_FAN_TOGGLE = 0x101E;
constexpr uint16_t VP_LED_TOGGLE = 0x101F;
// Axis settings
constexpr uint16_t VP_AXIS_SETTINGS_NAV_BUTTON = 0x22D9;
constexpr uint16_t AXIS_SETTINGS_NAV_BUTTON_VAL_X = 1;
constexpr uint16_t AXIS_SETTINGS_NAV_BUTTON_VAL_Y = 2;
constexpr uint16_t AXIS_SETTINGS_NAV_BUTTON_VAL_Z = 3;
constexpr uint16_t AXIS_SETTINGS_NAV_BUTTON_VAL_E = 4;
constexpr uint16_t VP_AXIS_SETTINGS_TITLE_ICON = 0x22DB;
constexpr uint16_t ICON_AXIS_SETTINGS_TITLE_X = 20;
constexpr uint16_t ICON_AXIS_SETTINGS_TITLE_Y = 21;
constexpr uint16_t ICON_AXIS_SETTINGS_TITLE_Z = 22;
constexpr uint16_t ICON_AXIS_SETTINGS_TITLE_E = 23;
constexpr uint16_t VP_AXIS_SETTINGS_NAV_BACKBUTTON = 0x22DD;
constexpr uint16_t VP_AXIS_SETTINGS_AXIS_STEPSMM = 0x22DF; // 2-byte
constexpr uint16_t VP_AXIS_SETTINGS_AXIS_MAX_ACCEL = 0x22E1; // 4-byte (!)
constexpr uint16_t VP_AXIS_SETTINGS_AXIS_JERK = 0x22E5; // 2-byte
constexpr uint16_t VP_AXIS_SETTINGS_AXIS_FEEDRATE = 0x22E7; // 2-byte
constexpr uint16_t VP_AXIS_SETTINGS_AXIS_TMCCURRENT = 0x22E9; // 2-byte
constexpr uint16_t VP_AXIS_SETTINGS_AXIS_TMCSTEALTHCHOP_BUTTON = 0x22EB; // 2-byte
constexpr uint16_t VP_AXIS_SETTINGS_AXIS_TMCSTEALTHCHOP_ICON = 0x22ED; // 2-byte
constexpr uint16_t VP_AXIS_SETTINGS_AXIS_TMCHYBRIDTHRESHOLD = 0x22EF; // 4-byte (!)
constexpr uint16_t VP_AXIS_TUNING_NAV_BUTTON = 0x22F5;
constexpr uint16_t VP_AXIS_TMC_NAV_BUTTON = 0x22F7;
constexpr uint16_t VP_AXIS_TMC_NAV_ICON = 0x22F3; // 2-byte
constexpr uint16_t AXIS_TMC_NAV_ICON_SHOWING = 10;
constexpr uint16_t AXIS_TMC_NAV_ICON_HIDING = 11;
// ... Advanced movement settings
constexpr uint16_t VP_MOV_NAV_BUTTON = 0x2305;
constexpr uint16_t VP_MOV_MINIMUM_SEGMENT_TIME = 0x22F9; // uint 2-byte
constexpr uint16_t VP_MOV_MINIMUM_FEEDRATE = 0x22FB; // float 2-byte
constexpr uint16_t VP_MOV_NORMAL_ACCELERATION = 0x22FD; // float 2-byte
constexpr uint16_t VP_MOV_MINIMUM_TRAVEL_FEEDRATE = 0x2301; // float 2-byte
constexpr uint16_t VP_MOV_MINIMUM_TRAVEL_ACCELERATION = 0x2303; // float 2-byte
constexpr uint16_t VP_MOV_RETRACT_ACCELERATION = 0x2307; // float 4-byte
// Misc settings
constexpr uint16_t VP_MISCSETTINGS_NAV_BUTTON = 0x2311;
constexpr uint16_t VP_FILAMENTRUNOUT_SENSOR_TOGGLE_BUTTON = 0x2309;
constexpr uint16_t VP_FILAMENTRUNOUT_SENSOR_TOGGLE_ICON = 0x230b;
constexpr uint16_t VP_PLR_TOGGLE_BUTTON = 0x230d;
constexpr uint16_t VP_PLR_TOGGLE_ICON = 0x230F;
// Mesh leveling
constexpr uint16_t VP_LEVELING_NAV_BUTTON = 0x238a;
constexpr uint16_t VP_LEVELING_EDIT_NAV_BUTTON = 0x23A8;
constexpr uint16_t VP_MESH_SCREEN_MESSAGE_ICON = 0x22cb;
constexpr uint16_t MESH_SCREEN_MESSAGE_ICON_LEVELING = 5;
constexpr uint16_t MESH_SCREEN_MESSAGE_ICON_VIEWING = 6;
constexpr uint16_t VP_MESH_LEVEL_TEMP = 0x108A;
constexpr uint16_t VP_MESH_LEVEL_STATUS = 0x108D;
constexpr uint8_t DGUS_GRID_VISUALIZATION_START_ID = GRID_MAX_POINTS > (4*4) ? 30 : 1;
static_assert(
(GRID_MAX_POINTS == 16 && DGUS_GRID_VISUALIZATION_START_ID == 1)|| // CR-6 SE
(GRID_MAX_POINTS == 49 && DGUS_GRID_VISUALIZATION_START_ID == 30) || // CR-6 MAX
(GRID_MAX_POINTS != 16 && GRID_MAX_POINTS != 49), // Custom Leveling
"Incorrect offset selected for leveling config"
);
static_assert(GRID_MAX_POINTS_X == GRID_MAX_POINTS_Y, "Assuming bed leveling points is square");
constexpr uint16_t VP_MESH_LEVEL_X0_Y0 = 0x1350;
constexpr uint16_t SP_MESH_LEVEL_X0_Y0 = 0x5000;
constexpr uint16_t MESH_LEVEL_EDGE_MAX_POINTS = 4;
constexpr uint16_t MESH_LEVEL_VP_SIZE = 0x4; // 4-byte native float
constexpr uint16_t MESH_LEVEL_SP_SIZE = 0x10; // 0x10 distance
constexpr uint16_t MESH_LEVEL_VP_EDGE_SIZE = MESH_LEVEL_VP_SIZE * MESH_LEVEL_EDGE_MAX_POINTS;
constexpr uint16_t MESH_LEVEL_SP_EDGE_SIZE = MESH_LEVEL_SP_SIZE * MESH_LEVEL_EDGE_MAX_POINTS;
constexpr uint16_t MESH_LEVEL_MAX_POINTS = MESH_LEVEL_EDGE_MAX_POINTS * MESH_LEVEL_EDGE_MAX_POINTS;
// Mesh inputs
constexpr uint16_t VP_MESH_INPUT_X0_Y0 = 0x2360;
#define MESH_INPUT_SUPPORTED_X_SIZE 4
#define MESH_INPUT_SUPPORTED_Y_SIZE 4
#define MESH_INPUT_SUPPORTED_SIZE 16
#define MESH_INPUT_DATA_SIZE 2 // 2 byte integer
// Color table: https://stackoverflow.com/q/13720937/646215
// Color picker: https://ee-programming-notepad.blogspot.com/2016/10/16-bit-color-generator-picker.html
// Colors below were picked on bed leveling visualizer defaults
constexpr uint16_t MESH_COLOR_BELOW_ZERO = 0x899B; // Blue
constexpr uint16_t MESH_COLOR_NEAR_ZERO = 0x1C80; // Green
constexpr uint16_t MESH_COLOR_ABOVE_ZERO = 0xB800; // Purple
constexpr uint16_t MESH_COLOR_NOT_MEASURED = 0xFFFF; // White (becomes invisible on white background)
constexpr float MESH_NEAR_ZERO = 0.020;
constexpr float MESH_UNSET_EPSILON = 0.001;
// Mesh validation pattern
constexpr uint16_t VP_MESHPATTERN_NOZZLE_TEMP = 0x2313;
constexpr uint16_t VP_MESHPATTERN_BED_TEMP = 0x2315;
constexpr uint16_t VP_MESHPATTERN_START_BUTTON = 0x2317;
constexpr uint16_t VP_MESHPATTERN_BUTTON_ICON = 0x2319;
constexpr uint16_t VP_MESHPATTERN_NAV_BUTTON = 0x231B;
constexpr uint16_t MESHPATTERN_BUTTON_START = 24; // This icon does not exist, and will therefore not show
constexpr uint16_t MESHPATTERN_BUTTON_CANCEL = 25;
// Movement screen
constexpr uint16_t VP_X_POSITION = 0x1048;
constexpr uint16_t SP_X_POSITION = 0x4000;
constexpr uint16_t VP_Y_POSITION = 0x104A;
constexpr uint16_t SP_Y_POSITION = 0x4030;
constexpr uint16_t VP_Z_POSITION = 0x104C;
constexpr uint16_t VP_Z_POSITION_PRECISION = 0x108F;
constexpr uint16_t SP_Z_POSITION = 0x4060;
constexpr uint16_t VP_BUTTON_MOVEKEY = 0x1046;
// Buttons
constexpr uint16_t VP_ESTEP_NAV_BUTTON = 0x2291;
constexpr uint16_t VP_PIDTUNE_NAV_BUTTON = 0x2293;
constexpr uint16_t VP_GENERIC_BACK_BUTTON = 0x2295; // Generic button for popping back to the old display
constexpr uint16_t GENERIC_BACK_BUTTON_NEED_SAVE = 0x1;
// PID tuning
constexpr uint16_t VP_PIDTUNE_TARGET_TEMP = 0x2297;
constexpr uint16_t VP_PIDTUNE_CYCLES = 0x2299;
constexpr uint16_t VP_PIDTUNE_FAN_TOGGLE = 0x238C;
constexpr uint16_t VP_PIDTUNE_FAN_TOGGLE_ICON = 0x238E;
constexpr uint16_t VP_PIDTUNE_START_BUTTON = 0x229B;
// FWRetract
constexpr uint16_t VP_FWRETRACT_NAV_BUTTON = 0x22AD;
constexpr uint16_t VP_FWRETRACT_RETRACT_LENGTH = 0x22B1;
constexpr uint16_t VP_FWRETRACT_RETRACT_FEEDRATE = 0x22B3;
constexpr uint16_t VP_FWRETRACT_RETRACT_ZHOP = 0x22B5;
constexpr uint16_t VP_FWRETRACT_RESTART_LENGTH = 0x22B7;
constexpr uint16_t VP_FWRETRACT_RESTART_FEEDRATE = 0x22B9;
constexpr uint16_t VP_FWRETRACT_TOGGLE_BUTTON = 0x22BB;
constexpr uint16_t VP_FWRETRACT_TOGGLE_BUTTON_ICON = 0x22BD;
constexpr uint16_t VP_FWRETRACT_INDICATOR_ICON = 0x22BF;
// Other tuning
constexpr uint16_t VP_LINEAR_ADVANCE_FACTOR = 0x22AF;
constexpr uint16_t VP_OTHER_TUNE_NAV_BUTTON = 0x2382;
// Leveling settings
constexpr uint16_t VP_TOGGLE_PROBING_HEATERS_OFF_ONOFF_BUTTON = 0x22C1;
constexpr uint16_t VP_TOGGLE_PROBING_HEATERS_OFF_ONOFF_ICON = 0x22C3;
constexpr uint16_t VP_TOGGLE_PROBE_PREHEAT_HOTEND_TEMP = 0x22C5;
constexpr uint16_t VP_TOGGLE_PROBE_PREHEAT_BED_TEMP = 0x22C7;
constexpr uint16_t VP_TOGGLE_PROBE_SETTINGS_NAV_BUTTON = 0x22C9;
constexpr uint16_t VP_TOGGLE_POST_PROBING_TEMPERATURE_STABILIZATION_ICON = 0x22CD;
constexpr uint16_t VP_TOGGLE_POST_PROBING_TEMPERATURE_STABILIZATION_BUTTON = 0x22CF;
constexpr uint16_t VP_LEVELING_FADE_HEIGHT = 0x231D;
// E-steps calibration
constexpr uint16_t VP_ESTEPS_CURRENT = 0x229d;
constexpr uint16_t VP_ESTEPS_CALIBRATION_TEMP = 0x229f;
constexpr uint16_t VP_ESTEPS_CALIBRATION_LENGTH = 0x22a1;
constexpr uint16_t VP_ESTEPS_CALIBRATION_MARK_LENGTH = 0x22ab;
constexpr uint16_t VP_ESTEPS_CALIBRATION_LEFTOVER_LENGTH = 0x22a3;
constexpr uint16_t VP_ESTEPS_CALCULATED_ESTEPS = 0x22a5;
constexpr uint16_t VP_ESTEPS_CALIBRATESTART_BUTTON = 0x22a7;
constexpr uint16_t VP_ESTEPS_APPLY_BUTTON = 0x22a9;
constexpr uint16_t VP_ESTEPS_BACK_BUTTON = 0x22D7;
// RGB
constexpr uint16_t VP_RGB_NAV_BUTTON = 0x2390;
constexpr uint16_t VP_RGB_CONTROL_R = 0x2392;
constexpr uint16_t VP_RGB_CONTROL_G = 0x2394;
constexpr uint16_t VP_RGB_CONTROL_B = 0x2396;
constexpr uint16_t VP_RGB_CONTROL_W = 0x2398;
constexpr uint16_t VP_RGB_CONTROL_I = 0x239A; // brightness
constexpr uint16_t VP_RGB_NAV_BUTTON_ICON = 0x239E;
constexpr uint16_t ICON_RGB_SETTINGS_AVAILABLE = 28;
constexpr uint16_t ICON_RGB_SETTINGS_UNAVAILABLE = 29;
// Filament load/unload
constexpr uint16_t VP_FILCHANGE_NAV_BUTTON = 0x23a6;
constexpr uint16_t VP_FILCHANGE_NOZZLE_TEMP = 0x23a0;
constexpr uint16_t VP_FILCHANGE_LENGTH = 0x23a2;
constexpr uint16_t VP_FILCHANGE_ACTION_BUTTON = 0x23a4;
constexpr uint16_t FILCHANGE_ACTION_UNLOAD_BUTTON = 1;
constexpr uint16_t FILCHANGE_ACTION_LOAD_BUTTON = 2;
// Icons
constexpr uint16_t ICON_TOGGLE_ON = 1;
constexpr uint16_t ICON_TOGGLE_OFF = 2;
constexpr uint16_t ICON_BACK_BUTTON_ENABLED = 7;
constexpr uint16_t ICON_BACK_BUTTON_DISABLED = 8;
constexpr uint16_t ICON_THROBBER_ANIM_OFF = 0;
constexpr uint16_t ICON_THROBBER_ANIM_ON = 1;
// Allow to visually disable/enable the back button
constexpr uint16_t VP_BACK_BUTTON_STATE = 0x22D1;
// Throbber animation
constexpr uint16_t VP_BUSY_ANIM_STATE = 0x22D3;
// Toggles
constexpr uint16_t ICON_FAN_TOGGLE_ON = 1;
constexpr uint16_t ICON_FAN_TOGGLE_OFF = 2;
constexpr uint16_t ICON_LED_TOGGLE_ON = 3;
constexpr uint16_t ICON_LED_TOGGLE_OFF = 4;
constexpr uint16_t ICON_SOUND_TOGGLE_ON = 5;
constexpr uint16_t ICON_SOUND_TOGGLE_OFF = 6;
constexpr uint16_t ICON_FWRETRACT_AUTO_TOGGLE_ON = 9;
constexpr uint16_t ICON_FWRETRACT_AUTO_TOGGLE_OFF = 10;
constexpr uint16_t ICON_ACCURACY_TOGGLE_ON = 11;
constexpr uint16_t ICON_ACCURACY_TOGGLE_OFF = 12;
constexpr uint16_t ICON_POST_PROBE_TEMP_STABILIZATION_TOGGLE_ON = 13;
constexpr uint16_t ICON_POST_PROBE_TEMP_STABILIZATION_TOGGLE_OFF = 14;
constexpr uint16_t ICON_FWRETRACT_AUTO_DISENGAGED = 4; // This icon deliberately does not exist
constexpr uint16_t ICON_FWRETRACT_AUTO_ENGAGED = 3;
// Development helper
constexpr uint16_t VP_DEVELOPMENT_HELPER_BUTTON = 0x22D5;
constexpr uint16_t VP_DEVELOPMENT_HELPER_BUTTON_ACTION_FIRMWARE_UPDATE = 2;
constexpr uint16_t VP_DEVELOPMENT_HELPER_BUTTON_ACTION_TO_MAIN_MENU = 4;
constexpr uint16_t VP_DEVELOPMENT_HELPER_BUTTON_ACTION_RESET_DISPLAY = 8;
@@ -1,188 +0,0 @@
#include "../../../../inc/MarlinConfigPre.h"
#if ENABLED(DGUS_LCD_UI_CREALITY_TOUCH)
#include "../DGUSDisplayDef.h"
#include "../DGUSDisplay.h"
#include "../DGUSScreenHandler.h"
#include "EstepsHandler.h"
#include "../../ui_api.h"
#include "../../../marlinui.h"
#include "../../../../module/temperature.h"
#include "../../../../module/settings.h"
#include "../../../../module/planner.h"
#include "../../../../gcode/gcode.h"
// Storage init
float EstepsHandler::set_esteps = 0;
float EstepsHandler::calculated_esteps = 0;
float EstepsHandler::remaining_filament = 0;
float EstepsHandler::mark_filament_mm = 0;
float EstepsHandler::filament_to_extrude = 0;
celsius_t EstepsHandler::calibration_temperature = 0;
void EstepsHandler::Init() {
// Use steps
set_esteps = ExtUI::getAxisSteps_per_mm(ExtUI::E0);
calculated_esteps = 0;
// Reset
filament_to_extrude = 100;
mark_filament_mm = 120;
remaining_filament = 0;
// Use configured PLA temps + 10 degrees
calibration_temperature = ui.material_preset[0].hotend_temp + 10;
// Welcome message
SetStatusMessage(PSTR("Ready"));
}
void EstepsHandler::HandleStartButton(DGUS_VP_Variable &var, void *val_ptr) {
//static_assert(ADVANCED_PAUSE_PURGE_LENGTH == 0, "Assuming PURGE_LENGTH is 0 so we can use M701");
// Validate
if (calibration_temperature < EXTRUDE_MINTEMP) {
SetStatusMessage(PSTR("Invalid temperature set"));
return;
}
if (filament_to_extrude < 10) {
SetStatusMessage(PSTR("Invalid extrusion length set"));
return;
}
if (mark_filament_mm < filament_to_extrude) {
SetStatusMessage(PSTR("Invalid mark length set"));
return;
}
// Synchronous operation - disable back button
DGUSSynchronousOperation syncOperation;
syncOperation.start();
// Prepare
bool zAxisWasRelative = GcodeSuite::axis_is_relative(Z_AXIS);
bool eAxisWasRelative = GcodeSuite::axis_is_relative(E_AXIS);
#if ENABLED(LIN_ADVANCE)
float kFactor = planner.extruder_advance_K[0];
#endif
GcodeSuite::set_e_relative();
GcodeSuite::set_relative_mode(true);
#if ENABLED(LIN_ADVANCE)
planner.extruder_advance_K[0] = 0;
#endif
ExtUI::injectCommands_P("G0 Z5 F150");
queue.advance();
// Heat up if necessary
if (abs(ExtUI::getActualTemp_celsius(ExtUI::E0) - calibration_temperature) > 2) {
thermalManager.setTargetHotend(calibration_temperature, ExtUI::H0);
SetStatusMessage(PSTR("Heating up..."));
thermalManager.wait_for_hotend(ExtUI::H0, false);
}
planner.synchronize();
// Set-up command
SetStatusMessage(PSTR("Extruding..."));
char cmd[64];
sprintf_P(cmd, PSTR("G1 E%f F50"), filament_to_extrude);
ExtUI::injectCommands(cmd);
queue.advance();
planner.synchronize();
// Restore position
ExtUI::injectCommands_P("G0 Z-5 F150");
queue.advance();
planner.synchronize();
// Restore defaults
if (!zAxisWasRelative) GcodeSuite::set_relative_mode(false);
if (!eAxisWasRelative) GcodeSuite::set_e_absolute();
#if ENABLED(LIN_ADVANCE)
planner.extruder_advance_K[0] = kFactor;
#endif
// Done
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_ESTEPS_CALIBRATION_RESULTS, false);
ScreenHandler.Buzzer(0, 250);
syncOperation.done();
SetStatusMessage(PSTR("Measure remaining filament"));
}
void EstepsHandler::HandleApplyButton(DGUS_VP_Variable &var, void *val_ptr) {
if (abs(calculated_esteps) < 1) {
// User intented to set e-steps directly
ExtUI::setAxisSteps_per_mm(set_esteps, ExtUI::E0);
} else {
ExtUI::setAxisSteps_per_mm(calculated_esteps, ExtUI::E0);
}
SaveSettingsAndReturn(true);
}
void EstepsHandler::HandleBackButton(DGUS_VP_Variable &var, void *val_ptr) {
// User intented to set e-steps directly
ExtUI::setAxisSteps_per_mm(set_esteps, ExtUI::E0);
SaveSettingsAndReturn(false);
}
void EstepsHandler::SaveSettingsAndReturn(bool fullConfirm) {
// Save & reset
settings.save();
if (fullConfirm) ScreenHandler.Buzzer(0, 250);
ScreenHandler.PopToOldScreen();
if (fullConfirm) ScreenHandler.GotoScreen(DGUSLCD_SCREEN_MAIN, false);
SetStatusMessage(PSTR("New e-steps value saved"));
}
void EstepsHandler::HandleRemainingFilament(DGUS_VP_Variable &var, void *val_ptr) {
ScreenHandler.DGUSLCD_SetFloatAsIntFromDisplay<1>(var, val_ptr);
// Calculate
constexpr float precision = 0.01;
float actualExtrusion = mark_filament_mm - remaining_filament;
if (actualExtrusion < (-precision)) {
SetStatusMessage(PSTR("Mark filament further"));
return;
}
if (actualExtrusion < precision) {
SetStatusMessage(PSTR("E-steps are correct"));
calculated_esteps = set_esteps;
return;
}
float current_steps = ExtUI::getAxisSteps_per_mm(ExtUI::E0);
SERIAL_ECHOLNPGM("Current steps: ", current_steps);
SERIAL_ECHOLNPGM("Actual extrusion: ", actualExtrusion);
float new_steps = (current_steps * filament_to_extrude) / actualExtrusion;
SERIAL_ECHOLNPGM("New steps: ", new_steps);
calculated_esteps = new_steps;
// Status update
SetStatusMessage(PSTR("Calculated new e-steps"));
}
void EstepsHandler::SetStatusMessage(PGM_P statusMessage) {
ScreenHandler.setstatusmessagePGM(statusMessage);
}
#endif
@@ -1,29 +0,0 @@
#pragma once
#include <cstdint>
class EstepsHandler {
public:
static void Init();
static void HandleStartButton(DGUS_VP_Variable &var, void *val_ptr);
static void HandleApplyButton(DGUS_VP_Variable &var, void *val_ptr);
static void HandleBackButton(DGUS_VP_Variable &var, void *val_ptr);
static void HandleRemainingFilament(DGUS_VP_Variable &var, void *val_ptr);
public:
static float set_esteps;
static float calculated_esteps;
static float mark_filament_mm;
static float remaining_filament;
static float filament_to_extrude;
static celsius_t calibration_temperature;
private:
static void SaveSettingsAndReturn(bool fullConfirm);
static void SetStatusMessage(PGM_P statusMessage);
};
@@ -1,106 +0,0 @@
#include "../../../../inc/MarlinConfigPre.h"
#if ENABLED(DGUS_LCD_UI_CREALITY_TOUCH)
#include "../DGUSDisplayDef.h"
#include "../DGUSDisplay.h"
#include "../DGUSScreenHandler.h"
#include "FilamentLoadUnloadHandler.h"
#include "../../ui_api.h"
#include "../../../marlinui.h"
#include "../../../../module/temperature.h"
#include "../../../../module/settings.h"
#include "../../../../module/planner.h"
#include "../../../../gcode/gcode.h"
celsius_t FilamentLoadUnloadHandler::nozzle_temperature = 0;
float FilamentLoadUnloadHandler::length = 0;
void FilamentLoadUnloadHandler::Init() {
nozzle_temperature = ui.material_preset[0].hotend_temp;
length = 150;
if (ExtUI::isPrinting()) {
nozzle_temperature = ExtUI::getTargetTemp_celsius(ExtUI::extruder_t::E0);
}
}
void FilamentLoadUnloadHandler::HandleTemperature(DGUS_VP_Variable &var, void *val_ptr) {
ScreenHandler.DGUSLCD_SetValueDirectly<uint16_t>(var, val_ptr);
ValidateTemperatures();
}
void FilamentLoadUnloadHandler::HandleLoadUnloadButton(DGUS_VP_Variable &var, void *val_ptr) {
// Common for load/unload -> determine minimum temperature
if (length < 0.1) {
SetStatusMessage("Invalid feed length");
return;
}
if (ExtUI::isPrinting() && !ExtUI::isPrintingPaused()) {
SetStatusMessage(PSTR("Finish Printing First"));
return;
}
DGUSSynchronousOperation syncOperation;
uint16_t button_value = uInt16Value(val_ptr);
switch (button_value) {
case FILCHANGE_ACTION_LOAD_BUTTON:
syncOperation.start();
ChangeFilamentWithTemperature(PSTR("M701 L%f P0"));
syncOperation.done();
break;
case FILCHANGE_ACTION_UNLOAD_BUTTON:
syncOperation.start();
ChangeFilamentWithTemperature(PSTR("M702 U%f"));
syncOperation.done();
break;
}
}
void FilamentLoadUnloadHandler::ValidateTemperatures() {
LIMIT(nozzle_temperature, EXTRUDE_MINTEMP, HEATER_0_MAXTEMP - HOTEND_OVERSHOOT);
}
void FilamentLoadUnloadHandler::ChangeFilamentWithTemperature(PGM_P command) {
// Heat if necessary
if (ExtUI::getActualTemp_celsius(ExtUI::E0) < nozzle_temperature && abs(ExtUI::getActualTemp_celsius(ExtUI::E0) - nozzle_temperature) > THERMAL_PROTECTION_HYSTERESIS) {
SetStatusMessage(PSTR("Heating up..."));
uint16_t target_celsius = nozzle_temperature;
NOMORE(target_celsius, thermalManager.hotend_max_target(0));
thermalManager.setTargetHotend(target_celsius, ExtUI::H0);
thermalManager.wait_for_hotend(ExtUI::H0, false);
}
// Inject load filament command
SetStatusMessage(PSTR("Filament load/unload..."));
char cmd[64];
sprintf_P(cmd, command, length);
// Handle commands
SERIAL_ECHOPGM("Injecting command: ", cmd);
GcodeSuite::process_subcommands_now(cmd);
SERIAL_ECHOPGM_P("- done");
if (ScreenHandler.Settings.display_sound) ScreenHandler.Buzzer(500, 100);
SetStatusMessage(PSTR("Filament load/unload complete"));
}
void FilamentLoadUnloadHandler::SetStatusMessage(PGM_P statusMessage) {
ScreenHandler.setstatusmessagePGM(statusMessage);
}
#endif
@@ -1,22 +0,0 @@
#pragma once
#include <cstdint>
class FilamentLoadUnloadHandler {
public:
static void Init();
static void HandleTemperature(DGUS_VP_Variable &var, void *val_ptr);
static void HandleLoadUnloadButton(DGUS_VP_Variable &var, void *val_ptr);
public:
static celsius_t nozzle_temperature;
static float length;
private:
static void ValidateTemperatures();
static void ChangeFilamentWithTemperature(PGM_P command);
static void SetStatusMessage(PGM_P statusMessage);
};
@@ -1,150 +0,0 @@
#include "../../../../inc/MarlinConfigPre.h"
#if ENABLED(DGUS_LCD_UI_CREALITY_TOUCH) && HAS_MESH
#include "../DGUSDisplayDef.h"
#include "../DGUSDisplay.h"
#include "../DGUSScreenHandler.h"
#include "MeshValidationHandler.h"
#include "../../ui_api.h"
#include "../../../marlinui.h"
#include "../../../../module/temperature.h"
#include "../../../../module/settings.h"
#include "../../../../module/planner.h"
#include "../../../../gcode/gcode.h"
celsius_t MeshValidationHandler::nozzle_temperature;
celsius_t MeshValidationHandler::bed_temperature;
bool MeshValidationHandler::is_running;
bool MeshValidationHandler::started_from_screen;
bool MeshValidationHandler::is_cancelling;
feedRate_t MeshValidationHandler::prev_feedrate;
void MeshValidationHandler::Init() {
// Set to PLA pre-heat temps by default
nozzle_temperature = ui.material_preset[0].hotend_temp;
bed_temperature = ui.material_preset[0].bed_temp;
ValidateTemperatures();
}
void MeshValidationHandler::HandleTemperature(DGUS_VP_Variable &var, void *val_ptr) {
ScreenHandler.DGUSLCD_SetValueDirectly<uint16_t>(var, val_ptr);
ValidateTemperatures();
}
void MeshValidationHandler::HandleStartOrCancelButton(DGUS_VP_Variable &var, void *val_ptr) {
if (!is_running) {
Start();
} else {
Cancel();
}
}
void MeshValidationHandler::Start() {
if (is_running) return;
// Validate
if (!ExtUI::getMeshValid()) {
SetStatusMessage("Please level bed first");
return;
}
// Block
ScreenHandler.SetSynchronousOperationStart();
is_running = true;
started_from_screen = true;
// Home if necessary - do this synchronously
if (!all_axes_trusted()) {
queue.inject_P("G28 U0");
queue.advance();
}
// Home X and Y so we droop at the side of the bed.
// G26 with temperature and set for full bed, full pattern, retract 4mm, prime 5mm
char gcodeBuffer[128] = {0};
sprintf_P(gcodeBuffer, PSTR("G90\nG0 X0\nG26 B%d H%d R Q4 P2 X0 Y0"), bed_temperature, nozzle_temperature);
queue.inject(gcodeBuffer);
queue.advance();
// Set feedrate
prev_feedrate = ExtUI::getFeedrate_mm_s();
ExtUI::setFeedrate_mm_s(MESH_VALIDATION_PATTERN_FEEDRATE);
SetStatusMessage("Starting...");
}
void MeshValidationHandler::Cancel() {
if (is_cancelling) return;
is_cancelling = true;
ExtUI::simulateUserClick();
SetStatusMessage("Cancelling...");
}
void MeshValidationHandler::OnMeshValidationStart() {
// Note: can also be called when manually invoking G26
if (ScreenHandler.getCurrentScreen() != DGUSLCD_SCREEN_MESH_VALIDATION) {
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_MESH_VALIDATION);
}
// Set state
ScreenHandler.SetSynchronousOperationStart();
is_running = true;
}
void MeshValidationHandler::OnMeshValidationFinish() {
// If invoked externally, pop back
if (!started_from_screen) {
ScreenHandler.PopToOldScreen();
}
if (started_from_screen) {
ExtUI::setFeedrate_mm_s(prev_feedrate);
char gcodeBuffer[128] = {0};
if (!is_cancelling) {
// Present
// - Set absolute mode
// - Present bed, high Z
// - Disable stepper
strcpy_P(gcodeBuffer, PSTR("M84"));
SetStatusMessage("Mesh validation pattern printed");
} else {
// Park and disable steppers
strcpy_P(gcodeBuffer, PSTR("G0 X5 F2000\nG27\nM84"));
SetStatusMessage("Canceled mesh validation pattern");
}
// Enqueue
gcode.process_subcommands_now(gcodeBuffer);
}
// Reset state
is_running = false;
started_from_screen = false;
is_cancelling = false;
ScreenHandler.SetSynchronousOperationFinish();
ExtUI::simulateUserClick();
}
void MeshValidationHandler::ValidateTemperatures() {
LIMIT(nozzle_temperature, EXTRUDE_MINTEMP, HEATER_0_MAXTEMP - HOTEND_OVERSHOOT);
LIMIT(bed_temperature, 40 /*Hardcoded minimum for G26, apparently*/, BED_MAXTEMP - BED_OVERSHOOT);
}
void MeshValidationHandler::SetStatusMessage(PGM_P statusMessage) {
ScreenHandler.setstatusmessagePGM(statusMessage);
}
#endif
@@ -1,33 +0,0 @@
#include <cstdint>
#if HAS_MESH
class MeshValidationHandler {
public:
static void Init();
static void HandleTemperature(DGUS_VP_Variable &var, void *val_ptr);
static void HandleStartOrCancelButton(DGUS_VP_Variable &var, void *val_ptr);
static void OnMeshValidationStart();
static void OnMeshValidationFinish();
public:
static celsius_t nozzle_temperature;
static celsius_t bed_temperature;
static feedRate_t prev_feedrate;
static bool is_cancelling;
static bool is_running;
static bool started_from_screen;
private:
static void Start();
static void Cancel();
static void ValidateTemperatures();
static void SetStatusMessage(PGM_P statusMessage);
};
constexpr feedRate_t MESH_VALIDATION_PATTERN_FEEDRATE = G26_XY_FEEDRATE;
#endif
@@ -1,91 +0,0 @@
#include "../../../../inc/MarlinConfigPre.h"
#if ENABLED(DGUS_LCD_UI_CREALITY_TOUCH)
#include "../DGUSDisplayDef.h"
#include "../DGUSDisplay.h"
#include "../DGUSScreenHandler.h"
#include "PIDHandler.h"
#include "../../ui_api.h"
#include "../../../marlinui.h"
#include "../../../../module/temperature.h"
#include "../../../../module/settings.h"
#include "../../../../module/planner.h"
#include "../../../../gcode/gcode.h"
// Storage init
uint16_t PIDHandler::cycles = 0;
celsius_t PIDHandler::calibration_temperature = 0;
bool PIDHandler::fan_on = false;
PGM_P PIDHandler::result_message = nullptr;
void PIDHandler::Init() {
// Reset
cycles = 3;
fan_on = ExtUI::getTargetFan_percent(ExtUI::fan_t::FAN0) > 10;
// Use configured PLA temps + 10 degrees
calibration_temperature = ui.material_preset[0].hotend_temp + 15;
// Welcome message
SetStatusMessage(PSTR("Ready"));
}
void PIDHandler::HandleStartButton(DGUS_VP_Variable &var, void *val_ptr) {
//static_assert(ADVANCED_PAUSE_PURGE_LENGTH == 0, "Assuming PURGE_LENGTH is 0 so we can use M701");
// Validate
if (calibration_temperature < EXTRUDE_MINTEMP) {
SetStatusMessage(PSTR("Invalid temperature set"));
return;
}
if (calibration_temperature > HEATER_0_MAXTEMP) {
SetStatusMessage(PSTR("Invalid temperature set"));
return;
}
if (cycles < 1) {
SetStatusMessage(PSTR("Invalid number of cycles"));
return;
}
// Synchronous operation - disable back button
DGUSSynchronousOperation syncOperation;
syncOperation.start();
// Fan
const auto prev_fan_percentage = ExtUI::getActualFan_percent(ExtUI::fan_t::FAN0);
const uint8_t fan_speed = fan_on ? 255 : 0;
// Set-up command
SetStatusMessage(PSTR("PID tuning. Please wait..."));
char cmd[64]; // Add a G4 to allow the fan speed to take effect
sprintf_P(cmd, PSTR("M106 S%d\nG4 S2\nM303 S%d C%d U1"), fan_speed, calibration_temperature, cycles);
SERIAL_ECHOLNPGM("Executing: ", cmd);
ExtUI::injectCommands(cmd);
while (queue.has_commands_queued()) queue.advance();
// Done
ExtUI::setTargetFan_percent(prev_fan_percentage, ExtUI::fan_t::FAN0);
ScreenHandler.Buzzer(0, 250);
settings.save();
syncOperation.done();
SetStatusMessage(result_message);
}
void PIDHandler::SetStatusMessage(PGM_P statusMessage) {
ScreenHandler.setstatusmessagePGM(statusMessage);
}
#endif
@@ -1,21 +0,0 @@
#pragma once
#include <cstdint>
class PIDHandler {
public:
static void Init();
static void HandleStartButton(DGUS_VP_Variable &var, void *val_ptr);
public:
static uint16_t cycles;
static celsius_t calibration_temperature;
static bool fan_on;
static PGM_P result_message;
private:
static void SetStatusMessage(PGM_P statusMessage);
};
@@ -1,470 +0,0 @@
#include "../../../../inc/MarlinConfigPre.h"
#if ENABLED(DGUS_LCD_UI_CREALITY_TOUCH)
#include "../DGUSDisplayDef.h"
#include "../DGUSDisplay.h"
#include "../DGUSScreenHandler.h"
#include "../../../../module/temperature.h"
#include "../../../../module/motion.h"
#include "../../../../module/planner.h"
#include "../../../../feature/pause.h"
#include "../../../../gcode/gcode.h"
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
#include "../../../../feature/runout.h"
#endif
#include "../../../../module/settings.h"
#include "../../ui_api.h"
#include "../../../marlinui.h"
#include "PageHandlers.h"
// Definitions of page handlers
void MainMenuHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP) {
case VP_BUTTON_MAINENTERKEY:
switch (buttonValue) {
case 1:
// Try to mount an unmounted card (BTT SKR board has especially some trouble sometimes)
card.mount();
ScreenHandler.SDCardInserted();
break;
case 2:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_PREPARE);
break;
case 3:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_SETUP);
break;
case 4:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_CALIBRATE);
break;
}
break;
}
}
void SetupMenuHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP) {
case VP_BUTTON_PREPAREENTERKEY:
switch(buttonValue) {
case 5: // About
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_INFO);
break;
case 7: // Reset to factory settings
settings.reset();
settings.save();
ExtUI::injectCommands_P(PSTR("M300"));
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_MAIN, false);
ScreenHandler.setstatusmessagePGM(PSTR("Restored default settings. Please turn your printer off and then on to complete the reset"));
break;
}
break;
case VP_BUTTON_TEMPCONTROL:
if (buttonValue == 2) ScreenHandler.GotoScreen(DGUSLCD_SCREEN_TEMP);
break;
case VP_BUTTON_ADJUSTENTERKEY:
ScreenHandler.HandleLEDToggle();
break;
}
}
#if HAS_MESH
void LevelingModeHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP) {
case VP_BUTTON_BEDLEVELKEY:
switch (buttonValue) {
case 1:
queue.enqueue_one("G28 U0");
queue.enqueue_one("G0 Z0");
break;
case 2:
// Increase Z-offset
ExtUI::smartAdjustAxis_steps(ExtUI::mmToWholeSteps(0.01, ExtUI::axis_t::Z), ExtUI::axis_t::Z, true);;
ScreenHandler.ForceCompleteUpdate();
ScreenHandler.RequestSaveSettings();
break;
case 3:
// Decrease Z-offset
ExtUI::smartAdjustAxis_steps(ExtUI::mmToWholeSteps(-0.01, ExtUI::axis_t::Z), ExtUI::axis_t::Z, true);;
ScreenHandler.ForceCompleteUpdate();
ScreenHandler.RequestSaveSettings();
break;
}
break;
case VP_BUTTON_PREPAREENTERKEY:
if (buttonValue == 9) {
#if DISABLED(HOTEND_IDLE_TIMEOUT)
thermalManager.disable_all_heaters();
#endif
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_MAIN, false);
}
if (buttonValue == 1) {
// TODO: set state for "view leveling mesh"
ScreenHandler.SetViewMeshLevelState();
ScreenHandler.InitMeshValues();
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_LEVELING);
}
break;
case VP_BUTTON_MAINENTERKEY:
// Go to leveling screen
ExtUI::injectCommands_P("G28 U0\nG29 U0");
ScreenHandler.ResetMeshValues();
dgusdisplay.WriteVariable(VP_MESH_SCREEN_MESSAGE_ICON, static_cast<uint16_t>(MESH_SCREEN_MESSAGE_ICON_LEVELING));
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_LEVELING);
break;
}
}
void LevelingHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP) {
case VP_BUTTON_BEDLEVELKEY:
const bool busy = TERN0(HOST_KEEPALIVE_FEATURE, ((ExtUI::getHostKeepaliveState() == GcodeSuite::MarlinBusyState::IN_PROCESS) || (ExtUI::getHostKeepaliveState() == GcodeSuite::MarlinBusyState::IN_HANDLER)));
if (!busy) {
ScreenHandler.PopToOldScreen();
} else {
ScreenHandler.setstatusmessagePGM("Wait for leveling completion...");
}
break;
}
}
#endif
void TempMenuHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP) {
case VP_BUTTON_ADJUSTENTERKEY:
switch (buttonValue) {
case 3:
ScreenHandler.HandleFanToggle();
break;
}
break;
case VP_BUTTON_TEMPCONTROL:
switch (buttonValue){
case 3:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_TEMP_PLA);
break;
case 4:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_TEMP_ABS);
break;
}
break;
}
}
void PrepareMenuHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP) {
case VP_BUTTON_PREPAREENTERKEY:
switch (buttonValue){
case 3:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_MOVE10MM);
break;
case 6:
// Disable steppers
ScreenHandler.HandleMotorLockUnlock(var, &buttonValue);
break;
}
break;
case VP_BUTTON_HEATLOADSTARTKEY:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_FEED);
break;
case VP_BUTTON_COOLDOWN:
ScreenHandler.HandleAllHeatersOff(var, &buttonValue);
break;
case VP_BUTTON_TEMPCONTROL:
switch (buttonValue) {
case 5:
thermalManager.setTargetHotend(ui.material_preset[0].hotend_temp, 0);
thermalManager.setTargetBed(ui.material_preset[0].bed_temp);
break;
case 6:
thermalManager.setTargetHotend(ui.material_preset[1].hotend_temp, 0);
thermalManager.setTargetBed(ui.material_preset[1].bed_temp);
break;
}
break;
}
ScreenHandler.ForceCompleteUpdate();
}
void TuneMenuHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP) {
case VP_BUTTON_BEDLEVELKEY:
switch (buttonValue) {
case 2:
// Increase Z-offset
ExtUI::smartAdjustAxis_steps(ExtUI::mmToWholeSteps(0.01, ExtUI::axis_t::Z), ExtUI::axis_t::Z, true);;
ScreenHandler.ForceCompleteUpdate();
ScreenHandler.RequestSaveSettings();
break;
case 3:
// Decrease Z-offset
ExtUI::smartAdjustAxis_steps(ExtUI::mmToWholeSteps(-0.01, ExtUI::axis_t::Z), ExtUI::axis_t::Z, true);;
ScreenHandler.ForceCompleteUpdate();
ScreenHandler.RequestSaveSettings();
break;
}
break;
case VP_BUTTON_ADJUSTENTERKEY:
switch (buttonValue) {
case 2:
ScreenHandler.GotoScreen(ExtUI::isPrintingPaused() ? DGUSLCD_SCREEN_PRINT_PAUSED : DGUSLCD_SCREEN_PRINT_RUNNING, false);
break;
case 3:
ScreenHandler.HandleFanToggle();
break;
case 4:
ScreenHandler.HandleLEDToggle();
break;
}
}
}
void PrintRunningMenuHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP) {
case VP_BUTTON_ADJUSTENTERKEY:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_TUNING);
break;
case VP_BUTTON_PAUSEPRINTKEY:
if (!ScreenHandler.HandlePendingUserConfirmation() && ExtUI::isPrintingPaused()) {
ExtUI::resumePrint();
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_PRINT_RUNNING);
} else
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_DIALOG_PAUSE);
break;
case VP_BUTTON_STOPPRINTKEY:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_DIALOG_STOP);
break;
}
}
void PrintPausedMenuHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP) {
case VP_BUTTON_RESUMEPRINTKEY:
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
runout.reset();
#endif
if (!ScreenHandler.HandlePendingUserConfirmation()) {
ExtUI::resumePrint();
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_PRINT_RUNNING);
}
break;
case VP_BUTTON_ADJUSTENTERKEY:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_TUNING);
break;
case VP_BUTTON_STOPPRINTKEY:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_DIALOG_STOP);
break;
}
}
void PrintPauseDialogHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP){
case VP_BUTTON_PAUSEPRINTKEY:
switch (buttonValue) {
case 2:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_PRINT_RUNNING);
ScreenHandler.setstatusmessagePGM(PSTR("Pausing print - please wait..."));
ExtUI::pausePrint();
break;
case 3:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_PRINT_RUNNING);
break;
}
break;
}
}
void PrintFinishMenuHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP){
case VP_BUTTON_MAINENTERKEY:
switch (buttonValue) {
case 5:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_MAIN);
break;
}
break;
}
}
void FilamentRunoutHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP){
case VP_BUTTON_RESUMEPRINTKEY:
ExtUI::resumePrint();
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_PRINT_RUNNING);
break;
case VP_BUTTON_STOPPRINTKEY:
ExtUI::stopPrint();
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_MAIN);
break;
}
}
void StopConfirmScreenHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP){
case VP_BUTTON_STOPPRINTKEY:
switch (buttonValue) {
case 2:
ExtUI::stopPrint();
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_MAIN);
break;
case 3:
ScreenHandler.GotoScreen(ExtUI::isPrintingPaused() ? DGUSLCD_SCREEN_PRINT_PAUSED : DGUSLCD_SCREEN_PRINT_RUNNING);
break;
}
break;
}
}
void PreheatSettingsScreenHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
switch (var.VP){
case VP_BUTTON_PREPAREENTERKEY:
// Save button, save settings and go back
ScreenHandler.RequestSaveSettings();
ScreenHandler.PopToOldScreen();
break;
case VP_BUTTON_COOLDOWN: // You can't make this up
// Back button, discard settings
settings.load();
ScreenHandler.PopToOldScreen();
break;
}
}
void MoveHandler(DGUS_VP_Variable &var, unsigned short buttonValue) {
if (var.VP == VP_BUTTON_MOVEKEY) {
switch (buttonValue) {
case 1:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_MOVE10MM, false);
break;
case 2:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_MOVE1MM, false);
break;
case 3:
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_MOVE01MM, false);
break;
case 4:
// Temporary copy probe settings so we home without preheating, then restore setings afterward
//This machine should never home Z cold...
//auto prev_probe_settings = probe.settings;
//probe.settings.preheat_bed_temp = 0;
//probe.settings.preheat_hotend_temp = 0;
//probe.settings.stabilize_temperatures_after_probing = false;
ExtUI::injectCommands_P("G28");
while (queue.has_commands_queued()) queue.advance();
// ... Restore settings
//probe.settings = prev_probe_settings;
break;
}
}
}
// Register the page handlers
#define PAGE_HANDLER(SCRID, HDLRPTR) { .ScreenID=SCRID, .Handler=HDLRPTR },
const struct PageHandler PageHandlers[] PROGMEM = {
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_MAIN, MainMenuHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_SETUP, SetupMenuHandler)
#if HAS_MESH
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_ZOFFSET_LEVEL, LevelingModeHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_LEVELING, LevelingHandler)
#endif
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_TEMP, TempMenuHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_TEMP_PLA, PreheatSettingsScreenHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_TEMP_ABS, PreheatSettingsScreenHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_TUNING, TuneMenuHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_MOVE01MM, MoveHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_MOVE1MM, MoveHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_MOVE10MM, MoveHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_FILAMENTRUNOUT1, FilamentRunoutHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_FILAMENTRUNOUT2, FilamentRunoutHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_DIALOG_STOP, StopConfirmScreenHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_PRINT_RUNNING, PrintRunningMenuHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_PRINT_PAUSED, PrintPausedMenuHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_PRINT_FINISH, PrintFinishMenuHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_DIALOG_PAUSE, PrintPauseDialogHandler)
PAGE_HANDLER(DGUSLCD_Screens::DGUSLCD_SCREEN_PREPARE, PrepareMenuHandler)
// Terminating
PAGE_HANDLER(static_cast<DGUSLCD_Screens>(0) ,0)
};
void DGUSCrealityDisplay_HandleReturnKeyEvent(DGUS_VP_Variable &var, void *val_ptr) {
const struct PageHandler *map = PageHandlers;
const uint16_t *ret;
const DGUSLCD_Screens current_screen = DGUSScreenHandler::getCurrentScreen();
while ((ret = (uint16_t*) pgm_read_ptr(&(map->Handler)))) {
if ((map->ScreenID) == current_screen) {
uint16_t button_value = uInt16Value(val_ptr);
SERIAL_ECHOLNPGM("Invoking handler for screen ", current_screen);
SERIAL_ECHOLNPGM("with VP=", var.VP, " value=", button_value);
map->Handler(var, button_value);
return;
}
map++;
}
}
#endif
@@ -1,11 +0,0 @@
#pragma once
// Mapping of handlers per page. This construction is necessary because the CR-6 touch screen re-uses the same button IDs all over the place.
typedef void (*DGUS_CREALITY_SCREEN_BUTTON_HANDLER)(DGUS_VP_Variable &var, unsigned short buttonValue);
struct PageHandler {
DGUSLCD_Screens ScreenID;
DGUS_CREALITY_SCREEN_BUTTON_HANDLER Handler;
};
void DGUSCrealityDisplay_HandleReturnKeyEvent(DGUS_VP_Variable &var, void *val_ptr);
-267
View File
@@ -1,267 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* dgus_creality_lcd.cpp
*
* DGUS implementation written by coldtobi in 2019 for Marlin
*/
#include "../../inc/MarlinConfigPre.h"
#if ENABLED(DGUS_LCD_UI_CREALITY_TOUCH)
#include "ui_api.h"
#include "../marlinui.h"
#include "./dgus_creality/DGUSDisplay.h"
#include "./dgus_creality/DGUSDisplayDef.h"
#include "./dgus_creality/DGUSScreenHandler.h"
#include "./dgus_creality/creality_touch/PIDHandler.h"
#include "./dgus_creality/creality_touch/MeshValidationHandler.h"
#if ENABLED(POWER_LOSS_RECOVERY)
#include "../../feature/powerloss.h"
#endif
extern const char NUL_STR[];
namespace ExtUI {
void onStartup() {
ScreenHandler.Init();
ScreenHandler.UpdateScreenVPData();
}
void onIdle() { ScreenHandler.loop(); }
void onPrinterKilled(FSTR_P const error, FSTR_P const component) {
ScreenHandler.sendinfoscreen(GET_TEXT_F(MSG_HALTED), error, GET_TEXT_F(MSG_PLEASE_RESET), GET_TEXT_F(MSG_PLEASE_RESET), true, true, true, true);
if (error == GET_TEXT_F(MSG_ERR_MAXTEMP) || error == GET_TEXT_F(MSG_THERMAL_RUNAWAY)) {
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_THERMAL_RUNAWAY);
} else if ( error == GET_TEXT_F(MSG_HEATING_FAILED_LCD)) {
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_HEATING_FAILED);
}else if (error == GET_TEXT_F(MSG_ERR_MINTEMP)) {
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_THERMISTOR_ERROR);
} else {
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_KILL);
}
ScreenHandler.KillScreenCalled();
while (!ScreenHandler.loop()); // Wait while anything is left to be sent
}
void onMediaInserted() { TERN_(SDSUPPORT, ScreenHandler.SDCardInserted()); }
void onMediaError() { TERN_(SDSUPPORT, ScreenHandler.SDCardError()); }
void onMediaRemoved() { TERN_(SDSUPPORT, ScreenHandler.SDCardRemoved()); }
void onPlayTone(const uint16_t frequency, const uint16_t duration) {
if (ScreenHandler.getCurrentScreen() == DGUSLCD_SCREEN_FEED) {
// We're in the feed (load filament) workflow - no beep - there is no confirmation
return;
}
ScreenHandler.Buzzer(frequency, duration);
}
bool hasPrintTimer = false;
void onPrintTimerStarted() {
hasPrintTimer = true;
if (!IS_SD_FILE_OPEN() && !(PrintJobRecovery::valid() && PrintJobRecovery::exists())) {
ScreenHandler.SetPrintingFromHost();
}
#if ENABLED(LCD_SET_PROGRESS_MANUALLY)
ui.progress_reset();
#endif
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_PRINT_RUNNING);
}
void onPrintTimerPaused() {
// Handle M28 Pause SD print - But only if we're not waiting on a user
if (ExtUI::isPrintingFromMediaPaused() && ScreenHandler.getCurrentScreen() == DGUSLCD_SCREEN_PRINT_RUNNING && !ExtUI::awaitingUserConfirm()) {
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_PRINT_PAUSED);
}
}
void onPrintTimerStopped() {
hasPrintTimer = false;
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_PRINT_FINISH);
}
void onFilamentRunout(const extruder_t extruder) {
// Only navigate to filament runout screen when we don't use M600 for changing the filament - otherwise it gets confusing for the user
#ifndef FILAMENT_RUNOUT_SCRIPT
#define FILAMENT_RUNOUT_SCRIPT "M25"
#endif
if (strcmp_P(FILAMENT_RUNOUT_SCRIPT, PSTR("M600")) != 0) {
ScreenHandler.FilamentRunout();
}
}
void onUserConfirmed() {
SERIAL_ECHOLN("User confirmation invoked");
setPauseMenuResponse(PAUSE_RESPONSE_RESUME_PRINT);
ExtUI::setUserConfirmed();
}
void onUserConfirmRequired(const char * const msg) {
//if (msg) {
SERIAL_ECHOLNPGM("User confirmation requested: ", msg);
if (ScreenHandler.getCurrentScreen() == DGUSLCD_SCREEN_FEED) {
// We're in the feed (load filament) workflow - immediately assume confirmed
onUserConfirmed();
return;
}
ScreenHandler.setstatusmessagePGM(msg);
ScreenHandler.sendinfoscreen("Confirmation required", msg, NUL_STR, "Ok", true, true, false, true);
if (ExtUI::isPrinting()) {
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_PRINT_PAUSED);
} else {
ScreenHandler.GotoScreen(DGUSLCD_SCREEN_POPUP);
}
//}
//else if (ScreenHandler.getCurrentScreen() == DGUSLCD_SCREEN_POPUP) {
// DEBUG_ECHOLNPAIR("User confirmation canceled");
// ScreenHandler.setstatusmessagePGM(nullptr);
// ScreenHandler.PopToOldScreen();
//}
}
void onStatusChanged(const char * const msg) { ScreenHandler.setstatusmessage(msg); }
void onFactoryReset() {
ScreenHandler.OnFactoryReset();
}
void onHomingStart() {
ScreenHandler.OnHomingStart();
}
void onHomingDone() {
ScreenHandler.OnHomingComplete();
}
void onPrintDone() {
ScreenHandler.OnPrintFinished();
}
void onStoreSettings(char *buff) {
ScreenHandler.StoreSettings(buff);
}
void onLoadSettings(const char *buff) {
ScreenHandler.LoadSettings(buff);
}
void onPostprocessSettings() {
// Called after loading or resetting stored settings
}
void onSettingsStored(bool success) {
// Called after the entire EEPROM has been written,
// whether successful or not.
}
void onSettingsLoaded(bool success) {
// Called after the entire EEPROM has been read,
// whether successful or not.
}
#if HAS_MESH
void onLevelingStart() {
#if HAS_BED_PROBE
ScreenHandler.OnMeshLevelingStart();
#endif
}
void onMeshUpdate(const int8_t xpos, const int8_t ypos, const float zval) {
ScreenHandler.OnMeshLevelingUpdate(xpos, ypos, zval);
}
void onMeshUpdate(const int8_t xpos, const int8_t ypos, const ExtUI::probe_state_t state) {
ScreenHandler.OnMeshLevelingUpdate(xpos, ypos, 0);
}
void onLevelingDone() {
}
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
void onPowerLossResume() {
// Called on resume from power-loss
ScreenHandler.OnPowerlossResume();
}
#endif
#if HAS_PID_HEATING
void onPidTuning(const result_t rst) {
// Called for temperature PID tuning result
switch (rst) {
case PID_BAD_HEATER_ID:
PIDHandler::result_message = GET_TEXT(MSG_PID_BAD_HEATER_ID);
ScreenHandler.setstatusmessagePGM(PIDHandler::result_message);
break;
case PID_TEMP_TOO_HIGH:
PIDHandler::result_message = GET_TEXT(MSG_PID_TEMP_TOO_HIGH);
ScreenHandler.setstatusmessagePGM(PIDHandler::result_message);
break;
case PID_TUNING_TIMEOUT:
PIDHandler::result_message = GET_TEXT(MSG_PID_TIMEOUT);
ScreenHandler.setstatusmessagePGM(PIDHandler::result_message);
break;
case PID_DONE:
PIDHandler::result_message = GET_TEXT(MSG_PID_AUTOTUNE_DONE);
ScreenHandler.setstatusmessagePGM(PIDHandler::result_message);
break;
default:
break;
}
}
#endif
void onSteppersDisabled() {
}
void onSteppersEnabled() {
}
#if HAS_MESH
void onMeshValidationStarting() {
MeshValidationHandler::OnMeshValidationStart();
}
void onMeshValidationFinished() {
MeshValidationHandler::OnMeshValidationFinish();
}
#endif
}
#endif // HAS_DGUS_LCD
@@ -395,12 +395,7 @@ void DGUSReturnKeyCodeHandler::Command_SettingsMenu(DGUS_VP &vp, void *data) {
}
static void _gotoTrammingPoint(unsigned char point) {
#if ENABLED(BED_TRAMMING_USE_PROBE)
float lfrb[4] = {X_MIN_BED + probe.min_x(), Y_MIN_BED + probe.min_y(),
X_MAX_BED - probe.max_x(), Y_MAX_BED - probe.max_y() };
#else
constexpr float lfrb[4] = BED_TRAMMING_INSET_LFRB;
#endif
constexpr float lfrb[4] = BED_TRAMMING_INSET_LFRB;
float x, y;
switch (point) {
@@ -38,9 +38,6 @@
#if ENABLED(ADVANCED_PAUSE_FEATURE)
#include "../../../feature/pause.h"
#endif
#if ENABLED(BED_TRAMMING_USE_PROBE)
#include "../../../module/probe.h"
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
#include "../../../feature/powerloss.h"
#endif
@@ -467,14 +464,7 @@ void DGUSRxHandler::moveToPoint(DGUS_VP &vp, void *data_ptr) {
}
const uint8_t point = ((uint8_t*)data_ptr)[1];
#if ENABLED(BED_TRAMMING_USE_PROBE)
float lfrb[4] = {X_MIN_BED + probe.min_x(), Y_MIN_BED + probe.min_y(),
X_MAX_BED - probe.max_x(), Y_MAX_BED - probe.max_y() };
#else
constexpr float lfrb[4] = BED_TRAMMING_INSET_LFRB;
#endif
constexpr float lfrb[4] = BED_TRAMMING_INSET_LFRB;
float x, y;
switch (point) {
File diff suppressed because it is too large Load Diff
@@ -1,304 +0,0 @@
/**
* 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/>.
*
*/
/* ****************************************
* lcd/extui/lib/Creality/Creality_DWIN.h
* ****************************************
* Extensible_UI implementation for Creality DWIN
* 10SPro, Max, CRX, and others
* Based original Creality release, ported to ExtUI for Marlin 2.0
* Written by Insanity Automation, sponsored by Tiny Machines 3D
*
* ***************************************/
#pragma once
#include "string.h"
#include <Arduino.h>
#include "../ui_api.h"
#if ENABLED(EXTENSIBLE_UI)
namespace ExtUI {
/*********************************/
#define FHONE (0x5A)
#define FHTWO (0xA5)
#define FHLENG (0x06)
#define TEXTBYTELEN 18
#define MaxFileNumber 20// 16
#define CEIconGrap 12
#define FileNum MaxFileNumber
#define FileNameLen TEXTBYTELEN
#define SizeofDatabuf 46
/*************Register and Variable addr*****************/
#define RegAddr_W 0x80
#define RegAddr_R 0x81
#define VarAddr_W 0x82
#define VarAddr_R 0x83
#define ExchangePageBase (unsigned long)0x5A010000 //the first page ID. other page = first page ID + relevant num;
#define StartSoundSet ((unsigned long)0x060480A0) // 06,start-music; 04, 4 musics; 80, the volume value; 04, return value about music number.
#define FONT_EEPROM 90
#define AutoLeve_EEPROM 100
#define FanOn 255
#define FanOff 0
/*variable addr*/
#define ExchangepageAddr 0x0084
#define SoundAddr 0x00A0
#define StartIcon 0x1000
#define FeedrateDisplay 0x1006 // Speed
#define Stopprint 0x1008
#define Pauseprint 0x100A
#define Resumeprint 0x100C
#define PrintscheduleIcon 0x100E
#define Timehour 0x1010
#define Timemin 0x1012
#define IconPrintstatus 0x1014
#define Percentage 0x1016
#define FanKeyIcon 0x101E
#define Flowrate 0x1300
#define RunoutToggle 0x1018
#define PowerLossToggle 0x101A
#define LedToggle 0x101C
#define StepMM_X 0x1242
#define StepMM_Y 0x1246
#define StepMM_Z 0x124A
#define StepMM_E 0x124E
#define ProbeOffset_X 0x1236
#define ProbeOffset_Y 0x123A
#define ProbeOffset_Z 0x1026
#define T2Offset_X 0x1090
#define T2Offset_Y 0x1094
#define T2Offset_Z 0x1098
#define T2StepMM_E 0x109C
#define ActiveToolVP 0x1014
#define HotendPID_AutoTmp 0x1252
#define BedPID_AutoTmp 0x1254
#define HotendPID_P 0x1256
#define HotendPID_I 0x125A
#define HotendPID_D 0x125E
#define BedPID_P 0x1262
#define BedPID_I 0x1266
#define BedPID_D 0x126A
#define Jerk_X 0x1270
#define Jerk_Y 0x1272
#define Jerk_Z 0x1274
#define Jerk_E 0x1276
#define Feed_X 0x1278
#define Feed_Y 0x127A
#define Feed_Z 0x127C
#define Feed_E 0x127E
#define Accel_X 0x1280
#define Accel_Y 0x1282
#define Accel_Z 0x1284
#define Accel_E 0x1286
#define ShapingZetaX 0x10A0
#define ShapingZetaY 0x10A2
#define ShapingFreqX 0x10A4
#define ShapingFreqY 0x10A8
#define LinAdvKFactor 0x10AA
#define RunoutMode 0x10AC
#define BabystepIncrement 0x10AE
#define HeatPercentIcon 0x1024
#define NzBdSet 0x1032 // cooldown Hotend and Bed
#define NozzlePreheat 0x1034 // setpoint
#define NozzleTemp 0x1036 // Actual
#define BedPreheat 0x103A // Setpoint
#define Bedtemp 0x103C // Actual
#define e2Temp 0x1050
#define e2Preheat 0x104E
#define AutoZeroIcon 0x1042
#define AutoLevelIcon 0x1045
#define AutoZero 0x1046
#define DisplayXaxis 0x1048
#define DisplayYaxis 0x104A
#define DisplayZaxis 0x104C
#define FilementUnit1 0x1054
#define Exchfilement 0x1056
#define FilementUnit2 0x1058
#define MacVersion 0x1060
#define SoftVersion 0x106A
#define PrinterSize 0x1074
#define CorpWebsite 0x107E
#define VolumeIcon 0x108A
#define SoundIcon 0x108C
#define AutolevelIcon 0x108D
#define ExchFlmntIcon 0x108E
#define AutolevelVal 0x1100
#define FilenameIcon 0x1200
#define FilenameIcon1 0x1220
#define Printfilename 0x2000
#define FilesCurentPage 0x1310
#define FilesMaxPage 0x1312
#define SDFILE_ADDR 0x200A
#define FilenamePlay 0x20D2
#define FilenameChs 0x20D3
#define Choosefilename 0x20D4
#define FilenameCount 0x20DE
#define FilenameNature 0x6003
#define VolumeDisplay 0x1140
#define DisplayBrightness 0x1142
#define DisplayStandbyBrightness 0x1144
#define DisplayStandbyEnableIndicator 0x1146
#define DisplayStandbySeconds 0x1148
#define StatusMessageString 0x2064
#if defined(TARGET_STM32F4)
#define DWIN_SERIAL Serial1
#else
#define DWIN_SERIAL LCD_SERIAL
#endif
/************struct**************/
typedef enum : uint8_t {
DGUS_IDLE, //< waiting for DGUS_HEADER1.
DGUS_HEADER1_SEEN, //< DGUS_HEADER1 received
DGUS_HEADER2_SEEN, //< DGUS_HEADER2 received
DGUS_WAIT_TELEGRAM, //< LEN received, Waiting for to receive all bytes.
} rx_datagram_state_t;
typedef struct DataBuf
{
unsigned char len;
unsigned char head[2];
unsigned char command;
unsigned long addr;
unsigned long bytelen;
unsigned short data[32];
unsigned char reserv[4];
} DB;
struct creality_dwin_settings_t {
size_t settings_size;
uint8_t settings_version;
bool display_standby;
bool display_sound;
int8_t screen_rotation;
int16_t display_volume;
uint8_t standby_screen_brightness;
uint8_t screen_brightness;
int16_t standby_time_seconds;
};
void SetTouchScreenConfiguration();
class RTSSHOW {
public:
RTSSHOW();
int RTS_RecData();
void RTS_SDCardInit(void);
void RTS_SDCardUpate(bool, bool);
int RTS_CheckFilement(int);
void RTS_SndData(void);
void RTS_SndData(const String &, unsigned long, unsigned char = VarAddr_W);
void RTS_SndData(const char[], unsigned long, unsigned char = VarAddr_W);
void RTS_SndData(char, unsigned long, unsigned char = VarAddr_W);
void RTS_SndData(unsigned char*, unsigned long, unsigned char = VarAddr_W);
void RTS_SndData(int, unsigned long, unsigned char = VarAddr_W);
void RTS_SndData(float, unsigned long, unsigned char = VarAddr_W);
void RTS_SndData(unsigned int,unsigned long, unsigned char = VarAddr_W);
void RTS_SndData(long,unsigned long, unsigned char = VarAddr_W);
void RTS_SndData(unsigned long,unsigned long, unsigned char = VarAddr_W);
void WriteVariable(uint16_t adr, const void* values, uint8_t valueslen, bool isstr=false, char fillChar = ' ');
void WriteVariable(uint16_t adr, long);
void RTS_SDcard_Stop();
void RTS_HandleData();
void RTS_Init();
DB recdat;
DB snddat;
unsigned char databuf[SizeofDatabuf];
static rx_datagram_state_t rx_datagram_state;
static uint8_t rx_datagram_len;
static bool Initialized;
};
static RTSSHOW rtscheck;
#define Addvalue 3
#define PrintChoice_Value (0+Addvalue)
#define Zoffset_Value (3+Addvalue)
#define Setting_Value (8+Addvalue)
#define XYZEaxis_Value (12+Addvalue)
#define Filement_Value (15+Addvalue)
#define Language_Value (18+Addvalue)
#define Filename_Value (22+Addvalue)
#define Idex_Settings_Value (26+Addvalue)
enum PROC_COM {Printfile=0,Ajust,Feedrate,PrintChoice=PrintChoice_Value,Zoffset=Zoffset_Value,TempControl,ManualSetTemp,Setting=Setting_Value,
ReturnBack,Bedlevel,Autohome,XYZEaxis=XYZEaxis_Value,Filement=Filement_Value,LanguageChoice=Language_Value,No_Filement,PwrOffNoF,Volume,Filename=Filename_Value,Idex_Settings=Idex_Settings_Value};
const unsigned long Addrbuf[] = {0x1002, 0x1004, 0x1006, 0x1008, 0x100A, 0x100C, 0x1026, 0x1030, 0x1032, 0x1034, 0x103A,
0x103E, 0x1040, 0x1044, 0x1046, 0x1048, 0x104A, 0x104C, 0x1054, 0x1056, 0x1058,
0x105C, 0x105E, 0x105F, 0x1088, 0};
void RTSUpdate();
void RTSInit();
}
#ifndef MAIN_MENU_ITEM_1_GCODE
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
#define MEASURING_GCODE "M190S55\nG28O\nG34\nG29\nM400\nM104S215\nG28\nM109S215\nM420S1\nG1X100Y100F5000\nG1Z0\nM500\nM117 Set Z Offset"
#elif ENABLED(AUTO_BED_LEVELING_UBL)
#define MEASURING_GCODE "M190S55\nG28O\nG34\nG29P1\nG29P3\nG29S1\nG29S0\nG29F0.0\nG29A\nM104S215\nG28\nM109S215\nG1X150Y150F5000\nG1Z0\nM500\nM400\nM117 Set Z Offset"
#else
#define MEASURING_GCODE "G28"
#endif
#else
#define MEASURING_GCODE MAIN_MENU_ITEM_1_GCODE
#endif
#endif
@@ -1,189 +0,0 @@
/**
* 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/>.
*
*/
/* ****************************************
* lcd/extui/lib/Creality/FileNavigator.cpp
* ****************************************
* Extensible_UI implementation for Creality DWIN
* 10SPro, Max, CR10V2
* Based on implementations for Anycubic Chiron and Nextion by Nick Wells and Skorpi08
* Written by Insanity Automation
* ***************************************/
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(EXTENSIBLE_UI)
#include "FileNavigator.h"
using namespace ExtUI;
#define DEBUG_OUT NEXDEBUGLEVEL
#include "../../../core/debug_out.h"
FileList FileNavigator::filelist; // Instance of the Marlin file API
char FileNavigator::currentfoldername[MAX_PATH_LEN]; // Current folder path
uint16_t FileNavigator::lastindex;
uint8_t FileNavigator::folderdepth;
uint16_t FileNavigator::currentindex; // override the panel request
FileNavigator filenavigator;
FileNavigator::FileNavigator() { reset(); }
void FileNavigator::reset() {
currentfoldername[0] = '\0';
folderdepth = 0;
currentindex = 0;
lastindex = 0;
// Start at root folder
while (!filelist.isAtRootDir()) filelist.upDir();
refresh();
}
void FileNavigator::refresh() { filelist.refresh(); }
bool FileNavigator::getIndexisDir(uint16_t index){
filelist.seek(index);
return filelist.isDir();
}
const char *FileNavigator::getIndexName(uint16_t index){
filelist.seek(index);
return filelist.shortFilename();
}
uint16_t FileNavigator::maxFiles() {
return filelist.count();
}
void FileNavigator::getFiles(uint16_t index) {
uint16_t files = DISPLAY_FILES, fcnt = 0;
if (index == 0)
currentindex = 0;
else {
// Each time we change folder we reset the file index to 0 and keep track
// of the current position as the TFT panel isn't aware of folder trees.
--currentindex; // go back a file to take account of the .. added to the root.
if (index > lastindex)
currentindex += files + 1;
else if (currentindex >= files)
currentindex -= files - 1;
else
currentindex = 0;
}
lastindex = index;
// Clear currently drawn screen
for (int i = 0; i < DISPLAY_FILES; i++)
{
for (int j = 0; j < 20; j++)
rtscheck.RTS_SndData(0, SDFILE_ADDR + (i * 20) + j);
}
for (int j = 0; j < 10; j++)
{
rtscheck.RTS_SndData(0, Printfilename + j); //clean screen.
rtscheck.RTS_SndData(0, Choosefilename + j); //clean filename
}
for (int j = 0; j < 8; j++)
rtscheck.RTS_SndData(0, FilenameCount + j);
for (int j = 1; j <= DISPLAY_FILES; j++)
{
rtscheck.RTS_SndData(10, FilenameIcon + j);
rtscheck.RTS_SndData(10, FilenameIcon1 + j);
}
DEBUG_ECHOLNPGM("index=", index, " currentindex=", currentindex, "folderdepth=", folderdepth);
if (currentindex == 0 && folderdepth > 0) { // Add a link to go up a folder
files--;
rtscheck.RTS_SndData("Up Directory", SDFILE_ADDR);
fcnt++;
}
else if(currentindex == DISPLAY_FILES && folderdepth > 0)
currentindex--;
for (uint16_t seek = currentindex; seek < currentindex + files; seek++) {
if (filelist.seek(seek)) {
const int filelen = strlen(filelist.filename());
if(filelen > 20)
{
char *buf = (char *)filelist.filename();
//char buf[filelen];
//strcpy(&buf[filelen], filelist.filename());
buf[18] = '\0'; // cutoff at screen edge
rtscheck.RTS_SndData(buf, (SDFILE_ADDR + (fcnt * 20)));
}
else
rtscheck.RTS_SndData(filelist.filename(), (SDFILE_ADDR + (fcnt * 20)));
if (filelist.isDir())
{
rtscheck.RTS_SndData((uint8_t)4, FilenameIcon + (fcnt+1));
rtscheck.RTS_SndData((unsigned long)0x041F, (FilenameNature + ((1+fcnt) * 16))); // Change BG of selected line to Blue
}
else
{
rtscheck.RTS_SndData((uint8_t)0, FilenameIcon + (fcnt+1));
rtscheck.RTS_SndData((unsigned long)0xFFFF, (FilenameNature + ((1+fcnt) * 16))); // white
}
SERIAL_ECHOLNPGM("-", seek, " '", filelist.filename(), "' '", currentfoldername, "", filelist.shortFilename(), "'\n");
fcnt++;
}
}
}
void FileNavigator::changeDIR(char *folder) {
DEBUG_ECHOLNPGM("currentfolder: ", currentfoldername, " New: ", folder);
if (folderdepth >= MAX_FOLDER_DEPTH) return; // limit the folder depth
strcat(currentfoldername, folder);
strcat(currentfoldername, "/");
filelist.changeDir(folder);
refresh();
folderdepth++;
currentindex = 0;
}
void FileNavigator::upDIR() {
filelist.upDir();
refresh();
folderdepth--;
currentindex = 0;
// Remove the last child folder from the stored path
if (folderdepth == 0) {
currentfoldername[0] = '\0';
reset();
}
else {
char *pos = nullptr;
for (uint8_t f = 0; f < folderdepth; f++)
pos = strchr(currentfoldername, '/');
pos[1] = '\0';
}
DEBUG_ECHOLNPGM("depth: ", folderdepth, " currentfoldername: ", currentfoldername);
}
char* FileNavigator::getCurrentFolderName() { return currentfoldername; }
#endif
@@ -1,63 +0,0 @@
/**
* 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
/* ****************************************
* lcd/extui/lib/Creality/FileNavigator.h
* ****************************************
* Extensible_UI implementation for Creality DWIN
* 10SPro, Max, CRX and others
* Based on implementations for Anycubic Chiron and Nextion by Nick Wells and Skorpi08
* Written by Insanity Automation
* ***************************************/
#include "../ui_api.h"
#include "Creality_DWIN.h"
#define MAX_FOLDER_DEPTH 4 // Limit folder depth TFT has a limit for the file path
#define MAX_CMND_LEN 16 * MAX_FOLDER_DEPTH // Maximum Length for a Panel command
#define MAX_PATH_LEN 16 * MAX_FOLDER_DEPTH // Maximum number of characters in a SD file path
#define DISPLAY_FILES 4
using namespace ExtUI;
class FileNavigator {
public:
FileNavigator();
static void reset();
static void getFiles(uint16_t);
static void upDIR();
static void changeDIR(char *);
static void refresh();
static char* getCurrentFolderName();
static uint8_t folderdepth;
static uint16_t currentindex;
static bool getIndexisDir(uint16_t);
const char *getIndexName(uint16_t);
static uint16_t maxFiles();
private:
static FileList filelist;
static char currentfoldername[MAX_PATH_LEN];
static uint16_t lastindex;
};
extern FileNavigator filenavigator;
+2 -34
View File
@@ -722,23 +722,12 @@ namespace ExtUI {
}
#if HAS_FILAMENT_SENSOR
bool getFilamentRunoutEnabled(const extruder_t extruder/*=E0*/) { return (runout.enabled[extruder] && (runout.mode[extruder]!=0)); }
bool getFilamentRunoutEnabled(const extruder_t extruder/*=E0*/) { return runout.enabled[extruder]; }
void setFilamentRunoutEnabled(const bool value, const extruder_t extruder/*=E0*/) { runout.enabled[extruder] = value; }
bool getFilamentRunoutState() { return runout.filament_ran_out; }
void setFilamentRunoutState(const bool value) { runout.filament_ran_out = value; }
float getFilamentRunoutDistance_mm() { return runout.runout_distance(); }
void setFilamentRunoutDistance_mm(const_float_t value) { runout.set_runout_distance(constrain(value, 0, 999)); }
int getRunoutMode(const extruder_t extruder/*=E0*/){
return (int)runout.mode[extruder];
}
void setRunoutMode(const int mode, const extruder_t extruder/*=E0*/){
if((mode >= 0 && mode <=2) || mode==7) {
runout.mode[extruder] = (RunoutMode)mode;
runout.setup();
}
}
#endif
#if ENABLED(CASE_LIGHT_ENABLE)
@@ -773,26 +762,6 @@ namespace ExtUI {
}
#endif
#if HAS_SHAPING
float getShapingZeta(const axis_t axis) {
return stepper.get_shaping_damping_ratio(AxisEnum(axis));
}
void setShapingZeta(const float zeta, const axis_t axis) {
if (WITHIN(zeta, 0, 1)) {
stepper.set_shaping_damping_ratio(AxisEnum(axis), zeta);
}
}
float getShapingFrequency(const axis_t axis) {
return stepper.get_shaping_frequency(AxisEnum(axis));
}
void setShapingFrequency(const float freq, const axis_t axis) {
constexpr float min_freq = float(uint32_t(STEPPER_TIMER_RATE) / 2) / shaping_time_t(-2);
if (freq == 0.0f || freq > min_freq) {
stepper.set_shaping_frequency(AxisEnum(axis), freq);
}
}
#endif
#if HAS_JUNCTION_DEVIATION
float getJunctionDeviation_mm() { return planner.junction_deviation_mm; }
@@ -961,7 +930,6 @@ namespace ExtUI {
#if HAS_BED_PROBE
float getProbeOffset_mm(const axis_t axis) { return probe.offset.pos[axis]; }
void setProbeOffset_mm(const_float_t val, const axis_t axis) { probe.offset.pos[axis] = val; }
probe_limits getBedProbeLimits() {return (probe_limits){probe.min_x(), probe.min_y(), probe.max_x(), probe.max_y()};}
#endif
#if ENABLED(BACKLASH_GCODE)
@@ -1198,7 +1166,7 @@ namespace ExtUI {
return isPrinting() && (isPrintingFromMediaPaused() || print_job_timer.isPaused());
}
bool isMediaInserted() { return TERN0(HAS_MEDIA, IS_SD_INSERTED() || card.isMounted()); }
bool isMediaInserted() { return TERN0(HAS_MEDIA, IS_SD_INSERTED()); }
// Pause/Resume/Stop are implemented in MarlinUI
void pausePrint() { ui.pause_print(); }
-11
View File
@@ -68,7 +68,6 @@ namespace ExtUI {
enum extruder_t : uint8_t { E0, E1, E2, E3, E4, E5, E6, E7 };
enum heater_t : uint8_t { H0, H1, H2, H3, H4, H5, BED, CHAMBER, COOLER };
enum fan_t : uint8_t { FAN0, FAN1, FAN2, FAN3, FAN4, FAN5, FAN6, FAN7 };
struct probe_limits { float pos[4];};
#if HAS_PID_HEATING
enum pidresult_t : uint8_t { PID_STARTED, PID_BED_STARTED, PID_CHAMBER_STARTED, PID_BAD_HEATER_ID, PID_TEMP_TOO_HIGH, PID_TUNING_TIMEOUT, PID_DONE };
#endif
@@ -328,13 +327,6 @@ namespace ExtUI {
void setLinearAdvance_mm_mm_s(const_float_t, const extruder_t);
#endif
#if HAS_SHAPING
float getShapingZeta(const axis_t);
void setShapingZeta(const float, const axis_t);
float getShapingFrequency(const axis_t);
void setShapingFrequency(const float, const axis_t);
#endif
// JD or Jerk Control
#if HAS_JUNCTION_DEVIATION
float getJunctionDeviation_mm();
@@ -375,7 +367,6 @@ namespace ExtUI {
#if HAS_BED_PROBE
float getProbeOffset_mm(const axis_t);
void setProbeOffset_mm(const_float_t, const axis_t);
probe_limits getBedProbeLimits();
#endif
// Backlash Control
@@ -400,8 +391,6 @@ namespace ExtUI {
void setFilamentRunoutState(const bool);
float getFilamentRunoutDistance_mm();
void setFilamentRunoutDistance_mm(const_float_t);
int getRunoutMode(const extruder_t extruder=E0);
void setRunoutMode(const int, const extruder_t extruder=E0);
#endif
// Case Light Control
+2 -2
View File
@@ -99,7 +99,7 @@ void menu_backlash();
#endif
#if HAS_FILAMENT_SENSOR
#if HAS_FILAMENT_SENSOR && DISABLED(SLIM_LCD_MENUS)
void set_runout_mode_none(const uint8_t e) { runout.mode[e] = RM_NONE; runout.setup(); }
void set_runout_mode_high(const uint8_t e) { runout.mode[e] = RM_OUT_ON_HIGH; runout.setup(); }
@@ -200,7 +200,7 @@ void menu_backlash();
#endif
#endif
#if HAS_FILAMENT_SENSOR
#if HAS_FILAMENT_SENSOR && DISABLED(SLIM_LCD_MENUS)
SUBMENU(MSG_RUNOUT_MODE, menu_runout_config);
#endif
+8 -9
View File
@@ -94,22 +94,16 @@ static_assert(COUNT(lco) == 4 || lcodiff == 1 || lcodiff == 3, "The first two BE
constexpr int nr_edge_points = tramming_3_points ? 3 : 4;
constexpr int available_points = nr_edge_points + ENABLED(BED_TRAMMING_INCLUDE_CENTER);
constexpr int center_index = TERN(BED_TRAMMING_INCLUDE_CENTER, available_points - 1, -1);
#if DISABLED(BED_TRAMMING_USE_PROBE)
constexpr float inset_lfrb[4] = BED_TRAMMING_INSET_LFRB;
constexpr xy_pos_t lf { (X_MIN_BED) + inset_lfrb[0], (Y_MIN_BED) + inset_lfrb[1] },
constexpr float inset_lfrb[4] = BED_TRAMMING_INSET_LFRB;
constexpr xy_pos_t lf { (X_MIN_BED) + inset_lfrb[0], (Y_MIN_BED) + inset_lfrb[1] },
rb { (X_MAX_BED) - inset_lfrb[2], (Y_MAX_BED) - inset_lfrb[3] };
#endif
static int8_t bed_corner;
/**
* Move to the next corner coordinates
*/
static void _lcd_goto_next_corner() {
#if ENABLED(BED_TRAMMING_USE_PROBE)
xy_pos_t lf = {X_MIN_BED + probe.min_x() + 0.01f, Y_MIN_BED + probe.min_y() + 0.01f },
rb = {X_MAX_BED - probe.max_x() - 0.01f, Y_MAX_BED - probe.max_y() - 0.01f };
#endif
xy_pos_t corner_point = lf; // Left front
if (tramming_3_points) {
@@ -171,6 +165,11 @@ static void _lcd_goto_next_corner() {
#if ENABLED(BED_TRAMMING_USE_PROBE)
#define VALIDATE_POINT(X, Y, STR) static_assert(Probe::build_time::can_reach((X), (Y)), \
"BED_TRAMMING_INSET_LFRB " STR " inset is not reachable with the default NOZZLE_TO_PROBE offset and PROBING_MARGIN.")
VALIDATE_POINT(lf.x, Y_CENTER, "left"); VALIDATE_POINT(X_CENTER, lf.y, "front");
VALIDATE_POINT(rb.x, Y_CENTER, "right"); VALIDATE_POINT(X_CENTER, rb.y, "back");
#ifndef PAGE_CONTAINS
#define PAGE_CONTAINS(...) true
#endif
+9 -12
View File
@@ -26,7 +26,7 @@
#include "../../inc/MarlinConfigPre.h"
#if ALL(HAS_MARLINUI_MENU, ADVANCED_PAUSE_FEATURE)
#if BOTH(HAS_MARLINUI_MENU, ADVANCED_PAUSE_FEATURE)
#include "menu_item.h"
#include "../../module/temperature.h"
@@ -96,7 +96,7 @@ void _menu_temp_filament_op(const PauseMode mode, const int8_t extruder) {
if (LCD_HEIGHT >= 4) STATIC_ITEM_F(change_filament_header(mode), SS_DEFAULT|SS_INVERT);
BACK_ITEM(MSG_BACK);
#if HAS_PREHEAT
for (uint8_t m = 0; m < PREHEAT_COUNT; ++m)
LOOP_L_N(m, PREHEAT_COUNT)
ACTION_ITEM_N_f(m, ui.get_preheat_label(m), MSG_PREHEAT_M, _change_filament_with_preset);
#endif
EDIT_ITEM_FAST_N(int3, extruder, MSG_PREHEAT_CUSTOM, &thermalManager.temp_hotend[extruder].target,
@@ -130,7 +130,7 @@ void menu_change_filament() {
#endif
START_MENU();
BACK_ITEM(MSG_MAIN_MENU);
BACK_ITEM(MSG_MAIN);
// Change filament
#if E_STEPPERS == 1
@@ -141,7 +141,7 @@ void menu_change_filament() {
GCODES_ITEM_F(fmsg, F("M600 B0"));
#else
FSTR_P const fmsg = GET_TEXT_F(MSG_FILAMENTCHANGE_E);
for (uint8_t s = 0; s < E_STEPPERS; ++s) {
LOOP_L_N(s, E_STEPPERS) {
if (thermalManager.targetTooColdToExtrude(s))
SUBMENU_N_F(s, fmsg, []{ _menu_temp_filament_op(PAUSE_MODE_CHANGE_FILAMENT, MenuItemBase::itemIndex); });
else {
@@ -166,7 +166,7 @@ void menu_change_filament() {
GCODES_ITEM_F(msg_load, F("M701"));
#else
FSTR_P const msg_load = GET_TEXT_F(MSG_FILAMENTLOAD_E);
for (uint8_t s = 0; s < E_STEPPERS; ++s) {
LOOP_L_N(s, E_STEPPERS) {
if (thermalManager.targetTooColdToExtrude(s))
SUBMENU_N_F(s, msg_load, []{ _menu_temp_filament_op(PAUSE_MODE_LOAD_FILAMENT, MenuItemBase::itemIndex); });
else {
@@ -194,7 +194,7 @@ void menu_change_filament() {
GCODES_ITEM(MSG_FILAMENTUNLOAD_ALL, F("M702"));
#endif
FSTR_P const msg_unload = GET_TEXT_F(MSG_FILAMENTUNLOAD_E);
for (uint8_t s = 0; s < E_STEPPERS; ++s) {
LOOP_L_N(s, E_STEPPERS) {
if (thermalManager.targetTooColdToExtrude(s))
SUBMENU_N_F(s, msg_unload, []{ _menu_temp_filament_op(PAUSE_MODE_UNLOAD_FILAMENT, MenuItemBase::itemIndex); });
else {
@@ -250,12 +250,6 @@ static FSTR_P pause_header() {
}while(0)
void menu_pause_option() {
#if HAS_FILAMENT_SENSOR
const bool still_out = runout.filament_ran_out;
#else
constexpr bool still_out = false;
#endif
START_MENU();
#if LCD_HEIGHT > 2
STATIC_ITEM(MSG_FILAMENT_CHANGE_OPTION_HEADER);
@@ -263,8 +257,11 @@ void menu_pause_option() {
ACTION_ITEM(MSG_FILAMENT_CHANGE_OPTION_PURGE, []{ pause_menu_response = PAUSE_RESPONSE_EXTRUDE_MORE; });
#if HAS_FILAMENT_SENSOR
const bool still_out = runout.filament_ran_out;
if (still_out)
EDIT_ITEM(bool, MSG_RUNOUT_SENSOR, &runout.enabled[active_extruder], runout.reset);
#else
constexpr bool still_out = false;
#endif
if (!still_out)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-2
View File
@@ -224,8 +224,6 @@
#include "ramps/pins_RAMPS_CREALITY.h" // ATmega2560 env:mega2560
#elif MB(DAGOMA_F5)
#include "ramps/pins_DAGOMA_F5.h" // ATmega2560 env:mega2560
#elif MB(DAGOMA_D6)
#include "ramps/pins_DAGOMA_D6.h" // ATmega2560 env:mega2560ext
#elif MB(FYSETC_F6_13)
#include "ramps/pins_FYSETC_F6_13.h" // ATmega2560 env:FYSETC_F6
#elif MB(FYSETC_F6_14)
-119
View File
@@ -1,119 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2024 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
#if HOTENDS > 2 || E_STEPPERS > 2
#error "Dagoma3D D6 supports up to 2 hotends / E-steppers."
#endif
#define BOARD_INFO_NAME "Dagoma3D D6"
//
// Trinamic Stallguard pins
//
#define X_DIAG_PIN 43
#define Y_DIAG_PIN 41
#define Z_DIAG_PIN 47
#define E0_DIAG_PIN 21
#define E1_DIAG_PIN 20
//
// Endstops
//
#define X_STOP_PIN 2
#define Y_STOP_PIN 3
#define Z_STOP_PIN 15
//
// Filament Runout Sensor
//
#ifndef FIL_RUNOUT_PIN
#define FIL_RUNOUT_PIN 39
#endif
#if EXTRUDERS > 1 && !defined(FIL_RUNOUT2_PIN)
#define FIL_RUNOUT2_PIN 14
#endif
// Alter timing for graphical display
#if IS_U8GLIB_ST7920
#ifndef BOARD_ST7920_DELAY_1
#define BOARD_ST7920_DELAY_1 0
#endif
#ifndef BOARD_ST7920_DELAY_2
#define BOARD_ST7920_DELAY_2 250
#endif
#ifndef BOARD_ST7920_DELAY_3
#define BOARD_ST7920_DELAY_3 250
#endif
#endif
#define KILL_PIN -1 // NC
#define LCD_CONTRAST_DEFAULT 255
//
// Sensorless homing DIAG pin is not directly connected to the MCU. Close
// the jumper next to the limit switch socket when using sensorless homing.
//
#if HAS_TMC_UART
/**
* TMC2208/TMC2209 stepper drivers
*/
#define X_SERIAL_RX_PIN 73
#define X_SERIAL_TX_PIN 73
#define Y_SERIAL_RX_PIN 73
#define Y_SERIAL_TX_PIN 73
#define Z_SERIAL_RX_PIN 73
#define Z_SERIAL_TX_PIN 73
#define E0_SERIAL_RX_PIN 73
#define E0_SERIAL_TX_PIN 73
#define E1_SERIAL_RX_PIN 12
#define E1_SERIAL_TX_PIN 12
// Default TMC slave addresses
#ifndef X_SLAVE_ADDRESS
#define X_SLAVE_ADDRESS 0
#endif
#ifndef Y_SLAVE_ADDRESS
#define Y_SLAVE_ADDRESS 1
#endif
#ifndef Z_SLAVE_ADDRESS
#define Z_SLAVE_ADDRESS 2
#endif
#ifndef E0_SLAVE_ADDRESS
#define E0_SLAVE_ADDRESS 3
#endif
#ifndef E1_SLAVE_ADDRESS
#define E1_SLAVE_ADDRESS 3
#endif
static_assert(X_SLAVE_ADDRESS == 0, "X_SLAVE_ADDRESS must be 0 for BOARD_DAGOMA_D6.");
static_assert(Y_SLAVE_ADDRESS == 1, "Y_SLAVE_ADDRESS must be 1 for BOARD_DAGOMA_D6.");
static_assert(Z_SLAVE_ADDRESS == 2, "Z_SLAVE_ADDRESS must be 2 for BOARD_DAGOMA_D6.");
static_assert(E0_SLAVE_ADDRESS == 3, "E0_SLAVE_ADDRESS must be 3 for BOARD_DAGOMA_D6.");
static_assert(E1_SLAVE_ADDRESS == 3, "E1_SLAVE_ADDRESS must be 3 for BOARD_DAGOMA_D6.");
#endif
//
// Import default RAMPS 1.4 pins
//
#include "pins_RAMPS.h"
+9 -3
View File
@@ -69,7 +69,13 @@
#endif
#if HAS_MARLINUI_U8GLIB
#define BOARD_ST7920_DELAY_1 125
#define BOARD_ST7920_DELAY_2 125
#define BOARD_ST7920_DELAY_3 125
#ifndef BOARD_ST7920_DELAY_1
#define BOARD_ST7920_DELAY_1 125
#endif
#ifndef BOARD_ST7920_DELAY_2
#define BOARD_ST7920_DELAY_2 125
#endif
#ifndef BOARD_ST7920_DELAY_3
#define BOARD_ST7920_DELAY_3 125
#endif
#endif
+10 -3
View File
@@ -182,7 +182,14 @@
#endif
#if HAS_MARLINUI_U8GLIB
#define BOARD_ST7920_DELAY_1 125
#define BOARD_ST7920_DELAY_2 125
#define BOARD_ST7920_DELAY_3 125
#ifndef BOARD_ST7920_DELAY_1
#define BOARD_ST7920_DELAY_1 125
#endif
#ifndef BOARD_ST7920_DELAY_2
#define BOARD_ST7920_DELAY_2 125
#endif
#ifndef BOARD_ST7920_DELAY_3
#define BOARD_ST7920_DELAY_3 125
#endif
#endif
+26 -24
View File
@@ -36,6 +36,14 @@
#define BOARD_INFO_NAME "Tenlog D3 Hero"
#define DEFAULT_MACHINE_NAME BOARD_INFO_NAME
//
// Servos
//
#define SERVO0_PIN 11
#define SERVO1_PIN 6
#define SERVO2_PIN -1 // Original pin 5 used for hotend fans
#define SERVO3_PIN 4
//
// Limit Switches
//
@@ -44,12 +52,14 @@
#define Y_MIN_PIN 14
//#define Y_MAX_PIN 15 // Connected to "DJ" plug on extruder heads
#define Z_MIN_PIN 18
#if ENABLED(BLTOUCH)
#define SERVO0_PIN 19
#else
#define Z_MAX_PIN 19
#endif
#define Z_MAX_PIN 19
//
// Z Probe (when not Z_MIN_PIN)
//
#ifndef Z_MIN_PROBE_PIN
#define Z_MIN_PROBE_PIN 15 // Ramps is normally 32
#endif
//
// Steppers
@@ -89,17 +99,16 @@
//#define Z2_CS_PIN 40
//#endif
#define E0_STEP_PIN 57
#define E0_DIR_PIN 58
#define E0_ENABLE_PIN 59
#define E0_STEP_PIN 26
#define E0_DIR_PIN 28
#define E0_ENABLE_PIN 24
//#ifndef E0_CS_PIN
//define E0_CS_PIN 42
//#endif
#define E1_STEP_PIN 26
#define E1_DIR_PIN 28
#define E1_ENABLE_PIN 24
#define E1_STEP_PIN 57
#define E1_DIR_PIN 58
#define E1_ENABLE_PIN 59
//#ifndef E1_CS_PIN
//define E1_CS_PIN 44
//#endif
@@ -111,8 +120,8 @@
//
// Temperature Sensors
//
#define TEMP_0_PIN 15 // Analog Input
#define TEMP_1_PIN 13 // Analog Input
#define TEMP_0_PIN 13 // Analog Input
#define TEMP_1_PIN 15 // Analog Input
#define TEMP_BED_PIN 14 // Analog Input
// SPI for MAX Thermocouple
@@ -125,8 +134,8 @@
//
// Heaters / Fans
//
#define HEATER_0_PIN 11
#define HEATER_1_PIN 10
#define HEATER_0_PIN 10
#define HEATER_1_PIN 11
#define HEATER_BED_PIN 8
#define FAN0_PIN 9
@@ -134,16 +143,9 @@
// XXX Runout support unknown?
//#define NUM_RUNOUT_SENSORS 0
#define FIL_RUNOUT_PIN 15
//#define FIL_RUNOUT_PIN 22
//#define FIL_RUNOUT2_PIN 21
//
// PSU and Powerloss Recovery
//
#ifdef PSU_CONTROL
#define PS_ON_PIN 40
#endif
//
// Misc. Functions
//
@@ -105,11 +105,6 @@
#define BEEPER_PIN -1
#endif
#if ENABLED(MINIPANEL)
#undef DOGLCD_CS
#define DOGLCD_CS 28
#endif
/**
PIN: 0 Port: B0 E0_DIR_PIN protected
PIN: 1 Port: B1 E0_STEP_PIN protected
+2 -10
View File
@@ -64,14 +64,8 @@
//
// Probe
//
#if ENABLED(NOZZLE_AS_PROBE)
#ifndef PROBE_TARE_PIN
#define PROBE_TARE_PIN PA5
#endif
#else
#ifndef SERVO0_PIN
#define SERVO0_PIN PA5
#endif
#ifndef PROBE_TARE_PIN
#define PROBE_TARE_PIN PA5
#endif
//
@@ -118,5 +112,3 @@
// Misc. Functions
//
#define CASE_LIGHT_PIN PA6
#define LED_PIN PA6
-5
View File
@@ -36,10 +36,6 @@
#include "../lcd/e3v2/creality/dwin.h"
#endif
#if ENABLED(EXTENSIBLE_UI)
#include "../lcd/extui/ui_api.h"
#endif
#include "../module/planner.h" // for synchronize
#include "../module/printcounter.h"
#include "../gcode/queue.h"
@@ -495,7 +491,6 @@ void CardReader::mount() {
else {
flag.mounted = true;
SERIAL_ECHO_MSG(STR_SD_CARD_OK);
TERN_(EXTENSIBLE_UI, ExtUI::isMediaInserted()); // ExtUI response
}
if (flag.mounted)
+35
View File
@@ -37,6 +37,41 @@
// Startup tests are run at the end of setup()
void runStartupTests() {
// Call post-setup tests here to validate behaviors.
// String with cutoff at 20 chars:
// "F-string, 1234.50, 2"
SString<20> str20;
str20 = F("F-string, ");
str20.append(1234.5f).append(',').append(' ')
.append(2345.67).append(',').append(' ')
.echoln();
// Truncate to "F-string"
str20.trunc(8).echoln();
// 100 dashes, but chopped down to DEFAULT_MSTRING_SIZE (20)
TSS(repchr_t('-', 100)).echoln();
// Hello World!-123456------ <spaces!33
// ^ eol! ... 1234.50*2345.602 = 2895645.67
SString<100> str(F("Hello"));
str.append(F(" World!"));
str += '-';
str += uint8_t(123);
str += F("456");
str += repchr_t('-', 6);
str += Spaces(3);
str += "< spaces!";
str += int8_t(33);
str.eol();
str += "^ eol!";
str.append("...", 1234.5f, '*', p_float_t(2345.602, 3), F(" = "), 1234.5 * 2345.602).echoln();
// Print it again with SERIAL_ECHOLN
auto print_char_ptr = [](char * const str) { SERIAL_ECHOLN(str); };
print_char_ptr(str);
}
// Periodic tests are run from within loop()
-5
View File
@@ -1,5 +0,0 @@
These test files are executed by the unit-tests built from the `<root>/test` folder.
These are placed outside of the main PlatformIO test folder so we can collect all test files and compile them into multiple PlatformIO test binaries. This enables tests to be executed against a variety of Marlin configurations.
To execute these tests, refer to the top-level Makefile.
File diff suppressed because it is too large Load Diff
-58
View File
@@ -1,58 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2024 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 "../test/unit_tests.h"
#include <src/gcode/gcode.h>
#include <src/gcode/parser.h>
MARLIN_TEST(gcode, process_parsed_command) {
GcodeSuite suite;
parser.command_letter = 'G';
parser.codenum = 0;
suite.process_parsed_command(false);
}
MARLIN_TEST(gcode, parse_g1_xz) {
char current_command[] = "G0 X10 Z30";
parser.command_letter = -128;
parser.codenum = -1;
parser.parse(current_command);
TEST_ASSERT_EQUAL('G', parser.command_letter);
TEST_ASSERT_EQUAL(0, parser.codenum);
TEST_ASSERT_TRUE(parser.seen('X'));
TEST_ASSERT_FALSE(parser.seen('Y'));
TEST_ASSERT_TRUE(parser.seen('Z'));
TEST_ASSERT_FALSE(parser.seen('E'));
}
MARLIN_TEST(gcode, parse_g1_nxz) {
char current_command[] = "N123 G0 X10 Z30";
parser.command_letter = -128;
parser.codenum = -1;
parser.parse(current_command);
TEST_ASSERT_EQUAL('G', parser.command_letter);
TEST_ASSERT_EQUAL(0, parser.codenum);
TEST_ASSERT_TRUE(parser.seen('X'));
TEST_ASSERT_FALSE(parser.seen('Y'));
TEST_ASSERT_TRUE(parser.seen('Z'));
TEST_ASSERT_FALSE(parser.seen('E'));
}
@@ -1,36 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2024 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 "../test/unit_tests.h"
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
#include <src/feature/runout.h>
MARLIN_TEST(runout, poll_runout_states) {
FilamentSensorBase sensor;
// Expected default value is one bit set for each extruder
uint8_t expected = static_cast<uint8_t>(~(~0u << NUM_RUNOUT_SENSORS));
TEST_ASSERT_EQUAL(expected, sensor.poll_runout_states());
}
#endif
-160
View File
@@ -1,160 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2024 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 "../test/unit_tests.h"
#include "src/core/types.h"
MARLIN_TEST(types, XYval_const_as_bools) {
const XYval<int> xy_const_true = {1, 2};
TEST_ASSERT_TRUE(xy_const_true);
const XYval<int> xy_const_false = {0, 0};
TEST_ASSERT_FALSE(xy_const_false);
}
MARLIN_TEST(types, XYval_non_const_as_bools) {
XYval<int> xy_true = {1, 2};
TEST_ASSERT_TRUE(xy_true);
XYval<int> xy_false = {0, 0};
TEST_ASSERT_FALSE(xy_false);
}
MARLIN_TEST(types, XYZval_const_as_bools) {
const XYZval<int> xyz_const_true = {1, 2, 3};
TEST_ASSERT_TRUE(xyz_const_true);
const XYZval<int> xyz_const_false = {0, 0, 0};
TEST_ASSERT_FALSE(xyz_const_false);
}
MARLIN_TEST(types, XYZval_non_const_as_bools) {
XYZval<int> xyz_true = {1, 2, 3};
TEST_ASSERT_TRUE(xyz_true);
XYZval<int> xyz_false = {0, 0, 0};
TEST_ASSERT_FALSE(xyz_false);
}
MARLIN_TEST(types, XYZEval_const_as_bools) {
const XYZEval<int> xyze_const_true = {1, 2, 3, 4};
TEST_ASSERT_TRUE(xyze_const_true);
const XYZEval<int> xyze_const_false = {0, 0, 0, 0};
TEST_ASSERT_FALSE(xyze_const_false);
}
MARLIN_TEST(types, XYZEval_non_const_as_bools) {
XYZEval<int> xyze_true = {1, 2, 3, 4};
TEST_ASSERT_TRUE(xyze_true);
XYZEval<int> xyze_false = {0, 0, 0, 0};
TEST_ASSERT_FALSE(xyze_false);
}
MARLIN_TEST(types, Flags_const_as_bools) {
const Flags<32> flags_const_false = {0};
TEST_ASSERT_FALSE(flags_const_false);
const Flags<32> flags_const_true = {1};
TEST_ASSERT_TRUE(flags_const_true);
}
MARLIN_TEST(types, Flags_non_const_as_bools) {
Flags<32> flags_false = {0};
TEST_ASSERT_FALSE(flags_false);
Flags<32> flags_true = {1};
TEST_ASSERT_TRUE(flags_true);
}
MARLIN_TEST(types, AxisFlags_const_as_bools) {
const AxisFlags axis_flags_const_false = {0};
TEST_ASSERT_FALSE(axis_flags_const_false);
const AxisFlags axis_flags_const_true = {1};
TEST_ASSERT_TRUE(axis_flags_const_true);
}
MARLIN_TEST(types, AxisFlags_non_const_as_bools) {
AxisFlags axis_flags_false = {0};
TEST_ASSERT_FALSE(axis_flags_false);
AxisFlags axis_flags_true = {1};
TEST_ASSERT_TRUE(axis_flags_true);
}
MARLIN_TEST(types, AxisBits_const_as_bools) {
const AxisBits axis_bits_const_false = {0};
TEST_ASSERT_FALSE(axis_bits_const_false);
const AxisBits axis_bits_const_true = {1};
TEST_ASSERT_TRUE(axis_bits_const_true);
}
MARLIN_TEST(types, AxisBits_non_const_as_bools) {
AxisBits axis_bits_false = {0};
TEST_ASSERT_FALSE(axis_bits_false);
AxisBits axis_bits_true = {1};
TEST_ASSERT_TRUE(axis_bits_true);
}
MARLIN_TEST(types, MString1) {
// String with cutoff at 20 chars:
// "F-string, 1234.50, 2"
MString<20> str20;
str20 = F("F-string, ");
str20.append(1234.5f).append(',').append(' ')
.append(2345.67).append(',').append(' ');
TEST_ASSERT_TRUE(strcmp_P(str20, PSTR("F-string, 1234.50, 2")) == 0);
// Truncate to "F-string"
str20.trunc(8);
TEST_ASSERT_FALSE(strcmp_P(&str20, PSTR("F-string")) != 0);
}
MARLIN_TEST(types, MString2) {
// 100 dashes, but chopped down to DEFAULT_MSTRING_SIZE (20)
TEST_ASSERT_TRUE(TSS(repchr_t('-', 100)).length() == 20);
}
MARLIN_TEST(types, SString) {
// Hello World!-123456------ < spaces!33
// ^ eol! ... 1234.50*2345.602 = 2895645.67
SString<100> str(F("Hello"));
str.append(F(" World!"));
str += '-';
str += uint8_t(123);
str += F("456");
str += repchr_t('-', 6);
str += Spaces(3);
str += "< spaces!";
str += int8_t(33);
str.eol();
str += "^ eol!";
str.append(" ... ", 1234.5f, '*', p_float_t(2345.602, 3), F(" = "), 1234.5 * 2345.602);
TEST_ASSERT_TRUE(strcmp_P(str, PSTR("Hello World!-123456------ < spaces!33\n^ eol! ... 1234.50*2345.602 = 2895645.67")) == 0);
}
+142 -227
View File
@@ -1,238 +1,153 @@
## Creality Touch/TFT Screen supported firmware
This branch adds support for the Creality touchscreen machines and was split off from the standard Creality branches due to specific custom changes not found upstream. This includes extensions to the EXTui framework among other smaller tweaks that we have been working towards getting submitted upstream. Machines supported here are :
- [CR10S Pro / V2](https://www.tinymachines3d.com/products/cr-10s-pro-v2-3d-printer?rfsn=3419592.cc302fe)
- [CR10 Max](https://www.tinymachines3d.com/products/creality-cr-10-max-3d-printer?rfsn=3419592.cc302fe)
- [Ender 5 Plus](https://www.tinymachines3d.com/products/ender-5-plus-silent-board-custom-dual-z-3d-printer?rfsn=3419592.cc302fe)
- [Ender 6](https://amzn.to/3JRyOhi)
- [CR-X / Pro](https://www.tinymachines3d.com/products/creality-cr-x-pro-3d-printer-with-dual-extruder-and-bl-touch?rfsn=3419592.cc302fe)
- [CR10 V2 ](https://www.tinymachines3d.com/products/creality-cr-10-v2-3d-printer?rfsn=3419592.cc302fe)
- [CR10 V3 ](https://www.tinymachines3d.com/products/creality-cr-10-v3-plus-3d-printer-with-genuine-e3d-direct-drive-extruder-and-bl-touch?rfsn=3419592.cc302fe)
- [Ender 3 / Pro 4.2.2 and 4.2.7](https://amzn.to/3BRHlxY)
- [Ender 3 V2](https://www.tinymachines3d.com/products/ender-3-v2?rfsn=3419592.cc302fe)
- [Ender 3 Max](https://www.tinymachines3d.com/products/ender-3-max-3d-printer?rfsn=3419592.cc302fe)
- [Ender 5 / Pro 4.2.2 and 4.2.7](https://amzn.to/3gMb2Yu)
- [CR10S5 500mm](https://www.tinymachines3d.com/products/creality-cr-10-s5-3d-printer?rfsn=3419592.cc302fe)
- [CR6 SE](https://www.tinymachines3d.com/products/creality-cr-6-se-3d-printer?rfsn=3419592.cc302fe)
- [CR6 Max](https://www.tinymachines3d.com/products/creality-cr-6-max-3d-printer?rfsn=3419592.cc302fe)
- [CR10 Smart](https://www.tinymachines3d.com/products/creality-cr-10-smart-3d-printer?rfsn=3419592.cc302fe)
- [Ender 7](https://www.tinymachines3d.com/products/ender-7-3d-printer?rfsn=3419592.cc302fe)
- [CR30](https://www.tinymachines3d.com/products/cr-30-infinite-z-belt-3d-printer?rfsn=3419592.cc302fe)
- [Sermoon D1](https://amzn.to/3LXfZeD)
- [CR5 / Pro HT](https://amzn.to/3gWvpBt)
- [Ender 3 S1](https://www.tinymachines3d.com/products/ender-3-s1-3d-printer?rfsn=3419592.cc302fe)
- [Ender 2 Pro](https://www.tinymachines3d.com/products/ender-2-pro-3d-printer?rfsn=3419592.cc302fe)
- CR10S, CR10S4, CR20 and Pro, CR10, CR10Mini, CR2020, Ender 4, Ender 2 - Legacy support
- These configurations exist however due to age and product availability are no longer actively tested
## Coming Soon
- [CR10 Smart Pro](https://www.tinymachines3d.com/products/cr-10-smart-pro-3d-printer?rfsn=3419592.cc302fe)
- [CR200B]()
## Resin machines below from Tiny Machines are listed simply as an additional way to help support the project. If youre considering buying one, please do so through the following links :
- [Halot One CL-60](https://www.tinymachines3d.com/products/halot-one-cl-60-resin-3d-printer?rfsn=3419592.cc302fe)
- [LD-002R](https://www.tinymachines3d.com/products/ld-002r-resin-printer?rfsn=3419592.cc302fe)
- [LD-002H](https://www.tinymachines3d.com/products/ld-002h-resin-3d-printer?rfsn=3419592.cc302fe)
- [LD-006](https://www.tinymachines3d.com/products/ld-006-resin-3d-printer?rfsn=3419592.cc302fe)
- [UW-02 Washer](https://www.tinymachines3d.com/products/uw-02-washing-curing-machine?rfsn=3419592.cc302fe)
Ender 3V2 has a dedicated file set. CR10 Smart has a dedicated high resolution screen set. Portrait displays use the CR6/E3 Touch variant and landscape use the combined set.
Screen files are archived with [7-Zip](https://www.7-zip.org/) simply because it came out 1/5 the file size of a zip file. That added up fast!
There is a limitation with Windows systems and path depth so the file names need to be shorter than we would prefer. If you get an error compiling due to the path limit, move the folder to the root of your hard drive. Here is a legend to help decode the files:
- BLT = BLTouch
- BIL = Bilinear Leveling
- UBL - Unified Bed Leveling
- DZ = Dual Z Steppers
- Fil = FilamentRunout
- Slnt = Creality Silent Board
- H = E3D Hemera Extruder
- MC = Mosquito Creality mount
- ME = Mosquito E3D mount
- Melzi Host option disables local SD card to allow more features and buffer for Octoprint control
- NF = Noise filtering for machines with cable extensions - reduces homing accuracy!
- LR = Stock runout replaced with Lerdge
- ZM = BLTouch connected to ZMin port instead of Probe pin 5 connector harness
## Support
This firmware is provided to the public as-is with no warranty or guarantee. It's based on a large open source project and there is no entitlement to support. That said, Tiny Machines 3D customers may obtain
support through their normal support queue. I will provide support to Patreons as I am able. If you require more immediate support and are not a Tiny Machines 3D customer, you may contact them at
support@tinymachines3d.com about purchasing support hours. Aside from this, we are active on many Facebook groups as well as several discord channels and typically help anyone we can when we come across them.
We have now created a dedicated Discord server to handle support and archive relevant guides and instructions. Patreon supporters will get priority assistance.
## We will NOT handle any support requests for any built compiled from upstream code. The display library from here was taken and submitted upstream without consultation or properly tagging authorship of changes. It was kept off the upstream repo as it was explicitly designed as a drop in library before the Extensible UI API methodology was butchered by hybrid applications with direct includes being repeatedly duplicated. We will not now or ever spend the time to chase bugs caused by changes to the API data types made without concern for backwards compatability.
Extensible UI was designed to allow UI code to live standalone long term. If the API was managed and either versioned or functions overloaded, not changed, UI's no longer being actively maintained would not require maintenance by the Marlin team. The intention was any UI set would drop into the Lib folder and just work. This UI has been maintained under that mindset despite the upstream implementations being full of macros requiring direct pointer access to processed variables, making them fundamentally incompatible with the API, however still relying on its event trigger mechanism.
As another reason this was not placed upstream was to eliminate the nead to develop around merge conflicts following previous code theft issues which have cuased most development to now proceed in the dark, the merge upstream was caught by exactly that, merge issues while adding IDEX functionality.
Due to the blatent disregard to intentions and correct attribution, all support Marlin links have been removed from this repo and open PRs closed, and as long as the situation remains, no further work will be submitted upstream.
Shout out to Tom Brazier, as nearly all notable improvements to the Marlin core code since the last release have come from him.
Insanity Automation Discord - https://discord.gg/TKmJ85PyG4
## Primary Notes for DW7.4.8
- Added Linear Adv and Input Shaping Screens
- Signifigant improvement in response times following changes to new generation machines
-- The DWIN OS 3.5 had an option to enable NOACK with an addon bin file. 4.0 has a specific throttled response OS revision. 4.5 needed a totally different UI image flashed. No way it could all live together without completely confusing users so we set about figuring out how to keep universal support and found a balance in data send cycles that the 2560 buffers could still handle the replies without overunning.
- Added support for changing runout sensor type on the LCD
- Added toggle to change babystepping increment on the LCD
- Thanks to EvilGremlin for some of the icon and display graphics work
## Primary Notes for DW7.4.7
- Added IDEX screens
- Fan adjustment now numeric instead of simple on/off
- Tap Z offset on adjustment screen to type numeric value
- Sync to 2.1.2 with LA now on for all builds, Silent specific builds eliminated
- TODO note prior to building release batches - Primary outstanding bug is upstream issue causing M600 to fail to resume, verified on both DWIN and Standard full graphics displays.
## Primary Notes for DW7.4.6
- Added Support for the Ender 2 Pro
- Added support for the Ender 3 S1 thanks to F1rst Layer providing a machine!
- Added support for the new DACAI screens being used on current production E3V2 and S1 machines
- Added support for runtime configurable runout sensors matching RRF M591 including type and polarity
- Moved E3V2/S1 machines to Marlin Display
- - Due to the ongoing fued between developers and GPL violations involved with both the Pro/Enahnced UI and the Jyers UI, we have decided to support neither and stay away from the conflict as much as possible. The Marlin UI has more configuration functionality and the menus are more adaptive to the configuration of the machine. This is based off of the default Marlin menu system and will be the most stable long term going forward as well. The cosmetics and graphical icons may not be as nice as with the other UI's however we belive the added functionality more than makes up for it.
- Removed non-touchscreen 8 bit UBL builds due to RAM constraints
- Removed Pre-Built Melzi / Sanguino files. These are legacy and no longer actively supported. Its recommended to purchase replacement 32bit motherboards for any machine still using it from https://amzn.to/3KdqyI8
## Primary Notes for DW7.4.5
- Added support for CR10 Smart - Thanks to Tinymachines for providing the machine
- Revised file size issues causing corrupted screens on DWINOS3/4 displays (Sermoon, E6/7 etc)
- Added support for enabling / disabling filament runout and power loss recovery on the touchscreen
- Added LED control for equiped machines
- Resolved issue redirecting some users to chinese language displays instead of manual move screens
- Update to upstream current as of 2022-02-04
- CR6 / E3 Portrait Touchscreen files have an added NextGen dwin set. This supports the new DWIN OS 4 screens that began shipping in december. There are a few cosmetic issues left to resolve, but we decided to add them now anyway so that users who haver that hardware and will require it are not stuck.
## Primary Notes for DW7.4.4
- Added Feedrate / Accel / Jerk Screens
- Touchscreen DGUS tools bumped to 8.2
- - All Portrait displays operate with the same build
- - Older screens (10S Pro) audio file selection is a bit off, havnt found a way to properly enforce wav file used yet
- Ender 7 support
- Sermoon D1 Support
- - Some users have reported Z clicking that the scripts run in the Leveling screen resolves, so if you hear clicking from the Z stepper when printing, run measuring from the leveling screen after powerup before printing.
- E3V2 Screens Icon issue fixed thanks to note from Jyers on icon file size limit
## Primary Notes for DW7.4.3
- PID Messaging Fixed
- M600 / Advanced pause messaging improved
- Volume / Brightness numeric entry fixed
- Bump base to 2.0.9.2
-- Includes improved UI for the E3V2 with expanded menus submitted by Jyers
- Add Gcode configuration to disable BLTouch High Speed Mode to allow runtime config to support CRTouch
-- This one is pending upstream https://github.com/MarlinFirmware/Marlin/pull/22916
- Untested preliminary support for the Sermoon D1
-- Preliminary reports say it works aside from the LCD
-- I do not own one of these, however a local community member has offered to bring his down when im done with the Ender 7
- CR30 Support Added
## Primary Notes for DW7.4
- Added Screen Calibration Options
-- Standby Brightness
-- Volume
-- Both now saved in EEPROM
-- Screen configuration code based loosely on the work from the CR6 community modified for this screen model
-- Automatic Screen rotation for the Ender 6 (Default is upside-down)
- Manual Mesh Controls for no Probe machines
-- CRX and Ender 6 with no Probe can now use all mesh controls
-- All machines now use the same screen files except for Ender 3 V2 Rotary Dial machines and CR6
- Home button added to 5 point adjustment screen
- Tap mesh values to manually type in a new value - allows for manual adjustment of mesh values
- Additional functions, messaging on pause / filament runout
-- No will no longer cancel print
-- Depending on state, if only option is continue (eg Reheat, Load filament) Any response continues
-- On final Confirm Continue, No will purge more filament and Yes will resume
- Most places temperatures are shown, can now tap them to type in a value to set the temerature
- Updated to Marlin 2.0.9 Base
- CR6 Branches merged in
-- Support for this machine is primarily based on the fork by the [CR6 Community](https://github.com/CR6Community)
## Primary notes for DW7.3
- File browser rewritten to support paging as well as subdirectories
-- New file browser has a limit of a 66 character directory depth. This can be expanded at the cost of more RAM if users find this more limiting.
-- Due to the above, the current recommendation is to try and limit folder depth to 3 subdirectories and keep names short if possible.
- Base bumped to Marlin Bugfix as of 20210418
# Changes for DW7.3.1
- Added SD file refresh button for users with damaged SD Detect Pins
- Modified print finish button action to raise z by 5mm and disable steppers rather than rehome XY
- Solve rounding issue with babystepping below step precision by forcing always round up caused by recent upstream change
- Modified babystepping resolution for fine adjustment to .02mm from .01mm
- Force file pages to reset paging value on entry to screen to prevent incorrect scrolling
- Additional string length buffer safeties
The default build button is now a batch Build All! If you want to build a custom stock 2560 environment, use the env:megaatmega2560 environment.
For SKR 1.3/1.4 boards use the LPC1768/9 environments as usual. For SKR Mini or Creality STM32F1 boards use the standard STM32 environments per vendor.
## About Our Branches
The firmware branches maintained here are made possible by the support of [Tiny Machines 3D](https://www.tinymachines3d.com/?rfsn=3419592.cc302fe) as well as our customer base through our 3D printing Services.
Maintaining and developing these branches takes a significant investment, made up of time and machines. To support continued development, please consider your next 3D Printer related purchase from Tiny Machines 3D
and thank them for supporting open source development. Or, consider us for printing services outside of your machines capabilities. Print service requests can be sent to d.menzel@insanityautomation.com and we will
respond typically within 1 working day. If you do not need anything printed or a 3D Printer but still want to contribute, you can support us through [Patreon](https://www.patreon.com/InsanityAutomation).
## Setup
All configuration options intended to be adjusted by end users have been placed in the top section of Configuration.h and have been documented there. There is typically a break line to segregate the standard
configuration below. Anything aside from the upper options is intended for advanced users only.
Please keep in mind when flashing the Creality 32 bit boards with the binary files (.bin) that occasionally they will not accept particular filenames. This is most common with reflashing after an aborted flash. The machine stores the filename it was last flashed with, so renaming the file to something such as firmware.bin or firmware1.bin (anything different than what it is now) will typically resolve any issue with file names.
## Known Issues
- While auto leveling (measuring) is in progress pressing other buttons on the screen can abort portions of the script depending where it is
- - The process includes heating the bed before probing, probing then heating the nozzle before moving to Z0.
- Thanks to Jarrett Wendt for finding that if you are experiencing distorted sounds, and use a Mac, the default Archive Utility on MacOS has been found to be corrupting the files. If you're on a Mac, try unzipping with The Unarchiver or Keka instead.
## Future Goals
For this branch, we still have some active goals open that we plan to continue working on provided there is continued interest in the project.
- CR10 Smart Power controls and network reset pin output to web interface device
- Screens for IS and LA adjustment
## Creality Firmware Branches
- Most Creality machines [CrealityDwin_2.0](https://github.com/InsanityAutomation/Marlin/tree/CrealityDwin_2.0)
- CR6 modified from [CR-6 Community](https://github.com/CR6Community) - [Creality CR6](https://github.com/InsanityAutomation/Marlin/tree/CR-6Devel)
## Formbot / Vivedino Firmware Branches
- Raptor 1/2 Firmware [Raptor_2.0.X](https://github.com/InsanityAutomation/Marlin/tree/Raptor_2.0.X)
- Trex 2+/3 Firmware [TM_Trex2+_2.0.x](https://github.com/InsanityAutomation/Marlin/tree/TM_Trex2+_2.0.x)
## Mamorubot / HieHa Firmware Branches
- SX4/SX2 Firmware [TM_SX4_2.0](https://github.com/InsanityAutomation/Marlin/tree/TM_SX4_2.0)
## Other Firmware
- Raise 3D N2+ (Dual) 2.0 [Raise3D-N2+-Dual](https://github.com/InsanityAutomation/Marlin/tree/Raise3D-N2+-Dual)
- Evnovo Artillery Sidewinder X1 2.0 [Evnovo X1](https://github.com/InsanityAutomation/Marlin/tree/ArtilleryX1_2.0_Devel)
- [Anet E16](https://github.com/InsanityAutomation/Marlin/tree/AnetE16V2.0.5.2)
- Lulzbot with Universal Tools options [Lulzbot](https://github.com/InsanityAutomation/Marlin/tree/LulzbotTestBase)
- Funmat HT with Graphical Display [Funmat HT](https://github.com/InsanityAutomation/Marlin/tree/FunmatHT)
- [Modix Big60](https://github.com/InsanityAutomation/Marlin/tree/ModixBig60)
- Tronxy Chithu Machines [Tronxy](https://github.com/InsanityAutomation/Marlin/tree/TronxyX5SA)
[Marlin Commit History](https://github.com/MarlinFirmware/Marlin/pulls?q=is%3Apr+is%3Aclosed+author%3AInsanityAutomation)
## Marlin
This is just one of many forks of Marlin. We don't try to bury that behind fancy marketting or anything else.
<p align="center"><img src="buildroot/share/pixmaps/logo/marlin-outrun-nf-500.png" height="250" alt="MarlinFirmware's logo" /></p>
<h1 align="center">Marlin 3D Printer Firmware</h1>
<p align="center">
<a href="/LICENSE"><img alt="GPL-V3.0 License" src="https://img.shields.io/github/license/marlinfirmware/marlin.svg"></a>
<a href="https://github.com/MarlinFirmware/Marlin/graphs/contributors"><img alt="Contributors" src="https://img.shields.io/github/contributors/marlinfirmware/marlin.svg"></a>
<a href="https://github.com/MarlinFirmware/Marlin/releases"><img alt="Last Release Date" src="https://img.shields.io/github/release-date/MarlinFirmware/Marlin"></a>
<a href="https://github.com/MarlinFirmware/Marlin/actions"><img alt="CI Status" src="https://github.com/MarlinFirmware/Marlin/actions/workflows/test-builds.yml/badge.svg"></a>
<a href="https://github.com/sponsors/thinkyhead"><img alt="GitHub Sponsors" src="https://img.shields.io/github/sponsors/thinkyhead?color=db61a2"></a>
<br />
<a href="https://fosstodon.org/@marlinfirmware"><img alt="Follow MarlinFirmware on Mastodon" src="https://img.shields.io/mastodon/follow/109450200866020466?domain=https%3A%2F%2Ffosstodon.org&logoColor=%2300B&style=social"></a>
</p>
Additional documentation can be found at the [Marlin Home Page](https://marlinfw.org/).
Please test this firmware and let us know if it misbehaves in any way. Volunteers are standing by!
## Marlin 2.1 Bugfix Branch
__Not for production use. Use with caution!__
Marlin 2.1 takes this popular RepRap firmware to the next level by adding support for much faster 32-bit and ARM-based boards while improving support for 8-bit AVR boards. Read about Marlin's decision to use a "Hardware Abstraction Layer" below.
This branch is for patches to the latest 2.1.x release version. Periodically this branch will form the basis for the next minor 2.1.x release.
Download earlier versions of Marlin on the [Releases page](https://github.com/MarlinFirmware/Marlin/releases).
## Example Configurations
Before you can build Marlin for your machine you'll need a configuration for your specific hardware. Upon request, your vendor will be happy to provide you with the complete source code and configurations for your machine, but you'll need to get updated configuration files if you want to install a newer version of Marlin. Fortunately, Marlin users have contributed dozens of tested configurations to get you started. Visit the [MarlinFirmware/Configurations](https://github.com/MarlinFirmware/Configurations) repository to find the right configuration for your hardware.
## Building Marlin 2.1
To build and upload Marlin you will use one of these tools:
- The free [Visual Studio Code](https://code.visualstudio.com/download) using the [Auto Build Marlin](https://marlinfw.org/docs/basics/auto_build_marlin.html) extension.
- The free [Arduino IDE](https://www.arduino.cc/en/main/software) : See [Building Marlin with Arduino](https://marlinfw.org/docs/basics/install_arduino.html)
- You can also use VSCode with devcontainer : See [Installing Marlin (VSCode devcontainer)](http://marlinfw.org/docs/basics/install_devcontainer_vscode.html).
Marlin is optimized to build with the **PlatformIO IDE** extension for **Visual Studio Code**. You can still build Marlin with **Arduino IDE**, and we hope to improve the Arduino build experience, but at this time PlatformIO is the better choice.
## Hardware Abstraction Layer (HAL)
Marlin includes an abstraction layer to provide a common API for all the platforms it targets. This allows Marlin code to address the details of motion and user interface tasks at the lowest and highest levels with no system overhead, tying all events directly to the hardware clock.
Every new HAL opens up a world of hardware. At this time we need HALs for RP2040 and the Duet3D family of boards. A HAL that wraps an RTOS is an interesting concept that could be explored. Did you know that Marlin includes a Simulator that can run on Windows, macOS, and Linux? Join the Discord to help move these sub-projects forward!
## 8-Bit AVR Boards
A core tenet of this project is to keep supporting 8-bit AVR boards while also maintaining a single codebase that applies equally to all machines. We want casual hobbyists to benefit from the community's innovations as much as possible just as much as those with fancier machines. Plus, those old AVR-based machines are often the best for your testing and feedback!
### Supported Platforms
Platform|MCU|Example Boards
--------|---|-------
[Arduino AVR](https://www.arduino.cc/)|ATmega|RAMPS, Melzi, RAMBo
[Teensy++ 2.0](https://www.microchip.com/en-us/product/AT90USB1286)|AT90USB1286|Printrboard
[Arduino Due](https://www.arduino.cc/en/Guide/ArduinoDue)|SAM3X8E|RAMPS-FD, RADDS, RAMPS4DUE
[ESP32](https://github.com/espressif/arduino-esp32)|ESP32|FYSETC E4, E4d@BOX, MRR
[LPC1768](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpc1700-cortex-m3/512-kb-flash-64-kb-sram-ethernet-usb-lqfp100-package:LPC1768FBD100)|ARM® Cortex-M3|MKS SBASE, Re-ARM, Selena Compact
[LPC1769](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpc1700-cortex-m3/512-kb-flash-64-kb-sram-ethernet-usb-lqfp100-package:LPC1769FBD100)|ARM® Cortex-M3|Smoothieboard, Azteeg X5 mini, TH3D EZBoard
[STM32F103](https://www.st.com/en/microcontrollers-microprocessors/stm32f103.html)|ARM® Cortex-M3|Malyan M200, GTM32 Pro, MKS Robin, BTT SKR Mini
[STM32F401](https://www.st.com/en/microcontrollers-microprocessors/stm32f401.html)|ARM® Cortex-M4|ARMED, Rumba32, SKR Pro, Lerdge, FYSETC S6, Artillery Ruby
[STM32F7x6](https://www.st.com/en/microcontrollers-microprocessors/stm32f7x6.html)|ARM® Cortex-M7|The Borg, RemRam V1
[STM32G0B1RET6](https://www.st.com/en/microcontrollers-microprocessors/stm32g0x1.html)|ARM® Cortex-M0+|BigTreeTech SKR mini E3 V3.0
[STM32H743xIT6](https://www.st.com/en/microcontrollers-microprocessors/stm32h743-753.html)|ARM® Cortex-M7|BigTreeTech SKR V3.0, SKR EZ V3.0, SKR SE BX V2.0/V3.0
[SAMD51P20A](https://www.adafruit.com/product/4064)|ARM® Cortex-M4|Adafruit Grand Central M4
[Teensy 3.5](https://www.pjrc.com/store/teensy35.html)|ARM® Cortex-M4|
[Teensy 3.6](https://www.pjrc.com/store/teensy36.html)|ARM® Cortex-M4|
[Teensy 4.0](https://www.pjrc.com/store/teensy40.html)|ARM® Cortex-M7|
[Teensy 4.1](https://www.pjrc.com/store/teensy41.html)|ARM® Cortex-M7|
Linux Native|x86/ARM/etc.|Raspberry Pi
## Submitting Patches
Proposed patches should be submitted as a Pull Request against the ([bugfix-2.1.x](https://github.com/MarlinFirmware/Marlin/tree/bugfix-2.1.x)) branch.
- This branch is for fixing bugs and integrating any new features for the duration of the Marlin 2.1.x life-cycle.
- Follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) to gain points with the maintainers.
- Please submit Feature Requests and Bug Reports to the [Issue Queue](https://github.com/MarlinFirmware/Marlin/issues/new/choose). Support resources are also listed there.
- Whenever you add new features, be sure to add tests to `buildroot/tests` and then run your tests locally, if possible.
- It's optional: Running all the tests on Windows might take a long time, and they will run anyway on GitHub.
- If you're running the tests on Linux (or on WSL with the code on a Linux volume) the speed is much faster.
- You can use `make tests-all-local` or `make tests-single-local TEST_TARGET=...`.
- If you prefer Docker you can use `make tests-all-local-docker` or `make tests-all-local-docker TEST_TARGET=...`.
## Marlin Support
The Issue Queue is reserved for Bug Reports and Feature Requests. To get help with configuration and troubleshooting, please use the following resources:
- [Marlin Documentation](https://marlinfw.org) - Official Marlin documentation
- [Marlin Discord](https://discord.gg/n5NJ59y) - Discuss issues with Marlin users and developers
- Facebook Group ["Marlin Firmware"](https://www.facebook.com/groups/1049718498464482/)
- RepRap.org [Marlin Forum](https://forums.reprap.org/list.php?415)
- Facebook Group ["Marlin Firmware for 3D Printers"](https://www.facebook.com/groups/3Dtechtalk/)
- [Marlin Configuration](https://www.youtube.com/results?search_query=marlin+configuration) on YouTube
## Contributors
Marlin is constantly improving thanks to a huge number of contributors from all over the world bringing their specialties and talents. Huge thanks are due to [all the contributors](https://github.com/MarlinFirmware/Marlin/graphs/contributors) who regularly patch up bugs, help direct traffic, and basically keep Marlin from falling apart. Marlin's continued existence would not be possible without them.
## Administration
Regular users can open and close their own issues, but only the administrators can do project-related things like add labels, merge changes, set milestones, and kick trolls. The current Marlin admin team consists of:
<table align="center">
<tr><td>Project Maintainer</td></tr>
<tr><td>
🇺🇸 **Scott Lahteine**
[@thinkyhead](https://github.com/thinkyhead)
[<kbd>Donate 💸 </kbd>](https://www.thinkyhead.com/donate-to-marlin)
</td><td>
🇺🇸 **Roxanne Neufeld**
[@Roxy-3D](https://github.com/Roxy-3D)
🇺🇸 **Keith Bennett**
[@thisiskeithb](https://github.com/thisiskeithb)
[<kbd>Donate 💸 </kbd>](https://github.com/sponsors/thisiskeithb)
🇺🇸 **Jason Smith**
[@sjasonsmith](https://github.com/sjasonsmith)
</td><td>
🇧🇷 **Victor Oliveira**
[@rhapsodyv](https://github.com/rhapsodyv)
🇬🇧 **Chris Pepper**
[@p3p](https://github.com/p3p)
🇳🇿 **Peter Ellens**
[@ellensp](https://github.com/ellensp)
[<kbd>Donate 💸 </kbd>](https://ko-fi.com/ellensp)
</td><td>
🇺🇸 **Bob Kuhn**
[@Bob-the-Kuhn](https://github.com/Bob-the-Kuhn)
🇳🇱 **Erik van der Zalm**
[@ErikZalm](https://github.com/ErikZalm)
</td></tr>
</table>
## License
Marlin is published under the [GPL license](/LICENSE) because we believe in open development. The GPL comes with both rights and obligations. Whether you use Marlin firmware as the driver for your open or closed-source product, you must keep Marlin open, and you must provide your compatible Marlin source code to end users upon request. The most straightforward way to comply with the Marlin license is to make a fork of Marlin on Github, perform your modifications, and direct users to your modified fork.
While we can't prevent the use of this code in products (3D printers, CNC, etc.) that are closed source or crippled by a patent, we would prefer that you choose another firmware or, better yet, make your own.
Binary file not shown.

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