| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324 | #include "temperature.h"#include "ultralcd.h"#ifdef ULTRA_LCD#include "Marlin.h"#include "language.h"#include "cardreader.h"#include "temperature.h"#include "stepper.h"#include "ConfigurationStore.h"#include <string.h>//#include "Configuration.h"#define _STRINGIFY(s) #sint8_t encoderDiff; /* encoderDiff is updated from interrupt context and added to encoderPosition every LCD update */extern int lcd_change_fil_state;int babystepMem[3];float babystepMemMM[3];union Data{  byte b[2];  int value;};int8_t ReInitLCD = 0;int8_t SDscrool = 0;int8_t SilentModeMenu = 0;int lcd_commands_type=0;int lcd_commands_step=0;bool isPrintPaused = false;bool menuExiting = false;/* Configuration settings */int plaPreheatHotendTemp;int plaPreheatHPBTemp;int plaPreheatFanSpeed;int absPreheatHotendTemp;int absPreheatHPBTemp;int absPreheatFanSpeed;int ppPreheatHotendTemp = PP_PREHEAT_HOTEND_TEMP;int ppPreheatHPBTemp = PP_PREHEAT_HPB_TEMP;int ppPreheatFanSpeed = PP_PREHEAT_FAN_SPEED;int petPreheatHotendTemp = PET_PREHEAT_HOTEND_TEMP;int petPreheatHPBTemp = PET_PREHEAT_HPB_TEMP;int petPreheatFanSpeed = PET_PREHEAT_FAN_SPEED;int hipsPreheatHotendTemp = HIPS_PREHEAT_HOTEND_TEMP;int hipsPreheatHPBTemp = HIPS_PREHEAT_HPB_TEMP;int hipsPreheatFanSpeed = HIPS_PREHEAT_FAN_SPEED;int flexPreheatHotendTemp = FLEX_PREHEAT_HOTEND_TEMP;int flexPreheatHPBTemp = FLEX_PREHEAT_HPB_TEMP;int flexPreheatFanSpeed = FLEX_PREHEAT_FAN_SPEED;#ifdef FILAMENT_LCD_DISPLAYunsigned long message_millis = 0;#endif#ifdef ULTIPANELstatic float manual_feedrate[] = MANUAL_FEEDRATE;#endif // ULTIPANEL/* !Configuration settings *///Function pointer to menu functions.typedef void (*menuFunc_t)();uint8_t lcd_status_message_level;char lcd_status_message[LCD_WIDTH + 1] = ""; //////WELCOME!unsigned char firstrun = 1;#ifdef DOGLCD#include "dogm_lcd_implementation.h"#else#include "ultralcd_implementation_hitachi_HD44780.h"#endif/** forward declarations **/void copy_and_scalePID_i();void copy_and_scalePID_d();/* Different menus */static void lcd_status_screen();#ifdef ULTIPANELextern bool powersupply;static void lcd_main_menu();static void lcd_tune_menu();static void lcd_prepare_menu();static void lcd_move_menu();static void lcd_control_menu();static void lcd_settings_menu();static void lcd_language_menu();static void lcd_control_temperature_menu();static void lcd_control_temperature_preheat_pla_settings_menu();static void lcd_control_temperature_preheat_abs_settings_menu();static void lcd_control_motion_menu();static void lcd_control_volumetric_menu();#ifdef DOGLCDstatic void lcd_set_contrast();#endifstatic void lcd_control_retract_menu();static void lcd_sdcard_menu();#ifdef DELTA_CALIBRATION_MENUstatic void lcd_delta_calibrate_menu();#endif // DELTA_CALIBRATION_MENUstatic void lcd_quick_feedback();//Cause an LCD refresh, and give the user visual or audible feedback that something has happened/* Different types of actions that can be used in menu items. */static void menu_action_back(menuFunc_t data);static void menu_action_submenu(menuFunc_t data);static void menu_action_gcode(const char* pgcode);static void menu_action_function(menuFunc_t data);static void menu_action_setlang(unsigned char lang);static void menu_action_sdfile(const char* filename, char* longFilename);static void menu_action_sddirectory(const char* filename, char* longFilename);static void menu_action_setting_edit_bool(const char* pstr, bool* ptr);static void menu_action_setting_edit_int3(const char* pstr, int* ptr, int minValue, int maxValue);static void menu_action_setting_edit_float3(const char* pstr, float* ptr, float minValue, float maxValue);static void menu_action_setting_edit_float32(const char* pstr, float* ptr, float minValue, float maxValue);static void menu_action_setting_edit_float43(const char* pstr, float* ptr, float minValue, float maxValue);static void menu_action_setting_edit_float5(const char* pstr, float* ptr, float minValue, float maxValue);static void menu_action_setting_edit_float51(const char* pstr, float* ptr, float minValue, float maxValue);static void menu_action_setting_edit_float52(const char* pstr, float* ptr, float minValue, float maxValue);static void menu_action_setting_edit_long5(const char* pstr, unsigned long* ptr, unsigned long minValue, unsigned long maxValue);static void menu_action_setting_edit_callback_bool(const char* pstr, bool* ptr, menuFunc_t callbackFunc);static void menu_action_setting_edit_callback_int3(const char* pstr, int* ptr, int minValue, int maxValue, menuFunc_t callbackFunc);static void menu_action_setting_edit_callback_float3(const char* pstr, float* ptr, float minValue, float maxValue, menuFunc_t callbackFunc);static void menu_action_setting_edit_callback_float32(const char* pstr, float* ptr, float minValue, float maxValue, menuFunc_t callbackFunc);static void menu_action_setting_edit_callback_float43(const char* pstr, float* ptr, float minValue, float maxValue, menuFunc_t callbackFunc);static void menu_action_setting_edit_callback_float5(const char* pstr, float* ptr, float minValue, float maxValue, menuFunc_t callbackFunc);static void menu_action_setting_edit_callback_float51(const char* pstr, float* ptr, float minValue, float maxValue, menuFunc_t callbackFunc);static void menu_action_setting_edit_callback_float52(const char* pstr, float* ptr, float minValue, float maxValue, menuFunc_t callbackFunc);static void menu_action_setting_edit_callback_long5(const char* pstr, unsigned long* ptr, unsigned long minValue, unsigned long maxValue, menuFunc_t callbackFunc);#define ENCODER_FEEDRATE_DEADZONE 10#if !defined(LCD_I2C_VIKI)#ifndef ENCODER_STEPS_PER_MENU_ITEM#define ENCODER_STEPS_PER_MENU_ITEM 5#endif#ifndef ENCODER_PULSES_PER_STEP#define ENCODER_PULSES_PER_STEP 1#endif#else#ifndef ENCODER_STEPS_PER_MENU_ITEM#define ENCODER_STEPS_PER_MENU_ITEM 2 // VIKI LCD rotary encoder uses a different number of steps per rotation#endif#ifndef ENCODER_PULSES_PER_STEP#define ENCODER_PULSES_PER_STEP 1#endif#endif/* Helper macros for menus */#define START_MENU() do { \    if (encoderPosition > 0x8000) encoderPosition = 0; \    if (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM < currentMenuViewOffset) currentMenuViewOffset = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM;\    uint8_t _lineNr = currentMenuViewOffset, _menuItemNr; \    bool wasClicked = LCD_CLICKED;\    for(uint8_t _drawLineNr = 0; _drawLineNr < LCD_HEIGHT; _drawLineNr++, _lineNr++) { \      _menuItemNr = 0;#define MENU_ITEM(type, label, args...) do { \    if (_menuItemNr == _lineNr) { \      if (lcdDrawUpdate) { \        const char* _label_pstr = (label); \        if ((encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr) { \          lcd_implementation_drawmenu_ ## type ## _selected (_drawLineNr, _label_pstr , ## args ); \        }else{\          lcd_implementation_drawmenu_ ## type (_drawLineNr, _label_pstr , ## args ); \        }\      }\      if (wasClicked && (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr) {\        lcd_quick_feedback(); \        menu_action_ ## type ( args ); \        return;\      }\    }\    _menuItemNr++;\  } while(0)#define MENU_ITEM_DUMMY() do { _menuItemNr++; } while(0)#define MENU_ITEM_EDIT(type, label, args...) MENU_ITEM(setting_edit_ ## type, label, (label) , ## args )#define MENU_ITEM_EDIT_CALLBACK(type, label, args...) MENU_ITEM(setting_edit_callback_ ## type, label, (label) , ## args )#define END_MENU() \  if (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM >= _menuItemNr) encoderPosition = _menuItemNr * ENCODER_STEPS_PER_MENU_ITEM - 1; \  if ((uint8_t)(encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) >= currentMenuViewOffset + LCD_HEIGHT) { currentMenuViewOffset = (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) - LCD_HEIGHT + 1; lcdDrawUpdate = 1; _lineNr = currentMenuViewOffset - 1; _drawLineNr = -1; } \  } } while(0)/** Used variables to keep track of the menu */#ifndef REPRAPWORLD_KEYPADvolatile uint8_t buttons;//Contains the bits of the currently pressed buttons.#elsevolatile uint8_t buttons_reprapworld_keypad; // to store the reprapworld_keypad shift register values#endif#ifdef LCD_HAS_SLOW_BUTTONSvolatile uint8_t slow_buttons;//Contains the bits of the currently pressed buttons.#endifuint8_t currentMenuViewOffset;              /* scroll offset in the current menu */uint32_t blocking_enc;uint8_t lastEncoderBits;uint32_t encoderPosition;#if (SDCARDDETECT > 0)bool lcd_oldcardstatus;#endif#endif //ULTIPANELmenuFunc_t currentMenu = lcd_status_screen; /* function pointer to the currently active menu */uint32_t lcd_next_update_millis;uint8_t lcd_status_update_delay;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) *///prevMenu and prevEncoderPosition are used to store the previous menu location when editing settings.menuFunc_t prevMenu = NULL;uint16_t prevEncoderPosition;//Variables used when editing values.const char* editLabel;void* editValue;int32_t minEditValue, maxEditValue;menuFunc_t callbackFunc;// place-holders for Ki and Kd editsfloat raw_Ki, raw_Kd;static void lcd_goto_menu(menuFunc_t menu, const uint32_t encoder = 0, const bool feedback = true) {  if (currentMenu != menu) {    currentMenu = menu;    encoderPosition = encoder;    if (feedback) lcd_quick_feedback();    // For LCD_PROGRESS_BAR re-initialize the custom characters#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)    lcd_set_custom_characters(menu == lcd_status_screen);#endif  }}/* 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;void set_language_from_EEPROM() {  unsigned char eep = eeprom_read_byte((unsigned char*)EEPROM_LANG);  if (eep < LANG_NUM)  {    lang_selected = eep;    langsel = 0;  }  else  {    lang_selected = 1;    langsel = 1;  }}void lcd_mylang();static void lcd_status_screen(){	  if (firstrun == 1)   {    firstrun = 0;    set_language_from_EEPROM();    strncpy_P(lcd_status_message, WELCOME_MSG, LCD_WIDTH);		if (eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 1) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 2) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 3) == 255)	{		eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, 0);		eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, 0);	}		if (langsel) {      //strncpy_P(lcd_status_message, PSTR(">>>>>>>>>>>> PRESS v"), LCD_WIDTH);      lcd_mylang();    }  }    if (lcd_status_update_delay)    lcd_status_update_delay--;  else    lcdDrawUpdate = 1;  if (lcdDrawUpdate)  {    ReInitLCD++;    if (ReInitLCD == 30) {      lcd_implementation_init( // to maybe revive the LCD if static electricity killed it.#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)        currentMenu == lcd_status_screen#endif      );      ReInitLCD = 0 ;    } else {      if ((ReInitLCD % 10) == 0) {        //lcd_implementation_nodisplay();        lcd_implementation_init_noclear( // to maybe revive the LCD if static electricity killed it.#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)          currentMenu == lcd_status_screen#endif        );      }    }    //lcd_implementation_display();    lcd_implementation_status_screen();    //lcd_implementation_clear();    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)	{		lcd_commands();	}	  }#ifdef ULTIPANEL  bool current_click = LCD_CLICKED;  if (ignore_click) {    if (wait_for_unclick) {      if (!current_click) {        ignore_click = wait_for_unclick = false;      }      else {        current_click = false;      }    }    else if (current_click) {      lcd_quick_feedback();      wait_for_unclick = true;      current_click = false;    }  }  //if (--langsel ==0) {langsel=1;current_click=true;}  if (current_click)  {    lcd_goto_menu(lcd_main_menu);    lcd_implementation_init( // to maybe revive the LCD if static electricity killed it.#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)      currentMenu == lcd_status_screen#endif    );#ifdef FILAMENT_LCD_DISPLAY    message_millis = millis();  // get status message to show up for a while#endif  }#ifdef ULTIPANEL_FEEDMULTIPLY  // Dead zone at 100% feedrate  if ((feedmultiply < 100 && (feedmultiply + int(encoderPosition)) > 100) ||      (feedmultiply > 100 && (feedmultiply + int(encoderPosition)) < 100))  {    encoderPosition = 0;    feedmultiply = 100;  }  if (feedmultiply == 100 && int(encoderPosition) > ENCODER_FEEDRATE_DEADZONE)  {    feedmultiply += int(encoderPosition) - ENCODER_FEEDRATE_DEADZONE;    encoderPosition = 0;  }  else if (feedmultiply == 100 && int(encoderPosition) < -ENCODER_FEEDRATE_DEADZONE)  {    feedmultiply += int(encoderPosition) + ENCODER_FEEDRATE_DEADZONE;    encoderPosition = 0;  }  else if (feedmultiply != 100)  {    feedmultiply += int(encoderPosition);    encoderPosition = 0;  }#endif //ULTIPANEL_FEEDMULTIPLY  if (feedmultiply < 10)    feedmultiply = 10;  else if (feedmultiply > 999)    feedmultiply = 999;#endif //ULTIPANEL}#ifdef ULTIPANELvoid lcd_commands(){	if (lcd_commands_type == 1)   //// load filament sequence	{		if (lcd_commands_step == 0) { lcd_commands_step = 5; custom_message = true; }			if (lcd_commands_step == 1 && !blocks_queued())			{				lcd_commands_step = 0;				lcd_commands_type = 0;				lcd_setstatuspgm(WELCOME_MSG);				disable_z();				custom_message = false;				custom_message_type = 0;			}			if (lcd_commands_step == 2 && !blocks_queued())			{				lcd_setstatuspgm(MSG_LOADING_FILAMENT);				enquecommand_P(PSTR(LOAD_FILAMENT_2));				lcd_commands_step = 1;			}			if (lcd_commands_step == 3 && !blocks_queued())			{				enquecommand_P(PSTR(LOAD_FILAMENT_1));				lcd_commands_step = 2;			}			if (lcd_commands_step == 4 && !blocks_queued())			{				lcd_setstatuspgm(MSG_INSERT_FILAMENT);				enquecommand_P(PSTR(LOAD_FILAMENT_0));				lcd_commands_step = 3;			}			if (lcd_commands_step == 5 && !blocks_queued())			{				lcd_setstatuspgm(MSG_PLEASE_WAIT);				enable_z();				custom_message = true;				custom_message_type = 2;				lcd_commands_step = 4;			} 							}	if (lcd_commands_type == 2)   /// stop print	{		if (lcd_commands_step == 0) { lcd_commands_step = 6; custom_message = true;	}		if (lcd_commands_step == 1 && !blocks_queued())		{			lcd_commands_step = 0;			lcd_commands_type = 0;			lcd_setstatuspgm(WELCOME_MSG);			custom_message = false;		}		if (lcd_commands_step == 2 && !blocks_queued())		{			setTargetBed(0);			setTargetHotend(0, 0);			setTargetHotend(0, 1);			setTargetHotend(0, 2);			manage_heater();			lcd_setstatuspgm(WELCOME_MSG);			cancel_heatup = false;			lcd_commands_step = 1;		}		if (lcd_commands_step == 3 && !blocks_queued())		{			enquecommand_P(PSTR("M84"));			autotempShutdown();			lcd_commands_step = 2;		}		if (lcd_commands_step == 4 && !blocks_queued())		{			enquecommand_P(PSTR("G90"));			#ifdef X_CANCEL_POS 			enquecommand_P(PSTR("G1 X"  STRINGIFY(X_CANCEL_POS) " Y" STRINGIFY(Y_CANCEL_POS) " E0 F7000"));			#else			enquecommand_P(PSTR("G1 X50 Y" STRINGIFY(Y_MAX_POS) " E0 F7000"));			#endif			lcd_ignore_click(false);			lcd_commands_step = 3;		}		if (lcd_commands_step == 5 && !blocks_queued())		{			lcd_setstatuspgm(MSG_PRINT_ABORTED);			enquecommand_P(PSTR("G91"));			enquecommand_P(PSTR("G1 Z15 F1500"));			lcd_commands_step = 4;		}		if (lcd_commands_step == 6 && !blocks_queued())		{			lcd_setstatuspgm(MSG_PRINT_ABORTED);			cancel_heatup = true;			setTargetBed(0);			setTargetHotend(0, 0);			setTargetHotend(0, 1);			setTargetHotend(0, 2);			manage_heater();			lcd_commands_step = 5;		}	}	if (lcd_commands_type == 3)	{		lcd_commands_type = 0;	}}static void lcd_return_to_status() {  lcd_implementation_init( // to maybe revive the LCD if static electricity killed it.#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)    currentMenu == lcd_status_screen#endif  );    lcd_goto_menu(lcd_status_screen, 0, false);}static void lcd_sdcard_pause() {  card.pauseSDPrint();  isPrintPaused = true;  lcdDrawUpdate = 3;}static void lcd_sdcard_resume() {	card.startFileprint();	isPrintPaused = false;	lcdDrawUpdate = 3;}float move_menu_scale;static void lcd_move_menu_axis();/* Menu implementation */void lcd_preheat_pla(){  setTargetHotend0(plaPreheatHotendTemp);  setTargetBed(plaPreheatHPBTemp);  fanSpeed = 0;  lcd_return_to_status();  setWatch(); // heater sanity check timer}void lcd_preheat_abs(){  setTargetHotend0(absPreheatHotendTemp);  setTargetBed(absPreheatHPBTemp);  fanSpeed = 0;  lcd_return_to_status();  setWatch(); // heater sanity check timer}void lcd_preheat_pp(){  setTargetHotend0(ppPreheatHotendTemp);  setTargetBed(ppPreheatHPBTemp);  fanSpeed = 0;  lcd_return_to_status();  setWatch(); // heater sanity check timer}void lcd_preheat_pet(){  setTargetHotend0(petPreheatHotendTemp);  setTargetBed(petPreheatHPBTemp);  fanSpeed = 0;  lcd_return_to_status();  setWatch(); // heater sanity check timer}void lcd_preheat_hips(){  setTargetHotend0(hipsPreheatHotendTemp);  setTargetBed(hipsPreheatHPBTemp);  fanSpeed = 0;  lcd_return_to_status();  setWatch(); // heater sanity check timer}void lcd_preheat_flex(){  setTargetHotend0(flexPreheatHotendTemp);  setTargetBed(flexPreheatHPBTemp);  fanSpeed = 0;  lcd_return_to_status();  setWatch(); // heater sanity check timer}void lcd_cooldown(){  setTargetHotend0(0);  setTargetHotend1(0);  setTargetHotend2(0);  setTargetBed(0);  fanSpeed = 0;  lcd_return_to_status();}static void lcd_preheat_menu(){  START_MENU();  MENU_ITEM(back, MSG_MAIN, lcd_main_menu);  MENU_ITEM(function, PSTR("ABS  -  " STRINGIFY(ABS_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(ABS_PREHEAT_HPB_TEMP)), lcd_preheat_abs);  MENU_ITEM(function, PSTR("PLA  -  " STRINGIFY(PLA_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PLA_PREHEAT_HPB_TEMP)), lcd_preheat_pla);  MENU_ITEM(function, PSTR("PET  -  " STRINGIFY(PET_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PET_PREHEAT_HPB_TEMP)), lcd_preheat_pet);  MENU_ITEM(function, PSTR("HIPS -  " STRINGIFY(HIPS_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(HIPS_PREHEAT_HPB_TEMP)), lcd_preheat_hips);  MENU_ITEM(function, PSTR("PP   -  " STRINGIFY(PP_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PP_PREHEAT_HPB_TEMP)), lcd_preheat_pp);  MENU_ITEM(function, PSTR("FLEX -  " STRINGIFY(FLEX_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(FLEX_PREHEAT_HPB_TEMP)), lcd_preheat_flex);  MENU_ITEM(function, MSG_COOLDOWN, lcd_cooldown);  END_MENU();}static void lcd_support_menu(){  START_MENU();  MENU_ITEM(back, MSG_MAIN, lcd_main_menu);  MENU_ITEM(back, PSTR(MSG_FW_VERSION " - " FW_version), lcd_main_menu);  MENU_ITEM(back, MSG_PRUSA3D, lcd_main_menu);  MENU_ITEM(back, MSG_PRUSA3D_FORUM, lcd_main_menu);  MENU_ITEM(back, MSG_PRUSA3D_HOWTO, lcd_main_menu);  MENU_ITEM(back, PSTR("------------"), lcd_main_menu);  MENU_ITEM(back, PSTR(FILAMENT_SIZE), lcd_main_menu);  MENU_ITEM(back, PSTR(ELECTRONICS),lcd_main_menu);  MENU_ITEM(back, PSTR(NOZZLE_TYPE),lcd_main_menu);  MENU_ITEM(back, PSTR("------------"), lcd_main_menu);  MENU_ITEM(back, PSTR("Date: "), lcd_main_menu);  MENU_ITEM(back, PSTR(__DATE__), lcd_main_menu);  END_MENU();}void lcd_unLoadFilament(){  if (degHotend0() > EXTRUDE_MINTEMP) {    enquecommand_P(PSTR(UNLOAD_FILAMENT_0));    enquecommand_P(PSTR(UNLOAD_FILAMENT_1));  } else {    lcd_implementation_clear();    lcd.setCursor(0, 0);    lcd_printPGM(MSG_ERROR);    lcd.setCursor(0, 2);    lcd_printPGM(MSG_PREHEAT_NOZZLE);    delay(2000);    lcd_implementation_clear();  }  lcd_return_to_status();}void lcd_change_filament() {  lcd_implementation_clear();  lcd.setCursor(0, 1);  lcd_printPGM(MSG_CHANGING_FILAMENT);}void lcd_wait_interact() {  lcd_implementation_clear();  lcd.setCursor(0, 1);  lcd_printPGM(MSG_INSERT_FILAMENT);  lcd.setCursor(0, 2);  lcd_printPGM(MSG_PRESS);}void lcd_change_success() {  lcd_implementation_clear();  lcd.setCursor(0, 2);  lcd_printPGM(MSG_CHANGE_SUCCESS);}void lcd_loading_color() {  lcd_implementation_clear();  lcd.setCursor(0, 0);  lcd_printPGM(MSG_LOADING_COLOR);  lcd.setCursor(0, 2);  lcd_printPGM(MSG_PLEASE_WAIT);  for (int i = 0; i < 20; i++) {    lcd.setCursor(i, 3);    lcd.print(".");    for (int j = 0; j < 10 ; j++) {      manage_heater();      manage_inactivity(true);      delay(85);    }  }}void lcd_loading_filament() {  lcd_implementation_clear();  lcd.setCursor(0, 0);  lcd_printPGM(MSG_LOADING_FILAMENT);  lcd.setCursor(0, 2);  lcd_printPGM(MSG_PLEASE_WAIT);  for (int i = 0; i < 20; i++) {    lcd.setCursor(i, 3);    lcd.print(".");    for (int j = 0; j < 10 ; j++) {      manage_heater();      manage_inactivity(true);      delay(110);    }  }}void lcd_alright() {  int enc_dif = 0;  int cursor_pos = 1;  lcd_implementation_clear();  lcd.setCursor(0, 0);  lcd_printPGM(MSG_CORRECTLY);  lcd.setCursor(1, 1);  lcd_printPGM(MSG_YES);  lcd.setCursor(1, 2);  lcd_printPGM(MSG_NOT_LOADED);  lcd.setCursor(1, 3);  lcd_printPGM(MSG_NOT_COLOR);  lcd.setCursor(0, 1);  lcd.print(">");  enc_dif = encoderDiff;  while (lcd_change_fil_state == 0) {    manage_heater();    manage_inactivity(true);    if ( abs((enc_dif - encoderDiff)) > 4 ) {      if ( (abs(enc_dif - encoderDiff)) > 1 ) {        if (enc_dif > encoderDiff ) {          cursor_pos --;        }        if (enc_dif < encoderDiff  ) {          cursor_pos ++;        }        if (cursor_pos > 3) {          cursor_pos = 3;        }        if (cursor_pos < 1) {          cursor_pos = 1;        }        lcd.setCursor(0, 1);        lcd.print(" ");        lcd.setCursor(0, 2);        lcd.print(" ");        lcd.setCursor(0, 3);        lcd.print(" ");        lcd.setCursor(0, cursor_pos);        lcd.print(">");        enc_dif = encoderDiff;        delay(100);      }    }    if (lcd_clicked()) {      lcd_change_fil_state = cursor_pos;      delay(500);    }  };  lcd_implementation_clear();  lcd_return_to_status();}void lcd_LoadFilament(){  if (degHotend0() > EXTRUDE_MINTEMP)   {	  custom_message = true;	  lcd_commands_type = 1;	  SERIAL_ECHOLN("Loading filament");	  // commands() will handle the rest  }   else   {    lcd_implementation_clear();    lcd.setCursor(0, 0);    lcd_printPGM(MSG_ERROR);    lcd.setCursor(0, 2);	lcd_printPGM(MSG_PREHEAT_NOZZLE);    delay(2000);    lcd_implementation_clear();  }  lcd_return_to_status();}static void lcd_menu_statistics(){	if (IS_SD_PRINTING)	{		int _met = total_filament_used / 100000;		int _cm = (total_filament_used - (_met * 100000))/10;				int _t = (millis() - starttime) / 1000;		int _h = _t / 3600;		int _m = (_t - (_h * 60)) / 60;		int _s = _t - ((_h * 3600) + (_m * 60));				lcd.setCursor(0, 0);		lcd_printPGM(MSG_STATS_FILAMENTUSED);		lcd.setCursor(6, 1);		lcd.print(itostr3(_met));		lcd.print("m ");		lcd.print(ftostr32ns(_cm));		lcd.print("cm");				lcd.setCursor(0, 2);		lcd_printPGM(MSG_STATS_PRINTTIME);		lcd.setCursor(8, 3);		lcd.print(itostr2(_h));		lcd.print("h ");		lcd.print(itostr2(_m));		lcd.print("m ");		lcd.print(itostr2(_s));		lcd.print("s");		if (lcd_clicked())		{			lcd_quick_feedback();			lcd_return_to_status();		}	}	else	{		unsigned long _filament = eeprom_read_dword((uint32_t *)EEPROM_FILAMENTUSED);		unsigned long _time = eeprom_read_dword((uint32_t *)EEPROM_TOTALTIME);		uint8_t _days, _hours, _minutes;		float _filament_m = (float)_filament;		int _filament_km = (_filament >= 100000) ? _filament / 100000 : 0;		if (_filament_km > 0)  _filament_m = _filament - (_filament_km * 100000);		_days = _time / 1440;		_hours = (_time - (_days * 1440)) / 60;		_minutes = _time - ((_days * 1440) + (_hours * 60));		lcd_implementation_clear();		lcd.setCursor(0, 0);		lcd_printPGM(MSG_STATS_TOTALFILAMENT);		lcd.setCursor(17 - strlen(ftostr32ns(_filament_m)), 1);		lcd.print(ftostr32ns(_filament_m));		if (_filament_km > 0)		{			lcd.setCursor(17 - strlen(ftostr32ns(_filament_m)) - 3, 1);			lcd.print("km");			lcd.setCursor(17 - strlen(ftostr32ns(_filament_m)) - 8, 1);			lcd.print(itostr4(_filament_km));		}		lcd.setCursor(18, 1);		lcd.print("m");		lcd.setCursor(0, 2);		lcd_printPGM(MSG_STATS_TOTALPRINTTIME);;		lcd.setCursor(18, 3);		lcd.print("m");		lcd.setCursor(14, 3);		lcd.print(itostr3(_minutes));		lcd.setCursor(14, 3);		lcd.print(":");		lcd.setCursor(12, 3);		lcd.print("h");		lcd.setCursor(9, 3);		lcd.print(itostr3(_hours));		lcd.setCursor(9, 3);		lcd.print(":");		lcd.setCursor(7, 3);		lcd.print("d");		lcd.setCursor(4, 3);		lcd.print(itostr3(_days));		while (!lcd_clicked())		{			manage_heater();			manage_inactivity(true);			delay(100);		}		lcd_quick_feedback();		lcd_return_to_status();	}}static void _lcd_move(const char *name, int axis, int min, int max) {  if (encoderPosition != 0) {    refresh_cmd_timeout();    current_position[axis] += float((int)encoderPosition) * move_menu_scale;    if (min_software_endstops && current_position[axis] < min) current_position[axis] = min;    if (max_software_endstops && current_position[axis] > max) current_position[axis] = max;    encoderPosition = 0;    plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[axis] / 60, active_extruder);    lcdDrawUpdate = 1;  }  if (lcdDrawUpdate) lcd_implementation_drawedit(name, ftostr31(current_position[axis]));  if (LCD_CLICKED) lcd_goto_menu(lcd_move_menu_axis);}static void lcd_move_e(){  if (encoderPosition != 0)  {    current_position[E_AXIS] += float((int)encoderPosition) * move_menu_scale;    encoderPosition = 0;    plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[E_AXIS] / 60, active_extruder);    lcdDrawUpdate = 1;  }  if (lcdDrawUpdate)  {    lcd_implementation_drawedit(PSTR("Extruder"), ftostr31(current_position[E_AXIS]));  }  if (LCD_CLICKED) lcd_goto_menu(lcd_move_menu_axis);}// Save a single axis babystep value.void EEPROM_save_B(int pos, int* value){  union Data data;  data.value = *value;  eeprom_update_byte((unsigned char*)pos, data.b[0]);  eeprom_update_byte((unsigned char*)pos + 1, data.b[1]);}// Read a single axis babystep value.void EEPROM_read_B(int pos, int* value){  union Data data;  data.b[0] = eeprom_read_byte((unsigned char*)pos);  data.b[1] = eeprom_read_byte((unsigned char*)pos + 1);  *value = data.value;}static void lcd_move_x() {  _lcd_move(PSTR("X"), X_AXIS, X_MIN_POS, X_MAX_POS);}static void lcd_move_y() {  _lcd_move(PSTR("Y"), Y_AXIS, Y_MIN_POS, Y_MAX_POS);}static void lcd_move_z() {  _lcd_move(PSTR("Z"), Z_AXIS, Z_MIN_POS, Z_MAX_POS);}static void _lcd_babystep(int axis, const char *msg) {  if (encoderPosition != 0)   {    babystepsTodo[axis] += (int)encoderPosition;    babystepMem[axis] += (int)encoderPosition;    babystepMemMM[axis] = babystepMem[axis]/axis_steps_per_unit[Z_AXIS];	  delay(50);	  encoderPosition = 0;    lcdDrawUpdate = 1;  }  if (lcdDrawUpdate) lcd_implementation_drawedit_2(msg, ftostr13ns(babystepMemMM[axis]));  if (LCD_CLICKED || menuExiting) {    // Only update the EEPROM when leaving the menu.    EEPROM_save_B(      (axis == 0) ? EEPROM_BABYSTEP_X : ((axis == 1) ? EEPROM_BABYSTEP_Y : EEPROM_BABYSTEP_Z),       &babystepMem[axis]);  }  if (LCD_CLICKED) lcd_goto_menu(lcd_main_menu);}static void lcd_babystep_x() {  _lcd_babystep(X_AXIS, (MSG_BABYSTEPPING_X));}static void lcd_babystep_y() {  _lcd_babystep(Y_AXIS, (MSG_BABYSTEPPING_Y));}static void lcd_babystep_z() {	_lcd_babystep(Z_AXIS, (MSG_BABYSTEPPING_Z));}void lcd_adjust_z() {  int enc_dif = 0;  int cursor_pos = 1;  int fsm = 0;  lcd_implementation_clear();  lcd.setCursor(0, 0);  lcd_printPGM(MSG_ADJUSTZ);  lcd.setCursor(1, 1);  lcd_printPGM(MSG_YES);  lcd.setCursor(1, 2);  lcd_printPGM(MSG_NO);  lcd.setCursor(0, 1);  lcd.print(">");  enc_dif = encoderDiff;  while (fsm == 0) {    manage_heater();    manage_inactivity(true);    if ( abs((enc_dif - encoderDiff)) > 4 ) {      if ( (abs(enc_dif - encoderDiff)) > 1 ) {        if (enc_dif > encoderDiff ) {          cursor_pos --;        }        if (enc_dif < encoderDiff  ) {          cursor_pos ++;        }        if (cursor_pos > 2) {          cursor_pos = 2;        }        if (cursor_pos < 1) {          cursor_pos = 1;        }        lcd.setCursor(0, 1);        lcd.print(" ");        lcd.setCursor(0, 2);        lcd.print(" ");        lcd.setCursor(0, cursor_pos);        lcd.print(">");        enc_dif = encoderDiff;        delay(100);      }    }    if (lcd_clicked()) {      fsm = cursor_pos;      if (fsm == 1) {        EEPROM_read_B(EEPROM_BABYSTEP_X, &babystepMem[0]);        EEPROM_read_B(EEPROM_BABYSTEP_Y, &babystepMem[1]);        EEPROM_read_B(EEPROM_BABYSTEP_Z, &babystepMem[2]);        babystepsTodo[Z_AXIS] = babystepMem[2];      } else {        babystepMem[0] = 0;        babystepMem[1] = 0;        babystepMem[2] = 0;        EEPROM_save_B(EEPROM_BABYSTEP_X, &babystepMem[0]);        EEPROM_save_B(EEPROM_BABYSTEP_Y, &babystepMem[1]);        EEPROM_save_B(EEPROM_BABYSTEP_Z, &babystepMem[2]);      }      delay(500);    }  };  lcd_implementation_clear();  lcd_return_to_status();}// Lets the user move the Z carriage up to the end stoppers.// When done, it sets the current Z to Z_MAX_POS and returns true.// Otherwise the Z calibration is not changed and false is returned.bool lcd_calibrate_z_end_stop_manual(){    const unsigned long max_inactive_time = 60 * 1000; // 60 seconds    unsigned long previous_millis_cmd = millis();    int8_t        cursor_pos;    int8_t        enc_dif = 0;    // Don't know where we are. Let's claim we are Z=0, so the soft end stops will not be triggered when moving up.    current_position[Z_AXIS] = 0;    plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);    // Until confirmed by the confirmation dialog.    for (;;) {        previous_millis_cmd = millis();        lcd_implementation_clear();        lcd.setCursor(0, 0);        lcd_printPGM(MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE1);        lcd.setCursor(0, 1);        lcd_printPGM(MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE2);        lcd.setCursor(0, 2);        lcd_printPGM(MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE3);        lcd.setCursor(0, 3);        lcd_printPGM(MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE4);        // Until the user finishes the z up movement.        encoderDiff = 0;        encoderPosition = 0;        for (;;) {            if (millis() - previous_millis_cmd >  max_inactive_time)                goto canceled;            manage_heater();            manage_inactivity(true);            if (abs(encoderDiff) >= ENCODER_PULSES_PER_STEP) {                delay(50);                previous_millis_cmd = millis();                encoderPosition += abs(encoderDiff / ENCODER_PULSES_PER_STEP);                encoderDiff = 0;                // Only move up, whatever the user does.                current_position[Z_AXIS] += fabs(encoderPosition);                encoderPosition = 0;                plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[Z_AXIS] / 60, active_extruder);                // Wait for the motors to stop.                st_synchronize();                // Claim we are at Z=0, so the soft end stop will not trigger.                current_position[Z_AXIS] = 0;                plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);            }            if (lcd_clicked()) {                // Wait until the Z up movement is finished.                st_synchronize();                while (lcd_clicked()) ;                delay(10);                while (lcd_clicked()) ;                break;            }        }        // Let the user confirm, that the Z carriage is at the top end stoppers.        lcd_implementation_clear();        lcd.setCursor(0, 0);        lcd_printPGM(MSG_CONFIRM_CARRIAGE_AT_THE_TOP_LINE1);        lcd.setCursor(0, 1);        lcd_printPGM(MSG_CONFIRM_CARRIAGE_AT_THE_TOP_LINE2);        lcd.setCursor(1, 2);        lcd_printPGM(MSG_YES);        lcd.setCursor(1, 3);        lcd_printPGM(MSG_NO);        cursor_pos = 3;        lcd.setCursor(0, cursor_pos);        lcd_printPGM(PSTR(">"));        previous_millis_cmd = millis();        enc_dif = encoderDiff;        for (;;) {            if (millis() - previous_millis_cmd >  max_inactive_time)                goto canceled;            manage_heater();            manage_inactivity(true);            if (abs((enc_dif - encoderDiff)) > 4) {                if (abs(enc_dif - encoderDiff) > 1) {                    lcd.setCursor(0, 2);                    if (enc_dif > encoderDiff && cursor_pos == 4) {                        lcd_printPGM((PSTR(" ")));                        lcd.setCursor(0, 3);                        lcd_printPGM((PSTR(">")));                        -- cursor_pos;                    } else if (enc_dif < encoderDiff && cursor_pos == 3) {                        ++ cursor_pos;                        lcd_printPGM((PSTR(">")));                        lcd.setCursor(0, 3);                        lcd_printPGM((PSTR(" ")));                    }                    enc_dif = encoderDiff;                }            }            if (lcd_clicked()) {                while (lcd_clicked()) ;                delay(10);                while (lcd_clicked()) ;                if (cursor_pos == 3) {                    // Perform another round of the Z up dialog.                    break;                }                goto calibrated;            }        }    }calibrated:    current_position[Z_AXIS] = Z_MAX_POS;    plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);    return true;canceled:    return false;}static inline bool pgm_is_whitespace(const char *c){    return pgm_read_byte(c) == ' ' || pgm_read_byte(c) == '\t' || pgm_read_byte(c) == '\r' || pgm_read_byte(c) == '\n';}void lcd_display_message_fullscreen_P(const char *msg){    // Disable update of the screen by the usual lcd_update() routine.     lcd_update_enable(false);    lcd_implementation_clear();    lcd.setCursor(0, 0);    for (int8_t row = 0; row < 4; ++ row) {        while (pgm_is_whitespace(msg))            ++ msg;        if (pgm_read_byte(msg) == 0)            // End of the message.            break;        lcd.setCursor(0, row);        const char *msgend2 = msg + min(strlen_P(msg), 20);        const char *msgend = msgend2;        if (pgm_read_byte(msgend) != 0 && ! pgm_is_whitespace(msgend)) {              // Splitting a word. Find the start of the current word.            while (msgend > msg && ! pgm_is_whitespace(msgend - 1))                 -- msgend;            if (msgend == msg)                // Found a single long word, which cannot be split. Just cut it.                msgend = msgend2;        }        for (; msg < msgend; ++ msg) {            char c = char(pgm_read_byte(msg));            if (c == '~')                c = ' ';            lcd.print(c);        }    }}static void lcd_show_fullscreen_message_and_wait_P(const char *msg){    lcd_display_message_fullscreen_P(msg);    // Until confirmed by a button click.    for (;;) {        delay_keep_alive(50);        if (lcd_clicked()) {            while (lcd_clicked()) ;            delay(10);            while (lcd_clicked()) ;            break;        }    }}void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result, uint8_t point_too_far_mask){    const char *msg = NULL;    if (result == BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND) {        lcd_show_fullscreen_message_and_wait_P(MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND);    } else if (result == BED_SKEW_OFFSET_DETECTION_FITTING_FAILED) {        if (point_too_far_mask == 0)            msg = MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED;        else if (point_too_far_mask == 2 || point_too_far_mask == 7)            // Only the center point or all the three front points.            msg = MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR;        else if (point_too_far_mask & 1 == 0)            // The right and maybe the center point out of reach.            msg = MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR;        else            // The left and maybe the center point out of reach.            msg = MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR;        lcd_show_fullscreen_message_and_wait_P(msg);    } else {        if (point_too_far_mask != 0) {            if (point_too_far_mask == 2 || point_too_far_mask == 7)                // Only the center point or all the three front points.                msg = MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR;            else if (point_too_far_mask & 1 == 0)                // The right and maybe the center point out of reach.                msg = MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR;            else                // The left and maybe the center point out of reach.                msg = MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR;            lcd_show_fullscreen_message_and_wait_P(msg);        }        if (point_too_far_mask == 0 || result > 0) {            switch (result) {                default:                    // should not happen                    msg = MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED;                    break;                case BED_SKEW_OFFSET_DETECTION_PERFECT:                    msg = MSG_BED_SKEW_OFFSET_DETECTION_PERFECT;                    break;                case BED_SKEW_OFFSET_DETECTION_SKEW_MILD:                    msg = MSG_BED_SKEW_OFFSET_DETECTION_SKEW_MILD;                    break;                case BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME:                    msg = MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME;                    break;            }            lcd_show_fullscreen_message_and_wait_P(msg);        }    }}static void lcd_show_end_stops() {    lcd.setCursor(0, 0);    lcd_printPGM((PSTR("End stops diag")));    lcd.setCursor(0, 1);    lcd_printPGM((READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1) ? (PSTR("X1")) : (PSTR("X0")));    lcd.setCursor(0, 2);    lcd_printPGM((READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1) ? (PSTR("Y1")) : (PSTR("Y0")));    lcd.setCursor(0, 3);    lcd_printPGM((READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING == 1) ? (PSTR("Z1")) : (PSTR("Z0")));}static void menu_show_end_stops() {    lcd_show_end_stops();    if (LCD_CLICKED) lcd_goto_menu(lcd_settings_menu);}// Lets the user move the Z carriage up to the end stoppers.// When done, it sets the current Z to Z_MAX_POS and returns true.// Otherwise the Z calibration is not changed and false is returned.void lcd_diag_show_end_stops(){    int enc_dif = encoderDiff;    lcd_implementation_clear();    for (;;) {        manage_heater();        manage_inactivity(true);        lcd_show_end_stops();        if (lcd_clicked()) {            while (lcd_clicked()) ;            delay(10);            while (lcd_clicked()) ;            break;        }    }    lcd_implementation_clear();    lcd_return_to_status();}void lcd_pick_babystep(){    int enc_dif = 0;    int cursor_pos = 1;    int fsm = 0;                    lcd_implementation_clear();        lcd.setCursor(0, 0);        lcd_printPGM(MSG_PICK_Z);            lcd.setCursor(3, 2);        lcd.print("1");        lcd.setCursor(3, 3);        lcd.print("2");        lcd.setCursor(12, 2);        lcd.print("3");        lcd.setCursor(12, 3);        lcd.print("4");        lcd.setCursor(1, 2);        lcd.print(">");            enc_dif = encoderDiff;        while (fsm == 0) {                manage_heater();        manage_inactivity(true);                if ( abs((enc_dif - encoderDiff)) > 4 ) {                        if ( (abs(enc_dif - encoderDiff)) > 1 ) {                if (enc_dif > encoderDiff ) {                    cursor_pos --;                }                                if (enc_dif < encoderDiff  ) {                    cursor_pos ++;                }                                if (cursor_pos > 4) {                    cursor_pos = 4;                }                                if (cursor_pos < 1) {                    cursor_pos = 1;                }                                lcd.setCursor(1, 2);                lcd.print(" ");                lcd.setCursor(1, 3);                lcd.print(" ");                lcd.setCursor(10, 2);                lcd.print(" ");                lcd.setCursor(10, 3);                lcd.print(" ");                                if (cursor_pos < 3) {                    lcd.setCursor(1, cursor_pos+1);                    lcd.print(">");                }else{                    lcd.setCursor(10, cursor_pos-1);                    lcd.print(">");                }                                   enc_dif = encoderDiff;                delay(100);            }                    }                        if (lcd_clicked()) {            fsm = cursor_pos;                        EEPROM_read_B(EEPROM_BABYSTEP_Z0+((fsm-1)*2),&babystepMem[2]);            EEPROM_save_B(EEPROM_BABYSTEP_Z,&babystepMem[2]);            eeprom_write_byte((unsigned char*)EEPROM_BABYSTEP_Z_SET, 0x01);            delay(500);                    }                            };            lcd_implementation_clear();    lcd_return_to_status();}void lcd_move_menu_axis(){  START_MENU();  MENU_ITEM(back, MSG_SETTINGS, lcd_settings_menu);  MENU_ITEM(submenu, MSG_MOVE_X, lcd_move_x);  MENU_ITEM(submenu, MSG_MOVE_Y, lcd_move_y);  if (move_menu_scale < 10.0)  {	  if (!isPrintPaused)	  {		  MENU_ITEM(submenu, MSG_MOVE_Z, lcd_move_z);	  }	  MENU_ITEM(submenu, MSG_MOVE_E, lcd_move_e);  }  END_MENU();}static void lcd_move_menu_1mm(){  move_menu_scale = 1.0;  lcd_move_menu_axis();}void EEPROM_save(int pos, uint8_t* value, uint8_t size){  do  {    eeprom_write_byte((unsigned char*)pos, *value);    pos++;    value++;  } while (--size);}void EEPROM_read(int pos, uint8_t* value, uint8_t size){  do  {    *value = eeprom_read_byte((unsigned char*)pos);    pos++;    value++;  } while (--size);}static void lcd_silent_mode_set() {  SilentModeMenu = !SilentModeMenu;  EEPROM_save(EEPROM_SILENT, (uint8_t*)&SilentModeMenu, sizeof(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;}void lcd_force_language_selection() {  eeprom_write_byte((unsigned char *)EEPROM_LANG, 255);}static void lcd_language_menu(){  START_MENU();  if (!langsel) {    MENU_ITEM(back, MSG_SETTINGS, lcd_settings_menu);  }  if (langsel == 2) {    MENU_ITEM(back, MSG_WATCH, lcd_status_screen);  }  for (int i=0;i<LANG_NUM;i++){    MENU_ITEM(setlang, MSG_LANGUAGE_NAME_EXPLICIT(i), i);  }  //MENU_ITEM(setlang, MSG_LANGUAGE_NAME_EXPLICIT(1), 1);  END_MENU();}void lcd_mesh_bedleveling(){	enquecommand_P(PSTR("G80"));	lcd_return_to_status();}void lcd_mesh_calibration(){  enquecommand_P(PSTR("M45"));  lcd_return_to_status();}static void lcd_settings_menu(){  EEPROM_read(EEPROM_SILENT, (uint8_t*)&SilentModeMenu, sizeof(SilentModeMenu));  START_MENU();  MENU_ITEM(back, MSG_MAIN, lcd_main_menu);  MENU_ITEM(submenu, MSG_TEMPERATURE, lcd_control_temperature_menu);  MENU_ITEM(submenu, MSG_MOVE_AXIS, lcd_move_menu_1mm);    if (!isPrintPaused)  {#ifndef MESH_BED_LEVELING	  MENU_ITEM(gcode, MSG_HOMEYZ, PSTR("G28 Z"));#else	  MENU_ITEM(submenu, MSG_HOMEYZ, lcd_mesh_bedleveling);#endif  }  if (!isPrintPaused)  {	  MENU_ITEM(gcode, MSG_DISABLE_STEPPERS, PSTR("M84"));	  MENU_ITEM(gcode, MSG_AUTO_HOME, PSTR("G28"));  }  if (SilentModeMenu == 0) {    MENU_ITEM(function, MSG_SILENT_MODE_OFF, lcd_silent_mode_set);  } else {    MENU_ITEM(function, MSG_SILENT_MODE_ON, lcd_silent_mode_set);  }    EEPROM_read_B(EEPROM_BABYSTEP_X, &babystepMem[0]);    EEPROM_read_B(EEPROM_BABYSTEP_Y, &babystepMem[1]);    EEPROM_read_B(EEPROM_BABYSTEP_Z, &babystepMem[2]);    babystepMemMM[2] = babystepMem[2]/axis_steps_per_unit[Z_AXIS];  	if (!isPrintPaused)	{		MENU_ITEM(submenu, MSG_BABYSTEP_Z, lcd_babystep_z);//8	}	MENU_ITEM(submenu, MSG_LANGUAGE_SELECT, lcd_language_menu);	if (!isPrintPaused)	{		MENU_ITEM(submenu, MSG_SELFTEST, lcd_selftest);    MENU_ITEM(submenu, MSG_SHOW_END_STOPS, menu_show_end_stops);    MENU_ITEM(submenu, MSG_CALIBRATE_BED, lcd_mesh_calibration);    MENU_ITEM(gcode, MSG_CALIBRATE_BED_RESET, PSTR("M44"));	}  	END_MENU();}/*void lcd_mylang_top(int hlaska) {    lcd.setCursor(0,0);    lcd.print("                    ");    lcd.setCursor(0,0);    lcd_printPGM(MSG_ALL[hlaska-1][LANGUAGE_SELECT]);   }void lcd_mylang_drawmenu(int cursor) {  int first = 0;  if (cursor>2) first = cursor-2;  if (cursor==LANG_NUM) first = LANG_NUM-3;  lcd.setCursor(0, 1);  lcd.print("                    ");  lcd.setCursor(1, 1);  lcd_printPGM(MSG_ALL[first][LANGUAGE_NAME]);  lcd.setCursor(0, 2);  lcd.print("                    ");  lcd.setCursor(1, 2);  lcd_printPGM(MSG_ALL[first+1][LANGUAGE_NAME]);  lcd.setCursor(0, 3);  lcd.print("                    ");  lcd.setCursor(1, 3);  lcd_printPGM(MSG_ALL[first+2][LANGUAGE_NAME]);      if (cursor==1) lcd.setCursor(0, 1);  if (cursor>1 && cursor<LANG_NUM) lcd.setCursor(0, 2);  if (cursor==LANG_NUM) lcd.setCursor(0, 3);  lcd.print(">");    if (cursor<LANG_NUM-1) {    lcd.setCursor(19,3);    lcd.print("\x01");  }  if (cursor>2) {    lcd.setCursor(19,1);    lcd.print("^");  }  }*/void lcd_mylang_drawmenu(int cursor) {  int first = 0;  if (cursor>3) first = cursor-3;  if (cursor==LANG_NUM && LANG_NUM>4) first = LANG_NUM-4;  if (cursor==LANG_NUM && LANG_NUM==4) first = LANG_NUM-4;  lcd.setCursor(0, 0);  lcd.print("                    ");  lcd.setCursor(1, 0);  lcd_printPGM(MSG_LANGUAGE_NAME_EXPLICIT(first+0));  lcd.setCursor(0, 1);  lcd.print("                    ");  lcd.setCursor(1, 1);  lcd_printPGM(MSG_LANGUAGE_NAME_EXPLICIT(first+1));  lcd.setCursor(0, 2);  lcd.print("                    ");  if (LANG_NUM > 2){    lcd.setCursor(1, 2);    lcd_printPGM(MSG_LANGUAGE_NAME_EXPLICIT(first+2));  }  lcd.setCursor(0, 3);  lcd.print("                    ");  if (LANG_NUM>3) {    lcd.setCursor(1, 3);    lcd_printPGM(MSG_LANGUAGE_NAME_EXPLICIT(first+3));  }    if (cursor==1) lcd.setCursor(0, 0);  if (cursor==2) lcd.setCursor(0, 1);  if (cursor>2) lcd.setCursor(0, 2);  if (cursor==LANG_NUM && LANG_NUM>3) lcd.setCursor(0, 3);  lcd.print(">");    if (cursor<LANG_NUM-1 && LANG_NUM>4) {    lcd.setCursor(19,3);    lcd.print("\x01");  }  if (cursor>3 && LANG_NUM>4) {    lcd.setCursor(19,0);    lcd.print("^");  }  } void lcd_set_custom_characters_arrows();void lcd_set_custom_characters_degree();void lcd_mylang_drawcursor(int cursor) {    if (cursor==1) lcd.setCursor(0, 1);  if (cursor>1 && cursor<LANG_NUM) lcd.setCursor(0, 2);  if (cursor==LANG_NUM) lcd.setCursor(0, 3);  lcd.print(">");  }  void lcd_mylang() {  int enc_dif = 0;  int cursor_pos = 1;  lang_selected=255;  int hlaska=1;  int counter=0;  lcd_set_custom_characters_arrows();  lcd_implementation_clear();  //lcd_mylang_top(hlaska);  lcd_mylang_drawmenu(cursor_pos);  enc_dif = encoderDiff;  while ( (lang_selected == 255) && (MYSERIAL.available() < 2) ) {    manage_heater();    manage_inactivity(true);    if ( abs((enc_dif - encoderDiff)) > 4 ) {      //if ( (abs(enc_dif - encoderDiff)) > 1 ) {        if (enc_dif > encoderDiff ) {          cursor_pos --;        }        if (enc_dif < encoderDiff  ) {          cursor_pos ++;        }        if (cursor_pos > LANG_NUM) {          cursor_pos = LANG_NUM;        }        if (cursor_pos < 1) {          cursor_pos = 1;        }        lcd_mylang_drawmenu(cursor_pos);        enc_dif = encoderDiff;        delay(100);      //}    } else delay(20);    if (lcd_clicked()) {      lcd_set_lang(cursor_pos-1);      delay(500);    }    /*    if (++counter == 80) {      hlaska++;      if(hlaska>LANG_NUM) hlaska=1;      lcd_mylang_top(hlaska);      lcd_mylang_drawcursor(cursor_pos);      counter=0;    }    */  };  if(MYSERIAL.available() > 1){    lang_selected = 0;    firstrun = 0;  }  lcd_set_custom_characters_degree();  lcd_implementation_clear();  lcd_return_to_status();}static void lcd_main_menu(){  SDscrool = 0;  /*  if (langsel == 1)  {    lcd_goto_menu(lcd_language_menu);  }  */  START_MENU();  // Majkl superawesome menu   MENU_ITEM(back, MSG_WATCH, lcd_status_screen);  if ( ( IS_SD_PRINTING || is_usb_printing ) && (current_position[Z_AXIS] < 0.5) )   {    EEPROM_read_B(EEPROM_BABYSTEP_X, &babystepMem[0]);	EEPROM_read_B(EEPROM_BABYSTEP_Y, &babystepMem[1]);	EEPROM_read_B(EEPROM_BABYSTEP_Z, &babystepMem[2]);	MENU_ITEM(submenu, MSG_BABYSTEP_Z, lcd_babystep_z);//8  }  if ( movesplanned() || IS_SD_PRINTING || is_usb_printing )  {    MENU_ITEM(submenu, MSG_TUNE, lcd_tune_menu);  } else   {    MENU_ITEM(submenu, MSG_PREHEAT, lcd_preheat_menu);  }#ifdef SDSUPPORT  if (card.cardOK)  {    if (card.isFileOpen())    {		if (card.sdprinting)		{			MENU_ITEM(function, MSG_PAUSE_PRINT, lcd_sdcard_pause);		}		else		{			MENU_ITEM(function, MSG_RESUME_PRINT, lcd_sdcard_resume);		}		MENU_ITEM(submenu, MSG_STOP_PRINT, lcd_sdcard_stop);	}	else	{		if (!is_usb_printing)		{			MENU_ITEM(submenu, MSG_CARD_MENU, lcd_sdcard_menu);		}#if SDCARDDETECT < 1      MENU_ITEM(gcode, MSG_CNG_SDCARD, PSTR("M21"));  // SD-card changed by user#endif    }  } else   {    MENU_ITEM(submenu, MSG_NO_CARD, lcd_sdcard_menu);#if SDCARDDETECT < 1    MENU_ITEM(gcode, MSG_INIT_SDCARD, PSTR("M21")); // Manually initialize the SD-card via user interface#endif  }#endif  if (IS_SD_PRINTING || is_usb_printing)  {  }   else   {    MENU_ITEM(function, MSG_LOAD_FILAMENT, lcd_LoadFilament);    MENU_ITEM(function, MSG_UNLOAD_FILAMENT, lcd_unLoadFilament);    MENU_ITEM(submenu, MSG_SETTINGS, lcd_settings_menu);  }  if (!is_usb_printing)  {	  MENU_ITEM(submenu, MSG_STATISTICS, lcd_menu_statistics);  }  MENU_ITEM(submenu, MSG_SUPPORT, lcd_support_menu);  END_MENU();}#ifdef SDSUPPORTstatic void lcd_autostart_sd(){  card.lastnr = 0;  card.setroot();  card.checkautostart(true);}#endifstatic void lcd_silent_mode_set_tune() {  SilentModeMenu = !SilentModeMenu;  EEPROM_save(EEPROM_SILENT, (uint8_t*)&SilentModeMenu, sizeof(SilentModeMenu));  digipot_init();  lcd_goto_menu(lcd_tune_menu, 9);}static void lcd_tune_menu(){  EEPROM_read(EEPROM_SILENT, (uint8_t*)&SilentModeMenu, sizeof(SilentModeMenu));    START_MENU();  MENU_ITEM(back, MSG_MAIN, lcd_main_menu); //1  MENU_ITEM_EDIT(int3, MSG_SPEED, &feedmultiply, 10, 999);//2  MENU_ITEM_EDIT(int3, MSG_NOZZLE, &target_temperature[0], 0, HEATER_0_MAXTEMP - 10);//3  MENU_ITEM_EDIT(int3, MSG_BED, &target_temperature_bed, 0, BED_MAXTEMP - 10);//4  MENU_ITEM_EDIT(int3, MSG_FAN_SPEED, &fanSpeed, 0, 255);//5  MENU_ITEM_EDIT(int3, MSG_FLOW, &extrudemultiply, 10, 999);//6#ifdef FILAMENTCHANGEENABLE  MENU_ITEM(gcode, MSG_FILAMENTCHANGE, PSTR("M600"));//7#endif    if (SilentModeMenu == 0) {    MENU_ITEM(function, MSG_SILENT_MODE_OFF, lcd_silent_mode_set_tune);  } else {    MENU_ITEM(function, MSG_SILENT_MODE_ON, lcd_silent_mode_set_tune);  }  END_MENU();}static void lcd_move_menu_01mm(){  move_menu_scale = 0.1;  lcd_move_menu_axis();}static void lcd_control_temperature_menu(){#ifdef PIDTEMP  // set up temp variables - undo the default scaling  raw_Ki = unscalePID_i(Ki);  raw_Kd = unscalePID_d(Kd);#endif  START_MENU();  MENU_ITEM(back, MSG_SETTINGS, lcd_settings_menu);  //MENU_ITEM(back, MSG_CONTROL, lcd_control_menu);#if TEMP_SENSOR_0 != 0  MENU_ITEM_EDIT(int3, MSG_NOZZLE, &target_temperature[0], 0, HEATER_0_MAXTEMP - 10);#endif#if TEMP_SENSOR_1 != 0  MENU_ITEM_EDIT(int3, MSG_NOZZLE1, &target_temperature[1], 0, HEATER_1_MAXTEMP - 10);#endif#if TEMP_SENSOR_2 != 0  MENU_ITEM_EDIT(int3, MSG_NOZZLE2, &target_temperature[2], 0, HEATER_2_MAXTEMP - 10);#endif#if TEMP_SENSOR_BED != 0  MENU_ITEM_EDIT(int3, MSG_BED, &target_temperature_bed, 0, BED_MAXTEMP - 3);#endif  MENU_ITEM_EDIT(int3, MSG_FAN_SPEED, &fanSpeed, 0, 255);#if defined AUTOTEMP && (TEMP_SENSOR_0 != 0)  MENU_ITEM_EDIT(bool, MSG_AUTOTEMP, &autotemp_enabled);  MENU_ITEM_EDIT(float3, MSG_MIN, &autotemp_min, 0, HEATER_0_MAXTEMP - 10);  MENU_ITEM_EDIT(float3, MSG_MAX, &autotemp_max, 0, HEATER_0_MAXTEMP - 10);  MENU_ITEM_EDIT(float32, MSG_FACTOR, &autotemp_factor, 0.0, 1.0);#endif  END_MENU();}#if SDCARDDETECT == -1static void lcd_sd_refresh(){  card.initsd();  currentMenuViewOffset = 0;}#endifstatic void lcd_sd_updir(){  SDscrool = 0;  card.updir();  currentMenuViewOffset = 0;}void lcd_sdcard_stop(){		lcd.setCursor(0, 0);	lcd_printPGM(MSG_STOP_PRINT);	lcd.setCursor(2, 2);	lcd_printPGM(MSG_NO);	lcd.setCursor(2, 3);	lcd_printPGM(MSG_YES);	lcd.setCursor(0, 2); lcd.print(" ");	lcd.setCursor(0, 3); lcd.print(" ");	if ((int32_t)encoderPosition > 2) { encoderPosition = 2; }	if ((int32_t)encoderPosition < 1) { encoderPosition = 1; }		lcd.setCursor(0, 1 + encoderPosition);	lcd.print(">");	if (lcd_clicked())	{		if ((int32_t)encoderPosition == 1)		{			lcd_return_to_status();		}		if ((int32_t)encoderPosition == 2)		{				cancel_heatup = true;				quickStop();				lcd_setstatuspgm(MSG_PRINT_ABORTED);				card.sdprinting = false;				card.closefile();				stoptime = millis();				unsigned long t = (stoptime - starttime) / 1000;				save_statistics(total_filament_used, t);				lcd_return_to_status();				lcd_ignore_click(true);				lcd_commands_type = 2;		}	}}void lcd_sdcard_menu(){	int tempScrool = 0;  if (lcdDrawUpdate == 0 && LCD_CLICKED == 0)    //delay(100);    return; // nothing to do (so don't thrash the SD card)  uint16_t fileCnt = card.getnrfilenames();  START_MENU();  MENU_ITEM(back, MSG_MAIN, lcd_main_menu);  card.getWorkDirName();  if (card.filename[0] == '/')  {#if SDCARDDETECT == -1    MENU_ITEM(function, MSG_REFRESH, lcd_sd_refresh);#endif  } else {    MENU_ITEM(function, PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);  }  for (uint16_t i = 0; i < fileCnt; i++)  {    if (_menuItemNr == _lineNr)    {#ifndef SDCARD_RATHERRECENTFIRST      card.getfilename(i);#else      card.getfilename(fileCnt - 1 - i);#endif      if (card.filenameIsDir)      {        MENU_ITEM(sddirectory, MSG_CARD_MENU, card.filename, card.longFilename);      } else {        MENU_ITEM(sdfile, MSG_CARD_MENU, card.filename, card.longFilename);      }    } else {      MENU_ITEM_DUMMY();    }  }  END_MENU();}#define menu_edit_type(_type, _name, _strFunc, scale) \  void menu_edit_ ## _name () \  { \    if ((int32_t)encoderPosition < 0) encoderPosition = 0; \    if ((int32_t)encoderPosition > maxEditValue) encoderPosition = maxEditValue; \    if (lcdDrawUpdate) \      lcd_implementation_drawedit(editLabel, _strFunc(((_type)((int32_t)encoderPosition + minEditValue)) / scale)); \    if (LCD_CLICKED) \    { \      *((_type*)editValue) = ((_type)((int32_t)encoderPosition + minEditValue)) / scale; \      lcd_goto_menu(prevMenu, prevEncoderPosition); \    } \  } \  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) \  { \    prevMenu = currentMenu; \    prevEncoderPosition = encoderPosition; \    \    lcdDrawUpdate = 2; \    currentMenu = menu_edit_ ## _name; \    \    editLabel = pstr; \    editValue = ptr; \    minEditValue = minValue * scale; \    maxEditValue = maxValue * scale - minEditValue; \    encoderPosition = (*ptr) * scale - minEditValue; \  }\  static void menu_action_setting_edit_callback_ ## _name (const char* pstr, _type* ptr, _type minValue, _type maxValue, menuFunc_t callback) \  { \    prevMenu = currentMenu; \    prevEncoderPosition = encoderPosition; \    \    lcdDrawUpdate = 2; \    currentMenu = menu_edit_callback_ ## _name; \    \    editLabel = pstr; \    editValue = ptr; \    minEditValue = minValue * scale; \    maxEditValue = maxValue * scale - minEditValue; \    encoderPosition = (*ptr) * scale - minEditValue; \    callbackFunc = callback;\  }menu_edit_type(int, int3, itostr3, 1)menu_edit_type(float, float3, ftostr3, 1)menu_edit_type(float, float32, ftostr32, 100)menu_edit_type(float, float43, ftostr43, 1000)menu_edit_type(float, float5, ftostr5, 0.01)menu_edit_type(float, float51, ftostr51, 10)menu_edit_type(float, float52, ftostr52, 100)menu_edit_type(unsigned long, long5, ftostr5, 0.01)static void lcd_selftest(){	int _progress = 0;	bool _result = false;	_progress = lcd_selftest_screen(-1, _progress, 4, true, 2000);	_progress = lcd_selftest_screen(0, _progress, 3, true, 2000);	_result = lcd_selfcheck_endstops();	if (_result)	{		_progress = lcd_selftest_screen(1, _progress, 3, true, 1000);		_result = lcd_selfcheck_check_heater(false);	}	if (_result)	{		_progress = lcd_selftest_screen(2, _progress, 3, true, 2000);		_result = lcd_selfcheck_axis(0, X_MAX_POS);	}	if (_result)	{		_progress = lcd_selftest_screen(3, _progress, 3, true, 1500);		_result = lcd_selfcheck_axis(1, Y_MAX_POS);	}	if (_result)	{		current_position[X_AXIS] = current_position[X_AXIS] - 3;		current_position[Y_AXIS] = current_position[Y_AXIS] - 14;		_progress = lcd_selftest_screen(4, _progress, 3, true, 1500);		_result = lcd_selfcheck_axis(2, Z_MAX_POS);	}	if (_result)	{		_progress = lcd_selftest_screen(5, _progress, 3, true, 2000);		_result = lcd_selfcheck_check_heater(true);	}	if (_result)	{		_progress = lcd_selftest_screen(6, _progress, 3, true, 5000);	}	else	{		_progress = lcd_selftest_screen(7, _progress, 3, true, 5000);	}	lcd_implementation_clear();	lcd_next_update_millis = millis() + LCD_UPDATE_INTERVAL;	if (_result)	{		LCD_ALERTMESSAGERPGM(MSG_SELFTEST_OK);	}	else	{		LCD_ALERTMESSAGERPGM(MSG_SELFTEST_FAILED);	}}static bool lcd_selfcheck_endstops(){	bool _result = true;	if (READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1 || READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1 || READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING == 1)	{		current_position[0] = (READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1) ? current_position[0] = current_position[0] + 10 : current_position[0];		current_position[1] = (READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1) ? current_position[1] = current_position[1] + 10 : current_position[1];		current_position[2] = (READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING == 1) ? current_position[2] = current_position[2] + 10 : current_position[2];	}	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[0] / 60, active_extruder);	delay(500);	if (READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1 || READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1 || READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING == 1)	{		_result = false;		String  _error = String((READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1) ? "X" : "") +			String((READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1) ? "Y" : "") +			String((READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING == 1) ? "Z" : "");		lcd_selftest_error(3, _error.c_str(), "");	}	manage_heater();	manage_inactivity();	return _result;}static bool lcd_selfcheck_axis(int _axis, int _travel){	bool _stepdone = false;	bool _stepresult = false;	int _progress = 0;	int _travel_done = 0;	int _err_endstop = 0;	int _lcd_refresh = 0;	_travel = _travel + (_travel / 10);	do {		if (_axis == 2)		{			current_position[_axis] = current_position[_axis] - 1;		}		else		{			current_position[_axis] = current_position[_axis] - 3;		}		plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[3], manual_feedrate[0] / 60, active_extruder);		st_synchronize();		if (READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1 || READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1 || READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING == 1)		{			if (_axis == 0)			{				_stepresult = (READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1) ? true : false;				_err_endstop = (READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1) ? 1 : 2;				disable_x();			}			if (_axis == 1)			{				_stepresult = (READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1) ? true : false;				_err_endstop = (READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1) ? 0 : 2;				disable_y();			}			if (_axis == 2)			{				_stepresult = (READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING == 1) ? true : false;				_err_endstop = (READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1) ? 0 : 1;				disable_z();			}			_stepdone = true;		}		if (_lcd_refresh < 6)		{			_lcd_refresh++;		}		else		{			_progress = lcd_selftest_screen(2 + _axis, _progress, 3, false, 0);			_lcd_refresh = 0;		}		manage_heater();		manage_inactivity();		delay(100);		(_travel_done <= _travel) ? _travel_done++ : _stepdone = true;	} while (!_stepdone);	current_position[_axis] = current_position[_axis] + 15;	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[3], manual_feedrate[0] / 60, active_extruder);	if (!_stepresult)	{		const char *_error_1;		const char *_error_2;		if (_axis == X_AXIS) _error_1 = "X";		if (_axis == Y_AXIS) _error_1 = "Y";		if (_axis == Z_AXIS) _error_1 = "Z";		if (_err_endstop == 0) _error_2 = "X";		if (_err_endstop == 1) _error_2 = "Y";		if (_err_endstop == 2) _error_2 = "Z";		if (_travel_done >= _travel)		{			lcd_selftest_error(5, _error_1, _error_2);		}		else		{			lcd_selftest_error(4, _error_1, _error_2);		}	}	return _stepresult;}static bool lcd_selfcheck_check_heater(bool _isbed){	int _counter = 0;	int _progress = 0;	bool _stepresult = false;	bool _docycle = true;	int _checked_snapshot = (_isbed) ? degBed() : degHotend(0);	int _opposite_snapshot = (_isbed) ? degHotend(0) : degBed();	int _cycles = (_isbed) ? 120 : 30;	target_temperature[0] = (_isbed) ? 0 : 100;	target_temperature_bed = (_isbed) ? 100 : 0;	manage_heater();	manage_inactivity();	do {		_counter++;		(_counter < _cycles) ? _docycle = true : _docycle = false;		manage_heater();		manage_inactivity();		_progress = (_isbed) ? lcd_selftest_screen(5, _progress, 2, false, 400) : lcd_selftest_screen(1, _progress, 2, false, 400);	} while (_docycle);	target_temperature[0] = 0;	target_temperature_bed = 0;	manage_heater();	int _checked_result = (_isbed) ? degBed() - _checked_snapshot : degHotend(0) - _checked_snapshot;	int _opposite_result = (_isbed) ? degHotend(0) - _opposite_snapshot : degBed() - _opposite_snapshot;	if (_opposite_result < (_isbed) ? 10 : 3)	{		if (_checked_result >= (_isbed) ? 3 : 10)		{			_stepresult = true;		}		else		{			lcd_selftest_error(1, "", "");		}	}	else	{		lcd_selftest_error(2, "", "");	}	manage_heater();	manage_inactivity();	return _stepresult;}static void lcd_selftest_error(int _error_no, const char *_error_1, const char *_error_2){	lcd_implementation_quick_feedback();	target_temperature[0] = 0;	target_temperature_bed = 0;	manage_heater();	manage_inactivity();	lcd_implementation_clear();	lcd.setCursor(0, 0);	lcd_printPGM(MSG_SELFTEST_ERROR);	lcd.setCursor(0, 1);	lcd_printPGM(MSG_SELFTEST_PLEASECHECK);	switch (_error_no)	{	case 1:		lcd.setCursor(0, 2);		lcd_printPGM(MSG_SELFTEST_HEATERTHERMISTOR);		lcd.setCursor(0, 3);		lcd_printPGM(MSG_SELFTEST_NOTCONNECTED);		break;	case 2:		lcd.setCursor(0, 2);		lcd_printPGM(MSG_SELFTEST_BEDHEATER);		lcd.setCursor(0, 3);		lcd_printPGM(MSG_SELFTEST_WIRINGERROR);		break;	case 3:		lcd.setCursor(0, 2);		lcd_printPGM(MSG_SELFTEST_ENDSTOPS);		lcd.setCursor(0, 3);		lcd_printPGM(MSG_SELFTEST_WIRINGERROR);		lcd.setCursor(17, 3);		lcd.print(_error_1);		break;	case 4:		lcd.setCursor(0, 2);		lcd_printPGM(MSG_SELFTEST_MOTOR);		lcd.setCursor(18, 2);		lcd.print(_error_1);		lcd.setCursor(0, 3);		lcd_printPGM(MSG_SELFTEST_ENDSTOP);		lcd.setCursor(18, 3);		lcd.print(_error_2);		break;	case 5:		lcd.setCursor(0, 2);		lcd_printPGM(MSG_SELFTEST_ENDSTOP_NOTHIT);		lcd.setCursor(0, 3);		lcd_printPGM(MSG_SELFTEST_MOTOR);		lcd.setCursor(18, 3);		lcd.print(_error_1);		break;	}	delay(1000);	lcd_implementation_quick_feedback();	do {		delay(100);		manage_heater();		manage_inactivity();	} while (!lcd_clicked());	LCD_ALERTMESSAGERPGM(MSG_SELFTEST_FAILED);	lcd_return_to_status();}static int lcd_selftest_screen(int _step, int _progress, int _progress_scale, bool _clear, int _delay){	lcd_next_update_millis = millis() + (LCD_UPDATE_INTERVAL * 10000);	int _step_block = 0;	const char *_indicator = (_progress > _progress_scale) ? "-" : "|";	if (_clear) lcd_implementation_clear();	lcd.setCursor(0, 0);	if (_step == -1) lcd_printPGM(MSG_SELFTEST_START);	if (_step == 0) lcd_printPGM(MSG_SELFTEST_CHECK_ENDSTOPS);	if (_step == 1) lcd_printPGM(MSG_SELFTEST_CHECK_HOTEND);	if (_step == 2) lcd_printPGM(MSG_SELFTEST_CHECK_X);	if (_step == 3) lcd_printPGM(MSG_SELFTEST_CHECK_Y);	if (_step == 4) lcd_printPGM(MSG_SELFTEST_CHECK_Z);	if (_step == 5) lcd_printPGM(MSG_SELFTEST_CHECK_BED);	if (_step == 6) lcd_printPGM(MSG_SELFTEST_CHECK_ALLCORRECT);	if (_step == 7) lcd_printPGM(MSG_SELFTEST_FAILED);	lcd.setCursor(0, 1);	lcd.print("--------------------");	_step_block = 1;	lcd_selftest_screen_step(3, 9, ((_step == _step_block) ? 1 : (_step < _step_block) ? 0 : 2), "Hotend", _indicator);	_step_block = 2;	lcd_selftest_screen_step(2, 2, ((_step == _step_block) ? 1 : (_step < _step_block) ? 0 : 2), "X", _indicator);	_step_block = 3;	lcd_selftest_screen_step(2, 8, ((_step == _step_block) ? 1 : (_step < _step_block) ? 0 : 2), "Y", _indicator);	_step_block = 4;	lcd_selftest_screen_step(2, 14, ((_step == _step_block) ? 1 : (_step < _step_block) ? 0 : 2), "Z", _indicator);	_step_block = 5;	lcd_selftest_screen_step(3, 0, ((_step == _step_block) ? 1 : (_step < _step_block) ? 0 : 2), "Bed", _indicator);	if (_delay > 0) delay(_delay);	_progress++;	return (_progress > _progress_scale * 2) ? 0 : _progress;}static void lcd_selftest_screen_step(int _row, int _col, int _state, const char *_name, const char *_indicator){	lcd.setCursor(_col, _row);	switch (_state)	{	case 1:		lcd.print(_name);		lcd.setCursor(_col + strlen(_name), _row);		lcd.print(":");		lcd.setCursor(_col + strlen(_name) + 1, _row);		lcd.print(_indicator);		break;	case 2:		lcd.print(_name);		lcd.setCursor(_col + strlen(_name), _row);		lcd.print(":");		lcd.setCursor(_col + strlen(_name) + 1, _row);		lcd.print("OK");		break;	default:		lcd.print(_name);	}}/** End of menus **/static void lcd_quick_feedback(){  lcdDrawUpdate = 2;  blocking_enc = millis() + 500;  lcd_implementation_quick_feedback();}/** Menu action functions **/static void menu_action_back(menuFunc_t data) {  lcd_goto_menu(data);}static void menu_action_submenu(menuFunc_t data) {  lcd_goto_menu(data);}static void menu_action_gcode(const char* pgcode) {  enquecommand_P(pgcode);}static void menu_action_setlang(unsigned char lang) {  lcd_set_lang(lang);}static void menu_action_function(menuFunc_t data) {  (*data)();}static void menu_action_sdfile(const char* filename, char* longFilename){  char cmd[30];  char* c;  sprintf_P(cmd, PSTR("M23 %s"), filename);  for (c = &cmd[4]; *c; c++)    *c = tolower(*c);  enquecommand(cmd);  enquecommand_P(PSTR("M24"));  lcd_return_to_status();}static void menu_action_sddirectory(const char* filename, char* longFilename){  card.chdir(filename);  encoderPosition = 0;}static void menu_action_setting_edit_bool(const char* pstr, bool* ptr){  *ptr = !(*ptr);}static void menu_action_setting_edit_callback_bool(const char* pstr, bool* ptr, menuFunc_t callback){  menu_action_setting_edit_bool(pstr, ptr);  (*callback)();}#endif//ULTIPANEL/** LCD API **/void lcd_init(){  lcd_implementation_init();#ifdef NEWPANEL  SET_INPUT(BTN_EN1);  SET_INPUT(BTN_EN2);  WRITE(BTN_EN1, HIGH);  WRITE(BTN_EN2, HIGH);#if BTN_ENC > 0  SET_INPUT(BTN_ENC);  WRITE(BTN_ENC, HIGH);#endif#ifdef REPRAPWORLD_KEYPAD  pinMode(SHIFT_CLK, OUTPUT);  pinMode(SHIFT_LD, OUTPUT);  pinMode(SHIFT_OUT, INPUT);  WRITE(SHIFT_OUT, HIGH);  WRITE(SHIFT_LD, HIGH);#endif#else  // Not NEWPANEL#ifdef SR_LCD_2W_NL // Non latching 2 wire shift register  pinMode (SR_DATA_PIN, OUTPUT);  pinMode (SR_CLK_PIN, OUTPUT);#elif defined(SHIFT_CLK)  pinMode(SHIFT_CLK, OUTPUT);  pinMode(SHIFT_LD, OUTPUT);  pinMode(SHIFT_EN, OUTPUT);  pinMode(SHIFT_OUT, INPUT);  WRITE(SHIFT_OUT, HIGH);  WRITE(SHIFT_LD, HIGH);  WRITE(SHIFT_EN, LOW);#else#ifdef ULTIPANEL#error ULTIPANEL requires an encoder#endif#endif // SR_LCD_2W_NL#endif//!NEWPANEL#if defined (SDSUPPORT) && defined(SDCARDDETECT) && (SDCARDDETECT > 0)  pinMode(SDCARDDETECT, INPUT);  WRITE(SDCARDDETECT, HIGH);  lcd_oldcardstatus = IS_SD_INSERTED;#endif//(SDCARDDETECT > 0)#ifdef LCD_HAS_SLOW_BUTTONS  slow_buttons = 0;#endif  lcd_buttons_update();#ifdef ULTIPANEL  encoderDiff = 0;#endif}//#include <avr/pgmspace.h>static volatile bool lcd_update_enabled = true;void lcd_update_enable(bool enabled){    lcd_update_enabled = enabled;}void lcd_update(){	static unsigned long timeoutToStatus = 0;  if (! lcd_update_enabled)      return;#ifdef LCD_HAS_SLOW_BUTTONS  slow_buttons = lcd_implementation_read_slow_buttons(); // buttons which take too long to read in interrupt context#endif  lcd_buttons_update();#if (SDCARDDETECT > 0)  if ((IS_SD_INSERTED != lcd_oldcardstatus && lcd_detected()))  {	  lcdDrawUpdate = 2;	  lcd_oldcardstatus = IS_SD_INSERTED;	  lcd_implementation_init( // to maybe revive the LCD if static electricity killed it.#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)		  currentMenu == lcd_status_screen#endif	  );	  if (lcd_oldcardstatus)	  {		  card.initsd();		  LCD_MESSAGERPGM(MSG_SD_INSERTED);	  }	  else	  {		  card.release();		  LCD_MESSAGERPGM(MSG_SD_REMOVED);	  }  }#endif//CARDINSERTED  if (lcd_next_update_millis < millis())  {#ifdef ULTIPANEL#ifdef REPRAPWORLD_KEYPAD	  if (REPRAPWORLD_KEYPAD_MOVE_Z_UP) {		  reprapworld_keypad_move_z_up();	  }	  if (REPRAPWORLD_KEYPAD_MOVE_Z_DOWN) {		  reprapworld_keypad_move_z_down();	  }	  if (REPRAPWORLD_KEYPAD_MOVE_X_LEFT) {		  reprapworld_keypad_move_x_left();	  }	  if (REPRAPWORLD_KEYPAD_MOVE_X_RIGHT) {		  reprapworld_keypad_move_x_right();	  }	  if (REPRAPWORLD_KEYPAD_MOVE_Y_DOWN) {		  reprapworld_keypad_move_y_down();	  }	  if (REPRAPWORLD_KEYPAD_MOVE_Y_UP) {		  reprapworld_keypad_move_y_up();	  }	  if (REPRAPWORLD_KEYPAD_MOVE_HOME) {		  reprapworld_keypad_move_home();	  }#endif	  if (abs(encoderDiff) >= ENCODER_PULSES_PER_STEP)	  {		  lcdDrawUpdate = 1;		  encoderPosition += encoderDiff / ENCODER_PULSES_PER_STEP;		  encoderDiff = 0;		  timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;	  }	  if (LCD_CLICKED)		  timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;#endif//ULTIPANEL#ifdef DOGLCD        // Changes due to different driver architecture of the DOGM display	  blink++;     // Variable for fan animation and alive dot	  u8g.firstPage();	  do	  {		  u8g.setFont(u8g_font_6x10_marlin);		  u8g.setPrintPos(125, 0);		  if (blink % 2) u8g.setColorIndex(1); else u8g.setColorIndex(0); // Set color for the alive dot		  u8g.drawPixel(127, 63); // draw alive dot		  u8g.setColorIndex(1); // black on white		  (*currentMenu)();		  if (!lcdDrawUpdate)  break; // Terminate display update, when nothing new to draw. This must be done before the last dogm.next()	  } while (u8g.nextPage());#else	  (*currentMenu)();#endif#ifdef LCD_HAS_STATUS_INDICATORS	  lcd_implementation_update_indicators();#endif#ifdef ULTIPANEL	  if (timeoutToStatus < millis() && currentMenu != lcd_status_screen)	  {      // Exiting a menu. Let's call the menu function the last time with menuExiting flag set to true      // to give it a chance to save its state.      // This is useful for example, when the babystep value has to be written into EEPROM.      if (currentMenu != NULL) {        menuExiting = true;        (*currentMenu)();        menuExiting = false;      }		  lcd_return_to_status();		  lcdDrawUpdate = 2;	  }#endif//ULTIPANEL	  if (lcdDrawUpdate == 2) lcd_implementation_clear();	  if (lcdDrawUpdate) lcdDrawUpdate--;	  lcd_next_update_millis = millis() + LCD_UPDATE_INTERVAL;	  }   }void lcd_ignore_click(bool b){  ignore_click = b;  wait_for_unclick = false;}void lcd_finishstatus() {  int len = strlen(lcd_status_message);  if (len > 0) {    while (len < LCD_WIDTH) {      lcd_status_message[len++] = ' ';    }  }  lcd_status_message[LCD_WIDTH] = '\0';#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)#if PROGRESS_MSG_EXPIRE > 0  messageTick =#endif    progressBarTick = millis();#endif  lcdDrawUpdate = 2;#ifdef FILAMENT_LCD_DISPLAY  message_millis = millis();  //get status message to show up for a while#endif}void lcd_setstatus(const char* message){  if (lcd_status_message_level > 0)    return;  strncpy(lcd_status_message, message, LCD_WIDTH);  lcd_finishstatus();}void lcd_setstatuspgm(const char* message){  if (lcd_status_message_level > 0)    return;  strncpy_P(lcd_status_message, message, LCD_WIDTH);  lcd_finishstatus();}void lcd_setalertstatuspgm(const char* message){  lcd_setstatuspgm(message);  lcd_status_message_level = 1;#ifdef ULTIPANEL  lcd_return_to_status();#endif//ULTIPANEL}void lcd_reset_alert_level(){  lcd_status_message_level = 0;}#ifdef DOGLCDvoid lcd_setcontrast(uint8_t value){  lcd_contrast = value & 63;  u8g.setContrast(lcd_contrast);}#endif#ifdef ULTIPANEL/* Warning: This function is called from interrupt context */void lcd_buttons_update(){#ifdef NEWPANEL  uint8_t newbutton = 0;  if (READ(BTN_EN1) == 0)  newbutton |= EN_A;  if (READ(BTN_EN2) == 0)  newbutton |= EN_B;#if BTN_ENC > 0  if ((blocking_enc < millis()) && (READ(BTN_ENC) == 0))    newbutton |= EN_C;#endif  buttons = newbutton;#ifdef LCD_HAS_SLOW_BUTTONS  buttons |= slow_buttons;#endif#ifdef REPRAPWORLD_KEYPAD  // for the reprapworld_keypad  uint8_t newbutton_reprapworld_keypad = 0;  WRITE(SHIFT_LD, LOW);  WRITE(SHIFT_LD, HIGH);  for (int8_t i = 0; i < 8; i++) {    newbutton_reprapworld_keypad = newbutton_reprapworld_keypad >> 1;    if (READ(SHIFT_OUT))      newbutton_reprapworld_keypad |= (1 << 7);    WRITE(SHIFT_CLK, HIGH);    WRITE(SHIFT_CLK, LOW);  }  buttons_reprapworld_keypad = ~newbutton_reprapworld_keypad; //invert it, because a pressed switch produces a logical 0#endif#else   //read it from the shift register  uint8_t newbutton = 0;  WRITE(SHIFT_LD, LOW);  WRITE(SHIFT_LD, HIGH);  unsigned char tmp_buttons = 0;  for (int8_t i = 0; i < 8; i++)  {    newbutton = newbutton >> 1;    if (READ(SHIFT_OUT))      newbutton |= (1 << 7);    WRITE(SHIFT_CLK, HIGH);    WRITE(SHIFT_CLK, LOW);  }  buttons = ~newbutton; //invert it, because a pressed switch produces a logical 0#endif//!NEWPANEL  //manage encoder rotation  uint8_t enc = 0;  if (buttons & EN_A) enc |= B01;  if (buttons & EN_B) enc |= B10;  if (enc != lastEncoderBits)  {    switch (enc)    {      case encrot0:        if (lastEncoderBits == encrot3)          encoderDiff++;        else if (lastEncoderBits == encrot1)          encoderDiff--;        break;      case encrot1:        if (lastEncoderBits == encrot0)          encoderDiff++;        else if (lastEncoderBits == encrot2)          encoderDiff--;        break;      case encrot2:        if (lastEncoderBits == encrot1)          encoderDiff++;        else if (lastEncoderBits == encrot3)          encoderDiff--;        break;      case encrot3:        if (lastEncoderBits == encrot2)          encoderDiff++;        else if (lastEncoderBits == encrot0)          encoderDiff--;        break;    }  }  lastEncoderBits = enc;}bool lcd_detected(void){#if (defined(LCD_I2C_TYPE_MCP23017) || defined(LCD_I2C_TYPE_MCP23008)) && defined(DETECT_DEVICE)  return lcd.LcdDetected() == 1;#else  return true;#endif}void lcd_buzz(long duration, uint16_t freq){#ifdef LCD_USE_I2C_BUZZER  lcd.buzz(duration, freq);#endif}bool lcd_clicked(){  return LCD_CLICKED;}#endif//ULTIPANEL/********************************//** Float conversion utilities **//********************************///  convert float to string with +123.4 formatchar conv[8];char *ftostr3(const float &x){  return itostr3((int)x);}char *itostr2(const uint8_t &x){  //sprintf(conv,"%5.1f",x);  int xx = x;  conv[0] = (xx / 10) % 10 + '0';  conv[1] = (xx) % 10 + '0';  conv[2] = 0;  return conv;}// Convert float to string with 123.4 format, dropping signchar *ftostr31(const float &x){  int xx = x * 10;  conv[0] = (xx >= 0) ? '+' : '-';  xx = abs(xx);  conv[1] = (xx / 1000) % 10 + '0';  conv[2] = (xx / 100) % 10 + '0';  conv[3] = (xx / 10) % 10 + '0';  conv[4] = '.';  conv[5] = (xx) % 10 + '0';  conv[6] = 0;  return conv;}// Convert float to string with 123.4 formatchar *ftostr31ns(const float &x){  int xx = x * 10;  //conv[0]=(xx>=0)?'+':'-';  xx = abs(xx);  conv[0] = (xx / 1000) % 10 + '0';  conv[1] = (xx / 100) % 10 + '0';  conv[2] = (xx / 10) % 10 + '0';  conv[3] = '.';  conv[4] = (xx) % 10 + '0';  conv[5] = 0;  return conv;}char *ftostr32(const float &x){  long xx = x * 100;  if (xx >= 0)    conv[0] = (xx / 10000) % 10 + '0';  else    conv[0] = '-';  xx = abs(xx);  conv[1] = (xx / 1000) % 10 + '0';  conv[2] = (xx / 100) % 10 + '0';  conv[3] = '.';  conv[4] = (xx / 10) % 10 + '0';  conv[5] = (xx) % 10 + '0';  conv[6] = 0;  return conv;}//// Convert float to rj string with 123.45 formatchar *ftostr32ns(const float &x) {	long xx = abs(x);	conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';	conv[1] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';	conv[2] = xx >= 100 ? (xx / 100) % 10 + '0' : '0';	conv[3] = '.';	conv[4] = (xx / 10) % 10 + '0';	conv[5] = xx % 10 + '0';	return conv;}// Convert float to string with 1.234 formatchar *ftostr43(const float &x){  long xx = x * 1000;  if (xx >= 0)    conv[0] = (xx / 1000) % 10 + '0';  else    conv[0] = '-';  xx = abs(xx);  conv[1] = '.';  conv[2] = (xx / 100) % 10 + '0';  conv[3] = (xx / 10) % 10 + '0';  conv[4] = (xx) % 10 + '0';  conv[5] = 0;  return conv;}//Float to string with 1.23 formatchar *ftostr12ns(const float &x){  long xx = x * 100;  xx = abs(xx);  conv[0] = (xx / 100) % 10 + '0';  conv[1] = '.';  conv[2] = (xx / 10) % 10 + '0';  conv[3] = (xx) % 10 + '0';  conv[4] = 0;  return conv;}//Float to string with 1.234 formatchar *ftostr13ns(const float &x){    long xx = x * 1000;    if (xx >= 0)        conv[0] = ' ';    else        conv[0] = '-';    xx = abs(xx);    conv[1] = (xx / 1000) % 10 + '0';    conv[2] = '.';    conv[3] = (xx / 100) % 10 + '0';    conv[4] = (xx / 10) % 10 + '0';    conv[5] = (xx) % 10 + '0';    conv[6] = 0;    return conv;}//  convert float to space-padded string with -_23.4_ formatchar *ftostr32sp(const float &x) {  long xx = abs(x * 100);  uint8_t dig;  if (x < 0) { // negative val = -_0    conv[0] = '-';    dig = (xx / 1000) % 10;    conv[1] = dig ? '0' + dig : ' ';  }  else { // positive val = __0    dig = (xx / 10000) % 10;    if (dig) {      conv[0] = '0' + dig;      conv[1] = '0' + (xx / 1000) % 10;    }    else {      conv[0] = ' ';      dig = (xx / 1000) % 10;      conv[1] = dig ? '0' + dig : ' ';    }  }  conv[2] = '0' + (xx / 100) % 10; // lsd always  dig = xx % 10;  if (dig) { // 2 decimal places    conv[5] = '0' + dig;    conv[4] = '0' + (xx / 10) % 10;    conv[3] = '.';  }  else { // 1 or 0 decimal place    dig = (xx / 10) % 10;    if (dig) {      conv[4] = '0' + dig;      conv[3] = '.';    }    else {      conv[3] = conv[4] = ' ';    }    conv[5] = ' ';  }  conv[6] = '\0';  return conv;}char *itostr31(const int &xx){  conv[0] = (xx >= 0) ? '+' : '-';  conv[1] = (xx / 1000) % 10 + '0';  conv[2] = (xx / 100) % 10 + '0';  conv[3] = (xx / 10) % 10 + '0';  conv[4] = '.';  conv[5] = (xx) % 10 + '0';  conv[6] = 0;  return conv;}// Convert int to rj string with 123 or -12 formatchar *itostr3(const int &x){  int xx = x;  if (xx < 0) {    conv[0] = '-';    xx = -xx;  } else if (xx >= 100)    conv[0] = (xx / 100) % 10 + '0';  else    conv[0] = ' ';  if (xx >= 10)    conv[1] = (xx / 10) % 10 + '0';  else    conv[1] = ' ';  conv[2] = (xx) % 10 + '0';  conv[3] = 0;  return conv;}// Convert int to lj string with 123 formatchar *itostr3left(const int &xx){  if (xx >= 100)  {    conv[0] = (xx / 100) % 10 + '0';    conv[1] = (xx / 10) % 10 + '0';    conv[2] = (xx) % 10 + '0';    conv[3] = 0;  }  else if (xx >= 10)  {    conv[0] = (xx / 10) % 10 + '0';    conv[1] = (xx) % 10 + '0';    conv[2] = 0;  }  else  {    conv[0] = (xx) % 10 + '0';    conv[1] = 0;  }  return conv;}// Convert int to rj string with 1234 formatchar *itostr4(const int &xx) {  conv[0] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';  conv[1] = xx >= 100 ? (xx / 100) % 10 + '0' : ' ';  conv[2] = xx >= 10 ? (xx / 10) % 10 + '0' : ' ';  conv[3] = xx % 10 + '0';  conv[4] = 0;  return conv;}// Convert float to rj string with 12345 formatchar *ftostr5(const float &x) {  long xx = abs(x);  conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';  conv[1] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';  conv[2] = xx >= 100 ? (xx / 100) % 10 + '0' : ' ';  conv[3] = xx >= 10 ? (xx / 10) % 10 + '0' : ' ';  conv[4] = xx % 10 + '0';  conv[5] = 0;  return conv;}// Convert float to string with +1234.5 formatchar *ftostr51(const float &x){  long xx = x * 10;  conv[0] = (xx >= 0) ? '+' : '-';  xx = abs(xx);  conv[1] = (xx / 10000) % 10 + '0';  conv[2] = (xx / 1000) % 10 + '0';  conv[3] = (xx / 100) % 10 + '0';  conv[4] = (xx / 10) % 10 + '0';  conv[5] = '.';  conv[6] = (xx) % 10 + '0';  conv[7] = 0;  return conv;}// Convert float to string with +123.45 formatchar *ftostr52(const float &x){  long xx = x * 100;  conv[0] = (xx >= 0) ? '+' : '-';  xx = abs(xx);  conv[1] = (xx / 10000) % 10 + '0';  conv[2] = (xx / 1000) % 10 + '0';  conv[3] = (xx / 100) % 10 + '0';  conv[4] = '.';  conv[5] = (xx / 10) % 10 + '0';  conv[6] = (xx) % 10 + '0';  conv[7] = 0;  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 drivervoid copy_and_scalePID_i(){#ifdef PIDTEMP  Ki = scalePID_i(raw_Ki);  updatePID();#endif}// Callback for after editing PID d value// grab the PID d value out of the temp variable; scale it; then update the PID drivervoid copy_and_scalePID_d(){#ifdef PIDTEMP  Kd = scalePID_d(raw_Kd);  updatePID();#endif}#endif //ULTRA_LCD
 |