Compare commits

...

20 Commits

Author SHA1 Message Date
Scott Lahteine
3b8ab730b2 🔖 Version 2.1.2.7 2026-02-03 23:49:37 -06:00
ellensp
3f4c9834bb 🔨 Preflight check for future config (#28320)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-02-03 23:49:37 -06:00
Scott Lahteine
e2208ba58f 🔨 Build quality improvements 2026-01-22 21:40:56 -06:00
Andrivet
57906a8466 🐛 Fix TFT LVGL UI + Y-DIR conflict (#28291)
Fixes #22967
2026-01-22 10:44:31 -06:00
Scott Lahteine
c67f981197 🩹 Fix offset_xy build error 2026-01-22 10:44:31 -06:00
Scott Lahteine
cd4dcee8c1 🔨 Remove dead envs 2026-01-22 10:44:31 -06:00
Scott Lahteine
652a619549 🔨 Update build scripts 2026-01-22 10:44:31 -06:00
Scott Lahteine
5554ccb52f 🔖 Version 2.1.2.6 2026-01-15 16:27:56 -06:00
Scott Lahteine
f869f0eb3b 🔨 No such env env:DUE_debug 2026-01-15 16:27:56 -06:00
Scott Lahteine
14708a3067 Update build scripts 2026-01-14 18:28:59 -06:00
Scott Lahteine
324ce04698 🔧 Uppercase PID, etc. 2026-01-14 18:28:58 -06:00
Scott Lahteine
75a98c6181 🐛 Fix Teensy 4.x stepper timing (#28169)
🧑‍💻 Timer general cleanup
🩹 Teensy 4.x timer mods
2025-11-20 15:25:16 -06:00
ellensp
0f2a057c24 🔨🐛 Don't use broken 'board = fysetc_f6_13' (#28159) 2025-11-05 17:23:55 -06:00
ellensp
d6c4e2f98f 🐛 Fix Hotend > 0 Preheat (#27932) 2025-06-20 16:19:21 -05:00
Scott Lahteine
429b5bcd72 🩹 Fix Y_STOP_PIN alias for Y_MAX_PIN 2025-05-04 15:22:44 -05:00
ellensp
21edd52063 🐛 Fix RAMPS AUX1 RX/TX pins (#27745) 2025-03-19 15:46:52 -05:00
ellensp
a4b7341bbe 🩹 Fix missing BTT_SKR_MINI_E3_V3_0_1 include (#27696) 2025-03-19 15:46:52 -05:00
Scott Lahteine
48142ac7c6 📝 Update HAL documentation, README 2025-03-19 15:46:52 -05:00
Scott Lahteine
f0b960e2ef 🧑‍💻 Update example build scripts 2024-12-16 15:25:47 -06:00
Scott Lahteine
c7e10c5622 🩹 Fix build with Color UI touch items 2024-12-16 15:06:38 -06:00
79 changed files with 1073 additions and 48553 deletions

View File

@@ -35,7 +35,7 @@
*
* Advanced settings can be found in Configuration_adv.h
*/
#define CONFIGURATION_H_VERSION 02010205
#define CONFIGURATION_H_VERSION 02010206
//===========================================================================
//============================= Getting Started =============================
@@ -682,13 +682,13 @@
#if ENABLED(PID_PARAMS_PER_HOTEND)
// Specify up to one value per hotend here, according to your setup.
// If there are fewer values, the last one applies to the remaining hotends.
#define DEFAULT_Kp_LIST { 22.20, 22.20 }
#define DEFAULT_Ki_LIST { 1.08, 1.08 }
#define DEFAULT_Kd_LIST { 114.00, 114.00 }
#define DEFAULT_KP_LIST { 22.20, 22.20 }
#define DEFAULT_KI_LIST { 1.08, 1.08 }
#define DEFAULT_KD_LIST { 114.00, 114.00 }
#else
#define DEFAULT_Kp 22.20
#define DEFAULT_Ki 1.08
#define DEFAULT_Kd 114.00
#define DEFAULT_KP 22.20
#define DEFAULT_KI 1.08
#define DEFAULT_KD 114.00
#endif
#else
#define BANG_MAX 255 // Limit hotend current while in bang-bang mode; 255=full current
@@ -775,9 +775,9 @@
// 120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
// from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
#define DEFAULT_bedKp 10.00
#define DEFAULT_bedKi .023
#define DEFAULT_bedKd 305.4
#define DEFAULT_BED_KP 10.00
#define DEFAULT_BED_KI .023
#define DEFAULT_BED_KD 305.4
// FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles.
#else
@@ -821,9 +821,9 @@
// Lasko "MyHeat Personal Heater" (200w) modified with a Fotek SSR-10DA to control only the heating element
// and placed inside the small Creality printer enclosure tent.
//
#define DEFAULT_chamberKp 37.04
#define DEFAULT_chamberKi 1.40
#define DEFAULT_chamberKd 655.17
#define DEFAULT_CHAMBER_KP 37.04
#define DEFAULT_CHAMBER_KI 1.40
#define DEFAULT_CHAMBER_KD 655.17
// M309 P37.04 I1.04 D655.17
// FIND YOUR OWN: "M303 E-2 C8 S50" to run autotune on the chamber at 50 degreesC for 8 cycles.

View File

@@ -30,7 +30,7 @@
*
* Basic settings can be found in Configuration.h
*/
#define CONFIGURATION_ADV_H_VERSION 02010205
#define CONFIGURATION_ADV_H_VERSION 02010206
// @section develop
@@ -375,14 +375,14 @@
// A well-chosen Kc value should add just enough power to melt the increased material volume.
//#define PID_EXTRUSION_SCALING
#if ENABLED(PID_EXTRUSION_SCALING)
#define DEFAULT_Kc (100) // heating power = Kc * e_speed
#define DEFAULT_KC (100) // heating power = Kc * e_speed
#define LPQ_MAX_LEN 50
#endif
/**
* Add an additional term to the heater power, proportional to the fan speed.
* A well-chosen Kf value should add just enough power to compensate for power-loss from the cooling fan.
* You can either just add a constant compensation with the DEFAULT_Kf value
* You can either just add a constant compensation with the DEFAULT_KF value
* or follow the instruction below to get speed-dependent compensation.
*
* Constant compensation (use only with fan speeds of 0% and 100%)
@@ -413,18 +413,18 @@
#if ENABLED(PID_FAN_SCALING_ALTERNATIVE_DEFINITION)
// The alternative definition is used for an easier configuration.
// Just figure out Kf at full speed (255) and PID_FAN_SCALING_MIN_SPEED.
// DEFAULT_Kf and PID_FAN_SCALING_LIN_FACTOR are calculated accordingly.
// DEFAULT_KF and PID_FAN_SCALING_LIN_FACTOR are calculated accordingly.
#define PID_FAN_SCALING_AT_FULL_SPEED 13.0 //=PID_FAN_SCALING_LIN_FACTOR*255+DEFAULT_Kf
#define PID_FAN_SCALING_AT_MIN_SPEED 6.0 //=PID_FAN_SCALING_LIN_FACTOR*PID_FAN_SCALING_MIN_SPEED+DEFAULT_Kf
#define PID_FAN_SCALING_AT_FULL_SPEED 13.0 //=PID_FAN_SCALING_LIN_FACTOR*255+DEFAULT_KF
#define PID_FAN_SCALING_AT_MIN_SPEED 6.0 //=PID_FAN_SCALING_LIN_FACTOR*PID_FAN_SCALING_MIN_SPEED+DEFAULT_KF
#define PID_FAN_SCALING_MIN_SPEED 10.0 // Minimum fan speed at which to enable PID_FAN_SCALING
#define DEFAULT_Kf (255.0*PID_FAN_SCALING_AT_MIN_SPEED-PID_FAN_SCALING_AT_FULL_SPEED*PID_FAN_SCALING_MIN_SPEED)/(255.0-PID_FAN_SCALING_MIN_SPEED)
#define PID_FAN_SCALING_LIN_FACTOR (PID_FAN_SCALING_AT_FULL_SPEED-DEFAULT_Kf)/255.0
#define DEFAULT_KF (255.0*PID_FAN_SCALING_AT_MIN_SPEED-PID_FAN_SCALING_AT_FULL_SPEED*PID_FAN_SCALING_MIN_SPEED)/(255.0-PID_FAN_SCALING_MIN_SPEED)
#define PID_FAN_SCALING_LIN_FACTOR (PID_FAN_SCALING_AT_FULL_SPEED-DEFAULT_KF)/255.0
#else
#define PID_FAN_SCALING_LIN_FACTOR (0) // Power-loss due to cooling = Kf * (fan_speed)
#define DEFAULT_Kf 10 // A constant value added to the PID-tuner
#define DEFAULT_KF 10 // A constant value added to the PID-tuner
#define PID_FAN_SCALING_MIN_SPEED 10 // Minimum fan speed at which to enable PID_FAN_SCALING
#endif
#endif

View File

@@ -28,7 +28,7 @@
/**
* Marlin release version identifier
*/
//#define SHORT_BUILD_VERSION "2.1.2.5"
//#define SHORT_BUILD_VERSION "2.1.2.7"
/**
* Verbose version identifier which should contain a reference to the location
@@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release
* version was tagged.
*/
//#define STRING_DISTRIBUTION_DATE "2024-11-18"
//#define STRING_DISTRIBUTION_DATE "2026-01-22"
/**
* The protocol for communication to the host. Protocol indicates communication

View File

@@ -111,8 +111,8 @@ FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) {
* (otherwise, characters will be lost due to UART overflow).
* Then: Stepper, Endstops, Temperature, and -finally- all others.
*/
#define HAL_timer_isr_prologue(T) NOOP
#define HAL_timer_isr_epilogue(T) NOOP
inline void HAL_timer_isr_prologue(const uint8_t) {}
inline void HAL_timer_isr_epilogue(const uint8_t) {}
#ifndef HAL_STEP_TIMER_ISR

View File

@@ -127,4 +127,4 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_SR;
}
#define HAL_timer_isr_epilogue(T) NOOP
inline void HAL_timer_isr_epilogue(const uint8_t) {}

View File

@@ -136,5 +136,5 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num);
void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
#define HAL_timer_isr_prologue(T) NOOP
#define HAL_timer_isr_epilogue(T) NOOP
inline void HAL_timer_isr_prologue(const uint8_t) {}
inline void HAL_timer_isr_epilogue(const uint8_t) {}

View File

@@ -1,180 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
/**
* Pins Debugging for HC32
*
* - NUMBER_PINS_TOTAL
* - MULTI_NAME_PAD
* - getPinByIndex(index)
* - printPinNameByIndex(index)
* - getPinIsDigitalByIndex(index)
* - digitalPinToAnalogIndex(pin)
* - getValidPinMode(pin)
* - isValidPin(pin)
* - isAnalogPin(pin)
* - digitalRead_mod(pin)
* - pwm_status(pin)
* - printPinPWM(pin)
* - printPinPort(pin)
* - printPinNumber(pin)
* - printPinAnalog(pin)
*/
#include "../../inc/MarlinConfig.h"
#include "fastio.h"
#include <drivers/timera/timera_pwm.h>
#ifndef BOARD_NR_GPIO_PINS
#error "Expected BOARD_NR_GPIO_PINS not found."
#endif
#define NUM_DIGITAL_PINS BOARD_NR_GPIO_PINS
#define NUMBER_PINS_TOTAL BOARD_NR_GPIO_PINS
#define isValidPin(P) IS_GPIO_PIN(P)
// Note: pin_array is defined in `Marlin/src/pins/pinsDebug.h`, and since this file is included
// after it, it is available in this file as well.
#define getPinByIndex(x) pin_t(pin_array[x].pin)
#define digitalRead_mod(P) extDigitalRead(P)
#define printPinNumber(P) do{ sprintf_P(buffer, PSTR("%3hd "), int16_t(P)); SERIAL_ECHO(buffer); }while(0)
#define printPinAnalog(P) do{ sprintf_P(buffer, PSTR(" (A%2d) "), digitalPinToAnalogIndex(P)); SERIAL_ECHO(buffer); }while(0)
#define printPinNameByIndex(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
#define MULTI_NAME_PAD 21 // Space needed to be pretty if not first name assigned to a pin
//
// Pins that will cause a hang / reset / disconnect in M43 Toggle and Watch utils
//
#ifndef M43_NEVER_TOUCH
// Don't touch any of the following pins:
// - Host serial pins, and
// - Pins that could be connected to oscillators (see datasheet, Table 2.1):
// - XTAL = PH0, PH1
// - XTAL32 = PC14, PC15
#define IS_HOST_USART_PIN(Q) (Q == BOARD_USART2_TX_PIN || Q == BOARD_USART2_RX_PIN)
#define IS_OSC_PIN(Q) (Q == PH0 || Q == PH1 || Q == PC14 || Q == PC15)
#define M43_NEVER_TOUCH(Q) (IS_HOST_USART_PIN(Q) || IS_OSC_PIN(Q))
#endif
int8_t digitalPinToAnalogIndex(const pin_t pin) {
if (!isValidPin(pin)) return -1;
const int8_t adc_channel = int8_t(PIN_MAP[pin].adc_info.channel);
return pin_t(adc_channel);
}
bool isAnalogPin(pin_t pin) {
if (!isValidPin(pin)) return false;
if (PIN_MAP[pin].adc_info.channel != ADC_PIN_INVALID)
return _GET_MODE(pin) == INPUT_ANALOG && !M43_NEVER_TOUCH(pin);
return false;
}
bool getValidPinMode(const pin_t pin) {
return isValidPin(pin) && !IS_INPUT(pin);
}
bool getPinIsDigitalByIndex(const int16_t index) {
const pin_t pin = getPinByIndex(index);
return (!isAnalogPin(pin));
}
/**
* @brief print pin PWM status
* @return true if pin is currently a PWM pin, false otherwise
*/
bool pwm_status(const pin_t pin) {
// Get timer assignment for pin
timera_config_t *unit;
en_timera_channel_t channel;
en_port_func_t port_function;
if (!timera_get_assignment(pin, unit, channel, port_function) || unit == nullptr) {
// No pwm pin or no unit assigned
return false;
}
// A pin that is PWM output is:
// - Assigned to a timerA unit (tested above)
// - Unit is initialized
// - Channel is active
// - PinMode is OUTPUT_PWM
return timera_is_unit_initialized(unit) && timera_is_channel_active(unit, channel) && getPinMode(pin) == OUTPUT_PWM;
}
void printPinPWM(const pin_t pin) {
// Get timer assignment for pin
timera_config_t *unit;
en_timera_channel_t channel;
en_port_func_t port_function;
if (!timera_get_assignment(pin, unit, channel, port_function) || unit == nullptr)
return; // No pwm pin or no unit assigned
// Print timer assignment of pin, eg. "TimerA1Ch2 Func4"
SERIAL_ECHOPGM("TimerA", TIMERA_REG_TO_X(unit->peripheral.register_base),
"Ch", TIMERA_CHANNEL_TO_X(channel),
" Func", int(port_function));
SERIAL_ECHO_SP(3); // 3 spaces
// Print timer unit state, eg. "1/16 PERAR=1234" OR "N/A"
if (timera_is_unit_initialized(unit)) {
// Unit initialized, print
// - Timer clock divider
// - Timer period value (PERAR)
const uint8_t clock_divider = timera_clk_div_to_n(unit->state.base_init->enClkDiv);
const uint16_t period = TIMERA_GetPeriodValue(unit->peripheral.register_base);
SERIAL_ECHOPGM("1/", clock_divider, " PERAR=", period);
}
else {
// Unit not initialized
SERIAL_ECHOPGM("N/A");
return;
}
SERIAL_ECHO_SP(3); // 3 spaces
// Print timer channel state, e.g. "CMPAR=1234" OR "N/A"
if (timera_is_channel_active(unit, channel)) {
// Channel active, print
// - Channel compare value
const uint16_t compare = TIMERA_GetCompareValue(unit->peripheral.register_base, channel);
SERIAL_ECHOPGM("CMPAR=", compare);
}
else {
// Channel inactive
SERIAL_ECHOPGM("N/A");
}
}
void printPinPort(pin_t pin) {
const char port = 'A' + char(pin >> 4); // Pin div 16
const int16_t gbit = PIN_MAP[pin].bit_pos;
char buffer[8];
sprintf_P(buffer, PSTR("P%c%hd "), port, gbit);
if (gbit < 10) {
SERIAL_CHAR(' ');
}
SERIAL_ECHO(buffer);
}

View File

@@ -93,5 +93,5 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num);
void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
#define HAL_timer_isr_prologue(T) NOOP
#define HAL_timer_isr_epilogue(T) NOOP
inline void HAL_timer_isr_prologue(const uint8_t) {}
inline void HAL_timer_isr_epilogue(const uint8_t) {}

View File

@@ -171,4 +171,4 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
}
}
#define HAL_timer_isr_epilogue(T) NOOP
inline void HAL_timer_isr_epilogue(const uint8_t) {}

View File

@@ -88,5 +88,5 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num);
void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
#define HAL_timer_isr_prologue(T) NOOP
#define HAL_timer_isr_epilogue(T) NOOP
inline void HAL_timer_isr_prologue(const uint8_t) {}
inline void HAL_timer_isr_epilogue(const uint8_t) {}

View File

@@ -157,4 +157,4 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
}
}
#define HAL_timer_isr_epilogue(timer_num)
inline void HAL_timer_isr_epilogue(const uint8_t) {}

View File

@@ -145,4 +145,4 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
}
}
#define HAL_timer_isr_epilogue(timer_num)
inline void HAL_timer_isr_epilogue(const uint8_t) {}

View File

@@ -39,12 +39,16 @@ static void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb, u
void MarlinSPI::setClockDivider(uint8_t _div) {
_speed = spi_getClkFreq(&_spi);// / _div;
_clockDivider = _div;
if (_clockDivider != _div) {
_clockDivider = _div;
_mustInit = true;
}
}
void MarlinSPI::begin(void) {
//TODO: only call spi_init if any parameter changed!!
if (!_mustInit) return;
spi_init(&_spi, _speed, _dataMode, _bitOrder, _dataSize);
_mustInit = false;
}
void MarlinSPI::setupDma(SPI_HandleTypeDef &_spiHandle, DMA_HandleTypeDef &_dmaHandle, uint32_t direction, bool minc) {

View File

@@ -76,15 +76,23 @@ public:
/* These methods are deprecated and kept for compatibility.
* Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
*/
void setBitOrder(BitOrder _order) { _bitOrder = _order; }
void setBitOrder(BitOrder order) {
if (_bitOrder == order) return;
_bitOrder = order;
_mustInit = true;
}
void setDataMode(uint8_t _mode) {
switch (_mode) {
void setDataMode(uint8_t mode) {
auto previous_mode = _dataMode;
switch (mode) {
case SPI_MODE0: _dataMode = SPI_MODE_0; break;
case SPI_MODE1: _dataMode = SPI_MODE_1; break;
case SPI_MODE2: _dataMode = SPI_MODE_2; break;
case SPI_MODE3: _dataMode = SPI_MODE_3; break;
default: return;
}
if (previous_mode != _dataMode)
_mustInit = true;
}
void setClockDivider(uint8_t _div);
@@ -104,4 +112,5 @@ private:
pin_t _misoPin;
pin_t _sckPin;
pin_t _ssPin;
bool _mustInit = true;
};

View File

@@ -116,5 +116,5 @@ FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const ha
}
}
#define HAL_timer_isr_prologue(T) NOOP
#define HAL_timer_isr_epilogue(T) NOOP
inline void HAL_timer_isr_prologue(const uint8_t) {}
inline void HAL_timer_isr_epilogue(const uint8_t) {}

View File

@@ -1,56 +1,62 @@
#!/usr/bin/env python
#
# STM32F1/build_flags.py
# Add build_flags for the base STM32F1_maple environment (stm32f1-maple.ini)
#
from __future__ import print_function
import sys
#dynamic build flags for generic compile options
# Dynamic build flags for generic compile options
if __name__ == "__main__":
args = " ".join([ "-std=gnu++14",
"-Os",
"-mcpu=cortex-m3",
"-mthumb",
"-fsigned-char",
"-fno-move-loop-invariants",
"-fno-strict-aliasing",
"-fsingle-precision-constant",
"--specs=nano.specs",
"--specs=nosys.specs",
"-IMarlin/src/HAL/STM32F1",
"-MMD",
"-MP",
"-DTARGET_STM32F1"
])
for i in range(1, len(sys.argv)):
args += " " + sys.argv[i]
print(args)
# extra script for linker options
else:
import pioutil
if pioutil.is_pio_build():
from SCons.Script import DefaultEnvironment
env = DefaultEnvironment()
env.Append(
ARFLAGS=["rcs"],
ASFLAGS=["-x", "assembler-with-cpp"],
CXXFLAGS=[
"-fabi-version=0",
"-fno-use-cxa-atexit",
"-fno-threadsafe-statics"
],
LINKFLAGS=[
# Print these plus the given args when running directly on the command-line
args = [
"-std=gnu++14",
"-Os",
"-mcpu=cortex-m3",
"-ffreestanding",
"-mthumb",
"-fsigned-char",
"-fno-move-loop-invariants",
"-fno-strict-aliasing",
"--specs=nano.specs",
"--specs=nosys.specs",
"-u_printf_float",
],
)
"-MMD", "-MP",
"-IMarlin/src/HAL/STM32F1",
"-DTARGET_STM32F1",
"-DARDUINO_ARCH_STM32",
"-DPLATFORM_M997_SUPPORT"
] + sys.argv[1:]
print(" ".join(args))
else:
# Extra script for stm32f1-maple.ini build_flags
import pioutil
if pioutil.is_pio_build():
pioutil.env.Append(
ARFLAGS=["rcs"],
ASFLAGS=["-x", "assembler-with-cpp"],
CXXFLAGS=[
"-fabi-version=0",
"-fno-use-cxa-atexit",
"-fno-threadsafe-statics"
],
LINKFLAGS=[
"-Os",
"-mcpu=cortex-m3",
"-ffreestanding",
"-mthumb",
"--specs=nano.specs",
"--specs=nosys.specs",
"-u_printf_float",
],
)

View File

@@ -188,7 +188,7 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
}
}
#define HAL_timer_isr_epilogue(T) NOOP
inline void HAL_timer_isr_epilogue(const uint8_t) {}
// No command is available in framework to turn off ARPE bit, which is turned on by default in libmaple.
// Needed here to reset ARPE=0 for stepper timer

View File

@@ -74,10 +74,10 @@ typedef uint32_t hal_timer_t;
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
#ifndef HAL_STEP_TIMER_ISR
#define HAL_STEP_TIMER_ISR() extern "C" void ftm0_isr() //void TC3_Handler()
#define HAL_STEP_TIMER_ISR() extern "C" void ftm0_isr()
#endif
#ifndef HAL_TEMP_TIMER_ISR
#define HAL_TEMP_TIMER_ISR() extern "C" void ftm1_isr() //void TC4_Handler()
#define HAL_TEMP_TIMER_ISR() extern "C" void ftm1_isr()
#endif
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
@@ -110,4 +110,4 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
void HAL_timer_isr_prologue(const uint8_t timer_num);
#define HAL_timer_isr_epilogue(T) NOOP
inline void HAL_timer_isr_epilogue(const uint8_t) {}

View File

@@ -110,4 +110,4 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
void HAL_timer_isr_prologue(const uint8_t timer_num);
#define HAL_timer_isr_epilogue(T) NOOP
inline void HAL_timer_isr_epilogue(const uint8_t) {}

View File

@@ -30,41 +30,82 @@
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
switch (timer_num) {
//
// Step Timer GPT1 - Compare Interrupt OCR1 - Reset Mode
//
case MF_TIMER_STEP:
CCM_CSCMR1 &= ~CCM_CSCMR1_PERCLK_CLK_SEL; // turn off 24mhz mode
// 24MHz mode off Use peripheral clock (150MHz)
CCM_CSCMR1 &= ~CCM_CSCMR1_PERCLK_CLK_SEL;
// Enable GPT1 clock gating
CCM_CCGR1 |= CCM_CCGR1_GPT1_BUS(CCM_CCGR_ON);
GPT1_CR = 0; // disable timer
GPT1_SR = 0x3F; // clear all prior status
GPT1_PR = GPT1_TIMER_PRESCALE - 1;
GPT1_CR |= GPT_CR_CLKSRC(1); //clock selection #1 (peripheral clock = 150 MHz)
GPT1_CR |= GPT_CR_ENMOD; //reset count to zero before enabling
GPT1_CR |= GPT_CR_OM1(1); // toggle mode
GPT1_OCR1 = (GPT1_TIMER_RATE / frequency) -1; // Initial compare value
GPT1_IR = GPT_IR_OF1IE; // Compare3 value
GPT1_CR |= GPT_CR_EN; //enable GPT2 counting at 150 MHz
// Disable timer, clear all status bits
GPT1_CR = 0; // Disable timer
GPT1_SR = 0x3F; // Clear all prior status
OUT_WRITE(15, HIGH);
// Prescaler = 2 => 75MHz counting clock
GPT1_PR = GPT1_TIMER_PRESCALE - 1;
GPT1_CR = GPT_CR_CLKSRC(1) // Clock selection #1 (peripheral clock = 150 MHz)
| GPT_CR_ENMOD // Reset count to zero before enabling
| GPT_CR_OM2(TERN(MARLIN_DEV_MODE, 1, 0)); // 0 = edge compare, 1 = toggle
// Compare value the number of clocks between edges
GPT1_OCR1 = (GPT1_TIMER_RATE / frequency) - 1;
// Enable compareevent interrupt
GPT1_IR = GPT_IR_OF1IE; // OF1 interrupt enabled
// Pull Pin 15 HIGH (logichigh is the “idle” state)
TERN_(MARLIN_DEV_MODE, OUT_WRITE(15, HIGH));
// Attach and enable Stepper IRQ
// Note: UART priority is 16
attachInterruptVector(IRQ_GPT1, &stepTC_Handler);
NVIC_SET_PRIORITY(IRQ_GPT1, 16);
NVIC_SET_PRIORITY(IRQ_GPT1, 16); // Priority 16 (higher than Temp Timer)
// Start GPT1 counting at 150 MHz
GPT1_CR |= GPT_CR_EN;
break;
//
// Temperature Timer GPT2 - Compare Interrupt OCR1 - Reset Mode
//
case MF_TIMER_TEMP:
CCM_CSCMR1 &= ~CCM_CSCMR1_PERCLK_CLK_SEL; // turn off 24mhz mode
// 24MHz mode off Use peripheral clock (150MHz)
CCM_CSCMR1 &= ~CCM_CSCMR1_PERCLK_CLK_SEL;
// Enable GPT2 clock gating
CCM_CCGR0 |= CCM_CCGR0_GPT2_BUS(CCM_CCGR_ON);
GPT2_CR = 0; // disable timer
GPT2_SR = 0x3F; // clear all prior status
GPT2_PR = GPT2_TIMER_PRESCALE - 1;
GPT2_CR |= GPT_CR_CLKSRC(1); //clock selection #1 (peripheral clock = 150 MHz)
GPT2_CR |= GPT_CR_ENMOD; //reset count to zero before enabling
GPT2_CR |= GPT_CR_OM1(1); // toggle mode
GPT2_OCR1 = (GPT2_TIMER_RATE / frequency) -1; // Initial compare value
GPT2_IR = GPT_IR_OF1IE; // Compare3 value
GPT2_CR |= GPT_CR_EN; //enable GPT2 counting at 150 MHz
// Disable timer, clear all status bits
GPT2_CR = 0; // Disable timer
GPT2_SR = 0x3F; // Clear all prior status
OUT_WRITE(14, HIGH);
// Prescaler = 10 => 15MHz counting clock
GPT2_PR = GPT2_TIMER_PRESCALE - 1;
GPT2_CR = GPT_CR_CLKSRC(1) // Clock selection #1 (peripheral clock = 150 MHz)
| GPT_CR_ENMOD // and reset count to zero before enabling
| GPT_CR_OM2(TERN(MARLIN_DEV_MODE, 1, 0)); // 0 = edge compare, 1 = toggle
// Compare value the number of clocks between edges
GPT2_OCR1 = (GPT2_TIMER_RATE / frequency) - 1;
// Enable compareevent interrupt
GPT2_IR = GPT_IR_OF1IE; // OF1 interrupt enabled
// Pull Pin 14 HIGH (logichigh is the “idle” state)
TERN_(MARLIN_DEV_MODE, OUT_WRITE(14, HIGH));
// Attach Temperature ISR
attachInterruptVector(IRQ_GPT2, &tempTC_Handler);
NVIC_SET_PRIORITY(IRQ_GPT2, 32);
NVIC_SET_PRIORITY(IRQ_GPT2, 32); // Priority 32 (lower than Step Timer)
// Start GPT2 counting at 150 MHz
GPT2_CR |= GPT_CR_EN;
break;
}
}
@@ -82,6 +123,7 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num) {
case MF_TIMER_TEMP: NVIC_DISABLE_IRQ(IRQ_GPT2); break;
}
// Ensure the CPU actually stops servicing the IRQ
// We NEED memory barriers to ensure Interrupts are actually disabled!
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
asm volatile("dsb");
@@ -97,8 +139,8 @@ bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
void HAL_timer_isr_prologue(const uint8_t timer_num) {
switch (timer_num) {
case MF_TIMER_STEP: GPT1_SR = GPT_IR_OF1IE; break; // clear OF3 bit
case MF_TIMER_TEMP: GPT2_SR = GPT_IR_OF1IE; break; // clear OF3 bit
case MF_TIMER_STEP: GPT1_SR = GPT_IR_OF1IE; break; // clear OF1
case MF_TIMER_TEMP: GPT2_SR = GPT_IR_OF1IE; break;
}
asm volatile("dsb");
}

View File

@@ -60,7 +60,7 @@ typedef uint32_t hal_timer_t;
#define HAL_TIMER_RATE GPT1_TIMER_RATE
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000)
#define STEPPER_TIMER_PRESCALE ((GPT_TIMER_RATE / 1000000) / STEPPER_TIMER_TICKS_PER_US)
#define STEPPER_TIMER_PRESCALE (GPT_TIMER_RATE / STEPPER_TIMER_RATE)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
@@ -89,8 +89,16 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
switch (timer_num) {
case MF_TIMER_STEP: GPT1_OCR1 = compare - 1; break;
case MF_TIMER_TEMP: GPT2_OCR1 = compare - 1; break;
case MF_TIMER_STEP:
GPT1_CR |= GPT_CR_FRR; // Free Run Mode (setting OCRx preserves CNT)
GPT1_OCR1 = compare - 1;
GPT1_CR &= ~GPT_CR_FRR; // Reset Mode (CNT resets on trigger)
break;
case MF_TIMER_TEMP:
GPT2_CR |= GPT_CR_FRR; // Free Run Mode (setting OCRx preserves CNT)
GPT2_OCR1 = compare - 1;
GPT2_CR &= ~GPT_CR_FRR; // Reset Mode (CNT resets on trigger)
break;
}
}
@@ -115,5 +123,4 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
void HAL_timer_isr_prologue(const uint8_t timer_num);
//void HAL_timer_isr_epilogue(const uint8_t timer_num) {}
#define HAL_timer_isr_epilogue(T) NOOP
inline void HAL_timer_isr_epilogue(const uint8_t) {}

View File

@@ -802,3 +802,5 @@
#define _HAS_E_TEMP(N) || TEMP_SENSOR(N)
#define HAS_E_TEMP_SENSOR (0 REPEAT(EXTRUDERS, _HAS_E_TEMP))
#define TEMP_SENSOR_IS_MAX_TC(T) (TEMP_SENSOR(T) == -5 || TEMP_SENSOR(T) == -3 || TEMP_SENSOR(T) == -2)
#define DGUS_UI_IS(...) 0 // Dummy macro needed for future preflight checking

View File

@@ -621,6 +621,18 @@
#error "BTT_MINI_12864_V1 is now BTT_MINI_12864."
#elif defined(SDIO_SUPPORT)
#error "SDIO_SUPPORT is now ONBOARD_SDIO."
#elif defined(DEFAULT_Kp_LIST) || defined(DEFAULT_Ki_LIST) || defined(DEFAULT_Kd_LIST)
#error "DEFAULT_Kp_LIST, DEFAULT_Ki_LIST, DEFAULT_Kd_LIST are now (uppercase) DEFAULT_KP_LIST, DEFAULT_KI_LIST, DEFAULT_KD_LIST."
#elif defined(DEFAULT_Kp) || defined(DEFAULT_Ki) || defined(DEFAULT_Kd)
#error "DEFAULT_Kp, DEFAULT_Ki, DEFAULT_Kd are now (uppercase) DEFAULT_KP, DEFAULT_KI, DEFAULT_KD."
#elif defined(DEFAULT_bedKp) || defined(DEFAULT_bedKi) || defined(DEFAULT_bedKd)
#error "DEFAULT_bedKp, DEFAULT_bedKi, DEFAULT_bedKd are now DEFAULT_BED_KP, DEFAULT_BED_KI, DEFAULT_BED_KD."
#elif defined(DEFAULT_chamberKp) || defined(DEFAULT_chamberKi) || defined(DEFAULT_chamberKd)
#error "DEFAULT_chamberKp, DEFAULT_chamberKi, DEFAULT_chamberKd are now DEFAULT_CHAMBER_KP, DEFAULT_CHAMBER_KI, DEFAULT_CHAMBER_KD."
#elif defined(DEFAULT_Kc)
#error "DEFAULT_Kc is now (uppercase) DEFAULT_KC."
#elif defined(DEFAULT_Kf)
#error "DEFAULT_Kf is now (uppercase) DEFAULT_KF."
#endif
// L64xx stepper drivers have been removed

View File

@@ -1013,6 +1013,7 @@
#endif
#if ANY(HAS_DWIN_E3V2_BASIC, DWIN_CREALITY_LCD_JYERSUI)
#define HAS_DWIN_E3V2 1
#undef LCD_BED_LEVELING // allow for MESH_EDIT_MENU
#endif
// E3V2 extras

View File

@@ -1528,7 +1528,7 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
* LCD_BED_LEVELING requirements
*/
#if ENABLED(LCD_BED_LEVELING)
#if !HAS_MARLINUI_MENU
#if NONE(HAS_MARLINUI_MENU, DWIN_LCD_PROUI)
#error "LCD_BED_LEVELING is not supported by the selected LCD controller."
#elif !(ENABLED(MESH_BED_LEVELING) || HAS_ABL_NOT_UBL)
#error "LCD_BED_LEVELING requires MESH_BED_LEVELING or AUTO_BED_LEVELING."

View File

@@ -25,7 +25,7 @@
* Release version. Leave the Marlin version or apply a custom scheme.
*/
#ifndef SHORT_BUILD_VERSION
#define SHORT_BUILD_VERSION "2.1.2.5"
#define SHORT_BUILD_VERSION "2.1.2.7"
#endif
/**
@@ -42,7 +42,7 @@
* version was tagged.
*/
#ifndef STRING_DISTRIBUTION_DATE
#define STRING_DISTRIBUTION_DATE "2024-11-18"
#define STRING_DISTRIBUTION_DATE "2026-01-22"
#endif
/**
@@ -52,7 +52,7 @@
* to alert users to major changes.
*/
#define MARLIN_HEX_VERSION 02010205
#define MARLIN_HEX_VERSION 02010206
#ifndef REQUIRED_CONFIGURATION_H_VERSION
#define REQUIRED_CONFIGURATION_H_VERSION MARLIN_HEX_VERSION
#endif

View File

@@ -503,7 +503,9 @@ void MarlinUI::draw_status_screen() {
const bool show_e_total = TERN0(LCD_SHOW_E_TOTAL, printingIsActive());
static u8g_uint_t progress_bar_solid_width = 0;
#if HAS_PRINT_PROGRESS
static u8g_uint_t progress_bar_solid_width = 0;
#endif
// At the first page, generate new display values
if (first_page) {

View File

@@ -127,7 +127,7 @@ void DWIN_WriteToMem(uint8_t mem, uint16_t addr, uint16_t length, uint8_t *data)
DWIN_Word(i, addr + indx); // start address of the data block
++i;
for (uint8_t j = 0; j < i; ++j) { LCD_SERIAL.write(DWIN_SendBuf[j]); delayMicroseconds(1); } // Buf header
for (uint16_t j = indx; j <= indx + to_send - 1; j++) LCD_SERIAL.write(*(data + j)); delayMicroseconds(1); // write block of data
for (uint16_t j = indx; j <= indx + to_send - 1; j++) { LCD_SERIAL.write(*(data + j)); delayMicroseconds(1); } // write block of data
for (uint8_t j = 0; j < 4; ++j) { LCD_SERIAL.write(DWIN_BufTail[j]); delayMicroseconds(1); }
block++;
pending -= to_send;

View File

@@ -128,7 +128,7 @@ void onDrawMenuItem(MenuItemClass* menuitem, int8_t line) {
if (menuitem->icon) DWINUI::Draw_Icon(menuitem->icon, ICOX, MBASE(line) - 3);
if (menuitem->frameid)
DWIN_Frame_AreaCopy(menuitem->frameid, menuitem->frame.left, menuitem->frame.top, menuitem->frame.right, menuitem->frame.bottom, LBLX, MBASE(line));
else if (menuitem->caption)
else if (menuitem->caption[0])
DWINUI::Draw_String(LBLX, MBASE(line) - 1, menuitem->caption);
DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MYPOS(line + 1), 240);
}

View File

@@ -548,7 +548,7 @@ public:
static FSTR_P get_preheat_label(const uint8_t m);
static void apply_preheat(const uint8_t m, const uint8_t pmask, const uint8_t e=active_extruder);
static void preheat_set_fan(const uint8_t m) { TERN_(HAS_FAN, apply_preheat(m, _BV(PT_FAN))); }
static void preheat_hotend(const uint8_t m, const uint8_t e=active_extruder) { TERN_(HAS_HOTEND, apply_preheat(m, _BV(PT_HOTEND))); }
static void preheat_hotend(const uint8_t m, const uint8_t e=active_extruder) { TERN_(HAS_HOTEND, apply_preheat(m, _BV(PT_HOTEND), e)); }
static void preheat_hotend_and_fan(const uint8_t m, const uint8_t e=active_extruder) { preheat_hotend(m, e); preheat_set_fan(m); }
static void preheat_bed(const uint8_t m) { TERN_(HAS_HEATED_BED, apply_preheat(m, _BV(PT_BED))); }
static void preheat_all(const uint8_t m) { apply_preheat(m, PT_ALL); }

View File

@@ -36,11 +36,9 @@
#include "../../module/probe.h"
#endif
#if HAS_GRAPHICAL_TFT
#if ALL(TOUCH_SCREEN, HAS_GRAPHICAL_TFT)
#include "../tft/tft.h"
#if ENABLED(TOUCH_SCREEN)
#include "../tft/touch.h"
#endif
#include "../tft/touch.h"
#endif
#if ANY(PROBE_MANUALLY, MESH_BED_LEVELING)

View File

@@ -36,6 +36,11 @@
#define XATC_Y_POSITION ((probe.max_y() - probe.min_y())/2)
#endif
#if ALL(TOUCH_SCREEN, HAS_GRAPHICAL_TFT)
#include "../tft/tft.h"
#include "../tft/touch.h"
#endif
void _goto_manual_move_z(const_float_t);
float measured_z, z_offset;

View File

@@ -109,6 +109,8 @@ xyz_pos_t Probe::offset; // Initialized by settings.load
#if HAS_PROBE_XY_OFFSET
const xy_pos_t &Probe::offset_xy = Probe::offset;
#else
constexpr xy_pos_t Probe::offset_xy;
#endif
#if ENABLED(SENSORLESS_PROBING)

View File

@@ -3242,47 +3242,47 @@ void MarlinSettings::reset() {
#if ENABLED(PIDTEMP)
#if ENABLED(PID_PARAMS_PER_HOTEND)
constexpr float defKp[] =
#ifdef DEFAULT_Kp_LIST
DEFAULT_Kp_LIST
constexpr float defKP[] =
#ifdef DEFAULT_KP_LIST
DEFAULT_KP_LIST
#else
ARRAY_BY_HOTENDS1(DEFAULT_Kp)
ARRAY_BY_HOTENDS1(DEFAULT_KP)
#endif
, defKi[] =
#ifdef DEFAULT_Ki_LIST
DEFAULT_Ki_LIST
, defKI[] =
#ifdef DEFAULT_KI_LIST
DEFAULT_KI_LIST
#else
ARRAY_BY_HOTENDS1(DEFAULT_Ki)
ARRAY_BY_HOTENDS1(DEFAULT_KI)
#endif
, defKd[] =
#ifdef DEFAULT_Kd_LIST
DEFAULT_Kd_LIST
, defKD[] =
#ifdef DEFAULT_KD_LIST
DEFAULT_KD_LIST
#else
ARRAY_BY_HOTENDS1(DEFAULT_Kd)
ARRAY_BY_HOTENDS1(DEFAULT_KD)
#endif
;
static_assert(WITHIN(COUNT(defKp), 1, HOTENDS), "DEFAULT_Kp_LIST must have between 1 and HOTENDS items.");
static_assert(WITHIN(COUNT(defKi), 1, HOTENDS), "DEFAULT_Ki_LIST must have between 1 and HOTENDS items.");
static_assert(WITHIN(COUNT(defKd), 1, HOTENDS), "DEFAULT_Kd_LIST must have between 1 and HOTENDS items.");
static_assert(WITHIN(COUNT(defKP), 1, HOTENDS), "DEFAULT_KP_LIST must have between 1 and HOTENDS items.");
static_assert(WITHIN(COUNT(defKI), 1, HOTENDS), "DEFAULT_KI_LIST must have between 1 and HOTENDS items.");
static_assert(WITHIN(COUNT(defKD), 1, HOTENDS), "DEFAULT_KD_LIST must have between 1 and HOTENDS items.");
#if ENABLED(PID_EXTRUSION_SCALING)
constexpr float defKc[] =
#ifdef DEFAULT_Kc_LIST
DEFAULT_Kc_LIST
constexpr float defKC[] =
#ifdef DEFAULT_KC_LIST
DEFAULT_KC_LIST
#else
ARRAY_BY_HOTENDS1(DEFAULT_Kc)
ARRAY_BY_HOTENDS1(DEFAULT_KC)
#endif
;
static_assert(WITHIN(COUNT(defKc), 1, HOTENDS), "DEFAULT_Kc_LIST must have between 1 and HOTENDS items.");
static_assert(WITHIN(COUNT(defKC), 1, HOTENDS), "DEFAULT_KC_LIST must have between 1 and HOTENDS items.");
#endif
#if ENABLED(PID_FAN_SCALING)
constexpr float defKf[] =
#ifdef DEFAULT_Kf_LIST
DEFAULT_Kf_LIST
constexpr float defKF[] =
#ifdef DEFAULT_KF_LIST
DEFAULT_KF_LIST
#else
ARRAY_BY_HOTENDS1(DEFAULT_Kf)
ARRAY_BY_HOTENDS1(DEFAULT_KF)
#endif
;
static_assert(WITHIN(COUNT(defKf), 1, HOTENDS), "DEFAULT_Kf_LIST must have between 1 and HOTENDS items.");
static_assert(WITHIN(COUNT(defKF), 1, HOTENDS), "DEFAULT_KF_LIST must have between 1 and HOTENDS items.");
#endif
#define PID_DEFAULT(N,E) def##N[E]
#else
@@ -3290,11 +3290,11 @@ void MarlinSettings::reset() {
#endif
HOTEND_LOOP() {
thermalManager.temp_hotend[e].pid.set(
PID_DEFAULT(Kp, ALIM(e, defKp)),
PID_DEFAULT(Ki, ALIM(e, defKi)),
PID_DEFAULT(Kd, ALIM(e, defKd))
OPTARG(PID_EXTRUSION_SCALING, PID_DEFAULT(Kc, ALIM(e, defKc)))
OPTARG(PID_FAN_SCALING, PID_DEFAULT(Kf, ALIM(e, defKf)))
PID_DEFAULT(KP, ALIM(e, defKP)),
PID_DEFAULT(KI, ALIM(e, defKI)),
PID_DEFAULT(KD, ALIM(e, defKD))
OPTARG(PID_EXTRUSION_SCALING, PID_DEFAULT(KC, ALIM(e, defKC)))
OPTARG(PID_FAN_SCALING, PID_DEFAULT(KF, ALIM(e, defKF)))
);
}
#endif
@@ -3308,14 +3308,14 @@ void MarlinSettings::reset() {
// Heated Bed PID
//
#if ENABLED(PIDTEMPBED)
thermalManager.temp_bed.pid.set(DEFAULT_bedKp, DEFAULT_bedKi, DEFAULT_bedKd);
thermalManager.temp_bed.pid.set(DEFAULT_BED_KP, DEFAULT_BED_KI, DEFAULT_BED_KD);
#endif
//
// Heated Chamber PID
//
#if ENABLED(PIDTEMPCHAMBER)
thermalManager.temp_chamber.pid.set(DEFAULT_chamberKp, DEFAULT_chamberKi, DEFAULT_chamberKd);
thermalManager.temp_chamber.pid.set(DEFAULT_CHAMBER_KP, DEFAULT_CHAMBER_KI, DEFAULT_CHAMBER_KD);
#endif
//

View File

@@ -1454,11 +1454,7 @@ HAL_STEP_TIMER_ISR() {
HAL_timer_isr_epilogue(MF_TIMER_STEP);
}
#ifdef CPU_32_BIT
#define STEP_MULTIPLY(A,B) MultiU32X24toH32(A, B)
#else
#define STEP_MULTIPLY(A,B) MultiU24X32toH16(A, B)
#endif
#define STEP_MULTIPLY(A,B) TERN(CPU_32_BIT, MultiU32X24toH32, MultiU24X32toH16)(A, B)
void Stepper::isr() {

View File

@@ -839,14 +839,14 @@ volatile bool Temperature::raw_temps_ready = false;
TERN_(HOST_PROMPT_SUPPORT, hostui.notify(GET_TEXT_F(MSG_PID_AUTOTUNE_DONE)));
#if ANY(PIDTEMPBED, PIDTEMPCHAMBER)
FSTR_P const estring = GHV(F("chamber"), F("bed"), FPSTR(NUL_STR));
say_default_(); SERIAL_ECHOF(estring); SERIAL_ECHOLNPGM("Kp ", tune_pid.p);
say_default_(); SERIAL_ECHOF(estring); SERIAL_ECHOLNPGM("Ki ", tune_pid.i);
say_default_(); SERIAL_ECHOF(estring); SERIAL_ECHOLNPGM("Kd ", tune_pid.d);
FSTR_P const estring = GHV(F("CHAMBER_"), F("BED_"), FPSTR(NUL_STR));
say_default_(); SERIAL_ECHOF(estring); SERIAL_ECHOLNPGM("KP ", tune_pid.p);
say_default_(); SERIAL_ECHOF(estring); SERIAL_ECHOLNPGM("KI ", tune_pid.i);
say_default_(); SERIAL_ECHOF(estring); SERIAL_ECHOLNPGM("KD ", tune_pid.d);
#else
say_default_(); SERIAL_ECHOLNPGM("Kp ", tune_pid.p);
say_default_(); SERIAL_ECHOLNPGM("Ki ", tune_pid.i);
say_default_(); SERIAL_ECHOLNPGM("Kd ", tune_pid.d);
say_default_(); SERIAL_ECHOLNPGM("KP ", tune_pid.p);
say_default_(); SERIAL_ECHOLNPGM("KI ", tune_pid.i);
say_default_(); SERIAL_ECHOLNPGM("KD ", tune_pid.d);
#endif
auto _set_hotend_pid = [](const uint8_t tool, const raw_pid_t &in_pid) {

View File

@@ -178,9 +178,9 @@
#elif MB(DAGOMA_F5)
#include "ramps/pins_DAGOMA_F5.h" // ATmega2560 env:mega2560
#elif MB(FYSETC_F6_13)
#include "ramps/pins_FYSETC_F6_13.h" // ATmega2560 env:FYSETC_F6
#include "ramps/pins_FYSETC_F6_13.h" // ATmega2560 env:mega2560ext
#elif MB(FYSETC_F6_14)
#include "ramps/pins_FYSETC_F6_14.h" // ATmega2560 env:FYSETC_F6
#include "ramps/pins_FYSETC_F6_14.h" // ATmega2560 env:mega2560ext
#elif MB(DUPLICATOR_I3_PLUS)
#include "ramps/pins_DUPLICATOR_I3_PLUS.h" // ATmega2560 env:mega2560
#elif MB(VORON)
@@ -449,33 +449,33 @@
//
#elif MB(DUE3DOM)
#include "sam/pins_DUE3DOM.h" // SAM3X8E env:DUE env:DUE_USB env:DUE_debug
#include "sam/pins_DUE3DOM.h" // SAM3X8E env:DUE env:DUE_USB
#elif MB(DUE3DOM_MINI)
#include "sam/pins_DUE3DOM_MINI.h" // SAM3X8E env:DUE env:DUE_USB env:DUE_debug
#include "sam/pins_DUE3DOM_MINI.h" // SAM3X8E env:DUE env:DUE_USB
#elif MB(RADDS)
#include "sam/pins_RADDS.h" // SAM3X8E env:DUE env:DUE_USB env:DUE_debug
#include "sam/pins_RADDS.h" // SAM3X8E env:DUE env:DUE_USB
#elif MB(RAMPS_FD_V1)
#include "sam/pins_RAMPS_FD_V1.h" // SAM3X8E env:DUE env:DUE_USB env:DUE_debug
#include "sam/pins_RAMPS_FD_V1.h" // SAM3X8E env:DUE env:DUE_USB
#elif MB(RAMPS_FD_V2)
#include "sam/pins_RAMPS_FD_V2.h" // SAM3X8E env:DUE env:DUE_USB env:DUE_debug
#include "sam/pins_RAMPS_FD_V2.h" // SAM3X8E env:DUE env:DUE_USB
#elif MB(RAMPS_SMART_EFB, RAMPS_SMART_EEB, RAMPS_SMART_EFF, RAMPS_SMART_EEF, RAMPS_SMART_SF)
#include "sam/pins_RAMPS_SMART.h" // SAM3X8E env:DUE env:DUE_USB env:DUE_debug
#include "sam/pins_RAMPS_SMART.h" // SAM3X8E env:DUE env:DUE_USB
#elif MB(RAMPS_DUO_EFB, RAMPS_DUO_EEB, RAMPS_DUO_EFF, RAMPS_DUO_EEF, RAMPS_DUO_SF)
#include "sam/pins_RAMPS_DUO.h" // SAM3X8E env:DUE env:DUE_USB env:DUE_debug
#include "sam/pins_RAMPS_DUO.h" // SAM3X8E env:DUE env:DUE_USB
#elif MB(RAMPS4DUE_EFB, RAMPS4DUE_EEB, RAMPS4DUE_EFF, RAMPS4DUE_EEF, RAMPS4DUE_SF)
#include "sam/pins_RAMPS4DUE.h" // SAM3X8E env:DUE env:DUE_USB env:DUE_debug
#include "sam/pins_RAMPS4DUE.h" // SAM3X8E env:DUE env:DUE_USB
#elif MB(RURAMPS4D_11)
#include "sam/pins_RURAMPS4D_11.h" // SAM3X8E env:DUE env:DUE_USB env:DUE_debug
#include "sam/pins_RURAMPS4D_11.h" // SAM3X8E env:DUE env:DUE_USB
#elif MB(RURAMPS4D_13)
#include "sam/pins_RURAMPS4D_13.h" // SAM3X8E env:DUE env:DUE_USB env:DUE_debug
#include "sam/pins_RURAMPS4D_13.h" // SAM3X8E env:DUE env:DUE_USB
#elif MB(ULTRATRONICS_PRO)
#include "sam/pins_ULTRATRONICS_PRO.h" // SAM3X8E env:DUE env:DUE_debug
#include "sam/pins_ULTRATRONICS_PRO.h" // SAM3X8E env:DUE
#elif MB(ARCHIM1)
#include "sam/pins_ARCHIM1.h" // SAM3X8E env:DUE_archim env:DUE_archim_debug
#include "sam/pins_ARCHIM1.h" // SAM3X8E env:DUE_archim
#elif MB(ARCHIM2)
#include "sam/pins_ARCHIM2.h" // SAM3X8E env:DUE_archim env:DUE_archim_debug
#include "sam/pins_ARCHIM2.h" // SAM3X8E env:DUE_archim
#elif MB(ALLIGATOR)
#include "sam/pins_ALLIGATOR_R2.h" // SAM3X8E env:DUE env:DUE_debug
#include "sam/pins_ALLIGATOR_R2.h" // SAM3X8E env:DUE
#elif MB(CNCONTROLS_15D)
#include "sam/pins_CNCONTROLS_15D.h" // SAM3X8E env:DUE env:DUE_USB
#elif MB(KRATOS32)
@@ -488,7 +488,7 @@
#elif MB(PRINTRBOARD_G2)
#include "sam/pins_PRINTRBOARD_G2.h" // SAM3X8C env:DUE_USB
#elif MB(ADSK)
#include "sam/pins_ADSK.h" // SAM3X8C env:DUE env:DUE_debug
#include "sam/pins_ADSK.h" // SAM3X8C env:DUE
//
// STM32 ARM Cortex-M0+
@@ -670,6 +670,8 @@
#include "stm32f4/pins_RUMBA32_BTT.h" // STM32F4 env:rumba32
#elif MB(BLACK_STM32F407VE)
#include "stm32f4/pins_BLACK_STM32F407VE.h" // STM32F4 env:STM32F407VE_black
#elif MB(BTT_SKR_MINI_E3_V3_0_1)
#include "stm32f4/pins_BTT_SKR_MINI_E3_V3_0_1.h" // STM32F4 env:STM32F401RC_btt env:STM32F401RC_btt_xfer
#elif MB(BTT_SKR_PRO_V1_1)
#include "stm32f4/pins_BTT_SKR_PRO_V1_1.h" // STM32F4 env:BIGTREE_SKR_PRO env:BIGTREE_SKR_PRO_usb_flash_drive
#elif MB(BTT_SKR_PRO_V1_2)

View File

@@ -613,7 +613,7 @@
#endif
#elif X_HOME_TO_MIN
#define X_STOP_PIN X_MIN_PIN
#else
#elif X_HOME_TO_MAX
#define X_STOP_PIN X_MAX_PIN
#endif
#if !defined(X2_USE_ENDSTOP) && ENABLED(X_DUAL_ENDSTOPS) && PIN_EXISTS(X_STOP)
@@ -635,7 +635,7 @@
#endif
#elif Y_HOME_TO_MIN
#define Y_STOP_PIN Y_MIN_PIN
#else
#elif Y_HOME_TO_MAX
#define Y_STOP_PIN Y_MAX_PIN
#endif
#if !defined(Y2_USE_ENDSTOP) && ENABLED(Y_DUAL_ENDSTOPS) && PIN_EXISTS(Y_STOP)
@@ -658,7 +658,7 @@
#endif
#elif Z_HOME_TO_MIN
#define Z_STOP_PIN Z_MIN_PIN
#else
#elif Z_HOME_TO_MAX
#define Z_STOP_PIN Z_MAX_PIN
#endif
#if ENABLED(Z_MULTI_ENDSTOPS) && PIN_EXISTS(Z_STOP)
@@ -689,7 +689,7 @@
#endif
#elif I_HOME_TO_MIN
#define I_STOP_PIN I_MIN_PIN
#else
#elif I_HOME_TO_MAX
#define I_STOP_PIN I_MAX_PIN
#endif
#else
@@ -712,7 +712,7 @@
#endif
#elif J_HOME_TO_MIN
#define J_STOP_PIN J_MIN_PIN
#else
#elif J_HOME_TO_MAX
#define J_STOP_PIN J_MAX_PIN
#endif
#else
@@ -735,7 +735,7 @@
#endif
#elif K_HOME_TO_MIN
#define K_STOP_PIN K_MIN_PIN
#else
#elif K_HOME_TO_MAX
#define K_STOP_PIN K_MAX_PIN
#endif
#else
@@ -758,7 +758,7 @@
#endif
#elif U_HOME_TO_MIN
#define U_STOP_PIN U_MIN_PIN
#else
#elif U_HOME_TO_MAX
#define U_STOP_PIN U_MAX_PIN
#endif
#else
@@ -781,7 +781,7 @@
#endif
#elif V_HOME_TO_MIN
#define V_STOP_PIN V_MIN_PIN
#else
#elif V_HOME_TO_MAX
#define V_STOP_PIN V_MAX_PIN
#endif
#else
@@ -804,7 +804,7 @@
#endif
#elif W_HOME_TO_MIN
#define W_STOP_PIN W_MIN_PIN
#else
#elif W_HOME_TO_MAX
#define W_STOP_PIN W_MAX_PIN
#endif
#else

View File

@@ -484,15 +484,15 @@
#endif
//
// AUX1 5V GND D2 D1
// AUX1 5V GND D1 D0
// 2 4 6 8
// 1 3 5 7
// 5V GND A3 A4
//
#define AUX1_05 57 // (A3)
#define AUX1_06 2
#define AUX1_06 1 // TX0
#define AUX1_07 58 // (A4)
#define AUX1_08 1
#define AUX1_08 0 // RX0
//
// AUX2 GND A9 D40 D42 A11

View File

@@ -22,7 +22,9 @@
#pragma once
/**
* ReprapWorld's Minitronics v2.0
* ReprapWorld Minitronics v2.0
* https://reprap.org/wiki/Minitronics_20
* 48MHz Atmel SAMD21J18 ARM Cortex-M0+
*/
#if NOT_TARGET(__SAMD21__)
@@ -125,6 +127,11 @@
#endif
// Verify that drivers match the hardware
#if (HAS_X_AXIS && !AXIS_DRIVER_TYPE_X(DRV8825)) || (HAS_Y_AXIS && !AXIS_DRIVER_TYPE_Y(DRV8825)) || (HAS_Z_AXIS && !AXIS_DRIVER_TYPE_Z(DRV8825)) || (HAS_EXTRUDER && !AXIS_DRIVER_TYPE_E0(DRV8825))
#error "Minitronics v2.0 has hard-wired DRV8825 drivers. Comment out this line to continue."
#endif
//
// Extruder / Bed
//

View File

@@ -60,12 +60,15 @@ Every new HAL opens up a world of hardware. At this time we need HALs for RP2040
[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.5](//www.pjrc.com/store/teensy35.html)|ARM® Cortex-M4|
[Teensy 3.6](//www.pjrc.com/store/teensy36.html)|ARM® Cortex-M4|
[Teensy 4.0](//www.pjrc.com/store/teensy40.html)|ARM® Cortex-M7|
[Teensy 4.1](//www.pjrc.com/store/teensy41.html)|ARM® Cortex-M7|
Linux Native|x86/ARM/etc.|Raspberry Pi
[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

View File

@@ -2,21 +2,22 @@
#
# Usage:
#
# build_all_examples [-b|--branch=<branch>] - Branch to fetch from Configurations repo (import-2.1.x)
# build_all_examples [-a|--archive] - Copy the binary to the export location
# [-B|--base] - Base path of configurations, overriding -b
# [-b|--branch=<branch>] - Branch to fetch from Configurations repo (import-2.1.x)
# [-c|--continue] - Continue the paused build
# [-p|--purge] - Purge the status file and start over
# [-s|--skip] - Continue the paused build, skipping one
# [-r|--resume=<path>] - Start at some config in the filesystem order
# [-l|--limit=#] - Limit the number of builds in this run
# [-d|--debug] - Print extra debug output (after)
# [-n|--nobuild] - Don't actually build anything
# [-d|-v|--debug] - Print extra debug output (after)
# [-e|--export=N] - Set CONFIG_EXPORT and export to the export location
# [-f|--nofail] - Don't stop on a failed build
# [-e|--export=N] - Set CONFIG_EXPORT and export into each config folder
# [-a|--archive] - Copy the binary to the export location
# [-h|--help] - Print usage and exit
# [-l|--limit=#] - Limit the number of builds in this run
# [-m|--many] - Build all the environments for each example
# [-n|--nobuild] - Don't actually build anything
# [-o|--output] - Redirect export / archiving to another location
# (By default export to origin config folders)
# [-h|--help] - Print usage and exit
# [-p|--purge] - Purge the status file and start over
# [-r|--resume=<path>] - Start at some config in the filesystem order
# [-s|--skip] - Continue the paused build, skipping one
#
HERE=`dirname $0`
@@ -29,21 +30,22 @@ STAT_FILE=./.pio/.buildall
usage() { echo "Usage:
build_all_examples [-b|--branch=<branch>] - Branch to fetch from Configurations repo (import-2.1.x)
build_all_examples [-a|--archive] - Copy the binary to the export location
[-B|--base] - Base path of configurations, overriding -b
[-b|--branch=<branch>] - Branch to fetch from Configurations repo (import-2.1.x)
[-c|--continue] - Continue the paused build
[-p|--purge] - Purge the status file and start over
[-s|--skip] - Continue the paused build, skipping one
[-r|--resume=<path>] - Start at some config in the filesystem order
[-d|-v|--debug] - Print extra debug output (after)
[-e|--export=N] - Set CONFIG_EXPORT and export to the export location
[-a|--archive] - Copy the binary to the export location
[-o|--output] - Redirect export / archiving to another location
(By default export to origin config folders)
[-d|--debug] - Print extra debug output (after)
[-l|--limit=#] - Limit the number of builds in this run
[-n|--nobuild] - Don't actually build anything
[-f|--nofail] - Don't stop on a failed build
[-h|--help] - Print usage and exit
[-l|--limit=#] - Limit the number of builds in this run
[-m|--many] - Build all the environments for each example
[-n|--nobuild] - Don't actually build anything
[-o|--output] - Redirect export / archiving to another location
(By default export to origin config folders)
[-p|--purge] - Purge the status file and start over
[-r|--resume=<path>] - Start at some config in the filesystem order
[-s|--skip] - Continue the paused build, skipping one
"
}
@@ -53,27 +55,29 @@ unset FIRST_CONF
EXIT_USAGE=
LIMIT=1000
while getopts 'aB:b:ce:fdhl:no:pr:sv-:' OFLAG; do
while getopts 'aB:b:cde:fhl:mno:pr:sv-:' OFLAG; do
case "${OFLAG}" in
a) ARCHIVE=1 ; bugout "Archiving" ;;
B) CBASE=${OPTARG%/} ; bugout "Base: $CBASE" ;;
b) BRANCH=$OPTARG ; bugout "Branch: $BRANCH" ;;
f) NOFAIL=1 ; bugout "Continue on Fail" ;;
r) ISRES=1 ; FIRST_CONF=$OPTARG ; bugout "Resume: $FIRST_CONF" ;;
c) CONTINUE=1 ; bugout "Continue" ;;
s) CONTSKIP=1 ; bugout "Continue, skipping" ;;
d|v) DEBUG=1 ; bugout "Debug ON" ;;
e) CEXPORT=$OPTARG ; bugout "Export $CEXPORT" ;;
o) OUTBASE="${OPTARG%/}" ; bugout "Archive to $OUTBASE" ;;
f) NOFAIL=1 ; bugout "Continue on Fail" ;;
h) EXIT_USAGE=1 ; break ;;
l) LIMIT=$OPTARG ; bugout "Limit to $LIMIT build(s)" ;;
d|v) DEBUG=1 ; bugout "Debug ON" ;;
m) MANY=1 ; bugout "Many Envs" ;;
n) DRYRUN=1 ; bugout "Dry Run" ;;
o) OUTBASE="${OPTARG%/}" ; bugout "Archive to $OUTBASE" ;;
p) PURGE=1 ; bugout "Purge stat file" ;;
r) ISRES=1 ; FIRST_CONF=$OPTARG ; bugout "Resume: $FIRST_CONF" ;;
s) CONTSKIP=1 ; bugout "Continue, skipping" ;;
-) ONAM="${OPTARG%%=*}" ; OVAL="${OPTARG#*=}"
case "$ONAM" in
archive) ARCHIVE=1 ; bugout "Archiving" ;;
base) CBASE=${OVAL%/} ; bugout "Base: $CBASE" ;;
branch) BRANCH=$OVAL ; bugout "Branch: $BRANCH" ;;
many) MANY=1 ; bugout "Many Envs" ;;
nofail) NOFAIL=1 ; bugout "Continue on Fail" ;;
resume) ISRES=1 ; FIRST_CONF=$OVAL ; bugout "Resume: $FIRST_CONF" ;;
continue) CONTINUE=1 ; bugout "Continue" ;;
@@ -154,7 +158,9 @@ shopt -s nullglob
export PAUSE=1
# Get a list of all folders that contain a file matching "Configuration*.h"
find -ds "$CBASE"/config/examples -type d -name 'Configuration.h' -o -name 'Configuration_adv.h' -print0 | while IFS= read -r -d $'\0' CONF; do
find "$CBASE"/config/examples -type d -name 'Configuration.h' -o -name 'Configuration_adv.h' -print0 \
| LC_ALL=C sort -fz \
| while IFS= read -r -d $'\0' CONF; do
# Remove the file name and slash from the end of the path
CONF=${CONF%/*}
@@ -179,6 +185,9 @@ find -ds "$CBASE"/config/examples -type d -name 'Configuration.h' -o -name 'Conf
# Exporting? Add -e argument
((CEXPORT)) && CARGS+=("-e" "$CEXPORT")
# Build many environments? Add -m argument
((MANY)) && CARGS+=("-m")
# Continue on fail? Add -f argument
((NOFAIL)) && CARGS+=("-f")

View File

@@ -4,11 +4,14 @@
#
# build_example -b|--base=<path> - Configurations root folder (e.g., ./.pio/build-BRANCH)
# -c|--config=<rel> - Sub-path of the configs to build (within config/examples)
# [-n|--index=N] - Which environment to build, by index (Based on pins.h comments)
# [-m|--many] - Build all the board's environments listed in pins.h
# [-e|--export=N] - Use CONFIG_EXPORT N to export the config to the export location
# [-a|--archive] - Archive the build (to the export location)
# [-o|--output] - Redirect export / archiving to another location
# (By default export to origin config folder)
# [-f|--nofail] - Don't stop on a failed build
# [-x|--noxfer] - Skip the build if the env ends with _xfer. Implied with --many.
# [-w|--nowarn] - Suppress warnings with extra config options
# [-r|--reveal] - Reveal the config/export folder after the build
# [-h|--help] - Print usage and exit
@@ -19,11 +22,14 @@ usage() { echo "Usage:
build_example -b|--base=<path> - Configurations root folder (e.g., ./.pio/build-BRANCH)
-c|--config=<rel> - Sub-path of the configs to build (within config/examples)
[-n|--index=N] - Which environment to build, by index (Based on pins.h comments)
[-m|--many] - Build all the board's environments listed in pins.h
[-e|--export=N] - Use CONFIG_EXPORT N to export the config to the export location
[-a|--archive] - Archive the build (to the export location)
[-o|--output] - Redirect export / archiving to another location
(By default export to origin config folder)
[-f|--nofail] - Don't stop on a failed build
[-x|--noxfer] - Skip the build if the env ends with _xfer. Implied with --many.
[-w|--nowarn] - Suppress warnings with extra config options
[-r|--reveal] - Reveal the config/export folder after the build
[-h|--help] - Print usage and exit
@@ -50,27 +56,37 @@ REVEAL=
EXPNUM=
NOFAIL=
OUTBASE=
while getopts 'ab:c:e:fhio:r-:' OFLAG; do
BUILDINDEX=1
MANY=
NOXFER=
while getopts 'ab:c:e:fhmn:o:r-:x' OFLAG; do
case "${OFLAG}" in
a) ARCHIVE=1 ;;
b) BASE="${OPTARG%/}" ;;
c) CONFIG="${OPTARG%/}" ;;
e) EXPNUM="$OPTARG" ;;
o) OUTBASE="${OPTARG%/}" ;;
h) EXIT_USAGE=1 ; break ;;
f) NOFAIL=1 ;;
h) EXIT_USAGE=1 ; break ;;
m) MANY=1 ; NOXFER=1 ;;
n) BUILDINDEX="$OPTARG" ;;
o) OUTBASE="${OPTARG%/}" ;;
r) REVEAL=1 ;;
x) NOXFER=1 ;;
-) ONAM="${OPTARG%%=*}" ; OVAL="${OPTARG#*=}"
case "$ONAM" in
archive) ARCHIVE=1 ;;
allow) ALLOW=1 ;;
base) BASE="${OVAL%/}" ;;
config) CONFIG="${OVAL%/}" ;;
many) MANY=1 ; NOXFER=1 ;;
index) BUILDINDEX="$OVAL" ;;
export) EXPNUM="$OVAL" ;;
output) OUTBASE="${OVAL%/}" ;;
help) EXIT_USAGE=1 ; break ;;
nofail) NOFAIL=1 ;;
reveal) REVEAL=1 ;;
noxfer) NOXFER=1 ;;
*) EXIT_USAGE=2 ; echo "$SELF: unrecognized option \`--$ONAM'" ; break ;;
esac
;;
@@ -154,11 +170,12 @@ ENAME=("-name" "marlin_config.json" \
"-o" "-name" "schema.yml")
# Possible built firmware names (in the build folder)
BNAME=("-name" 'firmware*.hex' \
BNAME=("-name" "firmware*.hex" \
"-o" "-name" "firmware*.bin" \
"-o" "-name" "project*.bin" \
"-o" "-name" "Robin*.bin" \
"-o" "-name" "main_*.bin")
"-o" "-name" "main_*.bin" \
"-o" "-name" "MarlinSimulator*")
mkdir -p "$BUILD"
@@ -166,64 +183,122 @@ mkdir -p "$BUILD"
if [[ $EXPNUM ]]; then
opt_set CONFIG_EXPORT $EXPNUM
# Clean up old exports
find "$BUILD" \( "${ENAME[@]}" \) -exec rm "{}" \;
find "$BUILD" -type f \( "${ENAME[@]}" \) -exec rm "{}" \;
fi
((ARCHIVE)) && find "$BUILD" \( "${BNAME[@]}" \) -exec rm "{}" \;
((ARCHIVE)) && find "$BUILD" -type f \( "${BNAME[@]}" \) -exec rm "{}" \;
set +e
echo "Building example $CONFIG..."
echo "Building example $CONFIG ..."
mftest -s -a -n1 ; ERR=$?
# If doing many builds get a list of all environment names,
# which also gives us the number of environments.
if ((MANY)); then
ENVLIST=$(mfenvs) # BOARD_NAME_STRING (1234): [ env1 env2 env3 ... ]
ENVLIST=${ENVLIST##*: [ }
ENVARRAY=(${ENVLIST% ]})
ENVCOUNT=${#ENVARRAY[*]}
((ENVCOUNT)) || { alrt "mfenvs failed for this board." ; exit 1 ; }
echo "Found $ENVCOUNT environment(s): ${ENVARRAY[*]}"
fi
((ERR)) && alrt "Failed ($ERR)" || annc "Success"
# Run one or more builds based on --many
# Build all from BUILDINDEX onward (usually 1) meaning ALL.
# MANY with a BUILDINDEX may be useful for continuing an interrupted build.
set -e
while true; do
set +e
if [[ $ERR -gt 0 ]]; then
# Skip over "_xfer" environments when specified
if [[ -n $NOXFER && ${ENVARRAY[BUILDINDEX-1]} =~ _xfer$ ]]; then
echo "Skipping example $CONFIG ($BUILDINDEX)..."
# Error? For --nofail simply log. Otherwise return the error.
if [[ -n $NOFAIL ]]; then
date +"%F %T [FAIL] $CONFIG" >>./.pio/error-log.txt
else
exit $ERR
echo "Building example $CONFIG ($BUILDINDEX)..."
# Run a build and record the error number
mftest -s -a -n$BUILDINDEX ; ERR=$?
# "Index out of range" can fail without an error
((MANY)) && ((ERR == 66)) && ERR=0 && break # "index out of range"
set -e
if [[ $ERR -gt 0 ]]; then
alrt "Failed ($ERR)"
# Error? For --nofail simply log. Otherwise return the error.
if [[ -n $NOFAIL ]]; then
date +"%F %T [FAIL] $CONFIG ($BUILDINDEX)" >>./.pio/error-log.txt
else
exit $ERR
fi
else
annc "Success"
# Copy exports back to the configs
if [[ -n $EXPNUM ]]; then
annc "Exporting $EXPNUM"
[[ -f Marlin/Config-export.h ]] && { cp Marlin/Config-export.h "$ARCSUB"/Config.h ; }
find "$BUILD" -type f \( "${ENAME[@]}" \) -exec cp "{}" "$ARCSUB" \;
fi
# When building many, create sub-folders for each build env name
if [[ -n $MANY ]]; then
ENV=${ENVARRAY[BUILDINDEX-1]}
ARCENVSUB="$ARCSUB/$ENV"
else
ARCENVSUB="$ARCSUB"
fi
# Copy potential firmware files into the config folder
# TODO: Consider firmware that needs an STM32F4_UPDATE folder.
# Currently only BOARD_CREALITY_F401RE env:STM32F401RE_creality
if ((ARCHIVE)); then
annc "Archiving"
find "$BUILD" -type f \( "${BNAME[@]}" \) -exec sh -c '
ARCDIR="$1" ; CONFIG="$2" ; FILE="$3" ; shift 3
NAME=${FILE##*/} ; SHRT=${NAME%.*} ; DIR=${FILE%/*}
ZIPX=
if [[ $CONFIG == *Simulator* ]]; then
case $(uname | tr '[:upper:]' '[:lower:]') in
darwin) SUB="macOS" ; ZIPX="-X" ;;
*linux) SUB="Linux" ;;
win*) SUB="Windows" ;;
msys*) SUB="Windows" ;;
cygwin*) SUB="Windows" ;;
mingw*) SUB="Windows" ;;
*) SUB='Unix' ;;
esac
ARCH=$(uname -m | tr '[:lower:]' '[:upper:]')
ARCDIR="$ARCDIR/$SUB-$ARCH"
fi
mkdir -p "$ARCDIR"
rm -f "$ARCDIR"/*.zip "$ARCDIR"/*.sha256.txt
cd "$DIR"
SHASUM=$(sha256sum "$NAME" | cut -d" " -f1)
echo "$CONFIG\n$SHASUM" > "$ARCDIR/$NAME.sha256.txt"
zip $ZIPX "$ARCDIR/$SHRT.zip" "$NAME" && rm "$NAME"
cd - >/dev/null
' sh "$ARCENVSUB" "$CONFIG" {} +
fi # ARCHIVE
# Reveal the configs after the build, if requested
((REVEAL)) && { annc "Revealing $ARCENVSUB" ; open "$ARCENVSUB" ; }
fi # Success
fi
else
((MANY)) || break # Only one build if not --many
# Copy exports back to the configs
if [[ -n $EXPNUM ]]; then
annc "Exporting $EXPNUM"
[[ -f Marlin/Config-export.h ]] && { cp Marlin/Config-export.h "$ARCSUB"/Config.h ; }
find "$BUILD" \( "${ENAME[@]}" \) -exec cp "{}" "$ARCSUB" \;
fi
# Set up for the next build, if there is one
((++BUILDINDEX > ENVCOUNT)) && break
# Copy potential firmware files into the config folder
# TODO: Consider firmware that needs an STM32F4_UPDATE folder.
# Currently only BOARD_CREALITY_F401RE env:STM32F401RE_creality
if ((ARCHIVE)); then
annc "Archiving"
rm -f "$ARCSUB"/*.bin.tar.gz "$ARCSUB"/*.hex.tar.gz
find "$BUILD" \( "${BNAME[@]}" \) -exec sh -c '
ARCSUB="$1"
CONFIG="$2"
shift 2
for FILE in "$@"; do
cd "${FILE%/*}"
NAME=${FILE##*/}
SHRT=${NAME%.*}
SHASUM=$(sha256sum "$NAME" | cut -d" " -f1)
tar -czf "$ARCSUB/$SHRT.tar.gz" "$NAME"
echo "$CONFIG\n$SHASUM" > "$ARCSUB/$NAME.sha256.txt"
rm "$NAME"
cd - >/dev/null
done
' sh "$ARCSUB" "$CONFIG" {} +
fi
# Reveal the configs after the build, if requested
((REVEAL)) && { annc "Revealing $ARCSUB" ; open "$ARCSUB" ; }
fi
done
exit 0

35
buildroot/bin/mfenvs Executable file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
#
# mfenvs Print the current board and environment information
# Use -n to remove "*_xfer" environments from the list.
# Output -> "SHORT_NAME (###): [ env1 env2 env3 ... ]"
#
[[ -d Marlin/src ]] || { echo "Please 'cd' to the Marlin repo root." ; exit 1 ; }
which pio >/dev/null || { echo "Make sure 'pio' is in your execution PATH." ; exit 1 ; }
errout() { echo -e "\033[0;31m$1\033[0m" ; }
case $(uname | tr '[:upper:]' '[:lower:]') in
darwin) SYS='mac' ;;
*linux) SYS='lin' ;;
win*) SYS='win' ;;
msys*) SYS='win' ;;
cygwin*) SYS='win' ;;
mingw*) SYS='win' ;;
*) SYS='uni' ;;
esac
ACODE='/^[[:space:]]*#define[[:space:]]MOTHERBOARD[[:space:]]/ { sub(/^BOARD_/, "", $3); print $3 }'
MB=$(awk "$ACODE" Marlin/Configuration.h 2>/dev/null)
[[ -z $MB ]] && MB=$(awk "$ACODE" Marlin/Config.h 2>/dev/null)
[[ -z $MB ]] && { echo "Error - Can't read MOTHERBOARD setting." ; exit 1 ; }
BLINE=$( grep -E "define\s+BOARD_$MB\b" Marlin/src/core/boards.h )
BNUM=$( sed -E 's/^.+BOARD_[^ ]+ +([0-9]+).+$/\1/' <<<"$BLINE" )
[[ -z $BNUM ]] && { echo "Error - Can't find BOARD_$MB in core/boards.h." ; exit 1 ; }
ENVS=( $( grep -EA1 "MB\(.*\b$MB\b.*\)" Marlin/src/pins/pins.h | grep -E "#include.+//.+(env|$SYS):[^ ]+" | grep -oE "(env|$SYS):[^ ]+" | sed -E "s/(env|$SYS)://" ) )
[[ "$1" = "-n" ]] && ENVS=( $(printf "%s\n" "${ENVS[@]}" | grep -v "_xfer$") )
[[ -z $ENVS ]] && { errout "Error - Can't find target(s) for $MB ($BNUM)." ; exit 1 ; }
ECOUNT=${#ENVS[*]}
[[ $ECOUNT == 1 ]] && EOUT=$ENVS || EOUT="${ENVS[@]}"
echo "$MB ($BNUM): [ $EOUT ]"

View File

@@ -16,23 +16,24 @@ bugout() { ((DEBUG)) && echo -e "\033[0;32m$1\033[0m" ; }
usage() {
echo "
Usage: mftest [-t|--env=<env|index>] [-n|--num=<num>] [-m|--make] [-y|--build=<Y|n>]
mftest [-a|--autobuild]
Usage: mftest [-a|--autobuild]
mftest [-r|--rebuild]
mftest [-s|--silent]
mftest [-t|--env=<env|index>] [-n|--num=<num>] [-m|--make] [-y|--build=<Y|n>]
mftest [-u|--autoupload] [-n|--num=<num>]
OPTIONS
-t --env The environment to apply / run, or the menu index number.
-n --num The index of the test to run. (In file order.)
-m --make Use the make / Docker method for the build.
-y --build Skip 'Do you want to build this test?' and assume YES.
-h --help Print this help.
-a --autobuild PIO Build using the MOTHERBOARD environment.
-d --default Restore to defaults before applying configs.
-h --help Print this help.
-m --make Use the make / Docker method for the build.
-n --num The index of the test to run. (In file order.)
-r --rebuild Rebuild previous PIO Build.
-s --silent Silence build output from PlatformIO.
-t --env The environment to apply / run, or the menu index number.
-u --autoupload PIO Upload using the MOTHERBOARD environment.
-v --verbose Extra output for debugging.
-s --silent Silence build output from PlatformIO.
-d --default Restore to defaults before applying configs.
-y --build Skip 'Do you want to build this test?' and assume YES.
env shortcuts: tree due esp lin lp8|lpc8 lp9|lpc9 m128 m256|mega stm|f1 f4 f7 s6 teensy|t31|t32 t35|t36 t40|t41
"
@@ -56,7 +57,7 @@ TESTENV='-'
CHOICE=0
DEBUG=0
while getopts 'abdhmrsuvyn:t:-:' OFLAG; do
while getopts 'adhmn:rst:uvy-:' OFLAG; do
case "${OFLAG}" in
a) AUTO_BUILD=1 ; bugout "Auto-Build target..." ;;
d) DL_DEFAULTS=1 ; bugout "Restore to defaults..." ;;
@@ -195,7 +196,7 @@ if ((AUTO_BUILD)); then
fi
else
echo "Detected \"$BDESC\" | $MB ($BNUM)."
[[ $CHOICE > $ECOUNT ]] && { echo "Environment selection out of range." ; exit 1 ; }
[[ $CHOICE > $ECOUNT ]] && { echo "Environment selection out of range." ; exit 66 ; }
fi
TARGET="${ENVS[$CHOICE-1]}"
if [[ $MB == 'SIMULATED' && $TARGET == 'linux_native' ]]; then

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python
import sys, os,config
import sys, os, config
def main():
args = sys.argv[1:]

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python
import sys, os,config
import sys, os, config
def main():
args = sys.argv[1:]

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/usr/bin/env python
#
# use_example_configs [repo:]configpath
#
@@ -14,40 +14,127 @@
# The fallback branch is bugfix-2.1.x.
#
which curl >/dev/null && TOOL='curl -L -s -S -f -o wgot'
which wget >/dev/null && TOOL='wget -q -O wgot'
import os, subprocess, sys, urllib.request, urllib.error
from pathlib import Path
CURR=$(git branch 2>/dev/null | grep ^* | sed 's/\* //g')
case "$CURR" in
bugfix-2.*.x ) BRANCH=$CURR ;;
*-2.1.x|2.1.x ) BRANCH=latest-2.1.x ;;
*-2.0.x|2.0.x ) BRANCH=latest-2.0.x ;;
*-1.1.x|1.1.x ) BRANCH=latest-1.1.x ;;
*-1.0.x|1.0.x ) BRANCH=latest-1.0.x ;;
* ) BRANCH=bugfix-2.1.x ;;
esac
DEBUGGING = False
CONFIG_FILES = ("Configuration.h", "Configuration_adv.h", "_Bootscreen.h", "_Statusscreen.h")
if [[ $# > 0 ]]; then
IFS=: read -r PART1 PART2 <<< "$@"
[[ -n $PART2 ]] && { UDIR="$PART2" ; BRANCH="$PART1" ; } \
|| { UDIR="$PART1" ; }
RDIR="${UDIR// /%20}"
echo "Fetching $UDIR configurations from $BRANCH..."
EXAMPLES="examples/$RDIR"
else
EXAMPLES="default"
fi
def debug_print(s):
if DEBUGGING: print(s)
CONFIGS="https://raw.githubusercontent.com/MarlinFirmware/Configurations/$BRANCH/config/${EXAMPLES}"
def get_current_branch():
try:
result = subprocess.run(['git', 'branch'], capture_output=True, text=True, check=True)
for line in result.stdout.splitlines():
if line.startswith('*'):
return line[2:]
except subprocess.CalledProcessError:
return None
restore_configs
def sparse_checkout(branch, config_path, repo_url="https://github.com/MarlinFirmware/Configurations.git"):
configs_dir = Path("ConfigurationsRepo")
config_subdir = f"config/{config_path}"
cd Marlin
if not configs_dir.exists():
# Step 1: Clone with no checkout
subprocess.run([
"git", "clone", "--depth", "1", "--filter=blob:none", "--sparse",
"--branch", branch, repo_url, str(configs_dir)
], check=True)
$TOOL "$CONFIGS/Configuration.h" >/dev/null 2>&1 && mv wgot Configuration.h
$TOOL "$CONFIGS/Configuration_adv.h" >/dev/null 2>&1 && mv wgot Configuration_adv.h
$TOOL "$CONFIGS/_Bootscreen.h" >/dev/null 2>&1 && mv wgot _Bootscreen.h
$TOOL "$CONFIGS/_Statusscreen.h" >/dev/null 2>&1 && mv wgot _Statusscreen.h
# Step 2: Enable sparse checkout and set the folder
subprocess.run(["git", "sparse-checkout", "set", config_subdir], cwd=str(configs_dir), check=True)
# Step 3: Pull the latest for that branch/folder
subprocess.run(["git", "pull"], cwd=str(configs_dir), check=True)
rm -f wgot
cd - >/dev/null
def copy_config_files(branch, config_path, dest_dir):
sparse_checkout(branch, config_path)
src_dir = Path("ConfigurationsRepo") / "config" / config_path
for fname in CONFIG_FILES:
src_file = src_dir / fname
if src_file.exists():
dest_file = dest_dir / fname
debug_print(f"Copying {src_file} to {dest_file}")
dest_file.write_bytes(src_file.read_bytes())
else:
debug_print(f"{fname} not found in {src_dir}")
def fetch_config_files(branch, config_path, dest_dir):
config_path_url = config_path.replace(' ', '%20')
base_url = f"https://raw.githubusercontent.com/MarlinFirmware/Configurations/{branch}/config/{config_path_url}"
for file in CONFIG_FILES:
url = f"{base_url}/{file}"
dest_file = dest_dir / file
if os.getenv('DEBUG', '0') == '1':
debug_print(f"Fetching {file} from {url} to {dest_file}")
try:
urllib.request.urlretrieve(url, dest_file)
except urllib.error.HTTPError as e:
if e.code == 404:
if os.getenv('DEBUG', '0') == '1':
print(f"File {file} not found (404), skipping.")
else:
raise
def fetch_configs(branch, config_path):
print(f"Fetching {config_path} configurations from {branch}...")
marlin_dir = Path("Marlin")
if not marlin_dir.exists():
print(f"Directory 'Marlin' not found at the current location.")
sys.exit(1)
if os.environ.get('GITHUB_ACTIONS'): # Running on GitHub ?
copy_config_files(branch, config_path, marlin_dir)
else:
fetch_config_files(branch, config_path, marlin_dir)
def main():
branch = get_current_branch()
if not branch:
print("Not a git repository or no branch found.")
sys.exit(1)
if branch.startswith("bugfix-2."):
branch = branch
elif branch.endswith("bugfix-2.1.x"):
branch = "bugfix-2.1.x"
elif branch.endswith("-2.1.x") or branch == "2.1.x":
branch = "latest-2.1.x"
elif branch.endswith("-2.0.x") or branch == "2.0.x":
branch = "latest-2.0.x"
elif branch.endswith("-1.1.x") or branch == "1.1.x":
branch = "latest-1.1.x"
elif branch.endswith("-1.0.x") or branch == "1.0.x":
branch = "latest-1.0.x"
else:
branch = "bugfix-2.1.x"
if len(sys.argv) > 1:
arg = sys.argv[1]
if ':' in arg:
part1, part2 = arg.split(':', 1)
config_path = part2
branch = part1
else:
config_path = arg
config_path = 'examples/'+config_path
else:
config_path = "default"
try:
subprocess.run(['restore_configs'], check=True)
except FileNotFoundError:
try:
subprocess.run(['./buildroot/bin/restore_configs'], check=True)
except FileNotFoundError:
print("restore_configs not found, skipping.")
fetch_configs(branch, config_path)
if __name__ == "__main__":
main()

View File

@@ -4,15 +4,15 @@
#
import pioutil
if pioutil.is_pio_build():
import struct,uuid,marlin
import struct, uuid, marlin
board = marlin.env.BoardConfig()
board = pioutil.env.BoardConfig()
def calculate_crc(contents, seed):
accumulating_xor_value = seed
for i in range(0, len(contents), 4):
value = struct.unpack('<I', contents[ i : i + 4])[0]
value = struct.unpack("<I", contents[i : i + 4])[0]
accumulating_xor_value = accumulating_xor_value ^ value
return accumulating_xor_value
@@ -29,12 +29,12 @@ if pioutil.is_pio_build():
# This is the block counter
block_number = xor_seed * block_number
#load the xor key from the file
r7 = file_key
# load the xor key from the file
r7 = file_key
for loop_counter in range(0, block_size):
# meant to make sure different bits of the key are used.
xor_seed = int(loop_counter / key_length)
xor_seed = loop_counter // key_length
# IP is a scratch register / R12
ip = loop_counter - (key_length * xor_seed)
@@ -54,10 +54,10 @@ if pioutil.is_pio_build():
# and then with IP
xor_seed = xor_seed ^ ip
#Now store the byte back
# Now store the byte back
r1[loop_counter] = xor_seed & 0xFF
#increment the loop_counter
# increment the loop_counter
loop_counter = loop_counter + 1
def encrypt_file(input, output_file, file_length):
@@ -82,15 +82,15 @@ if pioutil.is_pio_build():
# write the file_key
output_file.write(struct.pack("<I", file_key))
#TODO - how to enforce that the firmware aligns to block boundaries?
block_count = int(len(input_file) / block_size)
print ("Block Count is ", block_count)
# TODO: - how to enforce that the firmware aligns to block boundaries?
block_count = len(input_file) // block_size
print("Block Count is ", block_count)
for block_number in range(0, block_count):
block_offset = (block_number * block_size)
block_offset = block_number * block_size
block_end = block_offset + block_size
block_array = bytearray(input_file[block_offset: block_end])
block_array = bytearray(input_file[block_offset:block_end])
xor_block(block_array, block_array, block_number, block_size, file_key)
for n in range (0, block_size):
for n in range(0, block_size):
input_file[block_offset + n] = block_array[n]
# update the expected CRC value.

View File

@@ -5,17 +5,19 @@
import pioutil
if pioutil.is_pio_build():
Import("env")
env = pioutil.env
cxxflags = [
# "-Wno-incompatible-pointer-types",
# "-Wno-unused-const-variable",
# "-Wno-maybe-uninitialized",
# "-Wno-sign-compare"
# "-Wno-sign-compare",
"-fno-sized-deallocation"
]
if "teensy" not in env["PIOENV"]:
if "teensy" not in env["PIOENV"] and "esp32" not in env["PIOENV"]:
cxxflags += ["-Wno-register"]
env.Append(CXXFLAGS=cxxflags)
env.Append(CFLAGS=["-Wno-implicit-function-declaration"])
#
# Add CPU frequency as a compile time constant instead of a runtime variable
@@ -27,8 +29,8 @@ if pioutil.is_pio_build():
# Useful for JTAG debugging
#
# It will separate release and debug build folders.
# It useful to keep two live versions: a debug version for debugging and another for
# release, for flashing when upload is not done automatically by jlink/stlink.
# This is useful to keep two live versions: a debug version and a release version,
# for flashing when upload is not done automatically by jlink/stlink.
# Without this, PIO needs to recompile everything twice for any small change.
if env.GetBuildType() == "debug" and env.get("UPLOAD_PROTOCOL") not in ["jlink", "stlink", "custom"]:
env["BUILD_DIR"] = "$PROJECT_BUILD_DIR/$PIOENV/debug"

View File

@@ -2,10 +2,11 @@
# pioutil.py
#
from SCons.Script import DefaultEnvironment
env = DefaultEnvironment()
# Make sure 'vscode init' is not the current command
def is_pio_build():
from SCons.Script import DefaultEnvironment
env = DefaultEnvironment()
if "IsCleanTarget" in dir(env) and env.IsCleanTarget(): return False
return not env.IsIntegrationDump()

View File

@@ -86,6 +86,16 @@ if pioutil.is_pio_build():
err = "ERROR: Config files found in directory %s. Please move them into the Marlin subfolder." % p
raise SystemExit(err)
#
# Check for DGUS_UI_IS in Configuration.h
#
config_path = epath / "Marlin" / "Configuration.h"
if config_path.is_file():
with config_path.open() as f:
if "DGUS_UI_IS" in f.read():
err = "ERROR: Future Configurations (2.1.3 and up) are not supported for Marlin 2.1.2."
raise SystemExit(err)
#
# Find the name.cpp.o or name.o and remove it
#

View File

@@ -1,17 +1,35 @@
#!/usr/bin/env python3
#
# schema.py
#
# Used by signature.py via common-dependencies.py to generate a schema file during the PlatformIO build
# when CONFIG_EXPORT is defined in the configuration.
#
# This script can also be run standalone from within the Marlin repo to generate JSON and YAML schema files.
#
# This script is a companion to abm/js/schema.js in the MarlinFirmware/AutoBuildMarlin project, which has
# been extended to evaluate conditions and can determine what options are actually enabled, not just which
# options are uncommented. That will be migrated to this script for standalone migration.
#
import re,json
"""
schema.py
Extract firmware configuration into structured JSON or YAML schema format.
Used by signature.py via common-dependencies.py to generate a schema file during the
PlatformIO build when CONFIG_EXPORT is defined in the configuration.
This script can also be run standalone from within the Marlin repo, and is a companion to
abm/js/schema.js in the MarlinFirmware/AutoBuildMarlin project, which has been extended to
evaluate conditions and can determine what options are actually enabled, not just which
options are uncommented. That will be migrated to this script for standalone migration.
Usage: schema.py [-h] [some|json|jsons|group|yml|yaml]
Process Marlin firmware configuration files (Configuration.h and Configuration_adv.h)
to produce structured output suitable for documentation, tooling, or automated processing.
Positional arguments:
some Generate both JSON and YAML output (schema.json and schema.yml)
json Generate JSON output (schema.json)
jsons Generate grouped JSON output with wildcard options (schema.json and schema_grouped.json)
group Generate grouped JSON output only (schema_grouped.json)
yml Generate YAML output (schema.yml)
yaml Same as 'yml'
Optional arguments:
-h, --help Show this help message and exit
"""
import re, json
from pathlib import Path
def extend_dict(d:dict, k:tuple):
@@ -43,8 +61,7 @@ def find_grouping(gdict, filekey, sectkey, optkey, pindex):
optparts[pindex] = '*'
wildkey = '_'.join(optparts)
kkey = f'{filekey}|{sectkey}|{wildkey}'
if kkey not in gdict: gdict[kkey] = []
gdict[kkey].append((subkey, modkey))
gdict.setdefault(kkey, []).append((subkey, modkey))
# Build a list of potential groups. Only those with multiple items will be grouped.
def group_options(schema):
@@ -70,7 +87,7 @@ def group_options(schema):
def load_boards():
bpath = Path("Marlin/src/core/boards.h")
if bpath.is_file():
with bpath.open() as bfile:
with bpath.open(encoding='utf-8') as bfile:
boards = []
for line in bfile:
if line.startswith("#define BOARD_"):
@@ -80,7 +97,7 @@ def load_boards():
return ''
#
# Extract the current configuration files in the form of a structured schema.
# Extract the specified configuration files in the form of a structured schema.
# Contains the full schema for the configuration files, not just the enabled options,
# Contains the current values of the options, not just data structure, so "schema" is a slight misnomer.
#
@@ -99,9 +116,9 @@ def load_boards():
# - requires = The conditions that must be met for the define to be enabled
# - comment = The comment for the define, if it has one
# - units = The units for the define, if it has one
# - options = The options for the define, if it has one
# - options = The options for the define, if it has any
#
def extract():
def extract_files(filekey):
# Load board names from boards.h
boards = load_boards()
@@ -114,23 +131,21 @@ def extract():
GET_SENSORS = 4 # Gathering temperature sensor options
ERROR = 9 # Syntax error
# List of files to process, with shorthand
filekey = { 'Configuration.h':'basic', 'Configuration_adv.h':'advanced' }
# A JSON object to store the data
sch_out = { 'basic':{}, 'advanced':{} }
sch_out = { key:{} for key in filekey.values() }
# Regex for #define NAME [VALUE] [COMMENT] with sanitized line
defgrep = re.compile(r'^(//)?\s*(#define)\s+([A-Za-z0-9_]+)\s*(.*?)\s*(//.+)?$')
# Pattern to match a float value
flt = r'[-+]?\s*(\d+\.|\d*\.\d+)([eE][-+]?\d+)?[fF]?'
# Defines to ignore
ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_EXAMPLES_DIR', 'CONFIG_EXPORT')
flt = r'[-+]?\s*(?:\d+\.|\d*\.\d+)(?:[eE][-+]?\d+)?[fF]?'
# Pattern to match an integer expression
int_expr = r'(?:[-+]?\s*\d+(?:\s*[*\/+\-]\s*\d+)*)'
# Start with unknown state
state = Parse.NORMAL
# Serial ID
sid = 0
# Loop through files and parse them line by line
for fn, fk in filekey.items():
with Path("Marlin", fn).open() as fileobj:
with Path("Marlin", fn).open(encoding='utf-8') as fileobj:
section = 'none' # Current Settings section
line_number = 0 # Counter for the line number of the file
conditions = [] # Create a condition stack for the current file
@@ -140,7 +155,7 @@ def extract():
eol_options = False # The options came from end of line, so only apply once
join_line = False # A flag that the line should be joined with the previous one
line = '' # A line buffer to handle \ continuation
last_added_ref = None # Reference to the last added item
last_added_ref = {} # Reference to the last added item
# Loop through the lines in the file
for the_line in fileobj.readlines():
line_number += 1
@@ -180,26 +195,42 @@ def extract():
cfield = 'notes' if 'comment' in last_added_ref else 'comment'
last_added_ref[cfield] = cline
#
# Add the given comment line to the comment buffer, unless:
# - The line starts with ':' and JSON values to assign to 'opt'.
# - The line starts with '@section' so a new section needs to be returned.
# - The line starts with '======' so just skip it.
#
def use_comment(c, opt, sec, bufref):
if c.startswith(':'): # If the comment starts with : then it has magic JSON
d = c[1:].strip() # Strip the leading :
cbr = c.rindex('}') if d.startswith('{') else c.rindex(']') if d.startswith('[') else 0
'''
c - The comment line to parse
opt - Options JSON string to return (if not updated)
sec - Section to return (if not updated)
bufref - The comment buffer to add to
'''
sc = c.strip() # Strip for special patterns
if sc.startswith(':'): # If the comment starts with : then it has magic JSON
d = sc[1:].strip() # Strip the leading : and spaces
# Look for a JSON container
cbr = sc.rindex('}') if d.startswith('{') else sc.rindex(']') if d.startswith('[') else 0
if cbr:
opt, cmt = c[1:cbr+1].strip(), c[cbr+1:].strip()
opt, cmt = sc[1:cbr+1].strip(), sc[cbr+1:].strip()
if cmt != '': bufref.append(cmt)
else:
opt = c[1:].strip()
elif c.startswith('@section'): # Start a new section
sec = c[8:].strip()
elif not c.startswith('========'):
bufref.append(c)
opt = sc[1:].strip() # Some literal value not in a JSON container?
else:
m = re.match(r'@section\s*(.+)', sc) # Start a new section?
if m:
sec = m[1]
elif not sc.startswith('========'):
bufref.append(c) # Anything else is part of the comment
return opt, sec
# For slash comments, capture consecutive slash comments.
# The comment will be applied to the next #define.
if state == Parse.SLASH_COMMENT:
if not defmatch and the_line.startswith('//'):
use_comment(the_line[2:].strip(), options_json, section, comment_buff)
options_json, section = use_comment(the_line[2:].strip(), options_json, section, comment_buff)
continue
else:
state = Parse.NORMAL
@@ -216,17 +247,16 @@ def extract():
# Temperature sensors are done
if state == Parse.GET_SENSORS:
options_json = f'[ {options_json[:-2]} ]'
state = Parse.NORMAL
# Strip the leading '*' from block comments
# Strip the leading '* ' from block comments
cline = re.sub(r'^\* ?', '', cline)
# Collect temperature sensors
if state == Parse.GET_SENSORS:
sens = re.match(r'^(-?\d+)\s*:\s*(.+)$', cline)
sens = re.match(r'^\s*(-?\d+)\s*:\s*(.+)$', cline)
if sens:
s2 = sens[2].replace("'","''")
s2 = sens[2].replace("'", "''")
options_json += f"{sens[1]}:'{sens[1]} - {s2}', "
elif state == Parse.BLOCK_COMMENT:
@@ -251,12 +281,11 @@ def extract():
comment_buff = []
state = Parse.BLOCK_COMMENT
eol_options = False
elif cpos2 != -1 and (cpos2 < cpos1 or cpos1 == -1):
cpos = cpos2
# Comment after a define may be continued on the following lines
if defmatch != None and cpos > 10:
if defmatch is not None and cpos > 10:
state = Parse.EOL_COMMENT
prev_comment = '\n'.join(comment_buff)
comment_buff = []
@@ -286,9 +315,11 @@ def extract():
# Parenthesize the given expression if needed
def atomize(s):
if s == '' \
or re.match(r'^[A-Za-z0-9_]*(\([^)]+\))?$', s) \
or re.match(r'^[A-Za-z0-9_]+ == \d+?$', s):
s = s.strip()
if not s or s.isidentifier() or (s.startswith('(') and s.endswith(')')):
return s
if re.match(r'^[A-Za-z0-9_]*(\([^)]+\))$', s) \
or re.match(r'^[A-Za-z0-9_]+\s*[=!<>]=?\s*.*$', s):
return s
return f'({s})'
@@ -323,10 +354,10 @@ def extract():
conditions.append([ f'!defined({line[7:].strip()})' ])
# Handle a complete #define line
elif defmatch != None:
elif defmatch is not None:
# Get the match groups into vars
enabled, define_name, val = defmatch[1] == None, defmatch[3], defmatch[4]
enabled, define_name, val = defmatch[1] is None, defmatch[3], defmatch[4]
# Increment the serial ID
sid += 1
@@ -341,27 +372,30 @@ def extract():
}
# Type is based on the value
value_type = \
'switch' if val == '' \
else 'bool' if re.match(r'^(true|false)$', val) \
else 'int' if re.match(r'^[-+]?\s*\d+$', val) \
else 'ints' if re.match(r'^([-+]?\s*\d+)(\s*,\s*[-+]?\s*\d+)+$', val) \
else 'floats' if re.match(rf'({flt}(\s*,\s*{flt})+)', val) \
else 'float' if re.match(f'^({flt})$', val) \
else 'string' if val[0] == '"' \
else 'char' if val[0] == "'" \
else 'state' if re.match(r'^(LOW|HIGH)$', val) \
else 'enum' if re.match(r'^[A-Za-z0-9_]{3,}$', val) \
else 'int[]' if re.match(r'^{\s*[-+]?\s*\d+(\s*,\s*[-+]?\s*\d+)*\s*}$', val) \
else 'float[]' if re.match(r'^{{\s*{flt}(\s*,\s*{flt})*\s*}}$', val) \
else 'array' if val[0] == '{' \
else ''
value_type = (
'switch' if val == ''
else 'int' if re.match(r'^[-+]?\s*\d+$', val)
else 'ints' if re.match(r'^[-+]?\s*\d+(?:\s*,\s*[-+]?\s*\d+)+$', val)
else 'floats' if re.match(rf"^{flt}(?:\s*,\s*{flt})+$", val)
else 'float' if re.match(rf"^{flt}$", val)
else 'string' if val.startswith('"')
else 'char' if val.startswith("'")
else 'bool' if val in ('true', 'false')
else 'state' if val in ('HIGH', 'LOW')
else 'int[]' if re.match(rf"^\{{\s*{int_expr}(?:\s*,\s*{int_expr})*\s*\}}$", val)
else 'float[]' if re.match(rf"^\{{\s*{flt}(?:\s*,\s*{flt})*\s*\}}$", val)
else 'array' if val.startswith('{')
else 'enum' if re.match(r'^[A-Za-z0-9_]{3,}$', val)
else ''
)
val = (val == 'true') if value_type == 'bool' \
else int(val) if value_type == 'int' \
else val.replace('f','') if value_type == 'floats' \
else float(val.replace('f','')) if value_type == 'float' \
else val
val = (
(val == 'true') if value_type == 'bool'
else int(val) if value_type == 'int'
else val.replace('f','') if value_type == 'floats'
else float(val.replace('f','')) if value_type == 'float'
else val
)
if val != '': define_info['value'] = val
if value_type != '': define_info['type'] = value_type
@@ -371,7 +405,7 @@ def extract():
# If the comment_buff is not empty, add the comment to the info
if comment_buff:
full_comment = '\n'.join(comment_buff)
full_comment = '\n'.join(comment_buff).strip()
# An EOL comment will be added later
# The handling could go here instead of above
@@ -385,9 +419,17 @@ def extract():
units = re.match(r'^\(([^)]+)\)', full_comment)
if units:
units = units[1]
if units == 's' or units == 'sec': units = 'seconds'
if units in ('s', 'sec'): units = 'seconds'
define_info['units'] = units
if 'comment' not in define_info or define_info['comment'] == '':
if prev_comment:
define_info['comment'] = prev_comment
prev_comment = ''
if 'comment' in define_info and define_info['comment'] == '':
del define_info['comment']
# Set the options for the current #define
if define_name == "MOTHERBOARD" and boards != '':
define_info['options'] = boards
@@ -412,13 +454,31 @@ def extract():
return sch_out
#
# Extract the current configuration files in the form of a structured schema.
#
def extract():
# List of files to process, with shorthand
return extract_files({ 'Configuration.h':'basic', 'Configuration_adv.h':'advanced' })
def dump_json(schema:dict, jpath:Path):
with jpath.open('w') as jfile:
with jpath.open('w', encoding='utf-8') as jfile:
json.dump(schema, jfile, ensure_ascii=False, indent=2)
def dump_yaml(schema:dict, ypath:Path):
import yaml
with ypath.open('w') as yfile:
# Custom representer for all multi-line strings
def str_literal_representer(dumper, data):
if '\n' in data: # Check for multi-line strings
# Add a newline to trigger '|+'
if not data.endswith('\n'): data += '\n'
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
return dumper.represent_scalar('tag:yaml.org,2002:str', data)
yaml.add_representer(str, str_literal_representer)
with ypath.open('w', encoding='utf-8') as yfile:
yaml.dump(schema, yfile, default_flow_style=False, width=120, indent=2)
def main():
@@ -439,12 +499,17 @@ def main():
def inargs(c): return len(set(args) & set(c)) > 0
# Help / Unknown option
unk = not inargs(['some','json','jsons','group','yml','yaml'])
unk = not inargs(['some','json','jsons','group','yml','yaml', '-h', '--help'])
if (unk): print(f"Unknown option: '{args[0]}'")
if inargs(['-h', '--help']) or unk:
print("Usage: schema.py [some|json|jsons|group|yml|yaml]...")
print(" some = json + yml")
print(" jsons = json + group")
print("Extract firmware configuration into structured JSON or YAML schema format.")
print("Usage: schema.py [-h] [some|json|jsons|group|yml|yaml]")
print(" some Generate both JSON and YAML output (schema.json and schema.yml)")
print(" json Generate JSON output (schema.json)")
print(" jsons Generate grouped JSON output with wildcard options (schema.json and schema_grouped.json)")
print(" group Generate grouped JSON output only (schema_grouped.json)")
print(" yml Generate YAML output (schema.yml)")
print(" yaml Same as 'yml'")
return
# JSON schema

View File

@@ -2,11 +2,10 @@
#
# signature.py
#
import schema
import subprocess,re,json,hashlib
import schema, subprocess, re, json, hashlib
from datetime import datetime
from pathlib import Path
from functools import reduce
def enabled_defines(filepath):
'''
@@ -35,18 +34,29 @@ def enabled_defines(filepath):
'''
outdict = {}
section = "user"
spatt = re.compile(r".*@section +([-a-zA-Z0-9_\s]+)$") # must match @section ...
spatt = re.compile(r".*@section +([-a-zA-Z0-9_\s]+)$") # @section ...
if not Path(filepath).is_file(): return outdict
f = open(filepath, encoding="utf8").read().split("\n")
# Get the full contents of the file and remove all block comments.
# This will avoid false positives from #defines in comments
f = re.sub(r'/\*.*?\*/', '', '\n'.join(f), flags=re.DOTALL).split("\n")
incomment = False
for line in f:
sline = line.strip()
m = re.match(spatt, sline) # @section ...
if m: section = m.group(1).strip() ; continue
if incomment:
if '*/' in sline:
incomment = False
continue
else:
mpos, spos = sline.find('/*'), sline.find('//')
if mpos >= 0 and (spos < 0 or spos > mpos):
incomment = True
continue
if sline[:7] == "#define":
# Extract the key here (we don't care about the value)
kv = sline[8:].strip().split()
@@ -56,9 +66,10 @@ def enabled_defines(filepath):
# Compute the SHA256 hash of a file
def get_file_sha256sum(filepath):
sha256_hash = hashlib.sha256()
with open(filepath,"rb") as f:
if not Path(filepath).is_file(): return ""
with open(filepath, "rb") as f:
# Read and update hash string value in blocks of 4K
for byte_block in iter(lambda: f.read(4096),b""):
for byte_block in iter(lambda: f.read(4096), b""):
sha256_hash.update(byte_block)
return sha256_hash.hexdigest()
@@ -67,9 +78,14 @@ def get_file_sha256sum(filepath):
#
import zipfile
def compress_file(filepath, storedname, outpath):
with zipfile.ZipFile(outpath, 'w', compression=zipfile.ZIP_BZIP2, compresslevel=9) as zipf:
zipf.write(filepath, arcname=storedname, compress_type=zipfile.ZIP_BZIP2, compresslevel=9)
with zipfile.ZipFile(outpath, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False, compresslevel=9) as zipf:
zipf.write(filepath, arcname=storedname)
ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_EXAMPLES_DIR', 'CONFIG_EXPORT')
#
# Compute a build signature and/or export the configuration
#
def compute_build_signature(env):
'''
Compute the build signature by extracting all configuration settings and
@@ -81,11 +97,17 @@ def compute_build_signature(env):
env.Append(BUILD_SIGNATURE=1)
build_path = Path(env['PROJECT_BUILD_DIR'], env['PIOENV'])
marlin_json = build_path / 'marlin_config.json'
json_name = 'marlin_config.json'
marlin_json = build_path / json_name
marlin_zip = build_path / 'mc.zip'
# ANSI colors
green = "\u001b[32m"
yellow = "\u001b[33m"
red = "\u001b[31m"
# Definitions from these files will be kept
header_paths = [ 'Marlin/Configuration.h', 'Marlin/Configuration_adv.h' ]
header_paths = ('Marlin/Configuration.h', 'Marlin/Configuration_adv.h')
# Check if we can skip processing
hashes = ''
@@ -100,7 +122,7 @@ def compute_build_signature(env):
conf = json.load(infile)
same_hash = conf['__INITIAL_HASH'] == hashes
if same_hash:
compress_file(marlin_json, 'marlin_config.json', marlin_zip)
compress_file(marlin_json, json_name, marlin_zip)
except:
pass
@@ -142,7 +164,8 @@ def compute_build_signature(env):
#
# Continue to gather data for CONFIGURATION_EMBEDDING or CONFIG_EXPORT
#
if not ('CONFIGURATION_EMBEDDING' in build_defines or 'CONFIG_EXPORT' in build_defines):
is_embed = 'CONFIGURATION_EMBEDDING' in build_defines
if not (is_embed or 'CONFIG_EXPORT' in build_defines):
return
# Filter out useless macros from the output
@@ -175,29 +198,60 @@ def compute_build_signature(env):
# Get the CONFIG_EXPORT value and do an extended dump if > 100
# For example, CONFIG_EXPORT 102 will make a 'config.ini' with a [config:] group for each schema @section
config_dump = tryint('CONFIG_EXPORT')
config_dump = 1 if is_embed else tryint('CONFIG_EXPORT')
extended_dump = config_dump > 100
if extended_dump: config_dump -= 100
config_dump %= 100
# Get the schema class for exports that require it
if config_dump in (3, 4) or (extended_dump and config_dump in (2, 5)):
try:
conf_schema = schema.extract()
except Exception as exc:
print(red + "Error: " + str(exc))
conf_schema = None
optorder = ('MOTHERBOARD','SERIAL_PORT','BAUDRATE','USE_WATCHDOG','THERMAL_PROTECTION_HOTENDS','THERMAL_PROTECTION_HYSTERESIS','THERMAL_PROTECTION_PERIOD','BUFSIZE','BLOCK_BUFFER_SIZE','MAX_CMD_SIZE','EXTRUDERS','TEMP_SENSOR_0','TEMP_HYSTERESIS','HEATER_0_MINTEMP','HEATER_0_MAXTEMP','PREHEAT_1_TEMP_HOTEND','BANG_MAX','PIDTEMP','PID_K1','PID_MAX','PID_FUNCTIONAL_RANGE','DEFAULT_KP','DEFAULT_KI','DEFAULT_KD','X_DRIVER_TYPE','Y_DRIVER_TYPE','Z_DRIVER_TYPE','E0_DRIVER_TYPE','X_BED_SIZE','X_MIN_POS','X_MAX_POS','Y_BED_SIZE','Y_MIN_POS','Y_MAX_POS','Z_MIN_POS','Z_MAX_POS','X_HOME_DIR','Y_HOME_DIR','Z_HOME_DIR','X_MIN_ENDSTOP_HIT_STATE','Y_MIN_ENDSTOP_HIT_STATE','Z_MIN_ENDSTOP_HIT_STATE','DEFAULT_AXIS_STEPS_PER_UNIT','AXIS_RELATIVE_MODES','DEFAULT_MAX_FEEDRATE','DEFAULT_MAX_ACCELERATION','HOMING_FEEDRATE_MM_M','HOMING_BUMP_DIVISOR','X_ENABLE_ON','Y_ENABLE_ON','Z_ENABLE_ON','E_ENABLE_ON','INVERT_X_DIR','INVERT_Y_DIR','INVERT_Z_DIR','INVERT_E0_DIR','STEP_STATE_E','STEP_STATE_X','STEP_STATE_Y','STEP_STATE_Z','DISABLE_X','DISABLE_Y','DISABLE_Z','DISABLE_E','PROPORTIONAL_FONT_RATIO','DEFAULT_NOMINAL_FILAMENT_DIA','JUNCTION_DEVIATION_MM','DEFAULT_ACCELERATION','DEFAULT_TRAVEL_ACCELERATION','DEFAULT_RETRACT_ACCELERATION','DEFAULT_MINIMUMFEEDRATE','DEFAULT_MINTRAVELFEEDRATE','MINIMUM_PLANNER_SPEED','MIN_STEPS_PER_SEGMENT','DEFAULT_MINSEGMENTTIME','BED_OVERSHOOT','BUSY_WHILE_HEATING','DEFAULT_EJERK','DEFAULT_KEEPALIVE_INTERVAL','DEFAULT_LEVELING_FADE_HEIGHT','DISABLE_OTHER_EXTRUDERS','DISPLAY_CHARSET_HD44780','EEPROM_BOOT_SILENT','EEPROM_CHITCHAT','ENDSTOPPULLUPS','EXTRUDE_MAXLENGTH','EXTRUDE_MINTEMP','HOST_KEEPALIVE_FEATURE','HOTEND_OVERSHOOT','JD_HANDLE_SMALL_SEGMENTS','LCD_INFO_SCREEN_STYLE','LCD_LANGUAGE','MAX_BED_POWER','MESH_INSET','MIN_SOFTWARE_ENDSTOPS','MAX_SOFTWARE_ENDSTOPS','MIN_SOFTWARE_ENDSTOP_X','MIN_SOFTWARE_ENDSTOP_Y','MIN_SOFTWARE_ENDSTOP_Z','MAX_SOFTWARE_ENDSTOP_X','MAX_SOFTWARE_ENDSTOP_Y','MAX_SOFTWARE_ENDSTOP_Z','PREHEAT_1_FAN_SPEED','PREHEAT_1_LABEL','PREHEAT_1_TEMP_BED','PREVENT_COLD_EXTRUSION','PREVENT_LENGTHY_EXTRUDE','PRINTJOB_TIMER_AUTOSTART','PROBING_MARGIN','SHOW_BOOTSCREEN','SOFT_PWM_SCALE','STRING_CONFIG_H_AUTHOR','TEMP_BED_HYSTERESIS','TEMP_BED_RESIDENCY_TIME','TEMP_BED_WINDOW','TEMP_RESIDENCY_TIME','TEMP_WINDOW','VALIDATE_HOMING_ENDSTOPS','XY_PROBE_FEEDRATE','Z_CLEARANCE_BETWEEN_PROBES','Z_CLEARANCE_DEPLOY_PROBE','Z_CLEARANCE_MULTI_PROBE','ARC_SUPPORT','AUTO_REPORT_TEMPERATURES','AUTOTEMP','AUTOTEMP_OLDWEIGHT','BED_CHECK_INTERVAL','DEFAULT_STEPPER_TIMEOUT_SEC','DEFAULT_VOLUMETRIC_EXTRUDER_LIMIT','DISABLE_IDLE_X','DISABLE_IDLE_Y','DISABLE_IDLE_Z','DISABLE_IDLE_E','E0_AUTO_FAN_PIN','ENCODER_100X_STEPS_PER_SEC','ENCODER_10X_STEPS_PER_SEC','ENCODER_RATE_MULTIPLIER','EXTENDED_CAPABILITIES_REPORT','EXTRUDER_AUTO_FAN_SPEED','EXTRUDER_AUTO_FAN_TEMPERATURE','FANMUX0_PIN','FANMUX1_PIN','FANMUX2_PIN','FASTER_GCODE_PARSER','HOMING_BUMP_MM','MAX_ARC_SEGMENT_MM','MIN_ARC_SEGMENT_MM','MIN_CIRCLE_SEGMENTS','N_ARC_CORRECTION','SERIAL_OVERRUN_PROTECTION','SLOWDOWN','SLOWDOWN_DIVISOR','TEMP_SENSOR_BED','THERMAL_PROTECTION_BED_HYSTERESIS','THERMOCOUPLE_MAX_ERRORS','TX_BUFFER_SIZE','WATCH_BED_TEMP_INCREASE','WATCH_BED_TEMP_PERIOD','WATCH_TEMP_INCREASE','WATCH_TEMP_PERIOD')
def optsort(x, optorder):
return optorder.index(x) if x in optorder else float('inf')
#
# Produce an INI file if CONFIG_EXPORT == 2
# CONFIG_EXPORT 102 = config.ini, 105 = Config.h
# Get sections using the schema class
#
if extended_dump and config_dump in (2, 5):
if not conf_schema: exit(1)
# Start with a preferred @section ordering
preorder = ('test','custom','info','machine','eeprom','stepper drivers','multi stepper','idex','extruder','geometry','homing','kinematics','motion','motion control','endstops','filament runout sensors','probe type','probes','bltouch','leveling','temperature','hotend temp','mpctemp','pid temp','mpc temp','bed temp','chamber temp','fans','tool change','advanced pause','calibrate','calibration','media','lcd','lights','caselight','interface','custom main menu','custom config menu','custom buttons','develop','debug matrix','delta','scara','tpara','polar','polargraph','cnc','nozzle park','nozzle clean','gcode','serial','host','filament width','i2c encoders','i2cbus','joystick','multi-material','nanodlp','network','photo','power','psu control','reporting','safety','security','servos','stats','tmc/config','tmc/hybrid','tmc/serial','tmc/smart','tmc/spi','tmc/stallguard','tmc/status','tmc/stealthchop','tmc/tmc26x','units','volumetrics','extras')
sections = { key:{} for key in preorder }
# Group options by schema @section
for header in real_config:
for name in real_config[header]:
#print(f" name: {name}")
if name in ignore: continue
ddict = real_config[header][name]
#print(f" real_config[{header}][{name}]:", ddict)
sect = ddict['section']
if sect not in sections: sections[sect] = {}
sections[sect][name] = ddict
#
# CONFIG_EXPORT 2 or 102 = config.ini
#
if config_dump == 2:
print("Generating config.ini ...")
print(yellow + "Generating config.ini ...")
ini_fmt = '{0:40} = {1}'
ext_fmt = '{0:40} {1}'
ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_EXAMPLES_DIR', 'CONFIG_EXPORT')
if extended_dump:
# Extended export will dump config options by section
# We'll use Schema class to get the sections
try:
conf_schema = schema.extract()
except Exception as exc:
print("Error: " + str(exc))
exit(1)
if not conf_schema: exit(1)
# Then group options by schema @section
sections = {}
@@ -230,7 +284,7 @@ def compute_build_signature(env):
for line in sec_lines[1:]: sec_list += '\n' + ext_fmt.format('', line)
config_ini = build_path / 'config.ini'
with config_ini.open('w') as outfile:
with config_ini.open('w', encoding='utf-8', newline='') as outfile:
filegrp = { 'Configuration.h':'config:basic', 'Configuration_adv.h':'config:advanced' }
vers = build_defines["CONFIGURATION_H_VERSION"]
dt_string = datetime.now().strftime("%Y-%m-%d at %H:%M:%S")
@@ -293,7 +347,9 @@ f'''#
sani = re.sub(r'[- ]+', '_', skey).lower()
outfile.write(f"\n[config:{sani}]\n")
opts = sections[skey]
for name in sorted(opts):
opts_keys = sorted(opts.keys(), key=lambda x: optsort(x, optorder))
for name in opts_keys:
if name in ignore: continue
val = opts[name]['value']
if val == '': val = 'on'
#print(f" {name} = {val}")
@@ -304,28 +360,76 @@ f'''#
# Standard export just dumps config:basic and config:advanced sections
for header in real_config:
outfile.write(f'\n[{filegrp[header]}]\n')
for name in sorted(real_config[header]):
if name not in ignore:
val = real_config[header][name]['value']
if val == '': val = 'on'
outfile.write(ini_fmt.format(name.lower(), val) + '\n')
opts = real_config[header]
opts_keys = sorted(opts.keys(), key=lambda x: optsort(x, optorder))
for name in opts_keys:
if name in ignore: continue
val = opts[name]['value']
if val == '': val = 'on'
outfile.write(ini_fmt.format(name.lower(), val) + '\n')
#
# CONFIG_EXPORT 3 = schema.json, 4 = schema.yml
# CONFIG_EXPORT 5 or 105 = Config.h
#
if config_dump >= 3:
try:
conf_schema = schema.extract()
except Exception as exc:
print("Error: " + str(exc))
conf_schema = None
if config_dump == 5:
print(yellow + "Generating Config-export.h ...")
config_h = Path('Marlin', 'Config-export.h')
with config_h.open('w') as outfile:
filegrp = { 'Configuration.h':'config:basic', 'Configuration_adv.h':'config:advanced' }
vers = build_defines["CONFIGURATION_H_VERSION"]
dt_string = datetime.utcnow().strftime("%Y-%m-%d at %H:%M:%S")
out_text = f'''/**
* Config.h - Marlin Firmware distilled configuration
* Usage: Place this file in the 'Marlin' folder with the name 'Config.h'.
*
* Exported by Marlin build on {dt_string}.
*/
'''
subs = (('Bltouch','BLTouch'),('hchop','hChop'),('Eeprom','EEPROM'),('Gcode','G-code'),('lguard','lGuard'),('Idex','IDEX'),('Lcd','LCD'),('Mpc','MPC'),('Pid','PID'),('Psu','PSU'),('Scara','SCARA'),('Spi','SPI'),('Tmc','TMC'),('Tpara','TPARA'))
define_fmt = '#define {0:40} {1}'
if extended_dump:
# Loop through the sections
for skey in sections:
#print(f" skey: {skey}")
opts = sections[skey]
headed = False
opts_keys = sorted(opts.keys(), key=lambda x: optsort(x, optorder))
for name in opts_keys:
if name in ignore: continue
val = opts[name]['value']
if not headed:
head = reduce(lambda s, r: s.replace(*r), subs, skey.title())
out_text += f"\n//\n// {head}\n//\n"
headed = True
out_text += define_fmt.format(name, val).strip() + '\n'
else:
# Dump config options in just two sections, by file
for header in real_config:
out_text += f'\n/**\n * Overrides for {header}\n */\n'
opts = real_config[header]
opts_keys = sorted(opts.keys(), key=lambda x: optsort(x, optorder))
for name in opts_keys:
if name in ignore: continue
val = opts[name]['value']
out_text += define_fmt.format(name, val).strip() + '\n'
outfile.write(out_text)
#
# CONFIG_EXPORT 3 = schema.json, 13 = schema_grouped.json, 4 = schema.yml
#
if config_dump in (3, 4, 13):
if conf_schema:
#
# 3 = schema.json
#
if config_dump in (3, 13):
print("Generating schema.json ...")
print(yellow + "Generating schema.json ...")
schema.dump_json(conf_schema, build_path / 'schema.json')
if config_dump == 13:
schema.group_options(conf_schema)
@@ -335,7 +439,7 @@ f'''#
# 4 = schema.yml
#
elif config_dump == 4:
print("Generating schema.yml ...")
print(yellow + "Generating schema.yml ...")
try:
import yaml
except ImportError:
@@ -347,19 +451,20 @@ f'''#
schema.dump_yaml(conf_schema, build_path / 'schema.yml')
#
# Produce a JSON file for CONFIGURATION_EMBEDDING or CONFIG_EXPORT == 1
# Produce a JSON file for CONFIGURATION_EMBEDDING or CONFIG_EXPORT == 1 or 101
# Skip if an identical JSON file was already present.
#
if not same_hash and (config_dump == 1 or 'CONFIGURATION_EMBEDDING' in build_defines):
if not same_hash and config_dump == 1:
with marlin_json.open('w') as outfile:
json_data = {}
if extended_dump:
print("Extended dump ...")
print(yellow + "Extended dump ...")
for header in real_config:
confs = real_config[header]
json_data[header] = {}
for name in confs:
if name in ignore: continue
c = confs[name]
s = c['section']
if s not in json_data[header]: json_data[header][s] = {}
@@ -369,6 +474,7 @@ f'''#
conf = real_config[header]
#print(f"real_config[{header}]", conf)
for name in conf:
if name in ignore: continue
json_data[name] = conf[name]['value']
json_data['__INITIAL_HASH'] = hashes
@@ -389,13 +495,13 @@ f'''#
#
# The rest only applies to CONFIGURATION_EMBEDDING
#
if not 'CONFIGURATION_EMBEDDING' in build_defines:
if not is_embed:
(build_path / 'mc.zip').unlink(missing_ok=True)
return
# Compress the JSON file as much as we can
if not same_hash:
compress_file(marlin_json, 'marlin_config.json', marlin_zip)
compress_file(marlin_json, json_name, marlin_zip)
# Generate a C source file containing the entire ZIP file as an array
with open('Marlin/src/mczip.h','wb') as result_file:
@@ -415,5 +521,12 @@ f'''#
if __name__ == "__main__":
# Build required. From command line just explain usage.
print("Use schema.py to export JSON and YAML from the command-line.")
print("Build Marlin with CONFIG_EXPORT 2 to export 'config.ini'.")
print("*** THIS SCRIPT USED BY common-dependencies.py ***\n\n"
+ "Current options for config and schema export:\n"
+ " - marlin_config.json : Build Marlin with CONFIG_EXPORT 1 or 101. (Use CONFIGURATION_EMBEDDING for 'mc.zip')\n"
+ " - config.ini : Build Marlin with CONFIG_EXPORT 2 or 102.\n"
+ " - schema.json : Run 'schema.py json' (CONFIG_EXPORT 3).\n"
+ " - schema_grouped.json : Run 'schema.py group' (CONFIG_EXPORT 13).\n"
+ " - schema.yml : Run 'schema.py yml' (CONFIG_EXPORT 4).\n"
+ " - Config-export.h : Build Marlin with CONFIG_EXPORT 5 or 105.\n"
)

View File

@@ -4,8 +4,7 @@
# Author: Taylor Talkington
# License: GPL
import bdflib.reader
import math
import bdflib.reader, math
def glyph_bits(size_x, size_y, font, glyph_ord):
asc = font[b'FONT_ASCENT']

View File

@@ -12,6 +12,7 @@ Marlin Firmware Commands:
mfadd ....... Fetch a remote branch from any Marlin fork
mfclean ..... Attempt to clean up merged and deleted branches
mfdoc ....... Build the website, serve locally, and browse
mfenvs ...... Get current board SHORT_NAME (###): [ env1 env2 ... ]
mffp ........ Push new commits directly to MarlinFirmware
mfinfo ...... Provide branch information (for the other scripts)
mfinit ...... Create an 'upstream' remote for 'MarlinFirmare'

View File

@@ -2,14 +2,9 @@
# MarlinBinaryProtocol.py
# Supporting Firmware upload via USB/Serial, saving to the attached media.
#
import serial
import math
import time
import serial, math, time, threading, sys, datetime, random
from collections import deque
import threading
import sys
import datetime
import random
try:
import heatshrink2 as heatshrink
heatshrink_exists = True

View File

@@ -18,8 +18,7 @@ Options:
--num-temps=... the number of temperature points to calculate (default: 36)
"""
from __future__ import print_function
from __future__ import division
from __future__ import print_function, division
from math import *
import sys, getopt

View File

@@ -5,8 +5,7 @@
#
# Usage: rle16_compress_cpp_image_data.py INPUT_FILE.cpp OUTPUT_FILE.cpp
#
import sys,struct
import re
import sys, struct, re
def addCompressedData(input_file, output_file):
ofile = open(output_file, 'wt')

View File

@@ -6,10 +6,11 @@
#
# Usage: rle_compress_bitmap.py INPUT_FILE OUTPUT_FILE
#
import sys,struct
import re
import sys, struct, re
def addCompressedData(input_file, output_file):
input_lines = input_file.readlines()
input_file.close()
ofile = open(output_file, 'wt')
datatype = "uint8_t"
@@ -18,8 +19,7 @@ def addCompressedData(input_file, output_file):
arrname = ''
c_data_section = False ; c_skip_data = False ; c_footer = False
while True:
line = input_file.readline()
for line in input_lines:
if not line: break
if not c_footer:
@@ -56,8 +56,6 @@ def addCompressedData(input_file, output_file):
arrname = line.split('[')[0].split(' ')[-1]
print("Found data array", arrname)
input_file.close()
#print("\nRaw Bitmap Data", raw_data)
#
@@ -190,11 +188,11 @@ if len(sys.argv) <= 2:
print('Usage: rle_compress_bitmap.py INPUT_FILE OUTPUT_FILE')
exit(1)
output_cpp = sys.argv[2]
output_h = sys.argv[2]
inname = sys.argv[1].replace('//', '/')
try:
input_cpp = open(inname)
input_h = open(inname)
print("Processing", inname, "...")
addCompressedData(input_cpp, output_cpp)
addCompressedData(input_h, output_h)
except OSError:
print("Can't find input file", inname)

View File

@@ -1,40 +0,0 @@
Overview:
1) Install Sublime
2) Install Deviot (?optional?)
3) Install WebDevShell (this will execute the auto-build script)
4) Copy the menu configuration to the proper Sublime directory
5) Add platformio to your path (usually not needed)
Sublime with autobuild
Tools
Install Package Control
Tools
Command Palette
Package Control: Install Package
type in deviot and click on it
Tools
Command Palette
Package Control: Install Package
type in WebDevShell and click on it
in Sublime, open Marlin directory with "platformio.ini" in it
starting in the top level directory, go to the folder "Buildroot/shared/Sublime"
copy the folder "auto_build_sublime_menu" and contents to:
Windows
\Users\your_user_name\AppData\Roaming\Sublime Text 3\Packages
Linux
/home/your_user_name/.config/sublime-text-3/Packages/User
macOS (Click on the Finder's 'Go' menu and hold down Option to open...)
~/Library/Application Support/Sublime Text 3/Packages/User
The menu should now be visible
If you get an error message that says "file not found" and "subprocess.Popen(['platformio' ... "
then you'll need to add platformio to your path.
macOS
sudo nano /etc/paths
add these to the bottom
/Users/bob/.platformio
/Users/bob/.platformio/penv/bin

View File

@@ -1,66 +0,0 @@
[
{
"caption": "Auto Build",
"children": [
{
"caption": "PIO Build",
"command": "webdevshell",
"args": {
"command": "python buildroot/share/vscode/auto_build.py build"
}
},
{
"caption": "PIO Clean",
"command": "webdevshell",
"args": {
"command": "python buildroot/share/vscode/auto_build.py clean"
}
},
{
"caption": "PIO Upload",
"command": "webdevshell",
"args": {
"command": "python buildroot/share/vscode/auto_build.py upload"
}
},
{
"caption": "PIO Upload (traceback)",
"command": "webdevshell",
"args": {
"command": "python buildroot/share/vscode/auto_build.py traceback"
}
},
{
"caption": "PIO Upload using Programmer",
"command": "webdevshell",
"args": {
"command": "python buildroot/share/vscode/auto_build.py program"
}
},
{
"caption": "PIO Test",
"command": "webdevshell",
"args": {
"command": "python buildroot/share/vscode/auto_build.py test"
}
},
{
"caption": "PIO Debug",
"command": "webdevshell",
"args": {
"command": "python buildroot/share/vscode/auto_build.py debug"
}
},
{
"caption": "PIO Remote",
"command": "webdevshell",
"args": {
"command": "python buildroot/share/vscode/auto_build.py remote"
}
}
],
"id": "AutoBuild",
"mnemonic": "A"
}
]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,143 +0,0 @@
#!/usr/bin/env python
#
# Builds custom upload command
# 1) Run platformio as a subprocess to find a COM port
# 2) Build the upload command
# 3) Exit and let upload tool do the work
#
# This script runs between completion of the library/dependencies installation and compilation.
#
# Will continue on if a COM port isn't found so that the compilation can be done.
#
from __future__ import print_function
from __future__ import division
import subprocess, os, platform
from SCons.Script import DefaultEnvironment
current_OS = platform.system()
env = DefaultEnvironment()
build_type = os.environ.get("BUILD_TYPE", 'Not Set')
if not(build_type == 'upload' or build_type == 'traceback' or build_type == 'Not Set') :
env.Replace(UPLOAD_PROTOCOL = 'teensy-gui') # run normal Teensy2 scripts
else:
com_first = ''
com_last = ''
com_CDC = ''
description_first = ''
description_last = ''
description_CDC = ''
#
# grab the first com port that pops up unless we find one we know for sure
# is a CDC device
#
def get_com_port(com_search_text, descr_search_text, start):
global com_first
global com_last
global com_CDC
global description_first
global description_last
global description_CDC
print('\nLooking for Serial Port\n')
# stream output from subprocess and split it into lines
pio_subprocess = subprocess.Popen(['platformio', 'device', 'list'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
looking_for_description = False
for line in iter(pio_subprocess.stdout.readline, ''):
if 0 <= line.find(com_search_text):
looking_for_description = True
com_last = line.replace('\n', '')
if com_first == '':
com_first = com_last
if 0 <= line.find(descr_search_text) and looking_for_description:
looking_for_description = False
description_last = line[ start : ]
if description_first == '':
description_first = description_last
if 0 <= description_last.find('CDC'):
com_CDC = com_last
description_CDC = description_last
if com_CDC == '' and com_first != '':
com_CDC = com_first
description_CDC = description_first
elif com_CDC == '':
com_CDC = 'COM_PORT_NOT_FOUND'
while 0 <= com_CDC.find('\n'):
com_CDC = com_CDC.replace('\n', '')
while 0 <= com_CDC.find('\r'):
com_CDC = com_CDC.replace('\r', '')
if com_CDC == 'COM_PORT_NOT_FOUND':
print(com_CDC, '\n')
else:
print('FOUND: ', com_CDC)
print('DESCRIPTION: ', description_CDC, '\n')
if current_OS == 'Windows':
get_com_port('COM', 'Hardware ID:', 13)
# avrdude_conf_path = env.get("PIOHOME_DIR") + '\\packages\\toolchain-atmelavr\\etc\\avrdude.conf'
avrdude_conf_path = 'buildroot\\share\\vscode\\avrdude.conf'
avrdude_exe_path = 'buildroot\\share\\vscode\\avrdude_5.10.exe'
# source_path = env.get("PROJECTBUILD_DIR") + '\\' + env.get("PIOENV") + '\\firmware.hex'
source_path = '.pio\\build\\' + env.get("PIOENV") + '\\firmware.hex'
upload_string = avrdude_exe_path + ' -p usb1286 -c avr109 -P ' + com_CDC + ' -U flash:w:' + source_path + ':i'
if current_OS == 'Darwin': # MAC
get_com_port('usbmodem', 'Description:', 13)
# avrdude_conf_path = env.get("PIOHOME_DIR") + '/packages/toolchain-atmelavr/etc/avrdude.conf'
avrdude_conf_path = 'buildroot/share/vscode/avrdude_macOS.conf'
avrdude_exe_path = 'buildroot/share/vscode/avrdude_5.10_macOS'
# source_path = env.get("PROJECTBUILD_DIR") + '/' + env.get("PIOENV") + '/firmware.hex'
source_path = '.pio/build/' + env.get("PIOENV") + '/firmware.hex'
# upload_string = 'avrdude -p usb1286 -c avr109 -P ' + com_CDC + ' -U flash:w:' + source_path + ':i'
upload_string = avrdude_exe_path + ' -p usb1286 -c avr109 -P ' + com_CDC + ' -C ' + avrdude_conf_path + ' -U flash:w:' + source_path + ':i'
print('upload_string: ', upload_string)
if current_OS == 'Linux':
get_com_port('/dev/tty', 'Description:', 13)
# avrdude_conf_path = env.get("PIOHOME_DIR") + '/packages/toolchain-atmelavr/etc/avrdude.conf'
avrdude_conf_path = 'buildroot/share/vscode/avrdude_linux.conf'
avrdude_exe_path = 'buildroot/share/vscode/avrdude_5.10_linux'
# source_path = env.get("PROJECTBUILD_DIR") + '/' + env.get("PIOENV") + '/firmware.hex'
source_path = '.pio/build/' + env.get("PIOENV") + '/firmware.hex'
# upload_string = 'avrdude -p usb1286 -c avr109 -P ' + com_CDC + ' -U flash:w:' + source_path + ':i'
upload_string = avrdude_exe_path + ' -p usb1286 -c avr109 -P ' + com_CDC + ' -C ' + avrdude_conf_path + ' -U flash:w:' + source_path + ':i'
env.Replace(
UPLOADCMD = upload_string,
MAXIMUM_RAM_SIZE = 8192,
MAXIMUM_SIZE = 130048
)

View File

@@ -1,41 +0,0 @@
#
# Builds custom upload command
# 1) Run platformio as a subprocess to find a COM port
# 2) Build the upload command
# 3) Exit and let upload tool do the work
#
# This script runs between completion of the library/dependencies installation and compilation.
#
# Will continue on if a COM port isn't found so that the compilation can be done.
#
import os, platform
from SCons.Script import DefaultEnvironment
current_OS = platform.system()
env = DefaultEnvironment()
build_type = os.environ.get("BUILD_TYPE", 'Not Set')
if not(build_type == 'upload' or build_type == 'traceback' or build_type == 'Not Set') :
env.Replace(UPLOAD_PROTOCOL = 'teensy-gui') # run normal Teensy2 scripts
else:
if current_OS == 'Windows':
avrdude_conf_path = env.get("PIOHOME_DIR") + '\\packages\\toolchain-atmelavr\\etc\\avrdude.conf'
source_path = env.get("PROJECTBUILD_DIR") + '\\' + env.get("PIOENV") + '\\firmware.hex'
upload_string = 'avrdude -p usb1286 -c flip1 -C ' + avrdude_conf_path + ' -U flash:w:' + source_path + ':i'
else:
source_path = env.get("PROJECTBUILD_DIR") + '/' + env.get("PIOENV") + '/firmware.hex'
upload_string = 'avrdude -p usb1286 -c flip1 -U flash:w:' + source_path + ':i'
env.Replace(
UPLOADCMD = upload_string,
MAXIMUM_RAM_SIZE = 8192,
MAXIMUM_SIZE = 130048
)

View File

@@ -24,7 +24,7 @@ restore_configs
opt_set MOTHERBOARD BOARD_BTT_GTR_V1_0 SERIAL_PORT -1 \
EXTRUDERS 5 TEMP_SENSOR_1 1 TEMP_SENSOR_2 1 TEMP_SENSOR_3 1 TEMP_SENSOR_4 1 \
Z_DRIVER_TYPE A4988 Z2_DRIVER_TYPE A4988 Z3_DRIVER_TYPE A4988 Z4_DRIVER_TYPE A4988 \
DEFAULT_Kp_LIST '{ 22.2, 20.0, 21.0, 19.0, 18.0 }' DEFAULT_Ki_LIST '{ 1.08 }' DEFAULT_Kd_LIST '{ 114.0, 112.0, 110.0, 108.0 }'
DEFAULT_KP_LIST '{ 22.2, 20.0, 21.0, 19.0, 18.0 }' DEFAULT_KI_LIST '{ 1.08 }' DEFAULT_KD_LIST '{ 114.0, 112.0, 110.0, 108.0 }'
opt_enable TOOLCHANGE_FILAMENT_SWAP TOOLCHANGE_MIGRATION_FEATURE TOOLCHANGE_FS_SLOW_FIRST_PRIME TOOLCHANGE_FS_PRIME_FIRST_USED \
REPRAP_DISCOUNT_SMART_CONTROLLER PID_PARAMS_PER_HOTEND Z_MULTI_ENDSTOPS
exec_test $1 $2 "BigTreeTech GTR | 6 Extruders | Quad Z + Endstops" "$3"

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
# Build tests for AVR ATmega FYSETC F6 1.3
# Build tests for mega2560ext - AVR ATmega (extended)
#
# exit on first failure
@@ -64,7 +64,7 @@ opt_set MOTHERBOARD BOARD_FYSETC_F6_13 \
opt_enable USE_ZMIN_PLUG FIX_MOUNTED_PROBE AUTO_BED_LEVELING_BILINEAR PAUSE_BEFORE_DEPLOY_STOW \
FYSETC_242_OLED_12864 EEPROM_SETTINGS EEPROM_CHITCHAT M114_DETAIL Z_SAFE_HOMING \
STEALTHCHOP_XY STEALTHCHOP_Z STEALTHCHOP_E HYBRID_THRESHOLD SENSORLESS_HOMING SQUARE_WAVE_STEPPING
exec_test $1 $2 "FYSETC_F6 | SCARA | Mixed TMC | EEPROM" "$3"
exec_test $1 $2 "SCARA | Mixed TMC | EEPROM" "$3"
# clean up
restore_configs

View File

@@ -1,3 +1,3 @@
# Where have all the configurations gone?
## https://github.com/MarlinFirmware/Configurations/archive/release-2.1.2.5.zip
## https://github.com/MarlinFirmware/Configurations/archive/release-2.1.2.7.zip

View File

@@ -87,13 +87,6 @@ board = megaatmega2560
extends = common_avr8
board = reprap_rambo
#
# FYSETC F6 V1.3 / V1.4
#
[env:FYSETC_F6]
extends = common_avr8
board = fysetc_f6_13
#
# Sanguinololu (ATmega644p)
#

View File

@@ -30,10 +30,10 @@ extends = env:linux_native
extra_scripts = ${common.extra_scripts}
post:buildroot/share/PlatformIO/scripts/collect-code-tests.py
build_src_filter = ${env:linux_native.build_src_filter} +<tests>
lib_deps = throwtheswitch/Unity@^2.5.2
lib_deps = throwtheswitch/Unity@^2.6.0
test_build_src = true
build_unflags =
build_flags = ${env:linux_native.build_flags} -Werror
build_flags = ${env:linux_native.build_flags} -Werror -DNO_USER_FEEDBACK_WARNING
#
# Native Simulation
@@ -58,7 +58,7 @@ debug_build_flags = -fstack-protector-strong -g -g3 -ggdb
lib_compat_mode = off
build_src_filter = ${common.default_src_filter} +<src/HAL/NATIVE_SIM>
lib_deps = ${common.lib_deps}
MarlinSimUI=https://github.com/p3p/MarlinSimUI/archive/afe7c1c293.zip
MarlinSimUI=https://github.com/p3p/MarlinSimUI/archive/29c11d4f63.zip
Adafruit NeoPixel=https://github.com/p3p/Adafruit_NeoPixel/archive/c6b319f447.zip
LiquidCrystal=https://github.com/p3p/LiquidCrystal/archive/322fb5fc23.zip
extra_scripts = ${common.extra_scripts}
@@ -81,11 +81,15 @@ build_flags = ${simulator_linux.build_flags} ${simulator_linux.release_flags}
# Simulator for macOS (MacPorts)
#
#
# Use the script buildroot/bin/mac_gcc to prepare your environment.
#
# MacPorts:
# https://www.macports.org/install.php
#
# sudo port install gcc14 glm mesa libsdl2 libsdl2_net
#
# cd /opt/local/bin
# cd $(dirname "$(which port)")
# sudo rm gcc g++ cc ld
# sudo ln -s gcc-mp-14 gcc ; sudo ln -s g++-mp-14 g++ ; sudo ln -s g++ cc
# sudo ln -s ld-classic ld
@@ -99,7 +103,7 @@ build_flags = ${simulator_linux.build_flags} ${simulator_linux.release_flags}
#
# brew install gcc@14 glm mesa sdl2 sdl2_net
#
# cd /opt/homebrew/bin
# cd "$(brew --prefix)/bin"
# sudo rm -f gcc g++ cc
# sudo ln -s gcc-14 gcc ; sudo ln -s g++-14 g++ ; sudo ln -s g++ cc
# cd -
@@ -111,7 +115,7 @@ build_flags = -g2
-DHAS_LIBBSD
-I/opt/local/include
-I/opt/local/include/freetype2
-I/opt/local/include/SDL2/
-I/opt/local/include/SDL2
-L/opt/local/lib
-Wl,-framework,OpenGl
-Wl,-framework,CoreFoundation

View File

@@ -95,3 +95,6 @@ extends = renamed
[env:STM32F407ZE_btt_USB] ;=> STM32F407ZE_btt_usb_flash_drive
extends = renamed
[env:FYSETC_F6] ;=> mega2560ext
extends = renamed

View File

@@ -10,7 +10,7 @@
#################################
#
# Adafruit Grand Central M4 (Atmel SAMD51P20A ARM Cortex-M4)
# ReprapWorld Minitronics (Atmel SAMD21J18 ARM Cortex-M0+)
#
[env:SAMD21_minitronics20]
platform = atmelsam

View File

@@ -23,7 +23,7 @@
# HAL/STM32F1 Common Environment values
#
[STM32F1_maple]
platform = ststm32@~12.1
platform = ststm32@~15.4.1
board_build.core = maple
build_flags = !python Marlin/src/HAL/STM32F1/build_flags.py
${common.build_flags} -DARDUINO_ARCH_STM32 -DMAPLE_STM32F1 -DPLATFORM_M997_SUPPORT
@@ -31,13 +31,18 @@ build_unflags = -std=gnu11 -std=gnu++11
build_src_filter = ${common.default_src_filter} +<src/HAL/STM32F1> -<src/HAL/STM32F1/tft>
lib_ignore = SPI, FreeRTOS701, FreeRTOS821
lib_deps = ${common.lib_deps}
SoftwareSerialM
SoftwareSerialM
platform_packages = tool-stm32duino
toolchain-gccarmnoneeabi@1.120301.0 # Otherwise it's GCC 7.2.1
extra_scripts = ${common.extra_scripts}
pre:buildroot/share/PlatformIO/scripts/fix_framework_weakness.py
pre:buildroot/share/PlatformIO/scripts/stm32_serialbuffer.py
buildroot/share/PlatformIO/scripts/custom_board.py
buildroot/share/PlatformIO/scripts/offset_and_rename.py
custom_marlin.HAS_SPI_TFT = build_src_filter=+<src/HAL/STM32F1/tft/tft_spi.cpp>
custom_marlin.HAS_TFT_XPT2046 = build_src_filter=+<src/HAL/STM32F1/tft/xpt2046.cpp>
custom_marlin.HAS_FSMC_TFT = build_src_filter=+<src/HAL/STM32F1/tft/tft_fsmc.cpp>
custom_marlin.NEOPIXEL_LED = Adafruit NeoPixel=https://github.com/ccccmagicboy/Adafruit_NeoPixel#meeb_3dp_use
#
# Generic STM32F103RC environment
@@ -61,6 +66,8 @@ monitor_speed = 115200
[env:STM32F103RC_meeb_maple]
extends = env:STM32F103RC_maple
board = marlin_maple_MEEB_3DP
platform_packages = ${env:STM32F103RC_maple.platform_packages}
platformio/tool-dfuutil@~1.11.0
build_flags = ${env:STM32F103RC_maple.build_flags}
-DDEBUG_LEVEL=0
-DSS_TIMER=4
@@ -69,13 +76,13 @@ build_flags = ${env:STM32F103RC_maple.build_flags}
-DUSE_USB_COMPOSITE
-DVECT_TAB_OFFSET=0x2000
-DGENERIC_BOOTLOADER
-DNO_MAPLE_WARNING
board_build.ldscript = STM32F103RC_MEEB_3DP.ld
extra_scripts = ${env:STM32F103RC_maple.extra_scripts}
pre:buildroot/share/PlatformIO/scripts/STM32F1_create_variant.py
buildroot/share/PlatformIO/scripts/STM32F103RC_MEEB_3DP.py
lib_deps = ${env:STM32F103RC_maple.lib_deps}
USBComposite for STM32F1@0.91
custom_marlin.NEOPIXEL_LED = Adafruit NeoPixel=https://github.com/ccccmagicboy/Adafruit_NeoPixel#meeb_3dp_use
USBComposite for STM32F1@1.0.9
debug_tool = stlink
upload_protocol = dfu
@@ -83,13 +90,13 @@ upload_protocol = dfu
# FYSETC STM32F103RC
#
[env:STM32F103RC_fysetc_maple]
extends = env:STM32F103RC_maple
extra_scripts = ${env:STM32F103RC_maple.extra_scripts}
buildroot/share/PlatformIO/scripts/STM32F103RC_fysetc.py
build_flags = ${env:STM32F103RC_maple.build_flags} -DDEBUG_LEVEL=0
lib_ldf_mode = chain
debug_tool = stlink
upload_protocol = serial
extends = env:STM32F103RC_maple
extra_scripts = ${env:STM32F103RC_maple.extra_scripts}
buildroot/share/PlatformIO/scripts/STM32F103RC_fysetc.py
build_flags = ${env:STM32F103RC_maple.build_flags} -DDEBUG_LEVEL=0
lib_ldf_mode = chain
debug_tool = stlink
upload_protocol = serial
#
# BigTreeTech SKR Mini V1.1 / SKR Mini E3 & MZ (STM32F103RCT6 ARM Cortex-M3)
@@ -108,7 +115,7 @@ monitor_speed = 115200
extends = env:STM32F103RC_btt_maple
build_flags = ${env:STM32F103RC_btt_maple.build_flags} -DUSE_USB_COMPOSITE
lib_deps = ${env:STM32F103RC_btt_maple.lib_deps}
USBComposite for STM32F1@0.91
USBComposite for STM32F1@1.0.9
#
# Creality 512K (STM32F103RET6)
@@ -160,7 +167,7 @@ upload_protocol = stlink
extends = env:STM32F103RE_btt_maple
build_flags = ${env:STM32F103RE_btt_maple.build_flags} -DUSE_USB_COMPOSITE
lib_deps = ${env:STM32F103RE_btt_maple.lib_deps}
USBComposite for STM32F1@0.91
USBComposite for STM32F1@1.0.9
#
# Geeetech GTM32 (STM32F103VET6)
@@ -185,7 +192,7 @@ board_build.address = 0x08010000
board_build.rename = project.bin
board_build.ldscript = STM32F103VE_longer.ld
build_flags = ${STM32F1_maple.build_flags}
-DMCU_STM32F103VE -DSTM32F1xx -USERIAL_USB -DU20 -DTS_V12
-DMCU_STM32F103VE -DSTM32F1xx -DSERIAL_USB -DU20 -DTS_V12
build_unflags = ${STM32F1_maple.build_unflags}
-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DERROR_LED_PORT=GPIOE -DERROR_LED_PIN=6
@@ -236,6 +243,7 @@ board_build.ldscript = mks_robin_pro.ld
#
[env:trigorilla_pro_maple]
extends = env:mks_robin_maple
build_flags = ${env:mks_robin_maple.build_flags} -DSTM32_FLASH_SIZE=512
#
# MKS Robin E3D (STM32F103RCT6) and
@@ -311,14 +319,15 @@ lib_ignore = ${STM32F1_maple.lib_ignore}
# Chitu boards like Tronxy X5s (STM32F103ZET6)
#
[env:chitu_f103_maple]
extends = STM32F1_maple
board = marlin_maple_CHITU_F103
extra_scripts = ${STM32F1_maple.extra_scripts}
pre:buildroot/share/PlatformIO/scripts/STM32F1_create_variant.py
buildroot/share/PlatformIO/scripts/chitu_crypt.py
build_flags = ${STM32F1_maple.build_flags} -DSTM32F1xx -DSTM32_XL_DENSITY
build_unflags = ${STM32F1_maple.build_unflags}
-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG= -DERROR_LED_PORT=GPIOE -DERROR_LED_PIN=6
extends = STM32F1_maple
board = marlin_maple_CHITU_F103
extra_scripts = ${STM32F1_maple.extra_scripts}
pre:buildroot/share/PlatformIO/scripts/STM32F1_create_variant.py
buildroot/share/PlatformIO/scripts/chitu_crypt.py
build_flags = ${STM32F1_maple.build_flags} -DSTM32F1xx -DSTM32_XL_DENSITY -DSTM32_FLASH_SIZE=512
build_unflags = ${STM32F1_maple.build_unflags}
-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG= -DERROR_LED_PORT=GPIOE -DERROR_LED_PIN=6
board_build.crypt_chitu = update.cbd
#
# Some Chitu V5 boards have a problem with GPIO init.
@@ -353,8 +362,8 @@ board_upload.maximum_size = 237568
build_flags = ${STM32F1_maple.build_flags}
-D__STM32F1__=1 -DDEBUG_LEVEL=0 -DSS_TIMER=4 -DSERIAL_USB
lib_deps = ${STM32F1_maple.lib_deps}
USBComposite for STM32F1@0.91
lib_ignore = Adafruit NeoPixel, SPI, SailfishLCD, SailfishRGB_LED, SlowSoftI2CMaster, TMCStepper
USBComposite for STM32F1@1.0.9
lib_ignore = Adafruit NeoPixel, SPI, SailfishLCD, SailfishRGB_LED, SlowSoftI2CMaster
[env:STM32F103RC_ZM3E2_USB_maple]
extends = ZONESTAR_ZM3E_maple
@@ -385,6 +394,7 @@ build_flags = ${STM32F1_maple.build_flags}
-DMCU_STM32F103VE -DARDUINO_GENERIC_STM32F103V -DARDUINO_ARCH_STM32F1
-DDEBUG_LEVEL=DEBUG_NONE -DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1
-DSS_TIMER=4
-DNO_MAPLE_WARNING
board_build.variant = MARLIN_F103Vx
board_build.ldscript = eryone_ery32_mini.ld
board_build.address = 0x08004000
@@ -395,7 +405,7 @@ build_unflags = ${STM32F1_maple.build_unflags}
#
[env:GD32F103RET6_sovol_maple]
extends = env:STM32F103RE_maple
build_flags = ${STM32F1_maple.build_flags} -DTEMP_TIMER_CHAN=4
build_flags = ${STM32F1_maple.build_flags} -DTEMP_TIMER_CHAN=4 -DNO_MAPLE_WARNING
board_build.address = 0x08007000
board_build.ldscript = sovol.ld
board_build.rename = firmware-{date}-{time}.bin

View File

@@ -63,15 +63,15 @@ build_flags = ${common_STM32F103RC_variant.build_flags}
board_build.offset = 0x7000
board_upload.offset_address = 0x08007000
[USBD_CDC_MSC]
build_flags = -DUSE_USB_FS -DUSBD_USE_CDC_MSC -DUSBD_IRQ_PRIO=5 -DUSBD_IRQ_SUBPRIO=6
build_unflags = -DUSBD_USE_CDC
[env:STM32F103RC_btt_USB]
extends = env:STM32F103RC_btt
platform_packages = ${stm_flash_drive.platform_packages}
build_flags = ${env:STM32F103RC_btt.build_flags}
-DUSE_USB_FS
-DUSBD_IRQ_PRIO=5
-DUSBD_IRQ_SUBPRIO=6
-DUSBD_USE_CDC_MSC
build_unflags = ${common_stm32.build_unflags} -DUSBD_USE_CDC
build_flags = ${env:STM32F103RC_btt.build_flags} ${USBD_CDC_MSC.build_flags}
build_unflags = ${env:STM32F103RC_btt.build_unflags} ${USBD_CDC_MSC.build_unflags}
#
# Panda Pi V2.9 - Standalone (STM32F103RC)
@@ -83,8 +83,8 @@ build_flags = ${common_STM32F103RC_variant.build_flags}
-DTIMER_SERVO=TIM1
board_build.offset = 0x5000
board_upload.offset_address = 0x08005000
lib_deps =
markyue/Panda_SoftMasterI2C@1.0.3
lib_deps = markyue/Panda_SoftMasterI2C@1.0.3
#
# MKS Robin (STM32F103ZET6)
# Uses HAL STM32 to support Marlin UI for TFT screen with optional touch panel
@@ -95,6 +95,7 @@ board = genericSTM32F103ZE
board_build.variant = MARLIN_F103Zx
board_build.encrypt_mks = Robin.bin
board_build.offset = 0x7000
board_build.offset_address = 0x08007000
build_flags = ${stm32_variant.build_flags}
-DENABLE_HWSERIAL3 -DTIMER_SERIAL=TIM5
build_unflags = ${stm32_variant.build_unflags}
@@ -121,8 +122,8 @@ debug_tool = stlink
extends = stm32_variant
board_build.variant = MARLIN_F103Rx
board_build.offset = 0x7000
board_build.rename = firmware-{date}-{time}.bin
board_upload.offset_address = 0x08007000
board_build.rename = firmware-{date}-{time}.bin
build_flags = ${stm32_variant.build_flags}
-DMCU_STM32F103RE -DHAL_SD_MODULE_ENABLED
-DSS_TIMER=4 -DTIMER_SERVO=TIM5
@@ -177,6 +178,7 @@ board_upload.offset_address = 0x08010000
extends = env:STM32F103RE_creality
board_build.offset = 0x8000
board_upload.offset_address = 0x08008000
board_build.rename = main_board_{date}_{time}.bin
#
# Creality 256K (STM32F103RC)
@@ -199,7 +201,7 @@ board = genericSTM32F103RC
extends = STM32F103Rx_creality
board = genericSTM32F103VE
board_build.variant = MARLIN_F103Vx
build_flags = ${stm32_variant.build_flags}
build_flags = ${STM32F103Rx_creality.build_flags}
-DSS_TIMER=4 -DTIMER_SERVO=TIM5
-DENABLE_HWSERIAL3 -DTRANSFER_CLOCK_DIV=8
#
@@ -225,10 +227,8 @@ upload_protocol = jlink
[env:STM32F103RE_btt_USB]
extends = env:STM32F103RE_btt
platform_packages = ${stm_flash_drive.platform_packages}
build_flags = ${env:STM32F103RE_btt.build_flags}
-DUSE_USB_FS -DUSBD_IRQ_PRIO=5
-DUSBD_IRQ_SUBPRIO=6 -DUSBD_USE_CDC_MSC
build_unflags = ${env:STM32F103RE_btt.build_unflags} -DUSBD_USE_CDC
build_flags = ${env:STM32F103RE_btt.build_flags} ${USBD_CDC_MSC.build_flags}
build_unflags = ${env:STM32F103RE_btt.build_unflags} ${USBD_CDC_MSC.build_unflags}
#
# Mingda MPX_ARM_MINI
@@ -238,6 +238,7 @@ extends = stm32_variant
board = genericSTM32F103ZE
board_build.variant = MARLIN_F103Zx
board_build.offset = 0x10000
board_build.offset_address = 0x08010000
build_flags = ${stm32_variant.build_flags}
-DENABLE_HWSERIAL3 -DTIMER_SERIAL=TIM5
build_unflags = ${stm32_variant.build_unflags}
@@ -252,7 +253,7 @@ board = malyanm200_f103cb
build_flags = ${common_stm32.build_flags}
-DHAL_PCD_MODULE_ENABLED -DDISABLE_GENERIC_SERIALUSB
-DHAL_UART_MODULE_ENABLED
build_src_filter = ${common.default_src_filter} +<src/HAL/STM32> -<src/HAL/STM32/tft>
build_src_filter = ${common_stm32.build_src_filter} +<src/HAL/STM32> -<src/HAL/STM32/tft>
#
# FLYmaker FLY Mini (STM32F103RCT6)
@@ -263,7 +264,7 @@ board = genericSTM32F103RC
board_build.variant = MARLIN_F103Rx
board_build.offset = 0x5000
board_upload.offset_address = 0x08005000
build_flags = ${stm32_variant.build_flags} -DSS_TIMER=4
build_flags = ${stm32_variant.build_flags} -DSS_TIMER=4 -DSTM32_FLASH_SIZE=256
#
# (STM32F103VE_robin)
@@ -361,6 +362,8 @@ board_build.offset = 0xA000
board_upload.offset_address = 0x0800A000
build_flags = ${stm32_variant.build_flags}
-DSTM32F1xx -DSTM32_XL_DENSITY
build_unflags = ${stm32_variant.build_unflags}
-DUSBCON -DUSBD_USE_CDC
extra_scripts = ${stm32_variant.extra_scripts}
buildroot/share/PlatformIO/scripts/jgaurora_a5s_a1_with_bootloader.py
@@ -402,7 +405,7 @@ extends = stm32_variant
board = genericSTM32F103ZE
board_build.variant = MARLIN_F103Zx
build_flags = ${stm32_variant.build_flags}
-DENABLE_HWSERIAL3 -DTIMER_SERIAL=TIM5
-DENABLE_HWSERIAL3 -DTIMER_SERIAL=TIM5 -DSTM32_FLASH_SIZE=512
build_unflags = ${stm32_variant.build_unflags}
-DUSBCON -DUSBD_USE_CDC
@@ -416,6 +419,7 @@ board = genericSTM32F103ZE
board_build.crypt_chitu = update.zw
board_build.variant = MARLIN_F103Zx
board_build.offset = 0x8800
board_build.offset_address = 0x08008800
build_flags = ${stm32_variant.build_flags}
-DENABLE_HWSERIAL3 -DTIMER_SERIAL=TIM5
build_unflags = ${stm32_variant.build_unflags}
@@ -433,8 +437,8 @@ board = genericSTM32F103ZE
board_build.crypt_chitu = update.cbd
board_build.variant = MARLIN_F103Zx
board_build.offset = 0x8800
build_flags = ${stm32_variant.build_flags}
-DSTM32F1xx
board_build.offset_address = 0x08008800
build_flags = ${stm32_variant.build_flags} -DSTM32F1xx -DSTM32_FLASH_SIZE=512
build_unflags = ${stm32_variant.build_unflags}
extra_scripts = ${stm32_variant.extra_scripts}
buildroot/share/PlatformIO/scripts/chitu_crypt.py
@@ -457,13 +461,13 @@ build_flags = ${env:chitu_f103.build_flags} -DCHITU_V5_Z_MIN_BUGFIX
[ZONESTAR_ZM3E]
extends = stm32_variant
platform_packages = ${stm_flash_drive.platform_packages}
board_upload.offset_address = 0x08005000
board_build.offset = 0x5000
board_upload.offset_address = 0x08005000
board_upload.maximum_size = 237568
extra_scripts = ${stm32_variant.extra_scripts}
build_flags = ${common_stm32.build_flags}
-DSS_TIMER=4 -DTIMER_SERVO=TIM5 -DUSE_USB_FS -DUSBD_IRQ_PRIO=5 -DUSBD_IRQ_SUBPRIO=6 -DUSBD_USE_CDC_MSC
build_unflags = ${stm32_variant.build_unflags} -DUSBD_USE_CDC
build_flags = ${stm32_variant.build_flags} ${USBD_CDC_MSC.build_flags}
-DSS_TIMER=4 -DTIMER_SERVO=TIM5
build_unflags = ${stm32_variant.build_unflags} ${USBD_CDC_MSC.build_unflags}
[env:STM32F103RC_ZM3E2_USB]
extends = ZONESTAR_ZM3E