diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 060c07bbbc7..71a92113300 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -2825,6 +2825,11 @@
 //#define REPRAPWORLD_KEYPAD
 //#define REPRAPWORLD_KEYPAD_MOVE_STEP 10.0 // (mm) Distance to move per key-press
 
+//
+// EasyThreeD ET-4000+ with button input and status LED
+//
+//#define EASYTHREED_UI
+
 //=============================================================================
 //=============================== Extra Features ==============================
 //=============================================================================
diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp
index 827d2af8646..941903149f3 100644
--- a/Marlin/src/MarlinCore.cpp
+++ b/Marlin/src/MarlinCore.cpp
@@ -248,6 +248,10 @@
   #include "feature/power.h"
 #endif
 
+#if ENABLED(EASYTHREED_UI)
+  #include "feature/easythreed_ui.h"
+#endif
+
 PGMSTR(M112_KILL_STR, "M112 Shutdown");
 
 MarlinState marlin_state = MF_INITIALIZING;
@@ -637,6 +641,8 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
     #endif
   #endif
 
+  TERN_(EASYTHREED_UI, easythreed_ui.run());
+
   TERN_(USE_CONTROLLER_FAN, controllerFan.update()); // Check if fan should be turned on to cool stepper drivers down
 
   TERN_(AUTO_POWER_CONTROL, powerManager.check(!ui.on_status_screen() || printJobOngoing() || printingIsPaused()));
@@ -1606,6 +1612,10 @@ void setup() {
     SETUP_RUN(ui.check_touch_calibration());
   #endif
 
+  #if ENABLED(EASYTHREED_UI)
+    SETUP_RUN(easythreed_ui.init());
+  #endif
+
   marlin_state = MF_RUNNING;
 
   SETUP_LOG("setup() completed.");
diff --git a/Marlin/src/feature/easythreed_ui.cpp b/Marlin/src/feature/easythreed_ui.cpp
new file mode 100644
index 00000000000..3eff233c014
--- /dev/null
+++ b/Marlin/src/feature/easythreed_ui.cpp
@@ -0,0 +1,236 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../inc/MarlinConfigPre.h"
+
+#if ENABLED(EASYTHREED_UI)
+
+#include "easythreed_ui.h"
+#include "pause.h"
+#include "../module/temperature.h"
+#include "../module/printcounter.h"
+#include "../sd/cardreader.h"
+#include "../gcode/queue.h"
+#include "../module/motion.h"
+#include "../module/planner.h"
+#include "../MarlinCore.h"
+
+EasythreedUI easythreed_ui;
+
+#define BTN_DEBOUNCE_MS 20
+
+void EasythreedUI::init() {
+  SET_INPUT_PULLUP(BTN_HOME);     SET_OUTPUT(BTN_HOME_GND);
+  SET_INPUT_PULLUP(BTN_FEED);     SET_OUTPUT(BTN_FEED_GND);
+  SET_INPUT_PULLUP(BTN_RETRACT);  SET_OUTPUT(BTN_RETRACT_GND);
+  SET_INPUT_PULLUP(BTN_PRINT);
+  SET_OUTPUT(EASYTHREED_LED_PIN);
+}
+
+void EasythreedUI::run() {
+  blinkLED();
+  loadButton();
+  printButton();
+}
+
+enum LEDInterval : uint16_t {
+  LED_OFF     =    0,
+  LED_ON      = 4000,
+  LED_BLINK_0 = 2500,
+  LED_BLINK_1 = 1500,
+  LED_BLINK_2 = 1000,
+  LED_BLINK_3 =  800,
+  LED_BLINK_4 =  500,
+  LED_BLINK_5 =  300,
+  LED_BLINK_6 =  150,
+  LED_BLINK_7 =   50
+};
+
+uint16_t blink_interval_ms = LED_ON;   // Status LED on Start button
+
+void EasythreedUI::blinkLED() {
+  static millis_t prev_blink_interval_ms = 0, blink_start_ms = 0;
+
+  if (blink_interval_ms == LED_OFF) { WRITE(EASYTHREED_LED_PIN, HIGH); return; } // OFF
+  if (blink_interval_ms >= LED_ON)  { WRITE(EASYTHREED_LED_PIN,  LOW); return; } // ON
+
+  const millis_t ms = millis();
+  if (prev_blink_interval_ms != blink_interval_ms) {
+    prev_blink_interval_ms = blink_interval_ms;
+    blink_start_ms = ms;
+  }
+  if (PENDING(ms, blink_start_ms + blink_interval_ms))
+    WRITE(EASYTHREED_LED_PIN, LOW);
+  else if (PENDING(ms, blink_start_ms + 2 * blink_interval_ms))
+    WRITE(EASYTHREED_LED_PIN, HIGH);
+  else
+    blink_start_ms = ms;
+}
+
+//
+// Filament Load/Unload Button
+// Load/Unload buttons are a 3 position switch with a common center ground. 
+//
+void EasythreedUI::loadButton() {
+  if (printingIsActive()) return;
+
+  enum FilamentStatus : uint8_t { FS_IDLE, FS_PRESS, FS_CHECK, FS_PROCEED };
+  static uint8_t filament_status = FS_IDLE;
+  static millis_t filament_time = 0;
+
+  switch (filament_status) {
+
+    case FS_IDLE:
+      if (!READ(BTN_RETRACT) || !READ(BTN_FEED)) {                  // If feed/retract switch is toggled...
+        filament_status++;                                          // ...proceed to next test.
+        filament_time = millis();
+      }
+      break;
+
+    case FS_PRESS:
+      if (ELAPSED(millis(), filament_time + BTN_DEBOUNCE_MS)) {     // After a short debounce delay...
+        if (!READ(BTN_RETRACT) || !READ(BTN_FEED)) {                // ...if switch still toggled...
+          thermalManager.setTargetHotend(EXTRUDE_MINTEMP + 10, 0);  // Start heating up
+          blink_interval_ms = LED_BLINK_7;                          // Set the LED to blink fast
+          filament_status++;
+        }
+        else
+          filament_status = FS_IDLE;                                // Switch not toggled long enough
+      }
+      break;
+
+    case FS_CHECK:
+      if (READ(BTN_RETRACT) && READ(BTN_FEED)) {                    // Switch in center position (stop)
+        blink_interval_ms = LED_ON;                                 // LED on steady
+        filament_status = FS_IDLE;
+        thermalManager.disable_all_heaters();
+      }
+      else if (thermalManager.hotEnoughToExtrude(0)) {              // Is the hotend hot enough to move material?
+        filament_status++;                                          // Proceed to feed / retract.
+        blink_interval_ms = LED_BLINK_5;                            // Blink ~3 times per second
+      }
+      break;
+
+    case FS_PROCEED: {
+      // Feed or Retract just once. Hard abort all moves and return to idle on swicth release.
+      static bool flag = false;
+      if (READ(BTN_RETRACT) && READ(BTN_FEED)) {                    // Switch in center position (stop)
+        flag = false;                                               // Restore flag to false
+        filament_status = FS_IDLE;                                  // Go back to idle state
+        quickstop_stepper();                                        // Hard-stop all the steppers ... now!
+        thermalManager.disable_all_heaters();                       // And disable all the heaters
+        blink_interval_ms = LED_ON;
+      }
+      else if (!flag) {
+        flag = true;
+        queue.inject(!READ(BTN_RETRACT) ? F("G91\nG0 E10 F180\nG0 E-120 F180\nM104 S0") : F("G91\nG0 E100 F120\nM104 S0"));
+      }
+    } break;
+  }
+
+}
+
+#if HAS_STEPPER_RESET
+  void disableStepperDrivers();
+#endif
+
+//
+// Print Start/Pause/Resume Button
+//
+void EasythreedUI::printButton() {
+  enum KeyStatus : uint8_t { KS_IDLE, KS_PRESS, KS_PROCEED };
+  static uint8_t key_status = KS_IDLE;
+  static millis_t key_time = 0;
+
+  enum PrintFlag : uint8_t { PF_START, PF_PAUSE, PF_RESUME };
+  static PrintFlag print_key_flag = PF_START;
+
+  const millis_t ms = millis();
+
+  switch (key_status) {
+    case KS_IDLE:
+      if (!READ(BTN_PRINT)) {                                       // Print/Pause/Resume button pressed?
+        key_time = ms;                                              // Save start time
+        key_status++;                                               // Go to debounce test
+      }
+      break;
+
+    case KS_PRESS:
+      if (ELAPSED(ms, key_time + BTN_DEBOUNCE_MS))                  // Wait for debounce interval to expire
+        key_status = READ(BTN_PRINT) ? KS_IDLE : KS_PROCEED;        // Proceed if still pressed
+      break;
+
+    case KS_PROCEED:
+      if (!READ(BTN_PRINT)) break;                                  // Wait for the button to be released
+      key_status = KS_IDLE;                                         // Ready for the next press
+      if (PENDING(ms, key_time + 1200 - BTN_DEBOUNCE_MS)) {         // Register a press < 1.2 seconds
+        switch (print_key_flag) {
+          case PF_START: {                                          // The "Print" button starts an SD card print
+            if (printingIsActive()) break;                          // Already printing? (find another line that checks for 'is planner doing anything else right now?')
+            blink_interval_ms = LED_BLINK_2;                        // Blink the indicator LED at 1 second intervals
+            print_key_flag = PF_PAUSE;                              // The "Print" button now pauses the print
+            card.mount();                                           // Force SD card to mount - now!
+            if (!card.isMounted) {                                  // Failed to mount?
+                blink_interval_ms = LED_OFF;                        // Turn off LED
+                print_key_flag = PF_START;
+                return;                                             // Bail out
+            }
+            card.ls();                                            // List all files to serial output
+            const uint16_t filecnt = card.countFilesInWorkDir();  // Count printable files in cwd
+            if (filecnt == 0) return;                             // None are printable?
+            card.selectFileByIndex(filecnt);                      // Select the last file according to current sort options
+            card.openAndPrintFile(card.filename);                 // Start printing it
+            break;
+          }
+          case PF_PAUSE: {                                          // Pause printing (not currently firing)
+            if (!printingIsActive()) break;
+            blink_interval_ms = LED_ON;                             // Set indicator to steady ON
+            queue.inject(F("M25"));                                 // Queue Pause
+            print_key_flag = PF_RESUME;                             // The "Print" button now resumes the print
+            break;
+            }
+          case PF_RESUME: {                                         // Resume printing 
+            if (printingIsActive()) break;
+            blink_interval_ms = LED_BLINK_2;                        // Blink the indicator LED at 1 second intervals
+            queue.inject(F("M24"));                                 // Queue resume
+            print_key_flag = PF_PAUSE;                              // The "Print" button now pauses the print
+            break;
+          }
+        }
+      }
+      else {                                                        // Register a longer press
+        if (print_key_flag == PF_START && !printingIsActive())  {   // While not printing, this moves Z up 10mm
+          blink_interval_ms = LED_ON;
+          queue.inject(F("G91\nG0 Z10 F600\nG90"));                 // Raise Z soon after returning to main loop
+        }
+        else {                                                      // While printing, cancel print
+          card.abortFilePrintSoon();                                // There is a delay while the current steps play out
+          blink_interval_ms = LED_OFF;                              // Turn off LED
+        }
+        planner.synchronize();                                      // Wait for commands already in the planner to finish
+        TERN_(HAS_STEPPER_RESET, disableStepperDrivers());          // Disable all steppers - now!
+        print_key_flag = PF_START;                                  // The "Print" button now starts a new print
+      }
+      break;
+  }
+}
+#endif // EASYTHREED_UI
diff --git a/Marlin/src/feature/easythreed_ui.h b/Marlin/src/feature/easythreed_ui.h
new file mode 100644
index 00000000000..af9ad2d090b
--- /dev/null
+++ b/Marlin/src/feature/easythreed_ui.h
@@ -0,0 +1,35 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+class EasythreedUI {
+  public:
+    static void init();
+    static void run();
+
+  private:
+    static void blinkLED();
+    static void loadButton();
+    static void printButton();
+};
+
+extern EasythreedUI easythreed_ui;
diff --git a/Marlin/src/pins/stm32f1/pins_MKS_ROBIN_LITE.h b/Marlin/src/pins/stm32f1/pins_MKS_ROBIN_LITE.h
index 94f7313996d..9f33d4392a1 100644
--- a/Marlin/src/pins/stm32f1/pins_MKS_ROBIN_LITE.h
+++ b/Marlin/src/pins/stm32f1/pins_MKS_ROBIN_LITE.h
@@ -79,31 +79,51 @@
 
 #define FIL_RUNOUT_PIN                      PB8   // MT_DET
 
+/**                ------
+ *   (BEEPER) PD2 |10  9 | PB3  (BTN_ENC)
+ *  (BTN_EN1) PB5 | 8  7 | PA11 (RESET?)
+ *  (BTN_EN2) PB4   6  5 | PC1  (LCD_D4)
+ *   (LCD_RS) PC3 | 4  3 | PC2  (LCD_EN)
+ *            GND | 2  1 | 5V
+ *                 ------
+ *               "E3" EXP1
+ */
+#define E3_EXP1_01_PIN                      -1    // 5V
+#define E3_EXP1_02_PIN                      -1    // GND
+#define E3_EXP1_03_PIN                      PC2
+#define E3_EXP1_04_PIN                      PC3
+#define E3_EXP1_05_PIN                      PC1
+#define E3_EXP1_06_PIN                      PB4
+#define E3_EXP1_07_PIN                      PA11  // RESET?
+#define E3_EXP1_08_PIN                      PB5
+#define E3_EXP1_09_PIN                      PB3
+#define E3_EXP1_10_PIN                      PD2
+
 //
 // LCD Pins
 //
 #if HAS_WIRED_LCD
-  #define BEEPER_PIN                        PD2
-  #define BTN_ENC                           PB3
-  #define LCD_PINS_RS                       PC3
+  #define BEEPER_PIN              E3_EXP1_10_PIN
+  #define BTN_ENC                 E3_EXP1_09_PIN
+  #define LCD_PINS_RS             E3_EXP1_04_PIN
 
-  #define BTN_EN1                           PB5
-  #define BTN_EN2                           PB4
+  #define BTN_EN1                 E3_EXP1_08_PIN
+  #define BTN_EN2                 E3_EXP1_06_PIN
 
-  #define LCD_PINS_ENABLE                   PC2
+  #define LCD_PINS_ENABLE         E3_EXP1_03_PIN
 
   #if ENABLED(MKS_MINI_12864)
 
     #define LCD_BACKLIGHT_PIN               -1
     #define LCD_RESET_PIN                   -1
-    #define DOGLCD_A0                       PC1
-    #define DOGLCD_CS                       PC2
+    #define DOGLCD_A0             E3_EXP1_05_PIN
+    #define DOGLCD_CS             E3_EXP1_03_PIN
     #define DOGLCD_SCK                      PB13
     #define DOGLCD_MOSI                     PB15
 
   #else                                           // !MKS_MINI_12864
 
-    #define LCD_PINS_D4                     PC1
+    #define LCD_PINS_D4           E3_EXP1_05_PIN
     #if IS_ULTIPANEL
       #define LCD_PINS_D5                   -1
       #define LCD_PINS_D6                   -1
@@ -141,3 +161,15 @@
 #define SD_MISO_PIN                         PB14
 #define SD_MOSI_PIN                         PB15
 #define SD_SS_PIN                           PA15
+
+// EXP1 replace LCD with keys for EasyThreeD ET4000+ Mainboard
+#if ENABLED(EASYTHREED_UI)
+  #define BTN_HOME                E3_EXP1_04_PIN  // INPUT_PULLUP (unused)
+  #define BTN_FEED                E3_EXP1_09_PIN  // Run E Forward
+  #define BTN_RETRACT             E3_EXP1_08_PIN  // Run E Backward
+  #define BTN_PRINT               E3_EXP1_07_PIN  // Start File Print
+  #define BTN_HOME_GND            E3_EXP1_03_PIN  // OUTPUT (LOW)
+  #define BTN_FEED_GND            E3_EXP1_06_PIN  // OUTPUT (LOW)
+  #define BTN_RETRACT_GND         E3_EXP1_05_PIN  // OUTPUT (LOW)
+  #define EASYTHREED_LED_PIN      E3_EXP1_10_PIN  // Indicator LED
+#endif
diff --git a/ini/features.ini b/ini/features.ini
index 606370e07a6..91baa601cab 100644
--- a/ini/features.ini
+++ b/ini/features.ini
@@ -111,6 +111,7 @@ HAS_COOLER|LASER_COOLANT_FLOW_METER    = src_filter=+<src/feature/cooler.cpp>
 HAS_MOTOR_CURRENT_DAC                  = src_filter=+<src/feature/dac>
 DIRECT_STEPPING                        = src_filter=+<src/feature/direct_stepping.cpp> +<src/gcode/motion/G6.cpp>
 EMERGENCY_PARSER                       = src_filter=+<src/feature/e_parser.cpp> -<src/gcode/control/M108_*.cpp>
+EASYTHREED_UI                          = src_filter=+<src/feature/easythreed_ui.cpp>
 I2C_POSITION_ENCODERS                  = src_filter=+<src/feature/encoder_i2c.cpp>
 IIC_BL24CXX_EEPROM                     = src_filter=+<src/libs/BL24CXX.cpp>
 HAS_SPI_FLASH                          = src_filter=+<src/libs/W25Qxx.cpp>
diff --git a/platformio.ini b/platformio.ini
index 0be12fb6ae8..07821fca96b 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -109,6 +109,7 @@ default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared>
   -<src/feature/dac> -<src/feature/digipot>
   -<src/feature/direct_stepping.cpp> -<src/gcode/motion/G6.cpp>
   -<src/feature/e_parser.cpp>
+  -<src/feature/easythreed_ui.cpp>
   -<src/feature/encoder_i2c.cpp>
   -<src/feature/ethernet.cpp> -<src/gcode/feature/network/M552-M554.cpp>
   -<src/feature/fancheck.cpp>