diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index f88f5b9dbd..47be4f97a9 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -61,14 +61,14 @@
// @section info
// Author info of this build printed to the host during boot and M115
-#define STRING_CONFIG_H_AUTHOR "(none, default config)" // Who made the changes.
+#define STRING_CONFIG_H_AUTHOR "InsanityAutomation" // Who made the changes.
//#define CUSTOM_VERSION_FILE Version.h // Path from the root directory (no quotes)
// @section machine
// Choose the name from boards.h that matches your setup
#ifndef MOTHERBOARD
- #define MOTHERBOARD BOARD_RAMPS_14_EFB
+ #define MOTHERBOARD BOARD_EBAB
#endif
/**
@@ -79,7 +79,7 @@
*
* :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
-#define SERIAL_PORT 0
+#define SERIAL_PORT -1
/**
* Serial Port Baud Rate
@@ -101,7 +101,7 @@
* Currently Ethernet (-2) is only supported on Teensy 4.1 boards.
* :[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
-//#define SERIAL_PORT_2 -1
+#define SERIAL_PORT_2 0
//#define BAUDRATE_2 250000 // :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000] Enable to override BAUDRATE
/**
@@ -116,7 +116,7 @@
//#define BLUETOOTH
// Name displayed in the LCD "Ready" message and Info menu
-//#define CUSTOM_MACHINE_NAME "3D Printer"
+#define CUSTOM_MACHINE_NAME "FatBoy"
// Printer's unique ID, used by some programs to differentiate between machines.
// Choose your own or use a service like https://www.uuidgenerator.net/version4
@@ -139,21 +139,21 @@
* TMC5160, TMC5160_STANDALONE
* :['A4988', 'A5984', 'DRV8825', 'LV8729', 'TB6560', 'TB6600', 'TMC2100', 'TMC2130', 'TMC2130_STANDALONE', 'TMC2160', 'TMC2160_STANDALONE', 'TMC2208', 'TMC2208_STANDALONE', 'TMC2209', 'TMC2209_STANDALONE', 'TMC2660', 'TMC2660_STANDALONE', 'TMC5130', 'TMC5130_STANDALONE', 'TMC5160', 'TMC5160_STANDALONE']
*/
-#define X_DRIVER_TYPE A4988
-#define Y_DRIVER_TYPE A4988
-#define Z_DRIVER_TYPE A4988
+#define X_DRIVER_TYPE TB6560
+#define Y_DRIVER_TYPE TB6560
+#define Z_DRIVER_TYPE TB6560
//#define X2_DRIVER_TYPE A4988
-//#define Y2_DRIVER_TYPE A4988
-//#define Z2_DRIVER_TYPE A4988
-//#define Z3_DRIVER_TYPE A4988
-//#define Z4_DRIVER_TYPE A4988
+#define Y2_DRIVER_TYPE TB6560
+#define Z2_DRIVER_TYPE TB6560
+#define Z3_DRIVER_TYPE TB6560
+#define Z4_DRIVER_TYPE TB6560
//#define I_DRIVER_TYPE A4988
//#define J_DRIVER_TYPE A4988
//#define K_DRIVER_TYPE A4988
//#define U_DRIVER_TYPE A4988
//#define V_DRIVER_TYPE A4988
//#define W_DRIVER_TYPE A4988
-#define E0_DRIVER_TYPE A4988
+#define E0_DRIVER_TYPE TMC2209
//#define E1_DRIVER_TYPE A4988
//#define E2_DRIVER_TYPE A4988
//#define E3_DRIVER_TYPE A4988
@@ -561,7 +561,7 @@
#define TEMP_SENSOR_5 0
#define TEMP_SENSOR_6 0
#define TEMP_SENSOR_7 0
-#define TEMP_SENSOR_BED 1
+#define TEMP_SENSOR_BED 11
#define TEMP_SENSOR_PROBE 0
#define TEMP_SENSOR_CHAMBER 0
#define TEMP_SENSOR_COOLER 0
@@ -637,7 +637,7 @@
// Above this temperature the heater will be switched off.
// This can protect components from overheating, but NOT from shorts and failures.
// (Use MINTEMP for thermistor short/failure protection.)
-#define HEATER_0_MAXTEMP 275
+#define HEATER_0_MAXTEMP 300
#define HEATER_1_MAXTEMP 275
#define HEATER_2_MAXTEMP 275
#define HEATER_3_MAXTEMP 275
@@ -645,7 +645,7 @@
#define HEATER_5_MAXTEMP 275
#define HEATER_6_MAXTEMP 275
#define HEATER_7_MAXTEMP 275
-#define BED_MAXTEMP 150
+#define BED_MAXTEMP 120
#define CHAMBER_MAXTEMP 60
/**
@@ -654,7 +654,7 @@
* (especially before PID tuning). Setting the target temperature too close to MAXTEMP guarantees
* a MAXTEMP shutdown! Use these values to forbid temperatures being set too close to MAXTEMP.
*/
-#define HOTEND_OVERSHOOT 15 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
+#define HOTEND_OVERSHOOT 10 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
#define BED_OVERSHOOT 10 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
#define COOLER_OVERSHOOT 2 // (°C) Forbid temperatures closer than OVERSHOOT
@@ -757,7 +757,7 @@
* When set to any value below 255, enables a form of PWM to the bed that acts like a divider
* so don't use it unless you are OK with PWM on your bed. (See the comment on enabling PIDTEMPBED)
*/
-#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
+#define MAX_BED_POWER 180 // limits duty cycle to bed; 255=full current
/**
* PID Bed Heating
@@ -771,7 +771,7 @@
*
* With this option disabled, bang-bang will be used. BED_LIMIT_SWITCHING enables hysteresis.
*/
-//#define PIDTEMPBED
+#define PIDTEMPBED
#if ENABLED(PIDTEMPBED)
//#define MIN_BED_POWER 0
@@ -842,8 +842,8 @@
#define PID_FUNCTIONAL_RANGE 10 // If the temperature difference between the target temperature and the actual temperature
// is more than PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max.
- //#define PID_EDIT_MENU // Add PID editing to the "Advanced Settings" menu. (~700 bytes of flash)
- //#define PID_AUTOTUNE_MENU // Add PID auto-tuning to the "Advanced Settings" menu. (~250 bytes of flash)
+ #define PID_EDIT_MENU // Add PID editing to the "Advanced Settings" menu. (~700 bytes of flash)
+ #define PID_AUTOTUNE_MENU // Add PID auto-tuning to the "Advanced Settings" menu. (~250 bytes of flash)
#endif
// @section safety
@@ -1236,7 +1236,7 @@
* Override with M92 (when enabled below)
* X, Y, Z [, I [, J [, K...]]], E0 [, E1[, E2...]]
*/
-#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 400, 500 }
+#define DEFAULT_AXIS_STEPS_PER_UNIT { 40, 40, 200, 425 }
/**
* Enable support for M92. Disable to save at least ~530 bytes of flash.
@@ -1261,7 +1261,7 @@
* Override with M201
* X, Y, Z [, I [, J [, K...]]], E0 [, E1[, E2...]]
*/
-#define DEFAULT_MAX_ACCELERATION { 3000, 3000, 100, 10000 }
+#define DEFAULT_MAX_ACCELERATION { 12000, 12000, 500, 10000 }
//#define LIMITED_MAX_ACCEL_EDITING // Limit edit via M201 or LCD to DEFAULT_MAX_ACCELERATION * 2
#if ENABLED(LIMITED_MAX_ACCEL_EDITING)
@@ -1276,9 +1276,9 @@
* M204 R Retract Acceleration
* M204 T Travel Acceleration
*/
-#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E acceleration for printing moves
+#define DEFAULT_ACCELERATION 7000 // X, Y, Z and E acceleration for printing moves
#define DEFAULT_RETRACT_ACCELERATION 3000 // E acceleration for retracts
-#define DEFAULT_TRAVEL_ACCELERATION 3000 // X, Y, Z acceleration for travel (non printing) moves
+#define DEFAULT_TRAVEL_ACCELERATION 7000 // X, Y, Z acceleration for travel (non printing) moves
/**
* Default Jerk limits (mm/s)
@@ -1330,7 +1330,7 @@
*
* See https://github.com/synthetos/TinyG/wiki/Jerk-Controlled-Motion-Explained
*/
-//#define S_CURVE_ACCELERATION
+#define S_CURVE_ACCELERATION
//===========================================================================
//============================= Z Probe Options =============================
@@ -1346,10 +1346,10 @@
* The probe replaces the Z-MIN endstop and is used for Z homing.
* (Automatically enables USE_PROBE_FOR_Z_HOMING.)
*/
-#define Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN
+//#define Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN
// Force the use of the probe for Z-axis homing
-//#define USE_PROBE_FOR_Z_HOMING
+#define USE_PROBE_FOR_Z_HOMING
/**
* Z_MIN_PROBE_PIN
@@ -1406,7 +1406,7 @@
/**
* The BLTouch probe uses a Hall effect sensor and emulates a servo.
*/
-//#define BLTOUCH
+#define BLTOUCH
/**
* MagLev V4 probe by MDD
@@ -1647,7 +1647,7 @@
* A total of 2 does fast/slow probes with a weighted average.
* A total of 3 or more adds more slow probes, taking the average.
*/
-//#define MULTIPLE_PROBING 2
+#define MULTIPLE_PROBING 2
//#define EXTRA_PROBING 1
/**
@@ -1670,7 +1670,7 @@
#define Z_PROBE_ERROR_TOLERANCE 3 // (mm) Tolerance for early trigger (<= -probe.offset.z + ZPET)
//#define Z_AFTER_PROBING 5 // (mm) Z position after probing is done
-#define Z_PROBE_LOW_POINT -2 // (mm) Farthest distance below the trigger-point to go before stopping
+#define Z_PROBE_LOW_POINT -5 // (mm) Farthest distance below the trigger-point to go before stopping
// For M851 provide ranges for adjusting the X, Y, and Z probe offsets
//#define PROBE_OFFSET_XMIN -50 // (mm)
@@ -1749,9 +1749,9 @@
// @section motion
// Invert the stepper direction. Change (or reverse the motor connector) if an axis goes the wrong way.
-#define INVERT_X_DIR false
-#define INVERT_Y_DIR true
-#define INVERT_Z_DIR false
+#define INVERT_X_DIR true
+#define INVERT_Y_DIR false
+#define INVERT_Z_DIR true
//#define INVERT_I_DIR false
//#define INVERT_J_DIR false
//#define INVERT_K_DIR false
@@ -1821,8 +1821,8 @@
// @section geometry
// The size of the printable area
-#define X_BED_SIZE 200
-#define Y_BED_SIZE 200
+#define X_BED_SIZE 1200
+#define Y_BED_SIZE 1200
// Travel limits (linear=mm, rotational=°) after homing, corresponding to endstop positions.
#define X_MIN_POS 0
@@ -1830,7 +1830,7 @@
#define Z_MIN_POS 0
#define X_MAX_POS X_BED_SIZE
#define Y_MAX_POS Y_BED_SIZE
-#define Z_MAX_POS 200
+#define Z_MAX_POS 1000
//#define I_MIN_POS 0
//#define I_MAX_POS 50
//#define J_MIN_POS 0
@@ -1882,7 +1882,7 @@
#endif
#if ANY(MIN_SOFTWARE_ENDSTOPS, MAX_SOFTWARE_ENDSTOPS)
- //#define SOFT_ENDSTOPS_MENU_ITEM // Enable/Disable software endstops from the LCD
+ #define SOFT_ENDSTOPS_MENU_ITEM // Enable/Disable software endstops from the LCD
#endif
/**
@@ -2041,7 +2041,7 @@
*/
//#define AUTO_BED_LEVELING_3POINT
//#define AUTO_BED_LEVELING_LINEAR
-//#define AUTO_BED_LEVELING_BILINEAR
+#define AUTO_BED_LEVELING_BILINEAR
//#define AUTO_BED_LEVELING_UBL
//#define MESH_BED_LEVELING
@@ -2049,14 +2049,14 @@
* Commands to execute at the end of G29 probing.
* Useful to retract or move the Z probe out of the way.
*/
-//#define EVENT_GCODE_AFTER_G29 "G1 Z10 F12000\nG1 X15 Y330\nG1 Z0.5\nG1 Z10"
+//#define Z_PROBE_END_SCRIPT "G1 Z10 F12000\nG1 X15 Y330\nG1 Z0.5\nG1 Z10"
/**
* Normally G28 leaves leveling disabled on completion. Enable one of
* these options to restore the prior leveling state or to always enable
* leveling immediately after G28.
*/
-//#define RESTORE_LEVELING_AFTER_G28
+#define RESTORE_LEVELING_AFTER_G28
//#define ENABLE_LEVELING_AFTER_G28
/**
@@ -2071,7 +2071,7 @@
/**
* Enable detailed logging of G28, G29, M48, etc.
* Turn on with the command 'M111 S32'.
- * NOTE: Requires a lot of flash!
+ * NOTE: Requires a lot of PROGMEM!
*/
//#define DEBUG_LEVELING_FEATURE
@@ -2088,7 +2088,7 @@
*/
#define ENABLE_LEVELING_FADE_HEIGHT
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
- #define DEFAULT_LEVELING_FADE_HEIGHT 10.0 // (mm) Default fade height.
+ #define DEFAULT_LEVELING_FADE_HEIGHT 0.0 // (mm) Default fade height.
#endif
/**
@@ -2102,7 +2102,7 @@
/**
* Enable the G26 Mesh Validation Pattern tool.
*/
- //#define G26_MESH_VALIDATION
+ #define G26_MESH_VALIDATION
#if ENABLED(G26_MESH_VALIDATION)
#define MESH_TEST_NOZZLE_SIZE 0.4 // (mm) Diameter of primary nozzle.
#define MESH_TEST_LAYER_HEIGHT 0.2 // (mm) Default layer height for G26.
@@ -2118,7 +2118,7 @@
#if ANY(AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_BILINEAR)
// Set the number of grid points per dimension.
- #define GRID_MAX_POINTS_X 3
+ #define GRID_MAX_POINTS_X 15
#define GRID_MAX_POINTS_Y GRID_MAX_POINTS_X
// Probe along the Y axis, advancing X after each column
@@ -2128,7 +2128,7 @@
// Beyond the probed grid, continue the implied tilt?
// Default is to maintain the height of the nearest edge.
- //#define EXTRAPOLATE_BEYOND_GRID
+ #define EXTRAPOLATE_BEYOND_GRID
//
// Subdivision of the grid by Catmull-Rom method.
@@ -2204,12 +2204,12 @@
* Add a bed leveling sub-menu for ABL or MBL.
* Include a guided procedure if manual probing is enabled.
*/
-//#define LCD_BED_LEVELING
+#define LCD_BED_LEVELING
#if ENABLED(LCD_BED_LEVELING)
#define MESH_EDIT_Z_STEP 0.025 // (mm) Step size while manually probing Z axis.
- #define LCD_PROBE_Z_RANGE 4 // (mm) Z Range centered on Z_MIN_POS for LCD Z adjustment
- //#define MESH_EDIT_MENU // Add a menu to edit mesh points
+ #define LCD_PROBE_Z_RANGE 8 // (mm) Z Range centered on Z_MIN_POS for LCD Z adjustment
+ #define MESH_EDIT_MENU // Add a menu to edit mesh points
#endif
// Add a menu item to move between bed corners for manual bed adjustment
@@ -2271,7 +2271,7 @@
* - Allows Z homing only when XY positions are known and trusted.
* - If stepper drivers sleep, XY homing may be required again before Z homing.
*/
-//#define Z_SAFE_HOMING
+#define Z_SAFE_HOMING
#if ENABLED(Z_SAFE_HOMING)
#define Z_SAFE_HOMING_X_POINT X_CENTER // (mm) X point for Z homing
@@ -2358,12 +2358,12 @@
* M501 - Read settings from EEPROM. (i.e., Throw away unsaved changes)
* M502 - Revert settings to "factory" defaults. (Follow with M500 to init the EEPROM.)
*/
-//#define EEPROM_SETTINGS // Persistent storage with M500 and M501
+#define EEPROM_SETTINGS // Persistent storage with M500 and M501
//#define DISABLE_M503 // Saves ~2700 bytes of flash. Disable for release!
-#define EEPROM_CHITCHAT // Give feedback on EEPROM commands. Disable to save flash.
+#define EEPROM_CHITCHAT // Give feedback on EEPROM commands. Disable to save PROGMEM.
#define EEPROM_BOOT_SILENT // Keep M503 quiet and only give errors during first load
#if ENABLED(EEPROM_SETTINGS)
- //#define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors.
+ #define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors.
//#define EEPROM_INIT_NOW // Init EEPROM on first boot after a new build.
#endif
@@ -2421,11 +2421,11 @@
* P1 Raise the nozzle always to Z-park height.
* P2 Raise the nozzle by Z-park amount, limited to Z_MAX_POS.
*/
-//#define NOZZLE_PARK_FEATURE
+#define NOZZLE_PARK_FEATURE
#if ENABLED(NOZZLE_PARK_FEATURE)
// Specify a park position as { X, Y, Z_raise }
- #define NOZZLE_PARK_POINT { (X_MIN_POS + 10), (Y_MAX_POS - 10), 20 }
+ #define NOZZLE_PARK_POINT { (X_MIN_POS + 10), (Y_MIN_POS + 10), 5 }
#define NOZZLE_PARK_MOVE 0 // Park motion: 0 = XY Move, 1 = X Only, 2 = Y Only, 3 = X before Y, 4 = Y before X
#define NOZZLE_PARK_Z_RAISE_MIN 2 // (mm) Always raise Z by at least this distance
#define NOZZLE_PARK_XY_FEEDRATE 100 // (mm/s) X and Y axes feedrate (also used for delta Z axis)
@@ -2648,7 +2648,7 @@
* SD Card support is disabled by default. If your controller has an SD slot,
* you must uncomment the following option or it won't work.
*/
-//#define SDSUPPORT
+#define SDSUPPORT
/**
* SD CARD: ENABLE CRC
@@ -2728,7 +2728,7 @@
//
// Add individual axis homing items (Home X, Home Y, and Home Z) to the LCD menu.
//
-//#define INDIVIDUAL_AXIS_HOMING_MENU
+#define INDIVIDUAL_AXIS_HOMING_MENU
//#define INDIVIDUAL_AXIS_HOMING_SUBMENU
//
@@ -2737,7 +2737,7 @@
// If you have a speaker that can produce tones, enable it here.
// By default Marlin assumes you have a buzzer with a fixed frequency.
//
-//#define SPEAKER
+#define SPEAKER
//
// The duration and frequency for the UI feedback sound.
@@ -2931,7 +2931,7 @@
// RepRapDiscount FULL GRAPHIC Smart Controller
// https://reprap.org/wiki/RepRapDiscount_Full_Graphic_Smart_Controller
//
-//#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
+#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
//
// K.3D Full Graphic Smart Controller
diff --git a/Marlin/src/HAL/LPC4078/HAL.cpp b/Marlin/src/HAL/LPC4078/HAL.cpp
new file mode 100644
index 0000000000..3cdf636480
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/HAL.cpp
@@ -0,0 +1,125 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#ifdef TARGET_LPC4078
+
+#include "../../inc/MarlinConfig.h"
+#include "../shared/Delay.h"
+#include "../../../gcode/parser.h"
+
+DefaultSerial1 USBSerial(false, MCDCSerial0);
+
+uint32_t MarlinHAL::adc_result = 0;
+
+// U8glib required functions
+extern "C" {
+ void u8g_xMicroDelay(uint16_t val) { DELAY_US(val); }
+ void u8g_MicroDelay() { u8g_xMicroDelay(1); }
+ void u8g_10MicroDelay() { u8g_xMicroDelay(10); }
+ void u8g_Delay(uint16_t val) { delay(val); }
+}
+
+// return free heap space
+int freeMemory() {
+ char stack_end;
+ void *heap_start = malloc(sizeof(uint32_t));
+ if (heap_start == 0) return 0;
+
+ uint32_t result = (uint32_t)&stack_end - (uint32_t)heap_start;
+ free(heap_start);
+ return result;
+}
+
+void MarlinHAL::reboot() { MCUCore::nvic_system_reset(); }
+
+uint8_t MarlinHAL::get_reset_source() {
+ #if ENABLED(USE_WATCHDOG)
+ if (watchdog_timed_out()) return RST_WATCHDOG;
+ #endif
+ return RST_POWER_ON;
+}
+
+void MarlinHAL::clear_reset_source() { watchdog_clear_timeout_flag(); }
+
+void flashFirmware(const int16_t) {
+ delay(500); // Give OS time to disconnect
+ //USB_Connect(false); // USB clear connection
+ delay(1000); // Give OS time to notice
+ hal.reboot();
+}
+
+#if ENABLED(USE_WATCHDOG)
+
+ #define WDT_TIMEOUT TERN(WATCHDOG_DURATION_8S, 8.0f, 4.0f) // 4 or 8 second timeout
+
+ void MarlinHAL::watchdog_init() {
+ #if ENABLED(WATCHDOG_RESET_MANUAL)
+ // We enable the watchdog timer, but only for the interrupt.
+
+ // Configure WDT to only trigger an interrupt
+ // Disable WDT interrupt (just in case, to avoid triggering it!)
+ NVIC_DisableIRQ(WDT_IRQn);
+
+ // We NEED memory barriers to ensure Interrupts are actually disabled!
+ // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
+ __DSB();
+ __ISB();
+
+ // WDT defaults to trigger an interrupt
+
+ // Configure and enable WDT interrupt.
+ NVIC_ClearPendingIRQ(WDT_IRQn);
+ NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
+ NVIC_EnableIRQ(WDT_IRQn);
+ #else
+ MCUI::watchdog_set_timeout_triggers_reset();
+ #endif
+ MCUI::watchdog_set_timeout_in_seconds(WDT_TIMEOUT);
+ MCUI::watchdog_enable();
+ }
+
+ void MarlinHAL::watchdog_refresh() {
+ MCUI::watchdog_feed();
+ #if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
+ static millis_t next_flash = millis();
+ if (ELAPSED(millis(), next_flash)) {
+ next_flash = millis() + 200;
+ TOGGLE(LED_PIN); // heartbeat indicator
+ }
+ #endif
+ }
+
+ // Timeout state
+ bool MarlinHAL::watchdog_timed_out() { return MCUI::watchdog_has_triggered(); }
+ void MarlinHAL::watchdog_clear_timeout_flag() { MCUI::watchdog_clear_timeout_flag(); }
+
+#endif // USE_WATCHDOG
+
+// For M42/M43, scan command line for pin code
+// return index into pin map array if found and the pin is valid.
+// return dval if not found or not a valid pin.
+int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) {
+ const uint16_t val = (uint16_t)parser.intval(code, -1), port = val / 100, pin = val % 100;
+ const int16_t ind = (port < ((NUM_DIGITAL_PINS) >> 5) && pin < 32) ? ((port << 5) | pin) : -2;
+ return ind > -1 ? ind : dval;
+}
+
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/LPC4078/HAL.h b/Marlin/src/HAL/LPC4078/HAL.h
new file mode 100644
index 0000000000..c4803909a7
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/HAL.h
@@ -0,0 +1,267 @@
+/**
+ * Marlin 3D Printer Firmware
+ *
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
+ * Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+/**
+ * HAL_LPC1768/HAL.h
+ * Hardware Abstraction Layer for NXP LPC1768
+ */
+
+#define CPU_32_BIT
+
+#include
+#include
+#include
+
+#include "../shared/Marduino.h"
+#include "../shared/Delay.h"
+#include "../shared/math_32bit.h"
+#include "../shared/HAL_SPI.h"
+#include "fastio.h"
+#include "MarlinSerial.h"
+
+#include
+
+// ------------------------
+// Serial ports
+// ------------------------
+
+typedef ForwardSerial1Class< decltype(MCDCSerial0) > DefaultSerial1;
+extern DefaultSerial1 USBSerial;
+
+#define _MSERIAL(X) MSerial##X
+#define MSERIAL(X) _MSERIAL(X)
+
+#if SERIAL_PORT == -1
+ #define MYSERIAL1 USBSerial
+#elif WITHIN(SERIAL_PORT, 0, 3)
+ #define MYSERIAL1 MSERIAL(SERIAL_PORT)
+#else
+ #error "SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
+#endif
+
+#ifdef SERIAL_PORT_2
+ #if SERIAL_PORT_2 == -1
+ #define MYSERIAL2 USBSerial
+ #elif WITHIN(SERIAL_PORT_2, 0, 3)
+ #define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
+ #else
+ #error "SERIAL_PORT_2 must be from 0 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+#endif
+
+#ifdef SERIAL_PORT_3
+ #if SERIAL_PORT_3 == -1
+ #define MYSERIAL3 USBSerial
+ #elif WITHIN(SERIAL_PORT_3, 0, 3)
+ #define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
+ #else
+ #error "SERIAL_PORT_3 must be from 0 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+#endif
+
+#ifdef MMU2_SERIAL_PORT
+ #if MMU2_SERIAL_PORT == -1
+ #define MMU2_SERIAL USBSerial
+ #elif WITHIN(MMU2_SERIAL_PORT, 0, 3)
+ #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
+ #else
+ #error "MMU2_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+#endif
+
+#ifdef LCD_SERIAL_PORT
+ #if LCD_SERIAL_PORT == -1
+ #define LCD_SERIAL USBSerial
+ #elif WITHIN(LCD_SERIAL_PORT, 0, 3)
+ #define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
+ #else
+ #error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+ #if HAS_DGUS_LCD
+ #define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.available()
+ #endif
+#endif
+
+//
+// Interrupts
+//
+
+#define CRITICAL_SECTION_START() const bool irqon = !MCUCore::primask(); MCUCore::nvic_interrupts_disable()
+#define CRITICAL_SECTION_END() if (irqon) MCUCore::nvic_interrupts_enable()
+
+//
+// ADC
+//
+
+#define ADC_MEDIAN_FILTER_SIZE (23) // Higher values increase step delay (phase shift),
+ // (ADC_MEDIAN_FILTER_SIZE + 1) / 2 sample step delay (12 samples @ 500Hz: 24ms phase shift)
+ // Memory usage per ADC channel (bytes): (6 * ADC_MEDIAN_FILTER_SIZE) + 16
+ // 8 * ((6 * 23) + 16 ) = 1232 Bytes for 8 channels
+
+#define ADC_LOWPASS_K_VALUE (2) // Higher values increase rise time
+ // Rise time sample delays for 100% signal convergence on full range step
+ // (1 : 13, 2 : 32, 3 : 67, 4 : 139, 5 : 281, 6 : 565, 7 : 1135, 8 : 2273)
+ // K = 6, 565 samples, 500Hz sample rate, 1.13s convergence on full range step
+ // Memory usage per ADC channel (bytes): 4 (32 Bytes for 8 channels)
+
+#define HAL_ADC_VREF 3.3 // ADC voltage reference
+
+#define HAL_ADC_RESOLUTION 12 // 15 bit maximum, raw temperature is stored as int16_t
+#define HAL_ADC_FILTERED // Disable oversampling done in Marlin as ADC values already filtered in HAL
+
+//
+// Pin Mapping for M42, M43, M226
+//
+
+// Test whether the pin is valid
+constexpr bool VALID_PIN(const pin_t pin) {
+ return MCUI::pin_is_valid(pin);
+}
+
+// Get the analog index for a digital pin
+constexpr int8_t DIGITAL_PIN_TO_ANALOG_PIN(const pin_t pin) {
+ return (MCUI::pin_is_valid(pin) && MCUI::pin_has_adc(pin)) ? pin : -1;
+}
+
+// Return the index of a pin number
+constexpr int16_t GET_PIN_MAP_INDEX(const pin_t pin) {
+ return MCUI::pin_index(pin);
+}
+
+// Get the pin number at the given index
+constexpr pin_t GET_PIN_MAP_PIN(const int16_t index) {
+ return MCUI::pin_index(index);
+}
+
+// Parse a G-code word into a pin index
+int16_t PARSED_PIN_INDEX(const char code, const int16_t dval);
+// P0.6 thru P0.9 are for the onboard SD card
+#define HAL_SENSITIVE_PINS P0_06, P0_07, P0_08, P0_09,
+
+// ------------------------
+// Defines
+// ------------------------
+
+void flashFirmware(const int16_t);
+
+#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
+
+// Default graphical display delays
+#define CPU_ST7920_DELAY_1 600
+#define CPU_ST7920_DELAY_2 750
+#define CPU_ST7920_DELAY_3 750
+
+// ------------------------
+// Free Memory Accessor
+// ------------------------
+
+#pragma GCC diagnostic push
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+int freeMemory();
+
+#pragma GCC diagnostic pop
+
+// ------------------------
+// MarlinHAL Class
+// ------------------------
+
+class MarlinHAL {
+public:
+
+ // Earliest possible init, before setup()
+ MarlinHAL() {}
+
+ static void init(); // Called early in setup()
+ static void init_board() {} // Called less early in setup()
+ static void reboot(); // Restart the firmware from 0x0
+
+ // Interrupts
+ static bool isr_state() { return MCUCore::primask(); }
+ static void isr_on() { MCUCore::nvic_interrupts_enable(); }
+ static void isr_off() { MCUCore::nvic_interrupts_disable(); }
+
+ static void delay_ms(const int ms) { DELAY_US(ms * 1000); }
+
+ // Watchdog
+ static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
+ static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
+ static bool watchdog_timed_out() IF_DISABLED(USE_WATCHDOG, { return false; });
+ static void watchdog_clear_timeout_flag() IF_DISABLED(USE_WATCHDOG, {});
+
+ // Tasks, called from idle()
+ static void idletask();
+
+ // Reset
+ static uint8_t get_reset_source();
+ static void clear_reset_source();
+
+ // Free SRAM
+ static int freeMemory() { return ::freeMemory(); }
+
+ //
+ // ADC Methods
+ //
+
+ using FilteredADC = MCUI::ADC;
+
+ // Called by Temperature::init once at startup
+ static void adc_init() {
+ // Turn on and initialise ADC in burst mode
+ MCUI::adc_hardware.init();
+ MCUI::adc_hardware.burst_start();
+ }
+
+ // Called by Temperature::init for each sensor at startup
+ static void adc_enable(const pin_t pin) {
+ FilteredADC::enable_channel(pin);
+ }
+
+ // Begin ADC sampling on the given pin. Called from Temperature::isr!
+ static uint32_t adc_result;
+ static void adc_start(const pin_t pin) {
+ adc_result = FilteredADC::read(pin) >> (16 - HAL_ADC_RESOLUTION); // returns 16bit value, reduce to required bits
+ }
+
+ // Is the ADC ready for reading?
+ static bool adc_ready() { return true; }
+
+ // The current value of the ADC register
+ static uint16_t adc_value() { return uint16_t(adc_result); }
+
+ /**
+ * Set the PWM duty cycle for the pin to the given value.
+ * Optionally invert the duty cycle [default = false]
+ * Optionally change the scale of the provided value to enable finer PWM duty control [default = 255]
+ */
+ static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
+
+ /**
+ * Set the frequency of the timer corresponding to the provided pin
+ * All Hardware PWM pins will run at the same frequency and
+ * All Software PWM pins will run at the same frequency
+ */
+ static void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
+};
diff --git a/Marlin/src/HAL/LPC4078/HAL_SPI.cpp b/Marlin/src/HAL/LPC4078/HAL_SPI.cpp
new file mode 100644
index 0000000000..3af5677fbc
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/HAL_SPI.cpp
@@ -0,0 +1,404 @@
+// /**
+// * 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 .
+// *
+// */
+
+// /**
+// * Software SPI functions originally from Arduino Sd2Card Library
+// * Copyright (c) 2009 by William Greiman
+// */
+
+// /**
+// * For TARGET_LPC4078
+// */
+
+// /**
+// * Hardware SPI and Software SPI implementations are included in this file.
+// * The hardware SPI runs faster and has higher throughput but is not compatible
+// * with some LCD interfaces/adapters.
+// *
+// * Control of the slave select pin(s) is handled by the calling routines.
+// *
+// * Some of the LCD interfaces/adapters result in the LCD SPI and the SD card
+// * SPI sharing pins. The SCK, MOSI & MISO pins can NOT be set/cleared with
+// * WRITE nor digitalWrite when the hardware SPI module within the LPC17xx is
+// * active. If any of these pins are shared then the software SPI must be used.
+// *
+// * A more sophisticated hardware SPI can be found at the following link.
+// * This implementation has not been fully debugged.
+// * https://github.com/MarlinFirmware/Marlin/tree/071c7a78f27078fd4aee9a3ef365fcf5e143531e
+// */
+
+#ifdef TARGET_LPC4078
+
+#include "../../inc/MarlinConfig.h"
+#include
+
+// Hardware SPI and SPIClass
+
+#include "../shared/HAL_SPI.h"
+
+#define LPC_SOFTWARE_SPI
+
+// ------------------------
+// Public functions
+// ------------------------
+#if ENABLED(LPC_SOFTWARE_SPI)
+ #include "SoftwareSPI.h"
+
+ // Software SPI
+ static uint8_t SPI_speed = SPI_FULL_SPEED;
+
+ static uint8_t spiTransfer(uint8_t b) {
+ return swSpiTransfer(b, SPI_speed, SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN);
+ }
+
+ void spiBegin() {
+ swSpiBegin(SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN);
+ }
+
+ void spiInit(uint8_t spiRate) {
+ SPI_speed = swSpiInit(spiRate, SD_SCK_PIN, SD_MOSI_PIN);
+ }
+
+ uint8_t spiRec() { return spiTransfer(0xFF); }
+
+ void spiRead(uint8_t*buf, uint16_t nbyte) {
+ for (int i = 0; i < nbyte; i++)
+ buf[i] = spiTransfer(0xFF);
+ }
+
+ void spiSend(uint8_t b) { (void)spiTransfer(b); }
+
+ void spiSend(const uint8_t *buf, size_t nbyte) {
+ for (uint16_t i = 0; i < nbyte; i++)
+ (void)spiTransfer(buf[i]);
+ }
+
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
+ (void)spiTransfer(token);
+ for (uint16_t i = 0; i < 512; i++)
+ (void)spiTransfer(buf[i]);
+ }
+
+#else
+
+ #ifdef SD_SPI_SPEED
+ #define INIT_SPI_SPEED SD_SPI_SPEED
+ #else
+ #define INIT_SPI_SPEED SPI_FULL_SPEED
+ #endif
+
+ void spiBegin() { spiInit(INIT_SPI_SPEED); } // Set up SCK, MOSI & MISO pins for SSP0
+
+ void spiInit(uint8_t spiRate) {
+ #if SD_MISO_PIN == BOARD_SPI1_MISO_PIN
+ SPI.setModule(1);
+ #elif SD_MISO_PIN == BOARD_SPI2_MISO_PIN
+ SPI.setModule(2);
+ #endif
+ SPI.setDataSize(DATA_SIZE_8BIT);
+ SPI.setDataMode(SPI_MODE0);
+
+ SPI.setClock(SPISettings::spiRate2Clock(spiRate));
+ SPI.begin();
+ }
+
+ static uint8_t doio(uint8_t b) {
+ return SPI.transfer(b & 0x00FF) & 0x00FF;
+ }
+
+ void spiSend(uint8_t b) { doio(b); }
+
+ void spiSend(const uint8_t *buf, size_t nbyte) {
+ for (uint16_t i = 0; i < nbyte; i++) doio(buf[i]);
+ }
+
+ void spiSend(uint32_t chan, byte b) {}
+
+ void spiSend(uint32_t chan, const uint8_t *buf, size_t nbyte) {}
+
+ // Read single byte from SPI
+ uint8_t spiRec() { return doio(0xFF); }
+
+ uint8_t spiRec(uint32_t chan) { return 0; }
+
+ // Read from SPI into buffer
+ void spiRead(uint8_t *buf, uint16_t nbyte) {
+ for (uint16_t i = 0; i < nbyte; i++) buf[i] = doio(0xFF);
+ }
+
+ uint8_t spiTransfer(uint8_t b) { return doio(b); }
+
+ // Write from buffer to SPI
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
+ (void)spiTransfer(token);
+ for (uint16_t i = 0; i < 512; i++)
+ (void)spiTransfer(buf[i]);
+ }
+
+ // Begin SPI transaction, set clock, bit order, data mode
+ void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
+ // TODO: Implement this method
+ }
+
+#endif // LPC_SOFTWARE_SPI
+
+// /**
+// * @brief Wait until TXE (tx empty) flag is set and BSY (busy) flag unset.
+// */
+// static inline void waitSpiTxEnd(LPC_SSP_TypeDef *spi_d) {
+// while (SSP_GetStatus(spi_d, SSP_STAT_TXFIFO_EMPTY) == RESET) { /* nada */ } // wait until TXE=1
+// while (SSP_GetStatus(spi_d, SSP_STAT_BUSY) == SET) { /* nada */ } // wait until BSY=0
+// }
+
+// // Retain the pin init state of the SPI, to avoid init more than once,
+// // even if more instances of SPIClass exist
+// static bool spiInitialised[BOARD_NR_SPI] = { false };
+
+// SPIClass::SPIClass(uint8_t device) {
+// // Init things specific to each SPI device
+// // clock divider setup is a bit of hack, and needs to be improved at a later date.
+
+// #if BOARD_NR_SPI >= 1
+// _settings[0].spi_d = LPC_SSP0;
+// _settings[0].dataMode = SPI_MODE0;
+// _settings[0].dataSize = DATA_SIZE_8BIT;
+// _settings[0].clock = SPI_CLOCK_MAX;
+// //_settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock);
+// #endif
+
+// #if BOARD_NR_SPI >= 2
+// _settings[1].spi_d = LPC_SSP1;
+// _settings[1].dataMode = SPI_MODE0;
+// _settings[1].dataSize = DATA_SIZE_8BIT;
+// _settings[1].clock = SPI_CLOCK_MAX;
+// //_settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock);
+// #endif
+
+// setModule(device);
+
+// // Init the GPDMA controller
+// // TODO: call once in the constructor? or each time?
+// GPDMA_Init();
+// }
+
+// SPIClass::SPIClass(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel) {
+// #if BOARD_NR_SPI >= 1
+// if (mosi == BOARD_SPI1_MOSI_PIN) SPIClass(1);
+// #endif
+// #if BOARD_NR_SPI >= 2
+// if (mosi == BOARD_SPI2_MOSI_PIN) SPIClass(2);
+// #endif
+// }
+
+// void SPIClass::begin() {
+// // Init the SPI pins in the first begin call
+// if ((_currentSetting->spi_d == LPC_SSP0 && spiInitialised[0] == false) ||
+// (_currentSetting->spi_d == LPC_SSP1 && spiInitialised[1] == false)) {
+// pin_t sck, miso, mosi;
+// if (_currentSetting->spi_d == LPC_SSP0) {
+// sck = BOARD_SPI1_SCK_PIN;
+// miso = BOARD_SPI1_MISO_PIN;
+// mosi = BOARD_SPI1_MOSI_PIN;
+// spiInitialised[0] = true;
+// }
+// else if (_currentSetting->spi_d == LPC_SSP1) {
+// sck = BOARD_SPI2_SCK_PIN;
+// miso = BOARD_SPI2_MISO_PIN;
+// mosi = BOARD_SPI2_MOSI_PIN;
+// spiInitialised[1] = true;
+// }
+// PINSEL_CFG_Type PinCfg; // data structure to hold init values
+// PinCfg.Funcnum = 2;
+// PinCfg.OpenDrain = 0;
+// PinCfg.Pinmode = 0;
+// PinCfg.Pinnum = LPC176x::pin_bit(sck);
+// PinCfg.Portnum = LPC176x::pin_port(sck);
+// PINSEL_ConfigPin(&PinCfg);
+// SET_OUTPUT(sck);
+
+// PinCfg.Pinnum = LPC176x::pin_bit(miso);
+// PinCfg.Portnum = LPC176x::pin_port(miso);
+// PINSEL_ConfigPin(&PinCfg);
+// SET_INPUT(miso);
+
+// PinCfg.Pinnum = LPC176x::pin_bit(mosi);
+// PinCfg.Portnum = LPC176x::pin_port(mosi);
+// PINSEL_ConfigPin(&PinCfg);
+// SET_OUTPUT(mosi);
+// }
+
+// updateSettings();
+// SSP_Cmd(_currentSetting->spi_d, ENABLE); // start SSP running
+// }
+
+// void SPIClass::beginTransaction(const SPISettings &cfg) {
+// setBitOrder(cfg.bitOrder);
+// setDataMode(cfg.dataMode);
+// setDataSize(cfg.dataSize);
+// //setClockDivider(determine_baud_rate(_currentSetting->spi_d, settings.clock));
+// begin();
+// }
+
+// uint8_t SPIClass::transfer(const uint16_t b) {
+// // Send and receive a single byte
+// SSP_ReceiveData(_currentSetting->spi_d); // read any previous data
+// SSP_SendData(_currentSetting->spi_d, b);
+// waitSpiTxEnd(_currentSetting->spi_d); // wait for it to finish
+// return SSP_ReceiveData(_currentSetting->spi_d);
+// }
+
+// uint16_t SPIClass::transfer16(const uint16_t data) {
+// return (transfer((data >> 8) & 0xFF) << 8) | (transfer(data & 0xFF) & 0xFF);
+// }
+
+// void SPIClass::end() {
+// // Neither is needed for Marlin
+// //SSP_Cmd(_currentSetting->spi_d, DISABLE);
+// //SSP_DeInit(_currentSetting->spi_d);
+// }
+
+// void SPIClass::send(uint8_t data) {
+// SSP_SendData(_currentSetting->spi_d, data);
+// }
+
+// void SPIClass::dmaSend(void *buf, uint16_t length, bool minc) {
+// //TODO: LPC dma can only write 0xFFF bytes at once.
+// GPDMA_Channel_CFG_Type GPDMACfg;
+
+// /* Configure GPDMA channel 0 -------------------------------------------------------------*/
+// /* DMA Channel 0 */
+// GPDMACfg.ChannelNum = 0;
+// // Source memory
+// GPDMACfg.SrcMemAddr = (uint32_t)buf;
+// // Destination memory - Not used
+// GPDMACfg.DstMemAddr = 0;
+// // Transfer size
+// GPDMACfg.TransferSize = length;
+// // Transfer width
+// GPDMACfg.TransferWidth = (_currentSetting->dataSize == DATA_SIZE_16BIT) ? GPDMA_WIDTH_HALFWORD : GPDMA_WIDTH_BYTE;
+// // Transfer type
+// GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_M2P;
+// // Source connection - unused
+// GPDMACfg.SrcConn = 0;
+// // Destination connection
+// GPDMACfg.DstConn = (_currentSetting->spi_d == LPC_SSP0) ? GPDMA_CONN_SSP0_Tx : GPDMA_CONN_SSP1_Tx;
+
+// GPDMACfg.DMALLI = 0;
+
+// // Enable dma on SPI
+// SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, ENABLE);
+
+// // Only increase memory if minc is true
+// GPDMACfg.MemoryIncrease = (minc ? GPDMA_DMACCxControl_SI : 0);
+
+// // Setup channel with given parameter
+// GPDMA_Setup(&GPDMACfg);
+
+// // Enable DMA
+// GPDMA_ChannelCmd(0, ENABLE);
+
+// // Wait for data transfer
+// while (!GPDMA_IntGetStatus(GPDMA_STAT_RAWINTTC, 0) && !GPDMA_IntGetStatus(GPDMA_STAT_RAWINTERR, 0)) { }
+
+// // Clear err and int
+// GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0);
+// GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 0);
+
+// // Disable DMA
+// GPDMA_ChannelCmd(0, DISABLE);
+
+// waitSpiTxEnd(_currentSetting->spi_d);
+
+// SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, DISABLE);
+// }
+
+// uint16_t SPIClass::read() {
+// return SSP_ReceiveData(_currentSetting->spi_d);
+// }
+
+// void SPIClass::read(uint8_t *buf, uint32_t len) {
+// for (uint16_t i = 0; i < len; i++) buf[i] = transfer(0xFF);
+// }
+
+// void SPIClass::setClock(uint32_t clock) { _currentSetting->clock = clock; }
+
+// void SPIClass::setModule(uint8_t device) { _currentSetting = &_settings[device - 1]; } // SPI channels are called 1, 2, and 3 but the array is zero-indexed
+
+// void SPIClass::setBitOrder(uint8_t bitOrder) { _currentSetting->bitOrder = bitOrder; }
+
+// void SPIClass::setDataMode(uint8_t dataMode) { _currentSetting->dataMode = dataMode; }
+
+// void SPIClass::setDataSize(uint32_t dataSize) { _currentSetting->dataSize = dataSize; }
+
+// /**
+// * Set up/tear down
+// */
+// void SPIClass::updateSettings() {
+// //SSP_DeInit(_currentSetting->spi_d); //todo: need force de init?!
+
+// // Divide PCLK by 2 for SSP0
+// //CLKPWR_SetPCLKDiv(_currentSetting->spi_d == LPC_SSP0 ? CLKPWR_PCLKSEL_SSP0 : CLKPWR_PCLKSEL_SSP1, CLKPWR_PCLKSEL_CCLK_DIV_2);
+
+// SSP_CFG_Type HW_SPI_init; // data structure to hold init values
+// SSP_ConfigStructInit(&HW_SPI_init); // set values for SPI mode
+// HW_SPI_init.ClockRate = _currentSetting->clock;
+// HW_SPI_init.Databit = _currentSetting->dataSize;
+
+// /**
+// * SPI Mode CPOL CPHA Shift SCK-edge Capture SCK-edge
+// * 0 0 0 Falling Rising
+// * 1 0 1 Rising Falling
+// * 2 1 0 Rising Falling
+// * 3 1 1 Falling Rising
+// */
+// switch (_currentSetting->dataMode) {
+// case SPI_MODE0:
+// HW_SPI_init.CPHA = SSP_CPHA_FIRST;
+// HW_SPI_init.CPOL = SSP_CPOL_HI;
+// break;
+// case SPI_MODE1:
+// HW_SPI_init.CPHA = SSP_CPHA_SECOND;
+// HW_SPI_init.CPOL = SSP_CPOL_HI;
+// break;
+// case SPI_MODE2:
+// HW_SPI_init.CPHA = SSP_CPHA_FIRST;
+// HW_SPI_init.CPOL = SSP_CPOL_LO;
+// break;
+// case SPI_MODE3:
+// HW_SPI_init.CPHA = SSP_CPHA_SECOND;
+// HW_SPI_init.CPOL = SSP_CPOL_LO;
+// break;
+// default:
+// break;
+// }
+
+// // TODO: handle bitOrder
+// SSP_Init(_currentSetting->spi_d, &HW_SPI_init); // puts the values into the proper bits in the SSP0 registers
+// }
+
+// #if SD_MISO_PIN == BOARD_SPI1_MISO_PIN
+// SPIClass SPI(1);
+// #elif SD_MISO_PIN == BOARD_SPI2_MISO_PIN
+// SPIClass SPI(2);
+// #endif
+
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/LPC4078/MarlinSPI.h b/Marlin/src/HAL/LPC4078/MarlinSPI.h
new file mode 100644
index 0000000000..fab245f904
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/MarlinSPI.h
@@ -0,0 +1,45 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+#include
+
+/**
+ * Marlin currently requires 3 SPI classes:
+ *
+ * SPIClass:
+ * This class is normally provided by frameworks and has a semi-default interface.
+ * This is needed because some libraries reference it globally.
+ *
+ * SPISettings:
+ * Container for SPI configs for SPIClass. As above, libraries may reference it globally.
+ *
+ * These two classes are often provided by frameworks so we cannot extend them to add
+ * useful methods for Marlin.
+ *
+ * MarlinSPI:
+ * Provides the default SPIClass interface plus some Marlin goodies such as a simplified
+ * interface for SPI DMA transfer.
+ *
+ */
+
+using MarlinSPI = SPIClass;
diff --git a/Marlin/src/HAL/LPC4078/MarlinSerial.cpp b/Marlin/src/HAL/LPC4078/MarlinSerial.cpp
new file mode 100644
index 0000000000..d18ceedf7e
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/MarlinSerial.cpp
@@ -0,0 +1,78 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#ifdef TARGET_LPC4078
+
+#include "MarlinSerial.h"
+
+#include "../../inc/MarlinConfig.h"
+
+MarlinCDCSerial MCDCSerial0;
+
+#define MarlinSerial(ID) \
+ MarlinSerial _MSerial##ID(ID); \
+ MSerialT MSerial##ID(true, _MSerial##ID)
+
+#if USING_HW_SERIAL0
+ MarlinSerial(0);
+#endif
+#if USING_HW_SERIAL1
+ MarlinSerial(1);
+#endif
+#if USING_HW_SERIAL2
+ MarlinSerial(2);
+#endif
+#if USING_HW_SERIAL3
+ MarlinSerial(3);
+#endif
+
+#if ENABLED(EMERGENCY_PARSER)
+
+ bool MarlinSerial::recv_callback(const char c) {
+ // Need to figure out which serial port we are and react in consequence (Marlin does not have CONTAINER_OF macro)
+ if (false) {}
+ #if USING_HW_SERIAL0
+ else if (this == &_MSerial0) emergency_parser.update(MSerial0.emergency_state, c);
+ #endif
+ #if USING_HW_SERIAL1
+ else if (this == &_MSerial1) emergency_parser.update(MSerial1.emergency_state, c);
+ #endif
+ #if USING_HW_SERIAL2
+ else if (this == &_MSerial2) emergency_parser.update(MSerial2.emergency_state, c);
+ #endif
+ #if USING_HW_SERIAL3
+ else if (this == &_MSerial3) emergency_parser.update(MSerial3.emergency_state, c);
+ #endif
+ return true;
+ }
+
+ #include "../../feature/e_parser.h"
+
+ EmergencyParser::State emergency_state;
+
+ bool CDC_RecvCallback(const char c) {
+ emergency_parser.update(emergency_state, c);
+ return true;
+ }
+
+#endif
+
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/LPC4078/MarlinSerial.h b/Marlin/src/HAL/LPC4078/MarlinSerial.h
new file mode 100644
index 0000000000..60869e76c9
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/MarlinSerial.h
@@ -0,0 +1,108 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+#include
+#include
+#include
+
+#include
+
+#include "../../inc/MarlinConfigPre.h"
+#if ENABLED(EMERGENCY_PARSER)
+ #include "../../feature/e_parser.h"
+#endif
+#include "../../core/serial_hook.h"
+
+#ifndef SERIAL_PORT
+ #define SERIAL_PORT 0
+#endif
+#ifndef RX_BUFFER_SIZE
+ #define RX_BUFFER_SIZE 128
+#endif
+#ifndef TX_BUFFER_SIZE
+ #define TX_BUFFER_SIZE 32
+#endif
+
+class MarlinCDCSerial : public HardwareSerial {
+ public:
+ MarlinCDCSerial() {}
+ void begin(unsigned long baudrate) override {}
+ void begin(unsigned long baudrate, uint16_t config) override { }
+ void end() override { }
+ int available() override {
+ return MCUI::CDCSerial0::available();
+ }
+ int peek() override { char c = 0; return MCUI::CDCSerial0::peek((uint8_t*)&c)? c : -1; }
+ int read() override { char c = 0; return MCUI::CDCSerial0::read((uint8_t*)&c, 1)? c : -1; }
+ void flush() override {};
+ size_t write(uint8_t c) override { return write(&c, 1); }
+ size_t write(const uint8_t *buffer, size_t size) override { return MCUI::CDCSerial0::connected() ? MCUI::CDCSerial0::write(buffer, size) : 0; }
+ using Print::write;
+ operator bool() override { return true; }
+};
+extern MarlinCDCSerial MCDCSerial0;
+
+class MarlinSerial : public HardwareSerial {
+ public:
+ MarlinSerial(const uint32_t uart_id) : uart_device(uart_id) {}
+ void begin(unsigned long baudrate) override {
+ uart_device.configure_pins(P0_02, P0_03);
+ uart_device.init({ .baud = baudrate });
+ #if ENABLED(EMERGENCY_PARSER)
+ uart_device.set_rx_callback([this](char rx_value){ return this->recv_callback(rx_value); } );
+ #endif
+ }
+ void begin(unsigned long baudrate, uint16_t config) override {
+ begin(baudrate);
+ }
+ void end() override { }
+ int available() override {
+ return uart_device.rx_available();
+ }
+ int peek() override { char c = 0; return uart_device.peek(&c)? c : -1; }
+ int read() override { char c = 0; return uart_device.read(&c)? c : -1; }
+ void flush() override {};
+ size_t write(uint8_t c) override { return write(&c, 1); }
+ size_t write(const uint8_t *buffer, size_t size) override { return uart_device.write((const char *)buffer, size); }
+ using Print::write; // pull in write(str) and write(buf, size) from Print
+ operator bool() override { return true; }
+
+ bool recv_callback(char value);
+ private:
+ MCUI::BufferedUARTC uart_device;
+};
+
+// On LPC176x framework, HardwareSerial does not implement the same interface as Arduino's Serial, so overloads
+// of 'available' and 'read' method are not used in this multiple inheritance scenario.
+// Instead, use a ForwardSerial here that adapts the interface.
+typedef ForwardSerial1Class MSerialT;
+extern MSerialT MSerial0;
+extern MSerialT MSerial1;
+extern MSerialT MSerial2;
+extern MSerialT MSerial3;
+
+// Consequently, we can't use a RuntimeSerial either. The workaround would be to use
+// a RuntimeSerial> type here. Ignore for now until it's actually required.
+#if ENABLED(SERIAL_RUNTIME_HOOK)
+ #error "SERIAL_RUNTIME_HOOK is not yet supported for LPC176x."
+#endif
diff --git a/Marlin/src/HAL/LPC4078/MinSerial.cpp b/Marlin/src/HAL/LPC4078/MinSerial.cpp
new file mode 100644
index 0000000000..809a06b85d
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/MinSerial.cpp
@@ -0,0 +1,51 @@
+/**
+ * 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 .
+ *
+ */
+#ifdef TARGET_LPC4078
+
+#include "../../inc/MarlinConfig.h"
+#include "HAL.h"
+
+#if ENABLED(POSTMORTEM_DEBUGGING)
+
+#include "../shared/MinSerial.h"
+#include
+
+static void TX(char c) { _DBC(c); }
+void install_min_serial() { HAL_min_serial_out = &TX; }
+
+#if DISABLED(DYNAMIC_VECTORTABLE)
+extern "C" {
+ __attribute__((naked)) void JumpHandler_ASM() {
+ __asm__ __volatile__ (
+ "b CommonHandler_ASM\n"
+ );
+ }
+ void __attribute__((naked, alias("JumpHandler_ASM"))) HardFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) BusFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) UsageFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) MemManage_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) NMI_Handler();
+}
+#endif
+
+#endif // POSTMORTEM_DEBUGGING
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/LPC4078/Servo.h b/Marlin/src/HAL/LPC4078/Servo.h
new file mode 100644
index 0000000000..f02f503a67
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/Servo.h
@@ -0,0 +1,69 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+/**
+ * servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
+ * Copyright (c) 2009 Michael Margolis. All right reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#pragma once
+
+/**
+ * Based on "servo.h - Interrupt driven Servo library for Arduino using 16 bit timers -
+ * Version 2 Copyright (c) 2009 Michael Margolis. All right reserved.
+ *
+ * The only modification was to update/delete macros to match the LPC176x.
+ */
+
+#include
+
+class libServo: public Servo {
+ public:
+ void move(const int value) {
+ constexpr uint16_t servo_delay[] = SERVO_DELAY;
+ static_assert(COUNT(servo_delay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
+
+ if (attach(servo_info[servoIndex].Pin.nbr) >= 0) { // try to reattach
+ write(value);
+ safe_delay(servo_delay[servoIndex]); // delay to allow servo to reach position
+ TERN_(DEACTIVATE_SERVOS_AFTER_MOVE, detach());
+ }
+
+ }
+};
+
+class libServo;
+typedef libServo hal_servo_t;
diff --git a/Marlin/src/HAL/LPC4078/SoftwareSPI.cpp b/Marlin/src/HAL/LPC4078/SoftwareSPI.cpp
new file mode 100644
index 0000000000..156f0acc20
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/SoftwareSPI.cpp
@@ -0,0 +1,47 @@
+#ifdef TARGET_LPC4078
+
+#include
+#include "SoftwareSPI.h"
+
+#include
+
+uint8_t swSpiTransfer(uint8_t b, const uint8_t spi_speed, const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin) {
+ for (uint8_t i = 0; i < 8; i++) {
+ if (spi_speed == 0) {
+ MCUI::gpio_set(mosi_pin, !!(b & 0x80));
+ MCUI::gpio_set(sck_pin, HIGH);
+ b <<= 1;
+ if (miso_pin >= 0 && MCUI::gpio_get(miso_pin)) b |= 1;
+ MCUI::gpio_set(sck_pin, LOW);
+ }
+ else {
+ const uint8_t state = (b & 0x80) ? HIGH : LOW;
+ for (uint8_t j = 0; j < spi_speed; j++)
+ MCUI::gpio_set(mosi_pin, state);
+
+ for (uint8_t j = 0; j < spi_speed + (miso_pin >= 0 ? 0 : 1); j++)
+ MCUI::gpio_set(sck_pin, HIGH);
+
+ b <<= 1;
+ if (miso_pin >= 0 && MCUI::gpio_get(miso_pin)) b |= 1;
+
+ for (uint8_t j = 0; j < spi_speed; j++)
+ MCUI::gpio_set(sck_pin, LOW);
+ }
+ }
+ return b;
+}
+
+void swSpiBegin(const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin) {
+ pinMode(sck_pin, OUTPUT);
+ if (MCUI::pin_is_valid(miso_pin)) pinMode(miso_pin, INPUT);
+ pinMode(mosi_pin, OUTPUT);
+}
+
+uint8_t swSpiInit(const uint8_t spiRate, const pin_t sck_pin, const pin_t mosi_pin) {
+ MCUI::gpio_set(mosi_pin, HIGH);
+ MCUI::gpio_set(sck_pin, LOW);
+ return (SystemCoreClock == 120000000 ? 44 : 38) / std::pow(2, 6 - std::min(spiRate, (uint8_t)6));
+}
+
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/LPC4078/SoftwareSPI.h b/Marlin/src/HAL/LPC4078/SoftwareSPI.h
new file mode 100644
index 0000000000..7b4fe79b44
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/SoftwareSPI.h
@@ -0,0 +1,5 @@
+#include
+
+uint8_t swSpiTransfer(uint8_t b, const uint8_t spi_speed, const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin);
+void swSpiBegin(const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin);
+uint8_t swSpiInit(const uint8_t spiRate, const pin_t sck_pin, const pin_t mosi_pin);
diff --git a/Marlin/src/HAL/LPC4078/eeprom_internal.cpp b/Marlin/src/HAL/LPC4078/eeprom_internal.cpp
new file mode 100644
index 0000000000..69e2e15592
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/eeprom_internal.cpp
@@ -0,0 +1,116 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#ifdef TARGET_LPC4078
+
+/**
+ * Emulate EEPROM storage using Flash Memory
+ *
+ * Use a single 32K flash sector to store EEPROM data. To reduce the
+ * number of erase operations a simple "leveling" scheme is used that
+ * maintains a number of EEPROM "slots" within the larger flash sector.
+ * Each slot is used in turn and the entire sector is only erased when all
+ * slots have been used.
+ *
+ * A simple RAM image is used to hold the EEPROM data during I/O operations
+ * and this is flushed to the next available slot when an update is complete.
+ * If RAM usage becomes an issue we could store this image in one of the two
+ * 16Kb I/O buffers (intended to hold DMA USB and Ethernet data, but currently
+ * unused).
+ */
+#include "../../inc/MarlinConfig.h"
+
+#include "../shared/eeprom_api.h"
+
+//#include
+
+#ifndef MARLIN_EEPROM_SIZE
+ #define MARLIN_EEPROM_SIZE 4032 // 4KB
+#endif
+
+size_t PersistentStore::capacity() { return 4032; }
+
+constexpr uint32_t page_size = MCUI::EEPROM::page_size;
+uint32_t buffered_page = 0;
+uint8_t page_buffer[page_size];
+bool buffered_page_dirty = false;
+
+bool PersistentStore::access_start() {
+ MCUI::EEPROM::init();
+ MCUI::EEPROM::read_page(buffered_page, page_buffer, page_size);
+ return true;
+}
+
+bool PersistentStore::access_finish() {
+ if (buffered_page_dirty) {
+ MCUI::EEPROM::write_page(buffered_page, page_buffer, page_size);
+ }
+ return true;
+}
+
+bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
+ uint32_t address = pos;
+ //printf("Marlin::eeprom::write(pos = %d, size = %d)\n", pos, size);
+ uint32_t value_index = 0;
+ for (uint32_t addr = address; addr < address + size; ++addr) {
+ uint32_t page_address = addr & 0xFFFFFFC0;
+ if (page_address != buffered_page) {
+ //printf("Marlin::eeprom::write(@%ld):: page change new(%ld) != current(%d)\n",addr, page_address, buffered_page);
+ if (buffered_page_dirty == true) MCUI::EEPROM::write_page(buffered_page, page_buffer, page_size);
+ buffered_page = page_address;
+ buffered_page_dirty = false;
+ MCUI::EEPROM::read_page(buffered_page, page_buffer, page_size);
+ }
+ page_buffer[addr & ~0xFFFFFFC0] = value[value_index++];
+ buffered_page_dirty = true;
+ }
+
+ pos += size;
+ crc16(crc, value, size);
+
+ return false; // return true for any error
+}
+
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+ uint32_t address = pos;
+ //printf("Marlin::eeprom::read(pos = %d, size = %d, writing = %d)\n", pos, size, writing);
+ uint32_t value_index = 0;
+ for (uint32_t addr = address; addr < address + size; ++addr) {
+ uint32_t page_address = addr & 0xFFFFFFC0;
+ if (page_address != buffered_page) {
+ if (buffered_page_dirty) {
+ MCUI::EEPROM::write_page(buffered_page, page_buffer, page_size);
+ buffered_page_dirty = false;
+ }
+ buffered_page = page_address;
+ MCUI::EEPROM::read_page(buffered_page, page_buffer, page_size);
+ }
+ if (writing) value[value_index++] = page_buffer[addr & ~0xFFFFFFC0];
+ else crc16(crc, &page_buffer[addr & ~0xFFFFFFC0], 1);
+ }
+
+ if (writing) crc16(crc, value, size);
+ pos += size;
+
+ return false; // return true for any error
+}
+
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/LPC4078/endstop_interrupts.h b/Marlin/src/HAL/LPC4078/endstop_interrupts.h
new file mode 100644
index 0000000000..e4ac17f608
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/endstop_interrupts.h
@@ -0,0 +1,191 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+/**
+ * Endstop Interrupts
+ *
+ * Without endstop interrupts the endstop pins must be polled continually in
+ * the temperature-ISR via endstops.update(), most of the time finding no change.
+ * With this feature endstops.update() is called only when we know that at
+ * least one endstop has changed state, saving valuable CPU cycles.
+ *
+ * This feature only works when all used endstop pins can generate an 'external interrupt'.
+ *
+ * Test whether pins issue interrupts on your board by flashing 'pin_interrupt_test.ino'.
+ * (Located in Marlin/buildroot/share/pin_interrupt_test/pin_interrupt_test.ino)
+ */
+
+#include "../../module/endstops.h"
+
+// One ISR for all EXT-Interrupts
+void endstop_ISR() { endstops.update(); }
+
+void setup_endstop_interrupts() {
+ #define _ATTACH(P) attachInterrupt(digitalPinToInterrupt(P), endstop_ISR, CHANGE)
+ #define LPC1768_PIN_INTERRUPT_M(pin) ((pin >> 0x5 & 0x7) == 0 || (pin >> 0x5 & 0x7) == 2)
+
+ #if HAS_X_MAX
+ #if !LPC1768_PIN_INTERRUPT_M(X_MAX_PIN)
+ #error "X_MAX_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
+ #endif
+ _ATTACH(X_MAX_PIN);
+ #endif
+ #if HAS_X_MIN
+ #if !LPC1768_PIN_INTERRUPT_M(X_MIN_PIN)
+ #error "X_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
+ #endif
+ _ATTACH(X_MIN_PIN);
+ #endif
+ #if HAS_Y_MAX
+ #if !LPC1768_PIN_INTERRUPT_M(Y_MAX_PIN)
+ #error "Y_MAX_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
+ #endif
+ _ATTACH(Y_MAX_PIN);
+ #endif
+ #if HAS_Y_MIN
+ #if !LPC1768_PIN_INTERRUPT_M(Y_MIN_PIN)
+ #error "Y_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
+ #endif
+ _ATTACH(Y_MIN_PIN);
+ #endif
+ #if HAS_Z_MAX
+ #if !LPC1768_PIN_INTERRUPT_M(Z_MAX_PIN)
+ #error "Z_MAX_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
+ #endif
+ _ATTACH(Z_MAX_PIN);
+ #endif
+ #if HAS_Z_MIN
+ #if !LPC1768_PIN_INTERRUPT_M(Z_MIN_PIN)
+ #error "Z_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
+ #endif
+ _ATTACH(Z_MIN_PIN);
+ #endif
+ #if HAS_Z2_MAX
+ #if !LPC1768_PIN_INTERRUPT_M(Z2_MAX_PIN)
+ #error "Z2_MAX_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
+ #endif
+ _ATTACH(Z2_MAX_PIN);
+ #endif
+ #if HAS_Z2_MIN
+ #if !LPC1768_PIN_INTERRUPT_M(Z2_MIN_PIN)
+ #error "Z2_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
+ #endif
+ _ATTACH(Z2_MIN_PIN);
+ #endif
+ #if HAS_Z3_MAX
+ #if !LPC1768_PIN_INTERRUPT_M(Z3_MAX_PIN)
+ #error "Z3_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
+ #endif
+ _ATTACH(Z3_MAX_PIN);
+ #endif
+ #if HAS_Z3_MIN
+ #if !LPC1768_PIN_INTERRUPT_M(Z3_MIN_PIN)
+ #error "Z3_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
+ #endif
+ _ATTACH(Z3_MIN_PIN);
+ #endif
+ #if HAS_Z4_MAX
+ #if !LPC1768_PIN_INTERRUPT_M(Z4_MAX_PIN)
+ #error "Z4_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
+ #endif
+ _ATTACH(Z4_MAX_PIN);
+ #endif
+ #if HAS_Z4_MIN
+ #if !LPC1768_PIN_INTERRUPT_M(Z4_MIN_PIN)
+ #error "Z4_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
+ #endif
+ _ATTACH(Z4_MIN_PIN);
+ #endif
+ #if HAS_Z_MIN_PROBE_PIN
+ #if !LPC1768_PIN_INTERRUPT_M(Z_MIN_PROBE_PIN)
+ #error "Z_MIN_PROBE_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
+ #endif
+ _ATTACH(Z_MIN_PROBE_PIN);
+ #endif
+ #if HAS_I_MAX
+ #if !LPC1768_PIN_INTERRUPT_M(I_MAX_PIN)
+ #error "I_MAX_PIN is not INTERRUPT-capable."
+ #endif
+ _ATTACH(I_MAX_PIN);
+ #elif HAS_I_MIN
+ #if !LPC1768_PIN_INTERRUPT_M(I_MIN_PIN)
+ #error "I_MIN_PIN is not INTERRUPT-capable."
+ #endif
+ _ATTACH(I_MIN_PIN);
+ #endif
+ #if HAS_J_MAX
+ #if !LPC1768_PIN_INTERRUPT_M(J_MAX_PIN)
+ #error "J_MAX_PIN is not INTERRUPT-capable."
+ #endif
+ _ATTACH(J_MAX_PIN);
+ #elif HAS_J_MIN
+ #if !LPC1768_PIN_INTERRUPT_M(J_MIN_PIN)
+ #error "J_MIN_PIN is not INTERRUPT-capable."
+ #endif
+ _ATTACH(J_MIN_PIN);
+ #endif
+ #if HAS_K_MAX
+ #if !LPC1768_PIN_INTERRUPT_M(K_MAX_PIN)
+ #error "K_MAX_PIN is not INTERRUPT-capable."
+ #endif
+ _ATTACH(K_MAX_PIN);
+ #elif HAS_K_MIN
+ #if !LPC1768_PIN_INTERRUPT_M(K_MIN_PIN)
+ #error "K_MIN_PIN is not INTERRUPT-capable."
+ #endif
+ _ATTACH(K_MIN_PIN);
+ #endif
+ #if HAS_U_MAX
+ #if !LPC1768_PIN_INTERRUPT_M(U_MAX_PIN)
+ #error "U_MAX_PIN is not INTERRUPT-capable."
+ #endif
+ _ATTACH(U_MAX_PIN);
+ #elif HAS_U_MIN
+ #if !LPC1768_PIN_INTERRUPT_M(U_MIN_PIN)
+ #error "U_MIN_PIN is not INTERRUPT-capable."
+ #endif
+ _ATTACH(U_MIN_PIN);
+ #endif
+ #if HAS_V_MAX
+ #if !LPC1768_PIN_INTERRUPT_M(V_MAX_PIN)
+ #error "V_MAX_PIN is not INTERRUPT-capable."
+ #endif
+ _ATTACH(V_MAX_PIN);
+ #elif HAS_V_MIN
+ #if !LPC1768_PIN_INTERRUPT_M(V_MIN_PIN)
+ #error "V_MIN_PIN is not INTERRUPT-capable."
+ #endif
+ _ATTACH(V_MIN_PIN);
+ #endif
+ #if HAS_W_MAX
+ #if !LPC1768_PIN_INTERRUPT_M(W_MAX_PIN)
+ #error "W_MAX_PIN is not INTERRUPT-capable."
+ #endif
+ _ATTACH(W_MAX_PIN);
+ #elif HAS_W_MIN
+ #if !LPC1768_PIN_INTERRUPT_M(W_MIN_PIN)
+ #error "W_MIN_PIN is not INTERRUPT-capable."
+ #endif
+ _ATTACH(W_MIN_PIN);
+ #endif
+}
diff --git a/Marlin/src/HAL/LPC4078/fast_pwm.cpp b/Marlin/src/HAL/LPC4078/fast_pwm.cpp
new file mode 100644
index 0000000000..d202a49d28
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/fast_pwm.cpp
@@ -0,0 +1,37 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#ifdef TARGET_LPC4078
+
+#include "../../inc/MarlinConfig.h"
+#include
+
+void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
+ if (!MCUI::pin_is_valid(pin)) return;
+ if (MCUI::pwm_attach_pin(pin))
+ MCUI::pwm_write_ratio(pin, invert ? 1.0f - (float)v / v_size : (float)v / v_size); // map 1-254 onto PWM range
+}
+
+void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
+ MCUI::pwm_set_frequency(pin, f_desired);
+}
+
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/LPC4078/fastio.h b/Marlin/src/HAL/LPC4078/fastio.h
new file mode 100644
index 0000000000..9e384d6cf6
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/fastio.h
@@ -0,0 +1,120 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+/**
+ * Fast I/O Routines for LPC1768/9
+ * Use direct port manipulation to save scads of processor time.
+ * Contributed by Triffid_Hunter and modified by Kliment, thinkyhead, Bob-the-Kuhn, et.al.
+ */
+
+/**
+ * Description: Fast IO functions LPC1768
+ *
+ * For TARGET LPC1768
+ */
+
+#include "../shared/Marduino.h"
+#include
+
+#define PWM_PIN(P) true // all pins are software PWM capable
+
+#define LPC_PIN(pin) MCUI::gpio_pin(pin)
+#define LPC_GPIO(port) MCUI::gpio_port(port)
+
+#define SET_DIR_INPUT(IO) MCUI::gpio_set_input(IO)
+#define SET_DIR_OUTPUT(IO) MCUI::gpio_set_output(IO)
+
+#define SET_MODE(IO, mode) pinMode(IO, mode)
+
+#define WRITE_PIN_SET(IO) MCUI::gpio_set(IO)
+#define WRITE_PIN_CLR(IO) MCUI::gpio_clear(IO)
+
+#define READ_PIN(IO) MCUI::gpio_get(IO)
+#define WRITE_PIN(IO,V) MCUI::gpio_set(IO, V)
+
+/**
+ * Magic I/O routines
+ *
+ * Now you can simply SET_OUTPUT(STEP); WRITE(STEP, HIGH); WRITE(STEP, LOW);
+ *
+ * Why double up on these macros? see https://gcc.gnu.org/onlinedocs/gcc-4.8.5/cpp/Stringification.html
+ */
+
+/// Read a pin
+#define _READ(IO) READ_PIN(IO)
+
+/// Write to a pin
+#define _WRITE(IO,V) WRITE_PIN(IO,V)
+
+/// toggle a pin
+#define _TOGGLE(IO) MCUI::gpio_toggle(IO)
+
+/// set pin as input
+#define _SET_INPUT(IO) SET_DIR_INPUT(IO)
+
+/// set pin as output
+#define _SET_OUTPUT(IO) SET_DIR_OUTPUT(IO)
+
+/// set pin as input with pullup mode
+#define _PULLUP(IO,V) pinMode(IO, (V) ? INPUT_PULLUP : INPUT)
+
+/// set pin as input with pulldown mode
+#define _PULLDOWN(IO,V) pinMode(IO, (V) ? INPUT_PULLDOWN : INPUT)
+
+/// check if pin is an input
+#define _IS_INPUT(IO) (!MCUI::gpio_get_dir(IO))
+
+/// check if pin is an output
+#define _IS_OUTPUT(IO) (MCUI::gpio_get_dir(IO))
+
+/// Read a pin wrapper
+#define READ(IO) _READ(IO)
+
+/// Write to a pin wrapper
+#define WRITE(IO,V) _WRITE(IO,V)
+
+/// toggle a pin wrapper
+#define TOGGLE(IO) _TOGGLE(IO)
+
+/// set pin as input wrapper
+#define SET_INPUT(IO) _SET_INPUT(IO)
+/// set pin as input with pullup wrapper
+#define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _PULLUP(IO, HIGH); }while(0)
+/// set pin as input with pulldown wrapper
+#define SET_INPUT_PULLDOWN(IO) do{ _SET_INPUT(IO); _PULLDOWN(IO, HIGH); }while(0)
+/// set pin as output wrapper - reads the pin and sets the output to that value
+#define SET_OUTPUT(IO) do{ _WRITE(IO, _READ(IO)); _SET_OUTPUT(IO); }while(0)
+// set pin as PWM
+#define SET_PWM SET_OUTPUT
+
+/// check if pin is an input wrapper
+#define IS_INPUT(IO) _IS_INPUT(IO)
+/// check if pin is an output wrapper
+#define IS_OUTPUT(IO) _IS_OUTPUT(IO)
+
+// Shorthand
+#define OUT_WRITE(IO,V) do{ SET_OUTPUT(IO); WRITE(IO,V); }while(0)
+
+// digitalRead/Write wrappers
+#define extDigitalRead(IO) digitalRead(IO)
+#define extDigitalWrite(IO,V) digitalWrite(IO,V)
diff --git a/Marlin/src/HAL/LPC4078/inc/Conditionals_LCD.h b/Marlin/src/HAL/LPC4078/inc/Conditionals_LCD.h
new file mode 100644
index 0000000000..5f1c4b1601
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/inc/Conditionals_LCD.h
@@ -0,0 +1,22 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
diff --git a/Marlin/src/HAL/LPC4078/inc/Conditionals_adv.h b/Marlin/src/HAL/LPC4078/inc/Conditionals_adv.h
new file mode 100644
index 0000000000..8e7cab185f
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/inc/Conditionals_adv.h
@@ -0,0 +1,26 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+#if DISABLED(NO_SD_HOST_DRIVE)
+ #define HAS_SD_HOST_DRIVE 1
+#endif
diff --git a/Marlin/src/HAL/LPC4078/inc/Conditionals_post.h b/Marlin/src/HAL/LPC4078/inc/Conditionals_post.h
new file mode 100644
index 0000000000..865b71be7d
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/inc/Conditionals_post.h
@@ -0,0 +1,34 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+#if USE_FALLBACK_EEPROM
+ #define FLASH_EEPROM_EMULATION
+#elif ANY(I2C_EEPROM, SPI_EEPROM)
+ #define USE_SHARED_EEPROM 1
+#endif
+
+// LPC1768 boards seem to lose steps when saving to EEPROM during print (issue #20785)
+// TODO: Which other boards are incompatible?
+#if defined(MCU_LPC1768) && ENABLED(FLASH_EEPROM_EMULATION) && PRINTCOUNTER_SAVE_INTERVAL > 0
+ #define PRINTCOUNTER_SYNC 1
+#endif
diff --git a/Marlin/src/HAL/LPC4078/inc/SanityCheck.h b/Marlin/src/HAL/LPC4078/inc/SanityCheck.h
new file mode 100644
index 0000000000..f2f75e5854
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/inc/SanityCheck.h
@@ -0,0 +1,276 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+// #if PIO_PLATFORM_VERSION < 1001
+// #error "nxplpc-arduino-lpc176x package is out of date, Please update the PlatformIO platforms, frameworks and libraries. You may need to remove the platform and let it reinstall automatically."
+// #endif
+// #if PIO_FRAMEWORK_VERSION < 2006
+// #error "framework-arduino-lpc176x package is out of date, Please update the PlatformIO platforms, frameworks and libraries."
+// #endif
+
+/**
+ * Detect an old pins file by checking for old ADC pins values.
+ */
+#define _OLD_TEMP_PIN(P) PIN_EXISTS(P) && _CAT(P,_PIN) <= 7 && !WITHIN(_CAT(P,_PIN), TERN(LPC1768_IS_SKRV1_3, 0, 2), 3) // Include P0_00 and P0_01 for SKR V1.3 board
+#if _OLD_TEMP_PIN(TEMP_BED)
+ #error "TEMP_BED_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
+#elif _OLD_TEMP_PIN(TEMP_0)
+ #error "TEMP_0_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
+#elif _OLD_TEMP_PIN(TEMP_1)
+ #error "TEMP_1_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
+#elif _OLD_TEMP_PIN(TEMP_2)
+ #error "TEMP_2_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
+#elif _OLD_TEMP_PIN(TEMP_3)
+ #error "TEMP_3_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
+#elif _OLD_TEMP_PIN(TEMP_4)
+ #error "TEMP_4_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
+#elif _OLD_TEMP_PIN(TEMP_5)
+ #error "TEMP_5_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
+#elif _OLD_TEMP_PIN(TEMP_6)
+ #error "TEMP_6_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
+#elif _OLD_TEMP_PIN(TEMP_7)
+ #error "TEMP_7_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
+#endif
+#undef _OLD_TEMP_PIN
+
+/**
+ * Because PWM hardware channels all share the same frequency, along with the
+ * fallback software channels, FAST_PWM_FAN is incompatible with Servos.
+ */
+static_assert(!(NUM_SERVOS && ENABLED(FAST_PWM_FAN)), "BLTOUCH and Servos are incompatible with FAST_PWM_FAN on LPC176x boards.");
+
+#if SPINDLE_LASER_FREQUENCY
+ static_assert(!NUM_SERVOS, "BLTOUCH and Servos are incompatible with SPINDLE_LASER_FREQUENCY on LPC176x boards.");
+#endif
+
+/**
+ * Test LPC176x-specific configuration values for errors at compile-time.
+ */
+
+//#if ENABLED(SPINDLE_LASER_USE_PWM) && !(SPINDLE_LASER_PWM_PIN == 4 || SPINDLE_LASER_PWM_PIN == 6 || SPINDLE_LASER_PWM_PIN == 11)
+// #error "SPINDLE_LASER_PWM_PIN must use SERVO0, SERVO1 or SERVO3 connector"
+//#endif
+
+#if MB(RAMPS_14_RE_ARM_EFB, RAMPS_14_RE_ARM_EEB, RAMPS_14_RE_ARM_EFF, RAMPS_14_RE_ARM_EEF, RAMPS_14_RE_ARM_SF)
+ #if IS_RRD_FG_SC && HAS_DRIVER(TMC2130) && DISABLED(TMC_USE_SW_SPI)
+ #error "Re-ARM with REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER and TMC2130 requires TMC_USE_SW_SPI."
+ #endif
+#endif
+
+static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported on LPC176x.");
+
+/**
+ * Flag any serial port conflicts
+ *
+ * Port | TX | RX |
+ * --- | --- | --- |
+ * Serial | P0_02 | P0_03 |
+ * Serial1 | P0_15 | P0_16 |
+ * Serial2 | P0_10 | P0_11 |
+ * Serial3 | P0_00 | P0_01 |
+ */
+#define ANY_TX(N,V...) DO(IS_TX##N,||,V)
+#define ANY_RX(N,V...) DO(IS_RX##N,||,V)
+
+#if USING_HW_SERIAL0
+ #define IS_TX0(P) (P == P0_02)
+ #define IS_RX0(P) (P == P0_03)
+ #if IS_TX0(TMC_SW_MISO) || IS_RX0(TMC_SW_MOSI)
+ #error "Serial port pins (0) conflict with Trinamic SPI pins!"
+ #elif HAS_PRUSA_MMU1 && (IS_TX0(E_MUX1_PIN) || IS_RX0(E_MUX0_PIN))
+ #error "Serial port pins (0) conflict with Multi-Material-Unit multiplexer pins!"
+ #elif (AXIS_HAS_SPI(X) && IS_TX0(X_CS_PIN)) || (AXIS_HAS_SPI(Y) && IS_RX0(Y_CS_PIN))
+ #error "Serial port pins (0) conflict with X/Y axis SPI pins!"
+ #endif
+ #undef IS_TX0
+ #undef IS_RX0
+#endif
+
+#if USING_HW_SERIAL1
+ #define IS_TX1(P) (P == P0_15)
+ #define IS_RX1(P) (P == P0_16)
+ #define _IS_TX1_1 IS_TX1
+ #define _IS_RX1_1 IS_RX1
+ #if IS_TX1(TMC_SW_SCK)
+ #error "Serial port pins (1) conflict with other pins!"
+ #elif HAS_ROTARY_ENCODER
+ #if IS_TX1(BTN_EN2) || IS_RX1(BTN_EN1)
+ #error "Serial port pins (1) conflict with Encoder Buttons!"
+ #elif ANY_TX(1, SD_SCK_PIN, LCD_PINS_D4, DOGLCD_SCK, LCD_RESET_PIN, LCD_PINS_RS, SHIFT_CLK_PIN) \
+ || ANY_RX(1, LCD_SDSS, LCD_PINS_RS, SD_MISO_PIN, DOGLCD_A0, SD_SS_PIN, LCD_SDSS, DOGLCD_CS, LCD_RESET_PIN, LCD_BACKLIGHT_PIN)
+ #error "Serial port pins (1) conflict with LCD pins!"
+ #endif
+ #endif
+ #undef IS_TX1
+ #undef IS_RX1
+ #undef _IS_TX1_1
+ #undef _IS_RX1_1
+#endif
+
+#if USING_HW_SERIAL2
+ #define IS_TX2(P) (P == P0_10)
+ #define IS_RX2(P) (P == P0_11)
+ #define _IS_TX2_1 IS_TX2
+ #define _IS_RX2_1 IS_RX2
+ #if IS_TX2(X2_ENABLE_PIN) || ANY_RX(2, X2_DIR_PIN, X2_STEP_PIN) || (AXIS_HAS_SPI(X2) && IS_TX2(X2_CS_PIN))
+ #error "Serial port pins (2) conflict with X2 pins!"
+ #elif IS_TX2(Y2_ENABLE_PIN) || ANY_RX(2, Y2_DIR_PIN, Y2_STEP_PIN) || (AXIS_HAS_SPI(Y2) && IS_TX2(Y2_CS_PIN))
+ #error "Serial port pins (2) conflict with Y2 pins!"
+ #elif IS_TX2(Z2_ENABLE_PIN) || ANY_RX(2, Z2_DIR_PIN, Z2_STEP_PIN) || (AXIS_HAS_SPI(Z2) && IS_TX2(Z2_CS_PIN))
+ #error "Serial port pins (2) conflict with Z2 pins!"
+ #elif IS_TX2(Z3_ENABLE_PIN) || ANY_RX(2, Z3_DIR_PIN, Z3_STEP_PIN) || (AXIS_HAS_SPI(Z3) && IS_TX2(Z3_CS_PIN))
+ #error "Serial port pins (2) conflict with Z3 pins!"
+ #elif IS_TX2(Z4_ENABLE_PIN) || ANY_RX(2, Z4_DIR_PIN, Z4_STEP_PIN) || (AXIS_HAS_SPI(Z4) && IS_TX2(Z4_CS_PIN))
+ #error "Serial port pins (2) conflict with Z4 pins!"
+ #elif ANY_RX(2, X_DIR_PIN, Y_DIR_PIN)
+ #error "Serial port pins (2) conflict with other pins!"
+ #elif Y_HOME_TO_MIN && IS_TX2(Y_STOP_PIN)
+ #error "Serial port pins (2) conflict with Y endstop pin!"
+ #elif USES_Z_MIN_PROBE_PIN && IS_TX2(Z_MIN_PROBE_PIN)
+ #error "Serial port pins (2) conflict with probe pin!"
+ #elif ANY_TX(2, X_ENABLE_PIN, Y_ENABLE_PIN) || ANY_RX(2, X_DIR_PIN, Y_DIR_PIN)
+ #error "Serial port pins (2) conflict with X/Y stepper pins!"
+ #elif HAS_MULTI_EXTRUDER && (IS_TX2(E1_ENABLE_PIN) || (AXIS_HAS_SPI(E1) && IS_TX2(E1_CS_PIN)))
+ #error "Serial port pins (2) conflict with E1 stepper pins!"
+ #elif EXTRUDERS && ANY_RX(2, E0_DIR_PIN, E0_STEP_PIN)
+ #error "Serial port pins (2) conflict with E stepper pins!"
+ #endif
+ #undef IS_TX2
+ #undef IS_RX2
+ #undef _IS_TX2_1
+ #undef _IS_RX2_1
+#endif
+
+#if USING_HW_SERIAL3
+ #define PIN_IS_TX3(P) (PIN_EXISTS(P) && P##_PIN == P0_00)
+ #define PIN_IS_RX3(P) (P##_PIN == P0_01)
+ #if PIN_IS_TX3(X_MIN) || PIN_IS_RX3(X_MAX)
+ #error "Serial port pins (3) conflict with X endstop pins!"
+ #elif PIN_IS_TX3(Y_SERIAL_TX) || PIN_IS_TX3(Y_SERIAL_RX) || PIN_IS_RX3(X_SERIAL_TX) || PIN_IS_RX3(X_SERIAL_RX)
+ #error "Serial port pins (3) conflict with X/Y axis UART pins!"
+ #elif PIN_IS_TX3(X2_DIR) || PIN_IS_RX3(X2_STEP)
+ #error "Serial port pins (3) conflict with X2 pins!"
+ #elif PIN_IS_TX3(Y2_DIR) || PIN_IS_RX3(Y2_STEP)
+ #error "Serial port pins (3) conflict with Y2 pins!"
+ #elif PIN_IS_TX3(Z2_DIR) || PIN_IS_RX3(Z2_STEP)
+ #error "Serial port pins (3) conflict with Z2 pins!"
+ #elif PIN_IS_TX3(Z3_DIR) || PIN_IS_RX3(Z3_STEP)
+ #error "Serial port pins (3) conflict with Z3 pins!"
+ #elif PIN_IS_TX3(Z4_DIR) || PIN_IS_RX3(Z4_STEP)
+ #error "Serial port pins (3) conflict with Z4 pins!"
+ #elif HAS_MULTI_EXTRUDER && (PIN_IS_TX3(E1_DIR) || PIN_IS_RX3(E1_STEP))
+ #error "Serial port pins (3) conflict with E1 pins!"
+ #endif
+ #undef PIN_IS_TX3
+ #undef PIN_IS_RX3
+#endif
+
+#undef ANY_TX
+#undef ANY_RX
+
+//
+// Flag any i2c pin conflicts
+//
+#if ANY(HAS_MOTOR_CURRENT_I2C, HAS_MOTOR_CURRENT_DAC, EXPERIMENTAL_I2CBUS, I2C_POSITION_ENCODERS, PCA9632, I2C_EEPROM)
+ #define USEDI2CDEV_M 1 // /Wire.cpp
+
+ #if USEDI2CDEV_M == 0 // P0_27 [D57] (AUX-1) .......... P0_28 [D58] (AUX-1)
+ #define PIN_IS_SDA0(P) (P##_PIN == P0_27)
+ #define IS_SCL0(P) (P == P0_28)
+ #if ENABLED(SDSUPPORT) && PIN_IS_SDA0(SD_DETECT)
+ #error "SDA0 overlaps with SD_DETECT_PIN!"
+ #elif PIN_IS_SDA0(E0_AUTO_FAN)
+ #error "SDA0 overlaps with E0_AUTO_FAN_PIN!"
+ #elif PIN_IS_SDA0(BEEPER)
+ #error "SDA0 overlaps with BEEPER_PIN!"
+ #elif IS_SCL0(BTN_ENC)
+ #error "SCL0 overlaps with Encoder Button!"
+ #elif IS_SCL0(SD_SS_PIN)
+ #error "SCL0 overlaps with SD_SS_PIN!"
+ #elif IS_SCL0(LCD_SDSS)
+ #error "SCL0 overlaps with LCD_SDSS!"
+ #endif
+ #undef PIN_IS_SDA0
+ #undef IS_SCL0
+ #elif USEDI2CDEV_M == 1 // P0_00 [D20] (SCA) ............ P0_01 [D21] (SCL)
+ #define PIN_IS_SDA1(P) (PIN_EXISTS(P) && P##_PIN == P0_00)
+ #define PIN_IS_SCL1(P) (P##_PIN == P0_01)
+ #if PIN_IS_SDA1(X_MIN) || PIN_IS_SCL1(X_MAX)
+ #error "One or more i2c (1) pins overlaps with X endstop pins! Disable i2c peripherals."
+ #elif PIN_IS_SDA1(X2_DIR) || PIN_IS_SCL1(X2_STEP)
+ #error "One or more i2c (1) pins overlaps with X2 pins! Disable i2c peripherals."
+ #elif PIN_IS_SDA1(Y2_DIR) || PIN_IS_SCL1(Y2_STEP)
+ #error "One or more i2c (1) pins overlaps with Y2 pins! Disable i2c peripherals."
+ #elif PIN_IS_SDA1(Z2_DIR) || PIN_IS_SCL1(Z2_STEP)
+ #error "One or more i2c (1) pins overlaps with Z2 pins! Disable i2c peripherals."
+ #elif PIN_IS_SDA1(Z3_DIR) || PIN_IS_SCL1(Z3_STEP)
+ #error "One or more i2c (1) pins overlaps with Z3 pins! Disable i2c peripherals."
+ #elif PIN_IS_SDA1(Z4_DIR) || PIN_IS_SCL1(Z4_STEP)
+ #error "One or more i2c (1) pins overlaps with Z4 pins! Disable i2c peripherals."
+ #elif HAS_MULTI_EXTRUDER && (PIN_IS_SDA1(E1_DIR) || PIN_IS_SCL1(E1_STEP))
+ #error "One or more i2c (1) pins overlaps with E1 pins! Disable i2c peripherals."
+ #endif
+ #undef PIN_IS_SDA1
+ #undef PIN_IS_SCL1
+ #elif USEDI2CDEV_M == 2 // P0_10 [D38] (X_ENABLE_PIN) ... P0_11 [D55] (X_DIR_PIN)
+ #define PIN_IS_SDA2(P) (P##_PIN == P0_10)
+ #define PIN_IS_SCL2(P) (P##_PIN == P0_11)
+ #if PIN_IS_SDA2(Y_STOP)
+ #error "i2c SDA2 overlaps with Y endstop pin!"
+ #elif USES_Z_MIN_PROBE_PIN && PIN_IS_SDA2(Z_MIN_PROBE)
+ #error "i2c SDA2 overlaps with Z probe pin!"
+ #elif PIN_IS_SDA2(X_ENABLE) || PIN_IS_SDA2(Y_ENABLE)
+ #error "i2c SDA2 overlaps with X/Y ENABLE pin!"
+ #elif AXIS_HAS_SPI(X) && PIN_IS_SDA2(X_CS)
+ #error "i2c SDA2 overlaps with X CS pin!"
+ #elif PIN_IS_SDA2(X2_ENABLE)
+ #error "i2c SDA2 overlaps with X2 enable pin! Disable i2c peripherals."
+ #elif PIN_IS_SDA2(Y2_ENABLE)
+ #error "i2c SDA2 overlaps with Y2 enable pin! Disable i2c peripherals."
+ #elif PIN_IS_SDA2(Z2_ENABLE)
+ #error "i2c SDA2 overlaps with Z2 enable pin! Disable i2c peripherals."
+ #elif PIN_IS_SDA2(Z3_ENABLE)
+ #error "i2c SDA2 overlaps with Z3 enable pin! Disable i2c peripherals."
+ #elif PIN_IS_SDA2(Z4_ENABLE)
+ #error "i2c SDA2 overlaps with Z4 enable pin! Disable i2c peripherals."
+ #elif HAS_MULTI_EXTRUDER && PIN_IS_SDA2(E1_ENABLE)
+ #error "i2c SDA2 overlaps with E1 enable pin! Disable i2c peripherals."
+ #elif HAS_MULTI_EXTRUDER && AXIS_HAS_SPI(E1) && PIN_IS_SDA2(E1_CS)
+ #error "i2c SDA2 overlaps with E1 CS pin! Disable i2c peripherals."
+ #elif EXTRUDERS && (PIN_IS_SDA2(E0_STEP) || PIN_IS_SDA2(E0_DIR))
+ #error "i2c SCL2 overlaps with E0 STEP/DIR pin! Disable i2c peripherals."
+ #elif PIN_IS_SDA2(X_DIR) || PIN_IS_SDA2(Y_DIR)
+ #error "One or more i2c pins overlaps with X/Y DIR pin! Disable i2c peripherals."
+ #endif
+ #undef PIN_IS_SDA2
+ #undef PIN_IS_SCL2
+ #endif
+
+ #undef USEDI2CDEV_M
+#endif
+
+#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
+ #error "SERIAL_STATS_MAX_RX_QUEUED is not supported on LPC176x."
+#elif ENABLED(SERIAL_STATS_DROPPED_RX)
+ #error "SERIAL_STATS_DROPPED_RX is not supported on LPX176x."
+#endif
diff --git a/Marlin/src/HAL/LPC4078/include/SPI.h b/Marlin/src/HAL/LPC4078/include/SPI.h
new file mode 100644
index 0000000000..02bfdf8398
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/include/SPI.h
@@ -0,0 +1,197 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+#include "../../shared/HAL_SPI.h"
+
+#include
+// #include
+// #include
+
+//#define MSBFIRST 1
+
+#define SPI_MODE0 0
+#define SPI_MODE1 1
+#define SPI_MODE2 2
+#define SPI_MODE3 3
+
+#define SSP_CR0_DSS(n) ((uint32_t)((n-1)&0xF))
+#define SSP_DATABIT_4 SSP_CR0_DSS(4) /*!< Databit number = 4 */
+#define SSP_DATABIT_5 SSP_CR0_DSS(5) /*!< Databit number = 5 */
+#define SSP_DATABIT_6 SSP_CR0_DSS(6) /*!< Databit number = 6 */
+#define SSP_DATABIT_7 SSP_CR0_DSS(7) /*!< Databit number = 7 */
+#define SSP_DATABIT_8 SSP_CR0_DSS(8) /*!< Databit number = 8 */
+#define SSP_DATABIT_9 SSP_CR0_DSS(9) /*!< Databit number = 9 */
+#define SSP_DATABIT_10 SSP_CR0_DSS(10) /*!< Databit number = 10 */
+#define SSP_DATABIT_11 SSP_CR0_DSS(11) /*!< Databit number = 11 */
+#define SSP_DATABIT_12 SSP_CR0_DSS(12) /*!< Databit number = 12 */
+#define SSP_DATABIT_13 SSP_CR0_DSS(13) /*!< Databit number = 13 */
+#define SSP_DATABIT_14 SSP_CR0_DSS(14) /*!< Databit number = 14 */
+#define SSP_DATABIT_15 SSP_CR0_DSS(15) /*!< Databit number = 15 */
+#define SSP_DATABIT_16 SSP_CR0_DSS(16) /*!< Databit number = 16 */
+
+#define DATA_SIZE_8BIT SSP_DATABIT_8
+#define DATA_SIZE_16BIT SSP_DATABIT_16
+
+#define SPI_CLOCK_MAX_TFT 30000000UL
+#define SPI_CLOCK_DIV2 8333333 //(SCR: 2) desired: 8,000,000 actual: 8,333,333 +4.2% SPI_FULL_SPEED
+#define SPI_CLOCK_DIV4 4166667 //(SCR: 5) desired: 4,000,000 actual: 4,166,667 +4.2% SPI_HALF_SPEED
+#define SPI_CLOCK_DIV8 2083333 //(SCR: 11) desired: 2,000,000 actual: 2,083,333 +4.2% SPI_QUARTER_SPEED
+#define SPI_CLOCK_DIV16 1000000 //(SCR: 24) desired: 1,000,000 actual: 1,000,000 SPI_EIGHTH_SPEED
+#define SPI_CLOCK_DIV32 500000 //(SCR: 49) desired: 500,000 actual: 500,000 SPI_SPEED_5
+#define SPI_CLOCK_DIV64 250000 //(SCR: 99) desired: 250,000 actual: 250,000 SPI_SPEED_6
+#define SPI_CLOCK_DIV128 125000 //(SCR:199) desired: 125,000 actual: 125,000 Default from HAL.h
+
+#define SPI_CLOCK_MAX SPI_CLOCK_DIV2
+
+#define BOARD_NR_SPI 2
+
+//#define BOARD_SPI1_NSS_PIN PA4 ?!
+#define BOARD_SPI1_SCK_PIN P0_15
+#define BOARD_SPI1_MISO_PIN P0_17
+#define BOARD_SPI1_MOSI_PIN P0_18
+
+//#define BOARD_SPI2_NSS_PIN PB12 ?!
+#define BOARD_SPI2_SCK_PIN P0_07
+#define BOARD_SPI2_MISO_PIN P0_08
+#define BOARD_SPI2_MOSI_PIN P0_09
+
+class SPISettings {
+public:
+ SPISettings(uint32_t spiRate, int inBitOrder, int inDataMode) {
+ init_AlwaysInline(spiRate2Clock(spiRate), inBitOrder, inDataMode, DATA_SIZE_8BIT);
+ }
+ SPISettings(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) {
+ if (__builtin_constant_p(inClock))
+ init_AlwaysInline(inClock, inBitOrder, inDataMode, inDataSize);
+ else
+ init_MightInline(inClock, inBitOrder, inDataMode, inDataSize);
+ }
+ SPISettings() {
+ init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT);
+ }
+
+ //uint32_t spiRate() const { return spi_speed; }
+
+ static uint32_t spiRate2Clock(uint32_t spiRate) {
+ uint32_t Marlin_speed[7]; // CPSR is always 2
+ Marlin_speed[0] = 8333333; //(SCR: 2) desired: 8,000,000 actual: 8,333,333 +4.2% SPI_FULL_SPEED
+ Marlin_speed[1] = 4166667; //(SCR: 5) desired: 4,000,000 actual: 4,166,667 +4.2% SPI_HALF_SPEED
+ Marlin_speed[2] = 2083333; //(SCR: 11) desired: 2,000,000 actual: 2,083,333 +4.2% SPI_QUARTER_SPEED
+ Marlin_speed[3] = 1000000; //(SCR: 24) desired: 1,000,000 actual: 1,000,000 SPI_EIGHTH_SPEED
+ Marlin_speed[4] = 500000; //(SCR: 49) desired: 500,000 actual: 500,000 SPI_SPEED_5
+ Marlin_speed[5] = 250000; //(SCR: 99) desired: 250,000 actual: 250,000 SPI_SPEED_6
+ Marlin_speed[6] = 125000; //(SCR:199) desired: 125,000 actual: 125,000 Default from HAL.h
+ return Marlin_speed[spiRate > 6 ? 6 : spiRate];
+ }
+
+private:
+ void init_MightInline(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) {
+ init_AlwaysInline(inClock, inBitOrder, inDataMode, inDataSize);
+ }
+ void init_AlwaysInline(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) __attribute__((__always_inline__)) {
+ clock = inClock;
+ bitOrder = inBitOrder;
+ dataMode = inDataMode;
+ dataSize = inDataSize;
+ }
+
+ //uint32_t spi_speed;
+ uint32_t clock;
+ uint32_t dataSize;
+ //uint32_t clockDivider;
+ uint8_t bitOrder;
+ uint8_t dataMode;
+ //LPC_SSP_TypeDef *spi_d;
+
+ friend class SPIClass;
+};
+
+/**
+ * @brief Wirish SPI interface.
+ *
+ * This is the same interface is available across HAL
+ *
+ * This implementation uses software slave management, so the caller
+ * is responsible for controlling the slave select line.
+ */
+class SPIClass {
+public:
+ /**
+ * @param spiPortNumber Number of the SPI port to manage.
+ */
+ SPIClass(uint8_t spiPortNumber);
+
+ /**
+ * Init using pins
+ */
+ SPIClass(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel = (pin_t)-1);
+
+ /**
+ * Select and configure the current selected SPI device to use
+ */
+ void begin();
+
+ /**
+ * Disable the current SPI device
+ */
+ void end();
+
+ void beginTransaction(const SPISettings&);
+ void endTransaction() {}
+
+ // Transfer using 1 "Data Size"
+ uint8_t transfer(uint16_t data);
+ // Transfer 2 bytes in 8 bit mode
+ uint16_t transfer16(uint16_t data);
+
+ void send(uint8_t data);
+
+ uint16_t read();
+ void read(uint8_t *buf, uint32_t len);
+
+ void dmaSend(void *buf, uint16_t length, bool minc);
+
+ /**
+ * @brief Sets the number of the SPI peripheral to be used by
+ * this HardwareSPI instance.
+ *
+ * @param spi_num Number of the SPI port. 1-2 in low density devices
+ * or 1-3 in high density devices.
+ */
+ void setModule(uint8_t device);
+
+ void setClock(uint32_t clock);
+ void setBitOrder(uint8_t bitOrder);
+ void setDataMode(uint8_t dataMode);
+ void setDataSize(uint32_t ds);
+
+ inline uint32_t getDataSize() { return _currentSetting->dataSize; }
+
+private:
+ SPISettings _settings[BOARD_NR_SPI];
+ SPISettings *_currentSetting;
+
+ void updateSettings();
+};
+
+extern SPIClass SPI;
diff --git a/Marlin/src/HAL/LPC4078/main.cpp b/Marlin/src/HAL/LPC4078/main.cpp
new file mode 100644
index 0000000000..40b77728bd
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/main.cpp
@@ -0,0 +1,111 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#ifdef TARGET_LPC4078
+
+#include "../../inc/MarlinConfig.h"
+#include "../../core/millis_t.h"
+#include "../../sd/cardreader.h"
+
+#include
+#include
+
+TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial());
+
+void MarlinHAL::init() {
+
+ MCUI::pwm_init();
+
+ // Init LEDs
+ #if PIN_EXISTS(LED)
+ SET_DIR_OUTPUT(LED_PIN);
+ WRITE_PIN_CLR(LED_PIN);
+ #if PIN_EXISTS(LED2)
+ SET_DIR_OUTPUT(LED2_PIN);
+ WRITE_PIN_CLR(LED2_PIN);
+ #if PIN_EXISTS(LED3)
+ SET_DIR_OUTPUT(LED3_PIN);
+ WRITE_PIN_CLR(LED3_PIN);
+ #if PIN_EXISTS(LED4)
+ SET_DIR_OUTPUT(LED4_PIN);
+ WRITE_PIN_CLR(LED4_PIN);
+ #endif
+ #endif
+ #endif
+
+ // Flash status LED 3 times to indicate Marlin has started booting
+ for(int i = 0; i < 6; ++i) {
+ TOGGLE(LED_PIN);
+ delay(100);
+ }
+ #endif
+
+ // Init Servo Pins
+ #define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW)
+ #if HAS_SERVO_0
+ INIT_SERVO(0);
+ #endif
+ #if HAS_SERVO_1
+ INIT_SERVO(1);
+ #endif
+ #if HAS_SERVO_2
+ INIT_SERVO(2);
+ #endif
+ #if HAS_SERVO_3
+ INIT_SERVO(3);
+ #endif
+
+ #if PIN_EXISTS(SD_SS)
+ OUT_WRITE(SD_SS_PIN, HIGH);
+ #endif
+
+ #if PIN_EXISTS(ONBOARD_SD_CS) && ONBOARD_SD_CS_PIN != SD_SS_PIN
+ OUT_WRITE(ONBOARD_SD_CS_PIN, HIGH);
+ #endif
+
+ TERN_(HAS_SD_HOST_DRIVE, MCUI::USBDevice::msc_storage_init()); // Enable USB SD card access
+ MCUI::USBDevice::connect(2000, LED_PIN);
+
+ HAL_timer_init();
+
+ TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
+}
+
+// HAL idle task
+void MarlinHAL::idletask() {
+ #if HAS_SHARED_MEDIA
+ // If Marlin is using the SD card we need to lock it to prevent access from
+ // a PC via USB.
+ // Other HALs use IS_SD_PRINTING() and IS_SD_FILE_OPEN() to check for access but
+ // this will not reliably detect delete operations. To be safe we will lock
+ // the disk if Marlin has it mounted. Unfortunately there is currently no way
+ // to unmount the disk from the LCD menu.
+ // if (IS_SD_PRINTING() || IS_SD_FILE_OPEN())
+ if (card.isMounted())
+ MCUI::USBDevice::msc_storage_lock();
+ else
+ MCUI::USBDevice::msc_storage_release();
+ #endif
+ // Perform USB stack housekeeping
+ MCUI::USBDevice::msc_run_deferred_commands();
+}
+
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/LPC4078/pinsDebug.h b/Marlin/src/HAL/LPC4078/pinsDebug.h
new file mode 100644
index 0000000000..a1bae08d92
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/pinsDebug.h
@@ -0,0 +1,57 @@
+/**
+ * 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 .
+ *
+ */
+
+/**
+ * Support routines for LPC1768
+ */
+
+/**
+ * Translation of routines & variables used by pinsDebug.h
+ */
+
+#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS
+#define IS_ANALOG(P) (DIGITAL_PIN_TO_ANALOG_PIN(P) >= 0 ? 1 : 0)
+#define digitalRead_mod(p) extDigitalRead(p)
+#define PRINT_PORT(p)
+#define GET_ARRAY_PIN(p) pin_array[p].pin
+#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
+#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("P%d_%02d"), MCUI::pin_port(p), MCUI::pin_bit(p)); SERIAL_ECHO(buffer); }while(0)
+#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR("_A%d "), MCUI::pin_get_adc_channel(pin)); SERIAL_ECHO(buffer); }while(0)
+#define MULTI_NAME_PAD 17 // space needed to be pretty if not first name assigned to a pin
+
+// pins that will cause hang/reset/disconnect in M43 Toggle and Watch utilities
+#ifndef M43_NEVER_TOUCH
+ #define M43_NEVER_TOUCH(Q) ((Q) == P0_29 || (Q) == P0_30 || (Q) == P2_09) // USB pins
+#endif
+
+bool GET_PINMODE(const pin_t pin) {
+ if (!MCUI::pin_is_valid(pin) || MCUI::pin_adc_enabled(pin)) // found an invalid pin or active analog pin
+ return false;
+
+ return MCUI::gpio_direction(pin);
+}
+
+#define GET_ARRAY_IS_DIGITAL(x) ((bool) pin_array[x].is_digital)
+
+void print_port(const pin_t) {}
+void pwm_details(const pin_t) {}
+bool pwm_status(const pin_t) { return false; }
diff --git a/Marlin/src/HAL/LPC4078/spi_pins.h b/Marlin/src/HAL/LPC4078/spi_pins.h
new file mode 100644
index 0000000000..78bb0ec962
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/spi_pins.h
@@ -0,0 +1,54 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+#include "../../core/macros.h"
+
+#if ALL(SDSUPPORT, HAS_MARLINUI_U8GLIB) && (LCD_PINS_D4 == SD_SCK_PIN || LCD_PINS_ENABLE == SD_MOSI_PIN || DOGLCD_SCK == SD_SCK_PIN || DOGLCD_MOSI == SD_MOSI_PIN)
+ #define LPC_SOFTWARE_SPI // If the SD card and LCD adapter share the same SPI pins, then software SPI is currently
+ // needed due to the speed and mode required for communicating with each device being different.
+ // This requirement can be removed if the SPI access to these devices is updated to use
+ // spiBeginTransaction.
+#endif
+
+/** onboard SD card */
+//#define SD_SCK_PIN P0_07
+//#define SD_MISO_PIN P0_08
+//#define SD_MOSI_PIN P0_09
+//#define SD_SS_PIN P0_06
+/** external */
+#ifndef SD_SCK_PIN
+ #define SD_SCK_PIN P0_15
+#endif
+#ifndef SD_MISO_PIN
+ #define SD_MISO_PIN P0_17
+#endif
+#ifndef SD_MOSI_PIN
+ #define SD_MOSI_PIN P0_18
+#endif
+#ifndef SD_SS_PIN
+ #define SD_SS_PIN P1_23
+#endif
+#if !defined(SDSS) || SDSS == P_NC // gets defaulted in pins.h
+ #undef SDSS
+ #define SDSS SD_SS_PIN
+#endif
diff --git a/Marlin/src/HAL/LPC4078/timers.cpp b/Marlin/src/HAL/LPC4078/timers.cpp
new file mode 100644
index 0000000000..eb6d8a70ae
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/timers.cpp
@@ -0,0 +1,65 @@
+/**
+ * Marlin 3D Printer Firmware
+ *
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
+ * Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
+ *
+ * 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 .
+ *
+ */
+
+/**
+ * Description:
+ *
+ * Timers for LPC1768
+ */
+
+#ifdef TARGET_LPC4078
+
+#include "../../inc/MarlinConfig.h"
+
+void HAL_timer_init() {
+ SBI(MCUI::system_control.PCONP, SBIT_TIMER0); // Power ON Timer 0
+ STEP_TIMER_REF.PR = (HAL_TIMER_RATE) / (STEPPER_TIMER_RATE) - 1; // Use prescaler to set frequency if needed
+
+ SBI(MCUI::system_control.PCONP, SBIT_TIMER1); // Power ON Timer 1
+ TEMP_TIMER_REF.PR = (HAL_TIMER_RATE) / 1000000 - 1;
+}
+
+void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
+ switch (timer_num) {
+ case MF_TIMER_STEP:
+ STEP_TIMER_REF.MCR = _BV(SBIT_MR0I) | _BV(SBIT_MR0R); // Match on MR0, reset on MR0, interrupts when NVIC enables them
+ STEP_TIMER_REF.MR0 = uint32_t(STEPPER_TIMER_RATE) / frequency; // Match value (period) to set frequency
+ STEP_TIMER_REF.TCR = _BV(SBIT_CNTEN); // Counter Enable
+
+ MCUCore::nvic_set_priority(MCUI::IRQNumber::TIMER0, MCUCore::nvic_encode_priority(0, 1, 0));
+ MCUCore::nvic_enable_irq(MCUI::IRQNumber::TIMER0);
+ break;
+
+ case MF_TIMER_TEMP:
+ TEMP_TIMER_REF.MCR = _BV(SBIT_MR0I) | _BV(SBIT_MR0R); // Match on MR0, reset on MR0, interrupts when NVIC enables them
+ TEMP_TIMER_REF.MR0 = uint32_t(TEMP_TIMER_RATE) / frequency;
+ TEMP_TIMER_REF.TCR = _BV(SBIT_CNTEN); // Counter Enable
+
+ MCUCore::nvic_set_priority(MCUI::IRQNumber::TIMER1, MCUCore::nvic_encode_priority(0, 2, 0));
+ MCUCore::nvic_enable_irq(MCUI::IRQNumber::TIMER1);
+ break;
+
+ default: break;
+ }
+}
+
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/LPC4078/timers.h b/Marlin/src/HAL/LPC4078/timers.h
new file mode 100644
index 0000000000..3db982168f
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/timers.h
@@ -0,0 +1,165 @@
+/**
+ * Marlin 3D Printer Firmware
+ *
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+/**
+ * HAL For LPC1768
+ */
+
+
+#include
+#include
+
+#include "../../core/macros.h"
+
+#define SBIT_TIMER0 1
+#define SBIT_TIMER1 2
+
+#define SBIT_CNTEN 0
+
+#define SBIT_MR0I 0 // Timer 0 Interrupt when TC matches MR0
+#define SBIT_MR0R 1 // Timer 0 Reset TC on Match
+#define SBIT_MR0S 2 // Timer 0 Stop TC and PC on Match
+#define SBIT_MR1I 3
+#define SBIT_MR1R 4
+#define SBIT_MR1S 5
+#define SBIT_MR2I 6
+#define SBIT_MR2R 7
+#define SBIT_MR2S 8
+#define SBIT_MR3I 9
+#define SBIT_MR3R 10
+#define SBIT_MR3S 11
+
+// ------------------------
+// Defines
+// ------------------------
+
+#define _HAL_TIMER(T) _CAT(MCUI::timer, T)
+#define _HAL_TIMER_IRQ(T) TIMER##T##_IRQn
+#define __HAL_TIMER_ISR(T) extern "C" void TIMER##T##_IRQHandler()
+#define _HAL_TIMER_ISR(T) __HAL_TIMER_ISR(T)
+
+typedef uint32_t hal_timer_t;
+#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
+
+#define HAL_TIMER_RATE ((F_CPU) / 2) // frequency of timers peripherals
+
+#ifndef MF_TIMER_STEP
+ #define MF_TIMER_STEP 0 // Timer Index for Stepper
+#endif
+#ifndef MF_TIMER_PULSE
+ #define MF_TIMER_PULSE MF_TIMER_STEP
+#endif
+#ifndef MF_TIMER_TEMP
+ #define MF_TIMER_TEMP 1 // Timer Index for Temperature
+#endif
+#ifndef MF_TIMER_PWM
+ #define MF_TIMER_PWM 3 // Timer Index for PWM
+#endif
+
+#define TEMP_TIMER_RATE 1000000
+#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
+
+#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
+#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
+#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
+
+#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
+#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
+#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
+
+#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
+#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
+#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
+
+#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
+#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
+
+#ifndef HAL_STEP_TIMER_ISR
+ #define HAL_STEP_TIMER_ISR() _HAL_TIMER_ISR(MF_TIMER_STEP)
+#endif
+#ifndef HAL_TEMP_TIMER_ISR
+ #define HAL_TEMP_TIMER_ISR() _HAL_TIMER_ISR(MF_TIMER_TEMP)
+#endif
+
+// Timer references by index
+#define STEP_TIMER_REF _HAL_TIMER(MF_TIMER_STEP)
+#define TEMP_TIMER_REF _HAL_TIMER(MF_TIMER_TEMP)
+
+// ------------------------
+// Public functions
+// ------------------------
+void HAL_timer_init();
+void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
+
+FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
+ switch (timer_num) {
+ case MF_TIMER_STEP: STEP_TIMER_REF.MR0 = compare; break; // Stepper Timer Match Register 0
+ case MF_TIMER_TEMP: TEMP_TIMER_REF.MR0 = compare; break; // Temp Timer Match Register 0
+ }
+}
+
+FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
+ switch (timer_num) {
+ case MF_TIMER_STEP: return STEP_TIMER_REF.MR0; // Stepper Timer Match Register 0
+ case MF_TIMER_TEMP: return TEMP_TIMER_REF.MR0; // Temp Timer Match Register 0
+ }
+ return 0;
+}
+
+FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
+ switch (timer_num) {
+ case MF_TIMER_STEP: return STEP_TIMER_REF.TC; // Stepper Timer Count
+ case MF_TIMER_TEMP: return TEMP_TIMER_REF.TC; // Temp Timer Count
+ }
+ return 0;
+}
+
+FORCE_INLINE static void HAL_timer_enable_interrupt(const uint8_t timer_num) {
+ switch (timer_num) {
+ case MF_TIMER_STEP: MCUCore::nvic_enable_irq(MCUI::IRQNumber::TIMER0); break; // Enable interrupt handler
+ case MF_TIMER_TEMP: MCUCore::nvic_enable_irq(MCUI::IRQNumber::TIMER1); break; // Enable interrupt handler
+ }
+}
+
+FORCE_INLINE static void HAL_timer_disable_interrupt(const uint8_t timer_num) {
+ switch (timer_num) {
+ case MF_TIMER_STEP: MCUCore::nvic_disable_irq(MCUI::IRQNumber::TIMER0); break; // Disable interrupt handler
+ case MF_TIMER_TEMP: MCUCore::nvic_disable_irq(MCUI::IRQNumber::TIMER1); break; // Disable interrupt handler
+ }
+}
+
+FORCE_INLINE static bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
+ switch (timer_num) {
+ case MF_TIMER_STEP: return MCUCore::nvic_irq_is_enabled(MCUI::IRQNumber::TIMER0); // Check if interrupt is enabled or not
+ case MF_TIMER_TEMP: return MCUCore::nvic_irq_is_enabled(MCUI::IRQNumber::TIMER1); // Check if interrupt is enabled or not
+ }
+ return false;
+}
+
+FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
+ switch (timer_num) {
+ case MF_TIMER_STEP: SBI(STEP_TIMER_REF.IR, SBIT_CNTEN); break;
+ case MF_TIMER_TEMP: SBI(TEMP_TIMER_REF.IR, SBIT_CNTEN); break;
+ }
+}
+
+#define HAL_timer_isr_epilogue(T) NOOP
diff --git a/Marlin/src/HAL/LPC4078/u8g/LCD_I2C_routines.cpp b/Marlin/src/HAL/LPC4078/u8g/LCD_I2C_routines.cpp
new file mode 100644
index 0000000000..e714c3c16d
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/u8g/LCD_I2C_routines.cpp
@@ -0,0 +1,89 @@
+/**
+ * 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 .
+ *
+ */
+
+// adapted from I2C/master/master.c example
+// https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
+
+#ifdef TARGET_LPC1768
+
+#include "../include/i2c_util.h"
+#include "../../../core/millis_t.h"
+
+extern int millis();
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+#define I2CDEV_S_ADDR 0x78 // From SSD1306 (actual address is 0x3C - shift left 1 with LSB set to 0 to indicate write)
+
+// Send slave address and write bit
+uint8_t u8g_i2c_start(const uint8_t sla) {
+ // Sometimes TX data ACK or NAK status is returned. That mean the start state didn't
+ // happen which means only the value of the slave address was send. Keep looping until
+ // the slave address and write bit are actually sent.
+ do{
+ _I2C_Stop(I2CDEV_M); // output stop state on I2C bus
+ _I2C_Start(I2CDEV_M); // output start state on I2C bus
+ while ((I2C_status != I2C_I2STAT_M_TX_START)
+ && (I2C_status != I2C_I2STAT_M_TX_RESTART)
+ && (I2C_status != I2C_I2STAT_M_TX_DAT_ACK)
+ && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK)); //wait for start to be asserted
+
+ LPC_I2C1->I2CONCLR = I2C_I2CONCLR_STAC; // clear start state before tansmitting slave address
+ LPC_I2C1->I2DAT = I2CDEV_S_ADDR & I2C_I2DAT_BITMASK; // transmit slave address & write bit
+ LPC_I2C1->I2CONSET = I2C_I2CONSET_AA;
+ LPC_I2C1->I2CONCLR = I2C_I2CONCLR_SIC;
+ while ((I2C_status != I2C_I2STAT_M_TX_SLAW_ACK)
+ && (I2C_status != I2C_I2STAT_M_TX_SLAW_NACK)
+ && (I2C_status != I2C_I2STAT_M_TX_DAT_ACK)
+ && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK)); //wait for slaw to finish
+ }while ( (I2C_status == I2C_I2STAT_M_TX_DAT_ACK) || (I2C_status == I2C_I2STAT_M_TX_DAT_NACK));
+ return 1;
+}
+
+void u8g_i2c_init(const uint8_t clock_option) {
+ configure_i2c(clock_option);
+ u8g_i2c_start(0); // Send slave address and write bit
+}
+
+uint8_t u8g_i2c_send_byte(uint8_t data) {
+ #define I2C_TIMEOUT 3
+ LPC_I2C1->I2DAT = data & I2C_I2DAT_BITMASK; // transmit data
+ LPC_I2C1->I2CONSET = I2C_I2CONSET_AA;
+ LPC_I2C1->I2CONCLR = I2C_I2CONCLR_SIC;
+ const millis_t timeout = millis() + I2C_TIMEOUT;
+ while ((I2C_status != I2C_I2STAT_M_TX_DAT_ACK) && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK) && PENDING(millis(), timeout)); // wait for xmit to finish
+ // had hangs with SH1106 so added time out - have seen temporary screen corruption when this happens
+ return 1;
+}
+
+void u8g_i2c_stop() {
+}
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC4078/u8g/LCD_I2C_routines.h b/Marlin/src/HAL/LPC4078/u8g/LCD_I2C_routines.h
new file mode 100644
index 0000000000..2d976c92d2
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/u8g/LCD_I2C_routines.h
@@ -0,0 +1,28 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+void u8g_i2c_init(const uint8_t clock_options);
+//uint8_t u8g_i2c_wait(uint8_t mask, uint8_t pos);
+uint8_t u8g_i2c_start(uint8_t sla);
+uint8_t u8g_i2c_send_byte(uint8_t data);
+void u8g_i2c_stop();
diff --git a/Marlin/src/HAL/LPC4078/u8g/LCD_defines.h b/Marlin/src/HAL/LPC4078/u8g/LCD_defines.h
new file mode 100644
index 0000000000..5b58f1223a
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/u8g/LCD_defines.h
@@ -0,0 +1,46 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+/**
+ * LPC1768 LCD-specific defines
+ */
+
+#ifndef U8G_HAL_LINKS
+
+ #define U8G_COM_SSD_I2C_HAL u8g_com_arduino_ssd_i2c_fn // See U8glib-HAL
+
+#else
+
+ uint8_t u8g_com_HAL_LPC1768_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
+ uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
+ uint8_t u8g_com_HAL_LPC1768_ST7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
+ uint8_t u8g_com_HAL_LPC1768_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
+ uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
+
+ #define U8G_COM_HAL_SW_SPI_FN u8g_com_HAL_LPC1768_sw_spi_fn
+ #define U8G_COM_HAL_HW_SPI_FN u8g_com_HAL_LPC1768_hw_spi_fn
+ #define U8G_COM_ST7920_HAL_SW_SPI u8g_com_HAL_LPC1768_ST7920_sw_spi_fn
+ #define U8G_COM_ST7920_HAL_HW_SPI u8g_com_HAL_LPC1768_ST7920_hw_spi_fn
+ #define U8G_COM_SSD_I2C_HAL u8g_com_HAL_LPC1768_ssd_hw_i2c_fn
+
+#endif
diff --git a/Marlin/src/HAL/LPC4078/u8g/LCD_delay.h b/Marlin/src/HAL/LPC4078/u8g/LCD_delay.h
new file mode 100644
index 0000000000..0b9e2b4fd0
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/u8g/LCD_delay.h
@@ -0,0 +1,43 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+/**
+ * LCD delay routines - used by all the drivers.
+ *
+ * These are based on the LPC1768 routines.
+ *
+ * Couldn't just call exact copies because the overhead
+ * results in a one microsecond delay taking about 4µS.
+ */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+void U8g_delay(int msec);
+void u8g_MicroDelay();
+void u8g_10MicroDelay();
+
+#ifdef __cplusplus
+ }
+#endif
diff --git a/Marlin/src/HAL/LPC4078/u8g/LCD_pin_routines.cpp b/Marlin/src/HAL/LPC4078/u8g/LCD_pin_routines.cpp
new file mode 100644
index 0000000000..4635beda8c
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/u8g/LCD_pin_routines.cpp
@@ -0,0 +1,59 @@
+/**
+ * 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 .
+ *
+ */
+
+/**
+ * Low level pin manipulation routines - used by all the drivers.
+ *
+ * These are based on the LPC1768 pinMode, digitalRead & digitalWrite routines.
+ *
+ * Couldn't just call exact copies because the overhead killed the LCD update speed
+ * With an intermediate level the softspi was running in the 10-20kHz range which
+ * resulted in using about about 25% of the CPU's time.
+ */
+
+#ifdef TARGET_LPC4078
+
+#include
+
+extern "C" {
+
+#include "LCD_pin_routines.h"
+
+void u8g_SetPinOutput(uint8_t pin) {
+ MCUI::gpio_set_output(pin);
+}
+
+void u8g_SetPinInput(uint8_t pin) {
+ MCUI::gpio_set_input(pin);
+}
+
+void u8g_SetPinLevel(uint8_t pin, uint8_t pin_status) {
+ MCUI::gpio_set(pin, pin_status);
+}
+
+uint8_t u8g_GetPinLevel(uint8_t pin) {
+ return MCUI::gpio_get(pin);
+}
+
+}
+
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/LPC4078/u8g/LCD_pin_routines.h b/Marlin/src/HAL/LPC4078/u8g/LCD_pin_routines.h
new file mode 100644
index 0000000000..d60d93dadd
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/u8g/LCD_pin_routines.h
@@ -0,0 +1,37 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+/**
+ * Low level pin manipulation routines - used by all the drivers.
+ *
+ * These are based on the LPC1768 pinMode, digitalRead & digitalWrite routines.
+ *
+ * Couldn't just call exact copies because the overhead killed the LCD update speed
+ * With an intermediate level the softspi was running in the 10-20kHz range which
+ * resulted in using about about 25% of the CPU's time.
+ */
+
+void u8g_SetPinOutput(uint8_t internal_pin_number);
+void u8g_SetPinInput(uint8_t internal_pin_number);
+void u8g_SetPinLevel(uint8_t pin, uint8_t pin_status);
+uint8_t u8g_GetPinLevel(uint8_t pin);
diff --git a/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp b/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp
new file mode 100644
index 0000000000..ac46456409
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp
@@ -0,0 +1,129 @@
+/**
+ * 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 .
+ *
+ */
+
+/**
+ * Based on u8g_com_msp430_hw_spi.c
+ *
+ * Universal 8bit Graphics Library
+ *
+ * Copyright (c) 2011, olikraus@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef TARGET_LPC4078
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if HAS_MARLINUI_U8GLIB
+
+#include
+#include "../../shared/HAL_SPI.h"
+
+#ifndef LCD_SPI_SPEED
+ #ifdef SD_SPI_SPEED
+ #define LCD_SPI_SPEED SD_SPI_SPEED // Assume SPI speed shared with SD
+ #else
+ #define LCD_SPI_SPEED SPI_FULL_SPEED // Use full speed if SD speed is not supplied
+ #endif
+#endif
+
+uint8_t u8g_com_HAL_LPC1768_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
+ switch (msg) {
+ case U8G_COM_MSG_STOP:
+ break;
+
+ case U8G_COM_MSG_INIT:
+ u8g_SetPILevel(u8g, U8G_PI_CS, 1);
+ u8g_SetPILevel(u8g, U8G_PI_A0, 1);
+ u8g_SetPILevel(u8g, U8G_PI_RESET, 1);
+ u8g_SetPIOutput(u8g, U8G_PI_CS);
+ u8g_SetPIOutput(u8g, U8G_PI_A0);
+ u8g_SetPIOutput(u8g, U8G_PI_RESET);
+ u8g_Delay(5);
+ spiBegin();
+ spiInit(LCD_SPI_SPEED);
+ break;
+
+ case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
+ u8g_SetPILevel(u8g, U8G_PI_A0, arg_val);
+ break;
+
+ case U8G_COM_MSG_CHIP_SELECT:
+ u8g_SetPILevel(u8g, U8G_PI_CS, (arg_val ? 0 : 1));
+ break;
+
+ case U8G_COM_MSG_RESET:
+ u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
+ break;
+
+ case U8G_COM_MSG_WRITE_BYTE:
+ spiSend((uint8_t)arg_val);
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ: {
+ uint8_t *ptr = (uint8_t*) arg_ptr;
+ while (arg_val > 0) {
+ spiSend(*ptr++);
+ arg_val--;
+ }
+ }
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ_P: {
+ uint8_t *ptr = (uint8_t*) arg_ptr;
+ while (arg_val > 0) {
+ spiSend(*ptr++);
+ arg_val--;
+ }
+ }
+ break;
+ }
+ return 1;
+}
+
+#endif // HAS_MARLINUI_U8GLIB
+
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_ssd_hw_i2c.cpp b/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_ssd_hw_i2c.cpp
new file mode 100644
index 0000000000..bf76eaf0f4
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_ssd_hw_i2c.cpp
@@ -0,0 +1,198 @@
+/**
+ * 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 .
+ *
+ */
+
+/**
+ * Based on u8g_com_arduino_ssd_i2c.c
+ *
+ * COM interface for Arduino (AND ATmega) and the SSDxxxx chip (SOLOMON) variant
+ * I2C protocol
+ *
+ * Universal 8bit Graphics Library
+ *
+ * Copyright (c) 2011, olikraus@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Special pin usage:
+ * U8G_PI_I2C_OPTION additional options
+ * U8G_PI_A0_STATE used to store the last value of the command/data register selection
+ * U8G_PI_SET_A0 1: Signal request to update I2C device with new A0_STATE, 0: Do nothing, A0_STATE matches I2C device
+ * U8G_PI_SCL clock line (NOT USED)
+ * U8G_PI_SDA data line (NOT USED)
+ *
+ * U8G_PI_RESET reset line (currently disabled, see below)
+ *
+ * Protocol:
+ * SLA, Cmd/Data Selection, Arguments
+ * The command/data register is selected by a special instruction byte, which is sent after SLA
+ *
+ * The continue bit is always 0 so that a (re)start is equired for the change from cmd to/data mode
+ */
+
+#ifdef TARGET_LPC1768
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if HAS_MARLINUI_U8GLIB
+
+#include
+
+#define I2C_SLA (0x3C*2)
+//#define I2C_CMD_MODE 0x080
+#define I2C_CMD_MODE 0x000
+#define I2C_DATA_MODE 0x040
+
+uint8_t u8g_com_ssd_I2C_start_sequence(u8g_t *u8g) {
+ /* are we requested to set the a0 state? */
+ if (u8g->pin_list[U8G_PI_SET_A0] == 0) return 1;
+
+ /* setup bus, might be a repeated start */
+ if (u8g_i2c_start(I2C_SLA) == 0) return 0;
+ if (u8g->pin_list[U8G_PI_A0_STATE] == 0) {
+ if (u8g_i2c_send_byte(I2C_CMD_MODE) == 0) return 0;
+ }
+ else if (u8g_i2c_send_byte(I2C_DATA_MODE) == 0)
+ return 0;
+
+ u8g->pin_list[U8G_PI_SET_A0] = 0;
+ return 1;
+}
+
+uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
+ switch (msg) {
+ case U8G_COM_MSG_INIT:
+ //u8g_com_arduino_digital_write(u8g, U8G_PI_SCL, HIGH);
+ //u8g_com_arduino_digital_write(u8g, U8G_PI_SDA, HIGH);
+ //u8g->pin_list[U8G_PI_A0_STATE] = 0; /* initial RS state: unknown mode */
+
+ u8g_i2c_init(u8g->pin_list[U8G_PI_I2C_OPTION]);
+ u8g_com_ssd_I2C_start_sequence(u8g);
+ break;
+
+ case U8G_COM_MSG_STOP:
+ break;
+
+ case U8G_COM_MSG_RESET:
+ /* Currently disabled, but it could be enable. Previous restrictions have been removed */
+ /* u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val); */
+ break;
+
+ case U8G_COM_MSG_CHIP_SELECT:
+ u8g->pin_list[U8G_PI_A0_STATE] = 0;
+ u8g->pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again, also forces start condition */
+ if (arg_val == 0 ) {
+ /* disable chip, send stop condition */
+ u8g_i2c_stop();
+ }
+ else {
+ /* enable, do nothing: any byte writing will trigger the i2c start */
+ }
+ break;
+
+ case U8G_COM_MSG_WRITE_BYTE:
+ //u8g->pin_list[U8G_PI_SET_A0] = 1;
+ if (u8g_com_ssd_I2C_start_sequence(u8g) == 0) {
+ u8g_i2c_stop();
+ return 0;
+ }
+
+ if (u8g_i2c_send_byte(arg_val) == 0) {
+ u8g_i2c_stop();
+ return 0;
+ }
+ // u8g_i2c_stop();
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ: {
+ //u8g->pin_list[U8G_PI_SET_A0] = 1;
+ if (u8g_com_ssd_I2C_start_sequence(u8g) == 0) {
+ u8g_i2c_stop();
+ return 0;
+ }
+
+ uint8_t *ptr = (uint8_t *)arg_ptr;
+ while (arg_val > 0) {
+ if (u8g_i2c_send_byte(*ptr++) == 0) {
+ u8g_i2c_stop();
+ return 0;
+ }
+ arg_val--;
+ }
+ }
+ // u8g_i2c_stop();
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ_P: {
+ //u8g->pin_list[U8G_PI_SET_A0] = 1;
+ if (u8g_com_ssd_I2C_start_sequence(u8g) == 0) {
+ u8g_i2c_stop();
+ return 0;
+ }
+
+ uint8_t *ptr = (uint8_t *)arg_ptr;
+ while (arg_val > 0) {
+ if (u8g_i2c_send_byte(u8g_pgm_read(ptr)) == 0)
+ return 0;
+ ptr++;
+ arg_val--;
+ }
+ }
+ // u8g_i2c_stop();
+ break;
+
+ case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
+ u8g->pin_list[U8G_PI_A0_STATE] = arg_val;
+ u8g->pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again */
+ break;
+
+ } // switch
+ return 1;
+}
+
+#endif // HAS_MARLINUI_U8GLIB
+
+#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp b/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp
new file mode 100644
index 0000000000..c96e0f56f4
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp
@@ -0,0 +1,138 @@
+/**
+ * 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 .
+ *
+ */
+
+/**
+ * Based on u8g_com_LPC1768_st7920_hw_spi.c
+ *
+ * Universal 8bit Graphics Library
+ *
+ * Copyright (c) 2011, olikraus@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef TARGET_LPC4078
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if HAS_MARLINUI_U8GLIB
+
+#include
+#include "../../shared/HAL_SPI.h"
+#include "../../shared/Delay.h"
+
+void spiBegin();
+void spiInit(uint8_t spiRate);
+void spiSend(uint8_t b);
+void spiSend(const uint8_t *buf, size_t n);
+
+static uint8_t rs_last_state = 255;
+
+static void u8g_com_LPC1768_st7920_write_byte_hw_spi(uint8_t rs, uint8_t val) {
+
+ if (rs != rs_last_state) { // Time to send a command/data byte
+ rs_last_state = rs;
+ spiSend(rs ? 0x0FA : 0x0F8); // Send data or command
+ DELAY_US(40); // Give the controller some time: 20 is bad, 30 is OK, 40 is safe
+ }
+
+ spiSend(val & 0xF0);
+ spiSend(val << 4);
+}
+
+uint8_t u8g_com_HAL_LPC1768_ST7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
+ switch (msg) {
+ case U8G_COM_MSG_INIT:
+ u8g_SetPILevel(u8g, U8G_PI_CS, 0);
+ u8g_SetPIOutput(u8g, U8G_PI_CS);
+ u8g_Delay(5);
+ spiBegin();
+ spiInit(SPI_EIGHTH_SPEED); // ST7920 max speed is about 1.1 MHz
+ u8g->pin_list[U8G_PI_A0_STATE] = 0; // initial RS state: command mode
+ break;
+
+ case U8G_COM_MSG_STOP:
+ break;
+
+ case U8G_COM_MSG_RESET:
+ u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
+ break;
+
+ case U8G_COM_MSG_ADDRESS: // Define cmd (arg_val = 0) or data mode (arg_val = 1)
+ u8g->pin_list[U8G_PI_A0_STATE] = arg_val;
+ break;
+
+ case U8G_COM_MSG_CHIP_SELECT:
+ u8g_SetPILevel(u8g, U8G_PI_CS, arg_val); // Note: the ST7920 has an active high chip-select
+ break;
+
+ case U8G_COM_MSG_WRITE_BYTE:
+ u8g_com_LPC1768_st7920_write_byte_hw_spi(u8g->pin_list[U8G_PI_A0_STATE], arg_val);
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ: {
+ uint8_t *ptr = (uint8_t*) arg_ptr;
+ while (arg_val > 0) {
+ u8g_com_LPC1768_st7920_write_byte_hw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
+ arg_val--;
+ }
+ }
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ_P: {
+ uint8_t *ptr = (uint8_t*) arg_ptr;
+ while (arg_val > 0) {
+ u8g_com_LPC1768_st7920_write_byte_hw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
+ arg_val--;
+ }
+ }
+ break;
+ }
+ return 1;
+}
+
+#endif // HAS_MARLINUI_U8GLIB
+
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp b/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp
new file mode 100644
index 0000000000..436a972850
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp
@@ -0,0 +1,147 @@
+/**
+ * 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 .
+ *
+ */
+
+/**
+ * Based on u8g_com_st7920_hw_spi.c
+ *
+ * Universal 8bit Graphics Library
+ *
+ * Copyright (c) 2011, olikraus@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef TARGET_LPC4078
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if IS_U8GLIB_ST7920
+
+#include
+#include "../SoftwareSPI.h"
+#include "../../shared/Delay.h"
+#include "../../shared/HAL_SPI.h"
+
+#ifndef LCD_SPI_SPEED
+ #define LCD_SPI_SPEED SPI_EIGHTH_SPEED // About 1 MHz
+#endif
+
+static pin_t SCK_pin_ST7920_HAL, MOSI_pin_ST7920_HAL_HAL;
+static uint8_t SPI_speed = 0;
+
+static void u8g_com_LPC1768_st7920_write_byte_sw_spi(uint8_t rs, uint8_t val) {
+ static uint8_t rs_last_state = 255;
+ if (rs != rs_last_state) {
+ // Transfer Data (FA) or Command (F8)
+ swSpiTransfer(rs ? 0x0FA : 0x0F8, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
+ rs_last_state = rs;
+ DELAY_US(40); // Give the controller time to process the data: 20 is bad, 30 is OK, 40 is safe
+ }
+ swSpiTransfer(val & 0x0F0, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
+ swSpiTransfer(val << 4, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
+}
+
+uint8_t u8g_com_HAL_LPC1768_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
+ switch (msg) {
+ case U8G_COM_MSG_INIT:
+ SCK_pin_ST7920_HAL = u8g->pin_list[U8G_PI_SCK];
+ MOSI_pin_ST7920_HAL_HAL = u8g->pin_list[U8G_PI_MOSI];
+
+ u8g_SetPIOutput(u8g, U8G_PI_CS);
+ u8g_SetPIOutput(u8g, U8G_PI_SCK);
+ u8g_SetPIOutput(u8g, U8G_PI_MOSI);
+ u8g_Delay(5);
+
+ SPI_speed = swSpiInit(LCD_SPI_SPEED, SCK_pin_ST7920_HAL, MOSI_pin_ST7920_HAL_HAL);
+
+ u8g_SetPILevel(u8g, U8G_PI_CS, 0);
+ u8g_SetPILevel(u8g, U8G_PI_SCK, 0);
+ u8g_SetPILevel(u8g, U8G_PI_MOSI, 0);
+
+ u8g->pin_list[U8G_PI_A0_STATE] = 0; /* initial RS state: command mode */
+ break;
+
+ case U8G_COM_MSG_STOP:
+ break;
+
+ case U8G_COM_MSG_RESET:
+ if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
+ break;
+
+ case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
+ u8g->pin_list[U8G_PI_A0_STATE] = arg_val;
+ break;
+
+ case U8G_COM_MSG_CHIP_SELECT:
+ if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_CS]) u8g_SetPILevel(u8g, U8G_PI_CS, arg_val); //note: the st7920 has an active high chip select
+ break;
+
+ case U8G_COM_MSG_WRITE_BYTE:
+ u8g_com_LPC1768_st7920_write_byte_sw_spi(u8g->pin_list[U8G_PI_A0_STATE], arg_val);
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ: {
+ uint8_t *ptr = (uint8_t*) arg_ptr;
+ while (arg_val > 0) {
+ u8g_com_LPC1768_st7920_write_byte_sw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
+ arg_val--;
+ }
+ }
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ_P: {
+ uint8_t *ptr = (uint8_t*) arg_ptr;
+ while (arg_val > 0) {
+ u8g_com_LPC1768_st7920_write_byte_sw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
+ arg_val--;
+ }
+ }
+ break;
+ }
+ return 1;
+}
+
+#endif // IS_U8GLIB_ST7920
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp b/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp
new file mode 100644
index 0000000000..03cd7b48a9
--- /dev/null
+++ b/Marlin/src/HAL/LPC4078/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp
@@ -0,0 +1,209 @@
+/**
+ * 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 .
+ *
+ */
+
+/**
+ * Based on u8g_com_std_sw_spi.c
+ *
+ * Universal 8bit Graphics Library
+ *
+ * Copyright (c) 2015, olikraus@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef TARGET_LPC4078
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920
+
+#include
+#include "../../shared/HAL_SPI.h"
+
+#ifndef LCD_SPI_SPEED
+ #define LCD_SPI_SPEED SPI_QUARTER_SPEED // About 2 MHz
+#endif
+
+#include
+#include
+#include
+#include
+
+#include
+
+uint8_t swSpiTransfer_mode_0(uint8_t b, const uint8_t spi_speed, const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin ) {
+
+ LOOP_L_N(i, 8) {
+ if (spi_speed == 0) {
+ LPC176x::gpio_set(mosi_pin, !!(b & 0x80));
+ LPC176x::gpio_set(sck_pin, HIGH);
+ b <<= 1;
+ if (miso_pin >= 0 && LPC176x::gpio_get(miso_pin)) b |= 1;
+ LPC176x::gpio_set(sck_pin, LOW);
+ }
+ else {
+ const uint8_t state = (b & 0x80) ? HIGH : LOW;
+ LOOP_L_N(j, spi_speed)
+ LPC176x::gpio_set(mosi_pin, state);
+
+ LOOP_L_N(j, spi_speed + (miso_pin >= 0 ? 0 : 1))
+ LPC176x::gpio_set(sck_pin, HIGH);
+
+ b <<= 1;
+ if (miso_pin >= 0 && LPC176x::gpio_get(miso_pin)) b |= 1;
+
+ LOOP_L_N(j, spi_speed)
+ LPC176x::gpio_set(sck_pin, LOW);
+ }
+ }
+
+ return b;
+}
+
+uint8_t swSpiTransfer_mode_3(uint8_t b, const uint8_t spi_speed, const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin ) {
+
+ LOOP_L_N(i, 8) {
+ const uint8_t state = (b & 0x80) ? HIGH : LOW;
+ if (spi_speed == 0) {
+ LPC176x::gpio_set(sck_pin, LOW);
+ LPC176x::gpio_set(mosi_pin, state);
+ LPC176x::gpio_set(mosi_pin, state); // need some setup time
+ LPC176x::gpio_set(sck_pin, HIGH);
+ }
+ else {
+ LOOP_L_N(j, spi_speed + (miso_pin >= 0 ? 0 : 1))
+ LPC176x::gpio_set(sck_pin, LOW);
+
+ LOOP_L_N(j, spi_speed)
+ LPC176x::gpio_set(mosi_pin, state);
+
+ LOOP_L_N(j, spi_speed)
+ LPC176x::gpio_set(sck_pin, HIGH);
+ }
+ b <<= 1;
+ if (miso_pin >= 0 && LPC176x::gpio_get(miso_pin)) b |= 1;
+ }
+
+ return b;
+}
+
+static uint8_t SPI_speed = 0;
+
+static void u8g_sw_spi_HAL_LPC1768_shift_out(uint8_t dataPin, uint8_t clockPin, uint8_t val) {
+ #if EITHER(FYSETC_MINI_12864, MKS_MINI_12864)
+ swSpiTransfer_mode_3(val, SPI_speed, clockPin, -1, dataPin);
+ #else
+ swSpiTransfer_mode_0(val, SPI_speed, clockPin, -1, dataPin);
+ #endif
+}
+
+uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
+ switch (msg) {
+ case U8G_COM_MSG_INIT:
+ u8g_SetPIOutput(u8g, U8G_PI_SCK);
+ u8g_SetPIOutput(u8g, U8G_PI_MOSI);
+ u8g_SetPIOutput(u8g, U8G_PI_CS);
+ u8g_SetPIOutput(u8g, U8G_PI_A0);
+ if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_SetPIOutput(u8g, U8G_PI_RESET);
+ SPI_speed = swSpiInit(LCD_SPI_SPEED, u8g->pin_list[U8G_PI_SCK], u8g->pin_list[U8G_PI_MOSI]);
+ u8g_SetPILevel(u8g, U8G_PI_SCK, 0);
+ u8g_SetPILevel(u8g, U8G_PI_MOSI, 0);
+ break;
+
+ case U8G_COM_MSG_STOP:
+ break;
+
+ case U8G_COM_MSG_RESET:
+ if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
+ break;
+
+ case U8G_COM_MSG_CHIP_SELECT:
+ #if EITHER(FYSETC_MINI_12864, MKS_MINI_12864) // LCD SPI is running mode 3 while SD card is running mode 0
+ if (arg_val) { // SCK idle state needs to be set to the proper idle state before
+ // the next chip select goes active
+ u8g_SetPILevel(u8g, U8G_PI_SCK, 1); // Set SCK to mode 3 idle state before CS goes active
+ u8g_SetPILevel(u8g, U8G_PI_CS, LOW);
+ }
+ else {
+ u8g_SetPILevel(u8g, U8G_PI_CS, HIGH);
+ u8g_SetPILevel(u8g, U8G_PI_SCK, 0); // Set SCK to mode 0 idle state after CS goes inactive
+ }
+ #else
+ u8g_SetPILevel(u8g, U8G_PI_CS, !arg_val);
+ #endif
+ break;
+
+ case U8G_COM_MSG_WRITE_BYTE:
+ u8g_sw_spi_HAL_LPC1768_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], arg_val);
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ: {
+ uint8_t *ptr = (uint8_t *)arg_ptr;
+ while (arg_val > 0) {
+ u8g_sw_spi_HAL_LPC1768_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], *ptr++);
+ arg_val--;
+ }
+ }
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ_P: {
+ uint8_t *ptr = (uint8_t *)arg_ptr;
+ while (arg_val > 0) {
+ u8g_sw_spi_HAL_LPC1768_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], u8g_pgm_read(ptr));
+ ptr++;
+ arg_val--;
+ }
+ }
+ break;
+
+ case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
+ u8g_SetPILevel(u8g, U8G_PI_A0, arg_val);
+ break;
+ }
+ return 1;
+}
+
+#endif // HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920
+#endif // TARGET_LPC4078
diff --git a/Marlin/src/HAL/platforms.h b/Marlin/src/HAL/platforms.h
index 9eaf7cea98..c8e644087b 100644
--- a/Marlin/src/HAL/platforms.h
+++ b/Marlin/src/HAL/platforms.h
@@ -37,6 +37,8 @@
#define HAL_PATH(PATH, NAME) XSTR(PATH/HAL/LPC1768/NAME)
#elif defined(ARDUINO_ARCH_HC32)
#define HAL_PATH(PATH, NAME) XSTR(PATH/HAL/HC32/NAME)
+#elif defined(TARGET_LPC4078)
+ #define HAL_PATH(PATH, NAME) XSTR(PATH/HAL/LPC4078/NAME)
#elif defined(__STM32F1__) || defined(TARGET_STM32F1)
#define HAL_PATH(PATH, NAME) XSTR(PATH/HAL/STM32F1/NAME)
#elif defined(ARDUINO_ARCH_STM32)
diff --git a/Marlin/src/HAL/shared/servo.h b/Marlin/src/HAL/shared/servo.h
index 786c1e6a72..434e5b4055 100644
--- a/Marlin/src/HAL/shared/servo.h
+++ b/Marlin/src/HAL/shared/servo.h
@@ -76,6 +76,8 @@
#include "../LPC1768/Servo.h"
#elif defined(ARDUINO_ARCH_HC32)
#include "../HC32/Servo.h"
+#elif defined(TARGET_LPC4078)
+ #include "../LPC4078/Servo.h"
#elif defined(__STM32F1__) || defined(TARGET_STM32F1)
#include "../STM32F1/Servo.h"
#elif defined(ARDUINO_ARCH_STM32)
diff --git a/Marlin/src/core/boards.h b/Marlin/src/core/boards.h
index 21aeab6c3b..1c90e3c734 100644
--- a/Marlin/src/core/boards.h
+++ b/Marlin/src/core/boards.h
@@ -410,6 +410,7 @@
#define BOARD_TEENSY31_32 5100 // Teensy3.1 and Teensy3.2
#define BOARD_TEENSY35_36 5101 // Teensy3.5 and Teensy3.6
+#define BOARD_EBAB 5102
//
// STM32 ARM Cortex-M4F
diff --git a/Marlin/src/pins/lpc4078/pins_EBAB.h b/Marlin/src/pins/lpc4078/pins_EBAB.h
new file mode 100644
index 0000000000..83fa5bac4f
--- /dev/null
+++ b/Marlin/src/pins/lpc4078/pins_EBAB.h
@@ -0,0 +1,605 @@
+/**
+ * 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 .
+ *
+ */
+#pragma once
+
+#ifndef BOARD_INFO_NAME
+ #define BOARD_INFO_NAME "Extra Big Ass Board"
+#endif
+
+#ifndef DEFAULT_MACHINE_NAME
+ #define DEFAULT_MACHINE_NAME "XtraBigAssBoard"
+#endif
+
+#define LED_PIN P3_18 // PWM0_3
+
+// EXTRA PINS
+#define FIL_RUNOUT_PIN P1_12
+#define PS_ON_PIN P3_15
+
+// DRIVERS EXTRA PINS
+#define DRIVERS_SCK P1_20
+#define DRIVERS_MISO P1_23
+#define DRIVERS_MOSI P1_24
+
+
+//
+// Servos
+//
+#define SERVO0_PIN P2_05 // PWM1_6
+#define SERVO1_PIN P2_04 // PWM1_5
+#define SERVO2_PIN P2_03 // PWM1_4
+#define SERVO3_PIN P2_02 // PWM1_3
+
+
+//
+// Limit Switches
+//
+#define X_MIN_PIN P0_19
+#define X_MAX_PIN P0_18
+#define Y_MIN_PIN P0_20
+#define Y_MAX_PIN P0_17
+#define Z_MIN_PIN P0_21
+#define Z_MAX_PIN P0_15
+
+//
+// Z Probe (when not Z_MIN_PIN)
+//
+#ifndef Z_MIN_PROBE_PIN
+ #define Z_MIN_PROBE_PIN P0_21
+#endif
+
+//
+// Steppers
+//
+#define X_STEP_PIN P0_10
+#define X_DIR_PIN P4_03
+#define X_ENABLE_PIN P0_01
+#define X_CS_PIN P0_00
+#define X_DIAG_PIN P2_17
+
+#define Y_STEP_PIN P1_29
+#define Y_DIR_PIN P2_14
+#define Y_ENABLE_PIN P1_28
+#define Y_CS_PIN P2_22
+#define Y_DIAG_PIN P2_16
+
+#define Z_STEP_PIN P4_02
+#define Z_DIR_PIN P1_26
+#define Z_ENABLE_PIN P1_25
+#define Z_CS_PIN P4_01
+#define Z_DIAG_PIN P2_21
+
+#define E0_STEP_PIN P1_19
+#define E0_DIR_PIN P0_14
+#define E0_ENABLE_PIN P1_22
+#define E0_CS_PIN P4_00
+#define E0_DIAG_PIN P2_20
+
+#define E1_STEP_PIN P2_23
+#define E1_DIR_PIN P2_18
+#define E1_ENABLE_PIN P3_23
+#define E1_CS_PIN P1_18
+#define E1_DIAG_PIN P2_19
+
+#define E2_STEP_PIN P3_26
+#define E2_DIR_PIN P2_25
+#define E2_ENABLE_PIN P3_25
+#define E2_CS_PIN P3_24
+#define E2_DIAG_PIN P2_26
+
+#define E3_STEP_PIN P4_19
+#define E3_DIR_PIN P4_20
+#define E3_ENABLE_PIN P4_26
+#define E3_CS_PIN P4_21
+#define E3_DIAG_PIN P0_22
+
+#define E4_STEP_PIN P4_17
+#define E4_DIR_PIN P4_18
+#define E4_ENABLE_PIN P4_05
+#define E4_CS_PIN P2_12
+#define E4_DIAG_PIN P2_11
+
+#define E5_STEP_PIN P0_11
+#define E5_DIR_PIN P2_15
+#define E5_ENABLE_PIN P4_04
+#define E5_CS_PIN P4_16
+#define E5_DIAG_PIN P2_13
+
+#define E6_STEP_PIN P2_28
+#define E6_DIR_PIN P0_28
+#define E6_ENABLE_PIN P0_31
+#define E6_CS_PIN P0_27
+#define E6_DIAG_PIN P2_24
+
+#define E7_STEP_PIN P1_30
+#define E7_DIR_PIN P0_12
+#define E7_ENABLE_PIN P0_13
+#define E7_CS_PIN P2_29
+#define E7_DIAG_PIN P2_27
+
+#define E8_STEP_PIN P3_15
+#define E8_DIR_PIN P3_07
+#define E8_ENABLE_PIN P2_30
+#define E8_CS_PIN P5_01
+#define E8_DIAG_PIN P2_31
+
+
+#if HAS_TMC_UART
+ #define X_SERIAL_TX_PIN P0_00
+ #define X_SERIAL_RX_PIN P0_00
+ #define Y_SERIAL_TX_PIN P2_22
+ #define Y_SERIAL_RX_PIN P2_22
+ #define Z_SERIAL_TX_PIN P4_01
+ #define Z_SERIAL_RX_PIN P4_01
+ #define E0_SERIAL_TX_PIN P4_00
+ #define E0_SERIAL_RX_PIN P4_00
+ #define E1_SERIAL_TX_PIN P1_18
+ #define E1_SERIAL_RX_PIN P1_18
+ #define E2_SERIAL_TX_PIN P3_24
+ #define E2_SERIAL_RX_PIN P3_24
+ #define E3_SERIAL_TX_PIN P4_21
+ #define E3_SERIAL_RX_PIN P4_21
+ #define E4_SERIAL_TX_PIN P2_12
+ #define E4_SERIAL_RX_PIN P2_12
+ #define E5_SERIAL_TX_PIN P4_16
+ #define E5_SERIAL_RX_PIN P4_16
+ #define E6_SERIAL_TX_PIN P0_27
+ #define E6_SERIAL_RX_PIN P0_27
+ #define E7_SERIAL_TX_PIN P2_29
+ #define E7_SERIAL_RX_PIN P2_29
+ #define E8_SERIAL_TX_PIN P5_01
+ #define E8_SERIAL_RX_PIN P5_01
+
+ // Reduce baud rate to improve software serial reliability
+ #define TMC_BAUD_RATE 19200
+#endif // HAS_TMC_UART
+
+//
+// Temperature Sensors
+//
+#define TEMP_0_PIN P0_23
+#define TEMP_1_PIN P0_24
+#define TEMP_2_PIN P0_25
+#define TEMP_3_PIN P0_26
+#define TEMP_BED_PIN P1_31
+
+//
+// Heaters / Fans
+//
+
+#define HEATER_0_PIN P1_02
+#define HEATER_1_PIN P1_10
+#define HEATER_2_PIN P4_30
+#define HEATER_3_PIN P1_09
+#define HEATER_BED_PIN P4_23
+
+#define FAN0_PIN P3_08
+#define FAN1_PIN P3_00
+#define FAN2_PIN P3_27 //PWM1_4
+#define FAN3_PIN P5_04
+
+#define EFAN0_PIN P1_08
+#define EFAN1_PIN P4_31
+#define EFAN2_PIN P3_01
+#define EFAN3_PIN P3_10
+//
+// Misc. Functions
+//
+#if SD_CONNECTION_IS(LCD)
+ #define SD_DETECT_PIN P3_02
+ #define SD_SCK_PIN P1_00
+ #define SD_MISO_PIN P1_04
+ #define SD_MOSI_PIN P1_01
+ #define SD_SS_PIN P3_03
+ #define SDSS SD_SS_PIN
+#elif SD_CONNECTION_IS(ONBOARD)
+ #define SD_DETECT_PIN P_NC
+ #define SD_SCK_PIN P0_07
+ #define SD_MISO_PIN P0_08
+ #define SD_MOSI_PIN P0_09
+ #define ONBOARD_SD_CS_PIN P0_06
+ #define SD_SS_PIN ONBOARD_SD_CS_PIN
+ #define SDSS SD_SS_PIN
+#endif
+
+#ifndef NEOPIXEL_PIN
+ #define NEOPIXEL_PIN P_NC
+#endif
+
+#ifndef FILWIDTH_PIN
+ #define FILWIDTH_PIN P_NC
+#endif
+
+#ifndef FIL_RUNOUT_PIN
+ #define FIL_RUNOUT_PIN P_NC
+#endif
+
+#ifndef PS_ON_PIN
+ #define PS_ON_PIN P_NC
+#endif
+
+//
+// Průša i3 MK2 Multiplexer Support
+//
+#if HAS_PRUSA_MMU1
+ #ifndef E_MUX0_PIN
+ #define E_MUX0_PIN P_NC
+ #endif
+ #ifndef E_MUX1_PIN
+ #define E_MUX1_PIN P_NC
+ #endif
+ #ifndef E_MUX2_PIN
+ #define E_MUX2_PIN P_NC
+ #endif
+#endif
+
+/**
+ * Default pins for TMC software SPI
+ */
+#if ENABLED(TMC_USE_SW_SPI)
+ #ifndef TMC_SW_MOSI
+ #define TMC_SW_MOSI P1_24
+ #endif
+ #ifndef TMC_SW_MISO
+ #define TMC_SW_MISO P1_23
+ #endif
+ #ifndef TMC_SW_SCK
+ #define TMC_SW_SCK P1_20
+ #endif
+#endif
+
+
+//////////////////////////
+// LCDs and Controllers //
+//////////////////////////
+
+#if ANY(TFT_COLOR_UI, TFT_CLASSIC_UI, TFT_LVGL_UI)
+
+ #define TFT_A0_PIN 43
+ #define TFT_CS_PIN 49
+ #define TFT_DC_PIN 43
+ #define TFT_SCK_PIN SD_SCK_PIN
+ #define TFT_MOSI_PIN SD_MOSI_PIN
+ #define TFT_MISO_PIN SD_MISO_PIN
+ #define LCD_USE_DMA_SPI
+
+ #define BTN_EN1 40
+ #define BTN_EN2 63
+ #define BTN_ENC 59
+ #define BEEPER_PIN 42
+
+ #define TOUCH_CS_PIN 33
+
+ #define SD_DETECT_PIN 41
+
+ #define SPI_FLASH
+ #if ENABLED(SPI_FLASH)
+ #define SPI_DEVICE 1
+ #define SPI_FLASH_SIZE 0x1000000 // 16MB
+ #define SPI_FLASH_CS_PIN 31
+ #define SPI_FLASH_MOSI_PIN SD_MOSI_PIN
+ #define SPI_FLASH_MISO_PIN SD_MISO_PIN
+ #define SPI_FLASH_SCK_PIN SD_SCK_PIN
+ #endif
+
+ #define TFT_BUFFER_SIZE 0xFFFF
+ #ifndef TFT_DRIVER
+ #define TFT_DRIVER ST7796
+ #endif
+ #ifndef TOUCH_SCREEN_CALIBRATION
+ #if ENABLED(TFT_RES_320x240)
+ #ifndef TOUCH_CALIBRATION_X
+ #define TOUCH_CALIBRATION_X 20525
+ #endif
+ #ifndef TOUCH_CALIBRATION_Y
+ #define TOUCH_CALIBRATION_Y 15335
+ #endif
+ #ifndef TOUCH_OFFSET_X
+ #define TOUCH_OFFSET_X -1
+ #endif
+ #ifndef TOUCH_OFFSET_Y
+ #define TOUCH_OFFSET_Y 0
+ #endif
+ #elif ENABLED(TFT_RES_480x272)
+ #ifndef TOUCH_CALIBRATION_X
+ #define TOUCH_CALIBRATION_X 30715
+ #endif
+ #ifndef TOUCH_CALIBRATION_Y
+ #define TOUCH_CALIBRATION_Y 17415
+ #endif
+ #ifndef TOUCH_OFFSET_X
+ #define TOUCH_OFFSET_X 0
+ #endif
+ #ifndef TOUCH_OFFSET_Y
+ #define TOUCH_OFFSET_Y -1
+ #endif
+ #elif ENABLED(TFT_RES_480x320)
+ #ifndef TOUCH_CALIBRATION_X
+ #define TOUCH_CALIBRATION_X 30595
+ #endif
+ #ifndef TOUCH_CALIBRATION_Y
+ #define TOUCH_CALIBRATION_Y 20415
+ #endif
+ #ifndef TOUCH_OFFSET_X
+ #define TOUCH_OFFSET_X 2
+ #endif
+ #ifndef TOUCH_OFFSET_Y
+ #define TOUCH_OFFSET_Y 1
+ #endif
+ #elif ENABLED(TFT_RES_1024x600)
+ #ifndef TOUCH_CALIBRATION_X
+ #define TOUCH_CALIBRATION_X 65533
+ #endif
+ #ifndef TOUCH_CALIBRATION_Y
+ #define TOUCH_CALIBRATION_Y 38399
+ #endif
+ #ifndef TOUCH_OFFSET_X
+ #define TOUCH_OFFSET_X 2
+ #endif
+ #ifndef TOUCH_OFFSET_Y
+ #define TOUCH_OFFSET_Y 1
+ #endif
+ #endif
+ #endif
+
+ #define BTN_BACK 70
+
+#elif HAS_WIRED_LCD
+
+ //
+ // LCD Display output pins
+ //
+ #if ENABLED(REPRAPWORLD_GRAPHICAL_LCD)
+
+ #define LCD_PINS_RS P3_06 // CS chip select /SS chip slave select
+ #define LCD_PINS_EN P3_14 // SID (MOSI)
+ #define LCD_PINS_D4 P3_30 // SCK (CLK) clock
+
+ #elif ALL(IS_NEWPANEL, PANEL_ONE)
+
+ #define LCD_PINS_RS 40
+ #define LCD_PINS_EN 42
+ #define LCD_PINS_D4 65
+ #define LCD_PINS_D5 66
+ #define LCD_PINS_D6 44
+ #define LCD_PINS_D7 64
+
+ #else
+
+ #if ENABLED(CR10_STOCKDISPLAY)
+
+ #define LCD_PINS_RS 27
+ #define LCD_PINS_EN 29
+ #define LCD_PINS_D4 25
+
+ #if !IS_NEWPANEL
+ #define BEEPER_PIN 37
+ #endif
+
+ #elif ENABLED(ZONESTAR_LCD)
+
+ #define LCD_PINS_RS 64
+ #define LCD_PINS_EN 44
+ #define LCD_PINS_D4 63
+ #define LCD_PINS_D5 40
+ #define LCD_PINS_D6 42
+ #define LCD_PINS_D7 65
+
+ #else
+
+ #if ANY(MKS_12864OLED, MKS_12864OLED_SSD1306)
+ #define LCD_PINS_DC 25 // Set as output on init
+ #define LCD_PINS_RS 27 // Pull low for 1s to init
+ // DOGM SPI LCD Support
+ #define DOGLCD_CS 16
+ #define DOGLCD_MOSI 17
+ #define DOGLCD_SCK 23
+ #define DOGLCD_A0 LCD_PINS_DC
+ #else
+ #define LCD_PINS_RS P3_06
+ #define LCD_PINS_EN P3_14
+ #define LCD_PINS_D4 P3_30
+ #define LCD_PINS_D5 P3_05
+ #define LCD_PINS_D6 P3_29
+ #endif
+
+ #define LCD_PINS_D7 P5_00
+
+ #if !IS_NEWPANEL
+ #define BEEPER_PIN 33
+ #endif
+
+ #endif
+
+ #if !IS_NEWPANEL
+ // Buttons attached to a shift register
+ // Not wired yet
+ //#define SHIFT_CLK_PIN 38
+ //#define SHIFT_LD_PIN 42
+ //#define SHIFT_OUT_PIN 40
+ //#define SHIFT_EN_PIN 17
+ #endif
+
+ #endif
+
+ //
+ // LCD Display input pins
+ //
+ #if IS_NEWPANEL
+
+ #if ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER)
+
+ #define BEEPER_PIN P3_31
+
+ #if ENABLED(CR10_STOCKDISPLAY)
+ #define BTN_EN1 17
+ #define BTN_EN2 23
+ #else
+ #define BTN_EN1 P3_11
+ #define BTN_EN2 P3_12
+ #endif
+
+ #define BTN_ENC P3_28
+ #define SD_DETECT_PIN P3_02
+ //#define KILL_PIN P_NC
+
+ #if ENABLED(BQ_LCD_SMART_CONTROLLER)
+ #define LCD_BACKLIGHT_PIN 39
+ #endif
+
+ #elif ENABLED(REPRAPWORLD_GRAPHICAL_LCD)
+
+ #define BTN_EN1 64
+ #define BTN_EN2 59
+ #define BTN_ENC 63
+ #define SD_DETECT_PIN 42
+
+ #elif ENABLED(LCD_I2C_PANELOLU2)
+
+ #define BTN_EN1 47
+ #define BTN_EN2 43
+ #define BTN_ENC 32
+ #define LCD_SDSS SDSS
+ #define KILL_PIN 41
+
+ #elif ENABLED(LCD_I2C_VIKI)
+
+ #define BTN_EN1 22 // https://files.panucatt.com/datasheets/viki_wiring_diagram.pdf explains 40/42.
+ #define BTN_EN2 7 // 22/7 are unused on RAMPS_14. 22 is unused and 7 the SERVO0_PIN on RAMPS_13.
+ #define BTN_ENC -1
+
+ #define LCD_SDSS SDSS
+ #define SD_DETECT_PIN 49
+
+ #elif ANY(VIKI2, miniVIKI)
+
+ #define DOGLCD_CS 45
+ #define DOGLCD_A0 44
+
+ #define BEEPER_PIN 33
+ #define STAT_LED_RED_PIN 32
+ #define STAT_LED_BLUE_PIN 35
+
+ #define BTN_EN1 22
+ #define BTN_EN2 7
+ #define BTN_ENC 39
+
+ #define SD_DETECT_PIN -1 // Pin 49 for display sd interface, 72 for easy adapter board
+ #define KILL_PIN 31
+
+ #define LCD_SCREEN_ROTATE 180 // 0, 90, 180, 270
+
+ #elif ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
+
+ #define DOGLCD_CS 29
+ #define DOGLCD_A0 27
+
+ #define BEEPER_PIN 23
+ #define LCD_BACKLIGHT_PIN 33
+
+ #define BTN_EN1 35
+ #define BTN_EN2 37
+ #define BTN_ENC 31
+
+ #define LCD_SDSS SDSS
+ #define SD_DETECT_PIN 49
+ #define KILL_PIN 41
+
+ #elif ENABLED(MKS_MINI_12864)
+
+ #define DOGLCD_A0 27
+ #define DOGLCD_CS 25
+
+ #define BEEPER_PIN 37
+ // not connected to a pin
+ #define LCD_BACKLIGHT_PIN 65 // backlight LED on A11/D65
+
+ #define BTN_EN1 31
+ #define BTN_EN2 33
+ #define BTN_ENC 35
+
+ #define SD_DETECT_PIN 49
+ #define KILL_PIN 64
+
+ //#define LCD_SCREEN_ROTATE 180 // 0, 90, 180, 270
+
+ #elif ENABLED(MINIPANEL)
+
+ #define BEEPER_PIN 42
+ // not connected to a pin
+ #define LCD_BACKLIGHT_PIN 65 // backlight LED on A11/D65
+
+ #define DOGLCD_A0 44
+ #define DOGLCD_CS 66
+
+ #define BTN_EN1 40
+ #define BTN_EN2 63
+ #define BTN_ENC 59
+
+ #define SD_DETECT_PIN 49
+ #define KILL_PIN 64
+
+ //#define LCD_SCREEN_ROTATE 180 // 0, 90, 180, 270
+
+ #elif ENABLED(ZONESTAR_LCD)
+
+ #define ADC_KEYPAD_PIN 12
+
+ #elif ENABLED(AZSMZ_12864)
+
+ // Pins only defined for RAMPS_SMART currently
+
+ #else
+
+ // Beeper on AUX-4
+ #define BEEPER_PIN P3_31
+
+ // Buttons are directly attached to AUX-2
+ #if IS_RRW_KEYPAD
+ #define SHIFT_OUT_PIN 40
+ #define SHIFT_CLK_PIN 44
+ #define SHIFT_LD_PIN 42
+ #define BTN_EN1 64
+ #define BTN_EN2 59
+ #define BTN_ENC 63
+ #elif ENABLED(PANEL_ONE)
+ #define BTN_EN1 59 // AUX2 PIN 3
+ #define BTN_EN2 63 // AUX2 PIN 4
+ #define BTN_ENC 49 // AUX3 PIN 7
+ #else
+ #define BTN_EN1 P3_11
+ #define BTN_EN2 P3_12
+ #define BTN_ENC P3_28
+ #endif
+
+ #if ENABLED(G3D_PANEL)
+ #define SD_DETECT_PIN 49
+ #define KILL_PIN 41
+ #endif
+ #endif
+
+ // CUSTOM SIMULATOR INPUTS
+ #define BTN_BACK 70
+
+ #endif // IS_NEWPANEL
+
+#endif // HAS_WIRED_LCD
diff --git a/Marlin/src/pins/pins.h b/Marlin/src/pins/pins.h
index a9349910d7..b03f77fa51 100644
--- a/Marlin/src/pins/pins.h
+++ b/Marlin/src/pins/pins.h
@@ -504,6 +504,13 @@
#include "lpc1769/pins_BTT_SKR_E3_TURBO.h" // LPC1769 env:LPC1769
#elif MB(FLY_CDY)
#include "lpc1769/pins_FLY_CDY.h" // LPC1769 env:LPC1769
+//
+// LPC4078 ARM Cortex M4
+//
+
+#elif MB(EBAB)
+ #include "lpc4078/pins_EBAB.h" // LPC4078 env:LPC4078
+
//
// Due (ATSAM) boards
diff --git a/ini/lpc176x.ini b/ini/lpc176x.ini
index 8d5d2fd157..974debe59e 100644
--- a/ini/lpc176x.ini
+++ b/ini/lpc176x.ini
@@ -42,3 +42,27 @@ board = nxp_lpc1768
[env:LPC1769]
extends = common_LPC
board = nxp_lpc1769
+
+#
+# NXP LPC4078 ARM Cortex-M4
+#
+[env:LPC4078]
+board = nxp_lpc4078
+platform = symlink://C:\Users\DMenzel\Documents\GitHub\EBAB\ebab_platform\platform-mcui
+platform_packages = framework-arduino-mcui@symlink://C:\Users\DMenzel\Documents\GitHub\EBAB\ebab_platform\framework-arduino-mcui
+framework = arduino
+upload_protocol = jlink
+debug_tool = jlink
+monitor_speed = 500000
+lib_ldf_mode = off
+lib_compat_mode = strict
+extra_scripts = ${common.extra_scripts}
+ Marlin/src/HAL/LPC1768/upload_extra_script.py
+build_src_filter = ${common.default_src_filter} + +
+build_flags = ${common.build_flags} -IMarlin/src/HAL/LPC4078/include -DTARGET_LPC4078 -DU8G_HAL_LINKS -IMarlin/src/HAL/LPC4078/u8g -DPLATFORM_M997_SUPPORT -O3
+build_unflags = -Os
+lib_deps = ${common.lib_deps}
+ Servo
+ SoftwareSerial
+custom_marlin.USES_LIQUIDCRYSTAL = arduino-libraries/LiquidCrystal@~1.0.7
+custom_marlin.NEOPIXEL_LED = Adafruit NeoPixel=https://github.com/p3p/Adafruit_NeoPixel/archive/1.5.0.zip