mirror of
https://github.com/MarlinFirmware/Marlin.git
synced 2026-01-10 00:27:46 -07:00
Merge branch 'bugfix-2.1.x' into bugfix-2.1.x-February2
This commit is contained in:
commit
a207fdc26b
75 changed files with 613 additions and 395 deletions
|
|
@ -38,7 +38,7 @@
|
|||
"platformio.platformio-ide",
|
||||
"marlinfirmware.auto-build",
|
||||
"editorconfig.editorconfig"
|
||||
],
|
||||
]
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
|
|
|||
42
.github/workflows/ci-validate-boards.yml
vendored
42
.github/workflows/ci-validate-boards.yml
vendored
|
|
@ -9,14 +9,14 @@ name: CI - Validate boards.h
|
|||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- bugfix-2.1.x
|
||||
- bugfix-2.1.x
|
||||
paths:
|
||||
- 'Marlin/src/core/boards.h'
|
||||
- "Marlin/src/core/boards.h"
|
||||
push:
|
||||
branches:
|
||||
- bugfix-2.1.x
|
||||
- bugfix-2.1.x
|
||||
paths:
|
||||
- 'Marlin/src/core/boards.h'
|
||||
- "Marlin/src/core/boards.h"
|
||||
|
||||
jobs:
|
||||
validate_pins_files:
|
||||
|
|
@ -26,23 +26,23 @@ jobs:
|
|||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Check out the PR
|
||||
uses: actions/checkout@v4
|
||||
- name: Check out the PR
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-boards-v1
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-boards-
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-validation-v1
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-validation-
|
||||
|
||||
- name: Select Python 3.9
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.9'
|
||||
architecture: 'x64'
|
||||
- name: Select Python 3.9
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.9"
|
||||
architecture: "x64"
|
||||
|
||||
- name: Validate core/boards.h
|
||||
run: |
|
||||
make validate-boards -j
|
||||
- name: Validate core/boards.h
|
||||
run: |
|
||||
make validate-boards -j
|
||||
|
|
|
|||
40
.github/workflows/ci-validate-lines.yml
vendored
Normal file
40
.github/workflows/ci-validate-lines.yml
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#
|
||||
# ci-validate-lines.yml
|
||||
# Validate that all text files are unchanged by linesformat.py
|
||||
#
|
||||
|
||||
name: CI - Validate Source Files
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- bugfix-2.1.x
|
||||
- 2.1.x
|
||||
push:
|
||||
branches:
|
||||
- bugfix-2.1.x
|
||||
- 2.1.x
|
||||
|
||||
jobs:
|
||||
validate_source_files:
|
||||
name: Validate Source Files
|
||||
if: github.repository == 'MarlinFirmware/Marlin'
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Check out the PR
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cache node_modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-npm-lines-v1
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-lines-
|
||||
|
||||
- name: Validate text file formatting
|
||||
run: |
|
||||
npm install --save-dev prettier
|
||||
make validate-lines -j
|
||||
42
.github/workflows/ci-validate-pins.yml
vendored
42
.github/workflows/ci-validate-pins.yml
vendored
|
|
@ -8,18 +8,18 @@ name: CI - Validate Pins Files
|
|||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- bugfix-2.1.x
|
||||
- bugfix-2.1.x
|
||||
# Cannot be enabled on 2.1.x until it contains the unit test framework
|
||||
#- 2.1.x
|
||||
paths:
|
||||
- 'Marlin/src/pins/*/**'
|
||||
- "Marlin/src/pins/*/**"
|
||||
push:
|
||||
branches:
|
||||
- bugfix-2.1.x
|
||||
- bugfix-2.1.x
|
||||
# Cannot be enabled on 2.1.x until it contains the unit test framework
|
||||
#- 2.1.x
|
||||
paths:
|
||||
- 'Marlin/src/pins/*/**'
|
||||
- "Marlin/src/pins/*/**"
|
||||
|
||||
jobs:
|
||||
validate_pins_files:
|
||||
|
|
@ -29,23 +29,23 @@ jobs:
|
|||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Check out the PR
|
||||
uses: actions/checkout@v4
|
||||
- name: Check out the PR
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-pins-v1
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-pins-
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-validation-v1
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-validation-
|
||||
|
||||
- name: Select Python 3.9
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.9'
|
||||
architecture: 'x64'
|
||||
- name: Select Python 3.9
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.9"
|
||||
architecture: "x64"
|
||||
|
||||
- name: Validate all pins files
|
||||
run: |
|
||||
make validate-pins -j
|
||||
- name: Validate all pins files
|
||||
run: |
|
||||
make validate-pins -j
|
||||
|
|
|
|||
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -31,6 +31,11 @@ out-language/
|
|||
*.gen
|
||||
*.sublime-workspace
|
||||
|
||||
# npm
|
||||
node_modules/
|
||||
package.json
|
||||
package-lock.json
|
||||
|
||||
# OS
|
||||
applet/
|
||||
.DS_Store
|
||||
|
|
|
|||
10
.prettierignore
Normal file
10
.prettierignore
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Prettier Ignore file
|
||||
*.min.js
|
||||
web-ui/
|
||||
buildroot/share/PlatformIO/boards
|
||||
buildroot/share/PlatformIO/variants
|
||||
*.sublime-project
|
||||
*.sublime-syntax
|
||||
.github
|
||||
.vscode
|
||||
launch.json
|
||||
14
Makefile
14
Makefile
|
|
@ -8,6 +8,7 @@ help:
|
|||
@echo "Tasks for local development:"
|
||||
@echo "make marlin : Build Marlin for the configured board"
|
||||
@echo "make format-pins -j : Reformat all pins files (-j for parallel execution)"
|
||||
@echo "make validate-lines -j : Validate line endings, fails on trailing whitespace, etc."
|
||||
@echo "make validate-pins -j : Validate all pins files, fails if any require reformatting"
|
||||
@echo "make validate-boards -j : Validate boards.h and pins.h for standards compliance"
|
||||
@echo "make tests-single-ci : Run a single test from inside the CI"
|
||||
|
|
@ -95,7 +96,7 @@ PINS := $(shell find Marlin/src/pins -mindepth 2 -name '*.h')
|
|||
.PHONY: $(PINS) format-pins validate-pins
|
||||
|
||||
$(PINS): %:
|
||||
@echo "Formatting $@"
|
||||
@echo "Formatting pins $@"
|
||||
@python $(SCRIPTS_DIR)/pinsformat.py $< $@
|
||||
|
||||
format-pins: $(PINS)
|
||||
|
|
@ -104,6 +105,17 @@ validate-pins: format-pins
|
|||
@echo "Validating pins files"
|
||||
@git diff --exit-code || (git status && echo "\nError: Pins files are not formatted correctly. Run \"make format-pins\" to fix.\n" && exit 1)
|
||||
|
||||
.PHONY: format-lines validate-lines
|
||||
|
||||
format-lines:
|
||||
@echo "Formatting all sources"
|
||||
@python $(SCRIPTS_DIR)/linesformat.py buildroot
|
||||
@python $(SCRIPTS_DIR)/linesformat.py Marlin
|
||||
|
||||
validate-lines:
|
||||
@echo "Validating text formatting"
|
||||
@npx prettier --check . --editorconfig --object-wrap preserve
|
||||
|
||||
BOARDS_FILE := Marlin/src/core/boards.h
|
||||
|
||||
.PHONY: validate-boards
|
||||
|
|
|
|||
|
|
@ -3517,6 +3517,7 @@
|
|||
//#define W_STALL_SENSITIVITY 8
|
||||
//#define SPI_ENDSTOPS // TMC2130, TMC2240, and TMC5160
|
||||
//#define IMPROVE_HOMING_RELIABILITY
|
||||
//#define SENSORLESS_STALLGUARD_DELAY 0 // (ms) Delay to allow drivers to settle
|
||||
#endif
|
||||
|
||||
// @section tmc/config
|
||||
|
|
@ -4004,7 +4005,7 @@
|
|||
#endif
|
||||
|
||||
/**
|
||||
* M115 - Report capabilites. Disable to save ~1150 bytes of flash.
|
||||
* M115 - Report capabilities. Disable to save ~1150 bytes of flash.
|
||||
* Some hosts (and serial TFT displays) rely on this feature.
|
||||
*/
|
||||
#define CAPABILITIES_REPORT
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
* here we define this default string as the date where the latest release
|
||||
* version was tagged.
|
||||
*/
|
||||
//#define STRING_DISTRIBUTION_DATE "2025-08-26"
|
||||
//#define STRING_DISTRIBUTION_DATE "2025-09-09"
|
||||
|
||||
/**
|
||||
* The protocol for communication to the host. Protocol indicates communication
|
||||
|
|
|
|||
|
|
@ -523,7 +523,7 @@ static bool udd_ep_interrupt(void);
|
|||
* \internal
|
||||
* \brief Function called by UOTGHS interrupt to manage USB Device interrupts
|
||||
*
|
||||
* USB Device interrupt events are splited in three parts:
|
||||
* USB Device interrupt events are split in three parts:
|
||||
* - USB line events (SOF, reset, suspend, resume, wakeup)
|
||||
* - control endpoint events (setup reception, end of data transfer, underflow, overflow, stall)
|
||||
* - bulk/interrupt/isochronous endpoints events (end of data transfer)
|
||||
|
|
@ -1567,7 +1567,7 @@ static void udd_ctrl_out_received(void)
|
|||
udd_ctrl_payload_buf_cnt))) {
|
||||
// End of reception because it is a short packet
|
||||
// Before send ZLP, call intermediate callback
|
||||
// in case of data receiv generate a stall
|
||||
// in case of data receive generate a stall
|
||||
udd_g_ctrlreq.payload_size = udd_ctrl_payload_buf_cnt;
|
||||
if (NULL != udd_g_ctrlreq.over_under_run) {
|
||||
if (!udd_g_ctrlreq.over_under_run()) {
|
||||
|
|
@ -1808,7 +1808,7 @@ static void udd_ep_trans_done(udd_ep_id_t ep)
|
|||
}
|
||||
|
||||
if (ptr_job->buf_cnt != ptr_job->buf_size) {
|
||||
// Need to send or receiv other data
|
||||
// Need to send or receive other data
|
||||
next_trans = ptr_job->buf_size - ptr_job->buf_cnt;
|
||||
|
||||
if (UDD_ENDPOINT_MAX_TRANS < next_trans) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
This HAL is eventually intended to act as the generic HAL for all GD32 chips using the MFL library.
|
||||
|
||||
Currently it supports:
|
||||
* GD32F303RET6
|
||||
|
||||
- GD32F303RET6
|
||||
|
||||
Targeting the official [MFL Arduino Core](https://github.com/bnmguy/ArduinoCore_MFL).
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public:
|
|||
// Interrupt handler
|
||||
void handle_interrupts();
|
||||
|
||||
// Varaible stored parameters
|
||||
// Variable stored parameters
|
||||
auto get_scr(uint16_t rca, uint32_t* scr) -> SDIO_Error_Type;
|
||||
auto store_cid() -> SDIO_Error_Type;
|
||||
auto store_csd() -> SDIO_Error_Type;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ extern Timer0 step_timer;
|
|||
* See https://github.com/MarlinFirmware/Marlin/pull/27099 for more information.
|
||||
*
|
||||
* NOTE: If the 'constexpr' requirement is ever lifted, TIMER0_BASE_FREQUENCY could
|
||||
* be used instead. Tho this would probably not make any noticable difference.
|
||||
* be used instead. Tho this would probably not make any noticeable difference.
|
||||
*/
|
||||
#define HAL_TIMER_RATE F_PCLK1
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ void MarlinHAL::reboot() { watchdog_reboot(0, 0, 1); }
|
|||
|
||||
void MarlinHAL::watchdog_init() {
|
||||
#if DISABLED(DISABLE_WATCHDOG_INIT)
|
||||
static_assert(WDT_TIMEOUT_US > 1000, "WDT Timout is too small, aborting");
|
||||
static_assert(WDT_TIMEOUT_US > 1000, "WDT Timeout is too small, aborting");
|
||||
watchdog_enable(WDT_TIMEOUT_US/1000, true);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
|
|||
tc->COUNT32.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;
|
||||
//set prescaler
|
||||
//the clock normally counts at the GCLK_TC frequency, but we can set it to divide that frequency to slow it down
|
||||
//you can use different prescaler divisons here like TC_CTRLA_PRESCALER_DIV1 to get a different range
|
||||
//you can use different prescaler divisions here like TC_CTRLA_PRESCALER_DIV1 to get a different range
|
||||
tc->COUNT32.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1 | TC_CTRLA_ENABLE; //it will divide GCLK_TC frequency by 1024
|
||||
//set the compare-capture register.
|
||||
//The counter will count up to this value (it's a 16bit counter so we use uint16_t)
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ HAL_HardwareSerial::HAL_HardwareSerial(void *peripheral) {
|
|||
}
|
||||
#endif
|
||||
|
||||
else { // else get the pins of the first peripheral occurence in PinMap
|
||||
else { // else get the pins of the first peripheral occurrence in PinMap
|
||||
_serial.pin_rx = pinmap_pin(peripheral, PinMap_UART_RX);
|
||||
_serial.pin_tx = pinmap_pin(peripheral, PinMap_UART_TX);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@
|
|||
This HAL is intended to act as the generic STM32 HAL for all STM32 chips (The whole F, H and L family).
|
||||
|
||||
Currently it supports:
|
||||
* STM32F0xx
|
||||
* STM32F1xx
|
||||
* STM32F4xx
|
||||
* STM32F7xx
|
||||
|
||||
- STM32F0xx
|
||||
- STM32F1xx
|
||||
- STM32F4xx
|
||||
- STM32F7xx
|
||||
|
||||
Targeting the official [Arduino STM32 Core](https://github.com/stm32duino/Arduino_Core_STM32).
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ uint16_t MarlinHAL::adc_result;
|
|||
|
||||
#include <STM32ADC.h>
|
||||
|
||||
// Init the AD in continuous capture mode
|
||||
// Init the ADC in continuous capture mode
|
||||
void MarlinHAL::adc_init() {
|
||||
static const uint8_t adc_pins[] = {
|
||||
OPTITEM(HAS_TEMP_ADC_0, TEMP_0_PIN )
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ This HAL is for STM32F103 boards used with [Arduino STM32](https://github.com/ro
|
|||
Currently has been tested in Malyan M200 (103CBT6), SKRmini (103RCT6), Chitu 3d (103ZET6), and various 103VET6 boards.
|
||||
|
||||
### Main developers:
|
||||
|
||||
- Victorpv
|
||||
- xC000005
|
||||
- thisiskeithb
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#include "unwinder.h"
|
||||
|
||||
/** The maximum number of instructions to interpet in a function.
|
||||
/** The maximum number of instructions to interpret in a function.
|
||||
* Unwinding will be unconditionally stopped and UNWIND_EXHAUSTED returned
|
||||
* if more than this number of instructions are interpreted in a single
|
||||
* function without unwinding a stack frame. This prevents infinite loops
|
||||
|
|
|
|||
|
|
@ -483,7 +483,7 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
|
|||
// Check if the kill button was pressed and wait to ensure the signal is not noise
|
||||
// typically caused by poor insulation and grounding on LCD cables.
|
||||
// Lower numbers here will increase response time and therefore safety rating.
|
||||
// It is recommended to set this as low as possibe without false triggers.
|
||||
// It is recommended to set this as low as possible without false triggers.
|
||||
// -------------------------------------------------------------------------------
|
||||
#ifndef KILL_DELAY
|
||||
#define KILL_DELAY 250
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ void EasythreedUI::loadButton() {
|
|||
break;
|
||||
|
||||
case FS_PROCEED: {
|
||||
// Feed or Retract just once. Hard abort all moves and return to idle on swicth release.
|
||||
// Feed or Retract just once. Hard abort all moves and return to idle on switch release.
|
||||
static bool flag = false;
|
||||
if (READ(BTN_RETRACT) && READ(BTN_FEED)) { // Switch in center position (stop)
|
||||
flag = false; // Restore flag to false
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
Startup sequence
|
||||
================
|
||||
# Startup sequence
|
||||
|
||||
When initialized, MMU sends
|
||||
|
||||
|
|
@ -20,18 +19,17 @@ We follow with
|
|||
#endif
|
||||
|
||||
- MMU <= 'P0\n'
|
||||
- MMU => '*FINDA status*\n'
|
||||
- MMU => '_FINDA status_\n'
|
||||
|
||||
Now we are sure MMU is available and ready. If there was a timeout or other communication problem somewhere, printer will be killed.
|
||||
|
||||
- *Firmware version* is an integer value, but we don't care about it
|
||||
- *Build number* is an integer value and has to be >=126, or =>132 if 12V mode is enabled
|
||||
- *FINDA status* is 1 if the filament is loaded to the extruder, 0 otherwise
|
||||
- _Firmware version_ is an integer value, but we don't care about it
|
||||
- _Build number_ is an integer value and has to be >=126, or =>132 if 12V mode is enabled
|
||||
- _FINDA status_ is 1 if the filament is loaded to the extruder, 0 otherwise
|
||||
|
||||
*Build number* is checked against the required value, if it does not match, printer is halted.
|
||||
_Build number_ is checked against the required value, if it does not match, printer is halted.
|
||||
|
||||
Toolchange
|
||||
==========
|
||||
# Toolchange
|
||||
|
||||
- MMU <= 'T*Filament index*\n'
|
||||
|
||||
|
|
@ -51,16 +49,14 @@ When done, the MMU sends
|
|||
We don't wait for a response here but immediately continue with the next G-code which should
|
||||
be one or more extruder moves to feed the filament into the hotend.
|
||||
|
||||
FINDA status
|
||||
============
|
||||
# FINDA status
|
||||
|
||||
- MMU <= 'P0\n'
|
||||
- MMU => '*FINDA status*\n'
|
||||
- MMU => '_FINDA status_\n'
|
||||
|
||||
*FINDA status* is 1 if the is filament loaded to the extruder, 0 otherwise. This could be used as filament runout sensor if probed regularly.
|
||||
_FINDA status_ is 1 if the is filament loaded to the extruder, 0 otherwise. This could be used as filament runout sensor if probed regularly.
|
||||
|
||||
Load filament
|
||||
=============
|
||||
# Load filament
|
||||
|
||||
- MMU <= 'L*Filament index*\n'
|
||||
|
||||
|
|
@ -68,8 +64,7 @@ MMU will feed filament down to the extruder, when done
|
|||
|
||||
- MMU => 'ok\n'
|
||||
|
||||
Unload filament
|
||||
=============
|
||||
# Unload filament
|
||||
|
||||
- MMU <= 'U0\n'
|
||||
|
||||
|
|
@ -77,8 +72,7 @@ MMU will retract current filament from the extruder, when done
|
|||
|
||||
- MMU => 'ok\n'
|
||||
|
||||
Eject filament
|
||||
==============
|
||||
# Eject filament
|
||||
|
||||
- MMU <= 'E*Filament index*\n'
|
||||
- MMU => 'ok\n'
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ This set of responses combines to indicate firmware version 3.0.2.
|
|||
## Startup sequence
|
||||
|
||||
When initialized the MMU waits for requests. Marlin repeatedly sends `S0` commands until it gets an answer:
|
||||
|
||||
```
|
||||
MMU3:>S0*c6\n
|
||||
MMU3:>S0*c6\n
|
||||
|
|
@ -36,11 +37,13 @@ MMU3:>S0*c6\n
|
|||
```
|
||||
|
||||
Once communication is established the MMU responds with:
|
||||
|
||||
```
|
||||
MMU3:<S0 A3*22\n
|
||||
```
|
||||
|
||||
Then Marlin continues to get the rest of the MMU firmware version.
|
||||
|
||||
```
|
||||
MMU3:>S1*ad\n
|
||||
MMU3:<S1 A0*34\n
|
||||
|
|
@ -49,6 +52,7 @@ MMU3:<S2 A2*65\n
|
|||
```
|
||||
|
||||
Setting the stepper mode to SpreadCycle (M0) or StealthChop (M1):
|
||||
|
||||
```
|
||||
MMU3:>M1*{CRC8};
|
||||
MMU3:<---nothing---
|
||||
|
|
@ -61,10 +65,10 @@ MMU3:<P0 A{FINDA status}*{CRC8}\n
|
|||
|
||||
At this point we can be sure the MMU is available and ready. If there was a timeout or other communication problem somewhere, the printer will not be killed, but for safety the MMU feature will be disabled.
|
||||
|
||||
- *Firmware version* is an integer value, and we care about it. As there is no other way of knowing which protocol to use.
|
||||
- *FINDA status* is 1 if the filament is loaded to the extruder, 0 otherwise.
|
||||
- _Firmware version_ is an integer value, and we care about it. As there is no other way of knowing which protocol to use.
|
||||
- _FINDA status_ is 1 if the filament is loaded to the extruder, 0 otherwise.
|
||||
|
||||
The *Firmware version* is checked against the required value. If it doesn't match the printer will not be halted, but for safety the MMU feature will be disabled.
|
||||
The _Firmware version_ is checked against the required value. If it doesn't match the printer will not be halted, but for safety the MMU feature will be disabled.
|
||||
|
||||
## Toolchange
|
||||
|
||||
|
|
@ -74,11 +78,13 @@ MMU3:<Q0*ea\n
|
|||
```
|
||||
|
||||
The MMU sends:
|
||||
|
||||
```
|
||||
MMU3:<T{filament index}*P{ProgressCode}{CRC8}\n
|
||||
```
|
||||
|
||||
Which in normal operation would be as follows, let's say that we requested MMU to load `T0``:
|
||||
|
||||
```
|
||||
MMU3:>T0*{CRC8}\n
|
||||
|
||||
|
|
@ -96,6 +102,7 @@ MMU3:>C0*{CRC8}\n
|
|||
```
|
||||
|
||||
The MMU will feed a few more millimeters of filament for the extruder gears to grab. When done, the MMU sends:
|
||||
|
||||
```
|
||||
MMU3:>Q0*{CRC8}\n
|
||||
MMU3:<T0*P9{CRC8}\n # P9 => FinishingMoves
|
||||
|
|
@ -103,18 +110,20 @@ MMU3:<T0*P9{CRC8}\n # P9 => FinishingMoves
|
|||
|
||||
After the `T0*P9` response we immediately continue with the next G-code which should be one or more extruder moves to feed the filament into the hotend.
|
||||
|
||||
|
||||
## FINDA status
|
||||
|
||||
```
|
||||
MMU3:>P0*{CRC8}\n
|
||||
```
|
||||
|
||||
If the filament is loaded to the extruder, FINDA status is 1 and the MMU responds with:
|
||||
|
||||
```
|
||||
MMU3:<P0 A1*{CRC8}\n
|
||||
```
|
||||
|
||||
…otherwise it replies:
|
||||
|
||||
```
|
||||
MMU3:<P0 A0*7b\n
|
||||
```
|
||||
|
|
@ -124,22 +133,26 @@ This could be used as a filament runout sensor if polled regularly.
|
|||
## Load filament
|
||||
|
||||
To load a filament to the MMU itself, we run:
|
||||
|
||||
```
|
||||
MMU3:>L{Filament index}*{CRC8}\n
|
||||
MMU3:<L{Filament index} A1*{CRC8}\n
|
||||
```
|
||||
|
||||
…and immediately after that we query the status:
|
||||
|
||||
```
|
||||
MMU3:>Q0*{CRC8}\n
|
||||
```
|
||||
|
||||
The MMU will respond with status messages:
|
||||
|
||||
```
|
||||
MMU3:<L0*P5{CRC8}\n
|
||||
```
|
||||
|
||||
The MMU will load the filament and when done:
|
||||
|
||||
```
|
||||
MMU3:>Q0*{CRC8}\n
|
||||
MMU3:<L0*P9{CRC8}\n
|
||||
|
|
|
|||
|
|
@ -1162,7 +1162,7 @@ namespace MMU3 {
|
|||
//
|
||||
// Instead of doing a very long extrude as in PrusaFirmware,
|
||||
// Marlin's own MMU2s code has a better approach to this by spinning
|
||||
// the extruder indefinitelly...
|
||||
// the extruder indefinitely...
|
||||
//
|
||||
// this ensures that while the MMU is pushing the filament,
|
||||
// the extruder will keep rotating, preventing the filament to hit
|
||||
|
|
|
|||
|
|
@ -115,12 +115,12 @@
|
|||
void powerOn();
|
||||
|
||||
// Read from a MMU register (See gcode M707)
|
||||
// @param address Address of register in hexidecimal
|
||||
// @param address Address of register in hexadecimal
|
||||
// @return true upon success
|
||||
bool readRegister(uint8_t address);
|
||||
|
||||
// Write from a MMU register (See gcode M708)
|
||||
// @param address Address of register in hexidecimal
|
||||
// @param address Address of register in hexadecimal
|
||||
// @param data Data to write to register
|
||||
// @return true upon success
|
||||
bool writeRegister(uint8_t address, uint16_t data);
|
||||
|
|
@ -204,7 +204,7 @@
|
|||
ErrorCode getLastErrorCode() const { return lastErrorCode; }
|
||||
|
||||
// @return the version of the connected MMU FW.
|
||||
// In the future we'll return the trully detected FW version
|
||||
// In the future we'll return the truly detected FW version
|
||||
Version getMMUFWVersion() const {
|
||||
if (state() == xState::Active) {
|
||||
return { logic.mmuFwVersionMajor(), logic.mmuFwVersionMinor(), logic.mmuFwVersionRevision() };
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ namespace MMU3 {
|
|||
return (i != errorCodesEnd) ? (i - errorCodes) : (errorCodesSize - 1);
|
||||
}
|
||||
|
||||
// check that the searching algoritm works
|
||||
// check that the searching algorithm works
|
||||
// static_assert( FindErrorIndex(ERR_MECHANICAL_FINDA_DIDNT_TRIGGER) == 0);
|
||||
// static_assert( FindErrorIndex(ERR_MECHANICAL_FINDA_FILAMENT_STUCK) == 1);
|
||||
// static_assert( FindErrorIndex(ERR_MECHANICAL_FSENSOR_DIDNT_TRIGGER) == 2);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
namespace MMU3 {
|
||||
|
||||
// Can be used to block printer's filament sensor handling - to avoid errorneous injecting of M600
|
||||
// Can be used to block printer's filament sensor handling - to avoid erroneous injecting of M600
|
||||
// while doing a toolchange with the MMU
|
||||
// In case of "no filament sensor" these methods default to an empty implementation
|
||||
class FSensorBlockRunout {
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ namespace protocol {
|
|||
|
||||
// A response message - responses are being sent from the MMU into the printer as a response to a request message.
|
||||
struct ResponseMsg {
|
||||
RequestMsg request; //!< response is always preceeded by the request message
|
||||
RequestMsg request; //!< response is always preceded by the request message
|
||||
ResponseMsgParamCodes paramCode; //!< code of the parameter
|
||||
uint16_t paramValue; //!< value of the parameter
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ namespace protocol {
|
|||
|
||||
// Protocol class is responsible for creating/decoding messages in Rx/Tx buffer
|
||||
//
|
||||
// Beware - in the decoding more, it is meant to be a statefull instance which works through public methods
|
||||
// Beware - in the decoding more, it is meant to be a stateful instance which works through public methods
|
||||
// processing one input byte per call.
|
||||
class Protocol {
|
||||
public:
|
||||
|
|
@ -186,11 +186,11 @@ namespace protocol {
|
|||
static uint8_t EncodeWriteRequest(uint8_t address, uint16_t value, uint8_t *txbuff);
|
||||
|
||||
// @return the maximum byte length necessary to encode a request message
|
||||
// Beneficial in case of pre-allocating a buffer for enconding a RequestMsg.
|
||||
// Beneficial in case of pre-allocating a buffer for encoding a RequestMsg.
|
||||
static constexpr uint8_t MaxRequestSize() { return 13; }
|
||||
|
||||
// @return the maximum byte length necessary to encode a response message
|
||||
// Beneficial in case of pre-allocating a buffer for enconding a ResponseMsg.
|
||||
// Beneficial in case of pre-allocating a buffer for encoding a ResponseMsg.
|
||||
static constexpr uint8_t MaxResponseSize() { return 14; }
|
||||
|
||||
// Encode generic response Command Accepted or Rejected
|
||||
|
|
|
|||
|
|
@ -449,7 +449,7 @@ namespace MMU3 {
|
|||
|
||||
const uint8_t ei = PrusaErrorCodeIndex((ErrorCode)ec);
|
||||
|
||||
// This should be the equivelent of the switch..case above...
|
||||
// This should be the equivalent of the switch..case above...
|
||||
if ((uint8_t)ReportErrorHookState == (uint8_t)ReportErrorHookStates::RENDER_ERROR_SCREEN) {
|
||||
KEEPALIVE_STATE(PAUSED_FOR_USER);
|
||||
#if HAS_WIRED_LCD
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
* therefore the error codes have been extracted to one place.
|
||||
*
|
||||
* Please note the errors are intentionally coded as "negative" values (highest bit set),
|
||||
* becase they are a complement to reporting the state of the high-level state machines -
|
||||
* because they are a complement to reporting the state of the high-level state machines -
|
||||
* positive values are considered as normal progress, negative values are errors.
|
||||
*
|
||||
* Please note, that multiple TMC errors can occur at once, thus they are defined as a bitmask of the higher byte.
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ typedef enum : uint16_t {
|
|||
} err_num_t;
|
||||
|
||||
// Avr gcc has serious trouble understanding static data structures in PROGMEM
|
||||
// and inadvertedly falls back to copying the whole structure into RAM (which is obviously unwanted).
|
||||
// and inadvertently falls back to copying the whole structure into RAM (which is obviously unwanted).
|
||||
// But since this file ought to be generated in the future from yaml prescription,
|
||||
// it really makes no difference if there are "nice" data structures or plain arrays.
|
||||
static const constexpr err_num_t errorCodes[] PROGMEM = {
|
||||
|
|
|
|||
|
|
@ -1013,7 +1013,7 @@
|
|||
TMC_REPORT("Supply (v)", TMC_VSUPPLY);
|
||||
TMC_REPORT("Temp (°C)", TMC_TEMP);
|
||||
TMC_REPORT("OT pre warn (°C)", TMC_OVERTEMP);
|
||||
TMC_REPORT("OV theshold (v)", TMC_OVERVOLT_THD);
|
||||
TMC_REPORT("OV threshold (v)", TMC_OVERVOLT_THD);
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ void GcodeSuite::M706() {
|
|||
* M707 [ A ]
|
||||
*
|
||||
* Parameters:
|
||||
* A<hex> Address of register in hexidecimal
|
||||
* A<hex> Address of register in hexadecimal
|
||||
*
|
||||
* Example:
|
||||
* M707 A0x1b - Read a 8bit integer from register 0x1b and prints the result onto the serial line.
|
||||
|
|
@ -115,7 +115,7 @@ void GcodeSuite::M707() {
|
|||
* M708 [ A | X ]
|
||||
*
|
||||
* Parameters:
|
||||
* A<hex> Address of register in hexidecimal
|
||||
* A<hex> Address of register in hexadecimal
|
||||
* X<int> Data to write (16-bit integer). Default value 0
|
||||
*
|
||||
* Example:
|
||||
|
|
|
|||
|
|
@ -309,7 +309,7 @@ void plan_arc(
|
|||
// a) is <= any configured maximum speed,
|
||||
// b) does not require centripetal force greater than any configured maximum acceleration,
|
||||
// c) is <= nominal speed,
|
||||
// d) allows the print head to stop in the remining length of the curve within all configured maximum accelerations.
|
||||
// d) allows the print head to stop in the remaining length of the curve within all configured maximum accelerations.
|
||||
// The last has to be calculated every time through the loop.
|
||||
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]),
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
* F<watts/kelvin> Ambient heat transfer coefficient (fan on full).
|
||||
* H<joules/kelvin/mm> Filament heat capacity per mm.
|
||||
* P<watts> Heater power.
|
||||
* R<kelvin/second/kelvin> Sensor responsiveness (= transfer coefficient / heat capcity).
|
||||
* R<kelvin/second/kelvin> Sensor responsiveness (= transfer coefficient / heat capacity).
|
||||
*
|
||||
* With MPC_AUTOTUNE:
|
||||
* T Autotune the extruder specified with 'E' or the active extruder.
|
||||
|
|
@ -65,7 +65,7 @@ void GcodeSuite::M306() {
|
|||
default: tuning_type = Temperature::MPCTuningType::AUTO; break;
|
||||
}
|
||||
if (TERN0(MPC_PTC, tuning_type == Temperature::MPCTuningType::FORCE_ASYMPTOTIC))
|
||||
SERIAL_ECHOLNPGM("Aymptotic tuning not avaiable for PTC hotends");
|
||||
SERIAL_ECHOLNPGM("Asymptotic tuning not available for PTC hotends");
|
||||
else {
|
||||
LCD_MESSAGE(MSG_MPC_AUTOTUNE);
|
||||
thermalManager.MPC_autotune(e, tuning_type);
|
||||
|
|
|
|||
|
|
@ -1486,7 +1486,7 @@
|
|||
#if MB(MKS_MONSTER8_V1, BTT_SKR_MINI_E3_V1_0, BTT_SKR_MINI_E3_V1_2, BTT_SKR_MINI_E3_V2_0, BTT_SKR_MINI_E3_V3_0, BTT_SKR_MINI_E3_V3_0_1, BTT_SKR_E3_TURBO, BTT_OCTOPUS_V1_1, BTT_SKR_V3_0, BTT_SKR_V3_0_EZ, AQUILA_V101)
|
||||
|
||||
#define LCD_SERIAL_PORT 1
|
||||
#elif MB(CREALITY_V24S1_301, CREALITY_V24S1_301F4, CREALITY_F401RE, CREALITY_V423, CREALITY_CR4NTXXC10, CREALITY_CR4NS, MKS_ROBIN, PANOWIN_CUTLASS, KODAMA_BARDO)
|
||||
#elif MB(CREALITY_V24S1_301, CREALITY_V24S1_301F4, CREALITY_F401RE, CREALITY_V422_GD32_MFL, CREALITY_V423, CREALITY_V427_GD32_MFL, CREALITY_CR4NTXXC10, CREALITY_CR4NS, MKS_ROBIN, PANOWIN_CUTLASS, KODAMA_BARDO)
|
||||
#define LCD_SERIAL_PORT 2
|
||||
#else
|
||||
#define LCD_SERIAL_PORT 3
|
||||
|
|
|
|||
|
|
@ -77,18 +77,20 @@
|
|||
* tell you about new options that you might find useful. So it's recommended to transfer
|
||||
* your settings to new Configuration files matching your Marlin version as soon as possible.
|
||||
*/
|
||||
#define HEXIFY(H) _CAT(0x,H)
|
||||
#if !defined(CONFIGURATION_H_VERSION) || HEXIFY(CONFIGURATION_H_VERSION) < HEXIFY(REQUIRED_CONFIGURATION_H_VERSION)
|
||||
#error "Your Configuration.h file is for an old version of Marlin. Downgrade Marlin or upgrade your Configuration.h."
|
||||
#elif HEXIFY(CONFIGURATION_H_VERSION) > HEXIFY(REQUIRED_CONFIGURATION_H_VERSION)
|
||||
#error "Your Configuration.h file is for a newer version of Marlin. Upgrade Marlin or downgrade your Configuration.h."
|
||||
#endif
|
||||
#if !defined(CONFIGURATION_ADV_H_VERSION) || HEXIFY(CONFIGURATION_ADV_H_VERSION) < HEXIFY(REQUIRED_CONFIGURATION_ADV_H_VERSION)
|
||||
#error "Your Configuration_adv.h file is for an old version of Marlin. Downgrade Marlin or upgrade your Configuration_adv.h."
|
||||
#elif HEXIFY(CONFIGURATION_ADV_H_VERSION) > HEXIFY(REQUIRED_CONFIGURATION_ADV_H_VERSION)
|
||||
#error "Your Configuration_adv.h file is for a newer version of Marlin. Upgrade Marlin or downgrade your Configuration_adv.h."
|
||||
#endif
|
||||
#undef HEXIFY
|
||||
#if USE_STD_CONFIGS
|
||||
#define HEXIFY(H) _CAT(0x,H)
|
||||
#if !defined(CONFIGURATION_H_VERSION) || HEXIFY(CONFIGURATION_H_VERSION) < HEXIFY(REQUIRED_CONFIGURATION_H_VERSION)
|
||||
#error "Your Configuration.h file is for an old version of Marlin. Downgrade Marlin or upgrade your Configuration.h."
|
||||
#elif HEXIFY(CONFIGURATION_H_VERSION) > HEXIFY(REQUIRED_CONFIGURATION_H_VERSION)
|
||||
#error "Your Configuration.h file is for a newer version of Marlin. Upgrade Marlin or downgrade your Configuration.h."
|
||||
#endif
|
||||
#if !defined(CONFIGURATION_ADV_H_VERSION) || HEXIFY(CONFIGURATION_ADV_H_VERSION) < HEXIFY(REQUIRED_CONFIGURATION_ADV_H_VERSION)
|
||||
#error "Your Configuration_adv.h file is for an old version of Marlin. Downgrade Marlin or upgrade your Configuration_adv.h."
|
||||
#elif HEXIFY(CONFIGURATION_ADV_H_VERSION) > HEXIFY(REQUIRED_CONFIGURATION_ADV_H_VERSION)
|
||||
#error "Your Configuration_adv.h file is for a newer version of Marlin. Upgrade Marlin or downgrade your Configuration_adv.h."
|
||||
#endif
|
||||
#undef HEXIFY
|
||||
#endif // HAS_IGNORED_CONFIGS
|
||||
|
||||
/**
|
||||
* Warnings for old configurations
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
* version was tagged.
|
||||
*/
|
||||
#ifndef STRING_DISTRIBUTION_DATE
|
||||
#define STRING_DISTRIBUTION_DATE "2025-08-26"
|
||||
#define STRING_DISTRIBUTION_DATE "2025-09-09"
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -290,17 +290,17 @@ void MarlinUI::draw_status_screen() {
|
|||
);
|
||||
}
|
||||
|
||||
uint16_t hx = STATUS_HEATERS_X;
|
||||
uint16_t shx = STATUS_HEATERS_X;
|
||||
#if HAS_HOTEND
|
||||
_draw_heater_status(H_E0, hx, STATUS_HEATERS_Y);
|
||||
hx += STATUS_HEATERS_XSPACE;
|
||||
_draw_heater_status(H_E0, shx, STATUS_HEATERS_Y);
|
||||
shx += STATUS_HEATERS_XSPACE;
|
||||
#endif
|
||||
#if HAS_MULTI_HOTEND
|
||||
_draw_heater_status(H_E1, hx, STATUS_HEATERS_Y);
|
||||
hx += STATUS_HEATERS_XSPACE;
|
||||
_draw_heater_status(H_E1, shx, STATUS_HEATERS_Y);
|
||||
shx += STATUS_HEATERS_XSPACE;
|
||||
#endif
|
||||
#if HAS_HEATED_BED
|
||||
_draw_heater_status(H_BED, hx, STATUS_HEATERS_Y);
|
||||
_draw_heater_status(H_BED, shx, STATUS_HEATERS_Y);
|
||||
#endif
|
||||
#if HAS_FAN
|
||||
_draw_fan_status(LCD_PIXEL_WIDTH - STATUS_CHR_WIDTH * 5, STATUS_FAN_Y);
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ fileprop_t fileprop;
|
|||
void getValue(const char * const buf, PGM_P const key, float &value) {
|
||||
if (value != 0.0f) return;
|
||||
|
||||
char *posptr = strstr_P(buf, key);
|
||||
const char *posptr = strstr_P(buf, key);
|
||||
if (posptr == nullptr) return;
|
||||
|
||||
char num[10] = "";
|
||||
|
|
@ -101,8 +101,9 @@ void getValue(const char * const buf, PGM_P const key, float &value) {
|
|||
|
||||
bool Preview::hasPreview() {
|
||||
const char * const tbstart = PSTR("; thumbnail begin " STRINGIFY(THUMBWIDTH) "x" STRINGIFY(THUMBHEIGHT));
|
||||
char *posptr = nullptr;
|
||||
const char *posptr = nullptr;
|
||||
uint32_t indx = 0;
|
||||
uint32_t prev_indx = 0;
|
||||
float tmp = 0;
|
||||
|
||||
fileprop.clear();
|
||||
|
|
@ -114,7 +115,7 @@ bool Preview::hasPreview() {
|
|||
uint8_t nbyte = 1;
|
||||
while (!fileprop.thumbstart && nbyte > 0 && indx < 4 * sizeof(buf)) {
|
||||
nbyte = card.read(buf, sizeof(buf) - 1);
|
||||
if (nbyte > 0) {
|
||||
if (nbyte >= 0) {
|
||||
buf[nbyte] = '\0';
|
||||
getValue(buf, PSTR(";TIME:"), fileprop.time);
|
||||
getValue(buf, PSTR(";Filament used:"), fileprop.filament);
|
||||
|
|
@ -132,13 +133,17 @@ bool Preview::hasPreview() {
|
|||
fileprop.height -= tmp;
|
||||
posptr = strstr_P(buf, tbstart);
|
||||
if (posptr != nullptr) {
|
||||
fileprop.thumbstart = indx + (posptr - &buf[0]);
|
||||
fileprop.thumbstart = indx + (posptr - buf);
|
||||
}
|
||||
else {
|
||||
indx += _MAX(10, nbyte - (signed)strlen_P(tbstart));
|
||||
if (indx <= prev_indx) break;
|
||||
prev_indx = indx;
|
||||
card.setIndex(indx);
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (!fileprop.thumbstart) {
|
||||
|
|
@ -190,7 +195,7 @@ void Preview::drawFromSD() {
|
|||
return;
|
||||
}
|
||||
|
||||
MString<45> buf;
|
||||
TString 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);
|
||||
|
|
@ -210,7 +215,7 @@ void Preview::drawFromSD() {
|
|||
}
|
||||
DWINUI::drawButton(BTN_Print, 26, 290);
|
||||
DWINUI::drawButton(BTN_Cancel, 146, 290);
|
||||
show();
|
||||
if (fileprop.thumbsize) show();
|
||||
drawSelectHighlight(true, 290);
|
||||
dwinUpdateLCD();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@
|
|||
#endif
|
||||
|
||||
typedef struct {
|
||||
int32_t maxValue = 0; // Auxiliar max integer/scaled float value
|
||||
int32_t minValue = 0; // Auxiliar min integer/scaled float value
|
||||
int8_t dp = 0; // Auxiliar decimal places
|
||||
int32_t value = 0; // Auxiliar integer / scaled float value
|
||||
int16_t *intPtr = nullptr; // Auxiliar pointer to 16 bit integer variable
|
||||
float *floatPtr = nullptr; // Auxiliar pointer to float variable
|
||||
void (*apply)() = nullptr; // Auxiliar apply function
|
||||
void (*liveUpdate)() = nullptr; // Auxiliar live update function
|
||||
int32_t maxValue = 0; // Auxiliary max integer/scaled float value
|
||||
int32_t minValue = 0; // Auxiliary min integer/scaled float value
|
||||
int8_t dp = 0; // Auxiliary decimal places
|
||||
int32_t value = 0; // Auxiliary integer / scaled float value
|
||||
int16_t *intPtr = nullptr; // Auxiliary pointer to 16 bit integer variable
|
||||
float *floatPtr = nullptr; // Auxiliary pointer to float variable
|
||||
void (*apply)() = nullptr; // Auxiliary apply function
|
||||
void (*liveUpdate)() = nullptr; // Auxiliary live update function
|
||||
} MenuData_t;
|
||||
|
||||
extern MenuData_t menuData;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
* (not affiliated with Anycubic, Ltd.)
|
||||
*
|
||||
* The AC panel wants files in block of 4 and can only display a flat list
|
||||
* This library allows full folder traversal or flat file display and supports both standerd and new style panels.
|
||||
* This library allows full folder traversal or flat file display and supports both standard and new style panels.
|
||||
*
|
||||
* ## Old Style TFT panel
|
||||
* Supported chars {}[]-+=_"$%^&*()~<>|
|
||||
|
|
|
|||
|
|
@ -496,7 +496,7 @@ namespace Anycubic {
|
|||
#endif
|
||||
case AC_printer_printing:
|
||||
case AC_printer_paused:
|
||||
// Heater timout, send acknowledgement
|
||||
// Heater timeout, send acknowledgement
|
||||
if (strcmp_P(msg, MARLIN_msg_heater_timeout) == 0) {
|
||||
pause_state = AC_paused_heater_timed_out;
|
||||
tftSendLn(AC_msg_paused); // enable continue button
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
FTDI EVE Library
|
||||
----------------
|
||||
## FTDI EVE Library
|
||||
|
||||
The FTDI EVE Library is a fully open-source library and UI framework for the FTDI
|
||||
FT800 and FT810 graphics processor.
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ void MoveAxisScreen::onRedraw(draw_mode_t what) {
|
|||
#endif
|
||||
w.increments();
|
||||
#ifdef PARKING_COMMAND_GCODE
|
||||
if (!ExtUI::isPrinting()) { // making sure the Tool Head Swap Position is not avalible while printing
|
||||
if (!ExtUI::isPrinting()) { // making sure the Tool Head Swap Position is not available while printing
|
||||
cmd.font(font_medium)
|
||||
.colors(normal_btn)
|
||||
.tag(25).button(BTN_POS(1,(7+EXTRUDERS)), BTN_SIZE(13,1), GET_TEXT_F(MSG_TOOL_HEAD_SWAP));
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ void xatc_wizard_goto_next_point() {
|
|||
z_offset /= XATC_MAX_POINTS;
|
||||
|
||||
// Subtract the average from the values found with this wizard.
|
||||
// This way they are indipendent from the z-offset
|
||||
// This way they are independent from the z-offset
|
||||
for (uint8_t i = 0; i < XATC_MAX_POINTS; ++i) xatc.z_offset[i] -= z_offset;
|
||||
|
||||
ui.goto_screen(xatc_wizard_update_z_offset);
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ void Canvas::addImage(int16_t x, int16_t y, MarlinImage image, uint16_t *colors)
|
|||
rle_state.dsty = dsty;
|
||||
rle_state.srcx = srcx;
|
||||
rle_state.srcy = srcy;
|
||||
rle_state.rle_offset = bytedata - (uint8_t *)images[image].data;; // Keep these for skipping full RLE decode on future iteratons
|
||||
rle_state.rle_offset = bytedata - (uint8_t *)images[image].data;; // Keep these for skipping full RLE decode on future iterations
|
||||
}
|
||||
|
||||
uint8_t count = *bytedata++; // Get the count byte
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ void TFT_String::add_glyphs(const uint8_t *font) {
|
|||
}
|
||||
|
||||
glyph_t *TFT_String::glyph(uint16_t character) {
|
||||
if (character == 0x2026) character = 0x0a; /* character 0x2026 "…" is remaped to 0x0a and should be part of symbols font */
|
||||
if (character == 0x2026) character = 0x0a; /* character 0x2026 "…" is remapped to 0x0a and should be part of symbols font */
|
||||
if (character < 0x00ff) return glyphs[character] ?: glyphs['?']; /* Use '?' for unknown glyphs */
|
||||
|
||||
#if EXTRA_GLYPHS
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ ft_command_t FTMotion::stepperCmdBuff[FTM_STEPPERCMD_BUFF_SIZE] = {0U}; // Stepp
|
|||
int32_t FTMotion::stepperCmdBuff_produceIdx = 0, // Index of next stepper command write to the buffer.
|
||||
FTMotion::stepperCmdBuff_consumeIdx = 0; // Index of next stepper command read from the buffer.
|
||||
|
||||
bool FTMotion::sts_stepperBusy = false; // The stepper buffer has items and is in use.
|
||||
bool FTMotion::stepperCmdBuffHasData = false; // The stepper buffer has items and is in use.
|
||||
|
||||
XYZEval<millis_t> FTMotion::axis_move_end_ti = { 0 };
|
||||
AxisBits FTMotion::axis_move_dir;
|
||||
|
|
@ -64,9 +64,9 @@ bool FTMotion::batchRdyForInterp = false; // Indicates the batch is done b
|
|||
// ... if applicable, and is ready to be converted to step commands.
|
||||
|
||||
// Trapezoid data variables.
|
||||
xyze_pos_t FTMotion::startPosn, // (mm) Start position of block
|
||||
FTMotion::endPosn_prevBlock = { 0.0f }; // (mm) End position of previous block
|
||||
xyze_float_t FTMotion::ratio; // (ratio) Axis move ratio of block
|
||||
xyze_pos_t FTMotion::startPos, // (mm) Start position of block
|
||||
FTMotion::endPos_prevBlock = { 0.0f }; // (mm) End position of previous block
|
||||
xyze_float_t FTMotion::ratio; // (ratio) Axis move ratio of block
|
||||
float FTMotion::accel_P, // Acceleration prime of block. [mm/sec/sec]
|
||||
FTMotion::decel_P, // Deceleration prime of block. [mm/sec/sec]
|
||||
FTMotion::F_P, // Feedrate prime of block. [mm/sec]
|
||||
|
|
@ -135,7 +135,7 @@ void FTMotion::loop() {
|
|||
* 4. Signal ready for new block.
|
||||
*/
|
||||
if (stepper.abort_current_block) {
|
||||
if (sts_stepperBusy) return; // Wait until motion buffers are emptied
|
||||
if (stepperCmdBuffHasData) return; // Wait until motion buffers are emptied
|
||||
discard_planner_block_protected();
|
||||
reset();
|
||||
stepper.abort_current_block = false; // Abort finished.
|
||||
|
|
@ -149,13 +149,13 @@ void FTMotion::loop() {
|
|||
continue;
|
||||
}
|
||||
loadBlockData(stepper.current_block);
|
||||
blockProcRdy = true;
|
||||
|
||||
// If the endstop is already pressed, endstop interrupts won't invoke
|
||||
// endstop_triggered and the move will grind. So check here for a
|
||||
// triggered endstop, which shortly marks the block for discard.
|
||||
endstops.update();
|
||||
|
||||
blockProcRdy = true;
|
||||
// Some kinematics track axis motion in HX, HY, HZ
|
||||
#if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX)
|
||||
stepper.last_direction_bits.hx = stepper.current_block->direction_bits.hx;
|
||||
|
|
@ -170,18 +170,14 @@ void FTMotion::loop() {
|
|||
|
||||
if (blockProcRdy) {
|
||||
|
||||
if (!batchRdy) makeVector(); // Caution: Do not consolidate checks on blockProcRdy/batchRdy, as they are written by makeVector().
|
||||
// When makeVector is finished: either blockProcRdy has been set false (because the block is
|
||||
// done being processed) or batchRdy is set true, or both.
|
||||
if (!batchRdy) makeVector(); // may clear blockProcRdy
|
||||
|
||||
// Check if the block has been completely converted:
|
||||
if (!blockProcRdy) {
|
||||
discard_planner_block_protected();
|
||||
|
||||
// Check if the block needs to be runout:
|
||||
if (!batchRdy && !planner.has_blocks_queued()) {
|
||||
runoutBlock();
|
||||
makeVector(); // Do an additional makeVector call to guarantee batchRdy set this loop.
|
||||
makeVector(); // Additional call to guarantee batchRdy is set this loop.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -220,7 +216,7 @@ void FTMotion::loop() {
|
|||
}
|
||||
|
||||
// Report busy status to planner.
|
||||
busy = (sts_stepperBusy || blockProcRdy || batchRdy || batchRdyForInterp);
|
||||
busy = (stepperCmdBuffHasData || blockProcRdy || batchRdy || batchRdyForInterp);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -386,7 +382,7 @@ void FTMotion::reset() {
|
|||
|
||||
blockProcRdy = batchRdy = batchRdyForInterp = false;
|
||||
|
||||
endPosn_prevBlock.reset();
|
||||
endPos_prevBlock.reset();
|
||||
|
||||
makeVector_idx = 0;
|
||||
makeVector_batchIdx = TERN(FTM_UNIFIED_BWS, 0, _MIN(BATCH_SIDX_IN_WINDOW, FTM_BATCH_SIZE));
|
||||
|
|
@ -424,13 +420,13 @@ void FTMotion::discard_planner_block_protected() {
|
|||
/**
|
||||
* Set up a pseudo block to allow motion to settle and buffers to empty.
|
||||
* Called when the planner has one block left. The buffers will be filled
|
||||
* with the last commanded position by setting the startPosn block variable to
|
||||
* with the last commanded position by setting the startPos block variable to
|
||||
* the last position of the previous block and all ratios to zero such that no
|
||||
* axes' positions are incremented.
|
||||
*/
|
||||
void FTMotion::runoutBlock() {
|
||||
|
||||
startPosn = endPosn_prevBlock;
|
||||
startPos = endPos_prevBlock;
|
||||
ratio.reset();
|
||||
|
||||
const int32_t n_to_fill_batch = (FTM_WINDOW_SIZE) - makeVector_batchIdx;
|
||||
|
|
@ -466,19 +462,9 @@ void FTMotion::loadBlockData(block_t * const current_block) {
|
|||
const float totalLength = current_block->millimeters,
|
||||
oneOverLength = 1.0f / totalLength;
|
||||
|
||||
startPosn = endPosn_prevBlock;
|
||||
const xyze_pos_t moveDist = LOGICAL_AXIS_ARRAY(
|
||||
current_block->steps.e * planner.mm_per_step[block_extruder_axis] * (current_block->direction_bits.e ? 1 : -1),
|
||||
current_block->steps.x * planner.mm_per_step[X_AXIS] * (current_block->direction_bits.x ? 1 : -1),
|
||||
current_block->steps.y * planner.mm_per_step[Y_AXIS] * (current_block->direction_bits.y ? 1 : -1),
|
||||
current_block->steps.z * planner.mm_per_step[Z_AXIS] * (current_block->direction_bits.z ? 1 : -1),
|
||||
current_block->steps.i * planner.mm_per_step[I_AXIS] * (current_block->direction_bits.i ? 1 : -1),
|
||||
current_block->steps.j * planner.mm_per_step[J_AXIS] * (current_block->direction_bits.j ? 1 : -1),
|
||||
current_block->steps.k * planner.mm_per_step[K_AXIS] * (current_block->direction_bits.k ? 1 : -1),
|
||||
current_block->steps.u * planner.mm_per_step[U_AXIS] * (current_block->direction_bits.u ? 1 : -1),
|
||||
current_block->steps.v * planner.mm_per_step[V_AXIS] * (current_block->direction_bits.v ? 1 : -1),
|
||||
current_block->steps.w * planner.mm_per_step[W_AXIS] * (current_block->direction_bits.w ? 1 : -1)
|
||||
);
|
||||
startPos = endPos_prevBlock;
|
||||
|
||||
const xyze_pos_t& moveDist = current_block->dist_mm;
|
||||
|
||||
ratio = moveDist * oneOverLength;
|
||||
|
||||
|
|
@ -561,22 +547,19 @@ void FTMotion::loadBlockData(block_t * const current_block) {
|
|||
// Accel + Coasting + Decel datapoints
|
||||
max_intervals = N1 + N2 + N3;
|
||||
|
||||
endPosn_prevBlock += moveDist;
|
||||
endPos_prevBlock += moveDist;
|
||||
|
||||
// Watch endstops until the move ends
|
||||
const millis_t move_end_ti = millis() + SEC_TO_MS((FTM_TS) * float(max_intervals + num_samples_shaper_settle() + ((PROP_BATCHES) + 1) * (FTM_BATCH_SIZE)) + (float(FTM_STEPPERCMD_BUFF_SIZE) / float(FTM_STEPPER_FS)));
|
||||
|
||||
#define __SET_MOVE_END(A,V) do{ if (V) { axis_move_end_ti.A = move_end_ti; axis_move_dir.A = (V > 0); } }while(0);
|
||||
#define _SET_MOVE_END(A) __SET_MOVE_END(A, moveDist[_AXIS(A)])
|
||||
#if CORE_IS_XY
|
||||
__SET_MOVE_END(X, moveDist.x + moveDist.y);
|
||||
__SET_MOVE_END(Y, moveDist.x - moveDist.y);
|
||||
#else
|
||||
_SET_MOVE_END(X);
|
||||
_SET_MOVE_END(Y);
|
||||
#endif
|
||||
TERN_(HAS_Z_AXIS, _SET_MOVE_END(Z));
|
||||
SECONDARY_AXIS_MAP(_SET_MOVE_END);
|
||||
#define _SET_MOVE_END(A) do{ \
|
||||
if (moveDist.A) { \
|
||||
axis_move_end_ti.A = move_end_ti; \
|
||||
axis_move_dir.A = moveDist.A > 0; \
|
||||
} \
|
||||
}while(0);
|
||||
|
||||
LOGICAL_AXIS_MAP(_SET_MOVE_END);
|
||||
}
|
||||
|
||||
// Generate data points of the trajectory.
|
||||
|
|
@ -605,7 +588,7 @@ void FTMotion::makeVector() {
|
|||
TERN_(HAS_EXTRUDERS, accel_k = decel_P); // (mm/s^2) Acceleration K factor from Decel phase
|
||||
}
|
||||
|
||||
#define _SET_TRAJ(q) traj.q[makeVector_batchIdx] = startPosn.q + ratio.q * dist;
|
||||
#define _SET_TRAJ(q) traj.q[makeVector_batchIdx] = startPos.q + ratio.q * dist;
|
||||
LOGICAL_AXIS_MAP_LC(_SET_TRAJ);
|
||||
|
||||
#if HAS_EXTRUDERS
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ class FTMotion {
|
|||
static int32_t stepperCmdBuff_produceIdx, // Index of next stepper command write to the buffer.
|
||||
stepperCmdBuff_consumeIdx; // Index of next stepper command read from the buffer.
|
||||
|
||||
static bool sts_stepperBusy; // The stepper buffer has items and is in use.
|
||||
static bool stepperCmdBuffHasData; // The stepper buffer has items and is in use.
|
||||
|
||||
static XYZEval<millis_t> axis_move_end_ti;
|
||||
static AxisBits axis_move_dir;
|
||||
|
|
@ -145,9 +145,9 @@ class FTMotion {
|
|||
static bool batchRdy, batchRdyForInterp;
|
||||
|
||||
// Trapezoid data variables.
|
||||
static xyze_pos_t startPosn, // (mm) Start position of block
|
||||
endPosn_prevBlock; // (mm) End position of previous block
|
||||
static xyze_float_t ratio; // (ratio) Axis move ratio of block
|
||||
static xyze_pos_t startPos, // (mm) Start position of block
|
||||
endPos_prevBlock; // (mm) End position of previous block
|
||||
static xyze_float_t ratio; // (ratio) Axis move ratio of block
|
||||
static float accel_P, decel_P,
|
||||
F_P,
|
||||
f_s,
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ planner_settings_t Planner::settings; // Initialized by settings.load
|
|||
|
||||
/**
|
||||
* Set up inline block variables
|
||||
* Set laser_power_floor based on SPEED_POWER_MIN to pevent a zero power output state with LASER_POWER_TRAP
|
||||
* Set laser_power_floor based on SPEED_POWER_MIN to prevent a zero power output state with LASER_POWER_TRAP
|
||||
*/
|
||||
#if ENABLED(LASER_FEATURE)
|
||||
laser_state_t Planner::laser_inline; // Current state for blocks
|
||||
|
|
@ -2097,6 +2097,8 @@ bool Planner::_populate_block(
|
|||
TERN_(BACKLASH_COMPENSATION, backlash.add_correction_steps(dist, dm, block));
|
||||
}
|
||||
|
||||
TERN_(FT_MOTION, block->dist_mm = dist_mm); // Store the distance for all axes in mm for this block
|
||||
|
||||
TERN_(HAS_EXTRUDERS, block->steps.e = esteps);
|
||||
|
||||
block->step_event_count = (
|
||||
|
|
@ -2507,7 +2509,7 @@ bool Planner::_populate_block(
|
|||
* Compute maximum allowable entry speed at junction by centripetal acceleration approximation.
|
||||
* Let a circle be tangent to both previous and current path line segments, where the junction
|
||||
* deviation is defined as the distance from the junction to the closest edge of the circle,
|
||||
* colinear with the circle center. The circular segment joining the two paths represents the
|
||||
* collinear with the circle center. The circular segment joining the two paths represents the
|
||||
* path of centripetal acceleration. Solve for max velocity based on max acceleration about the
|
||||
* radius of the circle, defined indirectly by junction deviation. This may be also viewed as
|
||||
* path width or max_jerk in the previous Grbl version. This approach does not actually deviate
|
||||
|
|
@ -3191,7 +3193,7 @@ void Planner::set_machine_position_mm(const abce_pos_t &abce) {
|
|||
|
||||
/**
|
||||
* Set the machine positions in millimeters (soon) given the native position.
|
||||
* Synchonized with the planner queue.
|
||||
* Synchronized with the planner queue.
|
||||
*
|
||||
* - Modifiers are applied for skew, leveling, retract, etc.
|
||||
* - Kinematics are applied to remap cartesian positions to stepper positions.
|
||||
|
|
|
|||
|
|
@ -266,6 +266,10 @@ typedef struct PlannerBlock {
|
|||
|
||||
AxisBits direction_bits; // Direction bits set for this block, where 1 is negative motion
|
||||
|
||||
#if ENABLED(FT_MOTION)
|
||||
xyze_pos_t dist_mm; // The distance traveled in mm along each axis
|
||||
#endif
|
||||
|
||||
// Advance extrusion
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
#if ENABLED(SMOOTH_LIN_ADVANCE)
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ static inline float interp(const_float_t a, const_float_t b, const_float_t t) {
|
|||
* Compute a Bézier curve using the De Casteljau's algorithm (see
|
||||
* https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm), which is
|
||||
* easy to code and has good numerical stability (very important,
|
||||
* since Arudino works with limited precision real numbers).
|
||||
* since Arduino works with limited precision real numbers).
|
||||
*/
|
||||
static inline float eval_bezier(const_float_t a, const_float_t b, const_float_t c, const_float_t d, const_float_t t) {
|
||||
const float iab = interp(a, b, t),
|
||||
|
|
|
|||
|
|
@ -2474,7 +2474,7 @@ hal_timer_t Stepper::block_phase_isr() {
|
|||
* isPowered - True when a move is powered.
|
||||
* isEnabled - laser power is active.
|
||||
*
|
||||
* Laser power variables are calulated and stored in this block by the planner code.
|
||||
* Laser power variables are calculated and stored in this block by the planner code.
|
||||
* trap_ramp_active_pwr - the active power in this block across accel or decel trap steps.
|
||||
* trap_ramp_entry_incr - holds the precalculated value to increase the current power per accel step.
|
||||
*/
|
||||
|
|
@ -3565,8 +3565,8 @@ void Stepper::report_positions() {
|
|||
void Stepper::ftMotion_stepper() {
|
||||
|
||||
// Check if the buffer is empty.
|
||||
ftMotion.sts_stepperBusy = (ftMotion.stepperCmdBuff_produceIdx != ftMotion.stepperCmdBuff_consumeIdx);
|
||||
if (!ftMotion.sts_stepperBusy) return;
|
||||
ftMotion.stepperCmdBuffHasData = (ftMotion.stepperCmdBuff_produceIdx != ftMotion.stepperCmdBuff_consumeIdx);
|
||||
if (!ftMotion.stepperCmdBuffHasData) return;
|
||||
|
||||
// "Pop" one command from current motion buffer
|
||||
const ft_command_t command = ftMotion.stepperCmdBuff[ftMotion.stepperCmdBuff_consumeIdx];
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
* ...as measured on an LPC1768 with a scope and converted to cycles.
|
||||
* Not applicable to other 32-bit processors, but as long as others
|
||||
* take longer, pulses will be longer. For example the SKR Pro
|
||||
* (stm32f407zgt6) requires ~60 cyles.
|
||||
* (stm32f407zgt6) requires ~60 cycles.
|
||||
*/
|
||||
constexpr uint32_t timer_read_add_and_store_cycles = 34UL;
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
* Q_STEP_INIT() Q_STEP_WRITE(S) Q_STEP_READ()
|
||||
*
|
||||
* Steppers may not have an enable state or may be enabled by other methods
|
||||
* beyond a single pin (SOFTWARE_DRIVER_ENABLE) so these can be overriden:
|
||||
* beyond a single pin (SOFTWARE_DRIVER_ENABLE) so these can be overridden:
|
||||
* ENABLE_STEPPER_Q() DISABLE_STEPPER_Q()
|
||||
*
|
||||
* Axis Stepper Control (X Y Z I J K U V W)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
// B Value 3950K at 25/50 deg. C
|
||||
// B Value Tolerance + / - 1%
|
||||
constexpr temp_entry_t temptable_61[] PROGMEM = {
|
||||
{ OV( 2.00), 420 }, // Guestimate to ensure we don't lose a reading and drop temps to -50 when over
|
||||
{ OV( 2.00), 420 }, // Guesstimate to ensure we don't lose a reading and drop temps to -50 when over
|
||||
{ OV( 12.07), 350 },
|
||||
{ OV( 12.79), 345 },
|
||||
{ OV( 13.59), 340 },
|
||||
|
|
|
|||
|
|
@ -864,7 +864,7 @@
|
|||
#elif ENABLED(MINIPANEL)
|
||||
|
||||
#ifndef BEEPER_PIN
|
||||
#define BEEPER_PIN AUX2_08_PIN
|
||||
#define BEEPER_PIN AUX2_08
|
||||
#endif
|
||||
#define LCD_BACKLIGHT_PIN AUX2_10
|
||||
|
||||
|
|
|
|||
|
|
@ -326,13 +326,26 @@
|
|||
// Changing these will not change the pin they are on.
|
||||
|
||||
// Hardware UART pins
|
||||
#define UART1_TX_PIN PA9 // default uses CH340 RX
|
||||
#define UART1_RX_PIN PA10 // default uses CH340 TX
|
||||
#define UART2_TX_PIN PA2 // default uses HEATER_BED_PIN
|
||||
#define UART2_RX_PIN PA3 // not connected
|
||||
#define UART3_TX_PIN PB10 // default uses LCD connector
|
||||
#define UART3_RX_PIN PB11 // default uses LCD connector
|
||||
#define UART4_TX_PIN PC10 // default uses sdcard SDIO_D2
|
||||
#define UART4_RX_PIN PC11 // default uses sdcard SDIO_D3
|
||||
#define UART5_TX_PIN PC12 // default uses sdcard SDIO_CK
|
||||
#define UART5_RX_PIN PD2 // default uses sdcard SDIO_CMD
|
||||
#ifdef ARDUINO_ARCH_MFL // GD32 MFL UARTs start from 0
|
||||
#define UART0_TX_PIN PA9 // default uses CH340 RX
|
||||
#define UART0_RX_PIN PA10 // default uses CH340 TX
|
||||
#define UART1_TX_PIN PA2 // default uses HEATER_BED_PIN
|
||||
#define UART1_RX_PIN PA3 // not connected
|
||||
#define UART2_TX_PIN PB10 // default uses LCD connector
|
||||
#define UART2_RX_PIN PB11 // default uses LCD connector
|
||||
#define UART3_TX_PIN PC10 // default uses sdcard SDIO_D2
|
||||
#define UART3_RX_PIN PC11 // default uses sdcard SDIO_D3
|
||||
#define UART4_TX_PIN PC12 // default uses sdcard SDIO_CK
|
||||
#define UART4_RX_PIN PD2 // default uses sdcard SDIO_CMD
|
||||
#else
|
||||
#define UART1_TX_PIN PA9 // default uses CH340 RX
|
||||
#define UART1_RX_PIN PA10 // default uses CH340 TX
|
||||
#define UART2_TX_PIN PA2 // default uses HEATER_BED_PIN
|
||||
#define UART2_RX_PIN PA3 // not connected
|
||||
#define UART3_TX_PIN PB10 // default uses LCD connector
|
||||
#define UART3_RX_PIN PB11 // default uses LCD connector
|
||||
#define UART4_TX_PIN PC10 // default uses sdcard SDIO_D2
|
||||
#define UART4_RX_PIN PC11 // default uses sdcard SDIO_D3
|
||||
#define UART5_TX_PIN PC12 // default uses sdcard SDIO_CK
|
||||
#define UART5_RX_PIN PD2 // default uses sdcard SDIO_CMD
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@
|
|||
*/
|
||||
//#define E0_HARDWARE_SERIAL MSerial4
|
||||
|
||||
// This is the stable default value after testing, but, higher UART rates could be configured, remeber to test the Steppers with the M122 command to check if everything works.
|
||||
// This is the stable default value after testing, but, higher UART rates could be configured, remember to test the Steppers with the M122 command to check if everything works.
|
||||
//#define TMC_BAUD_RATE 250000
|
||||
|
||||
#define E0_SERIAL_TX_PIN PA15
|
||||
|
|
|
|||
|
|
@ -255,10 +255,12 @@ bool SdBaseFile::exists(const char *name) {
|
|||
* If no data is read, fgets() returns zero for EOF or -1 if an error occurred.
|
||||
*/
|
||||
int16_t SdBaseFile::fgets(char *str, int16_t num, char *delim) {
|
||||
if (!str || num <= 1) return -1; // Ensure space for at least '\0'
|
||||
|
||||
char ch;
|
||||
int16_t n = 0;
|
||||
int16_t r = -1;
|
||||
while ((n + 1) < num && (r = read(&ch, 1)) == 1) {
|
||||
while (n < num - 1 && (r = read(&ch, 1)) == 1) {
|
||||
// delete CR
|
||||
if (ch == '\r') continue;
|
||||
str[n++] = ch;
|
||||
|
|
@ -269,10 +271,7 @@ int16_t SdBaseFile::fgets(char *str, int16_t num, char *delim) {
|
|||
if (strchr(delim, ch)) break;
|
||||
}
|
||||
}
|
||||
if (r < 0) {
|
||||
// read error
|
||||
return -1;
|
||||
}
|
||||
if (r < 0) return -1; // read error
|
||||
str[n] = '\0';
|
||||
return n;
|
||||
}
|
||||
|
|
@ -342,7 +341,9 @@ int8_t SdBaseFile::lsPrintNext(const uint8_t flags, const uint8_t indent) {
|
|||
uint8_t w = 0;
|
||||
|
||||
while (1) {
|
||||
if (read(&dir, sizeof(dir)) != sizeof(dir)) return 0;
|
||||
const int16_t r = read(&dir, sizeof(dir));
|
||||
if (r < 0) return -1;
|
||||
if (r != sizeof(dir)) return 0;
|
||||
if (dir.name[0] == DIR_NAME_FREE) return 0;
|
||||
|
||||
// skip deleted entry and entries for . and ..
|
||||
|
|
@ -1277,7 +1278,8 @@ int SdBaseFile::peek() {
|
|||
filepos_t pos;
|
||||
getpos(&pos);
|
||||
int c = read();
|
||||
if (c >= 0) setpos(&pos);
|
||||
if (c < 0) return -1;
|
||||
setpos(&pos);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
|
@ -1346,8 +1348,10 @@ bool SdBaseFile::printName() {
|
|||
* If an error occurs or end of file is reached -1 is returned.
|
||||
*/
|
||||
int16_t SdBaseFile::read() {
|
||||
uint8_t b;
|
||||
return read(&b, 1) == 1 ? b : -1;
|
||||
uint8_t b = 0;
|
||||
const int16_t r = read(&b, 1);
|
||||
if (r != 1) return -1;
|
||||
return static_cast<int16_t>(b);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
77
README.md
77
README.md
|
|
@ -14,6 +14,7 @@
|
|||
</p>
|
||||
|
||||
### 🌍 Translations
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="//translate.google.com/translate?u=github.com/MarlinFirmware/Marlin&sl=auto&tl=an">Aragonés</a></td>
|
||||
|
|
@ -69,7 +70,7 @@ Please test this firmware and let us know if it misbehaves in any way. Volunteer
|
|||
|
||||
## Marlin 2.1 Bugfix Branch
|
||||
|
||||
__Not for production use. Use with caution!__
|
||||
**Not for production use. Use with caution!**
|
||||
|
||||
Marlin 2.1 continues to support both 32-bit ARM and 8-bit AVR boards while adding support for up to 9 coordinated axes and to up to 8 extruders.
|
||||
|
||||
|
|
@ -103,32 +104,32 @@ Every new HAL opens up a world of hardware. At this time we need HALs for RP2040
|
|||
|
||||
### Supported Platforms
|
||||
|
||||
Platform|MCU|Example Boards
|
||||
--------|---|-------
|
||||
[Arduino AVR](//www.arduino.cc/)|ATmega|RAMPS, Melzi, RAMBo
|
||||
[Teensy++ 2.0](//www.microchip.com/en-us/product/AT90USB1286)|AT90USB1286|Printrboard
|
||||
[Arduino Due](//www.arduino.cc/en/Guide/ArduinoDue)|SAM3X8E|RAMPS-FD, RADDS, RAMPS4DUE
|
||||
[ESP32](//github.com/espressif/arduino-esp32)|ESP32|FYSETC E4, E4d@BOX, MRR
|
||||
[GD32](//www.gigadevice.com/)|GD32 ARM Cortex-M4|Creality MFL GD32 V4.2.2
|
||||
[HC32](//www.huazhoucn.com/)|HC32|Ender-2 Pro, Voxelab Aquila
|
||||
[LPC1768](//www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpc1700-cortex-m3/512-kb-flash-64-kb-sram-ethernet-usb-lqfp100-package:LPC1768FBD100)|ARM® Cortex-M3|MKS SBASE, Re-ARM, Selena Compact
|
||||
[LPC1769](//www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpc1700-cortex-m3/512-kb-flash-64-kb-sram-ethernet-usb-lqfp100-package:LPC1769FBD100)|ARM® Cortex-M3|Smoothieboard, Azteeg X5 mini, TH3D EZBoard
|
||||
[Pico RP2040](//www.raspberrypi.com/documentation/microcontrollers/pico-series.html)|Dual Cortex M0+|BigTreeTech SKR Pico
|
||||
[STM32F103](//www.st.com/en/microcontrollers-microprocessors/stm32f103.html)|ARM® Cortex-M3|Malyan M200, GTM32 Pro, MKS Robin, BTT SKR Mini
|
||||
[STM32F401](//www.st.com/en/microcontrollers-microprocessors/stm32f401.html)|ARM® Cortex-M4|ARMED, Rumba32, SKR Pro, Lerdge, FYSETC S6, Artillery Ruby
|
||||
[STM32F7x6](//www.st.com/en/microcontrollers-microprocessors/stm32f7x6.html)|ARM® Cortex-M7|The Borg, RemRam V1
|
||||
[STM32G0B1RET6](//www.st.com/en/microcontrollers-microprocessors/stm32g0x1.html)|ARM® Cortex-M0+|BigTreeTech SKR mini E3 V3.0
|
||||
[STM32H743xIT6](//www.st.com/en/microcontrollers-microprocessors/stm32h743-753.html)|ARM® Cortex-M7|BigTreeTech SKR V3.0, SKR EZ V3.0, SKR SE BX V2.0/V3.0
|
||||
[SAMD21P20A](//www.adafruit.com/product/4064)|ARM® Cortex-M0+|Adafruit Grand Central M4
|
||||
[SAMD51P20A](//www.adafruit.com/product/4064)|ARM® Cortex-M4|Adafruit Grand Central M4
|
||||
[Teensy 3.2/3.1](//www.pjrc.com/teensy/teensy31.html)|MK20DX256VLH7 ARM® Cortex-M4|
|
||||
[Teensy 3.5](//www.pjrc.com/store/teensy35.html)|MK64FX512-VMD12 ARM® Cortex-M4|
|
||||
[Teensy 3.6](//www.pjrc.com/store/teensy36.html)|MK66FX1MB-VMD18 ARM® Cortex-M4|
|
||||
[Teensy 4.0](//www.pjrc.com/store/teensy40.html)|MIMXRT1062-DVL6B ARM® Cortex-M7|
|
||||
[Teensy 4.1](//www.pjrc.com/store/teensy41.html)|MIMXRT1062-DVJ6B ARM® Cortex-M7|
|
||||
Linux Native|x86 / ARM / RISC-V|Raspberry Pi GPIO
|
||||
Simulator|Windows, macOS, Linux|Desktop OS
|
||||
[All supported boards](//marlinfw.org/docs/hardware/boards.html#boards-list)|All platforms|All boards
|
||||
| Platform | MCU | Example Boards |
|
||||
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------- | ---------------------------------------------------------- |
|
||||
| [Arduino AVR](//www.arduino.cc/) | ATmega | RAMPS, Melzi, RAMBo |
|
||||
| [Teensy++ 2.0](//www.microchip.com/en-us/product/AT90USB1286) | AT90USB1286 | Printrboard |
|
||||
| [Arduino Due](//www.arduino.cc/en/Guide/ArduinoDue) | SAM3X8E | RAMPS-FD, RADDS, RAMPS4DUE |
|
||||
| [ESP32](//github.com/espressif/arduino-esp32) | ESP32 | FYSETC E4, E4d@BOX, MRR |
|
||||
| [GD32](//www.gigadevice.com/) | GD32 ARM Cortex-M4 | Creality MFL GD32 V4.2.2 |
|
||||
| [HC32](//www.huazhoucn.com/) | HC32 | Ender-2 Pro, Voxelab Aquila |
|
||||
| [LPC1768](//www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpc1700-cortex-m3/512-kb-flash-64-kb-sram-ethernet-usb-lqfp100-package:LPC1768FBD100) | ARM® Cortex-M3 | MKS SBASE, Re-ARM, Selena Compact |
|
||||
| [LPC1769](//www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpc1700-cortex-m3/512-kb-flash-64-kb-sram-ethernet-usb-lqfp100-package:LPC1769FBD100) | ARM® Cortex-M3 | Smoothieboard, Azteeg X5 mini, TH3D EZBoard |
|
||||
| [Pico RP2040](//www.raspberrypi.com/documentation/microcontrollers/pico-series.html) | Dual Cortex M0+ | BigTreeTech SKR Pico |
|
||||
| [STM32F103](//www.st.com/en/microcontrollers-microprocessors/stm32f103.html) | ARM® Cortex-M3 | Malyan M200, GTM32 Pro, MKS Robin, BTT SKR Mini |
|
||||
| [STM32F401](//www.st.com/en/microcontrollers-microprocessors/stm32f401.html) | ARM® Cortex-M4 | ARMED, Rumba32, SKR Pro, Lerdge, FYSETC S6, Artillery Ruby |
|
||||
| [STM32F7x6](//www.st.com/en/microcontrollers-microprocessors/stm32f7x6.html) | ARM® Cortex-M7 | The Borg, RemRam V1 |
|
||||
| [STM32G0B1RET6](//www.st.com/en/microcontrollers-microprocessors/stm32g0x1.html) | ARM® Cortex-M0+ | BigTreeTech SKR mini E3 V3.0 |
|
||||
| [STM32H743xIT6](//www.st.com/en/microcontrollers-microprocessors/stm32h743-753.html) | ARM® Cortex-M7 | BigTreeTech SKR V3.0, SKR EZ V3.0, SKR SE BX V2.0/V3.0 |
|
||||
| [SAMD21P20A](//www.adafruit.com/product/4064) | ARM® Cortex-M0+ | Adafruit Grand Central M4 |
|
||||
| [SAMD51P20A](//www.adafruit.com/product/4064) | ARM® Cortex-M4 | Adafruit Grand Central M4 |
|
||||
| [Teensy 3.2/3.1](//www.pjrc.com/teensy/teensy31.html) | MK20DX256VLH7 ARM® Cortex-M4 |
|
||||
| [Teensy 3.5](//www.pjrc.com/store/teensy35.html) | MK64FX512-VMD12 ARM® Cortex-M4 |
|
||||
| [Teensy 3.6](//www.pjrc.com/store/teensy36.html) | MK66FX1MB-VMD18 ARM® Cortex-M4 |
|
||||
| [Teensy 4.0](//www.pjrc.com/store/teensy40.html) | MIMXRT1062-DVL6B ARM® Cortex-M7 |
|
||||
| [Teensy 4.1](//www.pjrc.com/store/teensy41.html) | MIMXRT1062-DVJ6B ARM® Cortex-M7 |
|
||||
| Linux Native | x86 / ARM / RISC-V | Raspberry Pi GPIO |
|
||||
| Simulator | Windows, macOS, Linux | Desktop OS |
|
||||
| [All supported boards](//marlinfw.org/docs/hardware/boards.html#boards-list) | All platforms | All boards |
|
||||
|
||||
## Marlin Support
|
||||
|
||||
|
|
@ -173,17 +174,17 @@ Marlin Firmware original logo design by Ahmet Cem TURAN [@ahmetcemturan](//githu
|
|||
|
||||
## Project Leadership
|
||||
|
||||
Name|Role|Link|Donate
|
||||
----|----|----|----
|
||||
🇺🇸 Scott Lahteine|Project Lead|[[@thinkyhead](//github.com/thinkyhead)]|[💸 Donate](//marlinfw.org/docs/development/contributing.html#donate)
|
||||
🇺🇸 Roxanne Neufeld|Admin|[[@Roxy-3D](//github.com/Roxy-3D)]|
|
||||
🇺🇸 Keith Bennett|Admin|[[@thisiskeithb](//github.com/thisiskeithb)]|[💸 Donate](//github.com/sponsors/thisiskeithb)
|
||||
🇺🇸 Jason Smith|Admin|[[@sjasonsmith](//github.com/sjasonsmith)]|
|
||||
🇧🇷 Victor Oliveira|Admin|[[@rhapsodyv](//github.com/rhapsodyv)]|
|
||||
🇬🇧 Chris Pepper|Admin|[[@p3p](//github.com/p3p)]|
|
||||
🇳🇿 Peter Ellens|Admin|[[@ellensp](//github.com/ellensp)]|[💸 Donate](//ko-fi.com/ellensp)
|
||||
🇺🇸 Bob Kuhn|Admin|[[@Bob-the-Kuhn](//github.com/Bob-the-Kuhn)]|
|
||||
🇳🇱 Erik van der Zalm|Founder|[[@ErikZalm](//github.com/ErikZalm)]|
|
||||
| Name | Role | Link | Donate |
|
||||
| -------------------- | ------------ | -------------------------------------------- | --------------------------------------------------------------------- |
|
||||
| 🇺🇸 Scott Lahteine | Project Lead | [[@thinkyhead](//github.com/thinkyhead)] | [💸 Donate](//marlinfw.org/docs/development/contributing.html#donate) |
|
||||
| 🇺🇸 Roxanne Neufeld | Admin | [[@Roxy-3D](//github.com/Roxy-3D)] |
|
||||
| 🇺🇸 Keith Bennett | Admin | [[@thisiskeithb](//github.com/thisiskeithb)] | [💸 Donate](//github.com/sponsors/thisiskeithb) |
|
||||
| 🇺🇸 Jason Smith | Admin | [[@sjasonsmith](//github.com/sjasonsmith)] |
|
||||
| 🇧🇷 Victor Oliveira | Admin | [[@rhapsodyv](//github.com/rhapsodyv)] |
|
||||
| 🇬🇧 Chris Pepper | Admin | [[@p3p](//github.com/p3p)] |
|
||||
| 🇳🇿 Peter Ellens | Admin | [[@ellensp](//github.com/ellensp)] | [💸 Donate](//ko-fi.com/ellensp) |
|
||||
| 🇺🇸 Bob Kuhn | Admin | [[@Bob-the-Kuhn](//github.com/Bob-the-Kuhn)] |
|
||||
| 🇳🇱 Erik van der Zalm | Founder | [[@ErikZalm](//github.com/ErikZalm)] |
|
||||
|
||||
## Star History
|
||||
|
||||
|
|
|
|||
|
|
@ -42,13 +42,15 @@ These tools must be run from a terminal with access to an installed Python 3 and
|
|||
|
||||
Pillow is most easily installed with pip:
|
||||
|
||||
python3 -m pip install pillow
|
||||
```sh
|
||||
python3 -m pip install pillow
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
These tools process an `.ICO` file that you specify. The safest method is to create a folder and copy your `.ICO` file there. For example:
|
||||
|
||||
```
|
||||
```sh
|
||||
$ mkdir hackicons
|
||||
$ cp 7.ICO hackicons
|
||||
$ cd hackicons
|
||||
|
|
@ -61,11 +63,13 @@ The following explanations will refer back to this layout.
|
|||
If you want to edit the individual icons stored in an ICO file (or add more images) you'll first need to extract all the images from the archive using `splitIco.py`.
|
||||
|
||||
#### Usage:
|
||||
```
|
||||
|
||||
```sh
|
||||
splitIco.py #.ICO foldername
|
||||
```
|
||||
|
||||
#### Splitting .ICO FIle In Windows:
|
||||
|
||||
- Create `Split-ICO.bat` file in this folder with the following code:
|
||||
- `for /f %%f in ('dir *.ICO /B /O:-D') do splitico.py %%f %%f-icons`
|
||||
- Paste `.ICO` file into this folder
|
||||
|
|
@ -99,11 +103,13 @@ Once the individual JPEG files have been saved they can be edited using common g
|
|||
If you want to create an ICO file you'll need to use `makeIco.py`.
|
||||
|
||||
#### Usage:
|
||||
```
|
||||
|
||||
```sh
|
||||
makeIco.py foldername #.ICO
|
||||
```
|
||||
|
||||
#### Making .ICO FIle In Windows:
|
||||
|
||||
- Create `Make-ICO.bat` file in this folder with the following code:
|
||||
- ```
|
||||
setlocal enabledelayedexpansion
|
||||
|
|
|
|||
|
|
@ -1,21 +1,23 @@
|
|||
# Marlin fonts
|
||||
|
||||
## Author and license
|
||||
|
||||
The original author of the following font files is [A. Hardtung](https://github.com/AnHardt).
|
||||
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
- HD44780_C.fon ([fe2bd23](https://github.com/MarlinFirmware/Marlin/commit/fe2bd237d556439499dfdee852c1550c7a16430a))
|
||||
- HD44780_J.fon ([fe2bd23](https://github.com/MarlinFirmware/Marlin/commit/fe2bd237d556439499dfdee852c1550c7a16430a))
|
||||
- HD44780_W.fon ([fe2bd23](https://github.com/MarlinFirmware/Marlin/commit/fe2bd237d556439499dfdee852c1550c7a16430a))
|
||||
- ISO10646-1.fon ([be79235](https://github.com/MarlinFirmware/Marlin/commit/be79235ef255a5c42fd385820447ec351f23b9b1))
|
||||
- ISO10646_5_Cyrillic.fon ([fe2bd23](https://github.com/MarlinFirmware/Marlin/commit/fe2bd237d556439499dfdee852c1550c7a16430a))
|
||||
- ISO10646_CN.fon ([6b1b718](https://github.com/MarlinFirmware/Marlin/commit/6b1b71837c98ceab55db7433357a13cd829d1ede))
|
||||
- ISO10646_Kana.fon ([fe2bd23](https://github.com/MarlinFirmware/Marlin/commit/fe2bd237d556439499dfdee852c1550c7a16430a))
|
||||
- Marlin_symbols.fon ([fe2bd23](https://github.com/MarlinFirmware/Marlin/commit/fe2bd237d556439499dfdee852c1550c7a16430a))
|
||||
- HD44780_C.fon ([fe2bd23](https://github.com/MarlinFirmware/Marlin/commit/fe2bd237d556439499dfdee852c1550c7a16430a))
|
||||
- HD44780_J.fon ([fe2bd23](https://github.com/MarlinFirmware/Marlin/commit/fe2bd237d556439499dfdee852c1550c7a16430a))
|
||||
- HD44780_W.fon ([fe2bd23](https://github.com/MarlinFirmware/Marlin/commit/fe2bd237d556439499dfdee852c1550c7a16430a))
|
||||
- ISO10646-1.fon ([be79235](https://github.com/MarlinFirmware/Marlin/commit/be79235ef255a5c42fd385820447ec351f23b9b1))
|
||||
- ISO10646_5_Cyrillic.fon ([fe2bd23](https://github.com/MarlinFirmware/Marlin/commit/fe2bd237d556439499dfdee852c1550c7a16430a))
|
||||
- ISO10646_CN.fon ([6b1b718](https://github.com/MarlinFirmware/Marlin/commit/6b1b71837c98ceab55db7433357a13cd829d1ede))
|
||||
- ISO10646_Kana.fon ([fe2bd23](https://github.com/MarlinFirmware/Marlin/commit/fe2bd237d556439499dfdee852c1550c7a16430a))
|
||||
- Marlin_symbols.fon ([fe2bd23](https://github.com/MarlinFirmware/Marlin/commit/fe2bd237d556439499dfdee852c1550c7a16430a))
|
||||
|
||||
Additional changes to the original font files distributed with Marlin are copyrighted under the terms of the [GPLv3](https://www.gnu.org/licenses/gpl-3.0.txt) license.
|
||||
|
||||
## Documentation
|
||||
|
||||
For detailed information about adding new fonts to Marlin [see this article](https://marlinfw.org/docs/development/fonts.html).
|
||||
|
|
|
|||
|
|
@ -16,42 +16,42 @@ The following scripts can be used on any system with a GNU environment to speed
|
|||
|
||||
#### Remotes
|
||||
|
||||
File|Description
|
||||
----|-----------
|
||||
mfadd [user]|Add and Fetch Remote - Add and fetch another user's Marlin fork. Optionally, check out one of their branches.
|
||||
mfinit|Init Working Copy - Create a remote named '`upstream`' (for use by the other scripts) pointing to the '`MarlinFirmware`' fork. This only needs to be used once. Newer versions of Github Desktop may create `upstream` on your behalf.
|
||||
| File | Description |
|
||||
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| mfadd [user] | Add and Fetch Remote - Add and fetch another user's Marlin fork. Optionally, check out one of their branches. |
|
||||
| mfinit | Init Working Copy - Create a remote named '`upstream`' (for use by the other scripts) pointing to the '`MarlinFirmware`' fork. This only needs to be used once. Newer versions of Github Desktop may create `upstream` on your behalf. |
|
||||
|
||||
#### Branches
|
||||
|
||||
File|Description
|
||||
----|-----------
|
||||
mfnew [branch]|New Branch - Creates a new branch based on `upstream/[PR-target]`. All new work should start with this command.
|
||||
mffp|Fast Push - Push the HEAD or a commit ID to `upstream` immediately. Requires privileged access to the MarlinFirmware repo.
|
||||
firstpush|Push the current branch to 'origin' -your fork on Github- and set it to track '`origin`'. The branch needs to reside on Github before you can use it to make a PR.
|
||||
| File | Description |
|
||||
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| mfnew [branch] | New Branch - Creates a new branch based on `upstream/[PR-target]`. All new work should start with this command. |
|
||||
| mffp | Fast Push - Push the HEAD or a commit ID to `upstream` immediately. Requires privileged access to the MarlinFirmware repo. |
|
||||
| firstpush | Push the current branch to 'origin' -your fork on Github- and set it to track '`origin`'. The branch needs to reside on Github before you can use it to make a PR. |
|
||||
|
||||
#### Making / Amending PRs
|
||||
|
||||
File|Description
|
||||
----|-----------
|
||||
mfpr|Pull Request - Open the Compare / Pull Request page on Github for the current branch.
|
||||
mfrb|Do a `git rebase` then `git rebase -i` of the current branch onto `upstream/[PR-target]`. Use this to edit your commits anytime.
|
||||
mfqp|Quick Patch - Commit all current changes as "patch", then do `mfrb`, followed by `git push -f` if no conflicts need resolution.
|
||||
| File | Description |
|
||||
| ---- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| mfpr | Pull Request - Open the Compare / Pull Request page on Github for the current branch. |
|
||||
| mfrb | Do a `git rebase` then `git rebase -i` of the current branch onto `upstream/[PR-target]`. Use this to edit your commits anytime. |
|
||||
| mfqp | Quick Patch - Commit all current changes as "patch", then do `mfrb`, followed by `git push -f` if no conflicts need resolution. |
|
||||
|
||||
#### Documentation
|
||||
|
||||
File|Description
|
||||
----|-----------
|
||||
mfdoc|Build the documentation with Jekyll and preview it locally.
|
||||
mfpub|Build and publish the documentation to marlinfw.org.
|
||||
| File | Description |
|
||||
| ----- | ----------------------------------------------------------- |
|
||||
| mfdoc | Build the documentation with Jekyll and preview it locally. |
|
||||
| mfpub | Build and publish the documentation to marlinfw.org. |
|
||||
|
||||
#### Utilities
|
||||
|
||||
File|Description
|
||||
----|-----------
|
||||
ghtp -[h/s]|Set the protocol to use for all remotes. -h for HTTPS, -s for SSL.
|
||||
ghpc [-f]|Push current branch to 'origin' or to the remote indicated by the error.
|
||||
mfinfo|This utility script is used by the other scripts to get:<br/>- The upstream project ('`MarlinFirmware`')<br/>- the '`origin`' project (i.e., your Github username),<br/>- the repository name ('`Marlin`'),<br/>- the PR target branch ('`bugfix-1.1.x`'), and<br/>- the current branch (or the first command-line argument).<br/><br/>By itself, `mfinfo` simply prints these values to the console.
|
||||
mfclean |Prune your merged and remotely-deleted branches.
|
||||
| File | Description |
|
||||
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| ghtp -[h/s] | Set the protocol to use for all remotes. -h for HTTPS, -s for SSL. |
|
||||
| ghpc [-f] | Push current branch to 'origin' or to the remote indicated by the error. |
|
||||
| mfinfo | This utility script is used by the other scripts to get:<br/>- The upstream project ('`MarlinFirmware`')<br/>- the '`origin`' project (i.e., your Github username),<br/>- the repository name ('`Marlin`'),<br/>- the PR target branch ('`bugfix-1.1.x`'), and<br/>- the current branch (or the first command-line argument).<br/><br/>By itself, `mfinfo` simply prints these values to the console. |
|
||||
| mfclean | Prune your merged and remotely-deleted branches. |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
72
buildroot/share/scripts/linesformat.py
Executable file
72
buildroot/share/scripts/linesformat.py
Executable file
|
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Formatter script for *.h, *.c, *.cpp, *.md, *.txt, and other source files
|
||||
|
||||
usage: linesformat.py [infile] [outfile]
|
||||
|
||||
With no parameters convert STDIN to STDOUT
|
||||
"""
|
||||
|
||||
import sys, re, argparse
|
||||
|
||||
do_log = False
|
||||
def logmsg(msg, line):
|
||||
if do_log: print(msg, line)
|
||||
|
||||
def format_text(argv):
|
||||
parser = argparse.ArgumentParser(description="Formatter script for source files")
|
||||
parser.add_argument('infile', nargs='?', default=None, help="Input file to read from. If not provided, reads from stdin.")
|
||||
parser.add_argument('outfile', nargs='?', default=None, help="Output file to write to. If not provided, writes to stdout.")
|
||||
parser.add_argument('-v', action='store_true', help="Enable logging.")
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
src_file = args.infile or 'stdin'
|
||||
dst_file = args.outfile or None
|
||||
|
||||
scnt = 0
|
||||
for arg in argv:
|
||||
if arg == '-v':
|
||||
global do_log
|
||||
do_log = args.v or True
|
||||
elif scnt == 0:
|
||||
# Get a source file if specified. Default destination is the same file
|
||||
src_file = dst_file = arg
|
||||
scnt += 1
|
||||
elif scnt == 1:
|
||||
# Get destination file if specified
|
||||
dst_file = arg
|
||||
scnt += 1
|
||||
|
||||
# No text to process yet
|
||||
file_text = ''
|
||||
|
||||
if src_file == 'stdin':
|
||||
# If no source file specified read from STDIN
|
||||
file_text = sys.stdin.read()
|
||||
else:
|
||||
# Directory will be processed recursively with editorconfig
|
||||
if os.path.isdir(src_file):
|
||||
apply_editorconfig_rules(src_file)
|
||||
return
|
||||
|
||||
# Open and read the file src_file
|
||||
with open(src_file, 'r', encoding='utf-8') as rf: file_text = rf.read()
|
||||
|
||||
if len(file_text) == 0:
|
||||
print('No text to process')
|
||||
return
|
||||
|
||||
# Read from file or STDIN until it terminates
|
||||
filtered = re.sub(r'\s+$', '', file_text) + '\n'
|
||||
if dst_file:
|
||||
with open(dst_file, 'w', encoding='utf-8') as wf: wf.write(filtered)
|
||||
else:
|
||||
print(filtered)
|
||||
|
||||
# Python standard startup for command line with arguments
|
||||
if __name__ == '__main__':
|
||||
format_text(sys.argv[1:])
|
||||
|
||||
# Usage
|
||||
apply_editorconfig_rules('/path/to/your/folder')
|
||||
|
|
@ -38,7 +38,7 @@ mpatt = [ r'-?\d{1,3}', r'P[A-I]\d+', r'P\d_\d+', r'Pin[A-Z]\d\b' ]
|
|||
mstr = '|'.join(mpatt)
|
||||
mexpr = [ re.compile(f'^{m}$') for m in mpatt ]
|
||||
|
||||
# Corrsponding padding for each pattern
|
||||
# Corresponding padding for each pattern
|
||||
ppad = [ 3, 4, 5, 5 ]
|
||||
|
||||
# Match a define line
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
# Marlin Binary File Transfer (BFT)
|
||||
|
||||
Marlin is capable of transferring binary data to the internal storage (SD card) via serial when built with `BINARY_FILE_TRANSFER` enabled. The following is a description of the binary protocol that must be used to conduct transfers once the printer is in binary mode after running `M28 B1`.
|
||||
|
||||
## Data Endianness
|
||||
|
||||
All data structures are **little-endian**! This means that when constructing the packets with multi-byte values, the lower bits are packed first. For example, each packet should start with a 16-bit start token with the value of `0xB5AD`. The data itself should start with a value of `0xAD` followed by `0xB5` etc.
|
||||
|
||||
An example Connection SYNC packet, which is only a header and has no payload:
|
||||
|
||||
```
|
||||
S S P P P H
|
||||
t y r a a e
|
||||
|
|
@ -35,16 +38,17 @@ ADB5 00 0 1 0000 0103
|
|||
+-------------------------------+-------------------------------+
|
||||
```
|
||||
|
||||
| Field | Width | Description |
|
||||
|-----------------|---------|---|
|
||||
| Start Token | 16 bits | Each packet must start with the 16-bit value `0xB5AD`. |
|
||||
| Sync Number | 8 bits | Synchronization value, each packet after sync should increment this value by 1. |
|
||||
| Protocol ID | 4 bits | Protocol ID. `0` for Connection Control, `1` for Transfer. See Below. |
|
||||
| Packet Type | 4 bits | Packet Type ID. Depends on the Protocol ID, see below. |
|
||||
| Field | Width | Description |
|
||||
| --------------- | ------- | ------------------------------------------------------------------------------------------------- |
|
||||
| Start Token | 16 bits | Each packet must start with the 16-bit value `0xB5AD`. |
|
||||
| Sync Number | 8 bits | Synchronization value, each packet after sync should increment this value by 1. |
|
||||
| Protocol ID | 4 bits | Protocol ID. `0` for Connection Control, `1` for Transfer. See Below. |
|
||||
| Packet Type | 4 bits | Packet Type ID. Depends on the Protocol ID, see below. |
|
||||
| Payload Length | 16 bits | Length of payload data. If this value is greater than 0, a packet payload will follow the header. |
|
||||
| Header Checksum | 16 bits | 16-bit Fletchers checksum of the header data excluding the Start Token |
|
||||
| Header Checksum | 16 bits | 16-bit Fletchers checksum of the header data excluding the Start Token |
|
||||
|
||||
## Packet Payload
|
||||
|
||||
If the Payload Length field of the header is non-zero, payload data is expected to follow.
|
||||
|
||||
```
|
||||
|
|
@ -57,15 +61,17 @@ If the Payload Length field of the header is non-zero, payload data is expected
|
|||
+-------------------------------+-------------------------------+
|
||||
```
|
||||
|
||||
| Field | Width | Description |
|
||||
|-----------------|------------------------|---|
|
||||
| Payload Data | Payload Length bytes | Payload data. This should be no longer than the buffer length reported by the Connection SYNC operation. |
|
||||
| Packet Checksum | 16 bits | 16-bit Fletchers checksum of the header and payload, including the Header Checksum, but excluding the Start Token. |
|
||||
| Field | Width | Description |
|
||||
| --------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| Payload Data | Payload Length bytes | Payload data. This should be no longer than the buffer length reported by the Connection SYNC operation. |
|
||||
| Packet Checksum | 16 bits | 16-bit Fletchers checksum of the header and payload, including the Header Checksum, but excluding the Start Token. |
|
||||
|
||||
## Fletchers Checksum
|
||||
|
||||
Data packets require a checksum for the header and a checksum for the entire packet if the packet has a payload. In both cases the checksum does not include the first two bytes of the packet, the Start Token.
|
||||
|
||||
A simple example implementation:
|
||||
|
||||
```c++
|
||||
uint16_t cs = 0;
|
||||
for (size_t i = 2; i<packet.size(); i++) {
|
||||
|
|
@ -77,93 +83,108 @@ for (size_t i = 2; i<packet.size(); i++) {
|
|||
## General Responses
|
||||
|
||||
### ok
|
||||
|
||||
All packets **except** the SYNC Packet (see below) are acknowledged by an `ok<SYNC>` message. This acknowledgement only signifies the client has received the packet and that the header was well formed. An `ok` acknowledgement does not signify successful operation in cases where the client also sends detailed response messages (see details on packet types below). Most notably, with the current implementation the client will still respond `ok` when a client sends multiple packets with the same Sync Number, but will not send the proper response or any errors.
|
||||
|
||||
**NOTE**: The `ok` acknowledgement is sent before any packet type specific output. The `SYNC` value should match the Sync Number of the last packet sent, and the next packet sent should use a Sync Number of this value + 1.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
ok1
|
||||
```
|
||||
|
||||
### rs
|
||||
|
||||
In the case of a packet being sent out of order, where the Sync Number is not the previous Sync Number + 1, an `rs<SYNC>` message will be sent with the last Sync Number received.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
rs1
|
||||
```
|
||||
|
||||
## Connection Control (`Protocol ID` 0)
|
||||
|
||||
`Protocol ID` 0 packets control the binary connection itself. There are only 2 types:
|
||||
|
||||
| Packet Type | Name | Description |
|
||||
|---|---|---|
|
||||
| 1 | SYNC | Synchronize host and client and get connection info. |
|
||||
| 2 | CLOSE | Close the binary connection and switch back to ASCII. |
|
||||
| Packet Type | Name | Description |
|
||||
| ----------- | ----- | ----------------------------------------------------- |
|
||||
| 1 | SYNC | Synchronize host and client and get connection info. |
|
||||
| 2 | CLOSE | Close the binary connection and switch back to ASCII. |
|
||||
|
||||
### SYNC Packet
|
||||
|
||||
A SYNC packet should be the first packet sent by a host after enabling binary mode. On success, a sync response will be sent.
|
||||
|
||||
**Note**: This is the only packet that is not acknowledged with an `ok` response.
|
||||
|
||||
Returns a sync response:
|
||||
|
||||
```
|
||||
ss<SYNC>,<BUFFER_SIZE>,<VERSION_MAJOR>.<VERSION_MINOR>.<VERSION_PATCH>
|
||||
```
|
||||
|
||||
| Value | Description |
|
||||
|---|---|
|
||||
| SYNC | The current Sync Number, this should be used in the next packet sent and incremented by 1 for each packet sent after. |
|
||||
| BUFFER_SIZE | The client buffer size. Packet Payload Length must not exceed this value. |
|
||||
| VERSION_MAJOR | The major version number of the client Marlin BFT protocol, e.g., `0`. |
|
||||
| VERSION_MINOR | The minor version number of the client Marlin BFT protocol, e.g., `1`. |
|
||||
| VERSION_PATCH | The patch version number of the client Marlin BFT protocol, e.g., `0`. |
|
||||
| Value | Description |
|
||||
| ------------- | --------------------------------------------------------------------------------------------------------------------- |
|
||||
| SYNC | The current Sync Number, this should be used in the next packet sent and incremented by 1 for each packet sent after. |
|
||||
| BUFFER_SIZE | The client buffer size. Packet Payload Length must not exceed this value. |
|
||||
| VERSION_MAJOR | The major version number of the client Marlin BFT protocol, e.g., `0`. |
|
||||
| VERSION_MINOR | The minor version number of the client Marlin BFT protocol, e.g., `1`. |
|
||||
| VERSION_PATCH | The patch version number of the client Marlin BFT protocol, e.g., `0`. |
|
||||
|
||||
Example response:
|
||||
|
||||
```
|
||||
ss0,96,0.1.0
|
||||
```
|
||||
|
||||
### CLOSE Packet
|
||||
|
||||
A CLOSE packet should be the last packet sent by a host. On success, the client will switch back to ASCII mode.
|
||||
|
||||
## Transfer Control (`Protocol ID` 1)
|
||||
## Transfer Control (`Protocol ID` 1)
|
||||
|
||||
`Protocol ID` 1 packets control the file transfers performed over the connection:
|
||||
|
||||
| Packet Type | Name | Description |
|
||||
|---|---|---|
|
||||
| 0 | QUERY | Query the client protocol details and compression parameters. |
|
||||
| 1 | OPEN | Open a file for writing and begin accepting data to transfer. |
|
||||
| 2 | CLOSE | Finish writing and close the current file. |
|
||||
| 3 | WRITE | Write data to an open file. |
|
||||
| 4 | ABORT | Abort file transfer. |
|
||||
| Packet Type | Name | Description |
|
||||
| ----------- | ----- | ------------------------------------------------------------- |
|
||||
| 0 | QUERY | Query the client protocol details and compression parameters. |
|
||||
| 1 | OPEN | Open a file for writing and begin accepting data to transfer. |
|
||||
| 2 | CLOSE | Finish writing and close the current file. |
|
||||
| 3 | WRITE | Write data to an open file. |
|
||||
| 4 | ABORT | Abort file transfer. |
|
||||
|
||||
### QUERY Packet
|
||||
|
||||
A QUERY packet should be the second packet sent by a host, after a SYNC packet. On success a query response will be sent in addition to an `ok<sync>` acknowledgement.
|
||||
|
||||
Returns a query response:
|
||||
|
||||
```
|
||||
PFT:version:<VERSION_MAJOR>.<VERSION_MINOR>.<VERSION_PATCH>:compression:<COMPRESSION_ALGO>(,<COMPRESSION_PARAMS>)
|
||||
```
|
||||
|
||||
| Value | Description |
|
||||
|---|---|
|
||||
| VERSION_MAJOR | The major version number of the client Marlin BFT protocol, e.g., `0`. |
|
||||
| VERSION_MINOR | The minor version number of the client Marlin BFT protocol, e.g., `1`. |
|
||||
| VERSION_PATCH | The patch version number of the client Marlin BFT protocol, e.g., `0`. |
|
||||
| COMPRESSION_ALGO | Compression algorithm. Currently either `heatshrink` or `none` |
|
||||
| Value | Description |
|
||||
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| VERSION_MAJOR | The major version number of the client Marlin BFT protocol, e.g., `0`. |
|
||||
| VERSION_MINOR | The minor version number of the client Marlin BFT protocol, e.g., `1`. |
|
||||
| VERSION_PATCH | The patch version number of the client Marlin BFT protocol, e.g., `0`. |
|
||||
| COMPRESSION_ALGO | Compression algorithm. Currently either `heatshrink` or `none` |
|
||||
| COMPRESSION_PARAMS | Compression parameters, separated by commas. Currently, if `COMPRESSION_AGLO` is heatshrink, this will be the window size and lookahead size. |
|
||||
|
||||
Example response:
|
||||
|
||||
```
|
||||
PFT:version:0.1.0:compression:heatshrink,8,4
|
||||
```
|
||||
|
||||
### OPEN Packet
|
||||
|
||||
Opens a file for writing. The filename and other options are specified in the Packet Payload. The filename can be a long filename if the firmware is compiled with support, however the entire Packet Payload must not be longer than the buffer length returned by the SYNC Packet. The filename value must include a null terminator.
|
||||
|
||||
Payload:
|
||||
|
||||
```
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
|
|
@ -176,50 +197,53 @@ Payload:
|
|||
+-------------------------------+-------------------------------+
|
||||
```
|
||||
|
||||
| Field | Width | Description |
|
||||
|-----------------|------------------------|---|
|
||||
| Dummy | 8 bits | A boolean value indicating if this file transfer should be actually carried out or not. If `1`, the client will respond as if the file is opened and accept data transfer, but no data will be written. |
|
||||
| Compression | 8 bits | A boolean value indicating if the data to be transferred will be compressed using the algorithm and parameters returned in the QUERY Packet. |
|
||||
| Filename | ... | A filename including a null terminator byte. |
|
||||
| Packet Checksum | 16 bits | 16-bit Fletchers checksum of the header and payload, including the Header Checksum, but excluding the Start Token. |
|
||||
| Field | Width | Description |
|
||||
| --------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Dummy | 8 bits | A boolean value indicating if this file transfer should be actually carried out or not. If `1`, the client will respond as if the file is opened and accept data transfer, but no data will be written. |
|
||||
| Compression | 8 bits | A boolean value indicating if the data to be transferred will be compressed using the algorithm and parameters returned in the QUERY Packet. |
|
||||
| Filename | ... | A filename including a null terminator byte. |
|
||||
| Packet Checksum | 16 bits | 16-bit Fletchers checksum of the header and payload, including the Header Checksum, but excluding the Start Token. |
|
||||
|
||||
Responses:
|
||||
|
||||
| Response | Description |
|
||||
|---|---|
|
||||
| `PFT:success` | File opened and ready for write. |
|
||||
| Response | Description |
|
||||
| ------------- | ---------------------------------- |
|
||||
| `PFT:success` | File opened and ready for write. |
|
||||
| `PFT:fail` | The client couldn't open the file. |
|
||||
| `PFT:busy` | The file is already open. |
|
||||
| `PFT:busy` | The file is already open. |
|
||||
|
||||
### CLOSE Packet
|
||||
|
||||
Closes the currently open file.
|
||||
|
||||
Responses:
|
||||
|
||||
| Response | Description |
|
||||
|---|---|
|
||||
| Response | Description |
|
||||
| ------------- | ------------------------------- |
|
||||
| `PFT:success` | Buffer flushed and file closed. |
|
||||
| `PFT:ioerror` | Client storage device failure. |
|
||||
| `PFT:invalid` | No file open. |
|
||||
| `PFT:ioerror` | Client storage device failure. |
|
||||
| `PFT:invalid` | No file open. |
|
||||
|
||||
### WRITE Packet
|
||||
|
||||
Writes payload data to the currently open file. If the file was opened with Compression set to 1, the data will be decompressed first. Payload Length must not exceed the buffer size returned by the SYNC Packet.
|
||||
|
||||
Responses:
|
||||
On success, an `ok<SYNC>` response will be sent. On error, an `ok<SYNC>` response will be followed by an error response:
|
||||
|
||||
| Response | Description |
|
||||
|---|---|
|
||||
| Response | Description |
|
||||
| ------------- | ------------------------------ |
|
||||
| `PFT:ioerror` | Client storage device failure. |
|
||||
| `PFT:invalid` | No file open. |
|
||||
| `PFT:invalid` | No file open. |
|
||||
|
||||
### ABORT Packet
|
||||
|
||||
Closes the currently open file and remove it.
|
||||
|
||||
Responses:
|
||||
|
||||
| Response | Description |
|
||||
|---|---|
|
||||
| Response | Description |
|
||||
| ------------- | ------------------------------- |
|
||||
| `PFT:success` | Transfer aborted, file removed. |
|
||||
|
||||
## Typical Usage
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ The update rules for the error on each step may also be cast into ε' form. Cons
|
|||
ε = ε + m - 1
|
||||
```
|
||||
|
||||
Multiplying through by Δx yields:
|
||||
Multiplying through by Δx yields:
|
||||
|
||||
```
|
||||
ε.Δx = ε.Δx + Δy
|
||||
|
|
@ -111,7 +111,7 @@ Which is in ε' form:
|
|||
ε' = ε' + Δy - Δx
|
||||
```
|
||||
|
||||
Using this new ``error'' value, ε' with the new test and update equations gives Bresenham's integer-only line drawing algorithm:
|
||||
Using this new ``error'' value, ε' with the new test and update equations gives Bresenham's integer-only line drawing algorithm:
|
||||
|
||||
```
|
||||
ε' = 0, y = y[1]
|
||||
|
|
@ -125,7 +125,7 @@ for x = x1 to x2 do
|
|||
endfor
|
||||
```
|
||||
|
||||
It is a Integer only algorithm - hence efficient (fast). And the Multiplication by 2 can be implemented by left-shift. 0 <= m <= 1
|
||||
It is a Integer only algorithm - hence efficient (fast). And the Multiplication by 2 can be implemented by left-shift. 0 <= m <= 1
|
||||
|
||||
### Oversampling Bresenham algorithm:
|
||||
|
||||
|
|
@ -170,12 +170,14 @@ y + ε + m/r < y + 0.5
|
|||
Once we did the decision, then the error update conditions are:
|
||||
|
||||
Decision A:
|
||||
|
||||
```
|
||||
ε[new] = y + ε + m/r - y
|
||||
ε[new] = ε + m/r [2]
|
||||
```
|
||||
|
||||
Decision B:
|
||||
|
||||
```
|
||||
ε[new] = y + ε + m/r - (y+1)
|
||||
ε[new] = ε + m/r - 1 [3]
|
||||
|
|
|
|||
|
|
@ -3,13 +3,16 @@
|
|||
Starting with version 2.0.9.3, Marlin can automatically extract the configuration used to generate the firmware and store it in the firmware binary. This is enabled by defining `CONFIGURATION_EMBEDDING` in `Configuration_adv.h`.
|
||||
|
||||
## How it's done
|
||||
|
||||
At the start of the PlatformIO build process, we create an embedded configuration by extracting all active options from the Configuration files and writing them out as JSON to `marlin_config.json`, which also includes specific build information (like the git revision, the build date, and some version information). The JSON file is then compressed in a ZIP archive called `.pio/build/mc.zip` which is converted into a C array and stored in a C++ file called `mc.h` which is included in the build.
|
||||
|
||||
## Extracting configurations from a Marlin binary
|
||||
|
||||
To get the configuration out of a binary firmware, you'll need a non-write-protected SD card inserted into the printer while running the firmware.
|
||||
Send the command `M503 C` to write the file `mc.zip` to the SD card. Copy the file to your computer, ideally in the same folder as the Marlin repository.
|
||||
|
||||
Run the following commands to extract and apply the configuration:
|
||||
|
||||
```
|
||||
$ git checkout -f
|
||||
$ unzip mc.zip
|
||||
|
|
|
|||
|
|
@ -92,33 +92,33 @@ Once the entry and exit power values are determined, the values are divided into
|
|||
trap step power incr_decr = ( cruize power - entry_exit ) / accel_decel_steps
|
||||
|
||||
The trap steps are incremented or decremented during each accel or decel step until the block is complete.
|
||||
Step power is either cumulatively added or subtracted during trapeziod ramp progressions.
|
||||
Step power is either cumulatively added or subtracted during trapezoid ramp progressions.
|
||||
|
||||
#### Planner Code:
|
||||
|
||||
```
|
||||
if (block->laser.power > 0) {
|
||||
NOLESS(block->laser.power, laser_power_floor);
|
||||
block->laser.trap_ramp_active_pwr = (block->laser.power - laser_power_floor) * (initial_rate / float(block->nominal_rate)) + laser_power_floor;
|
||||
block->laser.trap_ramp_entry_incr = (block->laser.power - block->laser.trap_ramp_active_pwr) / accelerate_steps;
|
||||
float laser_pwr = block->laser.power * (final_rate / float(block->nominal_rate));
|
||||
NOLESS(laser_pwr, laser_power_floor);
|
||||
block->laser.trap_ramp_exit_decr = (block->laser.power - laser_pwr) / decelerate_steps;
|
||||
```
|
||||
```
|
||||
if (block->laser.power > 0) {
|
||||
NOLESS(block->laser.power, laser_power_floor);
|
||||
block->laser.trap_ramp_active_pwr = (block->laser.power - laser_power_floor) * (initial_rate / float(block->nominal_rate)) + laser_power_floor;
|
||||
block->laser.trap_ramp_entry_incr = (block->laser.power - block->laser.trap_ramp_active_pwr) / accelerate_steps;
|
||||
float laser_pwr = block->laser.power * (final_rate / float(block->nominal_rate));
|
||||
NOLESS(laser_pwr, laser_power_floor);
|
||||
block->laser.trap_ramp_exit_decr = (block->laser.power - laser_pwr) / decelerate_steps;
|
||||
```
|
||||
|
||||
#### Stepper Code:
|
||||
|
||||
```
|
||||
if (current_block->laser.trap_ramp_entry_incr > 0) {
|
||||
cutter.apply_power(current_block->laser.trap_ramp_active_pwr);
|
||||
current_block->laser.trap_ramp_active_pwr += current_block->laser.trap_ramp_entry_incr;
|
||||
```
|
||||
```
|
||||
if (current_block->laser.trap_ramp_entry_incr > 0) {
|
||||
cutter.apply_power(current_block->laser.trap_ramp_active_pwr);
|
||||
current_block->laser.trap_ramp_active_pwr += current_block->laser.trap_ramp_entry_incr;
|
||||
```
|
||||
|
||||
```
|
||||
if (current_block->laser.trap_ramp_exit_decr > 0) {
|
||||
current_block->laser.trap_ramp_active_pwr -= current_block->laser.trap_ramp_exit_decr;
|
||||
cutter.apply_power(current_block->laser.trap_ramp_active_pwr);
|
||||
```
|
||||
```
|
||||
if (current_block->laser.trap_ramp_exit_decr > 0) {
|
||||
current_block->laser.trap_ramp_active_pwr -= current_block->laser.trap_ramp_exit_decr;
|
||||
cutter.apply_power(current_block->laser.trap_ramp_active_pwr);
|
||||
```
|
||||
|
||||
### Dynamic Inline Calculations
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ Whenever the command queue gets full the sender needs to wait for space to open
|
|||
An opposite problem called "planner starvation" occurs when Marlin receives many short and fast moves in a row so the Planner Buffer gets completed very quickly. In this case the host can't send commands fast enough to prevent the Planner Buffer from emptying out. Planner starvation causes obvious stuttering and is commonly seen on overloaded deltabots during small curves. Marlin has strategies to mitigate this issue, but sometimes a model has to be re-sliced (or the G-code has to be post-processed with Arc Welder) just to stay within the machine's inherent limits.
|
||||
|
||||
Here's a basic flowchart of Marlin command processing:
|
||||
|
||||
```
|
||||
+------+ Marlin's GCodeQueue
|
||||
| | +--------------------------------------+ +-----------+
|
||||
|
|
@ -39,6 +40,7 @@ Here's a basic flowchart of Marlin command processing:
|
|||
```
|
||||
|
||||
Marlin is a single-threaded application with a main `loop()` that manages the command queue and an `idle()` routine that manages the hardware. The command queue is handled in two stages:
|
||||
|
||||
1. The `idle()` routine reads all inputs and attempts to enqueue any completed command lines.
|
||||
2. The main `loop()` gets the command at the front the G-code queue (if any) and runs it. Each G-code command blocks the main loop, preventing the queue from advancing until it returns. To keep essential tasks and the UI running, any commands that run a long process need to call `idle()` frequently.
|
||||
|
||||
|
|
@ -51,6 +53,7 @@ If no data is available on the serial buffer, Marlin can be configured to period
|
|||
## Limitation of the design
|
||||
|
||||
Some limitations to the design are evident:
|
||||
|
||||
1. Whenever the G-code processor is busy processing a command, the G-code queue cannot advance.
|
||||
2. A long command like `G29` causes commands to pile up and to fill the queue, making the host wait.
|
||||
3. Each serial input requires a buffer large enough for a complete G-code line. This is set by `MAX_CMD_SIZE` with a default value of 96.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Marlin is targeting a plethora of different CPU architectures and platforms. Each of these platforms has its own serial interface.
|
||||
While many provide a Arduino-like Serial class, it's not all of them, and the differences in the existing API create a very complex brain teaser for writing code that works more or less on each platform.
|
||||
|
||||
Moreover, many platform have intrinsic needs about serial port (like forwarding the output on multiple serial port, providing a *serial-like* telnet server, mixing USB-based serial port with SD card emulation) that are difficult to handle cleanly in the other platform serial logic.
|
||||
Moreover, many platform have intrinsic needs about serial port (like forwarding the output on multiple serial port, providing a _serial-like_ telnet server, mixing USB-based serial port with SD card emulation) that are difficult to handle cleanly in the other platform serial logic.
|
||||
|
||||
Starting with version 2.0.8, Marlin provides a common interface for its serial needs.
|
||||
|
||||
|
|
@ -18,54 +18,64 @@ Instead, the Curiously Recurring Template Pattern (**CRTP**) is used so that, up
|
|||
Because some platform do not follow the same interface, the missing method in the actual low-level implementation are detected via SFINAE and a wrapper is generated when such method are missing. See the `CALL_IF_EXISTS` macro in `Marlin/src/core/macros.h` for documentation of this technique.
|
||||
|
||||
## Composing the desired feature
|
||||
|
||||
The different specificities for each architecture are provided by composing the serial type based on desired functionality.
|
||||
In the `Marlin/src/core/serial_hook.h` file, the different serial feature are declared and defined in each templated type:
|
||||
|
||||
1. `BaseSerial` is a simple 1:1 wrapper to the underlying, Arduino compatible, `Serial`'s class. It derives from it. You'll use this if the platform does not do anything specific for the `Serial` object (for example, if an interrupt callback calls directly the serial **instance** in the platform's framework code, this is not the right class to use). This wrapper is completely inlined so that it does not generate any code upon compilation. `BaseSerial` constructor forwards any parameter to the platform's `Serial`'s constructor.
|
||||
2. `ForwardSerial` is a composing wrapper. It references an actual Arduino compatible `Serial` instance. You'll use this if the instance is declared in the platform's framework and is being referred directly in the framework. This is not as efficient as the `BaseSerial` implementation since static dereferencing is done for each method call (it'll still be faster than virtual dispatching)
|
||||
3. `ConditionalSerial` is working a bit like the `ForwardSerial` interface, but it checks a boolean condition before calling the referenced instance. You'll use it when the serial output can be switch off at runtime, for example in a *telnet* like serial output that should not emit any packet if no client is connected.
|
||||
3. `ConditionalSerial` is working a bit like the `ForwardSerial` interface, but it checks a boolean condition before calling the referenced instance. You'll use it when the serial output can be switch off at runtime, for example in a _telnet_ like serial output that should not emit any packet if no client is connected.
|
||||
4. `RuntimeSerial` is providing a runtime-modifiable hooking method for its `write` and `msgDone` method. You'll use it if you need to capture the serial output of Marlin, for example to display the G-Code parser's output on a GUI interface. The hooking interface is setup via the `setHook` method.
|
||||
5. `MultiSerial` is a runtime modifiable serial output multiplexer. It can output (*respectively input*) to 2 different interface based on a port *mask*. You'll use this if you need to output the same serial stream to multiple port. You can plug a `MultiSerial` to itself to duplicate to more than 2 ports.
|
||||
5. `MultiSerial` is a runtime modifiable serial output multiplexer. It can output (_respectively input_) to 2 different interface based on a port _mask_. You'll use this if you need to output the same serial stream to multiple port. You can plug a `MultiSerial` to itself to duplicate to more than 2 ports.
|
||||
|
||||
## Plumbing
|
||||
|
||||
Since all the types above are using CRTP, it's possible to combine them to get the appropriate functionality.
|
||||
This is easily done via type definition of the feature.
|
||||
|
||||
For example, to create a single serial interface with 2 serial outputs (one enabled at runtime and the other switchable):
|
||||
|
||||
```cpp
|
||||
typedef MultiSerial< RuntimeSerial<Serial>, ConditionalSerial<TelnetClient> > Serial1Class;
|
||||
```
|
||||
|
||||
To send the same output to 4 serial ports you could nest `MultiSerial` like this:
|
||||
|
||||
```cpp
|
||||
typedef MultiSerial< MultiSerial< BaseSerial<Serial>, BaseSerial<Serial1> >, MultiSerial< BaseSerial<Serial2>, BaseSerial<Serial3>, 2, 1>, 0, 2> Serial1Class;
|
||||
```
|
||||
|
||||
The magical numbers here are the step and offset for computing the serial port. Simplifying the above monster a bit:
|
||||
|
||||
```cpp
|
||||
MS< A = MS<a, b, offset=0, step=1>, B=MS<c, d, offset=2, step=1>, offset=0, step=2>
|
||||
```
|
||||
|
||||
This means that the underlying multiserial A (with output to `a,b`) is available from offset = 0 to offset + step = 1 (default value).
|
||||
The multiserial B (with output to `c,d`) is available from offset = 2 (the next step from the root multiserial) to offset + step = 3.
|
||||
In practice, the root multiserial will redirect any index/mask `offset` to `offset + step - 1` to its first leaf, and any index/mask `offset + step` to `offset + 2*step - 1` to its second leaf.
|
||||
|
||||
## Emergency parser
|
||||
|
||||
By default, the serial base interface provide an emergency parser that's only enable for serial classes that support it. Because of this condition, all underlying types take a first `bool emergencyParserEnabled` argument to their constructor. You must take into account this parameter when defining the actual type used.
|
||||
|
||||
## SERIAL macros
|
||||
|
||||
The following macros are defined (in `serial.h`) to output data to the serial ports:
|
||||
|
||||
| MACRO | Parameters | Usage | Example | Expected output |
|
||||
|-------|------------|-------|---------|-----------------|
|
||||
| `SERIAL_ECHO` | Any basic type is supported (`char`, `uint8_t`, `int16_t`, `int32_t`, `float`, `long`, `const char*`, ...). | For a numeric type it prints the number in decimal. A string is output as a string. | `uint8_t a = 123; SERIAL_ECHO(a); SERIAL_CHAR(' '); SERIAL_ECHO(' '); ` | `123 32` |
|
||||
| `SERIAL_ECHOLN` | Same as `SERIAL_ECHO` | Do `SERIAL_ECHO`, adding a newline | `int a = 456; SERIAL_ECHOLN(a);` | `456\n` |
|
||||
| `SERIAL_ECHOPGM` | String / Value pairs | Print a series of string literals and values alternately | `SERIAL_ECHOPGM("Bob", 34);` | `Bob34` |
|
||||
| `SERIAL_ECHOLNPGM` | Same as `SERIAL_ECHOPGM` | Do `SERIAL_ECHOPGM`, adding a newline | `SERIAL_ECHOPGM("Alice", 56);` | `alice56` |
|
||||
| `SERIAL_ECHOPGM_P` | Like `SERIAL_ECHOPGM` but takes PGM strings | Print a series of PGM strings and values alternately | `SERIAL_ECHOPGM_P(GET_TEXT(MSG_HELLO), 123);` | `Hello123` |
|
||||
| `SERIAL_ECHOLNPGM_P` | Same as `SERIAL_ECHOPGM_P` | Do `SERIAL_ECHOPGM_P`, adding a newline | `SERIAL_ECHOLNPGM_P(PSTR("Alice"), 78);` | `alice78\n` |
|
||||
| `SERIAL_ECHO_START` | None | Prefix an echo line | `SERIAL_ECHO_START();` | `echo:` |
|
||||
| `SERIAL_ECHO_MSG` | Same as `SERIAL_ECHOLNPGM` | Print a full echo line | `SERIAL_ECHO_MSG("Count is ", count);` | `echo:Count is 3` |
|
||||
| `SERIAL_ERROR_START`| None | Prefix an error line | `SERIAL_ERROR_START();` | `Error:` |
|
||||
| `SERIAL_ERROR_MSG` | Same as `SERIAL_ECHOLNPGM` | Print a full error line | `SERIAL_ERROR_MSG("Not found");` | `Error:Not found` |
|
||||
| `SERIAL_ECHO_SP` | Number of spaces | Print one or more spaces | `SERIAL_ECHO_SP(3)` | ` ` |
|
||||
| `SERIAL_EOL` | None | Print an end of line | `SERIAL_EOL();` | `\n` |
|
||||
| MACRO | Parameters | Usage | Example | Expected output |
|
||||
| -------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | ----------------- |
|
||||
| `SERIAL_ECHO` | Any basic type is supported (`char`, `uint8_t`, `int16_t`, `int32_t`, `float`, `long`, `const char*`, ...). | For a numeric type it prints the number in decimal. A string is output as a string. | `uint8_t a = 123; SERIAL_ECHO(a); SERIAL_CHAR(' '); SERIAL_ECHO(' '); ` | `123 32` |
|
||||
| `SERIAL_ECHOLN` | Same as `SERIAL_ECHO` | Do `SERIAL_ECHO`, adding a newline | `int a = 456; SERIAL_ECHOLN(a);` | `456\n` |
|
||||
| `SERIAL_ECHOPGM` | String / Value pairs | Print a series of string literals and values alternately | `SERIAL_ECHOPGM("Bob", 34);` | `Bob34` |
|
||||
| `SERIAL_ECHOLNPGM` | Same as `SERIAL_ECHOPGM` | Do `SERIAL_ECHOPGM`, adding a newline | `SERIAL_ECHOPGM("Alice", 56);` | `alice56` |
|
||||
| `SERIAL_ECHOPGM_P` | Like `SERIAL_ECHOPGM` but takes PGM strings | Print a series of PGM strings and values alternately | `SERIAL_ECHOPGM_P(GET_TEXT(MSG_HELLO), 123);` | `Hello123` |
|
||||
| `SERIAL_ECHOLNPGM_P` | Same as `SERIAL_ECHOPGM_P` | Do `SERIAL_ECHOPGM_P`, adding a newline | `SERIAL_ECHOLNPGM_P(PSTR("Alice"), 78);` | `alice78\n` |
|
||||
| `SERIAL_ECHO_START` | None | Prefix an echo line | `SERIAL_ECHO_START();` | `echo:` |
|
||||
| `SERIAL_ECHO_MSG` | Same as `SERIAL_ECHOLNPGM` | Print a full echo line | `SERIAL_ECHO_MSG("Count is ", count);` | `echo:Count is 3` |
|
||||
| `SERIAL_ERROR_START` | None | Prefix an error line | `SERIAL_ERROR_START();` | `Error:` |
|
||||
| `SERIAL_ERROR_MSG` | Same as `SERIAL_ECHOLNPGM` | Print a full error line | `SERIAL_ERROR_MSG("Not found");` | `Error:Not found` |
|
||||
| `SERIAL_ECHO_SP` | Number of spaces | Print one or more spaces | `SERIAL_ECHO_SP(3)` | ` ` |
|
||||
| `SERIAL_EOL` | None | Print an end of line | `SERIAL_EOL();` | `\n` |
|
||||
|
||||
*This document was written by [X-Ryl669](https://blog.cyril.by) and is under [CC-SA license](https://creativecommons.org/licenses/by-sa)*
|
||||
_This document was written by [X-Ryl669](https://blog.cyril.by) and is under [CC-SA license](https://creativecommons.org/licenses/by-sa)_
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# Testing Marlin
|
||||
|
||||
Marlin included two types of automated tests:
|
||||
|
||||
- [Build Tests](../buildroot/tests) to catch syntax and code build errors.
|
||||
- Unit Tests (this folder) to catch implementation errors.
|
||||
|
||||
|
|
@ -21,15 +22,19 @@ Generally speaking, the types of errors caught by unit tests are most often caug
|
|||
### Unit test FAQ
|
||||
|
||||
#### Q: Isn't writing unit tests a lot of work?
|
||||
|
||||
A: Yes, and it can be especially difficult with existing code that wasn't designed for unit testing. Some common sense should be used to decide where to employ unit testing, and at what level to perform it. While unit testing takes effort, it pays dividends in preventing regressions, and helping to pinpoint the source of failures when they do occur.
|
||||
|
||||
#### Q: Will this make refactoring harder?
|
||||
|
||||
A: Yes and No. Of course if you refactor code that unit tests use directly, it will have to be reworked as well. It actually can make refactoring more efficient, by providing assurance that the mechanism still works as intended.
|
||||
|
||||
#### Q: How can I debug one of these failing unit tests?
|
||||
|
||||
A: That's a great question, without a known immediate answer. It is likely possible to debug them interactively through PlatformIO, but that can at times take some creativity to configure. Unit tests are generally extremely small, so even without interactive debugging it can get you fairly close to the cause of the problem.
|
||||
|
||||
### Unit test architecture
|
||||
|
||||
We are currently using [PlatformIO unit tests](https://docs.platformio.org/en/latest/plus/unit-testing.html).
|
||||
|
||||
Since Marlin only compiles code required by the configuration, a separate test binary must be generated for any configuration change. The following process is used to unit test a variety of configurations:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue