Marlin_Firmware/Marlin/src/module/configuration_store.cpp

2485 lines
74 KiB
C++
Raw Normal View History

/**
2016-03-24 13:01:20 -05:00
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
2015-04-25 23:04:54 -05:00
* configuration_store.cpp
*
2017-04-09 21:47:49 -05:00
* Settings and EEPROM storage
*
2015-04-03 18:38:05 -05:00
* IMPORTANT: Whenever there are changes made to the variables stored in EEPROM
* in the functions below, also increment the version number. This makes sure that
* the default values are used whenever there is a change to the data, to prevent
* wrong data being written to the variables.
*
* ALSO: Variables in the Store and Retrieve sections must be in the same order.
* If a feature is disabled, some data must still be written that, when read,
* either sets a Sane Default, or results in No Change to the existing value.
*
*/
2018-01-04 19:59:43 -06:00
// Change EEPROM version if the structure changes
2018-02-23 00:53:29 -06:00
#define EEPROM_VERSION "V52"
#define EEPROM_OFFSET 100
2018-01-04 20:27:17 -06:00
// Check the integrity of data offsets.
// Can be disabled for production build.
//#define DEBUG_EEPROM_READWRITE
2017-04-09 21:47:49 -05:00
#include "configuration_store.h"
#include "endstops.h"
#include "planner.h"
#include "stepper.h"
2017-09-06 06:28:32 -05:00
#include "temperature.h"
#include "../lcd/ultralcd.h"
#include "../core/language.h"
2018-01-04 19:59:43 -06:00
#include "../libs/vector_3.h"
#include "../gcode/gcode.h"
2017-09-06 06:28:32 -05:00
#include "../Marlin.h"
2017-09-08 15:35:25 -05:00
#if HAS_LEVELING
#include "../feature/bedlevel/bedlevel.h"
#endif
2017-09-06 06:28:32 -05:00
#if HAS_BED_PROBE
#include "../module/probe.h"
#endif
2015-03-15 17:18:11 -05:00
#if ENABLED(HAVE_TMC2130)
#include "stepper_indirection.h"
#endif
2017-09-06 06:28:32 -05:00
#if ENABLED(FWRETRACT)
#include "../feature/fwretract.h"
2017-03-18 10:15:54 -05:00
#endif
2018-02-22 12:28:46 -06:00
#if ENABLED(ADVANCED_PAUSE_FEATURE)
#include "../feature/pause.h"
#endif
#pragma pack(push, 1) // No padding between variables
2018-01-04 19:59:43 -06:00
typedef struct PID { float Kp, Ki, Kd; } PID;
typedef struct PIDC { float Kp, Ki, Kd, Kc; } PIDC;
/**
* Current EEPROM Layout
*
* Keep this data structure up to date so
* EEPROM size is known at compile time!
*/
typedef struct SettingsDataStruct {
char version[4]; // Vnn\0
uint16_t crc; // Data Checksum
//
// DISTINCT_E_FACTORS
//
uint8_t esteppers; // XYZE_N - XYZ
float planner_axis_steps_per_mm[XYZE_N], // M92 XYZE planner.axis_steps_per_mm[XYZE_N]
planner_max_feedrate_mm_s[XYZE_N]; // M203 XYZE planner.max_feedrate_mm_s[XYZE_N]
uint32_t planner_max_acceleration_mm_per_s2[XYZE_N]; // M201 XYZE planner.max_acceleration_mm_per_s2[XYZE_N]
float planner_acceleration, // M204 P planner.acceleration
planner_retract_acceleration, // M204 R planner.retract_acceleration
planner_travel_acceleration, // M204 T planner.travel_acceleration
planner_min_feedrate_mm_s, // M205 S planner.min_feedrate_mm_s
planner_min_travel_feedrate_mm_s; // M205 T planner.min_travel_feedrate_mm_s
uint32_t planner_min_segment_time_us; // M205 B planner.min_segment_time_us
float planner_max_jerk[XYZE]; // M205 XYZE planner.max_jerk[XYZE]
float home_offset[XYZ]; // M206 XYZ
#if HOTENDS > 1
float hotend_offset[XYZ][HOTENDS - 1]; // M218 XYZ
#endif
//
// ENABLE_LEVELING_FADE_HEIGHT
//
float planner_z_fade_height; // M420 Zn planner.z_fade_height
//
// MESH_BED_LEVELING
//
float mbl_z_offset; // mbl.z_offset
uint8_t mesh_num_x, mesh_num_y; // GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y
#if ENABLED(MESH_BED_LEVELING)
float mbl_z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; // mbl.z_values
#else
float mbl_z_values[3][3];
#endif
//
// HAS_BED_PROBE
//
float zprobe_zoffset; // M851 Z
//
// ABL_PLANAR
//
matrix_3x3 planner_bed_level_matrix; // planner.bed_level_matrix
//
// AUTO_BED_LEVELING_BILINEAR
//
uint8_t grid_max_x, grid_max_y; // GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y
int bilinear_grid_spacing[2],
bilinear_start[2]; // G29 L F
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
float z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; // G29
#else
float z_values[3][3];
#endif
//
// AUTO_BED_LEVELING_UBL
//
bool planner_leveling_active; // M420 S planner.leveling_active
int8_t ubl_storage_slot; // ubl.storage_slot
//
// DELTA / [XYZ]_DUAL_ENDSTOPS
//
#if ENABLED(DELTA)
float delta_height, // M666 H
delta_endstop_adj[ABC], // M666 XYZ
delta_radius, // M665 R
delta_diagonal_rod, // M665 L
delta_segments_per_second, // M665 S
delta_calibration_radius, // M665 B
delta_tower_angle_trim[ABC]; // M665 XYZ
#elif ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
float x_endstop_adj, // M666 X
y_endstop_adj, // M666 Y
z_endstop_adj; // M666 Z
#endif
//
// ULTIPANEL
//
int16_t lcd_preheat_hotend_temp[2], // M145 S0 H
lcd_preheat_bed_temp[2], // M145 S0 B
lcd_preheat_fan_speed[2]; // M145 S0 F
2018-01-04 19:59:43 -06:00
//
// PIDTEMP
//
PIDC hotendPID[MAX_EXTRUDERS]; // M301 En PIDC / M303 En U
int lpq_len; // M301 L
//
// PIDTEMPBED
//
PID bedPID; // M304 PID / M303 E-1 U
//
// HAS_LCD_CONTRAST
//
int16_t lcd_contrast; // M250 C
2018-01-04 19:59:43 -06:00
//
// FWRETRACT
//
bool autoretract_enabled; // M209 S
float retract_length, // M207 S
retract_feedrate_mm_s, // M207 F
retract_zlift, // M207 Z
retract_recover_length, // M208 S
retract_recover_feedrate_mm_s, // M208 F
swap_retract_length, // M207 W
swap_retract_recover_length, // M208 W
swap_retract_recover_feedrate_mm_s; // M208 R
//
// !NO_VOLUMETRIC
//
bool parser_volumetric_enabled; // M200 D parser.volumetric_enabled
float planner_filament_size[MAX_EXTRUDERS]; // M200 T D planner.filament_size[]
//
// HAS_TRINAMIC
//
uint16_t tmc_stepper_current[11]; // M906 X Y Z X2 Y2 Z2 E0 E1 E2 E3 E4
2018-02-25 21:02:22 -06:00
int16_t tmc_sgt[XYZ]; // M914 X Y Z
2018-01-04 19:59:43 -06:00
//
// LIN_ADVANCE
//
2018-02-23 00:53:29 -06:00
float planner_extruder_advance_K; // M900 K planner.extruder_advance_K
2018-01-04 19:59:43 -06:00
//
// HAS_MOTOR_CURRENT_PWM
//
uint32_t motor_current_setting[XYZ]; // M907 X Z E
//
// CNC_COORDINATE_SYSTEMS
//
float coordinate_system[MAX_COORDINATE_SYSTEMS][XYZ]; // G54-G59.3
//
// SKEW_CORRECTION
//
float planner_xy_skew_factor, // M852 I planner.xy_skew_factor
planner_xz_skew_factor, // M852 J planner.xz_skew_factor
planner_yz_skew_factor; // M852 K planner.yz_skew_factor
//
// ADVANCED_PAUSE_FEATURE
//
float filament_change_unload_length[MAX_EXTRUDERS], // M603 T U
filament_change_load_length[MAX_EXTRUDERS]; // M603 T L
} SettingsData;
#pragma pack(pop)
2018-01-04 19:59:43 -06:00
MarlinSettings settings;
2018-01-04 20:01:25 -06:00
uint16_t MarlinSettings::datasize() { return sizeof(SettingsData); }
/**
* Post-process after Retrieve or Reset
*/
2018-01-04 19:59:43 -06:00
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
float new_z_fade_height;
#endif
2017-04-09 21:47:49 -05:00
void MarlinSettings::postprocess() {
2017-12-10 22:57:24 -06:00
const float oldpos[] = { current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] };
// steps per s2 needs to be updated to agree with units per s2
planner.reset_acceleration_rates();
// Make sure delta kinematics are updated before refreshing the
// planner position so the stepper counts will be set correctly.
#if ENABLED(DELTA)
2017-11-08 03:07:17 -06:00
recalc_delta_settings();
#endif
#if ENABLED(PIDTEMP)
thermalManager.updatePID();
#endif
#if DISABLED(NO_VOLUMETRICS)
planner.calculate_volumetric_multipliers();
2017-12-26 20:04:39 -06:00
#else
for (uint8_t i = COUNT(planner.e_factor); i--;)
planner.refresh_e_factor(i);
#endif
#if HAS_HOME_OFFSET || ENABLED(DUAL_X_CARRIAGE)
2017-03-04 18:01:33 -06:00
// Software endstops depend on home_offset
LOOP_XYZ(i) update_software_endstops((AxisEnum)i);
#endif
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
set_z_fade_height(new_z_fade_height, false); // false = no report
#endif
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
refresh_bed_level();
#endif
#if HAS_MOTOR_CURRENT_PWM
stepper.refresh_motor_power();
#endif
2017-09-29 08:03:28 -05:00
#if ENABLED(FWRETRACT)
fwretract.refresh_autoretract();
#endif
2017-12-19 19:11:07 -06:00
// Refresh steps_to_mm with the reciprocal of axis_steps_per_mm
// and init stepper.count[], planner.position[] with current_position
planner.refresh_positioning();
2017-11-04 16:36:41 -05:00
// Various factors can change the current position
if (memcmp(oldpos, current_position, sizeof(oldpos)))
report_current_position();
}
#if ENABLED(EEPROM_SETTINGS)
2017-09-06 06:28:32 -05:00
#include "../HAL/persistent_store_api.h"
#define DUMMY_PID_VALUE 3000.0f
#define EEPROM_START() int eeprom_index = EEPROM_OFFSET; HAL::PersistentStore::access_start()
#define EEPROM_FINISH() HAL::PersistentStore::access_finish()
#define EEPROM_SKIP(VAR) eeprom_index += sizeof(VAR)
#define EEPROM_WRITE(VAR) HAL::PersistentStore::write_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc)
2018-01-04 19:51:18 -06:00
#define EEPROM_READ(VAR) HAL::PersistentStore::read_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc, !validating)
#define EEPROM_READ_ALWAYS(VAR) HAL::PersistentStore::read_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc)
2017-11-05 08:49:38 -06:00
#define EEPROM_ASSERT(TST,ERR) if (!(TST)) do{ SERIAL_ERROR_START_P(port); SERIAL_ERRORLNPGM_P(port, ERR); eeprom_error = true; }while(0)
2018-01-04 20:27:17 -06:00
#if ENABLED(DEBUG_EEPROM_READWRITE)
2018-01-05 19:00:26 -06:00
#define _FIELD_TEST(FIELD) \
EEPROM_ASSERT( \
eeprom_error || eeprom_index == offsetof(SettingsData, FIELD) + EEPROM_OFFSET, \
"Field " STRINGIFY(FIELD) " mismatch." \
2018-01-04 20:27:17 -06:00
)
#else
#define _FIELD_TEST(FIELD) NOOP
#endif
2016-12-09 06:13:44 -06:00
const char version[4] = EEPROM_VERSION;
2018-01-04 19:51:18 -06:00
bool MarlinSettings::eeprom_error, MarlinSettings::validating;
2017-04-09 21:47:49 -05:00
2017-11-05 08:49:38 -06:00
bool MarlinSettings::size_error(const uint16_t size
#if ADD_PORT_ARG
, const int8_t port/*=-1*/
#endif
) {
2018-01-04 20:01:25 -06:00
if (size != datasize()) {
2017-11-05 08:49:38 -06:00
#if ENABLED(EEPROM_CHITCHAT)
SERIAL_ERROR_START_P(port);
SERIAL_ERRORLNPGM_P(port, "EEPROM datasize error.");
#endif
2018-01-04 20:01:25 -06:00
return true;
}
return false;
}
2016-10-28 18:55:42 -05:00
/**
* M500 - Store Configuration
*/
2017-11-05 08:49:38 -06:00
bool MarlinSettings::save(
#if ADD_PORT_ARG
const int8_t port/*=-1*/
#endif
) {
2016-10-28 18:55:42 -05:00
float dummy = 0.0f;
2018-01-05 19:00:26 -06:00
char ver[4] = "ERR";
uint16_t working_crc = 0;
2016-10-28 18:55:42 -05:00
EEPROM_START();
eeprom_error = false;
[2.0.x] Multiple updates to STM32F1 HAL (#8733) * STM32F1 HAL Adding files for STM32F1 HAL based on libmaple/stm32duino core. Current persistent_store uses cardreader changes to be sent in separate commit, but could be changed to use i2c eeprom. There is another persistent_store implementation that uses the MCU flash memory to emulate eeprom Adding readme with some information about the stm32 HAL. * Switch to Timer4 to avoid a hard reset on STM32F103C6 boards On bluepill STM32F103C6 boards, using Timer5 results in a error() vector call. Switch to 4 since these are both general purpose, 16 bit timers. * Add support for EEPROM emulation using Flash Some low end machines doe not have EEPROM support. Simulate it using the last two pages of flash. Flash does not allow rewrite between erases, so skip writing the working version if that's enabled. * Basic Pins for a malyan M200 This is a work in progress to go hand in hand with the STM32 work. * Add support for ADC with DMA. This work has exposed a problem with the pin enumerations in STM boards vs what marlin expects (i.e, try defining PA0 as a temp pin). The hack can be removed with we go to fastio completely. To see this work, set something in adc_pins to a value like PA0 and connect your pullup resistor'd thermistor. * Missing file - change HAL_adc_init to actually do something We have an actual ADC init function now. * Remove pinmode hack Remove the pin mode hack that I was using to init PA0. Updated Readme.md * Several changes to timers and GPIO Faster GPIO, and faster timer functions by accesing registers and libmaple. Still more changes pending for the Timer's code to skip using the HardwareTimer class altogether. Switch all enums to be within #defines This change allows a user to have, for instance, TEMP_4 and TEMP_BED definied but nothing else. The enums which are not defined move "out", allowing the first ones to take the slots in the enum, and since the array is sized on ADC_PIN_COUNT, we always have the right size data and in order. * Update Malyan M200 pins Update Malyan M200 pins with correct fan values. * Test all pins on actual hardware, update definitions Some of the pin definitions were from knowlege base/pdfs. Now they've been tested against actual hardware. This should be very close to final. * Update HAL_timers_Stm32f1.cpp * Add sample configurations for Malyan M200 Add sample configuration for Malyan M200 without bed leveling, and move fan to auto cool E0 since this printer by default has only one fan. Choose the timer based on MCU defintion. Timer5 is not valid on C8/CB class boards, so use Timer4 for the step timer. readme.md update * Updates to timers, and some stm32 boards definitiions * Correct pin toggle macro. * Remove duplicated Malyan M200 entry from pins.h * Update configuration_store.cpp * Formatting, indentation * Formatting in HAL_Stm32f1.cpp
2017-12-10 23:12:45 -06:00
#if ENABLED(FLASH_EEPROM_EMULATION)
EEPROM_SKIP(ver); // Flash doesn't allow rewriting without erase
#else
EEPROM_WRITE(ver); // invalidate data first
#endif
EEPROM_SKIP(working_crc); // Skip the checksum slot
2016-06-29 20:12:23 -05:00
working_crc = 0; // clear before first "real data"
2016-07-24 12:19:49 -05:00
2018-01-04 20:27:17 -06:00
_FIELD_TEST(esteppers);
2016-12-15 23:15:12 -06:00
const uint8_t esteppers = COUNT(planner.axis_steps_per_mm) - XYZ;
EEPROM_WRITE(esteppers);
2016-10-28 18:55:42 -05:00
EEPROM_WRITE(planner.axis_steps_per_mm);
EEPROM_WRITE(planner.max_feedrate_mm_s);
EEPROM_WRITE(planner.max_acceleration_mm_per_s2);
2016-10-28 18:55:42 -05:00
EEPROM_WRITE(planner.acceleration);
EEPROM_WRITE(planner.retract_acceleration);
EEPROM_WRITE(planner.travel_acceleration);
EEPROM_WRITE(planner.min_feedrate_mm_s);
EEPROM_WRITE(planner.min_travel_feedrate_mm_s);
EEPROM_WRITE(planner.min_segment_time_us);
2016-10-28 18:55:42 -05:00
EEPROM_WRITE(planner.max_jerk);
2018-01-04 20:27:17 -06:00
_FIELD_TEST(home_offset);
#if !HAS_HOME_OFFSET
const float home_offset[XYZ] = { 0 };
#endif
EEPROM_WRITE(home_offset);
#if HOTENDS > 1
// Skip hotend 0 which must be 0
for (uint8_t e = 1; e < HOTENDS; e++)
2016-10-28 18:55:42 -05:00
LOOP_XYZ(i) EEPROM_WRITE(hotend_offset[i][e]);
#endif
//
// Global Leveling
//
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
const float zfh = planner.z_fade_height;
#else
const float zfh = 10.0;
#endif
EEPROM_WRITE(zfh);
2016-12-10 00:17:49 -06:00
//
// Mesh Bed Leveling
//
#if ENABLED(MESH_BED_LEVELING)
2016-10-28 18:55:42 -05:00
// Compile time test that sizeof(mbl.z_values) is as expected
static_assert(
2017-05-11 23:22:35 -05:00
sizeof(mbl.z_values) == GRID_MAX_POINTS * sizeof(mbl.z_values[0][0]),
"MBL Z array is the wrong size."
);
const uint8_t mesh_num_x = GRID_MAX_POINTS_X, mesh_num_y = GRID_MAX_POINTS_Y;
2016-10-28 18:55:42 -05:00
EEPROM_WRITE(mbl.z_offset);
EEPROM_WRITE(mesh_num_x);
EEPROM_WRITE(mesh_num_y);
EEPROM_WRITE(mbl.z_values);
#else // For disabled MBL write a default mesh
2016-10-28 18:55:42 -05:00
dummy = 0.0f;
2016-12-14 01:44:39 -06:00
const uint8_t mesh_num_x = 3, mesh_num_y = 3;
2016-12-10 00:17:49 -06:00
EEPROM_WRITE(dummy); // z_offset
2016-10-28 18:55:42 -05:00
EEPROM_WRITE(mesh_num_x);
EEPROM_WRITE(mesh_num_y);
2016-12-10 00:17:49 -06:00
for (uint8_t q = mesh_num_x * mesh_num_y; q--;) EEPROM_WRITE(dummy);
2015-04-26 23:06:04 -05:00
#endif // MESH_BED_LEVELING
2015-03-15 17:18:11 -05:00
2018-01-04 20:27:17 -06:00
_FIELD_TEST(zprobe_zoffset);
2016-06-14 20:05:20 -05:00
#if !HAS_BED_PROBE
const float zprobe_zoffset = 0;
#endif
2016-10-28 18:55:42 -05:00
EEPROM_WRITE(zprobe_zoffset);
2016-12-14 01:50:06 -06:00
//
// Planar Bed Leveling matrix
//
#if ABL_PLANAR
EEPROM_WRITE(planner.bed_level_matrix);
#else
dummy = 0.0;
for (uint8_t q = 9; q--;) EEPROM_WRITE(dummy);
#endif
2016-12-10 00:17:49 -06:00
//
// Bilinear Auto Bed Leveling
//
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
// Compile time test that sizeof(z_values) is as expected
static_assert(
2017-05-11 23:22:35 -05:00
sizeof(z_values) == GRID_MAX_POINTS * sizeof(z_values[0][0]),
"Bilinear Z array is the wrong size."
);
const uint8_t grid_max_x = GRID_MAX_POINTS_X, grid_max_y = GRID_MAX_POINTS_Y;
2016-12-10 00:17:49 -06:00
EEPROM_WRITE(grid_max_x); // 1 byte
EEPROM_WRITE(grid_max_y); // 1 byte
EEPROM_WRITE(bilinear_grid_spacing); // 2 ints
EEPROM_WRITE(bilinear_start); // 2 ints
EEPROM_WRITE(z_values); // 9-256 floats
2016-12-10 00:17:49 -06:00
#else
// For disabled Bilinear Grid write an empty 3x3 grid
const uint8_t grid_max_x = 3, grid_max_y = 3;
const int bilinear_start[2] = { 0 }, bilinear_grid_spacing[2] = { 0 };
dummy = 0.0f;
EEPROM_WRITE(grid_max_x);
EEPROM_WRITE(grid_max_y);
EEPROM_WRITE(bilinear_grid_spacing);
EEPROM_WRITE(bilinear_start);
for (uint16_t q = grid_max_x * grid_max_y; q--;) EEPROM_WRITE(dummy);
#endif // AUTO_BED_LEVELING_BILINEAR
2018-01-04 20:27:17 -06:00
_FIELD_TEST(planner_leveling_active);
#if ENABLED(AUTO_BED_LEVELING_UBL)
EEPROM_WRITE(planner.leveling_active);
2017-10-13 21:56:27 -05:00
EEPROM_WRITE(ubl.storage_slot);
#else
2017-05-16 02:34:36 -05:00
const bool ubl_active = false;
const int8_t storage_slot = -1;
EEPROM_WRITE(ubl_active);
EEPROM_WRITE(storage_slot);
2017-05-09 12:35:43 -05:00
#endif // AUTO_BED_LEVELING_UBL
2017-11-30 22:45:17 -06:00
// 11 floats for DELTA / [XYZ]_DUAL_ENDSTOPS
#if ENABLED(DELTA)
2018-01-09 18:33:44 -06:00
2018-01-04 20:27:17 -06:00
_FIELD_TEST(delta_height);
2018-01-09 18:33:44 -06:00
EEPROM_WRITE(delta_height); // 1 float
2017-09-24 02:18:15 -05:00
EEPROM_WRITE(delta_endstop_adj); // 3 floats
2016-10-28 18:55:42 -05:00
EEPROM_WRITE(delta_radius); // 1 float
EEPROM_WRITE(delta_diagonal_rod); // 1 float
EEPROM_WRITE(delta_segments_per_second); // 1 float
EEPROM_WRITE(delta_calibration_radius); // 1 float
2017-09-24 02:18:15 -05:00
EEPROM_WRITE(delta_tower_angle_trim); // 3 floats
#elif ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
2018-01-09 18:33:44 -06:00
2018-01-04 20:27:17 -06:00
_FIELD_TEST(x_endstop_adj);
2018-01-09 18:33:44 -06:00
// Write dual endstops in X, Y, Z order. Unused = 0.0
dummy = 0.0f;
#if ENABLED(X_DUAL_ENDSTOPS)
EEPROM_WRITE(endstops.x_endstop_adj); // 1 float
#else
EEPROM_WRITE(dummy);
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
EEPROM_WRITE(endstops.y_endstop_adj); // 1 float
#else
EEPROM_WRITE(dummy);
#endif
#if ENABLED(Z_DUAL_ENDSTOPS)
EEPROM_WRITE(endstops.z_endstop_adj); // 1 float
#else
EEPROM_WRITE(dummy);
#endif
#endif
2018-01-04 20:27:17 -06:00
_FIELD_TEST(lcd_preheat_hotend_temp);
#if DISABLED(ULTIPANEL)
2018-01-19 15:24:13 -06:00
constexpr int16_t lcd_preheat_hotend_temp[2] = { PREHEAT_1_TEMP_HOTEND, PREHEAT_2_TEMP_HOTEND },
lcd_preheat_bed_temp[2] = { PREHEAT_1_TEMP_BED, PREHEAT_2_TEMP_BED },
lcd_preheat_fan_speed[2] = { PREHEAT_1_FAN_SPEED, PREHEAT_2_FAN_SPEED };
2017-06-05 17:41:38 -05:00
#endif
2016-10-28 18:55:42 -05:00
EEPROM_WRITE(lcd_preheat_hotend_temp);
EEPROM_WRITE(lcd_preheat_bed_temp);
EEPROM_WRITE(lcd_preheat_fan_speed);
2016-10-28 18:55:42 -05:00
for (uint8_t e = 0; e < MAX_EXTRUDERS; e++) {
#if ENABLED(PIDTEMP)
if (e < HOTENDS) {
EEPROM_WRITE(PID_PARAM(Kp, e));
EEPROM_WRITE(PID_PARAM(Ki, e));
EEPROM_WRITE(PID_PARAM(Kd, e));
#if ENABLED(PID_EXTRUSION_SCALING)
2016-10-28 18:55:42 -05:00
EEPROM_WRITE(PID_PARAM(Kc, e));
#else
2016-10-28 18:55:42 -05:00
dummy = 1.0f; // 1.0 = default kc
EEPROM_WRITE(dummy);
#endif
}
2016-10-28 18:55:42 -05:00
else
#endif // !PIDTEMP
{
dummy = DUMMY_PID_VALUE; // When read, will not change the existing value
EEPROM_WRITE(dummy); // Kp
dummy = 0.0f;
for (uint8_t q = 3; q--;) EEPROM_WRITE(dummy); // Ki, Kd, Kc
}
2016-10-28 18:55:42 -05:00
} // Hotends Loop
2018-01-09 18:33:44 -06:00
_FIELD_TEST(lpq_len);
#if DISABLED(PID_EXTRUSION_SCALING)
2016-10-28 18:55:42 -05:00
int lpq_len = 20;
2015-08-30 21:04:30 -05:00
#endif
2016-10-28 18:55:42 -05:00
EEPROM_WRITE(lpq_len);
#if DISABLED(PIDTEMPBED)
dummy = DUMMY_PID_VALUE;
for (uint8_t q = 3; q--;) EEPROM_WRITE(dummy);
2016-04-28 20:18:13 -05:00
#else
2016-10-28 18:55:42 -05:00
EEPROM_WRITE(thermalManager.bedKp);
EEPROM_WRITE(thermalManager.bedKi);
EEPROM_WRITE(thermalManager.bedKd);
2015-04-03 18:38:05 -05:00
#endif
2018-01-04 20:27:17 -06:00
_FIELD_TEST(lcd_contrast);
2016-05-31 13:47:02 -05:00
#if !HAS_LCD_CONTRAST
const int16_t lcd_contrast = 32;
#endif
2016-10-28 18:55:42 -05:00
EEPROM_WRITE(lcd_contrast);
#if DISABLED(FWRETRACT)
const bool autoretract_enabled = false;
2017-09-07 22:40:32 -05:00
const float autoretract_defaults[] = { 3, 45, 0, 0, 0, 13, 0, 8 };
EEPROM_WRITE(autoretract_enabled);
EEPROM_WRITE(autoretract_defaults);
#else
EEPROM_WRITE(fwretract.autoretract_enabled);
EEPROM_WRITE(fwretract.retract_length);
EEPROM_WRITE(fwretract.retract_feedrate_mm_s);
EEPROM_WRITE(fwretract.retract_zlift);
EEPROM_WRITE(fwretract.retract_recover_length);
EEPROM_WRITE(fwretract.retract_recover_feedrate_mm_s);
EEPROM_WRITE(fwretract.swap_retract_length);
EEPROM_WRITE(fwretract.swap_retract_recover_length);
EEPROM_WRITE(fwretract.swap_retract_recover_feedrate_mm_s);
#endif
//
// Volumetric & Filament Size
//
2018-01-09 18:33:44 -06:00
2018-01-04 20:27:17 -06:00
_FIELD_TEST(parser_volumetric_enabled);
2018-01-09 18:33:44 -06:00
#if DISABLED(NO_VOLUMETRICS)
EEPROM_WRITE(parser.volumetric_enabled);
// Save filament sizes
for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
if (q < COUNT(planner.filament_size)) dummy = planner.filament_size[q];
EEPROM_WRITE(dummy);
}
2018-01-04 20:23:24 -06:00
#else
const bool volumetric_enabled = false;
dummy = DEFAULT_NOMINAL_FILAMENT_DIA;
EEPROM_WRITE(volumetric_enabled);
for (uint8_t q = MAX_EXTRUDERS; q--;) EEPROM_WRITE(dummy);
#endif
2018-01-04 19:47:42 -06:00
//
2017-12-15 15:03:14 -06:00
// Save TMC2130 or TMC2208 Configuration, and placeholder values
2018-01-04 19:47:42 -06:00
//
2018-01-09 18:33:44 -06:00
2018-01-04 20:27:17 -06:00
_FIELD_TEST(tmc_stepper_current);
2018-01-09 18:33:44 -06:00
2018-01-04 19:47:42 -06:00
uint16_t currents[11] = {
#if HAS_TRINAMIC
#if X_IS_TRINAMIC
stepperX.getCurrent(),
#else
0,
#endif
#if Y_IS_TRINAMIC
stepperY.getCurrent(),
#else
0,
#endif
#if Z_IS_TRINAMIC
stepperZ.getCurrent(),
#else
0,
#endif
#if X2_IS_TRINAMIC
stepperX2.getCurrent(),
#else
0,
#endif
#if Y2_IS_TRINAMIC
stepperY2.getCurrent(),
#else
0,
#endif
#if Z2_IS_TRINAMIC
stepperZ2.getCurrent(),
#else
0,
#endif
#if E0_IS_TRINAMIC
stepperE0.getCurrent(),
#else
0,
#endif
#if E1_IS_TRINAMIC
stepperE1.getCurrent(),
#else
0,
#endif
#if E2_IS_TRINAMIC
stepperE2.getCurrent(),
#else
0,
#endif
#if E3_IS_TRINAMIC
stepperE3.getCurrent(),
#else
0,
#endif
#if E4_IS_TRINAMIC
stepperE4.getCurrent()
#else
0
#endif
#else
2018-01-04 19:47:42 -06:00
0
#endif
2018-01-04 19:47:42 -06:00
};
EEPROM_WRITE(currents);
2017-12-15 15:03:14 -06:00
//
// TMC2130 Sensorless homing threshold
//
2018-02-25 21:02:22 -06:00
int16_t thrs[XYZ] = {
#if ENABLED(SENSORLESS_HOMING)
#if ENABLED(X_IS_TMC2130) && defined(X_HOMING_SENSITIVITY)
stepperX.sgt(),
#else
0,
#endif
#if ENABLED(Y_IS_TMC2130) && defined(Y_HOMING_SENSITIVITY)
stepperY.sgt(),
#else
0
#endif
#if ENABLED(Z_IS_TMC2130) && defined(Z_HOMING_SENSITIVITY)
stepperZ.sgt()
#else
0
#endif
#else
2018-02-25 21:02:22 -06:00
0
#endif
2018-02-25 21:02:22 -06:00
};
EEPROM_WRITE(thrs);
2017-12-15 15:03:14 -06:00
//
// Linear Advance
//
2018-01-09 18:33:44 -06:00
2018-02-23 00:53:29 -06:00
_FIELD_TEST(planner_extruder_advance_K);
2018-01-09 18:33:44 -06:00
#if ENABLED(LIN_ADVANCE)
2018-02-23 00:53:29 -06:00
EEPROM_WRITE(planner.extruder_advance_K);
#else
dummy = 0.0f;
EEPROM_WRITE(dummy);
#endif
2018-01-09 18:33:44 -06:00
_FIELD_TEST(motor_current_setting);
#if HAS_MOTOR_CURRENT_PWM
2018-02-25 21:02:22 -06:00
for (uint8_t q = XYZ; q--;) EEPROM_WRITE(stepper.motor_current_setting[q]);
#else
2018-02-25 21:02:22 -06:00
const uint32_t dummyui32[XYZ] = { 0 };
EEPROM_WRITE(dummyui32);
#endif
2017-12-01 16:42:23 -06:00
//
// CNC Coordinate Systems
//
2018-01-09 18:33:44 -06:00
2018-01-04 20:27:17 -06:00
_FIELD_TEST(coordinate_system);
2018-01-09 18:33:44 -06:00
2017-11-04 16:36:41 -05:00
#if ENABLED(CNC_COORDINATE_SYSTEMS)
EEPROM_WRITE(coordinate_system); // 27 floats
#else
dummy = 0.0f;
2018-01-04 19:59:43 -06:00
for (uint8_t q = MAX_COORDINATE_SYSTEMS * XYZ; q--;) EEPROM_WRITE(dummy);
2017-11-04 16:36:41 -05:00
#endif
2017-12-01 16:42:23 -06:00
//
// Skew correction factors
//
2018-01-09 18:33:44 -06:00
2018-01-04 20:27:17 -06:00
_FIELD_TEST(planner_xy_skew_factor);
2018-01-09 18:33:44 -06:00
2017-12-01 16:42:23 -06:00
#if ENABLED(SKEW_CORRECTION)
EEPROM_WRITE(planner.xy_skew_factor);
EEPROM_WRITE(planner.xz_skew_factor);
EEPROM_WRITE(planner.yz_skew_factor);
#else
dummy = 0.0f;
2018-02-25 21:02:22 -06:00
for (uint8_t q = XYZ; q--;) EEPROM_WRITE(dummy);
2017-12-01 16:42:23 -06:00
#endif
//
// Advanced Pause filament load & unload lengths
//
2018-01-09 18:33:44 -06:00
2018-01-04 20:27:17 -06:00
_FIELD_TEST(filament_change_unload_length);
2018-01-09 18:33:44 -06:00
#if ENABLED(ADVANCED_PAUSE_FEATURE)
for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
if (q < COUNT(filament_change_unload_length)) dummy = filament_change_unload_length[q];
EEPROM_WRITE(dummy);
}
for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
if (q < COUNT(filament_change_load_length)) dummy = filament_change_load_length[q];
EEPROM_WRITE(dummy);
}
#else
dummy = 0.0f;
for (uint8_t q = MAX_EXTRUDERS * 2; q--;) EEPROM_WRITE(dummy);
#endif
2018-01-04 19:51:18 -06:00
//
2018-01-04 20:01:25 -06:00
// Validate CRC and Data Size
2018-01-04 19:51:18 -06:00
//
if (!eeprom_error) {
2018-01-04 19:59:43 -06:00
const uint16_t eeprom_size = eeprom_index - (EEPROM_OFFSET),
final_crc = working_crc;
2017-05-11 09:48:16 -05:00
// Write the EEPROM header
eeprom_index = EEPROM_OFFSET;
2017-05-11 09:48:16 -05:00
EEPROM_WRITE(version);
EEPROM_WRITE(final_crc);
2016-10-28 18:55:42 -05:00
// Report storage size
2017-07-01 21:48:18 -05:00
#if ENABLED(EEPROM_CHITCHAT)
2017-11-05 08:49:38 -06:00
SERIAL_ECHO_START_P(port);
SERIAL_ECHOPAIR_P(port, "Settings Stored (", eeprom_size);
SERIAL_ECHOPAIR_P(port, " bytes; crc ", (uint32_t)final_crc);
SERIAL_ECHOLNPGM_P(port, ")");
2017-07-01 21:48:18 -05:00
#endif
2018-01-04 20:01:25 -06:00
eeprom_error |= size_error(eeprom_size);
}
EEPROM_FINISH();
2018-01-04 19:51:18 -06:00
//
// UBL Mesh
//
#if ENABLED(UBL_SAVE_ACTIVE_ON_M500)
2017-10-13 21:56:27 -05:00
if (ubl.storage_slot >= 0)
store_mesh(ubl.storage_slot);
2017-03-18 10:15:54 -05:00
#endif
return !eeprom_error;
2016-10-28 18:55:42 -05:00
}
/**
* M501 - Retrieve Configuration
*/
2017-11-05 08:49:38 -06:00
bool MarlinSettings::_load(
#if ADD_PORT_ARG
const int8_t port/*=-1*/
#endif
) {
uint16_t working_crc = 0;
2016-10-28 18:55:42 -05:00
EEPROM_START();
char stored_ver[4];
2018-01-04 19:51:18 -06:00
EEPROM_READ_ALWAYS(stored_ver);
2016-10-28 18:55:42 -05:00
uint16_t stored_crc;
2018-01-04 19:51:18 -06:00
EEPROM_READ_ALWAYS(stored_crc);
2016-10-28 18:55:42 -05:00
// Version has to match or defaults are used
2016-10-28 18:55:42 -05:00
if (strncmp(version, stored_ver, 3) != 0) {
2018-01-05 19:00:26 -06:00
if (stored_ver[3] != '\0') {
stored_ver[0] = '?';
stored_ver[1] = '\0';
}
2017-07-01 21:48:18 -05:00
#if ENABLED(EEPROM_CHITCHAT)
2017-11-05 08:49:38 -06:00
SERIAL_ECHO_START_P(port);
SERIAL_ECHOPGM_P(port, "EEPROM version mismatch ");
SERIAL_ECHOPAIR_P(port, "(EEPROM=", stored_ver);
SERIAL_ECHOLNPGM_P(port, " Marlin=" EEPROM_VERSION ")");
2017-07-01 21:48:18 -05:00
#endif
2018-01-04 19:51:18 -06:00
if (!validating) reset();
eeprom_error = true;
2016-06-29 20:12:23 -05:00
}
2016-10-28 18:55:42 -05:00
else {
float dummy = 0;
2018-02-17 08:27:54 -06:00
#if DISABLED(AUTO_BED_LEVELING_UBL) || DISABLED(FWRETRACT) || ENABLED(NO_VOLUMETRICS)
2018-01-02 21:00:06 -06:00
bool dummyb;
#endif
working_crc = 0; // Init to 0. Accumulated by EEPROM_READ
2016-10-28 18:55:42 -05:00
2018-01-09 18:33:44 -06:00
_FIELD_TEST(esteppers);
// Number of esteppers may change
uint8_t esteppers;
2018-01-04 19:51:18 -06:00
EEPROM_READ_ALWAYS(esteppers);
2017-11-04 15:34:24 -05:00
//
// Planner Motion
//
// Get only the number of E stepper parameters previously stored
// Any steppers added later are set to their defaults
const float def1[] = DEFAULT_AXIS_STEPS_PER_UNIT, def2[] = DEFAULT_MAX_FEEDRATE;
const uint32_t def3[] = DEFAULT_MAX_ACCELERATION;
float tmp1[XYZ + esteppers], tmp2[XYZ + esteppers];
uint32_t tmp3[XYZ + esteppers];
EEPROM_READ(tmp1);
EEPROM_READ(tmp2);
EEPROM_READ(tmp3);
2018-01-04 19:51:18 -06:00
if (!validating) LOOP_XYZE_N(i) {
planner.axis_steps_per_mm[i] = i < XYZ + esteppers ? tmp1[i] : def1[i < COUNT(def1) ? i : COUNT(def1) - 1];
planner.max_feedrate_mm_s[i] = i < XYZ + esteppers ? tmp2[i] : def2[i < COUNT(def2) ? i : COUNT(def2) - 1];
planner.max_acceleration_mm_per_s2[i] = i < XYZ + esteppers ? tmp3[i] : def3[i < COUNT(def3) ? i : COUNT(def3) - 1];
}
2016-10-28 18:55:42 -05:00
EEPROM_READ(planner.acceleration);
EEPROM_READ(planner.retract_acceleration);
EEPROM_READ(planner.travel_acceleration);
EEPROM_READ(planner.min_feedrate_mm_s);
EEPROM_READ(planner.min_travel_feedrate_mm_s);
EEPROM_READ(planner.min_segment_time_us);
2016-10-28 18:55:42 -05:00
EEPROM_READ(planner.max_jerk);
2017-03-04 18:01:33 -06:00
2017-11-04 15:34:24 -05:00
//
// Home Offset (M206)
//
2018-01-09 18:33:44 -06:00
_FIELD_TEST(home_offset);
#if !HAS_HOME_OFFSET
2017-03-04 18:01:33 -06:00
float home_offset[XYZ];
#endif
2016-10-28 18:55:42 -05:00
EEPROM_READ(home_offset);
2017-11-04 15:34:24 -05:00
//
// Hotend Offsets, if any
//
2016-10-28 18:55:42 -05:00
#if HOTENDS > 1
// Skip hotend 0 which must be 0
for (uint8_t e = 1; e < HOTENDS; e++)
LOOP_XYZ(i) EEPROM_READ(hotend_offset[i][e]);
#endif
//
// Global Leveling
//
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
EEPROM_READ(new_z_fade_height);
#else
EEPROM_READ(dummy);
#endif
2016-12-10 00:17:49 -06:00
//
// Mesh (Manual) Bed Leveling
//
2016-12-14 01:44:39 -06:00
uint8_t mesh_num_x, mesh_num_y;
2016-10-28 18:55:42 -05:00
EEPROM_READ(dummy);
2018-01-04 19:51:18 -06:00
EEPROM_READ_ALWAYS(mesh_num_x);
EEPROM_READ_ALWAYS(mesh_num_y);
2016-12-14 01:44:39 -06:00
2016-10-28 18:55:42 -05:00
#if ENABLED(MESH_BED_LEVELING)
2018-01-06 23:47:29 -06:00
if (!validating) mbl.z_offset = dummy;
if (mesh_num_x == GRID_MAX_POINTS_X && mesh_num_y == GRID_MAX_POINTS_Y) {
2016-10-28 18:55:42 -05:00
// EEPROM data fits the current mesh
EEPROM_READ(mbl.z_values);
}
else {
// EEPROM data is stale
2018-01-04 19:51:18 -06:00
if (!validating) mbl.reset();
2016-12-10 00:17:49 -06:00
for (uint16_t q = mesh_num_x * mesh_num_y; q--;) EEPROM_READ(dummy);
2016-10-28 18:55:42 -05:00
}
#else
// MBL is disabled - skip the stored data
2016-12-10 00:17:49 -06:00
for (uint16_t q = mesh_num_x * mesh_num_y; q--;) EEPROM_READ(dummy);
2016-10-28 18:55:42 -05:00
#endif // MESH_BED_LEVELING
2018-01-09 18:33:44 -06:00
_FIELD_TEST(zprobe_zoffset);
2016-10-28 18:55:42 -05:00
#if !HAS_BED_PROBE
float zprobe_zoffset;
2016-10-28 18:55:42 -05:00
#endif
EEPROM_READ(zprobe_zoffset);
2016-12-14 01:50:06 -06:00
//
// Planar Bed Leveling matrix
//
#if ABL_PLANAR
EEPROM_READ(planner.bed_level_matrix);
#else
for (uint8_t q = 9; q--;) EEPROM_READ(dummy);
#endif
2016-12-10 00:17:49 -06:00
//
// Bilinear Auto Bed Leveling
//
uint8_t grid_max_x, grid_max_y;
2018-01-04 19:51:18 -06:00
EEPROM_READ_ALWAYS(grid_max_x); // 1 byte
EEPROM_READ_ALWAYS(grid_max_y); // 1 byte
2016-12-10 00:17:49 -06:00
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
if (grid_max_x == GRID_MAX_POINTS_X && grid_max_y == GRID_MAX_POINTS_Y) {
2018-01-04 19:51:18 -06:00
if (!validating) set_bed_leveling_enabled(false);
2016-12-10 00:17:49 -06:00
EEPROM_READ(bilinear_grid_spacing); // 2 ints
EEPROM_READ(bilinear_start); // 2 ints
EEPROM_READ(z_values); // 9 to 256 floats
2016-12-10 00:17:49 -06:00
}
else // EEPROM data is stale
#endif // AUTO_BED_LEVELING_BILINEAR
{
// Skip past disabled (or stale) Bilinear Grid data
int bgs[2], bs[2];
EEPROM_READ(bgs);
EEPROM_READ(bs);
for (uint16_t q = grid_max_x * grid_max_y; q--;) EEPROM_READ(dummy);
}
2017-11-04 15:34:24 -05:00
//
// Unified Bed Leveling active state
//
2018-01-09 18:33:44 -06:00
_FIELD_TEST(planner_leveling_active);
#if ENABLED(AUTO_BED_LEVELING_UBL)
EEPROM_READ(planner.leveling_active);
2017-10-13 21:56:27 -05:00
EEPROM_READ(ubl.storage_slot);
#else
uint8_t dummyui8;
EEPROM_READ(dummyb);
EEPROM_READ(dummyui8);
2017-05-09 12:35:43 -05:00
#endif // AUTO_BED_LEVELING_UBL
2017-11-04 15:34:24 -05:00
//
// DELTA Geometry or Dual Endstops offsets
//
2016-10-28 18:55:42 -05:00
#if ENABLED(DELTA)
2018-01-09 18:33:44 -06:00
_FIELD_TEST(delta_height);
EEPROM_READ(delta_height); // 1 float
2017-09-24 02:18:15 -05:00
EEPROM_READ(delta_endstop_adj); // 3 floats
2017-03-07 17:42:04 -06:00
EEPROM_READ(delta_radius); // 1 float
EEPROM_READ(delta_diagonal_rod); // 1 float
EEPROM_READ(delta_segments_per_second); // 1 float
EEPROM_READ(delta_calibration_radius); // 1 float
2017-09-24 02:18:15 -05:00
EEPROM_READ(delta_tower_angle_trim); // 3 floats
#elif ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
2018-01-09 18:33:44 -06:00
_FIELD_TEST(x_endstop_adj);
#if ENABLED(X_DUAL_ENDSTOPS)
EEPROM_READ(endstops.x_endstop_adj); // 1 float
#else
EEPROM_READ(dummy);
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
EEPROM_READ(endstops.y_endstop_adj); // 1 float
#else
EEPROM_READ(dummy);
#endif
#if ENABLED(Z_DUAL_ENDSTOPS)
EEPROM_READ(endstops.z_endstop_adj); // 1 float
#else
EEPROM_READ(dummy);
#endif
2016-10-28 18:55:42 -05:00
#endif
2017-11-04 15:34:24 -05:00
//
// LCD Preheat settings
//
2018-01-09 18:33:44 -06:00
_FIELD_TEST(lcd_preheat_hotend_temp);
2016-10-28 18:55:42 -05:00
#if DISABLED(ULTIPANEL)
2018-01-19 15:24:13 -06:00
int16_t lcd_preheat_hotend_temp[2], lcd_preheat_bed_temp[2], lcd_preheat_fan_speed[2];
2016-10-28 18:55:42 -05:00
#endif
2017-11-04 15:34:24 -05:00
EEPROM_READ(lcd_preheat_hotend_temp); // 2 floats
EEPROM_READ(lcd_preheat_bed_temp); // 2 floats
EEPROM_READ(lcd_preheat_fan_speed); // 2 floats
2016-10-28 18:55:42 -05:00
2017-04-09 21:47:49 -05:00
//EEPROM_ASSERT(
// WITHIN(lcd_preheat_fan_speed, 0, 255),
// "lcd_preheat_fan_speed out of range"
//);
2017-11-04 15:34:24 -05:00
//
// Hotend PID
//
2016-10-28 18:55:42 -05:00
#if ENABLED(PIDTEMP)
for (uint8_t e = 0; e < MAX_EXTRUDERS; e++) {
EEPROM_READ(dummy); // Kp
if (e < HOTENDS && dummy != DUMMY_PID_VALUE) {
// do not need to scale PID values as the values in EEPROM are already scaled
2018-01-04 19:51:18 -06:00
if (!validating) PID_PARAM(Kp, e) = dummy;
2016-10-28 18:55:42 -05:00
EEPROM_READ(PID_PARAM(Ki, e));
EEPROM_READ(PID_PARAM(Kd, e));
#if ENABLED(PID_EXTRUSION_SCALING)
EEPROM_READ(PID_PARAM(Kc, e));
#else
EEPROM_READ(dummy);
#endif
}
else {
for (uint8_t q=3; q--;) EEPROM_READ(dummy); // Ki, Kd, Kc
}
}
#else // !PIDTEMP
// 4 x 4 = 16 slots for PID parameters
for (uint8_t q = MAX_EXTRUDERS * 4; q--;) EEPROM_READ(dummy); // Kp, Ki, Kd, Kc
#endif // !PIDTEMP
2017-11-04 15:34:24 -05:00
//
// PID Extrusion Scaling
//
2018-01-09 18:33:44 -06:00
_FIELD_TEST(lpq_len);
2016-10-28 18:55:42 -05:00
#if DISABLED(PID_EXTRUSION_SCALING)
int lpq_len;
#endif
EEPROM_READ(lpq_len);
2017-11-04 15:34:24 -05:00
//
// Heated Bed PID
//
2016-10-28 18:55:42 -05:00
#if ENABLED(PIDTEMPBED)
EEPROM_READ(dummy); // bedKp
if (dummy != DUMMY_PID_VALUE) {
2018-01-04 19:51:18 -06:00
if (!validating) thermalManager.bedKp = dummy;
2016-10-28 18:55:42 -05:00
EEPROM_READ(thermalManager.bedKi);
EEPROM_READ(thermalManager.bedKd);
}
#else
for (uint8_t q=3; q--;) EEPROM_READ(dummy); // bedKp, bedKi, bedKd
#endif
2017-11-04 15:34:24 -05:00
//
// LCD Contrast
//
2018-01-09 18:33:44 -06:00
_FIELD_TEST(lcd_contrast);
2016-10-28 18:55:42 -05:00
#if !HAS_LCD_CONTRAST
int16_t lcd_contrast;
2016-10-28 18:55:42 -05:00
#endif
EEPROM_READ(lcd_contrast);
2017-11-04 15:34:24 -05:00
//
// Firmware Retraction
//
2016-10-28 18:55:42 -05:00
#if ENABLED(FWRETRACT)
2017-09-07 22:40:32 -05:00
EEPROM_READ(fwretract.autoretract_enabled);
EEPROM_READ(fwretract.retract_length);
EEPROM_READ(fwretract.retract_feedrate_mm_s);
EEPROM_READ(fwretract.retract_zlift);
EEPROM_READ(fwretract.retract_recover_length);
EEPROM_READ(fwretract.retract_recover_feedrate_mm_s);
EEPROM_READ(fwretract.swap_retract_length);
EEPROM_READ(fwretract.swap_retract_recover_length);
EEPROM_READ(fwretract.swap_retract_recover_feedrate_mm_s);
#else
EEPROM_READ(dummyb);
for (uint8_t q=8; q--;) EEPROM_READ(dummy);
#endif
2016-10-28 18:55:42 -05:00
2017-11-04 15:34:24 -05:00
//
// Volumetric & Filament Size
//
2018-01-09 18:33:44 -06:00
_FIELD_TEST(parser_volumetric_enabled);
#if DISABLED(NO_VOLUMETRICS)
2016-10-28 18:55:42 -05:00
EEPROM_READ(parser.volumetric_enabled);
for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
EEPROM_READ(dummy);
2018-01-04 19:51:18 -06:00
if (!validating && q < COUNT(planner.filament_size))
planner.filament_size[q] = dummy;
}
2018-01-04 20:23:24 -06:00
#else
EEPROM_READ(dummyb);
for (uint8_t q=MAX_EXTRUDERS; q--;) EEPROM_READ(dummy);
#endif
2016-10-28 18:55:42 -05:00
2017-11-04 15:34:24 -05:00
//
// TMC2130 Stepper Current
//
2018-01-09 18:33:44 -06:00
_FIELD_TEST(tmc_stepper_current);
2017-12-15 15:03:14 -06:00
#if HAS_TRINAMIC
2018-01-09 18:33:44 -06:00
#define SET_CURR(N,Q) stepper##Q.setCurrent(currents[N] ? currents[N] : Q##_CURRENT, R_SENSE, HOLD_MULTIPLIER)
uint16_t currents[11];
EEPROM_READ(currents);
2018-01-04 19:51:18 -06:00
if (!validating) {
#if X_IS_TRINAMIC
SET_CURR(0, X);
#endif
#if Y_IS_TRINAMIC
SET_CURR(1, Y);
#endif
#if Z_IS_TRINAMIC
SET_CURR(2, Z);
#endif
#if X2_IS_TRINAMIC
SET_CURR(3, X2);
#endif
#if Y2_IS_TRINAMIC
SET_CURR(4, Y2);
#endif
#if Z2_IS_TRINAMIC
SET_CURR(5, Z2);
#endif
#if E0_IS_TRINAMIC
SET_CURR(6, E0);
#endif
#if E1_IS_TRINAMIC
SET_CURR(7, E1);
#endif
#if E2_IS_TRINAMIC
SET_CURR(8, E2);
#endif
#if E3_IS_TRINAMIC
SET_CURR(9, E3);
#endif
#if E4_IS_TRINAMIC
SET_CURR(10, E4);
#endif
}
#else
2018-01-04 19:51:18 -06:00
uint16_t val;
for (uint8_t q=11; q--;) EEPROM_READ(val);
#endif
2017-12-15 15:03:14 -06:00
/*
* TMC2130 Sensorless homing threshold.
* X and X2 use the same value
* Y and Y2 use the same value
2018-02-25 21:02:22 -06:00
* Z and Z2 use the same value
2017-12-15 15:03:14 -06:00
*/
2018-02-25 21:02:22 -06:00
int16_t thrs[XYZ];
EEPROM_READ(thrs);
2017-12-15 15:03:14 -06:00
#if ENABLED(SENSORLESS_HOMING)
2018-02-25 21:02:22 -06:00
if (!validating) {
#ifdef X_HOMING_SENSITIVITY
#if ENABLED(X_IS_TMC2130)
2018-02-25 21:02:22 -06:00
stepperX.sgt(thrs[0]);
#endif
#if ENABLED(X2_IS_TMC2130)
2018-02-25 21:02:22 -06:00
stepperX2.sgt(thrs[0]);
#endif
2018-02-25 21:02:22 -06:00
#endif
#ifdef Y_HOMING_SENSITIVITY
#if ENABLED(Y_IS_TMC2130)
2018-02-25 21:02:22 -06:00
stepperY.sgt(thrs[1]);
#endif
#if ENABLED(Y2_IS_TMC2130)
2018-02-25 21:02:22 -06:00
stepperY2.sgt(thrs[1]);
#endif
2018-02-25 21:02:22 -06:00
#endif
#ifdef Z_HOMING_SENSITIVITY
#if ENABLED(Z_IS_TMC2130)
2018-02-25 21:02:22 -06:00
stepperZ.sgt(thrs[2]);
#endif
#if ENABLED(Z2_IS_TMC2130)
2018-02-25 21:02:22 -06:00
stepperZ2.sgt(thrs[2]);
#endif
2018-02-25 21:02:22 -06:00
#endif
}
2017-12-15 15:03:14 -06:00
#endif
//
// Linear Advance
//
2018-02-23 00:53:29 -06:00
_FIELD_TEST(planner_extruder_advance_K);
2018-01-09 18:33:44 -06:00
#if ENABLED(LIN_ADVANCE)
2018-02-23 00:53:29 -06:00
EEPROM_READ(planner.extruder_advance_K);
#else
EEPROM_READ(dummy);
#endif
2017-11-04 15:34:24 -05:00
//
// Motor Current PWM
//
2018-01-09 18:33:44 -06:00
_FIELD_TEST(motor_current_setting);
#if HAS_MOTOR_CURRENT_PWM
2018-02-25 21:02:22 -06:00
for (uint8_t q = XYZ; q--;) EEPROM_READ(stepper.motor_current_setting[q]);
#else
2018-02-25 21:02:22 -06:00
uint32_t dummyui32[XYZ];
EEPROM_READ(dummyui32);
#endif
2017-11-04 16:36:41 -05:00
//
// CNC Coordinate System
//
2018-01-09 18:33:44 -06:00
_FIELD_TEST(coordinate_system);
2017-11-04 16:36:41 -05:00
#if ENABLED(CNC_COORDINATE_SYSTEMS)
2018-01-04 19:51:18 -06:00
if (!validating) (void)gcode.select_coordinate_system(-1); // Go back to machine space
2017-11-04 16:36:41 -05:00
EEPROM_READ(gcode.coordinate_system); // 27 floats
#else
2018-01-04 19:59:43 -06:00
for (uint8_t q = MAX_COORDINATE_SYSTEMS * XYZ; q--;) EEPROM_READ(dummy);
2017-11-04 16:36:41 -05:00
#endif
2017-12-01 16:42:23 -06:00
//
// Skew correction factors
//
2018-01-09 18:33:44 -06:00
_FIELD_TEST(planner_xy_skew_factor);
2017-12-01 16:42:23 -06:00
#if ENABLED(SKEW_CORRECTION_GCODE)
EEPROM_READ(planner.xy_skew_factor);
#if ENABLED(SKEW_CORRECTION_FOR_Z)
EEPROM_READ(planner.xz_skew_factor);
EEPROM_READ(planner.yz_skew_factor);
#else
EEPROM_READ(dummy);
EEPROM_READ(dummy);
#endif
#else
2018-02-25 21:02:22 -06:00
for (uint8_t q = XYZ; q--;) EEPROM_READ(dummy);
2017-12-01 16:42:23 -06:00
#endif
//
// Advanced Pause filament load & unload lengths
//
2018-01-09 18:33:44 -06:00
_FIELD_TEST(filament_change_unload_length);
#if ENABLED(ADVANCED_PAUSE_FEATURE)
for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
EEPROM_READ(dummy);
2018-01-04 19:51:18 -06:00
if (!validating && q < COUNT(filament_change_unload_length)) filament_change_unload_length[q] = dummy;
}
for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
EEPROM_READ(dummy);
2018-01-04 19:51:18 -06:00
if (!validating && q < COUNT(filament_change_load_length)) filament_change_load_length[q] = dummy;
}
#else
for (uint8_t q = MAX_EXTRUDERS * 2; q--;) EEPROM_READ(dummy);
#endif
2018-01-04 20:01:25 -06:00
eeprom_error = size_error(eeprom_index - (EEPROM_OFFSET));
if (eeprom_error) {
2017-11-05 08:49:38 -06:00
SERIAL_ECHO_START_P(port);
SERIAL_ECHOPAIR_P(port, "Index: ", int(eeprom_index - (EEPROM_OFFSET)));
SERIAL_ECHOLNPAIR_P(port, " Size: ", datasize());
2016-10-28 18:55:42 -05:00
}
2018-01-04 20:01:25 -06:00
else if (working_crc != stored_crc) {
eeprom_error = true;
2017-07-01 21:48:18 -05:00
#if ENABLED(EEPROM_CHITCHAT)
2017-11-05 08:49:38 -06:00
SERIAL_ERROR_START_P(port);
SERIAL_ERRORPGM_P(port, "EEPROM CRC mismatch - (stored) ");
SERIAL_ERROR_P(port, stored_crc);
SERIAL_ERRORPGM_P(port, " != ");
SERIAL_ERROR_P(port, working_crc);
SERIAL_ERRORLNPGM_P(port, " (calculated)!");
2017-07-01 21:48:18 -05:00
#endif
2018-01-04 20:01:25 -06:00
}
else if (!validating) {
#if ENABLED(EEPROM_CHITCHAT)
2017-11-05 08:49:38 -06:00
SERIAL_ECHO_START_P(port);
SERIAL_ECHO_P(port, version);
SERIAL_ECHOPAIR_P(port, " stored settings retrieved (", eeprom_index - (EEPROM_OFFSET));
SERIAL_ECHOPAIR_P(port, " bytes; crc ", (uint32_t)working_crc);
SERIAL_ECHOLNPGM_P(port, ")");
2018-01-04 20:01:25 -06:00
#endif
}
if (!validating) {
if (eeprom_error) reset(); else postprocess();
2016-10-28 18:55:42 -05:00
}
2017-03-18 10:15:54 -05:00
#if ENABLED(AUTO_BED_LEVELING_UBL)
2017-05-16 02:34:36 -05:00
ubl.report_state();
2017-03-18 10:15:54 -05:00
2018-01-04 19:51:18 -06:00
if (!validating) {
if (!ubl.sanity_check()) {
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
2018-01-04 19:51:18 -06:00
#if ENABLED(EEPROM_CHITCHAT)
ubl.echo_name();
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, " initialized.\n");
2018-01-04 19:51:18 -06:00
#endif
}
else {
eeprom_error = true;
#if ENABLED(EEPROM_CHITCHAT)
2017-11-05 08:49:38 -06:00
SERIAL_PROTOCOLPGM_P(port, "?Can't enable ");
2018-01-04 19:51:18 -06:00
ubl.echo_name();
2017-11-05 08:49:38 -06:00
SERIAL_PROTOCOLLNPGM_P(port, ".");
2018-01-04 19:51:18 -06:00
#endif
ubl.reset();
}
2017-03-18 10:15:54 -05:00
2018-01-04 19:51:18 -06:00
if (ubl.storage_slot >= 0) {
load_mesh(ubl.storage_slot);
#if ENABLED(EEPROM_CHITCHAT)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, "Mesh ", ubl.storage_slot);
SERIAL_ECHOLNPGM_P(port, " loaded from storage.");
2018-01-04 19:51:18 -06:00
#endif
}
else {
ubl.reset();
#if ENABLED(EEPROM_CHITCHAT)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "UBL System reset()");
2018-01-04 19:51:18 -06:00
#endif
}
2017-03-18 10:15:54 -05:00
}
#endif
}
#if ENABLED(EEPROM_CHITCHAT) && DISABLED(DISABLE_M503)
2017-11-05 08:49:38 -06:00
if (!validating) report(
2018-01-22 06:27:22 -06:00
#if ADD_PORT_ARG
2017-11-05 08:49:38 -06:00
port
#endif
);
2016-10-28 18:55:42 -05:00
#endif
EEPROM_FINISH();
return !eeprom_error;
2016-10-28 18:55:42 -05:00
}
2017-11-05 08:49:38 -06:00
bool MarlinSettings::validate(
2018-01-22 06:27:22 -06:00
#if ADD_PORT_ARG
2017-11-05 08:49:38 -06:00
const int8_t port/*=-1*/
#endif
) {
2018-01-04 19:51:18 -06:00
validating = true;
2017-11-05 08:49:38 -06:00
const bool success = _load(
2018-01-22 06:27:22 -06:00
#if ADD_PORT_ARG
2017-11-05 08:49:38 -06:00
port
#endif
);
2018-01-04 19:51:18 -06:00
validating = false;
return success;
}
2017-11-05 08:49:38 -06:00
bool MarlinSettings::load(
#if ADD_PORT_ARG
const int8_t port/*=-1*/
#endif
) {
if (validate(
#if ADD_PORT_ARG
port
#endif
)) return _load(
2017-11-05 08:49:38 -06:00
#if ADD_PORT_ARG
port
#endif
);
2018-01-04 19:51:18 -06:00
reset();
return true;
}
#if ENABLED(AUTO_BED_LEVELING_UBL)
2017-07-01 21:48:18 -05:00
#if ENABLED(EEPROM_CHITCHAT)
void ubl_invalid_slot(const int s) {
SERIAL_PROTOCOLLNPGM("?Invalid slot.");
SERIAL_PROTOCOL(s);
SERIAL_PROTOCOLLNPGM(" mesh slots available.");
}
#endif
2017-05-16 02:34:36 -05:00
2018-01-04 21:09:56 -06:00
int16_t MarlinSettings::meshes_start_index() {
return (datasize() + EEPROM_OFFSET + 32) & 0xFFF8; // Pad the end of configuration data so it can float up
// or down a little bit without disrupting the mesh data
}
2018-01-04 21:09:56 -06:00
uint16_t MarlinSettings::calc_num_meshes() {
return (meshes_end - meshes_start_index()) / sizeof(ubl.z_values);
}
int MarlinSettings::mesh_slot_offset(const int8_t slot) {
return meshes_end - (slot + 1) * sizeof(ubl.z_values);
}
void MarlinSettings::store_mesh(const int8_t slot) {
#if ENABLED(AUTO_BED_LEVELING_UBL)
const int16_t a = calc_num_meshes();
if (!WITHIN(slot, 0, a - 1)) {
2017-07-01 21:48:18 -05:00
#if ENABLED(EEPROM_CHITCHAT)
ubl_invalid_slot(a);
SERIAL_PROTOCOLPAIR("E2END=", E2END);
SERIAL_PROTOCOLPAIR(" meshes_end=", meshes_end);
SERIAL_PROTOCOLLNPAIR(" slot=", slot);
SERIAL_EOL();
#endif
return;
}
int pos = mesh_slot_offset(slot);
uint16_t crc = 0;
HAL::PersistentStore::access_start();
const bool status = HAL::PersistentStore::write_data(pos, (uint8_t *)&ubl.z_values, sizeof(ubl.z_values), &crc);
HAL::PersistentStore::access_finish();
if (status)
2018-01-23 21:17:33 -06:00
SERIAL_PROTOCOLPGM("?Unable to save mesh data.\n");
// Write crc to MAT along with other data, or just tack on to the beginning or end
2017-07-01 21:48:18 -05:00
#if ENABLED(EEPROM_CHITCHAT)
if (!status)
SERIAL_PROTOCOLLNPAIR("Mesh saved in slot ", slot);
2017-07-01 21:48:18 -05:00
#endif
#else
// Other mesh types
#endif
}
void MarlinSettings::load_mesh(const int8_t slot, void * const into/*=NULL*/) {
#if ENABLED(AUTO_BED_LEVELING_UBL)
const int16_t a = settings.calc_num_meshes();
if (!WITHIN(slot, 0, a - 1)) {
2017-07-01 21:48:18 -05:00
#if ENABLED(EEPROM_CHITCHAT)
ubl_invalid_slot(a);
#endif
return;
}
int pos = mesh_slot_offset(slot);
uint16_t crc = 0;
uint8_t * const dest = into ? (uint8_t*)into : (uint8_t*)&ubl.z_values;
HAL::PersistentStore::access_start();
const uint16_t status = HAL::PersistentStore::read_data(pos, dest, sizeof(ubl.z_values), &crc);
HAL::PersistentStore::access_finish();
if (status)
2018-01-23 21:17:33 -06:00
SERIAL_PROTOCOLPGM("?Unable to load mesh data.\n");
2017-07-01 21:48:18 -05:00
#if ENABLED(EEPROM_CHITCHAT)
else
SERIAL_PROTOCOLLNPAIR("Mesh loaded from slot ", slot);
2017-07-01 21:48:18 -05:00
#endif
EEPROM_FINISH();
#else
// Other mesh types
#endif
}
//void MarlinSettings::delete_mesh() { return; }
//void MarlinSettings::defrag_meshes() { return; }
#endif // AUTO_BED_LEVELING_UBL
#else // !EEPROM_SETTINGS
2017-11-05 08:49:38 -06:00
bool MarlinSettings::save(
#if ADD_PORT_ARG
const int8_t port/*=-1*/
#endif
) {
#if ENABLED(EEPROM_CHITCHAT)
SERIAL_ERROR_START_P(port);
SERIAL_ERRORLNPGM_P(port, "EEPROM disabled");
#endif
return false;
}
#endif // !EEPROM_SETTINGS
/**
* M502 - Reset Configuration
*/
2017-11-05 08:49:38 -06:00
void MarlinSettings::reset(
#if ADD_PORT_ARG
const int8_t port/*=-1*/
#endif
) {
static const float tmp1[] PROGMEM = DEFAULT_AXIS_STEPS_PER_UNIT, tmp2[] PROGMEM = DEFAULT_MAX_FEEDRATE;
static const uint32_t tmp3[] PROGMEM = DEFAULT_MAX_ACCELERATION;
2016-12-03 22:02:27 -06:00
LOOP_XYZE_N(i) {
planner.axis_steps_per_mm[i] = pgm_read_float(&tmp1[i < COUNT(tmp1) ? i : COUNT(tmp1) - 1]);
planner.max_feedrate_mm_s[i] = pgm_read_float(&tmp2[i < COUNT(tmp2) ? i : COUNT(tmp2) - 1]);
2017-06-08 16:15:02 -05:00
planner.max_acceleration_mm_per_s2[i] = pgm_read_dword_near(&tmp3[i < COUNT(tmp3) ? i : COUNT(tmp3) - 1]);
}
2016-04-27 20:06:32 -05:00
planner.acceleration = DEFAULT_ACCELERATION;
planner.retract_acceleration = DEFAULT_RETRACT_ACCELERATION;
planner.travel_acceleration = DEFAULT_TRAVEL_ACCELERATION;
2016-07-15 20:49:34 -05:00
planner.min_feedrate_mm_s = DEFAULT_MINIMUMFEEDRATE;
planner.min_travel_feedrate_mm_s = DEFAULT_MINTRAVELFEEDRATE;
planner.min_segment_time_us = DEFAULT_MINSEGMENTTIME;
planner.max_jerk[X_AXIS] = DEFAULT_XJERK;
planner.max_jerk[Y_AXIS] = DEFAULT_YJERK;
planner.max_jerk[Z_AXIS] = DEFAULT_ZJERK;
planner.max_jerk[E_AXIS] = DEFAULT_EJERK;
#if HAS_HOME_OFFSET
2017-03-04 18:01:33 -06:00
ZERO(home_offset);
#endif
#if HOTENDS > 1
constexpr float tmp4[XYZ][HOTENDS] = {
HOTEND_OFFSET_X,
HOTEND_OFFSET_Y
#ifdef HOTEND_OFFSET_Z
, HOTEND_OFFSET_Z
#else
, { 0 }
#endif
};
static_assert(
tmp4[X_AXIS][0] == 0 && tmp4[Y_AXIS][0] == 0 && tmp4[Z_AXIS][0] == 0,
"Offsets for the first hotend must be 0.0."
);
LOOP_XYZ(i) HOTEND_LOOP() hotend_offset[i][e] = tmp4[i][e];
#endif
//
// Global Leveling
//
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
new_z_fade_height = 0.0;
#endif
2017-05-01 16:13:09 -05:00
#if HAS_LEVELING
2016-12-10 00:17:49 -06:00
reset_bed_level();
2015-03-26 01:06:33 -05:00
#endif
2016-06-14 20:05:20 -05:00
#if HAS_BED_PROBE
zprobe_zoffset = Z_PROBE_OFFSET_FROM_EXTRUDER;
2015-03-26 01:06:33 -05:00
#endif
2015-03-15 17:18:11 -05:00
#if ENABLED(DELTA)
2017-03-07 17:42:04 -06:00
const float adj[ABC] = DELTA_ENDSTOP_ADJ,
dta[ABC] = DELTA_TOWER_ANGLE_TRIM;
delta_height = DELTA_HEIGHT;
2017-09-08 15:35:25 -05:00
COPY(delta_endstop_adj, adj);
2016-12-10 00:17:49 -06:00
delta_radius = DELTA_RADIUS;
delta_diagonal_rod = DELTA_DIAGONAL_ROD;
delta_segments_per_second = DELTA_SEGMENTS_PER_SECOND;
delta_calibration_radius = DELTA_CALIBRATION_RADIUS;
2017-09-24 02:18:15 -05:00
COPY(delta_tower_angle_trim, dta);
#elif ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
#if ENABLED(X_DUAL_ENDSTOPS)
endstops.x_endstop_adj = (
#ifdef X_DUAL_ENDSTOPS_ADJUSTMENT
X_DUAL_ENDSTOPS_ADJUSTMENT
#else
0
#endif
);
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
endstops.y_endstop_adj = (
#ifdef Y_DUAL_ENDSTOPS_ADJUSTMENT
Y_DUAL_ENDSTOPS_ADJUSTMENT
#else
0
#endif
);
#endif
#if ENABLED(Z_DUAL_ENDSTOPS)
endstops.z_endstop_adj = (
#ifdef Z_DUAL_ENDSTOPS_ADJUSTMENT
Z_DUAL_ENDSTOPS_ADJUSTMENT
#else
0
#endif
);
#endif
#endif
#if ENABLED(ULTIPANEL)
lcd_preheat_hotend_temp[0] = PREHEAT_1_TEMP_HOTEND;
lcd_preheat_hotend_temp[1] = PREHEAT_2_TEMP_HOTEND;
lcd_preheat_bed_temp[0] = PREHEAT_1_TEMP_BED;
lcd_preheat_bed_temp[1] = PREHEAT_2_TEMP_BED;
lcd_preheat_fan_speed[0] = PREHEAT_1_FAN_SPEED;
lcd_preheat_fan_speed[1] = PREHEAT_2_FAN_SPEED;
#endif
#if ENABLED(PIDTEMP)
#if ENABLED(PID_PARAMS_PER_HOTEND) && HOTENDS > 1
HOTEND_LOOP()
#endif
{
PID_PARAM(Kp, e) = DEFAULT_Kp;
PID_PARAM(Ki, e) = scalePID_i(DEFAULT_Ki);
PID_PARAM(Kd, e) = scalePID_d(DEFAULT_Kd);
#if ENABLED(PID_EXTRUSION_SCALING)
PID_PARAM(Kc, e) = DEFAULT_Kc;
#endif
}
#if ENABLED(PID_EXTRUSION_SCALING)
2015-08-30 21:04:30 -05:00
lpq_len = 20; // default last-position-queue size
#endif
#endif // PIDTEMP
#if ENABLED(PIDTEMPBED)
2016-04-28 20:18:13 -05:00
thermalManager.bedKp = DEFAULT_bedKp;
thermalManager.bedKi = scalePID_i(DEFAULT_bedKi);
thermalManager.bedKd = scalePID_d(DEFAULT_bedKd);
2015-04-03 18:38:05 -05:00
#endif
#if HAS_LCD_CONTRAST
lcd_contrast = DEFAULT_LCD_CONTRAST;
#endif
#if ENABLED(FWRETRACT)
2017-09-07 22:40:32 -05:00
fwretract.reset();
#endif
#if DISABLED(NO_VOLUMETRICS)
parser.volumetric_enabled =
#if ENABLED(VOLUMETRIC_DEFAULT_ON)
true
#else
false
#endif
;
for (uint8_t q = 0; q < COUNT(planner.filament_size); q++)
planner.filament_size[q] = DEFAULT_NOMINAL_FILAMENT_DIA;
#endif
endstops.enable_globally(
#if ENABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)
true
#else
false
#endif
);
2017-12-15 15:03:14 -06:00
#if X_IS_TRINAMIC
stepperX.setCurrent(X_CURRENT, R_SENSE, HOLD_MULTIPLIER);
#endif
#if Y_IS_TRINAMIC
stepperY.setCurrent(Y_CURRENT, R_SENSE, HOLD_MULTIPLIER);
#endif
#if Z_IS_TRINAMIC
stepperZ.setCurrent(Z_CURRENT, R_SENSE, HOLD_MULTIPLIER);
#endif
#if X2_IS_TRINAMIC
stepperX2.setCurrent(X2_CURRENT, R_SENSE, HOLD_MULTIPLIER);
#endif
#if Y2_IS_TRINAMIC
stepperY2.setCurrent(Y2_CURRENT, R_SENSE, HOLD_MULTIPLIER);
#endif
#if Z2_IS_TRINAMIC
stepperZ2.setCurrent(Z2_CURRENT, R_SENSE, HOLD_MULTIPLIER);
#endif
#if E0_IS_TRINAMIC
stepperE0.setCurrent(E0_CURRENT, R_SENSE, HOLD_MULTIPLIER);
#endif
#if E1_IS_TRINAMIC
stepperE1.setCurrent(E1_CURRENT, R_SENSE, HOLD_MULTIPLIER);
#endif
#if E2_IS_TRINAMIC
stepperE2.setCurrent(E2_CURRENT, R_SENSE, HOLD_MULTIPLIER);
#endif
#if E3_IS_TRINAMIC
stepperE3.setCurrent(E3_CURRENT, R_SENSE, HOLD_MULTIPLIER);
#endif
#if E4_IS_TRINAMIC
stepperE4.setCurrent(E4_CURRENT, R_SENSE, HOLD_MULTIPLIER);
#endif
#if ENABLED(SENSORLESS_HOMING)
#ifdef X_HOMING_SENSITIVITY
#if ENABLED(X_IS_TMC2130)
stepperX.sgt(X_HOMING_SENSITIVITY);
#endif
#if ENABLED(X2_IS_TMC2130)
stepperX2.sgt(X_HOMING_SENSITIVITY);
#endif
#endif
#ifdef Y_HOMING_SENSITIVITY
#if ENABLED(Y_IS_TMC2130)
stepperY.sgt(Y_HOMING_SENSITIVITY);
#endif
#if ENABLED(Y2_IS_TMC2130)
stepperY2.sgt(Y_HOMING_SENSITIVITY);
#endif
#endif
#ifdef Z_HOMING_SENSITIVITY
#if ENABLED(Z_IS_TMC2130)
stepperZ.sgt(Z_HOMING_SENSITIVITY);
#endif
#if ENABLED(Z2_IS_TMC2130)
stepperZ2.sgt(Z_HOMING_SENSITIVITY);
#endif
#endif
#endif
#if ENABLED(LIN_ADVANCE)
2018-02-23 00:53:29 -06:00
planner.extruder_advance_K = LIN_ADVANCE_K;
#endif
#if HAS_MOTOR_CURRENT_PWM
2018-02-25 21:02:22 -06:00
uint32_t tmp_motor_current_setting[XYZ] = PWM_MOTOR_CURRENT;
for (uint8_t q = XYZ; q--;)
stepper.digipot_current(q, (stepper.motor_current_setting[q] = tmp_motor_current_setting[q]));
#endif
2017-12-01 16:42:23 -06:00
#if ENABLED(SKEW_CORRECTION_GCODE)
planner.xy_skew_factor = XY_SKEW_FACTOR;
#if ENABLED(SKEW_CORRECTION_FOR_Z)
planner.xz_skew_factor = XZ_SKEW_FACTOR;
planner.yz_skew_factor = YZ_SKEW_FACTOR;
#endif
#endif
#if ENABLED(ADVANCED_PAUSE_FEATURE)
for (uint8_t e = 0; e < E_STEPPERS; e++) {
filament_change_unload_length[e] = FILAMENT_CHANGE_UNLOAD_LENGTH;
filament_change_load_length[e] = FILAMENT_CHANGE_LOAD_LENGTH;
}
#endif
2017-04-09 21:47:49 -05:00
postprocess();
2017-07-01 21:48:18 -05:00
#if ENABLED(EEPROM_CHITCHAT)
2017-11-05 08:49:38 -06:00
SERIAL_ECHO_START_P(port);
SERIAL_ECHOLNPGM_P(port, "Hardcoded Default Settings Loaded");
2017-07-01 21:48:18 -05:00
#endif
}
#if DISABLED(DISABLE_M503)
#if ADD_PORT_ARG
#define CONFIG_ECHO_START do{ if (!forReplay) SERIAL_ECHO_START_P(port); }while(0)
#else
#define CONFIG_ECHO_START do{ if (!forReplay) SERIAL_ECHO_START(); }while(0)
#endif
2016-10-28 18:55:42 -05:00
/**
2017-04-09 21:47:49 -05:00
* M503 - Report current settings in RAM
*
2017-04-09 21:47:49 -05:00
* Unless specifically disabled, M503 is available even without EEPROM
2016-10-28 18:55:42 -05:00
*/
2017-11-05 08:49:38 -06:00
void MarlinSettings::report(const bool forReplay
#if NUM_SERIAL > 1
2017-11-05 08:49:38 -06:00
, const int8_t port/*=-1*/
#endif
) {
/**
* Announce current units, in case inches are being displayed
*/
CONFIG_ECHO_START;
#if ENABLED(INCH_MODE_SUPPORT)
#define LINEAR_UNIT(N) (float(N) / parser.linear_unit_factor)
#define VOLUMETRIC_UNIT(N) (float(N) / (parser.volumetric_enabled ? parser.volumetric_unit_factor : parser.linear_unit_factor))
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPGM_P(port, " G2");
SERIAL_CHAR_P(port, parser.linear_unit_factor == 1.0 ? '1' : '0');
SERIAL_ECHOPGM_P(port, " ; Units in ");
2017-05-20 03:03:08 -05:00
serialprintPGM(parser.linear_unit_factor == 1.0 ? PSTR("mm\n") : PSTR("inches\n"));
#else
#define LINEAR_UNIT(N) (N)
#define VOLUMETRIC_UNIT(N) (N)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, " G21 ; Units in mm");
#endif
2017-05-06 19:41:50 -05:00
#if ENABLED(ULTIPANEL)
// Temperature units - for Ultipanel temperature options
CONFIG_ECHO_START;
#if ENABLED(TEMPERATURE_UNITS_SUPPORT)
2017-05-20 03:03:08 -05:00
#define TEMP_UNIT(N) parser.to_temp_units(N)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPGM_P(port, " M149 ");
SERIAL_CHAR_P(port, parser.temp_units_code());
SERIAL_ECHOPGM_P(port, " ; Units in ");
serialprintPGM_P(port, parser.temp_units_name());
2017-05-06 19:41:50 -05:00
#else
#define TEMP_UNIT(N) (N)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, " M149 C ; Units in Celsius");
2017-05-06 19:41:50 -05:00
#endif
#endif
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
2017-05-25 18:02:29 -05:00
#if DISABLED(NO_VOLUMETRICS)
/**
* Volumetric extrusion M200
*/
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPGM_P(port, "Filament settings:");
if (parser.volumetric_enabled)
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
else
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, " Disabled");
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M200 D", LINEAR_UNIT(planner.filament_size[0]));
SERIAL_EOL_P(port);
#if EXTRUDERS > 1
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M200 T1 D", LINEAR_UNIT(planner.filament_size[1]));
SERIAL_EOL_P(port);
#if EXTRUDERS > 2
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M200 T2 D", LINEAR_UNIT(planner.filament_size[2]));
SERIAL_EOL_P(port);
#if EXTRUDERS > 3
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M200 T3 D", LINEAR_UNIT(planner.filament_size[3]));
SERIAL_EOL_P(port);
#if EXTRUDERS > 4
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M200 T4 D", LINEAR_UNIT(planner.filament_size[4]));
SERIAL_EOL_P(port);
#endif // EXTRUDERS > 4
#endif // EXTRUDERS > 3
#endif // EXTRUDERS > 2
#endif // EXTRUDERS > 1
if (!parser.volumetric_enabled) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, " M200 D0");
}
#endif // !NO_VOLUMETRICS
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Steps per unit:");
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M92 X", LINEAR_UNIT(planner.axis_steps_per_mm[X_AXIS]));
SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(planner.axis_steps_per_mm[Y_AXIS]));
SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(planner.axis_steps_per_mm[Z_AXIS]));
2016-12-11 19:37:29 -06:00
#if DISABLED(DISTINCT_E_FACTORS)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " E", VOLUMETRIC_UNIT(planner.axis_steps_per_mm[E_AXIS]));
2016-12-03 22:02:27 -06:00
#endif
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
2016-12-03 22:02:27 -06:00
#if ENABLED(DISTINCT_E_FACTORS)
CONFIG_ECHO_START;
2016-12-03 22:02:27 -06:00
for (uint8_t i = 0; i < E_STEPPERS; i++) {
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M92 T", (int)i);
SERIAL_ECHOLNPAIR_P(port, " E", VOLUMETRIC_UNIT(planner.axis_steps_per_mm[E_AXIS + i]));
2016-12-03 22:02:27 -06:00
}
#endif
2016-10-28 18:55:42 -05:00
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Maximum feedrates (units/s):");
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M203 X", LINEAR_UNIT(planner.max_feedrate_mm_s[X_AXIS]));
SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(planner.max_feedrate_mm_s[Y_AXIS]));
SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(planner.max_feedrate_mm_s[Z_AXIS]));
2016-12-11 19:37:29 -06:00
#if DISABLED(DISTINCT_E_FACTORS)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " E", VOLUMETRIC_UNIT(planner.max_feedrate_mm_s[E_AXIS]));
2016-12-03 22:02:27 -06:00
#endif
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
2016-12-03 22:02:27 -06:00
#if ENABLED(DISTINCT_E_FACTORS)
CONFIG_ECHO_START;
2016-12-03 22:02:27 -06:00
for (uint8_t i = 0; i < E_STEPPERS; i++) {
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M203 T", (int)i);
SERIAL_ECHOLNPAIR_P(port, " E", VOLUMETRIC_UNIT(planner.max_feedrate_mm_s[E_AXIS + i]));
2016-12-03 22:02:27 -06:00
}
#endif
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Maximum Acceleration (units/s2):");
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M201 X", LINEAR_UNIT(planner.max_acceleration_mm_per_s2[X_AXIS]));
SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(planner.max_acceleration_mm_per_s2[Y_AXIS]));
SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(planner.max_acceleration_mm_per_s2[Z_AXIS]));
2016-12-11 19:37:29 -06:00
#if DISABLED(DISTINCT_E_FACTORS)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " E", VOLUMETRIC_UNIT(planner.max_acceleration_mm_per_s2[E_AXIS]));
2016-12-03 22:02:27 -06:00
#endif
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
2016-12-03 22:02:27 -06:00
#if ENABLED(DISTINCT_E_FACTORS)
2017-05-24 16:56:36 -05:00
CONFIG_ECHO_START;
2016-12-03 22:02:27 -06:00
for (uint8_t i = 0; i < E_STEPPERS; i++) {
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M201 T", (int)i);
SERIAL_ECHOLNPAIR_P(port, " E", VOLUMETRIC_UNIT(planner.max_acceleration_mm_per_s2[E_AXIS + i]));
2016-12-03 22:02:27 -06:00
}
#endif
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Acceleration (units/s2): P<print_accel> R<retract_accel> T<travel_accel>");
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M204 P", LINEAR_UNIT(planner.acceleration));
SERIAL_ECHOPAIR_P(port, " R", LINEAR_UNIT(planner.retract_acceleration));
SERIAL_ECHOLNPAIR_P(port, " T", LINEAR_UNIT(planner.travel_acceleration));
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Advanced: S<min_feedrate> T<min_travel_feedrate> B<min_segment_time_us> X<max_xy_jerk> Z<max_z_jerk> E<max_e_jerk>");
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M205 S", LINEAR_UNIT(planner.min_feedrate_mm_s));
SERIAL_ECHOPAIR_P(port, " T", LINEAR_UNIT(planner.min_travel_feedrate_mm_s));
SERIAL_ECHOPAIR_P(port, " B", planner.min_segment_time_us);
SERIAL_ECHOPAIR_P(port, " X", LINEAR_UNIT(planner.max_jerk[X_AXIS]));
SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(planner.max_jerk[Y_AXIS]));
SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(planner.max_jerk[Z_AXIS]));
SERIAL_ECHOLNPAIR_P(port, " E", LINEAR_UNIT(planner.max_jerk[E_AXIS]));
#if HAS_M206_COMMAND
2017-03-04 18:01:33 -06:00
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Home offset:");
2017-03-04 18:01:33 -06:00
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M206 X", LINEAR_UNIT(home_offset[X_AXIS]));
SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(home_offset[Y_AXIS]));
SERIAL_ECHOLNPAIR_P(port, " Z", LINEAR_UNIT(home_offset[Z_AXIS]));
2017-03-04 18:01:33 -06:00
#endif
2016-10-28 18:55:42 -05:00
#if HOTENDS > 1
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Hotend offsets:");
2016-10-28 18:55:42 -05:00
}
CONFIG_ECHO_START;
2016-10-28 18:55:42 -05:00
for (uint8_t e = 1; e < HOTENDS; e++) {
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M218 T", (int)e);
SERIAL_ECHOPAIR_P(port, " X", LINEAR_UNIT(hotend_offset[X_AXIS][e]));
SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(hotend_offset[Y_AXIS][e]));
#if ENABLED(DUAL_X_CARRIAGE) || ENABLED(SWITCHING_NOZZLE) ||ENABLED(PARKING_EXTRUDER)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(hotend_offset[Z_AXIS][e]));
2015-08-30 21:04:30 -05:00
#endif
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
}
2016-10-28 18:55:42 -05:00
#endif
2018-01-03 21:55:07 -06:00
/**
* Bed Leveling
*/
#if HAS_LEVELING
2018-01-03 21:55:07 -06:00
#if ENABLED(MESH_BED_LEVELING)
if (!forReplay) {
2016-10-28 18:55:42 -05:00
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Mesh Bed Leveling:");
2016-10-28 18:55:42 -05:00
}
2018-01-03 21:55:07 -06:00
#elif ENABLED(AUTO_BED_LEVELING_UBL)
if (!forReplay) {
CONFIG_ECHO_START;
ubl.echo_name();
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, ":");
2018-01-03 21:55:07 -06:00
}
#elif HAS_ABL
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Auto Bed Leveling:");
2018-01-03 21:55:07 -06:00
}
#endif
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M420 S", planner.leveling_active ? 1 : 0);
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(planner.z_fade_height));
#endif
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
2018-01-03 21:55:07 -06:00
#if ENABLED(MESH_BED_LEVELING)
2017-05-16 02:34:36 -05:00
2018-02-25 08:07:48 -06:00
if (leveling_is_valid()) {
for (uint8_t py = 0; py < GRID_MAX_POINTS_Y; py++) {
for (uint8_t px = 0; px < GRID_MAX_POINTS_X; px++) {
CONFIG_ECHO_START;
SERIAL_ECHOPAIR_P(port, " G29 S3 X", (int)px + 1);
SERIAL_ECHOPAIR_P(port, " Y", (int)py + 1);
SERIAL_ECHOPGM_P(port, " Z");
SERIAL_PROTOCOL_F_P(port, LINEAR_UNIT(mbl.z_values[px][py]), 5);
SERIAL_EOL_P(port);
}
2018-01-03 21:55:07 -06:00
}
}
2018-01-03 21:55:07 -06:00
#elif ENABLED(AUTO_BED_LEVELING_UBL)
if (!forReplay) {
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
2018-01-03 21:55:07 -06:00
ubl.report_state();
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPAIR_P(port, "\nActive Mesh Slot: ", ubl.storage_slot);
SERIAL_ECHOPAIR_P(port, "EEPROM can hold ", calc_num_meshes());
SERIAL_ECHOLNPGM_P(port, " meshes.\n");
2018-01-03 21:55:07 -06:00
}
2018-02-25 08:07:48 -06:00
ubl.report_current_mesh(
#if ADD_PORT_ARG
port
#endif
);
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
if (leveling_is_valid()) {
for (uint8_t py = 0; py < GRID_MAX_POINTS_Y; py++) {
for (uint8_t px = 0; px < GRID_MAX_POINTS_X; px++) {
CONFIG_ECHO_START;
SERIAL_ECHOPAIR_P(port, " G29 W I", (int)px + 1);
SERIAL_ECHOPAIR_P(port, " J", (int)py + 1);
SERIAL_ECHOPGM_P(port, " Z");
SERIAL_PROTOCOL_F_P(port, LINEAR_UNIT(z_values[px][py]), 5);
SERIAL_EOL_P(port);
}
}
}
#endif
2018-01-03 21:55:07 -06:00
#endif // HAS_LEVELING
2016-10-28 18:55:42 -05:00
#if ENABLED(DELTA)
2017-11-05 08:49:38 -06:00
2016-10-28 18:55:42 -05:00
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Endstop adjustment:");
2016-10-28 18:55:42 -05:00
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M666 X", LINEAR_UNIT(delta_endstop_adj[X_AXIS]));
SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(delta_endstop_adj[Y_AXIS]));
SERIAL_ECHOLNPAIR_P(port, " Z", LINEAR_UNIT(delta_endstop_adj[Z_AXIS]));
2016-10-28 18:55:42 -05:00
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Delta settings: L<diagonal_rod> R<radius> H<height> S<segments_per_s> B<calibration radius> XYZ<tower angle corrections>");
2016-10-28 18:55:42 -05:00
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M665 L", LINEAR_UNIT(delta_diagonal_rod));
SERIAL_ECHOPAIR_P(port, " R", LINEAR_UNIT(delta_radius));
SERIAL_ECHOPAIR_P(port, " H", LINEAR_UNIT(delta_height));
SERIAL_ECHOPAIR_P(port, " S", delta_segments_per_second);
SERIAL_ECHOPAIR_P(port, " B", LINEAR_UNIT(delta_calibration_radius));
SERIAL_ECHOPAIR_P(port, " X", LINEAR_UNIT(delta_tower_angle_trim[A_AXIS]));
SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(delta_tower_angle_trim[B_AXIS]));
SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(delta_tower_angle_trim[C_AXIS]));
SERIAL_EOL_P(port);
#elif ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
2017-11-05 08:49:38 -06:00
2016-10-28 18:55:42 -05:00
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Endstop adjustment:");
2016-10-28 18:55:42 -05:00
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPGM_P(port, " M666");
#if ENABLED(X_DUAL_ENDSTOPS)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " X", LINEAR_UNIT(endstops.x_endstop_adj));
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(endstops.y_endstop_adj));
#endif
#if ENABLED(Z_DUAL_ENDSTOPS)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(endstops.z_endstop_adj));
#endif
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
#endif // [XYZ]_DUAL_ENDSTOPS
2016-10-28 18:55:42 -05:00
#if ENABLED(ULTIPANEL)
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Material heatup parameters:");
2016-10-28 18:55:42 -05:00
}
for (uint8_t i = 0; i < COUNT(lcd_preheat_hotend_temp); i++) {
2017-11-15 03:58:43 -06:00
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M145 S", (int)i);
SERIAL_ECHOPAIR_P(port, " H", TEMP_UNIT(lcd_preheat_hotend_temp[i]));
SERIAL_ECHOPAIR_P(port, " B", TEMP_UNIT(lcd_preheat_bed_temp[i]));
SERIAL_ECHOLNPAIR_P(port, " F", lcd_preheat_fan_speed[i]);
}
2016-10-28 18:55:42 -05:00
#endif // ULTIPANEL
2016-10-28 18:55:42 -05:00
#if HAS_PID_HEATING
2016-10-28 18:55:42 -05:00
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "PID settings:");
2016-10-28 18:55:42 -05:00
}
#if ENABLED(PIDTEMP)
#if HOTENDS > 1
if (forReplay) {
HOTEND_LOOP() {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M301 E", e);
SERIAL_ECHOPAIR_P(port, " P", PID_PARAM(Kp, e));
SERIAL_ECHOPAIR_P(port, " I", unscalePID_i(PID_PARAM(Ki, e)));
SERIAL_ECHOPAIR_P(port, " D", unscalePID_d(PID_PARAM(Kd, e)));
2016-10-28 18:55:42 -05:00
#if ENABLED(PID_EXTRUSION_SCALING)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " C", PID_PARAM(Kc, e));
if (e == 0) SERIAL_ECHOPAIR_P(port, " L", lpq_len);
2016-10-28 18:55:42 -05:00
#endif
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
2016-10-28 18:55:42 -05:00
}
}
else
#endif // HOTENDS > 1
// !forReplay || HOTENDS == 1
{
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M301 P", PID_PARAM(Kp, 0)); // for compatibility with hosts, only echo values for E0
SERIAL_ECHOPAIR_P(port, " I", unscalePID_i(PID_PARAM(Ki, 0)));
SERIAL_ECHOPAIR_P(port, " D", unscalePID_d(PID_PARAM(Kd, 0)));
2016-10-28 18:55:42 -05:00
#if ENABLED(PID_EXTRUSION_SCALING)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " C", PID_PARAM(Kc, 0));
SERIAL_ECHOPAIR_P(port, " L", lpq_len);
2016-10-28 18:55:42 -05:00
#endif
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
2016-10-28 18:55:42 -05:00
}
#endif // PIDTEMP
#if ENABLED(PIDTEMPBED)
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M304 P", thermalManager.bedKp);
SERIAL_ECHOPAIR_P(port, " I", unscalePID_i(thermalManager.bedKi));
SERIAL_ECHOPAIR_P(port, " D", unscalePID_d(thermalManager.bedKd));
SERIAL_EOL_P(port);
2016-10-28 18:55:42 -05:00
#endif
#endif // PIDTEMP || PIDTEMPBED
#if HAS_LCD_CONTRAST
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "LCD Contrast:");
2016-10-28 18:55:42 -05:00
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPAIR_P(port, " M250 C", lcd_contrast);
#endif
2016-10-28 18:55:42 -05:00
#if ENABLED(FWRETRACT)
2016-10-28 18:55:42 -05:00
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Retract: S<length> F<units/m> Z<lift>");
2016-10-28 18:55:42 -05:00
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M207 S", LINEAR_UNIT(fwretract.retract_length));
SERIAL_ECHOPAIR_P(port, " W", LINEAR_UNIT(fwretract.swap_retract_length));
SERIAL_ECHOPAIR_P(port, " F", MMS_TO_MMM(LINEAR_UNIT(fwretract.retract_feedrate_mm_s)));
SERIAL_ECHOLNPAIR_P(port, " Z", LINEAR_UNIT(fwretract.retract_zlift));
2016-10-28 18:55:42 -05:00
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Recover: S<length> F<units/m>");
2016-10-28 18:55:42 -05:00
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M208 S", LINEAR_UNIT(fwretract.retract_recover_length));
SERIAL_ECHOPAIR_P(port, " W", LINEAR_UNIT(fwretract.swap_retract_recover_length));
SERIAL_ECHOLNPAIR_P(port, " F", MMS_TO_MMM(LINEAR_UNIT(fwretract.retract_recover_feedrate_mm_s)));
2016-10-28 18:55:42 -05:00
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Auto-Retract: S=0 to disable, 1 to interpret E-only moves as retract/recover");
2016-10-28 18:55:42 -05:00
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPAIR_P(port, " M209 S", fwretract.autoretract_enabled ? 1 : 0);
#endif // FWRETRACT
2016-10-28 18:55:42 -05:00
/**
* Probe Offset
2016-10-28 18:55:42 -05:00
*/
#if HAS_BED_PROBE
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Z-Probe Offset (mm):");
2016-10-28 18:55:42 -05:00
}
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPAIR_P(port, " M851 Z", LINEAR_UNIT(zprobe_zoffset));
2016-10-28 18:55:42 -05:00
#endif
2017-12-01 16:42:23 -06:00
/**
* Bed Skew Correction
*/
#if ENABLED(SKEW_CORRECTION_GCODE)
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Skew Factor: ");
2017-12-01 16:42:23 -06:00
}
CONFIG_ECHO_START;
#if ENABLED(SKEW_CORRECTION_FOR_Z)
2018-01-23 19:09:40 -06:00
SERIAL_ECHOPGM_P(port, " M852 I");
2017-11-05 08:49:38 -06:00
SERIAL_ECHO_F_P(port, LINEAR_UNIT(planner.xy_skew_factor), 6);
SERIAL_ECHOPGM_P(port, " J");
SERIAL_ECHO_F_P(port, LINEAR_UNIT(planner.xz_skew_factor), 6);
SERIAL_ECHOPGM_P(port, " K");
SERIAL_ECHO_F_P(port, LINEAR_UNIT(planner.yz_skew_factor), 6);
SERIAL_EOL_P(port);
#else
2018-01-23 19:09:40 -06:00
SERIAL_ECHOPGM_P(port, " M852 S");
2017-11-05 08:49:38 -06:00
SERIAL_ECHO_F_P(port, LINEAR_UNIT(planner.xy_skew_factor), 6);
SERIAL_EOL_P(port);
2017-12-01 16:42:23 -06:00
#endif
#endif
/**
* TMC2130 stepper driver current
*/
2018-01-03 21:55:07 -06:00
#if HAS_TRINAMIC
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Stepper driver current:");
}
CONFIG_ECHO_START;
2018-01-23 19:09:40 -06:00
SERIAL_ECHOPGM_P(port, " M906");
2017-12-15 15:03:14 -06:00
#if ENABLED(X_IS_TMC2130) || ENABLED(X_IS_TMC2208)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " X ", stepperX.getCurrent());
#endif
2017-12-15 15:03:14 -06:00
#if ENABLED(Y_IS_TMC2130) || ENABLED(Y_IS_TMC2208)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " Y ", stepperY.getCurrent());
#endif
2017-12-15 15:03:14 -06:00
#if ENABLED(Z_IS_TMC2130) || ENABLED(Z_IS_TMC2208)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " Z ", stepperZ.getCurrent());
#endif
2017-12-15 15:03:14 -06:00
#if ENABLED(X2_IS_TMC2130) || ENABLED(X2_IS_TMC2208)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " X2 ", stepperX2.getCurrent());
#endif
2017-12-15 15:03:14 -06:00
#if ENABLED(Y2_IS_TMC2130) || ENABLED(Y2_IS_TMC2208)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " Y2 ", stepperY2.getCurrent());
#endif
2017-12-15 15:03:14 -06:00
#if ENABLED(Z2_IS_TMC2130) || ENABLED(Z2_IS_TMC2208)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " Z2 ", stepperZ2.getCurrent());
#endif
2017-12-15 15:03:14 -06:00
#if ENABLED(E0_IS_TMC2130) || ENABLED(E0_IS_TMC2208)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " E0 ", stepperE0.getCurrent());
#endif
2017-12-15 15:03:14 -06:00
#if ENABLED(E1_IS_TMC2130) || ENABLED(E1_IS_TMC2208)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " E1 ", stepperE1.getCurrent());
#endif
2017-12-15 15:03:14 -06:00
#if ENABLED(E2_IS_TMC2130) || ENABLED(E2_IS_TMC2208)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " E2 ", stepperE2.getCurrent());
#endif
2017-12-15 15:03:14 -06:00
#if ENABLED(E3_IS_TMC2130) || ENABLED(E3_IS_TMC2208)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " E3 ", stepperE3.getCurrent());
2017-12-15 15:03:14 -06:00
#endif
#if ENABLED(E4_IS_TMC2130) || ENABLED(E4_IS_TMC2208)
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " E4 ", stepperE4.getCurrent());
2017-12-15 15:03:14 -06:00
#endif
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
2017-12-15 15:03:14 -06:00
#endif
/**
* TMC2130 Sensorless homing thresholds
*/
2018-01-03 21:55:07 -06:00
#if ENABLED(SENSORLESS_HOMING)
2017-12-15 15:03:14 -06:00
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Sensorless homing threshold:");
2017-12-15 15:03:14 -06:00
}
CONFIG_ECHO_START;
2018-01-23 19:09:40 -06:00
SERIAL_ECHOPGM_P(port, " M914");
#ifdef X_HOMING_SENSITIVITY
#if ENABLED(X_IS_TMC2130)
SERIAL_ECHOPAIR_P(port, " X", stepperX.sgt());
#endif
#if ENABLED(X2_IS_TMC2130)
SERIAL_ECHOPAIR_P(port, " X2 ", stepperX2.sgt());
#endif
2017-12-15 15:03:14 -06:00
#endif
#ifdef Y_HOMING_SENSITIVITY
#if ENABLED(Y_IS_TMC2130)
SERIAL_ECHOPAIR_P(port, " Y", stepperY.sgt());
#endif
#if ENABLED(Y2_IS_TMC2130)
SERIAL_ECHOPAIR_P(port, " Y2 ", stepperY2.sgt());
#endif
2017-12-15 15:03:14 -06:00
#endif
#ifdef Z_HOMING_SENSITIVITY
#if ENABLED(Z_IS_TMC2130)
SERIAL_ECHOPAIR_P(port, " Z ", stepperZ.sgt());
#endif
#if ENABLED(Z2_IS_TMC2130)
SERIAL_ECHOPAIR_P(port, " Z2 ", stepperZ2.sgt());
#endif
#endif
2017-11-05 08:49:38 -06:00
SERIAL_EOL_P(port);
#endif
/**
* Linear Advance
*/
#if ENABLED(LIN_ADVANCE)
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Linear Advance:");
}
CONFIG_ECHO_START;
2018-02-23 00:53:29 -06:00
SERIAL_ECHOLNPAIR_P(port, " M900 K", planner.extruder_advance_K);
#endif
#if HAS_MOTOR_CURRENT_PWM
CONFIG_ECHO_START;
if (!forReplay) {
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Stepper motor currents:");
CONFIG_ECHO_START;
}
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M907 X", stepper.motor_current_setting[0]);
SERIAL_ECHOPAIR_P(port, " Z", stepper.motor_current_setting[1]);
SERIAL_ECHOPAIR_P(port, " E", stepper.motor_current_setting[2]);
SERIAL_EOL_P(port);
#endif
/**
* Advanced Pause filament load & unload lengths
*/
#if ENABLED(ADVANCED_PAUSE_FEATURE)
if (!forReplay) {
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOLNPGM_P(port, "Filament load/unload lengths:");
}
CONFIG_ECHO_START;
#if EXTRUDERS == 1
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M603 L", LINEAR_UNIT(filament_change_load_length[0]));
SERIAL_ECHOLNPAIR_P(port, " U", LINEAR_UNIT(filament_change_unload_length[0]));
#else
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M603 T0 L", LINEAR_UNIT(filament_change_load_length[0]));
SERIAL_ECHOLNPAIR_P(port, " U", LINEAR_UNIT(filament_change_unload_length[0]));
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M603 T1 L", LINEAR_UNIT(filament_change_load_length[1]));
SERIAL_ECHOLNPAIR_P(port, " U", LINEAR_UNIT(filament_change_unload_length[1]));
#if EXTRUDERS > 2
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M603 T2 L", LINEAR_UNIT(filament_change_load_length[2]));
SERIAL_ECHOLNPAIR_P(port, " U", LINEAR_UNIT(filament_change_unload_length[2]));
#if EXTRUDERS > 3
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M603 T3 L", LINEAR_UNIT(filament_change_load_length[3]));
SERIAL_ECHOLNPAIR_P(port, " U", LINEAR_UNIT(filament_change_unload_length[3]));
#if EXTRUDERS > 4
CONFIG_ECHO_START;
2017-11-05 08:49:38 -06:00
SERIAL_ECHOPAIR_P(port, " M603 T4 L", LINEAR_UNIT(filament_change_load_length[4]));
SERIAL_ECHOLNPAIR_P(port, " U", LINEAR_UNIT(filament_change_unload_length[4]));
#endif // EXTRUDERS > 4
#endif // EXTRUDERS > 3
#endif // EXTRUDERS > 2
#endif // EXTRUDERS == 1
#endif // ADVANCED_PAUSE_FEATURE
2016-10-28 18:55:42 -05:00
}
#endif // !DISABLE_M503