From 7e119f733fba284dd85c5d5cf4ee41229d64bb34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0ni=20M=C3=A1r=20Gilbert?= Date: Tue, 28 Feb 2023 21:33:17 +0000 Subject: [PATCH] Implement variant of enquecommand which accepts format string This eliminates many local buffers Change in memory: Flash: -450 bytes SRAM: 0 bytes --- Firmware/Marlin_main.cpp | 62 ++++++++++++-------------------------- Firmware/cardreader.cpp | 4 +-- Firmware/cmdqueue.cpp | 14 +++++++++ Firmware/cmdqueue.h | 4 +++ Firmware/first_lay_cal.cpp | 54 +++++++++------------------------ Firmware/first_lay_cal.h | 2 +- Firmware/ultralcd.cpp | 11 ++----- 7 files changed, 57 insertions(+), 94 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 4486c7322..4d2443dc5 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -3594,10 +3594,7 @@ static void gcode_M600(bool automatic, float x_position, float y_position, float // Recover feed rate feedmultiply = feedmultiplyBckp; - char cmd[9]; - sprintf_P(cmd, MSG_M220, feedmultiplyBckp); - enquecommand(cmd); - + enquecommandf(MSG_M220, feedmultiplyBckp); } lcd_setstatuspgm(MSG_WELCOME); @@ -10768,7 +10765,6 @@ ISR(INT4_vect) { } void recover_print(uint8_t automatic) { - char cmd[30]; lcd_update_enable(true); lcd_update(2); lcd_setstatuspgm(_i("Recovering print"));////MSG_RECOVERING_PRINT c=20 @@ -10780,21 +10776,16 @@ void recover_print(uint8_t automatic) { // and second also so one may remove the excess priming material. if(eeprom_read_byte((uint8_t*)EEPROM_UVLO) == 1) { - sprintf_P(cmd, PSTR("G1 Z%.3f F800"), current_position[Z_AXIS] + 25); - enquecommand(cmd); + enquecommandf(PSTR("G1 Z%.3f F800"), current_position[Z_AXIS] + 25); } // Home X and Y axes. Homing just X and Y shall not touch the babystep and the world2machine // transformation status. G28 will not touch Z when MBL is off. enquecommand_P(PSTR("G28 X Y")); // Set the target bed and nozzle temperatures and wait. - sprintf_P(cmd, PSTR("M104 S%d"), target_temperature[active_extruder]); - enquecommand(cmd); - sprintf_P(cmd, PSTR("M140 S%d"), target_temperature_bed); - enquecommand(cmd); - sprintf_P(cmd, PSTR("M109 S%d"), target_temperature[active_extruder]); - enquecommand(cmd); - + enquecommandf(PSTR("M104 S%d"), target_temperature[active_extruder]); + enquecommandf(PSTR("M140 S%d"), target_temperature_bed); + enquecommandf(PSTR("M109 S%d"), target_temperature[active_extruder]); enquecommand_P(MSG_M83); //E axis relative mode // If not automatically recoreverd (long power loss) @@ -10802,8 +10793,7 @@ void recover_print(uint8_t automatic) { //Extrude some filament to stabilize the pressure enquecommand_P(PSTR("G1 E5 F120")); // Retract to be consistent with a short pause - sprintf_P(cmd, G1_E_F2700, default_retraction); - enquecommand(cmd); + enquecommandf(G1_E_F2700, default_retraction); } printf_P(_N("After waiting for temp:\nCurrent pos X_AXIS:%.3f\nCurrent pos Y_AXIS:%.3f\n"), current_position[X_AXIS], current_position[Y_AXIS]); @@ -10894,7 +10884,6 @@ void restore_print_from_eeprom(bool mbl_was_active) { int feedrate_rec; int feedmultiply_rec; uint8_t fan_speed_rec; - char cmd[48]; char filename[FILENAME_LENGTH]; uint8_t depth = 0; char dir_name[9]; @@ -10926,9 +10915,8 @@ void restore_print_from_eeprom(bool mbl_was_active) { filename[8] = '\0'; MYSERIAL.print(filename); - strcat_P(filename, PSTR(".gco")); - sprintf_P(cmd, MSG_M23, filename); - enquecommand(cmd); + strcat_P(filename, PSTR(".gco")); + enquecommandf(MSG_M23, filename); uint32_t position = eeprom_read_dword((uint32_t*)(EEPROM_FILE_POSITION)); SERIAL_ECHOPGM("Position read from eeprom:"); MYSERIAL.println(position); @@ -10939,8 +10927,7 @@ void restore_print_from_eeprom(bool mbl_was_active) { float pos_y = eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 4)); if (pos_x != X_COORD_INVALID) { - sprintf_P(cmd, PSTR("G1 X%f Y%f F3000"), pos_x, pos_y); - enquecommand(cmd); + enquecommandf(PSTR("G1 X%f Y%f F3000"), pos_x, pos_y); } // Enable MBL and switch to logical positioning @@ -10948,37 +10935,29 @@ void restore_print_from_eeprom(bool mbl_was_active) { enquecommand_P(PSTR("PRUSA MBL V1")); // Move the Z axis down to the print, in logical coordinates. - sprintf_P(cmd, PSTR("G1 Z%f"), eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION_Z))); - enquecommand(cmd); + enquecommandf(PSTR("G1 Z%f"), eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION_Z))); // Restore acceleration settings float acceleration = eeprom_read_float((float*)(EEPROM_UVLO_ACCELL)); float retract_acceleration = eeprom_read_float((float*)(EEPROM_UVLO_RETRACT_ACCELL)); float travel_acceleration = eeprom_read_float((float*)(EEPROM_UVLO_TRAVEL_ACCELL)); - sprintf_P(cmd, PSTR("M204 P%f R%f T%f"), acceleration, retract_acceleration, travel_acceleration); - enquecommand(cmd); + enquecommandf(PSTR("M204 P%f R%f T%f"), acceleration, retract_acceleration, travel_acceleration); // Unretract. - sprintf_P(cmd, G1_E_F2700, default_retraction); - enquecommand(cmd); + enquecommandf(G1_E_F2700, default_retraction); // Recover final E axis position and mode float pos_e = eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION_E)); - sprintf_P(cmd, PSTR("G92 E%6.3f"), pos_e); - enquecommand(cmd); + enquecommandf(PSTR("G92 E%6.3f"), pos_e); if (eeprom_read_byte((uint8_t*)EEPROM_UVLO_E_ABS)) enquecommand_P(PSTR("M82")); //E axis abslute mode // Set the feedrates saved at the power panic. - sprintf_P(cmd, PSTR("G1 F%d"), feedrate_rec); - enquecommand(cmd); - sprintf_P(cmd, MSG_M220, feedmultiply_rec); - enquecommand(cmd); + enquecommandf(PSTR("G1 F%d"), feedrate_rec); + enquecommandf(MSG_M220, feedmultiply_rec); // Set the fan speed saved at the power panic. - sprintf_P(cmd, PSTR("M106 S%u"), fan_speed_rec); - enquecommand(cmd); + enquecommandf(PSTR("M106 S%u"), fan_speed_rec); // Set a position in the file. - sprintf_P(cmd, PSTR("M26 S%lu"), position); - enquecommand(cmd); + enquecommandf(PSTR("M26 S%lu"), position); enquecommand_P(PSTR("G4 S0")); enquecommand_P(PSTR("PRUSA uvlo")); } @@ -11149,7 +11128,6 @@ void stop_and_save_print_to_ram(float z_move, float e_move) // Rather than calling plan_buffer_line directly, push the move into the command queue so that // the caller can continue processing. This is used during powerpanic to save the state as we // move away from the print. - char buf[48]; if(e_move) { @@ -11163,15 +11141,13 @@ void stop_and_save_print_to_ram(float z_move, float e_move) // A snprintf would have been a safer call, but since it is not used // in the whole program, its implementation would bring more bytes to the total size // The behavior of dtostrf 8,3 should be roughly the same as %-0.3 - sprintf_P(buf, G1_E_F2700, e_move); - enquecommand(buf, false); + enquecommandf(G1_E_F2700, e_move); } if(z_move) { // Then lift Z axis - sprintf_P(buf, PSTR("G1 Z%-0.3f F%-0.3f"), saved_pos[Z_AXIS] + z_move, homing_feedrate[Z_AXIS]); - enquecommand(buf, false); + enquecommandf(PSTR("G1 Z%-0.3f F%-0.3f"), saved_pos[Z_AXIS] + z_move, homing_feedrate[Z_AXIS]); } // If this call is invoked from the main Arduino loop() function, let the caller know that the command diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp index f91f05b52..866a8eff4 100644 --- a/Firmware/cardreader.cpp +++ b/Firmware/cardreader.cpp @@ -649,10 +649,8 @@ void CardReader::checkautostart(bool force) if(p.name[9]!='~') //skip safety copies if(strncmp((char*)p.name,autoname,5)==0) { - char cmd[30]; // M23: Select SD file - sprintf_P(cmd, MSG_M23, autoname); - enquecommand(cmd); + enquecommandf(MSG_M23, autoname); // M24: Start/resume SD print enquecommand_P(MSG_M24); found=true; diff --git a/Firmware/cmdqueue.cpp b/Firmware/cmdqueue.cpp index cd5a3c348..98a013b37 100755 --- a/Firmware/cmdqueue.cpp +++ b/Firmware/cmdqueue.cpp @@ -1,3 +1,4 @@ +#include #include #include "cmdqueue.h" #include "cardreader.h" @@ -251,6 +252,19 @@ void cmdqueue_dump_to_serial() static const char bufferFull[] PROGMEM = "\" failed: Buffer full!"; static const char enqueingFront[] PROGMEM = "Enqueing to the front: \""; + +void enquecommandf(const char *fmt, ...) +{ + // MAX_CMD_SIZE is 96, but for formatting + // string we usually don't need more than 30 bytes + char cmd_buffer[30]; + va_list ap; + va_start(ap, fmt); + vsnprintf_P(cmd_buffer, sizeof(cmd_buffer), fmt, ap); + va_end(ap); + + enquecommand(cmd_buffer, false); +} //adds an command to the main command buffer //thats really done in a non-safe way. //needs overworking someday diff --git a/Firmware/cmdqueue.h b/Firmware/cmdqueue.h index 2ea684529..6c7b7a739 100644 --- a/Firmware/cmdqueue.h +++ b/Firmware/cmdqueue.h @@ -61,6 +61,10 @@ extern void cmdqueue_dump_to_serial_single_line(int nr, const char *p); extern void cmdqueue_dump_to_serial(); #endif /* CMDBUFFER_DEBUG */ extern bool cmd_buffer_empty(); + +/// @brief Variant of enquecommand which accepts a format string +/// @param fmt a format string residing in PROGMEM +void enquecommandf(const char *fmt, ...); extern void enquecommand(const char *cmd, bool from_progmem = false); extern void enquecommand_front(const char *cmd, bool from_progmem = false); extern void repeatcommand_front(); diff --git a/Firmware/first_lay_cal.cpp b/Firmware/first_lay_cal.cpp index 87d94c55c..84641ac32 100644 --- a/Firmware/first_lay_cal.cpp +++ b/Firmware/first_lay_cal.cpp @@ -58,7 +58,7 @@ void lay1cal_wait_preheat() //! @param cmd_buffer character buffer needed to format gcodes //! @param filament filament to use (applies for MMU only) //! @returns true if extra purge distance is needed in case of MMU prints (after a toolchange), otherwise false -bool lay1cal_load_filament(char *cmd_buffer, uint8_t filament) +bool lay1cal_load_filament(uint8_t filament) { if (MMU2::mmu2.Enabled()) { @@ -75,13 +75,7 @@ bool lay1cal_load_filament(char *cmd_buffer, uint8_t filament) enquecommand_P(MSG_M702_NO_LIFT); } // perform a toolchange - // sprintf_P(cmd_buffer, PSTR("T%d"), filament); - // rewriting the trivial T g-code command saves 30B: - cmd_buffer[0] = 'T'; - cmd_buffer[1] = filament + '0'; - cmd_buffer[2] = 0; - - enquecommand(cmd_buffer); + enquecommandf(PSTR("T%d"), filament); return true; } return false; @@ -128,12 +122,9 @@ void lay1cal_intro_line(bool extraPurgeNeeded, float layer_height, float extrusi } else { - char cmd_buffer[30]; static const char fmt1[] PROGMEM = "G1 X%d E%-.3f F1000"; - sprintf_P(cmd_buffer, fmt1, 60, count_e(layer_height, extrusion_width * 4.f, 60)); - enquecommand(cmd_buffer); - sprintf_P(cmd_buffer, fmt1, 100, count_e(layer_height, extrusion_width * 8.f, 40)); - enquecommand(cmd_buffer); + enquecommandf(fmt1, 60, count_e(layer_height, extrusion_width * 4.f, 60)); + enquecommandf(fmt1, 100, count_e(layer_height, extrusion_width * 8.f, 40)); } } @@ -166,31 +157,23 @@ void lay1cal_before_meander() //! @brief Print meander start void lay1cal_meander_start(float layer_height, float extrusion_width) { - char cmd_buffer[30]; enquecommand_P(PSTR("G1 X50 Y155")); static const char fmt1[] PROGMEM = "G1 Z%-.3f F7200"; - sprintf_P(cmd_buffer, fmt1, layer_height); - enquecommand(cmd_buffer); + enquecommandf(fmt1, layer_height); enquecommand_P(PSTR("G1 F1080")); - sprintf_P(cmd_buffer, extrude_fmt, 75, 155, count_e(layer_height, extrusion_width * 4.f, 25)); - enquecommand(cmd_buffer); - sprintf_P(cmd_buffer, extrude_fmt, 100, 155, count_e(layer_height, extrusion_width * 2.f, 25)); - enquecommand(cmd_buffer); - sprintf_P(cmd_buffer, extrude_fmt, 200, 155, count_e(layer_height, extrusion_width, 100)); - enquecommand(cmd_buffer); - sprintf_P(cmd_buffer, extrude_fmt, 200, 135, count_e(layer_height, extrusion_width, 20)); - enquecommand(cmd_buffer); + enquecommandf(extrude_fmt, 75, 155, count_e(layer_height, extrusion_width * 4.f, 25)); + enquecommandf(extrude_fmt, 100, 155, count_e(layer_height, extrusion_width * 2.f, 25)); + enquecommandf(extrude_fmt, 200, 155, count_e(layer_height, extrusion_width, 100)); + enquecommandf(extrude_fmt, 200, 135, count_e(layer_height, extrusion_width, 20)); } //! @brief Print meander //! @param cmd_buffer character buffer needed to format gcodes void lay1cal_meander(float layer_height, float extrusion_width) { - char cmd_buffer[30]; - const float short_length = 20; float long_length = 150; const float long_extrusion = count_e(layer_height, extrusion_width, long_length); @@ -200,13 +183,11 @@ void lay1cal_meander(float layer_height, float extrusion_width) uint8_t x_pos = 50; for(uint8_t i = 0; i <= 4; ++i) { - sprintf_P(cmd_buffer, extrude_fmt, x_pos, y_pos, long_extrusion); - enquecommand(cmd_buffer); + enquecommandf(extrude_fmt, x_pos, y_pos, long_extrusion); y_pos -= short_length; - sprintf_P(cmd_buffer, extrude_fmt, x_pos, y_pos, short_extrusion); - enquecommand(cmd_buffer); + enquecommandf(extrude_fmt, x_pos, y_pos, short_extrusion); x_pos += long_length; @@ -223,7 +204,6 @@ void lay1cal_meander(float layer_height, float extrusion_width) //! @param i iteration void lay1cal_square(uint8_t step, float layer_height, float extrusion_width) { - char cmd_buffer[30]; const float long_length = 20; const float short_length = spacing(layer_height, extrusion_width); const float long_extrusion = count_e(layer_height, extrusion_width, long_length); @@ -232,14 +212,10 @@ void lay1cal_square(uint8_t step, float layer_height, float extrusion_width) for (uint8_t i = step; i < step+4; ++i) { - sprintf_P(cmd_buffer, fmt1, 70, (35 - i*short_length * 2), long_extrusion); - enquecommand(cmd_buffer); - sprintf_P(cmd_buffer, fmt1, 70, (35 - (2 * i + 1)*short_length), short_extrusion); - enquecommand(cmd_buffer); - sprintf_P(cmd_buffer, fmt1, 50, (35 - (2 * i + 1)*short_length), long_extrusion); - enquecommand(cmd_buffer); - sprintf_P(cmd_buffer, fmt1, 50, (35 - (i + 1)*short_length * 2), short_extrusion); - enquecommand(cmd_buffer); + enquecommandf(fmt1, 70, (35 - i*short_length * 2), long_extrusion); + enquecommandf(fmt1, 70, (35 - (2 * i + 1)*short_length), short_extrusion); + enquecommandf(fmt1, 50, (35 - (2 * i + 1)*short_length), long_extrusion); + enquecommandf(fmt1, 50, (35 - (i + 1)*short_length * 2), short_extrusion); } } diff --git a/Firmware/first_lay_cal.h b/Firmware/first_lay_cal.h index 4580163b7..1e2dd624a 100644 --- a/Firmware/first_lay_cal.h +++ b/Firmware/first_lay_cal.h @@ -7,7 +7,7 @@ #include void lay1cal_wait_preheat(); -[[nodiscard]] bool lay1cal_load_filament(char *cmd_buffer, uint8_t filament); +[[nodiscard]] bool lay1cal_load_filament(uint8_t filament); void lay1cal_intro_line(bool skipExtraPurge, float layer_height, float extrusion_width); void lay1cal_before_meander(); void lay1cal_meander_start(float layer_height, float extrusion_width); diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 0f1b7ac06..2b8137b27 100644 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -830,7 +830,6 @@ void lcd_commands() if (lcd_commands_type == LcdCommands::Layer1Cal) { - char cmd1[30]; const uint16_t nozzle_dia = eeprom_read_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM); const float extrusion_width = (nozzle_dia + 20)/1000.0f; const float layer_height = 0.2f; @@ -848,7 +847,7 @@ void lcd_commands() lay1cal_wait_preheat(); break; case 11: - extraPurgeNeeded = lay1cal_load_filament(cmd1, lay1cal_filament); + extraPurgeNeeded = lay1cal_load_filament(lay1cal_filament); break; case 10: lcd_clear(); @@ -892,8 +891,6 @@ void lcd_commands() } if (lcd_commands_type == LcdCommands::PidExtruder) { - char cmd1[30]; - if (lcd_commands_step == 0) { custom_message_type = CustomMsg::PidCal; custom_message_state = 1; @@ -902,9 +899,8 @@ void lcd_commands() } if (lcd_commands_step == 3 && !blocks_queued()) { //PID calibration preparePidTuning(); // ensure we don't move to the next step early - sprintf_P(cmd1, PSTR("M303 E0 S%3u"), pid_temp); // setting the correct target temperature (for visualization) is done in PID_autotune - enquecommand(cmd1); + enquecommandf(PSTR("M303 E0 S%3u"), pid_temp); lcd_setstatuspgm(_i("PID cal."));////MSG_PID_RUNNING c=20 lcd_commands_step = 2; } @@ -913,8 +909,7 @@ void lcd_commands() lcd_setstatuspgm(_i("PID cal. finished"));////MSG_PID_FINISHED c=20 setTargetHotend(0); if (_Kp != 0 || _Ki != 0 || _Kd != 0) { - sprintf_P(cmd1, PSTR("M301 P%.2f I%.2f D%.2f"), _Kp, _Ki, _Kd); - enquecommand(cmd1); + enquecommandf(PSTR("M301 P%.2f I%.2f D%.2f"), _Kp, _Ki, _Kd); enquecommand_P(MSG_M500); } else {