diff --git a/Firmware/Configuration.h b/Firmware/Configuration.h index 3c89fb22..cbab1e1e 100644 --- a/Firmware/Configuration.h +++ b/Firmware/Configuration.h @@ -12,6 +12,7 @@ // The total size of the EEPROM is // 4096 for the Atmega2560 +#define EEPROM_TOP 4096 #define EEPROM_SILENT 4095 #define EEPROM_LANG 4094 #define EEPROM_BABYSTEP_X 4092 diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index fc8af6da..c1ba03a0 100644 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -222,6 +222,8 @@ void enquecommand_front(const char *cmd, bool from_progmem = false); #define enquecommand_P(cmd) enquecommand(cmd, true) #define enquecommand_front_P(cmd) enquecommand_front(cmd, true) void repeatcommand_front(); +// Remove all lines from the command queue. +void cmdqueue_reset(); void prepare_arc_move(char isclockwise); void clamp_to_software_endstops(float target[3]); diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 801c673d..b219cfe7 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -497,7 +497,7 @@ void serial_echopair_P(const char *s_P, unsigned long v) // Pop the currently processed command from the queue. // It is expected, that there is at least one command in the queue. -void cmdqueue_pop_front() +bool cmdqueue_pop_front() { if (buflen > 0) { #ifdef CMDBUFFER_DEBUG @@ -547,7 +547,14 @@ void cmdqueue_pop_front() SERIAL_ECHOLNPGM(""); #endif /* CMDBUFFER_DEBUG */ } + return true; } + return false; +} + +void cmdqueue_reset() +{ + while (cmdqueue_pop_front()) ; } // How long a string could be pushed to the front of the command queue? @@ -1015,6 +1022,16 @@ void setup() farm_no = 0; } + if (eeprom_read_dword((uint32_t*)(EEPROM_TOP-4)) == 0x0ffffffff && + eeprom_read_dword((uint32_t*)(EEPROM_TOP-8)) == 0x0ffffffff && + eeprom_read_dword((uint32_t*)(EEPROM_TOP-12)) == 0x0ffffffff) { + // Maiden startup. The firmware has been loaded and first started on a virgin RAMBo board, + // where all the EEPROM entries are set to 0x0ff. + // Once a firmware boots up, it forces at least a language selection, which changes + // EEPROM_LANG to number lower than 0x0ff. + // 1) Set a high power mode. + eeprom_write_byte((uint8_t*)EEPROM_SILENT, 0); + } // In the future, somewhere here would one compare the current firmware version against the firmware version stored in the EEPROM. // If they differ, an update procedure may need to be performed. At the end of this block, the current firmware version @@ -1028,7 +1045,7 @@ void setup() // Get the selected laugnage index before display update. lang_selected = eeprom_read_byte((uint8_t*)EEPROM_LANG); if (lang_selected >= LANG_NUM) - lang_selected = 1; + lang_selected = LANG_ID_DEFAULT; // Czech language // Show the message. lcd_show_fullscreen_message_and_wait_P(MSG_BABYSTEP_Z_NOT_SET); lcd_update_enable(true); @@ -1272,7 +1289,7 @@ void get_command() if (farm_mode) { prusa_statistics(6); - lcd_commands_type = 4; + lcd_commands_type = LCD_COMMAND_FARM_MODE_CONFIRM; } } diff --git a/Firmware/langtool.pl b/Firmware/langtool.pl index 41e1c297..5d9983c9 100644 --- a/Firmware/langtool.pl +++ b/Firmware/langtool.pl @@ -130,8 +130,29 @@ print $fh < ALWAYS TRY TO COMPILE MARLIN WITH/WITHOUT "ULTIPANEL" / "ULTRALCD" / "SDSUPPORT" #define IN "Configuration.h" -// ==> ALSO TRY ALL AVAILABLE LANGUAGE OPTIONS - -// Languages -// en English -// pl Polish -// fr French -// de German -// es Spanish -// ru Russian -// it Italian -// pt Portuguese -// fi Finnish -// an Aragonese -// nl Dutch -// ca Catalan -// eu Basque-Euskera - - - #define PROTOCOL_VERSION "1.0" #if MB(ULTIMAKER)|| MB(ULTIMAKER_OLD)|| MB(ULTIMAIN_2) @@ -66,10 +40,6 @@ #define STRINGIFY(n) STRINGIFY_(n) -// Common LCD messages - - /* nothing here yet */ - // Common serial messages #define MSG_MARLIN "Marlin" @@ -77,9 +47,6 @@ // LCD Menu Messages - -//#include LANGUAGE_INCLUDE - #include "language_all.h" #endif //__LANGUAGE_H diff --git a/Firmware/language_all.h b/Firmware/language_all.h index d968dc40..6655fad5 100644 --- a/Firmware/language_all.h +++ b/Firmware/language_all.h @@ -1,8 +1,24 @@ #ifndef LANGUAGE_ALL_H #define LANGUAGE_ALL_H -#define LANG_NUM (5) +// Language indices into their particular symbol tables. +#define LANG_ID_EN 0 +#define LANG_ID_CZ 1 +#define LANG_ID_IT 2 +#define LANG_ID_ES 3 +#define LANG_ID_PL 4 +// Language is not defined and it shall be selected from the menu. +#define LANG_ID_FORCE_SELECTION 254 +// Language is not defined on a virgin RAMBo board. +#define LANG_ID_UNDEFINED 255 +// Default language ID, if no language is selected. +#define LANG_ID_DEFAULT LANG_ID_CZ + +// Number of languages available in the language table. +#define LANG_NUM 5 + +// Currectly active language selection. extern unsigned char lang_selected; #define LANG_TABLE_SELECT_EXPLICIT(TABLE, LANG) ((const char*)(pgm_read_ptr(TABLE + (LANG)))) diff --git a/Firmware/planner.cpp b/Firmware/planner.cpp index 3d574017..62855f18 100644 --- a/Firmware/planner.cpp +++ b/Firmware/planner.cpp @@ -459,6 +459,54 @@ void check_axes_activity() #endif } +bool waiting_inside_plan_buffer_line_print_aborted = false; +/* +void planner_abort_soft() +{ + // Empty the queue. + while (blocks_queued()) plan_discard_current_block(); + // Relay to planner wait routine, that the current line shall be canceled. + waiting_inside_plan_buffer_line_print_aborted = true; + //current_position[i] +} +*/ + +void planner_abort_hard() +{ + // Abort the stepper routine and flush the planner queue. + quickStop(); + + // Now the front-end (the Marlin_main.cpp with its current_position) is out of sync. + // First update the planner's current position in the physical motor steps. + position[X_AXIS] = st_get_position(X_AXIS); + position[Y_AXIS] = st_get_position(Y_AXIS); + position[Z_AXIS] = st_get_position(Z_AXIS); + position[E_AXIS] = st_get_position(E_AXIS); + + // Second update the current position of the front end. + current_position[X_AXIS] = st_get_position_mm(X_AXIS); + current_position[Y_AXIS] = st_get_position_mm(Y_AXIS); + current_position[Z_AXIS] = st_get_position_mm(Z_AXIS); + current_position[E_AXIS] = st_get_position_mm(E_AXIS); + // Apply the mesh bed leveling correction to the Z axis. +#ifdef MESH_BED_LEVELING + if (mbl.active) + current_position[Z_AXIS] -= mbl.get_z(current_position[X_AXIS], current_position[Y_AXIS]); +#endif + // Apply inverse world correction matrix. + machine2world(current_position[X_AXIS], current_position[Y_AXIS]); + memcpy(destination, current_position, sizeof(destination)); + + // Resets planner junction speeds. Assumes start from rest. + previous_nominal_speed = 0.0; + previous_speed[0] = 0.0; + previous_speed[1] = 0.0; + previous_speed[2] = 0.0; + previous_speed[3] = 0.0; + + // Relay to planner wait routine, that the current line shall be canceled. + waiting_inside_plan_buffer_line_print_aborted = true; +} float junction_deviation = 0.1; // Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in @@ -471,12 +519,18 @@ void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate // If the buffer is full: good! That means we are well ahead of the robot. // Rest here until there is room in the buffer. - while(block_buffer_tail == next_buffer_head) - { - manage_heater(); - // Vojtech: Don't disable motors inside the planner! - manage_inactivity(false); - lcd_update(); + if (block_buffer_tail == next_buffer_head) { + waiting_inside_plan_buffer_line_print_aborted = false; + do { + manage_heater(); + // Vojtech: Don't disable motors inside the planner! + manage_inactivity(false); + lcd_update(); + } while (block_buffer_tail == next_buffer_head); + if (waiting_inside_plan_buffer_line_print_aborted) + // Inside the lcd_update() routine the print has been aborted. + // Cancel the print, do not plan the current line this routine is waiting on. + return; } #ifdef ENABLE_AUTO_BED_LEVELING diff --git a/Firmware/planner.h b/Firmware/planner.h index 9a8f7b1f..58619bea 100644 --- a/Firmware/planner.h +++ b/Firmware/planner.h @@ -185,6 +185,11 @@ FORCE_INLINE bool planner_queue_full() { return block_buffer_tail == next_block_index; } +// Abort the stepper routine, clean up the block queue, +// wait for the steppers to stop, +// update planner's current position and the current_position of the front end. +extern void planner_abort_hard(); + #ifdef PREVENT_DANGEROUS_EXTRUDE void set_extrude_min_temp(float temp); #endif diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 13b6189d..2a308f02 100644 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -29,6 +29,11 @@ struct EditMenuParentState //prevMenu and prevEncoderPosition are used to store the previous menu location when editing settings. menuFunc_t prevMenu; uint16_t prevEncoderPosition; + //Variables used when editing values. + const char* editLabel; + void* editValue; + int32_t minEditValue, maxEditValue; + // menuFunc_t callbackFunc; }; union MenuData @@ -52,7 +57,7 @@ union MenuData struct AdjustBed { - // 6+13=19B + // 6+13+16=35B // editMenuParentState is used when an edit menu is entered, so it knows // the return menu and encoder state. struct EditMenuParentState editMenuParentState; @@ -88,7 +93,7 @@ int8_t SDscrool = 0; int8_t SilentModeMenu = 0; -int lcd_commands_type=0; +int lcd_commands_type=LCD_COMMAND_IDLE; int lcd_commands_step=0; bool isPrintPaused = false; bool farm_mode = false; @@ -120,8 +125,8 @@ unsigned char firstrun = 1; /** forward declarations **/ -void copy_and_scalePID_i(); -void copy_and_scalePID_d(); +// void copy_and_scalePID_i(); +// void copy_and_scalePID_d(); /* Different menus */ static void lcd_status_screen(); @@ -268,14 +273,10 @@ bool ignore_click = false; bool wait_for_unclick; uint8_t lcdDrawUpdate = 2; /* Set to none-zero when the LCD needs to draw, decreased after every draw. Set to 2 in LCD routines so the LCD gets at least 1 full redraw (first redraw is partial) */ -//Variables used when editing values. -const char* editLabel; -void* editValue; -int32_t minEditValue, maxEditValue; -menuFunc_t callbackFunc; - // place-holders for Ki and Kd edits -float raw_Ki, raw_Kd; +#ifdef PIDTEMP +// float raw_Ki, raw_Kd; +#endif static void lcd_goto_menu(menuFunc_t menu, const uint32_t encoder = 0, const bool feedback = true, bool reset_menu_state = true) { if (currentMenu != menu) { @@ -296,26 +297,30 @@ static void lcd_goto_menu(menuFunc_t menu, const uint32_t encoder = 0, const boo } /* Main status screen. It's up to the implementation specific part to show what is needed. As this is very display dependent */ -/* -extern char langbuffer[]; -void lcd_printPGM(const char *s1) { - strncpy_P(langbuffer,s1,LCD_WIDTH); - lcd.print(langbuffer); -} -*/ -unsigned char langsel; + +// Language selection dialog not active. +#define LANGSEL_OFF 0 +// Language selection dialog modal, entered from the info screen. This is the case on firmware boot up, +// if the language index stored in the EEPROM is not valid. +#define LANGSEL_MODAL 1 +// Language selection dialog entered from the Setup menu. +#define LANGSEL_ACTIVE 2 +// Language selection dialog status +unsigned char langsel = LANGSEL_OFF; void set_language_from_EEPROM() { unsigned char eep = eeprom_read_byte((unsigned char*)EEPROM_LANG); if (eep < LANG_NUM) { lang_selected = eep; - langsel = 0; + // Language is valid, no need to enter the language selection screen. + langsel = LANGSEL_OFF; } else { - lang_selected = 1; - langsel = 1; + lang_selected = LANG_ID_DEFAULT; + // Invalid language, enter the language selection screen in a modal mode. + langsel = LANGSEL_MODAL; } } @@ -337,6 +342,7 @@ static void lcd_status_screen() if (langsel) { //strncpy_P(lcd_status_message, PSTR(">>>>>>>>>>>> PRESS v"), LCD_WIDTH); + // Entering the language selection screen in a modal mode. lcd_mylang(); } } @@ -404,7 +410,7 @@ static void lcd_status_screen() lcd_status_update_delay = 10; /* redraw the main screen every second. This is easier then trying keep track of all things that change on the screen */ - if (lcd_commands_type != 0) + if (lcd_commands_type != LCD_COMMAND_IDLE) { lcd_commands(); } @@ -485,7 +491,7 @@ static void lcd_status_screen() void lcd_commands() { - if (lcd_commands_type == 1) //// load filament sequence + if (lcd_commands_type == LCD_COMMAND_LOAD_FILAMENT) //// load filament sequence { if (lcd_commands_step == 0) { lcd_commands_step = 5; custom_message = true; } if (lcd_commands_step == 1 && !blocks_queued()) @@ -522,14 +528,9 @@ void lcd_commands() custom_message_type = 2; lcd_commands_step = 4; } - - - - - } - if (lcd_commands_type == 2) /// stop print + if (lcd_commands_type == LCD_COMMAND_STOP_PRINT) /// stop print { if (lcd_commands_step == 0) { lcd_commands_step = 6; custom_message = true; } @@ -554,13 +555,16 @@ void lcd_commands() } if (lcd_commands_step == 3 && !blocks_queued()) { + // M84: Disable steppers. enquecommand_P(PSTR("M84")); autotempShutdown(); lcd_commands_step = 2; } if (lcd_commands_step == 4 && !blocks_queued()) { + // G90: Absolute positioning. enquecommand_P(PSTR("G90")); + // M83: Set extruder to relative mode. enquecommand_P(PSTR("M83")); #ifdef X_CANCEL_POS enquecommand_P(PSTR("G1 X" STRINGIFY(X_CANCEL_POS) " Y" STRINGIFY(Y_CANCEL_POS) " E0 F7000")); @@ -573,7 +577,9 @@ void lcd_commands() if (lcd_commands_step == 5 && !blocks_queued()) { lcd_setstatuspgm(MSG_PRINT_ABORTED); + // G91: Set to relative positioning. enquecommand_P(PSTR("G91")); + // Lift up. enquecommand_P(PSTR("G1 Z15 F1500")); lcd_commands_step = 4; } @@ -596,7 +602,7 @@ void lcd_commands() lcd_commands_type = 0; } - if (lcd_commands_type == 4) /// farm mode confirm + if (lcd_commands_type == LCD_COMMAND_FARM_MODE_CONFIRM) /// farm mode confirm { if (lcd_commands_step == 0) { lcd_commands_step = 6; custom_message = true; } @@ -1016,7 +1022,7 @@ void lcd_LoadFilament() if (degHotend0() > EXTRUDE_MINTEMP) { custom_message = true; - lcd_commands_type = 1; + lcd_commands_type = LCD_COMMAND_LOAD_FILAMENT; SERIAL_ECHOLN("Loading filament"); // commands() will handle the rest } @@ -2001,33 +2007,35 @@ void EEPROM_read(int pos, uint8_t* value, uint8_t size) static void lcd_silent_mode_set() { SilentModeMenu = !SilentModeMenu; - EEPROM_save(EEPROM_SILENT, (uint8_t*)&SilentModeMenu, sizeof(SilentModeMenu)); + eeprom_update_byte((unsigned char *)EEPROM_SILENT, SilentModeMenu); digipot_init(); lcd_goto_menu(lcd_settings_menu, 7); } static void lcd_set_lang(unsigned char lang) { lang_selected = lang; firstrun = 1; - eeprom_write_byte((unsigned char *)EEPROM_LANG, lang);/*langsel=0;*/if (langsel == 1)langsel = 2; + eeprom_update_byte((unsigned char *)EEPROM_LANG, lang); + /*langsel=0;*/ + if (langsel == LANGSEL_MODAL) + // From modal mode to an active mode? This forces the menu to return to the setup menu. + langsel = LANGSEL_ACTIVE; } void lcd_force_language_selection() { - eeprom_write_byte((unsigned char *)EEPROM_LANG, 255); + eeprom_update_byte((unsigned char *)EEPROM_LANG, LANGUAGE_ID_FORCE_SELECTION); } static void lcd_language_menu() { START_MENU(); - if (!langsel) { + if (langsel == LANGSEL_OFF) { MENU_ITEM(back, MSG_SETTINGS, lcd_settings_menu); - } - if (langsel == 2) { + } else if (langsel == LANGSEL_ACTIVE) { MENU_ITEM(back, MSG_WATCH, lcd_status_screen); } for (int i=0;i maxEditValue) encoderPosition = maxEditValue; \ + if ((int32_t)encoderPosition > menuData.editMenuParentState.maxEditValue) encoderPosition = menuData.editMenuParentState.maxEditValue; \ if (lcdDrawUpdate) \ - lcd_implementation_drawedit(editLabel, _strFunc(((_type)((int32_t)encoderPosition + minEditValue)) / scale)); \ + lcd_implementation_drawedit(menuData.editMenuParentState.editLabel, _strFunc(((_type)((int32_t)encoderPosition + menuData.editMenuParentState.minEditValue)) / scale)); \ if (LCD_CLICKED) \ { \ - *((_type*)editValue) = ((_type)((int32_t)encoderPosition + minEditValue)) / scale; \ + *((_type*)menuData.editMenuParentState.editValue) = ((_type)((int32_t)encoderPosition + menuData.editMenuParentState.minEditValue)) / scale; \ lcd_goto_menu(menuData.editMenuParentState.prevMenu, menuData.editMenuParentState.prevEncoderPosition, true, false); \ } \ } \ - void menu_edit_callback_ ## _name () { \ - menu_edit_ ## _name (); \ - if (LCD_CLICKED) (*callbackFunc)(); \ - } \ static void menu_action_setting_edit_ ## _name (const char* pstr, _type* ptr, _type minValue, _type maxValue) \ { \ menuData.editMenuParentState.prevMenu = currentMenu; \ menuData.editMenuParentState.prevEncoderPosition = encoderPosition; \ \ lcdDrawUpdate = 2; \ - lcd_goto_menu(menu_edit_ ## _name, (*ptr) * scale - minEditValue, true, false); \ + menuData.editMenuParentState.editLabel = pstr; \ + menuData.editMenuParentState.editValue = ptr; \ + menuData.editMenuParentState.minEditValue = minValue * scale; \ + menuData.editMenuParentState.maxEditValue = maxValue * scale - menuData.editMenuParentState.minEditValue; \ + lcd_goto_menu(menu_edit_ ## _name, (*ptr) * scale - menuData.editMenuParentState.minEditValue, true, false); \ \ - editLabel = pstr; \ - editValue = ptr; \ - minEditValue = minValue * scale; \ - maxEditValue = maxValue * scale - minEditValue; \ }\ /* + void menu_edit_callback_ ## _name () { \ + menu_edit_ ## _name (); \ + if (LCD_CLICKED) (*callbackFunc)(); \ + } \ static void menu_action_setting_edit_callback_ ## _name (const char* pstr, _type* ptr, _type minValue, _type maxValue, menuFunc_t callback) \ { \ menuData.editMenuParentState.prevMenu = currentMenu; \ menuData.editMenuParentState.prevEncoderPosition = encoderPosition; \ \ lcdDrawUpdate = 2; \ - lcd_goto_menu(menu_edit_callback_ ## _name, (*ptr) * scale - minEditValue, true, false); \ + lcd_goto_menu(menu_edit_callback_ ## _name, (*ptr) * scale - menuData.editMenuParentState.minEditValue, true, false); \ \ - editLabel = pstr; \ - editValue = ptr; \ - minEditValue = minValue * scale; \ - maxEditValue = maxValue * scale - minEditValue; \ + menuData.editMenuParentState.editLabel = pstr; \ + menuData.editMenuParentState.editValue = ptr; \ + menuData.editMenuParentState.minEditValue = minValue * scale; \ + menuData.editMenuParentState.maxEditValue = maxValue * scale - menuData.editMenuParentState.minEditValue; \ callbackFunc = callback;\ } */ + menu_edit_type(int, int3, itostr3, 1) menu_edit_type(float, float3, ftostr3, 1) menu_edit_type(float, float32, ftostr32, 100) @@ -3806,6 +3812,7 @@ char *ftostr52(const float &x) return conv; } +/* // Callback for after editing PID i value // grab the PID i value out of the temp variable; scale it; then update the PID driver void copy_and_scalePID_i() @@ -3825,5 +3832,6 @@ void copy_and_scalePID_d() updatePID(); #endif } +*/ #endif //ULTRA_LCD \ No newline at end of file diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index d408cdf1..2b06399a 100644 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -78,6 +78,14 @@ #else FORCE_INLINE void lcd_buttons_update() {} #endif + + + // To be used in lcd_commands_type. + #define LCD_COMMAND_IDLE 0 + #define LCD_COMMAND_LOAD_FILAMENT 1 + #define LCD_COMMAND_STOP_PRINT 2 + #define LCD_COMMAND_FARM_MODE_CONFIRM 4 + extern int lcd_commands_type; extern bool farm_mode;