Browse Source

added marlin 1.1.9 based on ender3.fr/hotends.fr

Snarf 6 years ago
parent
commit
ec6315b6fc
100 changed files with 82946 additions and 1 deletions
  1. 17 1
      firmwares/marlin/README.md
  2. 27 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Conditionals.h
  3. 528 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Conditionals_LCD.h
  4. 1417 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Conditionals_post.h
  5. 1957 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Configuration.h
  6. 1663 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Configuration_adv.h
  7. 920 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/G26_Mesh_Validation_Tool.cpp
  8. 337 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/HAL.h
  9. 1140 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/I2CPositionEncoder.cpp
  10. 342 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/I2CPositionEncoder.h
  11. 332 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/M100_Free_Mem_Chk.cpp
  12. 686 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Makefile
  13. 647 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Marlin.h
  14. 53 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Marlin.ino
  15. 48 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/MarlinConfig.h
  16. 57 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/MarlinSPI.h
  17. 740 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/MarlinSerial.cpp
  18. 184 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/MarlinSerial.h
  19. 15377 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Marlin_main.cpp
  20. 593 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Max7219_Debug_LEDs.cpp
  21. 154 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Max7219_Debug_LEDs.h
  22. 1705 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SanityCheck.h
  23. 716 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Sd2Card.cpp
  24. 204 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Sd2Card.h
  25. 1728 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdBaseFile.cpp
  26. 390 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdBaseFile.h
  27. 116 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdFatConfig.h
  28. 615 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdFatStructs.h
  29. 91 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdFatUtil.cpp
  30. 51 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdFatUtil.h
  31. 100 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdFile.cpp
  32. 60 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdFile.h
  33. 267 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdInfo.h
  34. 384 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdVolume.cpp
  35. 211 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdVolume.h
  36. 94 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Version.h
  37. 75 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/_Bootscreen.h
  38. 38 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/bitmap_flags.h
  39. 46 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/blinkm.cpp
  40. 35 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/blinkm.h
  41. 161 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/boards.h
  42. 146 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/buzzer.h
  43. 987 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/cardreader.cpp
  44. 230 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/cardreader.h
  45. 145 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/circularqueue.h
  46. 2790 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/configuration_store.cpp
  47. 101 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/configuration_store.h
  48. 153 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dac_mcp4728.cpp
  49. 66 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dac_mcp4728.h
  50. 77 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/delay.h
  51. 106 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/digipot_mcp4018.cpp
  52. 79 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/digipot_mcp4451.cpp
  53. 1192 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_bitmaps.h
  54. 180 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_6x9_marlin.h
  55. 194 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_HD44780_C.h
  56. 192 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_HD44780_J.h
  57. 226 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_HD44780_W.h
  58. 286 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_1.h
  59. 184 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_1_PL.h
  60. 197 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_1_tr.h
  61. 196 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_5_Cyrillic.h
  62. 293 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_CN.h
  63. 192 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_CZ.h
  64. 205 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_Greek.h
  65. 192 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_Kana.h
  66. 151 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_SK.h
  67. 45 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_Marlin_symbols.h
  68. 73 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/drivers.h
  69. 170 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/duration_t.h
  70. 40 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/emergency_parser.cpp
  71. 144 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/emergency_parser.h
  72. 239 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/endstop_interrupts.h
  73. 774 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/endstops.cpp
  74. 174 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/endstops.h
  75. 175 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/enum.h
  76. 1940 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/AlephObjects/TAZ4/Configuration.h
  77. 1654 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/AlephObjects/TAZ4/Configuration_adv.h
  78. 1920 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/AliExpress/CL-260/Configuration.h
  79. 15 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/AliExpress/CL-260/README.txt
  80. 1997 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Anet/A2plus/Configuration.h
  81. 1654 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Anet/A2plus/Configuration_adv.h
  82. 2075 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Anet/A6/Configuration.h
  83. 1654 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Anet/A6/Configuration_adv.h
  84. 1929 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Anet/A8/Configuration.h
  85. 1654 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Anet/A8/Configuration_adv.h
  86. 1920 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BIBO/TouchX/Cyclops/Configuration.h
  87. 1654 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BIBO/TouchX/Cyclops/Configuration_adv.h
  88. 1920 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BIBO/TouchX/default/Configuration.h
  89. 1654 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BIBO/TouchX/default/Configuration_adv.h
  90. 1908 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/Hephestos/Configuration.h
  91. 1654 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/Hephestos/Configuration_adv.h
  92. 1918 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/Hephestos_2/Configuration.h
  93. 1662 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/Hephestos_2/Configuration_adv.h
  94. 29 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/Hephestos_2/README.md
  95. 100 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/Hephestos_2/_Bootscreen.h
  96. 1908 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/WITBOX/Configuration.h
  97. 1654 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/WITBOX/Configuration_adv.h
  98. 1919 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Cartesio/Configuration.h
  99. 1654 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Cartesio/Configuration_adv.h
  100. 0 0
      firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Cartesio/_Bootscreen.h

+ 17 - 1
firmwares/marlin/README.md

@@ -29,4 +29,20 @@ I've modified the `*_PROBE_BED_POSITION` defines to use probe offsets
 
 Some explainations about how it used id in the [Wiki](https://git.dahwa.fr/3DPrinting/Tips/wiki/TouchMi)
 
-TODO : increase BLOCK_BUFFER_SIZE, MAX_CMD_SIZE, and BUFSIZE 
+TODO : increase BLOCK_BUFFER_SIZE, MAX_CMD_SIZE, and BUFSIZE 
+
+## Touch Mi - Marlin-1.1.9-Ender3.fr
+
+This one is based on the Marlin mods made by [ender3.fr]() and [hotends.fr](). 
+
+I've done some update in their configuration : 
+
+* `LIN_ADVANCE` is disabled. I don't need it atm, and too complex to maintain for bowden
+* `S_CURVE_ACCELERATION` is enabled (see https://github.com/synthetos/TinyG/wiki/Jerk-Controlled-Motion-Explained)
+* `PIDTEMPBED` is enabled
+* `RESTORE_LEVELING_AFTER_G28` is enabled  (see [G29 ABL](http://marlinfw.org/docs/gcode/G029-abl.html) for details)
+* `ENABLE_LEVELING_FADE_HEIGHT` is enabled  (see [Marlin issue #7562](https://github.com/MarlinFirmware/Marlin/issues/7562) for details)
+* I need moar `PROGMEM` and use [OctoPrint](https://octoprint.org/), `SDSUPPORT` is disabled , so i can comment back `DISABLE_M503`
+* Step/mm, PIDs are feeded from my own values.
+* `GRID_MAX_POINTS_X` & `GRID_MAX_POINTS_Y` are set to 5
+

+ 27 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Conditionals.h

@@ -0,0 +1,27 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Conditionals.h
+ * OBSOLETE: Replaced by Conditionals_LCD.h and Conditionals_post.h
+ */
+#error "Old configurations? Please delete all #include lines from Configuration.h and Configuration_adv.h."

+ 528 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Conditionals_LCD.h

@@ -0,0 +1,528 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Conditionals_LCD.h
+ * Conditionals that need to be set before Configuration_adv.h or pins.h
+ */
+
+#ifndef CONDITIONALS_LCD_H // Get the LCD defines which are needed first
+#define CONDITIONALS_LCD_H
+
+#define LCD_HAS_DIRECTIONAL_BUTTONS (BUTTON_EXISTS(UP) || BUTTON_EXISTS(DWN) || BUTTON_EXISTS(LFT) || BUTTON_EXISTS(RT))
+
+#if ENABLED(CARTESIO_UI)
+
+  #define DOGLCD
+  #define ULTIPANEL
+  #define DEFAULT_LCD_CONTRAST 90
+  #define LCD_CONTRAST_MIN 60
+  #define LCD_CONTRAST_MAX 140
+
+#elif ENABLED(MAKRPANEL)
+
+  #define U8GLIB_ST7565_64128N
+
+#elif ENABLED(ZONESTAR_LCD)
+
+  #define REPRAPWORLD_KEYPAD
+  #define REPRAPWORLD_KEYPAD_MOVE_STEP 10.0
+  #define ADC_KEYPAD
+  #define ADC_KEY_NUM 8
+  #define ULTIPANEL
+
+  // this helps to implement ADC_KEYPAD menus
+  #define ENCODER_PULSES_PER_STEP 1
+  #define ENCODER_STEPS_PER_MENU_ITEM 1
+  #define ENCODER_FEEDRATE_DEADZONE 2
+  #define REVERSE_MENU_DIRECTION
+
+#elif ENABLED(ANET_FULL_GRAPHICS_LCD)
+
+  #define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
+
+#elif ENABLED(BQ_LCD_SMART_CONTROLLER)
+
+  #define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
+
+#elif ENABLED(miniVIKI) || ENABLED(VIKI2) || ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
+
+  #define ULTRA_LCD  //general LCD support, also 16x2
+  #define DOGLCD  // Support for SPI LCD 128x64 (Controller ST7565R graphic Display Family)
+  #define ULTIMAKERCONTROLLER //as available from the Ultimaker online store.
+
+  #if ENABLED(miniVIKI)
+    #define LCD_CONTRAST_MIN      75
+    #define LCD_CONTRAST_MAX     115
+    #define DEFAULT_LCD_CONTRAST  95
+    #define U8GLIB_ST7565_64128N
+  #elif ENABLED(VIKI2)
+    #define LCD_CONTRAST_MIN       0
+    #define LCD_CONTRAST_MAX     255
+    #define DEFAULT_LCD_CONTRAST 140
+    #define U8GLIB_ST7565_64128N
+  #elif ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
+    #define LCD_CONTRAST_MIN      90
+    #define LCD_CONTRAST_MAX     130
+    #define DEFAULT_LCD_CONTRAST 110
+    #define U8GLIB_LM6059_AF
+    #define SD_DETECT_INVERTED
+  #endif
+
+#elif ENABLED(OLED_PANEL_TINYBOY2)
+
+  #define U8GLIB_SSD1306
+  #define ULTIPANEL
+  #define REVERSE_ENCODER_DIRECTION
+  #define REVERSE_MENU_DIRECTION
+
+#elif ENABLED(RA_CONTROL_PANEL)
+
+  #define LCD_I2C_TYPE_PCA8574
+  #define LCD_I2C_ADDRESS 0x27   // I2C Address of the port expander
+  #define ULTIPANEL
+
+#elif ENABLED(REPRAPWORLD_GRAPHICAL_LCD)
+
+  #define DOGLCD
+  #define U8GLIB_ST7920
+  #define ULTIPANEL
+
+#elif ENABLED(CR10_STOCKDISPLAY)
+
+  #define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
+  #ifndef ST7920_DELAY_1
+    #define ST7920_DELAY_1 DELAY_NS(125)
+  #endif
+  #ifndef ST7920_DELAY_2
+    #define ST7920_DELAY_2 DELAY_NS(125)
+  #endif
+  #ifndef ST7920_DELAY_3
+    #define ST7920_DELAY_3 DELAY_NS(125)
+  #endif
+
+#elif ENABLED(MKS_12864OLED)
+
+  #define REPRAP_DISCOUNT_SMART_CONTROLLER
+  #define U8GLIB_SH1106
+
+#elif ENABLED(MKS_12864OLED_SSD1306)
+
+  #define REPRAP_DISCOUNT_SMART_CONTROLLER
+  #define U8GLIB_SSD1306
+
+#elif ENABLED(MKS_MINI_12864)
+
+  #define MINIPANEL
+
+#endif
+
+#if ENABLED(MAKRPANEL) || ENABLED(MINIPANEL)
+  #define DOGLCD
+  #define ULTIPANEL
+  #define DEFAULT_LCD_CONTRAST 17
+#endif
+
+#if ENABLED(ULTI_CONTROLLER)
+  #define U8GLIB_SSD1309
+  #define REVERSE_ENCODER_DIRECTION
+  #define LCD_RESET_PIN LCD_PINS_D6 //  This controller need a reset pin
+  #define LCD_CONTRAST_MIN 0
+  #define LCD_CONTRAST_MAX 254
+  #define DEFAULT_LCD_CONTRAST 127
+  #define ENCODER_PULSES_PER_STEP 2
+  #define ENCODER_STEPS_PER_MENU_ITEM 2
+#endif
+
+// Generic support for SSD1306 / SSD1309 / SH1106 OLED based LCDs.
+#if ENABLED(U8GLIB_SSD1306) || ENABLED(U8GLIB_SSD1309) || ENABLED(U8GLIB_SH1106)
+  #define ULTRA_LCD  //general LCD support, also 16x2
+  #define DOGLCD  // Support for I2C LCD 128x64 (Controller SSD1306 / SSD1309 / SH1106 graphic Display Family)
+#endif
+
+#if ENABLED(PANEL_ONE) || ENABLED(U8GLIB_SH1106)
+
+  #define ULTIMAKERCONTROLLER
+
+#elif ENABLED(MAKEBOARD_MINI_2_LINE_DISPLAY_1602)
+
+  #define REPRAP_DISCOUNT_SMART_CONTROLLER
+  #define LCD_WIDTH 16
+  #define LCD_HEIGHT 2
+
+#endif
+
+#if ENABLED(REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER) || ENABLED(LCD_FOR_MELZI) || ENABLED(SILVER_GATE_GLCD_CONTROLLER)
+  #define DOGLCD
+  #define U8GLIB_ST7920
+  #define REPRAP_DISCOUNT_SMART_CONTROLLER
+#endif
+
+#if ENABLED(ULTIMAKERCONTROLLER)              \
+ || ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER) \
+ || ENABLED(G3D_PANEL)                        \
+ || ENABLED(RIGIDBOT_PANEL)                   \
+ || ENABLED(ULTI_CONTROLLER)
+  #define ULTIPANEL
+#endif
+
+#if ENABLED(REPRAPWORLD_KEYPAD)
+  #define NEWPANEL
+  #if ENABLED(ULTIPANEL) && !defined(REPRAPWORLD_KEYPAD_MOVE_STEP)
+    #define REPRAPWORLD_KEYPAD_MOVE_STEP 1.0
+  #endif
+#endif
+
+/**
+ * I2C PANELS
+ */
+
+#if ENABLED(LCD_SAINSMART_I2C_1602) || ENABLED(LCD_SAINSMART_I2C_2004)
+
+  #define LCD_I2C_TYPE_PCF8575
+  #define LCD_I2C_ADDRESS 0x27   // I2C Address of the port expander
+  #define ULTRA_LCD
+
+  #if ENABLED(LCD_SAINSMART_I2C_2004)
+    #define LCD_WIDTH 20
+    #define LCD_HEIGHT 4
+  #endif
+
+#elif ENABLED(LCD_I2C_PANELOLU2)
+
+  // PANELOLU2 LCD with status LEDs, separate encoder and click inputs
+
+  #define LCD_I2C_TYPE_MCP23017
+  #define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
+  #define LCD_USE_I2C_BUZZER   // Enable buzzer on LCD (optional)
+  #define ULTIPANEL
+
+#elif ENABLED(LCD_I2C_VIKI)
+
+  /**
+   * Panucatt VIKI LCD with status LEDs, integrated click & L/R/U/P buttons, separate encoder inputs
+   *
+   * 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   // Enable buzzer on LCD (requires LiquidTWI2 v1.2.3 or later)
+  #define ULTIPANEL
+
+  #define ENCODER_FEEDRATE_DEADZONE 4
+
+  #define STD_ENCODER_PULSES_PER_STEP 1
+  #define STD_ENCODER_STEPS_PER_MENU_ITEM 2
+
+#elif ENABLED(G3D_PANEL)
+
+  #define STD_ENCODER_PULSES_PER_STEP 2
+  #define STD_ENCODER_STEPS_PER_MENU_ITEM 1
+
+#elif ENABLED(miniVIKI) || ENABLED(VIKI2) \
+   || ENABLED(ELB_FULL_GRAPHIC_CONTROLLER) \
+   || ENABLED(OLED_PANEL_TINYBOY2) \
+   || ENABLED(BQ_LCD_SMART_CONTROLLER) \
+   || ENABLED(LCD_I2C_PANELOLU2) \
+   || ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER)
+  #define STD_ENCODER_PULSES_PER_STEP 4
+  #define STD_ENCODER_STEPS_PER_MENU_ITEM 1
+#endif
+
+#ifndef STD_ENCODER_PULSES_PER_STEP
+  #define STD_ENCODER_PULSES_PER_STEP 5
+#endif
+#ifndef STD_ENCODER_STEPS_PER_MENU_ITEM
+  #define STD_ENCODER_STEPS_PER_MENU_ITEM 1
+#endif
+#ifndef ENCODER_PULSES_PER_STEP
+  #define ENCODER_PULSES_PER_STEP STD_ENCODER_PULSES_PER_STEP
+#endif
+#ifndef ENCODER_STEPS_PER_MENU_ITEM
+  #define ENCODER_STEPS_PER_MENU_ITEM STD_ENCODER_STEPS_PER_MENU_ITEM
+#endif
+#ifndef ENCODER_FEEDRATE_DEADZONE
+  #define ENCODER_FEEDRATE_DEADZONE 6
+#endif
+
+// Shift register panels
+// ---------------------
+// 2 wire Non-latching LCD SR from:
+// https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/schematics#!shiftregister-connection
+
+#if ENABLED(SAV_3DLCD)
+  #define SR_LCD_2W_NL    // Non latching 2 wire shift register
+  #define ULTIPANEL
+#endif
+
+#if ENABLED(DOGLCD) // Change number of lines to match the DOG graphic display
+  #ifndef LCD_WIDTH
+    #ifdef LCD_WIDTH_OVERRIDE
+      #define LCD_WIDTH LCD_WIDTH_OVERRIDE
+    #else
+      #define LCD_WIDTH 22
+    #endif
+  #endif
+  #ifndef LCD_HEIGHT
+    #define LCD_HEIGHT 5
+  #endif
+#endif
+
+#if ENABLED(NO_LCD_MENUS)
+  #undef ULTIPANEL
+#endif
+
+#if ENABLED(ULTIPANEL)
+  #define NEWPANEL  // Disable this if you actually have no click-encoder panel
+  #define ULTRA_LCD
+  #ifndef LCD_WIDTH
+    #define LCD_WIDTH 20
+  #endif
+  #ifndef LCD_HEIGHT
+    #define LCD_HEIGHT 4
+  #endif
+#elif ENABLED(ULTRA_LCD)  // no panel but just LCD
+  #ifndef LCD_WIDTH
+    #define LCD_WIDTH 16
+  #endif
+  #ifndef LCD_HEIGHT
+    #define LCD_HEIGHT 2
+  #endif
+#endif
+
+#if ENABLED(DOGLCD)
+  /* Custom characters defined in font dogm_font_data_Marlin_symbols.h / Marlin_symbols.fon */
+  // \x00 intentionally skipped to avoid problems in strings
+  #define LCD_STR_REFRESH     "\x01"
+  #define LCD_STR_FOLDER      "\x02"
+  #define LCD_STR_ARROW_RIGHT "\x03"
+  #define LCD_STR_UPLEVEL     "\x04"
+  #define LCD_STR_CLOCK       "\x05"
+  #define LCD_STR_FEEDRATE    "\x06"
+  #define LCD_STR_BEDTEMP     "\x07"
+  #define LCD_STR_THERMOMETER "\x08"
+  #define LCD_STR_DEGREE      "\x09"
+
+  #define LCD_STR_SPECIAL_MAX '\x09'
+  // Maximum here is 0x1F because 0x20 is ' ' (space) and the normal charsets begin.
+  // Better stay below 0x10 because DISPLAY_CHARSET_HD44780_WESTERN begins here.
+
+  // Symbol characters
+  #define LCD_STR_FILAM_DIA   "\xf8"
+  #define LCD_STR_FILAM_MUL   "\xa4"
+#else
+  // Custom characters defined in the first 8 characters of the LCD
+  #define LCD_BEDTEMP_CHAR     0x00  // Print only as a char. This will have 'unexpected' results when used in a string!
+  #define LCD_DEGREE_CHAR      0x01
+  #define LCD_STR_THERMOMETER "\x02" // Still used with string concatenation
+  #define LCD_UPLEVEL_CHAR     0x03
+  #define LCD_STR_REFRESH     "\x04"
+  #define LCD_STR_FOLDER      "\x05"
+  #define LCD_FEEDRATE_CHAR    0x06
+  #define LCD_CLOCK_CHAR       0x07
+  #define LCD_STR_ARROW_RIGHT ">"  /* from the default character set */
+#endif
+
+/**
+ * Default LCD contrast for dogm-like LCD displays
+ */
+#if ENABLED(DOGLCD)
+
+  #define HAS_LCD_CONTRAST ( \
+      ENABLED(MAKRPANEL) \
+   || ENABLED(CARTESIO_UI) \
+   || ENABLED(VIKI2) \
+   || ENABLED(miniVIKI) \
+   || ENABLED(ELB_FULL_GRAPHIC_CONTROLLER) \
+  )
+
+  #if HAS_LCD_CONTRAST
+    #ifndef LCD_CONTRAST_MIN
+      #define LCD_CONTRAST_MIN 0
+    #endif
+    #ifndef LCD_CONTRAST_MAX
+      #define LCD_CONTRAST_MAX 63
+    #endif
+    #ifndef DEFAULT_LCD_CONTRAST
+      #define DEFAULT_LCD_CONTRAST 32
+    #endif
+  #endif
+#endif
+
+// Boot screens
+#if DISABLED(ULTRA_LCD)
+  #undef SHOW_BOOTSCREEN
+#elif !defined(BOOTSCREEN_TIMEOUT)
+  #define BOOTSCREEN_TIMEOUT 2500
+#endif
+
+#define HAS_DEBUG_MENU (ENABLED(ULTIPANEL) && ENABLED(LCD_PROGRESS_BAR_TEST))
+
+/**
+ * Extruders have some combination of stepper motors and hotends
+ * so we separate these concepts into the defines:
+ *
+ *  EXTRUDERS    - Number of Selectable Tools
+ *  HOTENDS      - Number of hotends, whether connected or separate
+ *  E_STEPPERS   - Number of actual E stepper motors
+ *  E_MANUAL     - Number of E steppers for LCD move options
+ *
+ */
+#if ENABLED(SWITCHING_EXTRUDER)                               // One stepper for every two EXTRUDERS
+  #if EXTRUDERS > 4
+    #define E_STEPPERS    3
+  #elif EXTRUDERS > 2
+    #define E_STEPPERS    2
+  #else
+    #define E_STEPPERS    1
+  #endif
+  #if DISABLED(SWITCHING_NOZZLE)
+    #define HOTENDS       E_STEPPERS
+  #endif
+  #define E_MANUAL        EXTRUDERS
+#elif ENABLED(MIXING_EXTRUDER)
+  #define E_STEPPERS      MIXING_STEPPERS
+  #define E_MANUAL        1
+#else
+  #define E_STEPPERS      EXTRUDERS
+  #define E_MANUAL        EXTRUDERS
+#endif
+
+// No inactive extruders with MK2_MULTIPLEXER or SWITCHING_NOZZLE
+#if ENABLED(MK2_MULTIPLEXER) || ENABLED(SWITCHING_NOZZLE)
+  #undef DISABLE_INACTIVE_EXTRUDER
+#endif
+
+// MK2 Multiplexer forces SINGLENOZZLE
+#if ENABLED(MK2_MULTIPLEXER)
+  #define SINGLENOZZLE
+#endif
+
+#if ENABLED(SINGLENOZZLE) || ENABLED(MIXING_EXTRUDER)         // One hotend, one thermistor, no XY offset
+  #undef HOTENDS
+  #define HOTENDS       1
+  #undef TEMP_SENSOR_1_AS_REDUNDANT
+  #undef HOTEND_OFFSET_X
+  #undef HOTEND_OFFSET_Y
+#endif
+
+#ifndef HOTENDS
+  #define HOTENDS EXTRUDERS
+#endif
+
+#define DO_SWITCH_EXTRUDER (ENABLED(SWITCHING_EXTRUDER) && (DISABLED(SWITCHING_NOZZLE) || SWITCHING_EXTRUDER_SERVO_NR != SWITCHING_NOZZLE_SERVO_NR))
+
+/**
+ * DISTINCT_E_FACTORS affects how some E factors are accessed
+ */
+#if ENABLED(DISTINCT_E_FACTORS) && E_STEPPERS > 1
+  #define XYZE_N (XYZ + E_STEPPERS)
+  #if ENABLED(HANGPRINTER)
+    #define NUM_AXIS_N (ABCD + E_STEPPERS)
+  #else
+    #define NUM_AXIS_N (XYZ + E_STEPPERS)
+  #endif
+  #define E_AXIS_N (E_AXIS + extruder)
+#else
+  #undef DISTINCT_E_FACTORS
+  #define XYZE_N XYZE
+  #if ENABLED(HANGPRINTER)
+    #define NUM_AXIS_N ABCDE
+  #else
+    #define NUM_AXIS_N XYZE
+  #endif
+  #define E_AXIS_N E_AXIS
+#endif
+
+/**
+ * The BLTouch Probe emulates a servo probe
+ * and uses "special" angles for its state.
+ */
+#if ENABLED(BLTOUCH)
+  #ifndef Z_PROBE_SERVO_NR
+    #define Z_PROBE_SERVO_NR 0
+  #endif
+  #ifndef NUM_SERVOS
+    #define NUM_SERVOS (Z_PROBE_SERVO_NR + 1)
+  #endif
+  #undef DEACTIVATE_SERVOS_AFTER_MOVE
+  #if NUM_SERVOS == 1
+    #undef SERVO_DELAY
+    #define SERVO_DELAY { 50 }
+  #endif
+  #ifndef BLTOUCH_DELAY
+    #define BLTOUCH_DELAY 375
+  #endif
+  #undef Z_SERVO_ANGLES
+  #define Z_SERVO_ANGLES { BLTOUCH_DEPLOY, BLTOUCH_STOW }
+
+  #define BLTOUCH_DEPLOY    10
+  #define BLTOUCH_STOW      90
+  #define BLTOUCH_SELFTEST 120
+  #define BLTOUCH_RESET    160
+  #define _TEST_BLTOUCH(P) (READ(P##_PIN) != P##_ENDSTOP_INVERTING)
+
+  // Always disable probe pin inverting for BLTouch
+  #undef Z_MIN_PROBE_ENDSTOP_INVERTING
+  #define Z_MIN_PROBE_ENDSTOP_INVERTING false
+
+  #if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
+    #undef Z_MIN_ENDSTOP_INVERTING
+    #define Z_MIN_ENDSTOP_INVERTING Z_MIN_PROBE_ENDSTOP_INVERTING
+    #define TEST_BLTOUCH() _TEST_BLTOUCH(Z_MIN)
+  #else
+    #define TEST_BLTOUCH() _TEST_BLTOUCH(Z_MIN_PROBE)
+  #endif
+#endif
+
+/**
+ * Set a flag for a servo probe
+ */
+#define HAS_Z_SERVO_PROBE (defined(Z_PROBE_SERVO_NR) && Z_PROBE_SERVO_NR >= 0)
+
+/**
+ * Set flags for enabled probes
+ */
+#define HAS_BED_PROBE (ENABLED(FIX_MOUNTED_PROBE) || ENABLED(Z_PROBE_ALLEN_KEY) || HAS_Z_SERVO_PROBE || ENABLED(Z_PROBE_SLED) || ENABLED(SOLENOID_PROBE))
+#define PROBE_SELECTED (HAS_BED_PROBE || ENABLED(PROBE_MANUALLY) || ENABLED(MESH_BED_LEVELING))
+
+#if !HAS_BED_PROBE
+  // Clear probe pin settings when no probe is selected
+  #undef Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN
+  #undef Z_MIN_PROBE_ENDSTOP
+#elif ENABLED(Z_PROBE_ALLEN_KEY)
+  // Extra test for Allen Key Probe
+  #define PROBE_IS_TRIGGERED_WHEN_STOWED_TEST
+#endif
+
+#define HOMING_Z_WITH_PROBE (HAS_BED_PROBE && Z_HOME_DIR < 0 && ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN))
+
+#define HAS_SOFTWARE_ENDSTOPS (ENABLED(MIN_SOFTWARE_ENDSTOPS) || ENABLED(MAX_SOFTWARE_ENDSTOPS))
+#define HAS_RESUME_CONTINUE (ENABLED(NEWPANEL) || ENABLED(EMERGENCY_PARSER))
+#define HAS_COLOR_LEDS (ENABLED(BLINKM) || ENABLED(RGB_LED) || ENABLED(RGBW_LED) || ENABLED(PCA9632) || ENABLED(NEOPIXEL_LED))
+
+#define USE_MARLINSERIAL !(defined(__AVR__) && defined(USBCON))
+
+#endif // CONDITIONALS_LCD_H

File diff suppressed because it is too large
+ 1417 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Conditionals_post.h


File diff suppressed because it is too large
+ 1957 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Configuration.h


File diff suppressed because it is too large
+ 1663 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Configuration_adv.h


+ 920 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/G26_Mesh_Validation_Tool.cpp

@@ -0,0 +1,920 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Marlin Firmware -- G26 - Mesh Validation Tool
+ */
+
+#include "MarlinConfig.h"
+
+#if ENABLED(G26_MESH_VALIDATION)
+
+  #include "Marlin.h"
+  #include "planner.h"
+  #include "stepper.h"
+  #include "temperature.h"
+  #include "ultralcd.h"
+  #include "parser.h"
+  #include "serial.h"
+  #include "bitmap_flags.h"
+
+  #if ENABLED(MESH_BED_LEVELING)
+    #include "mesh_bed_leveling.h"
+  #elif ENABLED(AUTO_BED_LEVELING_UBL)
+    #include "ubl.h"
+  #endif
+
+  #define EXTRUSION_MULTIPLIER 1.0
+  #define RETRACTION_MULTIPLIER 1.0
+  #define PRIME_LENGTH 10.0
+  #define OOZE_AMOUNT 0.3
+
+  #define INTERSECTION_CIRCLE_RADIUS 5
+  #define CROSSHAIRS_SIZE 3
+
+  #if CROSSHAIRS_SIZE >= INTERSECTION_CIRCLE_RADIUS
+    #error "CROSSHAIRS_SIZE must be less than INTERSECTION_CIRCLE_RADIUS."
+  #endif
+
+  #define G26_OK false
+  #define G26_ERR true
+
+  /**
+   *   G26 Mesh Validation Tool
+   *
+   *   G26 is a Mesh Validation Tool intended to provide support for the Marlin Unified Bed Leveling System.
+   *   In order to fully utilize and benefit from the Marlin Unified Bed Leveling System an accurate Mesh must
+   *   be defined. G29 is designed to allow the user to quickly validate the correctness of her Mesh. It will
+   *   first heat the bed and nozzle. It will then print lines and circles along the Mesh Cell boundaries and
+   *   the intersections of those lines (respectively).
+   *
+   *   This action allows the user to immediately see where the Mesh is properly defined and where it needs to
+   *   be edited. The command will generate the Mesh lines closest to the nozzle's starting position. Alternatively
+   *   the user can specify the X and Y position of interest with command parameters. This allows the user to
+   *   focus on a particular area of the Mesh where attention is needed.
+   *
+   *   B #  Bed         Set the Bed Temperature. If not specified, a default of 60 C. will be assumed.
+   *
+   *   C    Current     When searching for Mesh Intersection points to draw, use the current nozzle location
+   *                    as the base for any distance comparison.
+   *
+   *   D    Disable     Disable the Unified Bed Leveling System. In the normal case the user is invoking this
+   *                    command to see how well a Mesh as been adjusted to match a print surface. In order to do
+   *                    this the Unified Bed Leveling System is turned on by the G26 command. The D parameter
+   *                    alters the command's normal behaviour and disables the Unified Bed Leveling System even if
+   *                    it is on.
+   *
+   *   H #  Hotend      Set the Nozzle Temperature. If not specified, a default of 205 C. will be assumed.
+   *
+   *   F #  Filament    Used to specify the diameter of the filament being used. If not specified
+   *                    1.75mm filament is assumed. If you are not getting acceptable results by using the
+   *                    'correct' numbers, you can scale this number up or down a little bit to change the amount
+   *                    of filament that is being extruded during the printing of the various lines on the bed.
+   *
+   *   K    Keep-On     Keep the heaters turned on at the end of the command.
+   *
+   *   L #  Layer       Layer height. (Height of nozzle above bed)  If not specified .20mm will be used.
+   *
+   *   O #  Ooooze      How much your nozzle will Ooooze filament while getting in position to print. This
+   *                    is over kill, but using this parameter will let you get the very first 'circle' perfect
+   *                    so you have a trophy to peel off of the bed and hang up to show how perfectly you have your
+   *                    Mesh calibrated. If not specified, a filament length of .3mm is assumed.
+   *
+   *   P #  Prime       Prime the nozzle with specified length of filament. If this parameter is not
+   *                    given, no prime action will take place. If the parameter specifies an amount, that much
+   *                    will be purged before continuing. If no amount is specified the command will start
+   *                    purging filament until the user provides an LCD Click and then it will continue with
+   *                    printing the Mesh. You can carefully remove the spent filament with a needle nose
+   *                    pliers while holding the LCD Click wheel in a depressed state. If you do not have
+   *                    an LCD, you must specify a value if you use P.
+   *
+   *   Q #  Multiplier  Retraction Multiplier. Normally not needed. Retraction defaults to 1.0mm and
+   *                    un-retraction is at 1.2mm   These numbers will be scaled by the specified amount
+   *
+   *   R #  Repeat      Prints the number of patterns given as a parameter, starting at the current location.
+   *                    If a parameter isn't given, every point will be printed unless G26 is interrupted.
+   *                    This works the same way that the UBL G29 P4 R parameter works.
+   *
+   *                    NOTE:  If you do not have an LCD, you -must- specify R. This is to ensure that you are
+   *                    aware that there's some risk associated with printing without the ability to abort in
+   *                    cases where mesh point Z value may be inaccurate. As above, if you do not include a
+   *                    parameter, every point will be printed.
+   *
+   *   S #  Nozzle      Used to control the size of nozzle diameter. If not specified, a .4mm nozzle is assumed.
+   *
+   *   U #  Random      Randomize the order that the circles are drawn on the bed. The search for the closest
+   *                    undrawn cicle is still done. But the distance to the location for each circle has a
+   *                    random number of the size specified added to it. Specifying S50 will give an interesting
+   *                    deviation from the normal behaviour on a 10 x 10 Mesh.
+   *
+   *   X #  X Coord.    Specify the starting location of the drawing activity.
+   *
+   *   Y #  Y Coord.    Specify the starting location of the drawing activity.
+   */
+
+  // External references
+
+  extern Planner planner;
+
+  // Private functions
+
+  static uint16_t circle_flags[16], horizontal_mesh_line_flags[16], vertical_mesh_line_flags[16];
+  float g26_e_axis_feedrate = 0.025,
+        random_deviation = 0.0;
+
+  static bool g26_retracted = false; // Track the retracted state of the nozzle so mismatched
+                                     // retracts/recovers won't result in a bad state.
+
+  static float g26_extrusion_multiplier,
+               g26_retraction_multiplier,
+               g26_layer_height,
+               g26_prime_length,
+               g26_x_pos, g26_y_pos;
+
+  static int16_t g26_bed_temp,
+                 g26_hotend_temp;
+
+  static int8_t g26_prime_flag;
+
+  #if ENABLED(ULTIPANEL)
+
+    /**
+     * If the LCD is clicked, cancel, wait for release, return true
+     */
+    bool user_canceled() {
+      if (!is_lcd_clicked()) return false; // Return if the button isn't pressed
+      lcd_setstatusPGM(PSTR("Mesh Validation Stopped."), 99);
+      #if ENABLED(ULTIPANEL)
+        lcd_quick_feedback(true);
+      #endif
+      wait_for_release();
+      return true;
+    }
+
+    bool exit_from_g26() {
+      lcd_setstatusPGM(PSTR("Leaving G26"), -1);
+      wait_for_release();
+      return G26_ERR;
+    }
+
+  #endif
+
+  void G26_line_to_destination(const float &feed_rate) {
+    const float save_feedrate = feedrate_mm_s;
+    feedrate_mm_s = feed_rate;
+    prepare_move_to_destination();  // will ultimately call ubl.line_to_destination_cartesian or ubl.prepare_linear_move_to for UBL_SEGMENTED
+    feedrate_mm_s = save_feedrate;
+  }
+
+  void move_to(const float &rx, const float &ry, const float &z, const float &e_delta) {
+    float feed_value;
+    static float last_z = -999.99;
+
+    bool has_xy_component = (rx != current_position[X_AXIS] || ry != current_position[Y_AXIS]); // Check if X or Y is involved in the movement.
+
+    if (z != last_z) {
+      last_z = z;
+      feed_value = planner.max_feedrate_mm_s[Z_AXIS]/(3.0);  // Base the feed rate off of the configured Z_AXIS feed rate
+
+      destination[X_AXIS] = current_position[X_AXIS];
+      destination[Y_AXIS] = current_position[Y_AXIS];
+      destination[Z_AXIS] = z;                          // We know the last_z==z or we wouldn't be in this block of code.
+      destination[E_CART] = current_position[E_CART];
+
+      G26_line_to_destination(feed_value);
+      set_destination_from_current();
+    }
+
+    // Check if X or Y is involved in the movement.
+    // Yes: a 'normal' movement. No: a retract() or recover()
+    feed_value = has_xy_component ? PLANNER_XY_FEEDRATE() / 10.0 : planner.max_feedrate_mm_s[E_AXIS] / 1.5;
+
+    if (g26_debug_flag) SERIAL_ECHOLNPAIR("in move_to() feed_value for XY:", feed_value);
+
+    destination[X_AXIS] = rx;
+    destination[Y_AXIS] = ry;
+    destination[E_CART] += e_delta;
+
+    G26_line_to_destination(feed_value);
+    set_destination_from_current();
+  }
+
+  FORCE_INLINE void move_to(const float where[XYZE], const float &de) { move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], de); }
+
+  void retract_filament(const float where[XYZE]) {
+    if (!g26_retracted) { // Only retract if we are not already retracted!
+      g26_retracted = true;
+      move_to(where, -1.0 * g26_retraction_multiplier);
+    }
+  }
+
+  void recover_filament(const float where[XYZE]) {
+    if (g26_retracted) { // Only un-retract if we are retracted.
+      move_to(where, 1.2 * g26_retraction_multiplier);
+      g26_retracted = false;
+    }
+  }
+
+  /**
+   * Prime the nozzle if needed. Return true on error.
+   */
+  inline bool prime_nozzle() {
+
+    #if ENABLED(ULTIPANEL)
+      float Total_Prime = 0.0;
+
+      if (g26_prime_flag == -1) {  // The user wants to control how much filament gets purged
+
+        lcd_external_control = true;
+        lcd_setstatusPGM(PSTR("User-Controlled Prime"), 99);
+        lcd_chirp();
+
+        set_destination_from_current();
+
+        recover_filament(destination); // Make sure G26 doesn't think the filament is retracted().
+
+        while (!is_lcd_clicked()) {
+          lcd_chirp();
+          destination[E_CART] += 0.25;
+          #ifdef PREVENT_LENGTHY_EXTRUDE
+            Total_Prime += 0.25;
+            if (Total_Prime >= EXTRUDE_MAXLENGTH) return G26_ERR;
+          #endif
+          G26_line_to_destination(planner.max_feedrate_mm_s[E_AXIS] / 15.0);
+          set_destination_from_current();
+          planner.synchronize();    // Without this synchronize, the purge is more consistent,
+                                    // but because the planner has a buffer, we won't be able
+                                    // to stop as quickly. So we put up with the less smooth
+                                    // action to give the user a more responsive 'Stop'.
+
+          SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
+        }
+
+        wait_for_release();
+
+        lcd_setstatusPGM(PSTR("Done Priming"), 99);
+        lcd_quick_feedback(true);
+        lcd_external_control = false;
+      }
+      else
+    #endif
+    {
+      #if ENABLED(ULTRA_LCD)
+        lcd_setstatusPGM(PSTR("Fixed Length Prime."), 99);
+        lcd_quick_feedback(true);
+      #endif
+      set_destination_from_current();
+      destination[E_CART] += g26_prime_length;
+      G26_line_to_destination(planner.max_feedrate_mm_s[E_AXIS] / 15.0);
+      set_destination_from_current();
+      retract_filament(destination);
+    }
+
+    return G26_OK;
+  }
+
+  mesh_index_pair find_closest_circle_to_print(const float &X, const float &Y) {
+    float closest = 99999.99;
+    mesh_index_pair return_val;
+
+    return_val.x_index = return_val.y_index = -1;
+
+    for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
+      for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
+        if (!is_bitmap_set(circle_flags, i, j)) {
+          const float mx = _GET_MESH_X(i),  // We found a circle that needs to be printed
+                      my = _GET_MESH_Y(j);
+
+          // Get the distance to this intersection
+          float f = HYPOT(X - mx, Y - my);
+
+          // It is possible that we are being called with the values
+          // to let us find the closest circle to the start position.
+          // But if this is not the case, add a small weighting to the
+          // distance calculation to help it choose a better place to continue.
+          f += HYPOT(g26_x_pos - mx, g26_y_pos - my) / 15.0;
+
+          // Add in the specified amount of Random Noise to our search
+          if (random_deviation > 1.0)
+            f += random(0.0, random_deviation);
+
+          if (f < closest) {
+            closest = f;              // We found a closer location that is still
+            return_val.x_index = i;   // un-printed  --- save the data for it
+            return_val.y_index = j;
+            return_val.distance = closest;
+          }
+        }
+      }
+    }
+    bitmap_set(circle_flags, return_val.x_index, return_val.y_index);   // Mark this location as done.
+    return return_val;
+  }
+
+  /**
+   * print_line_from_here_to_there() takes two cartesian coordinates and draws a line from one
+   * to the other. But there are really three sets of coordinates involved. The first coordinate
+   * is the present location of the nozzle. We don't necessarily want to print from this location.
+   * We first need to move the nozzle to the start of line segment where we want to print. Once
+   * there, we can use the two coordinates supplied to draw the line.
+   *
+   * Note:  Although we assume the first set of coordinates is the start of the line and the second
+   * set of coordinates is the end of the line, it does not always work out that way. This function
+   * optimizes the movement to minimize the travel distance before it can start printing. This saves
+   * a lot of time and eliminates a lot of nonsensical movement of the nozzle. However, it does
+   * cause a lot of very little short retracement of th nozzle when it draws the very first line
+   * segment of a 'circle'. The time this requires is very short and is easily saved by the other
+   * cases where the optimization comes into play.
+   */
+  void print_line_from_here_to_there(const float &sx, const float &sy, const float &sz, const float &ex, const float &ey, const float &ez) {
+    const float dx_s = current_position[X_AXIS] - sx,   // find our distance from the start of the actual line segment
+                dy_s = current_position[Y_AXIS] - sy,
+                dist_start = HYPOT2(dx_s, dy_s),        // We don't need to do a sqrt(), we can compare the distance^2
+                                                        // to save computation time
+                dx_e = current_position[X_AXIS] - ex,   // find our distance from the end of the actual line segment
+                dy_e = current_position[Y_AXIS] - ey,
+                dist_end = HYPOT2(dx_e, dy_e),
+
+                line_length = HYPOT(ex - sx, ey - sy);
+
+    // If the end point of the line is closer to the nozzle, flip the direction,
+    // moving from the end to the start. On very small lines the optimization isn't worth it.
+    if (dist_end < dist_start && (INTERSECTION_CIRCLE_RADIUS) < ABS(line_length))
+      return print_line_from_here_to_there(ex, ey, ez, sx, sy, sz);
+
+    // Decide whether to retract & bump
+
+    if (dist_start > 2.0) {
+      retract_filament(destination);
+      //todo:  parameterize the bump height with a define
+      move_to(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + 0.500, 0.0);  // Z bump to minimize scraping
+      move_to(sx, sy, sz + 0.500, 0.0); // Get to the starting point with no extrusion while bumped
+    }
+
+    move_to(sx, sy, sz, 0.0); // Get to the starting point with no extrusion / un-Z bump
+
+    const float e_pos_delta = line_length * g26_e_axis_feedrate * g26_extrusion_multiplier;
+
+    recover_filament(destination);
+    move_to(ex, ey, ez, e_pos_delta);  // Get to the ending point with an appropriate amount of extrusion
+  }
+
+  inline bool look_for_lines_to_connect() {
+    float sx, sy, ex, ey;
+
+    for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
+      for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
+
+        #if ENABLED(ULTIPANEL)
+          if (user_canceled()) return true;     // Check if the user wants to stop the Mesh Validation
+        #endif
+
+        if (i < GRID_MAX_POINTS_X) { // We can't connect to anything to the right than GRID_MAX_POINTS_X.
+                                     // This is already a half circle because we are at the edge of the bed.
+
+          if (is_bitmap_set(circle_flags, i, j) && is_bitmap_set(circle_flags, i + 1, j)) { // check if we can do a line to the left
+            if (!is_bitmap_set(horizontal_mesh_line_flags, i, j)) {
+
+              //
+              // We found two circles that need a horizontal line to connect them
+              // Print it!
+              //
+              sx = _GET_MESH_X(  i  ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // right edge
+              ex = _GET_MESH_X(i + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // left edge
+
+              sx = constrain(sx, X_MIN_POS + 1, X_MAX_POS - 1);
+              sy = ey = constrain(_GET_MESH_Y(j), Y_MIN_POS + 1, Y_MAX_POS - 1);
+              ex = constrain(ex, X_MIN_POS + 1, X_MAX_POS - 1);
+
+              if (position_is_reachable(sx, sy) && position_is_reachable(ex, ey)) {
+
+                if (g26_debug_flag) {
+                  SERIAL_ECHOPAIR(" Connecting with horizontal line (sx=", sx);
+                  SERIAL_ECHOPAIR(", sy=", sy);
+                  SERIAL_ECHOPAIR(") -> (ex=", ex);
+                  SERIAL_ECHOPAIR(", ey=", ey);
+                  SERIAL_CHAR(')');
+                  SERIAL_EOL();
+                  //debug_current_and_destination(PSTR("Connecting horizontal line."));
+                }
+                print_line_from_here_to_there(sx, sy, g26_layer_height, ex, ey, g26_layer_height);
+              }
+              bitmap_set(horizontal_mesh_line_flags, i, j);   // Mark it as done so we don't do it again, even if we skipped it
+            }
+          }
+
+          if (j < GRID_MAX_POINTS_Y) { // We can't connect to anything further back than GRID_MAX_POINTS_Y.
+                                           // This is already a half circle because we are at the edge  of the bed.
+
+            if (is_bitmap_set(circle_flags, i, j) && is_bitmap_set(circle_flags, i, j + 1)) { // check if we can do a line straight down
+              if (!is_bitmap_set( vertical_mesh_line_flags, i, j)) {
+                //
+                // We found two circles that need a vertical line to connect them
+                // Print it!
+                //
+                sy = _GET_MESH_Y(  j  ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // top edge
+                ey = _GET_MESH_Y(j + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // bottom edge
+
+                sx = ex = constrain(_GET_MESH_X(i), X_MIN_POS + 1, X_MAX_POS - 1);
+                sy = constrain(sy, Y_MIN_POS + 1, Y_MAX_POS - 1);
+                ey = constrain(ey, Y_MIN_POS + 1, Y_MAX_POS - 1);
+
+                if (position_is_reachable(sx, sy) && position_is_reachable(ex, ey)) {
+
+                  if (g26_debug_flag) {
+                    SERIAL_ECHOPAIR(" Connecting with vertical line (sx=", sx);
+                    SERIAL_ECHOPAIR(", sy=", sy);
+                    SERIAL_ECHOPAIR(") -> (ex=", ex);
+                    SERIAL_ECHOPAIR(", ey=", ey);
+                    SERIAL_CHAR(')');
+                    SERIAL_EOL();
+
+                    #if ENABLED(AUTO_BED_LEVELING_UBL)
+                      debug_current_and_destination(PSTR("Connecting vertical line."));
+                    #endif
+                  }
+                  print_line_from_here_to_there(sx, sy, g26_layer_height, ex, ey, g26_layer_height);
+                }
+                bitmap_set(vertical_mesh_line_flags, i, j);   // Mark it as done so we don't do it again, even if skipped
+              }
+            }
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Turn on the bed and nozzle heat and
+   * wait for them to get up to temperature.
+   */
+  inline bool turn_on_heaters() {
+    millis_t next = millis() + 5000UL;
+    #if HAS_HEATED_BED
+      #if ENABLED(ULTRA_LCD)
+        if (g26_bed_temp > 25) {
+          lcd_setstatusPGM(PSTR("G26 Heating Bed."), 99);
+          lcd_quick_feedback(true);
+          #if ENABLED(ULTIPANEL)
+            lcd_external_control = true;
+          #endif
+      #endif
+          thermalManager.setTargetBed(g26_bed_temp);
+          while (ABS(thermalManager.degBed() - g26_bed_temp) > 3) {
+
+            #if ENABLED(ULTIPANEL)
+              if (is_lcd_clicked()) return exit_from_g26();
+            #endif
+
+            if (ELAPSED(millis(), next)) {
+              next = millis() + 5000UL;
+              thermalManager.print_heaterstates();
+              SERIAL_EOL();
+            }
+            idle();
+            SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
+          }
+      #if ENABLED(ULTRA_LCD)
+        }
+        lcd_setstatusPGM(PSTR("G26 Heating Nozzle."), 99);
+        lcd_quick_feedback(true);
+      #endif
+    #endif
+
+    // Start heating the nozzle and wait for it to reach temperature.
+    thermalManager.setTargetHotend(g26_hotend_temp, 0);
+    while (ABS(thermalManager.degHotend(0) - g26_hotend_temp) > 3) {
+
+      #if ENABLED(ULTIPANEL)
+        if (is_lcd_clicked()) return exit_from_g26();
+      #endif
+
+      if (ELAPSED(millis(), next)) {
+        next = millis() + 5000UL;
+        thermalManager.print_heaterstates();
+        SERIAL_EOL();
+      }
+      idle();
+
+      SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
+    }
+    #if ENABLED(ULTRA_LCD)
+      lcd_reset_status();
+      lcd_quick_feedback(true);
+    #endif
+
+    return G26_OK;
+  }
+
+  float valid_trig_angle(float d) {
+    while (d > 360.0) d -= 360.0;
+    while (d < 0.0) d += 360.0;
+    return d;
+  }
+
+  /**
+   * G26: Mesh Validation Pattern generation.
+   *
+   * Used to interactively edit the mesh by placing the
+   * nozzle in a problem area and doing a G29 P4 R command.
+   *
+   * Parameters:
+   *
+   *  B  Bed Temperature
+   *  C  Continue from the Closest mesh point
+   *  D  Disable leveling before starting
+   *  F  Filament diameter
+   *  H  Hotend Temperature
+   *  K  Keep heaters on when completed
+   *  L  Layer Height
+   *  O  Ooze extrusion length
+   *  P  Prime length
+   *  Q  Retraction multiplier
+   *  R  Repetitions (number of grid points)
+   *  S  Nozzle Size (diameter) in mm
+   *  U  Random deviation (50 if no value given)
+   *  X  X position
+   *  Y  Y position
+   */
+  void gcode_G26() {
+    SERIAL_ECHOLNPGM("G26 command started. Waiting for heater(s).");
+
+    // Don't allow Mesh Validation without homing first,
+    // or if the parameter parsing did not go OK, abort
+    if (axis_unhomed_error()) return;
+
+    g26_extrusion_multiplier    = EXTRUSION_MULTIPLIER;
+    g26_retraction_multiplier   = RETRACTION_MULTIPLIER;
+    g26_layer_height            = MESH_TEST_LAYER_HEIGHT;
+    g26_prime_length            = PRIME_LENGTH;
+    g26_bed_temp                = MESH_TEST_BED_TEMP;
+    g26_hotend_temp             = MESH_TEST_HOTEND_TEMP;
+    g26_prime_flag              = 0;
+
+    float g26_nozzle            = MESH_TEST_NOZZLE_SIZE,
+          g26_filament_diameter = DEFAULT_NOMINAL_FILAMENT_DIA,
+          g26_ooze_amount       = parser.linearval('O', OOZE_AMOUNT);
+
+    bool g26_continue_with_closest = parser.boolval('C'),
+         g26_keep_heaters_on       = parser.boolval('K');
+
+    if (parser.seenval('B')) {
+      g26_bed_temp = parser.value_celsius();
+      if (g26_bed_temp && !WITHIN(g26_bed_temp, 40, 140)) {
+        SERIAL_PROTOCOLLNPGM("?Specified bed temperature not plausible (40-140C).");
+        return;
+      }
+    }
+
+    if (parser.seenval('L')) {
+      g26_layer_height = parser.value_linear_units();
+      if (!WITHIN(g26_layer_height, 0.0, 2.0)) {
+        SERIAL_PROTOCOLLNPGM("?Specified layer height not plausible.");
+        return;
+      }
+    }
+
+    if (parser.seen('Q')) {
+      if (parser.has_value()) {
+        g26_retraction_multiplier = parser.value_float();
+        if (!WITHIN(g26_retraction_multiplier, 0.05, 15.0)) {
+          SERIAL_PROTOCOLLNPGM("?Specified Retraction Multiplier not plausible.");
+          return;
+        }
+      }
+      else {
+        SERIAL_PROTOCOLLNPGM("?Retraction Multiplier must be specified.");
+        return;
+      }
+    }
+
+    if (parser.seenval('S')) {
+      g26_nozzle = parser.value_float();
+      if (!WITHIN(g26_nozzle, 0.1, 1.0)) {
+        SERIAL_PROTOCOLLNPGM("?Specified nozzle size not plausible.");
+        return;
+      }
+    }
+
+    if (parser.seen('P')) {
+      if (!parser.has_value()) {
+        #if ENABLED(ULTIPANEL)
+          g26_prime_flag = -1;
+        #else
+          SERIAL_PROTOCOLLNPGM("?Prime length must be specified when not using an LCD.");
+          return;
+        #endif
+      }
+      else {
+        g26_prime_flag++;
+        g26_prime_length = parser.value_linear_units();
+        if (!WITHIN(g26_prime_length, 0.0, 25.0)) {
+          SERIAL_PROTOCOLLNPGM("?Specified prime length not plausible.");
+          return;
+        }
+      }
+    }
+
+    if (parser.seenval('F')) {
+      g26_filament_diameter = parser.value_linear_units();
+      if (!WITHIN(g26_filament_diameter, 1.0, 4.0)) {
+        SERIAL_PROTOCOLLNPGM("?Specified filament size not plausible.");
+        return;
+      }
+    }
+    g26_extrusion_multiplier *= sq(1.75) / sq(g26_filament_diameter); // If we aren't using 1.75mm filament, we need to
+                                                                      // scale up or down the length needed to get the
+                                                                      // same volume of filament
+
+    g26_extrusion_multiplier *= g26_filament_diameter * sq(g26_nozzle) / sq(0.3); // Scale up by nozzle size
+
+    if (parser.seenval('H')) {
+      g26_hotend_temp = parser.value_celsius();
+      if (!WITHIN(g26_hotend_temp, 165, 280)) {
+        SERIAL_PROTOCOLLNPGM("?Specified nozzle temperature not plausible.");
+        return;
+      }
+    }
+
+    if (parser.seen('U')) {
+      randomSeed(millis());
+      // This setting will persist for the next G26
+      random_deviation = parser.has_value() ? parser.value_float() : 50.0;
+    }
+
+    int16_t g26_repeats;
+    #if ENABLED(ULTIPANEL)
+      g26_repeats = parser.intval('R', GRID_MAX_POINTS + 1);
+    #else
+      if (!parser.seen('R')) {
+        SERIAL_PROTOCOLLNPGM("?(R)epeat must be specified when not using an LCD.");
+        return;
+      }
+      else
+        g26_repeats = parser.has_value() ? parser.value_int() : GRID_MAX_POINTS + 1;
+    #endif
+    if (g26_repeats < 1) {
+      SERIAL_PROTOCOLLNPGM("?(R)epeat value not plausible; must be at least 1.");
+      return;
+    }
+
+    g26_x_pos = parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position[X_AXIS];
+    g26_y_pos = parser.seenval('Y') ? RAW_Y_POSITION(parser.value_linear_units()) : current_position[Y_AXIS];
+    if (!position_is_reachable(g26_x_pos, g26_y_pos)) {
+      SERIAL_PROTOCOLLNPGM("?Specified X,Y coordinate out of bounds.");
+      return;
+    }
+
+    /**
+     * Wait until all parameters are verified before altering the state!
+     */
+    set_bed_leveling_enabled(!parser.seen('D'));
+
+    if (current_position[Z_AXIS] < Z_CLEARANCE_BETWEEN_PROBES) {
+      do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
+      set_current_from_destination();
+    }
+
+    if (turn_on_heaters() != G26_OK) goto LEAVE;
+
+    current_position[E_CART] = 0.0;
+    sync_plan_position_e();
+
+    if (g26_prime_flag && prime_nozzle() != G26_OK) goto LEAVE;
+
+    /**
+     *  Bed is preheated
+     *
+     *  Nozzle is at temperature
+     *
+     *  Filament is primed!
+     *
+     *  It's  "Show Time" !!!
+     */
+
+    ZERO(circle_flags);
+    ZERO(horizontal_mesh_line_flags);
+    ZERO(vertical_mesh_line_flags);
+
+    // Move nozzle to the specified height for the first layer
+    set_destination_from_current();
+    destination[Z_AXIS] = g26_layer_height;
+    move_to(destination, 0.0);
+    move_to(destination, g26_ooze_amount);
+
+    #if ENABLED(ULTIPANEL)
+      lcd_external_control = true;
+    #endif
+
+    //debug_current_and_destination(PSTR("Starting G26 Mesh Validation Pattern."));
+
+    #if DISABLED(ARC_SUPPORT)
+
+      /**
+       * Pre-generate radius offset values at 30 degree intervals to reduce CPU load.
+       */
+      #define A_INT 30
+      #define _ANGS (360 / A_INT)
+      #define A_CNT (_ANGS / 2)
+      #define _IND(A) ((A + _ANGS * 8) % _ANGS)
+      #define _COS(A) (trig_table[_IND(A) % A_CNT] * (_IND(A) >= A_CNT ? -1 : 1))
+      #define _SIN(A) (-_COS((A + A_CNT / 2) % _ANGS))
+      #if A_CNT & 1
+        #error "A_CNT must be a positive value. Please change A_INT."
+      #endif
+      float trig_table[A_CNT];
+      for (uint8_t i = 0; i < A_CNT; i++)
+        trig_table[i] = INTERSECTION_CIRCLE_RADIUS * cos(RADIANS(i * A_INT));
+
+    #endif // !ARC_SUPPORT
+
+    mesh_index_pair location;
+    do {
+       location = g26_continue_with_closest
+        ? find_closest_circle_to_print(current_position[X_AXIS], current_position[Y_AXIS])
+        : find_closest_circle_to_print(g26_x_pos, g26_y_pos); // Find the closest Mesh Intersection to where we are now.
+
+      if (location.x_index >= 0 && location.y_index >= 0) {
+        const float circle_x = _GET_MESH_X(location.x_index),
+                    circle_y = _GET_MESH_Y(location.y_index);
+
+        // If this mesh location is outside the printable_radius, skip it.
+        if (!position_is_reachable(circle_x, circle_y)) continue;
+
+        // Determine where to start and end the circle,
+        // which is always drawn counter-clockwise.
+        const uint8_t xi = location.x_index, yi = location.y_index;
+        const bool f = yi == 0, r = xi >= GRID_MAX_POINTS_X - 1, b = yi >= GRID_MAX_POINTS_Y - 1;
+
+        #if ENABLED(ARC_SUPPORT)
+
+          #define ARC_LENGTH(quarters)  (INTERSECTION_CIRCLE_RADIUS * M_PI * (quarters) / 2)
+          float sx = circle_x + INTERSECTION_CIRCLE_RADIUS,   // default to full circle
+                ex = circle_x + INTERSECTION_CIRCLE_RADIUS,
+                sy = circle_y, ey = circle_y,
+                arc_length = ARC_LENGTH(4);
+
+          // Figure out where to start and end the arc - we always print counterclockwise
+          if (xi == 0) {                             // left edge
+            sx = f ? circle_x + INTERSECTION_CIRCLE_RADIUS : circle_x;
+            ex = b ? circle_x + INTERSECTION_CIRCLE_RADIUS : circle_x;
+            sy = f ? circle_y : circle_y - INTERSECTION_CIRCLE_RADIUS;
+            ey = b ? circle_y : circle_y + INTERSECTION_CIRCLE_RADIUS;
+            arc_length = (f || b) ? ARC_LENGTH(1) : ARC_LENGTH(2);
+          }
+          else if (r) {                             // right edge
+            sx = b ? circle_x - INTERSECTION_CIRCLE_RADIUS : circle_x;
+            ex = f ? circle_x - INTERSECTION_CIRCLE_RADIUS : circle_x;
+            sy = b ? circle_y : circle_y + INTERSECTION_CIRCLE_RADIUS;
+            ey = f ? circle_y : circle_y - INTERSECTION_CIRCLE_RADIUS;
+            arc_length = (f || b) ? ARC_LENGTH(1) : ARC_LENGTH(2);
+          }
+          else if (f) {
+            sx = circle_x + INTERSECTION_CIRCLE_RADIUS;
+            ex = circle_x - INTERSECTION_CIRCLE_RADIUS;
+            sy = ey = circle_y;
+            arc_length = ARC_LENGTH(2);
+          }
+          else if (b) {
+            sx = circle_x - INTERSECTION_CIRCLE_RADIUS;
+            ex = circle_x + INTERSECTION_CIRCLE_RADIUS;
+            sy = ey = circle_y;
+            arc_length = ARC_LENGTH(2);
+          }
+          const float arc_offset[2] = {
+            circle_x - sx,
+            circle_y - sy
+          };
+
+          const float dx_s = current_position[X_AXIS] - sx,   // find our distance from the start of the actual circle
+                      dy_s = current_position[Y_AXIS] - sy,
+                      dist_start = HYPOT2(dx_s, dy_s);
+          const float endpoint[XYZE] = {
+            ex, ey,
+            g26_layer_height,
+            current_position[E_CART] + (arc_length * g26_e_axis_feedrate * g26_extrusion_multiplier)
+          };
+
+          if (dist_start > 2.0) {
+            retract_filament(destination);
+            //todo:  parameterize the bump height with a define
+            move_to(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + 0.500, 0.0);  // Z bump to minimize scraping
+            move_to(sx, sy, g26_layer_height + 0.500, 0.0); // Get to the starting point with no extrusion while bumped
+          }
+
+          move_to(sx, sy, g26_layer_height, 0.0); // Get to the starting point with no extrusion / un-Z bump
+
+          recover_filament(destination);
+          const float save_feedrate = feedrate_mm_s;
+          feedrate_mm_s = PLANNER_XY_FEEDRATE() / 10.0;
+          plan_arc(endpoint, arc_offset, false);  // Draw a counter-clockwise arc
+          feedrate_mm_s = save_feedrate;
+          set_destination_from_current();
+          #if ENABLED(ULTIPANEL)
+            if (user_canceled()) goto LEAVE; // Check if the user wants to stop the Mesh Validation
+          #endif
+
+        #else // !ARC_SUPPORT
+
+          int8_t start_ind = -2, end_ind = 9; // Assume a full circle (from 5:00 to 5:00)
+          if (xi == 0) {                      // Left edge? Just right half.
+            start_ind = f ? 0 : -3;           //  03:00 to 12:00 for front-left
+            end_ind = b ? 0 : 2;              //  06:00 to 03:00 for back-left
+          }
+          else if (r) {                       // Right edge? Just left half.
+            start_ind = b ? 6 : 3;            //  12:00 to 09:00 for front-right
+            end_ind = f ? 5 : 8;              //  09:00 to 06:00 for back-right
+          }
+          else if (f) {                       // Front edge? Just back half.
+            start_ind = 0;                    //  03:00
+            end_ind = 5;                      //  09:00
+          }
+          else if (b) {                       // Back edge? Just front half.
+            start_ind = 6;                    //  09:00
+            end_ind = 11;                     //  03:00
+          }
+
+          for (int8_t ind = start_ind; ind <= end_ind; ind++) {
+
+            #if ENABLED(ULTIPANEL)
+              if (user_canceled()) goto LEAVE;          // Check if the user wants to stop the Mesh Validation
+            #endif
+
+            float rx = circle_x + _COS(ind),            // For speed, these are now a lookup table entry
+                  ry = circle_y + _SIN(ind),
+                  xe = circle_x + _COS(ind + 1),
+                  ye = circle_y + _SIN(ind + 1);
+
+            #if IS_KINEMATIC
+              // Check to make sure this segment is entirely on the bed, skip if not.
+              if (!position_is_reachable(rx, ry) || !position_is_reachable(xe, ye)) continue;
+            #else                                               // not, we need to skip
+              rx = constrain(rx, X_MIN_POS + 1, X_MAX_POS - 1); // This keeps us from bumping the endstops
+              ry = constrain(ry, Y_MIN_POS + 1, Y_MAX_POS - 1);
+              xe = constrain(xe, X_MIN_POS + 1, X_MAX_POS - 1);
+              ye = constrain(ye, Y_MIN_POS + 1, Y_MAX_POS - 1);
+            #endif
+
+            print_line_from_here_to_there(rx, ry, g26_layer_height, xe, ye, g26_layer_height);
+            SERIAL_FLUSH();  // Prevent host M105 buffer overrun.
+          }
+
+        #endif // !ARC_SUPPORT
+
+        if (look_for_lines_to_connect()) goto LEAVE;
+      }
+
+      SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
+
+    } while (--g26_repeats && location.x_index >= 0 && location.y_index >= 0);
+
+    LEAVE:
+    lcd_setstatusPGM(PSTR("Leaving G26"), -1);
+
+    retract_filament(destination);
+    destination[Z_AXIS] = Z_CLEARANCE_BETWEEN_PROBES;
+
+    //debug_current_and_destination(PSTR("ready to do Z-Raise."));
+    move_to(destination, 0); // Raise the nozzle
+    //debug_current_and_destination(PSTR("done doing Z-Raise."));
+
+    destination[X_AXIS] = g26_x_pos;                               // Move back to the starting position
+    destination[Y_AXIS] = g26_y_pos;
+    //destination[Z_AXIS] = Z_CLEARANCE_BETWEEN_PROBES;            // Keep the nozzle where it is
+
+    move_to(destination, 0); // Move back to the starting position
+    //debug_current_and_destination(PSTR("done doing X/Y move."));
+
+    #if ENABLED(ULTIPANEL)
+      lcd_external_control = false;     // Give back control of the LCD Panel!
+    #endif
+
+    if (!g26_keep_heaters_on) {
+      #if HAS_HEATED_BED
+        thermalManager.setTargetBed(0);
+      #endif
+      thermalManager.setTargetHotend(0, 0);
+    }
+  }
+
+#endif // G26_MESH_VALIDATION

+ 337 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/HAL.h

@@ -0,0 +1,337 @@
+/* **************************************************************************
+
+ Marlin 3D Printer Firmware
+ Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+
+ Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+****************************************************************************/
+
+/**
+ * Description: HAL for __AVR__
+ */
+
+#ifndef _HAL_AVR_H_
+#define _HAL_AVR_H_
+
+// --------------------------------------------------------------------------
+// Includes
+// --------------------------------------------------------------------------
+
+#include "fastio.h"
+
+#include <stdint.h>
+#include <Arduino.h>
+#include <util/delay.h>
+#include <avr/eeprom.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include <avr/io.h>
+
+// --------------------------------------------------------------------------
+// Defines
+// --------------------------------------------------------------------------
+
+//#define analogInputToDigitalPin(IO) IO
+
+// Bracket code that shouldn't be interrupted
+#ifndef CRITICAL_SECTION_START
+  #define CRITICAL_SECTION_START  unsigned char _sreg = SREG; cli()
+  #define CRITICAL_SECTION_END    SREG = _sreg
+#endif
+
+#define ISRS_ENABLED() TEST(SREG, SREG_I)
+#define ENABLE_ISRS()  sei()
+#define DISABLE_ISRS() cli()
+
+// --------------------------------------------------------------------------
+// Types
+// --------------------------------------------------------------------------
+
+typedef uint16_t hal_timer_t;
+#define HAL_TIMER_TYPE_MAX 0xFFFF
+
+typedef int8_t pin_t;
+
+#define HAL_SERVO_LIB Servo
+
+// --------------------------------------------------------------------------
+// Public Variables
+// --------------------------------------------------------------------------
+
+//extern uint8_t MCUSR;
+
+// --------------------------------------------------------------------------
+// Public functions
+// --------------------------------------------------------------------------
+
+//void cli(void);
+
+//void _delay_ms(const int delay);
+
+inline void HAL_clear_reset_source(void) { MCUSR = 0; }
+inline uint8_t HAL_get_reset_source(void) { return MCUSR; }
+
+// eeprom
+//void eeprom_write_byte(unsigned char *pos, unsigned char value);
+//unsigned char eeprom_read_byte(unsigned char *pos);
+
+// timers
+#define HAL_TIMER_RATE          ((F_CPU) / 8)    // i.e., 2MHz or 2.5MHz
+
+#define STEP_TIMER_NUM          1
+#define TEMP_TIMER_NUM          0
+#define PULSE_TIMER_NUM         STEP_TIMER_NUM
+
+#define TEMP_TIMER_FREQUENCY    ((F_CPU) / 64.0 / 256.0)
+
+#define STEPPER_TIMER_RATE      HAL_TIMER_RATE
+#define STEPPER_TIMER_PRESCALE  8
+#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // Cannot be of type double
+
+#define PULSE_TIMER_RATE       STEPPER_TIMER_RATE   // frequency of pulse timer
+#define PULSE_TIMER_PRESCALE   STEPPER_TIMER_PRESCALE
+#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
+
+#define ENABLE_STEPPER_DRIVER_INTERRUPT()  SBI(TIMSK1, OCIE1A)
+#define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
+#define STEPPER_ISR_ENABLED()             TEST(TIMSK1, OCIE1A)
+
+#define ENABLE_TEMPERATURE_INTERRUPT()     SBI(TIMSK0, OCIE0B)
+#define DISABLE_TEMPERATURE_INTERRUPT()    CBI(TIMSK0, OCIE0B)
+#define TEMPERATURE_ISR_ENABLED()         TEST(TIMSK0, OCIE0B)
+
+FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
+  UNUSED(frequency);
+  switch (timer_num) {
+    case STEP_TIMER_NUM:
+      // waveform generation = 0100 = CTC
+      SET_WGM(1, CTC_OCRnA);
+
+      // output mode = 00 (disconnected)
+      SET_COMA(1, NORMAL);
+
+      // Set the timer pre-scaler
+      // Generally we use a divider of 8, resulting in a 2MHz timer
+      // frequency on a 16MHz MCU. If you are going to change this, be
+      // sure to regenerate speed_lookuptable.h with
+      // create_speed_lookuptable.py
+      SET_CS(1, PRESCALER_8);  //  CS 2 = 1/8 prescaler
+
+      // Init Stepper ISR to 122 Hz for quick starting
+      // (F_CPU) / (STEPPER_TIMER_PRESCALE) / frequency
+      OCR1A = 0x4000;
+      TCNT1 = 0;
+      break;
+
+    case TEMP_TIMER_NUM:
+      // Use timer0 for temperature measurement
+      // Interleave temperature interrupt with millies interrupt
+      OCR0B = 128;
+      break;
+  }
+}
+
+#define TIMER_OCR_1             OCR1A
+#define TIMER_COUNTER_1         TCNT1
+
+#define TIMER_OCR_0             OCR0A
+#define TIMER_COUNTER_0         TCNT0
+
+#define _CAT(a, ...) a ## __VA_ARGS__
+#define HAL_timer_set_compare(timer, compare) (_CAT(TIMER_OCR_, timer) = compare)
+#define HAL_timer_get_compare(timer) _CAT(TIMER_OCR_, timer)
+#define HAL_timer_get_count(timer) _CAT(TIMER_COUNTER_, timer)
+
+/**
+ * On AVR there is no hardware prioritization and preemption of
+ * interrupts, so this emulates it. The UART has first priority
+ * (otherwise, characters will be lost due to UART overflow).
+ * Then: Stepper, Endstops, Temperature, and -finally- all others.
+ */
+#define HAL_timer_isr_prologue(TIMER_NUM)
+#define HAL_timer_isr_epilogue(TIMER_NUM)
+
+/* 18 cycles maximum latency */
+#define HAL_STEP_TIMER_ISR \
+extern "C" void TIMER1_COMPA_vect (void) __attribute__ ((signal, naked, used, externally_visible)); \
+extern "C" void TIMER1_COMPA_vect_bottom (void) asm ("TIMER1_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
+void TIMER1_COMPA_vect (void) { \
+  __asm__ __volatile__ ( \
+    A("push r16")                      /* 2 Save R16 */ \
+    A("in r16, __SREG__")              /* 1 Get SREG */ \
+    A("push r16")                      /* 2 Save SREG into stack */ \
+    A("lds r16, %[timsk0]")            /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
+    A("push r16")                      /* 2 Save TIMSK0 into the stack */ \
+    A("andi r16,~%[msk0]")             /* 1 Disable the temperature ISR */ \
+    A("sts %[timsk0], r16")            /* 2 And set the new value */ \
+    A("lds r16, %[timsk1]")            /* 2 Load into R0 the stepper timer Interrupt mask register [TIMSK1] */ \
+    A("andi r16,~%[msk1]")             /* 1 Disable the stepper ISR */ \
+    A("sts %[timsk1], r16")            /* 2 And set the new value */ \
+    A("push r16")                      /* 2 Save TIMSK1 into stack */ \
+    A("in r16, 0x3B")                  /* 1 Get RAMPZ register */ \
+    A("push r16")                      /* 2 Save RAMPZ into stack */ \
+    A("in r16, 0x3C")                  /* 1 Get EIND register */ \
+    A("push r0")                       /* C runtime can modify all the following registers without restoring them */ \
+    A("push r1")                       \
+    A("push r18")                      \
+    A("push r19")                      \
+    A("push r20")                      \
+    A("push r21")                      \
+    A("push r22")                      \
+    A("push r23")                      \
+    A("push r24")                      \
+    A("push r25")                      \
+    A("push r26")                      \
+    A("push r27")                      \
+    A("push r30")                      \
+    A("push r31")                      \
+    A("clr r1")                        /* C runtime expects this register to be 0 */ \
+    A("call TIMER1_COMPA_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */   \
+    A("pop r31")                       \
+    A("pop r30")                       \
+    A("pop r27")                       \
+    A("pop r26")                       \
+    A("pop r25")                       \
+    A("pop r24")                       \
+    A("pop r23")                       \
+    A("pop r22")                       \
+    A("pop r21")                       \
+    A("pop r20")                       \
+    A("pop r19")                       \
+    A("pop r18")                       \
+    A("pop r1")                        \
+    A("pop r0")                        \
+    A("out 0x3C, r16")                 /* 1 Restore EIND register */ \
+    A("pop r16")                       /* 2 Get the original RAMPZ register value */ \
+    A("out 0x3B, r16")                 /* 1 Restore RAMPZ register to its original value */ \
+    A("pop r16")                       /* 2 Get the original TIMSK1 value but with stepper ISR disabled */ \
+    A("ori r16,%[msk1]")               /* 1 Reenable the stepper ISR */ \
+    A("cli")                           /* 1 Disable global interrupts - Reenabling Stepper ISR can reenter amd temperature can reenter, and we want that, if it happens, after this ISR has ended */ \
+    A("sts %[timsk1], r16")            /* 2 And restore the old value - This reenables the stepper ISR */ \
+    A("pop r16")                       /* 2 Get the temperature timer Interrupt mask register [TIMSK0] */ \
+    A("sts %[timsk0], r16")            /* 2 And restore the old value - This reenables the temperature ISR */ \
+    A("pop r16")                       /* 2 Get the old SREG value */ \
+    A("out __SREG__, r16")             /* 1 And restore the SREG value */ \
+    A("pop r16")                       /* 2 Restore R16 value */ \
+    A("reti")                          /* 4 Return from interrupt */ \
+    :                                   \
+    : [timsk0] "i" ((uint16_t)&TIMSK0), \
+      [timsk1] "i" ((uint16_t)&TIMSK1), \
+      [msk0] "M" ((uint8_t)(1<<OCIE0B)),\
+      [msk1] "M" ((uint8_t)(1<<OCIE1A)) \
+    : \
+  ); \
+} \
+void TIMER1_COMPA_vect_bottom(void)
+
+/* 14 cycles maximum latency */
+#define HAL_TEMP_TIMER_ISR \
+extern "C" void TIMER0_COMPB_vect (void) __attribute__ ((signal, naked, used, externally_visible)); \
+extern "C" void TIMER0_COMPB_vect_bottom(void)  asm ("TIMER0_COMPB_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
+void TIMER0_COMPB_vect (void) { \
+  __asm__ __volatile__ ( \
+    A("push r16")                       /* 2 Save R16 */ \
+    A("in r16, __SREG__")               /* 1 Get SREG */ \
+    A("push r16")                       /* 2 Save SREG into stack */ \
+    A("lds r16, %[timsk0]")             /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
+    A("andi r16,~%[msk0]")              /* 1 Disable the temperature ISR */ \
+    A("sts %[timsk0], r16")             /* 2 And set the new value */ \
+    A("sei")                            /* 1 Enable global interrupts - It is safe, as the temperature ISR is disabled, so we cannot reenter it */    \
+    A("push r16")                       /* 2 Save TIMSK0 into stack */ \
+    A("in r16, 0x3B")                   /* 1 Get RAMPZ register */ \
+    A("push r16")                       /* 2 Save RAMPZ into stack */ \
+    A("in r16, 0x3C")                   /* 1 Get EIND register */ \
+    A("push r0")                        /* C runtime can modify all the following registers without restoring them */ \
+    A("push r1")                        \
+    A("push r18")                       \
+    A("push r19")                       \
+    A("push r20")                       \
+    A("push r21")                       \
+    A("push r22")                       \
+    A("push r23")                       \
+    A("push r24")                       \
+    A("push r25")                       \
+    A("push r26")                       \
+    A("push r27")                       \
+    A("push r30")                       \
+    A("push r31")                       \
+    A("clr r1")                         /* C runtime expects this register to be 0 */ \
+    A("call TIMER0_COMPB_vect_bottom")  /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */   \
+    A("pop r31")                        \
+    A("pop r30")                        \
+    A("pop r27")                        \
+    A("pop r26")                        \
+    A("pop r25")                        \
+    A("pop r24")                        \
+    A("pop r23")                        \
+    A("pop r22")                        \
+    A("pop r21")                        \
+    A("pop r20")                        \
+    A("pop r19")                        \
+    A("pop r18")                        \
+    A("pop r1")                         \
+    A("pop r0")                         \
+    A("out 0x3C, r16")                  /* 1 Restore EIND register */ \
+    A("pop r16")                        /* 2 Get the original RAMPZ register value */ \
+    A("out 0x3B, r16")                  /* 1 Restore RAMPZ register to its original value */ \
+    A("pop r16")                        /* 2 Get the original TIMSK0 value but with temperature ISR disabled */ \
+    A("ori r16,%[msk0]")                /* 1 Enable temperature ISR */ \
+    A("cli")                            /* 1 Disable global interrupts - We must do this, as we will reenable the temperature ISR, and we don't want to reenter this handler until the current one is done */ \
+    A("sts %[timsk0], r16")             /* 2 And restore the old value */ \
+    A("pop r16")                        /* 2 Get the old SREG */ \
+    A("out __SREG__, r16")              /* 1 And restore the SREG value */ \
+    A("pop r16")                        /* 2 Restore R16 */ \
+    A("reti")                           /* 4 Return from interrupt */ \
+    :                                   \
+    : [timsk0] "i"((uint16_t)&TIMSK0),  \
+      [msk0] "M" ((uint8_t)(1<<OCIE0B)) \
+    : \
+  ); \
+} \
+void TIMER0_COMPB_vect_bottom(void)
+
+// ADC
+#ifdef DIDR2
+  #define HAL_ANALOG_SELECT(pin) do{ if (pin < 8) SBI(DIDR0, pin); else SBI(DIDR2, pin & 0x07); }while(0)
+#else
+  #define HAL_ANALOG_SELECT(pin) do{ SBI(DIDR0, pin); }while(0)
+#endif
+
+inline void HAL_adc_init(void) {
+  ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
+  DIDR0 = 0;
+  #ifdef DIDR2
+    DIDR2 = 0;
+  #endif
+}
+
+#define SET_ADMUX_ADCSRA(pin) ADMUX = _BV(REFS0) | (pin & 0x07); SBI(ADCSRA, ADSC)
+#ifdef MUX5
+  #define HAL_START_ADC(pin) if (pin > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
+#else
+  #define HAL_START_ADC(pin) ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
+#endif
+
+#define HAL_READ_ADC()  ADC
+#define HAL_ADC_READY() !TEST(ADCSRA, ADSC)
+
+#define GET_PIN_MAP_PIN(index) index
+#define GET_PIN_MAP_INDEX(pin) pin
+#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
+
+#define HAL_SENSITIVE_PINS 0, 1
+
+#endif // _HAL_AVR_H_

File diff suppressed because it is too large
+ 1140 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/I2CPositionEncoder.cpp


+ 342 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/I2CPositionEncoder.h

@@ -0,0 +1,342 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016, 2017 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef I2CPOSENC_H
+#define I2CPOSENC_H
+
+#include "MarlinConfig.h"
+
+#if ENABLED(I2C_POSITION_ENCODERS)
+
+  #include "enum.h"
+  #include "macros.h"
+  #include "types.h"
+  #include <Wire.h>
+
+  //=========== Advanced / Less-Common Encoder Configuration Settings ==========
+
+  #define I2CPE_EC_THRESH_PROPORTIONAL                    // if enabled adjusts the error correction threshold
+                                                          // proportional to the current speed of the axis allows
+                                                          // for very small error margin at low speeds without
+                                                          // stuttering due to reading latency at high speeds
+
+  #define I2CPE_DEBUG                                     // enable encoder-related debug serial echos
+
+  #define I2CPE_REBOOT_TIME             5000              // time we wait for an encoder module to reboot
+                                                          // after changing address.
+
+  #define I2CPE_MAG_SIG_GOOD            0
+  #define I2CPE_MAG_SIG_MID             1
+  #define I2CPE_MAG_SIG_BAD             2
+  #define I2CPE_MAG_SIG_NF              255
+
+  #define I2CPE_REQ_REPORT              0
+  #define I2CPE_RESET_COUNT             1
+  #define I2CPE_SET_ADDR                2
+  #define I2CPE_SET_REPORT_MODE         3
+  #define I2CPE_CLEAR_EEPROM            4
+
+  #define I2CPE_LED_PAR_MODE            10
+  #define I2CPE_LED_PAR_BRT             11
+  #define I2CPE_LED_PAR_RATE            14
+
+  #define I2CPE_REPORT_DISTANCE         0
+  #define I2CPE_REPORT_STRENGTH         1
+  #define I2CPE_REPORT_VERSION          2
+
+  // Default I2C addresses
+  #define I2CPE_PRESET_ADDR_X           30
+  #define I2CPE_PRESET_ADDR_Y           31
+  #define I2CPE_PRESET_ADDR_Z           32
+  #define I2CPE_PRESET_ADDR_E           33
+
+  #define I2CPE_DEF_AXIS                X_AXIS
+  #define I2CPE_DEF_ADDR                I2CPE_PRESET_ADDR_X
+
+  // Error event counter; tracks how many times there is an error exceeding a certain threshold
+  #define I2CPE_ERR_CNT_THRESH          3.00
+  #define I2CPE_ERR_CNT_DEBOUNCE_MS     2000
+
+  #if ENABLED(I2CPE_ERR_ROLLING_AVERAGE)
+    #define I2CPE_ERR_ARRAY_SIZE        32
+    #define I2CPE_ERR_PRST_ARRAY_SIZE   10
+  #endif
+
+  // Error Correction Methods
+  #define I2CPE_ECM_NONE                0
+  #define I2CPE_ECM_MICROSTEP           1
+  #define I2CPE_ECM_PLANNER             2
+  #define I2CPE_ECM_STALLDETECT         3
+
+  // Encoder types
+  #define I2CPE_ENC_TYPE_ROTARY         0
+  #define I2CPE_ENC_TYPE_LINEAR         1
+
+  // Parser
+  #define I2CPE_PARSE_ERR               1
+  #define I2CPE_PARSE_OK                0
+
+  #define LOOP_PE(VAR) LOOP_L_N(VAR, I2CPE_ENCODER_CNT)
+  #define CHECK_IDX() do{ if (!WITHIN(idx, 0, I2CPE_ENCODER_CNT - 1)) return; }while(0)
+
+  typedef union {
+    volatile int32_t val = 0;
+    uint8_t          bval[4];
+  } i2cLong;
+
+  class I2CPositionEncoder {
+  private:
+    AxisEnum  encoderAxis         = I2CPE_DEF_AXIS;
+
+    uint8_t   i2cAddress          = I2CPE_DEF_ADDR,
+              ecMethod            = I2CPE_DEF_EC_METHOD,
+              type                = I2CPE_DEF_TYPE,
+              H                   = I2CPE_MAG_SIG_NF;    // Magnetic field strength
+
+    int       encoderTicksPerUnit = I2CPE_DEF_ENC_TICKS_UNIT,
+              stepperTicks        = I2CPE_DEF_TICKS_REV,
+              errorCount          = 0,
+              errorPrev           = 0;
+
+    float     ecThreshold         = I2CPE_DEF_EC_THRESH;
+
+    bool      homed               = false,
+              trusted             = false,
+              initialised         = false,
+              active              = false,
+              invert              = false,
+              ec                  = true;
+
+    int32_t   zeroOffset          = 0,
+              lastPosition        = 0,
+              position;
+
+    millis_t  lastPositionTime    = 0,
+              nextErrorCountTime  = 0,
+              lastErrorTime;
+
+    #if ENABLED(I2CPE_ERR_ROLLING_AVERAGE)
+      uint8_t errIdx = 0, errPrstIdx = 0;
+      int err[I2CPE_ERR_ARRAY_SIZE] = { 0 },
+          errPrst[I2CPE_ERR_PRST_ARRAY_SIZE] = { 0 };
+    #endif
+
+  public:
+    void init(const uint8_t address, const AxisEnum axis);
+    void reset();
+
+    void update();
+
+    void set_homed();
+
+    int32_t get_raw_count();
+
+    FORCE_INLINE float mm_from_count(const int32_t count) {
+      switch (type) {
+        default: return -1;
+        case I2CPE_ENC_TYPE_LINEAR:
+          return count / encoderTicksPerUnit;
+        case I2CPE_ENC_TYPE_ROTARY:
+          return (count * stepperTicks) / (encoderTicksPerUnit * planner.axis_steps_per_mm[encoderAxis]);
+      }
+    }
+
+    FORCE_INLINE float get_position_mm() { return mm_from_count(get_position()); }
+    FORCE_INLINE int32_t get_position() { return get_raw_count() - zeroOffset; }
+
+    int32_t get_axis_error_steps(const bool report);
+    float get_axis_error_mm(const bool report);
+
+    void calibrate_steps_mm(const uint8_t iter);
+
+    bool passes_test(const bool report);
+
+    bool test_axis(void);
+
+    FORCE_INLINE int get_error_count(void) { return errorCount; }
+    FORCE_INLINE void set_error_count(const int newCount) { errorCount = newCount; }
+
+    FORCE_INLINE uint8_t get_address() { return i2cAddress; }
+    FORCE_INLINE void set_address(const uint8_t addr) { i2cAddress = addr; }
+
+    FORCE_INLINE bool get_active(void) { return active; }
+    FORCE_INLINE void set_active(const bool a) { active = a; }
+
+    FORCE_INLINE void set_inverted(const bool i) { invert = i; }
+
+    FORCE_INLINE AxisEnum get_axis() { return encoderAxis; }
+
+    FORCE_INLINE bool get_ec_enabled() { return ec; }
+    FORCE_INLINE void set_ec_enabled(const bool enabled) { ec = enabled; }
+
+    FORCE_INLINE uint8_t get_ec_method() { return ecMethod; }
+    FORCE_INLINE void set_ec_method(const byte method) { ecMethod = method; }
+
+    FORCE_INLINE float get_ec_threshold() { return ecThreshold; }
+    FORCE_INLINE void set_ec_threshold(const float newThreshold) { ecThreshold = newThreshold; }
+
+    FORCE_INLINE int get_encoder_ticks_mm() {
+      switch (type) {
+        default: return 0;
+        case I2CPE_ENC_TYPE_LINEAR:
+          return encoderTicksPerUnit;
+        case I2CPE_ENC_TYPE_ROTARY:
+          return (int)((encoderTicksPerUnit / stepperTicks) * planner.axis_steps_per_mm[encoderAxis]);
+      }
+    }
+
+    FORCE_INLINE int get_ticks_unit() { return encoderTicksPerUnit; }
+    FORCE_INLINE void set_ticks_unit(const int ticks) { encoderTicksPerUnit = ticks; }
+
+    FORCE_INLINE uint8_t get_type() { return type; }
+    FORCE_INLINE void set_type(const byte newType) { type = newType; }
+
+    FORCE_INLINE int get_stepper_ticks() { return stepperTicks; }
+    FORCE_INLINE void set_stepper_ticks(const int ticks) { stepperTicks = ticks; }
+  };
+
+  class I2CPositionEncodersMgr {
+  private:
+    static bool I2CPE_anyaxis;
+    static uint8_t I2CPE_addr, I2CPE_idx;
+
+  public:
+
+    static void init(void);
+
+    // consider only updating one endoder per call / tick if encoders become too time intensive
+    static void update(void) { LOOP_PE(i) encoders[i].update(); }
+
+    static void homed(const AxisEnum axis) {
+      LOOP_PE(i)
+        if (encoders[i].get_axis() == axis) encoders[i].set_homed();
+    }
+
+    static void report_position(const int8_t idx, const bool units, const bool noOffset);
+
+    static void report_status(const int8_t idx) {
+      CHECK_IDX();
+      SERIAL_ECHOPAIR("Encoder ",idx);
+      SERIAL_ECHOPGM(": ");
+      encoders[idx].get_raw_count();
+      encoders[idx].passes_test(true);
+    }
+
+    static void report_error(const int8_t idx) {
+      CHECK_IDX();
+      encoders[idx].get_axis_error_steps(true);
+    }
+
+    static void test_axis(const int8_t idx) {
+      CHECK_IDX();
+      encoders[idx].test_axis();
+    }
+
+    static void calibrate_steps_mm(const int8_t idx, const int iterations) {
+      CHECK_IDX();
+      encoders[idx].calibrate_steps_mm(iterations);
+    }
+
+    static void change_module_address(const uint8_t oldaddr, const uint8_t newaddr);
+    static void report_module_firmware(const uint8_t address);
+
+    static void report_error_count(const int8_t idx, const AxisEnum axis) {
+      CHECK_IDX();
+      SERIAL_ECHOPAIR("Error count on ", axis_codes[axis]);
+      SERIAL_ECHOLNPAIR(" axis is ", encoders[idx].get_error_count());
+    }
+
+    static void reset_error_count(const int8_t idx, const AxisEnum axis) {
+      CHECK_IDX();
+      encoders[idx].set_error_count(0);
+      SERIAL_ECHOPAIR("Error count on ", axis_codes[axis]);
+      SERIAL_ECHOLNPGM(" axis has been reset.");
+    }
+
+    static void enable_ec(const int8_t idx, const bool enabled, const AxisEnum axis) {
+      CHECK_IDX();
+      encoders[idx].set_ec_enabled(enabled);
+      SERIAL_ECHOPAIR("Error correction on ", axis_codes[axis]);
+      SERIAL_ECHOPGM(" axis is ");
+      serialprintPGM(encoders[idx].get_ec_enabled() ? PSTR("en") : PSTR("dis"));
+      SERIAL_ECHOLNPGM("abled.");
+    }
+
+    static void set_ec_threshold(const int8_t idx, const float newThreshold, const AxisEnum axis) {
+      CHECK_IDX();
+      encoders[idx].set_ec_threshold(newThreshold);
+      SERIAL_ECHOPAIR("Error correct threshold for ", axis_codes[axis]);
+      SERIAL_ECHOPAIR_F(" axis set to ", newThreshold);
+      SERIAL_ECHOLNPGM("mm.");
+    }
+
+    static void get_ec_threshold(const int8_t idx, const AxisEnum axis) {
+      CHECK_IDX();
+      const float threshold = encoders[idx].get_ec_threshold();
+      SERIAL_ECHOPAIR("Error correct threshold for ", axis_codes[axis]);
+      SERIAL_ECHOPAIR_F(" axis is ", threshold);
+      SERIAL_ECHOLNPGM("mm.");
+    }
+
+    static int8_t idx_from_axis(const AxisEnum axis) {
+      LOOP_PE(i)
+        if (encoders[i].get_axis() == axis) return i;
+      return -1;
+    }
+
+    static int8_t idx_from_addr(const uint8_t addr) {
+      LOOP_PE(i)
+        if (encoders[i].get_address() == addr) return i;
+      return -1;
+    }
+
+    static int8_t parse();
+
+    static void M860();
+    static void M861();
+    static void M862();
+    static void M863();
+    static void M864();
+    static void M865();
+    static void M866();
+    static void M867();
+    static void M868();
+    static void M869();
+
+    static I2CPositionEncoder encoders[I2CPE_ENCODER_CNT];
+  };
+
+  extern I2CPositionEncodersMgr I2CPEM;
+
+  FORCE_INLINE static void gcode_M860() { I2CPEM.M860(); }
+  FORCE_INLINE static void gcode_M861() { I2CPEM.M861(); }
+  FORCE_INLINE static void gcode_M862() { I2CPEM.M862(); }
+  FORCE_INLINE static void gcode_M863() { I2CPEM.M863(); }
+  FORCE_INLINE static void gcode_M864() { I2CPEM.M864(); }
+  FORCE_INLINE static void gcode_M865() { I2CPEM.M865(); }
+  FORCE_INLINE static void gcode_M866() { I2CPEM.M866(); }
+  FORCE_INLINE static void gcode_M867() { I2CPEM.M867(); }
+  FORCE_INLINE static void gcode_M868() { I2CPEM.M868(); }
+  FORCE_INLINE static void gcode_M869() { I2CPEM.M869(); }
+
+#endif //I2C_POSITION_ENCODERS
+#endif //I2CPOSENC_H

+ 332 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/M100_Free_Mem_Chk.cpp

@@ -0,0 +1,332 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * M100 Free Memory Watcher
+ *
+ * This code watches the free memory block between the bottom of the heap and the top of the stack.
+ * This memory block is initialized and watched via the M100 command.
+ *
+ * M100 I   Initializes the free memory block and prints vitals statistics about the area
+ *
+ * M100 F   Identifies how much of the free memory block remains free and unused. It also
+ *          detects and reports any corruption within the free memory block that may have
+ *          happened due to errant firmware.
+ *
+ * M100 D   Does a hex display of the free memory block along with a flag for any errant
+ *          data that does not match the expected value.
+ *
+ * M100 C x Corrupts x locations within the free memory block. This is useful to check the
+ *          correctness of the M100 F and M100 D commands.
+ *
+ * Also, there are two support functions that can be called from a developer's C code.
+ *
+ *    uint16_t check_for_free_memory_corruption(const char * const ptr);
+ *    void M100_dump_routine(const char * const title, const char *start, const char *end);
+ *
+ * Initial version by Roxy-3D
+ */
+
+#include "MarlinConfig.h"
+
+#if ENABLED(M100_FREE_MEMORY_WATCHER)
+
+#define M100_FREE_MEMORY_DUMPER     // Enable for the `M100 D` Dump sub-command
+#define M100_FREE_MEMORY_CORRUPTOR  // Enable for the `M100 C` Corrupt sub-command
+
+#include "Marlin.h"
+#include "parser.h"
+#include "hex_print_routines.h"
+
+#define TEST_BYTE ((char) 0xE5)
+
+extern char* __brkval;
+extern size_t  __heap_start, __heap_end, __flp;
+extern char __bss_end;
+
+//
+// Utility functions
+//
+
+#define END_OF_HEAP() (__brkval ? __brkval : &__bss_end)
+int check_for_free_memory_corruption(const char * const title);
+
+// Location of a variable on its stack frame. Returns a value above
+// the stack (once the function returns to the caller).
+char* top_of_stack() {
+  char x;
+  return &x + 1; // x is pulled on return;
+}
+
+// Count the number of test bytes at the specified location.
+int16_t count_test_bytes(const char * const ptr) {
+  for (uint16_t i = 0; i < 32000; i++)
+    if (((char) ptr[i]) != TEST_BYTE)
+      return i - 1;
+
+  return -1;
+}
+
+//
+// M100 sub-commands
+//
+
+#if ENABLED(M100_FREE_MEMORY_DUMPER)
+  /**
+   * M100 D
+   *  Dump the free memory block from __brkval to the stack pointer.
+   *  malloc() eats memory from the start of the block and the stack grows
+   *  up from the bottom of the block. Solid test bytes indicate nothing has
+   *  used that memory yet. There should not be anything but test bytes within
+   *  the block. If so, it may indicate memory corruption due to a bad pointer.
+   *  Unexpected bytes are flagged in the right column.
+   */
+  void dump_free_memory(const char *ptr, const char *sp) {
+    //
+    // Start and end the dump on a nice 16 byte boundary
+    // (even though the values are not 16-byte aligned).
+    //
+    ptr = (char *)((uint16_t)ptr & 0xFFF0); // Align to 16-byte boundary
+    sp  = (char *)((uint16_t)sp  | 0x000F); // Align sp to the 15th byte (at or above sp)
+
+    // Dump command main loop
+    while (ptr < sp) {
+      print_hex_word((uint16_t)ptr);      // Print the address
+      SERIAL_CHAR(':');
+      for (uint8_t i = 0; i < 16; i++) {  // and 16 data bytes
+        if (i == 8) SERIAL_CHAR('-');
+        print_hex_byte(ptr[i]);
+        SERIAL_CHAR(' ');
+      }
+      safe_delay(25);
+      SERIAL_CHAR('|');                   // Point out non test bytes
+      for (uint8_t i = 0; i < 16; i++) {
+        char ccc = (char)ptr[i]; // cast to char before automatically casting to char on assignment, in case the compiler is broken
+        if (&ptr[i] >= (const char*)command_queue && &ptr[i] < (const char*)(command_queue + sizeof(command_queue))) { // Print out ASCII in the command buffer area
+          if (!WITHIN(ccc, ' ', 0x7E)) ccc = ' ';
+        }
+        else { // If not in the command buffer area, flag bytes that don't match the test byte
+          ccc = (ccc == TEST_BYTE) ? ' ' : '?';
+        }
+        SERIAL_CHAR(ccc);
+      }
+      SERIAL_EOL();
+      ptr += 16;
+      safe_delay(25);
+      idle();
+    }
+  }
+
+void M100_dump_routine(const char * const title, const char *start, const char *end) {
+  SERIAL_ECHOLN(title);
+  //
+  // Round the start and end locations to produce full lines of output
+  //
+  start = (char*)((uint16_t) start & 0xFFF0);
+  end   = (char*)((uint16_t) end   | 0x000F);
+  dump_free_memory(start, end);
+}
+
+#endif // M100_FREE_MEMORY_DUMPER
+
+/**
+ * M100 F
+ *  Return the number of free bytes in the memory pool,
+ *  with other vital statistics defining the pool.
+ */
+void free_memory_pool_report(char * const ptr, const int16_t size) {
+  int16_t max_cnt = -1, block_cnt = 0;
+  char *max_addr = NULL;
+  // Find the longest block of test bytes in the buffer
+  for (int16_t i = 0; i < size; i++) {
+    char *addr = ptr + i;
+    if (*addr == TEST_BYTE) {
+      const int16_t j = count_test_bytes(addr);
+      if (j > 8) {
+        SERIAL_ECHOPAIR("Found ", j);
+        SERIAL_ECHOLNPAIR(" bytes free at ", hex_address(addr));
+        if (j > max_cnt) {
+          max_cnt  = j;
+          max_addr = addr;
+        }
+        i += j;
+        block_cnt++;
+      }
+    }
+  }
+  if (block_cnt > 1) {
+    SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area.");
+    SERIAL_ECHOPAIR("\nLargest free block is ", max_cnt);
+    SERIAL_ECHOLNPAIR(" bytes at ", hex_address(max_addr));
+  }
+  SERIAL_ECHOLNPAIR("check_for_free_memory_corruption() = ", check_for_free_memory_corruption("M100 F "));
+}
+
+#if ENABLED(M100_FREE_MEMORY_CORRUPTOR)
+  /**
+   * M100 C<num>
+   *  Corrupt <num> locations in the free memory pool and report the corrupt addresses.
+   *  This is useful to check the correctness of the M100 D and the M100 F commands.
+   */
+  void corrupt_free_memory(char *ptr, const uint16_t size) {
+    ptr += 8;
+    const uint16_t near_top = top_of_stack() - ptr - 250, // -250 to avoid interrupt activity that's altered the stack.
+                   j = near_top / (size + 1);
+
+    SERIAL_ECHOLNPGM("Corrupting free memory block.\n");
+    for (uint16_t i = 1; i <= size; i++) {
+      char * const addr = ptr + i * j;
+      *addr = i;
+      SERIAL_ECHOPAIR("\nCorrupting address: ", hex_address(addr));
+    }
+    SERIAL_EOL();
+  }
+#endif // M100_FREE_MEMORY_CORRUPTOR
+
+/**
+ * M100 I
+ *  Init memory for the M100 tests. (Automatically applied on the first M100.)
+ */
+void init_free_memory(char *ptr, int16_t size) {
+  SERIAL_ECHOLNPGM("Initializing free memory block.\n\n");
+
+  size -= 250;    // -250 to avoid interrupt activity that's altered the stack.
+  if (size < 0) {
+    SERIAL_ECHOLNPGM("Unable to initialize.\n");
+    return;
+  }
+
+  ptr += 8;       // move a few bytes away from the heap just because we don't want
+                  // to be altering memory that close to it.
+  memset(ptr, TEST_BYTE, size);
+
+  SERIAL_ECHO(size);
+  SERIAL_ECHOLNPGM(" bytes of memory initialized.\n");
+
+  for (int16_t i = 0; i < size; i++) {
+    if (ptr[i] != TEST_BYTE) {
+      SERIAL_ECHOPAIR("? address : ", hex_address(ptr + i));
+      SERIAL_ECHOLNPAIR("=", hex_byte(ptr[i]));
+      SERIAL_EOL();
+    }
+  }
+}
+
+/**
+ * M100: Free Memory Check
+ */
+void gcode_M100() {
+  SERIAL_ECHOPAIR("\n__brkval : ", hex_address(__brkval));
+  SERIAL_ECHOPAIR("\n__bss_end : ", hex_address(&__bss_end));
+
+  char *ptr = END_OF_HEAP(), *sp = top_of_stack();
+
+  SERIAL_ECHOPAIR("\nstart of free space : ", hex_address(ptr));
+  SERIAL_ECHOLNPAIR("\nStack Pointer : ", hex_address(sp));
+
+  // Always init on the first invocation of M100
+  static bool m100_not_initialized = true;
+  if (m100_not_initialized || parser.seen('I')) {
+    m100_not_initialized = false;
+    init_free_memory(ptr, sp - ptr);
+  }
+
+  #if ENABLED(M100_FREE_MEMORY_DUMPER)
+    if (parser.seen('D'))
+      return dump_free_memory(ptr, sp);
+  #endif
+
+  if (parser.seen('F'))
+    return free_memory_pool_report(ptr, sp - ptr);
+
+  #if ENABLED(M100_FREE_MEMORY_CORRUPTOR)
+
+    if (parser.seen('C'))
+      return corrupt_free_memory(ptr, parser.value_int());
+
+  #endif
+}
+
+int check_for_free_memory_corruption(const char * const title) {
+  SERIAL_ECHO(title);
+
+  char *ptr = END_OF_HEAP(), *sp = top_of_stack();
+  int n = sp - ptr;
+
+  SERIAL_ECHOPAIR("\nfmc() n=", n);
+  SERIAL_ECHOPAIR("\n&__brkval: ", hex_address(&__brkval));
+  SERIAL_ECHOPAIR("=",             hex_address(__brkval));
+  SERIAL_ECHOPAIR("\n__bss_end: ", hex_address(&__bss_end));
+  SERIAL_ECHOPAIR(" sp=",          hex_address(sp));
+
+  if (sp < ptr)  {
+    SERIAL_ECHOPGM(" sp < Heap ");
+    // SET_INPUT_PULLUP(63);           // if the developer has a switch wired up to their controller board
+    // safe_delay(5);                  // this code can be enabled to pause the display as soon as the
+    // while ( READ(63))               // malfunction is detected.   It is currently defaulting to a switch
+    //   idle();                       // being on pin-63 which is unassigend and available on most controller
+    // safe_delay(20);                 // boards.
+    // while ( !READ(63))
+    //   idle();
+    safe_delay(20);
+    #ifdef M100_FREE_MEMORY_DUMPER
+      M100_dump_routine("   Memory corruption detected with sp<Heap\n", (char*)0x1B80, (char*)0x21FF);
+    #endif
+  }
+
+  // Scan through the range looking for the biggest block of 0xE5's we can find
+  int block_cnt = 0;
+  for (int i = 0; i < n; i++) {
+    if (ptr[i] == TEST_BYTE) {
+      int16_t j = count_test_bytes(ptr + i);
+      if (j > 8) {
+        // SERIAL_ECHOPAIR("Found ", j);
+        // SERIAL_ECHOLNPAIR(" bytes free at ", hex_address(ptr + i));
+        i += j;
+        block_cnt++;
+        SERIAL_ECHOPAIR(" (", block_cnt);
+        SERIAL_ECHOPAIR(") found=", j);
+        SERIAL_ECHOPGM("   ");
+      }
+    }
+  }
+  SERIAL_ECHOPAIR("  block_found=", block_cnt);
+
+  if (block_cnt != 1 || __brkval != 0x0000)
+    SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area.");
+
+  if (block_cnt == 0)       // Make sure the special case of no free blocks shows up as an
+    block_cnt = -1;         // error to the calling code!
+
+  SERIAL_ECHOPGM(" return=");
+  if (block_cnt == 1) {
+    SERIAL_CHAR('0');       // if the block_cnt is 1, nothing has broken up the free memory
+    SERIAL_EOL();             // area and it is appropriate to say 'no corruption'.
+    return 0;
+  }
+  SERIAL_ECHOLNPGM("true");
+  return block_cnt;
+}
+
+#endif // M100_FREE_MEMORY_WATCHER
+
+

+ 686 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Makefile

@@ -0,0 +1,686 @@
+# Marlin Firmware 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 containing "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 wild card (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 at the top of this file can be overriden from
+# the command line with, for example, "make HARDWARE_MOTHERBOARD=71"
+#
+# To compile for RAMPS (atmega2560) with Arduino 1.6.9 at root/arduino you would use...
+#
+#   make ARDUINO_VERSION=10609 AVR_TOOLS_PATH=/root/arduino/hardware/tools/avr/bin/ \
+#   HARDWARE_MOTHERBOARD=33 ARDUINO_INSTALL_DIR=/root/arduino
+#
+# To compile and upload simply add "upload" to the end of the line...
+#
+#   make ARDUINO_VERSION=10609 AVR_TOOLS_PATH=/root/arduino/hardware/tools/avr/bin/ \
+#   HARDWARE_MOTHERBOARD=33 ARDUINO_INSTALL_DIR=/root/arduino upload
+#
+# If uploading doesn't work try adding the parameter "AVRDUDE_PROGRAMMER=wiring" or
+# start upload manually (using stk500) like so:
+#
+#   avrdude -C /root/arduino/hardware/tools/avr/etc/avrdude.conf -v -p m2560 -c stk500 \
+#   -U flash:w:applet/Marlin.hex:i -P /dev/ttyUSB0
+#
+# Or, try disconnecting USB to power down and then reconnecting before running avrdude.
+#
+
+# This defines the board to compile for (see boards.h for your board's ID)
+HARDWARE_MOTHERBOARD ?= 11
+
+# Arduino source install directory, and version number
+# On most linuxes this will be /usr/share/arduino
+ARDUINO_INSTALL_DIR  ?= ${HOME}/Arduino
+ARDUINO_VERSION      ?= 106
+
+# 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        ?= 57600
+AVRDUDE_PROGRAMMER ?= arduino
+# on most linuxes this will be /dev/ttyACM0 or /dev/ttyACM1
+UPLOAD_PORT        ?= /dev/ttyUSB0
+
+#Directory used to build files in, contains all the build files, from object files to the final hex file
+#on linux it is best to put an absolute path like /home/username/tmp .
+BUILD_DIR          ?= applet
+
+# This defines whether Liquid_TWI2 support will be built
+LIQUID_TWI2        ?= 0
+
+# this defines if Wire is needed
+WIRE               ?= 0
+
+# this defines if U8GLIB is needed (may require RELOC_WORKAROUND)
+U8GLIB             ?= 1
+
+# this defines whether to add a workaround for the avr-gcc relocation bug
+#	  https://www.stix.id.au/wiki/AVR_relocation_truncations_workaround
+RELOC_WORKAROUND   ?= 1
+
+############################################################################
+# 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", ...
+
+ifeq ($(HARDWARE_MOTHERBOARD),0)
+
+  # No motherboard selected
+
+#
+# RAMPS 1.3 / 1.4 - ATmega1280, ATmega2560
+#
+
+# MEGA/RAMPS up to 1.2
+else ifeq ($(HARDWARE_MOTHERBOARD),3)
+
+# RAMPS 1.3 (Power outputs: Hotend, Fan, Bed)
+else ifeq ($(HARDWARE_MOTHERBOARD),33)
+# RAMPS 1.3 (Power outputs: Hotend0, Hotend1, Bed)
+else ifeq ($(HARDWARE_MOTHERBOARD),34)
+# RAMPS 1.3 (Power outputs: Hotend, Fan0, Fan1)
+else ifeq ($(HARDWARE_MOTHERBOARD),35)
+# RAMPS 1.3 (Power outputs: Hotend0, Hotend1, Fan)
+else ifeq ($(HARDWARE_MOTHERBOARD),36)
+# RAMPS 1.3 (Power outputs: Spindle, Controller Fan)
+else ifeq ($(HARDWARE_MOTHERBOARD),38)
+
+# RAMPS 1.4 (Power outputs: Hotend, Fan, Bed)
+else ifeq ($(HARDWARE_MOTHERBOARD),43)
+# RAMPS 1.4 (Power outputs: Hotend0, Hotend1, Bed)
+else ifeq ($(HARDWARE_MOTHERBOARD),44)
+# RAMPS 1.4 (Power outputs: Hotend, Fan0, Fan1)
+else ifeq ($(HARDWARE_MOTHERBOARD),45)
+# RAMPS 1.4 (Power outputs: Hotend0, Hotend1, Fan)
+else ifeq ($(HARDWARE_MOTHERBOARD),46)
+# RAMPS 1.4 (Power outputs: Spindle, Controller Fan)
+else ifeq ($(HARDWARE_MOTHERBOARD),48)
+
+# RAMPS Plus 3DYMY (Power outputs: Hotend, Fan, Bed)
+else ifeq ($(HARDWARE_MOTHERBOARD),143)
+# RAMPS Plus 3DYMY (Power outputs: Hotend0, Hotend1, Bed)
+else ifeq ($(HARDWARE_MOTHERBOARD),144)
+# RAMPS Plus 3DYMY (Power outputs: Hotend, Fan0, Fan1)
+else ifeq ($(HARDWARE_MOTHERBOARD),145)
+# RAMPS Plus 3DYMY (Power outputs: Hotend0, Hotend1, Fan)
+else ifeq ($(HARDWARE_MOTHERBOARD),146)
+# RAMPS Plus 3DYMY (Power outputs: Spindle, Controller Fan)
+else ifeq ($(HARDWARE_MOTHERBOARD),148)
+
+#
+# RAMPS Derivatives - ATmega1280, ATmega2560
+#
+
+# 3Drag Controller
+else ifeq ($(HARDWARE_MOTHERBOARD),77)
+# Velleman K8200 Controller (derived from 3Drag Controller)
+else ifeq ($(HARDWARE_MOTHERBOARD),78)
+# Velleman K8400 Controller (derived from 3Drag Controller)
+else ifeq ($(HARDWARE_MOTHERBOARD),79)
+# 2PrintBeta BAM&DICE with STK drivers
+else ifeq ($(HARDWARE_MOTHERBOARD),401)
+# 2PrintBeta BAM&DICE Due with STK drivers
+else ifeq ($(HARDWARE_MOTHERBOARD),402)
+# MKS BASE v1.0
+else ifeq ($(HARDWARE_MOTHERBOARD),40)
+# MKS v1.5 with Allegro A4982 stepper drivers
+else ifeq ($(HARDWARE_MOTHERBOARD),405)
+# MKS BASE 1.0 with Heroic HR4982 stepper drivers
+else ifeq ($(HARDWARE_MOTHERBOARD),41)
+# MKS GEN v1.3 or 1.4
+else ifeq ($(HARDWARE_MOTHERBOARD),47)
+# MKS GEN L
+else ifeq ($(HARDWARE_MOTHERBOARD),53)
+# zrib V2.0 control board (Chinese knock off RAMPS replica)
+else ifeq ($(HARDWARE_MOTHERBOARD),504)
+# Felix 2.0+ Electronics Board (RAMPS like)
+else ifeq ($(HARDWARE_MOTHERBOARD),37)
+# Invent-A-Part RigidBoard
+else ifeq ($(HARDWARE_MOTHERBOARD),42)
+# Invent-A-Part RigidBoard V2
+else ifeq ($(HARDWARE_MOTHERBOARD),52)
+# Sainsmart 2-in-1 board
+else ifeq ($(HARDWARE_MOTHERBOARD),49)
+# Ultimaker
+else ifeq ($(HARDWARE_MOTHERBOARD),7)
+# Ultimaker (Older electronics. Pre 1.5.4. This is rare)
+else ifeq ($(HARDWARE_MOTHERBOARD),71)
+MCU ?= atmega1280
+# Azteeg X3
+else ifeq ($(HARDWARE_MOTHERBOARD),67)
+# Azteeg X3 Pro
+else ifeq ($(HARDWARE_MOTHERBOARD),68)
+# Ultimainboard 2.x (Uses TEMP_SENSOR 20)
+else ifeq ($(HARDWARE_MOTHERBOARD),72)
+# Rumba
+else ifeq ($(HARDWARE_MOTHERBOARD),80)
+# bq ZUM Mega 3D
+else ifeq ($(HARDWARE_MOTHERBOARD),503)
+# MakeBoard Mini v2.1.2 is a control board sold by MicroMake
+else ifeq ($(HARDWARE_MOTHERBOARD),431)
+# TriGorilla Anycubic version 1.3 based on RAMPS EFB
+else ifeq ($(HARDWARE_MOTHERBOARD),343)
+# TriGorilla Anycubic version 1.4 based on RAMPS EFB
+else ifeq ($(HARDWARE_MOTHERBOARD),443)
+# Creality: Ender-4, CR-8
+else ifeq ($(HARDWARE_MOTHERBOARD),243)
+
+#
+# Other ATmega1280, ATmega2560
+#
+
+# Cartesio CN Controls V11
+else ifeq ($(HARDWARE_MOTHERBOARD),111)
+# Cartesio CN Controls V12
+else ifeq ($(HARDWARE_MOTHERBOARD),112)
+# Cheaptronic v1.0
+else ifeq ($(HARDWARE_MOTHERBOARD),2)
+# Cheaptronic v2.0
+else ifeq ($(HARDWARE_MOTHERBOARD),21)
+# Makerbot Mightyboard Revision E
+else ifeq ($(HARDWARE_MOTHERBOARD),200)
+# Megatronics
+else ifeq ($(HARDWARE_MOTHERBOARD),70)
+# Megatronics v2.0
+else ifeq ($(HARDWARE_MOTHERBOARD),701)
+# Megatronics v3.0
+else ifeq ($(HARDWARE_MOTHERBOARD),703)
+# Megatronics v3.1
+else ifeq ($(HARDWARE_MOTHERBOARD),704)
+# Rambo
+else ifeq ($(HARDWARE_MOTHERBOARD),301)
+# Mini-Rambo
+else ifeq ($(HARDWARE_MOTHERBOARD),302)
+# Mini-Rambo 1.0a
+else ifeq ($(HARDWARE_MOTHERBOARD),303)
+# Einsy Rambo
+else ifeq ($(HARDWARE_MOTHERBOARD),304)
+# Einsy Retro
+else ifeq ($(HARDWARE_MOTHERBOARD),305)
+# Elefu Ra Board (v3)
+else ifeq ($(HARDWARE_MOTHERBOARD),21)
+# Leapfrog
+else ifeq ($(HARDWARE_MOTHERBOARD),999)
+# Mega controller
+else ifeq ($(HARDWARE_MOTHERBOARD),310)
+# abee Scoovo X9H
+else ifeq ($(HARDWARE_MOTHERBOARD),321)
+# Geeetech GT2560 Rev. A
+else ifeq ($(HARDWARE_MOTHERBOARD),74)
+# Geeetech GT2560 Rev. A+ (with auto level probe)
+else ifeq ($(HARDWARE_MOTHERBOARD),75)
+
+#
+# ATmega1281, ATmega2561
+#
+
+else ifeq ($(HARDWARE_MOTHERBOARD),702)
+MCU              ?= atmega1281
+else ifeq ($(HARDWARE_MOTHERBOARD),25)
+MCU              ?= atmega1281
+
+#
+# Sanguinololu and Derivatives - ATmega644P, ATmega1284P
+#
+
+# Sanguinololu < 1.2
+else ifeq ($(HARDWARE_MOTHERBOARD),6)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega644p
+# Sanguinololu 1.2 and above
+else ifeq ($(HARDWARE_MOTHERBOARD),62)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega644p
+# Melzi
+else ifeq ($(HARDWARE_MOTHERBOARD),63)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega644p
+# Melzi with ATmega1284 (MaKr3d version)
+else ifeq ($(HARDWARE_MOTHERBOARD),66)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega1284p
+# Melzi Creality3D board (for CR-10 etc)
+else ifeq ($(HARDWARE_MOTHERBOARD),89)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega1284p
+# Melzi Malyan M150 board
+else ifeq ($(HARDWARE_MOTHERBOARD),92)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega1284p
+# Tronxy X5S
+else ifeq ($(HARDWARE_MOTHERBOARD),505)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega1284p
+# STB V1.1
+else ifeq ($(HARDWARE_MOTHERBOARD),64)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega1284p
+# Azteeg X1
+else ifeq ($(HARDWARE_MOTHERBOARD),65)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega1284p
+# Anet 1.0 (Melzi clone)
+else ifeq ($(HARDWARE_MOTHERBOARD),69)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega1284p
+
+#
+# Other ATmega644P, ATmega644, ATmega1284P
+#
+
+# Gen3 Monolithic Electronics
+else ifeq ($(HARDWARE_MOTHERBOARD),22)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega644p
+# Gen3+
+else ifeq ($(HARDWARE_MOTHERBOARD),9)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega644p
+# Gen6
+else ifeq ($(HARDWARE_MOTHERBOARD),5)
+HARDWARE_VARIANT ?= Gen6
+MCU              ?= atmega644p
+# Gen6 deluxe
+else ifeq ($(HARDWARE_MOTHERBOARD),51)
+HARDWARE_VARIANT ?= Gen6
+MCU              ?= atmega644p
+# Gen7 custom (Alfons3 Version)
+else ifeq ($(HARDWARE_MOTHERBOARD),10)
+HARDWARE_VARIANT ?= Gen7
+MCU              ?= atmega644
+F_CPU            ?= 20000000
+# Gen7 v1.1, v1.2
+else ifeq ($(HARDWARE_MOTHERBOARD),11)
+HARDWARE_VARIANT ?= Gen7
+MCU              ?= atmega644p
+F_CPU            ?= 20000000
+# Gen7 v1.3
+else ifeq ($(HARDWARE_MOTHERBOARD),12)
+HARDWARE_VARIANT ?= Gen7
+MCU              ?= atmega644p
+F_CPU            ?= 20000000
+# Gen7 v1.4
+else ifeq ($(HARDWARE_MOTHERBOARD),13)
+HARDWARE_VARIANT ?= Gen7
+MCU              ?= atmega1284p
+F_CPU            ?= 20000000
+# 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
+# Sethi 3D_1
+else ifeq ($(HARDWARE_MOTHERBOARD),20)
+HARDWARE_VARIANT ?= Sanguino
+MCU              ?= atmega644p
+
+#
+# Teensyduino - AT90USB1286, AT90USB1286P
+#
+
+# Teensylu
+else ifeq ($(HARDWARE_MOTHERBOARD),8)
+HARDWARE_VARIANT ?= Teensy
+MCU              ?= at90usb1286
+# Printrboard (AT90USB1286)
+else ifeq ($(HARDWARE_MOTHERBOARD),81)
+HARDWARE_VARIANT ?= Teensy
+MCU              ?= at90usb1286
+# Printrboard Revision F (AT90USB1286)
+else ifeq ($(HARDWARE_MOTHERBOARD),811)
+HARDWARE_VARIANT ?= Teensy
+MCU              ?= at90usb1286
+# Brainwave (AT90USB646)
+else ifeq ($(HARDWARE_MOTHERBOARD),82)
+HARDWARE_VARIANT ?= Teensy
+MCU              ?= at90usb646
+# Brainwave Pro (AT90USB1286)
+else ifeq ($(HARDWARE_MOTHERBOARD),83)
+HARDWARE_VARIANT ?= Teensy
+MCU              ?= at90usb1286
+# SAV Mk-I (AT90USB1286)
+else ifeq ($(HARDWARE_MOTHERBOARD),84)
+HARDWARE_VARIANT ?= Teensy
+MCU              ?= at90usb1286
+# Teensy++2.0 (AT90USB1286) - CLI compile: HARDWARE_MOTHERBOARD=84  make
+else ifeq ($(HARDWARE_MOTHERBOARD),85)
+HARDWARE_VARIANT ?= Teensy
+MCU              ?= at90usb1286
+# 5DPrint D8 Driver Board
+else ifeq ($(HARDWARE_MOTHERBOARD),88)
+HARDWARE_VARIANT ?= Teensy
+MCU              ?= at90usb1286
+
+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
+
+# Set to arduino, ATmega2560 if not yet set.
+HARDWARE_VARIANT ?= arduino
+MCU ?= atmega2560
+
+# Arduino contained 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
+
+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 += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/cores/arduino
+
+VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI
+VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI/src
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/LiquidCrystal/src
+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
+ifeq ($(NEOPIXEL), 1)
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Adafruit_NeoPixel
+endif
+ifeq ($(U8GLIB), 1)
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib/utility
+endif
+
+ifeq ($(HARDWARE_VARIANT), arduino)
+HARDWARE_SUB_VARIANT ?= mega
+VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/variants/$(HARDWARE_SUB_VARIANT)
+else
+ifeq ($(HARDWARE_VARIANT), Sanguino)
+VPATH += $(HARDWARE_DIR)/marlin/avr/variants/sanguino
+else
+HARDWARE_SUB_VARIANT ?= standard
+VPATH += $(HARDWARE_DIR)/$(HARDWARE_VARIANT)/variants/$(HARDWARE_SUB_VARIANT)
+endif
+endif
+SRC = wiring.c \
+	wiring_analog.c wiring_digital.c \
+	wiring_pulse.c \
+	wiring_shift.c WInterrupts.c hooks.c
+ifeq ($(HARDWARE_VARIANT), Teensy)
+SRC = wiring.c
+VPATH += $(ARDUINO_INSTALL_DIR)/hardware/teensy/cores/teensy
+endif
+CXXSRC = WMath.cpp WString.cpp Print.cpp SPI.cpp Tone.cpp
+CXXSRC += $(wildcard *.cpp)
+ifeq ($(NEOPIXEL), 1)
+CXXSRC += Adafruit_NeoPixel.cpp
+endif
+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
+
+ifeq ($(U8GLIB), 1)
+SRC += u8g_ll_api.c u8g_bitmap.c u8g_clip.c u8g_com_null.c u8g_delay.c u8g_page.c u8g_pb.c u8g_pb16h1.c u8g_rect.c u8g_state.c u8g_font.c u8g_font_data.c
+endif
+
+ifeq ($(RELOC_WORKAROUND), 1)
+LD_PREFIX=-nodefaultlibs
+LD_SUFFIX=-lm -lgcc -lc -lgcc -L$(ARDUINO_INSTALL_DIR)/hardware/tools/avr/avr/lib/avr6 -l$(MCU)
+endif
+
+#Check for Arduino 1.0.0 or higher and use the correct source files 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/CPP Standard level.
+CSTANDARD = -std=gnu99
+CXXSTANDARD = -std=gnu++11
+CDEBUG = -g$(DEBUG)
+CWARN = -Wall -Wstrict-prototypes
+CTUNING = -w -fsigned-char -funsigned-bitfields -fpack-struct \
+	-fshort-enums -ffunction-sections -fdata-sections -flto \
+	-DARDUINO=$(ARDUINO_VERSION)
+ifneq ($(HARDWARE_MOTHERBOARD),)
+CTUNING += -DMOTHERBOARD=${HARDWARE_MOTHERBOARD}
+endif
+#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
+CEXTRA = -fno-use-cxa-atexit -fno-threadsafe-statics
+
+CFLAGS := $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CEXTRA) $(CTUNING) $(CSTANDARD)
+CXXFLAGS :=         $(CDEFS) $(CINCS) -O$(OPT) -Wall    $(CEXTRA) $(CTUNING) $(CXXSTANDARD)
+#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
+LDFLAGS = -lm
+
+
+# Programming support using avrdude. Settings and variables.
+AVRDUDE_PORT = $(UPLOAD_PORT)
+AVRDUDE_WRITE_FLASH = -Uflash:w:$(BUILD_DIR)/$(TARGET).hex:i
+ifeq ($(shell uname -s), Linux)
+AVRDUDE_CONF = /etc/avrdude/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) $(LD_PREFIX) $(ALL_CXXFLAGS) -Wl,--gc-sections,--relax -o $@ -L. $(OBJ) $(LDFLAGS) $(LD_SUFFIX)
+
+$(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}

+ 647 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Marlin.h

@@ -0,0 +1,647 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#ifndef MARLIN_H
+#define MARLIN_H
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <util/delay.h>
+#include <avr/eeprom.h>
+#include <avr/interrupt.h>
+
+#include "MarlinConfig.h"
+
+#ifdef DEBUG_GCODE_PARSER
+  #include "parser.h"
+#endif
+
+#include "enum.h"
+#include "types.h"
+#include "fastio.h"
+#include "utility.h"
+#include "serial.h"
+
+void idle(
+  #if ENABLED(ADVANCED_PAUSE_FEATURE)
+    bool no_stepper_sleep = false  // pass true to keep steppers from disabling on timeout
+  #endif
+);
+
+void manage_inactivity(const bool ignore_stepper_queue=false);
+
+extern const char axis_codes[XYZE];
+
+#if ENABLED(DUAL_X_CARRIAGE) || ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
+  extern bool extruder_duplication_enabled;
+#endif
+
+#if HAS_X2_ENABLE
+  #define  enable_X() do{ X_ENABLE_WRITE( X_ENABLE_ON); X2_ENABLE_WRITE( X_ENABLE_ON); }while(0)
+  #define disable_X() do{ X_ENABLE_WRITE(!X_ENABLE_ON); X2_ENABLE_WRITE(!X_ENABLE_ON); CBI(axis_known_position, X_AXIS); }while(0)
+#elif HAS_X_ENABLE
+  #define  enable_X() X_ENABLE_WRITE( X_ENABLE_ON)
+  #define disable_X() do{ X_ENABLE_WRITE(!X_ENABLE_ON); CBI(axis_known_position, X_AXIS); }while(0)
+#else
+  #define  enable_X() NOOP
+  #define disable_X() NOOP
+#endif
+
+#if HAS_Y2_ENABLE
+  #define  enable_Y() do{ Y_ENABLE_WRITE( Y_ENABLE_ON); Y2_ENABLE_WRITE(Y_ENABLE_ON); }while(0)
+  #define disable_Y() do{ Y_ENABLE_WRITE(!Y_ENABLE_ON); Y2_ENABLE_WRITE(!Y_ENABLE_ON); CBI(axis_known_position, Y_AXIS); }while(0)
+#elif HAS_Y_ENABLE
+  #define  enable_Y() Y_ENABLE_WRITE( Y_ENABLE_ON)
+  #define disable_Y() do{ Y_ENABLE_WRITE(!Y_ENABLE_ON); CBI(axis_known_position, Y_AXIS); }while(0)
+#else
+  #define  enable_Y() NOOP
+  #define disable_Y() NOOP
+#endif
+
+#if HAS_Z2_ENABLE
+  #define  enable_Z() do{ Z_ENABLE_WRITE( Z_ENABLE_ON); Z2_ENABLE_WRITE(Z_ENABLE_ON); }while(0)
+  #define disable_Z() do{ Z_ENABLE_WRITE(!Z_ENABLE_ON); Z2_ENABLE_WRITE(!Z_ENABLE_ON); CBI(axis_known_position, Z_AXIS); }while(0)
+#elif HAS_Z_ENABLE
+  #define  enable_Z() Z_ENABLE_WRITE( Z_ENABLE_ON)
+  #define disable_Z() do{ Z_ENABLE_WRITE(!Z_ENABLE_ON); CBI(axis_known_position, Z_AXIS); }while(0)
+#else
+  #define  enable_Z() NOOP
+  #define disable_Z() NOOP
+#endif
+
+#if ENABLED(MIXING_EXTRUDER)
+
+  /**
+   * Mixing steppers synchronize their enable (and direction) together
+   */
+  #if MIXING_STEPPERS > 4
+    #define  enable_E0() { E0_ENABLE_WRITE( E_ENABLE_ON); E1_ENABLE_WRITE( E_ENABLE_ON); E2_ENABLE_WRITE( E_ENABLE_ON); E3_ENABLE_WRITE( E_ENABLE_ON); E4_ENABLE_WRITE( E_ENABLE_ON); }
+    #define disable_E0() { E0_ENABLE_WRITE(!E_ENABLE_ON); E1_ENABLE_WRITE(!E_ENABLE_ON); E2_ENABLE_WRITE(!E_ENABLE_ON); E3_ENABLE_WRITE(!E_ENABLE_ON); E4_ENABLE_WRITE(!E_ENABLE_ON); }
+  #elif MIXING_STEPPERS > 3
+    #define  enable_E0() { E0_ENABLE_WRITE( E_ENABLE_ON); E1_ENABLE_WRITE( E_ENABLE_ON); E2_ENABLE_WRITE( E_ENABLE_ON); E3_ENABLE_WRITE( E_ENABLE_ON); }
+    #define disable_E0() { E0_ENABLE_WRITE(!E_ENABLE_ON); E1_ENABLE_WRITE(!E_ENABLE_ON); E2_ENABLE_WRITE(!E_ENABLE_ON); E3_ENABLE_WRITE(!E_ENABLE_ON); }
+  #elif MIXING_STEPPERS > 2
+    #define  enable_E0() { E0_ENABLE_WRITE( E_ENABLE_ON); E1_ENABLE_WRITE( E_ENABLE_ON); E2_ENABLE_WRITE( E_ENABLE_ON); }
+    #define disable_E0() { E0_ENABLE_WRITE(!E_ENABLE_ON); E1_ENABLE_WRITE(!E_ENABLE_ON); E2_ENABLE_WRITE(!E_ENABLE_ON); }
+  #else
+    #define  enable_E0() { E0_ENABLE_WRITE( E_ENABLE_ON); E1_ENABLE_WRITE( E_ENABLE_ON); }
+    #define disable_E0() { E0_ENABLE_WRITE(!E_ENABLE_ON); E1_ENABLE_WRITE(!E_ENABLE_ON); }
+  #endif
+  #define  enable_E1() NOOP
+  #define disable_E1() NOOP
+  #define  enable_E2() NOOP
+  #define disable_E2() NOOP
+  #define  enable_E3() NOOP
+  #define disable_E3() NOOP
+  #define  enable_E4() NOOP
+  #define disable_E4() NOOP
+
+#else // !MIXING_EXTRUDER
+
+  #if HAS_E0_ENABLE
+    #define  enable_E0() E0_ENABLE_WRITE( E_ENABLE_ON)
+    #define disable_E0() E0_ENABLE_WRITE(!E_ENABLE_ON)
+  #else
+    #define  enable_E0() NOOP
+    #define disable_E0() NOOP
+  #endif
+
+  #if E_STEPPERS > 1 && HAS_E1_ENABLE
+    #define  enable_E1() E1_ENABLE_WRITE( E_ENABLE_ON)
+    #define disable_E1() E1_ENABLE_WRITE(!E_ENABLE_ON)
+  #else
+    #define  enable_E1() NOOP
+    #define disable_E1() NOOP
+  #endif
+
+  #if E_STEPPERS > 2 && HAS_E2_ENABLE
+    #define  enable_E2() E2_ENABLE_WRITE( E_ENABLE_ON)
+    #define disable_E2() E2_ENABLE_WRITE(!E_ENABLE_ON)
+  #else
+    #define  enable_E2() NOOP
+    #define disable_E2() NOOP
+  #endif
+
+  #if E_STEPPERS > 3 && HAS_E3_ENABLE
+    #define  enable_E3() E3_ENABLE_WRITE( E_ENABLE_ON)
+    #define disable_E3() E3_ENABLE_WRITE(!E_ENABLE_ON)
+  #else
+    #define  enable_E3() NOOP
+    #define disable_E3() NOOP
+  #endif
+
+  #if E_STEPPERS > 4 && HAS_E4_ENABLE
+    #define  enable_E4() E4_ENABLE_WRITE( E_ENABLE_ON)
+    #define disable_E4() E4_ENABLE_WRITE(!E_ENABLE_ON)
+  #else
+    #define  enable_E4() NOOP
+    #define disable_E4() NOOP
+  #endif
+
+#endif // !MIXING_EXTRUDER
+
+#if ENABLED(HANGPRINTER)
+
+  #define enable_A() enable_X()
+  #define enable_B() enable_Y()
+  #define enable_C() enable_Z()
+  #define __D_ENABLE(p) E##p##_ENABLE_WRITE(E_ENABLE_ON)
+  #define _D_ENABLE(p) __D_ENABLE(p)
+  #define enable_D() _D_ENABLE(EXTRUDERS)
+
+  // Don't allow any axes to be disabled
+  #undef disable_X
+  #undef disable_Y
+  #undef disable_Z
+  #define disable_X() NOOP
+  #define disable_Y() NOOP
+  #define disable_Z() NOOP
+
+  #if EXTRUDERS >= 1
+    #undef disable_E1
+    #define disable_E1() NOOP
+    #if EXTRUDERS >= 2
+      #undef disable_E2
+      #define disable_E2() NOOP
+      #if EXTRUDERS >= 3
+        #undef disable_E3
+        #define disable_E3() NOOP
+        #if EXTRUDERS >= 4
+          #undef disable_E4
+          #define disable_E4() NOOP
+        #endif // EXTRUDERS >= 4
+      #endif // EXTRUDERS >= 3
+    #endif // EXTRUDERS >= 2
+  #endif // EXTRUDERS >= 1
+
+#endif // HANGPRINTER
+
+#if ENABLED(G38_PROBE_TARGET)
+  extern bool G38_move,        // flag to tell the interrupt handler that a G38 command is being run
+              G38_endstop_hit; // flag from the interrupt handler to indicate if the endstop went active
+#endif
+
+void enable_all_steppers();
+void disable_e_stepper(const uint8_t e);
+void disable_e_steppers();
+void disable_all_steppers();
+
+void sync_plan_position();
+void sync_plan_position_e();
+
+#if IS_KINEMATIC
+  void sync_plan_position_kinematic();
+  #define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position_kinematic()
+#else
+  #define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position()
+#endif
+
+void flush_and_request_resend();
+void ok_to_send();
+
+void kill(const char*);
+
+void quickstop_stepper();
+
+extern uint8_t marlin_debug_flags;
+#define DEBUGGING(F) (marlin_debug_flags & (DEBUG_## F))
+
+extern bool Running;
+inline bool IsRunning() { return  Running; }
+inline bool IsStopped() { return !Running; }
+
+bool enqueue_and_echo_command(const char* cmd);           // Add a single command to the end of the buffer. Return false on failure.
+void enqueue_and_echo_commands_P(const char * const cmd); // Set one or more commands to be prioritized over the next Serial/SD command.
+void clear_command_queue();
+
+#if ENABLED(M100_FREE_MEMORY_WATCHER) || ENABLED(POWER_LOSS_RECOVERY)
+  extern char command_queue[BUFSIZE][MAX_CMD_SIZE];
+#endif
+
+#define HAS_LCD_QUEUE_NOW (ENABLED(MALYAN_LCD) || (ENABLED(ULTIPANEL) && (ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(PID_AUTOTUNE_MENU) || ENABLED(ADVANCED_PAUSE_FEATURE))))
+#define HAS_QUEUE_NOW (ENABLED(SDSUPPORT) || HAS_LCD_QUEUE_NOW)
+#if HAS_QUEUE_NOW
+  // Return only when commands are actually enqueued
+  void enqueue_and_echo_command_now(const char* cmd);
+  #if HAS_LCD_QUEUE_NOW
+    void enqueue_and_echo_commands_now_P(const char * const cmd);
+  #endif
+#endif
+
+extern millis_t previous_move_ms;
+inline void reset_stepper_timeout() { previous_move_ms = millis(); }
+
+/**
+ * Feedrate scaling and conversion
+ */
+extern float feedrate_mm_s;
+extern int16_t feedrate_percentage;
+
+#define MMS_SCALED(MM_S) ((MM_S)*feedrate_percentage*0.01f)
+
+extern bool axis_relative_modes[XYZE];
+
+extern uint8_t axis_homed, axis_known_position;
+
+constexpr uint8_t xyz_bits = _BV(X_AXIS) | _BV(Y_AXIS) | _BV(Z_AXIS);
+FORCE_INLINE bool all_axes_homed() { return (axis_homed & xyz_bits) == xyz_bits; }
+FORCE_INLINE bool all_axes_known() { return (axis_known_position & xyz_bits) == xyz_bits; }
+
+extern volatile bool wait_for_heatup;
+
+#if HAS_RESUME_CONTINUE
+  extern volatile bool wait_for_user;
+#endif
+
+#if HAS_AUTO_REPORTING || ENABLED(HOST_KEEPALIVE_FEATURE)
+  extern bool suspend_auto_report;
+#endif
+
+extern float current_position[XYZE], destination[XYZE];
+
+/**
+ * Workspace offsets
+ */
+#if HAS_WORKSPACE_OFFSET
+  #if HAS_HOME_OFFSET
+    extern float home_offset[XYZ];
+  #endif
+  #if HAS_POSITION_SHIFT
+    extern float position_shift[XYZ];
+  #endif
+  #if HAS_HOME_OFFSET && HAS_POSITION_SHIFT
+    extern float workspace_offset[XYZ];
+    #define WORKSPACE_OFFSET(AXIS) workspace_offset[AXIS]
+  #elif HAS_HOME_OFFSET
+    #define WORKSPACE_OFFSET(AXIS) home_offset[AXIS]
+  #elif HAS_POSITION_SHIFT
+    #define WORKSPACE_OFFSET(AXIS) position_shift[AXIS]
+  #endif
+  #define NATIVE_TO_LOGICAL(POS, AXIS) ((POS) + WORKSPACE_OFFSET(AXIS))
+  #define LOGICAL_TO_NATIVE(POS, AXIS) ((POS) - WORKSPACE_OFFSET(AXIS))
+#else
+  #define NATIVE_TO_LOGICAL(POS, AXIS) (POS)
+  #define LOGICAL_TO_NATIVE(POS, AXIS) (POS)
+#endif
+#define LOGICAL_X_POSITION(POS) NATIVE_TO_LOGICAL(POS, X_AXIS)
+#define LOGICAL_Y_POSITION(POS) NATIVE_TO_LOGICAL(POS, Y_AXIS)
+#define LOGICAL_Z_POSITION(POS) NATIVE_TO_LOGICAL(POS, Z_AXIS)
+#define RAW_X_POSITION(POS)     LOGICAL_TO_NATIVE(POS, X_AXIS)
+#define RAW_Y_POSITION(POS)     LOGICAL_TO_NATIVE(POS, Y_AXIS)
+#define RAW_Z_POSITION(POS)     LOGICAL_TO_NATIVE(POS, Z_AXIS)
+
+// Hotend Offsets
+#if HOTENDS > 1
+  extern float hotend_offset[XYZ][HOTENDS];
+#endif
+
+// Software Endstops
+extern float soft_endstop_min[XYZ], soft_endstop_max[XYZ];
+
+#if HAS_SOFTWARE_ENDSTOPS
+  extern bool soft_endstops_enabled;
+  void clamp_to_software_endstops(float target[XYZ]);
+#else
+  #define soft_endstops_enabled false
+  #define clamp_to_software_endstops(x) NOOP
+#endif
+
+#if HAS_WORKSPACE_OFFSET || ENABLED(DUAL_X_CARRIAGE)
+  void update_software_endstops(const AxisEnum axis);
+#endif
+
+#define MAX_COORDINATE_SYSTEMS 9
+#if ENABLED(CNC_COORDINATE_SYSTEMS)
+  extern float coordinate_system[MAX_COORDINATE_SYSTEMS][XYZ];
+  bool select_coordinate_system(const int8_t _new);
+#endif
+
+void tool_change(const uint8_t tmp_extruder, const float fr_mm_s=0.0, bool no_move=false);
+
+void home_all_axes();
+
+void report_current_position();
+
+#if IS_KINEMATIC
+  #if ENABLED(HANGPRINTER)
+    extern float line_lengths[ABCD];
+  #else
+    extern float delta[ABC];
+  #endif
+  void inverse_kinematics(const float raw[XYZ]);
+#endif
+
+#if ENABLED(DELTA)
+  extern float delta_height,
+               delta_endstop_adj[ABC],
+               delta_radius,
+               delta_tower_angle_trim[ABC],
+               delta_tower[ABC][2],
+               delta_diagonal_rod,
+               delta_calibration_radius,
+               delta_diagonal_rod_2_tower[ABC],
+               delta_segments_per_second,
+               delta_clip_start_height;
+
+  void recalc_delta_settings();
+  float delta_safe_distance_from_top();
+
+  // Macro to obtain the Z position of an individual tower
+  #define DELTA_Z(V,T) V[Z_AXIS] + SQRT(    \
+    delta_diagonal_rod_2_tower[T] - HYPOT2( \
+        delta_tower[T][X_AXIS] - V[X_AXIS], \
+        delta_tower[T][Y_AXIS] - V[Y_AXIS]  \
+      )                                     \
+    )
+
+  #define DELTA_IK(V) do {              \
+    delta[A_AXIS] = DELTA_Z(V, A_AXIS); \
+    delta[B_AXIS] = DELTA_Z(V, B_AXIS); \
+    delta[C_AXIS] = DELTA_Z(V, C_AXIS); \
+  }while(0)
+
+#elif ENABLED(HANGPRINTER)
+
+  // Don't collect anchor positions in array because there are no A_x, D_x or D_y
+  extern float anchor_A_y,
+               anchor_A_z,
+               anchor_B_x,
+               anchor_B_y,
+               anchor_B_z,
+               anchor_C_x,
+               anchor_C_y,
+               anchor_C_z,
+               anchor_D_z,
+               delta_segments_per_second,
+               line_lengths_origin[ABCD];
+
+  void recalc_hangprinter_settings();
+
+  #define HANGPRINTER_IK(V) do {                             \
+    line_lengths[A_AXIS] = SQRT(sq(anchor_A_z - V[Z_AXIS])   \
+                              + sq(anchor_A_y - V[Y_AXIS])   \
+                              + sq(             V[X_AXIS])); \
+    line_lengths[B_AXIS] = SQRT(sq(anchor_B_z - V[Z_AXIS])   \
+                              + sq(anchor_B_y - V[Y_AXIS])   \
+                              + sq(anchor_B_x - V[X_AXIS])); \
+    line_lengths[C_AXIS] = SQRT(sq(anchor_C_z - V[Z_AXIS])   \
+                              + sq(anchor_C_y - V[Y_AXIS])   \
+                              + sq(anchor_C_x - V[X_AXIS])); \
+    line_lengths[D_AXIS] = SQRT(sq(             V[X_AXIS])   \
+                              + sq(             V[Y_AXIS])   \
+                              + sq(anchor_D_z - V[Z_AXIS])); \
+  }while(0)
+
+  // Inverse kinematics at origin
+  #define HANGPRINTER_IK_ORIGIN(LL) do { \
+    LL[A_AXIS] = SQRT(sq(anchor_A_z)     \
+                    + sq(anchor_A_y));   \
+    LL[B_AXIS] = SQRT(sq(anchor_B_z)     \
+                    + sq(anchor_B_y)     \
+                    + sq(anchor_B_x));   \
+    LL[C_AXIS] = SQRT(sq(anchor_C_z)     \
+                    + sq(anchor_C_y)     \
+                    + sq(anchor_C_x));   \
+    LL[D_AXIS] = anchor_D_z;             \
+  }while(0)
+
+#elif IS_SCARA
+  void forward_kinematics_SCARA(const float &a, const float &b);
+#endif
+
+#if ENABLED(G26_MESH_VALIDATION)
+  extern bool g26_debug_flag;
+#elif ENABLED(AUTO_BED_LEVELING_UBL)
+  constexpr bool g26_debug_flag = false;
+#endif
+
+#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
+  #define _GET_MESH_X(I) (bilinear_start[X_AXIS] + (I) * bilinear_grid_spacing[X_AXIS])
+  #define _GET_MESH_Y(J) (bilinear_start[Y_AXIS] + (J) * bilinear_grid_spacing[Y_AXIS])
+#elif ENABLED(AUTO_BED_LEVELING_UBL)
+  #define _GET_MESH_X(I) ubl.mesh_index_to_xpos(I)
+  #define _GET_MESH_Y(J) ubl.mesh_index_to_ypos(J)
+#elif ENABLED(MESH_BED_LEVELING)
+  #define _GET_MESH_X(I) mbl.index_to_xpos[I]
+  #define _GET_MESH_Y(J) mbl.index_to_ypos[J]
+#endif
+
+#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
+  extern int bilinear_grid_spacing[2], bilinear_start[2];
+  extern float bilinear_grid_factor[2],
+               z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
+  float bilinear_z_offset(const float raw[XYZ]);
+#endif
+
+#if ENABLED(AUTO_BED_LEVELING_BILINEAR) || ENABLED(MESH_BED_LEVELING)
+  typedef float (*element_2d_fn)(const uint8_t, const uint8_t);
+  void print_2d_array(const uint8_t sx, const uint8_t sy, const uint8_t precision, const element_2d_fn fn);
+#endif
+
+#if HAS_LEVELING
+  bool leveling_is_valid();
+  void set_bed_leveling_enabled(const bool enable=true);
+  void reset_bed_level();
+#endif
+
+#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
+  void set_z_fade_height(const float zfh, const bool do_report=true);
+#endif
+
+#if HAS_BED_PROBE
+  extern float zprobe_zoffset;
+  bool set_probe_deployed(const bool deploy);
+  #ifdef Z_AFTER_PROBING
+    void move_z_after_probing();
+  #endif
+  enum ProbePtRaise : unsigned char {
+    PROBE_PT_NONE,  // No raise or stow after run_z_probe
+    PROBE_PT_STOW,  // Do a complete stow after run_z_probe
+    PROBE_PT_RAISE, // Raise to "between" clearance after run_z_probe
+    PROBE_PT_BIG_RAISE  // Raise to big clearance after run_z_probe
+  };
+  float probe_pt(const float &rx, const float &ry, const ProbePtRaise raise_after=PROBE_PT_NONE, const uint8_t verbose_level=0, const bool probe_relative=true);
+  #define DEPLOY_PROBE() set_probe_deployed(true)
+  #define STOW_PROBE() set_probe_deployed(false)
+#else
+  #define DEPLOY_PROBE()
+  #define STOW_PROBE()
+#endif
+
+#if ENABLED(HOST_KEEPALIVE_FEATURE)
+  extern MarlinBusyState busy_state;
+  #define KEEPALIVE_STATE(n) do{ busy_state = n; }while(0)
+#else
+  #define KEEPALIVE_STATE(n) NOOP
+#endif
+
+#if FAN_COUNT > 0
+  extern int16_t fanSpeeds[FAN_COUNT];
+  #if ENABLED(EXTRA_FAN_SPEED)
+    extern int16_t old_fanSpeeds[FAN_COUNT],
+                   new_fanSpeeds[FAN_COUNT];
+  #endif
+  #if ENABLED(PROBING_FANS_OFF)
+    extern bool fans_paused;
+    extern int16_t paused_fanSpeeds[FAN_COUNT];
+  #endif
+#endif
+
+#if ENABLED(USE_CONTROLLER_FAN)
+  extern int controllerFanSpeed;
+#endif
+
+#if ENABLED(BARICUDA)
+  extern uint8_t baricuda_valve_pressure, baricuda_e_to_p_pressure;
+#endif
+
+#if ENABLED(FILAMENT_WIDTH_SENSOR)
+  extern bool filament_sensor;         // Flag that filament sensor readings should control extrusion
+  extern float filament_width_nominal, // Theoretical filament diameter i.e., 3.00 or 1.75
+               filament_width_meas;    // Measured filament diameter
+  extern uint8_t meas_delay_cm;        // Delay distance
+  extern int8_t measurement_delay[MAX_MEASUREMENT_DELAY + 1],  // Ring buffer to delay measurement
+                filwidth_delay_index[2]; // Ring buffer indexes. Used by planner, temperature, and main code
+#endif
+
+#if ENABLED(ADVANCED_PAUSE_FEATURE)
+  extern int8_t did_pause_print;
+  extern AdvancedPauseMenuResponse advanced_pause_menu_response;
+  extern float filament_change_unload_length[EXTRUDERS],
+               filament_change_load_length[EXTRUDERS];
+#endif
+
+#if HAS_POWER_SWITCH
+  extern bool powersupply_on;
+  #define PSU_PIN_ON()  do{ OUT_WRITE(PS_ON_PIN, PS_ON_AWAKE); powersupply_on = true; }while(0)
+  #define PSU_PIN_OFF() do{ OUT_WRITE(PS_ON_PIN, PS_ON_ASLEEP); powersupply_on = false; }while(0)
+#endif
+
+// Handling multiple extruders pins
+extern uint8_t active_extruder;
+
+#if ENABLED(MIXING_EXTRUDER)
+  extern float mixing_factor[MIXING_STEPPERS];
+#endif
+
+inline void set_current_from_destination() { COPY(current_position, destination); }
+inline void set_destination_from_current() { COPY(destination, current_position); }
+void prepare_move_to_destination();
+
+/**
+ * Blocking movement and shorthand functions
+ */
+void do_blocking_move_to(const float rx, const float ry, const float rz, const float &fr_mm_s=0);
+void do_blocking_move_to_x(const float &rx, const float &fr_mm_s=0);
+void do_blocking_move_to_z(const float &rz, const float &fr_mm_s=0);
+void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm_s=0);
+
+#if ENABLED(ARC_SUPPORT)
+  void plan_arc(const float(&cart)[XYZE], const float(&offset)[2], const bool clockwise);
+#endif
+
+#define HAS_AXIS_UNHOMED_ERR (                                                     \
+         ENABLED(Z_PROBE_ALLEN_KEY)                                                \
+      || ENABLED(Z_PROBE_SLED)                                                     \
+      || HAS_PROBING_PROCEDURE                                                     \
+      || HOTENDS > 1                                                               \
+      || ENABLED(NOZZLE_CLEAN_FEATURE)                                             \
+      || ENABLED(NOZZLE_PARK_FEATURE)                                              \
+      || (ENABLED(ADVANCED_PAUSE_FEATURE) && ENABLED(HOME_BEFORE_FILAMENT_CHANGE)) \
+      || HAS_M206_COMMAND                                                          \
+    ) || ENABLED(NO_MOTION_BEFORE_HOMING)
+
+#if HAS_AXIS_UNHOMED_ERR
+  bool axis_unhomed_error(const bool x=true, const bool y=true, const bool z=true);
+#endif
+
+/**
+ * position_is_reachable family of functions
+ */
+
+#if IS_KINEMATIC // (DELTA or SCARA)
+
+  #if IS_SCARA
+    extern const float L1, L2;
+  #endif
+
+  // Return true if the given point is within the printable area
+  inline bool position_is_reachable(const float &rx, const float &ry, const float inset=0) {
+    #if ENABLED(DELTA)
+      return HYPOT2(rx, ry) <= sq(DELTA_PRINTABLE_RADIUS - inset);
+    #elif ENABLED(HANGPRINTER)
+      // TODO: This is over simplified. Hangprinter's build volume is _not_ cylindrical.
+      return HYPOT2(rx, ry) <= sq(HANGPRINTER_PRINTABLE_RADIUS - inset);
+    #elif IS_SCARA
+      const float R2 = HYPOT2(rx - SCARA_OFFSET_X, ry - SCARA_OFFSET_Y);
+      return (
+        R2 <= sq(L1 + L2) - inset
+        #if MIDDLE_DEAD_ZONE_R > 0
+          && R2 >= sq(float(MIDDLE_DEAD_ZONE_R))
+        #endif
+      );
+    #endif
+  }
+
+  #if HAS_BED_PROBE
+    // Return true if the both nozzle and the probe can reach the given point.
+    // Note: This won't work on SCARA since the probe offset rotates with the arm.
+    inline bool position_is_reachable_by_probe(const float &rx, const float &ry) {
+      return position_is_reachable(rx - (X_PROBE_OFFSET_FROM_EXTRUDER), ry - (Y_PROBE_OFFSET_FROM_EXTRUDER))
+             && position_is_reachable(rx, ry, ABS(MIN_PROBE_EDGE));
+    }
+  #endif
+
+#else // CARTESIAN
+
+   // Return true if the given position is within the machine bounds.
+  inline bool position_is_reachable(const float &rx, const float &ry) {
+    // Add 0.001 margin to deal with float imprecision
+    return WITHIN(rx, X_MIN_POS - 0.001f, X_MAX_POS + 0.001f)
+        && WITHIN(ry, Y_MIN_POS - 0.001f, Y_MAX_POS + 0.001f);
+  }
+
+  #if HAS_BED_PROBE
+    /**
+     * Return whether the given position is within the bed, and whether the nozzle
+     * can reach the position required to put the probe at the given position.
+     *
+     * Example: For a probe offset of -10,+10, then for the probe to reach 0,0 the
+     *          nozzle must be be able to reach +10,-10.
+     */
+    inline bool position_is_reachable_by_probe(const float &rx, const float &ry) {
+      return position_is_reachable(rx - (X_PROBE_OFFSET_FROM_EXTRUDER), ry - (Y_PROBE_OFFSET_FROM_EXTRUDER))
+          && WITHIN(rx, MIN_PROBE_X - 0.001f, MAX_PROBE_X + 0.001f)
+          && WITHIN(ry, MIN_PROBE_Y - 0.001f, MAX_PROBE_Y + 0.001f);
+    }
+  #endif
+
+#endif // CARTESIAN
+
+#if !HAS_BED_PROBE
+  FORCE_INLINE bool position_is_reachable_by_probe(const float &rx, const float &ry) { return position_is_reachable(rx, ry); }
+#endif
+
+#endif // MARLIN_H

+ 53 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Marlin.ino

@@ -0,0 +1,53 @@
+/*
+================================================================================
+
+  Marlin Firmware
+
+  (c) 2011-2018 MarlinFirmware
+  Portions of Marlin are (c) by their respective authors.
+  All code complies with GPLv2 and/or GPLv3
+
+================================================================================
+
+Greetings! Thank you for choosing Marlin as your 3D printer firmware.
+
+To configure Marlin you must edit Configuration.h and Configuration_adv.h
+located in the root 'Marlin' folder. Check the example_configurations folder to
+see if there's a more suitable starting-point for your specific hardware.
+
+Before diving in, we recommend the following essential links:
+
+Marlin Firmware Official Website
+
+  - http://marlinfw.org/
+    The official Marlin Firmware website contains the most up-to-date
+    documentation. Contributions are always welcome!
+
+Configuration
+
+  - https://www.youtube.com/watch?v=3gwWVFtdg-4
+    A good 20-minute overview of Marlin configuration by Tom Sanladerer.
+    (Applies to Marlin 1.0.x, so Jerk and Acceleration should be halved.)
+    Also... https://www.google.com/search?tbs=vid%3A1&q=configure+marlin
+
+  - http://marlinfw.org/docs/configuration/configuration.html
+    Marlin's configuration options are explained in more detail here.
+
+Getting Help
+
+  - http://forums.reprap.org/list.php?415
+    The Marlin Discussion Forum is a great place to get help from other Marlin
+    users who may have experienced similar issues to your own.
+
+  - https://github.com/MarlinFirmware/Marlin/issues
+    With a free GitHub account you can provide us with feedback, bug reports,
+    and feature requests via the Marlin Issue Queue.
+
+Contributing
+
+  - http://marlinfw.org/docs/development/contributing.html
+    If you'd like to contribute to Marlin, read this first!
+
+  - http://marlinfw.org/docs/development/coding_standards.html
+    Before submitting code get to know the Coding Standards.
+*/

+ 48 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/MarlinConfig.h

@@ -0,0 +1,48 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MARLIN_CONFIG_H
+#define MARLIN_CONFIG_H
+
+#include "boards.h"
+#include "macros.h"
+#include "Version.h"
+#include "Configuration.h"
+#include "Conditionals_LCD.h"
+#include "drivers.h"
+#include "Configuration_adv.h"
+
+#if USE_MARLINSERIAL
+  #define HardwareSerial_h // trick to disable the standard HWserial
+#endif
+
+#include "types.h"
+#include "HAL.h"
+#include "pins.h"
+#include "Conditionals_post.h"
+#include "SanityCheck.h"
+#include "enum.h"
+#include "language.h"
+#include "utility.h"
+#include "serial.h"
+
+#endif // MARLIN_CONFIG_H

+ 57 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/MarlinSPI.h

@@ -0,0 +1,57 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __MARLIN_SPI_H__
+#define __MARLIN_SPI_H__
+
+#include <stdint.h>
+#include "softspi.h"
+
+template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin>
+class SPI {
+  static SoftSPI<MisoPin, MosiPin, SckPin> softSPI;
+  public:
+    FORCE_INLINE static void init() { softSPI.begin(); }
+    FORCE_INLINE static void send(uint8_t data) { softSPI.send(data); }
+    FORCE_INLINE static uint8_t receive() { return softSPI.receive(); }
+};
+
+
+// Hardware SPI
+template<>
+class SPI<MISO_PIN, MOSI_PIN, SCK_PIN> {
+  public:
+    FORCE_INLINE static void init() {
+        OUT_WRITE(SCK_PIN, LOW);
+        OUT_WRITE(MOSI_PIN, HIGH);
+        SET_INPUT(MISO_PIN);
+        WRITE(MISO_PIN, HIGH);
+    }
+    FORCE_INLINE static uint8_t receive() {
+      SPDR = 0;
+      while (!TEST(SPSR, SPIF)) { /* nada */ }
+      return SPDR;
+    }
+
+};
+
+#endif // __MARLIN_SPI_H__

+ 740 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/MarlinSerial.cpp

@@ -0,0 +1,740 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * MarlinSerial.cpp - Hardware serial library for Wiring
+ * Copyright (c) 2006 Nicholas Zambetti.  All right reserved.
+ *
+ * Modified 23 November 2006 by David A. Mellis
+ * Modified 28 September 2010 by Mark Sproul
+ * Modified 14 February 2016 by Andreas Hardtung (added tx buffer)
+ * Modified 01 October 2017 by Eduardo José Tagle (added XON/XOFF)
+ * Modified 10 June 2018 by Eduardo José Tagle (See #10991)
+ */
+
+// Disable HardwareSerial.cpp to support chips without a UART (Attiny, etc.)
+
+#include "MarlinConfig.h"
+
+#if USE_MARLINSERIAL && (defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H))
+
+  #include "MarlinSerial.h"
+  #include "Marlin.h"
+
+  struct ring_buffer_r {
+    unsigned char buffer[RX_BUFFER_SIZE];
+    volatile ring_buffer_pos_t head, tail;
+  };
+
+  #if TX_BUFFER_SIZE > 0
+    struct ring_buffer_t {
+      unsigned char buffer[TX_BUFFER_SIZE];
+      volatile uint8_t head, tail;
+    };
+  #endif
+
+  #if UART_PRESENT(SERIAL_PORT)
+    ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
+    #if TX_BUFFER_SIZE > 0
+      ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
+    #endif
+    static bool _written;
+  #endif
+
+  #if ENABLED(SERIAL_XON_XOFF)
+    constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80,  // XON / XOFF Character was sent
+                      XON_XOFF_CHAR_MASK = 0x1F;  // XON / XOFF character to send
+    // XON / XOFF character definitions
+    constexpr uint8_t XON_CHAR  = 17, XOFF_CHAR = 19;
+    uint8_t xon_xoff_state = XON_XOFF_CHAR_SENT | XON_CHAR;
+  #endif
+
+  #if ENABLED(SERIAL_STATS_DROPPED_RX)
+    uint8_t rx_dropped_bytes = 0;
+  #endif
+
+  #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
+    uint8_t rx_buffer_overruns = 0;
+  #endif
+
+  #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
+    uint8_t rx_framing_errors = 0;
+  #endif
+
+  #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
+    ring_buffer_pos_t rx_max_enqueued = 0;
+  #endif
+
+  // A SW memory barrier, to ensure GCC does not overoptimize loops
+  #define sw_barrier() asm volatile("": : :"memory");
+
+  #if ENABLED(EMERGENCY_PARSER)
+    #include "emergency_parser.h"
+  #endif
+
+  // "Atomically" read the RX head index value without disabling interrupts:
+  // This MUST be called with RX interrupts enabled, and CAN'T be called
+  // from the RX ISR itself!
+  FORCE_INLINE ring_buffer_pos_t atomic_read_rx_head() {
+    #if RX_BUFFER_SIZE > 256
+      // Keep reading until 2 consecutive reads return the same value,
+      // meaning there was no update in-between caused by an interrupt.
+      // This works because serial RX interrupts happen at a slower rate
+      // than successive reads of a variable, so 2 consecutive reads with
+      // the same value means no interrupt updated it.
+      ring_buffer_pos_t vold, vnew = rx_buffer.head;
+      sw_barrier();
+      do {
+        vold = vnew;
+        vnew = rx_buffer.head;
+        sw_barrier();
+      } while (vold != vnew);
+      return vnew;
+    #else
+      // With an 8bit index, reads are always atomic. No need for special handling
+      return rx_buffer.head;
+    #endif
+  }
+
+  #if RX_BUFFER_SIZE > 256
+    static volatile bool rx_tail_value_not_stable = false;
+    static volatile uint16_t rx_tail_value_backup = 0;
+  #endif
+
+  // Set RX tail index, taking into account the RX ISR could interrupt
+  //  the write to this variable in the middle - So a backup strategy
+  //  is used to ensure reads of the correct values.
+  //    -Must NOT be called from the RX ISR -
+  FORCE_INLINE void atomic_set_rx_tail(ring_buffer_pos_t value) {
+    #if RX_BUFFER_SIZE > 256
+      // Store the new value in the backup
+      rx_tail_value_backup = value;
+      sw_barrier();
+      // Flag we are about to change the true value
+      rx_tail_value_not_stable = true;
+      sw_barrier();
+      // Store the new value
+      rx_buffer.tail = value;
+      sw_barrier();
+      // Signal the new value is completely stored into the value
+      rx_tail_value_not_stable = false;
+      sw_barrier();
+    #else
+      rx_buffer.tail = value;
+    #endif
+  }
+
+  // Get the RX tail index, taking into account the read could be
+  //  interrupting in the middle of the update of that index value
+  //    -Called from the RX ISR -
+  FORCE_INLINE ring_buffer_pos_t atomic_read_rx_tail() {
+    #if RX_BUFFER_SIZE > 256
+      // If the true index is being modified, return the backup value
+      if (rx_tail_value_not_stable) return rx_tail_value_backup;
+    #endif
+    // The true index is stable, return it
+    return rx_buffer.tail;
+  }
+
+  // (called with RX interrupts disabled)
+  FORCE_INLINE void store_rxd_char() {
+    // Get the tail - Nothing can alter its value while this ISR is executing, but there's
+    // a chance that this ISR interrupted the main process while it was updating the index.
+    // The backup mechanism ensures the correct value is always returned.
+    const ring_buffer_pos_t t = atomic_read_rx_tail();
+
+    // Get the head pointer - This ISR is the only one that modifies its value, so it's safe to read here
+    ring_buffer_pos_t h = rx_buffer.head;
+
+    // Get the next element
+    ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
+
+    // This must read the M_UCSRxA register before reading the received byte to detect error causes
+    #if ENABLED(SERIAL_STATS_DROPPED_RX)
+      if (TEST(M_UCSRxA, M_DORx) && !++rx_dropped_bytes) --rx_dropped_bytes;
+    #endif
+
+    #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
+      if (TEST(M_UCSRxA, M_DORx) && !++rx_buffer_overruns) --rx_buffer_overruns;
+    #endif
+
+    #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
+      if (TEST(M_UCSRxA, M_FEx) && !++rx_framing_errors) --rx_framing_errors;
+    #endif
+
+    // Read the character from the USART
+    uint8_t c = M_UDRx;
+
+    #if ENABLED(EMERGENCY_PARSER)
+      emergency_parser.update(c);
+    #endif
+
+    // If the character is to be stored at the index just before the tail
+    // (such that the head would advance to the current tail), the RX FIFO is
+    // full, so don't write the character or advance the head.
+    if (i != t) {
+      rx_buffer.buffer[h] = c;
+      h = i;
+    }
+    #if ENABLED(SERIAL_STATS_DROPPED_RX)
+      else if (!++rx_dropped_bytes) --rx_dropped_bytes;
+    #endif
+
+    #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
+      // Calculate count of bytes stored into the RX buffer
+      const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
+
+      // Keep track of the maximum count of enqueued bytes
+      NOLESS(rx_max_enqueued, rx_count);
+    #endif
+
+    #if ENABLED(SERIAL_XON_XOFF)
+      // If the last char that was sent was an XON
+      if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
+
+        // Bytes stored into the RX buffer
+        const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
+
+        // If over 12.5% of RX buffer capacity, send XOFF before running out of
+        // RX buffer space .. 325 bytes @ 250kbits/s needed to let the host react
+        // and stop sending bytes. This translates to 13mS propagation time.
+        if (rx_count >= (RX_BUFFER_SIZE) / 8) {
+
+          // At this point, definitely no TX interrupt was executing, since the TX ISR can't be preempted.
+          // Don't enable the TX interrupt here as a means to trigger the XOFF char, because if it happens
+          // to be in the middle of trying to disable the RX interrupt in the main program, eventually the
+          // enabling of the TX interrupt could be undone. The ONLY reliable thing this can do to ensure
+          // the sending of the XOFF char is to send it HERE AND NOW.
+
+          // About to send the XOFF char
+          xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
+
+          // Wait until the TX register becomes empty and send it - Here there could be a problem
+          // - While waiting for the TX register to empty, the RX register could receive a new
+          //   character. This must also handle that situation!
+          while (!TEST(M_UCSRxA, M_UDREx)) {
+
+            if (TEST(M_UCSRxA,M_RXCx)) {
+              // A char arrived while waiting for the TX buffer to be empty - Receive and process it!
+
+              i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
+
+              // Read the character from the USART
+              c = M_UDRx;
+
+              #if ENABLED(EMERGENCY_PARSER)
+                emergency_parser.update(c);
+              #endif
+
+              // If the character is to be stored at the index just before the tail
+              // (such that the head would advance to the current tail), the FIFO is
+              // full, so don't write the character or advance the head.
+              if (i != t) {
+                rx_buffer.buffer[h] = c;
+                h = i;
+              }
+              #if ENABLED(SERIAL_STATS_DROPPED_RX)
+                else if (!++rx_dropped_bytes) --rx_dropped_bytes;
+              #endif
+            }
+            sw_barrier();
+          }
+
+          M_UDRx = XOFF_CHAR;
+
+          // Clear the TXC bit -- "can be cleared by writing a one to its bit
+          // location". This makes sure flush() won't return until the bytes
+          // actually got written
+          SBI(M_UCSRxA, M_TXCx);
+
+          // At this point there could be a race condition between the write() function
+          // and this sending of the XOFF char. This interrupt could happen between the
+          // wait to be empty TX buffer loop and the actual write of the character. Since
+          // the TX buffer is full because it's sending the XOFF char, the only way to be
+          // sure the write() function will succeed is to wait for the XOFF char to be
+          // completely sent. Since an extra character could be received during the wait
+          // it must also be handled!
+          while (!TEST(M_UCSRxA, M_UDREx)) {
+
+            if (TEST(M_UCSRxA,M_RXCx)) {
+              // A char arrived while waiting for the TX buffer to be empty - Receive and process it!
+
+              i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
+
+              // Read the character from the USART
+              c = M_UDRx;
+
+              #if ENABLED(EMERGENCY_PARSER)
+                emergency_parser.update(c);
+              #endif
+
+              // If the character is to be stored at the index just before the tail
+              // (such that the head would advance to the current tail), the FIFO is
+              // full, so don't write the character or advance the head.
+              if (i != t) {
+                rx_buffer.buffer[h] = c;
+                h = i;
+              }
+              #if ENABLED(SERIAL_STATS_DROPPED_RX)
+                else if (!++rx_dropped_bytes) --rx_dropped_bytes;
+              #endif
+            }
+            sw_barrier();
+          }
+
+          // At this point everything is ready. The write() function won't
+          // have any issues writing to the UART TX register if it needs to!
+        }
+      }
+    #endif // SERIAL_XON_XOFF
+
+    // Store the new head value - The main loop will retry until the value is stable
+    rx_buffer.head = h;
+  }
+
+  #if TX_BUFFER_SIZE > 0
+
+    // (called with TX irqs disabled)
+    FORCE_INLINE void _tx_udr_empty_irq(void) {
+
+      // Read positions
+      uint8_t t = tx_buffer.tail;
+      const uint8_t h = tx_buffer.head;
+
+      #if ENABLED(SERIAL_XON_XOFF)
+        // If an XON char is pending to be sent, do it now
+        if (xon_xoff_state == XON_CHAR) {
+
+          // Send the character
+          M_UDRx = XON_CHAR;
+
+          // clear the TXC bit -- "can be cleared by writing a one to its bit
+          // location". This makes sure flush() won't return until the bytes
+          // actually got written
+          SBI(M_UCSRxA, M_TXCx);
+
+          // Remember we sent it.
+          xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
+
+          // If nothing else to transmit, just disable TX interrupts.
+          if (h == t) CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
+
+          return;
+        }
+      #endif
+
+      // If nothing to transmit, just disable TX interrupts. This could
+      // happen as the result of the non atomicity of the disabling of RX
+      // interrupts that could end reenabling TX interrupts as a side effect.
+      if (h == t) {
+        CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
+        return;
+      }
+
+      // There is something to TX, Send the next byte
+      const uint8_t c = tx_buffer.buffer[t];
+      t = (t + 1) & (TX_BUFFER_SIZE - 1);
+      M_UDRx = c;
+      tx_buffer.tail = t;
+
+      // Clear the TXC bit (by writing a one to its bit location).
+      // Ensures flush() won't return until the bytes are actually written/
+      SBI(M_UCSRxA, M_TXCx);
+
+      // Disable interrupts if there is nothing to transmit following this byte
+      if (h == t) CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
+    }
+
+    #ifdef M_USARTx_UDRE_vect
+      ISR(M_USARTx_UDRE_vect) { _tx_udr_empty_irq(); }
+    #endif
+
+  #endif // TX_BUFFER_SIZE
+
+  #ifdef M_USARTx_RX_vect
+    ISR(M_USARTx_RX_vect) { store_rxd_char(); }
+  #endif
+
+  // Public Methods
+
+  void MarlinSerial::begin(const long baud) {
+    uint16_t baud_setting;
+    bool useU2X = true;
+
+    #if F_CPU == 16000000UL && SERIAL_PORT == 0
+      // Hard-coded 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 = _BV(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);
+    #if TX_BUFFER_SIZE > 0
+      CBI(M_UCSRxB, M_UDRIEx);
+    #endif
+    _written = false;
+  }
+
+  void MarlinSerial::end() {
+    CBI(M_UCSRxB, M_RXENx);
+    CBI(M_UCSRxB, M_TXENx);
+    CBI(M_UCSRxB, M_RXCIEx);
+    CBI(M_UCSRxB, M_UDRIEx);
+  }
+
+  int MarlinSerial::peek(void) {
+    const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
+    return h == t ? -1 : rx_buffer.buffer[t];
+  }
+
+  int MarlinSerial::read(void) {
+    const ring_buffer_pos_t h = atomic_read_rx_head();
+
+    // Read the tail. Main thread owns it, so it is safe to directly read it
+    ring_buffer_pos_t t = rx_buffer.tail;
+
+    // If nothing to read, return now
+    if (h == t) return -1;
+
+    // Get the next char
+    const int v = rx_buffer.buffer[t];
+    t = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
+
+    // Advance tail - Making sure the RX ISR will always get an stable value, even
+    // if it interrupts the writing of the value of that variable in the middle.
+    atomic_set_rx_tail(t);
+
+    #if ENABLED(SERIAL_XON_XOFF)
+      // If the XOFF char was sent, or about to be sent...
+      if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
+        // Get count of bytes in the RX buffer
+        const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
+        if (rx_count < (RX_BUFFER_SIZE) / 10) {
+          #if TX_BUFFER_SIZE > 0
+            // Signal we want an XON character to be sent.
+            xon_xoff_state = XON_CHAR;
+            // Enable TX ISR. Non atomic, but it will eventually enable them
+            SBI(M_UCSRxB, M_UDRIEx);
+          #else
+            // If not using TX interrupts, we must send the XON char now
+            xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
+            while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
+            M_UDRx = XON_CHAR;
+          #endif
+        }
+      }
+    #endif
+
+    return v;
+  }
+
+  ring_buffer_pos_t MarlinSerial::available(void) {
+    const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
+    return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
+  }
+
+  void MarlinSerial::flush(void) {
+
+    // Set the tail to the head:
+    //  - Read the RX head index in a safe way. (See atomic_read_rx_head.)
+    //  - Set the tail, making sure the RX ISR will always get a stable value, even
+    //    if it interrupts the writing of the value of that variable in the middle.
+    atomic_set_rx_tail(atomic_read_rx_head());
+
+    #if ENABLED(SERIAL_XON_XOFF)
+      // If the XOFF char was sent, or about to be sent...
+      if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
+        #if TX_BUFFER_SIZE > 0
+          // Signal we want an XON character to be sent.
+          xon_xoff_state = XON_CHAR;
+          // Enable TX ISR. Non atomic, but it will eventually enable it.
+          SBI(M_UCSRxB, M_UDRIEx);
+        #else
+          // If not using TX interrupts, we must send the XON char now
+          xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
+          while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
+          M_UDRx = XON_CHAR;
+        #endif
+      }
+    #endif
+  }
+
+  #if TX_BUFFER_SIZE > 0
+    void MarlinSerial::write(const uint8_t c) {
+      _written = true;
+
+      // If the TX interrupts are disabled and the data register
+      // is empty, just write the byte to the data register and
+      // be done. This shortcut helps significantly improve the
+      // effective datarate at high (>500kbit/s) bitrates, where
+      // interrupt overhead becomes a slowdown.
+      // Yes, there is a race condition between the sending of the
+      // XOFF char at the RX ISR, but it is properly handled there
+      if (!TEST(M_UCSRxB, M_UDRIEx) && TEST(M_UCSRxA, M_UDREx)) {
+        M_UDRx = c;
+
+        // clear the TXC bit -- "can be cleared by writing a one to its bit
+        // location". This makes sure flush() won't return until the bytes
+        // actually got written
+        SBI(M_UCSRxA, M_TXCx);
+        return;
+      }
+
+      const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
+
+      // If global interrupts are disabled (as the result of being called from an ISR)...
+      if (!ISRS_ENABLED()) {
+
+        // Make room by polling if it is possible to transmit, and do so!
+        while (i == tx_buffer.tail) {
+
+          // If we can transmit another byte, do it.
+          if (TEST(M_UCSRxA, M_UDREx)) _tx_udr_empty_irq();
+
+          // Make sure compiler rereads tx_buffer.tail
+          sw_barrier();
+        }
+      }
+      else {
+        // Interrupts are enabled, just wait until there is space
+        while (i == tx_buffer.tail) { sw_barrier(); }
+      }
+
+      // Store new char. head is always safe to move
+      tx_buffer.buffer[tx_buffer.head] = c;
+      tx_buffer.head = i;
+
+      // Enable TX ISR - Non atomic, but it will eventually enable TX ISR
+      SBI(M_UCSRxB, M_UDRIEx);
+    }
+
+    void MarlinSerial::flushTX(void) {
+      // No bytes written, no need to flush. This special case is needed since there's
+      // no way to force the TXC (transmit complete) bit to 1 during initialization.
+      if (!_written) return;
+
+      // If global interrupts are disabled (as the result of being called from an ISR)...
+      if (!ISRS_ENABLED()) {
+
+        // Wait until everything was transmitted - We must do polling, as interrupts are disabled
+        while (tx_buffer.head != tx_buffer.tail || !TEST(M_UCSRxA, M_TXCx)) {
+
+          // If there is more space, send an extra character
+          if (TEST(M_UCSRxA, M_UDREx))
+            _tx_udr_empty_irq();
+
+          sw_barrier();
+        }
+
+      }
+      else {
+        // Wait until everything was transmitted
+        while (tx_buffer.head != tx_buffer.tail || !TEST(M_UCSRxA, M_TXCx)) sw_barrier();
+      }
+
+      // At this point nothing is queued anymore (DRIE is disabled) and
+      // the hardware finished transmission (TXC is set).
+    }
+
+  #else // TX_BUFFER_SIZE == 0
+
+    void MarlinSerial::write(const uint8_t c) {
+      _written = true;
+      while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
+      M_UDRx = c;
+    }
+
+    void MarlinSerial::flushTX(void) {
+      // No bytes written, no need to flush. This special case is needed since there's
+      // no way to force the TXC (transmit complete) bit to 1 during initialization.
+      if (!_written) return;
+
+      // Wait until everything was transmitted
+      while (!TEST(M_UCSRxA, M_TXCx)) sw_barrier();
+
+      // At this point nothing is queued anymore (DRIE is disabled) and
+      // the hardware finished transmission (TXC is set).
+    }
+  #endif // TX_BUFFER_SIZE == 0
+
+  /**
+   * 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) {
+    if (n) {
+      unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
+      int8_t i = 0;
+      while (n) {
+        buf[i++] = n % base;
+        n /= base;
+      }
+      while (i--)
+        print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
+    }
+    else
+      print('0');
+  }
+
+  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 *= 0.1;
+
+    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) {
+      print('.');
+      // Extract digits from the remainder one at a time
+      while (digits--) {
+        remainder *= 10.0;
+        int toPrint = int(remainder);
+        print(toPrint);
+        remainder -= toPrint;
+      }
+    }
+  }
+
+  // Preinstantiate
+  MarlinSerial customizedSerial;
+
+#endif // USE_MARLINSERIAL && (UBRRH || UBRR0H || UBRR1H || UBRR2H || UBRR3H)
+
+// For AT90USB targets use the UART for BT interfacing
+#if !USE_MARLINSERIAL && ENABLED(BLUETOOTH)
+  HardwareSerial bluetoothSerial;
+#endif

+ 184 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/MarlinSerial.h

@@ -0,0 +1,184 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * MarlinSerial.h - Hardware serial library for Wiring
+ * Copyright (c) 2006 Nicholas Zambetti.  All right reserved.
+ *
+ * Modified 28 September 2010 by Mark Sproul
+ * Modified 14 February 2016 by Andreas Hardtung (added tx buffer)
+ * Modified 01 October 2017 by Eduardo José Tagle (added XON/XOFF)
+ */
+
+#ifndef _MARLINSERIAL_H_
+#define _MARLINSERIAL_H_
+
+#include "MarlinConfig.h"
+
+#ifndef 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 (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_TXCx             SERIAL_REGNAME(TXC,SERIAL_PORT,)
+#define M_RXCIEx           SERIAL_REGNAME(RXCIE,SERIAL_PORT,)
+#define M_UDREx            SERIAL_REGNAME(UDRE,SERIAL_PORT,)
+#define M_FEx              SERIAL_REGNAME(FE,SERIAL_PORT,)
+#define M_DORx             SERIAL_REGNAME(DOR,SERIAL_PORT,)
+#define M_UPEx             SERIAL_REGNAME(UPE,SERIAL_PORT,)
+#define M_UDRIEx           SERIAL_REGNAME(UDRIE,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 M_USARTx_UDRE_vect SERIAL_REGNAME(USART,SERIAL_PORT,_UDRE_vect)
+
+#define DEC 10
+#define HEX 16
+#define OCT 8
+#define BIN 2
+#define BYTE 0
+
+// Define constants and variables for buffering serial data.
+// Use only 0 or powers of 2 greater than 1
+// : [0, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, ...]
+#ifndef RX_BUFFER_SIZE
+  #define RX_BUFFER_SIZE 128
+#endif
+// 256 is the max TX buffer limit due to uint8_t head and tail.
+#ifndef TX_BUFFER_SIZE
+  #define TX_BUFFER_SIZE 32
+#endif
+
+#if USE_MARLINSERIAL
+
+  #if RX_BUFFER_SIZE > 256
+    typedef uint16_t ring_buffer_pos_t;
+  #else
+    typedef uint8_t ring_buffer_pos_t;
+  #endif
+
+  #if ENABLED(SERIAL_STATS_DROPPED_RX)
+    extern uint8_t rx_dropped_bytes;
+  #endif
+
+  #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
+    extern uint8_t rx_buffer_overruns;
+  #endif
+
+  #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
+    extern uint8_t rx_framing_errors;
+  #endif
+
+  #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
+    extern ring_buffer_pos_t rx_max_enqueued;
+  #endif
+
+  class MarlinSerial {
+
+    public:
+      MarlinSerial() {};
+      static void begin(const long);
+      static void end();
+      static int peek(void);
+      static int read(void);
+      static void flush(void);
+      static ring_buffer_pos_t available(void);
+      static void write(const uint8_t c);
+      static void flushTX(void);
+
+      #if ENABLED(SERIAL_STATS_DROPPED_RX)
+        FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }
+      #endif
+
+      #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
+        FORCE_INLINE static uint32_t buffer_overruns() { return rx_buffer_overruns; }
+      #endif
+
+      #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
+        FORCE_INLINE static uint32_t framing_errors() { return rx_framing_errors; }
+      #endif
+
+      #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
+        FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return rx_max_enqueued; }
+      #endif
+
+      FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
+      FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
+      FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
+      FORCE_INLINE static void print(const char* str) { write(str); }
+
+      static void print(char, int = BYTE);
+      static void print(unsigned char, int = BYTE);
+      static void print(int, int = DEC);
+      static void print(unsigned int, int = DEC);
+      static void print(long, int = DEC);
+      static void print(unsigned long, int = DEC);
+      static void print(double, int = 2);
+
+      static void println(const String& s);
+      static void println(const char[]);
+      static void println(char, int = BYTE);
+      static void println(unsigned char, int = BYTE);
+      static void println(int, int = DEC);
+      static void println(unsigned int, int = DEC);
+      static void println(long, int = DEC);
+      static void println(unsigned long, int = DEC);
+      static void println(double, int = 2);
+      static void println(void);
+      operator bool() { return true; }
+
+    private:
+      static void printNumber(unsigned long, const uint8_t);
+      static void printFloat(double, uint8_t);
+  };
+
+  extern MarlinSerial customizedSerial;
+
+#endif // USE_MARLINSERIAL
+
+// Use the UART for Bluetooth in AT90USB configurations
+#if !USE_MARLINSERIAL && ENABLED(BLUETOOTH)
+  extern HardwareSerial bluetoothSerial;
+#endif
+
+#endif // _MARLINSERIAL_H_

File diff suppressed because it is too large
+ 15377 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Marlin_main.cpp


+ 593 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Max7219_Debug_LEDs.cpp

@@ -0,0 +1,593 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * This module is off by default, but can be enabled to facilitate the display of
+ * extra debug information during code development.
+ *
+ * Just connect up 5V and GND to give it power, then connect up the pins assigned
+ * in Configuration_adv.h. For example, on the Re-ARM you could use:
+ *
+ *   #define MAX7219_CLK_PIN   77
+ *   #define MAX7219_DIN_PIN   78
+ *   #define MAX7219_LOAD_PIN  79
+ *
+ * send() is called automatically at startup, and then there are a number of
+ * support functions available to control the LEDs in the 8x8 grid.
+ */
+
+#include "MarlinConfig.h"
+
+#if ENABLED(MAX7219_DEBUG)
+
+#define MAX7219_ERRORS // Disable to save 406 bytes of Program Memory
+
+#include "Max7219_Debug_LEDs.h"
+
+#include "planner.h"
+#include "stepper.h"
+#include "Marlin.h"
+#include "delay.h"
+
+Max7219 max7219;
+
+uint8_t Max7219::led_line[MAX7219_LINES]; // = { 0 };
+
+#define LINE_REG(Q)     (max7219_reg_digit0 + ((Q) & 0x7))
+#if _ROT == 0 || _ROT == 270
+  #define _LED_BIT(Q)   (7 - ((Q) & 0x7))
+  #define _LED_UNIT(Q)  ((Q) & ~0x7)
+#else
+  #define _LED_BIT(Q)   ((Q) & 0x7)
+  #define _LED_UNIT(Q)  ((MAX7219_NUMBER_UNITS - 1 - ((Q) >> 3)) << 3)
+#endif
+#if _ROT < 180
+  #define _LED_IND(P,Q) (_LED_UNIT(P) + (Q))
+#else
+  #define _LED_IND(P,Q) (_LED_UNIT(P) + (7 - ((Q) & 0x7)))
+#endif
+#if _ROT == 0 || _ROT == 180
+  #define LED_IND(X,Y)  _LED_IND(X,Y)
+  #define LED_BIT(X,Y)  _LED_BIT(X)
+#elif _ROT == 90 || _ROT == 270
+  #define LED_IND(X,Y)  _LED_IND(Y,X)
+  #define LED_BIT(X,Y)  _LED_BIT(Y)
+#endif
+#define XOR_7219(X,Y) do{ led_line[LED_IND(X,Y)] ^=  _BV(LED_BIT(X,Y)); }while(0)
+#define SET_7219(X,Y) do{ led_line[LED_IND(X,Y)] |=  _BV(LED_BIT(X,Y)); }while(0)
+#define CLR_7219(X,Y) do{ led_line[LED_IND(X,Y)] &= ~_BV(LED_BIT(X,Y)); }while(0)
+#define BIT_7219(X,Y) TEST(led_line[LED_IND(X,Y)], LED_BIT(X,Y))
+
+#ifdef CPU_32_BIT
+  #define SIG_DELAY() DELAY_US(1)   // Approximate a 1µs delay on 32-bit ARM
+  #undef CRITICAL_SECTION_START
+  #undef CRITICAL_SECTION_END
+  #define CRITICAL_SECTION_START NOOP
+  #define CRITICAL_SECTION_END   NOOP
+#else
+  #define SIG_DELAY() DELAY_NS(188) // Delay for 0.1875µs (16MHz AVR) or 0.15µs (20MHz AVR)
+#endif
+
+void Max7219::error(const char * const func, const int32_t v1, const int32_t v2/*=-1*/) {
+  #if ENABLED(MAX7219_ERRORS)
+    SERIAL_ECHOPGM("??? Max7219::");
+    serialprintPGM(func);
+    SERIAL_CHAR('(');
+    SERIAL_ECHO(v1);
+    if (v2 > 0) SERIAL_ECHOPAIR(", ", v2);
+    SERIAL_CHAR(')');
+    SERIAL_EOL();
+  #else
+    UNUSED(func); UNUSED(v1); UNUSED(v2);
+  #endif
+}
+
+/**
+ * Flip the lowest n_bytes of the supplied bits:
+ *  flipped(x, 1) flips the low 8  bits of x.
+ *  flipped(x, 2) flips the low 16 bits of x.
+ *  flipped(x, 3) flips the low 24 bits of x.
+ *  flipped(x, 4) flips the low 32 bits of x.
+ */
+inline uint32_t flipped(const uint32_t bits, const uint8_t n_bytes) {
+  uint32_t mask = 1, outbits = 0;
+  for (uint8_t b = 0; b < n_bytes * 8; b++) {
+    outbits <<= 1;
+    if (bits & mask) outbits |= 1;
+    mask <<= 1;
+  }
+  return outbits;
+}
+
+void Max7219::noop() {
+  CRITICAL_SECTION_START;
+  SIG_DELAY();
+  WRITE(MAX7219_DIN_PIN, LOW);
+  for (uint8_t i = 16; i--;) {
+    SIG_DELAY();
+    WRITE(MAX7219_CLK_PIN, LOW);
+    SIG_DELAY();
+    SIG_DELAY();
+    WRITE(MAX7219_CLK_PIN, HIGH);
+    SIG_DELAY();
+  }
+  CRITICAL_SECTION_END;
+}
+
+void Max7219::putbyte(uint8_t data) {
+  CRITICAL_SECTION_START;
+  for (uint8_t i = 8; i--;) {
+    SIG_DELAY();
+    WRITE(MAX7219_CLK_PIN, LOW);       // tick
+    SIG_DELAY();
+    WRITE(MAX7219_DIN_PIN, (data & 0x80) ? HIGH : LOW);  // send 1 or 0 based on data bit
+    SIG_DELAY();
+    WRITE(MAX7219_CLK_PIN, HIGH);      // tock
+    SIG_DELAY();
+    data <<= 1;
+  }
+  CRITICAL_SECTION_END;
+}
+
+void Max7219::pulse_load() {
+  SIG_DELAY();
+  WRITE(MAX7219_LOAD_PIN, LOW);  // tell the chip to load the data
+  SIG_DELAY();
+  WRITE(MAX7219_LOAD_PIN, HIGH);
+  SIG_DELAY();
+}
+
+void Max7219::send(const uint8_t reg, const uint8_t data) {
+  SIG_DELAY();
+  CRITICAL_SECTION_START;
+  SIG_DELAY();
+  putbyte(reg);          // specify register
+  SIG_DELAY();
+  putbyte(data);         // put data
+  CRITICAL_SECTION_END;
+}
+
+// Send out a single native row of bits to all units
+void Max7219::refresh_line(const uint8_t line) {
+  for (uint8_t u = MAX7219_NUMBER_UNITS; u--;)
+    send(LINE_REG(line), led_line[(u << 3) | (line & 0x7)]);
+  pulse_load();
+}
+
+// Send out a single native row of bits to just one unit
+void Max7219::refresh_unit_line(const uint8_t line) {
+  for (uint8_t u = MAX7219_NUMBER_UNITS; u--;)
+    if (u == (line >> 3)) send(LINE_REG(line), led_line[line]); else noop();
+  pulse_load();
+}
+
+void Max7219::set(const uint8_t line, const uint8_t bits) {
+  led_line[line] = bits;
+  refresh_line(line);
+}
+
+#if ENABLED(MAX7219_NUMERIC)
+
+  // Draw an integer with optional leading zeros and optional decimal point
+  void Max7219::print(const uint8_t start, int16_t value, uint8_t size, const bool leadzero=false, bool dec=false) {
+    constexpr uint8_t led_numeral[10] = { 0x7E, 0x60, 0x6D, 0x79, 0x63, 0x5B, 0x5F, 0x70, 0x7F, 0x7A },
+                      led_decimal = 0x80, led_minus = 0x01;
+
+    bool blank = false, neg = value < 0;
+    if (neg) value *= -1;
+    while (size--) {
+      const bool minus = neg && blank;
+      if (minus) neg = false;
+      send(
+        max7219_reg_digit0 + start + size,
+        minus ? led_minus : blank ? 0x00 : led_numeral[value % 10] | (dec ? led_decimal : 0x00)
+      );
+      pulse_load();  // tell the chips to load the clocked out data
+      value /= 10;
+      if (!value && !leadzero) blank = true;
+      dec = false;
+    }
+  }
+
+  // Draw a float with a decimal point and optional digits
+  void Max7219::print(const uint8_t start, const float value, const uint8_t pre_size, const uint8_t post_size, const bool leadzero=false) {
+    if (pre_size) print(start, value, pre_size, leadzero, !!post_size);
+    if (post_size) {
+      const int16_t after = ABS(value) * (10 ^ post_size);
+      print(start + pre_size, after, post_size, true);
+    }
+  }
+
+#endif // MAX7219_NUMERIC
+
+// Modify a single LED bit and send the changed line
+void Max7219::led_set(const uint8_t x, const uint8_t y, const bool on) {
+  if (x > MAX7219_X_LEDS - 1 || y > MAX7219_Y_LEDS - 1) return error(PSTR("led_set"), x, y);
+  if (BIT_7219(x, y) == on) return;
+  XOR_7219(x, y);
+  refresh_line(LED_IND(x, y));
+}
+
+void Max7219::led_on(const uint8_t x, const uint8_t y) {
+  if (x > MAX7219_X_LEDS - 1 || y > MAX7219_Y_LEDS - 1) return error(PSTR("led_on"), x, y);
+  led_set(x, y, true);
+}
+
+void Max7219::led_off(const uint8_t x, const uint8_t y) {
+  if (x > MAX7219_X_LEDS - 1 || y > MAX7219_Y_LEDS - 1) return error(PSTR("led_off"), x, y);
+  led_set(x, y, false);
+}
+
+void Max7219::led_toggle(const uint8_t x, const uint8_t y) {
+  if (x > MAX7219_X_LEDS - 1 || y > MAX7219_Y_LEDS - 1) return error(PSTR("led_toggle"), x, y);
+  led_set(x, y, !BIT_7219(x, y));
+}
+
+void Max7219::send_row(const uint8_t row) {
+  #if _ROT == 0 || _ROT == 180
+    refresh_line(LED_IND(0, row));
+  #else
+    UNUSED(row);
+    refresh();
+  #endif
+}
+
+void Max7219::send_column(const uint8_t col) {
+  #if _ROT == 90 || _ROT == 270
+    refresh_line(LED_IND(col, 0));
+  #else
+    UNUSED(col);
+    refresh();
+  #endif
+}
+
+void Max7219::clear() {
+  ZERO(led_line);
+  refresh();
+}
+
+void Max7219::fill() {
+  memset(led_line, 0xFF, sizeof(led_line));
+  refresh();
+}
+
+void Max7219::clear_row(const uint8_t row) {
+  if (row >= MAX7219_Y_LEDS) return error(PSTR("clear_row"), row);
+  for (uint8_t x = 0; x < MAX7219_X_LEDS; x++) CLR_7219(x, row);
+  send_row(row);
+}
+
+void Max7219::clear_column(const uint8_t col) {
+  if (col >= MAX7219_X_LEDS) return error(PSTR("set_column"), col);
+  for (uint8_t y = 0; y < MAX7219_Y_LEDS; y++) CLR_7219(col, y);
+  send_column(col);
+}
+
+/**
+ * Plot the low order bits of val to the specified row of the matrix.
+ * With 4 Max7219 units in the chain, it's possible to set 32 bits at once with
+ * one call to the function (if rotated 90° or 180°).
+ */
+void Max7219::set_row(const uint8_t row, const uint32_t val) {
+  if (row >= MAX7219_Y_LEDS) return error(PSTR("set_row"), row);
+  uint32_t mask = _BV32(MAX7219_X_LEDS - 1);
+  for (uint8_t x = 0; x < MAX7219_X_LEDS; x++) {
+    if (val & mask) SET_7219(x, row); else CLR_7219(x, row);
+    mask >>= 1;
+  }
+  send_row(row);
+}
+
+/**
+ * Plot the low order bits of val to the specified column of the matrix.
+ * With 4 Max7219 units in the chain, it's possible to set 32 bits at once with
+ * one call to the function (if rotated 90° or 180°).
+ */
+void Max7219::set_column(const uint8_t col, const uint32_t val) {
+  if (col >= MAX7219_X_LEDS) return error(PSTR("set_column"), col);
+  uint32_t mask = _BV32(MAX7219_Y_LEDS - 1);
+  for (uint8_t y = 0; y < MAX7219_Y_LEDS; y++) {
+    if (val & mask) SET_7219(col, y); else CLR_7219(col, y);
+    mask >>= 1;
+  }
+  send_column(col);
+}
+
+void Max7219::set_rows_16bits(const uint8_t y, uint32_t val) {
+  #if MAX7219_X_LEDS == 8
+    if (y > MAX7219_Y_LEDS - 2) return error(PSTR("set_rows_16bits"), y, val);
+    set_row(y + 1, val); val >>= 8;
+    set_row(y + 0, val);
+  #else // at least 16 bits on each row
+    if (y > MAX7219_Y_LEDS - 1) return error(PSTR("set_rows_16bits"), y, val);
+    set_row(y, val);
+  #endif
+}
+
+void Max7219::set_rows_32bits(const uint8_t y, uint32_t val) {
+  #if MAX7219_X_LEDS == 8
+    if (y > MAX7219_Y_LEDS - 4) return error(PSTR("set_rows_32bits"), y, val);
+    set_row(y + 3, val); val >>= 8;
+    set_row(y + 2, val); val >>= 8;
+    set_row(y + 1, val); val >>= 8;
+    set_row(y + 0, val);
+  #elif MAX7219_X_LEDS == 16
+    if (y > MAX7219_Y_LEDS - 2) return error(PSTR("set_rows_32bits"), y, val);
+    set_row(y + 1, val); val >>= 16;
+    set_row(y + 0, val);
+  #else // at least 24 bits on each row.  In the 3 matrix case, just display the low 24 bits
+    if (y > MAX7219_Y_LEDS - 1) return error(PSTR("set_rows_32bits"), y, val);
+    set_row(y, val);
+  #endif
+}
+
+void Max7219::set_columns_16bits(const uint8_t x, uint32_t val) {
+  #if MAX7219_Y_LEDS == 8
+    if (x > MAX7219_X_LEDS - 2) return error(PSTR("set_columns_16bits"), x, val);
+    set_column(x + 0, val); val >>= 8;
+    set_column(x + 1, val);
+  #else // at least 16 bits in each column
+    if (x > MAX7219_X_LEDS - 1) return error(PSTR("set_columns_16bits"), x, val);
+    set_column(x, val);
+  #endif
+}
+
+void Max7219::set_columns_32bits(const uint8_t x, uint32_t val) {
+  #if MAX7219_Y_LEDS == 8
+    if (x > MAX7219_X_LEDS - 4) return error(PSTR("set_rows_32bits"), x, val);
+    set_column(x + 3, val); val >>= 8;
+    set_column(x + 2, val); val >>= 8;
+    set_column(x + 1, val); val >>= 8;
+    set_column(x + 0, val);
+  #elif MAX7219_Y_LEDS == 16
+    if (x > MAX7219_X_LEDS - 2) return error(PSTR("set_rows_32bits"), x, val);
+    set_column(x + 1, val); val >>= 16;
+    set_column(x + 0, val);
+  #else // at least 24 bits on each row.  In the 3 matrix case, just display the low 24 bits
+    if (x > MAX7219_X_LEDS - 1) return error(PSTR("set_rows_32bits"), x, val);
+    set_column(x, val);
+  #endif
+}
+
+// Initialize the Max7219
+void Max7219::register_setup() {
+  for (uint8_t i = 0; i < MAX7219_NUMBER_UNITS; i++)
+    send(max7219_reg_scanLimit, 0x07);
+  pulse_load();                        // tell the chips to load the clocked out data
+
+  for (uint8_t i = 0; i < MAX7219_NUMBER_UNITS; i++)
+    send(max7219_reg_decodeMode, 0x00);     // using an led matrix (not digits)
+  pulse_load();                        // tell the chips to load the clocked out data
+
+  for (uint8_t i = 0; i < MAX7219_NUMBER_UNITS; i++)
+    send(max7219_reg_shutdown, 0x01);       // not in shutdown mode
+  pulse_load();                        // tell the chips to load the clocked out data
+
+  for (uint8_t i = 0; i < MAX7219_NUMBER_UNITS; i++)
+    send(max7219_reg_displayTest, 0x00);    // no display test
+  pulse_load();                        // tell the chips to load the clocked out data
+
+  for (uint8_t i = 0; i < MAX7219_NUMBER_UNITS; i++)
+    send(max7219_reg_intensity, 0x01 & 0x0F); // the first 0x0F is the value you can set
+                                                 // range: 0x00 to 0x0F
+  pulse_load();                          // tell the chips to load the clocked out data
+}
+
+#ifdef MAX7219_INIT_TEST
+#if MAX7219_INIT_TEST == 2
+
+  void Max7219::spiral(const bool on, const uint16_t del) {
+    constexpr int8_t way[] = { 1, 0, 0, 1, -1, 0, 0, -1 };
+    int8_t px = 0, py = 0, dir = 0;
+    for (uint8_t i = MAX7219_X_LEDS * MAX7219_Y_LEDS; i--;) {
+      led_set(px, py, on);
+      delay(del);
+      const int8_t x = px + way[dir], y = py + way[dir + 1];
+      if (!WITHIN(x, 0, MAX7219_X_LEDS-1) || !WITHIN(y, 0, MAX7219_Y_LEDS-1) || BIT_7219(x, y) == on) dir = (dir + 2) & 0x7;
+      px += way[dir]; py += way[dir + 1];
+    }
+  }
+
+#else
+
+  void Max7219::sweep(const int8_t dir, const uint16_t ms, const bool on) {
+    uint8_t x = dir > 0 ? 0 : MAX7219_X_LEDS-1;
+    for (uint8_t i = MAX7219_X_LEDS; i--; x += dir) {
+      set_column(x, on ? 0xFFFFFFFF : 0x00000000);
+      delay(ms);
+    }
+  }
+
+#endif
+#endif // MAX7219_INIT_TEST
+
+void Max7219::init() {
+  SET_OUTPUT(MAX7219_DIN_PIN);
+  SET_OUTPUT(MAX7219_CLK_PIN);
+  OUT_WRITE(MAX7219_LOAD_PIN, HIGH);
+  delay(1);
+
+  register_setup();
+
+  for (uint8_t i = 0; i <= 7; i++) {      // Empty registers to turn all LEDs off
+    led_line[i] = 0x00;
+    send(max7219_reg_digit0 + i, 0);
+    pulse_load();                 // tell the chips to load the clocked out data
+  }
+
+  #ifdef MAX7219_INIT_TEST
+    #if MAX7219_INIT_TEST == 2
+      spiral(true, 8);
+      delay(150);
+      spiral(false, 8);
+    #else
+      // Do an aesthetically-pleasing pattern to fully test the Max7219 module and LEDs.
+      // Light up and turn off columns, both forward and backward.
+      sweep(1, 20, true);
+      sweep(1, 20, false);
+      delay(150);
+      sweep(-1, 20, true);
+      sweep(-1, 20, false);
+    #endif
+  #endif
+}
+
+/**
+ * This code demonstrates some simple debugging using a single 8x8 LED Matrix. If your feature could
+ * benefit from matrix display, add its code here. Very little processing is required, so the 7219 is
+ * ideal for debugging when realtime feedback is important but serial output can't be used.
+ */
+
+// Apply changes to update a marker
+void Max7219::mark16(const uint8_t y, const uint8_t v1, const uint8_t v2) {
+  #if MAX7219_X_LEDS == 8
+    #if MAX7219_Y_LEDS == 8
+      led_off(v1 & 0x7, y + (v1 >= 8));
+       led_on(v2 & 0x7, y + (v2 >= 8));
+    #else
+      led_off(y, v1 & 0xF); // At least 16 LEDs down. Use a single column.
+       led_on(y, v2 & 0xF);
+    #endif
+  #else
+    led_off(v1 & 0xF, y);   // At least 16 LEDs across. Use a single row.
+     led_on(v2 & 0xF, y);
+  #endif
+}
+
+// Apply changes to update a tail-to-head range
+void Max7219::range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh) {
+  #if MAX7219_X_LEDS == 8
+    #if MAX7219_Y_LEDS == 8
+      if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
+        led_off(n & 0x7, y + (n >= 8));
+      if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
+         led_on(n & 0x7, y + (n >= 8));
+    #else // The Max7219 Y-Axis has at least 16 LED's.  So use a single column
+      if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
+        led_off(y, n & 0xF);
+      if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
+         led_on(y, n & 0xF);
+    #endif
+  #else   // LED matrix has at least 16 LED's on the X-Axis.  Use single line of LED's
+    if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
+      led_off(n & 0xF, y);
+    if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
+       led_on(n & 0xF, y);
+ #endif
+}
+
+// Apply changes to update a quantity
+void Max7219::quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv) {
+  for (uint8_t i = MIN(nv, ov); i < MAX(nv, ov); i++)
+    #if MAX7219_X_LEDS == 8
+      #if MAX7219_Y_LEDS == 8
+        led_set(i >> 1, y + (i & 1), nv >= ov); // single 8x8 LED matrix.  Use two lines to get 16 LED's
+      #else
+        led_set(y, i, nv >= ov);                // The Max7219 Y-Axis has at least 16 LED's.  So use a single column
+      #endif
+    #else
+      led_set(i, y, nv >= ov);                // LED matrix has at least 16 LED's on the X-Axis.  Use single line of LED's
+    #endif
+}
+
+void Max7219::idle_tasks() {
+  #define MAX7219_USE_HEAD (defined(MAX7219_DEBUG_PLANNER_HEAD) || defined(MAX7219_DEBUG_PLANNER_QUEUE))
+  #define MAX7219_USE_TAIL (defined(MAX7219_DEBUG_PLANNER_TAIL) || defined(MAX7219_DEBUG_PLANNER_QUEUE))
+  #if MAX7219_USE_HEAD || MAX7219_USE_TAIL
+    CRITICAL_SECTION_START;
+    #if MAX7219_USE_HEAD
+      const uint8_t head = planner.block_buffer_head;
+    #endif
+    #if MAX7219_USE_TAIL
+      const uint8_t tail = planner.block_buffer_tail;
+    #endif
+    CRITICAL_SECTION_END;
+  #endif
+
+  #if ENABLED(MAX7219_DEBUG_PRINTER_ALIVE)
+    static uint8_t refresh_cnt; // = 0
+    constexpr uint16_t refresh_limit = 5;
+    static millis_t next_blink = 0;
+    const millis_t ms = millis();
+    const bool do_blink = ELAPSED(ms, next_blink);
+  #else
+    static uint16_t refresh_cnt; // = 0
+    constexpr bool do_blink = true;
+    constexpr uint16_t refresh_limit = 50000;
+  #endif
+
+  // Some Max7219 units are vulnerable to electrical noise, especially
+  // with long wires next to high current wires. If the display becomes
+  // corrupted, this will fix it within a couple seconds.
+  if (do_blink && ++refresh_cnt >= refresh_limit) {
+    refresh_cnt = 0;
+    register_setup();
+  }
+
+  #if ENABLED(MAX7219_DEBUG_PRINTER_ALIVE)
+    if (do_blink) {
+      led_toggle(MAX7219_X_LEDS - 1, MAX7219_Y_LEDS - 1);
+      next_blink = ms + 1000;
+    }
+  #endif
+
+  #if defined(MAX7219_DEBUG_PLANNER_HEAD) && defined(MAX7219_DEBUG_PLANNER_TAIL) && MAX7219_DEBUG_PLANNER_HEAD == MAX7219_DEBUG_PLANNER_TAIL
+
+    static int16_t last_head_cnt = 0xF, last_tail_cnt = 0xF;
+
+    if (last_head_cnt != head || last_tail_cnt != tail) {
+      range16(MAX7219_DEBUG_PLANNER_HEAD, last_tail_cnt, tail, last_head_cnt, head);
+      last_head_cnt = head;
+      last_tail_cnt = tail;
+    }
+
+  #else
+
+    #ifdef MAX7219_DEBUG_PLANNER_HEAD
+      static int16_t last_head_cnt = 0x1;
+      if (last_head_cnt != head) {
+        mark16(MAX7219_DEBUG_PLANNER_HEAD, last_head_cnt, head);
+        last_head_cnt = head;
+      }
+    #endif
+
+    #ifdef MAX7219_DEBUG_PLANNER_TAIL
+      static int16_t last_tail_cnt = 0x1;
+      if (last_tail_cnt != tail) {
+        mark16(MAX7219_DEBUG_PLANNER_TAIL, last_tail_cnt, tail);
+        last_tail_cnt = tail;
+      }
+    #endif
+
+  #endif
+
+  #ifdef MAX7219_DEBUG_PLANNER_QUEUE
+    static int16_t last_depth = 0;
+    const int16_t current_depth = (head - tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1) & 0xF;
+    if (current_depth != last_depth) {
+      quantity16(MAX7219_DEBUG_PLANNER_QUEUE, last_depth, current_depth);
+      last_depth = current_depth;
+    }
+  #endif
+}
+
+#endif // MAX7219_DEBUG

+ 154 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Max7219_Debug_LEDs.h

@@ -0,0 +1,154 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * This module is off by default, but can be enabled to facilitate the display of
+ * extra debug information during code development.
+ *
+ * Just connect up 5V and GND to give it power, then connect up the pins assigned
+ * in Configuration_adv.h. For example, on the Re-ARM you could use:
+ *
+ *   #define MAX7219_CLK_PIN   77
+ *   #define MAX7219_DIN_PIN   78
+ *   #define MAX7219_LOAD_PIN  79
+ *
+ * max7219.init() is called automatically at startup, and then there are a number of
+ * support functions available to control the LEDs in the 8x8 grid.
+ *
+ * If you are using the Max7219 matrix for firmware debug purposes in time sensitive
+ * areas of the code, please be aware that the orientation (rotation) of the display can
+ * affect the speed.   The Max7219 can update a single column fairly fast.  It is much
+ * faster to do a Max7219_Set_Column() with a rotation of 90 or 270 degrees than to do
+ * a Max7219_Set_Row().    The opposite is true for rotations of 0 or 180 degrees.
+ */
+#pragma once
+
+#ifndef MAX7219_ROTATE
+  #define MAX7219_ROTATE 0
+#endif
+#define _ROT ((MAX7219_ROTATE + 360) % 360)
+
+#define MAX7219_LINES (8 * (MAX7219_NUMBER_UNITS))
+
+#if _ROT == 0 || _ROT == 180
+  #define MAX7219_Y_LEDS          8
+  #define MAX7219_X_LEDS          MAX7219_LINES
+#elif _ROT == 90 || _ROT == 270
+  #define MAX7219_X_LEDS          8
+  #define MAX7219_Y_LEDS          MAX7219_LINES
+#else
+  #error "MAX7219_ROTATE must be a multiple of +/- 90°."
+#endif
+
+//
+// MAX7219 registers
+//
+#define max7219_reg_noop        0x00
+#define max7219_reg_digit0      0x01
+#define max7219_reg_digit1      0x02
+#define max7219_reg_digit2      0x03
+#define max7219_reg_digit3      0x04
+#define max7219_reg_digit4      0x05
+#define max7219_reg_digit5      0x06
+#define max7219_reg_digit6      0x07
+#define max7219_reg_digit7      0x08
+
+#define max7219_reg_decodeMode  0x09
+#define max7219_reg_intensity   0x0A
+#define max7219_reg_scanLimit   0x0B
+#define max7219_reg_shutdown    0x0C
+#define max7219_reg_displayTest 0x0F
+
+class Max7219 {
+public:
+  static uint8_t led_line[MAX7219_LINES];
+
+  Max7219() { }
+
+  static void init();
+  static void register_setup();
+  static void putbyte(uint8_t data);
+  static void pulse_load();
+
+  // Set a single register (e.g., a whole native row)
+  static void send(const uint8_t reg, const uint8_t data);
+
+  // Refresh all units
+  inline static void refresh() { for (uint8_t i = 0; i < 8; i++) refresh_line(i); }
+
+  // Update a single native line on all units
+  static void refresh_line(const uint8_t line);
+
+  // Update a single native line on just one unit
+  static void refresh_unit_line(const uint8_t line);
+
+  // Set a single LED by XY coordinate
+  static void led_set(const uint8_t x, const uint8_t y, const bool on);
+  static void led_on(const uint8_t x, const uint8_t y);
+  static void led_off(const uint8_t x, const uint8_t y);
+  static void led_toggle(const uint8_t x, const uint8_t y);
+
+  // Set all LEDs in a single column
+  static void set_column(const uint8_t col, const uint32_t val);
+  static void clear_column(const uint8_t col);
+
+  // Set all LEDs in a single row
+  static void set_row(const uint8_t row, const uint32_t val);
+  static void clear_row(const uint8_t row);
+
+  // 16 and 32 bit versions of Row and Column functions
+  // Multiple rows and columns will be used to display the value if
+  // the array of matrix LED's is too narrow to accomplish the goal
+  static void set_rows_16bits(const uint8_t y, uint32_t val);
+  static void set_rows_32bits(const uint8_t y, uint32_t val);
+  static void set_columns_16bits(const uint8_t x, uint32_t val);
+  static void set_columns_32bits(const uint8_t x, uint32_t val);
+
+  // Quickly clear the whole matrix
+  static void clear();
+
+  // Quickly fill the whole matrix
+  static void fill();
+
+  // Apply custom code to update the matrix
+  static void idle_tasks();
+
+private:
+  static void error(const char * const func, const int32_t v1, const int32_t v2=-1);
+  static void noop();
+  static void set(const uint8_t line, const uint8_t bits);
+  static void send_row(const uint8_t row);
+  static void send_column(const uint8_t col);
+  static void mark16(const uint8_t y, const uint8_t v1, const uint8_t v2);
+  static void range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh);
+  static void quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv);
+
+  #ifdef MAX7219_INIT_TEST
+  #if MAX7219_INIT_TEST == 2
+    static void spiral(const bool on, const uint16_t del);
+  #else
+    static void sweep(const int8_t dir, const uint16_t ms, const bool on);
+  #endif
+  #endif
+};
+
+extern Max7219 max7219;

File diff suppressed because it is too large
+ 1705 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SanityCheck.h


+ 716 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Sd2Card.cpp

@@ -0,0 +1,716 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Arduino Sd2Card Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ */
+#include "MarlinConfig.h"
+
+#if ENABLED(SDSUPPORT)
+
+#include "Sd2Card.h"
+
+#if ENABLED(USE_WATCHDOG)
+  #include "watchdog.h"
+#endif
+
+#if DISABLED(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 = _BV(SPE) | _BV(MSTR) | (spiRate >> 1);
+    SPSR = spiRate & 1 || spiRate == 6 ? 0 : _BV(SPI2X);
+  }
+
+  /** SPI receive a byte */
+  static uint8_t spiRec() {
+    SPDR = 0xFF;
+    while (!TEST(SPSR, 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 (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
+      buf[i] = SPDR;
+      SPDR = 0xFF;
+    }
+    while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
+    buf[nbyte] = SPDR;
+  }
+
+  /** SPI send a byte */
+  static void spiSend(uint8_t b) {
+    SPDR = b;
+    while (!TEST(SPSR, 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 (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
+      SPDR = buf[i];
+      while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
+      SPDR = buf[i + 1];
+    }
+    while (!TEST(SPSR, 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
+    WRITE(SPI_MOSI_PIN, HIGH);
+
+    for (uint8_t i = 0; i < 8; i++) {
+      WRITE(SPI_SCK_PIN, HIGH);
+
+      // adjust so SCK is nice
+      nop;
+      nop;
+
+      data <<= 1;
+
+      if (READ(SPI_MISO_PIN)) data |= 1;
+
+      WRITE(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++) {
+      WRITE(SPI_SCK_PIN, LOW);
+
+      WRITE(SPI_MOSI_PIN, data & 0x80);
+
+      data <<= 1;
+
+      WRITE(SPI_SCK_PIN, HIGH);
+    }
+    // hold SCK high for a few ns
+    nop;
+    nop;
+    nop;
+    nop;
+
+    WRITE(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() {
+  #if DISABLED(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 true for success, false 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 true if single block erase is supported.
+ *         false 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 true for success, false for failure.
+ * The reason for failure can be determined by calling errorCode() and errorData().
+ */
+bool Sd2Card::init(uint8_t sckRateID, pin_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;
+
+  // If init takes more than 4s it could trigger
+  // watchdog leading to a reboot loop.
+  #if ENABLED(USE_WATCHDOG)
+    watchdog_reset();
+  #endif
+
+  // set pin modes
+  pinMode(chipSelectPin_, OUTPUT);
+  chipSelectHigh();
+  SET_INPUT(SPI_MISO_PIN);
+  SET_OUTPUT(SPI_MOSI_PIN);
+  SET_OUTPUT(SPI_SCK_PIN);
+
+  #if DISABLED(SOFTWARE_SPI)
+    // SS must be in output mode even it is not chip select
+    SET_OUTPUT(SS_PIN);
+    // set SS high - may be chip select for another SPI device
+    #if SET_SPI_SS_HIGH
+      WRITE(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();
+
+  #if DISABLED(SOFTWARE_SPI)
+    return setSckRate(sckRateID);
+  #else  // SOFTWARE_SPI
+    UNUSED(sckRateID);
+    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 true for success, false 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 ENABLED(SD_CHECK_AND_RETRY)
+    uint8_t retryCnt = 3;
+    for (;;) {
+      if (cardCommand(CMD17, blockNumber))
+        error(SD_CARD_ERROR_CMD17);
+      else if (readData(dst, 512))
+        return true;
+
+      chipSelectHigh();
+      if (!--retryCnt) break;
+
+      cardCommand(CMD12, 0); // Try sending a stop command, ignore the result.
+      errorCode_ = 0;
+    }
+    return false;
+  #else
+    if (cardCommand(CMD17, blockNumber)) {
+      error(SD_CARD_ERROR_CMD17);
+      chipSelectHigh();
+      return false;
+    }
+    else
+      return readData(dst, 512);
+  #endif
+}
+
+/**
+ * Read one data block in a multiple block read sequence
+ *
+ * \param[in] dst Pointer to the location for the data to be read.
+ *
+ * \return true for success, false for failure.
+ */
+bool Sd2Card::readData(uint8_t* dst) {
+  chipSelectLow();
+  return readData(dst, 512);
+}
+
+#if ENABLED(SD_CHECK_AND_RETRY)
+  static const uint16_t crctab[] PROGMEM = {
+    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
+    0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
+    0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
+    0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
+    0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
+    0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
+    0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
+    0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
+    0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
+    0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
+    0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
+    0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
+    0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
+    0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
+    0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
+    0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
+    0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
+    0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
+    0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
+    0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
+    0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
+    0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+    0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
+    0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
+    0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
+    0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
+    0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
+    0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
+    0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
+    0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
+    0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
+    0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
+  };
+  static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
+    uint16_t crc = 0;
+    for (size_t i = 0; i < n; i++) {
+      crc = pgm_read_word(&crctab[(crc >> 8 ^ data[i]) & 0xFF]) ^ (crc << 8);
+    }
+    return crc;
+  }
+#endif // SD_CHECK_AND_RETRY
+
+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);
+
+#if ENABLED(SD_CHECK_AND_RETRY)
+  {
+    uint16_t calcCrc = CRC_CCITT(dst, count);
+    uint16_t recvCrc = spiRec() << 8;
+    recvCrc |= spiRec();
+    if (calcCrc != recvCrc) {
+      error(SD_CARD_ERROR_CRC);
+      goto FAIL;
+    }
+  }
+#else
+  // discard CRC
+  spiRec();
+  spiRec();
+#endif
+  chipSelectHigh();
+  // Send an additional dummy byte, required by Toshiba Flash Air SD Card
+  spiSend(0XFF);
+  return true;
+  FAIL:
+  chipSelectHigh();
+  // Send an additional dummy byte, required by Toshiba Flash Air SD Card
+  spiSend(0XFF);
+  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);
+    chipSelectHigh();
+    return false;
+  }
+  return readData(dst, 16);
+}
+
+/**
+ * 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 true for success, false 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);
+    chipSelectHigh();
+    return false;
+  }
+  chipSelectHigh();
+  return true;
+}
+
+/**
+ * End a read multiple blocks sequence.
+ *
+ * \return true for success, false for failure.
+ */
+bool Sd2Card::readStop() {
+  chipSelectLow();
+  if (cardCommand(CMD12, 0)) {
+    error(SD_CARD_ERROR_CMD12);
+    chipSelectHigh();
+    return false;
+  }
+  chipSelectHigh();
+  return true;
+}
+
+/**
+ * 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) return false;
+
+  return true;
+}
+
+/**
+ * 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 true for success, false 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 true for success, false for failure.
+ */
+bool Sd2Card::writeData(const uint8_t* src) {
+  chipSelectLow();
+  // wait for previous write to finish
+  if (!waitNotBusy(SD_WRITE_TIMEOUT) || !writeData(WRITE_MULTIPLE_TOKEN, src)) {
+    error(SD_CARD_ERROR_WRITE_MULTIPLE);
+    chipSelectHigh();
+    return false;
+  }
+  chipSelectHigh();
+  return true;
+}
+
+// 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);
+    chipSelectHigh();
+    return false;
+  }
+  return true;
+}
+
+/**
+ * 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 true for success, false 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 true for success, false 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 // SDSUPPORT

+ 204 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Sd2Card.h

@@ -0,0 +1,204 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * \file
+ * \brief Sd2Card class for V2 SD/SDHC cards
+ */
+
+/**
+ * Arduino Sd2Card Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ */
+#ifndef _SD2CARD_H_
+#define _SD2CARD_H_
+
+#include "SdFatConfig.h"
+#include "SdInfo.h"
+
+// SPI speed is F_CPU/2^(1 + index), 0 <= index <= 6
+uint8_t const SPI_FULL_SPEED = 0,         // Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate().
+              SPI_HALF_SPEED = 1,         // Set SCK rate to F_CPU/4. See Sd2Card::setSckRate().
+              SPI_QUARTER_SPEED = 2,      // Set SCK rate to F_CPU/8. See Sd2Card::setSckRate().
+              SPI_EIGHTH_SPEED = 3,       // Set SCK rate to F_CPU/16. See Sd2Card::setSckRate().
+              SPI_SIXTEENTH_SPEED = 4;    // Set SCK rate to F_CPU/32. See Sd2Card::setSckRate().
+
+uint16_t const SD_INIT_TIMEOUT = 2000,    // init timeout ms
+               SD_ERASE_TIMEOUT = 10000,  // erase timeout ms
+               SD_READ_TIMEOUT = 300,     // read timeout ms
+               SD_WRITE_TIMEOUT = 600;    // write time out ms
+
+// SD card errors
+uint8_t const SD_CARD_ERROR_CMD0 = 0X1,                 // timeout error for command CMD0 (initialize card in SPI mode)
+              SD_CARD_ERROR_CMD8 = 0X2,                 // CMD8 was not accepted - not a valid SD card
+              SD_CARD_ERROR_CMD12 = 0X3,                // card returned an error response for CMD12 (write stop)
+              SD_CARD_ERROR_CMD17 = 0X4,                // card returned an error response for CMD17 (read block)
+              SD_CARD_ERROR_CMD18 = 0X5,                // card returned an error response for CMD18 (read multiple block)
+              SD_CARD_ERROR_CMD24 = 0X6,                // card returned an error response for CMD24 (write block)
+              SD_CARD_ERROR_CMD25 = 0X7,                // WRITE_MULTIPLE_BLOCKS command failed
+              SD_CARD_ERROR_CMD58 = 0X8,                // card returned an error response for CMD58 (read OCR)
+              SD_CARD_ERROR_ACMD23 = 0X9,               // SET_WR_BLK_ERASE_COUNT failed
+              SD_CARD_ERROR_ACMD41 = 0XA,               // ACMD41 initialization process timeout
+              SD_CARD_ERROR_BAD_CSD = 0XB,              // card returned a bad CSR version field
+              SD_CARD_ERROR_ERASE = 0XC,                // erase block group command failed
+              SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0XD,   // card not capable of single block erase
+              SD_CARD_ERROR_ERASE_TIMEOUT = 0XE,        // Erase sequence timed out
+              SD_CARD_ERROR_READ = 0XF,                 // card returned an error token instead of read data
+              SD_CARD_ERROR_READ_REG = 0x10,            // read CID or CSD failed
+              SD_CARD_ERROR_READ_TIMEOUT = 0x11,        // timeout while waiting for start of read data
+              SD_CARD_ERROR_STOP_TRAN = 0x12,           // card did not accept STOP_TRAN_TOKEN
+              SD_CARD_ERROR_WRITE = 0x13,               // card returned an error token as a response to a write operation
+              SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0x14,    // REMOVE - not used ... attempt to write protected block zero
+              SD_CARD_ERROR_WRITE_MULTIPLE = 0x15,      // card did not go ready for a multiple block write
+              SD_CARD_ERROR_WRITE_PROGRAMMING = 0x16,   // card returned an error to a CMD13 status check after a write
+              SD_CARD_ERROR_WRITE_TIMEOUT = 0x17,       // timeout occurred during write programming
+              SD_CARD_ERROR_SCK_RATE = 0x18,            // incorrect rate selected
+              SD_CARD_ERROR_INIT_NOT_CALLED = 0x19,     // init() not called
+              SD_CARD_ERROR_CRC = 0x20;                 // crc check error
+
+// card types
+uint8_t const SD_CARD_TYPE_SD1  = 1,                    // Standard capacity V1 SD card
+              SD_CARD_TYPE_SD2  = 2,                    // Standard capacity V2 SD card
+              SD_CARD_TYPE_SDHC = 3;                    // High Capacity SD card
+
+/**
+ * define SOFTWARE_SPI to use bit-bang SPI
+ */
+#if MEGA_SOFT_SPI
+  #define SOFTWARE_SPI
+#elif USE_SOFTWARE_SPI
+  #define SOFTWARE_SPI
+#endif
+
+// SPI pin definitions - do not edit here - change in SdFatConfig.h
+#if DISABLED(SOFTWARE_SPI)
+  // hardware pin defs
+  #define SD_CHIP_SELECT_PIN SS_PIN   // The default chip select pin for the SD card is SS.
+  // The following three pins must not be redefined for hardware SPI.
+  #define SPI_MOSI_PIN MOSI_PIN       // SPI Master Out Slave In pin
+  #define SPI_MISO_PIN MISO_PIN       // SPI Master In Slave Out pin
+  #define SPI_SCK_PIN SCK_PIN         // SPI Clock pin
+#else  // SOFTWARE_SPI
+  #define SD_CHIP_SELECT_PIN SOFT_SPI_CS_PIN  // SPI chip select pin
+  #define SPI_MOSI_PIN SOFT_SPI_MOSI_PIN      // SPI Master Out Slave In pin
+  #define SPI_MISO_PIN SOFT_SPI_MISO_PIN      // SPI Master In Slave Out pin
+  #define SPI_SCK_PIN SOFT_SPI_SCK_PIN        // SPI Clock pin
+#endif  // SOFTWARE_SPI
+
+/**
+ * \class Sd2Card
+ * \brief Raw access to SD and SDHC flash memory cards.
+ */
+class Sd2Card {
+  public:
+
+  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,
+            pin_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_,
+          errorCode_,
+          spiRate_,
+          status_,
+          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_

File diff suppressed because it is too large
+ 1728 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdBaseFile.cpp


+ 390 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdBaseFile.h

@@ -0,0 +1,390 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * \file
+ * \brief SdBaseFile class
+ */
+
+/**
+ * Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ */
+#ifndef _SDBASEFILE_H_
+#define _SDBASEFILE_H_
+
+#include "SdFatConfig.h"
+#include "SdVolume.h"
+
+#include <stdint.h>
+
+/**
+ * \struct filepos_t
+ * \brief internal type for istream
+ * do not use in user apps
+ */
+struct filepos_t {
+  uint32_t position;  // stream byte position
+  uint32_t cluster;   // cluster of position
+  filepos_t() : position(0), cluster(0) {}
+};
+
+// use the gnu style oflag in open()
+uint8_t const O_READ = 0x01,                    // open() oflag for reading
+              O_RDONLY = O_READ,                // open() oflag - same as O_IN
+              O_WRITE = 0x02,                   // open() oflag for write
+              O_WRONLY = O_WRITE,               // open() oflag - same as O_WRITE
+              O_RDWR = (O_READ | O_WRITE),      // open() oflag for reading and writing
+              O_ACCMODE = (O_READ | O_WRITE),   // open() oflag mask for access modes
+              O_APPEND = 0x04,                  // The file offset shall be set to the end of the file prior to each write.
+              O_SYNC = 0x08,                    // Synchronous writes - call sync() after each write
+              O_TRUNC = 0x10,                   // Truncate the file to zero length
+              O_AT_END = 0x20,                  // Set the initial position at the end of the file
+              O_CREAT = 0x40,                   // Create the file if nonexistent
+              O_EXCL = 0x80;                    // If O_CREAT and O_EXCL are set, open() shall fail if the file exists
+
+// SdBaseFile class static and const definitions
+
+// flags for ls()
+uint8_t const LS_DATE = 1,    // ls() flag to print modify date
+              LS_SIZE = 2,    // ls() flag to print file size
+              LS_R = 4;       // ls() flag for recursive list of subdirectories
+
+
+// flags for timestamp
+uint8_t const T_ACCESS = 1,   // Set the file's last access date
+              T_CREATE = 2,   // Set the file's creation date and time
+              T_WRITE = 4;    // Set the file's write date and time
+
+// values for type_
+uint8_t const FAT_FILE_TYPE_CLOSED = 0,                           // This file has not been opened.
+              FAT_FILE_TYPE_NORMAL = 1,                           // A normal file
+              FAT_FILE_TYPE_ROOT_FIXED = 2,                       // A FAT12 or FAT16 root directory
+              FAT_FILE_TYPE_ROOT32 = 3,                           // A FAT32 root directory
+              FAT_FILE_TYPE_SUBDIR = 4,                           // A subdirectory file
+              FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT_FIXED;   // Test value for directory type
+
+/**
+ * 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:
+  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(filepos_t* pos);
+
+  /**
+   * set position for streams
+   * \param[out] pos struct with value for new position
+   */
+  void setpos(filepos_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_; }
+
+  /**
+   * \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; }
+
+  bool getFilename(char * const name);
+  void ls(uint8_t flags = 0, uint8_t indent = 0);
+
+  bool mkdir(SdBaseFile* dir, const char* path, bool pFlag = true);
+  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();
+  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(const 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(const int32_t offset = 0) { return seekSet(fileSize_ + offset); }
+  bool seekSet(const 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. 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:
+  friend class SdFat;           // allow SdFat to set cwd_
+  static SdBaseFile* cwd_;      // global pointer to cwd dir
+
+  // data time callback function
+  static void (*dateTime_)(uint16_t* date, uint16_t* time);
+
+  // bits defined in flags_
+  static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC),   // should be 0x0F
+                       F_FILE_DIR_DIRTY = 0x80;                     // sync of directory entry required
+
+  // 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();
+};
+
+#endif // _SDBASEFILE_H_

+ 116 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdFatConfig.h

@@ -0,0 +1,116 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * SdFatConfig.h
+ * Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ */
+
+#ifndef _SDFATCONFIG_H_
+#define _SDFATCONFIG_H_
+
+#include "MarlinConfig.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 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
+#define SOFT_SPI_CS_PIN   10 // Software SPI chip select pin for the SD
+#define SOFT_SPI_MOSI_PIN 11 // Software SPI Master Out Slave In pin
+#define SOFT_SPI_MISO_PIN 12 // Software SPI Master In Slave Out pin
+#define SOFT_SPI_SCK_PIN  13 // Software SPI Clock pin
+
+/**
+ * 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 8.3 and long (vfat) filenames
+ */
+
+#define FILENAME_LENGTH 13 // Number of UTF-16 characters per entry
+
+// Total bytes needed to store a single long filename
+#define LONG_FILENAME_LENGTH (FILENAME_LENGTH * MAX_VFAT_ENTRIES + 1)
+
+#endif // _SDFATCONFIG_H_

+ 615 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdFatStructs.h

@@ -0,0 +1,615 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * \file
+ * \brief FAT file structures
+ */
+
+/**
+ * Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ */
+#ifndef SDFATSTRUCTS_H
+#define SDFATSTRUCTS_H
+
+#define PACKED __attribute__((__packed__))
+
+/**
+ * mostly from Microsoft document fatgen103.doc
+ * http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
+ */
+
+uint8_t const BOOTSIG0 = 0x55,          // Value for byte 510 of boot block or MBR
+              BOOTSIG1 = 0xAA,          // Value for byte 511 of boot block or MBR
+              EXTENDED_BOOT_SIG = 0x29; // Value for bootSignature field int FAT/FAT32 boot sector
+
+/**
+ * \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;
+
+  uint32_t firstSector;   // Logical block address of the first block in the partition.
+  uint32_t totalSectors;  // Length of the partition, in blocks.
+} PACKED;
+
+typedef struct partitionTable part_t; // Type name for partitionTable
+
+/**
+ * \struct masterBootRecord
+ *
+ * \brief Master Boot Record
+ *
+ * The first block of a storage device that is formatted with a MBR.
+ */
+struct masterBootRecord {
+  uint8_t  codeArea[440]; // Code Area for master boot program.
+  uint32_t diskSignature; // Optional Windows NT disk signature. May contain boot code.
+  uint16_t usuallyZero;   // Usually zero but may be more boot code.
+  part_t   part[4];       // Partition tables.
+  uint8_t  mbrSig0;       // First MBR signature byte. Must be 0x55
+  uint8_t  mbrSig1;       // Second MBR signature byte. Must be 0xAA
+} 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;
+
+  uint16_t sectorsPerTrack; // Sectors per track for interrupt 0x13. Not used otherwise.
+  uint16_t headCount;       // Number of heads for interrupt 0x13. Not used otherwise.
+
+  /**
+   * 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;
+
+  uint8_t  reserved1;       // used by Windows NT - should be zero for FAT
+  uint8_t  bootSignature;   // 0x29 if next three fields are valid
+
+  /**
+   * 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];
+
+  uint8_t  bootCode[448];   // X86 boot code
+  uint8_t  bootSectorSig0;  // must be 0x55
+  uint8_t  bootSectorSig1;  // must be 0xAA
+} PACKED;
+
+typedef struct fat_boot fat_boot_t;   // Type name for FAT Boot Sector
+
+/**
+ * \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;
+
+  uint16_t sectorsPerTrack; // Sectors per track for interrupt 0x13. Not used otherwise.
+  uint16_t headCount;       // Number of heads for interrupt 0x13. Not used otherwise.
+
+  /**
+   * 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;
+
+  uint8_t  reserved1;       // Used by Windows NT - should be zero for FAT
+  uint8_t  bootSignature;   // 0x29 if next three fields are valid
+
+  /**
+   * 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];
+
+  uint8_t  bootCode[420];   // X86 boot code
+  uint8_t  bootSectorSig0;  // must be 0x55
+  uint8_t  bootSectorSig1;  // must be 0xAA
+
+} PACKED;
+
+typedef struct fat32_boot fat32_boot_t; // Type name for FAT32 Boot Sector
+
+uint32_t const FSINFO_LEAD_SIG   = 0x41615252,  // 'AaRR' Lead signature for a FSINFO sector
+               FSINFO_STRUCT_SIG = 0x61417272;  // 'aArr' Struct signature for a FSINFO sector
+
+/**
+ * \struct fat32_fsinfo
+ *
+ * \brief FSINFO sector for a FAT32 volume.
+ *
+ */
+struct fat32_fsinfo {
+  uint32_t  leadSignature;    // must be 0x52, 0x52, 0x61, 0x41 'RRaA'
+  uint8_t  reserved1[480];    // must be zero
+  uint32_t  structSignature;  // must be 0x72, 0x72, 0x41, 0x61 'rrAa'
+          /**
+           * 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;
+
+  uint8_t  reserved2[12];     // must be zero
+  uint8_t  tailSignature[4];  // must be 0x00, 0x00, 0x55, 0xAA
+} PACKED;
+
+typedef struct fat32_fsinfo fat32_fsinfo_t; // Type name for FAT32 FSINFO Sector
+
+// End Of Chain values for FAT entries
+uint16_t const FAT12EOC = 0xFFF,          // FAT12 end of chain value used by Microsoft.
+               FAT12EOC_MIN = 0xFF8,      // Minimum value for FAT12 EOC.  Use to test for EOC.
+               FAT16EOC = 0xFFFF,         // FAT16 end of chain value used by Microsoft.
+               FAT16EOC_MIN = 0xFFF8;     // Minimum value for FAT16 EOC.  Use to test for EOC.
+uint32_t const FAT32EOC = 0x0FFFFFFF,     // FAT32 end of chain value used by Microsoft.
+               FAT32EOC_MIN = 0x0FFFFFF8, // Minimum value for FAT32 EOC.  Use to test for EOC.
+               FAT32MASK = 0x0FFFFFFF;    // Mask a for FAT32 entry. Entries are 28 bits.
+
+/**
+ * \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 it's valid
+   * value range is 0-199 inclusive. (WHG note - seems to be hundredths)
+   */
+  uint8_t  creationTimeTenths;
+
+  uint16_t creationTime;    // Time file was created.
+  uint16_t creationDate;    // Date file was created.
+
+  /**
+   * 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;
+
+  uint16_t lastWriteTime;   // Time of last write. File creation is considered a write.
+  uint16_t lastWriteDate;   // Date of last write. File creation is considered a write.
+  uint16_t firstClusterLow; // Low word of this entry's first cluster number.
+  uint32_t fileSize;        // 32-bit unsigned holding this file's size in bytes.
+} 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;
+
+  uint16_t name1[5];        // First set of UTF-16 characters
+  uint8_t  attributes;      // attributes (at the same location as in directoryEntry), always 0x0F
+  uint8_t  reservedNT;      // Reserved for use by Windows NT. Always 0.
+  uint8_t  checksum;        // 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.
+  uint16_t name2[6];        // Second set of UTF-16 characters
+  uint16_t firstClusterLow; // firstClusterLow is always zero for longFilenames
+  uint16_t name3[2];        // Third set of UTF-16 characters
+} PACKED;
+
+// Definitions for directory entries
+//
+typedef struct directoryEntry dir_t;          // Type name for directoryEntry
+typedef struct directoryVFATEntry vfat_t;     // Type name for directoryVFATEntry
+
+uint8_t const DIR_NAME_0xE5     = 0x05,       // escape for name[0] = 0xE5
+              DIR_NAME_DELETED  = 0xE5,       // name[0] value for entry that is free after being "deleted"
+              DIR_NAME_FREE     = 0x00,       // name[0] value for entry that is free and no allocated entries follow
+              DIR_ATT_READ_ONLY = 0x01,       // file is read-only
+              DIR_ATT_HIDDEN    = 0x02,       // File should hidden in directory listings
+              DIR_ATT_SYSTEM    = 0x04,       // Entry is for a system file
+              DIR_ATT_VOLUME_ID = 0x08,       // Directory entry contains the volume label
+              DIR_ATT_DIRECTORY = 0x10,       // Entry is for a directory
+              DIR_ATT_ARCHIVE   = 0x20,       // Old DOS archive bit for backup support
+              DIR_ATT_LONG_NAME = 0x0F,       // Test value for long name entry.  Test is (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME.
+              DIR_ATT_LONG_NAME_MASK = 0x3F,  // Test mask for long name entry
+              DIR_ATT_DEFINED_BITS = 0x3F;    // defined attribute bits
+
+/**
+ * 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

+ 91 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdFatUtil.cpp

@@ -0,0 +1,91 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Arduino SdFat Library
+ * Copyright (C) 2008 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ */
+#include "MarlinConfig.h"
+
+#if ENABLED(SDSUPPORT)
+
+#include "SdFatUtil.h"
+#include "serial.h"
+
+/**
+ * Amount of free RAM
+ * \return The number of free bytes.
+ */
+#ifdef __arm__
+extern "C" char* sbrk(int incr);
+int SdFatUtil::FreeRam() {
+  char top;
+  return &top - reinterpret_cast<char*>(sbrk(0));
+}
+#else  // __arm__
+extern char* __brkval;
+extern char __bss_end;
+/**
+ * Amount of free RAM
+ * \return The number of free bytes.
+ */
+int SdFatUtil::FreeRam() {
+  char top;
+  return __brkval ? &top - __brkval : &top - &__bss_end;
+}
+#endif  // __arm
+
+/**
+ * %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++) SERIAL_CHAR(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); SERIAL_EOL(); }
+
+/**
+ * %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 // SDSUPPORT

+ 51 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdFatUtil.h

@@ -0,0 +1,51 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Arduino SdFat Library
+ * Copyright (C) 2008 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ */
+#ifndef _SDFATUTIL_H_
+#define _SDFATUTIL_H_
+
+/**
+ * \file
+ * \brief Useful utility functions.
+ */
+/** 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 // _SDFATUTIL_H_

+ 100 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdFile.cpp

@@ -0,0 +1,100 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ */
+#include "MarlinConfig.h"
+
+#if ENABLED(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 // SDSUPPORT

+ 60 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdFile.h

@@ -0,0 +1,60 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * \file
+ * \brief SdFile class
+ */
+
+/**
+ * Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ */
+#ifndef _SDFILE_H_
+#define _SDFILE_H_
+
+#include "SdBaseFile.h"
+#include <Print.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_

+ 267 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdInfo.h

@@ -0,0 +1,267 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Arduino Sd2Card Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ */
+#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
+uint8_t const CMD0 = 0x00,    // GO_IDLE_STATE - init card in spi mode if CS low
+              CMD8 = 0x08,    // SEND_IF_COND - verify SD Memory Card interface operating condition
+              CMD9 = 0x09,    // SEND_CSD - read the Card Specific Data (CSD register)
+              CMD10 = 0x0A,   // SEND_CID - read the card identification information (CID register)
+              CMD12 = 0x0C,   // STOP_TRANSMISSION - end multiple block read sequence
+              CMD13 = 0x0D,   // SEND_STATUS - read the card status register
+              CMD17 = 0x11,   // READ_SINGLE_BLOCK - read a single data block from the card
+              CMD18 = 0x12,   // READ_MULTIPLE_BLOCK - read a multiple data blocks from the card
+              CMD24 = 0x18,   // WRITE_BLOCK - write a single data block to the card
+              CMD25 = 0x19,   // WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION
+              CMD32 = 0x20,   // ERASE_WR_BLK_START - sets the address of the first block to be erased
+              CMD33 = 0x21,   // ERASE_WR_BLK_END - sets the address of the last block of the continuous range to be erased*/
+              CMD38 = 0x26,   // ERASE - erase all previously selected blocks */
+              CMD55 = 0x37,   // APP_CMD - escape for application specific command */
+              CMD58 = 0x3A,   // READ_OCR - read the OCR register of a card */
+              ACMD23 = 0x17,  // SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be pre-erased before writing */
+              ACMD41 = 0x29;  // SD_SEND_OP_COMD - Sends host capacity support information and activates the card's initialization process */
+
+/** 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_

+ 384 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdVolume.cpp

@@ -0,0 +1,384 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ */
+#include "MarlinConfig.h"
+
+#if ENABLED(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_) return false;
+
+    // past end - start from beginning of FAT
+    if (endCluster > fatEnd) {
+      bgnCluster = endCluster = 2;
+    }
+    uint32_t f;
+    if (!fatGet(endCluster, &f)) return false;
+
+    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)) return false;
+
+  // link clusters
+  while (endCluster > bgnCluster) {
+    if (!fatPut(endCluster - 1, endCluster)) return false;
+    endCluster--;
+  }
+  if (*curCluster != 0) {
+    // connect chains
+    if (!fatPut(*curCluster, bgnCluster)) return false;
+  }
+  // return first cluster number to caller
+  *curCluster = bgnCluster;
+
+  // remember possible next free cluster
+  if (setStart) allocSearchStart_ = bgnCluster + 1;
+
+  return true;
+}
+
+bool SdVolume::cacheFlush() {
+  if (cacheDirty_) {
+    if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data))
+      return false;
+
+    // mirror FAT tables
+    if (cacheMirrorBlock_) {
+      if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data))
+        return false;
+      cacheMirrorBlock_ = 0;
+    }
+    cacheDirty_ = 0;
+  }
+  return true;
+}
+
+bool SdVolume::cacheRawBlock(uint32_t blockNumber, bool dirty) {
+  if (cacheBlockNumber_ != blockNumber) {
+    if (!cacheFlush()) return false;
+    if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) return false;
+    cacheBlockNumber_ = blockNumber;
+  }
+  if (dirty) cacheDirty_ = true;
+  return true;
+}
+
+// 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)) return false;
+    s += 512UL << clusterSizeShift_;
+  } while (!isEOC(cluster));
+  *size = s;
+  return true;
+}
+
+// Fetch a FAT entry
+bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
+  uint32_t lba;
+  if (cluster > (clusterCount_ + 1)) return false;
+  if (FAT12_SUPPORT && fatType_ == 12) {
+    uint16_t index = cluster;
+    index += index >> 1;
+    lba = fatStartBlock_ + (index >> 9);
+    if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false;
+    index &= 0x1FF;
+    uint16_t tmp = cacheBuffer_.data[index];
+    index++;
+    if (index == 512) {
+      if (!cacheRawBlock(lba + 1, CACHE_FOR_READ)) return false;
+      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
+    return false;
+
+  if (lba != cacheBlockNumber_ && !cacheRawBlock(lba, CACHE_FOR_READ))
+    return false;
+
+  *value = (fatType_ == 16) ? cacheBuffer_.fat16[cluster & 0xFF] : (cacheBuffer_.fat32[cluster & 0x7F] & FAT32MASK);
+  return true;
+}
+
+// Store a FAT entry
+bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
+  uint32_t lba;
+  // error if reserved cluster
+  if (cluster < 2) return false;
+
+  // error if not in FAT
+  if (cluster > (clusterCount_ + 1)) return false;
+
+  if (FAT12_SUPPORT && fatType_ == 12) {
+    uint16_t index = cluster;
+    index += index >> 1;
+    lba = fatStartBlock_ + (index >> 9);
+    if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) return false;
+    // 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)) return false;
+      // 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
+    return false;
+
+  if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) return false;
+
+  // 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;
+}
+
+// free a cluster chain
+bool SdVolume::freeChain(uint32_t cluster) {
+  // clear free cluster location
+  allocSearchStart_ = 2;
+
+  do {
+    uint32_t next;
+    if (!fatGet(cluster, &next)) return false;
+
+    // free cluster
+    if (!fatPut(cluster, 0)) return false;
+
+    cluster = next;
+  } while (!isEOC(cluster));
+
+  return true;
+}
+
+/** 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;
+    NOMORE(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 true for success, false 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, 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) return false;
+    if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;
+    part_t* p = &cacheBuffer_.mbr.part[part - 1];
+    if ((p->boot & 0x7F) != 0  || p->totalSectors < 100 || p->firstSector == 0)
+      return false; // not a valid partition
+    volumeStartBlock = p->firstSector;
+  }
+  if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;
+  fbs = &cacheBuffer_.fbs32;
+  if (fbs->bytesPerSector != 512 ||
+      fbs->fatCount == 0 ||
+      fbs->reservedSectorCount == 0 ||
+      fbs->sectorsPerCluster == 0) {
+    // not valid FAT volume
+    return false;
+  }
+  fatCount_ = fbs->fatCount;
+  blocksPerCluster_ = fbs->sectorsPerCluster;
+  // determine shift that is same as multiply by blocksPerCluster_
+  clusterSizeShift_ = 0;
+  while (blocksPerCluster_ != _BV(clusterSizeShift_)) {
+    // error if not power of 2
+    if (clusterSizeShift_++ > 7) return false;
+  }
+  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) return false;
+  }
+  else if (clusterCount_ < 65525)
+    fatType_ = 16;
+  else {
+    rootDirStart_ = fbs->fat32RootCluster;
+    fatType_ = 32;
+  }
+  return true;
+}
+
+#endif // SDSUPPORT

+ 211 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/SdVolume.h

@@ -0,0 +1,211 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * \file
+ * \brief SdVolume class
+ */
+
+/**
+ * Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino Sd2Card Library
+ */
+#ifndef _SDVOLUME_H_
+#define _SDVOLUME_H_
+
+#include "SdFatConfig.h"
+#include "Sd2Card.h"
+#include "SdFatStructs.h"
+
+//==============================================================================
+// SdVolume class
+/**
+ * \brief Cache for an SD data block
+ */
+union cache_t {
+  uint8_t         data[512];  // Used to access cached file data blocks.
+  uint16_t        fat16[256]; // Used to access cached FAT16 entries.
+  uint32_t        fat32[128]; // Used to access cached FAT32 entries.
+  dir_t           dir[16];    // Used to access cached directory entries.
+  mbr_t           mbr;        // Used to access a cached Master Boot Record.
+  fat_boot_t      fbs;        // Used to access to a cached FAT boot sector.
+  fat32_boot_t    fbs32;      // Used to access to a cached FAT32 boot sector.
+  fat32_fsinfo_t  fsinfo;     // Used to access to a cached FAT32 FSINFO sector.
+};
+
+/**
+ * \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 true for success, false 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
+  uint8_t blocksPerCluster() const { return blocksPerCluster_; } //> \return The volume's cluster size in blocks.
+  uint32_t blocksPerFat() const { return blocksPerFat_; }        //> \return The number of blocks in one FAT.
+  uint32_t clusterCount() const { return clusterCount_; }        //> \return The total number of clusters in the volume.
+  uint8_t clusterSizeShift() const { return clusterSizeShift_; } //> \return The shift count required to multiply by blocksPerCluster.
+  uint32_t dataStartBlock() const { return dataStartBlock_; }    //> \return The logical block number for the start of file data.
+  uint8_t fatCount() const { return fatCount_; }                 //> \return The number of FAT structures on the volume.
+  uint32_t fatStartBlock() const { return fatStartBlock_; }      //> \return The logical block number for the start of the first FAT.
+  uint8_t fatType() const { return fatType_; }                   //> \return The FAT type of the volume. Values are 12, 16 or 32.
+  int32_t freeClusterCount();
+  uint32_t rootDirEntryCount() const { return rootDirEntryCount_; } /** \return The number of entries in the root directory for FAT16 volumes. */
+
+  /**
+   * \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
+    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
+
+  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() const { return cacheBlockNumber_; }
+
+  #if USE_MULTIPLE_CARDS
+    bool cacheFlush();
+    bool cacheRawBlock(uint32_t blockNumber, bool dirty);
+  #else
+    static bool cacheFlush();
+    static bool cacheRawBlock(uint32_t blockNumber, bool dirty);
+  #endif
+
+  // 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
+  #if ALLOW_DEPRECATED_FUNCTIONS
+    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); }
+      /**
+       * \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) { return init(&dev, part); }
+  #endif  // ALLOW_DEPRECATED_FUNCTIONS
+};
+
+#endif // _SDVOLUME_H_

+ 94 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/Version.h

@@ -0,0 +1,94 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * This file is the standard Marlin version identifier file, all fields can be
+ * overriden by the ones defined on _Version.h by using the Configuration.h
+ * directive USE_AUTOMATIC_VERSIONING.
+ */
+
+#if ENABLED(USE_AUTOMATIC_VERSIONING)
+
+  #include "_Version.h"
+
+#else
+
+  /**
+   * Marlin release version identifier
+   */
+  #define SHORT_BUILD_VERSION "1.1.9"
+
+  /**
+   * Verbose version identifier which should contain a reference to the location
+   * from where the binary was downloaded or the source code was compiled.
+   */
+  #define DETAILED_BUILD_VERSION SHORT_BUILD_VERSION " (Github)"
+
+  /**
+   * The STRING_DISTRIBUTION_DATE represents when the binary file was built,
+   * here we define this default string as the date where the latest release
+   * version was tagged.
+   */
+  #define STRING_DISTRIBUTION_DATE "2018-08-01"
+
+  /**
+   * Required minimum Configuration.h and Configuration_adv.h file versions.
+   *
+   * You must increment this version number for every significant change such as,
+   * but not limited to: ADD, DELETE RENAME OR REPURPOSE any directive/option on
+   * the configuration files.
+   */
+  #define REQUIRED_CONFIGURATION_H_VERSION 010109
+  #define REQUIRED_CONFIGURATION_ADV_H_VERSION 010109
+
+  /**
+   * The protocol for communication to the host. Protocol indicates communication
+   * standards such as the use of ASCII, "echo:" and "error:" line prefixes, etc.
+   * (Other behaviors are given by the firmware version and capabilities report.)
+   */
+  #define PROTOCOL_VERSION "1.0"
+
+  /**
+   * Defines a generic printer name to be output to the LCD after booting Marlin.
+   */
+  #define MACHINE_NAME "3D Printer"
+
+  /**
+   * The SOURCE_CODE_URL is the location where users will find the Marlin Source
+   * Code which is installed on the device. In most cases —unless the manufacturer
+   * has a distinct Github fork— the Source Code URL should just be the main
+   * Marlin repository.
+   */
+  #define SOURCE_CODE_URL "https://github.com/MarlinFirmware/Marlin"
+
+  /**
+   * Default generic printer UUID.
+   */
+  #define DEFAULT_MACHINE_UUID "cede2a2f-41a2-4748-9b12-c55c62f367ff"
+
+  /**
+   * The WEBSITE_URL is the location where users can get more information such as
+   * documentation about a specific Marlin release.
+   */
+  #define WEBSITE_URL "http://marlinfw.org"
+
+#endif // USE_AUTOMATIC_VERSIONING

+ 75 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/_Bootscreen.h

@@ -0,0 +1,75 @@
+/**
+ * Made with Marlin Bitmap Converter
+ * http://marlinfw.org/tools/u8glib/converter.html
+ *
+ * This bitmap from the file 'bootscreen3.jpg'
+ */
+#define CUSTOM_BOOTSCREEN_BMPWIDTH  128
+#define CUSTOM_BOOTSCREEN_BMPHEIGHT 64
+const unsigned char custom_start_bmp[] PROGMEM = {
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x1F,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x07,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x0E,0x3C,0x38,0x89,0xE7,0xC0,0x00,
+  0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x11,0x22,0x44,0x89,0x24,0x00,0x00,
+  0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x10,0x22,0x44,0x89,0x24,0x00,0x00,
+  0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x13,0x3C,0x44,0x89,0xE7,0xC0,0x00,
+  0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x00,0x11,0x24,0x44,0x89,0x04,0x00,0x00,
+  0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x00,0x11,0x22,0x44,0x89,0x04,0x00,0x00,
+  0x00,0x7F,0xFF,0xC0,0x00,0x0F,0xFF,0xFC,0x00,0x0E,0x22,0x38,0x71,0x07,0xC0,0x00,
+  0x00,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0xFF,0xC0,0x00,0x00,0x00,0x0F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0xFE,0x00,0x00,0x78,0x00,0x01,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0xFE,0x00,0x06,0x01,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0xFC,0x00,0x10,0x00,0x40,0x00,0xFE,0x0F,0xA2,0x78,0xFB,0xC6,0x07,0x9E,0x00,
+  0x01,0xFC,0x00,0x20,0xFC,0x10,0x00,0xFE,0x08,0x32,0x44,0x82,0x29,0x04,0x11,0x00,
+  0x01,0xFC,0x00,0x0E,0xFF,0xC0,0x00,0xFE,0x08,0x32,0x44,0x82,0x21,0x04,0x11,0x00,
+  0x01,0xFC,0x00,0x8C,0xFD,0xC4,0x00,0x7E,0x0F,0xAA,0x44,0xFB,0xC2,0x07,0x1E,0x00,
+  0x01,0xFC,0x01,0x00,0xFC,0x02,0x00,0x7E,0x08,0x26,0x44,0x82,0x41,0x04,0x12,0x00,
+  0x01,0xF8,0x02,0x00,0xFC,0x00,0x00,0x7F,0x08,0x26,0x44,0x82,0x29,0x04,0x11,0x00,
+  0x01,0xF8,0x00,0xFE,0xFF,0xFD,0x00,0x7F,0x0F,0xA2,0x78,0xFA,0x26,0x24,0x11,0x00,
+  0x01,0xF8,0x04,0x00,0xFC,0x00,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x03,0xF8,0x00,0x00,0x00,0x00,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x03,0xF8,0x08,0x00,0x70,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x03,0xF8,0x08,0x00,0x20,0x00,0x40,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x03,0xF8,0x08,0x00,0x00,0x00,0x40,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,
+  0x03,0xF8,0x00,0x00,0x08,0x00,0x40,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,
+  0x03,0xF8,0x00,0x06,0x08,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,
+  0x03,0xF8,0x00,0x07,0xFE,0x20,0x00,0x3F,0x00,0x00,0x00,0x06,0x00,0x00,0x20,0x00,
+  0x03,0xF8,0x7F,0x07,0xFE,0xC3,0xF0,0x3F,0x00,0x00,0x00,0x03,0xC0,0x00,0x20,0x00,
+  0x03,0xF8,0x7F,0x3F,0xFF,0x63,0xF8,0x3F,0x00,0x00,0x00,0x00,0xF0,0x00,0x20,0x00,
+  0x03,0xF8,0x67,0x6F,0xFF,0xC1,0x98,0x3F,0x00,0x00,0x00,0x00,0x30,0x00,0x20,0x00,
+  0x03,0xF8,0x0E,0x2F,0xF7,0xF9,0x98,0x7F,0x00,0x00,0x00,0x00,0x30,0x00,0x20,0x00,
+  0x01,0xF8,0x0E,0x0F,0xFF,0xB1,0x98,0x7F,0x00,0x00,0x00,0x00,0x30,0x00,0x60,0x00,
+  0x01,0xF8,0x07,0x0F,0xFF,0x71,0x98,0x7F,0x00,0x00,0x00,0x00,0x30,0x00,0x60,0x00,
+  0x01,0xF8,0x67,0x09,0xFE,0x83,0x98,0x7F,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,
+  0x01,0xF8,0x7F,0x1B,0x4D,0x03,0xF0,0x7E,0x00,0x00,0x00,0x07,0xF0,0x00,0x60,0x00,
+  0x01,0xFC,0x3C,0x00,0x3E,0x83,0xE0,0x7E,0x00,0x00,0x00,0x0F,0xF8,0x00,0xC0,0x03,
+  0x01,0xFC,0x00,0x00,0xC0,0x00,0x00,0xFE,0x00,0x00,0x08,0x1F,0xFE,0x00,0xC0,0x06,
+  0x01,0xFC,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x08,0x1F,0xFF,0x00,0xC0,0x0C,
+  0x00,0xFC,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x0C,0x1F,0xFF,0x81,0xC0,0x18,
+  0x00,0xFE,0x00,0x00,0x00,0x00,0x01,0xFE,0x00,0x00,0x0C,0x1F,0xFF,0xC1,0x80,0xF0,
+  0x00,0xFF,0x00,0x02,0x00,0x00,0x01,0xFC,0x00,0x00,0x04,0x7F,0xFF,0xC1,0x81,0xE0,
+  0x00,0xFF,0xC0,0x1F,0xC0,0x00,0x0F,0xFC,0x00,0x00,0x07,0xFF,0xFF,0x83,0x83,0xC0,
+  0x00,0xFF,0xFC,0x7F,0xE0,0x00,0x7F,0xFC,0x00,0x00,0x03,0x8F,0xFF,0x83,0x87,0x00,
+  0x00,0x7F,0xFF,0xFF,0xF0,0x07,0xFF,0xF8,0x00,0x00,0x00,0x07,0xFF,0xFF,0x0E,0x00,
+  0x00,0x7F,0xFF,0xFF,0xF9,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x07,0xFF,0xFF,0x1C,0x00,
+  0x00,0x7F,0xFF,0xF9,0xF9,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x03,0xFF,0xFF,0x18,0x00,
+  0x00,0x0F,0xFF,0xF0,0xF9,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x01,0xFF,0xFF,0xB8,0x00,
+  0x00,0x01,0xFF,0xF0,0xF9,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xF0,0x00,
+  0x00,0x00,0xFF,0xF0,0xF9,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xF0,0x00,
+  0x00,0x00,0x1F,0xF9,0xF9,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xE0,0x00,
+  0x00,0x00,0x00,0xFF,0xF9,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xE0,0x03,
+  0x00,0x00,0x00,0x7F,0xF3,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xF0,0x7F,
+  0x00,0x00,0x00,0x3F,0xE1,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xF1,0xFF,
+  0x00,0x00,0x00,0x1F,0xC0,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xE0,
+  0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x03,0xF9,0xFF,0xFF,0xC0,
+  0x00,0x00,0x00,0x00,0x00,0x3F,0xC0,0x00,0x00,0x00,0x00,0x1F,0xF0,0xFF,0xFF,0xE0,
+  0x00,0x00,0x00,0x00,0x00,0x1F,0xC0,0x00,0x00,0x00,0xF9,0xFC,0x00,0xFF,0xFF,0xF0,
+  0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x00,0xFF,0xE0,0x03,0xFF,0xFF,0xFC,
+  0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x07,0x8F,0xFF,0xFE,
+  0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x1F,0x03,0xFF,0xFF,
+  0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x3C,0x03,0xFF,0xFF,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x03,0xFF,0xFF,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x07,0xFF,0xFF 
+};
+

+ 38 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/bitmap_flags.h

@@ -0,0 +1,38 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016, 2017 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _BITMAP_FLAGS_H_
+#define _BITMAP_FLAGS_H_
+
+#include "macros.h"
+
+/**
+ * These support functions allow the use of large bit arrays of flags that take very
+ * little RAM. Currently they are limited to being 16x16 in size. Changing the declaration
+ * to unsigned long will allow us to go to 32x32 if higher resolution meshes are needed
+ * in the future.
+ */
+FORCE_INLINE void bitmap_clear(uint16_t bits[16], const uint8_t x, const uint8_t y) { CBI(bits[y], x); }
+FORCE_INLINE void bitmap_set(uint16_t bits[16], const uint8_t x, const uint8_t y) { SBI(bits[y], x); }
+FORCE_INLINE bool is_bitmap_set(uint16_t bits[16], const uint8_t x, const uint8_t y) { return TEST(bits[y], x); }
+
+#endif // _BITMAP_FLAGS_H_

+ 46 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/blinkm.cpp

@@ -0,0 +1,46 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * blinkm.cpp - Control a BlinkM over i2c
+ */
+
+#include "MarlinConfig.h"
+
+#if ENABLED(BLINKM)
+
+#include "blinkm.h"
+#include "leds.h"
+#include <Wire.h>
+
+void blinkm_set_led_color(const LEDColor &color) {
+  Wire.begin();
+  Wire.beginTransmission(0x09);
+  Wire.write('o');                    //to disable ongoing script, only needs to be used once
+  Wire.write('n');
+  Wire.write(color.r);
+  Wire.write(color.g);
+  Wire.write(color.b);
+  Wire.endTransmission();
+}
+
+#endif // BLINKM

+ 35 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/blinkm.h

@@ -0,0 +1,35 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * blinkm.h - Control a BlinkM over i2c
+ */
+
+#ifndef _BLINKM_H_
+#define _BLINKM_H_
+
+struct LEDColor;
+typedef LEDColor LEDColor;
+
+void blinkm_set_led_color(const LEDColor &color);
+
+#endif // _BLINKM_H_

+ 161 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/boards.h

@@ -0,0 +1,161 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BOARDS_H
+#define BOARDS_H
+
+#define BOARD_UNKNOWN -1
+
+//
+// RAMPS 1.3 / 1.4 - ATmega1280, ATmega2560
+//
+
+#define BOARD_RAMPS_OLD         3     // MEGA/RAMPS up to 1.2
+
+#define BOARD_RAMPS_13_EFB      33    // RAMPS 1.3 (Power outputs: Hotend, Fan, Bed)
+#define BOARD_RAMPS_13_EEB      34    // RAMPS 1.3 (Power outputs: Hotend0, Hotend1, Bed)
+#define BOARD_RAMPS_13_EFF      35    // RAMPS 1.3 (Power outputs: Hotend, Fan0, Fan1)
+#define BOARD_RAMPS_13_EEF      36    // RAMPS 1.3 (Power outputs: Hotend0, Hotend1, Fan)
+#define BOARD_RAMPS_13_SF       38    // RAMPS 1.3 (Power outputs: Spindle, Controller Fan)
+
+#define BOARD_RAMPS_14_EFB      43    // RAMPS 1.4 (Power outputs: Hotend, Fan, Bed)
+#define BOARD_RAMPS_14_EEB      44    // RAMPS 1.4 (Power outputs: Hotend0, Hotend1, Bed)
+#define BOARD_RAMPS_14_EFF      45    // RAMPS 1.4 (Power outputs: Hotend, Fan0, Fan1)
+#define BOARD_RAMPS_14_EEF      46    // RAMPS 1.4 (Power outputs: Hotend0, Hotend1, Fan)
+#define BOARD_RAMPS_14_SF       48    // RAMPS 1.4 (Power outputs: Spindle, Controller Fan)
+
+#define BOARD_RAMPS_PLUS_EFB   143    // RAMPS Plus 3DYMY (Power outputs: Hotend, Fan, Bed)
+#define BOARD_RAMPS_PLUS_EEB   144    // RAMPS Plus 3DYMY (Power outputs: Hotend0, Hotend1, Bed)
+#define BOARD_RAMPS_PLUS_EFF   145    // RAMPS Plus 3DYMY (Power outputs: Hotend, Fan0, Fan1)
+#define BOARD_RAMPS_PLUS_EEF   146    // RAMPS Plus 3DYMY (Power outputs: Hotend0, Hotend1, Fan)
+#define BOARD_RAMPS_PLUS_SF    148    // RAMPS Plus 3DYMY (Power outputs: Spindle, Controller Fan)
+
+//
+// RAMPS Derivatives - ATmega1280, ATmega2560
+//
+
+#define BOARD_3DRAG             77    // 3Drag Controller
+#define BOARD_K8200             78    // Velleman K8200 Controller (derived from 3Drag Controller)
+#define BOARD_K8400             79    // Velleman K8400 Controller (derived from 3Drag Controller)
+#define BOARD_BAM_DICE          401   // 2PrintBeta BAM&DICE with STK drivers
+#define BOARD_BAM_DICE_DUE      402   // 2PrintBeta BAM&DICE Due with STK drivers
+#define BOARD_MKS_BASE          40    // MKS BASE v1.0
+#define BOARD_MKS_BASE_15       405   // MKS v1.5 with Allegro A4982 stepper drivers
+#define BOARD_MKS_BASE_HEROIC   41    // MKS BASE 1.0 with Heroic HR4982 stepper drivers
+#define BOARD_MKS_GEN_13        47    // MKS GEN v1.3 or 1.4
+#define BOARD_MKS_GEN_L         53    // MKS GEN L
+#define BOARD_ZRIB_V20          504   // zrib V2.0 control board (Chinese knock off RAMPS replica)
+#define BOARD_FELIX2            37    // Felix 2.0+ Electronics Board (RAMPS like)
+#define BOARD_RIGIDBOARD        42    // Invent-A-Part RigidBoard
+#define BOARD_RIGIDBOARD_V2     52    // Invent-A-Part RigidBoard V2
+#define BOARD_SAINSMART_2IN1    49    // Sainsmart 2-in-1 board
+#define BOARD_ULTIMAKER         7     // Ultimaker
+#define BOARD_ULTIMAKER_OLD     71    // Ultimaker (Older electronics. Pre 1.5.4. This is rare)
+#define BOARD_AZTEEG_X3         67    // Azteeg X3
+#define BOARD_AZTEEG_X3_PRO     68    // Azteeg X3 Pro
+#define BOARD_ULTIMAIN_2        72    // Ultimainboard 2.x (Uses TEMP_SENSOR 20)
+#define BOARD_RUMBA             80    // Rumba
+#define BOARD_BQ_ZUM_MEGA_3D    503   // bq ZUM Mega 3D
+#define BOARD_MAKEBOARD_MINI    431   // MakeBoard Mini v2.1.2 is a control board sold by MicroMake
+#define BOARD_TRIGORILLA_13     343   // TriGorilla Anycubic version 1.3 based on RAMPS EFB
+#define BOARD_TRIGORILLA_14     443   // TriGorilla Anycubic version 1.4 based on RAMPS EFB
+#define BOARD_RAMPS_ENDER_4     243   // Creality: Ender-4, CR-8
+
+//
+// Other ATmega1280, ATmega2560
+//
+
+#define BOARD_CNCONTROLS_11     111   // Cartesio CN Controls V11
+#define BOARD_CNCONTROLS_12     112   // Cartesio CN Controls V12
+#define BOARD_CHEAPTRONIC       2     // Cheaptronic v1.0
+#define BOARD_CHEAPTRONIC_V2    21    // Cheaptronic v2.0
+#define BOARD_MIGHTYBOARD_REVE  200   // Makerbot Mightyboard Revision E
+#define BOARD_MEGATRONICS       70    // Megatronics
+#define BOARD_MEGATRONICS_2     701   // Megatronics v2.0
+#define BOARD_MEGATRONICS_3     703   // Megatronics v3.0
+#define BOARD_MEGATRONICS_31    704   // Megatronics v3.1
+#define BOARD_RAMBO             301   // Rambo
+#define BOARD_MINIRAMBO         302   // Mini-Rambo
+#define BOARD_MINIRAMBO_10A     303   // Mini-Rambo 1.0a
+#define BOARD_EINSY_RAMBO       304   // Einsy Rambo
+#define BOARD_EINSY_RETRO       305   // Einsy Retro
+#define BOARD_ELEFU_3           21    // Elefu Ra Board (v3)
+#define BOARD_LEAPFROG          999   // Leapfrog
+#define BOARD_MEGACONTROLLER    310   // Mega controller
+#define BOARD_SCOOVO_X9H        321   // abee Scoovo X9H
+#define BOARD_GT2560_REV_A      74    // Geeetech GT2560 Rev. A
+#define BOARD_GT2560_REV_A_PLUS 75    // Geeetech GT2560 Rev. A+ (with auto level probe)
+
+//
+// ATmega1281, ATmega2561
+//
+
+#define BOARD_MINITRONICS       702   // Minitronics v1.0/1.1
+#define BOARD_SILVER_GATE       25    // Silvergate v1.0
+
+//
+// Sanguinololu and Derivatives - ATmega644P, ATmega1284P
+//
+
+#define BOARD_SANGUINOLOLU_11   6     // Sanguinololu < 1.2
+#define BOARD_SANGUINOLOLU_12   62    // Sanguinololu 1.2 and above
+#define BOARD_MELZI             63    // Melzi
+#define BOARD_MELZI_MAKR3D      66    // Melzi with ATmega1284 (MaKr3d version)
+#define BOARD_MELZI_CREALITY    89    // Melzi Creality3D board (for CR-10 etc)
+#define BOARD_MELZI_MALYAN      92    // Melzi Malyan M150 board
+#define BOARD_MELZI_TRONXY      505   // Tronxy X5S
+#define BOARD_STB_11            64    // STB V1.1
+#define BOARD_AZTEEG_X1         65    // Azteeg X1
+#define BOARD_ANET_10           69    // Anet 1.0 (Melzi clone)
+
+//
+// Other ATmega644P, ATmega644, ATmega1284P
+//
+
+#define BOARD_GEN3_MONOLITHIC   22    // Gen3 Monolithic Electronics
+#define BOARD_GEN3_PLUS         9     // Gen3+
+#define BOARD_GEN6              5     // Gen6
+#define BOARD_GEN6_DELUXE       51    // Gen6 deluxe
+#define BOARD_GEN7_CUSTOM       10    // Gen7 custom (Alfons3 Version) "https://github.com/Alfons3/Generation_7_Electronics"
+#define BOARD_GEN7_12           11    // Gen7 v1.1, v1.2
+#define BOARD_GEN7_13           12    // Gen7 v1.3
+#define BOARD_GEN7_14           13    // Gen7 v1.4
+#define BOARD_OMCA_A            90    // Alpha OMCA board
+#define BOARD_OMCA              91    // Final OMCA board
+#define BOARD_SETHI             20    // Sethi 3D_1
+
+//
+// Teensyduino - AT90USB1286, AT90USB1286P
+//
+
+#define BOARD_TEENSYLU          8     // Teensylu
+#define BOARD_PRINTRBOARD       81    // Printrboard (AT90USB1286)
+#define BOARD_PRINTRBOARD_REVF  811   // Printrboard Revision F (AT90USB1286)
+#define BOARD_BRAINWAVE         82    // Brainwave (AT90USB646)
+#define BOARD_BRAINWAVE_PRO     85    // Brainwave Pro (AT90USB1286)
+#define BOARD_SAV_MKI           83    // SAV Mk-I (AT90USB1286)
+#define BOARD_TEENSY2           84    // Teensy++2.0 (AT90USB1286) - CLI compile: HARDWARE_MOTHERBOARD=84  make
+#define BOARD_5DPRINT           88    // 5DPrint D8 Driver Board
+
+#define MB(board) (defined(BOARD_##board) && MOTHERBOARD==BOARD_##board)
+
+#endif // __BOARDS_H

+ 146 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/buzzer.h

@@ -0,0 +1,146 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __BUZZER_H__
+#define __BUZZER_H__
+
+#include "types.h"
+#include "fastio.h"
+#include "circularqueue.h"
+#include "temperature.h"
+
+#include "MarlinConfig.h"
+
+#define TONE_QUEUE_LENGTH 4
+
+/**
+ * @brief Tone structure
+ * @details Simple abstraction of a tone based on a duration and a frequency.
+ */
+struct tone_t {
+  uint16_t duration;
+  uint16_t frequency;
+};
+
+/**
+ * @brief Buzzer class
+ */
+class Buzzer {
+  private:
+    struct state_t {
+      tone_t   tone;
+      uint32_t endtime;
+    } state;
+
+  protected:
+    CircularQueue<tone_t, TONE_QUEUE_LENGTH> buffer;
+
+    /**
+     * @brief Inverts the sate of a digital PIN
+     * @details This will invert the current state of an digital IO pin.
+     */
+    void invert() {
+      TOGGLE(BEEPER_PIN);
+    }
+
+    /**
+     * @brief Turn off a digital PIN
+     * @details Alias of digitalWrite(PIN, LOW) using FastIO
+     */
+    void off() {
+      WRITE(BEEPER_PIN, LOW);
+    }
+
+    /**
+     * @brief Turn on a digital PIN
+     * @details Alias of digitalWrite(PIN, HIGH) using FastIO
+     */
+    void on() {
+      WRITE(BEEPER_PIN, HIGH);
+    }
+
+    /**
+     * @brief Resets the state of the class
+     * @details Brings the class state to a known one.
+     */
+    void reset() {
+      this->off();
+      this->state.endtime = 0;
+    }
+
+  public:
+    /**
+     * @brief Class constructor
+     */
+    Buzzer() {
+      SET_OUTPUT(BEEPER_PIN);
+      this->reset();
+    }
+
+    /**
+     * @brief Add a tone to the queue
+     * @details Adds a tone_t structure to the ring buffer, will block IO if the
+     *          queue is full waiting for one slot to get available.
+     *
+     * @param duration Duration of the tone in milliseconds
+     * @param frequency Frequency of the tone in hertz
+     */
+    void tone(const uint16_t &duration, const uint16_t &frequency=0) {
+      while (buffer.isFull()) {
+        this->tick();
+        thermalManager.manage_heater();
+      }
+      tone_t tone = { duration, frequency };
+      this->buffer.enqueue(tone);
+    }
+
+    /**
+     * @brief Loop function
+     * @details This function should be called at loop, it will take care of
+     *          playing the tones in the queue.
+     */
+    virtual void tick() {
+      const millis_t now = millis();
+
+      if (!this->state.endtime) {
+        if (this->buffer.isEmpty()) return;
+
+        this->state.tone = this->buffer.dequeue();
+        this->state.endtime = now + this->state.tone.duration;
+
+        if (this->state.tone.frequency > 0) {
+          #if ENABLED(SPEAKER)
+            CRITICAL_SECTION_START;
+            ::tone(BEEPER_PIN, this->state.tone.frequency, this->state.tone.duration);
+            CRITICAL_SECTION_END;
+          #else
+            this->on();
+          #endif
+        }
+      }
+      else if (ELAPSED(now, this->state.endtime)) this->reset();
+    }
+};
+
+extern Buzzer buzzer;
+
+#endif

+ 987 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/cardreader.cpp

@@ -0,0 +1,987 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "MarlinConfig.h"
+
+#if ENABLED(SDSUPPORT)
+
+#include "cardreader.h"
+
+#include "ultralcd.h"
+#include "stepper.h"
+#include "language.h"
+#include "printcounter.h"
+
+#if ENABLED(POWER_LOSS_RECOVERY)
+  #include "power_loss_recovery.h"
+#endif
+
+CardReader::CardReader() {
+  #if ENABLED(SDCARD_SORT_ALPHA)
+    sort_count = 0;
+    #if ENABLED(SDSORT_GCODE)
+      sort_alpha = true;
+      sort_folders = FOLDER_SORTING;
+      //sort_reverse = false;
+    #endif
+  #endif
+  sdprinting = cardOK = saving = logging = false;
+  filesize = 0;
+  sdpos = 0;
+  file_subcall_ctr = 0;
+
+  workDirDepth = 0;
+  ZERO(workDirParents);
+
+  // Disable autostart until card is initialized
+  autostart_index = -1;
+
+  //power to SD reader
+  #if SDPOWER > -1
+    OUT_WRITE(SDPOWER, HIGH);
+  #endif
+}
+
+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;
+}
+
+/**
+ * Dive into a folder and recurse depth-first to perform a pre-set operation lsAction:
+ *   LS_Count       - Add +1 to nrFiles for every file within the parent
+ *   LS_GetFilename - Get the filename of the file indexed by nrFile_index
+ *   LS_SerialPrint - Print the full path and size of each file to serial output
+ */
+
+uint16_t nrFile_index;
+
+void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/) {
+  dir_t p;
+  uint8_t cnt = 0;
+
+  // Read the next entry from a directory
+  while (parent.readDir(&p, longFilename) > 0) {
+
+    // If the entry is a directory and the action is LS_SerialPrint
+    if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) {
+
+      // Get the short name for the item, which we know is a folder
+      char dosFilename[FILENAME_LENGTH];
+      createFilename(dosFilename, p);
+
+      // Allocate enough stack space for the full path to a folder, trailing slash, and nul
+      const bool prepend_is_empty = (!prepend || prepend[0] == '\0');
+      const int len = (prepend_is_empty ? 1 : strlen(prepend)) + strlen(dosFilename) + 1 + 1;
+      char path[len];
+
+      // Append the FOLDERNAME12/ to the passed string.
+      // It contains the full path to the "parent" argument.
+      // We now have the full path to the item in this folder.
+      strcpy(path, prepend_is_empty ? "/" : prepend); // root slash if prepend is empty
+      strcat(path, dosFilename); // FILENAME_LENGTH-1 characters maximum
+      strcat(path, "/");       // 1 character
+
+      // Serial.print(path);
+
+      // Get a new directory object using the full path
+      // and dive recursively into it.
+      SdFile dir;
+      if (!dir.open(&parent, dosFilename, O_READ)) {
+        if (lsAction == LS_SerialPrint) {
+          SERIAL_ECHO_START();
+          SERIAL_ECHOPGM(MSG_SD_CANT_OPEN_SUBDIR);
+          SERIAL_ECHOLN(dosFilename);
+        }
+      }
+      lsDive(path, dir);
+      // close() is done automatically by destructor of SdFile
+    }
+    else {
+      uint8_t pn0 = p.name[0];
+      if (pn0 == DIR_NAME_FREE) break;
+      if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue;
+      if (longFilename[0] == '.') continue;
+
+      if (!DIR_IS_FILE_OR_SUBDIR(&p) || (p.attributes & DIR_ATT_HIDDEN)) continue;
+
+      filenameIsDir = DIR_IS_SUBDIR(&p);
+
+      if (!filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue;
+
+      switch (lsAction) {  // 1 based file count
+        case LS_Count:
+          nrFiles++;
+          break;
+
+        case LS_SerialPrint:
+          createFilename(filename, p);
+          if (prepend) SERIAL_PROTOCOL(prepend);
+          SERIAL_PROTOCOL(filename);
+          SERIAL_PROTOCOLCHAR(' ');
+          SERIAL_PROTOCOLLN(p.fileSize);
+          break;
+
+        case LS_GetFilename:
+          createFilename(filename, p);
+          if (match != NULL) {
+            if (strcasecmp(match, filename) == 0) return;
+          }
+          else if (cnt == nrFile_index) return;  // 0 based index
+          cnt++;
+          break;
+      }
+
+    }
+  } // while readDir
+}
+
+void CardReader::ls() {
+  lsAction = LS_SerialPrint;
+  root.rewind();
+  lsDive(NULL, root);
+}
+
+#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
+
+  /**
+   * Get a long pretty path based on a DOS 8.3 path
+   */
+  void CardReader::printLongPath(char *path) {
+    lsAction = LS_GetFilename;
+
+    int i, pathLen = strlen(path);
+
+    // SERIAL_ECHOPGM("Full Path: "); SERIAL_ECHOLN(path);
+
+    // Zero out slashes to make segments
+    for (i = 0; i < pathLen; i++) if (path[i] == '/') path[i] = '\0';
+
+    SdFile diveDir = root; // start from the root for segment 1
+    for (i = 0; i < pathLen;) {
+
+      if (path[i] == '\0') i++; // move past a single nul
+
+      char *segment = &path[i]; // The segment after most slashes
+
+      // If a segment is empty (extra-slash) then exit
+      if (!*segment) break;
+
+      // Go to the next segment
+      while (path[++i]) { }
+
+      // SERIAL_ECHOPGM("Looking for segment: "); SERIAL_ECHOLN(segment);
+
+      // Find the item, setting the long filename
+      diveDir.rewind();
+      lsDive(NULL, diveDir, segment);
+
+      // Print /LongNamePart to serial output
+      SERIAL_PROTOCOLCHAR('/');
+      SERIAL_PROTOCOL(longFilename[0] ? longFilename : "???");
+
+      // If the filename was printed then that's it
+      if (!filenameIsDir) break;
+
+      // SERIAL_ECHOPGM("Opening dir: "); SERIAL_ECHOLN(segment);
+
+      // Open the sub-item as the new dive parent
+      SdFile dir;
+      if (!dir.open(&diveDir, segment, O_READ)) {
+        SERIAL_EOL();
+        SERIAL_ECHO_START();
+        SERIAL_ECHOPGM(MSG_SD_CANT_OPEN_SUBDIR);
+        SERIAL_ECHO(segment);
+        break;
+      }
+
+      diveDir.close();
+      diveDir = dir;
+
+    } // while i<pathLen
+
+    SERIAL_EOL();
+  }
+
+#endif // LONG_FILENAME_HOST_SUPPORT
+
+/**
+ * Echo the DOS 8.3 filename (and long filename, if any)
+ */
+void CardReader::printFilename() {
+  if (file.isOpen()) {
+    char dosFilename[FILENAME_LENGTH];
+    file.getFilename(dosFilename);
+    SERIAL_ECHO(dosFilename);
+    #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
+      getfilename(0, dosFilename);
+      if (longFilename[0]) {
+        SERIAL_ECHO(' ');
+        SERIAL_ECHO(longFilename);
+      }
+    #endif
+  }
+  else
+    SERIAL_ECHOPGM("(no file)");
+
+  SERIAL_EOL();
+}
+
+void CardReader::initsd() {
+  cardOK = false;
+  if (root.isOpen()) root.close();
+
+  #ifndef SPI_SPEED
+    #define SPI_SPEED SPI_FULL_SPEED
+  #endif
+
+  if (!sd2card.init(SPI_SPEED, SDSS)
+    #if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
+      && !sd2card.init(SPI_SPEED, LCD_SDSS)
+    #endif
+  ) {
+    //if (!sd2card.init(SPI_HALF_SPEED,SDSS))
+    SERIAL_ECHO_START();
+    SERIAL_ECHOLNPGM(MSG_SD_INIT_FAIL);
+  }
+  else if (!volume.init(&sd2card)) {
+    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);
+  }
+  setroot();
+}
+
+void CardReader::release() {
+  sdprinting = false;
+  cardOK = false;
+}
+
+void CardReader::openAndPrintFile(const char *name) {
+  char cmd[4 + strlen(name) + 1]; // Room for "M23 ", filename, and null
+  sprintf_P(cmd, PSTR("M23 %s"), name);
+  for (char *c = &cmd[4]; *c; c++) *c = tolower(*c);
+  enqueue_and_echo_command_now(cmd);
+  enqueue_and_echo_commands_P(PSTR("M24"));
+}
+
+void CardReader::startFileprint() {
+  if (cardOK) {
+    sdprinting = true;
+    #if SD_RESORT
+      flush_presort();
+    #endif
+  }
+}
+
+void CardReader::stopSDPrint(
+  #if SD_RESORT
+    const bool re_sort/*=false*/
+  #endif
+) {
+  #if ENABLED(ADVANCED_PAUSE_FEATURE)
+    did_pause_print = 0;
+  #endif
+  sdprinting = false;
+  if (isFileOpen()) file.close();
+  #if SD_RESORT
+    if (re_sort) presort();
+  #endif
+}
+
+void CardReader::openLogFile(char * const path) {
+  logging = true;
+  openFile(path, false);
+}
+
+void appendAtom(SdFile &file, char *& dst, uint8_t &cnt) {
+  file.getFilename(dst);
+  while (*dst && cnt < MAXPATHNAMELENGTH) { dst++; cnt++; }
+  if (cnt < MAXPATHNAMELENGTH) { *dst = '/'; dst++; cnt++; }
+}
+
+void CardReader::getAbsFilename(char *t) {
+  *t++ = '/';                                               // Root folder
+  uint8_t cnt = 1;
+
+  for (uint8_t i = 0; i < workDirDepth; i++)                // Loop to current work dir
+    appendAtom(workDirParents[i], t, cnt);
+
+  if (cnt < MAXPATHNAMELENGTH - (FILENAME_LENGTH)) {
+    appendAtom(file, t, cnt);
+    --t;
+  }
+  *t = '\0';
+}
+
+void CardReader::openFile(char * const path, const bool read, const bool subcall/*=false*/) {
+
+  if (!cardOK) return;
+
+  uint8_t doing = 0;
+  if (isFileOpen()) {                     // Replacing current file or doing a subroutine
+    if (subcall) {
+      if (file_subcall_ctr > SD_PROCEDURE_DEPTH - 1) {
+        SERIAL_ERROR_START();
+        SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
+        SERIAL_ERRORLN((int)SD_PROCEDURE_DEPTH);
+        kill(PSTR(MSG_KILLED));
+        return;
+      }
+
+      // Store current filename (based on workDirParents) and position
+      getAbsFilename(proc_filenames[file_subcall_ctr]);
+      filespos[file_subcall_ctr] = sdpos;
+
+      SERIAL_ECHO_START();
+      SERIAL_ECHOPAIR("SUBROUTINE CALL target:\"", path);
+      SERIAL_ECHOPAIR("\" parent:\"", proc_filenames[file_subcall_ctr]);
+      SERIAL_ECHOLNPAIR("\" pos", sdpos);
+      file_subcall_ctr++;
+    }
+    else
+      doing = 1;
+  }
+  else if (subcall) {     // Returning from a subcall?
+    SERIAL_ECHO_START();
+    SERIAL_ECHOLNPGM("END SUBROUTINE");
+  }
+  else {                  // Opening fresh file
+    doing = 2;
+    file_subcall_ctr = 0; // Reset procedure depth in case user cancels print while in procedure
+  }
+
+  if (doing) {
+    SERIAL_ECHO_START();
+    SERIAL_ECHOPGM("Now ");
+    serialprintPGM(doing == 1 ? PSTR("doing") : PSTR("fresh"));
+    SERIAL_ECHOLNPAIR(" file: ", path);
+  }
+
+  stopSDPrint();
+
+  SdFile *curDir;
+  const char * const fname = diveToFile(curDir, path, false);
+  if (!fname) return;
+
+  if (read) {
+    if (file.open(curDir, fname, O_READ)) {
+      filesize = file.fileSize();
+      sdpos = 0;
+      SERIAL_PROTOCOLPAIR(MSG_SD_FILE_OPENED, fname);
+      SERIAL_PROTOCOLLNPAIR(MSG_SD_SIZE, filesize);
+      SERIAL_PROTOCOLLNPGM(MSG_SD_FILE_SELECTED);
+
+      getfilename(0, fname);
+      lcd_setstatus(longFilename[0] ? longFilename : fname);
+      //if (longFilename[0]) {
+      //  SERIAL_PROTOCOLPAIR(MSG_SD_FILE_LONG_NAME, longFilename);
+      //}
+    }
+    else {
+      SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, fname);
+      SERIAL_PROTOCOLCHAR('.');
+      SERIAL_EOL();
+    }
+  }
+  else { //write
+    if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) {
+      SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, fname);
+      SERIAL_PROTOCOLCHAR('.');
+      SERIAL_EOL();
+    }
+    else {
+      saving = true;
+      SERIAL_PROTOCOLLNPAIR(MSG_SD_WRITE_TO_FILE, path);
+      lcd_setstatus(fname);
+    }
+  }
+}
+
+void CardReader::removeFile(const char * const name) {
+  if (!cardOK) return;
+
+  stopSDPrint();
+
+  SdFile *curDir;
+  const char * const fname = diveToFile(curDir, name, false);
+  if (!fname) return;
+
+  if (file.remove(curDir, fname)) {
+    SERIAL_PROTOCOLPGM("File deleted:");
+    SERIAL_PROTOCOLLN(fname);
+    sdpos = 0;
+    #if ENABLED(SDCARD_SORT_ALPHA)
+      presort();
+    #endif
+  }
+  else {
+    SERIAL_PROTOCOLPGM("Deletion failed, File: ");
+    SERIAL_PROTOCOL(fname);
+    SERIAL_PROTOCOLCHAR('.');
+  }
+}
+
+void CardReader::getStatus() {
+  if (cardOK && sdprinting) {
+    SERIAL_PROTOCOLPGM(MSG_SD_PRINTING_BYTE);
+    SERIAL_PROTOCOL(sdpos);
+    SERIAL_PROTOCOLCHAR('/');
+    SERIAL_PROTOCOLLN(filesize);
+  }
+  else
+    SERIAL_PROTOCOLLNPGM(MSG_SD_NOT_PRINTING);
+}
+
+void CardReader::write_command(char *buf) {
+  char* begin = buf;
+  char* npos = NULL;
+  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);
+  }
+}
+
+//
+// Run the next autostart file. Called:
+// - On boot after successful card init
+// - After finishing the previous autostart file
+// - From the LCD command to run the autostart file
+//
+
+void CardReader::checkautostart() {
+
+  if (autostart_index < 0 || sdprinting) return;
+
+  if (!cardOK) initsd();
+
+  if (cardOK
+    #if ENABLED(POWER_LOSS_RECOVERY)
+      && !jobRecoverFileExists() // Don't run auto#.g when a resume file exists
+    #endif
+  ) {
+    char autoname[10];
+    sprintf_P(autoname, PSTR("auto%i.g"), int(autostart_index));
+    dir_t p;
+    root.rewind();
+    while (root.readDir(&p, NULL) > 0) {
+      for (int8_t i = (int8_t)strlen((char*)p.name); i--;) p.name[i] = tolower(p.name[i]);
+      if (p.name[9] != '~' && strncmp((char*)p.name, autoname, 5) == 0) {
+        openAndPrintFile(autoname);
+        autostart_index++;
+        return;
+      }
+    }
+  }
+  autostart_index = -1;
+}
+
+void CardReader::beginautostart() {
+  autostart_index = 0;
+  setroot();
+}
+
+void CardReader::closefile(const bool store_location) {
+  file.sync();
+  file.close();
+  saving = logging = false;
+
+  if (store_location) {
+    //future: store printer state, filename and position for continuing a stopped print
+    // so one can unplug the printer and continue printing the next day.
+  }
+}
+
+/**
+ * Get the name of a file in the current directory by index
+ * with optional name to match.
+ */
+void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/) {
+  #if ENABLED(SDSORT_CACHE_NAMES)
+    if (match != NULL) {
+      while (nr < sort_count) {
+        if (strcasecmp(match, sortshort[nr]) == 0) break;
+        nr++;
+      }
+    }
+    if (nr < sort_count) {
+      strcpy(filename, sortshort[nr]);
+      strcpy(longFilename, sortnames[nr]);
+      filenameIsDir = TEST(isDir[nr>>3], nr & 0x07);
+      return;
+    }
+  #endif // SDSORT_CACHE_NAMES
+  lsAction = LS_GetFilename;
+  nrFile_index = nr;
+  workDir.rewind();
+  lsDive(NULL, workDir, match);
+}
+
+uint16_t CardReader::getnrfilenames() {
+  lsAction = LS_Count;
+  nrFiles = 0;
+  workDir.rewind();
+  lsDive(NULL, workDir);
+  //SERIAL_ECHOLN(nrFiles);
+  return nrFiles;
+}
+
+/**
+ * Dive to the given file path, with optional echo.
+ * On exit set curDir and return the name part of the path.
+ * A NULL result indicates an unrecoverable error.
+ */
+const char* CardReader::diveToFile(SdFile*& curDir, const char * const path, const bool echo) {
+  SdFile myDir;
+  if (path[0] != '/') { curDir = &workDir; return path; }
+
+  curDir = &root;
+  const char *dirname_start = &path[1];
+  while (dirname_start) {
+    char * const dirname_end = strchr(dirname_start, '/');
+    if (dirname_end <= dirname_start) break;
+    const uint8_t len = dirname_end - dirname_start;
+    char dosSubdirname[len + 1];
+    strncpy(dosSubdirname, dirname_start, len);
+    dosSubdirname[len] = 0;
+
+    if (echo) SERIAL_ECHOLN(dosSubdirname);
+
+    if (!myDir.open(curDir, dosSubdirname, O_READ)) {
+      SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, dosSubdirname);
+      SERIAL_PROTOCOLCHAR('.');
+      SERIAL_EOL();
+      return NULL;
+    }
+    curDir = &myDir;
+    dirname_start = dirname_end + 1;
+  }
+  return dirname_start;
+}
+
+void CardReader::chdir(const char * relpath) {
+  SdFile newDir;
+  SdFile *parent = workDir.isOpen() ? &workDir : &root;
+
+  if (newDir.open(parent, relpath, O_READ)) {
+    workDir = newDir;
+    if (workDirDepth < MAX_DIR_DEPTH)
+      workDirParents[workDirDepth++] = workDir;
+    #if ENABLED(SDCARD_SORT_ALPHA)
+      presort();
+    #endif
+  }
+  else {
+    SERIAL_ECHO_START();
+    SERIAL_ECHOPGM(MSG_SD_CANT_ENTER_SUBDIR);
+    SERIAL_ECHOLN(relpath);
+  }
+}
+
+int8_t CardReader::updir() {
+  if (workDirDepth > 0) {                                               // At least 1 dir has been saved
+    workDir = --workDirDepth ? workDirParents[workDirDepth - 1] : root; // Use parent, or root if none
+    #if ENABLED(SDCARD_SORT_ALPHA)
+      presort();
+    #endif
+  }
+  return workDirDepth;
+}
+
+void CardReader::setroot() {
+  /*if (!workDir.openRoot(&volume)) {
+    SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
+  }*/
+  workDir = root;
+  #if ENABLED(SDCARD_SORT_ALPHA)
+    presort();
+  #endif
+}
+
+#if ENABLED(SDCARD_SORT_ALPHA)
+
+  /**
+   * Get the name of a file in the current directory by sort-index
+   */
+  void CardReader::getfilename_sorted(const uint16_t nr) {
+    getfilename(
+      #if ENABLED(SDSORT_GCODE)
+        sort_alpha &&
+      #endif
+      (nr < sort_count) ? sort_order[nr] : nr
+    );
+  }
+
+  /**
+   * Read all the files and produce a sort key
+   *
+   * We can do this in 3 ways...
+   *  - Minimal RAM: Read two filenames at a time sorting along...
+   *  - Some RAM: Buffer the directory just for this sort
+   *  - Most RAM: Buffer the directory and return filenames from RAM
+   */
+  void CardReader::presort() {
+
+    // Throw away old sort index
+    flush_presort();
+
+    // Sorting may be turned off
+    #if ENABLED(SDSORT_GCODE)
+      if (!sort_alpha) return;
+    #endif
+
+    // If there are files, sort up to the limit
+    uint16_t fileCnt = getnrfilenames();
+    if (fileCnt > 0) {
+
+      // Never sort more than the max allowed
+      // If you use folders to organize, 20 may be enough
+      if (fileCnt > SDSORT_LIMIT) fileCnt = SDSORT_LIMIT;
+
+      // Sort order is always needed. May be static or dynamic.
+      #if ENABLED(SDSORT_DYNAMIC_RAM)
+        sort_order = new uint8_t[fileCnt];
+      #endif
+
+      // Use RAM to store the entire directory during pre-sort.
+      // SDSORT_LIMIT should be set to prevent over-allocation.
+      #if ENABLED(SDSORT_USES_RAM)
+
+        // If using dynamic ram for names, allocate on the heap.
+        #if ENABLED(SDSORT_CACHE_NAMES)
+          #if ENABLED(SDSORT_DYNAMIC_RAM)
+            sortshort = new char*[fileCnt];
+            sortnames = new char*[fileCnt];
+          #endif
+        #elif ENABLED(SDSORT_USES_STACK)
+          char sortnames[fileCnt][SORTED_LONGNAME_MAXLEN];
+        #endif
+
+        // Folder sorting needs 1 bit per entry for flags.
+        #if HAS_FOLDER_SORTING
+          #if ENABLED(SDSORT_DYNAMIC_RAM)
+            isDir = new uint8_t[(fileCnt + 7) >> 3];
+          #elif ENABLED(SDSORT_USES_STACK)
+            uint8_t isDir[(fileCnt + 7) >> 3];
+          #endif
+        #endif
+
+      #else // !SDSORT_USES_RAM
+
+        // By default re-read the names from SD for every compare
+        // retaining only two filenames at a time. This is very
+        // slow but is safest and uses minimal RAM.
+        char name1[LONG_FILENAME_LENGTH + 1];
+
+      #endif
+
+      if (fileCnt > 1) {
+
+        // Init sort order.
+        for (uint16_t i = 0; i < fileCnt; i++) {
+          sort_order[i] = i;
+          // If using RAM then read all filenames now.
+          #if ENABLED(SDSORT_USES_RAM)
+            getfilename(i);
+            #if ENABLED(SDSORT_DYNAMIC_RAM)
+              // Use dynamic method to copy long filename
+              sortnames[i] = strdup(longest_filename());
+              #if ENABLED(SDSORT_CACHE_NAMES)
+                // When caching also store the short name, since
+                // we're replacing the getfilename() behavior.
+                sortshort[i] = strdup(filename);
+              #endif
+            #else
+              // Copy filenames into the static array
+              #if SORTED_LONGNAME_MAXLEN != LONG_FILENAME_LENGTH
+                strncpy(sortnames[i], longest_filename(), SORTED_LONGNAME_MAXLEN);
+                sortnames[i][SORTED_LONGNAME_MAXLEN - 1] = '\0';
+              #else
+                strncpy(sortnames[i], longest_filename(), SORTED_LONGNAME_MAXLEN);
+              #endif
+              #if ENABLED(SDSORT_CACHE_NAMES)
+                strcpy(sortshort[i], filename);
+              #endif
+            #endif
+            // char out[30];
+            // sprintf_P(out, PSTR("---- %i %s %s"), i, filenameIsDir ? "D" : " ", sortnames[i]);
+            // SERIAL_ECHOLN(out);
+            #if HAS_FOLDER_SORTING
+              const uint16_t bit = i & 0x07, ind = i >> 3;
+              if (bit == 0) isDir[ind] = 0x00;
+              if (filenameIsDir) isDir[ind] |= _BV(bit);
+            #endif
+          #endif
+        }
+
+        // Bubble Sort
+        for (uint16_t i = fileCnt; --i;) {
+          bool didSwap = false;
+          for (uint16_t j = 0; j < i; ++j) {
+            const uint16_t o1 = sort_order[j], o2 = sort_order[j + 1];
+
+            // Compare names from the array or just the two buffered names
+            #if ENABLED(SDSORT_USES_RAM)
+              #define _SORT_CMP_NODIR() (strcasecmp(sortnames[o1], sortnames[o2]) > 0)
+            #else
+              #define _SORT_CMP_NODIR() (strcasecmp(name1, name2) > 0)
+            #endif
+
+            #if HAS_FOLDER_SORTING
+              #if ENABLED(SDSORT_USES_RAM)
+                // Folder sorting needs an index and bit to test for folder-ness.
+                const uint8_t ind1 = o1 >> 3, bit1 = o1 & 0x07,
+                              ind2 = o2 >> 3, bit2 = o2 & 0x07;
+                #define _SORT_CMP_DIR(fs) \
+                  (((isDir[ind1] & _BV(bit1)) != 0) == ((isDir[ind2] & _BV(bit2)) != 0) \
+                    ? _SORT_CMP_NODIR() \
+                    : (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
+              #else
+                #define _SORT_CMP_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1))
+              #endif
+            #endif
+
+            // The most economical method reads names as-needed
+            // throughout the loop. Slow if there are many.
+            #if DISABLED(SDSORT_USES_RAM)
+              getfilename(o1);
+              strcpy(name1, longest_filename()); // save (or getfilename below will trounce it)
+              #if HAS_FOLDER_SORTING
+                bool dir1 = filenameIsDir;
+              #endif
+              getfilename(o2);
+              char *name2 = longest_filename(); // use the string in-place
+            #endif // !SDSORT_USES_RAM
+
+            // Sort the current pair according to settings.
+            if (
+              #if HAS_FOLDER_SORTING
+                #if ENABLED(SDSORT_GCODE)
+                  sort_folders ? _SORT_CMP_DIR(sort_folders) : _SORT_CMP_NODIR()
+                #else
+                  _SORT_CMP_DIR(FOLDER_SORTING)
+                #endif
+              #else
+                _SORT_CMP_NODIR()
+              #endif
+            ) {
+              sort_order[j] = o2;
+              sort_order[j + 1] = o1;
+              didSwap = true;
+            }
+          }
+          if (!didSwap) break;
+        }
+        // Using RAM but not keeping names around
+        #if ENABLED(SDSORT_USES_RAM) && DISABLED(SDSORT_CACHE_NAMES)
+          #if ENABLED(SDSORT_DYNAMIC_RAM)
+            for (uint16_t i = 0; i < fileCnt; ++i) free(sortnames[i]);
+            #if HAS_FOLDER_SORTING
+              free(isDir);
+            #endif
+          #endif
+        #endif
+      }
+      else {
+        sort_order[0] = 0;
+        #if ENABLED(SDSORT_USES_RAM) && ENABLED(SDSORT_CACHE_NAMES)
+          getfilename(0);
+          #if ENABLED(SDSORT_DYNAMIC_RAM)
+            sortnames = new char*[1];
+            sortnames[0] = strdup(longest_filename()); // malloc
+            #if ENABLED(SDSORT_CACHE_NAMES)
+              sortshort = new char*[1];
+              sortshort[0] = strdup(filename);       // malloc
+            #endif
+            isDir = new uint8_t[1];
+          #else
+            #if SORTED_LONGNAME_MAXLEN != LONG_FILENAME_LENGTH
+              strncpy(sortnames[0], longest_filename(), SORTED_LONGNAME_MAXLEN);
+              sortnames[0][SORTED_LONGNAME_MAXLEN - 1] = '\0';
+            #else
+              strncpy(sortnames[0], longest_filename(), SORTED_LONGNAME_MAXLEN);
+            #endif
+            #if ENABLED(SDSORT_CACHE_NAMES)
+              strcpy(sortshort[0], filename);
+            #endif
+          #endif
+          isDir[0] = filenameIsDir ? 0x01 : 0x00;
+        #endif
+      }
+
+      sort_count = fileCnt;
+    }
+  }
+
+  void CardReader::flush_presort() {
+    if (sort_count > 0) {
+      #if ENABLED(SDSORT_DYNAMIC_RAM)
+        delete sort_order;
+        #if ENABLED(SDSORT_CACHE_NAMES)
+          for (uint8_t i = 0; i < sort_count; ++i) {
+            free(sortshort[i]); // strdup
+            free(sortnames[i]); // strdup
+          }
+          delete sortshort;
+          delete sortnames;
+        #endif
+      #endif
+      sort_count = 0;
+    }
+  }
+
+#endif // SDCARD_SORT_ALPHA
+
+uint16_t CardReader::get_num_Files() {
+  return
+    #if ENABLED(SDCARD_SORT_ALPHA) && SDSORT_USES_RAM && SDSORT_CACHE_NAMES
+      nrFiles // no need to access the SD card for filenames
+    #else
+      getnrfilenames()
+    #endif
+  ;
+}
+
+void CardReader::printingHasFinished() {
+  planner.synchronize();
+  file.close();
+  if (file_subcall_ctr > 0) { // Heading up to a parent file that called current as a procedure.
+    file_subcall_ctr--;
+    openFile(proc_filenames[file_subcall_ctr], true, true);
+    setIndex(filespos[file_subcall_ctr]);
+    startFileprint();
+  }
+  else {
+    sdprinting = false;
+
+    #if ENABLED(POWER_LOSS_RECOVERY)
+      removeJobRecoveryFile();
+    #endif
+
+    #if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
+      planner.finish_and_disable();
+    #endif
+    print_job_timer.stop();
+    if (print_job_timer.duration() > 60)
+      enqueue_and_echo_commands_P(PSTR("M31"));
+    #if ENABLED(SDCARD_SORT_ALPHA)
+      presort();
+    #endif
+    #if ENABLED(ULTRA_LCD) && ENABLED(LCD_SET_PROGRESS_MANUALLY)
+      progress_bar_percent = 0;
+    #endif
+    #if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
+      lcd_reselect_last_file();
+    #endif
+  }
+}
+
+#if ENABLED(AUTO_REPORT_SD_STATUS)
+  uint8_t CardReader::auto_report_sd_interval = 0;
+  millis_t CardReader::next_sd_report_ms;
+
+  void CardReader::auto_report_sd_status() {
+    millis_t current_ms = millis();
+    if (auto_report_sd_interval && ELAPSED(current_ms, next_sd_report_ms)) {
+      next_sd_report_ms = current_ms + 1000UL * auto_report_sd_interval;
+      getStatus();
+    }
+  }
+#endif // AUTO_REPORT_SD_STATUS
+
+#if ENABLED(POWER_LOSS_RECOVERY)
+
+  char job_recovery_file_name[4] = "bin";
+
+  void CardReader::openJobRecoveryFile(const bool read) {
+    if (!cardOK) return;
+    if (jobRecoveryFile.isOpen()) return;
+    if (!jobRecoveryFile.open(&root, job_recovery_file_name, read ? O_READ : O_CREAT | O_WRITE | O_TRUNC | O_SYNC)) {
+      SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, job_recovery_file_name);
+      SERIAL_PROTOCOLCHAR('.');
+      SERIAL_EOL();
+    }
+    else if (!read)
+      SERIAL_PROTOCOLLNPAIR(MSG_SD_WRITE_TO_FILE, job_recovery_file_name);
+  }
+
+  void CardReader::closeJobRecoveryFile() { jobRecoveryFile.close(); }
+
+  bool CardReader::jobRecoverFileExists() {
+    const bool exists = jobRecoveryFile.open(&root, job_recovery_file_name, O_READ);
+    if (exists) jobRecoveryFile.close();
+    return exists;
+  }
+
+  int16_t CardReader::saveJobRecoveryInfo() {
+    jobRecoveryFile.seekSet(0);
+    const int16_t ret = jobRecoveryFile.write(&job_recovery_info, sizeof(job_recovery_info));
+    #if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
+      if (ret == -1) SERIAL_PROTOCOLLNPGM("Power-loss file write failed.");
+    #endif
+    return ret;
+  }
+
+  int16_t CardReader::loadJobRecoveryInfo() {
+    return jobRecoveryFile.read(&job_recovery_info, sizeof(job_recovery_info));
+  }
+
+  void CardReader::removeJobRecoveryFile() {
+    job_recovery_info.valid_head = job_recovery_info.valid_foot = job_recovery_commands_count = 0;
+    if (jobRecoverFileExists()) {
+      closefile();
+      removeFile(job_recovery_file_name);
+      #if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
+        SERIAL_PROTOCOLPGM("Power-loss file delete");
+        serialprintPGM(jobRecoverFileExists() ? PSTR(" failed.\n") : PSTR("d.\n"));
+      #endif
+    }
+  }
+
+#endif // POWER_LOSS_RECOVERY
+
+#endif // SDSUPPORT

+ 230 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/cardreader.h

@@ -0,0 +1,230 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _CARDREADER_H_
+#define _CARDREADER_H_
+
+#include "MarlinConfig.h"
+
+#if ENABLED(SDSUPPORT)
+
+#define SD_RESORT ENABLED(SDCARD_SORT_ALPHA) && ENABLED(SDSORT_DYNAMIC_RAM)
+
+#define MAX_DIR_DEPTH 10          // Maximum folder depth
+
+#include "SdFile.h"
+
+class CardReader {
+public:
+  CardReader();
+
+  void initsd();
+  void write_command(char *buf);
+
+  void beginautostart();
+  void checkautostart();
+
+  void openFile(char * const path, const bool read, const bool subcall=false);
+  void openLogFile(char * const path);
+  void removeFile(const char * const name);
+  void closefile(const bool store_location=false);
+  void release();
+  void openAndPrintFile(const char *name);
+  void startFileprint();
+  void stopSDPrint(
+    #if SD_RESORT
+      const bool re_sort=false
+    #endif
+  );
+  void getStatus();
+  void printingHasFinished();
+  void printFilename();
+
+  #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
+    void printLongPath(char *path);
+  #endif
+
+  void getfilename(uint16_t nr, const char* const match=NULL);
+  uint16_t getnrfilenames();
+
+  void getAbsFilename(char *t);
+
+  void ls();
+  void chdir(const char *relpath);
+  int8_t updir();
+  void setroot();
+
+  const char* diveToFile(SdFile*& curDir, const char * const path, const bool echo);
+
+  uint16_t get_num_Files();
+
+  #if ENABLED(SDCARD_SORT_ALPHA)
+    void presort();
+    void getfilename_sorted(const uint16_t nr);
+    #if ENABLED(SDSORT_GCODE)
+      FORCE_INLINE void setSortOn(bool b) { sort_alpha = b; presort(); }
+      FORCE_INLINE void setSortFolders(int i) { sort_folders = i; presort(); }
+      //FORCE_INLINE void setSortReverse(bool b) { sort_reverse = b; }
+    #endif
+  #endif
+
+  #if ENABLED(POWER_LOSS_RECOVERY)
+    void openJobRecoveryFile(const bool read);
+    void closeJobRecoveryFile();
+    bool jobRecoverFileExists();
+    int16_t saveJobRecoveryInfo();
+    int16_t loadJobRecoveryInfo();
+    void removeJobRecoveryFile();
+  #endif
+
+  FORCE_INLINE void pauseSDPrint() { sdprinting = false; }
+  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(const uint32_t index) { sdpos = index; file.seekSet(index); }
+  FORCE_INLINE uint32_t getIndex() { return sdpos; }
+  FORCE_INLINE uint8_t percentDone() { return (isFileOpen() && filesize) ? sdpos / ((filesize + 99) / 100) : 0; }
+  FORCE_INLINE char* getWorkDirName() { workDir.getFilename(filename); return filename; }
+
+  #if ENABLED(AUTO_REPORT_SD_STATUS)
+    void auto_report_sd_status(void);
+    FORCE_INLINE void set_auto_report_interval(uint8_t v) {
+      NOMORE(v, 60);
+      auto_report_sd_interval = v;
+      next_sd_report_ms = millis() + 1000UL * v;
+    }
+  #endif
+
+  FORCE_INLINE char* longest_filename() { return longFilename[0] ? longFilename : filename; }
+
+public:
+  bool saving, logging, sdprinting, cardOK, filenameIsDir;
+  char filename[FILENAME_LENGTH], longFilename[LONG_FILENAME_LENGTH];
+  int8_t autostart_index;
+private:
+  SdFile root, workDir, workDirParents[MAX_DIR_DEPTH];
+  uint8_t workDirDepth;
+
+  // Sort files and folders alphabetically.
+  #if ENABLED(SDCARD_SORT_ALPHA)
+    uint16_t sort_count;        // Count of sorted items in the current directory
+    #if ENABLED(SDSORT_GCODE)
+      bool sort_alpha;          // Flag to enable / disable the feature
+      int sort_folders;         // Flag to enable / disable folder sorting
+      //bool sort_reverse;      // Flag to enable / disable reverse sorting
+    #endif
+
+    // By default the sort index is static
+    #if ENABLED(SDSORT_DYNAMIC_RAM)
+      uint8_t *sort_order;
+    #else
+      uint8_t sort_order[SDSORT_LIMIT];
+    #endif
+
+    #if ENABLED(SDSORT_USES_RAM) && ENABLED(SDSORT_CACHE_NAMES) && DISABLED(SDSORT_DYNAMIC_RAM)
+      #define SORTED_LONGNAME_MAXLEN ((SDSORT_CACHE_VFATS) * (FILENAME_LENGTH) + 1)
+    #else
+      #define SORTED_LONGNAME_MAXLEN LONG_FILENAME_LENGTH
+    #endif
+
+    // Cache filenames to speed up SD menus.
+    #if ENABLED(SDSORT_USES_RAM)
+
+      // If using dynamic ram for names, allocate on the heap.
+      #if ENABLED(SDSORT_CACHE_NAMES)
+        #if ENABLED(SDSORT_DYNAMIC_RAM)
+          char **sortshort, **sortnames;
+        #else
+          char sortshort[SDSORT_LIMIT][FILENAME_LENGTH];
+          char sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN];
+        #endif
+      #elif DISABLED(SDSORT_USES_STACK)
+        char sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN];
+      #endif
+
+      // Folder sorting uses an isDir array when caching items.
+      #if HAS_FOLDER_SORTING
+        #if ENABLED(SDSORT_DYNAMIC_RAM)
+          uint8_t *isDir;
+        #elif ENABLED(SDSORT_CACHE_NAMES) || DISABLED(SDSORT_USES_STACK)
+          uint8_t isDir[(SDSORT_LIMIT+7)>>3];
+        #endif
+      #endif
+
+    #endif // SDSORT_USES_RAM
+
+  #endif // SDCARD_SORT_ALPHA
+
+  Sd2Card sd2card;
+  SdVolume volume;
+  SdFile file;
+
+  #if ENABLED(POWER_LOSS_RECOVERY)
+    SdFile jobRecoveryFile;
+  #endif
+
+  #define SD_PROCEDURE_DEPTH 1
+  #define MAXPATHNAMELENGTH (FILENAME_LENGTH*MAX_DIR_DEPTH + MAX_DIR_DEPTH + 1)
+  uint8_t file_subcall_ctr;
+  uint32_t filespos[SD_PROCEDURE_DEPTH];
+  char proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
+  uint32_t filesize, sdpos;
+
+  LsAction lsAction; //stored for recursion.
+  uint16_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, const char * const match=NULL);
+
+  #if ENABLED(SDCARD_SORT_ALPHA)
+    void flush_presort();
+  #endif
+
+  #if ENABLED(AUTO_REPORT_SD_STATUS)
+    static uint8_t auto_report_sd_interval;
+    static millis_t next_sd_report_ms;
+  #endif
+};
+
+#if PIN_EXISTS(SD_DETECT)
+  #if ENABLED(SD_DETECT_INVERTED)
+    #define IS_SD_INSERTED (READ(SD_DETECT_PIN) == HIGH)
+  #else
+    #define IS_SD_INSERTED (READ(SD_DETECT_PIN) == LOW)
+  #endif
+#else
+  // No card detect line? Assume the card is inserted.
+  #define IS_SD_INSERTED true
+#endif
+
+extern CardReader card;
+
+#endif // SDSUPPORT
+
+#if ENABLED(SDSUPPORT)
+  #define IS_SD_PRINTING (card.sdprinting)
+  #define IS_SD_FILE_OPEN (card.isFileOpen())
+#else
+  #define IS_SD_PRINTING (false)
+  #define IS_SD_FILE_OPEN (false)
+#endif
+
+#endif // _CARDREADER_H_

+ 145 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/circularqueue.h

@@ -0,0 +1,145 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __CIRCULARQUEUE_H__
+#define __CIRCULARQUEUE_H__
+
+#include <Arduino.h>
+
+/**
+ * @brief   Circular Queue class
+ * @details Implementation of the classic ring buffer data structure
+ */
+template<typename T, uint8_t N>
+class CircularQueue {
+  private:
+
+    /**
+     * @brief   Buffer structure
+     * @details This structure consolidates all the overhead required to handle
+     *          a circular queue such as the pointers and the buffer vector.
+     */
+    struct buffer_t {
+      uint8_t head;
+      uint8_t tail;
+      uint8_t count;
+      uint8_t size;
+      T queue[N];
+    } buffer;
+
+  public:
+    /**
+     * @brief   Class constructor
+     * @details This class requires two template parameters, T defines the type
+     *          of item this queue will handle and N defines the maximum number of
+     *          items that can be stored on the queue.
+     */
+    CircularQueue<T, N>() {
+      this->buffer.size = N;
+      this->buffer.count = this->buffer.head = this->buffer.tail = 0;
+    }
+
+    /**
+     * @brief   Removes and returns a item from the queue
+     * @details Removes the oldest item on the queue, pointed to by the
+     *          buffer_t head field. The item is returned to the caller.
+     * @return  type T item
+     */
+    T dequeue() {
+      if (this->isEmpty()) return T();
+
+      uint8_t index = this->buffer.head;
+
+      --this->buffer.count;
+      if (++this->buffer.head == this->buffer.size)
+        this->buffer.head = 0;
+
+      return this->buffer.queue[index];
+    }
+
+    /**
+     * @brief   Adds an item to the queue
+     * @details Adds an item to the queue on the location pointed by the buffer_t
+     *          tail variable. Returns false if no queue space is available.
+     * @param   item Item to be added to the queue
+     * @return  true if the operation was successful
+     */
+    bool enqueue(T const &item) {
+      if (this->isFull()) return false;
+
+      this->buffer.queue[this->buffer.tail] = item;
+
+      ++this->buffer.count;
+      if (++this->buffer.tail == this->buffer.size)
+        this->buffer.tail = 0;
+
+      return true;
+    }
+
+    /**
+     * @brief   Checks if the queue has no items
+     * @details Returns true if there are no items on the queue, false otherwise.
+     * @return  true if queue is empty
+     */
+    bool isEmpty() {
+      return this->buffer.count == 0;
+    }
+
+    /**
+     * @brief   Checks if the queue is full
+     * @details Returns true if the queue is full, false otherwise.
+     * @return  true if queue is full
+     */
+    bool isFull() {
+      return this->buffer.count == this->buffer.size;
+    }
+
+    /**
+     * @brief   Gets the queue size
+     * @details Returns the maximum number of items a queue can have.
+     * @return  the queue size
+     */
+    uint8_t size() {
+      return this->buffer.size;
+    }
+
+    /**
+     * @brief   Gets the next item from the queue without removing it
+     * @details Returns the next item in the queue without removing it
+     *          or updating the pointers.
+     * @return  first item in the queue
+     */
+    T peek() {
+      return this->buffer.queue[this->buffer.head];
+    }
+
+    /**
+     * @brief Gets the number of items on the queue
+     * @details Returns the current number of items stored on the queue.
+     * @return number of items in the queue
+     */
+    uint8_t count() {
+      return this->buffer.count;
+    }
+};
+
+#endif

File diff suppressed because it is too large
+ 2790 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/configuration_store.cpp


+ 101 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/configuration_store.h

@@ -0,0 +1,101 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CONFIGURATION_STORE_H
+#define CONFIGURATION_STORE_H
+
+#include "MarlinConfig.h"
+
+class MarlinSettings {
+  public:
+    MarlinSettings() { }
+
+    static uint16_t datasize();
+
+    static void reset();
+    static bool save();   // Return 'true' if data was saved
+
+    FORCE_INLINE static bool init_eeprom() {
+      reset();
+      #if ENABLED(EEPROM_SETTINGS)
+        const bool success = save();
+        #if ENABLED(EEPROM_CHITCHAT)
+          if (success) report();
+        #endif
+        return success;
+      #else
+        return true;
+      #endif
+    }
+
+    #if ENABLED(EEPROM_SETTINGS)
+      static bool load();     // Return 'true' if data was loaded ok
+      static bool validate(); // Return 'true' if EEPROM data is ok
+
+      #if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system
+                                         // That can store is enabled
+        static uint16_t meshes_start_index();
+        FORCE_INLINE static uint16_t meshes_end_index() { return meshes_end; }
+        static uint16_t calc_num_meshes();
+        static int mesh_slot_offset(const int8_t slot);
+        static void store_mesh(const int8_t slot);
+        static void load_mesh(const int8_t slot, void * const into=NULL);
+
+        //static void delete_mesh();    // necessary if we have a MAT
+        //static void defrag_meshes();  // "
+      #endif
+    #else
+      FORCE_INLINE
+      static bool load() { reset(); report(); return true; }
+    #endif
+
+    #if DISABLED(DISABLE_M503)
+      static void report(const bool forReplay=false);
+    #else
+      FORCE_INLINE
+      static void report(const bool forReplay=false) { UNUSED(forReplay); }
+    #endif
+
+  private:
+    static void postprocess();
+
+    #if ENABLED(EEPROM_SETTINGS)
+
+      static bool eeprom_error, validating;
+
+      #if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system
+                                         // That can store is enabled
+        static constexpr uint16_t meshes_end = E2END - 128; // 128 is a placeholder for the size of the MAT; the MAT will always
+                                                            // live at the very end of the eeprom
+
+      #endif
+
+      static bool _load();
+      static void write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc);
+      static void read_data(int &pos, uint8_t *value, uint16_t size, uint16_t *crc, const bool force=false);
+      static bool size_error(const uint16_t size);
+    #endif
+};
+
+extern MarlinSettings settings;
+
+#endif // CONFIGURATION_STORE_H

+ 153 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dac_mcp4728.cpp

@@ -0,0 +1,153 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * mcp4728.cpp - Arduino library for MicroChip MCP4728 I2C D/A converter
+ *
+ * For implementation details, please take a look at the datasheet:
+ * http://ww1.microchip.com/downloads/en/DeviceDoc/22187a.pdf
+ *
+ * For discussion and feedback, please go to:
+ * http://arduino.cc/forum/index.php/topic,51842.0.html
+ */
+
+#include "MarlinConfig.h"
+
+#if ENABLED(DAC_STEPPER_CURRENT)
+
+#include "dac_mcp4728.h"
+#include "enum.h"
+
+uint16_t mcp4728_values[XYZE];
+
+/**
+ * Begin I2C, get current values (input register and eeprom) of mcp4728
+ */
+void mcp4728_init() {
+  Wire.begin();
+  Wire.requestFrom(int(DAC_DEV_ADDRESS), 24);
+  while (Wire.available()) {
+    char deviceID = Wire.read(),
+         hiByte = Wire.read(),
+         loByte = Wire.read();
+
+    if (!(deviceID & 0x08))
+      mcp4728_values[(deviceID & 0x30) >> 4] = word((hiByte & 0x0F), loByte);
+  }
+}
+
+/**
+ * Write input resister value to specified channel using fastwrite method.
+ * Channel : 0-3, Values : 0-4095
+ */
+uint8_t mcp4728_analogWrite(uint8_t channel, uint16_t value) {
+  mcp4728_values[channel] = value;
+  return mcp4728_fastWrite();
+}
+
+/**
+ * Write all input resistor values to EEPROM using SequencialWrite method.
+ * This will update both input register and EEPROM value
+ * This will also write current Vref, PowerDown, Gain settings to EEPROM
+ */
+uint8_t mcp4728_eepromWrite() {
+  Wire.beginTransmission(DAC_DEV_ADDRESS);
+  Wire.write(SEQWRITE);
+  LOOP_XYZE(i) {
+    Wire.write(DAC_STEPPER_VREF << 7 | DAC_STEPPER_GAIN << 4 | highByte(mcp4728_values[i]));
+    Wire.write(lowByte(mcp4728_values[i]));
+  }
+  return Wire.endTransmission();
+}
+
+/**
+ * Write Voltage reference setting to all input regiters
+ */
+uint8_t mcp4728_setVref_all(uint8_t value) {
+  Wire.beginTransmission(DAC_DEV_ADDRESS);
+  Wire.write(VREFWRITE | (value ? 0x0F : 0x00));
+  return Wire.endTransmission();
+}
+/**
+ * Write Gain setting to all input regiters
+ */
+uint8_t mcp4728_setGain_all(uint8_t value) {
+  Wire.beginTransmission(DAC_DEV_ADDRESS);
+  Wire.write(GAINWRITE | (value ? 0x0F : 0x00));
+  return Wire.endTransmission();
+}
+
+/**
+ * Return Input Register value
+ */
+uint16_t mcp4728_getValue(uint8_t channel) { return mcp4728_values[channel]; }
+
+/**
+ * Steph: Might be useful in the future
+ * Return Vout
+ *
+uint16_t mcp4728_getVout(uint8_t channel) {
+  uint32_t vref = 2048,
+           vOut = (vref * mcp4728_values[channel] * (_DAC_STEPPER_GAIN + 1)) / 4096;
+  if (vOut > defaultVDD) vOut = defaultVDD;
+  return vOut;
+}
+*/
+
+/**
+ * Returns DAC values as a 0-100 percentage of drive strength
+ */
+uint8_t mcp4728_getDrvPct(uint8_t channel) { return uint8_t(100.0 * mcp4728_values[channel] / (DAC_STEPPER_MAX) + 0.5); }
+
+/**
+ * Receives all Drive strengths as 0-100 percent values, updates
+ * DAC Values array and calls fastwrite to update the DAC.
+ */
+void mcp4728_setDrvPct(uint8_t pct[XYZE]) {
+  LOOP_XYZE(i) mcp4728_values[i] = 0.01 * pct[i] * (DAC_STEPPER_MAX);
+  mcp4728_fastWrite();
+}
+
+/**
+ * FastWrite input register values - All DAC ouput update. refer to DATASHEET 5.6.1
+ * DAC Input and PowerDown bits update.
+ * No EEPROM update
+ */
+uint8_t mcp4728_fastWrite() {
+  Wire.beginTransmission(DAC_DEV_ADDRESS);
+  LOOP_XYZE(i) {
+    Wire.write(highByte(mcp4728_values[i]));
+    Wire.write(lowByte(mcp4728_values[i]));
+  }
+  return Wire.endTransmission();
+}
+
+/**
+ * Common function for simple general commands
+ */
+uint8_t mcp4728_simpleCommand(byte simpleCommand) {
+  Wire.beginTransmission(GENERALCALL);
+  Wire.write(simpleCommand);
+  return Wire.endTransmission();
+}
+
+#endif // DAC_STEPPER_CURRENT

+ 66 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dac_mcp4728.h

@@ -0,0 +1,66 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Arduino library for MicroChip MCP4728 I2C D/A converter.
+ */
+
+#ifndef DAC_MCP4728_H
+#define DAC_MCP4728_H
+
+#include "MarlinConfig.h"
+
+#if ENABLED(DAC_STEPPER_CURRENT)
+#include "Wire.h"
+
+#define defaultVDD     DAC_STEPPER_MAX //was 5000 but differs with internal Vref
+#define BASE_ADDR      0x60
+#define RESET          0B00000110
+#define WAKE           0B00001001
+#define UPDATE         0B00001000
+#define MULTIWRITE     0B01000000
+#define SINGLEWRITE    0B01011000
+#define SEQWRITE       0B01010000
+#define VREFWRITE      0B10000000
+#define GAINWRITE      0B11000000
+#define POWERDOWNWRITE 0B10100000
+#define GENERALCALL    0B00000000
+#define GAINWRITE      0B11000000
+
+// This is taken from the original lib, makes it easy to edit if needed
+// DAC_OR_ADDRESS defined in pins_BOARD.h  file
+#define DAC_DEV_ADDRESS (BASE_ADDR | DAC_OR_ADDRESS)
+
+
+void mcp4728_init();
+uint8_t mcp4728_analogWrite(uint8_t channel, uint16_t value);
+uint8_t mcp4728_eepromWrite();
+uint8_t mcp4728_setVref_all(uint8_t value);
+uint8_t mcp4728_setGain_all(uint8_t value);
+uint16_t mcp4728_getValue(uint8_t channel);
+uint8_t mcp4728_fastWrite();
+uint8_t mcp4728_simpleCommand(byte simpleCommand);
+uint8_t mcp4728_getDrvPct(uint8_t channel);
+void mcp4728_setDrvPct(uint8_t pct[XYZE]);
+
+#endif
+#endif // DAC_MCP4728_H

+ 77 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/delay.h

@@ -0,0 +1,77 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * AVR busy wait delay Cycles routines:
+ *
+ *  DELAY_CYCLES(count): Delay execution in cycles
+ *  DELAY_NS(count): Delay execution in nanoseconds
+ *  DELAY_US(count): Delay execution in microseconds
+ */
+
+#ifndef MARLIN_DELAY_H
+#define MARLIN_DELAY_H
+
+#define nop() __asm__ __volatile__("nop;\n\t":::)
+
+FORCE_INLINE static void __delay_4cycles(uint8_t cy) {
+  __asm__ __volatile__(
+    L("1")
+    A("dec %[cnt]")
+    A("nop")
+    A("brne 1b")
+    : [cnt] "+r"(cy)  // output: +r means input+output
+    :                 // input:
+    : "cc"            // clobbers:
+  );
+}
+
+/* ---------------- Delay in cycles */
+FORCE_INLINE static void DELAY_CYCLES(uint16_t x) {
+
+  if (__builtin_constant_p(x)) {
+    #define MAXNOPS 4
+
+    if (x <= (MAXNOPS)) {
+      switch (x) { case 4: nop(); case 3: nop(); case 2: nop(); case 1: nop(); }
+    }
+    else {
+      const uint32_t rem = (x) % (MAXNOPS);
+      switch (rem) { case 3: nop(); case 2: nop(); case 1: nop(); }
+      if ((x = (x) / (MAXNOPS)))
+        __delay_4cycles(x); // if need more then 4 nop loop is more optimal
+    }
+
+    #undef MAXNOPS
+  }
+  else
+    __delay_4cycles(x / 4);
+}
+#undef nop
+
+/* ---------------- Delay in nanoseconds */
+#define DELAY_NS(x) DELAY_CYCLES( (x) * (F_CPU/1000000L) / 1000L )
+
+/* ---------------- Delay in microseconds */
+#define DELAY_US(x) DELAY_CYCLES( (x) * (F_CPU/1000000L) )
+
+#endif // MARLIN_DELAY_H

+ 106 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/digipot_mcp4018.cpp

@@ -0,0 +1,106 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "MarlinConfig.h"
+
+#if ENABLED(DIGIPOT_I2C) && ENABLED(DIGIPOT_MCP4018)
+
+#include "enum.h"
+#include "Stream.h"
+#include "utility/twi.h"
+#include <SlowSoftI2CMaster.h>  //https://github.com/stawel/SlowSoftI2CMaster
+
+// Settings for the I2C based DIGIPOT (MCP4018) based on WT150
+
+#define DIGIPOT_I2C_ADDRESS             0x2F
+
+#define DIGIPOT_A4988_Rsx               0.250
+#define DIGIPOT_A4988_Vrefmax           1.666
+#define DIGIPOT_A4988_MAX_VALUE         127
+
+#define DIGIPOT_A4988_Itripmax(Vref)    ((Vref)/(8.0*DIGIPOT_A4988_Rsx))
+
+#define DIGIPOT_A4988_FACTOR            ((DIGIPOT_A4988_MAX_VALUE)/DIGIPOT_A4988_Itripmax(DIGIPOT_A4988_Vrefmax))
+#define DIGIPOT_A4988_MAX_CURRENT       2.0
+
+static byte current_to_wiper(const float current) {
+  const int16_t value = ceil(float(DIGIPOT_A4988_FACTOR) * current);
+  return byte(constrain(value, 0, DIGIPOT_A4988_MAX_VALUE));
+}
+
+const uint8_t sda_pins[DIGIPOT_I2C_NUM_CHANNELS] = {
+  DIGIPOTS_I2C_SDA_X
+  #if DIGIPOT_I2C_NUM_CHANNELS > 1
+    , DIGIPOTS_I2C_SDA_Y
+    #if DIGIPOT_I2C_NUM_CHANNELS > 2
+      , DIGIPOTS_I2C_SDA_Z
+      #if DIGIPOT_I2C_NUM_CHANNELS > 3
+        , DIGIPOTS_I2C_SDA_E0
+        #if DIGIPOT_I2C_NUM_CHANNELS > 4
+          , DIGIPOTS_I2C_SDA_E1
+        #endif
+      #endif
+    #endif
+  #endif
+};
+
+static SlowSoftI2CMaster pots[DIGIPOT_I2C_NUM_CHANNELS] = {
+  SlowSoftI2CMaster { sda_pins[X_AXIS], DIGIPOTS_I2C_SCL }
+  #if DIGIPOT_I2C_NUM_CHANNELS > 1
+    , SlowSoftI2CMaster { sda_pins[Y_AXIS], DIGIPOTS_I2C_SCL }
+    #if DIGIPOT_I2C_NUM_CHANNELS > 2
+      , SlowSoftI2CMaster { sda_pins[Z_AXIS], DIGIPOTS_I2C_SCL }
+      #if DIGIPOT_I2C_NUM_CHANNELS > 3
+        , SlowSoftI2CMaster { sda_pins[E_AXIS], DIGIPOTS_I2C_SCL }
+        #if DIGIPOT_I2C_NUM_CHANNELS > 4
+          , SlowSoftI2CMaster { sda_pins[E_AXIS + 1], DIGIPOTS_I2C_SCL }
+        #endif
+      #endif
+    #endif
+  #endif
+};
+
+static void i2c_send(const uint8_t channel, const byte v) {
+  if (WITHIN(channel, 0, DIGIPOT_I2C_NUM_CHANNELS - 1)) {
+    pots[channel].i2c_start(((DIGIPOT_I2C_ADDRESS) << 1) | I2C_WRITE);
+    pots[channel].i2c_write(v);
+    pots[channel].i2c_stop();
+  }
+}
+
+// This is for the MCP4018 I2C based digipot
+void digipot_i2c_set_current(uint8_t channel, float current) {
+  i2c_send(channel, current_to_wiper(MIN(MAX(current, 0), float(DIGIPOT_A4988_MAX_CURRENT))));
+}
+
+void digipot_i2c_init() {
+  static const float digipot_motor_current[] PROGMEM = DIGIPOT_I2C_MOTOR_CURRENTS;
+
+  for (uint8_t i = 0; i < DIGIPOT_I2C_NUM_CHANNELS; i++)
+    pots[i].i2c_init();
+
+  // setup initial currents as defined in Configuration_adv.h
+  for (uint8_t i = 0; i < COUNT(digipot_motor_current); i++)
+    digipot_i2c_set_current(i, pgm_read_float(&digipot_motor_current[i]));
+}
+
+#endif // DIGIPOT_I2C && DIGIPOT_MCP4018

+ 79 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/digipot_mcp4451.cpp

@@ -0,0 +1,79 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "MarlinConfig.h"
+
+#if ENABLED(DIGIPOT_I2C) && DISABLED(DIGIPOT_MCP4018)
+
+#include "Stream.h"
+#include "utility/twi.h"
+#include "Wire.h"
+
+// Settings for the I2C based DIGIPOT (MCP4451) on Azteeg X3 Pro
+#if MB(5DPRINT)
+  #define DIGIPOT_I2C_FACTOR 117.96
+  #define DIGIPOT_I2C_MAX_CURRENT 1.736
+#else
+  #define DIGIPOT_I2C_FACTOR 106.7
+  #define DIGIPOT_I2C_MAX_CURRENT 2.5
+#endif
+
+static byte current_to_wiper(const float current) {
+  return byte(CEIL(float((DIGIPOT_I2C_FACTOR * current))));
+}
+
+static void i2c_send(const byte addr, const byte a, const 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(uint8_t channel, float current) {
+  current = MIN((float) MAX(current, 0), 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() {
+  static const float digipot_motor_current[] PROGMEM = DIGIPOT_I2C_MOTOR_CURRENTS;
+  Wire.begin();
+  // setup initial currents as defined in Configuration_adv.h
+  for (uint8_t i = 0; i < COUNT(digipot_motor_current); i++)
+    digipot_i2c_set_current(i, pgm_read_float(&digipot_motor_current[i]));
+}
+
+#endif // DIGIPOT_I2C

File diff suppressed because it is too large
+ 1192 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_bitmaps.h


+ 180 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_6x9_marlin.h

@@ -0,0 +1,180 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+  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 <U8glib.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
+};

+ 194 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_HD44780_C.h

@@ -0,0 +1,194 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+  Fontname: HD44780_C v1.2
+  Copyright: A. Hardtung, public domain
+  Capital A Height: 7, '1' Height: 7
+  Calculated Max Values w= 5 h= 8 x= 2 y= 7 dx= 6 dy= 0 ascent= 8 len= 8
+  Font Bounding box     w= 6 h= 9 x= 0 y=-2
+  Calculated Min Values           x= 0 y=-1 dx= 0 dy= 0
+  Pure Font   ascent = 7 descent=-1
+  X Font      ascent = 7 descent=-1
+  Max Font    ascent = 8 descent=-1
+*/
+#include <U8glib.h>
+const u8g_fntpgm_uint8_t HD44780_C_5x7[2522] U8G_SECTION(".progmem.HD44780_C_5x7") = {
+  0, 6, 9, 0, 254, 7, 1, 145, 3, 34, 32, 255, 255, 8, 255, 7,
+  255, 0, 0, 0, 6, 0, 0, 1, 7, 7, 6, 2, 0, 128, 128, 128,
+  128, 128, 0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6,
+  0, 0, 80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32,
+  120, 160, 112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32,
+  64, 152, 24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104,
+  2, 3, 3, 6, 1, 4, 192, 64, 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, 32, 168, 112, 168, 32, 5, 5,
+  5, 6, 0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192,
+  64, 128, 5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192,
+  192, 5, 5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6,
+  0, 0, 112, 136, 152, 168, 200, 136, 112, 3, 7, 7, 6, 1, 0, 64,
+  192, 64, 64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112,
+  128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240,
+  5, 7, 7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7,
+  6, 0, 0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0,
+  48, 64, 128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16,
+  32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136,
+  112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 16, 96, 2, 5,
+  5, 6, 2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192,
+  192, 0, 192, 64, 128, 4, 7, 7, 6, 0, 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,
+  8, 16, 32, 0, 32, 5, 6, 6, 6, 0, 0, 112, 136, 8, 104, 168,
+  112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5, 7,
+  7, 6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6, 0,
+  0, 112, 136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 224, 144,
+  136, 136, 136, 144, 224, 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, 184, 136, 136, 112, 5, 7, 7, 6,
+  0, 0, 136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0, 128,
+  128, 128, 128, 128, 128, 128, 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, 216, 168, 136, 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, 7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5, 7,
+  7, 6, 0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6, 0,
+  0, 120, 128, 128, 112, 8, 8, 240, 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, 136, 136, 80, 32, 5,
+  7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7, 6,
+  0, 0, 136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0, 136,
+  136, 136, 80, 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, 32, 112, 160, 160, 168, 112, 32, 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, 0, 248, 2, 2, 2, 6, 2, 5,
+  128, 64, 5, 5, 5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7,
+  6, 0, 0, 128, 128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0,
+  112, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136,
+  136, 120, 5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7,
+  6, 0, 0, 48, 72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255,
+  112, 136, 136, 120, 8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200,
+  136, 136, 136, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128,
+  3, 8, 8, 6, 1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7,
+  7, 6, 0, 0, 128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1,
+  0, 192, 64, 64, 64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168,
+  168, 168, 168, 5, 5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5,
+  5, 6, 0, 0, 112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240,
+  136, 136, 240, 128, 128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 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, 224,
+  64, 64, 72, 48, 5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5,
+  5, 5, 6, 0, 0, 136, 136, 136, 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, 6, 6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6,
+  0, 0, 248, 16, 32, 64, 248, 5, 5, 5, 6, 0, 2, 184, 168, 168,
+  168, 184, 5, 5, 5, 6, 0, 2, 184, 136, 184, 160, 184, 5, 5, 5,
+  6, 0, 2, 184, 160, 184, 136, 184, 5, 6, 6, 6, 0, 1, 8, 40,
+  72, 248, 64, 32, 5, 5, 5, 6, 0, 0, 56, 112, 224, 136, 240, 0,
+  0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
+  0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
+  6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+  0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
+  0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
+  6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+  0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
+  0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
+  6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+  0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
+  0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
+  6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 5,
+  7, 7, 6, 0, 0, 248, 136, 128, 240, 136, 136, 240, 5, 7, 7, 6,
+  0, 0, 248, 136, 128, 128, 128, 128, 128, 5, 7, 7, 6, 0, 0, 80,
+  0, 248, 128, 240, 128, 248, 5, 7, 7, 6, 0, 0, 168, 168, 168, 112,
+  168, 168, 168, 5, 7, 7, 6, 0, 0, 240, 8, 8, 112, 8, 8, 240,
+  5, 7, 7, 6, 0, 0, 136, 136, 152, 168, 200, 136, 136, 5, 8, 8,
+  6, 0, 0, 80, 32, 136, 152, 168, 168, 200, 136, 5, 7, 7, 6, 0,
+  0, 120, 40, 40, 40, 40, 168, 72, 5, 7, 7, 6, 0, 0, 248, 136,
+  136, 136, 136, 136, 136, 5, 7, 7, 6, 0, 0, 136, 136, 136, 80, 32,
+  64, 128, 5, 7, 7, 6, 0, 0, 32, 112, 168, 168, 168, 112, 32, 5,
+  7, 7, 6, 0, 0, 136, 136, 136, 120, 8, 8, 8, 5, 7, 7, 6,
+  0, 0, 168, 168, 168, 168, 168, 168, 248, 5, 7, 7, 6, 0, 0, 192,
+  64, 64, 112, 72, 72, 112, 5, 7, 7, 6, 0, 0, 136, 136, 136, 200,
+  168, 168, 200, 5, 7, 7, 6, 0, 0, 112, 136, 8, 56, 8, 136, 112,
+  5, 7, 7, 6, 0, 0, 144, 168, 168, 232, 168, 168, 144, 5, 7, 7,
+  6, 0, 0, 120, 136, 136, 120, 40, 72, 136, 5, 7, 7, 6, 0, 0,
+  24, 96, 128, 240, 136, 136, 112, 4, 5, 5, 6, 0, 0, 224, 144, 224,
+  144, 224, 5, 5, 5, 6, 0, 0, 248, 136, 128, 128, 128, 5, 7, 7,
+  6, 0, 0, 80, 0, 112, 136, 248, 128, 112, 5, 5, 5, 6, 0, 0,
+  168, 168, 112, 168, 168, 5, 5, 5, 6, 0, 0, 240, 8, 48, 8, 240,
+  5, 5, 5, 6, 0, 0, 136, 152, 168, 200, 136, 5, 7, 7, 6, 0,
+  0, 80, 32, 136, 152, 168, 200, 136, 4, 5, 5, 6, 0, 0, 144, 160,
+  192, 160, 144, 5, 5, 5, 6, 0, 0, 248, 40, 40, 168, 72, 5, 5,
+  5, 6, 0, 0, 136, 216, 168, 136, 136, 5, 5, 5, 6, 0, 0, 136,
+  136, 248, 136, 136, 5, 5, 5, 6, 0, 0, 248, 136, 136, 136, 136, 5,
+  5, 5, 6, 0, 0, 248, 32, 32, 32, 32, 5, 5, 5, 6, 0, 0,
+  136, 136, 120, 8, 8, 5, 5, 5, 6, 0, 0, 168, 168, 168, 168, 248,
+  5, 5, 5, 6, 0, 0, 192, 64, 112, 72, 112, 5, 5, 5, 6, 0,
+  0, 136, 136, 200, 168, 200, 4, 5, 5, 6, 0, 0, 128, 128, 224, 144,
+  224, 5, 5, 5, 6, 0, 0, 112, 136, 56, 136, 112, 5, 5, 5, 6,
+  0, 0, 144, 168, 232, 168, 144, 5, 5, 5, 6, 0, 0, 120, 136, 120,
+  40, 72, 5, 5, 5, 6, 0, 1, 32, 72, 144, 72, 32, 5, 5, 5,
+  6, 0, 1, 32, 144, 72, 144, 32, 5, 3, 3, 6, 0, 0, 72, 144,
+  216, 5, 3, 3, 6, 0, 4, 216, 72, 144, 5, 7, 7, 6, 0, 0,
+  144, 208, 176, 144, 56, 40, 56, 5, 7, 7, 6, 0, 0, 32, 0, 32,
+  64, 128, 136, 112, 5, 7, 7, 6, 0, 0, 24, 32, 32, 112, 32, 32,
+  192, 5, 7, 7, 6, 0, 0, 32, 80, 64, 240, 64, 64, 120, 1, 2,
+  2, 6, 2, 0, 128, 128, 1, 4, 4, 6, 2, 0, 128, 128, 128, 128,
+  3, 5, 5, 6, 1, 0, 160, 160, 160, 0, 224, 3, 5, 5, 6, 1,
+  0, 160, 160, 160, 0, 160, 5, 7, 7, 6, 0, 0, 160, 0, 232, 16,
+  32, 64, 128, 5, 5, 5, 6, 0, 1, 216, 112, 32, 112, 216, 5, 7,
+  7, 6, 0, 0, 160, 64, 168, 16, 32, 64, 128, 3, 6, 6, 6, 1,
+  1, 224, 64, 64, 64, 64, 224, 5, 6, 6, 6, 0, 1, 248, 80, 80,
+  80, 80, 248, 5, 7, 7, 6, 0, 0, 32, 112, 168, 32, 32, 32, 32,
+  5, 7, 7, 6, 0, 0, 32, 32, 32, 32, 168, 112, 32, 5, 7, 7,
+  6, 0, 0, 128, 144, 176, 248, 176, 144, 128, 5, 7, 7, 6, 0, 0,
+  8, 72, 104, 248, 104, 72, 8, 5, 7, 7, 6, 0, 0, 128, 136, 168,
+  248, 168, 136, 128, 5, 7, 7, 6, 0, 0, 128, 224, 136, 16, 32, 64,
+  128, 2, 2, 2, 6, 2, 2, 192, 192, 5, 8, 8, 6, 0, 255, 120,
+  40, 40, 40, 72, 136, 248, 136, 5, 8, 8, 6, 0, 255, 136, 136, 136,
+  136, 136, 136, 248, 8, 5, 8, 8, 6, 0, 255, 168, 168, 168, 168, 168,
+  168, 248, 8, 5, 6, 6, 6, 0, 255, 120, 40, 72, 136, 248, 136, 5,
+  7, 7, 6, 0, 255, 32, 32, 112, 168, 168, 112, 32, 5, 6, 6, 6,
+  0, 255, 136, 136, 136, 136, 248, 8, 5, 6, 6, 6, 0, 255, 168, 168,
+  168, 168, 248, 8, 2, 2, 2, 6, 2, 6, 64, 128, 3, 1, 1, 6,
+  1, 7, 160, 5, 2, 2, 6, 0, 6, 72, 176, 5, 8, 8, 6, 0,
+  0, 16, 32, 0, 112, 136, 248, 128, 112, 5, 6, 6, 6, 0, 255, 112,
+  128, 136, 112, 32, 96, 3, 7, 7, 6, 1, 0, 160, 0, 160, 160, 160,
+  32, 192, 5, 6, 6, 6, 0, 1, 32, 112, 112, 112, 248, 32, 5, 5,
+  5, 6, 0, 1, 80, 0, 136, 0, 80, 5, 5, 5, 6, 0, 1, 112,
+  136, 136, 136, 112, 5, 7, 7, 6, 0, 0, 136, 144, 168, 88, 184, 8,
+  8, 5, 7, 7, 6, 0, 0, 136, 144, 184, 72, 184, 8, 56, 5, 7,
+  7, 6, 0, 0, 136, 144, 184, 72, 152, 32, 56, 5, 8, 8, 6, 0,
+  0, 192, 64, 192, 72, 216, 56, 8, 8, 5, 7, 7, 6, 0, 0, 136,
+  248, 136, 248, 136, 248, 136, 4, 5, 5, 6, 0, 2, 192, 0, 48, 0,
+  96, 5, 8, 8, 6, 0, 0, 64, 160, 224, 168, 8, 40, 120, 32, 5,
+  8, 8, 6, 0, 0, 64, 112, 64, 120, 64, 112, 64, 224, 5, 8, 8,
+  6, 0, 0, 32, 112, 32, 248, 32, 112, 32, 112, 5, 7, 7, 6, 0,
+  0, 104, 0, 232, 0, 104, 16, 56, 5, 8, 8, 6, 0, 0, 16, 112,
+  16, 240, 16, 112, 16, 56, 5, 7, 7, 6, 0, 1, 32, 112, 32, 248,
+  32, 112, 32, 5, 8, 8, 6, 0, 0, 16, 144, 80, 48, 80, 144, 16,
+  56, 5, 8, 8, 6, 0, 0, 48, 72, 32, 80, 80, 32, 144, 96, 5,
+  7, 7, 6, 0, 0, 120, 168, 168, 120, 40, 40, 40, 5, 8, 8, 6,
+  0, 0, 248, 248, 248, 248, 248, 248, 248, 248
+};

+ 192 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_HD44780_J.h

@@ -0,0 +1,192 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+  Fontname: HD44780_J
+  Copyright: A. Hardtung, public domain
+  Capital A Height: 7, '1' Height: 7
+  Calculated Max Values w= 6 h=10 x= 2 y= 5 dx= 6 dy= 0 ascent= 8 len= 8
+  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=-1
+  X Font      ascent = 7 descent=-1
+  Max Font    ascent = 8 descent=-2
+*/
+#include <U8glib.h>
+const u8g_fntpgm_uint8_t HD44780_J_5x7[2492] U8G_SECTION(".progmem.HD44780_J_5x7") = {
+  0, 6, 9, 0, 254, 7, 1, 145, 3, 34, 32, 255, 255, 8, 254, 7,
+  255, 0, 0, 0, 6, 0, 0, 1, 7, 7, 6, 2, 0, 128, 128, 128,
+  128, 128, 0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6,
+  0, 0, 80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32,
+  120, 160, 112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32,
+  64, 152, 24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104,
+  2, 3, 3, 6, 1, 4, 192, 64, 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, 32, 168, 112, 168, 32, 5, 5,
+  5, 6, 0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192,
+  64, 128, 5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192,
+  192, 5, 5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6,
+  0, 0, 112, 136, 152, 168, 200, 136, 112, 3, 7, 7, 6, 1, 0, 64,
+  192, 64, 64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112,
+  128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240,
+  5, 7, 7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7,
+  6, 0, 0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0,
+  48, 64, 128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16,
+  32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136,
+  112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 16, 96, 2, 5,
+  5, 6, 2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192,
+  192, 0, 192, 64, 128, 4, 7, 7, 6, 0, 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,
+  8, 16, 32, 0, 32, 5, 6, 6, 6, 0, 0, 112, 136, 8, 104, 168,
+  112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5, 7,
+  7, 6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6, 0,
+  0, 112, 136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 224, 144,
+  136, 136, 136, 144, 224, 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, 184, 136, 136, 112, 5, 7, 7, 6,
+  0, 0, 136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0, 128,
+  128, 128, 128, 128, 128, 128, 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, 216, 168, 136, 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, 7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5, 7,
+  7, 6, 0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6, 0,
+  0, 120, 128, 128, 112, 8, 8, 240, 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, 136, 136, 80, 32, 5,
+  7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7, 6,
+  0, 0, 136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0, 136,
+  136, 136, 80, 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, 136, 80, 248, 32, 248, 32, 32, 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, 0, 248, 2, 2, 2, 6, 2, 5,
+  128, 64, 5, 5, 5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7,
+  6, 0, 0, 128, 128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0,
+  112, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136,
+  136, 120, 5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7,
+  6, 0, 0, 48, 72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255,
+  112, 136, 136, 120, 8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200,
+  136, 136, 136, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128,
+  3, 8, 8, 6, 1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7,
+  7, 6, 0, 0, 128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1,
+  0, 192, 64, 64, 64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168,
+  168, 168, 168, 5, 5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5,
+  5, 6, 0, 0, 112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240,
+  136, 136, 240, 128, 128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 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, 224,
+  64, 64, 72, 48, 5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5,
+  5, 5, 6, 0, 0, 136, 136, 136, 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, 6, 6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6,
+  0, 0, 248, 16, 32, 64, 248, 3, 7, 7, 6, 1, 0, 32, 64, 64,
+  128, 64, 64, 32, 1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128, 128,
+  128, 3, 7, 7, 6, 1, 0, 128, 64, 64, 32, 64, 64, 128, 5, 5,
+  5, 6, 0, 1, 32, 16, 248, 16, 32, 5, 5, 5, 6, 0, 1, 32,
+  64, 248, 64, 32, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
+  0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
+  0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+  0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
+  0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
+  0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+  0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
+  0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
+  0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+  0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
+  0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
+  0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+  0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 3, 3, 3, 6, 0, 0,
+  224, 160, 224, 3, 4, 4, 6, 2, 3, 224, 128, 128, 128, 3, 4, 4,
+  6, 0, 0, 32, 32, 32, 224, 3, 3, 3, 6, 0, 0, 128, 64, 32,
+  2, 2, 2, 6, 1, 2, 192, 192, 5, 6, 6, 6, 0, 0, 248, 8,
+  248, 8, 16, 32, 5, 5, 5, 6, 0, 0, 248, 8, 48, 32, 64, 4,
+  5, 5, 6, 0, 0, 16, 32, 96, 160, 32, 5, 5, 5, 6, 0, 0,
+  32, 248, 136, 8, 48, 5, 4, 4, 6, 0, 0, 248, 32, 32, 248, 5,
+  5, 5, 6, 0, 0, 16, 248, 48, 80, 144, 5, 5, 5, 6, 0, 0,
+  64, 248, 72, 80, 64, 5, 4, 4, 6, 0, 0, 112, 16, 16, 248, 4,
+  5, 5, 6, 0, 0, 240, 16, 240, 16, 240, 5, 4, 4, 6, 0, 0,
+  168, 168, 8, 48, 5, 1, 1, 6, 0, 3, 248, 5, 7, 7, 6, 0,
+  0, 248, 8, 40, 48, 32, 32, 64, 5, 7, 7, 6, 0, 0, 8, 16,
+  32, 96, 160, 32, 32, 5, 7, 7, 6, 0, 0, 32, 248, 136, 136, 8,
+  16, 32, 5, 6, 6, 6, 0, 0, 248, 32, 32, 32, 32, 248, 5, 7,
+  7, 6, 0, 0, 16, 248, 16, 48, 80, 144, 16, 5, 7, 7, 6, 0,
+  0, 64, 248, 72, 72, 72, 72, 144, 5, 7, 7, 6, 0, 0, 32, 248,
+  32, 248, 32, 32, 32, 5, 6, 6, 6, 0, 0, 120, 72, 136, 8, 16,
+  96, 5, 7, 7, 6, 0, 0, 64, 120, 144, 16, 16, 16, 32, 5, 6,
+  6, 6, 0, 0, 248, 8, 8, 8, 8, 248, 5, 7, 7, 6, 0, 0,
+  80, 248, 80, 80, 16, 32, 64, 5, 6, 6, 6, 0, 0, 192, 8, 200,
+  8, 16, 224, 5, 6, 6, 6, 0, 0, 248, 8, 16, 32, 80, 136, 5,
+  7, 7, 6, 0, 0, 64, 248, 72, 80, 64, 64, 56, 5, 6, 6, 6,
+  0, 0, 136, 136, 72, 8, 16, 96, 5, 6, 6, 6, 0, 0, 120, 72,
+  168, 24, 16, 96, 5, 7, 7, 6, 0, 0, 16, 224, 32, 248, 32, 32,
+  64, 5, 6, 6, 6, 0, 0, 168, 168, 168, 8, 16, 32, 5, 7, 7,
+  6, 0, 0, 112, 0, 248, 32, 32, 32, 64, 3, 7, 7, 6, 1, 0,
+  128, 128, 128, 192, 160, 128, 128, 5, 7, 7, 6, 0, 0, 32, 32, 248,
+  32, 32, 64, 128, 5, 6, 6, 6, 0, 0, 112, 0, 0, 0, 0, 248,
+  5, 6, 6, 6, 0, 0, 248, 8, 80, 32, 80, 128, 5, 7, 7, 6,
+  0, 0, 32, 248, 16, 32, 112, 168, 32, 3, 7, 7, 6, 1, 0, 32,
+  32, 32, 32, 32, 64, 128, 5, 6, 6, 6, 0, 0, 32, 16, 136, 136,
+  136, 136, 5, 7, 7, 6, 0, 0, 128, 128, 248, 128, 128, 128, 120, 5,
+  6, 6, 6, 0, 0, 248, 8, 8, 8, 16, 96, 5, 5, 5, 6, 0,
+  1, 64, 160, 16, 8, 8, 5, 7, 7, 6, 0, 0, 32, 248, 32, 32,
+  168, 168, 32, 5, 6, 6, 6, 0, 0, 248, 8, 8, 80, 32, 16, 4,
+  6, 6, 6, 1, 0, 224, 0, 224, 0, 224, 16, 5, 6, 6, 6, 0,
+  0, 32, 64, 128, 136, 248, 8, 5, 6, 6, 6, 0, 0, 8, 8, 80,
+  32, 80, 128, 5, 6, 6, 6, 0, 0, 248, 64, 248, 64, 64, 56, 5,
+  7, 7, 6, 0, 0, 64, 64, 248, 72, 80, 64, 64, 5, 7, 7, 6,
+  0, 0, 112, 16, 16, 16, 16, 16, 248, 5, 6, 6, 6, 0, 0, 248,
+  8, 248, 8, 8, 248, 5, 7, 7, 6, 0, 0, 112, 0, 248, 8, 8,
+  16, 32, 4, 7, 7, 6, 0, 0, 144, 144, 144, 144, 16, 32, 64, 5,
+  6, 6, 6, 0, 0, 32, 160, 160, 168, 168, 176, 5, 7, 7, 6, 0,
+  0, 128, 128, 128, 136, 144, 160, 192, 5, 6, 6, 6, 0, 0, 248, 136,
+  136, 136, 136, 248, 5, 6, 6, 6, 0, 0, 248, 136, 136, 8, 16, 32,
+  5, 6, 6, 6, 0, 0, 192, 0, 8, 8, 16, 224, 4, 3, 3, 6,
+  0, 4, 32, 144, 64, 3, 3, 3, 6, 0, 4, 224, 160, 224, 5, 5,
+  5, 6, 0, 1, 72, 168, 144, 144, 104, 5, 7, 7, 6, 0, 0, 80,
+  0, 112, 8, 120, 136, 120, 4, 8, 8, 6, 1, 255, 96, 144, 144, 224,
+  144, 144, 224, 128, 5, 5, 5, 6, 0, 0, 112, 128, 96, 136, 112, 5,
+  6, 6, 6, 0, 255, 136, 136, 152, 232, 136, 128, 5, 5, 5, 6, 0,
+  0, 120, 160, 144, 136, 112, 5, 7, 7, 6, 0, 254, 48, 72, 136, 136,
+  240, 128, 128, 5, 8, 8, 6, 0, 254, 120, 136, 136, 136, 120, 8, 8,
+  112, 5, 5, 5, 6, 0, 1, 56, 32, 32, 160, 64, 4, 3, 3, 6,
+  0, 3, 16, 208, 16, 4, 8, 8, 6, 0, 255, 16, 0, 48, 16, 16,
+  16, 144, 96, 3, 3, 3, 6, 0, 4, 160, 64, 160, 5, 7, 7, 6,
+  0, 0, 32, 112, 160, 160, 168, 112, 32, 5, 7, 7, 6, 0, 0, 64,
+  64, 224, 64, 224, 64, 120, 5, 7, 7, 6, 0, 0, 112, 0, 176, 200,
+  136, 136, 136, 5, 7, 7, 6, 0, 0, 80, 0, 112, 136, 136, 136, 112,
+  5, 7, 7, 6, 0, 255, 176, 200, 136, 136, 240, 128, 128, 5, 7, 7,
+  6, 0, 255, 104, 152, 136, 136, 120, 8, 8, 5, 6, 6, 6, 0, 0,
+  112, 136, 248, 136, 136, 112, 5, 3, 3, 6, 0, 2, 88, 168, 208, 5,
+  5, 5, 6, 0, 0, 112, 136, 136, 80, 216, 5, 7, 7, 6, 0, 0,
+  80, 0, 136, 136, 136, 152, 104, 5, 7, 7, 6, 0, 0, 248, 128, 64,
+  32, 64, 128, 248, 5, 5, 5, 6, 0, 0, 248, 80, 80, 80, 152, 5,
+  7, 7, 6, 0, 0, 248, 0, 136, 80, 32, 80, 136, 5, 7, 7, 6,
+  0, 255, 136, 136, 136, 136, 120, 8, 112, 5, 6, 6, 6, 0, 0, 8,
+  240, 32, 248, 32, 32, 5, 5, 5, 6, 0, 0, 248, 64, 120, 72, 136,
+  5, 5, 5, 6, 0, 0, 248, 168, 248, 136, 136, 5, 5, 5, 6, 0,
+  1, 32, 0, 248, 0, 32, 0, 0, 0, 6, 0, 0, 6, 10, 10, 6,
+  0, 254, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252
+};

+ 226 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_HD44780_W.h

@@ -0,0 +1,226 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+  Fontname: HD44780_W
+  Copyright: A.Hardtung, public domain
+  Capital A Height: 7, '1' Height: 7
+  Calculated Max Values w= 5 h= 9 x= 2 y= 5 dx= 6 dy= 0 ascent= 8 len= 9
+  Font Bounding box     w= 6 h= 9 x= 0 y=-2
+  Calculated Min Values           x= 0 y=-1 dx= 0 dy= 0
+  Pure Font   ascent = 7 descent=-1
+  X Font      ascent = 7 descent=-1
+  Max Font    ascent = 8 descent=-1
+*/
+#include <U8glib.h>
+const u8g_fntpgm_uint8_t HD44780_W_5x7[3034] U8G_SECTION(".progmem.HD44780_W_5x7") = {
+  0, 6, 9, 0, 254, 7, 2, 79, 3, 222, 16, 255, 255, 8, 255, 7,
+  255, 4, 7, 7, 6, 0, 0, 16, 48, 112, 240, 112, 48, 16, 4, 7,
+  7, 6, 1, 0, 128, 192, 224, 240, 224, 192, 128, 5, 3, 3, 6, 0,
+  4, 216, 72, 144, 5, 3, 3, 6, 0, 4, 216, 144, 72, 5, 7, 7,
+  6, 0, 0, 32, 112, 248, 0, 32, 112, 248, 5, 7, 7, 6, 0, 0,
+  248, 112, 32, 0, 248, 112, 32, 5, 5, 5, 6, 0, 1, 112, 248, 248,
+  248, 112, 5, 7, 7, 6, 0, 0, 8, 8, 40, 72, 248, 64, 32, 5,
+  7, 7, 6, 0, 0, 32, 112, 168, 32, 32, 32, 32, 5, 7, 7, 6,
+  0, 0, 32, 32, 32, 32, 168, 112, 32, 5, 5, 5, 6, 0, 1, 32,
+  64, 248, 64, 32, 5, 5, 5, 6, 0, 1, 32, 16, 248, 16, 32, 5,
+  7, 7, 6, 0, 0, 16, 32, 64, 32, 16, 0, 248, 5, 7, 7, 6,
+  0, 0, 64, 32, 16, 32, 64, 0, 248, 5, 5, 5, 6, 0, 1, 32,
+  32, 112, 112, 248, 5, 5, 5, 6, 0, 0, 248, 112, 112, 32, 32, 0,
+  0, 0, 6, 0, 0, 1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128,
+  0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6, 0, 0,
+  80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32, 120, 160,
+  112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32, 64, 152,
+  24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104, 2, 3,
+  3, 6, 1, 4, 192, 64, 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, 32, 168, 112, 168, 32, 5, 5, 5, 6,
+  0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192, 64, 128,
+  5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192, 192, 5,
+  5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6, 0, 0,
+  112, 136, 152, 168, 200, 136, 112, 3, 7, 7, 6, 1, 0, 64, 192, 64,
+  64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112, 128, 128,
+  248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240, 5, 7,
+  7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7, 6, 0,
+  0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0, 48, 64,
+  128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16, 32, 32,
+  32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136, 112, 5,
+  7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 16, 96, 2, 5, 5, 6,
+  2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192, 192, 0,
+  192, 64, 128, 4, 7, 7, 6, 0, 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, 8, 16,
+  32, 0, 32, 5, 6, 6, 6, 0, 0, 112, 136, 8, 104, 168, 112, 5,
+  7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5, 7, 7, 6,
+  0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6, 0, 0, 112,
+  136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 224, 144, 136, 136,
+  136, 144, 224, 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, 184, 136, 136, 112, 5, 7, 7, 6, 0, 0,
+  136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0, 128, 128, 128,
+  128, 128, 128, 128, 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, 216, 168, 136, 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,
+  7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5, 7, 7, 6,
+  0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6, 0, 0, 120,
+  128, 128, 112, 8, 8, 240, 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, 136, 136, 80, 32, 5, 7, 7,
+  6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7, 6, 0, 0,
+  136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0, 136, 136, 136,
+  80, 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, 5,
+  5, 6, 0, 1, 128, 64, 32, 16, 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, 0, 248, 2, 2, 2, 6, 2, 5, 128, 64, 5, 5,
+  5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7, 6, 0, 0, 128,
+  128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0, 112, 128, 128, 136,
+  112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136, 136, 120, 5, 5,
+  5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7, 6, 0, 0, 48,
+  72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255, 112, 136, 136, 120,
+  8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200, 136, 136, 136, 1,
+  7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128, 3, 8, 8, 6,
+  1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7, 7, 6, 0, 0,
+  128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1, 0, 192, 64, 64,
+  64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168, 168, 168, 168, 5,
+  5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5, 5, 6, 0, 0,
+  112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240, 136, 136, 240, 128,
+  128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 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, 224, 64, 64, 72, 48,
+  5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5, 5, 5, 6, 0,
+  0, 136, 136, 136, 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, 6, 6, 6,
+  0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6, 0, 0, 248, 16,
+  32, 64, 248, 3, 7, 7, 6, 1, 0, 32, 64, 64, 128, 64, 64, 32,
+  1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128, 128, 128, 3, 7, 7,
+  6, 1, 0, 128, 64, 64, 32, 64, 64, 128, 5, 6, 6, 6, 0, 1,
+  8, 40, 72, 248, 64, 32, 5, 7, 7, 6, 0, 0, 32, 80, 136, 136,
+  136, 136, 248, 5, 7, 7, 6, 0, 0, 248, 136, 128, 240, 136, 136, 240,
+  5, 8, 8, 6, 0, 255, 120, 40, 40, 40, 72, 136, 248, 136, 5, 7,
+  7, 6, 0, 0, 168, 168, 168, 112, 168, 168, 168, 5, 7, 7, 6, 0,
+  0, 240, 8, 8, 112, 8, 8, 240, 5, 7, 7, 6, 0, 0, 136, 136,
+  152, 168, 200, 136, 136, 5, 8, 8, 6, 0, 0, 80, 32, 136, 152, 168,
+  168, 200, 136, 5, 7, 7, 6, 0, 0, 120, 40, 40, 40, 40, 168, 72,
+  5, 7, 7, 6, 0, 0, 248, 136, 136, 136, 136, 136, 136, 5, 7, 7,
+  6, 0, 0, 136, 136, 136, 80, 32, 64, 128, 5, 8, 8, 6, 0, 255,
+  136, 136, 136, 136, 136, 136, 248, 8, 5, 7, 7, 6, 0, 0, 136, 136,
+  136, 120, 8, 8, 8, 5, 7, 7, 6, 0, 0, 168, 168, 168, 168, 168,
+  168, 248, 5, 8, 8, 6, 0, 255, 168, 168, 168, 168, 168, 168, 248, 8,
+  5, 7, 7, 6, 0, 0, 192, 64, 64, 112, 72, 72, 112, 5, 7, 7,
+  6, 0, 0, 136, 136, 136, 200, 168, 168, 200, 5, 7, 7, 6, 0, 0,
+  112, 136, 40, 80, 8, 136, 112, 5, 5, 5, 6, 0, 0, 64, 160, 144,
+  144, 104, 5, 7, 7, 6, 0, 0, 32, 48, 40, 40, 32, 224, 224, 5,
+  7, 7, 6, 0, 0, 248, 136, 128, 128, 128, 128, 128, 5, 5, 5, 6,
+  0, 0, 248, 80, 80, 80, 152, 5, 7, 7, 6, 0, 0, 248, 128, 64,
+  32, 64, 128, 248, 5, 5, 5, 6, 0, 0, 120, 144, 144, 144, 96, 5,
+  7, 7, 6, 0, 0, 48, 40, 56, 40, 200, 216, 24, 5, 6, 6, 6,
+  0, 0, 8, 112, 160, 32, 32, 16, 5, 6, 6, 6, 0, 1, 32, 112,
+  112, 112, 248, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136,
+  112, 5, 5, 5, 6, 0, 0, 112, 136, 136, 80, 216, 5, 7, 7, 6,
+  0, 0, 48, 72, 32, 80, 136, 136, 112, 5, 3, 3, 6, 0, 2, 88,
+  168, 208, 5, 6, 6, 6, 0, 0, 80, 248, 248, 248, 112, 32, 5, 5,
+  5, 6, 0, 0, 112, 128, 96, 136, 112, 5, 7, 7, 6, 0, 0, 112,
+  136, 136, 136, 136, 136, 136, 5, 7, 7, 6, 0, 0, 216, 216, 216, 216,
+  216, 216, 216, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128,
+  5, 7, 7, 6, 0, 0, 32, 112, 160, 160, 168, 112, 32, 5, 7, 7,
+  6, 0, 0, 48, 64, 64, 224, 64, 80, 168, 5, 5, 5, 6, 0, 0,
+  136, 112, 80, 112, 136, 5, 7, 7, 6, 0, 0, 136, 80, 248, 32, 248,
+  32, 32, 1, 7, 7, 6, 2, 0, 128, 128, 128, 0, 128, 128, 128, 5,
+  8, 8, 6, 0, 0, 48, 72, 32, 80, 80, 32, 144, 96, 5, 7, 7,
+  6, 0, 0, 24, 32, 32, 112, 32, 32, 192, 5, 7, 7, 6, 0, 0,
+  248, 136, 184, 184, 184, 136, 248, 5, 7, 7, 6, 0, 0, 112, 8, 120,
+  136, 120, 0, 248, 5, 5, 5, 6, 0, 1, 40, 80, 160, 80, 40, 5,
+  7, 7, 6, 0, 0, 144, 168, 168, 232, 168, 168, 144, 5, 7, 7, 6,
+  0, 0, 120, 136, 136, 120, 40, 72, 136, 5, 7, 7, 6, 0, 0, 248,
+  136, 168, 136, 152, 168, 248, 2, 3, 3, 6, 2, 4, 64, 128, 192, 4,
+  5, 5, 6, 0, 3, 96, 144, 144, 144, 96, 5, 7, 7, 6, 0, 0,
+  32, 32, 248, 32, 32, 0, 248, 4, 5, 5, 6, 0, 3, 96, 144, 32,
+  64, 240, 3, 5, 5, 6, 0, 3, 224, 32, 224, 32, 224, 5, 8, 8,
+  6, 0, 0, 224, 144, 224, 128, 144, 184, 144, 24, 5, 8, 8, 6, 0,
+  255, 136, 136, 136, 136, 152, 232, 128, 128, 5, 7, 7, 6, 0, 0, 120,
+  152, 152, 120, 24, 24, 24, 2, 2, 2, 6, 2, 2, 192, 192, 5, 5,
+  5, 6, 0, 0, 80, 136, 168, 168, 80, 3, 5, 5, 6, 0, 3, 64,
+  192, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 136, 136, 112, 0,
+  248, 5, 5, 5, 6, 0, 1, 160, 80, 40, 80, 160, 5, 7, 7, 6,
+  0, 0, 136, 144, 168, 88, 184, 8, 8, 5, 7, 7, 6, 0, 0, 136,
+  144, 184, 72, 152, 32, 56, 5, 8, 8, 6, 0, 0, 192, 64, 192, 72,
+  216, 56, 8, 8, 5, 7, 7, 6, 0, 0, 32, 0, 32, 64, 128, 136,
+  112, 5, 8, 8, 6, 0, 0, 64, 32, 32, 80, 136, 248, 136, 136, 5,
+  8, 8, 6, 0, 0, 16, 32, 32, 80, 136, 248, 136, 136, 5, 8, 8,
+  6, 0, 0, 32, 80, 0, 112, 136, 248, 136, 136, 5, 8, 8, 6, 0,
+  0, 104, 144, 0, 112, 136, 248, 136, 136, 5, 8, 8, 6, 0, 0, 80,
+  0, 32, 80, 136, 248, 136, 136, 5, 8, 8, 6, 0, 0, 32, 80, 32,
+  112, 136, 248, 136, 136, 5, 7, 7, 6, 0, 0, 56, 96, 160, 184, 224,
+  160, 184, 5, 8, 8, 6, 0, 255, 112, 136, 128, 128, 136, 112, 32, 96,
+  5, 8, 8, 6, 0, 0, 64, 32, 0, 248, 128, 240, 128, 248, 5, 8,
+  8, 6, 0, 0, 8, 16, 0, 248, 128, 240, 128, 248, 5, 8, 8, 6,
+  0, 0, 32, 80, 0, 248, 128, 240, 128, 248, 5, 7, 7, 6, 0, 0,
+  80, 0, 248, 128, 240, 128, 248, 3, 8, 8, 6, 1, 0, 128, 64, 0,
+  224, 64, 64, 64, 224, 3, 8, 8, 6, 1, 0, 32, 64, 0, 224, 64,
+  64, 64, 224, 3, 8, 8, 6, 1, 0, 64, 160, 0, 224, 64, 64, 64,
+  224, 3, 7, 7, 6, 1, 0, 160, 0, 224, 64, 64, 64, 224, 5, 7,
+  7, 6, 0, 0, 112, 72, 72, 232, 72, 72, 112, 5, 8, 8, 6, 0,
+  0, 104, 144, 0, 136, 200, 168, 152, 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, 0, 112, 136,
+  136, 136, 112, 5, 8, 8, 6, 0, 0, 104, 144, 0, 112, 136, 136, 136,
+  112, 5, 8, 8, 6, 0, 0, 80, 0, 112, 136, 136, 136, 136, 112, 5,
+  5, 5, 6, 0, 1, 136, 80, 32, 80, 136, 5, 7, 7, 6, 0, 0,
+  112, 32, 112, 168, 112, 32, 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, 80, 32, 32, 32, 32, 5, 8, 8,
+  6, 0, 0, 192, 64, 112, 72, 72, 112, 64, 224, 5, 7, 7, 6, 0,
+  0, 48, 72, 72, 112, 72, 72, 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, 104, 144, 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, 5, 6, 6, 6, 0,
+  0, 208, 40, 120, 160, 168, 80, 5, 6, 6, 6, 0, 255, 112, 128, 136,
+  112, 32, 96, 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, 64, 192, 64, 64, 224, 3, 8, 8, 6, 1, 0, 32, 64,
+  0, 64, 192, 64, 64, 224, 3, 8, 8, 6, 1, 0, 64, 160, 0, 64,
+  192, 64, 64, 224, 3, 7, 7, 6, 1, 0, 160, 0, 64, 192, 64, 64,
+  224, 5, 7, 7, 6, 0, 0, 160, 64, 160, 16, 120, 136, 112, 5, 8,
+  8, 6, 0, 0, 104, 144, 0, 176, 200, 136, 136, 136, 5, 8, 8, 6,
+  0, 0, 64, 32, 0, 112, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0,
+  16, 32, 0, 112, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 32, 80,
+  0, 112, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 104, 144, 0, 112,
+  136, 136, 136, 112, 5, 7, 7, 6, 0, 0, 80, 0, 112, 136, 136, 136,
+  112, 5, 5, 5, 6, 0, 1, 32, 0, 248, 0, 32, 5, 7, 7, 6,
+  0, 0, 16, 32, 112, 168, 112, 32, 64, 5, 8, 8, 6, 0, 0, 64,
+  32, 0, 136, 136, 136, 152, 104, 5, 8, 8, 6, 0, 0, 16, 32, 0,
+  136, 136, 136, 152, 104, 5, 8, 8, 6, 0, 0, 32, 80, 0, 136, 136,
+  136, 152, 104, 5, 7, 7, 6, 0, 0, 80, 0, 136, 136, 136, 152, 104,
+  5, 9, 9, 6, 0, 255, 16, 32, 0, 136, 136, 136, 248, 8, 112, 4,
+  7, 7, 6, 1, 0, 192, 64, 96, 80, 96, 64, 224, 5, 8, 8, 6,
+  0, 255, 80, 0, 136, 136, 136, 248, 8, 112
+};

+ 286 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_1.h

@@ -0,0 +1,286 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+  Fontname: ISO10646-1
+  Copyright: A.Hardtung, public domain
+  Capital A Height: 7, '1' Height: 7
+  Calculated Max Values w= 5 h= 9 x= 2 y= 7 dx= 6 dy= 0 ascent= 8 len= 9
+  Font Bounding box     w= 6 h= 9 x= 0 y=-2
+  Calculated Min Values           x= 0 y=-1 dx= 0 dy= 0
+  Pure Font   ascent = 7 descent=-1
+  X Font      ascent = 7 descent=-1
+  Max Font    ascent = 8 descent=-1
+*/
+#include <U8glib.h>
+
+#if defined(__AVR__) && ENABLED(NOT_EXTENDED_ISO10646_1_5X7)
+
+  //
+  // Reduced font (only symbols 32 - 127) - About 1400 bytes smaller
+  //
+  const u8g_fntpgm_uint8_t ISO10646_1_5x7[] U8G_SECTION(".progmem.ISO10646_1_5x7") = {
+    0,6,9,0,254,7,1,146,3,33,32,127,255,7,255,7,
+    255,0,0,0,6,0,0,1,7,7,6,2,0,128,128,128,
+    128,128,0,128,3,2,2,6,1,5,160,160,5,7,7,6,
+    0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,32,
+    120,160,112,40,240,32,5,7,7,6,0,0,192,200,16,32,
+    64,152,24,5,7,7,6,0,0,96,144,160,64,168,144,104,
+    2,3,3,6,1,4,192,64,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,32,168,112,168,32,5,5,
+    5,6,0,1,32,32,248,32,32,2,3,3,6,2,255,192,
+    64,128,5,1,1,6,0,3,248,2,2,2,6,2,0,192,
+    192,5,5,5,6,0,1,8,16,32,64,128,5,7,7,6,
+    0,0,112,136,136,136,136,136,112,3,7,7,6,1,0,64,
+    192,64,64,64,64,224,5,7,7,6,0,0,112,136,8,112,
+    128,128,248,5,7,7,6,0,0,248,16,32,16,8,8,240,
+    5,7,7,6,0,0,16,48,80,144,248,16,16,5,7,7,
+    6,0,0,248,128,240,8,8,136,112,5,7,7,6,0,0,
+    112,128,128,240,136,136,112,5,7,7,6,0,0,248,8,16,
+    32,32,32,32,5,7,7,6,0,0,112,136,136,112,136,136,
+    112,5,7,7,6,0,0,112,136,136,120,8,8,112,2,5,
+    5,6,2,0,192,192,0,192,192,2,6,6,6,2,255,192,
+    192,0,192,64,128,4,7,7,6,0,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,
+    8,16,32,0,32,5,7,7,6,0,0,112,136,8,104,168,
+    168,112,5,7,7,6,0,0,112,136,136,248,136,136,136,5,
+    7,7,6,0,0,240,136,136,240,136,136,240,5,7,7,6,
+    0,0,112,136,128,128,128,136,112,5,7,7,6,0,0,240,
+    136,136,136,136,136,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,184,136,136,112,5,7,7,
+    6,0,0,136,136,136,248,136,136,136,1,7,7,6,2,0,
+    128,128,128,128,128,128,128,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,216,168,136,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,7,7,6,0,0,112,136,136,136,168,144,104,5,
+    7,7,6,0,0,240,136,136,240,160,144,136,5,7,7,6,
+    0,0,120,128,128,112,8,8,240,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,136,136,80,32,
+    5,7,7,6,0,0,136,136,136,136,136,168,80,5,7,7,
+    6,0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,
+    136,136,136,80,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,5,5,6,0,1,128,64,32,16,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,0,248,2,2,2,6,2,5,128,
+    64,5,5,5,6,0,0,112,8,120,136,120,5,7,7,6,
+    0,0,128,128,176,200,136,136,240,5,5,5,6,0,0,112,
+    128,128,136,112,5,7,7,6,0,0,8,8,104,152,136,136,
+    120,5,5,5,6,0,0,112,136,248,128,112,5,7,7,6,
+    0,0,48,72,224,64,64,64,64,5,6,6,6,0,255,112,
+    136,136,120,8,112,5,7,7,6,0,0,128,128,176,200,136,
+    136,136,1,7,7,6,2,0,128,0,128,128,128,128,128,3,
+    8,8,6,1,255,32,0,32,32,32,32,160,64,4,7,7,
+    6,0,0,128,128,144,160,192,160,144,3,7,7,6,1,0,
+    192,64,64,64,64,64,224,5,5,5,6,0,0,208,168,168,
+    168,168,5,5,5,6,0,0,176,200,136,136,136,5,5,5,
+    6,0,0,112,136,136,136,112,5,6,6,6,0,255,240,136,
+    136,240,128,128,5,6,6,6,0,255,120,136,136,120,8,8,
+    5,5,5,6,0,0,176,200,128,128,128,5,5,5,6,0,
+    0,112,128,112,8,240,4,7,7,6,0,0,64,64,224,64,
+    64,64,48,5,5,5,6,0,0,136,136,136,152,104,5,5,
+    5,6,0,0,136,136,136,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,
+    6,6,6,0,255,136,136,136,120,8,112,5,5,5,6,0,
+    0,248,16,32,64,248,3,7,7,6,1,0,32,64,64,128,
+    64,64,32,1,7,7,6,2,0,128,128,128,128,128,128,128,
+    3,7,7,6,1,0,128,64,64,32,64,64,128,5,2,2,
+    6,0,2,104,144,0,0,0,6,0,0};
+
+#else
+
+  //
+  // Extended (original) font (symbols 32 - 255)
+  //
+  const u8g_fntpgm_uint8_t ISO10646_1_5x7[] U8G_SECTION(".progmem.ISO10646_1_5x7") = {
+    0, 6, 9, 0, 254, 7, 1, 146, 3, 33, 32, 255, 255, 8, 255, 7,
+    255, 0, 0, 0, 6, 0, 0, 1, 7, 7, 6, 2, 0, 128, 128, 128,
+    128, 128, 0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6,
+    0, 0, 80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32,
+    120, 160, 112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32,
+    64, 152, 24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104,
+    2, 3, 3, 6, 1, 4, 192, 64, 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, 32, 168, 112, 168, 32, 5, 5,
+    5, 6, 0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192,
+    64, 128, 5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192,
+    192, 5, 5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6,
+    0, 0, 112, 136, 136, 136, 136, 136, 112, 3, 7, 7, 6, 1, 0, 64,
+    192, 64, 64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112,
+    128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240,
+    5, 7, 7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7,
+    6, 0, 0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0,
+    112, 128, 128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16,
+    32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136,
+    112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 8, 112, 2, 5,
+    5, 6, 2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192,
+    192, 0, 192, 64, 128, 4, 7, 7, 6, 0, 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,
+    8, 16, 32, 0, 32, 5, 7, 7, 6, 0, 0, 112, 136, 8, 104, 168,
+    168, 112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5,
+    7, 7, 6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6,
+    0, 0, 112, 136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 240,
+    136, 136, 136, 136, 136, 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, 184, 136, 136, 112, 5, 7, 7,
+    6, 0, 0, 136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0,
+    128, 128, 128, 128, 128, 128, 128, 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, 216, 168, 136, 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, 7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5,
+    7, 7, 6, 0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6,
+    0, 0, 120, 128, 128, 112, 8, 8, 240, 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, 136, 136, 80, 32,
+    5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7,
+    6, 0, 0, 136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0,
+    136, 136, 136, 80, 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, 5, 5, 6, 0, 1, 128, 64, 32, 16, 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, 0, 248, 2, 2, 2, 6, 2, 5, 128,
+    64, 5, 5, 5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7, 6,
+    0, 0, 128, 128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0, 112,
+    128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136, 136,
+    120, 5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7, 6,
+    0, 0, 48, 72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255, 112,
+    136, 136, 120, 8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200, 136,
+    136, 136, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128, 3,
+    8, 8, 6, 1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7, 7,
+    6, 0, 0, 128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1, 0,
+    192, 64, 64, 64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168, 168,
+    168, 168, 5, 5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5, 5,
+    6, 0, 0, 112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240, 136,
+    136, 240, 128, 128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 8, 8,
+    5, 5, 5, 6, 0, 0, 176, 200, 128, 128, 128, 5, 5, 5, 6, 0,
+    0, 112, 128, 112, 8, 240, 4, 7, 7, 6, 0, 0, 64, 64, 224, 64,
+    64, 64, 48, 5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5, 5,
+    5, 6, 0, 0, 136, 136, 136, 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,
+    6, 6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6, 0,
+    0, 248, 16, 32, 64, 248, 3, 7, 7, 6, 1, 0, 32, 64, 64, 128,
+    64, 64, 32, 1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128, 128, 128,
+    3, 7, 7, 6, 1, 0, 128, 64, 64, 32, 64, 64, 128, 5, 2, 2,
+    6, 0, 2, 104, 144, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
+    0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
+    6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+    0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
+    0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
+    6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+    0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
+    0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
+    6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+    0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
+    0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
+    6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+    0, 0, 6, 0, 0, 0, 0, 0, 6, 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, 0, 32, 112, 168, 160, 168, 112, 32, 5, 7, 7, 6, 0,
+    0, 48, 64, 64, 224, 64, 80, 168, 5, 5, 5, 6, 0, 0, 136, 112,
+    80, 112, 136, 5, 7, 7, 6, 0, 0, 136, 80, 32, 248, 32, 248, 32,
+    1, 7, 7, 6, 2, 0, 128, 128, 128, 0, 128, 128, 128, 5, 8, 8,
+    6, 0, 0, 48, 72, 32, 80, 80, 32, 144, 96, 3, 1, 1, 6, 1,
+    7, 160, 5, 7, 7, 6, 0, 0, 248, 136, 184, 184, 184, 136, 248, 5,
+    7, 7, 6, 0, 1, 112, 8, 120, 136, 120, 0, 248, 5, 5, 5, 6,
+    0, 1, 40, 80, 160, 80, 40, 5, 3, 3, 6, 0, 1, 248, 8, 8,
+    2, 2, 2, 6, 2, 6, 64, 128, 5, 7, 7, 6, 0, 0, 248, 136,
+    168, 136, 152, 168, 248, 5, 1, 1, 6, 0, 6, 248, 4, 4, 4, 6,
+    0, 3, 96, 144, 144, 96, 5, 7, 7, 6, 0, 0, 32, 32, 248, 32,
+    32, 0, 248, 4, 5, 5, 6, 0, 3, 96, 144, 32, 64, 240, 3, 5,
+    5, 6, 0, 3, 224, 32, 224, 32, 224, 2, 2, 2, 6, 2, 6, 64,
+    128, 5, 8, 8, 6, 0, 255, 136, 136, 136, 136, 152, 232, 128, 128, 5,
+    7, 7, 6, 0, 0, 120, 152, 152, 120, 24, 24, 24, 2, 2, 2, 6,
+    2, 2, 192, 192, 2, 2, 2, 6, 2, 255, 64, 128, 3, 5, 5, 6,
+    0, 3, 64, 192, 64, 64, 224, 5, 7, 7, 6, 0, 1, 112, 136, 136,
+    136, 112, 0, 248, 5, 5, 5, 6, 0, 1, 160, 80, 40, 80, 160, 5,
+    7, 7, 6, 0, 0, 136, 144, 168, 88, 184, 8, 8, 5, 7, 7, 6,
+    0, 0, 136, 144, 184, 72, 152, 32, 56, 5, 8, 8, 6, 0, 0, 192,
+    64, 192, 72, 216, 56, 8, 8, 5, 7, 7, 6, 0, 0, 32, 0, 32,
+    64, 128, 136, 112, 5, 8, 8, 6, 0, 0, 64, 32, 0, 112, 136, 248,
+    136, 136, 5, 8, 8, 6, 0, 0, 16, 32, 0, 112, 136, 248, 136, 136,
+    5, 8, 8, 6, 0, 0, 32, 80, 0, 112, 136, 248, 136, 136, 5, 8,
+    8, 6, 0, 0, 104, 144, 0, 112, 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, 32, 112, 136, 248, 136, 136, 5, 7, 7, 6, 0, 0, 56, 96,
+    160, 184, 224, 160, 184, 5, 8, 8, 6, 0, 255, 112, 136, 128, 128, 136,
+    112, 32, 96, 5, 8, 8, 6, 0, 0, 64, 32, 0, 248, 128, 240, 128,
+    248, 5, 8, 8, 6, 0, 0, 8, 16, 0, 248, 128, 240, 128, 248, 5,
+    8, 8, 6, 0, 0, 32, 80, 0, 248, 128, 240, 128, 248, 5, 7, 7,
+    6, 0, 0, 80, 0, 248, 128, 240, 128, 248, 3, 8, 8, 6, 1, 0,
+    128, 64, 0, 224, 64, 64, 64, 224, 3, 8, 8, 6, 1, 0, 32, 64,
+    0, 224, 64, 64, 64, 224, 3, 8, 8, 6, 1, 0, 64, 160, 0, 224,
+    64, 64, 64, 224, 3, 7, 7, 6, 1, 0, 160, 0, 224, 64, 64, 64,
+    224, 5, 7, 7, 6, 0, 0, 112, 72, 72, 232, 72, 72, 112, 5, 8,
+    8, 6, 0, 0, 104, 144, 0, 136, 200, 168, 152, 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,
+    0, 112, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 104, 144, 0, 112,
+    136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 80, 0, 112, 136, 136, 136,
+    136, 112, 5, 5, 5, 6, 0, 1, 136, 80, 32, 80, 136, 5, 8, 8,
+    6, 0, 255, 16, 112, 168, 168, 168, 168, 112, 64, 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, 80, 32, 32, 32,
+    32, 5, 9, 9, 6, 0, 255, 192, 64, 112, 72, 72, 112, 64, 64, 224,
+    4, 8, 8, 6, 1, 255, 96, 144, 144, 160, 144, 144, 224, 128, 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, 104, 144,
+    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, 5, 6, 6, 6, 0, 0, 208, 40, 120, 160, 168, 80, 5, 6, 6,
+    6, 0, 255, 112, 128, 136, 112, 32, 96, 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, 64, 192, 64, 64, 224, 3, 8,
+    8, 6, 1, 0, 32, 64, 0, 64, 192, 64, 64, 224, 3, 8, 8, 6,
+    1, 0, 64, 160, 0, 64, 192, 64, 64, 224, 3, 7, 7, 6, 1, 0,
+    160, 0, 64, 192, 64, 64, 224, 5, 7, 7, 6, 0, 0, 160, 64, 160,
+    16, 120, 136, 112, 5, 8, 8, 6, 0, 0, 104, 144, 0, 176, 200, 136,
+    136, 136, 5, 8, 8, 6, 0, 0, 64, 32, 0, 112, 136, 136, 136, 112,
+    5, 8, 8, 6, 0, 0, 16, 32, 0, 112, 136, 136, 136, 112, 5, 8,
+    8, 6, 0, 0, 32, 80, 0, 112, 136, 136, 136, 112, 5, 8, 8, 6,
+    0, 0, 104, 144, 0, 112, 136, 136, 136, 112, 5, 7, 7, 6, 0, 0,
+    80, 0, 112, 136, 136, 136, 112, 5, 5, 5, 6, 0, 1, 32, 0, 248,
+    0, 32, 5, 7, 7, 6, 0, 255, 16, 112, 168, 168, 168, 112, 64, 5,
+    8, 8, 6, 0, 0, 64, 32, 0, 136, 136, 136, 152, 104, 5, 8, 8,
+    6, 0, 0, 16, 32, 0, 136, 136, 136, 152, 104, 5, 8, 8, 6, 0,
+    0, 32, 80, 0, 136, 136, 136, 152, 104, 5, 7, 7, 6, 0, 0, 80,
+    0, 136, 136, 136, 152, 104, 5, 9, 9, 6, 0, 255, 16, 32, 0, 136,
+    136, 136, 248, 8, 112, 4, 7, 7, 6, 1, 255, 192, 64, 96, 80, 96,
+    64, 224, 5, 8, 8, 6, 0, 255, 80, 0, 136, 136, 136, 120, 8, 112
+  };
+
+#endif

+ 184 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_1_PL.h

@@ -0,0 +1,184 @@
+/*
+  Fontname: ISO10646-1-PL
+  Copyright: A.Hardtung, public domain
+  Capital A Height: 7, '1' Height: 7
+  Calculated Max Values w= 5 h= 9 x= 2 y= 7 dx= 6 dy= 0 ascent= 8 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 = 7 descent=-1
+  X Font      ascent = 7 descent=-1
+  Max Font    ascent = 8 descent=-2
+*/
+#include <U8glib.h>
+const u8g_fntpgm_uint8_t ISO10646_1_PL_5x7[2732] U8G_FONT_SECTION(".progmem.ISO10646_1_PL_5x7") = {
+  0,6,9,0,254,7,1,146,3,33,32,255,255,8,254,7,
+  255,0,0,0,6,0,0,1,7,7,6,2,0,128,128,128,
+  128,128,0,128,3,2,2,6,1,5,160,160,5,7,7,6,
+  0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,32,
+  120,160,112,40,240,32,5,7,7,6,0,0,192,200,16,32,
+  64,152,24,5,7,7,6,0,0,96,144,160,64,168,144,104,
+  2,3,3,6,1,4,192,64,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,32,168,112,168,32,5,5,
+  5,6,0,1,32,32,248,32,32,2,3,3,6,2,255,192,
+  64,128,5,1,1,6,0,3,248,2,2,2,6,2,0,192,
+  192,5,5,5,6,0,1,8,16,32,64,128,5,7,7,6,
+  0,0,112,136,136,136,136,136,112,3,7,7,6,1,0,64,
+  192,64,64,64,64,224,5,7,7,6,0,0,112,136,8,112,
+  128,128,248,5,7,7,6,0,0,248,16,32,16,8,8,240,
+  5,7,7,6,0,0,16,48,80,144,248,16,16,5,7,7,
+  6,0,0,248,128,240,8,8,136,112,5,7,7,6,0,0,
+  112,128,128,240,136,136,112,5,7,7,6,0,0,248,8,16,
+  32,32,32,32,5,7,7,6,0,0,112,136,136,112,136,136,
+  112,5,7,7,6,0,0,112,136,136,120,8,8,112,2,5,
+  5,6,2,0,192,192,0,192,192,2,6,6,6,2,255,192,
+  192,0,192,64,128,4,7,7,6,0,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,
+  8,16,32,0,32,5,7,7,6,0,0,112,136,8,104,168,
+  168,112,5,7,7,6,0,0,112,136,136,248,136,136,136,5,
+  7,7,6,0,0,240,136,136,240,136,136,240,5,7,7,6,
+  0,0,112,136,128,128,128,136,112,5,7,7,6,0,0,240,
+  136,136,136,136,136,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,184,136,136,112,5,7,7,
+  6,0,0,136,136,136,248,136,136,136,1,7,7,6,2,0,
+  128,128,128,128,128,128,128,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,216,168,136,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,7,7,6,0,0,112,136,136,136,168,144,104,5,
+  7,7,6,0,0,240,136,136,240,160,144,136,5,7,7,6,
+  0,0,120,128,128,112,8,8,240,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,136,136,80,32,
+  5,7,7,6,0,0,136,136,136,136,136,168,80,5,7,7,
+  6,0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,
+  136,136,136,80,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,5,5,6,0,1,128,64,32,16,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,0,248,2,2,2,6,2,5,128,
+  64,5,5,5,6,0,0,112,8,120,136,120,5,7,7,6,
+  0,0,128,128,176,200,136,136,240,5,5,5,6,0,0,112,
+  128,128,136,112,5,7,7,6,0,0,8,8,104,152,136,136,
+  120,5,5,5,6,0,0,112,136,248,128,112,5,7,7,6,
+  0,0,48,72,224,64,64,64,64,5,6,6,6,0,255,112,
+  136,136,120,8,112,5,7,7,6,0,0,128,128,176,200,136,
+  136,136,1,7,7,6,2,0,128,0,128,128,128,128,128,3,
+  8,8,6,1,255,32,0,32,32,32,32,160,64,4,7,7,
+  6,0,0,128,128,144,160,192,160,144,3,7,7,6,1,0,
+  192,64,64,64,64,64,224,5,5,5,6,0,0,208,168,168,
+  168,168,5,5,5,6,0,0,176,200,136,136,136,5,5,5,
+  6,0,0,112,136,136,136,112,5,6,6,6,0,255,240,136,
+  136,240,128,128,5,6,6,6,0,255,120,136,136,120,8,8,
+  5,5,5,6,0,0,176,200,128,128,128,5,5,5,6,0,
+  0,112,128,112,8,240,4,7,7,6,0,0,64,64,224,64,
+  64,64,48,5,5,5,6,0,0,136,136,136,152,104,5,5,
+  5,6,0,0,136,136,136,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,
+  6,6,6,0,255,136,136,136,120,8,112,5,5,5,6,0,
+  0,248,16,32,64,248,3,7,7,6,1,0,32,64,64,128,
+  64,64,32,1,7,7,6,2,0,128,128,128,128,128,128,128,
+  3,7,7,6,1,0,128,64,64,32,64,64,128,5,2,2,
+  6,0,2,104,144,0,0,0,6,0,0,5,9,9,6,0,
+  254,112,136,136,248,136,136,136,16,32,5,7,7,6,0,254,
+  112,8,120,136,120,16,32,5,8,8,6,0,0,16,32,112,
+  136,128,128,136,112,5,7,7,6,0,0,16,32,112,128,128,
+  136,112,5,9,9,6,0,254,248,128,128,240,128,128,248,8,
+  16,5,7,7,6,0,254,112,136,248,128,112,16,32,5,7,
+  7,6,0,0,128,144,160,192,128,128,248,5,7,7,6,0,
+  0,96,40,48,96,160,32,112,5,8,8,6,0,0,16,168,
+  136,200,168,152,136,136,5,8,8,6,0,0,8,16,0,176,
+  200,136,136,136,5,8,8,6,0,0,16,32,112,136,136,136,
+  136,112,5,8,8,6,0,0,16,32,0,112,136,136,136,112,
+  5,8,8,6,0,0,16,120,128,128,112,8,8,240,5,8,
+  8,6,0,0,16,32,0,112,128,112,8,240,5,8,8,6,
+  0,0,32,248,8,16,32,64,128,248,5,8,8,6,0,0,
+  16,32,0,248,16,32,64,248,5,7,7,6,0,0,248,8,
+  16,248,64,128,248,5,8,8,6,0,0,48,48,0,248,16,
+  32,64,248,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,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,0,
+  32,112,168,160,168,112,32,5,7,7,6,0,0,48,64,64,
+  224,64,80,168,5,5,5,6,0,0,136,112,80,112,136,5,
+  7,7,6,0,0,136,80,32,248,32,248,32,1,7,7,6,
+  2,0,128,128,128,0,128,128,128,5,8,8,6,0,0,48,
+  72,32,80,80,32,144,96,3,1,1,6,1,7,160,5,7,
+  7,6,0,0,248,136,184,184,184,136,248,5,7,7,6,0,
+  1,112,8,120,136,120,0,248,5,5,5,6,0,1,40,80,
+  160,80,40,5,3,3,6,0,1,248,8,8,2,2,2,6,
+  2,6,64,128,5,7,7,6,0,0,248,136,168,136,152,168,
+  248,5,1,1,6,0,6,248,4,4,4,6,0,3,96,144,
+  144,96,5,7,7,6,0,0,32,32,248,32,32,0,248,4,
+  5,5,6,0,3,96,144,32,64,240,3,5,5,6,0,3,
+  224,32,224,32,224,2,2,2,6,2,6,64,128,5,8,8,
+  6,0,255,136,136,136,136,152,232,128,128,5,7,7,6,0,
+  0,120,152,152,120,24,24,24,2,2,2,6,2,2,192,192,
+  2,2,2,6,2,255,64,128,3,5,5,6,0,3,64,192,
+  64,64,224,5,7,7,6,0,1,112,136,136,136,112,0,248,
+  5,5,5,6,0,1,160,80,40,80,160,5,7,7,6,0,
+  0,136,144,168,88,184,8,8,5,7,7,6,0,0,136,144,
+  184,72,152,32,56,5,8,8,6,0,0,192,64,192,72,216,
+  56,8,8,5,7,7,6,0,0,32,0,32,64,128,136,112,
+  5,8,8,6,0,0,64,32,0,112,136,248,136,136,5,8,
+  8,6,0,0,16,32,0,112,136,248,136,136,5,8,8,6,
+  0,0,32,80,0,112,136,248,136,136,5,8,8,6,0,0,
+  104,144,0,112,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,32,112,
+  136,248,136,136,5,7,7,6,0,0,56,96,160,184,224,160,
+  184,5,8,8,6,0,255,112,136,128,128,136,112,32,96,5,
+  8,8,6,0,0,64,32,0,248,128,240,128,248,5,8,8,
+  6,0,0,8,16,0,248,128,240,128,248,5,8,8,6,0,
+  0,32,80,0,248,128,240,128,248,5,7,7,6,0,0,80,
+  0,248,128,240,128,248,3,8,8,6,1,0,128,64,0,224,
+  64,64,64,224,3,8,8,6,1,0,32,64,0,224,64,64,
+  64,224,3,8,8,6,1,0,64,160,0,224,64,64,64,224,
+  3,7,7,6,1,0,160,0,224,64,64,64,224,5,7,7,
+  6,0,0,112,72,72,232,72,72,112,5,8,8,6,0,0,
+  104,144,0,136,200,168,152,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,0,112,136,136,
+  136,112,5,8,8,6,0,0,104,144,0,112,136,136,136,112,
+  5,8,8,6,0,0,80,0,112,136,136,136,136,112,5,5,
+  5,6,0,1,136,80,32,80,136,5,8,8,6,0,255,16,
+  112,168,168,168,168,112,64,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,80,32,32,32,32,5,9,9,
+  6,0,255,192,64,112,72,72,112,64,64,224,4,8,8,6,
+  1,255,96,144,144,160,144,144,224,128,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,104,144,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,5,6,6,
+  6,0,0,208,40,120,160,168,80,5,6,6,6,0,255,112,
+  128,136,112,32,96,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,64,192,64,64,224,3,8,8,6,1,0,
+  32,64,0,64,192,64,64,224,3,8,8,6,1,0,64,160,
+  0,64,192,64,64,224,3,7,7,6,1,0,160,0,64,192,
+  64,64,224,5,7,7,6,0,0,160,64,160,16,120,136,112,
+  5,8,8,6,0,0,104,144,0,176,200,136,136,136,5,8,
+  8,6,0,0,64,32,0,112,136,136,136,112,5,8,8,6,
+  0,0,16,32,0,112,136,136,136,112,5,8,8,6,0,0,
+  32,80,0,112,136,136,136,112,5,8,8,6,0,0,104,144,
+  0,112,136,136,136,112,5,7,7,6,0,0,80,0,112,136,
+  136,136,112,5,5,5,6,0,1,32,0,248,0,32,5,7,
+  7,6,0,255,16,112,168,168,168,112,64,5,8,8,6,0,
+  0,64,32,0,136,136,136,152,104,5,8,8,6,0,0,16,
+  32,0,136,136,136,152,104,5,8,8,6,0,0,32,80,0,
+  136,136,136,152,104,5,7,7,6,0,0,80,0,136,136,136,
+  152,104,5,9,9,6,0,255,16,32,0,136,136,136,248,8,
+  112,4,7,7,6,1,255,192,64,96,80,96,64,224,5,8,
+  8,6,0,255,80,0,136,136,136,120,8,112};

+ 197 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_1_tr.h

@@ -0,0 +1,197 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+  Fontname: ISO10646-1-tr
+  Copyright: public domain
+  Capital A Height: 7, '1' Height: 7
+  Calculated Max Values w= 5 h= 9 x= 2 y= 7 dx= 6 dy= 0 ascent= 8 len= 9
+  Font Bounding box     w= 6 h= 9 x= 0 y=-2
+  Calculated Min Values           x= 0 y=-1 dx= 0 dy= 0
+  Pure Font   ascent = 7 descent=-1
+  X Font      ascent = 7 descent=-1
+  Max Font    ascent = 8 descent=-1
+*/
+#include <U8glib.h>
+const u8g_fntpgm_uint8_t ISO10646_TR[2591] U8G_SECTION(".progmem.ISO10646_TR") = {
+  0,6,9,0,254,7,1,146,3,33,32,255,255,8,255,7,
+  255,0,0,0,6,0,0,1,7,7,6,2,0,128,128,128,
+  128,128,0,128,3,2,2,6,1,5,160,160,5,7,7,6,
+  0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,32,
+  120,160,112,40,240,32,5,7,7,6,0,0,192,200,16,32,
+  64,152,24,5,7,7,6,0,0,96,144,160,64,168,144,104,
+  2,3,3,6,1,4,192,64,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,32,168,112,168,32,5,5,
+  5,6,0,1,32,32,248,32,32,2,3,3,6,2,255,192,
+  64,128,5,1,1,6,0,3,248,2,2,2,6,2,0,192,
+  192,5,5,5,6,0,1,8,16,32,64,128,5,7,7,6,
+  0,0,112,136,136,136,136,136,112,3,7,7,6,1,0,64,
+  192,64,64,64,64,224,5,7,7,6,0,0,112,136,8,112,
+  128,128,248,5,7,7,6,0,0,248,16,32,16,8,8,240,
+  5,7,7,6,0,0,16,48,80,144,248,16,16,5,7,7,
+  6,0,0,248,128,240,8,8,136,112,5,7,7,6,0,0,
+  112,128,128,240,136,136,112,5,7,7,6,0,0,248,8,16,
+  32,32,32,32,5,7,7,6,0,0,112,136,136,112,136,136,
+  112,5,7,7,6,0,0,112,136,136,120,8,8,112,2,5,
+  5,6,2,0,192,192,0,192,192,2,6,6,6,2,255,192,
+  192,0,192,64,128,4,7,7,6,0,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,
+  8,16,32,0,32,5,7,7,6,0,0,112,136,8,104,168,
+  168,112,5,7,7,6,0,0,112,136,136,248,136,136,136,5,
+  7,7,6,0,0,240,136,136,240,136,136,240,5,7,7,6,
+  0,0,112,136,128,128,128,136,112,5,7,7,6,0,0,240,
+  136,136,136,136,136,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,184,136,136,112,5,7,7,
+  6,0,0,136,136,136,248,136,136,136,1,7,7,6,2,0,
+  128,128,128,128,128,128,128,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,216,168,136,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,7,7,6,0,0,112,136,136,136,168,144,104,5,
+  7,7,6,0,0,240,136,136,240,160,144,136,5,7,7,6,
+  0,0,120,128,128,112,8,8,240,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,136,136,80,32,
+  5,7,7,6,0,0,136,136,136,136,136,168,80,5,7,7,
+  6,0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,
+  136,136,136,80,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,5,5,6,0,1,128,64,32,16,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,0,248,2,2,2,6,2,5,128,
+  64,5,5,5,6,0,0,112,8,120,136,120,5,7,7,6,
+  0,0,128,128,176,200,136,136,240,5,5,5,6,0,0,112,
+  128,128,136,112,5,7,7,6,0,0,8,8,104,152,136,136,
+  120,5,5,5,6,0,0,112,136,248,128,112,5,7,7,6,
+  0,0,48,72,224,64,64,64,64,5,6,6,6,0,255,112,
+  136,136,120,8,112,5,7,7,6,0,0,128,128,176,200,136,
+  136,136,1,7,7,6,2,0,128,0,128,128,128,128,128,3,
+  8,8,6,1,255,32,0,32,32,32,32,160,64,4,7,7,
+  6,0,0,128,128,144,160,192,160,144,3,7,7,6,1,0,
+  192,64,64,64,64,64,224,5,5,5,6,0,0,208,168,168,
+  168,168,5,5,5,6,0,0,176,200,136,136,136,5,5,5,
+  6,0,0,112,136,136,136,112,5,6,6,6,0,255,240,136,
+  136,240,128,128,5,6,6,6,0,255,120,136,136,120,8,8,
+  5,5,5,6,0,0,176,200,128,128,128,5,5,5,6,0,
+  0,112,128,112,8,240,4,7,7,6,0,0,64,64,224,64,
+  64,64,48,5,5,5,6,0,0,136,136,136,152,104,5,5,
+  5,6,0,0,136,136,136,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,
+  6,6,6,0,255,136,136,136,120,8,112,5,5,5,6,0,
+  0,248,16,32,64,248,3,7,7,6,1,0,32,64,64,128,
+  64,64,32,1,7,7,6,2,0,128,128,128,128,128,128,128,
+  3,7,7,6,1,0,128,64,64,32,64,64,128,5,2,2,
+  6,0,2,104,144,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,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,0,32,112,168,160,168,112,32,5,7,7,6,0,
+  0,48,64,64,224,64,80,168,5,5,5,6,0,0,136,112,
+  80,112,136,5,7,7,6,0,0,136,80,32,248,32,248,32,
+  1,7,7,6,2,0,128,128,128,0,128,128,128,5,8,8,
+  6,0,0,48,72,32,80,80,32,144,96,3,1,1,6,1,
+  7,160,5,7,7,6,0,0,248,136,184,184,184,136,248,5,
+  7,7,6,0,1,112,8,120,136,120,0,248,5,5,5,6,
+  0,1,40,80,160,80,40,5,3,3,6,0,1,248,8,8,
+  2,2,2,6,2,6,64,128,5,7,7,6,0,0,248,136,
+  168,136,152,168,248,5,1,1,6,0,6,248,4,4,4,6,
+  0,3,96,144,144,96,5,7,7,6,0,0,32,32,248,32,
+  32,0,248,4,5,5,6,0,3,96,144,32,64,240,3,5,
+  5,6,0,3,224,32,224,32,224,2,2,2,6,2,6,64,
+  128,5,8,8,6,0,255,136,136,136,136,152,232,128,128,5,
+  7,7,6,0,0,120,152,152,120,24,24,24,2,2,2,6,
+  2,2,192,192,2,2,2,6,2,255,64,128,3,5,5,6,
+  0,3,64,192,64,64,224,5,7,7,6,0,1,112,136,136,
+  136,112,0,248,5,5,5,6,0,1,160,80,40,80,160,5,
+  7,7,6,0,0,136,144,168,88,184,8,8,5,7,7,6,
+  0,0,136,144,184,72,152,32,56,5,8,8,6,0,0,192,
+  64,192,72,216,56,8,8,5,7,7,6,0,0,32,0,32,
+  64,128,136,112,5,8,8,6,0,0,64,32,0,112,136,248,
+  136,136,5,8,8,6,0,0,16,32,0,112,136,248,136,136,
+  5,8,8,6,0,0,32,80,0,112,136,248,136,136,5,8,
+  8,6,0,0,104,144,0,112,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,32,112,136,248,136,136,5,7,7,6,0,0,56,96,
+  160,184,224,160,184,5,8,8,6,0,255,112,136,128,128,136,
+  112,32,96,5,8,8,6,0,0,64,32,0,248,128,240,128,
+  248,5,8,8,6,0,0,8,16,0,248,128,240,128,248,5,
+  8,8,6,0,0,32,80,0,248,128,240,128,248,5,7,7,
+  6,0,0,80,0,248,128,240,128,248,3,8,8,6,1,0,
+  128,64,0,224,64,64,64,224,3,8,8,6,1,0,32,64,
+  0,224,64,64,64,224,3,8,8,6,1,0,64,160,0,224,
+  64,64,64,224,3,7,7,6,1,0,160,0,224,64,64,64,
+  224,5,9,9,6,0,255,80,32,112,136,128,184,136,136,112,
+  5,8,8,6,0,0,104,144,0,136,200,168,152,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,0,112,136,136,136,112,5,8,8,6,0,0,104,144,
+  0,112,136,136,136,112,5,8,8,6,0,0,80,0,112,136,
+  136,136,136,112,5,5,5,6,0,1,136,80,32,80,136,5,
+  8,8,6,0,255,16,112,168,168,168,168,112,64,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,1,7,7,6,2,0,128,0,128,128,128,
+  128,128,5,9,9,6,0,255,120,128,128,112,8,8,240,32,
+  96,4,8,8,6,1,255,96,144,144,160,144,144,224,128,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,104,
+  144,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,5,6,6,6,0,0,208,40,120,160,168,80,5,7,
+  7,6,0,255,112,128,128,136,112,32,96,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,64,192,64,64,224,
+  3,8,8,6,1,0,32,64,0,64,192,64,64,224,3,8,
+  8,6,1,0,64,160,0,64,192,64,64,224,3,7,7,6,
+  1,0,160,0,64,192,64,64,224,5,8,8,6,0,255,80,
+  32,112,136,136,120,8,112,5,8,8,6,0,0,104,144,0,
+  176,200,136,136,136,5,8,8,6,0,0,64,32,0,112,136,
+  136,136,112,5,8,8,6,0,0,16,32,0,112,136,136,136,
+  112,5,8,8,6,0,0,32,80,0,112,136,136,136,112,5,
+  8,8,6,0,0,104,144,0,112,136,136,136,112,5,7,7,
+  6,0,0,80,0,112,136,136,136,112,5,5,5,6,0,1,
+  32,0,248,0,32,5,7,7,6,0,255,16,112,168,168,168,
+  112,64,5,8,8,6,0,0,64,32,0,136,136,136,152,104,
+  5,8,8,6,0,0,16,32,0,136,136,136,152,104,5,8,
+  8,6,0,0,32,80,0,136,136,136,152,104,5,7,7,6,
+  0,0,80,0,136,136,136,152,104,1,5,5,6,2,0,128,
+  128,128,128,128,5,7,7,6,0,255,112,128,112,8,240,32,
+  96,5,8,8,6,0,255,80,0,136,136,136,120,8,112};

+ 196 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_5_Cyrillic.h

@@ -0,0 +1,196 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+  Fontname: ISO10646_5_Cyrillic
+  Copyright: A. Hardtung, public domain
+  Capital A Height: 7, '1' Height: 7
+  Calculated Max Values w= 5 h= 9 x= 2 y= 5 dx= 6 dy= 0 ascent= 8 len= 9
+  Font Bounding box     w= 6 h= 9 x= 0 y=-2
+  Calculated Min Values           x= 0 y=-1 dx= 0 dy= 0
+  Pure Font   ascent = 7 descent=-1
+  X Font      ascent = 7 descent=-1
+  Max Font    ascent = 8 descent=-1
+*/
+#include <U8glib.h>
+const u8g_fntpgm_uint8_t ISO10646_5_Cyrillic_5x7[2560] U8G_SECTION(".progmem.ISO10646_5_Cyrillic_5x7") = {
+  0, 6, 9, 0, 254, 7, 1, 145, 3, 32, 32, 255, 255, 8, 255, 7,
+  255, 0, 0, 0, 6, 0, 0, 1, 7, 7, 6, 2, 0, 128, 128, 128,
+  128, 128, 0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6,
+  0, 0, 80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32,
+  120, 160, 112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32,
+  64, 152, 24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104,
+  2, 3, 3, 6, 1, 4, 192, 64, 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, 32, 168, 112, 168, 32, 5, 5,
+  5, 6, 0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192,
+  64, 128, 5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192,
+  192, 5, 5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6,
+  0, 0, 112, 136, 152, 168, 200, 136, 112, 3, 7, 7, 6, 1, 0, 64,
+  192, 64, 64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112,
+  128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240,
+  5, 7, 7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7,
+  6, 0, 0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0,
+  48, 64, 128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16,
+  32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136,
+  112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 16, 96, 2, 5,
+  5, 6, 2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192,
+  192, 0, 192, 64, 128, 4, 7, 7, 6, 0, 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,
+  8, 16, 32, 0, 32, 5, 6, 6, 6, 0, 0, 112, 136, 8, 104, 168,
+  112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5, 7,
+  7, 6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6, 0,
+  0, 112, 136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 224, 144,
+  136, 136, 136, 144, 224, 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, 184, 136, 136, 112, 5, 7, 7, 6,
+  0, 0, 136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0, 128,
+  128, 128, 128, 128, 128, 128, 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, 216, 168, 136, 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, 7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5, 7,
+  7, 6, 0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6, 0,
+  0, 120, 128, 128, 112, 8, 8, 240, 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, 136, 136, 80, 32, 5,
+  7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7, 6,
+  0, 0, 136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0, 136,
+  136, 136, 80, 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, 5, 5, 6, 0, 1, 128, 64, 32, 16, 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, 0, 248, 2, 2, 2, 6, 2, 5, 128, 64,
+  5, 5, 5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7, 6, 0,
+  0, 128, 128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0, 112, 128,
+  128, 136, 112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136, 136, 120,
+  5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7, 6, 0,
+  0, 48, 72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255, 112, 136,
+  136, 120, 8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200, 136, 136,
+  136, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128, 3, 8,
+  8, 6, 1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7, 7, 6,
+  0, 0, 128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1, 0, 192,
+  64, 64, 64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168, 168, 168,
+  168, 5, 5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5, 5, 6,
+  0, 0, 112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240, 136, 136,
+  240, 128, 128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 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, 224, 64, 64,
+  72, 48, 5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5, 5, 5,
+  6, 0, 0, 136, 136, 136, 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, 6,
+  6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6, 0, 0,
+  248, 16, 32, 64, 248, 3, 7, 7, 6, 1, 0, 32, 64, 64, 128, 64,
+  64, 32, 1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128, 128, 128, 3,
+  7, 7, 6, 1, 0, 128, 64, 64, 32, 64, 64, 128, 5, 2, 2, 6,
+  0, 3, 104, 144, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
+  0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
+  0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+  0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
+  0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
+  0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+  0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
+  0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
+  0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+  0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
+  0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
+  0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+  0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 5, 8, 8, 6, 0, 0,
+  64, 248, 128, 128, 240, 128, 128, 248, 5, 8, 8, 6, 0, 0, 80, 248,
+  128, 128, 240, 128, 128, 248, 5, 7, 7, 6, 0, 0, 224, 64, 64, 112,
+  72, 72, 112, 5, 8, 8, 6, 0, 0, 16, 32, 248, 136, 128, 128, 128,
+  128, 5, 7, 7, 6, 0, 0, 48, 72, 128, 224, 128, 72, 48, 5, 7,
+  7, 6, 0, 0, 112, 136, 128, 112, 8, 136, 112, 3, 7, 7, 6, 1,
+  0, 224, 64, 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, 56, 16, 16, 16,
+  16, 144, 96, 5, 7, 7, 6, 0, 0, 160, 160, 160, 184, 168, 168, 184,
+  5, 7, 7, 6, 0, 0, 160, 160, 160, 248, 168, 168, 184, 4, 7, 7,
+  6, 0, 0, 224, 64, 112, 80, 80, 80, 80, 5, 8, 8, 6, 0, 0,
+  16, 32, 136, 144, 160, 224, 144, 136, 5, 8, 8, 6, 0, 0, 64, 32,
+  136, 152, 168, 200, 136, 136, 5, 9, 9, 6, 0, 255, 80, 32, 136, 136,
+  136, 80, 32, 32, 32, 5, 8, 8, 6, 0, 255, 136, 136, 136, 136, 136,
+  136, 248, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136,
+  5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 136, 136, 240, 5, 7, 7,
+  6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6, 0, 0,
+  248, 136, 128, 128, 128, 128, 128, 5, 8, 8, 6, 0, 255, 120, 40, 40,
+  40, 72, 136, 248, 136, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128,
+  128, 248, 5, 7, 7, 6, 0, 0, 168, 168, 168, 112, 168, 168, 168, 5,
+  7, 7, 6, 0, 0, 240, 8, 8, 112, 8, 8, 240, 5, 7, 7, 6,
+  0, 0, 136, 136, 152, 168, 200, 136, 136, 5, 8, 8, 6, 0, 0, 80,
+  32, 136, 152, 168, 168, 200, 136, 5, 7, 7, 6, 0, 0, 136, 144, 160,
+  192, 160, 144, 136, 5, 7, 7, 6, 0, 0, 120, 40, 40, 40, 40, 168,
+  72, 5, 7, 7, 6, 0, 0, 136, 216, 168, 136, 136, 136, 136, 5, 7,
+  7, 6, 0, 0, 136, 136, 136, 248, 136, 136, 136, 5, 7, 7, 6, 0,
+  0, 112, 136, 136, 136, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 136,
+  136, 136, 136, 136, 136, 5, 7, 7, 6, 0, 0, 240, 136, 136, 240, 128,
+  128, 128, 5, 7, 7, 6, 0, 0, 112, 136, 128, 128, 128, 136, 112, 5,
+  7, 7, 6, 0, 0, 248, 32, 32, 32, 32, 32, 32, 5, 7, 7, 6,
+  0, 0, 136, 136, 136, 80, 32, 64, 128, 5, 7, 7, 6, 0, 0, 32,
+  112, 168, 168, 168, 112, 32, 5, 7, 7, 6, 0, 0, 136, 136, 80, 32,
+  80, 136, 136, 5, 8, 8, 6, 0, 255, 136, 136, 136, 136, 136, 136, 248,
+  8, 5, 7, 7, 6, 0, 0, 136, 136, 136, 152, 104, 8, 8, 5, 7,
+  7, 6, 0, 0, 168, 168, 168, 168, 168, 168, 248, 5, 8, 8, 6, 0,
+  255, 168, 168, 168, 168, 168, 168, 248, 8, 5, 7, 7, 6, 0, 0, 192,
+  64, 64, 112, 72, 72, 112, 5, 7, 7, 6, 0, 0, 136, 136, 136, 200,
+  168, 168, 200, 5, 7, 7, 6, 0, 0, 128, 128, 128, 240, 136, 136, 240,
+  5, 7, 7, 6, 0, 0, 112, 136, 8, 56, 8, 136, 112, 5, 7, 7,
+  6, 0, 0, 144, 168, 168, 232, 168, 168, 144, 5, 7, 7, 6, 0, 0,
+  120, 136, 136, 120, 40, 72, 136, 5, 5, 5, 6, 0, 0, 112, 8, 120,
+  136, 120, 5, 7, 7, 6, 0, 0, 24, 96, 128, 240, 136, 136, 112, 4,
+  5, 5, 6, 0, 0, 224, 144, 224, 144, 224, 5, 5, 5, 6, 0, 0,
+  248, 136, 128, 128, 128, 5, 6, 6, 6, 0, 255, 120, 40, 72, 136, 248,
+  136, 5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 5, 5, 6,
+  0, 0, 168, 168, 112, 168, 168, 5, 5, 5, 6, 0, 0, 240, 8, 48,
+  8, 240, 5, 5, 5, 6, 0, 0, 136, 152, 168, 200, 136, 5, 7, 7,
+  6, 0, 0, 80, 32, 136, 152, 168, 200, 136, 4, 5, 5, 6, 0, 0,
+  144, 160, 192, 160, 144, 5, 5, 5, 6, 0, 0, 248, 40, 40, 168, 72,
+  5, 5, 5, 6, 0, 0, 136, 216, 168, 136, 136, 5, 5, 5, 6, 0,
+  0, 136, 136, 248, 136, 136, 5, 5, 5, 6, 0, 0, 112, 136, 136, 136,
+  112, 5, 5, 5, 6, 0, 0, 248, 136, 136, 136, 136, 5, 6, 6, 6,
+  0, 255, 240, 136, 136, 240, 128, 128, 5, 5, 5, 6, 0, 0, 112, 128,
+  128, 136, 112, 5, 5, 5, 6, 0, 0, 248, 32, 32, 32, 32, 5, 6,
+  6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 6, 6, 6, 0, 0,
+  32, 112, 168, 168, 112, 32, 5, 5, 5, 6, 0, 0, 136, 80, 32, 80,
+  136, 5, 6, 6, 6, 0, 255, 136, 136, 136, 136, 248, 8, 5, 5, 5,
+  6, 0, 0, 136, 136, 248, 8, 8, 5, 5, 5, 6, 0, 0, 168, 168,
+  168, 168, 248, 5, 6, 6, 6, 0, 255, 168, 168, 168, 168, 248, 8, 5,
+  5, 5, 6, 0, 0, 192, 64, 112, 72, 112, 5, 5, 5, 6, 0, 0,
+  136, 136, 200, 168, 200, 3, 5, 5, 6, 1, 0, 128, 128, 192, 160, 192,
+  5, 5, 5, 6, 0, 0, 112, 136, 56, 136, 112, 5, 5, 5, 6, 0,
+  0, 144, 168, 232, 168, 144, 5, 5, 5, 6, 0, 0, 120, 136, 120, 40,
+  72, 5, 8, 8, 6, 0, 0, 64, 32, 0, 112, 136, 248, 128, 112, 5,
+  7, 7, 6, 0, 0, 80, 0, 112, 136, 248, 128, 112, 5, 9, 9, 6,
+  0, 255, 64, 224, 64, 64, 120, 72, 72, 72, 16, 5, 8, 8, 6, 0,
+  0, 16, 32, 0, 248, 136, 128, 128, 128, 5, 5, 5, 6, 0, 0, 112,
+  136, 96, 136, 112, 5, 5, 5, 6, 0, 0, 112, 128, 112, 8, 240, 1,
+  7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128, 3, 7, 7, 6,
+  1, 0, 160, 0, 64, 64, 64, 64, 64, 3, 8, 8, 6, 1, 255, 32,
+  0, 32, 32, 32, 32, 160, 64, 5, 5, 5, 6, 0, 0, 160, 160, 184,
+  168, 184, 5, 5, 5, 6, 0, 0, 160, 160, 248, 168, 184, 5, 6, 6,
+  6, 0, 0, 64, 224, 64, 120, 72, 72, 4, 8, 8, 6, 0, 0, 16,
+  32, 0, 144, 160, 192, 160, 144, 5, 8, 8, 6, 0, 0, 64, 32, 0,
+  136, 152, 168, 200, 136, 5, 9, 9, 6, 0, 255, 80, 32, 0, 136, 136,
+  136, 120, 8, 112, 5, 6, 6, 6, 0, 255, 136, 136, 136, 136, 248, 32
+};

+ 293 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_CN.h

@@ -0,0 +1,293 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+  Fontname: ISO10646_CN
+  Copyright: A. Hardtung, public domain
+  Capital A Height: 7, '1' Height: 7
+  Calculated Max Values w=11 h=11 x= 2 y=10 dx=12 dy= 0 ascent=10 len=22
+  Font Bounding box     w=12 h=11 x= 0 y=-2
+  Calculated Min Values           x= 0 y=-1 dx= 0 dy= 0
+  Pure Font   ascent = 7 descent=-1
+  X Font      ascent = 7 descent=-1
+  Max Font    ascent =10 descent=-1
+*/
+#include <U8glib.h>
+const u8g_fntpgm_uint8_t ISO10646_CN[4105] U8G_SECTION(".progmem.ISO10646_CN") = {
+  0, 12, 11, 0, 254, 7, 1, 146, 3, 33, 32, 255, 255, 10, 255, 7,
+  255, 0, 0, 0, 6, 0, 10, 1, 7, 7, 6, 2, 0, 128, 128, 128,
+  128, 128, 0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6,
+  0, 0, 80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32,
+  120, 160, 112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32,
+  64, 152, 24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104,
+  2, 3, 3, 6, 1, 4, 192, 64, 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, 32, 168, 112, 168, 32, 5, 5,
+  5, 6, 0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192,
+  64, 128, 5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192,
+  192, 5, 5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6,
+  0, 0, 112, 136, 152, 168, 200, 136, 112, 3, 7, 7, 6, 1, 0, 64,
+  192, 64, 64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112,
+  128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240,
+  5, 7, 7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7,
+  6, 0, 0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0,
+  112, 128, 128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16,
+  32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136,
+  112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 8, 112, 2, 5,
+  5, 6, 2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192,
+  192, 0, 192, 64, 128, 4, 7, 7, 6, 0, 0, 16, 32, 64, 128, 64,
+  32, 16, 5, 3, 3, 6, 0, 2, 248, 0, 248, 4, 7, 7, 6, 0,
+  0, 128, 64, 32, 16, 32, 64, 128, 5, 7, 7, 6, 0, 0, 112, 136,
+  8, 16, 32, 0, 32, 5, 7, 7, 6, 0, 0, 112, 136, 8, 104, 168,
+  168, 112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5,
+  7, 7, 6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6,
+  0, 0, 112, 136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 240,
+  136, 136, 136, 136, 136, 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, 184, 136, 136, 112, 5, 7, 7,
+  6, 0, 0, 136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0,
+  128, 128, 128, 128, 128, 128, 128, 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, 216, 168, 136, 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, 7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5,
+  7, 7, 6, 0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6,
+  0, 0, 120, 128, 128, 112, 8, 8, 240, 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, 136, 136, 80, 32,
+  5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7,
+  6, 0, 0, 136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0,
+  136, 136, 136, 80, 32, 32, 32, 5, 7, 7, 6, 0, 0, 248, 8, 16,
+  32, 64, 128, 248, 3, 7, 7, 6, 0, 0, 224, 128, 128, 128, 128, 128,
+  224, 5, 5, 5, 6, 0, 1, 128, 64, 32, 16, 8, 3, 7, 7, 6,
+  0, 0, 224, 32, 32, 32, 32, 32, 224, 5, 3, 3, 6, 0, 4, 32,
+  80, 136, 5, 1, 1, 6, 0, 0, 248, 2, 2, 2, 6, 2, 5, 128,
+  64, 5, 5, 5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7, 6,
+  0, 0, 128, 128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0, 112,
+  128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136, 136,
+  120, 5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7, 6,
+  0, 0, 48, 72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255, 112,
+  136, 136, 120, 8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200, 136,
+  136, 136, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128, 3,
+  8, 8, 6, 1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7, 7,
+  6, 1, 0, 128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1, 0,
+  192, 64, 64, 64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168, 168,
+  168, 168, 5, 5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5, 5,
+  6, 0, 0, 112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240, 136,
+  136, 240, 128, 128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 8, 8,
+  5, 5, 5, 6, 0, 0, 176, 200, 128, 128, 128, 5, 5, 5, 6, 0,
+  0, 112, 128, 112, 8, 240, 4, 7, 7, 6, 0, 0, 64, 64, 224, 64,
+  64, 64, 48, 5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5, 5,
+  5, 6, 0, 0, 136, 136, 136, 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,
+  6, 6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6, 0,
+  0, 248, 16, 32, 64, 248, 3, 7, 7, 6, 1, 0, 32, 64, 64, 128,
+  64, 64, 32, 1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128, 128, 128,
+  3, 7, 7, 6, 1, 0, 128, 64, 64, 32, 64, 64, 128, 5, 2, 2,
+  6, 0, 3, 104, 144, 0, 0, 0, 6, 0, 10, 0, 0, 0, 12, 0,
+  10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0,
+  12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0,
+  0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0,
+  10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0,
+  12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0,
+  0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0,
+  10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0,
+  12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0,
+  0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0,
+  10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0,
+  12, 0, 10, 0, 0, 0, 12, 0, 10, 11, 11, 22, 12, 0, 255, 255,
+  224, 2, 0, 2, 0, 4, 0, 13, 0, 20, 128, 36, 64, 196, 32, 4,
+  0, 4, 0, 4, 0, 11, 11, 22, 12, 0, 255, 249, 0, 138, 0, 171,
+  224, 172, 64, 170, 64, 170, 64, 170, 64, 170, 128, 33, 0, 82, 128, 140,
+  96, 11, 11, 22, 12, 0, 255, 36, 0, 36, 0, 63, 128, 68, 0, 132,
+  0, 4, 0, 255, 224, 10, 0, 17, 0, 32, 128, 192, 96, 11, 11, 22,
+  12, 0, 255, 36, 0, 36, 0, 63, 192, 68, 0, 4, 0, 255, 224, 9,
+  0, 9, 0, 17, 32, 33, 32, 64, 224, 11, 11, 22, 12, 0, 255, 32,
+  0, 61, 224, 81, 32, 145, 32, 17, 32, 255, 32, 17, 32, 41, 32, 37,
+  224, 69, 32, 128, 0, 11, 11, 22, 12, 0, 255, 32, 128, 127, 192, 8,
+  64, 255, 224, 17, 0, 32, 128, 95, 64, 128, 32, 63, 128, 0, 0, 127,
+  192, 11, 11, 22, 12, 0, 255, 34, 64, 71, 224, 148, 128, 228, 128, 47,
+  224, 68, 128, 244, 128, 7, 224, 52, 128, 196, 128, 7, 224, 11, 11, 22,
+  12, 0, 255, 4, 128, 143, 224, 73, 0, 25, 0, 47, 192, 9, 0, 9,
+  0, 47, 192, 73, 0, 137, 0, 15, 224, 11, 11, 22, 12, 0, 255, 16,
+  0, 63, 128, 81, 0, 14, 0, 49, 128, 192, 96, 63, 128, 36, 128, 63,
+  128, 36, 128, 63, 128, 11, 11, 22, 12, 0, 255, 34, 128, 250, 64, 7,
+  224, 250, 128, 138, 128, 138, 128, 250, 128, 34, 128, 178, 128, 170, 160, 100,
+  224, 11, 11, 22, 12, 0, 255, 34, 32, 71, 64, 146, 128, 239, 224, 34,
+  0, 71, 192, 236, 64, 7, 192, 52, 64, 199, 192, 4, 64, 11, 11, 22,
+  12, 0, 255, 8, 0, 15, 192, 8, 0, 8, 0, 255, 224, 8, 0, 14,
+  0, 9, 128, 8, 64, 8, 0, 8, 0, 10, 11, 22, 12, 0, 255, 255,
+  128, 0, 128, 0, 128, 128, 128, 128, 128, 255, 128, 128, 0, 128, 0, 128,
+  64, 128, 64, 127, 192, 11, 11, 22, 12, 0, 255, 71, 192, 65, 0, 239,
+  224, 65, 0, 69, 0, 105, 96, 201, 32, 77, 96, 73, 32, 79, 224, 200,
+  32, 11, 11, 22, 12, 0, 255, 8, 0, 4, 0, 4, 0, 10, 0, 10,
+  0, 10, 0, 17, 0, 17, 0, 32, 128, 64, 64, 128, 32, 11, 11, 22,
+  12, 0, 255, 34, 64, 34, 0, 247, 224, 34, 0, 35, 224, 53, 32, 229,
+  32, 37, 64, 40, 128, 41, 64, 114, 32, 11, 10, 20, 12, 0, 0, 68,
+  64, 68, 64, 68, 64, 127, 192, 4, 0, 4, 0, 132, 32, 132, 32, 132,
+  32, 255, 224, 11, 11, 22, 12, 0, 255, 4, 0, 0, 0, 127, 192, 4,
+  0, 4, 0, 4, 0, 127, 192, 4, 0, 4, 0, 4, 0, 255, 224, 11,
+  11, 22, 12, 0, 255, 255, 224, 17, 0, 1, 192, 254, 0, 72, 128, 37,
+  0, 4, 0, 255, 224, 21, 0, 36, 128, 196, 96, 11, 11, 22, 12, 0,
+  255, 17, 0, 127, 192, 68, 64, 127, 192, 68, 64, 127, 192, 4, 0, 255,
+  224, 4, 0, 4, 0, 4, 0, 9, 11, 22, 12, 0, 255, 16, 0, 255,
+  128, 128, 128, 128, 128, 255, 128, 128, 128, 128, 128, 255, 128, 128, 128, 128,
+  128, 255, 128, 11, 11, 22, 12, 0, 255, 113, 0, 1, 0, 3, 224, 249,
+  32, 33, 32, 65, 32, 81, 32, 137, 32, 250, 32, 2, 32, 4, 192, 11,
+  11, 22, 12, 0, 255, 127, 192, 17, 0, 17, 0, 17, 0, 17, 0, 255,
+  224, 17, 0, 17, 0, 33, 0, 33, 0, 65, 0, 11, 11, 22, 12, 0,
+  255, 33, 0, 34, 0, 244, 64, 87, 224, 80, 32, 87, 192, 148, 64, 84,
+  64, 36, 64, 87, 192, 148, 64, 11, 11, 22, 12, 0, 255, 17, 0, 10,
+  0, 127, 192, 4, 0, 4, 0, 255, 224, 4, 0, 10, 0, 17, 0, 32,
+  128, 192, 96, 10, 11, 22, 12, 0, 255, 95, 192, 0, 64, 132, 64, 132,
+  64, 191, 64, 132, 64, 140, 64, 148, 64, 164, 64, 140, 64, 129, 192, 11,
+  11, 22, 12, 0, 255, 36, 0, 39, 192, 36, 0, 36, 0, 255, 224, 0,
+  0, 20, 64, 36, 128, 71, 0, 12, 0, 112, 0, 11, 11, 22, 12, 0,
+  255, 36, 128, 4, 128, 15, 192, 228, 128, 36, 128, 63, 224, 36, 128, 36,
+  128, 40, 128, 80, 0, 143, 224, 11, 11, 22, 12, 0, 255, 8, 0, 8,
+  0, 255, 128, 136, 128, 136, 128, 255, 128, 136, 128, 136, 128, 255, 160, 136,
+  32, 7, 224, 11, 11, 22, 12, 0, 255, 39, 128, 36, 128, 244, 128, 36,
+  128, 116, 128, 108, 128, 164, 128, 36, 128, 36, 160, 40, 160, 48, 96, 10,
+  11, 22, 12, 0, 255, 255, 192, 128, 64, 128, 64, 158, 64, 146, 64, 146,
+  64, 158, 64, 128, 64, 128, 64, 255, 192, 128, 64, 11, 11, 22, 12, 0,
+  255, 127, 192, 68, 0, 95, 192, 80, 64, 95, 192, 80, 64, 95, 192, 66,
+  0, 74, 128, 82, 64, 166, 32, 11, 11, 22, 12, 0, 255, 4, 0, 7,
+  224, 4, 0, 127, 192, 64, 64, 64, 64, 64, 64, 127, 192, 0, 0, 82,
+  64, 137, 32, 11, 11, 22, 12, 0, 255, 71, 128, 36, 128, 4, 128, 4,
+  128, 232, 96, 32, 0, 47, 192, 36, 64, 34, 128, 49, 0, 38, 192, 11,
+  11, 22, 12, 0, 255, 127, 192, 74, 64, 127, 192, 4, 0, 255, 224, 4,
+  0, 63, 128, 32, 128, 36, 128, 36, 128, 255, 224, 11, 11, 22, 12, 0,
+  255, 34, 0, 79, 224, 72, 32, 79, 224, 200, 0, 79, 224, 74, 160, 90,
+  160, 111, 224, 74, 160, 72, 96, 11, 11, 22, 12, 0, 255, 243, 192, 36,
+  64, 42, 128, 241, 0, 34, 128, 101, 224, 114, 32, 165, 64, 32, 128, 35,
+  0, 44, 0, 11, 11, 22, 12, 0, 255, 4, 0, 255, 224, 128, 32, 0,
+  0, 255, 224, 4, 0, 36, 0, 39, 192, 36, 0, 84, 0, 143, 224, 11,
+  11, 22, 12, 0, 255, 115, 224, 16, 128, 81, 0, 35, 224, 250, 32, 42,
+  160, 34, 160, 34, 160, 32, 128, 33, 64, 98, 32, 11, 11, 22, 12, 0,
+  255, 34, 0, 247, 128, 34, 128, 54, 128, 226, 160, 37, 160, 36, 96, 104,
+  32, 0, 0, 82, 64, 137, 32, 11, 11, 22, 12, 0, 255, 115, 192, 66,
+  0, 66, 0, 123, 224, 74, 64, 74, 64, 122, 64, 74, 64, 66, 64, 68,
+  64, 136, 64, 11, 11, 22, 12, 0, 255, 8, 0, 255, 224, 8, 0, 31,
+  192, 48, 64, 95, 192, 144, 64, 31, 192, 16, 64, 16, 64, 16, 192, 11,
+  11, 22, 12, 0, 255, 2, 0, 127, 224, 66, 0, 66, 0, 95, 192, 66,
+  0, 71, 0, 74, 128, 82, 64, 98, 32, 130, 0, 11, 11, 22, 12, 0,
+  255, 243, 192, 150, 64, 145, 128, 166, 96, 161, 0, 151, 192, 145, 0, 149,
+  0, 231, 224, 129, 0, 129, 0, 11, 11, 22, 12, 0, 255, 15, 128, 136,
+  128, 79, 128, 8, 128, 143, 128, 64, 0, 31, 192, 53, 64, 85, 64, 149,
+  64, 63, 224, 11, 11, 22, 12, 0, 255, 39, 224, 32, 128, 248, 128, 32,
+  128, 32, 128, 56, 128, 224, 128, 32, 128, 32, 128, 32, 128, 97, 128, 11,
+  11, 22, 12, 0, 255, 31, 224, 145, 0, 87, 192, 20, 64, 23, 192, 148,
+  64, 87, 192, 17, 0, 85, 64, 153, 32, 35, 0, 11, 11, 22, 12, 0,
+  255, 32, 128, 39, 224, 242, 64, 33, 128, 34, 64, 52, 32, 226, 64, 34,
+  64, 34, 64, 34, 64, 100, 64, 11, 11, 22, 12, 0, 255, 65, 0, 65,
+  0, 79, 224, 233, 32, 73, 32, 73, 32, 111, 224, 201, 32, 73, 32, 73,
+  32, 207, 224, 11, 11, 22, 12, 0, 255, 33, 0, 241, 0, 79, 224, 169,
+  32, 249, 32, 47, 224, 57, 32, 233, 32, 41, 32, 47, 224, 40, 32, 11,
+  11, 22, 12, 0, 255, 143, 224, 73, 32, 9, 32, 203, 160, 73, 32, 79,
+  224, 72, 32, 75, 160, 74, 160, 107, 160, 80, 224, 11, 11, 22, 12, 0,
+  255, 127, 192, 4, 0, 68, 64, 36, 64, 36, 128, 4, 0, 255, 224, 4,
+  0, 4, 0, 4, 0, 4, 0, 11, 11, 22, 12, 0, 255, 130, 0, 66,
+  0, 31, 224, 194, 0, 95, 192, 82, 64, 95, 192, 71, 0, 74, 128, 82,
+  64, 191, 224, 11, 11, 22, 12, 0, 255, 4, 0, 127, 224, 72, 128, 127,
+  224, 72, 128, 79, 128, 64, 0, 95, 192, 72, 64, 71, 128, 152, 96, 11,
+  11, 22, 12, 0, 255, 1, 0, 239, 224, 161, 0, 164, 64, 175, 224, 164,
+  64, 175, 224, 169, 32, 233, 32, 2, 128, 12, 96, 11, 11, 22, 12, 0,
+  255, 20, 192, 246, 160, 188, 96, 167, 128, 168, 128, 191, 224, 169, 32, 239,
+  224, 9, 32, 15, 224, 9, 32, 11, 11, 22, 12, 0, 255, 127, 128, 64,
+  128, 66, 128, 98, 128, 84, 128, 72, 128, 72, 128, 84, 160, 98, 160, 64,
+  96, 128, 32, 11, 11, 22, 12, 0, 255, 4, 0, 127, 224, 64, 32, 127,
+  224, 64, 0, 125, 224, 84, 32, 76, 160, 84, 96, 100, 160, 141, 96, 11,
+  11, 22, 12, 0, 255, 130, 0, 95, 224, 4, 0, 8, 64, 159, 224, 64,
+  32, 10, 128, 10, 128, 74, 160, 146, 160, 34, 96, 11, 11, 22, 12, 0,
+  255, 65, 0, 79, 224, 232, 32, 66, 128, 68, 64, 104, 32, 199, 192, 65,
+  0, 65, 0, 65, 0, 207, 224, 11, 11, 22, 12, 0, 255, 80, 32, 125,
+  32, 145, 32, 255, 32, 17, 32, 125, 32, 85, 32, 85, 32, 84, 32, 92,
+  32, 16, 224, 11, 11, 22, 12, 0, 255, 63, 128, 32, 128, 63, 128, 32,
+  128, 255, 224, 72, 0, 123, 192, 73, 64, 121, 64, 72, 128, 251, 96, 11,
+  11, 22, 12, 0, 255, 4, 0, 4, 0, 4, 0, 36, 128, 36, 64, 68,
+  64, 68, 32, 132, 32, 4, 0, 4, 0, 28, 0, 11, 11, 22, 12, 0,
+  255, 4, 0, 4, 0, 4, 0, 255, 224, 4, 0, 10, 0, 10, 0, 17,
+  0, 17, 0, 32, 128, 192, 96, 9, 10, 20, 10, 0, 0, 136, 128, 73,
+  0, 8, 0, 255, 128, 0, 128, 0, 128, 127, 128, 0, 128, 0, 128, 255,
+  128, 11, 11, 22, 12, 0, 255, 33, 0, 18, 0, 255, 224, 0, 0, 120,
+  128, 74, 128, 122, 128, 74, 128, 122, 128, 72, 128, 89, 128, 11, 11, 22,
+  12, 0, 255, 39, 192, 0, 0, 0, 0, 239, 224, 33, 0, 34, 0, 36,
+  64, 47, 224, 32, 32, 80, 0, 143, 224, 11, 11, 22, 12, 0, 255, 32,
+  128, 39, 0, 249, 0, 33, 192, 119, 0, 33, 0, 249, 224, 39, 0, 113,
+  32, 169, 32, 32, 224, 11, 11, 22, 12, 0, 255, 16, 64, 16, 64, 253,
+  224, 16, 64, 56, 192, 53, 64, 82, 64, 148, 64, 16, 64, 16, 64, 16,
+  192, 11, 11, 22, 12, 0, 255, 0, 64, 248, 64, 11, 224, 8, 64, 136,
+  64, 82, 64, 81, 64, 33, 64, 80, 64, 72, 64, 137, 192, 10, 11, 22,
+  12, 0, 255, 132, 0, 132, 64, 132, 128, 245, 0, 134, 0, 132, 0, 132,
+  0, 148, 0, 164, 64, 196, 64, 131, 192, 11, 11, 22, 12, 0, 255, 17,
+  32, 125, 0, 17, 0, 255, 224, 41, 0, 253, 64, 73, 64, 124, 128, 8,
+  160, 253, 96, 10, 32, 11, 11, 22, 12, 0, 255, 23, 192, 36, 64, 36,
+  64, 103, 192, 161, 0, 47, 224, 33, 0, 35, 128, 37, 64, 41, 32, 33,
+  0, 11, 11, 22, 12, 0, 255, 8, 0, 255, 224, 16, 0, 39, 192, 32,
+  128, 97, 0, 175, 224, 33, 0, 33, 0, 33, 0, 35, 0, 11, 11, 22,
+  12, 0, 255, 36, 0, 47, 224, 180, 0, 164, 128, 164, 160, 170, 192, 42,
+  128, 40, 128, 41, 64, 50, 64, 36, 32, 11, 11, 22, 12, 0, 255, 127,
+  224, 128, 0, 63, 192, 32, 64, 63, 192, 16, 0, 31, 192, 16, 64, 40,
+  128, 71, 0, 56, 224, 11, 11, 22, 12, 0, 255, 127, 224, 64, 0, 64,
+  0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 128,
+  0, 11, 11, 22, 12, 0, 255, 255, 224, 4, 0, 127, 192, 68, 64, 127,
+  192, 68, 64, 127, 192, 68, 0, 36, 0, 24, 0, 231, 224, 11, 11, 22,
+  12, 0, 255, 17, 224, 253, 0, 69, 0, 41, 224, 253, 64, 17, 64, 125,
+  64, 17, 64, 85, 64, 146, 64, 52, 64, 11, 11, 22, 12, 0, 255, 33,
+  0, 95, 224, 64, 0, 207, 192, 64, 0, 79, 192, 64, 0, 79, 192, 72,
+  64, 79, 192, 72, 64, 11, 11, 22, 12, 0, 255, 4, 0, 127, 192, 64,
+  64, 127, 192, 64, 64, 127, 192, 64, 64, 127, 192, 4, 64, 82, 32, 191,
+  160, 11, 11, 22, 12, 0, 255, 127, 192, 68, 64, 127, 192, 68, 64, 127,
+  192, 4, 0, 27, 0, 224, 224, 17, 0, 17, 0, 97, 0, 11, 11, 22,
+  12, 0, 255, 255, 224, 4, 0, 8, 0, 127, 224, 73, 32, 79, 32, 73,
+  32, 79, 32, 73, 32, 73, 32, 127, 224, 11, 11, 22, 12, 0, 255, 253,
+  224, 86, 64, 121, 64, 56, 128, 85, 64, 146, 32, 255, 224, 4, 0, 39,
+  192, 36, 0, 255, 224, 11, 11, 22, 12, 0, 255, 251, 128, 82, 0, 123,
+  224, 18, 64, 250, 64, 20, 64, 63, 128, 32, 128, 63, 128, 32, 128, 63,
+  128, 11, 11, 22, 12, 0, 255, 31, 224, 32, 0, 39, 192, 100, 64, 167,
+  192, 32, 0, 47, 224, 40, 32, 39, 192, 33, 0, 35, 0, 11, 11, 22,
+  12, 0, 255, 243, 224, 130, 32, 130, 32, 250, 32, 130, 32, 130, 32, 138,
+  32, 178, 32, 194, 224, 2, 0, 2, 0, 11, 11, 22, 12, 0, 255, 36,
+  128, 70, 160, 149, 192, 228, 128, 39, 224, 68, 128, 245, 192, 6, 160, 52,
+  128, 196, 128, 7, 224, 11, 11, 22, 12, 0, 255, 39, 192, 65, 0, 135,
+  224, 224, 32, 34, 128, 69, 128, 242, 128, 15, 224, 48, 128, 193, 64, 2,
+  32, 11, 11, 22, 12, 0, 255, 2, 0, 2, 0, 34, 0, 35, 192, 34,
+  0, 34, 0, 34, 0, 34, 0, 34, 0, 34, 0, 255, 224, 9, 11, 22,
+  12, 0, 255, 8, 0, 8, 0, 255, 128, 136, 128, 136, 128, 136, 128, 255,
+  128, 136, 128, 136, 128, 136, 128, 255, 128, 11, 11, 22, 12, 0, 255, 33,
+  0, 83, 160, 65, 0, 247, 224, 81, 0, 83, 192, 86, 64, 83, 192, 90,
+  64, 83, 192, 66, 64, 11, 11, 22, 12, 0, 255, 127, 192, 4, 0, 4,
+  0, 4, 0, 255, 224, 10, 0, 10, 0, 18, 0, 34, 32, 66, 32, 129,
+  224, 11, 11, 22, 12, 0, 255, 17, 0, 33, 0, 47, 224, 97, 0, 163,
+  128, 35, 128, 37, 64, 37, 64, 41, 32, 33, 0, 33, 0, 11, 11, 22,
+  12, 0, 255, 247, 224, 148, 32, 244, 32, 151, 224, 148, 128, 244, 128, 151,
+  224, 148, 128, 244, 160, 150, 96, 4, 32, 11, 11, 22, 12, 0, 255, 123,
+  224, 148, 128, 4, 0, 127, 192, 4, 0, 255, 224, 1, 0, 255, 224, 33,
+  0, 17, 0, 7, 0, 11, 11, 22, 12, 0, 255, 33, 0, 71, 192, 145,
+  0, 47, 224, 96, 128, 175, 224, 32, 128, 36, 128, 34, 128, 32, 128, 35,
+  128, 11, 11, 22, 12, 0, 255, 39, 192, 36, 64, 247, 192, 46, 224, 42,
+  160, 62, 224, 225, 0, 47, 224, 35, 128, 37, 64, 105, 32, 11, 11, 22,
+  12, 0, 255, 20, 0, 39, 224, 42, 0, 98, 0, 163, 192, 34, 0, 34,
+  0, 35, 224, 34, 0, 34, 0, 34, 0
+};

+ 192 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_CZ.h

@@ -0,0 +1,192 @@
+/*
+  Fontname: ISO10646_CZ
+  Copyright: A. Hardtung, public domain
+  Modified for Czech accents by Petr Zahradnik, http://www.zahradniksebavi.cz
+  Capital A Height: 7, '1' Height: 7
+  Calculated Max Values w= 6 h= 9 x= 2 y= 7 dx= 6 dy= 0 ascent= 8 len= 9
+  Font Bounding box     w= 6 h= 9 x= 0 y=-2
+  Calculated Min Values           x= 0 y=-1 dx= 0 dy= 0
+  Pure Font   ascent = 7 descent=-1
+  X Font      ascent = 7 descent=-1
+  Max Font    ascent = 8 descent=-1
+*/
+#include <U8glib.h>
+const u8g_fntpgm_uint8_t ISO10646_CZ[2832] U8G_SECTION(".progmem.ISO10646_CZ") = {
+  0,6,9,0,254,7,1,146,3,33,32,255,255,8,255,7,
+  255,0,0,0,6,0,0,1,7,7,6,2,0,128,128,128,
+  128,128,0,128,3,2,2,6,1,5,160,160,5,7,7,6,
+  0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,32,
+  120,160,112,40,240,32,5,7,7,6,0,0,192,200,16,32,
+  64,152,24,5,7,7,6,0,0,96,144,160,64,168,144,104,
+  2,3,3,6,1,4,192,64,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,32,168,112,168,32,5,5,
+  5,6,0,1,32,32,248,32,32,2,3,3,6,2,255,192,
+  64,128,5,1,1,6,0,3,248,2,2,2,6,2,0,192,
+  192,5,5,5,6,0,1,8,16,32,64,128,5,7,7,6,
+  0,0,112,136,136,136,136,136,112,3,7,7,6,1,0,64,
+  192,64,64,64,64,224,5,7,7,6,0,0,112,136,8,112,
+  128,128,248,5,7,7,6,0,0,248,16,32,16,8,8,240,
+  5,7,7,6,0,0,16,48,80,144,248,16,16,5,7,7,
+  6,0,0,248,128,240,8,8,136,112,5,7,7,6,0,0,
+  112,128,128,240,136,136,112,5,7,7,6,0,0,248,8,16,
+  32,32,32,32,5,7,7,6,0,0,112,136,136,112,136,136,
+  112,5,7,7,6,0,0,112,136,136,120,8,8,112,2,5,
+  5,6,2,0,192,192,0,192,192,2,6,6,6,2,255,192,
+  192,0,192,64,128,4,7,7,6,0,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,
+  8,16,32,0,32,5,7,7,6,0,0,112,136,8,104,168,
+  168,112,5,7,7,6,0,0,112,136,136,248,136,136,136,5,
+  7,7,6,0,0,240,136,136,240,136,136,240,5,7,7,6,
+  0,0,112,136,128,128,128,136,112,5,7,7,6,0,0,240,
+  136,136,136,136,136,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,184,136,136,112,5,7,7,
+  6,0,0,136,136,136,248,136,136,136,1,7,7,6,2,0,
+  128,128,128,128,128,128,128,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,216,168,136,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,7,7,6,0,0,112,136,136,136,168,144,104,5,
+  7,7,6,0,0,240,136,136,240,160,144,136,5,7,7,6,
+  0,0,120,128,128,112,8,8,240,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,136,136,80,32,
+  5,7,7,6,0,0,136,136,136,136,136,168,80,5,7,7,
+  6,0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,
+  136,136,136,80,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,5,5,6,0,1,128,64,32,16,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,0,248,2,2,2,6,2,5,128,
+  64,5,5,5,6,0,0,112,8,120,136,120,5,7,7,6,
+  0,0,128,128,176,200,136,136,240,5,5,5,6,0,0,112,
+  128,128,136,112,5,7,7,6,0,0,8,8,104,152,136,136,
+  120,5,5,5,6,0,0,112,136,248,128,112,5,7,7,6,
+  0,0,48,72,224,64,64,64,64,5,6,6,6,0,255,112,
+  136,136,120,8,112,5,7,7,6,0,0,128,128,176,200,136,
+  136,136,1,7,7,6,2,0,128,0,128,128,128,128,128,3,
+  8,8,6,1,255,32,0,32,32,32,32,160,64,4,7,7,
+  6,0,0,128,128,144,160,192,160,144,3,7,7,6,1,0,
+  192,64,64,64,64,64,224,5,5,5,6,0,0,208,168,168,
+  168,168,5,5,5,6,0,0,176,200,136,136,136,5,5,5,
+  6,0,0,112,136,136,136,112,5,6,6,6,0,255,240,136,
+  136,240,128,128,5,6,6,6,0,255,120,136,136,120,8,8,
+  5,5,5,6,0,0,176,200,128,128,128,5,5,5,6,0,
+  0,112,128,112,8,240,4,7,7,6,0,0,64,64,224,64,
+  64,64,48,5,5,5,6,0,0,136,136,136,152,104,5,5,
+  5,6,0,0,136,136,136,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,
+  6,6,6,0,255,136,136,136,120,8,112,5,5,5,6,0,
+  0,248,16,32,64,248,3,7,7,6,1,0,32,64,64,128,
+  64,64,32,1,7,7,6,2,0,128,128,128,128,128,128,128,
+  3,7,7,6,1,0,128,64,64,32,64,64,128,5,2,2,
+  6,0,2,104,144,0,0,0,6,0,0,5,8,8,6,0,
+  0,16,32,112,136,136,248,136,136,5,8,8,6,0,0,8,
+  16,248,128,128,240,128,248,3,8,8,6,1,0,32,64,224,
+  64,64,64,64,224,5,8,8,6,0,0,16,32,112,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,16,32,136,136,80,32,32,32,5,
+  8,8,6,0,0,16,32,0,112,8,120,136,120,5,8,8,
+  6,0,0,16,32,0,112,136,248,128,112,2,8,8,6,2,
+  0,64,128,0,128,128,128,128,128,5,8,8,6,0,0,16,
+  32,0,112,136,136,136,112,5,8,8,6,0,0,16,32,0,
+  136,136,136,152,104,5,9,9,6,0,255,16,32,0,136,136,
+  136,120,8,112,5,8,8,6,0,0,80,32,112,136,128,128,
+  136,112,5,8,8,6,0,0,80,32,0,112,128,128,136,112,
+  5,8,8,6,0,0,80,32,240,136,136,136,136,240,6,8,
+  8,6,0,0,4,20,24,112,144,144,144,112,5,8,8,6,
+  0,0,80,32,248,128,128,240,128,248,5,8,8,6,0,0,
+  80,32,0,112,136,248,128,112,5,8,8,6,0,0,80,32,
+  136,200,168,152,136,136,5,8,8,6,0,0,80,32,0,176,
+  200,136,136,136,5,8,8,6,0,0,80,32,240,136,240,160,
+  144,136,5,8,8,6,0,0,80,32,0,176,200,128,128,128,
+  5,8,8,6,0,0,80,32,120,128,128,112,8,240,5,8,
+  8,6,0,0,80,32,0,112,128,112,8,240,5,8,8,6,
+  0,0,80,32,248,32,32,32,32,32,6,8,8,6,0,0,
+  4,68,72,224,64,64,64,48,5,8,8,6,0,0,32,80,
+  168,136,136,136,136,112,5,8,8,6,0,0,32,80,32,136,
+  136,136,152,104,5,8,8,6,0,0,80,32,248,8,48,64,
+  128,248,5,8,8,6,0,0,80,32,0,248,16,32,64,248,
+  0,0,0,6,0,0,0,0,0,6,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,0,32,112,168,160,168,112,32,5,7,7,6,
+  0,0,48,64,64,224,64,80,168,5,5,5,6,0,0,136,
+  112,80,112,136,5,7,7,6,0,0,136,80,32,248,32,248,
+  32,1,7,7,6,2,0,128,128,128,0,128,128,128,5,8,
+  8,6,0,0,48,72,32,80,80,32,144,96,3,1,1,6,
+  1,7,160,5,7,7,6,0,0,248,136,184,184,184,136,248,
+  5,7,7,6,0,1,112,8,120,136,120,0,248,5,5,5,
+  6,0,1,40,80,160,80,40,5,3,3,6,0,1,248,8,
+  8,2,2,2,6,2,6,64,128,5,7,7,6,0,0,248,
+  136,168,136,152,168,248,5,1,1,6,0,6,248,4,4,4,
+  6,0,3,96,144,144,96,5,7,7,6,0,0,32,32,248,
+  32,32,0,248,4,5,5,6,0,3,96,144,32,64,240,3,
+  5,5,6,0,3,224,32,224,32,224,2,2,2,6,2,6,
+  64,128,5,8,8,6,0,255,136,136,136,136,152,232,128,128,
+  5,7,7,6,0,0,120,152,152,120,24,24,24,2,2,2,
+  6,2,2,192,192,2,2,2,6,2,255,64,128,3,5,5,
+  6,0,3,64,192,64,64,224,5,7,7,6,0,1,112,136,
+  136,136,112,0,248,5,5,5,6,0,1,160,80,40,80,160,
+  5,7,7,6,0,0,136,144,168,88,184,8,8,5,7,7,
+  6,0,0,136,144,184,72,152,32,56,5,8,8,6,0,0,
+  192,64,192,72,216,56,8,8,5,7,7,6,0,0,32,0,
+  32,64,128,136,112,5,8,8,6,0,0,64,32,0,112,136,
+  248,136,136,5,8,8,6,0,0,16,32,0,112,136,248,136,
+  136,5,8,8,6,0,0,32,80,0,112,136,248,136,136,5,
+  8,8,6,0,0,104,144,0,112,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,32,112,136,248,136,136,5,7,7,6,0,0,56,
+  96,160,184,224,160,184,5,8,8,6,0,255,112,136,128,128,
+  136,112,32,96,5,8,8,6,0,0,64,32,0,248,128,240,
+  128,248,5,8,8,6,0,0,8,16,0,248,128,240,128,248,
+  5,8,8,6,0,0,32,80,0,248,128,240,128,248,5,7,
+  7,6,0,0,80,0,248,128,240,128,248,3,8,8,6,1,
+  0,128,64,0,224,64,64,64,224,3,8,8,6,1,0,32,
+  64,0,224,64,64,64,224,3,8,8,6,1,0,64,160,0,
+  224,64,64,64,224,3,7,7,6,1,0,160,0,224,64,64,
+  64,224,5,9,9,6,0,255,80,32,112,136,128,184,136,136,
+  112,5,8,8,6,0,0,104,144,0,136,200,168,152,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,0,112,136,136,136,112,5,8,8,6,0,0,104,
+  144,0,112,136,136,136,112,5,8,8,6,0,0,80,0,112,
+  136,136,136,136,112,5,5,5,6,0,1,136,80,32,80,136,
+  5,8,8,6,0,255,16,112,168,168,168,168,112,64,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,1,7,7,6,2,0,128,0,128,128,
+  128,128,128,5,9,9,6,0,255,120,128,128,112,8,8,240,
+  32,96,4,8,8,6,1,255,96,144,144,160,144,144,224,128,
+  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,
+  104,144,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,5,6,6,6,0,0,208,40,120,160,168,80,5,
+  7,7,6,0,255,112,128,128,136,112,32,96,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,64,192,64,64,
+  224,3,8,8,6,1,0,32,64,0,64,192,64,64,224,3,
+  8,8,6,1,0,64,160,0,64,192,64,64,224,3,7,7,
+  6,1,0,160,0,64,192,64,64,224,5,8,8,6,0,255,
+  80,32,112,136,136,120,8,112,5,8,8,6,0,0,104,144,
+  0,176,200,136,136,136,5,8,8,6,0,0,64,32,0,112,
+  136,136,136,112,5,8,8,6,0,0,16,32,0,112,136,136,
+  136,112,5,8,8,6,0,0,32,80,0,112,136,136,136,112,
+  5,8,8,6,0,0,104,144,0,112,136,136,136,112,5,7,
+  7,6,0,0,80,0,112,136,136,136,112,5,5,5,6,0,
+  1,32,0,248,0,32,5,7,7,6,0,255,16,112,168,168,
+  168,112,64,5,8,8,6,0,0,64,32,0,136,136,136,152,
+  104,5,8,8,6,0,0,16,32,0,136,136,136,152,104,5,
+  8,8,6,0,0,32,80,0,136,136,136,152,104,5,7,7,
+  6,0,0,80,0,136,136,136,152,104,1,5,5,6,2,0,
+  128,128,128,128,128,5,7,7,6,0,255,112,128,112,8,240,
+  32,96,5,8,8,6,0,255,80,0,136,136,136,120,8,112
+  };

+ 205 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_Greek.h

@@ -0,0 +1,205 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+  Fontname: ISO10646_4_Greek
+  Copyright: A. Hardtung, public domain
+  Capital A Height: 7, '1' Height: 7
+  Calculated Max Values w= 5 h= 9 x= 2 y= 6 dx= 6 dy= 0 ascent= 8 len= 9
+  Font Bounding box     w= 6 h= 9 x= 0 y=-2
+  Calculated Min Values           x= 0 y=-1 dx= 0 dy= 0
+  Pure Font   ascent = 7 descent=-1
+  X Font      ascent = 7 descent=-1
+  Max Font    ascent = 8 descent=-1
+*/
+#include <U8glib.h>
+const u8g_fntpgm_uint8_t ISO10646_Greek_5x7[2715] U8G_SECTION(".progmem.ISO10646_Greek_5x7") = {
+  0,6,9,0,254,7,1,145,3,32,32,255,255,8,255,7,
+  255,0,0,0,6,0,0,1,7,7,6,2,0,128,128,128,
+  128,128,0,128,3,2,2,6,1,5,160,160,5,7,7,6,
+  0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,32,
+  120,160,112,40,240,32,5,7,7,6,0,0,192,200,16,32,
+  64,152,24,5,7,7,6,0,0,96,144,160,64,168,144,104,
+  2,3,3,6,1,4,192,64,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,32,168,112,168,32,5,5,
+  5,6,0,1,32,32,248,32,32,2,3,3,6,2,255,192,
+  64,128,5,1,1,6,0,3,248,2,2,2,6,2,0,192,
+  192,5,5,5,6,0,1,8,16,32,64,128,5,7,7,6,
+  0,0,112,136,152,168,200,136,112,3,7,7,6,1,0,64,
+  192,64,64,64,64,224,5,7,7,6,0,0,112,136,8,112,
+  128,128,248,5,7,7,6,0,0,248,16,32,16,8,8,240,
+  5,7,7,6,0,0,16,48,80,144,248,16,16,5,7,7,
+  6,0,0,248,128,240,8,8,136,112,5,7,7,6,0,0,
+  48,64,128,240,136,136,112,5,7,7,6,0,0,248,8,16,
+  32,32,32,32,5,7,7,6,0,0,112,136,136,112,136,136,
+  112,5,7,7,6,0,0,112,136,136,120,8,16,96,2,5,
+  5,6,2,0,192,192,0,192,192,2,6,6,6,2,255,192,
+  192,0,192,64,128,4,7,7,6,0,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,
+  8,16,32,0,32,5,6,6,6,0,0,112,136,8,104,168,
+  112,5,7,7,6,0,0,112,136,136,248,136,136,136,5,7,
+  7,6,0,0,240,136,136,240,136,136,240,5,7,7,6,0,
+  0,112,136,128,128,128,136,112,5,7,7,6,0,0,224,144,
+  136,136,136,144,224,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,184,136,136,112,5,7,7,6,
+  0,0,136,136,136,248,136,136,136,1,7,7,6,2,0,128,
+  128,128,128,128,128,128,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,216,168,136,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,7,7,6,0,0,112,136,136,136,168,144,104,5,7,
+  7,6,0,0,240,136,136,240,160,144,136,5,7,7,6,0,
+  0,120,128,128,112,8,8,240,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,136,136,80,32,5,
+  7,7,6,0,0,136,136,136,136,136,168,80,5,7,7,6,
+  0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,136,
+  136,136,80,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,5,5,6,0,1,128,64,32,16,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,0,248,2,2,2,6,2,5,128,64,
+  5,5,5,6,0,0,112,8,120,136,120,5,7,7,6,0,
+  0,128,128,176,200,136,136,240,5,5,5,6,0,0,112,128,
+  128,136,112,5,7,7,6,0,0,8,8,104,152,136,136,120,
+  5,5,5,6,0,0,112,136,248,128,112,5,7,7,6,0,
+  0,48,72,224,64,64,64,64,5,6,6,6,0,255,112,136,
+  136,120,8,112,5,7,7,6,0,0,128,128,176,200,136,136,
+  136,1,7,7,6,2,0,128,0,128,128,128,128,128,3,8,
+  8,6,1,255,32,0,32,32,32,32,160,64,4,7,7,6,
+  0,0,128,128,144,160,192,160,144,3,7,7,6,1,0,192,
+  64,64,64,64,64,224,5,5,5,6,0,0,208,168,168,168,
+  168,5,5,5,6,0,0,176,200,136,136,136,5,5,5,6,
+  0,0,112,136,136,136,112,5,6,6,6,0,255,240,136,136,
+  240,128,128,5,6,6,6,0,255,120,136,136,120,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,224,64,64,
+  72,48,5,5,5,6,0,0,136,136,136,152,104,5,5,5,
+  6,0,0,136,136,136,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,6,
+  6,6,0,255,136,136,136,120,8,112,5,5,5,6,0,0,
+  248,16,32,64,248,3,7,7,6,1,0,32,64,64,128,64,
+  64,32,1,7,7,6,2,0,128,128,128,128,128,128,128,3,
+  7,7,6,1,0,128,64,64,32,64,64,128,5,2,2,6,
+  0,3,104,144,0,0,0,6,0,0,0,0,0,6,0,0,
+  0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,
+  0,0,2,2,2,6,1,6,64,128,3,3,3,6,1,5,
+  32,64,160,5,8,8,6,0,0,64,160,80,80,136,248,136,
+  136,2,2,2,6,1,2,192,192,5,8,8,6,0,0,64,
+  128,248,128,240,128,128,248,5,8,8,6,0,0,64,128,136,
+  136,248,136,136,136,4,8,8,6,0,0,64,128,112,32,32,
+  32,32,112,0,0,0,6,0,0,5,8,8,6,0,0,64,
+  128,112,136,136,136,136,112,0,0,0,6,0,0,5,8,8,
+  6,0,0,64,128,8,136,112,32,32,32,5,8,8,6,0,
+  0,64,128,112,136,136,136,80,216,3,8,8,6,1,0,32,
+  64,160,0,64,64,64,32,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,248,128,128,128,128,128,128,5,6,
+  6,6,0,0,32,80,80,136,136,248,5,7,7,6,0,0,
+  248,128,128,240,128,128,248,5,7,7,6,0,0,248,8,16,
+  32,64,128,248,5,7,7,6,0,0,136,136,136,248,136,136,
+  136,5,7,7,6,0,0,112,136,136,168,136,136,112,3,7,
+  7,6,1,0,224,64,64,64,64,64,224,5,7,7,6,0,
+  0,136,144,160,192,160,144,136,5,7,7,6,0,0,32,80,
+  136,136,136,136,136,5,7,7,6,0,0,136,216,168,168,136,
+  136,136,5,7,7,6,0,0,136,200,200,168,152,152,136,5,
+  7,7,6,0,0,248,0,0,112,0,0,248,5,7,7,6,
+  0,0,112,136,136,136,136,136,112,5,7,7,6,0,0,248,
+  80,80,80,80,80,80,5,7,7,6,0,0,240,136,136,240,
+  128,128,128,0,0,0,6,0,0,5,7,7,6,0,0,248,
+  128,64,32,64,128,248,5,7,7,6,0,0,248,32,32,32,
+  32,32,32,5,7,7,6,0,0,136,136,80,32,32,32,32,
+  5,7,7,6,0,0,112,32,112,168,112,32,112,5,7,7,
+  6,0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,
+  168,168,168,168,112,32,32,5,6,6,6,0,0,112,136,136,
+  80,80,216,3,8,8,6,1,0,160,0,224,64,64,64,64,
+  224,5,8,8,6,0,0,80,0,136,136,136,80,32,32,5,
+  8,8,6,0,0,32,64,8,104,152,144,144,104,5,8,8,
+  6,0,0,32,64,0,112,136,224,136,112,5,9,9,6,0,
+  255,32,64,0,112,136,136,136,136,8,2,8,8,6,1,0,
+  64,128,0,128,128,128,128,64,5,8,8,6,0,0,16,32,
+  80,0,136,136,136,112,5,6,6,6,0,0,8,104,152,144,
+  144,104,4,6,6,6,0,255,96,144,240,144,224,128,5,6,
+  6,6,0,255,136,72,80,32,32,64,5,6,6,6,0,0,
+  48,64,112,136,136,112,5,5,5,6,0,0,112,136,224,136,
+  112,5,8,8,6,0,255,128,112,64,128,128,112,8,112,5,
+  6,6,6,0,255,184,200,136,136,136,8,5,5,5,6,0,
+  0,112,136,248,136,112,3,5,5,6,1,0,128,128,128,128,
+  96,4,5,5,6,0,0,144,160,192,160,144,5,6,6,6,
+  0,0,64,32,32,80,80,136,5,6,6,6,0,255,136,136,
+  136,216,168,128,5,5,5,6,0,0,136,136,80,96,32,5,
+  9,9,6,0,255,128,224,128,112,32,64,240,8,112,5,5,
+  5,6,0,0,112,136,136,136,112,5,5,5,6,0,0,248,
+  80,80,80,80,5,6,6,6,0,255,112,136,136,200,176,128,
+  5,7,7,6,0,255,48,64,128,64,48,8,112,5,5,5,
+  6,0,0,104,144,144,144,96,4,5,5,6,0,0,240,64,
+  64,64,48,5,5,5,6,0,0,136,136,144,144,224,5,7,
+  7,6,0,255,32,168,168,168,112,32,32,5,6,6,6,0,
+  255,136,80,32,32,80,136,5,6,6,6,0,255,168,168,168,
+  168,112,32,5,5,5,6,0,0,80,136,136,168,112,4,7,
+  7,6,0,0,160,0,64,64,64,64,48,5,7,7,6,0,
+  0,80,0,136,136,144,144,224,4,8,8,6,0,0,32,64,
+  0,96,144,144,144,96,5,8,8,6,0,0,32,64,0,136,
+  136,144,144,96,5,8,8,6,0,0,32,64,0,80,136,136,
+  168,112,5,7,7,6,0,255,144,160,192,160,144,136,16,5,
+  8,8,6,0,0,96,144,160,128,240,136,136,112,5,7,7,
+  6,0,0,112,80,56,144,144,144,96,5,6,6,6,0,0,
+  152,80,32,32,32,32,5,8,8,6,0,0,64,128,152,80,
+  32,32,32,32,5,8,8,6,0,0,80,0,152,80,32,32,
+  32,32,5,7,7,6,0,255,48,168,168,168,168,112,32,5,
+  5,5,6,0,0,248,80,80,80,88,5,6,6,6,0,255,
+  136,80,112,80,136,16,5,7,7,6,0,255,112,136,136,136,
+  112,32,112,5,6,6,6,0,255,112,136,136,112,32,112,5,
+  6,6,6,0,0,112,136,128,112,32,112,5,7,7,6,0,
+  255,8,8,112,128,112,16,96,5,6,6,6,0,0,248,128,
+  128,240,128,128,4,5,5,6,0,0,240,128,224,128,128,5,
+  6,6,6,0,0,248,0,0,112,0,248,4,5,5,6,0,
+  0,64,128,240,16,32,5,7,7,6,0,0,224,80,40,40,
+  8,8,16,5,7,7,6,0,0,192,32,80,40,8,8,8,
+  5,7,7,6,0,255,168,168,168,168,88,8,112,5,6,6,
+  6,0,255,168,168,168,88,8,112,5,6,6,6,0,0,104,
+  136,136,120,8,8,5,6,6,6,0,255,104,136,136,120,8,
+  8,4,8,8,6,0,255,128,224,144,144,144,144,32,192,5,
+  5,5,6,0,0,104,144,112,16,224,5,6,6,6,0,0,
+  96,144,16,96,136,112,4,6,6,6,0,0,96,144,16,96,
+  128,112,5,6,6,6,0,0,136,80,32,80,136,248,5,5,
+  5,6,0,0,136,80,32,80,112,5,6,6,6,0,0,120,
+  128,240,136,136,112,4,5,5,6,0,0,240,128,224,144,96,
+  3,6,6,6,1,0,64,224,64,64,64,64,3,6,6,6,
+  1,255,64,224,64,64,64,128,5,5,5,6,0,0,136,80,
+  112,80,136,5,6,6,6,0,255,112,136,136,240,128,112,4,
+  5,5,6,0,0,112,128,128,128,112,2,8,8,6,1,255,
+  64,0,192,64,64,64,64,128,5,7,7,6,0,0,112,136,
+  136,248,136,136,112,4,5,5,6,0,0,112,128,224,128,112,
+  4,5,5,6,0,0,224,16,112,16,224,5,7,7,6,0,
+  0,128,240,136,136,136,240,128,4,7,7,6,0,255,128,224,
+  144,144,144,224,128,5,6,6,6,0,0,112,136,128,128,136,
+  112,5,6,6,6,0,0,136,216,168,136,136,136,5,6,6,
+  6,0,255,136,216,168,136,136,128,5,8,8,6,0,255,112,
+  136,136,136,112,64,224,64,5,6,6,6,0,0,112,136,8,
+  8,136,112,5,6,6,6,0,0,112,136,160,128,136,112,5,
+  6,6,6,0,0,112,136,40,8,136,112};

+ 192 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_Kana.h

@@ -0,0 +1,192 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+  Fontname: ISO10646_Kana
+  Copyright: A. Hardtung, public domain
+  Capital A Height: 7, '1' Height: 7
+  Calculated Max Values w= 5 h= 8 x= 2 y= 5 dx= 6 dy= 0 ascent= 8 len= 8
+  Font Bounding box     w= 6 h= 9 x= 0 y=-2
+  Calculated Min Values           x= 0 y=-1 dx= 0 dy= 0
+  Pure Font   ascent = 7 descent=-1
+  X Font      ascent = 7 descent=-1
+  Max Font    ascent = 8 descent=-1
+*/
+#include <U8glib.h>
+const u8g_fntpgm_uint8_t ISO10646_Kana_5x7[2482] U8G_SECTION(".progmem.ISO10646_Kana_5x7") = {
+  0, 6, 9, 0, 254, 7, 1, 145, 3, 32, 32, 255, 255, 8, 255, 7,
+  255, 0, 0, 0, 6, 0, 0, 1, 7, 7, 6, 2, 0, 128, 128, 128,
+  128, 128, 0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6,
+  0, 0, 80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32,
+  120, 160, 112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32,
+  64, 152, 24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104,
+  2, 3, 3, 6, 1, 4, 192, 64, 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, 32, 168, 112, 168, 32, 5, 5,
+  5, 6, 0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192,
+  64, 128, 5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192,
+  192, 5, 5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6,
+  0, 0, 112, 136, 152, 168, 200, 136, 112, 3, 7, 7, 6, 1, 0, 64,
+  192, 64, 64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112,
+  128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240,
+  5, 7, 7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7,
+  6, 0, 0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0,
+  48, 64, 128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16,
+  32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136,
+  112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 16, 96, 2, 5,
+  5, 6, 2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192,
+  192, 0, 192, 64, 128, 4, 7, 7, 6, 0, 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,
+  8, 16, 32, 0, 32, 5, 6, 6, 6, 0, 0, 112, 136, 8, 104, 168,
+  112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5, 7,
+  7, 6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6, 0,
+  0, 112, 136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 224, 144,
+  136, 136, 136, 144, 224, 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, 184, 136, 136, 112, 5, 7, 7, 6,
+  0, 0, 136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0, 128,
+  128, 128, 128, 128, 128, 128, 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, 216, 168, 136, 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, 7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5, 7,
+  7, 6, 0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6, 0,
+  0, 120, 128, 128, 112, 8, 8, 240, 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, 136, 136, 80, 32, 5,
+  7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7, 6,
+  0, 0, 136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0, 136,
+  136, 136, 80, 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, 5, 5, 6, 0, 1, 128, 64, 32, 16, 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, 0, 248, 2, 2, 2, 6, 2, 5, 128, 64,
+  5, 5, 5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7, 6, 0,
+  0, 128, 128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0, 112, 128,
+  128, 136, 112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136, 136, 120,
+  5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7, 6, 0,
+  0, 48, 72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255, 112, 136,
+  136, 120, 8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200, 136, 136,
+  136, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128, 3, 8,
+  8, 6, 1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7, 7, 6,
+  0, 0, 128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1, 0, 192,
+  64, 64, 64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168, 168, 168,
+  168, 5, 5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5, 5, 6,
+  0, 0, 112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240, 136, 136,
+  240, 128, 128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 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, 224, 64, 64,
+  72, 48, 5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5, 5, 5,
+  6, 0, 0, 136, 136, 136, 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, 6,
+  6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6, 0, 0,
+  248, 16, 32, 64, 248, 3, 7, 7, 6, 1, 0, 32, 64, 64, 128, 64,
+  64, 32, 1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128, 128, 128, 3,
+  7, 7, 6, 1, 0, 128, 64, 64, 32, 64, 64, 128, 5, 2, 2, 6,
+  0, 3, 104, 144, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
+  0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
+  0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+  0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
+  0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
+  0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+  0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
+  0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
+  0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+  0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
+  0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
+  0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+  0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 5, 3, 3, 6, 0, 1,
+  248, 0, 248, 4, 4, 4, 6, 0, 0, 240, 16, 96, 64, 5, 6, 6,
+  6, 0, 0, 248, 8, 40, 48, 32, 64, 3, 4, 4, 6, 1, 0, 32,
+  64, 192, 64, 4, 6, 6, 6, 0, 0, 16, 32, 96, 160, 32, 32, 4,
+  4, 4, 6, 0, 0, 32, 240, 144, 32, 5, 6, 6, 6, 0, 0, 32,
+  248, 136, 8, 16, 32, 3, 4, 4, 6, 1, 0, 224, 64, 64, 224, 5,
+  5, 5, 6, 0, 0, 248, 32, 32, 32, 248, 4, 4, 4, 6, 0, 0,
+  32, 240, 96, 160, 5, 6, 6, 6, 0, 0, 16, 248, 48, 80, 144, 16,
+  5, 6, 6, 6, 0, 0, 64, 248, 72, 72, 72, 144, 5, 8, 8, 6,
+  0, 0, 40, 0, 64, 248, 72, 72, 72, 144, 5, 6, 6, 6, 0, 0,
+  32, 248, 32, 248, 32, 32, 5, 8, 8, 6, 0, 0, 40, 0, 32, 248,
+  32, 248, 32, 32, 4, 5, 5, 6, 0, 0, 112, 144, 16, 32, 192, 5,
+  7, 7, 6, 0, 0, 40, 0, 112, 144, 16, 32, 192, 5, 6, 6, 6,
+  0, 0, 64, 120, 144, 16, 16, 32, 5, 8, 8, 6, 0, 0, 40, 0,
+  64, 120, 144, 16, 16, 32, 5, 5, 5, 6, 0, 0, 248, 8, 8, 8,
+  248, 5, 7, 7, 6, 0, 0, 40, 0, 248, 8, 8, 8, 248, 5, 6,
+  6, 6, 0, 0, 80, 248, 80, 16, 32, 64, 5, 8, 8, 6, 0, 0,
+  40, 0, 80, 248, 80, 16, 32, 64, 5, 5, 5, 6, 0, 0, 192, 8,
+  200, 16, 224, 5, 7, 7, 6, 0, 0, 40, 0, 192, 8, 200, 16, 224,
+  5, 5, 5, 6, 0, 0, 248, 16, 32, 80, 136, 5, 7, 7, 6, 0,
+  0, 40, 0, 248, 16, 32, 80, 136, 5, 6, 6, 6, 0, 0, 64, 248,
+  72, 80, 64, 56, 5, 8, 8, 6, 0, 0, 40, 0, 64, 248, 72, 80,
+  64, 56, 5, 5, 5, 6, 0, 0, 136, 136, 72, 16, 96, 5, 7, 7,
+  6, 0, 0, 40, 0, 136, 136, 72, 16, 96, 5, 5, 5, 6, 0, 0,
+  120, 72, 168, 16, 96, 5, 7, 7, 6, 0, 0, 40, 0, 120, 72, 168,
+  16, 96, 5, 6, 6, 6, 0, 0, 16, 224, 32, 248, 32, 64, 5, 8,
+  8, 6, 0, 0, 40, 0, 16, 224, 32, 248, 32, 64, 5, 4, 4, 6,
+  0, 0, 168, 168, 8, 48, 5, 5, 5, 6, 0, 0, 168, 168, 8, 16,
+  32, 5, 7, 7, 6, 0, 0, 40, 0, 168, 168, 8, 16, 32, 5, 6,
+  6, 6, 0, 0, 112, 0, 248, 32, 32, 64, 5, 8, 8, 6, 0, 0,
+  40, 0, 112, 0, 248, 32, 32, 64, 3, 6, 6, 6, 1, 0, 128, 128,
+  192, 160, 128, 128, 4, 8, 8, 6, 1, 0, 80, 0, 128, 128, 192, 160,
+  128, 128, 5, 6, 6, 6, 0, 0, 32, 248, 32, 32, 64, 128, 5, 5,
+  5, 6, 0, 0, 112, 0, 0, 0, 248, 5, 5, 5, 6, 0, 0, 248,
+  8, 80, 32, 208, 5, 6, 6, 6, 0, 0, 32, 248, 16, 32, 112, 168,
+  3, 6, 6, 6, 1, 0, 32, 32, 32, 32, 64, 128, 5, 5, 5, 6,
+  0, 0, 16, 136, 136, 136, 136, 5, 7, 7, 6, 0, 0, 40, 0, 16,
+  136, 136, 136, 136, 5, 8, 8, 6, 0, 0, 24, 24, 0, 16, 136, 136,
+  136, 136, 5, 6, 6, 6, 0, 0, 128, 128, 248, 128, 128, 120, 5, 7,
+  7, 6, 0, 0, 40, 128, 128, 248, 128, 128, 120, 5, 7, 7, 6, 0,
+  0, 24, 152, 128, 248, 128, 128, 120, 5, 5, 5, 6, 0, 0, 248, 8,
+  8, 16, 96, 5, 7, 7, 6, 0, 0, 40, 0, 248, 8, 8, 16, 96,
+  5, 8, 8, 6, 0, 0, 24, 24, 0, 248, 8, 8, 16, 96, 5, 4,
+  4, 6, 0, 1, 64, 160, 16, 8, 5, 6, 6, 6, 0, 1, 40, 0,
+  64, 160, 16, 8, 5, 6, 6, 6, 0, 1, 24, 24, 64, 160, 16, 8,
+  5, 6, 6, 6, 0, 0, 32, 248, 32, 168, 168, 32, 5, 8, 8, 6,
+  0, 0, 40, 0, 32, 248, 32, 168, 168, 32, 5, 8, 8, 6, 0, 0,
+  24, 24, 32, 248, 32, 168, 168, 32, 5, 5, 5, 6, 0, 0, 248, 8,
+  80, 32, 16, 4, 5, 5, 6, 1, 0, 224, 0, 224, 0, 240, 5, 5,
+  5, 6, 0, 0, 32, 64, 136, 248, 8, 5, 5, 5, 6, 0, 0, 8,
+  40, 16, 40, 192, 5, 5, 5, 6, 0, 0, 248, 64, 248, 64, 56, 5,
+  4, 4, 6, 0, 0, 64, 248, 80, 64, 5, 6, 6, 6, 0, 0, 64,
+  248, 72, 80, 64, 64, 4, 4, 4, 6, 0, 0, 96, 32, 32, 240, 5,
+  5, 5, 6, 0, 0, 112, 16, 16, 16, 248, 4, 5, 5, 6, 0, 0,
+  240, 16, 240, 16, 240, 5, 5, 5, 6, 0, 0, 248, 8, 248, 8, 248,
+  5, 6, 6, 6, 0, 0, 112, 0, 248, 8, 16, 32, 4, 6, 6, 6,
+  0, 0, 144, 144, 144, 144, 16, 32, 5, 5, 5, 6, 0, 0, 32, 160,
+  168, 168, 176, 4, 5, 5, 6, 0, 0, 128, 128, 144, 160, 192, 5, 5,
+  5, 6, 0, 0, 248, 136, 136, 136, 248, 4, 4, 4, 6, 0, 0, 240,
+  144, 16, 32, 5, 5, 5, 6, 0, 0, 248, 136, 8, 16, 32, 5, 6,
+  6, 6, 0, 0, 16, 248, 80, 80, 248, 16, 5, 5, 5, 6, 0, 0,
+  248, 8, 48, 32, 248, 5, 5, 5, 6, 0, 0, 248, 8, 248, 8, 48,
+  5, 5, 5, 6, 0, 0, 192, 8, 8, 16, 224, 5, 8, 8, 6, 0,
+  0, 40, 0, 32, 248, 136, 8, 16, 32, 4, 4, 4, 6, 0, 0, 64,
+  240, 80, 160, 4, 4, 4, 6, 0, 0, 64, 240, 32, 64, 5, 7, 7,
+  6, 0, 0, 40, 0, 248, 136, 8, 16, 96, 5, 8, 8, 6, 0, 0,
+  40, 0, 16, 248, 80, 80, 248, 16, 5, 7, 7, 6, 0, 0, 40, 0,
+  248, 8, 48, 32, 248, 5, 7, 7, 6, 0, 0, 40, 0, 248, 8, 248,
+  8, 48, 2, 2, 2, 6, 2, 2, 192, 192, 5, 1, 1, 6, 0, 2,
+  248, 5, 4, 4, 6, 0, 1, 128, 96, 16, 8, 5, 5, 5, 6, 0,
+  1, 40, 128, 96, 16, 8, 5, 6, 6, 6, 0, 0, 248, 8, 8, 8,
+  8, 8
+};

+ 151 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_ISO10646_SK.h

@@ -0,0 +1,151 @@
+/*
+  Fontname: ISO10646_SK
+  Copyright: A. Hardtung, modified by Roman Moravcik
+  Capital A Height: 7, '1' Height: 7
+  Calculated Max Values w= 6 h= 9 x= 2 y= 7 dx= 6 dy= 0 ascent= 8 len= 9
+  Font Bounding box     w= 6 h= 9 x= 0 y=-2
+  Calculated Min Values           x= 0 y=-1 dx= 0 dy= 0
+  Pure Font   ascent = 7 descent=-1
+  X Font      ascent = 7 descent=-1
+  Max Font    ascent = 8 descent=-1
+*/
+#include <U8glib.h>
+const u8g_fntpgm_uint8_t ISO10646_SK[2203] U8G_SECTION(".progmem.ISO10646_SK") = {
+  0,6,9,0,254,7,1,146,3,33,32,255,255,8,255,7,
+  255,0,0,0,6,0,0,1,7,7,6,2,0,128,128,128,
+  128,128,0,128,3,2,2,6,1,5,160,160,5,7,7,6,
+  0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,32,
+  120,160,112,40,240,32,5,7,7,6,0,0,192,200,16,32,
+  64,152,24,5,7,7,6,0,0,96,144,160,64,168,144,104,
+  2,3,3,6,1,4,192,64,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,32,168,112,168,32,5,5,
+  5,6,0,1,32,32,248,32,32,2,3,3,6,2,255,192,
+  64,128,5,1,1,6,0,3,248,2,2,2,6,2,0,192,
+  192,5,5,5,6,0,1,8,16,32,64,128,5,7,7,6,
+  0,0,112,136,136,136,136,136,112,3,7,7,6,1,0,64,
+  192,64,64,64,64,224,5,7,7,6,0,0,112,136,8,112,
+  128,128,248,5,7,7,6,0,0,248,16,32,16,8,8,240,
+  5,7,7,6,0,0,16,48,80,144,248,16,16,5,7,7,
+  6,0,0,248,128,240,8,8,136,112,5,7,7,6,0,0,
+  112,128,128,240,136,136,112,5,7,7,6,0,0,248,8,16,
+  32,32,32,32,5,7,7,6,0,0,112,136,136,112,136,136,
+  112,5,7,7,6,0,0,112,136,136,120,8,8,112,2,5,
+  5,6,2,0,192,192,0,192,192,2,6,6,6,2,255,192,
+  192,0,192,64,128,4,7,7,6,0,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,
+  8,16,32,0,32,5,7,7,6,0,0,112,136,8,104,168,
+  168,112,5,7,7,6,0,0,112,136,136,248,136,136,136,5,
+  7,7,6,0,0,240,136,136,240,136,136,240,5,7,7,6,
+  0,0,112,136,128,128,128,136,112,5,7,7,6,0,0,240,
+  136,136,136,136,136,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,184,136,136,112,5,7,7,
+  6,0,0,136,136,136,248,136,136,136,1,7,7,6,2,0,
+  128,128,128,128,128,128,128,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,216,168,136,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,7,7,6,0,0,112,136,136,136,168,144,104,5,
+  7,7,6,0,0,240,136,136,240,160,144,136,5,7,7,6,
+  0,0,120,128,128,112,8,8,240,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,136,136,80,32,
+  5,7,7,6,0,0,136,136,136,136,136,168,80,5,7,7,
+  6,0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,
+  136,136,136,80,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,5,5,6,0,1,128,64,32,16,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,0,248,2,2,2,6,2,5,128,
+  64,5,5,5,6,0,0,112,8,120,136,120,5,7,7,6,
+  0,0,128,128,176,200,136,136,240,5,5,5,6,0,0,112,
+  128,128,136,112,5,7,7,6,0,0,8,8,104,152,136,136,
+  120,5,5,5,6,0,0,112,136,248,128,112,5,7,7,6,
+  0,0,48,72,224,64,64,64,64,5,6,6,6,0,255,112,
+  136,136,120,8,112,5,7,7,6,0,0,128,128,176,200,136,
+  136,136,1,7,7,6,2,0,128,0,128,128,128,128,128,3,
+  8,8,6,1,255,32,0,32,32,32,32,160,64,4,7,7,
+  6,0,0,128,128,144,160,192,160,144,3,7,7,6,1,0,
+  192,64,64,64,64,64,224,5,5,5,6,0,0,208,168,168,
+  168,168,5,5,5,6,0,0,176,200,136,136,136,5,5,5,
+  6,0,0,112,136,136,136,112,5,6,6,6,0,255,240,136,
+  136,240,128,128,5,6,6,6,0,255,120,136,136,120,8,8,
+  5,5,5,6,0,0,176,200,128,128,128,5,5,5,6,0,
+  0,112,128,112,8,240,4,7,7,6,0,0,64,64,224,64,
+  64,64,48,5,5,5,6,0,0,136,136,136,152,104,5,5,
+  5,6,0,0,136,136,136,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,
+  6,6,6,0,255,136,136,136,120,8,112,5,5,5,6,0,
+  0,248,16,32,64,248,3,7,7,6,1,0,32,64,64,128,
+  64,64,32,1,7,7,6,2,0,128,128,128,128,128,128,128,
+  3,7,7,6,1,0,128,64,64,32,64,64,128,5,2,2,
+  6,0,2,104,144,0,0,0,6,0,0,5,8,8,6,0,
+  0,16,32,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,8,16,248,
+  128,128,240,128,248,3,8,8,6,1,0,32,64,224,64,64,
+  64,64,224,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,16,32,136,136,136,136,136,112,5,8,8,
+  6,0,0,16,32,136,136,80,32,32,32,5,8,8,6,0,
+  0,16,32,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,16,32,0,112,
+  136,248,128,112,2,8,8,6,2,0,64,128,0,128,128,128,
+  128,128,5,8,8,6,0,0,16,32,0,112,136,136,136,112,
+  5,8,8,6,0,0,32,80,0,112,136,136,136,112,5,8,
+  8,6,0,0,16,32,0,136,136,136,152,104,5,9,9,6,
+  0,255,16,32,0,136,136,136,120,8,112,5,8,8,6,0,
+  0,80,32,112,136,128,128,136,112,5,8,8,6,0,0,80,
+  32,0,112,128,128,136,112,5,8,8,6,0,0,80,32,240,
+  136,136,136,136,240,6,8,8,6,0,0,4,20,24,112,144,
+  144,144,112,5,8,8,6,0,0,16,32,128,128,128,128,128,
+  248,3,8,8,6,1,0,32,64,0,192,64,64,64,224,5,
+  8,8,6,0,0,16,144,160,128,128,128,128,248,5,8,8,
+  6,1,0,8,200,80,64,64,64,64,224,5,8,8,6,0,
+  0,80,32,136,200,168,152,136,136,5,8,8,6,0,0,80,
+  32,0,176,200,136,136,136,5,8,8,6,0,0,16,32,240,
+  136,240,160,144,136,5,8,8,6,0,0,16,32,0,176,200,
+  128,128,128,5,8,8,6,0,0,80,32,120,128,128,112,8,
+  240,5,8,8,6,0,0,80,32,0,112,128,112,8,240,5,
+  8,8,6,0,0,80,32,248,32,32,32,32,32,6,8,8,
+  6,0,0,4,68,72,224,64,64,64,48,5,8,8,6,0,
+  0,80,32,248,8,48,64,128,248,5,8,8,6,0,0,80,
+  32,0,248,16,32,64,248,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
+  0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
+  6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
+  0,0,6,0,0,0,0,0,6,0,0};

+ 45 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/dogm_font_data_Marlin_symbols.h

@@ -0,0 +1,45 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+  Fontname: Marlin_symbols
+  Copyright: Created with Fony 1.4.7
+  Capital A Height: 0, '1' Height: 0
+  Calculated Max Values w= 5 h=10 x= 0 y= 3 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 = 0 descent= 0
+  X Font      ascent = 0 descent= 0
+  Max Font    ascent = 8 descent=-2
+*/
+#include <U8glib.h>
+const u8g_fntpgm_uint8_t Marlin_symbols[140] U8G_SECTION(".progmem.Marlin_symbols") = {
+  0, 6, 9, 0, 254, 0, 0, 0, 0, 0, 1, 9, 0, 8, 254, 0,
+  0, 5, 8, 8, 6, 0, 0, 64, 240, 200, 136, 136, 152, 120, 16, 5,
+  8, 8, 6, 0, 0, 192, 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, 112, 32, 5, 9, 9, 6, 0, 255, 224, 128, 192, 176, 168,
+  40, 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, 3, 3, 3, 6, 0, 3, 64, 160, 64
+};

+ 73 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/drivers.h

@@ -0,0 +1,73 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#ifndef _DRIVERS_H_
+#define _DRIVERS_H_
+
+#include "MarlinConfig.h"
+
+#define A4988               0x001
+#define DRV8825             0x002
+#define LV8729              0x003
+#define L6470               0x104
+#define TB6560              0x005
+#define TB6600              0x006
+#define TMC2100             0x007
+#define TMC2130             0x108
+#define TMC2130_STANDALONE  0x008
+#define TMC2208             0x109
+#define TMC2208_STANDALONE  0x009
+#define TMC26X              0x10A
+#define TMC26X_STANDALONE   0x00A
+#define TMC2660             0x10B
+#define TMC2660_STANDALONE  0x00B
+
+#define _AXIS_DRIVER_TYPE(A,T) ( defined(A##_DRIVER_TYPE) && (A##_DRIVER_TYPE == T) )
+
+#define AXIS_DRIVER_TYPE_X(T) _AXIS_DRIVER_TYPE(X,T)
+#define AXIS_DRIVER_TYPE_Y(T) _AXIS_DRIVER_TYPE(Y,T)
+#define AXIS_DRIVER_TYPE_Z(T) _AXIS_DRIVER_TYPE(Z,T)
+#define AXIS_DRIVER_TYPE_X2(T) (ENABLED(X_DUAL_STEPPER_DRIVERS) || ENABLED(DUAL_X_CARRIAGE)) && _AXIS_DRIVER_TYPE(X2,T)
+#define AXIS_DRIVER_TYPE_Y2(T) (ENABLED(Y_DUAL_STEPPER_DRIVERS) && _AXIS_DRIVER_TYPE(Y2,T))
+#define AXIS_DRIVER_TYPE_Z2(T) (ENABLED(Z_DUAL_STEPPER_DRIVERS) && _AXIS_DRIVER_TYPE(Z2,T))
+#define AXIS_DRIVER_TYPE_E0(T) (E_STEPPERS > 0 && _AXIS_DRIVER_TYPE(E0,T))
+#define AXIS_DRIVER_TYPE_E1(T) (E_STEPPERS > 1 && _AXIS_DRIVER_TYPE(E1,T))
+#define AXIS_DRIVER_TYPE_E2(T) (E_STEPPERS > 2 && _AXIS_DRIVER_TYPE(E2,T))
+#define AXIS_DRIVER_TYPE_E3(T) (E_STEPPERS > 3 && _AXIS_DRIVER_TYPE(E3,T))
+#define AXIS_DRIVER_TYPE_E4(T) (E_STEPPERS > 4 && _AXIS_DRIVER_TYPE(E4,T))
+
+#define AXIS_DRIVER_TYPE(A,T) AXIS_DRIVER_TYPE_##A(T)
+
+#define HAS_DRIVER(T)  (AXIS_DRIVER_TYPE_X(T)  || AXIS_DRIVER_TYPE_X2(T) || \
+                        AXIS_DRIVER_TYPE_Y(T)  || AXIS_DRIVER_TYPE_Y2(T) || \
+                        AXIS_DRIVER_TYPE_Z(T)  || AXIS_DRIVER_TYPE_Z2(T) || \
+                        AXIS_DRIVER_TYPE_E0(T) || AXIS_DRIVER_TYPE_E1(T) || \
+                        AXIS_DRIVER_TYPE_E2(T) || AXIS_DRIVER_TYPE_E3(T) || \
+                        AXIS_DRIVER_TYPE_E4(T) )
+
+// Test for supported TMC drivers that require advanced configuration
+// Does not match standalone configurations
+#define HAS_TRINAMIC (HAS_DRIVER(TMC2130) || HAS_DRIVER(TMC2208))
+
+#define AXIS_IS_TMC(A) ( AXIS_DRIVER_TYPE_##A(TMC2130) || \
+                         AXIS_DRIVER_TYPE_##A(TMC2208) )
+
+#endif // _DRIVERS_H_

+ 170 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/duration_t.h

@@ -0,0 +1,170 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __DURATION_T__
+#define __DURATION_T__
+
+#include <stdio.h>
+#include <inttypes.h>
+
+struct duration_t {
+  /**
+   * @brief Duration is stored in seconds
+   */
+  uint32_t value;
+
+  /**
+   * @brief Constructor
+   */
+  duration_t()
+    : duration_t(0) {};
+
+  /**
+   * @brief Constructor
+   *
+   * @param seconds The number of seconds
+   */
+  duration_t(uint32_t const &seconds) {
+    this->value = seconds;
+  }
+
+  /**
+   * @brief Equality comparison
+   * @details Overloads the equality comparison operator
+   *
+   * @param value The number of seconds to compare to
+   * @return True if both durations are equal
+   */
+  bool operator==(const uint32_t &value) const {
+    return (this->value == value);
+  }
+
+  /**
+   * @brief Inequality comparison
+   * @details Overloads the inequality comparison operator
+   *
+   * @param value The number of seconds to compare to
+   * @return False if both durations are equal
+   */
+  bool operator!=(const uint32_t &value) const {
+    return ! this->operator==(value);
+  }
+
+  /**
+   * @brief Formats the duration as years
+   * @return The number of years
+   */
+  inline uint8_t year() const {
+    return this->day() / 365;
+  }
+
+  /**
+   * @brief Formats the duration as days
+   * @return The number of days
+   */
+  inline uint16_t day() const {
+    return this->hour() / 24;
+  }
+
+  /**
+   * @brief Formats the duration as hours
+   * @return The number of hours
+   */
+  inline uint32_t hour() const {
+    return this->minute() / 60;
+  }
+
+  /**
+   * @brief Formats the duration as minutes
+   * @return The number of minutes
+   */
+  inline uint32_t minute() const {
+    return this->second() / 60;
+  }
+
+  /**
+   * @brief Formats the duration as seconds
+   * @return The number of seconds
+   */
+  inline uint32_t second() const {
+    return this->value;
+  }
+
+  /**
+   * @brief Formats the duration as a string
+   * @details String will be formated using a "full" representation of duration
+   *
+   * @param buffer The array pointed to must be able to accommodate 21 bytes
+   *
+   * Output examples:
+   *  123456789012345678901 (strlen)
+   *  135y 364d 23h 59m 59s
+   *  364d 23h 59m 59s
+   *  23h 59m 59s
+   *  59m 59s
+   *  59s
+   */
+  void toString(char *buffer) const {
+    int y = this->year(),
+        d = this->day() % 365,
+        h = this->hour() % 24,
+        m = this->minute() % 60,
+        s = this->second() % 60;
+
+    if (y) sprintf_P(buffer, PSTR("%iy %id %ih %im %is"), y, d, h, m, s);
+    else if (d) sprintf_P(buffer, PSTR("%id %ih %im %is"), d, h, m, s);
+    else if (h) sprintf_P(buffer, PSTR("%ih %im %is"), h, m, s);
+    else if (m) sprintf_P(buffer, PSTR("%im %is"), m, s);
+    else sprintf_P(buffer, PSTR("%is"), s);
+  }
+
+  /**
+   * @brief Formats the duration as a string
+   * @details String will be formated using a "digital" representation of duration
+   *
+   * @param buffer The array pointed to must be able to accommodate 10 bytes
+   *
+   * Output examples:
+   *  123456789 (strlen)
+   *  99:59
+   *  11d 12:33
+   */
+  uint8_t toDigital(char *buffer, bool with_days=false) const {
+    uint16_t h = uint16_t(this->hour()),
+             m = uint16_t(this->minute() % 60UL);
+    if (with_days) {
+      uint16_t d = this->day();
+      sprintf_P(buffer, PSTR("%ud %02u:%02u"), d, h % 24, m);
+      return d >= 10 ? 9 : 8;
+    }
+    else if (h < 100) {
+      sprintf_P(buffer, PSTR("%02u:%02u"), h, m);
+      return 5;
+    }
+    else {
+      sprintf_P(buffer, PSTR("%u:%02u"), h, m);
+      return 6;
+    }
+  }
+};
+
+#endif // __DURATION_T__

+ 40 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/emergency_parser.cpp

@@ -0,0 +1,40 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * emergency_parser.cpp - Intercept special commands directly in the serial stream
+ */
+
+#include "MarlinConfig.h"
+
+#if ENABLED(EMERGENCY_PARSER)
+
+#include "emergency_parser.h"
+
+// Static data members
+bool EmergencyParser::killed_by_M112; // = false
+EmergencyParser::State EmergencyParser::state; // = EP_RESET
+
+// Global instance
+EmergencyParser emergency_parser;
+
+#endif // EMERGENCY_PARSER

+ 144 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/emergency_parser.h

@@ -0,0 +1,144 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * emergency_parser.h - Intercept special commands directly in the serial stream
+ */
+
+#ifndef _EMERGENCY_PARSER_H_
+#define _EMERGENCY_PARSER_H_
+
+// External references
+extern volatile bool wait_for_user, wait_for_heatup;
+void quickstop_stepper();
+
+class EmergencyParser {
+
+public:
+
+  // Currently looking for: M108, M112, M410
+  enum State : char {
+    EP_RESET,
+    EP_N,
+    EP_M,
+    EP_M1,
+    EP_M10,
+    EP_M108,
+    EP_M11,
+    EP_M112,
+    EP_M4,
+    EP_M41,
+    EP_M410,
+    EP_IGNORE // to '\n'
+  };
+
+  static bool killed_by_M112;
+  static State state;
+
+  EmergencyParser() {}
+
+  __attribute__((always_inline)) inline
+  static void update(const uint8_t c) {
+
+    switch (state) {
+      case EP_RESET:
+        switch (c) {
+          case ' ': break;
+          case 'N': state = EP_N;      break;
+          case 'M': state = EP_M;      break;
+          default: state  = EP_IGNORE;
+        }
+        break;
+
+      case EP_N:
+        switch (c) {
+          case '0': case '1': case '2':
+          case '3': case '4': case '5':
+          case '6': case '7': case '8':
+          case '9': case '-': case ' ':   break;
+          case 'M': state = EP_M;      break;
+          default:  state = EP_IGNORE;
+        }
+        break;
+
+      case EP_M:
+        switch (c) {
+          case ' ': break;
+          case '1': state = EP_M1;     break;
+          case '4': state = EP_M4;     break;
+          default: state  = EP_IGNORE;
+        }
+        break;
+
+      case EP_M1:
+        switch (c) {
+          case '0': state = EP_M10;    break;
+          case '1': state = EP_M11;    break;
+          default: state  = EP_IGNORE;
+        }
+        break;
+
+      case EP_M10:
+        state = (c == '8') ? EP_M108 : EP_IGNORE;
+        break;
+
+      case EP_M11:
+        state = (c == '2') ? EP_M112 : EP_IGNORE;
+        break;
+
+      case EP_M4:
+        state = (c == '1') ? EP_M41 : EP_IGNORE;
+        break;
+
+      case EP_M41:
+        state = (c == '0') ? EP_M410 : EP_IGNORE;
+        break;
+
+      case EP_IGNORE:
+        if (c == '\n') state = EP_RESET;
+        break;
+
+      default:
+        if (c == '\n') {
+          switch (state) {
+            case EP_M108:
+              wait_for_user = wait_for_heatup = false;
+              break;
+            case EP_M112:
+              killed_by_M112 = true;
+              break;
+            case EP_M410:
+              quickstop_stepper();
+              break;
+            default:
+              break;
+          }
+          state = EP_RESET;
+        }
+    }
+  }
+
+};
+
+extern EmergencyParser emergency_parser;
+
+#endif // _EMERGENCY_PARSER_H_

+ 239 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/endstop_interrupts.h

@@ -0,0 +1,239 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Endstop Interrupts
+ *
+ * Without endstop interrupts the endstop pins must be polled continually in
+ * the temperature-ISR via endstops.update(), most of the time finding no change.
+ * With this feature endstops.update() is called only when we know that at
+ * least one endstop has changed state, saving valuable CPU cycles.
+ *
+ * This feature only works when all used endstop pins can generate either an
+ * 'external interrupt' or a 'pin change interrupt'.
+ *
+ * Test whether pins issue interrupts on your board by flashing 'pin_interrupt_test.ino'.
+ * (Located in Marlin/buildroot/share/pin_interrupt_test/pin_interrupt_test.ino)
+ */
+
+#ifndef _ENDSTOP_INTERRUPTS_H_
+#define _ENDSTOP_INTERRUPTS_H_
+
+#include "macros.h"
+
+// One ISR for all EXT-Interrupts
+void endstop_ISR(void) { endstops.update(); }
+
+/**
+ * Patch for pins_arduino.h (...\Arduino\hardware\arduino\avr\variants\mega\pins_arduino.h)
+ *
+ * These macros for the Arduino MEGA do not include the two connected pins on Port J (D13, D14).
+ * So we extend them here because these are the normal pins for Y_MIN and Y_MAX on RAMPS.
+ * There are more PCI-enabled processor pins on Port J, but they are not connected to Arduino MEGA.
+ */
+#if defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_AVR_MEGA)
+  #undef  digitalPinToPCICR
+  #define digitalPinToPCICR(p)    ( WITHIN(p, 10, 15) || \
+                                    WITHIN(p, 50, 53) || \
+                                    WITHIN(p, 62, 69) ? &PCICR : (uint8_t*)0 )
+  #undef  digitalPinToPCICRbit
+  #define digitalPinToPCICRbit(p) ( WITHIN(p, 10, 13) || WITHIN(p, 50, 53) ? 0 : \
+                                    WITHIN(p, 14, 15) ? 1 : \
+                                    WITHIN(p, 62, 69) ? 2 : \
+                                    0 )
+  #undef  digitalPinToPCMSK
+  #define digitalPinToPCMSK(p)    ( WITHIN(p, 10, 13) || WITHIN(p, 50, 53) ? &PCMSK0 : \
+                                    WITHIN(p, 14, 15) ? &PCMSK1 : \
+                                    WITHIN(p, 62, 69) ? &PCMSK2 : \
+                                    (uint8_t *)0 )
+  #undef  digitalPinToPCMSKbit
+  #define digitalPinToPCMSKbit(p) ( WITHIN(p, 10, 13) ? ((p) - 6) : \
+                                    (p) == 14 || (p) == 51 ? 2 : \
+                                    (p) == 15 || (p) == 52 ? 1 : \
+                                    (p) == 50 ? 3 : \
+                                    (p) == 53 ? 0 : \
+                                    WITHIN(p, 62, 69) ? ((p) - 62) : \
+                                    0 )
+#endif
+
+
+// Install Pin change interrupt for a pin. Can be called multiple times.
+void pciSetup(const int8_t pin) {
+  SBI(*digitalPinToPCMSK(pin), digitalPinToPCMSKbit(pin));  // enable pin
+  SBI(PCIFR, digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
+  SBI(PCICR, digitalPinToPCICRbit(pin)); // enable interrupt for the group
+}
+
+
+// Handlers for pin change interrupts
+#ifdef PCINT0_vect
+  ISR(PCINT0_vect) { endstop_ISR(); }
+#endif
+
+#ifdef PCINT1_vect
+  ISR(PCINT1_vect) { endstop_ISR(); }
+#endif
+
+#ifdef PCINT2_vect
+  ISR(PCINT2_vect) { endstop_ISR(); }
+#endif
+
+#ifdef PCINT3_vect
+  ISR(PCINT3_vect) { endstop_ISR(); }
+#endif
+
+void setup_endstop_interrupts( void ) {
+
+  #if HAS_X_MAX
+    #if digitalPinToInterrupt(X_MAX_PIN) != NOT_AN_INTERRUPT // if pin has an external interrupt
+      attachInterrupt(digitalPinToInterrupt(X_MAX_PIN), endstop_ISR, CHANGE); // assign it
+    #else
+      // Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
+      static_assert(digitalPinToPCICR(X_MAX_PIN) != NULL, "X_MAX_PIN is not interrupt-capable"); // if pin has no pin change interrupt - error
+      pciSetup(X_MAX_PIN);                                                            // assign it
+    #endif
+  #endif
+
+  #if HAS_X_MIN
+    #if digitalPinToInterrupt(X_MIN_PIN) != NOT_AN_INTERRUPT
+      attachInterrupt(digitalPinToInterrupt(X_MIN_PIN), endstop_ISR, CHANGE);
+    #else
+      // Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
+      static_assert(digitalPinToPCICR(X_MIN_PIN) != NULL, "X_MIN_PIN is not interrupt-capable");
+      pciSetup(X_MIN_PIN);
+    #endif
+  #endif
+
+  #if HAS_Y_MAX
+    #if digitalPinToInterrupt(Y_MAX_PIN) != NOT_AN_INTERRUPT
+      attachInterrupt(digitalPinToInterrupt(Y_MAX_PIN), endstop_ISR, CHANGE);
+    #else
+      // Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
+      static_assert(digitalPinToPCICR(Y_MAX_PIN) != NULL, "Y_MAX_PIN is not interrupt-capable");
+      pciSetup(Y_MAX_PIN);
+    #endif
+  #endif
+
+  #if HAS_Y_MIN
+    #if digitalPinToInterrupt(Y_MIN_PIN) != NOT_AN_INTERRUPT
+      attachInterrupt(digitalPinToInterrupt(Y_MIN_PIN), endstop_ISR, CHANGE);
+    #else
+      // Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
+      static_assert(digitalPinToPCICR(Y_MIN_PIN) != NULL, "Y_MIN_PIN is not interrupt-capable");
+      pciSetup(Y_MIN_PIN);
+    #endif
+  #endif
+
+  #if HAS_Z_MAX
+    #if digitalPinToInterrupt(Z_MAX_PIN) != NOT_AN_INTERRUPT
+      attachInterrupt(digitalPinToInterrupt(Z_MAX_PIN), endstop_ISR, CHANGE);
+    #else
+      // Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
+      static_assert(digitalPinToPCICR(Z_MAX_PIN) != NULL, "Z_MAX_PIN is not interrupt-capable");
+      pciSetup(Z_MAX_PIN);
+    #endif
+  #endif
+
+  #if HAS_Z_MIN
+    #if digitalPinToInterrupt(Z_MIN_PIN) != NOT_AN_INTERRUPT
+      attachInterrupt(digitalPinToInterrupt(Z_MIN_PIN), endstop_ISR, CHANGE);
+    #else
+      // Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
+      static_assert(digitalPinToPCICR(Z_MIN_PIN) != NULL, "Z_MIN_PIN is not interrupt-capable");
+      pciSetup(Z_MIN_PIN);
+    #endif
+  #endif
+
+  #if HAS_X2_MAX
+    #if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT)
+      attachInterrupt(digitalPinToInterrupt(X2_MAX_PIN), endstop_ISR, CHANGE);
+    #else
+      // Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
+      static_assert(digitalPinToPCICR(X2_MAX_PIN) != NULL, "X2_MAX_PIN is not interrupt-capable");
+      pciSetup(X2_MAX_PIN);
+    #endif
+  #endif
+
+  #if HAS_X2_MIN
+    #if (digitalPinToInterrupt(X2_MIN_PIN) != NOT_AN_INTERRUPT)
+      attachInterrupt(digitalPinToInterrupt(X2_MIN_PIN), endstop_ISR, CHANGE);
+    #else
+      // Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
+      static_assert(digitalPinToPCICR(X2_MIN_PIN) != NULL, "X2_MIN_PIN is not interrupt-capable");
+      pciSetup(X2_MIN_PIN);
+    #endif
+  #endif
+
+  #if HAS_Y2_MAX
+    #if (digitalPinToInterrupt(Y2_MAX_PIN) != NOT_AN_INTERRUPT)
+      attachInterrupt(digitalPinToInterrupt(Y2_MAX_PIN), endstop_ISR, CHANGE);
+    #else
+      // Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
+      static_assert(digitalPinToPCICR(Y2_MAX_PIN) != NULL, "Y2_MAX_PIN is not interrupt-capable");
+      pciSetup(Y2_MAX_PIN);
+    #endif
+  #endif
+
+  #if HAS_Y2_MIN
+    #if (digitalPinToInterrupt(Y2_MIN_PIN) != NOT_AN_INTERRUPT)
+      attachInterrupt(digitalPinToInterrupt(Y2_MIN_PIN), endstop_ISR, CHANGE);
+    #else
+      // Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
+      static_assert(digitalPinToPCICR(Y2_MIN_PIN) != NULL, "Y2_MIN_PIN is not interrupt-capable");
+      pciSetup(Y2_MIN_PIN);
+    #endif
+  #endif
+
+  #if HAS_Z2_MAX
+    #if digitalPinToInterrupt(Z2_MAX_PIN) != NOT_AN_INTERRUPT
+      attachInterrupt(digitalPinToInterrupt(Z2_MAX_PIN), endstop_ISR, CHANGE);
+    #else
+      // Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
+      static_assert(digitalPinToPCICR(Z2_MAX_PIN) != NULL, "Z2_MAX_PIN is not interrupt-capable");
+      pciSetup(Z2_MAX_PIN);
+    #endif
+  #endif
+
+  #if HAS_Z2_MIN
+    #if digitalPinToInterrupt(Z2_MIN_PIN) != NOT_AN_INTERRUPT
+      attachInterrupt(digitalPinToInterrupt(Z2_MIN_PIN), endstop_ISR, CHANGE);
+    #else
+      // Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
+      static_assert(digitalPinToPCICR(Z2_MIN_PIN) != NULL, "Z2_MIN_PIN is not interrupt-capable");
+      pciSetup(Z2_MIN_PIN);
+    #endif
+  #endif
+
+  #if HAS_Z_MIN_PROBE_PIN
+    #if digitalPinToInterrupt(Z_MIN_PROBE_PIN) != NOT_AN_INTERRUPT
+      attachInterrupt(digitalPinToInterrupt(Z_MIN_PROBE_PIN), endstop_ISR, CHANGE);
+    #else
+      // Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
+      static_assert(digitalPinToPCICR(Z_MIN_PROBE_PIN) != NULL, "Z_MIN_PROBE_PIN is not interrupt-capable");
+      pciSetup(Z_MIN_PROBE_PIN);
+    #endif
+  #endif
+
+  // If we arrive here without raising an assertion, each pin has either an EXT-interrupt or a PCI.
+}
+
+#endif // _ENDSTOP_INTERRUPTS_H_

+ 774 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/endstops.cpp

@@ -0,0 +1,774 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * endstops.cpp - A singleton object to manage endstops
+ */
+
+#include "Marlin.h"
+#include "cardreader.h"
+#include "endstops.h"
+#include "temperature.h"
+#include "stepper.h"
+#include "ultralcd.h"
+
+#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
+  #include "endstop_interrupts.h"
+#endif
+
+Endstops endstops;
+
+// public:
+
+bool Endstops::enabled, Endstops::enabled_globally; // Initialized by settings.load()
+volatile uint8_t Endstops::hit_state;
+
+Endstops::esbits_t Endstops::live_state = 0;
+
+#if ENABLED(ENDSTOP_NOISE_FILTER)
+  Endstops::esbits_t Endstops::validated_live_state;
+  uint8_t Endstops::endstop_poll_count;
+#endif
+
+#if HAS_BED_PROBE
+  volatile bool Endstops::z_probe_enabled = false;
+#endif
+
+// Initialized by settings.load()
+#if ENABLED(X_DUAL_ENDSTOPS)
+  float Endstops::x_endstop_adj;
+#endif
+#if ENABLED(Y_DUAL_ENDSTOPS)
+  float Endstops::y_endstop_adj;
+#endif
+#if ENABLED(Z_DUAL_ENDSTOPS)
+  float Endstops::z_endstop_adj;
+#endif
+
+/**
+ * Class and Instance Methods
+ */
+
+void Endstops::init() {
+
+  #if HAS_X_MIN
+    #if ENABLED(ENDSTOPPULLUP_XMIN)
+      SET_INPUT_PULLUP(X_MIN_PIN);
+    #else
+      SET_INPUT(X_MIN_PIN);
+    #endif
+  #endif
+
+  #if HAS_X2_MIN
+    #if ENABLED(ENDSTOPPULLUP_XMIN)
+      SET_INPUT_PULLUP(X2_MIN_PIN);
+    #else
+      SET_INPUT(X2_MIN_PIN);
+    #endif
+  #endif
+
+  #if HAS_Y_MIN
+    #if ENABLED(ENDSTOPPULLUP_YMIN)
+      SET_INPUT_PULLUP(Y_MIN_PIN);
+    #else
+      SET_INPUT(Y_MIN_PIN);
+    #endif
+  #endif
+
+  #if HAS_Y2_MIN
+    #if ENABLED(ENDSTOPPULLUP_YMIN)
+      SET_INPUT_PULLUP(Y2_MIN_PIN);
+    #else
+      SET_INPUT(Y2_MIN_PIN);
+    #endif
+  #endif
+
+  #if HAS_Z_MIN
+    #if ENABLED(ENDSTOPPULLUP_ZMIN)
+      SET_INPUT_PULLUP(Z_MIN_PIN);
+    #else
+      SET_INPUT(Z_MIN_PIN);
+    #endif
+  #endif
+
+  #if HAS_Z2_MIN
+    #if ENABLED(ENDSTOPPULLUP_ZMIN)
+      SET_INPUT_PULLUP(Z2_MIN_PIN);
+    #else
+      SET_INPUT(Z2_MIN_PIN);
+    #endif
+  #endif
+
+  #if HAS_X_MAX
+    #if ENABLED(ENDSTOPPULLUP_XMAX)
+      SET_INPUT_PULLUP(X_MAX_PIN);
+    #else
+      SET_INPUT(X_MAX_PIN);
+    #endif
+  #endif
+
+  #if HAS_X2_MAX
+    #if ENABLED(ENDSTOPPULLUP_XMAX)
+      SET_INPUT_PULLUP(X2_MAX_PIN);
+    #else
+      SET_INPUT(X2_MAX_PIN);
+    #endif
+  #endif
+
+  #if HAS_Y_MAX
+    #if ENABLED(ENDSTOPPULLUP_YMAX)
+      SET_INPUT_PULLUP(Y_MAX_PIN);
+    #else
+      SET_INPUT(Y_MAX_PIN);
+    #endif
+  #endif
+
+  #if HAS_Y2_MAX
+    #if ENABLED(ENDSTOPPULLUP_YMAX)
+      SET_INPUT_PULLUP(Y2_MAX_PIN);
+    #else
+      SET_INPUT(Y2_MAX_PIN);
+    #endif
+  #endif
+
+  #if HAS_Z_MAX
+    #if ENABLED(ENDSTOPPULLUP_ZMAX)
+      SET_INPUT_PULLUP(Z_MAX_PIN);
+    #else
+      SET_INPUT(Z_MAX_PIN);
+    #endif
+  #endif
+
+  #if HAS_Z2_MAX
+    #if ENABLED(ENDSTOPPULLUP_ZMAX)
+      SET_INPUT_PULLUP(Z2_MAX_PIN);
+    #else
+      SET_INPUT(Z2_MAX_PIN);
+    #endif
+  #endif
+
+  #if ENABLED(Z_MIN_PROBE_ENDSTOP)
+    #if ENABLED(ENDSTOPPULLUP_ZMIN_PROBE)
+      SET_INPUT_PULLUP(Z_MIN_PROBE_PIN);
+    #else
+      SET_INPUT(Z_MIN_PROBE_PIN);
+    #endif
+  #endif
+
+  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
+    setup_endstop_interrupts();
+  #endif
+
+  // Enable endstops
+  enable_globally(
+    #if ENABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)
+      true
+    #else
+      false
+    #endif
+  );
+
+} // Endstops::init
+
+// Called at ~1KHz from Temperature ISR: Poll endstop state if required
+void Endstops::poll() {
+
+  #if ENABLED(PINS_DEBUGGING)
+    run_monitor();  // report changes in endstop status
+  #endif
+
+  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE) && ENABLED(ENDSTOP_NOISE_FILTER)
+    if (endstop_poll_count) update();
+  #elif DISABLED(ENDSTOP_INTERRUPTS_FEATURE) || ENABLED(ENDSTOP_NOISE_FILTER)
+    update();
+  #endif
+}
+
+void Endstops::enable_globally(const bool onoff) {
+  enabled_globally = enabled = onoff;
+
+  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
+    update();
+  #endif
+}
+
+// Enable / disable endstop checking
+void Endstops::enable(const bool onoff) {
+  enabled = onoff;
+
+  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
+    update();
+  #endif
+}
+
+// Disable / Enable endstops based on ENSTOPS_ONLY_FOR_HOMING and global enable
+void Endstops::not_homing() {
+  enabled = enabled_globally;
+
+  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
+    update();
+  #endif
+}
+
+#if ENABLED(VALIDATE_HOMING_ENDSTOPS)
+  // If the last move failed to trigger an endstop, call kill
+  void Endstops::validate_homing_move() {
+    if (trigger_state()) hit_on_purpose();
+    else kill(PSTR(MSG_ERR_HOMING_FAILED));
+  }
+#endif
+
+// Enable / disable endstop z-probe checking
+#if HAS_BED_PROBE
+  void Endstops::enable_z_probe(const bool onoff) {
+    z_probe_enabled = onoff;
+
+    #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
+      update();
+    #endif
+  }
+#endif
+
+#if ENABLED(PINS_DEBUGGING)
+  void Endstops::run_monitor() {
+    if (!monitor_flag) return;
+    static uint8_t monitor_count = 16;  // offset this check from the others
+    monitor_count += _BV(1);            //  15 Hz
+    monitor_count &= 0x7F;
+    if (!monitor_count) monitor();      // report changes in endstop status
+  }
+#endif
+
+void Endstops::event_handler() {
+  static uint8_t prev_hit_state; // = 0
+  if (hit_state && hit_state != prev_hit_state) {
+    #if ENABLED(ULTRA_LCD)
+      char chrX = ' ', chrY = ' ', chrZ = ' ', chrP = ' ';
+      #define _SET_STOP_CHAR(A,C) (chr## A = C)
+    #else
+      #define _SET_STOP_CHAR(A,C) ;
+    #endif
+
+    #define _ENDSTOP_HIT_ECHO(A,C) do{ \
+      SERIAL_ECHOPAIR(" " STRINGIFY(A) ":", planner.triggered_position_mm(_AXIS(A))); \
+      _SET_STOP_CHAR(A,C); }while(0)
+
+    #define _ENDSTOP_HIT_TEST(A,C) \
+      if (TEST(hit_state, A ##_MIN) || TEST(hit_state, A ##_MAX)) \
+        _ENDSTOP_HIT_ECHO(A,C)
+
+    #define ENDSTOP_HIT_TEST_X() _ENDSTOP_HIT_TEST(X,'X')
+    #define ENDSTOP_HIT_TEST_Y() _ENDSTOP_HIT_TEST(Y,'Y')
+    #define ENDSTOP_HIT_TEST_Z() _ENDSTOP_HIT_TEST(Z,'Z')
+
+    SERIAL_ECHO_START();
+    SERIAL_ECHOPGM(MSG_ENDSTOPS_HIT);
+    ENDSTOP_HIT_TEST_X();
+    ENDSTOP_HIT_TEST_Y();
+    ENDSTOP_HIT_TEST_Z();
+
+    #if ENABLED(Z_MIN_PROBE_ENDSTOP)
+      #define P_AXIS Z_AXIS
+      if (TEST(hit_state, Z_MIN_PROBE)) _ENDSTOP_HIT_ECHO(P, 'P');
+    #endif
+    SERIAL_EOL();
+
+    #if ENABLED(ULTRA_LCD)
+      lcd_status_printf_P(0, PSTR(MSG_LCD_ENDSTOPS " %c %c %c %c"), chrX, chrY, chrZ, chrP);
+    #endif
+
+    #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED) && ENABLED(SDSUPPORT)
+      if (planner.abort_on_endstop_hit) {
+        card.sdprinting = false;
+        card.closefile();
+        quickstop_stepper();
+        thermalManager.disable_all_heaters(); // switch off all heaters.
+      }
+    #endif
+  }
+  prev_hit_state = hit_state;
+} // Endstops::report_state
+
+static void print_es_state(const bool is_hit, const char * const label=NULL) {
+  if (label) serialprintPGM(label);
+  SERIAL_PROTOCOLPGM(": ");
+  serialprintPGM(is_hit ? PSTR(MSG_ENDSTOP_HIT) : PSTR(MSG_ENDSTOP_OPEN));
+  SERIAL_EOL();
+}
+
+void _O2 Endstops::M119() {
+  SERIAL_PROTOCOLLNPGM(MSG_M119_REPORT);
+  #define ES_REPORT(S) print_es_state(READ(S##_PIN) != S##_ENDSTOP_INVERTING, PSTR(MSG_##S))
+  #if HAS_X_MIN
+    ES_REPORT(X_MIN);
+  #endif
+  #if HAS_X2_MIN
+    ES_REPORT(X2_MIN);
+  #endif
+  #if HAS_X_MAX
+    ES_REPORT(X_MAX);
+  #endif
+  #if HAS_X2_MAX
+    ES_REPORT(X2_MAX);
+  #endif
+  #if HAS_Y_MIN
+    ES_REPORT(Y_MIN);
+  #endif
+  #if HAS_Y2_MIN
+    ES_REPORT(Y2_MIN);
+  #endif
+  #if HAS_Y_MAX
+    ES_REPORT(Y_MAX);
+  #endif
+  #if HAS_Y2_MAX
+    ES_REPORT(Y2_MAX);
+  #endif
+  #if HAS_Z_MIN
+    ES_REPORT(Z_MIN);
+  #endif
+  #if HAS_Z2_MIN
+    ES_REPORT(Z2_MIN);
+  #endif
+  #if HAS_Z_MAX
+    ES_REPORT(Z_MAX);
+  #endif
+  #if HAS_Z2_MAX
+    ES_REPORT(Z2_MAX);
+  #endif
+  #if ENABLED(Z_MIN_PROBE_ENDSTOP)
+    print_es_state(READ(Z_MIN_PROBE_PIN) != Z_MIN_PROBE_ENDSTOP_INVERTING, PSTR(MSG_Z_PROBE));
+  #endif
+  #if ENABLED(FILAMENT_RUNOUT_SENSOR)
+    #if NUM_RUNOUT_SENSORS == 1
+      print_es_state(READ(FIL_RUNOUT_PIN) != FIL_RUNOUT_INVERTING, PSTR(MSG_FILAMENT_RUNOUT_SENSOR));
+    #else
+      for (uint8_t i = 1; i <= NUM_RUNOUT_SENSORS; i++) {
+        pin_t pin;
+        switch (i) {
+          default: continue;
+          case 1: pin = FIL_RUNOUT_PIN; break;
+          case 2: pin = FIL_RUNOUT2_PIN; break;
+          #if NUM_RUNOUT_SENSORS > 2
+            case 3: pin = FIL_RUNOUT3_PIN; break;
+            #if NUM_RUNOUT_SENSORS > 3
+              case 4: pin = FIL_RUNOUT4_PIN; break;
+              #if NUM_RUNOUT_SENSORS > 4
+                case 5: pin = FIL_RUNOUT5_PIN; break;
+              #endif
+            #endif
+          #endif
+        }
+        SERIAL_PROTOCOLPGM(MSG_FILAMENT_RUNOUT_SENSOR);
+        if (i > 1) { SERIAL_CHAR(' '); SERIAL_CHAR('0' + i); }
+        print_es_state(digitalRead(pin) != FIL_RUNOUT_INVERTING);
+      }
+    #endif
+  #endif
+} // Endstops::M119
+
+// The following routines are called from an ISR context. It could be the temperature ISR, the
+// endstop ISR or the Stepper ISR.
+
+#define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX
+#define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_## MINMAX ##_PIN
+#define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_## MINMAX ##_ENDSTOP_INVERTING
+
+// Check endstops - Could be called from Temperature ISR!
+void Endstops::update() {
+
+  #if DISABLED(ENDSTOP_NOISE_FILTER)
+    if (!abort_enabled()) return;
+  #endif
+
+  #define UPDATE_ENDSTOP_BIT(AXIS, MINMAX) SET_BIT_TO(live_state, _ENDSTOP(AXIS, MINMAX), (READ(_ENDSTOP_PIN(AXIS, MINMAX)) != _ENDSTOP_INVERTING(AXIS, MINMAX)))
+  #define COPY_LIVE_STATE(SRC_BIT, DST_BIT) SET_BIT_TO(live_state, DST_BIT, TEST(live_state, SRC_BIT))
+
+  #if ENABLED(G38_PROBE_TARGET) && PIN_EXISTS(Z_MIN_PROBE) && !(CORE_IS_XY || CORE_IS_XZ)
+    // If G38 command is active check Z_MIN_PROBE for ALL movement
+    if (G38_move) UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
+  #endif
+
+  // With Dual X, endstops are only checked in the homing direction for the active extruder
+  #if ENABLED(DUAL_X_CARRIAGE)
+    #define E0_ACTIVE stepper.movement_extruder() == 0
+    #define X_MIN_TEST ((X_HOME_DIR < 0 && E0_ACTIVE) || (X2_HOME_DIR < 0 && !E0_ACTIVE))
+    #define X_MAX_TEST ((X_HOME_DIR > 0 && E0_ACTIVE) || (X2_HOME_DIR > 0 && !E0_ACTIVE))
+  #else
+    #define X_MIN_TEST true
+    #define X_MAX_TEST true
+  #endif
+
+  // Use HEAD for core axes, AXIS for others
+  #if CORE_IS_XY || CORE_IS_XZ
+    #define X_AXIS_HEAD X_HEAD
+  #else
+    #define X_AXIS_HEAD X_AXIS
+  #endif
+  #if CORE_IS_XY || CORE_IS_YZ
+    #define Y_AXIS_HEAD Y_HEAD
+  #else
+    #define Y_AXIS_HEAD Y_AXIS
+  #endif
+  #if CORE_IS_XZ || CORE_IS_YZ
+    #define Z_AXIS_HEAD Z_HEAD
+  #else
+    #define Z_AXIS_HEAD Z_AXIS
+  #endif
+
+  /**
+   * Check and update endstops
+   */
+  #if HAS_X_MIN
+    #if ENABLED(X_DUAL_ENDSTOPS)
+      UPDATE_ENDSTOP_BIT(X, MIN);
+      #if HAS_X2_MIN
+        UPDATE_ENDSTOP_BIT(X2, MIN);
+      #else
+        COPY_LIVE_STATE(X_MIN, X2_MIN);
+      #endif
+    #else
+      UPDATE_ENDSTOP_BIT(X, MIN);
+    #endif
+  #endif
+
+  #if HAS_X_MAX
+    #if ENABLED(X_DUAL_ENDSTOPS)
+      UPDATE_ENDSTOP_BIT(X, MAX);
+      #if HAS_X2_MAX
+        UPDATE_ENDSTOP_BIT(X2, MAX);
+      #else
+        COPY_LIVE_STATE(X_MAX, X2_MAX);
+      #endif
+    #else
+      UPDATE_ENDSTOP_BIT(X, MAX);
+    #endif
+  #endif
+
+  #if HAS_Y_MIN
+    #if ENABLED(Y_DUAL_ENDSTOPS)
+      UPDATE_ENDSTOP_BIT(Y, MIN);
+      #if HAS_Y2_MIN
+        UPDATE_ENDSTOP_BIT(Y2, MIN);
+      #else
+        COPY_LIVE_STATE(Y_MIN, Y2_MIN);
+      #endif
+    #else
+      UPDATE_ENDSTOP_BIT(Y, MIN);
+    #endif
+  #endif
+
+  #if HAS_Y_MAX
+    #if ENABLED(Y_DUAL_ENDSTOPS)
+      UPDATE_ENDSTOP_BIT(Y, MAX);
+      #if HAS_Y2_MAX
+        UPDATE_ENDSTOP_BIT(Y2, MAX);
+      #else
+        COPY_LIVE_STATE(Y_MAX, Y2_MAX);
+      #endif
+    #else
+      UPDATE_ENDSTOP_BIT(Y, MAX);
+    #endif
+  #endif
+
+  #if HAS_Z_MIN
+    #if ENABLED(Z_DUAL_ENDSTOPS)
+      UPDATE_ENDSTOP_BIT(Z, MIN);
+      #if HAS_Z2_MIN
+        UPDATE_ENDSTOP_BIT(Z2, MIN);
+      #else
+        COPY_LIVE_STATE(Z_MIN, Z2_MIN);
+      #endif
+    #elif ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
+      UPDATE_ENDSTOP_BIT(Z, MIN);
+    #elif Z_HOME_DIR < 0
+      UPDATE_ENDSTOP_BIT(Z, MIN);
+    #endif
+  #endif
+
+  // When closing the gap check the enabled probe
+  #if ENABLED(Z_MIN_PROBE_ENDSTOP)
+    UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
+  #endif
+
+  #if HAS_Z_MAX
+    // Check both Z dual endstops
+    #if ENABLED(Z_DUAL_ENDSTOPS)
+      UPDATE_ENDSTOP_BIT(Z, MAX);
+      #if HAS_Z2_MAX
+        UPDATE_ENDSTOP_BIT(Z2, MAX);
+      #else
+        COPY_LIVE_STATE(Z_MAX, Z2_MAX);
+      #endif
+    #elif DISABLED(Z_MIN_PROBE_ENDSTOP) || Z_MAX_PIN != Z_MIN_PROBE_PIN
+      // If this pin isn't the bed probe it's the Z endstop
+      UPDATE_ENDSTOP_BIT(Z, MAX);
+    #endif
+  #endif
+
+  #if ENABLED(ENDSTOP_NOISE_FILTER)
+    /**
+     * Filtering out noise on endstops requires a delayed decision. Let's assume, due to noise,
+     * that 50% of endstop signal samples are good and 50% are bad (assuming normal distribution
+     * of random noise). Then the first sample has a 50% chance to be good or bad. The 2nd sample
+     * also has a 50% chance to be good or bad. The chances of 2 samples both being bad becomes
+     * 50% of 50%, or 25%. That was the previous implementation of Marlin endstop handling. It
+     * reduces chances of bad readings in half, at the cost of 1 extra sample period, but chances
+     * still exist. The only way to reduce them further is to increase the number of samples.
+     * To reduce the chance to 1% (1/128th) requires 7 samples (adding 7ms of delay).
+     */
+    static esbits_t old_live_state;
+    if (old_live_state != live_state) {
+      endstop_poll_count = 7;
+      old_live_state = live_state;
+    }
+    else if (endstop_poll_count && !--endstop_poll_count)
+      validated_live_state = live_state;
+
+    if (!abort_enabled()) return;
+
+  #endif
+
+  // Test the current status of an endstop
+  #define TEST_ENDSTOP(ENDSTOP) (TEST(state(), ENDSTOP))
+
+  // Record endstop was hit
+  #define _ENDSTOP_HIT(AXIS, MINMAX) SBI(hit_state, _ENDSTOP(AXIS, MINMAX))
+
+  // Call the endstop triggered routine for single endstops
+  #define PROCESS_ENDSTOP(AXIS,MINMAX) do { \
+    if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX))) { \
+      _ENDSTOP_HIT(AXIS, MINMAX); \
+      planner.endstop_triggered(_AXIS(AXIS)); \
+    } \
+  }while(0)
+
+  // Call the endstop triggered routine for dual endstops
+  #define PROCESS_DUAL_ENDSTOP(AXIS1, AXIS2, MINMAX) do { \
+    const byte dual_hit = TEST_ENDSTOP(_ENDSTOP(AXIS1, MINMAX)) | (TEST_ENDSTOP(_ENDSTOP(AXIS2, MINMAX)) << 1); \
+    if (dual_hit) { \
+      _ENDSTOP_HIT(AXIS1, MINMAX); \
+      /* if not performing home or if both endstops were trigged during homing... */ \
+      if (!stepper.homing_dual_axis || dual_hit == 0b11) \
+        planner.endstop_triggered(_AXIS(AXIS1)); \
+    } \
+  }while(0)
+
+  #if ENABLED(G38_PROBE_TARGET) && PIN_EXISTS(Z_MIN_PROBE) && !(CORE_IS_XY || CORE_IS_XZ)
+    // If G38 command is active check Z_MIN_PROBE for ALL movement
+    if (G38_move) {
+      if (TEST_ENDSTOP(_ENDSTOP(Z, MIN_PROBE))) {
+        if      (stepper.axis_is_moving(X_AXIS)) { _ENDSTOP_HIT(X, MIN); planner.endstop_triggered(X_AXIS); }
+        else if (stepper.axis_is_moving(Y_AXIS)) { _ENDSTOP_HIT(Y, MIN); planner.endstop_triggered(Y_AXIS); }
+        else if (stepper.axis_is_moving(Z_AXIS)) { _ENDSTOP_HIT(Z, MIN); planner.endstop_triggered(Z_AXIS); }
+        G38_endstop_hit = true;
+      }
+    }
+  #endif
+
+  // Now, we must signal, after validation, if an endstop limit is pressed or not
+  if (stepper.axis_is_moving(X_AXIS)) {
+    if (stepper.motor_direction(X_AXIS_HEAD)) { // -direction
+      #if HAS_X_MIN
+        #if ENABLED(X_DUAL_ENDSTOPS)
+          PROCESS_DUAL_ENDSTOP(X, X2, MIN);
+        #else
+          if (X_MIN_TEST) PROCESS_ENDSTOP(X, MIN);
+        #endif
+      #endif
+    }
+    else { // +direction
+      #if HAS_X_MAX
+        #if ENABLED(X_DUAL_ENDSTOPS)
+          PROCESS_DUAL_ENDSTOP(X, X2, MAX);
+        #else
+          if (X_MAX_TEST) PROCESS_ENDSTOP(X, MAX);
+        #endif
+      #endif
+    }
+  }
+
+  if (stepper.axis_is_moving(Y_AXIS)) {
+    if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
+      #if HAS_Y_MIN
+        #if ENABLED(Y_DUAL_ENDSTOPS)
+          PROCESS_DUAL_ENDSTOP(Y, Y2, MIN);
+        #else
+          PROCESS_ENDSTOP(Y, MIN);
+        #endif
+      #endif
+    }
+    else { // +direction
+      #if HAS_Y_MAX
+        #if ENABLED(Y_DUAL_ENDSTOPS)
+          PROCESS_DUAL_ENDSTOP(Y, Y2, MAX);
+        #else
+          PROCESS_ENDSTOP(Y, MAX);
+        #endif
+      #endif
+    }
+  }
+
+  if (stepper.axis_is_moving(Z_AXIS)) {
+    if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
+      #if HAS_Z_MIN
+        #if ENABLED(Z_DUAL_ENDSTOPS)
+          PROCESS_DUAL_ENDSTOP(Z, Z2, MIN);
+        #else
+          #if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
+            if (z_probe_enabled) PROCESS_ENDSTOP(Z, MIN);
+          #elif ENABLED(Z_MIN_PROBE_ENDSTOP)
+            if (!z_probe_enabled) PROCESS_ENDSTOP(Z, MIN);
+          #else
+            PROCESS_ENDSTOP(Z, MIN);
+          #endif
+        #endif
+      #endif
+
+      // When closing the gap check the enabled probe
+      #if ENABLED(Z_MIN_PROBE_ENDSTOP)
+        if (z_probe_enabled) PROCESS_ENDSTOP(Z, MIN_PROBE);
+      #endif
+    }
+    else { // Z +direction. Gantry up, bed down.
+      #if HAS_Z_MAX
+        #if ENABLED(Z_DUAL_ENDSTOPS)
+          PROCESS_DUAL_ENDSTOP(Z, Z2, MAX);
+        #elif DISABLED(Z_MIN_PROBE_ENDSTOP) || Z_MAX_PIN != Z_MIN_PROBE_PIN
+          // If this pin is not hijacked for the bed probe
+          // then it belongs to the Z endstop
+          PROCESS_ENDSTOP(Z, MAX);
+        #endif
+      #endif
+    }
+  }
+} // Endstops::update()
+
+#if ENABLED(PINS_DEBUGGING)
+
+  bool Endstops::monitor_flag = false;
+
+  /**
+   * monitors endstops & Z probe for changes
+   *
+   * If a change is detected then the LED is toggled and
+   * a message is sent out the serial port
+   *
+   * Yes, we could miss a rapid back & forth change but
+   * that won't matter because this is all manual.
+   *
+   */
+  void Endstops::monitor() {
+
+    static uint16_t old_live_state_local = 0;
+    static uint8_t local_LED_status = 0;
+    uint16_t live_state_local = 0;
+
+    #if HAS_X_MIN
+      if (READ(X_MIN_PIN)) SBI(live_state_local, X_MIN);
+    #endif
+    #if HAS_X_MAX
+      if (READ(X_MAX_PIN)) SBI(live_state_local, X_MAX);
+    #endif
+    #if HAS_Y_MIN
+      if (READ(Y_MIN_PIN)) SBI(live_state_local, Y_MIN);
+    #endif
+    #if HAS_Y_MAX
+      if (READ(Y_MAX_PIN)) SBI(live_state_local, Y_MAX);
+    #endif
+    #if HAS_Z_MIN
+      if (READ(Z_MIN_PIN)) SBI(live_state_local, Z_MIN);
+    #endif
+    #if HAS_Z_MAX
+      if (READ(Z_MAX_PIN)) SBI(live_state_local, Z_MAX);
+    #endif
+    #if HAS_Z_MIN_PROBE_PIN
+      if (READ(Z_MIN_PROBE_PIN)) SBI(live_state_local, Z_MIN_PROBE);
+    #endif
+    #if HAS_X2_MIN
+      if (READ(X2_MIN_PIN)) SBI(live_state_local, X2_MIN);
+    #endif
+    #if HAS_X2_MAX
+      if (READ(X2_MAX_PIN)) SBI(live_state_local, X2_MAX);
+    #endif
+    #if HAS_Y2_MIN
+      if (READ(Y2_MIN_PIN)) SBI(live_state_local, Y2_MIN);
+    #endif
+    #if HAS_Y2_MAX
+      if (READ(Y2_MAX_PIN)) SBI(live_state_local, Y2_MAX);
+    #endif
+    #if HAS_Z2_MIN
+      if (READ(Z2_MIN_PIN)) SBI(live_state_local, Z2_MIN);
+    #endif
+    #if HAS_Z2_MAX
+      if (READ(Z2_MAX_PIN)) SBI(live_state_local, Z2_MAX);
+    #endif
+
+    uint16_t endstop_change = live_state_local ^ old_live_state_local;
+
+    if (endstop_change) {
+      #if HAS_X_MIN
+        if (TEST(endstop_change, X_MIN)) SERIAL_PROTOCOLPAIR("  X_MIN:", TEST(live_state_local, X_MIN));
+      #endif
+      #if HAS_X_MAX
+        if (TEST(endstop_change, X_MAX)) SERIAL_PROTOCOLPAIR("  X_MAX:", TEST(live_state_local, X_MAX));
+      #endif
+      #if HAS_Y_MIN
+        if (TEST(endstop_change, Y_MIN)) SERIAL_PROTOCOLPAIR("  Y_MIN:", TEST(live_state_local, Y_MIN));
+      #endif
+      #if HAS_Y_MAX
+        if (TEST(endstop_change, Y_MAX)) SERIAL_PROTOCOLPAIR("  Y_MAX:", TEST(live_state_local, Y_MAX));
+      #endif
+      #if HAS_Z_MIN
+        if (TEST(endstop_change, Z_MIN)) SERIAL_PROTOCOLPAIR("  Z_MIN:", TEST(live_state_local, Z_MIN));
+      #endif
+      #if HAS_Z_MAX
+        if (TEST(endstop_change, Z_MAX)) SERIAL_PROTOCOLPAIR("  Z_MAX:", TEST(live_state_local, Z_MAX));
+      #endif
+      #if HAS_Z_MIN_PROBE_PIN
+        if (TEST(endstop_change, Z_MIN_PROBE)) SERIAL_PROTOCOLPAIR("  PROBE:", TEST(live_state_local, Z_MIN_PROBE));
+      #endif
+      #if HAS_X2_MIN
+        if (TEST(endstop_change, X2_MIN)) SERIAL_PROTOCOLPAIR("  X2_MIN:", TEST(live_state_local, X2_MIN));
+      #endif
+      #if HAS_X2_MAX
+        if (TEST(endstop_change, X2_MAX)) SERIAL_PROTOCOLPAIR("  X2_MAX:", TEST(live_state_local, X2_MAX));
+      #endif
+      #if HAS_Y2_MIN
+        if (TEST(endstop_change, Y2_MIN)) SERIAL_PROTOCOLPAIR("  Y2_MIN:", TEST(live_state_local, Y2_MIN));
+      #endif
+      #if HAS_Y2_MAX
+        if (TEST(endstop_change, Y2_MAX)) SERIAL_PROTOCOLPAIR("  Y2_MAX:", TEST(live_state_local, Y2_MAX));
+      #endif
+      #if HAS_Z2_MIN
+        if (TEST(endstop_change, Z2_MIN)) SERIAL_PROTOCOLPAIR("  Z2_MIN:", TEST(live_state_local, Z2_MIN));
+      #endif
+      #if HAS_Z2_MAX
+        if (TEST(endstop_change, Z2_MAX)) SERIAL_PROTOCOLPAIR("  Z2_MAX:", TEST(live_state_local, Z2_MAX));
+      #endif
+      SERIAL_PROTOCOLPGM("\n\n");
+      analogWrite(LED_PIN, local_LED_status);
+      local_LED_status ^= 255;
+      old_live_state_local = live_state_local;
+    }
+  }
+
+#endif // PINS_DEBUGGING

+ 174 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/endstops.h

@@ -0,0 +1,174 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * endstops.h - manages endstops
+ */
+
+#ifndef __ENDSTOPS_H__
+#define __ENDSTOPS_H__
+
+#include "MarlinConfig.h"
+
+#define VALIDATE_HOMING_ENDSTOPS
+
+enum EndstopEnum : char {
+  X_MIN,
+  Y_MIN,
+  Z_MIN,
+  Z_MIN_PROBE,
+  X_MAX,
+  Y_MAX,
+  Z_MAX,
+  X2_MIN,
+  X2_MAX,
+  Y2_MIN,
+  Y2_MAX,
+  Z2_MIN,
+  Z2_MAX
+};
+
+class Endstops {
+
+  public:
+
+    static bool enabled, enabled_globally;
+
+    #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
+      typedef uint16_t esbits_t;
+      #if ENABLED(X_DUAL_ENDSTOPS)
+        static float x_endstop_adj;
+      #endif
+      #if ENABLED(Y_DUAL_ENDSTOPS)
+        static float y_endstop_adj;
+      #endif
+      #if ENABLED(Z_DUAL_ENDSTOPS)
+        static float z_endstop_adj;
+      #endif
+    #else
+      typedef uint8_t esbits_t;
+    #endif
+
+  private:
+    static esbits_t live_state;
+    static volatile uint8_t hit_state;      // Use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT index
+
+    #if ENABLED(ENDSTOP_NOISE_FILTER)
+      static esbits_t validated_live_state;
+      static uint8_t endstop_poll_count;    // Countdown from threshold for polling
+    #endif
+
+  public:
+    Endstops() {};
+
+    /**
+     * Initialize the endstop pins
+     */
+    static void init();
+
+    /**
+     * Are endstops or the probe set to abort the move?
+     */
+    FORCE_INLINE static bool abort_enabled() {
+      return (enabled
+        #if HAS_BED_PROBE
+          || z_probe_enabled
+        #endif
+      );
+    }
+
+    /**
+     * Periodic call to poll endstops if required. Called from temperature ISR
+     */
+    static void poll();
+
+    /**
+     * Update endstops bits from the pins. Apply filtering to get a verified state.
+     * If abort_enabled() and moving towards a triggered switch, abort the current move.
+     * Called from ISR contexts.
+     */
+    static void update();
+
+    /**
+     * Get Endstop hit state.
+     */
+    FORCE_INLINE static uint8_t trigger_state() { return hit_state; }
+
+    /**
+     * Get current endstops state
+     */
+    FORCE_INLINE static esbits_t state() {
+      return
+        #if ENABLED(ENDSTOP_NOISE_FILTER)
+          validated_live_state
+        #else
+          live_state
+        #endif
+      ;
+    }
+
+    /**
+     * Report endstop hits to serial. Called from loop().
+     */
+    static void event_handler();
+
+    /**
+     * Report endstop positions in response to M119
+     */
+    static void M119();
+
+    // Enable / disable endstop checking globally
+    static void enable_globally(const bool onoff=true);
+
+    // Enable / disable endstop checking
+    static void enable(const bool onoff=true);
+
+    // Disable / Enable endstops based on ENSTOPS_ONLY_FOR_HOMING and global enable
+    static void not_homing();
+
+    #if ENABLED(VALIDATE_HOMING_ENDSTOPS)
+      // If the last move failed to trigger an endstop, call kill
+      static void validate_homing_move();
+    #else
+      FORCE_INLINE static void validate_homing_move() { hit_on_purpose(); }
+    #endif
+
+    // Clear endstops (i.e., they were hit intentionally) to suppress the report
+    FORCE_INLINE static void hit_on_purpose() { hit_state = 0; }
+
+    // Enable / disable endstop z-probe checking
+    #if HAS_BED_PROBE
+      static volatile bool z_probe_enabled;
+      static void enable_z_probe(const bool onoff=true);
+    #endif
+
+    // Debugging of endstops
+    #if ENABLED(PINS_DEBUGGING)
+      static bool monitor_flag;
+      static void monitor();
+      static void run_monitor();
+    #endif
+};
+
+extern Endstops endstops;
+
+#endif // __ENDSTOPS_H__

+ 175 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/enum.h

@@ -0,0 +1,175 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __ENUM_H__
+#define __ENUM_H__
+
+#include "MarlinConfig.h"
+
+/**
+ * Axis indices as enumerated constants
+ *
+ *  - X_AXIS, Y_AXIS, and Z_AXIS should be used for axes in Cartesian space
+ *  - A_AXIS, B_AXIS, and C_AXIS should be used for Steppers, corresponding to XYZ on Cartesians
+ *  - X_HEAD, Y_HEAD, and Z_HEAD should be used for Steppers on Core kinematics
+ */
+enum AxisEnum : unsigned char {
+  X_AXIS    = 0,
+  A_AXIS    = 0,
+  Y_AXIS    = 1,
+  B_AXIS    = 1,
+  Z_AXIS    = 2,
+  C_AXIS    = 2,
+  E_CART    = 3,
+  #if ENABLED(HANGPRINTER) // Hangprinter order: A_AXIS, B_AXIS, C_AXIS, D_AXIS, E_AXIS
+    D_AXIS  = 3,
+    E_AXIS  = 4,
+  #else
+    E_AXIS  = 3,
+  #endif
+  X_HEAD, Y_HEAD, Z_HEAD,
+  ALL_AXES  = 0xFE,
+  NO_AXIS   = 0xFF
+};
+
+#define LOOP_S_LE_N(VAR, S, N) for (uint8_t VAR=S; VAR<=N; VAR++)
+#define LOOP_S_L_N(VAR, S, N) for (uint8_t VAR=S; VAR<N; VAR++)
+#define LOOP_LE_N(VAR, N) LOOP_S_LE_N(VAR, 0, N)
+#define LOOP_L_N(VAR, N) LOOP_S_L_N(VAR, 0, N)
+
+#define LOOP_NA(VAR) LOOP_L_N(VAR, NUM_AXIS)
+#define LOOP_XYZ(VAR) LOOP_S_LE_N(VAR, X_AXIS, Z_AXIS)
+#define LOOP_XYZE(VAR) LOOP_S_LE_N(VAR, X_AXIS, E_CART)
+#define LOOP_XYZE_N(VAR) LOOP_S_L_N(VAR, X_AXIS, XYZE_N)
+#define LOOP_MOV_AXIS(VAR) LOOP_S_L_N(VAR, A_AXIS, MOV_AXIS)
+#define LOOP_NUM_AXIS(VAR) LOOP_S_L_N(VAR, A_AXIS, NUM_AXIS)
+#define LOOP_NUM_AXIS_N(VAR) LOOP_S_L_N(VAR, A_AXIS, NUM_AXIS_N)
+
+typedef enum {
+  LINEARUNIT_MM,
+  LINEARUNIT_INCH
+} LinearUnit;
+
+typedef enum {
+  TEMPUNIT_C,
+  TEMPUNIT_K,
+  TEMPUNIT_F
+} TempUnit;
+
+/**
+ * Debug flags
+ * Not yet widely applied
+ */
+enum DebugFlags : unsigned char {
+  DEBUG_NONE          = 0,
+  DEBUG_ECHO          = _BV(0), ///< Echo commands in order as they are processed
+  DEBUG_INFO          = _BV(1), ///< Print messages for code that has debug output
+  DEBUG_ERRORS        = _BV(2), ///< Not implemented
+  DEBUG_DRYRUN        = _BV(3), ///< Ignore temperature setting and E movement commands
+  DEBUG_COMMUNICATION = _BV(4), ///< Not implemented
+  DEBUG_LEVELING      = _BV(5), ///< Print detailed output for homing and leveling
+  DEBUG_MESH_ADJUST   = _BV(6), ///< UBL bed leveling
+  DEBUG_ALL           = 0xFF
+};
+
+#if ENABLED(ADVANCED_PAUSE_FEATURE)
+  enum AdvancedPauseMenuResponse : char {
+    ADVANCED_PAUSE_RESPONSE_WAIT_FOR,
+    ADVANCED_PAUSE_RESPONSE_EXTRUDE_MORE,
+    ADVANCED_PAUSE_RESPONSE_RESUME_PRINT
+  };
+
+  #if ENABLED(ULTIPANEL)
+    enum AdvancedPauseMessage : char {
+      ADVANCED_PAUSE_MESSAGE_INIT,
+      ADVANCED_PAUSE_MESSAGE_UNLOAD,
+      ADVANCED_PAUSE_MESSAGE_INSERT,
+      ADVANCED_PAUSE_MESSAGE_LOAD,
+      ADVANCED_PAUSE_MESSAGE_PURGE,
+      #if ENABLED(ADVANCED_PAUSE_CONTINUOUS_PURGE)
+        ADVANCED_PAUSE_MESSAGE_CONTINUOUS_PURGE,
+      #endif
+      ADVANCED_PAUSE_MESSAGE_OPTION,
+      ADVANCED_PAUSE_MESSAGE_RESUME,
+      ADVANCED_PAUSE_MESSAGE_STATUS,
+      ADVANCED_PAUSE_MESSAGE_CLICK_TO_HEAT_NOZZLE,
+      ADVANCED_PAUSE_MESSAGE_WAIT_FOR_NOZZLES_TO_HEAT
+    };
+  #endif
+
+  enum AdvancedPauseMode : char {
+    ADVANCED_PAUSE_MODE_PAUSE_PRINT,
+    ADVANCED_PAUSE_MODE_LOAD_FILAMENT,
+    ADVANCED_PAUSE_MODE_UNLOAD_FILAMENT
+  };
+#endif
+
+/**
+ * States for managing Marlin and host communication
+ * Marlin sends messages if blocked or busy
+ */
+#if ENABLED(HOST_KEEPALIVE_FEATURE)
+  enum MarlinBusyState : char {
+    NOT_BUSY,           // Not in a handler
+    IN_HANDLER,         // Processing a GCode
+    IN_PROCESS,         // Known to be blocking command input (as in G29)
+    PAUSED_FOR_USER,    // Blocking pending any input
+    PAUSED_FOR_INPUT    // Blocking pending text input (concept)
+  };
+#endif
+
+/**
+ * SD Card
+ */
+enum LsAction : char { LS_SerialPrint, LS_Count, LS_GetFilename };
+
+/**
+ * Ultra LCD
+ */
+enum LCDViewAction : char {
+  LCDVIEW_NONE,
+  LCDVIEW_REDRAW_NOW,
+  LCDVIEW_CALL_REDRAW_NEXT,
+  LCDVIEW_CLEAR_CALL_REDRAW,
+  LCDVIEW_CALL_NO_REDRAW
+};
+
+/**
+ * Dual X Carriage modes. A Dual Nozzle can also do duplication.
+ */
+#if ENABLED(DUAL_X_CARRIAGE) || ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
+  enum DualXMode : char {
+    DXC_FULL_CONTROL_MODE,  // DUAL_X_CARRIAGE only
+    DXC_AUTO_PARK_MODE,     // DUAL_X_CARRIAGE only
+    DXC_DUPLICATION_MODE
+  };
+#endif
+
+/**
+ * Workspace planes only apply to G2/G3 moves
+ * (and "canned cycles" - not a current feature)
+ */
+#if ENABLED(CNC_WORKSPACE_PLANES)
+  enum WorkspacePlane : char { PLANE_XY, PLANE_ZX, PLANE_YZ };
+#endif
+
+#endif // __ENUM_H__

File diff suppressed because it is too large
+ 1940 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/AlephObjects/TAZ4/Configuration.h


File diff suppressed because it is too large
+ 1654 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/AlephObjects/TAZ4/Configuration_adv.h


File diff suppressed because it is too large
+ 1920 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/AliExpress/CL-260/Configuration.h


+ 15 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/AliExpress/CL-260/README.txt

@@ -0,0 +1,15 @@
+This is an example configuration for the CL-260 Ultimaker 2 clone.
+Change Z_MAX_POS to 300 for the CL-260MAX.
+
+(The printer is available on AliExpress; be aware that this is not a beginner's
+printer -- it needs tweaking and some parts replaced before being decent.)
+
+The printer comes with a quite old Marlin, the sources are available here:
+http://www.thingiverse.com/thing:1635830/ and I recommend replacing them.
+
+The setting "works" for my printer and the extruder using my calibration value.
+You might want to tweak some settings, e.g enable EEPROM, increase default Z speed, adjust homing speeds,...
+
+Have fun!
+--
+tobi

File diff suppressed because it is too large
+ 1997 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Anet/A2plus/Configuration.h


File diff suppressed because it is too large
+ 1654 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Anet/A2plus/Configuration_adv.h


File diff suppressed because it is too large
+ 2075 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Anet/A6/Configuration.h


File diff suppressed because it is too large
+ 1654 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Anet/A6/Configuration_adv.h


File diff suppressed because it is too large
+ 1929 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Anet/A8/Configuration.h


File diff suppressed because it is too large
+ 1654 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Anet/A8/Configuration_adv.h


File diff suppressed because it is too large
+ 1920 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BIBO/TouchX/Cyclops/Configuration.h


File diff suppressed because it is too large
+ 1654 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BIBO/TouchX/Cyclops/Configuration_adv.h


File diff suppressed because it is too large
+ 1920 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BIBO/TouchX/default/Configuration.h


File diff suppressed because it is too large
+ 1654 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BIBO/TouchX/default/Configuration_adv.h


File diff suppressed because it is too large
+ 1908 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/Hephestos/Configuration.h


File diff suppressed because it is too large
+ 1654 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/Hephestos/Configuration_adv.h


File diff suppressed because it is too large
+ 1918 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/Hephestos_2/Configuration.h


File diff suppressed because it is too large
+ 1662 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/Hephestos_2/Configuration_adv.h


+ 29 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/Hephestos_2/README.md

@@ -0,0 +1,29 @@
+# Example Configuration for BQ [Hephestos 2](http://www.bq.com/uk/hephestos-2)
+Based on the original configuration file shipped with the heavily modified Marlin fork by BQ.
+The forked firmware and configuration files can be found at the [BQ Github repository](https://github.com/bq/Marlin).
+
+NOTE: The look and feel of the LCD menu will change dramatically when using the original Marlin firmware.
+
+## Changelog
+ * 2018/05/30 - Configuration updated to the latest Marlin version (43a55a9af).
+                ABL Bilinear 5x5 is active by default.
+
+ * 2017/07/06 - Configuration updated to the latest Marlin version and added support for the
+                official BQ heated bed upgrade kit.
+
+ * 2016/12/13 - Configuration updated to the latest Marlin version.
+
+ * 2016/07/13 - Configuration updated to the latest Marlin version.
+
+ * 2016/06/21 - Disabled heated bed related options, activated software endstops and SD printing now
+               disables the heater when finishes printing.
+
+ * 2016/03/21 - Activated 4-point auto leveling by default and updated miscellaneous z-probe values.
+
+ * 2016/03/01 - The first release of Marlin's configuration file for the
+                BQ Hephestos 2 3D printer.
+
+
+## Support
+This configuration should work easily with the stock Hephestos 2, nevertheless if you encounter any
+issues you may contact me on [Github](https://github.com/jbrazio), [Twitter](https://twitter.com/jbrazio) or by mail.

+ 100 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/Hephestos_2/_Bootscreen.h

@@ -0,0 +1,100 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Custom Boot Screen bitmap
+ *
+ * Place this file in the root with your configuration files
+ * and enable SHOW_CUSTOM_BOOTSCREEN in Configuration.h.
+ *
+ * Use the Marlin Bitmap Converter to make your own:
+ * http://marlinfw.org/tools/u8glib/converter.html
+ */
+
+#define CUSTOM_BOOTSCREEN_BMPWIDTH  64
+
+const unsigned char custom_start_bmp[] PROGMEM = {
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000011,B11110000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000111,B11111000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000111,B11111000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00001111,B11111100,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00001111,B11111100,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000111,B11111000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B11111000,B00000111,B11111000,B00000111,B11000000,B00000000,
+  B00000000,B00000001,B11111100,B00000011,B11110000,B00001111,B11100000,B00000000,
+  B00000000,B00000011,B11111110,B00000000,B11000000,B00011111,B11110000,B00000000,
+  B00000000,B00000011,B11111110,B00000000,B00000000,B00011111,B11110000,B00000000,
+  B00000000,B00000011,B11111110,B00000000,B00000000,B00011111,B11110000,B00000000,
+  B00000000,B00000011,B11111110,B00000000,B00000000,B00011111,B11110000,B00000000,
+  B00000000,B00000011,B11111100,B00000000,B00000000,B00001111,B11100000,B00000000,
+  B00000000,B00000001,B11111000,B00000000,B00000000,B00001111,B11100000,B00000000,
+  B00000000,B00000000,B01110000,B00000000,B00000000,B00000011,B10000000,B00000000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01100000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111100,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111100,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111100,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111100,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111100,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111100,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01000000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
+  B00001111,B10000000,B00000000,B00000000,B01110000,B00000000,B00000000,B00000000,
+  B00011111,B11000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000000,
+  B00111111,B11000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000000,
+  B00111111,B11100000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000000,
+  B00111111,B11100000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000000,
+  B00111111,B11100000,B00000000,B00000000,B01111011,B11000000,B00001111,B00000000,
+  B00111111,B11000000,B00000000,B00000000,B01111111,B11110000,B00111111,B11000000,
+  B00011111,B10000000,B00000000,B00000000,B01111111,B11111000,B01111111,B11100000,
+  B00001111,B00000000,B00000000,B00000000,B01111110,B11111100,B11111001,B11110000,
+  B00000000,B00000000,B00000000,B00000000,B01111000,B00111100,B11100000,B11110000,
+  B00000000,B00000000,B00000000,B00000000,B01111000,B00011101,B11100000,B01110000,
+  B00000000,B00000000,B00000000,B00000000,B01111000,B00011101,B11100000,B01110000,
+  B00000000,B00000000,B00000000,B00000000,B01111000,B00011101,B11100000,B01110000,
+  B00000000,B00000000,B00000000,B00000000,B01111000,B00011101,B11100000,B01110000,
+  B00000000,B00000000,B00000000,B00000000,B01111000,B00011101,B11100000,B01110000,
+  B00000000,B00000000,B00000000,B00000000,B01111000,B00111100,B11100000,B11110000,
+  B00000000,B00000000,B00000000,B00000000,B01111100,B01111100,B11111001,B11110000,
+  B00000000,B00000000,B00000000,B00000000,B00011111,B11111000,B11111111,B11110000,
+  B00000000,B00000000,B00000000,B00000000,B00001111,B11110000,B01111111,B11110000,
+  B00000000,B00000000,B00000000,B00000000,B00000111,B11100000,B00011111,B01110000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01110000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01110000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01110000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01110000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01110000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
+  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000
+};

File diff suppressed because it is too large
+ 1908 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/WITBOX/Configuration.h


File diff suppressed because it is too large
+ 1654 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/BQ/WITBOX/Configuration_adv.h


File diff suppressed because it is too large
+ 1919 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Cartesio/Configuration.h


File diff suppressed because it is too large
+ 1654 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Cartesio/Configuration_adv.h


+ 0 - 0
firmwares/marlin/Touch Mi - Marlin-1.1.9-Ender3.fr/example_configurations/Cartesio/_Bootscreen.h


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