Browse Source

Add files via upload

Naomi Wu 6 years ago
parent
commit
ae8ca2abab
68 changed files with 43201 additions and 0 deletions
  1. 7092 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Ender-3断电续打公司中文.hex
  2. 29 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/BlinkM.cpp
  3. 14 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/BlinkM.h
  4. 188 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/COPYING
  5. 714 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Configuration.h
  6. 299 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/ConfigurationStore.cpp
  7. 22 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/ConfigurationStore.h
  8. 483 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Configuration_adv.h
  9. 487 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/DOGMbitmaps.h
  10. BIN
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/LCD Menu Tree CN.pdf
  11. BIN
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/LCD Menu Tree.pdf
  12. 389 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/LiquidCrystalRus.cpp
  13. 129 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/LiquidCrystalRus.h
  14. 484 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Makefile
  15. 249 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Marlin.h
  16. 56 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Marlin.ino
  17. 328 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/MarlinSerial.cpp
  18. 189 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/MarlinSerial.h
  19. 3806 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Marlin_main.cpp
  20. BIN
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Menu Plans.xlsx
  21. 641 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Sd2Card.cpp
  22. 241 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Sd2Card.h
  23. 368 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Sd2PinMap.h
  24. 1825 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdBaseFile.cpp
  25. 483 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdBaseFile.h
  26. 121 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdFatConfig.h
  27. 646 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdFatStructs.h
  28. 79 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdFatUtil.cpp
  29. 48 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdFatUtil.h
  30. 95 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdFile.cpp
  31. 54 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdFile.h
  32. 280 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdInfo.h
  33. 405 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdVolume.cpp
  34. 214 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdVolume.h
  35. 344 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Servo.cpp
  36. 135 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Servo.h
  37. 686 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/cardreader.cpp
  38. 144 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/cardreader.h
  39. 155 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/createTemperatureLookupMarlin.py
  40. 50 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/create_speed_lookuptable.py
  41. 54 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/digipot_mcp4451.cpp
  42. 599 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/dogm_font_data_marlin.h
  43. 648 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/dogm_lcd_implementation.h
  44. 697 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/example_configurations/delta/Configuration.h
  45. 479 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/example_configurations/delta/Configuration_adv.h
  46. 4020 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/fastio.h
  47. 1748 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/language.h
  48. 137 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/motion_control.cpp
  49. 32 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/motion_control.h
  50. 2771 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/pins.h
  51. 1001 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/planner.cpp
  52. 169 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/planner.h
  53. 1932 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/qr_solve.cpp
  54. 22 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/qr_solve.h
  55. 152 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/speed_lookuptable.h
  56. 1293 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/stepper.cpp
  57. 101 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/stepper.h
  58. 1323 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/temperature.cpp
  59. 171 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/temperature.h
  60. 953 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/thermistortables.h
  61. 1596 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/ultralcd.cpp
  62. 114 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/ultralcd.h
  63. 774 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/ultralcd_implementation_hitachi_HD44780.h
  64. 131 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/ultralcd_st7920_u8glib_rrd.h
  65. 177 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/vector_3.cpp
  66. 62 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/vector_3.h
  67. 56 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/watchdog.cpp
  68. 17 0
      Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/watchdog.h

File diff suppressed because it is too large
+ 7092 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Ender-3断电续打公司中文.hex


+ 29 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/BlinkM.cpp

@@ -0,0 +1,29 @@
+/*
+  BlinkM.cpp - Library for controlling a BlinkM over i2c
+  Created by Tim Koster, August 21 2013.
+*/
+#include "Marlin.h"
+#ifdef BLINKM
+
+#if (ARDUINO >= 100)
+  # include "Arduino.h"
+#else
+  # include "WProgram.h"
+#endif
+
+#include "BlinkM.h"
+
+void SendColors(byte red, byte grn, byte blu)
+{
+  Wire.begin(); 
+  Wire.beginTransmission(0x09);
+  Wire.write('o');                    //to disable ongoing script, only needs to be used once
+  Wire.write('n');
+  Wire.write(red);
+  Wire.write(grn);
+  Wire.write(blu);
+  Wire.endTransmission();
+}
+
+#endif //BLINKM
+

+ 14 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/BlinkM.h

@@ -0,0 +1,14 @@
+/*
+  BlinkM.h
+  Library header file for BlinkM library
+ */
+#if (ARDUINO >= 100)
+  # include "Arduino.h"
+#else
+  # include "WProgram.h"
+#endif
+
+#include "Wire.h"
+
+void SendColors(byte red, byte grn, byte blu);
+

File diff suppressed because it is too large
+ 188 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/COPYING


+ 714 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Configuration.h

@@ -0,0 +1,714 @@
+#ifndef CONFIGURATION_H
+#define CONFIGURATION_H
+
+// This configuration file contains the basic settings.
+// Advanced settings can be found in Configuration_adv.h
+// BASIC SETTINGS: select your board type, temperature sensor type, axis scaling, and endstop configuration
+
+//===========================================================================
+//============================= DELTA Printer ===============================
+//===========================================================================
+// For a Delta printer rplace the configuration files wilth the files in the
+// example_configurations/delta directory.
+//
+
+// User-specified version info of this build to display in [Pronterface, etc] terminal window during
+// startup. Implementation of an idea by Prof Braino to inform user that any changes made to this
+// build by the user have been successfully uploaded into firmware.
+#define STRING_VERSION_CONFIG_H __DATE__ " " __TIME__ // build date and time
+#define STRING_CONFIG_H_AUTHOR "(Ender3)" // Who made the changes.
+
+// SERIAL_PORT selects which serial port should be used for communication with the host.
+// This allows the connection of wireless adapters (for instance) to non-default port pins.
+// Serial port 0 is still used by the Arduino bootloader regardless of this setting.
+#define SERIAL_PORT 0
+
+// This determines the communication speed of the printer
+// This determines the communication speed of the printer
+#define BAUDRATE 115200
+
+// This enables the serial port associated to the Bluetooth interface
+//#define BTENABLED              // Enable BT interface on AT90USB devices
+
+
+//// The following define selects which electronics board you have. Please choose the one that matches your setup
+// 10 = Gen7 custom (Alfons3 Version) "https://github.com/Alfons3/Generation_7_Electronics"
+// 11 = Gen7 v1.1, v1.2 = 11
+// 12 = Gen7 v1.3
+// 13 = Gen7 v1.4
+// 2  = Cheaptronic v1.0
+// 20 = Sethi 3D_1
+// 3  = MEGA/RAMPS up to 1.2 = 3
+// 33 = RAMPS 1.3 / 1.4 (Power outputs: Extruder, Fan, Bed)
+// 34 = RAMPS 1.3 / 1.4 (Power outputs: Extruder0, Extruder1, Bed)
+// 35 = RAMPS 1.3 / 1.4 (Power outputs: Extruder, Fan, Fan)
+// 4  = Duemilanove w/ ATMega328P pin assignment
+// 5  = Gen6
+// 51 = Gen6 deluxe
+// 6  = Sanguinololu < 1.2
+// 62 = Sanguinololu 1.2 and above
+// 63 = Melzi
+// 64 = STB V1.1
+// 65 = Azteeg X1
+// 66 = Melzi with ATmega1284 (MaKr3d version)
+// 67 = Azteeg X3
+// 68 = Azteeg X3 Pro
+// 7  = Ultimaker
+// 71 = Ultimaker (Older electronics. Pre 1.5.4. This is rare)
+// 77 = 3Drag Controller
+// 8  = Teensylu
+// 80 = Rumba
+// 81 = Printrboard (AT90USB1286)
+// 82 = Brainwave (AT90USB646)
+// 83 = SAV Mk-I (AT90USB1286)
+// 9  = Gen3+
+// 70 = Megatronics
+// 701= Megatronics v2.0
+// 702= Minitronics v1.0
+// 90 = Alpha OMCA board
+// 91 = Final OMCA board
+// 301 = Rambo
+// 21 = Elefu Ra Board (v3)
+// 310 = Mega Controller
+
+#ifndef MOTHERBOARD
+#define MOTHERBOARD 63
+#endif
+
+// Define this to set a custom name for your generic Mendel,
+// #define CUSTOM_MENDEL_NAME "This Mendel"
+
+// Define this to set a unique identifier for this printer, (Used by some programs to differentiate between machines)
+// You can use an online service to generate a random UUID. (eg http://www.uuidgenerator.net/version4)
+// #define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
+
+// This defines the number of extruders
+#define EXTRUDERS 1
+
+//// The following define selects which power supply you have. Please choose the one that matches your setup
+// 1 = ATX
+// 2 = X-Box 360 203Watts (the blue wire connected to PS_ON and the red wire to VCC)
+
+#define POWER_SUPPLY 1
+
+// Define this to have the electronics keep the powersupply off on startup. If you don't know what this is leave it.
+// #define PS_DEFAULT_OFF
+
+//===========================================================================
+//=============================Thermal Settings  ============================
+//===========================================================================
+//
+//--NORMAL IS 4.7kohm PULLUP!-- 1kohm pullup can be used on hotend sensor, using correct resistor and table
+//
+//// Temperature sensor settings:
+// -2 is thermocouple with MAX6675 (only for sensor 0)
+// -1 is thermocouple with AD595
+// 0 is not used
+// 1 is 100k thermistor - best choice for EPCOS 100k (4.7k pullup)
+// 2 is 200k thermistor - ATC Semitec 204GT-2 (4.7k pullup)
+// 3 is mendel-parts thermistor (4.7k pullup)
+// 4 is 10k thermistor !! do not use it for a hotend. It gives bad resolution at high temp. !!
+// 5 is 100K thermistor - ATC Semitec 104GT-2 (Used in ParCan & J-Head) (4.7k pullup)
+// 6 is 100k EPCOS - Not as accurate as table 1 (created using a fluke thermocouple) (4.7k pullup)
+// 7 is 100k Honeywell thermistor 135-104LAG-J01 (4.7k pullup)
+// 71 is 100k Honeywell thermistor 135-104LAF-J01 (4.7k pullup)
+// 8 is 100k 0603 SMD Vishay NTCS0603E3104FXT (4.7k pullup)
+// 9 is 100k GE Sensing AL03006-58.2K-97-G1 (4.7k pullup)
+// 10 is 100k RS thermistor 198-961 (4.7k pullup)
+// 60 is 100k Maker's Tool Works Kapton Bed Thermister
+//
+//    1k ohm pullup tables - This is not normal, you would have to have changed out your 4.7k for 1k
+//                          (but gives greater accuracy and more stable PID)
+// 51 is 100k thermistor - EPCOS (1k pullup)
+// 52 is 200k thermistor - ATC Semitec 204GT-2 (1k pullup)
+// 55 is 100k thermistor - ATC Semitec 104GT-2 (Used in ParCan & J-Head) (1k pullup)
+
+#define TEMP_SENSOR_0 1
+#define TEMP_SENSOR_1 0
+#define TEMP_SENSOR_2 0
+#define TEMP_SENSOR_BED 1
+
+// This makes temp sensor 1 a redundant sensor for sensor 0. If the temperatures difference between these sensors is to high the print will be aborted.
+//#define TEMP_SENSOR_1_AS_REDUNDANT
+#define MAX_REDUNDANT_TEMP_SENSOR_DIFF 10
+
+// Actual temperature must be close to target for this long before M109 returns success
+//#define TEMP_RESIDENCY_TIME 10  // (seconds)
+#define TEMP_HYSTERESIS 3       // (degC) range of +/- temperatures considered "close" to the target one
+#define TEMP_WINDOW     1       // (degC) Window around target to start the residency timer x degC early.
+
+// The minimal temperature defines the temperature below which the heater will not be enabled It is used
+// to check that the wiring to the thermistor is not broken.
+// Otherwise this would lead to the heater being powered on all the time.
+#define HEATER_0_MINTEMP 5
+#define HEATER_1_MINTEMP 5
+#define HEATER_2_MINTEMP 5
+#define BED_MINTEMP 5
+
+// When temperature exceeds max temp, your heater will be switched off.
+// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure!
+// You should use MINTEMP for thermistor short/failure protection.
+#define HEATER_0_MAXTEMP 275
+#define HEATER_1_MAXTEMP 275
+#define HEATER_2_MAXTEMP 275
+#define BED_MAXTEMP 150
+
+// If your bed has low resistance e.g. .6 ohm and throws the fuse you can duty cycle it to reduce the
+// average current. The value should be an integer and the heat bed will be turned on for 1 interval of
+// HEATER_BED_DUTY_CYCLE_DIVIDER intervals.
+//#define HEATER_BED_DUTY_CYCLE_DIVIDER 4
+
+// If you want the M105 heater power reported in watts, define the BED_WATTS, and (shared for all extruders) EXTRUDER_WATTS
+//#define EXTRUDER_WATTS (12.0*12.0/6.7) //  P=I^2/R
+//#define BED_WATTS (12.0*12.0/1.1)      // P=I^2/R
+
+// PID settings:
+// Comment the following line to disable PID and enable bang-bang.
+#define PIDTEMP
+#define BANG_MAX 255 // limits current to nozzle while in bang-bang mode; 255=full current
+#define PID_MAX 255 // limits current to nozzle while PID is active (see PID_FUNCTIONAL_RANGE below); 255=full current
+#ifdef PIDTEMP
+  //#define PID_DEBUG // Sends debug data to the serial port.
+  //#define PID_OPENLOOP 1 // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
+  #define PID_FUNCTIONAL_RANGE 10 // If the temperature difference between the target temperature and the actual temperature
+                                  // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max.
+  #define PID_INTEGRAL_DRIVE_MAX 255  //limit for the integral term
+  #define K1 0.95 //smoothing factor within the PID
+  #define PID_dT ((OVERSAMPLENR * 8.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine
+
+//PID for Makerlab J-head
+  #define  DEFAULT_Kp 21.73
+  #define  DEFAULT_Ki 1.54
+  #define  DEFAULT_Kd 76.55
+
+
+// If you are using a preconfigured hotend then you can use one of the value sets by uncommenting it
+// Ultimaker
+//    #define  DEFAULT_Kp 22.2
+//    #define  DEFAULT_Ki 1.08
+//    #define  DEFAULT_Kd 114
+
+// Makergear
+//    #define  DEFAULT_Kp 7.0
+//    #define  DEFAULT_Ki 0.1
+//    #define  DEFAULT_Kd 12
+
+// Mendel Parts V9 on 12V
+//    #define  DEFAULT_Kp 63.0
+//    #define  DEFAULT_Ki 2.25
+//    #define  DEFAULT_Kd 440
+#endif // PIDTEMP
+
+// Bed Temperature Control
+// Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis
+//
+// Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder.
+// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz,
+// which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating.
+// This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater.
+// If your configuration is significantly different than this and you don't understand the issues involved, you probably
+// shouldn't use bed PID until someone else verifies your hardware works.
+// If this is enabled, find your own PID constants below.
+//#define PIDTEMPBED
+//
+//#define BED_LIMIT_SWITCHING
+
+// This sets the max power delivered to the bed, and replaces the HEATER_BED_DUTY_CYCLE_DIVIDER option.
+// all forms of bed control obey this (PID, bang-bang, bang-bang with hysteresis)
+// setting this to anything other than 255 enables a form of PWM to the bed just like HEATER_BED_DUTY_CYCLE_DIVIDER did,
+// so you shouldn'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
+
+#ifdef PIDTEMPBED
+//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
+//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
+    #define  DEFAULT_bedKp 10.00
+    #define  DEFAULT_bedKi .023
+    #define  DEFAULT_bedKd 305.4
+
+//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
+//from pidautotune
+//    #define  DEFAULT_bedKp 97.1
+//    #define  DEFAULT_bedKi 1.41
+//    #define  DEFAULT_bedKd 1675.16
+
+// FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles.
+#endif // PIDTEMPBED
+
+
+
+//this prevents dangerous Extruder moves, i.e. if the temperature is under the limit
+//can be software-disabled for whatever purposes by
+//#define PREVENT_DANGEROUS_EXTRUDE
+//if PREVENT_DANGEROUS_EXTRUDE is on, you can still disable (uncomment) very long bits of extrusion separately.
+#define PREVENT_LENGTHY_EXTRUDE
+
+#define EXTRUDE_MINTEMP 170
+#define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH) //prevent extrusion of very large distances.
+
+//===========================================================================
+//=============================Mechanical Settings===========================
+//===========================================================================
+
+// Uncomment the following line to enable CoreXY kinematics
+// #define COREXY
+
+// coarse Endstop Settings
+#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
+
+#ifndef ENDSTOPPULLUPS
+  // fine Enstop settings: Individual Pullups. will be ignored if ENDSTOPPULLUPS is defined
+  // #define ENDSTOPPULLUP_XMAX
+  // #define ENDSTOPPULLUP_YMAX
+  // #define ENDSTOPPULLUP_ZMAX
+  // #define ENDSTOPPULLUP_XMIN
+  // #define ENDSTOPPULLUP_YMIN
+  // #define ENDSTOPPULLUP_ZMIN
+#endif
+
+#ifdef ENDSTOPPULLUPS
+  #define ENDSTOPPULLUP_XMAX
+  #define ENDSTOPPULLUP_YMAX
+  #define ENDSTOPPULLUP_ZMAX
+  #define ENDSTOPPULLUP_XMIN
+  #define ENDSTOPPULLUP_YMIN
+  #define ENDSTOPPULLUP_ZMIN
+#endif
+
+// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins.
+const bool X_MIN_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
+const bool Y_MIN_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
+const bool Z_MIN_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
+const bool X_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
+const bool Y_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
+const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
+//#define DISABLE_MAX_ENDSTOPS
+//#define DISABLE_MIN_ENDSTOPS
+
+// Disable max endstops for compatibility with endstop checking routine
+#if defined(COREXY) && !defined(DISABLE_MAX_ENDSTOPS)
+  #define DISABLE_MAX_ENDSTOPS
+#endif
+
+// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1
+#define X_ENABLE_ON 0
+#define Y_ENABLE_ON 0
+#define Z_ENABLE_ON 0
+#define E_ENABLE_ON 0 // For all extruders
+
+// Disables axis when it's not being used.
+#define DISABLE_X false
+#define DISABLE_Y false
+#define DISABLE_Z false
+#define DISABLE_E false // For all extruders
+
+#define INVERT_X_DIR true    // for Mendel set to false, for Orca set to true
+#define INVERT_Y_DIR true    // for Mendel set to true, for Orca set to false
+#define INVERT_Z_DIR false     // for Mendel set to false, for Orca set to true
+#define INVERT_E0_DIR true   // for direct drive extruder v9 set to true, for geared extruder set to false
+#define INVERT_E1_DIR false    // for direct drive extruder v9 set to true, for geared extruder set to false
+#define INVERT_E2_DIR false   // for direct drive extruder v9 set to true, for geared extruder set to false
+
+// ENDSTOP SETTINGS:
+// Sets direction of endstops when homing; 1=MAX, -1=MIN
+#define X_HOME_DIR -1
+#define Y_HOME_DIR -1
+#define Z_HOME_DIR -1
+
+#define min_software_endstops true // If true, axis won't move to coordinates less than HOME_POS.
+#define max_software_endstops true  // If true, axis won't move to coordinates greater than the defined lengths below.
+
+// Travel limits after homing
+#define X_MAX_POS 235
+#define X_MIN_POS 0
+#define Y_MAX_POS 235
+#define Y_MIN_POS 0
+#define Z_MAX_POS 260
+#define Z_MIN_POS 0
+
+#define X_MAX_LENGTH (X_MAX_POS - X_MIN_POS)
+#define Y_MAX_LENGTH (Y_MAX_POS - Y_MIN_POS)
+#define Z_MAX_LENGTH (Z_MAX_POS - Z_MIN_POS)
+//============================= Bed Auto Leveling ===========================
+
+//#define ENABLE_AUTO_BED_LEVELING // Delete the comment to enable (remove // at the start of the line)
+
+#ifdef ENABLE_AUTO_BED_LEVELING
+
+  // these are the positions on the bed to do the probing
+  #define LEFT_PROBE_BED_POSITION 50
+  #define RIGHT_PROBE_BED_POSITION 180
+  #define BACK_PROBE_BED_POSITION 180
+  #define FRONT_PROBE_BED_POSITION 50
+
+  // these are the offsets to the prob relative to the extruder tip (Hotend - Probe)
+  #define X_PROBE_OFFSET_FROM_EXTRUDER -34
+  #define Y_PROBE_OFFSET_FROM_EXTRUDER 8
+  #define Z_PROBE_OFFSET_FROM_EXTRUDER -19.2
+
+  #define Z_RAISE_BEFORE_HOMING 18       // (in mm) Raise Z before homing (G28) for Probe Clearance.
+                                        // Be sure you have this distance over your Z_MAX_POS in case
+
+  #define XY_TRAVEL_SPEED 8000         // X and Y axis travel speed between probes, in mm/min
+
+  #define Z_RAISE_BEFORE_PROBING 20    //How much the extruder will be raised before traveling to the first probing point.
+  #define Z_RAISE_BETWEEN_PROBINGS 10  //How much the extruder will be raised when traveling from between next probing points
+
+
+  //If defined, the Probe servo will be turned on only during movement and then turned off to avoid jerk
+  //The value is the delay to turn the servo off after powered on - depends on the servo speed; 300ms is good value, but you can try lower it.
+  // You MUST HAVE the SERVO_ENDSTOPS defined to use here a value higher than zero otherwise your code will not compile.
+
+  #define PROBE_SERVO_DEACTIVATION_DELAY 300
+
+
+//If you have enabled the Bed Auto Levelling and are using the same Z Probe for Z Homing,
+//it is highly recommended you let this Z_SAFE_HOMING enabled!!!
+
+  #define Z_SAFE_HOMING   // This feature is meant to avoid Z homing with probe outside the bed area.
+                          // When defined, it will:
+                          // - Allow Z homing only after X and Y homing AND stepper drivers still enabled
+                          // - If stepper drivers timeout, it will need X and Y homing again before Z homing
+                          // - Position the probe in a defined XY point before Z Homing when homing all axis (G28)
+                          // - Block Z homing only when the probe is outside bed area.
+
+  #ifdef Z_SAFE_HOMING
+
+    #define Z_SAFE_HOMING_X_POINT (X_MAX_LENGTH/2)    // X point for Z homing when homing all axis (G28)
+    #define Z_SAFE_HOMING_Y_POINT (Y_MAX_LENGTH/2)    // Y point for Z homing when homing all axis (G28)
+
+  #endif
+
+  // with accurate bed leveling, the bed is sampled in a ACCURATE_BED_LEVELING_POINTSxACCURATE_BED_LEVELING_POINTS grid and least squares solution is calculated
+  // Note: this feature occupies 10'206 byte
+  #define ACCURATE_BED_LEVELING
+
+  #ifdef ACCURATE_BED_LEVELING
+     // I wouldn't see a reason to go above 3 (=9 probing points on the bed)
+    #define ACCURATE_BED_LEVELING_POINTS 2
+  #endif
+
+#endif
+
+
+// The position of the homing switches
+//#define MANUAL_HOME_POSITIONS  // If defined, MANUAL_*_HOME_POS below will be used
+//#define BED_CENTER_AT_0_0  // If defined, the center of the bed is at (X=0, Y=0)
+
+//Manual homing switch locations:
+// For deltabots this means top and center of the cartesian print volume.
+#define MANUAL_X_HOME_POS 0
+#define MANUAL_Y_HOME_POS 0
+#define MANUAL_Z_HOME_POS 0
+//#define MANUAL_Z_HOME_POS 402 // For delta: Distance between nozzle and print surface after homing.
+
+//// MOVEMENT SETTINGS
+#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E
+#define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0}  // set the homing speeds (mm/min)
+
+// default settings
+
+#define DEFAULT_AXIS_STEPS_PER_UNIT   {80.000,80.000,400.000,93.00}  // default steps per unit for Ultimaker
+#define DEFAULT_MAX_FEEDRATE          {500, 500, 5, 25}    // (mm/sec)
+#define DEFAULT_MAX_ACCELERATION      {500,500,100,5000}    // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot.
+
+#define DEFAULT_ACCELERATION          500    // X, Y, Z and E max acceleration in mm/s^2 for printing moves
+#define DEFAULT_RETRACT_ACCELERATION  500   // X, Y, Z and E max acceleration in mm/s^2 for retracts
+
+// Offset of the extruders (uncomment if using more than one and relying on firmware to position when changing).
+// The offset has to be X=0, Y=0 for the extruder 0 hotend (default extruder).
+// For the other hotends it is their distance from the extruder 0 hotend.
+// #define EXTRUDER_OFFSET_X {0.0, 20.00} // (in mm) for each extruder, offset of the hotend on the X axis
+// #define EXTRUDER_OFFSET_Y {0.0, 5.00}  // (in mm) for each extruder, offset of the hotend on the Y axis
+
+// The speed change that does not require acceleration (i.e. the software might assume it can be done instantaneously)
+#define DEFAULT_XYJERK                20.0    // (mm/sec)
+#define DEFAULT_ZJERK                 0.4     // (mm/sec)
+#define DEFAULT_EJERK                 5.0    // (mm/sec)
+
+//===========================================================================
+//=============================Additional Features===========================
+//===========================================================================
+
+// EEPROM
+// the microcontroller can store settings in the EEPROM, e.g. max velocity...
+// M500 - stores paramters in EEPROM
+// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).
+// M502 - reverts to the default "factory settings".  You still need to store them in EEPROM afterwards if you want to.
+//define this to enable eeprom support
+//#define EEPROM_SETTINGS
+//to disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out:
+// please keep turned on if you can.
+//#define EEPROM_CHITCHAT
+
+// Preheat Constants
+#define PLA_PREHEAT_HOTEND_TEMP 185
+#define PLA_PREHEAT_HPB_TEMP 0
+#define PLA_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
+
+#define ABS_PREHEAT_HOTEND_TEMP 240
+#define ABS_PREHEAT_HPB_TEMP 0
+#define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
+
+//LCD and SD support
+//#define ULTRA_LCD  //general lcd support, also 16x2
+//#define DOGLCD  // Support for SPI LCD 128x64 (Controller ST7565R graphic Display Family)
+//#define SDSUPPORT // Enable SD Card Support in Hardware Console
+#define POWEROFF_SAVE_SD_FILE // If power off, after power on, the printing can be resumed. 
+//#define SDSLOW // Use slower SD transfer mode (not normally needed - uncomment if you're getting volume init error)
+//#define ENCODER_PULSES_PER_STEP 1 // Increase if you have a high resolution encoder
+//#define ENCODER_STEPS_PER_MENU_ITEM 5 // Set according to ENCODER_PULSES_PER_STEP or your liking
+//#define ULTIMAKERCONTROLLER //as available from the ultimaker online store.
+//#define ULTIPANEL  //the ultipanel as on thingiverse
+//#define LCD_FEEDBACK_FREQUENCY_HZ 1000	// this is the tone frequency the buzzer plays when on UI feedback. ie Screen Click
+//#define LCD_FEEDBACK_FREQUENCY_DURATION_MS 100 // the duration the buzzer plays the UI feedback sound. ie Screen Click
+
+// The MakerLab Maker Panel with graphic controller and SD support
+// http://reprap.org/wiki/Maker_panel
+// #define MAKERPANEL
+
+// The MakerLab Multi Panel with OLED display and SD support
+// #define MULTIPANEL
+
+// The MakerLab Mini Panel with graphic controller and SD support
+// http://reprap.org/wiki/Mini_panel
+// #define MINIPANEL
+
+// The MaKr3d Makr-Panel with graphic controller and SD support
+// http://reprap.org/wiki/MaKr3d_MaKrPanel
+//#define MAKRPANEL
+
+// The RepRapDiscount Smart Controller (white PCB)
+// http://reprap.org/wiki/RepRapDiscount_Smart_Controller
+//#define REPRAP_DISCOUNT_SMART_CONTROLLER
+
+// The GADGETS3D G3D LCD/SD Controller (blue PCB)
+// http://reprap.org/wiki/RAMPS_1.3/1.4_GADGETS3D_Shield_with_Panel
+//#define G3D_PANEL
+
+// The RepRapDiscount FULL GRAPHIC Smart Controller (quadratic white PCB)
+// http://reprap.org/wiki/RepRapDiscount_Full_Graphic_Smart_Controller
+//
+// ==> REMEMBER TO INSTALL U8glib to your ARDUINO library folder: http://code.google.com/p/u8glib/wiki/u8glib
+#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
+
+// The RepRapWorld REPRAPWORLD_KEYPAD v1.1
+// http://reprapworld.com/?products_details&products_id=202&cPath=1591_1626
+//#define REPRAPWORLD_KEYPAD
+//#define REPRAPWORLD_KEYPAD_MOVE_STEP 10.0 // how much should be moved when a key is pressed, eg 10.0 means 10mm per click
+
+// The Elefu RA Board Control Panel
+// http://www.elefu.com/index.php?route=product/product&product_id=53
+// REMEMBER TO INSTALL LiquidCrystal_I2C.h in your ARUDINO library folder: https://github.com/kiyoshigawa/LiquidCrystal_I2C
+//#define RA_CONTROL_PANEL
+
+#if defined (MAKERPANEL)
+ #define DOGLCD
+ #define SDSUPPORT
+ #define ULTIPANEL
+ #define NEWPANEL
+ #define U8GLIB_ST7920
+#endif
+
+#if defined (MULTIPANEL)
+ #define DOGLCD
+ #define SDSUPPORT
+ #define ULTIPANEL
+ #define NEWPANEL
+ #define DEFAULT_LCD_CONTRAST 17
+#endif
+
+#if defined (MINIPANEL)
+ #define DOGLCD
+ #define SDSUPPORT
+ #define ULTIPANEL
+ #define NEWPANEL
+ #define DEFAULT_LCD_CONTRAST 17
+#endif
+
+//automatic expansion
+#if defined (MAKRPANEL)
+ #define DOGLCD
+ #define SDSUPPORT
+ #define ULTIPANEL
+ #define NEWPANEL
+ #define DEFAULT_LCD_CONTRAST 17
+#endif
+
+#if defined (REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER)
+ #define DOGLCD
+ #define U8GLIB_ST7920
+ #define REPRAP_DISCOUNT_SMART_CONTROLLER
+#endif
+
+#if defined(ULTIMAKERCONTROLLER) || defined(REPRAP_DISCOUNT_SMART_CONTROLLER) || defined(G3D_PANEL)
+ #define ULTIPANEL
+ #define NEWPANEL
+#endif
+
+#if defined(REPRAPWORLD_KEYPAD)
+  #define NEWPANEL
+  #define ULTIPANEL
+#endif
+#if defined(RA_CONTROL_PANEL)
+ #define ULTIPANEL
+ #define NEWPANEL
+ #define LCD_I2C_TYPE_PCA8574
+ #define LCD_I2C_ADDRESS 0x27   // I2C Address of the port expander
+#endif
+
+//I2C PANELS
+
+//#define LCD_I2C_SAINSMART_YWROBOT
+#ifdef LCD_I2C_SAINSMART_YWROBOT
+  // This uses the LiquidCrystal_I2C library ( https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home )
+  // Make sure it is placed in the Arduino libraries directory.
+  #define LCD_I2C_TYPE_PCF8575
+  #define LCD_I2C_ADDRESS 0x27   // I2C Address of the port expander
+  #define NEWPANEL
+  #define ULTIPANEL
+#endif
+
+// PANELOLU2 LCD with status LEDs, separate encoder and click inputs
+//#define LCD_I2C_PANELOLU2
+#ifdef LCD_I2C_PANELOLU2
+  // This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
+  // Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
+  // (v1.2.3 no longer requires you to define PANELOLU in the LiquidTWI2.h library header file)
+  // Note: The PANELOLU2 encoder click input can either be directly connected to a pin
+  //       (if BTN_ENC defined to != -1) or read through I2C (when BTN_ENC == -1).
+  #define LCD_I2C_TYPE_MCP23017
+  #define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
+  #define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD
+  #define NEWPANEL
+  #define ULTIPANEL
+
+  #ifndef ENCODER_PULSES_PER_STEP
+	#define ENCODER_PULSES_PER_STEP 4
+  #endif
+
+  #ifndef ENCODER_STEPS_PER_MENU_ITEM
+	#define ENCODER_STEPS_PER_MENU_ITEM 1
+  #endif
+
+
+  #ifdef LCD_USE_I2C_BUZZER
+	#define LCD_FEEDBACK_FREQUENCY_HZ 1000
+	#define LCD_FEEDBACK_FREQUENCY_DURATION_MS 100
+  #endif
+
+#endif
+
+// Panucatt VIKI LCD with status LEDs, integrated click & L/R/U/P buttons, separate encoder inputs
+//#define LCD_I2C_VIKI
+#ifdef LCD_I2C_VIKI
+  // This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
+  // Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
+  // Note: The pause/stop/resume LCD button pin should be connected to the Arduino
+  //       BTN_ENC pin (or set BTN_ENC to -1 if not used)
+  #define LCD_I2C_TYPE_MCP23017
+  #define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
+  #define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD (requires LiquidTWI2 v1.2.3 or later)
+  #define NEWPANEL
+  #define ULTIPANEL
+#endif
+
+// Shift register panels
+// ---------------------
+// 2 wire Non-latching LCD SR from:
+// https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/schematics#!shiftregister-connection
+//#define SR_LCD
+#ifdef SR_LCD
+   #define SR_LCD_2W_NL    // Non latching 2 wire shiftregister
+   //#define NEWPANEL
+#endif
+
+
+#ifdef ULTIPANEL
+//  #define NEWPANEL  //enable this if you have a click-encoder panel
+  #define SDSUPPORT
+  #define ULTRA_LCD
+  #ifdef DOGLCD // Change number of lines to match the DOG graphic display
+    #define LCD_WIDTH 20
+    #define LCD_HEIGHT 5
+  #else
+    #define LCD_WIDTH 20
+    #define LCD_HEIGHT 4
+  #endif
+#else //no panel but just lcd
+  #ifdef ULTRA_LCD
+  #ifdef DOGLCD // Change number of lines to match the 128x64 graphics display
+    #define LCD_WIDTH 20
+    #define LCD_HEIGHT 5
+  #else
+    #define LCD_WIDTH 16
+    #define LCD_HEIGHT 2
+  #endif
+  #endif
+#endif
+
+// default LCD contrast for dogm-like LCD displays
+#ifdef DOGLCD
+# ifndef DEFAULT_LCD_CONTRAST
+#  define DEFAULT_LCD_CONTRAST 32
+# endif
+#endif
+
+// Increase the FAN pwm frequency. Removes the PWM noise but increases heating in the FET/Arduino
+//#define FAST_PWM_FAN
+
+// Temperature status leds that display the hotend and bet temperature.
+// If alle hotends and bed temperature and temperature setpoint are < 54C then the BLUE led is on.
+// Otherwise the RED led is on. There is 1C hysteresis.
+//#define TEMP_STAT_LEDS
+
+// Use software PWM to drive the fan, as for the heaters. This uses a very low frequency
+// which is not ass annoying as with the hardware PWM. On the other hand, if this frequency
+// is too low, you should also increment SOFT_PWM_SCALE.
+//#define FAN_SOFT_PWM
+
+// Incrementing this by 1 will double the software PWM frequency,
+// affecting heaters, and the fan if FAN_SOFT_PWM is enabled.
+// However, control resolution will be halved for each increment;
+// at zero value, there are 128 effective control positions.
+#define SOFT_PWM_SCALE 0
+
+// M240  Triggers a camera by emulating a Canon RC-1 Remote
+// Data from: http://www.doc-diy.net/photo/rc-1_hacked/
+// #define PHOTOGRAPH_PIN     23
+
+// SF send wrong arc g-codes when using Arc Point as fillet procedure
+//#define SF_ARC_FIX
+
+// Support for the BariCUDA Paste Extruder.
+//#define BARICUDA
+
+//define BlinkM/CyzRgb Support
+//#define BLINKM
+
+/*********************************************************************\
+* R/C SERVO support
+* Sponsored by TrinityLabs, Reworked by codexmas
+**********************************************************************/
+
+// Number of servos
+//
+// If you select a configuration below, this will receive a default value and does not need to be set manually
+// set it manually if you have more servos than extruders and wish to manually control some
+// leaving it undefined or defining as 0 will disable the servo subsystem
+// If unsure, leave commented / disabled
+//
+#define NUM_SERVOS 1 // Servo index starts with 0 for M280 command
+
+// Servo Endstops
+//
+// This allows for servo actuated endstops, primary usage is for the Z Axis to eliminate calibration or bed height changes.
+// Use M206 command to correct for switch height offset to actual nozzle height. Store that setting with M500.
+//
+#define SERVO_ENDSTOPS {-1, -1, 0} // Servo index for X, Y, Z. Disable with -1
+#define SERVO_ENDSTOP_ANGLES {0,0, 0,0, 125,40} // X,Y,Z Axis Extend and Retract angles
+
+#include "Configuration_adv.h"
+#include "thermistortables.h"
+
+#endif //__CONFIGURATION_H

+ 299 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/ConfigurationStore.cpp

@@ -0,0 +1,299 @@
+#include "Marlin.h"
+#include "planner.h"
+#include "temperature.h"
+#include "ultralcd.h"
+#include "ConfigurationStore.h"
+
+void _EEPROM_writeData(int &pos, uint8_t* value, uint8_t size)
+{
+    do
+    {
+        eeprom_write_byte((unsigned char*)pos, *value);
+        pos++;
+        value++;
+    }while(--size);
+}
+#define EEPROM_WRITE_VAR(pos, value) _EEPROM_writeData(pos, (uint8_t*)&value, sizeof(value))
+void _EEPROM_readData(int &pos, uint8_t* value, uint8_t size)
+{
+    do
+    {
+        *value = eeprom_read_byte((unsigned char*)pos);
+        pos++;
+        value++;
+    }while(--size);
+}
+#define EEPROM_READ_VAR(pos, value) _EEPROM_readData(pos, (uint8_t*)&value, sizeof(value))
+//======================================================================================
+
+
+
+
+#define EEPROM_OFFSET 100
+
+
+// IMPORTANT:  Whenever there are changes made to the variables stored in EEPROM
+// in the functions below, also increment the version number. This makes sure that
+// the default values are used whenever there is a change to the data, to prevent
+// wrong data being written to the variables.
+// ALSO:  always make sure the variables in the Store and retrieve sections are in the same order.
+#define EEPROM_VERSION "V10"
+
+#ifdef EEPROM_SETTINGS
+void Config_StoreSettings() 
+{
+  char ver[4]= "000";
+  int i=EEPROM_OFFSET;
+  EEPROM_WRITE_VAR(i,ver); // invalidate data first 
+  EEPROM_WRITE_VAR(i,axis_steps_per_unit);  
+  EEPROM_WRITE_VAR(i,max_feedrate);  
+  EEPROM_WRITE_VAR(i,max_acceleration_units_per_sq_second);
+  EEPROM_WRITE_VAR(i,acceleration);
+  EEPROM_WRITE_VAR(i,retract_acceleration);
+  EEPROM_WRITE_VAR(i,minimumfeedrate);
+  EEPROM_WRITE_VAR(i,mintravelfeedrate);
+  EEPROM_WRITE_VAR(i,minsegmenttime);
+  EEPROM_WRITE_VAR(i,max_xy_jerk);
+  EEPROM_WRITE_VAR(i,max_z_jerk);
+  EEPROM_WRITE_VAR(i,max_e_jerk);
+  EEPROM_WRITE_VAR(i,add_homeing);
+  #ifdef DELTA
+  EEPROM_WRITE_VAR(i,endstop_adj);
+  #endif
+  #ifndef ULTIPANEL
+  int plaPreheatHotendTemp = PLA_PREHEAT_HOTEND_TEMP, plaPreheatHPBTemp = PLA_PREHEAT_HPB_TEMP, plaPreheatFanSpeed = PLA_PREHEAT_FAN_SPEED;
+  int absPreheatHotendTemp = ABS_PREHEAT_HOTEND_TEMP, absPreheatHPBTemp = ABS_PREHEAT_HPB_TEMP, absPreheatFanSpeed = ABS_PREHEAT_FAN_SPEED;
+  #endif
+  EEPROM_WRITE_VAR(i,plaPreheatHotendTemp);
+  EEPROM_WRITE_VAR(i,plaPreheatHPBTemp);
+  EEPROM_WRITE_VAR(i,plaPreheatFanSpeed);
+  EEPROM_WRITE_VAR(i,absPreheatHotendTemp);
+  EEPROM_WRITE_VAR(i,absPreheatHPBTemp);
+  EEPROM_WRITE_VAR(i,absPreheatFanSpeed);
+  EEPROM_WRITE_VAR(i,zprobe_zoffset);
+  #ifdef PIDTEMP
+    EEPROM_WRITE_VAR(i,Kp);
+    EEPROM_WRITE_VAR(i,Ki);
+    EEPROM_WRITE_VAR(i,Kd);
+  #else
+		float dummy = 3000.0f;
+    EEPROM_WRITE_VAR(i,dummy);
+		dummy = 0.0f;
+    EEPROM_WRITE_VAR(i,dummy);
+    EEPROM_WRITE_VAR(i,dummy);
+  #endif
+  #ifndef DOGLCD
+    int lcd_contrast = 32;
+  #endif
+  EEPROM_WRITE_VAR(i,lcd_contrast);
+  char ver2[4]=EEPROM_VERSION;
+  i=EEPROM_OFFSET;
+  EEPROM_WRITE_VAR(i,ver2); // validate data
+  SERIAL_ECHO_START;
+  SERIAL_ECHOLNPGM("Settings Stored");
+}
+#endif //EEPROM_SETTINGS
+
+
+#ifndef DISABLE_M503
+void Config_PrintSettings()
+{  // Always have this function, even with EEPROM_SETTINGS disabled, the current values will be shown
+    SERIAL_ECHO_START;
+    SERIAL_ECHOLNPGM("Steps per unit:");
+    SERIAL_ECHO_START;
+    SERIAL_ECHOPAIR("  M92 X",axis_steps_per_unit[0]);
+    SERIAL_ECHOPAIR(" Y",axis_steps_per_unit[1]);
+    SERIAL_ECHOPAIR(" Z",axis_steps_per_unit[2]);
+    SERIAL_ECHOPAIR(" E",axis_steps_per_unit[3]);
+    SERIAL_ECHOLN("");
+      
+    SERIAL_ECHO_START;
+    SERIAL_ECHOLNPGM("Maximum feedrates (mm/s):");
+    SERIAL_ECHO_START;
+    SERIAL_ECHOPAIR("  M203 X",max_feedrate[0]);
+    SERIAL_ECHOPAIR(" Y",max_feedrate[1] ); 
+    SERIAL_ECHOPAIR(" Z", max_feedrate[2] ); 
+    SERIAL_ECHOPAIR(" E", max_feedrate[3]);
+    SERIAL_ECHOLN("");
+
+    SERIAL_ECHO_START;
+    SERIAL_ECHOLNPGM("Maximum Acceleration (mm/s2):");
+    SERIAL_ECHO_START;
+    SERIAL_ECHOPAIR("  M201 X" ,max_acceleration_units_per_sq_second[0] ); 
+    SERIAL_ECHOPAIR(" Y" , max_acceleration_units_per_sq_second[1] ); 
+    SERIAL_ECHOPAIR(" Z" ,max_acceleration_units_per_sq_second[2] );
+    SERIAL_ECHOPAIR(" E" ,max_acceleration_units_per_sq_second[3]);
+    SERIAL_ECHOLN("");
+    SERIAL_ECHO_START;
+    SERIAL_ECHOLNPGM("Acceleration: S=acceleration, T=retract acceleration");
+    SERIAL_ECHO_START;
+    SERIAL_ECHOPAIR("  M204 S",acceleration ); 
+    SERIAL_ECHOPAIR(" T" ,retract_acceleration);
+    SERIAL_ECHOLN("");
+
+    SERIAL_ECHO_START;
+    SERIAL_ECHOLNPGM("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s),  Z=maximum Z jerk (mm/s),  E=maximum E jerk (mm/s)");
+    SERIAL_ECHO_START;
+    SERIAL_ECHOPAIR("  M205 S",minimumfeedrate ); 
+    SERIAL_ECHOPAIR(" T" ,mintravelfeedrate ); 
+    SERIAL_ECHOPAIR(" B" ,minsegmenttime ); 
+    SERIAL_ECHOPAIR(" X" ,max_xy_jerk ); 
+    SERIAL_ECHOPAIR(" Z" ,max_z_jerk);
+    SERIAL_ECHOPAIR(" E" ,max_e_jerk);
+    SERIAL_ECHOLN(""); 
+
+    SERIAL_ECHO_START;
+    SERIAL_ECHOLNPGM("Home offset (mm):");
+    SERIAL_ECHO_START;
+    SERIAL_ECHOPAIR("  M206 X",add_homeing[0] );
+    SERIAL_ECHOPAIR(" Y" ,add_homeing[1] );
+    SERIAL_ECHOPAIR(" Z" ,add_homeing[2] );
+    SERIAL_ECHOLN("");
+#ifdef DELTA
+    SERIAL_ECHO_START;
+    SERIAL_ECHOLNPGM("Endstop adjustement (mm):");
+    SERIAL_ECHO_START;
+    SERIAL_ECHOPAIR("  M666 X",endstop_adj[0] );
+    SERIAL_ECHOPAIR(" Y" ,endstop_adj[1] );
+    SERIAL_ECHOPAIR(" Z" ,endstop_adj[2] );
+    SERIAL_ECHOLN("");
+#endif
+#ifdef PIDTEMP
+    SERIAL_ECHO_START;
+    SERIAL_ECHOLNPGM("PID settings:");
+    SERIAL_ECHO_START;
+    SERIAL_ECHOPAIR("   M301 P",Kp); 
+    SERIAL_ECHOPAIR(" I" ,unscalePID_i(Ki)); 
+    SERIAL_ECHOPAIR(" D" ,unscalePID_d(Kd));
+    SERIAL_ECHOLN(""); 
+#endif
+} 
+#endif
+
+
+#ifdef EEPROM_SETTINGS
+void Config_RetrieveSettings()
+{
+    int i=EEPROM_OFFSET;
+    char stored_ver[4];
+    char ver[4]=EEPROM_VERSION;
+    EEPROM_READ_VAR(i,stored_ver); //read stored version
+    //  SERIAL_ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]");
+    if (strncmp(ver,stored_ver,3) == 0)
+    {
+        // version number match
+        EEPROM_READ_VAR(i,axis_steps_per_unit);  
+        EEPROM_READ_VAR(i,max_feedrate);  
+        EEPROM_READ_VAR(i,max_acceleration_units_per_sq_second);
+        
+        // steps per sq second need to be updated to agree with the units per sq second (as they are what is used in the planner)
+		reset_acceleration_rates();
+        
+        EEPROM_READ_VAR(i,acceleration);
+        EEPROM_READ_VAR(i,retract_acceleration);
+        EEPROM_READ_VAR(i,minimumfeedrate);
+        EEPROM_READ_VAR(i,mintravelfeedrate);
+        EEPROM_READ_VAR(i,minsegmenttime);
+        EEPROM_READ_VAR(i,max_xy_jerk);
+        EEPROM_READ_VAR(i,max_z_jerk);
+        EEPROM_READ_VAR(i,max_e_jerk);
+        EEPROM_READ_VAR(i,add_homeing);
+        #ifdef DELTA
+        EEPROM_READ_VAR(i,endstop_adj);
+        #endif
+        #ifndef ULTIPANEL
+        int plaPreheatHotendTemp, plaPreheatHPBTemp, plaPreheatFanSpeed;
+        int absPreheatHotendTemp, absPreheatHPBTemp, absPreheatFanSpeed;
+        #endif
+        EEPROM_READ_VAR(i,plaPreheatHotendTemp);
+        EEPROM_READ_VAR(i,plaPreheatHPBTemp);
+        EEPROM_READ_VAR(i,plaPreheatFanSpeed);
+        EEPROM_READ_VAR(i,absPreheatHotendTemp);
+        EEPROM_READ_VAR(i,absPreheatHPBTemp);
+        EEPROM_READ_VAR(i,absPreheatFanSpeed);
+        EEPROM_READ_VAR(i,zprobe_zoffset);
+        #ifndef PIDTEMP
+        float Kp,Ki,Kd;
+        #endif
+        // do not need to scale PID values as the values in EEPROM are already scaled		
+        EEPROM_READ_VAR(i,Kp);
+        EEPROM_READ_VAR(i,Ki);
+        EEPROM_READ_VAR(i,Kd);
+        #ifndef DOGLCD
+        int lcd_contrast;
+        #endif
+        EEPROM_READ_VAR(i,lcd_contrast);
+
+		// Call updatePID (similar to when we have processed M301)
+		updatePID();
+        SERIAL_ECHO_START;
+        SERIAL_ECHOLNPGM("Stored settings retrieved");
+    }
+    else
+    {
+        Config_ResetDefault();
+    }
+    #ifdef EEPROM_CHITCHAT
+      Config_PrintSettings();
+    #endif
+}
+#endif
+
+void Config_ResetDefault()
+{
+    float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT;
+    float tmp2[]=DEFAULT_MAX_FEEDRATE;
+    long tmp3[]=DEFAULT_MAX_ACCELERATION;
+    for (short i=0;i<4;i++) 
+    {
+        axis_steps_per_unit[i]=tmp1[i];  
+        max_feedrate[i]=tmp2[i];  
+        max_acceleration_units_per_sq_second[i]=tmp3[i];
+    }
+    
+    // steps per sq second need to be updated to agree with the units per sq second
+    reset_acceleration_rates();
+    
+    acceleration=DEFAULT_ACCELERATION;
+    retract_acceleration=DEFAULT_RETRACT_ACCELERATION;
+    minimumfeedrate=DEFAULT_MINIMUMFEEDRATE;
+    minsegmenttime=DEFAULT_MINSEGMENTTIME;       
+    mintravelfeedrate=DEFAULT_MINTRAVELFEEDRATE;
+    max_xy_jerk=DEFAULT_XYJERK;
+    max_z_jerk=DEFAULT_ZJERK;
+    max_e_jerk=DEFAULT_EJERK;
+    add_homeing[0] = add_homeing[1] = add_homeing[2] = 0;
+#ifdef DELTA
+    endstop_adj[0] = endstop_adj[1] = endstop_adj[2] = 0;
+#endif
+#ifdef ULTIPANEL
+    plaPreheatHotendTemp = PLA_PREHEAT_HOTEND_TEMP;
+    plaPreheatHPBTemp = PLA_PREHEAT_HPB_TEMP;
+    plaPreheatFanSpeed = PLA_PREHEAT_FAN_SPEED;
+    absPreheatHotendTemp = ABS_PREHEAT_HOTEND_TEMP;
+    absPreheatHPBTemp = ABS_PREHEAT_HPB_TEMP;
+    absPreheatFanSpeed = ABS_PREHEAT_FAN_SPEED;
+#endif
+#ifdef ENABLE_AUTO_BED_LEVELING
+    zprobe_zoffset = -Z_PROBE_OFFSET_FROM_EXTRUDER;
+#endif
+#ifdef DOGLCD
+    lcd_contrast = DEFAULT_LCD_CONTRAST;
+#endif
+#ifdef PIDTEMP
+    Kp = DEFAULT_Kp;
+    Ki = scalePID_i(DEFAULT_Ki);
+    Kd = scalePID_d(DEFAULT_Kd);
+    
+    // call updatePID (similar to when we have processed M301)
+    updatePID();
+    
+#ifdef PID_ADD_EXTRUSION_RATE
+    Kc = DEFAULT_Kc;
+#endif//PID_ADD_EXTRUSION_RATE
+#endif//PIDTEMP
+
+SERIAL_ECHO_START;
+SERIAL_ECHOLNPGM("Hardcoded Default Settings Loaded");
+
+}

+ 22 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/ConfigurationStore.h

@@ -0,0 +1,22 @@
+#ifndef CONFIG_STORE_H
+#define CONFIG_STORE_H
+
+#include "Configuration.h"
+
+void Config_ResetDefault();
+
+#ifndef DISABLE_M503
+void Config_PrintSettings();
+#else
+FORCE_INLINE void Config_PrintSettings() {}
+#endif
+
+#ifdef EEPROM_SETTINGS
+void Config_StoreSettings();
+void Config_RetrieveSettings();
+#else
+FORCE_INLINE void Config_StoreSettings() {}
+FORCE_INLINE void Config_RetrieveSettings() { Config_ResetDefault(); Config_PrintSettings(); }
+#endif
+
+#endif//CONFIG_STORE_H

+ 483 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Configuration_adv.h

@@ -0,0 +1,483 @@
+#ifndef CONFIGURATION_ADV_H
+#define CONFIGURATION_ADV_H
+
+//===========================================================================
+//=============================Thermal Settings  ============================
+//===========================================================================
+
+#ifdef BED_LIMIT_SWITCHING
+  #define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS
+#endif
+#define BED_CHECK_INTERVAL 5000 //ms between checks in bang-bang control
+
+//// Heating sanity check:
+// This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature
+// If the temperature has not increased at the end of that period, the target temperature is set to zero.
+// It can be reset with another M104/M109. This check is also only triggered if the target temperature and the current temperature
+//  differ by at least 2x WATCH_TEMP_INCREASE
+//#define WATCH_TEMP_PERIOD 40000 //40 seconds
+//#define WATCH_TEMP_INCREASE 10  //Heat up at least 10 degree in 20 seconds
+
+#ifdef PIDTEMP
+  // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed.
+  // if Kc is choosen well, the additional required power due to increased melting should be compensated.
+  #define PID_ADD_EXTRUSION_RATE
+  #ifdef PID_ADD_EXTRUSION_RATE
+    #define  DEFAULT_Kc (1) //heatingpower=Kc*(e_speed)
+  #endif
+#endif
+
+
+//automatic temperature: The hot end target temperature is calculated by all the buffered lines of gcode.
+//The maximum buffered steps/sec of the extruder motor are called "se".
+//You enter the autotemp mode by a M109 S<mintemp> T<maxtemp> F<factor>
+// the target temperature is set to mintemp+factor*se[steps/sec] and limited by mintemp and maxtemp
+// you exit the value by any M109 without F*
+// Also, if the temperature is set to a value <mintemp, it is not changed by autotemp.
+// on an ultimaker, some initial testing worked with M109 S215 B260 F1 in the start.gcode
+#define AUTOTEMP
+#ifdef AUTOTEMP
+  #define AUTOTEMP_OLDWEIGHT 0.98
+#endif
+
+//Show Temperature ADC value
+//The M105 command return, besides traditional information, the ADC value read from temperature sensors.
+//#define SHOW_TEMP_ADC_VALUES
+
+//  extruder run-out prevention.
+//if the machine is idle, and the temperature over MINTEMP, every couple of SECONDS some filament is extruded
+//#define EXTRUDER_RUNOUT_PREVENT
+#define EXTRUDER_RUNOUT_MINTEMP 190
+#define EXTRUDER_RUNOUT_SECONDS 30.
+#define EXTRUDER_RUNOUT_ESTEPS 14. //mm filament
+#define EXTRUDER_RUNOUT_SPEED 1500.  //extrusion speed
+#define EXTRUDER_RUNOUT_EXTRUDE 100
+
+//These defines help to calibrate the AD595 sensor in case you get wrong temperature measurements.
+//The measured temperature is defined as "actualTemp = (measuredTemp * TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET"
+#define TEMP_SENSOR_AD595_OFFSET 0.0
+#define TEMP_SENSOR_AD595_GAIN   1.0
+
+//This is for controlling a fan to cool down the stepper drivers
+//it will turn on when any driver is enabled
+//and turn off after the set amount of seconds from last driver being disabled again
+#define CONTROLLERFAN_PIN -1 //Pin used for the fan to cool controller (-1 to disable)
+#define CONTROLLERFAN_SECS 60 //How many seconds, after all motors were disabled, the fan should run
+#define CONTROLLERFAN_SPEED 255  // == full speed
+
+// When first starting the main fan, run it at full speed for the
+// given number of milliseconds.  This gets the fan spinning reliably
+// before setting a PWM value. (Does not work with software PWM for fan on Sanguinololu)
+//#define FAN_KICKSTART_TIME 100
+
+// Extruder cooling fans
+// Configure fan pin outputs to automatically turn on/off when the associated
+// extruder temperature is above/below EXTRUDER_AUTO_FAN_TEMPERATURE.
+// Multiple extruders can be assigned to the same pin in which case
+// the fan will turn on when any selected extruder is above the threshold.
+#define EXTRUDER_0_AUTO_FAN_PIN   -1
+#define EXTRUDER_1_AUTO_FAN_PIN   -1
+#define EXTRUDER_2_AUTO_FAN_PIN   -1
+#define EXTRUDER_AUTO_FAN_TEMPERATURE 50
+#define EXTRUDER_AUTO_FAN_SPEED   255  // == full speed
+
+
+//===========================================================================
+//=============================Mechanical Settings===========================
+//===========================================================================
+
+#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing
+
+
+//// AUTOSET LOCATIONS OF LIMIT SWITCHES
+//// Added by ZetaPhoenix 09-15-2012
+#ifdef MANUAL_HOME_POSITIONS  // Use manual limit switch locations
+  #define X_HOME_POS MANUAL_X_HOME_POS
+  #define Y_HOME_POS MANUAL_Y_HOME_POS
+  #define Z_HOME_POS MANUAL_Z_HOME_POS
+#else //Set min/max homing switch positions based upon homing direction and min/max travel limits
+  //X axis
+  #if X_HOME_DIR == -1
+    #ifdef BED_CENTER_AT_0_0
+      #define X_HOME_POS X_MAX_LENGTH * -0.5
+    #else
+      #define X_HOME_POS X_MIN_POS
+    #endif //BED_CENTER_AT_0_0
+  #else
+    #ifdef BED_CENTER_AT_0_0
+      #define X_HOME_POS X_MAX_LENGTH * 0.5
+    #else
+      #define X_HOME_POS X_MAX_POS
+    #endif //BED_CENTER_AT_0_0
+  #endif //X_HOME_DIR == -1
+
+  //Y axis
+  #if Y_HOME_DIR == -1
+    #ifdef BED_CENTER_AT_0_0
+      #define Y_HOME_POS Y_MAX_LENGTH * -0.5
+    #else
+      #define Y_HOME_POS Y_MIN_POS
+    #endif //BED_CENTER_AT_0_0
+  #else
+    #ifdef BED_CENTER_AT_0_0
+      #define Y_HOME_POS Y_MAX_LENGTH * 0.5
+    #else
+      #define Y_HOME_POS Y_MAX_POS
+    #endif //BED_CENTER_AT_0_0
+  #endif //Y_HOME_DIR == -1
+
+  // Z axis
+  #if Z_HOME_DIR == -1 //BED_CENTER_AT_0_0 not used
+    #define Z_HOME_POS Z_MIN_POS
+  #else
+    #define Z_HOME_POS Z_MAX_POS
+  #endif //Z_HOME_DIR == -1
+#endif //End auto min/max positions
+//END AUTOSET LOCATIONS OF LIMIT SWITCHES -ZP
+
+
+//#define Z_LATE_ENABLE // Enable Z the last moment. Needed if your Z driver overheats.
+
+// A single Z stepper driver is usually used to drive 2 stepper motors.
+// Uncomment this define to utilize a separate stepper driver for each Z axis motor.
+// Only a few motherboards support this, like RAMPS, which have dual extruder support (the 2nd, often unused, extruder driver is used
+// to control the 2nd Z axis stepper motor). The pins are currently only defined for a RAMPS motherboards.
+// On a RAMPS (or other 5 driver) motherboard, using this feature will limit you to using 1 extruder.
+//#define Z_DUAL_STEPPER_DRIVERS
+
+#ifdef Z_DUAL_STEPPER_DRIVERS
+  #undef EXTRUDERS
+  #define EXTRUDERS 1
+#endif
+
+// Same again but for Y Axis.
+//#define Y_DUAL_STEPPER_DRIVERS
+
+// Define if the two Y drives need to rotate in opposite directions
+#define INVERT_Y2_VS_Y_DIR true
+
+#ifdef Y_DUAL_STEPPER_DRIVERS
+  #undef EXTRUDERS
+  #define EXTRUDERS 1
+#endif
+
+#if defined (Z_DUAL_STEPPER_DRIVERS) && defined (Y_DUAL_STEPPER_DRIVERS)
+  #error "You cannot have dual drivers for both Y and Z"
+#endif
+
+// Enable this for dual x-carriage printers.
+// A dual x-carriage design has the advantage that the inactive extruder can be parked which
+// prevents hot-end ooze contaminating the print. It also reduces the weight of each x-carriage
+// allowing faster printing speeds.
+//#define DUAL_X_CARRIAGE
+#ifdef DUAL_X_CARRIAGE
+// Configuration for second X-carriage
+// Note: the first x-carriage is defined as the x-carriage which homes to the minimum endstop;
+// the second x-carriage always homes to the maximum endstop.
+#define X2_MIN_POS 80     // set minimum to ensure second x-carriage doesn't hit the parked first X-carriage
+#define X2_MAX_POS 353    // set maximum to the distance between toolheads when both heads are homed
+#define X2_HOME_DIR 1     // the second X-carriage always homes to the maximum endstop position
+#define X2_HOME_POS X2_MAX_POS // default home position is the maximum carriage position
+    // However: In this mode the EXTRUDER_OFFSET_X value for the second extruder provides a software
+    // override for X2_HOME_POS. This also allow recalibration of the distance between the two endstops
+    // without modifying the firmware (through the "M218 T1 X???" command).
+    // Remember: you should set the second extruder x-offset to 0 in your slicer.
+
+// Pins for second x-carriage stepper driver (defined here to avoid further complicating pins.h)
+#define X2_ENABLE_PIN 29
+#define X2_STEP_PIN 25
+#define X2_DIR_PIN 23
+
+// There are a few selectable movement modes for dual x-carriages using M605 S<mode>
+//    Mode 0: Full control. The slicer has full control over both x-carriages and can achieve optimal travel results
+//                           as long as it supports dual x-carriages. (M605 S0)
+//    Mode 1: Auto-park mode. The firmware will automatically park and unpark the x-carriages on tool changes so
+//                           that additional slicer support is not required. (M605 S1)
+//    Mode 2: Duplication mode. The firmware will transparently make the second x-carriage and extruder copy all
+//                           actions of the first x-carriage. This allows the printer to print 2 arbitrary items at
+//                           once. (2nd extruder x offset and temp offset are set using: M605 S2 [Xnnn] [Rmmm])
+
+// This is the default power-up mode which can be later using M605.
+#define DEFAULT_DUAL_X_CARRIAGE_MODE 0
+
+// As the x-carriages are independent we can now account for any relative Z offset
+#define EXTRUDER1_Z_OFFSET 0.0           // z offset relative to extruder 0
+
+// Default settings in "Auto-park Mode"
+#define TOOLCHANGE_PARK_ZLIFT   0.2      // the distance to raise Z axis when parking an extruder
+#define TOOLCHANGE_UNPARK_ZLIFT 1        // the distance to raise Z axis when unparking an extruder
+
+// Default x offset in duplication mode (typically set to half print bed width)
+#define DEFAULT_DUPLICATION_X_OFFSET 100
+
+#endif //DUAL_X_CARRIAGE
+
+//homing hits the endstop, then retracts by this distance, before it tries to slowly bump again:
+#define X_HOME_RETRACT_MM 5
+#define Y_HOME_RETRACT_MM 5
+#define Z_HOME_RETRACT_MM 1
+//#define QUICK_HOME  //if this is defined, if both x and y are to be homed, a diagonal move will be performed initially.
+
+#define AXIS_RELATIVE_MODES {false, false, false, false}
+
+#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step)
+
+//By default pololu step drivers require an active high signal. However, some high power drivers require an active low signal as step.
+#define INVERT_X_STEP_PIN false
+#define INVERT_Y_STEP_PIN false
+#define INVERT_Z_STEP_PIN false
+#define INVERT_E_STEP_PIN false
+
+//default stepper release if idle
+#define DEFAULT_STEPPER_DEACTIVE_TIME 60
+
+#define DEFAULT_MINIMUMFEEDRATE       0.0     // minimum feedrate
+#define DEFAULT_MINTRAVELFEEDRATE     0.0
+
+// Feedrates for manual moves along X, Y, Z, E from panel
+#ifdef ULTIPANEL
+#define MANUAL_FEEDRATE {50*60, 50*60, 4*60, 60}  // set the speeds for manual moves (mm/min)
+#endif
+
+// minimum time in microseconds that a movement needs to take if the buffer is emptied.
+#define DEFAULT_MINSEGMENTTIME        20000
+
+// If defined the movements slow down when the look ahead buffer is only half full
+#define SLOWDOWN
+
+// Frequency limit
+// See nophead's blog for more info
+// Not working O
+//#define XY_FREQUENCY_LIMIT  15
+
+// Minimum planner junction speed. Sets the default minimum speed the planner plans for at the end
+// of the buffer and all stops. This should not be much greater than zero and should only be changed
+// if unwanted behavior is observed on a user's machine when running at very slow speeds.
+#define MINIMUM_PLANNER_SPEED 0.05// (mm/sec)
+
+// MS1 MS2 Stepper Driver Microstepping mode table
+#define MICROSTEP1 LOW,LOW
+#define MICROSTEP2 HIGH,LOW
+#define MICROSTEP4 LOW,HIGH
+#define MICROSTEP8 HIGH,HIGH
+#define MICROSTEP16 HIGH,HIGH
+
+// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
+#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]
+
+// Motor Current setting (Only functional when motor driver current ref pins are connected to a digital trimpot on supported boards)
+#define DIGIPOT_MOTOR_CURRENT {135,135,135,135,135} // Values 0-255 (RAMBO 135 = ~0.75A, 185 = ~1A)
+
+// uncomment to enable an I2C based DIGIPOT like on the Azteeg X3 Pro
+//#define DIGIPOT_I2C
+// Number of channels available for I2C digipot, For Azteeg X3 Pro we have 8
+#define DIGIPOT_I2C_NUM_CHANNELS 8
+// actual motor currents in Amps, need as many here as DIGIPOT_I2C_NUM_CHANNELS
+#define DIGIPOT_I2C_MOTOR_CURRENTS {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}
+
+//===========================================================================
+//=============================Additional Features===========================
+//===========================================================================
+
+#define SD_FINISHED_STEPPERRELEASE true  //if sd support and the file is finished: disable steppers?
+#define SD_FINISHED_RELEASECOMMAND "M84 X Y Z E" // You might want to keep the z enabled so your bed stays in place.
+
+#define SDCARD_RATHERRECENTFIRST  //reverse file order of sd card menu display. Its sorted practically after the filesystem block order.
+// if a file is deleted, it frees a block. hence, the order is not purely cronological. To still have auto0.g accessible, there is again the option to do that.
+// using:
+//#define MENU_ADDAUTOSTART
+
+// The hardware watchdog should reset the Microcontroller disabling all outputs, in case the firmware gets stuck and doesn't do temperature regulation.
+//#define USE_WATCHDOG
+
+#ifdef USE_WATCHDOG
+// If you have a watchdog reboot in an ArduinoMega2560 then the device will hang forever, as a watchdog reset will leave the watchdog on.
+// The "WATCHDOG_RESET_MANUAL" goes around this by not using the hardware reset.
+//  However, THIS FEATURE IS UNSAFE!, as it will only work if interrupts are disabled. And the code could hang in an interrupt routine with interrupts disabled.
+//#define WATCHDOG_RESET_MANUAL
+#endif
+
+// Enable the option to stop SD printing when hitting and endstops, needs to be enabled from the LCD menu when this option is enabled.
+//#define ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
+
+// Babystepping enables the user to control the axis in tiny amounts, independently from the normal printing process
+// it can e.g. be used to change z-positions in the print startup phase in realtime
+// does not respect endstops!
+//#define BABYSTEPPING
+#ifdef BABYSTEPPING
+  #define BABYSTEP_XY  //not only z, but also XY in the menu. more clutter, more functions
+  #define BABYSTEP_INVERT_Z false  //true for inverse movements in Z
+  #define BABYSTEP_Z_MULTIPLICATOR 2 //faster z movements
+
+  #ifdef COREXY
+    #error BABYSTEPPING not implemented for COREXY yet.
+  #endif
+
+  #ifdef DELTA
+    #ifdef BABYSTEP_XY
+      #error BABYSTEPPING only implemented for Z axis on deltabots.
+    #endif
+  #endif
+#endif
+
+// extruder advance constant (s2/mm3)
+//
+// advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2
+//
+// hooke's law says:		force = k * distance
+// bernoulli's priniciple says:	v ^ 2 / 2 + g . h + pressure / density = constant
+// so: v ^ 2 is proportional to number of steps we advance the extruder
+//#define ADVANCE
+
+#ifdef ADVANCE
+  #define EXTRUDER_ADVANCE_K .0
+
+  #define D_FILAMENT 2.85
+  #define STEPS_MM_E 836
+  #define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159)
+  #define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA)
+
+#endif // ADVANCE
+
+// Arc interpretation settings:
+#define MM_PER_ARC_SEGMENT 1
+#define N_ARC_CORRECTION 25
+
+const unsigned int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement
+
+// If you are using a RAMPS board or cheap E-bay purchased boards that do not detect when an SD card is inserted
+// You can get round this by connecting a push button or single throw switch to the pin defined as SDCARDCARDDETECT
+// in the pins.h file.  When using a push button pulling the pin to ground this will need inverted.  This setting should
+// be commented out otherwise
+#define SDCARDDETECTINVERTED
+
+#ifdef ULTIPANEL
+ #undef SDCARDDETECTINVERTED
+#endif
+
+// Power Signal Control Definitions
+// By default use ATX definition
+#ifndef POWER_SUPPLY
+  #define POWER_SUPPLY 1
+#endif
+// 1 = ATX
+#if (POWER_SUPPLY == 1)
+  #define PS_ON_AWAKE  LOW
+  #define PS_ON_ASLEEP HIGH
+#endif
+// 2 = X-Box 360 203W
+#if (POWER_SUPPLY == 2)
+  #define PS_ON_AWAKE  HIGH
+  #define PS_ON_ASLEEP LOW
+#endif
+
+// Control heater 0 and heater 1 in parallel.
+//#define HEATERS_PARALLEL
+
+//===========================================================================
+//=============================Buffers           ============================
+//===========================================================================
+
+// The number of linear motions that can be in the plan at any give time.
+// THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, i.g. 8,16,32 because shifts and ors are used to do the ringbuffering.
+#if defined SDSUPPORT
+  #define BLOCK_BUFFER_SIZE 16   // SD,LCD,Buttons take more memory, block buffer needs to be smaller
+#else
+  #define BLOCK_BUFFER_SIZE 16 // maximize block buffer
+#endif
+
+
+//The ASCII buffer for recieving from the serial:
+#define MAX_CMD_SIZE 96
+#define BUFSIZE 4
+
+
+// Firmware based and LCD controled retract
+// M207 and M208 can be used to define parameters for the retraction.
+// The retraction can be called by the slicer using G10 and G11
+// until then, intended retractions can be detected by moves that only extrude and the direction.
+// the moves are than replaced by the firmware controlled ones.
+
+// #define FWRETRACT  //ONLY PARTIALLY TESTED
+#define MIN_RETRACT 0.1 //minimum extruded mm to accept a automatic gcode retraction attempt
+
+
+//adds support for experimental filament exchange support M600; requires display
+#ifdef ULTIPANEL
+  #define FILAMENTCHANGEENABLE
+  #ifdef FILAMENTCHANGEENABLE
+    #define FILAMENTCHANGE_XPOS 3
+    #define FILAMENTCHANGE_YPOS 3
+    #define FILAMENTCHANGE_ZADD 10
+    #define FILAMENTCHANGE_FIRSTRETRACT -2
+    #define FILAMENTCHANGE_FINALRETRACT -100
+  #endif
+#endif
+
+#ifdef FILAMENTCHANGEENABLE
+  #ifdef EXTRUDER_RUNOUT_PREVENT
+    #error EXTRUDER_RUNOUT_PREVENT currently incompatible with FILAMENTCHANGE
+  #endif
+#endif
+
+//===========================================================================
+//=============================  Define Defines  ============================
+//===========================================================================
+#if EXTRUDERS > 1 && defined TEMP_SENSOR_1_AS_REDUNDANT
+  #error "You cannot use TEMP_SENSOR_1_AS_REDUNDANT if EXTRUDERS > 1"
+#endif
+
+#if EXTRUDERS > 1 && defined HEATERS_PARALLEL
+  #error "You cannot use HEATERS_PARALLEL if EXTRUDERS > 1"
+#endif
+
+#if TEMP_SENSOR_0 > 0
+  #define THERMISTORHEATER_0 TEMP_SENSOR_0
+  #define HEATER_0_USES_THERMISTOR
+#endif
+#if TEMP_SENSOR_1 > 0
+  #define THERMISTORHEATER_1 TEMP_SENSOR_1
+  #define HEATER_1_USES_THERMISTOR
+#endif
+#if TEMP_SENSOR_2 > 0
+  #define THERMISTORHEATER_2 TEMP_SENSOR_2
+  #define HEATER_2_USES_THERMISTOR
+#endif
+#if TEMP_SENSOR_BED > 0
+  #define THERMISTORBED TEMP_SENSOR_BED
+  #define BED_USES_THERMISTOR
+#endif
+#if TEMP_SENSOR_0 == -1
+  #define HEATER_0_USES_AD595
+#endif
+#if TEMP_SENSOR_1 == -1
+  #define HEATER_1_USES_AD595
+#endif
+#if TEMP_SENSOR_2 == -1
+  #define HEATER_2_USES_AD595
+#endif
+#if TEMP_SENSOR_BED == -1
+  #define BED_USES_AD595
+#endif
+#if TEMP_SENSOR_0 == -2
+  #define HEATER_0_USES_MAX6675
+#endif
+#if TEMP_SENSOR_0 == 0
+  #undef HEATER_0_MINTEMP
+  #undef HEATER_0_MAXTEMP
+#endif
+#if TEMP_SENSOR_1 == 0
+  #undef HEATER_1_MINTEMP
+  #undef HEATER_1_MAXTEMP
+#endif
+#if TEMP_SENSOR_2 == 0
+  #undef HEATER_2_MINTEMP
+  #undef HEATER_2_MAXTEMP
+#endif
+#if TEMP_SENSOR_BED == 0
+  #undef BED_MINTEMP
+  #undef BED_MAXTEMP
+#endif
+
+
+#endif //__CONFIGURATION_ADV_H

+ 487 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/DOGMbitmaps.h

@@ -0,0 +1,487 @@
+#define START_BMPWIDTH 	128	//Width in pixels
+#define START_BMPHEIGHT 	64	//Height in pixels
+#define START_BMPBYTEWIDTH 	16	//Width in bytes
+const unsigned char start_bmp[] PROGMEM = { //AVR-GCC, WinAVR
+/*0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0xF9,0xFF,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0xF0,0xFF,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0xE0,0x7F,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0xC0,0x3F,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0x80,0x1F,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0x00,0x0F,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFC,0x00,0x03,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xF8,0x00,0x01,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xE0,0x00,0x00,0x7F,0xFF,0xF0,
+0xFF,0xFF,0xC0,0x00,0x00,0x3F,0xFF,0xF0,
+0xFF,0xFF,0x80,0x00,0x00,0x3F,0xFF,0xF0,
+0xFF,0xFF,0x00,0x00,0x00,0x1F,0xFF,0xF0,
+0xFF,0xFE,0x00,0x00,0x00,0x0F,0xFF,0xF0,
+0xFF,0xFE,0x00,0x00,0x00,0x07,0xFF,0xF0,
+0xFF,0xFC,0x00,0x00,0x00,0x07,0xFF,0xF0,
+0xFF,0xFC,0x00,0x00,0x00,0x03,0xFF,0xF0,
+0xFF,0xF8,0x00,0x00,0x00,0x03,0xFF,0xF0,
+0xFF,0xF8,0x00,0x00,0x00,0x03,0xFF,0xF0,
+0xFF,0xF8,0x00,0x00,0x00,0x01,0xFF,0xF0,
+0xFF,0xF8,0x00,0x00,0x00,0x01,0xFF,0xF0,
+0xFF,0xF8,0x00,0x00,0x00,0x01,0xFF,0xF0,
+0xFF,0xF8,0x00,0x00,0x00,0x01,0xFF,0xF0,
+0xFF,0xF8,0x00,0x00,0x00,0x01,0xFF,0xF0,
+0xFF,0xF8,0x00,0x00,0x00,0x01,0xFF,0xF0,
+0xFF,0xF8,0x00,0x00,0x00,0x01,0xFF,0xF0,
+0xFF,0xF8,0x00,0x00,0x00,0x01,0xFF,0xF0,
+0xFF,0xF8,0x00,0x00,0x00,0x03,0xFF,0xF0,
+0xFF,0xF8,0x00,0x00,0x00,0x03,0xFF,0xF0,
+0xFF,0xFC,0x00,0x00,0x00,0x03,0xFF,0xF0,
+0xFF,0xFC,0x00,0x00,0x00,0x07,0xFF,0xF0,
+0xFF,0xFE,0x00,0x00,0x00,0x07,0xFF,0xF0,
+0xFF,0xFE,0x00,0x00,0x00,0x0F,0xFF,0xF0,
+0xFF,0xFF,0x00,0x00,0x00,0x1F,0xFF,0xF0,
+0xFF,0xFF,0x80,0x00,0x00,0x1F,0xFF,0xF0,
+0xFF,0xFF,0xC0,0x00,0x00,0x3F,0xFF,0xF0,
+0xFF,0xFF,0xE0,0x00,0x00,0x7F,0xFF,0xF0,
+0xFF,0xFF,0xF0,0x00,0x01,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFC,0x00,0x03,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0x00,0x1F,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,
+0x83,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xF0,
+0x80,0xFF,0xFF,0xFE,0x03,0xFF,0xFF,0xF0,
+0x88,0x7F,0xFF,0xFE,0x23,0xFF,0xFF,0xF0,
+0x8C,0x70,0x38,0x0E,0x71,0x81,0xC0,0x70,
+0x8C,0x60,0x38,0x0E,0x63,0x80,0xC0,0x30,
+0x80,0xE3,0x19,0xC6,0x07,0xF8,0xC7,0x30,
+0x80,0xE0,0x19,0xC6,0x03,0x80,0xC7,0x10,
+0x8C,0x62,0x79,0xC6,0x63,0x9C,0xC7,0x30,
+0x8C,0x63,0xF8,0xC6,0x71,0x18,0xC6,0x30,
+0x8E,0x30,0x18,0x0E,0x71,0x80,0xC0,0x30,
+0x9E,0x38,0x39,0x1E,0x79,0xC4,0xC4,0xF0,
+0xFF,0xFF,0xF9,0xFF,0xFF,0xFF,0xC7,0xF0,
+0xFF,0xFF,0xF9,0xFF,0xFF,0xFF,0xC7,0xF0,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0
+
+
+//3D printer
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0xFC,0x03,0xFC,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x03,0xFE,0x03,0xFF,0x00,0x00,0xFF,0x80,0x01,0x80,0x00,0x03,0x00,0x00,0x00,0x00,
+0x03,0x07,0x06,0x07,0x80,0x01,0x81,0xC0,0x01,0x80,0x00,0x03,0x00,0x00,0x00,0x00,
+0x00,0x03,0x06,0x01,0x80,0x01,0x80,0xC0,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,
+0x00,0x03,0x06,0x01,0xC0,0x01,0x80,0xC0,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,
+0x00,0x06,0x06,0x00,0xC0,0x01,0x80,0xC6,0x71,0x83,0x7E,0x0F,0xE0,0xF8,0x0C,0xE0,
+0x00,0x0E,0x06,0x00,0xC0,0x01,0x80,0xC7,0xF1,0x83,0xFF,0x1F,0xE3,0xFC,0x0F,0xE0,
+0x00,0xF8,0x0C,0x00,0xC0,0x03,0x01,0x8F,0x03,0x07,0x87,0x06,0x07,0x0E,0x1E,0x00,
+0x00,0xF8,0x0C,0x00,0xC0,0x03,0x07,0x0C,0x03,0x06,0x03,0x0C,0x0C,0x06,0x18,0x00,
+0x00,0x0C,0x0C,0x00,0xC0,0x03,0xFE,0x0C,0x03,0x06,0x03,0x0C,0x0C,0x06,0x18,0x00,
+0x00,0x06,0x0C,0x01,0x80,0x03,0xF8,0x0C,0x03,0x06,0x03,0x0C,0x1F,0xFE,0x18,0x00,
+0x00,0x06,0x18,0x01,0x80,0x06,0x00,0x18,0x06,0x0C,0x06,0x0C,0x1F,0xFE,0x30,0x00,
+0x00,0x06,0x18,0x01,0x80,0x06,0x00,0x18,0x06,0x0C,0x06,0x18,0x18,0x00,0x30,0x00,
+0x00,0x06,0x18,0x03,0x00,0x06,0x00,0x18,0x06,0x0C,0x06,0x18,0x18,0x00,0x30,0x00,
+0x00,0x0C,0x18,0x06,0x00,0x06,0x00,0x18,0x06,0x0C,0x06,0x18,0x18,0x00,0x30,0x00,
+0x18,0x1C,0x18,0x1C,0x00,0x06,0x00,0x18,0x06,0x0C,0x06,0x18,0x1C,0x0C,0x30,0x00,
+0x1F,0xF8,0x3F,0xF8,0x00,0x0C,0x00,0x30,0x0C,0x18,0x0C,0x1F,0x8F,0xFC,0x60,0x00,
+0x0F,0xE0,0x3F,0xE0,0x00,0x0C,0x00,0x30,0x0C,0x18,0x0C,0x0F,0x83,0xF0,0x60,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+*/
+  // chuangxiang 3D
+/*
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x60,0x00,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,
+0x00,0x00,0x00,0xE0,0x06,0x01,0x80,0x18,0x00,0x00,0x00,0x0E,0x1F,0x00,0x00,0x00,
+0x00,0x00,0x00,0xF8,0x06,0x01,0x87,0xF8,0x00,0x00,0x70,0x0C,0x39,0x80,0x00,0x00,
+0x00,0x00,0x00,0xCE,0x06,0x01,0xB6,0x18,0x0F,0xFF,0xC0,0x0C,0x30,0x00,0x00,0x00,
+0x00,0x00,0x01,0x86,0x66,0x0F,0xE6,0x18,0x00,0x00,0x00,0x19,0xBF,0xF0,0x00,0x00,
+0x00,0x00,0x01,0x80,0x66,0x03,0x87,0xF8,0x00,0x00,0x00,0x1B,0xB3,0x00,0x00,0x00,
+0x00,0x00,0x03,0x00,0x66,0x03,0xC6,0x18,0x00,0x00,0x00,0x33,0x73,0x00,0x00,0x00,
+0x00,0x00,0x07,0xFC,0x66,0x07,0xF7,0xF8,0x00,0x00,0x00,0x7E,0xF3,0x00,0x00,0x00,
+0x00,0x00,0x0D,0x8C,0x66,0x07,0xB6,0x18,0x00,0x00,0xC0,0x36,0xFF,0xF0,0x00,0x00,
+0x00,0x00,0x01,0x8C,0x66,0x0D,0x86,0x18,0x00,0x01,0xE0,0x0D,0xB3,0x00,0x00,0x00,
+0x00,0x00,0x01,0x8C,0x66,0x19,0x87,0xF8,0x03,0xFF,0x00,0x0C,0x33,0x00,0x00,0x00,
+0x00,0x00,0x01,0x9C,0x66,0x01,0x86,0x18,0x00,0x00,0x00,0x1B,0xB3,0x00,0x00,0x00,
+0x00,0x00,0x01,0xF8,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x3F,0xF0,0x00,0x00,
+0x00,0x00,0x01,0xB8,0x06,0x00,0x6C,0x38,0x00,0x00,0x00,0x00,0x33,0x00,0x00,0x00,
+0x00,0x00,0x01,0x83,0x06,0x00,0x66,0x1C,0x00,0x00,0x00,0x01,0xB3,0x00,0x00,0x00,
+0x00,0x00,0x01,0x83,0x06,0x06,0x67,0xCE,0x00,0x00,0x18,0x0F,0x33,0x00,0x00,0x00,
+0x00,0x00,0x01,0x83,0x06,0x0E,0x60,0xC0,0x1F,0xFF,0xFC,0x38,0x33,0x38,0x00,0x00,
+0x00,0x00,0x01,0xFF,0x3E,0x0C,0x7F,0xE0,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,
+0x00,0x00,0x00,0x00,0x0C,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7E,0x00,0x00,0x00,0x0F,0x03,0x80,0x00,0x00,0x00,0x3E,0x7E,0x00,0x00,
+0x00,0x00,0xC6,0x00,0x00,0x00,0x03,0x03,0x80,0x00,0x00,0x00,0x63,0x33,0x00,0x00,
+0x00,0x00,0xC6,0x00,0x00,0x00,0x03,0x00,0x00,0xC0,0x00,0x00,0x63,0x31,0x80,0x00,
+0x00,0x01,0x80,0x00,0x00,0x00,0x03,0x00,0x00,0xC0,0x00,0x00,0x06,0x31,0x80,0x00,
+0x00,0x01,0x80,0xFF,0x1F,0x0F,0x83,0x07,0x83,0xF3,0xDE,0x00,0x1C,0x31,0x80,0x00,
+0x00,0x01,0x80,0x3B,0x31,0x98,0xC3,0x01,0x80,0xC1,0x8C,0x00,0x06,0x31,0x80,0x00,
+0x00,0x01,0x80,0x30,0x3F,0x87,0xC3,0x01,0x80,0xC0,0xD8,0x00,0x03,0x31,0x80,0x00,
+0x00,0x01,0x80,0x30,0x30,0x0C,0xC3,0x01,0x80,0xC0,0xD8,0x00,0x03,0x31,0x80,0x00,
+0x00,0x00,0xC6,0x30,0x30,0x18,0xC3,0x01,0x80,0xC0,0xF0,0x00,0x63,0x31,0x80,0x00,
+0x00,0x00,0xCC,0x30,0x31,0x98,0xC3,0x01,0x80,0xC0,0x70,0x00,0x66,0x33,0x00,0x00,
+0x00,0x00,0x78,0xFC,0x1F,0x0F,0xEF,0xC7,0xE0,0x70,0x60,0x00,0x3C,0x7E,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+*/
+
+//Creality 3d
+/*
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,
+0x01,0xFC,0x00,0x00,0x00,0x00,0x7C,0x03,0x80,0x00,0x00,0x00,0x00,0xC6,0x3F,0x80,
+0x03,0x1C,0x00,0x00,0x00,0x00,0x0C,0x03,0x80,0x30,0x00,0x00,0x00,0xC3,0x18,0xC0,
+0x06,0x0C,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x30,0x00,0x00,0x00,0xC3,0x18,0x60,
+0x06,0x0C,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x30,0x00,0x00,0x00,0x03,0x18,0x30,
+0x0C,0x00,0xF7,0x87,0xC1,0xF8,0x0C,0x07,0x80,0xFE,0x3D,0xE0,0x00,0x06,0x18,0x30,
+0x0C,0x00,0x3D,0x8C,0x63,0x0C,0x0C,0x01,0x80,0x30,0x18,0xC0,0x00,0x1E,0x18,0x30,
+0x0C,0x00,0x38,0x18,0x33,0x0C,0x0C,0x01,0x80,0x30,0x0D,0x80,0x00,0x03,0x18,0x30,
+0x0C,0x00,0x30,0x18,0x30,0x3C,0x0C,0x01,0x80,0x30,0x0D,0x80,0x00,0x01,0x98,0x30,
+0x0C,0x00,0x30,0x1F,0xF1,0xEC,0x0C,0x01,0x80,0x30,0x0D,0x80,0x00,0x01,0x98,0x30,
+0x0C,0x0C,0x30,0x18,0x03,0x0C,0x0C,0x01,0x80,0x30,0x07,0x80,0x00,0xC1,0x98,0x30,
+0x06,0x0C,0x30,0x18,0x33,0x0C,0x0C,0x01,0x80,0x30,0x07,0x00,0x00,0xC1,0x98,0x60,
+0x07,0x18,0x30,0x0C,0x63,0x1F,0x0C,0x01,0x80,0x33,0x03,0x00,0x00,0xC3,0x18,0xC0,
+0x01,0xF0,0xFC,0x07,0xC1,0xFF,0x7F,0x87,0xE0,0x1E,0x03,0x00,0x00,0x7E,0x3F,0x80,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+*/
+
+// ENDER
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0xCF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1,0xE1,0xCF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFE,0x78,0x00,0x00,0x03,0xDD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFE,0xFF,0x80,0x7E,0x00,0x01,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFE,0x7D,0xCF,0xFC,0x00,0x00,0xF7,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0x8E,0x06,0x00,0x00,0x00,0x7B,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x7D,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFC,0x01,0xFE,0x00,0x00,0x3E,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x00,0x03,0x1F,0x73,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x00,0x01,0x8F,0x81,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x83,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xFC,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x0F,0xFF,0xC0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFE,0x03,0xFF,0xFF,0xC0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x00,0x07,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x07,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x07,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x07,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x83,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xF8,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0xF8,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7E,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x7F,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xFF,0xFF,0xE0,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xC3,0xFC,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xC3,0xFC,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0x87,0xFD,0xFF,0xFF,0xFF,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0x87,0xFF,0xFF,0xFF,0xFF,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0x0F,0xE7,0xF3,0x0F,0xFC,0x23,0xFC,0x3F,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0x0F,0xEF,0x80,0x07,0xF0,0x03,0xF0,0x1E,0x00,0x7F,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFE,0x1F,0xCF,0x81,0x87,0xC7,0x87,0xC7,0x0C,0x00,0x7F,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFE,0x00,0x1F,0xC7,0xC7,0x8F,0xC7,0x9F,0x0F,0x0C,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFE,0x00,0x1F,0x87,0x8F,0x1F,0x8F,0x1F,0x0F,0x1F,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFC,0x3F,0x9F,0x8F,0x8F,0x1F,0x8E,0x00,0x1E,0x3F,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFC,0x7F,0x3F,0x0F,0x1E,0x3F,0x1E,0x3F,0xFE,0x3F,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xF8,0x7F,0xFF,0x1F,0x1C,0x3F,0x1C,0x7F,0xFC,0x7F,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0x1E,0x1C,0x7E,0x1C,0x7F,0xFC,0x7F,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xF0,0xFF,0xCE,0x3E,0x3C,0x7E,0x3C,0x7F,0xB8,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xF0,0xFF,0x9E,0x3C,0x38,0x7C,0x38,0x7E,0x78,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xE1,0xFF,0x3C,0x7C,0x78,0x7C,0x78,0x3C,0xF1,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xE1,0xF8,0x38,0x78,0x78,0x10,0x18,0x01,0xF1,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0x00,0x00,0x60,0x20,0x3C,0x00,0x7C,0x07,0x80,0x7F,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x1F,0xFE,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+
+};
+
+#define STATUS_SCREENWIDTH 		125	//Width in pixels
+#define STATUS_SCREENHEIGHT 	19	//Height in pixels
+#define STATUS_SCREENBYTEWIDTH 	16	//Width in bytes
+const unsigned char status_screen0_bmp[] PROGMEM = { //AVR-GCC, WinAVR
+//chuangxiang
+/*
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x70,
+0x00,0x80,0x81,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x87,0x30,
+0x00,0xC0,0x81,0x1F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x87,0x90,
+0x01,0x20,0x81,0x10,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x87,0xD0,
+0x02,0x14,0x8F,0xDF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x87,0xD0,
+0x04,0x04,0x81,0x10,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x03,0xD0,
+0x0B,0xE4,0x83,0x9F,0x80,0x1F,0xE0,0x00,0x00,0x08,0x20,0x80,0x00,0x20,0x30,0x10,
+0x02,0x24,0x85,0x50,0x80,0x3F,0xF0,0x00,0x00,0x04,0x10,0x40,0x00,0x20,0x78,0x10,
+0x02,0x24,0x89,0x1F,0x80,0x3F,0xF0,0x00,0x00,0x04,0x10,0x40,0x00,0x20,0x78,0x10,
+0x02,0x24,0x81,0x10,0x00,0x3F,0xF0,0x00,0x00,0x08,0x20,0x80,0x00,0x20,0x30,0x10,
+0x02,0xC4,0x80,0xA1,0x00,0x1F,0xE0,0x00,0x00,0x10,0x41,0x00,0x00,0x2F,0x03,0xD0,
+0x02,0x00,0x82,0x90,0x80,0x1F,0xE0,0x00,0x00,0x20,0x82,0x00,0x00,0x2F,0x87,0xD0,
+0x02,0x10,0x82,0x8A,0x40,0x3F,0xF0,0x00,0x00,0x20,0x82,0x00,0x00,0x2F,0x87,0xD0,
+0x02,0x12,0x84,0x82,0x00,0x3F,0xF0,0x00,0x00,0x10,0x41,0x00,0x00,0x27,0x87,0x90,
+0x01,0xF1,0x00,0x7E,0x00,0x3F,0xF0,0x00,0x00,0x08,0x20,0x80,0x00,0x33,0x87,0x30,
+0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x70,
+0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,
+*/
+
+// 3D
+/*
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x70,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x87,0x30,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x87,0x90,
+0x00,0x3E,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x87,0xD0,
+0x00,0xC1,0x86,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x87,0xD0,
+0x00,0xC1,0x86,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x03,0xD0,
+0x00,0x01,0x86,0x04,0x00,0x1F,0xE0,0x00,0x00,0x08,0x20,0x80,0x00,0x20,0x30,0x10,
+0x00,0x03,0x06,0x04,0x00,0x3F,0xF0,0x00,0x00,0x04,0x10,0x40,0x00,0x20,0x78,0x10,
+0x00,0x1F,0x06,0x04,0x00,0x3F,0xF0,0x00,0x00,0x04,0x10,0x40,0x00,0x20,0x78,0x10,
+0x00,0x03,0x06,0x04,0x00,0x3F,0xF0,0x00,0x00,0x08,0x20,0x80,0x00,0x20,0x30,0x10,
+0x00,0x01,0x86,0x04,0x00,0x1F,0xE0,0x00,0x00,0x10,0x41,0x00,0x00,0x2F,0x03,0xD0,
+0x00,0xC1,0x86,0x0C,0x00,0x1F,0xE0,0x00,0x00,0x20,0x82,0x00,0x00,0x2F,0x87,0xD0,
+0x00,0xC1,0x86,0x18,0x00,0x3F,0xF0,0x00,0x00,0x20,0x82,0x00,0x00,0x2F,0x87,0xD0,
+0x00,0x3E,0x0F,0xF0,0x00,0x3F,0xF0,0x00,0x00,0x10,0x41,0x00,0x00,0x27,0x87,0x90,
+0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x00,0x00,0x08,0x20,0x80,0x00,0x33,0x87,0x30,
+0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x70,
+0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,
+*/
+
+// ENDER-3
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x70,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x87,0x30,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x87,0x90,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x87,0xD0,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x87,0xD0,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x03,0xD0,
+0xF8,0x01,0x80,0x00,0x0C,0x1F,0xE0,0x00,0x00,0x08,0x20,0x80,0x00,0x20,0x30,0x10,
+0x48,0x00,0x80,0x00,0x12,0x3F,0xF0,0x00,0x00,0x04,0x10,0x40,0x00,0x20,0x78,0x10,
+0x43,0xC3,0x8C,0xD0,0x02,0x3F,0xF0,0x00,0x00,0x04,0x10,0x40,0x00,0x20,0x78,0x10,
+0x71,0x24,0x92,0x67,0xCC,0x3F,0xF0,0x00,0x00,0x08,0x20,0x80,0x00,0x20,0x30,0x10,
+0x41,0x24,0x9E,0x40,0x02,0x1F,0xE0,0x00,0x00,0x10,0x41,0x00,0x00,0x2F,0x03,0xD0,
+0x49,0x24,0x90,0x40,0x12,0x1F,0xE0,0x00,0x00,0x20,0x82,0x00,0x00,0x2F,0x87,0xD0,
+0xFB,0xB3,0xCE,0xE0,0x0C,0x3F,0xF0,0x00,0x00,0x20,0x82,0x00,0x00,0x2F,0x87,0xD0,
+0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x00,0x00,0x10,0x41,0x00,0x00,0x27,0x87,0x90,
+0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x00,0x00,0x08,0x20,0x80,0x00,0x33,0x87,0x30,
+0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x70,
+0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,
+
+};
+
+#define STATUS_SCREENWIDTH 		125	//Width in pixels
+#define STATUS_SCREENHEIGHT 	19	//Height in pixels
+#define STATUS_SCREENBYTEWIDTH 	16	//Width in bytes
+const unsigned char status_screen1_bmp[] PROGMEM = { //AVR-GCC, WinAVR
+//chuangxiang
+/*
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF0, 
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x70,
+0x00,0x80,0x81,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xFC,0x30,
+0x00,0xC0,0x81,0x1F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xFC,0x10,
+0x01,0x20,0x81,0x10,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x78,0x10,
+0x02,0x14,0x8F,0xDF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x30,0x10,
+0x04,0x04,0x81,0x10,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2C,0x00,0xD0,
+0x0B,0xE4,0x83,0x9F,0x80,0x1F,0xE0,0x00,0x00,0x10,0x41,0x00,0x00,0x2E,0x31,0xD0,
+0x02,0x24,0x85,0x50,0x80,0x3F,0xF0,0x00,0x00,0x08,0x20,0x80,0x00,0x2F,0x7B,0xD0,
+0x02,0x24,0x89,0x1F,0x80,0x3F,0xF0,0x00,0x00,0x08,0x20,0x80,0x00,0x2F,0x7B,0xD0,
+0x02,0x24,0x81,0x10,0x00,0x3F,0xF0,0x00,0x00,0x10,0x41,0x00,0x00,0x2E,0x31,0xD0,
+0x02,0xC4,0x80,0xA1,0x00,0x1F,0xE0,0x00,0x00,0x20,0x82,0x00,0x00,0x2C,0x00,0xD0,
+0x02,0x00,0x82,0x90,0x80,0x1F,0xE0,0x00,0x00,0x41,0x04,0x00,0x00,0x20,0x30,0x10,
+0x02,0x10,0x82,0x8A,0x40,0x3F,0xF0,0x00,0x00,0x41,0x04,0x00,0x00,0x20,0x78,0x10,
+0x02,0x12,0x84,0x82,0x00,0x3F,0xF0,0x00,0x00,0x20,0x82,0x00,0x00,0x20,0xFC,0x10,
+0x01,0xF1,0x00,0x7E,0x00,0x3F,0xF0,0x00,0x00,0x10,0x41,0x00,0x00,0x30,0xFC,0x30,
+0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x70,
+0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,
+*/
+
+// 3D
+/*
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x70,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xFC,0x30,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xFC,0x10,
+0x00,0x3E,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x78,0x10,
+0x00,0xC1,0x86,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x30,0x10,
+0x00,0xC1,0x86,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2C,0x00,0xD0,
+0x00,0x01,0x86,0x04,0x00,0x1F,0xE0,0x00,0x00,0x10,0x41,0x00,0x00,0x2E,0x31,0xD0,
+0x00,0x03,0x06,0x04,0x00,0x3F,0xF0,0x00,0x00,0x08,0x20,0x80,0x00,0x2F,0x7B,0xD0,
+0x00,0x1F,0x06,0x04,0x00,0x3F,0xF0,0x00,0x00,0x08,0x20,0x80,0x00,0x2F,0x7B,0xD0,
+0x00,0x03,0x06,0x04,0x00,0x3F,0xF0,0x00,0x00,0x10,0x41,0x00,0x00,0x2E,0x31,0xD0,
+0x00,0x01,0x86,0x04,0x00,0x1F,0xE0,0x00,0x00,0x20,0x82,0x00,0x00,0x2C,0x00,0xD0,
+0x00,0xC1,0x86,0x0C,0x00,0x1F,0xE0,0x00,0x00,0x41,0x04,0x00,0x00,0x20,0x30,0x10,
+0x00,0xC1,0x86,0x18,0x00,0x3F,0xF0,0x00,0x00,0x41,0x04,0x00,0x00,0x20,0x78,0x10,
+0x00,0x3E,0x0F,0xF0,0x00,0x3F,0xF0,0x00,0x00,0x20,0x82,0x00,0x00,0x20,0xFC,0x10,
+0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x00,0x00,0x10,0x41,0x00,0x00,0x30,0xFC,0x30,
+0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x70,
+0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,
+*/
+
+// ENDER-3
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x70,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xFC,0x30,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xFC,0x10,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x78,0x10,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x30,0x10,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2C,0x00,0xD0,
+0xF8,0x01,0x80,0x00,0x0C,0x1F,0xE0,0x00,0x00,0x10,0x41,0x00,0x00,0x2E,0x31,0xD0,
+0x48,0x00,0x80,0x00,0x12,0x3F,0xF0,0x00,0x00,0x08,0x20,0x80,0x00,0x2F,0x7B,0xD0,
+0x43,0xC3,0x8C,0xD0,0x02,0x3F,0xF0,0x00,0x00,0x08,0x20,0x80,0x00,0x2F,0x7B,0xD0,
+0x71,0x24,0x92,0x67,0xCC,0x3F,0xF0,0x00,0x00,0x10,0x41,0x00,0x00,0x2E,0x31,0xD0,
+0x41,0x24,0x9E,0x40,0x02,0x1F,0xE0,0x00,0x00,0x20,0x82,0x00,0x00,0x2C,0x00,0xD0,
+0x49,0x24,0x90,0x40,0x12,0x1F,0xE0,0x00,0x00,0x41,0x04,0x00,0x00,0x20,0x30,0x10,
+0xFB,0xB3,0xCE,0xE0,0x0C,0x3F,0xF0,0x00,0x00,0x41,0x04,0x00,0x00,0x20,0x78,0x10,
+0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x00,0x00,0x20,0x82,0x00,0x00,0x20,0xFC,0x10,
+0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x00,0x00,0x10,0x41,0x00,0x00,0x30,0xFC,0x30,
+0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x70,
+0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,
+
+};
+
+

BIN
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/LCD Menu Tree CN.pdf


BIN
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/LCD Menu Tree.pdf


+ 389 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/LiquidCrystalRus.cpp

@@ -0,0 +1,389 @@
+#include "LiquidCrystalRus.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <avr/pgmspace.h>
+
+#if defined(ARDUINO) && ARDUINO >= 100
+  #include "Arduino.h"
+#else
+  #include "WProgram.h"
+#endif
+
+// it is a russian alphabet translation
+// except 0401 --> 0xa2 = ╗, 0451 --> 0xb5
+const PROGMEM uint8_t utf_recode[] = 
+       { 0x41,0xa0,0x42,0xa1,0xe0,0x45,0xa3,0xa4,0xa5,0xa6,0x4b,0xa7,0x4d,0x48,0x4f,
+         0xa8,0x50,0x43,0x54,0xa9,0xaa,0x58,0xe1,0xab,0xac,0xe2,0xad,0xae,0x62,0xaf,0xb0,0xb1,
+         0x61,0xb2,0xb3,0xb4,0xe3,0x65,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0x6f,
+         0xbe,0x70,0x63,0xbf,0x79,0xe4,0x78,0xe5,0xc0,0xc1,0xe6,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7
+        };     
+
+// When the display powers up, it is configured as follows:
+//
+// 1. Display clear
+// 2. Function set: 
+//    DL = 1; 8-bit interface data 
+//    N = 0; 1-line display 
+//    F = 0; 5x8 dot character font 
+// 3. Display on/off control: 
+//    D = 0; Display off 
+//    C = 0; Cursor off 
+//    B = 0; Blinking off 
+// 4. Entry mode set: 
+//    I/D = 1; Increment by 1 
+//    S = 0; No shift 
+//
+// Note, however, that resetting the Arduino doesn't reset the LCD, so we
+// can't assume that it's in that state when a sketch starts (and the
+// LiquidCrystal constructor is called).
+// 
+// modified 27 Jul 2011
+// by Ilya V. Danilov http://mk90.ru/
+
+
+LiquidCrystalRus::LiquidCrystalRus(uint8_t rs, uint8_t rw, uint8_t enable,
+			     uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
+			     uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
+{
+  init(0, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7);
+}
+
+LiquidCrystalRus::LiquidCrystalRus(uint8_t rs, uint8_t enable,
+			     uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
+			     uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
+{
+  init(0, rs, 255, enable, d0, d1, d2, d3, d4, d5, d6, d7);
+}
+
+LiquidCrystalRus::LiquidCrystalRus(uint8_t rs, uint8_t rw, uint8_t enable,
+			     uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3)
+{
+  init(1, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0);
+}
+
+LiquidCrystalRus::LiquidCrystalRus(uint8_t rs,  uint8_t enable,
+			     uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3)
+{
+  init(1, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0);
+}
+
+void LiquidCrystalRus::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
+			 uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
+			 uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
+{
+  _rs_pin = rs;
+  _rw_pin = rw;
+  _enable_pin = enable;
+  
+  _data_pins[0] = d0;
+  _data_pins[1] = d1;
+  _data_pins[2] = d2;
+  _data_pins[3] = d3; 
+  _data_pins[4] = d4;
+  _data_pins[5] = d5;
+  _data_pins[6] = d6;
+  _data_pins[7] = d7; 
+
+  pinMode(_rs_pin, OUTPUT);
+  // we can save 1 pin by not using RW. Indicate by passing 255 instead of pin#
+  if (_rw_pin != 255) { 
+    pinMode(_rw_pin, OUTPUT);
+  }
+  pinMode(_enable_pin, OUTPUT);
+  
+  if (fourbitmode)
+    _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
+  else 
+    _displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS;
+  
+  begin(16, 1);  
+}
+
+void LiquidCrystalRus::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
+  if (lines > 1) {
+    _displayfunction |= LCD_2LINE;
+  }
+  _numlines = lines;
+  _currline = 0;
+
+  // for some 1 line displays you can select a 10 pixel high font
+  if ((dotsize != 0) && (lines == 1)) {
+    _displayfunction |= LCD_5x10DOTS;
+  }
+
+  // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
+  // according to datasheet, we need at least 40ms after power rises above 2.7V
+  // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
+  delayMicroseconds(50000); 
+  // Now we pull both RS and R/W low to begin commands
+  digitalWrite(_rs_pin, LOW);
+  digitalWrite(_enable_pin, LOW);
+  if (_rw_pin != 255) { 
+    digitalWrite(_rw_pin, LOW);
+  }
+  
+  //put the LCD into 4 bit or 8 bit mode
+  if (! (_displayfunction & LCD_8BITMODE)) {
+    // this is according to the hitachi HD44780 datasheet
+    // figure 24, pg 46
+
+    // we start in 8bit mode, try to set 4 bit mode
+    writeNbits(0x03,4);
+    delayMicroseconds(4500); // wait min 4.1ms
+
+    // second try
+    writeNbits(0x03,4);
+    delayMicroseconds(4500); // wait min 4.1ms
+    
+    // third go!
+    writeNbits(0x03,4); 
+    delayMicroseconds(150);
+
+    // finally, set to 8-bit interface
+    writeNbits(0x02,4); 
+  } else {
+    // this is according to the hitachi HD44780 datasheet
+    // page 45 figure 23
+
+    // Send function set command sequence
+    command(LCD_FUNCTIONSET | _displayfunction);
+    delayMicroseconds(4500);  // wait more than 4.1ms
+
+    // second try
+    command(LCD_FUNCTIONSET | _displayfunction);
+    delayMicroseconds(150);
+
+    // third go
+    command(LCD_FUNCTIONSET | _displayfunction);
+  }
+
+  // finally, set # lines, font size, etc.
+  command(LCD_FUNCTIONSET | _displayfunction);  
+
+  // turn the display on with no cursor or blinking default
+  _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;  
+  display();
+
+  // clear it off
+  clear();
+
+  // Initialize to default text direction (for romance languages)
+  _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
+  // set the entry mode
+  command(LCD_ENTRYMODESET | _displaymode);
+
+}
+
+void LiquidCrystalRus::setDRAMModel(uint8_t model) {
+  _dram_model = model;
+}
+
+/********** high level commands, for the user! */
+void LiquidCrystalRus::clear()
+{
+  command(LCD_CLEARDISPLAY);  // clear display, set cursor position to zero
+  delayMicroseconds(2000);  // this command takes a long time!
+}
+
+void LiquidCrystalRus::home()
+{
+  command(LCD_RETURNHOME);  // set cursor position to zero
+  delayMicroseconds(2000);  // this command takes a long time!
+}
+
+void LiquidCrystalRus::setCursor(uint8_t col, uint8_t row)
+{
+  int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
+  if ( row >= _numlines ) {
+    row = _numlines-1;    // we count rows starting w/0
+  }
+  
+  command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
+}
+
+// Turn the display on/off (quickly)
+void LiquidCrystalRus::noDisplay() {
+  _displaycontrol &= ~LCD_DISPLAYON;
+  command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+void LiquidCrystalRus::display() {
+  _displaycontrol |= LCD_DISPLAYON;
+  command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+// Turns the underline cursor on/off
+void LiquidCrystalRus::noCursor() {
+  _displaycontrol &= ~LCD_CURSORON;
+  command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+void LiquidCrystalRus::cursor() {
+  _displaycontrol |= LCD_CURSORON;
+  command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+// Turn on and off the blinking cursor
+void LiquidCrystalRus::noBlink() {
+  _displaycontrol &= ~LCD_BLINKON;
+  command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+void LiquidCrystalRus::blink() {
+  _displaycontrol |= LCD_BLINKON;
+  command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+// These commands scroll the display without changing the RAM
+void LiquidCrystalRus::scrollDisplayLeft(void) {
+  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
+}
+void LiquidCrystalRus::scrollDisplayRight(void) {
+  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
+}
+
+// This is for text that flows Left to Right
+void LiquidCrystalRus::leftToRight(void) {
+  _displaymode |= LCD_ENTRYLEFT;
+  command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// This is for text that flows Right to Left
+void LiquidCrystalRus::rightToLeft(void) {
+  _displaymode &= ~LCD_ENTRYLEFT;
+  command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// This will 'right justify' text from the cursor
+void LiquidCrystalRus::autoscroll(void) {
+  _displaymode |= LCD_ENTRYSHIFTINCREMENT;
+  command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// This will 'left justify' text from the cursor
+void LiquidCrystalRus::noAutoscroll(void) {
+  _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
+  command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// Allows us to fill the first 8 CGRAM locations
+// with custom characters
+void LiquidCrystalRus::createChar(uint8_t location, uint8_t charmap[]) {
+  location &= 0x7; // we only have 8 locations 0-7
+  command(LCD_SETCGRAMADDR | (location << 3));
+  for (int i=0; i<8; i++) {
+    write(charmap[i]);
+  }
+}
+
+/*********** mid level commands, for sending data/cmds */
+
+inline void LiquidCrystalRus::command(uint8_t value) {
+  send(value, LOW);
+}
+
+#if defined(ARDUINO) && ARDUINO >= 100
+  size_t LiquidCrystalRus::write(uint8_t value)
+#else
+  void   LiquidCrystalRus::write(uint8_t value)
+#endif
+{
+  uint8_t out_char=value;
+
+  if (_dram_model == LCD_DRAM_WH1601) {  
+    uint8_t ac=recv(LOW) & 0x7f;
+    if (ac>7 && ac<0x14) command(LCD_SETDDRAMADDR | (0x40+ac-8));
+  }
+
+  if (value>=0x80) { // UTF-8 handling
+    if (value >= 0xc0) {
+      utf_hi_char = value - 0xd0;
+    } else {
+      value &= 0x3f;
+      if (!utf_hi_char && (value == 1)) 
+        send(0xa2,HIGH); // ╗
+      else if ((utf_hi_char == 1) && (value == 0x11)) 
+        send(0xb5,HIGH); // ╦
+      else 
+        send(pgm_read_byte_near(utf_recode + value + (utf_hi_char<<6) - 0x10), HIGH);
+    }    
+  } else send(out_char, HIGH);
+#if defined(ARDUINO) && ARDUINO >= 100
+  return 1; // assume sucess 
+#endif
+}
+
+/************ low level data pushing commands **********/
+
+// write either command or data, with automatic 4/8-bit selection
+void LiquidCrystalRus::send(uint8_t value, uint8_t mode) {
+  digitalWrite(_rs_pin, mode);
+
+  // if there is a RW pin indicated, set it low to Write
+  if (_rw_pin != 255) { 
+    digitalWrite(_rw_pin, LOW);
+  }
+  
+  if (_displayfunction & LCD_8BITMODE) {
+    writeNbits(value,8); 
+  } else {
+    writeNbits(value>>4,4);
+    writeNbits(value,4);
+  }
+}
+
+// read  data, with automatic 4/8-bit selection
+uint8_t LiquidCrystalRus::recv(uint8_t mode) {
+  uint8_t retval;
+  digitalWrite(_rs_pin, mode);
+
+  // if there is a RW pin indicated, set it low to Write
+  if (_rw_pin != 255) { 
+    digitalWrite(_rw_pin, HIGH);
+  }
+  
+  if (_displayfunction & LCD_8BITMODE) {
+    retval = readNbits(8); 
+  } else {
+    retval = readNbits(4) << 4;
+    retval |= readNbits(4);
+  }
+  return retval;
+}
+void LiquidCrystalRus::pulseEnable() {
+  digitalWrite(_enable_pin, LOW);
+  delayMicroseconds(1);    
+  digitalWrite(_enable_pin, HIGH);
+  delayMicroseconds(1);    // enable pulse must be >450ns
+  digitalWrite(_enable_pin, LOW);
+  delayMicroseconds(100);   // commands need > 37us to settle
+}
+
+void LiquidCrystalRus::writeNbits(uint8_t value, uint8_t n) {
+  for (int i = 0; i < n; i++) {
+    pinMode(_data_pins[i], OUTPUT);
+    digitalWrite(_data_pins[i], (value >> i) & 0x01);
+  }
+
+  pulseEnable();
+}
+
+uint8_t LiquidCrystalRus::readNbits(uint8_t n) {
+  uint8_t retval=0;
+  for (int i = 0; i < n; i++) {
+    pinMode(_data_pins[i], INPUT);
+  }
+
+  digitalWrite(_enable_pin, LOW);
+  delayMicroseconds(1);    
+  digitalWrite(_enable_pin, HIGH);
+  delayMicroseconds(1);    // enable pulse must be >450ns
+  
+  for (int i = 0; i < n; i++) {
+    retval |= (digitalRead(_data_pins[i]) == HIGH)?(1 << i):0;
+  }
+
+  digitalWrite(_enable_pin, LOW);
+
+  return retval;
+}
+

+ 129 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/LiquidCrystalRus.h

@@ -0,0 +1,129 @@
+//
+// based on LiquidCrystal library from ArduinoIDE, see http://arduino.cc
+//  modified 27 Jul 2011
+// by Ilya V. Danilov http://mk90.ru/
+// 
+
+#ifndef LiquidCrystalRus_h
+#define LiquidCrystalRus_h
+
+#include <inttypes.h>
+#include "Print.h"
+
+// commands
+#define LCD_CLEARDISPLAY 0x01
+#define LCD_RETURNHOME 0x02
+#define LCD_ENTRYMODESET 0x04
+#define LCD_DISPLAYCONTROL 0x08
+#define LCD_CURSORSHIFT 0x10
+#define LCD_FUNCTIONSET 0x20
+#define LCD_SETCGRAMADDR 0x40
+#define LCD_SETDDRAMADDR 0x80
+
+// flags for display entry mode
+#define LCD_ENTRYRIGHT 0x00
+#define LCD_ENTRYLEFT 0x02
+#define LCD_ENTRYSHIFTINCREMENT 0x01
+#define LCD_ENTRYSHIFTDECREMENT 0x00
+
+// flags for display on/off control
+#define LCD_DISPLAYON 0x04
+#define LCD_DISPLAYOFF 0x00
+#define LCD_CURSORON 0x02
+#define LCD_CURSOROFF 0x00
+#define LCD_BLINKON 0x01
+#define LCD_BLINKOFF 0x00
+
+// flags for display/cursor shift
+#define LCD_DISPLAYMOVE 0x08
+#define LCD_CURSORMOVE 0x00
+#define LCD_MOVERIGHT 0x04
+#define LCD_MOVELEFT 0x00
+
+// flags for function set
+#define LCD_8BITMODE 0x10
+#define LCD_4BITMODE 0x00
+#define LCD_2LINE 0x08
+#define LCD_1LINE 0x00
+#define LCD_5x10DOTS 0x04
+#define LCD_5x8DOTS 0x00
+
+// enum for 
+#define LCD_DRAM_Normal 0x00
+#define LCD_DRAM_WH1601 0x01
+
+
+class LiquidCrystalRus : public Print {
+public:
+  LiquidCrystalRus(uint8_t rs, uint8_t enable,
+		uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
+		uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
+  LiquidCrystalRus(uint8_t rs, uint8_t rw, uint8_t enable,
+		uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
+		uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
+  LiquidCrystalRus(uint8_t rs, uint8_t rw, uint8_t enable,
+		uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);
+  LiquidCrystalRus(uint8_t rs, uint8_t enable,
+		uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);
+
+  void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
+	    uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
+	    uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
+    
+  void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
+
+  void clear();
+  void home();
+
+  void noDisplay();
+  void display();
+  void noBlink();
+  void blink();
+  void noCursor();
+  void cursor();
+  void scrollDisplayLeft();
+  void scrollDisplayRight();
+  void leftToRight();
+  void rightToLeft();
+  void autoscroll();
+  void noAutoscroll();
+
+  void createChar(uint8_t, uint8_t[]);
+  void setCursor(uint8_t, uint8_t);
+ 
+#if defined(ARDUINO) && ARDUINO >= 100
+  virtual size_t write(uint8_t);
+  using Print::write;
+#else
+  virtual void write(uint8_t);
+#endif
+
+  void command(uint8_t);
+
+  void setDRAMModel(uint8_t);
+
+private:
+  void send(uint8_t, uint8_t);
+  void writeNbits(uint8_t, uint8_t);
+  uint8_t recv(uint8_t);
+  uint8_t readNbits(uint8_t); 
+  void pulseEnable();
+
+  uint8_t _rs_pin; // LOW: command.  HIGH: character.
+  uint8_t _rw_pin; // LOW: write to LCD.  HIGH: read from LCD.
+  uint8_t _enable_pin; // activated by a HIGH pulse.
+  uint8_t _data_pins[8];
+
+  uint8_t _displayfunction;
+  uint8_t _displaycontrol;
+  uint8_t _displaymode;
+
+  uint8_t _initialized;
+
+  uint8_t _numlines,_currline;
+
+  uint8_t _dram_model;
+  uint8_t utf_hi_char; // UTF-8 high part
+};
+
+#endif

+ 484 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Makefile

@@ -0,0 +1,484 @@
+# Sprinter Arduino Project Makefile
+#
+# Makefile Based on:
+# Arduino 0011 Makefile
+# Arduino adaptation by mellis, eighthave, oli.keller
+# Marlin adaption by Daid
+#
+# This has been tested with Arduino 0022.
+#
+# This makefile allows you to build sketches from the command line
+# without the Arduino environment (or Java).
+#
+# Detailed instructions for using the makefile:
+#
+#  1. Modify the line containg "ARDUINO_INSTALL_DIR" to point to the directory that
+#     contains the Arduino installation (for example, under Mac OS X, this
+#     might be /Applications/Arduino.app/Contents/Resources/Java).
+#
+#  2. Modify the line containing "UPLOAD_PORT" to refer to the filename
+#     representing the USB or serial connection to your Arduino board
+#     (e.g. UPLOAD_PORT = /dev/tty.USB0).  If the exact name of this file
+#     changes, you can use * as a wildcard (e.g. UPLOAD_PORT = /dev/tty.usb*).
+#
+#  3. Set the line containing "MCU" to match your board's processor.
+#     Older one's are atmega8 based, newer ones like Arduino Mini, Bluetooth
+#     or Diecimila have the atmega168.  If you're using a LilyPad Arduino,
+#     change F_CPU to 8000000. If you are using Gen7 electronics, you
+#     probably need to use 20000000. Either way, you must regenerate
+#     the speed lookup table with create_speed_lookuptable.py.
+#
+#  4. Type "make" and press enter to compile/verify your program.
+#
+#  5. Type "make upload", reset your Arduino board, and press enter to
+#     upload your program to the Arduino board.
+#
+# Note that all settings are set with ?=, this means you can override them
+# from the commandline with "make HARDWARE_MOTHERBOARD=71" for example
+
+# This defined the board you are compiling for (see Configuration.h for the options)
+HARDWARE_MOTHERBOARD ?= 11
+
+# Arduino source install directory, and version number
+ARDUINO_INSTALL_DIR  ?= /Applications/Arduino.app/Contents/Resources/Java
+ARDUINO_VERSION      ?= 105
+
+# You can optionally set a path to the avr-gcc tools. Requires a trailing slash. (ex: /usr/local/avr-gcc/bin)
+AVR_TOOLS_PATH ?=
+
+#Programmer configuration
+UPLOAD_RATE        ?= 115200
+AVRDUDE_PROGRAMMER ?= arduino
+UPLOAD_PORT        ?= /dev/arduino
+
+#Directory used to build files in, contains all the build files, from object files to the final hex file.
+BUILD_DIR          ?= applet
+
+# This defines whether Liquid_TWI2 support will be built
+LIQUID_TWI2        ?= 0
+
+# this defines if Wire is needed
+WIRE               ?= 0
+
+############################################################################
+# Below here nothing should be changed...
+
+# Here the Arduino variant is selected by the board type
+# HARDWARE_VARIANT = "arduino", "Sanguino", "Gen7", ...
+# MCU = "atmega1280", "Mega2560", "atmega2560", "atmega644p", ...
+
+#Gen7
+ifeq ($(HARDWARE_MOTHERBOARD),10)
+HARDWARE_VARIANT ?= Gen7
+MCU              ?= atmega644
+F_CPU            ?= 20000000
+else ifeq  ($(HARDWARE_MOTHERBOARD),11)
+HARDWARE_VARIANT ?= Gen7
+MCU              ?= atmega644p
+F_CPU            ?= 20000000
+else ifeq  ($(HARDWARE_MOTHERBOARD),12)
+HARDWARE_VARIANT ?= Gen7
+MCU              ?= atmega644p
+F_CPU            ?= 20000000
+else ifeq  ($(HARDWARE_MOTHERBOARD),13)
+HARDWARE_VARIANT ?= Gen7
+MCU              ?= atmega1284p
+F_CPU            ?= 20000000
+
+#RAMPS
+else ifeq  ($(HARDWARE_MOTHERBOARD),3)
+HARDWARE_VARIANT ?= arduino
+MCU              ?= atmega2560
+else ifeq  ($(HARDWARE_MOTHERBOARD),33)
+HARDWARE_VARIANT ?= arduino
+MCU              ?= atmega2560
+else ifeq  ($(HARDWARE_MOTHERBOARD),34)
+HARDWARE_VARIANT ?= arduino
+MCU              ?= atmega2560
+
+#Duemilanove w/ ATMega328P pin assignment
+else ifeq  ($(HARDWARE_MOTHERBOARD),4)
+HARDWARE_VARIANT ?= arduino
+HARDWARE_SUB_VARIANT ?= standard
+MCU              ?= atmega328p
+
+#Gen6
+else ifeq  ($(HARDWARE_MOTHERBOARD),5)
+HARDWARE_VARIANT ?= Gen6
+MCU              ?= atmega644p
+else ifeq  ($(HARDWARE_MOTHERBOARD),51)
+HARDWARE_VARIANT ?= Gen6
+MCU              ?= atmega644p
+
+#Sanguinololu
+else ifeq  ($(HARDWARE_MOTHERBOARD),6)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega644p
+else ifeq  ($(HARDWARE_MOTHERBOARD),62)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega644p
+else ifeq  ($(HARDWARE_MOTHERBOARD),63)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega644p
+else ifeq  ($(HARDWARE_MOTHERBOARD),65)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega1284p
+else ifeq  ($(HARDWARE_MOTHERBOARD),66)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega1284p
+
+#Ultimaker
+else ifeq  ($(HARDWARE_MOTHERBOARD),7)
+HARDWARE_VARIANT ?= arduino
+MCU              ?= atmega2560
+else ifeq  ($(HARDWARE_MOTHERBOARD),71)
+HARDWARE_VARIANT ?= arduino
+MCU              ?= atmega1280
+
+#Teensylu
+else ifeq  ($(HARDWARE_MOTHERBOARD),8)
+HARDWARE_VARIANT ?= Teensy
+MCU              ?= at90usb1286
+else ifeq  ($(HARDWARE_MOTHERBOARD),81)
+HARDWARE_VARIANT ?= Teensy
+MCU              ?= at90usb1286
+else ifeq  ($(HARDWARE_MOTHERBOARD),82)
+HARDWARE_VARIANT ?= Teensy
+MCU              ?= at90usb646
+else ifeq  ($(HARDWARE_MOTHERBOARD),83)
+HARDWARE_VARIANT ?= Teensy
+MCU              ?= at90usb1286
+else ifeq  ($(HARDWARE_MOTHERBOARD),84)
+HARDWARE_VARIANT ?= Teensy
+MCU              ?= at90usb1286
+
+#Gen3+
+else ifeq  ($(HARDWARE_MOTHERBOARD),9)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega644p
+
+#Megatronics
+else ifeq  ($(HARDWARE_MOTHERBOARD),70)
+HARDWARE_VARIANT ?= arduino
+MCU              ?= atmega2560
+
+#Alpha OMCA board
+else ifeq  ($(HARDWARE_MOTHERBOARD),90)
+HARDWARE_VARIANT ?= SanguinoA
+MCU              ?= atmega644
+
+#Final OMCA board
+else ifeq  ($(HARDWARE_MOTHERBOARD),91)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega644p
+
+#Rambo
+else ifeq  ($(HARDWARE_MOTHERBOARD),301)
+HARDWARE_VARIANT ?= arduino
+MCU              ?= atmega2560
+
+# Azteeg
+else ifeq  ($(HARDWARE_MOTHERBOARD),67)
+HARDWARE_VARIANT ?= arduino
+MCU              ?= atmega2560
+else ifeq  ($(HARDWARE_MOTHERBOARD),68)
+HARDWARE_VARIANT ?= arduino
+MCU              ?= atmega2560
+
+endif
+
+# Be sure to regenerate speed_lookuptable.h with create_speed_lookuptable.py
+# if you are setting this to something other than 16MHz
+# Set to 16Mhz if not yet set.
+F_CPU ?= 16000000
+
+# Arduino containd the main source code for the Arduino
+# Libraries, the "hardware variant" are for boards
+# that derives from that, and their source are present in
+# the main Marlin source directory
+ifeq ($(HARDWARE_VARIANT), arduino)
+HARDWARE_DIR = $(ARDUINO_INSTALL_DIR)/hardware
+else
+ifeq ($(shell [ $(ARDUINO_VERSION) -ge 100 ] && echo true), true)
+HARDWARE_DIR = ../ArduinoAddons/Arduino_1.x.x
+else
+HARDWARE_DIR = ../ArduinoAddons/Arduino_0.xx
+endif
+endif
+HARDWARE_SRC = $(HARDWARE_DIR)/$(HARDWARE_VARIANT)/cores/arduino
+
+TARGET = $(notdir $(CURDIR))
+
+# VPATH tells make to look into these directory for source files,
+# there is no need to specify explicit pathnames as long as the
+# directory is added here
+
+VPATH = .
+VPATH += $(BUILD_DIR)
+VPATH += $(HARDWARE_SRC)
+ifeq ($(HARDWARE_VARIANT), arduino)
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/LiquidCrystal
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/SPI
+ifeq ($(LIQUID_TWI2), 1)
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire/utility
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/LiquidTWI2
+endif
+ifeq ($(WIRE), 1)
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire/utility
+endif
+else
+VPATH += $(HARDWARE_DIR)/libraries/LiquidCrystal
+VPATH += $(HARDWARE_DIR)/libraries/SPI
+ifeq ($(LIQUID_TWI2), 1)
+VPATH += $(HARDWARE_DIR)/libraries/Wire
+VPATH += $(HARDWARE_DIR)/libraries/Wire/utility
+VPATH += $(HARDWARE_DIR)/libraries/LiquidTWI2
+endif
+ifeq ($(WIRE, 1)
+VPATH += $(HARDWARE_DIR)/libraries/Wire
+VPATH += $(HARDWARE_DIR)/libraries/Wire/utility
+endif
+endif
+ifeq ($(HARDWARE_VARIANT), arduino)
+HARDWARE_SUB_VARIANT ?= mega
+VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/variants/$(HARDWARE_SUB_VARIANT)
+else
+HARDWARE_SUB_VARIANT ?= standard
+VPATH += $(HARDWARE_DIR)/$(HARDWARE_VARIANT)/variants/$(HARDWARE_SUB_VARIANT)
+endif
+SRC = wiring.c \
+	wiring_analog.c wiring_digital.c \
+	wiring_pulse.c \
+	wiring_shift.c WInterrupts.c
+ifeq ($(HARDWARE_VARIANT), Teensy)
+SRC = wiring.c
+VPATH += $(ARDUINO_INSTALL_DIR)/hardware/teensy/cores/teensy
+endif
+CXXSRC = WMath.cpp WString.cpp Print.cpp Marlin_main.cpp	\
+	MarlinSerial.cpp Sd2Card.cpp SdBaseFile.cpp SdFatUtil.cpp	\
+	SdFile.cpp SdVolume.cpp motion_control.cpp planner.cpp		\
+	stepper.cpp temperature.cpp cardreader.cpp ConfigurationStore.cpp \
+	watchdog.cpp SPI.cpp Servo.cpp Tone.cpp ultralcd.cpp digipot_mcp4451.cpp
+ifeq ($(LIQUID_TWI2), 0)
+CXXSRC += LiquidCrystal.cpp
+else
+SRC += twi.c
+CXXSRC += Wire.cpp LiquidTWI2.cpp
+endif
+
+ifeq ($(WIRE), 1)
+SRC += twi.c
+CXXSRC += Wire.cpp
+endif
+
+#Check for Arduino 1.0.0 or higher and use the correct sourcefiles for that version
+ifeq ($(shell [ $(ARDUINO_VERSION) -ge 100 ] && echo true), true)
+CXXSRC += main.cpp
+else
+SRC += pins_arduino.c main.c
+endif
+
+FORMAT = ihex
+
+# Name of this Makefile (used for "make depend").
+MAKEFILE = Makefile
+
+# Debugging format.
+# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
+# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
+DEBUG = stabs
+
+OPT = s
+
+DEFINES ?=
+
+# Program settings
+CC = $(AVR_TOOLS_PATH)avr-gcc
+CXX = $(AVR_TOOLS_PATH)avr-g++
+OBJCOPY = $(AVR_TOOLS_PATH)avr-objcopy
+OBJDUMP = $(AVR_TOOLS_PATH)avr-objdump
+AR  = $(AVR_TOOLS_PATH)avr-ar
+SIZE = $(AVR_TOOLS_PATH)avr-size
+NM = $(AVR_TOOLS_PATH)avr-nm
+AVRDUDE = avrdude
+REMOVE = rm -f
+MV = mv -f
+
+# Place -D or -U options here
+CDEFS    = -DF_CPU=$(F_CPU) ${addprefix -D , $(DEFINES)}
+CXXDEFS  = $(CDEFS)
+
+ifeq ($(HARDWARE_VARIANT), Teensy)
+CDEFS  += -DUSB_SERIAL
+SRC    += usb.c pins_teensy.c
+CXXSRC += usb_api.cpp
+endif
+
+# Add all the source directories as include directories too
+CINCS = ${addprefix -I ,${VPATH}}
+CXXINCS = ${addprefix -I ,${VPATH}}
+
+# Compiler flag to set the C Standard level.
+# c89   - "ANSI" C
+# gnu89 - c89 plus GCC extensions
+# c99   - ISO C99 standard (not yet fully implemented)
+# gnu99 - c99 plus GCC extensions
+#CSTANDARD = -std=gnu99
+CDEBUG = -g$(DEBUG)
+CWARN = -Wall -Wstrict-prototypes
+CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct \
+	-fshort-enums -w -ffunction-sections -fdata-sections \
+	-DARDUINO=$(ARDUINO_VERSION)
+ifneq ($(HARDWARE_MOTHERBOARD),)
+CTUNING += -DMOTHERBOARD=${HARDWARE_MOTHERBOARD}
+endif
+#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
+CEXTRA = -fno-use-cxa-atexit
+
+CFLAGS := $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CEXTRA) $(CTUNING)
+CXXFLAGS :=         $(CDEFS) $(CINCS) -O$(OPT) -Wall    $(CEXTRA) $(CTUNING)
+#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
+LDFLAGS = -lm
+
+
+# Programming support using avrdude. Settings and variables.
+AVRDUDE_PORT = $(UPLOAD_PORT)
+AVRDUDE_WRITE_FLASH = -U flash:w:$(BUILD_DIR)/$(TARGET).hex:i
+ifeq ($(shell uname -s), Linux)
+AVRDUDE_CONF = $(ARDUINO_INSTALL_DIR)/hardware/tools/avrdude.conf
+else
+AVRDUDE_CONF = $(ARDUINO_INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf
+endif
+AVRDUDE_FLAGS = -D -C $(AVRDUDE_CONF) \
+	-p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
+	-b $(UPLOAD_RATE)
+
+# Define all object files.
+OBJ = ${patsubst %.c, $(BUILD_DIR)/%.o, ${SRC}}
+OBJ += ${patsubst %.cpp, $(BUILD_DIR)/%.o, ${CXXSRC}}
+OBJ += ${patsubst %.S, $(BUILD_DIR)/%.o, ${ASRC}}
+
+# Define all listing files.
+LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)
+
+# Combine all necessary flags and optional flags.
+# Add target processor to flags.
+ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
+ALL_CXXFLAGS = -mmcu=$(MCU) $(CXXFLAGS)
+ALL_ASFLAGS = -mmcu=$(MCU) -x assembler-with-cpp $(ASFLAGS)
+
+# set V=1 (eg, "make V=1") to print the full commands etc.
+ifneq ($V,1)
+ Pecho=@echo
+ P=@
+else
+ Pecho=@:
+ P=
+endif
+
+# Default target.
+all: sizeafter
+
+build: $(BUILD_DIR) elf hex
+
+# Creates the object directory
+$(BUILD_DIR):
+	$P mkdir -p $(BUILD_DIR)
+
+elf: $(BUILD_DIR)/$(TARGET).elf
+hex: $(BUILD_DIR)/$(TARGET).hex
+eep: $(BUILD_DIR)/$(TARGET).eep
+lss: $(BUILD_DIR)/$(TARGET).lss
+sym: $(BUILD_DIR)/$(TARGET).sym
+
+# Program the device.
+# Do not try to reset an arduino if it's not one
+upload: $(BUILD_DIR)/$(TARGET).hex
+ifeq (${AVRDUDE_PROGRAMMER}, arduino)
+	stty hup < $(UPLOAD_PORT); true
+endif
+	$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)
+ifeq (${AVRDUDE_PROGRAMMER}, arduino)
+	stty -hup < $(UPLOAD_PORT); true
+endif
+
+	# Display size of file.
+HEXSIZE = $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex
+ELFSIZE = $(SIZE) --mcu=$(MCU) -C $(BUILD_DIR)/$(TARGET).elf; \
+          $(SIZE)  $(BUILD_DIR)/$(TARGET).elf
+sizebefore:
+	$P if [ -f $(BUILD_DIR)/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi
+
+sizeafter: build
+	$P if [ -f $(BUILD_DIR)/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
+
+
+# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
+COFFCONVERT=$(OBJCOPY) --debugging \
+	--change-section-address .data-0x800000 \
+	--change-section-address .bss-0x800000 \
+	--change-section-address .noinit-0x800000 \
+	--change-section-address .eeprom-0x810000
+
+
+coff: $(BUILD_DIR)/$(TARGET).elf
+	$(COFFCONVERT) -O coff-avr $(BUILD_DIR)/$(TARGET).elf $(TARGET).cof
+
+
+extcoff: $(TARGET).elf
+	$(COFFCONVERT) -O coff-ext-avr $(BUILD_DIR)/$(TARGET).elf $(TARGET).cof
+
+
+.SUFFIXES: .elf .hex .eep .lss .sym
+.PRECIOUS: .o
+
+.elf.hex:
+	$(Pecho) "  COPY  $@"
+	$P $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
+
+.elf.eep:
+	-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+		--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
+
+# Create extended listing file from ELF output file.
+.elf.lss:
+	$(OBJDUMP) -h -S $< > $@
+
+# Create a symbol table from ELF output file.
+.elf.sym:
+	$(NM) -n $< > $@
+
+	# Link: create ELF output file from library.
+$(BUILD_DIR)/$(TARGET).elf: $(OBJ) Configuration.h
+	$(Pecho) "  CXX   $@"
+	$P $(CC) $(ALL_CXXFLAGS) -Wl,--gc-sections -o $@ -L. $(OBJ) $(LDFLAGS)
+
+$(BUILD_DIR)/%.o: %.c Configuration.h Configuration_adv.h $(MAKEFILE)
+	$(Pecho) "  CC    $<"
+	$P $(CC) -MMD -c $(ALL_CFLAGS) $< -o $@
+
+$(BUILD_DIR)/%.o: $(BUILD_DIR)/%.cpp Configuration.h Configuration_adv.h $(MAKEFILE)
+	$(Pecho) "  CXX   $<"
+	$P $(CXX) -MMD -c $(ALL_CXXFLAGS) $< -o $@
+
+$(BUILD_DIR)/%.o: %.cpp Configuration.h Configuration_adv.h $(MAKEFILE)
+	$(Pecho) "  CXX   $<"
+	$P $(CXX) -MMD -c $(ALL_CXXFLAGS) $< -o $@
+
+
+# Target: clean project.
+clean:
+	$(Pecho) "  RM    $(BUILD_DIR)/*"
+	$P $(REMOVE) $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep $(BUILD_DIR)/$(TARGET).cof $(BUILD_DIR)/$(TARGET).elf \
+		$(BUILD_DIR)/$(TARGET).map $(BUILD_DIR)/$(TARGET).sym $(BUILD_DIR)/$(TARGET).lss $(BUILD_DIR)/$(TARGET).cpp \
+		$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d)
+	$(Pecho) "  RMDIR $(BUILD_DIR)/"
+	$P rm -rf $(BUILD_DIR)
+
+
+.PHONY:	all build elf hex eep lss sym program coff extcoff clean depend sizebefore sizeafter
+
+# Automaticaly include the dependency files created by gcc
+-include ${wildcard $(BUILD_DIR)/*.d}

+ 249 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Marlin.h

@@ -0,0 +1,249 @@
+// Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware.
+// Licence: GPL
+
+#ifndef MARLIN_H
+#define MARLIN_H
+
+#define  FORCE_INLINE __attribute__((always_inline)) inline
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <util/delay.h>
+#include <avr/pgmspace.h>
+#include <avr/eeprom.h>
+#include <avr/interrupt.h>
+
+
+#include "fastio.h"
+#include "Configuration.h"
+#include "pins.h"
+
+#ifndef AT90USB
+#define  HardwareSerial_h // trick to disable the standard HWserial
+#endif
+
+typedef unsigned long millis_t;
+
+#if (ARDUINO >= 100)
+# include "Arduino.h"
+#else
+# include "WProgram.h"
+  //Arduino < 1.0.0 does not define this, so we need to do it ourselfs
+# define analogInputToDigitalPin(p) ((p) + A0)
+#endif
+
+#ifdef AT90USB
+#include "HardwareSerial.h"
+#endif
+
+#include "MarlinSerial.h"
+
+#ifndef cbi
+#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
+#endif
+#ifndef sbi
+#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
+#endif
+
+#include "WString.h"
+
+#ifdef AT90USB
+   #ifdef BTENABLED
+         #define MYSERIAL bt
+   #else
+         #define MYSERIAL Serial
+   #endif // BTENABLED
+#else
+  #define MYSERIAL MSerial
+#endif
+
+#define SERIAL_PROTOCOL(x) (MYSERIAL.print(x))
+#define SERIAL_PROTOCOL_F(x,y) (MYSERIAL.print(x,y))
+#define SERIAL_PROTOCOLPGM(x) (serialprintPGM(PSTR(x)))
+#define SERIAL_PROTOCOLLN(x) (MYSERIAL.print(x),MYSERIAL.write('\n'))
+#define SERIAL_PROTOCOLLNPGM(x) (serialprintPGM(PSTR(x)),MYSERIAL.write('\n'))
+
+
+const char errormagic[] PROGMEM ="Error:";
+const char echomagic[] PROGMEM ="echo:";
+#define SERIAL_ERROR_START (serialprintPGM(errormagic))
+#define SERIAL_ERROR(x) SERIAL_PROTOCOL(x)
+#define SERIAL_ERRORPGM(x) SERIAL_PROTOCOLPGM(x)
+#define SERIAL_ERRORLN(x) SERIAL_PROTOCOLLN(x)
+#define SERIAL_ERRORLNPGM(x) SERIAL_PROTOCOLLNPGM(x)
+
+#define SERIAL_ECHO_START (serialprintPGM(echomagic))
+#define SERIAL_ECHO(x) SERIAL_PROTOCOL(x)
+#define SERIAL_ECHOPGM(x) SERIAL_PROTOCOLPGM(x)
+#define SERIAL_ECHOLN(x) SERIAL_PROTOCOLLN(x)
+#define SERIAL_ECHOLNPGM(x) SERIAL_PROTOCOLLNPGM(x)
+
+#define SERIAL_ECHOPAIR(name,value) (serial_echopair_P(PSTR(name),(value)))
+
+void serial_echopair_P(const char *s_P, float v);
+void serial_echopair_P(const char *s_P, double v);
+void serial_echopair_P(const char *s_P, unsigned long v);
+
+
+//things to write to serial from Programmemory. saves 400 to 2k of RAM.
+FORCE_INLINE void serialprintPGM(const char *str)
+{
+  char ch=pgm_read_byte(str);
+  while(ch)
+  {
+    MYSERIAL.write(ch);
+    ch=pgm_read_byte(++str);
+  }
+}
+
+
+void get_command();
+void process_commands();
+
+void manage_inactivity();
+
+#if defined(DUAL_X_CARRIAGE) && defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1 \
+    && defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1
+  #define  enable_x() do { WRITE(X_ENABLE_PIN, X_ENABLE_ON); WRITE(X2_ENABLE_PIN, X_ENABLE_ON); } while (0)
+  #define disable_x() do { WRITE(X_ENABLE_PIN,!X_ENABLE_ON); WRITE(X2_ENABLE_PIN,!X_ENABLE_ON); axis_known_position[X_AXIS] = false; } while (0)
+#elif defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1
+  #define  enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON)
+  #define disable_x() { WRITE(X_ENABLE_PIN,!X_ENABLE_ON); axis_known_position[X_AXIS] = false; }
+#else
+  #define enable_x() ;
+  #define disable_x() ;
+#endif
+
+#if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
+  #ifdef Y_DUAL_STEPPER_DRIVERS
+    #define  enable_y() { WRITE(Y_ENABLE_PIN, Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN,  Y_ENABLE_ON); }
+    #define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, !Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }
+  #else
+    #define  enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)
+    #define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }
+  #endif
+#else
+  #define enable_y() ;
+  #define disable_y() ;
+#endif
+
+#if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
+  #ifdef Z_DUAL_STEPPER_DRIVERS
+    #define  enable_z() { WRITE(Z_ENABLE_PIN, Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN, Z_ENABLE_ON); }
+    #define disable_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
+  #else
+    #define  enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
+    #define disable_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
+  #endif
+#else
+  #define enable_z() ;
+  #define disable_z() ;
+#endif
+
+#if defined(E0_ENABLE_PIN) && (E0_ENABLE_PIN > -1)
+  #define enable_e0() WRITE(E0_ENABLE_PIN, E_ENABLE_ON)
+  #define disable_e0() WRITE(E0_ENABLE_PIN,!E_ENABLE_ON)
+#else
+  #define enable_e0()  /* nothing */
+  #define disable_e0() /* nothing */
+#endif
+
+#if (EXTRUDERS > 1) && defined(E1_ENABLE_PIN) && (E1_ENABLE_PIN > -1)
+  #define enable_e1() WRITE(E1_ENABLE_PIN, E_ENABLE_ON)
+  #define disable_e1() WRITE(E1_ENABLE_PIN,!E_ENABLE_ON)
+#else
+  #define enable_e1()  /* nothing */
+  #define disable_e1() /* nothing */
+#endif
+
+#if (EXTRUDERS > 2) && defined(E2_ENABLE_PIN) && (E2_ENABLE_PIN > -1)
+  #define enable_e2() WRITE(E2_ENABLE_PIN, E_ENABLE_ON)
+  #define disable_e2() WRITE(E2_ENABLE_PIN,!E_ENABLE_ON)
+#else
+  #define enable_e2()  /* nothing */
+  #define disable_e2() /* nothing */
+#endif
+
+
+enum AxisEnum {X_AXIS=0, Y_AXIS=1, Z_AXIS=2, E_AXIS=3};
+
+
+void FlushSerialRequestResend();
+void ClearToSend();
+
+void get_coordinates();
+#ifdef DELTA
+void calculate_delta(float cartesian[3]);
+extern float delta[3];
+#endif
+void prepare_move();
+void kill();
+void Stop();
+
+bool IsStopped();
+
+bool enqueuecommand(const char* cmd);
+void enqueuecommands_P(const char* pgcode);
+void prepare_arc_move(char isclockwise);
+void clamp_to_software_endstops(float target[3]);
+
+#ifdef FAST_PWM_FAN
+void setPwmFrequency(uint8_t pin, int val);
+#endif
+
+#ifndef CRITICAL_SECTION_START
+  #define CRITICAL_SECTION_START  unsigned char _sreg = SREG; cli();
+  #define CRITICAL_SECTION_END    SREG = _sreg;
+#endif //CRITICAL_SECTION_START
+
+extern float homing_feedrate[];
+extern bool axis_relative_modes[];
+extern int feedmultiply;
+extern int extrudemultiply; // Sets extrude multiply factor (in percent)
+extern float volumetric_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner
+extern float current_position[NUM_AXIS] ;
+extern float add_homeing[3];
+#ifdef DELTA
+extern float endstop_adj[3];
+#endif
+extern float min_pos[3];
+extern float max_pos[3];
+extern bool axis_known_position[3];
+extern float zprobe_zoffset;
+extern int fanSpeed;
+#ifdef BARICUDA
+extern int ValvePressure;
+extern int EtoPPressure;
+#endif
+
+#ifdef FAN_SOFT_PWM
+extern unsigned char fanSpeedSoftPwm;
+#endif
+
+#ifdef FWRETRACT
+extern bool autoretract_enabled;
+extern bool retracted;
+extern float retract_length, retract_feedrate, retract_zlift;
+extern float retract_recover_length, retract_recover_feedrate;
+#endif
+
+extern unsigned long starttime;
+extern unsigned long stoptime;
+
+// Handling multiple extruders pins
+extern uint8_t active_extruder;
+
+#if defined(SDSUPPORT) && defined(POWEROFF_SAVE_SD_FILE)
+void init_power_off_info();
+#endif
+
+#ifdef DIGIPOT_I2C
+extern void digipot_i2c_set_current( int channel, float current );
+extern void digipot_i2c_init();
+#endif
+
+#endif

+ 56 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Marlin.ino

@@ -0,0 +1,56 @@
+/* -*- c++ -*- */
+
+/*
+    Reprap firmware 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 <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ This firmware is a mashup between Sprinter and grbl.
+  (https://github.com/kliment/Sprinter)
+  (https://github.com/simen/grbl/tree)
+
+ It has preliminary support for Matthew Roberts advance algorithm
+    http://reprap.org/pipermail/reprap-dev/2011-May/003323.html
+ */
+
+/* All the implementation is done in *.cpp files to get better compatibility with avr-gcc without the Arduino IDE */
+/* Use this file to help the Arduino IDE find which Arduino libraries are needed and to keep documentation on GCode */
+
+#include "Configuration.h"
+#include "pins.h"
+
+#ifdef ULTRA_LCD
+  #if defined(LCD_I2C_TYPE_PCF8575)
+    #include <Wire.h>
+    #include <LiquidCrystal_I2C.h>
+  #elif defined(LCD_I2C_TYPE_MCP23017) || defined(LCD_I2C_TYPE_MCP23008)
+    #include <Wire.h>
+    #include <LiquidTWI2.h>
+  #elif defined(DOGLCD)
+    #include <U8glib.h> // library for graphics LCD by Oli Kraus (https://code.google.com/p/u8glib/)
+  #else
+    #include <LiquidCrystal.h> // library for character LCD
+  #endif
+#endif
+
+#if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
+#include <SPI.h>
+#endif
+
+#if defined(DIGIPOT_I2C)
+  #include <Wire.h>
+#endif

+ 328 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/MarlinSerial.cpp

@@ -0,0 +1,328 @@
+/*
+  HardwareSerial.cpp - Hardware serial library for Wiring
+  Copyright (c) 2006 Nicholas Zambetti.  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
+  
+  Modified 23 November 2006 by David A. Mellis
+  Modified 28 September 2010 by Mark Sproul
+*/
+
+#include "Marlin.h"
+#include "MarlinSerial.h"
+
+#ifndef AT90USB
+// this next line disables the entire HardwareSerial.cpp, 
+// this is so I can support Attiny series and any other chip without a uart
+#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H)
+
+#if UART_PRESENT(SERIAL_PORT)
+  ring_buffer rx_buffer  =  { { 0 }, 0, 0 };
+#endif
+
+FORCE_INLINE void store_char(unsigned char c)
+{
+  int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE;
+
+  // if we should be storing the received character into the location
+  // just before the tail (meaning that the head would advance to the
+  // current location of the tail), we're about to overflow the buffer
+  // and so we don't write the character or advance the head.
+  if (i != rx_buffer.tail) {
+    rx_buffer.buffer[rx_buffer.head] = c;
+    rx_buffer.head = i;
+  }
+}
+
+
+//#elif defined(SIG_USART_RECV)
+#if defined(M_USARTx_RX_vect)
+  // fixed by Mark Sproul this is on the 644/644p
+  //SIGNAL(SIG_USART_RECV)
+  SIGNAL(M_USARTx_RX_vect)
+  {
+    unsigned char c  =  M_UDRx;
+    store_char(c);
+  }
+#endif
+
+// Constructors ////////////////////////////////////////////////////////////////
+
+MarlinSerial::MarlinSerial()
+{
+
+}
+
+// Public Methods //////////////////////////////////////////////////////////////
+
+void MarlinSerial::begin(long baud)
+{
+  uint16_t baud_setting;
+  bool useU2X = true;
+
+#if F_CPU == 16000000UL && SERIAL_PORT == 0
+  // hardcoded exception for compatibility with the bootloader shipped
+  // with the Duemilanove and previous boards and the firmware on the 8U2
+  // on the Uno and Mega 2560.
+  if (baud == 57600) {
+    useU2X = false;
+  }
+#endif
+  
+  if (useU2X) {
+    M_UCSRxA = 1 << M_U2Xx;
+    baud_setting = (F_CPU / 4 / baud - 1) / 2;
+  } else {
+    M_UCSRxA = 0;
+    baud_setting = (F_CPU / 8 / baud - 1) / 2;
+  }
+
+  // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
+  M_UBRRxH = baud_setting >> 8;
+  M_UBRRxL = baud_setting;
+
+  sbi(M_UCSRxB, M_RXENx);
+  sbi(M_UCSRxB, M_TXENx);
+  sbi(M_UCSRxB, M_RXCIEx);
+}
+
+void MarlinSerial::end()
+{
+  cbi(M_UCSRxB, M_RXENx);
+  cbi(M_UCSRxB, M_TXENx);
+  cbi(M_UCSRxB, M_RXCIEx);  
+}
+
+
+
+int MarlinSerial::peek(void)
+{
+  if (rx_buffer.head == rx_buffer.tail) {
+    return -1;
+  } else {
+    return rx_buffer.buffer[rx_buffer.tail];
+  }
+}
+
+int MarlinSerial::read(void)
+{
+  // if the head isn't ahead of the tail, we don't have any characters
+  if (rx_buffer.head == rx_buffer.tail) {
+    return -1;
+  } else {
+    unsigned char c = rx_buffer.buffer[rx_buffer.tail];
+    rx_buffer.tail = (unsigned int)(rx_buffer.tail + 1) % RX_BUFFER_SIZE;
+    return c;
+  }
+}
+
+void MarlinSerial::flush()
+{
+  // don't reverse this or there may be problems if the RX interrupt
+  // occurs after reading the value of rx_buffer_head but before writing
+  // the value to rx_buffer_tail; the previous value of rx_buffer_head
+  // may be written to rx_buffer_tail, making it appear as if the buffer
+  // don't reverse this or there may be problems if the RX interrupt
+  // occurs after reading the value of rx_buffer_head but before writing
+  // the value to rx_buffer_tail; the previous value of rx_buffer_head
+  // may be written to rx_buffer_tail, making it appear as if the buffer
+  // were full, not empty.
+  rx_buffer.head = rx_buffer.tail;
+}
+
+
+
+
+/// imports from print.h
+
+
+
+
+void MarlinSerial::print(char c, int base)
+{
+  print((long) c, base);
+}
+
+void MarlinSerial::print(unsigned char b, int base)
+{
+  print((unsigned long) b, base);
+}
+
+void MarlinSerial::print(int n, int base)
+{
+  print((long) n, base);
+}
+
+void MarlinSerial::print(unsigned int n, int base)
+{
+  print((unsigned long) n, base);
+}
+
+void MarlinSerial::print(long n, int base)
+{
+  if (base == 0) {
+    write(n);
+  } else if (base == 10) {
+    if (n < 0) {
+      print('-');
+      n = -n;
+    }
+    printNumber(n, 10);
+  } else {
+    printNumber(n, base);
+  }
+}
+
+void MarlinSerial::print(unsigned long n, int base)
+{
+  if (base == 0) write(n);
+  else printNumber(n, base);
+}
+
+void MarlinSerial::print(double n, int digits)
+{
+  printFloat(n, digits);
+}
+
+void MarlinSerial::println(void)
+{
+  print('\r');
+  print('\n');  
+}
+
+void MarlinSerial::println(const String &s)
+{
+  print(s);
+  println();
+}
+
+void MarlinSerial::println(const char c[])
+{
+  print(c);
+  println();
+}
+
+void MarlinSerial::println(char c, int base)
+{
+  print(c, base);
+  println();
+}
+
+void MarlinSerial::println(unsigned char b, int base)
+{
+  print(b, base);
+  println();
+}
+
+void MarlinSerial::println(int n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void MarlinSerial::println(unsigned int n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void MarlinSerial::println(long n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void MarlinSerial::println(unsigned long n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void MarlinSerial::println(double n, int digits)
+{
+  print(n, digits);
+  println();
+}
+
+// Private Methods /////////////////////////////////////////////////////////////
+
+void MarlinSerial::printNumber(unsigned long n, uint8_t base)
+{
+  unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. 
+  unsigned long i = 0;
+
+  if (n == 0) {
+    print('0');
+    return;
+  } 
+
+  while (n > 0) {
+    buf[i++] = n % base;
+    n /= base;
+  }
+
+  for (; i > 0; i--)
+    print((char) (buf[i - 1] < 10 ?
+      '0' + buf[i - 1] :
+      'A' + buf[i - 1] - 10));
+}
+
+void MarlinSerial::printFloat(double number, uint8_t digits) 
+{ 
+  // Handle negative numbers
+  if (number < 0.0)
+  {
+     print('-');
+     number = -number;
+  }
+
+  // Round correctly so that print(1.999, 2) prints as "2.00"
+  double rounding = 0.5;
+  for (uint8_t i=0; i<digits; ++i)
+    rounding /= 10.0;
+  
+  number += rounding;
+
+  // Extract the integer part of the number and print it
+  unsigned long int_part = (unsigned long)number;
+  double remainder = number - (double)int_part;
+  print(int_part);
+
+  // Print the decimal point, but only if there are digits beyond
+  if (digits > 0)
+    print("."); 
+
+  // Extract digits from the remainder one at a time
+  while (digits-- > 0)
+  {
+    remainder *= 10.0;
+    int toPrint = int(remainder);
+    print(toPrint);
+    remainder -= toPrint; 
+  } 
+}
+// Preinstantiate Objects //////////////////////////////////////////////////////
+
+
+MarlinSerial MSerial;
+
+#endif // whole file
+#endif // !AT90USB
+
+// For AT90USB targets use the UART for BT interfacing
+#if defined(AT90USB) && defined (BTENABLED)
+   HardwareSerial bt;
+#endif
+

+ 189 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/MarlinSerial.h

@@ -0,0 +1,189 @@
+/*
+  HardwareSerial.h - Hardware serial library for Wiring
+  Copyright (c) 2006 Nicholas Zambetti.  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
+
+  Modified 28 September 2010 by Mark Sproul
+*/
+
+#ifndef MarlinSerial_h
+#define MarlinSerial_h
+#include "Marlin.h"
+
+#if !defined(SERIAL_PORT) 
+#define SERIAL_PORT 0
+#endif
+
+// The presence of the UBRRH register is used to detect a UART.
+#define UART_PRESENT(port) ((port == 0 && (defined(UBRRH) || defined(UBRR0H))) || \
+						(port == 1 && defined(UBRR1H)) || (port == 2 && defined(UBRR2H)) || \
+						(port == 3 && defined(UBRR3H)))				
+						
+// These are macros to build serial port register names for the selected SERIAL_PORT (C preprocessor
+// requires two levels of indirection to expand macro values properly)
+#define SERIAL_REGNAME(registerbase,number,suffix) SERIAL_REGNAME_INTERNAL(registerbase,number,suffix)
+#if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
+#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
+#else
+#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
+#endif
+
+// Registers used by MarlinSerial class (these are expanded 
+// depending on selected serial port
+#define M_UCSRxA SERIAL_REGNAME(UCSR,SERIAL_PORT,A) // defines M_UCSRxA to be UCSRnA where n is the serial port number
+#define M_UCSRxB SERIAL_REGNAME(UCSR,SERIAL_PORT,B) 
+#define M_RXENx SERIAL_REGNAME(RXEN,SERIAL_PORT,)    
+#define M_TXENx SERIAL_REGNAME(TXEN,SERIAL_PORT,)    
+#define M_RXCIEx SERIAL_REGNAME(RXCIE,SERIAL_PORT,)    
+#define M_UDREx SERIAL_REGNAME(UDRE,SERIAL_PORT,)    
+#define M_UDRx SERIAL_REGNAME(UDR,SERIAL_PORT,)  
+#define M_UBRRxH SERIAL_REGNAME(UBRR,SERIAL_PORT,H)
+#define M_UBRRxL SERIAL_REGNAME(UBRR,SERIAL_PORT,L)
+#define M_RXCx SERIAL_REGNAME(RXC,SERIAL_PORT,)
+#define M_USARTx_RX_vect SERIAL_REGNAME(USART,SERIAL_PORT,_RX_vect)
+#define M_U2Xx SERIAL_REGNAME(U2X,SERIAL_PORT,)
+
+
+
+#define DEC 10
+#define HEX 16
+#define OCT 8
+#define BIN 2
+#define BYTE 0
+
+
+#ifndef AT90USB
+// Define constants and variables for buffering incoming serial data.  We're
+// using a ring buffer (I think), in which rx_buffer_head is the index of the
+// location to which to write the next incoming character and rx_buffer_tail
+// is the index of the location from which to read.
+#define RX_BUFFER_SIZE 128
+
+
+struct ring_buffer
+{
+  unsigned char buffer[RX_BUFFER_SIZE];
+  int head;
+  int tail;
+};
+
+#if UART_PRESENT(SERIAL_PORT)
+  extern ring_buffer rx_buffer;
+#endif
+
+class MarlinSerial //: public Stream
+{
+
+  public:
+    MarlinSerial();
+    void begin(long);
+    void end();
+    int peek(void);
+    int read(void);
+    void flush(void);
+    
+    FORCE_INLINE int available(void)
+    {
+      return (unsigned int)(RX_BUFFER_SIZE + rx_buffer.head - rx_buffer.tail) % RX_BUFFER_SIZE;
+    }
+    
+    FORCE_INLINE void write(uint8_t c)
+    {
+      while (!((M_UCSRxA) & (1 << M_UDREx)))
+        ;
+
+      M_UDRx = c;
+    }
+    
+    
+    FORCE_INLINE void checkRx(void)
+    {
+      if((M_UCSRxA & (1<<M_RXCx)) != 0) {
+        unsigned char c  =  M_UDRx;
+        int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE;
+
+        // if we should be storing the received character into the location
+        // just before the tail (meaning that the head would advance to the
+        // current location of the tail), we're about to overflow the buffer
+        // and so we don't write the character or advance the head.
+        if (i != rx_buffer.tail) {
+          rx_buffer.buffer[rx_buffer.head] = c;
+          rx_buffer.head = i;
+        }
+      }
+    }
+    
+    
+    private:
+    void printNumber(unsigned long, uint8_t);
+    void printFloat(double, uint8_t);
+    
+    
+  public:
+    
+    FORCE_INLINE void write(const char *str)
+    {
+      while (*str)
+        write(*str++);
+    }
+
+
+    FORCE_INLINE void write(const uint8_t *buffer, size_t size)
+    {
+      while (size--)
+        write(*buffer++);
+    }
+
+    FORCE_INLINE void print(const String &s)
+    {
+      for (int i = 0; i < (int)s.length(); i++) {
+        write(s[i]);
+      }
+    }
+    
+    FORCE_INLINE void print(const char *str)
+    {
+      write(str);
+    }
+    void print(char, int = BYTE);
+    void print(unsigned char, int = BYTE);
+    void print(int, int = DEC);
+    void print(unsigned int, int = DEC);
+    void print(long, int = DEC);
+    void print(unsigned long, int = DEC);
+    void print(double, int = 2);
+
+    void println(const String &s);
+    void println(const char[]);
+    void println(char, int = BYTE);
+    void println(unsigned char, int = BYTE);
+    void println(int, int = DEC);
+    void println(unsigned int, int = DEC);
+    void println(long, int = DEC);
+    void println(unsigned long, int = DEC);
+    void println(double, int = 2);
+    void println(void);
+};
+
+extern MarlinSerial MSerial;
+#endif // !AT90USB
+
+// Use the UART for BT in AT90USB configurations
+#if defined(AT90USB) && defined (BTENABLED)
+   extern HardwareSerial bt;
+#endif
+
+#endif

File diff suppressed because it is too large
+ 3806 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Marlin_main.cpp


BIN
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Menu Plans.xlsx


+ 641 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Sd2Card.cpp

@@ -0,0 +1,641 @@
+/* Arduino Sd2Card Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ *
+ * This Library 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino Sd2Card Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#include "Marlin.h"
+
+#ifdef SDSUPPORT
+#include "Sd2Card.h"
+//------------------------------------------------------------------------------
+#ifndef SOFTWARE_SPI
+// functions for hardware SPI
+//------------------------------------------------------------------------------
+// make sure SPCR rate is in expected bits
+#if (SPR0 != 0 || SPR1 != 1)
+#error unexpected SPCR bits
+#endif
+/**
+ * Initialize hardware SPI
+ * Set SCK rate to F_CPU/pow(2, 1 + spiRate) for spiRate [0,6]
+ */
+static void spiInit(uint8_t spiRate) {
+  // See avr processor documentation
+  SPCR = (1 << SPE) | (1 << MSTR) | (spiRate >> 1);
+  SPSR = spiRate & 1 || spiRate == 6 ? 0 : 1 << SPI2X;
+}
+//------------------------------------------------------------------------------
+/** SPI receive a byte */
+static uint8_t spiRec() {
+  SPDR = 0XFF;
+  while (!(SPSR & (1 << SPIF))) { /* Intentionally left empty */ }
+  return SPDR;
+}
+//------------------------------------------------------------------------------
+/** SPI read data - only one call so force inline */
+static inline __attribute__((always_inline))
+void spiRead(uint8_t* buf, uint16_t nbyte) {
+  if (nbyte-- == 0) return;
+  SPDR = 0XFF;
+  for (uint16_t i = 0; i < nbyte; i++) {
+    while (!(SPSR & (1 << SPIF))) { /* Intentionally left empty */ }
+    buf[i] = SPDR;
+    SPDR = 0XFF;
+  }
+  while (!(SPSR & (1 << SPIF))) { /* Intentionally left empty */ }
+  buf[nbyte] = SPDR;
+}
+//------------------------------------------------------------------------------
+/** SPI send a byte */
+static void spiSend(uint8_t b) {
+  SPDR = b;
+  while (!(SPSR & (1 << SPIF))) { /* Intentionally left empty */ }
+}
+//------------------------------------------------------------------------------
+/** SPI send block - only one call so force inline */
+static inline __attribute__((always_inline))
+  void spiSendBlock(uint8_t token, const uint8_t* buf) {
+  SPDR = token;
+  for (uint16_t i = 0; i < 512; i += 2) {
+    while (!(SPSR & (1 << SPIF))) { /* Intentionally left empty */ }
+    SPDR = buf[i];
+    while (!(SPSR & (1 << SPIF))) { /* Intentionally left empty */ }
+    SPDR = buf[i + 1];
+  }
+  while (!(SPSR & (1 << SPIF))) { /* Intentionally left empty */ }
+}
+//------------------------------------------------------------------------------
+#else  // SOFTWARE_SPI
+//------------------------------------------------------------------------------
+/** nop to tune soft SPI timing */
+#define nop asm volatile ("nop\n\t")
+//------------------------------------------------------------------------------
+/** Soft SPI receive byte */
+static uint8_t spiRec() {
+  uint8_t data = 0;
+  // no interrupts during byte receive - about 8 us
+  cli();
+  // output pin high - like sending 0XFF
+  fastDigitalWrite(SPI_MOSI_PIN, HIGH);
+
+  for (uint8_t i = 0; i < 8; i++) {
+    fastDigitalWrite(SPI_SCK_PIN, HIGH);
+
+    // adjust so SCK is nice
+    nop;
+    nop;
+
+    data <<= 1;
+
+    if (fastDigitalRead(SPI_MISO_PIN)) data |= 1;
+
+    fastDigitalWrite(SPI_SCK_PIN, LOW);
+  }
+  // enable interrupts
+  sei();
+  return data;
+}
+//------------------------------------------------------------------------------
+/** Soft SPI read data */
+static void spiRead(uint8_t* buf, uint16_t nbyte) {
+  for (uint16_t i = 0; i < nbyte; i++) {
+    buf[i] = spiRec();
+  }
+}
+//------------------------------------------------------------------------------
+/** Soft SPI send byte */
+static void spiSend(uint8_t data) {
+  // no interrupts during byte send - about 8 us
+  cli();
+  for (uint8_t i = 0; i < 8; i++) {
+    fastDigitalWrite(SPI_SCK_PIN, LOW);
+
+    fastDigitalWrite(SPI_MOSI_PIN, data & 0X80);
+
+    data <<= 1;
+
+    fastDigitalWrite(SPI_SCK_PIN, HIGH);
+  }
+  // hold SCK high for a few ns
+  nop;
+  nop;
+  nop;
+  nop;
+
+  fastDigitalWrite(SPI_SCK_PIN, LOW);
+  // enable interrupts
+  sei();
+}
+//------------------------------------------------------------------------------
+/** Soft SPI send block */
+  void spiSendBlock(uint8_t token, const uint8_t* buf) {
+  spiSend(token);
+  for (uint16_t i = 0; i < 512; i++) {
+    spiSend(buf[i]);
+  }
+}
+#endif  // SOFTWARE_SPI
+//------------------------------------------------------------------------------
+// send command and return error code.  Return zero for OK
+uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
+  // select card
+  chipSelectLow();
+
+  // wait up to 300 ms if busy
+  waitNotBusy(300);
+
+  // send command
+  spiSend(cmd | 0x40);
+
+  // send argument
+  for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s);
+
+  // send CRC
+  uint8_t crc = 0XFF;
+  if (cmd == CMD0) crc = 0X95;  // correct crc for CMD0 with arg 0
+  if (cmd == CMD8) crc = 0X87;  // correct crc for CMD8 with arg 0X1AA
+  spiSend(crc);
+
+  // skip stuff byte for stop read
+  if (cmd == CMD12) spiRec();
+
+  // wait for response
+  for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++) { /* Intentionally left empty */ }
+  return status_;
+}
+//------------------------------------------------------------------------------
+/**
+ * Determine the size of an SD flash memory card.
+ *
+ * \return The number of 512 byte data blocks in the card
+ *         or zero if an error occurs.
+ */
+uint32_t Sd2Card::cardSize() {
+  csd_t csd;
+  if (!readCSD(&csd)) return 0;
+  if (csd.v1.csd_ver == 0) {
+    uint8_t read_bl_len = csd.v1.read_bl_len;
+    uint16_t c_size = (csd.v1.c_size_high << 10)
+                      | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low;
+    uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1)
+                          | csd.v1.c_size_mult_low;
+    return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7);
+  } else if (csd.v2.csd_ver == 1) {
+    uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16)
+                      | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low;
+    return (c_size + 1) << 10;
+  } else {
+    error(SD_CARD_ERROR_BAD_CSD);
+    return 0;
+  }
+}
+//------------------------------------------------------------------------------
+void Sd2Card::chipSelectHigh() {
+  digitalWrite(chipSelectPin_, HIGH);
+}
+//------------------------------------------------------------------------------
+void Sd2Card::chipSelectLow() {
+#ifndef SOFTWARE_SPI
+  spiInit(spiRate_);
+#endif  // SOFTWARE_SPI
+  digitalWrite(chipSelectPin_, LOW);
+}
+//------------------------------------------------------------------------------
+/** Erase a range of blocks.
+ *
+ * \param[in] firstBlock The address of the first block in the range.
+ * \param[in] lastBlock The address of the last block in the range.
+ *
+ * \note This function requests the SD card to do a flash erase for a
+ * range of blocks.  The data on the card after an erase operation is
+ * either 0 or 1, depends on the card vendor.  The card must support
+ * single block erase.
+ *
+ * \return The value one, true, is returned for success and
+ * the value zero, false, is returned for failure.
+ */
+bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
+  csd_t csd;
+  if (!readCSD(&csd)) goto fail;
+  // check for single block erase
+  if (!csd.v1.erase_blk_en) {
+    // erase size mask
+    uint8_t m = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low;
+    if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) {
+      // error card can't erase specified area
+      error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);
+      goto fail;
+    }
+  }
+  if (type_ != SD_CARD_TYPE_SDHC) {
+    firstBlock <<= 9;
+    lastBlock <<= 9;
+  }
+  if (cardCommand(CMD32, firstBlock)
+    || cardCommand(CMD33, lastBlock)
+    || cardCommand(CMD38, 0)) {
+      error(SD_CARD_ERROR_ERASE);
+      goto fail;
+  }
+  if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
+    error(SD_CARD_ERROR_ERASE_TIMEOUT);
+    goto fail;
+  }
+  chipSelectHigh();
+  return true;
+
+ fail:
+  chipSelectHigh();
+  return false;
+}
+//------------------------------------------------------------------------------
+/** Determine if card supports single block erase.
+ *
+ * \return The value one, true, is returned if single block erase is supported.
+ * The value zero, false, is returned if single block erase is not supported.
+ */
+bool Sd2Card::eraseSingleBlockEnable() {
+  csd_t csd;
+  return readCSD(&csd) ? csd.v1.erase_blk_en : false;
+}
+//------------------------------------------------------------------------------
+/**
+ * Initialize an SD flash memory card.
+ *
+ * \param[in] sckRateID SPI clock rate selector. See setSckRate().
+ * \param[in] chipSelectPin SD chip select pin number.
+ *
+ * \return The value one, true, is returned for success and
+ * the value zero, false, is returned for failure.  The reason for failure
+ * can be determined by calling errorCode() and errorData().
+ */
+bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
+  errorCode_ = type_ = 0;
+  chipSelectPin_ = chipSelectPin;
+  // 16-bit init start time allows over a minute
+  uint16_t t0 = (uint16_t)millis();
+  uint32_t arg;
+
+  // set pin modes
+  pinMode(chipSelectPin_, OUTPUT);
+  chipSelectHigh();
+  pinMode(SPI_MISO_PIN, INPUT);
+  pinMode(SPI_MOSI_PIN, OUTPUT);
+  pinMode(SPI_SCK_PIN, OUTPUT);
+
+#ifndef SOFTWARE_SPI
+  // SS must be in output mode even it is not chip select
+  pinMode(SS_PIN, OUTPUT);
+  // set SS high - may be chip select for another SPI device
+#if SET_SPI_SS_HIGH
+  digitalWrite(SS_PIN, HIGH);
+#endif  // SET_SPI_SS_HIGH
+  // set SCK rate for initialization commands
+  spiRate_ = SPI_SD_INIT_RATE;
+  spiInit(spiRate_);
+#endif  // SOFTWARE_SPI
+
+  // must supply min of 74 clock cycles with CS high.
+  for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
+
+  // command to go idle in SPI mode
+  while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
+    if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
+      error(SD_CARD_ERROR_CMD0);
+      goto fail;
+    }
+  }
+  // check SD version
+  if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
+    type(SD_CARD_TYPE_SD1);
+  } else {
+    // only need last byte of r7 response
+    for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
+    if (status_ != 0XAA) {
+      error(SD_CARD_ERROR_CMD8);
+      goto fail;
+    }
+    type(SD_CARD_TYPE_SD2);
+  }
+  // initialize card and send host supports SDHC if SD2
+  arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;
+
+  while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
+    // check for timeout
+    if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
+      error(SD_CARD_ERROR_ACMD41);
+      goto fail;
+    }
+  }
+  // if SD2 read OCR register to check for SDHC card
+  if (type() == SD_CARD_TYPE_SD2) {
+    if (cardCommand(CMD58, 0)) {
+      error(SD_CARD_ERROR_CMD58);
+      goto fail;
+    }
+    if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC);
+    // discard rest of ocr - contains allowed voltage range
+    for (uint8_t i = 0; i < 3; i++) spiRec();
+  }
+  chipSelectHigh();
+
+#ifndef SOFTWARE_SPI
+  return setSckRate(sckRateID);
+#else  // SOFTWARE_SPI
+  return true;
+#endif  // SOFTWARE_SPI
+
+ fail:
+  chipSelectHigh();
+  return false;
+}
+//------------------------------------------------------------------------------
+/**
+ * Read a 512 byte block from an SD card.
+ *
+ * \param[in] blockNumber Logical block to be read.
+ * \param[out] dst Pointer to the location that will receive the data.
+ * \return The value one, true, is returned for success and
+ * the value zero, false, is returned for failure.
+ */
+bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
+  // use address if not SDHC card
+  if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9;
+  if (cardCommand(CMD17, blockNumber)) {
+    error(SD_CARD_ERROR_CMD17);
+    goto fail;
+  }
+  return readData(dst, 512);
+
+ fail:
+  chipSelectHigh();
+  return false;
+}
+//------------------------------------------------------------------------------
+/** Read one data block in a multiple block read sequence
+ *
+ * \param[in] dst Pointer to the location for the data to be read.
+ *
+ * \return The value one, true, is returned for success and
+ * the value zero, false, is returned for failure.
+ */
+bool Sd2Card::readData(uint8_t *dst) {
+  chipSelectLow();
+  return readData(dst, 512);
+}
+//------------------------------------------------------------------------------
+bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
+  // wait for start block token
+  uint16_t t0 = millis();
+  while ((status_ = spiRec()) == 0XFF) {
+    if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) {
+      error(SD_CARD_ERROR_READ_TIMEOUT);
+      goto fail;
+    }
+  }
+  if (status_ != DATA_START_BLOCK) {
+    error(SD_CARD_ERROR_READ);
+    goto fail;
+  }
+  // transfer data
+  spiRead(dst, count);
+
+  // discard CRC
+  spiRec();
+  spiRec();
+  chipSelectHigh();
+  return true;
+
+ fail:
+  chipSelectHigh();
+  return false;
+}
+//------------------------------------------------------------------------------
+/** read CID or CSR register */
+bool Sd2Card::readRegister(uint8_t cmd, void* buf) {
+  uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
+  if (cardCommand(cmd, 0)) {
+    error(SD_CARD_ERROR_READ_REG);
+    goto fail;
+  }
+  return readData(dst, 16);
+
+ fail:
+  chipSelectHigh();
+  return false;
+}
+//------------------------------------------------------------------------------
+/** Start a read multiple blocks sequence.
+ *
+ * \param[in] blockNumber Address of first block in sequence.
+ *
+ * \note This function is used with readData() and readStop() for optimized
+ * multiple block reads.  SPI chipSelect must be low for the entire sequence.
+ *
+ * \return The value one, true, is returned for success and
+ * the value zero, false, is returned for failure.
+ */
+bool Sd2Card::readStart(uint32_t blockNumber) {
+  if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9;
+  if (cardCommand(CMD18, blockNumber)) {
+    error(SD_CARD_ERROR_CMD18);
+    goto fail;
+  }
+  chipSelectHigh();
+  return true;
+
+ fail:
+  chipSelectHigh();
+  return false;
+}
+//------------------------------------------------------------------------------
+/** End a read multiple blocks sequence.
+ *
+* \return The value one, true, is returned for success and
+ * the value zero, false, is returned for failure.
+ */
+bool Sd2Card::readStop() {
+  chipSelectLow();
+  if (cardCommand(CMD12, 0)) {
+    error(SD_CARD_ERROR_CMD12);
+    goto fail;
+  }
+  chipSelectHigh();
+  return true;
+
+ fail:
+  chipSelectHigh();
+  return false;
+}
+//------------------------------------------------------------------------------
+/**
+ * Set the SPI clock rate.
+ *
+ * \param[in] sckRateID A value in the range [0, 6].
+ *
+ * The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum
+ * SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128
+ * for \a scsRateID = 6.
+ *
+ * \return The value one, true, is returned for success and the value zero,
+ * false, is returned for an invalid value of \a sckRateID.
+ */
+bool Sd2Card::setSckRate(uint8_t sckRateID) {
+  if (sckRateID > 6) {
+    error(SD_CARD_ERROR_SCK_RATE);
+    return false;
+  }
+  spiRate_ = sckRateID;
+  return true;
+}
+//------------------------------------------------------------------------------
+// wait for card to go not busy
+bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
+  uint16_t t0 = millis();
+  while (spiRec() != 0XFF) {
+    if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail;
+  }
+  return true;
+
+ fail:
+  return false;
+}
+//------------------------------------------------------------------------------
+/**
+ * Writes a 512 byte block to an SD card.
+ *
+ * \param[in] blockNumber Logical block to be written.
+ * \param[in] src Pointer to the location of the data to be written.
+ * \return The value one, true, is returned for success and
+ * the value zero, false, is returned for failure.
+ */
+bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
+  // use address if not SDHC card
+  if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
+  if (cardCommand(CMD24, blockNumber)) {
+    error(SD_CARD_ERROR_CMD24);
+    goto fail;
+  }
+  if (!writeData(DATA_START_BLOCK, src)) goto fail;
+
+  // wait for flash programming to complete
+  if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
+    error(SD_CARD_ERROR_WRITE_TIMEOUT);
+    goto fail;
+  }
+  // response is r2 so get and check two bytes for nonzero
+  if (cardCommand(CMD13, 0) || spiRec()) {
+    error(SD_CARD_ERROR_WRITE_PROGRAMMING);
+    goto fail;
+  }
+  chipSelectHigh();
+  return true;
+
+ fail:
+  chipSelectHigh();
+  return false;
+}
+//------------------------------------------------------------------------------
+/** Write one data block in a multiple block write sequence
+ * \param[in] src Pointer to the location of the data to be written.
+ * \return The value one, true, is returned for success and
+ * the value zero, false, is returned for failure.
+ */
+bool Sd2Card::writeData(const uint8_t* src) {
+  chipSelectLow();
+  // wait for previous write to finish
+  if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
+  if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto fail;
+  chipSelectHigh();
+  return true;
+
+ fail:
+  error(SD_CARD_ERROR_WRITE_MULTIPLE);
+  chipSelectHigh();
+  return false;
+}
+//------------------------------------------------------------------------------
+// send one block of data for write block or write multiple blocks
+bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
+  spiSendBlock(token, src);
+
+  spiSend(0xff);  // dummy crc
+  spiSend(0xff);  // dummy crc
+
+  status_ = spiRec();
+  if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
+    error(SD_CARD_ERROR_WRITE);
+    goto fail;
+  }
+  return true;
+
+ fail:
+  chipSelectHigh();
+  return false;
+}
+//------------------------------------------------------------------------------
+/** Start a write multiple blocks sequence.
+ *
+ * \param[in] blockNumber Address of first block in sequence.
+ * \param[in] eraseCount The number of blocks to be pre-erased.
+ *
+ * \note This function is used with writeData() and writeStop()
+ * for optimized multiple block writes.
+ *
+ * \return The value one, true, is returned for success and
+ * the value zero, false, is returned for failure.
+ */
+bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
+  // send pre-erase count
+  if (cardAcmd(ACMD23, eraseCount)) {
+    error(SD_CARD_ERROR_ACMD23);
+    goto fail;
+  }
+  // use address if not SDHC card
+  if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
+  if (cardCommand(CMD25, blockNumber)) {
+    error(SD_CARD_ERROR_CMD25);
+    goto fail;
+  }
+  chipSelectHigh();
+  return true;
+
+ fail:
+  chipSelectHigh();
+  return false;
+}
+//------------------------------------------------------------------------------
+/** End a write multiple blocks sequence.
+ *
+* \return The value one, true, is returned for success and
+ * the value zero, false, is returned for failure.
+ */
+bool Sd2Card::writeStop() {
+  chipSelectLow();
+  if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
+  spiSend(STOP_TRAN_TOKEN);
+  if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
+  chipSelectHigh();
+  return true;
+
+ fail:
+  error(SD_CARD_ERROR_STOP_TRAN);
+  chipSelectHigh();
+  return false;
+}
+
+#endif

+ 241 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Sd2Card.h

@@ -0,0 +1,241 @@
+/* Arduino Sd2Card Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ *
+ * This Library 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino Sd2Card Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "Marlin.h"
+#ifdef SDSUPPORT
+
+#ifndef Sd2Card_h
+#define Sd2Card_h
+/**
+ * \file
+ * \brief Sd2Card class for V2 SD/SDHC cards
+ */
+#include "SdFatConfig.h"
+#include "Sd2PinMap.h"
+#include "SdInfo.h"
+//------------------------------------------------------------------------------
+// SPI speed is F_CPU/2^(1 + index), 0 <= index <= 6
+/** Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate(). */
+uint8_t const SPI_FULL_SPEED = 0;
+/** Set SCK rate to F_CPU/4. See Sd2Card::setSckRate(). */
+uint8_t const SPI_HALF_SPEED = 1;
+/** Set SCK rate to F_CPU/8. See Sd2Card::setSckRate(). */
+uint8_t const SPI_QUARTER_SPEED = 2;
+/** Set SCK rate to F_CPU/16. See Sd2Card::setSckRate(). */
+uint8_t const SPI_EIGHTH_SPEED = 3;
+/** Set SCK rate to F_CPU/32. See Sd2Card::setSckRate(). */
+uint8_t const SPI_SIXTEENTH_SPEED = 4;
+//------------------------------------------------------------------------------
+/** init timeout ms */
+uint16_t const SD_INIT_TIMEOUT = 2000;
+/** erase timeout ms */
+uint16_t const SD_ERASE_TIMEOUT = 10000;
+/** read timeout ms */
+uint16_t const SD_READ_TIMEOUT = 300;
+/** write time out ms */
+uint16_t const SD_WRITE_TIMEOUT = 600;
+//------------------------------------------------------------------------------
+// SD card errors
+/** timeout error for command CMD0 (initialize card in SPI mode) */
+uint8_t const SD_CARD_ERROR_CMD0 = 0X1;
+/** CMD8 was not accepted - not a valid SD card*/
+uint8_t const SD_CARD_ERROR_CMD8 = 0X2;
+/** card returned an error response for CMD12 (write stop) */
+uint8_t const SD_CARD_ERROR_CMD12 = 0X3;
+/** card returned an error response for CMD17 (read block) */
+uint8_t const SD_CARD_ERROR_CMD17 = 0X4;
+/** card returned an error response for CMD18 (read multiple block) */
+uint8_t const SD_CARD_ERROR_CMD18 = 0X5;
+/** card returned an error response for CMD24 (write block) */
+uint8_t const SD_CARD_ERROR_CMD24 = 0X6;
+/**  WRITE_MULTIPLE_BLOCKS command failed */
+uint8_t const SD_CARD_ERROR_CMD25 = 0X7;
+/** card returned an error response for CMD58 (read OCR) */
+uint8_t const SD_CARD_ERROR_CMD58 = 0X8;
+/** SET_WR_BLK_ERASE_COUNT failed */
+uint8_t const SD_CARD_ERROR_ACMD23 = 0X9;
+/** ACMD41 initialization process timeout */
+uint8_t const SD_CARD_ERROR_ACMD41 = 0XA;
+/** card returned a bad CSR version field */
+uint8_t const SD_CARD_ERROR_BAD_CSD = 0XB;
+/** erase block group command failed */
+uint8_t const SD_CARD_ERROR_ERASE = 0XC;
+/** card not capable of single block erase */
+uint8_t const SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0XD;
+/** Erase sequence timed out */
+uint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0XE;
+/** card returned an error token instead of read data */
+uint8_t const SD_CARD_ERROR_READ = 0XF;
+/** read CID or CSD failed */
+uint8_t const SD_CARD_ERROR_READ_REG = 0X10;
+/** timeout while waiting for start of read data */
+uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0X11;
+/** card did not accept STOP_TRAN_TOKEN */
+uint8_t const SD_CARD_ERROR_STOP_TRAN = 0X12;
+/** card returned an error token as a response to a write operation */
+uint8_t const SD_CARD_ERROR_WRITE = 0X13;
+/** attempt to write protected block zero */
+uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X14;  // REMOVE - not used
+/** card did not go ready for a multiple block write */
+uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X15;
+/** card returned an error to a CMD13 status check after a write */
+uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X16;
+/** timeout occurred during write programming */
+uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0X17;
+/** incorrect rate selected */
+uint8_t const SD_CARD_ERROR_SCK_RATE = 0X18;
+/** init() not called */
+uint8_t const SD_CARD_ERROR_INIT_NOT_CALLED = 0X19;
+//------------------------------------------------------------------------------
+// card types
+/** Standard capacity V1 SD card */
+uint8_t const SD_CARD_TYPE_SD1  = 1;
+/** Standard capacity V2 SD card */
+uint8_t const SD_CARD_TYPE_SD2  = 2;
+/** High Capacity SD card */
+uint8_t const SD_CARD_TYPE_SDHC = 3;
+/**
+ * define SOFTWARE_SPI to use bit-bang SPI
+ */
+//------------------------------------------------------------------------------
+#if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__))
+#define SOFTWARE_SPI
+#elif USE_SOFTWARE_SPI
+#define SOFTWARE_SPI
+#endif  // MEGA_SOFT_SPI
+//------------------------------------------------------------------------------
+// SPI pin definitions - do not edit here - change in SdFatConfig.h
+//
+#ifndef SOFTWARE_SPI
+// hardware pin defs
+/** The default chip select pin for the SD card is SS. */
+uint8_t const  SD_CHIP_SELECT_PIN = SS_PIN;
+// The following three pins must not be redefined for hardware SPI.
+/** SPI Master Out Slave In pin */
+uint8_t const  SPI_MOSI_PIN = MOSI_PIN;
+/** SPI Master In Slave Out pin */
+uint8_t const  SPI_MISO_PIN = MISO_PIN;
+/** SPI Clock pin */
+uint8_t const  SPI_SCK_PIN = SCK_PIN;
+
+#else  // SOFTWARE_SPI
+
+/** SPI chip select pin */
+uint8_t const SD_CHIP_SELECT_PIN = SOFT_SPI_CS_PIN;
+/** SPI Master Out Slave In pin */
+uint8_t const SPI_MOSI_PIN = SOFT_SPI_MOSI_PIN;
+/** SPI Master In Slave Out pin */
+uint8_t const SPI_MISO_PIN = SOFT_SPI_MISO_PIN;
+/** SPI Clock pin */
+uint8_t const SPI_SCK_PIN = SOFT_SPI_SCK_PIN;
+#endif  // SOFTWARE_SPI
+//------------------------------------------------------------------------------
+/**
+ * \class Sd2Card
+ * \brief Raw access to SD and SDHC flash memory cards.
+ */
+class Sd2Card {
+ public:
+  /** Construct an instance of Sd2Card. */
+  Sd2Card() : errorCode_(SD_CARD_ERROR_INIT_NOT_CALLED), type_(0) {}
+  uint32_t cardSize();
+  bool erase(uint32_t firstBlock, uint32_t lastBlock);
+  bool eraseSingleBlockEnable();
+  /**
+   *  Set SD error code.
+   *  \param[in] code value for error code.
+   */
+  void error(uint8_t code) {errorCode_ = code;}
+  /**
+   * \return error code for last error. See Sd2Card.h for a list of error codes.
+   */
+  int errorCode() const {return errorCode_;}
+  /** \return error data for last error. */
+  int errorData() const {return status_;}
+  /**
+   * Initialize an SD flash memory card with default clock rate and chip
+   * select pin.  See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin).
+   *
+   * \return true for success or false for failure.
+   */
+  bool init(uint8_t sckRateID = SPI_FULL_SPEED,
+    uint8_t chipSelectPin = SD_CHIP_SELECT_PIN);
+  bool readBlock(uint32_t block, uint8_t* dst);
+  /**
+   * Read a card's CID register. The CID contains card identification
+   * information such as Manufacturer ID, Product name, Product serial
+   * number and Manufacturing date. 
+   *
+   * \param[out] cid pointer to area for returned data.
+   *
+   * \return true for success or false for failure.
+   */
+  bool readCID(cid_t* cid) {
+    return readRegister(CMD10, cid);
+  }
+  /**
+   * Read a card's CSD register. The CSD contains Card-Specific Data that
+   * provides information regarding access to the card's contents.
+   *
+   * \param[out] csd pointer to area for returned data.
+   *
+   * \return true for success or false for failure.
+   */
+  bool readCSD(csd_t* csd) {
+    return readRegister(CMD9, csd);
+  }
+  bool readData(uint8_t *dst);
+  bool readStart(uint32_t blockNumber);
+  bool readStop();
+  bool setSckRate(uint8_t sckRateID);
+  /** Return the card type: SD V1, SD V2 or SDHC
+   * \return 0 - SD V1, 1 - SD V2, or 3 - SDHC.
+   */
+  int type() const {return type_;}
+  bool writeBlock(uint32_t blockNumber, const uint8_t* src);
+  bool writeData(const uint8_t* src);
+  bool writeStart(uint32_t blockNumber, uint32_t eraseCount);
+  bool writeStop();
+ private:
+  //----------------------------------------------------------------------------
+  uint8_t chipSelectPin_;
+  uint8_t errorCode_;
+  uint8_t spiRate_;
+  uint8_t status_;
+  uint8_t type_;
+  // private functions
+  uint8_t cardAcmd(uint8_t cmd, uint32_t arg) {
+    cardCommand(CMD55, 0);
+    return cardCommand(cmd, arg);
+  }
+  uint8_t cardCommand(uint8_t cmd, uint32_t arg);
+
+  bool readData(uint8_t* dst, uint16_t count);
+  bool readRegister(uint8_t cmd, void* buf);
+  void chipSelectHigh();
+  void chipSelectLow();
+  void type(uint8_t value) {type_ = value;}
+  bool waitNotBusy(uint16_t timeoutMillis);
+  bool writeData(uint8_t token, const uint8_t* src);
+};
+#endif  // Sd2Card_h
+
+
+#endif

+ 368 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Sd2PinMap.h

@@ -0,0 +1,368 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2010 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+// Warning this file was generated by a program.
+#include "Marlin.h"
+#ifdef SDSUPPORT
+
+#ifndef Sd2PinMap_h
+#define Sd2PinMap_h
+#include <avr/io.h>
+//------------------------------------------------------------------------------
+/** struct for mapping digital pins */
+struct pin_map_t {
+  volatile uint8_t* ddr;
+  volatile uint8_t* pin;
+  volatile uint8_t* port;
+  uint8_t bit;
+};
+//------------------------------------------------------------------------------
+#if defined(__AVR_ATmega1280__)\
+|| defined(__AVR_ATmega2560__)
+// Mega
+
+// Two Wire (aka I2C) ports
+uint8_t const SDA_PIN = 20;  // D1
+uint8_t const SCL_PIN = 21;  // D0
+
+#undef MOSI_PIN
+#undef MISO_PIN
+// SPI port
+uint8_t const SS_PIN = 53;    // B0
+uint8_t const MOSI_PIN = 51;  // B2
+uint8_t const MISO_PIN = 50;  // B3
+uint8_t const SCK_PIN = 52;   // B1
+
+static const pin_map_t digitalPinMap[] = {
+  {&DDRE, &PINE, &PORTE, 0},  // E0  0
+  {&DDRE, &PINE, &PORTE, 1},  // E1  1
+  {&DDRE, &PINE, &PORTE, 4},  // E4  2
+  {&DDRE, &PINE, &PORTE, 5},  // E5  3
+  {&DDRG, &PING, &PORTG, 5},  // G5  4
+  {&DDRE, &PINE, &PORTE, 3},  // E3  5
+  {&DDRH, &PINH, &PORTH, 3},  // H3  6
+  {&DDRH, &PINH, &PORTH, 4},  // H4  7
+  {&DDRH, &PINH, &PORTH, 5},  // H5  8
+  {&DDRH, &PINH, &PORTH, 6},  // H6  9
+  {&DDRB, &PINB, &PORTB, 4},  // B4 10
+  {&DDRB, &PINB, &PORTB, 5},  // B5 11
+  {&DDRB, &PINB, &PORTB, 6},  // B6 12
+  {&DDRB, &PINB, &PORTB, 7},  // B7 13
+  {&DDRJ, &PINJ, &PORTJ, 1},  // J1 14
+  {&DDRJ, &PINJ, &PORTJ, 0},  // J0 15
+  {&DDRH, &PINH, &PORTH, 1},  // H1 16
+  {&DDRH, &PINH, &PORTH, 0},  // H0 17
+  {&DDRD, &PIND, &PORTD, 3},  // D3 18
+  {&DDRD, &PIND, &PORTD, 2},  // D2 19
+  {&DDRD, &PIND, &PORTD, 1},  // D1 20
+  {&DDRD, &PIND, &PORTD, 0},  // D0 21
+  {&DDRA, &PINA, &PORTA, 0},  // A0 22
+  {&DDRA, &PINA, &PORTA, 1},  // A1 23
+  {&DDRA, &PINA, &PORTA, 2},  // A2 24
+  {&DDRA, &PINA, &PORTA, 3},  // A3 25
+  {&DDRA, &PINA, &PORTA, 4},  // A4 26
+  {&DDRA, &PINA, &PORTA, 5},  // A5 27
+  {&DDRA, &PINA, &PORTA, 6},  // A6 28
+  {&DDRA, &PINA, &PORTA, 7},  // A7 29
+  {&DDRC, &PINC, &PORTC, 7},  // C7 30
+  {&DDRC, &PINC, &PORTC, 6},  // C6 31
+  {&DDRC, &PINC, &PORTC, 5},  // C5 32
+  {&DDRC, &PINC, &PORTC, 4},  // C4 33
+  {&DDRC, &PINC, &PORTC, 3},  // C3 34
+  {&DDRC, &PINC, &PORTC, 2},  // C2 35
+  {&DDRC, &PINC, &PORTC, 1},  // C1 36
+  {&DDRC, &PINC, &PORTC, 0},  // C0 37
+  {&DDRD, &PIND, &PORTD, 7},  // D7 38
+  {&DDRG, &PING, &PORTG, 2},  // G2 39
+  {&DDRG, &PING, &PORTG, 1},  // G1 40
+  {&DDRG, &PING, &PORTG, 0},  // G0 41
+  {&DDRL, &PINL, &PORTL, 7},  // L7 42
+  {&DDRL, &PINL, &PORTL, 6},  // L6 43
+  {&DDRL, &PINL, &PORTL, 5},  // L5 44
+  {&DDRL, &PINL, &PORTL, 4},  // L4 45
+  {&DDRL, &PINL, &PORTL, 3},  // L3 46
+  {&DDRL, &PINL, &PORTL, 2},  // L2 47
+  {&DDRL, &PINL, &PORTL, 1},  // L1 48
+  {&DDRL, &PINL, &PORTL, 0},  // L0 49
+  {&DDRB, &PINB, &PORTB, 3},  // B3 50
+  {&DDRB, &PINB, &PORTB, 2},  // B2 51
+  {&DDRB, &PINB, &PORTB, 1},  // B1 52
+  {&DDRB, &PINB, &PORTB, 0},  // B0 53
+  {&DDRF, &PINF, &PORTF, 0},  // F0 54
+  {&DDRF, &PINF, &PORTF, 1},  // F1 55
+  {&DDRF, &PINF, &PORTF, 2},  // F2 56
+  {&DDRF, &PINF, &PORTF, 3},  // F3 57
+  {&DDRF, &PINF, &PORTF, 4},  // F4 58
+  {&DDRF, &PINF, &PORTF, 5},  // F5 59
+  {&DDRF, &PINF, &PORTF, 6},  // F6 60
+  {&DDRF, &PINF, &PORTF, 7},  // F7 61
+  {&DDRK, &PINK, &PORTK, 0},  // K0 62
+  {&DDRK, &PINK, &PORTK, 1},  // K1 63
+  {&DDRK, &PINK, &PORTK, 2},  // K2 64
+  {&DDRK, &PINK, &PORTK, 3},  // K3 65
+  {&DDRK, &PINK, &PORTK, 4},  // K4 66
+  {&DDRK, &PINK, &PORTK, 5},  // K5 67
+  {&DDRK, &PINK, &PORTK, 6},  // K6 68
+  {&DDRK, &PINK, &PORTK, 7}   // K7 69
+};
+//------------------------------------------------------------------------------
+#elif defined(__AVR_ATmega644P__)\
+|| defined(__AVR_ATmega644__)\
+|| defined(__AVR_ATmega1284P__)
+// Sanguino
+
+// Two Wire (aka I2C) ports
+uint8_t const SDA_PIN = 17;  // C1
+uint8_t const SCL_PIN = 18;  // C2
+
+// SPI port
+uint8_t const SS_PIN = 4;    // B4
+uint8_t const MOSI_PIN = 5;  // B5
+uint8_t const MISO_PIN = 6;  // B6
+uint8_t const SCK_PIN = 7;   // B7
+
+static const pin_map_t digitalPinMap[] = {
+  {&DDRB, &PINB, &PORTB, 0},  // B0  0
+  {&DDRB, &PINB, &PORTB, 1},  // B1  1
+  {&DDRB, &PINB, &PORTB, 2},  // B2  2
+  {&DDRB, &PINB, &PORTB, 3},  // B3  3
+  {&DDRB, &PINB, &PORTB, 4},  // B4  4
+  {&DDRB, &PINB, &PORTB, 5},  // B5  5
+  {&DDRB, &PINB, &PORTB, 6},  // B6  6
+  {&DDRB, &PINB, &PORTB, 7},  // B7  7
+  {&DDRD, &PIND, &PORTD, 0},  // D0  8
+  {&DDRD, &PIND, &PORTD, 1},  // D1  9
+  {&DDRD, &PIND, &PORTD, 2},  // D2 10
+  {&DDRD, &PIND, &PORTD, 3},  // D3 11
+  {&DDRD, &PIND, &PORTD, 4},  // D4 12
+  {&DDRD, &PIND, &PORTD, 5},  // D5 13
+  {&DDRD, &PIND, &PORTD, 6},  // D6 14
+  {&DDRD, &PIND, &PORTD, 7},  // D7 15
+  {&DDRC, &PINC, &PORTC, 0},  // C0 16
+  {&DDRC, &PINC, &PORTC, 1},  // C1 17
+  {&DDRC, &PINC, &PORTC, 2},  // C2 18
+  {&DDRC, &PINC, &PORTC, 3},  // C3 19
+  {&DDRC, &PINC, &PORTC, 4},  // C4 20
+  {&DDRC, &PINC, &PORTC, 5},  // C5 21
+  {&DDRC, &PINC, &PORTC, 6},  // C6 22
+  {&DDRC, &PINC, &PORTC, 7},  // C7 23
+  {&DDRA, &PINA, &PORTA, 7},  // A7 24
+  {&DDRA, &PINA, &PORTA, 6},  // A6 25
+  {&DDRA, &PINA, &PORTA, 5},  // A5 26
+  {&DDRA, &PINA, &PORTA, 4},  // A4 27
+  {&DDRA, &PINA, &PORTA, 3},  // A3 28
+  {&DDRA, &PINA, &PORTA, 2},  // A2 29
+  {&DDRA, &PINA, &PORTA, 1},  // A1 30
+  {&DDRA, &PINA, &PORTA, 0}   // A0 31
+};
+//------------------------------------------------------------------------------
+#elif defined(__AVR_ATmega32U4__)
+// Teensy 2.0
+
+// Two Wire (aka I2C) ports
+uint8_t const SDA_PIN = 6;  // D1
+uint8_t const SCL_PIN = 5;  // D0
+
+// SPI port
+uint8_t const SS_PIN = 0;    // B0
+uint8_t const MOSI_PIN = 2;  // B2
+uint8_t const MISO_PIN = 3;  // B3
+uint8_t const SCK_PIN = 1;   // B1
+
+static const pin_map_t digitalPinMap[] = {
+  {&DDRB, &PINB, &PORTB, 0},  // B0  0
+  {&DDRB, &PINB, &PORTB, 1},  // B1  1
+  {&DDRB, &PINB, &PORTB, 2},  // B2  2
+  {&DDRB, &PINB, &PORTB, 3},  // B3  3
+  {&DDRB, &PINB, &PORTB, 7},  // B7  4
+  {&DDRD, &PIND, &PORTD, 0},  // D0  5
+  {&DDRD, &PIND, &PORTD, 1},  // D1  6
+  {&DDRD, &PIND, &PORTD, 2},  // D2  7
+  {&DDRD, &PIND, &PORTD, 3},  // D3  8
+  {&DDRC, &PINC, &PORTC, 6},  // C6  9
+  {&DDRC, &PINC, &PORTC, 7},  // C7 10
+  {&DDRD, &PIND, &PORTD, 6},  // D6 11
+  {&DDRD, &PIND, &PORTD, 7},  // D7 12
+  {&DDRB, &PINB, &PORTB, 4},  // B4 13
+  {&DDRB, &PINB, &PORTB, 5},  // B5 14
+  {&DDRB, &PINB, &PORTB, 6},  // B6 15
+  {&DDRF, &PINF, &PORTF, 7},  // F7 16
+  {&DDRF, &PINF, &PORTF, 6},  // F6 17
+  {&DDRF, &PINF, &PORTF, 5},  // F5 18
+  {&DDRF, &PINF, &PORTF, 4},  // F4 19
+  {&DDRF, &PINF, &PORTF, 1},  // F1 20
+  {&DDRF, &PINF, &PORTF, 0},  // F0 21
+  {&DDRD, &PIND, &PORTD, 4},  // D4 22
+  {&DDRD, &PIND, &PORTD, 5},  // D5 23
+  {&DDRE, &PINE, &PORTE, 6}   // E6 24
+};
+//------------------------------------------------------------------------------
+#elif defined(__AVR_AT90USB646__)\
+|| defined(__AVR_AT90USB1286__)
+// Teensy++ 1.0 & 2.0
+
+// Two Wire (aka I2C) ports
+uint8_t const SDA_PIN = 1;  // D1
+uint8_t const SCL_PIN = 0;  // D0
+
+// SPI port
+uint8_t const SS_PIN    = 20;    // B0
+uint8_t const MOSI_PIN  = 22;    // B2
+uint8_t const MISO_PIN  = 23;    // B3
+uint8_t const SCK_PIN   = 21;    // B1
+
+static const pin_map_t digitalPinMap[] = {
+  {&DDRD, &PIND, &PORTD, 0},  // D0  0
+  {&DDRD, &PIND, &PORTD, 1},  // D1  1
+  {&DDRD, &PIND, &PORTD, 2},  // D2  2
+  {&DDRD, &PIND, &PORTD, 3},  // D3  3
+  {&DDRD, &PIND, &PORTD, 4},  // D4  4
+  {&DDRD, &PIND, &PORTD, 5},  // D5  5
+  {&DDRD, &PIND, &PORTD, 6},  // D6  6
+  {&DDRD, &PIND, &PORTD, 7},  // D7  7
+  {&DDRE, &PINE, &PORTE, 0},  // E0  8
+  {&DDRE, &PINE, &PORTE, 1},  // E1  9
+  {&DDRC, &PINC, &PORTC, 0},  // C0 10
+  {&DDRC, &PINC, &PORTC, 1},  // C1 11
+  {&DDRC, &PINC, &PORTC, 2},  // C2 12
+  {&DDRC, &PINC, &PORTC, 3},  // C3 13
+  {&DDRC, &PINC, &PORTC, 4},  // C4 14
+  {&DDRC, &PINC, &PORTC, 5},  // C5 15
+  {&DDRC, &PINC, &PORTC, 6},  // C6 16
+  {&DDRC, &PINC, &PORTC, 7},  // C7 17
+  {&DDRE, &PINE, &PORTE, 6},  // E6 18
+  {&DDRE, &PINE, &PORTE, 7},  // E7 19
+  {&DDRB, &PINB, &PORTB, 0},  // B0 20
+  {&DDRB, &PINB, &PORTB, 1},  // B1 21
+  {&DDRB, &PINB, &PORTB, 2},  // B2 22
+  {&DDRB, &PINB, &PORTB, 3},  // B3 23
+  {&DDRB, &PINB, &PORTB, 4},  // B4 24
+  {&DDRB, &PINB, &PORTB, 5},  // B5 25
+  {&DDRB, &PINB, &PORTB, 6},  // B6 26
+  {&DDRB, &PINB, &PORTB, 7},  // B7 27
+  {&DDRA, &PINA, &PORTA, 0},  // A0 28
+  {&DDRA, &PINA, &PORTA, 1},  // A1 29
+  {&DDRA, &PINA, &PORTA, 2},  // A2 30
+  {&DDRA, &PINA, &PORTA, 3},  // A3 31
+  {&DDRA, &PINA, &PORTA, 4},  // A4 32
+  {&DDRA, &PINA, &PORTA, 5},  // A5 33
+  {&DDRA, &PINA, &PORTA, 6},  // A6 34
+  {&DDRA, &PINA, &PORTA, 7},  // A7 35
+  {&DDRE, &PINE, &PORTE, 4},  // E4 36
+  {&DDRE, &PINE, &PORTE, 5},  // E5 37
+  {&DDRF, &PINF, &PORTF, 0},  // F0 38
+  {&DDRF, &PINF, &PORTF, 1},  // F1 39
+  {&DDRF, &PINF, &PORTF, 2},  // F2 40
+  {&DDRF, &PINF, &PORTF, 3},  // F3 41
+  {&DDRF, &PINF, &PORTF, 4},  // F4 42
+  {&DDRF, &PINF, &PORTF, 5},  // F5 43
+  {&DDRF, &PINF, &PORTF, 6},  // F6 44
+  {&DDRF, &PINF, &PORTF, 7}   // F7 45
+};
+//------------------------------------------------------------------------------
+#elif defined(__AVR_ATmega168__)\
+||defined(__AVR_ATmega168P__)\
+||defined(__AVR_ATmega328P__)
+// 168 and 328 Arduinos
+
+// Two Wire (aka I2C) ports
+uint8_t const SDA_PIN = 18;  // C4
+uint8_t const SCL_PIN = 19;  // C5
+
+// SPI port
+uint8_t const SS_PIN = 10;    // B2
+uint8_t const MOSI_PIN = 11;  // B3
+uint8_t const MISO_PIN = 12;  // B4
+uint8_t const SCK_PIN = 13;   // B5
+
+static const pin_map_t digitalPinMap[] = {
+  {&DDRD, &PIND, &PORTD, 0},  // D0  0
+  {&DDRD, &PIND, &PORTD, 1},  // D1  1
+  {&DDRD, &PIND, &PORTD, 2},  // D2  2
+  {&DDRD, &PIND, &PORTD, 3},  // D3  3
+  {&DDRD, &PIND, &PORTD, 4},  // D4  4
+  {&DDRD, &PIND, &PORTD, 5},  // D5  5
+  {&DDRD, &PIND, &PORTD, 6},  // D6  6
+  {&DDRD, &PIND, &PORTD, 7},  // D7  7
+  {&DDRB, &PINB, &PORTB, 0},  // B0  8
+  {&DDRB, &PINB, &PORTB, 1},  // B1  9
+  {&DDRB, &PINB, &PORTB, 2},  // B2 10
+  {&DDRB, &PINB, &PORTB, 3},  // B3 11
+  {&DDRB, &PINB, &PORTB, 4},  // B4 12
+  {&DDRB, &PINB, &PORTB, 5},  // B5 13
+  {&DDRC, &PINC, &PORTC, 0},  // C0 14
+  {&DDRC, &PINC, &PORTC, 1},  // C1 15
+  {&DDRC, &PINC, &PORTC, 2},  // C2 16
+  {&DDRC, &PINC, &PORTC, 3},  // C3 17
+  {&DDRC, &PINC, &PORTC, 4},  // C4 18
+  {&DDRC, &PINC, &PORTC, 5}   // C5 19
+};
+#else  // defined(__AVR_ATmega1280__)
+#error unknown chip
+#endif  // defined(__AVR_ATmega1280__)
+//------------------------------------------------------------------------------
+static const uint8_t digitalPinCount = sizeof(digitalPinMap)/sizeof(pin_map_t);
+
+uint8_t badPinNumber(void)
+  __attribute__((error("Pin number is too large or not a constant")));
+
+static inline __attribute__((always_inline))
+  bool getPinMode(uint8_t pin) {
+  if (__builtin_constant_p(pin) && pin < digitalPinCount) {
+    return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1;
+  } else {
+    return badPinNumber();
+  }
+}
+static inline __attribute__((always_inline))
+  void setPinMode(uint8_t pin, uint8_t mode) {
+  if (__builtin_constant_p(pin) && pin < digitalPinCount) {
+    if (mode) {
+      *digitalPinMap[pin].ddr |= 1 << digitalPinMap[pin].bit;
+    } else {
+      *digitalPinMap[pin].ddr &= ~(1 << digitalPinMap[pin].bit);
+    }
+  } else {
+    badPinNumber();
+  }
+}
+static inline __attribute__((always_inline))
+  bool fastDigitalRead(uint8_t pin) {
+  if (__builtin_constant_p(pin) && pin < digitalPinCount) {
+    return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1;
+  } else {
+    return badPinNumber();
+  }
+}
+static inline __attribute__((always_inline))
+  void fastDigitalWrite(uint8_t pin, uint8_t value) {
+  if (__builtin_constant_p(pin) && pin < digitalPinCount) {
+    if (value) {
+      *digitalPinMap[pin].port |= 1 << digitalPinMap[pin].bit;
+    } else {
+      *digitalPinMap[pin].port &= ~(1 << digitalPinMap[pin].bit);
+    }
+  } else {
+    badPinNumber();
+  }
+}
+#endif  // Sd2PinMap_h
+
+
+#endif

File diff suppressed because it is too large
+ 1825 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdBaseFile.cpp


+ 483 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdBaseFile.h

@@ -0,0 +1,483 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#include "Marlin.h"
+#ifdef SDSUPPORT
+
+#ifndef SdBaseFile_h
+#define SdBaseFile_h
+/**
+ * \file
+ * \brief SdBaseFile class
+ */
+#include "Marlin.h"
+#include "SdFatConfig.h"
+#include "SdVolume.h"
+//------------------------------------------------------------------------------
+/**
+ * \struct fpos_t
+ * \brief internal type for istream
+ * do not use in user apps
+ */
+struct fpos_t {
+  /** stream position */
+  uint32_t position;
+  /** cluster for position */
+  uint32_t cluster;
+  fpos_t() : position(0), cluster(0) {}
+};
+
+// use the gnu style oflag in open()
+/** open() oflag for reading */
+uint8_t const O_READ = 0X01;
+/** open() oflag - same as O_IN */
+uint8_t const O_RDONLY = O_READ;
+/** open() oflag for write */
+uint8_t const O_WRITE = 0X02;
+/** open() oflag - same as O_WRITE */
+uint8_t const O_WRONLY = O_WRITE;
+/** open() oflag for reading and writing */
+uint8_t const O_RDWR = (O_READ | O_WRITE);
+/** open() oflag mask for access modes */
+uint8_t const O_ACCMODE = (O_READ | O_WRITE);
+/** The file offset shall be set to the end of the file prior to each write. */
+uint8_t const O_APPEND = 0X04;
+/** synchronous writes - call sync() after each write */
+uint8_t const O_SYNC = 0X08;
+/** truncate the file to zero length */
+uint8_t const O_TRUNC = 0X10;
+/** set the initial position at the end of the file */
+uint8_t const O_AT_END = 0X20;
+/** create the file if nonexistent */
+uint8_t const O_CREAT = 0X40;
+/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
+uint8_t const O_EXCL = 0X80;
+
+// SdBaseFile class static and const definitions
+// flags for ls()
+/** ls() flag to print modify date */
+uint8_t const LS_DATE = 1;
+/** ls() flag to print file size */
+uint8_t const LS_SIZE = 2;
+/** ls() flag for recursive list of subdirectories */
+uint8_t const LS_R = 4;
+
+
+// flags for timestamp
+/** set the file's last access date */
+uint8_t const T_ACCESS = 1;
+/** set the file's creation date and time */
+uint8_t const T_CREATE = 2;
+/** Set the file's write date and time */
+uint8_t const T_WRITE = 4;
+// values for type_
+/** This file has not been opened. */
+uint8_t const FAT_FILE_TYPE_CLOSED = 0;
+/** A normal file */
+uint8_t const FAT_FILE_TYPE_NORMAL = 1;
+/** A FAT12 or FAT16 root directory */
+uint8_t const FAT_FILE_TYPE_ROOT_FIXED = 2;
+/** A FAT32 root directory */
+uint8_t const FAT_FILE_TYPE_ROOT32 = 3;
+/** A subdirectory file*/
+uint8_t const FAT_FILE_TYPE_SUBDIR = 4;
+/** Test value for directory type */
+uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT_FIXED;
+
+/** date field for FAT directory entry
+ * \param[in] year [1980,2107]
+ * \param[in] month [1,12]
+ * \param[in] day [1,31]
+ *
+ * \return Packed date for dir_t entry.
+ */
+static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {
+  return (year - 1980) << 9 | month << 5 | day;
+}
+/** year part of FAT directory date field
+ * \param[in] fatDate Date in packed dir format.
+ *
+ * \return Extracted year [1980,2107]
+ */
+static inline uint16_t FAT_YEAR(uint16_t fatDate) {
+  return 1980 + (fatDate >> 9);
+}
+/** month part of FAT directory date field
+ * \param[in] fatDate Date in packed dir format.
+ *
+ * \return Extracted month [1,12]
+ */
+static inline uint8_t FAT_MONTH(uint16_t fatDate) {
+  return (fatDate >> 5) & 0XF;
+}
+/** day part of FAT directory date field
+ * \param[in] fatDate Date in packed dir format.
+ *
+ * \return Extracted day [1,31]
+ */
+static inline uint8_t FAT_DAY(uint16_t fatDate) {
+  return fatDate & 0X1F;
+}
+/** time field for FAT directory entry
+ * \param[in] hour [0,23]
+ * \param[in] minute [0,59]
+ * \param[in] second [0,59]
+ *
+ * \return Packed time for dir_t entry.
+ */
+static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) {
+  return hour << 11 | minute << 5 | second >> 1;
+}
+/** hour part of FAT directory time field
+ * \param[in] fatTime Time in packed dir format.
+ *
+ * \return Extracted hour [0,23]
+ */
+static inline uint8_t FAT_HOUR(uint16_t fatTime) {
+  return fatTime >> 11;
+}
+/** minute part of FAT directory time field
+ * \param[in] fatTime Time in packed dir format.
+ *
+ * \return Extracted minute [0,59]
+ */
+static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
+  return(fatTime >> 5) & 0X3F;
+}
+/** second part of FAT directory time field
+ * Note second/2 is stored in packed time.
+ *
+ * \param[in] fatTime Time in packed dir format.
+ *
+ * \return Extracted second [0,58]
+ */
+static inline uint8_t FAT_SECOND(uint16_t fatTime) {
+  return 2*(fatTime & 0X1F);
+}
+/** Default date for file timestamps is 1 Jan 2000 */
+uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
+/** Default time for file timestamp is 1 am */
+uint16_t const FAT_DEFAULT_TIME = (1 << 11);
+//------------------------------------------------------------------------------
+/**
+ * \class SdBaseFile
+ * \brief Base class for SdFile with Print and C++ streams.
+ */
+class SdBaseFile {
+ public:
+  /** Create an instance. */
+  SdBaseFile() : writeError(false), type_(FAT_FILE_TYPE_CLOSED) {}
+  SdBaseFile(const char* path, uint8_t oflag);
+  ~SdBaseFile() {if(isOpen()) close();}
+  /**
+   * writeError is set to true if an error occurs during a write().
+   * Set writeError to false before calling print() and/or write() and check
+   * for true after calls to print() and/or write().
+   */
+  bool writeError;
+  //----------------------------------------------------------------------------
+  // helpers for stream classes
+  /** get position for streams
+   * \param[out] pos struct to receive position
+   */
+  void getpos(fpos_t* pos);
+  /** set position for streams
+   * \param[out] pos struct with value for new position
+   */
+  void setpos(fpos_t* pos);
+  //----------------------------------------------------------------------------
+  bool close();
+  bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
+  bool createContiguous(SdBaseFile* dirFile,
+          const char* path, uint32_t size);
+  /** \return The current cluster number for a file or directory. */
+  uint32_t curCluster() const {return curCluster_;}
+  /** \return The current position for a file or directory. */
+  uint32_t curPosition() const {return curPosition_;}
+  /** \return Current working directory */
+  static SdBaseFile* cwd() {return cwd_;}
+  /** Set the date/time callback function
+   *
+   * \param[in] dateTime The user's call back function.  The callback
+   * function is of the form:
+   *
+   * \code
+   * void dateTime(uint16_t* date, uint16_t* time) {
+   *   uint16_t year;
+   *   uint8_t month, day, hour, minute, second;
+   *
+   *   // User gets date and time from GPS or real-time clock here
+   *
+   *   // return date using FAT_DATE macro to format fields
+   *   *date = FAT_DATE(year, month, day);
+   *
+   *   // return time using FAT_TIME macro to format fields
+   *   *time = FAT_TIME(hour, minute, second);
+   * }
+   * \endcode
+   *
+   * Sets the function that is called when a file is created or when
+   * a file's directory entry is modified by sync(). All timestamps,
+   * access, creation, and modify, are set when a file is created.
+   * sync() maintains the last access date and last modify date/time.
+   *
+   * See the timestamp() function.
+   */
+  static void dateTimeCallback(
+    void (*dateTime)(uint16_t* date, uint16_t* time)) {
+    dateTime_ = dateTime;
+  }
+  /**  Cancel the date/time callback function. */
+  static void dateTimeCallbackCancel() {dateTime_ = 0;}
+  bool dirEntry(dir_t* dir);
+  static void dirName(const dir_t& dir, char* name);
+  bool exists(const char* name);
+  int16_t fgets(char* str, int16_t num, char* delim = 0);
+  /** \return The total number of bytes in a file or directory. */
+  uint32_t fileSize() const {return fileSize_;}
+  /** \return The first cluster number for a file or directory. */
+  uint32_t firstCluster() const {return firstCluster_;}
+  bool getFilename(char* name);
+  /** \return True if this is a directory else false. */
+  bool isDir() const {return type_ >= FAT_FILE_TYPE_MIN_DIR;}
+  /** \return True if this is a normal file else false. */
+  bool isFile() const {return type_ == FAT_FILE_TYPE_NORMAL;}
+  /** \return True if this is an open file/directory else false. */
+  bool isOpen() const {return type_ != FAT_FILE_TYPE_CLOSED;}
+  /** \return True if this is a subdirectory else false. */
+  bool isSubDir() const {return type_ == FAT_FILE_TYPE_SUBDIR;}
+  /** \return True if this is the root directory. */
+  bool isRoot() const {
+    return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32;
+  }
+  void ls( uint8_t flags = 0, uint8_t indent = 0);
+  bool mkdir(SdBaseFile* dir, const char* path, bool pFlag = true);
+  // alias for backward compactability
+  bool makeDir(SdBaseFile* dir, const char* path) {
+    return mkdir(dir, path, false);
+  }
+  bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
+  bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
+  bool open(const char* path, uint8_t oflag = O_READ);
+  bool openNext(SdBaseFile* dirFile, uint8_t oflag);
+  bool openRoot(SdVolume* vol);
+  int peek();
+  static void printFatDate(uint16_t fatDate);
+  static void printFatTime( uint16_t fatTime);
+  bool printName();
+  int16_t read();
+  int16_t read(void* buf, uint16_t nbyte);
+  int8_t readDir(dir_t* dir, char* longFilename);
+  static bool remove(SdBaseFile* dirFile, const char* path);
+  bool remove();
+  /** Set the file's current position to zero. */
+  void rewind() {seekSet(0);}
+  bool rename(SdBaseFile* dirFile, const char* newPath);
+  bool rmdir();
+  // for backward compatibility
+  bool rmDir() {return rmdir();}
+  bool rmRfStar();
+  /** Set the files position to current position + \a pos. See seekSet().
+   * \param[in] offset The new position in bytes from the current position.
+   * \return true for success or false for failure.
+   */
+  bool seekCur(int32_t offset) {
+    return seekSet(curPosition_ + offset);
+  }
+  /** Set the files position to end-of-file + \a offset. See seekSet().
+   * \param[in] offset The new position in bytes from end-of-file.
+   * \return true for success or false for failure.
+   */
+  bool seekEnd(int32_t offset = 0) {return seekSet(fileSize_ + offset);}
+  bool seekSet(uint32_t pos);
+  bool sync();
+  bool timestamp(SdBaseFile* file);
+  bool timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,
+          uint8_t hour, uint8_t minute, uint8_t second);
+  /** Type of file.  You should use isFile() or isDir() instead of type()
+   * if possible.
+   *
+   * \return The file or directory type.
+   */
+  uint8_t type() const {return type_;}
+  bool truncate(uint32_t size);
+  /** \return SdVolume that contains this file. */
+  SdVolume* volume() const {return vol_;}
+  int16_t write(const void* buf, uint16_t nbyte);
+//------------------------------------------------------------------------------
+ private:
+  // allow SdFat to set cwd_
+  friend class SdFat;
+  // global pointer to cwd dir
+  static SdBaseFile* cwd_;
+  // data time callback function
+  static void (*dateTime_)(uint16_t* date, uint16_t* time);
+  // bits defined in flags_
+  // should be 0X0F
+  static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);
+  // sync of directory entry required
+  static uint8_t const F_FILE_DIR_DIRTY = 0X80;
+
+  // private data
+  uint8_t   flags_;         // See above for definition of flags_ bits
+  uint8_t   fstate_;        // error and eof indicator
+  uint8_t   type_;          // type of file see above for values
+  uint32_t  curCluster_;    // cluster for current file position
+  uint32_t  curPosition_;   // current file position in bytes from beginning
+  uint32_t  dirBlock_;      // block for this files directory entry
+  uint8_t   dirIndex_;      // index of directory entry in dirBlock
+  uint32_t  fileSize_;      // file size in bytes
+  uint32_t  firstCluster_;  // first cluster of file
+  SdVolume* vol_;           // volume where file is located
+
+  /** experimental don't use */
+  bool openParent(SdBaseFile* dir);
+  // private functions
+  bool addCluster();
+  bool addDirCluster();
+  dir_t* cacheDirEntry(uint8_t action);
+  int8_t lsPrintNext( uint8_t flags, uint8_t indent);
+  static bool make83Name(const char* str, uint8_t* name, const char** ptr);
+  bool mkdir(SdBaseFile* parent, const uint8_t dname[11]);
+  bool open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag);
+  bool openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
+  dir_t* readDirCache();
+//------------------------------------------------------------------------------
+// to be deleted
+  static void printDirName( const dir_t& dir,
+    uint8_t width, bool printSlash);
+//------------------------------------------------------------------------------
+// Deprecated functions  - suppress cpplint warnings with NOLINT comment
+#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
+ public:
+  /** \deprecated Use:
+   * bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
+   * \param[out] bgnBlock the first block address for the file.
+   * \param[out] endBlock the last  block address for the file.
+   * \return true for success or false for failure.
+   */
+  bool contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) {  // NOLINT
+    return contiguousRange(&bgnBlock, &endBlock);
+  }
+ /** \deprecated Use:
+   * bool createContiguous(SdBaseFile* dirFile,
+   *   const char* path, uint32_t size)
+   * \param[in] dirFile The directory where the file will be created.
+   * \param[in] path A path with a valid DOS 8.3 file name.
+   * \param[in] size The desired file size.
+   * \return true for success or false for failure.
+   */
+  bool createContiguous(SdBaseFile& dirFile,  // NOLINT
+    const char* path, uint32_t size) {
+    return createContiguous(&dirFile, path, size);
+  }
+  /** \deprecated Use:
+   * static void dateTimeCallback(
+   *   void (*dateTime)(uint16_t* date, uint16_t* time));
+   * \param[in] dateTime The user's call back function.
+   */
+  static void dateTimeCallback(
+    void (*dateTime)(uint16_t& date, uint16_t& time)) {  // NOLINT
+    oldDateTime_ = dateTime;
+    dateTime_ = dateTime ? oldToNew : 0;
+  }
+  /** \deprecated Use: bool dirEntry(dir_t* dir);
+   * \param[out] dir Location for return of the file's directory entry.
+   * \return true for success or false for failure.
+   */
+  bool dirEntry(dir_t& dir) {return dirEntry(&dir);}  // NOLINT
+  /** \deprecated Use:
+   * bool mkdir(SdBaseFile* dir, const char* path);
+   * \param[in] dir An open SdFat instance for the directory that will contain
+   * the new directory.
+   * \param[in] path A path with a valid 8.3 DOS name for the new directory.
+   * \return true for success or false for failure.
+   */
+  bool mkdir(SdBaseFile& dir, const char* path) {  // NOLINT
+    return mkdir(&dir, path);
+  }
+  /** \deprecated Use:
+   * bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
+   * \param[in] dirFile An open SdFat instance for the directory containing the
+   * file to be opened.
+   * \param[in] path A path with a valid 8.3 DOS name for the file.
+   * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
+   * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
+   * \return true for success or false for failure.
+   */
+  bool open(SdBaseFile& dirFile, // NOLINT
+    const char* path, uint8_t oflag) {
+    return open(&dirFile, path, oflag);
+  }
+  /** \deprecated  Do not use in new apps
+   * \param[in] dirFile An open SdFat instance for the directory containing the
+   * file to be opened.
+   * \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
+   * \return true for success or false for failure.
+   */
+  bool open(SdBaseFile& dirFile, const char* path) {  // NOLINT
+    return open(dirFile, path, O_RDWR);
+  }
+  /** \deprecated Use:
+   * bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
+   * \param[in] dirFile An open SdFat instance for the directory.
+   * \param[in] index The \a index of the directory entry for the file to be
+   * opened.  The value for \a index is (directory file position)/32.
+   * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
+   * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
+   * \return true for success or false for failure.
+   */
+  bool open(SdBaseFile& dirFile, uint16_t index, uint8_t oflag) {  // NOLINT
+    return open(&dirFile, index, oflag);
+  }
+  /** \deprecated Use: bool openRoot(SdVolume* vol);
+   * \param[in] vol The FAT volume containing the root directory to be opened.
+   * \return true for success or false for failure.
+   */
+  bool openRoot(SdVolume& vol) {return openRoot(&vol);}  // NOLINT
+  /** \deprecated Use: int8_t readDir(dir_t* dir);
+   * \param[out] dir The dir_t struct that will receive the data.
+   * \return bytes read for success zero for eof or -1 for failure.
+   */
+  int8_t readDir(dir_t& dir, char* longFilename) {return readDir(&dir, longFilename);}  // NOLINT
+  /** \deprecated Use:
+   * static uint8_t remove(SdBaseFile* dirFile, const char* path);
+   * \param[in] dirFile The directory that contains the file.
+   * \param[in] path The name of the file to be removed.
+   * \return true for success or false for failure.
+   */
+  static bool remove(SdBaseFile& dirFile, const char* path) {  // NOLINT
+    return remove(&dirFile, path);
+  }
+//------------------------------------------------------------------------------
+// rest are private
+ private:
+  static void (*oldDateTime_)(uint16_t& date, uint16_t& time);  // NOLINT
+  static void oldToNew(uint16_t* date, uint16_t* time) {
+    uint16_t d;
+    uint16_t t;
+    oldDateTime_(d, t);
+    *date = d;
+    *time = t;
+  }
+#endif  // ALLOW_DEPRECATED_FUNCTIONS
+};
+
+#endif  // SdBaseFile_h
+#endif

+ 121 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdFatConfig.h

@@ -0,0 +1,121 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+/**
+ * \file
+ * \brief configuration definitions
+ */
+#include "Marlin.h"
+#ifdef SDSUPPORT
+
+#ifndef SdFatConfig_h
+#define SdFatConfig_h
+#include <stdint.h>
+//------------------------------------------------------------------------------
+/**
+ * To use multiple SD cards set USE_MULTIPLE_CARDS nonzero.
+ *
+ * Using multiple cards costs 400 - 500  bytes of flash.
+ *
+ * Each card requires about 550 bytes of SRAM so use of a Mega is recommended.
+ */
+#define USE_MULTIPLE_CARDS 0
+//------------------------------------------------------------------------------
+/**
+ * Call flush for endl if ENDL_CALLS_FLUSH is nonzero
+ *
+ * The standard for iostreams is to call flush.  This is very costly for
+ * SdFat.  Each call to flush causes 2048 bytes of I/O to the SD.
+ *
+ * SdFat has a single 512 byte buffer for SD I/O so it must write the current
+ * data block to the SD, read the directory block from the SD, update the
+ * directory entry, write the directory block to the SD and read the data
+ * block back into the buffer.
+ *
+ * The SD flash memory controller is not designed for this many rewrites
+ * so performance may be reduced by more than a factor of 100.
+ *
+ * If ENDL_CALLS_FLUSH is zero, you must call flush and/or close to force
+ * all data to be written to the SD.
+ */
+#define ENDL_CALLS_FLUSH 0
+//------------------------------------------------------------------------------
+/**
+ * Allow use of deprecated functions if ALLOW_DEPRECATED_FUNCTIONS is nonzero
+ */
+#define ALLOW_DEPRECATED_FUNCTIONS 1
+//------------------------------------------------------------------------------
+/**
+ * Allow FAT12 volumes if FAT12_SUPPORT is nonzero.
+ * FAT12 has not been well tested.
+ */
+#define FAT12_SUPPORT 0
+//------------------------------------------------------------------------------
+/**
+ * SPI init rate for SD initialization commands. Must be 5 (F_CPU/64)
+ * or 6 (F_CPU/128).
+ */
+#define SPI_SD_INIT_RATE 5
+//------------------------------------------------------------------------------
+/**
+ * Set the SS pin high for hardware SPI.  If SS is chip select for another SPI
+ * device this will disable that device during the SD init phase.
+ */
+#define SET_SPI_SS_HIGH 1
+//------------------------------------------------------------------------------
+/**
+ * Define MEGA_SOFT_SPI nonzero to use software SPI on Mega Arduinos.
+ * Pins used are SS 10, MOSI 11, MISO 12, and SCK 13.
+ *
+ * MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used
+ * on Mega Arduinos.  Software SPI works well with GPS Shield V1.1
+ * but many SD cards will fail with GPS Shield V1.0.
+ */
+#define MEGA_SOFT_SPI 0
+//------------------------------------------------------------------------------
+/**
+ * Set USE_SOFTWARE_SPI nonzero to always use software SPI.
+ */
+#define USE_SOFTWARE_SPI 0
+// define software SPI pins so Mega can use unmodified 168/328 shields
+/** Software SPI chip select pin for the SD */
+uint8_t const SOFT_SPI_CS_PIN = 10;
+/** Software SPI Master Out Slave In pin */
+uint8_t const SOFT_SPI_MOSI_PIN = 11;
+/** Software SPI Master In Slave Out pin */
+uint8_t const SOFT_SPI_MISO_PIN = 12;
+/** Software SPI Clock pin */
+uint8_t const SOFT_SPI_SCK_PIN = 13;
+//------------------------------------------------------------------------------
+/**
+ * The __cxa_pure_virtual function is an error handler that is invoked when
+ * a pure virtual function is called.
+ */
+#define USE_CXA_PURE_VIRTUAL 1
+/**
+ * Defines for long (vfat) filenames
+ */
+/** Number of VFAT entries used. Every entry has 13 UTF-16 characters */
+#define MAX_VFAT_ENTRIES (2)
+/** Total size of the buffer used to store the long filenames */
+#define LONG_FILENAME_LENGTH (13*MAX_VFAT_ENTRIES+1)
+#endif  // SdFatConfig_h
+
+
+#endif

+ 646 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdFatStructs.h

@@ -0,0 +1,646 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#include "Marlin.h"
+#ifdef SDSUPPORT
+
+#ifndef SdFatStructs_h
+#define SdFatStructs_h
+
+#define PACKED __attribute__((__packed__))
+/**
+ * \file
+ * \brief FAT file structures
+ */
+/*
+ * mostly from Microsoft document fatgen103.doc
+ * http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
+ */
+//------------------------------------------------------------------------------
+/** Value for byte 510 of boot block or MBR */
+uint8_t const BOOTSIG0 = 0X55;
+/** Value for byte 511 of boot block or MBR */
+uint8_t const BOOTSIG1 = 0XAA;
+/** Value for bootSignature field int FAT/FAT32 boot sector */
+uint8_t const EXTENDED_BOOT_SIG = 0X29;
+//------------------------------------------------------------------------------
+/**
+ * \struct partitionTable
+ * \brief MBR partition table entry
+ *
+ * A partition table entry for a MBR formatted storage device.
+ * The MBR partition table has four entries.
+ */
+struct partitionTable {
+          /**
+           * Boot Indicator . Indicates whether the volume is the active
+           * partition.  Legal values include: 0X00. Do not use for booting.
+           * 0X80 Active partition.
+           */
+  uint8_t  boot;
+          /**
+            * Head part of Cylinder-head-sector address of the first block in
+            * the partition. Legal values are 0-255. Only used in old PC BIOS.
+            */
+  uint8_t  beginHead;
+          /**
+           * Sector part of Cylinder-head-sector address of the first block in
+           * the partition. Legal values are 1-63. Only used in old PC BIOS.
+           */
+  unsigned beginSector : 6;
+           /** High bits cylinder for first block in partition. */
+  unsigned beginCylinderHigh : 2;
+          /**
+           * Combine beginCylinderLow with beginCylinderHigh. Legal values
+           * are 0-1023.  Only used in old PC BIOS.
+           */
+  uint8_t  beginCylinderLow;
+          /**
+           * Partition type. See defines that begin with PART_TYPE_ for
+           * some Microsoft partition types.
+           */
+  uint8_t  type;
+          /**
+           * head part of cylinder-head-sector address of the last sector in the
+           * partition.  Legal values are 0-255. Only used in old PC BIOS.
+           */
+  uint8_t  endHead;
+          /**
+           * Sector part of cylinder-head-sector address of the last sector in
+           * the partition.  Legal values are 1-63. Only used in old PC BIOS.
+           */
+  unsigned endSector : 6;
+           /** High bits of end cylinder */
+  unsigned endCylinderHigh : 2;
+          /**
+           * Combine endCylinderLow with endCylinderHigh. Legal values
+           * are 0-1023.  Only used in old PC BIOS.
+           */
+  uint8_t  endCylinderLow;
+           /** Logical block address of the first block in the partition. */
+  uint32_t firstSector;
+           /** Length of the partition, in blocks. */
+  uint32_t totalSectors;
+} PACKED;
+/** Type name for partitionTable */
+typedef struct partitionTable part_t;
+//------------------------------------------------------------------------------
+/**
+ * \struct masterBootRecord
+ *
+ * \brief Master Boot Record
+ *
+ * The first block of a storage device that is formatted with a MBR.
+ */
+struct masterBootRecord {
+           /** Code Area for master boot program. */
+  uint8_t  codeArea[440];
+           /** Optional Windows NT disk signature. May contain boot code. */
+  uint32_t diskSignature;
+           /** Usually zero but may be more boot code. */
+  uint16_t usuallyZero;
+           /** Partition tables. */
+  part_t   part[4];
+           /** First MBR signature byte. Must be 0X55 */
+  uint8_t  mbrSig0;
+           /** Second MBR signature byte. Must be 0XAA */
+  uint8_t  mbrSig1;
+} PACKED;
+/** Type name for masterBootRecord */
+typedef struct masterBootRecord mbr_t;
+//------------------------------------------------------------------------------
+/**
+ * \struct fat_boot
+ *
+ * \brief Boot sector for a FAT12/FAT16 volume.
+ *
+ */
+struct fat_boot {
+         /**
+          * The first three bytes of the boot sector must be valid,
+          * executable x 86-based CPU instructions. This includes a
+          * jump instruction that skips the next nonexecutable bytes.
+          */
+  uint8_t jump[3];
+         /**
+          * This is typically a string of characters that identifies
+          * the operating system that formatted the volume.
+          */
+  char    oemId[8];
+          /**
+           * The size of a hardware sector. Valid decimal values for this
+           * field are 512, 1024, 2048, and 4096. For most disks used in
+           * the United States, the value of this field is 512.
+           */
+  uint16_t bytesPerSector;
+          /**
+           * Number of sectors per allocation unit. This value must be a
+           * power of 2 that is greater than 0. The legal values are
+           * 1, 2, 4, 8, 16, 32, 64, and 128.  128 should be avoided.
+           */
+  uint8_t  sectorsPerCluster;
+          /**
+           * The number of sectors preceding the start of the first FAT,
+           * including the boot sector. The value of this field is always 1.
+           */
+  uint16_t reservedSectorCount;
+          /**
+           * The number of copies of the FAT on the volume.
+           * The value of this field is always 2.
+           */
+  uint8_t  fatCount;
+          /**
+           * For FAT12 and FAT16 volumes, this field contains the count of
+           * 32-byte directory entries in the root directory. For FAT32 volumes,
+           * this field must be set to 0. For FAT12 and FAT16 volumes, this
+           * value should always specify a count that when multiplied by 32
+           * results in a multiple of bytesPerSector.  FAT16 volumes should
+           * use the value 512.
+           */
+  uint16_t rootDirEntryCount;
+          /**
+           * This field is the old 16-bit total count of sectors on the volume.
+           * This count includes the count of all sectors in all four regions
+           * of the volume. This field can be 0; if it is 0, then totalSectors32
+           * must be nonzero.  For FAT32 volumes, this field must be 0. For
+           * FAT12 and FAT16 volumes, this field contains the sector count, and
+           * totalSectors32 is 0 if the total sector count fits
+           * (is less than 0x10000).
+           */
+  uint16_t totalSectors16;
+          /**
+           * This dates back to the old MS-DOS 1.x media determination and is
+           * no longer usually used for anything.  0xF8 is the standard value
+           * for fixed (nonremovable) media. For removable media, 0xF0 is
+           * frequently used. Legal values are 0xF0 or 0xF8-0xFF.
+           */
+  uint8_t  mediaType;
+          /**
+           * Count of sectors occupied by one FAT on FAT12/FAT16 volumes.
+           * On FAT32 volumes this field must be 0, and sectorsPerFat32
+           * contains the FAT size count.
+           */
+  uint16_t sectorsPerFat16;
+           /** Sectors per track for interrupt 0x13. Not used otherwise. */
+  uint16_t sectorsPerTrack;
+           /** Number of heads for interrupt 0x13.  Not used otherwise. */
+  uint16_t headCount;
+          /**
+           * Count of hidden sectors preceding the partition that contains this
+           * FAT volume. This field is generally only relevant for media
+           * visible on interrupt 0x13.
+           */
+  uint32_t hidddenSectors;
+          /**
+           * This field is the new 32-bit total count of sectors on the volume.
+           * This count includes the count of all sectors in all four regions
+           * of the volume.  This field can be 0; if it is 0, then
+           * totalSectors16 must be nonzero.
+           */
+  uint32_t totalSectors32;
+           /**
+            * Related to the BIOS physical drive number. Floppy drives are
+            * identified as 0x00 and physical hard disks are identified as
+            * 0x80, regardless of the number of physical disk drives.
+            * Typically, this value is set prior to issuing an INT 13h BIOS
+            * call to specify the device to access. The value is only
+            * relevant if the device is a boot device.
+            */
+  uint8_t  driveNumber;
+           /** used by Windows NT - should be zero for FAT */
+  uint8_t  reserved1;
+           /** 0X29 if next three fields are valid */
+  uint8_t  bootSignature;
+           /**
+            * A random serial number created when formatting a disk,
+            * which helps to distinguish between disks.
+            * Usually generated by combining date and time.
+            */
+  uint32_t volumeSerialNumber;
+           /**
+            * A field once used to store the volume label. The volume label
+            * is now stored as a special file in the root directory.
+            */
+  char     volumeLabel[11];
+           /**
+            * A field with a value of either FAT, FAT12 or FAT16,
+            * depending on the disk format.
+            */
+  char     fileSystemType[8];
+           /** X86 boot code */
+  uint8_t  bootCode[448];
+           /** must be 0X55 */
+  uint8_t  bootSectorSig0;
+           /** must be 0XAA */
+  uint8_t  bootSectorSig1;
+} PACKED;
+/** Type name for FAT Boot Sector */
+typedef struct fat_boot fat_boot_t;
+//------------------------------------------------------------------------------
+/**
+ * \struct fat32_boot
+ *
+ * \brief Boot sector for a FAT32 volume.
+ *
+ */
+struct fat32_boot {
+         /**
+          * The first three bytes of the boot sector must be valid,
+          * executable x 86-based CPU instructions. This includes a
+          * jump instruction that skips the next nonexecutable bytes.
+          */
+  uint8_t jump[3];
+         /**
+          * This is typically a string of characters that identifies
+          * the operating system that formatted the volume.
+          */
+  char    oemId[8];
+          /**
+           * The size of a hardware sector. Valid decimal values for this
+           * field are 512, 1024, 2048, and 4096. For most disks used in
+           * the United States, the value of this field is 512.
+           */
+  uint16_t bytesPerSector;
+          /**
+           * Number of sectors per allocation unit. This value must be a
+           * power of 2 that is greater than 0. The legal values are
+           * 1, 2, 4, 8, 16, 32, 64, and 128.  128 should be avoided.
+           */
+  uint8_t  sectorsPerCluster;
+          /**
+           * The number of sectors preceding the start of the first FAT,
+           * including the boot sector. Must not be zero
+           */
+  uint16_t reservedSectorCount;
+          /**
+           * The number of copies of the FAT on the volume.
+           * The value of this field is always 2.
+           */
+  uint8_t  fatCount;
+          /**
+           * FAT12/FAT16 only. For FAT32 volumes, this field must be set to 0.
+           */
+  uint16_t rootDirEntryCount;
+          /**
+           * For FAT32 volumes, this field must be 0.
+           */
+  uint16_t totalSectors16;
+          /**
+           * This dates back to the old MS-DOS 1.x media determination and is
+           * no longer usually used for anything.  0xF8 is the standard value
+           * for fixed (nonremovable) media. For removable media, 0xF0 is
+           * frequently used. Legal values are 0xF0 or 0xF8-0xFF.
+           */
+  uint8_t  mediaType;
+          /**
+           * On FAT32 volumes this field must be 0, and sectorsPerFat32
+           * contains the FAT size count.
+           */
+  uint16_t sectorsPerFat16;
+           /** Sectors per track for interrupt 0x13. Not used otherwise. */
+  uint16_t sectorsPerTrack;
+           /** Number of heads for interrupt 0x13.  Not used otherwise. */
+  uint16_t headCount;
+          /**
+           * Count of hidden sectors preceding the partition that contains this
+           * FAT volume. This field is generally only relevant for media
+           * visible on interrupt 0x13.
+           */
+  uint32_t hidddenSectors;
+          /**
+           * Contains the total number of sectors in the FAT32 volume.
+           */
+  uint32_t totalSectors32;
+         /**
+           * Count of sectors occupied by one FAT on FAT32 volumes.
+           */
+  uint32_t sectorsPerFat32;
+          /**
+           * This field is only defined for FAT32 media and does not exist on
+           * FAT12 and FAT16 media.
+           * Bits 0-3 -- Zero-based number of active FAT.
+           *             Only valid if mirroring is disabled.
+           * Bits 4-6 -- Reserved.
+           * Bit 7	-- 0 means the FAT is mirrored at runtime into all FATs.
+	         *        -- 1 means only one FAT is active; it is the one referenced
+	         *             in bits 0-3.
+           * Bits 8-15 	-- Reserved.
+           */
+  uint16_t fat32Flags;
+          /**
+           * FAT32 version. High byte is major revision number.
+           * Low byte is minor revision number. Only 0.0 define.
+           */
+  uint16_t fat32Version;
+          /**
+           * Cluster number of the first cluster of the root directory for FAT32.
+           * This usually 2 but not required to be 2.
+           */
+  uint32_t fat32RootCluster;
+          /**
+           * Sector number of FSINFO structure in the reserved area of the
+           * FAT32 volume. Usually 1.
+           */
+  uint16_t fat32FSInfo;
+          /**
+           * If nonzero, indicates the sector number in the reserved area
+           * of the volume of a copy of the boot record. Usually 6.
+           * No value other than 6 is recommended.
+           */
+  uint16_t fat32BackBootBlock;
+          /**
+           * Reserved for future expansion. Code that formats FAT32 volumes
+           * should always set all of the bytes of this field to 0.
+           */
+  uint8_t  fat32Reserved[12];
+           /**
+            * Related to the BIOS physical drive number. Floppy drives are
+            * identified as 0x00 and physical hard disks are identified as
+            * 0x80, regardless of the number of physical disk drives.
+            * Typically, this value is set prior to issuing an INT 13h BIOS
+            * call to specify the device to access. The value is only
+            * relevant if the device is a boot device.
+            */
+  uint8_t  driveNumber;
+           /** used by Windows NT - should be zero for FAT */
+  uint8_t  reserved1;
+           /** 0X29 if next three fields are valid */
+  uint8_t  bootSignature;
+           /**
+            * A random serial number created when formatting a disk,
+            * which helps to distinguish between disks.
+            * Usually generated by combining date and time.
+            */
+  uint32_t volumeSerialNumber;
+           /**
+            * A field once used to store the volume label. The volume label
+            * is now stored as a special file in the root directory.
+            */
+  char     volumeLabel[11];
+           /**
+            * A text field with a value of FAT32.
+            */
+  char     fileSystemType[8];
+           /** X86 boot code */
+  uint8_t  bootCode[420];
+           /** must be 0X55 */
+  uint8_t  bootSectorSig0;
+           /** must be 0XAA */
+  uint8_t  bootSectorSig1;
+} PACKED;
+/** Type name for FAT32 Boot Sector */
+typedef struct fat32_boot fat32_boot_t;
+//------------------------------------------------------------------------------
+/** Lead signature for a FSINFO sector */
+uint32_t const FSINFO_LEAD_SIG = 0x41615252;
+/** Struct signature for a FSINFO sector */
+uint32_t const FSINFO_STRUCT_SIG = 0x61417272;
+/**
+ * \struct fat32_fsinfo
+ *
+ * \brief FSINFO sector for a FAT32 volume.
+ *
+ */
+struct fat32_fsinfo {
+           /** must be 0X52, 0X52, 0X61, 0X41 */
+  uint32_t  leadSignature;
+           /** must be zero */
+  uint8_t  reserved1[480];
+           /** must be 0X72, 0X72, 0X41, 0X61 */
+  uint32_t  structSignature;
+          /**
+           * Contains the last known free cluster count on the volume.
+           * If the value is 0xFFFFFFFF, then the free count is unknown
+           * and must be computed. Any other value can be used, but is
+           * not necessarily correct. It should be range checked at least
+           * to make sure it is <= volume cluster count.
+           */
+  uint32_t freeCount;
+          /**
+           * This is a hint for the FAT driver. It indicates the cluster
+           * number at which the driver should start looking for free clusters.
+           * If the value is 0xFFFFFFFF, then there is no hint and the driver
+           * should start looking at cluster 2.
+           */
+  uint32_t nextFree;
+           /** must be zero */
+  uint8_t  reserved2[12];
+           /** must be 0X00, 0X00, 0X55, 0XAA */
+  uint8_t  tailSignature[4];
+} PACKED;
+/** Type name for FAT32 FSINFO Sector */
+typedef struct fat32_fsinfo fat32_fsinfo_t;
+//------------------------------------------------------------------------------
+// End Of Chain values for FAT entries
+/** FAT12 end of chain value used by Microsoft. */
+uint16_t const FAT12EOC = 0XFFF;
+/** Minimum value for FAT12 EOC.  Use to test for EOC. */
+uint16_t const FAT12EOC_MIN = 0XFF8;
+/** FAT16 end of chain value used by Microsoft. */
+uint16_t const FAT16EOC = 0XFFFF;
+/** Minimum value for FAT16 EOC.  Use to test for EOC. */
+uint16_t const FAT16EOC_MIN = 0XFFF8;
+/** FAT32 end of chain value used by Microsoft. */
+uint32_t const FAT32EOC = 0X0FFFFFFF;
+/** Minimum value for FAT32 EOC.  Use to test for EOC. */
+uint32_t const FAT32EOC_MIN = 0X0FFFFFF8;
+/** Mask a for FAT32 entry. Entries are 28 bits. */
+uint32_t const FAT32MASK = 0X0FFFFFFF;
+//------------------------------------------------------------------------------
+/**
+ * \struct directoryEntry
+ * \brief FAT short directory entry
+ *
+ * Short means short 8.3 name, not the entry size.
+ *  
+ * Date Format. A FAT directory entry date stamp is a 16-bit field that is 
+ * basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the
+ * format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the 
+ * 16-bit word):
+ *   
+ * Bits 9-15: Count of years from 1980, valid value range 0-127 
+ * inclusive (1980-2107).
+ *   
+ * Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive.
+ *
+ * Bits 0-4: Day of month, valid value range 1-31 inclusive.
+ *
+ * Time Format. A FAT directory entry time stamp is a 16-bit field that has
+ * a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the 
+ * 16-bit word, bit 15 is the MSB of the 16-bit word).
+ *   
+ * Bits 11-15: Hours, valid value range 0-23 inclusive.
+ * 
+ * Bits 5-10: Minutes, valid value range 0-59 inclusive.
+ *      
+ * Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds).
+ *   
+ * The valid time range is from Midnight 00:00:00 to 23:59:58.
+ */
+struct directoryEntry {
+           /** Short 8.3 name.
+            *
+            * The first eight bytes contain the file name with blank fill.
+            * The last three bytes contain the file extension with blank fill.
+            */
+  uint8_t  name[11];
+          /** Entry attributes.
+           *
+           * The upper two bits of the attribute byte are reserved and should
+           * always be set to 0 when a file is created and never modified or
+           * looked at after that.  See defines that begin with DIR_ATT_.
+           */
+  uint8_t  attributes;
+          /**
+           * Reserved for use by Windows NT. Set value to 0 when a file is
+           * created and never modify or look at it after that.
+           */
+  uint8_t  reservedNT;
+          /**
+           * The granularity of the seconds part of creationTime is 2 seconds
+           * so this field is a count of tenths of a second and its valid
+           * value range is 0-199 inclusive. (WHG note - seems to be hundredths)
+           */
+  uint8_t  creationTimeTenths;
+           /** Time file was created. */
+  uint16_t creationTime;
+           /** Date file was created. */
+  uint16_t creationDate;
+          /**
+           * Last access date. Note that there is no last access time, only
+           * a date.  This is the date of last read or write. In the case of
+           * a write, this should be set to the same date as lastWriteDate.
+           */
+  uint16_t lastAccessDate;
+          /**
+           * High word of this entry's first cluster number (always 0 for a
+           * FAT12 or FAT16 volume).
+           */
+  uint16_t firstClusterHigh;
+           /** Time of last write. File creation is considered a write. */
+  uint16_t lastWriteTime;
+           /** Date of last write. File creation is considered a write. */
+  uint16_t lastWriteDate;
+           /** Low word of this entry's first cluster number. */
+  uint16_t firstClusterLow;
+           /** 32-bit unsigned holding this file's size in bytes. */
+  uint32_t fileSize;
+} PACKED;
+/**
+ * \struct directoryVFATEntry
+ * \brief VFAT long filename directory entry
+ *
+ * directoryVFATEntries are found in the same list as normal directoryEntry.
+ * But have the attribute field set to DIR_ATT_LONG_NAME.
+ * 
+ * Long filenames are saved in multiple directoryVFATEntries.
+ * Each entry containing 13 UTF-16 characters.
+ */
+struct directoryVFATEntry {
+  /**
+   * Sequence number. Consists of 2 parts:
+   *  bit 6:   indicates first long filename block for the next file
+   *  bit 0-4: the position of this long filename block (first block is 1)
+   */
+  uint8_t  sequenceNumber;
+  /** First set of UTF-16 characters */
+  uint16_t name1[5];//UTF-16
+  /** attributes (at the same location as in directoryEntry), always 0x0F */
+  uint8_t  attributes;
+  /** Reserved for use by Windows NT. Always 0. */
+  uint8_t  reservedNT;
+  /** Checksum of the short 8.3 filename, can be used to checked if the file system as modified by a not-long-filename aware implementation. */
+  uint8_t  checksum;
+  /** Second set of UTF-16 characters */
+  uint16_t name2[6];//UTF-16
+  /** firstClusterLow is always zero for longFilenames */
+  uint16_t firstClusterLow;
+  /** Third set of UTF-16 characters */
+  uint16_t name3[2];//UTF-16
+} PACKED;
+//------------------------------------------------------------------------------
+// Definitions for directory entries
+//
+/** Type name for directoryEntry */
+typedef struct directoryEntry dir_t;
+/** Type name for directoryVFATEntry */
+typedef struct directoryVFATEntry vfat_t;
+/** escape for name[0] = 0XE5 */
+uint8_t const DIR_NAME_0XE5 = 0X05;
+/** name[0] value for entry that is free after being "deleted" */
+uint8_t const DIR_NAME_DELETED = 0XE5;
+/** name[0] value for entry that is free and no allocated entries follow */
+uint8_t const DIR_NAME_FREE = 0X00;
+/** file is read-only */
+uint8_t const DIR_ATT_READ_ONLY = 0X01;
+/** File should hidden in directory listings */
+uint8_t const DIR_ATT_HIDDEN = 0X02;
+/** Entry is for a system file */
+uint8_t const DIR_ATT_SYSTEM = 0X04;
+/** Directory entry contains the volume label */
+uint8_t const DIR_ATT_VOLUME_ID = 0X08;
+/** Entry is for a directory */
+uint8_t const DIR_ATT_DIRECTORY = 0X10;
+/** Old DOS archive bit for backup support */
+uint8_t const DIR_ATT_ARCHIVE = 0X20;
+/** Test value for long name entry.  Test is
+  (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */
+uint8_t const DIR_ATT_LONG_NAME = 0X0F;
+/** Test mask for long name entry */
+uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F;
+/** defined attribute bits */
+uint8_t const DIR_ATT_DEFINED_BITS = 0X3F;
+/** Directory entry is part of a long name
+ * \param[in] dir Pointer to a directory entry.
+ *
+ * \return true if the entry is for part of a long name else false.
+ */
+static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) {
+  return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME;
+}
+/** Mask for file/subdirectory tests */
+uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);
+/** Directory entry is for a file
+ * \param[in] dir Pointer to a directory entry.
+ *
+ * \return true if the entry is for a normal file else false.
+ */
+static inline uint8_t DIR_IS_FILE(const dir_t* dir) {
+  return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0;
+}
+/** Directory entry is for a subdirectory
+ * \param[in] dir Pointer to a directory entry.
+ *
+ * \return true if the entry is for a subdirectory else false.
+ */
+static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) {
+  return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY;
+}
+/** Directory entry is for a file or subdirectory
+ * \param[in] dir Pointer to a directory entry.
+ *
+ * \return true if the entry is for a normal file or subdirectory else false.
+ */
+static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) {
+  return (dir->attributes & DIR_ATT_VOLUME_ID) == 0;
+}
+#endif  // SdFatStructs_h
+
+
+#endif

+ 79 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdFatUtil.cpp

@@ -0,0 +1,79 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2008 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library 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 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 General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#include "Marlin.h"
+
+#ifdef SDSUPPORT
+#include "SdFatUtil.h"
+
+//------------------------------------------------------------------------------
+/** Amount of free RAM
+ * \return The number of free bytes.
+ */
+int SdFatUtil::FreeRam() {
+  extern int  __bss_end;
+  extern int* __brkval;
+  int free_memory;
+  if (reinterpret_cast<int>(__brkval) == 0) {
+    // if no heap use from end of bss section
+    free_memory = reinterpret_cast<int>(&free_memory)
+                  - reinterpret_cast<int>(&__bss_end);
+  } else {
+    // use from top of stack to heap
+    free_memory = reinterpret_cast<int>(&free_memory)
+                  - reinterpret_cast<int>(__brkval);
+  }
+  return free_memory;
+}
+//------------------------------------------------------------------------------
+/** %Print a string in flash memory.
+ *
+ * \param[in] pr Print object for output.
+ * \param[in] str Pointer to string stored in flash memory.
+ */
+void SdFatUtil::print_P( PGM_P str) {
+  for (uint8_t c; (c = pgm_read_byte(str)); str++) MYSERIAL.write(c);
+}
+//------------------------------------------------------------------------------
+/** %Print a string in flash memory followed by a CR/LF.
+ *
+ * \param[in] pr Print object for output.
+ * \param[in] str Pointer to string stored in flash memory.
+ */
+void SdFatUtil::println_P( PGM_P str) {
+  print_P( str);
+  MYSERIAL.println();
+}
+//------------------------------------------------------------------------------
+/** %Print a string in flash memory to Serial.
+ *
+ * \param[in] str Pointer to string stored in flash memory.
+ */
+void SdFatUtil::SerialPrint_P(PGM_P str) {
+  print_P(str);
+}
+//------------------------------------------------------------------------------
+/** %Print a string in flash memory to Serial followed by a CR/LF.
+ *
+ * \param[in] str Pointer to string stored in flash memory.
+ */
+void SdFatUtil::SerialPrintln_P(PGM_P str) {
+  println_P( str);
+}
+#endif

+ 48 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdFatUtil.h

@@ -0,0 +1,48 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2008 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library 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 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 General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#include "Marlin.h"
+#ifdef SDSUPPORT
+
+#ifndef SdFatUtil_h
+#define SdFatUtil_h
+/**
+ * \file
+ * \brief Useful utility functions.
+ */
+#include "Marlin.h"
+#include "MarlinSerial.h"
+/** Store and print a string in flash memory.*/
+#define PgmPrint(x) SerialPrint_P(PSTR(x))
+/** Store and print a string in flash memory followed by a CR/LF.*/
+#define PgmPrintln(x) SerialPrintln_P(PSTR(x))
+
+namespace SdFatUtil {
+  int FreeRam();
+  void print_P( PGM_P str);
+  void println_P( PGM_P str);
+  void SerialPrint_P(PGM_P str);
+  void SerialPrintln_P(PGM_P str);
+}
+
+using namespace SdFatUtil;  // NOLINT
+#endif  // #define SdFatUtil_h
+
+
+#endif

+ 95 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdFile.cpp

@@ -0,0 +1,95 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#include "Marlin.h"
+
+#ifdef SDSUPPORT
+#include "SdFile.h"
+/**  Create a file object and open it in the current working directory.
+ *
+ * \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
+ *
+ * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
+ * OR of open flags. see SdBaseFile::open(SdBaseFile*, const char*, uint8_t).
+ */
+SdFile::SdFile(const char* path, uint8_t oflag) : SdBaseFile(path, oflag) {
+}
+//------------------------------------------------------------------------------
+/** Write data to an open file.
+ *
+ * \note Data is moved to the cache but may not be written to the
+ * storage device until sync() is called.
+ *
+ * \param[in] buf Pointer to the location of the data to be written.
+ *
+ * \param[in] nbyte Number of bytes to write.
+ *
+ * \return For success write() returns the number of bytes written, always
+ * \a nbyte.  If an error occurs, write() returns -1.  Possible errors
+ * include write() is called before a file has been opened, write is called
+ * for a read-only file, device is full, a corrupt file system or an I/O error.
+ *
+ */
+int16_t SdFile::write(const void* buf, uint16_t nbyte) {
+  return SdBaseFile::write(buf, nbyte);
+}
+//------------------------------------------------------------------------------
+/** Write a byte to a file. Required by the Arduino Print class.
+ * \param[in] b the byte to be written.
+ * Use writeError to check for errors.
+ */
+#if ARDUINO >= 100
+size_t SdFile::write(uint8_t b)
+{
+    return SdBaseFile::write(&b, 1);
+}
+#else
+void SdFile::write(uint8_t b)
+{
+    SdBaseFile::write(&b, 1);
+}
+#endif
+//------------------------------------------------------------------------------
+/** Write a string to a file. Used by the Arduino Print class.
+ * \param[in] str Pointer to the string.
+ * Use writeError to check for errors.
+ */
+void SdFile::write(const char* str) {
+  SdBaseFile::write(str, strlen(str));
+}
+//------------------------------------------------------------------------------
+/** Write a PROGMEM string to a file.
+ * \param[in] str Pointer to the PROGMEM string.
+ * Use writeError to check for errors.
+ */
+void SdFile::write_P(PGM_P str) {
+  for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c);
+}
+//------------------------------------------------------------------------------
+/** Write a PROGMEM string followed by CR/LF to a file.
+ * \param[in] str Pointer to the PROGMEM string.
+ * Use writeError to check for errors.
+ */
+void SdFile::writeln_P(PGM_P str) {
+  write_P(str);
+  write_P(PSTR("\r\n"));
+}
+
+
+#endif

+ 54 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdFile.h

@@ -0,0 +1,54 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+/**
+ * \file
+ * \brief SdFile class
+ */
+#include "Marlin.h"
+
+#ifdef SDSUPPORT
+#include "SdBaseFile.h"
+#include <Print.h>
+#ifndef SdFile_h
+#define SdFile_h
+//------------------------------------------------------------------------------
+/**
+ * \class SdFile
+ * \brief SdBaseFile with Print.
+ */
+class SdFile : public SdBaseFile, public Print {
+ public:
+  SdFile() {}
+  SdFile(const char* name, uint8_t oflag);
+  #if ARDUINO >= 100
+      size_t write(uint8_t b);
+  #else
+   void write(uint8_t b);
+  #endif
+  
+  int16_t write(const void* buf, uint16_t nbyte);
+  void write(const char* str);
+  void write_P(PGM_P str);
+  void writeln_P(PGM_P str);
+};
+#endif  // SdFile_h
+
+
+#endif

+ 280 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdInfo.h

@@ -0,0 +1,280 @@
+/* Arduino Sd2Card Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ *
+ * This Library 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino Sd2Card Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#include "Marlin.h"
+#ifdef SDSUPPORT
+
+#ifndef SdInfo_h
+#define SdInfo_h
+#include <stdint.h>
+// Based on the document:
+//
+// SD Specifications
+// Part 1
+// Physical Layer
+// Simplified Specification
+// Version 3.01
+// May 18, 2010
+//
+// http://www.sdcard.org/developers/tech/sdcard/pls/simplified_specs
+//------------------------------------------------------------------------------
+// SD card commands
+/** GO_IDLE_STATE - init card in spi mode if CS low */
+uint8_t const CMD0 = 0X00;
+/** SEND_IF_COND - verify SD Memory Card interface operating condition.*/
+uint8_t const CMD8 = 0X08;
+/** SEND_CSD - read the Card Specific Data (CSD register) */
+uint8_t const CMD9 = 0X09;
+/** SEND_CID - read the card identification information (CID register) */
+uint8_t const CMD10 = 0X0A;
+/** STOP_TRANSMISSION - end multiple block read sequence */
+uint8_t const CMD12 = 0X0C;
+/** SEND_STATUS - read the card status register */
+uint8_t const CMD13 = 0X0D;
+/** READ_SINGLE_BLOCK - read a single data block from the card */
+uint8_t const CMD17 = 0X11;
+/** READ_MULTIPLE_BLOCK - read a multiple data blocks from the card */
+uint8_t const CMD18 = 0X12;
+/** WRITE_BLOCK - write a single data block to the card */
+uint8_t const CMD24 = 0X18;
+/** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */
+uint8_t const CMD25 = 0X19;
+/** ERASE_WR_BLK_START - sets the address of the first block to be erased */
+uint8_t const CMD32 = 0X20;
+/** ERASE_WR_BLK_END - sets the address of the last block of the continuous
+    range to be erased*/
+uint8_t const CMD33 = 0X21;
+/** ERASE - erase all previously selected blocks */
+uint8_t const CMD38 = 0X26;
+/** APP_CMD - escape for application specific command */
+uint8_t const CMD55 = 0X37;
+/** READ_OCR - read the OCR register of a card */
+uint8_t const CMD58 = 0X3A;
+/** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be
+     pre-erased before writing */
+uint8_t const ACMD23 = 0X17;
+/** SD_SEND_OP_COMD - Sends host capacity support information and
+    activates the card's initialization process */
+uint8_t const ACMD41 = 0X29;
+//------------------------------------------------------------------------------
+/** status for card in the ready state */
+uint8_t const R1_READY_STATE = 0X00;
+/** status for card in the idle state */
+uint8_t const R1_IDLE_STATE = 0X01;
+/** status bit for illegal command */
+uint8_t const R1_ILLEGAL_COMMAND = 0X04;
+/** start data token for read or write single block*/
+uint8_t const DATA_START_BLOCK = 0XFE;
+/** stop token for write multiple blocks*/
+uint8_t const STOP_TRAN_TOKEN = 0XFD;
+/** start data token for write multiple blocks*/
+uint8_t const WRITE_MULTIPLE_TOKEN = 0XFC;
+/** mask for data response tokens after a write block operation */
+uint8_t const DATA_RES_MASK = 0X1F;
+/** write data accepted token */
+uint8_t const DATA_RES_ACCEPTED = 0X05;
+//------------------------------------------------------------------------------
+/** Card IDentification (CID) register */
+typedef struct CID {
+  // byte 0
+  /** Manufacturer ID */
+  unsigned char mid;
+  // byte 1-2
+  /** OEM/Application ID */
+  char oid[2];
+  // byte 3-7
+  /** Product name */
+  char pnm[5];
+  // byte 8
+  /** Product revision least significant digit */
+  unsigned char prv_m : 4;
+  /** Product revision most significant digit */
+  unsigned char prv_n : 4;
+  // byte 9-12
+  /** Product serial number */
+  uint32_t psn;
+  // byte 13
+  /** Manufacturing date year low digit */
+  unsigned char mdt_year_high : 4;
+  /** not used */
+  unsigned char reserved : 4;
+  // byte 14
+  /** Manufacturing date month */
+  unsigned char mdt_month : 4;
+  /** Manufacturing date year low digit */
+  unsigned char mdt_year_low :4;
+  // byte 15
+  /** not used always 1 */
+  unsigned char always1 : 1;
+  /** CRC7 checksum */
+  unsigned char crc : 7;
+}cid_t;
+//------------------------------------------------------------------------------
+/** CSD for version 1.00 cards */
+typedef struct CSDV1 {
+  // byte 0
+  unsigned char reserved1 : 6;
+  unsigned char csd_ver : 2;
+  // byte 1
+  unsigned char taac;
+  // byte 2
+  unsigned char nsac;
+  // byte 3
+  unsigned char tran_speed;
+  // byte 4
+  unsigned char ccc_high;
+  // byte 5
+  unsigned char read_bl_len : 4;
+  unsigned char ccc_low : 4;
+  // byte 6
+  unsigned char c_size_high : 2;
+  unsigned char reserved2 : 2;
+  unsigned char dsr_imp : 1;
+  unsigned char read_blk_misalign :1;
+  unsigned char write_blk_misalign : 1;
+  unsigned char read_bl_partial : 1;
+  // byte 7
+  unsigned char c_size_mid;
+  // byte 8
+  unsigned char vdd_r_curr_max : 3;
+  unsigned char vdd_r_curr_min : 3;
+  unsigned char c_size_low :2;
+  // byte 9
+  unsigned char c_size_mult_high : 2;
+  unsigned char vdd_w_cur_max : 3;
+  unsigned char vdd_w_curr_min : 3;
+  // byte 10
+  unsigned char sector_size_high : 6;
+  unsigned char erase_blk_en : 1;
+  unsigned char c_size_mult_low : 1;
+  // byte 11
+  unsigned char wp_grp_size : 7;
+  unsigned char sector_size_low : 1;
+  // byte 12
+  unsigned char write_bl_len_high : 2;
+  unsigned char r2w_factor : 3;
+  unsigned char reserved3 : 2;
+  unsigned char wp_grp_enable : 1;
+  // byte 13
+  unsigned char reserved4 : 5;
+  unsigned char write_partial : 1;
+  unsigned char write_bl_len_low : 2;
+  // byte 14
+  unsigned char reserved5: 2;
+  unsigned char file_format : 2;
+  unsigned char tmp_write_protect : 1;
+  unsigned char perm_write_protect : 1;
+  unsigned char copy : 1;
+  /** Indicates the file format on the card */
+  unsigned char file_format_grp : 1;
+  // byte 15
+  unsigned char always1 : 1;
+  unsigned char crc : 7;
+}csd1_t;
+//------------------------------------------------------------------------------
+/** CSD for version 2.00 cards */
+typedef struct CSDV2 {
+  // byte 0
+  unsigned char reserved1 : 6;
+  unsigned char csd_ver : 2;
+  // byte 1
+  /** fixed to 0X0E */
+  unsigned char taac;
+  // byte 2
+  /** fixed to 0 */
+  unsigned char nsac;
+  // byte 3
+  unsigned char tran_speed;
+  // byte 4
+  unsigned char ccc_high;
+  // byte 5
+  /** This field is fixed to 9h, which indicates READ_BL_LEN=512 Byte */
+  unsigned char read_bl_len : 4;
+  unsigned char ccc_low : 4;
+  // byte 6
+  /** not used */
+  unsigned char reserved2 : 4;
+  unsigned char dsr_imp : 1;
+  /** fixed to 0 */
+  unsigned char read_blk_misalign :1;
+  /** fixed to 0 */
+  unsigned char write_blk_misalign : 1;
+  /** fixed to 0 - no partial read */
+  unsigned char read_bl_partial : 1;
+  // byte 7
+  /** not used */
+  unsigned char reserved3 : 2;
+  /** high part of card size */
+  unsigned char c_size_high : 6;
+  // byte 8
+  /** middle part of card size */
+  unsigned char c_size_mid;
+  // byte 9
+  /** low part of card size */
+  unsigned char c_size_low;
+  // byte 10
+  /** sector size is fixed at 64 KB */
+  unsigned char sector_size_high : 6;
+  /** fixed to 1 - erase single is supported */
+  unsigned char erase_blk_en : 1;
+  /** not used */
+  unsigned char reserved4 : 1;
+  // byte 11
+  unsigned char wp_grp_size : 7;
+  /** sector size is fixed at 64 KB */
+  unsigned char sector_size_low : 1;
+  // byte 12
+  /** write_bl_len fixed for 512 byte blocks */
+  unsigned char write_bl_len_high : 2;
+  /** fixed value of 2 */
+  unsigned char r2w_factor : 3;
+  /** not used */
+  unsigned char reserved5 : 2;
+  /** fixed value of 0 - no write protect groups */
+  unsigned char wp_grp_enable : 1;
+  // byte 13
+  unsigned char reserved6 : 5;
+  /** always zero - no partial block read*/
+  unsigned char write_partial : 1;
+  /** write_bl_len fixed for 512 byte blocks */
+  unsigned char write_bl_len_low : 2;
+  // byte 14
+  unsigned char reserved7: 2;
+  /** Do not use always 0 */
+  unsigned char file_format : 2;
+  unsigned char tmp_write_protect : 1;
+  unsigned char perm_write_protect : 1;
+  unsigned char copy : 1;
+  /** Do not use always 0 */
+  unsigned char file_format_grp : 1;
+  // byte 15
+  /** not used always 1 */
+  unsigned char always1 : 1;
+  /** checksum */
+  unsigned char crc : 7;
+}csd2_t;
+//------------------------------------------------------------------------------
+/** union of old and new style CSD register */
+union csd_t {
+  csd1_t v1;
+  csd2_t v2;
+};
+#endif  // SdInfo_h
+
+#endif

+ 405 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdVolume.cpp

@@ -0,0 +1,405 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#include "Marlin.h"
+#ifdef SDSUPPORT
+
+#include "SdVolume.h"
+//------------------------------------------------------------------------------
+#if !USE_MULTIPLE_CARDS
+// raw block cache
+uint32_t SdVolume::cacheBlockNumber_;  // current block number
+cache_t  SdVolume::cacheBuffer_;       // 512 byte cache for Sd2Card
+Sd2Card* SdVolume::sdCard_;            // pointer to SD card object
+bool     SdVolume::cacheDirty_;        // cacheFlush() will write block if true
+uint32_t SdVolume::cacheMirrorBlock_;  // mirror  block for second FAT
+#endif  // USE_MULTIPLE_CARDS
+//------------------------------------------------------------------------------
+// find a contiguous group of clusters
+bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
+  // start of group
+  uint32_t bgnCluster;
+  // end of group
+  uint32_t endCluster;
+  // last cluster of FAT
+  uint32_t fatEnd = clusterCount_ + 1;
+
+  // flag to save place to start next search
+  bool setStart;
+
+  // set search start cluster
+  if (*curCluster) {
+    // try to make file contiguous
+    bgnCluster = *curCluster + 1;
+
+    // don't save new start location
+    setStart = false;
+  } else {
+    // start at likely place for free cluster
+    bgnCluster = allocSearchStart_;
+
+    // save next search start if one cluster
+    setStart = count == 1;
+  }
+  // end of group
+  endCluster = bgnCluster;
+
+  // search the FAT for free clusters
+  for (uint32_t n = 0;; n++, endCluster++) {
+    // can't find space checked all clusters
+    if (n >= clusterCount_) goto fail;
+
+    // past end - start from beginning of FAT
+    if (endCluster > fatEnd) {
+      bgnCluster = endCluster = 2;
+    }
+    uint32_t f;
+    if (!fatGet(endCluster, &f)) goto fail;
+
+    if (f != 0) {
+      // cluster in use try next cluster as bgnCluster
+      bgnCluster = endCluster + 1;
+    } else if ((endCluster - bgnCluster + 1) == count) {
+      // done - found space
+      break;
+    }
+  }
+  // mark end of chain
+  if (!fatPutEOC(endCluster)) goto fail;
+
+  // link clusters
+  while (endCluster > bgnCluster) {
+    if (!fatPut(endCluster - 1, endCluster)) goto fail;
+    endCluster--;
+  }
+  if (*curCluster != 0) {
+    // connect chains
+    if (!fatPut(*curCluster, bgnCluster)) goto fail;
+  }
+  // return first cluster number to caller
+  *curCluster = bgnCluster;
+
+  // remember possible next free cluster
+  if (setStart) allocSearchStart_ = bgnCluster + 1;
+
+  return true;
+
+ fail:
+  return false;
+}
+//------------------------------------------------------------------------------
+bool SdVolume::cacheFlush() {
+  if (cacheDirty_) {
+    if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) {
+      goto fail;
+    }
+    // mirror FAT tables
+    if (cacheMirrorBlock_) {
+      if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) {
+        goto fail;
+      }
+      cacheMirrorBlock_ = 0;
+    }
+    cacheDirty_ = 0;
+  }
+  return true;
+
+ fail:
+  return false;
+}
+//------------------------------------------------------------------------------
+bool SdVolume::cacheRawBlock(uint32_t blockNumber, bool dirty) {
+  if (cacheBlockNumber_ != blockNumber) {
+    if (!cacheFlush()) goto fail;
+    if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) goto fail;
+    cacheBlockNumber_ = blockNumber;
+  }
+  if (dirty) cacheDirty_ = true;
+  return true;
+
+ fail:
+  return false;
+}
+//------------------------------------------------------------------------------
+// return the size in bytes of a cluster chain
+bool SdVolume::chainSize(uint32_t cluster, uint32_t* size) {
+  uint32_t s = 0;
+  do {
+    if (!fatGet(cluster, &cluster)) goto fail;
+    s += 512UL << clusterSizeShift_;
+  } while (!isEOC(cluster));
+  *size = s;
+  return true;
+
+ fail:
+  return false;
+}
+//------------------------------------------------------------------------------
+// Fetch a FAT entry
+bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
+  uint32_t lba;
+  if (cluster > (clusterCount_ + 1)) goto fail;
+  if (FAT12_SUPPORT && fatType_ == 12) {
+    uint16_t index = cluster;
+    index += index >> 1;
+    lba = fatStartBlock_ + (index >> 9);
+    if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto fail;
+    index &= 0X1FF;
+    uint16_t tmp = cacheBuffer_.data[index];
+    index++;
+    if (index == 512) {
+      if (!cacheRawBlock(lba + 1, CACHE_FOR_READ)) goto fail;
+      index = 0;
+    }
+    tmp |= cacheBuffer_.data[index] << 8;
+    *value = cluster & 1 ? tmp >> 4 : tmp & 0XFFF;
+    return true;
+  }
+  if (fatType_ == 16) {
+    lba = fatStartBlock_ + (cluster >> 8);
+  } else if (fatType_ == 32) {
+    lba = fatStartBlock_ + (cluster >> 7);
+  } else {
+    goto fail;
+  }
+  if (lba != cacheBlockNumber_) {
+    if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto fail;
+  }
+  if (fatType_ == 16) {
+    *value = cacheBuffer_.fat16[cluster & 0XFF];
+  } else {
+    *value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK;
+  }
+  return true;
+
+ fail:
+  return false;
+}
+//------------------------------------------------------------------------------
+// Store a FAT entry
+bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
+  uint32_t lba;
+  // error if reserved cluster
+  if (cluster < 2) goto fail;
+
+  // error if not in FAT
+  if (cluster > (clusterCount_ + 1)) goto fail;
+
+  if (FAT12_SUPPORT && fatType_ == 12) {
+    uint16_t index = cluster;
+    index += index >> 1;
+    lba = fatStartBlock_ + (index >> 9);
+    if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
+    // mirror second FAT
+    if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
+    index &= 0X1FF;
+    uint8_t tmp = value;
+    if (cluster & 1) {
+      tmp = (cacheBuffer_.data[index] & 0XF) | tmp << 4;
+    }
+    cacheBuffer_.data[index] = tmp;
+    index++;
+    if (index == 512) {
+      lba++;
+      index = 0;
+      if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
+      // mirror second FAT
+      if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
+    }
+    tmp = value >> 4;
+    if (!(cluster & 1)) {
+      tmp = ((cacheBuffer_.data[index] & 0XF0)) | tmp >> 4;
+    }
+    cacheBuffer_.data[index] = tmp;
+    return true;
+  }
+  if (fatType_ == 16) {
+    lba = fatStartBlock_ + (cluster >> 8);
+  } else if (fatType_ == 32) {
+    lba = fatStartBlock_ + (cluster >> 7);
+  } else {
+    goto fail;
+  }
+  if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
+  // store entry
+  if (fatType_ == 16) {
+    cacheBuffer_.fat16[cluster & 0XFF] = value;
+  } else {
+    cacheBuffer_.fat32[cluster & 0X7F] = value;
+  }
+  // mirror second FAT
+  if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
+  return true;
+
+ fail:
+  return false;
+}
+//------------------------------------------------------------------------------
+// free a cluster chain
+bool SdVolume::freeChain(uint32_t cluster) {
+  uint32_t next;
+
+  // clear free cluster location
+  allocSearchStart_ = 2;
+
+  do {
+    if (!fatGet(cluster, &next)) goto fail;
+
+    // free cluster
+    if (!fatPut(cluster, 0)) goto fail;
+
+    cluster = next;
+  } while (!isEOC(cluster));
+
+  return true;
+
+ fail:
+  return false;
+}
+//------------------------------------------------------------------------------
+/** Volume free space in clusters.
+ *
+ * \return Count of free clusters for success or -1 if an error occurs.
+ */
+int32_t SdVolume::freeClusterCount() {
+  uint32_t free = 0;
+  uint16_t n;
+  uint32_t todo = clusterCount_ + 2;
+
+  if (fatType_ == 16) {
+    n = 256;
+  } else if (fatType_ == 32) {
+    n = 128;
+  } else {
+    // put FAT12 here
+    return -1;
+  }
+
+  for (uint32_t lba = fatStartBlock_; todo; todo -= n, lba++) {
+    if (!cacheRawBlock(lba, CACHE_FOR_READ)) return -1;
+    if (todo < n) n = todo;
+    if (fatType_ == 16) {
+      for (uint16_t i = 0; i < n; i++) {
+        if (cacheBuffer_.fat16[i] == 0) free++;
+      }
+    } else {
+      for (uint16_t i = 0; i < n; i++) {
+        if (cacheBuffer_.fat32[i] == 0) free++;
+      }
+    }
+  }
+  return free;
+}
+//------------------------------------------------------------------------------
+/** Initialize a FAT volume.
+ *
+ * \param[in] dev The SD card where the volume is located.
+ *
+ * \param[in] part The partition to be used.  Legal values for \a part are
+ * 1-4 to use the corresponding partition on a device formatted with
+ * a MBR, Master Boot Record, or zero if the device is formatted as
+ * a super floppy with the FAT boot sector in block zero.
+ *
+ * \return The value one, true, is returned for success and
+ * the value zero, false, is returned for failure.  Reasons for
+ * failure include not finding a valid partition, not finding a valid
+ * FAT file system in the specified partition or an I/O error.
+ */
+bool SdVolume::init(Sd2Card* dev, uint8_t part) {
+  uint32_t totalBlocks;
+  uint32_t volumeStartBlock = 0;
+  fat32_boot_t* fbs;
+
+  sdCard_ = dev;
+  fatType_ = 0;
+  allocSearchStart_ = 2;
+  cacheDirty_ = 0;  // cacheFlush() will write block if true
+  cacheMirrorBlock_ = 0;
+  cacheBlockNumber_ = 0XFFFFFFFF;
+
+  // if part == 0 assume super floppy with FAT boot sector in block zero
+  // if part > 0 assume mbr volume with partition table
+  if (part) {
+    if (part > 4)goto fail;
+    if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail;
+    part_t* p = &cacheBuffer_.mbr.part[part-1];
+    if ((p->boot & 0X7F) !=0  ||
+      p->totalSectors < 100 ||
+      p->firstSector == 0) {
+      // not a valid partition
+      goto fail;
+    }
+    volumeStartBlock = p->firstSector;
+  }
+  if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail;
+  fbs = &cacheBuffer_.fbs32;
+  if (fbs->bytesPerSector != 512 ||
+    fbs->fatCount == 0 ||
+    fbs->reservedSectorCount == 0 ||
+    fbs->sectorsPerCluster == 0) {
+       // not valid FAT volume
+      goto fail;
+  }
+  fatCount_ = fbs->fatCount;
+  blocksPerCluster_ = fbs->sectorsPerCluster;
+  // determine shift that is same as multiply by blocksPerCluster_
+  clusterSizeShift_ = 0;
+  while (blocksPerCluster_ != (1 << clusterSizeShift_)) {
+    // error if not power of 2
+    if (clusterSizeShift_++ > 7) goto fail;
+  }
+  blocksPerFat_ = fbs->sectorsPerFat16 ?
+                    fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
+
+  fatStartBlock_ = volumeStartBlock + fbs->reservedSectorCount;
+
+  // count for FAT16 zero for FAT32
+  rootDirEntryCount_ = fbs->rootDirEntryCount;
+
+  // directory start for FAT16 dataStart for FAT32
+  rootDirStart_ = fatStartBlock_ + fbs->fatCount * blocksPerFat_;
+
+  // data start for FAT16 and FAT32
+  dataStartBlock_ = rootDirStart_ + ((32 * fbs->rootDirEntryCount + 511)/512);
+
+  // total blocks for FAT16 or FAT32
+  totalBlocks = fbs->totalSectors16 ?
+                           fbs->totalSectors16 : fbs->totalSectors32;
+  // total data blocks
+  clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock);
+
+  // divide by cluster size to get cluster count
+  clusterCount_ >>= clusterSizeShift_;
+
+  // FAT type is determined by cluster count
+  if (clusterCount_ < 4085) {
+    fatType_ = 12;
+    if (!FAT12_SUPPORT) goto fail;
+  } else if (clusterCount_ < 65525) {
+    fatType_ = 16;
+  } else {
+    rootDirStart_ = fbs->fat32RootCluster;
+    fatType_ = 32;
+  }
+  return true;
+
+ fail:
+  return false;
+}
+#endif

+ 214 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/SdVolume.h

@@ -0,0 +1,214 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#include "Marlin.h"
+#ifdef SDSUPPORT
+#ifndef SdVolume_h
+#define SdVolume_h
+/**
+ * \file
+ * \brief SdVolume class
+ */
+#include "SdFatConfig.h"
+#include "Sd2Card.h"
+#include "SdFatStructs.h"
+
+//==============================================================================
+// SdVolume class
+/**
+ * \brief Cache for an SD data block
+ */
+union cache_t {
+           /** Used to access cached file data blocks. */
+  uint8_t  data[512];
+           /** Used to access cached FAT16 entries. */
+  uint16_t fat16[256];
+           /** Used to access cached FAT32 entries. */
+  uint32_t fat32[128];
+           /** Used to access cached directory entries. */
+  dir_t    dir[16];
+           /** Used to access a cached Master Boot Record. */
+  mbr_t    mbr;
+           /** Used to access to a cached FAT boot sector. */
+  fat_boot_t fbs;
+           /** Used to access to a cached FAT32 boot sector. */
+  fat32_boot_t fbs32;
+           /** Used to access to a cached FAT32 FSINFO sector. */
+  fat32_fsinfo_t fsinfo;
+};
+//------------------------------------------------------------------------------
+/**
+ * \class SdVolume
+ * \brief Access FAT16 and FAT32 volumes on SD and SDHC cards.
+ */
+class SdVolume {
+ public:
+  /** Create an instance of SdVolume */
+  SdVolume() : fatType_(0) {}
+  /** Clear the cache and returns a pointer to the cache.  Used by the WaveRP
+   * recorder to do raw write to the SD card.  Not for normal apps.
+   * \return A pointer to the cache buffer or zero if an error occurs.
+   */
+  cache_t* cacheClear() {
+    if (!cacheFlush()) return 0;
+    cacheBlockNumber_ = 0XFFFFFFFF;
+    return &cacheBuffer_;
+  }
+  /** Initialize a FAT volume.  Try partition one first then try super
+   * floppy format.
+   *
+   * \param[in] dev The Sd2Card where the volume is located.
+   *
+   * \return The value one, true, is returned for success and
+   * the value zero, false, is returned for failure.  Reasons for
+   * failure include not finding a valid partition, not finding a valid
+   * FAT file system or an I/O error.
+   */
+  bool init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);}
+  bool init(Sd2Card* dev, uint8_t part);
+
+  // inline functions that return volume info
+  /** \return The volume's cluster size in blocks. */
+  uint8_t blocksPerCluster() const {return blocksPerCluster_;}
+  /** \return The number of blocks in one FAT. */
+  uint32_t blocksPerFat()  const {return blocksPerFat_;}
+  /** \return The total number of clusters in the volume. */
+  uint32_t clusterCount() const {return clusterCount_;}
+  /** \return The shift count required to multiply by blocksPerCluster. */
+  uint8_t clusterSizeShift() const {return clusterSizeShift_;}
+  /** \return The logical block number for the start of file data. */
+  uint32_t dataStartBlock() const {return dataStartBlock_;}
+  /** \return The number of FAT structures on the volume. */
+  uint8_t fatCount() const {return fatCount_;}
+  /** \return The logical block number for the start of the first FAT. */
+  uint32_t fatStartBlock() const {return fatStartBlock_;}
+  /** \return The FAT type of the volume. Values are 12, 16 or 32. */
+  uint8_t fatType() const {return fatType_;}
+  int32_t freeClusterCount();
+  /** \return The number of entries in the root directory for FAT16 volumes. */
+  uint32_t rootDirEntryCount() const {return rootDirEntryCount_;}
+  /** \return The logical block number for the start of the root directory
+       on FAT16 volumes or the first cluster number on FAT32 volumes. */
+  uint32_t rootDirStart() const {return rootDirStart_;}
+  /** Sd2Card object for this volume
+   * \return pointer to Sd2Card object.
+   */
+  Sd2Card* sdCard() {return sdCard_;}
+  /** Debug access to FAT table
+   *
+   * \param[in] n cluster number.
+   * \param[out] v value of entry
+   * \return true for success or false for failure
+   */
+  bool dbgFat(uint32_t n, uint32_t* v) {return fatGet(n, v);}
+//------------------------------------------------------------------------------
+ private:
+  // Allow SdBaseFile access to SdVolume private data.
+  friend class SdBaseFile;
+
+  // value for dirty argument in cacheRawBlock to indicate read from cache
+  static bool const CACHE_FOR_READ = false;
+  // value for dirty argument in cacheRawBlock to indicate write to cache
+  static bool const CACHE_FOR_WRITE = true;
+
+#if USE_MULTIPLE_CARDS
+  cache_t cacheBuffer_;        // 512 byte cache for device blocks
+  uint32_t cacheBlockNumber_;  // Logical number of block in the cache
+  Sd2Card* sdCard_;            // Sd2Card object for cache
+  bool cacheDirty_;            // cacheFlush() will write block if true
+  uint32_t cacheMirrorBlock_;  // block number for mirror FAT
+#else  // USE_MULTIPLE_CARDS
+  static cache_t cacheBuffer_;        // 512 byte cache for device blocks
+  static uint32_t cacheBlockNumber_;  // Logical number of block in the cache
+  static Sd2Card* sdCard_;            // Sd2Card object for cache
+  static bool cacheDirty_;            // cacheFlush() will write block if true
+  static uint32_t cacheMirrorBlock_;  // block number for mirror FAT
+#endif  // USE_MULTIPLE_CARDS
+  uint32_t allocSearchStart_;   // start cluster for alloc search
+  uint8_t blocksPerCluster_;    // cluster size in blocks
+  uint32_t blocksPerFat_;       // FAT size in blocks
+  uint32_t clusterCount_;       // clusters in one FAT
+  uint8_t clusterSizeShift_;    // shift to convert cluster count to block count
+  uint32_t dataStartBlock_;     // first data block number
+  uint8_t fatCount_;            // number of FATs on volume
+  uint32_t fatStartBlock_;      // start block for first FAT
+  uint8_t fatType_;             // volume type (12, 16, OR 32)
+  uint16_t rootDirEntryCount_;  // number of entries in FAT16 root dir
+  uint32_t rootDirStart_;       // root start block for FAT16, cluster for FAT32
+  //----------------------------------------------------------------------------
+  bool allocContiguous(uint32_t count, uint32_t* curCluster);
+  uint8_t blockOfCluster(uint32_t position) const {
+          return (position >> 9) & (blocksPerCluster_ - 1);}
+  uint32_t clusterStartBlock(uint32_t cluster) const {
+           return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);}
+  uint32_t blockNumber(uint32_t cluster, uint32_t position) const {
+           return clusterStartBlock(cluster) + blockOfCluster(position);}
+  cache_t *cache() {return &cacheBuffer_;}
+  uint32_t cacheBlockNumber() {return cacheBlockNumber_;}
+#if USE_MULTIPLE_CARDS
+  bool cacheFlush();
+  bool cacheRawBlock(uint32_t blockNumber, bool dirty);
+#else  // USE_MULTIPLE_CARDS
+  static bool cacheFlush();
+  static bool cacheRawBlock(uint32_t blockNumber, bool dirty);
+#endif  // USE_MULTIPLE_CARDS
+  // used by SdBaseFile write to assign cache to SD location
+  void cacheSetBlockNumber(uint32_t blockNumber, bool dirty) {
+    cacheDirty_ = dirty;
+    cacheBlockNumber_  = blockNumber;
+  }
+  void cacheSetDirty() {cacheDirty_ |= CACHE_FOR_WRITE;}
+  bool chainSize(uint32_t beginCluster, uint32_t* size);
+  bool fatGet(uint32_t cluster, uint32_t* value);
+  bool fatPut(uint32_t cluster, uint32_t value);
+  bool fatPutEOC(uint32_t cluster) {
+    return fatPut(cluster, 0x0FFFFFFF);
+  }
+  bool freeChain(uint32_t cluster);
+  bool isEOC(uint32_t cluster) const {
+    if (FAT12_SUPPORT && fatType_ == 12) return  cluster >= FAT12EOC_MIN;
+    if (fatType_ == 16) return cluster >= FAT16EOC_MIN;
+    return  cluster >= FAT32EOC_MIN;
+  }
+  bool readBlock(uint32_t block, uint8_t* dst) {
+    return sdCard_->readBlock(block, dst);}
+  bool writeBlock(uint32_t block, const uint8_t* dst) {
+    return sdCard_->writeBlock(block, dst);
+  }
+//------------------------------------------------------------------------------
+  // Deprecated functions  - suppress cpplint warnings with NOLINT comment
+#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
+ public:
+  /** \deprecated Use: bool SdVolume::init(Sd2Card* dev);
+   * \param[in] dev The SD card where the volume is located.
+   * \return true for success or false for failure.
+   */
+  bool init(Sd2Card& dev) {return init(&dev);}  // NOLINT
+  /** \deprecated Use: bool SdVolume::init(Sd2Card* dev, uint8_t vol);
+   * \param[in] dev The SD card where the volume is located.
+   * \param[in] part The partition to be used.
+   * \return true for success or false for failure.
+   */
+  bool init(Sd2Card& dev, uint8_t part) {  // NOLINT
+    return init(&dev, part);
+  }
+#endif  // ALLOW_DEPRECATED_FUNCTIONS
+};
+#endif  // SdVolume
+#endif

+ 344 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Servo.cpp

@@ -0,0 +1,344 @@
+/*
+ Servo.cpp - 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
+ */
+
+/*
+
+ A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method.
+ The servos are pulsed in the background using the value most recently written using the write() method
+
+ Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached.
+ Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four.
+
+ The methods are:
+
+ Servo - Class for manipulating servo motors connected to Arduino pins.
+
+ attach(pin )  - Attaches a servo motor to an i/o pin.
+ attach(pin, min, max  ) - Attaches to a pin setting min and max values in microseconds
+ default min is 544, max is 2400
+
+ write()     - Sets the servo angle in degrees.  (invalid angle that is valid as pulse in microseconds is treated as microseconds)
+ writeMicroseconds() - Sets the servo pulse width in microseconds
+ read()      - Gets the last written servo pulse width as an angle between 0 and 180.
+ readMicroseconds()   - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
+ attached()  - Returns true if there is a servo attached.
+ detach()    - Stops an attached servos from pulsing its i/o pin.
+
+*/
+#include "Configuration.h" 
+
+#ifdef NUM_SERVOS
+#include <avr/interrupt.h>
+#include <Arduino.h>
+
+#include "Servo.h"
+
+#define usToTicks(_us)    (( clockCyclesPerMicrosecond()* _us) / 8)     // converts microseconds to tick (assumes prescale of 8)  // 12 Aug 2009
+#define ticksToUs(_ticks) (( (unsigned)_ticks * 8)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds
+
+
+#define TRIM_DURATION       2                               // compensation ticks to trim adjust for digitalWrite delays // 12 August 2009
+
+//#define NBR_TIMERS        (MAX_SERVOS / SERVOS_PER_TIMER)
+
+static servo_t servos[MAX_SERVOS];                          // static array of servo structures
+static volatile int8_t Channel[_Nbr_16timers ];             // counter for the servo being pulsed for each timer (or -1 if refresh interval)
+
+uint8_t ServoCount = 0;                                     // the total number of attached servos
+
+
+// convenience macros
+#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo
+#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER)       // returns the index of the servo on this timer
+#define SERVO_INDEX(_timer,_channel)  ((_timer*SERVOS_PER_TIMER) + _channel)     // macro to access servo index by timer and channel
+#define SERVO(_timer,_channel)  (servos[SERVO_INDEX(_timer,_channel)])            // macro to access servo class by timer and channel
+
+#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4)  // minimum value in uS for this servo
+#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4)  // maximum value in uS for this servo
+
+/************ static functions common to all instances ***********************/
+
+static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA)
+{
+  if( Channel[timer] < 0 )
+    *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
+  else{
+    if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true )
+      digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated
+  }
+
+  Channel[timer]++;    // increment to the next channel
+  if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
+    *OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
+    if(SERVO(timer,Channel[timer]).Pin.isActive == true)     // check if activated
+      digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
+  }
+  else {
+    // finished all channels so wait for the refresh period to expire before starting over
+    if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) )  // allow a few ticks to ensure the next OCR1A not missed
+      *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
+    else
+      *OCRnA = *TCNTn + 4;  // at least REFRESH_INTERVAL has elapsed
+    Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
+  }
+}
+
+#ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
+// Interrupt handlers for Arduino
+#if defined(_useTimer1)
+SIGNAL (TIMER1_COMPA_vect)
+{
+  handle_interrupts(_timer1, &TCNT1, &OCR1A);
+}
+#endif
+
+#if defined(_useTimer3)
+SIGNAL (TIMER3_COMPA_vect)
+{
+  handle_interrupts(_timer3, &TCNT3, &OCR3A);
+}
+#endif
+
+#if defined(_useTimer4)
+SIGNAL (TIMER4_COMPA_vect)
+{
+  handle_interrupts(_timer4, &TCNT4, &OCR4A);
+}
+#endif
+
+#if defined(_useTimer5)
+SIGNAL (TIMER5_COMPA_vect)
+{
+  handle_interrupts(_timer5, &TCNT5, &OCR5A);
+}
+#endif
+
+#elif defined WIRING
+// Interrupt handlers for Wiring
+#if defined(_useTimer1)
+void Timer1Service()
+{
+  handle_interrupts(_timer1, &TCNT1, &OCR1A);
+}
+#endif
+#if defined(_useTimer3)
+void Timer3Service()
+{
+  handle_interrupts(_timer3, &TCNT3, &OCR3A);
+}
+#endif
+#endif
+
+
+static void initISR(timer16_Sequence_t timer)
+{
+#if defined (_useTimer1)
+  if(timer == _timer1) {
+    TCCR1A = 0;             // normal counting mode
+    TCCR1B = _BV(CS11);     // set prescaler of 8
+    TCNT1 = 0;              // clear the timer count
+#if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__)
+    TIFR |= _BV(OCF1A);      // clear any pending interrupts;
+    TIMSK |=  _BV(OCIE1A) ;  // enable the output compare interrupt
+#else
+    // here if not ATmega8 or ATmega128
+    TIFR1 |= _BV(OCF1A);     // clear any pending interrupts;
+    TIMSK1 |=  _BV(OCIE1A) ; // enable the output compare interrupt
+#endif
+#if defined(WIRING)
+    timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
+#endif
+  }
+#endif
+
+#if defined (_useTimer3)
+  if(timer == _timer3) {
+    TCCR3A = 0;             // normal counting mode
+    TCCR3B = _BV(CS31);     // set prescaler of 8
+    TCNT3 = 0;              // clear the timer count
+#if defined(__AVR_ATmega128__)
+    TIFR |= _BV(OCF3A);     // clear any pending interrupts;
+	ETIMSK |= _BV(OCIE3A);  // enable the output compare interrupt
+#else
+    TIFR3 = _BV(OCF3A);     // clear any pending interrupts;
+    TIMSK3 =  _BV(OCIE3A) ; // enable the output compare interrupt
+#endif
+#if defined(WIRING)
+    timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service);  // for Wiring platform only
+#endif
+  }
+#endif
+
+#if defined (_useTimer4)
+  if(timer == _timer4) {
+    TCCR4A = 0;             // normal counting mode
+    TCCR4B = _BV(CS41);     // set prescaler of 8
+    TCNT4 = 0;              // clear the timer count
+    TIFR4 = _BV(OCF4A);     // clear any pending interrupts;
+    TIMSK4 =  _BV(OCIE4A) ; // enable the output compare interrupt
+  }
+#endif
+
+#if defined (_useTimer5)
+  if(timer == _timer5) {
+    TCCR5A = 0;             // normal counting mode
+    TCCR5B = _BV(CS51);     // set prescaler of 8
+    TCNT5 = 0;              // clear the timer count
+    TIFR5 = _BV(OCF5A);     // clear any pending interrupts;
+    TIMSK5 =  _BV(OCIE5A) ; // enable the output compare interrupt
+  }
+#endif
+}
+
+static void finISR(timer16_Sequence_t timer)
+{
+    //disable use of the given timer
+#if defined WIRING   // Wiring
+  if(timer == _timer1) {
+    #if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
+    TIMSK1 &=  ~_BV(OCIE1A) ;  // disable timer 1 output compare interrupt
+    #else
+    TIMSK &=  ~_BV(OCIE1A) ;  // disable timer 1 output compare interrupt
+    #endif
+    timerDetach(TIMER1OUTCOMPAREA_INT);
+  }
+  else if(timer == _timer3) {
+    #if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
+    TIMSK3 &= ~_BV(OCIE3A);    // disable the timer3 output compare A interrupt
+    #else
+    ETIMSK &= ~_BV(OCIE3A);    // disable the timer3 output compare A interrupt
+    #endif
+    timerDetach(TIMER3OUTCOMPAREA_INT);
+  }
+#else
+    //For arduino - in future: call here to a currently undefined function to reset the timer
+#endif
+}
+
+static boolean isTimerActive(timer16_Sequence_t timer)
+{
+  // returns true if any servo is active on this timer
+  for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
+    if(SERVO(timer,channel).Pin.isActive == true)
+      return true;
+  }
+  return false;
+}
+
+
+/****************** end of static functions ******************************/
+
+Servo::Servo()
+{
+  if( ServoCount < MAX_SERVOS) {
+    this->servoIndex = ServoCount++;                    // assign a servo index to this instance
+	servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH);   // store default values  - 12 Aug 2009
+  }
+  else
+    this->servoIndex = INVALID_SERVO ;  // too many servos
+}
+
+uint8_t Servo::attach(int pin)
+{
+  return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
+}
+
+uint8_t Servo::attach(int pin, int min, int max)
+{
+  if(this->servoIndex < MAX_SERVOS ) {
+#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
+    if (pin > 0) this->pin = pin; else pin = this->pin;
+#endif
+    pinMode( pin, OUTPUT) ;                                   // set servo pin to output
+    servos[this->servoIndex].Pin.nbr = pin;
+    // todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
+    this->min  = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
+    this->max  = (MAX_PULSE_WIDTH - max)/4;
+    // initialize the timer if it has not already been initialized
+    timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
+    if(isTimerActive(timer) == false)
+      initISR(timer);
+    servos[this->servoIndex].Pin.isActive = true;  // this must be set after the check for isTimerActive
+  }
+  return this->servoIndex ;
+}
+
+void Servo::detach()
+{
+  servos[this->servoIndex].Pin.isActive = false;
+  timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
+  if(isTimerActive(timer) == false) {
+    finISR(timer);
+  }
+}
+
+void Servo::write(int value)
+{
+  if(value < MIN_PULSE_WIDTH)
+  {  // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
+    if(value < 0) value = 0;
+    if(value > 180) value = 180;
+    value = map(value, 0, 180, SERVO_MIN(),  SERVO_MAX());
+  }
+  this->writeMicroseconds(value);
+}
+
+void Servo::writeMicroseconds(int value)
+{
+  // calculate and store the values for the given channel
+  byte channel = this->servoIndex;
+  if( (channel < MAX_SERVOS) )   // ensure channel is valid
+  {
+    if( value < SERVO_MIN() )          // ensure pulse width is valid
+      value = SERVO_MIN();
+    else if( value > SERVO_MAX() )
+      value = SERVO_MAX();
+
+  	value = value - TRIM_DURATION;
+    value = usToTicks(value);  // convert to ticks after compensating for interrupt overhead - 12 Aug 2009
+
+    uint8_t oldSREG = SREG;
+    cli();
+    servos[channel].ticks = value;
+    SREG = oldSREG;
+  }
+}
+
+int Servo::read() // return the value as degrees
+{
+  return  map( this->readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
+}
+
+int Servo::readMicroseconds()
+{
+  unsigned int pulsewidth;
+  if( this->servoIndex != INVALID_SERVO )
+    pulsewidth = ticksToUs(servos[this->servoIndex].ticks)  + TRIM_DURATION ;   // 12 aug 2009
+  else
+    pulsewidth  = 0;
+
+  return pulsewidth;
+}
+
+bool Servo::attached()
+{
+  return servos[this->servoIndex].Pin.isActive ;
+}
+
+#endif

+ 135 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/Servo.h

@@ -0,0 +1,135 @@
+/*
+  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
+*/
+
+/*
+
+  A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method.
+  The servos are pulsed in the background using the value most recently written using the write() method
+
+  Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached.
+  Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four.
+  The sequence used to sieze timers is defined in timers.h
+
+  The methods are:
+
+   Servo - Class for manipulating servo motors connected to Arduino pins.
+
+   attach(pin )  - Attaches a servo motor to an i/o pin.
+   attach(pin, min, max  ) - Attaches to a pin setting min and max values in microseconds
+   default min is 544, max is 2400
+
+   write()     - Sets the servo angle in degrees.  (invalid angle that is valid as pulse in microseconds is treated as microseconds)
+   writeMicroseconds() - Sets the servo pulse width in microseconds
+   read()      - Gets the last written servo pulse width as an angle between 0 and 180.
+   readMicroseconds()   - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
+   attached()  - Returns true if there is a servo attached.
+   detach()    - Stops an attached servos from pulsing its i/o pin.
+ */
+
+#ifndef Servo_h
+#define Servo_h
+
+#include <inttypes.h>
+
+/*
+ * Defines for 16 bit timers used with  Servo library
+ *
+ * If _useTimerX is defined then TimerX is a 16 bit timer on the curent board
+ * timer16_Sequence_t enumerates the sequence that the timers should be allocated
+ * _Nbr_16timers indicates how many 16 bit timers are available.
+ *
+ */
+
+// Say which 16 bit timers can be used and in what order
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+#define _useTimer5
+//#define _useTimer1
+#define _useTimer3
+#define _useTimer4
+//typedef enum { _timer5, _timer1, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t ;
+typedef enum { _timer5, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t ;
+
+#elif defined(__AVR_ATmega32U4__)
+//#define _useTimer1
+#define _useTimer3
+//typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t ;
+typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t ;
+
+#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
+#define _useTimer3
+//#define _useTimer1
+//typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t ;
+typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t ;
+
+#elif defined(__AVR_ATmega128__) ||defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1284P__) ||defined(__AVR_ATmega2561__)
+#define _useTimer3
+//#define _useTimer1
+//typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t ;
+typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t ;
+
+#else  // everything else
+//#define _useTimer1
+//typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t ;
+typedef enum { _Nbr_16timers } timer16_Sequence_t ;
+#endif
+
+#define Servo_VERSION           2      // software version of this library
+
+#define MIN_PULSE_WIDTH       544     // the shortest pulse sent to a servo
+#define MAX_PULSE_WIDTH      2400     // the longest pulse sent to a servo
+#define DEFAULT_PULSE_WIDTH  1500     // default pulse width when servo is attached
+#define REFRESH_INTERVAL    20000     // minumim time to refresh servos in microseconds
+
+#define SERVOS_PER_TIMER       12     // the maximum number of servos controlled by one timer
+#define MAX_SERVOS   (_Nbr_16timers  * SERVOS_PER_TIMER)
+
+#define INVALID_SERVO         255     // flag indicating an invalid servo index
+
+typedef struct  {
+  uint8_t nbr        :6 ;             // a pin number from 0 to 63
+  uint8_t isActive   :1 ;             // true if this channel is enabled, pin not pulsed if false
+} ServoPin_t   ;
+
+typedef struct {
+  ServoPin_t Pin;
+  unsigned int ticks;
+} servo_t;
+
+class Servo
+{
+public:
+  Servo();
+  uint8_t attach(int pin);           // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
+  uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes.
+  void detach();
+  void write(int value);             // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds
+  void writeMicroseconds(int value); // Write pulse width in microseconds
+  int read();                        // returns current pulse width as an angle between 0 and 180 degrees
+  int readMicroseconds();            // returns current pulse width in microseconds for this servo (was read_us() in first release)
+  bool attached();                   // return true if this servo is attached, otherwise false
+#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
+  int pin;                           // store the hw pin of the servo
+#endif
+private:
+   uint8_t servoIndex;               // index into the channel data for this servo
+   int8_t min;                       // minimum is this value times 4 added to MIN_PULSE_WIDTH
+   int8_t max;                       // maximum is this value times 4 added to MAX_PULSE_WIDTH
+};
+
+#endif

+ 686 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/cardreader.cpp

@@ -0,0 +1,686 @@
+#include "Marlin.h"
+#include "cardreader.h"
+#include "ultralcd.h"
+#include "stepper.h"
+#include "temperature.h"
+#include "language.h"
+
+#ifdef SDSUPPORT
+
+
+
+CardReader::CardReader()
+{
+   filesize = 0;
+   sdpos = 0;
+   sdprinting = false;
+   cardOK = false;
+   saving = false;
+   logging = false;
+   autostart_atmillis=0;
+   workDirDepth = 0;
+   file_subcall_ctr=0;
+   memset(workDirParents, 0, sizeof(workDirParents));
+
+   autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
+   lastnr=0;
+  //power to SD reader
+  #if SDPOWER > -1
+    SET_OUTPUT(SDPOWER); 
+    WRITE(SDPOWER,HIGH);
+  #endif //SDPOWER
+  
+  autostart_atmillis=millis()+5000;
+}
+
+char *createFilename(char *buffer,const dir_t &p) //buffer>12characters
+{
+  char *pos=buffer;
+  for (uint8_t i = 0; i < 11; i++) 
+  {
+    if (p.name[i] == ' ')continue;
+    if (i == 8) 
+    {
+      *pos++='.';
+    }
+    *pos++=p.name[i];
+  }
+  *pos++=0;
+  return buffer;
+}
+
+
+void  CardReader::lsDive(const char *prepend,SdFile parent)
+{
+  dir_t p;
+ uint8_t cnt=0;
+ 
+  while (parent.readDir(p, longFilename) > 0)
+  {
+    if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) // hence LS_SerialPrint
+    {
+
+      char path[13*2];
+      char lfilename[13];
+      createFilename(lfilename,p);
+      
+      path[0]=0;
+      if(strlen(prepend)==0) //avoid leading / if already in prepend
+      {
+       strcat(path,"/");
+      }
+      strcat(path,prepend);
+      strcat(path,lfilename);
+      strcat(path,"/");
+      
+      //Serial.print(path);
+      
+      SdFile dir;
+      if(!dir.open(parent,lfilename, O_READ))
+      {
+        if(lsAction==LS_SerialPrint)
+        {
+          SERIAL_ECHO_START;
+          SERIAL_ECHOLN(MSG_SD_CANT_OPEN_SUBDIR);
+          SERIAL_ECHOLN(lfilename);
+        }
+      }
+      lsDive(path,dir);
+      //close done automatically by destructor of SdFile
+
+      
+    }
+    else
+    {
+      if (p.name[0] == DIR_NAME_FREE) break;
+      if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue;
+      if (longFilename[0] != '\0' &&
+          (longFilename[0] == '.' || longFilename[0] == '_')) continue;
+      if ( p.name[0] == '.')
+      {
+        if ( p.name[1] != '.')
+        continue;
+      }
+      
+      if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
+      filenameIsDir=DIR_IS_SUBDIR(&p);
+      
+      
+      if(!filenameIsDir)
+      {
+        if(p.name[8]!='G') continue;
+        if(p.name[9]=='~') continue;
+      }
+      //if(cnt++!=nr) continue;
+      createFilename(filename,p);
+      if(lsAction==LS_SerialPrint)
+      {
+        SERIAL_PROTOCOL(prepend);
+        SERIAL_PROTOCOLLN(filename);
+      }
+      else if(lsAction==LS_Count)
+      {
+        nrFiles++;
+      } 
+      else if(lsAction==LS_GetFilename)
+      {
+        if(cnt==nrFiles)
+          return;
+        cnt++;
+        
+      }
+    }
+  }
+}
+
+void CardReader::ls() 
+{
+  lsAction=LS_SerialPrint;
+  if(lsAction==LS_Count)
+  nrFiles=0;
+
+  root.rewind();
+  lsDive("",root);
+}
+
+
+void CardReader::initsd()
+{
+  cardOK = false;
+  if(root.isOpen())
+    root.close();
+#ifdef SDSLOW
+  if (!card.init(SPI_HALF_SPEED,SDSS))
+#else
+  if (!card.init(SPI_FULL_SPEED,SDSS))
+#endif
+  {
+    //if (!card.init(SPI_HALF_SPEED,SDSS))
+    SERIAL_ECHO_START;
+    SERIAL_ECHOLNPGM(MSG_SD_INIT_FAIL);
+  }
+  else if (!volume.init(&card))
+  {
+    SERIAL_ERROR_START;
+    SERIAL_ERRORLNPGM(MSG_SD_VOL_INIT_FAIL);
+  }
+  else if (!root.openRoot(&volume)) 
+  {
+    SERIAL_ERROR_START;
+    SERIAL_ERRORLNPGM(MSG_SD_OPENROOT_FAIL);
+  }
+  else 
+  {
+    cardOK = true;
+    SERIAL_ECHO_START;
+    SERIAL_ECHOLNPGM(MSG_SD_CARD_OK);
+  }
+  workDir=root;
+  curDir=&root;
+  /*
+  if(!workDir.openRoot(&volume))
+  {
+    SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
+  }
+  */
+  
+}
+
+void CardReader::setroot()
+{
+  /*if(!workDir.openRoot(&volume))
+  {
+    SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
+  }*/
+  workDir=root;
+  
+  curDir=&workDir;
+}
+void CardReader::release()
+{
+  sdprinting = false;
+  cardOK = false;
+}
+
+void CardReader::startFileprint()
+{
+  if(cardOK)
+  {
+    sdprinting = true;
+  }
+}
+
+void CardReader::pauseSDPrint()
+{
+  if(sdprinting)
+  {
+    sdprinting = false;
+  }
+}
+
+
+void CardReader::openLogFile(char* name)
+{
+  logging = true;
+  openFile(name, false);
+}
+#if defined(SDSUPPORT) && defined(POWEROFF_SAVE_SD_FILE)
+void CardReader::openPowerOffFile(char* name, uint8_t oflag) {
+	if (!cardOK) return;
+	if (powerOffFile.isOpen()) return;
+	if (!powerOffFile.open(&root, name, oflag)) {
+	  SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
+	  SERIAL_PROTOCOL(name);
+	  SERIAL_PROTOCOLPGM(".\n");
+	}
+	else {
+	  SERIAL_PROTOCOLPGM(MSG_SD_WRITE_TO_FILE);
+	  SERIAL_PROTOCOLLN(name);
+	}
+}
+void CardReader::closePowerOffFile() {
+  powerOffFile.close();
+}
+bool CardReader::existPowerOffFile(char* name) {
+	bool ret = powerOffFile.open(&root, name, O_READ);
+  return ret;
+}
+int16_t CardReader::savePowerOffInfo(const void* data, uint16_t size) {
+  powerOffFile.seekSet(0);
+	return powerOffFile.write(data, size);
+}
+
+int16_t CardReader::getPowerOffInfo(void* data, uint16_t size) {
+	return powerOffFile.read(data, size);
+}
+void CardReader::removePowerOffFile() {
+  if (powerOffFile.remove(&root, power_off_info.power_off_filename)) {
+    SERIAL_PROTOCOLPGM("File(bin) deleted");
+  }
+  else {
+    SERIAL_PROTOCOLPGM("Deletion(bin) failed");
+  }
+  SERIAL_PROTOCOLPGM(".\n");
+}
+#endif
+void CardReader::getAbsFilename(char *t)
+{
+  uint8_t cnt=0;
+  *t='/';t++;cnt++;
+  for(uint8_t i=0;i<workDirDepth;i++)
+  {
+    workDirParents[i].getFilename(t); //SDBaseFile.getfilename!
+    while(*t!=0 && cnt< MAXPATHNAMELENGTH) 
+    {t++;cnt++;}  //crawl counter forward.
+  }
+  if(cnt<MAXPATHNAMELENGTH-13)
+    file.getFilename(t);
+  else
+    t[0]=0;
+}
+
+void CardReader::openFile(char* name,bool read, bool replace_current/*=true*/)
+{
+  if(!cardOK)
+    return;
+  if(file.isOpen())  //replaceing current file by new file, or subfile call
+  {
+    if(!replace_current)
+    {
+     if((int)file_subcall_ctr>(int)SD_PROCEDURE_DEPTH-1)
+     {
+       SERIAL_ERROR_START;
+       SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
+       SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
+       kill();
+       return;
+     }
+     
+     SERIAL_ECHO_START;
+     SERIAL_ECHOPGM("SUBROUTINE CALL target:\"");
+     SERIAL_ECHO(name);
+     SERIAL_ECHOPGM("\" parent:\"");
+     
+     //store current filename and position
+     getAbsFilename(filenames[file_subcall_ctr]);
+     
+     SERIAL_ECHO(filenames[file_subcall_ctr]);
+     SERIAL_ECHOPGM("\" pos");
+     SERIAL_ECHOLN(sdpos);
+     filespos[file_subcall_ctr]=sdpos;
+     file_subcall_ctr++;
+    }
+    else
+    {
+     SERIAL_ECHO_START;
+     SERIAL_ECHOPGM("Now doing file: ");
+     SERIAL_ECHOLN(name);
+    }
+    file.close();
+  }
+  else //opening fresh file
+  {
+    file_subcall_ctr=0; //resetting procedure depth in case user cancels print while in procedure
+    SERIAL_ECHO_START;
+    SERIAL_ECHOPGM("Now fresh file: ");
+    SERIAL_ECHOLN(name);
+  }
+  sdprinting = false;
+  
+ 
+  SdFile myDir;
+  curDir=&root;
+  char *fname=name;
+  
+  char *dirname_start,*dirname_end;
+  if(name[0]=='/')
+  {
+    dirname_start=strchr(name,'/')+1;
+    while(dirname_start>0)
+    {
+      dirname_end=strchr(dirname_start,'/');
+      //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name));
+      //SERIAL_ECHO("end  :");SERIAL_ECHOLN((int)(dirname_end-name));
+      if(dirname_end>0 && dirname_end>dirname_start)
+      {
+        char subdirname[13];
+        strncpy(subdirname, dirname_start, dirname_end-dirname_start);
+        subdirname[dirname_end-dirname_start]=0;
+        SERIAL_ECHOLN(subdirname);
+        if(!myDir.open(curDir,subdirname,O_READ))
+        {
+          SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
+          SERIAL_PROTOCOL(subdirname);
+          SERIAL_PROTOCOLLNPGM(".");
+          return;
+        }
+        else
+        {
+          //SERIAL_ECHOLN("dive ok");
+        }
+          
+        curDir=&myDir; 
+        dirname_start=dirname_end+1;
+      }
+      else // the reminder after all /fsa/fdsa/ is the filename
+      {
+        fname=dirname_start;
+        //SERIAL_ECHOLN("remaider");
+        //SERIAL_ECHOLN(fname);
+        break;
+      }
+      
+    }
+  }
+  else //relative path
+  {
+    curDir=&workDir;
+  }
+  if(read)
+  {
+    if (file.open(curDir, fname, O_READ)) 
+    {
+      filesize = file.fileSize();
+      SERIAL_PROTOCOLPGM(MSG_SD_FILE_OPENED);
+      SERIAL_PROTOCOL(fname);
+      SERIAL_PROTOCOLPGM(MSG_SD_SIZE);
+      SERIAL_PROTOCOLLN(filesize);
+      sdpos = 0;
+      
+      SERIAL_PROTOCOLLNPGM(MSG_SD_FILE_SELECTED);
+      lcd_setstatus(fname);
+    }
+    else
+    {
+      SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
+      SERIAL_PROTOCOL(fname);
+      SERIAL_PROTOCOLLNPGM(".");
+    }
+  }
+  else 
+  { //write
+    if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))
+    {
+      SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
+      SERIAL_PROTOCOL(fname);
+      SERIAL_PROTOCOLLNPGM(".");
+    }
+    else
+    {
+      saving = true;
+      SERIAL_PROTOCOLPGM(MSG_SD_WRITE_TO_FILE);
+      SERIAL_PROTOCOLLN(name);
+      lcd_setstatus(fname);
+    }
+  }
+  
+}
+
+void CardReader::removeFile(char* name)
+{
+  if(!cardOK)
+    return;
+  file.close();
+  sdprinting = false;
+  
+  
+  SdFile myDir;
+  curDir=&root;
+  char *fname=name;
+  
+  char *dirname_start,*dirname_end;
+  if(name[0]=='/')
+  {
+    dirname_start=strchr(name,'/')+1;
+    while(dirname_start>0)
+    {
+      dirname_end=strchr(dirname_start,'/');
+      //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name));
+      //SERIAL_ECHO("end  :");SERIAL_ECHOLN((int)(dirname_end-name));
+      if(dirname_end>0 && dirname_end>dirname_start)
+      {
+        char subdirname[13];
+        strncpy(subdirname, dirname_start, dirname_end-dirname_start);
+        subdirname[dirname_end-dirname_start]=0;
+        SERIAL_ECHOLN(subdirname);
+        if(!myDir.open(curDir,subdirname,O_READ))
+        {
+          SERIAL_PROTOCOLPGM("open failed, File: ");
+          SERIAL_PROTOCOL(subdirname);
+          SERIAL_PROTOCOLLNPGM(".");
+          return;
+        }
+        else
+        {
+          //SERIAL_ECHOLN("dive ok");
+        }
+          
+        curDir=&myDir; 
+        dirname_start=dirname_end+1;
+      }
+      else // the reminder after all /fsa/fdsa/ is the filename
+      {
+        fname=dirname_start;
+        //SERIAL_ECHOLN("remaider");
+        //SERIAL_ECHOLN(fname);
+        break;
+      }
+      
+    }
+  }
+  else //relative path
+  {
+    curDir=&workDir;
+  }
+    if (file.remove(curDir, fname)) 
+    {
+      SERIAL_PROTOCOLPGM("File deleted:");
+      SERIAL_PROTOCOL(fname);
+      sdpos = 0;
+    }
+    else
+    {
+      SERIAL_PROTOCOLPGM("Deletion failed, File: ");
+      SERIAL_PROTOCOL(fname);
+      SERIAL_PROTOCOLLNPGM(".");
+    }
+  
+}
+
+void CardReader::getStatus()
+{
+  if(cardOK){
+    SERIAL_PROTOCOLPGM(MSG_SD_PRINTING_BYTE);
+    SERIAL_PROTOCOL(sdpos);
+    SERIAL_PROTOCOLPGM("/");
+    SERIAL_PROTOCOLLN(filesize);
+  }
+  else{
+    SERIAL_PROTOCOLLNPGM(MSG_SD_NOT_PRINTING);
+  }
+}
+void CardReader::write_command(char *buf)
+{
+  char* begin = buf;
+  char* npos = 0;
+  char* end = buf + strlen(buf) - 1;
+
+  file.writeError = false;
+  if((npos = strchr(buf, 'N')) != NULL)
+  {
+    begin = strchr(npos, ' ') + 1;
+    end = strchr(npos, '*') - 1;
+  }
+  end[1] = '\r';
+  end[2] = '\n';
+  end[3] = '\0';
+  file.write(begin);
+  if (file.writeError)
+  {
+    SERIAL_ERROR_START;
+    SERIAL_ERRORLNPGM(MSG_SD_ERR_WRITE_TO_FILE);
+  }
+}
+
+
+void CardReader::checkautostart(bool force)
+{
+  if(!force)
+  {
+    if(!autostart_stilltocheck)
+      return;
+    if(autostart_atmillis<millis())
+      return;
+  }
+  autostart_stilltocheck=false;
+  if(!cardOK)
+  {
+    initsd();
+    if(!cardOK) //fail
+      return;
+  }
+  
+  char autoname[30];
+  sprintf_P(autoname, PSTR("auto%i.g"), lastnr);
+  for(int8_t i=0;i<(int8_t)strlen(autoname);i++)
+    autoname[i]=tolower(autoname[i]);
+  dir_t p;
+
+  root.rewind();
+  
+  bool found=false;
+  while (root.readDir(p, NULL) > 0) 
+  {
+    for(int8_t i=0;i<(int8_t)strlen((char*)p.name);i++)
+    p.name[i]=tolower(p.name[i]);
+    //Serial.print((char*)p.name);
+    //Serial.print(" ");
+    //Serial.println(autoname);
+    if(p.name[9]!='~') //skip safety copies
+    if(strncmp((char*)p.name,autoname,5)==0)
+    {
+      char cmd[30];
+
+      sprintf_P(cmd, PSTR("M23 %s"), autoname);
+      enqueuecommand(cmd);
+      enqueuecommands_P(PSTR("M24"));
+      found=true;
+    }
+  }
+  if(!found)
+    lastnr=-1;
+  else
+    lastnr++;
+}
+
+void CardReader::closefile(bool store_location)
+{
+  file.sync();
+  file.close();
+  saving = false; 
+  logging = false;
+  
+  if(store_location)
+  {
+    //future: store printer state, filename and position for continueing a stoped print
+    // so one can unplug the printer and continue printing the next day.
+    
+  }
+
+  
+}
+
+void CardReader::getfilename(const uint8_t nr)
+{
+  curDir=&workDir;
+  lsAction=LS_GetFilename;
+  nrFiles=nr;
+  curDir->rewind();
+  lsDive("",*curDir);
+  
+}
+
+uint16_t CardReader::getnrfilenames()
+{
+  curDir=&workDir;
+  lsAction=LS_Count;
+  nrFiles=0;
+  curDir->rewind();
+  lsDive("",*curDir);
+  //SERIAL_ECHOLN(nrFiles);
+  return nrFiles;
+}
+
+void CardReader::chdir(const char * relpath)
+{
+  SdFile newfile;
+  SdFile *parent=&root;
+  
+  if(workDir.isOpen())
+    parent=&workDir;
+  
+  if(!newfile.open(*parent,relpath, O_READ))
+  {
+   SERIAL_ECHO_START;
+   SERIAL_ECHOPGM(MSG_SD_CANT_ENTER_SUBDIR);
+   SERIAL_ECHOLN(relpath);
+  }
+  else
+  {
+    if (workDirDepth < MAX_DIR_DEPTH) {
+      for (int d = ++workDirDepth; d--;)
+        workDirParents[d+1] = workDirParents[d];
+      workDirParents[0]=*parent;
+    }
+    workDir=newfile;
+  }
+}
+
+void CardReader::updir()
+{
+  if(workDirDepth > 0)
+  {
+    --workDirDepth;
+    workDir = workDirParents[0];
+    int d;
+    for (int d = 0; d < workDirDepth; d++)
+      workDirParents[d] = workDirParents[d+1];
+  }
+}
+
+
+void CardReader::printingHasFinished()
+{
+    st_synchronize();
+    if(file_subcall_ctr>0) //heading up to a parent file that called current as a procedure.
+    {
+      file.close();
+      file_subcall_ctr--;
+      openFile(filenames[file_subcall_ctr],true,true);
+      setIndex(filespos[file_subcall_ctr]);
+      startFileprint();
+    }
+    else
+    {
+      quickStop();
+      file.close();
+      sdprinting = false;
+      #if defined(SDSUPPORT) && defined(POWEROFF_SAVE_SD_FILE)
+      openPowerOffFile(power_off_info.power_off_filename, O_CREAT | O_WRITE | O_TRUNC | O_SYNC);
+      power_off_info.valid_head = 0;
+      power_off_info.valid_foot = 0;
+      if (savePowerOffInfo(&power_off_info, sizeof(power_off_info)) == -1){
+        SERIAL_PROTOCOLLN("Stop to Write power off file failed.");
+      }
+	  power_off_commands_count = 0;
+      closePowerOffFile();
+      #endif
+      if(SD_FINISHED_STEPPERRELEASE)
+      {
+          //finishAndDisableSteppers();
+          enqueuecommands_P(PSTR(SD_FINISHED_RELEASECOMMAND));
+      }
+      autotempShutdown();
+    }
+}
+#endif //SDSUPPORT

+ 144 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/cardreader.h

@@ -0,0 +1,144 @@
+#ifndef CARDREADER_H
+#define CARDREADER_H
+
+#ifdef SDSUPPORT
+
+#define MAX_DIR_DEPTH 10
+
+#include "SdFile.h"
+enum LsAction {LS_SerialPrint,LS_Count,LS_GetFilename};
+class CardReader
+{
+public:
+  CardReader();
+  
+  void initsd();
+  void write_command(char *buf);
+  //files auto[0-9].g on the sd card are performed in a row
+  //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset
+
+  void checkautostart(bool x); 
+  void openFile(char* name,bool read,bool replace_current=true);
+  void openLogFile(char* name);
+  #if defined(SDSUPPORT) && defined(POWEROFF_SAVE_SD_FILE)
+  void openPowerOffFile(char* name, uint8_t oflag);
+  void closePowerOffFile();
+  bool existPowerOffFile(char* name);
+  int16_t savePowerOffInfo(const void* data, uint16_t size);
+  int16_t getPowerOffInfo(void* data, uint16_t size);
+  void removePowerOffFile();
+  #endif
+  void removeFile(char* name);
+  void closefile(bool store_location=false);
+  void release();
+  void startFileprint();
+  void pauseSDPrint();
+  void getStatus();
+  void printingHasFinished();
+
+  void getfilename(const uint8_t nr);
+  uint16_t getnrfilenames();
+  
+  void getAbsFilename(char *t);
+  
+
+  void ls();
+  void chdir(const char * relpath);
+  void updir();
+  void setroot();
+
+
+  FORCE_INLINE bool isFileOpen() { return file.isOpen(); }
+  FORCE_INLINE bool eof() { return sdpos>=filesize ;};
+  FORCE_INLINE int16_t get() {  sdpos = file.curPosition();return (int16_t)file.read();};
+  FORCE_INLINE void setIndex(long index) {sdpos = index;file.seekSet(index);};
+  FORCE_INLINE uint32_t getIndex() { return sdpos; }
+  FORCE_INLINE uint8_t percentDone(){if(!isFileOpen()) return 0; if(filesize) return sdpos/((filesize+99)/100); else return 0;};
+  FORCE_INLINE char* getWorkDirName(){workDir.getFilename(filename);return filename;};
+
+public:
+  bool saving;
+  bool logging;
+  bool sdprinting ;  
+  bool cardOK ;
+  char filename[13];
+  char longFilename[LONG_FILENAME_LENGTH];
+  bool filenameIsDir;
+  int lastnr; //last number of the autostart;
+private:
+  SdFile root,*curDir,workDir,workDirParents[MAX_DIR_DEPTH];
+  uint16_t workDirDepth;
+  Sd2Card card;
+  SdVolume volume;
+  SdFile file;
+  #if defined(SDSUPPORT) && defined(POWEROFF_SAVE_SD_FILE)
+  SdFile powerOffFile;
+  #endif
+  #define SD_PROCEDURE_DEPTH 1
+  #define MAXPATHNAMELENGTH (13*MAX_DIR_DEPTH+MAX_DIR_DEPTH+1)
+  uint8_t file_subcall_ctr;
+  uint32_t filespos[SD_PROCEDURE_DEPTH];
+  char filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
+  uint32_t filesize;
+  //int16_t n;
+  unsigned long autostart_atmillis;
+  uint32_t sdpos ;
+
+  bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
+  
+  LsAction lsAction; //stored for recursion.
+  int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
+  char* diveDirName;
+  void lsDive(const char *prepend,SdFile parent);
+};
+extern CardReader card;
+#if defined(SDSUPPORT) && defined(POWEROFF_SAVE_SD_FILE)
+struct power_off_info_t {
+  /* header (1B + 7B = 8B) */
+  uint8_t valid_head;
+  //uint8_t reserved1[8-1];
+  /* Gcode related information. (44B + 20B = 64B) */
+  float current_position[NUM_AXIS];
+  float feedrate;
+  float saved_z;
+  int target_temperature[4];
+  int target_temperature_bed;
+  //uint8_t reserved2[64-44];
+  /* print queue related information. (396B + 116B = 512B) */
+  int cmd_queue_index_r;
+  int cmd_queue_index_w;
+  int commands_in_queue;
+  char command_queue[BUFSIZE][MAX_CMD_SIZE];
+  //uint8_t reserved3[512-396];
+  /* SD card related information. (165B + 91B = 256B)*/
+  uint32_t sdpos;
+  millis_t print_job_start_ms;
+  char sd_filename[MAXPATHNAMELENGTH];
+  char power_off_filename[16];
+  //uint8_t reserved4[256-166];
+  uint8_t valid_foot;
+};
+
+extern struct power_off_info_t power_off_info;
+extern int power_off_commands_count;
+extern int power_off_type_yes;
+#endif
+#define IS_SD_PRINTING (card.sdprinting)
+
+#if (SDCARDDETECT > -1)
+# ifdef SDCARDDETECTINVERTED 
+#  define IS_SD_INSERTED (READ(SDCARDDETECT)!=0)
+# else
+#  define IS_SD_INSERTED (READ(SDCARDDETECT)==0)
+# endif //SDCARDTETECTINVERTED
+#else
+//If we don't have a card detect line, aways asume the card is inserted
+# define IS_SD_INSERTED true
+#endif
+
+#else
+
+#define IS_SD_PRINTING (false)
+
+#endif //SDSUPPORT
+#endif

+ 155 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/createTemperatureLookupMarlin.py

@@ -0,0 +1,155 @@
+#!/usr/bin/python
+#
+# Creates a C code lookup table for doing ADC to temperature conversion
+# on a microcontroller
+# based on: http://hydraraptor.blogspot.com/2007/10/measuring-temperature-easy-way.html
+"""Thermistor Value Lookup Table Generator
+
+Generates lookup to temperature values for use in a microcontroller in C format based on: 
+http://hydraraptor.blogspot.com/2007/10/measuring-temperature-easy-way.html
+
+The main use is for Arduino programs that read data from the circuit board described here:
+http://make.rrrf.org/ts-1.0
+
+Usage: python createTemperatureLookup.py [options]
+
+Options:
+  -h, --help        show this help
+  --rp=...          pull-up resistor
+  --t0=ttt:rrr      low temperature temperature:resistance point (around 25C)
+  --t1=ttt:rrr      middle temperature temperature:resistance point (around 150C)
+  --t2=ttt:rrr      high temperature temperature:resistance point (around 250C)
+  --num-temps=...   the number of temperature points to calculate (default: 20)
+"""
+
+from math import *
+import sys
+import getopt
+
+class Thermistor:
+    "Class to do the thermistor maths"
+    def __init__(self, rp, t1, r1, t2, r2, t3, r3):
+        t1 = t1 + 273.15               # low temperature (25C)
+        r1 = r1                        # resistance at low temperature
+        t2 = t2 + 273.15               # middle temperature (150C)
+        r2 = r2                        # resistance at middle temperature
+        t3 = t3 + 273.15               # high temperature (250C)
+        r3 = r3                        # resistance at high temperature
+        self.rp = rp                   # pull-up resistance
+        self.vadc = 5.0                # ADC reference
+        self.vcc = 5.0                 # supply voltage to potential divider
+        a1 = log(r1)
+        a2 = log(r2)
+        a3 = log(r3)
+        z = a1 - a2
+        y = a1 - a3
+        x = 1/t1 - 1/t2
+        w = 1/t1 - 1/t3
+        v = pow(a1,3) - pow(a2,3)
+        u = pow(a1,3) - pow(a3,3)
+        c3 = (x-z*w/y)/(v-z*u/y)
+        c2 = (x-c3*v)/z
+        c1 = 1/t1-c3*pow(a1,3)-c2*a1
+        self.c1 = c1
+        self.c2 = c2
+        self.c3 = c3
+
+    def res(self,adc):
+        "Convert ADC reading into a resolution"
+        res = self.temp(adc)-self.temp(adc+1)
+        return res
+
+    def v(self,adc):
+        "Convert ADC reading into a Voltage"
+        v = adc * self.vadc / (1024 )   # convert the 10 bit ADC value to a voltage
+        return v
+
+    def r(self,adc):
+        "Convert ADC reading into a resistance in Ohms"
+        v = adc * self.vadc / (1024 )   # convert the 10 bit ADC value to a voltage
+        r = self.rp * v / (self.vcc - v)    # resistance of thermistor
+        return r
+
+    def temp(self,adc):
+        "Convert ADC reading into a temperature in Celcius"
+        v = adc * self.vadc / (1024 )   # convert the 10 bit ADC value to a voltage
+        r = self.rp * v / (self.vcc - v)    # resistance of thermistor
+        lnr = log(r)
+        Tinv = self.c1 + (self.c2*lnr) + (self.c3*pow(lnr,3))
+        return (1/Tinv) - 273.15        # temperature
+
+    def adc(self,temp):
+        "Convert temperature into a ADC reading"
+        y = (self.c1 - (1/(temp+273.15))) / (2*self.c3)
+	x = sqrt(pow(self.c2 / (3*self.c3),3) + pow(y,2))
+        r = exp(pow(x-y,1.0/3) - pow(x+y,1.0/3)) # resistance of thermistor
+        return (r / (self.rp + r)) * (1024)
+
+def main(argv):
+
+    rp = 4700;
+    t1 = 25;
+    r1 = 100000;
+    t2 = 150;
+    r2 = 1641.9;
+    t3 = 250;
+    r3 = 226.15;
+    num_temps = int(36);
+    
+    try:
+        opts, args = getopt.getopt(argv, "h", ["help", "rp=", "t1=", "t2=", "t3=", "num-temps="])
+    except getopt.GetoptError:
+        usage()
+        sys.exit(2)
+        
+    for opt, arg in opts:
+        if opt in ("-h", "--help"):
+            usage()
+            sys.exit()
+        elif opt == "--rp":
+            rp = int(arg)
+        elif opt == "--t1":
+            arg =  arg.split(':')
+            t1 = float( arg[0])
+            r1 = float( arg[1])
+        elif opt == "--t2":
+            arg =  arg.split(':')
+            t2 = float( arg[0])
+            r2 = float( arg[1])
+        elif opt == "--t3":
+            arg =  arg.split(':')
+            t3 = float( arg[0])
+            r3 = float( arg[1])
+        elif opt == "--num-temps":
+            num_temps =  int(arg)
+
+    max_adc = (1024 ) - 1
+    min_temp = 0
+    max_temp = 350
+    increment = int(max_adc/(num_temps-1));
+            
+    t = Thermistor(rp, t1, r1, t2, r2, t3, r3)
+    tmp = (min_temp - max_temp) / (num_temps-1)
+    print tmp
+    temps = range(max_temp, min_temp + tmp, tmp);
+
+    print "// Thermistor lookup table for Marlin"
+    print "// ./createTemperatureLookupMarlin.py --rp=%s --t1=%s:%s --t2=%s:%s --t3=%s:%s --num-temps=%s" % (rp, t1, r1, t2, r2, t3, r3, num_temps)
+    print "// Steinhart-Hart Coefficients: %.15g, %.15g,  %.15g " % (t.c1, t.c2, t.c3)
+    print "//#define NUMTEMPS %s" % (len(temps))
+    print "const short temptable[NUMTEMPS][2] PROGMEM = {"
+
+    counter = 0
+    for temp in temps:
+        counter = counter +1
+        if counter == len(temps):
+            print "   {(short)(%.2f*OVERSAMPLENR), %s}  // v=%s r=%s res=%s C/count" % ((t.adc(temp)), temp, t.v(t.adc(temp)), t.r(t.adc(temp)),t.res(t.adc(temp)))
+        else:
+            print "   {(short)(%.2f*OVERSAMPLENR), %s}, // v=%s r=%s res=%s C/count" % ((t.adc(temp)), temp, t.v(t.adc(temp)), t.r(t.adc(temp)),t.res(t.adc(temp)))
+    print "};"
+    
+def usage():
+    print __doc__
+
+if __name__ == "__main__":
+    main(sys.argv[1:])

+ 50 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/create_speed_lookuptable.py

@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+
+""" Generate the stepper delay lookup table for Marlin firmware. """
+
+import argparse
+
+__author__ = "Ben Gamari <bgamari@gmail.com>"
+__copyright__ = "Copyright 2012, Ben Gamari"
+__license__ = "GPL"
+
+parser = argparse.ArgumentParser(description=__doc__)
+parser.add_argument('-f', '--cpu-freq', type=int, default=16, help='CPU clockrate in MHz (default=16)')
+parser.add_argument('-d', '--divider', type=int, default=8, help='Timer/counter pre-scale divider (default=8)')
+args = parser.parse_args()
+
+cpu_freq = args.cpu_freq * 1000000
+timer_freq = cpu_freq / args.divider
+
+print "#ifndef SPEED_LOOKUPTABLE_H"
+print "#define SPEED_LOOKUPTABLE_H"
+print
+print '#include "Marlin.h"'
+print
+
+print "const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {"
+a = [ timer_freq / ((i*256)+(args.cpu_freq*2)) for i in range(256) ]
+b = [ a[i] - a[i+1] for i in range(255) ]
+b.append(b[-1])
+for i in range(32):
+    print "  ",
+    for j in range(8):
+        print "{%d, %d}," % (a[8*i+j], b[8*i+j]),
+    print 
+print "};"
+print
+
+print "const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {"
+a = [ timer_freq / ((i*8)+(args.cpu_freq*2)) for i in range(256) ]
+b = [ a[i] - a[i+1] for i in range(255) ]
+b.append(b[-1])
+for i in range(32):
+    print "  ",
+    for j in range(8):
+        print "{%d, %d}," % (a[8*i+j], b[8*i+j]),
+    print 
+print "};"
+print
+
+print "#endif"
+

+ 54 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/digipot_mcp4451.cpp

@@ -0,0 +1,54 @@
+#include "Configuration.h"
+
+#ifdef DIGIPOT_I2C
+#include "Stream.h"
+#include "utility/twi.h"
+#include "Wire.h"
+
+// Settings for the I2C based DIGIPOT (MCP4451) on Azteeg X3 Pro
+#define DIGIPOT_I2C_FACTOR 106.7
+#define DIGIPOT_I2C_MAX_CURRENT 2.5
+
+static byte current_to_wiper( float current ){
+    return byte(ceil(float((DIGIPOT_I2C_FACTOR*current))));
+}
+
+static void i2c_send(byte addr, byte a, byte b)
+{
+	Wire.beginTransmission(addr);
+    Wire.write(a);
+    Wire.write(b);
+    Wire.endTransmission();
+}
+
+// This is for the MCP4451 I2C based digipot
+void digipot_i2c_set_current( int channel, float current )
+{
+    current = min( (float) max( current, 0.0f ), DIGIPOT_I2C_MAX_CURRENT);
+    // these addresses are specific to Azteeg X3 Pro, can be set to others,
+    // In this case first digipot is at address A0=0, A1= 0, second one is at A0=0, A1= 1
+    byte addr= 0x2C; // channel 0-3
+    if(channel >= 4) {
+    	addr= 0x2E; // channel 4-7
+    	channel-= 4;
+    }
+
+    // Initial setup
+    i2c_send( addr, 0x40, 0xff );
+    i2c_send( addr, 0xA0, 0xff );
+
+    // Set actual wiper value
+    byte addresses[4] = { 0x00, 0x10, 0x60, 0x70 };
+    i2c_send( addr, addresses[channel], current_to_wiper(current) );
+}
+
+void digipot_i2c_init()
+{
+    const float digipot_motor_current[] = DIGIPOT_I2C_MOTOR_CURRENTS;
+    Wire.begin();
+    // setup initial currents as defined in Configuration_adv.h
+    for(int i=0;i<=sizeof(digipot_motor_current)/sizeof(float);i++) {
+        digipot_i2c_set_current(i, digipot_motor_current[i]);
+    }
+}
+#endif

+ 599 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/dogm_font_data_marlin.h

@@ -0,0 +1,599 @@
+/*
+  Fontname: -Misc-Fixed-Medium-R-Normal--9-90-75-75-C-60-ISO10646-1
+  Copyright: Public domain font.  Share and enjoy.
+  Capital A Height: 6, '1' Height: 6
+  Calculated Max Values w= 6 h= 9 x= 2 y= 7 dx= 6 dy= 0 ascent= 7 len= 9
+  Font Bounding box     w= 6 h= 9 x= 0 y=-2
+  Calculated Min Values           x= 0 y=-2 dx= 0 dy= 0
+  Pure Font   ascent = 6 descent=-2
+  X Font      ascent = 6 descent=-2
+  Max Font    ascent = 7 descent=-2
+*/
+#include <utility/u8g.h>
+const u8g_fntpgm_uint8_t u8g_font_6x9[2300] U8G_SECTION(".progmem.u8g_font_6x9") = {
+  0,6,9,0,254,6,1,137,2,254,32,255,254,7,254,6,
+  254,0,0,0,6,0,7,1,6,6,6,2,0,128,128,128,
+  128,0,128,3,3,3,6,1,3,160,160,160,5,7,7,6,
+  0,255,80,80,248,80,248,80,80,5,9,9,6,0,254,32,
+  112,168,160,112,40,168,112,32,6,8,8,6,0,255,64,168,
+  72,16,32,72,84,8,5,7,7,6,0,255,96,144,144,96,
+  152,144,104,1,3,3,6,2,3,128,128,128,2,7,7,6,
+  2,255,64,128,128,128,128,128,64,2,7,7,6,2,255,128,
+  64,64,64,64,64,128,5,5,5,6,0,0,136,80,248,80,
+  136,5,5,5,6,0,0,32,32,248,32,32,2,4,4,6,
+  2,254,192,64,64,128,5,1,1,6,0,2,248,2,2,2,
+  6,2,0,192,192,4,6,6,6,1,0,16,16,32,64,128,
+  128,4,6,6,6,1,0,96,144,144,144,144,96,3,6,6,
+  6,1,0,64,192,64,64,64,224,4,6,6,6,1,0,96,
+  144,16,32,64,240,4,6,6,6,1,0,240,32,96,16,16,
+  224,5,6,6,6,0,0,16,48,80,144,248,16,4,6,6,
+  6,1,0,240,128,224,16,16,224,4,6,6,6,1,0,96,
+  128,224,144,144,96,4,6,6,6,1,0,240,16,16,32,64,
+  64,4,6,6,6,1,0,96,144,96,144,144,96,4,6,6,
+  6,1,0,96,144,144,112,16,96,2,5,5,6,2,0,192,
+  192,0,192,192,2,7,7,6,2,254,192,192,0,192,64,64,
+  128,5,5,5,6,0,0,24,96,128,96,24,5,3,3,6,
+  0,1,248,0,248,5,5,5,6,0,0,192,48,8,48,192,
+  4,7,7,6,1,0,96,144,16,96,64,0,64,5,6,6,
+  6,0,0,112,144,168,176,128,112,5,6,6,6,0,0,32,
+  80,136,248,136,136,5,6,6,6,0,0,240,136,240,136,136,
+  240,4,6,6,6,1,0,96,144,128,128,144,96,4,6,6,
+  6,1,0,224,144,144,144,144,224,4,6,6,6,1,0,240,
+  128,224,128,128,240,4,6,6,6,1,0,240,128,224,128,128,
+  128,4,6,6,6,1,0,96,144,128,176,144,96,4,6,6,
+  6,1,0,144,144,240,144,144,144,3,6,6,6,1,0,224,
+  64,64,64,64,224,5,6,6,6,0,0,56,16,16,16,144,
+  96,4,6,6,6,1,0,144,160,192,160,144,144,4,6,6,
+  6,1,0,128,128,128,128,128,240,5,6,6,6,0,0,136,
+  216,168,168,136,136,4,6,6,6,1,0,144,208,176,144,144,
+  144,5,6,6,6,0,0,112,136,136,136,136,112,4,6,6,
+  6,1,0,224,144,144,224,128,128,4,7,7,6,1,255,96,
+  144,144,208,176,96,16,4,6,6,6,1,0,224,144,144,224,
+  144,144,4,6,6,6,1,0,96,144,64,32,144,96,5,6,
+  6,6,0,0,248,32,32,32,32,32,4,6,6,6,1,0,
+  144,144,144,144,144,96,4,6,6,6,1,0,144,144,144,240,
+  96,96,5,6,6,6,0,0,136,136,168,168,216,136,5,6,
+  6,6,0,0,136,80,32,32,80,136,5,6,6,6,0,0,
+  136,136,80,32,32,32,4,6,6,6,1,0,240,16,32,64,
+  128,240,3,6,6,6,1,0,224,128,128,128,128,224,4,6,
+  6,6,1,0,128,128,64,32,16,16,3,6,6,6,1,0,
+  224,32,32,32,32,224,5,3,3,6,0,3,32,80,136,5,
+  1,1,6,0,254,248,2,2,2,6,2,4,128,64,4,4,
+  4,6,1,0,112,144,144,112,4,6,6,6,1,0,128,128,
+  224,144,144,224,4,4,4,6,1,0,112,128,128,112,4,6,
+  6,6,1,0,16,16,112,144,144,112,4,4,4,6,1,0,
+  96,176,192,112,4,6,6,6,1,0,32,80,64,224,64,64,
+  4,6,6,6,1,254,96,144,144,112,16,96,4,6,6,6,
+  1,0,128,128,224,144,144,144,3,6,6,6,1,0,64,0,
+  192,64,64,224,3,8,8,6,1,254,32,0,96,32,32,32,
+  160,64,4,6,6,6,1,0,128,128,160,192,160,144,3,6,
+  6,6,1,0,192,64,64,64,64,224,5,4,4,6,0,0,
+  208,168,168,136,4,4,4,6,1,0,224,144,144,144,4,4,
+  4,6,1,0,96,144,144,96,4,6,6,6,1,254,224,144,
+  144,224,128,128,4,6,6,6,1,254,112,144,144,112,16,16,
+  4,4,4,6,1,0,160,208,128,128,4,4,4,6,1,0,
+  112,192,48,224,4,6,6,6,1,0,64,64,224,64,80,32,
+  4,4,4,6,1,0,144,144,144,112,4,4,4,6,1,0,
+  144,144,96,96,5,4,4,6,0,0,136,168,168,80,4,4,
+  4,6,1,0,144,96,96,144,4,6,6,6,1,254,144,144,
+  144,112,144,96,4,4,4,6,1,0,240,32,64,240,3,7,
+  7,6,1,0,32,64,64,128,64,64,32,1,7,7,6,2,
+  255,128,128,128,128,128,128,128,3,7,7,6,1,0,128,64,
+  64,32,64,64,128,4,2,2,6,1,3,80,160,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,
+  0,6,0,7,1,6,6,6,2,0,128,0,128,128,128,128,
+  4,6,6,6,1,255,32,112,160,160,112,32,5,7,7,6,
+  0,255,48,72,64,240,64,64,248,5,5,5,6,0,0,168,
+  80,136,80,168,5,6,6,6,0,0,136,80,248,32,248,32,
+  1,7,7,6,2,255,128,128,128,0,128,128,128,4,7,7,
+  6,1,255,112,128,96,144,96,16,224,3,1,1,6,1,5,
+  160,6,7,7,6,0,0,120,132,148,164,148,132,120,3,5,
+  5,6,1,1,96,160,96,0,224,5,5,5,6,0,0,40,
+  80,160,80,40,4,3,3,6,1,0,240,16,16,4,1,1,
+  6,1,2,240,6,7,7,6,0,0,120,132,180,164,164,132,
+  120,4,1,1,6,1,5,240,4,3,3,6,1,2,96,144,
+  96,5,7,7,6,0,255,32,32,248,32,32,0,248,3,5,
+  5,6,1,1,64,160,32,64,224,3,5,5,6,1,1,192,
+  32,64,32,192,2,2,2,6,2,4,64,128,4,5,5,6,
+  1,255,144,144,176,208,128,5,6,6,6,0,0,120,232,232,
+  104,40,40,1,1,1,6,2,2,128,2,2,2,6,2,254,
+  64,128,3,5,5,6,1,1,64,192,64,64,224,3,5,5,
+  6,1,1,64,160,64,0,224,5,5,5,6,0,0,160,80,
+  40,80,160,5,8,8,6,0,255,64,192,64,80,112,48,120,
+  16,5,8,8,6,0,255,64,192,64,80,104,8,16,56,5,
+  8,8,6,0,255,192,32,64,48,240,48,120,16,4,7,7,
+  6,1,0,32,0,32,96,128,144,96,5,7,7,6,0,0,
+  64,32,32,80,112,136,136,5,7,7,6,0,0,16,32,32,
+  80,112,136,136,5,7,7,6,0,0,32,80,32,80,112,136,
+  136,5,7,7,6,0,0,40,80,32,80,112,136,136,5,7,
+  7,6,0,0,80,0,32,80,112,136,136,5,7,7,6,0,
+  0,32,80,32,80,112,136,136,5,6,6,6,0,0,120,160,
+  240,160,160,184,4,8,8,6,1,254,96,144,128,128,144,96,
+  32,64,4,7,7,6,1,0,64,32,240,128,224,128,240,4,
+  7,7,6,1,0,32,64,240,128,224,128,240,4,7,7,6,
+  1,0,32,80,240,128,224,128,240,4,7,7,6,1,0,80,
+  0,240,128,224,128,240,3,7,7,6,1,0,128,64,224,64,
+  64,64,224,3,7,7,6,1,0,32,64,224,64,64,64,224,
+  3,7,7,6,1,0,64,160,224,64,64,64,224,3,7,7,
+  6,1,0,160,0,224,64,64,64,224,5,6,6,6,0,0,
+  112,72,232,72,72,112,4,7,7,6,1,0,80,160,144,208,
+  176,144,144,4,7,7,6,1,0,64,32,96,144,144,144,96,
+  4,7,7,6,1,0,32,64,96,144,144,144,96,4,7,7,
+  6,1,0,32,80,96,144,144,144,96,4,7,7,6,1,0,
+  80,160,96,144,144,144,96,4,7,7,6,1,0,80,0,96,
+  144,144,144,96,5,5,5,6,0,0,136,80,32,80,136,4,
+  8,8,6,1,255,16,112,176,176,208,208,224,128,4,7,7,
+  6,1,0,64,32,144,144,144,144,96,4,7,7,6,1,0,
+  32,64,144,144,144,144,96,4,7,7,6,1,0,32,80,144,
+  144,144,144,96,4,7,7,6,1,0,80,0,144,144,144,144,
+  96,5,7,7,6,0,0,16,32,136,80,32,32,32,4,6,
+  6,6,1,0,128,224,144,144,224,128,4,6,6,6,1,0,
+  96,144,160,160,144,160,4,7,7,6,1,0,64,32,0,112,
+  144,144,112,4,7,7,6,1,0,32,64,0,112,144,144,112,
+  4,7,7,6,1,0,32,80,0,112,144,144,112,4,7,7,
+  6,1,0,80,160,0,112,144,144,112,4,6,6,6,1,0,
+  80,0,112,144,144,112,4,7,7,6,1,0,32,80,32,112,
+  144,144,112,5,4,4,6,0,0,112,168,176,120,4,6,6,
+  6,1,254,112,128,128,112,32,64,4,7,7,6,1,0,64,
+  32,0,96,176,192,112,4,7,7,6,1,0,32,64,0,96,
+  176,192,112,4,7,7,6,1,0,32,80,0,96,176,192,112,
+  4,6,6,6,1,0,80,0,96,176,192,112,3,7,7,6,
+  1,0,128,64,0,192,64,64,224,3,7,7,6,1,0,32,
+  64,0,192,64,64,224,3,7,7,6,1,0,64,160,0,192,
+  64,64,224,3,6,6,6,1,0,160,0,192,64,64,224,4,
+  7,7,6,1,0,48,96,16,112,144,144,96,4,7,7,6,
+  1,0,80,160,0,224,144,144,144,4,7,7,6,1,0,64,
+  32,0,96,144,144,96,4,7,7,6,1,0,32,64,0,96,
+  144,144,96,4,7,7,6,1,0,32,80,0,96,144,144,96,
+  4,7,7,6,1,0,80,160,0,96,144,144,96,4,6,6,
+  6,1,0,80,0,96,144,144,96,5,5,5,6,0,0,32,
+  0,248,0,32,4,4,4,6,1,0,112,176,208,224,4,7,
+  7,6,1,0,64,32,0,144,144,144,112,4,7,7,6,1,
+  0,32,64,0,144,144,144,112,4,7,7,6,1,0,32,80,
+  0,144,144,144,112,4,6,6,6,1,0,80,0,144,144,144,
+  112,4,9,9,6,1,254,32,64,0,144,144,144,112,144,96,
+  4,8,8,6,1,254,128,128,224,144,144,224,128,128,4,8,
+  8,6,1,254,80,0,144,144,144,112,144,96};
+
+// STB Marlin
+/*
+  Fontname: u8g_font_6x10_marlin
+  Copyright: Public domain terminal emulator font.  Share and enjoy.
+  Capital A Height: 7, '1' Height: 7
+  Calculated Max Values w= 6 h=10 x= 2 y= 7 dx= 6 dy= 0 ascent= 8 len=10
+  Font Bounding box     w= 6 h= 9 x= 0 y=-2
+  Calculated Min Values           x= 0 y=-2 dx= 0 dy= 0
+  Pure Font   ascent = 7 descent=-2
+  X Font      ascent = 7 descent=-2
+  Max Font    ascent = 8 descent=-2
+*/
+#include <utility/u8g.h>
+const u8g_fntpgm_uint8_t u8g_font_6x10_marlin[2617] U8G_SECTION(".progmem.u8g_font_6x10_marlin") = {
+  0,6,9,0,254,7,1,153,3,43,32,255,254,8,254,7,
+  254,0,0,0,6,0,0,1,7,7,6,2,0,128,128,128,
+  128,128,0,128,3,3,3,6,1,4,160,160,160,5,7,7,
+  6,0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,
+  32,112,160,112,40,112,32,5,7,7,6,0,0,72,168,80,
+  32,80,168,144,5,7,7,6,0,0,64,160,160,64,168,144,
+  104,1,3,3,6,2,4,128,128,128,3,7,7,6,1,0,
+  32,64,128,128,128,64,32,3,7,7,6,1,0,128,64,32,
+  32,32,64,128,5,5,5,6,0,1,136,80,248,80,136,5,
+  5,5,6,0,1,32,32,248,32,32,3,3,3,6,1,255,
+  96,64,128,5,1,1,6,0,3,248,3,3,3,6,1,255,
+  64,224,64,5,7,7,6,0,0,8,8,16,32,64,128,128,
+  5,7,7,6,0,0,32,80,136,136,136,80,32,5,7,7,
+  6,0,0,32,96,160,32,32,32,248,5,7,7,6,0,0,
+  112,136,8,48,64,128,248,5,7,7,6,0,0,248,8,16,
+  48,8,136,112,5,7,7,6,0,0,16,48,80,144,248,16,
+  16,5,7,7,6,0,0,248,128,176,200,8,136,112,5,7,
+  7,6,0,0,48,64,128,176,200,136,112,5,7,7,6,0,
+  0,248,8,16,16,32,64,64,5,7,7,6,0,0,112,136,
+  136,112,136,136,112,5,7,7,6,0,0,112,136,152,104,8,
+  16,96,3,7,7,6,1,255,64,224,64,0,64,224,64,3,
+  7,7,6,1,255,64,224,64,0,96,64,128,4,7,7,6,
+  1,0,16,32,64,128,64,32,16,5,3,3,6,0,2,248,
+  0,248,4,7,7,6,1,0,128,64,32,16,32,64,128,5,
+  7,7,6,0,0,112,136,16,32,32,0,32,5,7,7,6,
+  0,0,112,136,152,168,176,128,112,5,7,7,6,0,0,32,
+  80,136,136,248,136,136,5,7,7,6,0,0,240,72,72,112,
+  72,72,240,5,7,7,6,0,0,112,136,128,128,128,136,112,
+  5,7,7,6,0,0,240,72,72,72,72,72,240,5,7,7,
+  6,0,0,248,128,128,240,128,128,248,5,7,7,6,0,0,
+  248,128,128,240,128,128,128,5,7,7,6,0,0,112,136,128,
+  128,152,136,112,5,7,7,6,0,0,136,136,136,248,136,136,
+  136,3,7,7,6,1,0,224,64,64,64,64,64,224,5,7,
+  7,6,0,0,56,16,16,16,16,144,96,5,7,7,6,0,
+  0,136,144,160,192,160,144,136,5,7,7,6,0,0,128,128,
+  128,128,128,128,248,5,7,7,6,0,0,136,136,216,168,136,
+  136,136,5,7,7,6,0,0,136,136,200,168,152,136,136,5,
+  7,7,6,0,0,112,136,136,136,136,136,112,5,7,7,6,
+  0,0,240,136,136,240,128,128,128,5,8,8,6,0,255,112,
+  136,136,136,136,168,112,8,5,7,7,6,0,0,240,136,136,
+  240,160,144,136,5,7,7,6,0,0,112,136,128,112,8,136,
+  112,5,7,7,6,0,0,248,32,32,32,32,32,32,5,7,
+  7,6,0,0,136,136,136,136,136,136,112,5,7,7,6,0,
+  0,136,136,136,80,80,80,32,5,7,7,6,0,0,136,136,
+  136,168,168,216,136,5,7,7,6,0,0,136,136,80,32,80,
+  136,136,5,7,7,6,0,0,136,136,80,32,32,32,32,5,
+  7,7,6,0,0,248,8,16,32,64,128,248,3,7,7,6,
+  1,0,224,128,128,128,128,128,224,5,7,7,6,0,0,128,
+  128,64,32,16,8,8,3,7,7,6,1,0,224,32,32,32,
+  32,32,224,5,3,3,6,0,4,32,80,136,5,1,1,6,
+  0,255,248,2,2,2,6,2,6,128,64,5,5,5,6,0,
+  0,112,8,120,136,120,5,7,7,6,0,0,128,128,176,200,
+  136,200,176,5,5,5,6,0,0,112,136,128,136,112,5,7,
+  7,6,0,0,8,8,104,152,136,152,104,5,5,5,6,0,
+  0,112,136,248,128,112,5,7,7,6,0,0,48,72,64,240,
+  64,64,64,5,7,7,6,0,254,120,136,136,120,8,136,112,
+  5,7,7,6,0,0,128,128,176,200,136,136,136,3,7,7,
+  6,1,0,64,0,192,64,64,64,224,4,9,9,6,1,254,
+  16,0,48,16,16,16,144,144,96,5,7,7,6,0,0,128,
+  128,136,144,224,144,136,3,7,7,6,1,0,192,64,64,64,
+  64,64,224,5,5,5,6,0,0,208,168,168,168,136,5,5,
+  5,6,0,0,176,200,136,136,136,5,5,5,6,0,0,112,
+  136,136,136,112,5,7,7,6,0,254,176,200,136,200,176,128,
+  128,5,7,7,6,0,254,104,152,136,152,104,8,8,5,5,
+  5,6,0,0,176,200,128,128,128,5,5,5,6,0,0,112,
+  128,112,8,240,5,7,7,6,0,0,64,64,240,64,64,72,
+  48,5,5,5,6,0,0,136,136,136,152,104,5,5,5,6,
+  0,0,136,136,80,80,32,5,5,5,6,0,0,136,136,168,
+  168,80,5,5,5,6,0,0,136,80,32,80,136,5,7,7,
+  6,0,254,136,136,152,104,8,136,112,5,5,5,6,0,0,
+  248,16,32,64,248,4,7,7,6,1,0,48,64,32,192,32,
+  64,48,1,7,7,6,2,0,128,128,128,128,128,128,128,4,
+  7,7,6,1,0,192,32,64,48,64,32,192,5,3,3,6,
+  0,4,72,168,144,0,0,0,1,0,0,0,0,0,1,0,
+  0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,
+  1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,
+  0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,
+  0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,
+  1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,
+  0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,
+  0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,
+  1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,
+  0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,
+  0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,
+  1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,
+  0,0,1,0,0,0,0,0,1,0,0,0,0,0,6,0,
+  0,1,7,7,6,2,0,128,0,128,128,128,128,128,5,7,
+  7,6,0,255,32,120,160,160,160,120,32,5,7,7,6,0,
+  0,48,72,64,224,64,72,176,5,5,5,6,0,0,136,112,
+  80,112,136,5,8,8,6,0,255,136,136,80,32,248,32,32,
+  32,1,7,7,6,2,0,128,128,128,0,128,128,128,5,8,
+  8,6,0,255,112,128,224,144,72,56,8,112,3,1,1,6,
+  1,7,160,5,7,7,6,0,0,112,136,168,200,168,136,112,
+  4,6,6,6,1,1,112,144,176,80,0,240,6,5,5,6,
+  0,0,36,72,144,72,36,4,2,2,6,1,2,240,16,4,
+  1,1,6,1,3,240,5,7,7,6,0,0,112,136,232,200,
+  200,136,112,5,1,1,6,0,7,248,3,3,3,6,1,4,
+  64,160,64,5,6,6,6,0,0,32,32,248,32,32,248,4,
+  5,5,6,1,3,96,144,32,64,240,4,5,5,6,1,3,
+  224,16,96,16,224,2,2,2,6,2,6,64,128,5,6,6,
+  6,0,255,136,136,136,200,176,128,5,7,7,6,0,0,120,
+  232,232,104,40,40,40,1,1,1,6,2,3,128,2,2,2,
+  6,2,254,64,128,3,5,5,6,1,3,64,192,64,64,224,
+  4,6,6,6,1,1,96,144,144,96,0,240,6,5,5,6,
+  0,0,144,72,36,72,144,6,9,9,6,0,255,64,192,64,
+  64,228,12,20,60,4,6,9,9,6,0,255,64,192,64,64,
+  232,20,4,8,28,5,9,9,6,0,255,192,32,64,32,200,
+  24,40,120,8,5,7,7,6,0,0,32,0,32,32,64,136,
+  112,5,8,8,6,0,0,64,32,112,136,136,248,136,136,5,
+  8,8,6,0,0,16,32,112,136,136,248,136,136,5,8,8,
+  6,0,0,32,80,112,136,136,248,136,136,5,8,8,6,0,
+  0,72,176,112,136,136,248,136,136,5,8,8,6,0,0,80,
+  0,112,136,136,248,136,136,5,8,8,6,0,0,32,80,112,
+  136,136,248,136,136,6,7,7,6,0,0,60,80,144,156,240,
+  144,156,5,9,9,6,0,254,112,136,128,128,128,136,112,32,
+  64,5,8,8,6,0,0,64,248,128,128,240,128,128,248,5,
+  8,8,6,0,0,16,248,128,128,240,128,128,248,5,8,8,
+  6,0,0,32,248,128,128,240,128,128,248,5,8,8,6,0,
+  0,80,248,128,128,240,128,128,248,3,8,8,6,1,0,128,
+  64,224,64,64,64,64,224,3,8,8,6,1,0,32,64,224,
+  64,64,64,64,224,3,8,8,6,1,0,64,160,224,64,64,
+  64,64,224,3,8,8,6,1,0,160,0,224,64,64,64,64,
+  224,5,7,7,6,0,0,240,72,72,232,72,72,240,5,8,
+  8,6,0,0,40,80,136,200,168,152,136,136,5,8,8,6,
+  0,0,64,32,112,136,136,136,136,112,5,8,8,6,0,0,
+  16,32,112,136,136,136,136,112,5,8,8,6,0,0,32,80,
+  112,136,136,136,136,112,5,8,8,6,0,0,40,80,112,136,
+  136,136,136,112,5,8,8,6,0,0,80,0,112,136,136,136,
+  136,112,5,5,5,6,0,0,136,80,32,80,136,5,7,7,
+  6,0,0,112,152,152,168,200,200,112,5,8,8,6,0,0,
+  64,32,136,136,136,136,136,112,5,8,8,6,0,0,16,32,
+  136,136,136,136,136,112,5,8,8,6,0,0,32,80,0,136,
+  136,136,136,112,5,8,8,6,0,0,80,0,136,136,136,136,
+  136,112,5,8,8,6,0,0,16,32,136,136,80,32,32,32,
+  5,7,7,6,0,0,128,240,136,240,128,128,128,5,7,7,
+  6,0,0,112,136,144,160,144,136,176,5,8,8,6,0,0,
+  64,32,0,112,8,120,136,120,5,8,8,6,0,0,16,32,
+  0,112,8,120,136,120,5,8,8,6,0,0,32,80,0,112,
+  8,120,136,120,5,8,8,6,0,0,40,80,0,112,8,120,
+  136,120,5,7,7,6,0,0,80,0,112,8,120,136,120,5,
+  8,8,6,0,0,32,80,32,112,8,120,136,120,6,5,5,
+  6,0,0,120,20,124,144,124,5,7,7,6,0,254,112,136,
+  128,136,112,32,64,5,8,8,6,0,0,64,32,0,112,136,
+  248,128,112,5,8,8,6,0,0,16,32,0,112,136,248,128,
+  112,5,8,8,6,0,0,32,80,0,112,136,248,128,112,5,
+  7,7,6,0,0,80,0,112,136,248,128,112,3,8,8,6,
+  1,0,128,64,0,192,64,64,64,224,3,8,8,6,1,0,
+  64,128,0,192,64,64,64,224,3,8,8,6,1,0,64,160,
+  0,192,64,64,64,224,6,10,10,6,0,254,164,168,0,252,
+  132,128,128,128,132,252,6,10,10,6,0,254,84,148,0,252,
+  132,4,4,4,132,252,5,8,8,6,0,0,40,80,0,176,
+  200,136,136,136,5,8,8,6,0,0,64,32,0,112,136,136,
+  136,112,4,10,10,6,2,254,48,64,128,144,144,144,144,144,
+  144,144,4,10,10,6,0,254,192,32,16,144,144,144,144,144,
+  144,144,6,7,7,6,0,1,68,140,140,132,128,64,60,6,
+  7,7,6,0,1,136,196,196,132,4,8,240,5,5,5,6,
+  0,1,32,0,248,0,32,5,8,8,6,0,0,64,240,200,
+  136,136,152,120,16,5,8,8,6,0,0,224,248,136,136,136,
+  136,136,248,5,5,5,6,0,1,32,48,248,48,32,5,8,
+  8,6,0,0,32,112,248,32,32,32,32,224,5,9,9,6,
+  0,255,32,112,168,168,184,136,136,80,32,5,9,9,6,0,
+  255,224,128,192,176,168,168,48,40,40,5,9,9,6,0,255,
+  248,168,136,136,136,136,136,168,248,5,10,10,6,0,254,32,
+  80,80,80,80,136,168,168,136,112};
+
+/*
+  Fontname: -Firefly-Firefly New Sung-Medium-R-Normal--11-110-75-75-P-109-ISO10646-1
+  Copyright: 
+  Capital A Height: 9, '1' Height: 9
+  Calculated Max Values w=11 h=11 x= 4 y= 6 dx=11 dy= 0 ascent=10 len=22
+  Font Bounding box     w=11 h=11 x= 0 y=-1
+  Calculated Min Values           x= 0 y=-1 dx= 0 dy= 0
+  Pure Font   ascent = 9 descent=-1
+  X Font      ascent = 9 descent=-1
+  Max Font    ascent =10 descent=-1
+  
+  Added By MakerLab.me for Chinese Support.
+*/
+
+#if LANGUAGE_CHOICE == 10
+
+#include "utility/u8g.h"
+
+const u8g_fntpgm_uint8_t chinese[3819] U8G_SECTION(".progmem.chinese") = {
+    0,11,11,0,255,9,1,207,3,158,32,255,255,10,255,9,
+  255,0,0,0,6,0,1,1,9,9,6,2,0,128,128,128,
+  128,128,128,0,0,128,5,3,3,6,0,6,216,72,144,6,
+  9,9,6,0,0,40,40,40,124,40,252,80,80,80,5,9,
+  9,6,0,0,32,112,168,160,112,40,168,112,32,6,10,10,
+  6,0,255,72,168,168,176,80,40,84,84,148,136,5,9,9,
+  6,0,0,32,80,80,80,96,168,144,144,104,2,3,3,6,
+  2,6,192,64,128,3,10,10,6,1,255,32,64,64,128,128,
+  128,128,64,64,32,3,10,10,6,1,255,128,64,64,32,32,
+  32,32,64,64,128,5,7,7,6,0,1,32,168,112,32,112,
+  168,32,5,7,7,6,0,1,32,32,32,248,32,32,32,2,
+  3,3,6,2,0,192,64,128,5,1,1,6,0,4,248,1,
+  2,2,6,2,0,128,128,5,10,10,6,0,255,8,8,16,
+  16,32,32,64,64,128,128,5,9,9,6,0,0,32,80,136,
+  136,136,136,136,80,32,3,9,9,6,1,0,64,192,64,64,
+  64,64,64,64,224,5,9,9,6,0,0,112,136,136,8,16,
+  32,64,136,248,5,9,9,6,0,0,112,136,8,8,48,8,
+  8,136,112,5,9,9,6,0,0,16,48,48,80,80,144,248,
+  16,56,5,9,9,6,0,0,120,64,64,64,112,8,8,136,
+  112,5,9,9,6,0,0,112,136,128,128,240,136,136,136,112,
+  5,9,9,6,0,0,248,136,8,16,16,32,32,32,32,5,
+  9,9,6,0,0,112,136,136,136,112,136,136,136,112,5,9,
+  9,6,0,0,112,136,136,136,120,8,8,136,112,1,7,7,
+  6,2,1,128,128,0,0,0,128,128,2,7,7,6,2,0,
+  192,192,0,0,192,64,128,5,10,10,6,0,255,8,16,32,
+  64,128,128,64,32,16,8,5,3,3,6,0,2,248,0,248,
+  5,10,10,6,0,255,128,64,32,16,8,8,16,32,64,128,
+  5,9,9,6,0,0,112,136,136,16,32,32,32,0,32,6,
+  10,10,6,0,255,48,72,180,212,212,212,212,168,128,120,5,
+  9,9,6,0,0,32,32,32,80,80,112,136,136,136,5,9,
+  9,6,0,0,240,136,136,136,240,136,136,136,240,5,9,9,
+  6,0,0,48,72,136,128,128,128,128,72,48,5,9,9,6,
+  0,0,224,144,136,136,136,136,136,144,224,5,9,9,6,0,
+  0,248,128,128,128,240,128,128,128,248,5,9,9,6,0,0,
+  248,128,128,128,240,128,128,128,128,5,9,9,6,0,0,48,
+  72,128,128,128,152,136,72,48,5,9,9,6,0,0,136,136,
+  136,136,248,136,136,136,136,3,9,9,6,1,0,224,64,64,
+  64,64,64,64,64,224,5,9,9,6,0,0,56,16,16,16,
+  16,16,16,144,96,5,9,9,6,0,0,136,136,144,160,224,
+  144,144,136,136,5,9,9,6,0,0,224,64,64,64,64,64,
+  64,72,248,5,9,9,6,0,0,136,136,216,216,168,168,168,
+  136,136,5,9,9,6,0,0,136,200,200,168,168,168,152,152,
+  136,5,9,9,6,0,0,112,136,136,136,136,136,136,136,112,
+  5,9,9,6,0,0,240,72,72,72,112,64,64,64,224,5,
+  9,9,6,0,0,112,136,136,136,136,232,152,112,8,5,9,
+  9,6,0,0,240,136,136,136,240,160,144,136,136,5,9,9,
+  6,0,0,112,136,136,128,112,8,136,136,112,5,9,9,6,
+  0,0,248,168,32,32,32,32,32,32,112,5,9,9,6,0,
+  0,136,136,136,136,136,136,136,136,112,5,9,9,6,0,0,
+  136,136,136,80,80,80,32,32,32,5,9,9,6,0,0,168,
+  168,168,168,248,80,80,80,80,5,9,9,6,0,0,136,136,
+  80,80,32,80,80,136,136,5,9,9,6,0,0,136,136,80,
+  80,32,32,32,32,32,5,9,9,6,0,0,248,136,16,16,
+  32,32,64,136,248,3,10,10,6,2,255,224,128,128,128,128,
+  128,128,128,128,224,5,10,10,6,0,255,128,128,64,64,32,
+  32,16,16,8,8,3,10,10,6,1,255,224,32,32,32,32,
+  32,32,32,32,224,5,3,3,6,0,6,32,80,136,5,1,
+  1,6,0,255,248,3,3,3,6,1,6,192,64,32,5,6,
+  6,6,0,0,224,16,112,144,144,104,5,9,9,6,0,0,
+  128,128,128,240,136,136,136,200,176,5,6,6,6,0,0,112,
+  136,128,128,136,112,5,9,9,6,0,0,8,8,8,120,136,
+  136,136,152,104,5,6,6,6,0,0,112,136,248,128,136,112,
+  5,9,9,6,0,0,48,72,64,240,64,64,64,64,224,5,
+  7,7,6,0,255,104,144,144,96,144,136,112,5,9,9,6,
+  0,0,128,128,128,176,200,136,136,136,136,3,9,9,6,1,
+  0,64,0,0,192,64,64,64,64,224,4,10,10,6,0,255,
+  16,0,0,48,16,16,16,16,144,96,5,9,9,6,0,0,
+  128,128,136,144,160,192,160,144,136,3,9,9,6,1,0,192,
+  64,64,64,64,64,64,64,224,5,6,6,6,0,0,208,168,
+  168,168,168,168,5,6,6,6,0,0,176,72,72,72,72,72,
+  5,6,6,6,0,0,112,136,136,136,136,112,5,7,7,6,
+  0,255,240,136,136,240,128,128,128,5,7,7,6,0,255,120,
+  136,136,136,120,8,8,5,6,6,6,0,0,208,104,64,64,
+  64,224,5,6,6,6,0,0,112,136,96,16,136,112,5,8,
+  8,6,0,0,64,64,240,64,64,64,72,48,5,6,6,6,
+  0,0,136,136,136,136,152,104,5,6,6,6,0,0,136,136,
+  80,80,32,32,5,6,6,6,0,0,168,168,168,80,80,80,
+  5,6,6,6,0,0,136,80,32,32,80,136,4,7,7,6,
+  1,255,144,144,80,80,32,32,192,5,6,6,6,0,0,248,
+  136,16,32,72,248,3,10,10,6,1,255,32,64,64,64,64,
+  128,64,64,64,32,1,11,11,6,2,255,128,128,128,128,128,
+  128,128,128,128,128,128,3,10,10,6,1,255,128,64,64,64,
+  64,32,64,64,64,128,4,2,2,6,1,4,80,160,10,10,
+  20,11,0,255,48,64,72,64,133,64,121,64,73,64,73,64,
+  89,64,64,64,68,64,61,192,10,10,20,11,0,255,4,0,
+  255,192,144,64,31,0,49,0,78,0,17,0,255,192,33,0,
+  63,0,9,10,20,11,1,255,8,0,255,128,160,128,24,0,
+  72,0,40,0,255,128,8,0,54,0,193,128,11,10,20,11,
+  0,255,113,0,99,0,164,192,175,128,240,0,18,64,89,128,
+  148,128,17,0,47,224,9,10,20,11,1,255,8,0,255,128,
+  128,128,127,0,34,0,125,0,8,0,127,0,8,0,255,128,
+  9,10,20,11,1,255,8,0,8,0,255,128,136,128,136,128,
+  255,128,136,128,8,0,8,0,8,0,10,10,20,11,0,255,
+  8,0,4,0,255,192,17,0,17,0,10,0,4,0,10,0,
+  49,192,192,128,9,10,20,11,1,255,8,0,255,128,8,0,
+  8,0,127,0,34,0,20,0,8,0,54,0,193,128,10,10,
+  20,11,0,255,33,0,39,192,241,0,47,192,48,128,111,192,
+  168,128,36,128,32,128,99,128,10,10,20,11,0,255,69,0,
+  47,192,9,0,25,0,47,192,41,0,207,192,73,0,73,0,
+  79,192,9,10,20,11,1,255,63,0,82,0,140,0,50,0,
+  193,128,127,0,73,0,127,0,73,0,127,0,10,10,20,11,
+  0,255,39,192,33,0,249,0,33,0,57,0,225,0,33,0,
+  41,0,231,0,66,0,10,10,20,11,0,255,123,192,66,64,
+  66,64,122,64,66,64,74,64,82,64,226,192,66,0,2,0,
+  9,10,20,11,1,255,16,0,255,128,16,0,47,128,97,0,
+  162,0,63,128,34,0,34,0,46,0,10,10,20,11,0,255,
+  97,0,87,192,65,64,247,192,81,0,83,192,86,64,91,192,
+  82,64,67,192,9,10,20,11,1,255,8,0,8,0,15,0,
+  8,0,255,128,8,0,12,0,10,0,9,0,8,0,9,10,
+  20,11,1,255,255,0,1,0,1,0,65,0,127,0,64,0,
+  64,0,64,128,64,128,63,128,10,10,20,11,0,255,33,192,
+  38,0,127,192,34,0,46,192,234,64,46,192,42,64,47,192,
+  104,64,9,10,20,11,1,255,48,0,8,0,8,0,8,0,
+  8,0,8,0,20,0,34,0,65,0,128,128,10,10,20,11,
+  1,255,69,0,68,0,255,128,72,0,105,0,205,0,86,0,
+  82,0,69,0,200,192,9,10,20,11,1,255,8,0,73,0,
+  73,0,73,0,127,0,8,0,136,128,136,128,136,128,255,128,
+  9,10,20,11,1,255,16,0,9,0,255,128,8,0,8,0,
+  127,0,8,0,8,0,9,0,255,128,10,10,20,11,0,255,
+  255,192,18,0,3,128,124,0,37,0,36,64,127,192,22,0,
+  37,128,68,64,9,10,20,11,1,255,34,0,20,0,127,0,
+  73,0,127,0,73,0,127,0,8,0,255,128,8,0,7,10,
+  10,11,2,255,48,32,254,130,254,130,254,130,254,130,10,10,
+  20,11,0,255,114,0,2,0,7,192,250,64,34,64,34,64,
+  66,64,74,64,252,64,9,128,9,10,20,11,1,255,255,128,
+  34,0,34,0,34,0,255,128,34,0,34,0,34,0,66,0,
+  130,0,10,10,20,11,0,255,33,0,34,0,252,64,87,192,
+  80,0,87,192,84,64,36,64,87,192,148,64,9,10,20,11,
+  1,255,34,0,20,0,127,0,8,0,8,0,255,128,8,0,
+  20,0,34,0,193,128,9,9,18,11,1,0,79,128,160,128,
+  132,128,190,128,140,128,148,128,164,128,196,128,129,128,10,10,
+  20,11,0,255,4,0,39,128,36,0,255,192,4,0,20,0,
+  36,128,65,0,6,0,120,0,10,10,20,11,0,255,68,128,
+  36,128,15,192,4,128,228,128,47,192,36,128,40,128,80,0,
+  143,192,11,10,20,11,0,255,119,192,84,0,86,0,165,128,
+  116,128,21,128,53,64,212,64,20,0,23,224,9,10,20,11,
+  1,255,255,128,128,128,190,128,162,128,162,128,190,128,162,128,
+  128,128,255,128,128,128,10,10,20,11,0,255,127,192,68,0,
+  95,128,80,128,95,128,80,128,95,128,85,0,164,128,204,64,
+  9,10,20,11,1,255,8,0,15,128,8,0,127,0,66,0,
+  66,0,126,0,0,0,144,128,18,0,10,10,20,11,1,255,
+  143,0,73,0,9,0,193,192,95,0,73,0,70,0,66,0,
+  77,0,16,192,10,10,20,11,0,255,4,0,127,192,64,64,
+  63,128,4,0,36,0,39,128,36,0,84,0,143,192,10,10,
+  20,11,0,255,119,192,18,0,39,192,157,64,117,64,37,64,
+  37,64,38,0,34,64,44,0,10,10,20,11,0,255,34,0,
+  250,0,39,128,50,128,230,128,35,192,100,64,18,128,73,64,
+  137,64,10,10,20,11,0,255,231,192,164,128,171,0,196,192,
+  169,0,175,192,165,0,239,192,129,0,129,0,10,10,20,11,
+  0,255,79,128,40,128,143,128,88,128,47,128,192,0,95,192,
+  85,64,85,64,127,192,10,10,20,11,0,255,8,0,255,128,
+  136,128,255,128,136,128,255,128,136,128,8,0,8,64,7,192,
+  10,10,20,11,0,255,95,192,49,0,151,192,84,64,55,192,
+  52,64,215,192,81,0,85,128,107,64,10,10,20,11,1,255,
+  66,0,95,128,234,0,70,0,77,192,217,0,73,0,73,0,
+  73,0,17,0,10,10,20,11,0,255,20,0,84,0,87,192,
+  84,128,92,128,82,128,114,128,209,0,18,128,20,64,10,10,
+  20,11,0,255,26,0,227,192,36,64,250,128,39,0,49,192,
+  110,64,162,128,33,0,46,0,10,10,20,11,0,255,1,0,
+  241,0,71,192,165,64,253,64,39,192,53,64,229,64,39,192,
+  36,64,10,10,20,11,0,255,130,0,95,192,2,0,15,128,
+  234,128,47,128,38,0,42,128,82,64,143,192,10,10,20,11,
+  0,255,4,0,127,192,73,0,127,192,73,0,95,128,73,0,
+  70,0,137,0,176,192,9,10,20,11,1,255,36,0,20,0,
+  68,0,36,0,4,0,255,128,8,0,20,0,34,0,193,128,
+  10,10,20,11,0,255,4,0,127,192,66,0,127,192,66,0,
+  75,0,82,128,82,128,162,64,162,64,10,10,20,11,0,255,
+  127,128,64,128,82,128,74,128,68,128,68,128,74,128,82,128,
+  64,128,128,64,9,9,18,11,1,255,127,128,127,128,64,0,
+  123,128,106,128,72,128,138,128,236,128,25,128,10,10,20,11,
+  0,255,34,0,47,192,248,64,37,0,40,128,112,64,175,128,
+  34,0,162,0,95,192,10,10,20,11,0,255,80,64,125,64,
+  145,64,127,64,17,64,125,64,85,64,84,64,92,64,17,192,
+  10,10,20,11,0,255,63,128,32,128,63,128,32,128,255,192,
+  72,0,123,192,74,64,253,128,10,64,9,10,20,11,1,255,
+  8,0,8,0,255,128,8,0,8,0,8,0,20,0,34,0,
+  65,0,128,128,10,10,20,11,0,255,4,0,4,0,4,0,
+  21,0,36,128,68,64,132,64,36,0,28,0,8,0,9,10,
+  20,11,1,255,255,128,136,128,136,128,255,128,136,128,136,128,
+  148,128,162,128,255,128,128,128,10,10,20,11,1,255,162,0,
+  52,0,251,192,180,128,4,128,243,0,83,0,113,0,34,128,
+  204,0,10,10,20,11,0,255,34,0,63,192,32,0,111,128,
+  160,0,47,128,32,0,47,128,40,128,47,128,10,10,20,11,
+  0,255,8,0,63,128,32,128,63,128,32,128,63,128,32,128,
+  63,128,84,128,159,64,9,10,20,11,1,255,127,0,73,0,
+  127,0,73,0,127,0,34,0,83,0,146,128,34,0,66,0,
+  10,10,20,11,0,255,255,192,8,0,127,128,82,128,94,128,
+  82,128,94,128,82,128,127,128,64,128,9,10,20,11,1,255,
+  127,0,8,0,8,0,255,128,20,0,20,0,20,0,36,128,
+  68,128,131,128,10,10,20,11,0,255,32,0,35,192,250,64,
+  42,64,42,64,42,64,42,64,42,64,75,192,146,64,10,11,
+  22,11,0,255,32,0,63,192,32,0,95,128,148,128,18,128,
+  255,192,36,128,63,192,0,128,3,0,10,10,20,11,0,255,
+  79,128,32,0,0,0,31,192,226,0,36,128,41,192,62,64,
+  80,0,143,192,10,10,20,11,0,255,47,128,40,128,40,128,
+  111,128,162,0,63,192,34,0,39,0,42,128,50,64,9,10,
+  20,11,1,255,34,0,127,0,17,0,255,128,42,0,209,128,
+  36,0,25,0,2,0,124,0,9,10,20,11,1,255,35,0,
+  250,128,255,128,66,0,250,128,171,0,249,0,41,0,243,128,
+  36,0,10,10,20,11,0,255,34,0,47,192,178,0,165,0,
+  169,64,53,128,37,0,35,0,36,128,40,64,9,10,20,11,
+  1,255,63,128,97,0,191,0,33,0,63,0,16,0,63,0,
+  82,0,140,0,115,128,10,10,20,11,0,255,127,192,64,0,
+  64,0,64,0,64,0,64,0,64,0,64,0,128,0,128,0,
+  10,10,20,11,0,255,124,64,69,64,125,64,81,64,125,64,
+  85,64,85,64,84,64,156,64,144,192,10,10,20,11,0,255,
+  35,192,250,0,82,0,251,192,34,128,250,128,34,128,114,128,
+  172,128,96,128,9,10,20,11,1,255,95,128,18,128,31,128,
+  210,128,87,128,87,128,117,128,87,128,32,128,1,128,10,10,
+  20,11,0,255,255,0,85,192,125,64,88,128,149,64,127,192,
+  4,0,39,128,36,0,255,192,11,10,20,11,0,255,251,192,
+  82,0,123,224,36,128,244,128,63,0,32,128,63,128,32,128,
+  63,128,10,10,20,11,0,255,34,0,47,192,32,0,103,128,
+  164,128,47,192,48,64,47,128,33,0,35,0,9,10,20,11,
+  1,255,82,0,186,128,182,0,223,128,146,0,211,0,30,128,
+  90,0,146,0,31,128,10,11,22,11,1,255,66,0,143,128,
+  162,0,191,192,200,128,134,0,170,0,223,192,20,0,231,128,
+  24,0,10,10,20,11,0,255,4,0,4,0,4,0,36,0,
+  39,128,36,0,36,0,36,0,36,128,255,192,9,10,20,11,
+  1,255,8,0,8,0,255,128,136,128,136,128,255,128,136,128,
+  136,128,255,128,128,128,10,10,20,11,0,255,18,0,18,0,
+  47,192,98,0,162,0,39,0,42,128,50,64,34,0,34,0,
+  10,10,20,11,1,255,239,128,168,128,175,128,234,128,170,0,
+  239,192,170,0,233,0,168,192,0,64,255,255,255,255,255,255,
+  255,255,255,255,6,10,10,11,3,0,32,16,0,0,120,136,
+  136,136,136,124,6,9,9,11,2,1,32,0,0,112,136,136,
+  136,136,124,255,255,255,255,255,255,5,10,10,11,3,0,64,
+  48,0,0,112,136,248,128,136,112,5,10,10,11,3,0,16,
+  32,0,0,112,136,248,128,136,112,5,9,9,11,3,1,112,
+  8,0,112,136,248,128,136,112,255,3,10,10,11,4,0,128,
+  64,0,0,192,64,64,64,64,224,3,10,10,11,4,0,64,
+  128,0,0,192,64,64,64,64,224,255,255,255,255,5,9,9,
+  11,3,0,64,32,0,112,136,136,136,136,112,5,10,10,11,
+  3,0,16,32,0,0,112,136,136,136,136,112,255,255,255,8,
+  7,7,11,1,1,24,24,0,255,0,24,24,255,6,9,9,
+  11,2,0,32,16,0,204,68,68,68,76,52,11,3,6,11,
+  0,3,0,128,255,224,0,192,3,11,11,11,4,255,64,64,
+  224,64,64,64,64,64,64,64,64,6,9,9,11,2,0,68,
+  0,0,204,68,68,68,76,52,255,255,255
+};
+
+#endif //LANGUAGE_CHOICE == 10
+  

+ 648 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/dogm_lcd_implementation.h

@@ -0,0 +1,648 @@
+/**
+ *dogm_lcd_implementation.h
+ *
+ *Graphics LCD implementation for 128x64 pixel LCDs by STB for ErikZalm/Marlin
+ *Demonstrator: http://www.reprap.org/wiki/STB_Electronics
+ *License: http://opensource.org/licenses/BSD-3-Clause
+ *
+ *With the use of:
+ *u8glib by Oliver Kraus
+ *http://code.google.com/p/u8glib/
+ *License: http://opensource.org/licenses/BSD-3-Clause
+ */
+
+
+#ifndef ULTRA_LCD_IMPLEMENTATION_DOGM_H
+#define ULTRA_LCD_IMPLEMENTATION_DOGM_H
+
+/**
+* Implementation of the LCD display routines for a DOGM128 graphic display. These are common LCD 128x64 pixel graphic displays.
+**/
+
+#ifdef ULTIPANEL
+#define BLEN_A 0
+#define BLEN_B 1
+#define BLEN_C 2
+#define EN_A (1<<BLEN_A)
+#define EN_B (1<<BLEN_B)
+#define EN_C (1<<BLEN_C)
+#define encrot0 0
+#define encrot1 2
+#define encrot2 3
+#define encrot3 1
+#define LCD_CLICKED (buttons&EN_C)
+#endif
+
+#include <U8glib.h>
+#include "DOGMbitmaps.h"
+#include "dogm_font_data_marlin.h"
+#include "ultralcd.h"
+#include "ultralcd_st7920_u8glib_rrd.h"
+
+
+/* Russian language not supported yet, needs custom font
+
+#if LANGUAGE_CHOICE == 6
+#include "LiquidCrystalRus.h"
+#define LCD_CLASS LiquidCrystalRus
+#else
+#include <LiquidCrystal.h>
+#define LCD_CLASS LiquidCrystal
+#endif
+*/
+#if LANGUAGE_CHOICE == 10
+// DOGM parameters (size in pixels)
+#define DOG_CHAR_WIDTH			11
+#define DOG_CHAR_HEIGHT			12
+#define DOG_CHAR_WIDTH_LARGE	11
+#define DOG_CHAR_HEIGHT_LARGE	12
+#else
+// DOGM parameters (size in pixels)
+#define DOG_CHAR_WIDTH			6
+#define DOG_CHAR_HEIGHT			12
+#define DOG_CHAR_WIDTH_LARGE	9
+#define DOG_CHAR_HEIGHT_LARGE	18
+#endif
+
+#define START_ROW				0
+
+
+/* Custom characters defined in font font_6x10_marlin.c */
+#define LCD_STR_BEDTEMP     "\xFE"
+#define LCD_STR_DEGREE      "\xB0"
+#define LCD_STR_THERMOMETER "\xFF"
+#define LCD_STR_UPLEVEL     "\xFB"
+#define LCD_STR_REFRESH     "\xF8"
+#define LCD_STR_FOLDER      "\xF9"
+#define LCD_STR_FEEDRATE    "\xFD"
+#define LCD_STR_CLOCK       "\xFC"
+#define LCD_STR_ARROW_RIGHT "\xFA"
+
+#define FONT_STATUSMENU	u8g_font_6x9
+
+int lcd_contrast;
+
+// LCD selection
+#ifdef U8GLIB_ST7920
+//U8GLIB_ST7920_128X64_RRD u8g(0,0,0);
+U8GLIB_ST7920_128X64_RRD u8g(0);
+#elif defined(MAKRPANEL)
+// The MaKrPanel display, ST7565 controller as well
+U8GLIB_NHD_C12864 u8g(DOGLCD_CS, DOGLCD_A0);
+#elif defined(MINIPANEL)
+// The MINIPanel display
+U8GLIB_MINI12864 u8g(DOGLCD_CS, DOGLCD_A0);
+#elif defined(MULTIPANEL)
+// The MULTIPanel OLED display
+U8GLIB_SSD1309_128X64 u8g(DOGLCD_CS, DOGLCD_A0);
+#else
+// for regular DOGM128 display with HW-SPI
+U8GLIB_DOGM128 u8g(DOGLCD_CS, DOGLCD_A0);	// HW-SPI Com: CS, A0
+#endif
+
+static void lcd_implementation_init()
+{
+#ifdef LCD_PIN_BL
+	pinMode(LCD_PIN_BL, OUTPUT);	// Enable LCD backlight
+	digitalWrite(LCD_PIN_BL, HIGH);
+#endif
+
+#ifndef MINIPANEL//setContrast not working for Mini Panel
+        u8g.setContrast(lcd_contrast);	
+#endif
+	//  Uncomment this if you have the first generation (V1.10) of STBs board
+	//  pinMode(17, OUTPUT);	// Enable LCD backlight
+	//  digitalWrite(17, HIGH);
+	
+	u8g.firstPage();
+	do {
+		u8g.setFont(u8g_font_6x10_marlin);
+		u8g.setColorIndex(1);
+		u8g.drawBox (0, 0, u8g.getWidth(), u8g.getHeight());
+		u8g.setColorIndex(1);
+	   } while( u8g.nextPage() );
+
+#ifdef LCD_SCREEN_ROT_90
+	u8g.setRot90();	// Rotate screen by 90°
+#endif
+
+#ifdef LCD_SCREEN_ROT_180
+	u8g.setRot180();	// Rotate screen by 180°
+#endif
+
+#ifdef LCD_SCREEN_ROT_270
+	u8g.setRot270();	// Rotate screen by 270°
+#endif
+
+   
+	u8g.firstPage();
+	do {
+			// RepRap init bmp
+			u8g.drawBitmapP(0,0,START_BMPBYTEWIDTH,START_BMPHEIGHT,start_bmp);
+			// Welcome message
+	/*		u8g.setFont(u8g_font_6x10_marlin);
+			u8g.drawStr(62,10,"MARLIN"); 
+			u8g.setFont(u8g_font_5x8);
+			u8g.drawStr(62,19,"V1.0.0 RC2-mm");
+			u8g.setFont(u8g_font_6x10_marlin);
+			u8g.drawStr(62,28,"by ErikZalm");
+  #if LANGUAGE_CHOICE == 10
+      u8g.setFont(chinese);
+      u8g.drawStr(62,40,"\x84\x85\x86\x87 By");
+			u8g.drawStr(62,52,"\x7f\x80\x81\x82\x83");
+			u8g.drawStr(62,63,"MakerLab.me");
+  #else
+			u8g.drawStr(62,41,"DOGM128 LCD");
+			u8g.setFont(u8g_font_5x8);
+			u8g.drawStr(62,48,"enhancements");
+			u8g.setFont(u8g_font_5x8);
+			u8g.drawStr(62,55,"by STB, MM");
+			u8g.drawStr(62,61,"uses u");
+			u8g.drawStr90(92,57,"8");
+			u8g.drawStr(100,61,"glib");
+  #endif
+			//u8g.setFont(u8g_font_5x8);
+			//u8g.drawStr(62,61,"uses u");
+			//u8g.drawStr90(92,57,"8");
+			//u8g.drawStr(100,61,"glib");
+*/
+	   } while( u8g.nextPage() );
+}
+
+static void lcd_implementation_clear()
+{
+// NO NEED TO IMPLEMENT LIKE SO. Picture loop automatically clears the display.
+//
+// Check this article: http://arduino.cc/forum/index.php?topic=91395.25;wap2
+//
+//	u8g.firstPage();
+//	do {	
+//			u8g.setColorIndex(0);
+//			u8g.drawBox (0, 0, u8g.getWidth(), u8g.getHeight());
+//			u8g.setColorIndex(1);
+//		} while( u8g.nextPage() );
+}
+
+/* Arduino < 1.0.0 is missing a function to print PROGMEM strings, so we need to implement our own */
+static void lcd_printPGM(const char* str)
+{
+    char c;
+    while((c = pgm_read_byte(str++)) != '\0')
+    {
+			u8g.print(c);
+    }
+}
+
+
+static void lcd_implementation_status_screen()
+{
+
+ static unsigned char fan_rot = 0;
+ 
+ u8g.setColorIndex(1);	// black on white
+ 
+ // Symbols menu graphics, animated fan
+ if ((blink % 2) &&  fanSpeed )	u8g.drawBitmapP(0,1,STATUS_SCREENBYTEWIDTH,STATUS_SCREENHEIGHT,status_screen0_bmp);
+	else u8g.drawBitmapP(0,1,STATUS_SCREENBYTEWIDTH,STATUS_SCREENHEIGHT,status_screen1_bmp);
+ 
+ #ifdef SDSUPPORT
+ //SD Card Symbol
+ u8g.drawBox(42,42,8,7);
+ u8g.drawBox(50,44,2,5);
+ u8g.drawFrame(42,49,10,4);
+ u8g.drawPixel(50,43);
+ // Progress bar
+ u8g.drawFrame(54,49,73,4);
+ 
+ // SD Card Progress bar and clock
+ u8g.setFont(FONT_STATUSMENU);
+ 
+ if (IS_SD_PRINTING)
+   {
+	// Progress bar
+	u8g.drawBox(55,50, (unsigned int)( (71 * card.percentDone())/100) ,2);
+   }
+    else {
+			// do nothing
+		 }
+ 
+ u8g.setPrintPos(80,47);
+ if(starttime != 0)
+    {
+        uint16_t time = millis()/60000 - starttime/60000;
+
+		u8g.print(itostr2(time/60));
+		u8g.print(':');
+		u8g.print(itostr2(time%60));
+    }else{
+			lcd_printPGM(PSTR("--:--"));
+		 }
+ #endif
+ 
+ // Extruder 1
+ u8g.setFont(FONT_STATUSMENU);
+ u8g.setPrintPos(39,6);
+ u8g.print(itostr3(int(degTargetHotend(0) + 0.5)));
+ lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
+ u8g.setPrintPos(38,27);
+ u8g.print(itostr3(int(degHotend(0) + 0.5)));
+ lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
+ if (!isHeatingHotend(0)) u8g.drawBox(13+33,16,2,2);
+	else
+		{
+		 u8g.setColorIndex(0);	// white on black
+		 u8g.drawBox(13+33,16,2,2);
+		 u8g.setColorIndex(1);	// black on white
+		}
+ 
+ // Extruder 2
+ /*u8g.setFont(FONT_STATUSMENU);
+ #if EXTRUDERS > 1
+ u8g.setPrintPos(31,6);
+ u8g.print(itostr3(int(degTargetHotend(1) + 0.5)));
+ lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
+ u8g.setPrintPos(31,27);
+ u8g.print(itostr3(int(degHotend(1) + 0.5)));
+ lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
+ if (!isHeatingHotend(1)) u8g.drawBox(38,17,2,2);
+	else
+		{
+		 u8g.setColorIndex(0);	// white on black
+		 u8g.drawBox(38,17,2,2);
+		 u8g.setColorIndex(1);	// black on white
+		}
+ #else
+ u8g.setPrintPos(31,27);
+ u8g.print("---");
+ #endif
+ 
+ // Extruder 3
+ u8g.setFont(FONT_STATUSMENU);
+ # if EXTRUDERS > 2
+ u8g.setPrintPos(55,6);
+ u8g.print(itostr3(int(degTargetHotend(2) + 0.5)));
+ lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
+ u8g.setPrintPos(55,27);
+ u8g.print(itostr3(int(degHotend(2) + 0.5)));
+ lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
+ if (!isHeatingHotend(2)) u8g.drawBox(62,17,2,2);
+	else
+		{
+		 u8g.setColorIndex(0);	// white on black
+		 u8g.drawBox(62,17,2,2);
+		 u8g.setColorIndex(1);	// black on white
+		}
+ #else
+ u8g.setPrintPos(55,27);
+ u8g.print("---");
+ #endif
+ */
+ // Heatbed
+ u8g.setFont(FONT_STATUSMENU);
+ u8g.setPrintPos(81-9,6);
+ u8g.print(itostr3(int(degTargetBed() + 0.5)));
+ lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
+ u8g.setPrintPos(81-9,27);
+ u8g.print(itostr3(int(degBed() + 0.5)));
+ lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
+ if (!isHeatingBed()) u8g.drawBox(88-9,18,2,2);
+	else
+		{
+		 u8g.setColorIndex(0);	// white on black
+		 u8g.drawBox(88-9,18,2,2);
+		 u8g.setColorIndex(1);	// black on white
+		}
+ 
+ // Fan
+ u8g.setFont(FONT_STATUSMENU);
+ u8g.setPrintPos(103,27);
+ #if defined(FAN_PIN) && FAN_PIN > -1
+ u8g.print(itostr3(int((fanSpeed*100)/256 + 1)));
+ u8g.print("%");
+ #else
+ u8g.print("---");
+ #endif
+ 
+ 
+ // X, Y, Z-Coordinates
+ u8g.setFont(FONT_STATUSMENU);
+ u8g.drawBox(0,29,128,10);
+ u8g.setColorIndex(0);	// white on black
+ u8g.setPrintPos(2,37);
+ u8g.print("X");
+ u8g.drawPixel(8,33);
+ u8g.drawPixel(8,35);
+ u8g.setPrintPos(10,37);
+ u8g.print(ftostr31ns(current_position[X_AXIS]));
+ u8g.setPrintPos(43,37);
+ lcd_printPGM(PSTR("Y"));
+ u8g.drawPixel(49,33);
+ u8g.drawPixel(49,35);
+ u8g.setPrintPos(51,37);
+ u8g.print(ftostr31ns(current_position[Y_AXIS]));
+ u8g.setPrintPos(83,37);
+ u8g.print("Z");
+ u8g.drawPixel(89,33);
+ u8g.drawPixel(89,35);
+ u8g.setPrintPos(91,37);
+ u8g.print(ftostr31(current_position[Z_AXIS]));
+ u8g.setColorIndex(1);	// black on white
+ 
+ // Feedrate
+ u8g.setFont(u8g_font_6x10_marlin);
+ u8g.setPrintPos(3,49);
+ u8g.print(LCD_STR_FEEDRATE[0]);
+ u8g.setFont(FONT_STATUSMENU);
+ u8g.setPrintPos(12,48);
+ u8g.print(itostr3(feedmultiply));
+ u8g.print('%');
+
+ // Status line
+#if LANGUAGE_CHOICE == 10
+ u8g.setFont(chinese);
+ u8g.setPrintPos(0,63);
+#else
+ u8g.setFont(FONT_STATUSMENU);
+ u8g.setPrintPos(0,61);
+#endif
+ u8g.print(lcd_status_message);
+
+}
+
+static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, char pre_char, char post_char)
+{
+    char c;
+    
+    uint8_t n = LCD_WIDTH - 1 - 2;
+		
+		if ((pre_char == '>') || (pre_char == LCD_STR_UPLEVEL[0] ))
+		   {
+			u8g.setColorIndex(1);		// black on white
+#if LANGUAGE_CHOICE == 10
+			u8g.drawBox (0, row*DOG_CHAR_HEIGHT + 2, 128, DOG_CHAR_HEIGHT);
+#else
+			u8g.drawBox (0, row*DOG_CHAR_HEIGHT + 3, 128, DOG_CHAR_HEIGHT);
+#endif
+			u8g.setColorIndex(0);		// following text must be white on black
+		   } else u8g.setColorIndex(1); // unmarked text is black on white
+		
+		u8g.setPrintPos(0 * DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT);
+		if (pre_char != '>') u8g.print(pre_char); else u8g.print(' ');	// Row selector is obsolete
+
+
+    while( (c = pgm_read_byte(pstr)) != '\0' )
+    {
+		u8g.print(c);
+        pstr++;
+        n--;
+    }
+    while(n--){
+					u8g.print(' ');
+		}
+	   
+		u8g.print(post_char);
+		u8g.print(' ');
+		u8g.setColorIndex(1);		// restore settings to black on white
+}
+
+static void lcd_implementation_drawmenu_setting_edit_generic(uint8_t row, const char* pstr, char pre_char, char* data)
+{
+    static unsigned int fkt_cnt = 0;
+	char c;
+    uint8_t n = LCD_WIDTH - 1 - 2 - strlen(data);
+		
+		u8g.setPrintPos(0 * DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT);
+		u8g.print(pre_char);
+	
+    while( (c = pgm_read_byte(pstr)) != '\0' )
+    {
+			u8g.print(c);
+		
+        pstr++;
+        n--;
+    }
+		u8g.print(':');
+
+    while(n--){
+					u8g.print(' ');
+			  }
+
+		u8g.print(data);
+}
+
+static void lcd_implementation_drawmenu_setting_edit_generic_P(uint8_t row, const char* pstr, char pre_char, const char* data)
+{
+    char c;
+    uint8_t n= LCD_WIDTH - 1 - 2 - strlen_P(data);
+
+		u8g.setPrintPos(0 * DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT);
+		u8g.print(pre_char);
+	
+    while( (c = pgm_read_byte(pstr)) != '\0' )
+    {
+			u8g.print(c);
+		
+        pstr++;
+        n--;
+    }
+		u8g.print(':');
+	
+    while(n--){
+					u8g.print(' ');
+			  }
+
+		lcd_printPGM(data);
+}
+
+#define lcd_implementation_drawmenu_setting_edit_int3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_int3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float32_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float32(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float52_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float52(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float51_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float51(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_long5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_long5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_bool_selected(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
+#define lcd_implementation_drawmenu_setting_edit_bool(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
+
+//Add version for callback functions
+#define lcd_implementation_drawmenu_setting_edit_callback_int3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_int3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float32_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float32(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float52_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float52(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float51_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float51(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_long5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_long5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_bool_selected(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
+#define lcd_implementation_drawmenu_setting_edit_callback_bool(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
+
+void lcd_implementation_drawedit(const char* pstr, char* value)
+{
+		u8g.setPrintPos(0 * DOG_CHAR_WIDTH_LARGE, (u8g.getHeight() - 1 - DOG_CHAR_HEIGHT_LARGE) - (1 * DOG_CHAR_HEIGHT_LARGE) - START_ROW );
+  #if LANGUAGE_CHOICE == 10 
+    u8g.setFont(chinese);
+  #else
+    u8g.setFont(u8g_font_9x18);
+  #endif
+		lcd_printPGM(pstr);
+		u8g.print(':');
+  #if LANGUAGE_CHOICE == 10 
+		u8g.setPrintPos((12 - strlen(value)) * DOG_CHAR_WIDTH_LARGE, (u8g.getHeight() - 1 - DOG_CHAR_HEIGHT_LARGE) - (1 * DOG_CHAR_HEIGHT_LARGE) - START_ROW );
+  #else
+		u8g.setPrintPos((14 - strlen(value)) * DOG_CHAR_WIDTH_LARGE, (u8g.getHeight() - 1 - DOG_CHAR_HEIGHT_LARGE) - (1 * DOG_CHAR_HEIGHT_LARGE) - START_ROW );
+  #endif
+		u8g.print(value);
+}
+
+static void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename)
+{
+    char c;
+    uint8_t n = LCD_WIDTH - 1;
+
+    if (longFilename[0] != '\0')
+    {
+        filename = longFilename;
+        longFilename[LCD_WIDTH-1] = '\0';
+    }
+
+		u8g.setColorIndex(1);		// black on white
+		u8g.drawBox (0, row*DOG_CHAR_HEIGHT + 3, 128, DOG_CHAR_HEIGHT);
+		u8g.setColorIndex(0);		// following text must be white on black
+		u8g.setPrintPos(0 * DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT);
+		u8g.print(' ');	// Indent by 1 char
+	   
+    while((c = *filename) != '\0')
+    {
+		u8g.print(c);
+        filename++;
+        n--;
+    }
+    while(n--){
+					u8g.print(' ');
+			   }
+	u8g.setColorIndex(1);		// black on white
+}
+
+static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* pstr, const char* filename, char* longFilename)
+{
+    char c;
+    uint8_t n = LCD_WIDTH - 1;
+
+    if (longFilename[0] != '\0')
+    {
+        filename = longFilename;
+        longFilename[LCD_WIDTH-1] = '\0';
+    }
+
+		u8g.setPrintPos(0 * DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT);
+		u8g.print(' ');
+		
+while((c = *filename) != '\0')
+    {
+			u8g.print(c);
+		
+        filename++;
+        n--;
+    }
+    while(n--){
+					u8g.print(' ');
+			   }
+
+}
+
+static void lcd_implementation_drawmenu_sddirectory_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename)
+{
+    char c;
+    uint8_t n = LCD_WIDTH - 2;
+		
+    if (longFilename[0] != '\0')
+    {
+        filename = longFilename;
+        longFilename[LCD_WIDTH-2] = '\0';
+    }
+		u8g.setColorIndex(1);		// black on white
+		u8g.drawBox (0, row*DOG_CHAR_HEIGHT + 3, 128, DOG_CHAR_HEIGHT);
+		u8g.setColorIndex(0);		// following text must be white on black
+		u8g.setPrintPos(0 * DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT);
+		u8g.print(' ');	// Indent by 1 char
+		u8g.print(LCD_STR_FOLDER[0]);		
+	   
+    while((c = *filename) != '\0')
+    {
+			u8g.print(c);
+		
+        filename++;
+        n--;
+    }
+    while(n--){
+					u8g.print(' ');
+			   }
+	u8g.setColorIndex(1);		// black on white
+}
+
+static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* pstr, const char* filename, char* longFilename)
+{
+    char c;
+    uint8_t n = LCD_WIDTH - 2;
+
+    if (longFilename[0] != '\0')
+    {
+        filename = longFilename;
+        longFilename[LCD_WIDTH-2] = '\0';
+    }
+
+		u8g.setPrintPos(0 * DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT);
+		u8g.print(' ');
+		u8g.print(LCD_STR_FOLDER[0]);
+
+    while((c = *filename) != '\0')
+    {
+			u8g.print(c);
+		
+        filename++;
+        n--;
+    }
+    while(n--){
+					u8g.print(' ');
+			   }
+}
+
+#define lcd_implementation_drawmenu_back_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
+#define lcd_implementation_drawmenu_back(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_UPLEVEL[0])
+#define lcd_implementation_drawmenu_submenu_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
+#define lcd_implementation_drawmenu_submenu(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_ARROW_RIGHT[0])
+#define lcd_implementation_drawmenu_gcode_selected(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
+#define lcd_implementation_drawmenu_gcode(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
+#define lcd_implementation_drawmenu_function_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
+#define lcd_implementation_drawmenu_function(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
+
+static void lcd_implementation_quick_feedback()
+{
+
+#if BEEPER > -1
+    SET_OUTPUT(BEEPER);
+    for(int8_t i=0;i<10;i++)
+    {
+		WRITE(BEEPER,HIGH);
+		delay(3);
+		WRITE(BEEPER,LOW);
+		delay(3);
+    }
+#endif
+}
+#endif//ULTRA_LCD_IMPLEMENTATION_DOGM_H
+
+

+ 697 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/example_configurations/delta/Configuration.h

@@ -0,0 +1,697 @@
+#ifndef CONFIGURATION_H
+#define CONFIGURATION_H
+
+// This configuration file contains the basic settings.
+// Advanced settings can be found in Configuration_adv.h
+// BASIC SETTINGS: select your board type, temperature sensor type, axis scaling, and endstop configuration
+
+//===========================================================================
+//============================= DELTA Printer ===============================
+//===========================================================================
+// For a Delta printer rplace the configuration files wilth the files in the
+// example_configurations/delta directory.
+//
+
+// User-specified version info of this build to display in [Pronterface, etc] terminal window during
+// startup. Implementation of an idea by Prof Braino to inform user that any changes made to this
+// build by the user have been successfully uploaded into firmware.
+#define STRING_VERSION_CONFIG_H __DATE__ " " __TIME__ // build date and time
+#define STRING_CONFIG_H_AUTHOR "(none, default config)" // Who made the changes.
+
+// SERIAL_PORT selects which serial port should be used for communication with the host.
+// This allows the connection of wireless adapters (for instance) to non-default port pins.
+// Serial port 0 is still used by the Arduino bootloader regardless of this setting.
+#define SERIAL_PORT 0
+
+// This determines the communication speed of the printer
+#define BAUDRATE 250000
+
+// This enables the serial port associated to the Bluetooth interface
+//#define BTENABLED              // Enable BT interface on AT90USB devices
+
+
+//// The following define selects which electronics board you have. Please choose the one that matches your setup
+// 10 = Gen7 custom (Alfons3 Version) "https://github.com/Alfons3/Generation_7_Electronics"
+// 11 = Gen7 v1.1, v1.2 = 11
+// 12 = Gen7 v1.3
+// 13 = Gen7 v1.4
+// 2  = Cheaptronic v1.0
+// 20 = Sethi 3D_1
+// 3  = MEGA/RAMPS up to 1.2 = 3
+// 33 = RAMPS 1.3 / 1.4 (Power outputs: Extruder, Fan, Bed)
+// 34 = RAMPS 1.3 / 1.4 (Power outputs: Extruder0, Extruder1, Bed)
+// 35 = RAMPS 1.3 / 1.4 (Power outputs: Extruder, Fan, Fan)
+// 4  = Duemilanove w/ ATMega328P pin assignment
+// 5  = Gen6
+// 51 = Gen6 deluxe
+// 6  = Sanguinololu < 1.2
+// 62 = Sanguinololu 1.2 and above
+// 63 = Melzi
+// 64 = STB V1.1
+// 65 = Azteeg X1
+// 66 = Melzi with ATmega1284 (MaKr3d version)
+// 67 = Azteeg X3
+// 7  = Ultimaker
+// 71 = Ultimaker (Older electronics. Pre 1.5.4. This is rare)
+// 77 = 3Drag Controller
+// 8  = Teensylu
+// 80 = Rumba
+// 81 = Printrboard (AT90USB1286)
+// 82 = Brainwave (AT90USB646)
+// 83 = SAV Mk-I (AT90USB1286)
+// 9  = Gen3+
+// 70 = Megatronics
+// 701= Megatronics v2.0
+// 702= Minitronics v1.0
+// 90 = Alpha OMCA board
+// 91 = Final OMCA board
+// 301 = Rambo
+// 21 = Elefu Ra Board (v3)
+// 310 = Mega Controller
+
+#ifndef MOTHERBOARD
+#define MOTHERBOARD 33
+#endif
+
+// Define this to set a custom name for your generic Mendel,
+// #define CUSTOM_MENDEL_NAME "This Mendel"
+
+// Define this to set a unique identifier for this printer, (Used by some programs to differentiate between machines)
+// You can use an online service to generate a random UUID. (eg http://www.uuidgenerator.net/version4)
+// #define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
+
+// This defines the number of extruders
+#define EXTRUDERS 1
+
+//// The following define selects which power supply you have. Please choose the one that matches your setup
+// 1 = ATX
+// 2 = X-Box 360 203Watts (the blue wire connected to PS_ON and the red wire to VCC)
+
+#define POWER_SUPPLY 1
+
+// Define this to have the electronics keep the powersupply off on startup. If you don't know what this is leave it.
+// #define PS_DEFAULT_OFF
+
+//===========================================================================
+//============================== Delta Settings =============================
+//===========================================================================
+// Enable DELTA kinematics and most of the default configuration for Deltas
+#define DELTA
+
+// Make delta curves from many straight lines (linear interpolation).
+// This is a trade-off between visible corners (not enough segments)
+// and processor overload (too many expensive sqrt calls).
+#define DELTA_SEGMENTS_PER_SECOND 200
+
+// NOTE NB all values for DELTA_* values MOUST be floating point, so always have a decimal point in them
+
+// Center-to-center distance of the holes in the diagonal push rods.
+#define DELTA_DIAGONAL_ROD 250.0 // mm
+
+// Horizontal offset from middle of printer to smooth rod center.
+#define DELTA_SMOOTH_ROD_OFFSET 175.0 // mm
+
+// Horizontal offset of the universal joints on the end effector.
+#define DELTA_EFFECTOR_OFFSET 33.0 // mm
+
+// Horizontal offset of the universal joints on the carriages.
+#define DELTA_CARRIAGE_OFFSET 18.0 // mm
+
+// Effective horizontal distance bridged by diagonal push rods.
+#define DELTA_RADIUS (DELTA_SMOOTH_ROD_OFFSET-DELTA_EFFECTOR_OFFSET-DELTA_CARRIAGE_OFFSET)
+
+#define DELTA_DIAGONAL_ROD_2 sq(DELTA_DIAGONAL_ROD)
+
+// Effective X/Y positions of the three vertical towers.
+#define SIN_60 0.8660254037844386
+#define COS_60 0.5
+#define DELTA_TOWER1_X -SIN_60*DELTA_RADIUS // front left tower
+#define DELTA_TOWER1_Y -COS_60*DELTA_RADIUS
+#define DELTA_TOWER2_X SIN_60*DELTA_RADIUS // front right tower
+#define DELTA_TOWER2_Y -COS_60*DELTA_RADIUS
+#define DELTA_TOWER3_X 0.0 // back middle tower
+#define DELTA_TOWER3_Y DELTA_RADIUS
+
+//===========================================================================
+//=============================Thermal Settings  ============================
+//===========================================================================
+//
+//--NORMAL IS 4.7kohm PULLUP!-- 1kohm pullup can be used on hotend sensor, using correct resistor and table
+//
+//// Temperature sensor settings:
+// -2 is thermocouple with MAX6675 (only for sensor 0)
+// -1 is thermocouple with AD595
+// 0 is not used
+// 1 is 100k thermistor - best choice for EPCOS 100k (4.7k pullup)
+// 2 is 200k thermistor - ATC Semitec 204GT-2 (4.7k pullup)
+// 3 is mendel-parts thermistor (4.7k pullup)
+// 4 is 10k thermistor !! do not use it for a hotend. It gives bad resolution at high temp. !!
+// 5 is 100K thermistor - ATC Semitec 104GT-2 (Used in ParCan & J-Head) (4.7k pullup)
+// 6 is 100k EPCOS - Not as accurate as table 1 (created using a fluke thermocouple) (4.7k pullup)
+// 7 is 100k Honeywell thermistor 135-104LAG-J01 (4.7k pullup)
+// 71 is 100k Honeywell thermistor 135-104LAF-J01 (4.7k pullup)
+// 8 is 100k 0603 SMD Vishay NTCS0603E3104FXT (4.7k pullup)
+// 9 is 100k GE Sensing AL03006-58.2K-97-G1 (4.7k pullup)
+// 10 is 100k RS thermistor 198-961 (4.7k pullup)
+// 60 is 100k Maker's Tool Works Kapton Bed Thermister
+//
+//    1k ohm pullup tables - This is not normal, you would have to have changed out your 4.7k for 1k
+//                          (but gives greater accuracy and more stable PID)
+// 51 is 100k thermistor - EPCOS (1k pullup)
+// 52 is 200k thermistor - ATC Semitec 204GT-2 (1k pullup)
+// 55 is 100k thermistor - ATC Semitec 104GT-2 (Used in ParCan & J-Head) (1k pullup)
+
+#define TEMP_SENSOR_0 -1
+#define TEMP_SENSOR_1 -1
+#define TEMP_SENSOR_2 0
+#define TEMP_SENSOR_BED 0
+
+// This makes temp sensor 1 a redundant sensor for sensor 0. If the temperatures difference between these sensors is to high the print will be aborted.
+//#define TEMP_SENSOR_1_AS_REDUNDANT
+#define MAX_REDUNDANT_TEMP_SENSOR_DIFF 10
+
+// Actual temperature must be close to target for this long before M109 returns success
+#define TEMP_RESIDENCY_TIME 10  // (seconds)
+#define TEMP_HYSTERESIS 3       // (degC) range of +/- temperatures considered "close" to the target one
+#define TEMP_WINDOW     1       // (degC) Window around target to start the residency timer x degC early.
+
+// The minimal temperature defines the temperature below which the heater will not be enabled It is used
+// to check that the wiring to the thermistor is not broken.
+// Otherwise this would lead to the heater being powered on all the time.
+#define HEATER_0_MINTEMP 5
+#define HEATER_1_MINTEMP 5
+#define HEATER_2_MINTEMP 5
+#define BED_MINTEMP 5
+
+// When temperature exceeds max temp, your heater will be switched off.
+// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure!
+// You should use MINTEMP for thermistor short/failure protection.
+#define HEATER_0_MAXTEMP 275
+#define HEATER_1_MAXTEMP 275
+#define HEATER_2_MAXTEMP 275
+#define BED_MAXTEMP 150
+
+// If your bed has low resistance e.g. .6 ohm and throws the fuse you can duty cycle it to reduce the
+// average current. The value should be an integer and the heat bed will be turned on for 1 interval of
+// HEATER_BED_DUTY_CYCLE_DIVIDER intervals.
+//#define HEATER_BED_DUTY_CYCLE_DIVIDER 4
+
+// PID settings:
+// Comment the following line to disable PID and enable bang-bang.
+#define PIDTEMP
+#define BANG_MAX 255 // limits current to nozzle while in bang-bang mode; 255=full current
+#define PID_MAX 255 // limits current to nozzle while PID is active (see PID_FUNCTIONAL_RANGE below); 255=full current
+#ifdef PIDTEMP
+  //#define PID_DEBUG // Sends debug data to the serial port.
+  //#define PID_OPENLOOP 1 // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
+  #define PID_FUNCTIONAL_RANGE 10 // If the temperature difference between the target temperature and the actual temperature
+                                  // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max.
+  #define PID_INTEGRAL_DRIVE_MAX 255  //limit for the integral term
+  #define K1 0.95 //smoothing factor within the PID
+  #define PID_dT ((16.0 * 8.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine
+
+// If you are using a preconfigured hotend then you can use one of the value sets by uncommenting it
+// Ultimaker
+    #define  DEFAULT_Kp 22.2
+    #define  DEFAULT_Ki 1.08
+    #define  DEFAULT_Kd 114
+
+// Makergear
+//    #define  DEFAULT_Kp 7.0
+//    #define  DEFAULT_Ki 0.1
+//    #define  DEFAULT_Kd 12
+
+// Mendel Parts V9 on 12V
+//    #define  DEFAULT_Kp 63.0
+//    #define  DEFAULT_Ki 2.25
+//    #define  DEFAULT_Kd 440
+#endif // PIDTEMP
+
+// Bed Temperature Control
+// Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis
+//
+// Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder.
+// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz,
+// which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating.
+// This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater.
+// If your configuration is significantly different than this and you don't understand the issues involved, you probably
+// shouldn't use bed PID until someone else verifies your hardware works.
+// If this is enabled, find your own PID constants below.
+//#define PIDTEMPBED
+//
+//#define BED_LIMIT_SWITCHING
+
+// This sets the max power delivered to the bed, and replaces the HEATER_BED_DUTY_CYCLE_DIVIDER option.
+// all forms of bed control obey this (PID, bang-bang, bang-bang with hysteresis)
+// setting this to anything other than 255 enables a form of PWM to the bed just like HEATER_BED_DUTY_CYCLE_DIVIDER did,
+// so you shouldn'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
+
+#ifdef PIDTEMPBED
+//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
+//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
+    #define  DEFAULT_bedKp 10.00
+    #define  DEFAULT_bedKi .023
+    #define  DEFAULT_bedKd 305.4
+
+//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
+//from pidautotune
+//    #define  DEFAULT_bedKp 97.1
+//    #define  DEFAULT_bedKi 1.41
+//    #define  DEFAULT_bedKd 1675.16
+
+// FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles.
+#endif // PIDTEMPBED
+
+
+
+//this prevents dangerous Extruder moves, i.e. if the temperature is under the limit
+//can be software-disabled for whatever purposes by
+#define PREVENT_DANGEROUS_EXTRUDE
+//if PREVENT_DANGEROUS_EXTRUDE is on, you can still disable (uncomment) very long bits of extrusion separately.
+#define PREVENT_LENGTHY_EXTRUDE
+
+#define EXTRUDE_MINTEMP 170
+#define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH) //prevent extrusion of very large distances.
+
+//===========================================================================
+//=============================Mechanical Settings===========================
+//===========================================================================
+
+// Uncomment the following line to enable CoreXY kinematics
+// #define COREXY
+
+// coarse Endstop Settings
+#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
+
+#ifndef ENDSTOPPULLUPS
+  // fine Enstop settings: Individual Pullups. will be ignored if ENDSTOPPULLUPS is defined
+  // #define ENDSTOPPULLUP_XMAX
+  // #define ENDSTOPPULLUP_YMAX
+  // #define ENDSTOPPULLUP_ZMAX
+  // #define ENDSTOPPULLUP_XMIN
+  // #define ENDSTOPPULLUP_YMIN
+  // #define ENDSTOPPULLUP_ZMIN
+#endif
+
+#ifdef ENDSTOPPULLUPS
+  #define ENDSTOPPULLUP_XMAX
+  #define ENDSTOPPULLUP_YMAX
+  #define ENDSTOPPULLUP_ZMAX
+  #define ENDSTOPPULLUP_XMIN
+  #define ENDSTOPPULLUP_YMIN
+  #define ENDSTOPPULLUP_ZMIN
+#endif
+
+// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins.
+const bool X_MIN_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
+const bool Y_MIN_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
+const bool Z_MIN_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
+const bool X_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
+const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
+const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
+//#define DISABLE_MAX_ENDSTOPS
+// Deltas never have min endstops
+#define DISABLE_MIN_ENDSTOPS
+// Disable max endstops for compatibility with endstop checking routine
+#if defined(COREXY) && !defined(DISABLE_MAX_ENDSTOPS)
+  #define DISABLE_MAX_ENDSTOPS
+#endif
+
+// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1
+#define X_ENABLE_ON 0
+#define Y_ENABLE_ON 0
+#define Z_ENABLE_ON 0
+#define E_ENABLE_ON 0 // For all extruders
+
+// Disables axis when it's not being used.
+#define DISABLE_X false
+#define DISABLE_Y false
+#define DISABLE_Z false
+#define DISABLE_E false // For all extruders
+
+#define INVERT_X_DIR false // DELTA does not invert
+#define INVERT_Y_DIR false
+#define INVERT_Z_DIR false
+
+#define INVERT_E0_DIR false   // for direct drive extruder v9 set to true, for geared extruder set to false
+#define INVERT_E1_DIR false    // for direct drive extruder v9 set to true, for geared extruder set to false
+#define INVERT_E2_DIR false   // for direct drive extruder v9 set to true, for geared extruder set to false
+
+// ENDSTOP SETTINGS:
+// Sets direction of endstops when homing; 1=MAX, -1=MIN
+// deltas always home to max
+#define X_HOME_DIR 1
+#define Y_HOME_DIR 1
+#define Z_HOME_DIR 1
+
+#define min_software_endstops true // If true, axis won't move to coordinates less than HOME_POS.
+#define max_software_endstops true  // If true, axis won't move to coordinates greater than the defined lengths below.
+
+// Travel limits after homing
+#define X_MAX_POS 90
+#define X_MIN_POS -90
+#define Y_MAX_POS 90
+#define Y_MIN_POS -90
+#define Z_MAX_POS MANUAL_Z_HOME_POS
+#define Z_MIN_POS 0
+
+#define X_MAX_LENGTH (X_MAX_POS - X_MIN_POS)
+#define Y_MAX_LENGTH (Y_MAX_POS - Y_MIN_POS)
+#define Z_MAX_LENGTH (Z_MAX_POS - Z_MIN_POS)
+//============================= Bed Auto Leveling ===========================
+
+//#define ENABLE_AUTO_BED_LEVELING // Delete the comment to enable (remove // at the start of the line)
+
+#ifdef ENABLE_AUTO_BED_LEVELING
+
+  // these are the positions on the bed to do the probing
+  #define LEFT_PROBE_BED_POSITION 15
+  #define RIGHT_PROBE_BED_POSITION 170
+  #define BACK_PROBE_BED_POSITION 180
+  #define FRONT_PROBE_BED_POSITION 20
+
+  // these are the offsets to the prob relative to the extruder tip (Hotend - Probe)
+  #define X_PROBE_OFFSET_FROM_EXTRUDER -25
+  #define Y_PROBE_OFFSET_FROM_EXTRUDER -29
+  #define Z_PROBE_OFFSET_FROM_EXTRUDER -12.35
+
+  #define Z_RAISE_BEFORE_HOMING 4       // (in mm) Raise Z before homing (G28) for Probe Clearance.
+                                        // Be sure you have this distance over your Z_MAX_POS in case
+
+  #define XY_TRAVEL_SPEED 8000         // X and Y axis travel speed between probes, in mm/min
+
+  #define Z_RAISE_BEFORE_PROBING 15    //How much the extruder will be raised before traveling to the first probing point.
+  #define Z_RAISE_BETWEEN_PROBINGS 5  //How much the extruder will be raised when traveling from between next probing points
+
+
+  //If defined, the Probe servo will be turned on only during movement and then turned off to avoid jerk
+  //The value is the delay to turn the servo off after powered on - depends on the servo speed; 300ms is good value, but you can try lower it.
+  // You MUST HAVE the SERVO_ENDSTOPS defined to use here a value higher than zero otherwise your code will not compile.
+
+//  #define PROBE_SERVO_DEACTIVATION_DELAY 300
+
+
+//If you have enabled the Bed Auto Levelling and are using the same Z Probe for Z Homing,
+//it is highly recommended you let this Z_SAFE_HOMING enabled!!!
+
+  #define Z_SAFE_HOMING   // This feature is meant to avoid Z homing with probe outside the bed area.
+                          // When defined, it will:
+                          // - Allow Z homing only after X and Y homing AND stepper drivers still enabled
+                          // - If stepper drivers timeout, it will need X and Y homing again before Z homing
+                          // - Position the probe in a defined XY point before Z Homing when homing all axis (G28)
+                          // - Block Z homing only when the probe is outside bed area.
+
+  #ifdef Z_SAFE_HOMING
+
+    #define Z_SAFE_HOMING_X_POINT (X_MAX_LENGTH/2)    // X point for Z homing when homing all axis (G28)
+    #define Z_SAFE_HOMING_Y_POINT (Y_MAX_LENGTH/2)    // Y point for Z homing when homing all axis (G28)
+
+  #endif
+
+#endif
+
+
+// The position of the homing switches
+//#define MANUAL_HOME_POSITIONS  // If defined, MANUAL_*_HOME_POS below will be used
+//#define BED_CENTER_AT_0_0  // If defined, the center of the bed is at (X=0, Y=0)
+
+//Manual homing switch locations:
+
+#define MANUAL_HOME_POSITIONS  // MANUAL_*_HOME_POS below will be used
+// For deltabots this means top and center of the cartesian print volume.
+#define MANUAL_X_HOME_POS 0
+#define MANUAL_Y_HOME_POS 0
+#define MANUAL_Z_HOME_POS 250 // For delta: Distance between nozzle and print surface after homing.
+
+//// MOVEMENT SETTINGS
+#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E
+
+// delta homing speeds must be the same on xyz
+#define HOMING_FEEDRATE {200*60, 200*60, 200*60, 0}  // set the homing speeds (mm/min)
+
+// default settings
+// delta speeds must be the same on xyz
+#define DEFAULT_AXIS_STEPS_PER_UNIT   {80, 80, 80, 760*1.1}  // default steps per unit for Kossel (GT2, 20 tooth)
+#define DEFAULT_MAX_FEEDRATE          {500, 500, 500, 25}    // (mm/sec)
+#define DEFAULT_MAX_ACCELERATION      {9000,9000,9000,10000}    // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot.
+
+#define DEFAULT_ACCELERATION          3000    // X, Y, Z and E max acceleration in mm/s^2 for printing moves
+#define DEFAULT_RETRACT_ACCELERATION  3000   // X, Y, Z and E max acceleration in mm/s^2 for retracts
+
+// Offset of the extruders (uncomment if using more than one and relying on firmware to position when changing).
+// The offset has to be X=0, Y=0 for the extruder 0 hotend (default extruder).
+// For the other hotends it is their distance from the extruder 0 hotend.
+// #define EXTRUDER_OFFSET_X {0.0, 20.00} // (in mm) for each extruder, offset of the hotend on the X axis
+// #define EXTRUDER_OFFSET_Y {0.0, 5.00}  // (in mm) for each extruder, offset of the hotend on the Y axis
+
+// The speed change that does not require acceleration (i.e. the software might assume it can be done instantaneously)
+#define DEFAULT_XYJERK                20.0    // (mm/sec)
+#define DEFAULT_ZJERK                 20.0    // (mm/sec) Must be same as XY for delta
+#define DEFAULT_EJERK                 5.0    // (mm/sec)
+
+//===========================================================================
+//=============================Additional Features===========================
+//===========================================================================
+
+// EEPROM
+// the microcontroller can store settings in the EEPROM, e.g. max velocity...
+// M500 - stores paramters in EEPROM
+// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).
+// M502 - reverts to the default "factory settings".  You still need to store them in EEPROM afterwards if you want to.
+//define this to enable eeprom support
+//#define EEPROM_SETTINGS
+//to disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out:
+// please keep turned on if you can.
+//#define EEPROM_CHITCHAT
+
+// Preheat Constants
+#define PLA_PREHEAT_HOTEND_TEMP 180
+#define PLA_PREHEAT_HPB_TEMP 70
+#define PLA_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
+
+#define ABS_PREHEAT_HOTEND_TEMP 240
+#define ABS_PREHEAT_HPB_TEMP 100
+#define ABS_PREHEAT_FAN_SPEED 255   // Insert Value between 0 and 255
+
+//LCD and SD support
+//#define ULTRA_LCD  //general lcd support, also 16x2
+//#define DOGLCD  // Support for SPI LCD 128x64 (Controller ST7565R graphic Display Family)
+//#define SDSUPPORT // Enable SD Card Support in Hardware Console
+//#define SDSLOW // Use slower SD transfer mode (not normally needed - uncomment if you're getting volume init error)
+//#define ENCODER_PULSES_PER_STEP 1 // Increase if you have a high resolution encoder
+//#define ENCODER_STEPS_PER_MENU_ITEM 5 // Set according to ENCODER_PULSES_PER_STEP or your liking
+//#define ULTIMAKERCONTROLLER //as available from the ultimaker online store.
+//#define ULTIPANEL  //the ultipanel as on thingiverse
+
+// The MakerLab Mini Panel with graphic controller and SD support
+// http://reprap.org/wiki/Mini_panel
+//#define MINIPANEL
+
+// The MaKr3d Makr-Panel with graphic controller and SD support
+// http://reprap.org/wiki/MaKr3d_MaKrPanel
+//#define MAKRPANEL
+
+// The RepRapDiscount Smart Controller (white PCB)
+// http://reprap.org/wiki/RepRapDiscount_Smart_Controller
+//#define REPRAP_DISCOUNT_SMART_CONTROLLER
+
+// The GADGETS3D G3D LCD/SD Controller (blue PCB)
+// http://reprap.org/wiki/RAMPS_1.3/1.4_GADGETS3D_Shield_with_Panel
+//#define G3D_PANEL
+
+// The RepRapDiscount FULL GRAPHIC Smart Controller (quadratic white PCB)
+// http://reprap.org/wiki/RepRapDiscount_Full_Graphic_Smart_Controller
+//
+// ==> REMEMBER TO INSTALL U8glib to your ARDUINO library folder: http://code.google.com/p/u8glib/wiki/u8glib
+//#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
+
+// The RepRapWorld REPRAPWORLD_KEYPAD v1.1
+// http://reprapworld.com/?products_details&products_id=202&cPath=1591_1626
+//#define REPRAPWORLD_KEYPAD
+//#define REPRAPWORLD_KEYPAD_MOVE_STEP 10.0 // how much should be moved when a key is pressed, eg 10.0 means 10mm per click
+
+// The Elefu RA Board Control Panel
+// http://www.elefu.com/index.php?route=product/product&product_id=53
+// REMEMBER TO INSTALL LiquidCrystal_I2C.h in your ARUDINO library folder: https://github.com/kiyoshigawa/LiquidCrystal_I2C
+//#define RA_CONTROL_PANEL
+
+#if defined (MINIPANEL)
+ #define DOGLCD
+ #define SDSUPPORT
+ #define ULTIPANEL
+ #define NEWPANEL
+ #define DEFAULT_LCD_CONTRAST 17
+#endif
+
+//automatic expansion
+#if defined (MAKRPANEL)
+ #define DOGLCD
+ #define SDSUPPORT
+ #define ULTIPANEL
+ #define NEWPANEL
+ #define DEFAULT_LCD_CONTRAST 17
+#endif
+
+#if defined (REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER)
+ #define DOGLCD
+ #define U8GLIB_ST7920
+ #define REPRAP_DISCOUNT_SMART_CONTROLLER
+#endif
+
+#if defined(ULTIMAKERCONTROLLER) || defined(REPRAP_DISCOUNT_SMART_CONTROLLER) || defined(G3D_PANEL)
+ #define ULTIPANEL
+ #define NEWPANEL
+#endif
+
+#if defined(REPRAPWORLD_KEYPAD)
+  #define NEWPANEL
+  #define ULTIPANEL
+#endif
+#if defined(RA_CONTROL_PANEL)
+ #define ULTIPANEL
+ #define NEWPANEL
+ #define LCD_I2C_TYPE_PCA8574
+ #define LCD_I2C_ADDRESS 0x27   // I2C Address of the port expander
+#endif
+
+//I2C PANELS
+
+//#define LCD_I2C_SAINSMART_YWROBOT
+#ifdef LCD_I2C_SAINSMART_YWROBOT
+  // This uses the LiquidCrystal_I2C library ( https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home )
+  // Make sure it is placed in the Arduino libraries directory.
+  #define LCD_I2C_TYPE_PCF8575
+  #define LCD_I2C_ADDRESS 0x27   // I2C Address of the port expander
+  #define NEWPANEL
+  #define ULTIPANEL
+#endif
+
+// PANELOLU2 LCD with status LEDs, separate encoder and click inputs
+//#define LCD_I2C_PANELOLU2
+#ifdef LCD_I2C_PANELOLU2
+  // This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
+  // Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
+  // (v1.2.3 no longer requires you to define PANELOLU in the LiquidTWI2.h library header file)
+  // Note: The PANELOLU2 encoder click input can either be directly connected to a pin
+  //       (if BTN_ENC defined to != -1) or read through I2C (when BTN_ENC == -1).
+  #define LCD_I2C_TYPE_MCP23017
+  #define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
+  #define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD
+  #define NEWPANEL
+  #define ULTIPANEL
+#endif
+
+// Panucatt VIKI LCD with status LEDs, integrated click & L/R/U/P buttons, separate encoder inputs
+//#define LCD_I2C_VIKI
+#ifdef LCD_I2C_VIKI
+  // This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
+  // Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
+  // Note: The pause/stop/resume LCD button pin should be connected to the Arduino
+  //       BTN_ENC pin (or set BTN_ENC to -1 if not used)
+  #define LCD_I2C_TYPE_MCP23017
+  #define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
+  #define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD (requires LiquidTWI2 v1.2.3 or later)
+  #define NEWPANEL
+  #define ULTIPANEL
+#endif
+
+// Shift register panels
+// ---------------------
+// 2 wire Non-latching LCD SR from:
+// https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/schematics#!shiftregister-connection
+//#define SR_LCD
+#ifdef SR_LCD
+   #define SR_LCD_2W_NL    // Non latching 2 wire shiftregister
+   //#define NEWPANEL
+#endif
+
+
+#ifdef ULTIPANEL
+//  #define NEWPANEL  //enable this if you have a click-encoder panel
+  #define SDSUPPORT
+  #define ULTRA_LCD
+  #ifdef DOGLCD // Change number of lines to match the DOG graphic display
+    #define LCD_WIDTH 20
+    #define LCD_HEIGHT 5
+  #else
+    #define LCD_WIDTH 20
+    #define LCD_HEIGHT 4
+  #endif
+#else //no panel but just lcd
+  #ifdef ULTRA_LCD
+  #ifdef DOGLCD // Change number of lines to match the 128x64 graphics display
+    #define LCD_WIDTH 20
+    #define LCD_HEIGHT 5
+  #else
+    #define LCD_WIDTH 16
+    #define LCD_HEIGHT 2
+  #endif
+  #endif
+#endif
+
+// default LCD contrast for dogm-like LCD displays
+#ifdef DOGLCD
+# ifndef DEFAULT_LCD_CONTRAST
+#  define DEFAULT_LCD_CONTRAST 32
+# endif
+#endif
+
+// Increase the FAN pwm frequency. Removes the PWM noise but increases heating in the FET/Arduino
+//#define FAST_PWM_FAN
+
+// Temperature status leds that display the hotend and bet temperature.
+// If alle hotends and bed temperature and temperature setpoint are < 54C then the BLUE led is on.
+// Otherwise the RED led is on. There is 1C hysteresis.
+//#define TEMP_STAT_LEDS
+
+// Use software PWM to drive the fan, as for the heaters. This uses a very low frequency
+// which is not ass annoying as with the hardware PWM. On the other hand, if this frequency
+// is too low, you should also increment SOFT_PWM_SCALE.
+//#define FAN_SOFT_PWM
+
+// Incrementing this by 1 will double the software PWM frequency,
+// affecting heaters, and the fan if FAN_SOFT_PWM is enabled.
+// However, control resolution will be halved for each increment;
+// at zero value, there are 128 effective control positions.
+#define SOFT_PWM_SCALE 0
+
+// M240  Triggers a camera by emulating a Canon RC-1 Remote
+// Data from: http://www.doc-diy.net/photo/rc-1_hacked/
+// #define PHOTOGRAPH_PIN     23
+
+// SF send wrong arc g-codes when using Arc Point as fillet procedure
+//#define SF_ARC_FIX
+
+// Support for the BariCUDA Paste Extruder.
+//#define BARICUDA
+
+//define BlinkM/CyzRgb Support
+//#define BLINKM
+
+/*********************************************************************\
+* R/C SERVO support
+* Sponsored by TrinityLabs, Reworked by codexmas
+**********************************************************************/
+
+// Number of servos
+//
+// If you select a configuration below, this will receive a default value and does not need to be set manually
+// set it manually if you have more servos than extruders and wish to manually control some
+// leaving it undefined or defining as 0 will disable the servo subsystem
+// If unsure, leave commented / disabled
+//
+//#define NUM_SERVOS 3 // Servo index starts with 0 for M280 command
+
+// Servo Endstops
+//
+// This allows for servo actuated endstops, primary usage is for the Z Axis to eliminate calibration or bed height changes.
+// Use M206 command to correct for switch height offset to actual nozzle height. Store that setting with M500.
+//
+//#define SERVO_ENDSTOPS {-1, -1, 0} // Servo index for X, Y, Z. Disable with -1
+//#define SERVO_ENDSTOP_ANGLES {0,0, 0,0, 70,0} // X,Y,Z Axis Extend and Retract angles
+
+#include "Configuration_adv.h"
+#include "thermistortables.h"
+
+#endif //__CONFIGURATION_H

+ 479 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/example_configurations/delta/Configuration_adv.h

@@ -0,0 +1,479 @@
+#ifndef CONFIGURATION_ADV_H
+#define CONFIGURATION_ADV_H
+
+//===========================================================================
+//=============================Thermal Settings  ============================
+//===========================================================================
+
+#ifdef BED_LIMIT_SWITCHING
+  #define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS
+#endif
+#define BED_CHECK_INTERVAL 5000 //ms between checks in bang-bang control
+
+//// Heating sanity check:
+// This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature
+// If the temperature has not increased at the end of that period, the target temperature is set to zero. 
+// It can be reset with another M104/M109. This check is also only triggered if the target temperature and the current temperature
+//  differ by at least 2x WATCH_TEMP_INCREASE
+//#define WATCH_TEMP_PERIOD 40000 //40 seconds
+//#define WATCH_TEMP_INCREASE 10  //Heat up at least 10 degree in 20 seconds
+
+#ifdef PIDTEMP
+  // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed.
+  // if Kc is choosen well, the additional required power due to increased melting should be compensated.
+  #define PID_ADD_EXTRUSION_RATE  
+  #ifdef PID_ADD_EXTRUSION_RATE
+    #define  DEFAULT_Kc (1) //heatingpower=Kc*(e_speed)
+  #endif
+#endif
+
+
+//automatic temperature: The hot end target temperature is calculated by all the buffered lines of gcode.
+//The maximum buffered steps/sec of the extruder motor are called "se".
+//You enter the autotemp mode by a M109 S<mintemp> T<maxtemp> F<factor>
+// the target temperature is set to mintemp+factor*se[steps/sec] and limited by mintemp and maxtemp
+// you exit the value by any M109 without F*
+// Also, if the temperature is set to a value <mintemp, it is not changed by autotemp.
+// on an ultimaker, some initial testing worked with M109 S215 B260 F1 in the start.gcode
+#define AUTOTEMP
+#ifdef AUTOTEMP
+  #define AUTOTEMP_OLDWEIGHT 0.98
+#endif
+
+//Show Temperature ADC value
+//The M105 command return, besides traditional information, the ADC value read from temperature sensors.
+//#define SHOW_TEMP_ADC_VALUES
+
+//  extruder run-out prevention. 
+//if the machine is idle, and the temperature over MINTEMP, every couple of SECONDS some filament is extruded
+//#define EXTRUDER_RUNOUT_PREVENT  
+#define EXTRUDER_RUNOUT_MINTEMP 190  
+#define EXTRUDER_RUNOUT_SECONDS 30.
+#define EXTRUDER_RUNOUT_ESTEPS 14. //mm filament
+#define EXTRUDER_RUNOUT_SPEED 1500.  //extrusion speed
+#define EXTRUDER_RUNOUT_EXTRUDE 100
+
+//These defines help to calibrate the AD595 sensor in case you get wrong temperature measurements.
+//The measured temperature is defined as "actualTemp = (measuredTemp * TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET"
+#define TEMP_SENSOR_AD595_OFFSET 0.0
+#define TEMP_SENSOR_AD595_GAIN   1.0
+
+//This is for controlling a fan to cool down the stepper drivers
+//it will turn on when any driver is enabled
+//and turn off after the set amount of seconds from last driver being disabled again
+#define CONTROLLERFAN_PIN -1 //Pin used for the fan to cool controller (-1 to disable)
+#define CONTROLLERFAN_SECS 60 //How many seconds, after all motors were disabled, the fan should run
+#define CONTROLLERFAN_SPEED 255  // == full speed
+
+// When first starting the main fan, run it at full speed for the
+// given number of milliseconds.  This gets the fan spinning reliably
+// before setting a PWM value. (Does not work with software PWM for fan on Sanguinololu)
+//#define FAN_KICKSTART_TIME 100
+
+// Extruder cooling fans
+// Configure fan pin outputs to automatically turn on/off when the associated
+// extruder temperature is above/below EXTRUDER_AUTO_FAN_TEMPERATURE.
+// Multiple extruders can be assigned to the same pin in which case 
+// the fan will turn on when any selected extruder is above the threshold.
+#define EXTRUDER_0_AUTO_FAN_PIN   -1
+#define EXTRUDER_1_AUTO_FAN_PIN   -1
+#define EXTRUDER_2_AUTO_FAN_PIN   -1
+#define EXTRUDER_AUTO_FAN_TEMPERATURE 50
+#define EXTRUDER_AUTO_FAN_SPEED   255  // == full speed
+
+
+//===========================================================================
+//=============================Mechanical Settings===========================
+//===========================================================================
+
+#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing
+
+
+//// AUTOSET LOCATIONS OF LIMIT SWITCHES
+//// Added by ZetaPhoenix 09-15-2012
+#ifdef MANUAL_HOME_POSITIONS  // Use manual limit switch locations
+  #define X_HOME_POS MANUAL_X_HOME_POS
+  #define Y_HOME_POS MANUAL_Y_HOME_POS
+  #define Z_HOME_POS MANUAL_Z_HOME_POS
+#else //Set min/max homing switch positions based upon homing direction and min/max travel limits
+  //X axis
+  #if X_HOME_DIR == -1
+    #ifdef BED_CENTER_AT_0_0
+      #define X_HOME_POS X_MAX_LENGTH * -0.5
+    #else
+      #define X_HOME_POS X_MIN_POS
+    #endif //BED_CENTER_AT_0_0
+  #else    
+    #ifdef BED_CENTER_AT_0_0
+      #define X_HOME_POS X_MAX_LENGTH * 0.5
+    #else
+      #define X_HOME_POS X_MAX_POS
+    #endif //BED_CENTER_AT_0_0
+  #endif //X_HOME_DIR == -1
+  
+  //Y axis
+  #if Y_HOME_DIR == -1
+    #ifdef BED_CENTER_AT_0_0
+      #define Y_HOME_POS Y_MAX_LENGTH * -0.5
+    #else
+      #define Y_HOME_POS Y_MIN_POS
+    #endif //BED_CENTER_AT_0_0
+  #else    
+    #ifdef BED_CENTER_AT_0_0
+      #define Y_HOME_POS Y_MAX_LENGTH * 0.5
+    #else
+      #define Y_HOME_POS Y_MAX_POS
+    #endif //BED_CENTER_AT_0_0
+  #endif //Y_HOME_DIR == -1
+  
+  // Z axis
+  #if Z_HOME_DIR == -1 //BED_CENTER_AT_0_0 not used
+    #define Z_HOME_POS Z_MIN_POS
+  #else    
+    #define Z_HOME_POS Z_MAX_POS
+  #endif //Z_HOME_DIR == -1
+#endif //End auto min/max positions
+//END AUTOSET LOCATIONS OF LIMIT SWITCHES -ZP
+
+
+//#define Z_LATE_ENABLE // Enable Z the last moment. Needed if your Z driver overheats.
+
+// A single Z stepper driver is usually used to drive 2 stepper motors.
+// Uncomment this define to utilize a separate stepper driver for each Z axis motor.
+// Only a few motherboards support this, like RAMPS, which have dual extruder support (the 2nd, often unused, extruder driver is used
+// to control the 2nd Z axis stepper motor). The pins are currently only defined for a RAMPS motherboards.
+// On a RAMPS (or other 5 driver) motherboard, using this feature will limit you to using 1 extruder.
+//#define Z_DUAL_STEPPER_DRIVERS
+
+#ifdef Z_DUAL_STEPPER_DRIVERS
+  #undef EXTRUDERS
+  #define EXTRUDERS 1
+#endif
+
+// Same again but for Y Axis.
+//#define Y_DUAL_STEPPER_DRIVERS
+
+// Define if the two Y drives need to rotate in opposite directions
+#define INVERT_Y2_VS_Y_DIR true
+
+#ifdef Y_DUAL_STEPPER_DRIVERS
+  #undef EXTRUDERS
+  #define EXTRUDERS 1
+#endif
+
+#if defined (Z_DUAL_STEPPER_DRIVERS) && defined (Y_DUAL_STEPPER_DRIVERS)
+  #error "You cannot have dual drivers for both Y and Z"
+#endif
+
+// Enable this for dual x-carriage printers. 
+// A dual x-carriage design has the advantage that the inactive extruder can be parked which
+// prevents hot-end ooze contaminating the print. It also reduces the weight of each x-carriage
+// allowing faster printing speeds.
+//#define DUAL_X_CARRIAGE
+#ifdef DUAL_X_CARRIAGE
+// Configuration for second X-carriage
+// Note: the first x-carriage is defined as the x-carriage which homes to the minimum endstop;
+// the second x-carriage always homes to the maximum endstop.
+#define X2_MIN_POS 80     // set minimum to ensure second x-carriage doesn't hit the parked first X-carriage
+#define X2_MAX_POS 353    // set maximum to the distance between toolheads when both heads are homed 
+#define X2_HOME_DIR 1     // the second X-carriage always homes to the maximum endstop position
+#define X2_HOME_POS X2_MAX_POS // default home position is the maximum carriage position 
+    // However: In this mode the EXTRUDER_OFFSET_X value for the second extruder provides a software 
+    // override for X2_HOME_POS. This also allow recalibration of the distance between the two endstops
+    // without modifying the firmware (through the "M218 T1 X???" command).
+    // Remember: you should set the second extruder x-offset to 0 in your slicer.
+
+// Pins for second x-carriage stepper driver (defined here to avoid further complicating pins.h)
+#define X2_ENABLE_PIN 29
+#define X2_STEP_PIN 25
+#define X2_DIR_PIN 23
+
+// There are a few selectable movement modes for dual x-carriages using M605 S<mode>
+//    Mode 0: Full control. The slicer has full control over both x-carriages and can achieve optimal travel results
+//                           as long as it supports dual x-carriages. (M605 S0)
+//    Mode 1: Auto-park mode. The firmware will automatically park and unpark the x-carriages on tool changes so
+//                           that additional slicer support is not required. (M605 S1)
+//    Mode 2: Duplication mode. The firmware will transparently make the second x-carriage and extruder copy all  
+//                           actions of the first x-carriage. This allows the printer to print 2 arbitrary items at
+//                           once. (2nd extruder x offset and temp offset are set using: M605 S2 [Xnnn] [Rmmm])
+
+// This is the default power-up mode which can be later using M605. 
+#define DEFAULT_DUAL_X_CARRIAGE_MODE 0 
+
+// As the x-carriages are independent we can now account for any relative Z offset
+#define EXTRUDER1_Z_OFFSET 0.0           // z offset relative to extruder 0
+
+// Default settings in "Auto-park Mode" 
+#define TOOLCHANGE_PARK_ZLIFT   0.2      // the distance to raise Z axis when parking an extruder
+#define TOOLCHANGE_UNPARK_ZLIFT 1        // the distance to raise Z axis when unparking an extruder
+
+// Default x offset in duplication mode (typically set to half print bed width)
+#define DEFAULT_DUPLICATION_X_OFFSET 100
+
+#endif //DUAL_X_CARRIAGE
+    
+//homing hits the endstop, then retracts by this distance, before it tries to slowly bump again:
+#define X_HOME_RETRACT_MM 5 
+#define Y_HOME_RETRACT_MM 5 
+#define Z_HOME_RETRACT_MM 5 // deltas need the same for all three axis
+
+//#define QUICK_HOME  //if this is defined, if both x and y are to be homed, a diagonal move will be performed initially.
+
+#define AXIS_RELATIVE_MODES {false, false, false, false}
+
+#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step)
+
+//By default pololu step drivers require an active high signal. However, some high power drivers require an active low signal as step.
+#define INVERT_X_STEP_PIN false
+#define INVERT_Y_STEP_PIN false
+#define INVERT_Z_STEP_PIN false
+#define INVERT_E_STEP_PIN false
+
+//default stepper release if idle
+#define DEFAULT_STEPPER_DEACTIVE_TIME 60
+
+#define DEFAULT_MINIMUMFEEDRATE       0.0     // minimum feedrate
+#define DEFAULT_MINTRAVELFEEDRATE     0.0
+
+// Feedrates for manual moves along X, Y, Z, E from panel
+#ifdef ULTIPANEL
+#define MANUAL_FEEDRATE {50*60, 50*60, 4*60, 60}  // set the speeds for manual moves (mm/min)
+#endif
+
+// minimum time in microseconds that a movement needs to take if the buffer is emptied.
+#define DEFAULT_MINSEGMENTTIME        20000
+
+// If defined the movements slow down when the look ahead buffer is only half full
+// (don't use SLOWDOWN with DELTA because DELTA generates hundreds of segments per second)
+//#define SLOWDOWN
+
+// Frequency limit
+// See nophead's blog for more info
+// Not working O
+//#define XY_FREQUENCY_LIMIT  15
+
+// Minimum planner junction speed. Sets the default minimum speed the planner plans for at the end
+// of the buffer and all stops. This should not be much greater than zero and should only be changed
+// if unwanted behavior is observed on a user's machine when running at very slow speeds.
+#define MINIMUM_PLANNER_SPEED 0.05// (mm/sec)
+
+// MS1 MS2 Stepper Driver Microstepping mode table
+#define MICROSTEP1 LOW,LOW
+#define MICROSTEP2 HIGH,LOW
+#define MICROSTEP4 LOW,HIGH
+#define MICROSTEP8 HIGH,HIGH
+#define MICROSTEP16 HIGH,HIGH
+
+// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
+#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]
+
+// Motor Current setting (Only functional when motor driver current ref pins are connected to a digital trimpot on supported boards)
+#define DIGIPOT_MOTOR_CURRENT {135,135,135,135,135} // Values 0-255 (RAMBO 135 = ~0.75A, 185 = ~1A)
+
+
+//===========================================================================
+//=============================Additional Features===========================
+//===========================================================================
+
+#define SD_FINISHED_STEPPERRELEASE true  //if sd support and the file is finished: disable steppers?
+#define SD_FINISHED_RELEASECOMMAND "M84 X Y Z E" // You might want to keep the z enabled so your bed stays in place.
+
+#define SDCARD_RATHERRECENTFIRST  //reverse file order of sd card menu display. Its sorted practically after the filesystem block order. 
+// if a file is deleted, it frees a block. hence, the order is not purely cronological. To still have auto0.g accessible, there is again the option to do that.
+// using:
+//#define MENU_ADDAUTOSTART
+
+// The hardware watchdog should reset the Microcontroller disabling all outputs, in case the firmware gets stuck and doesn't do temperature regulation.
+//#define USE_WATCHDOG
+
+#ifdef USE_WATCHDOG
+// If you have a watchdog reboot in an ArduinoMega2560 then the device will hang forever, as a watchdog reset will leave the watchdog on.
+// The "WATCHDOG_RESET_MANUAL" goes around this by not using the hardware reset.
+//  However, THIS FEATURE IS UNSAFE!, as it will only work if interrupts are disabled. And the code could hang in an interrupt routine with interrupts disabled.
+//#define WATCHDOG_RESET_MANUAL
+#endif
+
+// Enable the option to stop SD printing when hitting and endstops, needs to be enabled from the LCD menu when this option is enabled.
+//#define ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
+
+// Babystepping enables the user to control the axis in tiny amounts, independently from the normal printing process
+// it can e.g. be used to change z-positions in the print startup phase in realtime
+// does not respect endstops!
+//#define BABYSTEPPING
+#ifdef BABYSTEPPING
+  #define BABYSTEP_XY  //not only z, but also XY in the menu. more clutter, more functions
+  #define BABYSTEP_INVERT_Z false  //true for inverse movements in Z
+  #define BABYSTEP_Z_MULTIPLICATOR 2 //faster z movements
+  
+  #ifdef COREXY
+    #error BABYSTEPPING not implemented for COREXY yet.
+  #endif
+
+  #ifdef DELTA
+    #ifdef BABYSTEP_XY
+      #error BABYSTEPPING only implemented for Z axis on deltabots.
+    #endif
+  #endif
+#endif
+
+// extruder advance constant (s2/mm3)
+//
+// advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2
+//
+// hooke's law says:		force = k * distance
+// bernoulli's priniciple says:	v ^ 2 / 2 + g . h + pressure / density = constant
+// so: v ^ 2 is proportional to number of steps we advance the extruder
+//#define ADVANCE
+
+#ifdef ADVANCE
+  #define EXTRUDER_ADVANCE_K .0
+
+  #define D_FILAMENT 2.85
+  #define STEPS_MM_E 836
+  #define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159)
+  #define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA)
+
+#endif // ADVANCE
+
+// Arc interpretation settings:
+#define MM_PER_ARC_SEGMENT 1
+#define N_ARC_CORRECTION 25
+
+const unsigned int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement
+
+// If you are using a RAMPS board or cheap E-bay purchased boards that do not detect when an SD card is inserted
+// You can get round this by connecting a push button or single throw switch to the pin defined as SDCARDCARDDETECT 
+// in the pins.h file.  When using a push button pulling the pin to ground this will need inverted.  This setting should
+// be commented out otherwise
+#define SDCARDDETECTINVERTED 
+
+#ifdef ULTIPANEL
+ #undef SDCARDDETECTINVERTED
+#endif
+
+// Power Signal Control Definitions
+// By default use ATX definition
+#ifndef POWER_SUPPLY
+  #define POWER_SUPPLY 1
+#endif
+// 1 = ATX
+#if (POWER_SUPPLY == 1) 
+  #define PS_ON_AWAKE  LOW
+  #define PS_ON_ASLEEP HIGH
+#endif
+// 2 = X-Box 360 203W
+#if (POWER_SUPPLY == 2) 
+  #define PS_ON_AWAKE  HIGH
+  #define PS_ON_ASLEEP LOW
+#endif
+
+// Control heater 0 and heater 1 in parallel.
+//#define HEATERS_PARALLEL
+
+//===========================================================================
+//=============================Buffers           ============================
+//===========================================================================
+
+// The number of linear motions that can be in the plan at any give time.  
+// THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, i.g. 8,16,32 because shifts and ors are used to do the ringbuffering.
+#if defined SDSUPPORT
+  #define BLOCK_BUFFER_SIZE 16   // SD,LCD,Buttons take more memory, block buffer needs to be smaller
+#else
+  #define BLOCK_BUFFER_SIZE 16 // maximize block buffer
+#endif
+
+
+//The ASCII buffer for recieving from the serial:
+#define MAX_CMD_SIZE 96
+#define BUFSIZE 4
+
+
+// Firmware based and LCD controled retract
+// M207 and M208 can be used to define parameters for the retraction. 
+// The retraction can be called by the slicer using G10 and G11
+// until then, intended retractions can be detected by moves that only extrude and the direction. 
+// the moves are than replaced by the firmware controlled ones.
+
+// #define FWRETRACT  //ONLY PARTIALLY TESTED
+#define MIN_RETRACT 0.1 //minimum extruded mm to accept a automatic gcode retraction attempt
+
+
+//adds support for experimental filament exchange support M600; requires display
+#ifdef ULTIPANEL
+  #define FILAMENTCHANGEENABLE
+  #ifdef FILAMENTCHANGEENABLE
+    #define FILAMENTCHANGE_XPOS 3
+    #define FILAMENTCHANGE_YPOS 3
+    #define FILAMENTCHANGE_ZADD 10
+    #define FILAMENTCHANGE_FIRSTRETRACT -2
+    #define FILAMENTCHANGE_FINALRETRACT -100
+  #endif
+#endif
+
+#ifdef FILAMENTCHANGEENABLE
+  #ifdef EXTRUDER_RUNOUT_PREVENT
+    #error EXTRUDER_RUNOUT_PREVENT currently incompatible with FILAMENTCHANGE
+  #endif 
+#endif
+ 
+//===========================================================================
+//=============================  Define Defines  ============================
+//===========================================================================
+#if EXTRUDERS > 1 && defined TEMP_SENSOR_1_AS_REDUNDANT
+  #error "You cannot use TEMP_SENSOR_1_AS_REDUNDANT if EXTRUDERS > 1"
+#endif
+
+#if EXTRUDERS > 1 && defined HEATERS_PARALLEL
+  #error "You cannot use HEATERS_PARALLEL if EXTRUDERS > 1"
+#endif
+
+#if TEMP_SENSOR_0 > 0
+  #define THERMISTORHEATER_0 TEMP_SENSOR_0
+  #define HEATER_0_USES_THERMISTOR
+#endif
+#if TEMP_SENSOR_1 > 0
+  #define THERMISTORHEATER_1 TEMP_SENSOR_1
+  #define HEATER_1_USES_THERMISTOR
+#endif
+#if TEMP_SENSOR_2 > 0
+  #define THERMISTORHEATER_2 TEMP_SENSOR_2
+  #define HEATER_2_USES_THERMISTOR
+#endif
+#if TEMP_SENSOR_BED > 0
+  #define THERMISTORBED TEMP_SENSOR_BED
+  #define BED_USES_THERMISTOR
+#endif
+#if TEMP_SENSOR_0 == -1
+  #define HEATER_0_USES_AD595
+#endif
+#if TEMP_SENSOR_1 == -1
+  #define HEATER_1_USES_AD595
+#endif
+#if TEMP_SENSOR_2 == -1
+  #define HEATER_2_USES_AD595
+#endif
+#if TEMP_SENSOR_BED == -1
+  #define BED_USES_AD595
+#endif
+#if TEMP_SENSOR_0 == -2
+  #define HEATER_0_USES_MAX6675
+#endif
+#if TEMP_SENSOR_0 == 0
+  #undef HEATER_0_MINTEMP
+  #undef HEATER_0_MAXTEMP
+#endif
+#if TEMP_SENSOR_1 == 0
+  #undef HEATER_1_MINTEMP
+  #undef HEATER_1_MAXTEMP
+#endif
+#if TEMP_SENSOR_2 == 0
+  #undef HEATER_2_MINTEMP
+  #undef HEATER_2_MAXTEMP
+#endif
+#if TEMP_SENSOR_BED == 0
+  #undef BED_MINTEMP
+  #undef BED_MAXTEMP
+#endif
+
+
+#endif //__CONFIGURATION_ADV_H

File diff suppressed because it is too large
+ 4020 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/fastio.h


File diff suppressed because it is too large
+ 1748 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/language.h


+ 137 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/motion_control.cpp

@@ -0,0 +1,137 @@
+/*
+  motion_control.c - high level interface for issuing motion commands
+  Part of Grbl
+
+  Copyright (c) 2009-2011 Simen Svale Skogsrud
+  Copyright (c) 2011 Sungeun K. Jeon
+  
+  Grbl 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.
+
+  Grbl 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 Grbl.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "Marlin.h"
+#include "stepper.h"
+#include "planner.h"
+
+// The arc is approximated by generating a huge number of tiny, linear segments. The length of each 
+// segment is configured in settings.mm_per_arc_segment.  
+void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1, 
+  uint8_t axis_linear, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder)
+{      
+  //   int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled();
+  //   plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc
+  float center_axis0 = position[axis_0] + offset[axis_0];
+  float center_axis1 = position[axis_1] + offset[axis_1];
+  float linear_travel = target[axis_linear] - position[axis_linear];
+  float extruder_travel = target[E_AXIS] - position[E_AXIS];
+  float r_axis0 = -offset[axis_0];  // Radius vector from center to current location
+  float r_axis1 = -offset[axis_1];
+  float rt_axis0 = target[axis_0] - center_axis0;
+  float rt_axis1 = target[axis_1] - center_axis1;
+  
+  // CCW angle between position and target from circle center. Only one atan2() trig computation required.
+  float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1);
+  if (angular_travel < 0) { angular_travel += 2*M_PI; }
+  if (isclockwise) { angular_travel -= 2*M_PI; }
+  
+  float millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel));
+  if (millimeters_of_travel < 0.001) { return; }
+  uint16_t segments = floor(millimeters_of_travel/MM_PER_ARC_SEGMENT);
+  if(segments == 0) segments = 1;
+  
+  /*  
+    // Multiply inverse feed_rate to compensate for the fact that this movement is approximated
+    // by a number of discrete segments. The inverse feed_rate should be correct for the sum of 
+    // all segments.
+    if (invert_feed_rate) { feed_rate *= segments; }
+  */
+  float theta_per_segment = angular_travel/segments;
+  float linear_per_segment = linear_travel/segments;
+  float extruder_per_segment = extruder_travel/segments;
+  
+  /* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
+     and phi is the angle of rotation. Based on the solution approach by Jens Geisler.
+         r_T = [cos(phi) -sin(phi);
+                sin(phi)  cos(phi] * r ;
+     
+     For arc generation, the center of the circle is the axis of rotation and the radius vector is 
+     defined from the circle center to the initial position. Each line segment is formed by successive
+     vector rotations. This requires only two cos() and sin() computations to form the rotation
+     matrix for the duration of the entire arc. Error may accumulate from numerical round-off, since
+     all double numbers are single precision on the Arduino. (True double precision will not have
+     round off issues for CNC applications.) Single precision error can accumulate to be greater than
+     tool precision in some cases. Therefore, arc path correction is implemented. 
+
+     Small angle approximation may be used to reduce computation overhead further. This approximation
+     holds for everything, but very small circles and large mm_per_arc_segment values. In other words,
+     theta_per_segment would need to be greater than 0.1 rad and N_ARC_CORRECTION would need to be large
+     to cause an appreciable drift error. N_ARC_CORRECTION~=25 is more than small enough to correct for 
+     numerical drift error. N_ARC_CORRECTION may be on the order a hundred(s) before error becomes an
+     issue for CNC machines with the single precision Arduino calculations.
+     
+     This approximation also allows mc_arc to immediately insert a line segment into the planner 
+     without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied
+     a correction, the planner should have caught up to the lag caused by the initial mc_arc overhead. 
+     This is important when there are successive arc motions. 
+  */
+  // Vector rotation matrix values
+  float cos_T = 1-0.5*theta_per_segment*theta_per_segment; // Small angle approximation
+  float sin_T = theta_per_segment;
+  
+  float arc_target[4];
+  float sin_Ti;
+  float cos_Ti;
+  float r_axisi;
+  uint16_t i;
+  int8_t count = 0;
+
+  // Initialize the linear axis
+  arc_target[axis_linear] = position[axis_linear];
+  
+  // Initialize the extruder axis
+  arc_target[E_AXIS] = position[E_AXIS];
+
+  for (i = 1; i<segments; i++) { // Increment (segments-1)
+    
+    if (count < N_ARC_CORRECTION) {
+      // Apply vector rotation matrix 
+      r_axisi = r_axis0*sin_T + r_axis1*cos_T;
+      r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
+      r_axis1 = r_axisi;
+      count++;
+    } else {
+      // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
+      // Compute exact location by applying transformation matrix from initial radius vector(=-offset).
+      cos_Ti = cos(i*theta_per_segment);
+      sin_Ti = sin(i*theta_per_segment);
+      r_axis0 = -offset[axis_0]*cos_Ti + offset[axis_1]*sin_Ti;
+      r_axis1 = -offset[axis_0]*sin_Ti - offset[axis_1]*cos_Ti;
+      count = 0;
+    }
+
+    // Update arc_target location
+    arc_target[axis_0] = center_axis0 + r_axis0;
+    arc_target[axis_1] = center_axis1 + r_axis1;
+    arc_target[axis_linear] += linear_per_segment;
+    arc_target[E_AXIS] += extruder_per_segment;
+
+    clamp_to_software_endstops(arc_target);
+    plan_buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], feed_rate, extruder);
+    
+  }
+  // Ensure last segment arrives at target location.
+  plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], feed_rate, extruder);
+
+  //   plan_set_acceleration_manager_enabled(acceleration_manager_was_enabled);
+}
+

+ 32 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/motion_control.h

@@ -0,0 +1,32 @@
+/*
+  motion_control.h - high level interface for issuing motion commands
+  Part of Grbl
+
+  Copyright (c) 2009-2011 Simen Svale Skogsrud
+  Copyright (c) 2011 Sungeun K. Jeon
+  
+  Grbl 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.
+
+  Grbl 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 Grbl.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef motion_control_h
+#define motion_control_h
+
+// Execute an arc in offset mode format. position == current xyz, target == target xyz, 
+// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is
+// the direction of helical travel, radius == circle radius, isclockwise boolean. Used
+// for vector transformation direction.
+void mc_arc(float *position, float *target, float *offset, unsigned char axis_0, unsigned char axis_1,
+  unsigned char axis_linear, float feed_rate, float radius, unsigned char isclockwise, uint8_t extruder);
+  
+#endif

File diff suppressed because it is too large
+ 2771 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/pins.h


File diff suppressed because it is too large
+ 1001 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/planner.cpp


+ 169 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/planner.h

@@ -0,0 +1,169 @@
+/*
+  planner.h - buffers movement commands and manages the acceleration profile plan
+  Part of Grbl
+
+  Copyright (c) 2009-2011 Simen Svale Skogsrud
+
+  Grbl 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.
+
+  Grbl 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 Grbl.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+// This module is to be considered a sub-module of stepper.c. Please don't include 
+// this file from any other module.
+
+#ifndef planner_h
+#define planner_h
+
+#include "Marlin.h"
+
+#ifdef ENABLE_AUTO_BED_LEVELING
+#include "vector_3.h"
+#endif // ENABLE_AUTO_BED_LEVELING
+
+// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in 
+// the source g-code and may never actually be reached if acceleration management is active.
+typedef struct {
+  // Fields used by the bresenham algorithm for tracing the line
+  long steps_x, steps_y, steps_z, steps_e;  // Step count along each axis
+  unsigned long step_event_count;           // The number of step events required to complete this block
+  long accelerate_until;                    // The index of the step event on which to stop acceleration
+  long decelerate_after;                    // The index of the step event on which to start decelerating
+  long acceleration_rate;                   // The acceleration rate used for acceleration calculation
+  unsigned char direction_bits;             // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
+  unsigned char active_extruder;            // Selects the active extruder
+  #ifdef ADVANCE
+    long advance_rate;
+    volatile long initial_advance;
+    volatile long final_advance;
+    float advance;
+  #endif
+
+  // Fields used by the motion planner to manage acceleration
+//  float speed_x, speed_y, speed_z, speed_e;        // Nominal mm/sec for each axis
+  float nominal_speed;                               // The nominal speed for this block in mm/sec 
+  float entry_speed;                                 // Entry speed at previous-current junction in mm/sec
+  float max_entry_speed;                             // Maximum allowable junction entry speed in mm/sec
+  float millimeters;                                 // The total travel of this block in mm
+  float acceleration;                                // acceleration mm/sec^2
+  unsigned char recalculate_flag;                    // Planner flag to recalculate trapezoids on entry junction
+  unsigned char nominal_length_flag;                 // Planner flag for nominal speed always reached
+
+  // Settings for the trapezoid generator
+  unsigned long nominal_rate;                        // The nominal step rate for this block in step_events/sec 
+  unsigned long initial_rate;                        // The jerk-adjusted step rate at start of block  
+  unsigned long final_rate;                          // The minimal rate at exit
+  unsigned long acceleration_st;                     // acceleration steps/sec^2
+  unsigned long fan_speed;
+  #ifdef BARICUDA
+  unsigned long valve_pressure;
+  unsigned long e_to_p_pressure;
+  #endif
+  volatile char busy;
+} block_t;
+
+#ifdef ENABLE_AUTO_BED_LEVELING
+// this holds the required transform to compensate for bed level
+extern matrix_3x3 plan_bed_level_matrix;
+#endif // #ifdef ENABLE_AUTO_BED_LEVELING
+
+// Initialize the motion plan subsystem      
+void plan_init();
+
+// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in 
+// millimaters. Feed rate specifies the speed of the motion.
+
+#ifdef ENABLE_AUTO_BED_LEVELING
+void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, const uint8_t &extruder);
+
+// Get the position applying the bed level matrix if enabled
+vector_3 plan_get_position();
+#else
+void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder);
+#endif // ENABLE_AUTO_BED_LEVELING
+
+// Set position. Used for G92 instructions.
+#ifdef ENABLE_AUTO_BED_LEVELING
+void plan_set_position(float x, float y, float z, const float &e);
+#else
+void plan_set_position(const float &x, const float &y, const float &z, const float &e);
+#endif // ENABLE_AUTO_BED_LEVELING
+
+void plan_set_e_position(const float &e);
+
+
+
+void check_axes_activity();
+uint8_t movesplanned(); //return the nr of buffered moves
+
+extern unsigned long minsegmenttime;
+extern float max_feedrate[4]; // set the max speeds
+extern float axis_steps_per_unit[4];
+extern unsigned long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software
+extern float minimumfeedrate;
+extern float acceleration;         // Normal acceleration mm/s^2  THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX
+extern float retract_acceleration; //  mm/s^2   filament pull-pack and push-forward  while standing still in the other axis M204 TXXXX
+extern float max_xy_jerk; //speed than can be stopped at once, if i understand correctly.
+extern float max_z_jerk;
+extern float max_e_jerk;
+extern float mintravelfeedrate;
+extern unsigned long axis_steps_per_sqr_second[NUM_AXIS];
+
+#ifdef AUTOTEMP
+    extern bool autotemp_enabled;
+    extern float autotemp_max;
+    extern float autotemp_min;
+    extern float autotemp_factor;
+#endif
+
+    
+
+
+extern block_t block_buffer[BLOCK_BUFFER_SIZE];            // A ring buffer for motion instfructions
+extern volatile unsigned char block_buffer_head;           // Index of the next block to be pushed
+extern volatile unsigned char block_buffer_tail; 
+// Called when the current block is no longer needed. Discards the block and makes the memory
+// availible for new blocks.    
+FORCE_INLINE void plan_discard_current_block()  
+{
+  if (block_buffer_head != block_buffer_tail) {
+    block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1);  
+  }
+}
+
+// Gets the current block. Returns NULL if buffer empty
+FORCE_INLINE block_t *plan_get_current_block() 
+{
+  if (block_buffer_head == block_buffer_tail) { 
+    return(NULL); 
+  }
+  block_t *block = &block_buffer[block_buffer_tail];
+  block->busy = true;
+  return(block);
+}
+
+// Gets the current block. Returns NULL if buffer empty
+FORCE_INLINE bool blocks_queued() 
+{
+  if (block_buffer_head == block_buffer_tail) { 
+    return false; 
+  }
+  else
+    return true;
+}
+
+#ifdef PREVENT_DANGEROUS_EXTRUDE
+void set_extrude_min_temp(float temp);
+#endif
+
+void reset_acceleration_rates();
+#endif

File diff suppressed because it is too large
+ 1932 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/qr_solve.cpp


+ 22 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/qr_solve.h

@@ -0,0 +1,22 @@
+#include "Configuration.h"
+
+#ifdef ACCURATE_BED_LEVELING
+
+void daxpy ( int n, double da, double dx[], int incx, double dy[], int incy );
+double ddot ( int n, double dx[], int incx, double dy[], int incy );
+double dnrm2 ( int n, double x[], int incx );
+void dqrank ( double a[], int lda, int m, int n, double tol, int *kr, 
+  int jpvt[], double qraux[] );
+void dqrdc ( double a[], int lda, int n, int p, double qraux[], int jpvt[], 
+  double work[], int job );
+int dqrls ( double a[], int lda, int m, int n, double tol, int *kr, double b[], 
+  double x[], double rsd[], int jpvt[], double qraux[], int itask );
+void dqrlss ( double a[], int lda, int m, int n, int kr, double b[], double x[], 
+  double rsd[], int jpvt[], double qraux[] );
+int dqrsl ( double a[], int lda, int n, int k, double qraux[], double y[], 
+  double qy[], double qty[], double b[], double rsd[], double ab[], int job );
+void dscal ( int n, double sa, double x[], int incx );
+void dswap ( int n, double x[], int incx, double y[], int incy );
+double *qr_solve ( int m, int n, double a[], double b[] );
+
+#endif

+ 152 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/speed_lookuptable.h

@@ -0,0 +1,152 @@
+#ifndef SPEED_LOOKUPTABLE_H
+#define SPEED_LOOKUPTABLE_H
+
+#include "Marlin.h"
+
+#if F_CPU == 16000000
+
+const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\
+{ 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135}, 
+{ 961, 105}, { 856, 85}, { 771, 69}, { 702, 58}, { 644, 49}, { 595, 42}, { 553, 37}, { 516, 32}, 
+{ 484, 28}, { 456, 25}, { 431, 23}, { 408, 20}, { 388, 19}, { 369, 16}, { 353, 16}, { 337, 14}, 
+{ 323, 13}, { 310, 11}, { 299, 11}, { 288, 11}, { 277, 9}, { 268, 9}, { 259, 8}, { 251, 8}, 
+{ 243, 8}, { 235, 7}, { 228, 6}, { 222, 6}, { 216, 6}, { 210, 6}, { 204, 5}, { 199, 5}, 
+{ 194, 5}, { 189, 4}, { 185, 4}, { 181, 4}, { 177, 4}, { 173, 4}, { 169, 4}, { 165, 3}, 
+{ 162, 3}, { 159, 4}, { 155, 3}, { 152, 3}, { 149, 2}, { 147, 3}, { 144, 3}, { 141, 2}, 
+{ 139, 3}, { 136, 2}, { 134, 2}, { 132, 3}, { 129, 2}, { 127, 2}, { 125, 2}, { 123, 2}, 
+{ 121, 2}, { 119, 1}, { 118, 2}, { 116, 2}, { 114, 1}, { 113, 2}, { 111, 2}, { 109, 1}, 
+{ 108, 2}, { 106, 1}, { 105, 2}, { 103, 1}, { 102, 1}, { 101, 1}, { 100, 2}, { 98, 1}, 
+{ 97, 1}, { 96, 1}, { 95, 2}, { 93, 1}, { 92, 1}, { 91, 1}, { 90, 1}, { 89, 1}, 
+{ 88, 1}, { 87, 1}, { 86, 1}, { 85, 1}, { 84, 1}, { 83, 0}, { 83, 1}, { 82, 1}, 
+{ 81, 1}, { 80, 1}, { 79, 1}, { 78, 0}, { 78, 1}, { 77, 1}, { 76, 1}, { 75, 0}, 
+{ 75, 1}, { 74, 1}, { 73, 1}, { 72, 0}, { 72, 1}, { 71, 1}, { 70, 0}, { 70, 1}, 
+{ 69, 0}, { 69, 1}, { 68, 1}, { 67, 0}, { 67, 1}, { 66, 0}, { 66, 1}, { 65, 0}, 
+{ 65, 1}, { 64, 1}, { 63, 0}, { 63, 1}, { 62, 0}, { 62, 1}, { 61, 0}, { 61, 1}, 
+{ 60, 0}, { 60, 0}, { 60, 1}, { 59, 0}, { 59, 1}, { 58, 0}, { 58, 1}, { 57, 0}, 
+{ 57, 1}, { 56, 0}, { 56, 0}, { 56, 1}, { 55, 0}, { 55, 1}, { 54, 0}, { 54, 0}, 
+{ 54, 1}, { 53, 0}, { 53, 0}, { 53, 1}, { 52, 0}, { 52, 0}, { 52, 1}, { 51, 0}, 
+{ 51, 0}, { 51, 1}, { 50, 0}, { 50, 0}, { 50, 1}, { 49, 0}, { 49, 0}, { 49, 1}, 
+{ 48, 0}, { 48, 0}, { 48, 1}, { 47, 0}, { 47, 0}, { 47, 0}, { 47, 1}, { 46, 0}, 
+{ 46, 0}, { 46, 1}, { 45, 0}, { 45, 0}, { 45, 0}, { 45, 1}, { 44, 0}, { 44, 0}, 
+{ 44, 0}, { 44, 1}, { 43, 0}, { 43, 0}, { 43, 0}, { 43, 1}, { 42, 0}, { 42, 0}, 
+{ 42, 0}, { 42, 1}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 1}, { 40, 0}, 
+{ 40, 0}, { 40, 0}, { 40, 0}, { 40, 1}, { 39, 0}, { 39, 0}, { 39, 0}, { 39, 0}, 
+{ 39, 1}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 1}, { 37, 0}, { 37, 0}, 
+{ 37, 0}, { 37, 0}, { 37, 0}, { 37, 1}, { 36, 0}, { 36, 0}, { 36, 0}, { 36, 0}, 
+{ 36, 1}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 1}, 
+{ 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 1}, { 33, 0}, { 33, 0}, 
+{ 33, 0}, { 33, 0}, { 33, 0}, { 33, 0}, { 33, 1}, { 32, 0}, { 32, 0}, { 32, 0}, 
+{ 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 1}, { 31, 0}, { 31, 0}, { 31, 0}, 
+{ 31, 0}, { 31, 0}, { 31, 0}, { 31, 1}, { 30, 0}, { 30, 0}, { 30, 0}, { 30, 0}
+};
+
+const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\
+{ 62500, 12500}, { 50000, 8334}, { 41666, 5952}, { 35714, 4464}, { 31250, 3473}, { 27777, 2777}, { 25000, 2273}, { 22727, 1894}, 
+{ 20833, 1603}, { 19230, 1373}, { 17857, 1191}, { 16666, 1041}, { 15625, 920}, { 14705, 817}, { 13888, 731}, { 13157, 657}, 
+{ 12500, 596}, { 11904, 541}, { 11363, 494}, { 10869, 453}, { 10416, 416}, { 10000, 385}, { 9615, 356}, { 9259, 331}, 
+{ 8928, 308}, { 8620, 287}, { 8333, 269}, { 8064, 252}, { 7812, 237}, { 7575, 223}, { 7352, 210}, { 7142, 198}, 
+{ 6944, 188}, { 6756, 178}, { 6578, 168}, { 6410, 160}, { 6250, 153}, { 6097, 145}, { 5952, 139}, { 5813, 132}, 
+{ 5681, 126}, { 5555, 121}, { 5434, 115}, { 5319, 111}, { 5208, 106}, { 5102, 102}, { 5000, 99}, { 4901, 94}, 
+{ 4807, 91}, { 4716, 87}, { 4629, 84}, { 4545, 81}, { 4464, 79}, { 4385, 75}, { 4310, 73}, { 4237, 71}, 
+{ 4166, 68}, { 4098, 66}, { 4032, 64}, { 3968, 62}, { 3906, 60}, { 3846, 59}, { 3787, 56}, { 3731, 55}, 
+{ 3676, 53}, { 3623, 52}, { 3571, 50}, { 3521, 49}, { 3472, 48}, { 3424, 46}, { 3378, 45}, { 3333, 44}, 
+{ 3289, 43}, { 3246, 41}, { 3205, 41}, { 3164, 39}, { 3125, 39}, { 3086, 38}, { 3048, 36}, { 3012, 36}, 
+{ 2976, 35}, { 2941, 35}, { 2906, 33}, { 2873, 33}, { 2840, 32}, { 2808, 31}, { 2777, 30}, { 2747, 30}, 
+{ 2717, 29}, { 2688, 29}, { 2659, 28}, { 2631, 27}, { 2604, 27}, { 2577, 26}, { 2551, 26}, { 2525, 25}, 
+{ 2500, 25}, { 2475, 25}, { 2450, 23}, { 2427, 24}, { 2403, 23}, { 2380, 22}, { 2358, 22}, { 2336, 22}, 
+{ 2314, 21}, { 2293, 21}, { 2272, 20}, { 2252, 20}, { 2232, 20}, { 2212, 20}, { 2192, 19}, { 2173, 18}, 
+{ 2155, 19}, { 2136, 18}, { 2118, 18}, { 2100, 17}, { 2083, 17}, { 2066, 17}, { 2049, 17}, { 2032, 16}, 
+{ 2016, 16}, { 2000, 16}, { 1984, 16}, { 1968, 15}, { 1953, 16}, { 1937, 14}, { 1923, 15}, { 1908, 15}, 
+{ 1893, 14}, { 1879, 14}, { 1865, 14}, { 1851, 13}, { 1838, 14}, { 1824, 13}, { 1811, 13}, { 1798, 13}, 
+{ 1785, 12}, { 1773, 13}, { 1760, 12}, { 1748, 12}, { 1736, 12}, { 1724, 12}, { 1712, 12}, { 1700, 11}, 
+{ 1689, 12}, { 1677, 11}, { 1666, 11}, { 1655, 11}, { 1644, 11}, { 1633, 10}, { 1623, 11}, { 1612, 10}, 
+{ 1602, 10}, { 1592, 10}, { 1582, 10}, { 1572, 10}, { 1562, 10}, { 1552, 9}, { 1543, 10}, { 1533, 9}, 
+{ 1524, 9}, { 1515, 9}, { 1506, 9}, { 1497, 9}, { 1488, 9}, { 1479, 9}, { 1470, 9}, { 1461, 8}, 
+{ 1453, 8}, { 1445, 9}, { 1436, 8}, { 1428, 8}, { 1420, 8}, { 1412, 8}, { 1404, 8}, { 1396, 8}, 
+{ 1388, 7}, { 1381, 8}, { 1373, 7}, { 1366, 8}, { 1358, 7}, { 1351, 7}, { 1344, 8}, { 1336, 7}, 
+{ 1329, 7}, { 1322, 7}, { 1315, 7}, { 1308, 6}, { 1302, 7}, { 1295, 7}, { 1288, 6}, { 1282, 7}, 
+{ 1275, 6}, { 1269, 7}, { 1262, 6}, { 1256, 6}, { 1250, 7}, { 1243, 6}, { 1237, 6}, { 1231, 6}, 
+{ 1225, 6}, { 1219, 6}, { 1213, 6}, { 1207, 6}, { 1201, 5}, { 1196, 6}, { 1190, 6}, { 1184, 5}, 
+{ 1179, 6}, { 1173, 5}, { 1168, 6}, { 1162, 5}, { 1157, 5}, { 1152, 6}, { 1146, 5}, { 1141, 5}, 
+{ 1136, 5}, { 1131, 5}, { 1126, 5}, { 1121, 5}, { 1116, 5}, { 1111, 5}, { 1106, 5}, { 1101, 5}, 
+{ 1096, 5}, { 1091, 5}, { 1086, 4}, { 1082, 5}, { 1077, 5}, { 1072, 4}, { 1068, 5}, { 1063, 4}, 
+{ 1059, 5}, { 1054, 4}, { 1050, 4}, { 1046, 5}, { 1041, 4}, { 1037, 4}, { 1033, 5}, { 1028, 4}, 
+{ 1024, 4}, { 1020, 4}, { 1016, 4}, { 1012, 4}, { 1008, 4}, { 1004, 4}, { 1000, 4}, { 996, 4}, 
+{ 992, 4}, { 988, 4}, { 984, 4}, { 980, 4}, { 976, 4}, { 972, 4}, { 968, 3}, { 965, 3}
+};
+
+#elif F_CPU == 20000000
+
+const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {
+   {62500, 54055}, {8445, 3917}, {4528, 1434}, {3094, 745}, {2349, 456}, {1893, 307}, {1586, 222}, {1364, 167},
+   {1197, 131}, {1066, 105}, {961, 86}, {875, 72}, {803, 61}, {742, 53}, {689, 45}, {644, 40},
+   {604, 35}, {569, 32}, {537, 28}, {509, 25}, {484, 23}, {461, 21}, {440, 19}, {421, 17},
+   {404, 16}, {388, 15}, {373, 14}, {359, 13}, {346, 12}, {334, 11}, {323, 10}, {313, 10},
+   {303, 9}, {294, 9}, {285, 8}, {277, 7}, {270, 8}, {262, 7}, {255, 6}, {249, 6},
+   {243, 6}, {237, 6}, {231, 5}, {226, 5}, {221, 5}, {216, 5}, {211, 4}, {207, 5},
+   {202, 4}, {198, 4}, {194, 4}, {190, 3}, {187, 4}, {183, 3}, {180, 3}, {177, 4},
+   {173, 3}, {170, 3}, {167, 2}, {165, 3}, {162, 3}, {159, 2}, {157, 3}, {154, 2},
+   {152, 3}, {149, 2}, {147, 2}, {145, 2}, {143, 2}, {141, 2}, {139, 2}, {137, 2},
+   {135, 2}, {133, 2}, {131, 2}, {129, 1}, {128, 2}, {126, 2}, {124, 1}, {123, 2},
+   {121, 1}, {120, 2}, {118, 1}, {117, 1}, {116, 2}, {114, 1}, {113, 1}, {112, 2},
+   {110, 1}, {109, 1}, {108, 1}, {107, 2}, {105, 1}, {104, 1}, {103, 1}, {102, 1},
+   {101, 1}, {100, 1}, {99, 1}, {98, 1}, {97, 1}, {96, 1}, {95, 1}, {94, 1},
+   {93, 1}, {92, 1}, {91, 0}, {91, 1}, {90, 1}, {89, 1}, {88, 1}, {87, 0},
+   {87, 1}, {86, 1}, {85, 1}, {84, 0}, {84, 1}, {83, 1}, {82, 1}, {81, 0},
+   {81, 1}, {80, 1}, {79, 0}, {79, 1}, {78, 0}, {78, 1}, {77, 1}, {76, 0},
+   {76, 1}, {75, 0}, {75, 1}, {74, 1}, {73, 0}, {73, 1}, {72, 0}, {72, 1},
+   {71, 0}, {71, 1}, {70, 0}, {70, 1}, {69, 0}, {69, 1}, {68, 0}, {68, 1},
+   {67, 0}, {67, 1}, {66, 0}, {66, 1}, {65, 0}, {65, 0}, {65, 1}, {64, 0},
+   {64, 1}, {63, 0}, {63, 1}, {62, 0}, {62, 0}, {62, 1}, {61, 0}, {61, 1},
+   {60, 0}, {60, 0}, {60, 1}, {59, 0}, {59, 0}, {59, 1}, {58, 0}, {58, 0},
+   {58, 1}, {57, 0}, {57, 0}, {57, 1}, {56, 0}, {56, 0}, {56, 1}, {55, 0},
+   {55, 0}, {55, 1}, {54, 0}, {54, 0}, {54, 1}, {53, 0}, {53, 0}, {53, 0},
+   {53, 1}, {52, 0}, {52, 0}, {52, 1}, {51, 0}, {51, 0}, {51, 0}, {51, 1},
+   {50, 0}, {50, 0}, {50, 0}, {50, 1}, {49, 0}, {49, 0}, {49, 0}, {49, 1},
+   {48, 0}, {48, 0}, {48, 0}, {48, 1}, {47, 0}, {47, 0}, {47, 0}, {47, 1},
+   {46, 0}, {46, 0}, {46, 0}, {46, 0}, {46, 1}, {45, 0}, {45, 0}, {45, 0},
+   {45, 1}, {44, 0}, {44, 0}, {44, 0}, {44, 0}, {44, 1}, {43, 0}, {43, 0},
+   {43, 0}, {43, 0}, {43, 1}, {42, 0}, {42, 0}, {42, 0}, {42, 0}, {42, 0},
+   {42, 1}, {41, 0}, {41, 0}, {41, 0}, {41, 0}, {41, 0}, {41, 1}, {40, 0},
+   {40, 0}, {40, 0}, {40, 0}, {40, 1}, {39, 0}, {39, 0}, {39, 0}, {39, 0},
+   {39, 0}, {39, 0}, {39, 1}, {38, 0}, {38, 0}, {38, 0}, {38, 0}, {38, 0},
+};
+
+const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {
+   {62500, 10417}, {52083, 7441}, {44642, 5580}, {39062, 4340}, {34722, 3472}, {31250, 2841}, {28409, 2368}, {26041, 2003},
+   {24038, 1717}, {22321, 1488}, {20833, 1302}, {19531, 1149}, {18382, 1021}, {17361, 914}, {16447, 822}, {15625, 745},
+   {14880, 676}, {14204, 618}, {13586, 566}, {13020, 520}, {12500, 481}, {12019, 445}, {11574, 414}, {11160, 385},
+   {10775, 359}, {10416, 336}, {10080, 315}, {9765, 296}, {9469, 278}, {9191, 263}, {8928, 248}, {8680, 235},
+   {8445, 222}, {8223, 211}, {8012, 200}, {7812, 191}, {7621, 181}, {7440, 173}, {7267, 165}, {7102, 158},
+   {6944, 151}, {6793, 145}, {6648, 138}, {6510, 133}, {6377, 127}, {6250, 123}, {6127, 118}, {6009, 113},
+   {5896, 109}, {5787, 106}, {5681, 101}, {5580, 98}, {5482, 95}, {5387, 91}, {5296, 88}, {5208, 86},
+   {5122, 82}, {5040, 80}, {4960, 78}, {4882, 75}, {4807, 73}, {4734, 70}, {4664, 69}, {4595, 67},
+   {4528, 64}, {4464, 63}, {4401, 61}, {4340, 60}, {4280, 58}, {4222, 56}, {4166, 55}, {4111, 53},
+   {4058, 52}, {4006, 51}, {3955, 49}, {3906, 48}, {3858, 48}, {3810, 45}, {3765, 45}, {3720, 44},
+   {3676, 43}, {3633, 42}, {3591, 40}, {3551, 40}, {3511, 39}, {3472, 38}, {3434, 38}, {3396, 36},
+   {3360, 36}, {3324, 35}, {3289, 34}, {3255, 34}, {3221, 33}, {3188, 32}, {3156, 31}, {3125, 31},
+   {3094, 31}, {3063, 30}, {3033, 29}, {3004, 28}, {2976, 28}, {2948, 28}, {2920, 27}, {2893, 27},
+   {2866, 26}, {2840, 25}, {2815, 25}, {2790, 25}, {2765, 24}, {2741, 24}, {2717, 24}, {2693, 23},
+   {2670, 22}, {2648, 22}, {2626, 22}, {2604, 22}, {2582, 21}, {2561, 21}, {2540, 20}, {2520, 20},
+   {2500, 20}, {2480, 20}, {2460, 19}, {2441, 19}, {2422, 19}, {2403, 18}, {2385, 18}, {2367, 18},
+   {2349, 17}, {2332, 18}, {2314, 17}, {2297, 16}, {2281, 17}, {2264, 16}, {2248, 16}, {2232, 16},
+   {2216, 16}, {2200, 15}, {2185, 15}, {2170, 15}, {2155, 15}, {2140, 15}, {2125, 14}, {2111, 14},
+   {2097, 14}, {2083, 14}, {2069, 14}, {2055, 13}, {2042, 13}, {2029, 13}, {2016, 13}, {2003, 13},
+   {1990, 13}, {1977, 12}, {1965, 12}, {1953, 13}, {1940, 11}, {1929, 12}, {1917, 12}, {1905, 12},
+   {1893, 11}, {1882, 11}, {1871, 11}, {1860, 11}, {1849, 11}, {1838, 11}, {1827, 11}, {1816, 10},
+   {1806, 11}, {1795, 10}, {1785, 10}, {1775, 10}, {1765, 10}, {1755, 10}, {1745, 9}, {1736, 10},
+   {1726, 9}, {1717, 10}, {1707, 9}, {1698, 9}, {1689, 9}, {1680, 9}, {1671, 9}, {1662, 9},
+   {1653, 9}, {1644, 8}, {1636, 9}, {1627, 8}, {1619, 9}, {1610, 8}, {1602, 8}, {1594, 8},
+   {1586, 8}, {1578, 8}, {1570, 8}, {1562, 8}, {1554, 7}, {1547, 8}, {1539, 8}, {1531, 7},
+   {1524, 8}, {1516, 7}, {1509, 7}, {1502, 7}, {1495, 7}, {1488, 7}, {1481, 7}, {1474, 7},
+   {1467, 7}, {1460, 7}, {1453, 7}, {1446, 6}, {1440, 7}, {1433, 7}, {1426, 6}, {1420, 6},
+   {1414, 7}, {1407, 6}, {1401, 6}, {1395, 7}, {1388, 6}, {1382, 6}, {1376, 6}, {1370, 6},
+   {1364, 6}, {1358, 6}, {1352, 6}, {1346, 5}, {1341, 6}, {1335, 6}, {1329, 5}, {1324, 6},
+   {1318, 5}, {1313, 6}, {1307, 5}, {1302, 6}, {1296, 5}, {1291, 5}, {1286, 6}, {1280, 5},
+   {1275, 5}, {1270, 5}, {1265, 5}, {1260, 5}, {1255, 5}, {1250, 5}, {1245, 5}, {1240, 5},
+   {1235, 5}, {1230, 5}, {1225, 5}, {1220, 5}, {1215, 4}, {1211, 5}, {1206, 5}, {1201, 5},
+};
+
+#endif
+
+#endif

File diff suppressed because it is too large
+ 1293 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/stepper.cpp


+ 101 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/stepper.h

@@ -0,0 +1,101 @@
+/*
+  stepper.h - stepper motor driver: executes motion plans of planner.c using the stepper motors
+  Part of Grbl
+
+  Copyright (c) 2009-2011 Simen Svale Skogsrud
+
+  Grbl 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.
+
+  Grbl 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 Grbl.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef stepper_h
+#define stepper_h 
+
+#include "planner.h"
+
+#if EXTRUDERS > 2
+  #define WRITE_E_STEP(v) { if(current_block->active_extruder == 2) { WRITE(E2_STEP_PIN, v); } else { if(current_block->active_extruder == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}}
+  #define NORM_E_DIR() { if(current_block->active_extruder == 2) { WRITE(E2_DIR_PIN, !INVERT_E2_DIR); } else { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}}
+  #define REV_E_DIR() { if(current_block->active_extruder == 2) { WRITE(E2_DIR_PIN, INVERT_E2_DIR); } else { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}}
+#elif EXTRUDERS > 1
+  #ifndef DUAL_X_CARRIAGE
+    #define WRITE_E_STEP(v) { if(current_block->active_extruder == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}
+    #define NORM_E_DIR() { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}
+    #define REV_E_DIR() { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}
+  #else
+    extern bool extruder_duplication_enabled;
+    #define WRITE_E_STEP(v) { if(extruder_duplication_enabled) { WRITE(E0_STEP_PIN, v); WRITE(E1_STEP_PIN, v); } else if(current_block->active_extruder == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}
+    #define NORM_E_DIR() { if(extruder_duplication_enabled) { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}
+    #define REV_E_DIR() { if(extruder_duplication_enabled) { WRITE(E0_DIR_PIN, INVERT_E0_DIR); WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}
+  #endif  
+#else
+  #define WRITE_E_STEP(v) WRITE(E0_STEP_PIN, v)
+  #define NORM_E_DIR() WRITE(E0_DIR_PIN, !INVERT_E0_DIR)
+  #define REV_E_DIR() WRITE(E0_DIR_PIN, INVERT_E0_DIR)
+#endif
+
+#ifdef ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
+extern bool abort_on_endstop_hit;
+#endif
+
+// Initialize and start the stepper motor subsystem
+void st_init();
+
+// Block until all buffered steps are executed
+void st_synchronize();
+
+// Set current position in steps
+void st_set_position(const long &x, const long &y, const long &z, const long &e);
+void st_set_e_position(const long &e);
+
+// Get current position in steps
+long st_get_position(uint8_t axis);
+
+#ifdef ENABLE_AUTO_BED_LEVELING
+// Get current position in mm
+float st_get_position_mm(uint8_t axis);
+#endif  //ENABLE_AUTO_BED_LEVELING
+
+// The stepper subsystem goes to sleep when it runs out of things to execute. Call this
+// to notify the subsystem that it is time to go to work.
+void st_wake_up();
+
+  
+void checkHitEndstops(); //call from somwhere to create an serial error message with the locations the endstops where hit, in case they were triggered
+void endstops_hit_on_purpose(); //avoid creation of the message, i.e. after homeing and before a routine call of checkHitEndstops();
+
+void enable_endstops(bool check); // Enable/disable endstop checking
+
+void checkStepperErrors(); //Print errors detected by the stepper
+
+void finishAndDisableSteppers();
+
+extern block_t *current_block;  // A pointer to the block currently being traced
+
+void quickStop();
+
+void digitalPotWrite(int address, int value);
+void microstep_ms(uint8_t driver, int8_t ms1, int8_t ms2);
+void microstep_mode(uint8_t driver, uint8_t stepping);
+void digipot_init();
+void digipot_current(uint8_t driver, int current);
+void microstep_init();
+void microstep_readings();
+
+#ifdef BABYSTEPPING
+  void babystep(const uint8_t axis,const bool direction); // perform a short step with a single stepper motor, outside of any convention
+#endif
+     
+
+
+#endif

File diff suppressed because it is too large
+ 1323 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/temperature.cpp


+ 171 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/temperature.h

@@ -0,0 +1,171 @@
+/*
+  temperature.h - temperature controller
+  Part of Marlin
+
+  Copyright (c) 2011 Erik van der Zalm
+
+  Grbl 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.
+
+  Grbl 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 Grbl.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef temperature_h
+#define temperature_h 
+
+#include "Marlin.h"
+#include "planner.h"
+#ifdef PID_ADD_EXTRUSION_RATE
+  #include "stepper.h"
+#endif
+
+// public functions
+void tp_init();  //initialise the heating
+void manage_heater(); //it is critical that this is called periodically.
+
+// low level conversion routines
+// do not use these routines and variables outside of temperature.cpp
+extern int target_temperature[EXTRUDERS];  
+extern float current_temperature[EXTRUDERS];
+#ifdef SHOW_TEMP_ADC_VALUES
+  extern int current_temperature_raw[EXTRUDERS];
+  extern int current_temperature_bed_raw;
+#endif
+extern int target_temperature_bed;
+extern float current_temperature_bed;
+#ifdef TEMP_SENSOR_1_AS_REDUNDANT
+  extern float redundant_temperature;
+#endif
+
+#if defined(CONTROLLERFAN_PIN) && CONTROLLERFAN_PIN > -1
+  extern unsigned char soft_pwm_bed;
+#endif
+
+#ifdef PIDTEMP
+  extern float Kp,Ki,Kd,Kc;
+  float scalePID_i(float i);
+  float scalePID_d(float d);
+  float unscalePID_i(float i);
+  float unscalePID_d(float d);
+
+#endif
+#ifdef PIDTEMPBED
+  extern float bedKp,bedKi,bedKd;
+#endif
+  
+  
+#ifdef BABYSTEPPING
+  extern volatile int babystepsTodo[3];
+#endif
+  
+//high level conversion routines, for use outside of temperature.cpp
+//inline so that there is no performance decrease.
+//deg=degreeCelsius
+
+FORCE_INLINE float degHotend(uint8_t extruder) {  
+  return current_temperature[extruder];
+};
+
+#ifdef SHOW_TEMP_ADC_VALUES
+  FORCE_INLINE float rawHotendTemp(uint8_t extruder) {  
+    return current_temperature_raw[extruder];
+  };
+
+  FORCE_INLINE float rawBedTemp() {  
+    return current_temperature_bed_raw;
+  };
+#endif
+
+FORCE_INLINE float degBed() {
+  return current_temperature_bed;
+};
+
+FORCE_INLINE float degTargetHotend(uint8_t extruder) {  
+  return target_temperature[extruder];
+};
+
+FORCE_INLINE float degTargetBed() {   
+  return target_temperature_bed;
+};
+
+FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) {  
+  target_temperature[extruder] = celsius;
+};
+
+FORCE_INLINE void setTargetBed(const float &celsius) {  
+  target_temperature_bed = celsius;
+};
+
+FORCE_INLINE bool isHeatingHotend(uint8_t extruder){  
+  return target_temperature[extruder] > current_temperature[extruder];
+};
+
+FORCE_INLINE bool isHeatingBed() {
+  return target_temperature_bed > current_temperature_bed;
+};
+
+FORCE_INLINE bool isCoolingHotend(uint8_t extruder) {  
+  return target_temperature[extruder] < current_temperature[extruder];
+};
+
+FORCE_INLINE bool isCoolingBed() {
+  return target_temperature_bed < current_temperature_bed;
+};
+
+#define degHotend0() degHotend(0)
+#define degTargetHotend0() degTargetHotend(0)
+#define setTargetHotend0(_celsius) setTargetHotend((_celsius), 0)
+#define isHeatingHotend0() isHeatingHotend(0)
+#define isCoolingHotend0() isCoolingHotend(0)
+#if EXTRUDERS > 1
+#define degHotend1() degHotend(1)
+#define degTargetHotend1() degTargetHotend(1)
+#define setTargetHotend1(_celsius) setTargetHotend((_celsius), 1)
+#define isHeatingHotend1() isHeatingHotend(1)
+#define isCoolingHotend1() isCoolingHotend(1)
+#else
+#define setTargetHotend1(_celsius) do{}while(0)
+#endif
+#if EXTRUDERS > 2
+#define degHotend2() degHotend(2)
+#define degTargetHotend2() degTargetHotend(2)
+#define setTargetHotend2(_celsius) setTargetHotend((_celsius), 2)
+#define isHeatingHotend2() isHeatingHotend(2)
+#define isCoolingHotend2() isCoolingHotend(2)
+#else
+#define setTargetHotend2(_celsius) do{}while(0)
+#endif
+#if EXTRUDERS > 3
+#error Invalid number of extruders
+#endif
+
+
+
+int getHeaterPower(int heater);
+void disable_heater();
+void setWatch();
+void updatePID();
+
+FORCE_INLINE void autotempShutdown(){
+ #ifdef AUTOTEMP
+ if(autotemp_enabled)
+ {
+  autotemp_enabled=false;
+  if(degTargetHotend(active_extruder)>autotemp_min)
+    setTargetHotend(0,active_extruder);
+ }
+ #endif
+}
+
+void PID_autotune(float temp, int extruder, int ncycles);
+
+#endif
+

+ 953 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/thermistortables.h

@@ -0,0 +1,953 @@
+#ifndef THERMISTORTABLES_H_
+#define THERMISTORTABLES_H_
+
+#include "Marlin.h"
+
+#define OVERSAMPLENR 16
+
+#if (THERMISTORHEATER_0 == 1) || (THERMISTORHEATER_1 == 1)  || (THERMISTORHEATER_2 == 1) || (THERMISTORBED == 1) //100k bed thermistor
+
+const short temptable_1[][2] PROGMEM = {
+{       23*OVERSAMPLENR ,       300     },
+{       25*OVERSAMPLENR ,       295     },
+{       27*OVERSAMPLENR ,       290     },
+{       28*OVERSAMPLENR ,       285     },
+{       31*OVERSAMPLENR ,       280     },
+{       33*OVERSAMPLENR ,       275     },
+{       35*OVERSAMPLENR ,       270     },
+{       38*OVERSAMPLENR ,       265     },
+{       41*OVERSAMPLENR ,       260     },
+{       44*OVERSAMPLENR ,       255     },
+{       48*OVERSAMPLENR ,       250     },
+{       52*OVERSAMPLENR ,       245     },
+{       56*OVERSAMPLENR ,       240     },
+{       61*OVERSAMPLENR ,       235     },
+{       66*OVERSAMPLENR ,       230     },
+{       71*OVERSAMPLENR ,       225     },
+{       78*OVERSAMPLENR ,       220     },
+{       84*OVERSAMPLENR ,       215     },
+{       92*OVERSAMPLENR ,       210     },
+{       100*OVERSAMPLENR        ,       205     },
+{       109*OVERSAMPLENR        ,       200     },
+{       120*OVERSAMPLENR        ,       195     },
+{       131*OVERSAMPLENR        ,       190     },
+{       143*OVERSAMPLENR        ,       185     },
+{       156*OVERSAMPLENR        ,       180     },
+{       171*OVERSAMPLENR        ,       175     },
+{       187*OVERSAMPLENR        ,       170     },
+{       205*OVERSAMPLENR        ,       165     },
+{       224*OVERSAMPLENR        ,       160     },
+{       245*OVERSAMPLENR        ,       155     },
+{       268*OVERSAMPLENR        ,       150     },
+{       293*OVERSAMPLENR        ,       145     },
+{       320*OVERSAMPLENR        ,       140     },
+{       348*OVERSAMPLENR        ,       135     },
+{       379*OVERSAMPLENR        ,       130     },
+{       411*OVERSAMPLENR        ,       125     },
+{       445*OVERSAMPLENR        ,       120     },
+{       480*OVERSAMPLENR        ,       115     },
+{       516*OVERSAMPLENR        ,       110     },
+{       553*OVERSAMPLENR        ,       105     },
+{       591*OVERSAMPLENR        ,       100     },
+{       628*OVERSAMPLENR        ,       95      },
+{       665*OVERSAMPLENR        ,       90      },
+{       702*OVERSAMPLENR        ,       85      },
+{       737*OVERSAMPLENR        ,       80      },
+{       770*OVERSAMPLENR        ,       75      },
+{       801*OVERSAMPLENR        ,       70      },
+{       830*OVERSAMPLENR        ,       65      },
+{       857*OVERSAMPLENR        ,       60      },
+{       881*OVERSAMPLENR        ,       55      },
+{       903*OVERSAMPLENR        ,       50      },
+{       922*OVERSAMPLENR        ,       45      },
+{       939*OVERSAMPLENR        ,       40      },
+{       954*OVERSAMPLENR        ,       35      },
+{       966*OVERSAMPLENR        ,       30      },
+{       977*OVERSAMPLENR        ,       25      },
+{       985*OVERSAMPLENR        ,       20      },
+{       993*OVERSAMPLENR        ,       15      },
+{       999*OVERSAMPLENR        ,       10      },
+{       1004*OVERSAMPLENR       ,       5       },
+{       1008*OVERSAMPLENR       ,       0       } //safety
+};
+#endif
+#if (THERMISTORHEATER_0 == 2) || (THERMISTORHEATER_1 == 2) || (THERMISTORHEATER_2 == 2) || (THERMISTORBED == 2) //200k bed thermistor
+const short temptable_2[][2] PROGMEM = {
+//200k ATC Semitec 204GT-2
+//Verified by linagee. Source: http://shop.arcol.hu/static/datasheets/thermistors.pdf
+// Calculated using 4.7kohm pullup, voltage divider math, and manufacturer provided temp/resistance
+   {1*OVERSAMPLENR, 848},
+   {30*OVERSAMPLENR, 300}, //top rating 300C
+   {34*OVERSAMPLENR, 290},
+   {39*OVERSAMPLENR, 280},
+   {46*OVERSAMPLENR, 270},
+   {53*OVERSAMPLENR, 260},
+   {63*OVERSAMPLENR, 250},
+   {74*OVERSAMPLENR, 240},
+   {87*OVERSAMPLENR, 230},
+   {104*OVERSAMPLENR, 220},
+   {124*OVERSAMPLENR, 210},
+   {148*OVERSAMPLENR, 200},
+   {176*OVERSAMPLENR, 190},
+   {211*OVERSAMPLENR, 180},
+   {252*OVERSAMPLENR, 170},
+   {301*OVERSAMPLENR, 160},
+   {357*OVERSAMPLENR, 150},
+   {420*OVERSAMPLENR, 140},
+   {489*OVERSAMPLENR, 130},
+   {562*OVERSAMPLENR, 120},
+   {636*OVERSAMPLENR, 110},
+   {708*OVERSAMPLENR, 100},
+   {775*OVERSAMPLENR, 90},
+   {835*OVERSAMPLENR, 80},
+   {884*OVERSAMPLENR, 70},
+   {924*OVERSAMPLENR, 60},
+   {955*OVERSAMPLENR, 50},
+   {977*OVERSAMPLENR, 40},
+   {993*OVERSAMPLENR, 30},
+   {1004*OVERSAMPLENR, 20},
+   {1012*OVERSAMPLENR, 10},
+   {1016*OVERSAMPLENR, 0},
+};
+
+#endif
+#if (THERMISTORHEATER_0 == 3) || (THERMISTORHEATER_1 == 3) || (THERMISTORHEATER_2 == 3) || (THERMISTORBED == 3) //mendel-parts
+const short temptable_3[][2] PROGMEM = {
+                {1*OVERSAMPLENR,864},
+                {21*OVERSAMPLENR,300},
+                {25*OVERSAMPLENR,290},
+                {29*OVERSAMPLENR,280},
+                {33*OVERSAMPLENR,270},
+                {39*OVERSAMPLENR,260},
+                {46*OVERSAMPLENR,250},
+                {54*OVERSAMPLENR,240},
+                {64*OVERSAMPLENR,230},
+                {75*OVERSAMPLENR,220},
+                {90*OVERSAMPLENR,210},
+                {107*OVERSAMPLENR,200},
+                {128*OVERSAMPLENR,190},
+                {154*OVERSAMPLENR,180},
+                {184*OVERSAMPLENR,170},
+                {221*OVERSAMPLENR,160},
+                {265*OVERSAMPLENR,150},
+                {316*OVERSAMPLENR,140},
+                {375*OVERSAMPLENR,130},
+                {441*OVERSAMPLENR,120},
+                {513*OVERSAMPLENR,110},
+                {588*OVERSAMPLENR,100},
+                {734*OVERSAMPLENR,80},
+                {856*OVERSAMPLENR,60},
+                {938*OVERSAMPLENR,40},
+                {986*OVERSAMPLENR,20},
+                {1008*OVERSAMPLENR,0},
+                {1018*OVERSAMPLENR,-20}
+        };
+
+#endif
+#if (THERMISTORHEATER_0 == 4) || (THERMISTORHEATER_1 == 4) || (THERMISTORHEATER_2 == 4) || (THERMISTORBED == 4) //10k thermistor
+const short temptable_4[][2] PROGMEM = {
+   {1*OVERSAMPLENR, 430},
+   {54*OVERSAMPLENR, 137},
+   {107*OVERSAMPLENR, 107},
+   {160*OVERSAMPLENR, 91},
+   {213*OVERSAMPLENR, 80},
+   {266*OVERSAMPLENR, 71},
+   {319*OVERSAMPLENR, 64},
+   {372*OVERSAMPLENR, 57},
+   {425*OVERSAMPLENR, 51},
+   {478*OVERSAMPLENR, 46},
+   {531*OVERSAMPLENR, 41},
+   {584*OVERSAMPLENR, 35},
+   {637*OVERSAMPLENR, 30},
+   {690*OVERSAMPLENR, 25},
+   {743*OVERSAMPLENR, 20},
+   {796*OVERSAMPLENR, 14},
+   {849*OVERSAMPLENR, 7},
+   {902*OVERSAMPLENR, 0},
+   {955*OVERSAMPLENR, -11},
+   {1008*OVERSAMPLENR, -35}
+};
+#endif
+
+#if (THERMISTORHEATER_0 == 5) || (THERMISTORHEATER_1 == 5) || (THERMISTORHEATER_2 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2)
+const short temptable_5[][2] PROGMEM = {
+// ATC Semitec 104GT-2 (Used in ParCan)
+// Verified by linagee. Source: http://shop.arcol.hu/static/datasheets/thermistors.pdf
+// Calculated using 4.7kohm pullup, voltage divider math, and manufacturer provided temp/resistance
+   {1*OVERSAMPLENR, 713},
+   {17*OVERSAMPLENR, 300}, //top rating 300C
+   {20*OVERSAMPLENR, 290},
+   {23*OVERSAMPLENR, 280},
+   {27*OVERSAMPLENR, 270},
+   {31*OVERSAMPLENR, 260},
+   {37*OVERSAMPLENR, 250},
+   {43*OVERSAMPLENR, 240},
+   {51*OVERSAMPLENR, 230},
+   {61*OVERSAMPLENR, 220},
+   {73*OVERSAMPLENR, 210},
+   {87*OVERSAMPLENR, 200},
+   {106*OVERSAMPLENR, 190},
+   {128*OVERSAMPLENR, 180},
+   {155*OVERSAMPLENR, 170},
+   {189*OVERSAMPLENR, 160},
+   {230*OVERSAMPLENR, 150},
+   {278*OVERSAMPLENR, 140},
+   {336*OVERSAMPLENR, 130},
+   {402*OVERSAMPLENR, 120},
+   {476*OVERSAMPLENR, 110},
+   {554*OVERSAMPLENR, 100},
+   {635*OVERSAMPLENR, 90},
+   {713*OVERSAMPLENR, 80},
+   {784*OVERSAMPLENR, 70},
+   {846*OVERSAMPLENR, 60},
+   {897*OVERSAMPLENR, 50},
+   {937*OVERSAMPLENR, 40},
+   {966*OVERSAMPLENR, 30},
+   {986*OVERSAMPLENR, 20},
+   {1000*OVERSAMPLENR, 10},
+   {1010*OVERSAMPLENR, 0}
+};
+#endif
+
+#if (THERMISTORHEATER_0 == 6) || (THERMISTORHEATER_1 == 6) || (THERMISTORHEATER_2 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor
+const short temptable_6[][2] PROGMEM = {
+   {1*OVERSAMPLENR, 350},
+   {28*OVERSAMPLENR, 250}, //top rating 250C
+   {31*OVERSAMPLENR, 245},
+   {35*OVERSAMPLENR, 240},
+   {39*OVERSAMPLENR, 235},
+   {42*OVERSAMPLENR, 230},
+   {44*OVERSAMPLENR, 225},
+   {49*OVERSAMPLENR, 220},
+   {53*OVERSAMPLENR, 215},
+   {62*OVERSAMPLENR, 210},
+   {71*OVERSAMPLENR, 205}, //fitted graphically
+   {78*OVERSAMPLENR, 200}, //fitted graphically
+   {94*OVERSAMPLENR, 190},
+   {102*OVERSAMPLENR, 185},
+   {116*OVERSAMPLENR, 170},
+   {143*OVERSAMPLENR, 160},
+   {183*OVERSAMPLENR, 150},
+   {223*OVERSAMPLENR, 140},
+   {270*OVERSAMPLENR, 130},
+   {318*OVERSAMPLENR, 120},
+   {383*OVERSAMPLENR, 110},
+   {413*OVERSAMPLENR, 105},
+   {439*OVERSAMPLENR, 100},
+   {484*OVERSAMPLENR, 95},
+   {513*OVERSAMPLENR, 90},
+   {607*OVERSAMPLENR, 80},
+   {664*OVERSAMPLENR, 70},
+   {781*OVERSAMPLENR, 60},
+   {810*OVERSAMPLENR, 55},
+   {849*OVERSAMPLENR, 50},
+   {914*OVERSAMPLENR, 45},
+   {914*OVERSAMPLENR, 40},
+   {935*OVERSAMPLENR, 35},
+   {954*OVERSAMPLENR, 30},
+   {970*OVERSAMPLENR, 25},
+   {978*OVERSAMPLENR, 22},
+   {1008*OVERSAMPLENR, 3},
+   {1023*OVERSAMPLENR, 0}  //to allow internal 0 degrees C
+};
+#endif
+
+#if (THERMISTORHEATER_0 == 7) || (THERMISTORHEATER_1 == 7) || (THERMISTORHEATER_2 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01
+const short temptable_7[][2] PROGMEM = {
+   {1*OVERSAMPLENR, 941},
+   {19*OVERSAMPLENR, 362},
+   {37*OVERSAMPLENR, 299}, //top rating 300C
+   {55*OVERSAMPLENR, 266},
+   {73*OVERSAMPLENR, 245},
+   {91*OVERSAMPLENR, 229},
+   {109*OVERSAMPLENR, 216},
+   {127*OVERSAMPLENR, 206},
+   {145*OVERSAMPLENR, 197},
+   {163*OVERSAMPLENR, 190},
+   {181*OVERSAMPLENR, 183},
+   {199*OVERSAMPLENR, 177},
+   {217*OVERSAMPLENR, 171},
+   {235*OVERSAMPLENR, 166},
+   {253*OVERSAMPLENR, 162},
+   {271*OVERSAMPLENR, 157},
+   {289*OVERSAMPLENR, 153},
+   {307*OVERSAMPLENR, 149},
+   {325*OVERSAMPLENR, 146},
+   {343*OVERSAMPLENR, 142},
+   {361*OVERSAMPLENR, 139},
+   {379*OVERSAMPLENR, 135},
+   {397*OVERSAMPLENR, 132},
+   {415*OVERSAMPLENR, 129},
+   {433*OVERSAMPLENR, 126},
+   {451*OVERSAMPLENR, 123},
+   {469*OVERSAMPLENR, 121},
+   {487*OVERSAMPLENR, 118},
+   {505*OVERSAMPLENR, 115},
+   {523*OVERSAMPLENR, 112},
+   {541*OVERSAMPLENR, 110},
+   {559*OVERSAMPLENR, 107},
+   {577*OVERSAMPLENR, 105},
+   {595*OVERSAMPLENR, 102},
+   {613*OVERSAMPLENR, 99},
+   {631*OVERSAMPLENR, 97},
+   {649*OVERSAMPLENR, 94},
+   {667*OVERSAMPLENR, 92},
+   {685*OVERSAMPLENR, 89},
+   {703*OVERSAMPLENR, 86},
+   {721*OVERSAMPLENR, 84},
+   {739*OVERSAMPLENR, 81},
+   {757*OVERSAMPLENR, 78},
+   {775*OVERSAMPLENR, 75},
+   {793*OVERSAMPLENR, 72},
+   {811*OVERSAMPLENR, 69},
+   {829*OVERSAMPLENR, 66},
+   {847*OVERSAMPLENR, 62},
+   {865*OVERSAMPLENR, 59},
+   {883*OVERSAMPLENR, 55},
+   {901*OVERSAMPLENR, 51},
+   {919*OVERSAMPLENR, 46},
+   {937*OVERSAMPLENR, 41},
+   {955*OVERSAMPLENR, 35},
+   {973*OVERSAMPLENR, 27},
+   {991*OVERSAMPLENR, 17},
+   {1009*OVERSAMPLENR, 1},
+   {1023*OVERSAMPLENR, 0}  //to allow internal 0 degrees C
+};
+#endif
+
+#if (THERMISTORHEATER_0 == 71) || (THERMISTORHEATER_1 == 71) || (THERMISTORHEATER_2 == 71) || (THERMISTORBED == 71) // 100k Honeywell 135-104LAF-J01
+// R0 = 100000 Ohm
+// T0 = 25 °C
+// Beta = 3974
+// R1 = 0 Ohm
+// R2 = 4700 Ohm
+const short temptable_71[][2] PROGMEM = {
+   {35*OVERSAMPLENR, 300},
+   {51*OVERSAMPLENR, 270},
+   {54*OVERSAMPLENR, 265},
+   {58*OVERSAMPLENR, 260},
+   {59*OVERSAMPLENR, 258},
+   {61*OVERSAMPLENR, 256},
+   {63*OVERSAMPLENR, 254},
+   {64*OVERSAMPLENR, 252},
+   {66*OVERSAMPLENR, 250},
+   {67*OVERSAMPLENR, 249},
+   {68*OVERSAMPLENR, 248},
+   {69*OVERSAMPLENR, 247},
+   {70*OVERSAMPLENR, 246},
+   {71*OVERSAMPLENR, 245},
+   {72*OVERSAMPLENR, 244},
+   {73*OVERSAMPLENR, 243},
+   {74*OVERSAMPLENR, 242},
+   {75*OVERSAMPLENR, 241},
+   {76*OVERSAMPLENR, 240},
+   {77*OVERSAMPLENR, 239},
+   {78*OVERSAMPLENR, 238},
+   {79*OVERSAMPLENR, 237},
+   {80*OVERSAMPLENR, 236},
+   {81*OVERSAMPLENR, 235},
+   {82*OVERSAMPLENR, 234},
+   {84*OVERSAMPLENR, 233},
+   {85*OVERSAMPLENR, 232},
+   {86*OVERSAMPLENR, 231},
+   {87*OVERSAMPLENR, 230},
+   {89*OVERSAMPLENR, 229},
+   {90*OVERSAMPLENR, 228},
+   {91*OVERSAMPLENR, 227},
+   {92*OVERSAMPLENR, 226},
+   {94*OVERSAMPLENR, 225},
+   {95*OVERSAMPLENR, 224},
+   {97*OVERSAMPLENR, 223},
+   {98*OVERSAMPLENR, 222},
+   {99*OVERSAMPLENR, 221},
+   {101*OVERSAMPLENR, 220},
+   {102*OVERSAMPLENR, 219},
+   {104*OVERSAMPLENR, 218},
+   {106*OVERSAMPLENR, 217},
+   {107*OVERSAMPLENR, 216},
+   {109*OVERSAMPLENR, 215},
+   {110*OVERSAMPLENR, 214},
+   {112*OVERSAMPLENR, 213},
+   {114*OVERSAMPLENR, 212},
+   {115*OVERSAMPLENR, 211},
+   {117*OVERSAMPLENR, 210},
+   {119*OVERSAMPLENR, 209},
+   {121*OVERSAMPLENR, 208},
+   {123*OVERSAMPLENR, 207},
+   {125*OVERSAMPLENR, 206},
+   {126*OVERSAMPLENR, 205},
+   {128*OVERSAMPLENR, 204},
+   {130*OVERSAMPLENR, 203},
+   {132*OVERSAMPLENR, 202},
+   {134*OVERSAMPLENR, 201},
+   {136*OVERSAMPLENR, 200},
+   {139*OVERSAMPLENR, 199},
+   {141*OVERSAMPLENR, 198},
+   {143*OVERSAMPLENR, 197},
+   {145*OVERSAMPLENR, 196},
+   {147*OVERSAMPLENR, 195},
+   {150*OVERSAMPLENR, 194},
+   {152*OVERSAMPLENR, 193},
+   {154*OVERSAMPLENR, 192},
+   {157*OVERSAMPLENR, 191},
+   {159*OVERSAMPLENR, 190},
+   {162*OVERSAMPLENR, 189},
+   {164*OVERSAMPLENR, 188},
+   {167*OVERSAMPLENR, 187},
+   {170*OVERSAMPLENR, 186},
+   {172*OVERSAMPLENR, 185},
+   {175*OVERSAMPLENR, 184},
+   {178*OVERSAMPLENR, 183},
+   {181*OVERSAMPLENR, 182},
+   {184*OVERSAMPLENR, 181},
+   {187*OVERSAMPLENR, 180},
+   {190*OVERSAMPLENR, 179},
+   {193*OVERSAMPLENR, 178},
+   {196*OVERSAMPLENR, 177},
+   {199*OVERSAMPLENR, 176},
+   {202*OVERSAMPLENR, 175},
+   {205*OVERSAMPLENR, 174},
+   {208*OVERSAMPLENR, 173},
+   {212*OVERSAMPLENR, 172},
+   {215*OVERSAMPLENR, 171},
+   {219*OVERSAMPLENR, 170},
+   {237*OVERSAMPLENR, 165},
+   {256*OVERSAMPLENR, 160},
+   {300*OVERSAMPLENR, 150},
+   {351*OVERSAMPLENR, 140},
+   {470*OVERSAMPLENR, 120},
+   {504*OVERSAMPLENR, 115},
+   {538*OVERSAMPLENR, 110},
+   {552*OVERSAMPLENR, 108},
+   {566*OVERSAMPLENR, 106},
+   {580*OVERSAMPLENR, 104},
+   {594*OVERSAMPLENR, 102},
+   {608*OVERSAMPLENR, 100},
+   {622*OVERSAMPLENR, 98},
+   {636*OVERSAMPLENR, 96},
+   {650*OVERSAMPLENR, 94},
+   {664*OVERSAMPLENR, 92},
+   {678*OVERSAMPLENR, 90},
+   {712*OVERSAMPLENR, 85},
+   {745*OVERSAMPLENR, 80},
+   {758*OVERSAMPLENR, 78},
+   {770*OVERSAMPLENR, 76},
+   {783*OVERSAMPLENR, 74},
+   {795*OVERSAMPLENR, 72},
+   {806*OVERSAMPLENR, 70},
+   {818*OVERSAMPLENR, 68},
+   {829*OVERSAMPLENR, 66},
+   {840*OVERSAMPLENR, 64},
+   {850*OVERSAMPLENR, 62},
+   {860*OVERSAMPLENR, 60},
+   {870*OVERSAMPLENR, 58},
+   {879*OVERSAMPLENR, 56},
+   {888*OVERSAMPLENR, 54},
+   {897*OVERSAMPLENR, 52},
+   {905*OVERSAMPLENR, 50},
+   {924*OVERSAMPLENR, 45},
+   {940*OVERSAMPLENR, 40},
+   {955*OVERSAMPLENR, 35},
+   {967*OVERSAMPLENR, 30},
+   {970*OVERSAMPLENR, 29},
+   {972*OVERSAMPLENR, 28},
+   {974*OVERSAMPLENR, 27},
+   {976*OVERSAMPLENR, 26},
+   {978*OVERSAMPLENR, 25},
+   {980*OVERSAMPLENR, 24},
+   {982*OVERSAMPLENR, 23},
+   {984*OVERSAMPLENR, 22},
+   {985*OVERSAMPLENR, 21},
+   {987*OVERSAMPLENR, 20},
+   {995*OVERSAMPLENR, 15},
+   {1001*OVERSAMPLENR, 10},
+   {1006*OVERSAMPLENR, 5},
+   {1010*OVERSAMPLENR, 0},
+};
+#endif
+
+#if (THERMISTORHEATER_0 == 8) || (THERMISTORHEATER_1 == 8) || (THERMISTORHEATER_2 == 8) || (THERMISTORBED == 8)
+// 100k 0603 SMD Vishay NTCS0603E3104FXT (4.7k pullup)
+const short temptable_8[][2] PROGMEM = {
+   {1*OVERSAMPLENR, 704},
+   {54*OVERSAMPLENR, 216},
+   {107*OVERSAMPLENR, 175},
+   {160*OVERSAMPLENR, 152},
+   {213*OVERSAMPLENR, 137},
+   {266*OVERSAMPLENR, 125},
+   {319*OVERSAMPLENR, 115},
+   {372*OVERSAMPLENR, 106},
+   {425*OVERSAMPLENR, 99},
+   {478*OVERSAMPLENR, 91},
+   {531*OVERSAMPLENR, 85},
+   {584*OVERSAMPLENR, 78},
+   {637*OVERSAMPLENR, 71},
+   {690*OVERSAMPLENR, 65},
+   {743*OVERSAMPLENR, 58},
+   {796*OVERSAMPLENR, 50},
+   {849*OVERSAMPLENR, 42},
+   {902*OVERSAMPLENR, 31},
+   {955*OVERSAMPLENR, 17},
+   {1008*OVERSAMPLENR, 0}
+};
+#endif
+#if (THERMISTORHEATER_0 == 9) || (THERMISTORHEATER_1 == 9) || (THERMISTORHEATER_2 == 9) || (THERMISTORBED == 9)
+// 100k GE Sensing AL03006-58.2K-97-G1 (4.7k pullup)
+const short temptable_9[][2] PROGMEM = {
+	{1*OVERSAMPLENR, 936},
+	{36*OVERSAMPLENR, 300},
+	{71*OVERSAMPLENR, 246},
+	{106*OVERSAMPLENR, 218},
+	{141*OVERSAMPLENR, 199},
+	{176*OVERSAMPLENR, 185},
+	{211*OVERSAMPLENR, 173},
+	{246*OVERSAMPLENR, 163},
+	{281*OVERSAMPLENR, 155},
+	{316*OVERSAMPLENR, 147},
+	{351*OVERSAMPLENR, 140},
+	{386*OVERSAMPLENR, 134},
+	{421*OVERSAMPLENR, 128},
+	{456*OVERSAMPLENR, 122},
+	{491*OVERSAMPLENR, 117},
+	{526*OVERSAMPLENR, 112},
+	{561*OVERSAMPLENR, 107},
+	{596*OVERSAMPLENR, 102},
+	{631*OVERSAMPLENR, 97},
+	{666*OVERSAMPLENR, 92},
+	{701*OVERSAMPLENR, 87},
+	{736*OVERSAMPLENR, 81},
+	{771*OVERSAMPLENR, 76},
+	{806*OVERSAMPLENR, 70},
+	{841*OVERSAMPLENR, 63},
+	{876*OVERSAMPLENR, 56},
+	{911*OVERSAMPLENR, 48},
+	{946*OVERSAMPLENR, 38},
+	{981*OVERSAMPLENR, 23},
+	{1005*OVERSAMPLENR, 5},
+	{1016*OVERSAMPLENR, 0}
+};
+#endif
+#if (THERMISTORHEATER_0 == 10) || (THERMISTORHEATER_1 == 10) || (THERMISTORHEATER_2 == 10) || (THERMISTORBED == 10)
+// 100k RS thermistor 198-961 (4.7k pullup)
+const short temptable_10[][2] PROGMEM = {
+   {1*OVERSAMPLENR, 929},
+   {36*OVERSAMPLENR, 299},
+   {71*OVERSAMPLENR, 246},
+   {106*OVERSAMPLENR, 217},
+   {141*OVERSAMPLENR, 198},
+   {176*OVERSAMPLENR, 184},
+   {211*OVERSAMPLENR, 173},
+   {246*OVERSAMPLENR, 163},
+   {281*OVERSAMPLENR, 154},
+   {316*OVERSAMPLENR, 147},
+   {351*OVERSAMPLENR, 140},
+   {386*OVERSAMPLENR, 134},
+   {421*OVERSAMPLENR, 128},
+   {456*OVERSAMPLENR, 122},
+   {491*OVERSAMPLENR, 117},
+   {526*OVERSAMPLENR, 112},
+   {561*OVERSAMPLENR, 107},
+   {596*OVERSAMPLENR, 102},
+   {631*OVERSAMPLENR, 97},
+   {666*OVERSAMPLENR, 91},
+   {701*OVERSAMPLENR, 86},
+   {736*OVERSAMPLENR, 81},
+   {771*OVERSAMPLENR, 76},
+   {806*OVERSAMPLENR, 70},
+   {841*OVERSAMPLENR, 63},
+   {876*OVERSAMPLENR, 56},
+   {911*OVERSAMPLENR, 48},
+   {946*OVERSAMPLENR, 38},
+   {981*OVERSAMPLENR, 23},
+   {1005*OVERSAMPLENR, 5},
+   {1016*OVERSAMPLENR, 0}
+};
+#endif
+
+#if (THERMISTORHEATER_0 == 20) || (THERMISTORHEATER_1 == 20) || (THERMISTORHEATER_2 == 20) || (THERMISTORBED == 20) // PT100 with INA826 amp on Ultimaker v2.0 electronics
+/* The PT100 in the Ultimaker v2.0 electronics has a high sample value for a high temperature.
+This does not match the normal thermistor behaviour so we need to set the following defines */
+#if (THERMISTORHEATER_0 == 20)
+# define HEATER_0_RAW_HI_TEMP 16383
+# define HEATER_0_RAW_LO_TEMP 0
+#endif
+#if (THERMISTORHEATER_1 == 20)
+# define HEATER_1_RAW_HI_TEMP 16383
+# define HEATER_1_RAW_LO_TEMP 0
+#endif
+#if (THERMISTORHEATER_2 == 20)
+# define HEATER_2_RAW_HI_TEMP 16383
+# define HEATER_2_RAW_LO_TEMP 0
+#endif
+#if (THERMISTORBED == 20)
+# define HEATER_BED_RAW_HI_TEMP 16383
+# define HEATER_BED_RAW_LO_TEMP 0
+#endif
+const short temptable_20[][2] PROGMEM = {
+{         0*OVERSAMPLENR ,       0     },
+{       227*OVERSAMPLENR ,       1     },
+{       236*OVERSAMPLENR ,       10     },
+{       245*OVERSAMPLENR ,       20     },
+{       253*OVERSAMPLENR ,       30     },
+{       262*OVERSAMPLENR ,       40     },
+{       270*OVERSAMPLENR ,       50     },
+{       279*OVERSAMPLENR ,       60     },
+{       287*OVERSAMPLENR ,       70     },
+{       295*OVERSAMPLENR ,       80     },
+{       304*OVERSAMPLENR ,       90     },
+{       312*OVERSAMPLENR ,       100     },
+{       320*OVERSAMPLENR ,       110     },
+{       329*OVERSAMPLENR ,       120     },
+{       337*OVERSAMPLENR ,       130     },
+{       345*OVERSAMPLENR ,       140     },
+{       353*OVERSAMPLENR ,       150     },
+{       361*OVERSAMPLENR ,       160     },
+{       369*OVERSAMPLENR ,       170     },
+{       377*OVERSAMPLENR ,       180     },
+{       385*OVERSAMPLENR ,       190     },
+{       393*OVERSAMPLENR ,       200     },
+{       401*OVERSAMPLENR ,       210     },
+{       409*OVERSAMPLENR ,       220     },
+{       417*OVERSAMPLENR ,       230     },
+{       424*OVERSAMPLENR ,       240     },
+{       432*OVERSAMPLENR ,       250     },
+{       440*OVERSAMPLENR ,       260     },
+{       447*OVERSAMPLENR ,       270     },
+{       455*OVERSAMPLENR ,       280     },
+{       463*OVERSAMPLENR ,       290     },
+{       470*OVERSAMPLENR ,       300     },
+{       478*OVERSAMPLENR ,       310     },
+{       485*OVERSAMPLENR ,       320     },
+{       493*OVERSAMPLENR ,       330     },
+{       500*OVERSAMPLENR ,       340     },
+{       507*OVERSAMPLENR ,       350     },
+{       515*OVERSAMPLENR ,       360     },
+{       522*OVERSAMPLENR ,       370     },
+{       529*OVERSAMPLENR ,       380     },
+{       537*OVERSAMPLENR ,       390     },
+{       544*OVERSAMPLENR ,       400     },
+{       614*OVERSAMPLENR ,       500     },
+{       681*OVERSAMPLENR ,       600     },
+{       744*OVERSAMPLENR ,       700     },
+{       805*OVERSAMPLENR ,       800     },
+{       862*OVERSAMPLENR ,       900     },
+{       917*OVERSAMPLENR ,       1000     },
+{       968*OVERSAMPLENR ,       1100     }
+};
+#endif
+
+#if (THERMISTORHEATER_0 == 51) || (THERMISTORHEATER_1 == 51) || (THERMISTORHEATER_2 == 51) || (THERMISTORBED == 51)
+// 100k EPCOS (WITH 1kohm RESISTOR FOR PULLUP, R9 ON SANGUINOLOLU! NOT FOR 4.7kohm PULLUP! THIS IS NOT NORMAL!)
+// Verified by linagee.
+// Calculated using 1kohm pullup, voltage divider math, and manufacturer provided temp/resistance
+// Advantage: Twice the resolution and better linearity from 150C to 200C
+const short temptable_51[][2] PROGMEM = {
+   {1*OVERSAMPLENR, 350},
+   {190*OVERSAMPLENR, 250}, //top rating 250C
+   {203*OVERSAMPLENR, 245},
+   {217*OVERSAMPLENR, 240},
+   {232*OVERSAMPLENR, 235},
+   {248*OVERSAMPLENR, 230},
+   {265*OVERSAMPLENR, 225},
+   {283*OVERSAMPLENR, 220},
+   {302*OVERSAMPLENR, 215},
+   {322*OVERSAMPLENR, 210},
+   {344*OVERSAMPLENR, 205},
+   {366*OVERSAMPLENR, 200},
+   {390*OVERSAMPLENR, 195},
+   {415*OVERSAMPLENR, 190},
+   {440*OVERSAMPLENR, 185},
+   {467*OVERSAMPLENR, 180},
+   {494*OVERSAMPLENR, 175},
+   {522*OVERSAMPLENR, 170},
+   {551*OVERSAMPLENR, 165},
+   {580*OVERSAMPLENR, 160},
+   {609*OVERSAMPLENR, 155},
+   {638*OVERSAMPLENR, 150},
+   {666*OVERSAMPLENR, 145},
+   {695*OVERSAMPLENR, 140},
+   {722*OVERSAMPLENR, 135},
+   {749*OVERSAMPLENR, 130},
+   {775*OVERSAMPLENR, 125},
+   {800*OVERSAMPLENR, 120},
+   {823*OVERSAMPLENR, 115},
+   {845*OVERSAMPLENR, 110},
+   {865*OVERSAMPLENR, 105},
+   {884*OVERSAMPLENR, 100},
+   {901*OVERSAMPLENR, 95},
+   {917*OVERSAMPLENR, 90},
+   {932*OVERSAMPLENR, 85},
+   {944*OVERSAMPLENR, 80},
+   {956*OVERSAMPLENR, 75},
+   {966*OVERSAMPLENR, 70},
+   {975*OVERSAMPLENR, 65},
+   {982*OVERSAMPLENR, 60},
+   {989*OVERSAMPLENR, 55},
+   {995*OVERSAMPLENR, 50},
+   {1000*OVERSAMPLENR, 45},
+   {1004*OVERSAMPLENR, 40},
+   {1007*OVERSAMPLENR, 35},
+   {1010*OVERSAMPLENR, 30},
+   {1013*OVERSAMPLENR, 25},
+   {1015*OVERSAMPLENR, 20},
+   {1017*OVERSAMPLENR, 15},
+   {1018*OVERSAMPLENR, 10},
+   {1019*OVERSAMPLENR, 5},
+   {1020*OVERSAMPLENR, 0},
+   {1021*OVERSAMPLENR, -5}
+};
+#endif
+
+#if (THERMISTORHEATER_0 == 52) || (THERMISTORHEATER_1 == 52) || (THERMISTORHEATER_2 == 52) || (THERMISTORBED == 52) 
+// 200k ATC Semitec 204GT-2 (WITH 1kohm RESISTOR FOR PULLUP, R9 ON SANGUINOLOLU! NOT FOR 4.7kohm PULLUP! THIS IS NOT NORMAL!)
+// Verified by linagee. Source: http://shop.arcol.hu/static/datasheets/thermistors.pdf
+// Calculated using 1kohm pullup, voltage divider math, and manufacturer provided temp/resistance
+// Advantage: More resolution and better linearity from 150C to 200C
+const short temptable_52[][2] PROGMEM = {
+   {1*OVERSAMPLENR, 500},
+   {125*OVERSAMPLENR, 300}, //top rating 300C
+   {142*OVERSAMPLENR, 290},
+   {162*OVERSAMPLENR, 280},
+   {185*OVERSAMPLENR, 270},
+   {211*OVERSAMPLENR, 260},
+   {240*OVERSAMPLENR, 250},
+   {274*OVERSAMPLENR, 240},
+   {312*OVERSAMPLENR, 230},
+   {355*OVERSAMPLENR, 220},
+   {401*OVERSAMPLENR, 210},
+   {452*OVERSAMPLENR, 200},
+   {506*OVERSAMPLENR, 190},
+   {563*OVERSAMPLENR, 180},
+   {620*OVERSAMPLENR, 170},
+   {677*OVERSAMPLENR, 160},
+   {732*OVERSAMPLENR, 150},
+   {783*OVERSAMPLENR, 140},
+   {830*OVERSAMPLENR, 130},
+   {871*OVERSAMPLENR, 120},
+   {906*OVERSAMPLENR, 110},
+   {935*OVERSAMPLENR, 100},
+   {958*OVERSAMPLENR, 90},
+   {976*OVERSAMPLENR, 80},
+   {990*OVERSAMPLENR, 70},
+   {1000*OVERSAMPLENR, 60},
+   {1008*OVERSAMPLENR, 50},
+   {1013*OVERSAMPLENR, 40},
+   {1017*OVERSAMPLENR, 30},
+   {1019*OVERSAMPLENR, 20},
+   {1021*OVERSAMPLENR, 10},
+   {1022*OVERSAMPLENR, 0}
+};
+#endif
+
+#if (THERMISTORHEATER_0 == 55) || (THERMISTORHEATER_1 == 55) || (THERMISTORHEATER_2 == 55) || (THERMISTORBED == 55) 
+// 100k ATC Semitec 104GT-2 (Used on ParCan) (WITH 1kohm RESISTOR FOR PULLUP, R9 ON SANGUINOLOLU! NOT FOR 4.7kohm PULLUP! THIS IS NOT NORMAL!)
+// Verified by linagee. Source: http://shop.arcol.hu/static/datasheets/thermistors.pdf
+// Calculated using 1kohm pullup, voltage divider math, and manufacturer provided temp/resistance
+// Advantage: More resolution and better linearity from 150C to 200C
+const short temptable_55[][2] PROGMEM = {
+   {1*OVERSAMPLENR, 500},
+   {76*OVERSAMPLENR, 300},
+   {87*OVERSAMPLENR, 290},
+   {100*OVERSAMPLENR, 280},
+   {114*OVERSAMPLENR, 270},
+   {131*OVERSAMPLENR, 260},
+   {152*OVERSAMPLENR, 250},
+   {175*OVERSAMPLENR, 240},
+   {202*OVERSAMPLENR, 230},
+   {234*OVERSAMPLENR, 220},
+   {271*OVERSAMPLENR, 210},
+   {312*OVERSAMPLENR, 200},
+   {359*OVERSAMPLENR, 190},
+   {411*OVERSAMPLENR, 180},
+   {467*OVERSAMPLENR, 170},
+   {527*OVERSAMPLENR, 160},
+   {590*OVERSAMPLENR, 150},
+   {652*OVERSAMPLENR, 140},
+   {713*OVERSAMPLENR, 130},
+   {770*OVERSAMPLENR, 120},
+   {822*OVERSAMPLENR, 110},
+   {867*OVERSAMPLENR, 100},
+   {905*OVERSAMPLENR, 90},
+   {936*OVERSAMPLENR, 80},
+   {961*OVERSAMPLENR, 70},
+   {979*OVERSAMPLENR, 60},
+   {993*OVERSAMPLENR, 50},
+   {1003*OVERSAMPLENR, 40},
+   {1010*OVERSAMPLENR, 30},
+   {1015*OVERSAMPLENR, 20},
+   {1018*OVERSAMPLENR, 10},
+   {1020*OVERSAMPLENR, 0}
+};
+#endif
+
+#if (THERMISTORHEATER_0 == 60) || (THERMISTORHEATER_1 == 60) || (THERMISTORHEATER_2 == 60) || (THERMISTORBED == 60) // Maker's Tool Works Kapton Bed Thermister
+const short temptable_60[][2] PROGMEM = {
+   {51*OVERSAMPLENR, 272},
+   {61*OVERSAMPLENR, 258},
+   {71*OVERSAMPLENR, 247},
+   {81*OVERSAMPLENR, 237},
+   {91*OVERSAMPLENR, 229},
+   {101*OVERSAMPLENR, 221},
+   {131*OVERSAMPLENR, 204},
+   {161*OVERSAMPLENR, 190},
+   {191*OVERSAMPLENR, 179},
+   {231*OVERSAMPLENR, 167},
+   {271*OVERSAMPLENR, 157},
+   {311*OVERSAMPLENR, 148},
+   {351*OVERSAMPLENR, 140},
+   {381*OVERSAMPLENR, 135},
+   {411*OVERSAMPLENR, 130},
+   {441*OVERSAMPLENR, 125},
+   {451*OVERSAMPLENR, 123},
+   {461*OVERSAMPLENR, 122},
+   {471*OVERSAMPLENR, 120},
+   {481*OVERSAMPLENR, 119},
+   {491*OVERSAMPLENR, 117},
+   {501*OVERSAMPLENR, 116},
+   {511*OVERSAMPLENR, 114},
+   {521*OVERSAMPLENR, 113},
+   {531*OVERSAMPLENR, 111},
+   {541*OVERSAMPLENR, 110},
+   {551*OVERSAMPLENR, 108},
+   {561*OVERSAMPLENR, 107},
+   {571*OVERSAMPLENR, 105},
+   {581*OVERSAMPLENR, 104},
+   {591*OVERSAMPLENR, 102},
+   {601*OVERSAMPLENR, 101},
+   {611*OVERSAMPLENR, 100},
+   {621*OVERSAMPLENR, 98},
+   {631*OVERSAMPLENR, 97},
+   {641*OVERSAMPLENR, 95},
+   {651*OVERSAMPLENR, 94},
+   {661*OVERSAMPLENR, 92},
+   {671*OVERSAMPLENR, 91},
+   {681*OVERSAMPLENR, 90},
+   {691*OVERSAMPLENR, 88},
+   {701*OVERSAMPLENR, 87},
+   {711*OVERSAMPLENR, 85},
+   {721*OVERSAMPLENR, 84},
+   {731*OVERSAMPLENR, 82},
+   {741*OVERSAMPLENR, 81},
+   {751*OVERSAMPLENR, 79},
+   {761*OVERSAMPLENR, 77},
+   {771*OVERSAMPLENR, 76},
+   {781*OVERSAMPLENR, 74},
+   {791*OVERSAMPLENR, 72},
+   {801*OVERSAMPLENR, 71},
+   {811*OVERSAMPLENR, 69},
+   {821*OVERSAMPLENR, 67},
+   {831*OVERSAMPLENR, 65},
+   {841*OVERSAMPLENR, 63},
+   {851*OVERSAMPLENR, 62},
+   {861*OVERSAMPLENR, 60},
+   {871*OVERSAMPLENR, 57},
+   {881*OVERSAMPLENR, 55},
+   {891*OVERSAMPLENR, 53},
+   {901*OVERSAMPLENR, 51},
+   {911*OVERSAMPLENR, 48},
+   {921*OVERSAMPLENR, 45},
+   {931*OVERSAMPLENR, 42},
+   {941*OVERSAMPLENR, 39},
+   {951*OVERSAMPLENR, 36},
+   {961*OVERSAMPLENR, 32},
+   {981*OVERSAMPLENR, 23},
+   {991*OVERSAMPLENR, 17},
+   {1001*OVERSAMPLENR, 9},
+   {1008*OVERSAMPLENR, 0},
+};
+#endif
+
+
+#define _TT_NAME(_N) temptable_ ## _N
+#define TT_NAME(_N) _TT_NAME(_N)
+
+#ifdef THERMISTORHEATER_0
+# define HEATER_0_TEMPTABLE TT_NAME(THERMISTORHEATER_0)
+# define HEATER_0_TEMPTABLE_LEN (sizeof(HEATER_0_TEMPTABLE)/sizeof(*HEATER_0_TEMPTABLE))
+#else
+# ifdef HEATER_0_USES_THERMISTOR
+#  error No heater 0 thermistor table specified
+# else  // HEATER_0_USES_THERMISTOR
+#  define HEATER_0_TEMPTABLE NULL
+#  define HEATER_0_TEMPTABLE_LEN 0
+# endif // HEATER_0_USES_THERMISTOR
+#endif
+
+//Set the high and low raw values for the heater, this indicates which raw value is a high or low temperature
+#ifndef HEATER_0_RAW_HI_TEMP
+# ifdef HEATER_0_USES_THERMISTOR   //In case of a thermistor the highest temperature results in the lowest ADC value
+#  define HEATER_0_RAW_HI_TEMP 0
+#  define HEATER_0_RAW_LO_TEMP 16383
+# else                          //In case of an thermocouple the highest temperature results in the highest ADC value
+#  define HEATER_0_RAW_HI_TEMP 16383
+#  define HEATER_0_RAW_LO_TEMP 0
+# endif
+#endif
+
+#ifdef THERMISTORHEATER_1
+# define HEATER_1_TEMPTABLE TT_NAME(THERMISTORHEATER_1)
+# define HEATER_1_TEMPTABLE_LEN (sizeof(HEATER_1_TEMPTABLE)/sizeof(*HEATER_1_TEMPTABLE))
+#else
+# ifdef HEATER_1_USES_THERMISTOR
+#  error No heater 1 thermistor table specified
+# else  // HEATER_1_USES_THERMISTOR
+#  define HEATER_1_TEMPTABLE NULL
+#  define HEATER_1_TEMPTABLE_LEN 0
+# endif // HEATER_1_USES_THERMISTOR
+#endif
+
+//Set the high and low raw values for the heater, this indicates which raw value is a high or low temperature
+#ifndef HEATER_1_RAW_HI_TEMP
+# ifdef HEATER_1_USES_THERMISTOR   //In case of a thermistor the highest temperature results in the lowest ADC value
+#  define HEATER_1_RAW_HI_TEMP 0
+#  define HEATER_1_RAW_LO_TEMP 16383
+# else                          //In case of an thermocouple the highest temperature results in the highest ADC value
+#  define HEATER_1_RAW_HI_TEMP 16383
+#  define HEATER_1_RAW_LO_TEMP 0
+# endif
+#endif
+
+#ifdef THERMISTORHEATER_2
+# define HEATER_2_TEMPTABLE TT_NAME(THERMISTORHEATER_2)
+# define HEATER_2_TEMPTABLE_LEN (sizeof(HEATER_2_TEMPTABLE)/sizeof(*HEATER_2_TEMPTABLE))
+#else
+# ifdef HEATER_2_USES_THERMISTOR
+#  error No heater 2 thermistor table specified
+# else  // HEATER_2_USES_THERMISTOR
+#  define HEATER_2_TEMPTABLE NULL
+#  define HEATER_2_TEMPTABLE_LEN 0
+# endif // HEATER_2_USES_THERMISTOR
+#endif
+
+//Set the high and low raw values for the heater, this indicates which raw value is a high or low temperature
+#ifndef HEATER_2_RAW_HI_TEMP
+# ifdef HEATER_2_USES_THERMISTOR   //In case of a thermistor the highest temperature results in the lowest ADC value
+#  define HEATER_2_RAW_HI_TEMP 0
+#  define HEATER_2_RAW_LO_TEMP 16383
+# else                          //In case of an thermocouple the highest temperature results in the highest ADC value
+#  define HEATER_2_RAW_HI_TEMP 16383
+#  define HEATER_2_RAW_LO_TEMP 0
+# endif
+#endif
+
+#ifdef THERMISTORBED
+# define BEDTEMPTABLE TT_NAME(THERMISTORBED)
+# define BEDTEMPTABLE_LEN (sizeof(BEDTEMPTABLE)/sizeof(*BEDTEMPTABLE))
+#else
+# ifdef BED_USES_THERMISTOR
+#  error No bed thermistor table specified
+# endif // BED_USES_THERMISTOR
+#endif
+
+//Set the high and low raw values for the heater, this indicates which raw value is a high or low temperature
+#ifndef HEATER_BED_RAW_HI_TEMP
+# ifdef BED_USES_THERMISTOR   //In case of a thermistor the highest temperature results in the lowest ADC value
+#  define HEATER_BED_RAW_HI_TEMP 0
+#  define HEATER_BED_RAW_LO_TEMP 16383
+# else                          //In case of an thermocouple the highest temperature results in the highest ADC value
+#  define HEATER_BED_RAW_HI_TEMP 16383
+#  define HEATER_BED_RAW_LO_TEMP 0
+# endif
+#endif
+
+#endif //THERMISTORTABLES_H_

File diff suppressed because it is too large
+ 1596 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/ultralcd.cpp


+ 114 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/ultralcd.h

@@ -0,0 +1,114 @@
+#ifndef ULTRALCD_H
+#define ULTRALCD_H
+
+#include "Marlin.h"
+
+#ifdef ULTRA_LCD
+
+  void lcd_update();
+  void lcd_init();
+  void lcd_setstatus(const char* message);
+  void lcd_setstatuspgm(const char* message);
+  void lcd_setalertstatuspgm(const char* message);
+  void lcd_reset_alert_level();
+
+#ifdef DOGLCD
+  extern int lcd_contrast;
+  void lcd_setcontrast(uint8_t value);
+#endif
+
+  static unsigned char blink = 0;	// Variable for visualisation of fan rotation in GLCD
+
+  #define LCD_MESSAGEPGM(x) lcd_setstatuspgm(PSTR(x))
+  #define LCD_ALERTMESSAGEPGM(x) lcd_setalertstatuspgm(PSTR(x))
+
+  #define LCD_UPDATE_INTERVAL 100
+  #define LCD_TIMEOUT_TO_STATUS 15000
+
+  #ifdef ULTIPANEL
+  void lcd_buttons_update();
+  extern volatile uint8_t buttons;  //the last checked buttons in a bit array.
+  #ifdef REPRAPWORLD_KEYPAD
+    extern volatile uint8_t buttons_reprapworld_keypad; // to store the keypad shiftregister values
+  #endif
+  #else
+  FORCE_INLINE void lcd_buttons_update() {}
+  #endif
+
+  extern int plaPreheatHotendTemp;
+  extern int plaPreheatHPBTemp;
+  extern int plaPreheatFanSpeed;
+
+  extern int absPreheatHotendTemp;
+  extern int absPreheatHPBTemp;
+  extern int absPreheatFanSpeed;
+    
+  void lcd_buzz(long duration,uint16_t freq);
+  bool lcd_clicked();
+
+  #ifdef NEWPANEL
+    #define EN_C (1<<BLEN_C)
+    #define EN_B (1<<BLEN_B)
+    #define EN_A (1<<BLEN_A)
+
+    #define LCD_CLICKED (buttons&EN_C)
+    #ifdef REPRAPWORLD_KEYPAD
+  	  #define EN_REPRAPWORLD_KEYPAD_F3 (1<<BLEN_REPRAPWORLD_KEYPAD_F3)
+  	  #define EN_REPRAPWORLD_KEYPAD_F2 (1<<BLEN_REPRAPWORLD_KEYPAD_F2)
+  	  #define EN_REPRAPWORLD_KEYPAD_F1 (1<<BLEN_REPRAPWORLD_KEYPAD_F1)
+  	  #define EN_REPRAPWORLD_KEYPAD_UP (1<<BLEN_REPRAPWORLD_KEYPAD_UP)
+  	  #define EN_REPRAPWORLD_KEYPAD_RIGHT (1<<BLEN_REPRAPWORLD_KEYPAD_RIGHT)
+  	  #define EN_REPRAPWORLD_KEYPAD_MIDDLE (1<<BLEN_REPRAPWORLD_KEYPAD_MIDDLE)
+  	  #define EN_REPRAPWORLD_KEYPAD_DOWN (1<<BLEN_REPRAPWORLD_KEYPAD_DOWN)
+  	  #define EN_REPRAPWORLD_KEYPAD_LEFT (1<<BLEN_REPRAPWORLD_KEYPAD_LEFT)
+
+  	  #define LCD_CLICKED ((buttons&EN_C) || (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_F1))
+  	  #define REPRAPWORLD_KEYPAD_MOVE_Z_UP (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_F2)
+  	  #define REPRAPWORLD_KEYPAD_MOVE_Z_DOWN (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_F3)
+  	  #define REPRAPWORLD_KEYPAD_MOVE_X_LEFT (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_LEFT)
+  	  #define REPRAPWORLD_KEYPAD_MOVE_X_RIGHT (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_RIGHT)
+  	  #define REPRAPWORLD_KEYPAD_MOVE_Y_DOWN (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_DOWN)
+  	  #define REPRAPWORLD_KEYPAD_MOVE_Y_UP (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_UP)
+  	  #define REPRAPWORLD_KEYPAD_MOVE_HOME (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_MIDDLE)
+    #endif //REPRAPWORLD_KEYPAD
+  #else
+    //atomatic, do not change
+    #define B_LE (1<<BL_LE)
+    #define B_UP (1<<BL_UP)
+    #define B_MI (1<<BL_MI)
+    #define B_DW (1<<BL_DW)
+    #define B_RI (1<<BL_RI)
+    #define B_ST (1<<BL_ST)
+    #define EN_B (1<<BLEN_B)
+    #define EN_A (1<<BLEN_A)
+    
+    #define LCD_CLICKED ((buttons&B_MI)||(buttons&B_ST))
+  #endif//NEWPANEL
+
+#else //no lcd
+  FORCE_INLINE void lcd_update() {}
+  FORCE_INLINE void lcd_init() {}
+  FORCE_INLINE void lcd_setstatus(const char* message) {}
+  FORCE_INLINE void lcd_buttons_update() {}
+  FORCE_INLINE void lcd_reset_alert_level() {}
+  FORCE_INLINE void lcd_buzz(long duration,uint16_t freq) {}
+
+  #define LCD_MESSAGEPGM(x) 
+  #define LCD_ALERTMESSAGEPGM(x) 
+#endif 
+
+char *itostr2(const uint8_t &x);
+char *itostr31(const int &xx);
+char *itostr3(const int &xx);
+char *itostr3left(const int &xx);
+char *itostr4(const int &xx);
+
+char *ftostr3(const float &x);
+char *ftostr31ns(const float &x); // float to string without sign character
+char *ftostr31(const float &x);
+char *ftostr32(const float &x);
+char *ftostr5(const float &x);
+char *ftostr51(const float &x);
+char *ftostr52(const float &x);
+
+#endif //ULTRALCD

+ 774 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/ultralcd_implementation_hitachi_HD44780.h

@@ -0,0 +1,774 @@
+#ifndef ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H
+#define ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H
+
+/**
+* Implementation of the LCD display routines for a hitachi HD44780 display. These are common LCD character displays.
+* When selecting the rusian language, a slightly different LCD implementation is used to handle UTF8 characters.
+**/
+
+#ifndef REPRAPWORLD_KEYPAD
+extern volatile uint8_t buttons;  //the last checked buttons in a bit array.
+#else
+extern volatile uint16_t buttons;  //an extended version of the last checked buttons in a bit array.
+#endif
+
+////////////////////////////////////
+// Setup button and encode mappings for each panel (into 'buttons' variable
+//
+// This is just to map common functions (across different panels) onto the same 
+// macro name. The mapping is independent of whether the button is directly connected or 
+// via a shift/i2c register.
+
+#ifdef ULTIPANEL
+// All Ultipanels might have an encoder - so this is always be mapped onto first two bits
+#define BLEN_B 1
+#define BLEN_A 0
+
+#define EN_B (1<<BLEN_B) // The two encoder pins are connected through BTN_EN1 and BTN_EN2
+#define EN_A (1<<BLEN_A)
+
+#if defined(BTN_ENC) && BTN_ENC > -1
+  // encoder click is directly connected
+  #define BLEN_C 2 
+  #define EN_C (1<<BLEN_C) 
+#endif 
+  
+//
+// Setup other button mappings of each panel
+//
+#if defined(LCD_I2C_VIKI)
+  #define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C)
+  
+  // button and encoder bit positions within 'buttons'
+  #define B_LE (BUTTON_LEFT<<B_I2C_BTN_OFFSET)    // The remaining normalized buttons are all read via I2C
+  #define B_UP (BUTTON_UP<<B_I2C_BTN_OFFSET)
+  #define B_MI (BUTTON_SELECT<<B_I2C_BTN_OFFSET)
+  #define B_DW (BUTTON_DOWN<<B_I2C_BTN_OFFSET)
+  #define B_RI (BUTTON_RIGHT<<B_I2C_BTN_OFFSET)
+
+  #if defined(BTN_ENC) && BTN_ENC > -1 
+    // the pause/stop/restart button is connected to BTN_ENC when used
+    #define B_ST (EN_C)                            // Map the pause/stop/resume button into its normalized functional name 
+    #define LCD_CLICKED (buttons&(B_MI|B_RI|B_ST)) // pause/stop button also acts as click until we implement proper pause/stop.
+  #else
+    #define LCD_CLICKED (buttons&(B_MI|B_RI))
+  #endif  
+
+  // I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update
+  #define LCD_HAS_SLOW_BUTTONS
+
+#elif defined(LCD_I2C_PANELOLU2)
+  // encoder click can be read through I2C if not directly connected
+  #if BTN_ENC <= 0 
+    #define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C)
+  
+    #define B_MI (PANELOLU2_ENCODER_C<<B_I2C_BTN_OFFSET) // requires LiquidTWI2 library v1.2.3 or later
+
+    #define LCD_CLICKED (buttons&B_MI)
+
+    // I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update
+    #define LCD_HAS_SLOW_BUTTONS
+  #else
+    #define LCD_CLICKED (buttons&EN_C)  
+  #endif
+
+#elif defined(REPRAPWORLD_KEYPAD)
+    // define register bit values, don't change it
+    #define BLEN_REPRAPWORLD_KEYPAD_F3 0
+    #define BLEN_REPRAPWORLD_KEYPAD_F2 1
+    #define BLEN_REPRAPWORLD_KEYPAD_F1 2
+    #define BLEN_REPRAPWORLD_KEYPAD_UP 3
+    #define BLEN_REPRAPWORLD_KEYPAD_RIGHT 4
+    #define BLEN_REPRAPWORLD_KEYPAD_MIDDLE 5
+    #define BLEN_REPRAPWORLD_KEYPAD_DOWN 6
+    #define BLEN_REPRAPWORLD_KEYPAD_LEFT 7
+    
+    #define REPRAPWORLD_BTN_OFFSET 3 // bit offset into buttons for shift register values
+
+    #define EN_REPRAPWORLD_KEYPAD_F3 (1<<(BLEN_REPRAPWORLD_KEYPAD_F3+REPRAPWORLD_BTN_OFFSET))
+    #define EN_REPRAPWORLD_KEYPAD_F2 (1<<(BLEN_REPRAPWORLD_KEYPAD_F2+REPRAPWORLD_BTN_OFFSET))
+    #define EN_REPRAPWORLD_KEYPAD_F1 (1<<(BLEN_REPRAPWORLD_KEYPAD_F1+REPRAPWORLD_BTN_OFFSET))
+    #define EN_REPRAPWORLD_KEYPAD_UP (1<<(BLEN_REPRAPWORLD_KEYPAD_UP+REPRAPWORLD_BTN_OFFSET))
+    #define EN_REPRAPWORLD_KEYPAD_RIGHT (1<<(BLEN_REPRAPWORLD_KEYPAD_RIGHT+REPRAPWORLD_BTN_OFFSET))
+    #define EN_REPRAPWORLD_KEYPAD_MIDDLE (1<<(BLEN_REPRAPWORLD_KEYPAD_MIDDLE+REPRAPWORLD_BTN_OFFSET))
+    #define EN_REPRAPWORLD_KEYPAD_DOWN (1<<(BLEN_REPRAPWORLD_KEYPAD_DOWN+REPRAPWORLD_BTN_OFFSET))
+    #define EN_REPRAPWORLD_KEYPAD_LEFT (1<<(BLEN_REPRAPWORLD_KEYPAD_LEFT+REPRAPWORLD_BTN_OFFSET))
+
+    #define LCD_CLICKED ((buttons&EN_C) || (buttons&EN_REPRAPWORLD_KEYPAD_F1))
+    #define REPRAPWORLD_KEYPAD_MOVE_Y_DOWN (buttons&EN_REPRAPWORLD_KEYPAD_DOWN)
+    #define REPRAPWORLD_KEYPAD_MOVE_Y_UP (buttons&EN_REPRAPWORLD_KEYPAD_UP)
+    #define REPRAPWORLD_KEYPAD_MOVE_HOME (buttons&EN_REPRAPWORLD_KEYPAD_MIDDLE)
+
+#elif defined(NEWPANEL)
+  #define LCD_CLICKED (buttons&EN_C)
+  
+#else // old style ULTIPANEL
+  //bits in the shift register that carry the buttons for:
+  // left up center down right red(stop)
+  #define BL_LE 7
+  #define BL_UP 6
+  #define BL_MI 5
+  #define BL_DW 4
+  #define BL_RI 3
+  #define BL_ST 2
+
+  //automatic, do not change
+  #define B_LE (1<<BL_LE)
+  #define B_UP (1<<BL_UP)
+  #define B_MI (1<<BL_MI)
+  #define B_DW (1<<BL_DW)
+  #define B_RI (1<<BL_RI)
+  #define B_ST (1<<BL_ST)
+  
+  #define LCD_CLICKED (buttons&(B_MI|B_ST))
+#endif
+
+////////////////////////
+// Setup Rotary Encoder Bit Values (for two pin encoders to indicate movement)
+// These values are independent of which pins are used for EN_A and EN_B indications
+// The rotary encoder part is also independent to the chipset used for the LCD
+#if defined(EN_A) && defined(EN_B)
+    #define encrot0 0
+    #define encrot1 2
+    #define encrot2 3
+    #define encrot3 1
+#endif 
+
+#endif //ULTIPANEL
+
+////////////////////////////////////
+// Create LCD class instance and chipset-specific information
+#if defined(LCD_I2C_TYPE_PCF8575)
+  // note: these are register mapped pins on the PCF8575 controller not Arduino pins
+  #define LCD_I2C_PIN_BL  3
+  #define LCD_I2C_PIN_EN  2
+  #define LCD_I2C_PIN_RW  1
+  #define LCD_I2C_PIN_RS  0
+  #define LCD_I2C_PIN_D4  4
+  #define LCD_I2C_PIN_D5  5
+  #define LCD_I2C_PIN_D6  6
+  #define LCD_I2C_PIN_D7  7
+
+  #include <Wire.h>
+  #include <LCD.h>
+  #include <LiquidCrystal_I2C.h>
+  #define LCD_CLASS LiquidCrystal_I2C
+  LCD_CLASS lcd(LCD_I2C_ADDRESS,LCD_I2C_PIN_EN,LCD_I2C_PIN_RW,LCD_I2C_PIN_RS,LCD_I2C_PIN_D4,LCD_I2C_PIN_D5,LCD_I2C_PIN_D6,LCD_I2C_PIN_D7);
+  
+#elif defined(LCD_I2C_TYPE_MCP23017)
+  //for the LED indicators (which maybe mapped to different things in lcd_implementation_update_indicators())
+  #define LED_A 0x04 //100
+  #define LED_B 0x02 //010
+  #define LED_C 0x01 //001
+
+  #define LCD_HAS_STATUS_INDICATORS
+
+  #include <Wire.h>
+  #include <LiquidTWI2.h>
+  #define LCD_CLASS LiquidTWI2
+  LCD_CLASS lcd(LCD_I2C_ADDRESS);
+  
+#elif defined(LCD_I2C_TYPE_MCP23008)
+  #include <Wire.h>
+  #include <LiquidTWI2.h>
+  #define LCD_CLASS LiquidTWI2
+  LCD_CLASS lcd(LCD_I2C_ADDRESS);  
+
+#elif defined(LCD_I2C_TYPE_PCA8574)
+    #include <LiquidCrystal_I2C.h>
+    #define LCD_CLASS LiquidCrystal_I2C
+    LCD_CLASS lcd(LCD_I2C_ADDRESS, LCD_WIDTH, LCD_HEIGHT);
+    
+// 2 wire Non-latching LCD SR from:
+// https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/schematics#!shiftregister-connection 
+#elif defined(SR_LCD_2W_NL)
+   
+  #include <LCD.h>
+  #include <LiquidCrystal_SR.h>
+  #define LCD_CLASS LiquidCrystal_SR
+  LCD_CLASS lcd(SR_DATA_PIN, SR_CLK_PIN);
+
+#else
+  // Standard directly connected LCD implementations
+  #if LANGUAGE_CHOICE == 6
+    #include "LiquidCrystalRus.h"
+    #define LCD_CLASS LiquidCrystalRus
+  #else 
+    #include <LiquidCrystal.h>
+    #define LCD_CLASS LiquidCrystal
+  #endif  
+  LCD_CLASS lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5,LCD_PINS_D6,LCD_PINS_D7);  //RS,Enable,D4,D5,D6,D7
+#endif
+
+/* Custom characters defined in the first 8 characters of the LCD */
+#define LCD_STR_BEDTEMP     "\x00"
+#define LCD_STR_DEGREE      "\x01"
+#define LCD_STR_THERMOMETER "\x02"
+#define LCD_STR_UPLEVEL     "\x03"
+#define LCD_STR_REFRESH     "\x04"
+#define LCD_STR_FOLDER      "\x05"
+#define LCD_STR_FEEDRATE    "\x06"
+#define LCD_STR_CLOCK       "\x07"
+#define LCD_STR_ARROW_RIGHT "\x7E"  /* from the default character set */
+
+static void lcd_implementation_init()
+{
+    byte bedTemp[8] =
+    {
+        B00000,
+        B11111,
+        B10101,
+        B10001,
+        B10101,
+        B11111,
+        B00000,
+        B00000
+    }; //thanks Sonny Mounicou
+    byte degree[8] =
+    {
+        B01100,
+        B10010,
+        B10010,
+        B01100,
+        B00000,
+        B00000,
+        B00000,
+        B00000
+    };
+    byte thermometer[8] =
+    {
+        B00100,
+        B01010,
+        B01010,
+        B01010,
+        B01010,
+        B10001,
+        B10001,
+        B01110
+    };
+    byte uplevel[8]={
+        B00100,
+        B01110,
+        B11111,
+        B00100,
+        B11100,
+        B00000,
+        B00000,
+        B00000
+    }; //thanks joris
+    byte refresh[8]={
+        B00000,
+        B00110,
+        B11001,
+        B11000,
+        B00011,
+        B10011,
+        B01100,
+        B00000,
+    }; //thanks joris
+    byte folder [8]={
+        B00000,
+        B11100,
+        B11111,
+        B10001,
+        B10001,
+        B11111,
+        B00000,
+        B00000
+    }; //thanks joris
+    byte feedrate [8]={
+        B11100,
+        B10000,
+        B11000,
+        B10111,
+        B00101,
+        B00110,
+        B00101,
+        B00000
+    }; //thanks Sonny Mounicou
+    byte clock [8]={
+        B00000,
+        B01110,
+        B10011,
+        B10101,
+        B10001,
+        B01110,
+        B00000,
+        B00000
+    }; //thanks Sonny Mounicou
+
+#if defined(LCDI2C_TYPE_PCF8575)
+    lcd.begin(LCD_WIDTH, LCD_HEIGHT);
+  #ifdef LCD_I2C_PIN_BL
+    lcd.setBacklightPin(LCD_I2C_PIN_BL,POSITIVE);
+    lcd.setBacklight(HIGH);
+  #endif
+  
+#elif defined(LCD_I2C_TYPE_MCP23017)
+    lcd.setMCPType(LTI_TYPE_MCP23017);
+    lcd.begin(LCD_WIDTH, LCD_HEIGHT);
+    lcd.setBacklight(0); //set all the LEDs off to begin with
+    
+#elif defined(LCD_I2C_TYPE_MCP23008)
+    lcd.setMCPType(LTI_TYPE_MCP23008);
+    lcd.begin(LCD_WIDTH, LCD_HEIGHT);
+
+#elif defined(LCD_I2C_TYPE_PCA8574)
+      lcd.init();
+      lcd.backlight();
+    
+#else
+    lcd.begin(LCD_WIDTH, LCD_HEIGHT);
+#endif
+
+    lcd.createChar(LCD_STR_BEDTEMP[0], bedTemp);
+    lcd.createChar(LCD_STR_DEGREE[0], degree);
+    lcd.createChar(LCD_STR_THERMOMETER[0], thermometer);
+    lcd.createChar(LCD_STR_UPLEVEL[0], uplevel);
+    lcd.createChar(LCD_STR_REFRESH[0], refresh);
+    lcd.createChar(LCD_STR_FOLDER[0], folder);
+    lcd.createChar(LCD_STR_FEEDRATE[0], feedrate);
+    lcd.createChar(LCD_STR_CLOCK[0], clock);
+    lcd.clear();
+}
+static void lcd_implementation_clear()
+{
+    lcd.clear();
+}
+/* Arduino < 1.0.0 is missing a function to print PROGMEM strings, so we need to implement our own */
+static void lcd_printPGM(const char* str)
+{
+    char c;
+    while((c = pgm_read_byte(str++)) != '\0')
+    {
+        lcd.write(c);
+    }
+}
+/*
+Possible status screens:
+16x2   |0123456789012345|
+       |000/000 B000/000|
+       |Status line.....|
+
+16x4   |0123456789012345|
+       |000/000 B000/000|
+       |SD100%    Z000.0|
+       |F100%     T--:--|
+       |Status line.....|
+
+20x2   |01234567890123456789|
+       |T000/000D B000/000D |
+       |Status line.........|
+
+20x4   |01234567890123456789|
+       |T000/000D B000/000D |
+       |X+000.0 Y+000.0 Z+000.0|
+       |F100%  SD100% T--:--|
+       |Status line.........|
+
+20x4   |01234567890123456789|
+       |T000/000D B000/000D |
+       |T000/000D     Z000.0|
+       |F100%  SD100% T--:--|
+       |Status line.........|
+*/
+static void lcd_implementation_status_screen()
+{
+    int tHotend=int(degHotend(0) + 0.5);
+    int tTarget=int(degTargetHotend(0) + 0.5);
+
+#if LCD_WIDTH < 20
+    lcd.setCursor(0, 0);
+    lcd.print(itostr3(tHotend));
+    lcd.print('/');
+    lcd.print(itostr3left(tTarget));
+
+# if EXTRUDERS > 1 || TEMP_SENSOR_BED != 0
+    //If we have an 2nd extruder or heated bed, show that in the top right corner
+    lcd.setCursor(8, 0);
+#  if EXTRUDERS > 1
+    tHotend = int(degHotend(1) + 0.5);
+    tTarget = int(degTargetHotend(1) + 0.5);
+    lcd.print(LCD_STR_THERMOMETER[0]);
+#  else//Heated bed
+    tHotend=int(degBed() + 0.5);
+    tTarget=int(degTargetBed() + 0.5);
+    lcd.print(LCD_STR_BEDTEMP[0]);
+#  endif
+    lcd.print(itostr3(tHotend));
+    lcd.print('/');
+    lcd.print(itostr3left(tTarget));
+# endif//EXTRUDERS > 1 || TEMP_SENSOR_BED != 0
+
+#else//LCD_WIDTH > 19
+    lcd.setCursor(0, 0);
+    lcd.print(LCD_STR_THERMOMETER[0]);
+    lcd.print(itostr3(tHotend));
+    lcd.print('/');
+    lcd.print(itostr3left(tTarget));
+    lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
+    if (tTarget < 10)
+        lcd.print(' ');
+
+# if EXTRUDERS > 1 || TEMP_SENSOR_BED != 0
+    //If we have an 2nd extruder or heated bed, show that in the top right corner
+    lcd.setCursor(10, 0);
+#  if EXTRUDERS > 1
+    tHotend = int(degHotend(1) + 0.5);
+    tTarget = int(degTargetHotend(1) + 0.5);
+    lcd.print(LCD_STR_THERMOMETER[0]);
+#  else//Heated bed
+    tHotend=int(degBed() + 0.5);
+    tTarget=int(degTargetBed() + 0.5);
+    lcd.print(LCD_STR_BEDTEMP[0]);
+#  endif
+    lcd.print(itostr3(tHotend));
+    lcd.print('/');
+    lcd.print(itostr3left(tTarget));
+    lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
+    if (tTarget < 10)
+        lcd.print(' ');
+# endif//EXTRUDERS > 1 || TEMP_SENSOR_BED != 0
+#endif//LCD_WIDTH > 19
+
+#if LCD_HEIGHT > 2
+//Lines 2 for 4 line LCD
+# if LCD_WIDTH < 20
+#  ifdef SDSUPPORT
+    lcd.setCursor(0, 2);
+    lcd_printPGM(PSTR("SD"));
+    if (IS_SD_PRINTING)
+        lcd.print(itostr3(card.percentDone()));
+    else
+        lcd_printPGM(PSTR("---"));
+    lcd.print('%');
+#  endif//SDSUPPORT
+# else//LCD_WIDTH > 19
+#  if EXTRUDERS > 1 && TEMP_SENSOR_BED != 0
+    //If we both have a 2nd extruder and a heated bed, show the heated bed temp on the 2nd line on the left, as the first line is filled with extruder temps
+    tHotend=int(degBed() + 0.5);
+    tTarget=int(degTargetBed() + 0.5);
+
+    lcd.setCursor(0, 1);
+    lcd.print(LCD_STR_BEDTEMP[0]);
+    lcd.print(itostr3(tHotend));
+    lcd.print('/');
+    lcd.print(itostr3left(tTarget));
+    lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
+    if (tTarget < 10)
+        lcd.print(' ');
+#  else
+    lcd.setCursor(0,1);
+    lcd.print('X');
+    lcd.print(ftostr3(current_position[X_AXIS]));
+    lcd_printPGM(PSTR(" Y"));
+    lcd.print(ftostr3(current_position[Y_AXIS]));
+#  endif//EXTRUDERS > 1 || TEMP_SENSOR_BED != 0
+# endif//LCD_WIDTH > 19
+    lcd.setCursor(LCD_WIDTH - 8, 1);
+    lcd.print('Z');
+    lcd.print(ftostr32(current_position[Z_AXIS]));
+#endif//LCD_HEIGHT > 2
+
+#if LCD_HEIGHT > 3
+    lcd.setCursor(0, 2);
+    lcd.print(LCD_STR_FEEDRATE[0]);
+    lcd.print(itostr3(feedmultiply));
+    lcd.print('%');
+# if LCD_WIDTH > 19
+#  ifdef SDSUPPORT
+    lcd.setCursor(7, 2);
+    lcd_printPGM(PSTR("SD"));
+    if (IS_SD_PRINTING)
+        lcd.print(itostr3(card.percentDone()));
+    else
+        lcd_printPGM(PSTR("---"));
+    lcd.print('%');
+#  endif//SDSUPPORT
+# endif//LCD_WIDTH > 19
+    lcd.setCursor(LCD_WIDTH - 6, 2);
+    lcd.print(LCD_STR_CLOCK[0]);
+    if(starttime != 0)
+    {
+        uint16_t time = millis()/60000 - starttime/60000;
+        lcd.print(itostr2(time/60));
+        lcd.print(':');
+        lcd.print(itostr2(time%60));
+    }else{
+        lcd_printPGM(PSTR("--:--"));
+    }
+#endif
+
+    //Status message line on the last line
+    lcd.setCursor(0, LCD_HEIGHT - 1);
+    lcd.print(lcd_status_message);
+}
+static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, char pre_char, char post_char)
+{
+    char c;
+    //Use all characters in narrow LCDs
+  #if LCD_WIDTH < 20
+      uint8_t n = LCD_WIDTH - 1 - 1;
+    #else
+      uint8_t n = LCD_WIDTH - 1 - 2;
+  #endif
+    lcd.setCursor(0, row);
+    lcd.print(pre_char);
+    while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) )
+    {
+        lcd.print(c);
+        pstr++;
+        n--;
+    }
+    while(n--)
+        lcd.print(' ');
+    lcd.print(post_char);
+    lcd.print(' ');
+}
+static void lcd_implementation_drawmenu_setting_edit_generic(uint8_t row, const char* pstr, char pre_char, char* data)
+{
+    char c;
+    //Use all characters in narrow LCDs
+  #if LCD_WIDTH < 20
+      uint8_t n = LCD_WIDTH - 1 - 1 - strlen(data);
+    #else
+      uint8_t n = LCD_WIDTH - 1 - 2 - strlen(data);
+  #endif
+    lcd.setCursor(0, row);
+    lcd.print(pre_char);
+    while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) )
+    {
+        lcd.print(c);
+        pstr++;
+        n--;
+    }
+    lcd.print(':');
+    while(n--)
+        lcd.print(' ');
+    lcd.print(data);
+}
+static void lcd_implementation_drawmenu_setting_edit_generic_P(uint8_t row, const char* pstr, char pre_char, const char* data)
+{
+    char c;
+    //Use all characters in narrow LCDs
+  #if LCD_WIDTH < 20
+      uint8_t n = LCD_WIDTH - 1 - 1 - strlen_P(data);
+    #else
+      uint8_t n = LCD_WIDTH - 1 - 2 - strlen_P(data);
+  #endif
+    lcd.setCursor(0, row);
+    lcd.print(pre_char);
+    while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) )
+    {
+        lcd.print(c);
+        pstr++;
+        n--;
+    }
+    lcd.print(':');
+    while(n--)
+        lcd.print(' ');
+    lcd_printPGM(data);
+}
+#define lcd_implementation_drawmenu_setting_edit_int3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_int3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float32_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float32(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float52_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float52(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float51_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_float51(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_long5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_long5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_bool_selected(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
+#define lcd_implementation_drawmenu_setting_edit_bool(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
+
+//Add version for callback functions
+#define lcd_implementation_drawmenu_setting_edit_callback_int3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_int3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float32_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float32(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float52_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float52(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float51_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_float51(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_long5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_long5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
+#define lcd_implementation_drawmenu_setting_edit_callback_bool_selected(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
+#define lcd_implementation_drawmenu_setting_edit_callback_bool(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
+
+
+void lcd_implementation_drawedit(const char* pstr, char* value)
+{
+    lcd.setCursor(1, 1);
+    lcd_printPGM(pstr);
+    lcd.print(':');
+   #if LCD_WIDTH < 20
+      lcd.setCursor(LCD_WIDTH - strlen(value), 1);
+    #else
+      lcd.setCursor(LCD_WIDTH -1 - strlen(value), 1);
+   #endif
+    lcd.print(value);
+}
+static void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename)
+{
+    char c;
+    uint8_t n = LCD_WIDTH - 1;
+    lcd.setCursor(0, row);
+    lcd.print('>');
+    if (longFilename[0] != '\0')
+    {
+        filename = longFilename;
+        longFilename[LCD_WIDTH-1] = '\0';
+    }
+    while( ((c = *filename) != '\0') && (n>0) )
+    {
+        lcd.print(c);
+        filename++;
+        n--;
+    }
+    while(n--)
+        lcd.print(' ');
+}
+static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* pstr, const char* filename, char* longFilename)
+{
+    char c;
+    uint8_t n = LCD_WIDTH - 1;
+    lcd.setCursor(0, row);
+    lcd.print(' ');
+    if (longFilename[0] != '\0')
+    {
+        filename = longFilename;
+        longFilename[LCD_WIDTH-1] = '\0';
+    }
+    while( ((c = *filename) != '\0') && (n>0) )
+    {
+        lcd.print(c);
+        filename++;
+        n--;
+    }
+    while(n--)
+        lcd.print(' ');
+}
+static void lcd_implementation_drawmenu_sddirectory_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename)
+{
+    char c;
+    uint8_t n = LCD_WIDTH - 2;
+    lcd.setCursor(0, row);
+    lcd.print('>');
+    lcd.print(LCD_STR_FOLDER[0]);
+    if (longFilename[0] != '\0')
+    {
+        filename = longFilename;
+        longFilename[LCD_WIDTH-2] = '\0';
+    }
+    while( ((c = *filename) != '\0') && (n>0) )
+    {
+        lcd.print(c);
+        filename++;
+        n--;
+    }
+    while(n--)
+        lcd.print(' ');
+}
+static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* pstr, const char* filename, char* longFilename)
+{
+    char c;
+    uint8_t n = LCD_WIDTH - 2;
+    lcd.setCursor(0, row);
+    lcd.print(' ');
+    lcd.print(LCD_STR_FOLDER[0]);
+    if (longFilename[0] != '\0')
+    {
+        filename = longFilename;
+        longFilename[LCD_WIDTH-2] = '\0';
+    }
+    while( ((c = *filename) != '\0') && (n>0) )
+    {
+        lcd.print(c);
+        filename++;
+        n--;
+    }
+    while(n--)
+        lcd.print(' ');
+}
+#define lcd_implementation_drawmenu_back_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
+#define lcd_implementation_drawmenu_back(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_UPLEVEL[0])
+#define lcd_implementation_drawmenu_submenu_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
+#define lcd_implementation_drawmenu_submenu(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_ARROW_RIGHT[0])
+#define lcd_implementation_drawmenu_gcode_selected(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
+#define lcd_implementation_drawmenu_gcode(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
+#define lcd_implementation_drawmenu_function_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
+#define lcd_implementation_drawmenu_function(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
+
+static void lcd_implementation_quick_feedback()
+{
+#ifdef LCD_USE_I2C_BUZZER
+	#if !defined(LCD_FEEDBACK_FREQUENCY_HZ) || !defined(LCD_FEEDBACK_FREQUENCY_DURATION_MS)
+	  lcd_buzz(1000/6,100);
+	#else
+	  lcd_buzz(LCD_FEEDBACK_FREQUENCY_DURATION_MS,LCD_FEEDBACK_FREQUENCY_HZ);
+	#endif
+#elif defined(BEEPER) && BEEPER > -1
+    SET_OUTPUT(BEEPER);
+    for(int8_t i=0;i<10;i++)
+    {
+      WRITE(BEEPER,HIGH);
+      delayMicroseconds(100);
+      WRITE(BEEPER,LOW);
+      delayMicroseconds(100);
+    }
+#endif
+}
+
+#ifdef LCD_HAS_STATUS_INDICATORS
+static void lcd_implementation_update_indicators()
+{
+  #if defined(LCD_I2C_PANELOLU2) || defined(LCD_I2C_VIKI)
+    //set the LEDS - referred to as backlights by the LiquidTWI2 library 
+    static uint8_t ledsprev = 0;
+    uint8_t leds = 0;
+    if (target_temperature_bed > 0) leds |= LED_A;
+    if (target_temperature[0] > 0) leds |= LED_B;
+    if (fanSpeed) leds |= LED_C;
+    #if EXTRUDERS > 1  
+      if (target_temperature[1] > 0) leds |= LED_C;
+    #endif
+    if (leds != ledsprev) {
+      lcd.setBacklight(leds);
+      ledsprev = leds;
+    }
+  #endif
+}
+#endif
+
+#ifdef LCD_HAS_SLOW_BUTTONS
+extern uint32_t blocking_enc;
+
+static uint8_t lcd_implementation_read_slow_buttons()
+{
+  #ifdef LCD_I2C_TYPE_MCP23017
+  uint8_t slow_buttons;
+    // Reading these buttons this is likely to be too slow to call inside interrupt context
+    // so they are called during normal lcd_update
+    slow_buttons = lcd.readButtons() << B_I2C_BTN_OFFSET; 
+    #if defined(LCD_I2C_VIKI)
+    if(slow_buttons & (B_MI|B_RI)) { //LCD clicked
+       if(blocking_enc > millis()) {
+         slow_buttons &= ~(B_MI|B_RI); // Disable LCD clicked buttons if screen is updated
+       }
+    }
+    #endif
+    return slow_buttons; 
+  #endif
+}
+#endif
+
+#endif//ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H

+ 131 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/ultralcd_st7920_u8glib_rrd.h

@@ -0,0 +1,131 @@
+#ifndef ULCDST7920_H
+#define ULCDST7920_H
+
+#include "Marlin.h"
+
+#ifdef U8GLIB_ST7920
+
+//set optimization so ARDUINO optimizes this file
+#pragma GCC optimize (3)
+
+#define ST7920_CLK_PIN  LCD_PINS_D4
+#define ST7920_DAT_PIN  LCD_PINS_ENABLE
+#define ST7920_CS_PIN   LCD_PINS_RS
+
+//#define PAGE_HEIGHT 8   //128 byte frambuffer
+//#define PAGE_HEIGHT 16  //256 byte frambuffer
+#define PAGE_HEIGHT 32  //512 byte framebuffer
+
+#define WIDTH 128
+#define HEIGHT 64
+
+#include <U8glib.h>
+
+static void ST7920_SWSPI_SND_8BIT(uint8_t val)
+{
+  uint8_t i;
+  for( i=0; i<8; i++ )
+  {
+    WRITE(ST7920_CLK_PIN,0);
+    WRITE(ST7920_DAT_PIN,val&0x80); 
+    val<<=1;
+    WRITE(ST7920_CLK_PIN,1);
+  }
+}
+
+#define ST7920_CS()              {WRITE(ST7920_CS_PIN,1);u8g_10MicroDelay();}
+#define ST7920_NCS()             {WRITE(ST7920_CS_PIN,0);}
+#define ST7920_SET_CMD()         {ST7920_SWSPI_SND_8BIT(0xf8);u8g_10MicroDelay();}
+#define ST7920_SET_DAT()         {ST7920_SWSPI_SND_8BIT(0xfa);u8g_10MicroDelay();}
+#define ST7920_WRITE_BYTE(a)     {ST7920_SWSPI_SND_8BIT((a)&0xf0);ST7920_SWSPI_SND_8BIT((a)<<4);u8g_10MicroDelay();}
+#define ST7920_WRITE_BYTES(p,l)  {uint8_t i;for(i=0;i<l;i++){ST7920_SWSPI_SND_8BIT(*p&0xf0);ST7920_SWSPI_SND_8BIT(*p<<4);p++;}u8g_10MicroDelay();}
+
+uint8_t u8g_dev_rrd_st7920_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg)
+{
+  uint8_t i,y;
+  switch(msg)
+  {
+    case U8G_DEV_MSG_INIT:
+      {
+        SET_OUTPUT(ST7920_CS_PIN);
+        WRITE(ST7920_CS_PIN,0);
+        SET_OUTPUT(ST7920_DAT_PIN);
+        WRITE(ST7920_DAT_PIN,0);
+        SET_OUTPUT(ST7920_CLK_PIN);
+        WRITE(ST7920_CLK_PIN,1);
+
+        ST7920_CS();
+        u8g_Delay(90);                 //initial delay for boot up
+        ST7920_SET_CMD();
+        ST7920_WRITE_BYTE(0x08);       //display off, cursor+blink off
+        ST7920_WRITE_BYTE(0x01);       //clear CGRAM ram
+        u8g_Delay(10);                 //delay for cgram clear
+        ST7920_WRITE_BYTE(0x3E);       //extended mode + gdram active
+        for(y=0;y<HEIGHT/2;y++)        //clear GDRAM
+        {
+          ST7920_WRITE_BYTE(0x80|y);   //set y
+          ST7920_WRITE_BYTE(0x80);     //set x = 0
+          ST7920_SET_DAT();
+          for(i=0;i<2*WIDTH/8;i++)     //2x width clears both segments
+            ST7920_WRITE_BYTE(0);
+          ST7920_SET_CMD();
+        }
+        ST7920_WRITE_BYTE(0x0C); //display on, cursor+blink off
+        ST7920_NCS();
+      }
+      break;
+
+    case U8G_DEV_MSG_STOP:
+      break;
+    case U8G_DEV_MSG_PAGE_NEXT:
+      {
+        uint8_t *ptr;
+        u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem);
+        y = pb->p.page_y0;
+        ptr = (uint8_t*)pb->buf;
+
+        ST7920_CS();
+        for( i = 0; i < PAGE_HEIGHT; i ++ )
+        {
+          ST7920_SET_CMD();
+          if ( y < 32 )
+          {
+            ST7920_WRITE_BYTE(0x80 | y);       //y
+            ST7920_WRITE_BYTE(0x80);           //x=0
+          }
+          else
+          {
+            ST7920_WRITE_BYTE(0x80 | (y-32));  //y
+            ST7920_WRITE_BYTE(0x80 | 8);       //x=64
+          }
+
+          ST7920_SET_DAT();
+          ST7920_WRITE_BYTES(ptr,WIDTH/8); //ptr is incremented inside of macro
+          y++;
+        }
+        ST7920_NCS();
+      }
+      break;
+  }
+#if PAGE_HEIGHT == 8
+  return u8g_dev_pb8h1_base_fn(u8g, dev, msg, arg);
+#elif PAGE_HEIGHT == 16
+  return u8g_dev_pb16h1_base_fn(u8g, dev, msg, arg);
+#else
+  return u8g_dev_pb32h1_base_fn(u8g, dev, msg, arg);
+#endif
+}
+
+uint8_t   u8g_dev_st7920_128x64_rrd_buf[WIDTH*(PAGE_HEIGHT/8)] U8G_NOCOMMON;
+u8g_pb_t  u8g_dev_st7920_128x64_rrd_pb = {{PAGE_HEIGHT,HEIGHT,0,0,0},WIDTH,u8g_dev_st7920_128x64_rrd_buf};
+u8g_dev_t u8g_dev_st7920_128x64_rrd_sw_spi = {u8g_dev_rrd_st7920_128x64_fn,&u8g_dev_st7920_128x64_rrd_pb,&u8g_com_null_fn};
+
+class U8GLIB_ST7920_128X64_RRD : public U8GLIB
+{
+  public:
+    U8GLIB_ST7920_128X64_RRD(uint8_t dummy) : U8GLIB(&u8g_dev_st7920_128x64_rrd_sw_spi) {}
+};
+
+
+#endif //U8GLIB_ST7920
+#endif //ULCDST7920_H

+ 177 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/vector_3.cpp

@@ -0,0 +1,177 @@
+/*
+  vector_3.cpp - Vector library for bed leveling
+  Copyright (c) 2012 Lars Brubaker.  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
+*/
+#include <math.h>
+#include "Marlin.h"
+
+#ifdef ENABLE_AUTO_BED_LEVELING
+#include "vector_3.h"
+
+vector_3::vector_3()
+{
+  this->x = 0;
+  this->y = 0;
+  this->z = 0;
+}
+
+vector_3::vector_3(float x, float y, float z)
+{
+	this->x = x;
+	this->y = y;
+	this->z = z;
+}
+
+vector_3 vector_3::cross(vector_3 left, vector_3 right)
+{
+	return vector_3(left.y * right.z - left.z * right.y,
+		left.z * right.x - left.x * right.z,
+		left.x * right.y - left.y * right.x);
+}
+
+vector_3 vector_3::operator+(vector_3 v) 
+{
+	return vector_3((x + v.x), (y + v.y), (z + v.z));
+}
+
+vector_3 vector_3::operator-(vector_3 v) 
+{
+	return vector_3((x - v.x), (y - v.y), (z - v.z));
+}
+
+vector_3 vector_3::get_normal() 
+{
+	vector_3 normalized = vector_3(x, y, z);
+	normalized.normalize();
+	return normalized;
+}
+
+float vector_3::get_length() 
+{
+        float length = sqrt((x * x) + (y * y) + (z * z));
+	return length;
+}
+ 
+void vector_3::normalize()
+{
+	float length = get_length();
+	x /= length;
+	y /= length;
+	z /= length;
+}
+
+void vector_3::apply_rotation(matrix_3x3 matrix)
+{
+	float resultX = x * matrix.matrix[3*0+0] + y * matrix.matrix[3*1+0] + z * matrix.matrix[3*2+0];
+	float resultY = x * matrix.matrix[3*0+1] + y * matrix.matrix[3*1+1] + z * matrix.matrix[3*2+1];
+	float resultZ = x * matrix.matrix[3*0+2] + y * matrix.matrix[3*1+2] + z * matrix.matrix[3*2+2];
+
+	x = resultX;
+	y = resultY;
+	z = resultZ;
+}
+
+void vector_3::debug(char* title)
+{
+	SERIAL_PROTOCOL(title);
+	SERIAL_PROTOCOLPGM(" x: ");
+	SERIAL_PROTOCOL(x);
+	SERIAL_PROTOCOLPGM(" y: ");
+	SERIAL_PROTOCOL(y);
+	SERIAL_PROTOCOLPGM(" z: ");
+	SERIAL_PROTOCOL(z);
+	SERIAL_PROTOCOLPGM("\n");
+}
+
+void apply_rotation_xyz(matrix_3x3 matrix, float &x, float& y, float& z)
+{
+	vector_3 vector = vector_3(x, y, z);
+	vector.apply_rotation(matrix);
+	x = vector.x;
+	y = vector.y;
+	z = vector.z;
+}
+
+matrix_3x3 matrix_3x3::create_from_rows(vector_3 row_0, vector_3 row_1, vector_3 row_2)
+{
+        //row_0.debug("row_0");
+        //row_1.debug("row_1");
+        //row_2.debug("row_2");
+	matrix_3x3 new_matrix;
+	new_matrix.matrix[0] = row_0.x; new_matrix.matrix[1] = row_0.y; new_matrix.matrix[2] = row_0.z; 
+	new_matrix.matrix[3] = row_1.x; new_matrix.matrix[4] = row_1.y; new_matrix.matrix[5] = row_1.z; 
+	new_matrix.matrix[6] = row_2.x; new_matrix.matrix[7] = row_2.y; new_matrix.matrix[8] = row_2.z; 
+        //new_matrix.debug("new_matrix");
+        
+	return new_matrix;
+}
+
+void matrix_3x3::set_to_identity()
+{
+	matrix[0] = 1; matrix[1] = 0; matrix[2] = 0;
+	matrix[3] = 0; matrix[4] = 1; matrix[5] = 0;
+	matrix[6] = 0; matrix[7] = 0; matrix[8] = 1;
+}
+
+matrix_3x3 matrix_3x3::create_look_at(vector_3 target)
+{
+    vector_3 z_row = target.get_normal();
+    vector_3 x_row = vector_3(1, 0, -target.x/target.z).get_normal();
+    vector_3 y_row = vector_3(0, 1, -target.y/target.z).get_normal();
+
+   // x_row.debug("x_row");
+   // y_row.debug("y_row");
+   // z_row.debug("z_row");
+
+ 
+     // create the matrix already correctly transposed
+    matrix_3x3 rot = matrix_3x3::create_from_rows(x_row, y_row, z_row);
+
+ //   rot.debug("rot");
+    return rot;
+}
+
+
+matrix_3x3 matrix_3x3::transpose(matrix_3x3 original)
+{
+  matrix_3x3 new_matrix;
+  new_matrix.matrix[0] = original.matrix[0]; new_matrix.matrix[1] = original.matrix[3]; new_matrix.matrix[2] = original.matrix[6]; 
+  new_matrix.matrix[3] = original.matrix[1]; new_matrix.matrix[4] = original.matrix[4]; new_matrix.matrix[5] = original.matrix[7]; 
+  new_matrix.matrix[6] = original.matrix[2]; new_matrix.matrix[7] = original.matrix[5]; new_matrix.matrix[8] = original.matrix[8];
+  return new_matrix;
+}
+
+void matrix_3x3::debug(char* title)
+{
+	SERIAL_PROTOCOL(title);
+	SERIAL_PROTOCOL("\n");
+	int count = 0;
+	for(int i=0; i<3; i++)
+	{
+		for(int j=0; j<3; j++)
+		{
+			SERIAL_PROTOCOL(matrix[count]);
+			SERIAL_PROTOCOLPGM(" ");
+		        count++;
+		}
+
+		SERIAL_PROTOCOLPGM("\n");
+	}
+}
+
+#endif // #ifdef ENABLE_AUTO_BED_LEVELING
+

+ 62 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/vector_3.h

@@ -0,0 +1,62 @@
+/*
+  vector_3.cpp - Vector library for bed leveling
+  Copyright (c) 2012 Lars Brubaker.  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
+*/
+#ifndef VECTOR_3_H
+#define VECTOR_3_H
+
+#ifdef ENABLE_AUTO_BED_LEVELING
+class matrix_3x3;
+
+struct vector_3
+{
+	float x, y, z;
+
+        vector_3();
+	vector_3(float x, float y, float z);
+
+	static vector_3 cross(vector_3 a, vector_3 b);
+
+	vector_3 operator+(vector_3 v);
+	vector_3 operator-(vector_3 v);
+	void normalize();
+	float get_length();
+	vector_3 get_normal();
+
+	void debug(char* title);
+	
+	void apply_rotation(matrix_3x3 matrix);
+};
+
+struct matrix_3x3
+{
+	float matrix[9];
+
+	static matrix_3x3 create_from_rows(vector_3 row_0, vector_3 row_1, vector_3 row_2);
+	static matrix_3x3 create_look_at(vector_3 target);
+	static matrix_3x3 transpose(matrix_3x3 original);
+
+	void set_to_identity();
+
+	void debug(char* title);
+};
+
+
+void apply_rotation_xyz(matrix_3x3 rotationMatrix, float &x, float& y, float& z);
+#endif // ENABLE_AUTO_BED_LEVELING
+
+#endif // VECTOR_3_H

+ 56 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/watchdog.cpp

@@ -0,0 +1,56 @@
+#include "Marlin.h"
+
+#ifdef USE_WATCHDOG
+#include <avr/wdt.h>
+
+#include "watchdog.h"
+#include "ultralcd.h"
+
+//===========================================================================
+//=============================private variables  ============================
+//===========================================================================
+
+//===========================================================================
+//=============================functinos         ============================
+//===========================================================================
+
+
+/// intialise watch dog with a 4 sec interrupt time
+void watchdog_init()
+{
+#ifdef WATCHDOG_RESET_MANUAL
+    //We enable the watchdog timer, but only for the interrupt.
+    //Take care, as this requires the correct order of operation, with interrupts disabled. See the datasheet of any AVR chip for details.
+    wdt_reset();
+    _WD_CONTROL_REG = _BV(_WD_CHANGE_BIT) | _BV(WDE);
+    _WD_CONTROL_REG = _BV(WDIE) | WDTO_4S;
+#else
+    wdt_enable(WDTO_4S);
+#endif
+}
+
+/// reset watchdog. MUST be called every 1s after init or avr will reset.
+void watchdog_reset() 
+{
+    wdt_reset();
+}
+
+//===========================================================================
+//=============================ISR               ============================
+//===========================================================================
+
+//Watchdog timer interrupt, called if main program blocks >1sec and manual reset is enabled.
+#ifdef WATCHDOG_RESET_MANUAL
+ISR(WDT_vect)
+{ 
+    //TODO: This message gets overwritten by the kill() call
+    LCD_ALERTMESSAGEPGM("ERR:Please Reset");//16 characters so it fits on a 16x2 display
+    lcd_update();
+    SERIAL_ERROR_START;
+    SERIAL_ERRORLNPGM("Something is wrong, please turn off the printer.");
+    kill(); //kill blocks
+    while(1); //wait for user or serial reset
+}
+#endif//RESET_MANUAL
+
+#endif//USE_WATCHDOG

+ 17 - 0
Ender-3 Firmware (Marlin)/Ender-3 (includes power failure resume- Chinese)/Marlin/watchdog.h

@@ -0,0 +1,17 @@
+#ifndef WATCHDOG_H
+#define WATCHDOG_H
+
+#include "Marlin.h"
+
+#ifdef USE_WATCHDOG
+  // intialise watch dog with a 1 sec interrupt time
+  void watchdog_init();
+  // pad the dog/reset watchdog. MUST be called at least every second after the first watchdog_init or avr will go into emergency procedures..
+  void watchdog_reset();
+#else
+  //If we do not have a watchdog, then we can have empty functions which are optimized away.
+  FORCE_INLINE void watchdog_init() {};
+  FORCE_INLINE void watchdog_reset() {};
+#endif
+
+#endif