M550 CONFIGURABLE_MACHINE_NAME (#27731)

This commit is contained in:
Scott Lahteine 2025-03-16 03:24:00 -05:00 committed by GitHub
parent 434bf81f8e
commit b954959f55
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
65 changed files with 367 additions and 226 deletions

View file

@ -129,6 +129,7 @@
// Name displayed in the LCD "Ready" message and Info menu
//#define CUSTOM_MACHINE_NAME "3D Printer"
//#define CONFIGURABLE_MACHINE_NAME // Add G-code M550 to set/report the machine name
// Printer's unique ID, used by some programs to differentiate between machines.
// Choose your own or use a service like https://www.uuidgenerator.net/version4

View file

@ -2227,7 +2227,7 @@
// Developer menu (accessed by touching "About Printer" copyright text)
//#define TOUCH_UI_DEVELOPER_MENU
#endif
#endif // TOUCH_UI_FTDI_EVE
//
// Classic UI Options

View file

@ -271,6 +271,10 @@
PGMSTR(M112_KILL_STR, "M112 Shutdown");
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
MString<64> machine_name;
#endif
MarlinState marlin_state = MarlinState::MF_INITIALIZING;
// For M109 and M190, this flag may be cleared (by M108) to exit the wait loop
@ -1363,6 +1367,10 @@ void setup() {
SETUP_RUN(settings.first_load()); // Load data from EEPROM if available (or use defaults)
// This also updates variables in the planner, elsewhere
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
SETUP_RUN(ui.reset_status(false)); // machine_name Initialized by settings.load()
#endif
#if ENABLED(PROBE_TARE)
SETUP_RUN(probe.tare_init());
#endif

View file

@ -41,6 +41,10 @@ inline void idle_no_sleep() { idle(true); }
void kill(FSTR_P const lcd_error=nullptr, FSTR_P const lcd_component=nullptr, const bool steppers_off=false);
void minkill(const bool steppers_off=false);
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
extern MString<64> machine_name;
#endif
// Global State of the firmware
enum class MarlinState : uint8_t {
MF_INITIALIZING = 0,

View file

@ -88,6 +88,7 @@
#undef MACHINE_NAME
#define MACHINE_NAME DEFAULT_MACHINE_NAME
#endif
#define MACHINE_NAME_SUBST TERN(CONFIGURABLE_MACHINE_NAME, "$", MACHINE_NAME)
#define MARLIN_WEBSITE_URL "marlinfw.org"

View file

@ -298,6 +298,9 @@ public:
MString& clear() { return set(); }
MString& eol() { return append('\n'); }
MString& trunc(const int &i) { if (i <= SIZE) str[i] = '\0'; debug(F("trunc")); return *this; }
MString& ltrim() { char *s = str; while (*s == ' ') ++s; if (s != str) strcpy(str, s); return *this; }
MString& rtrim() { int s = length(); while (s && str[s - 1] == ' ') --s; str[s] = '\0'; return *this; }
MString& trim() { return rtrim().ltrim(); }
// Truncate on a Unicode boundary
MString& utrunc(const int &n=SIZE) {

View file

@ -0,0 +1,59 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../../inc/MarlinConfig.h"
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
#include "../gcode.h"
#include "../../MarlinCore.h"
#include "../../lcd/marlinui.h"
/**
* M550: Set machine name
*
* Parameters:
* P "<name>" Set the name using the 'P' parameter (RepRapFirmware)
* "<name>" Set the name using the "string" parameter
*/
void GcodeSuite::M550() {
bool did_set = true;
if (parser.seenval('P'))
machine_name = parser.value_string();
else if (TERN(GCODE_QUOTED_STRINGS, false, parser.seen('P')))
machine_name = parser.string_arg[0] == 'P' ? &parser.string_arg[1] : parser.string_arg;
else if (parser.string_arg && parser.string_arg[0])
machine_name = parser.string_arg;
else
did_set = false;
if (did_set) {
machine_name.trim();
ui.reset_status(false);
}
else
SERIAL_ECHOLNPGM("RepRap name: ", &machine_name);
}
#endif // CONFIGURABLE_MACHINE_NAME

View file

@ -38,7 +38,7 @@
#include "../../feature/powerloss.h"
#endif
#if HAS_SUICIDE
#if ANY(HAS_SUICIDE, CONFIGURABLE_MACHINE_NAME)
#include "../../MarlinCore.h"
#endif
@ -92,7 +92,11 @@ void GcodeSuite::M81() {
safe_delay(1000); // Wait 1 second before switching off
LCD_MESSAGE_F(MACHINE_NAME " " STR_OFF ".");
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
ui.set_status(&MString<30>(&machine_name, ' ', F(STR_OFF), '.'));
#else
LCD_MESSAGE_F(MACHINE_NAME " " STR_OFF ".");
#endif
bool delayed_power_off = false;

View file

@ -947,6 +947,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 540: M540(); break; // M540: Set abort on endstop hit for SD printing
#endif
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
case 550: M550(); break; // M550: Set machine name
#endif
#if HAS_ETHERNET
case 552: M552(); break; // M552: Set IP address
case 553: M553(); break; // M553: Set gateway

View file

@ -261,6 +261,7 @@
* M512 - Set/Change/Remove Password (Requires PASSWORD_CHANGE_GCODE)
* M524 - Abort the current SD print job started with M24. (Requires SDSUPPORT)
* M540 - Enable/disable SD card abort on endstop hit: "M540 S<state>". (Requires SD_ABORT_ON_ENDSTOP_HIT)
* M550 - Set the machine name: "M550 P<name>". (Requires CONFIGURABLE_MACHINE_NAME)
* M552 - Get or set IP address. Enable/disable network interface. (Requires enabled Ethernet port)
* M553 - Get or set IP netmask. (Requires enabled Ethernet port)
* M554 - Get or set IP gateway. (Requires enabled Ethernet port)
@ -1128,6 +1129,10 @@ private:
static void M540();
#endif
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
static void M550();
#endif
#if HAS_ETHERNET
static void M552();
static void M552_report();

View file

@ -33,7 +33,7 @@
*/
void GcodeSuite::M16() {
if (strcmp_P(parser.string_arg, PSTR(MACHINE_NAME)))
if (TERN(CONFIGURABLE_MACHINE_NAME, strcmp(parser.string_arg, machine_name), strcmp_P(parser.string_arg, PSTR(MACHINE_NAME))))
kill(GET_TEXT_F(MSG_KILL_EXPECTED_PRINTER));
}

View file

@ -615,12 +615,20 @@
#define HAS_STATUS_MESSAGE 1
#endif
#if HAS_WIRED_LCD && !HAS_GRAPHICAL_TFT && !IS_DWIN_MARLINUI
#define HAS_LCDPRINT 1
#if ANY(HAS_WIRED_LCD, DWIN_LCD_PROUI)
#if ENABLED(STATUS_MESSAGE_SCROLLING)
#define MAX_MESSAGE_SIZE _MAX(LONG_FILENAME_LENGTH, MAX_LANG_CHARSIZE * (LCD_WIDTH))
#else
#define MAX_MESSAGE_SIZE (MAX_LANG_CHARSIZE * (LCD_WIDTH))
#endif
#elif HAS_STATUS_MESSAGE
#define MAX_MESSAGE_SIZE 63
#else
#define MAX_MESSAGE_SIZE 1
#endif
#if HAS_DISPLAY || HAS_LCDPRINT
#define HAS_UTF8_UTILS 1
#if HAS_WIRED_LCD && !HAS_GRAPHICAL_TFT && !IS_DWIN_MARLINUI
#define HAS_LCDPRINT 1
#endif
#if IS_ULTIPANEL && DISABLED(NO_LCD_MENUS)

View file

@ -4507,6 +4507,10 @@ static_assert(WITHIN(MULTISTEPPING_LIMIT, 1, 128) && IS_POWER_OF_2(MULTISTEPPING
#error "Only enable ULTIPANEL_FEEDMULTIPLY or ULTIPANEL_FLOWPERCENT, but not both."
#endif
#if ENABLED(CONFIGURABLE_MACHINE_NAME) && DISABLED(GCODE_QUOTED_STRINGS)
#error "CONFIGURABLE_MACHINE_NAME requires GCODE_QUOTED_STRINGS."
#endif
// Misc. Cleanup
#undef _TEST_PWM
#undef _NUM_AXES_STR

View file

@ -107,7 +107,7 @@ int lcd_put_u8str_max_P(PGM_P utf8_pstr, const pixel_len_t max_length) {
return lcd_put_u8str_max_cb(utf8_pstr, read_byte_rom, max_length);
}
lcd_uint_t lcd_put_u8str_P(PGM_P const ptpl, const int8_t ind, const char * const cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/, const lcd_uint_t maxlen/*=LCD_WIDTH*/) {
lcd_uint_t lcd_put_u8str_P(PGM_P const ptpl, const int8_t ind, const char * const cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/, const lcd_uint_t maxlen/*=MAX_MESSAGE_SIZE*/) {
dwin_string.set(ptpl, ind, cstr, fstr);
dwin_string.truncate(maxlen);
dwinDrawString(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, dwin_string.string());

View file

@ -74,7 +74,7 @@ namespace ExtUI {
void onMinTempError(const heater_id_t header_id) {}
void onMaxTempError(const heater_id_t header_id) {}
void onStatusChanged(const char *lcd_msg) { StatusScreen::setStatusMessage(lcd_msg); }
void onStatusChanged(const char * const lcd_msg) { StatusScreen::setStatusMessage(lcd_msg); }
void onPrintTimerStarted() {
InterfaceSoundsScreen::playEventSound(InterfaceSoundsScreen::PRINTING_STARTED);

View file

@ -252,9 +252,15 @@ void onUserConfirmRequired(const int icon, FSTR_P const fstr, FSTR_P const fBtn)
}
#endif
void onStatusChanged(const char *const statMsg) {
for (int16_t j = 0; j < 20; j++) // Clear old message
static constexpr int16_t STATUS_MESSAGE_SIZE = 20;
void clearStatus() {
for (int16_t j = 0; j < STATUS_MESSAGE_SIZE; j++) // Clear old message
rts.sendData(' ', StatusMessageString + j);
}
void onStatusChanged(const char * const statMsg) {
clearStatus();
rts.sendData(statMsg, StatusMessageString);
}

View file

@ -99,7 +99,12 @@ void RTS::onStartup() {
sendData(StartSoundSet, SoundAddr);
delay_ms(400); // Delay to allow screen to configure
onStatusChanged(MACHINE_NAME " Ready");
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
const MString<32> ready(message_string, " Ready");
onStatusChanged(ready);
#else
onStatusChanged(F(MACHINE_NAME " Ready"));
#endif
sendData(100, FeedrateDisplay);

View file

@ -63,12 +63,16 @@ void NextionTFT::startup() {
delay_ms(100);
SEND_VAL("tmppage.connected", 1);
SEND_VALasTXT("tmppage.marlin", SHORT_BUILD_VERSION);
SEND_VALasTXT("tmppage.compiled", __DATE__ " / " __TIME__);
SEND_TXT("tmppage.marlin", SHORT_BUILD_VERSION);
SEND_TXT("tmppage.compiled", __DATE__ " / " __TIME__);
SEND_VALasTXT("tmppage.extruder", EXTRUDERS);
SEND_VALasTXT("tmppage.printer", MACHINE_NAME);
SEND_VALasTXT("tmppage.author", STRING_CONFIG_H_AUTHOR);
SEND_VALasTXT("tmppage.released", STRING_DISTRIBUTION_DATE);
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
SEND_VALasTXT("tmppage.printer", &machine_name);
#else
SEND_TXT("tmppage.printer", MACHINE_NAME);
#endif
SEND_TXT("tmppage.author", STRING_CONFIG_H_AUTHOR);
SEND_TXT("tmppage.released", STRING_DISTRIBUTION_DATE);
SEND_VALasTXT("tmppage.bedx", X_BED_SIZE);
SEND_VALasTXT("tmppage.bedy", Y_BED_SIZE);
SEND_VALasTXT("tmppage.bedz", Z_MAX_POS);
@ -222,12 +226,16 @@ void NextionTFT::panelInfo(uint8_t req) {
case 2: // Printer Info
if (!isPrinting()) {
SEND_VAL("tmppage.connected", 1);
SEND_VALasTXT("tmppage.marlin", SHORT_BUILD_VERSION);
SEND_VALasTXT("tmppage.compiled", __DATE__ " / " __TIME__);
SEND_TXT("tmppage.marlin", SHORT_BUILD_VERSION);
SEND_TXT("tmppage.compiled", __DATE__ " / " __TIME__);
SEND_VALasTXT("tmppage.extruder", EXTRUDERS);
SEND_VALasTXT("tmppage.printer", MACHINE_NAME);
SEND_VALasTXT("tmppage.author", STRING_CONFIG_H_AUTHOR);
SEND_VALasTXT("tmppage.released", STRING_DISTRIBUTION_DATE);
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
SEND_VALasTXT("tmppage.printer", &machine_name);
#else
SEND_TXT("tmppage.printer", MACHINE_NAME);
#endif
SEND_TXT("tmppage.author", STRING_CONFIG_H_AUTHOR);
SEND_TXT("tmppage.released", STRING_DISTRIBUTION_DATE);
SEND_VALasTXT("tmppage.bedx", X_BED_SIZE);
SEND_VALasTXT("tmppage.bedy", Y_BED_SIZE);
SEND_VALasTXT("tmppage.bedz", Z_MAX_POS);
@ -430,59 +438,43 @@ void NextionTFT::panelInfo(uint8_t req) {
case 36: // Endstop Info
#if X_HOME_TO_MIN
SEND_VALasTXT("x1", READ(X_MIN_PIN) == X_MIN_ENDSTOP_HIT_STATE ? "triggered" : "open");
SEND_TXT_F("x1", READ(X_MIN_PIN) == X_MIN_ENDSTOP_HIT_STATE ? F("triggered") : F("open"));
#elif X_HOME_TO_MAX
SEND_VALasTXT("x2", READ(X_MAX_PIN) == X_MAX_ENDSTOP_HIT_STATE ? "triggered" : "open");
SEND_TXT_F("x2", READ(X_MAX_PIN) == X_MAX_ENDSTOP_HIT_STATE ? F("triggered") : F("open"));
#endif
#if Y_HOME_TO_MIN
SEND_VALasTXT("y1", READ(Y_MIN_PIN) == Y_MIN_ENDSTOP_HIT_STATE ? "triggered" : "open");
SEND_TXT_F("y1", READ(Y_MIN_PIN) == Y_MIN_ENDSTOP_HIT_STATE ? F("triggered") : F("open"));
#elif Y_HOME_TO_MAX
SEND_VALasTXT("y2", READ(X_MAX_PIN) == Y_MAX_ENDSTOP_HIT_STATE ? "triggered" : "open");
SEND_TXT_F("y2", READ(X_MAX_PIN) == Y_MAX_ENDSTOP_HIT_STATE ? F("triggered") : F("open"));
#endif
#if Z_HOME_TO_MIN
SEND_VALasTXT("z1", READ(Z_MIN_PIN) == Z_MIN_ENDSTOP_HIT_STATE ? "triggered" : "open");
SEND_TXT_F("z1", READ(Z_MIN_PIN) == Z_MIN_ENDSTOP_HIT_STATE ? F("triggered") : F("open"));
#elif Z_HOME_TO_MAX
SEND_VALasTXT("z2", READ(Z_MAX_PIN) == Z_MAX_ENDSTOP_HIT_STATE ? "triggered" : "open");
SEND_TXT_F("z2", READ(Z_MAX_PIN) == Z_MAX_ENDSTOP_HIT_STATE ? F("triggered") : F("open"));
#endif
#if USE_Z2_MIN
SEND_VALasTXT("z2", READ(Z2_MIN_PIN) == Z2_MIN_ENDSTOP_HIT_STATE ? "triggered" : "open");
SEND_TXT_F("z2", READ(Z2_MIN_PIN) == Z2_MIN_ENDSTOP_HIT_STATE ? F("triggered") : F("open"));
#elif USE_Z2_MAX
SEND_VALasTXT("z2", READ(Z2_MAX_PIN) == Z2_MAX_ENDSTOP_HIT_STATE ? "triggered" : "open");
SEND_TXT_F("z2", READ(Z2_MAX_PIN) == Z2_MAX_ENDSTOP_HIT_STATE ? F("triggered") : F("open"));
#endif
#if HAS_BED_PROBE
//SEND_VALasTXT("bltouch", PROBE_TRIGGERED() ? "triggered" : "open");
//SEND_TXT_F("bltouch", PROBE_TRIGGERED() ? F("triggered") : F("open"));
#else
SEND_NA("bltouch");
#endif
break;
case 37: // PID
#if ENABLED(PIDTEMP)
#define SEND_PID_INFO_0(A, B) SEND_VALasTXT(A, getPID_K##B(E0))
#else
#define SEND_PID_INFO_0(A, B) SEND_NA(A)
#endif
#define SEND_PID_INFO_0(A, B) TERN(PIDTEMP, SEND_VALasTXT(A, getPID_K##B(E0)), SEND_NA(A))
#if ALL(PIDTEMP, HAS_MULTI_EXTRUDER)
#define SEND_PID_INFO_1(A, B) SEND_VALasTXT(A, getPID_K##B(E1))
#else
#define SEND_PID_INFO_1(A, B) SEND_NA(A)
#endif
#if ENABLED(PIDTEMPBED)
#define SEND_PID_INFO_BED(A, B) SEND_VALasTXT(A, getBedPID_K##B())
#else
#define SEND_PID_INFO_BED(A, B) SEND_NA(A)
#endif
SEND_PID_INFO_0("p0", p);
SEND_PID_INFO_0("i0", i);
SEND_PID_INFO_0("d0", d);
SEND_PID_INFO_1("p1", p);
SEND_PID_INFO_1("i1", i);
SEND_PID_INFO_1("d1", d);
SEND_PID_INFO_BED("hbp", p);
SEND_PID_INFO_BED("hbi", i);
SEND_PID_INFO_BED("hbd", d);
#define SEND_PID_INFO_BED(A, B) TERN(PIDTEMPBED, SEND_VALasTXT(A, getBedPID_K##B()), SEND_NA(A))
SEND_PID_INFO_0("p0", p); SEND_PID_INFO_0("i0", i); SEND_PID_INFO_0("d0", d);
SEND_PID_INFO_1("p1", p); SEND_PID_INFO_1("i1", i); SEND_PID_INFO_1("d1", d);
SEND_PID_INFO_BED("hbp", p); SEND_PID_INFO_BED("hbi", i); SEND_PID_INFO_BED("hbd", d);
break;
}
}

View file

@ -54,10 +54,14 @@
// TFT panel commands
#define msg_welcome MACHINE_NAME " Ready."
#define SEND_TEMP(x,y,t,z) (nextion.tftSend(F(x)), nextion.tftSend(F(".txt=\"")), LCD_SERIAL.print(y), nextion.tftSend(F(t)), LCD_SERIAL.print(z), nextion.tftSend(F("\"\xFF\xFF\xFF")))
#define SEND_VAL(x,y) (nextion.tftSend(F(x)), nextion.tftSend(F(".val=")), LCD_SERIAL.print(y), nextion.tftSend(F("\xFF\xFF\xFF")))
#define SEND_TXT(x,y) (nextion.tftSend(F(x)), nextion.tftSend(F(".txt=\"")), nextion.tftSend(F(y)), nextion.tftSend(F("\"\xFF\xFF\xFF")))
#define SEND_TXT_F(x,y) (nextion.tftSend(F(x)), nextion.tftSend(F(".txt=\"")), nextion.tftSend(y), nextion.tftSend(F("\"\xFF\xFF\xFF")))
#define SEND_VALasTXT(x,y) (nextion.tftSend(F(x)), nextion.tftSend(F(".txt=\"")), LCD_SERIAL.print(y), nextion.tftSend(F("\"\xFF\xFF\xFF")))
#define SEND_TXT_END(x) (nextion.tftSend(F(x)), nextion.tftSend(F("\xFF\xFF\xFF")))
#define SEND_PCO2(x,y,z) (nextion.tftSend(F(x)), LCD_SERIAL.print(y), nextion.tftSend(F(".pco=")), nextion.tftSend(F(z)), nextion.tftSend(F("\xFF\xFF\xFF")))
#define TXT_OPEN() nextion.tftSend(F(".txt=\""))
#define TXT_CLOSE() nextion.tftSend(F("\"\xFF\xFF\xFF"))
#define VAL_OPEN() nextion.tftSend(F(".val="))
#define VAL_CLOSE() nextion.tftSend(F("\xFF\xFF\xFF"))
#define SEND_TEMP(x,y,t,z) (nextion.tftSend(F(x)), TXT_OPEN(), LCD_SERIAL.print(y), nextion.tftSend(F(t)), LCD_SERIAL.print(z), TXT_CLOSE()) // XXX.txt="YYYTTTZZZ"<end>
#define SEND_VAL(x,y) (nextion.tftSend(F(x)), VAL_OPEN(), LCD_SERIAL.print(y), VAL_CLOSE()) // XXX.val=YYY<end>
#define SEND_TXT(x,y) (nextion.tftSend(F(x)), TXT_OPEN(), nextion.tftSend(F(y)), TXT_CLOSE()) // XXX.txt="YYY"<end>
#define SEND_TXT_F(x,y) (nextion.tftSend(F(x)), TXT_OPEN(), nextion.tftSend(y), TXT_CLOSE()) // XXX.txt="YYY"<end>
#define SEND_VALasTXT(x,y) (nextion.tftSend(F(x)), TXT_OPEN(), LCD_SERIAL.print(y), TXT_CLOSE()) // XXX.txt="YYY"<end>
#define SEND_TXT_END(x) (nextion.tftSend(F(x)), VAL_CLOSE()) // XXX<end>
#define SEND_PCO2(x,y,z) (nextion.tftSend(F(x)), LCD_SERIAL.print(y), nextion.tftSend(F(".pco=")), nextion.tftSend(F(z)), VAL_CLOSE()) // XXXYYY.pco=ZZZ<end>

View file

@ -1213,13 +1213,13 @@ namespace ExtUI {
#endif
}
void onStatusChanged(FSTR_P const fstr) {
void onStatusChanged_P(PGM_P const pstr) {
#ifdef __AVR__
char msg[strlen_P(FTOP(fstr)) + 1];
strcpy_P(msg, FTOP(fstr));
char msg[strlen_P(pstr) + 1];
strcpy_P(msg, pstr);
onStatusChanged(msg);
#else
onStatusChanged(FTOP(fstr));
onStatusChanged(pstr);
#endif
}

View file

@ -530,8 +530,9 @@ namespace ExtUI {
void onPauseMode(const PauseMessage message, const PauseMode mode=PAUSE_MODE_SAME, const uint8_t extruder=active_extruder);
#endif
void onStatusChanged_P(PGM_P const msg);
inline void onStatusChanged(FSTR_P const fstr) { onStatusChanged_P(FTOP(fstr)); }
void onStatusChanged(const char * const msg);
void onStatusChanged(FSTR_P const fstr);
void onHomingStart();
void onHomingDone();

View file

@ -37,7 +37,7 @@ namespace LanguageNarrow_an {
constexpr uint8_t CHARSIZE = 1;
LSTR LANGUAGE = _UxGT("Aragonese");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" parada.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" parada.");
LSTR MSG_MEDIA_INSERTED = _UxGT("Tarcheta mesa");
LSTR MSG_MEDIA_REMOVED = _UxGT("Tarcheta sacada");
LSTR MSG_LCD_ENDSTOPS = _UxGT("Endstops"); // Max length 8 characters

View file

@ -36,7 +36,7 @@ namespace LanguageNarrow_bg {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Bulgarian");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" Готов.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" Готов.");
LSTR MSG_MEDIA_INSERTED = _UxGT("Картата е поставена");
LSTR MSG_MEDIA_REMOVED = _UxGT("Картата е извадена");
LSTR MSG_MAIN_MENU = _UxGT("Меню");

View file

@ -33,7 +33,7 @@ namespace LanguageNarrow_ca {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Catalan");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" preparada.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" preparada.");
LSTR MSG_MEDIA_INSERTED = _UxGT("Targeta detectada.");
LSTR MSG_MEDIA_REMOVED = _UxGT("Targeta extreta.");
LSTR MSG_LCD_ENDSTOPS = _UxGT("Endstops");

View file

@ -41,7 +41,7 @@ namespace LanguageNarrow_cz {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Czech");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" připraven.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" připraven.");
LSTR MSG_YES = _UxGT("ANO");
LSTR MSG_NO = _UxGT("NE");
LSTR MSG_BACK = _UxGT("Zpět");

View file

@ -36,7 +36,7 @@ namespace LanguageNarrow_da {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Danish");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" er klar");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" er klar");
LSTR MSG_MEDIA_INSERTED = _UxGT("Kort isat");
LSTR MSG_MEDIA_REMOVED = _UxGT("Kort fjernet");
LSTR MSG_MAIN_MENU = _UxGT("Menu");

View file

@ -34,7 +34,7 @@ namespace LanguageNarrow_de {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Deutsch");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" bereit");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" bereit");
LSTR MSG_YES = _UxGT("JA");
LSTR MSG_NO = _UxGT("NEIN");
LSTR MSG_HIGH = _UxGT("HOCH");

View file

@ -36,7 +36,7 @@ namespace LanguageNarrow_el {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Greek (Greece)");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" έτοιμος.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" έτοιμος.");
LSTR MSG_YES = _UxGT("ΝΑΙ");
LSTR MSG_NO = _UxGT("ΟΧΙ");
LSTR MSG_BACK = _UxGT("Πίσω");

View file

@ -36,7 +36,7 @@ namespace LanguageNarrow_el_gr {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Greek (Greece)");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" έτοιμο.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" έτοιμο.");
LSTR MSG_MEDIA_INSERTED = _UxGT("Εισαγωγή κάρτας");
LSTR MSG_MEDIA_REMOVED = _UxGT("Αφαίρεση κάρτας");
LSTR MSG_LCD_ENDSTOPS = _UxGT("Endstops"); // Max length 8 characters

View file

@ -69,7 +69,7 @@ namespace LanguageNarrow_en {
LSTR LANGUAGE = _UxGT("English");
// These strings should be translated
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" Ready.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" Ready.");
LSTR MSG_YES = _UxGT("YES");
LSTR MSG_NO = _UxGT("NO");
LSTR MSG_HIGH = _UxGT("HIGH");

View file

@ -36,7 +36,7 @@ namespace LanguageNarrow_es {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Spanish");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" Lista");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" Lista");
LSTR MSG_YES = _UxGT("SI");
LSTR MSG_NO = _UxGT("NO");
LSTR MSG_BACK = _UxGT("Atrás");

View file

@ -37,7 +37,7 @@ namespace LanguageNarrow_eu {
constexpr uint8_t CHARSIZE = 1;
LSTR LANGUAGE = _UxGT("Basque-Euskera");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" prest.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" prest.");
LSTR MSG_BACK = _UxGT("Atzera");
LSTR MSG_MEDIA_INSERTED = _UxGT("Txartela sartuta");
LSTR MSG_MEDIA_REMOVED = _UxGT("Txartela kenduta");

View file

@ -36,7 +36,7 @@ namespace LanguageNarrow_fi {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Finnish");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" valmis.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" valmis.");
LSTR MSG_MEDIA_INSERTED = _UxGT("Kortti asetettu");
LSTR MSG_MEDIA_REMOVED = _UxGT("Kortti poistettu");
LSTR MSG_MAIN_MENU = _UxGT("Palaa");

View file

@ -36,7 +36,7 @@ namespace LanguageNarrow_fr {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Français");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" prête.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" prête.");
LSTR MSG_YES = _UxGT("Oui");
LSTR MSG_NO = _UxGT("Non");
LSTR MSG_BACK = _UxGT("Retour");

View file

@ -36,7 +36,7 @@ namespace LanguageNarrow_fr_na {
LSTR LANGUAGE = _UxGT("Francais");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" prete.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" prete.");
LSTR MSG_YES = _UxGT("Oui");
LSTR MSG_NO = _UxGT("Non");
LSTR MSG_BACK = _UxGT("Retour");

View file

@ -38,7 +38,7 @@ namespace LanguageNarrow_gl {
constexpr uint8_t CHARSIZE = 1;
LSTR LANGUAGE = _UxGT("Galician");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" lista.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" lista.");
LSTR MSG_YES = _UxGT("SI");
LSTR MSG_NO = _UxGT("NON");
LSTR MSG_BACK = _UxGT("Atrás");

View file

@ -36,7 +36,7 @@ namespace LanguageNarrow_hr {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Croatian");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" spreman.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" spreman.");
LSTR MSG_MEDIA_INSERTED = _UxGT("SD kartica umetnuta");
LSTR MSG_MEDIA_REMOVED = _UxGT("SD kartica uklonjena");
LSTR MSG_LCD_ENDSTOPS = _UxGT("Endstops"); // Max length 8 characters

View file

@ -39,7 +39,7 @@ namespace LanguageNarrow_hu {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Magyar");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" Kész.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" Kész.");
LSTR MSG_YES = _UxGT("IGEN");
LSTR MSG_NO = _UxGT("NEM");
LSTR MSG_BACK = _UxGT("Vissza");

View file

@ -46,7 +46,7 @@ namespace LanguageNarrow_it {
constexpr uint8_t CHARSIZE = 1;
LSTR LANGUAGE = _UxGT("Italiano");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" pronta.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" pronta.");
LSTR MSG_YES = _UxGT("Si");
LSTR MSG_NO = _UxGT("No");
LSTR MSG_HIGH = _UxGT("ALTO");

View file

@ -41,7 +41,7 @@ namespace LanguageNarrow_jp_kana {
// This translation can be improved by using the full charset of unicode codeblock U+30A0 to U+30FF.
// 片仮名表示定義
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" ジュンビカンリョウ");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" ジュンビカンリョウ");
LSTR MSG_MEDIA_INSERTED = _UxGT("メディアガソウニュウサレマシタ"); // "Card inserted"
LSTR MSG_MEDIA_REMOVED = _UxGT("メディアガアリマセン"); // "Card removed"
LSTR MSG_RELEASE_MEDIA = _UxGT("メディアノトリダシ");

View file

@ -33,7 +33,7 @@ namespace LanguageNarrow_ko_KR {
constexpr uint8_t CHARSIZE = 1;
LSTR LANGUAGE = _UxGT("Korean");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" 준비.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" 준비.");
LSTR MSG_BACK = _UxGT("뒤로");
LSTR MSG_MEDIA_INSERTED = _UxGT("카드 삽입됨");
LSTR MSG_MEDIA_REMOVED = _UxGT("카드 제거됨");

View file

@ -37,7 +37,7 @@ namespace LanguageNarrow_nl {
constexpr uint8_t CHARSIZE = 1;
LSTR LANGUAGE = _UxGT("Dutch");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" gereed.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" gereed.");
LSTR MSG_BACK = _UxGT("Terug");
LSTR MSG_MEDIA_INSERTED = _UxGT("Kaart ingestoken");
LSTR MSG_MEDIA_REMOVED = _UxGT("Kaart verwijderd");

View file

@ -44,7 +44,7 @@ namespace LanguageNarrow_pl {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Polski");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" gotowy.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" gotowy.");
LSTR MSG_YES = _UxGT("TAK");
LSTR MSG_NO = _UxGT("NIE");
LSTR MSG_BACK = _UxGT("Wstecz");

View file

@ -37,7 +37,7 @@ namespace LanguageNarrow_pt {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Portuguese");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" pronta.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" pronta.");
LSTR MSG_MEDIA_INSERTED = _UxGT("Cartão inserido");
LSTR MSG_MEDIA_REMOVED = _UxGT("Cartão removido");
LSTR MSG_MAIN_MENU = _UxGT("Menu principal");

View file

@ -34,7 +34,7 @@ namespace LanguageNarrow_pt_br {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Portuguese (BR)");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" pronto.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" pronto.");
LSTR MSG_YES = _UxGT("SIM");
LSTR MSG_NO = _UxGT("NÃO");
LSTR MSG_BACK = _UxGT("Voltar");

View file

@ -35,7 +35,7 @@ namespace LanguageNarrow_ro {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Romanian");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" Pregatit.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" Pregatit.");
LSTR MSG_YES = _UxGT("DA");
LSTR MSG_NO = _UxGT("NU");
LSTR MSG_BACK = _UxGT("Inapoi");

View file

@ -35,7 +35,7 @@ namespace LanguageNarrow_ru {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Russian");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" Готов.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" Готов.");
LSTR MSG_YES = _UxGT("Да");
LSTR MSG_NO = _UxGT("Нет");
LSTR MSG_BACK = _UxGT("Назад");

View file

@ -47,7 +47,7 @@ namespace LanguageNarrow_sk {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Slovenčina");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" pripravená.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" pripravená.");
LSTR MSG_YES = _UxGT("ÁNO");
LSTR MSG_NO = _UxGT("NIE");
LSTR MSG_HIGH = _UxGT("VYSOKÁ");

View file

@ -36,7 +36,7 @@ namespace LanguageNarrow_sv {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Swedish");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" Redo.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" Redo.");
LSTR MSG_YES = _UxGT("JA");
LSTR MSG_NO = _UxGT("NEJ");
LSTR MSG_BACK = _UxGT("Bakåt");

View file

@ -45,7 +45,7 @@ namespace LanguageNarrow_tr {
LSTR LANGUAGE = _UxGT("Turkish");
// These strings should be translated
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" Hazır.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" Hazır.");
LSTR MSG_YES = _UxGT("EVET");
LSTR MSG_NO = _UxGT("HAYIR");
LSTR MSG_HIGH = _UxGT("YÜKSEK");

View file

@ -36,7 +36,7 @@ namespace LanguageNarrow_uk {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Ukrainian");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" Готовий.");
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" Готовий.");
LSTR MSG_YES = _UxGT("ТАК");
LSTR MSG_NO = _UxGT("НІ");
LSTR MSG_BACK = _UxGT("Назад");

View file

@ -33,7 +33,7 @@ namespace LanguageNarrow_vi {
constexpr uint8_t CHARSIZE = 2;
LSTR LANGUAGE = _UxGT("Vietnamese");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" Sẵn sàng."); // Ready
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT(" Sẵn sàng."); // Ready
LSTR MSG_BACK = _UxGT("Trở lại"); // Back
LSTR MSG_MEDIA_ABORTING = _UxGT("Đang hủy bỏ...");
LSTR MSG_MEDIA_INSERTED = _UxGT("Phương tiện được cắm vào"); // Media inserted

View file

@ -33,7 +33,7 @@ namespace LanguageNarrow_zh_CN {
constexpr uint8_t CHARSIZE = 3;
LSTR LANGUAGE = _UxGT("Simplified Chinese");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT("已就绪."); // " ready."
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT("已就绪."); // " ready."
LSTR MSG_MARLIN = _UxGT("马林");
LSTR MSG_YES = _UxGT("");
LSTR MSG_NO = _UxGT("");

View file

@ -33,7 +33,7 @@ namespace LanguageNarrow_zh_TW {
constexpr uint8_t CHARSIZE = 3;
LSTR LANGUAGE = _UxGT("Traditional Chinese");
LSTR WELCOME_MSG = MACHINE_NAME _UxGT("已就緒."); // " ready."
LSTR WELCOME_MSG = MACHINE_NAME_SUBST _UxGT("已就緒."); // " ready."
LSTR MSG_YES = _UxGT(""); // "YES"
LSTR MSG_NO = _UxGT(""); // "NO"
LSTR MSG_BACK = _UxGT("返回"); // "Back"

View file

@ -31,75 +31,6 @@
#include "marlinui.h"
#include "lcdprint.h"
/**
* expand_u8str_P
*
* Expand a string with optional substitutions:
*
* $ displays the clipped string given by fstr or cstr
* { displays '0'....'10' for indexes 0 - 10
* ~ displays '1'....'11' for indexes 0 - 10
* * displays 'E1'...'E11' for indexes 0 - 10 (By default. Uses LCD_FIRST_TOOL)
* @ displays an axis name such as XYZUVW, or E for an extruder
*
* Return the number of characters emitted
*/
lcd_uint_t expand_u8str_P(char * const outstr, PGM_P const ptpl, const int8_t ind, const char *cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/, const lcd_uint_t maxlen/*=LCD_WIDTH*/) {
const uint8_t *p = (uint8_t*)ptpl;
char *o = outstr;
int8_t n = maxlen;
while (n > 0) {
lchar_t wc;
uint8_t *psc = (uint8_t *)p;
p = get_utf8_value_cb(p, read_byte_rom, wc);
if (!wc) break;
if (wc == '{' || wc == '~' || wc == '*') {
if (ind >= 0) {
if (wc == '*') { *o++ = 'E'; n--; }
if (n) {
int8_t inum = ind + ((wc == '{') ? 0 : LCD_FIRST_TOOL);
if (inum >= 10) {
*o++ = ('0' + (inum / 10)); n--;
inum %= 10;
}
if (n) { *o++ = '0' + inum; n--; }
}
}
else {
PGM_P const b = ind == -2 ? GET_TEXT(MSG_CHAMBER) : GET_TEXT(MSG_BED);
strlcpy_P(o, b, n + 1);
n -= utf8_strlen(o);
o += strlen(o);
}
if (n > 0) {
strlcpy_P(o, (PGM_P)p, n + 1);
n -= utf8_strlen(o);
o += strlen(o);
break;
}
}
else if (wc == '$' && fstr) {
strlcpy_P(o, FTOP(fstr), n + 1);
n -= utf8_strlen(o);
o += strlen(o);
}
else if (wc == '$' && cstr) {
strlcpy(o, cstr, n + 1);
n -= utf8_strlen(o);
o += strlen(o);
}
else {
if (wc == '@')
*o++ = AXIS_CHAR(ind);
else
while (psc != p) *o++ = read_byte_rom(psc++);
*o = '\0';
n--;
}
}
return maxlen - n;
}
/**
* lcd_put_u8str_P
*
@ -113,7 +44,7 @@ lcd_uint_t expand_u8str_P(char * const outstr, PGM_P const ptpl, const int8_t in
*
* Return the number of characters emitted
*/
lcd_uint_t lcd_put_u8str_P(PGM_P const ptpl, const int8_t ind, const char *cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/, const lcd_uint_t maxlen/*=LCD_WIDTH*/) {
lcd_uint_t lcd_put_u8str_P(PGM_P const ptpl, const int8_t ind, const char *cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/, const lcd_uint_t maxlen/*=MAX_MESSAGE_SIZE*/) {
char estr[maxlen * LANG_CHARSIZE + 2];
const lcd_uint_t outlen = expand_u8str_P(estr, ptpl, ind, cstr, fstr, maxlen);
lcd_put_u8str_max(estr, maxlen * (MENU_FONT_WIDTH));

View file

@ -200,29 +200,6 @@ inline int lcd_put_u8str(const lcd_uint_t col, const lcd_uint_t row, FSTR_P cons
return lcd_put_u8str_P(col, row, FTOP(fstr));
}
/**
* @brief Expand a string with optional substitution
* @details Expand a string with optional substitutions:
* $ : the clipped string given by fstr or cstr
* { : '0'....'10' for indexes 0 - 10
* ~ : '1'....'11' for indexes 0 - 10
* * : 'E1'...'E11' for indexes 0 - 10 (By default. Uses LCD_FIRST_TOOL)
* @ : an axis name such as XYZUVW, or E for an extruder
*
* @param *outstr The output destination buffer
* @param ptpl A ROM string (template)
* @param ind An index value to use for = ~ * substitution
* @param cstr An SRAM C-string to use for $ substitution
* @param fstr A ROM F-string to use for $ substitution
* @param maxlen The maximum size of the string (in pixels on GLCD)
* @return the output width (in pixels on GLCD)
*/
lcd_uint_t expand_u8str_P(char * const outstr, PGM_P const ptpl, const int8_t ind, const char *cstr=nullptr, FSTR_P const fstr=nullptr, const lcd_uint_t maxlen=LCD_WIDTH);
inline lcd_uint_t expand_u8str(char * const outstr, FSTR_P const ftpl, const int8_t ind, const char *cstr=nullptr, FSTR_P const fstr=nullptr, const lcd_uint_t maxlen=LCD_WIDTH) {
return expand_u8str_P(outstr, FTOP(ftpl), ind, cstr, fstr, maxlen);
}
/**
* @brief Draw a string with optional substitution
* @details Print a string with optional substitutions:
@ -239,8 +216,8 @@ inline lcd_uint_t expand_u8str(char * const outstr, FSTR_P const ftpl, const int
* @param maxlen The maximum size of the string (in pixels on GLCD)
* @return the output width (in pixels on GLCD)
*/
lcd_uint_t lcd_put_u8str_P(PGM_P const ptpl, const int8_t ind, const char *cstr=nullptr, FSTR_P const fstr=nullptr, const lcd_uint_t maxlen=LCD_WIDTH);
inline lcd_uint_t lcd_put_u8str_P(const lcd_uint_t col, const lcd_uint_t row, PGM_P const ptpl, const int8_t ind, const char *cstr=nullptr, FSTR_P const fstr=nullptr, const lcd_uint_t maxlen=LCD_WIDTH) {
lcd_uint_t lcd_put_u8str_P(PGM_P const ptpl, const int8_t ind, const char *cstr=nullptr, FSTR_P const fstr=nullptr, const lcd_uint_t maxlen=MAX_MESSAGE_SIZE);
inline lcd_uint_t lcd_put_u8str_P(const lcd_uint_t col, const lcd_uint_t row, PGM_P const ptpl, const int8_t ind, const char *cstr=nullptr, FSTR_P const fstr=nullptr, const lcd_uint_t maxlen=MAX_MESSAGE_SIZE) {
lcd_moveto(col, row);
return lcd_put_u8str_P(ptpl, ind, cstr, fstr, maxlen);
}
@ -255,14 +232,14 @@ inline lcd_uint_t lcd_put_u8str_P(const lcd_uint_t col, const lcd_uint_t row, PG
* @param maxlen The maximum size of the string (in pixels on GLCD)
* @return the output width (in pixels on GLCD)
*/
inline lcd_uint_t lcd_put_u8str(FSTR_P const ftpl, const int8_t ind, const char *cstr=nullptr, FSTR_P const fstr=nullptr, const lcd_uint_t maxlen=LCD_WIDTH) {
inline lcd_uint_t lcd_put_u8str(FSTR_P const ftpl, const int8_t ind, const char *cstr=nullptr, FSTR_P const fstr=nullptr, const lcd_uint_t maxlen=MAX_MESSAGE_SIZE) {
return lcd_put_u8str_P(FTOP(ftpl), ind, cstr, fstr, maxlen);
}
/**
* @param col
* @param row
*/
inline lcd_uint_t lcd_put_u8str(const lcd_uint_t col, const lcd_uint_t row, FSTR_P const ftpl, const int8_t ind, const char *cstr=nullptr, FSTR_P const fstr=nullptr, const lcd_uint_t maxlen=LCD_WIDTH) {
inline lcd_uint_t lcd_put_u8str(const lcd_uint_t col, const lcd_uint_t row, FSTR_P const ftpl, const int8_t ind, const char *cstr=nullptr, FSTR_P const fstr=nullptr, const lcd_uint_t maxlen=MAX_MESSAGE_SIZE) {
return lcd_put_u8str_P(col, row, FTOP(ftpl), ind, cstr, fstr, maxlen);
}

View file

@ -22,7 +22,7 @@
#include "../inc/MarlinConfig.h"
#include "../MarlinCore.h" // for printingIsPaused
#include "../MarlinCore.h" // for printingIsPaused, machine_name
#include "../gcode/parser.h" // for axis_is_rotational, using_inch_units
#if HAS_LED_POWEROFF_TIMEOUT || ALL(HAS_WIRED_LCD, PRINTER_EVENT_LEDS) || (HAS_BACKLIGHT_TIMEOUT && defined(NEOPIXEL_BKGD_INDEX_FIRST))
@ -72,7 +72,7 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;
#if ENABLED(STATUS_MESSAGE_SCROLLING)
uint8_t MarlinUI::status_scroll_offset; // = 0
#endif
MString<MAX_MESSAGE_LENGTH> MarlinUI::status_message;
MString<MAX_MESSAGE_SIZE> MarlinUI::status_message;
uint8_t MarlinUI::alert_level; // = 0
#if HAS_STATUS_MESSAGE_TIMEOUT
millis_t MarlinUI::status_message_expire_ms; // = 0
@ -1462,6 +1462,62 @@ void MarlinUI::host_notify(const char * const cstr) {
#include <stdarg.h>
uint8_t expand_u8str_P(char * const outstr, PGM_P const ptpl, const int8_t ind, const char *cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/, const uint8_t maxlen/*=MAX_MESSAGE_SIZE*/) {
const uint8_t *p = (uint8_t*)ptpl;
char *o = outstr;
int8_t n = maxlen;
while (n > 0) {
lchar_t wc;
uint8_t *psc = (uint8_t *)p;
p = get_utf8_value_cb(p, read_byte_rom, wc);
if (!wc) break;
if (wc == '{' || wc == '~' || wc == '*') {
if (ind >= 0) {
if (wc == '*') { *o++ = 'E'; n--; }
if (n) {
int8_t inum = ind + ((wc == '{') ? 0 : LCD_FIRST_TOOL);
if (inum >= 10) {
*o++ = ('0' + (inum / 10)); n--;
inum %= 10;
}
if (n) { *o++ = '0' + inum; n--; }
}
}
else {
PGM_P const b = ind == -2 ? GET_TEXT(MSG_CHAMBER) : GET_TEXT(MSG_BED);
strlcpy_P(o, b, n + 1);
n -= utf8_strlen(o);
o += strlen(o);
}
if (n > 0) {
strlcpy_P(o, (PGM_P)p, n + 1);
n -= utf8_strlen(o);
o += strlen(o);
break;
}
}
else if (wc == '$' && fstr) {
strlcpy_P(o, FTOP(fstr), n + 1);
n -= utf8_strlen(o);
o += strlen(o);
}
else if (wc == '$' && cstr) {
strlcpy(o, cstr, n + 1);
n -= utf8_strlen(o);
o += strlen(o);
}
else {
if (wc == '@')
*o++ = AXIS_CHAR(ind);
else
while (psc != p) *o++ = read_byte_rom(psc++);
*o = '\0';
n--;
}
}
return maxlen - n;
}
#if HAS_STATUS_MESSAGE
#if ENABLED(EXTENSIBLE_UI)
@ -1492,7 +1548,16 @@ void MarlinUI::host_notify(const char * const cstr) {
else if (print_job_timer.needsService(3)) msg = F("> " SERVICE_NAME_3 "!");
#endif
else if (!no_welcome) msg = GET_TEXT_F(WELCOME_MSG);
else if (!no_welcome) {
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
char new_status[MAX_MESSAGE_SIZE + 1];
expand_u8str_P(new_status, GET_TEXT(WELCOME_MSG), 0, &machine_name);
_set_status_and_level(new_status, -1);
return;
#else
msg = GET_TEXT_F(WELCOME_MSG);
#endif
}
else if (ENABLED(STATUS_DO_CLEAR_EMPTY))
msg = F("");
@ -1528,7 +1593,7 @@ void MarlinUI::host_notify(const char * const cstr) {
MString<30> msg;
pgm ? msg.set_P(ustr) : msg.set(ustr);
status_message.set(&msg).utrunc(MAX_MESSAGE_LENGTH);
status_message.set(&msg).utrunc(MAX_MESSAGE_SIZE);
finish_status(level > 0); // Persist if the status has a level
}
@ -1546,7 +1611,7 @@ void MarlinUI::host_notify(const char * const cstr) {
pgm ? host_notify_P(ustr) : host_notify(ustr);
// Remove the last partial Unicode glyph, if any
(pgm ? status_message.set_P(ustr) : status_message.set(ustr)).utrunc(MAX_MESSAGE_LENGTH);
(pgm ? status_message.set_P(ustr) : status_message.set(ustr)).utrunc(MAX_MESSAGE_SIZE);
finish_status(persist);
}
@ -1574,7 +1639,7 @@ void MarlinUI::host_notify(const char * const cstr) {
va_list args;
va_start(args, pfmt);
vsnprintf_P(status_message, MAX_MESSAGE_LENGTH, pfmt, args);
vsnprintf_P(status_message, MAX_MESSAGE_SIZE, pfmt, args);
va_end(args);
host_notify(status_message);
@ -1865,6 +1930,7 @@ void MarlinUI::host_notify(const char * const cstr) {
#endif // HAS_MEDIA
#if HAS_MARLINUI_MENU
void MarlinUI::reset_settings() {
settings.reset();
completion_feedback();
@ -1886,7 +1952,7 @@ void MarlinUI::host_notify(const char * const cstr) {
}
#endif
#endif
#endif // HAS_MARLINUI_MENU
#if ENABLED(EEPROM_SETTINGS)

View file

@ -369,17 +369,7 @@ public:
#if HAS_STATUS_MESSAGE
#if ANY(HAS_WIRED_LCD, DWIN_LCD_PROUI)
#if ENABLED(STATUS_MESSAGE_SCROLLING)
#define MAX_MESSAGE_LENGTH _MAX(LONG_FILENAME_LENGTH, MAX_LANG_CHARSIZE * 2 * (LCD_WIDTH))
#else
#define MAX_MESSAGE_LENGTH (MAX_LANG_CHARSIZE * (LCD_WIDTH))
#endif
#else
#define MAX_MESSAGE_LENGTH 63
#endif
static MString<MAX_MESSAGE_LENGTH> status_message;
static MString<MAX_MESSAGE_SIZE> status_message;
static uint8_t alert_level; // Higher levels block lower levels
#if HAS_STATUS_MESSAGE_TIMEOUT
@ -410,7 +400,6 @@ public:
#else
#define MAX_MESSAGE_LENGTH 1
static constexpr bool has_status() { return false; }
static bool set_alert_level(int8_t) { return false; }
@ -912,6 +901,29 @@ private:
#endif
};
/**
* @brief Expand a string with optional substitution
* @details Expand a string with optional substitutions:
* $ : the clipped string given by fstr or cstr
* { : '0'....'10' for indexes 0 - 10
* ~ : '1'....'11' for indexes 0 - 10
* * : 'E1'...'E11' for indexes 0 - 10 (By default. Uses LCD_FIRST_TOOL)
* @ : an axis name such as XYZUVW, or E for an extruder
*
* @param *outstr The output destination buffer
* @param ptpl A ROM string (template)
* @param ind An index value to use for = ~ * substitution
* @param cstr An SRAM C-string to use for $ substitution
* @param fstr A ROM F-string to use for $ substitution
* @param maxlen The maximum size of the string (in pixels on GLCD)
* @return the output width (in pixels on GLCD)
*/
uint8_t expand_u8str_P(char * const outstr, PGM_P const ptpl, const int8_t ind, const char *cstr=nullptr, FSTR_P const fstr=nullptr, const uint8_t maxlen=MAX_MESSAGE_SIZE);
inline uint8_t expand_u8str(char * const outstr, FSTR_P const ftpl, const int8_t ind, const char *cstr=nullptr, FSTR_P const fstr=nullptr, const uint8_t maxlen=MAX_MESSAGE_SIZE) {
return expand_u8str_P(outstr, FTOP(ftpl), ind, cstr, fstr, maxlen);
}
#define LCD_MESSAGE_F(S) ui.set_status(F(S))
#define LCD_MESSAGE(M) ui.set_status(GET_TEXT_F(M))
#define LCD_MESSAGE_MIN(M) ui.set_min_status(GET_TEXT_F(M))

View file

@ -30,6 +30,10 @@
#include "menu_item.h"
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
#include "../../MarlinCore.h"
#endif
#if HAS_GAMES
#include "game/game.h"
#endif
@ -246,7 +250,11 @@ void menu_info_board() {
STATIC_ITEM(MSG_MARLIN, SS_DEFAULT|SS_INVERT); // Marlin
STATIC_ITEM_F(F(SHORT_BUILD_VERSION)); // x.x.x-Branch
STATIC_ITEM_F(F(STRING_DISTRIBUTION_DATE)); // YYYY-MM-DD HH:MM
STATIC_ITEM_F(F(MACHINE_NAME), SS_DEFAULT|SS_INVERT); // My3DPrinter
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
STATIC_ITEM_C(&machine_name, SS_DEFAULT|SS_INVERT); // My3DPrinter
#else
STATIC_ITEM_F(F(MACHINE_NAME), SS_DEFAULT|SS_INVERT); // My3DPrinter
#endif
STATIC_ITEM_F(F(WEBSITE_URL)); // www.my3dprinter.com
PSTRING_ITEM(MSG_INFO_EXTRUDERS, STRINGIFY(EXTRUDERS), SS_CENTER); // Extruders: 2
#if HAS_LEVELING

View file

@ -358,20 +358,24 @@ class MenuItem_bool : public MenuEditItemBase {
// STATIC_ITEM draws a styled string with no highlight.
// Parameters: label [, style [, char *value] ]
#define STATIC_ITEM_INNER_F(FLABEL, V...) do{ \
#define STATIC_SKIP() do{ \
if (_skipStatic && encoderLine <= _thisItemNr) { \
ui.encoderPosition += ENCODER_STEPS_PER_MENU_ITEM; \
++encoderLine; \
} \
if (ui.should_draw()) \
MenuItem_static::draw(_lcdLineNr, FLABEL, ##V); \
} while(0)
}while(0)
#define STATIC_ITEM_INNER_F(FLABEL, V...) do{ \
STATIC_SKIP(); \
if (ui.should_draw()) \
MenuItem_static::draw(_lcdLineNr, FLABEL, ##V); \
}while(0)
#define STATIC_ITEM_F(FLABEL, V...) do{ \
if (MY_LINE()) \
STATIC_ITEM_INNER_F(FLABEL, ##V); \
NEXT_ITEM(); \
} while(0)
}while(0)
#define STATIC_ITEM_N_F(N, FLABEL, V...) do{ \
if (MY_LINE()) { \
@ -381,6 +385,16 @@ class MenuItem_bool : public MenuEditItemBase {
NEXT_ITEM(); \
}while(0)
#define STATIC_ITEM_N_F_C(N, FLABEL, CSTR, V...) do{ \
if (MY_LINE()) { \
MenuItemBase::init(N, CSTR); \
STATIC_ITEM_INNER_F(FLABEL, ##V); \
} \
NEXT_ITEM(); \
}while(0)
#define STATIC_ITEM_C(CSTR, V...) STATIC_ITEM_N_F_C(0, F("$"), CSTR, ##V)
// PSTRING_ITEM is like STATIC_ITEM
// but also takes a PSTR and style.

View file

@ -31,8 +31,6 @@
#include "../inc/MarlinConfigPre.h"
#if HAS_UTF8_UTILS
#include "../inc/MarlinConfig.h"
#if HAS_WIRED_LCD
@ -204,5 +202,3 @@ uint8_t utf8_byte_pos_by_char_num(const char *pstart, const uint8_t charnum) {
uint8_t utf8_byte_pos_by_char_num_P(PGM_P pstart, const uint8_t charnum) {
return utf8_byte_pos_by_char_num_cb(pstart, read_byte_rom, charnum);
}
#endif // HAS_UTF8_UTILS

View file

@ -570,6 +570,13 @@ typedef struct SettingsDataStruct {
uint8_t caselight_brightness; // M355 P
#endif
//
// CONFIGURABLE_MACHINE_NAME
//
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
MString<64> machine_name; // M550 P
#endif
//
// PASSWORD_FEATURE
//
@ -1686,6 +1693,13 @@ void MarlinSettings::postprocess() {
EEPROM_WRITE(caselight.brightness);
#endif
//
// CONFIGURABLE_MACHINE_NAME
//
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
EEPROM_WRITE(machine_name);
#endif
//
// Password feature
//
@ -2810,6 +2824,13 @@ void MarlinSettings::postprocess() {
EEPROM_READ(caselight.brightness);
#endif
//
// CONFIGURABLE_MACHINE_NAME
//
#if ENABLED(CONFIGURABLE_MACHINE_NAME)
EEPROM_READ(machine_name);
#endif
//
// Password feature
//
@ -3399,6 +3420,11 @@ void MarlinSettings::reset() {
//
TERN_(CASELIGHT_USES_BRIGHTNESS, caselight.brightness = CASE_LIGHT_DEFAULT_BRIGHTNESS);
//
// CONFIGURABLE_MACHINE_NAME
//
TERN_(CONFIGURABLE_MACHINE_NAME, machine_name = PSTR(MACHINE_NAME));
//
// TOUCH_SCREEN_CALIBRATION
//

View file

@ -12,5 +12,5 @@ set -e
restore_configs
use_example_configs ArmEd
opt_set X_DRIVER_TYPE TMC2130 Y_DRIVER_TYPE TMC2208
opt_enable LASER_SYNCHRONOUS_M106_M107
opt_enable CONFIGURABLE_MACHINE_NAME GCODE_QUOTED_STRINGS LASER_SYNCHRONOUS_M106_M107
exec_test $1 $2 "ArmEd Example Configuration with mixed TMC Drivers" "$3"

View file

@ -20,9 +20,10 @@ opt_set MOTHERBOARD BOARD_MINITRONICS20 SERIAL_PORT -1 \
opt_enable ENDSTOP_INTERRUPTS_FEATURE BLTOUCH Z_MIN_PROBE_REPEATABILITY_TEST \
FILAMENT_RUNOUT_SENSOR G26_MESH_VALIDATION MESH_EDIT_GFX_OVERLAY Z_SAFE_HOMING \
EEPROM_SETTINGS NOZZLE_PARK_FEATURE SDSUPPORT SD_CHECK_AND_RETRY \
REPRAPWORLD_GRAPHICAL_LCD ADAPTIVE_STEP_SMOOTHING \
REPRAPWORLD_GRAPHICAL_LCD ADAPTIVE_STEP_SMOOTHING LCD_INFO_MENU \
STATUS_MESSAGE_SCROLLING SET_PROGRESS_MANUALLY SHOW_REMAINING_TIME SET_REMAINING_TIME \
LONG_FILENAME_HOST_SUPPORT CUSTOM_FIRMWARE_UPLOAD M20_TIMESTAMP_SUPPORT \
CONFIGURABLE_MACHINE_NAME GCODE_QUOTED_STRINGS \
SCROLL_LONG_FILENAMES BABYSTEPPING DOUBLECLICK_FOR_Z_BABYSTEPPING \
MOVE_Z_WHEN_IDLE BABYSTEP_ZPROBE_OFFSET BABYSTEP_GFX_OVERLAY \
LIN_ADVANCE ADVANCED_PAUSE_FEATURE PARK_HEAD_ON_PAUSE MONITOR_DRIVER_STATUS

View file

@ -295,6 +295,7 @@ PIDTEMPBED = build_src_filter=+<src/gcode/config/M30
HAS_USER_THERMISTORS = build_src_filter=+<src/gcode/config/M305.cpp>
PIDTEMPCHAMBER = build_src_filter=+<src/gcode/config/M309.cpp>
SD_ABORT_ON_ENDSTOP_HIT = build_src_filter=+<src/gcode/config/M540.cpp>
CONFIGURABLE_MACHINE_NAME = build_src_filter=+<src/gcode/config/M550.cpp>
BAUD_RATE_GCODE = build_src_filter=+<src/gcode/config/M575.cpp>
HAS_SMART_EFF_MOD = build_src_filter=+<src/gcode/config/M672.cpp>
COOLANT_CONTROL|AIR_ASSIST = build_src_filter=+<src/gcode/control/M7-M9.cpp>