diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index f40c7e512..77af6d5f4 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1,4 +1,7 @@ //! @file +//! @date Aug 28, 2019 +//! @author mkbel +//! @brief LCD #include "temperature.h" #include "ultralcd.h" @@ -857,18 +860,23 @@ void lcdui_print_status_line(void) lcd_print(' '); } +//! @brief Show Status Screen +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! |N 000/000D Z000.0 | +//! |B 000/000D F100% | +//! |USB100% T0 t--:-- | +//! |Status line.........| +//! ---------------------- +//! N - nozzle temp symbol LCD_STR_THERMOMETER +//! D - Degree sysmbol LCD_STR_DEGREE +//! B - bed temp symbol LCD_STR_BEDTEMP +//! F - feedrate symbol LCD_STR_FEEDRATE +//! t - clock symbol LCD_STR_THERMOMETER +//! @endcode void lcdui_print_status_screen(void) { -//|01234567890123456789| -//|N 000/000D Z000.0 | -//|B 000/000D F100% | -//|USB100% T0 t--:-- | -//|Status line.........| -//---------------------- -//N - nozzle temp symbol LCD_STR_THERMOMETER -//B - bed temp symbol LCD_STR_BEDTEMP -//F - feedrate symbol LCD_STR_FEEDRATE -//t - clock symbol LCD_STR_THERMOMETER lcd_set_cursor(0, 0); //line 0 @@ -1692,22 +1700,27 @@ static void pgmtext_with_colon(const char *ipgmLabel, char *dst, uint8_t dstSize dst[dstSize-1] = '\0'; // terminate the string properly } +//! @brief Show Extruder Info +//! +//! @code{.unparsed} +//! |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. void lcd_menu_extruder_info() // NOT static due to using inside "Marlin_main" module ("manage_inactivity()") { -//|01234567890123456789| -//|Nozzle FAN: RPM| -//|Print FAN: RPM| -//|Fil. Xd: Yd: | -//|Int: Shut: | -//---------------------- // Display Nozzle fan RPM lcd_timeoutToStatus.stop(); //infinite timeout lcd_home(); static const size_t maxChars = 12; char nozzle[maxChars], print[maxChars]; - pgmtext_with_colon(_i("Nozzle FAN"), nozzle, maxChars); - pgmtext_with_colon(_i("Print FAN"), 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 @@ -1728,8 +1741,9 @@ void lcd_menu_extruder_info() // NOT static due to using ins 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" - "Int: %3d Shut: %3d" + "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 @@ -1741,125 +1755,183 @@ void lcd_menu_extruder_info() // NOT static due to using ins menu_back_if_clicked(); } +//! @brief Show Fails Statistics MMU +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! | Main | c=18 r=1 +//! | Last print | c=18 r=1 +//! | Total | c=18 r=1 +//! | | +//! ---------------------- +//! @endcode static void lcd_menu_fails_stats_mmu() { MENU_BEGIN(); MENU_ITEM_BACK_P(_T(MSG_MAIN)); - MENU_ITEM_SUBMENU_P(_i("Last print"), lcd_menu_fails_stats_mmu_print); - MENU_ITEM_SUBMENU_P(_i("Total"), lcd_menu_fails_stats_mmu_total); + MENU_ITEM_SUBMENU_P(_i("Last print"), lcd_menu_fails_stats_mmu_print); ////c=18 r=1 + MENU_ITEM_SUBMENU_P(_i("Total"), lcd_menu_fails_stats_mmu_total); ////c=18 r=1 MENU_END(); } +//! @brief Show Last Print Failures Statistics MMU +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! |Last print failures | c=20 r=1 +//! | MMU fails: 000| c=14 r=1 +//! | MMU load fails: 000| c=14 r=1 +//! | | +//! ---------------------- +//! @endcode +//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. static void lcd_menu_fails_stats_mmu_print() { -//01234567890123456789 -//Last print failures -// MMU fails 000 -// MMU load fails 000 -// -////////////////////// - lcd_timeoutToStatus.stop(); //infinite timeout + lcd_timeoutToStatus.stop(); //infinite timeout uint8_t fails = eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL); uint16_t load_fails = eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL); lcd_home(); - lcd_printf_P(PSTR("%S\n" " %-16.16S%-3d\n" " %-16.16S%-3d"), _i("Last print failures"), _i("MMU fails"), fails, _i("MMU load fails"), load_fails); + lcd_printf_P(PSTR("%S\n" " %-16.16S%-3d\n" " %-16.16S%-3d"), + _i("Last print failures"), ////c=20 r=1 + _i("MMU fails"), fails, ////c=14 r=1 + _i("MMU load fails"), load_fails); ////c=14 r=1 menu_back_if_clicked_fb(); } +//! @brief Show Total Failures Statistics MMU +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! |Total failures | c=20 r=1 +//! | MMU fails: 000| c=14 r=1 +//! | MMU load fails: 000| c=14 r=1 +//! | MMU power fails:000| c=14 r=1 +//! ---------------------- +//! @endcode +//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. static void lcd_menu_fails_stats_mmu_total() { -//01234567890123456789 -//Last print failures -// MMU fails 000 -// MMU load fails 000 -// -////////////////////// - mmu_command(MmuCmd::S3); - lcd_timeoutToStatus.stop(); //infinite timeout + mmu_command(MmuCmd::S3); + lcd_timeoutToStatus.stop(); //infinite timeout uint8_t fails = eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL_TOT); uint16_t load_fails = eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL_TOT); lcd_home(); - lcd_printf_P(PSTR("%S\n" " %-16.16S%-3d\n" " %-16.16S%-3d\n" " %-16.16S%-3d"), _i("Total failures"), _i("MMU fails"), fails, _i("MMU load fails"), load_fails, _i("MMU power fails"), mmu_power_failures); + lcd_printf_P(PSTR("%S\n" " %-16.16S%-3d\n" " %-16.16S%-3d\n" " %-16.16S%-3d"), + _i("Total failures"), ////c=20 r=1 + _i("MMU fails"), fails, ////c=14 r=1 + _i("MMU load fails"), load_fails, ////c=14 r=1 + _i("MMU power fails"), mmu_power_failures); ////c=14 r=1 menu_back_if_clicked_fb(); } #if defined(TMC2130) && defined(FILAMENT_SENSOR) static const char failStatsFmt[] PROGMEM = "%S\n" " %-16.16S%-3d\n" " %-16.16S%-3d\n" " %-7.7SX %-3d Y %-3d"; + +//! @brief Show Total Failures Statistics MMU +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! |Total failures | c=20 r=1 +//! | Power failures: 000| c=14 r=1 +//! | Filam. runouts: 000| c=14 r=1 +//! | Crash X:000 Y:000| c=7 r=1 +//! ---------------------- +//! @endcode +//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. static void lcd_menu_fails_stats_total() { -//01234567890123456789 -//Total failures -// Power failures 000 -// Filam. runouts 000 -// Crash X 000 Y 000 -////////////////////// - lcd_timeoutToStatus.stop(); //infinite timeout + lcd_timeoutToStatus.stop(); //infinite timeout uint16_t power = eeprom_read_word((uint16_t*)EEPROM_POWER_COUNT_TOT); uint16_t filam = eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT); uint16_t crashX = eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT); uint16_t crashY = eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT); lcd_home(); - lcd_printf_P(failStatsFmt, _i("Total failures"), _i("Power failures"), power, _i("Filam. runouts"), filam, _i("Crash"), crashX, crashY); + lcd_printf_P(failStatsFmt, + _i("Total failures"), ////c=20 r=1 + _i("Power failures"), power, ////c=14 r=1 + _i("Filam. runouts"), filam, ////c=14 r=1 + _i("Crash"), crashX, crashY); ////c=7 r=1 menu_back_if_clicked_fb(); } +//! @brief Show Last Print Failures Statistics +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! |Last print failures | c=20 r=1 +//! | Power failures: 000| c=14 r=1 +//! | Filam. runouts: 000| c=14 r=1 +//! | Crash X:000 Y:000| c=7 r=1 +//! ---------------------- +//! @endcode +//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. static void lcd_menu_fails_stats_print() { -//01234567890123456789 -//Last print failures -// Power failures 000 -// Filam. runouts 000 -// Crash X 000 Y 000 -////////////////////// - lcd_timeoutToStatus.stop(); //infinite timeout + lcd_timeoutToStatus.stop(); //infinite timeout uint8_t power = eeprom_read_byte((uint8_t*)EEPROM_POWER_COUNT); uint8_t filam = eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT); uint8_t crashX = eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_X); uint8_t crashY = eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_Y); lcd_home(); - lcd_printf_P(failStatsFmt, _i("Last print failures"), _i("Power failures"), power, _i("Filam. runouts"), filam, _i("Crash"), crashX, crashY); + lcd_printf_P(failStatsFmt, + _i("Last print failures"), ////c=20 r=1 + _i("Power failures"), power, ////c=14 r=1 + _i("Filam. runouts"), filam, ////c=14 r=1 + _i("Crash"), crashX, crashY); ////c=7 r=1 menu_back_if_clicked_fb(); } -/** - * @brief Open fail statistics menu - * - * This version of function is used, when there is filament sensor, - * power failure and crash detection. - * There are Last print and Total menu items. - */ +//! @brief Open fail statistics menu +//! +//! This version of function is used, when there is filament sensor, +//! power failure and crash detection. +//! There are Last print and Total menu items. +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! | Main | c=18 r=1 +//! | Last print | c=18 r=1 +//! | Total | c=18 r=1 +//! | | +//! ---------------------- +//! @endcode + static void lcd_menu_fails_stats() { MENU_BEGIN(); MENU_ITEM_BACK_P(_T(MSG_MAIN)); - MENU_ITEM_SUBMENU_P(_i("Last print"), lcd_menu_fails_stats_print); - MENU_ITEM_SUBMENU_P(_i("Total"), lcd_menu_fails_stats_total); + MENU_ITEM_SUBMENU_P(_i("Last print"), lcd_menu_fails_stats_print); ////c=18 r=1 + MENU_ITEM_SUBMENU_P(_i("Total"), lcd_menu_fails_stats_total); ////c=18 r=1 MENU_END(); } #elif defined(FILAMENT_SENSOR) -/** - * @brief Print last print and total filament run outs - * - * This version of function is used, when there is filament sensor, - * but no other sensors (e.g. power failure, crash detection). - * - * Example screen: - * @code - * 01234567890123456789 - * Last print failures - * Filam. runouts 0 - * Total failures - * Filam. runouts 5 - * @endcode - */ +//! +//! @brief Print last print and total filament run outs +//! +//! This version of function is used, when there is filament sensor, +//! but no other sensors (e.g. power failure, crash detection). +//! +//! Example screen: +//! @code{.unparsed} +//! |01234567890123456789| +//! |Last print failures | c=20 r=1 +//! | Filam. runouts: 000| c=14 r=1 +//! |Total failures | c=20 r=1 +//! | Filam. runouts: 000| c=14 r=1 +//! ---------------------- +//! @endcode +//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. static void lcd_menu_fails_stats() { lcd_timeoutToStatus.stop(); //infinite timeout uint8_t filamentLast = eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT); uint16_t filamentTotal = eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT); lcd_home(); - lcd_printf_P(PSTR("Last print failures\n" " Filam. runouts %-3d\n" "Total failures\n" " Filam. runouts %-3d"), filamentLast, filamentTotal); + lcd_printf_P(PSTR("Last print failures\n" ////c=20 r=1 + " Filam. runouts %-3d\n" ////c=14 r=1 + "Total failures\n" ////c=20 r=1 + " Filam. runouts %-3d"), filamentLast, filamentTotal); ////c=14 r=1 menu_back_if_clicked(); } #else @@ -1880,11 +1952,25 @@ extern char* __malloc_heap_start; extern char* __malloc_heap_end; #endif //DEBUG_STACK_MONITOR +//! @brief Show Debug Information +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! |RAM statistics | c=20 r=1 +//! | SP_min: 0000| c=14 r=1 +//! | heap_start: 0000| c=14 r=1 +//! | heap_end: 0000| c=14 r=1 +//! ---------------------- +//! @endcode +//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. static void lcd_menu_debug() { #ifdef DEBUG_STACK_MONITOR lcd_home(); - lcd_printf_P(PSTR("RAM statistics\n" " SP_min: 0x%04x\n" " heap_start: 0x%04x\n" " heap_end: 0x%04x"), SP_min, __malloc_heap_start, __malloc_heap_end); + lcd_printf_P(PSTR("RAM statistics\n" ////c=20 r=1 + " SP_min: 0x%04x\n" ////c=14 r=1 + " heap_start: 0x%04x\n" ////c=14 r=1 + " heap_end: 0x%04x"), SP_min, __malloc_heap_start, __malloc_heap_end); ////c=14 r=1 #endif //DEBUG_STACK_MONITOR menu_back_if_clicked_fb(); @@ -1900,16 +1986,29 @@ static void lcd_menu_temperatures_line(const char *ipgmLabel, int value){ pgmtext_with_colon(ipgmLabel, tmp, maxChars); lcd_printf_P(PSTR(" %s%3d\x01 \n"), tmp, value); // no need to add -14.14 to string alignment } + +//! @brief Show Temperatures +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! | Nozzle: 000D| c=14 r=1 +//! | Bed: 000D| c=14 r=1 +//! | Ambient: 000D| c=14 r=1 +//! | PINDA: 000D| c=14 r=1 +//! ---------------------- +//! D - Degree sysmbol LCD_STR_DEGREE +//! @endcode +//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. static void lcd_menu_temperatures() { lcd_timeoutToStatus.stop(); //infinite timeout lcd_home(); - lcd_menu_temperatures_line( _T(MSG_NOZZLE), (int)current_temperature[0] ); - lcd_menu_temperatures_line( _T(MSG_BED), (int)current_temperature_bed ); + lcd_menu_temperatures_line( _T(MSG_NOZZLE), (int)current_temperature[0] ); ////c=14 r=1 + lcd_menu_temperatures_line( _T(MSG_BED), (int)current_temperature_bed ); ////c=14 r=1 #ifdef AMBIENT_THERMISTOR - lcd_menu_temperatures_line( _i("Ambient"), (int)current_temperature_ambient ); + lcd_menu_temperatures_line( _i("Ambient"), (int)current_temperature_ambient ); ////c=14 r=1 #endif - lcd_menu_temperatures_line( _i("PINDA"), (int)current_temperature_pinda ); + lcd_menu_temperatures_line( _i("PINDA"), (int)current_temperature_pinda ); ////c=14 r=1 menu_back_if_clicked(); @@ -1920,6 +2019,17 @@ static void lcd_menu_temperatures() #define VOLT_DIV_R2 2370 #define VOLT_DIV_FAC ((float)VOLT_DIV_R2 / (VOLT_DIV_R2 + VOLT_DIV_R1)) #define VOLT_DIV_REF 5 +//! @brief Show Voltages +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! | | +//! | PWR: 00.0V | c=12 r=1 +//! | Bed: 00.0V | c=12 r=1 +//! | | +//! ---------------------- +//! @endcode +//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. static void lcd_menu_voltages() { lcd_timeoutToStatus.stop(); //infinite timeout @@ -1932,6 +2042,17 @@ static void lcd_menu_voltages() #endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN #ifdef TMC2130 +//! @brief Show Belt Status +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! | Belt status | c=18 r=1 +//! | X: 000 | +//! | Y: 000 | +//! | | +//! ---------------------- +//! @endcode +//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. static void lcd_menu_belt_status() { lcd_home(); @@ -1955,12 +2076,85 @@ static void lcd_menu_test_restore() } #endif //RESUME_DEBUG +//! @brief Show Preheat Menu static void lcd_preheat_menu() { eFilamentAction = FilamentAction::Preheat; mFilamentMenu(); } +//! @brief Show Support Menu +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! | Main | +//! | Firmware: | c=18 r=1 +//! | 3.7.2.-2363 | c=16 r=1 +//! | prusa3d.com | MSG_PRUSA3D +//! | forum.prusa3d.com | MSG_PRUSA3D_FORUM +//! | howto.prusa3d.com | MSG_PRUSA3D_HOWTO +//! | -------------- | STR_SEPARATOR +//! | 1_75mm_MK3 | FILAMENT_SIZE +//! | howto.prusa3d.com | ELECTRONICS +//! | howto.prusa3d.com | NOZZLE_TYPE +//! | -------------- | STR_SEPARATOR +//! | Date: | c=17 r=1 +//! | MMM DD YYYY | __DATE__ +//! | -------------- | STR_SEPARATOR +//! @endcode +//! +//! If MMU is connected +//! +//! @code{.unparsed} +//! | MMU2 connected | c=18 r=1 +//! | FW: 1.0.6-7064523 | +//! @endcode +//! +//! If MMU is not connected +//! +//! @code{.unparsed} +//! | MMU2 N/A | c=18 r=1 +//! @endcode +//! +//! If Flash Air is connected +//! +//! @code{.unparsed} +//! | -------------- | STR_SEPARATOR +//! | FlashAir IP Addr: | c=18 r=1 +//! | 192.168.1.100 | +//! @endcode +//! +//! @code{.unparsed} +//! | -------------- | STR_SEPARATOR +//! | XYZ cal. details | MSG_XYZ_DETAILS +//! | Extruder info | MSG_INFO_EXTRUDER +//! | XYZ cal. details | MSG_INFO_SENSORS +//! @endcode +//! +//! If TMC2130 defined +//! +//! @code{.unparsed} +//! | Belt status | MSG_MENU_BELT_STATUS +//! @endcode +//! +//! @code{.unparsed} +//! | Temperatures | MSG_MENU_TEMPERATURES +//! @endcode +//! +//! If Voltage Bed and PWR Pin are defined +//! +//! @code{.unparsed} +//! | Voltages | MSG_MENU_VOLTAGES +//! @endcode +//! +//! +//! If DEBUG_BUILD is defined +//! +//! @code{.unparsed} +//! | Debug | c=18 r=1 +//! @endcode +//! ---------------------- +//! @endcode static void lcd_support_menu() { typedef struct @@ -2022,8 +2216,8 @@ static void lcd_support_menu() MENU_ITEM_BACK_P(STR_SEPARATOR); if (mmu_enabled) { - MENU_ITEM_BACK_P(_i("MMU2 connected")); - MENU_ITEM_BACK_P(PSTR(" FW:")); + MENU_ITEM_BACK_P(_i("MMU2 connected")); ////c=18 r=1 + MENU_ITEM_BACK_P(PSTR(" FW:")); ////c=17 r=1 if (((menu_item - 1) == menu_line) && lcd_draw_update) { lcd_set_cursor(6, menu_row); @@ -2040,7 +2234,7 @@ static void lcd_support_menu() // Show the FlashAir IP address, if the card is available. if (_md->is_flash_air) { MENU_ITEM_BACK_P(STR_SEPARATOR); - MENU_ITEM_BACK_P(PSTR("FlashAir IP Addr:")); + MENU_ITEM_BACK_P(PSTR("FlashAir IP Addr:")); //c=18 r=1 ///! MENU_ITEM(back_RAM, _md->ip_str, 0); } @@ -2061,7 +2255,7 @@ static void lcd_support_menu() #endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN #ifdef DEBUG_BUILD - MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug); + MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////c=18 r=1 #endif /* DEBUG_BUILD */ #endif //MK1BP @@ -2653,9 +2847,9 @@ if(0) //! //! @code{.unparsed} //! |01234567890123456789| -//! |Filament used: | +//! |Filament used: | c=18 r=1 //! | 00.00m | -//! |Print time: | +//! |Print time: | c=18 r=1 //! | 00h 00m 00s | //! ---------------------- //! @endcode @@ -2664,12 +2858,13 @@ if(0) //! //! @code{.unparsed} //! |01234567890123456789| -//! |Total filament : | +//! |Total filament : | c=18 r=1 //! | 000.00 m | -//! |Total print time : | +//! |Total print time : | c=18 r=1 //! | 00d :00h :00 m | //! ---------------------- //! @endcode +//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. Translations missing for "d"days, "h"ours, "m"inutes", "s"seconds". void lcd_menu_statistics() { if (IS_SD_PRINTING) @@ -2686,7 +2881,9 @@ void lcd_menu_statistics() "%17.2fm \n" "%S:\n" "%2dh %02dm %02ds" - ),_i("Filament used"), _met, _i("Print time"), _h, _m, _s); + ), + _i("Filament used"), _met, ////c=18 r=1 + _i("Print time"), _h, _m, _s); ////c=18 r=1 menu_back_if_clicked_fb(); } else @@ -2793,17 +2990,20 @@ static void lcd_move_e() } -//@brief Show measured Y distance of front calibration points from Y_MIN_POS -//If those points are detected too close to edge of reachable area, their confidence is lowered. -//This functionality is applied more often for MK2 printers. +//! @brief Show measured Y distance of front calibration points from Y_MIN_POS +//! If those points are detected too close to edge of reachable area, their confidence is lowered. +//! This functionality is applied more often for MK2 printers. +//! @code{.unparsed} +//! |01234567890123456789| +//! |Y distance from min | c=19 r=1 +//! | -------------- | STR_SEPARATOR +//! |Left: 00.00mm | c=11 r=1 +//! |Right: 00.00mm | c=11 r=1 +//! ---------------------- +//! @endcode +//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. static void lcd_menu_xyz_y_min() { -//|01234567890123456789| -//|Y distance from min:| -//|--------------------| -//|Left: N/A | -//|Right: N/A | -//---------------------- float distanceMin[2]; count_xyz_details(distanceMin); lcd_home(); @@ -2813,15 +3013,15 @@ static void lcd_menu_xyz_y_min() "%S:\n" "%S:" ), - _i("Y distance from min"), + _i("Y distance from min"), ////c=19 r=1 separator, - _i("Left"), - _i("Right") + _i("Left"), ////c=11 r=1 + _i("Right") ////c=11 r=1 ); for (uint8_t i = 0; i < 2; i++) { lcd_set_cursor(11,2+i); - if (distanceMin[i] >= 200) lcd_puts_P(_N("N/A")); + if (distanceMin[i] >= 200) lcd_puts_P(_N("N/A")); ////c=3 r=1 else lcd_printf_P(_N("%6.2fmm"), distanceMin[i]); } if (lcd_clicked()) @@ -2834,14 +3034,20 @@ float _deg(float rad) return rad * 180 / M_PI; } +//! @brief Show Measured XYZ Skew +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! |Measured skew: 0.00D| c=13 r=1 +//! | -------------- | STR_SEPARATOR +//! |Slight skew: 0.12D| c=13 r=1 c=4 r=1 +//! |Severe skew: 0.25D| c=13 r=1 c=4 r=1 +//! ---------------------- +//! D - Degree sysmbol LCD_STR_DEGREE +//! @endcode +//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. static void lcd_menu_xyz_skew() { -//|01234567890123456789| -//|Measured skew: N/A | -//|--------------------| -//|Slight skew: 0.12d| -//|Severe skew: 0.25d| -//---------------------- float angleDiff = eeprom_read_float((float*)(EEPROM_XYZ_CAL_SKEW)); lcd_home(); lcd_printf_P(_N( @@ -2850,10 +3056,10 @@ static void lcd_menu_xyz_skew() "%-15.15S%3.2f\x01\n" "%-15.15S%3.2f\x01" ), - _i("Measured skew"), + _i("Measured skew"), ////c=13 r=1 separator, - _i("Slight skew:"), _deg(bed_skew_angle_mild), - _i("Severe skew:"), _deg(bed_skew_angle_extreme) + _i("Slight skew:"), _deg(bed_skew_angle_mild), ////c=13 r=1 c=4 r=1 + _i("Severe skew:"), _deg(bed_skew_angle_extreme) ////c=13 r=1 c=4 r=1 ); if (angleDiff < 100){ lcd_set_cursor(15,0); @@ -2866,16 +3072,24 @@ static void lcd_menu_xyz_skew() if (lcd_clicked()) menu_goto(lcd_menu_xyz_offset, 0, true, true); } -/** - * @brief Show measured bed offset from expected position - */ +//! @brief Show measured bed offset from expected position +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! |[0;0] point offset | c=20 r=1 +//! | -------------- | STR_SEPARATOR +//! |X: 000.00mm| c=10 r=1 +//! |Y: 000.00mm| c=10 r=1 +//! ---------------------- +//! @endcode +//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. static void lcd_menu_xyz_offset() { lcd_set_cursor(0,0); lcd_puts_P(_i("[0;0] point offset"));////MSG_MEASURED_OFFSET lcd_puts_at_P(0, 1, separator); - lcd_puts_at_P(0, 2, PSTR("X")); - lcd_puts_at_P(0, 3, PSTR("Y")); + lcd_puts_at_P(0, 2, PSTR("X")); ////c=10 r=1 + lcd_puts_at_P(0, 3, PSTR("Y")); ////c=10 r=1 float vec_x[2]; float vec_y[2]; @@ -3034,6 +3248,18 @@ void lcd_adjust_bed_reset(void) _md->status = 0; } +//! @brief Show Bed level correct +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! |Settings: | MSG_SETTINGS +//! |Left side [um]: | MSG_BED_CORRECTION_LEFT +//! |Right side[um]: | MSG_BED_CORRECTION_RIGHT +//! |Front side[um]: | MSG_BED_CORRECTION_FRONT +//! |Rear side [um]: | MSG_BED_CORRECTION_REAR +//! |Reset | MSG_BED_CORRECTION_RESET +//! ---------------------- +//! @endcode void lcd_adjust_bed(void) { _menu_data_adjust_bed_t* _md = (_menu_data_adjust_bed_t*)&(menu_data[0]); @@ -3071,6 +3297,16 @@ void lcd_adjust_bed(void) MENU_END(); } +//! @brief Show PID Extruder +//! +//! @code{.unparsed} +//! |01234567890123456789| +//! | Set temperature: | MSG_SET_TEMPERATURE +//! | | +//! | 210 | +//! | | +//! ---------------------- +//! @endcode void pid_extruder() { lcd_clear(); @@ -4540,7 +4776,9 @@ void lcd_v2_calibration() { if (mmu_enabled) { - const uint8_t filament = choose_menu_P(_i("Select PLA filament:"),_T(MSG_FILAMENT),_i("Cancel")); ////c=20 r=1 ////c=19 r=1 + const uint8_t filament = choose_menu_P( + _i("Select PLA filament:"), ////c=20 r=1 + _T(MSG_FILAMENT),_i("Cancel")); ////c=19 r=1 if (filament < 5) { lcd_commands_step = 20 + filament; diff --git a/lang/lang-import.sh b/lang/lang-import.sh index 092afb981..060b4f888 100755 --- a/lang/lang-import.sh +++ b/lang/lang-import.sh @@ -4,7 +4,19 @@ # for importing translated xx.po LNG=$1 -if [ -z "$LNG" ]; then exit -1; fi +# if no arguments, 'all' is selected (all po and also pot will be generated) +if [ -z "$LNG" ]; then LNG=all; fi + +# if 'all' is selected, script will generate all po files and also pot file +if [ "$LNG" = "all" ]; then + ./lang-import.sh cz + ./lang-import.sh de + ./lang-import.sh es + ./lang-import.sh fr + ./lang-import.sh it + ./lang-import.sh pl + exit 0 +fi # language code (iso639-1) is equal to LNG LNGISO=$LNG @@ -28,43 +40,51 @@ sed -i 's/ \\n/ /g;s/\\n/ /g' $LNG'_filtered.po' #replace in czech translation if [ "$LNG" = "cz" ]; then - #replace 'ž' with 'z' + #replace 'ž' with 'z' sed -i 's/\xc5\xbe/z/g' $LNG'_filtered.po' - #replace 'ì' with 'e' + #replace 'ì' with 'e' sed -i 's/\xc4\x9b/e/g' $LNG'_filtered.po' - #replace 'í' with 'i' + #replace 'í' with 'i' sed -i 's/\xc3\xad/i/g' $LNG'_filtered.po' - #replace 'ø' with 'r' + #replace 'ø' with 'r' sed -i 's/\xc5\x99/r/g' $LNG'_filtered.po' - #replace 'è' with 'c' + #replace 'è' with 'c' sed -i 's/\xc4\x8d/c/g' $LNG'_filtered.po' - #replace 'á' with 'a' + #replace 'á' with 'a' sed -i 's/\xc3\xa1/a/g' $LNG'_filtered.po' - #replace 'é' with 'e' + #replace 'é' with 'e' sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po' fi -#replace in german translation +#replace in german translation https://en.wikipedia.org/wiki/German_orthography if [ "$LNG" = "de" ]; then - #replace 'ä' with 'ae' + #replace 'ä' with 'ae' sed -i 's/\xc3\xa4/ae/g' $LNG'_filtered.po' - #replace 'ü' with 'ue' + #replace 'Ä' with 'Ae' + sed -i 's/\xc3\x84/Ae/g' $LNG'_filtered.po' + #replace 'ü' with 'ue' sed -i 's/\xc3\xbc/ue/g' $LNG'_filtered.po' - #replace 'ö' with 'oe' + #replace 'Ü' with 'Ue' + sed -i 's/\xc3\x9c/Ue/g' $LNG'_filtered.po' + #replace 'ö' with 'oe' sed -i 's/\xc3\xb6/oe/g' $LNG'_filtered.po' + #replace 'Ö' with 'Oe' + sed -i 's/\xc3\x96/Oe/g' $LNG'_filtered.po' + #replace 'ß' with 'ss' + sed -i 's/\xc3\x9f/ss/g' $LNG'_filtered.po' fi #replace in spain translation if [ "$LNG" = "es" ]; then - #replace 'á' with 'a' + #replace 'á' with 'a' sed -i 's/\xc3\xa1/a/g' $LNG'_filtered.po' - #replace '?' with '?' + #replace '¿' with '?' sed -i 's/\xc2\xbf/?/g' $LNG'_filtered.po' - #replace 'ó' with 'o' + #replace 'ó' with 'o' sed -i 's/\xc3\xb3/o/g' $LNG'_filtered.po' - #replace 'é' with 'e' + #replace 'é' with 'e' sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po' - #replace 'í' with 'i' + #replace 'í' with 'i' sed -i 's/\xc3\xad/i/g' $LNG'_filtered.po' #replace '!' with '!' sed -i 's/\xc2\xa1/!/g' $LNG'_filtered.po' @@ -72,31 +92,39 @@ if [ "$LNG" = "es" ]; then sed -i 's/\xc3\xb1/n/g' $LNG'_filtered.po' fi -#replace in french translation +#replace in french translation https://en.wikipedia.org/wiki/French_orthography if [ "$LNG" = "fr" ]; then - #replace 'é' with 'e' - sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po' - #replace 'É' with 'E' - sed -i 's/\xc3\x89/E/g' $LNG'_filtered.po' - #replace 'é' with 'e' (left) - sed -i 's/\xc3\xa8/e/g' $LNG'_filtered.po' - #replace 'á' with 'a' (left) + #replace 'á' with 'a' (right) + sed -i 's/\xc3\xa1/a/g' $LNG'_filtered.po' + #replace 'Ã' with 'A' (right) + sed -i 's/\xc3\x81/A/g' $LNG'_filtered.po' + #replace 'à' with 'a' (left) sed -i 's/\xc3\xa0/a/g' $LNG'_filtered.po' + #replace 'À' with 'A' (left) + sed -i 's/\xc3\x80/A/g' $LNG'_filtered.po' + #replace 'é' with 'e' (right) + sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po' + #replace 'É' with 'E' (right) + sed -i 's/\xc3\x89/E/g' $LNG'_filtered.po' + #replace 'è' with 'e' (left) + sed -i 's/\xc3\xa8/e/g' $LNG'_filtered.po' + #replace 'È' with 'E' (left) + sed -i 's/\xc3\x88/E/g' $LNG'_filtered.po' fi #replace in italian translation if [ "$LNG" = "it" ]; then - #replace 'é' with 'e' (left) + #replace 'é' with 'e' (left) sed -i 's/\xc3\xa8/e/g' $LNG'_filtered.po' - #replace 'á' with 'a' (left) + #replace 'á' with 'a' (left) sed -i 's/\xc3\xa0/a/g' $LNG'_filtered.po' - #replace 'ó' with 'o' (left) + #replace 'ó' with 'o' (left) sed -i 's/\xc3\xb2/o/g' $LNG'_filtered.po' - #replace 'ú' with 'u' (left) + #replace 'ú' with 'u' (left) sed -i 's/\xc3\xb9/u/g' $LNG'_filtered.po' - #replace 'é' with 'e' + #replace 'é' with 'e' sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po' - #replace 'É' with 'E' (left) + #replace 'É' with 'E' (left) sed -i 's/\xc3\x88/E/g' $LNG'_filtered.po' fi diff --git a/lang/translations.md b/lang/translations.md new file mode 100644 index 000000000..6c787787c --- /dev/null +++ b/lang/translations.md @@ -0,0 +1,252 @@ +# Translations + +## Workflow + +- Build firmware + - using `build.sh` + - using `PF-build.sh` with a `break` before `# build languages` +- change to `lang` folder +- check if lang scripts being able to run with `config.sh` + - if you get `Arduino main folder: NG` message change in `config.sh` `export ARDUINO=C:/arduino-1.8.5` to `export ARDUINO=` + -example: `export ARDUINO=D:/Github/Prusa-Firmware/PF-build-env-1.0.6/windows-64` +- run `lang-build.sh en` to create english `lang_en.tmp`, `lang_en.dat` and `lang_en.bin` files +- change in `fw-build.sh` `IGNORE_MISSING_TEXT=1` to `IGNORE_MISSING_TEXT=0` so it stops with error and generates `not_used.txt` and `not_tran.txt` +- run modified `fw-build.sh` + - `not_tran.txt` should be reviewed and added as these are potential missing translations + - copy `not_tran.txt` as `lang_add.txt` + - check if there are things you don't want to translate or must be modifed + - als check that the strings do not start with `spaces` as the scripts doesn't handle these well at this moment. + - run `lang-add.sh lang_add.txt` to add the missing translations to `lang_en.txt` and `lang_en_??.txt` + - `not_used.txt` should only contain mesages that aren't used in this variant like MK2.5 vs MK3 +- run `fw-clean.sh` to cleanup firmware related files +- delete `not_used.txt` and `not_tran.txt` +- run `lang-clean.sh` to cleanup language related files +- run `lang-export.sh all` to create PO files for translation these are stored in `/lang/po` folder + - Send them to translators and reviewers or + - copy these to `/lang/po/new` and + - translate these with POEdit the newly added messages + - easiest way is to choose `Validate`in POEdit as it shows you `errors` and the `missing transalations` / most likely the newly added at the top. +- The new translated files are expected in `/lang/po/new` folder so store the received files these +- run `lang-import.sh ` for each newly translated language + - script improvement to import "all" and other things would be great. +- Double check if something is missing or faulty + - run `lang-build.sh` to to create `lang_en.tmp/.dat/.bin` and `lang_en_??.tmp/.dat/.bin` files + - run `fw-build.sh` and check if there are still some messages in `not_tran.txt` that need attention +- After approval + - run `fw-clean.sh` to cleanup firmware related files + - run `lang-clean.sh` to cleanup language related files + - change in `fw-build.sh` back to `IGNORE_MISSING_TEXT=1` + - remove `break` from `PF-build.sh` script if that has been modified + - build your firmware with `build.sh`, `PF-build.sh` or how you normally do it. + - Check/Test firmware on printer + +## Code / usage +There are 2 modes of operation. If `LANG_MODE==0`, only one language is being used (the default compilation approach from plain Arduino IDE). +The reset of this explanation is devoted to `LANG_MODE==1`: + +`language.h`: +```C++ +// section .loc_sec (originaly .progmem0) will be used for localized translated strings +#define PROGMEM_I2 __attribute__((section(".loc_sec"))) +// section .loc_pri (originaly .progmem1) will be used for localized strings in english +#define PROGMEM_I1 __attribute__((section(".loc_pri"))) +// section .noloc (originaly progmem2) will be used for not localized strings in english +#define PROGMEM_N1 __attribute__((section(".noloc"))) +#define _I(s) (__extension__({static const char __c[] PROGMEM_I1 = "\xff\xff" s; &__c[0];})) +#define ISTR(s) "\xff\xff" s +#define _i(s) lang_get_translation(_I(s)) +#define _T(s) lang_get_translation(s) +``` +That explains the macros: +- `_i` expands into `lang_get_translation((__extension__({static const char __c[] PROGMEM_I1 = "\xff\xff" s; &__c[0];})))` . Note the two 0xff's in the beginning of the string. `_i` allows for declaring a string directly inplace of C++ code, no string table is used. The downside of this approach is obvious - the compiler is not able/willing to merge duplicit strings into one. +- `_T` expands into `lang_get_translation(s)` without the two 0xff's at the beginning. Must be used in conjunction with MSG tables in `messages.h`. Allows to declare a string only once and use many times. +- `_N` means not-translated. These strings reside in a different segment of memory. + +The two 0xff's are somehow magically replaced by real string ID's where the translations are available (still don't know where). +```C++ +const char* lang_get_translation(const char* s){ + if (lang_selected == 0) return s + 2; //primary language selected, return orig. str. + if (lang_table == 0) return s + 2; //sec. lang table not found, return orig. str. + uint16_t ui = pgm_read_word(((uint16_t*)s)); //read string id + if (ui == 0xffff) return s + 2; //translation not found, return orig. str. + ui = pgm_read_word(((uint16_t*)(((char*)lang_table + 16 + ui*2)))); //read relative offset + if (pgm_read_byte(((uint8_t*)((char*)lang_table + ui))) == 0) //read first character + return s + 2;//zero length string == not translated, return orig. str. + return (const char*)((char*)lang_table + ui); //return calculated pointer +} +``` + +## Files + +### `lang_en.txt` +``` +#MSG_CRASH_DET_ONLY_IN_NORMAL c=20 r=4 +"Crash detection can\x0abe turned on only in\x0aNormal mode" +``` + +### `lang_en_*.txt` +``` +#MSG_CRASH_DET_ONLY_IN_NORMAL c=20 r=4 +"Crash detection can\x0abe turned on only in\x0aNormal mode" +"Crash detekce muze\x0abyt zapnuta pouze v\x0aNormal modu" +``` +1. a comment - usually a MSG define with number of characters (c) and rows (r) +2. English text +3. translated text + +### `not_tran.txt` +A simple list of strings that are not translated yet. + +### `not_used.txt` +A list os strings not currently used in this variant of the firmware or are obsolete. +Example: There are MK2.5 specific messages that aren't used when you compile a MK3 variant and vice versa. So be carefull and double check the code if this message is obsolete or just not used due to the chosen variant. + +## Scripts + +### `config.sh` +- Checks setup and sets auxiliary env vars used in many other scripts. +- Looks for env var `ARDUINO`. If not found/empty, a default `C:/arduino-1.8.5` is used. +- Sets env var `CONFIG_OK=1` when all good, otherwise sets `CONFIG_OK=0` + +### `fw-build.sh` +Joins firmware HEX and language binaries into one file. + +### `fw-clean.sh` + +### `lang-add.sh` +Adds new messages into the dictionary regardless of whether there have been any older versions. + +### `lang-build.sh` +Generates lang_xx.bin (language binary files) for the whole firmware build. + +Arguments: +- `$1` : language code (`en`, `cz`, `de`, `es`, `fr`, `it`, `pl`) or `all` +- empty/no arguments defaults to `all` + +Input: `lang_en.txt` or `lang_en_xx.txt` + +Output: `lang_xx.bin` + +Temporary files: `lang_xx.tmp` and `lang_xx.dat` + +Description of the process: +The script first runs `lang-check.py $1` and removes empty lines and comments (and non-translated texts) into `lang_$1.tmp`. +The tmp file now contains all translated texts (some of them empty, i.e. ""). +The tmp file is then transformed into `lang_$1.dat`, which is a simple dump of all texts together, each terminated with a `\x00`. +Format of the `bin` file: +- 00-01: `A5 5A` +- 02-03: `B4 4B` +- 04-05: 2B size +- 06-07: 2B number of strings +- 08-09: 2B checksum +- 0A-0B: 2B lang code hex data: basically `en` converted into `ne`, i.e. characters swapped. Only `cz` is changed into `sc` (old `cs` ISO code). +- 0C-0D: 2B signature low +- 0E-0F: 2B signature high +- 10-(10 + 2*number of strings): table of string offsets from the beginning of this file +- after the table there are the strings themselves, each terminated with `\x00` + +The signature is composed of 2B number of strings and 2B checksum in lang_en.bin. Signature in lang_en.bin is zero. + +### `lang-check.sh` and `lang-check.py` +Both do the same, only lang-check.py is newer, i.e. lang-check.sh is not used anymore. +lang-check.py makes a binary comparison between what's in the dictionary and what's in the binary. + +### `lang-clean.sh` +Removes all language output files from lang folder. That means deleting: +- if [ "$1" = "en" ]; then + rm_if_exists lang_$1.tmp + else + rm_if_exists lang_$1.tmp + rm_if_exists lang_en_$1.tmp + rm_if_exists lang_en_$1.dif + rm_if_exists lang_$1.ofs + rm_if_exists lang_$1.txt + fi + rm_if_exists lang_$1_check.dif + rm_if_exists lang_$1.bin + rm_if_exists lang_$1.dat + rm_if_exists lang_$1_1.tmp + rm_if_exists lang_$1_2.tmp + +### `lang-export.sh` +Exports PO (gettext) for external translators. + +### `lang-import.sh` +Import from PO. + +Arguments: +- `$1` : language code (`en`, `cz`, `de`, `es`, `fr`, `it`, `pl`) +- empty/no arguments quits the script + +Input files: `.po` files like `de.po`, `es.po`, etc. + +Input folder: ´/lang/po/new´ + +Output files: + +Output foler: ´/lang/po/new´ + +Needed improments to scrpit: + - add `all` argument + - update `replace in translations` to all known special characters the LCD display with Japanese ROM cannot display + - move `lang_en_.txt` to folder `/lang` + - cleanup `_filtered.po`, `_new.po` and `nonasci.txt` + +### `progmem.sh` + +Examine content of progmem sections (default is progmem1). + +Input: +- $OUTDIR/Firmware.ino.elf +- $OUTDIR/sketch/*.o (all object files) + +Outputs: +- text.sym - formated symbol listing of section '.text' +- $PROGMEM.sym - formated symbol listing of section '.progmemX' +- $PROGMEM.lss - disassembly listing file +- $PROGMEM.hex - variables - hex +- $PROGMEM.chr - variables - char escape +- $PROGMEM.var - variables - strings +- $PROGMEM.txt - text data only (not used) + +Description of process: +- check input files +- remove output files +- list symbol table of section '.text' from output elf file to text.sym (sorted by address) +- calculate start and stop address of section '.$PROGMEM' +- dump $PROGMEM data in hex format, cut disassembly (keep hex data only) into $PROGMEM.lss +- convert $PROGMEM.lss to $PROGMEM.hex: + - replace empty lines with '|' (variables separated by empty lines) + - remove address from multiline variables (keep address at first variable line only) + - remove '<' and '>:', remove whitespace at end of lines + - remove line-endings, replace separator with '\n' (join hex data lines - each line will contain single variable) +- convert $PROGMEM.hex to $PROGMEM.chr (prepare string data for character check and conversion) + - replace first space with tab + - replace second and third space with tab and space + - replace all remaining spaces with '\x' + - replace all tabs with spaces +- convert $PROGMEM.chr to $PROGMEM.var (convert data to text) - a set of special characters is escaped here including `\x0a` + + +### `textaddr.sh` + +Compiles `progmem1.var` and `lang_en.txt` files to `textaddr.txt` file (mapping of progmem addreses to text idenifiers). + +Description of process: +- check if input files exists +- create sorted list of strings from progmem1.var and lang_en.txt +- lines from progmem1.var will contain addres (8 chars) and english text +- lines from lang_en.txt will contain linenumber and english text +- after sort this will generate pairs of lines (line from progmem1 first) +- result of sort is compiled with simple script and stored into file textaddr.txt + +Input: +- progmem1.var +- lang_en.txt + +Output: +- textaddr.txt + + + +update_lang.sh