diff --git a/Firmware/Configuration_adv.h b/Firmware/Configuration_adv.h
index 7a9a4929a..ee12716e6 100644
--- a/Firmware/Configuration_adv.h
+++ b/Firmware/Configuration_adv.h
@@ -338,6 +338,11 @@ const unsigned int dropsegments=5; //everything with less than this number of st
// Control heater 0 and heater 1 in parallel.
//#define HEATERS_PARALLEL
+//LCD status clock interval timer to switch between
+// remaining print time
+// and time to change/pause/interaction
+#define CLOCK_INTERVAL_TIME 5
+
//===========================================================================
//=============================Buffers ============================
//===========================================================================
diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h
index 1ed5e0bd3..a1b6fe4eb 100755
--- a/Firmware/Marlin.h
+++ b/Firmware/Marlin.h
@@ -350,10 +350,6 @@ extern unsigned long t_fan_rising_edge;
extern bool mesh_bed_leveling_flag;
extern bool mesh_bed_run_from_menu;
-extern bool sortAlpha;
-
-extern char dir_names[][9];
-
extern int8_t lcd_change_fil_state;
// save/restore printing
extern bool saved_printing;
@@ -370,6 +366,8 @@ extern uint8_t print_percent_done_normal;
extern uint16_t print_time_remaining_normal;
extern uint8_t print_percent_done_silent;
extern uint16_t print_time_remaining_silent;
+extern uint16_t print_time_to_change_normal;
+extern uint16_t print_time_to_change_silent;
#define PRINT_TIME_REMAINING_INIT 0xffff
@@ -441,7 +439,6 @@ extern void cancel_saved_printing();
//estimated time to end of the print
-extern uint16_t print_time_remaining();
extern uint8_t calc_percent_done();
diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp
index c8297b374..e43501994 100755
--- a/Firmware/Marlin_main.cpp
+++ b/Firmware/Marlin_main.cpp
@@ -228,10 +228,6 @@ bool fan_state[2];
int fan_edge_counter[2];
int fan_speed[2];
-char dir_names[MAX_DIR_DEPTH][9];
-
-bool sortAlpha = false;
-
float extruder_multiplier[EXTRUDERS] = {1.0
#if EXTRUDERS > 1
@@ -320,6 +316,8 @@ uint8_t print_percent_done_normal = PRINT_PERCENT_DONE_INIT;
uint16_t print_time_remaining_normal = PRINT_TIME_REMAINING_INIT; //estimated remaining print time in minutes
uint8_t print_percent_done_silent = PRINT_PERCENT_DONE_INIT;
uint16_t print_time_remaining_silent = PRINT_TIME_REMAINING_INIT; //estimated remaining print time in minutes
+uint16_t print_time_to_change_normal = PRINT_TIME_REMAINING_INIT; //estimated remaining time to next change in minutes
+uint16_t print_time_to_change_silent = PRINT_TIME_REMAINING_INIT; //estimated remaining time to next change in minutes
uint32_t IP_address = 0;
@@ -711,124 +709,98 @@ void softReset()
#endif
+static void factory_reset_stats(){
+ eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, 0);
+ eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, 0);
+
+ eeprom_update_byte((uint8_t *)EEPROM_CRASH_COUNT_X, 0);
+ eeprom_update_byte((uint8_t *)EEPROM_CRASH_COUNT_Y, 0);
+ eeprom_update_byte((uint8_t *)EEPROM_FERROR_COUNT, 0);
+ eeprom_update_byte((uint8_t *)EEPROM_POWER_COUNT, 0);
+
+ eeprom_update_word((uint16_t *)EEPROM_CRASH_COUNT_X_TOT, 0);
+ eeprom_update_word((uint16_t *)EEPROM_CRASH_COUNT_Y_TOT, 0);
+ eeprom_update_word((uint16_t *)EEPROM_FERROR_COUNT_TOT, 0);
+ eeprom_update_word((uint16_t *)EEPROM_POWER_COUNT_TOT, 0);
+
+ eeprom_update_word((uint16_t *)EEPROM_MMU_FAIL_TOT, 0);
+ eeprom_update_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT, 0);
+ eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0);
+ eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0);
+}
+
// Factory reset function
// This function is used to erase parts or whole EEPROM memory which is used for storing calibration and and so on.
// Level input parameter sets depth of reset
-int er_progress = 0;
static void factory_reset(char level)
-{
+{
lcd_clear();
- switch (level) {
-
- // Level 0: Language reset
- case 0:
- Sound_MakeCustom(100,0,false);
- lang_reset();
- break;
-
- //Level 1: Reset statistics
- case 1:
- Sound_MakeCustom(100,0,false);
- eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, 0);
- eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, 0);
+ Sound_MakeCustom(100,0,false);
+ switch (level) {
- eeprom_update_byte((uint8_t *)EEPROM_CRASH_COUNT_X, 0);
- eeprom_update_byte((uint8_t *)EEPROM_CRASH_COUNT_Y, 0);
- eeprom_update_byte((uint8_t *)EEPROM_FERROR_COUNT, 0);
- eeprom_update_byte((uint8_t *)EEPROM_POWER_COUNT, 0);
+ case 0: // Level 0: Language reset
+ lang_reset();
+ break;
- eeprom_update_word((uint16_t *)EEPROM_CRASH_COUNT_X_TOT, 0);
- eeprom_update_word((uint16_t *)EEPROM_CRASH_COUNT_Y_TOT, 0);
- eeprom_update_word((uint16_t *)EEPROM_FERROR_COUNT_TOT, 0);
- eeprom_update_word((uint16_t *)EEPROM_POWER_COUNT_TOT, 0);
+ case 1: //Level 1: Reset statistics
+ factory_reset_stats();
+ lcd_menu_statistics();
+ break;
- eeprom_update_word((uint16_t *)EEPROM_MMU_FAIL_TOT, 0);
- eeprom_update_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT, 0);
- eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0);
- eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0);
+ case 2: // Level 2: Prepare for shipping
+ factory_reset_stats();
+ // [[fallthrough]] // there is no break intentionally
-
- lcd_menu_statistics();
-
- break;
-
- // Level 2: Prepare for shipping
- case 2:
- //lcd_puts_P(PSTR("Factory RESET"));
- //lcd_puts_at_P(1,2,PSTR("Shipping prep"));
-
- // Force language selection at the next boot up.
- lang_reset();
- // Force the "Follow calibration flow" message at the next boot up.
- calibration_status_store(CALIBRATION_STATUS_Z_CALIBRATION);
- eeprom_write_byte((uint8_t*)EEPROM_WIZARD_ACTIVE, 1); //run wizard
- farm_mode = false;
- eeprom_update_byte((uint8_t*)EEPROM_FARM_MODE, farm_mode);
-
- eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, 0);
- eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, 0);
-
- eeprom_update_byte((uint8_t *)EEPROM_CRASH_COUNT_X, 0);
- eeprom_update_byte((uint8_t *)EEPROM_CRASH_COUNT_Y, 0);
- eeprom_update_byte((uint8_t *)EEPROM_FERROR_COUNT, 0);
- eeprom_update_byte((uint8_t *)EEPROM_POWER_COUNT, 0);
-
- eeprom_update_word((uint16_t *)EEPROM_CRASH_COUNT_X_TOT, 0);
- eeprom_update_word((uint16_t *)EEPROM_CRASH_COUNT_Y_TOT, 0);
- eeprom_update_word((uint16_t *)EEPROM_FERROR_COUNT_TOT, 0);
- eeprom_update_word((uint16_t *)EEPROM_POWER_COUNT_TOT, 0);
-
- eeprom_update_word((uint16_t *)EEPROM_MMU_FAIL_TOT, 0);
- eeprom_update_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT, 0);
- eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0);
- eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0);
+ case 4: // Level 4: Preparation after being serviced
+ // Force language selection at the next boot up.
+ lang_reset();
+ // Force the "Follow calibration flow" message at the next boot up.
+ calibration_status_store(CALIBRATION_STATUS_Z_CALIBRATION);
+ eeprom_write_byte((uint8_t*)EEPROM_WIZARD_ACTIVE, 1); //run wizard
+ farm_mode = false;
+ eeprom_update_byte((uint8_t*)EEPROM_FARM_MODE, farm_mode);
#ifdef FILAMENT_SENSOR
- fsensor_enable();
- fsensor_autoload_set(true);
+ fsensor_enable();
+ fsensor_autoload_set(true);
#endif //FILAMENT_SENSOR
- Sound_MakeCustom(100,0,false);
- //_delay_ms(2000);
- break;
+ break;
- // Level 3: erase everything, whole EEPROM will be set to 0xFF
+ case 3:{ // Level 3: erase everything, whole EEPROM will be set to 0xFF
+ lcd_puts_P(PSTR("Factory RESET"));
+ lcd_puts_at_P(1, 2, PSTR("ERASING all data"));
+ uint16_t er_progress = 0;
+ lcd_set_cursor(3, 3);
+ lcd_space(6);
+ lcd_set_cursor(3, 3);
+ lcd_print(er_progress);
- case 3:
- lcd_puts_P(PSTR("Factory RESET"));
- lcd_puts_at_P(1, 2, PSTR("ERASING all data"));
-
- Sound_MakeCustom(100,0,false);
- er_progress = 0;
- lcd_puts_at_P(3, 3, PSTR(" "));
- lcd_set_cursor(3, 3);
- lcd_print(er_progress);
-
- // Erase EEPROM
- for (int i = 0; i < 4096; i++) {
- eeprom_update_byte((uint8_t*)i, 0xFF);
-
- if (i % 41 == 0) {
- er_progress++;
- lcd_puts_at_P(3, 3, PSTR(" "));
- lcd_set_cursor(3, 3);
- lcd_print(er_progress);
- lcd_puts_P(PSTR("%"));
- }
+ // Erase EEPROM
+ for (uint16_t i = 0; i < 4096; i++) {
+ eeprom_update_byte((uint8_t*)i, 0xFF);
+ if (i % 41 == 0) {
+ er_progress++;
+ lcd_set_cursor(3, 3);
+ lcd_space(6);
+ lcd_set_cursor(3, 3);
+ lcd_print(er_progress);
+ lcd_puts_P(PSTR("%"));
}
- softReset();
+
+ }
+ softReset();
+ }break;
- break;
- case 4:
- bowden_menu();
- break;
-
- default:
- break;
- }
-
-
+#ifdef SNMM
+ case 5:
+ bowden_menu();
+ break;
+#endif
+ default:
+ break;
+ }
}
extern "C" {
@@ -859,30 +831,27 @@ void factory_reset()
{
lcd_clear();
-
lcd_puts_P(PSTR("Factory RESET"));
-
SET_OUTPUT(BEEPER);
- if(eSoundMode!=e_SOUND_MODE_SILENT)
- WRITE(BEEPER, HIGH);
+ if(eSoundMode!=e_SOUND_MODE_SILENT)
+ WRITE(BEEPER, HIGH);
while (!READ(BTN_ENC));
WRITE(BEEPER, LOW);
-
-
_delay_ms(2000);
char level = reset_menu();
factory_reset(level);
switch (level) {
- case 0: _delay_ms(0); break;
- case 1: _delay_ms(0); break;
- case 2: _delay_ms(0); break;
- case 3: _delay_ms(0); break;
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4: _delay_ms(0); break;
}
}
@@ -3801,31 +3770,90 @@ void process_commands()
float tmp_motor_loud[3] = DEFAULT_PWM_MOTOR_CURRENT_LOUD;
int8_t SilentMode;
#endif
- /*!
+ /*!
+
+ ---------------------------------------------------------------------------------
+ ### M117 - Display Message M117: Display Message
+ This causes the given message to be shown in the status line on an attached LCD.
+ It is processed early as to allow printing messages that contain G, M, N or T.
+
+ ---------------------------------------------------------------------------------
+ ### Special internal commands
+ These are used by internal functions to process certain actions in the right order. Some of these are also usable by the user.
+ They are processed early as the commands are complex (strings).
+ These are only available on the MK3(S) as these require TMC2130 drivers:
+ - CRASH DETECTED
+ - CRASH RECOVER
+ - CRASH_CANCEL
+ - TMC_SET_WAVE
+ - TMC_SET_STEP
+ - TMC_SET_CHOP
+ */
+ if (code_seen_P(PSTR("M117"))) //moved to highest priority place to be able to to print strings which includes "G", "PRUSA" and "^"
+ {
+ starpos = (strchr(strchr_pointer + 5, '*'));
+ if (starpos != NULL)
+ *(starpos) = '\0';
+ lcd_setstatus(strchr_pointer + 5);
+ custom_message_type = CustomMsg::MsgUpdate;
+ }
+
+ /*!
+ ### M0, M1 - Stop the printer M0: Stop or Unconditional stop
+ #### Usage
+
+ M0 [P] [string]
+ M1 [P] [S] [string]
+
+ #### Parameters
- ---------------------------------------------------------------------------------
- ### M117 - Display Message M117: Display Message
- This causes the given message to be shown in the status line on an attached LCD.
- It is processed early as to allow printing messages that contain G, M, N or T.
-
- ---------------------------------------------------------------------------------
- ### Special internal commands
- These are used by internal functions to process certain actions in the right order. Some of these are also usable by the user.
- They are processed early as the commands are complex (strings).
- These are only available on the MK3(S) as these require TMC2130 drivers:
- - CRASH DETECTED
- - CRASH RECOVER
- - CRASH_CANCEL
- - TMC_SET_WAVE
- - TMC_SET_STEP
- - TMC_SET_CHOP
- */
- if (code_seen_P(PSTR("M117"))) { //moved to highest priority place to be able to to print strings which includes "G", "PRUSA" and "^"
- starpos = (strchr(strchr_pointer + 5, '*'));
- if (starpos != NULL)
- *(starpos) = '\0';
- lcd_setstatus(strchr_pointer + 5);
- }
+ - `P` - Expire time, in milliseconds
+ - `S` - Expire time, in seconds
+ - `string` - Must for M1 and optional for M0 message to display on the LCD
+ */
+
+ else if (code_seen_P(PSTR("M0")) || code_seen_P(PSTR("M1 "))) {// M0 and M1 - (Un)conditional stop - Wait for user button press on LCD
+ char *src = strchr_pointer + 2;
+ codenum = 0;
+ bool hasP = false, hasS = false;
+ if (code_seen('P')) {
+ codenum = code_value(); // milliseconds to wait
+ hasP = codenum > 0;
+ }
+ if (code_seen('S')) {
+ codenum = code_value() * 1000; // seconds to wait
+ hasS = codenum > 0;
+ }
+ starpos = strchr(src, '*');
+ if (starpos != NULL) *(starpos) = '\0';
+ while (*src == ' ') ++src;
+ custom_message_type = CustomMsg::M0Wait;
+ if (!hasP && !hasS && *src != '\0') {
+ lcd_setstatus(src);
+ } else {
+ LCD_MESSAGERPGM(_i("Wait for user..."));////MSG_USERWAIT
+ }
+ lcd_ignore_click(); //call lcd_ignore_click aslo for else ???
+ st_synchronize();
+ previous_millis_cmd = _millis();
+ if (codenum > 0) {
+ codenum += _millis(); // keep track of when we started waiting
+ KEEPALIVE_STATE(PAUSED_FOR_USER);
+ while(_millis() < codenum && !lcd_clicked()) {
+ manage_heater();
+ manage_inactivity(true);
+ lcd_update(0);
+ }
+ KEEPALIVE_STATE(IN_HANDLER);
+ lcd_ignore_click(false);
+ } else {
+ marlin_wait_for_click();
+ }
+ if (IS_SD_PRINTING)
+ custom_message_type = CustomMsg::Status;
+ else
+ LCD_MESSAGERPGM(_T(WELCOME_MSG));
+ }
#ifdef TMC2130
else if (strncmp_P(CMDBUFFER_CURRENT_STRING, PSTR("CRASH_"), 6) == 0)
@@ -4006,9 +4034,9 @@ void process_commands()
}else if (code_seen_P("fv")) { // PRUSA fv
// get file version
#ifdef SDSUPPORT
- card.openFile(strchr_pointer + 3,true);
+ card.openFileReadFilteredGcode(strchr_pointer + 3,true);
while (true) {
- uint16_t readByte = card.get();
+ uint16_t readByte = card.getFilteredGcodeChar();
MYSERIAL.write(readByte);
if (readByte=='\n') {
break;
@@ -4021,7 +4049,7 @@ void process_commands()
} else if (code_seen_P(PSTR("M28"))) { // PRUSA M28
trace();
prusa_sd_card_upload = true;
- card.openFile(strchr_pointer+4,false);
+ card.openFileWrite(strchr_pointer+4);
} else if (code_seen_P(PSTR("SN"))) { // PRUSA SN
char SN[20];
@@ -5684,60 +5712,10 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
switch(mcode_in_progress)
{
- /*!
- ### M0, M1 - Stop the printer M0: Stop or Unconditional stop
- */
- case 0: // M0 - Unconditional stop - Wait for user button press on LCD
- case 1: // M1 - Conditional stop - Wait for user button press on LCD
- {
- char *src = strchr_pointer + 2;
-
- codenum = 0;
-
- bool hasP = false, hasS = false;
- if (code_seen('P')) {
- codenum = code_value(); // milliseconds to wait
- hasP = codenum > 0;
- }
- if (code_seen('S')) {
- codenum = code_value() * 1000; // seconds to wait
- hasS = codenum > 0;
- }
- starpos = strchr(src, '*');
- if (starpos != NULL) *(starpos) = '\0';
- while (*src == ' ') ++src;
- if (!hasP && !hasS && *src != '\0') {
- lcd_setstatus(src);
- } else {
- LCD_MESSAGERPGM(_i("Wait for user..."));////MSG_USERWAIT
- }
-
- lcd_ignore_click(); //call lcd_ignore_click aslo for else ???
- st_synchronize();
- previous_millis_cmd = _millis();
- if (codenum > 0){
- codenum += _millis(); // keep track of when we started waiting
- KEEPALIVE_STATE(PAUSED_FOR_USER);
- while(_millis() < codenum && !lcd_clicked()){
- manage_heater();
- manage_inactivity(true);
- lcd_update(0);
- }
- KEEPALIVE_STATE(IN_HANDLER);
- lcd_ignore_click(false);
- }else{
- marlin_wait_for_click();
- }
- if (IS_SD_PRINTING)
- LCD_MESSAGERPGM(_T(MSG_RESUMING_PRINT));
- else
- LCD_MESSAGERPGM(_T(WELCOME_MSG));
- }
- break;
-
/*!
### M17 - Enable all axes M17: Enable/Power all stepper motors
*/
+
case 17:
LCD_MESSAGERPGM(_i("No move."));////MSG_NO_MOVE
enable_x();
@@ -5790,7 +5768,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
starpos = (strchr(strchr_pointer + 4,'*'));
if(starpos!=NULL)
*(starpos)='\0';
- card.openFile(strchr_pointer + 4,true);
+ card.openFileReadFilteredGcode(strchr_pointer + 4);
break;
/*!
@@ -5860,7 +5838,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
strchr_pointer = strchr(npos,' ') + 1;
*(starpos) = '\0';
}
- card.openFile(strchr_pointer+4,false);
+ card.openFileWrite(strchr_pointer+4);
break;
/*! ### M29 - Stop SD write M29: Stop writing to SD card
@@ -5921,7 +5899,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
if( card.cardOK )
{
- card.openFile(namestartpos,true,!call_procedure);
+ card.openFileReadFilteredGcode(namestartpos,!call_procedure);
if(code_seen('S'))
if(strchr_pointerM73: Set/Get build percentage
- #### Usage
+ /*!
+ ### M73 - Set/get print progress M73: Set/Get build percentage
+ #### Usage
- M73 [ P | R | Q | S ]
-
- #### Parameters
- - `P` - Percent in normal mode
- - `R` - Time remaining in normal mode
- - `Q` - Percent in silent mode
- - `S` - Time in silent mode
- */
- case 73: //M73 show percent done and time remaining
- if(code_seen('P')) print_percent_done_normal = code_value();
- if(code_seen('R')) print_time_remaining_normal = code_value();
- if(code_seen('Q')) print_percent_done_silent = code_value();
- if(code_seen('S')) print_time_remaining_silent = code_value();
+ M73 [ P | R | Q | S | C | D ]
- {
- const char* _msg_mode_done_remain = _N("%S MODE: Percent done: %d; print time remaining in mins: %d\n");
- printf_P(_msg_mode_done_remain, _N("NORMAL"), int(print_percent_done_normal), print_time_remaining_normal);
- printf_P(_msg_mode_done_remain, _N("SILENT"), int(print_percent_done_silent), print_time_remaining_silent);
- }
- break;
+ #### Parameters
+ - `P` - Percent in normal mode
+ - `R` - Time remaining in normal mode
+ - `Q` - Percent in silent mode
+ - `S` - Time in silent mode
+ - `C` - Time to change/pause/user interaction in normal mode
+ - `D` - Time to change/pause/user interaction in silent mode
+ */
+ //!@todo update RepRap Gcode wiki
+ case 73: //M73 show percent done, time remaining and time to change/pause
+ {
+ if(code_seen('P')) print_percent_done_normal = code_value();
+ if(code_seen('R')) print_time_remaining_normal = code_value();
+ if(code_seen('Q')) print_percent_done_silent = code_value();
+ if(code_seen('S')) print_time_remaining_silent = code_value();
+ if(code_seen('C')) print_time_to_change_normal = code_value();
+ if(code_seen('D')) print_time_to_change_silent = code_value();
+ {
+ const char* _msg_mode_done_remain = _N("%S MODE: Percent done: %d; print time remaining in mins: %d; Change in mins: %d\n");
+ printf_P(_msg_mode_done_remain, _N("NORMAL"), int(print_percent_done_normal), print_time_remaining_normal, print_time_to_change_normal);
+ printf_P(_msg_mode_done_remain, _N("SILENT"), int(print_percent_done_silent), print_time_remaining_silent, print_time_to_change_silent);
+ }
+ break;
+ }
/*!
### M104 - Set hotend temperature M104: Set Extruder Temperature
#### Usage
@@ -8135,35 +8119,34 @@ Sigma_Exit:
/*!
### M25 - Pause SD print M25: Pause SD print
*/
- case 25:
- case 601:
- {
- if (!isPrintPaused)
- {
+ case 25:
+ case 601:
+ {
+ if (!isPrintPaused) {
st_synchronize();
ClearToSend(); //send OK even before the command finishes executing because we want to make sure it is not skipped because of cmdqueue_pop_front();
cmdqueue_pop_front(); //trick because we want skip this command (M601) after restore
lcd_pause_print();
}
- }
- break;
+ }
+ break;
/*!
- ### M602 - Resume print M602: Resume print
+ ### M602 - Resume print M602: Resume print
*/
- case 602: {
- if (isPrintPaused)
- lcd_resume_print();
- }
- break;
+ case 602: {
+ if (isPrintPaused)
+ lcd_resume_print();
+ }
+ break;
/*!
### M603 - Stop print M603: Stop print
*/
- case 603: {
- lcd_print_stop();
- }
- break;
+ case 603: {
+ lcd_print_stop();
+ }
+ break;
#ifdef PINDA_THERMISTOR
/*!
@@ -9707,7 +9690,7 @@ void manage_inactivity_IR_ANALOG_Check(uint16_t &nFSCheckCount, ClFsensorPCB isV
void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument set in Marlin.h
{
#ifdef FILAMENT_SENSOR
-bool bInhibitFlag;
+bool bInhibitFlag = false;
#ifdef IR_SENSOR_ANALOG
static uint16_t nFSCheckCount=0;
#endif // IR_SENSOR_ANALOG
@@ -9715,16 +9698,11 @@ static uint16_t nFSCheckCount=0;
if (mmu_enabled == false)
{
//-// if (mcode_in_progress != 600) //M600 not in progress
-#ifdef PAT9125
- bInhibitFlag=(menu_menu==lcd_menu_extruder_info); // Support::ExtruderInfo menu active
-#endif // PAT9125
-#ifdef IR_SENSOR
- bInhibitFlag=(menu_menu==lcd_menu_show_sensors_state); // Support::SensorInfo menu active
+ if (!PRINTER_ACTIVE) bInhibitFlag=(menu_menu==lcd_menu_show_sensors_state); //Block Filament sensor actions if PRINTER is not active and Support::SensorInfo menu active
#ifdef IR_SENSOR_ANALOG
- bInhibitFlag=bInhibitFlag||bMenuFSDetect; // Settings::HWsetup::FSdetect menu active
+ bInhibitFlag=bInhibitFlag||bMenuFSDetect; // Block Filament sensor actions if Settings::HWsetup::FSdetect menu active
#endif // IR_SENSOR_ANALOG
-#endif // IR_SENSOR
- if ((mcode_in_progress != 600) && (eFilamentAction != FilamentAction::AutoLoad) && (!bInhibitFlag) && (menu_menu != lcd_move_e)) //M600 not in progress, preHeat @ autoLoad menu not active, Support::ExtruderInfo/SensorInfo menu not active
+ if ((mcode_in_progress != 600) && (eFilamentAction != FilamentAction::AutoLoad) && (!bInhibitFlag) && (menu_menu != lcd_move_e)) //M600 not in progress, preHeat @ autoLoad menu not active
{
if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LcdCommands::Layer1Cal) && ! eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE))
{
@@ -11281,8 +11259,8 @@ void restore_print_from_eeprom(bool mbl_was_active) {
}
dir_name[8] = '\0';
MYSERIAL.println(dir_name);
- strcpy(dir_names[i], dir_name);
- card.chdir(dir_name);
+ // strcpy(dir_names[i], dir_name);
+ card.chdir(dir_name, false);
}
for (int i = 0; i < 8; i++) {
@@ -11657,46 +11635,40 @@ void print_mesh_bed_leveling_table()
SERIAL_ECHOLN();
}
-uint16_t print_time_remaining() {
- uint16_t print_t = PRINT_TIME_REMAINING_INIT;
-#ifdef TMC2130
- if (SilentModeMenu == SILENT_MODE_OFF) print_t = print_time_remaining_normal;
- else print_t = print_time_remaining_silent;
-#else
- print_t = print_time_remaining_normal;
-#endif //TMC2130
- if ((print_t != PRINT_TIME_REMAINING_INIT) && (feedmultiply != 0)) print_t = 100ul * print_t / feedmultiply;
- return print_t;
-}
-
uint8_t calc_percent_done()
{
- //in case that we have information from M73 gcode return percentage counted by slicer, else return percentage counted as byte_printed/filesize
- uint8_t percent_done = 0;
+ //in case that we have information from M73 gcode return percentage counted by slicer, else return percentage counted as byte_printed/filesize
+ uint8_t percent_done = 0;
#ifdef TMC2130
- if (SilentModeMenu == SILENT_MODE_OFF && print_percent_done_normal <= 100) {
- percent_done = print_percent_done_normal;
- }
- else if (print_percent_done_silent <= 100) {
- percent_done = print_percent_done_silent;
- }
+ if (SilentModeMenu == SILENT_MODE_OFF && print_percent_done_normal <= 100)
+ {
+ percent_done = print_percent_done_normal;
+ }
+ else if (print_percent_done_silent <= 100)
+ {
+ percent_done = print_percent_done_silent;
+ }
#else
- if (print_percent_done_normal <= 100) {
- percent_done = print_percent_done_normal;
- }
+ if (print_percent_done_normal <= 100)
+ {
+ percent_done = print_percent_done_normal;
+ }
#endif //TMC2130
- else {
- percent_done = card.percentDone();
- }
- return percent_done;
+ else
+ {
+ percent_done = card.percentDone();
+ }
+ return percent_done;
}
static void print_time_remaining_init()
{
- print_time_remaining_normal = PRINT_TIME_REMAINING_INIT;
- print_time_remaining_silent = PRINT_TIME_REMAINING_INIT;
- print_percent_done_normal = PRINT_PERCENT_DONE_INIT;
- print_percent_done_silent = PRINT_PERCENT_DONE_INIT;
+ print_time_remaining_normal = PRINT_TIME_REMAINING_INIT;
+ print_percent_done_normal = PRINT_PERCENT_DONE_INIT;
+ print_time_remaining_silent = PRINT_TIME_REMAINING_INIT;
+ print_percent_done_silent = PRINT_PERCENT_DONE_INIT;
+ print_time_to_change_normal = PRINT_TIME_REMAINING_INIT;
+ print_time_to_change_silent = PRINT_TIME_REMAINING_INIT;
}
void load_filament_final_feed()
diff --git a/Firmware/SdBaseFile.cpp b/Firmware/SdBaseFile.cpp
index b9e881ef2..e3b1c18c8 100644
--- a/Firmware/SdBaseFile.cpp
+++ b/Firmware/SdBaseFile.cpp
@@ -530,9 +530,9 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
* \return The value one, true, is returned for success and
* the value zero, false, is returned for failure.
*/
- bool SdBaseFile::open(const char* path, uint8_t oflag) {
- return open(cwd_, path, oflag);
- }
+bool SdBaseFile::open(const char* path, uint8_t oflag) {
+ return open(cwd_, path, oflag);
+}
//------------------------------------------------------------------------------
/** Open a file or directory by name.
*
diff --git a/Firmware/SdBaseFile.h b/Firmware/SdBaseFile.h
index 923a391dd..a6bd311fe 100644
--- a/Firmware/SdBaseFile.h
+++ b/Firmware/SdBaseFile.h
@@ -281,8 +281,10 @@ class SdBaseFile {
static void printFatDate(uint16_t fatDate);
static void printFatTime( uint16_t fatTime);
bool printName();
+protected:
int16_t read();
int16_t read(void* buf, uint16_t nbyte);
+public:
int8_t readDir(dir_t* dir, char* longFilename);
static bool remove(SdBaseFile* dirFile, const char* path);
bool remove();
@@ -321,7 +323,7 @@ class SdBaseFile {
SdVolume* volume() const {return vol_;}
int16_t write(const void* buf, uint16_t nbyte);
//------------------------------------------------------------------------------
- private:
+ protected:
// allow SdFat to set cwd_
friend class SdFat;
// global pointer to cwd dir
diff --git a/Firmware/SdFile.cpp b/Firmware/SdFile.cpp
index 2fb4d5943..1bad4319f 100644
--- a/Firmware/SdFile.cpp
+++ b/Firmware/SdFile.cpp
@@ -30,6 +30,191 @@
*/
SdFile::SdFile(const char* path, uint8_t oflag) : SdBaseFile(path, oflag) {
}
+
+bool SdFile::openFilteredGcode(SdBaseFile* dirFile, const char* path){
+ if( open(dirFile, path, O_READ) ){
+ // compute the block to start with
+ if( ! gfComputeNextFileBlock() )
+ return false;
+ gfReset();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool SdFile::seekSetFilteredGcode(uint32_t pos){
+ if(! seekSet(pos) )return false;
+ if(! gfComputeNextFileBlock() )return false;
+ gfReset();
+ return true;
+}
+
+const uint8_t *SdFile::gfBlockBuffBegin() const {
+ return vol_->cache()->data; // this is constant for the whole time, so it should be fast and sleek
+}
+
+void SdFile::gfReset(){
+ // reset cache read ptr to its begin
+ gfReadPtr = gfBlockBuffBegin() + gfOffset;
+}
+
+// think twice before allowing this to inline - manipulating 4B longs is costly
+// moreover - this function has its parameters in registers only, so no heavy stack usage besides the call/ret
+void __attribute__((noinline)) SdFile::gfUpdateCurrentPosition(uint16_t inc){
+ curPosition_ += inc;
+}
+
+#define find_endl(resultP, startP) \
+__asm__ __volatile__ ( \
+"cycle: \n" \
+"ld r22, Z+ \n" \
+"cpi r22, 0x0A \n" \
+"brne cycle \n" \
+: "=z" (resultP) /* result of the ASM code - in our case the Z register (R30:R31) */ \
+: "z" (startP) /* input of the ASM code - in our case the Z register as well (R30:R31) */ \
+: "r22" /* modifying register R22 - so that the compiler knows */ \
+)
+
+// avoid calling the default heavy-weight read() for just one byte
+int16_t SdFile::readFilteredGcode(){
+ if( ! gfEnsureBlock() ){
+ goto eof_or_fail; // this is unfortunate :( ... other calls are using the cache and we can loose the data block of our gcode file
+ }
+ // assume, we have the 512B block cache filled and terminated with a '\n'
+ {
+ const uint8_t *start = gfReadPtr;
+
+ // It may seem unreasonable to copy the variable into a local one and copy it back at the end of this method,
+ // but there is an important point of view: the compiler is unsure whether it can optimize the reads/writes
+ // to gfReadPtr within this method, because it is a class member variable.
+ // The compiler cannot see, if omitting read/write won't have any incorrect side-effects to the rest of the whole FW.
+ // So this trick explicitly states, that rdPtr is a local variable limited to the scope of this method,
+ // therefore the compiler can omit read/write to it (keep it in registers!) as it sees fit.
+ // And it does! Codesize dropped by 68B!
+ const uint8_t *rdPtr = gfReadPtr;
+
+ // the same applies to gfXBegin, codesize dropped another 100B!
+ const uint8_t *blockBuffBegin = gfBlockBuffBegin();
+
+ uint8_t consecutiveCommentLines = 0;
+ while( *rdPtr == ';' ){
+ for(;;){
+
+ //while( *(++gfReadPtr) != '\n' ); // skip until a newline is found - suboptimal code!
+ // Wondering, why this "nice while cycle" is done in such a weird way using a separate find_endl() function?
+ // Have a look at the ASM code GCC produced!
+
+ // At first - a separate find_endl() makes the compiler understand,
+ // that I don't need to store gfReadPtr every time, I'm only interested in the final address where the '\n' was found
+ // - the cycle can run on CPU registers only without touching memory besides reading the character being compared.
+ // Not only makes the code run considerably faster, but is also 40B shorter!
+ // This was the generated code:
+ //FORCE_INLINE const uint8_t * find_endl(const uint8_t *p){
+ // while( *(++p) != '\n' ); // skip until a newline is found
+ // return p; }
+ // 11c5e: movw r30, r18
+ // 11c60: subi r18, 0xFF ; 255
+ // 11c62: sbci r19, 0xFF ; 255
+ // 11c64: ld r22, Z
+ // 11c66: cpi r22, 0x0A ; 10
+ // 11c68: brne .-12 ; 0x11c5e
+
+ // Still, even that was suboptimal as the compiler seems not to understand the usage of ld r22, Z+ (the plus is important)
+ // aka automatic increment of the Z register (R30:R31 pair)
+ // There is no other way than pure ASM!
+ find_endl(rdPtr, rdPtr);
+
+ // found a newline, prepare the next block if block cache end reached
+ if( rdPtr - blockBuffBegin > 512 ){
+ // at the end of block cache, fill new data in
+ gfUpdateCurrentPosition( rdPtr - start - 1 );
+ if( ! gfComputeNextFileBlock() )goto eof_or_fail;
+ if( ! gfEnsureBlock() )goto eof_or_fail; // fetch it into RAM
+ rdPtr = start = blockBuffBegin;
+ } else {
+ if(consecutiveCommentLines >= 250){
+ --rdPtr; // unget the already consumed newline
+ goto emit_char;
+ }
+ // peek the next byte - we are inside the block at least at 511th index - still safe
+ if( *rdPtr == ';' ){
+ // consecutive comment
+ ++consecutiveCommentLines;
+ } else {
+ --rdPtr; // unget the already consumed newline
+ goto emit_char;
+ }
+ break; // found the real end of the line even across many blocks
+ }
+ }
+ }
+emit_char:
+ {
+ gfUpdateCurrentPosition( rdPtr - start + 1 );
+ int16_t rv = *rdPtr++;
+
+ if( curPosition_ >= fileSize_ ){
+ // past the end of file
+ goto eof_or_fail;
+ } else if( rdPtr - blockBuffBegin >= 512 ){
+ // past the end of current bufferred block - prepare the next one...
+ if( ! gfComputeNextFileBlock() )goto eof_or_fail;
+ // don't need to force fetch the block here, it will get loaded on the next call
+ rdPtr = blockBuffBegin;
+ }
+
+ // save the current read ptr for the next run
+ gfReadPtr = rdPtr;
+ return rv;
+ }
+
+}
+
+eof_or_fail:
+ // make the rdptr point to a safe location - end of file
+ gfReadPtr = gfBlockBuffBegin() + 512;
+ return -1;
+}
+
+bool SdFile::gfEnsureBlock(){
+ if ( vol_->cacheRawBlock(gfBlock, SdVolume::CACHE_FOR_READ)){
+ // terminate with a '\n'
+ const uint16_t terminateOfs = fileSize_ - gfOffset;
+ vol_->cache()->data[ terminateOfs < 512 ? terminateOfs : 512 ] = '\n';
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool SdFile::gfComputeNextFileBlock() {
+ // error if not open or write only
+ if (!isOpen() || !(flags_ & O_READ)) return false;
+
+ gfOffset = curPosition_ & 0X1FF; // offset in block
+ if (type_ == FAT_FILE_TYPE_ROOT_FIXED) {
+ // SHR by 9 means skip the last byte and shift just 3 bytes by 1
+ // -> should be 8 instructions... and not the horrible loop shifting 4 bytes at once
+ // still need to get some work on this
+ gfBlock = vol_->rootDirStart() + (curPosition_ >> 9);
+ } else {
+ uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
+ if (gfOffset == 0 && blockOfCluster == 0) {
+ // start of new cluster
+ if (curPosition_ == 0) {
+ // use first cluster in file
+ curCluster_ = firstCluster_;
+ } else {
+ // get next cluster from FAT
+ if (!vol_->fatGet(curCluster_, &curCluster_)) return false;
+ }
+ }
+ gfBlock = vol_->clusterStartBlock(curCluster_) + blockOfCluster;
+ }
+ return true;
+}
+
//------------------------------------------------------------------------------
/** Write data to an open file.
*
diff --git a/Firmware/SdFile.h b/Firmware/SdFile.h
index 60e2f5deb..465224623 100644
--- a/Firmware/SdFile.h
+++ b/Firmware/SdFile.h
@@ -34,7 +34,24 @@
* \brief SdBaseFile with Print.
*/
class SdFile : public SdBaseFile/*, public Print*/ {
- public:
+ // GCode filtering vars and methods - due to optimization reasons not wrapped in a separate class
+
+ // beware - this read ptr is manipulated inside just 2 methods - readFilteredGcode and gfReset
+ // If you even want to call gfReset from readFilteredGcode, you must make sure
+ // to update gfReadPtr inside readFilteredGcode from a local copy (see explanation of this trick in readFilteredGcode)
+ const uint8_t *gfReadPtr;
+
+ uint32_t gfBlock; // remember the current file block to be kept in cache - due to reuse of the memory, the block may fall out a must be read back
+ uint16_t gfOffset;
+
+ const uint8_t *gfBlockBuffBegin()const;
+
+ void gfReset();
+
+ bool gfEnsureBlock();
+ bool gfComputeNextFileBlock();
+ void gfUpdateCurrentPosition(uint16_t inc);
+public:
SdFile() {}
SdFile(const char* name, uint8_t oflag);
#if ARDUINO >= 100
@@ -43,6 +60,9 @@ class SdFile : public SdBaseFile/*, public Print*/ {
void write(uint8_t b);
#endif
+ bool openFilteredGcode(SdBaseFile* dirFile, const char* path);
+ int16_t readFilteredGcode();
+ bool seekSetFilteredGcode(uint32_t pos);
int16_t write(const void* buf, uint16_t nbyte);
void write(const char* str);
void write_P(PGM_P str);
@@ -51,4 +71,4 @@ class SdFile : public SdBaseFile/*, public Print*/ {
#endif // SdFile_h
-#endif
\ No newline at end of file
+#endif
diff --git a/Firmware/SdVolume.h b/Firmware/SdVolume.h
index 2ff2b6eb9..17699190e 100644
--- a/Firmware/SdVolume.h
+++ b/Firmware/SdVolume.h
@@ -36,7 +36,7 @@
*/
union cache_t {
/** Used to access cached file data blocks. */
- uint8_t data[512];
+ uint8_t data[512 + 1]; // abuse the last byte for saving '\n' - ugly optimization of read_filtered's inner skipping loop
/** Used to access cached FAT16 entries. */
uint16_t fat16[256];
/** Used to access cached FAT32 entries. */
@@ -119,6 +119,7 @@ class SdVolume {
bool dbgFat(uint32_t n, uint32_t* v) {return fatGet(n, v);}
//------------------------------------------------------------------------------
private:
+ friend class SdFile;
// Allow SdBaseFile access to SdVolume private data.
friend class SdBaseFile;
@@ -211,4 +212,4 @@ class SdVolume {
#endif // ALLOW_DEPRECATED_FUNCTIONS
};
#endif // SdVolume
-#endif
\ No newline at end of file
+#endif
diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp
index a96268972..6fe890095 100644
--- a/Firmware/cardreader.cpp
+++ b/Firmware/cardreader.cpp
@@ -32,6 +32,7 @@ CardReader::CardReader()
workDirDepth = 0;
file_subcall_ctr=0;
memset(workDirParents, 0, sizeof(workDirParents));
+ presort_flag = false;
autostart_stilltocheck=true; //the SD start is delayed, because otherwise the serial cannot answer fast enough to make contact with the host software.
lastnr=0;
@@ -69,12 +70,23 @@ char *createFilename(char *buffer,const dir_t &p) //buffer>12characters
+*/
void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/) {
+ static uint8_t recursionCnt = 0;
+ // RAII incrementer for the recursionCnt
+ class _incrementer
+ {
+ public:
+ _incrementer() {recursionCnt++;}
+ ~_incrementer() {recursionCnt--;}
+ } recursionCntIncrementer;
+
dir_t p;
uint8_t cnt = 0;
// Read the next entry from a directory
while (parent.readDir(p, longFilename) > 0) {
- // If the entry is a directory and the action is LS_SerialPrint
- if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) {
+ if (recursionCnt > MAX_DIR_DEPTH)
+ return;
+ else if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { // If the entry is a directory and the action is LS_SerialPrint
+
// Get the short name for the item, which we know is a folder
char lfilename[FILENAME_LENGTH];
createFilename(lfilename, p);
@@ -241,18 +253,18 @@ void CardReader::initsd()
}
-void CardReader::setroot()
+void CardReader::setroot(bool doPresort)
{
- /*if(!workDir.openRoot(&volume))
- {
- SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
- }*/
workDir=root;
+ workDirDepth = 0;
curDir=&workDir;
- #ifdef SDCARD_SORT_ALPHA
- presort();
- #endif
+#ifdef SDCARD_SORT_ALPHA
+ if (doPresort)
+ presort();
+ else
+ presort_flag = true;
+#endif
}
void CardReader::release()
{
@@ -277,7 +289,7 @@ void CardReader::startFileprint()
void CardReader::openLogFile(const char* name)
{
logging = true;
- openFile(name, false);
+ openFileWrite(name);
}
void CardReader::getDirName(char* name, uint8_t level)
@@ -304,6 +316,18 @@ void CardReader::getAbsFilename(char *t)
else
t[0]=0;
}
+
+void CardReader::printAbsFilenameFast()
+{
+ SERIAL_PROTOCOL('/');
+ for (uint8_t i = 0; i < getWorkDirDepth(); i++)
+ {
+ SERIAL_PROTOCOL(dir_names[i]);
+ SERIAL_PROTOCOL('/');
+ }
+ SERIAL_PROTOCOL(LONGEST_FILENAME);
+}
+
/**
* @brief Dive into subfolder
*
@@ -317,19 +341,17 @@ void CardReader::getAbsFilename(char *t)
* @param[in,out] fileName
* expects file name including path
* in case of absolute path, file name without path is returned
- * @param[in,out] dir SdFile object to operate with,
- * in case of absolute path, curDir is modified to point to dir,
- * so it is not possible to create on stack inside this function,
- * as curDir would point to destroyed object.
*/
-void CardReader::diveSubfolder (const char *fileName, SdFile& dir)
+bool CardReader::diveSubfolder (const char *&fileName)
{
curDir=&root;
- if (!fileName) return;
+ if (!fileName)
+ return 1;
const char *dirname_start, *dirname_end;
if (fileName[0] == '/') // absolute path
{
+ setroot(false);
dirname_start = fileName + 1;
while (*dirname_start)
{
@@ -340,23 +362,13 @@ void CardReader::diveSubfolder (const char *fileName, SdFile& dir)
{
const size_t maxLen = 12;
char subdirname[maxLen+1];
- subdirname[maxLen] = 0;
const size_t len = ((static_cast(dirname_end-dirname_start))>maxLen) ? maxLen : (dirname_end-dirname_start);
strncpy(subdirname, dirname_start, len);
- SERIAL_ECHOLN(subdirname);
- if (!dir.open(curDir, subdirname, O_READ))
- {
- SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
- SERIAL_PROTOCOL(subdirname);
- SERIAL_PROTOCOLLN('.');
- return;
- }
- else
- {
- //SERIAL_ECHOLN("dive ok");
- }
+ subdirname[len] = 0;
+ if (!chdir(subdirname, false))
+ return 0;
- curDir = &dir;
+ curDir = &workDir;
dirname_start = dirname_end + 1;
}
else // the reminder after all /fsa/fdsa/ is the filename
@@ -373,100 +385,142 @@ void CardReader::diveSubfolder (const char *fileName, SdFile& dir)
{
curDir = &workDir;
}
+ return 1;
}
-void CardReader::openFile(const char* name,bool read, bool replace_current/*=true*/)
-{
- if(!cardOK)
- return;
- if(file.isOpen()) //replacing current file by new file, or subfile call
- {
- if(!replace_current)
- {
- if((int)file_subcall_ctr>(int)SD_PROCEDURE_DEPTH-1)
- {
- // SERIAL_ERROR_START;
- // SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
- // SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
- kill(_n("trying to call sub-gcode files with too many levels."), 1);
- return;
- }
-
- SERIAL_ECHO_START;
- SERIAL_ECHOPGM("SUBROUTINE CALL target:\"");
- SERIAL_ECHO(name);
- SERIAL_ECHOPGM("\" parent:\"");
-
- //store current filename and position
- getAbsFilename(filenames[file_subcall_ctr]);
-
- SERIAL_ECHO(filenames[file_subcall_ctr]);
- SERIAL_ECHOPGM("\" pos");
- SERIAL_ECHOLN(sdpos);
- filespos[file_subcall_ctr]=sdpos;
- file_subcall_ctr++;
- }
- else
- {
- SERIAL_ECHO_START;
- SERIAL_ECHOPGM("Now doing file: ");
- SERIAL_ECHOLN(name);
- }
- file.close();
- }
- else //opening fresh file
- {
- file_subcall_ctr=0; //resetting procedure depth in case user cancels print while in procedure
- SERIAL_ECHO_START;
- SERIAL_ECHOPGM("Now fresh file: ");
- SERIAL_ECHOLN(name);
- }
- sdprinting = false;
+static const char ofKill[] PROGMEM = "trying to call sub-gcode files with too many levels.";
+static const char ofSubroutineCallTgt[] PROGMEM = "SUBROUTINE CALL target:\"";
+static const char ofParent[] PROGMEM = "\" parent:\"";
+static const char ofPos[] PROGMEM = "\" pos";
+static const char ofNowDoingFile[] PROGMEM = "Now doing file: ";
+static const char ofNowFreshFile[] PROGMEM = "Now fresh file: ";
+static const char ofFileOpened[] PROGMEM = "File opened: ";
+static const char ofSize[] PROGMEM = " Size: ";
+static const char ofFileSelected[] PROGMEM = "File selected";
+static const char ofSDPrinting[] PROGMEM = "SD-PRINTING ";
+static const char ofWritingToFile[] PROGMEM = "Writing to file: ";
- SdFile myDir;
- const char *fname=name;
- diveSubfolder(fname,myDir);
-
- if(read)
- {
- if (file.open(curDir, fname, O_READ))
- {
- filesize = file.fileSize();
- SERIAL_PROTOCOLRPGM(_N("File opened: "));////MSG_SD_FILE_OPENED
- SERIAL_PROTOCOL(fname);
- SERIAL_PROTOCOLRPGM(_n(" Size: "));////MSG_SD_SIZE
- SERIAL_PROTOCOLLN(filesize);
- sdpos = 0;
-
- SERIAL_PROTOCOLLNRPGM(_N("File selected"));////MSG_SD_FILE_SELECTED
- getfilename(0, fname);
- lcd_setstatus(longFilename[0] ? longFilename : fname);
- lcd_setstatuspgm(PSTR("SD-PRINTING"));
+void CardReader::openFileReadFilteredGcode(const char* name, bool replace_current/* = false*/){
+ if(!cardOK)
+ return;
+
+ if(file.isOpen()){ //replacing current file by new file, or subfile call
+ if(!replace_current){
+ if((int)file_subcall_ctr>(int)SD_PROCEDURE_DEPTH-1){
+ // SERIAL_ERROR_START;
+ // SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
+ // SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
+ kill(ofKill, 1);
+ return;
+ }
+
+ SERIAL_ECHO_START;
+ SERIAL_ECHORPGM(ofSubroutineCallTgt);
+ SERIAL_ECHO(name);
+ SERIAL_ECHORPGM(ofParent);
+
+ //store current filename and position
+ getAbsFilename(filenames[file_subcall_ctr]);
+
+ SERIAL_ECHO(filenames[file_subcall_ctr]);
+ SERIAL_ECHORPGM(ofPos);
+ SERIAL_ECHOLN(sdpos);
+ filespos[file_subcall_ctr]=sdpos;
+ file_subcall_ctr++;
+ } else {
+ SERIAL_ECHO_START;
+ SERIAL_ECHORPGM(ofNowDoingFile);
+ SERIAL_ECHOLN(name);
+ }
+ file.close();
+ } else { //opening fresh file
+ file_subcall_ctr=0; //resetting procedure depth in case user cancels print while in procedure
+ SERIAL_ECHO_START;
+ SERIAL_ECHORPGM(ofNowFreshFile);
+ SERIAL_ECHOLN(name);
}
- else
- {
- SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
- SERIAL_PROTOCOL(fname);
- SERIAL_PROTOCOLLN('.');
- }
- }
- else
- { //write
- if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))
- {
- SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
- SERIAL_PROTOCOL(fname);
- SERIAL_PROTOCOLLN('.');
- }
- else
- {
- saving = true;
- SERIAL_PROTOCOLRPGM(_N("Writing to file: "));////MSG_SD_WRITE_TO_FILE
- SERIAL_PROTOCOLLN(name);
- lcd_setstatus(fname);
- }
- }
+ sdprinting = false;
+ const char *fname=name;
+ if (!diveSubfolder(fname))
+ return;
+
+ if (file.openFilteredGcode(curDir, fname)) {
+ filesize = file.fileSize();
+ SERIAL_PROTOCOLRPGM(ofFileOpened);////MSG_SD_FILE_OPENED
+ SERIAL_PROTOCOL(fname);
+ SERIAL_PROTOCOLRPGM(ofSize);////MSG_SD_SIZE
+ SERIAL_PROTOCOLLN(filesize);
+ sdpos = 0;
+
+ SERIAL_PROTOCOLLNRPGM(ofFileSelected);////MSG_SD_FILE_SELECTED
+ getfilename(0, fname);
+ lcd_setstatus(longFilename[0] ? longFilename : fname);
+ lcd_setstatuspgm(ofSDPrinting);
+ } else {
+ SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
+ SERIAL_PROTOCOL(fname);
+ SERIAL_PROTOCOLLN('.');
+ }
+}
+
+void CardReader::openFileWrite(const char* name)
+{
+ if(!cardOK)
+ return;
+ if(file.isOpen()){ //replacing current file by new file, or subfile call
+#if 0
+ // I doubt chained files support is necessary for file saving:
+ // Intentionally disabled because it takes a lot of code size while being not used
+
+ if((int)file_subcall_ctr>(int)SD_PROCEDURE_DEPTH-1){
+ // SERIAL_ERROR_START;
+ // SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
+ // SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
+ kill(ofKill, 1);
+ return;
+ }
+
+ SERIAL_ECHO_START;
+ SERIAL_ECHORPGM(ofSubroutineCallTgt);
+ SERIAL_ECHO(name);
+ SERIAL_ECHORPGM(ofParent);
+
+ //store current filename and position
+ getAbsFilename(filenames[file_subcall_ctr]);
+
+ SERIAL_ECHO(filenames[file_subcall_ctr]);
+ SERIAL_ECHORPGM(ofPos);
+ SERIAL_ECHOLN(sdpos);
+ filespos[file_subcall_ctr]=sdpos;
+ file_subcall_ctr++;
+ file.close();
+#else
+ SERIAL_ECHOLNPGM("File already opened");
+#endif
+ } else { //opening fresh file
+ file_subcall_ctr=0; //resetting procedure depth in case user cancels print while in procedure
+ SERIAL_ECHO_START;
+ SERIAL_ECHORPGM(ofNowFreshFile);
+ SERIAL_ECHOLN(name);
+ }
+ sdprinting = false;
+
+ const char *fname=name;
+ if (!diveSubfolder(fname))
+ return;
+
+ //write
+ if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)){
+ SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
+ SERIAL_PROTOCOL(fname);
+ SERIAL_PROTOCOLLN('.');
+ } else {
+ saving = true;
+ SERIAL_PROTOCOLRPGM(ofWritingToFile);////MSG_SD_WRITE_TO_FILE
+ SERIAL_PROTOCOLLN(fname);
+ lcd_setstatus(fname);
+ }
}
void CardReader::removeFile(const char* name)
@@ -475,9 +529,9 @@ void CardReader::removeFile(const char* name)
file.close();
sdprinting = false;
- SdFile myDir;
const char *fname=name;
- diveSubfolder(fname,myDir);
+ if (!diveSubfolder(fname))
+ return;
if (file.remove(curDir, fname))
{
@@ -515,10 +569,8 @@ void CardReader::getStatus(bool arg_P)
{
if (arg_P)
{
- SERIAL_PROTOCOL('/');
- for (uint8_t i = 0; i < getWorkDirDepth(); i++)
- printf_P(PSTR("%s/"), dir_names[i]);
- puts(filename);
+ printAbsFilenameFast();
+ SERIAL_PROTOCOLLN();
}
else
SERIAL_PROTOCOLLN(LONGEST_FILENAME);
@@ -670,7 +722,7 @@ uint16_t CardReader::getnrfilenames()
return nrFiles;
}
-void CardReader::chdir(const char * relpath)
+bool CardReader::chdir(const char * relpath, bool doPresort)
{
SdFile newfile;
SdFile *parent=&root;
@@ -678,23 +730,32 @@ void CardReader::chdir(const char * relpath)
if(workDir.isOpen())
parent=&workDir;
- if(!newfile.open(*parent,relpath, O_READ))
+ if(!newfile.open(*parent,relpath, O_READ) || ((workDirDepth + 1) >= MAX_DIR_DEPTH))
{
SERIAL_ECHO_START;
SERIAL_ECHORPGM(_n("Cannot enter subdir: "));////MSG_SD_CANT_ENTER_SUBDIR
SERIAL_ECHOLN(relpath);
+ return 0;
}
else
{
+ strcpy(dir_names[workDirDepth], relpath);
+ puts(relpath);
+
if (workDirDepth < MAX_DIR_DEPTH) {
for (int d = ++workDirDepth; d--;)
workDirParents[d+1] = workDirParents[d];
workDirParents[0]=*parent;
}
workDir=newfile;
- #ifdef SDCARD_SORT_ALPHA
+
+#ifdef SDCARD_SORT_ALPHA
+ if (doPresort)
presort();
- #endif
+ else
+ presort_flag = true;
+#endif
+ return 1;
}
}
@@ -1011,7 +1072,7 @@ void CardReader::printingHasFinished()
{
file.close();
file_subcall_ctr--;
- openFile(filenames[file_subcall_ctr],true,true);
+ openFileReadFilteredGcode(filenames[file_subcall_ctr],true);
setIndex(filespos[file_subcall_ctr]);
startFileprint();
}
diff --git a/Firmware/cardreader.h b/Firmware/cardreader.h
index 9bf9bd0a6..c79420737 100644
--- a/Firmware/cardreader.h
+++ b/Firmware/cardreader.h
@@ -1,6 +1,8 @@
#ifndef CARDREADER_H
#define CARDREADER_H
+#define SDSUPPORT
+
#ifdef SDSUPPORT
#define MAX_DIR_DEPTH 6
@@ -19,7 +21,8 @@ public:
//this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset
void checkautostart(bool x);
- void openFile(const char* name,bool read,bool replace_current=true);
+ void openFileWrite(const char* name);
+ void openFileReadFilteredGcode(const char* name, bool replace_current = false);
void openLogFile(const char* name);
void removeFile(const char* name);
void closefile(bool store_location=false);
@@ -34,14 +37,15 @@ public:
uint16_t getnrfilenames();
void getAbsFilename(char *t);
+ void printAbsFilenameFast();
void getDirName(char* name, uint8_t level);
uint16_t getWorkDirDepth();
void ls(bool printLFN);
- void chdir(const char * relpath);
+ bool chdir(const char * relpath, bool doPresort);
void updir();
- void setroot();
+ void setroot(bool doPresort);
#ifdef SDCARD_SORT_ALPHA
void presort();
@@ -58,9 +62,11 @@ public:
#endif
FORCE_INLINE bool isFileOpen() { return file.isOpen(); }
- FORCE_INLINE bool eof() { return sdpos>=filesize ;};
- FORCE_INLINE int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();};
- FORCE_INLINE void setIndex(long index) {sdpos = index;file.seekSet(index);};
+ bool eof() { return sdpos>=filesize; }
+ // There may be a potential performance problem - when the comment reading fails, sdpos points to the last correctly read character.
+ // However, repeated reading (e.g. after power panic) the comment will be read again - it should survive correctly, it will just take a few moments to skip
+ FORCE_INLINE int16_t getFilteredGcodeChar() { sdpos = file.curPosition();return (int16_t)file.readFilteredGcode();};
+ void setIndex(long index) {sdpos = index;file.seekSetFilteredGcode(index);};
FORCE_INLINE uint8_t percentDone(){if(!isFileOpen()) return 0; if(filesize) return sdpos/((filesize+99)/100); else return 0;};
FORCE_INLINE char* getWorkDirName(){workDir.getFilename(filename);return filename;};
FORCE_INLINE uint32_t get_sdpos() { if (!isFileOpen()) return 0; else return(sdpos); };
@@ -82,6 +88,10 @@ public:
char longFilename[LONG_FILENAME_LENGTH];
bool filenameIsDir;
int lastnr; //last number of the autostart;
+#ifdef SDCARD_SORT_ALPHA
+ bool presort_flag;
+ char dir_names[MAX_DIR_DEPTH][9];
+#endif // SDCARD_SORT_ALPHA
private:
SdFile root,*curDir,workDir,workDirParents[MAX_DIR_DEPTH];
uint16_t workDirDepth;
@@ -155,7 +165,7 @@ private:
int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
char* diveDirName;
- void diveSubfolder (const char *fileName, SdFile& dir);
+ bool diveSubfolder (const char *&fileName);
void lsDive(const char *prepend, SdFile parent, const char * const match=NULL);
#ifdef SDCARD_SORT_ALPHA
void flush_presort();
diff --git a/Firmware/cmdqueue.cpp b/Firmware/cmdqueue.cpp
index afdddfba2..9c822dab5 100755
--- a/Firmware/cmdqueue.cpp
+++ b/Firmware/cmdqueue.cpp
@@ -584,13 +584,14 @@ void get_command()
sd_count.value = 0;
// Reads whole lines from the SD card. Never leaves a half-filled line in the cmdbuffer.
while( !card.eof() && !stop_buffering) {
- int16_t n=card.get();
+ int16_t n=card.getFilteredGcodeChar();
char serial_char = (char)n;
- if(serial_char == '\n' ||
- serial_char == '\r' ||
- ((serial_char == '#' || serial_char == ':') && comment_mode == false) ||
- serial_count >= (MAX_CMD_SIZE - 1) || n==-1)
- {
+ if( serial_char == '\n'
+ || serial_char == '\r'
+ || ((serial_char == '#' || serial_char == ':') )
+ || serial_count >= (MAX_CMD_SIZE - 1)
+ || n==-1
+ ){
if(serial_char=='#')
stop_buffering=true;
@@ -601,8 +602,7 @@ void get_command()
// read from the sdcard into sd_count,
// so that the lenght of the already read empty lines and comments will be added
// to the following non-empty line.
- comment_mode = false;
- continue; //if empty line
+ return; // prevent cycling indefinitely - let manage_heaters do their job
}
// The new command buffer could be updated non-atomically, because it is not yet considered
// to be inside the active queue.
@@ -618,10 +618,10 @@ void get_command()
// MYSERIAL.print(sd_count.value, DEC);
// SERIAL_ECHOPGM(") ");
// SERIAL_ECHOLN(cmdbuffer+bufindw+CMDHDRSIZE);
-// SERIAL_ECHOPGM("cmdbuffer:");
-// MYSERIAL.print(cmdbuffer);
-// SERIAL_ECHOPGM("buflen:");
-// MYSERIAL.print(buflen+1);
+// SERIAL_ECHOPGM("cmdbuffer:");
+// MYSERIAL.print(cmdbuffer);
+// SERIAL_ECHOPGM("buflen:");
+// MYSERIAL.print(buflen+1);
sd_count.value = 0;
cli();
@@ -640,15 +640,15 @@ void get_command()
serial_count = 0; //clear buffer
if(card.eof()) break;
-
+
// The following line will reserve buffer space if available.
if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1, true))
return;
}
else
{
- if(serial_char == ';') comment_mode = true;
- else if(!comment_mode) cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
+ // there are no comments coming from the filtered file
+ cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
}
}
if(card.eof())
diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp
index a0efc3aae..fb79022ff 100644
--- a/Firmware/mesh_bed_calibration.cpp
+++ b/Firmware/mesh_bed_calibration.cpp
@@ -944,7 +944,7 @@ static inline void update_current_position_z()
// At the current position, find the Z stop.
-inline bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
+bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
#ifdef SUPPORT_VERBOSITY
verbosity_level
#endif //SUPPORT_VERBOSITY
@@ -1065,7 +1065,7 @@ error:
}
#ifdef NEW_XYZCAL
-extern bool xyzcal_find_bed_induction_sensor_point_xy();
+bool xyzcal_find_bed_induction_sensor_point_xy();
#endif //NEW_XYZCAL
// Search around the current_position[X,Y],
// look for the induction sensor response.
@@ -1081,7 +1081,7 @@ extern bool xyzcal_find_bed_induction_sensor_point_xy();
#endif //HEATBED_V2
#ifdef HEATBED_V2
-inline bool find_bed_induction_sensor_point_xy(int
+bool find_bed_induction_sensor_point_xy(int
#if !defined (NEW_XYZCAL) && defined (SUPPORT_VERBOSITY)
verbosity_level
#endif
@@ -1335,7 +1335,7 @@ inline bool find_bed_induction_sensor_point_xy(int
#endif //NEW_XYZCAL
}
#else //HEATBED_V2
-inline bool find_bed_induction_sensor_point_xy(int verbosity_level)
+bool find_bed_induction_sensor_point_xy(int verbosity_level)
{
#ifdef NEW_XYZCAL
return xyzcal_find_bed_induction_sensor_point_xy();
diff --git a/Firmware/mesh_bed_calibration.h b/Firmware/mesh_bed_calibration.h
index 8adc1c119..7ca93c953 100644
--- a/Firmware/mesh_bed_calibration.h
+++ b/Firmware/mesh_bed_calibration.h
@@ -146,9 +146,9 @@ inline bool world2machine_clamp(float &x, float &y)
return clamped;
}
-extern bool find_bed_induction_sensor_point_z(float minimum_z = -10.f, uint8_t n_iter = 3, int verbosity_level = 0);
-extern bool find_bed_induction_sensor_point_xy(int verbosity_level = 0);
-extern void go_home_with_z_lift();
+bool find_bed_induction_sensor_point_z(float minimum_z = -10.f, uint8_t n_iter = 3, int verbosity_level = 0);
+bool find_bed_induction_sensor_point_xy(int verbosity_level = 0);
+void go_home_with_z_lift();
/**
* @brief Bed skew and offest detection result
diff --git a/Firmware/messages.c b/Firmware/messages.c
index 0b1d58e04..aa05ad990 100644
--- a/Firmware/messages.c
+++ b/Firmware/messages.c
@@ -16,7 +16,7 @@ const char MSG_BED_DONE[] PROGMEM_I1 = ISTR("Bed done"); ////
const char MSG_BED_HEATING[] PROGMEM_I1 = ISTR("Bed Heating"); ////
const char MSG_BED_LEVELING_FAILED_POINT_LOW[] PROGMEM_I1 = ISTR("Bed leveling failed. Sensor didnt trigger. Debris on nozzle? Waiting for reset."); ////c=20 r=5
const char MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED[] PROGMEM_I1 = ISTR("XYZ calibration failed. Please consult the manual."); ////c=20 r=8
-const char MSG_BELT_STATUS[] PROGMEM_I1 = ISTR("Belt Status");////c=18
+const char MSG_BELT_STATUS[] PROGMEM_I1 = ISTR("Belt status");////c=18
const char MSG_CALIBRATE_Z_AUTO[] PROGMEM_I1 = ISTR("Calibrating Z"); ////c=20 r=2
const char MSG_CARD_MENU[] PROGMEM_I1 = ISTR("Print from SD"); ////
const char MSG_CHECKING_X[] PROGMEM_I1 = ISTR("Checking X axis"); ////c=20
@@ -29,7 +29,7 @@ const char MSG_CRASHDETECT[] PROGMEM_I1 = ISTR("Crash det."); ////c=13
const char MSG_ERROR[] PROGMEM_I1 = ISTR("ERROR:"); ////
const char MSG_EXTRUDER[] PROGMEM_I1 = ISTR("Extruder"); ////c=17
const char MSG_FANS_CHECK[] PROGMEM_I1 = ISTR("Fans check"); ////c=13
-const char MSG_FIL_RUNOUTS[] PROGMEM_I1 = ISTR("Fil. runouts"); ////c=14
+const char MSG_FIL_RUNOUTS[] PROGMEM_I1 = ISTR("Fil. runouts"); ////c=15
const char MSG_FILAMENT[] PROGMEM_I1 = ISTR("Filament"); ////c=17 r=1
const char MSG_FAN_SPEED[] PROGMEM_I1 = ISTR("Fan speed"); ////c=14
const char MSG_FILAMENT_CLEAN[] PROGMEM_I1 = ISTR("Filament extruding & with correct color?"); ////c=20 r=2
@@ -65,14 +65,14 @@ const char MSG_STEEL_SHEETS[] PROGMEM_I1 = ISTR("Steel sheets"); ////c=18
const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1[] PROGMEM_I1 = ISTR("Measuring reference height of calibration point"); ////c=60
const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2[] PROGMEM_I1 = ISTR(" of 9"); ////c=14
const char MSG_MENU_CALIBRATION[] PROGMEM_I1 = ISTR("Calibration"); ////
-const char MSG_MMU_FAILS[] PROGMEM_I1 = ISTR("MMU fails"); ////c=14
-const char MSG_MMU_LOAD_FAILS[] PROGMEM_I1 = ISTR("MMU load fails"); ////c=14
+const char MSG_MMU_FAILS[] PROGMEM_I1 = ISTR("MMU fails"); ////c=15
+const char MSG_MMU_LOAD_FAILS[] PROGMEM_I1 = ISTR("MMU load fails"); ////c=15
const char MSG_NO[] PROGMEM_I1 = ISTR("No"); ////
const char MSG_NOZZLE[] PROGMEM_I1 = ISTR("Nozzle"); ////
const char MSG_PAPER[] PROGMEM_I1 = ISTR("Place a sheet of paper under the nozzle during the calibration of first 4 points. If the nozzle catches the paper, power off the printer immediately."); ////c=20 r=10
const char MSG_PLACE_STEEL_SHEET[] PROGMEM_I1 = ISTR("Please place steel sheet on heatbed."); ////c=20 r=4
const char MSG_PLEASE_WAIT[] PROGMEM_I1 = ISTR("Please wait"); ////c=20
-const char MSG_POWER_FAILURES[] PROGMEM_I1 = ISTR("Power failures"); ////c=14
+const char MSG_POWER_FAILURES[] PROGMEM_I1 = ISTR("Power failures"); ////c=15
const char MSG_PREHEAT_NOZZLE[] PROGMEM_I1 = ISTR("Preheat the nozzle!"); ////c=20
const char MSG_PRESS_TO_UNLOAD[] PROGMEM_I1 = ISTR("Please press the knob to unload filament"); ////c=20 r=4
const char MSG_PRINT_ABORTED[] PROGMEM_I1 = ISTR("Print aborted"); ////c=20
@@ -131,7 +131,7 @@ const char MSG_MODEL[] PROGMEM_I1 = ISTR("Model"); ////
const char MSG_FIRMWARE[] PROGMEM_I1 = ISTR("Firmware"); ////
const char MSG_GCODE[] PROGMEM_I1 = ISTR("Gcode"); ////
const char MSG_GCODE_DIFF_PRINTER_CONTINUE[] PROGMEM_I1 = ISTR("G-code sliced for a different printer type. Continue?"); ////c=20 r=5
-const char MSG_GCODE_DIFF_PRINTER_CANCELLED[] PROGMEM_I1 =ISTR("G-code sliced for a different printer type. Please re-slice the model again. Print cancelled."); ////c=20 r=6
+const char MSG_GCODE_DIFF_PRINTER_CANCELLED[] PROGMEM_I1 =ISTR("G-code sliced for a different printer type. Please re-slice the model again. Print cancelled."); ////c=20 r=7
const char MSG_NOZZLE_DIAMETER[] PROGMEM_I1 = ISTR("Nozzle d."); ////
const char MSG_MMU_MODE[] PROGMEM_I1 = ISTR("MMU Mode"); ////
const char MSG_SD_CARD[] PROGMEM_I1 = ISTR("SD card"); ////
@@ -197,3 +197,4 @@ const char MSG_M112_KILL[] PROGMEM_N1 = "M112 called. Emergency Stop."; ////c=20
const char MSG_ADVANCE_K[] PROGMEM_N1 = "Advance K:"; ////c=13
const char MSG_POWERPANIC_DETECTED[] PROGMEM_N1 = "POWER PANIC DETECTED"; ////c=20
const char MSG_LCD_STATUS_CHANGED[] PROGMEM_N1 = "LCD status changed";
+const char MSG_FILE_SELECTED[] PROGMEM_N1 = "File selected"; ////c=20
diff --git a/Firmware/messages.h b/Firmware/messages.h
index 0a05c58f5..a5b672fa2 100644
--- a/Firmware/messages.h
+++ b/Firmware/messages.h
@@ -197,6 +197,7 @@ extern const char MSG_M112_KILL[];
extern const char MSG_ADVANCE_K[];
extern const char MSG_POWERPANIC_DETECTED[];
extern const char MSG_LCD_STATUS_CHANGED[];
+extern const char MSG_FILE_SELECTED[];
#if defined(__cplusplus)
}
diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp
index c2b6600fb..7e5054fff 100755
--- a/Firmware/ultralcd.cpp
+++ b/Firmware/ultralcd.cpp
@@ -57,7 +57,7 @@
int scrollstuff = 0;
char longFilenameOLD[LONG_FILENAME_LENGTH];
-
+int clock_interval = 0;
static void lcd_sd_updir();
static void lcd_mesh_bed_leveling_settings();
@@ -75,11 +75,6 @@ int8_t FSensorStateMenu = 1;
bool bMenuFSDetect=false;
#endif //IR_SENSOR_ANALOG
-
-#ifdef SDCARD_SORT_ALPHA
-bool presort_flag = false;
-#endif
-
LcdCommands lcd_commands_type = LcdCommands::Idle;
static uint8_t lcd_commands_step = 0;
@@ -676,185 +671,219 @@ void lcdui_print_cmd_diag(void)
// Print time (8 chars total)
void lcdui_print_time(void)
{
- //if remaining print time estimation is available print it else print elapsed time
- uint16_t print_t = 0;
- if (print_time_remaining_normal != PRINT_TIME_REMAINING_INIT)
- print_t = print_time_remaining();
- else if(starttime != 0)
- print_t = _millis() / 60000 - starttime / 60000;
- int chars = 0;
- if ((PRINTER_ACTIVE) && ((print_time_remaining_normal != PRINT_TIME_REMAINING_INIT) || (starttime != 0)))
- {
- char suff = ' ';
- char suff_doubt = ' ';
- if (print_time_remaining_normal != PRINT_TIME_REMAINING_INIT)
- {
- suff = 'R';
- if (feedmultiply != 100)
- suff_doubt = '?';
- }
- if (print_t < 6000) //time<100h
- chars = lcd_printf_P(_N("%c%02u:%02u%c%c"), LCD_STR_CLOCK[0], print_t / 60, print_t % 60, suff, suff_doubt);
- else //time>=100h
- chars = lcd_printf_P(_N("%c%3uh %c%c"), LCD_STR_CLOCK[0], print_t / 60, suff, suff_doubt);
- }
- else
- chars = lcd_printf_P(_N("%c--:-- "), LCD_STR_CLOCK[0]);
- lcd_space(8 - chars);
+ //if remaining print time estimation is available print it else print elapsed time
+ int chars = 0;
+ if ((PRINTER_ACTIVE) && (starttime != 0))
+ {
+ uint16_t print_t = 0;
+ uint16_t print_tr = 0;
+ uint16_t print_tc = 0;
+ char suff = ' ';
+ char suff_doubt = ' ';
+
+#ifdef TMC2130
+ if (SilentModeMenu != SILENT_MODE_OFF)
+ {
+ if (print_time_remaining_silent != PRINT_TIME_REMAINING_INIT)
+ {
+ print_tr = print_time_remaining_silent;
+ }
+//#ifdef CLOCK_INTERVAL_TIME
+ if (print_time_to_change_silent != PRINT_TIME_REMAINING_INIT)
+ {
+ print_tc = print_time_to_change_silent;
+ }
+//#endif //CLOCK_INTERVAL_TIME
+ }
+ else
+ {
+#endif //TMC2130
+ if (print_time_remaining_normal != PRINT_TIME_REMAINING_INIT)
+ {
+ print_tr = print_time_remaining_normal;
+ }
+//#ifdef CLOCK_INTERVAL_TIME
+ if (print_time_to_change_normal != PRINT_TIME_REMAINING_INIT)
+ {
+ print_tc = print_time_to_change_normal;
+ }
+//#endif //CLOCK_INTERVAL_TIME
+#ifdef TMC2130
+ }
+#endif //TMC2130
+
+//#ifdef CLOCK_INTERVAL_TIME
+ if (clock_interval == CLOCK_INTERVAL_TIME*2)
+ {
+ clock_interval = 0;
+ }
+ clock_interval++;
+
+ if (print_tc != 0 && clock_interval > CLOCK_INTERVAL_TIME)
+ {
+ print_t = print_tc;
+ suff = 'C';
+ }
+ else
+//#endif //CLOCK_INTERVAL_TIME
+ if (print_tr != 0)
+ {
+ print_t = print_tr;
+ suff = 'R';
+ }
+ else
+ {
+ print_t = _millis() / 60000 - starttime / 60000;
+ }
+
+ if (feedmultiply != 100 && (print_t == print_tr || print_t == print_tc))
+ {
+ suff_doubt = '?';
+ print_t = 100ul * print_t / feedmultiply;
+ }
+
+ if (print_t < 6000) //time<100h
+ chars = lcd_printf_P(_N("%c%02u:%02u%c%c"), LCD_STR_CLOCK[0], print_t / 60, print_t % 60, suff, suff_doubt);
+ else //time>=100h
+ chars = lcd_printf_P(_N("%c%3uh %c%c"), LCD_STR_CLOCK[0], print_t / 60, suff, suff_doubt);
+ }
+ else
+ chars = lcd_printf_P(_N("%c--:-- "), LCD_STR_CLOCK[0]);
+ lcd_space(8 - chars);
}
-//Print status line on status screen
+//! @Brief Print status line on status screen
void lcdui_print_status_line(void)
{
- if (IS_SD_PRINTING)
- {
- if (strcmp(longFilenameOLD, (card.longFilename[0] ? card.longFilename : card.filename)) != 0)
- {
- memset(longFilenameOLD, '\0', strlen(longFilenameOLD));
- sprintf_P(longFilenameOLD, PSTR("%s"), (card.longFilename[0] ? card.longFilename : card.filename));
- scrollstuff = 0;
- }
- }
+ if (IS_SD_PRINTING) {
+ if (strcmp(longFilenameOLD, (card.longFilename[0] ? card.longFilename : card.filename)) != 0) {
+ memset(longFilenameOLD, '\0', strlen(longFilenameOLD));
+ sprintf_P(longFilenameOLD, PSTR("%s"), (card.longFilename[0] ? card.longFilename : card.filename));
+ scrollstuff = 0;
+ }
+ }
- if (heating_status)
- { // If heating flag, show progress of heating
- heating_status_counter++;
- if (heating_status_counter > 13)
- {
- heating_status_counter = 0;
- }
- lcd_set_cursor(7, 3);
- lcd_space(13);
+ if (heating_status) { // If heating flag, show progress of heating
+ heating_status_counter++;
+ if (heating_status_counter > 13) {
+ heating_status_counter = 0;
+ }
+ lcd_set_cursor(7, 3);
+ lcd_space(13);
+
+ for (unsigned int dots = 0; dots < heating_status_counter; dots++) {
+ lcd_putc_at(7 + dots, 3, '.');
+ }
+ switch (heating_status) {
+ case 1:
+ lcd_puts_at_P(0, 3, _T(MSG_HEATING));
+ break;
+ case 2:
+ lcd_puts_at_P(0, 3, _T(MSG_HEATING_COMPLETE));
+ heating_status = 0;
+ heating_status_counter = 0;
+ break;
+ case 3:
+ lcd_puts_at_P(0, 3, _T(MSG_BED_HEATING));
+ break;
+ case 4:
+ lcd_puts_at_P(0, 3, _T(MSG_BED_DONE));
+ heating_status = 0;
+ heating_status_counter = 0;
+ break;
+ default:
+ break;
+ }
+ }
+ else if ((IS_SD_PRINTING) && (custom_message_type == CustomMsg::Status)) { // If printing from SD, show what we are printing
+ if(strlen(longFilenameOLD) > LCD_WIDTH) {
+ int inters = 0;
+ int gh = scrollstuff;
+ while (((gh - scrollstuff) < LCD_WIDTH) && (inters == 0)) {
+ if (longFilenameOLD[gh] == '\0') {
+ lcd_set_cursor(gh - scrollstuff, 3);
+ lcd_print(longFilenameOLD[gh - 1]);
+ scrollstuff = 0;
+ gh = scrollstuff;
+ inters = 1;
+ } else {
+ lcd_set_cursor(gh - scrollstuff, 3);
+ lcd_print(longFilenameOLD[gh - 1]);
+ gh++;
+ }
+ }
+ scrollstuff++;
+ } else {
+ lcd_printf_P(PSTR("%-20s"), longFilenameOLD);
+ }
+ } else { // Otherwise check for other special events
+ switch (custom_message_type) {
+ case CustomMsg::MsgUpdate: //Short message even while printing from SD
+ case CustomMsg::Status: // Nothing special, print status message normally
+ case CustomMsg::M0Wait: // M0/M1 Wait command working even from SD
+ lcd_print(lcd_status_message);
+ break;
+ case CustomMsg::MeshBedLeveling: // If mesh bed leveling in progress, show the status
+ if (custom_message_state > 10) {
+ lcd_set_cursor(0, 3);
+ lcd_space(20);
+ lcd_puts_at_P(0, 3, _T(MSG_CALIBRATE_Z_AUTO));
+ lcd_puts_P(PSTR(" : "));
+ lcd_print(custom_message_state-10);
+ } else {
+ if (custom_message_state == 3)
+ {
+ lcd_puts_P(_T(WELCOME_MSG));
+ lcd_setstatuspgm(_T(WELCOME_MSG));
+ custom_message_type = CustomMsg::Status;
+ }
+ if (custom_message_state > 3 && custom_message_state <= 10 ) {
+ lcd_set_cursor(0, 3);
+ lcd_space(19);
+ lcd_puts_at_P(0, 3, _i("Calibration done"));////MSG_HOMEYZ_DONE
+ custom_message_state--;
+ }
+ }
+ break;
+ case CustomMsg::FilamentLoading: // If loading filament, print status
+ lcd_print(lcd_status_message);
+ break;
+ case CustomMsg::PidCal: // PID tuning in progress
+ lcd_print(lcd_status_message);
+ if (pid_cycle <= pid_number_of_cycles && custom_message_state > 0) {
+ lcd_set_cursor(10, 3);
+ lcd_print(itostr3(pid_cycle));
+ lcd_print('/');
+ lcd_print(itostr3left(pid_number_of_cycles));
+ }
+ break;
+ case CustomMsg::TempCal: // PINDA temp calibration in progress
+ char statusLine[LCD_WIDTH + 1];
+ sprintf_P(statusLine, PSTR("%-20S"), _T(MSG_TEMP_CALIBRATION));
+ char progress[4];
+ sprintf_P(progress, PSTR("%d/6"), custom_message_state);
+ memcpy(statusLine + 12, progress, sizeof(progress) - 1);
+ lcd_set_cursor(0, 3);
+ lcd_print(statusLine);
+ break;
+ case CustomMsg::TempCompPreheat: // temp compensation preheat
+ lcd_puts_at_P(0, 3, _i("PINDA Heating"));////MSG_PINDA_PREHEAT c=20 r=1
+ if (custom_message_state <= PINDA_HEAT_T) {
+ lcd_puts_P(PSTR(": "));
+ lcd_print(custom_message_state); //seconds
+ lcd_print(' ');
+ }
+ break;
+ case CustomMsg::Resuming: //Resuming
+ lcd_puts_at_P(0, 3, _T(MSG_RESUMING_PRINT));
+ break;
+ }
+ }
- for (unsigned int dots = 0; dots < heating_status_counter; dots++)
- {
- lcd_putc_at(7 + dots, 3, '.');
- }
- switch (heating_status)
- {
- case 1:
- lcd_puts_at_P(0, 3, _T(MSG_HEATING));
- break;
- case 2:
- lcd_puts_at_P(0, 3, _T(MSG_HEATING_COMPLETE));
- heating_status = 0;
- heating_status_counter = 0;
- break;
- case 3:
- lcd_puts_at_P(0, 3, _T(MSG_BED_HEATING));
- break;
- case 4:
- lcd_puts_at_P(0, 3, _T(MSG_BED_DONE));
- heating_status = 0;
- heating_status_counter = 0;
- break;
- default:
- break;
- }
- }
- else if ((IS_SD_PRINTING) && (custom_message_type == CustomMsg::Status))
- { // If printing from SD, show what we are printing
- if(strlen(longFilenameOLD) > LCD_WIDTH)
- {
- int inters = 0;
- int gh = scrollstuff;
- while (((gh - scrollstuff) < LCD_WIDTH) && (inters == 0))
- {
- if (longFilenameOLD[gh] == '\0')
- {
- lcd_set_cursor(gh - scrollstuff, 3);
- lcd_print(longFilenameOLD[gh - 1]);
- scrollstuff = 0;
- gh = scrollstuff;
- inters = 1;
- }
- else
- {
- lcd_set_cursor(gh - scrollstuff, 3);
- lcd_print(longFilenameOLD[gh - 1]);
- gh++;
- }
- }
- scrollstuff++;
- }
- else
- {
- lcd_printf_P(PSTR("%-20s"), longFilenameOLD);
- }
- }
- else
- { // Otherwise check for other special events
- switch (custom_message_type)
- {
- case CustomMsg::Status: // Nothing special, print status message normally
- lcd_print(lcd_status_message);
- break;
- case CustomMsg::MeshBedLeveling: // If mesh bed leveling in progress, show the status
- if (custom_message_state > 10)
- {
- lcd_set_cursor(0, 3);
- lcd_space(20);
- lcd_puts_at_P(0, 3, _T(MSG_CALIBRATE_Z_AUTO));
- lcd_puts_P(PSTR(" : "));
- lcd_print(custom_message_state-10);
- }
- else
- {
- if (custom_message_state == 3)
- {
- lcd_puts_P(_T(WELCOME_MSG));
- lcd_setstatuspgm(_T(WELCOME_MSG));
- custom_message_type = CustomMsg::Status;
- }
- if (custom_message_state > 3 && custom_message_state <= 10 )
- {
- lcd_set_cursor(0, 3);
- lcd_space(19);
- lcd_puts_at_P(0, 3, _i("Calibration done"));////MSG_HOMEYZ_DONE
- custom_message_state--;
- }
- }
- break;
- case CustomMsg::FilamentLoading: // If loading filament, print status
- lcd_print(lcd_status_message);
- break;
- case CustomMsg::PidCal: // PID tuning in progress
- lcd_print(lcd_status_message);
- if (pid_cycle <= pid_number_of_cycles && custom_message_state > 0)
- {
- lcd_set_cursor(10, 3);
- lcd_print(itostr3(pid_cycle));
- lcd_print('/');
- lcd_print(itostr3left(pid_number_of_cycles));
- }
- break;
- case CustomMsg::TempCal: // PINDA temp calibration in progress
- {
- char statusLine[LCD_WIDTH + 1];
- sprintf_P(statusLine, PSTR("%-20S"), _T(MSG_TEMP_CALIBRATION));
- char progress[4];
- sprintf_P(progress, PSTR("%d/6"), custom_message_state);
- memcpy(statusLine + 12, progress, sizeof(progress) - 1);
- lcd_set_cursor(0, 3);
- lcd_print(statusLine);
- }
- break;
- case CustomMsg::TempCompPreheat: // temp compensation preheat
- lcd_puts_at_P(0, 3, _i("PINDA Heating"));////MSG_PINDA_PREHEAT c=20 r=1
- if (custom_message_state <= PINDA_HEAT_T)
- {
- lcd_puts_P(PSTR(": "));
- lcd_print(custom_message_state); //seconds
- lcd_print(' ');
- }
- break;
- }
- }
-
// Fill the rest of line to have nice and clean output
- for(int fillspace = 0; fillspace < 20; fillspace++)
- if ((lcd_status_message[fillspace] <= 31 ))
- lcd_print(' ');
+ for(int fillspace = 0; fillspace < 20; fillspace++)
+ if ((lcd_status_message[fillspace] <= 31 ))
+ lcd_print(' ');
}
//! @brief Show Status Screen
@@ -1584,8 +1613,8 @@ static void pgmtext_with_colon(const char *ipgmLabel, char *dst, uint8_t dstSize
//! |01234567890123456789|
//! |Nozzle FAN: 0000 RPM| FAN c=10 r=1 SPEED c=3 r=1
//! |Print FAN: 0000 RPM| FAN c=10 r=1 SPEED c=3 r=1
-//! |Fil. Xd:000 Yd:000 | Fil. c=4 r=1
-//! |Int: 000 Shut: 000 | Int: c=4 r=1 Shut: c=4 r=1
+//! | |
+//! | |
//! ----------------------
//! @endcode
//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations.
@@ -1599,37 +1628,7 @@ void lcd_menu_extruder_info() // NOT static due to using ins
char nozzle[maxChars], print[maxChars];
pgmtext_with_colon(_i("Nozzle FAN"), nozzle, maxChars); ////c=10 r=1
pgmtext_with_colon(_i("Print FAN"), print, maxChars); ////c=10 r=1
- lcd_printf_P(_N("%s %4d RPM\n" "%s %4d RPM\n"), nozzle, 60*fan_speed[0], print, 60*fan_speed[1] );
-
-#ifdef PAT9125
- // Display X and Y difference from Filament sensor
- // Display Light intensity from Filament sensor
- // Frame_Avg register represents the average brightness of all pixels within a frame (324 pixels). This
- // value ranges from 0(darkest) to 255(brightest).
- // Display LASER shutter time from Filament sensor
- // Shutter register is an index of LASER shutter time. It is automatically controlled by the chip's internal
- // auto-exposure algorithm. When the chip is tracking on a good reflection surface, the Shutter is small.
- // When the chip is tracking on a poor reflection surface, the Shutter is large. Value ranges from 0 to 46.
- if (mmu_enabled == false)
- {
- if (!fsensor_enabled)
- lcd_puts_P(_N("Filament sensor\n" "is disabled."));
- else
- {
- if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LcdCommands::Layer1Cal))
- pat9125_update();
- lcd_printf_P(_N(
- "Fil. Xd:%3d Yd:%3d\n" ////c=4 r=1
- "Int: %3d " ////c=4 r=1
- "Shut: %3d" ////c=4 r=1
- ),
- pat9125_x, pat9125_y,
- pat9125_b, pat9125_s
- );
- }
- }
-#endif //PAT9125
-
+ lcd_printf_P(_N("%s %4d RPM\n" "%s %4d RPM\n"), nozzle, 60*fan_speed[0], print, 60*fan_speed[1] );
menu_back_if_clicked();
}
@@ -1661,8 +1660,8 @@ static void lcd_menu_fails_stats_mmu()
//! @code{.unparsed}
//! |01234567890123456789|
//! |Last print failures | MSG_LAST_PRINT_FAILURES c=20
-//! | MMU fails: 000| MSG_MMU_FAILS c=14
-//! | MMU load fails: 000| MSG_MMU_LOAD_FAILS c=14
+//! | MMU fails 000| MSG_MMU_FAILS c=15
+//! | MMU load fails 000| MSG_MMU_LOAD_FAILS c=15
//! | |
//! ----------------------
//! @endcode
@@ -1683,9 +1682,9 @@ static void lcd_menu_fails_stats_mmu_print()
//! @code{.unparsed}
//! |01234567890123456789|
//! |Total failures | MSG_TOTAL_FAILURES c=20
-//! | MMU fails: 000| MSG_MMU_FAILS c=14
-//! | MMU load fails: 000| MSG_MMU_LOAD_FAILS c=14
-//! | MMU power fails:000| c=14 r=1
+//! | MMU fails 000| MSG_MMU_FAILS c=15
+//! | MMU load fails 000| MSG_MMU_LOAD_FAILS c=15
+//! | MMU power fails 000| c=15
//! ----------------------
//! @endcode
//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations.
@@ -1710,8 +1709,8 @@ static const char failStatsFmt[] PROGMEM = "%S\n" " %-16.16S%-3d\n" " %-16.16S%-
//! @code{.unparsed}
//! |01234567890123456789|
//! |Total failures | MSG_TOTAL_FAILURES c=20
-//! | Power failures: 000| MSG_POWER_FAILURES c=14
-//! | Fil. runouts : 000| MSG_FIL_RUNOUTS c=14
+//! | Power failures 000| MSG_POWER_FAILURES c=15
+//! | Fil. runouts 000| MSG_FIL_RUNOUTS c=15
//! | Crash X:000 Y:000| MSG_CRASH c=7
//! ----------------------
//! @endcode
@@ -1735,9 +1734,9 @@ static void lcd_menu_fails_stats_total()
//! @code{.unparsed}
//! |01234567890123456789|
//! |Last print failures | MSG_LAST_PRINT_FAILURES c=20
-//! | Power failures 000| MSG_POWER_FAILURES c=14
-//! | Fil. runouts 000| MSG_FIL_RUNOUTS c=14
-//! | Crash X:000 Y:000| MSG_CRASH c=7
+//! | Power failures 000| MSG_POWER_FAILURES c=15
+//! | Fil. runouts 000| MSG_FIL_RUNOUTS c=15
+//! | Crash X 000 Y 000| MSG_CRASH c=7
//! ----------------------
//! @endcode
//! @brief Show Last Print Failures Statistics with PAT9125
@@ -1763,8 +1762,8 @@ static void lcd_menu_fails_stats_print()
#ifndef PAT9125
lcd_printf_P(failStatsFmt,
_T(MSG_LAST_PRINT_FAILURES), ////c=20
- _T(MSG_POWER_FAILURES), power, ////c=14
- _T(MSG_FIL_RUNOUTS), filam, ////c=14
+ _T(MSG_POWER_FAILURES), power, ////c=15
+ _T(MSG_FIL_RUNOUTS), filam, ////c=15
_T(MSG_CRASH), crashX, crashY); ////c=7
#else
// On the MK3 include detailed PAT9125 statistics about soft failures
@@ -1773,7 +1772,7 @@ static void lcd_menu_fails_stats_print()
" %-7.7S H %-3d S %-3d\n"
" %-7.7S X %-3d Y %-3d"),
_T(MSG_LAST_PRINT_FAILURES), ////c=20
- _T(MSG_POWER_FAILURES), power, ////c=14
+ _T(MSG_POWER_FAILURES), power, ////c=15
_i("Runouts"), filam, fsensor_softfail, //c=7
_T(MSG_CRASH), crashX, crashY); ////c=7
#endif
@@ -1816,9 +1815,9 @@ static const char failStatsFmt[] PROGMEM = "%S\n" " %-16.16S%-3d\n" "%S\n" " %-1
//! @code{.unparsed}
//! |01234567890123456789|
//! |Last print failures | MSG_LAST_PRINT_FAILURES c=20
-//! | Fil. runouts 000| MSG_FIL_RUNOUTS c=14
+//! | Fil. runouts 000| MSG_FIL_RUNOUTS c=15
//! |Total failures | MSG_TOTAL_FAILURES c=20
-//! | Fil. runouts 000| MSG_FIL_RUNOUTS c=14
+//! | Fil. runouts 000| MSG_FIL_RUNOUTS c=15
//! ----------------------
//! @endcode
//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations.
@@ -1830,9 +1829,9 @@ static void lcd_menu_fails_stats()
lcd_home();
lcd_printf_P(failStatsFmt,
_T(MSG_LAST_PRINT_FAILURES), ////c=20
- _T(MSG_FIL_RUNOUTS), filamentLast, ////c=14
+ _T(MSG_FIL_RUNOUTS), filamentLast, ////c=15
_T(MSG_TOTAL_FAILURES), ////c=20
- _T(MSG_FIL_RUNOUTS), filamentTotal); ////c=14
+ _T(MSG_FIL_RUNOUTS), filamentTotal); ////c=15
menu_back_if_clicked();
}
@@ -3920,6 +3919,16 @@ static void lcd_print_state(uint8_t state)
}
}
+//! @brief Show sensor state
+//!
+//! @code{.unparsed}
+//! |01234567890123456789|
+//! |PINDA N/A FINDA N/A| MSG_PINDA c=6 MSG_FINDA c=6
+//! |Fil. sensor N/A| MSG_FSENSOR
+//! |Xd 000 Yd 000| MSG_XD
+//! |Int 000 Shut 000|
+//! ----------------------
+//! @endcode
static void lcd_show_sensors_state()
{
//0: N/A; 1: OFF; 2: ON
@@ -3932,21 +3941,56 @@ static void lcd_show_sensors_state()
{
finda_state = mmu_finda;
}
- if (ir_sensor_detected) {
- idler_state = !READ(IR_SENSOR_PIN);
- }
- lcd_puts_at_P(0, 0, _i("Sensor state"));
- lcd_puts_at_P(1, 1, _i("PINDA:"));
- lcd_set_cursor(LCD_WIDTH - 4, 1);
+ //lcd_puts_at_P(0, 0, _i("Sensor state"));
+ lcd_puts_at_P(0, 0, _i("PINDA"));
+ lcd_set_cursor(LCD_WIDTH - 14, 0);
lcd_print_state(pinda_state);
- lcd_puts_at_P(1, 2, _i("FINDA:"));
- lcd_set_cursor(LCD_WIDTH - 4, 2);
- lcd_print_state(finda_state);
+ if (mmu_enabled == true)
+ {
+ lcd_puts_at_P(10, 0, _i("FINDA"));
+ lcd_set_cursor(LCD_WIDTH - 3, 0);
+ lcd_print_state(finda_state);
+ }
- lcd_puts_at_P(1, 3, _i("IR:"));
- lcd_set_cursor(LCD_WIDTH - 4, 3);
- lcd_print_state(idler_state);
+ if (ir_sensor_detected) {
+ idler_state = !READ(IR_SENSOR_PIN);
+ lcd_puts_at_P(0, 1, _i("Fil. sensor"));
+ lcd_set_cursor(LCD_WIDTH - 3, 1);
+ lcd_print_state(idler_state);
+ }
+
+
+#ifdef PAT9125
+ // Display X and Y difference from Filament sensor
+ // Display Light intensity from Filament sensor
+ // Frame_Avg register represents the average brightness of all pixels within a frame (324 pixels). This
+ // value ranges from 0(darkest) to 255(brightest).
+ // Display LASER shutter time from Filament sensor
+ // Shutter register is an index of LASER shutter time. It is automatically controlled by the chip's internal
+ // auto-exposure algorithm. When the chip is tracking on a good reflection surface, the Shutter is small.
+ // When the chip is tracking on a poor reflection surface, the Shutter is large. Value ranges from 0 to 46.
+ if (mmu_enabled == false)
+ {
+ //if (!fsensor_enabled)
+ // lcd_puts_P(_N("Filament sensor\n" "is disabled."));
+ //else
+ //{
+ if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LcdCommands::Layer1Cal))
+ pat9125_update();
+ lcd_set_cursor(0, 2);
+ lcd_printf_P(_N(
+ "Xd: %3d "
+ "Yd: %3d\n" ////c=4 r=1
+ "Int: %3d " ////c=4 r=1
+ "Shut: %3d" ////c=4 r=1
+ ),
+ pat9125_x, pat9125_y,
+ pat9125_b, pat9125_s
+ );
+ //}
+ }
+#endif //PAT9125
}
void lcd_menu_show_sensors_state() // NOT static due to using inside "Marlin_main" module ("manage_inactivity()")
@@ -4326,7 +4370,7 @@ static void lcd_sort_type_set() {
default: sdSort = SD_SORT_TIME;
}
eeprom_update_byte((unsigned char *)EEPROM_SD_SORT, sdSort);
- presort_flag = true;
+ card.presort_flag = true;
}
#endif //SDCARD_SORT_ALPHA
@@ -6096,15 +6140,15 @@ uint8_t choose_menu_P(const char *header, const char *item, const char *last_ite
char reset_menu() {
const uint8_t items_no =
#ifdef SNMM
- 5;
+ 6;
#else
- 4;
+ 5;
#endif
static int8_t first = 0;
int8_t enc_dif = 0;
char cursor_pos = 0;
- const char *const item[items_no] PROGMEM = {PSTR("Language"), PSTR("Statistics"), PSTR("Shipping prep"), PSTR("All Data")
+ const char *const item[items_no] PROGMEM = {PSTR("Language"), PSTR("Statistics"), PSTR("Shipping prep"), PSTR("All Data"), PSTR("Service prep")
#ifdef SNMM
, PSTR("Bowden length")
#endif
@@ -6495,12 +6539,13 @@ void lcd_resume_print()
lcd_setstatuspgm(_T(MSG_FINISHING_MOVEMENTS));
st_synchronize();
- lcd_setstatuspgm(_T(MSG_RESUMING_PRINT)); ////MSG_RESUMING_PRINT c=20
+ custom_message_type = CustomMsg::Resuming;
isPrintPaused = false;
restore_print_from_ram_and_continue(default_retraction);
pause_time += (_millis() - start_pause_print); //accumulate time when print is paused for correct statistics calculation
refresh_cmd_timeout();
SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_RESUMED); //resume octoprint
+ custom_message_type = CustomMsg::Status;
}
static void change_sheet()
@@ -7189,8 +7234,8 @@ void lcd_sdcard_menu()
{
uint8_t sdSort = eeprom_read_byte((uint8_t*)EEPROM_SD_SORT);
- if (presort_flag == true) {
- presort_flag = false;
+ if (card.presort_flag == true) {
+ card.presort_flag = false;
card.presort();
}
if (lcd_draw_update == 0 && LCD_CLICKED == 0)
@@ -8403,7 +8448,7 @@ static int lcd_selftest_screen(TestScreen screen, int _progress, int _progress_s
if (screen == TestScreen::EndStops) lcd_puts_P(_i("Checking endstops"));////MSG_SELFTEST_CHECK_ENDSTOPS c=20
if (screen == TestScreen::AxisX) lcd_puts_P(_T(MSG_CHECKING_X));
if (screen == TestScreen::AxisY) lcd_puts_P(_T(MSG_CHECKING_Y));
- if (screen == TestScreen::AxisZ) lcd_puts_P(_i("Checking Z axis "));////MSG_SELFTEST_CHECK_Z c=20
+ if (screen == TestScreen::AxisZ) lcd_puts_P(_i("Checking Z axis"));////MSG_SELFTEST_CHECK_Z c=20
if (screen == TestScreen::Bed) lcd_puts_P(_T(MSG_SELFTEST_CHECK_BED));
if (screen == TestScreen::Hotend
|| screen == TestScreen::HotendOk) lcd_puts_P(_i("Checking hotend "));////MSG_SELFTEST_CHECK_HOTEND c=20
@@ -8487,7 +8532,7 @@ static void lcd_selftest_screen_step(int _row, int _col, int _state, const char
static bool check_file(const char* filename) {
if (farm_mode) return true;
- card.openFile((char*)filename, true);
+ card.openFileReadFilteredGcode(filename, true);
bool result = false;
const uint32_t filesize = card.getFileSize();
uint32_t startPos = 0;
@@ -8554,7 +8599,7 @@ static void menu_action_sdfile(const char* filename)
for (uint_least8_t i = 0; i < depth; i++) {
for (uint_least8_t j = 0; j < 8; j++) {
- eeprom_write_byte((uint8_t*)EEPROM_DIRS + j + 8 * i, dir_names[i][j]);
+ eeprom_write_byte((uint8_t*)EEPROM_DIRS + j + 8 * i, card.dir_names[i][j]);
}
}
@@ -8572,12 +8617,8 @@ static void menu_action_sdfile(const char* filename)
void menu_action_sddirectory(const char* filename)
{
- uint8_t depth = (uint8_t)card.getWorkDirDepth();
-
- strcpy(dir_names[depth], filename);
- MYSERIAL.println(dir_names[depth]);
- card.chdir(filename);
- lcd_encoder = 0;
+ card.chdir(filename, true);
+ lcd_encoder = 0;
}
/** LCD API **/
diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h
index 62aed6dff..ac8178cbc 100755
--- a/Firmware/ultralcd.h
+++ b/Firmware/ultralcd.h
@@ -114,12 +114,15 @@ extern int8_t FSensorStateMenu;
enum class CustomMsg : uint_least8_t
{
- Status, //!< status message from lcd_status_message variable
- MeshBedLeveling, //!< Mesh bed leveling in progress
- FilamentLoading, //!< Loading filament in progress
- PidCal, //!< PID tuning in progress
- TempCal, //!< PINDA temperature calibration
- TempCompPreheat, //!< Temperature compensation preheat
+ Status, //!< status message from lcd_status_message variable
+ MeshBedLeveling, //!< Mesh bed leveling in progress
+ FilamentLoading, //!< Loading filament in progress
+ PidCal, //!< PID tuning in progress
+ TempCal, //!< PINDA temperature calibration
+ TempCompPreheat, //!< Temperature compensation preheat
+ M0Wait, //!< M0/M1 Wait command working even from SD
+ MsgUpdate, //!< Short message even while printing from SD
+ Resuming, //!< Resuming message
};
extern CustomMsg custom_message_type;
diff --git a/lang/lang_en.txt b/lang/lang_en.txt
index 8c0e6eb9d..79848fe87 100644
--- a/lang/lang_en.txt
+++ b/lang/lang_en.txt
@@ -253,8 +253,8 @@
#MSG_FSENSOR
"Fil. sensor"
-#MSG_FIL_RUNOUTS c=14
-"Fil. runouts "
+#MSG_FIL_RUNOUTS c=15
+"Fil. runouts"
#MSG_FILAMENT_CLEAN c=20 r=2
"Filament extruding & with correct color?"
@@ -448,13 +448,13 @@
#
"Measured skew"
-#MSG_MMU_FAILS c=14
+#MSG_MMU_FAILS c=15
"MMU fails"
#
"MMU load failed "
-#MSG_MMU_LOAD_FAILS c=14
+#MSG_MMU_LOAD_FAILS c=15
"MMU load fails"
#MSG_MMU_OK_RESUMING c=20 r=4
@@ -625,7 +625,7 @@
#MSG_FS_PAUSE c=5
"Pause"
-#MSG_POWER_FAILURES c=14
+#MSG_POWER_FAILURES c=15
"Power failures"
#MSG_PRINT_ABORTED c=20
@@ -1048,7 +1048,7 @@
#MSG_GCODE_DIFF_PRINTER_CONTINUE c=20 r=5
"G-code sliced for a different printer type. Continue?"
-#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=6
+#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=7
"G-code sliced for a different printer type. Please re-slice the model again. Print cancelled."
#
diff --git a/lang/lang_en_cz.txt b/lang/lang_en_cz.txt
index 2c0bc664b..ea2dbc83d 100644
--- a/lang/lang_en_cz.txt
+++ b/lang/lang_en_cz.txt
@@ -338,8 +338,8 @@
"Fil. sensor"
"Fil. senzor"
-#MSG_FIL_RUNOUTS c=14
-"Fil. runouts "
+#MSG_FIL_RUNOUTS c=15
+"Fil. runouts"
"Vypadky filam."
#MSG_FILAMENT_CLEAN c=20 r=2
@@ -598,7 +598,7 @@
"Measured skew"
"Merene zkoseni"
-#MSG_MMU_FAILS c=14
+#MSG_MMU_FAILS c=15
"MMU fails"
"Selhani MMU"
@@ -606,7 +606,7 @@
"MMU load failed "
"Zavedeni MMU selhalo"
-#MSG_MMU_LOAD_FAILS c=14
+#MSG_MMU_LOAD_FAILS c=15
"MMU load fails"
"MMU selhani zavadeni"
@@ -834,7 +834,7 @@
"Pause"
"\x00"
-#MSG_POWER_FAILURES c=14
+#MSG_POWER_FAILURES c=15
"Power failures"
"Vypadky proudu"
@@ -1398,7 +1398,7 @@
"G-code sliced for a different printer type. Continue?"
"G-code je pripraven pro jiny typ tiskarny. Pokracovat?"
-#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=6
+#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=7
"G-code sliced for a different printer type. Please re-slice the model again. Print cancelled."
"G-code je pripraven pro jiny typ tiskarny. Prosim preslicujte model znovu. Tisk zrusen."
diff --git a/lang/lang_en_de.txt b/lang/lang_en_de.txt
index e6fd5bccc..ffc35678e 100644
--- a/lang/lang_en_de.txt
+++ b/lang/lang_en_de.txt
@@ -338,9 +338,9 @@
"Fil. sensor"
"Fil. Sensor"
-#MSG_FIL_RUNOUTS c=14
-"Fil. runouts "
-"Fil. Maengel "
+#MSG_FIL_RUNOUTS c=15
+"Fil. runouts"
+"Fil. Maengel"
#MSG_FILAMENT_CLEAN c=20 r=2
"Filament extruding & with correct color?"
@@ -598,7 +598,7 @@
"Measured skew"
"Schraeglauf"
-#MSG_MMU_FAILS c=14
+#MSG_MMU_FAILS c=15
"MMU fails"
"MMU Fehler"
@@ -606,7 +606,7 @@
"MMU load failed "
"MMU Ladefehler"
-#MSG_MMU_LOAD_FAILS c=14
+#MSG_MMU_LOAD_FAILS c=15
"MMU load fails"
"MMU Ladefehler"
@@ -834,7 +834,7 @@
"Pause"
"\x00"
-#MSG_POWER_FAILURES c=14
+#MSG_POWER_FAILURES c=15
"Power failures"
"Netzfehler"
@@ -1398,7 +1398,7 @@
"G-code sliced for a different printer type. Continue?"
"G-Code ist fuer einen anderen Drucker geslict. Fortfahren?"
-#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=6
+#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=7
"G-code sliced for a different printer type. Please re-slice the model again. Print cancelled."
"G-Code ist fuer einen anderen Drucker geslict. Bitte slicen Sie das Modell erneut. Druck abgebrochen."
diff --git a/lang/lang_en_es.txt b/lang/lang_en_es.txt
index 4e622ebb9..b5bca7656 100644
--- a/lang/lang_en_es.txt
+++ b/lang/lang_en_es.txt
@@ -338,9 +338,9 @@
"Fil. sensor"
"Sensor Fil."
-#MSG_FIL_RUNOUTS c=14
-"Fil. runouts "
-"Fil. acabado "
+#MSG_FIL_RUNOUTS c=15
+"Fil. runouts"
+"Fil. acabado"
#MSG_FILAMENT_CLEAN c=20 r=2
"Filament extruding & with correct color?"
@@ -598,7 +598,7 @@
"Measured skew"
"Desviacion med:"
-#MSG_MMU_FAILS c=14
+#MSG_MMU_FAILS c=15
"MMU fails"
"Fallos MMU"
@@ -606,7 +606,7 @@
"MMU load failed "
"Carga MMU fallida"
-#MSG_MMU_LOAD_FAILS c=14
+#MSG_MMU_LOAD_FAILS c=15
"MMU load fails"
"Carga MMU falla"
@@ -834,9 +834,9 @@
"Pause"
"Pausa"
-#MSG_POWER_FAILURES c=14
+#MSG_POWER_FAILURES c=15
"Power failures"
-"Cortes de energia"
+"Fallas energia"
#MSG_PRINT_ABORTED c=20
"Print aborted"
@@ -1398,7 +1398,7 @@
"G-code sliced for a different printer type. Continue?"
"Codigo G laminado para un tipo de impresora diferente. ?Continuar?"
-#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=6
+#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=7
"G-code sliced for a different printer type. Please re-slice the model again. Print cancelled."
"Codigo G laminado para una impresora diferente. Por favor relamina el modelo de nuevo. Impresion cancelada."
diff --git a/lang/lang_en_fr.txt b/lang/lang_en_fr.txt
index edf2bb8b4..7bd47294e 100644
--- a/lang/lang_en_fr.txt
+++ b/lang/lang_en_fr.txt
@@ -338,9 +338,9 @@
"Fil. sensor"
"Capteur Fil."
-#MSG_FIL_RUNOUTS c=14
-"Fil. runouts "
-"Fins filament "
+#MSG_FIL_RUNOUTS c=15
+"Fil. runouts"
+"Fins filament"
#MSG_FILAMENT_CLEAN c=20 r=2
"Filament extruding & with correct color?"
@@ -598,7 +598,7 @@
"Measured skew"
"Deviat.mesuree"
-#MSG_MMU_FAILS c=14
+#MSG_MMU_FAILS c=15
"MMU fails"
"Echecs MMU"
@@ -606,7 +606,7 @@
"MMU load failed "
"Echec chargement MMU"
-#MSG_MMU_LOAD_FAILS c=14
+#MSG_MMU_LOAD_FAILS c=15
"MMU load fails"
"Echecs charg. MMU"
@@ -834,7 +834,7 @@
"Pause"
"\x00"
-#MSG_POWER_FAILURES c=14
+#MSG_POWER_FAILURES c=15
"Power failures"
"Coup.de courant"
@@ -1398,7 +1398,7 @@
"G-code sliced for a different printer type. Continue?"
"Le G-code a ete prepare pour une autre version de l'imprimante. Continuer?"
-#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=6
+#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=7
"G-code sliced for a different printer type. Please re-slice the model again. Print cancelled."
"Le G-code a ete prepare pour une autre version de l'imprimante. Veuillez decouper le modele a nouveau. L'impression a ete annulee."
diff --git a/lang/lang_en_it.txt b/lang/lang_en_it.txt
index 043d1141b..d4cac7620 100644
--- a/lang/lang_en_it.txt
+++ b/lang/lang_en_it.txt
@@ -338,9 +338,9 @@
"Fil. sensor"
"Sensore fil."
-#MSG_FIL_RUNOUTS c=14
-"Fil. runouts "
-"Fil. esauriti "
+#MSG_FIL_RUNOUTS c=15
+"Fil. runouts"
+"Fil. esauriti"
#MSG_FILAMENT_CLEAN c=20 r=2
"Filament extruding & with correct color?"
@@ -598,7 +598,7 @@
"Measured skew"
"Deviazione mis"
-#MSG_MMU_FAILS c=14
+#MSG_MMU_FAILS c=15
"MMU fails"
"Fallimenti MMU"
@@ -606,7 +606,7 @@
"MMU load failed "
"Caricamento MMU fallito"
-#MSG_MMU_LOAD_FAILS c=14
+#MSG_MMU_LOAD_FAILS c=15
"MMU load fails"
"Caricamenti MMU falliti"
@@ -834,7 +834,7 @@
"Pause"
"Pausa"
-#MSG_POWER_FAILURES c=14
+#MSG_POWER_FAILURES c=15
"Power failures"
"Mancanza corrente"
@@ -1398,7 +1398,7 @@
"G-code sliced for a different printer type. Continue?"
"G-code processato per una stampante diversa. Continuare?"
-#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=6
+#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=7
"G-code sliced for a different printer type. Please re-slice the model again. Print cancelled."
"G-code processato per una stampante diversa. Per favore esegui nuovamente lo slice del modello. Stampa annullata."
diff --git a/lang/lang_en_pl.txt b/lang/lang_en_pl.txt
index 4e6be18e0..bbdf0aca1 100644
--- a/lang/lang_en_pl.txt
+++ b/lang/lang_en_pl.txt
@@ -338,8 +338,8 @@
"Fil. sensor"
"Czuj. filam."
-#MSG_FIL_RUNOUTS c=14
-"Fil. runouts "
+#MSG_FIL_RUNOUTS c=15
+"Fil. runouts"
"Konc.filamentu"
#MSG_FILAMENT_CLEAN c=20 r=2
@@ -598,7 +598,7 @@
"Measured skew"
"Zmierzony skos"
-#MSG_MMU_FAILS c=14
+#MSG_MMU_FAILS c=15
"MMU fails"
"Bledy MMU"
@@ -606,7 +606,7 @@
"MMU load failed "
"Blad ladowania MMU"
-#MSG_MMU_LOAD_FAILS c=14
+#MSG_MMU_LOAD_FAILS c=15
"MMU load fails"
"Bledy ladow. MMU"
@@ -834,7 +834,7 @@
"Pause"
"Pauza"
-#MSG_POWER_FAILURES c=14
+#MSG_POWER_FAILURES c=15
"Power failures"
"Zaniki zasilania"
@@ -1398,7 +1398,7 @@
"G-code sliced for a different printer type. Continue?"
"G-code pociety dla innej drukarki. Kontynuowac?"
-#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=6
+#MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=7
"G-code sliced for a different printer type. Please re-slice the model again. Print cancelled."
"G-code pociety dla drukarki innego typu. Potnij model ponownie. Druk anulowany."