From 4bca73dc5a88bb68918a0873e93636b0a7367044 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Fri, 5 Sep 2025 20:30:39 -0500 Subject: [PATCH] =?UTF-8?q?=E2=9C=85=20Validate=20source=20formatting=20(#?= =?UTF-8?q?28028)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devcontainer/devcontainer.json | 2 +- .github/workflows/ci-validate-boards.yml | 42 +++--- .github/workflows/ci-validate-lines.yml | 40 ++++++ .github/workflows/ci-validate-pins.yml | 42 +++--- .gitignore | 5 + .prettierignore | 10 ++ Makefile | 14 +- Marlin/src/HAL/GD32_MFL/README.md | 3 +- Marlin/src/HAL/STM32/README.md | 9 +- Marlin/src/HAL/STM32F1/README.md | 1 + .../src/feature/mmu/mmu2-serial-protocol.md | 32 ++--- .../src/feature/mmu3/mmu3-serial-protocol.md | 21 ++- .../ftdi_eve_touch_ui/ftdi_eve_lib/README.md | 3 +- README.md | 77 +++++----- buildroot/share/dwin/bin/README.md | 14 +- buildroot/share/fonts/README.md | 18 +-- buildroot/share/git/README.md | 48 +++---- buildroot/share/scripts/linesformat.py | 72 ++++++++++ buildroot/share/scripts/pinsformat.py | 2 +- docs/BinaryFileTransferProtocol.md | 134 +++++++++++------- docs/Bresenham.md | 8 +- docs/ConfigEmbedding.md | 3 + docs/Cutter.md | 38 ++--- docs/Queue.md | 3 + docs/Serial.md | 46 +++--- test/README.md | 5 + 26 files changed, 448 insertions(+), 244 deletions(-) create mode 100644 .github/workflows/ci-validate-lines.yml create mode 100644 .prettierignore create mode 100755 buildroot/share/scripts/linesformat.py diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 54627d462b..77479946b5 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -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": [], diff --git a/.github/workflows/ci-validate-boards.yml b/.github/workflows/ci-validate-boards.yml index 36f3a3522a..aa6d284f06 100644 --- a/.github/workflows/ci-validate-boards.yml +++ b/.github/workflows/ci-validate-boards.yml @@ -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 diff --git a/.github/workflows/ci-validate-lines.yml b/.github/workflows/ci-validate-lines.yml new file mode 100644 index 0000000000..367db12e6c --- /dev/null +++ b/.github/workflows/ci-validate-lines.yml @@ -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 diff --git a/.github/workflows/ci-validate-pins.yml b/.github/workflows/ci-validate-pins.yml index ae777427e7..2086fea37a 100644 --- a/.github/workflows/ci-validate-pins.yml +++ b/.github/workflows/ci-validate-pins.yml @@ -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 diff --git a/.gitignore b/.gitignore index daa5c5c288..87d7ef47d3 100755 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,11 @@ out-language/ *.gen *.sublime-workspace +# npm +node_modules/ +package.json +package-lock.json + # OS applet/ .DS_Store diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..62761b99e9 --- /dev/null +++ b/.prettierignore @@ -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 diff --git a/Makefile b/Makefile index 23826497b6..f1f64e1342 100644 --- a/Makefile +++ b/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 diff --git a/Marlin/src/HAL/GD32_MFL/README.md b/Marlin/src/HAL/GD32_MFL/README.md index af23a37f2f..61800eda1c 100644 --- a/Marlin/src/HAL/GD32_MFL/README.md +++ b/Marlin/src/HAL/GD32_MFL/README.md @@ -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). diff --git a/Marlin/src/HAL/STM32/README.md b/Marlin/src/HAL/STM32/README.md index 7680df6654..cf8aa50d50 100644 --- a/Marlin/src/HAL/STM32/README.md +++ b/Marlin/src/HAL/STM32/README.md @@ -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). diff --git a/Marlin/src/HAL/STM32F1/README.md b/Marlin/src/HAL/STM32F1/README.md index b5bd5141fb..e289f35433 100644 --- a/Marlin/src/HAL/STM32F1/README.md +++ b/Marlin/src/HAL/STM32F1/README.md @@ -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 diff --git a/Marlin/src/feature/mmu/mmu2-serial-protocol.md b/Marlin/src/feature/mmu/mmu2-serial-protocol.md index 088d41b446..40799d41a9 100644 --- a/Marlin/src/feature/mmu/mmu2-serial-protocol.md +++ b/Marlin/src/feature/mmu/mmu2-serial-protocol.md @@ -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' diff --git a/Marlin/src/feature/mmu3/mmu3-serial-protocol.md b/Marlin/src/feature/mmu3/mmu3-serial-protocol.md index fd0f1fbcba..0d0f7ac6e0 100644 --- a/Marlin/src/feature/mmu3/mmu3-serial-protocol.md +++ b/Marlin/src/feature/mmu3/mmu3-serial-protocol.md @@ -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:S1*ad\n MMU3:M1*{CRC8}; MMU3:<---nothing--- @@ -61,10 +65,10 @@ 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: FinishingMoves @@ -103,18 +110,20 @@ MMU3: 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:L{Filament index}*{CRC8}\n MMU3:Q0*{CRC8}\n ``` The MMU will respond with status messages: + ``` MMU3:Q0*{CRC8}\n MMU3: ### 🌍 Translations + @@ -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 diff --git a/buildroot/share/dwin/bin/README.md b/buildroot/share/dwin/bin/README.md index c78f4eb97f..b439d53905 100644 --- a/buildroot/share/dwin/bin/README.md +++ b/buildroot/share/dwin/bin/README.md @@ -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 diff --git a/buildroot/share/fonts/README.md b/buildroot/share/fonts/README.md index b80de8e26e..57b4d1f57e 100644 --- a/buildroot/share/fonts/README.md +++ b/buildroot/share/fonts/README.md @@ -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). diff --git a/buildroot/share/git/README.md b/buildroot/share/git/README.md index 4dcd7c15a7..c1474c603b 100755 --- a/buildroot/share/git/README.md +++ b/buildroot/share/git/README.md @@ -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:
- The upstream project ('`MarlinFirmware`')
- the '`origin`' project (i.e., your Github username),
- the repository name ('`Marlin`'),
- the PR target branch ('`bugfix-1.1.x`'), and
- the current branch (or the first command-line argument).

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:
- The upstream project ('`MarlinFirmware`')
- the '`origin`' project (i.e., your Github username),
- the repository name ('`Marlin`'),
- the PR target branch ('`bugfix-1.1.x`'), and
- the current branch (or the first command-line argument).

By itself, `mfinfo` simply prints these values to the console. | +| mfclean      | Prune your merged and remotely-deleted branches. | --- diff --git a/buildroot/share/scripts/linesformat.py b/buildroot/share/scripts/linesformat.py new file mode 100755 index 0000000000..4cbe8190f5 --- /dev/null +++ b/buildroot/share/scripts/linesformat.py @@ -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') diff --git a/buildroot/share/scripts/pinsformat.py b/buildroot/share/scripts/pinsformat.py index 41949c42cc..d9712bbc63 100755 --- a/buildroot/share/scripts/pinsformat.py +++ b/buildroot/share/scripts/pinsformat.py @@ -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 diff --git a/docs/BinaryFileTransferProtocol.md b/docs/BinaryFileTransferProtocol.md index 6d52671789..ebb1194aac 100644 --- a/docs/BinaryFileTransferProtocol.md +++ b/docs/BinaryFileTransferProtocol.md @@ -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` 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` 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,,.. ``` -| 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` acknowledgement. Returns a query response: + ``` PFT:version:..:compression:(,) ``` -| 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` response will be sent. On error, an `ok` 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 diff --git a/docs/Bresenham.md b/docs/Bresenham.md index 2d57a1cdab..6916e35f48 100644 --- a/docs/Bresenham.md +++ b/docs/Bresenham.md @@ -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] diff --git a/docs/ConfigEmbedding.md b/docs/ConfigEmbedding.md index 562661e111..a9770fb42b 100644 --- a/docs/ConfigEmbedding.md +++ b/docs/ConfigEmbedding.md @@ -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 diff --git a/docs/Cutter.md b/docs/Cutter.md index 207036c6e8..932e8cd043 100644 --- a/docs/Cutter.md +++ b/docs/Cutter.md @@ -96,29 +96,29 @@ Step power is either cumulatively added or subtracted during trapeziod ramp prog #### 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 diff --git a/docs/Queue.md b/docs/Queue.md index 6d4fb9d041..e0f50e7807 100644 --- a/docs/Queue.md +++ b/docs/Queue.md @@ -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. diff --git a/docs/Serial.md b/docs/Serial.md index 5e0d7e63eb..9ef9a781fa 100644 --- a/docs/Serial.md +++ b/docs/Serial.md @@ -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, ConditionalSerial > Serial1Class; ``` To send the same output to 4 serial ports you could nest `MultiSerial` like this: + ```cpp typedef MultiSerial< MultiSerial< BaseSerial, BaseSerial >, MultiSerial< BaseSerial, BaseSerial, 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, B=MS, 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)_ diff --git a/test/README.md b/test/README.md index 19b4cd7d59..3bcd29bcc2 100644 --- a/test/README.md +++ b/test/README.md @@ -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:
Aragonés