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_size = 2
[{*.py,*.conf,*.sublime-project}]
[{*.py}]
indent_style = space
indent_size = 4
[{*.conf,*.sublime-project}]
indent_style = tab
indent_size = 4

31
Marlin/Configuration.h

@ -35,7 +35,7 @@
*
* Advanced settings can be found in Configuration_adv.h
*/
#define CONFIGURATION_H_VERSION 02010100
#define CONFIGURATION_H_VERSION 02010200
//===========================================================================
//============================= Getting Started =============================
@ -140,6 +140,8 @@
// Choose your own or use a service like https://www.uuidgenerator.net/version4
//#define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
// @section stepper drivers
/**
* Stepper Drivers
*
@ -239,6 +241,8 @@
//#define SINGLENOZZLE_STANDBY_FAN
#endif
// @section multi-material
/**
* Multi-Material Unit
* Set to one of these predefined models:
@ -251,6 +255,7 @@
*
* Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails.
* See additional options in Configuration_adv.h.
* :["PRUSA_MMU1", "PRUSA_MMU2", "PRUSA_MMU2S", "EXTENDABLE_EMU_MMU2", "EXTENDABLE_EMU_MMU2S"]
*/
//#define MMU_MODEL PRUSA_MMU2
@ -1627,7 +1632,7 @@
#define DISABLE_E false // Disable the extruder when not stepping
#define DISABLE_INACTIVE_EXTRUDER // Keep only the active extruder enabled
// @section machine
// @section motion
#define ALL_DRV_2208
//#define FB_4S_STOCK
@ -2160,9 +2165,8 @@
#define XY_DIAG_BD 282.8427124746
#define XY_SIDE_AD 200
// Or, set the default skew factors directly here
// to override the above measurements:
#define XY_SKEW_FACTOR 0.0
// Or, set the XY skew factor directly:
//#define XY_SKEW_FACTOR 0.0
//#define SKEW_CORRECTION_FOR_Z
#if ENABLED(SKEW_CORRECTION_FOR_Z)
@ -2171,8 +2175,10 @@
#define YZ_DIAG_AC 282.8427124746
#define YZ_DIAG_BD 282.8427124746
#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
// Enable this option for M852 to set skew at runtime
@ -2230,7 +2236,7 @@
// @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_TEMP_HOTEND 180
@ -2388,7 +2394,7 @@
*/
//#define 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
// @section security
@ -3181,10 +3187,11 @@
//
#define TOUCH_SCREEN
#if ENABLED(TOUCH_SCREEN)
#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_EDIT 50 // (ms) Button repeat delay for edit screens
#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

7
Marlin/Configuration_adv.h

@ -30,7 +30,7 @@
*
* Basic settings can be found in Configuration.h
*/
#define CONFIGURATION_ADV_H_VERSION 02010100
#define CONFIGURATION_ADV_H_VERSION 02010200
// @section develop
@ -1321,7 +1321,7 @@
//
// 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)
//#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_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
@ -1739,7 +1740,7 @@
* Adds the menu item Configuration > LCD Timeout (m) to set a wait period
* 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

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

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

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,
};
#if !defined(XPT2046_Z1_THRESHOLD)
#ifndef XPT2046_Z1_THRESHOLD
#define XPT2046_Z1_THRESHOLD 10
#endif

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

@ -27,3 +27,8 @@
#elif EITHER(I2C_EEPROM, SPI_EEPROM)
#define USE_SHARED_EEPROM 1
#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."
#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)
#error "FLASH_EEPROM_LEVELING is currently only supported on STM32F4 hardware."
#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() {
#if defined(STM32F1xx)
#ifdef STM32F1xx
volatile bool dmaEnabled = (DMAtx.Instance->CCR & DMA_CCR_EN) != RESET;
#elif defined(STM32F4xx)
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() {
#if defined(STM32F1xx)
#ifdef STM32F1xx
volatile bool dmaEnabled = (DMAtx.Instance->CCR & DMA_CCR_EN) != RESET;
#elif defined(STM32F4xx)
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
#if HAS_FREEZE_PIN
#if ENABLED(FREEZE_FEATURE)
stepper.frozen = READ(FREEZE_PIN) == FREEZE_STATE;
#endif

2
Marlin/src/core/macros.h

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

4
Marlin/src/core/types.h

@ -752,8 +752,12 @@ struct XYZEval {
// 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) 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) 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

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

@ -96,22 +96,23 @@ void BDS_Leveling::process() {
const float z_sensor = (tmp & 0x3FF) / 100.0f;
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);
if ( cur_z < config_state * 0.1f
&& config_state > 0
&& old_cur_z == cur_z
&& 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)
SERIAL_ECHOLNPGM("BD:", z_sensor, ", Z:", cur_z, "|", current_position.z);
#endif
}
else {
babystep.set_mm(Z_AXIS, 0);
//if (old_cur_z <= cur_z) Z_DIR_WRITE(!INVERT_Z_DIR);
stepper.set_directions();
}
#if ENABLED(BABYSTEPPING)
if (cur_z < config_state * 0.1f
&& config_state > 0
&& old_cur_z == cur_z
&& 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)
SERIAL_ECHOLNPGM("BD:", z_sensor, ", Z:", cur_z, "|", current_position.z);
#endif
}
else {
babystep.set_mm(Z_AXIS, 0); //if (old_cur_z <= cur_z) Z_DIR_WRITE(!INVERT_Z_DIR);
stepper.set_directions();
}
#endif
old_cur_z = cur_z;
old_buf_z = current_position.z;
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.y, 0, GRID_MAX_CELLS_Y);
float z_x0y0 = z_values[icell.x ][icell.y ], // z at lower left corner
z_x1y0 = z_values[icell.x+1][icell.y ], // z at upper left corner
z_x0y1 = z_values[icell.x ][icell.y+1], // z at lower right corner
z_x1y1 = z_values[icell.x+1][icell.y+1]; // z at upper right corner
const int8_t ncellx = _MIN(icell.x+1, GRID_MAX_CELLS_X),
ncelly = _MIN(icell.y+1, GRID_MAX_CELLS_Y);
float z_x0y0 = z_values[icell.x][icell.y], // z at lower left 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_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);
power = upower_to_ocr(menuPower);
apply_power(power);
} else
} else
apply_power(0);
}

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

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

26
Marlin/src/gcode/parser.h

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

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

@ -28,18 +28,23 @@
#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() {
if (card.flag.mounted) {
SERIAL_ECHOLNPGM(STR_BEGIN_FILE_LIST);
card.ls(
TERN_(CUSTOM_FIRMWARE_UPLOAD, parser.boolval('F'))
#if BOTH(CUSTOM_FIRMWARE_UPLOAD, LONG_FILENAME_HOST_SUPPORT)
,
#endif
TERN_(LONG_FILENAME_HOST_SUPPORT, parser.boolval('L'))
);
card.ls(TERN0(CUSTOM_FIRMWARE_UPLOAD, parser.boolval('F') << LS_ONLY_BIN)
| TERN0(LONG_FILENAME_HOST_SUPPORT, parser.boolval('L') << LS_LONG_FILENAME)
| TERN0(M20_TIMESTAMP_SUPPORT, parser.boolval('T') << LS_TIMESTAMP));
SERIAL_ECHOLNPGM(STR_END_FILE_LIST);
}
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_ADDRESS 0x27 // I2C Address of the port expander
#define IS_ULTIPANEL 1
#if ENABLED(LCD_SAINSMART_I2C_2004)
#define LCD_WIDTH 20
@ -1598,7 +1599,7 @@
// This emulated DOGM has 'touch/xpt2046', not 'tft/xpt2046'
#if ENABLED(TOUCH_SCREEN)
#if TOUCH_IDLE_SLEEP
#if TOUCH_IDLE_SLEEP_MINS
#define HAS_TOUCH_SLEEP 1
#endif
#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)
#define HAS_LEDS_OFF_FLAG 1
#endif
#ifdef DISPLAY_SLEEP_MINUTES
#if DISPLAY_SLEEP_MINUTES || TOUCH_IDLE_SLEEP_MINS
#define HAS_DISPLAY_SLEEP 1
#endif
#if HAS_DISPLAY_SLEEP || LCD_BACKLIGHT_TIMEOUT
#if HAS_DISPLAY_SLEEP || LCD_BACKLIGHT_TIMEOUT_MINS
#define HAS_GCODE_M255 1
#endif
@ -1003,7 +1003,7 @@
#endif
// 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
#endif

10
Marlin/src/inc/Conditionals_post.h

@ -3306,7 +3306,15 @@
#endif
#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
#elif defined(PREHEAT_5_LABEL)
#define PREHEAT_COUNT 5

30
Marlin/src/inc/SanityCheck.h

@ -642,6 +642,10 @@
#error "LEVEL_CORNERS_* settings have been renamed BED_TRAMMING_*."
#elif defined(LEVEL_CENTER_TOO)
#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
// 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 !HAS_CONTROLLER_FAN
#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."
#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."
#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."
#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."
#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
@ -2276,7 +2288,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
* Redundant temperature sensor config
*/
#if HAS_TEMP_REDUNDANT
#if !defined(TEMP_SENSOR_REDUNDANT_SOURCE)
#ifndef TEMP_SENSOR_REDUNDANT_SOURCE
#error "TEMP_SENSOR_REDUNDANT requires TEMP_SENSOR_REDUNDANT_SOURCE."
#elif !defined(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
#if ENABLED(ANYCUBIC_LCD_CHIRON)
#if !defined(BEEPER_PIN)
#ifndef BEEPER_PIN
#error "ANYCUBIC_LCD_CHIRON requires BEEPER_PIN"
#elif DISABLED(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
#if LCD_BACKLIGHT_TIMEOUT
#if LCD_BACKLIGHT_TIMEOUT_MINS
#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)
#error "LCD_BACKLIGHT_TIMEOUT requires LCD_BACKLIGHT_PIN."
#error "LCD_BACKLIGHT_TIMEOUT_MINS requires LCD_BACKLIGHT_PIN."
#endif
#endif

2
Marlin/src/inc/Version.h

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

5
Marlin/src/inc/Warnings.cpp

@ -707,9 +707,8 @@
#warning "Don't forget to update your TFT settings in Configuration.h."
#endif
// Ender 3 Pro (but, apparently all Creality 4.2.2 boards)
#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)."
#if ENABLED(EMIT_CREALITY_422_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). (Define EMIT_CREALITY_422_WARNING false to suppress this warning.)"
#endif
#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
#if HAS_DISPLAY_SLEEP
void MarlinUI::sleep_on() { u8g.sleepOn(); }
void MarlinUI::sleep_off() { u8g.sleepOff(); }
void MarlinUI::sleep_display(const bool sleep) { sleep ? u8g.sleepOn() : u8g.sleepOff(); }
#endif
#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
// 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*/) {
#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));
#endif
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,
uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, uint32_t value) {
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);
// Bit 7: bshow
// 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) {
//uint8_t *fvalue = (uint8_t*)&value;
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, (bShow * 0x80) | (zeroFill * 0x20) | (zeroMode * 0x10) | size);
DWIN_Word(i, color);

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

@ -204,6 +204,55 @@ bool probe_deployed = false;
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
struct Mesh_Settings {
@ -689,31 +738,13 @@ void CrealityDWINClass::Draw_Print_Screen() {
}
void CrealityDWINClass::Draw_Print_Filename(const bool reset/*=false*/) {
static uint8_t namescrl = 0;
if (reset) namescrl = 0;
typedef TextScroller<30> Scroller;
static Scroller scroller;
if (reset) scroller.reset();
if (process == Print) {
constexpr int8_t maxlen = 30;
char *outstr = filename;
size_t slen = strlen(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++;
}
Scroller::Buffer buf;
size_t outlen = 0;
const char* outstr = scroller.scroll(outlen, buf, filename);
DWIN_Draw_Rectangle(1, Color_Bg_Black, 8, 50, DWIN_WIDTH - 8, 80);
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);
@ -973,57 +1004,30 @@ void CrealityDWINClass::Popup_Select() {
}
void CrealityDWINClass::Update_Status_Bar(bool refresh/*=false*/) {
typedef TextScroller<30> Scroller;
static bool new_msg;
static uint8_t msgscrl = 0;
static Scroller scroller;
static char lastmsg[64];
if (strcmp(lastmsg, statusmsg) != 0 || refresh) {
strcpy(lastmsg, statusmsg);
msgscrl = 0;
scroller.reset();
new_msg = true;
}
size_t len = strlen(statusmsg);
int8_t pos = len;
if (pos > 30) {
pos -= msgscrl;
len = pos;
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';
Scroller::Buffer buf;
size_t len = 0;
const char* dispmsg = scroller.scroll(len, buf, statusmsg, &new_msg);
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 - 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);
}
else {
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);
}
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() {
typedef TextScroller<MENU_CHAR_LIMIT> Scroller;
static Scroller scroller;
EncoderState encoder_diffState = Encoder_ReceiveAnalyze();
static uint8_t filescrl = 0;
if (encoder_diffState == ENCODER_DIFF_NO) {
if (selection > 0) {
card.getfilename_sorted(SD_ORDER(selection - 1, card.get_num_Files()));
char * const filename = card.longest_filename();
size_t len = strlen(filename);
int8_t pos = len;
size_t pos = len;
if (!card.flag.filenameIsDir)
while (pos && filename[pos] != '.') pos--;
if (pos > MENU_CHAR_LIMIT) {
static millis_t time = 0;
if (PENDING(millis(), time)) return;
time = millis() + 200;
pos -= filescrl;
len = _MIN(pos, MENU_CHAR_LIMIT);
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';
Scroller::Buffer buf;
const char* const name = scroller.scroll(pos, buf, filename);
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);
if (-pos >= MENU_CHAR_LIMIT) filescrl = 0;
filescrl++;
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);
Draw_SD_Item(selection, selection - scrollpos);
}
filescrl = 0;
scroller.reset();
selection++; // Select Down
if (selection > scrollpos + MROWS) {
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, LBLX, MBASE(selection - scrollpos) - 14, 271, MBASE(selection - scrollpos) + 28);
Draw_SD_Item(selection, selection - scrollpos);
filescrl = 0;
scroller.reset();
selection--; // Select Up
if (selection < scrollpos) {
scrollpos--;

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

@ -39,7 +39,6 @@
enum DGUSLCD_Screens : uint8_t;
//#define DEBUG_DGUSLCD
#define DEBUG_OUT ENABLED(DEBUG_DGUSLCD)
#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
void DGUSScreenHandler::DGUSLCD_PercentageToUint8(DGUS_VP_Variable &var, void *val_ptr) {
if (var.memadr) {
uint16_t value = swap16(*(uint16_t*)val_ptr);
DEBUG_ECHOLNPGM("FAN value get:", value);
const uint16_t value = BE16_P(val_ptr);
DEBUG_ECHOLNPGM("Got percent:", value);
*(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 index = 0;
//DEBUG_ECHOPGM(" DGUSLCD_SendWaitingStatusToDisplay ", var.VP);
//DEBUG_ECHOLNPGM(" data ", swap16(index));
//DEBUG_ECHOLNPGM(" data ", BE16_P(&index));
if (period++ > DGUS_UI_WAITING_STATUS_PERIOD) {
dgusdisplay.WriteVariable(var.VP, index);
//DEBUG_ECHOLNPGM(" data ", swap16(index));
//DEBUG_ECHOLNPGM(" data ", BE16_P(&index));
if (++index >= DGUS_UI_WAITING_STATUS) index = 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) {
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) {
top_file += scroll;
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) {
celsius_t newvalue = swap16(*(uint16_t*)val_ptr);
celsius_t newvalue = BE16_P(val_ptr);
celsius_t acceptedvalue;
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) {
#if HAS_EXTRUDERS
uint16_t newvalue = swap16(*(uint16_t*)val_ptr);
const uint16_t newvalue = BE16_P(val_ptr);
uint8_t target_extruder;
switch (var.VP) {
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) {
DEBUG_ECHOLNPGM("HandleManualExtrude");
int16_t movevalue = swap16(*(uint16_t*)val_ptr);
const int16_t movevalue = BE16_P(val_ptr);
float target = movevalue * 0.01f;
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)
void DGUSScreenHandler::HandleManualMoveOption(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleManualMoveOption");
*(uint16_t*)var.memadr = swap16(*(uint16_t*)val_ptr);
*(uint16_t*)var.memadr = BE16_P(val_ptr);
}
#endif
void DGUSScreenHandler::HandleMotorLockUnlock(DGUS_VP_Variable &var, void *val_ptr) {
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"));
}
void DGUSScreenHandler::HandleSettings(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleSettings");
uint16_t value = swap16(*(uint16_t*)val_ptr);
const uint16_t value = BE16_P(val_ptr);
switch (value) {
default: break;
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) {
DEBUG_ECHOLNPGM("HandleStepPerMMChanged");
uint16_t value_raw = swap16(*(uint16_t*)val_ptr);
DEBUG_ECHOLNPGM("value_raw:", value_raw);
float value = (float)value_raw / 10;
const uint16_t value_raw = BE16_P(val_ptr);
DEBUG_ECHOLNPGM("HandleStepPerMMChanged:", value_raw);
const float value = (float)value_raw / 10;
ExtUI::axis_t axis;
switch (var.VP) {
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);
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
return;
}
void DGUSScreenHandler::HandleStepPerMMExtruderChanged(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandleStepPerMMExtruderChanged");
uint16_t value_raw = swap16(*(uint16_t*)val_ptr);
DEBUG_ECHOLNPGM("value_raw:", value_raw);
float value = (float)value_raw / 10;
const uint16_t value_raw = BE16_P(val_ptr);
DEBUG_ECHOLNPGM("HandleStepPerMMExtruderChanged:", value_raw);
const float value = (float)value_raw / 10;
ExtUI::extruder_t extruder;
switch (var.VP) {
default: return;
@ -575,7 +570,7 @@ void DGUSScreenHandler::HandleStepPerMMExtruderChanged(DGUS_VP_Variable &var, vo
void DGUSScreenHandler::HandleProbeOffsetZChanged(DGUS_VP_Variable &var, void *val_ptr) {
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);
skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
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) {
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) {
default:
switch (var.VP) {
@ -644,7 +639,7 @@ void DGUSScreenHandler::HandleHeaterControl(DGUS_VP_Variable &var, void *val_ptr
#if ENABLED(POWER_LOSS_RECOVERY)
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) {
queue.inject(F("M1000"));
dgusdisplay.WriteVariable(VP_SD_Print_Filename, filelist.filename(), 32, true);

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

@ -42,6 +42,10 @@
#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)
#include "origin/DGUSScreenHandler.h"
#elif ENABLED(DGUS_LCD_UI_MKS)

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

@ -54,9 +54,6 @@
bool DGUSAutoTurnOff = false;
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
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);
@ -108,10 +105,10 @@ void DGUSScreenHandlerMKS::DGUSLCD_SendPrintTimeToDisplay(DGUS_VP_Variable &var)
void DGUSScreenHandlerMKS::DGUSLCD_SetUint8(DGUS_VP_Variable &var, void *val_ptr) {
if (var.memadr) {
const uint16_t value = swap16(*(uint16_t*)val_ptr);
DEBUG_ECHOLNPGM("FAN value get:", value);
const uint16_t value = BE16_P(val_ptr);
DEBUG_ECHOLNPGM("Got uint8:", value);
*(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)
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 (!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) {
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
auto cs = getCurrentScreen();
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
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);
}
#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) {
const uint16_t target = swap16(*(uint16_t *)val_ptr);
const uint16_t target = BE16_P(val_ptr);
DEBUG_ECHOLNPGM(" back = 0x%x", 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) {
DEBUG_ECHOLNPGM("GetTurnOffCtrl\n");
const uint16_t value = swap16(*(uint16_t *)val_ptr);
const uint16_t value = BE16_P(val_ptr);
switch (value) {
case 0 ... 1: DGUSAutoTurnOff = (bool)value; 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) {
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);
mks_min_extrusion_temp = value;
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) {
DEBUG_ECHOLNPGM("GetZoffsetDistance");
const uint16_t value = swap16(*(uint16_t *)val_ptr);
const uint16_t value = BE16_P(val_ptr);
float val_distance = 0;
switch (value) {
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) {
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) {
const uint16_t eep_flag = swap16(*(uint16_t *)val_ptr);
const uint16_t eep_flag = BE16_P(val_ptr);
switch (eep_flag) {
case 0:
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) {
const uint16_t z_value = swap16(*(uint16_t *)val_ptr);
const uint16_t z_value = BE16_P(val_ptr);
switch (z_value) {
case 0: Z_distance = 0.01; 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) {
#if HAS_BED_PROBE
int32_t value = swap32(*(int32_t *)val_ptr);
float Offset = value / 100.0f;
const int32_t value = BE32_P(val_ptr);
const float Offset = value / 100.0f;
DEBUG_ECHOLNPGM("\nget int6 offset >> ", value, 6);
#endif
switch (var.VP) {
case VP_OFFSET_X: TERN_(HAS_BED_PROBE, probe.offset.x = Offset); break;
case VP_OFFSET_Y: TERN_(HAS_BED_PROBE, probe.offset.y = Offset); break;
case VP_OFFSET_Z: TERN_(HAS_BED_PROBE, probe.offset.z = Offset); break;
default: break;
}
settings.save();
switch (var.VP) {
default: break;
case VP_OFFSET_X: probe.offset.x = Offset; break;
case VP_OFFSET_Y: probe.offset.y = Offset; break;
case VP_OFFSET_Z: probe.offset.z = Offset; break;
}
settings.save();
#endif
}
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) {
case MKS_SimpleChinese:
DGUS_LanguageDisplay(MKS_SimpleChinese);
@ -436,10 +433,10 @@ void DGUSScreenHandlerMKS::LanguageChange(DGUS_VP_Variable &var, void *val_ptr)
#endif
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)
auto cs = getCurrentScreen();
#endif
const uint16_t lev_but = BE16_P(val_ptr);
switch (lev_but) {
case 0:
#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) {
const uint16_t mesh_dist = swap16(*(uint16_t *)val_ptr);
const uint16_t mesh_dist = BE16_P(val_ptr);
switch (mesh_dist) {
case 0: mesh_adj_distance = 0.01; 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) {
#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;
char cmd_buf[30];
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) {
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);
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) {
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
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)
void DGUSScreenHandlerMKS::TMC_ChangeConfig(DGUS_VP_Variable &var, void *val_ptr) {
#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
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) {
DEBUG_ECHOLNPGM("HandleManualMove");
int16_t movevalue = swap16(*(uint16_t*)val_ptr);
int16_t movevalue = BE16_P(val_ptr);
// Choose Move distance
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) {
const int16_t value_pos = swap16(*(int16_t*)val_ptr);
const int16_t value_pos = BE16_P(val_ptr);
switch (var.VP) {
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) {
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);
*(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) {
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;
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) {
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;
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) {
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;
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) {
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;
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) {
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;
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) {
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);
float value = (float)value_raw;
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) {
uint16_t value_travel = swap16(*(uint16_t*)val_ptr);
uint16_t value_travel = BE16_P(val_ptr);
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
}
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;
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) {
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;
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) {
uint16_t value_acc = swap16(*(uint16_t*)val_ptr);
uint16_t value_acc = BE16_P(val_ptr);
planner.settings.acceleration = (float)value_acc;
skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
}
#if ENABLED(PREVENT_COLD_EXTRUSION)
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;
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
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);
const float value = 1.0f * rawvalue;
DEBUG_ECHOLNPGM("V2:", value);
@ -1125,9 +1122,9 @@ void DGUSScreenHandlerMKS::HandleAccChange(DGUS_VP_Variable &var, void *val_ptr)
#if ENABLED(BABYSTEPPING)
void DGUSScreenHandler::HandleLiveAdjustZ(DGUS_VP_Variable &var, void *val_ptr) {
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) {
case 0:
if (step == 0.01)
@ -1159,34 +1156,26 @@ void DGUSScreenHandlerMKS::HandleAccChange(DGUS_VP_Variable &var, void *val_ptr)
z_offset_add += ZOffset_distance;
break;
default:
break;
default: break;
}
ForceCompleteUpdate();
}
#endif // BABYSTEPPING
void DGUSScreenHandlerMKS::GetManualFilament(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("GetManualFilament");
uint16_t value_len = swap16(*(uint16_t*)val_ptr);
const uint16_t value_len = BE16_P(val_ptr);
const float value = (float)value_len;
float value = (float)value_len;
DEBUG_ECHOLNPGM("Get Filament len value:", value);
DEBUG_ECHOLNPGM("GetManualFilament:", value);
distanceFilament = value;
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) {
DEBUG_ECHOLNPGM("GetManualFilamentSpeed");
uint16_t value_len = swap16(*(uint16_t*)val_ptr);
DEBUG_ECHOLNPGM("filamentSpeed_mm_s value:", value_len);
const uint16_t value_len = BE16_P(val_ptr);
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
}
@ -1205,7 +1194,7 @@ void DGUSScreenHandlerMKS::FilamentLoadUnload(DGUS_VP_Variable &var, void *val_p
if (!print_job_timer.isPaused() && !queue.ring_buffer.empty())
return;
const uint16_t val_t = swap16(*(uint16_t*)val_ptr);
const uint16_t val_t = BE16_P(val_ptr);
switch (val_t) {
default: break;
case 0:
@ -1291,7 +1280,7 @@ void DGUSScreenHandlerMKS::FilamentUnLoad(DGUS_VP_Variable &var, void *val_ptr)
uint8_t e_temp = 0;
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
preheat_option -= 10;
filament_data.action = 2;

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

@ -21,7 +21,10 @@
*/
#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_Control.h"
@ -30,11 +33,13 @@
#include "../../../inc/MarlinConfigPre.h"
#include "../../../MarlinCore.h"
#define DEBUG_DGUSLCD // Uncomment for debug messages
#define DEBUG_OUT ENABLED(DEBUG_DGUSLCD)
#include "../../../core/debug_out.h"
#define Swap16(val) ((uint16_t)(((uint16_t)(val) >> 8) |\
((uint16_t)(val) << 8)))
// New endianness swap for 32bit mcu (tested with STM32G0B1RE)
#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.
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) {
UNUSED(vp);
const int16_t feedrate = Swap16(*(int16_t*)data_ptr);
const int16_t feedrate = BE16_P(data_ptr);
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) {
const int16_t flowrate = Swap16(*(int16_t*)data_ptr);
const int16_t flowrate = BE16_P(data_ptr);
switch (vp.addr) {
default: return;
@ -246,7 +246,7 @@ void DGUSRxHandler::Flowrate(DGUS_VP &vp, void *data_ptr) {
void DGUSRxHandler::BabystepSet(DGUS_VP &vp, void *data_ptr) {
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 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) {
const int16_t temp = Swap16(*(int16_t*)data_ptr);
const int16_t temp = BE16_P(data_ptr);
switch (vp.addr) {
default: return;
@ -338,7 +338,7 @@ void DGUSRxHandler::TempTarget(DGUS_VP &vp, void *data_ptr) {
void DGUSRxHandler::TempCool(DGUS_VP &vp, void *data_ptr) {
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) {
default: return;
@ -397,7 +397,7 @@ void DGUSRxHandler::ZOffset(DGUS_VP &vp, void *data_ptr) {
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 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) {
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) {
default: return;
@ -563,7 +563,7 @@ void DGUSRxHandler::FilamentSelect(DGUS_VP &vp, void *data_ptr) {
void DGUSRxHandler::FilamentLength(DGUS_VP &vp, void *data_ptr) {
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);
@ -644,7 +644,7 @@ void DGUSRxHandler::Home(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);
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) {
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) {
default: return;
@ -846,7 +846,7 @@ void DGUSRxHandler::PIDSetTemp(DGUS_VP &vp, void *data_ptr) {
return;
}
uint16_t temp = Swap16(*(uint16_t*)data_ptr);
uint16_t temp = BE16_P(data_ptr);
switch (dgus_screen_handler.pid_heater) {
default: return;

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

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

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

@ -24,6 +24,8 @@
#include "DGUSDisplay.h"
#include "definition/DGUS_VP.h"
#define Swap16(val) ((uint16_t)(((uint16_t)(val) >> 8) | ((uint16_t)(val) << 8)))
namespace DGUSTxHandler {
#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)
namespace FTDI {
#if defined(TOUCH_UI_800x480_GENERIC)
#ifdef TOUCH_UI_800x480_GENERIC
constexpr uint8_t Pclk = 2;
constexpr uint16_t Hsize = 800;
constexpr uint16_t Vsize = 480;

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

@ -31,7 +31,7 @@
extern lv_group_t *g;
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 };
@ -48,11 +48,20 @@ void lv_draw_about() {
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);
fw_type = lv_label_create(scr, "Firmware: Marlin " SHORT_BUILD_VERSION);
lv_obj_align(fw_type, nullptr, LV_ALIGN_CENTER, 0, -20);
board = lv_label_create(scr, BOARD_INFO_NAME);
lv_obj_align(board, nullptr, LV_ALIGN_CENTER, 0, -80);
board = lv_label_create(scr, "Board: " BOARD_INFO_NAME);
lv_obj_align(board, nullptr, LV_ALIGN_CENTER, 0, -60);
fw_type = lv_label_create(scr, "Marlin " SHORT_BUILD_VERSION " (" STRING_DISTRIBUTION_DATE ")");
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() {

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

@ -407,7 +407,6 @@ namespace Language_de {
LSTR MSG_ADVANCE_K_E = _UxGT("Vorschubfaktor *");
LSTR MSG_CONTRAST = _UxGT("LCD-Kontrast");
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_BRIGHTNESS_OFF = _UxGT("LCD ausschalten");
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_CONTRAST = _UxGT("LCD Contrast");
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_BRIGHTNESS_OFF = _UxGT("Backlight Off");
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_BRIGHTNESS = _UxGT("Luminosité 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_STORE_EEPROM = _UxGT("Enregistrer 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_CONTRAST = _UxGT("Contrasto 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_BRIGHTNESS_OFF = _UxGT("Spegni Retroillum.");
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_CONTRAST = _UxGT("Kontrast 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_BRIGHTNESS_OFF = _UxGT("Podsviet. vyp.");
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_BRIGHTNESS = _UxGT("Яскравість");
#endif
LSTR MSG_LCD_TIMEOUT_SEC = _UxGT("LCD Таймаут, с");
LSTR MSG_SCREEN_TIMEOUT = _UxGT("LCD Таймаут, x");
LSTR MSG_BRIGHTNESS_OFF = _UxGT("Підсвітка вимк.");
LSTR MSG_STORE_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
#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;
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);
}
#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()
millis_t MarlinUI::screen_timeout_millis = 0;
void MarlinUI::refresh_screen_timeout() {
screen_timeout_millis = sleep_timeout_minutes ? millis() + sleep_timeout_minutes * 60UL * 1000UL : 0;
sleep_off();
sleep_display(false);
}
#endif
@ -1059,7 +1063,7 @@ void MarlinUI::init() {
reset_status_timeout(ms);
#if LCD_BACKLIGHT_TIMEOUT
#if LCD_BACKLIGHT_TIMEOUT_MINS
refresh_backlight_timeout();
#elif HAS_DISPLAY_SLEEP
refresh_screen_timeout();
@ -1169,14 +1173,14 @@ void MarlinUI::init() {
return_to_status();
#endif
#if LCD_BACKLIGHT_TIMEOUT
#if LCD_BACKLIGHT_TIMEOUT_MINS
if (backlight_off_ms && ELAPSED(ms, backlight_off_ms)) {
WRITE(LCD_BACKLIGHT_PIN, LOW); // Backlight off
backlight_off_ms = 0;
}
#elif HAS_DISPLAY_SLEEP
if (screen_timeout_millis && ELAPSED(ms, screen_timeout_millis))
sleep_on();
sleep_display();
#endif
// 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); }
#endif
#if LCD_BACKLIGHT_TIMEOUT
#define LCD_BKL_TIMEOUT_MIN 1u
#define LCD_BKL_TIMEOUT_MAX UINT16_MAX // Slightly more than 18 hours
static uint16_t lcd_backlight_timeout;
#if LCD_BACKLIGHT_TIMEOUT_MINS
static constexpr uint8_t backlight_timeout_min = 0;
static constexpr uint8_t backlight_timeout_max = 99;
static uint8_t backlight_timeout_minutes;
static millis_t backlight_off_ms;
static void refresh_backlight_timeout();
#elif HAS_DISPLAY_SLEEP
#define SLEEP_TIMEOUT_MIN 0
#define SLEEP_TIMEOUT_MAX 99
static constexpr uint8_t sleep_timeout_min = 0;
static constexpr uint8_t sleep_timeout_max = 99;
static uint8_t sleep_timeout_minutes;
static millis_t screen_timeout_millis;
static void refresh_screen_timeout();
static void sleep_on();
static void sleep_off();
static void sleep_display(const bool sleep=true);
#endif
#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
//
#if LCD_BACKLIGHT_TIMEOUT && LCD_BKL_TIMEOUT_MIN < LCD_BKL_TIMEOUT_MAX
EDIT_ITEM(uint16_4, MSG_LCD_TIMEOUT_SEC, &ui.lcd_backlight_timeout, LCD_BKL_TIMEOUT_MIN, LCD_BKL_TIMEOUT_MAX, ui.refresh_backlight_timeout);
#if LCD_BACKLIGHT_TIMEOUT_MINS
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
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
#if ENABLED(FWRETRACT)

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

@ -402,8 +402,13 @@ class MenuItem_bool : public MenuEditItemBase {
// Predefined menu item types //
#define BACK_ITEM_F(FLABEL) MENU_ITEM_F(back, FLABEL)
#define BACK_ITEM(LABEL) MENU_ITEM(back, LABEL)
#if DISABLED(DISABLE_ENCODER)
#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(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
#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() {
const bool busy = printingIsActive()
#if ENABLED(SDSUPPORT)
@ -317,6 +327,10 @@ void menu_main() {
SUBMENU(MSG_MOTION, menu_motion);
}
#if BOTH(ADVANCED_PAUSE_FEATURE, DISABLE_ENCODER)
FILAMENT_CHANGE_ITEM();
#endif
#if HAS_CUTTER
SUBMENU(MSG_CUTTER(MENU), STICKY_SCREEN(menu_spindle_laser));
#endif
@ -349,17 +363,6 @@ void menu_main() {
}
#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)
SUBMENU(MSG_INFO_MENU, menu_info);
#endif
@ -458,6 +461,10 @@ void menu_main() {
});
#endif
#if ENABLED(ADVANCED_PAUSE_FEATURE) && DISABLED(DISABLE_ENCODER)
FILAMENT_CHANGE_ITEM();
#endif
END_MENU();
}

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

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

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

@ -61,7 +61,7 @@ TouchButtons touchBt;
void TouchButtons::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() {
@ -135,7 +135,7 @@ uint8_t TouchButtons::read_buttons() {
WRITE(TFT_BACKLIGHT_PIN, HIGH);
#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

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
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;
if (!deploy()) {

18
Marlin/src/module/settings.cpp

@ -402,8 +402,8 @@ typedef struct SettingsDataStruct {
//
// Display Sleep
//
#if LCD_BACKLIGHT_TIMEOUT
uint16_t lcd_backlight_timeout; // M255 S
#if LCD_BACKLIGHT_TIMEOUT_MINS
uint8_t backlight_timeout_minutes; // M255 S
#elif HAS_DISPLAY_SLEEP
uint8_t sleep_timeout_minutes; // M255 S
#endif
@ -640,7 +640,7 @@ void MarlinSettings::postprocess() {
TERN_(HAS_LCD_CONTRAST, ui.refresh_contrast());
TERN_(HAS_LCD_BRIGHTNESS, ui.refresh_brightness());
#if LCD_BACKLIGHT_TIMEOUT
#if LCD_BACKLIGHT_TIMEOUT_MINS
ui.refresh_backlight_timeout();
#elif HAS_DISPLAY_SLEEP
ui.refresh_screen_timeout();
@ -1157,8 +1157,8 @@ void MarlinSettings::postprocess() {
//
// LCD Backlight / Sleep Timeout
//
#if LCD_BACKLIGHT_TIMEOUT
EEPROM_WRITE(ui.lcd_backlight_timeout);
#if LCD_BACKLIGHT_TIMEOUT_MINS
EEPROM_WRITE(ui.backlight_timeout_minutes);
#elif HAS_DISPLAY_SLEEP
EEPROM_WRITE(ui.sleep_timeout_minutes);
#endif
@ -2108,8 +2108,8 @@ void MarlinSettings::postprocess() {
//
// LCD Backlight / Sleep Timeout
//
#if LCD_BACKLIGHT_TIMEOUT
EEPROM_READ(ui.lcd_backlight_timeout);
#if LCD_BACKLIGHT_TIMEOUT_MINS
EEPROM_READ(ui.backlight_timeout_minutes);
#elif HAS_DISPLAY_SLEEP
EEPROM_READ(ui.sleep_timeout_minutes);
#endif
@ -3198,8 +3198,8 @@ void MarlinSettings::reset() {
//
// LCD Backlight / Sleep Timeout
//
#if LCD_BACKLIGHT_TIMEOUT
ui.lcd_backlight_timeout = LCD_BACKLIGHT_TIMEOUT;
#if LCD_BACKLIGHT_TIMEOUT_MINS
ui.backlight_timeout_minutes = LCD_BACKLIGHT_TIMEOUT_MINS;
#elif HAS_DISPLAY_SLEEP
ui.sleep_timeout_minutes = DISPLAY_SLEEP_MINUTES;
#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) {
if (TERN0(HAS_PID_DEBUG, thermalManager.pid_debug_flag)) {
SERIAL_ECHO_START();
if (name) SERIAL_ECHOLNF(name);
if (name) SERIAL_ECHOF(name);
if (index >= 0) SERIAL_ECHO(index);
SERIAL_ECHOLNPGM(
STR_PID_DEBUG_INPUT, c,
STR_PID_DEBUG_OUTPUT, pid_out
#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
);
}

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

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

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

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

6
Marlin/src/pins/pins.h

@ -512,9 +512,9 @@
#elif MB(MKS_ROBIN_MINI)
#include "stm32f1/pins_MKS_ROBIN_MINI.h" // STM32F1 env:mks_robin_mini env:mks_robin_mini_maple
#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)
#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)
#include "stm32f1/pins_MKS_ROBIN_LITE.h" // STM32F1 env:mks_robin_lite env:mks_robin_lite_maple
#elif MB(MKS_ROBIN_LITE3)
@ -694,7 +694,7 @@
#elif MB(OPULO_LUMEN_REV3)
#include "stm32f4/pins_OPULO_LUMEN_REV3.h" // STM32F4 env:Opulo_Lumen_REV3
#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)
#include "stm32f4/pins_MKS_EAGLE.h" // STM32F4 env:mks_eagle
#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
* 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 DEFAULT_MACHINE_NAME "Creality3D"
#ifndef EMIT_CREALITY_422_WARNING
#define EMIT_CREALITY_422_WARNING
#endif
#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
* 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
*/

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

@ -29,7 +29,7 @@
#define ALLOW_STM32DUINO
#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

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_NO_NATIVE_USB
#ifndef USB_MOD
#define BOARD_NO_NATIVE_USB
#endif
#define USES_DIAG_PINS
// 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."
#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
#define TEMP_TIMER 5
@ -58,9 +60,14 @@
// Limit Switches
//
#define X_STOP_PIN PA15
#define Y_STOP_PIN PA12
#define Z_MIN_PIN PA11
#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

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

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

50
Marlin/src/sd/cardreader.cpp

@ -29,6 +29,7 @@
#include "cardreader.h"
#include "../MarlinCore.h"
#include "../libs/hex_print.h"
#include "../lcd/marlinui.h"
#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
//
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];
#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
* good addition.
*/
void CardReader::printListing(
SdFile parent, const char * const prepend
OPTARG(CUSTOM_FIRMWARE_UPLOAD, bool onlyBin/*=false*/)
OPTARG(LONG_FILENAME_HOST_SUPPORT, const bool includeLongNames/*=false*/)
void CardReader::printListing(SdFile parent, const char * const prepend, const uint8_t lsflags
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;
while (parent.readDir(&p, longFilename) > 0) {
if (DIR_IS_SUBDIR(&p)) {
@ -301,19 +307,17 @@ void CardReader::printListing(
SdFile child; // child.close() in destructor
if (child.open(&parent, dosFilename, O_READ)) {
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
if (includeLongNames) {
size_t lenPrependLong = prependLong ? strlen(prependLong) + 1 : 0;
if (includeLong) {
const size_t lenPrependLong = prependLong ? strlen(prependLong) + 1 : 0;
// Allocate enough stack space for the full long path including / separator
char pathLong[lenPrependLong + strlen(longFilename) + 1];
if (prependLong) { strcpy(pathLong, prependLong); pathLong[lenPrependLong - 1] = '/'; }
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
printListing(child, path, lsflags);
}
else {
SERIAL_ECHO_MSG(STR_SD_CANT_OPEN_SUBDIR, dosFilename);
@ -325,8 +329,18 @@ void CardReader::printListing(
SERIAL_ECHO(createFilename(filename, p));
SERIAL_CHAR(' ');
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 (includeLongNames) {
if (includeLong) {
SERIAL_CHAR(' ');
if (prependLong) { SERIAL_ECHO(prependLong); SERIAL_CHAR('/'); }
SERIAL_ECHO(longFilename[0] ? longFilename : filename);
@ -340,16 +354,10 @@ void CardReader::printListing(
//
// List all files on the SD card
//
void CardReader::ls(
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*/)
) {
void CardReader::ls(const uint8_t lsflags) {
if (flag.mounted) {
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;
enum ListingFlags : uint8_t { LS_LONG_FILENAME, LS_ONLY_BIN, LS_TIMESTAMP };
#if ENABLED(AUTO_REPORT_SD_STATUS)
#include "../libs/autoreport.h"
#endif
@ -207,13 +209,7 @@ public:
FORCE_INLINE static void getfilename_sorted(const uint16_t nr) { selectFileByIndex(nr); }
#endif
static void ls(
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)
);
static void ls(const uint8_t lsflags);
#if ENABLED(POWER_LOSS_RECOVERY)
static bool jobRecoverFileExists();
@ -348,10 +344,7 @@ private:
static int countItems(SdFile dir);
static void selectByIndex(SdFile dir, const uint8_t index);
static void selectByName(SdFile dir, const char * const match);
static void printListing(
SdFile parent, const char * const prepend
OPTARG(CUSTOM_FIRMWARE_UPLOAD, const bool onlyBin=false)
OPTARG(LONG_FILENAME_HOST_SUPPORT, const bool includeLongNames=false)
static void printListing(SdFile parent, const char * const prepend, const uint8_t lsflags
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
if pioutil.is_pio_build():
from os.path import join, isfile
import shutil
from os.path import join, isfile
import shutil
Import("env")
Import("env")
mf = env["MARLIN_FEATURES"]
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"
mf = env["MARLIN_FEATURES"]
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"
serialBuf = str(max(int(rxBuf), int(txBuf), 350))
serialBuf = str(max(int(rxBuf), int(txBuf), 350))
build_flags = env.get('BUILD_FLAGS')
build_flags.append("-DSERIAL_BUFFER_SIZE=" + serialBuf)
env.Replace(BUILD_FLAGS=build_flags)
build_flags = env.get('BUILD_FLAGS')
build_flags.append("-DSERIAL_BUFFER_SIZE=" + serialBuf)
env.Replace(BUILD_FLAGS=build_flags)

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

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

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

@ -2,38 +2,45 @@
# common-cxxflags.py
# Convenience script to apply customizations to CPP flags
#
import pioutil
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 = [
#"-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)
# Useful for JTAG debugging
#
# 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"
#
# 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'])
def on_program_ready(source, target, env):
import shutil
shutil.copy(target[0].get_abspath(), env.subst("$PROJECT_BUILD_DIR/$PIOENV"))
# Useful for JTAG debugging
#
# 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'
env.AddPostAction("$PROGPATH", on_program_ready)
# 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
# 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
add_cpu_freq()
# 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
# 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
add_cpu_freq()

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

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

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

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

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

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

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

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

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

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

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

@ -4,32 +4,32 @@
import pioutil
if pioutil.is_pio_build():
import shutil
from os.path import join, isfile
from pprint import pprint
import shutil
from os.path import join, isfile
from pprint import pprint
Import("env")
Import("env")
if env.MarlinHas("POSTMORTEM_DEBUGGING"):
FRAMEWORK_DIR = env.PioPlatform().get_package_dir("framework-arduinoststm32-maple")
patchflag_path = join(FRAMEWORK_DIR, ".exc-patching-done")
if env.MarlinHas("POSTMORTEM_DEBUGGING"):
FRAMEWORK_DIR = env.PioPlatform().get_package_dir("framework-arduinoststm32-maple")
patchflag_path = join(FRAMEWORK_DIR, ".exc-patching-done")
# patch file only if we didn't do it before
if not isfile(patchflag_path):
print("Patching libmaple exception handlers")
original_file = join(FRAMEWORK_DIR, "STM32F1", "cores", "maple", "libmaple", "exc.S")
backup_file = join(FRAMEWORK_DIR, "STM32F1", "cores", "maple", "libmaple", "exc.S.bak")
src_file = join("buildroot", "share", "PlatformIO", "scripts", "exc.S")
# patch file only if we didn't do it before
if not isfile(patchflag_path):
print("Patching libmaple exception handlers")
original_file = join(FRAMEWORK_DIR, "STM32F1", "cores", "maple", "libmaple", "exc.S")
backup_file = join(FRAMEWORK_DIR, "STM32F1", "cores", "maple", "libmaple", "exc.S.bak")
src_file = join("buildroot", "share", "PlatformIO", "scripts", "exc.S")
assert isfile(original_file) and isfile(src_file)
shutil.copyfile(original_file, backup_file)
shutil.copyfile(src_file, original_file);
assert isfile(original_file) and isfile(src_file)
shutil.copyfile(original_file, backup_file)
shutil.copyfile(src_file, original_file);
def _touch(path):
with open(path, "w") as fp:
fp.write("")
def _touch(path):
with open(path, "w") as fp:
fp.write("")
env.Execute(lambda *args, **kwargs: _touch(patchflag_path))
print("Done patching exception handler")
env.Execute(lambda *args, **kwargs: _touch(patchflag_path))
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
if pioutil.is_pio_build():
import shutil,marlin
from pathlib import Path
#
# Get the platform name from the 'platform_packages' option,
# or look it up by the platform.class.name.
#
env = marlin.env
platform = env.PioPlatform()
from platformio.package.meta import PackageSpec
platform_packages = env.GetProjectOption('platform_packages')
# Remove all tool items from platform_packages
platform_packages = [x for x in platform_packages if not x.startswith("platformio/tool-")]
if len(platform_packages) == 0:
framewords = {
"Ststm32Platform": "framework-arduinoststm32",
"AtmelavrPlatform": "framework-arduino-avr"
}
platform_name = framewords[platform.__class__.__name__]
else:
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" ]:
platform_name = "framework-arduinoststm32"
FRAMEWORK_DIR = Path(platform.get_package_dir(platform_name))
assert FRAMEWORK_DIR.is_dir()
board = env.BoardConfig()
#mcu_type = board.get("build.mcu")[:-2]
variant = board.get("build.variant")
#series = mcu_type[:7].upper() + "xx"
# Prepare a new empty folder at the destination
variant_dir = FRAMEWORK_DIR / "variants" / variant
if variant_dir.is_dir():
shutil.rmtree(variant_dir)
if not variant_dir.is_dir():
variant_dir.mkdir()
# Source dir is a local variant sub-folder
source_dir = Path("buildroot/share/PlatformIO/variants", variant)
assert source_dir.is_dir()
marlin.copytree(source_dir, variant_dir)
import shutil,marlin
from pathlib import Path
#
# Get the platform name from the 'platform_packages' option,
# or look it up by the platform.class.name.
#
env = marlin.env
platform = env.PioPlatform()
from platformio.package.meta import PackageSpec
platform_packages = env.GetProjectOption('platform_packages')
# Remove all tool items from platform_packages
platform_packages = [x for x in platform_packages if not x.startswith("platformio/tool-")]
if len(platform_packages) == 0:
framewords = {
"Ststm32Platform": "framework-arduinoststm32",
"AtmelavrPlatform": "framework-arduino-avr"
}
platform_name = framewords[platform.__class__.__name__]
else:
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" ]:
platform_name = "framework-arduinoststm32"
FRAMEWORK_DIR = Path(platform.get_package_dir(platform_name))
assert FRAMEWORK_DIR.is_dir()
board = env.BoardConfig()
#mcu_type = board.get("build.mcu")[:-2]
variant = board.get("build.variant")
#series = mcu_type[:7].upper() + "xx"
# Prepare a new empty folder at the destination
variant_dir = FRAMEWORK_DIR / "variants" / variant
if variant_dir.is_dir():
shutil.rmtree(variant_dir)
if not variant_dir.is_dir():
variant_dir.mkdir()
# Source dir is a local variant sub-folder
source_dir = Path("buildroot/share/PlatformIO/variants", variant)
assert source_dir.is_dir()
marlin.copytree(source_dir, variant_dir)

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

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

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

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

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

@ -9,64 +9,64 @@ from SCons.Script import DefaultEnvironment
env = DefaultEnvironment()
def copytree(src, dst, symlinks=False, ignore=None):
for item in src.iterdir():
if item.is_dir():
shutil.copytree(item, dst / item.name, symlinks, ignore)
else:
shutil.copy2(item, dst / item.name)
for item in src.iterdir():
if item.is_dir():
shutil.copytree(item, dst / item.name, symlinks, ignore)
else:
shutil.copy2(item, dst / item.name)
def replace_define(field, value):
for define in env['CPPDEFINES']:
if define[0] == field:
env['CPPDEFINES'].remove(define)
env['CPPDEFINES'].append((field, value))
for define in env['CPPDEFINES']:
if define[0] == field:
env['CPPDEFINES'].remove(define)
env['CPPDEFINES'].append((field, value))
# Relocate the firmware to a new address, such as "0x08005000"
def relocate_firmware(address):
replace_define("VECT_TAB_ADDR", address)
replace_define("VECT_TAB_ADDR", address)
# Relocate the vector table with a new offset
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
def custom_ld_script(ldname):
apath = str(Path("buildroot/share/PlatformIO/ldscripts", ldname).resolve())
for i, flag in enumerate(env["LINKFLAGS"]):
if "-Wl,-T" in flag:
env["LINKFLAGS"][i] = "-Wl,-T" + apath
elif flag == "-T":
env["LINKFLAGS"][i + 1] = apath
apath = str(Path("buildroot/share/PlatformIO/ldscripts", ldname).resolve())
for i, flag in enumerate(env["LINKFLAGS"]):
if "-Wl,-T" in flag:
env["LINKFLAGS"][i] = "-Wl,-T" + apath
elif flag == "-T":
env["LINKFLAGS"][i + 1] = apath
# 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'.
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
mf = env["MARLIN_FEATURES"]
if "FIRMWARE_BIN" in mf: new_name = mf["FIRMWARE_BIN"]
# If FIRMWARE_BIN is defined by config, override all
mf = env["MARLIN_FEATURES"]
if "FIRMWARE_BIN" in mf: new_name = mf["FIRMWARE_BIN"]
fwpath = Path(target[0].path)
fwfile = fwpath.open("rb")
enfile = Path(target[0].dir.path, new_name).open("wb")
length = fwpath.stat().st_size
position = 0
try:
while position < length:
byte = fwfile.read(1)
if 320 <= position < 31040:
byte = chr(ord(byte) ^ key[position & 31])
if sys.version_info[0] > 2:
byte = bytes(byte, 'latin1')
enfile.write(byte)
position += 1
finally:
fwfile.close()
enfile.close()
fwpath.unlink()
fwpath = Path(target[0].path)
fwfile = fwpath.open("rb")
enfile = Path(target[0].dir.path, new_name).open("wb")
length = fwpath.stat().st_size
position = 0
try:
while position < length:
byte = fwfile.read(1)
if 320 <= position < 31040:
byte = chr(ord(byte) ^ key[position & 31])
if sys.version_info[0] > 2:
byte = bytes(byte, 'latin1')
enfile.write(byte)
position += 1
finally:
fwfile.close()
enfile.close()
fwpath.unlink()
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'
try:
with open('marlin_config.json', 'r') as infile:
conf = json.load(infile)
for key in conf:
# We don't care about the hash when restoring here
if key == '__INITIAL_HASH':
continue
if key == 'VERSION':
for k, v in sorted(conf[key].items()):
print(k + ': ' + v)
continue
# The key is the file name, so let's build it now
outfile = open('Marlin/' + key + output_suffix, 'w')
for k, v in sorted(conf[key].items()):
# Make define line now
if opt_output:
if v != '':
if '"' in v:
v = "'%s'" % v
elif ' ' in v:
v = '"%s"' % v
define = 'opt_set ' + k + ' ' + v + '\n'
else:
define = 'opt_enable ' + k + '\n'
else:
define = '#define ' + k + ' ' + v + '\n'
outfile.write(define)
outfile.close()
with open('marlin_config.json', 'r') as infile:
conf = json.load(infile)
for key in conf:
# We don't care about the hash when restoring here
if key == '__INITIAL_HASH':
continue
if key == 'VERSION':
for k, v in sorted(conf[key].items()):
print(k + ': ' + v)
continue
# The key is the file name, so let's build it now
outfile = open('Marlin/' + key + output_suffix, 'w')
for k, v in sorted(conf[key].items()):
# Make define line now
if opt_output:
if v != '':
if '"' in v:
v = "'%s'" % v
elif ' ' in v:
v = '"%s"' % v
define = 'opt_set ' + k + ' ' + v + '\n'
else:
define = 'opt_enable ' + k + '\n'
else:
define = '#define ' + k + ' ' + v + '\n'
outfile.write(define)
outfile.close()
# Try to apply changes to the actual configuration file (in order to keep useful comments)
if output_suffix != '':
# Move the existing configuration so it doesn't interfere
shutil.move('Marlin/' + key, 'Marlin/' + key + '.orig')
infile_lines = open('Marlin/' + key + '.orig', 'r').read().split('\n')
outfile = open('Marlin/' + key, 'w')
for line in infile_lines:
sline = line.strip(" \t\n\r")
if sline[:7] == "#define":
# Extract the key here (we don't care about the value)
kv = sline[8:].strip().split(' ')
if kv[0] in conf[key]:
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
del conf[key][kv[0]]
else:
outfile.write(line + '\n')
else:
outfile.write(line + '\n')
# Process any remaining defines here
for k, v in sorted(conf[key].items()):
define = '#define ' + k + ' ' + v + '\n'
outfile.write(define)
outfile.close()
# Try to apply changes to the actual configuration file (in order to keep useful comments)
if output_suffix != '':
# Move the existing configuration so it doesn't interfere
shutil.move('Marlin/' + key, 'Marlin/' + key + '.orig')
infile_lines = open('Marlin/' + key + '.orig', 'r').read().split('\n')
outfile = open('Marlin/' + key, 'w')
for line in infile_lines:
sline = line.strip(" \t\n\r")
if sline[:7] == "#define":
# Extract the key here (we don't care about the value)
kv = sline[8:].strip().split(' ')
if kv[0] in conf[key]:
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
del conf[key][kv[0]]
else:
outfile.write(line + '\n')
else:
outfile.write(line + '\n')
# Process any remaining defines here
for k, v in sorted(conf[key].items()):
define = '#define ' + k + ' ' + v + '\n'
outfile.write(define)
outfile.close()
print('Output configuration written to: ' + 'Marlin/' + key + output_suffix)
print('Output configuration written to: ' + 'Marlin/' + key + output_suffix)
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
#
# - 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_MAX_DATA_SIZE based on 'build.maximum_ram_size'.
# - Define STM32_FLASH_SIZE from 'upload.maximum_size' for use by Flash-based EEPROM emulation.
# - 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'.
# - 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.
#
import pioutil
if pioutil.is_pio_build():
import sys,marlin
env = marlin.env
board = env.BoardConfig()
board_keys = board.get("build").keys()
#
# For build.offset define LD_FLASH_OFFSET, used by ldscript.ld
#
if 'offset' in board_keys:
LD_FLASH_OFFSET = board.get("build.offset")
marlin.relocate_vtab(LD_FLASH_OFFSET)
# Flash size
maximum_flash_size = int(board.get("upload.maximum_size") / 1024)
marlin.replace_define('STM32_FLASH_SIZE', maximum_flash_size)
# Get upload.maximum_ram_size (defined by /buildroot/share/PlatformIO/boards/VARIOUS.json)
maximum_ram_size = board.get("upload.maximum_ram_size")
for i, flag in enumerate(env["LINKFLAGS"]):
if "-Wl,--defsym=LD_FLASH_OFFSET" in flag:
env["LINKFLAGS"][i] = "-Wl,--defsym=LD_FLASH_OFFSET=" + LD_FLASH_OFFSET
if "-Wl,--defsym=LD_MAX_DATA_SIZE" in flag:
env["LINKFLAGS"][i] = "-Wl,--defsym=LD_MAX_DATA_SIZE=" + str(maximum_ram_size - 40)
#
# For build.encrypt_mks rename and encode the firmware file.
#
if 'encrypt_mks' in board_keys:
# Encrypt ${PROGNAME}.bin and save it with the name given in build.encrypt_mks
def encrypt(source, target, env):
marlin.encrypt_mks(source, target, env, board.get("build.encrypt_mks"))
if board.get("build.encrypt_mks") != "":
marlin.add_post_action(encrypt)
#
# For build.rename simply rename the firmware file.
#
if 'rename' in board_keys:
def rename_target(source, target, env):
from pathlib import Path
Path(target[0].path).replace(Path(target[0].dir.path, board.get("build.rename")))
marlin.add_post_action(rename_target)
import sys,marlin
env = marlin.env
board = env.BoardConfig()
board_keys = board.get("build").keys()
#
# For build.offset define LD_FLASH_OFFSET, used by ldscript.ld
#
if 'offset' in board_keys:
LD_FLASH_OFFSET = board.get("build.offset")
marlin.relocate_vtab(LD_FLASH_OFFSET)
# Flash size
maximum_flash_size = int(board.get("upload.maximum_size") / 1024)
marlin.replace_define('STM32_FLASH_SIZE', maximum_flash_size)
# Get upload.maximum_ram_size (defined by /buildroot/share/PlatformIO/boards/VARIOUS.json)
maximum_ram_size = board.get("upload.maximum_ram_size")
for i, flag in enumerate(env["LINKFLAGS"]):
if "-Wl,--defsym=LD_FLASH_OFFSET" in flag:
env["LINKFLAGS"][i] = "-Wl,--defsym=LD_FLASH_OFFSET=" + LD_FLASH_OFFSET
if "-Wl,--defsym=LD_MAX_DATA_SIZE" in flag:
env["LINKFLAGS"][i] = "-Wl,--defsym=LD_MAX_DATA_SIZE=" + str(maximum_ram_size - 40)
#
# For build.encrypt_mks rename and encode the firmware file.
#
if 'encrypt_mks' in board_keys:
# Encrypt ${PROGNAME}.bin and save it with the name given in build.encrypt_mks
def encrypt(source, target, env):
marlin.encrypt_mks(source, target, env, board.get("build.encrypt_mks"))
if board.get("build.encrypt_mks") != "":
marlin.add_post_action(encrypt)
#
# For build.rename simply rename the firmware file.
#
if 'rename' in board_keys:
# If FIRMWARE_BIN is defined by config, override all
mf = env["MARLIN_FEATURES"]
if "FIRMWARE_BIN" in mf: new_name = mf["FIRMWARE_BIN"]
else: new_name = board.get("build.rename")
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
if pioutil.is_pio_build():
import os,sys
from os.path import join
import os,sys
from os.path import join
Import("env")
Import("env")
board = env.BoardConfig()
board_keys = board.get("build").keys()
if 'encode' in board_keys:
env.AddPostAction(
join("$BUILD_DIR", "${PROGNAME}.bin"),
env.VerboseAction(" ".join([
"$OBJCOPY", "-O", "srec",
"\"$BUILD_DIR/${PROGNAME}.elf\"", "\"" + join("$BUILD_DIR", board.get("build.encode")) + "\""
]), "Building " + board.get("build.encode"))
)
board = env.BoardConfig()
board_keys = board.get("build").keys()
if 'encode' in board_keys:
env.AddPostAction(
join("$BUILD_DIR", "${PROGNAME}.bin"),
env.VerboseAction(" ".join([
"$OBJCOPY", "-O", "srec",
"\"$BUILD_DIR/${PROGNAME}.elf\"", "\"" + join("$BUILD_DIR", 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
def is_pio_build():
from SCons.Script import DefaultEnvironment
env = DefaultEnvironment()
return not env.IsIntegrationDump()
from SCons.Script import DefaultEnvironment
env = DefaultEnvironment()
return not env.IsIntegrationDump()
def get_pio_version():
from platformio import util
return util.pioversion_to_intstr()
from platformio import util
return util.pioversion_to_intstr()

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

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

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

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

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

@ -4,6 +4,6 @@
#
import pioutil
if pioutil.is_pio_build():
from datetime import datetime
Import("env")
env['PROGNAME'] = datetime.now().strftime("firmware-%Y%m%d-%H%M%S")
from datetime import datetime
Import("env")
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
def extend_dict(d:dict, k:tuple):
if len(k) >= 1 and k[0] not in d:
d[k[0]] = {}
if len(k) >= 2 and k[1] not in d[k[0]]:
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]] = {}
if len(k) >= 1 and k[0] not in d:
d[k[0]] = {}
if len(k) >= 2 and k[1] not in d[k[0]]:
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]] = {}
grouping_patterns = [
re.compile(r'^([XYZIJKUVW]|[XYZ]2|Z[34]|E[0-7])$'),
re.compile(r'^AXIS\d$'),
re.compile(r'^(MIN|MAX)$'),
re.compile(r'^[0-8]$'),
re.compile(r'^HOTEND[0-7]$'),
re.compile(r'^(HOTENDS|BED|PROBE|COOLER)$'),
re.compile(r'^[XYZIJKUVW]M(IN|AX)$')
re.compile(r'^([XYZIJKUVW]|[XYZ]2|Z[34]|E[0-7])$'),
re.compile(r'^AXIS\d$'),
re.compile(r'^(MIN|MAX)$'),
re.compile(r'^[0-8]$'),
re.compile(r'^HOTEND[0-7]$'),
re.compile(r'^(HOTENDS|BED|PROBE|COOLER)$'),
re.compile(r'^[XYZIJKUVW]M(IN|AX)$')
]
# If the indexed part of the option name matches a pattern
# then add it to the dictionary.
def find_grouping(gdict, filekey, sectkey, optkey, pindex):
optparts = optkey.split('_')
if 1 < len(optparts) > pindex:
for patt in grouping_patterns:
if patt.match(optparts[pindex]):
subkey = optparts[pindex]
modkey = '_'.join(optparts)
optparts[pindex] = '*'
wildkey = '_'.join(optparts)
kkey = f'{filekey}|{sectkey}|{wildkey}'
if kkey not in gdict: gdict[kkey] = []
gdict[kkey].append((subkey, modkey))
optparts = optkey.split('_')
if 1 < len(optparts) > pindex:
for patt in grouping_patterns:
if patt.match(optparts[pindex]):
subkey = optparts[pindex]
modkey = '_'.join(optparts)
optparts[pindex] = '*'
wildkey = '_'.join(optparts)
kkey = f'{filekey}|{sectkey}|{wildkey}'
if kkey not in gdict: gdict[kkey] = []
gdict[kkey].append((subkey, modkey))
# Build a list of potential groups. Only those with multiple items will be grouped.
def group_options(schema):
for pindex in range(10, -1, -1):
found_groups = {}
for filekey, f in schema.items():
for sectkey, s in f.items():
for optkey in s:
find_grouping(found_groups, filekey, sectkey, optkey, pindex)
fkeys = [ k for k in found_groups.keys() ]
for kkey in fkeys:
items = found_groups[kkey]
if len(items) > 1:
f, s, w = kkey.split('|')
extend_dict(schema, (f, s, w)) # Add wildcard group to schema
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
del schema[f][s][optkey]
del found_groups[kkey]
for pindex in range(10, -1, -1):
found_groups = {}
for filekey, f in schema.items():
for sectkey, s in f.items():
for optkey in s:
find_grouping(found_groups, filekey, sectkey, optkey, pindex)
fkeys = [ k for k in found_groups.keys() ]
for kkey in fkeys:
items = found_groups[kkey]
if len(items) > 1:
f, s, w = kkey.split('|')
extend_dict(schema, (f, s, w)) # Add wildcard group to schema
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
del schema[f][s][optkey]
del found_groups[kkey]
# Extract all board names from boards.h
def load_boards():
bpath = Path("Marlin/src/core/boards.h")
if bpath.is_file():
with bpath.open() as bfile:
boards = []
for line in bfile:
if line.startswith("#define BOARD_"):
bname = line.split()[1]
if bname != "BOARD_UNKNOWN": boards.append(bname)
return "['" + "','".join(boards) + "']"
return ''
bpath = Path("Marlin/src/core/boards.h")
if bpath.is_file():
with bpath.open() as bfile:
boards = []
for line in bfile:
if line.startswith("#define BOARD_"):
bname = line.split()[1]
if bname != "BOARD_UNKNOWN": boards.append(bname)
return "['" + "','".join(boards) + "']"
return ''
#
# Extract a schema from the current configuration files
#
def extract():
# Load board names from boards.h
boards = load_boards()
# Parsing states
class Parse:
NORMAL = 0 # No condition yet
BLOCK_COMMENT = 1 # Looking for the end of the block comment
EOL_COMMENT = 2 # EOL comment started, maybe add the next comment?
GET_SENSORS = 3 # Gathering temperature sensor options
ERROR = 9 # Syntax error
# List of files to process, with shorthand
filekey = { 'Configuration.h':'basic', 'Configuration_adv.h':'advanced' }
# A JSON object to store the data
sch_out = { 'basic':{}, 'advanced':{} }
# Regex for #define NAME [VALUE] [COMMENT] with sanitized line
defgrep = re.compile(r'^(//)?\s*(#define)\s+([A-Za-z0-9_]+)\s*(.*?)\s*(//.+)?$')
# Defines to ignore
ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_EXAMPLES_DIR', 'CONFIG_EXPORT')
# Start with unknown state
state = Parse.NORMAL
# Serial ID
sid = 0
# Loop through files and parse them line by line
for fn, fk in filekey.items():
with Path("Marlin", fn).open() as fileobj:
section = 'none' # Current Settings section
line_number = 0 # Counter for the line number of the file
conditions = [] # Create a condition stack for the current file
comment_buff = [] # A temporary buffer for comments
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
join_line = False # A flag that the line should be joined with the previous one
line = '' # A line buffer to handle \ continuation
last_added_ref = None # Reference to the last added item
# Loop through the lines in the file
for the_line in fileobj.readlines():
line_number += 1
# Clean the line for easier parsing
the_line = the_line.strip()
if join_line: # A previous line is being made longer
line += (' ' if line else '') + the_line
else: # Otherwise, start the line anew
line, line_start = the_line, line_number
# If the resulting line ends with a \, don't process now.
# Strip the end off. The next line will be joined with it.
join_line = line.endswith("\\")
if join_line:
line = line[:-1].strip()
continue
else:
line_end = line_number
defmatch = defgrep.match(line)
# Special handling for EOL comments after a #define.
# At this point the #define is already digested and inserted,
# so we have to extend it
if state == Parse.EOL_COMMENT:
# If the line is not a comment, we're done with the EOL comment
if not defmatch and the_line.startswith('//'):
comment_buff.append(the_line[2:].strip())
else:
last_added_ref['comment'] = ' '.join(comment_buff)
comment_buff = []
state = Parse.NORMAL
def use_comment(c, opt, sec, bufref):
if c.startswith(':'): # If the comment starts with : then it has magic JSON
d = c[1:].strip() # Strip the leading :
cbr = c.rindex('}') if d.startswith('{') else c.rindex(']') if d.startswith('[') else 0
if cbr:
opt, cmt = c[1:cbr+1].strip(), c[cbr+1:].strip()
if cmt != '': bufref.append(cmt)
else:
opt = c[1:].strip()
elif c.startswith('@section'): # Start a new section
sec = c[8:].strip()
elif not c.startswith('========'):
bufref.append(c)
return opt, sec
# In a block comment, capture lines up to the end of the comment.
# Assume nothing follows the comment closure.
if state in (Parse.BLOCK_COMMENT, Parse.GET_SENSORS):
endpos = line.find('*/')
if endpos < 0:
cline = line
else:
cline, line = line[:endpos].strip(), line[endpos+2:].strip()
# Temperature sensors are done
if state == Parse.GET_SENSORS:
options_json = f'[ {options_json[:-2]} ]'
state = Parse.NORMAL
# Strip the leading '*' from block comments
if cline.startswith('*'): cline = cline[1:].strip()
# Collect temperature sensors
if state == Parse.GET_SENSORS:
sens = re.match(r'^(-?\d+)\s*:\s*(.+)$', cline)
if sens:
s2 = sens[2].replace("'","''")
options_json += f"{sens[1]}:'{s2}', "
elif state == Parse.BLOCK_COMMENT:
# Look for temperature sensors
if cline == "Temperature sensors available:":
state, cline = Parse.GET_SENSORS, "Temperature Sensors"
options_json, section = use_comment(cline, options_json, section, comment_buff)
# For the normal state we're looking for any non-blank line
elif state == Parse.NORMAL:
# Skip a commented define when evaluating comment opening
st = 2 if re.match(r'^//\s*#define', line) else 0
cpos1 = line.find('/*') # Start a block comment on the line?
cpos2 = line.find('//', st) # Start an end of line comment on the line?
# Only the first comment starter gets evaluated
cpos = -1
if cpos1 != -1 and (cpos1 < cpos2 or cpos2 == -1):
cpos = cpos1
comment_buff = []
state = Parse.BLOCK_COMMENT
eol_options = False
elif cpos2 != -1 and (cpos2 < cpos1 or cpos1 == -1):
cpos = cpos2
# Expire end-of-line options after first use
if cline.startswith(':'): eol_options = True
# Comment after a define may be continued on the following lines
if state == Parse.NORMAL and defmatch != None and cpos > 10:
state = Parse.EOL_COMMENT
comment_buff = []
# Process the start of a new comment
if cpos != -1:
cline, line = line[cpos+2:].strip(), line[:cpos].strip()
# Strip leading '*' from block comments
if state == Parse.BLOCK_COMMENT:
if cline.startswith('*'): cline = cline[1:].strip()
# Buffer a non-empty comment start
if cline != '':
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 line == '':
options_json = ''
continue
# Parenthesize the given expression if needed
def atomize(s):
if s == '' \
or re.match(r'^[A-Za-z0-9_]*(\([^)]+\))?$', s) \
or re.match(r'^[A-Za-z0-9_]+ == \d+?$', s):
return s
return f'({s})'
#
# The conditions stack is an array containing condition-arrays.
# Each condition-array lists the conditions for the current block.
# IF/N/DEF adds a new condition-array to the stack.
# ELSE/ELIF/ENDIF pop the condition-array.
# ELSE/ELIF negate the last item in the popped condition-array.
# ELIF adds a new condition to the end of the array.
# ELSE/ELIF re-push the condition-array.
#
cparts = line.split()
iselif, iselse = cparts[0] == '#elif', cparts[0] == '#else'
if iselif or iselse or cparts[0] == '#endif':
if len(conditions) == 0:
raise Exception(f'no #if block at line {line_number}')
# Pop the last condition-array from the stack
prev = conditions.pop()
if iselif or iselse:
prev[-1] = '!' + prev[-1] # Invert the last condition
if iselif: prev.append(atomize(line[5:].strip()))
conditions.append(prev)
elif cparts[0] == '#if':
conditions.append([ atomize(line[3:].strip()) ])
elif cparts[0] == '#ifdef':
conditions.append([ f'defined({line[6:].strip()})' ])
elif cparts[0] == '#ifndef':
conditions.append([ f'!defined({line[7:].strip()})' ])
# Handle a complete #define line
elif defmatch != None:
# Get the match groups into vars
enabled, define_name, val = defmatch[1] == None, defmatch[3], defmatch[4]
# Increment the serial ID
sid += 1
# Create a new dictionary for the current #define
define_info = {
'section': section,
'name': define_name,
'enabled': enabled,
'line': line_start,
'sid': sid
}
# Type is based on the value
if val == '':
value_type = 'switch'
elif re.match(r'^(true|false)$', val):
value_type = 'bool'
val = val == 'true'
elif re.match(r'^[-+]?\s*\d+$', val):
value_type = 'int'
val = int(val)
elif re.match(r'[-+]?\s*(\d+\.|\d*\.\d+)([eE][-+]?\d+)?[fF]?', val):
value_type = 'float'
val = float(val.replace('f',''))
else:
value_type = 'string' if val[0] == '"' \
else 'char' if val[0] == "'" \
else 'state' if re.match(r'^(LOW|HIGH)$', 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 'float[]' if re.match(r'^{(\s*[-+]?\s*(\d+\.|\d*\.\d+)([eE][-+]?\d+)?[fF]?\s*(,\s*)?)+}$', val) \
else 'array' if val[0] == '{' \
else ''
if val != '': define_info['value'] = val
if value_type != '': define_info['type'] = value_type
# Join up accumulated conditions with &&
if conditions: define_info['requires'] = ' && '.join(sum(conditions, []))
# If the comment_buff is not empty, add the comment to the info
if comment_buff:
full_comment = '\n'.join(comment_buff)
# An EOL comment will be added later
# The handling could go here instead of above
if state == Parse.EOL_COMMENT:
define_info['comment'] = ''
else:
define_info['comment'] = full_comment
comment_buff = []
# If the comment specifies units, add that to the info
units = re.match(r'^\(([^)]+)\)', full_comment)
if units:
units = units[1]
if units == 's' or units == 'sec': units = 'seconds'
define_info['units'] = units
# Set the options for the current #define
if define_name == "MOTHERBOARD" and boards != '':
define_info['options'] = boards
elif options_json != '':
define_info['options'] = options_json
if eol_options: options_json = ''
# Create section dict if it doesn't exist yet
if section not in sch_out[fk]: sch_out[fk][section] = {}
# If define has already been seen...
if define_name in sch_out[fk][section]:
info = sch_out[fk][section][define_name]
if isinstance(info, dict): info = [ info ] # Convert a single dict into a list
info.append(define_info) # Add to the list
else:
# Add the define dict with name as key
sch_out[fk][section][define_name] = define_info
if state == Parse.EOL_COMMENT:
last_added_ref = define_info
return sch_out
# Load board names from boards.h
boards = load_boards()
# Parsing states
class Parse:
NORMAL = 0 # No condition yet
BLOCK_COMMENT = 1 # Looking for the end of the block comment
EOL_COMMENT = 2 # EOL comment started, maybe add the next comment?
GET_SENSORS = 3 # Gathering temperature sensor options
ERROR = 9 # Syntax error
# List of files to process, with shorthand
filekey = { 'Configuration.h':'basic', 'Configuration_adv.h':'advanced' }
# A JSON object to store the data
sch_out = { 'basic':{}, 'advanced':{} }
# Regex for #define NAME [VALUE] [COMMENT] with sanitized line
defgrep = re.compile(r'^(//)?\s*(#define)\s+([A-Za-z0-9_]+)\s*(.*?)\s*(//.+)?$')
# Defines to ignore
ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_EXAMPLES_DIR', 'CONFIG_EXPORT')
# Start with unknown state
state = Parse.NORMAL
# Serial ID
sid = 0
# Loop through files and parse them line by line
for fn, fk in filekey.items():
with Path("Marlin", fn).open() as fileobj:
section = 'none' # Current Settings section
line_number = 0 # Counter for the line number of the file
conditions = [] # Create a condition stack for the current file
comment_buff = [] # A temporary buffer for comments
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
join_line = False # A flag that the line should be joined with the previous one
line = '' # A line buffer to handle \ continuation
last_added_ref = None # Reference to the last added item
# Loop through the lines in the file
for the_line in fileobj.readlines():
line_number += 1
# Clean the line for easier parsing
the_line = the_line.strip()
if join_line: # A previous line is being made longer
line += (' ' if line else '') + the_line
else: # Otherwise, start the line anew
line, line_start = the_line, line_number
# If the resulting line ends with a \, don't process now.
# Strip the end off. The next line will be joined with it.
join_line = line.endswith("\\")
if join_line:
line = line[:-1].strip()
continue
else:
line_end = line_number
defmatch = defgrep.match(line)
# Special handling for EOL comments after a #define.
# At this point the #define is already digested and inserted,
# so we have to extend it
if state == Parse.EOL_COMMENT:
# If the line is not a comment, we're done with the EOL comment
if not defmatch and the_line.startswith('//'):
comment_buff.append(the_line[2:].strip())
else:
last_added_ref['comment'] = ' '.join(comment_buff)
comment_buff = []
state = Parse.NORMAL
def use_comment(c, opt, sec, bufref):
if c.startswith(':'): # If the comment starts with : then it has magic JSON
d = c[1:].strip() # Strip the leading :
cbr = c.rindex('}') if d.startswith('{') else c.rindex(']') if d.startswith('[') else 0
if cbr:
opt, cmt = c[1:cbr+1].strip(), c[cbr+1:].strip()
if cmt != '': bufref.append(cmt)
else:
opt = c[1:].strip()
elif c.startswith('@section'): # Start a new section
sec = c[8:].strip()
elif not c.startswith('========'):
bufref.append(c)
return opt, sec
# In a block comment, capture lines up to the end of the comment.
# Assume nothing follows the comment closure.
if state in (Parse.BLOCK_COMMENT, Parse.GET_SENSORS):
endpos = line.find('*/')
if endpos < 0:
cline = line
else:
cline, line = line[:endpos].strip(), line[endpos+2:].strip()
# Temperature sensors are done
if state == Parse.GET_SENSORS:
options_json = f'[ {options_json[:-2]} ]'
state = Parse.NORMAL
# Strip the leading '*' from block comments
if cline.startswith('*'): cline = cline[1:].strip()
# Collect temperature sensors
if state == Parse.GET_SENSORS:
sens = re.match(r'^(-?\d+)\s*:\s*(.+)$', cline)
if sens:
s2 = sens[2].replace("'","''")
options_json += f"{sens[1]}:'{s2}', "
elif state == Parse.BLOCK_COMMENT:
# Look for temperature sensors
if cline == "Temperature sensors available:":
state, cline = Parse.GET_SENSORS, "Temperature Sensors"
options_json, section = use_comment(cline, options_json, section, comment_buff)
# For the normal state we're looking for any non-blank line
elif state == Parse.NORMAL:
# Skip a commented define when evaluating comment opening
st = 2 if re.match(r'^//\s*#define', line) else 0
cpos1 = line.find('/*') # Start a block comment on the line?
cpos2 = line.find('//', st) # Start an end of line comment on the line?
# Only the first comment starter gets evaluated
cpos = -1
if cpos1 != -1 and (cpos1 < cpos2 or cpos2 == -1):
cpos = cpos1
comment_buff = []
state = Parse.BLOCK_COMMENT
eol_options = False
elif cpos2 != -1 and (cpos2 < cpos1 or cpos1 == -1):
cpos = cpos2
# Comment after a define may be continued on the following lines
if defmatch != None and cpos > 10:
state = Parse.EOL_COMMENT
comment_buff = []
# Process the start of a new comment
if cpos != -1:
cline, line = line[cpos+2:].strip(), line[:cpos].strip()
if state == Parse.BLOCK_COMMENT:
# Strip leading '*' from block comments
if cline.startswith('*'): cline = cline[1:].strip()
else:
# Expire end-of-line options after first use
if cline.startswith(':'): eol_options = True
# Buffer a non-empty comment start
if cline != '':
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 line == '':
options_json = ''
continue
# Parenthesize the given expression if needed
def atomize(s):
if s == '' \
or re.match(r'^[A-Za-z0-9_]*(\([^)]+\))?$', s) \
or re.match(r'^[A-Za-z0-9_]+ == \d+?$', s):
return s
return f'({s})'
#
# The conditions stack is an array containing condition-arrays.
# Each condition-array lists the conditions for the current block.
# IF/N/DEF adds a new condition-array to the stack.
# ELSE/ELIF/ENDIF pop the condition-array.
# ELSE/ELIF negate the last item in the popped condition-array.
# ELIF adds a new condition to the end of the array.
# ELSE/ELIF re-push the condition-array.
#
cparts = line.split()
iselif, iselse = cparts[0] == '#elif', cparts[0] == '#else'
if iselif or iselse or cparts[0] == '#endif':
if len(conditions) == 0:
raise Exception(f'no #if block at line {line_number}')
# Pop the last condition-array from the stack
prev = conditions.pop()
if iselif or iselse:
prev[-1] = '!' + prev[-1] # Invert the last condition
if iselif: prev.append(atomize(line[5:].strip()))
conditions.append(prev)
elif cparts[0] == '#if':
conditions.append([ atomize(line[3:].strip()) ])
elif cparts[0] == '#ifdef':
conditions.append([ f'defined({line[6:].strip()})' ])
elif cparts[0] == '#ifndef':
conditions.append([ f'!defined({line[7:].strip()})' ])
# Handle a complete #define line
elif defmatch != None:
# Get the match groups into vars
enabled, define_name, val = defmatch[1] == None, defmatch[3], defmatch[4]
# Increment the serial ID
sid += 1
# Create a new dictionary for the current #define
define_info = {
'section': section,
'name': define_name,
'enabled': enabled,
'line': line_start,
'sid': sid
}
# Type is based on the value
if val == '':
value_type = 'switch'
elif re.match(r'^(true|false)$', val):
value_type = 'bool'
val = val == 'true'
elif re.match(r'^[-+]?\s*\d+$', val):
value_type = 'int'
val = int(val)
elif re.match(r'[-+]?\s*(\d+\.|\d*\.\d+)([eE][-+]?\d+)?[fF]?', val):
value_type = 'float'
val = float(val.replace('f',''))
else:
value_type = 'string' if val[0] == '"' \
else 'char' if val[0] == "'" \
else 'state' if re.match(r'^(LOW|HIGH)$', 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 'float[]' if re.match(r'^{(\s*[-+]?\s*(\d+\.|\d*\.\d+)([eE][-+]?\d+)?[fF]?\s*(,\s*)?)+}$', val) \
else 'array' if val[0] == '{' \
else ''
if val != '': define_info['value'] = val
if value_type != '': define_info['type'] = value_type
# Join up accumulated conditions with &&
if conditions: define_info['requires'] = ' && '.join(sum(conditions, []))
# If the comment_buff is not empty, add the comment to the info
if comment_buff:
full_comment = '\n'.join(comment_buff)
# An EOL comment will be added later
# The handling could go here instead of above
if state == Parse.EOL_COMMENT:
define_info['comment'] = ''
else:
define_info['comment'] = full_comment
comment_buff = []
# If the comment specifies units, add that to the info
units = re.match(r'^\(([^)]+)\)', full_comment)
if units:
units = units[1]
if units == 's' or units == 'sec': units = 'seconds'
define_info['units'] = units
# Set the options for the current #define
if define_name == "MOTHERBOARD" and boards != '':
define_info['options'] = boards
elif options_json != '':
define_info['options'] = options_json
if eol_options: options_json = ''
# Create section dict if it doesn't exist yet
if section not in sch_out[fk]: sch_out[fk][section] = {}
# If define has already been seen...
if define_name in sch_out[fk][section]:
info = sch_out[fk][section][define_name]
if isinstance(info, dict): info = [ info ] # Convert a single dict into a list
info.append(define_info) # Add to the list
else:
# Add the define dict with name as key
sch_out[fk][section][define_name] = define_info
if state == Parse.EOL_COMMENT:
last_added_ref = define_info
return sch_out
def dump_json(schema:dict, jpath:Path):
with jpath.open('w') as jfile:
json.dump(schema, jfile, ensure_ascii=False, indent=2)
with jpath.open('w') as jfile:
json.dump(schema, jfile, ensure_ascii=False, indent=2)
def dump_yaml(schema:dict, ypath:Path):
import yaml
with ypath.open('w') as yfile:
yaml.dump(schema, yfile, default_flow_style=False, width=120, indent=2)
import yaml
with ypath.open('w') as yfile:
yaml.dump(schema, yfile, default_flow_style=False, width=120, indent=2)
def main():
try:
schema = extract()
except Exception as exc:
print("Error: " + str(exc))
schema = None
if schema:
print("Generating JSON ...")
dump_json(schema, Path('schema.json'))
group_options(schema)
dump_json(schema, Path('schema_grouped.json'))
try:
import yaml
except ImportError:
print("Installing YAML module ...")
import subprocess
subprocess.run(['python3', '-m', 'pip', 'install', 'pyyaml'])
import yaml
print("Generating YML ...")
dump_yaml(schema, Path('schema.yml'))
try:
schema = extract()
except Exception as exc:
print("Error: " + str(exc))
schema = None
if schema:
# Get the first command line argument
import sys
if len(sys.argv) > 1:
arg = sys.argv[1]
else:
arg = 'some'
# JSON schema
if arg in ['some', 'json', 'jsons']:
print("Generating JSON ...")
dump_json(schema, Path('schema.json'))
# JSON schema (wildcard names)
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__':
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.
#
def extract_defines(filepath):
f = open(filepath, encoding="utf8").read().split("\n")
a = []
for line in f:
sline = line.strip()
if sline[:7] == "#define":
# Extract the key here (we don't care about the value)
kv = sline[8:].strip().split()
a.append(kv[0])
return a
f = open(filepath, encoding="utf8").read().split("\n")
a = []
for line in f:
sline = line.strip()
if sline[:7] == "#define":
# Extract the key here (we don't care about the value)
kv = sline[8:].strip().split()
a.append(kv[0])
return a
# Compute the SHA256 hash of a file
def get_file_sha256sum(filepath):
sha256_hash = hashlib.sha256()
with open(filepath,"rb") as f:
# Read and update hash string value in blocks of 4K
for byte_block in iter(lambda: f.read(4096),b""):
sha256_hash.update(byte_block)
return sha256_hash.hexdigest()
sha256_hash = hashlib.sha256()
with open(filepath,"rb") as f:
# Read and update hash string value in blocks of 4K
for byte_block in iter(lambda: f.read(4096),b""):
sha256_hash.update(byte_block)
return sha256_hash.hexdigest()
#
# Compress a JSON file into a zip file
#
import zipfile
def compress_file(filepath, outpath):
with zipfile.ZipFile(outpath, 'w', compression=zipfile.ZIP_BZIP2, compresslevel=9) as zipf:
zipf.write(filepath, compress_type=zipfile.ZIP_BZIP2, compresslevel=9)
with zipfile.ZipFile(outpath, 'w', compression=zipfile.ZIP_BZIP2, compresslevel=9) as zipf:
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
@ -49,228 +49,228 @@ def compress_file(filepath, outpath):
# We can reverse the signature to get a 1:1 equivalent configuration file
#
def compute_build_signature(env):
if 'BUILD_SIGNATURE' in env:
return
# Definitions from these files will be kept
files_to_keep = [ 'Marlin/Configuration.h', 'Marlin/Configuration_adv.h' ]
build_path = Path(env['PROJECT_BUILD_DIR'], env['PIOENV'])
# Check if we can skip processing
hashes = ''
for header in files_to_keep:
hashes += get_file_sha256sum(header)[0:10]
marlin_json = build_path / 'marlin_config.json'
marlin_zip = build_path / 'mc.zip'
# Read existing config file
try:
with marlin_json.open() as infile:
conf = json.load(infile)
if conf['__INITIAL_HASH'] == hashes:
# Same configuration, skip recomputing the building signature
compress_file(marlin_json, marlin_zip)
return
except:
pass
# Get enabled config options based on preprocessor
from preprocessor import run_preprocessor
complete_cfg = run_preprocessor(env)
# Dumb #define extraction from the configuration files
conf_defines = {}
all_defines = []
for header in files_to_keep:
defines = extract_defines(header)
# To filter only the define we want
all_defines += defines
# To remember from which file it cames from
conf_defines[header.split('/')[-1]] = defines
r = re.compile(r"\(+(\s*-*\s*_.*)\)+")
# First step is to collect all valid macros
defines = {}
for line in complete_cfg:
# Split the define from the value
key_val = line[8:].strip().decode().split(' ')
key, value = key_val[0], ' '.join(key_val[1:])
# Ignore values starting with two underscore, since it's low level
if len(key) > 2 and key[0:2] == "__" :
continue
# Ignore values containing a parenthesis (likely a function macro)
if '(' in key and ')' in key:
continue
# Then filter dumb values
if r.match(value):
continue
defines[key] = value if len(value) else ""
#
# Continue to gather data for CONFIGURATION_EMBEDDING or CONFIG_EXPORT
#
if not ('CONFIGURATION_EMBEDDING' in defines or 'CONFIG_EXPORT' in defines):
return
# Second step is to filter useless macro
resolved_defines = {}
for key in defines:
# Remove all boards now
if key.startswith("BOARD_") and key != "BOARD_INFO_NAME":
continue
# 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":
continue
# Remove all keys ending by "_T_DECLARED" as it's a copy of extraneous system stuff
if key.endswith("_T_DECLARED"):
continue
# 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' ]:
continue
# Don't be that smart guy here
resolved_defines[key] = defines[key]
# Generate a build signature now
# We are making an object that's a bit more complex than a basic dictionary here
data = {}
data['__INITIAL_HASH'] = hashes
# First create a key for each header here
for header in conf_defines:
data[header] = {}
# Then populate the object where each key is going to (that's a O(N^2) algorithm here...)
for key in resolved_defines:
for header in conf_defines:
if key in conf_defines[header]:
data[header][key] = resolved_defines[key]
# Every python needs this toy
def tryint(key):
try:
return int(defines[key])
except:
return 0
config_dump = tryint('CONFIG_EXPORT')
#
# Produce an INI file if CONFIG_EXPORT == 2
#
if config_dump == 2:
print("Generating config.ini ...")
config_ini = build_path / 'config.ini'
with config_ini.open('w') as outfile:
ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_EXPORT')
filegrp = { 'Configuration.h':'config:basic', 'Configuration_adv.h':'config:advanced' }
vers = defines["CONFIGURATION_H_VERSION"]
dt_string = datetime.now().strftime("%Y-%m-%d at %H:%M:%S")
ini_fmt = '{0:40}{1}\n'
outfile.write(
'#\n'
+ '# Marlin Firmware\n'
+ '# config.ini - Options to apply before the build\n'
+ '#\n'
+ f'# Generated by Marlin build on {dt_string}\n'
+ '#\n'
+ '\n'
+ '[config:base]\n'
+ ini_fmt.format('ini_use_config', ' = all')
+ ini_fmt.format('ini_config_vers', f' = {vers}')
)
# Loop through the data array of arrays
for header in data:
if header.startswith('__'):
continue
outfile.write('\n[' + filegrp[header] + ']\n')
for key in sorted(data[header]):
if key not in ignore:
val = 'on' if data[header][key] == '' else data[header][key]
outfile.write(ini_fmt.format(key.lower(), ' = ' + val))
#
# Produce a schema.json file if CONFIG_EXPORT == 3
#
if config_dump >= 3:
try:
conf_schema = schema.extract()
except Exception as exc:
print("Error: " + str(exc))
conf_schema = None
if conf_schema:
#
# Produce a schema.json file if CONFIG_EXPORT == 3
#
if config_dump in (3, 13):
print("Generating schema.json ...")
schema.dump_json(conf_schema, build_path / 'schema.json')
if config_dump == 13:
schema.group_options(conf_schema)
schema.dump_json(conf_schema, build_path / 'schema_grouped.json')
#
# Produce a schema.yml file if CONFIG_EXPORT == 4
#
elif config_dump == 4:
print("Generating schema.yml ...")
try:
import yaml
except ImportError:
env.Execute(env.VerboseAction(
'$PYTHONEXE -m pip install "pyyaml"',
"Installing YAML for schema.yml export",
))
import yaml
schema.dump_yaml(conf_schema, build_path / 'schema.yml')
# Append the source code version and date
data['VERSION'] = {}
data['VERSION']['DETAILED_BUILD_VERSION'] = resolved_defines['DETAILED_BUILD_VERSION']
data['VERSION']['STRING_DISTRIBUTION_DATE'] = resolved_defines['STRING_DISTRIBUTION_DATE']
try:
curver = subprocess.check_output(["git", "describe", "--match=NeVeRmAtCh", "--always"]).strip()
data['VERSION']['GIT_REF'] = curver.decode()
except:
pass
#
# Produce a JSON file for CONFIGURATION_EMBEDDING or CONFIG_EXPORT == 1
#
if config_dump == 1 or 'CONFIGURATION_EMBEDDING' in defines:
with marlin_json.open('w') as outfile:
json.dump(data, outfile, separators=(',', ':'))
#
# The rest only applies to CONFIGURATION_EMBEDDING
#
if not 'CONFIGURATION_EMBEDDING' in defines:
return
# Compress the JSON file as much as we can
compress_file(marlin_json, marlin_zip)
# Generate a C source file for storing this array
with open('Marlin/src/mczip.h','wb') as result_file:
result_file.write(
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'#endif\n'
+ b'const unsigned char mc_zip[] PROGMEM = {\n '
)
count = 0
for b in (build_path / 'mc.zip').open('rb').read():
result_file.write(b' 0x%02X,' % b)
count += 1
if count % 16 == 0:
result_file.write(b'\n ')
if count % 16:
result_file.write(b'\n')
result_file.write(b'};\n')
if 'BUILD_SIGNATURE' in env:
return
# Definitions from these files will be kept
files_to_keep = [ 'Marlin/Configuration.h', 'Marlin/Configuration_adv.h' ]
build_path = Path(env['PROJECT_BUILD_DIR'], env['PIOENV'])
# Check if we can skip processing
hashes = ''
for header in files_to_keep:
hashes += get_file_sha256sum(header)[0:10]
marlin_json = build_path / 'marlin_config.json'
marlin_zip = build_path / 'mc.zip'
# Read existing config file
try:
with marlin_json.open() as infile:
conf = json.load(infile)
if conf['__INITIAL_HASH'] == hashes:
# Same configuration, skip recomputing the building signature
compress_file(marlin_json, marlin_zip)
return
except:
pass
# Get enabled config options based on preprocessor
from preprocessor import run_preprocessor
complete_cfg = run_preprocessor(env)
# Dumb #define extraction from the configuration files
conf_defines = {}
all_defines = []
for header in files_to_keep:
defines = extract_defines(header)
# To filter only the define we want
all_defines += defines
# To remember from which file it cames from
conf_defines[header.split('/')[-1]] = defines
r = re.compile(r"\(+(\s*-*\s*_.*)\)+")
# First step is to collect all valid macros
defines = {}
for line in complete_cfg:
# Split the define from the value
key_val = line[8:].strip().decode().split(' ')
key, value = key_val[0], ' '.join(key_val[1:])
# Ignore values starting with two underscore, since it's low level
if len(key) > 2 and key[0:2] == "__" :
continue
# Ignore values containing a parenthesis (likely a function macro)
if '(' in key and ')' in key:
continue
# Then filter dumb values
if r.match(value):
continue
defines[key] = value if len(value) else ""
#
# Continue to gather data for CONFIGURATION_EMBEDDING or CONFIG_EXPORT
#
if not ('CONFIGURATION_EMBEDDING' in defines or 'CONFIG_EXPORT' in defines):
return
# Second step is to filter useless macro
resolved_defines = {}
for key in defines:
# Remove all boards now
if key.startswith("BOARD_") and key != "BOARD_INFO_NAME":
continue
# 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":
continue
# Remove all keys ending by "_T_DECLARED" as it's a copy of extraneous system stuff
if key.endswith("_T_DECLARED"):
continue
# 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' ]:
continue
# Don't be that smart guy here
resolved_defines[key] = defines[key]
# Generate a build signature now
# We are making an object that's a bit more complex than a basic dictionary here
data = {}
data['__INITIAL_HASH'] = hashes
# First create a key for each header here
for header in conf_defines:
data[header] = {}
# Then populate the object where each key is going to (that's a O(N^2) algorithm here...)
for key in resolved_defines:
for header in conf_defines:
if key in conf_defines[header]:
data[header][key] = resolved_defines[key]
# Every python needs this toy
def tryint(key):
try:
return int(defines[key])
except:
return 0
config_dump = tryint('CONFIG_EXPORT')
#
# Produce an INI file if CONFIG_EXPORT == 2
#
if config_dump == 2:
print("Generating config.ini ...")
config_ini = build_path / 'config.ini'
with config_ini.open('w') as outfile:
ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_EXPORT')
filegrp = { 'Configuration.h':'config:basic', 'Configuration_adv.h':'config:advanced' }
vers = defines["CONFIGURATION_H_VERSION"]
dt_string = datetime.now().strftime("%Y-%m-%d at %H:%M:%S")
ini_fmt = '{0:40}{1}\n'
outfile.write(
'#\n'
+ '# Marlin Firmware\n'
+ '# config.ini - Options to apply before the build\n'
+ '#\n'
+ f'# Generated by Marlin build on {dt_string}\n'
+ '#\n'
+ '\n'
+ '[config:base]\n'
+ ini_fmt.format('ini_use_config', ' = all')
+ ini_fmt.format('ini_config_vers', f' = {vers}')
)
# Loop through the data array of arrays
for header in data:
if header.startswith('__'):
continue
outfile.write('\n[' + filegrp[header] + ']\n')
for key in sorted(data[header]):
if key not in ignore:
val = 'on' if data[header][key] == '' else data[header][key]
outfile.write(ini_fmt.format(key.lower(), ' = ' + val))
#
# Produce a schema.json file if CONFIG_EXPORT == 3
#
if config_dump >= 3:
try:
conf_schema = schema.extract()
except Exception as exc:
print("Error: " + str(exc))
conf_schema = None
if conf_schema:
#
# Produce a schema.json file if CONFIG_EXPORT == 3
#
if config_dump in (3, 13):
print("Generating schema.json ...")
schema.dump_json(conf_schema, build_path / 'schema.json')
if config_dump == 13:
schema.group_options(conf_schema)
schema.dump_json(conf_schema, build_path / 'schema_grouped.json')
#
# Produce a schema.yml file if CONFIG_EXPORT == 4
#
elif config_dump == 4:
print("Generating schema.yml ...")
try:
import yaml
except ImportError:
env.Execute(env.VerboseAction(
'$PYTHONEXE -m pip install "pyyaml"',
"Installing YAML for schema.yml export",
))
import yaml
schema.dump_yaml(conf_schema, build_path / 'schema.yml')
# Append the source code version and date
data['VERSION'] = {}
data['VERSION']['DETAILED_BUILD_VERSION'] = resolved_defines['DETAILED_BUILD_VERSION']
data['VERSION']['STRING_DISTRIBUTION_DATE'] = resolved_defines['STRING_DISTRIBUTION_DATE']
try:
curver = subprocess.check_output(["git", "describe", "--match=NeVeRmAtCh", "--always"]).strip()
data['VERSION']['GIT_REF'] = curver.decode()
except:
pass
#
# Produce a JSON file for CONFIGURATION_EMBEDDING or CONFIG_EXPORT == 1
#
if config_dump == 1 or 'CONFIGURATION_EMBEDDING' in defines:
with marlin_json.open('w') as outfile:
json.dump(data, outfile, separators=(',', ':'))
#
# The rest only applies to CONFIGURATION_EMBEDDING
#
if not 'CONFIGURATION_EMBEDDING' in defines:
return
# Compress the JSON file as much as we can
compress_file(marlin_json, marlin_zip)
# Generate a C source file for storing this array
with open('Marlin/src/mczip.h','wb') as result_file:
result_file.write(
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'#endif\n'
+ b'const unsigned char mc_zip[] PROGMEM = {\n '
)
count = 0
for b in (build_path / 'mc.zip').open('rb').read():
result_file.write(b' 0x%02X,' % b)
count += 1
if count % 16 == 0:
result_file.write(b'\n ')
if count % 16:
result_file.write(b'\n')
result_file.write(b'};\n')

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

@ -2,51 +2,52 @@
# simulator.py
# PlatformIO pre: script for simulator builds
#
import pioutil
if pioutil.is_pio_build():
# Get the environment thus far for the build
Import("env")
# Get the environment thus far for the build
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,
# or if Mesa is installed try to use its GL/gl.h.
#
#
# If Xcode is installed add the path to its Frameworks folder,
# or if Mesa is installed try to use its GL/gl.h.
#
import sys
if sys.platform == 'darwin':
import sys
if sys.platform == 'darwin':
#
# Silence half of the ranlib warnings. (No equivalent for 'ARFLAGS')
#
env['RANLIBFLAGS'] += [ "-no_warning_for_no_symbols" ]
#
# Silence half of the ranlib warnings. (No equivalent for 'ARFLAGS')
#
env['RANLIBFLAGS'] += [ "-no_warning_for_no_symbols" ]
# 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"
mesa_path = "/opt/local/include/GL/gl.h"
# 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"
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 ]
print("Using OpenGL framework headers from Xcode.app")
env['BUILD_FLAGS'] += [ "-F" + xcode_path ]
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__' ]
print("Using OpenGL header from", mesa_path)
env['BUILD_FLAGS'] += [ '-D__MESA__' ]
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
sys.exit(1)
# Break out of the PIO build immediately
sys.exit(1)

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

@ -3,59 +3,59 @@
#
import pioutil
if pioutil.is_pio_build():
Import("env")
# Get a build flag's value or None
def getBuildFlagValue(name):
for flag in build_flags:
if isinstance(flag, list) and flag[0] == name:
return flag[1]
return None
# Get an overriding buffer size for RX or TX from the build flags
def getInternalSize(side):
return getBuildFlagValue(f"MF_{side}_BUFFER_SIZE") or \
getBuildFlagValue(f"SERIAL_{side}_BUFFER_SIZE") or \
getBuildFlagValue(f"USART_{side}_BUF_SIZE")
# Get the largest defined buffer size for RX or TX
def getBufferSize(side, default):
# Get a build flag value or fall back to the given default
internal = int(getInternalSize(side) or default)
flag = side + "_BUFFER_SIZE"
# Return the largest value
return max(int(mf[flag]), internal) if flag in mf else internal
# Add a build flag if it's not already defined
def tryAddFlag(name, value):
if getBuildFlagValue(name) is None:
env.Append(BUILD_FLAGS=[f"-D{name}={value}"])
# Marlin uses the `RX_BUFFER_SIZE` \ `TX_BUFFER_SIZE` options to
# configure buffer sizes for receiving \ transmitting serial data.
# Stm32duino uses another set of defines for the same purpose, so this
# script gets the values from the configuration and uses them to define
# `SERIAL_RX_BUFFER_SIZE` and `SERIAL_TX_BUFFER_SIZE` as global build
# flags so they are available for use by the platform.
#
# The script will set the value as the default one (64 bytes)
# or the user-configured one, whichever is higher.
#
# Marlin's default buffer sizes are 128 for RX and 32 for TX.
# The highest value is taken (128/64).
#
# If MF_*_BUFFER_SIZE, SERIAL_*_BUFFER_SIZE, USART_*_BUF_SIZE, are
# defined, the first of these values will be used as the minimum.
build_flags = env.ParseFlags(env.get('BUILD_FLAGS'))["CPPDEFINES"]
mf = env["MARLIN_FEATURES"]
# Get the largest defined buffer sizes for RX or TX, using defaults for undefined
rxBuf = getBufferSize("RX", 128)
txBuf = getBufferSize("TX", 64)
# Provide serial buffer sizes to the stm32duino platform
tryAddFlag("SERIAL_RX_BUFFER_SIZE", rxBuf)
tryAddFlag("SERIAL_TX_BUFFER_SIZE", txBuf)
tryAddFlag("USART_RX_BUF_SIZE", rxBuf)
tryAddFlag("USART_TX_BUF_SIZE", txBuf)
Import("env")
# Get a build flag's value or None
def getBuildFlagValue(name):
for flag in build_flags:
if isinstance(flag, list) and flag[0] == name:
return flag[1]
return None
# Get an overriding buffer size for RX or TX from the build flags
def getInternalSize(side):
return getBuildFlagValue(f"MF_{side}_BUFFER_SIZE") or \
getBuildFlagValue(f"SERIAL_{side}_BUFFER_SIZE") or \
getBuildFlagValue(f"USART_{side}_BUF_SIZE")
# Get the largest defined buffer size for RX or TX
def getBufferSize(side, default):
# Get a build flag value or fall back to the given default
internal = int(getInternalSize(side) or default)
flag = side + "_BUFFER_SIZE"
# Return the largest value
return max(int(mf[flag]), internal) if flag in mf else internal
# Add a build flag if it's not already defined
def tryAddFlag(name, value):
if getBuildFlagValue(name) is None:
env.Append(BUILD_FLAGS=[f"-D{name}={value}"])
# Marlin uses the `RX_BUFFER_SIZE` \ `TX_BUFFER_SIZE` options to
# configure buffer sizes for receiving \ transmitting serial data.
# Stm32duino uses another set of defines for the same purpose, so this
# script gets the values from the configuration and uses them to define
# `SERIAL_RX_BUFFER_SIZE` and `SERIAL_TX_BUFFER_SIZE` as global build
# flags so they are available for use by the platform.
#
# The script will set the value as the default one (64 bytes)
# or the user-configured one, whichever is higher.
#
# Marlin's default buffer sizes are 128 for RX and 32 for TX.
# The highest value is taken (128/64).
#
# If MF_*_BUFFER_SIZE, SERIAL_*_BUFFER_SIZE, USART_*_BUF_SIZE, are
# defined, the first of these values will be used as the minimum.
build_flags = env.ParseFlags(env.get('BUILD_FLAGS'))["CPPDEFINES"]
mf = env["MARLIN_FEATURES"]
# Get the largest defined buffer sizes for RX or TX, using defaults for undefined
rxBuf = getBufferSize("RX", 128)
txBuf = getBufferSize("TX", 64)
# Provide serial buffer sizes to the stm32duino platform
tryAddFlag("SERIAL_RX_BUFFER_SIZE", rxBuf)
tryAddFlag("SERIAL_TX_BUFFER_SIZE", txBuf)
tryAddFlag("USART_RX_BUF_SIZE", rxBuf)
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
for (unsigned i = 0; i < PINS_COUNT; i++)
digitalWrite(i, LOW);
digitalWrite(i, LOW);
// Enable parallel access on PIO output data registers
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
* (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 */
#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 */
#endif /* HSE_STARTUP_TIMEOUT */
@ -112,7 +112,7 @@ extern "C" {
* @brief Internal oscillator (CSI) default value.
* 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*/
#endif /* CSI_VALUE */
@ -121,7 +121,7 @@ extern "C" {
* 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).
*/
#if !defined (HSI_VALUE)
#ifndef HSI_VALUE
#define HSI_VALUE ((uint32_t)64000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
@ -129,16 +129,16 @@ extern "C" {
* @brief External Low Speed oscillator (LSE) value.
* 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*/
#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 */
#endif /* LSE_STARTUP_TIMEOUT */
#if !defined (LSI_VALUE)
#ifndef LSI_VALUE
#define LSI_VALUE ((uint32_t)32000) /*!< LSI Typical Value in Hz*/
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
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
* 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*/
#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->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
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 |= 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 |= (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 |= 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 |= 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
@ -209,7 +209,7 @@ void SystemClockStartupInit() {
// 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->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) << 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
@ -271,8 +271,8 @@ uint8_t MPU_Set_Protection(uint32_t baseaddr, uint32_t size, uint32_t rnum, uint
uint8_t rnr = 0;
if ((size % 32) || size == 0) return 1;
rnr = MPU_Convert_Bytes_To_POT(size) - 1;
SCB->SHCSR &= ~(1 << 16); //disable MemManage
MPU->CTRL &= ~(1 << 0); //disable MPU
SCB->SHCSR &= ~(1 << 16); //disable MemManage
MPU->CTRL &= ~(1 << 0); //disable MPU
MPU->RNR = rnum;
MPU->RBAR = baseaddr;
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;
MPU->RASR = tempreg;
MPU->CTRL = (1 << 2) | (1 << 0); //enable PRIVDEFENA
SCB->SHCSR |= 1 << 16; //enable MemManage
SCB->SHCSR |= 1 << 16; //enable MemManage
return 0;
}
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(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(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(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(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(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(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
{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
#if defined(STM32F103xG)
#ifdef STM32F103xG
// {PA_2, TIM5, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 3, 0)}, // TIM5_CH3
#endif
#if defined(STM32F103xE) || defined(STM32F103xG)
@ -148,11 +148,11 @@ WEAK const PinMap PinMap_PWM[] = {
#else
{PA_3, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 4, 0)}, // TIM2_CH4
#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
#endif
{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
#endif
// {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
{PA_7, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM1_PARTIAL, 1, 1)}, // TIM1_CH1N
#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
#endif
{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_9, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 4, 0)}, // TIM4_CH4
#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
#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
#endif
{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_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
#if defined(STM32F103xG)
#ifdef STM32F103xG
// {PB_14, TIM12, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM12_CH1
#endif
{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
#endif
{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)
{PC_10, UART4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE)},
#endif
#if defined(STM32F103xB)
#ifdef STM32F103xB
{PC_10, USART3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_USART3_PARTIAL)},
#endif
#if defined(STM32F103xE) || defined(STM32F103xG)
@ -270,7 +270,7 @@ WEAK const PinMap PinMap_UART_RX[] = {
#if defined(STM32F103xE) || defined(STM32F103xG)
{PC_11, UART4, STM_PIN_DATA(STM_MODE_INPUT, GPIO_PULLUP, AFIO_NONE)},
#endif
#if defined(STM32F103xB)
#ifdef STM32F103xB
{PC_11, USART3, STM_PIN_DATA(STM_MODE_INPUT, GPIO_PULLUP, AFIO_USART3_PARTIAL)},
#endif
#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
* Deactivated: CRC code cleaned from driver
*/
#if !defined(USE_SPI_CRC)
#ifndef USE_SPI_CRC
#define USE_SPI_CRC 0
#endif

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

@ -139,7 +139,7 @@ extern "C" {
#define PIN_SERIAL2_TX PA2
// Extra HAL modules
#if defined(STM32F103xE)
#ifdef STM32F103xE
//#define HAL_DAC_MODULE_ENABLED (unused or maybe for the eeprom write?)
#define HAL_SD_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
{PA_3, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 4, 0)}, // TIM2_CH4
#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
#endif
{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
#endif
{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, 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
#endif
{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_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
#if defined(STM32F103xG)
#ifdef STM32F103xG
//{PB_8, TIM10, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM10_CH1
#endif
{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
#endif
{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_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
#if defined(STM32F103xG)
#ifdef STM32F103xG
//{PB_14, TIM12, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_NONE, 1, 0)}, // TIM12_CH1
#endif
{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
#endif
{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_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
#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_6, TIM9, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, AFIO_TIM9_ENABLE, 2, 0)}, // TIM9_CH2
#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
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
#if defined(USE_STM3210C_EVAL)
#ifndef HSE_VALUE
#ifdef USE_STM3210C_EVAL
#define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */
#else
#define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */
#endif
#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 */
#endif /* HSE_STARTUP_TIMEOUT */
@ -98,14 +98,14 @@ extern "C" {
* 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).
*/
#if !defined (HSI_VALUE)
#ifndef HSI_VALUE
#define HSI_VALUE 8000000U /*!< Value of the Internal oscillator in Hz */
#endif /* HSI_VALUE */
/**
* @brief Internal Low Speed oscillator (LSI) value.
*/
#if !defined (LSI_VALUE)
#ifndef LSI_VALUE
#define LSI_VALUE 40000U /*!< LSI Typical Value in Hz */
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations
@ -114,11 +114,11 @@ extern "C" {
* @brief External Low Speed oscillator (LSE) value.
* 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 */
#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 */
#endif /* LSE_STARTUP_TIMEOUT */
@ -129,7 +129,7 @@ extern "C" {
/**
* @brief This is the HAL system configuration section
*/
#if !defined(VDD_VALUE)
#ifndef VDD_VALUE
#define VDD_VALUE 3300U /*!< Value of VDD in mv */
#endif
#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
* (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 */
#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 */
#endif /* HSE_STARTUP_TIMEOUT */
@ -104,14 +104,14 @@
* 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).
*/
#if !defined (HSI_VALUE)
#ifndef HSI_VALUE
#define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz */
#endif /* HSI_VALUE */
/**
* @brief Internal Low Speed oscillator (LSI) value.
*/
#if !defined (LSI_VALUE)
#ifndef LSI_VALUE
#define LSI_VALUE 32000U /*!< LSI Typical Value in Hz */
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations
@ -119,11 +119,11 @@
/**
* @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 */
#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 */
#endif /* LSE_STARTUP_TIMEOUT */
@ -132,7 +132,7 @@
* 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.
*/
#if !defined (EXTERNAL_CLOCK_VALUE)
#ifndef EXTERNAL_CLOCK_VALUE
#define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External oscillator in Hz*/
#endif /* EXTERNAL_CLOCK_VALUE */

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

Loading…
Cancel
Save