Merge branch 'bugfix-2.1.x' of https://github.com/MarlinFirmware/Marlin into bugfix-2.1.x

This commit is contained in:
InsanityAutomation
2023-11-08 09:39:42 -05:00
250 changed files with 6634 additions and 3009 deletions
+8 -2
View File
@@ -1,12 +1,14 @@
# editorconfig.org
root = true
[*]
trim_trailing_whitespace = true
insert_final_newline = true
[{*.patch,syntax_test_*}]
trim_trailing_whitespace = false
[{*.c,*.cpp,*.h,*.ino,*.py,Makefile}]
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
[{*.c,*.cpp,*.h,*.ino}]
@@ -18,6 +20,10 @@ indent_size = 2
indent_style = tab
indent_size = 2
[*.md]
# Two spaces at the end of the line means newline in Markdown
trim_trailing_whitespace = false
[{*.py}]
indent_style = space
indent_size = 4
+7 -2
View File
@@ -109,8 +109,13 @@ body:
- type: input
attributes:
label: Add-ons
description: Please list any hardware add-ons that could be involved.
label: LCD/Controller
description: Some Marlin behaviors are determined by the controller. Describe your LCD/Controller model and version.
- type: input
attributes:
label: Other add-ons
description: Please list any other hardware add-ons that could be involved.
- type: dropdown
attributes:
+1 -7
View File
@@ -28,15 +28,9 @@ Project maintainers are responsible for clarifying the standards of acceptable b
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [marlinfirmware@github.com](mailto:marlinfirmware@github.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by messaging @MarlinFirmware/moderators on the relevant issue, [or privately](//github.com/orgs/MarlinFirmware/teams/moderators). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
## Attribution
+1 -1
View File
@@ -26,7 +26,7 @@ The following is a set of guidelines for contributing to Marlin, hosted by the [
## Code of Conduct
This project and everyone participating in it is governed by the [Marlin Code of Conduct](code_of_conduct.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [marlinfirmware@github.com](mailto:marlinfirmware@github.com).
This project and everyone participating in it is governed by the [Marlin Code of Conduct](code_of_conduct.md). By participating, you are expected to uphold this code. Please report unacceptable behavior by messaging @MarlinFirmware/moderators on the relevant issue, [or privately](//github.com/orgs/MarlinFirmware/teams/moderators).
## I don't want to read this whole thing I just have a question!!!
+15 -3
View File
@@ -20,9 +20,21 @@ jobs:
- uses: actions/stale@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue has had no activity in the last 60 days. Please add a reply if you want to keep this issue active, otherwise it will be automatically closed within 10 days.'
days-before-stale: 60
days-before-close: 10
stale-issue-message: |
Greetings from the Marlin AutoBot!
This issue has had no activity for the last 90 days.
Do you still see this issue with the latest `bugfix-2.1.x` code?
Please add a reply within 14 days or this issue will be automatically closed.
To keep a confirmed issue open we can also add a "Bug: Confirmed" tag.
Disclaimer: This is an open community project with lots of activity and limited
resources. The main project contributors will do a bug sweep ahead of the next
release, but any skilled member of the community may jump in at any time to fix
this issue. That can take a while depending on our busy lives so please be patient,
and take advantage of other resources such as the MarlinFirmware Discord to help
solve the issue.
days-before-stale: 90
days-before-close: 14
stale-issue-label: 'stale-closing-soon'
exempt-all-assignees: true
exempt-issue-labels: 'Bug: Confirmed !,T: Feature Request,Needs: More Data,Needs: Discussion,Needs: Documentation,Needs: Patch,Needs: Work,Needs: Testing,help wanted,no-locking'
+3
View File
@@ -133,6 +133,9 @@ jobs:
#- STM32F103RC_btt_maple
#- STM32F103RE_creality_maple
# STM32G0
- STM32G0B1RE_btt
# LPC176x - Lengthy tests
- LPC1768
- LPC1769
+1
View File
@@ -6,6 +6,7 @@
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode-remote.remote-containers",
"ms-vscode.cpptools-extension-pack"
]
}
+43 -34
View File
@@ -244,7 +244,8 @@
#if ENABLED(SWITCHING_NOZZLE)
#define SWITCHING_NOZZLE_SERVO_NR 0
//#define SWITCHING_NOZZLE_E1_SERVO_NR 1 // If two servos are used, the index of the second
#define SWITCHING_NOZZLE_SERVO_ANGLES { 0, 90 } // Angles for E0, E1 (single servo) or lowered/raised (dual servo)
#define SWITCHING_NOZZLE_SERVO_ANGLES { 0, 90 } // A pair of angles for { E0, E1 }.
// For Dual Servo use two pairs: { { lower, raise }, { lower, raise } }
#define SWITCHING_NOZZLE_SERVO_DWELL 2500 // Dwell time to wait for servo to make physical move
#endif
@@ -412,11 +413,12 @@
//#define AUTO_POWER_CONTROL // Enable automatic control of the PS_ON pin
#if ENABLED(AUTO_POWER_CONTROL)
#define AUTO_POWER_FANS // Turn on PSU if fans need power
#define AUTO_POWER_E_FANS
#define AUTO_POWER_CONTROLLERFAN
#define AUTO_POWER_CHAMBER_FAN
#define AUTO_POWER_COOLER_FAN
#define AUTO_POWER_FANS // Turn on PSU for fans
#define AUTO_POWER_E_FANS // Turn on PSU for E Fans
#define AUTO_POWER_CONTROLLERFAN // Turn on PSU for Controller Fan
#define AUTO_POWER_CHAMBER_FAN // Turn on PSU for Chamber Fan
#define AUTO_POWER_COOLER_FAN // Turn on PSU for Cooler Fan
#define AUTO_POWER_SPINDLE_LASER // Turn on PSU for Spindle/Laser
#define POWER_TIMEOUT 30 // (s) Turn off power if the machine is idle for this duration
//#define POWER_OFF_DELAY 60 // (s) Delay of poweroff after M81 command. Useful to let fans run for extra time.
#endif
@@ -465,6 +467,7 @@
* 13 : 100kΩ Hisens up to 300°C - for "Simple ONE" & "All In ONE" hotend - beta 3950, 1%
* 14 : 100kΩ (R25), 4092K (beta25), 4.7kΩ pull-up, bed thermistor as used in Ender-5 S1
* 15 : 100kΩ Calibrated for JGAurora A5 hotend
* 17 : 100kΩ Dagoma NTC white thermistor
* 18 : 200kΩ ATC Semitec 204GT-2 Dagoma.Fr - MKS_Base_DKU001327
* 22 : 100kΩ GTM32 Pro vB - hotend - 4.7kΩ pullup to 3.3V and 220Ω to analog input
* 23 : 100kΩ GTM32 Pro vB - bed - 4.7kΩ pullup to 3.3v and 220Ω to analog input
@@ -476,6 +479,7 @@
* 68 : PT100 Smplifier board from Dyze Design
* 70 : 100kΩ bq Hephestos 2
* 75 : 100kΩ Generic Silicon Heat Pad with NTC100K MGB18-104F39050L32
* 666 : 200kΩ Einstart S custom thermistor with 10k pullup.
* 2000 : 100kΩ Ultimachine Rambo TDK NTCG104LH104KT1 NTC100K motherboard Thermistor
*
* ================================================================
@@ -662,7 +666,7 @@
//#define MPCTEMP // ** EXPERIMENTAL ** See https://marlinfw.org/docs/features/model_predictive_control.html
#define PID_MAX 255 // Limit hotend current while PID is active (see PID_FUNCTIONAL_RANGE below); 255=full current
#define PID_K1 0.95 // Smoothing factor within any PID loop
#define PID_K1 0.95 // Smoothing factor within any PID loop
#if ENABLED(PIDTEMP)
//#define PID_DEBUG // Print PID debug data to the serial port. Use 'M303 D' to toggle activation.
@@ -1415,6 +1419,15 @@
//#define TOUCH_MI_MANUAL_DEPLOY // For manual deploy (LCD menu)
#endif
/**
* Bed Distance Sensor
*
* Measures the distance from bed to nozzle with accuracy of 0.01mm.
* For information about this sensor https://github.com/markniu/Bed_Distance_sensor
* Uses I2C port, so it requires I2C library markyue/Panda_SoftMasterI2C.
*/
//#define BD_SENSOR
// A probe that is deployed and stowed with a solenoid pin (SOL1_PIN)
//#define SOLENOID_PROBE
@@ -1513,7 +1526,7 @@
*
* Tune and Adjust
* - Probe Offsets can be tuned at runtime with 'M851', LCD menus, babystepping, etc.
* - PROBE_OFFSET_WIZARD (configuration_adv.h) can be used for setting the Z offset.
* - PROBE_OFFSET_WIZARD (Configuration_adv.h) can be used for setting the Z offset.
*
* Assuming the typical work area orientation:
* - Probe to RIGHT of the Nozzle has a Positive X offset
@@ -1620,16 +1633,21 @@
* Example: `M851 Z-5` with a CLEARANCE of 4 => 9mm from bed to nozzle.
* But: `M851 Z+1` with a CLEARANCE of 2 => 2mm from bed to nozzle.
*/
#define Z_CLEARANCE_DEPLOY_PROBE 10 // Z Clearance for Deploy/Stow
#define Z_CLEARANCE_BETWEEN_PROBES 5 // Z Clearance between probe points
#define Z_CLEARANCE_MULTI_PROBE 5 // Z Clearance between multiple probes
//#define Z_AFTER_PROBING 5 // Z position after probing is done
#define Z_CLEARANCE_DEPLOY_PROBE 10 // (mm) Z Clearance for Deploy/Stow
#define Z_CLEARANCE_BETWEEN_PROBES 5 // (mm) Z Clearance between probe points
#define Z_CLEARANCE_MULTI_PROBE 5 // (mm) Z Clearance between multiple probes
#define Z_PROBE_ERROR_TOLERANCE 3 // (mm) Tolerance for early trigger (<= -probe.offset.z + ZPET)
//#define Z_AFTER_PROBING 5 // (mm) Z position after probing is done
#define Z_PROBE_LOW_POINT -2 // Farthest distance below the trigger-point to go before stopping
#define Z_PROBE_LOW_POINT -2 // (mm) Farthest distance below the trigger-point to go before stopping
// For M851 give a range for adjusting the Z probe offset
#define Z_PROBE_OFFSET_RANGE_MIN -20
#define Z_PROBE_OFFSET_RANGE_MAX 20
// For M851 provide ranges for adjusting the X, Y, and Z probe offsets
//#define PROBE_OFFSET_XMIN -50 // (mm)
//#define PROBE_OFFSET_XMAX 50 // (mm)
//#define PROBE_OFFSET_YMIN -50 // (mm)
//#define PROBE_OFFSET_YMAX 50 // (mm)
//#define PROBE_OFFSET_ZMIN -20 // (mm)
//#define PROBE_OFFSET_ZMAX 20 // (mm)
// Enable the M48 repeatability test to test probe accuracy
//#define Z_MIN_PROBE_REPEATABILITY_TEST
@@ -1993,6 +2011,12 @@
//#define AUTO_BED_LEVELING_UBL
//#define MESH_BED_LEVELING
/**
* Commands to execute at the end of G29 probing.
* Useful to retract or move the Z probe out of the way.
*/
//#define Z_PROBE_END_SCRIPT "G1 Z10 F12000\nG1 X15 Y330\nG1 Z0.5\nG1 Z10"
/**
* Normally G28 leaves leveling disabled on completion. Enable one of
* these options to restore the prior leveling state or to always enable
@@ -2010,15 +2034,6 @@
#define LEVELING_BED_TEMP 50
#endif
/**
* Bed Distance Sensor
*
* Measures the distance from bed to nozzle with accuracy of 0.01mm.
* For information about this sensor https://github.com/markniu/Bed_Distance_sensor
* Uses I2C port, so it requires I2C library markyue/Panda_SoftMasterI2C.
*/
//#define BD_SENSOR
/**
* Enable detailed logging of G28, G29, M48, etc.
* Turn on with the command 'M111 S32'.
@@ -2198,12 +2213,6 @@
#define BED_TRAMMING_LEVELING_ORDER { LF, RF, RB, LB }
#endif
/**
* Commands to execute at the end of G29 probing.
* Useful to retract or move the Z probe out of the way.
*/
//#define Z_PROBE_END_SCRIPT "G1 Z10 F12000\nG1 X15 Y330\nG1 Z0.5\nG1 Z10"
// @section homing
// The center of the bed is at (X=0, Y=0)
@@ -2984,10 +2993,10 @@
//#define FYSETC_GENERIC_12864_1_1 // Larger display with basic ON/OFF backlight.
//
// BigTreeTech Mini 12864 V1.0 is an alias for FYSETC_MINI_12864_2_1. Type A/B. NeoPixel RGB Backlight.
// https://github.com/bigtreetech/MINI-12864/tree/master/mini12864_v1.0
// BigTreeTech Mini 12864 V1.0 / V2.0 is an alias for FYSETC_MINI_12864_2_1. Type A/B. NeoPixel RGB Backlight.
// https://github.com/bigtreetech/MINI-12864
//
//#define BTT_MINI_12864_V1
//#define BTT_MINI_12864
//
// Factory display for Creality CR-10 / CR-7 / Ender-3
+79 -35
View File
@@ -304,8 +304,8 @@
* THERMAL_PROTECTION_HYSTERESIS and/or THERMAL_PROTECTION_PERIOD
*/
#if ENABLED(THERMAL_PROTECTION_HOTENDS)
#define THERMAL_PROTECTION_PERIOD 40 // Seconds
#define THERMAL_PROTECTION_HYSTERESIS 4 // Degrees Celsius
#define THERMAL_PROTECTION_PERIOD 40 // (seconds)
#define THERMAL_PROTECTION_HYSTERESIS 4 // (°C)
//#define ADAPTIVE_FAN_SLOWING // Slow down the part-cooling fan if the temperature drops
#if ENABLED(ADAPTIVE_FAN_SLOWING)
@@ -327,50 +327,50 @@
* and/or decrease WATCH_TEMP_INCREASE. WATCH_TEMP_INCREASE should not be set
* below 2.
*/
#define WATCH_TEMP_PERIOD 40 // Seconds
#define WATCH_TEMP_INCREASE 2 // Degrees Celsius
#define WATCH_TEMP_PERIOD 40 // (seconds)
#define WATCH_TEMP_INCREASE 2 // (°C)
#endif
/**
* Thermal Protection parameters for the bed are just as above for hotends.
*/
#if ENABLED(THERMAL_PROTECTION_BED)
#define THERMAL_PROTECTION_BED_PERIOD 20 // Seconds
#define THERMAL_PROTECTION_BED_HYSTERESIS 2 // Degrees Celsius
#define THERMAL_PROTECTION_BED_PERIOD 20 // (seconds)
#define THERMAL_PROTECTION_BED_HYSTERESIS 2 // (°C)
/**
* As described above, except for the bed (M140/M190/M303).
*/
#define WATCH_BED_TEMP_PERIOD 60 // Seconds
#define WATCH_BED_TEMP_INCREASE 2 // Degrees Celsius
#define WATCH_BED_TEMP_PERIOD 60 // (seconds)
#define WATCH_BED_TEMP_INCREASE 2 // (°C)
#endif
/**
* Thermal Protection parameters for the heated chamber.
*/
#if ENABLED(THERMAL_PROTECTION_CHAMBER)
#define THERMAL_PROTECTION_CHAMBER_PERIOD 20 // Seconds
#define THERMAL_PROTECTION_CHAMBER_HYSTERESIS 2 // Degrees Celsius
#define THERMAL_PROTECTION_CHAMBER_PERIOD 20 // (seconds)
#define THERMAL_PROTECTION_CHAMBER_HYSTERESIS 2 // (°C)
/**
* Heated chamber watch settings (M141/M191).
*/
#define WATCH_CHAMBER_TEMP_PERIOD 60 // Seconds
#define WATCH_CHAMBER_TEMP_INCREASE 2 // Degrees Celsius
#define WATCH_CHAMBER_TEMP_PERIOD 60 // (seconds)
#define WATCH_CHAMBER_TEMP_INCREASE 2 // (°C)
#endif
/**
* Thermal Protection parameters for the laser cooler.
*/
#if ENABLED(THERMAL_PROTECTION_COOLER)
#define THERMAL_PROTECTION_COOLER_PERIOD 10 // Seconds
#define THERMAL_PROTECTION_COOLER_HYSTERESIS 3 // Degrees Celsius
#define THERMAL_PROTECTION_COOLER_PERIOD 10 // (seconds)
#define THERMAL_PROTECTION_COOLER_HYSTERESIS 3 // (°C)
/**
* Laser cooling watch settings (M143/M193).
*/
#define WATCH_COOLER_TEMP_PERIOD 60 // Seconds
#define WATCH_COOLER_TEMP_INCREASE 3 // Degrees Celsius
#define WATCH_COOLER_TEMP_PERIOD 60 // (seconds)
#define WATCH_COOLER_TEMP_INCREASE 3 // (°C)
#endif
#if ANY(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_BED, THERMAL_PROTECTION_CHAMBER, THERMAL_PROTECTION_COOLER)
@@ -564,6 +564,8 @@
#define TEMP_SENSOR_AD8495_OFFSET 0.0
#define TEMP_SENSOR_AD8495_GAIN 1.0
// @section fans
/**
* Controller Fan
* To cool down the stepper drivers and MOSFETs.
@@ -667,8 +669,6 @@
//#define NUM_REDUNDANT_FANS 1 // Number of sequential fans to synchronize with Fan 0
#endif
// @section extruder
/**
* Extruder cooling fans
*
@@ -745,6 +745,7 @@
#define FANMUX2_PIN -1
/**
* @section caselight
* M355 Case Light on-off / brightness
*/
//#define CASE_LIGHT_ENABLE
@@ -767,7 +768,7 @@
#endif
#endif
// @section homing
// @section endstops
// If you want endstops to stay on (by default) even when not homing
// enable this option. Override at any time with M120, M121.
@@ -784,6 +785,8 @@
//#define CLOSED_LOOP_MOVE_COMPLETE_PIN -1
#endif
// @section idex
/**
* Dual X Carriage
*
@@ -833,6 +836,8 @@
//#define EVENT_GCODE_IDEX_AFTER_MODECHANGE "G28X"
#endif
// @section multi stepper
/**
* Multi-Stepper / Multi-Endstop
*
@@ -904,6 +909,8 @@
//#define INVERT_E1_VS_E0_DIR // E direction signals are opposites
#endif
// @section extruder
// Activate a solenoid on the active extruder with M380. Disable all with M381.
// Define SOL0_PIN, SOL1_PIN, etc., for each extruder that has a solenoid.
//#define EXT_SOLENOID
@@ -1250,11 +1257,6 @@
#define XY_FREQUENCY_MIN_PERCENT 5 // (percent) Minimum FR percentage to apply. Set with M201 G<min%>.
#endif
// Minimum planner junction speed. Sets the default minimum speed the planner plans for at the end
// of the buffer and all stops. This should not be much greater than zero and should only be changed
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/s)
//
// Backlash Compensation
// Adds extra movement to axes on direction-changes to account for backlash.
@@ -1746,9 +1748,10 @@
// SD Card Sorting options
#if ENABLED(SDCARD_SORT_ALPHA)
#define SDSORT_REVERSE false // Default to sorting file names in reverse order.
#define SDSORT_LIMIT 40 // Maximum number of sorted items (10-256). Costs 27 bytes each.
#define FOLDER_SORTING -1 // -1=above 0=none 1=below
#define SDSORT_GCODE false // Allow turning sorting on/off with LCD and M34 G-code.
#define SDSORT_FOLDERS -1 // -1=above 0=none 1=below
#define SDSORT_GCODE false // Enable G-code M34 to set sorting behaviors: M34 S<-1|0|1> F<-1|0|1>
#define SDSORT_USES_RAM false // Pre-allocate a static array for faster pre-sorting.
#define SDSORT_USES_STACK false // Prefer the stack for pre-sorting to give back some SRAM. (Negated by next 2 options.)
#define SDSORT_CACHE_NAMES false // Keep sorted items in RAM longer for speedy performance. Most expensive option.
@@ -1967,7 +1970,10 @@
//#define STATUS_ALT_BED_BITMAP // Use the alternative bed bitmap
//#define STATUS_ALT_FAN_BITMAP // Use the alternative fan bitmap
//#define STATUS_FAN_FRAMES 3 // :[0,1,2,3,4] Number of fan animation frames
// Only one STATUS_HEAT_* option can be enabled
//#define STATUS_HEAT_PERCENT // Show heating in a progress bar
//#define STATUS_HEAT_POWER // Show heater output power as a vertical bar
// Frivolous Game Options
//#define MARLIN_BRICKOUT
@@ -2264,6 +2270,14 @@
//#define EXPERIMENTAL_I2S_LA // Allow I2S_STEPPER_STREAM to be used with LA. Performance degrades as the LA step rate reaches ~20kHz.
#endif
/**
* Nonlinear Extrusion Control
*
* Control extrusion rate based on instantaneous extruder velocity. Can be used to correct for
* underextrusion at high extruder speeds that are otherwise well-behaved (i.e., not skipping).
*/
//#define NONLINEAR_EXTRUSION
// @section leveling
/**
@@ -2347,6 +2361,8 @@
#endif
// @section probes
/**
* Thermal Probe Compensation
*
@@ -2409,7 +2425,7 @@
// Height above Z=0.0 to raise the nozzle. Lowering this can help the probe to heat faster.
// Note: The Z=0.0 offset is determined by the probe Z offset (e.g., as set with M851 Z).
#define PTC_PROBE_HEATING_OFFSET 0.5
#define PTC_PROBE_HEATING_OFFSET 0.5 // (mm)
#endif
#endif // PTC_PROBE || PTC_BED || PTC_HOTEND
@@ -2464,6 +2480,8 @@
#define G38_MINIMUM_MOVE 0.0275 // (mm) Minimum distance that will produce a move.
#endif
// @section motion
// Moves (or segments) with fewer steps than this will be joined with the next move
#define MIN_STEPS_PER_SEGMENT 6
@@ -2519,10 +2537,9 @@
//================================= Buffers =================================
//===========================================================================
// @section motion
// @section gcode
// The number of linear moves that can be in the planner at once.
// The value of BLOCK_BUFFER_SIZE must be a power of 2 (e.g., 8, 16, 32)
#if ALL(HAS_MEDIA, DIRECT_STEPPING)
#define BLOCK_BUFFER_SIZE 8
#elif HAS_MEDIA
@@ -2608,7 +2625,7 @@
// Therefore some clients abort after 30 seconds in a timeout.
// Some other clients start sending commands while receiving a 'wait'.
// This "wait" is only sent when the buffer is empty. 1 second is a good value here.
//#define NO_TIMEOUTS 1000 // Milliseconds
//#define NO_TIMEOUTS 1000 // (ms)
// Some clients will have this feature soon. This could make the NO_TIMEOUTS unnecessary.
//#define ADVANCED_OK
@@ -2640,6 +2657,8 @@
*/
//#define EXTRA_FAN_SPEED
// @section gcode
/**
* Firmware-based and LCD-controlled retract
*
@@ -2674,6 +2693,8 @@
#endif
#endif
// @section tool change
/**
* Universal tool change settings.
* Applies to all types of extruders except where explicitly noted.
@@ -2754,7 +2775,21 @@
* - Switch to a different nozzle on an extruder jam
*/
#define TOOLCHANGE_MIGRATION_FEATURE
#if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
// Override toolchange settings
// By default tool migration uses regular toolchange settings.
// With a prime tower, tool-change swapping/priming occur inside the bed.
// When migrating to a new unprimed tool you can set override values below.
//#define MIGRATION_ZRAISE 0 // (mm)
// Longer prime to clean out
//#define MIGRATION_FS_EXTRA_PRIME 0 // (mm) Extra priming length
//#define MIGRATION_FS_WIPE_RETRACT 0 // (mm) Retract before cooling for less stringing, better wipe, etc.
// Cool after prime to reduce stringing
//#define MIGRATION_FS_FAN_SPEED 255 // 0-255
//#define MIGRATION_FS_FAN_TIME 0 // (seconds)
#endif
#endif
/**
@@ -2767,6 +2802,9 @@
#define TOOLCHANGE_PARK_XY_FEEDRATE 6000 // (mm/min)
//#define TOOLCHANGE_PARK_X_ONLY // X axis only move
//#define TOOLCHANGE_PARK_Y_ONLY // Y axis only move
#if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
//#define TOOLCHANGE_MIGRATION_DO_PARK // Force park (or no-park) on migration
#endif
#endif
#endif // HAS_MULTI_EXTRUDER
@@ -3802,7 +3840,8 @@
* Use 'M200 [T<extruder>] L<limit>' to override and 'M502' to reset.
* A non-zero value activates Volume-based Extrusion Limiting.
*/
#define DEFAULT_VOLUMETRIC_EXTRUDER_LIMIT 0.00 // (mm^3/sec)
#define DEFAULT_VOLUMETRIC_EXTRUDER_LIMIT 0.00 // (mm^3/sec)
#define VOLUMETRIC_EXTRUDER_LIMIT_MAX 20 // (mm^3/sec)
#endif
#endif
@@ -4194,6 +4233,7 @@
// row. By default idle() is profiled so this shows how "idle" the processor is.
// See class CodeProfiler.
//#define MAX7219_DEBUG_MULTISTEPPING 6 // Show multi-stepping 1 to 128 on this LED matrix row.
//#define MAX7219_DEBUG_SLOWDOWN 6 // Count (mod 16) how many times SLOWDOWN has reduced print speed.
#endif
/**
@@ -4218,13 +4258,17 @@
#endif
/**
* WiFi Support (Espressif ESP32 WiFi)
* Native ESP32 board with WiFi or add-on ESP32 WiFi-101 module
*/
//#define WIFISUPPORT // Marlin embedded WiFi management
//#define WIFISUPPORT // Marlin embedded WiFi management. Not needed for simple WiFi serial port.
//#define ESP3D_WIFISUPPORT // ESP3D Library WiFi management (https://github.com/luc-github/ESP3DLib)
#if ANY(WIFISUPPORT, ESP3D_WIFISUPPORT)
//#define WEBSUPPORT // Start a webserver (which may include auto-discovery)
/**
* Extras for an ESP32-based motherboard with WIFISUPPORT
* These options don't apply to add-on WiFi modules based on ESP32 WiFi101.
*/
#if ENABLED(WIFISUPPORT)
//#define WEBSUPPORT // Start a webserver (which may include auto-discovery) using SPIFFS
//#define OTASUPPORT // Support over-the-air firmware updates
//#define WIFI_CUSTOM_COMMAND // Accept feature config commands (e.g., WiFi ESP3D) from the host
+1 -1
View File
@@ -2,7 +2,7 @@
Marlin Firmware
(c) 2011-2020 MarlinFirmware
(c) 2011-2023 MarlinFirmware
Portions of Marlin are (c) by their respective authors.
All code complies with GPLv2 and/or GPLv3
+1 -1
View File
@@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release
* version was tagged.
*/
//#define STRING_DISTRIBUTION_DATE "2023-08-04"
//#define STRING_DISTRIBUTION_DATE "2023-11-07"
/**
* Defines a generic printer name to be output to the LCD after booting Marlin.
@@ -70,7 +70,7 @@
#include "../../shared/HAL_SPI.h"
#ifndef LCD_SPI_SPEED
#define LCD_SPI_SPEED SPI_QUARTER_SPEED
#define LCD_SPI_SPEED SPI_HALF_SPEED
#endif
void u8g_SetPIOutput(u8g_t *u8g, uint8_t pin_index) {
@@ -85,7 +85,6 @@ void u8g_SetPILevel(u8g_t *u8g, uint8_t pin_index, uint8_t level) {
uint8_t u8g_com_samd21_st7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
static SPISettings lcdSPIConfig;
switch (msg) {
case U8G_COM_MSG_STOP:
@@ -99,7 +98,6 @@ uint8_t u8g_com_samd21_st7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val
u8g_SetPILevel(u8g, U8G_PI_CS, LOW);
spiBegin();
lcdSPIConfig = SPISettings(900000, MSBFIRST, SPI_MODE0);
u8g->pin_list[U8G_PI_A0_STATE] = 0;
break;
@@ -117,7 +115,7 @@ uint8_t u8g_com_samd21_st7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val
break;
case U8G_COM_MSG_WRITE_BYTE:
SPI.beginTransaction(lcdSPIConfig);
spiBeginTransaction(LCD_SPI_SPEED, MSBFIRST, SPI_MODE0);
if (u8g->pin_list[U8G_PI_A0_STATE] == 0) { // command
SPI.transfer(0x0f8); u8g->pin_list[U8G_PI_A0_STATE] = 2;
@@ -132,7 +130,7 @@ uint8_t u8g_com_samd21_st7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val
break;
case U8G_COM_MSG_WRITE_SEQ:
SPI.beginTransaction(lcdSPIConfig);
spiBeginTransaction(LCD_SPI_SPEED, MSBFIRST, SPI_MODE0);
if (u8g->pin_list[U8G_PI_A0_STATE] == 0 ) { // command
SPI.transfer(0x0f8); u8g->pin_list[U8G_PI_A0_STATE] = 2;
+45 -21
View File
@@ -33,6 +33,12 @@
#define BLOCK_SIZE 512
#define PRODUCT_ID 0x29
#ifndef SD_MULTIBLOCK_RETRY_CNT
#define SD_MULTIBLOCK_RETRY_CNT 1
#elif SD_MULTIBLOCK_RETRY_CNT < 1
#error "SD_MULTIBLOCK_RETRY_CNT must be greater than or equal to 1."
#endif
class Sd2CardUSBMscHandler : public USBMscHandler {
public:
DiskIODriver* diskIODriver() {
@@ -58,19 +64,29 @@ public:
// single block
if (blkLen == 1) {
hal.watchdog_refresh();
sd2card->writeBlock(blkAddr, pBuf);
return true;
return sd2card->writeBlock(blkAddr, pBuf);
}
// multi block optimization
sd2card->writeStart(blkAddr, blkLen);
while (blkLen--) {
hal.watchdog_refresh();
sd2card->writeData(pBuf);
pBuf += BLOCK_SIZE;
bool done = false;
for (uint16_t rcount = SD_MULTIBLOCK_RETRY_CNT; !done && rcount--;) {
uint8_t *cBuf = pBuf;
sd2card->writeStart(blkAddr, blkLen);
bool okay = true; // Assume success
for (uint32_t i = blkLen; i--;) {
hal.watchdog_refresh();
if (!sd2card->writeData(cBuf)) { // Write. Did it fail?
sd2card->writeStop(); // writeStop for new writeStart
okay = false; // Failed, so retry
break; // Go to while... below
}
cBuf += BLOCK_SIZE;
}
done = okay; // Done if no error occurred
}
sd2card->writeStop();
return true;
if (done) sd2card->writeStop();
return done;
}
bool Read(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) {
@@ -78,24 +94,32 @@ public:
// single block
if (blkLen == 1) {
hal.watchdog_refresh();
sd2card->readBlock(blkAddr, pBuf);
return true;
return sd2card->readBlock(blkAddr, pBuf);
}
// multi block optimization
sd2card->readStart(blkAddr);
while (blkLen--) {
hal.watchdog_refresh();
sd2card->readData(pBuf);
pBuf += BLOCK_SIZE;
bool done = false;
for (uint16_t rcount = SD_MULTIBLOCK_RETRY_CNT; !done && rcount--;) {
uint8_t *cBuf = pBuf;
sd2card->readStart(blkAddr);
bool okay = true; // Assume success
for (uint32_t i = blkLen; i--;) {
hal.watchdog_refresh();
if (!sd2card->readData(cBuf)) { // Read. Did it fail?
sd2card->readStop(); // readStop for new readStart
okay = false; // Failed, so retry
break; // Go to while... below
}
cBuf += BLOCK_SIZE;
}
done = okay; // Done if no error occurred
}
sd2card->readStop();
return true;
if (done) sd2card->readStop();
return done;
}
bool IsReady() {
return diskIODriver()->isReady();
}
bool IsReady() { return diskIODriver()->isReady(); }
};
Sd2CardUSBMscHandler usbMscHandler;
+2 -2
View File
@@ -28,7 +28,7 @@
// Copied from ~/.platformio/packages/framework-arduinoststm32-maple/STM32F1/system/libmaple/usart_private.h
// Changed to handle Emergency Parser
static inline __always_inline void my_usart_irq(ring_buffer *rb, ring_buffer *wb, usart_reg_map *regs, MSerialT &serial) {
static __always_inline void my_usart_irq(ring_buffer *rb, ring_buffer *wb, usart_reg_map *regs, MSerialT &serial) {
/* Handle RXNEIE and TXEIE interrupts.
* RXNE signifies availability of a byte in DR.
*
@@ -75,7 +75,7 @@ static inline __always_inline void my_usart_irq(ring_buffer *rb, ring_buffer *wb
}
// Not every MarlinSerial port should handle emergency parsing.
// It would not make sense to parse GCode from TMC responses, for example.
// It would not make sense to parse G-Code from TMC responses, for example.
constexpr bool serial_handles_emergency(int port) {
return (false
#ifdef SERIAL_PORT
@@ -55,7 +55,12 @@ static const char *UnwTabGetFunctionName(const UnwindCallbacks *cb, uint32_t add
return nullptr;
if ((flag_word & 0xFF000000) == 0xFF000000) {
return (const char *)(address - 4 - (flag_word & 0x00FFFFFF));
const uint32_t fn_name_addr = address - 4 - (flag_word & 0x00FFFFFF);
// Ensure the address is readable to avoid returning a bogus pointer
uint8_t dummy = 0;
if (cb->readB(fn_name_addr, &dummy))
return (const char *)fn_name_addr;
}
return nullptr;
}
@@ -279,8 +279,6 @@ void CommonHandler_C(ContextStateFrame * frame, unsigned long lr, unsigned long
if (!faulted_from_exception) { // Not sure about the non_usage_fault, we want to try anyway, don't we ? && !non_usage_fault_occurred)
// Try to resume to our handler here
CFSR |= CFSR; // The ARM programmer manual says you must write to 1 all fault bits to clear them so this instruction is correct
// The frame will not be valid when returning anymore, let's clean it
savedFrame.CFSR = 0;
frame->pc = (uint32_t)resume_from_fault; // Patch where to return to
frame->lr = 0xDEADBEEF; // If our handler returns (it shouldn't), let's make it trigger an exception immediately
+2 -2
View File
@@ -862,7 +862,7 @@ void idle(const bool no_stepper_sleep/*=false*/) {
TERN_(HAS_TFT_LVGL_UI, LV_TASK_HANDLER());
// Manage Fixed-time Motion Control
TERN_(FT_MOTION, fxdTiCtrl.loop());
TERN_(FT_MOTION, ftMotion.loop());
IDLE_DONE:
TERN_(MARLIN_DEV_MODE, idle_depth--);
@@ -1632,7 +1632,7 @@ void setup() {
#endif
#if ENABLED(FT_MOTION)
SETUP_RUN(fxdTiCtrl.init());
SETUP_RUN(ftMotion.init());
#endif
marlin_state = MF_RUNNING;
+7 -3
View File
@@ -179,6 +179,7 @@
#define BOARD_GT2560_V4_A20 1328 // Geeetech GT2560 Rev B for A20(M/T/D)
#define BOARD_PROTONEER_CNC_SHIELD_V3 1329 // Mega controller & Protoneer CNC Shield V3.00
#define BOARD_WEEDO_62A 1330 // WEEDO 62A board (TINA2, Monoprice Cadet, etc.)
#define BOARD_GT2560_V41B 1331 // Geeetech GT2560 V4.1B for A10(M/T/D)
//
// ATmega1281, ATmega2561
@@ -317,9 +318,9 @@
//
#define BOARD_BTT_EBB42_V1_1 4000 // BigTreeTech EBB42 V1.1 (STM32G0B1CB)
#define BOARD_BTT_SKR_MINI_E3_V3_0 4001 // BigTreeTech SKR Mini E3 V3.0 (STM32G0B1RE)
#define BOARD_BTT_SKR_MINI_E3_V3_0 4001 // BigTreeTech SKR Mini E3 V3.0 (STM32G0B0RE / STM32G0B1RE)
#define BOARD_BTT_MANTA_E3_EZ_V1_0 4002 // BigTreeTech Manta E3 EZ V1.0 (STM32G0B1RE)
#define BOARD_BTT_MANTA_M4P_V1_0 4003 // BigTreeTech Manta M4P V1.0 (STM32G0B1RE)
#define BOARD_BTT_MANTA_M4P_V2_1 4003 // BigTreeTech Manta M4P V2.1 (STM32G0B0RE)
#define BOARD_BTT_MANTA_M5P_V1_0 4004 // BigTreeTech Manta M5P V1.0 (STM32G0B1RE)
#define BOARD_BTT_MANTA_M8P_V1_0 4005 // BigTreeTech Manta M8P V1.0 (STM32G0B1VE)
#define BOARD_BTT_MANTA_M8P_V1_1 4006 // BigTreeTech Manta M8P V1.1 (STM32G0B1VE)
@@ -395,7 +396,7 @@
#define BOARD_ZONESTAR_ZM3E4V2 5064 // Zonestar ZM3E4 V2 (STM32F103VC)
#define BOARD_ERYONE_ERY32_MINI 5065 // Eryone Ery32 mini (STM32F103VE)
#define BOARD_PANDA_PI_V29 5066 // Panda Pi V2.9 - Standalone (STM32F103RC)
#define BOARD_SOVOL_V131 5067 // Sovol V1.3.1 (GD32F103RET6)
#define BOARD_SOVOL_V131 5067 // Sovol V1.3.1 (GD32F103RE)
#define BOARD_TRIGORILLA_V006 5068 // Trigorilla V0.0.6 (GD32F103RE)
#define BOARD_KEDI_CONTROLLER_V1_2 5069 // EDUTRONICS Kedi Controller V1.2 (STM32F103RC)
@@ -458,6 +459,8 @@
#define BOARD_CREALITY_F401RE 5245 // Creality CR4NS200141C13 (STM32F401RE) as found in the Ender-5 S1
#define BOARD_BLACKPILL_CUSTOM 5246 // Custom board based on STM32F401CDU6.
#define BOARD_I3DBEEZ9_V1 5247 // I3DBEEZ9 V1 (STM32F407ZG)
#define BOARD_MELLOW_FLY_E3_V2 5248 // Mellow Fly E3 V2 (STM32F407VG)
#define BOARD_FYSETC_CHEETAH_V30 5249 // FYSETC Cheetah V3.0 (STM32F446RC)
//
// ARM Cortex-M7
@@ -489,6 +492,7 @@
#define BOARD_MKS_TINYBEE 7008 // MKS TinyBee based on ESP32 (with I2S stepper stream)
#define BOARD_ENWI_ESPNP 7009 // enwi ESPNP based on ESP32 (with I2S stepper stream)
#define BOARD_GODI_CONTROLLER_V1_0 7010 // Godi Controller based on ESP32 32-Bit V1.0
#define BOARD_MM_JOKER 7011 // MagicMaker JOKER based on ESP32 (with I2S stepper stream)
//
// SAMD51 ARM Cortex-M4
+6
View File
@@ -29,6 +29,7 @@
#undef DEBUG_SECTION
#undef DEBUG_ECHO_START
#undef DEBUG_ERROR_START
#undef DEBUG_WARN_START
#undef DEBUG_CHAR
#undef DEBUG_ECHO
#undef DEBUG_ECHOLN
@@ -38,6 +39,7 @@
#undef DEBUG_ECHOLNPGM_P
#undef DEBUG_ECHO_MSG
#undef DEBUG_ERROR_MSG
#undef DEBUG_WARN_MSG
#undef DEBUG_EOL
#undef DEBUG_FLUSH
#undef DEBUG_POS
@@ -52,6 +54,7 @@
#define DEBUG_ECHO_START SERIAL_ECHO_START
#define DEBUG_ERROR_START SERIAL_ERROR_START
#define DEBUG_WARN_START SERIAL_WARN_START
#define DEBUG_CHAR SERIAL_CHAR
#define DEBUG_ECHO SERIAL_ECHO
#define DEBUG_ECHOLN SERIAL_ECHOLN
@@ -63,6 +66,7 @@
#define DEBUG_ECHOLNPGM_P SERIAL_ECHOLNPGM_P
#define DEBUG_ECHO_MSG SERIAL_ECHO_MSG
#define DEBUG_ERROR_MSG SERIAL_ERROR_MSG
#define DEBUG_WARN_MSG SERIAL_WARN_MSG
#define DEBUG_EOL SERIAL_EOL
#define DEBUG_FLUSH SERIAL_FLUSH
#define DEBUG_POS SERIAL_POS
@@ -75,6 +79,7 @@
#define DEBUG_SECTION(...) NOOP
#define DEBUG_ECHO_START() NOOP
#define DEBUG_ERROR_START() NOOP
#define DEBUG_WARN_START() NOOP
#define DEBUG_CHAR(...) NOOP
#define DEBUG_ECHO(...) NOOP
#define DEBUG_ECHOLN(...) NOOP
@@ -84,6 +89,7 @@
#define DEBUG_ECHOLNPGM_P(...) NOOP
#define DEBUG_ECHO_MSG(...) NOOP
#define DEBUG_ERROR_MSG(...) NOOP
#define DEBUG_WARN_MSG(...) NOOP
#define DEBUG_EOL() NOOP
#define DEBUG_FLUSH() NOOP
#define DEBUG_POS(...) NOOP
+3 -2
View File
@@ -154,7 +154,7 @@
#define STR_ERR_ARC_ARGS "G2/G3 bad parameters"
#define STR_ERR_PROTECTED_PIN "Protected Pin"
#define STR_ERR_M420_FAILED "Failed to enable Bed Leveling"
#define STR_ERR_M428_TOO_FAR "Too far from reference point"
#define STR_ERR_M428_TOO_FAR "Too far from MIN/MAX"
#define STR_ERR_M303_DISABLED "PIDTEMP disabled"
#define STR_M119_REPORT "Reporting endstop status"
#define STR_ON "ON"
@@ -254,7 +254,7 @@
#define STR_REDUNDANCY "Heater switched off. Temperature difference between temp sensors is too high !"
#define STR_T_HEATING_FAILED "Heating failed"
#define STR_T_THERMAL_RUNAWAY "Thermal Runaway"
#define STR_T_MALFUNCTION "Thermal Malfunction"
#define STR_T_THERMAL_MALFUNCTION "Thermal Malfunction"
#define STR_T_MAXTEMP "MAXTEMP triggered"
#define STR_T_MINTEMP "MINTEMP triggered"
#define STR_ERR_PROBING_FAILED "Probing Failed"
@@ -301,6 +301,7 @@
#define STR_CHAMBER_PID "Chamber PID"
#define STR_STEPS_PER_UNIT "Steps per unit"
#define STR_LINEAR_ADVANCE "Linear Advance"
#define STR_NONLINEAR_EXTRUSION "Nonlinear Extrusion"
#define STR_CONTROLLER_FAN "Controller Fan"
#define STR_STEPPER_MOTOR_CURRENTS "Stepper motor currents"
#define STR_RETRACT_S_F_Z "Retract (S<length> F<feedrate> Z<lift>)"
+12 -4
View File
@@ -178,16 +178,18 @@
#define _DO_N(W,C,N,V...) __DO_N(W,C,N,V)
#define DO(W,C,V...) (_DO_N(W,C,NUM_ARGS(V),V))
// Macros to support option testing
// Concatenate symbol names, without or with pre-expansion
#define _CAT(a,V...) a##V
#define CAT(a,V...) _CAT(a,V)
// Recognize "true" values: blank, 1, 0x1, true
#define _ISENA_ ~,1
#define _ISENA_1 ~,1
#define _ISENA_0x1 ~,1
#define _ISENA_true ~,1
#define _ISENA(V...) IS_PROBE(V)
// Macros to evaluate simple option switches
#define _ENA_1(O) _ISENA(CAT(_IS,CAT(ENA_, O)))
#define _DIS_1(O) NOT(_ENA_1(O))
#define ENABLED(V...) DO(ENA,&&,V)
@@ -198,6 +200,7 @@
#define COUNT_ENABLED(V...) DO(ENA,+,V)
#define MANY(V...) (COUNT_ENABLED(V) > 1)
// Ternary pre-compiler macros conceal non-emitted content from the compiler
#define TERN(O,A,B) _TERN(_ENA_1(O),B,A) // OPTION ? 'A' : 'B'
#define TERN0(O,A) _TERN(_ENA_1(O),0,A) // OPTION ? 'A' : '0'
#define TERN1(O,A) _TERN(_ENA_1(O),1,A) // OPTION ? 'A' : '1'
@@ -205,7 +208,9 @@
#define _TERN(E,V...) __TERN(_CAT(T_,E),V) // Prepend 'T_' to get 'T_0' or 'T_1'
#define __TERN(T,V...) ___TERN(_CAT(_NO,T),V) // Prepend '_NO' to get '_NOT_0' or '_NOT_1'
#define ___TERN(P,V...) THIRD(P,V) // If first argument has a comma, A. Else B.
#define IF_DISABLED(O,A) TERN(O,,A)
// Macros to conditionally emit array items and function arguments
#define _OPTITEM(A...) A,
#define OPTITEM(O,A...) TERN_(O,DEFER4(_OPTITEM)(A))
#define _OPTARG(A...) , A
@@ -220,8 +225,6 @@
#define SUM_TERN(O,B,A) ((B) PLUS_TERN0(O,A)) // ((B) (OPTION ? '+ (A)' : '<nul>'))
#define DIFF_TERN(O,B,A) ((B) MINUS_TERN0(O,A)) // ((B) (OPTION ? '- (A)' : '<nul>'))
#define IF_DISABLED(O,A) TERN(O,,A)
// Macros to support pins/buttons exist testing
#define PIN_EXISTS(PN) (defined(PN##_PIN) && PN##_PIN >= 0)
#define _PINEX_1 PIN_EXISTS
@@ -233,6 +236,7 @@
#define BUTTONS_EXIST(V...) DO(BTNEX,&&,V)
#define ANY_BUTTON(V...) DO(BTNEX,||,V)
// Value helper macros
#define WITHIN(N,L,H) ((N) >= (L) && (N) <= (H))
#define ISEOL(C) ((C) == '\n' || (C) == '\r')
#define NUMERIC(a) WITHIN(a, '0', '9')
@@ -240,6 +244,8 @@
#define HEXCHR(a) (NUMERIC(a) ? (a) - '0' : WITHIN(a, 'a', 'f') ? ((a) - 'a' + 10) : WITHIN(a, 'A', 'F') ? ((a) - 'A' + 10) : -1)
#define NUMERIC_SIGNED(a) (NUMERIC(a) || (a) == '-' || (a) == '+')
#define DECIMAL_SIGNED(a) (DECIMAL(a) || (a) == '-' || (a) == '+')
// Array shorthand
#define COUNT(a) (sizeof(a)/sizeof(*a))
#define ZERO(a) memset((void*)a,0,sizeof(a))
#define COPY(a,b) do{ \
@@ -247,6 +253,7 @@
memcpy(&a[0],&b[0],_MIN(sizeof(a),sizeof(b))); \
}while(0)
// Expansion of some code
#define CODE_16( A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,...) A; B; C; D; E; F; G; H; I; J; K; L; M; N; O; P
#define CODE_15( A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,...) A; B; C; D; E; F; G; H; I; J; K; L; M; N; O
#define CODE_14( A,B,C,D,E,F,G,H,I,J,K,L,M,N,...) A; B; C; D; E; F; G; H; I; J; K; L; M; N
@@ -267,6 +274,7 @@
#define _CODE_N(N,V...) CODE_##N(V)
#define CODE_N(N,V...) _CODE_N(N,V)
// Expansion of some non-delimited content
#define GANG_16(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,...) A B C D E F G H I J K L M N O P
#define GANG_15(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,...) A B C D E F G H I J K L M N O
#define GANG_14(A,B,C,D,E,F,G,H,I,J,K,L,M,N,...) A B C D E F G H I J K L M N
@@ -288,7 +296,7 @@
#define GANG_N(N,V...) _GANG_N(N,V)
#define GANG_N_1(N,K) _GANG_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K)
// Macros for initializing arrays
// Expansion of some list items
#define LIST_26(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
#define LIST_25(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y
#define LIST_24(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X
+4 -2
View File
@@ -27,7 +27,8 @@
#include "../feature/ethernet.h"
#endif
uint8_t marlin_debug_flags = MARLIN_DEBUG_NONE;
// Echo commands to the terminal by default in dev mode
uint8_t marlin_debug_flags = TERN(MARLIN_DEV_MODE, MARLIN_DEBUG_ECHO, MARLIN_DEBUG_NONE);
// Commonly-used strings in serial output
PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C");
@@ -69,7 +70,7 @@ MAP(_N_LBL, LOGICAL_AXIS_NAMES); MAP(_SP_N_LBL, LOGICAL_AXIS_NAMES);
#endif
// Specializations for float, p_float_t, w_float_t
template <> void SERIAL_ECHO(const float f) { SERIAL_IMPL.print(f); }
template <> void SERIAL_ECHO(const float f) { SERIAL_IMPL.print(f, SERIAL_FLOAT_PRECISION); }
template <> void SERIAL_ECHO(const p_float_t pf) { SERIAL_IMPL.print(pf.value, pf.prec); }
template <> void SERIAL_ECHO(const w_float_t wf) { char f1[20]; SERIAL_IMPL.print(dtostrf(wf.value, wf.width, wf.prec, f1)); }
@@ -92,6 +93,7 @@ void SERIAL_ECHOLN_P(PGM_P pstr) { SERIAL_ECHO_P(pstr); SERIAL_EOL(); }
void SERIAL_ECHO_START() { SERIAL_ECHO(F("echo:")); }
void SERIAL_ERROR_START() { SERIAL_ECHO(F("Error:")); }
void SERIAL_WARN_START() { SERIAL_ECHO(F("Warning:")); }
void SERIAL_ECHO_SP(uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) SERIAL_CHAR(' '); }
+2
View File
@@ -161,6 +161,7 @@ void SERIAL_FLUSHTX();
// Start an echo: or error: output
void SERIAL_ECHO_START();
void SERIAL_ERROR_START();
void SERIAL_WARN_START();
// Serial end-of-line
void SERIAL_EOL();
@@ -227,6 +228,7 @@ void SERIAL_ECHOLN(T arg1, Args ... args) { SERIAL_ECHO(arg1); SERIAL_ECHO(args
#define SERIAL_ECHO_MSG(V...) do{ SERIAL_ECHO_START(); SERIAL_ECHOLNPGM(V); }while(0)
#define SERIAL_ERROR_MSG(V...) do{ SERIAL_ERROR_START(); SERIAL_ECHOLNPGM(V); }while(0)
#define SERIAL_WARN_MSG(V...) do{ SERIAL_WARN_START(); SERIAL_ECHOLNPGM(V); }while(0)
// Print a prefix, conditional string, and suffix
void serial_ternary(FSTR_P const pre, const bool onoff, FSTR_P const on, FSTR_P const off, FSTR_P const post=nullptr);
+1 -1
View File
@@ -33,7 +33,7 @@ void safe_delay(millis_t ms); // Delay ensuring that temperatures are
inline void serial_delay(const millis_t) {}
#endif
#if (GRID_MAX_POINTS_X) && (GRID_MAX_POINTS_Y)
#if GRID_MAX_POINTS
// 16x16 bit arrays
template <int W, int H>
+37 -17
View File
@@ -63,25 +63,25 @@ Backlash backlash;
* spread over multiple segments, smoothing out artifacts even more.
*/
void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const int32_t &dc, const AxisBits dm, block_t * const block) {
void Backlash::add_correction_steps(const xyze_long_t &dist, const AxisBits dm, block_t * const block) {
AxisBits changed_dir = last_direction_bits ^ dm;
// Ignore direction change unless steps are taken in that direction
#if DISABLED(CORE_BACKLASH) || ANY(MARKFORGED_XY, MARKFORGED_YX)
if (!da) changed_dir.x = false;
if (!db) changed_dir.y = false;
if (!dc) changed_dir.z = false;
if (!dist.a) changed_dir.x = false;
if (!dist.b) changed_dir.y = false;
if (!dist.c) changed_dir.z = false;
#elif CORE_IS_XY
if (!(da + db)) changed_dir.x = false;
if (!(da - db)) changed_dir.y = false;
if (!dc) changed_dir.z = false;
if (!(dist.a + dist.b)) changed_dir.x = false;
if (!(dist.a - dist.b)) changed_dir.y = false;
if (!dist.c) changed_dir.z = false;
#elif CORE_IS_XZ
if (!(da + dc)) changed_dir.x = false;
if (!(da - dc)) changed_dir.z = false;
if (!db) changed_dir.y = false;
if (!(dist.a + dist.c)) changed_dir.x = false;
if (!(dist.a - dist.c)) changed_dir.z = false;
if (!dist.b) changed_dir.y = false;
#elif CORE_IS_YZ
if (!(db + dc)) changed_dir.y = false;
if (!(db - dc)) changed_dir.z = false;
if (!da) changed_dir.x = false;
if (!(dist.b + dist.c)) changed_dir.y = false;
if (!(dist.b - dist.c)) changed_dir.z = false;
if (!dist.a) changed_dir.x = false;
#endif
last_direction_bits ^= changed_dir;
@@ -97,7 +97,15 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const
const float f_corr = float(correction) / all_on;
bool changed = false;
float millimeters_delta = 0.0f;
#if IS_KINEMATIC
float sqr_stepper_space_mm = 0.0f;
#endif
LOOP_NUM_AXES(axis) {
TERN_(IS_KINEMATIC, sqr_stepper_space_mm += sq(dist[axis] * planner.mm_per_step[axis]));
if (distance_mm[axis]) {
const bool forward = dm[axis];
@@ -107,8 +115,6 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const
// Decide how much of the residual error to correct in this segment
int32_t error_correction = residual_error[axis];
if (forward == (error_correction < 0))
error_correction = 0; // Don't take up any backlash in this segment, as it would subtract steps
#ifdef BACKLASH_SMOOTHING_MM
if (error_correction && smoothing_mm != 0) {
@@ -118,9 +124,18 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const
}
#endif
// Don't correct backlash in the opposite direction to movement on this axis and for accuracy in
// updating block->millimeters, don't add too many steps to the movement on this axis
if (forward)
LIMIT(error_correction, 0, dist[axis]);
else
LIMIT(error_correction, dist[axis], 0);
// This correction reduces the residual error and adds block steps
if (error_correction) {
changed = true;
block->steps[axis] += ABS(error_correction);
millimeters_delta += dist[axis] * error_correction * sq(planner.mm_per_step[axis]);
#if ENABLED(CORE_BACKLASH)
switch (axis) {
case CORE_AXIS_1:
@@ -142,6 +157,11 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const
}
}
}
// If backlash correction steps were added modify block->millimeters with a linear approximation
// See https://github.com/MarlinFirmware/Marlin/pull/26392
if (changed)
block->millimeters += TERN(IS_KINEMATIC, millimeters_delta * block->millimeters / sqr_stepper_space_mm, millimeters_delta / block->millimeters);
}
int32_t Backlash::get_applied_steps(const AxisEnum axis) {
@@ -151,8 +171,8 @@ int32_t Backlash::get_applied_steps(const AxisEnum axis) {
const int32_t residual_error_axis = residual_error[axis];
// At startup it is assumed the last move was forwards. So the applied
// steps will always be a non-positive number.
// At startup it is assumed the last move was forward.
// So the applied steps will always be negative.
if (forward) return -residual_error_axis;
+1 -1
View File
@@ -72,7 +72,7 @@ public:
return has_measurement(X_AXIS) || has_measurement(Y_AXIS) || has_measurement(Z_AXIS);
}
static void add_correction_steps(const int32_t &da, const int32_t &db, const int32_t &dc, const AxisBits dm, block_t * const block);
static void add_correction_steps(const xyze_long_t &dist, const AxisBits dm, block_t * const block);
static int32_t get_applied_steps(const AxisEnum axis);
#if ENABLED(BACKLASH_GCODE)
+15 -12
View File
@@ -78,8 +78,8 @@ bool BDS_Leveling::check(const uint16_t data, const bool raw_data/*=false*/, con
return true; // error
}
if (raw_data == true) {
if (hicheck && (data & 0x3FF) > 550)
SERIAL_ECHOLNPGM("BD Sensor mounted too high!");
if (hicheck && (data & 0x3FF) > 400)
SERIAL_ECHOLNPGM("Bad BD Sensor height! Recommended distance 0.5-2.0mm");
else if (!good_data(data))
SERIAL_ECHOLNPGM("Invalid data, please calibrate.");
else
@@ -109,7 +109,8 @@ void BDS_Leveling::process() {
static float zpos = 0.0f;
const millis_t ms = millis();
if (ELAPSED(ms, next_check_ms)) { // timed out (or first run)
next_check_ms = ms + (config_state < BDS_IDLE ? 200 : 50); // check at 5Hz or 20Hz
// Check at 1KHz, 5Hz, or 20Hz
next_check_ms = ms + (config_state == BDS_HOMING_Z ? 1 : (config_state < BDS_IDLE ? 200 : 50));
uint16_t tmp = 0;
const float cur_z = planner.get_axis_position_mm(Z_AXIS) - pos_zero_offset;
@@ -127,16 +128,14 @@ void BDS_Leveling::process() {
babystep.set_mm(Z_AXIS, cur_z - z_sensor);
DEBUG_ECHOLNPGM("BD:", z_sensor, ", Z:", cur_z, "|", current_position.z);
}
else {
babystep.set_mm(Z_AXIS, 0); //if (old_cur_z <= cur_z) Z_DIR_WRITE(HIGH);
//stepper.apply_directions(); // TODO: Remove this line as probably not needed
}
else
babystep.set_mm(Z_AXIS, 0);
}
#endif
old_cur_z = cur_z;
old_buf_z = current_position.z;
endstops.bdp_state_update(z_sensor <= 0.01f);
endstops.bdp_state_update(z_sensor <= BD_SENSOR_HOME_Z_POSITION);
#if HAS_STATUS_MESSAGE
static float old_z_sensor = 0;
@@ -149,8 +148,10 @@ void BDS_Leveling::process() {
}
#endif
}
else
stepper.apply_directions();
else if (config_state == BDS_HOMING_Z) {
SERIAL_ECHOLNPGM("Read:", tmp);
kill(F("BDsensor connect Err!"));
}
DEBUG_ECHOLNPGM("BD:", tmp & 0x3FF, " Z:", cur_z, "|", current_position.z);
if (TERN0(DEBUG_OUT_BD, BD_I2C_SENSOR.BD_Check_OddEven(tmp) == 0)) DEBUG_ECHOLNPGM("CRC error");
@@ -233,11 +234,13 @@ void BDS_Leveling::process() {
sprintf_P(tmp_1, PSTR("G1Z%d.%d"), int(zpos), int(zpos * 10) % 10);
gcode.process_subcommands_now(tmp_1);
SERIAL_ECHO(tmp_1); SERIAL_ECHOLNPGM(", Z:", current_position.z);
for (float tmp_k = 0; abs(zpos - tmp_k) > 0.004f;) {
uint16_t failcount = 300;
for (float tmp_k = 0; abs(zpos - tmp_k) > 0.006f && failcount--;) {
tmp_k = planner.get_axis_position_mm(Z_AXIS) - pos_zero_offset;
safe_delay(10);
if (!failcount--) break;
}
safe_delay(zpos <= 0.4f ? 600 : 100);
safe_delay(600);
tmp = uint16_t((zpos + 0.00001f) * 10);
BD_I2C_SENSOR.BD_i2c_write(tmp);
SERIAL_ECHOLNPGM("w:", tmp, ", Z:", zpos);
+4
View File
@@ -23,6 +23,10 @@
#include <stdint.h>
#ifndef BD_SENSOR_HOME_Z_POSITION
#define BD_SENSOR_HOME_Z_POSITION 0.5
#endif
enum BDS_State : int8_t {
BDS_IDLE,
BDS_VERSION = -1,
+9 -2
View File
@@ -772,6 +772,7 @@ void unified_bed_leveling::shift_mesh_height() {
const grid_count_t point_num = (GRID_MAX_POINTS - count) + 1;
SERIAL_ECHOLNPGM("Probing mesh point ", point_num, "/", GRID_MAX_POINTS, ".");
TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_POINT), point_num, int(GRID_MAX_POINTS)));
TERN_(LCD_BACKLIGHT_TIMEOUT_MINS, ui.refresh_backlight_timeout());
#if HAS_MARLINUI_MENU
if (ui.button_pressed()) {
@@ -786,14 +787,18 @@ void unified_bed_leveling::shift_mesh_height() {
}
#endif
best = do_furthest
#ifndef HUGE_VALF
#define HUGE_VALF FLT_MAX
#endif
best = do_furthest // Points with valid data or HUGE_VALF are skipped
? find_furthest_invalid_mesh_point()
: find_closest_mesh_point_of_type(INVALID, nearby, true);
if (best.pos.x >= 0) { // mesh point found and is reachable by probe
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::G29_POINT_START));
const float measured_z = probe.probe_at_point(best.meshpos(), stow_probe ? PROBE_PT_STOW : PROBE_PT_RAISE, param.V_verbosity);
z_values[best.pos.x][best.pos.y] = measured_z;
z_values[best.pos.x][best.pos.y] = isnan(measured_z) ? HUGE_VALF : measured_z; // Mark invalid point already probed with HUGE_VALF to omit it in the next loop
#if ENABLED(EXTENSIBLE_UI)
ExtUI::onMeshUpdate(best.pos, ExtUI::G29_POINT_FINISH);
ExtUI::onMeshUpdate(best.pos, measured_z);
@@ -803,6 +808,8 @@ void unified_bed_leveling::shift_mesh_height() {
} while (best.pos.x >= 0 && --count);
GRID_LOOP(x, y) if (z_values[x][y] == HUGE_VALF) z_values[x][y] = NAN; // Restore NAN for HUGE_VALF marks
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::G29_FINISH));
// Release UI during stow to allow for PAUSE_BEFORE_DEPLOY_STOW
+1 -1
View File
@@ -30,7 +30,7 @@
class CaseLight {
public:
static bool on;
#if ENABLED(CASELIGHT_USES_BRIGHTNESS)
#if CASELIGHT_USES_BRIGHTNESS
static uint8_t brightness;
#endif
+10 -1
View File
@@ -706,7 +706,7 @@ void Max7219::idle_tasks() {
#ifdef MAX7219_DEBUG_PLANNER_QUEUE
static int16_t last_depth = 0;
const int16_t current_depth = (head - tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1) & 0xF;
const int16_t current_depth = BLOCK_MOD(head - tail + (BLOCK_BUFFER_SIZE)) & 0xF;
if (current_depth != last_depth) {
quantity16(MAX7219_DEBUG_PLANNER_QUEUE, last_depth, current_depth, &row_change_mask);
last_depth = current_depth;
@@ -735,6 +735,15 @@ void Max7219::idle_tasks() {
}
#endif
#ifdef MAX7219_DEBUG_SLOWDOWN
static uint8_t last_slowdown_count = 0;
const uint8_t slowdown_count = Planner::slowdown_count;
if (slowdown_count != last_slowdown_count) {
mark16(MAX7219_DEBUG_SLOWDOWN, last_slowdown_count, slowdown_count, &row_change_mask);
last_slowdown_count = slowdown_count;
}
#endif
// batch line updates
suspended--;
if (!suspended)
+1 -1
View File
@@ -160,7 +160,7 @@ void MMU2::mmu_loop() {
MMU2_SEND("S1"); // Read Version
state = -2;
}
else if (millis() > 30000) { // 30sec after reset disable MMU
else if (ELAPSED(millis(), prev_request + 30000)) { // 30sec after reset disable MMU
SERIAL_ECHOLNPGM("MMU not responding - DISABLED");
state = 0;
}
+8
View File
@@ -53,6 +53,10 @@ bool Power::psu_on;
#include "controllerfan.h"
#endif
#if ANY(LASER_FEATURE, SPINDLE_FEATURE)
#include "spindle_laser.h"
#endif
millis_t Power::lastPowerOn;
#endif
@@ -196,6 +200,10 @@ void Power::power_off() {
if (controllerFan.state()) return true;
#endif
#if ANY(LASER_FEATURE, SPINDLE_FEATURE)
if (TERN0(AUTO_POWER_SPINDLE_LASER, cutter.enabled())) return true;
#endif
if (TERN0(AUTO_POWER_CHAMBER_FAN, thermalManager.chamberfan_speed))
return true;
+5 -5
View File
@@ -219,15 +219,13 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW
#endif
#endif
#if HAS_EXTRUDERS
#if HAS_HOTEND
HOTEND_LOOP() info.target_temperature[e] = thermalManager.degTargetHotend(e);
#endif
TERN_(HAS_HEATED_BED, info.target_temperature_bed = thermalManager.degTargetBed());
#if HAS_FAN
COPY(info.fan_speed, thermalManager.fan_speed);
#endif
TERN_(HAS_FAN, COPY(info.fan_speed, thermalManager.fan_speed));
#if HAS_LEVELING
info.flag.leveling = planner.leveling_active;
@@ -672,7 +670,9 @@ void PrintJobRecovery::resume() {
DEBUG_ECHOLNPGM("flag.dryrun: ", AS_DIGIT(info.flag.dryrun));
DEBUG_ECHOLNPGM("flag.allow_cold_extrusion: ", AS_DIGIT(info.flag.allow_cold_extrusion));
DEBUG_ECHOLNPGM("flag.volumetric_enabled: ", AS_DIGIT(info.flag.volumetric_enabled));
#if DISABLED(NO_VOLUMETRICS)
DEBUG_ECHOLNPGM("flag.volumetric_enabled: ", AS_DIGIT(info.flag.volumetric_enabled));
#endif
}
else
DEBUG_ECHOLNPGM("INVALID DATA");
+3 -4
View File
@@ -57,7 +57,8 @@
* 41 - Counter-Clockwise M4
* 50 - Clockwise M5
* 51 - Counter-Clockwise M5
**/
*
*/
void GcodeSuite::G35() {
DEBUG_SECTION(log_G35, "G35", DEBUGGING(LEVELING));
@@ -82,9 +83,7 @@ void GcodeSuite::G35() {
set_bed_leveling_enabled(false);
#endif
#if ENABLED(CNC_WORKSPACE_PLANES)
workspace_plane = PLANE_XY;
#endif
TERN_(CNC_WORKSPACE_PLANES, workspace_plane = PLANE_XY);
probe.use_probing_tool();
+1
View File
@@ -748,6 +748,7 @@ G29_TYPE GcodeSuite::G29() {
}
//if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM_P(axis == Y_AXIS ? PSTR("Y=") : PSTR("X=", pos);
safe_delay(4);
abl.measured_z = current_position.z - bdl.read();
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("x_cur ", planner.get_axis_position_mm(X_AXIS), " z ", abl.measured_z);
+1 -1
View File
@@ -536,7 +536,7 @@ void GcodeSuite::G28() {
/**
* Preserve DXC mode across a G28 for IDEX printers in DXC_DUPLICATION_MODE.
* This is important because it lets a user use the LCD Panel to set an IDEX Duplication mode, and
* then print a standard GCode file that contains a single print that does a G28 and has no other
* then print a standard G-Code file that contains a single print that does a G28 and has no other
* IDEX specific commands in it.
*/
#if ENABLED(DUAL_X_CARRIAGE)
+10 -11
View File
@@ -84,7 +84,7 @@ void ac_setup(const bool reset_bed) {
#endif
}
void ac_cleanup(TERN_(HAS_MULTI_HOTEND, const uint8_t old_tool_index)) {
void ac_cleanup() {
TERN_(DELTA_HOME_TO_SAFE_ZONE, do_blocking_move_to_z(delta_clip_start_height));
TERN_(HAS_BED_PROBE, probe.stow());
restore_feedrate_and_scaling();
@@ -97,7 +97,7 @@ void print_signed_float(FSTR_P const prefix, const_float_t f) {
}
/**
* - Print the delta settings
* - Print the delta settings
*/
static void print_calibration_settings(const bool end_stops, const bool tower_angles) {
SERIAL_ECHOPGM(".Height:", delta_height);
@@ -123,7 +123,7 @@ static void print_calibration_settings(const bool end_stops, const bool tower_an
}
/**
* - Print the probe results
* - Print the probe results
*/
static void print_calibration_results(const float z_pt[NPP + 1], const bool tower_points, const bool opposite_points) {
SERIAL_ECHOPGM(". ");
@@ -147,7 +147,7 @@ static void print_calibration_results(const float z_pt[NPP + 1], const bool towe
}
/**
* - Calculate the standard deviation from the zero plane
* - Calculate the standard deviation from the zero plane
*/
static float std_dev_points(float z_pt[NPP + 1], const bool _0p_cal, const bool _1p_cal, const bool _4p_cal, const bool _4p_opp) {
if (!_0p_cal) {
@@ -165,7 +165,7 @@ static float std_dev_points(float z_pt[NPP + 1], const bool _0p_cal, const bool
}
/**
* - Probe a point
* - Probe a point
*/
static float calibration_probe(const xy_pos_t &xy, const bool stow, const bool probe_at_offset) {
#if HAS_BED_PROBE
@@ -177,7 +177,7 @@ static float calibration_probe(const xy_pos_t &xy, const bool stow, const bool p
}
/**
* - Probe a grid
* - Probe a grid
*/
static bool probe_calibration_points(float z_pt[NPP + 1], const int8_t probe_points, const float dcr, const bool towers_set, const bool stow_after_each, const bool probe_at_offset) {
const bool _0p_calibration = probe_points == 0,
@@ -459,9 +459,8 @@ void GcodeSuite::G33() {
SERIAL_ECHOLNPGM("G33 Auto Calibrate");
// Report settings
PGM_P const checkingac = PSTR("Checking... AC");
SERIAL_ECHOPGM_P(checkingac);
SERIAL_ECHOPGM(" at radius:", dcr);
FSTR_P const checkingac = F("Checking... AC");
SERIAL_ECHO(checkingac, F(" at radius:"), dcr);
if (verbose_level == 0) SERIAL_ECHOPGM(" (DRY-RUN)");
SERIAL_EOL();
ui.set_status(checkingac);
@@ -501,7 +500,7 @@ void GcodeSuite::G33() {
zero_std_dev_old = zero_std_dev;
if (!probe_calibration_points(z_at_pt, probe_points, dcr, towers_set, stow_after_each, probe_at_offset)) {
SERIAL_ECHOLNPGM("Correct delta settings with M665 and M666");
return ac_cleanup(TERN_(HAS_MULTI_HOTEND, old_tool_index));
return ac_cleanup();
}
zero_std_dev = std_dev_points(z_at_pt, _0p_calibration, _1p_calibration, _4p_calibration, _4p_opposite_points);
@@ -678,7 +677,7 @@ void GcodeSuite::G33() {
}
while (((zero_std_dev < test_precision && iterations < 31) || iterations <= force_iterations) && zero_std_dev > calibration_precision);
ac_cleanup(TERN_(HAS_MULTI_HOTEND, old_tool_index));
ac_cleanup();
TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(M_IDLE));
#if HAS_DELTA_SENSORLESS_PROBING
+2 -2
View File
@@ -64,10 +64,10 @@
if (parser.seenval('L')) {
// Set volumetric limit (in mm^3/sec)
const float lval = parser.value_float();
if (WITHIN(lval, 0, 20))
if (WITHIN(lval, 0, VOLUMETRIC_EXTRUDER_LIMIT_MAX))
planner.set_volumetric_extruder_limit(target_extruder, lval);
else
SERIAL_ECHOLNPGM("?L value out of range (0-20).");
SERIAL_ECHOLNPGM("?L value out of range (0-" STRINGIFY(VOLUMETRIC_EXTRUDER_LIMIT_MAX) ").");
}
#endif
+3
View File
@@ -66,6 +66,9 @@ void GcodeSuite::M281_report(const bool forReplay/*=true*/) {
#endif
#elif ENABLED(SWITCHING_NOZZLE)
case SWITCHING_NOZZLE_SERVO_NR:
#if ENABLED(SWITCHING_NOZZLE_TWO_SERVOS)
case SWITCHING_NOZZLE_E1_SERVO_NR:
#endif
#elif ENABLED(BLTOUCH) || (HAS_Z_SERVO_PROBE && defined(Z_SERVO_ANGLES))
case Z_PROBE_SERVO_NR:
#endif
+12 -12
View File
@@ -32,21 +32,18 @@
* Laser:
* M3 - Laser ON/Power (Ramped power)
* M4 - Laser ON/Power (Ramped power)
* M5 - Set power output to 0 (leaving inline mode unchanged).
*
* M3I - Enable continuous inline power to be processed by the planner, with power
* calculated and set in the planner blocks, processed inline during stepping.
* Within inline mode M3 S-Values will set the power for the next moves e.g. G1 X10 Y10 powers on with the last S-Value.
* In inline mode M3 S-Values will set the power for the next moves.
* (e.g., G1 X10 Y10 powers on with the last S-Value.)
* M3I must be set before using planner-synced M3 inline S-Values (LASER_POWER_SYNC).
*
* M4I - Set dynamic mode which calculates laser power OCR based on the current feedrate.
*
* M5I - Clear inline mode and set power to 0.
*
* Spindle:
* M3 - Spindle ON (Clockwise)
* M4 - Spindle ON (Counter-clockwise)
* M5 - Spindle OFF
*
* Parameters:
* S<power> - Set power. S0 will turn the spindle/laser off.
@@ -92,19 +89,15 @@ void GcodeSuite::M3_M4(const bool is_M4) {
#endif
auto get_s_power = [] {
float u;
if (parser.seenval('S')) {
const float v = parser.value_float();
u = TERN(LASER_POWER_TRAP, v, cutter.power_to_range(v));
cutter.menuPower = cutter.unitPower = TERN(LASER_POWER_TRAP, v, cutter.power_to_range(v));
}
else if (cutter.cutter_mode == CUTTER_MODE_STANDARD)
u = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP);
cutter.menuPower = cutter.unitPower = u;
cutter.menuPower = cutter.unitPower = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP);
// PWM not implied, power converted to OCR from unit definition and on/off if not PWM.
cutter.power = TERN(SPINDLE_LASER_USE_PWM, cutter.upower_to_ocr(u), u > 0 ? 255 : 0);
return u;
cutter.power = TERN(SPINDLE_LASER_USE_PWM, cutter.upower_to_ocr(cutter.unitPower), cutter.unitPower > 0 ? 255 : 0);
};
if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS || cutter.cutter_mode == CUTTER_MODE_DYNAMIC) { // Laser power in inline mode
@@ -138,6 +131,13 @@ void GcodeSuite::M3_M4(const bool is_M4) {
/**
* M5 - Cutter OFF (when moves are complete)
*
* Laser:
* M5 - Set power output to 0 (leaving inline mode unchanged).
* M5I - Clear inline mode and set power to 0.
*
* Spindle:
* M5 - Spindle OFF
*/
void GcodeSuite::M5() {
planner.synchronize();
+1 -1
View File
@@ -44,7 +44,7 @@ void protected_pin_err() {
}
/**
* M42: Change pin status via GCode
* M42: Change pin status via G-Code
*
* P<pin> Pin number (LED if omitted)
* For LPC1768 specify pin P1_02 as M42 P102,
+10 -2
View File
@@ -41,13 +41,21 @@
* S1 Don't move the tool in XY after change
*
* For PRUSA_MMU2(S) and EXTENDABLE_EMU_MMU2(S)
* T[n] Gcode to extrude at least 38.10 mm at feedrate 19.02 mm/s must follow immediately to load to extruder wheels.
* T? Gcode to extrude shouldn't have to follow. Load to extruder wheels is done automatically.
* T[n] G-code to extrude at least 38.10 mm at feedrate 19.02 mm/s must follow immediately to load to extruder wheels.
* T? G-code to extrude shouldn't have to follow. Load to extruder wheels is done automatically.
* Tx Same as T?, but nozzle doesn't have to be preheated. Tc requires a preheated nozzle to finish filament load.
* Tc Load to nozzle after filament was prepared by Tc and nozzle is already heated.
*/
void GcodeSuite::T(const int8_t tool_index) {
#if HAS_MULTI_EXTRUDER
// For 'T' with no parameter report the current tool.
if (parser.string_arg && *parser.string_arg == '*') {
SERIAL_ECHOLNPGM(STR_ACTIVE_EXTRUDER, active_extruder);
return;
}
#endif
DEBUG_SECTION(log_T, "T", DEBUGGING(LEVELING));
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("...(", tool_index, ")");
+33 -33
View File
@@ -29,13 +29,13 @@
void say_shaping() {
// FT Enabled
SERIAL_ECHO_TERNARY(fxdTiCtrl.cfg.mode, "Fixed-Time Motion ", "en", "dis", "abled");
SERIAL_ECHO_TERNARY(ftMotion.cfg.mode, "Fixed-Time Motion ", "en", "dis", "abled");
// FT Shaping
#if HAS_X_AXIS
if (fxdTiCtrl.cfg.mode > ftMotionMode_ENABLED) {
if (ftMotion.cfg.mode > ftMotionMode_ENABLED) {
SERIAL_ECHOPGM(" with ");
switch (fxdTiCtrl.cfg.mode) {
switch (ftMotion.cfg.mode) {
default: break;
case ftMotionMode_ZV: SERIAL_ECHOPGM("ZV"); break;
case ftMotionMode_ZVD: SERIAL_ECHOPGM("ZVD"); break;
@@ -51,15 +51,15 @@ void say_shaping() {
#endif
SERIAL_ECHOLNPGM(".");
const bool z_based = TERN0(HAS_DYNAMIC_FREQ_MM, fxdTiCtrl.cfg.dynFreqMode == dynFreqMode_Z_BASED),
g_based = TERN0(HAS_DYNAMIC_FREQ_G, fxdTiCtrl.cfg.dynFreqMode == dynFreqMode_MASS_BASED),
const bool z_based = TERN0(HAS_DYNAMIC_FREQ_MM, ftMotion.cfg.dynFreqMode == dynFreqMode_Z_BASED),
g_based = TERN0(HAS_DYNAMIC_FREQ_G, ftMotion.cfg.dynFreqMode == dynFreqMode_MASS_BASED),
dynamic = z_based || g_based;
// FT Dynamic Frequency Mode
if (fxdTiCtrl.cfg.modeHasShaper()) {
if (ftMotion.cfg.modeHasShaper()) {
#if HAS_DYNAMIC_FREQ
SERIAL_ECHOPGM("Dynamic Frequency Mode ");
switch (fxdTiCtrl.cfg.dynFreqMode) {
switch (ftMotion.cfg.dynFreqMode) {
default:
case dynFreqMode_DISABLED: SERIAL_ECHOPGM("disabled"); break;
#if HAS_DYNAMIC_FREQ_MM
@@ -74,32 +74,32 @@ void say_shaping() {
#if HAS_X_AXIS
SERIAL_ECHO_TERNARY(dynamic, "X/A ", "base dynamic", "static", " compensator frequency: ");
SERIAL_ECHO(p_float_t(fxdTiCtrl.cfg.baseFreq[X_AXIS], 2), F("Hz"));
SERIAL_ECHO(p_float_t(ftMotion.cfg.baseFreq[X_AXIS], 2), F("Hz"));
#if HAS_DYNAMIC_FREQ
if (dynamic) SERIAL_ECHO(" scaling: ", p_float_t(fxdTiCtrl.cfg.dynFreqK[X_AXIS], 8), F("Hz/"), z_based ? F("mm") : F("g"));
if (dynamic) SERIAL_ECHO(" scaling: ", p_float_t(ftMotion.cfg.dynFreqK[X_AXIS], 8), F("Hz/"), z_based ? F("mm") : F("g"));
#endif
SERIAL_EOL();
#endif
#if HAS_Y_AXIS
SERIAL_ECHO_TERNARY(dynamic, "Y/B ", "base dynamic", "static", " compensator frequency: ");
SERIAL_ECHO(p_float_t(fxdTiCtrl.cfg.baseFreq[Y_AXIS], 2), F(" Hz"));
SERIAL_ECHO(p_float_t(ftMotion.cfg.baseFreq[Y_AXIS], 2), F(" Hz"));
#if HAS_DYNAMIC_FREQ
if (dynamic) SERIAL_ECHO(F(" scaling: "), p_float_t(fxdTiCtrl.cfg.dynFreqK[Y_AXIS], 8), F("Hz/"), z_based ? F("mm") : F("g"));
if (dynamic) SERIAL_ECHO(F(" scaling: "), p_float_t(ftMotion.cfg.dynFreqK[Y_AXIS], 8), F("Hz/"), z_based ? F("mm") : F("g"));
#endif
SERIAL_EOL();
#endif
}
#if HAS_EXTRUDERS
SERIAL_ECHO_TERNARY(fxdTiCtrl.cfg.linearAdvEna, "Linear Advance ", "en", "dis", "abled");
SERIAL_ECHOLN(F(". Gain: "), p_float_t(fxdTiCtrl.cfg.linearAdvK, 5));
SERIAL_ECHO_TERNARY(ftMotion.cfg.linearAdvEna, "Linear Advance ", "en", "dis", "abled");
SERIAL_ECHOLN(F(". Gain: "), p_float_t(ftMotion.cfg.linearAdvK, 5));
#endif
}
void GcodeSuite::M493_report(const bool forReplay/*=true*/) {
report_heading_etc(forReplay, F(STR_FT_MOTION));
const ft_config_t &c = fxdTiCtrl.cfg;
const ft_config_t &c = ftMotion.cfg;
SERIAL_ECHOPGM(" M493 S", c.mode);
#if HAS_X_AXIS
SERIAL_ECHOPGM(" A", c.baseFreq[X_AXIS]);
@@ -160,7 +160,7 @@ void GcodeSuite::M493() {
// Parse 'S' mode parameter.
if (parser.seenval('S')) {
const ftMotionMode_t oldmm = fxdTiCtrl.cfg.mode,
const ftMotionMode_t oldmm = ftMotion.cfg.mode,
newmm = (ftMotionMode_t)parser.value_byte();
if (newmm != oldmm) {
@@ -179,7 +179,7 @@ void GcodeSuite::M493() {
#endif
case ftMotionMode_DISABLED:
case ftMotionMode_ENABLED:
fxdTiCtrl.cfg.mode = newmm;
ftMotion.cfg.mode = newmm;
flag.report_h = true;
if (oldmm == ftMotionMode_DISABLED) flag.reset_ft = true;
break;
@@ -192,7 +192,7 @@ void GcodeSuite::M493() {
// Pressure control (linear advance) parameter.
if (parser.seen('P')) {
const bool val = parser.value_bool();
fxdTiCtrl.cfg.linearAdvEna = val;
ftMotion.cfg.linearAdvEna = val;
SERIAL_ECHO_TERNARY(val, "Linear Advance ", "en", "dis", "abled.\n");
}
@@ -200,7 +200,7 @@ void GcodeSuite::M493() {
if (parser.seenval('K')) {
const float val = parser.value_float();
if (val >= 0.0f) {
fxdTiCtrl.cfg.linearAdvK = val;
ftMotion.cfg.linearAdvK = val;
flag.report_h = true;
}
else // Value out of range.
@@ -213,22 +213,22 @@ void GcodeSuite::M493() {
// Dynamic frequency mode parameter.
if (parser.seenval('D')) {
if (fxdTiCtrl.cfg.modeHasShaper()) {
if (ftMotion.cfg.modeHasShaper()) {
const dynFreqMode_t val = dynFreqMode_t(parser.value_byte());
switch (val) {
case dynFreqMode_DISABLED:
fxdTiCtrl.cfg.dynFreqMode = val;
ftMotion.cfg.dynFreqMode = val;
flag.report_h = true;
break;
#if HAS_DYNAMIC_FREQ_MM
case dynFreqMode_Z_BASED:
fxdTiCtrl.cfg.dynFreqMode = val;
ftMotion.cfg.dynFreqMode = val;
flag.report_h = true;
break;
#endif
#if HAS_DYNAMIC_FREQ_G
case dynFreqMode_MASS_BASED:
fxdTiCtrl.cfg.dynFreqMode = val;
ftMotion.cfg.dynFreqMode = val;
flag.report_h = true;
break;
#endif
@@ -243,8 +243,8 @@ void GcodeSuite::M493() {
}
const bool modeUsesDynFreq = (
TERN0(HAS_DYNAMIC_FREQ_MM, fxdTiCtrl.cfg.dynFreqMode == dynFreqMode_Z_BASED)
|| TERN0(HAS_DYNAMIC_FREQ_G, fxdTiCtrl.cfg.dynFreqMode == dynFreqMode_MASS_BASED)
TERN0(HAS_DYNAMIC_FREQ_MM, ftMotion.cfg.dynFreqMode == dynFreqMode_Z_BASED)
|| TERN0(HAS_DYNAMIC_FREQ_G, ftMotion.cfg.dynFreqMode == dynFreqMode_MASS_BASED)
);
#endif // HAS_DYNAMIC_FREQ
@@ -253,11 +253,11 @@ void GcodeSuite::M493() {
// Parse frequency parameter (X axis).
if (parser.seenval('A')) {
if (fxdTiCtrl.cfg.modeHasShaper()) {
if (ftMotion.cfg.modeHasShaper()) {
const float val = parser.value_float();
// TODO: Frequency minimum is dependent on the shaper used; the above check isn't always correct.
if (WITHIN(val, FTM_MIN_SHAPE_FREQ, (FTM_FS) / 2)) {
fxdTiCtrl.cfg.baseFreq[X_AXIS] = val;
ftMotion.cfg.baseFreq[X_AXIS] = val;
flag.update_n = flag.reset_ft = flag.report_h = true;
}
else // Frequency out of range.
@@ -271,7 +271,7 @@ void GcodeSuite::M493() {
// Parse frequency scaling parameter (X axis).
if (parser.seenval('F')) {
if (modeUsesDynFreq) {
fxdTiCtrl.cfg.dynFreqK[X_AXIS] = parser.value_float();
ftMotion.cfg.dynFreqK[X_AXIS] = parser.value_float();
flag.report_h = true;
}
else
@@ -285,10 +285,10 @@ void GcodeSuite::M493() {
// Parse frequency parameter (Y axis).
if (parser.seenval('B')) {
if (fxdTiCtrl.cfg.modeHasShaper()) {
if (ftMotion.cfg.modeHasShaper()) {
const float val = parser.value_float();
if (WITHIN(val, FTM_MIN_SHAPE_FREQ, (FTM_FS) / 2)) {
fxdTiCtrl.cfg.baseFreq[Y_AXIS] = val;
ftMotion.cfg.baseFreq[Y_AXIS] = val;
flag.update_n = flag.reset_ft = flag.report_h = true;
}
else // Frequency out of range.
@@ -302,7 +302,7 @@ void GcodeSuite::M493() {
// Parse frequency scaling parameter (Y axis).
if (parser.seenval('H')) {
if (modeUsesDynFreq) {
fxdTiCtrl.cfg.dynFreqK[Y_AXIS] = parser.value_float();
ftMotion.cfg.dynFreqK[Y_AXIS] = parser.value_float();
flag.report_h = true;
}
else
@@ -313,10 +313,10 @@ void GcodeSuite::M493() {
#endif // HAS_Y_AXIS
#if HAS_X_AXIS
if (flag.update_n) fxdTiCtrl.refreshShapingN();
if (flag.update_a) fxdTiCtrl.updateShapingA();
if (flag.update_n) ftMotion.refreshShapingN();
if (flag.update_a) ftMotion.updateShapingA();
#endif
if (flag.reset_ft) fxdTiCtrl.reset();
if (flag.reset_ft) ftMotion.reset();
if (flag.report_h) say_shaping();
}
@@ -76,7 +76,7 @@ void GcodeSuite::M164() {
* I[factor] Mix factor for extruder stepper 6
*/
void GcodeSuite::M165() {
// Get mixing parameters from the GCode
// Get mixing parameters from the G-Code
// The total "must" be 1.0 (but it will be normalized)
// If no mix factors are given, the old mix is preserved
const char mixing_codes[] = { LIST_N(MIXING_STEPPERS, 'A', 'B', 'C', 'D', 'H', 'I') };
@@ -0,0 +1,51 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfig.h"
#if ENABLED(NONLINEAR_EXTRUSION)
#include "../../gcode.h"
#include "../../../module/stepper.h"
void GcodeSuite::M592_report(const bool forReplay/*=true*/) {
report_heading(forReplay, F(STR_NONLINEAR_EXTRUSION));
SERIAL_ECHOLNPGM(" M593 A", stepper.ne.A, " B", stepper.ne.B, " C", stepper.ne.C);
}
/**
* M592: Get or set nonlinear extrusion parameters
* A<factor> Linear coefficient (default 0.0)
* B<factor> Quadratic coefficient (default 0.0)
* C<factor> Constant coefficient (default 1.0)
*
* Adjusts the amount of extrusion based on the instantaneous velocity of extrusion, as a multiplier.
* The amount of extrusion is multiplied by max(C, C + A*v + B*v^2) where v is extruder velocity in mm/s.
* Only adjusts forward extrusions, since those are the ones affected by backpressure.
*/
void GcodeSuite::M592() {
if (parser.seenval('A')) stepper.ne.A = parser.value_float();
if (parser.seenval('B')) stepper.ne.B = parser.value_float();
if (parser.seenval('C')) stepper.ne.C = parser.value_float();
}
#endif // NONLINEAR_EXTRUSION
+7 -3
View File
@@ -153,7 +153,7 @@ int8_t GcodeSuite::get_target_e_stepper_from_command(const int8_t dval/*=-1*/) {
}
/**
* Set XYZ...E destination and feedrate from the current GCode command
* Set XYZ...E destination and feedrate from the current G-Code command
*
* - Set destination from included axis codes
* - Set to current for missing axis codes
@@ -459,7 +459,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
#endif
#if ENABLED(DEBUG_GCODE_PARSER)
case 800: parser.debug(); break; // G800: GCode Parser Test for G
case 800: parser.debug(); break; // G800: G-Code Parser Test for G
#endif
default: parser.unknown_command_warning(); break;
@@ -935,6 +935,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 575: M575(); break; // M575: Set serial baudrate
#endif
#if ENABLED(NONLINEAR_EXTRUSION)
case 592: M592(); break; // M592: Nonlinear Extrusion control
#endif
#if HAS_ZV_SHAPING
case 593: M593(); break; // M593: Input Shaping control
#endif
@@ -1031,7 +1035,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
#endif
#if ENABLED(DEBUG_GCODE_PARSER)
case 800: parser.debug(); break; // M800: GCode Parser Test for M
case 800: parser.debug(); break; // M800: G-Code Parser Test for M
#endif
#if ENABLED(GCODE_REPEAT_MARKERS)
+7 -1
View File
@@ -259,6 +259,7 @@
* M554 - Get or set IP gateway. (Requires enabled Ethernet port)
* M569 - Enable stealthChop on an axis. (Requires at least one _DRIVER_TYPE to be TMC2130/2160/2208/2209/5130/5160)
* M575 - Change the serial baud rate. (Requires BAUD_RATE_GCODE)
* M592 - Get or set nonlinear extrusion parameters. (Requires NONLINEAR_EXTRUSION)
* M593 - Get or set input shaping parameters. (Requires INPUT_SHAPING_[XY])
* M600 - Pause for filament change: "M600 X<pos> Y<pos> Z<raise> E<first_retract> L<later_retract>". (Requires ADVANCED_PAUSE_FEATURE)
* M603 - Configure filament change: "M603 T<tool> U<unload_length> L<load_length>". (Requires ADVANCED_PAUSE_FEATURE)
@@ -461,7 +462,7 @@ public:
*/
enum MarlinBusyState : char {
NOT_BUSY, // Not in a handler
IN_HANDLER, // Processing a GCode
IN_HANDLER, // Processing a G-Code
IN_PROCESS, // Known to be blocking command input (as in G29)
PAUSED_FOR_USER, // Blocking pending any input
PAUSED_FOR_INPUT // Blocking pending text input (concept)
@@ -1106,6 +1107,11 @@ private:
static void M575();
#endif
#if ENABLED(NONLINEAR_EXTRUSION)
static void M592();
static void M592_report(const bool forReplay=true);
#endif
#if HAS_ZV_SHAPING
static void M593();
static void M593_report(const bool forReplay=true);
+11
View File
@@ -34,8 +34,19 @@
*
* S<frequency> - (Hz) The frequency of the tone. 0 for silence.
* P<duration> - (ms) The duration of the tone.
*
* With SOUND_MENU_ITEM:
* E<0|1> - Mute or enable sound
*/
void GcodeSuite::M300() {
#if ENABLED(SOUND_MENU_ITEM)
if (parser.seen('E')) {
ui.sound_on = parser.value_bool();
return;
}
#endif
const uint16_t frequency = parser.ushortval('S', 260);
uint16_t duration = parser.ushortval('P', 1000);
+64 -66
View File
@@ -82,14 +82,17 @@ void plan_arc(
rt_X = cart[axis_p] - center_P,
rt_Y = cart[axis_q] - center_Q;
ARC_LIJKUVW_CODE(
const float start_L = current_position[axis_l],
const float start_I = current_position.i,
const float start_J = current_position.j,
const float start_K = current_position.k,
const float start_U = current_position.u,
const float start_V = current_position.v,
const float start_W = current_position.w
// Starting position of the move for all non-arc axes
// i.e., only one of X, Y, or Z, plus the rest.
ARC_LIJKUVWE_CODE(
float start_L = current_position[axis_l],
float start_I = current_position.i,
float start_J = current_position.j,
float start_K = current_position.k,
float start_U = current_position.u,
float start_V = current_position.v,
float start_W = current_position.w,
float start_E = current_position.e
);
// Angle of rotation between position and target from the circle center.
@@ -125,6 +128,7 @@ void plan_arc(
min_segments = CEIL((MIN_CIRCLE_SEGMENTS) * portion_of_circle); // Minimum segments for the arc
}
// Total travel on all the non-arc axes
ARC_LIJKUVWE_CODE(
float travel_L = cart[axis_l] - start_L,
float travel_I = cart.i - start_I,
@@ -133,7 +137,7 @@ void plan_arc(
float travel_U = cart.u - start_U,
float travel_V = cart.v - start_V,
float travel_W = cart.w - start_W,
float travel_E = cart.e - current_position.e
float travel_E = cart.e - start_E
);
// If "P" specified circles, call plan_arc recursively then continue with the rest of the arc
@@ -166,15 +170,29 @@ void plan_arc(
);
plan_arc(temp_position, offset, clockwise, 0); // Plan a single whole circle
}
// Get starting coordinates for the remainder from the current position
ARC_LIJKUVWE_CODE(
travel_L = cart[axis_l] - current_position[axis_l], // Linear X, Y, or Z
travel_I = cart.i - current_position.i, // The rest are also non-arc
travel_J = cart.j - current_position.j,
travel_K = cart.k - current_position.k,
travel_U = cart.u - current_position.u,
travel_V = cart.v - current_position.v,
travel_W = cart.w - current_position.w,
travel_E = cart.e - current_position.e
start_L = current_position[axis_l],
start_I = current_position.i,
start_J = current_position.j,
start_K = current_position.k,
start_U = current_position.u,
start_V = current_position.v,
start_W = current_position.w,
start_E = current_position.e
);
// Update travel distance for the remainder
ARC_LIJKUVWE_CODE(
travel_L = cart[axis_l] - start_L, // Linear X, Y, or Z
travel_I = cart.i - start_I, // The rest are also non-arc
travel_J = cart.j - start_J,
travel_K = cart.k - start_K,
travel_U = cart.u - start_U,
travel_V = cart.v - start_V,
travel_W = cart.w - start_W,
travel_E = cart.e - start_E
);
}
@@ -256,7 +274,7 @@ void plan_arc(
xyze_pos_t raw;
// do not calculate rotation parameters for trivial single-segment arcs
// Don't calculate rotation parameters for trivial single-segment arcs
if (segments > 1) {
// Vector rotation matrix values
const float theta_per_segment = angular_travel / segments,
@@ -264,30 +282,27 @@ void plan_arc(
sin_T = theta_per_segment - sq_theta_per_segment * theta_per_segment / 6,
cos_T = 1 - 0.5f * sq_theta_per_segment; // Small angle approximation
#if DISABLED(AUTO_BED_LEVELING_UBL)
ARC_LIJKUVW_CODE(
const float per_segment_L = travel_L / segments,
const float per_segment_I = travel_I / segments,
const float per_segment_J = travel_J / segments,
const float per_segment_K = travel_K / segments,
const float per_segment_U = travel_U / segments,
const float per_segment_V = travel_V / segments,
const float per_segment_W = travel_W / segments
);
#endif
CODE_ITEM_E(const float extruder_per_segment = travel_E / segments);
ARC_LIJKUVWE_CODE(
const float per_segment_L = travel_L / segments,
const float per_segment_I = travel_I / segments,
const float per_segment_J = travel_J / segments,
const float per_segment_K = travel_K / segments,
const float per_segment_U = travel_U / segments,
const float per_segment_V = travel_V / segments,
const float per_segment_W = travel_W / segments,
const float per_segment_E = travel_E / segments
);
// Initialize all linear axes and E
ARC_LIJKUVWE_CODE(
raw[axis_l] = current_position[axis_l],
raw.i = current_position.i,
raw.j = current_position.j,
raw.k = current_position.k,
raw.u = current_position.u,
raw.v = current_position.v,
raw.w = current_position.w,
raw.e = current_position.e
raw[axis_l] = start_L,
raw.i = start_I,
raw.j = start_J,
raw.k = start_K,
raw.u = start_U,
raw.v = start_V,
raw.w = start_W,
raw.e = start_E
);
millis_t next_idle_ms = millis() + 200UL;
@@ -305,7 +320,6 @@ void plan_arc(
const float limiting_accel = _MIN(planner.settings.max_acceleration_mm_per_s2[axis_p], planner.settings.max_acceleration_mm_per_s2[axis_q]),
limiting_speed = _MIN(planner.settings.max_feedrate_mm_s[axis_p], planner.settings.max_feedrate_mm_s[axis_q]),
limiting_speed_sqr = _MIN(sq(limiting_speed), limiting_accel * radius, sq(scaled_fr_mm_s));
float arc_mm_remaining = flat_mm;
for (uint16_t i = 1; i < segments; i++) { // Iterate (segments-1) times
@@ -343,16 +357,14 @@ void plan_arc(
raw[axis_p] = center_P + rvec.a;
raw[axis_q] = center_Q + rvec.b;
ARC_LIJKUVWE_CODE(
#if ENABLED(AUTO_BED_LEVELING_UBL)
raw[axis_l] = start_L,
raw.i = start_I, raw.j = start_J, raw.k = start_K,
raw.u = start_U, raw.v = start_V, raw.w = start_V
#else
raw[axis_l] += per_segment_L,
raw.i += per_segment_I, raw.j += per_segment_J, raw.k += per_segment_K,
raw.u += per_segment_U, raw.v += per_segment_V, raw.w += per_segment_W
#endif
, raw.e += extruder_per_segment
raw[axis_l] = start_L + per_segment_L * i,
raw.i = start_I + per_segment_I * i,
raw.j = start_J + per_segment_J * i,
raw.k = start_K + per_segment_K * i,
raw.u = start_U + per_segment_U * i,
raw.v = start_V + per_segment_V * i,
raw.w = start_W + per_segment_W * i,
raw.e = start_E + per_segment_E * i
);
apply_motion_limits(raw);
@@ -362,7 +374,7 @@ void plan_arc(
#endif
// calculate safe speed for stopping by the end of the arc
arc_mm_remaining -= segment_mm;
const float arc_mm_remaining = flat_mm - segment_mm * i;
hints.safe_exit_speed_sqr = _MIN(limiting_speed_sqr, 2 * limiting_accel * arc_mm_remaining);
if (!planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, hints))
@@ -374,13 +386,6 @@ void plan_arc(
// Ensure last segment arrives at target location.
raw = cart;
#if ENABLED(AUTO_BED_LEVELING_UBL)
ARC_LIJKUVW_CODE(
raw[axis_l] = start_L,
raw.i = start_I, raw.j = start_J, raw.k = start_K,
raw.u = start_U, raw.v = start_V, raw.w = start_W
);
#endif
apply_motion_limits(raw);
@@ -392,14 +397,7 @@ void plan_arc(
hints.safe_exit_speed_sqr = 0.0f;
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, hints);
#if ENABLED(AUTO_BED_LEVELING_UBL)
ARC_LIJKUVW_CODE(
raw[axis_l] = start_L,
raw.i = start_I, raw.j = start_J, raw.k = start_K,
raw.u = start_U, raw.v = start_V, raw.w = start_W
);
#endif
current_position = raw;
current_position = cart;
} // plan_arc
+11 -5
View File
@@ -21,7 +21,7 @@
*/
/**
* parser.cpp - Parser for a GCode line, providing a parameter interface.
* parser.cpp - Parser for a G-Code line, providing a parameter interface.
*/
#include "parser.h"
@@ -66,7 +66,7 @@ uint16_t GCodeParser::codenum;
char *GCodeParser::command_args; // start of parameters
#endif
// Create a global instance of the GCode parser singleton
// Create a global instance of the G-Code parser singleton
GCodeParser parser;
/**
@@ -108,7 +108,7 @@ void GCodeParser::reset() {
/**
* Populate the command line state (command_letter, codenum, subcode, and string_arg)
* by parsing a single line of GCode. 58 bytes of SRAM are used to speed up seen/value.
* by parsing a single line of G-Code. 58 bytes of SRAM are used to speed up seen/value.
*/
void GCodeParser::parse(char *p) {
@@ -189,7 +189,13 @@ void GCodeParser::parse(char *p) {
#endif
// Bail if there's no command code number
if (!TERN(SIGNED_CODENUM, NUMERIC_SIGNED(*p), NUMERIC(*p))) return;
if (!TERN(SIGNED_CODENUM, NUMERIC_SIGNED(*p), NUMERIC(*p))) {
if (TERN0(HAS_MULTI_EXTRUDER, letter == 'T')) {
p[0] = '*'; p[1] = '\0'; string_arg = p; // Convert 'T' alone into 'T*'
command_letter = letter;
}
return;
}
// Save the command letter at this point
// A '?' signifies an unknown command
@@ -311,7 +317,7 @@ void GCodeParser::parse(char *p) {
#endif
#if ENABLED(FASTER_GCODE_PARSER)
// Arguments MUST be uppercase for fast GCode parsing
// Arguments MUST be uppercase for fast G-Code parsing
#define PARAM_OK(P) WITHIN((P), 'A', 'Z')
#else
#define PARAM_OK(P) true
+5 -5
View File
@@ -22,8 +22,8 @@
#pragma once
/**
* parser.h - Parser for a GCode line, providing a parameter interface.
* Codes like M149 control the way the GCode parser behaves,
* parser.h - Parser for a G-Code line, providing a parameter interface.
* Codes like M149 control the way the G-Code parser behaves,
* so settings for these codes are located in this class.
*/
@@ -43,7 +43,7 @@
#endif
/**
* GCode parser
* G-Code parser
*
* - Parse a single G-code line for its letter, code, subcode, and parameters
* - FASTER_GCODE_PARSER:
@@ -68,7 +68,7 @@ private:
public:
// Global states for GCode-level units features
// Global states for G-Code-level units features
static bool volumetric_enabled;
@@ -233,7 +233,7 @@ public:
FORCE_INLINE static char* unescape_string(char* &src) { return src; }
#endif
// Populate all fields by parsing a single line of GCode
// Populate all fields by parsing a single line of G-Code
// This uses 54 bytes of SRAM to speed up seen/value
static void parse(char * p);
+3 -3
View File
@@ -82,9 +82,9 @@ void GcodeSuite::G30() {
if (!isnan(measured_z)) {
const xy_pos_t lpos = probepos.asLogical();
SString<30> msg(
F("Bed X:"), p_float_t(lpos.x, 1),
F( " Y:"), p_float_t(lpos.y, 1),
F( " Z:"), p_float_t(measured_z, 2)
F("Bed X:"), p_float_t(lpos.x, 2),
F( " Y:"), p_float_t(lpos.y, 2),
F( " Z:"), p_float_t(measured_z, 3)
);
msg.echoln();
#if ANY(DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI)
+6 -6
View File
@@ -44,10 +44,10 @@ void GcodeSuite::M851() {
if (parser.seenval('X')) {
const float x = parser.value_float();
#if HAS_PROBE_XY_OFFSET
if (WITHIN(x, -(X_BED_SIZE), X_BED_SIZE))
if (WITHIN(x, PROBE_OFFSET_XMIN, PROBE_OFFSET_XMAX))
offs.x = x;
else {
SERIAL_ECHOLNPGM("?X out of range (-", X_BED_SIZE, " to ", X_BED_SIZE, ")");
SERIAL_ECHOLNPGM("?X out of range (", PROBE_OFFSET_XMIN, " to ", PROBE_OFFSET_XMAX, ")");
ok = false;
}
#else
@@ -58,10 +58,10 @@ void GcodeSuite::M851() {
if (parser.seenval('Y')) {
const float y = parser.value_float();
#if HAS_PROBE_XY_OFFSET
if (WITHIN(y, -(Y_BED_SIZE), Y_BED_SIZE))
if (WITHIN(y, PROBE_OFFSET_YMIN, PROBE_OFFSET_YMAX))
offs.y = y;
else {
SERIAL_ECHOLNPGM("?Y out of range (-", Y_BED_SIZE, " to ", Y_BED_SIZE, ")");
SERIAL_ECHOLNPGM("?Y out of range (", PROBE_OFFSET_YMIN, " to ", PROBE_OFFSET_YMAX, ")");
ok = false;
}
#else
@@ -71,10 +71,10 @@ void GcodeSuite::M851() {
if (parser.seenval('Z')) {
const float z = parser.value_float();
if (WITHIN(z, Z_PROBE_OFFSET_RANGE_MIN, Z_PROBE_OFFSET_RANGE_MAX))
if (WITHIN(z, PROBE_OFFSET_ZMIN, PROBE_OFFSET_ZMAX))
offs.z = z;
else {
SERIAL_ECHOLNPGM("?Z out of range (", Z_PROBE_OFFSET_RANGE_MIN, " to ", Z_PROBE_OFFSET_RANGE_MAX, ")");
SERIAL_ECHOLNPGM("?Z out of range (", PROBE_OFFSET_ZMIN, " to ", PROBE_OFFSET_ZMAX, ")");
ok = false;
}
}
+2 -2
View File
@@ -35,7 +35,7 @@ public:
*/
struct SerialState {
/**
* GCode line number handling. Hosts may include line numbers when sending
* G-Code line number handling. Hosts may include line numbers when sending
* commands to Marlin, and lines will be checked for sequentiality.
* M110 N<int> sets the current line number.
*/
@@ -48,7 +48,7 @@ public:
static SerialState serial_state[NUM_SERIAL]; //!< Serial states for each serial port
/**
* GCode Command Queue
* G-Code Command Queue
* A simple (circular) ring buffer of BUFSIZE command strings.
*
* Commands are copied into this buffer by the command injectors
+11 -1
View File
@@ -29,9 +29,19 @@
/**
* M34: Set SD Card Sorting Options
*
* S - Default sorting (i.e., SDSORT_REVERSE)
* S-1 - Reverse alpha sorting
* S0 - FID Order (not always newest)
* S1 - Forward alpha sorting
* S2 - Alias for S-1 [deprecated]
*
* F-1 - Folders above files
* F0 - Sort According to 'S'
* F1 - Folders after files
*/
void GcodeSuite::M34() {
if (parser.seen('S')) card.setSortOn(parser.value_bool());
if (parser.seen('S')) card.setSortOn(SortFlag(parser.ushortval('S', TERN(SDSORT_REVERSE, AS_REV, AS_FWD))));
if (parser.seenval('F')) {
const int v = parser.value_long();
card.setSortFolders(v < 0 ? -1 : v > 0 ? 1 : 0);
+6
View File
@@ -661,6 +661,12 @@
#error "Z4_USE_ENDSTOP is obsolete. Instead set Z4_STOP_PIN directly. (e.g., 'Z4_USE_ENDSTOP _ZMAX_' becomes 'Z4_STOP_PIN Z_MAX_PIN')"
#elif defined(INTEGRATED_BABYSTEPPING)
#error "INTEGRATED_BABYSTEPPING is no longer needed and should be removed."
#elif defined(FOLDER_SORTING)
#error "FOLDER_SORTING is now SDSORT_FOLDERS."
#elif defined(BTT_MINI_12864_V1)
#error "BTT_MINI_12864_V1 is now BTT_MINI_12864."
#elif defined(Z_PROBE_OFFSET_RANGE_MIN) || defined(Z_PROBE_OFFSET_RANGE_MAX)
#error "Z_PROBE_OFFSET_RANGE_(MIN|MAX) is now PROBE_OFFSET_Z(MIN|MAX)."
#endif
// L64xx stepper drivers have been removed
+36 -5
View File
@@ -35,8 +35,8 @@
#define MKS_MINI_12864
#endif
// MKS_MINI_12864_V3 and BTT_MINI_12864_V1 are identical to FYSETC_MINI_12864_2_1
#if ANY(MKS_MINI_12864_V3, BTT_MINI_12864_V1)
// MKS_MINI_12864_V3 and BTT_MINI_12864 have identical pinouts to FYSETC_MINI_12864_2_1
#if ANY(MKS_MINI_12864_V3, BTT_MINI_12864)
#define FYSETC_MINI_12864_2_1
#endif
@@ -490,7 +490,7 @@
// Extensible UI serial touch screens. (See src/lcd/extui)
#if ANY(HAS_DGUS_LCD, MALYAN_LCD, ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON, NEXTION_TFT, TOUCH_UI_FTDI_EVE)
#define IS_EXTUI 1
#define IS_EXTUI 1 // Just for sanity check.
#define EXTENSIBLE_UI
#endif
@@ -1439,8 +1439,14 @@
#if ANY(Z_PROBE_ALLEN_KEY, MAG_MOUNTED_PROBE)
#define PROBE_TRIGGERED_WHEN_STOWED_TEST 1 // Extra test for Allen Key Probe
#endif
#ifndef Z_PROBE_LOW_POINT
#define Z_PROBE_LOW_POINT -5
#ifndef Z_CLEARANCE_BETWEEN_PROBES
#define Z_CLEARANCE_BETWEEN_PROBES 5
#endif
#ifndef Z_CLEARANCE_MULTI_PROBE
#define Z_CLEARANCE_MULTI_PROBE 5
#endif
#ifndef Z_PROBE_ERROR_TOLERANCE
#define Z_PROBE_ERROR_TOLERANCE Z_CLEARANCE_MULTI_PROBE
#endif
#if MULTIPLE_PROBING > 1
#if EXTRA_PROBING > 0
@@ -1454,6 +1460,31 @@
#undef Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN
#undef USE_PROBE_FOR_Z_HOMING
#undef Z_MIN_PROBE_REPEATABILITY_TEST
#undef HOMING_Z_WITH_PROBE
#undef Z_CLEARANCE_MULTI_PROBE
#undef Z_PROBE_ERROR_TOLERANCE
#undef MULTIPLE_PROBING
#undef EXTRA_PROBING
#undef Z_PROBE_OFFSET_RANGE_MIN
#undef Z_PROBE_OFFSET_RANGE_MAX
#undef PAUSE_BEFORE_DEPLOY_STOW
#undef PAUSE_PROBE_DEPLOY_WHEN_TRIGGERED
#undef PROBING_HEATERS_OFF
#undef WAIT_FOR_BED_HEATER
#undef WAIT_FOR_HOTEND
#undef PROBING_STEPPERS_OFF
#undef DELAY_BEFORE_PROBING
#undef PREHEAT_BEFORE_PROBING
#undef PROBING_NOZZLE_TEMP
#undef PROBING_BED_TEMP
#undef NOZZLE_TO_PROBE_OFFSET
#endif
#ifndef Z_CLEARANCE_DEPLOY_PROBE
#define Z_CLEARANCE_DEPLOY_PROBE 10
#endif
#ifndef Z_PROBE_LOW_POINT
#define Z_PROBE_LOW_POINT -5
#endif
#if ENABLED(BELTPRINTER) && !defined(HOME_Y_BEFORE_X)
+19 -1
View File
@@ -1230,7 +1230,7 @@
#define _HAS_1(N) (defined(MAIN_MENU_ITEM_##N##_DESC) && defined(MAIN_MENU_ITEM_##N##_GCODE))
#define HAS_USER_ITEM(V...) DO(HAS,||,V)
#else
#define HAS_USER_ITEM(N) 0
#define HAS_USER_ITEM(...) 0
#endif
/**
@@ -1275,6 +1275,24 @@
#undef TC_GCODE_USE_GLOBAL_Z
#endif
// TOOLCHANGE_MIGRATION_FEATURE - Clean up after sloppy auto config
#if DISABLED(TOOLCHANGE_MIGRATION_FEATURE)
#undef MIGRATION_ZRAISE
#undef MIGRATION_FS_EXTRA_PRIME
#undef MIGRATION_FS_WIPE_RETRACT
#undef MIGRATION_FS_FAN_SPEED
#undef MIGRATION_FS_FAN_TIME
#undef TOOLCHANGE_MIGRATION_DO_PARK
#endif
// TOOLCHANGE_PARK - Clean up after sloppy auto config
#if DISABLED(TOOLCHANGE_PARK)
#undef TOOLCHANGE_PARK_XY
#undef TOOLCHANGE_PARK_XY_FEEDRATE
#undef TOOLCHANGE_PARK_X_ONLY
#undef TOOLCHANGE_PARK_Y_ONLY
#undef TOOLCHANGE_MIGRATION_DO_PARK
#endif
// Multi-Stepping Limit
#ifndef MULTISTEPPING_LIMIT
#define MULTISTEPPING_LIMIT 128
+24 -12
View File
@@ -2623,6 +2623,9 @@
#if !HAS_AUTO_COOLER_FAN || AUTO_COOLER_IS_E
#undef AUTO_POWER_COOLER_FAN
#endif
#if !HAS_CUTTER
#undef AUTO_POWER_SPINDLE_LASER
#endif
/**
* Controller Fan Settings
@@ -2940,14 +2943,26 @@
* Bed Probe dependencies
*/
#if ANY(MESH_BED_LEVELING, HAS_BED_PROBE)
#ifndef Z_PROBE_OFFSET_RANGE_MIN
#define Z_PROBE_OFFSET_RANGE_MIN -20
#ifndef PROBE_OFFSET_ZMIN
#define PROBE_OFFSET_ZMIN -20
#endif
#ifndef Z_PROBE_OFFSET_RANGE_MAX
#define Z_PROBE_OFFSET_RANGE_MAX 20
#ifndef PROBE_OFFSET_ZMAX
#define PROBE_OFFSET_ZMAX 20
#endif
#endif
#if HAS_BED_PROBE
#ifndef PROBE_OFFSET_XMIN
#define PROBE_OFFSET_XMIN -50
#endif
#ifndef PROBE_OFFSET_XMAX
#define PROBE_OFFSET_XMAX 50
#endif
#ifndef PROBE_OFFSET_YMIN
#define PROBE_OFFSET_YMIN -50
#endif
#ifndef PROBE_OFFSET_YMAX
#define PROBE_OFFSET_YMAX 50
#endif
#if ALL(ENDSTOPPULLUPS, USE_Z_MIN_PROBE)
#define ENDSTOPPULLUP_ZMIN_PROBE
#endif
@@ -2957,9 +2972,6 @@
#ifndef NOZZLE_TO_PROBE_OFFSET
#define NOZZLE_TO_PROBE_OFFSET { 0, 0, 0 }
#endif
#else
#undef NOZZLE_TO_PROBE_OFFSET
#undef PROBING_STEPPERS_OFF
#endif
/**
@@ -3214,10 +3226,10 @@
#endif
#endif
#ifndef Z_CLEARANCE_BETWEEN_PROBES
#define Z_CLEARANCE_BETWEEN_PROBES Z_CLEARANCE_FOR_HOMING
#endif
#if PROBE_SELECTED
#ifndef Z_CLEARANCE_BETWEEN_PROBES
#define Z_CLEARANCE_BETWEEN_PROBES Z_CLEARANCE_FOR_HOMING
#endif
#if Z_CLEARANCE_BETWEEN_PROBES > Z_CLEARANCE_FOR_HOMING
#define Z_CLEARANCE_BETWEEN_MANUAL_PROBES Z_CLEARANCE_BETWEEN_PROBES
#else
@@ -3334,8 +3346,8 @@
#define SDSORT_CACHE_NAMES true
#define SDSORT_CACHE_LPC1768_WARNING 1
#endif
#ifndef FOLDER_SORTING
#define FOLDER_SORTING -1
#ifndef SDSORT_FOLDERS
#define SDSORT_FOLDERS -1
#endif
#ifndef SDSORT_GCODE
#define SDSORT_GCODE false
+105 -54
View File
@@ -404,6 +404,10 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
#error "CUSTOM_STATUS_SCREEN_IMAGE requires a 128x64 DOGM B/W Graphical LCD."
#endif
#if ALL(STATUS_HEAT_PERCENT, STATUS_HEAT_POWER)
#error "Only enable STATUS_HEAT_PERCENT or STATUS_HEAT_POWER, but not both."
#endif
/**
* LCD Lightweight Screen Style
*/
@@ -644,10 +648,12 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
*/
#if HAS_MULTI_EXTRUDER
#if HAS_EXTENDABLE_MMU
#define MAX_EXTRUDERS 15
#else
#define MAX_EXTRUDERS 8
#ifndef MAX_EXTRUDERS
#if HAS_EXTENDABLE_MMU
#define MAX_EXTRUDERS 15
#else
#define MAX_EXTRUDERS 8
#endif
#endif
static_assert(EXTRUDERS <= MAX_EXTRUDERS, "Marlin supports a maximum of " STRINGIFY(MAX_EXTRUDERS) " EXTRUDERS.");
#undef MAX_EXTRUDERS
@@ -852,6 +858,19 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
#endif
#endif
/**
* Nonlinear Extrusion requirements
*/
#if ENABLED(NONLINEAR_EXTRUSION)
#if DISABLED(ADAPTIVE_STEP_SMOOTHING)
#error "ADAPTIVE_STEP_SMOOTHING is required for NONLINEAR_EXTRUSION."
#elif HAS_MULTI_EXTRUDER
#error "NONLINEAR_EXTRUSION doesn't currently support multi-extruder setups."
#elif DISABLED(CPU_32_BIT)
#error "NONLINEAR_EXTRUSION requires a 32-bit CPU."
#endif
#endif
/**
* Special tool-changing options
*/
@@ -1399,20 +1418,15 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
#endif
/**
* Check for improper NOZZLE_TO_PROBE_OFFSET
* Check for improper PROBING_MARGIN
*/
constexpr xyz_pos_t sanity_nozzle_to_probe_offset = NOZZLE_TO_PROBE_OFFSET;
#if ENABLED(NOZZLE_AS_PROBE)
static_assert(sanity_nozzle_to_probe_offset.x == 0 && sanity_nozzle_to_probe_offset.y == 0,
"NOZZLE_AS_PROBE requires the XY offsets in NOZZLE_TO_PROBE_OFFSET to both be 0.");
#elif !IS_KINEMATIC
#if NONE(NOZZLE_AS_PROBE, IS_KINEMATIC)
static_assert(PROBING_MARGIN >= 0, "PROBING_MARGIN must be >= 0.");
static_assert(PROBING_MARGIN_BACK >= 0, "PROBING_MARGIN_BACK must be >= 0.");
static_assert(PROBING_MARGIN_FRONT >= 0, "PROBING_MARGIN_FRONT must be >= 0.");
static_assert(PROBING_MARGIN_LEFT >= 0, "PROBING_MARGIN_LEFT must be >= 0.");
static_assert(PROBING_MARGIN_RIGHT >= 0, "PROBING_MARGIN_RIGHT must be >= 0.");
#endif
#define _MARGIN(A) TERN(IS_KINEMATIC, PRINTABLE_RADIUS, ((A##_BED_SIZE) / 2))
static_assert(PROBING_MARGIN < _MARGIN(X), "PROBING_MARGIN is too large.");
static_assert(PROBING_MARGIN_BACK < _MARGIN(Y), "PROBING_MARGIN_BACK is too large.");
@@ -1421,6 +1435,34 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
static_assert(PROBING_MARGIN_RIGHT < _MARGIN(X), "PROBING_MARGIN_RIGHT is too large.");
#undef _MARGIN
/**
* Check for improper PROBE_OFFSET_[XYZ](MIN|MAX)
*/
#define PROBE_OFFSET_ASSERT(varname, x, min, max) static_assert(WITHIN(x, min, max), varname " must be within " STRINGIFY(min) " and " STRINGIFY(max))
#if HAS_PROBE_XY_OFFSET
PROBE_OFFSET_ASSERT("PROBE_OFFSET_XMIN", PROBE_OFFSET_XMIN, -(X_BED_SIZE), X_BED_SIZE);
PROBE_OFFSET_ASSERT("PROBE_OFFSET_XMAX", PROBE_OFFSET_XMAX, -(X_BED_SIZE), X_BED_SIZE);
PROBE_OFFSET_ASSERT("PROBE_OFFSET_YMIN", PROBE_OFFSET_YMIN, -(Y_BED_SIZE), Y_BED_SIZE);
PROBE_OFFSET_ASSERT("PROBE_OFFSET_YMAX", PROBE_OFFSET_YMAX, -(Y_BED_SIZE), Y_BED_SIZE);
#endif
PROBE_OFFSET_ASSERT("PROBE_OFFSET_ZMIN", PROBE_OFFSET_ZMIN, -20, 20);
PROBE_OFFSET_ASSERT("PROBE_OFFSET_ZMAX", PROBE_OFFSET_ZMAX, -20, 20);
/**
* Check for improper NOZZLE_AS_PROBE or NOZZLE_TO_PROBE_OFFSET
*/
constexpr xyz_pos_t sanity_nozzle_to_probe_offset = NOZZLE_TO_PROBE_OFFSET;
#if ENABLED(NOZZLE_AS_PROBE)
static_assert(sanity_nozzle_to_probe_offset.x == 0 && sanity_nozzle_to_probe_offset.y == 0,
"NOZZLE_AS_PROBE requires the XY offsets in NOZZLE_TO_PROBE_OFFSET to both be 0.");
#endif
#if HAS_PROBE_XY_OFFSET
PROBE_OFFSET_ASSERT("NOZZLE_TO_PROBE_OFFSET.x", sanity_nozzle_to_probe_offset.x, PROBE_OFFSET_XMIN, PROBE_OFFSET_XMAX);
PROBE_OFFSET_ASSERT("NOZZLE_TO_PROBE_OFFSET.y", sanity_nozzle_to_probe_offset.y, PROBE_OFFSET_YMIN, PROBE_OFFSET_YMAX);
#endif
PROBE_OFFSET_ASSERT("NOZZLE_TO_PROBE_OFFSET.z", sanity_nozzle_to_probe_offset.z, PROBE_OFFSET_ZMIN, PROBE_OFFSET_ZMAX);
#undef PROBE_OFFSET_ASSERT
/**
* Make sure Z raise values are set
*/
@@ -1498,46 +1540,28 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
* Bed Leveling Requirements
*/
#if ENABLED(AUTO_BED_LEVELING_UBL)
/**
* Unified Bed Leveling
*/
#if IS_SCARA
#error "AUTO_BED_LEVELING_UBL does not yet support SCARA printers."
#elif ENABLED(POLAR)
#if IS_SCARA && ANY(AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_3POINT, AUTO_BED_LEVELING_UBL)
#error "SCARA machines can only use AUTO_BED_LEVELING_BILINEAR or MESH_BED_LEVELING leveling."
#elif ENABLED(AUTO_BED_LEVELING_LINEAR) && !(WITHIN(GRID_MAX_POINTS_X, 2, 255) && WITHIN(GRID_MAX_POINTS_Y, 2, 255))
#error "GRID_MAX_POINTS_[XY] must be between 2 and 255 with AUTO_BED_LEVELING_LINEAR."
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR) && !(WITHIN(GRID_MAX_POINTS_X, 3, 255) && WITHIN(GRID_MAX_POINTS_Y, 3, 255))
#error "GRID_MAX_POINTS_[XY] must be between 3 and 255 with AUTO_BED_LEVELING_BILINEAR."
#elif ENABLED(AUTO_BED_LEVELING_UBL)
#if ENABLED(POLAR)
#error "AUTO_BED_LEVELING_UBL does not yet support POLAR printers."
#elif DISABLED(EEPROM_SETTINGS)
#error "AUTO_BED_LEVELING_UBL requires EEPROM_SETTINGS."
#elif !WITHIN(GRID_MAX_POINTS_X, 3, 255) || !WITHIN(GRID_MAX_POINTS_Y, 3, 255)
#error "GRID_MAX_POINTS_[XY] must be between 3 and 255."
#elif ALL(UBL_HILBERT_CURVE, DELTA)
#error "UBL_HILBERT_CURVE can only be used with a square / rectangular printable area."
#endif
#elif HAS_ABL_NOT_UBL
/**
* Auto Bed Leveling
*/
/**
* Delta and SCARA have limited bed leveling options
*/
#if IS_SCARA && DISABLED(AUTO_BED_LEVELING_BILINEAR)
#error "SCARA machines can only use the AUTO_BED_LEVELING_BILINEAR leveling option."
#elif ABL_USES_GRID && !(WITHIN(GRID_MAX_POINTS_X, 3, 255) && WITHIN(GRID_MAX_POINTS_Y, 3, 255))
#error "GRID_MAX_POINTS_[XY] must be between 3 and 255."
#endif
#elif ENABLED(MESH_BED_LEVELING)
// Mesh Bed Leveling
#if ENABLED(DELTA)
#error "MESH_BED_LEVELING is not compatible with DELTA printers."
#elif (GRID_MAX_POINTS_X) > 9 || (GRID_MAX_POINTS_Y) > 9
#error "GRID_MAX_POINTS_X and GRID_MAX_POINTS_Y must be less than 10 for MBL."
#endif
#endif
#define _POINT_COUNT (defined(PROBE_PT_1) + defined(PROBE_PT_2) + defined(PROBE_PT_3))
@@ -2328,9 +2352,9 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
#elif Y_HOME_TO_MAX && !HAS_Y_MAX_STATE
#error "Y_MAX_PIN, Y_STOP_PIN, or Y_SPI_SENSORLESS is required for Y axis homing."
#elif Z_HOME_TO_MIN && !HAS_Z_MIN_STATE
#error "Z_MIN_PIN, Z_STOP_PIN, or Z_SPI_SENSORLESS is required for Y axis homing."
#error "Z_MIN_PIN, Z_STOP_PIN, or Z_SPI_SENSORLESS is required for Z axis homing."
#elif Z_HOME_TO_MAX && !HAS_Z_MAX_STATE
#error "Z_MAX_PIN, Z_STOP_PIN, or Z_SPI_SENSORLESS is required for Y axis homing."
#error "Z_MAX_PIN, Z_STOP_PIN, or Z_SPI_SENSORLESS is required for Z axis homing."
#elif I_HOME_TO_MIN && !HAS_I_MIN_STATE
#error "I_MIN_PIN, I_STOP_PIN, or I_SPI_SENSORLESS is required for I axis homing."
#elif I_HOME_TO_MAX && !HAS_I_MAX_STATE
@@ -2575,8 +2599,8 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
+ (ENABLED(U8GLIB_SSD1306) && DISABLED(IS_U8GLIB_SSD1306)) \
+ (ENABLED(MINIPANEL) && NONE(MKS_MINI_12864, ENDER2_STOCKDISPLAY)) \
+ (ENABLED(MKS_MINI_12864) && NONE(MKS_LCD12864A, MKS_LCD12864B)) \
+ (ENABLED(FYSETC_MINI_12864_2_1) && NONE(MKS_MINI_12864_V3, BTT_MINI_12864_V1)) \
+ COUNT_ENABLED(MKS_MINI_12864_V3, BTT_MINI_12864_V1) \
+ (ENABLED(FYSETC_MINI_12864_2_1) && NONE(MKS_MINI_12864_V3, BTT_MINI_12864)) \
+ COUNT_ENABLED(MKS_MINI_12864_V3, BTT_MINI_12864) \
+ (ENABLED(EXTENSIBLE_UI) && DISABLED(IS_EXTUI)) \
+ (DISABLED(IS_LEGACY_TFT) && ENABLED(TFT_GENERIC)) \
+ (ENABLED(IS_LEGACY_TFT) && COUNT_ENABLED(TFT_320x240, TFT_320x240_SPI, TFT_480x320, TFT_480x320_SPI)) \
@@ -2736,7 +2760,7 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
#endif
#if LCD_BACKLIGHT_TIMEOUT_MINS
#if !HAS_ENCODER_ACTION
#if !HAS_ENCODER_ACTION && DISABLED(HAS_DWIN_E3V2)
#error "LCD_BACKLIGHT_TIMEOUT_MINS requires an LCD with encoder or keypad."
#elif ENABLED(NEOPIXEL_BKGD_INDEX_FIRST)
#if PIN_EXISTS(LCD_BACKLIGHT)
@@ -2744,8 +2768,8 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
#elif ENABLED(NEOPIXEL_BKGD_ALWAYS_ON)
#error "LCD_BACKLIGHT_TIMEOUT is not compatible with NEOPIXEL_BKGD_ALWAYS_ON."
#endif
#elif !PIN_EXISTS(LCD_BACKLIGHT)
#error "LCD_BACKLIGHT_TIMEOUT_MINS requires either LCD_BACKLIGHT_PIN or NEOPIXEL_BKGD_INDEX_FIRST."
#elif !PIN_EXISTS(LCD_BACKLIGHT) && DISABLED(HAS_DWIN_E3V2)
#error "LCD_BACKLIGHT_TIMEOUT_MINS requires LCD_BACKLIGHT_PIN, NEOPIXEL_BKGD_INDEX_FIRST, or an Ender-3 V2 DWIN LCD."
#endif
#endif
@@ -3031,6 +3055,25 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
#error "STEALTHCHOP_XY and STEALTHCHOP_Z must be the same on DELTA."
#endif
// H-Bot kinematic axes can't use homing phases
#if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX) && defined(TMC_HOME_PHASE)
constexpr float _phases[] = TMC_HOME_PHASE, _vphase[9] = TMC_HOME_PHASE;
constexpr int _nphase = COUNT(_phases);
static_assert(_nphase == NUM_AXES, "TMC_HOME_PHASE must have exactly " _NUM_AXES_STR " elements.");
static_assert(_nphase < 0 || _vphase[0] == -1 || NORMAL_AXIS == 0, "TMC_HOME_PHASE.x must be -1 for the selected kinematics.");
static_assert(_nphase < 1 || _vphase[1] == -1 || NORMAL_AXIS == 1, "TMC_HOME_PHASE.y must be -1 for the selected kinematics.");
static_assert(_nphase < 2 || _vphase[2] == -1 || NORMAL_AXIS == 2, "TMC_HOME_PHASE.z must be -1 for the selected kinematics.");
static_assert(_nphase < 0 || WITHIN(_vphase[0], -1, 1023), "TMC_HOME_PHASE.x must be between -1 and 1023.");
static_assert(_nphase < 1 || WITHIN(_vphase[1], -1, 1023), "TMC_HOME_PHASE.y must be between -1 and 1023.");
static_assert(_nphase < 2 || WITHIN(_vphase[2], -1, 1023), "TMC_HOME_PHASE.z must be between -1 and 1023.");
static_assert(_nphase < 3 || WITHIN(_vphase[3], -1, 1023), "TMC_HOME_PHASE.i must be between -1 and 1023.");
static_assert(_nphase < 4 || WITHIN(_vphase[4], -1, 1023), "TMC_HOME_PHASE.j must be between -1 and 1023.");
static_assert(_nphase < 5 || WITHIN(_vphase[5], -1, 1023), "TMC_HOME_PHASE.k must be between -1 and 1023.");
static_assert(_nphase < 6 || WITHIN(_vphase[6], -1, 1023), "TMC_HOME_PHASE.u must be between -1 and 1023.");
static_assert(_nphase < 7 || WITHIN(_vphase[7], -1, 1023), "TMC_HOME_PHASE.v must be between -1 and 1023.");
static_assert(_nphase < 8 || WITHIN(_vphase[8], -1, 1023), "TMC_HOME_PHASE.w must be between -1 and 1023.");
#endif
#if ENABLED(SENSORLESS_HOMING)
// Require STEALTHCHOP for SENSORLESS_HOMING on DELTA as the transition from spreadCycle to stealthChop
// is necessary in order to reset the stallGuard indication between the initial movement of all three
@@ -3443,8 +3486,8 @@ static_assert(_PLUS_TEST(3), "DEFAULT_MAX_ACCELERATION values must be positive."
#error "CNC_COORDINATE_SYSTEMS is incompatible with NO_WORKSPACE_OFFSETS."
#endif
#if !BLOCK_BUFFER_SIZE || !IS_POWER_OF_2(BLOCK_BUFFER_SIZE)
#error "BLOCK_BUFFER_SIZE must be a power of 2."
#if !BLOCK_BUFFER_SIZE
#error "BLOCK_BUFFER_SIZE must be non-zero."
#elif BLOCK_BUFFER_SIZE > 64
#error "A very large BLOCK_BUFFER_SIZE is not needed and takes longer to drain the buffer on pause / cancel."
#endif
@@ -3804,12 +3847,20 @@ static_assert(_PLUS_TEST(3), "DEFAULT_MAX_ACCELERATION values must be positive."
/**
* Sanity check WiFi options
*/
#if ENABLED(ESP3D_WIFISUPPORT) && DISABLED(ARDUINO_ARCH_ESP32)
#error "ESP3D_WIFISUPPORT requires an ESP32 MOTHERBOARD."
#elif ENABLED(WEBSUPPORT) && NONE(ARDUINO_ARCH_ESP32, WIFISUPPORT)
#error "WEBSUPPORT requires WIFISUPPORT and an ESP32 MOTHERBOARD."
#elif ALL(ESP3D_WIFISUPPORT, WIFISUPPORT)
#error "Enable only one of ESP3D_WIFISUPPORT or WIFISUPPORT."
#if ALL(WIFISUPPORT, ESP3D_WIFISUPPORT)
#error "Enable only one of WIFISUPPORT or ESP3D_WIFISUPPORT."
#elif ENABLED(ESP3D_WIFISUPPORT) && DISABLED(ARDUINO_ARCH_ESP32)
#error "ESP3D_WIFISUPPORT requires an ESP32 motherboard."
#elif ALL(ARDUINO_ARCH_ESP32, WIFISUPPORT)
#if !(defined(WIFI_SSID) && defined(WIFI_PWD))
#error "ESP32 motherboard with WIFISUPPORT requires WIFI_SSID and WIFI_PWD."
#endif
#elif ENABLED(WIFI_CUSTOM_COMMAND)
#error "WIFI_CUSTOM_COMMAND requires an ESP32 motherboard and WIFISUPPORT."
#elif ENABLED(OTASUPPORT)
#error "OTASUPPORT requires an ESP32 motherboard and WIFISUPPORT."
#elif defined(WIFI_SSID) || defined(WIFI_PWD)
#error "WIFI_SSID and WIFI_PWD only apply to ESP32 motherboard with WIFISUPPORT."
#endif
/**
+1 -1
View File
@@ -42,7 +42,7 @@
* version was tagged.
*/
#ifndef STRING_DISTRIBUTION_DATE
#define STRING_DISTRIBUTION_DATE "2023-08-04"
#define STRING_DISTRIBUTION_DATE "2023-11-07"
#endif
/**
+33 -20
View File
@@ -1165,32 +1165,43 @@ void MarlinUI::draw_status_screen() {
#endif // ADVANCED_PAUSE_FEATURE
// Draw a static item with no left-right margin required. Centered by default.
void MenuItem_static::draw(const uint8_t row, FSTR_P const fstr, const uint8_t style/*=SS_DEFAULT*/, const char *vstr/*=nullptr*/) {
void MenuItem_static::draw(const uint8_t row, FSTR_P const ftpl, const uint8_t style/*=SS_DEFAULT*/, const char *vstr/*=nullptr*/) {
lcd_moveto(0, row);
int8_t n = LCD_WIDTH;
const bool center = bool(style & SS_CENTER), full = bool(style & SS_FULL);
const int8_t plen = fstr ? utf8_strlen(fstr) : 0,
vlen = vstr ? utf8_strlen(vstr) : 0;
int8_t pad = (center || full) ? n - plen - vlen : 0;
// Value length, if any
int8_t vlen = vstr ? utf8_strlen(vstr) : 0;
// Expanded label string and width in chars
char estr[calculateWidth(ftpl) + 3] = "\0";
int8_t llen = ftpl ? expand_u8str(estr, ftpl, itemIndex, itemStringC, itemStringF, n - vlen) : 0;
bool mv_colon = false;
if (vlen) {
// Move the leading colon from the value to the label below
mv_colon = (*vstr == ':');
// Shorter value, wider label
if (mv_colon) { vstr++; vlen--; llen++; }
// Remove leading spaces from the value and shorten
while (*vstr == ' ') { vstr++; vlen--; }
}
// Padding for center or full justification
int8_t pad = (center || full) ? n - llen - vlen : 0;
// SS_CENTER: Pad with half of the unused space first
if (center) for (int8_t lpad = pad / 2; lpad > 0; --lpad) { lcd_put_u8str(F(" ")); n--; }
if (center) for (int8_t lpad = pad / 2; lpad > 0; --lpad, --pad, --n) lcd_put_u8str(F(" "));
// Draw as much of the label as fits
if (plen) {
const int8_t expl = n;
n = lcd_put_u8str(fstr, itemIndex, itemStringC, itemStringF, n);
pad -= (expl - n - plen); // Reduce the padding
}
// Draw as much of the label as fits (without the relocated colon, drawn below)
if (llen) n -= lcd_put_u8str_max(estr, n - vlen);
if (vlen && n > 0) {
// SS_FULL: Pad with enough space to justify the value
if (full && !center) {
// Move the leading colon from the value to the label
if (*vstr == ':') { n -= lcd_put_u8str(F(":")); vstr++; }
// Move spaces to the padding
while (*vstr == ' ') { vstr++; pad++; }
if (mv_colon) n -= lcd_put_u8str(F(":"));
// Pad in-between
for (; pad > 0; --pad) { lcd_put_u8str(F(" ")); n--; }
}
@@ -1203,7 +1214,8 @@ void MarlinUI::draw_status_screen() {
// Draw a generic menu item with pre_char (if selected) and post_char
void MenuItemBase::_draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char pre_char, const char post_char) {
lcd_put_lchar(0, row, sel ? pre_char : ' ');
uint8_t n = lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, LCD_WIDTH - 2);
uint8_t n = LCD_WIDTH - 2;
n -= lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, n);
for (; n; --n) lcd_put_u8str(F(" "));
lcd_put_lchar(post_char);
}
@@ -1224,7 +1236,8 @@ void MarlinUI::draw_status_screen() {
// Low-level draw_edit_screen can be used to draw an edit screen from anyplace
void MenuEditItemBase::draw_edit_screen(FSTR_P const ftpl, const char * const value/*=nullptr*/) {
ui.encoder_direction_normal();
uint8_t n = lcd_put_u8str(0, 1, ftpl, itemIndex, itemStringC, itemStringF, LCD_WIDTH - 1);
uint8_t n = LCD_WIDTH - 1;
n -= lcd_put_u8str(0, 1, ftpl, itemIndex, itemStringC, itemStringF, n);
if (value) {
lcd_put_u8str(F(":")); n--;
const uint8_t len = utf8_strlen(value) + 1; // Plus one for a leading space
@@ -1235,8 +1248,8 @@ void MarlinUI::draw_status_screen() {
}
// The Select Screen presents a prompt and two "buttons"
void MenuItem_confirm::draw_select_screen(FSTR_P const yes, FSTR_P const no, const bool yesno, FSTR_P const pref, const char * const string/*=nullptr*/, FSTR_P const suff/*=nullptr*/) {
ui.draw_select_screen_prompt(pref, string, suff);
void MenuItem_confirm::draw_select_screen(FSTR_P const yes, FSTR_P const no, const bool yesno, FSTR_P const fpre, const char * const string/*=nullptr*/, FSTR_P const fsuf/*=nullptr*/) {
ui.draw_select_screen_prompt(fpre, string, fsuf);
if (no) {
SETCURSOR(0, LCD_HEIGHT - 1);
lcd_put_lchar(yesno ? ' ' : '['); lcd_put_u8str(no); lcd_put_lchar(yesno ? ' ' : ']');
@@ -1251,8 +1264,8 @@ void MarlinUI::draw_status_screen() {
void MenuItem_sdbase::draw(const bool sel, const uint8_t row, FSTR_P const, CardReader &theCard, const bool isDir) {
lcd_put_lchar(0, row, sel ? LCD_STR_ARROW_RIGHT[0] : ' ');
constexpr uint8_t maxlen = LCD_WIDTH - 2;
uint8_t n = maxlen - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, row, sel), maxlen);
uint8_t n = LCD_WIDTH - 2;
n -= lcd_put_u8str_max(ui.scrolled_filename(theCard, n, row, sel), n);
for (; n; --n) lcd_put_u8str(F(" "));
lcd_put_lchar(isDir ? LCD_STR_FOLDER[0] : ' ');
}
+31 -20
View File
@@ -969,33 +969,42 @@ void MarlinUI::draw_status_screen() {
#endif
// Draw a static item with no left-right margin required. Centered by default.
void MenuItem_static::draw(const uint8_t row, FSTR_P const fstr, const uint8_t style/*=SS_DEFAULT*/, const char *vstr/*=nullptr*/) {
void MenuItem_static::draw(const uint8_t row, FSTR_P const ftpl, const uint8_t style/*=SS_DEFAULT*/, const char *vstr/*=nullptr*/) {
if (!PanelDetected) return;
lcd_moveto(0, row);
uint8_t n = LCD_WIDTH;
const bool center = bool(style & SS_CENTER), full = bool(style & SS_FULL);
const int8_t plen = fstr ? utf8_strlen(fstr) : 0,
vlen = vstr ? utf8_strlen(vstr) : 0;
int8_t pad = (center || full) ? n - plen - vlen : 0;
// Value length, if any
int8_t vlen = vstr ? utf8_strlen(vstr) : 0;
char estr[utf8_strlen(ftpl) + 3] = "\0";
int8_t llen = ftpl ? expand_u8str(estr, ftpl, itemIndex, itemStringC, itemStringF, n - vlen) : 0;
bool mv_colon = false;
if (vlen) {
// Move the leading colon from the value to the label below
mv_colon = (*vstr == ':');
// Shorter value, wider label
if (mv_colon) { vstr++; vlen--; llen++; }
// Remove leading spaces from the value and shorten
while (*vstr == ' ') { vstr++; vlen--; }
}
int8_t pad = (center || full) ? n - llen - vlen : 0;
// SS_CENTER: Pad with half of the unused space first
if (center) for (int8_t lpad = pad / 2; lpad > 0; --lpad) { lcd.write(' '); n--; }
// Draw as much of the label as fits
if (plen) {
const int8_t expl = n;
n = lcd_put_u8str(fstr, itemIndex, itemStringC, itemStringF, n);
pad -= (expl - n - plen); // Reduce the padding
}
if (llen) n -= lcd_put_u8str_max(estr, n - vlen);
if (vlen && n > 0) {
// SS_FULL: Pad with enough space to justify the value
if (full && !center) {
// Move the leading colon from the value to the label
if (*vstr == ':') { lcd.write(':'); vstr++; n--; }
// Move spaces to the padding
while (*vstr == ' ') { vstr++; pad++; }
if (mv_colon) { lcd.write(':'); n--; }
// Pad in-between
for (; pad > 0; --pad) { lcd.write(' '); n--; }
}
@@ -1008,23 +1017,25 @@ void MarlinUI::draw_status_screen() {
}
// Draw a generic menu item with pre_char (if selected) and post_char
void MenuItemBase::_draw(const bool sel, const uint8_t row, FSTR_P const fstr, const char pre_char, const char post_char) {
void MenuItemBase::_draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char pre_char, const char post_char) {
if (!PanelDetected) return;
lcd_moveto(0, row);
lcd.write(sel ? pre_char : ' ');
uint8_t n = lcd_put_u8str(fstr, itemIndex, itemStringC, itemStringF, LCD_WIDTH - 2);
uint8_t n = LCD_WIDTH - 2;
n -= lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, n);
for (; n; --n) lcd.write(' ');
lcd.write(post_char);
lcd.print_line();
}
// Draw a menu item with a (potentially) editable value
void MenuEditItemBase::draw(const bool sel, const uint8_t row, FSTR_P const fstr, const char * const inStr, const bool pgm) {
void MenuEditItemBase::draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char * const inStr, const bool pgm) {
if (!PanelDetected) return;
const uint8_t vlen = inStr ? (pgm ? utf8_strlen_P(inStr) : utf8_strlen(inStr)) : 0;
lcd_moveto(0, row);
lcd.write(sel ? LCD_STR_ARROW_RIGHT[0] : ' ');
uint8_t n = lcd_put_u8str(fstr, itemIndex, itemStringC, itemStringF, LCD_WIDTH - 2 - vlen);
uint8_t n = LCD_WIDTH - 2 - vlen;
n -= lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, n);
if (vlen) {
lcd.write(':');
for (; n; --n) lcd.write(' ');
@@ -1053,9 +1064,9 @@ void MarlinUI::draw_status_screen() {
}
// The Select Screen presents a prompt and two "buttons"
void MenuItem_confirm::draw_select_screen(FSTR_P const yes, FSTR_P const no, const bool yesno, FSTR_P const pref, const char * const string, FSTR_P const suff) {
void MenuItem_confirm::draw_select_screen(FSTR_P const yes, FSTR_P const no, const bool yesno, FSTR_P const fpre, const char * const string, FSTR_P const fsuf) {
if (!PanelDetected) return;
ui.draw_select_screen_prompt(pref, string, suff);
ui.draw_select_screen_prompt(fpre, string, fsuf);
lcd.write(COLOR_EDIT);
if (no) {
lcd_moveto(0, MIDDLE_Y);
@@ -1074,8 +1085,8 @@ void MarlinUI::draw_status_screen() {
if (!PanelDetected) return;
lcd_moveto(0, row);
lcd.write(sel ? LCD_STR_ARROW_RIGHT[0] : ' ');
constexpr uint8_t maxlen = LCD_WIDTH - 2;
uint8_t n = maxlen - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, row, sel), maxlen);
uint8_t n = LCD_WIDTH - 2;
n -= lcd_put_u8str_max(ui.scrolled_filename(theCard, n, row, sel), n);
for (; n; --n) lcd.write(' ');
lcd.write(isDir ? LCD_STR_FOLDER[0] : ' ');
lcd.print_line();
+20 -20
View File
@@ -31,12 +31,12 @@ extern u8g_dev_t u8g_dev_st7565_64128n_HAL_2x_hw_spi;
class U8GLIB_64128N_2X_HAL : public U8GLIB {
public:
U8GLIB_64128N_2X_HAL() : U8GLIB() { }
U8GLIB_64128N_2X_HAL(pin_t sck, pin_t mosi, pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) { init(sck, mosi, cs, a0, reset); }
U8GLIB_64128N_2X_HAL(pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) { init(cs, a0, reset); }
void init(pin_t sck, pin_t mosi, pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) {
U8GLIB_64128N_2X_HAL(pin_t sck, pin_t mosi, pin_t cs, pin_t a0, pin_t reset=U8G_PIN_NONE) { init(sck, mosi, cs, a0, reset); }
U8GLIB_64128N_2X_HAL(pin_t cs, pin_t a0, pin_t reset=U8G_PIN_NONE) { init(cs, a0, reset); }
void init(pin_t sck, pin_t mosi, pin_t cs, pin_t a0, pin_t reset=U8G_PIN_NONE) {
U8GLIB::init(&u8g_dev_st7565_64128n_HAL_2x_sw_spi, (uint8_t)sck, (uint8_t)mosi, (uint8_t)cs, (uint8_t)a0, (uint8_t)reset);
}
void init(pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) {
void init(pin_t cs, pin_t a0, pin_t reset=U8G_PIN_NONE) {
U8GLIB::init(&u8g_dev_st7565_64128n_HAL_2x_hw_spi, (uint8_t)cs, (uint8_t)a0, (uint8_t)reset);
}
};
@@ -47,12 +47,12 @@ extern u8g_dev_t u8g_dev_st7920_128x64_HAL_4x_hw_spi;
class U8GLIB_ST7920_128X64_4X_HAL : public U8GLIB {
public:
U8GLIB_ST7920_128X64_4X_HAL() : U8GLIB() { }
U8GLIB_ST7920_128X64_4X_HAL(pin_t sck, pin_t mosi, pin_t cs, pin_t reset = U8G_PIN_NONE) { init(sck, mosi, cs, reset); }
U8GLIB_ST7920_128X64_4X_HAL(pin_t cs, pin_t reset = U8G_PIN_NONE) { init(cs, reset); }
void init(pin_t sck, pin_t mosi, pin_t cs, pin_t reset = U8G_PIN_NONE) {
U8GLIB_ST7920_128X64_4X_HAL(pin_t sck, pin_t mosi, pin_t cs, pin_t reset=U8G_PIN_NONE) { init(sck, mosi, cs, reset); }
U8GLIB_ST7920_128X64_4X_HAL(pin_t cs, pin_t reset=U8G_PIN_NONE) { init(cs, reset); }
void init(pin_t sck, pin_t mosi, pin_t cs, pin_t reset=U8G_PIN_NONE) {
U8GLIB::init(&u8g_dev_st7920_128x64_HAL_4x_sw_spi, (uint8_t)sck, (uint8_t)mosi, (uint8_t)cs, U8G_PIN_NONE, (uint8_t)reset); // a0 = U8G_PIN_NONE
}
void init(pin_t cs, pin_t reset = U8G_PIN_NONE) {
void init(pin_t cs, pin_t reset=U8G_PIN_NONE) {
U8GLIB::init(&u8g_dev_st7920_128x64_HAL_4x_hw_spi, (uint8_t)cs, U8G_PIN_NONE, (uint8_t)reset); // a0 = U8G_PIN_NONE
}
};
@@ -66,8 +66,8 @@ extern u8g_dev_t u8g_dev_st7920_128x64_rrd_sw_spi;
class U8GLIB_ST7920_128X64_RRD : public U8GLIB {
public:
U8GLIB_ST7920_128X64_RRD() : U8GLIB() { }
U8GLIB_ST7920_128X64_RRD(pin_t sck, pin_t mosi, pin_t cs, pin_t reset = U8G_PIN_NONE) { init(sck, mosi, cs, reset); }
void init(pin_t sck, pin_t mosi, pin_t cs, pin_t reset = U8G_PIN_NONE) {
U8GLIB_ST7920_128X64_RRD(pin_t sck, pin_t mosi, pin_t cs, pin_t reset=U8G_PIN_NONE) { init(sck, mosi, cs, reset); }
void init(pin_t sck, pin_t mosi, pin_t cs, pin_t reset=U8G_PIN_NONE) {
U8GLIB::init(&u8g_dev_st7920_128x64_rrd_sw_spi, (uint8_t)sck, (uint8_t)mosi, (uint8_t)cs, U8G_PIN_NONE, (uint8_t)reset); // a0 = U8G_PIN_NONE
}
};
@@ -99,8 +99,8 @@ extern u8g_dev_t u8g_dev_tft_320x240_upscale_from_128x64;
class U8GLIB_TFT_320X240_UPSCALE_FROM_128X64 : public U8GLIB {
public:
U8GLIB_TFT_320X240_UPSCALE_FROM_128X64() : U8GLIB() { }
U8GLIB_TFT_320X240_UPSCALE_FROM_128X64(uint8_t cs, uint8_t rs, uint8_t reset = U8G_PIN_NONE) { init(cs, rs, reset); }
void init(uint8_t cs, uint8_t rs, uint8_t reset = U8G_PIN_NONE) { U8GLIB::init(&u8g_dev_tft_320x240_upscale_from_128x64, cs, rs, reset); }
U8GLIB_TFT_320X240_UPSCALE_FROM_128X64(uint8_t cs, uint8_t rs, uint8_t reset=U8G_PIN_NONE) { init(cs, rs, reset); }
void init(uint8_t cs, uint8_t rs, uint8_t reset=U8G_PIN_NONE) { U8GLIB::init(&u8g_dev_tft_320x240_upscale_from_128x64, cs, rs, reset); }
};
@@ -109,12 +109,12 @@ extern u8g_dev_t u8g_dev_uc1701_mini12864_HAL_2x_sw_spi, u8g_dev_uc1701_mini1286
class U8GLIB_MINI12864_2X_HAL : public U8GLIB {
public:
U8GLIB_MINI12864_2X_HAL() : U8GLIB() { }
U8GLIB_MINI12864_2X_HAL(uint8_t sck, uint8_t mosi, uint8_t cs, uint8_t a0, uint8_t reset = U8G_PIN_NONE) { init(sck, mosi, cs, a0, reset); }
U8GLIB_MINI12864_2X_HAL(uint8_t cs, uint8_t a0, uint8_t reset = U8G_PIN_NONE) { init(cs, a0, reset); }
void init(uint8_t sck, uint8_t mosi, uint8_t cs, uint8_t a0, uint8_t reset = U8G_PIN_NONE) {
U8GLIB_MINI12864_2X_HAL(uint8_t sck, uint8_t mosi, uint8_t cs, uint8_t a0, uint8_t reset=U8G_PIN_NONE) { init(sck, mosi, cs, a0, reset); }
U8GLIB_MINI12864_2X_HAL(uint8_t cs, uint8_t a0, uint8_t reset=U8G_PIN_NONE) { init(cs, a0, reset); }
void init(uint8_t sck, uint8_t mosi, uint8_t cs, uint8_t a0, uint8_t reset=U8G_PIN_NONE) {
U8GLIB::init(&u8g_dev_uc1701_mini12864_HAL_2x_sw_spi, sck, mosi, cs, a0, reset);
}
void init(uint8_t cs, uint8_t a0, uint8_t reset = U8G_PIN_NONE) {
void init(uint8_t cs, uint8_t a0, uint8_t reset=U8G_PIN_NONE) {
U8GLIB::init(&u8g_dev_uc1701_mini12864_HAL_2x_hw_spi, cs, a0, reset);
}
};
@@ -125,12 +125,12 @@ extern u8g_dev_t u8g_dev_ssd1309_hw_spi;
class U8GLIB_SSD1309_128X64_HAL : public U8GLIB {
public:
U8GLIB_SSD1309_128X64_HAL() : U8GLIB() { }
U8GLIB_SSD1309_128X64_HAL(pin_t sck, pin_t mosi, pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) { init(sck, mosi, cs, a0, reset); }
U8GLIB_SSD1309_128X64_HAL(pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) { init(cs, a0, reset); }
void init(pin_t sck, pin_t mosi, pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) {
U8GLIB_SSD1309_128X64_HAL(pin_t sck, pin_t mosi, pin_t cs, pin_t a0, pin_t reset=U8G_PIN_NONE) { init(sck, mosi, cs, a0, reset); }
U8GLIB_SSD1309_128X64_HAL(pin_t cs, pin_t a0, pin_t reset=U8G_PIN_NONE) { init(cs, a0, reset); }
void init(pin_t sck, pin_t mosi, pin_t cs, pin_t a0, pin_t reset=U8G_PIN_NONE) {
U8GLIB::init(&u8g_dev_ssd1309_sw_spi, (uint8_t)sck, (uint8_t)mosi, (uint8_t)cs, (uint8_t)a0, (uint8_t)reset);
}
void init(pin_t cs, pin_t a0, pin_t reset = U8G_PIN_NONE) {
void init(pin_t cs, pin_t a0, pin_t reset=U8G_PIN_NONE) {
U8GLIB::init(&u8g_dev_ssd1309_hw_spi, (uint8_t)cs, (uint8_t)a0, (uint8_t)reset);
}
};
@@ -41,11 +41,9 @@
#define U8G_COM_HAL_HW_SPI_FN u8g_com_samd51_hw_spi_fn
#define U8G_COM_ST7920_HAL_HW_SPI u8g_com_samd51_st7920_hw_spi_fn
#elif defined(__SAMD21__)
uint8_t u8g_com_samd21_st7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
#define U8G_COM_ST7920_HAL_HW_SPI u8g_com_samd21_st7920_hw_spi_fn
#elif defined(__STM32F1__)
+6
View File
@@ -38,6 +38,9 @@ int lcd_put_lchar_max(const lchar_t &c, const pixel_len_t max_length) {
return ret;
}
/**
* @return output width in pixels
*/
int lcd_put_u8str_max(const char * utf8_str, const pixel_len_t max_length) {
u8g_uint_t x = u8g.getPrintCol(), y = u8g.getPrintRow(),
ret = uxg_DrawUtf8Str(u8g.getU8g(), x, y, utf8_str, max_length);
@@ -45,6 +48,9 @@ int lcd_put_u8str_max(const char * utf8_str, const pixel_len_t max_length) {
return ret;
}
/**
* @return output width in pixels
*/
int lcd_put_u8str_max_P(PGM_P utf8_pstr, const pixel_len_t max_length) {
u8g_uint_t x = u8g.getPrintCol(), y = u8g.getPrintRow(),
ret = uxg_DrawUtf8StrP(u8g.getU8g(), x, y, utf8_pstr, max_length);
+67 -54
View File
@@ -411,65 +411,78 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
// Draw a static line of text in the same idiom as a menu item
void MenuItem_static::draw(const uint8_t row, FSTR_P const ftpl, const uint8_t style/*=SS_DEFAULT*/, const char *vstr/*=nullptr*/) {
if (!mark_as_selected(row, style & SS_INVERT)) return;
if (mark_as_selected(row, style & SS_INVERT)) {
pixel_len_t n = LCD_PIXEL_WIDTH; // pixel width of string allowed
pixel_len_t n = LCD_PIXEL_WIDTH; // pixel width of string allowed
const bool center = bool(style & SS_CENTER), full = bool(style & SS_FULL);
const bool center = bool(style & SS_CENTER), full = bool(style & SS_FULL);
const int pwide = ftpl ? calculateWidth(ftpl) : 0,
vlen = vstr ? utf8_strlen(vstr) : 0;
int pad = (center || full) ? ((LCD_PIXEL_WIDTH) - pwide - vlen * (MENU_FONT_WIDTH)) / (MENU_FONT_WIDTH) : 0;
char estr[calculateWidth(ftpl) + 3] = "\0";
pixel_len_t lwide = ftpl ? (MENU_FONT_WIDTH) * expand_u8str(estr, ftpl, itemIndex, itemStringC, itemStringF, (LCD_PIXEL_WIDTH) / (MENU_FONT_WIDTH)) : 0;
// SS_CENTER: Pad with half of the unused space first
if (center) for (int lpad = pad / 2; lpad > 0; --lpad) n -= lcd_put_u8str(F(" "));
// Value length, if any
int8_t vlen = vstr ? utf8_strlen(vstr) : 0;
// Draw as much of the label as fits
if (pwide) {
const pixel_len_t expw = n;
n = lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, n / (MENU_FONT_WIDTH)) * (MENU_FONT_WIDTH);
pad -= (expw - n - pwide) / (MENU_FONT_WIDTH); // Reduce the padding
}
if (vlen) {
// SS_FULL: Pad with enough space to justify the value
if (full && !center && n > MENU_FONT_WIDTH) {
// Move the leading colon from the value to the label
if (*vstr == ':') { n -= lcd_put_u8str(F(":")); vstr++; }
// Move spaces to the padding
while (*vstr == ' ') { vstr++; pad++; }
// Pad in-between
for (; pad > 0; --pad) n -= lcd_put_u8str(F(" "));
}
n -= lcd_put_u8str_max(vstr, n);
}
while (n > MENU_FONT_WIDTH) n -= lcd_put_u8str(F(" "));
bool mv_colon = false;
if (vlen) {
// Move the leading colon from the value to the label below
mv_colon = (*vstr == ':');
// Shorter value, wider label
if (mv_colon) { vstr++; vlen--; lwide += MENU_FONT_WIDTH; }
// Remove leading spaces from the value and shorten
while (*vstr == ' ') { vstr++; vlen--; }
}
// Padding for center or full justification
int8_t pad = (center || full) ? ((LCD_PIXEL_WIDTH) - lwide - vlen * (MENU_FONT_WIDTH)) / (MENU_FONT_WIDTH) : 0;
// SS_CENTER: Pad with half of the unused space first
if (center) for (int8_t lpad = pad / 2; lpad > 0; --lpad) n -= lcd_put_u8str(F(" "));
// Draw as much of the label as fits (without the relocated colon, drawn below)
if (lwide) lcd_put_u8str_max(estr, n);
// Value string?
if (vlen) {
// SS_FULL: Pad with enough space to justify the value
if (full && !center && n > MENU_FONT_WIDTH) {
// Draw the leading colon moved from the value to the label
if (mv_colon) n -= lcd_put_u8str(F(":"));
// Pad in-between
for (; pad > 0; --pad) n -= lcd_put_u8str(F(" "));
}
// Draw the value string
n -= lcd_put_u8str_max(vstr, n);
}
// Always fill out the rest with spaces
while (n > MENU_FONT_WIDTH) n -= lcd_put_u8str(F(" "));
}
// Draw a generic menu item
void MenuItemBase::_draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char, const char post_char) {
if (mark_as_selected(row, sel)) {
pixel_len_t n = lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, LCD_WIDTH - 1) * (MENU_FONT_WIDTH);
while (n > MENU_FONT_WIDTH) n -= lcd_put_u8str(F(" "));
lcd_put_lchar(LCD_PIXEL_WIDTH - (MENU_FONT_WIDTH), row_y2, post_char);
lcd_put_u8str(F(" "));
}
if (!mark_as_selected(row, sel)) return;
uint8_t n = LCD_WIDTH - 1;
n -= lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, n);
for (; n; --n) lcd_put_u8str(F(" "));
lcd_put_lchar(LCD_PIXEL_WIDTH - (MENU_FONT_WIDTH), row_y2, post_char);
lcd_put_u8str(F(" "));
}
// Draw a menu item with an editable value
void MenuEditItemBase::draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char * const inStr, const bool pgm) {
if (mark_as_selected(row, sel)) {
const uint8_t vallen = (pgm ? utf8_strlen_P(inStr) : utf8_strlen(inStr)),
pixelwidth = (pgm ? uxg_GetUtf8StrPixelWidthP(u8g.getU8g(), inStr) : uxg_GetUtf8StrPixelWidth(u8g.getU8g(), inStr));
const u8g_uint_t prop = USE_WIDE_GLYPH ? 2 : 1;
if (!mark_as_selected(row, sel)) return;
pixel_len_t n = lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, LCD_WIDTH - 2 - vallen * prop) * (MENU_FONT_WIDTH);
if (vallen) {
lcd_put_u8str(F(":"));
while (n > MENU_FONT_WIDTH) n -= lcd_put_u8str(F(" "));
lcd_moveto(LCD_PIXEL_WIDTH - _MAX((MENU_FONT_WIDTH) * vallen, pixelwidth + 2), row_y2);
if (pgm) lcd_put_u8str_P(inStr); else lcd_put_u8str(inStr);
}
const uint8_t vallen = (pgm ? utf8_strlen_P(inStr) : utf8_strlen(inStr)),
pixelwidth = (pgm ? uxg_GetUtf8StrPixelWidthP(u8g.getU8g(), inStr) : uxg_GetUtf8StrPixelWidth(u8g.getU8g(), inStr));
const u8g_uint_t prop = USE_WIDE_GLYPH ? 2 : 1;
uint8_t n = LCD_WIDTH - 2 - vallen * prop;
n -= lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, n);
if (vallen) {
lcd_put_u8str(F(":"));
for (; n; --n) lcd_put_u8str(F(" "));
lcd_moveto(LCD_PIXEL_WIDTH - _MAX((MENU_FONT_WIDTH) * vallen, pixelwidth + 2), row_y2);
if (pgm) lcd_put_u8str_P(inStr); else lcd_put_u8str(inStr);
}
}
@@ -538,8 +551,8 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
if (inv) u8g.setColorIndex(1);
}
void MenuItem_confirm::draw_select_screen(FSTR_P const yes, FSTR_P const no, const bool yesno, FSTR_P const fpre, const char * const string/*=nullptr*/, FSTR_P const suff/*=nullptr*/) {
ui.draw_select_screen_prompt(fpre, string, suff);
void MenuItem_confirm::draw_select_screen(FSTR_P const yes, FSTR_P const no, const bool yesno, FSTR_P const fpre, const char * const string/*=nullptr*/, FSTR_P const fsuf/*=nullptr*/) {
ui.draw_select_screen_prompt(fpre, string, fsuf);
if (no) draw_boxed_string(1, LCD_HEIGHT - 1, no, !yesno);
if (yes) draw_boxed_string(LCD_WIDTH - (utf8_strlen(yes) * (USE_WIDE_GLYPH ? 2 : 1) + 1), LCD_HEIGHT - 1, yes, yesno);
}
@@ -547,13 +560,13 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
#if HAS_MEDIA
void MenuItem_sdbase::draw(const bool sel, const uint8_t row, FSTR_P const, CardReader &theCard, const bool isDir) {
if (mark_as_selected(row, sel)) {
const uint8_t maxlen = LCD_WIDTH - isDir;
if (isDir) lcd_put_lchar(LCD_STR_FOLDER[0]);
const pixel_len_t pixw = maxlen * (MENU_FONT_WIDTH);
pixel_len_t n = pixw - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, row, sel), pixw);
while (n > MENU_FONT_WIDTH) n -= lcd_put_u8str(F(" "));
}
if (!mark_as_selected(row, sel)) return;
const uint8_t maxlen = LCD_WIDTH - isDir;
if (isDir) lcd_put_lchar(LCD_STR_FOLDER[0]);
const pixel_len_t pixw = maxlen * (MENU_FONT_WIDTH);
pixel_len_t n = pixw - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, row, sel), pixw);
for (; n > MENU_FONT_WIDTH; n -= MENU_FONT_WIDTH) lcd_put_u8str(F(" "));
}
#endif // HAS_MEDIA
+9 -5
View File
@@ -36,11 +36,15 @@
// RepRapWorld Graphical LCD
#if !HAS_MEDIA && (LCD_PINS_D4 == SD_SCK_PIN) && (LCD_PINS_EN == SD_MOSI_PIN)
#define U8G_CLASS U8GLIB_ST7920_128X64_4X_HAL
#if HAS_MEDIA
#ifdef __SAMD21__
#define U8G_CLASS U8GLIB_ST7920_128X64_4X_HAL
#else
#define U8G_CLASS U8GLIB_ST7920_128X64_4X
#endif
#define U8G_PARAM LCD_PINS_RS
#elif HAS_MEDIA && __SAMD21__
#define U8G_CLASS U8GLIB_ST7920_128X64_4X
#elif (LCD_PINS_D4 == SD_SCK_PIN) && (LCD_PINS_EN == SD_MOSI_PIN)
#define U8G_CLASS U8GLIB_ST7920_128X64_4X_HAL
#define U8G_PARAM LCD_PINS_RS
#else
#define U8G_CLASS U8GLIB_ST7920_128X64_4X
@@ -61,7 +65,7 @@
#else
#define U8G_CLASS U8GLIB_ST7920_128X64_RRD // Adjust stripes with PAGE_HEIGHT in ultralcd_st7920_u8glib_rrd.h
#endif
#define U8G_PARAM LCD_PINS_D4, LCD_PINS_EN, LCD_PINS_RS // AVR version ignores these pin settings
#define U8G_PARAM LCD_PINS_D4, LCD_PINS_EN, LCD_PINS_RS // AVR version ignores these pin settings
// HAL version uses these pin settings
#endif
+24 -24
View File
@@ -41,32 +41,32 @@
#ifdef STATUS_CHAMBER_ANIM
const unsigned char status_chamber_bmp[] PROGMEM = {
B00011111,B11111111,B11111000,
B00010000,B00000000,B00001000,
B00010000,B00000000,B00001000,
B00010000,B00000000,B00001000,
B00010000,B00000000,B00001000,
B00010000,B00000000,B00001000,
B00010000,B00000000,B00001000,
B00010000,B00000000,B00001000,
B00010000,B00000000,B00001000,
B00010000,B00000000,B00001000,
B00011111,B11111111,B11111000,
B00011111,B11111111,B11111000
B00001111,B11111111,B11111000,
B00001000,B00000000,B00001000,
B00001000,B00000000,B00001000,
B00001000,B00000000,B00001000,
B00001000,B00000000,B00001000,
B00001000,B00000000,B00001000,
B00001000,B00000000,B00001000,
B00001000,B00000000,B00001000,
B00001000,B00000000,B00001000,
B00001000,B00000000,B00001000,
B00001111,B11111111,B11111000,
B00001111,B11111111,B11111000
};
const unsigned char status_chamber_on_bmp[] PROGMEM = {
B00011111,B11111111,B11111000,
B00010000,B00000000,B00001000,
B00010000,B10000100,B00001000,
B00010000,B01000010,B00001000,
B00010000,B01000010,B00001000,
B00010000,B10000100,B00001000,
B00010001,B00001000,B00001000,
B00010001,B00001000,B00001000,
B00010000,B10000100,B00001000,
B00010000,B00000000,B00001000,
B00011111,B11111111,B11111000,
B00011111,B11111111,B11111000
B00001111,B11111111,B11111000,
B00001000,B00000000,B00001000,
B00001000,B10000100,B00001000,
B00001000,B01000010,B00001000,
B00001000,B01000010,B00001000,
B00001000,B10000100,B00001000,
B00001001,B00001000,B00001000,
B00001001,B00001000,B00001000,
B00001000,B10000100,B00001000,
B00001000,B00000000,B00001000,
B00001111,B11111111,B11111000,
B00001111,B11111111,B11111000
};
#else
+44 -30
View File
@@ -247,14 +247,13 @@ FORCE_INLINE void _draw_centered_temp(const celsius_t temp, const uint8_t tx, co
const celsius_t temp = thermalManager.wholeDegHotend(heater_id),
target = thermalManager.degTargetHotend(heater_id);
#if DISABLED(STATUS_HOTEND_ANIM)
#define STATIC_HOTEND true
#define HOTEND_DOT isHeat
#else
#define STATIC_HOTEND false
#define HOTEND_DOT false
#if ENABLED(STATUS_HEAT_POWER)
const uint16_t power = thermalManager.getHeaterPower(heater_id);
#endif
#define STATIC_HOTEND DISABLED(STATUS_HOTEND_ANIM)
#define HOTEND_DOT TERN(STATUS_HOTEND_ANIM, false, isHeat)
#if ENABLED(STATUS_HOTEND_NUMBERLESS)
#define OFF_BMP(N) TERN(STATUS_HOTEND_INVERTED, status_hotend_b_bmp, status_hotend_a_bmp)
#define ON_BMP(N) TERN(STATUS_HOTEND_INVERTED, status_hotend_a_bmp, status_hotend_b_bmp)
@@ -285,23 +284,34 @@ FORCE_INLINE void _draw_centered_temp(const celsius_t temp, const uint8_t tx, co
#define BAR_TALL (STATUS_HEATERS_HEIGHT - 2)
const float prop = target - 20,
perc = prop > 0 && temp >= 20 ? (temp - 20) / prop : 0;
uint8_t tall = uint8_t(perc * BAR_TALL + 0.5f);
NOMORE(tall, BAR_TALL);
// Draw hotend bitmap, either whole or split by the heating percent
const uint8_t hx = STATUS_HOTEND_X(heater_id),
bw = STATUS_HOTEND_BYTEWIDTH(heater_id);
#if ENABLED(STATUS_HEAT_PERCENT)
if (isHeat && tall <= BAR_TALL) {
#if ANY(STATUS_HEAT_PERCENT, STATUS_HEAT_POWER)
uint8_t tall = 0;
#if ENABLED(STATUS_HEAT_POWER)
// Rounded int. At least 1 pixel tall on minimal PWM.
tall = power ? (power >= 127 ? BAR_TALL : (uint16_t((uint8_t(power) * BAR_TALL) + 127U) / 128U)) : 0;
#elif ENABLED(STATUS_HEAT_PERCENT)
const float prop = target - 20,
perc = prop > 0 && temp >= 20 ? (temp - 20) / prop : 0;
tall = uint8_t(perc * BAR_TALL + 0.5f);
#endif
NOMORE(tall, BAR_TALL);
const bool draw_partial = isHeat && tall < BAR_TALL;
if (draw_partial) {
const uint8_t ph = STATUS_HEATERS_HEIGHT - 1 - tall;
u8g.drawBitmapP(hx, STATUS_HEATERS_Y, bw, ph, HOTEND_BITMAP(TERN(HAS_MMU, active_extruder, heater_id), false));
u8g.drawBitmapP(hx, STATUS_HEATERS_Y + ph, bw, tall + 1, HOTEND_BITMAP(TERN(HAS_MMU, active_extruder, heater_id), true) + ph * bw);
}
else
#else
constexpr bool draw_partial = false;
#endif
u8g.drawBitmapP(hx, STATUS_HEATERS_Y, bw, STATUS_HEATERS_HEIGHT, HOTEND_BITMAP(TERN(HAS_MMU, active_extruder, heater_id), isHeat));
if (!draw_partial)
u8g.drawBitmapP(hx, STATUS_HEATERS_Y, bw, STATUS_HEATERS_HEIGHT, HOTEND_BITMAP(TERN(HAS_MMU, active_extruder, heater_id), isHeat));
} // PAGE_CONTAINS
@@ -342,29 +352,31 @@ FORCE_INLINE void _draw_centered_temp(const celsius_t temp, const uint8_t tx, co
const celsius_t temp = thermalManager.wholeDegBed(),
target = thermalManager.degTargetBed();
#if ENABLED(STATUS_HEAT_PERCENT) || DISABLED(STATUS_BED_ANIM)
#if ANY(STATUS_HEAT_PERCENT, STATUS_HEAT_POWER) || DISABLED(STATUS_BED_ANIM)
const bool isHeat = BED_ALT();
#endif
#if DISABLED(STATUS_BED_ANIM)
#define STATIC_BED true
#define BED_DOT isHeat
#else
#define STATIC_BED false
#define BED_DOT false
#endif
#define STATIC_BED DISABLED(STATUS_BED_ANIM)
#define BED_DOT TERN(STATUS_BED_ANIM, false, isHeat)
if (PAGE_CONTAINS(STATUS_HEATERS_Y, STATUS_HEATERS_BOT)) {
#define BAR_TALL (STATUS_HEATERS_HEIGHT - 2)
const float prop = target - 20,
perc = prop > 0 && temp >= 20 ? (temp - 20) / prop : 0;
uint8_t tall = uint8_t(perc * BAR_TALL + 0.5f);
NOMORE(tall, BAR_TALL);
// Draw a heating progress bar, if specified
#if ENABLED(STATUS_HEAT_PERCENT)
#if ANY(STATUS_HEAT_PERCENT, STATUS_HEAT_POWER)
uint8_t tall = 0;
#if ENABLED(STATUS_HEAT_POWER)
const uint16_t power = thermalManager.getHeaterPower(H_BED);
tall = power ? (power >= 127) ? BAR_TALL : uint16_t((uint8_t(power) * BAR_TALL) + 127U) / 128U : 0;
#elif ENABLED(STATUS_HEAT_PERCENT)
const float prop = target - 20,
perc = prop > 0 && temp >= 20 ? (temp - 20) / prop : 0;
tall = uint8_t(perc * BAR_TALL + 0.5f);
#endif
NOMORE(tall, BAR_TALL);
if (isHeat) {
const uint8_t bx = STATUS_BED_X + STATUS_BED_WIDTH;
@@ -538,9 +550,11 @@ void MarlinUI::draw_status_screen() {
#if ANIM_HBCC
uint8_t new_bits = 0;
#if ANIM_HOTEND
HOTEND_LOOP() if (thermalManager.isHeatingHotend(e)) SBI(new_bits, DRAWBIT_HOTEND + e);
HOTEND_LOOP() if (thermalManager.TERN(STATUS_HEAT_POWER, getHeaterPower(heater_id_t(e)), isHeatingHotend(e))) SBI(new_bits, DRAWBIT_HOTEND + e);
#endif
#if ANIM_BED
if (TERN(STATUS_HEAT_POWER, (thermalManager.degTargetBed() || thermalManager.getHeaterPower(H_BED)), thermalManager.isHeatingBed())) SBI(new_bits, DRAWBIT_BED);
#endif
if (TERN0(ANIM_BED, thermalManager.isHeatingBed())) SBI(new_bits, DRAWBIT_BED);
#if DO_DRAW_CHAMBER && HAS_HEATED_CHAMBER
if (thermalManager.isHeatingChamber()) SBI(new_bits, DRAWBIT_CHAMBER);
#endif
+2 -2
View File
@@ -121,8 +121,8 @@ static font_group_t g_fontgroup_root = { nullptr, 0 };
*/
static inline bool uxg_Utf8FontIsInited() { return flag_fontgroup_was_inited; }
int uxg_SetUtf8Fonts (const uxg_fontinfo_t * fntinfo, int number) {
flag_fontgroup_was_inited = 1;
int uxg_SetUtf8Fonts(const uxg_fontinfo_t *fntinfo, int number) {
flag_fontgroup_was_inited = true;
return fontgroup_init(&g_fontgroup_root, fntinfo, number);
}
+1 -1
View File
@@ -317,7 +317,7 @@ void dwinDrawFloatValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t
//uint8_t *fvalue = (uint8_t*)&value;
size_t i = 0;
#if DISABLED(DWIN_CREALITY_LCD_JYERSUI)
dwinDrawRectangle(1, bColor, x, y, x + fontWidth(size) * (iNum+fNum+1), y + fontHeight(size));
dwinDrawRectangle(1, bColor, x, y, x + fontWidth(size) * (iNum + fNum + 1), y + fontHeight(size));
#endif
dwinByte(i, 0x14);
dwinByte(i, (bShow * 0x80) | (zeroFill * 0x20) | (zeroMode * 0x10) | size);
+6
View File
@@ -145,3 +145,9 @@
#define ICON_ProbeOffsetZ ICON_StepZ
#define ICON_PIDNozzle ICON_SetEndTemp
#define ICON_PIDbed ICON_SetBedTemp
#define ICON_FWRetract ICON_StepE
#define ICON_FWRetLength ICON_StepE
#define ICON_FWRetSpeed ICON_Setspeed
#define ICON_FWRetZRaise ICON_MoveZ
#define ICON_FWRecSpeed ICON_Setspeed
#define ICON_FWRecExtra ICON_StepE
+15 -3
View File
@@ -87,7 +87,13 @@ EncoderState encoderReceiveAnalyze() {
#if PIN_EXISTS(LCD_LED)
//LED_Action();
#endif
if (!ui.backlight) ui.refresh_brightness();
#if LCD_BACKLIGHT_TIMEOUT_MINS
ui.refresh_backlight_timeout();
#endif
if (!ui.backlight) {
ui.refresh_brightness();
return ENCODER_DIFF_NO;
}
const bool was_waiting = wait_for_user;
wait_for_user = false;
return was_waiting ? ENCODER_DIFF_NO : ENCODER_DIFF_ENTER;
@@ -154,6 +160,12 @@ EncoderState encoderReceiveAnalyze() {
temp_diff = 0;
}
if (temp_diffState != ENCODER_DIFF_NO) {
#if LCD_BACKLIGHT_TIMEOUT_MINS
ui.refresh_backlight_timeout();
#endif
if (!ui.backlight) ui.refresh_brightness();
}
return temp_diffState;
}
@@ -164,9 +176,9 @@ EncoderState encoderReceiveAnalyze() {
// LED light operation
void LED_Action() {
LED_Control(RGB_SCALE_WARM_WHITE,0x0F);
LED_Control(RGB_SCALE_WARM_WHITE, 0x0F);
delay(30);
LED_Control(RGB_SCALE_WARM_WHITE,0x00);
LED_Control(RGB_SCALE_WARM_WHITE, 0x00);
}
// LED initialization
+1 -1
View File
@@ -1384,7 +1384,7 @@ void hmiMoveDone(const AxisEnum axis) {
dwinUpdateLCD();
return;
}
LIMIT(hmiValues.offset_value, (Z_PROBE_OFFSET_RANGE_MIN) * 100, (Z_PROBE_OFFSET_RANGE_MAX) * 100);
LIMIT(hmiValues.offset_value, (PROBE_OFFSET_ZMIN) * 100, (PROBE_OFFSET_ZMAX) * 100);
last_zoffset = dwin_zoffset;
dwin_zoffset = hmiValues.offset_value / 100.0f;
#if ANY(BABYSTEP_ZPROBE_OFFSET, JUST_BABYSTEP)
File diff suppressed because it is too large Load Diff
+2 -3
View File
@@ -83,6 +83,7 @@ enum menuID : uint8_t {
ID_Preheat,
ID_ChangeFilament,
ID_MenuCustom,
OPTITEM(FWRETRACT, ID_FWMenu)
ID_Control,
ID_TempMenu,
ID_PID,
@@ -105,9 +106,7 @@ enum menuID : uint8_t {
ID_ColorSettings,
ID_Advanced,
ID_ProbeMenu,
#if HAS_TRINAMIC_CONFIG
ID_TMCMenu,
#endif
OPTITEM(HAS_TRINAMIC_CONFIG, ID_TMCMenu)
ID_Info,
ID_Leveling,
ID_LevelManual,
+93 -80
View File
@@ -308,103 +308,116 @@ void MarlinUI::draw_status_message(const bool blink) {
void MenuItem_static::draw(const uint8_t row, FSTR_P const ftpl, const uint8_t style/*=SS_DEFAULT*/, const char *vstr/*=nullptr*/) {
// Call mark_as_selected to draw a bigger selection box
// and draw the text without a background
if (mark_as_selected(row, (bool)(style & SS_INVERT), true)) {
ui.set_font(DWIN_FONT_MENU);
dwin_font.solid = false;
dwin_font.fg = COLOR_WHITE;
if (!mark_as_selected(row, (bool)(style & SS_INVERT), true)) return;
dwin_string.set();
ui.set_font(DWIN_FONT_MENU);
dwin_font.solid = false;
dwin_font.fg = COLOR_WHITE;
const bool center = bool(style & SS_CENTER), full = bool(style & SS_FULL);
const int8_t plen = ftpl ? utf8_strlen(ftpl) : 0,
vlen = vstr ? utf8_strlen(vstr) : 0;
int8_t pad = (center || full) ? (LCD_WIDTH) - 1 - plen - vlen : 0;
dwin_string.set();
// SS_CENTER: Pad with half of the unused space first
if (center) for (int8_t lpad = pad / 2; lpad > 0; --lpad) dwin_string.add(' ');
const bool center = bool(style & SS_CENTER), full = bool(style & SS_FULL);
int8_t plen = ftpl ? utf8_strlen(ftpl) : 0;
const int8_t olen = plen;
// Append the templated label string
if (plen) {
dwin_string.add(ftpl, itemIndex, itemStringC, itemStringF);
pad -= dwin_string.length - plen;
}
// Value length, if any
int8_t vlen = vstr ? utf8_strlen(vstr) : 0;
// SS_FULL: Pad with enough space to justify the value
if (vlen) {
if (full && !center) {
// Move the leading colon from the value to the label
if (*vstr == ':') { dwin_string.add(':'); vstr++; }
// Move spaces to the padding
while (*vstr == ' ') { vstr++; pad++; }
// Pad in-between
for (; pad > 0; --pad) dwin_string.add(' ');
}
// Append the value
dwin_string.add(vstr);
}
// SS_CENTER: Pad the rest of the string
if (center) for (int8_t rpad = pad - (pad / 2); rpad > 0; --rpad) dwin_string.add(' ');
lcd_moveto(1, row);
lcd_put_dwin_string();
bool mv_colon = false;
if (vlen) {
// Move the leading colon from the value to the label below
mv_colon = (*vstr == ':');
// Shorter value, wider label
if (mv_colon) { vstr++; vlen--; plen++; }
// Remove leading spaces from the value and shorten
while (*vstr == ' ') { vstr++; vlen--; }
}
int8_t pad = (center || full) ? (LCD_WIDTH) - 1 - plen - vlen : 0;
// SS_CENTER: Pad with half of the unused space first
if (center) for (int8_t lpad = pad / 2; lpad > 0; --lpad, --pad) dwin_string.add(' ');
if (plen) {
// Append the templated label string
dwin_string.add(ftpl, itemIndex, itemStringC, itemStringF);
// Remove padding if the string was expanded
pad -= dwin_string.length - olen;
}
// SS_FULL: Pad with enough space to justify the value
if (vlen) {
if (full && !center) {
// Append the leading colon moved from the value to the label
if (mv_colon) dwin_string.add(':');
// Pad in-between
for (; pad > 0; --pad) dwin_string.add(' ');
}
// Append the value
dwin_string.add(vstr);
}
// SS_CENTER: Pad the rest of the string
if (center) while (pad--) dwin_string.add(' ');
lcd_moveto(1, row);
lcd_put_dwin_string();
}
// Draw a generic menu item
void MenuItemBase::_draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char, const char post_char) {
if (mark_as_selected(row, sel)) {
ui.set_font(DWIN_FONT_MENU);
dwin_font.solid = false;
dwin_font.fg = COLOR_WHITE;
if (!mark_as_selected(row, sel)) return;
dwin_string.set(ftpl, itemIndex, itemStringC, itemStringF);
ui.set_font(DWIN_FONT_MENU);
dwin_font.solid = false;
dwin_font.fg = COLOR_WHITE;
pixel_len_t n = LCD_WIDTH - 1 - dwin_string.length;
while (--n > 1) dwin_string.add(' ');
dwin_string.set(ftpl, itemIndex, itemStringC, itemStringF);
dwin_string.add(post_char);
pixel_len_t n = LCD_WIDTH - 1 - dwin_string.length;
while (--n > 1) dwin_string.add(' ');
lcd_moveto(1, row);
lcd_put_dwin_string();
}
dwin_string.add(post_char);
lcd_moveto(1, row);
lcd_put_dwin_string();
}
//
// Draw a menu item with an editable value
//
void MenuEditItemBase::draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char * const inStr, const bool pgm) {
if (mark_as_selected(row, sel)) {
ui.set_font(DWIN_FONT_MENU);
dwin_font.solid = false;
dwin_font.fg = COLOR_WHITE;
if (!mark_as_selected(row, sel)) return;
const uint8_t vallen = (pgm ? utf8_strlen_P(inStr) : utf8_strlen(S(inStr)));
ui.set_font(DWIN_FONT_MENU);
dwin_font.solid = false;
dwin_font.fg = COLOR_WHITE;
dwin_string.set(ftpl, itemIndex, itemStringC, itemStringF);
if (vallen) dwin_string.add(':');
const uint8_t vallen = (pgm ? utf8_strlen_P(inStr) : utf8_strlen(S(inStr)));
lcd_moveto(1, row);
dwin_string.set(ftpl, itemIndex, itemStringC, itemStringF);
if (vallen) dwin_string.add(':');
lcd_moveto(1, row);
lcd_put_dwin_string();
if (vallen) {
dwin_font.fg = COLOR_YELLOW;
dwin_string.set(inStr);
lcd_moveto(LCD_WIDTH - vallen - 1, row);
lcd_put_dwin_string();
if (vallen) {
dwin_font.fg = COLOR_YELLOW;
dwin_string.set(inStr);
lcd_moveto(LCD_WIDTH - vallen - 1, row);
lcd_put_dwin_string();
}
}
}
//
// Draw an edit screen with label and current value
//
void MenuEditItemBase::draw_edit_screen(FSTR_P const fstr, const char* const value/*=nullptr*/) {
void MenuEditItemBase::draw_edit_screen(FSTR_P const ftpl, const char* const value/*=nullptr*/) {
ui.encoder_direction_normal();
const dwin_coord_t labellen = utf8_strlen(fstr), vallen = utf8_strlen(value);
const dwin_coord_t labellen = utf8_strlen(ftpl), vallen = utf8_strlen(value);
dwin_string.set(FTOP(fstr), itemIndex);
dwin_string.set(FTOP(ftpl), itemIndex);
if (vallen) dwin_string.add(':'); // If a value is included, add a colon
// Assume the label is alpha-numeric (with a descender)
@@ -422,7 +435,7 @@ void MarlinUI::draw_status_message(const bool blink) {
const dwin_coord_t by = (row * MENU_LINE_HEIGHT) + MENU_FONT_HEIGHT + EXTRA_ROW_HEIGHT / 2;
dwinDrawString(true, font16x32, COLOR_YELLOW, COLOR_BG_BLACK, (LCD_PIXEL_WIDTH - vallen * 16) / 2, by, S(dwin_string.string()));
if (ui.can_show_slider()) {
if (ui.can_show_slider() && maxEditValue > 0) {
const dwin_coord_t slider_length = LCD_PIXEL_WIDTH - TERN(DWIN_MARLINUI_LANDSCAPE, 120, 20),
slider_height = 16,
@@ -440,7 +453,7 @@ void MarlinUI::draw_status_message(const bool blink) {
}
inline void draw_boxed_string(const bool yesopt, FSTR_P const fstr, const bool inv) {
const uint8_t len = utf8_strlen(fstr),
const uint8_t len = utf8_strlen_P(FTOP(fstr)),
mar = TERN(DWIN_MARLINUI_PORTRAIT, 1, 4),
col = yesopt ? LCD_WIDTH - mar - len : mar,
row = (LCD_HEIGHT >= 8 ? LCD_HEIGHT / 2 + 3 : LCD_HEIGHT - 1);
@@ -451,12 +464,12 @@ void MarlinUI::draw_status_message(const bool blink) {
void MenuItem_confirm::draw_select_screen(
FSTR_P const yes, FSTR_P const no, const bool yesno,
FSTR_P const pref, const char * const string/*=nullptr*/, FSTR_P const suff/*=nullptr*/
FSTR_P const fpre, const char * const string/*=nullptr*/, FSTR_P const fsuf/*=nullptr*/
) {
ui.set_font(DWIN_FONT_MENU);
dwin_font.solid = false;
dwin_font.fg = COLOR_WHITE;
ui.draw_select_screen_prompt(pref, string, suff);
ui.draw_select_screen_prompt(fpre, string, fsuf);
if (no) draw_boxed_string(false, no, !yesno);
if (yes) draw_boxed_string(true, yes, yesno);
}
@@ -464,21 +477,21 @@ void MarlinUI::draw_status_message(const bool blink) {
#if HAS_MEDIA
void MenuItem_sdbase::draw(const bool sel, const uint8_t row, FSTR_P const, CardReader &theCard, const bool isDir) {
if (mark_as_selected(row, sel)) {
dwin_string.set();
if (!mark_as_selected(row, sel)) return;
uint8_t maxlen = LCD_WIDTH - 1;
if (isDir) {
dwin_string.add(LCD_STR_FOLDER " ");
maxlen -= 2;
}
dwin_string.set();
dwin_string.add(ui.scrolled_filename(theCard, maxlen, row, sel), maxlen);
uint8_t n = maxlen - dwin_string.length;
while (n > 0) { dwin_string.add(' '); --n; }
lcd_moveto(1, row);
lcd_put_dwin_string();
uint8_t maxlen = LCD_WIDTH - 1;
if (isDir) {
dwin_string.add(LCD_STR_FOLDER " ");
maxlen -= 2;
}
dwin_string.add(ui.scrolled_filename(theCard, maxlen, row, sel), maxlen);
uint8_t n = maxlen - dwin_string.length;
while (n > 0) { dwin_string.add(' '); --n; }
lcd_moveto(1, row);
lcd_put_dwin_string();
}
#endif // HAS_MEDIA
@@ -8,9 +8,7 @@
* Changed unsigned int to uint16_t for use in the professional Ender-3V2/S1 firmware
* Url: https://www.arduino.cc/reference/en/libraries/base64/
*/
#ifndef BASE64_H_INCLUDED
#define BASE64_H_INCLUDED
#pragma once
/* binary_to_base64:
* Description:
@@ -135,11 +133,11 @@ uint16_t decode_base64_length(unsigned char input[], uint16_t input_length) {
}
input_length = input - start;
return input_length/4*3 + (input_length % 4 ? input_length % 4 - 1 : 0);
return input_length / 4 * 3 + (input_length % 4 ? input_length % 4 - 1 : 0);
}
uint16_t encode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]) {
uint16_t full_sets = input_length/3;
uint16_t full_sets = input_length / 3;
// While there are still full sets of 24 bits...
for (uint16_t i = 0; i < full_sets; ++i) {
@@ -152,7 +150,7 @@ uint16_t encode_base64(unsigned char input[], uint16_t input_length, unsigned ch
output += 4;
}
switch(input_length % 3) {
switch (input_length % 3) {
case 0:
output[0] = '\0';
break;
@@ -192,7 +190,7 @@ uint16_t decode_base64(unsigned char input[], uint16_t input_length, unsigned ch
output += 3;
}
switch(output_length % 3) {
switch (output_length % 3) {
case 1:
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
break;
@@ -204,5 +202,3 @@ uint16_t decode_base64(unsigned char input[], uint16_t input_length, unsigned ch
return output_length;
}
#endif // ifndef
+17 -31
View File
@@ -66,7 +66,6 @@
BedLevelTools bedLevelTools;
#if ENABLED(USE_GRID_MESHVIEWER)
bool BedLevelTools::viewer_asymmetric_range = false;
bool BedLevelTools::viewer_print_value = false;
#endif
bool BedLevelTools::goto_mesh_value = false;
@@ -186,20 +185,14 @@ void BedLevelTools::meshReset() {
// Accessors
float BedLevelTools::getMaxValue() {
float max = __FLT_MAX__ * -1;
GRID_LOOP(x, y) {
if (!isnan(bedlevel.z_values[x][y]) && bedlevel.z_values[x][y] > max)
max = bedlevel.z_values[x][y];
}
float max = -(__FLT_MAX__);
GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOLESS(max, z); }
return max;
}
float BedLevelTools::getMinValue() {
float min = __FLT_MAX__;
GRID_LOOP(x, y) {
if (!isnan(bedlevel.z_values[x][y]) && bedlevel.z_values[x][y] < min)
min = bedlevel.z_values[x][y];
}
GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOMORE(min, z); }
return min;
}
@@ -221,7 +214,7 @@ bool BedLevelTools::meshValidate() {
const uint16_t total_width_px = DWIN_WIDTH - padding_x - padding_x;
const uint16_t cell_width_px = total_width_px / (GRID_MAX_POINTS_X);
const uint16_t cell_height_px = total_width_px / (GRID_MAX_POINTS_Y);
const float v_max = abs(getMaxValue()), v_min = abs(getMinValue()), range = _MAX(v_min, v_max);
const float v_max = abs(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max);
// Clear background from previous selection and select new square
dwinDrawRectangle(1, COLOR_BG_BLACK, _MAX(0, padding_x - gridline_width), _MAX(0, padding_y_top - gridline_width), padding_x + total_width_px, padding_y_top + total_width_px);
@@ -242,8 +235,8 @@ bool BedLevelTools::meshValidate() {
dwinDrawRectangle(1, // RGB565 colors: http://www.barth-dev.de/online/rgb565-color-picker/
isnan(bedlevel.z_values[x][y]) ? COLOR_GREY : ( // gray if undefined
(bedlevel.z_values[x][y] < 0 ?
(uint16_t)round(0x1F * -bedlevel.z_values[x][y] / (!viewer_asymmetric_range ? range : v_min)) << 11 : // red if mesh point value is negative
(uint16_t)round(0x3F * bedlevel.z_values[x][y] / (!viewer_asymmetric_range ? range : v_max)) << 5) | // green if mesh point value is positive
(uint16_t)round(0x1F * -bedlevel.z_values[x][y] / rmax) << 11 : // red if mesh point value is negative
(uint16_t)round(0x3F * bedlevel.z_values[x][y] / rmax) << 5) | // green if mesh point value is positive
_MIN(0x1F, (((uint8_t)abs(bedlevel.z_values[x][y]) / 10) * 4))), // + blue stepping for every mm
start_x_px, start_y_px, end_x_px, end_y_px
);
@@ -252,7 +245,6 @@ bool BedLevelTools::meshValidate() {
LCD_SERIAL.flushTX();
// Draw value text on
char buf[8];
const uint8_t fs = DWINUI::fontWidth(meshfont);
if (viewer_print_value) {
int8_t offset_x, offset_y = cell_height_px / 2 - fs;
@@ -260,14 +252,15 @@ bool BedLevelTools::meshValidate() {
dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset_y, F("X"));
}
else { // has value
if (GRID_MAX_POINTS_X < (ENABLED(TJC_DISPLAY) ? 8 : 10))
sprintf_P(buf, PSTR("%s"), dtostrf(abs(bedlevel.z_values[x][y]), 1, 2, str_1));
MString<12> msg;
if ((GRID_MAX_POINTS_X) < TERN(TJC_DISPLAY, 8, 10))
msg.set(p_float_t(abs(bedlevel.z_values[x][y]), 2));
else
sprintf_P(buf, PSTR("%02i"), (uint16_t)(abs(bedlevel.z_values[x][y] - (int16_t)bedlevel.z_values[x][y]) * 100));
offset_x = cell_width_px / 2 - (fs/2) * (strlen(buf)) - 2;
if (!(GRID_MAX_POINTS_X < (ENABLED(TJC_DISPLAY) ? 8 : 10)))
msg.setf(F("%02i"), uint16_t(abs(bedlevel.z_values[x][y] - int16_t(bedlevel.z_values[x][y])) * 100));
offset_x = cell_width_px / 2 - (fs / 2) * msg.length() - 2;
if ((GRID_MAX_POINTS_X) >= TERN(TJC_DISPLAY, 8, 10))
dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px - 2 + offset_x, start_y_px + offset_y, F("."));
dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + 1 + offset_x, start_y_px + offset_y, buf);
dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + 1 + offset_x, start_y_px + offset_y, msg);
}
safe_delay(10);
LCD_SERIAL.flushTX();
@@ -276,17 +269,10 @@ bool BedLevelTools::meshValidate() {
}
void BedLevelTools::setMeshViewerStatus() { // TODO: draw gradient with values as a legend instead
float v_max = abs(getMaxValue()), v_min = abs(getMinValue()), range = _MAX(v_min, v_max);
if (v_min > 3e+10f) v_min = 0.0000001;
if (v_max > 3e+10f) v_max = 0.0000001;
if (range > 3e+10f) range = 0.0000001;
ui.set_status(
&MString<45>(
F("Red "), p_float_t(viewer_asymmetric_range ? -v_min : -range, 3),
F("..0.."), p_float_t(viewer_asymmetric_range ? v_max : range, 3),
F(" Green")
)
);
float v_max = abs(getMaxValue()), v_min = abs(getMinValue()), rmax = _MAX(v_min, v_max), rmin = _MIN(v_min, v_max);
if (rmax > 3e+10f) rmax = 0.0000001;
if (rmin > 3e+10f) rmin = 0.0000001;
ui.set_status(&MString<47>(F("Red "), p_float_t(-rmax, 3), F("..0.."), p_float_t(rmin, 3), F(" Green")));
drawing_mesh = false;
}
+94 -66
View File
@@ -161,8 +161,8 @@
#define MIN_BEDTEMP 0
#define MAX_BEDTEMP BED_MAX_TARGET
#define DWIN_VAR_UPDATE_INTERVAL 1024
#define DWIN_UPDATE_INTERVAL 1024
#define DWIN_VAR_UPDATE_INTERVAL 500
#define DWIN_UPDATE_INTERVAL 1000
#if HAS_MESH && HAS_BED_PROBE
#define BABY_Z_VAR probe.offset.z
@@ -214,13 +214,13 @@ Menu *prepareMenu = nullptr;
Menu *trammingMenu = nullptr;
#endif
Menu *moveMenu = nullptr;
Menu *ControlMenu = nullptr;
Menu *AdvancedSettings = nullptr;
Menu *controlMenu = nullptr;
Menu *advancedSettingsMenu = nullptr;
#if HAS_HOME_OFFSET
Menu *homeOffsetMenu = nullptr;
#endif
#if HAS_BED_PROBE
Menu *ProbeSetMenu = nullptr;
Menu *probeSettingsMenu = nullptr;
#endif
Menu *filSetMenu = nullptr;
Menu *selectColorMenu = nullptr;
@@ -229,7 +229,7 @@ Menu *tuneMenu = nullptr;
Menu *motionMenu = nullptr;
Menu *filamentMenu = nullptr;
#if ENABLED(MESH_BED_LEVELING)
Menu *manualMesh = nullptr;
Menu *manualMeshMenu = nullptr;
#endif
#if HAS_PREHEAT
Menu *preheatMenu = nullptr;
@@ -251,7 +251,7 @@ Menu *stepsMenu = nullptr;
#if ENABLED(PIDTEMPBED) && ANY(PID_EDIT_MENU, PID_AUTOTUNE_MENU)
Menu *bedPIDMenu = nullptr;
#endif
#if ENABLED(CASELIGHT_USES_BRIGHTNESS)
#if CASELIGHT_USES_BRIGHTNESS
Menu *caseLightMenu = nullptr;
#endif
#if ENABLED(LED_CONTROL_MENU)
@@ -288,7 +288,7 @@ MenuItem *editZValueItem = nullptr;
bool isPrinting() { return printingIsActive() || printingIsPaused(); }
bool sdPrinting() { return isPrinting() && IS_SD_FILE_OPEN(); }
bool Host_Printing() { return isPrinting() && !IS_SD_FILE_OPEN(); }
bool hostPrinting() { return isPrinting() && !IS_SD_FILE_OPEN(); }
#define DWIN_LANGUAGE_EEPROM_ADDRESS 0x01 // Between 0x01 and 0x63 (EEPROM_OFFSET-1)
// BL24CXX::check() uses 0x00
@@ -634,9 +634,9 @@ void drawPrintDone() {
DWINUI::clearMainArea();
dwinPrintHeader(nullptr);
#if HAS_GCODE_PREVIEW
const bool haspreview = Preview_Valid();
const bool haspreview = preview.valid();
if (haspreview) {
Preview_Show();
preview.show();
DWINUI::drawButton(BTN_Continue, 86, 295);
}
#else
@@ -850,7 +850,7 @@ bool DWIN_lcd_sd_status = false;
#if ENABLED(MEDIASORT_MENU_ITEM)
void setMediaSort() {
toggleCheckboxLine(hmiData.mediaSort);
card.setSortOn(hmiData.mediaSort);
card.setSortOn(hmiData.mediaSort ? TERN(SDSORT_REVERSE, AS_REV, AS_FWD) : AS_OFF);
}
#endif
@@ -1253,6 +1253,13 @@ void eachMomentUpdate() {
static millis_t next_var_update_ms = 0, next_rts_update_ms = 0, next_status_update_ms = 0;
const millis_t ms = millis();
#if LCD_BACKLIGHT_TIMEOUT_MINS
if (ui.backlight_off_ms && ELAPSED(ms, ui.backlight_off_ms)) {
turnOffBacklight(); // Backlight off
ui.backlight_off_ms = 0;
}
#endif
if (ELAPSED(ms, next_var_update_ms)) {
next_var_update_ms = ms + DWIN_VAR_UPDATE_INTERVAL;
blink = !blink;
@@ -1276,7 +1283,7 @@ void eachMomentUpdate() {
#endif
if (ELAPSED(ms, next_status_update_ms)) {
next_status_update_ms = ms + 500;
next_status_update_ms = ms + DWIN_VAR_UPDATE_INTERVAL;
dwinDrawStatusMessage();
#if ENABLED(SCROLL_LONG_FILENAMES)
if (isMenu(fileMenu)) fileMenuIdle();
@@ -1675,7 +1682,7 @@ void dwinLevelingDone() {
// Started a Print Job
void dwinPrintStarted() {
TERN_(HAS_GCODE_PREVIEW, if (Host_Printing()) Preview_Invalidate());
TERN_(HAS_GCODE_PREVIEW, if (hostPrinting()) preview.invalidate());
TERN_(SET_PROGRESS_PERCENT, ui.progress_reset());
TERN_(SET_REMAINING_TIME, ui.reset_remaining_time());
hmiFlag.pause_flag = false;
@@ -1754,7 +1761,7 @@ void dwinSetDataDefaults() {
#endif
#if ENABLED(MEDIASORT_MENU_ITEM)
hmiData.mediaSort = true;
card.setSortOn(true);
card.setSortOn(TERN(SDSORT_REVERSE, AS_REV, AS_FWD));
#endif
hmiData.mediaAutoMount = ENABLED(HAS_SD_EXTENDER);
#if ALL(INDIVIDUAL_AXIS_HOMING_SUBMENU, MESH_BED_LEVELING)
@@ -1825,7 +1832,7 @@ void MarlinUI::refresh() { /* Nothing to see here */ }
void MarlinUI::_set_brightness() { dwinLCDBrightness(backlight ? brightness : 0); }
#endif
void MarlinUI::kill_screen(FSTR_P const lcd_error, FSTR_P const lcd_component) {
void MarlinUI::kill_screen(FSTR_P const lcd_error, FSTR_P const) {
dwinDrawPopup(ICON_BLTouch, GET_TEXT_F(MSG_PRINTER_KILLED), lcd_error);
DWINUI::drawCenteredString(hmiData.colorPopupTxt, 270, GET_TEXT_F(MSG_TURN_OFF));
dwinUpdateLCD();
@@ -1960,7 +1967,7 @@ void dwinRedrawScreen() {
void gotoConfirmToPrint() {
#if HAS_GCODE_PREVIEW
if (hmiData.enablePreview) return gotoPopup(Preview_DrawFromSD, onClickConfirmToPrint);
if (hmiData.enablePreview) return gotoPopup(preview.drawFromSD, onClickConfirmToPrint);
#endif
card.openAndPrintFile(card.filename); // Direct print SD file
}
@@ -2050,7 +2057,7 @@ void autoHome() { queue.inject_P(G28_STR); }
#if ANY(BABYSTEP_ZPROBE_OFFSET, JUST_BABYSTEP)
babystep.accum = round(planner.settings.axis_steps_per_mm[Z_AXIS] * BABY_Z_VAR);
#endif
setPFloatOnClick(Z_PROBE_OFFSET_RANGE_MIN, Z_PROBE_OFFSET_RANGE_MAX, 2, applyZOffset, liveZOffset);
setPFloatOnClick(PROBE_OFFSET_ZMIN, PROBE_OFFSET_ZMAX, 2, applyZOffset, liveZOffset);
}
void setMoveZto0() {
@@ -2152,9 +2159,10 @@ void setMoveZ() { hmiValue.axis = Z_AXIS; setPFloatOnClick(Z_MIN_POS, Z_MAX_POS,
toggleCheckboxLine(caselight.on);
caselight.update_enabled();
}
#if ENABLED(CASELIGHT_USES_BRIGHTNESS)
#if CASELIGHT_USES_BRIGHTNESS
bool enableLiveCaseLightBrightness = true;
void liveCaseLightBrightness() { caselight.brightness = menuData.value; caselight.update_brightness(); }
void setCaseLightBrightness() { setIntOnClick(0, 255, caselight.brightness, nullptr, liveCaseLightBrightness); }
void setCaseLightBrightness() { setIntOnClick(0, 255, caselight.brightness, liveCaseLightBrightness, enableLiveCaseLightBrightness ? liveCaseLightBrightness : nullptr); }
#endif
#endif
@@ -2166,10 +2174,12 @@ void setMoveZ() { hmiValue.axis = Z_AXIS; setPFloatOnClick(Z_MIN_POS, Z_MAX_POS,
}
#endif
#if HAS_COLOR_LEDS
bool enableLiveLedColor = true;
void applyLEDColor() {
hmiData.ledColor = LEDColor( {leds.color.r, leds.color.g, leds.color.b OPTARG(HAS_WHITE_LED, hmiData.ledColor.w) } );
if (!enableLiveLedColor) leds.update();
}
void liveLEDColor(uint8_t *color) { *color = menuData.value; leds.update(); }
void liveLEDColor(uint8_t *color) { *color = menuData.value; if (enableLiveLedColor) leds.update(); }
void liveLEDColorR() { liveLEDColor(&leds.color.r); }
void liveLEDColorG() { liveLEDColor(&leds.color.g); }
void liveLEDColorB() { liveLEDColor(&leds.color.b); }
@@ -2217,6 +2227,10 @@ void setMoveZ() { hmiValue.axis = Z_AXIS; setPFloatOnClick(Z_MIN_POS, Z_MAX_POS,
#endif
#if LCD_BACKLIGHT_TIMEOUT_MINS
void setTimer() { setPIntOnClick(ui.backlight_timeout_min, ui.backlight_timeout_max); }
#endif
#if HAS_FILAMENT_SENSOR
void setRunoutEnable() {
runout.reset();
@@ -2255,6 +2269,13 @@ void setSpeed() { setPIntOnClick(MIN_PRINT_SPEED, MAX_PRINT_SPEED); }
void setFanSpeed() { setIntOnClick(0, 255, thermalManager.fan_speed[0], applyFanSpeed); }
#endif
#if ENABLED(NOZZLE_PARK_FEATURE)
void parkHead() {
LCD_MESSAGE(MSG_FILAMENT_PARK_ENABLED);
queue.inject(F("G28O\nG27"));
}
#endif
#if ENABLED(ADVANCED_PAUSE_FEATURE)
void changeFilament() {
@@ -2262,13 +2283,6 @@ void setSpeed() { setPIntOnClick(MIN_PRINT_SPEED, MAX_PRINT_SPEED); }
queue.inject(F("M600 B2"));
}
#if ENABLED(NOZZLE_PARK_FEATURE)
void parkHead() {
LCD_MESSAGE(MSG_FILAMENT_PARK_ENABLED);
queue.inject(F("G28O\nG27"));
}
#endif
#if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES)
void unloadFilament() {
LCD_MESSAGE(MSG_FILAMENTUNLOAD);
@@ -2976,9 +2990,7 @@ void drawPrepareMenu() {
checkkey = ID_Menu;
if (SET_MENU_R(prepareMenu, selrect({133, 1, 28, 13}), MSG_PREPARE, 10 + PREHEAT_COUNT)) {
BACK_ITEM(gotoMainMenu);
#if ENABLED(ADVANCED_PAUSE_FEATURE)
MENU_ITEM(ICON_FilMan, MSG_FILAMENT_MAN, onDrawSubMenu, drawFilamentManMenu);
#endif
MENU_ITEM(ICON_FilMan, MSG_FILAMENT_MAN, onDrawSubMenu, drawFilamentManMenu);
MENU_ITEM(ICON_Axis, MSG_MOVE_AXIS, onDrawMoveSubMenu, drawMoveMenu);
#if ENABLED(LCD_BED_TRAMMING)
MENU_ITEM(ICON_Tram, MSG_BED_TRAMMING, onDrawSubMenu, drawTrammingMenu);
@@ -3039,35 +3051,37 @@ void drawPrepareMenu() {
void drawControlMenu() {
checkkey = ID_Menu;
if (SET_MENU_R(ControlMenu, selrect({103, 1, 28, 14}), MSG_CONTROL, 11)) {
if (SET_MENU_R(controlMenu, selrect({103, 1, 28, 14}), MSG_CONTROL, 11)) {
BACK_ITEM(gotoMainMenu);
MENU_ITEM(ICON_Temperature, MSG_TEMPERATURE, onDrawTempSubMenu, drawTemperatureMenu);
MENU_ITEM(ICON_Motion, MSG_MOTION, onDrawMotionSubMenu, drawMotionMenu);
#if ENABLED(EEPROM_SETTINGS)
MENU_ITEM(ICON_WriteEEPROM, MSG_STORE_EEPROM, onDrawWriteEeprom, writeEEPROM);
MENU_ITEM(ICON_ReadEEPROM, MSG_LOAD_EEPROM, onDrawReadEeprom, readEEPROM);
MENU_ITEM(ICON_ResumeEEPROM, MSG_RESTORE_DEFAULTS, onDrawResetEeprom, resetEEPROM);
#endif
MENU_ITEM(ICON_Reboot, MSG_RESET_PRINTER, onDrawMenuItem, rebootPrinter);
#if ENABLED(CASE_LIGHT_MENU)
#if ENABLED(CASELIGHT_USES_BRIGHTNESS)
#if CASELIGHT_USES_BRIGHTNESS
enableLiveCaseLightBrightness = true; // Allow live update of brightness in control menu
MENU_ITEM(ICON_CaseLight, MSG_CASE_LIGHT, onDrawSubMenu, drawCaseLightMenu);
#else
MENU_ITEM(ICON_CaseLight, MSG_CASE_LIGHT, onDrawChkbMenu, setCaseLight, &caselight.on);
#endif
#endif
#if ENABLED(LED_CONTROL_MENU)
enableLiveLedColor = true; // Allow live update of color in control menu
MENU_ITEM(ICON_LedControl, MSG_LED_CONTROL, onDrawSubMenu, drawLedControlMenu);
#endif
#if ENABLED(EEPROM_SETTINGS)
MENU_ITEM(ICON_WriteEEPROM, MSG_STORE_EEPROM, onDrawWriteEeprom, writeEEPROM);
MENU_ITEM(ICON_ReadEEPROM, MSG_LOAD_EEPROM, onDrawReadEeprom, readEEPROM);
MENU_ITEM(ICON_ResumeEEPROM, MSG_RESTORE_DEFAULTS, onDrawResetEeprom, resetEEPROM);
#endif
MENU_ITEM(ICON_Reboot, MSG_RESET_PRINTER, onDrawMenuItem, rebootPrinter);
MENU_ITEM(ICON_Info, MSG_INFO_SCREEN, onDrawInfoSubMenu, gotoInfoMenu);
}
ui.reset_status(true);
updateMenu(ControlMenu);
updateMenu(controlMenu);
}
void drawAdvancedSettingsMenu() {
checkkey = ID_Menu;
if (SET_MENU(AdvancedSettings, MSG_ADVANCED_SETTINGS, 23)) {
if (SET_MENU(advancedSettingsMenu, MSG_ADVANCED_SETTINGS, 24)) {
BACK_ITEM(gotoMainMenu);
#if ENABLED(EEPROM_SETTINGS)
MENU_ITEM(ICON_WriteEEPROM, MSG_STORE_EEPROM, onDrawMenuItem, writeEEPROM);
@@ -3104,6 +3118,9 @@ void drawAdvancedSettingsMenu() {
#if HAS_LOCKSCREEN
MENU_ITEM(ICON_Lock, MSG_LOCKSCREEN, onDrawMenuItem, dwinLockScreen);
#endif
#if LCD_BACKLIGHT_TIMEOUT_MINS
EDIT_ITEM(ICON_Brightness, MSG_SCREEN_TIMEOUT, onDrawPIntMenu, setTimer, &ui.backlight_timeout_minutes);
#endif
#if ENABLED(SOUND_MENU_ITEM)
EDIT_ITEM(ICON_Sound, MSG_SOUND_ENABLE, onDrawChkbMenu, setEnableSound, &ui.sound_on);
#endif
@@ -3129,7 +3146,7 @@ void drawAdvancedSettingsMenu() {
#endif
}
ui.reset_status(true);
updateMenu(AdvancedSettings);
updateMenu(advancedSettingsMenu);
}
void drawMoveMenu() {
@@ -3180,7 +3197,7 @@ void drawMoveMenu() {
void drawProbeSetMenu() {
checkkey = ID_Menu;
if (SET_MENU(ProbeSetMenu, MSG_ZPROBE_SETTINGS, 9)) {
if (SET_MENU(probeSettingsMenu, MSG_ZPROBE_SETTINGS, 9)) {
BACK_ITEM(drawAdvancedSettingsMenu);
#if HAS_X_AXIS
EDIT_ITEM(ICON_ProbeOffsetX, MSG_ZPROBE_XOFFSET, onDrawPFloatMenu, setProbeOffsetX, &probe.offset.x);
@@ -3203,7 +3220,7 @@ void drawMoveMenu() {
MENU_ITEM(ICON_ProbeTest, MSG_M48_TEST, onDrawMenuItem, probeTest);
#endif
}
updateMenu(ProbeSetMenu);
updateMenu(probeSettingsMenu);
}
#endif // HAS_BED_PROBE
@@ -3251,7 +3268,7 @@ void drawFilSetMenu() {
void drawLedControlMenu() {
checkkey = ID_Menu;
if (SET_MENU(ledControlMenu, MSG_LED_CONTROL, 10)) {
BACK_ITEM(drawControlMenu);
BACK_ITEM((currentMenu == tuneMenu) ? drawTuneMenu : drawControlMenu);
#if !ALL(CASE_LIGHT_MENU, CASE_LIGHT_USE_NEOPIXEL)
EDIT_ITEM(ICON_LedControl, MSG_LEDS, onDrawChkbMenu, setLedStatus, &leds.lights_on);
#endif
@@ -3282,7 +3299,7 @@ void drawFilSetMenu() {
void drawTuneMenu() {
checkkey = ID_Menu;
if (SET_MENU_R(tuneMenu, selrect({73, 2, 28, 12}), MSG_TUNE, 17)) {
if (SET_MENU_R(tuneMenu, selrect({73, 2, 28, 12}), MSG_TUNE, 18)) {
BACK_ITEM(gotoPrintProcess);
EDIT_ITEM(ICON_Speed, MSG_SPEED, onDrawSpeedItem, setSpeed, &feedrate_percentage);
#if HAS_HOTEND
@@ -3325,8 +3342,21 @@ void drawTuneMenu() {
EDIT_ITEM(ICON_Brightness, MSG_BRIGHTNESS, onDrawPInt8Menu, setBrightness, &ui.brightness);
MENU_ITEM(ICON_Brightness, MSG_BRIGHTNESS_OFF, onDrawMenuItem, turnOffBacklight);
#endif
#if LCD_BACKLIGHT_TIMEOUT_MINS
EDIT_ITEM(ICON_Brightness, MSG_SCREEN_TIMEOUT, onDrawPIntMenu, setTimer, &ui.backlight_timeout_minutes);
#endif
#if ENABLED(CASE_LIGHT_MENU)
EDIT_ITEM(ICON_CaseLight, MSG_CASE_LIGHT, onDrawChkbMenu, setCaseLight, &caselight.on);
#if CASELIGHT_USES_BRIGHTNESS
// Avoid heavy interference with print job disabling live update of brightness in tune menu
enableLiveCaseLightBrightness = false;
EDIT_ITEM(ICON_Brightness, MSG_CASE_LIGHT_BRIGHTNESS, onDrawPInt8Menu, setCaseLightBrightness, &caselight.brightness);
#endif
#if ENABLED(LED_CONTROL_MENU)
// Avoid heavy interference with print job disabling live update of color in tune menu
enableLiveLedColor = false;
MENU_ITEM(ICON_LedControl, MSG_LED_CONTROL, onDrawSubMenu, drawLedControlMenu);
#endif
#elif ENABLED(LED_CONTROL_MENU) && DISABLED(CASE_LIGHT_USE_NEOPIXEL)
EDIT_ITEM(ICON_LedControl, MSG_LEDS, onDrawChkbMenu, setLedStatus, &leds.lights_on);
#endif
@@ -3437,9 +3467,7 @@ void drawMotionMenu() {
updateMenu(motionMenu);
}
#if ENABLED(ADVANCED_PAUSE_FEATURE)
#if HAS_PREHEAT
#if ALL(ADVANCED_PAUSE_FEATURE, HAS_PREHEAT)
void drawPreheatHotendMenu() {
checkkey = ID_Menu;
@@ -3451,34 +3479,34 @@ void drawMotionMenu() {
updateMenu(preheatHotendMenu);
}
#endif
#endif
void drawFilamentManMenu() {
checkkey = ID_Menu;
if (SET_MENU(filamentMenu, MSG_FILAMENT_MAN, 6)) {
BACK_ITEM(drawPrepareMenu);
#if ENABLED(NOZZLE_PARK_FEATURE)
MENU_ITEM(ICON_Park, MSG_FILAMENT_PARK_ENABLED, onDrawMenuItem, parkHead);
#endif
void drawFilamentManMenu() {
checkkey = ID_Menu;
if (SET_MENU(filamentMenu, MSG_FILAMENT_MAN, 6)) {
BACK_ITEM(drawPrepareMenu);
#if ENABLED(NOZZLE_PARK_FEATURE)
MENU_ITEM(ICON_Park, MSG_FILAMENT_PARK_ENABLED, onDrawMenuItem, parkHead);
#endif
#if ENABLED(ADVANCED_PAUSE_FEATURE)
#if HAS_PREHEAT
MENU_ITEM(ICON_SetEndTemp, MSG_PREHEAT_HOTEND, onDrawSubMenu, drawPreheatHotendMenu);
#endif
MENU_ITEM(ICON_FilMan, MSG_FILAMENTCHANGE, onDrawMenuItem, changeFilament);
#if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES)
MENU_ITEM(ICON_FilUnload, MSG_FILAMENTUNLOAD, onDrawMenuItem, unloadFilament);
MENU_ITEM(ICON_FilLoad, MSG_FILAMENTLOAD, onDrawMenuItem, loadFilament);
#endif
}
updateMenu(filamentMenu);
#endif
#if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES)
MENU_ITEM(ICON_FilUnload, MSG_FILAMENTUNLOAD, onDrawMenuItem, unloadFilament);
MENU_ITEM(ICON_FilLoad, MSG_FILAMENTLOAD, onDrawMenuItem, loadFilament);
#endif
}
#endif
updateMenu(filamentMenu);
}
#if ENABLED(MESH_BED_LEVELING)
void drawManualMeshMenu() {
checkkey = ID_Menu;
if (SET_MENU(manualMesh, MSG_UBL_MANUAL_MESH, 6)) {
if (SET_MENU(manualMeshMenu, MSG_UBL_MANUAL_MESH, 6)) {
BACK_ITEM(drawPrepareMenu);
MENU_ITEM(ICON_ManualMesh, MSG_LEVEL_BED, onDrawMenuItem, manualMeshStart);
mMeshMoveZItem = EDIT_ITEM(ICON_Zoffset, MSG_MOVE_Z, onDrawMMeshMoveZ, setMMeshMoveZ, &current_position.z);
@@ -3486,7 +3514,7 @@ void drawMotionMenu() {
MENU_ITEM(ICON_MeshViewer, MSG_MESH_VIEW, onDrawSubMenu, dwinMeshViewer);
MENU_ITEM(ICON_MeshSave, MSG_UBL_SAVE_MESH, onDrawMenuItem, manualMeshSave);
}
updateMenu(manualMesh);
updateMenu(manualMeshMenu);
}
#endif // MESH_BED_LEVELING
+4 -3
View File
@@ -35,6 +35,9 @@
#include "../common/encoder.h"
#include "../common/limits.h"
#include "../../../libs/BL24CXX.h"
#if ENABLED(LED_CONTROL_MENU)
#include "../../../feature/leds/leds.h"
#endif
#if ANY(BABYSTEPPING, HAS_BED_PROBE)
#define HAS_ZOFFSET_ITEM 1
@@ -318,9 +321,7 @@ void drawFilSetMenu();
#endif
void drawTuneMenu();
void drawMotionMenu();
#if ENABLED(ADVANCED_PAUSE_FEATURE)
void drawFilamentManMenu();
#endif
void drawFilamentManMenu();
#if ENABLED(MESH_BED_LEVELING)
void drawManualMeshMenu();
#endif
+1 -1
View File
@@ -66,7 +66,7 @@
#if ALL(LED_CONTROL_MENU, HAS_COLOR_LEDS)
#define defColorLeds LEDColorWhite()
#endif
#if ENABLED(CASELIGHT_USES_BRIGHTNESS)
#if CASELIGHT_USES_BRIGHTNESS
#define defCaseLightBrightness 255
#endif
#ifdef Z_AFTER_HOMING
+15 -25
View File
@@ -263,7 +263,7 @@ void DWINUI::drawCircle(uint16_t color, uint16_t x, uint16_t y, uint8_t r) {
// x: the abscissa of the center of the circle
// y: ordinate of the center of the circle
// r: circle radius
void DWINUI::drawFillCircle(uint16_t bcolor, uint16_t x,uint16_t y,uint8_t r) {
void DWINUI::drawFillCircle(uint16_t bcolor, uint16_t x, uint16_t y, uint8_t r) {
dwinDrawLine(bcolor, x - r, y, x + r, y);
uint16_t b = 1;
while (b <= r) {
@@ -280,12 +280,12 @@ void DWINUI::drawFillCircle(uint16_t bcolor, uint16_t x,uint16_t y,uint8_t r) {
// maxv : Maximum value
// color1 : Start color
// color2 : End color
uint16_t DWINUI::ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2) {
uint16_t DWINUI::colorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2) {
uint8_t B, G, R;
const float n = float(val - minv) / (maxv - minv);
R = (1 - n) * GetRColor(color1) + n * GetRColor(color2);
G = (1 - n) * GetGColor(color1) + n * GetGColor(color2);
B = (1 - n) * GetBColor(color1) + n * GetBColor(color2);
const float n = float(val - minv) / (maxv - minv + 1);
R = (1.0f - n) * GetRColor(color1) + n * GetRColor(color2);
G = (1.0f - n) * GetGColor(color1) + n * GetGColor(color2);
B = (1.0f - n) * GetBColor(color1) + n * GetBColor(color2);
return RGB(R, G, B);
}
@@ -293,27 +293,17 @@ uint16_t DWINUI::ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t colo
// val : Interpolator minv..maxv
// minv : Minimum value
// maxv : Maximum value
uint16_t DWINUI::RainbowInt(int16_t val, int16_t minv, int16_t maxv) {
uint8_t B, G, R;
const uint8_t maxB = 28, maxR = 28, maxG = 38;
uint16_t DWINUI::rainbowInt(int16_t val, int16_t minv, int16_t maxv) {
const int16_t limv = _MAX(abs(minv), abs(maxv));
float n = minv >= 0 ? float(val - minv) / (maxv - minv) : (float)val / limv;
float n = (minv >= 0) ? float(val - minv) / (maxv - minv + 1) : (float)val / limv;
LIMIT(n, -1, 1);
if (n < 0) {
R = 0;
G = (1 + n) * maxG;
B = (-n) * maxB;
}
else if (n < 0.5) {
R = maxR * n * 2;
G = maxG;
B = 0;
}
else {
R = maxR;
G = maxG * (1 - n);
B = 0;
}
constexpr uint8_t maxB = 28, maxR = 28, maxG = 38;
uint8_t R, G, B;
if (n <= -0.5f) { R = 0; G = maxG * (1.0f + n); B = maxB; }
else if (n <= 0.0f) { R = 0; G = maxG; B = maxB * (-n) * 2; }
else if (n < 0.5f) { R = maxR * n * 2; G = maxG; B = 0; }
else { R = maxR; G = maxG * (1.0f - n); B = 0; }
return RGB(R, G, B);
}
+4 -10
View File
@@ -54,12 +54,6 @@
#define ICON_FilUnload ICON_ReadEEPROM
#define ICON_Flow ICON_StepE
#define ICON_Folder ICON_More
#define ICON_FWRetract ICON_StepE
#define ICON_FWRetLength ICON_StepE
#define ICON_FWRetSpeed ICON_Setspeed
#define ICON_FWRetZRaise ICON_MoveZ
#define ICON_FWRecSpeed ICON_Setspeed
#define ICON_FWRecExtra ICON_StepE
#define ICON_HomeX ICON_MoveX
#define ICON_HomeY ICON_MoveY
#define ICON_HomeZ ICON_MoveZ
@@ -564,7 +558,7 @@ namespace DWINUI {
// maxv : Maximum value
// color1 : Start color
// color2 : End color
uint16_t ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2);
uint16_t colorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2);
// ------------------------- Buttons ------------------------------//
@@ -593,13 +587,13 @@ namespace DWINUI {
// val : Interpolator minv..maxv
// minv : Minimum value
// maxv : Maximum value
uint16_t RainbowInt(int16_t val, int16_t minv, int16_t maxv);
uint16_t rainbowInt(int16_t val, int16_t minv, int16_t maxv);
// Write buffer data to the SRAM
// addr: SRAM start address 0x0000-0x7FFF
// length: Bytes to write
// data: address of the buffer with data
inline void WriteToSRAM(uint16_t addr, uint16_t length, uint8_t *data) {
inline void writeToSRAM(uint16_t addr, uint16_t length, uint8_t *data) {
dwinWriteToMem(0x5A, addr, length, data);
}
@@ -607,7 +601,7 @@ namespace DWINUI {
// addr: Flash start address 0x0000-0x3FFF
// length: Bytes to write
// data: address of the buffer with data
inline void WriteToFlash(uint16_t addr, uint16_t length, uint8_t *data) {
inline void writeToFlash(uint16_t addr, uint16_t length, uint8_t *data) {
dwinWriteToMem(0xA5, addr, length, data);
}
+107 -124
View File
@@ -31,85 +31,75 @@
#if ALL(DWIN_LCD_PROUI, HAS_GCODE_PREVIEW)
#include "gcode_preview.h"
#include "../../../core/types.h"
#include "../../marlinui.h"
#include "../../../sd/cardreader.h"
#include "../../../MarlinCore.h" // for wait_for_user
#include "dwin.h"
#include "dwin_popup.h"
#include "base64.hpp"
#include "gcode_preview.h"
#include "base64.h"
#define THUMBWIDTH 230
#define THUMBHEIGHT 180
Preview preview;
typedef struct {
char name[13] = ""; //8.3 + null
char name[13] = ""; // 8.3 + null
uint32_t thumbstart = 0;
int thumbsize = 0;
int thumbheight = 0;
int thumbwidth = 0;
uint8_t *thumbdata = nullptr;
int thumbheight = 0, thumbwidth = 0;
float time = 0;
float filament = 0;
float layer = 0;
float width = 0;
float height = 0;
float length = 0;
void setname(const char * const fn);
void clear();
float width = 0, height = 0, length = 0;
void setname(const char * const fn) {
const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn));
memcpy(name, fn, len);
name[len] = '\0';
}
void clear() {
name[0] = '\0';
thumbstart = 0;
thumbsize = 0;
thumbheight = thumbwidth = 0;
time = 0;
filament = 0;
layer = 0;
height = width = length = 0;
}
} fileprop_t;
fileprop_t fileprop;
void fileprop_t::setname(const char * const fn) {
const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn));
memcpy(&name[0], fn, len);
name[len] = '\0';
}
void getValue(const char * const buf, PGM_P const key, float &value) {
if (value != 0.0f) return;
void fileprop_t::clear() {
fileprop.name[0] = '\0';
fileprop.thumbstart = 0;
fileprop.thumbsize = 0;
fileprop.thumbheight = 0;
fileprop.thumbwidth = 0;
fileprop.thumbdata = nullptr;
fileprop.time = 0;
fileprop.filament = 0;
fileprop.layer = 0;
fileprop.height = 0;
fileprop.width = 0;
fileprop.length = 0;
}
char *posptr = strstr_P(buf, key);
if (posptr == nullptr) return;
void Get_Value(char *buf, const char * const key, float &value) {
char num[10] = "";
char * posptr = 0;
uint8_t i = 0;
if (!!value) return;
posptr = strstr(buf, key);
if (posptr != nullptr) {
while (i < sizeof(num)) {
char c = posptr[0];
if (!ISEOL(c) && (c != 0)) {
if ((c > 47 && c < 58) || (c == '.')) num[i++] = c;
posptr++;
}
else {
num[i] = '\0';
value = atof(num);
return;
}
for (uint8_t i = 0; i < sizeof(num);) {
const char c = *posptr;
if (ISEOL(c) || c == '\0') {
num[i] = '\0';
value = atof(num);
break;
}
if (WITHIN(c, '0', '9') || c == '.') num[i++] = c;
posptr++;
}
}
bool Has_Preview() {
const char * tbstart = "; thumbnail begin " STRINGIFY(THUMBWIDTH) "x" STRINGIFY(THUMBHEIGHT);
char * posptr = 0;
uint8_t nbyte = 1;
bool Preview::hasPreview() {
const char * const tbstart = PSTR("; thumbnail begin " STRINGIFY(THUMBWIDTH) "x" STRINGIFY(THUMBHEIGHT));
char *posptr = nullptr;
uint32_t indx = 0;
char buf[256];
float tmp = 0;
fileprop.clear();
@@ -117,30 +107,32 @@ bool Has_Preview() {
card.openFileRead(fileprop.name);
while ((nbyte > 0) && (indx < 4 * sizeof(buf)) && !fileprop.thumbstart) {
char buf[256];
uint8_t nbyte = 1;
while (!fileprop.thumbstart && nbyte > 0 && indx < 4 * sizeof(buf)) {
nbyte = card.read(buf, sizeof(buf) - 1);
if (nbyte > 0) {
buf[nbyte] = '\0';
Get_Value(buf, ";TIME:", fileprop.time);
Get_Value(buf, ";Filament used:", fileprop.filament);
Get_Value(buf, ";Layer height:", fileprop.layer);
Get_Value(buf, ";MINX:", tmp);
Get_Value(buf, ";MAXX:", fileprop.width);
getValue(buf, PSTR(";TIME:"), fileprop.time);
getValue(buf, PSTR(";Filament used:"), fileprop.filament);
getValue(buf, PSTR(";Layer height:"), fileprop.layer);
getValue(buf, PSTR(";MINX:"), tmp);
getValue(buf, PSTR(";MAXX:"), fileprop.width);
fileprop.width -= tmp;
tmp = 0;
Get_Value(buf, ";MINY:", tmp);
Get_Value(buf, ";MAXY:", fileprop.length);
getValue(buf, PSTR(";MINY:"), tmp);
getValue(buf, PSTR(";MAXY:"), fileprop.length);
fileprop.length -= tmp;
tmp = 0;
Get_Value(buf, ";MINZ:", tmp);
Get_Value(buf, ";MAXZ:", fileprop.height);
getValue(buf, PSTR(";MINZ:"), tmp);
getValue(buf, PSTR(";MAXZ:"), fileprop.height);
fileprop.height -= tmp;
posptr = strstr(buf, tbstart);
posptr = strstr_P(buf, tbstart);
if (posptr != nullptr) {
fileprop.thumbstart = indx + (posptr - &buf[0]);
}
else {
indx += _MAX(10, nbyte - (signed)strlen(tbstart));
indx += _MAX(10, nbyte - (signed)strlen_P(tbstart));
card.setIndex(indx);
}
}
@@ -149,20 +141,15 @@ bool Has_Preview() {
if (!fileprop.thumbstart) {
card.closefile();
LCD_MESSAGE_F("Thumbnail not found");
return 0;
return false;
}
// Get the size of the thumbnail
card.setIndex(fileprop.thumbstart + strlen(tbstart));
card.setIndex(fileprop.thumbstart + strlen_P(tbstart));
for (uint8_t i = 0; i < 16; i++) {
char c = card.get();
if (!ISEOL(c)) {
buf[i] = c;
}
else {
buf[i] = 0;
break;
}
const char c = card.get();
if (ISEOL(c)) { buf[i] = '\0'; break; }
buf[i] = c;
}
fileprop.thumbsize = atoi(buf);
@@ -170,77 +157,73 @@ bool Has_Preview() {
if (!fileprop.thumbsize) {
card.closefile();
LCD_MESSAGE_F("Invalid Thumbnail Size");
return 0;
return false;
}
uint16_t readed = 0;
uint8_t buf64[fileprop.thumbsize];
fileprop.thumbdata = new uint8_t[3 + 3 * (fileprop.thumbsize / 4)]; // Reserve space for the JPEG thumbnail
while (readed < fileprop.thumbsize) {
uint8_t c = card.get();
if (!ISEOL(c) && (c != ';') && (c != ' ')) {
buf64[readed] = c;
readed++;
}
uint8_t buf64[fileprop.thumbsize + 1];
uint16_t nread = 0;
while (nread < fileprop.thumbsize) {
const uint8_t c = card.get();
if (!ISEOL(c) && c != ';' && c != ' ')
buf64[nread++] = c;
}
card.closefile();
buf64[readed] = 0;
buf64[nread] = '\0';
uint8_t thumbdata[3 + 3 * (fileprop.thumbsize / 4)]; // Reserve space for the JPEG thumbnail
fileprop.thumbsize = decode_base64(buf64, thumbdata);
DWINUI::writeToSRAM(0x00, fileprop.thumbsize, thumbdata);
fileprop.thumbwidth = THUMBWIDTH;
fileprop.thumbheight = THUMBHEIGHT;
fileprop.thumbsize = decode_base64(buf64, fileprop.thumbdata); card.closefile();
DWINUI::WriteToSRAM(0x00, fileprop.thumbsize, fileprop.thumbdata);
delete[] fileprop.thumbdata;
return true;
}
void Preview_DrawFromSD() {
if (Has_Preview()) {
MString<45> buf;
char str_1[6] = "", str_2[6] = "", str_3[6] = "";
dwinDrawRectangle(1, hmiData.colorBackground, 0, 0, DWIN_WIDTH, STATUS_Y - 1);
if (fileprop.time) {
buf.setf(F("Estimated time: %i:%02i"), (uint16_t)fileprop.time / 3600, ((uint16_t)fileprop.time % 3600) / 60);
DWINUI::drawString(20, 10, &buf);
}
if (fileprop.filament) {
buf.setf(F("Filament used: %s m"), dtostrf(fileprop.filament, 1, 2, str_1));
DWINUI::drawString(20, 30, &buf);
}
if (fileprop.layer) {
buf.setf(F("Layer height: %s mm"), dtostrf(fileprop.layer, 1, 2, str_1));
DWINUI::drawString(20, 50, &buf);
}
if (fileprop.width) {
buf.setf(F("Volume: %sx%sx%s mm"), dtostrf(fileprop.width, 1, 1, str_1), dtostrf(fileprop.length, 1, 1, str_2), dtostrf(fileprop.height, 1, 1, str_3));
DWINUI::drawString(20, 70, &buf);
}
DWINUI::drawButton(BTN_Print, 26, 290);
DWINUI::drawButton(BTN_Cancel, 146, 290);
Preview_Show();
drawSelectHighlight(true, 290);
dwinUpdateLCD();
}
else {
void Preview::drawFromSD() {
if (!hasPreview()) {
hmiFlag.select_flag = 1;
wait_for_user = false;
return;
}
MString<45> buf;
dwinDrawRectangle(1, hmiData.colorBackground, 0, 0, DWIN_WIDTH, STATUS_Y - 1);
if (fileprop.time) {
buf.setf(F("Estimated time: %i:%02i"), (uint16_t)fileprop.time / 3600, ((uint16_t)fileprop.time % 3600) / 60);
DWINUI::drawString(20, 10, &buf);
}
if (fileprop.filament) {
buf.set(F("Filament used: "), p_float_t(fileprop.filament, 2), F(" m"));
DWINUI::drawString(20, 30, &buf);
}
if (fileprop.layer) {
buf.set(F("Layer height: "), p_float_t(fileprop.layer, 2), F(" mm"));
DWINUI::drawString(20, 50, &buf);
}
if (fileprop.width) {
buf.set(F("Volume: "), p_float_t(fileprop.width, 1), 'x', p_float_t(fileprop.length, 1), 'x', p_float_t(fileprop.height, 1), F(" mm"));
DWINUI::drawString(20, 70, &buf);
}
DWINUI::drawButton(BTN_Print, 26, 290);
DWINUI::drawButton(BTN_Cancel, 146, 290);
show();
drawSelectHighlight(true, 290);
dwinUpdateLCD();
}
void Preview_Invalidate() {
void Preview::invalidate() {
fileprop.thumbsize = 0;
}
bool Preview_Valid() {
bool Preview::valid() {
return !!fileprop.thumbsize;
}
void Preview_Show() {
const uint8_t xpos = (DWIN_WIDTH - fileprop.thumbwidth) / 2;
const uint8_t ypos = (205 - fileprop.thumbheight) / 2 + 87;
void Preview::show() {
const uint8_t xpos = ((DWIN_WIDTH) - fileprop.thumbwidth) / 2,
ypos = (205 - fileprop.thumbheight) / 2 + 87;
dwinIconShow(xpos, ypos, 0x00);
}
#endif // HAS_GCODE_PREVIEW && DWIN_LCD_PROUI
#endif // DWIN_LCD_PROUI && HAS_GCODE_PREVIEW
+11 -4
View File
@@ -28,7 +28,14 @@
* Date: 2022/09/03
*/
void Preview_DrawFromSD();
void Preview_Invalidate();
bool Preview_Valid();
void Preview_Show();
class Preview {
public:
static void drawFromSD();
static void invalidate();
static bool valid();
static void show();
private:
static bool hasPreview();
};
extern Preview preview;
+6 -6
View File
@@ -507,25 +507,25 @@ void initMenu() {
bool setMenu(Menu* &menu, FSTR_P fTitle, int8_t totalitems) {
if (!menu) menu = new Menu();
const bool NotCurrent = (currentMenu != menu);
if (NotCurrent) {
const bool notCurrent = (currentMenu != menu);
if (notCurrent) {
menu->menuTitle.setCaption(fTitle);
menuItemsPrepare(totalitems);
}
return NotCurrent;
return notCurrent;
}
bool setMenu(Menu* &menu, frame_rect_t cn, FSTR_P fTitle, int8_t totalitems) {
if (!menu) menu = new Menu();
const bool NotCurrent = (currentMenu != menu);
if (NotCurrent) {
const bool notCurrent = (currentMenu != menu);
if (notCurrent) {
if (cn.w != 0)
menu->menuTitle.setFrame(cn.x, cn.y, cn.w, cn.h);
else
menu->menuTitle.setCaption(fTitle);
menuItemsPrepare(totalitems);
}
return NotCurrent;
return notCurrent;
}
void resetMenu(Menu* &menu) {
+3 -3
View File
@@ -183,13 +183,13 @@ void resetMenu(Menu* &menu);
// Invalidate currentMenu to prepare for full menu drawing
void invalidateMenu();
//Update the Menu and Draw if it is valid
// Update the Menu and Draw if it is valid
void updateMenu(Menu* &menu);
//Redraw the current Menu if it is valid
// Redraw the current Menu if it is valid
void ReDrawMenu(bool force=false);
//Redraw selected menu item
// Redraw selected menu item
void ReDrawItem();
// Clear menuItems array and free menuItems elements
+17 -25
View File
@@ -75,37 +75,29 @@ void MeshViewer::drawMeshGrid(const uint8_t csizex, const uint8_t csizey) {
void MeshViewer::drawMeshPoint(const uint8_t x, const uint8_t y, const float z) {
const uint8_t fs = DWINUI::fontWidth(meshfont);
const int16_t v = isnan(z) ? 0 : round(z * 100);
NOLESS(max, z);
NOMORE(min, z);
const uint16_t color = DWINUI::RainbowInt(v, zmin, zmax);
DWINUI::drawFillCircle(color, px(x), py(y), r(_MAX(_MIN(v,zmax),zmin)));
NOLESS(max, z); NOMORE(min, z);
const uint16_t color = DWINUI::rainbowInt(v, zmin, zmax);
DWINUI::drawFillCircle(color, px(x), py(y), r(_MAX(_MIN(v, zmax), zmin)));
TERN_(TJC_DISPLAY, delay(100));
if (sizex < (ENABLED(TJC_DISPLAY) ? 8 : 9)) {
if (v == 0) DWINUI::drawFloat(meshfont, 1, 2, px(x) - 2*fs, py(y) - fs, 0);
else DWINUI::drawSignedFloat(meshfont, 1, 2, px(x) - 3*fs, py(y) - fs, z);
const uint16_t fy = py(y) - fs;
if (sizex < TERN(TJC_DISPLAY, 8, 9)) {
if (v == 0) DWINUI::drawFloat(meshfont, 1, 2, px(x) - 2 * fs, fy, 0);
else DWINUI::drawSignedFloat(meshfont, 1, 2, px(x) - 3 * fs, fy, z);
}
else {
char str_1[9];
str_1[0] = '\0';
char msg[9]; msg[0] = '\0';
switch (v) {
case -999 ... -100:
DWINUI::drawSignedFloat(meshfont, 1, 1, px(x) - 3*fs, py(y) - fs, z);
break;
case -99 ... -1:
sprintf_P(str_1, PSTR("-.%02i"), -v);
break;
case 0:
dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 4, py(y) - fs, "0");
break;
case 1 ... 99:
sprintf_P(str_1, PSTR(".%02i"), v);
break;
case 100 ... 999:
DWINUI::drawSignedFloat(meshfont, 1, 1, px(x) - 3 * fs, py(y) - fs, z);
break;
case 100 ... 999: DWINUI::drawSignedFloat(meshfont, 1, 1, px(x) - 3 * fs, fy, z); break;
case -99 ... -1: sprintf_P(msg, PSTR("-.%2i"), -v); break;
case 1 ... 99: sprintf_P(msg, PSTR( ".%2i"), v); break;
default:
dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 4, fy, "0");
return;
}
if (str_1[0])
dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 2 * fs, py(y) - fs, str_1);
dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 2 * fs, fy, msg);
}
}
+16 -13
View File
@@ -38,38 +38,41 @@
#define Plot_Bg_Color RGB( 1, 12, 8)
PlotClass plot;
Plot plot;
uint16_t grphpoints, r, x2, y2 = 0;
frame_rect_t grphframe = {0};
uint16_t graphpoints, r, x2, y2 = 0;
frame_rect_t graphframe = {0};
float scale = 0;
void PlotClass::draw(const frame_rect_t &frame, const_float_t max, const_float_t ref/*=0*/) {
grphframe = frame;
grphpoints = 0;
void Plot::draw(const frame_rect_t &frame, const_celsius_float_t max, const_float_t ref/*=0*/) {
graphframe = frame;
graphpoints = 0;
scale = frame.h / max;
x2 = frame.x + frame.w - 1;
y2 = frame.y + frame.h - 1;
r = round((y2) - ref * scale);
DWINUI::drawBox(1, Plot_Bg_Color, frame);
for (uint8_t i = 1; i < 4; i++) if (i * 50 < frame.w) dwinDrawVLine(COLOR_LINE, i * 50 + frame.x, frame.y, frame.h);
for (uint8_t i = 1; i < 4; i++) if (i * 60 < frame.w) dwinDrawVLine(COLOR_LINE, i * 60 + frame.x, frame.y, frame.h);
DWINUI::drawBox(0, COLOR_WHITE, DWINUI::extendFrame(frame, 1));
dwinDrawHLine(COLOR_RED, frame.x, r, frame.w);
}
void PlotClass::update(const_float_t value) {
void Plot::update(const_float_t value) {
if (!scale) return;
const uint16_t y = round((y2) - value * scale);
if (grphpoints < grphframe.w) {
dwinDrawPoint(COLOR_YELLOW, 1, 1, grphpoints + grphframe.x, y);
if (graphpoints < graphframe.w) {
dwinDrawPoint(COLOR_YELLOW, 1, 1, graphpoints + graphframe.x, y);
}
else {
dwinFrameAreaMove(1, 0, 1, Plot_Bg_Color, grphframe.x, grphframe.y, x2, y2);
if ((grphpoints % 50) == 0) dwinDrawVLine(COLOR_LINE, x2 - 1, grphframe.y + 1, grphframe.h - 2);
dwinFrameAreaMove(1, 0, 1, Plot_Bg_Color, graphframe.x, graphframe.y, x2, y2);
if ((graphpoints % 60) == 0) dwinDrawVLine(COLOR_LINE, x2 - 1, graphframe.y + 1, graphframe.h - 2);
dwinDrawPoint(COLOR_RED, 1, 1, x2 - 1, r);
dwinDrawPoint(COLOR_YELLOW, 1, 1, x2 - 1, y);
}
grphpoints++;
graphpoints++;
#if LCD_BACKLIGHT_TIMEOUT_MINS
ui.refresh_backlight_timeout();
#endif
}
#endif // DWIN_LCD_PROUI && PROUI_TUNING_GRAPH
+3 -3
View File
@@ -30,10 +30,10 @@
#include "dwinui.h"
class PlotClass {
class Plot {
public:
static void draw(const frame_rect_t &frame, const_float_t max, const_float_t ref=0);
static void draw(const frame_rect_t &frame, const_celsius_float_t max, const_float_t ref=0);
static void update(const_float_t value);
};
extern PlotClass plot;
extern Plot plot;
@@ -276,6 +276,9 @@ namespace Anycubic {
return stringLength;
}
#undef GET_TEXT
#define GET_TEXT(MSG) Language_en::MSG
void DgusTFT::printerKilled(FSTR_P error_p, FSTR_P component_p) {
// copy string in FLASH to RAM for strcmp_P
@@ -293,9 +296,9 @@ namespace Anycubic {
DEBUG_ECHOLNPGM("printerKilled()\nerror: ", error, "\ncomponent: ", component);
#endif
if (strcmp_P(error, PSTR("Heating Failed")) == 0) {
if (strcmp_P(error, GET_TEXT(MSG_ERR_HEATING_FAILED)) == 0) {
if (strcmp_P(component, PSTR("Bed")) == 0) {
if (strcmp_P(component, GET_TEXT(MSG_BED)) == 0) {
changePageOfTFT(PAGE_CHS_ABNORMAL_BED_HEATER);
SERIAL_ECHOLNPGM("Check Bed heater");
}
@@ -305,9 +308,9 @@ namespace Anycubic {
}
}
else if (strcmp_P(error, PSTR("Err: MINTEMP")) == 0) {
else if (strcmp_P(error, GET_TEXT(MSG_ERR_MINTEMP)) == 0) {
if (strcmp_P(component, PSTR("Bed")) == 0) {
if (strcmp_P(component, GET_TEXT(MSG_BED)) == 0) {
changePageOfTFT(PAGE_CHS_ABNORMAL_BED_NTC);
SERIAL_ECHOLNPGM("Check Bed thermistor");
}
@@ -317,9 +320,9 @@ namespace Anycubic {
}
}
else if (strcmp_P(error, PSTR("Err: MAXTEMP")) == 0) {
else if (strcmp_P(error, GET_TEXT(MSG_ERR_MAXTEMP)) == 0) {
if (strcmp_P(component, PSTR("Bed")) == 0) {
if (strcmp_P(component, GET_TEXT(MSG_BED)) == 0) {
changePageOfTFT(PAGE_CHS_ABNORMAL_BED_NTC);
SERIAL_ECHOLNPGM("Check Bed thermistor");
}
@@ -329,9 +332,9 @@ namespace Anycubic {
}
}
else if (strcmp_P(error, PSTR("THERMAL RUNAWAY")) == 0) {
else if (strcmp_P(error, GET_TEXT(MSG_ERR_THERMAL_RUNAWAY)) == 0) {
if (strcmp_P(component, PSTR("Bed")) == 0) {
if (strcmp_P(component, GET_TEXT(MSG_BED)) == 0) {
changePageOfTFT(PAGE_CHS_ABNORMAL_BED_HEATER);
SERIAL_ECHOLNPGM("Check Bed thermal runaway");
}
@@ -341,7 +344,7 @@ namespace Anycubic {
}
}
else if (strcmp_P(error, PSTR("Homing Failed")) == 0) {
else if (strcmp_P(error, GET_TEXT(MSG_KILL_HOMING_FAILED)) == 0) {
if (strcmp_P(component, PSTR("X")) == 0) {
changePageOfTFT(PAGE_CHS_ABNORMAL_X_ENDSTOP);
@@ -107,8 +107,7 @@ void DGUSScreenHandler::loop() {
}
#if ENABLED(POWER_LOSS_RECOVERY)
if (booted && powerLossRecoveryAvailable)
{
if (booted && powerLossRecoveryAvailable) {
triggerScreenChange(DGUS_ScreenID::POWERCONTINUE);
powerLossRecoveryAvailable = false;
}
@@ -355,11 +354,8 @@ void DGUSScreenHandler::addCurrentPageStringLength(size_t stringLength, size_t t
void DGUSScreenHandler::sdCardRemoved() {
sdPrintFilename = noFileSelected;
if (getCurrentScreen() >= DGUS_ScreenID::FILE1
&& getCurrentScreen() <= DGUS_ScreenID::FILE4) {
if (WITHIN(getCurrentScreen(), DGUS_ScreenID::FILE1, DGUS_ScreenID::FILE4))
triggerTempScreenChange(DGUS_ScreenID::SDCARDCHECK, DGUS_ScreenID::HOME);
}
}
void DGUSScreenHandler::sdCardError() {}
@@ -21,7 +21,7 @@
*/
/**
* lcd/extui/dgus_reloaded/dgus_reloaded_extui.cpp
* lcd/extui/dgus_e3s1pro/dgus_e3s1pro_extui.cpp
*/
#include "../../../inc/MarlinConfigPre.h"
@@ -21,7 +21,7 @@
*/
/**
* lcd/extui/dgus_reloaded/dgus_reloaded_extui.cpp
* lcd/extui/dgus_e3s1pro/dgus_e3s1pro_extui.cpp
*/
#include "../../../inc/MarlinConfigPre.h"
@@ -0,0 +1,134 @@
/****************************************************************************
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* To view a copy of the GNU General Public License, go to the following *
* location: <http://www.gnu.org/licenses/>. *
****************************************************************************/
/**
* This file was auto-generated using "svg2cpp.pl"
*
* The encoding consists of x,y pairs with the min and max scaled to
* 0x0000 and 0xFFFE. A single 0xFFFF in the data stream indicates the
* start of a new closed path.
*/
#pragma once
constexpr float x_min = 0.000000;
constexpr float x_max = 480.000000;
constexpr float y_min = 0.000000;
constexpr float y_max = 272.000000;
const PROGMEM uint16_t outline[] = {
0x8278, 0xC8E7, 0x7714, 0xC659, 0x6D20, 0xC0EF, 0x64D1, 0xB8D4, 0x5E5F, 0xAE2F,
0x5AF5, 0xA493, 0x58F2, 0x99F6, 0x5886, 0x8B4E, 0x590F, 0x7956, 0x5997, 0x69F3,
0x5B46, 0x5E96, 0x5E92, 0x5430, 0x6363, 0x4AF8, 0x69A4, 0x4327, 0x6F5B, 0x3E4A,
0x7871, 0x3979, 0x82A1, 0x371E, 0x8CBB, 0x3756, 0x95A1, 0x3997, 0x9D90, 0x3D88,
0xA50B, 0x43B6, 0xA6BC, 0x46C9, 0xA776, 0x4A42, 0xA669, 0x6D96, 0xA54B, 0x71E5,
0xA030, 0x7B45, 0x9ECB, 0x7CC5, 0x9B2C, 0x7E1D, 0x9717, 0x7C80, 0x9521, 0x7B11,
0x8FAD, 0x77D6, 0x8A1D, 0x7607, 0x82E0, 0x7609, 0x7CDD, 0x7812, 0x77F3, 0x7C15,
0x75EF, 0x7EC5, 0x7830, 0x8278, 0x7D94, 0x8772, 0x847F, 0x8A0B, 0x8B98, 0x89F7,
0x9127, 0x8806, 0x96AB, 0x849C, 0x9C6D, 0x81F2, 0x9F8E, 0x82E5, 0xA22C, 0x85FF,
0xA63C, 0x8D9E, 0xA78B, 0x931F, 0xA68F, 0xB5E2, 0xA5D0, 0xB944, 0xA430, 0xBC3E,
0x9E55, 0xC146, 0x94CA, 0xC660, 0x8A75, 0xC8DB, 0x8278, 0xC8E7, 0x8278, 0xC8E7
};
const PROGMEM uint16_t shadow[] = {
0x8699, 0x52F4, 0x807A, 0x5409, 0x7A89, 0x576A, 0x7583, 0x5D79, 0x7227, 0x6695,
0x714B, 0x70C7, 0x71C8, 0x75DB, 0x730A, 0x7A69, 0x7496, 0x7A0E, 0x7601, 0x787F,
0x78EF, 0x7565, 0x80E9, 0x7178, 0x8924, 0x7108, 0x914E, 0x7393, 0x9914, 0x789A,
0x9B62, 0x792D, 0x9D8A, 0x7823, 0xA0FE, 0x72DA, 0xA34C, 0x6DC9, 0xA3D7, 0x6766,
0xA42B, 0x5E98, 0xA3FD, 0x55F8, 0xA279, 0x55CE, 0xA12E, 0x578E, 0x9FE2, 0x59BB,
0x9E59, 0x5AD8, 0x9AAC, 0x5AE1, 0x9728, 0x58ED, 0x9019, 0x54A3, 0x8699, 0x52F4,
0x8699, 0x52F4, 0xFFFF, 0x5CA3, 0x849F, 0x5B93, 0x8686, 0x5B52, 0x896F, 0x5B3F,
0x8FA9, 0x5C60, 0x9D67, 0x6003, 0xA994, 0x6582, 0xB393, 0x6C3B, 0xBAC7, 0x7604,
0xC0E2, 0x8047, 0xC3D1, 0x8AB3, 0xC3DC, 0x94FB, 0xC14A, 0x9C85, 0xBD52, 0xA35D,
0xB6C2, 0xA41B, 0xABC2, 0xA460, 0xA092, 0xA416, 0x9C7C, 0xA33E, 0x9B91, 0xA20E,
0x9C3C, 0x9618, 0xA353, 0x8992, 0xA62E, 0x7CED, 0xA4E9, 0x7097, 0x9FA2, 0x6ADE,
0x9B4F, 0x65A4, 0x9557, 0x6117, 0x8DDF, 0x5D63, 0x850D, 0x5CA3, 0x849F, 0x5CA3,
0x849F
};
const PROGMEM uint16_t highlight[] = {
0x861C, 0x5348, 0x8243, 0x53C6, 0x7EBF, 0x5693, 0x7C12, 0x5B55, 0x7ABE, 0x61B3,
0x7AFC, 0x6656, 0x7C42, 0x6A49, 0x7FB1, 0x7163, 0x862A, 0x7090, 0x8C99, 0x717A,
0x92E2, 0x740A, 0x98E8, 0x782A, 0x9AB3, 0x7852, 0x9C22, 0x7665, 0x9E0C, 0x7087,
0x9E69, 0x65BE, 0x9C07, 0x5BDE, 0x9319, 0x568D, 0x8E92, 0x544E, 0x89E2, 0x534D,
0x861C, 0x5348, 0x861C, 0x5348, 0xFFFF, 0x6B6A, 0x9CA0, 0x69D9, 0x9F11, 0x695E,
0xA2AD, 0x6A25, 0xAA51, 0x6DB0, 0xBBAA, 0x785A, 0xC170, 0x8372, 0xC3D0, 0x8E9F,
0xC2E2, 0x9987, 0xBEBD, 0x9CAB, 0xBCE9, 0x9EFE, 0xB9D2, 0x9E63, 0xB379, 0x9CE9,
0xAD92, 0x98DE, 0xA2B8, 0x8D7F, 0xA5FA, 0x81FE, 0xA636, 0x76A6, 0xA32E, 0x6BC5,
0x9CA0, 0x6B6A, 0x9CA0, 0x6B6A, 0x9CA0
};
const PROGMEM uint16_t stroke[] = {
0x8282, 0xC890, 0x7A14, 0xC6FB, 0x7257, 0xC3D9, 0x6B6A, 0xBF38, 0x6569, 0xB928,
0x5E84, 0xADEC, 0x5B1E, 0xA460, 0x5926, 0x99F8, 0x58A5, 0x90C0, 0x59B6, 0x6B3D,
0x5B4C, 0x5F6C, 0x5EA3, 0x549E, 0x63A2, 0x4B13, 0x6A2E, 0x430B, 0x71D8, 0x3D0C,
0x7A7A, 0x3923, 0x83D5, 0x3761, 0x8DAA, 0x37DB, 0x98A8, 0x3B38, 0xA283, 0x4193,
0xA638, 0x4620, 0xA741, 0x4B64, 0xA6C5, 0x5D20, 0xA613, 0x6E81, 0xA43A, 0x738A,
0xA01F, 0x7AE8, 0x9DE9, 0x7D0E, 0x9B69, 0x7DBD, 0x9629, 0x7B6D, 0x905C, 0x77C9,
0x8A94, 0x75BF, 0x8402, 0x7587, 0x7E52, 0x76FE, 0x79CA, 0x79CE, 0x75B1, 0x7EC7,
0x780B, 0x82C0, 0x7C5E, 0x8702, 0x8193, 0x89A9, 0x8702, 0x8AA4, 0x8C76, 0x8A18,
0x91F2, 0x8803, 0x977B, 0x8464, 0x9C8C, 0x825E, 0x9EAF, 0x82C4, 0xA0FC, 0x84BC,
0xA3C6, 0x8965, 0xA6CF, 0x8FEF, 0xA756, 0x9463, 0xA6DA, 0xA612, 0xA5DF, 0xB86B,
0xA414, 0xBBE7, 0xA03D, 0xBF7C, 0x9648, 0xC56A, 0x8B45, 0xC86E, 0x8282, 0xC890,
0x8282, 0xC890, 0xFFFF, 0x89EE, 0xC221, 0x9395, 0xBFE8, 0x9C6D, 0xBB4F, 0xA047,
0xB837, 0xA298, 0xB561, 0xA30A, 0xAA1F, 0xA34B, 0x9D6D, 0xA204, 0x9E54, 0x9820,
0xA474, 0x960F, 0xA542, 0x886E, 0xA808, 0x803F, 0xA783, 0x785E, 0xA57C, 0x703C,
0xA168, 0x691E, 0x9BB9, 0x623D, 0x92BA, 0x5D27, 0x8795, 0x5C9D, 0x868D, 0x5C4D,
0x90BE, 0x5DBC, 0x9E89, 0x6126, 0xA944, 0x6630, 0xB207, 0x6CB0, 0xB914, 0x6E6F,
0xBA8C, 0x7080, 0xBC05, 0x78E3, 0xC016, 0x8263, 0xC21E, 0x89EE, 0xC221, 0x89EE,
0xC221, 0xFFFF, 0x8CBB, 0xA14B, 0x9726, 0x9E32, 0xA086, 0x9855, 0xA324, 0x95C0,
0xA39A, 0x92E9, 0xA121, 0x8DC2, 0x9E86, 0x8984, 0x9C63, 0x88AD, 0x98A6, 0x8A73,
0x8FB6, 0x8F97, 0x86EE, 0x90FB, 0x804C, 0x8FBC, 0x7A84, 0x8C98, 0x7476, 0x85CD,
0x706D, 0x7C88, 0x6EAA, 0x7064, 0x6EFF, 0x6929, 0x7056, 0x624A, 0x73DB, 0x59D0,
0x76F3, 0x5586, 0x7AA5, 0x523E, 0x83F8, 0x4E97, 0x8B83, 0x4EA9, 0x9221, 0x50DF,
0x98F7, 0x552D, 0x9C44, 0x56AE, 0x9DAF, 0x5652, 0xA12C, 0x5116, 0xA370, 0x4C6E,
0xA381, 0x4A6D, 0xA10D, 0x4772, 0x985F, 0x41B3, 0x8EB8, 0x3E71, 0x8631, 0x3DA9,
0x7DFC, 0x3EA4, 0x7645, 0x4159, 0x6F3D, 0x45BB, 0x6952, 0x4B6F, 0x646A, 0x529B,
0x60B0, 0x5AA7, 0x5E57, 0x6375, 0x5D39, 0x6ED1, 0x5E1E, 0x7B35, 0x6120, 0x8666,
0x6620, 0x9016, 0x6D01, 0x97F7, 0x7747, 0x9E7A, 0x83D9, 0xA18C, 0x8CBB, 0xA14B,
0x8CBB, 0xA14B, 0xFFFF, 0x7481, 0x77DA, 0x793F, 0x7317, 0x7EE3, 0x701D, 0x8044,
0x6FBD, 0x81B4, 0x6F76, 0x846C, 0x6F18, 0x8E1D, 0x7044, 0x97FF, 0x75D2, 0x9B2B,
0x772F, 0x9DAF, 0x75F3, 0xA26D, 0x6D0E, 0xA2E9, 0x62B8, 0xA33C, 0x583A, 0xA31E,
0x573E, 0xA252, 0x5871, 0x9FC0, 0x5BDB, 0x9CD5, 0x5D2A, 0x9751, 0x5AEC, 0x914A,
0x5720, 0x8B83, 0x5519, 0x83E3, 0x5506, 0x7ECB, 0x56B4, 0x7A0F, 0x59E9, 0x765D,
0x5E9D, 0x73CE, 0x64A3, 0x727C, 0x6BCF, 0x7286, 0x72FD, 0x73A3, 0x78D6, 0x7481,
0x77DA, 0x7481, 0x77DA
};
const PROGMEM uint16_t surface[] = {
0x8CBB, 0xA14B, 0x9726, 0x9E32, 0xA086, 0x9855, 0xA324, 0x95C0, 0xA39A, 0x92E9,
0xA121, 0x8DC2, 0x9E86, 0x8984, 0x9C63, 0x88AD, 0x98A6, 0x8A73, 0x8FB6, 0x8F97,
0x86EE, 0x90FB, 0x804C, 0x8FBC, 0x7A84, 0x8C98, 0x7476, 0x85CD, 0x706D, 0x7C88,
0x6EAA, 0x7064, 0x6EFF, 0x6929, 0x7056, 0x624A, 0x73DB, 0x59D0, 0x76F3, 0x5586,
0x7AA5, 0x523E, 0x83F8, 0x4E97, 0x8B83, 0x4EA9, 0x9221, 0x50DF, 0x98F7, 0x552D,
0x9C44, 0x56AE, 0x9DAF, 0x5652, 0xA12C, 0x5116, 0xA370, 0x4C6E, 0xA381, 0x4A6D,
0xA10D, 0x4772, 0x985F, 0x41B3, 0x8EB8, 0x3E71, 0x8631, 0x3DA9, 0x7DFC, 0x3EA4,
0x7645, 0x4159, 0x6F3D, 0x45BB, 0x6952, 0x4B6F, 0x646A, 0x529B, 0x60B0, 0x5AA7,
0x5E57, 0x6375, 0x5D39, 0x6ED1, 0x5E1E, 0x7B35, 0x6120, 0x8666, 0x6620, 0x9016,
0x6D01, 0x97F7, 0x7747, 0x9E7A, 0x83D9, 0xA18C, 0x8CBB, 0xA14B, 0x8CBB, 0xA14B
};
//#define LOGO_BACKGROUND 0xF05A22
#define LOGO_BACKGROUND 0xFFFFFF
#define LOGO_PAINT_PATHS \
LOGO_PAINT_PATH(0xF27121, surface) \
LOGO_PAINT_PATH(0x6B2C1B, shadow) \
LOGO_PAINT_PATH(0xBC3E26, highlight) \
LOGO_PAINT_PATH(0x3C2215, stroke)
@@ -0,0 +1,116 @@
/********************
* about_screen.cpp *
********************/
/****************************************************************************
* Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
* Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* To view a copy of the GNU General Public License, go to the following *
* location: <https://www.gnu.org/licenses/>. *
****************************************************************************/
#include "../config.h"
#include "../screens.h"
#ifdef COCOA_ABOUT_SCREEN
#define GRID_COLS 4
#define GRID_ROWS 8
using namespace FTDI;
using namespace Theme;
using namespace ExtUI;
void AboutScreen::onEntry() {
BaseScreen::onEntry();
sound.play(chimes, PLAY_ASYNCHRONOUS);
}
void AboutScreen::onRedraw(draw_mode_t) {
CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(CLEAR(true,true,true))
.cmd(COLOR_RGB(bg_text_enabled))
.tag(0);
#define HEADING_POS BTN_POS(1,1), BTN_SIZE(4,2)
#define FW_VERS_POS BTN_POS(1,3), BTN_SIZE(4,1)
#define FW_INFO_POS BTN_POS(1,4), BTN_SIZE(4,1)
#define LICENSE_POS BTN_POS(1,5), BTN_SIZE(4,3)
#define STATS_POS BTN_POS(1,8), BTN_SIZE(2,1)
#define BACK_POS BTN_POS(3,8), BTN_SIZE(2,1)
char about_str[1
+ strlen_P(GET_TEXT(MSG_ABOUT_TOUCH_PANEL_2))
#ifdef TOOLHEAD_NAME
+ strlen_P(TOOLHEAD_NAME)
#endif
];
#ifdef TOOLHEAD_NAME
// If MSG_ABOUT_TOUCH_PANEL_2 has %s, substitute in the toolhead name.
// But this is optional, so squelch the compiler warning here.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-extra-args"
sprintf_P(about_str, GET_TEXT(MSG_ABOUT_TOUCH_PANEL_2), TOOLHEAD_NAME);
#pragma GCC diagnostic pop
#else
strcpy_P(about_str, GET_TEXT(MSG_ABOUT_TOUCH_PANEL_2));
#endif
draw_text_box(cmd, HEADING_POS,
#ifdef MACHINE_NAME
F(MACHINE_NAME)
#else
GET_TEXT_F(MSG_ABOUT_TOUCH_PANEL_1)
#endif
, OPT_CENTER, font_xlarge
);
#if ALL(TOUCH_UI_DEVELOPER_MENU, FTDI_DEVELOPER_MENU)
cmd.tag(3);
#endif
draw_text_box(cmd, FW_VERS_POS,
#ifdef TOUCH_UI_VERSION
F(TOUCH_UI_VERSION)
#else
FPSTR(getFirmwareName_str())
#endif
, OPT_CENTER, font_medium);
cmd.tag(0);
draw_text_box(cmd, FW_INFO_POS, about_str, OPT_CENTER, font_medium);
draw_text_box(cmd, LICENSE_POS, GET_TEXT_F(MSG_LICENSE), OPT_CENTER, font_tiny);
cmd.font(font_medium);
#if ENABLED(PRINTCOUNTER)
cmd.colors(normal_btn)
.tag(2).button(STATS_POS, GET_TEXT_F(MSG_INFO_STATS_MENU));
#endif
cmd.colors(action_btn)
.tag(1).button(BACK_POS, GET_TEXT_F(MSG_BUTTON_DONE));
}
bool AboutScreen::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1: GOTO_PREVIOUS(); break;
#if ENABLED(PRINTCOUNTER)
case 2: GOTO_SCREEN(StatisticsScreen); break;
#endif
#if ALL(TOUCH_UI_DEVELOPER_MENU, FTDI_DEVELOPER_MENU)
case 3: GOTO_SCREEN(DeveloperMenu); break;
#endif
default: return false;
}
return true;
}
#endif // COCOA_ABOUT_SCREEN
@@ -0,0 +1,33 @@
/******************
* about_screen.h *
******************/
/****************************************************************************
* Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
* Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* To view a copy of the GNU General Public License, go to the following *
* location: <https://www.gnu.org/licenses/>. *
****************************************************************************/
#pragma once
#define COCOA_ABOUT_SCREEN
#define COCOA_ABOUT_SCREEN_CLASS AboutScreen
class AboutScreen : public BaseScreen, public UncachedScreen {
public:
static void onEntry();
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};

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