Browse Source

Merge branch '2.1.x' into vanilla_fb_2.1.x

Signed-off-by: Sergey Terentiev <sergey@terentiev.me>
FB4S_WIFI
Sergey Terentiev 2 years ago
parent
commit
f1b6e6e5b8
No known key found for this signature in database GPG Key ID: AFAA57ACD15D1EB0
  1. 6
      .editorconfig
  2. 31
      Marlin/Configuration.h
  3. 7
      Marlin/Configuration_adv.h
  4. 224
      Marlin/src/HAL/LPC1768/upload_extra_script.py
  5. 2
      Marlin/src/HAL/NATIVE_SIM/fastio.h
  6. 2
      Marlin/src/HAL/NATIVE_SIM/tft/xpt2046.h
  7. 5
      Marlin/src/HAL/STM32/inc/Conditionals_post.h
  8. 5
      Marlin/src/HAL/STM32/inc/SanityCheck.h
  9. 2
      Marlin/src/HAL/STM32/tft/tft_fsmc.cpp
  10. 2
      Marlin/src/HAL/STM32/tft/tft_spi.cpp
  11. 2
      Marlin/src/MarlinCore.cpp
  12. 2
      Marlin/src/core/macros.h
  13. 4
      Marlin/src/core/types.h
  14. 33
      Marlin/src/feature/bedlevel/bdl/bdl.cpp
  15. 10
      Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp
  16. 2
      Marlin/src/feature/spindle_laser.h
  17. 14
      Marlin/src/gcode/lcd/M255.cpp
  18. 26
      Marlin/src/gcode/parser.h
  19. 21
      Marlin/src/gcode/sd/M20.cpp
  20. 3
      Marlin/src/inc/Conditionals_LCD.h
  21. 6
      Marlin/src/inc/Conditionals_adv.h
  22. 10
      Marlin/src/inc/Conditionals_post.h
  23. 30
      Marlin/src/inc/SanityCheck.h
  24. 2
      Marlin/src/inc/Version.h
  25. 5
      Marlin/src/inc/Warnings.cpp
  26. 3
      Marlin/src/lcd/dogm/marlinui_DOGM.cpp
  27. 10
      Marlin/src/lcd/e3v2/common/dwin_api.cpp
  28. 150
      Marlin/src/lcd/e3v2/jyersui/dwin.cpp
  29. 1
      Marlin/src/lcd/extui/dgus/DGUSDisplay.h
  30. 47
      Marlin/src/lcd/extui/dgus/DGUSScreenHandler.cpp
  31. 4
      Marlin/src/lcd/extui/dgus/DGUSScreenHandler.h
  32. 121
      Marlin/src/lcd/extui/dgus/mks/DGUSScreenHandler.cpp
  33. 11
      Marlin/src/lcd/extui/dgus_reloaded/DGUSDisplay.h
  34. 22
      Marlin/src/lcd/extui/dgus_reloaded/DGUSRxHandler.cpp
  35. 2
      Marlin/src/lcd/extui/dgus_reloaded/DGUSRxHandler.h
  36. 2
      Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.h
  37. 2
      Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/basic/resolutions.h
  38. 19
      Marlin/src/lcd/extui/mks_ui/draw_about.cpp
  39. 1
      Marlin/src/lcd/language/language_de.h
  40. 1
      Marlin/src/lcd/language/language_en.h
  41. 2
      Marlin/src/lcd/language/language_fr.h
  42. 1
      Marlin/src/lcd/language/language_it.h
  43. 1
      Marlin/src/lcd/language/language_sk.h
  44. 2
      Marlin/src/lcd/language/language_uk.h
  45. 18
      Marlin/src/lcd/marlinui.cpp
  46. 15
      Marlin/src/lcd/marlinui.h
  47. 6
      Marlin/src/lcd/menu/menu_configuration.cpp
  48. 9
      Marlin/src/lcd/menu/menu_item.h
  49. 29
      Marlin/src/lcd/menu/menu_main.cpp
  50. 22
      Marlin/src/lcd/menu/menu_ubl.cpp
  51. 2
      Marlin/src/lcd/tft/touch.cpp
  52. 4
      Marlin/src/lcd/touch/touch_buttons.cpp
  53. 4
      Marlin/src/module/probe.cpp
  54. 18
      Marlin/src/module/settings.cpp
  55. 4
      Marlin/src/module/temperature.cpp
  56. 2
      Marlin/src/module/thermistor/thermistor_504.h
  57. 2
      Marlin/src/module/thermistor/thermistor_505.h
  58. 6
      Marlin/src/pins/pins.h
  59. 2
      Marlin/src/pins/sanguino/pins_ZMIB_V2.h
  60. 4
      Marlin/src/pins/stm32f1/pins_CREALITY_V422.h
  61. 2
      Marlin/src/pins/stm32f1/pins_GTM32_PRO_VB.h
  62. 2
      Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO.h
  63. 4
      Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO_V2.h
  64. 13
      Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO_common.h
  65. 2
      Marlin/src/pins/stm32f4/pins_ARTILLERY_RUBY.h
  66. 50
      Marlin/src/sd/cardreader.cpp
  67. 15
      Marlin/src/sd/cardreader.h
  68. 20
      buildroot/share/PlatformIO/scripts/SAMD51_grandcentral_m4.py
  69. 174
      buildroot/share/PlatformIO/scripts/chitu_crypt.py
  70. 65
      buildroot/share/PlatformIO/scripts/common-cxxflags.py
  71. 16
      buildroot/share/PlatformIO/scripts/common-dependencies-post.py
  72. 488
      buildroot/share/PlatformIO/scripts/common-dependencies.py
  73. 396
      buildroot/share/PlatformIO/scripts/configuration.py
  74. 16
      buildroot/share/PlatformIO/scripts/custom_board.py
  75. 84
      buildroot/share/PlatformIO/scripts/download_mks_assets.py
  76. 44
      buildroot/share/PlatformIO/scripts/fix_framework_weakness.py
  77. 98
      buildroot/share/PlatformIO/scripts/generic_create_variant.py
  78. 46
      buildroot/share/PlatformIO/scripts/jgaurora_a5s_a1_with_bootloader.py
  79. 62
      buildroot/share/PlatformIO/scripts/lerdge.py
  80. 82
      buildroot/share/PlatformIO/scripts/marlin.py
  81. 106
      buildroot/share/PlatformIO/scripts/mc-apply.py
  82. 107
      buildroot/share/PlatformIO/scripts/offset_and_rename.py
  83. 26
      buildroot/share/PlatformIO/scripts/openblt.py
  84. 10
      buildroot/share/PlatformIO/scripts/pioutil.py
  85. 240
      buildroot/share/PlatformIO/scripts/preflight-checks.py
  86. 140
      buildroot/share/PlatformIO/scripts/preprocessor.py
  87. 6
      buildroot/share/PlatformIO/scripts/random-bin.py
  88. 751
      buildroot/share/PlatformIO/scripts/schema.py
  89. 484
      buildroot/share/PlatformIO/scripts/signature.py
  90. 63
      buildroot/share/PlatformIO/scripts/simulator.py
  91. 112
      buildroot/share/PlatformIO/scripts/stm32_serialbuffer.py
  92. 2
      buildroot/share/PlatformIO/variants/MARLIN_ARCHIM/variant.cpp
  93. 16
      buildroot/share/PlatformIO/variants/MARLIN_BTT_SKR_SE_BX/hal_conf_extra.h
  94. 28
      buildroot/share/PlatformIO/variants/MARLIN_BTT_SKR_SE_BX/variant.cpp
  95. 20
      buildroot/share/PlatformIO/variants/MARLIN_F103Rx/PeripheralPins.c
  96. 2
      buildroot/share/PlatformIO/variants/MARLIN_F103VE_LONGER/hal_conf_custom.h
  97. 2
      buildroot/share/PlatformIO/variants/MARLIN_F103VE_LONGER/variant.h
  98. 16
      buildroot/share/PlatformIO/variants/MARLIN_F103Vx/PeripheralPins.c
  99. 16
      buildroot/share/PlatformIO/variants/MARLIN_F103Zx/hal_conf_custom.h
  100. 14
      buildroot/share/PlatformIO/variants/MARLIN_F4x7Vx/hal_conf_extra.h

6
.editorconfig

@ -14,6 +14,10 @@ end_of_line = lf
indent_style = space indent_style = space
indent_size = 2 indent_size = 2
[{*.py,*.conf,*.sublime-project}] [{*.py}]
indent_style = space
indent_size = 4
[{*.conf,*.sublime-project}]
indent_style = tab indent_style = tab
indent_size = 4 indent_size = 4

31
Marlin/Configuration.h

@ -35,7 +35,7 @@
* *
* Advanced settings can be found in Configuration_adv.h * Advanced settings can be found in Configuration_adv.h
*/ */
#define CONFIGURATION_H_VERSION 02010100 #define CONFIGURATION_H_VERSION 02010200
//=========================================================================== //===========================================================================
//============================= Getting Started ============================= //============================= Getting Started =============================
@ -140,6 +140,8 @@
// Choose your own or use a service like https://www.uuidgenerator.net/version4 // Choose your own or use a service like https://www.uuidgenerator.net/version4
//#define MACHINE_UUID "00000000-0000-0000-0000-000000000000" //#define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
// @section stepper drivers
/** /**
* Stepper Drivers * Stepper Drivers
* *
@ -239,6 +241,8 @@
//#define SINGLENOZZLE_STANDBY_FAN //#define SINGLENOZZLE_STANDBY_FAN
#endif #endif
// @section multi-material
/** /**
* Multi-Material Unit * Multi-Material Unit
* Set to one of these predefined models: * Set to one of these predefined models:
@ -251,6 +255,7 @@
* *
* Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails. * Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails.
* See additional options in Configuration_adv.h. * See additional options in Configuration_adv.h.
* :["PRUSA_MMU1", "PRUSA_MMU2", "PRUSA_MMU2S", "EXTENDABLE_EMU_MMU2", "EXTENDABLE_EMU_MMU2S"]
*/ */
//#define MMU_MODEL PRUSA_MMU2 //#define MMU_MODEL PRUSA_MMU2
@ -1627,7 +1632,7 @@
#define DISABLE_E false // Disable the extruder when not stepping #define DISABLE_E false // Disable the extruder when not stepping
#define DISABLE_INACTIVE_EXTRUDER // Keep only the active extruder enabled #define DISABLE_INACTIVE_EXTRUDER // Keep only the active extruder enabled
// @section machine // @section motion
#define ALL_DRV_2208 #define ALL_DRV_2208
//#define FB_4S_STOCK //#define FB_4S_STOCK
@ -2160,9 +2165,8 @@
#define XY_DIAG_BD 282.8427124746 #define XY_DIAG_BD 282.8427124746
#define XY_SIDE_AD 200 #define XY_SIDE_AD 200
// Or, set the default skew factors directly here // Or, set the XY skew factor directly:
// to override the above measurements: //#define XY_SKEW_FACTOR 0.0
#define XY_SKEW_FACTOR 0.0
//#define SKEW_CORRECTION_FOR_Z //#define SKEW_CORRECTION_FOR_Z
#if ENABLED(SKEW_CORRECTION_FOR_Z) #if ENABLED(SKEW_CORRECTION_FOR_Z)
@ -2171,8 +2175,10 @@
#define YZ_DIAG_AC 282.8427124746 #define YZ_DIAG_AC 282.8427124746
#define YZ_DIAG_BD 282.8427124746 #define YZ_DIAG_BD 282.8427124746
#define YZ_SIDE_AD 200 #define YZ_SIDE_AD 200
#define XZ_SKEW_FACTOR 0.0
#define YZ_SKEW_FACTOR 0.0 // Or, set the Z skew factors directly:
//#define XZ_SKEW_FACTOR 0.0
//#define YZ_SKEW_FACTOR 0.0
#endif #endif
// Enable this option for M852 to set skew at runtime // Enable this option for M852 to set skew at runtime
@ -2230,7 +2236,7 @@
// @section temperature // @section temperature
// //
// Preheat Constants - Up to 6 are supported without changes // Preheat Constants - Up to 10 are supported without changes
// //
#define PREHEAT_1_LABEL "PLA" #define PREHEAT_1_LABEL "PLA"
#define PREHEAT_1_TEMP_HOTEND 180 #define PREHEAT_1_TEMP_HOTEND 180
@ -2388,7 +2394,7 @@
*/ */
//#define PRINTCOUNTER //#define PRINTCOUNTER
#if ENABLED(PRINTCOUNTER) #if ENABLED(PRINTCOUNTER)
#define PRINTCOUNTER_SAVE_INTERVAL 60 // (minutes) EEPROM save interval during print #define PRINTCOUNTER_SAVE_INTERVAL 60 // (minutes) EEPROM save interval during print. A value of 0 will save stats at end of print.
#endif #endif
// @section security // @section security
@ -3181,10 +3187,11 @@
// //
#define TOUCH_SCREEN #define TOUCH_SCREEN
#if ENABLED(TOUCH_SCREEN) #if ENABLED(TOUCH_SCREEN)
#define BUTTON_DELAY_EDIT 50 // (ms) Button repeat delay for edit screens #define BUTTON_DELAY_EDIT 50 // (ms) Button repeat delay for edit screens
#define BUTTON_DELAY_MENU 250 // (ms) Button repeat delay for menus #define BUTTON_DELAY_MENU 250 // (ms) Button repeat delay for menus
//#define TOUCH_IDLE_SLEEP 300 // (s) Turn off the TFT backlight if set (5mn) //#define DISABLE_ENCODER // Disable the click encoder, if any
//#define TOUCH_IDLE_SLEEP_MINS 5 // (minutes) Display Sleep after a period of inactivity. Set with M255 S.
#define TOUCH_SCREEN_CALIBRATION #define TOUCH_SCREEN_CALIBRATION

7
Marlin/Configuration_adv.h

@ -30,7 +30,7 @@
* *
* Basic settings can be found in Configuration.h * Basic settings can be found in Configuration.h
*/ */
#define CONFIGURATION_ADV_H_VERSION 02010100 #define CONFIGURATION_ADV_H_VERSION 02010200
// @section develop // @section develop
@ -1321,7 +1321,7 @@
// //
// LCD Backlight Timeout // LCD Backlight Timeout
// //
//#define LCD_BACKLIGHT_TIMEOUT 30 // (s) Timeout before turning off the backlight //#define LCD_BACKLIGHT_TIMEOUT_MINS 1 // (minutes) Timeout before turning off the backlight
#if HAS_BED_PROBE && EITHER(HAS_MARLINUI_MENU, HAS_TFT_LVGL_UI) #if HAS_BED_PROBE && EITHER(HAS_MARLINUI_MENU, HAS_TFT_LVGL_UI)
//#define PROBE_OFFSET_WIZARD // Add a Probe Z Offset calibration option to the LCD menu //#define PROBE_OFFSET_WIZARD // Add a Probe Z Offset calibration option to the LCD menu
@ -1578,6 +1578,7 @@
#define LONG_FILENAME_HOST_SUPPORT // Get the long filename of a file/folder with 'M33 <dosname>' and list long filenames with 'M20 L' #define LONG_FILENAME_HOST_SUPPORT // Get the long filename of a file/folder with 'M33 <dosname>' and list long filenames with 'M20 L'
#define LONG_FILENAME_WRITE_SUPPORT // Create / delete files with long filenames via M28, M30, and Binary Transfer Protocol #define LONG_FILENAME_WRITE_SUPPORT // Create / delete files with long filenames via M28, M30, and Binary Transfer Protocol
//#define M20_TIMESTAMP_SUPPORT // Include timestamps by adding the 'T' flag to M20 commands
#define SCROLL_LONG_FILENAMES // Scroll long filenames in the SD card menu #define SCROLL_LONG_FILENAMES // Scroll long filenames in the SD card menu
@ -1739,7 +1740,7 @@
* Adds the menu item Configuration > LCD Timeout (m) to set a wait period * Adds the menu item Configuration > LCD Timeout (m) to set a wait period
* from 0 (disabled) to 99 minutes. * from 0 (disabled) to 99 minutes.
*/ */
//#define DISPLAY_SLEEP_MINUTES 2 // (minutes) Timeout before turning off the screen //#define DISPLAY_SLEEP_MINUTES 2 // (minutes) Timeout before turning off the screen. Set with M255 S.
/** /**
* ST7920-based LCDs can emulate a 16 x 4 character display using * ST7920-based LCDs can emulate a 16 x 4 character display using

224
Marlin/src/HAL/LPC1768/upload_extra_script.py

@ -9,127 +9,127 @@ from __future__ import print_function
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
target_filename = "FIRMWARE.CUR" target_filename = "FIRMWARE.CUR"
target_drive = "REARM" target_drive = "REARM"
import platform import platform
current_OS = platform.system() current_OS = platform.system()
Import("env") Import("env")
def print_error(e): def print_error(e):
print('\nUnable to find destination disk (%s)\n' \ print('\nUnable to find destination disk (%s)\n' \
'Please select it in platformio.ini using the upload_port keyword ' \ 'Please select it in platformio.ini using the upload_port keyword ' \
'(https://docs.platformio.org/en/latest/projectconf/section_env_upload.html) ' \ '(https://docs.platformio.org/en/latest/projectconf/section_env_upload.html) ' \
'or copy the firmware (.pio/build/%s/firmware.bin) manually to the appropriate disk\n' \ 'or copy the firmware (.pio/build/%s/firmware.bin) manually to the appropriate disk\n' \
%(e, env.get('PIOENV'))) %(e, env.get('PIOENV')))
def before_upload(source, target, env): def before_upload(source, target, env):
try: try:
from pathlib import Path from pathlib import Path
# #
# Find a disk for upload # Find a disk for upload
# #
upload_disk = 'Disk not found' upload_disk = 'Disk not found'
target_file_found = False target_file_found = False
target_drive_found = False target_drive_found = False
if current_OS == 'Windows': if current_OS == 'Windows':
# #
# platformio.ini will accept this for a Windows upload port designation: 'upload_port = L:' # platformio.ini will accept this for a Windows upload port designation: 'upload_port = L:'
# Windows - doesn't care about the disk's name, only cares about the drive letter # Windows - doesn't care about the disk's name, only cares about the drive letter
import subprocess,string import subprocess,string
from ctypes import windll from ctypes import windll
from pathlib import PureWindowsPath from pathlib import PureWindowsPath
# getting list of drives # getting list of drives
# https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python # https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python
drives = [] drives = []
bitmask = windll.kernel32.GetLogicalDrives() bitmask = windll.kernel32.GetLogicalDrives()
for letter in string.ascii_uppercase: for letter in string.ascii_uppercase:
if bitmask & 1: if bitmask & 1:
drives.append(letter) drives.append(letter)
bitmask >>= 1 bitmask >>= 1
for drive in drives: for drive in drives:
final_drive_name = drive + ':' final_drive_name = drive + ':'
# print ('disc check: {}'.format(final_drive_name)) # print ('disc check: {}'.format(final_drive_name))
try: try:
volume_info = str(subprocess.check_output('cmd /C dir ' + final_drive_name, stderr=subprocess.STDOUT)) volume_info = str(subprocess.check_output('cmd /C dir ' + final_drive_name, stderr=subprocess.STDOUT))
except Exception as e: except Exception as e:
print ('error:{}'.format(e)) print ('error:{}'.format(e))
continue continue
else: else:
if target_drive in volume_info and not target_file_found: # set upload if not found target file yet if target_drive in volume_info and not target_file_found: # set upload if not found target file yet
target_drive_found = True target_drive_found = True
upload_disk = PureWindowsPath(final_drive_name) upload_disk = PureWindowsPath(final_drive_name)
if target_filename in volume_info: if target_filename in volume_info:
if not target_file_found: if not target_file_found:
upload_disk = PureWindowsPath(final_drive_name) upload_disk = PureWindowsPath(final_drive_name)
target_file_found = True target_file_found = True
elif current_OS == 'Linux': elif current_OS == 'Linux':
# #
# platformio.ini will accept this for a Linux upload port designation: 'upload_port = /media/media_name/drive' # platformio.ini will accept this for a Linux upload port designation: 'upload_port = /media/media_name/drive'
# #
import getpass import getpass
user = getpass.getuser() user = getpass.getuser()
mpath = Path('media', user) mpath = Path('media', user)
drives = [ x for x in mpath.iterdir() if x.is_dir() ] drives = [ x for x in mpath.iterdir() if x.is_dir() ]
if target_drive in drives: # If target drive is found, use it. if target_drive in drives: # If target drive is found, use it.
target_drive_found = True target_drive_found = True
upload_disk = mpath / target_drive upload_disk = mpath / target_drive
else: else:
for drive in drives: for drive in drives:
try: try:
fpath = mpath / drive fpath = mpath / drive
files = [ x for x in fpath.iterdir() if x.is_file() ] filenames = [ x.name for x in fpath.iterdir() if x.is_file() ]
except: except:
continue continue
else: else:
if target_filename in files: if target_filename in filenames:
upload_disk = mpath / drive upload_disk = mpath / drive
target_file_found = True target_file_found = True
break break
# #
# set upload_port to drive if found # set upload_port to drive if found
# #
if target_file_found or target_drive_found: if target_file_found or target_drive_found:
env.Replace( env.Replace(
UPLOAD_FLAGS="-P$UPLOAD_PORT" UPLOAD_FLAGS="-P$UPLOAD_PORT"
) )
elif current_OS == 'Darwin': # MAC elif current_OS == 'Darwin': # MAC
# #
# platformio.ini will accept this for a OSX upload port designation: 'upload_port = /media/media_name/drive' # platformio.ini will accept this for a OSX upload port designation: 'upload_port = /media/media_name/drive'
# #
dpath = Path('/Volumes') # human readable names dpath = Path('/Volumes') # human readable names
drives = [ x for x in dpath.iterdir() ] drives = [ x for x in dpath.iterdir() if x.is_dir() ]
if target_drive in drives and not target_file_found: # set upload if not found target file yet if target_drive in drives and not target_file_found: # set upload if not found target file yet
target_drive_found = True target_drive_found = True
upload_disk = dpath / target_drive upload_disk = dpath / target_drive
for drive in drives: for drive in drives:
try: try:
fpath = dpath / drive # will get an error if the drive is protected fpath = dpath / drive # will get an error if the drive is protected
files = [ x for x in fpath.iterdir() ] filenames = [ x.name for x in fpath.iterdir() if x.is_file() ]
except: except:
continue continue
else: else:
if target_filename in files: if target_filename in filenames:
if not target_file_found: upload_disk = dpath / drive
upload_disk = dpath / drive target_file_found = True
target_file_found = True break
# #
# Set upload_port to drive if found # Set upload_port to drive if found
# #
if target_file_found or target_drive_found: if target_file_found or target_drive_found:
env.Replace(UPLOAD_PORT=str(upload_disk)) env.Replace(UPLOAD_PORT=str(upload_disk))
print('\nUpload disk: ', upload_disk, '\n') print('\nUpload disk: ', upload_disk, '\n')
else: else:
print_error('Autodetect Error') print_error('Autodetect Error')
except Exception as e: except Exception as e:
print_error(str(e)) print_error(str(e))
env.AddPreAction("upload", before_upload) env.AddPreAction("upload", before_upload)

2
Marlin/src/HAL/NATIVE_SIM/fastio.h

@ -44,7 +44,7 @@
* *
* Now you can simply SET_OUTPUT(STEP); WRITE(STEP, HIGH); WRITE(STEP, LOW); * Now you can simply SET_OUTPUT(STEP); WRITE(STEP, HIGH); WRITE(STEP, LOW);
* *
* Why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html * Why double up on these macros? see https://gcc.gnu.org/onlinedocs/cpp/Stringification.html
*/ */
/// Read a pin /// Read a pin

2
Marlin/src/HAL/NATIVE_SIM/tft/xpt2046.h

@ -51,7 +51,7 @@ enum XPTCoordinate : uint8_t {
XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE, XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE,
}; };
#if !defined(XPT2046_Z1_THRESHOLD) #ifndef XPT2046_Z1_THRESHOLD
#define XPT2046_Z1_THRESHOLD 10 #define XPT2046_Z1_THRESHOLD 10
#endif #endif

5
Marlin/src/HAL/STM32/inc/Conditionals_post.h

@ -27,3 +27,8 @@
#elif EITHER(I2C_EEPROM, SPI_EEPROM) #elif EITHER(I2C_EEPROM, SPI_EEPROM)
#define USE_SHARED_EEPROM 1 #define USE_SHARED_EEPROM 1
#endif #endif
// Some STM32F4 boards may lose steps when saving to EEPROM during print (PR #17946)
#if defined(STM32F4xx) && PRINTCOUNTER_SAVE_INTERVAL > 0
#define PRINTCOUNTER_SYNC 1
#endif

5
Marlin/src/HAL/STM32/inc/SanityCheck.h

@ -37,11 +37,6 @@
#error "SDCARD_EEPROM_EMULATION requires SDSUPPORT. Enable SDSUPPORT or choose another EEPROM emulation." #error "SDCARD_EEPROM_EMULATION requires SDSUPPORT. Enable SDSUPPORT or choose another EEPROM emulation."
#endif #endif
#if defined(STM32F4xx) && BOTH(PRINTCOUNTER, FLASH_EEPROM_EMULATION)
#warning "FLASH_EEPROM_EMULATION may cause long delays when writing and should not be used while printing."
#error "Disable PRINTCOUNTER or choose another EEPROM emulation."
#endif
#if !defined(STM32F4xx) && ENABLED(FLASH_EEPROM_LEVELING) #if !defined(STM32F4xx) && ENABLED(FLASH_EEPROM_LEVELING)
#error "FLASH_EEPROM_LEVELING is currently only supported on STM32F4 hardware." #error "FLASH_EEPROM_LEVELING is currently only supported on STM32F4 hardware."
#endif #endif

2
Marlin/src/HAL/STM32/tft/tft_fsmc.cpp

@ -147,7 +147,7 @@ uint32_t TFT_FSMC::ReadID(tft_data_t Reg) {
} }
bool TFT_FSMC::isBusy() { bool TFT_FSMC::isBusy() {
#if defined(STM32F1xx) #ifdef STM32F1xx
volatile bool dmaEnabled = (DMAtx.Instance->CCR & DMA_CCR_EN) != RESET; volatile bool dmaEnabled = (DMAtx.Instance->CCR & DMA_CCR_EN) != RESET;
#elif defined(STM32F4xx) #elif defined(STM32F4xx)
volatile bool dmaEnabled = DMAtx.Instance->CR & DMA_SxCR_EN; volatile bool dmaEnabled = DMAtx.Instance->CR & DMA_SxCR_EN;

2
Marlin/src/HAL/STM32/tft/tft_spi.cpp

@ -179,7 +179,7 @@ uint32_t TFT_SPI::ReadID(uint16_t Reg) {
} }
bool TFT_SPI::isBusy() { bool TFT_SPI::isBusy() {
#if defined(STM32F1xx) #ifdef STM32F1xx
volatile bool dmaEnabled = (DMAtx.Instance->CCR & DMA_CCR_EN) != RESET; volatile bool dmaEnabled = (DMAtx.Instance->CCR & DMA_CCR_EN) != RESET;
#elif defined(STM32F4xx) #elif defined(STM32F4xx)
volatile bool dmaEnabled = DMAtx.Instance->CR & DMA_SxCR_EN; volatile bool dmaEnabled = DMAtx.Instance->CR & DMA_SxCR_EN;

2
Marlin/src/MarlinCore.cpp

@ -488,7 +488,7 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
} }
#endif #endif
#if HAS_FREEZE_PIN #if ENABLED(FREEZE_FEATURE)
stepper.frozen = READ(FREEZE_PIN) == FREEZE_STATE; stepper.frozen = READ(FREEZE_PIN) == FREEZE_STATE;
#endif #endif

2
Marlin/src/core/macros.h

@ -21,7 +21,7 @@
*/ */
#pragma once #pragma once
#if !defined(__has_include) #ifndef __has_include
#define __has_include(...) 1 #define __has_include(...) 1
#endif #endif

4
Marlin/src/core/types.h

@ -752,8 +752,12 @@ struct XYZEval {
// Exact comparisons. For floats a "NEAR" operation may be better. // Exact comparisons. For floats a "NEAR" operation may be better.
FI bool operator==(const XYZval<T> &rs) { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); } FI bool operator==(const XYZval<T> &rs) { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator==(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); } FI bool operator==(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator==(const XYZEval<T> &rs) { return true LOGICAL_AXIS_GANG(&& e == rs.e, && x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator==(const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e == rs.e, && x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator!=(const XYZval<T> &rs) { return !operator==(rs); } FI bool operator!=(const XYZval<T> &rs) { return !operator==(rs); }
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); } FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
FI bool operator!=(const XYZEval<T> &rs) { return !operator==(rs); }
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
}; };
#undef _RECIP #undef _RECIP

33
Marlin/src/feature/bedlevel/bdl/bdl.cpp

@ -96,22 +96,23 @@ void BDS_Leveling::process() {
const float z_sensor = (tmp & 0x3FF) / 100.0f; const float z_sensor = (tmp & 0x3FF) / 100.0f;
if (cur_z < 0) config_state = 0; if (cur_z < 0) config_state = 0;
//float abs_z = current_position.z > cur_z ? (current_position.z - cur_z) : (cur_z - current_position.z); //float abs_z = current_position.z > cur_z ? (current_position.z - cur_z) : (cur_z - current_position.z);
if ( cur_z < config_state * 0.1f #if ENABLED(BABYSTEPPING)
&& config_state > 0 if (cur_z < config_state * 0.1f
&& old_cur_z == cur_z && config_state > 0
&& old_buf_z == current_position.z && old_cur_z == cur_z
&& z_sensor < (MAX_BD_HEIGHT) && old_buf_z == current_position.z
) { && z_sensor < (MAX_BD_HEIGHT)
babystep.set_mm(Z_AXIS, cur_z - z_sensor); ) {
#if ENABLED(DEBUG_OUT_BD) babystep.set_mm(Z_AXIS, cur_z - z_sensor);
SERIAL_ECHOLNPGM("BD:", z_sensor, ", Z:", cur_z, "|", current_position.z); #if ENABLED(DEBUG_OUT_BD)
#endif SERIAL_ECHOLNPGM("BD:", z_sensor, ", Z:", cur_z, "|", current_position.z);
} #endif
else { }
babystep.set_mm(Z_AXIS, 0); else {
//if (old_cur_z <= cur_z) Z_DIR_WRITE(!INVERT_Z_DIR); babystep.set_mm(Z_AXIS, 0); //if (old_cur_z <= cur_z) Z_DIR_WRITE(!INVERT_Z_DIR);
stepper.set_directions(); stepper.set_directions();
} }
#endif
old_cur_z = cur_z; old_cur_z = cur_z;
old_buf_z = current_position.z; old_buf_z = current_position.z;
endstops.bdp_state_update(z_sensor <= 0.01f); endstops.bdp_state_update(z_sensor <= 0.01f);

10
Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp

@ -423,10 +423,12 @@
LIMIT(icell.x, 0, GRID_MAX_CELLS_X); LIMIT(icell.x, 0, GRID_MAX_CELLS_X);
LIMIT(icell.y, 0, GRID_MAX_CELLS_Y); LIMIT(icell.y, 0, GRID_MAX_CELLS_Y);
float z_x0y0 = z_values[icell.x ][icell.y ], // z at lower left corner const int8_t ncellx = _MIN(icell.x+1, GRID_MAX_CELLS_X),
z_x1y0 = z_values[icell.x+1][icell.y ], // z at upper left corner ncelly = _MIN(icell.y+1, GRID_MAX_CELLS_Y);
z_x0y1 = z_values[icell.x ][icell.y+1], // z at lower right corner float z_x0y0 = z_values[icell.x][icell.y], // z at lower left corner
z_x1y1 = z_values[icell.x+1][icell.y+1]; // z at upper right corner z_x1y0 = z_values[ncellx ][icell.y], // z at upper left corner
z_x0y1 = z_values[icell.x][ncelly ], // z at lower right corner
z_x1y1 = z_values[ncellx ][ncelly ]; // z at upper right corner
if (isnan(z_x0y0)) z_x0y0 = 0; // ideally activating planner.leveling_active (G29 A) if (isnan(z_x0y0)) z_x0y0 = 0; // ideally activating planner.leveling_active (G29 A)
if (isnan(z_x1y0)) z_x1y0 = 0; // should refuse if any invalid mesh points if (isnan(z_x1y0)) z_x1y0 = 0; // should refuse if any invalid mesh points

2
Marlin/src/feature/spindle_laser.h

@ -285,7 +285,7 @@ public:
if (!menuPower) menuPower = cpwr_to_upwr(SPEED_POWER_STARTUP); if (!menuPower) menuPower = cpwr_to_upwr(SPEED_POWER_STARTUP);
power = upower_to_ocr(menuPower); power = upower_to_ocr(menuPower);
apply_power(power); apply_power(power);
} else } else
apply_power(0); apply_power(0);
} }

14
Marlin/src/gcode/lcd/M255.cpp

@ -32,12 +32,11 @@
*/ */
void GcodeSuite::M255() { void GcodeSuite::M255() {
if (parser.seenval('S')) { if (parser.seenval('S')) {
const int m = parser.value_int();
#if HAS_DISPLAY_SLEEP #if HAS_DISPLAY_SLEEP
const int m = parser.value_int(); ui.sleep_timeout_minutes = constrain(m, ui.sleep_timeout_min, ui.sleep_timeout_max);
ui.sleep_timeout_minutes = constrain(m, SLEEP_TIMEOUT_MIN, SLEEP_TIMEOUT_MAX);
#else #else
const unsigned int s = parser.value_ushort() * 60; ui.backlight_timeout_minutes = constrain(m, ui.backlight_timeout_min, ui.backlight_timeout_max);
ui.lcd_backlight_timeout = constrain(s, LCD_BKL_TIMEOUT_MIN, LCD_BKL_TIMEOUT_MAX);
#endif #endif
} }
else else
@ -47,11 +46,8 @@ void GcodeSuite::M255() {
void GcodeSuite::M255_report(const bool forReplay/*=true*/) { void GcodeSuite::M255_report(const bool forReplay/*=true*/) {
report_heading_etc(forReplay, F(STR_DISPLAY_SLEEP)); report_heading_etc(forReplay, F(STR_DISPLAY_SLEEP));
SERIAL_ECHOLNPGM(" M255 S", SERIAL_ECHOLNPGM(" M255 S",
#if HAS_DISPLAY_SLEEP TERN(HAS_DISPLAY_SLEEP, ui.sleep_timeout_minutes, ui.backlight_timeout_minutes),
ui.sleep_timeout_minutes, " ; (minutes)" " ; (minutes)"
#else
ui.lcd_backlight_timeout, " ; (seconds)"
#endif
); );
} }

26
Marlin/src/gcode/parser.h

@ -256,22 +256,20 @@ public:
// Float removes 'E' to prevent scientific notation interpretation // Float removes 'E' to prevent scientific notation interpretation
static float value_float() { static float value_float() {
if (value_ptr) { if (!value_ptr) return 0;
char *e = value_ptr; char *e = value_ptr;
for (;;) { for (;;) {
const char c = *e; const char c = *e;
if (c == '\0' || c == ' ') break; if (c == '\0' || c == ' ') break;
if (c == 'E' || c == 'e') { if (c == 'E' || c == 'e' || c == 'X' || c == 'x') {
*e = '\0'; *e = '\0';
const float ret = strtof(value_ptr, nullptr); const float ret = strtof(value_ptr, nullptr);
*e = c; *e = c;
return ret; return ret;
}
++e;
} }
return strtof(value_ptr, nullptr); ++e;
} }
return 0; return strtof(value_ptr, nullptr);
} }
// Code value as a long or ulong // Code value as a long or ulong

21
Marlin/src/gcode/sd/M20.cpp

@ -28,18 +28,23 @@
#include "../../sd/cardreader.h" #include "../../sd/cardreader.h"
/** /**
* M20: List SD card to serial output * M20: List SD card to serial output in [name] [size] format.
*
* With CUSTOM_FIRMWARE_UPLOAD:
* F<bool> - List BIN files only, for use with firmware upload
*
* With LONG_FILENAME_HOST_SUPPORT:
* L<bool> - List long filenames (instead of DOS8.3 names)
*
* With M20_TIMESTAMP_SUPPORT:
* T<bool> - Include timestamps
*/ */
void GcodeSuite::M20() { void GcodeSuite::M20() {
if (card.flag.mounted) { if (card.flag.mounted) {
SERIAL_ECHOLNPGM(STR_BEGIN_FILE_LIST); SERIAL_ECHOLNPGM(STR_BEGIN_FILE_LIST);
card.ls( card.ls(TERN0(CUSTOM_FIRMWARE_UPLOAD, parser.boolval('F') << LS_ONLY_BIN)
TERN_(CUSTOM_FIRMWARE_UPLOAD, parser.boolval('F')) | TERN0(LONG_FILENAME_HOST_SUPPORT, parser.boolval('L') << LS_LONG_FILENAME)
#if BOTH(CUSTOM_FIRMWARE_UPLOAD, LONG_FILENAME_HOST_SUPPORT) | TERN0(M20_TIMESTAMP_SUPPORT, parser.boolval('T') << LS_TIMESTAMP));
,
#endif
TERN_(LONG_FILENAME_HOST_SUPPORT, parser.boolval('L'))
);
SERIAL_ECHOLNPGM(STR_END_FILE_LIST); SERIAL_ECHOLNPGM(STR_END_FILE_LIST);
} }
else else

3
Marlin/src/inc/Conditionals_LCD.h

@ -373,6 +373,7 @@
#define LCD_I2C_TYPE_PCF8575 // I2C Character-based 12864 display #define LCD_I2C_TYPE_PCF8575 // I2C Character-based 12864 display
#define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander #define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander
#define IS_ULTIPANEL 1
#if ENABLED(LCD_SAINSMART_I2C_2004) #if ENABLED(LCD_SAINSMART_I2C_2004)
#define LCD_WIDTH 20 #define LCD_WIDTH 20
@ -1598,7 +1599,7 @@
// This emulated DOGM has 'touch/xpt2046', not 'tft/xpt2046' // This emulated DOGM has 'touch/xpt2046', not 'tft/xpt2046'
#if ENABLED(TOUCH_SCREEN) #if ENABLED(TOUCH_SCREEN)
#if TOUCH_IDLE_SLEEP #if TOUCH_IDLE_SLEEP_MINS
#define HAS_TOUCH_SLEEP 1 #define HAS_TOUCH_SLEEP 1
#endif #endif
#if NONE(TFT_TOUCH_DEVICE_GT911, TFT_TOUCH_DEVICE_XPT2046) #if NONE(TFT_TOUCH_DEVICE_GT911, TFT_TOUCH_DEVICE_XPT2046)

6
Marlin/src/inc/Conditionals_adv.h

@ -647,10 +647,10 @@
#if ALL(HAS_RESUME_CONTINUE, PRINTER_EVENT_LEDS, SDSUPPORT) #if ALL(HAS_RESUME_CONTINUE, PRINTER_EVENT_LEDS, SDSUPPORT)
#define HAS_LEDS_OFF_FLAG 1 #define HAS_LEDS_OFF_FLAG 1
#endif #endif
#ifdef DISPLAY_SLEEP_MINUTES #if DISPLAY_SLEEP_MINUTES || TOUCH_IDLE_SLEEP_MINS
#define HAS_DISPLAY_SLEEP 1 #define HAS_DISPLAY_SLEEP 1
#endif #endif
#if HAS_DISPLAY_SLEEP || LCD_BACKLIGHT_TIMEOUT #if HAS_DISPLAY_SLEEP || LCD_BACKLIGHT_TIMEOUT_MINS
#define HAS_GCODE_M255 1 #define HAS_GCODE_M255 1
#endif #endif
@ -1003,7 +1003,7 @@
#endif #endif
// Flag whether hex_print.cpp is used // Flag whether hex_print.cpp is used
#if ANY(AUTO_BED_LEVELING_UBL, M100_FREE_MEMORY_WATCHER, DEBUG_GCODE_PARSER, TMC_DEBUG, MARLIN_DEV_MODE, DEBUG_CARDREADER) #if ANY(AUTO_BED_LEVELING_UBL, M100_FREE_MEMORY_WATCHER, DEBUG_GCODE_PARSER, TMC_DEBUG, MARLIN_DEV_MODE, DEBUG_CARDREADER, M20_TIMESTAMP_SUPPORT)
#define NEED_HEX_PRINT 1 #define NEED_HEX_PRINT 1
#endif #endif

10
Marlin/src/inc/Conditionals_post.h

@ -3306,7 +3306,15 @@
#endif #endif
#if HAS_TEMPERATURE && ANY(HAS_MARLINUI_MENU, HAS_DWIN_E3V2, HAS_DGUS_LCD_CLASSIC) #if HAS_TEMPERATURE && ANY(HAS_MARLINUI_MENU, HAS_DWIN_E3V2, HAS_DGUS_LCD_CLASSIC)
#ifdef PREHEAT_6_LABEL #ifdef PREHEAT_10_LABEL
#define PREHEAT_COUNT 10
#elif defined(PREHEAT_9_LABEL)
#define PREHEAT_COUNT 9
#elif defined(PREHEAT_8_LABEL)
#define PREHEAT_COUNT 8
#elif defined(PREHEAT_7_LABEL)
#define PREHEAT_COUNT 7
#elif defined(PREHEAT_6_LABEL)
#define PREHEAT_COUNT 6 #define PREHEAT_COUNT 6
#elif defined(PREHEAT_5_LABEL) #elif defined(PREHEAT_5_LABEL)
#define PREHEAT_COUNT 5 #define PREHEAT_COUNT 5

30
Marlin/src/inc/SanityCheck.h

@ -642,6 +642,10 @@
#error "LEVEL_CORNERS_* settings have been renamed BED_TRAMMING_*." #error "LEVEL_CORNERS_* settings have been renamed BED_TRAMMING_*."
#elif defined(LEVEL_CENTER_TOO) #elif defined(LEVEL_CENTER_TOO)
#error "LEVEL_CENTER_TOO is now BED_TRAMMING_INCLUDE_CENTER." #error "LEVEL_CENTER_TOO is now BED_TRAMMING_INCLUDE_CENTER."
#elif defined(TOUCH_IDLE_SLEEP)
#error "TOUCH_IDLE_SLEEP (seconds) is now TOUCH_IDLE_SLEEP_MINS (minutes)."
#elif defined(LCD_BACKLIGHT_TIMEOUT)
#error "LCD_BACKLIGHT_TIMEOUT (seconds) is now LCD_BACKLIGHT_TIMEOUT_MINS (minutes)."
#endif #endif
// L64xx stepper drivers have been removed // L64xx stepper drivers have been removed
@ -2193,14 +2197,22 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#if ENABLED(USE_CONTROLLER_FAN) #if ENABLED(USE_CONTROLLER_FAN)
#if !HAS_CONTROLLER_FAN #if !HAS_CONTROLLER_FAN
#error "USE_CONTROLLER_FAN requires a CONTROLLER_FAN_PIN. Define in Configuration_adv.h." #error "USE_CONTROLLER_FAN requires a CONTROLLER_FAN_PIN. Define in Configuration_adv.h."
#elif E0_AUTO_FAN_PIN == CONTROLLER_FAN_PIN #elif PIN_EXISTS(E0_AUTO_FAN) && E0_AUTO_FAN_PIN == CONTROLLER_FAN_PIN
#error "You cannot set E0_AUTO_FAN_PIN equal to CONTROLLER_FAN_PIN." #error "You cannot set E0_AUTO_FAN_PIN equal to CONTROLLER_FAN_PIN."
#elif E1_AUTO_FAN_PIN == CONTROLLER_FAN_PIN #elif PIN_EXISTS(E1_AUTO_FAN) && E1_AUTO_FAN_PIN == CONTROLLER_FAN_PIN
#error "You cannot set E1_AUTO_FAN_PIN equal to CONTROLLER_FAN_PIN." #error "You cannot set E1_AUTO_FAN_PIN equal to CONTROLLER_FAN_PIN."
#elif E2_AUTO_FAN_PIN == CONTROLLER_FAN_PIN #elif PIN_EXISTS(E2_AUTO_FAN) && E2_AUTO_FAN_PIN == CONTROLLER_FAN_PIN
#error "You cannot set E2_AUTO_FAN_PIN equal to CONTROLLER_FAN_PIN." #error "You cannot set E2_AUTO_FAN_PIN equal to CONTROLLER_FAN_PIN."
#elif E3_AUTO_FAN_PIN == CONTROLLER_FAN_PIN #elif PIN_EXISTS(E3_AUTO_FAN) && E3_AUTO_FAN_PIN == CONTROLLER_FAN_PIN
#error "You cannot set E3_AUTO_FAN_PIN equal to CONTROLLER_FAN_PIN." #error "You cannot set E3_AUTO_FAN_PIN equal to CONTROLLER_FAN_PIN."
#elif PIN_EXISTS(E4_AUTO_FAN) && E4_AUTO_FAN_PIN == CONTROLLER_FAN_PIN
#error "You cannot set E4_AUTO_FAN_PIN equal to CONTROLLER_FAN_PIN."
#elif PIN_EXISTS(E5_AUTO_FAN) && E5_AUTO_FAN_PIN == CONTROLLER_FAN_PIN
#error "You cannot set E5_AUTO_FAN_PIN equal to CONTROLLER_FAN_PIN."
#elif PIN_EXISTS(E6_AUTO_FAN) && E6_AUTO_FAN_PIN == CONTROLLER_FAN_PIN
#error "You cannot set E6_AUTO_FAN_PIN equal to CONTROLLER_FAN_PIN."
#elif PIN_EXISTS(E7_AUTO_FAN) && E7_AUTO_FAN_PIN == CONTROLLER_FAN_PIN
#error "You cannot set E7_AUTO_FAN_PIN equal to CONTROLLER_FAN_PIN."
#endif #endif
#endif #endif
@ -2276,7 +2288,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
* Redundant temperature sensor config * Redundant temperature sensor config
*/ */
#if HAS_TEMP_REDUNDANT #if HAS_TEMP_REDUNDANT
#if !defined(TEMP_SENSOR_REDUNDANT_SOURCE) #ifndef TEMP_SENSOR_REDUNDANT_SOURCE
#error "TEMP_SENSOR_REDUNDANT requires TEMP_SENSOR_REDUNDANT_SOURCE." #error "TEMP_SENSOR_REDUNDANT requires TEMP_SENSOR_REDUNDANT_SOURCE."
#elif !defined(TEMP_SENSOR_REDUNDANT_TARGET) #elif !defined(TEMP_SENSOR_REDUNDANT_TARGET)
#error "TEMP_SENSOR_REDUNDANT requires TEMP_SENSOR_REDUNDANT_TARGET." #error "TEMP_SENSOR_REDUNDANT requires TEMP_SENSOR_REDUNDANT_TARGET."
@ -2984,7 +2996,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#endif #endif
#if ENABLED(ANYCUBIC_LCD_CHIRON) #if ENABLED(ANYCUBIC_LCD_CHIRON)
#if !defined(BEEPER_PIN) #ifndef BEEPER_PIN
#error "ANYCUBIC_LCD_CHIRON requires BEEPER_PIN" #error "ANYCUBIC_LCD_CHIRON requires BEEPER_PIN"
#elif DISABLED(SDSUPPORT) #elif DISABLED(SDSUPPORT)
#error "ANYCUBIC_LCD_CHIRON requires SDSUPPORT" #error "ANYCUBIC_LCD_CHIRON requires SDSUPPORT"
@ -3030,11 +3042,11 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#endif #endif
#endif #endif
#if LCD_BACKLIGHT_TIMEOUT #if LCD_BACKLIGHT_TIMEOUT_MINS
#if !HAS_ENCODER_ACTION #if !HAS_ENCODER_ACTION
#error "LCD_BACKLIGHT_TIMEOUT requires an LCD with encoder or keypad." #error "LCD_BACKLIGHT_TIMEOUT_MINS requires an LCD with encoder or keypad."
#elif !PIN_EXISTS(LCD_BACKLIGHT) #elif !PIN_EXISTS(LCD_BACKLIGHT)
#error "LCD_BACKLIGHT_TIMEOUT requires LCD_BACKLIGHT_PIN." #error "LCD_BACKLIGHT_TIMEOUT_MINS requires LCD_BACKLIGHT_PIN."
#endif #endif
#endif #endif

2
Marlin/src/inc/Version.h

@ -52,7 +52,7 @@
* to alert users to major changes. * to alert users to major changes.
*/ */
#define MARLIN_HEX_VERSION 02010100 #define MARLIN_HEX_VERSION 02010200
#ifndef REQUIRED_CONFIGURATION_H_VERSION #ifndef REQUIRED_CONFIGURATION_H_VERSION
#define REQUIRED_CONFIGURATION_H_VERSION MARLIN_HEX_VERSION #define REQUIRED_CONFIGURATION_H_VERSION MARLIN_HEX_VERSION
#endif #endif

5
Marlin/src/inc/Warnings.cpp

@ -707,9 +707,8 @@
#warning "Don't forget to update your TFT settings in Configuration.h." #warning "Don't forget to update your TFT settings in Configuration.h."
#endif #endif
// Ender 3 Pro (but, apparently all Creality 4.2.2 boards) #if ENABLED(EMIT_CREALITY_422_WARNING)
#if ENABLED(EMIT_CREALITY_422_WARNING) || MB(CREALITY_V4) #warning "Creality 4.2.2 boards come with a variety of stepper drivers. Check the board label and set the correct *_DRIVER_TYPE! (C=HR4988, E=A4988, A=TMC2208, B=TMC2209, H=TMC2225). (Define EMIT_CREALITY_422_WARNING false to suppress this warning.)"
#warning "Creality 4.2.2 boards come with a variety of stepper drivers. Check the board label and set the correct *_DRIVER_TYPE! (C=HR4988, E=A4988, A=TMC2208, B=TMC2209, H=TMC2225)."
#endif #endif
#if PRINTCOUNTER_SYNC #if PRINTCOUNTER_SYNC

3
Marlin/src/lcd/dogm/marlinui_DOGM.cpp

@ -343,8 +343,7 @@ void MarlinUI::draw_kill_screen() {
void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
#if HAS_DISPLAY_SLEEP #if HAS_DISPLAY_SLEEP
void MarlinUI::sleep_on() { u8g.sleepOn(); } void MarlinUI::sleep_display(const bool sleep) { sleep ? u8g.sleepOn() : u8g.sleepOff(); }
void MarlinUI::sleep_off() { u8g.sleepOff(); }
#endif #endif
#if HAS_LCD_BRIGHTNESS #if HAS_LCD_BRIGHTNESS

10
Marlin/src/lcd/e3v2/common/dwin_api.cpp

@ -234,7 +234,7 @@ void DWIN_Frame_AreaMove(uint8_t mode, uint8_t dir, uint16_t dis,
// *string: The string // *string: The string
// rlimit: To limit the drawn string length // rlimit: To limit the drawn string length
void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, const char * const string, uint16_t rlimit/*=0xFFFF*/) { void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, const char * const string, uint16_t rlimit/*=0xFFFF*/) {
#if DISABLED(DWIN_LCD_PROUI) #if NONE(DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI)
DWIN_Draw_Rectangle(1, bColor, x, y, x + (fontWidth(size) * strlen_P(string)), y + fontHeight(size)); DWIN_Draw_Rectangle(1, bColor, x, y, x + (fontWidth(size) * strlen_P(string)), y + fontHeight(size));
#endif #endif
constexpr uint8_t widthAdjust = 0; constexpr uint8_t widthAdjust = 0;
@ -266,7 +266,9 @@ void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor,
void DWIN_Draw_IntValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, void DWIN_Draw_IntValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, uint32_t value) { uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, uint32_t value) {
size_t i = 0; size_t i = 0;
DWIN_Draw_Rectangle(1, bColor, x, y, x + fontWidth(size) * iNum + 1, y + fontHeight(size)); #if DISABLED(DWIN_CREALITY_LCD_JYERSUI)
DWIN_Draw_Rectangle(1, bColor, x, y, x + fontWidth(size) * iNum + 1, y + fontHeight(size));
#endif
DWIN_Byte(i, 0x14); DWIN_Byte(i, 0x14);
// Bit 7: bshow // Bit 7: bshow
// Bit 6: 1 = signed; 0 = unsigned number; // Bit 6: 1 = signed; 0 = unsigned number;
@ -314,7 +316,9 @@ void DWIN_Draw_FloatValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_
uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, int32_t value) { uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, int32_t value) {
//uint8_t *fvalue = (uint8_t*)&value; //uint8_t *fvalue = (uint8_t*)&value;
size_t i = 0; size_t i = 0;
DWIN_Draw_Rectangle(1, bColor, x, y, x + fontWidth(size) * (iNum+fNum+1), y + fontHeight(size)); #if DISABLED(DWIN_CREALITY_LCD_JYERSUI)
DWIN_Draw_Rectangle(1, bColor, x, y, x + fontWidth(size) * (iNum+fNum+1), y + fontHeight(size));
#endif
DWIN_Byte(i, 0x14); DWIN_Byte(i, 0x14);
DWIN_Byte(i, (bShow * 0x80) | (zeroFill * 0x20) | (zeroMode * 0x10) | size); DWIN_Byte(i, (bShow * 0x80) | (zeroFill * 0x20) | (zeroMode * 0x10) | size);
DWIN_Word(i, color); DWIN_Word(i, color);

150
Marlin/src/lcd/e3v2/jyersui/dwin.cpp

@ -204,6 +204,55 @@ bool probe_deployed = false;
CrealityDWINClass CrealityDWIN; CrealityDWINClass CrealityDWIN;
template <unsigned N, unsigned S = N>
class TextScroller {
public:
static const unsigned SIZE = N;
static const unsigned SPACE = S;
typedef char Buffer[SIZE + 1];
inline TextScroller()
: scrollpos(0)
{ }
inline void reset() {
scrollpos = 0;
}
const char* scroll(size_t& pos, Buffer &buf, const char * text, bool *updated = nullptr) {
const size_t len = strlen(text);
if (len > SIZE) {
if (updated) *updated = true;
if (scrollpos >= len + SPACE) scrollpos = 0;
pos = 0;
if (scrollpos < len) {
const size_t n = min(len - scrollpos, SIZE);
memcpy(buf, text + scrollpos, n);
pos += n;
}
if (pos < SIZE) {
const size_t n = min(len + SPACE - scrollpos, SIZE - pos);
memset(buf + pos, ' ', n);
pos += n;
}
if (pos < SIZE) {
const size_t n = SIZE - pos;
memcpy(buf + pos, text, n);
pos += n;
}
buf[pos] = '\0';
++scrollpos;
return buf;
} else {
pos = len;
return text;
}
}
private:
uint16_t scrollpos;
};
#if HAS_MESH #if HAS_MESH
struct Mesh_Settings { struct Mesh_Settings {
@ -689,31 +738,13 @@ void CrealityDWINClass::Draw_Print_Screen() {
} }
void CrealityDWINClass::Draw_Print_Filename(const bool reset/*=false*/) { void CrealityDWINClass::Draw_Print_Filename(const bool reset/*=false*/) {
static uint8_t namescrl = 0; typedef TextScroller<30> Scroller;
if (reset) namescrl = 0; static Scroller scroller;
if (reset) scroller.reset();
if (process == Print) { if (process == Print) {
constexpr int8_t maxlen = 30; Scroller::Buffer buf;
char *outstr = filename; size_t outlen = 0;
size_t slen = strlen(filename); const char* outstr = scroller.scroll(outlen, buf, filename);
int8_t outlen = slen;
if (slen > maxlen) {
char dispname[maxlen + 1];
int8_t pos = slen - namescrl, len = maxlen;
if (pos >= 0) {
NOMORE(len, pos);
LOOP_L_N(i, len) dispname[i] = filename[i + namescrl];
}
else {
const int8_t mp = maxlen + pos;
LOOP_L_N(i, mp) dispname[i] = ' ';
LOOP_S_L_N(i, mp, maxlen) dispname[i] = filename[i - mp];
if (mp <= 0) namescrl = 0;
}
dispname[len] = '\0';
outstr = dispname;
outlen = maxlen;
namescrl++;
}
DWIN_Draw_Rectangle(1, Color_Bg_Black, 8, 50, DWIN_WIDTH - 8, 80); DWIN_Draw_Rectangle(1, Color_Bg_Black, 8, 50, DWIN_WIDTH - 8, 80);
const int8_t npos = (DWIN_WIDTH - outlen * MENU_CHR_W) / 2; const int8_t npos = (DWIN_WIDTH - outlen * MENU_CHR_W) / 2;
DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Black, npos, 60, outstr); DWIN_Draw_String(false, DWIN_FONT_MENU, Color_White, Color_Bg_Black, npos, 60, outstr);
@ -973,57 +1004,30 @@ void CrealityDWINClass::Popup_Select() {
} }
void CrealityDWINClass::Update_Status_Bar(bool refresh/*=false*/) { void CrealityDWINClass::Update_Status_Bar(bool refresh/*=false*/) {
typedef TextScroller<30> Scroller;
static bool new_msg; static bool new_msg;
static uint8_t msgscrl = 0; static Scroller scroller;
static char lastmsg[64]; static char lastmsg[64];
if (strcmp(lastmsg, statusmsg) != 0 || refresh) { if (strcmp(lastmsg, statusmsg) != 0 || refresh) {
strcpy(lastmsg, statusmsg); strcpy(lastmsg, statusmsg);
msgscrl = 0; scroller.reset();
new_msg = true; new_msg = true;
} }
size_t len = strlen(statusmsg); Scroller::Buffer buf;
int8_t pos = len; size_t len = 0;
if (pos > 30) { const char* dispmsg = scroller.scroll(len, buf, statusmsg, &new_msg);
pos -= msgscrl; if (new_msg) {
len = pos; new_msg = false;
if (len > 30)
len = 30;
char dispmsg[len + 1];
if (pos >= 0) {
LOOP_L_N(i, len) dispmsg[i] = statusmsg[i + msgscrl];
}
else {
LOOP_L_N(i, 30 + pos) dispmsg[i] = ' ';
LOOP_S_L_N(i, 30 + pos, 30) dispmsg[i] = statusmsg[i - (30 + pos)];
}
dispmsg[len] = '\0';
if (process == Print) { if (process == Print) {
DWIN_Draw_Rectangle(1, Color_Grey, 8, 214, DWIN_WIDTH - 8, 238); DWIN_Draw_Rectangle(1, Color_Grey, 8, 214, DWIN_WIDTH - 8, 238);
const int8_t npos = (DWIN_WIDTH - 30 * MENU_CHR_W) / 2; const int8_t npos = (DWIN_WIDTH - len * MENU_CHR_W) / 2;
DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.status_bar_text, Color_White), Color_Bg_Black, npos, 219, dispmsg); DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.status_bar_text, Color_White), Color_Bg_Black, npos, 219, dispmsg);
} }
else { else {
DWIN_Draw_Rectangle(1, Color_Bg_Black, 8, 352, DWIN_WIDTH - 8, 376); DWIN_Draw_Rectangle(1, Color_Bg_Black, 8, 352, DWIN_WIDTH - 8, 376);
const int8_t npos = (DWIN_WIDTH - 30 * MENU_CHR_W) / 2; const int8_t npos = (DWIN_WIDTH - len * MENU_CHR_W) / 2;
DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.status_bar_text, Color_White), Color_Bg_Black, npos, 357, dispmsg); DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.status_bar_text, Color_White), Color_Bg_Black, npos, 357, dispmsg);
} }
if (-pos >= 30) msgscrl = 0;
msgscrl++;
}
else {
if (new_msg) {
new_msg = false;
if (process == Print) {
DWIN_Draw_Rectangle(1, Color_Grey, 8, 214, DWIN_WIDTH - 8, 238);
const int8_t npos = (DWIN_WIDTH - strlen(statusmsg) * MENU_CHR_W) / 2;
DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.status_bar_text, Color_White), Color_Bg_Black, npos, 219, statusmsg);
}
else {
DWIN_Draw_Rectangle(1, Color_Bg_Black, 8, 352, DWIN_WIDTH - 8, 376);
const int8_t npos = (DWIN_WIDTH - strlen(statusmsg) * MENU_CHR_W) / 2;
DWIN_Draw_String(false, DWIN_FONT_MENU, GetColor(eeprom_settings.status_bar_text, Color_White), Color_Bg_Black, npos, 357, statusmsg);
}
}
} }
} }
@ -4168,35 +4172,25 @@ void CrealityDWINClass::Option_Control() {
} }
void CrealityDWINClass::File_Control() { void CrealityDWINClass::File_Control() {
typedef TextScroller<MENU_CHAR_LIMIT> Scroller;
static Scroller scroller;
EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); EncoderState encoder_diffState = Encoder_ReceiveAnalyze();
static uint8_t filescrl = 0;
if (encoder_diffState == ENCODER_DIFF_NO) { if (encoder_diffState == ENCODER_DIFF_NO) {
if (selection > 0) { if (selection > 0) {
card.getfilename_sorted(SD_ORDER(selection - 1, card.get_num_Files())); card.getfilename_sorted(SD_ORDER(selection - 1, card.get_num_Files()));
char * const filename = card.longest_filename(); char * const filename = card.longest_filename();
size_t len = strlen(filename); size_t len = strlen(filename);
int8_t pos = len; size_t pos = len;
if (!card.flag.filenameIsDir) if (!card.flag.filenameIsDir)
while (pos && filename[pos] != '.') pos--; while (pos && filename[pos] != '.') pos--;
if (pos > MENU_CHAR_LIMIT) { if (pos > MENU_CHAR_LIMIT) {
static millis_t time = 0; static millis_t time = 0;
if (PENDING(millis(), time)) return; if (PENDING(millis(), time)) return;
time = millis() + 200; time = millis() + 200;
pos -= filescrl; Scroller::Buffer buf;
len = _MIN(pos, MENU_CHAR_LIMIT); const char* const name = scroller.scroll(pos, buf, filename);
char name[len + 1];
if (pos >= 0) {
LOOP_L_N(i, len) name[i] = filename[i + filescrl];
}
else {
LOOP_L_N(i, MENU_CHAR_LIMIT + pos) name[i] = ' ';
LOOP_S_L_N(i, MENU_CHAR_LIMIT + pos, MENU_CHAR_LIMIT) name[i] = filename[i - (MENU_CHAR_LIMIT + pos)];
}
name[len] = '\0';
DWIN_Draw_Rectangle(1, Color_Bg_Black, LBLX, MBASE(selection - scrollpos) - 14, 271, MBASE(selection - scrollpos) + 28); DWIN_Draw_Rectangle(1, Color_Bg_Black, LBLX, MBASE(selection - scrollpos) - 14, 271, MBASE(selection - scrollpos) + 28);
Draw_Menu_Item(selection - scrollpos, card.flag.filenameIsDir ? ICON_More : ICON_File, name); Draw_Menu_Item(selection - scrollpos, card.flag.filenameIsDir ? ICON_More : ICON_File, name);
if (-pos >= MENU_CHAR_LIMIT) filescrl = 0;
filescrl++;
DWIN_UpdateLCD(); DWIN_UpdateLCD();
} }
} }
@ -4208,7 +4202,7 @@ void CrealityDWINClass::File_Control() {
DWIN_Draw_Rectangle(1, Color_Bg_Black, LBLX, MBASE(selection - scrollpos) - 14, 271, MBASE(selection - scrollpos) + 28); DWIN_Draw_Rectangle(1, Color_Bg_Black, LBLX, MBASE(selection - scrollpos) - 14, 271, MBASE(selection - scrollpos) + 28);
Draw_SD_Item(selection, selection - scrollpos); Draw_SD_Item(selection, selection - scrollpos);
} }
filescrl = 0; scroller.reset();
selection++; // Select Down selection++; // Select Down
if (selection > scrollpos + MROWS) { if (selection > scrollpos + MROWS) {
scrollpos++; scrollpos++;
@ -4221,7 +4215,7 @@ void CrealityDWINClass::File_Control() {
DWIN_Draw_Rectangle(1, Color_Bg_Black, 0, MBASE(selection - scrollpos) - 18, 14, MBASE(selection - scrollpos) + 33); DWIN_Draw_Rectangle(1, Color_Bg_Black, 0, MBASE(selection - scrollpos) - 18, 14, MBASE(selection - scrollpos) + 33);
DWIN_Draw_Rectangle(1, Color_Bg_Black, LBLX, MBASE(selection - scrollpos) - 14, 271, MBASE(selection - scrollpos) + 28); DWIN_Draw_Rectangle(1, Color_Bg_Black, LBLX, MBASE(selection - scrollpos) - 14, 271, MBASE(selection - scrollpos) + 28);
Draw_SD_Item(selection, selection - scrollpos); Draw_SD_Item(selection, selection - scrollpos);
filescrl = 0; scroller.reset();
selection--; // Select Up selection--; // Select Up
if (selection < scrollpos) { if (selection < scrollpos) {
scrollpos--; scrollpos--;

1
Marlin/src/lcd/extui/dgus/DGUSDisplay.h

@ -39,7 +39,6 @@
enum DGUSLCD_Screens : uint8_t; enum DGUSLCD_Screens : uint8_t;
//#define DEBUG_DGUSLCD
#define DEBUG_OUT ENABLED(DEBUG_DGUSLCD) #define DEBUG_OUT ENABLED(DEBUG_DGUSLCD)
#include "../../../core/debug_out.h" #include "../../../core/debug_out.h"

47
Marlin/src/lcd/extui/dgus/DGUSScreenHandler.cpp

@ -152,10 +152,10 @@ void DGUSScreenHandler::DGUSLCD_SendPrintTimeToDisplay(DGUS_VP_Variable &var) {
// Send an uint8_t between 0 and 100 to a variable scale to 0..255 // Send an uint8_t between 0 and 100 to a variable scale to 0..255
void DGUSScreenHandler::DGUSLCD_PercentageToUint8(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::DGUSLCD_PercentageToUint8(DGUS_VP_Variable &var, void *val_ptr) {
if (var.memadr) { if (var.memadr) {
uint16_t value = swap16(*(uint16_t*)val_ptr); const uint16_t value = BE16_P(val_ptr);
DEBUG_ECHOLNPGM("FAN value get:", value); DEBUG_ECHOLNPGM("Got percent:", value);
*(uint8_t*)var.memadr = map(constrain(value, 0, 100), 0, 100, 0, 255); *(uint8_t*)var.memadr = map(constrain(value, 0, 100), 0, 100, 0, 255);
DEBUG_ECHOLNPGM("FAN value change:", *(uint8_t*)var.memadr); DEBUG_ECHOLNPGM("Set uint8:", *(uint8_t*)var.memadr);
} }
} }
@ -264,10 +264,10 @@ void DGUSScreenHandler::DGUSLCD_SendHeaterStatusToDisplay(DGUS_VP_Variable &var)
static uint16_t period = 0; static uint16_t period = 0;
static uint16_t index = 0; static uint16_t index = 0;
//DEBUG_ECHOPGM(" DGUSLCD_SendWaitingStatusToDisplay ", var.VP); //DEBUG_ECHOPGM(" DGUSLCD_SendWaitingStatusToDisplay ", var.VP);
//DEBUG_ECHOLNPGM(" data ", swap16(index)); //DEBUG_ECHOLNPGM(" data ", BE16_P(&index));
if (period++ > DGUS_UI_WAITING_STATUS_PERIOD) { if (period++ > DGUS_UI_WAITING_STATUS_PERIOD) {
dgusdisplay.WriteVariable(var.VP, index); dgusdisplay.WriteVariable(var.VP, index);
//DEBUG_ECHOLNPGM(" data ", swap16(index)); //DEBUG_ECHOLNPGM(" data ", BE16_P(&index));
if (++index >= DGUS_UI_WAITING_STATUS) index = 0; if (++index >= DGUS_UI_WAITING_STATUS) index = 0;
period = 0; period = 0;
} }
@ -306,7 +306,7 @@ void DGUSScreenHandler::DGUSLCD_SendHeaterStatusToDisplay(DGUS_VP_Variable &var)
void DGUSScreenHandler::DGUSLCD_SD_ScrollFilelist(DGUS_VP_Variable& var, void *val_ptr) { void DGUSScreenHandler::DGUSLCD_SD_ScrollFilelist(DGUS_VP_Variable& var, void *val_ptr) {
auto old_top = top_file; auto old_top = top_file;
const int16_t scroll = (int16_t)swap16(*(uint16_t*)val_ptr); const int16_t scroll = (int16_t)BE16_P(val_ptr);
if (scroll) { if (scroll) {
top_file += scroll; top_file += scroll;
DEBUG_ECHOPGM("new topfile calculated:", top_file); DEBUG_ECHOPGM("new topfile calculated:", top_file);
@ -391,7 +391,7 @@ void DGUSScreenHandler::HandleAllHeatersOff(DGUS_VP_Variable &var, void *val_ptr
} }
void DGUSScreenHandler::HandleTemperatureChanged(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandleTemperatureChanged(DGUS_VP_Variable &var, void *val_ptr) {
celsius_t newvalue = swap16(*(uint16_t*)val_ptr); celsius_t newvalue = BE16_P(val_ptr);
celsius_t acceptedvalue; celsius_t acceptedvalue;
switch (var.VP) { switch (var.VP) {
@ -426,7 +426,7 @@ void DGUSScreenHandler::HandleTemperatureChanged(DGUS_VP_Variable &var, void *va
void DGUSScreenHandler::HandleFlowRateChanged(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandleFlowRateChanged(DGUS_VP_Variable &var, void *val_ptr) {
#if HAS_EXTRUDERS #if HAS_EXTRUDERS
uint16_t newvalue = swap16(*(uint16_t*)val_ptr); const uint16_t newvalue = BE16_P(val_ptr);
uint8_t target_extruder; uint8_t target_extruder;
switch (var.VP) { switch (var.VP) {
default: return; default: return;
@ -446,7 +446,7 @@ void DGUSScreenHandler::HandleFlowRateChanged(DGUS_VP_Variable &var, void *val_p
void DGUSScreenHandler::HandleManualExtrude(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandleManualExtrude(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleManualExtrude"); DEBUG_ECHOLNPGM("HandleManualExtrude");
int16_t movevalue = swap16(*(uint16_t*)val_ptr); const int16_t movevalue = BE16_P(val_ptr);
float target = movevalue * 0.01f; float target = movevalue * 0.01f;
ExtUI::extruder_t target_extruder; ExtUI::extruder_t target_extruder;
@ -468,19 +468,19 @@ void DGUSScreenHandler::HandleManualExtrude(DGUS_VP_Variable &var, void *val_ptr
#if ENABLED(DGUS_UI_MOVE_DIS_OPTION) #if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
void DGUSScreenHandler::HandleManualMoveOption(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandleManualMoveOption(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleManualMoveOption"); DEBUG_ECHOLNPGM("HandleManualMoveOption");
*(uint16_t*)var.memadr = swap16(*(uint16_t*)val_ptr); *(uint16_t*)var.memadr = BE16_P(val_ptr);
} }
#endif #endif
void DGUSScreenHandler::HandleMotorLockUnlock(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandleMotorLockUnlock(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleMotorLockUnlock"); DEBUG_ECHOLNPGM("HandleMotorLockUnlock");
const int16_t lock = swap16(*(uint16_t*)val_ptr); const int16_t lock = BE16_P(val_ptr);
queue.enqueue_one_now(lock ? F("M18") : F("M17")); queue.enqueue_one_now(lock ? F("M18") : F("M17"));
} }
void DGUSScreenHandler::HandleSettings(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandleSettings(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleSettings"); DEBUG_ECHOLNPGM("HandleSettings");
uint16_t value = swap16(*(uint16_t*)val_ptr); const uint16_t value = BE16_P(val_ptr);
switch (value) { switch (value) {
default: break; default: break;
case 1: case 1:
@ -494,11 +494,9 @@ void DGUSScreenHandler::HandleSettings(DGUS_VP_Variable &var, void *val_ptr) {
} }
void DGUSScreenHandler::HandleStepPerMMChanged(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandleStepPerMMChanged(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleStepPerMMChanged"); const uint16_t value_raw = BE16_P(val_ptr);
DEBUG_ECHOLNPGM("HandleStepPerMMChanged:", value_raw);
uint16_t value_raw = swap16(*(uint16_t*)val_ptr); const float value = (float)value_raw / 10;
DEBUG_ECHOLNPGM("value_raw:", value_raw);
float value = (float)value_raw / 10;
ExtUI::axis_t axis; ExtUI::axis_t axis;
switch (var.VP) { switch (var.VP) {
case VP_X_STEP_PER_MM: axis = ExtUI::axis_t::X; break; case VP_X_STEP_PER_MM: axis = ExtUI::axis_t::X; break;
@ -510,15 +508,12 @@ void DGUSScreenHandler::HandleStepPerMMChanged(DGUS_VP_Variable &var, void *val_
ExtUI::setAxisSteps_per_mm(value, axis); ExtUI::setAxisSteps_per_mm(value, axis);
DEBUG_ECHOLNPGM("value_set:", ExtUI::getAxisSteps_per_mm(axis)); DEBUG_ECHOLNPGM("value_set:", ExtUI::getAxisSteps_per_mm(axis));
skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
return;
} }
void DGUSScreenHandler::HandleStepPerMMExtruderChanged(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandleStepPerMMExtruderChanged(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleStepPerMMExtruderChanged"); const uint16_t value_raw = BE16_P(val_ptr);
DEBUG_ECHOLNPGM("HandleStepPerMMExtruderChanged:", value_raw);
uint16_t value_raw = swap16(*(uint16_t*)val_ptr); const float value = (float)value_raw / 10;
DEBUG_ECHOLNPGM("value_raw:", value_raw);
float value = (float)value_raw / 10;
ExtUI::extruder_t extruder; ExtUI::extruder_t extruder;
switch (var.VP) { switch (var.VP) {
default: return; default: return;
@ -575,7 +570,7 @@ void DGUSScreenHandler::HandleStepPerMMExtruderChanged(DGUS_VP_Variable &var, vo
void DGUSScreenHandler::HandleProbeOffsetZChanged(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandleProbeOffsetZChanged(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleProbeOffsetZChanged"); DEBUG_ECHOLNPGM("HandleProbeOffsetZChanged");
const float offset = float(int16_t(swap16(*(uint16_t*)val_ptr))) / 100.0f; const float offset = float(int16_t(BE16_P(val_ptr))) / 100.0f;
ExtUI::setZOffset_mm(offset); ExtUI::setZOffset_mm(offset);
skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
return; return;
@ -621,7 +616,7 @@ void DGUSScreenHandler::HandleHeaterControl(DGUS_VP_Variable &var, void *val_ptr
void DGUSScreenHandler::HandlePreheat(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandlePreheat(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandlePreheat"); DEBUG_ECHOLNPGM("HandlePreheat");
const uint16_t preheat_option = swap16(*(uint16_t*)val_ptr); const uint16_t preheat_option = BE16_P(val_ptr);
switch (preheat_option) { switch (preheat_option) {
default: default:
switch (var.VP) { switch (var.VP) {
@ -644,7 +639,7 @@ void DGUSScreenHandler::HandleHeaterControl(DGUS_VP_Variable &var, void *val_ptr
#if ENABLED(POWER_LOSS_RECOVERY) #if ENABLED(POWER_LOSS_RECOVERY)
void DGUSScreenHandler::HandlePowerLossRecovery(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandlePowerLossRecovery(DGUS_VP_Variable &var, void *val_ptr) {
uint16_t value = swap16(*(uint16_t*)val_ptr); uint16_t value = BE16_P(val_ptr);
if (value) { if (value) {
queue.inject(F("M1000")); queue.inject(F("M1000"));
dgusdisplay.WriteVariable(VP_SD_Print_Filename, filelist.filename(), 32, true); dgusdisplay.WriteVariable(VP_SD_Print_Filename, filelist.filename(), 32, true);

4
Marlin/src/lcd/extui/dgus/DGUSScreenHandler.h

@ -42,6 +42,10 @@
#endif #endif
// endianness swap
#define BE16_P(V) ( ((uint8_t*)(V))[0] << 8U | ((uint8_t*)(V))[1] )
#define BE32_P(V) ( ((uint8_t*)(V))[0] << 24U | ((uint8_t*)(V))[1] << 16U | ((uint8_t*)(V))[2] << 8U | ((uint8_t*)(V))[3] )
#if ENABLED(DGUS_LCD_UI_ORIGIN) #if ENABLED(DGUS_LCD_UI_ORIGIN)
#include "origin/DGUSScreenHandler.h" #include "origin/DGUSScreenHandler.h"
#elif ENABLED(DGUS_LCD_UI_MKS) #elif ENABLED(DGUS_LCD_UI_MKS)

121
Marlin/src/lcd/extui/dgus/mks/DGUSScreenHandler.cpp

@ -54,9 +54,6 @@
bool DGUSAutoTurnOff = false; bool DGUSAutoTurnOff = false;
MKS_Language mks_language_index; // Initialized by settings.load() MKS_Language mks_language_index; // Initialized by settings.load()
// endianness swap
uint32_t swap32(const uint32_t value) { return (value & 0x000000FFU) << 24U | (value & 0x0000FF00U) << 8U | (value & 0x00FF0000U) >> 8U | (value & 0xFF000000U) >> 24U; }
#if 0 #if 0
void DGUSScreenHandlerMKS::sendinfoscreen_ch(const uint16_t *line1, const uint16_t *line2, const uint16_t *line3, const uint16_t *line4) { void DGUSScreenHandlerMKS::sendinfoscreen_ch(const uint16_t *line1, const uint16_t *line2, const uint16_t *line3, const uint16_t *line4) {
dgusdisplay.WriteVariable(VP_MSGSTR1, line1, 32, true); dgusdisplay.WriteVariable(VP_MSGSTR1, line1, 32, true);
@ -108,10 +105,10 @@ void DGUSScreenHandlerMKS::DGUSLCD_SendPrintTimeToDisplay(DGUS_VP_Variable &var)
void DGUSScreenHandlerMKS::DGUSLCD_SetUint8(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::DGUSLCD_SetUint8(DGUS_VP_Variable &var, void *val_ptr) {
if (var.memadr) { if (var.memadr) {
const uint16_t value = swap16(*(uint16_t*)val_ptr); const uint16_t value = BE16_P(val_ptr);
DEBUG_ECHOLNPGM("FAN value get:", value); DEBUG_ECHOLNPGM("Got uint8:", value);
*(uint8_t*)var.memadr = map(constrain(value, 0, 255), 0, 255, 0, 255); *(uint8_t*)var.memadr = map(constrain(value, 0, 255), 0, 255, 0, 255);
DEBUG_ECHOLNPGM("FAN value change:", *(uint8_t*)var.memadr); DEBUG_ECHOLNPGM("Set uint8:", *(uint8_t*)var.memadr);
} }
} }
@ -152,7 +149,7 @@ void DGUSScreenHandlerMKS::DGUSLCD_SendTMCStepValue(DGUS_VP_Variable &var) {
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
void DGUSScreenHandler::DGUSLCD_SD_FileSelected(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::DGUSLCD_SD_FileSelected(DGUS_VP_Variable &var, void *val_ptr) {
uint16_t touched_nr = (int16_t)swap16(*(uint16_t*)val_ptr) + top_file; uint16_t touched_nr = (int16_t)BE16_P(val_ptr) + top_file;
if (touched_nr != 0x0F && touched_nr > filelist.count()) return; if (touched_nr != 0x0F && touched_nr > filelist.count()) return;
if (!filelist.seek(touched_nr) && touched_nr != 0x0F) return; if (!filelist.seek(touched_nr) && touched_nr != 0x0F) return;
@ -191,7 +188,7 @@ void DGUSScreenHandlerMKS::DGUSLCD_SendTMCStepValue(DGUS_VP_Variable &var) {
void DGUSScreenHandler::DGUSLCD_SD_ResumePauseAbort(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::DGUSLCD_SD_ResumePauseAbort(DGUS_VP_Variable &var, void *val_ptr) {
if (!ExtUI::isPrintingFromMedia()) return; // avoid race condition when user stays in this menu and printer finishes. if (!ExtUI::isPrintingFromMedia()) return; // avoid race condition when user stays in this menu and printer finishes.
switch (swap16(*(uint16_t*)val_ptr)) { switch (BE16_P(val_ptr)) {
case 0: { // Resume case 0: { // Resume
auto cs = getCurrentScreen(); auto cs = getCurrentScreen();
if (runout_mks.runout_status != RUNOUT_WAITING_STATUS && runout_mks.runout_status != UNRUNOUT_STATUS) { if (runout_mks.runout_status != RUNOUT_WAITING_STATUS && runout_mks.runout_status != UNRUNOUT_STATUS) {
@ -268,7 +265,7 @@ void DGUSScreenHandlerMKS::DGUSLCD_SendTMCStepValue(DGUS_VP_Variable &var) {
#else #else
void DGUSScreenHandlerMKS::PrintReturn(DGUS_VP_Variable& var, void *val_ptr) { void DGUSScreenHandlerMKS::PrintReturn(DGUS_VP_Variable& var, void *val_ptr) {
uint16_t value = swap16(*(uint16_t*)val_ptr); const uint16_t value = BE16_P(val_ptr);
if (value == 0x0F) GotoScreen(DGUSLCD_SCREEN_MAIN); if (value == 0x0F) GotoScreen(DGUSLCD_SCREEN_MAIN);
} }
#endif // SDSUPPORT #endif // SDSUPPORT
@ -315,7 +312,7 @@ void DGUSScreenHandler::ScreenChangeHook(DGUS_VP_Variable &var, void *val_ptr) {
} }
void DGUSScreenHandlerMKS::ScreenBackChange(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::ScreenBackChange(DGUS_VP_Variable &var, void *val_ptr) {
const uint16_t target = swap16(*(uint16_t *)val_ptr); const uint16_t target = BE16_P(val_ptr);
DEBUG_ECHOLNPGM(" back = 0x%x", target); DEBUG_ECHOLNPGM(" back = 0x%x", target);
switch (target) { switch (target) {
} }
@ -331,7 +328,7 @@ void DGUSScreenHandlerMKS::ZoffsetConfirm(DGUS_VP_Variable &var, void *val_ptr)
void DGUSScreenHandlerMKS::GetTurnOffCtrl(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::GetTurnOffCtrl(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("GetTurnOffCtrl\n"); DEBUG_ECHOLNPGM("GetTurnOffCtrl\n");
const uint16_t value = swap16(*(uint16_t *)val_ptr); const uint16_t value = BE16_P(val_ptr);
switch (value) { switch (value) {
case 0 ... 1: DGUSAutoTurnOff = (bool)value; break; case 0 ... 1: DGUSAutoTurnOff = (bool)value; break;
default: break; default: break;
@ -340,7 +337,7 @@ void DGUSScreenHandlerMKS::GetTurnOffCtrl(DGUS_VP_Variable &var, void *val_ptr)
void DGUSScreenHandlerMKS::GetMinExtrudeTemp(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::GetMinExtrudeTemp(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("GetMinExtrudeTemp"); DEBUG_ECHOLNPGM("GetMinExtrudeTemp");
const uint16_t value = swap16(*(uint16_t *)val_ptr); const uint16_t value = BE16_P(val_ptr);
TERN_(PREVENT_COLD_EXTRUSION, thermalManager.extrude_min_temp = value); TERN_(PREVENT_COLD_EXTRUSION, thermalManager.extrude_min_temp = value);
mks_min_extrusion_temp = value; mks_min_extrusion_temp = value;
settings.save(); settings.save();
@ -348,7 +345,7 @@ void DGUSScreenHandlerMKS::GetMinExtrudeTemp(DGUS_VP_Variable &var, void *val_pt
void DGUSScreenHandlerMKS::GetZoffsetDistance(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::GetZoffsetDistance(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("GetZoffsetDistance"); DEBUG_ECHOLNPGM("GetZoffsetDistance");
const uint16_t value = swap16(*(uint16_t *)val_ptr); const uint16_t value = BE16_P(val_ptr);
float val_distance = 0; float val_distance = 0;
switch (value) { switch (value) {
case 0: val_distance = 0.01; break; case 0: val_distance = 0.01; break;
@ -362,11 +359,11 @@ void DGUSScreenHandlerMKS::GetZoffsetDistance(DGUS_VP_Variable &var, void *val_p
void DGUSScreenHandlerMKS::GetManualMovestep(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::GetManualMovestep(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("\nGetManualMovestep"); DEBUG_ECHOLNPGM("\nGetManualMovestep");
*(uint16_t *)var.memadr = swap16(*(uint16_t *)val_ptr); *(uint16_t *)var.memadr = BE16_P(val_ptr);
} }
void DGUSScreenHandlerMKS::EEPROM_CTRL(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::EEPROM_CTRL(DGUS_VP_Variable &var, void *val_ptr) {
const uint16_t eep_flag = swap16(*(uint16_t *)val_ptr); const uint16_t eep_flag = BE16_P(val_ptr);
switch (eep_flag) { switch (eep_flag) {
case 0: case 0:
settings.save(); settings.save();
@ -384,7 +381,7 @@ void DGUSScreenHandlerMKS::EEPROM_CTRL(DGUS_VP_Variable &var, void *val_ptr) {
} }
void DGUSScreenHandlerMKS::Z_offset_select(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::Z_offset_select(DGUS_VP_Variable &var, void *val_ptr) {
const uint16_t z_value = swap16(*(uint16_t *)val_ptr); const uint16_t z_value = BE16_P(val_ptr);
switch (z_value) { switch (z_value) {
case 0: Z_distance = 0.01; break; case 0: Z_distance = 0.01; break;
case 1: Z_distance = 0.1; break; case 1: Z_distance = 0.1; break;
@ -396,22 +393,22 @@ void DGUSScreenHandlerMKS::Z_offset_select(DGUS_VP_Variable &var, void *val_ptr)
void DGUSScreenHandlerMKS::GetOffsetValue(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::GetOffsetValue(DGUS_VP_Variable &var, void *val_ptr) {
#if HAS_BED_PROBE #if HAS_BED_PROBE
int32_t value = swap32(*(int32_t *)val_ptr); const int32_t value = BE32_P(val_ptr);
float Offset = value / 100.0f; const float Offset = value / 100.0f;
DEBUG_ECHOLNPGM("\nget int6 offset >> ", value, 6); DEBUG_ECHOLNPGM("\nget int6 offset >> ", value, 6);
#endif
switch (var.VP) { switch (var.VP) {
case VP_OFFSET_X: TERN_(HAS_BED_PROBE, probe.offset.x = Offset); break; default: break;
case VP_OFFSET_Y: TERN_(HAS_BED_PROBE, probe.offset.y = Offset); break; case VP_OFFSET_X: probe.offset.x = Offset; break;
case VP_OFFSET_Z: TERN_(HAS_BED_PROBE, probe.offset.z = Offset); break; case VP_OFFSET_Y: probe.offset.y = Offset; break;
default: break; case VP_OFFSET_Z: probe.offset.z = Offset; break;
} }
settings.save(); settings.save();
#endif
} }
void DGUSScreenHandlerMKS::LanguageChange(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::LanguageChange(DGUS_VP_Variable &var, void *val_ptr) {
const uint16_t lag_flag = swap16(*(uint16_t *)val_ptr); const uint16_t lag_flag = BE16_P(val_ptr);
switch (lag_flag) { switch (lag_flag) {
case MKS_SimpleChinese: case MKS_SimpleChinese:
DGUS_LanguageDisplay(MKS_SimpleChinese); DGUS_LanguageDisplay(MKS_SimpleChinese);
@ -436,10 +433,10 @@ void DGUSScreenHandlerMKS::LanguageChange(DGUS_VP_Variable &var, void *val_ptr)
#endif #endif
void DGUSScreenHandlerMKS::Level_Ctrl(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::Level_Ctrl(DGUS_VP_Variable &var, void *val_ptr) {
const uint16_t lev_but = swap16(*(uint16_t *)val_ptr);
#if ENABLED(MESH_BED_LEVELING) #if ENABLED(MESH_BED_LEVELING)
auto cs = getCurrentScreen(); auto cs = getCurrentScreen();
#endif #endif
const uint16_t lev_but = BE16_P(val_ptr);
switch (lev_but) { switch (lev_but) {
case 0: case 0:
#if ENABLED(AUTO_BED_LEVELING_BILINEAR) #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
@ -483,7 +480,7 @@ void DGUSScreenHandlerMKS::Level_Ctrl(DGUS_VP_Variable &var, void *val_ptr) {
} }
void DGUSScreenHandlerMKS::MeshLevelDistanceConfig(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::MeshLevelDistanceConfig(DGUS_VP_Variable &var, void *val_ptr) {
const uint16_t mesh_dist = swap16(*(uint16_t *)val_ptr); const uint16_t mesh_dist = BE16_P(val_ptr);
switch (mesh_dist) { switch (mesh_dist) {
case 0: mesh_adj_distance = 0.01; break; case 0: mesh_adj_distance = 0.01; break;
case 1: mesh_adj_distance = 0.1; break; case 1: mesh_adj_distance = 0.1; break;
@ -494,7 +491,7 @@ void DGUSScreenHandlerMKS::MeshLevelDistanceConfig(DGUS_VP_Variable &var, void *
void DGUSScreenHandlerMKS::MeshLevel(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::MeshLevel(DGUS_VP_Variable &var, void *val_ptr) {
#if ENABLED(MESH_BED_LEVELING) #if ENABLED(MESH_BED_LEVELING)
const uint16_t mesh_value = swap16(*(uint16_t *)val_ptr); const uint16_t mesh_value = BE16_P(val_ptr);
// static uint8_t a_first_level = 1; // static uint8_t a_first_level = 1;
char cmd_buf[30]; char cmd_buf[30];
float offset = mesh_adj_distance; float offset = mesh_adj_distance;
@ -592,8 +589,8 @@ void DGUSScreenHandlerMKS::SD_FileBack(DGUS_VP_Variable&, void*) {
} }
void DGUSScreenHandlerMKS::LCD_BLK_Adjust(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::LCD_BLK_Adjust(DGUS_VP_Variable &var, void *val_ptr) {
const uint16_t lcd_value = swap16(*(uint16_t *)val_ptr);
const uint16_t lcd_value = BE16_P(val_ptr);
lcd_default_light = constrain(lcd_value, 10, 100); lcd_default_light = constrain(lcd_value, 10, 100);
const uint16_t lcd_data[2] = { lcd_default_light, lcd_default_light }; const uint16_t lcd_data[2] = { lcd_default_light, lcd_default_light };
@ -601,7 +598,7 @@ void DGUSScreenHandlerMKS::LCD_BLK_Adjust(DGUS_VP_Variable &var, void *val_ptr)
} }
void DGUSScreenHandlerMKS::ManualAssistLeveling(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::ManualAssistLeveling(DGUS_VP_Variable &var, void *val_ptr) {
const int16_t point_value = swap16(*(uint16_t *)val_ptr); const int16_t point_value = BE16_P(val_ptr);
// Insist on leveling first time at this screen // Insist on leveling first time at this screen
static bool first_level_flag = false; static bool first_level_flag = false;
@ -655,7 +652,7 @@ void DGUSScreenHandlerMKS::ManualAssistLeveling(DGUS_VP_Variable &var, void *val
#define mks_max(a, b) ((a) > (b)) ? (a) : (b) #define mks_max(a, b) ((a) > (b)) ? (a) : (b)
void DGUSScreenHandlerMKS::TMC_ChangeConfig(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::TMC_ChangeConfig(DGUS_VP_Variable &var, void *val_ptr) {
#if EITHER(HAS_TRINAMIC_CONFIG, HAS_STEALTHCHOP) #if EITHER(HAS_TRINAMIC_CONFIG, HAS_STEALTHCHOP)
const uint16_t tmc_value = swap16(*(uint16_t*)val_ptr); const uint16_t tmc_value = BE16_P(val_ptr);
#endif #endif
switch (var.VP) { switch (var.VP) {
@ -748,7 +745,7 @@ void DGUSScreenHandlerMKS::TMC_ChangeConfig(DGUS_VP_Variable &var, void *val_ptr
void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleManualMove"); DEBUG_ECHOLNPGM("HandleManualMove");
int16_t movevalue = swap16(*(uint16_t*)val_ptr); int16_t movevalue = BE16_P(val_ptr);
// Choose Move distance // Choose Move distance
if (manualMoveStep == 0x01) manualMoveStep = 10; if (manualMoveStep == 0x01) manualMoveStep = 10;
@ -893,7 +890,7 @@ void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
} }
void DGUSScreenHandlerMKS::GetParkPos(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::GetParkPos(DGUS_VP_Variable &var, void *val_ptr) {
const int16_t value_pos = swap16(*(int16_t*)val_ptr); const int16_t value_pos = BE16_P(val_ptr);
switch (var.VP) { switch (var.VP) {
case VP_X_PARK_POS: mks_park_pos.x = value_pos; break; case VP_X_PARK_POS: mks_park_pos.x = value_pos; break;
@ -907,7 +904,7 @@ void DGUSScreenHandlerMKS::GetParkPos(DGUS_VP_Variable &var, void *val_ptr) {
void DGUSScreenHandlerMKS::HandleChangeLevelPoint(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::HandleChangeLevelPoint(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleChangeLevelPoint"); DEBUG_ECHOLNPGM("HandleChangeLevelPoint");
const int16_t value_raw = swap16(*(int16_t*)val_ptr); const int16_t value_raw = BE16_P(val_ptr);
DEBUG_ECHOLNPGM("value_raw:", value_raw); DEBUG_ECHOLNPGM("value_raw:", value_raw);
*(int16_t*)var.memadr = value_raw; *(int16_t*)var.memadr = value_raw;
@ -919,7 +916,7 @@ void DGUSScreenHandlerMKS::HandleChangeLevelPoint(DGUS_VP_Variable &var, void *v
void DGUSScreenHandlerMKS::HandleStepPerMMChanged(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::HandleStepPerMMChanged(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleStepPerMMChanged"); DEBUG_ECHOLNPGM("HandleStepPerMMChanged");
const uint16_t value_raw = swap16(*(uint16_t*)val_ptr); const uint16_t value_raw = BE16_P(val_ptr);
const float value = (float)value_raw; const float value = (float)value_raw;
DEBUG_ECHOLNPGM("value_raw:", value_raw); DEBUG_ECHOLNPGM("value_raw:", value_raw);
@ -941,7 +938,7 @@ void DGUSScreenHandlerMKS::HandleStepPerMMChanged(DGUS_VP_Variable &var, void *v
void DGUSScreenHandlerMKS::HandleStepPerMMExtruderChanged(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::HandleStepPerMMExtruderChanged(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleStepPerMMExtruderChanged"); DEBUG_ECHOLNPGM("HandleStepPerMMExtruderChanged");
const uint16_t value_raw = swap16(*(uint16_t*)val_ptr); const uint16_t value_raw = BE16_P(val_ptr);
const float value = (float)value_raw; const float value = (float)value_raw;
DEBUG_ECHOLNPGM("value_raw:", value_raw); DEBUG_ECHOLNPGM("value_raw:", value_raw);
@ -966,7 +963,7 @@ void DGUSScreenHandlerMKS::HandleStepPerMMExtruderChanged(DGUS_VP_Variable &var,
void DGUSScreenHandlerMKS::HandleMaxSpeedChange(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::HandleMaxSpeedChange(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleMaxSpeedChange"); DEBUG_ECHOLNPGM("HandleMaxSpeedChange");
const uint16_t value_raw = swap16(*(uint16_t*)val_ptr); const uint16_t value_raw = BE16_P(val_ptr);
const float value = (float)value_raw; const float value = (float)value_raw;
DEBUG_ECHOLNPGM("value_raw:", value_raw); DEBUG_ECHOLNPGM("value_raw:", value_raw);
@ -988,7 +985,7 @@ void DGUSScreenHandlerMKS::HandleMaxSpeedChange(DGUS_VP_Variable &var, void *val
void DGUSScreenHandlerMKS::HandleExtruderMaxSpeedChange(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::HandleExtruderMaxSpeedChange(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleExtruderMaxSpeedChange"); DEBUG_ECHOLNPGM("HandleExtruderMaxSpeedChange");
const uint16_t value_raw = swap16(*(uint16_t*)val_ptr); const uint16_t value_raw = BE16_P(val_ptr);
const float value = (float)value_raw; const float value = (float)value_raw;
DEBUG_ECHOLNPGM("value_raw:", value_raw); DEBUG_ECHOLNPGM("value_raw:", value_raw);
@ -1013,7 +1010,7 @@ void DGUSScreenHandlerMKS::HandleExtruderMaxSpeedChange(DGUS_VP_Variable &var, v
void DGUSScreenHandlerMKS::HandleMaxAccChange(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::HandleMaxAccChange(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleMaxAccChange"); DEBUG_ECHOLNPGM("HandleMaxAccChange");
const uint16_t value_raw = swap16(*(uint16_t*)val_ptr); const uint16_t value_raw = BE16_P(val_ptr);
const float value = (float)value_raw; const float value = (float)value_raw;
DEBUG_ECHOLNPGM("value_raw:", value_raw); DEBUG_ECHOLNPGM("value_raw:", value_raw);
@ -1035,7 +1032,7 @@ void DGUSScreenHandlerMKS::HandleMaxAccChange(DGUS_VP_Variable &var, void *val_p
void DGUSScreenHandlerMKS::HandleExtruderAccChange(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::HandleExtruderAccChange(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleExtruderAccChange"); DEBUG_ECHOLNPGM("HandleExtruderAccChange");
uint16_t value_raw = swap16(*(uint16_t*)val_ptr); uint16_t value_raw = BE16_P(val_ptr);
DEBUG_ECHOLNPGM("value_raw:", value_raw); DEBUG_ECHOLNPGM("value_raw:", value_raw);
float value = (float)value_raw; float value = (float)value_raw;
ExtUI::extruder_t extruder; ExtUI::extruder_t extruder;
@ -1056,32 +1053,32 @@ void DGUSScreenHandlerMKS::HandleExtruderAccChange(DGUS_VP_Variable &var, void *
} }
void DGUSScreenHandlerMKS::HandleTravelAccChange(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::HandleTravelAccChange(DGUS_VP_Variable &var, void *val_ptr) {
uint16_t value_travel = swap16(*(uint16_t*)val_ptr); uint16_t value_travel = BE16_P(val_ptr);
planner.settings.travel_acceleration = (float)value_travel; planner.settings.travel_acceleration = (float)value_travel;
skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
} }
void DGUSScreenHandlerMKS::HandleFeedRateMinChange(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::HandleFeedRateMinChange(DGUS_VP_Variable &var, void *val_ptr) {
uint16_t value_t = swap16(*(uint16_t*)val_ptr); uint16_t value_t = BE16_P(val_ptr);
planner.settings.min_feedrate_mm_s = (float)value_t; planner.settings.min_feedrate_mm_s = (float)value_t;
skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
} }
void DGUSScreenHandlerMKS::HandleMin_T_F(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::HandleMin_T_F(DGUS_VP_Variable &var, void *val_ptr) {
uint16_t value_t_f = swap16(*(uint16_t*)val_ptr); uint16_t value_t_f = BE16_P(val_ptr);
planner.settings.min_travel_feedrate_mm_s = (float)value_t_f; planner.settings.min_travel_feedrate_mm_s = (float)value_t_f;
skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
} }
void DGUSScreenHandlerMKS::HandleAccChange(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::HandleAccChange(DGUS_VP_Variable &var, void *val_ptr) {
uint16_t value_acc = swap16(*(uint16_t*)val_ptr); uint16_t value_acc = BE16_P(val_ptr);
planner.settings.acceleration = (float)value_acc; planner.settings.acceleration = (float)value_acc;
skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
} }
#if ENABLED(PREVENT_COLD_EXTRUSION) #if ENABLED(PREVENT_COLD_EXTRUSION)
void DGUSScreenHandlerMKS::HandleGetExMinTemp(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::HandleGetExMinTemp(DGUS_VP_Variable &var, void *val_ptr) {
const uint16_t value_ex_min_temp = swap16(*(uint16_t*)val_ptr); const uint16_t value_ex_min_temp = BE16_P(val_ptr);
thermalManager.extrude_min_temp = value_ex_min_temp; thermalManager.extrude_min_temp = value_ex_min_temp;
skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
} }
@ -1089,7 +1086,7 @@ void DGUSScreenHandlerMKS::HandleAccChange(DGUS_VP_Variable &var, void *val_ptr)
#if HAS_PID_HEATING #if HAS_PID_HEATING
void DGUSScreenHandler::HandleTemperaturePIDChanged(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandleTemperaturePIDChanged(DGUS_VP_Variable &var, void *val_ptr) {
const uint16_t rawvalue = swap16(*(uint16_t*)val_ptr); const uint16_t rawvalue = BE16_P(val_ptr);
DEBUG_ECHOLNPGM("V1:", rawvalue); DEBUG_ECHOLNPGM("V1:", rawvalue);
const float value = 1.0f * rawvalue; const float value = 1.0f * rawvalue;
DEBUG_ECHOLNPGM("V2:", value); DEBUG_ECHOLNPGM("V2:", value);
@ -1125,9 +1122,9 @@ void DGUSScreenHandlerMKS::HandleAccChange(DGUS_VP_Variable &var, void *val_ptr)
#if ENABLED(BABYSTEPPING) #if ENABLED(BABYSTEPPING)
void DGUSScreenHandler::HandleLiveAdjustZ(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandler::HandleLiveAdjustZ(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleLiveAdjustZ"); DEBUG_ECHOLNPGM("HandleLiveAdjustZ");
float step = ZOffset_distance; const float step = ZOffset_distance;
uint16_t flag = swap16(*(uint16_t*)val_ptr); const uint16_t flag = BE16_P(val_ptr);
switch (flag) { switch (flag) {
case 0: case 0:
if (step == 0.01) if (step == 0.01)
@ -1159,34 +1156,26 @@ void DGUSScreenHandlerMKS::HandleAccChange(DGUS_VP_Variable &var, void *val_ptr)
z_offset_add += ZOffset_distance; z_offset_add += ZOffset_distance;
break; break;
default: default: break;
break;
} }
ForceCompleteUpdate(); ForceCompleteUpdate();
} }
#endif // BABYSTEPPING #endif // BABYSTEPPING
void DGUSScreenHandlerMKS::GetManualFilament(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::GetManualFilament(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("GetManualFilament"); const uint16_t value_len = BE16_P(val_ptr);
const float value = (float)value_len;
uint16_t value_len = swap16(*(uint16_t*)val_ptr);
float value = (float)value_len; DEBUG_ECHOLNPGM("GetManualFilament:", value);
DEBUG_ECHOLNPGM("Get Filament len value:", value);
distanceFilament = value; distanceFilament = value;
skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
} }
void DGUSScreenHandlerMKS::GetManualFilamentSpeed(DGUS_VP_Variable &var, void *val_ptr) { void DGUSScreenHandlerMKS::GetManualFilamentSpeed(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("GetManualFilamentSpeed"); const uint16_t value_len = BE16_P(val_ptr);
uint16_t value_len = swap16(*(uint16_t*)val_ptr);
DEBUG_ECHOLNPGM("filamentSpeed_mm_s value:", value_len);
filamentSpeed_mm_s = value_len; filamentSpeed_mm_s = value_len;
DEBUG_ECHOLNPGM("GetManualFilamentSpeed:", value_len);
skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
} }
@ -1205,7 +1194,7 @@ void DGUSScreenHandlerMKS::FilamentLoadUnload(DGUS_VP_Variable &var, void *val_p
if (!print_job_timer.isPaused() && !queue.ring_buffer.empty()) if (!print_job_timer.isPaused() && !queue.ring_buffer.empty())
return; return;
const uint16_t val_t = swap16(*(uint16_t*)val_ptr); const uint16_t val_t = BE16_P(val_ptr);
switch (val_t) { switch (val_t) {
default: break; default: break;
case 0: case 0:
@ -1291,7 +1280,7 @@ void DGUSScreenHandlerMKS::FilamentUnLoad(DGUS_VP_Variable &var, void *val_ptr)
uint8_t e_temp = 0; uint8_t e_temp = 0;
filament_data.heated = false; filament_data.heated = false;
uint16_t preheat_option = swap16(*(uint16_t*)val_ptr); uint16_t preheat_option = BE16_P(val_ptr);
if (preheat_option >= 10) { // Unload filament type if (preheat_option >= 10) { // Unload filament type
preheat_option -= 10; preheat_option -= 10;
filament_data.action = 2; filament_data.action = 2;

11
Marlin/src/lcd/extui/dgus_reloaded/DGUSDisplay.h

@ -21,7 +21,10 @@
*/ */
#pragma once #pragma once
/* DGUS implementation written by coldtobi in 2019 for Marlin */ /**
* DGUS implementation written by coldtobi in 2019.
* Updated for STM32G0B1RE by Protomosh in 2022.
*/
#include "config/DGUS_Screen.h" #include "config/DGUS_Screen.h"
#include "config/DGUS_Control.h" #include "config/DGUS_Control.h"
@ -30,11 +33,13 @@
#include "../../../inc/MarlinConfigPre.h" #include "../../../inc/MarlinConfigPre.h"
#include "../../../MarlinCore.h" #include "../../../MarlinCore.h"
#define DEBUG_DGUSLCD // Uncomment for debug messages
#define DEBUG_OUT ENABLED(DEBUG_DGUSLCD) #define DEBUG_OUT ENABLED(DEBUG_DGUSLCD)
#include "../../../core/debug_out.h" #include "../../../core/debug_out.h"
#define Swap16(val) ((uint16_t)(((uint16_t)(val) >> 8) |\ // New endianness swap for 32bit mcu (tested with STM32G0B1RE)
((uint16_t)(val) << 8))) #define BE16_P(V) ( ((uint8_t*)(V))[0] << 8U | ((uint8_t*)(V))[1] )
#define BE32_P(V) ( ((uint8_t*)(V))[0] << 24U | ((uint8_t*)(V))[1] << 16U | ((uint8_t*)(V))[2] << 8U | ((uint8_t*)(V))[3] )
// Low-Level access to the display. // Low-Level access to the display.
class DGUSDisplay { class DGUSDisplay {

22
Marlin/src/lcd/extui/dgus_reloaded/DGUSRxHandler.cpp

@ -215,7 +215,7 @@ void DGUSRxHandler::PrintResume(DGUS_VP &vp, void *data_ptr) {
void DGUSRxHandler::Feedrate(DGUS_VP &vp, void *data_ptr) { void DGUSRxHandler::Feedrate(DGUS_VP &vp, void *data_ptr) {
UNUSED(vp); UNUSED(vp);
const int16_t feedrate = Swap16(*(int16_t*)data_ptr); const int16_t feedrate = BE16_P(data_ptr);
ExtUI::setFeedrate_percent(feedrate); ExtUI::setFeedrate_percent(feedrate);
@ -223,7 +223,7 @@ void DGUSRxHandler::Feedrate(DGUS_VP &vp, void *data_ptr) {
} }
void DGUSRxHandler::Flowrate(DGUS_VP &vp, void *data_ptr) { void DGUSRxHandler::Flowrate(DGUS_VP &vp, void *data_ptr) {
const int16_t flowrate = Swap16(*(int16_t*)data_ptr); const int16_t flowrate = BE16_P(data_ptr);
switch (vp.addr) { switch (vp.addr) {
default: return; default: return;
@ -246,7 +246,7 @@ void DGUSRxHandler::Flowrate(DGUS_VP &vp, void *data_ptr) {
void DGUSRxHandler::BabystepSet(DGUS_VP &vp, void *data_ptr) { void DGUSRxHandler::BabystepSet(DGUS_VP &vp, void *data_ptr) {
UNUSED(vp); UNUSED(vp);
const int16_t data = Swap16(*(int16_t*)data_ptr); const int16_t data = BE16_P(data_ptr);
const float offset = dgus_display.FromFixedPoint<int16_t, float, 2>(data); const float offset = dgus_display.FromFixedPoint<int16_t, float, 2>(data);
const int16_t steps = ExtUI::mmToWholeSteps(offset - ExtUI::getZOffset_mm(), ExtUI::Z); const int16_t steps = ExtUI::mmToWholeSteps(offset - ExtUI::getZOffset_mm(), ExtUI::Z);
@ -315,7 +315,7 @@ void DGUSRxHandler::TempPreset(DGUS_VP &vp, void *data_ptr) {
} }
void DGUSRxHandler::TempTarget(DGUS_VP &vp, void *data_ptr) { void DGUSRxHandler::TempTarget(DGUS_VP &vp, void *data_ptr) {
const int16_t temp = Swap16(*(int16_t*)data_ptr); const int16_t temp = BE16_P(data_ptr);
switch (vp.addr) { switch (vp.addr) {
default: return; default: return;
@ -338,7 +338,7 @@ void DGUSRxHandler::TempTarget(DGUS_VP &vp, void *data_ptr) {
void DGUSRxHandler::TempCool(DGUS_VP &vp, void *data_ptr) { void DGUSRxHandler::TempCool(DGUS_VP &vp, void *data_ptr) {
UNUSED(vp); UNUSED(vp);
const DGUS_Data::Heater heater = (DGUS_Data::Heater)Swap16(*(uint16_t*)data_ptr); const DGUS_Data::Heater heater = (DGUS_Data::Heater)BE16_P(data_ptr);
switch (heater) { switch (heater) {
default: return; default: return;
@ -397,7 +397,7 @@ void DGUSRxHandler::ZOffset(DGUS_VP &vp, void *data_ptr) {
return; return;
} }
const int16_t data = Swap16(*(int16_t*)data_ptr); const int16_t data = BE16_P(data_ptr);
const float offset = dgus_display.FromFixedPoint<int16_t, float, 2>(data); const float offset = dgus_display.FromFixedPoint<int16_t, float, 2>(data);
const int16_t steps = ExtUI::mmToWholeSteps(offset - ExtUI::getZOffset_mm(), ExtUI::Z); const int16_t steps = ExtUI::mmToWholeSteps(offset - ExtUI::getZOffset_mm(), ExtUI::Z);
@ -546,7 +546,7 @@ void DGUSRxHandler::DisableABL(DGUS_VP &vp, void *data_ptr) {
void DGUSRxHandler::FilamentSelect(DGUS_VP &vp, void *data_ptr) { void DGUSRxHandler::FilamentSelect(DGUS_VP &vp, void *data_ptr) {
UNUSED(vp); UNUSED(vp);
const DGUS_Data::Extruder extruder = (DGUS_Data::Extruder)Swap16(*(uint16_t*)data_ptr); const DGUS_Data::Extruder extruder = (DGUS_Data::Extruder)BE16_P(data_ptr);
switch (extruder) { switch (extruder) {
default: return; default: return;
@ -563,7 +563,7 @@ void DGUSRxHandler::FilamentSelect(DGUS_VP &vp, void *data_ptr) {
void DGUSRxHandler::FilamentLength(DGUS_VP &vp, void *data_ptr) { void DGUSRxHandler::FilamentLength(DGUS_VP &vp, void *data_ptr) {
UNUSED(vp); UNUSED(vp);
const uint16_t length = Swap16(*(uint16_t*)data_ptr); const uint16_t length = BE16_P(data_ptr);
dgus_screen_handler.filament_length = constrain(length, 0, EXTRUDE_MAXLENGTH); dgus_screen_handler.filament_length = constrain(length, 0, EXTRUDE_MAXLENGTH);
@ -644,7 +644,7 @@ void DGUSRxHandler::Home(DGUS_VP &vp, void *data_ptr) {
} }
void DGUSRxHandler::Move(DGUS_VP &vp, void *data_ptr) { void DGUSRxHandler::Move(DGUS_VP &vp, void *data_ptr) {
const int16_t data = Swap16(*(int16_t*)data_ptr); const int16_t data = BE16_P(data_ptr);
const float position = dgus_display.FromFixedPoint<int16_t, float, 1>(data); const float position = dgus_display.FromFixedPoint<int16_t, float, 1>(data);
ExtUI::axis_t axis; ExtUI::axis_t axis;
@ -816,7 +816,7 @@ void DGUSRxHandler::SettingsExtra(DGUS_VP &vp, void *data_ptr) {
void DGUSRxHandler::PIDSelect(DGUS_VP &vp, void *data_ptr) { void DGUSRxHandler::PIDSelect(DGUS_VP &vp, void *data_ptr) {
UNUSED(vp); UNUSED(vp);
const DGUS_Data::Heater heater = (DGUS_Data::Heater)Swap16(*(uint16_t*)data_ptr); const DGUS_Data::Heater heater = (DGUS_Data::Heater)BE16_P(data_ptr);
switch (heater) { switch (heater) {
default: return; default: return;
@ -846,7 +846,7 @@ void DGUSRxHandler::PIDSetTemp(DGUS_VP &vp, void *data_ptr) {
return; return;
} }
uint16_t temp = Swap16(*(uint16_t*)data_ptr); uint16_t temp = BE16_P(data_ptr);
switch (dgus_screen_handler.pid_heater) { switch (dgus_screen_handler.pid_heater) {
default: return; default: return;

2
Marlin/src/lcd/extui/dgus_reloaded/DGUSRxHandler.h

@ -107,7 +107,7 @@ namespace DGUSRxHandler {
break; break;
} }
case 2: { case 2: {
const uint16_t data = Swap16(*(uint16_t*)data_ptr); const uint16_t data = BE16_P(data_ptr);
*(T*)vp.extra = (T)data; *(T*)vp.extra = (T)data;
break; break;
} }

2
Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.h

@ -24,6 +24,8 @@
#include "DGUSDisplay.h" #include "DGUSDisplay.h"
#include "definition/DGUS_VP.h" #include "definition/DGUS_VP.h"
#define Swap16(val) ((uint16_t)(((uint16_t)(val) >> 8) | ((uint16_t)(val) << 8)))
namespace DGUSTxHandler { namespace DGUSTxHandler {
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)

2
Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/basic/resolutions.h

@ -97,7 +97,7 @@
#elif defined(TOUCH_UI_800x480) #elif defined(TOUCH_UI_800x480)
namespace FTDI { namespace FTDI {
#if defined(TOUCH_UI_800x480_GENERIC) #ifdef TOUCH_UI_800x480_GENERIC
constexpr uint8_t Pclk = 2; constexpr uint8_t Pclk = 2;
constexpr uint16_t Hsize = 800; constexpr uint16_t Hsize = 800;
constexpr uint16_t Vsize = 480; constexpr uint16_t Vsize = 480;

19
Marlin/src/lcd/extui/mks_ui/draw_about.cpp

@ -31,7 +31,7 @@
extern lv_group_t *g; extern lv_group_t *g;
static lv_obj_t *scr; static lv_obj_t *scr;
static lv_obj_t *fw_type, *board; static lv_obj_t *fw_type, *board, *website, *uuid, *protocol;
enum { ID_A_RETURN = 1 }; enum { ID_A_RETURN = 1 };
@ -48,11 +48,20 @@ void lv_draw_about() {
scr = lv_screen_create(ABOUT_UI); scr = lv_screen_create(ABOUT_UI);
lv_big_button_create(scr, "F:/bmp_return.bin", common_menu.text_back, BTN_X_PIXEL * 3 + INTERVAL_V * 4, BTN_Y_PIXEL + INTERVAL_H + titleHeight, event_handler, ID_A_RETURN); lv_big_button_create(scr, "F:/bmp_return.bin", common_menu.text_back, BTN_X_PIXEL * 3 + INTERVAL_V * 4, BTN_Y_PIXEL + INTERVAL_H + titleHeight, event_handler, ID_A_RETURN);
fw_type = lv_label_create(scr, "Firmware: Marlin " SHORT_BUILD_VERSION); board = lv_label_create(scr, BOARD_INFO_NAME);
lv_obj_align(fw_type, nullptr, LV_ALIGN_CENTER, 0, -20); lv_obj_align(board, nullptr, LV_ALIGN_CENTER, 0, -80);
board = lv_label_create(scr, "Board: " BOARD_INFO_NAME); fw_type = lv_label_create(scr, "Marlin " SHORT_BUILD_VERSION " (" STRING_DISTRIBUTION_DATE ")");
lv_obj_align(board, nullptr, LV_ALIGN_CENTER, 0, -60); lv_obj_align(fw_type, nullptr, LV_ALIGN_CENTER, 0, -50);
website = lv_label_create(scr, WEBSITE_URL);
lv_obj_align(website, nullptr, LV_ALIGN_CENTER, 0, -20);
uuid = lv_label_create(scr, "UUID: " DEFAULT_MACHINE_UUID);
lv_obj_align(uuid, nullptr, LV_ALIGN_CENTER, 0, 10);
protocol = lv_label_create(scr, "Protocol: " PROTOCOL_VERSION);
lv_obj_align(protocol, nullptr, LV_ALIGN_CENTER, 0, 40);
} }
void lv_clear_about() { void lv_clear_about() {

1
Marlin/src/lcd/language/language_de.h

@ -407,7 +407,6 @@ namespace Language_de {
LSTR MSG_ADVANCE_K_E = _UxGT("Vorschubfaktor *"); LSTR MSG_ADVANCE_K_E = _UxGT("Vorschubfaktor *");
LSTR MSG_CONTRAST = _UxGT("LCD-Kontrast"); LSTR MSG_CONTRAST = _UxGT("LCD-Kontrast");
LSTR MSG_BRIGHTNESS = _UxGT("LCD-Helligkeit"); LSTR MSG_BRIGHTNESS = _UxGT("LCD-Helligkeit");
LSTR MSG_LCD_TIMEOUT_SEC = _UxGT("LCD-Ruhezustand (s)");
LSTR MSG_SCREEN_TIMEOUT = _UxGT("LCD Timeout (m)"); LSTR MSG_SCREEN_TIMEOUT = _UxGT("LCD Timeout (m)");
LSTR MSG_BRIGHTNESS_OFF = _UxGT("LCD ausschalten"); LSTR MSG_BRIGHTNESS_OFF = _UxGT("LCD ausschalten");
LSTR MSG_STORE_EEPROM = _UxGT("Konfig. speichern"); LSTR MSG_STORE_EEPROM = _UxGT("Konfig. speichern");

1
Marlin/src/lcd/language/language_en.h

@ -422,7 +422,6 @@ namespace Language_en {
LSTR MSG_ADVANCE_K_E = _UxGT("Advance K *"); LSTR MSG_ADVANCE_K_E = _UxGT("Advance K *");
LSTR MSG_CONTRAST = _UxGT("LCD Contrast"); LSTR MSG_CONTRAST = _UxGT("LCD Contrast");
LSTR MSG_BRIGHTNESS = _UxGT("LCD Brightness"); LSTR MSG_BRIGHTNESS = _UxGT("LCD Brightness");
LSTR MSG_LCD_TIMEOUT_SEC = _UxGT("LCD Timeout (s)");
LSTR MSG_SCREEN_TIMEOUT = _UxGT("LCD Timeout (m)"); LSTR MSG_SCREEN_TIMEOUT = _UxGT("LCD Timeout (m)");
LSTR MSG_BRIGHTNESS_OFF = _UxGT("Backlight Off"); LSTR MSG_BRIGHTNESS_OFF = _UxGT("Backlight Off");
LSTR MSG_STORE_EEPROM = _UxGT("Store Settings"); LSTR MSG_STORE_EEPROM = _UxGT("Store Settings");

2
Marlin/src/lcd/language/language_fr.h

@ -321,7 +321,7 @@ namespace Language_fr {
LSTR MSG_ADVANCE_K_E = _UxGT("Avance K *"); LSTR MSG_ADVANCE_K_E = _UxGT("Avance K *");
LSTR MSG_BRIGHTNESS = _UxGT("Luminosité LCD"); LSTR MSG_BRIGHTNESS = _UxGT("Luminosité LCD");
LSTR MSG_CONTRAST = _UxGT("Contraste LCD"); LSTR MSG_CONTRAST = _UxGT("Contraste LCD");
LSTR MSG_LCD_TIMEOUT_SEC = _UxGT("Veille LCD (s)"); LSTR MSG_SCREEN_TIMEOUT = _UxGT("Veille LCD (m)");
LSTR MSG_BRIGHTNESS_OFF = _UxGT("Éteindre l'écran LCD"); LSTR MSG_BRIGHTNESS_OFF = _UxGT("Éteindre l'écran LCD");
LSTR MSG_STORE_EEPROM = _UxGT("Enregistrer config."); LSTR MSG_STORE_EEPROM = _UxGT("Enregistrer config.");
LSTR MSG_LOAD_EEPROM = _UxGT("Charger config."); LSTR MSG_LOAD_EEPROM = _UxGT("Charger config.");

1
Marlin/src/lcd/language/language_it.h

@ -418,7 +418,6 @@ namespace Language_it {
LSTR MSG_ADVANCE_K_E = _UxGT("K Avanzamento *"); LSTR MSG_ADVANCE_K_E = _UxGT("K Avanzamento *");
LSTR MSG_CONTRAST = _UxGT("Contrasto LCD"); LSTR MSG_CONTRAST = _UxGT("Contrasto LCD");
LSTR MSG_BRIGHTNESS = _UxGT("Luminosità LCD"); LSTR MSG_BRIGHTNESS = _UxGT("Luminosità LCD");
LSTR MSG_LCD_TIMEOUT_SEC = _UxGT("Timeout LCD (s)");
LSTR MSG_SCREEN_TIMEOUT = _UxGT("Timeout LCD (m)"); LSTR MSG_SCREEN_TIMEOUT = _UxGT("Timeout LCD (m)");
LSTR MSG_BRIGHTNESS_OFF = _UxGT("Spegni Retroillum."); LSTR MSG_BRIGHTNESS_OFF = _UxGT("Spegni Retroillum.");
LSTR MSG_STORE_EEPROM = _UxGT("Salva impostazioni"); LSTR MSG_STORE_EEPROM = _UxGT("Salva impostazioni");

1
Marlin/src/lcd/language/language_sk.h

@ -419,7 +419,6 @@ namespace Language_sk {
LSTR MSG_ADVANCE_K_E = _UxGT("K pre posun *"); LSTR MSG_ADVANCE_K_E = _UxGT("K pre posun *");
LSTR MSG_CONTRAST = _UxGT("Kontrast LCD"); LSTR MSG_CONTRAST = _UxGT("Kontrast LCD");
LSTR MSG_BRIGHTNESS = _UxGT("Jas LCD"); LSTR MSG_BRIGHTNESS = _UxGT("Jas LCD");
LSTR MSG_LCD_TIMEOUT_SEC = _UxGT("Čas. limit LCD (s)");
LSTR MSG_SCREEN_TIMEOUT = _UxGT("Čas. limit LCD (m)"); LSTR MSG_SCREEN_TIMEOUT = _UxGT("Čas. limit LCD (m)");
LSTR MSG_BRIGHTNESS_OFF = _UxGT("Podsviet. vyp."); LSTR MSG_BRIGHTNESS_OFF = _UxGT("Podsviet. vyp.");
LSTR MSG_STORE_EEPROM = _UxGT("Uložiť nastavenie"); LSTR MSG_STORE_EEPROM = _UxGT("Uložiť nastavenie");

2
Marlin/src/lcd/language/language_uk.h

@ -455,7 +455,7 @@ namespace Language_uk {
LSTR MSG_CONTRAST = _UxGT("Контраст"); LSTR MSG_CONTRAST = _UxGT("Контраст");
LSTR MSG_BRIGHTNESS = _UxGT("Яскравість"); LSTR MSG_BRIGHTNESS = _UxGT("Яскравість");
#endif #endif
LSTR MSG_LCD_TIMEOUT_SEC = _UxGT("LCD Таймаут, с"); LSTR MSG_SCREEN_TIMEOUT = _UxGT("LCD Таймаут, x");
LSTR MSG_BRIGHTNESS_OFF = _UxGT("Підсвітка вимк."); LSTR MSG_BRIGHTNESS_OFF = _UxGT("Підсвітка вимк.");
LSTR MSG_STORE_EEPROM = _UxGT("Зберегти в EEPROM"); LSTR MSG_STORE_EEPROM = _UxGT("Зберегти в EEPROM");
LSTR MSG_LOAD_EEPROM = _UxGT("Зчитати з EEPROM"); LSTR MSG_LOAD_EEPROM = _UxGT("Зчитати з EEPROM");

18
Marlin/src/lcd/marlinui.cpp

@ -174,22 +174,26 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;
volatile int8_t encoderDiff; // Updated in update_buttons, added to encoderPosition every LCD update volatile int8_t encoderDiff; // Updated in update_buttons, added to encoderPosition every LCD update
#endif #endif
#if LCD_BACKLIGHT_TIMEOUT #if LCD_BACKLIGHT_TIMEOUT_MINS
uint16_t MarlinUI::lcd_backlight_timeout; // Initialized by settings.load() constexpr uint8_t MarlinUI::backlight_timeout_min, MarlinUI::backlight_timeout_max;
uint8_t MarlinUI::backlight_timeout_minutes; // Initialized by settings.load()
millis_t MarlinUI::backlight_off_ms = 0; millis_t MarlinUI::backlight_off_ms = 0;
void MarlinUI::refresh_backlight_timeout() { void MarlinUI::refresh_backlight_timeout() {
backlight_off_ms = lcd_backlight_timeout ? millis() + lcd_backlight_timeout * 1000UL : 0; backlight_off_ms = backlight_timeout_minutes ? millis() + backlight_timeout_minutes * 60UL * 1000UL : 0;
WRITE(LCD_BACKLIGHT_PIN, HIGH); WRITE(LCD_BACKLIGHT_PIN, HIGH);
} }
#elif HAS_DISPLAY_SLEEP #elif HAS_DISPLAY_SLEEP
constexpr uint8_t MarlinUI::sleep_timeout_min, MarlinUI::sleep_timeout_max;
uint8_t MarlinUI::sleep_timeout_minutes; // Initialized by settings.load() uint8_t MarlinUI::sleep_timeout_minutes; // Initialized by settings.load()
millis_t MarlinUI::screen_timeout_millis = 0; millis_t MarlinUI::screen_timeout_millis = 0;
void MarlinUI::refresh_screen_timeout() { void MarlinUI::refresh_screen_timeout() {
screen_timeout_millis = sleep_timeout_minutes ? millis() + sleep_timeout_minutes * 60UL * 1000UL : 0; screen_timeout_millis = sleep_timeout_minutes ? millis() + sleep_timeout_minutes * 60UL * 1000UL : 0;
sleep_off(); sleep_display(false);
} }
#endif #endif
@ -1059,7 +1063,7 @@ void MarlinUI::init() {
reset_status_timeout(ms); reset_status_timeout(ms);
#if LCD_BACKLIGHT_TIMEOUT #if LCD_BACKLIGHT_TIMEOUT_MINS
refresh_backlight_timeout(); refresh_backlight_timeout();
#elif HAS_DISPLAY_SLEEP #elif HAS_DISPLAY_SLEEP
refresh_screen_timeout(); refresh_screen_timeout();
@ -1169,14 +1173,14 @@ void MarlinUI::init() {
return_to_status(); return_to_status();
#endif #endif
#if LCD_BACKLIGHT_TIMEOUT #if LCD_BACKLIGHT_TIMEOUT_MINS
if (backlight_off_ms && ELAPSED(ms, backlight_off_ms)) { if (backlight_off_ms && ELAPSED(ms, backlight_off_ms)) {
WRITE(LCD_BACKLIGHT_PIN, LOW); // Backlight off WRITE(LCD_BACKLIGHT_PIN, LOW); // Backlight off
backlight_off_ms = 0; backlight_off_ms = 0;
} }
#elif HAS_DISPLAY_SLEEP #elif HAS_DISPLAY_SLEEP
if (screen_timeout_millis && ELAPSED(ms, screen_timeout_millis)) if (screen_timeout_millis && ELAPSED(ms, screen_timeout_millis))
sleep_on(); sleep_display();
#endif #endif
// Change state of drawing flag between screen updates // Change state of drawing flag between screen updates

15
Marlin/src/lcd/marlinui.h

@ -270,20 +270,19 @@ public:
FORCE_INLINE static void refresh_brightness() { set_brightness(brightness); } FORCE_INLINE static void refresh_brightness() { set_brightness(brightness); }
#endif #endif
#if LCD_BACKLIGHT_TIMEOUT #if LCD_BACKLIGHT_TIMEOUT_MINS
#define LCD_BKL_TIMEOUT_MIN 1u static constexpr uint8_t backlight_timeout_min = 0;
#define LCD_BKL_TIMEOUT_MAX UINT16_MAX // Slightly more than 18 hours static constexpr uint8_t backlight_timeout_max = 99;
static uint16_t lcd_backlight_timeout; static uint8_t backlight_timeout_minutes;
static millis_t backlight_off_ms; static millis_t backlight_off_ms;
static void refresh_backlight_timeout(); static void refresh_backlight_timeout();
#elif HAS_DISPLAY_SLEEP #elif HAS_DISPLAY_SLEEP
#define SLEEP_TIMEOUT_MIN 0 static constexpr uint8_t sleep_timeout_min = 0;
#define SLEEP_TIMEOUT_MAX 99 static constexpr uint8_t sleep_timeout_max = 99;
static uint8_t sleep_timeout_minutes; static uint8_t sleep_timeout_minutes;
static millis_t screen_timeout_millis; static millis_t screen_timeout_millis;
static void refresh_screen_timeout(); static void refresh_screen_timeout();
static void sleep_on(); static void sleep_display(const bool sleep=true);
static void sleep_off();
#endif #endif
#if HAS_DWIN_E3V2_BASIC #if HAS_DWIN_E3V2_BASIC

6
Marlin/src/lcd/menu/menu_configuration.cpp

@ -547,10 +547,10 @@ void menu_configuration() {
// //
// Set display backlight / sleep timeout // Set display backlight / sleep timeout
// //
#if LCD_BACKLIGHT_TIMEOUT && LCD_BKL_TIMEOUT_MIN < LCD_BKL_TIMEOUT_MAX #if LCD_BACKLIGHT_TIMEOUT_MINS
EDIT_ITEM(uint16_4, MSG_LCD_TIMEOUT_SEC, &ui.lcd_backlight_timeout, LCD_BKL_TIMEOUT_MIN, LCD_BKL_TIMEOUT_MAX, ui.refresh_backlight_timeout); EDIT_ITEM(uint8, MSG_SCREEN_TIMEOUT, &ui.backlight_timeout_minutes, ui.backlight_timeout_min, ui.backlight_timeout_max, ui.refresh_backlight_timeout);
#elif HAS_DISPLAY_SLEEP #elif HAS_DISPLAY_SLEEP
EDIT_ITEM(uint8, MSG_SCREEN_TIMEOUT, &ui.sleep_timeout_minutes, SLEEP_TIMEOUT_MIN, SLEEP_TIMEOUT_MAX, ui.refresh_screen_timeout); EDIT_ITEM(uint8, MSG_SCREEN_TIMEOUT, &ui.sleep_timeout_minutes, ui.sleep_timeout_min, ui.sleep_timeout_max, ui.refresh_screen_timeout);
#endif #endif
#if ENABLED(FWRETRACT) #if ENABLED(FWRETRACT)

9
Marlin/src/lcd/menu/menu_item.h

@ -402,8 +402,13 @@ class MenuItem_bool : public MenuEditItemBase {
// Predefined menu item types // // Predefined menu item types //
#define BACK_ITEM_F(FLABEL) MENU_ITEM_F(back, FLABEL) #if DISABLED(DISABLE_ENCODER)
#define BACK_ITEM(LABEL) MENU_ITEM(back, LABEL) #define BACK_ITEM_F(FLABEL) MENU_ITEM_F(back, FLABEL)
#define BACK_ITEM(LABEL) MENU_ITEM(back, LABEL)
#else
#define BACK_ITEM_F(FLABEL) NOOP
#define BACK_ITEM(LABEL) NOOP
#endif
#define ACTION_ITEM_N_S_F(N, S, FLABEL, ACTION) MENU_ITEM_N_S_F(function, N, S, FLABEL, ACTION) #define ACTION_ITEM_N_S_F(N, S, FLABEL, ACTION) MENU_ITEM_N_S_F(function, N, S, FLABEL, ACTION)
#define ACTION_ITEM_N_S(N, S, LABEL, ACTION) ACTION_ITEM_N_S_F(N, S, GET_TEXT_F(LABEL), ACTION) #define ACTION_ITEM_N_S(N, S, LABEL, ACTION) ACTION_ITEM_N_S_F(N, S, GET_TEXT_F(LABEL), ACTION)

29
Marlin/src/lcd/menu/menu_main.cpp

@ -222,6 +222,16 @@ void menu_configuration();
#endif // CUSTOM_MENU_MAIN #endif // CUSTOM_MENU_MAIN
#if ENABLED(ADVANCED_PAUSE_FEATURE)
// This menu item is last with an encoder. Otherwise, somewhere in the middle.
#if E_STEPPERS == 1 && DISABLED(FILAMENT_LOAD_UNLOAD_GCODES)
#define FILAMENT_CHANGE_ITEM() YESNO_ITEM(MSG_FILAMENTCHANGE, menu_change_filament, nullptr, \
GET_TEXT_F(MSG_FILAMENTCHANGE), (const char *)nullptr, F("?"))
#else
#define FILAMENT_CHANGE_ITEM() SUBMENU(MSG_FILAMENTCHANGE, menu_change_filament)
#endif
#endif
void menu_main() { void menu_main() {
const bool busy = printingIsActive() const bool busy = printingIsActive()
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
@ -317,6 +327,10 @@ void menu_main() {
SUBMENU(MSG_MOTION, menu_motion); SUBMENU(MSG_MOTION, menu_motion);
} }
#if BOTH(ADVANCED_PAUSE_FEATURE, DISABLE_ENCODER)
FILAMENT_CHANGE_ITEM();
#endif
#if HAS_CUTTER #if HAS_CUTTER
SUBMENU(MSG_CUTTER(MENU), STICKY_SCREEN(menu_spindle_laser)); SUBMENU(MSG_CUTTER(MENU), STICKY_SCREEN(menu_spindle_laser));
#endif #endif
@ -349,17 +363,6 @@ void menu_main() {
} }
#endif #endif
#if ENABLED(ADVANCED_PAUSE_FEATURE)
#if E_STEPPERS == 1 && DISABLED(FILAMENT_LOAD_UNLOAD_GCODES)
YESNO_ITEM(MSG_FILAMENTCHANGE,
menu_change_filament, nullptr,
GET_TEXT_F(MSG_FILAMENTCHANGE), (const char *)nullptr, F("?")
);
#else
SUBMENU(MSG_FILAMENTCHANGE, menu_change_filament);
#endif
#endif
#if ENABLED(LCD_INFO_MENU) #if ENABLED(LCD_INFO_MENU)
SUBMENU(MSG_INFO_MENU, menu_info); SUBMENU(MSG_INFO_MENU, menu_info);
#endif #endif
@ -458,6 +461,10 @@ void menu_main() {
}); });
#endif #endif
#if ENABLED(ADVANCED_PAUSE_FEATURE) && DISABLED(DISABLE_ENCODER)
FILAMENT_CHANGE_ITEM();
#endif
END_MENU(); END_MENU();
} }

22
Marlin/src/lcd/menu/menu_ubl.cpp

@ -312,11 +312,7 @@ void _lcd_ubl_build_mesh() {
START_MENU(); START_MENU();
BACK_ITEM(MSG_UBL_TOOLS); BACK_ITEM(MSG_UBL_TOOLS);
#if HAS_PREHEAT #if HAS_PREHEAT
#if HAS_HEATED_BED #define PREHEAT_BED_GCODE(M) TERN(HAS_HEATED_BED, "M190I" STRINGIFY(M) "\n", "")
#define PREHEAT_BED_GCODE(M) "M190I" STRINGIFY(M) "\n"
#else
#define PREHEAT_BED_GCODE(M) ""
#endif
#define BUILD_MESH_GCODE_ITEM(M) GCODES_ITEM_f(ui.get_preheat_label(M), MSG_UBL_BUILD_MESH_M, \ #define BUILD_MESH_GCODE_ITEM(M) GCODES_ITEM_f(ui.get_preheat_label(M), MSG_UBL_BUILD_MESH_M, \
F( \ F( \
"G28\n" \ "G28\n" \
@ -325,20 +321,8 @@ void _lcd_ubl_build_mesh() {
"G29P1\n" \ "G29P1\n" \
"M104S0\n" \ "M104S0\n" \
"M140S0" \ "M140S0" \
) ) ) );
BUILD_MESH_GCODE_ITEM(0); REPEAT(PREHEAT_COUNT, BUILD_MESH_GCODE_ITEM)
#if PREHEAT_COUNT > 1
BUILD_MESH_GCODE_ITEM(1);
#if PREHEAT_COUNT > 2
BUILD_MESH_GCODE_ITEM(2);
#if PREHEAT_COUNT > 3
BUILD_MESH_GCODE_ITEM(3);
#if PREHEAT_COUNT > 4
BUILD_MESH_GCODE_ITEM(4);
#endif
#endif
#endif
#endif
#endif // HAS_PREHEAT #endif // HAS_PREHEAT
SUBMENU(MSG_UBL_BUILD_CUSTOM_MESH, _lcd_ubl_custom_mesh); SUBMENU(MSG_UBL_BUILD_CUSTOM_MESH, _lcd_ubl_custom_mesh);

2
Marlin/src/lcd/tft/touch.cpp

@ -302,7 +302,7 @@ bool Touch::get_point(int16_t *x, int16_t *y) {
WRITE(TFT_BACKLIGHT_PIN, HIGH); WRITE(TFT_BACKLIGHT_PIN, HIGH);
#endif #endif
} }
next_sleep_ms = millis() + SEC_TO_MS(TOUCH_IDLE_SLEEP); next_sleep_ms = millis() + SEC_TO_MS(ui.sleep_timeout_minutes * 60);
} }
#endif // HAS_TOUCH_SLEEP #endif // HAS_TOUCH_SLEEP

4
Marlin/src/lcd/touch/touch_buttons.cpp

@ -61,7 +61,7 @@ TouchButtons touchBt;
void TouchButtons::init() { void TouchButtons::init() {
touchIO.Init(); touchIO.Init();
TERN_(HAS_TOUCH_SLEEP, next_sleep_ms = millis() + SEC_TO_MS(TOUCH_IDLE_SLEEP)); TERN_(HAS_TOUCH_SLEEP, next_sleep_ms = millis() + SEC_TO_MS(ui.sleep_timeout_minutes * 60));
} }
uint8_t TouchButtons::read_buttons() { uint8_t TouchButtons::read_buttons() {
@ -135,7 +135,7 @@ uint8_t TouchButtons::read_buttons() {
WRITE(TFT_BACKLIGHT_PIN, HIGH); WRITE(TFT_BACKLIGHT_PIN, HIGH);
#endif #endif
} }
next_sleep_ms = millis() + SEC_TO_MS(TOUCH_IDLE_SLEEP); next_sleep_ms = millis() + SEC_TO_MS(ui.sleep_timeout_minutes * 60);
} }
#endif // HAS_TOUCH_SLEEP #endif // HAS_TOUCH_SLEEP

4
Marlin/src/module/probe.cpp

@ -882,7 +882,9 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
// Move the probe to the starting XYZ // Move the probe to the starting XYZ
do_blocking_move_to(npos, feedRate_t(XY_PROBE_FEEDRATE_MM_S)); do_blocking_move_to(npos, feedRate_t(XY_PROBE_FEEDRATE_MM_S));
TERN_(BD_SENSOR, return bdl.read()); #if ENABLED(BD_SENSOR)
return current_position.z - bdl.read(); // Difference between Z-home-relative Z and sensor reading
#endif
float measured_z = NAN; float measured_z = NAN;
if (!deploy()) { if (!deploy()) {

18
Marlin/src/module/settings.cpp

@ -402,8 +402,8 @@ typedef struct SettingsDataStruct {
// //
// Display Sleep // Display Sleep
// //
#if LCD_BACKLIGHT_TIMEOUT #if LCD_BACKLIGHT_TIMEOUT_MINS
uint16_t lcd_backlight_timeout; // M255 S uint8_t backlight_timeout_minutes; // M255 S
#elif HAS_DISPLAY_SLEEP #elif HAS_DISPLAY_SLEEP
uint8_t sleep_timeout_minutes; // M255 S uint8_t sleep_timeout_minutes; // M255 S
#endif #endif
@ -640,7 +640,7 @@ void MarlinSettings::postprocess() {
TERN_(HAS_LCD_CONTRAST, ui.refresh_contrast()); TERN_(HAS_LCD_CONTRAST, ui.refresh_contrast());
TERN_(HAS_LCD_BRIGHTNESS, ui.refresh_brightness()); TERN_(HAS_LCD_BRIGHTNESS, ui.refresh_brightness());
#if LCD_BACKLIGHT_TIMEOUT #if LCD_BACKLIGHT_TIMEOUT_MINS
ui.refresh_backlight_timeout(); ui.refresh_backlight_timeout();
#elif HAS_DISPLAY_SLEEP #elif HAS_DISPLAY_SLEEP
ui.refresh_screen_timeout(); ui.refresh_screen_timeout();
@ -1157,8 +1157,8 @@ void MarlinSettings::postprocess() {
// //
// LCD Backlight / Sleep Timeout // LCD Backlight / Sleep Timeout
// //
#if LCD_BACKLIGHT_TIMEOUT #if LCD_BACKLIGHT_TIMEOUT_MINS
EEPROM_WRITE(ui.lcd_backlight_timeout); EEPROM_WRITE(ui.backlight_timeout_minutes);
#elif HAS_DISPLAY_SLEEP #elif HAS_DISPLAY_SLEEP
EEPROM_WRITE(ui.sleep_timeout_minutes); EEPROM_WRITE(ui.sleep_timeout_minutes);
#endif #endif
@ -2108,8 +2108,8 @@ void MarlinSettings::postprocess() {
// //
// LCD Backlight / Sleep Timeout // LCD Backlight / Sleep Timeout
// //
#if LCD_BACKLIGHT_TIMEOUT #if LCD_BACKLIGHT_TIMEOUT_MINS
EEPROM_READ(ui.lcd_backlight_timeout); EEPROM_READ(ui.backlight_timeout_minutes);
#elif HAS_DISPLAY_SLEEP #elif HAS_DISPLAY_SLEEP
EEPROM_READ(ui.sleep_timeout_minutes); EEPROM_READ(ui.sleep_timeout_minutes);
#endif #endif
@ -3198,8 +3198,8 @@ void MarlinSettings::reset() {
// //
// LCD Backlight / Sleep Timeout // LCD Backlight / Sleep Timeout
// //
#if LCD_BACKLIGHT_TIMEOUT #if LCD_BACKLIGHT_TIMEOUT_MINS
ui.lcd_backlight_timeout = LCD_BACKLIGHT_TIMEOUT; ui.backlight_timeout_minutes = LCD_BACKLIGHT_TIMEOUT_MINS;
#elif HAS_DISPLAY_SLEEP #elif HAS_DISPLAY_SLEEP
ui.sleep_timeout_minutes = DISPLAY_SLEEP_MINUTES; ui.sleep_timeout_minutes = DISPLAY_SLEEP_MINUTES;
#endif #endif

4
Marlin/src/module/temperature.cpp

@ -1374,13 +1374,13 @@ void Temperature::min_temp_error(const heater_id_t heater_id) {
FORCE_INLINE void debug(const_celsius_float_t c, const_float_t pid_out, FSTR_P const name=nullptr, const int8_t index=-1) { FORCE_INLINE void debug(const_celsius_float_t c, const_float_t pid_out, FSTR_P const name=nullptr, const int8_t index=-1) {
if (TERN0(HAS_PID_DEBUG, thermalManager.pid_debug_flag)) { if (TERN0(HAS_PID_DEBUG, thermalManager.pid_debug_flag)) {
SERIAL_ECHO_START(); SERIAL_ECHO_START();
if (name) SERIAL_ECHOLNF(name); if (name) SERIAL_ECHOF(name);
if (index >= 0) SERIAL_ECHO(index); if (index >= 0) SERIAL_ECHO(index);
SERIAL_ECHOLNPGM( SERIAL_ECHOLNPGM(
STR_PID_DEBUG_INPUT, c, STR_PID_DEBUG_INPUT, c,
STR_PID_DEBUG_OUTPUT, pid_out STR_PID_DEBUG_OUTPUT, pid_out
#if DISABLED(PID_OPENLOOP) #if DISABLED(PID_OPENLOOP)
, "pTerm", work_pid.Kp, "iTerm", work_pid.Ki, "dTerm", work_pid.Kd , " pTerm ", work_pid.Kp, " iTerm ", work_pid.Ki, " dTerm ", work_pid.Kd
#endif #endif
); );
} }

2
Marlin/src/module/thermistor/thermistor_504.h

@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

2
Marlin/src/module/thermistor/thermistor_505.h

@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

6
Marlin/src/pins/pins.h

@ -512,9 +512,9 @@
#elif MB(MKS_ROBIN_MINI) #elif MB(MKS_ROBIN_MINI)
#include "stm32f1/pins_MKS_ROBIN_MINI.h" // STM32F1 env:mks_robin_mini env:mks_robin_mini_maple #include "stm32f1/pins_MKS_ROBIN_MINI.h" // STM32F1 env:mks_robin_mini env:mks_robin_mini_maple
#elif MB(MKS_ROBIN_NANO) #elif MB(MKS_ROBIN_NANO)
#include "stm32f1/pins_MKS_ROBIN_NANO.h" // STM32F1 env:mks_robin_nano35 env:mks_robin_nano35_maple #include "stm32f1/pins_MKS_ROBIN_NANO.h" // STM32F1 env:mks_robin_nano_v1v2 env:mks_robin_nano_v1v2_maple env:mks_robin_nano_v1_2_usbmod
#elif MB(MKS_ROBIN_NANO_V2) #elif MB(MKS_ROBIN_NANO_V2)
#include "stm32f1/pins_MKS_ROBIN_NANO_V2.h" // STM32F1 env:mks_robin_nano35 env:mks_robin_nano35_maple #include "stm32f1/pins_MKS_ROBIN_NANO_V2.h" // STM32F1 env:mks_robin_nano_v1v2 env:mks_robin_nano3_v1v2_maple
#elif MB(MKS_ROBIN_LITE) #elif MB(MKS_ROBIN_LITE)
#include "stm32f1/pins_MKS_ROBIN_LITE.h" // STM32F1 env:mks_robin_lite env:mks_robin_lite_maple #include "stm32f1/pins_MKS_ROBIN_LITE.h" // STM32F1 env:mks_robin_lite env:mks_robin_lite_maple
#elif MB(MKS_ROBIN_LITE3) #elif MB(MKS_ROBIN_LITE3)
@ -694,7 +694,7 @@
#elif MB(OPULO_LUMEN_REV3) #elif MB(OPULO_LUMEN_REV3)
#include "stm32f4/pins_OPULO_LUMEN_REV3.h" // STM32F4 env:Opulo_Lumen_REV3 #include "stm32f4/pins_OPULO_LUMEN_REV3.h" // STM32F4 env:Opulo_Lumen_REV3
#elif MB(MKS_ROBIN_NANO_V1_3_F4) #elif MB(MKS_ROBIN_NANO_V1_3_F4)
#include "stm32f4/pins_MKS_ROBIN_NANO_V1_3_F4.h" // STM32F4 env:mks_robin_nano_v1_3_f4 #include "stm32f4/pins_MKS_ROBIN_NANO_V1_3_F4.h" // STM32F4 env:mks_robin_nano_v1_3_f4 env:mks_robin_nano_v1_3_f4_usbmod
#elif MB(MKS_EAGLE) #elif MB(MKS_EAGLE)
#include "stm32f4/pins_MKS_EAGLE.h" // STM32F4 env:mks_eagle #include "stm32f4/pins_MKS_EAGLE.h" // STM32F4 env:mks_eagle
#elif MB(ARTILLERY_RUBY) #elif MB(ARTILLERY_RUBY)

2
Marlin/src/pins/sanguino/pins_ZMIB_V2.h

@ -36,7 +36,7 @@
* If you don't have a chip programmer you can use a spare Arduino plus a few * If you don't have a chip programmer you can use a spare Arduino plus a few
* electronic components to write the bootloader. * electronic components to write the bootloader.
* *
* See http://www.instructables.com/id/Burn-Arduino-Bootloader-with-Arduino-MEGA/ * See https://www.instructables.com/Burn-Arduino-Bootloader-with-Arduino-MEGA/
*/ */
/** /**

4
Marlin/src/pins/stm32f1/pins_CREALITY_V422.h

@ -28,4 +28,8 @@
#define BOARD_INFO_NAME "Creality v4.2.2" #define BOARD_INFO_NAME "Creality v4.2.2"
#define DEFAULT_MACHINE_NAME "Creality3D" #define DEFAULT_MACHINE_NAME "Creality3D"
#ifndef EMIT_CREALITY_422_WARNING
#define EMIT_CREALITY_422_WARNING
#endif
#include "pins_CREALITY_V4.h" #include "pins_CREALITY_V4.h"

2
Marlin/src/pins/stm32f1/pins_GTM32_PRO_VB.h

@ -23,7 +23,7 @@
/** /**
* Geeetech GTM32 Pro VB board pin assignments * Geeetech GTM32 Pro VB board pin assignments
* http://www.geeetech.com/wiki/index.php/File:Hardware_GTM32_PRO_VB.pdf * https://www.geeetech.com/wiki/index.php/File:Hardware_GTM32_PRO_VB.pdf
* *
* Also applies to GTM32 Pro VD * Also applies to GTM32 Pro VD
*/ */

2
Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO.h

@ -29,7 +29,7 @@
#define ALLOW_STM32DUINO #define ALLOW_STM32DUINO
#include "env_validate.h" #include "env_validate.h"
#define BOARD_INFO_NAME "MKS Robin Nano" #define BOARD_INFO_NAME "MKS Robin Nano V1"
// //
// Release PB4 (Y_ENABLE_PIN) from JTAG NRST role // Release PB4 (Y_ENABLE_PIN) from JTAG NRST role

4
Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO_V2.h

@ -35,7 +35,9 @@
#define BOARD_INFO_NAME "MKS Robin nano V2.0" #define BOARD_INFO_NAME "MKS Robin nano V2.0"
#define BOARD_NO_NATIVE_USB #ifndef USB_MOD
#define BOARD_NO_NATIVE_USB
#endif
#define USES_DIAG_PINS #define USES_DIAG_PINS
// Avoid conflict with TIMER_SERVO when using the STM32 HAL // Avoid conflict with TIMER_SERVO when using the STM32 HAL

13
Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO_common.h

@ -29,7 +29,9 @@
#error "MKS Robin nano boards support up to 2 hotends / E steppers." #error "MKS Robin nano boards support up to 2 hotends / E steppers."
#endif #endif
#define BOARD_NO_NATIVE_USB #ifndef USB_MOD
#define BOARD_NO_NATIVE_USB
#endif
// Avoid conflict with TIMER_SERVO when using the STM32 HAL // Avoid conflict with TIMER_SERVO when using the STM32 HAL
#define TEMP_TIMER 5 #define TEMP_TIMER 5
@ -58,9 +60,14 @@
// Limit Switches // Limit Switches
// //
#define X_STOP_PIN PA15 #define X_STOP_PIN PA15
#define Y_STOP_PIN PA12
#define Z_MIN_PIN PA11
#define Z_MAX_PIN PC4 #define Z_MAX_PIN PC4
#ifndef USB_MOD
#define Y_STOP_PIN PA12
#define Z_MIN_PIN PA11
#else
#define Y_STOP_PIN PB10
#define Z_MIN_PIN PB11
#endif
// //
// Steppers // Steppers

2
Marlin/src/pins/stm32f4/pins_ARTILLERY_RUBY.h

@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

50
Marlin/src/sd/cardreader.cpp

@ -29,6 +29,7 @@
#include "cardreader.h" #include "cardreader.h"
#include "../MarlinCore.h" #include "../MarlinCore.h"
#include "../libs/hex_print.h"
#include "../lcd/marlinui.h" #include "../lcd/marlinui.h"
#if ENABLED(DWIN_CREALITY_LCD) #if ENABLED(DWIN_CREALITY_LCD)
@ -197,7 +198,7 @@ char *createFilename(char * const buffer, const dir_t &p) {
// //
// Return 'true' if the item is a folder, G-code file or Binary file // Return 'true' if the item is a folder, G-code file or Binary file
// //
bool CardReader::is_visible_entity(const dir_t &p OPTARG(CUSTOM_FIRMWARE_UPLOAD, bool onlyBin/*=false*/)) { bool CardReader::is_visible_entity(const dir_t &p OPTARG(CUSTOM_FIRMWARE_UPLOAD, const bool onlyBin/*=false*/)) {
//uint8_t pn0 = p.name[0]; //uint8_t pn0 = p.name[0];
#if DISABLED(CUSTOM_FIRMWARE_UPLOAD) #if DISABLED(CUSTOM_FIRMWARE_UPLOAD)
@ -279,12 +280,17 @@ void CardReader::selectByName(SdFile dir, const char * const match) {
* this can blow up the stack, so a 'depth' parameter would be a * this can blow up the stack, so a 'depth' parameter would be a
* good addition. * good addition.
*/ */
void CardReader::printListing( void CardReader::printListing(SdFile parent, const char * const prepend, const uint8_t lsflags
SdFile parent, const char * const prepend
OPTARG(CUSTOM_FIRMWARE_UPLOAD, bool onlyBin/*=false*/)
OPTARG(LONG_FILENAME_HOST_SUPPORT, const bool includeLongNames/*=false*/)
OPTARG(LONG_FILENAME_HOST_SUPPORT, const char * const prependLong/*=nullptr*/) OPTARG(LONG_FILENAME_HOST_SUPPORT, const char * const prependLong/*=nullptr*/)
) { ) {
const bool includeTime = TERN0(M20_TIMESTAMP_SUPPORT, TEST(lsflags, LS_TIMESTAMP));
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
const bool includeLong = TEST(lsflags, LS_LONG_FILENAME);
#endif
#if ENABLED(CUSTOM_FIRMWARE_UPLOAD)
const bool onlyBin = TEST(lsflags, LS_ONLY_BIN);
#endif
UNUSED(lsflags);
dir_t p; dir_t p;
while (parent.readDir(&p, longFilename) > 0) { while (parent.readDir(&p, longFilename) > 0) {
if (DIR_IS_SUBDIR(&p)) { if (DIR_IS_SUBDIR(&p)) {
@ -301,19 +307,17 @@ void CardReader::printListing(
SdFile child; // child.close() in destructor SdFile child; // child.close() in destructor
if (child.open(&parent, dosFilename, O_READ)) { if (child.open(&parent, dosFilename, O_READ)) {
#if ENABLED(LONG_FILENAME_HOST_SUPPORT) #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
if (includeLongNames) { if (includeLong) {
size_t lenPrependLong = prependLong ? strlen(prependLong) + 1 : 0; const size_t lenPrependLong = prependLong ? strlen(prependLong) + 1 : 0;
// Allocate enough stack space for the full long path including / separator // Allocate enough stack space for the full long path including / separator
char pathLong[lenPrependLong + strlen(longFilename) + 1]; char pathLong[lenPrependLong + strlen(longFilename) + 1];
if (prependLong) { strcpy(pathLong, prependLong); pathLong[lenPrependLong - 1] = '/'; } if (prependLong) { strcpy(pathLong, prependLong); pathLong[lenPrependLong - 1] = '/'; }
strcpy(pathLong + lenPrependLong, longFilename); strcpy(pathLong + lenPrependLong, longFilename);
printListing(child, path OPTARG(CUSTOM_FIRMWARE_UPLOAD, onlyBin), true, pathLong); printListing(child, path, lsflags, pathLong);
continue;
} }
else
printListing(child, path OPTARG(CUSTOM_FIRMWARE_UPLOAD, onlyBin));
#else
printListing(child, path OPTARG(CUSTOM_FIRMWARE_UPLOAD, onlyBin));
#endif #endif
printListing(child, path, lsflags);
} }
else { else {
SERIAL_ECHO_MSG(STR_SD_CANT_OPEN_SUBDIR, dosFilename); SERIAL_ECHO_MSG(STR_SD_CANT_OPEN_SUBDIR, dosFilename);
@ -325,8 +329,18 @@ void CardReader::printListing(
SERIAL_ECHO(createFilename(filename, p)); SERIAL_ECHO(createFilename(filename, p));
SERIAL_CHAR(' '); SERIAL_CHAR(' ');
SERIAL_ECHO(p.fileSize); SERIAL_ECHO(p.fileSize);
if (includeTime) {
SERIAL_CHAR(' ');
uint16_t crmodDate = p.lastWriteDate, crmodTime = p.lastWriteTime;
if (crmodDate < p.creationDate || (crmodDate == p.creationDate && crmodTime < p.creationTime)) {
crmodDate = p.creationDate;
crmodTime = p.creationTime;
}
SERIAL_ECHOPGM("0x", hex_word(crmodDate));
print_hex_word(crmodTime);
}
#if ENABLED(LONG_FILENAME_HOST_SUPPORT) #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
if (includeLongNames) { if (includeLong) {
SERIAL_CHAR(' '); SERIAL_CHAR(' ');
if (prependLong) { SERIAL_ECHO(prependLong); SERIAL_CHAR('/'); } if (prependLong) { SERIAL_ECHO(prependLong); SERIAL_CHAR('/'); }
SERIAL_ECHO(longFilename[0] ? longFilename : filename); SERIAL_ECHO(longFilename[0] ? longFilename : filename);
@ -340,16 +354,10 @@ void CardReader::printListing(
// //
// List all files on the SD card // List all files on the SD card
// //
void CardReader::ls( void CardReader::ls(const uint8_t lsflags) {
TERN_(CUSTOM_FIRMWARE_UPLOAD, const bool onlyBin/*=false*/)
#if BOTH(CUSTOM_FIRMWARE_UPLOAD, LONG_FILENAME_HOST_SUPPORT)
,
#endif
TERN_(LONG_FILENAME_HOST_SUPPORT, const bool includeLongNames/*=false*/)
) {
if (flag.mounted) { if (flag.mounted) {
root.rewind(); root.rewind();
printListing(root, nullptr OPTARG(CUSTOM_FIRMWARE_UPLOAD, onlyBin) OPTARG(LONG_FILENAME_HOST_SUPPORT, includeLongNames)); printListing(root, nullptr, lsflags);
} }
} }

15
Marlin/src/sd/cardreader.h

@ -89,6 +89,8 @@ typedef struct {
; ;
} card_flags_t; } card_flags_t;
enum ListingFlags : uint8_t { LS_LONG_FILENAME, LS_ONLY_BIN, LS_TIMESTAMP };
#if ENABLED(AUTO_REPORT_SD_STATUS) #if ENABLED(AUTO_REPORT_SD_STATUS)
#include "../libs/autoreport.h" #include "../libs/autoreport.h"
#endif #endif
@ -207,13 +209,7 @@ public:
FORCE_INLINE static void getfilename_sorted(const uint16_t nr) { selectFileByIndex(nr); } FORCE_INLINE static void getfilename_sorted(const uint16_t nr) { selectFileByIndex(nr); }
#endif #endif
static void ls( static void ls(const uint8_t lsflags);
TERN_(CUSTOM_FIRMWARE_UPLOAD, const bool onlyBin=false)
#if BOTH(CUSTOM_FIRMWARE_UPLOAD, LONG_FILENAME_HOST_SUPPORT)
,
#endif
TERN_(LONG_FILENAME_HOST_SUPPORT, const bool includeLongNames=false)
);
#if ENABLED(POWER_LOSS_RECOVERY) #if ENABLED(POWER_LOSS_RECOVERY)
static bool jobRecoverFileExists(); static bool jobRecoverFileExists();
@ -348,10 +344,7 @@ private:
static int countItems(SdFile dir); static int countItems(SdFile dir);
static void selectByIndex(SdFile dir, const uint8_t index); static void selectByIndex(SdFile dir, const uint8_t index);
static void selectByName(SdFile dir, const char * const match); static void selectByName(SdFile dir, const char * const match);
static void printListing( static void printListing(SdFile parent, const char * const prepend, const uint8_t lsflags
SdFile parent, const char * const prepend
OPTARG(CUSTOM_FIRMWARE_UPLOAD, const bool onlyBin=false)
OPTARG(LONG_FILENAME_HOST_SUPPORT, const bool includeLongNames=false)
OPTARG(LONG_FILENAME_HOST_SUPPORT, const char * const prependLong=nullptr) OPTARG(LONG_FILENAME_HOST_SUPPORT, const char * const prependLong=nullptr)
); );

20
buildroot/share/PlatformIO/scripts/SAMD51_grandcentral_m4.py

@ -4,17 +4,17 @@
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
from os.path import join, isfile from os.path import join, isfile
import shutil import shutil
Import("env") Import("env")
mf = env["MARLIN_FEATURES"] mf = env["MARLIN_FEATURES"]
rxBuf = mf["RX_BUFFER_SIZE"] if "RX_BUFFER_SIZE" in mf else "0" rxBuf = mf["RX_BUFFER_SIZE"] if "RX_BUFFER_SIZE" in mf else "0"
txBuf = mf["TX_BUFFER_SIZE"] if "TX_BUFFER_SIZE" in mf else "0" txBuf = mf["TX_BUFFER_SIZE"] if "TX_BUFFER_SIZE" in mf else "0"
serialBuf = str(max(int(rxBuf), int(txBuf), 350)) serialBuf = str(max(int(rxBuf), int(txBuf), 350))
build_flags = env.get('BUILD_FLAGS') build_flags = env.get('BUILD_FLAGS')
build_flags.append("-DSERIAL_BUFFER_SIZE=" + serialBuf) build_flags.append("-DSERIAL_BUFFER_SIZE=" + serialBuf)
env.Replace(BUILD_FLAGS=build_flags) env.Replace(BUILD_FLAGS=build_flags)

174
buildroot/share/PlatformIO/scripts/chitu_crypt.py

@ -4,123 +4,123 @@
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
import struct,uuid,marlin import struct,uuid,marlin
board = marlin.env.BoardConfig() board = marlin.env.BoardConfig()
def calculate_crc(contents, seed): def calculate_crc(contents, seed):
accumulating_xor_value = seed; accumulating_xor_value = seed;
for i in range(0, len(contents), 4): for i in range(0, len(contents), 4):
value = struct.unpack('<I', contents[ i : i + 4])[0] value = struct.unpack('<I', contents[ i : i + 4])[0]
accumulating_xor_value = accumulating_xor_value ^ value accumulating_xor_value = accumulating_xor_value ^ value
return accumulating_xor_value return accumulating_xor_value
def xor_block(r0, r1, block_number, block_size, file_key): def xor_block(r0, r1, block_number, block_size, file_key):
# This is the loop counter # This is the loop counter
loop_counter = 0x0 loop_counter = 0x0
# This is the key length # This is the key length
key_length = 0x18 key_length = 0x18
# This is an initial seed # This is an initial seed
xor_seed = 0x4BAD xor_seed = 0x4BAD
# This is the block counter # This is the block counter
block_number = xor_seed * block_number block_number = xor_seed * block_number
#load the xor key from the file #load the xor key from the file
r7 = file_key r7 = file_key
for loop_counter in range(0, block_size): for loop_counter in range(0, block_size):
# meant to make sure different bits of the key are used. # meant to make sure different bits of the key are used.
xor_seed = int(loop_counter / key_length) xor_seed = int(loop_counter / key_length)
# IP is a scratch register / R12 # IP is a scratch register / R12
ip = loop_counter - (key_length * xor_seed) ip = loop_counter - (key_length * xor_seed)
# xor_seed = (loop_counter * loop_counter) + block_number # xor_seed = (loop_counter * loop_counter) + block_number
xor_seed = (loop_counter * loop_counter) + block_number xor_seed = (loop_counter * loop_counter) + block_number
# shift the xor_seed left by the bits in IP. # shift the xor_seed left by the bits in IP.
xor_seed = xor_seed >> ip xor_seed = xor_seed >> ip
# load a byte into IP # load a byte into IP
ip = r0[loop_counter] ip = r0[loop_counter]
# XOR the seed with r7 # XOR the seed with r7
xor_seed = xor_seed ^ r7 xor_seed = xor_seed ^ r7
# and then with IP # and then with IP
xor_seed = xor_seed ^ ip xor_seed = xor_seed ^ ip
#Now store the byte back #Now store the byte back
r1[loop_counter] = xor_seed & 0xFF r1[loop_counter] = xor_seed & 0xFF
#increment the loop_counter #increment the loop_counter
loop_counter = loop_counter + 1 loop_counter = loop_counter + 1
def encrypt_file(input, output_file, file_length): def encrypt_file(input, output_file, file_length):
input_file = bytearray(input.read()) input_file = bytearray(input.read())
block_size = 0x800 block_size = 0x800
key_length = 0x18 key_length = 0x18
uid_value = uuid.uuid4() uid_value = uuid.uuid4()
file_key = int(uid_value.hex[0:8], 16) file_key = int(uid_value.hex[0:8], 16)
xor_crc = 0xEF3D4323; xor_crc = 0xEF3D4323;
# the input file is exepcted to be in chunks of 0x800 # the input file is exepcted to be in chunks of 0x800
# so round the size # so round the size
while len(input_file) % block_size != 0: while len(input_file) % block_size != 0:
input_file.extend(b'0x0') input_file.extend(b'0x0')
# write the file header # write the file header
output_file.write(struct.pack(">I", 0x443D2D3F)) output_file.write(struct.pack(">I", 0x443D2D3F))
# encrypt the contents using a known file header key # encrypt the contents using a known file header key
# write the file_key # write the file_key
output_file.write(struct.pack("<I", file_key)) output_file.write(struct.pack("<I", file_key))
#TODO - how to enforce that the firmware aligns to block boundaries? #TODO - how to enforce that the firmware aligns to block boundaries?
block_count = int(len(input_file) / block_size) block_count = int(len(input_file) / block_size)
print ("Block Count is ", block_count) print ("Block Count is ", block_count)
for block_number in range(0, block_count): for block_number in range(0, block_count):
block_offset = (block_number * block_size) block_offset = (block_number * block_size)
block_end = block_offset + block_size block_end = block_offset + block_size
block_array = bytearray(input_file[block_offset: block_end]) block_array = bytearray(input_file[block_offset: block_end])
xor_block(block_array, block_array, block_number, block_size, file_key) xor_block(block_array, block_array, block_number, block_size, file_key)
for n in range (0, block_size): for n in range (0, block_size):
input_file[block_offset + n] = block_array[n] input_file[block_offset + n] = block_array[n]
# update the expected CRC value. # update the expected CRC value.
xor_crc = calculate_crc(block_array, xor_crc) xor_crc = calculate_crc(block_array, xor_crc)
# write CRC # write CRC
output_file.write(struct.pack("<I", xor_crc)) output_file.write(struct.pack("<I", xor_crc))
# finally, append the encrypted results. # finally, append the encrypted results.
output_file.write(input_file) output_file.write(input_file)
return return
# Encrypt ${PROGNAME}.bin and save it as 'update.cbd' # Encrypt ${PROGNAME}.bin and save it as 'update.cbd'
def encrypt(source, target, env): def encrypt(source, target, env):
from pathlib import Path from pathlib import Path
fwpath = Path(target[0].path) fwpath = Path(target[0].path)
fwsize = fwpath.stat().st_size fwsize = fwpath.stat().st_size
enname = board.get("build.crypt_chitu") enname = board.get("build.crypt_chitu")
enpath = Path(target[0].dir.path) enpath = Path(target[0].dir.path)
fwfile = fwpath.open("rb") fwfile = fwpath.open("rb")
enfile = (enpath / enname).open("wb") enfile = (enpath / enname).open("wb")
print(f"Encrypting {fwpath} to {enname}") print(f"Encrypting {fwpath} to {enname}")
encrypt_file(fwfile, enfile, fwsize) encrypt_file(fwfile, enfile, fwsize)
fwfile.close() fwfile.close()
enfile.close() enfile.close()
fwpath.unlink() fwpath.unlink()
marlin.relocate_firmware("0x08008800") marlin.relocate_firmware("0x08008800")
marlin.add_post_action(encrypt); marlin.add_post_action(encrypt);

65
buildroot/share/PlatformIO/scripts/common-cxxflags.py

@ -2,38 +2,45 @@
# common-cxxflags.py # common-cxxflags.py
# Convenience script to apply customizations to CPP flags # Convenience script to apply customizations to CPP flags
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
Import("env") Import("env")
cxxflags = [
# "-Wno-incompatible-pointer-types",
# "-Wno-unused-const-variable",
# "-Wno-maybe-uninitialized",
# "-Wno-sign-compare"
]
if "teensy" not in env["PIOENV"]:
cxxflags += ["-Wno-register"]
env.Append(CXXFLAGS=cxxflags)
#
# Add CPU frequency as a compile time constant instead of a runtime variable
#
def add_cpu_freq():
if "BOARD_F_CPU" in env:
env["BUILD_FLAGS"].append("-DBOARD_F_CPU=" + env["BOARD_F_CPU"])
cxxflags = [ # Useful for JTAG debugging
#"-Wno-incompatible-pointer-types", #
#"-Wno-unused-const-variable", # It will separate release and debug build folders.
#"-Wno-maybe-uninitialized", # It useful to keep two live versions: a debug version for debugging and another for
#"-Wno-sign-compare" # release, for flashing when upload is not done automatically by jlink/stlink.
] # Without this, PIO needs to recompile everything twice for any small change.
if "teensy" not in env['PIOENV']: if env.GetBuildType() == "debug" and env.get("UPLOAD_PROTOCOL") not in ["jlink", "stlink", "custom"]:
cxxflags += ["-Wno-register"] env["BUILD_DIR"] = "$PROJECT_BUILD_DIR/$PIOENV/debug"
env.Append(CXXFLAGS=cxxflags)
# def on_program_ready(source, target, env):
# Add CPU frequency as a compile time constant instead of a runtime variable import shutil
# shutil.copy(target[0].get_abspath(), env.subst("$PROJECT_BUILD_DIR/$PIOENV"))
def add_cpu_freq():
if 'BOARD_F_CPU' in env:
env['BUILD_FLAGS'].append('-DBOARD_F_CPU=' + env['BOARD_F_CPU'])
# Useful for JTAG debugging env.AddPostAction("$PROGPATH", on_program_ready)
#
# It will separate release and debug build folders.
# It useful to keep two live versions: a debug version for debugging and another for
# release, for flashing when upload is not done automatically by jlink/stlink.
# Without this, PIO needs to recompile everything twice for any small change.
if env.GetBuildType() == "debug" and env.get('UPLOAD_PROTOCOL') not in ['jlink', 'stlink', 'custom']:
env['BUILD_DIR'] = '$PROJECT_BUILD_DIR/$PIOENV/debug'
# On some platform, F_CPU is a runtime variable. Since it's used to convert from ns # On some platform, F_CPU is a runtime variable. Since it's used to convert from ns
# to CPU cycles, this adds overhead preventing small delay (in the order of less than # to CPU cycles, this adds overhead preventing small delay (in the order of less than
# 30 cycles) to be generated correctly. By using a compile time constant instead # 30 cycles) to be generated correctly. By using a compile time constant instead
# the compiler will perform the computation and this overhead will be avoided # the compiler will perform the computation and this overhead will be avoided
add_cpu_freq() add_cpu_freq()

16
buildroot/share/PlatformIO/scripts/common-dependencies-post.py

@ -4,13 +4,13 @@
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
Import("env", "projenv") Import("env", "projenv")
def apply_board_build_flags(): def apply_board_build_flags():
if not 'BOARD_CUSTOM_BUILD_FLAGS' in env['MARLIN_FEATURES']: if not 'BOARD_CUSTOM_BUILD_FLAGS' in env['MARLIN_FEATURES']:
return return
projenv.Append(CCFLAGS=env['MARLIN_FEATURES']['BOARD_CUSTOM_BUILD_FLAGS'].split()) projenv.Append(CCFLAGS=env['MARLIN_FEATURES']['BOARD_CUSTOM_BUILD_FLAGS'].split())
# We need to add the board build flags in a post script # We need to add the board build flags in a post script
# so the platform build script doesn't overwrite the custom CCFLAGS # so the platform build script doesn't overwrite the custom CCFLAGS
apply_board_build_flags() apply_board_build_flags()

488
buildroot/share/PlatformIO/scripts/common-dependencies.py

@ -5,247 +5,247 @@
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
import subprocess,os,re import subprocess,os,re
Import("env") Import("env")
from platformio.package.meta import PackageSpec from platformio.package.meta import PackageSpec
from platformio.project.config import ProjectConfig from platformio.project.config import ProjectConfig
verbose = 0 verbose = 0
FEATURE_CONFIG = {} FEATURE_CONFIG = {}
def validate_pio(): def validate_pio():
PIO_VERSION_MIN = (6, 0, 1) PIO_VERSION_MIN = (6, 0, 1)
try: try:
from platformio import VERSION as PIO_VERSION from platformio import VERSION as PIO_VERSION
weights = (1000, 100, 1) weights = (1000, 100, 1)
version_min = sum([x[0] * float(re.sub(r'[^0-9]', '.', str(x[1]))) for x in zip(weights, PIO_VERSION_MIN)]) version_min = sum([x[0] * float(re.sub(r'[^0-9]', '.', str(x[1]))) for x in zip(weights, PIO_VERSION_MIN)])
version_cur = sum([x[0] * float(re.sub(r'[^0-9]', '.', str(x[1]))) for x in zip(weights, PIO_VERSION)]) version_cur = sum([x[0] * float(re.sub(r'[^0-9]', '.', str(x[1]))) for x in zip(weights, PIO_VERSION)])
if version_cur < version_min: if version_cur < version_min:
print() print()
print("**************************************************") print("**************************************************")
print("****** An update to PlatformIO is ******") print("****** An update to PlatformIO is ******")
print("****** required to build Marlin Firmware. ******") print("****** required to build Marlin Firmware. ******")
print("****** ******") print("****** ******")
print("****** Minimum version: ", PIO_VERSION_MIN, " ******") print("****** Minimum version: ", PIO_VERSION_MIN, " ******")
print("****** Current Version: ", PIO_VERSION, " ******") print("****** Current Version: ", PIO_VERSION, " ******")
print("****** ******") print("****** ******")
print("****** Update PlatformIO and try again. ******") print("****** Update PlatformIO and try again. ******")
print("**************************************************") print("**************************************************")
print() print()
exit(1) exit(1)
except SystemExit: except SystemExit:
exit(1) exit(1)
except: except:
print("Can't detect PlatformIO Version") print("Can't detect PlatformIO Version")
def blab(str,level=1): def blab(str,level=1):
if verbose >= level: if verbose >= level:
print("[deps] %s" % str) print("[deps] %s" % str)
def add_to_feat_cnf(feature, flines): def add_to_feat_cnf(feature, flines):
try: try:
feat = FEATURE_CONFIG[feature] feat = FEATURE_CONFIG[feature]
except: except:
FEATURE_CONFIG[feature] = {} FEATURE_CONFIG[feature] = {}
# Get a reference to the FEATURE_CONFIG under construction # Get a reference to the FEATURE_CONFIG under construction
feat = FEATURE_CONFIG[feature] feat = FEATURE_CONFIG[feature]
# Split up passed lines on commas or newlines and iterate # Split up passed lines on commas or newlines and iterate
# Add common options to the features config under construction # Add common options to the features config under construction
# For lib_deps replace a previous instance of the same library # For lib_deps replace a previous instance of the same library
atoms = re.sub(r',\s*', '\n', flines).strip().split('\n') atoms = re.sub(r',\s*', '\n', flines).strip().split('\n')
for line in atoms: for line in atoms:
parts = line.split('=') parts = line.split('=')
name = parts.pop(0) name = parts.pop(0)
if name in ['build_flags', 'extra_scripts', 'src_filter', 'lib_ignore']: if name in ['build_flags', 'extra_scripts', 'src_filter', 'lib_ignore']:
feat[name] = '='.join(parts) feat[name] = '='.join(parts)
blab("[%s] %s=%s" % (feature, name, feat[name]), 3) blab("[%s] %s=%s" % (feature, name, feat[name]), 3)
else: else:
for dep in re.split(r',\s*', line): for dep in re.split(r',\s*', line):
lib_name = re.sub(r'@([~^]|[<>]=?)?[\d.]+', '', dep.strip()).split('=').pop(0) lib_name = re.sub(r'@([~^]|[<>]=?)?[\d.]+', '', dep.strip()).split('=').pop(0)
lib_re = re.compile('(?!^' + lib_name + '\\b)') lib_re = re.compile('(?!^' + lib_name + '\\b)')
feat['lib_deps'] = list(filter(lib_re.match, feat['lib_deps'])) + [dep] feat['lib_deps'] = list(filter(lib_re.match, feat['lib_deps'])) + [dep]
blab("[%s] lib_deps = %s" % (feature, dep), 3) blab("[%s] lib_deps = %s" % (feature, dep), 3)
def load_features(): def load_features():
blab("========== Gather [features] entries...") blab("========== Gather [features] entries...")
for key in ProjectConfig().items('features'): for key in ProjectConfig().items('features'):
feature = key[0].upper() feature = key[0].upper()
if not feature in FEATURE_CONFIG: if not feature in FEATURE_CONFIG:
FEATURE_CONFIG[feature] = { 'lib_deps': [] } FEATURE_CONFIG[feature] = { 'lib_deps': [] }
add_to_feat_cnf(feature, key[1]) add_to_feat_cnf(feature, key[1])
# Add options matching custom_marlin.MY_OPTION to the pile # Add options matching custom_marlin.MY_OPTION to the pile
blab("========== Gather custom_marlin entries...") blab("========== Gather custom_marlin entries...")
for n in env.GetProjectOptions(): for n in env.GetProjectOptions():
key = n[0] key = n[0]
mat = re.match(r'custom_marlin\.(.+)', key) mat = re.match(r'custom_marlin\.(.+)', key)
if mat: if mat:
try: try:
val = env.GetProjectOption(key) val = env.GetProjectOption(key)
except: except:
val = None val = None
if val: if val:
opt = mat[1].upper() opt = mat[1].upper()
blab("%s.custom_marlin.%s = '%s'" % ( env['PIOENV'], opt, val )) blab("%s.custom_marlin.%s = '%s'" % ( env['PIOENV'], opt, val ))
add_to_feat_cnf(opt, val) add_to_feat_cnf(opt, val)
def get_all_known_libs(): def get_all_known_libs():
known_libs = [] known_libs = []
for feature in FEATURE_CONFIG: for feature in FEATURE_CONFIG:
feat = FEATURE_CONFIG[feature] feat = FEATURE_CONFIG[feature]
if not 'lib_deps' in feat: if not 'lib_deps' in feat:
continue continue
for dep in feat['lib_deps']: for dep in feat['lib_deps']:
known_libs.append(PackageSpec(dep).name) known_libs.append(PackageSpec(dep).name)
return known_libs return known_libs
def get_all_env_libs(): def get_all_env_libs():
env_libs = [] env_libs = []
lib_deps = env.GetProjectOption('lib_deps') lib_deps = env.GetProjectOption('lib_deps')
for dep in lib_deps: for dep in lib_deps:
env_libs.append(PackageSpec(dep).name) env_libs.append(PackageSpec(dep).name)
return env_libs return env_libs
def set_env_field(field, value): def set_env_field(field, value):
proj = env.GetProjectConfig() proj = env.GetProjectConfig()
proj.set("env:" + env['PIOENV'], field, value) proj.set("env:" + env['PIOENV'], field, value)
# All unused libs should be ignored so that if a library # All unused libs should be ignored so that if a library
# exists in .pio/lib_deps it will not break compilation. # exists in .pio/lib_deps it will not break compilation.
def force_ignore_unused_libs(): def force_ignore_unused_libs():
env_libs = get_all_env_libs() env_libs = get_all_env_libs()
known_libs = get_all_known_libs() known_libs = get_all_known_libs()
diff = (list(set(known_libs) - set(env_libs))) diff = (list(set(known_libs) - set(env_libs)))
lib_ignore = env.GetProjectOption('lib_ignore') + diff lib_ignore = env.GetProjectOption('lib_ignore') + diff
blab("Ignore libraries: %s" % lib_ignore) blab("Ignore libraries: %s" % lib_ignore)
set_env_field('lib_ignore', lib_ignore) set_env_field('lib_ignore', lib_ignore)
def apply_features_config(): def apply_features_config():
load_features() load_features()
blab("========== Apply enabled features...") blab("========== Apply enabled features...")
for feature in FEATURE_CONFIG: for feature in FEATURE_CONFIG:
if not env.MarlinHas(feature): if not env.MarlinHas(feature):
continue continue
feat = FEATURE_CONFIG[feature] feat = FEATURE_CONFIG[feature]
if 'lib_deps' in feat and len(feat['lib_deps']): if 'lib_deps' in feat and len(feat['lib_deps']):
blab("========== Adding lib_deps for %s... " % feature, 2) blab("========== Adding lib_deps for %s... " % feature, 2)
# feat to add # feat to add
deps_to_add = {} deps_to_add = {}
for dep in feat['lib_deps']: for dep in feat['lib_deps']:
deps_to_add[PackageSpec(dep).name] = dep deps_to_add[PackageSpec(dep).name] = dep
blab("==================== %s... " % dep, 2) blab("==================== %s... " % dep, 2)
# Does the env already have the dependency? # Does the env already have the dependency?
deps = env.GetProjectOption('lib_deps') deps = env.GetProjectOption('lib_deps')
for dep in deps: for dep in deps:
name = PackageSpec(dep).name name = PackageSpec(dep).name
if name in deps_to_add: if name in deps_to_add:
del deps_to_add[name] del deps_to_add[name]
# Are there any libraries that should be ignored? # Are there any libraries that should be ignored?
lib_ignore = env.GetProjectOption('lib_ignore') lib_ignore = env.GetProjectOption('lib_ignore')
for dep in deps: for dep in deps:
name = PackageSpec(dep).name name = PackageSpec(dep).name
if name in deps_to_add: if name in deps_to_add:
del deps_to_add[name] del deps_to_add[name]
# Is there anything left? # Is there anything left?
if len(deps_to_add) > 0: if len(deps_to_add) > 0:
# Only add the missing dependencies # Only add the missing dependencies
set_env_field('lib_deps', deps + list(deps_to_add.values())) set_env_field('lib_deps', deps + list(deps_to_add.values()))
if 'build_flags' in feat: if 'build_flags' in feat:
f = feat['build_flags'] f = feat['build_flags']
blab("========== Adding build_flags for %s: %s" % (feature, f), 2) blab("========== Adding build_flags for %s: %s" % (feature, f), 2)
new_flags = env.GetProjectOption('build_flags') + [ f ] new_flags = env.GetProjectOption('build_flags') + [ f ]
env.Replace(BUILD_FLAGS=new_flags) env.Replace(BUILD_FLAGS=new_flags)
if 'extra_scripts' in feat: if 'extra_scripts' in feat:
blab("Running extra_scripts for %s... " % feature, 2) blab("Running extra_scripts for %s... " % feature, 2)
env.SConscript(feat['extra_scripts'], exports="env") env.SConscript(feat['extra_scripts'], exports="env")
if 'src_filter' in feat: if 'src_filter' in feat:
blab("========== Adding build_src_filter for %s... " % feature, 2) blab("========== Adding build_src_filter for %s... " % feature, 2)
src_filter = ' '.join(env.GetProjectOption('src_filter')) src_filter = ' '.join(env.GetProjectOption('src_filter'))
# first we need to remove the references to the same folder # first we need to remove the references to the same folder
my_srcs = re.findall(r'[+-](<.*?>)', feat['src_filter']) my_srcs = re.findall(r'[+-](<.*?>)', feat['src_filter'])
cur_srcs = re.findall(r'[+-](<.*?>)', src_filter) cur_srcs = re.findall(r'[+-](<.*?>)', src_filter)
for d in my_srcs: for d in my_srcs:
if d in cur_srcs: if d in cur_srcs:
src_filter = re.sub(r'[+-]' + d, '', src_filter) src_filter = re.sub(r'[+-]' + d, '', src_filter)
src_filter = feat['src_filter'] + ' ' + src_filter src_filter = feat['src_filter'] + ' ' + src_filter
set_env_field('build_src_filter', [src_filter]) set_env_field('build_src_filter', [src_filter])
env.Replace(SRC_FILTER=src_filter) env.Replace(SRC_FILTER=src_filter)
if 'lib_ignore' in feat: if 'lib_ignore' in feat:
blab("========== Adding lib_ignore for %s... " % feature, 2) blab("========== Adding lib_ignore for %s... " % feature, 2)
lib_ignore = env.GetProjectOption('lib_ignore') + [feat['lib_ignore']] lib_ignore = env.GetProjectOption('lib_ignore') + [feat['lib_ignore']]
set_env_field('lib_ignore', lib_ignore) set_env_field('lib_ignore', lib_ignore)
# #
# Use the compiler to get a list of all enabled features # Use the compiler to get a list of all enabled features
# #
def load_marlin_features(): def load_marlin_features():
if 'MARLIN_FEATURES' in env: if 'MARLIN_FEATURES' in env:
return return
# Process defines # Process defines
from preprocessor import run_preprocessor from preprocessor import run_preprocessor
define_list = run_preprocessor(env) define_list = run_preprocessor(env)
marlin_features = {} marlin_features = {}
for define in define_list: for define in define_list:
feature = define[8:].strip().decode().split(' ') feature = define[8:].strip().decode().split(' ')
feature, definition = feature[0], ' '.join(feature[1:]) feature, definition = feature[0], ' '.join(feature[1:])
marlin_features[feature] = definition marlin_features[feature] = definition
env['MARLIN_FEATURES'] = marlin_features env['MARLIN_FEATURES'] = marlin_features
# #
# Return True if a matching feature is enabled # Return True if a matching feature is enabled
# #
def MarlinHas(env, feature): def MarlinHas(env, feature):
load_marlin_features() load_marlin_features()
r = re.compile('^' + feature + '$') r = re.compile('^' + feature + '$')
found = list(filter(r.match, env['MARLIN_FEATURES'])) found = list(filter(r.match, env['MARLIN_FEATURES']))
# Defines could still be 'false' or '0', so check # Defines could still be 'false' or '0', so check
some_on = False some_on = False
if len(found): if len(found):
for f in found: for f in found:
val = env['MARLIN_FEATURES'][f] val = env['MARLIN_FEATURES'][f]
if val in [ '', '1', 'true' ]: if val in [ '', '1', 'true' ]:
some_on = True some_on = True
elif val in env['MARLIN_FEATURES']: elif val in env['MARLIN_FEATURES']:
some_on = env.MarlinHas(val) some_on = env.MarlinHas(val)
return some_on return some_on
validate_pio() validate_pio()
try: try:
verbose = int(env.GetProjectOption('custom_verbose')) verbose = int(env.GetProjectOption('custom_verbose'))
except: except:
pass pass
# #
# Add a method for other PIO scripts to query enabled features # Add a method for other PIO scripts to query enabled features
# #
env.AddMethod(MarlinHas) env.AddMethod(MarlinHas)
# #
# Add dependencies for enabled Marlin features # Add dependencies for enabled Marlin features
# #
apply_features_config() apply_features_config()
force_ignore_unused_libs() force_ignore_unused_libs()
#print(env.Dump()) #print(env.Dump())
from signature import compute_build_signature from signature import compute_build_signature
compute_build_signature(env) compute_build_signature(env)

396
buildroot/share/PlatformIO/scripts/configuration.py

@ -7,233 +7,229 @@ from pathlib import Path
verbose = 0 verbose = 0
def blab(str,level=1): def blab(str,level=1):
if verbose >= level: print(f"[config] {str}") if verbose >= level: print(f"[config] {str}")
def config_path(cpath): def config_path(cpath):
return Path("Marlin", cpath) return Path("Marlin", cpath)
# Apply a single name = on/off ; name = value ; etc. # Apply a single name = on/off ; name = value ; etc.
# TODO: Limit to the given (optional) configuration # TODO: Limit to the given (optional) configuration
def apply_opt(name, val, conf=None): def apply_opt(name, val, conf=None):
if name == "lcd": name, val = val, "on" if name == "lcd": name, val = val, "on"
# Create a regex to match the option and capture parts of the line # Create a regex to match the option and capture parts of the line
regex = re.compile(rf'^(\s*)(//\s*)?(#define\s+)({name}\b)(\s*)(.*?)(\s*)(//.*)?$', re.IGNORECASE) regex = re.compile(rf'^(\s*)(//\s*)?(#define\s+)({name}\b)(\s*)(.*?)(\s*)(//.*)?$', re.IGNORECASE)
# Find and enable and/or update all matches # Find and enable and/or update all matches
for file in ("Configuration.h", "Configuration_adv.h"): for file in ("Configuration.h", "Configuration_adv.h"):
fullpath = config_path(file) fullpath = config_path(file)
lines = fullpath.read_text().split('\n') lines = fullpath.read_text().split('\n')
found = False found = False
for i in range(len(lines)): for i in range(len(lines)):
line = lines[i] line = lines[i]
match = regex.match(line) match = regex.match(line)
if match and match[4].upper() == name.upper(): if match and match[4].upper() == name.upper():
found = True found = True
# For boolean options un/comment the define # For boolean options un/comment the define
if val in ("on", "", None): if val in ("on", "", None):
newline = re.sub(r'^(\s*)//+\s*(#define)(\s{1,3})?(\s*)', r'\1\2 \4', line) newline = re.sub(r'^(\s*)//+\s*(#define)(\s{1,3})?(\s*)', r'\1\2 \4', line)
elif val == "off": elif val == "off":
newline = re.sub(r'^(\s*)(#define)(\s{1,3})?(\s*)', r'\1//\2 \4', line) newline = re.sub(r'^(\s*)(#define)(\s{1,3})?(\s*)', r'\1//\2 \4', line)
else: else:
# For options with values, enable and set the value # For options with values, enable and set the value
newline = match[1] + match[3] + match[4] + match[5] + val newline = match[1] + match[3] + match[4] + match[5] + val
if match[8]: if match[8]:
sp = match[7] if match[7] else ' ' sp = match[7] if match[7] else ' '
newline += sp + match[8] newline += sp + match[8]
lines[i] = newline lines[i] = newline
blab(f"Set {name} to {val}") blab(f"Set {name} to {val}")
# If the option was found, write the modified lines # If the option was found, write the modified lines
if found: if found:
fullpath.write_text('\n'.join(lines)) fullpath.write_text('\n'.join(lines))
break break
# If the option didn't appear in either config file, add it # If the option didn't appear in either config file, add it
if not found: if not found:
# OFF options are added as disabled items so they appear # OFF options are added as disabled items so they appear
# in config dumps. Useful for custom settings. # in config dumps. Useful for custom settings.
prefix = "" prefix = ""
if val == "off": if val == "off":
prefix, val = "//", "" # Item doesn't appear in config dump prefix, val = "//", "" # Item doesn't appear in config dump
#val = "false" # Item appears in config dump #val = "false" # Item appears in config dump
# Uppercase the option unless already mixed/uppercase # Uppercase the option unless already mixed/uppercase
added = name.upper() if name.islower() else name added = name.upper() if name.islower() else name
# Add the provided value after the name # Add the provided value after the name
if val != "on" and val != "" and val is not None: if val != "on" and val != "" and val is not None:
added += " " + val added += " " + val
# Prepend the new option after the first set of #define lines # Prepend the new option after the first set of #define lines
fullpath = config_path("Configuration.h") fullpath = config_path("Configuration.h")
with fullpath.open() as f: with fullpath.open() as f:
lines = f.readlines() lines = f.readlines()
linenum = 0 linenum = 0
gotdef = False gotdef = False
for line in lines: for line in lines:
isdef = line.startswith("#define") isdef = line.startswith("#define")
if not gotdef: if not gotdef:
gotdef = isdef gotdef = isdef
elif not isdef: elif not isdef:
break break
linenum += 1 linenum += 1
lines.insert(linenum, f"{prefix}#define {added} // Added by config.ini\n") lines.insert(linenum, f"{prefix}#define {added} // Added by config.ini\n")
fullpath.write_text('\n'.join(lines)) fullpath.write_text('\n'.join(lines))
# Fetch configuration files from GitHub given the path. # Fetch configuration files from GitHub given the path.
# Return True if any files were fetched. # Return True if any files were fetched.
def fetch_example(path): def fetch_example(url):
if path.endswith("/"): if url.endswith("/"): url = url[:-1]
path = path[:-1] if url.startswith('http'):
url = url.replace("%", "%25").replace(" ", "%20")
if '@' in path: else:
path, brch = map(strip, path.split('@')) brch = "bugfix-2.1.x"
if '@' in path: path, brch = map(str.strip, path.split('@'))
url = path.replace("%", "%25").replace(" ", "%20") url = f"https://raw.githubusercontent.com/MarlinFirmware/Configurations/{brch}/config/{url}"
if not path.startswith('http'):
url = "https://raw.githubusercontent.com/MarlinFirmware/Configurations/bugfix-2.1.x/config/%s" % url # Find a suitable fetch command
if shutil.which("curl") is not None:
# Find a suitable fetch command fetch = "curl -L -s -S -f -o"
if shutil.which("curl") is not None: elif shutil.which("wget") is not None:
fetch = "curl -L -s -S -f -o" fetch = "wget -q -O"
elif shutil.which("wget") is not None: else:
fetch = "wget -q -O" blab("Couldn't find curl or wget", -1)
else: return False
blab("Couldn't find curl or wget", -1)
return False import os
import os # Reset configurations to default
os.system("git reset --hard HEAD")
# Reset configurations to default
os.system("git reset --hard HEAD") # Try to fetch the remote files
gotfile = False
gotfile = False for fn in ("Configuration.h", "Configuration_adv.h", "_Bootscreen.h", "_Statusscreen.h"):
if os.system(f"{fetch} wgot {url}/{fn} >/dev/null 2>&1") == 0:
# Try to fetch the remote files shutil.move('wgot', config_path(fn))
for fn in ("Configuration.h", "Configuration_adv.h", "_Bootscreen.h", "_Statusscreen.h"): gotfile = True
if os.system("%s wgot %s/%s >/dev/null 2>&1" % (fetch, url, fn)) == 0:
shutil.move('wgot', config_path(fn)) if Path('wgot').exists(): shutil.rmtree('wgot')
gotfile = True
return gotfile
if Path('wgot').exists():
shutil.rmtree('wgot')
return gotfile
def section_items(cp, sectkey): def section_items(cp, sectkey):
return cp.items(sectkey) if sectkey in cp.sections() else [] return cp.items(sectkey) if sectkey in cp.sections() else []
# Apply all items from a config section # Apply all items from a config section
def apply_ini_by_name(cp, sect): def apply_ini_by_name(cp, sect):
iniok = True iniok = True
if sect in ('config:base', 'config:root'): if sect in ('config:base', 'config:root'):
iniok = False iniok = False
items = section_items(cp, 'config:base') + section_items(cp, 'config:root') items = section_items(cp, 'config:base') + section_items(cp, 'config:root')
else: else:
items = cp.items(sect) items = cp.items(sect)
for item in items: for item in items:
if iniok or not item[0].startswith('ini_'): if iniok or not item[0].startswith('ini_'):
apply_opt(item[0], item[1]) apply_opt(item[0], item[1])
# Apply all config sections from a parsed file # Apply all config sections from a parsed file
def apply_all_sections(cp): def apply_all_sections(cp):
for sect in cp.sections(): for sect in cp.sections():
if sect.startswith('config:'): if sect.startswith('config:'):
apply_ini_by_name(cp, sect) apply_ini_by_name(cp, sect)
# Apply certain config sections from a parsed file # Apply certain config sections from a parsed file
def apply_sections(cp, ckey='all', addbase=False): def apply_sections(cp, ckey='all'):
blab("[config] apply section key: %s" % ckey) blab(f"Apply section key: {ckey}")
if ckey == 'all': if ckey == 'all':
apply_all_sections(cp) apply_all_sections(cp)
else: else:
# Apply the base/root config.ini settings after external files are done # Apply the base/root config.ini settings after external files are done
if addbase or ckey in ('base', 'root'): if ckey in ('base', 'root'):
apply_ini_by_name(cp, 'config:base') apply_ini_by_name(cp, 'config:base')
# Apply historically 'Configuration.h' settings everywhere # Apply historically 'Configuration.h' settings everywhere
if ckey == 'basic': if ckey == 'basic':
apply_ini_by_name(cp, 'config:basic') apply_ini_by_name(cp, 'config:basic')
# Apply historically Configuration_adv.h settings everywhere # Apply historically Configuration_adv.h settings everywhere
# (Some of which rely on defines in 'Conditionals_LCD.h') # (Some of which rely on defines in 'Conditionals_LCD.h')
elif ckey in ('adv', 'advanced'): elif ckey in ('adv', 'advanced'):
apply_ini_by_name(cp, 'config:advanced') apply_ini_by_name(cp, 'config:advanced')
# Apply a specific config:<name> section directly # Apply a specific config:<name> section directly
elif ckey.startswith('config:'): elif ckey.startswith('config:'):
apply_ini_by_name(cp, ckey) apply_ini_by_name(cp, ckey)
# Apply settings from a top level config.ini # Apply settings from a top level config.ini
def apply_config_ini(cp): def apply_config_ini(cp):
blab("=" * 20 + " Gather 'config.ini' entries...") blab("=" * 20 + " Gather 'config.ini' entries...")
# Pre-scan for ini_use_config to get config_keys # Pre-scan for ini_use_config to get config_keys
base_items = section_items(cp, 'config:base') + section_items(cp, 'config:root') base_items = section_items(cp, 'config:base') + section_items(cp, 'config:root')
config_keys = ['base'] config_keys = ['base']
for ikey, ival in base_items: for ikey, ival in base_items:
if ikey == 'ini_use_config': if ikey == 'ini_use_config':
config_keys = [ x.strip() for x in ival.split(',') ] config_keys = map(str.strip, ival.split(','))
# For each ini_use_config item perform an action # For each ini_use_config item perform an action
for ckey in config_keys: for ckey in config_keys:
addbase = False addbase = False
# For a key ending in .ini load and parse another .ini file # For a key ending in .ini load and parse another .ini file
if ckey.endswith('.ini'): if ckey.endswith('.ini'):
sect = 'base' sect = 'base'
if '@' in ckey: sect, ckey = ckey.split('@') if '@' in ckey: sect, ckey = ckey.split('@')
other_ini = configparser.ConfigParser() other_ini = configparser.ConfigParser()
other_ini.read(config_path(ckey)) other_ini.read(config_path(ckey))
apply_sections(other_ini, sect) apply_sections(other_ini, sect)
# (Allow 'example/' as a shortcut for 'examples/') # (Allow 'example/' as a shortcut for 'examples/')
elif ckey.startswith('example/'): elif ckey.startswith('example/'):
ckey = 'examples' + ckey[7:] ckey = 'examples' + ckey[7:]
# For 'examples/<path>' fetch an example set from GitHub. # For 'examples/<path>' fetch an example set from GitHub.
# For https?:// do a direct fetch of the URL. # For https?:// do a direct fetch of the URL.
elif ckey.startswith('examples/') or ckey.startswith('http'): elif ckey.startswith('examples/') or ckey.startswith('http'):
addbase = True fetch_example(ckey)
fetch_example(ckey) ckey = 'base'
# Apply keyed sections after external files are done # Apply keyed sections after external files are done
apply_sections(cp, 'config:' + ckey, addbase) apply_sections(cp, 'config:' + ckey)
if __name__ == "__main__": if __name__ == "__main__":
# #
# From command line use the given file name # From command line use the given file name
# #
import sys import sys
args = sys.argv[1:] args = sys.argv[1:]
if len(args) > 0: if len(args) > 0:
if args[0].endswith('.ini'): if args[0].endswith('.ini'):
ini_file = args[0] ini_file = args[0]
else: else:
print("Usage: %s <.ini file>" % sys.argv[0]) print("Usage: %s <.ini file>" % sys.argv[0])
else: else:
ini_file = config_path('config.ini') ini_file = config_path('config.ini')
if ini_file: if ini_file:
user_ini = configparser.ConfigParser() user_ini = configparser.ConfigParser()
user_ini.read(ini_file) user_ini.read(ini_file)
apply_config_ini(user_ini) apply_config_ini(user_ini)
else: else:
# #
# From within PlatformIO use the loaded INI file # From within PlatformIO use the loaded INI file
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
Import("env") Import("env")
try: try:
verbose = int(env.GetProjectOption('custom_verbose')) verbose = int(env.GetProjectOption('custom_verbose'))
except: except:
pass pass
from platformio.project.config import ProjectConfig from platformio.project.config import ProjectConfig
apply_config_ini(ProjectConfig()) apply_config_ini(ProjectConfig())

16
buildroot/share/PlatformIO/scripts/custom_board.py

@ -6,13 +6,13 @@
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
import marlin import marlin
board = marlin.env.BoardConfig() board = marlin.env.BoardConfig()
address = board.get("build.address", "") address = board.get("build.address", "")
if address: if address:
marlin.relocate_firmware(address) marlin.relocate_firmware(address)
ldscript = board.get("build.ldscript", "") ldscript = board.get("build.ldscript", "")
if ldscript: if ldscript:
marlin.custom_ld_script(ldscript) marlin.custom_ld_script(ldscript)

84
buildroot/share/PlatformIO/scripts/download_mks_assets.py

@ -4,50 +4,50 @@
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
Import("env") Import("env")
import requests,zipfile,tempfile,shutil import requests,zipfile,tempfile,shutil
from pathlib import Path from pathlib import Path
url = "https://github.com/makerbase-mks/Mks-Robin-Nano-Marlin2.0-Firmware/archive/0263cdaccf.zip" url = "https://github.com/makerbase-mks/Mks-Robin-Nano-Marlin2.0-Firmware/archive/0263cdaccf.zip"
deps_path = Path(env.Dictionary("PROJECT_LIBDEPS_DIR")) deps_path = Path(env.Dictionary("PROJECT_LIBDEPS_DIR"))
zip_path = deps_path / "mks-assets.zip" zip_path = deps_path / "mks-assets.zip"
assets_path = Path(env.Dictionary("PROJECT_BUILD_DIR"), env.Dictionary("PIOENV"), "assets") assets_path = Path(env.Dictionary("PROJECT_BUILD_DIR"), env.Dictionary("PIOENV"), "assets")
def download_mks_assets(): def download_mks_assets():
print("Downloading MKS Assets") print("Downloading MKS Assets")
r = requests.get(url, stream=True) r = requests.get(url, stream=True)
# the user may have a very clean workspace, # the user may have a very clean workspace,
# so create the PROJECT_LIBDEPS_DIR directory if not exits # so create the PROJECT_LIBDEPS_DIR directory if not exits
if not deps_path.exists(): if not deps_path.exists():
deps_path.mkdir() deps_path.mkdir()
with zip_path.open('wb') as fd: with zip_path.open('wb') as fd:
for chunk in r.iter_content(chunk_size=128): for chunk in r.iter_content(chunk_size=128):
fd.write(chunk) fd.write(chunk)
def copy_mks_assets(): def copy_mks_assets():
print("Copying MKS Assets") print("Copying MKS Assets")
output_path = Path(tempfile.mkdtemp()) output_path = Path(tempfile.mkdtemp())
zip_obj = zipfile.ZipFile(zip_path, 'r') zip_obj = zipfile.ZipFile(zip_path, 'r')
zip_obj.extractall(output_path) zip_obj.extractall(output_path)
zip_obj.close() zip_obj.close()
if assets_path.exists() and not assets_path.is_dir(): if assets_path.exists() and not assets_path.is_dir():
assets_path.unlink() assets_path.unlink()
if not assets_path.exists(): if not assets_path.exists():
assets_path.mkdir() assets_path.mkdir()
base_path = '' base_path = ''
for filename in output_path.iterdir(): for filename in output_path.iterdir():
base_path = filename base_path = filename
fw_path = (output_path / base_path / 'Firmware') fw_path = (output_path / base_path / 'Firmware')
font_path = fw_path / 'mks_font' font_path = fw_path / 'mks_font'
for filename in font_path.iterdir(): for filename in font_path.iterdir():
shutil.copy(font_path / filename, assets_path) shutil.copy(font_path / filename, assets_path)
pic_path = fw_path / 'mks_pic' pic_path = fw_path / 'mks_pic'
for filename in pic_path.iterdir(): for filename in pic_path.iterdir():
shutil.copy(pic_path / filename, assets_path) shutil.copy(pic_path / filename, assets_path)
shutil.rmtree(output_path, ignore_errors=True) shutil.rmtree(output_path, ignore_errors=True)
if not zip_path.exists(): if not zip_path.exists():
download_mks_assets() download_mks_assets()
if not assets_path.exists(): if not assets_path.exists():
copy_mks_assets() copy_mks_assets()

44
buildroot/share/PlatformIO/scripts/fix_framework_weakness.py

@ -4,32 +4,32 @@
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
import shutil import shutil
from os.path import join, isfile from os.path import join, isfile
from pprint import pprint from pprint import pprint
Import("env") Import("env")
if env.MarlinHas("POSTMORTEM_DEBUGGING"): if env.MarlinHas("POSTMORTEM_DEBUGGING"):
FRAMEWORK_DIR = env.PioPlatform().get_package_dir("framework-arduinoststm32-maple") FRAMEWORK_DIR = env.PioPlatform().get_package_dir("framework-arduinoststm32-maple")
patchflag_path = join(FRAMEWORK_DIR, ".exc-patching-done") patchflag_path = join(FRAMEWORK_DIR, ".exc-patching-done")
# patch file only if we didn't do it before # patch file only if we didn't do it before
if not isfile(patchflag_path): if not isfile(patchflag_path):
print("Patching libmaple exception handlers") print("Patching libmaple exception handlers")
original_file = join(FRAMEWORK_DIR, "STM32F1", "cores", "maple", "libmaple", "exc.S") original_file = join(FRAMEWORK_DIR, "STM32F1", "cores", "maple", "libmaple", "exc.S")
backup_file = join(FRAMEWORK_DIR, "STM32F1", "cores", "maple", "libmaple", "exc.S.bak") backup_file = join(FRAMEWORK_DIR, "STM32F1", "cores", "maple", "libmaple", "exc.S.bak")
src_file = join("buildroot", "share", "PlatformIO", "scripts", "exc.S") src_file = join("buildroot", "share", "PlatformIO", "scripts", "exc.S")
assert isfile(original_file) and isfile(src_file) assert isfile(original_file) and isfile(src_file)
shutil.copyfile(original_file, backup_file) shutil.copyfile(original_file, backup_file)
shutil.copyfile(src_file, original_file); shutil.copyfile(src_file, original_file);
def _touch(path): def _touch(path):
with open(path, "w") as fp: with open(path, "w") as fp:
fp.write("") fp.write("")
env.Execute(lambda *args, **kwargs: _touch(patchflag_path)) env.Execute(lambda *args, **kwargs: _touch(patchflag_path))
print("Done patching exception handler") print("Done patching exception handler")
print("Libmaple modified and ready for post mortem debugging") print("Libmaple modified and ready for post mortem debugging")

98
buildroot/share/PlatformIO/scripts/generic_create_variant.py

@ -7,52 +7,52 @@
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
import shutil,marlin import shutil,marlin
from pathlib import Path from pathlib import Path
# #
# Get the platform name from the 'platform_packages' option, # Get the platform name from the 'platform_packages' option,
# or look it up by the platform.class.name. # or look it up by the platform.class.name.
# #
env = marlin.env env = marlin.env
platform = env.PioPlatform() platform = env.PioPlatform()
from platformio.package.meta import PackageSpec from platformio.package.meta import PackageSpec
platform_packages = env.GetProjectOption('platform_packages') platform_packages = env.GetProjectOption('platform_packages')
# Remove all tool items from platform_packages # Remove all tool items from platform_packages
platform_packages = [x for x in platform_packages if not x.startswith("platformio/tool-")] platform_packages = [x for x in platform_packages if not x.startswith("platformio/tool-")]
if len(platform_packages) == 0: if len(platform_packages) == 0:
framewords = { framewords = {
"Ststm32Platform": "framework-arduinoststm32", "Ststm32Platform": "framework-arduinoststm32",
"AtmelavrPlatform": "framework-arduino-avr" "AtmelavrPlatform": "framework-arduino-avr"
} }
platform_name = framewords[platform.__class__.__name__] platform_name = framewords[platform.__class__.__name__]
else: else:
platform_name = PackageSpec(platform_packages[0]).name platform_name = PackageSpec(platform_packages[0]).name
if platform_name in [ "usb-host-msc", "usb-host-msc-cdc-msc", "usb-host-msc-cdc-msc-2", "usb-host-msc-cdc-msc-3", "tool-stm32duino", "biqu-bx-workaround", "main" ]: if platform_name in [ "usb-host-msc", "usb-host-msc-cdc-msc", "usb-host-msc-cdc-msc-2", "usb-host-msc-cdc-msc-3", "tool-stm32duino", "biqu-bx-workaround", "main" ]:
platform_name = "framework-arduinoststm32" platform_name = "framework-arduinoststm32"
FRAMEWORK_DIR = Path(platform.get_package_dir(platform_name)) FRAMEWORK_DIR = Path(platform.get_package_dir(platform_name))
assert FRAMEWORK_DIR.is_dir() assert FRAMEWORK_DIR.is_dir()
board = env.BoardConfig() board = env.BoardConfig()
#mcu_type = board.get("build.mcu")[:-2] #mcu_type = board.get("build.mcu")[:-2]
variant = board.get("build.variant") variant = board.get("build.variant")
#series = mcu_type[:7].upper() + "xx" #series = mcu_type[:7].upper() + "xx"
# Prepare a new empty folder at the destination # Prepare a new empty folder at the destination
variant_dir = FRAMEWORK_DIR / "variants" / variant variant_dir = FRAMEWORK_DIR / "variants" / variant
if variant_dir.is_dir(): if variant_dir.is_dir():
shutil.rmtree(variant_dir) shutil.rmtree(variant_dir)
if not variant_dir.is_dir(): if not variant_dir.is_dir():
variant_dir.mkdir() variant_dir.mkdir()
# Source dir is a local variant sub-folder # Source dir is a local variant sub-folder
source_dir = Path("buildroot/share/PlatformIO/variants", variant) source_dir = Path("buildroot/share/PlatformIO/variants", variant)
assert source_dir.is_dir() assert source_dir.is_dir()
marlin.copytree(source_dir, variant_dir) marlin.copytree(source_dir, variant_dir)

46
buildroot/share/PlatformIO/scripts/jgaurora_a5s_a1_with_bootloader.py

@ -5,31 +5,31 @@
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
# Append ${PROGNAME}.bin firmware after bootloader and save it as 'jgaurora_firmware.bin' # Append ${PROGNAME}.bin firmware after bootloader and save it as 'jgaurora_firmware.bin'
def addboot(source, target, env): def addboot(source, target, env):
from pathlib import Path from pathlib import Path
fw_path = Path(target[0].path) fw_path = Path(target[0].path)
fwb_path = fw_path.parent / 'firmware_with_bootloader.bin' fwb_path = fw_path.parent / 'firmware_with_bootloader.bin'
with fwb_path.open("wb") as fwb_file: with fwb_path.open("wb") as fwb_file:
bl_path = Path("buildroot/share/PlatformIO/scripts/jgaurora_bootloader.bin") bl_path = Path("buildroot/share/PlatformIO/scripts/jgaurora_bootloader.bin")
bl_file = bl_path.open("rb") bl_file = bl_path.open("rb")
while True: while True:
b = bl_file.read(1) b = bl_file.read(1)
if b == b'': break if b == b'': break
else: fwb_file.write(b) else: fwb_file.write(b)
with fw_path.open("rb") as fw_file: with fw_path.open("rb") as fw_file:
while True: while True:
b = fw_file.read(1) b = fw_file.read(1)
if b == b'': break if b == b'': break
else: fwb_file.write(b) else: fwb_file.write(b)
fws_path = Path(target[0].dir.path, 'firmware_for_sd_upload.bin') fws_path = Path(target[0].dir.path, 'firmware_for_sd_upload.bin')
if fws_path.exists(): if fws_path.exists():
fws_path.unlink() fws_path.unlink()
fw_path.rename(fws_path) fw_path.rename(fws_path)
import marlin import marlin
marlin.add_post_action(addboot); marlin.add_post_action(addboot);

62
buildroot/share/PlatformIO/scripts/lerdge.py

@ -7,41 +7,41 @@
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
import os,marlin import os,marlin
board = marlin.env.BoardConfig() board = marlin.env.BoardConfig()
def encryptByte(byte): def encryptByte(byte):
byte = 0xFF & ((byte << 6) | (byte >> 2)) byte = 0xFF & ((byte << 6) | (byte >> 2))
i = 0x58 + byte i = 0x58 + byte
j = 0x05 + byte + (i >> 8) j = 0x05 + byte + (i >> 8)
byte = (0xF8 & i) | (0x07 & j) byte = (0xF8 & i) | (0x07 & j)
return byte return byte
def encrypt_file(input, output_file, file_length): def encrypt_file(input, output_file, file_length):
input_file = bytearray(input.read()) input_file = bytearray(input.read())
for i in range(len(input_file)): for i in range(len(input_file)):
input_file[i] = encryptByte(input_file[i]) input_file[i] = encryptByte(input_file[i])
output_file.write(input_file) output_file.write(input_file)
# Encrypt ${PROGNAME}.bin and save it with the name given in build.crypt_lerdge # Encrypt ${PROGNAME}.bin and save it with the name given in build.crypt_lerdge
def encrypt(source, target, env): def encrypt(source, target, env):
fwpath = target[0].path fwpath = target[0].path
enname = board.get("build.crypt_lerdge") enname = board.get("build.crypt_lerdge")
print("Encrypting %s to %s" % (fwpath, enname)) print("Encrypting %s to %s" % (fwpath, enname))
fwfile = open(fwpath, "rb") fwfile = open(fwpath, "rb")
enfile = open(target[0].dir.path + "/" + enname, "wb") enfile = open(target[0].dir.path + "/" + enname, "wb")
length = os.path.getsize(fwpath) length = os.path.getsize(fwpath)
encrypt_file(fwfile, enfile, length) encrypt_file(fwfile, enfile, length)
fwfile.close() fwfile.close()
enfile.close() enfile.close()
os.remove(fwpath) os.remove(fwpath)
if 'crypt_lerdge' in board.get("build").keys(): if 'crypt_lerdge' in board.get("build").keys():
if board.get("build.crypt_lerdge") != "": if board.get("build.crypt_lerdge") != "":
marlin.add_post_action(encrypt) marlin.add_post_action(encrypt)
else: else:
print("LERDGE builds require output file via board_build.crypt_lerdge = 'filename' parameter") print("LERDGE builds require output file via board_build.crypt_lerdge = 'filename' parameter")
exit(1) exit(1)

82
buildroot/share/PlatformIO/scripts/marlin.py

@ -9,64 +9,64 @@ from SCons.Script import DefaultEnvironment
env = DefaultEnvironment() env = DefaultEnvironment()
def copytree(src, dst, symlinks=False, ignore=None): def copytree(src, dst, symlinks=False, ignore=None):
for item in src.iterdir(): for item in src.iterdir():
if item.is_dir(): if item.is_dir():
shutil.copytree(item, dst / item.name, symlinks, ignore) shutil.copytree(item, dst / item.name, symlinks, ignore)
else: else:
shutil.copy2(item, dst / item.name) shutil.copy2(item, dst / item.name)
def replace_define(field, value): def replace_define(field, value):
for define in env['CPPDEFINES']: for define in env['CPPDEFINES']:
if define[0] == field: if define[0] == field:
env['CPPDEFINES'].remove(define) env['CPPDEFINES'].remove(define)
env['CPPDEFINES'].append((field, value)) env['CPPDEFINES'].append((field, value))
# Relocate the firmware to a new address, such as "0x08005000" # Relocate the firmware to a new address, such as "0x08005000"
def relocate_firmware(address): def relocate_firmware(address):
replace_define("VECT_TAB_ADDR", address) replace_define("VECT_TAB_ADDR", address)
# Relocate the vector table with a new offset # Relocate the vector table with a new offset
def relocate_vtab(address): def relocate_vtab(address):
replace_define("VECT_TAB_OFFSET", address) replace_define("VECT_TAB_OFFSET", address)
# Replace the existing -Wl,-T with the given ldscript path # Replace the existing -Wl,-T with the given ldscript path
def custom_ld_script(ldname): def custom_ld_script(ldname):
apath = str(Path("buildroot/share/PlatformIO/ldscripts", ldname).resolve()) apath = str(Path("buildroot/share/PlatformIO/ldscripts", ldname).resolve())
for i, flag in enumerate(env["LINKFLAGS"]): for i, flag in enumerate(env["LINKFLAGS"]):
if "-Wl,-T" in flag: if "-Wl,-T" in flag:
env["LINKFLAGS"][i] = "-Wl,-T" + apath env["LINKFLAGS"][i] = "-Wl,-T" + apath
elif flag == "-T": elif flag == "-T":
env["LINKFLAGS"][i + 1] = apath env["LINKFLAGS"][i + 1] = apath
# Encrypt ${PROGNAME}.bin and save it with a new name. This applies (mostly) to MKS boards # Encrypt ${PROGNAME}.bin and save it with a new name. This applies (mostly) to MKS boards
# This PostAction is set up by offset_and_rename.py for envs with 'build.encrypt_mks'. # This PostAction is set up by offset_and_rename.py for envs with 'build.encrypt_mks'.
def encrypt_mks(source, target, env, new_name): def encrypt_mks(source, target, env, new_name):
import sys import sys
key = [0xA3, 0xBD, 0xAD, 0x0D, 0x41, 0x11, 0xBB, 0x8D, 0xDC, 0x80, 0x2D, 0xD0, 0xD2, 0xC4, 0x9B, 0x1E, 0x26, 0xEB, 0xE3, 0x33, 0x4A, 0x15, 0xE4, 0x0A, 0xB3, 0xB1, 0x3C, 0x93, 0xBB, 0xAF, 0xF7, 0x3E] key = [0xA3, 0xBD, 0xAD, 0x0D, 0x41, 0x11, 0xBB, 0x8D, 0xDC, 0x80, 0x2D, 0xD0, 0xD2, 0xC4, 0x9B, 0x1E, 0x26, 0xEB, 0xE3, 0x33, 0x4A, 0x15, 0xE4, 0x0A, 0xB3, 0xB1, 0x3C, 0x93, 0xBB, 0xAF, 0xF7, 0x3E]
# If FIRMWARE_BIN is defined by config, override all # If FIRMWARE_BIN is defined by config, override all
mf = env["MARLIN_FEATURES"] mf = env["MARLIN_FEATURES"]
if "FIRMWARE_BIN" in mf: new_name = mf["FIRMWARE_BIN"] if "FIRMWARE_BIN" in mf: new_name = mf["FIRMWARE_BIN"]
fwpath = Path(target[0].path) fwpath = Path(target[0].path)
fwfile = fwpath.open("rb") fwfile = fwpath.open("rb")
enfile = Path(target[0].dir.path, new_name).open("wb") enfile = Path(target[0].dir.path, new_name).open("wb")
length = fwpath.stat().st_size length = fwpath.stat().st_size
position = 0 position = 0
try: try:
while position < length: while position < length:
byte = fwfile.read(1) byte = fwfile.read(1)
if 320 <= position < 31040: if 320 <= position < 31040:
byte = chr(ord(byte) ^ key[position & 31]) byte = chr(ord(byte) ^ key[position & 31])
if sys.version_info[0] > 2: if sys.version_info[0] > 2:
byte = bytes(byte, 'latin1') byte = bytes(byte, 'latin1')
enfile.write(byte) enfile.write(byte)
position += 1 position += 1
finally: finally:
fwfile.close() fwfile.close()
enfile.close() enfile.close()
fwpath.unlink() fwpath.unlink()
def add_post_action(action): def add_post_action(action):
env.AddPostAction(str(Path("$BUILD_DIR", "${PROGNAME}.bin")), action); env.AddPostAction(str(Path("$BUILD_DIR", "${PROGNAME}.bin")), action);

106
buildroot/share/PlatformIO/scripts/mc-apply.py

@ -11,59 +11,59 @@ opt_output = '--opt' in sys.argv
output_suffix = '.sh' if opt_output else '' if '--bare-output' in sys.argv else '.gen' output_suffix = '.sh' if opt_output else '' if '--bare-output' in sys.argv else '.gen'
try: try:
with open('marlin_config.json', 'r') as infile: with open('marlin_config.json', 'r') as infile:
conf = json.load(infile) conf = json.load(infile)
for key in conf: for key in conf:
# We don't care about the hash when restoring here # We don't care about the hash when restoring here
if key == '__INITIAL_HASH': if key == '__INITIAL_HASH':
continue continue
if key == 'VERSION': if key == 'VERSION':
for k, v in sorted(conf[key].items()): for k, v in sorted(conf[key].items()):
print(k + ': ' + v) print(k + ': ' + v)
continue continue
# The key is the file name, so let's build it now # The key is the file name, so let's build it now
outfile = open('Marlin/' + key + output_suffix, 'w') outfile = open('Marlin/' + key + output_suffix, 'w')
for k, v in sorted(conf[key].items()): for k, v in sorted(conf[key].items()):
# Make define line now # Make define line now
if opt_output: if opt_output:
if v != '': if v != '':
if '"' in v: if '"' in v:
v = "'%s'" % v v = "'%s'" % v
elif ' ' in v: elif ' ' in v:
v = '"%s"' % v v = '"%s"' % v
define = 'opt_set ' + k + ' ' + v + '\n' define = 'opt_set ' + k + ' ' + v + '\n'
else: else:
define = 'opt_enable ' + k + '\n' define = 'opt_enable ' + k + '\n'
else: else:
define = '#define ' + k + ' ' + v + '\n' define = '#define ' + k + ' ' + v + '\n'
outfile.write(define) outfile.write(define)
outfile.close() outfile.close()
# Try to apply changes to the actual configuration file (in order to keep useful comments) # Try to apply changes to the actual configuration file (in order to keep useful comments)
if output_suffix != '': if output_suffix != '':
# Move the existing configuration so it doesn't interfere # Move the existing configuration so it doesn't interfere
shutil.move('Marlin/' + key, 'Marlin/' + key + '.orig') shutil.move('Marlin/' + key, 'Marlin/' + key + '.orig')
infile_lines = open('Marlin/' + key + '.orig', 'r').read().split('\n') infile_lines = open('Marlin/' + key + '.orig', 'r').read().split('\n')
outfile = open('Marlin/' + key, 'w') outfile = open('Marlin/' + key, 'w')
for line in infile_lines: for line in infile_lines:
sline = line.strip(" \t\n\r") sline = line.strip(" \t\n\r")
if sline[:7] == "#define": if sline[:7] == "#define":
# Extract the key here (we don't care about the value) # Extract the key here (we don't care about the value)
kv = sline[8:].strip().split(' ') kv = sline[8:].strip().split(' ')
if kv[0] in conf[key]: if kv[0] in conf[key]:
outfile.write('#define ' + kv[0] + ' ' + conf[key][kv[0]] + '\n') outfile.write('#define ' + kv[0] + ' ' + conf[key][kv[0]] + '\n')
# Remove the key from the dict, so we can still write all missing keys at the end of the file # Remove the key from the dict, so we can still write all missing keys at the end of the file
del conf[key][kv[0]] del conf[key][kv[0]]
else: else:
outfile.write(line + '\n') outfile.write(line + '\n')
else: else:
outfile.write(line + '\n') outfile.write(line + '\n')
# Process any remaining defines here # Process any remaining defines here
for k, v in sorted(conf[key].items()): for k, v in sorted(conf[key].items()):
define = '#define ' + k + ' ' + v + '\n' define = '#define ' + k + ' ' + v + '\n'
outfile.write(define) outfile.write(define)
outfile.close() outfile.close()
print('Output configuration written to: ' + 'Marlin/' + key + output_suffix) print('Output configuration written to: ' + 'Marlin/' + key + output_suffix)
except: except:
print('No marlin_config.json found.') print('No marlin_config.json found.')

107
buildroot/share/PlatformIO/scripts/offset_and_rename.py

@ -2,59 +2,64 @@
# offset_and_rename.py # offset_and_rename.py
# #
# - If 'build.offset' is provided, either by JSON or by the environment... # - If 'build.offset' is provided, either by JSON or by the environment...
# - Set linker flag LD_FLASH_OFFSET and relocate the VTAB based on 'build.offset'. # - Set linker flag LD_FLASH_OFFSET and relocate the VTAB based on 'build.offset'.
# - Set linker flag LD_MAX_DATA_SIZE based on 'build.maximum_ram_size'. # - Set linker flag LD_MAX_DATA_SIZE based on 'build.maximum_ram_size'.
# - Define STM32_FLASH_SIZE from 'upload.maximum_size' for use by Flash-based EEPROM emulation. # - Define STM32_FLASH_SIZE from 'upload.maximum_size' for use by Flash-based EEPROM emulation.
# #
# - For 'board_build.rename' add a post-action to rename the firmware file. # - For 'board_build.rename' add a post-action to rename the firmware file.
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
import sys,marlin import sys,marlin
env = marlin.env env = marlin.env
board = env.BoardConfig() board = env.BoardConfig()
board_keys = board.get("build").keys() board_keys = board.get("build").keys()
# #
# For build.offset define LD_FLASH_OFFSET, used by ldscript.ld # For build.offset define LD_FLASH_OFFSET, used by ldscript.ld
# #
if 'offset' in board_keys: if 'offset' in board_keys:
LD_FLASH_OFFSET = board.get("build.offset") LD_FLASH_OFFSET = board.get("build.offset")
marlin.relocate_vtab(LD_FLASH_OFFSET) marlin.relocate_vtab(LD_FLASH_OFFSET)
# Flash size # Flash size
maximum_flash_size = int(board.get("upload.maximum_size") / 1024) maximum_flash_size = int(board.get("upload.maximum_size") / 1024)
marlin.replace_define('STM32_FLASH_SIZE', maximum_flash_size) marlin.replace_define('STM32_FLASH_SIZE', maximum_flash_size)
# Get upload.maximum_ram_size (defined by /buildroot/share/PlatformIO/boards/VARIOUS.json) # Get upload.maximum_ram_size (defined by /buildroot/share/PlatformIO/boards/VARIOUS.json)
maximum_ram_size = board.get("upload.maximum_ram_size") maximum_ram_size = board.get("upload.maximum_ram_size")
for i, flag in enumerate(env["LINKFLAGS"]): for i, flag in enumerate(env["LINKFLAGS"]):
if "-Wl,--defsym=LD_FLASH_OFFSET" in flag: if "-Wl,--defsym=LD_FLASH_OFFSET" in flag:
env["LINKFLAGS"][i] = "-Wl,--defsym=LD_FLASH_OFFSET=" + LD_FLASH_OFFSET env["LINKFLAGS"][i] = "-Wl,--defsym=LD_FLASH_OFFSET=" + LD_FLASH_OFFSET
if "-Wl,--defsym=LD_MAX_DATA_SIZE" in flag: if "-Wl,--defsym=LD_MAX_DATA_SIZE" in flag:
env["LINKFLAGS"][i] = "-Wl,--defsym=LD_MAX_DATA_SIZE=" + str(maximum_ram_size - 40) env["LINKFLAGS"][i] = "-Wl,--defsym=LD_MAX_DATA_SIZE=" + str(maximum_ram_size - 40)
# #
# For build.encrypt_mks rename and encode the firmware file. # For build.encrypt_mks rename and encode the firmware file.
# #
if 'encrypt_mks' in board_keys: if 'encrypt_mks' in board_keys:
# Encrypt ${PROGNAME}.bin and save it with the name given in build.encrypt_mks # Encrypt ${PROGNAME}.bin and save it with the name given in build.encrypt_mks
def encrypt(source, target, env): def encrypt(source, target, env):
marlin.encrypt_mks(source, target, env, board.get("build.encrypt_mks")) marlin.encrypt_mks(source, target, env, board.get("build.encrypt_mks"))
if board.get("build.encrypt_mks") != "": if board.get("build.encrypt_mks") != "":
marlin.add_post_action(encrypt) marlin.add_post_action(encrypt)
# #
# For build.rename simply rename the firmware file. # For build.rename simply rename the firmware file.
# #
if 'rename' in board_keys: if 'rename' in board_keys:
def rename_target(source, target, env): # If FIRMWARE_BIN is defined by config, override all
from pathlib import Path mf = env["MARLIN_FEATURES"]
Path(target[0].path).replace(Path(target[0].dir.path, board.get("build.rename"))) if "FIRMWARE_BIN" in mf: new_name = mf["FIRMWARE_BIN"]
else: new_name = board.get("build.rename")
marlin.add_post_action(rename_target)
def rename_target(source, target, env):
from pathlib import Path
Path(target[0].path).replace(Path(target[0].dir.path, new_name))
marlin.add_post_action(rename_target)

26
buildroot/share/PlatformIO/scripts/openblt.py

@ -3,18 +3,18 @@
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
import os,sys import os,sys
from os.path import join from os.path import join
Import("env") Import("env")
board = env.BoardConfig() board = env.BoardConfig()
board_keys = board.get("build").keys() board_keys = board.get("build").keys()
if 'encode' in board_keys: if 'encode' in board_keys:
env.AddPostAction( env.AddPostAction(
join("$BUILD_DIR", "${PROGNAME}.bin"), join("$BUILD_DIR", "${PROGNAME}.bin"),
env.VerboseAction(" ".join([ env.VerboseAction(" ".join([
"$OBJCOPY", "-O", "srec", "$OBJCOPY", "-O", "srec",
"\"$BUILD_DIR/${PROGNAME}.elf\"", "\"" + join("$BUILD_DIR", board.get("build.encode")) + "\"" "\"$BUILD_DIR/${PROGNAME}.elf\"", "\"" + join("$BUILD_DIR", board.get("build.encode")) + "\""
]), "Building " + board.get("build.encode")) ]), "Building " + board.get("build.encode"))
) )

10
buildroot/share/PlatformIO/scripts/pioutil.py

@ -4,10 +4,10 @@
# Make sure 'vscode init' is not the current command # Make sure 'vscode init' is not the current command
def is_pio_build(): def is_pio_build():
from SCons.Script import DefaultEnvironment from SCons.Script import DefaultEnvironment
env = DefaultEnvironment() env = DefaultEnvironment()
return not env.IsIntegrationDump() return not env.IsIntegrationDump()
def get_pio_version(): def get_pio_version():
from platformio import util from platformio import util
return util.pioversion_to_intstr() return util.pioversion_to_intstr()

240
buildroot/share/PlatformIO/scripts/preflight-checks.py

@ -5,123 +5,123 @@
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
import os,re,sys import os,re,sys
from pathlib import Path from pathlib import Path
Import("env") Import("env")
def get_envs_for_board(board): def get_envs_for_board(board):
ppath = Path("Marlin/src/pins/pins.h") ppath = Path("Marlin/src/pins/pins.h")
with ppath.open() as file: with ppath.open() as file:
if sys.platform == 'win32': if sys.platform == 'win32':
envregex = r"(?:env|win):" envregex = r"(?:env|win):"
elif sys.platform == 'darwin': elif sys.platform == 'darwin':
envregex = r"(?:env|mac|uni):" envregex = r"(?:env|mac|uni):"
elif sys.platform == 'linux': elif sys.platform == 'linux':
envregex = r"(?:env|lin|uni):" envregex = r"(?:env|lin|uni):"
else: else:
envregex = r"(?:env):" envregex = r"(?:env):"
r = re.compile(r"if\s+MB\((.+)\)") r = re.compile(r"if\s+MB\((.+)\)")
if board.startswith("BOARD_"): if board.startswith("BOARD_"):
board = board[6:] board = board[6:]
for line in file: for line in file:
mbs = r.findall(line) mbs = r.findall(line)
if mbs and board in re.split(r",\s*", mbs[0]): if mbs and board in re.split(r",\s*", mbs[0]):
line = file.readline() line = file.readline()
found_envs = re.match(r"\s*#include .+" + envregex, line) found_envs = re.match(r"\s*#include .+" + envregex, line)
if found_envs: if found_envs:
envlist = re.findall(envregex + r"(\w+)", line) envlist = re.findall(envregex + r"(\w+)", line)
return [ "env:"+s for s in envlist ] return [ "env:"+s for s in envlist ]
return [] return []
def check_envs(build_env, board_envs, config): def check_envs(build_env, board_envs, config):
if build_env in board_envs: if build_env in board_envs:
return True return True
ext = config.get(build_env, 'extends', default=None) ext = config.get(build_env, 'extends', default=None)
if ext: if ext:
if isinstance(ext, str): if isinstance(ext, str):
return check_envs(ext, board_envs, config) return check_envs(ext, board_envs, config)
elif isinstance(ext, list): elif isinstance(ext, list):
for ext_env in ext: for ext_env in ext:
if check_envs(ext_env, board_envs, config): if check_envs(ext_env, board_envs, config):
return True return True
return False return False
def sanity_check_target(): def sanity_check_target():
# Sanity checks: # Sanity checks:
if 'PIOENV' not in env: if 'PIOENV' not in env:
raise SystemExit("Error: PIOENV is not defined. This script is intended to be used with PlatformIO") raise SystemExit("Error: PIOENV is not defined. This script is intended to be used with PlatformIO")
# Require PlatformIO 6.1.1 or later # Require PlatformIO 6.1.1 or later
vers = pioutil.get_pio_version() vers = pioutil.get_pio_version()
if vers < [6, 1, 1]: if vers < [6, 1, 1]:
raise SystemExit("Error: Marlin requires PlatformIO >= 6.1.1. Use 'pio upgrade' to get a newer version.") raise SystemExit("Error: Marlin requires PlatformIO >= 6.1.1. Use 'pio upgrade' to get a newer version.")
if 'MARLIN_FEATURES' not in env: if 'MARLIN_FEATURES' not in env:
raise SystemExit("Error: this script should be used after common Marlin scripts") raise SystemExit("Error: this script should be used after common Marlin scripts")
if 'MOTHERBOARD' not in env['MARLIN_FEATURES']: if 'MOTHERBOARD' not in env['MARLIN_FEATURES']:
raise SystemExit("Error: MOTHERBOARD is not defined in Configuration.h") raise SystemExit("Error: MOTHERBOARD is not defined in Configuration.h")
build_env = env['PIOENV'] build_env = env['PIOENV']
motherboard = env['MARLIN_FEATURES']['MOTHERBOARD'] motherboard = env['MARLIN_FEATURES']['MOTHERBOARD']
board_envs = get_envs_for_board(motherboard) board_envs = get_envs_for_board(motherboard)
config = env.GetProjectConfig() config = env.GetProjectConfig()
result = check_envs("env:"+build_env, board_envs, config) result = check_envs("env:"+build_env, board_envs, config)
if not result: if not result:
err = "Error: Build environment '%s' is incompatible with %s. Use one of these: %s" % \ err = "Error: Build environment '%s' is incompatible with %s. Use one of these: %s" % \
( build_env, motherboard, ", ".join([ e[4:] for e in board_envs if e.startswith("env:") ]) ) ( build_env, motherboard, ", ".join([ e[4:] for e in board_envs if e.startswith("env:") ]) )
raise SystemExit(err) raise SystemExit(err)
# #
# Check for Config files in two common incorrect places # Check for Config files in two common incorrect places
# #
epath = Path(env['PROJECT_DIR']) epath = Path(env['PROJECT_DIR'])
for p in [ epath, epath / "config" ]: for p in [ epath, epath / "config" ]:
for f in ("Configuration.h", "Configuration_adv.h"): for f in ("Configuration.h", "Configuration_adv.h"):
if (p / f).is_file(): if (p / f).is_file():
err = "ERROR: Config files found in directory %s. Please move them into the Marlin subfolder." % p err = "ERROR: Config files found in directory %s. Please move them into the Marlin subfolder." % p
raise SystemExit(err) raise SystemExit(err)
# #
# Find the name.cpp.o or name.o and remove it # Find the name.cpp.o or name.o and remove it
# #
def rm_ofile(subdir, name): def rm_ofile(subdir, name):
build_dir = Path(env['PROJECT_BUILD_DIR'], build_env); build_dir = Path(env['PROJECT_BUILD_DIR'], build_env);
for outdir in (build_dir, build_dir / "debug"): for outdir in (build_dir, build_dir / "debug"):
for ext in (".cpp.o", ".o"): for ext in (".cpp.o", ".o"):
fpath = outdir / "src/src" / subdir / (name + ext) fpath = outdir / "src/src" / subdir / (name + ext)
if fpath.exists(): if fpath.exists():
fpath.unlink() fpath.unlink()
# #
# Give warnings on every build # Give warnings on every build
# #
rm_ofile("inc", "Warnings") rm_ofile("inc", "Warnings")
# #
# Rebuild 'settings.cpp' for EEPROM_INIT_NOW # Rebuild 'settings.cpp' for EEPROM_INIT_NOW
# #
if 'EEPROM_INIT_NOW' in env['MARLIN_FEATURES']: if 'EEPROM_INIT_NOW' in env['MARLIN_FEATURES']:
rm_ofile("module", "settings") rm_ofile("module", "settings")
# #
# Check for old files indicating an entangled Marlin (mixing old and new code) # Check for old files indicating an entangled Marlin (mixing old and new code)
# #
mixedin = [] mixedin = []
p = Path(env['PROJECT_DIR'], "Marlin/src/lcd/dogm") p = Path(env['PROJECT_DIR'], "Marlin/src/lcd/dogm")
for f in [ "ultralcd_DOGM.cpp", "ultralcd_DOGM.h" ]: for f in [ "ultralcd_DOGM.cpp", "ultralcd_DOGM.h" ]:
if (p / f).is_file(): if (p / f).is_file():
mixedin += [ f ] mixedin += [ f ]
p = Path(env['PROJECT_DIR'], "Marlin/src/feature/bedlevel/abl") p = Path(env['PROJECT_DIR'], "Marlin/src/feature/bedlevel/abl")
for f in [ "abl.cpp", "abl.h" ]: for f in [ "abl.cpp", "abl.h" ]:
if (p / f).is_file(): if (p / f).is_file():
mixedin += [ f ] mixedin += [ f ]
if mixedin: if mixedin:
err = "ERROR: Old files fell into your Marlin folder. Remove %s and try again" % ", ".join(mixedin) err = "ERROR: Old files fell into your Marlin folder. Remove %s and try again" % ", ".join(mixedin)
raise SystemExit(err) raise SystemExit(err)
sanity_check_target() sanity_check_target()

140
buildroot/share/PlatformIO/scripts/preprocessor.py

@ -7,8 +7,8 @@ nocache = 1
verbose = 0 verbose = 0
def blab(str): def blab(str):
if verbose: if verbose:
print(str) print(str)
################################################################################ ################################################################################
# #
@ -16,36 +16,36 @@ def blab(str):
# #
preprocessor_cache = {} preprocessor_cache = {}
def run_preprocessor(env, fn=None): def run_preprocessor(env, fn=None):
filename = fn or 'buildroot/share/PlatformIO/scripts/common-dependencies.h' filename = fn or 'buildroot/share/PlatformIO/scripts/common-dependencies.h'
if filename in preprocessor_cache: if filename in preprocessor_cache:
return preprocessor_cache[filename] return preprocessor_cache[filename]
# Process defines # Process defines
build_flags = env.get('BUILD_FLAGS') build_flags = env.get('BUILD_FLAGS')
build_flags = env.ParseFlagsExtended(build_flags) build_flags = env.ParseFlagsExtended(build_flags)
cxx = search_compiler(env) cxx = search_compiler(env)
cmd = ['"' + cxx + '"'] cmd = ['"' + cxx + '"']
# Build flags from board.json # Build flags from board.json
#if 'BOARD' in env: #if 'BOARD' in env:
# cmd += [env.BoardConfig().get("build.extra_flags")] # cmd += [env.BoardConfig().get("build.extra_flags")]
for s in build_flags['CPPDEFINES']: for s in build_flags['CPPDEFINES']:
if isinstance(s, tuple): if isinstance(s, tuple):
cmd += ['-D' + s[0] + '=' + str(s[1])] cmd += ['-D' + s[0] + '=' + str(s[1])]
else: else:
cmd += ['-D' + s] cmd += ['-D' + s]
cmd += ['-D__MARLIN_DEPS__ -w -dM -E -x c++'] cmd += ['-D__MARLIN_DEPS__ -w -dM -E -x c++']
depcmd = cmd + [ filename ] depcmd = cmd + [ filename ]
cmd = ' '.join(depcmd) cmd = ' '.join(depcmd)
blab(cmd) blab(cmd)
try: try:
define_list = subprocess.check_output(cmd, shell=True).splitlines() define_list = subprocess.check_output(cmd, shell=True).splitlines()
except: except:
define_list = {} define_list = {}
preprocessor_cache[filename] = define_list preprocessor_cache[filename] = define_list
return define_list return define_list
################################################################################ ################################################################################
@ -54,41 +54,41 @@ def run_preprocessor(env, fn=None):
# #
def search_compiler(env): def search_compiler(env):
from pathlib import Path, PurePath from pathlib import Path, PurePath
ENV_BUILD_PATH = Path(env['PROJECT_BUILD_DIR'], env['PIOENV']) ENV_BUILD_PATH = Path(env['PROJECT_BUILD_DIR'], env['PIOENV'])
GCC_PATH_CACHE = ENV_BUILD_PATH / ".gcc_path" GCC_PATH_CACHE = ENV_BUILD_PATH / ".gcc_path"
try: try:
gccpath = env.GetProjectOption('custom_gcc') gccpath = env.GetProjectOption('custom_gcc')
blab("Getting compiler from env") blab("Getting compiler from env")
return gccpath return gccpath
except: except:
pass pass
# Warning: The cached .gcc_path will obscure a newly-installed toolkit # Warning: The cached .gcc_path will obscure a newly-installed toolkit
if not nocache and GCC_PATH_CACHE.exists(): if not nocache and GCC_PATH_CACHE.exists():
blab("Getting g++ path from cache") blab("Getting g++ path from cache")
return GCC_PATH_CACHE.read_text() return GCC_PATH_CACHE.read_text()
# Use any item in $PATH corresponding to a platformio toolchain bin folder # Use any item in $PATH corresponding to a platformio toolchain bin folder
path_separator = ':' path_separator = ':'
gcc_exe = '*g++' gcc_exe = '*g++'
if env['PLATFORM'] == 'win32': if env['PLATFORM'] == 'win32':
path_separator = ';' path_separator = ';'
gcc_exe += ".exe" gcc_exe += ".exe"
# Search for the compiler in PATH # Search for the compiler in PATH
for ppath in map(Path, env['ENV']['PATH'].split(path_separator)): for ppath in map(Path, env['ENV']['PATH'].split(path_separator)):
if ppath.match(env['PROJECT_PACKAGES_DIR'] + "/**/bin"): if ppath.match(env['PROJECT_PACKAGES_DIR'] + "/**/bin"):
for gpath in ppath.glob(gcc_exe): for gpath in ppath.glob(gcc_exe):
gccpath = str(gpath.resolve()) gccpath = str(gpath.resolve())
# Cache the g++ path to no search always # Cache the g++ path to no search always
if not nocache and ENV_BUILD_PATH.exists(): if not nocache and ENV_BUILD_PATH.exists():
blab("Caching g++ for current env") blab("Caching g++ for current env")
GCC_PATH_CACHE.write_text(gccpath) GCC_PATH_CACHE.write_text(gccpath)
return gccpath return gccpath
gccpath = env.get('CXX') gccpath = env.get('CXX')
blab("Couldn't find a compiler! Fallback to %s" % gccpath) blab("Couldn't find a compiler! Fallback to %s" % gccpath)
return gccpath return gccpath

6
buildroot/share/PlatformIO/scripts/random-bin.py

@ -4,6 +4,6 @@
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
from datetime import datetime from datetime import datetime
Import("env") Import("env")
env['PROGNAME'] = datetime.now().strftime("firmware-%Y%m%d-%H%M%S") env['PROGNAME'] = datetime.now().strftime("firmware-%Y%m%d-%H%M%S")

751
buildroot/share/PlatformIO/scripts/schema.py

@ -9,394 +9,413 @@ import re,json
from pathlib import Path from pathlib import Path
def extend_dict(d:dict, k:tuple): def extend_dict(d:dict, k:tuple):
if len(k) >= 1 and k[0] not in d: if len(k) >= 1 and k[0] not in d:
d[k[0]] = {} d[k[0]] = {}
if len(k) >= 2 and k[1] not in d[k[0]]: if len(k) >= 2 and k[1] not in d[k[0]]:
d[k[0]][k[1]] = {} d[k[0]][k[1]] = {}
if len(k) >= 3 and k[2] not in d[k[0]][k[1]]: if len(k) >= 3 and k[2] not in d[k[0]][k[1]]:
d[k[0]][k[1]][k[2]] = {} d[k[0]][k[1]][k[2]] = {}
grouping_patterns = [ grouping_patterns = [
re.compile(r'^([XYZIJKUVW]|[XYZ]2|Z[34]|E[0-7])$'), re.compile(r'^([XYZIJKUVW]|[XYZ]2|Z[34]|E[0-7])$'),
re.compile(r'^AXIS\d$'), re.compile(r'^AXIS\d$'),
re.compile(r'^(MIN|MAX)$'), re.compile(r'^(MIN|MAX)$'),
re.compile(r'^[0-8]$'), re.compile(r'^[0-8]$'),
re.compile(r'^HOTEND[0-7]$'), re.compile(r'^HOTEND[0-7]$'),
re.compile(r'^(HOTENDS|BED|PROBE|COOLER)$'), re.compile(r'^(HOTENDS|BED|PROBE|COOLER)$'),
re.compile(r'^[XYZIJKUVW]M(IN|AX)$') re.compile(r'^[XYZIJKUVW]M(IN|AX)$')
] ]
# If the indexed part of the option name matches a pattern # If the indexed part of the option name matches a pattern
# then add it to the dictionary. # then add it to the dictionary.
def find_grouping(gdict, filekey, sectkey, optkey, pindex): def find_grouping(gdict, filekey, sectkey, optkey, pindex):
optparts = optkey.split('_') optparts = optkey.split('_')
if 1 < len(optparts) > pindex: if 1 < len(optparts) > pindex:
for patt in grouping_patterns: for patt in grouping_patterns:
if patt.match(optparts[pindex]): if patt.match(optparts[pindex]):
subkey = optparts[pindex] subkey = optparts[pindex]
modkey = '_'.join(optparts) modkey = '_'.join(optparts)
optparts[pindex] = '*' optparts[pindex] = '*'
wildkey = '_'.join(optparts) wildkey = '_'.join(optparts)
kkey = f'{filekey}|{sectkey}|{wildkey}' kkey = f'{filekey}|{sectkey}|{wildkey}'
if kkey not in gdict: gdict[kkey] = [] if kkey not in gdict: gdict[kkey] = []
gdict[kkey].append((subkey, modkey)) gdict[kkey].append((subkey, modkey))
# Build a list of potential groups. Only those with multiple items will be grouped. # Build a list of potential groups. Only those with multiple items will be grouped.
def group_options(schema): def group_options(schema):
for pindex in range(10, -1, -1): for pindex in range(10, -1, -1):
found_groups = {} found_groups = {}
for filekey, f in schema.items(): for filekey, f in schema.items():
for sectkey, s in f.items(): for sectkey, s in f.items():
for optkey in s: for optkey in s:
find_grouping(found_groups, filekey, sectkey, optkey, pindex) find_grouping(found_groups, filekey, sectkey, optkey, pindex)
fkeys = [ k for k in found_groups.keys() ] fkeys = [ k for k in found_groups.keys() ]
for kkey in fkeys: for kkey in fkeys:
items = found_groups[kkey] items = found_groups[kkey]
if len(items) > 1: if len(items) > 1:
f, s, w = kkey.split('|') f, s, w = kkey.split('|')
extend_dict(schema, (f, s, w)) # Add wildcard group to schema extend_dict(schema, (f, s, w)) # Add wildcard group to schema
for subkey, optkey in items: # Add all items to wildcard group for subkey, optkey in items: # Add all items to wildcard group
schema[f][s][w][subkey] = schema[f][s][optkey] # Move non-wildcard item to wildcard group schema[f][s][w][subkey] = schema[f][s][optkey] # Move non-wildcard item to wildcard group
del schema[f][s][optkey] del schema[f][s][optkey]
del found_groups[kkey] del found_groups[kkey]
# Extract all board names from boards.h # Extract all board names from boards.h
def load_boards(): def load_boards():
bpath = Path("Marlin/src/core/boards.h") bpath = Path("Marlin/src/core/boards.h")
if bpath.is_file(): if bpath.is_file():
with bpath.open() as bfile: with bpath.open() as bfile:
boards = [] boards = []
for line in bfile: for line in bfile:
if line.startswith("#define BOARD_"): if line.startswith("#define BOARD_"):
bname = line.split()[1] bname = line.split()[1]
if bname != "BOARD_UNKNOWN": boards.append(bname) if bname != "BOARD_UNKNOWN": boards.append(bname)
return "['" + "','".join(boards) + "']" return "['" + "','".join(boards) + "']"
return '' return ''
# #
# Extract a schema from the current configuration files # Extract a schema from the current configuration files
# #
def extract(): def extract():
# Load board names from boards.h # Load board names from boards.h
boards = load_boards() boards = load_boards()
# Parsing states # Parsing states
class Parse: class Parse:
NORMAL = 0 # No condition yet NORMAL = 0 # No condition yet
BLOCK_COMMENT = 1 # Looking for the end of the block comment BLOCK_COMMENT = 1 # Looking for the end of the block comment
EOL_COMMENT = 2 # EOL comment started, maybe add the next comment? EOL_COMMENT = 2 # EOL comment started, maybe add the next comment?
GET_SENSORS = 3 # Gathering temperature sensor options GET_SENSORS = 3 # Gathering temperature sensor options
ERROR = 9 # Syntax error ERROR = 9 # Syntax error
# List of files to process, with shorthand # List of files to process, with shorthand
filekey = { 'Configuration.h':'basic', 'Configuration_adv.h':'advanced' } filekey = { 'Configuration.h':'basic', 'Configuration_adv.h':'advanced' }
# A JSON object to store the data # A JSON object to store the data
sch_out = { 'basic':{}, 'advanced':{} } sch_out = { 'basic':{}, 'advanced':{} }
# Regex for #define NAME [VALUE] [COMMENT] with sanitized line # Regex for #define NAME [VALUE] [COMMENT] with sanitized line
defgrep = re.compile(r'^(//)?\s*(#define)\s+([A-Za-z0-9_]+)\s*(.*?)\s*(//.+)?$') defgrep = re.compile(r'^(//)?\s*(#define)\s+([A-Za-z0-9_]+)\s*(.*?)\s*(//.+)?$')
# Defines to ignore # Defines to ignore
ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_EXAMPLES_DIR', 'CONFIG_EXPORT') ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_EXAMPLES_DIR', 'CONFIG_EXPORT')
# Start with unknown state # Start with unknown state
state = Parse.NORMAL state = Parse.NORMAL
# Serial ID # Serial ID
sid = 0 sid = 0
# Loop through files and parse them line by line # Loop through files and parse them line by line
for fn, fk in filekey.items(): for fn, fk in filekey.items():
with Path("Marlin", fn).open() as fileobj: with Path("Marlin", fn).open() as fileobj:
section = 'none' # Current Settings section section = 'none' # Current Settings section
line_number = 0 # Counter for the line number of the file line_number = 0 # Counter for the line number of the file
conditions = [] # Create a condition stack for the current file conditions = [] # Create a condition stack for the current file
comment_buff = [] # A temporary buffer for comments comment_buff = [] # A temporary buffer for comments
options_json = '' # A buffer for the most recent options JSON found options_json = '' # A buffer for the most recent options JSON found
eol_options = False # The options came from end of line, so only apply once eol_options = False # The options came from end of line, so only apply once
join_line = False # A flag that the line should be joined with the previous one join_line = False # A flag that the line should be joined with the previous one
line = '' # A line buffer to handle \ continuation line = '' # A line buffer to handle \ continuation
last_added_ref = None # Reference to the last added item last_added_ref = None # Reference to the last added item
# Loop through the lines in the file # Loop through the lines in the file
for the_line in fileobj.readlines(): for the_line in fileobj.readlines():
line_number += 1 line_number += 1
# Clean the line for easier parsing # Clean the line for easier parsing
the_line = the_line.strip() the_line = the_line.strip()
if join_line: # A previous line is being made longer if join_line: # A previous line is being made longer
line += (' ' if line else '') + the_line line += (' ' if line else '') + the_line
else: # Otherwise, start the line anew else: # Otherwise, start the line anew
line, line_start = the_line, line_number line, line_start = the_line, line_number
# If the resulting line ends with a \, don't process now. # If the resulting line ends with a \, don't process now.
# Strip the end off. The next line will be joined with it. # Strip the end off. The next line will be joined with it.
join_line = line.endswith("\\") join_line = line.endswith("\\")
if join_line: if join_line:
line = line[:-1].strip() line = line[:-1].strip()
continue continue
else: else:
line_end = line_number line_end = line_number
defmatch = defgrep.match(line) defmatch = defgrep.match(line)
# Special handling for EOL comments after a #define. # Special handling for EOL comments after a #define.
# At this point the #define is already digested and inserted, # At this point the #define is already digested and inserted,
# so we have to extend it # so we have to extend it
if state == Parse.EOL_COMMENT: if state == Parse.EOL_COMMENT:
# If the line is not a comment, we're done with the EOL comment # If the line is not a comment, we're done with the EOL comment
if not defmatch and the_line.startswith('//'): if not defmatch and the_line.startswith('//'):
comment_buff.append(the_line[2:].strip()) comment_buff.append(the_line[2:].strip())
else: else:
last_added_ref['comment'] = ' '.join(comment_buff) last_added_ref['comment'] = ' '.join(comment_buff)
comment_buff = [] comment_buff = []
state = Parse.NORMAL state = Parse.NORMAL
def use_comment(c, opt, sec, bufref): def use_comment(c, opt, sec, bufref):
if c.startswith(':'): # If the comment starts with : then it has magic JSON if c.startswith(':'): # If the comment starts with : then it has magic JSON
d = c[1:].strip() # Strip the leading : d = c[1:].strip() # Strip the leading :
cbr = c.rindex('}') if d.startswith('{') else c.rindex(']') if d.startswith('[') else 0 cbr = c.rindex('}') if d.startswith('{') else c.rindex(']') if d.startswith('[') else 0
if cbr: if cbr:
opt, cmt = c[1:cbr+1].strip(), c[cbr+1:].strip() opt, cmt = c[1:cbr+1].strip(), c[cbr+1:].strip()
if cmt != '': bufref.append(cmt) if cmt != '': bufref.append(cmt)
else: else:
opt = c[1:].strip() opt = c[1:].strip()
elif c.startswith('@section'): # Start a new section elif c.startswith('@section'): # Start a new section
sec = c[8:].strip() sec = c[8:].strip()
elif not c.startswith('========'): elif not c.startswith('========'):
bufref.append(c) bufref.append(c)
return opt, sec return opt, sec
# In a block comment, capture lines up to the end of the comment. # In a block comment, capture lines up to the end of the comment.
# Assume nothing follows the comment closure. # Assume nothing follows the comment closure.
if state in (Parse.BLOCK_COMMENT, Parse.GET_SENSORS): if state in (Parse.BLOCK_COMMENT, Parse.GET_SENSORS):
endpos = line.find('*/') endpos = line.find('*/')
if endpos < 0: if endpos < 0:
cline = line cline = line
else: else:
cline, line = line[:endpos].strip(), line[endpos+2:].strip() cline, line = line[:endpos].strip(), line[endpos+2:].strip()
# Temperature sensors are done # Temperature sensors are done
if state == Parse.GET_SENSORS: if state == Parse.GET_SENSORS:
options_json = f'[ {options_json[:-2]} ]' options_json = f'[ {options_json[:-2]} ]'
state = Parse.NORMAL state = Parse.NORMAL
# Strip the leading '*' from block comments # Strip the leading '*' from block comments
if cline.startswith('*'): cline = cline[1:].strip() if cline.startswith('*'): cline = cline[1:].strip()
# Collect temperature sensors # Collect temperature sensors
if state == Parse.GET_SENSORS: if state == Parse.GET_SENSORS:
sens = re.match(r'^(-?\d+)\s*:\s*(.+)$', cline) sens = re.match(r'^(-?\d+)\s*:\s*(.+)$', cline)
if sens: if sens:
s2 = sens[2].replace("'","''") s2 = sens[2].replace("'","''")
options_json += f"{sens[1]}:'{s2}', " options_json += f"{sens[1]}:'{s2}', "
elif state == Parse.BLOCK_COMMENT: elif state == Parse.BLOCK_COMMENT:
# Look for temperature sensors # Look for temperature sensors
if cline == "Temperature sensors available:": if cline == "Temperature sensors available:":
state, cline = Parse.GET_SENSORS, "Temperature Sensors" state, cline = Parse.GET_SENSORS, "Temperature Sensors"
options_json, section = use_comment(cline, options_json, section, comment_buff) options_json, section = use_comment(cline, options_json, section, comment_buff)
# For the normal state we're looking for any non-blank line # For the normal state we're looking for any non-blank line
elif state == Parse.NORMAL: elif state == Parse.NORMAL:
# Skip a commented define when evaluating comment opening # Skip a commented define when evaluating comment opening
st = 2 if re.match(r'^//\s*#define', line) else 0 st = 2 if re.match(r'^//\s*#define', line) else 0
cpos1 = line.find('/*') # Start a block comment on the line? cpos1 = line.find('/*') # Start a block comment on the line?
cpos2 = line.find('//', st) # Start an end of line comment on the line? cpos2 = line.find('//', st) # Start an end of line comment on the line?
# Only the first comment starter gets evaluated # Only the first comment starter gets evaluated
cpos = -1 cpos = -1
if cpos1 != -1 and (cpos1 < cpos2 or cpos2 == -1): if cpos1 != -1 and (cpos1 < cpos2 or cpos2 == -1):
cpos = cpos1 cpos = cpos1
comment_buff = [] comment_buff = []
state = Parse.BLOCK_COMMENT state = Parse.BLOCK_COMMENT
eol_options = False eol_options = False
elif cpos2 != -1 and (cpos2 < cpos1 or cpos1 == -1): elif cpos2 != -1 and (cpos2 < cpos1 or cpos1 == -1):
cpos = cpos2 cpos = cpos2
# Expire end-of-line options after first use # Comment after a define may be continued on the following lines
if cline.startswith(':'): eol_options = True if defmatch != None and cpos > 10:
state = Parse.EOL_COMMENT
# Comment after a define may be continued on the following lines comment_buff = []
if state == Parse.NORMAL and defmatch != None and cpos > 10:
state = Parse.EOL_COMMENT # Process the start of a new comment
comment_buff = [] if cpos != -1:
cline, line = line[cpos+2:].strip(), line[:cpos].strip()
# Process the start of a new comment
if cpos != -1: if state == Parse.BLOCK_COMMENT:
cline, line = line[cpos+2:].strip(), line[:cpos].strip() # Strip leading '*' from block comments
if cline.startswith('*'): cline = cline[1:].strip()
# Strip leading '*' from block comments else:
if state == Parse.BLOCK_COMMENT: # Expire end-of-line options after first use
if cline.startswith('*'): cline = cline[1:].strip() if cline.startswith(':'): eol_options = True
# Buffer a non-empty comment start # Buffer a non-empty comment start
if cline != '': if cline != '':
options_json, section = use_comment(cline, options_json, section, comment_buff) options_json, section = use_comment(cline, options_json, section, comment_buff)
# If the line has nothing before the comment, go to the next line # If the line has nothing before the comment, go to the next line
if line == '': if line == '':
options_json = '' options_json = ''
continue continue
# Parenthesize the given expression if needed # Parenthesize the given expression if needed
def atomize(s): def atomize(s):
if s == '' \ if s == '' \
or re.match(r'^[A-Za-z0-9_]*(\([^)]+\))?$', s) \ or re.match(r'^[A-Za-z0-9_]*(\([^)]+\))?$', s) \
or re.match(r'^[A-Za-z0-9_]+ == \d+?$', s): or re.match(r'^[A-Za-z0-9_]+ == \d+?$', s):
return s return s
return f'({s})' return f'({s})'
# #
# The conditions stack is an array containing condition-arrays. # The conditions stack is an array containing condition-arrays.
# Each condition-array lists the conditions for the current block. # Each condition-array lists the conditions for the current block.
# IF/N/DEF adds a new condition-array to the stack. # IF/N/DEF adds a new condition-array to the stack.
# ELSE/ELIF/ENDIF pop the condition-array. # ELSE/ELIF/ENDIF pop the condition-array.
# ELSE/ELIF negate the last item in the popped condition-array. # ELSE/ELIF negate the last item in the popped condition-array.
# ELIF adds a new condition to the end of the array. # ELIF adds a new condition to the end of the array.
# ELSE/ELIF re-push the condition-array. # ELSE/ELIF re-push the condition-array.
# #
cparts = line.split() cparts = line.split()
iselif, iselse = cparts[0] == '#elif', cparts[0] == '#else' iselif, iselse = cparts[0] == '#elif', cparts[0] == '#else'
if iselif or iselse or cparts[0] == '#endif': if iselif or iselse or cparts[0] == '#endif':
if len(conditions) == 0: if len(conditions) == 0:
raise Exception(f'no #if block at line {line_number}') raise Exception(f'no #if block at line {line_number}')
# Pop the last condition-array from the stack # Pop the last condition-array from the stack
prev = conditions.pop() prev = conditions.pop()
if iselif or iselse: if iselif or iselse:
prev[-1] = '!' + prev[-1] # Invert the last condition prev[-1] = '!' + prev[-1] # Invert the last condition
if iselif: prev.append(atomize(line[5:].strip())) if iselif: prev.append(atomize(line[5:].strip()))
conditions.append(prev) conditions.append(prev)
elif cparts[0] == '#if': elif cparts[0] == '#if':
conditions.append([ atomize(line[3:].strip()) ]) conditions.append([ atomize(line[3:].strip()) ])
elif cparts[0] == '#ifdef': elif cparts[0] == '#ifdef':
conditions.append([ f'defined({line[6:].strip()})' ]) conditions.append([ f'defined({line[6:].strip()})' ])
elif cparts[0] == '#ifndef': elif cparts[0] == '#ifndef':
conditions.append([ f'!defined({line[7:].strip()})' ]) conditions.append([ f'!defined({line[7:].strip()})' ])
# Handle a complete #define line # Handle a complete #define line
elif defmatch != None: elif defmatch != None:
# Get the match groups into vars # Get the match groups into vars
enabled, define_name, val = defmatch[1] == None, defmatch[3], defmatch[4] enabled, define_name, val = defmatch[1] == None, defmatch[3], defmatch[4]
# Increment the serial ID # Increment the serial ID
sid += 1 sid += 1
# Create a new dictionary for the current #define # Create a new dictionary for the current #define
define_info = { define_info = {
'section': section, 'section': section,
'name': define_name, 'name': define_name,
'enabled': enabled, 'enabled': enabled,
'line': line_start, 'line': line_start,
'sid': sid 'sid': sid
} }
# Type is based on the value # Type is based on the value
if val == '': if val == '':
value_type = 'switch' value_type = 'switch'
elif re.match(r'^(true|false)$', val): elif re.match(r'^(true|false)$', val):
value_type = 'bool' value_type = 'bool'
val = val == 'true' val = val == 'true'
elif re.match(r'^[-+]?\s*\d+$', val): elif re.match(r'^[-+]?\s*\d+$', val):
value_type = 'int' value_type = 'int'
val = int(val) val = int(val)
elif re.match(r'[-+]?\s*(\d+\.|\d*\.\d+)([eE][-+]?\d+)?[fF]?', val): elif re.match(r'[-+]?\s*(\d+\.|\d*\.\d+)([eE][-+]?\d+)?[fF]?', val):
value_type = 'float' value_type = 'float'
val = float(val.replace('f','')) val = float(val.replace('f',''))
else: else:
value_type = 'string' if val[0] == '"' \ value_type = 'string' if val[0] == '"' \
else 'char' if val[0] == "'" \ else 'char' if val[0] == "'" \
else 'state' if re.match(r'^(LOW|HIGH)$', val) \ else 'state' if re.match(r'^(LOW|HIGH)$', val) \
else 'enum' if re.match(r'^[A-Za-z0-9_]{3,}$', val) \ else 'enum' if re.match(r'^[A-Za-z0-9_]{3,}$', val) \
else 'int[]' if re.match(r'^{(\s*[-+]?\s*\d+\s*(,\s*)?)+}$', val) \ else 'int[]' if re.match(r'^{(\s*[-+]?\s*\d+\s*(,\s*)?)+}$', val) \
else 'float[]' if re.match(r'^{(\s*[-+]?\s*(\d+\.|\d*\.\d+)([eE][-+]?\d+)?[fF]?\s*(,\s*)?)+}$', val) \ else 'float[]' if re.match(r'^{(\s*[-+]?\s*(\d+\.|\d*\.\d+)([eE][-+]?\d+)?[fF]?\s*(,\s*)?)+}$', val) \
else 'array' if val[0] == '{' \ else 'array' if val[0] == '{' \
else '' else ''
if val != '': define_info['value'] = val if val != '': define_info['value'] = val
if value_type != '': define_info['type'] = value_type if value_type != '': define_info['type'] = value_type
# Join up accumulated conditions with && # Join up accumulated conditions with &&
if conditions: define_info['requires'] = ' && '.join(sum(conditions, [])) if conditions: define_info['requires'] = ' && '.join(sum(conditions, []))
# If the comment_buff is not empty, add the comment to the info # If the comment_buff is not empty, add the comment to the info
if comment_buff: if comment_buff:
full_comment = '\n'.join(comment_buff) full_comment = '\n'.join(comment_buff)
# An EOL comment will be added later # An EOL comment will be added later
# The handling could go here instead of above # The handling could go here instead of above
if state == Parse.EOL_COMMENT: if state == Parse.EOL_COMMENT:
define_info['comment'] = '' define_info['comment'] = ''
else: else:
define_info['comment'] = full_comment define_info['comment'] = full_comment
comment_buff = [] comment_buff = []
# If the comment specifies units, add that to the info # If the comment specifies units, add that to the info
units = re.match(r'^\(([^)]+)\)', full_comment) units = re.match(r'^\(([^)]+)\)', full_comment)
if units: if units:
units = units[1] units = units[1]
if units == 's' or units == 'sec': units = 'seconds' if units == 's' or units == 'sec': units = 'seconds'
define_info['units'] = units define_info['units'] = units
# Set the options for the current #define # Set the options for the current #define
if define_name == "MOTHERBOARD" and boards != '': if define_name == "MOTHERBOARD" and boards != '':
define_info['options'] = boards define_info['options'] = boards
elif options_json != '': elif options_json != '':
define_info['options'] = options_json define_info['options'] = options_json
if eol_options: options_json = '' if eol_options: options_json = ''
# Create section dict if it doesn't exist yet # Create section dict if it doesn't exist yet
if section not in sch_out[fk]: sch_out[fk][section] = {} if section not in sch_out[fk]: sch_out[fk][section] = {}
# If define has already been seen... # If define has already been seen...
if define_name in sch_out[fk][section]: if define_name in sch_out[fk][section]:
info = sch_out[fk][section][define_name] info = sch_out[fk][section][define_name]
if isinstance(info, dict): info = [ info ] # Convert a single dict into a list if isinstance(info, dict): info = [ info ] # Convert a single dict into a list
info.append(define_info) # Add to the list info.append(define_info) # Add to the list
else: else:
# Add the define dict with name as key # Add the define dict with name as key
sch_out[fk][section][define_name] = define_info sch_out[fk][section][define_name] = define_info
if state == Parse.EOL_COMMENT: if state == Parse.EOL_COMMENT:
last_added_ref = define_info last_added_ref = define_info
return sch_out return sch_out
def dump_json(schema:dict, jpath:Path): def dump_json(schema:dict, jpath:Path):
with jpath.open('w') as jfile: with jpath.open('w') as jfile:
json.dump(schema, jfile, ensure_ascii=False, indent=2) json.dump(schema, jfile, ensure_ascii=False, indent=2)
def dump_yaml(schema:dict, ypath:Path): def dump_yaml(schema:dict, ypath:Path):
import yaml import yaml
with ypath.open('w') as yfile: with ypath.open('w') as yfile:
yaml.dump(schema, yfile, default_flow_style=False, width=120, indent=2) yaml.dump(schema, yfile, default_flow_style=False, width=120, indent=2)
def main(): def main():
try: try:
schema = extract() schema = extract()
except Exception as exc: except Exception as exc:
print("Error: " + str(exc)) print("Error: " + str(exc))
schema = None schema = None
if schema: if schema:
print("Generating JSON ...")
dump_json(schema, Path('schema.json')) # Get the first command line argument
group_options(schema) import sys
dump_json(schema, Path('schema_grouped.json')) if len(sys.argv) > 1:
arg = sys.argv[1]
try: else:
import yaml arg = 'some'
except ImportError:
print("Installing YAML module ...") # JSON schema
import subprocess if arg in ['some', 'json', 'jsons']:
subprocess.run(['python3', '-m', 'pip', 'install', 'pyyaml']) print("Generating JSON ...")
import yaml dump_json(schema, Path('schema.json'))
print("Generating YML ...") # JSON schema (wildcard names)
dump_yaml(schema, Path('schema.yml')) if arg in ['group', 'jsons']:
group_options(schema)
dump_json(schema, Path('schema_grouped.json'))
# YAML
if arg in ['some', 'yml', 'yaml']:
try:
import yaml
except ImportError:
print("Installing YAML module ...")
import subprocess
try:
subprocess.run(['python3', '-m', 'pip', 'install', 'pyyaml'])
import yaml
except:
print("Failed to install YAML module")
return
print("Generating YML ...")
dump_yaml(schema, Path('schema.yml'))
if __name__ == '__main__': if __name__ == '__main__':
main() main()

484
buildroot/share/PlatformIO/scripts/signature.py

@ -16,32 +16,32 @@ from pathlib import Path
# resulting config.ini to produce more exact configuration files. # resulting config.ini to produce more exact configuration files.
# #
def extract_defines(filepath): def extract_defines(filepath):
f = open(filepath, encoding="utf8").read().split("\n") f = open(filepath, encoding="utf8").read().split("\n")
a = [] a = []
for line in f: for line in f:
sline = line.strip() sline = line.strip()
if sline[:7] == "#define": if sline[:7] == "#define":
# Extract the key here (we don't care about the value) # Extract the key here (we don't care about the value)
kv = sline[8:].strip().split() kv = sline[8:].strip().split()
a.append(kv[0]) a.append(kv[0])
return a return a
# Compute the SHA256 hash of a file # Compute the SHA256 hash of a file
def get_file_sha256sum(filepath): def get_file_sha256sum(filepath):
sha256_hash = hashlib.sha256() sha256_hash = hashlib.sha256()
with open(filepath,"rb") as f: with open(filepath,"rb") as f:
# Read and update hash string value in blocks of 4K # Read and update hash string value in blocks of 4K
for byte_block in iter(lambda: f.read(4096),b""): for byte_block in iter(lambda: f.read(4096),b""):
sha256_hash.update(byte_block) sha256_hash.update(byte_block)
return sha256_hash.hexdigest() return sha256_hash.hexdigest()
# #
# Compress a JSON file into a zip file # Compress a JSON file into a zip file
# #
import zipfile import zipfile
def compress_file(filepath, outpath): def compress_file(filepath, outpath):
with zipfile.ZipFile(outpath, 'w', compression=zipfile.ZIP_BZIP2, compresslevel=9) as zipf: with zipfile.ZipFile(outpath, 'w', compression=zipfile.ZIP_BZIP2, compresslevel=9) as zipf:
zipf.write(filepath, compress_type=zipfile.ZIP_BZIP2, compresslevel=9) zipf.write(filepath, compress_type=zipfile.ZIP_BZIP2, compresslevel=9)
# #
# Compute the build signature. The idea is to extract all defines in the configuration headers # Compute the build signature. The idea is to extract all defines in the configuration headers
@ -49,228 +49,228 @@ def compress_file(filepath, outpath):
# We can reverse the signature to get a 1:1 equivalent configuration file # We can reverse the signature to get a 1:1 equivalent configuration file
# #
def compute_build_signature(env): def compute_build_signature(env):
if 'BUILD_SIGNATURE' in env: if 'BUILD_SIGNATURE' in env:
return return
# Definitions from these files will be kept # Definitions from these files will be kept
files_to_keep = [ 'Marlin/Configuration.h', 'Marlin/Configuration_adv.h' ] files_to_keep = [ 'Marlin/Configuration.h', 'Marlin/Configuration_adv.h' ]
build_path = Path(env['PROJECT_BUILD_DIR'], env['PIOENV']) build_path = Path(env['PROJECT_BUILD_DIR'], env['PIOENV'])
# Check if we can skip processing # Check if we can skip processing
hashes = '' hashes = ''
for header in files_to_keep: for header in files_to_keep:
hashes += get_file_sha256sum(header)[0:10] hashes += get_file_sha256sum(header)[0:10]
marlin_json = build_path / 'marlin_config.json' marlin_json = build_path / 'marlin_config.json'
marlin_zip = build_path / 'mc.zip' marlin_zip = build_path / 'mc.zip'
# Read existing config file # Read existing config file
try: try:
with marlin_json.open() as infile: with marlin_json.open() as infile:
conf = json.load(infile) conf = json.load(infile)
if conf['__INITIAL_HASH'] == hashes: if conf['__INITIAL_HASH'] == hashes:
# Same configuration, skip recomputing the building signature # Same configuration, skip recomputing the building signature
compress_file(marlin_json, marlin_zip) compress_file(marlin_json, marlin_zip)
return return
except: except:
pass pass
# Get enabled config options based on preprocessor # Get enabled config options based on preprocessor
from preprocessor import run_preprocessor from preprocessor import run_preprocessor
complete_cfg = run_preprocessor(env) complete_cfg = run_preprocessor(env)
# Dumb #define extraction from the configuration files # Dumb #define extraction from the configuration files
conf_defines = {} conf_defines = {}
all_defines = [] all_defines = []
for header in files_to_keep: for header in files_to_keep:
defines = extract_defines(header) defines = extract_defines(header)
# To filter only the define we want # To filter only the define we want
all_defines += defines all_defines += defines
# To remember from which file it cames from # To remember from which file it cames from
conf_defines[header.split('/')[-1]] = defines conf_defines[header.split('/')[-1]] = defines
r = re.compile(r"\(+(\s*-*\s*_.*)\)+") r = re.compile(r"\(+(\s*-*\s*_.*)\)+")
# First step is to collect all valid macros # First step is to collect all valid macros
defines = {} defines = {}
for line in complete_cfg: for line in complete_cfg:
# Split the define from the value # Split the define from the value
key_val = line[8:].strip().decode().split(' ') key_val = line[8:].strip().decode().split(' ')
key, value = key_val[0], ' '.join(key_val[1:]) key, value = key_val[0], ' '.join(key_val[1:])
# Ignore values starting with two underscore, since it's low level # Ignore values starting with two underscore, since it's low level
if len(key) > 2 and key[0:2] == "__" : if len(key) > 2 and key[0:2] == "__" :
continue continue
# Ignore values containing a parenthesis (likely a function macro) # Ignore values containing a parenthesis (likely a function macro)
if '(' in key and ')' in key: if '(' in key and ')' in key:
continue continue
# Then filter dumb values # Then filter dumb values
if r.match(value): if r.match(value):
continue continue
defines[key] = value if len(value) else "" defines[key] = value if len(value) else ""
# #
# Continue to gather data for CONFIGURATION_EMBEDDING or CONFIG_EXPORT # Continue to gather data for CONFIGURATION_EMBEDDING or CONFIG_EXPORT
# #
if not ('CONFIGURATION_EMBEDDING' in defines or 'CONFIG_EXPORT' in defines): if not ('CONFIGURATION_EMBEDDING' in defines or 'CONFIG_EXPORT' in defines):
return return
# Second step is to filter useless macro # Second step is to filter useless macro
resolved_defines = {} resolved_defines = {}
for key in defines: for key in defines:
# Remove all boards now # Remove all boards now
if key.startswith("BOARD_") and key != "BOARD_INFO_NAME": if key.startswith("BOARD_") and key != "BOARD_INFO_NAME":
continue continue
# Remove all keys ending by "_NAME" as it does not make a difference to the configuration # Remove all keys ending by "_NAME" as it does not make a difference to the configuration
if key.endswith("_NAME") and key != "CUSTOM_MACHINE_NAME": if key.endswith("_NAME") and key != "CUSTOM_MACHINE_NAME":
continue continue
# Remove all keys ending by "_T_DECLARED" as it's a copy of extraneous system stuff # Remove all keys ending by "_T_DECLARED" as it's a copy of extraneous system stuff
if key.endswith("_T_DECLARED"): if key.endswith("_T_DECLARED"):
continue continue
# Remove keys that are not in the #define list in the Configuration list # Remove keys that are not in the #define list in the Configuration list
if key not in all_defines + [ 'DETAILED_BUILD_VERSION', 'STRING_DISTRIBUTION_DATE' ]: if key not in all_defines + [ 'DETAILED_BUILD_VERSION', 'STRING_DISTRIBUTION_DATE' ]:
continue continue
# Don't be that smart guy here # Don't be that smart guy here
resolved_defines[key] = defines[key] resolved_defines[key] = defines[key]
# Generate a build signature now # Generate a build signature now
# We are making an object that's a bit more complex than a basic dictionary here # We are making an object that's a bit more complex than a basic dictionary here
data = {} data = {}
data['__INITIAL_HASH'] = hashes data['__INITIAL_HASH'] = hashes
# First create a key for each header here # First create a key for each header here
for header in conf_defines: for header in conf_defines:
data[header] = {} data[header] = {}
# Then populate the object where each key is going to (that's a O(N^2) algorithm here...) # Then populate the object where each key is going to (that's a O(N^2) algorithm here...)
for key in resolved_defines: for key in resolved_defines:
for header in conf_defines: for header in conf_defines:
if key in conf_defines[header]: if key in conf_defines[header]:
data[header][key] = resolved_defines[key] data[header][key] = resolved_defines[key]
# Every python needs this toy # Every python needs this toy
def tryint(key): def tryint(key):
try: try:
return int(defines[key]) return int(defines[key])
except: except:
return 0 return 0
config_dump = tryint('CONFIG_EXPORT') config_dump = tryint('CONFIG_EXPORT')
# #
# Produce an INI file if CONFIG_EXPORT == 2 # Produce an INI file if CONFIG_EXPORT == 2
# #
if config_dump == 2: if config_dump == 2:
print("Generating config.ini ...") print("Generating config.ini ...")
config_ini = build_path / 'config.ini' config_ini = build_path / 'config.ini'
with config_ini.open('w') as outfile: with config_ini.open('w') as outfile:
ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_EXPORT') ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_EXPORT')
filegrp = { 'Configuration.h':'config:basic', 'Configuration_adv.h':'config:advanced' } filegrp = { 'Configuration.h':'config:basic', 'Configuration_adv.h':'config:advanced' }
vers = defines["CONFIGURATION_H_VERSION"] vers = defines["CONFIGURATION_H_VERSION"]
dt_string = datetime.now().strftime("%Y-%m-%d at %H:%M:%S") dt_string = datetime.now().strftime("%Y-%m-%d at %H:%M:%S")
ini_fmt = '{0:40}{1}\n' ini_fmt = '{0:40}{1}\n'
outfile.write( outfile.write(
'#\n' '#\n'
+ '# Marlin Firmware\n' + '# Marlin Firmware\n'
+ '# config.ini - Options to apply before the build\n' + '# config.ini - Options to apply before the build\n'
+ '#\n' + '#\n'
+ f'# Generated by Marlin build on {dt_string}\n' + f'# Generated by Marlin build on {dt_string}\n'
+ '#\n' + '#\n'
+ '\n' + '\n'
+ '[config:base]\n' + '[config:base]\n'
+ ini_fmt.format('ini_use_config', ' = all') + ini_fmt.format('ini_use_config', ' = all')
+ ini_fmt.format('ini_config_vers', f' = {vers}') + ini_fmt.format('ini_config_vers', f' = {vers}')
) )
# Loop through the data array of arrays # Loop through the data array of arrays
for header in data: for header in data:
if header.startswith('__'): if header.startswith('__'):
continue continue
outfile.write('\n[' + filegrp[header] + ']\n') outfile.write('\n[' + filegrp[header] + ']\n')
for key in sorted(data[header]): for key in sorted(data[header]):
if key not in ignore: if key not in ignore:
val = 'on' if data[header][key] == '' else data[header][key] val = 'on' if data[header][key] == '' else data[header][key]
outfile.write(ini_fmt.format(key.lower(), ' = ' + val)) outfile.write(ini_fmt.format(key.lower(), ' = ' + val))
# #
# Produce a schema.json file if CONFIG_EXPORT == 3 # Produce a schema.json file if CONFIG_EXPORT == 3
# #
if config_dump >= 3: if config_dump >= 3:
try: try:
conf_schema = schema.extract() conf_schema = schema.extract()
except Exception as exc: except Exception as exc:
print("Error: " + str(exc)) print("Error: " + str(exc))
conf_schema = None conf_schema = None
if conf_schema: if conf_schema:
# #
# Produce a schema.json file if CONFIG_EXPORT == 3 # Produce a schema.json file if CONFIG_EXPORT == 3
# #
if config_dump in (3, 13): if config_dump in (3, 13):
print("Generating schema.json ...") print("Generating schema.json ...")
schema.dump_json(conf_schema, build_path / 'schema.json') schema.dump_json(conf_schema, build_path / 'schema.json')
if config_dump == 13: if config_dump == 13:
schema.group_options(conf_schema) schema.group_options(conf_schema)
schema.dump_json(conf_schema, build_path / 'schema_grouped.json') schema.dump_json(conf_schema, build_path / 'schema_grouped.json')
# #
# Produce a schema.yml file if CONFIG_EXPORT == 4 # Produce a schema.yml file if CONFIG_EXPORT == 4
# #
elif config_dump == 4: elif config_dump == 4:
print("Generating schema.yml ...") print("Generating schema.yml ...")
try: try:
import yaml import yaml
except ImportError: except ImportError:
env.Execute(env.VerboseAction( env.Execute(env.VerboseAction(
'$PYTHONEXE -m pip install "pyyaml"', '$PYTHONEXE -m pip install "pyyaml"',
"Installing YAML for schema.yml export", "Installing YAML for schema.yml export",
)) ))
import yaml import yaml
schema.dump_yaml(conf_schema, build_path / 'schema.yml') schema.dump_yaml(conf_schema, build_path / 'schema.yml')
# Append the source code version and date # Append the source code version and date
data['VERSION'] = {} data['VERSION'] = {}
data['VERSION']['DETAILED_BUILD_VERSION'] = resolved_defines['DETAILED_BUILD_VERSION'] data['VERSION']['DETAILED_BUILD_VERSION'] = resolved_defines['DETAILED_BUILD_VERSION']
data['VERSION']['STRING_DISTRIBUTION_DATE'] = resolved_defines['STRING_DISTRIBUTION_DATE'] data['VERSION']['STRING_DISTRIBUTION_DATE'] = resolved_defines['STRING_DISTRIBUTION_DATE']
try: try:
curver = subprocess.check_output(["git", "describe", "--match=NeVeRmAtCh", "--always"]).strip() curver = subprocess.check_output(["git", "describe", "--match=NeVeRmAtCh", "--always"]).strip()
data['VERSION']['GIT_REF'] = curver.decode() data['VERSION']['GIT_REF'] = curver.decode()
except: except:
pass pass
# #
# Produce a JSON file for CONFIGURATION_EMBEDDING or CONFIG_EXPORT == 1 # Produce a JSON file for CONFIGURATION_EMBEDDING or CONFIG_EXPORT == 1
# #
if config_dump == 1 or 'CONFIGURATION_EMBEDDING' in defines: if config_dump == 1 or 'CONFIGURATION_EMBEDDING' in defines:
with marlin_json.open('w') as outfile: with marlin_json.open('w') as outfile:
json.dump(data, outfile, separators=(',', ':')) json.dump(data, outfile, separators=(',', ':'))
# #
# The rest only applies to CONFIGURATION_EMBEDDING # The rest only applies to CONFIGURATION_EMBEDDING
# #
if not 'CONFIGURATION_EMBEDDING' in defines: if not 'CONFIGURATION_EMBEDDING' in defines:
return return
# Compress the JSON file as much as we can # Compress the JSON file as much as we can
compress_file(marlin_json, marlin_zip) compress_file(marlin_json, marlin_zip)
# Generate a C source file for storing this array # Generate a C source file for storing this array
with open('Marlin/src/mczip.h','wb') as result_file: with open('Marlin/src/mczip.h','wb') as result_file:
result_file.write( result_file.write(
b'#ifndef NO_CONFIGURATION_EMBEDDING_WARNING\n' b'#ifndef NO_CONFIGURATION_EMBEDDING_WARNING\n'
+ b' #warning "Generated file \'mc.zip\' is embedded (Define NO_CONFIGURATION_EMBEDDING_WARNING to suppress this warning.)"\n' + b' #warning "Generated file \'mc.zip\' is embedded (Define NO_CONFIGURATION_EMBEDDING_WARNING to suppress this warning.)"\n'
+ b'#endif\n' + b'#endif\n'
+ b'const unsigned char mc_zip[] PROGMEM = {\n ' + b'const unsigned char mc_zip[] PROGMEM = {\n '
) )
count = 0 count = 0
for b in (build_path / 'mc.zip').open('rb').read(): for b in (build_path / 'mc.zip').open('rb').read():
result_file.write(b' 0x%02X,' % b) result_file.write(b' 0x%02X,' % b)
count += 1 count += 1
if count % 16 == 0: if count % 16 == 0:
result_file.write(b'\n ') result_file.write(b'\n ')
if count % 16: if count % 16:
result_file.write(b'\n') result_file.write(b'\n')
result_file.write(b'};\n') result_file.write(b'};\n')

63
buildroot/share/PlatformIO/scripts/simulator.py

@ -2,51 +2,52 @@
# simulator.py # simulator.py
# PlatformIO pre: script for simulator builds # PlatformIO pre: script for simulator builds
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
# Get the environment thus far for the build # Get the environment thus far for the build
Import("env") Import("env")
#print(env.Dump()) #print(env.Dump())
# #
# Give the binary a distinctive name # Give the binary a distinctive name
# #
env['PROGNAME'] = "MarlinSimulator" env['PROGNAME'] = "MarlinSimulator"
# #
# If Xcode is installed add the path to its Frameworks folder, # If Xcode is installed add the path to its Frameworks folder,
# or if Mesa is installed try to use its GL/gl.h. # or if Mesa is installed try to use its GL/gl.h.
# #
import sys import sys
if sys.platform == 'darwin': if sys.platform == 'darwin':
# #
# Silence half of the ranlib warnings. (No equivalent for 'ARFLAGS') # Silence half of the ranlib warnings. (No equivalent for 'ARFLAGS')
# #
env['RANLIBFLAGS'] += [ "-no_warning_for_no_symbols" ] env['RANLIBFLAGS'] += [ "-no_warning_for_no_symbols" ]
# Default paths for Xcode and a lucky GL/gl.h dropped by Mesa # Default paths for Xcode and a lucky GL/gl.h dropped by Mesa
xcode_path = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks" xcode_path = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks"
mesa_path = "/opt/local/include/GL/gl.h" mesa_path = "/opt/local/include/GL/gl.h"
import os.path import os.path
if os.path.exists(xcode_path): if os.path.exists(xcode_path):
env['BUILD_FLAGS'] += [ "-F" + xcode_path ] env['BUILD_FLAGS'] += [ "-F" + xcode_path ]
print("Using OpenGL framework headers from Xcode.app") print("Using OpenGL framework headers from Xcode.app")
elif os.path.exists(mesa_path): elif os.path.exists(mesa_path):
env['BUILD_FLAGS'] += [ '-D__MESA__' ] env['BUILD_FLAGS'] += [ '-D__MESA__' ]
print("Using OpenGL header from", mesa_path) print("Using OpenGL header from", mesa_path)
else: else:
print("\n\nNo OpenGL headers found. Install Xcode for matching headers, or use 'sudo port install mesa' to get a GL/gl.h.\n\n") print("\n\nNo OpenGL headers found. Install Xcode for matching headers, or use 'sudo port install mesa' to get a GL/gl.h.\n\n")
# Break out of the PIO build immediately # Break out of the PIO build immediately
sys.exit(1) sys.exit(1)

112
buildroot/share/PlatformIO/scripts/stm32_serialbuffer.py

@ -3,59 +3,59 @@
# #
import pioutil import pioutil
if pioutil.is_pio_build(): if pioutil.is_pio_build():
Import("env") Import("env")
# Get a build flag's value or None # Get a build flag's value or None
def getBuildFlagValue(name): def getBuildFlagValue(name):
for flag in build_flags: for flag in build_flags:
if isinstance(flag, list) and flag[0] == name: if isinstance(flag, list) and flag[0] == name:
return flag[1] return flag[1]
return None return None
# Get an overriding buffer size for RX or TX from the build flags # Get an overriding buffer size for RX or TX from the build flags
def getInternalSize(side): def getInternalSize(side):
return getBuildFlagValue(f"MF_{side}_BUFFER_SIZE") or \ return getBuildFlagValue(f"MF_{side}_BUFFER_SIZE") or \
getBuildFlagValue(f"SERIAL_{side}_BUFFER_SIZE") or \ getBuildFlagValue(f"SERIAL_{side}_BUFFER_SIZE") or \
getBuildFlagValue(f"USART_{side}_BUF_SIZE") getBuildFlagValue(f"USART_{side}_BUF_SIZE")
# Get the largest defined buffer size for RX or TX # Get the largest defined buffer size for RX or TX
def getBufferSize(side, default): def getBufferSize(side, default):
# Get a build flag value or fall back to the given default # Get a build flag value or fall back to the given default
internal = int(getInternalSize(side) or default) internal = int(getInternalSize(side) or default)
flag = side + "_BUFFER_SIZE" flag = side + "_BUFFER_SIZE"
# Return the largest value # Return the largest value
return max(int(mf[flag]), internal) if flag in mf else internal return max(int(mf[flag]), internal) if flag in mf else internal
# Add a build flag if it's not already defined # Add a build flag if it's not already defined
def tryAddFlag(name, value): def tryAddFlag(name, value):
if getBuildFlagValue(name) is None: if getBuildFlagValue(name) is None:
env.Append(BUILD_FLAGS=[f"-D{name}={value}"]) env.Append(BUILD_FLAGS=[f"-D{name}={value}"])
# Marlin uses the `RX_BUFFER_SIZE` \ `TX_BUFFER_SIZE` options to # Marlin uses the `RX_BUFFER_SIZE` \ `TX_BUFFER_SIZE` options to
# configure buffer sizes for receiving \ transmitting serial data. # configure buffer sizes for receiving \ transmitting serial data.
# Stm32duino uses another set of defines for the same purpose, so this # Stm32duino uses another set of defines for the same purpose, so this
# script gets the values from the configuration and uses them to define # script gets the values from the configuration and uses them to define
# `SERIAL_RX_BUFFER_SIZE` and `SERIAL_TX_BUFFER_SIZE` as global build # `SERIAL_RX_BUFFER_SIZE` and `SERIAL_TX_BUFFER_SIZE` as global build
# flags so they are available for use by the platform. # flags so they are available for use by the platform.
# #
# The script will set the value as the default one (64 bytes) # The script will set the value as the default one (64 bytes)
# or the user-configured one, whichever is higher. # or the user-configured one, whichever is higher.
# #
# Marlin's default buffer sizes are 128 for RX and 32 for TX. # Marlin's default buffer sizes are 128 for RX and 32 for TX.
# The highest value is taken (128/64). # The highest value is taken (128/64).
# #
# If MF_*_BUFFER_SIZE, SERIAL_*_BUFFER_SIZE, USART_*_BUF_SIZE, are # If MF_*_BUFFER_SIZE, SERIAL_*_BUFFER_SIZE, USART_*_BUF_SIZE, are
# defined, the first of these values will be used as the minimum. # defined, the first of these values will be used as the minimum.
build_flags = env.ParseFlags(env.get('BUILD_FLAGS'))["CPPDEFINES"] build_flags = env.ParseFlags(env.get('BUILD_FLAGS'))["CPPDEFINES"]
mf = env["MARLIN_FEATURES"] mf = env["MARLIN_FEATURES"]
# Get the largest defined buffer sizes for RX or TX, using defaults for undefined # Get the largest defined buffer sizes for RX or TX, using defaults for undefined
rxBuf = getBufferSize("RX", 128) rxBuf = getBufferSize("RX", 128)
txBuf = getBufferSize("TX", 64) txBuf = getBufferSize("TX", 64)
# Provide serial buffer sizes to the stm32duino platform # Provide serial buffer sizes to the stm32duino platform
tryAddFlag("SERIAL_RX_BUFFER_SIZE", rxBuf) tryAddFlag("SERIAL_RX_BUFFER_SIZE", rxBuf)
tryAddFlag("SERIAL_TX_BUFFER_SIZE", txBuf) tryAddFlag("SERIAL_TX_BUFFER_SIZE", txBuf)
tryAddFlag("USART_RX_BUF_SIZE", rxBuf) tryAddFlag("USART_RX_BUF_SIZE", rxBuf)
tryAddFlag("USART_TX_BUF_SIZE", txBuf) tryAddFlag("USART_TX_BUF_SIZE", txBuf)

2
buildroot/share/PlatformIO/variants/MARLIN_ARCHIM/variant.cpp

@ -413,7 +413,7 @@ void init( void )
// Disable pull-up on every pin // Disable pull-up on every pin
for (unsigned i = 0; i < PINS_COUNT; i++) for (unsigned i = 0; i < PINS_COUNT; i++)
digitalWrite(i, LOW); digitalWrite(i, LOW);
// Enable parallel access on PIO output data registers // Enable parallel access on PIO output data registers
PIOA->PIO_OWER = 0xFFFFFFFF; PIOA->PIO_OWER = 0xFFFFFFFF;

16
buildroot/share/PlatformIO/variants/MARLIN_BTT_SKR_SE_BX/hal_conf_extra.h

@ -100,11 +100,11 @@ extern "C" {
* This value is used by the RCC HAL module to compute the system frequency * This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL). * (when HSE is used as system clock source, directly or through the PLL).
*/ */
#if !defined (HSE_VALUE) #ifndef HSE_VALUE
#define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */ #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */ #endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT) #ifndef HSE_STARTUP_TIMEOUT
#define HSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for HSE start up, in ms */ #define HSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */ #endif /* HSE_STARTUP_TIMEOUT */
@ -112,7 +112,7 @@ extern "C" {
* @brief Internal oscillator (CSI) default value. * @brief Internal oscillator (CSI) default value.
* This value is the default CSI value after Reset. * This value is the default CSI value after Reset.
*/ */
#if !defined (CSI_VALUE) #ifndef CSI_VALUE
#define CSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/ #define CSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* CSI_VALUE */ #endif /* CSI_VALUE */
@ -121,7 +121,7 @@ extern "C" {
* This value is used by the RCC HAL module to compute the system frequency * This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL). * (when HSI is used as system clock source, directly or through the PLL).
*/ */
#if !defined (HSI_VALUE) #ifndef HSI_VALUE
#define HSI_VALUE ((uint32_t)64000000) /*!< Value of the Internal oscillator in Hz*/ #define HSI_VALUE ((uint32_t)64000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */ #endif /* HSI_VALUE */
@ -129,16 +129,16 @@ extern "C" {
* @brief External Low Speed oscillator (LSE) value. * @brief External Low Speed oscillator (LSE) value.
* This value is used by the UART, RTC HAL module to compute the system frequency * This value is used by the UART, RTC HAL module to compute the system frequency
*/ */
#if !defined (LSE_VALUE) #ifndef LSE_VALUE
#define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/ #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/
#endif /* LSE_VALUE */ #endif /* LSE_VALUE */
#if !defined (LSE_STARTUP_TIMEOUT) #ifndef LSE_STARTUP_TIMEOUT
#define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */ #endif /* LSE_STARTUP_TIMEOUT */
#if !defined (LSI_VALUE) #ifndef LSI_VALUE
#define LSI_VALUE ((uint32_t)32000) /*!< LSI Typical Value in Hz*/ #define LSI_VALUE ((uint32_t)32000) /*!< LSI Typical Value in Hz*/
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz #endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations The real value may vary depending on the variations
@ -148,7 +148,7 @@ in voltage and temperature.*/
* This value is used by the I2S HAL module to compute the I2S clock source * This value is used by the I2S HAL module to compute the I2S clock source
* frequency, this source is inserted directly through I2S_CKIN pad. * frequency, this source is inserted directly through I2S_CKIN pad.
*/ */
#if !defined (EXTERNAL_CLOCK_VALUE) #ifndef EXTERNAL_CLOCK_VALUE
#define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External clock in Hz*/ #define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External clock in Hz*/
#endif /* EXTERNAL_CLOCK_VALUE */ #endif /* EXTERNAL_CLOCK_VALUE */

28
buildroot/share/PlatformIO/variants/MARLIN_BTT_SKR_SE_BX/variant.cpp

@ -184,7 +184,7 @@ void SystemClockStartupInit() {
PWR->CR3 &= ~(1 << 2); // SCUEN=0 PWR->CR3 &= ~(1 << 2); // SCUEN=0
PWR->D3CR |= 3 << 14; // VOS=3,Scale1,1.15~1.26V core voltage PWR->D3CR |= 3 << 14; // VOS=3,Scale1,1.15~1.26V core voltage
while((PWR->D3CR & (1 << 13)) == 0); // Wait for the voltage to stabilize while((PWR->D3CR & (1 << 13)) == 0); // Wait for the voltage to stabilize
RCC->CR |= 1<<16; // Enable HSE RCC->CR |= 1<<16; // Enable HSE
uint16_t timeout = 0; uint16_t timeout = 0;
@ -198,9 +198,9 @@ void SystemClockStartupInit() {
RCC->PLLCKSELR |= 2 << 0; // PLLSRC[1:0] = 2, HSE for PLL clock source RCC->PLLCKSELR |= 2 << 0; // PLLSRC[1:0] = 2, HSE for PLL clock source
RCC->PLLCKSELR |= 5 << 4; // DIVM1[5:0] = pllm, Prescaler for PLL1 RCC->PLLCKSELR |= 5 << 4; // DIVM1[5:0] = pllm, Prescaler for PLL1
RCC->PLL1DIVR |= (160 - 1) << 0; // DIVN1[8:0] = plln - 1, Multiplication factor for PLL1 VCO RCC->PLL1DIVR |= (160 - 1) << 0; // DIVN1[8:0] = plln - 1, Multiplication factor for PLL1 VCO
RCC->PLL1DIVR |= (2 - 1) << 9; // DIVP1[6:0] = pllp - 1, PLL1 DIVP division factor RCC->PLL1DIVR |= (2 - 1) << 9; // DIVP1[6:0] = pllp - 1, PLL1 DIVP division factor
RCC->PLL1DIVR |= (4 - 1) << 16; // DIVQ1[6:0] = pllq - 1, PLL1 DIVQ division factor RCC->PLL1DIVR |= (4 - 1) << 16; // DIVQ1[6:0] = pllq - 1, PLL1 DIVQ division factor
RCC->PLL1DIVR |= 1 << 24; // DIVR1[6:0] = pllr - 1, PLL1 DIVR division factor RCC->PLL1DIVR |= 1 << 24; // DIVR1[6:0] = pllr - 1, PLL1 DIVR division factor
RCC->PLLCFGR |= 2 << 2; // PLL1 input (ref1_ck) clock range frequency is between 4 and 8 MHz RCC->PLLCFGR |= 2 << 2; // PLL1 input (ref1_ck) clock range frequency is between 4 and 8 MHz
RCC->PLLCFGR |= 0 << 1; // PLL1 VCO selection, 0: 192 to 836 MHz, 1 : 150 to 420 MHz RCC->PLLCFGR |= 0 << 1; // PLL1 VCO selection, 0: 192 to 836 MHz, 1 : 150 to 420 MHz
RCC->PLLCFGR |= 3 << 16; // pll1_q_ck and pll1_p_ck output is enabled RCC->PLLCFGR |= 3 << 16; // pll1_q_ck and pll1_p_ck output is enabled
@ -209,7 +209,7 @@ void SystemClockStartupInit() {
// PLL2 DIVR clock frequency = 220MHz, so that SDRAM clock can be set to 110MHz // PLL2 DIVR clock frequency = 220MHz, so that SDRAM clock can be set to 110MHz
RCC->PLLCKSELR |= 25 << 12; // DIVM2[5:0] = 25, Prescaler for PLL2 RCC->PLLCKSELR |= 25 << 12; // DIVM2[5:0] = 25, Prescaler for PLL2
RCC->PLL2DIVR |= (440 - 1) << 0; // DIVN2[8:0] = 440 - 1, Multiplication factor for PLL2 VCO RCC->PLL2DIVR |= (440 - 1) << 0; // DIVN2[8:0] = 440 - 1, Multiplication factor for PLL2 VCO
RCC->PLL2DIVR |= (2 - 1) << 9; // DIVP2[6:0] = 2-1, PLL2 DIVP division factor RCC->PLL2DIVR |= (2 - 1) << 9; // DIVP2[6:0] = 2-1, PLL2 DIVP division factor
RCC->PLL2DIVR |= (2 - 1) << 24; // DIVR2[6:0] = 2-1, PLL2 DIVR division factor RCC->PLL2DIVR |= (2 - 1) << 24; // DIVR2[6:0] = 2-1, PLL2 DIVR division factor
RCC->PLLCFGR |= 0 << 6; // PLL2RGE[1:0]=0, PLL2 input (ref2_ck) clock range frequency is between 1 and 2 MHz RCC->PLLCFGR |= 0 << 6; // PLL2RGE[1:0]=0, PLL2 input (ref2_ck) clock range frequency is between 1 and 2 MHz
@ -271,8 +271,8 @@ uint8_t MPU_Set_Protection(uint32_t baseaddr, uint32_t size, uint32_t rnum, uint
uint8_t rnr = 0; uint8_t rnr = 0;
if ((size % 32) || size == 0) return 1; if ((size % 32) || size == 0) return 1;
rnr = MPU_Convert_Bytes_To_POT(size) - 1; rnr = MPU_Convert_Bytes_To_POT(size) - 1;
SCB->SHCSR &= ~(1 << 16); //disable MemManage SCB->SHCSR &= ~(1 << 16); //disable MemManage
MPU->CTRL &= ~(1 << 0); //disable MPU MPU->CTRL &= ~(1 << 0); //disable MPU
MPU->RNR = rnum; MPU->RNR = rnum;
MPU->RBAR = baseaddr; MPU->RBAR = baseaddr;
tempreg |= 0 << 28; tempreg |= 0 << 28;
@ -286,21 +286,21 @@ uint8_t MPU_Set_Protection(uint32_t baseaddr, uint32_t size, uint32_t rnum, uint
tempreg |= 1 << 0; tempreg |= 1 << 0;
MPU->RASR = tempreg; MPU->RASR = tempreg;
MPU->CTRL = (1 << 2) | (1 << 0); //enable PRIVDEFENA MPU->CTRL = (1 << 2) | (1 << 0); //enable PRIVDEFENA
SCB->SHCSR |= 1 << 16; //enable MemManage SCB->SHCSR |= 1 << 16; //enable MemManage
return 0; return 0;
} }
void MPU_Memory_Protection(void) void MPU_Memory_Protection(void)
{ {
MPU_Set_Protection(0x20000000, 128 * 1024, 1, MPU_REGION_FULL_ACCESS, 0, 1, 1); // protect DTCM 128k, Sharing is prohibited, cache is allowed, and buffering is allowed MPU_Set_Protection(0x20000000, 128 * 1024, 1, MPU_REGION_FULL_ACCESS, 0, 1, 1); // protect DTCM 128k, Sharing is prohibited, cache is allowed, and buffering is allowed
MPU_Set_Protection(0x24000000, 512 * 1024, 2, MPU_REGION_FULL_ACCESS, 0, 1, 1); // protect AXI SRAM, Sharing is prohibited, cache is allowed, and buffering is allowed MPU_Set_Protection(0x24000000, 512 * 1024, 2, MPU_REGION_FULL_ACCESS, 0, 1, 1); // protect AXI SRAM, Sharing is prohibited, cache is allowed, and buffering is allowed
MPU_Set_Protection(0x30000000, 512 * 1024, 3, MPU_REGION_FULL_ACCESS, 0, 1, 1); // protect SRAM1~SRAM3, Sharing is prohibited, cache is allowed, and buffering is allowed MPU_Set_Protection(0x30000000, 512 * 1024, 3, MPU_REGION_FULL_ACCESS, 0, 1, 1); // protect SRAM1~SRAM3, Sharing is prohibited, cache is allowed, and buffering is allowed
MPU_Set_Protection(0x38000000, 64 * 1024, 4, MPU_REGION_FULL_ACCESS, 0, 1, 1); // protect SRAM4, Sharing is prohibited, cache is allowed, and buffering is allowed MPU_Set_Protection(0x38000000, 64 * 1024, 4, MPU_REGION_FULL_ACCESS, 0, 1, 1); // protect SRAM4, Sharing is prohibited, cache is allowed, and buffering is allowed
MPU_Set_Protection(0x60000000, 64 * 1024 * 1024, 5, MPU_REGION_FULL_ACCESS, 0, 0, 0); // protect LCD FMC 64M, No sharing, no cache, no buffering MPU_Set_Protection(0x60000000, 64 * 1024 * 1024, 5, MPU_REGION_FULL_ACCESS, 0, 0, 0); // protect LCD FMC 64M, No sharing, no cache, no buffering
MPU_Set_Protection(0XC0000000, 32 * 1024 * 1024, 6, MPU_REGION_FULL_ACCESS, 0, 1, 1); // protect SDRAM 32M, Sharing is prohibited, cache is allowed, and buffering is allowed MPU_Set_Protection(0XC0000000, 32 * 1024 * 1024, 6, MPU_REGION_FULL_ACCESS, 0, 1, 1); // protect SDRAM 32M, Sharing is prohibited, cache is allowed, and buffering is allowed
MPU_Set_Protection(0X80000000, 256 * 1024 * 1024, 7, MPU_REGION_FULL_ACCESS, 0, 0, 0); // protect NAND FLASH 256M, No sharing, no cache, no buffering MPU_Set_Protection(0X80000000, 256 * 1024 * 1024, 7, MPU_REGION_FULL_ACCESS, 0, 0, 0); // protect NAND FLASH 256M, No sharing, no cache, no buffering
} }
/** /**

20
buildroot/share/PlatformIO/variants/MARLIN_F103Rx/PeripheralPins.c

@ -136,7 +136,7 @@ WEAK const PinMap PinMap_PWM[] = {
#endif #endif
{PA_2, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 3, 0)}, // TIM2_CH3 {PA_2, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 3, 0)}, // TIM2_CH3
// {PA_2, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM2_PARTIAL_1, 3, 0)}, // TIM2_CH3 // {PA_2, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM2_PARTIAL_1, 3, 0)}, // TIM2_CH3
#if defined(STM32F103xG) #ifdef STM32F103xG
// {PA_2, TIM5, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 3, 0)}, // TIM5_CH3 // {PA_2, TIM5, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 3, 0)}, // TIM5_CH3
#endif #endif
#if defined(STM32F103xE) || defined(STM32F103xG) #if defined(STM32F103xE) || defined(STM32F103xG)
@ -148,11 +148,11 @@ WEAK const PinMap PinMap_PWM[] = {
#else #else
{PA_3, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 4, 0)}, // TIM2_CH4 {PA_3, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 4, 0)}, // TIM2_CH4
#endif #endif
#if defined(STM32F103xG) #ifdef STM32F103xG
// {PA_3, TIM9, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM9_CH2 // {PA_3, TIM9, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM9_CH2
#endif #endif
{PA_6, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM3_CH1 {PA_6, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM3_CH1
#if defined(STM32F103xG) #ifdef STM32F103xG
// {PA_6, TIM13, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM13_CH1 // {PA_6, TIM13, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM13_CH1
#endif #endif
// {PA_7, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM3_CH2 // {PA_7, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM3_CH2
@ -161,7 +161,7 @@ WEAK const PinMap PinMap_PWM[] = {
#else #else
{PA_7, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM1_PARTIAL, 1, 1)}, // TIM1_CH1N {PA_7, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM1_PARTIAL, 1, 1)}, // TIM1_CH1N
#endif #endif
#if defined(STM32F103xG) #ifdef STM32F103xG
// {PA_7, TIM14, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM14_CH1 // {PA_7, TIM14, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM14_CH1
#endif #endif
{PA_8, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM1_CH1 {PA_8, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM1_CH1
@ -196,10 +196,10 @@ WEAK const PinMap PinMap_PWM[] = {
{PB_8, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 3, 0)}, // TIM4_CH3 {PB_8, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 3, 0)}, // TIM4_CH3
{PB_9, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 4, 0)}, // TIM4_CH4 {PB_9, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 4, 0)}, // TIM4_CH4
#endif #endif
#if defined(STM32F103xG) #ifdef STM32F103xG
// {PB_8, TIM10, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM10_CH1 // {PB_8, TIM10, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM10_CH1
#endif #endif
#if defined(STM32F103xG) #ifdef STM32F103xG
// {PB_9, TIM11, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM11_CH1 // {PB_9, TIM11, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM11_CH1
#endif #endif
{PB_10, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM2_PARTIAL_2, 3, 0)}, // TIM2_CH3 {PB_10, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM2_PARTIAL_2, 3, 0)}, // TIM2_CH3
@ -208,11 +208,11 @@ WEAK const PinMap PinMap_PWM[] = {
// {PB_11, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM2_ENABLE, 4, 0)}, // TIM2_CH4 // {PB_11, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM2_ENABLE, 4, 0)}, // TIM2_CH4
{PB_13, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 1)}, // TIM1_CH1N {PB_13, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 1)}, // TIM1_CH1N
{PB_14, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 1)}, // TIM1_CH2N {PB_14, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 1)}, // TIM1_CH2N
#if defined(STM32F103xG) #ifdef STM32F103xG
// {PB_14, TIM12, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM12_CH1 // {PB_14, TIM12, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM12_CH1
#endif #endif
{PB_15, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 3, 1)}, // TIM1_CH3N {PB_15, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 3, 1)}, // TIM1_CH3N
#if defined(STM32F103xG) #ifdef STM32F103xG
// {PB_15, TIM12, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM12_CH2 // {PB_15, TIM12, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM12_CH2
#endif #endif
{PC_6, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM3_ENABLE, 1, 0)}, // TIM3_CH1 {PC_6, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM3_ENABLE, 1, 0)}, // TIM3_CH1
@ -249,7 +249,7 @@ WEAK const PinMap PinMap_UART_TX[] = {
#if defined(STM32F103xE) || defined(STM32F103xG) #if defined(STM32F103xE) || defined(STM32F103xG)
{PC_10, UART4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE)}, {PC_10, UART4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE)},
#endif #endif
#if defined(STM32F103xB) #ifdef STM32F103xB
{PC_10, USART3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_USART3_PARTIAL)}, {PC_10, USART3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_USART3_PARTIAL)},
#endif #endif
#if defined(STM32F103xE) || defined(STM32F103xG) #if defined(STM32F103xE) || defined(STM32F103xG)
@ -270,7 +270,7 @@ WEAK const PinMap PinMap_UART_RX[] = {
#if defined(STM32F103xE) || defined(STM32F103xG) #if defined(STM32F103xE) || defined(STM32F103xG)
{PC_11, UART4, STM_PIN_DATA(STM_MODE_INPUT, GPIO_PULLUP, AFIO_NONE)}, {PC_11, UART4, STM_PIN_DATA(STM_MODE_INPUT, GPIO_PULLUP, AFIO_NONE)},
#endif #endif
#if defined(STM32F103xB) #ifdef STM32F103xB
{PC_11, USART3, STM_PIN_DATA(STM_MODE_INPUT, GPIO_PULLUP, AFIO_USART3_PARTIAL)}, {PC_11, USART3, STM_PIN_DATA(STM_MODE_INPUT, GPIO_PULLUP, AFIO_USART3_PARTIAL)},
#endif #endif
#if defined(STM32F103xE) || defined(STM32F103xG) #if defined(STM32F103xE) || defined(STM32F103xG)

2
buildroot/share/PlatformIO/variants/MARLIN_F103VE_LONGER/hal_conf_custom.h

@ -171,7 +171,7 @@ extern "C" {
* Activated: CRC code is present inside driver * Activated: CRC code is present inside driver
* Deactivated: CRC code cleaned from driver * Deactivated: CRC code cleaned from driver
*/ */
#if !defined(USE_SPI_CRC) #ifndef USE_SPI_CRC
#define USE_SPI_CRC 0 #define USE_SPI_CRC 0
#endif #endif

2
buildroot/share/PlatformIO/variants/MARLIN_F103VE_LONGER/variant.h

@ -139,7 +139,7 @@ extern "C" {
#define PIN_SERIAL2_TX PA2 #define PIN_SERIAL2_TX PA2
// Extra HAL modules // Extra HAL modules
#if defined(STM32F103xE) #ifdef STM32F103xE
//#define HAL_DAC_MODULE_ENABLED (unused or maybe for the eeprom write?) //#define HAL_DAC_MODULE_ENABLED (unused or maybe for the eeprom write?)
#define HAL_SD_MODULE_ENABLED #define HAL_SD_MODULE_ENABLED
#define HAL_SRAM_MODULE_ENABLED #define HAL_SRAM_MODULE_ENABLED

16
buildroot/share/PlatformIO/variants/MARLIN_F103Vx/PeripheralPins.c

@ -143,17 +143,17 @@ WEAK const PinMap PinMap_PWM[] = {
#else #else
{PA_3, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 4, 0)}, // TIM2_CH4 {PA_3, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 4, 0)}, // TIM2_CH4
#endif #endif
#if defined(STM32F103xG) #ifdef STM32F103xG
//{PA_3, TIM9, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM9_CH2 //{PA_3, TIM9, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM9_CH2
#endif #endif
{PA_6, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM3_CH1 {PA_6, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM3_CH1
#if defined(STM32F103xG) #ifdef STM32F103xG
//{PA_6, TIM13, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM13_CH1 //{PA_6, TIM13, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM13_CH1
#endif #endif
{PA_7, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM1_PARTIAL, 1, 1)}, // TIM1_CH1N {PA_7, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM1_PARTIAL, 1, 1)}, // TIM1_CH1N
//{PA_7, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM3_CH2 //{PA_7, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM3_CH2
//{PA_7, TIM8, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 1)}, // TIM8_CH1N //{PA_7, TIM8, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 1)}, // TIM8_CH1N
#if defined(STM32F103xG) #ifdef STM32F103xG
//{PA_7, TIM14, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM14_CH1 //{PA_7, TIM14, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM14_CH1
#endif #endif
{PA_8, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM1_CH1 {PA_8, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM1_CH1
@ -185,11 +185,11 @@ WEAK const PinMap PinMap_PWM[] = {
{PB_6, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM4_CH1 {PB_6, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM4_CH1
{PB_7, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM4_CH2 {PB_7, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM4_CH2
{PB_8, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 3, 0)}, // TIM4_CH3 {PB_8, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 3, 0)}, // TIM4_CH3
#if defined(STM32F103xG) #ifdef STM32F103xG
//{PB_8, TIM10, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM10_CH1 //{PB_8, TIM10, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM10_CH1
#endif #endif
{PB_9, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 4, 0)}, // TIM4_CH4 {PB_9, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 4, 0)}, // TIM4_CH4
#if defined(STM32F103xG) #ifdef STM32F103xG
//{PB_9, TIM11, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM11_CH1 //{PB_9, TIM11, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM11_CH1
#endif #endif
{PB_10, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM2_PARTIAL_2, 3, 0)}, // TIM2_CH3 {PB_10, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM2_PARTIAL_2, 3, 0)}, // TIM2_CH3
@ -198,11 +198,11 @@ WEAK const PinMap PinMap_PWM[] = {
//{PB_11, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM2_ENABLE, 4, 0)}, // TIM2_CH4 //{PB_11, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM2_ENABLE, 4, 0)}, // TIM2_CH4
{PB_13, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 1)}, // TIM1_CH1N {PB_13, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 1)}, // TIM1_CH1N
{PB_14, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 1)}, // TIM1_CH2N {PB_14, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 1)}, // TIM1_CH2N
#if defined(STM32F103xG) #ifdef STM32F103xG
//{PB_14, TIM12, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM12_CH1 //{PB_14, TIM12, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM12_CH1
#endif #endif
{PB_15, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 3, 1)}, // TIM1_CH3N {PB_15, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 3, 1)}, // TIM1_CH3N
#if defined(STM32F103xG) #ifdef STM32F103xG
//{PB_15, TIM12, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM12_CH2 //{PB_15, TIM12, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 2, 0)}, // TIM12_CH2
#endif #endif
{PC_6, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM3_ENABLE, 1, 0)}, // TIM3_CH1 {PC_6, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM3_ENABLE, 1, 0)}, // TIM3_CH1
@ -223,7 +223,7 @@ WEAK const PinMap PinMap_PWM[] = {
{PD_13, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM4_ENABLE, 2, 0)}, // TIM4_CH2 {PD_13, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM4_ENABLE, 2, 0)}, // TIM4_CH2
{PD_14, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM4_ENABLE, 3, 0)}, // TIM4_CH3 {PD_14, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM4_ENABLE, 3, 0)}, // TIM4_CH3
{PD_15, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM4_ENABLE, 4, 0)}, // TIM4_CH4 {PD_15, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM4_ENABLE, 4, 0)}, // TIM4_CH4
#if defined(STM32F103xG) #ifdef STM32F103xG
{PE_5, TIM9, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM9_ENABLE, 1, 0)}, // TIM9_CH1 {PE_5, TIM9, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM9_ENABLE, 1, 0)}, // TIM9_CH1
{PE_6, TIM9, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM9_ENABLE, 2, 0)}, // TIM9_CH2 {PE_6, TIM9, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM9_ENABLE, 2, 0)}, // TIM9_CH2
#endif #endif

16
buildroot/share/PlatformIO/variants/MARLIN_F103Zx/hal_conf_custom.h

@ -81,15 +81,15 @@ extern "C" {
* This value is used by the RCC HAL module to compute the system frequency * This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL). * (when HSE is used as system clock source, directly or through the PLL).
*/ */
#if !defined (HSE_VALUE) #ifndef HSE_VALUE
#if defined(USE_STM3210C_EVAL) #ifdef USE_STM3210C_EVAL
#define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */ #define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */
#else #else
#define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */
#endif #endif
#endif /* HSE_VALUE */ #endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT) #ifndef HSE_STARTUP_TIMEOUT
#define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */ #endif /* HSE_STARTUP_TIMEOUT */
@ -98,14 +98,14 @@ extern "C" {
* This value is used by the RCC HAL module to compute the system frequency * This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL). * (when HSI is used as system clock source, directly or through the PLL).
*/ */
#if !defined (HSI_VALUE) #ifndef HSI_VALUE
#define HSI_VALUE 8000000U /*!< Value of the Internal oscillator in Hz */ #define HSI_VALUE 8000000U /*!< Value of the Internal oscillator in Hz */
#endif /* HSI_VALUE */ #endif /* HSI_VALUE */
/** /**
* @brief Internal Low Speed oscillator (LSI) value. * @brief Internal Low Speed oscillator (LSI) value.
*/ */
#if !defined (LSI_VALUE) #ifndef LSI_VALUE
#define LSI_VALUE 40000U /*!< LSI Typical Value in Hz */ #define LSI_VALUE 40000U /*!< LSI Typical Value in Hz */
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz #endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations The real value may vary depending on the variations
@ -114,11 +114,11 @@ extern "C" {
* @brief External Low Speed oscillator (LSE) value. * @brief External Low Speed oscillator (LSE) value.
* This value is used by the UART, RTC HAL module to compute the system frequency * This value is used by the UART, RTC HAL module to compute the system frequency
*/ */
#if !defined (LSE_VALUE) #ifndef LSE_VALUE
#define LSE_VALUE 32768U /*!< Value of the External Low Speed oscillator in Hz */ #define LSE_VALUE 32768U /*!< Value of the External Low Speed oscillator in Hz */
#endif /* LSE_VALUE */ #endif /* LSE_VALUE */
#if !defined (LSE_STARTUP_TIMEOUT) #ifndef LSE_STARTUP_TIMEOUT
#define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */ #endif /* LSE_STARTUP_TIMEOUT */
@ -129,7 +129,7 @@ extern "C" {
/** /**
* @brief This is the HAL system configuration section * @brief This is the HAL system configuration section
*/ */
#if !defined(VDD_VALUE) #ifndef VDD_VALUE
#define VDD_VALUE 3300U /*!< Value of VDD in mv */ #define VDD_VALUE 3300U /*!< Value of VDD in mv */
#endif #endif
#if !defined (TICK_INT_PRIORITY) #if !defined (TICK_INT_PRIORITY)

14
buildroot/share/PlatformIO/variants/MARLIN_F4x7Vx/hal_conf_extra.h

@ -91,11 +91,11 @@
* This value is used by the RCC HAL module to compute the system frequency * This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL). * (when HSE is used as system clock source, directly or through the PLL).
*/ */
#if !defined (HSE_VALUE) #ifndef HSE_VALUE
#define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */ #define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */ #endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT) #ifndef HSE_STARTUP_TIMEOUT
#define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */ #endif /* HSE_STARTUP_TIMEOUT */
@ -104,14 +104,14 @@
* This value is used by the RCC HAL module to compute the system frequency * This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL). * (when HSI is used as system clock source, directly or through the PLL).
*/ */
#if !defined (HSI_VALUE) #ifndef HSI_VALUE
#define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz */ #define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz */
#endif /* HSI_VALUE */ #endif /* HSI_VALUE */
/** /**
* @brief Internal Low Speed oscillator (LSI) value. * @brief Internal Low Speed oscillator (LSI) value.
*/ */
#if !defined (LSI_VALUE) #ifndef LSI_VALUE
#define LSI_VALUE 32000U /*!< LSI Typical Value in Hz */ #define LSI_VALUE 32000U /*!< LSI Typical Value in Hz */
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz #endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations The real value may vary depending on the variations
@ -119,11 +119,11 @@
/** /**
* @brief External Low Speed oscillator (LSE) value. * @brief External Low Speed oscillator (LSE) value.
*/ */
#if !defined (LSE_VALUE) #ifndef LSE_VALUE
#define LSE_VALUE 32768U /*!< Value of the External Low Speed oscillator in Hz */ #define LSE_VALUE 32768U /*!< Value of the External Low Speed oscillator in Hz */
#endif /* LSE_VALUE */ #endif /* LSE_VALUE */
#if !defined (LSE_STARTUP_TIMEOUT) #ifndef LSE_STARTUP_TIMEOUT
#define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */ #endif /* LSE_STARTUP_TIMEOUT */
@ -132,7 +132,7 @@
* This value is used by the I2S HAL module to compute the I2S clock source * This value is used by the I2S HAL module to compute the I2S clock source
* frequency, this source is inserted directly through I2S_CKIN pad. * frequency, this source is inserted directly through I2S_CKIN pad.
*/ */
#if !defined (EXTERNAL_CLOCK_VALUE) #ifndef EXTERNAL_CLOCK_VALUE
#define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External oscillator in Hz*/ #define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External oscillator in Hz*/
#endif /* EXTERNAL_CLOCK_VALUE */ #endif /* EXTERNAL_CLOCK_VALUE */

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

Loading…
Cancel
Save