diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 80961d4cbf..2c1b8546df 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -48,6 +48,7 @@ // 90 = Alpha OMCA board // 91 = Final OMCA board // 301 = Rambo +// 21 = Elefu Ra Board (v3) #ifndef MOTHERBOARD #define MOTHERBOARD 7 @@ -361,6 +362,11 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th //#define REPRAPWORLD_KEYPAD //#define REPRAPWORLD_KEYPAD_MOVE_STEP 10.0 // how much should be moved when a key is pressed, eg 10.0 means 10mm per click +// The Elefu RA Board Control Panel +// http://www.elefu.com/index.php?route=product/product&product_id=53 +// REMEMBER TO INSTALL LiquidCrystal_I2C.h in your ARUDINO library folder: https://github.com/kiyoshigawa/LiquidCrystal_I2C +//#define RA_CONTROL_PANEL + //automatic expansion #if defined (REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER) #define DOGLCD @@ -377,6 +383,12 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define NEWPANEL #define ULTIPANEL #endif +#if defined(RA_CONTROL_PANEL) + #define ULTIPANEL + #define NEWPANEL + #define LCD_I2C_TYPE_PCA8574 + #define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander +#endif //I2C PANELS diff --git a/Marlin/pins.h b/Marlin/pins.h index b761b65cf6..7a8bdf2b5d 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -53,6 +53,7 @@ #endif /* 99 */ + /**************************************************************************************** * Gen7 v1.1, v1.2, v1.3 pin assignment * @@ -571,6 +572,131 @@ #endif +/**************************************************************************************** +* Elefu RA Board Pin Assignments +* +****************************************************************************************/ +#if MOTHERBOARD == 21 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. +#endif + + +#define X_STEP_PIN 49 +#define X_DIR_PIN 13 +#define X_ENABLE_PIN 48 +#define X_MIN_PIN 35 +#define X_MAX_PIN -1 //34 + +#define Y_STEP_PIN 11 +#define Y_DIR_PIN 9 +#define Y_ENABLE_PIN 12 +#define Y_MIN_PIN 33 +#define Y_MAX_PIN -1 //32 + +#define Z_STEP_PIN 7 +#define Z_DIR_PIN 6 +#define Z_ENABLE_PIN 8 +#define Z_MIN_PIN 31 +#define Z_MAX_PIN -1 //30 + +#define E2_STEP_PIN 43 +#define E2_DIR_PIN 47 +#define E2_ENABLE_PIN 42 + +#define E1_STEP_PIN 18 +#define E1_DIR_PIN 19 +#define E1_ENABLE_PIN 38 + +#define E0_STEP_PIN 40 +#define E0_DIR_PIN 41 +#define E0_ENABLE_PIN 37 + +#define SDPOWER -1 +#define LED_PIN -1 //Use +12V Aux port for LED Ring + +#define FAN_PIN 16 //5V PWM + +#define PS_ON_PIN 10 //Set to -1 if using a manual switch on the PWRSW Connector +#define SLEEP_WAKE_PIN 26 //This feature still needs work + +#define HEATER_0_PIN 45 //12V PWM1 +#define HEATER_1_PIN 46 //12V PWM2 +#define HEATER_2_PIN 17 //12V PWM3 +#define HEATER_BED_PIN 44 //DOUBLE 12V PWM +#define TEMP_0_PIN 3 //ANALOG NUMBERING +#define TEMP_1_PIN 2 //ANALOG NUMBERING +#define TEMP_2_PIN 1 //ANALOG NUMBERING +#define TEMP_BED_PIN 0 //ANALOG NUMBERING + +#define BEEPER 36 + +#define KILL_PIN -1 + +// M240 Triggers a camera by emulating a Canon RC-1 Remote +// Data from: http://www.doc-diy.net/photo/rc-1_hacked/ +#define PHOTOGRAPH_PIN 29 + +#ifdef RA_CONTROL_PANEL + + #define SDSS 53 + #define SDCARDDETECT 28 + + #define BTN_EN1 14 + #define BTN_EN2 39 + #define BTN_ENC 15 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + +#endif //RA_CONTROL_PANEL + +#ifdef RA_DISCO + //variables for which pins the TLC5947 is using + #define TLC_CLOCK_PIN 25 + #define TLC_BLANK_PIN 23 + #define TLC_XLAT_PIN 22 + #define TLC_DATA_PIN 24 + + //We also need to define pin to port number mapping for the 2560 to match the pins listed above. If you change the TLC pins, update this as well per the 2560 datasheet! + //This currently only works with the RA Board. + #define TLC_CLOCK_BIT 3 //bit 3 on port A + #define TLC_CLOCK_PORT &PORTA //bit 3 on port A + + #define TLC_BLANK_BIT 1 //bit 1 on port A + #define TLC_BLANK_PORT &PORTA //bit 1 on port A + + #define TLC_DATA_BIT 2 //bit 2 on port A + #define TLC_DATA_PORT &PORTA //bit 2 on port A + + #define TLC_XLAT_BIT 0 //bit 0 on port A + #define TLC_XLAT_PORT &PORTA //bit 0 on port A + + //change this to match your situation. Lots of TLCs takes up the arduino SRAM very quickly, so be careful + //Leave it at at least 1 if you have enabled RA_LIGHTING + //The number of TLC5947 boards chained together for use with the animation, additional ones will repeat the animation on them, but are not individually addressable and mimic those before them. You can leave the default at 2 even if you only have 1 TLC5947 module. + #define NUM_TLCS 2 + + //These TRANS_ARRAY values let you change the order the LEDs on the lighting modules will animate for chase functions. + //Modify them according to your specific situation. + //NOTE: the array should be 8 long for every TLC you have. These defaults assume (2) TLCs. + #define TRANS_ARRAY {0, 1, 2, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8} //forwards + //#define TRANS_ARRAY {7, 6, 5, 4, 3, 2, 1, 0, 8, 9, 10, 11, 12, 13, 14, 15} //backwards +#endif //RA_LIGHTING + + +#endif /* Ra Board */ + + /**************************************************************************************** * Gen6 pin assignment * @@ -1847,3 +1973,6 @@ _E0_PINS _E1_PINS _E2_PINS \ analogInputToDigitalPin(TEMP_0_PIN), analogInputToDigitalPin(TEMP_1_PIN), analogInputToDigitalPin(TEMP_2_PIN), analogInputToDigitalPin(TEMP_BED_PIN) } #endif + + + diff --git a/Marlin/ultralcd_implementation_hitachi_HD44780.h b/Marlin/ultralcd_implementation_hitachi_HD44780.h index 2cf33d930b..a025244876 100644 --- a/Marlin/ultralcd_implementation_hitachi_HD44780.h +++ b/Marlin/ultralcd_implementation_hitachi_HD44780.h @@ -1,748 +1,757 @@ -#ifndef ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H -#define ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H - -/** -* Implementation of the LCD display routines for a hitachi HD44780 display. These are common LCD character displays. -* When selecting the rusian language, a slightly different LCD implementation is used to handle UTF8 characters. -**/ - -#ifndef REPRAPWORLD_KEYPAD -extern volatile uint8_t buttons; //the last checked buttons in a bit array. -#else -extern volatile uint16_t buttons; //an extended version of the last checked buttons in a bit array. -#endif - -//////////////////////////////////// -// Setup button and encode mappings for each panel (into 'buttons' variable) -// -// This is just to map common functions (across different panels) onto the same -// macro name. The mapping is independent of whether the button is directly connected or -// via a shift/i2c register. - -#ifdef ULTIPANEL -// All Ultipanels might have an encoder - so this is always be mapped onto first two bits -#define BLEN_B 1 -#define BLEN_A 0 - -#define EN_B (1< -1 - // encoder click is directly connected - #define BLEN_C 2 - #define EN_C (1< -1 - // the pause/stop/restart button is connected to BTN_ENC when used - #define B_ST (EN_C) // Map the pause/stop/resume button into its normalized functional name - #define LCD_CLICKED (buttons&(B_MI|B_RI|B_ST)) // pause/stop button also acts as click until we implement proper pause/stop. - #else - #define LCD_CLICKED (buttons&(B_MI|B_RI)) - #endif - - // I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update - #define LCD_HAS_SLOW_BUTTONS - -#elif defined(LCD_I2C_PANELOLU2) - // encoder click can be read through I2C if not directly connected - #if BTN_ENC <= 0 - #define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C) - - #define B_MI (PANELOLU2_ENCODER_C< - #include - #include - #define LCD_CLASS LiquidCrystal_I2C - LCD_CLASS lcd(LCD_I2C_ADDRESS,LCD_I2C_PIN_EN,LCD_I2C_PIN_RW,LCD_I2C_PIN_RS,LCD_I2C_PIN_D4,LCD_I2C_PIN_D5,LCD_I2C_PIN_D6,LCD_I2C_PIN_D7); - -#elif defined(LCD_I2C_TYPE_MCP23017) - //for the LED indicators (which maybe mapped to different things in lcd_implementation_update_indicators()) - #define LED_A 0x04 //100 - #define LED_B 0x02 //010 - #define LED_C 0x01 //001 - - #define LCD_HAS_STATUS_INDICATORS - - #include - #include - #define LCD_CLASS LiquidTWI2 - LCD_CLASS lcd(LCD_I2C_ADDRESS); - -#elif defined(LCD_I2C_TYPE_MCP23008) - #include - #include - #define LCD_CLASS LiquidTWI2 - LCD_CLASS lcd(LCD_I2C_ADDRESS); - -#else - // Standard directly connected LCD implementations - #if LANGUAGE_CHOICE == 6 - #include "LiquidCrystalRus.h" - #define LCD_CLASS LiquidCrystalRus - #else - #include - #define LCD_CLASS LiquidCrystal - #endif - LCD_CLASS lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5,LCD_PINS_D6,LCD_PINS_D7); //RS,Enable,D4,D5,D6,D7 -#endif - -/* Custom characters defined in the first 8 characters of the LCD */ -#define LCD_STR_BEDTEMP "\x00" -#define LCD_STR_DEGREE "\x01" -#define LCD_STR_THERMOMETER "\x02" -#define LCD_STR_UPLEVEL "\x03" -#define LCD_STR_REFRESH "\x04" -#define LCD_STR_FOLDER "\x05" -#define LCD_STR_FEEDRATE "\x06" -#define LCD_STR_CLOCK "\x07" -#define LCD_STR_ARROW_RIGHT "\x7E" /* from the default character set */ - -static void lcd_implementation_init() -{ - byte bedTemp[8] = - { - B00000, - B11111, - B10101, - B10001, - B10101, - B11111, - B00000, - B00000 - }; //thanks Sonny Mounicou - byte degree[8] = - { - B01100, - B10010, - B10010, - B01100, - B00000, - B00000, - B00000, - B00000 - }; - byte thermometer[8] = - { - B00100, - B01010, - B01010, - B01010, - B01010, - B10001, - B10001, - B01110 - }; - byte uplevel[8]={ - B00100, - B01110, - B11111, - B00100, - B11100, - B00000, - B00000, - B00000 - }; //thanks joris - byte refresh[8]={ - B00000, - B00110, - B11001, - B11000, - B00011, - B10011, - B01100, - B00000, - }; //thanks joris - byte folder [8]={ - B00000, - B11100, - B11111, - B10001, - B10001, - B11111, - B00000, - B00000 - }; //thanks joris - byte feedrate [8]={ - B11100, - B10000, - B11000, - B10111, - B00101, - B00110, - B00101, - B00000 - }; //thanks Sonny Mounicou - byte clock [8]={ - B00000, - B01110, - B10011, - B10101, - B10001, - B01110, - B00000, - B00000 - }; //thanks Sonny Mounicou - -#if defined(LCDI2C_TYPE_PCF8575) - lcd.begin(LCD_WIDTH, LCD_HEIGHT); - #ifdef LCD_I2C_PIN_BL - lcd.setBacklightPin(LCD_I2C_PIN_BL,POSITIVE); - lcd.setBacklight(HIGH); - #endif - -#elif defined(LCD_I2C_TYPE_MCP23017) - lcd.setMCPType(LTI_TYPE_MCP23017); - lcd.begin(LCD_WIDTH, LCD_HEIGHT); - lcd.setBacklight(0); //set all the LEDs off to begin with - -#elif defined(LCD_I2C_TYPE_MCP23008) - lcd.setMCPType(LTI_TYPE_MCP23008); - lcd.begin(LCD_WIDTH, LCD_HEIGHT); - -#else - lcd.begin(LCD_WIDTH, LCD_HEIGHT); -#endif - - lcd.createChar(LCD_STR_BEDTEMP[0], bedTemp); - lcd.createChar(LCD_STR_DEGREE[0], degree); - lcd.createChar(LCD_STR_THERMOMETER[0], thermometer); - lcd.createChar(LCD_STR_UPLEVEL[0], uplevel); - lcd.createChar(LCD_STR_REFRESH[0], refresh); - lcd.createChar(LCD_STR_FOLDER[0], folder); - lcd.createChar(LCD_STR_FEEDRATE[0], feedrate); - lcd.createChar(LCD_STR_CLOCK[0], clock); - lcd.clear(); -} -static void lcd_implementation_clear() -{ - lcd.clear(); -} -/* Arduino < 1.0.0 is missing a function to print PROGMEM strings, so we need to implement our own */ -static void lcd_printPGM(const char* str) -{ - char c; - while((c = pgm_read_byte(str++)) != '\0') - { - lcd.write(c); - } -} -/* -Possible status screens: -16x2 |0123456789012345| - |000/000 B000/000| - |Status line.....| - -16x4 |0123456789012345| - |000/000 B000/000| - |SD100% Z000.0| - |F100% T--:--| - |Status line.....| - -20x2 |01234567890123456789| - |T000/000D B000/000D | - |Status line.........| - -20x4 |01234567890123456789| - |T000/000D B000/000D | - |X+000.0 Y+000.0 Z+000.0| - |F100% SD100% T--:--| - |Status line.........| - -20x4 |01234567890123456789| - |T000/000D B000/000D | - |T000/000D Z000.0| - |F100% SD100% T--:--| - |Status line.........| -*/ -static void lcd_implementation_status_screen() -{ - int tHotend=int(degHotend(0) + 0.5); - int tTarget=int(degTargetHotend(0) + 0.5); - -#if LCD_WIDTH < 20 - lcd.setCursor(0, 0); - lcd.print(itostr3(tHotend)); - lcd.print('/'); - lcd.print(itostr3left(tTarget)); - -# if EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 - //If we have an 2nd extruder or heated bed, show that in the top right corner - lcd.setCursor(8, 0); -# if EXTRUDERS > 1 - tHotend = int(degHotend(1) + 0.5); - tTarget = int(degTargetHotend(1) + 0.5); - lcd.print(LCD_STR_THERMOMETER[0]); -# else//Heated bed - tHotend=int(degBed() + 0.5); - tTarget=int(degTargetBed() + 0.5); - lcd.print(LCD_STR_BEDTEMP[0]); -# endif - lcd.print(itostr3(tHotend)); - lcd.print('/'); - lcd.print(itostr3left(tTarget)); -# endif//EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 - -#else//LCD_WIDTH > 19 - lcd.setCursor(0, 0); - lcd.print(LCD_STR_THERMOMETER[0]); - lcd.print(itostr3(tHotend)); - lcd.print('/'); - lcd.print(itostr3left(tTarget)); - lcd_printPGM(PSTR(LCD_STR_DEGREE " ")); - if (tTarget < 10) - lcd.print(' '); - -# if EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 - //If we have an 2nd extruder or heated bed, show that in the top right corner - lcd.setCursor(10, 0); -# if EXTRUDERS > 1 - tHotend = int(degHotend(1) + 0.5); - tTarget = int(degTargetHotend(1) + 0.5); - lcd.print(LCD_STR_THERMOMETER[0]); -# else//Heated bed - tHotend=int(degBed() + 0.5); - tTarget=int(degTargetBed() + 0.5); - lcd.print(LCD_STR_BEDTEMP[0]); -# endif - lcd.print(itostr3(tHotend)); - lcd.print('/'); - lcd.print(itostr3left(tTarget)); - lcd_printPGM(PSTR(LCD_STR_DEGREE " ")); - if (tTarget < 10) - lcd.print(' '); -# endif//EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 -#endif//LCD_WIDTH > 19 - -#if LCD_HEIGHT > 2 -//Lines 2 for 4 line LCD -# if LCD_WIDTH < 20 -# ifdef SDSUPPORT - lcd.setCursor(0, 2); - lcd_printPGM(PSTR("SD")); - if (IS_SD_PRINTING) - lcd.print(itostr3(card.percentDone())); - else - lcd_printPGM(PSTR("---")); - lcd.print('%'); -# endif//SDSUPPORT -# else//LCD_WIDTH > 19 -# if EXTRUDERS > 1 && TEMP_SENSOR_BED != 0 - //If we both have a 2nd extruder and a heated bed, show the heated bed temp on the 2nd line on the left, as the first line is filled with extruder temps - tHotend=int(degBed() + 0.5); - tTarget=int(degTargetBed() + 0.5); - - lcd.setCursor(0, 1); - lcd.print(LCD_STR_BEDTEMP[0]); - lcd.print(itostr3(tHotend)); - lcd.print('/'); - lcd.print(itostr3left(tTarget)); - lcd_printPGM(PSTR(LCD_STR_DEGREE " ")); - if (tTarget < 10) - lcd.print(' '); -# else - lcd.setCursor(0,1); - lcd.print('X'); - lcd.print(ftostr3(current_position[X_AXIS])); - lcd_printPGM(PSTR(" Y")); - lcd.print(ftostr3(current_position[Y_AXIS])); -# endif//EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 -# endif//LCD_WIDTH > 19 - lcd.setCursor(LCD_WIDTH - 8, 1); - lcd.print('Z'); - lcd.print(ftostr32(current_position[Z_AXIS])); -#endif//LCD_HEIGHT > 2 - -#if LCD_HEIGHT > 3 - lcd.setCursor(0, 2); - lcd.print(LCD_STR_FEEDRATE[0]); - lcd.print(itostr3(feedmultiply)); - lcd.print('%'); -# if LCD_WIDTH > 19 -# ifdef SDSUPPORT - lcd.setCursor(7, 2); - lcd_printPGM(PSTR("SD")); - if (IS_SD_PRINTING) - lcd.print(itostr3(card.percentDone())); - else - lcd_printPGM(PSTR("---")); - lcd.print('%'); -# endif//SDSUPPORT -# endif//LCD_WIDTH > 19 - lcd.setCursor(LCD_WIDTH - 6, 2); - lcd.print(LCD_STR_CLOCK[0]); - if(starttime != 0) - { - uint16_t time = millis()/60000 - starttime/60000; - lcd.print(itostr2(time/60)); - lcd.print(':'); - lcd.print(itostr2(time%60)); - }else{ - lcd_printPGM(PSTR("--:--")); - } -#endif - - //Status message line on the last line - lcd.setCursor(0, LCD_HEIGHT - 1); - lcd.print(lcd_status_message); -} -static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, char pre_char, char post_char) -{ - char c; - //Use all characters in narrow LCDs - #if LCD_WIDTH < 20 - uint8_t n = LCD_WIDTH - 1 - 1; - #else - uint8_t n = LCD_WIDTH - 1 - 2; - #endif - lcd.setCursor(0, row); - lcd.print(pre_char); - while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) ) - { - lcd.print(c); - pstr++; - n--; - } - while(n--) - lcd.print(' '); - lcd.print(post_char); - lcd.print(' '); -} -static void lcd_implementation_drawmenu_setting_edit_generic(uint8_t row, const char* pstr, char pre_char, char* data) -{ - char c; - //Use all characters in narrow LCDs - #if LCD_WIDTH < 20 - uint8_t n = LCD_WIDTH - 1 - 1 - strlen(data); - #else - uint8_t n = LCD_WIDTH - 1 - 2 - strlen(data); - #endif - lcd.setCursor(0, row); - lcd.print(pre_char); - while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) ) - { - lcd.print(c); - pstr++; - n--; - } - lcd.print(':'); - while(n--) - lcd.print(' '); - lcd.print(data); -} -static void lcd_implementation_drawmenu_setting_edit_generic_P(uint8_t row, const char* pstr, char pre_char, const char* data) -{ - char c; - //Use all characters in narrow LCDs - #if LCD_WIDTH < 20 - uint8_t n = LCD_WIDTH - 1 - 1 - strlen_P(data); - #else - uint8_t n = LCD_WIDTH - 1 - 2 - strlen_P(data); - #endif - lcd.setCursor(0, row); - lcd.print(pre_char); - while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) ) - { - lcd.print(c); - pstr++; - n--; - } - lcd.print(':'); - while(n--) - lcd.print(' '); - lcd_printPGM(data); -} -#define lcd_implementation_drawmenu_setting_edit_int3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_int3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float32_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float32(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float52_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float52(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float51_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float51(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data))) -#define lcd_implementation_drawmenu_setting_edit_long5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_long5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_bool_selected(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) -#define lcd_implementation_drawmenu_setting_edit_bool(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) - -//Add version for callback functions -#define lcd_implementation_drawmenu_setting_edit_callback_int3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_int3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float32_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float32(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float52_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float52(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float51_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float51(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_long5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_long5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_bool_selected(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) -#define lcd_implementation_drawmenu_setting_edit_callback_bool(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) - - -void lcd_implementation_drawedit(const char* pstr, char* value) -{ - lcd.setCursor(1, 1); - lcd_printPGM(pstr); - lcd.print(':'); - #if LCD_WIDTH < 20 - lcd.setCursor(LCD_WIDTH - strlen(value), 1); - #else - lcd.setCursor(LCD_WIDTH -1 - strlen(value), 1); - #endif - lcd.print(value); -} -static void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename) -{ - char c; - uint8_t n = LCD_WIDTH - 1; - lcd.setCursor(0, row); - lcd.print('>'); - if (longFilename[0] != '\0') - { - filename = longFilename; - longFilename[LCD_WIDTH-1] = '\0'; - } - while( ((c = *filename) != '\0') && (n>0) ) - { - lcd.print(c); - filename++; - n--; - } - while(n--) - lcd.print(' '); -} -static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* pstr, const char* filename, char* longFilename) -{ - char c; - uint8_t n = LCD_WIDTH - 1; - lcd.setCursor(0, row); - lcd.print(' '); - if (longFilename[0] != '\0') - { - filename = longFilename; - longFilename[LCD_WIDTH-1] = '\0'; - } - while( ((c = *filename) != '\0') && (n>0) ) - { - lcd.print(c); - filename++; - n--; - } - while(n--) - lcd.print(' '); -} -static void lcd_implementation_drawmenu_sddirectory_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename) -{ - char c; - uint8_t n = LCD_WIDTH - 2; - lcd.setCursor(0, row); - lcd.print('>'); - lcd.print(LCD_STR_FOLDER[0]); - if (longFilename[0] != '\0') - { - filename = longFilename; - longFilename[LCD_WIDTH-2] = '\0'; - } - while( ((c = *filename) != '\0') && (n>0) ) - { - lcd.print(c); - filename++; - n--; - } - while(n--) - lcd.print(' '); -} -static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* pstr, const char* filename, char* longFilename) -{ - char c; - uint8_t n = LCD_WIDTH - 2; - lcd.setCursor(0, row); - lcd.print(' '); - lcd.print(LCD_STR_FOLDER[0]); - if (longFilename[0] != '\0') - { - filename = longFilename; - longFilename[LCD_WIDTH-2] = '\0'; - } - while( ((c = *filename) != '\0') && (n>0) ) - { - lcd.print(c); - filename++; - n--; - } - while(n--) - lcd.print(' '); -} -#define lcd_implementation_drawmenu_back_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0]) -#define lcd_implementation_drawmenu_back(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_UPLEVEL[0]) -#define lcd_implementation_drawmenu_submenu_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', LCD_STR_ARROW_RIGHT[0]) -#define lcd_implementation_drawmenu_submenu(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_ARROW_RIGHT[0]) -#define lcd_implementation_drawmenu_gcode_selected(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ') -#define lcd_implementation_drawmenu_gcode(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ') -#define lcd_implementation_drawmenu_function_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ') -#define lcd_implementation_drawmenu_function(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ') - -static void lcd_implementation_quick_feedback() -{ -#ifdef LCD_USE_I2C_BUZZER - lcd.buzz(60,1000/6); -#elif defined(BEEPER) && BEEPER > -1 - SET_OUTPUT(BEEPER); - for(int8_t i=0;i<10;i++) - { - WRITE(BEEPER,HIGH); - delay(3); - WRITE(BEEPER,LOW); - delay(3); - } -#endif -} - -#ifdef LCD_HAS_STATUS_INDICATORS -static void lcd_implementation_update_indicators() -{ - #if defined(LCD_I2C_PANELOLU2) || defined(LCD_I2C_VIKI) - //set the LEDS - referred to as backlights by the LiquidTWI2 library - static uint8_t ledsprev = 0; - uint8_t leds = 0; - if (target_temperature_bed > 0) leds |= LED_A; - if (target_temperature[0] > 0) leds |= LED_B; - if (fanSpeed) leds |= LED_C; - #if EXTRUDERS > 1 - if (target_temperature[1] > 0) leds |= LED_C; - #endif - if (leds != ledsprev) { - lcd.setBacklight(leds); - ledsprev = leds; - } - #endif -} -#endif - -#ifdef LCD_HAS_SLOW_BUTTONS -static uint8_t lcd_implementation_read_slow_buttons() -{ - #ifdef LCD_I2C_TYPE_MCP23017 - // Reading these buttons this is likely to be too slow to call inside interrupt context - // so they are called during normal lcd_update - return lcd.readButtons() << B_I2C_BTN_OFFSET; - #endif -} -#endif - -#endif//ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H +#ifndef ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H +#define ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H + +/** +* Implementation of the LCD display routines for a hitachi HD44780 display. These are common LCD character displays. +* When selecting the rusian language, a slightly different LCD implementation is used to handle UTF8 characters. +**/ + +#ifndef REPRAPWORLD_KEYPAD +extern volatile uint8_t buttons; //the last checked buttons in a bit array. +#else +extern volatile uint16_t buttons; //an extended version of the last checked buttons in a bit array. +#endif + +//////////////////////////////////// +// Setup button and encode mappings for each panel (into 'buttons' variable) +// +// This is just to map common functions (across different panels) onto the same +// macro name. The mapping is independent of whether the button is directly connected or +// via a shift/i2c register. + +#ifdef ULTIPANEL +// All Ultipanels might have an encoder - so this is always be mapped onto first two bits +#define BLEN_B 1 +#define BLEN_A 0 + +#define EN_B (1< -1 + // encoder click is directly connected + #define BLEN_C 2 + #define EN_C (1< -1 + // the pause/stop/restart button is connected to BTN_ENC when used + #define B_ST (EN_C) // Map the pause/stop/resume button into its normalized functional name + #define LCD_CLICKED (buttons&(B_MI|B_RI|B_ST)) // pause/stop button also acts as click until we implement proper pause/stop. + #else + #define LCD_CLICKED (buttons&(B_MI|B_RI)) + #endif + + // I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update + #define LCD_HAS_SLOW_BUTTONS + +#elif defined(LCD_I2C_PANELOLU2) + // encoder click can be read through I2C if not directly connected + #if BTN_ENC <= 0 + #define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C) + + #define B_MI (PANELOLU2_ENCODER_C< + #include + #include + #define LCD_CLASS LiquidCrystal_I2C + LCD_CLASS lcd(LCD_I2C_ADDRESS,LCD_I2C_PIN_EN,LCD_I2C_PIN_RW,LCD_I2C_PIN_RS,LCD_I2C_PIN_D4,LCD_I2C_PIN_D5,LCD_I2C_PIN_D6,LCD_I2C_PIN_D7); + +#elif defined(LCD_I2C_TYPE_MCP23017) + //for the LED indicators (which maybe mapped to different things in lcd_implementation_update_indicators()) + #define LED_A 0x04 //100 + #define LED_B 0x02 //010 + #define LED_C 0x01 //001 + + #define LCD_HAS_STATUS_INDICATORS + + #include + #include + #define LCD_CLASS LiquidTWI2 + LCD_CLASS lcd(LCD_I2C_ADDRESS); + +#elif defined(LCD_I2C_TYPE_MCP23008) + #include + #include + #define LCD_CLASS LiquidTWI2 + LCD_CLASS lcd(LCD_I2C_ADDRESS); + +#elif defined(LCD_I2C_TYPE_PCA8574) + #include + #define LCD_CLASS LiquidCrystal_I2C + LCD_CLASS lcd(LCD_I2C_ADDRESS, LCD_WIDTH, LCD_HEIGHT); + +#else + // Standard directly connected LCD implementations + #if LANGUAGE_CHOICE == 6 + #include "LiquidCrystalRus.h" + #define LCD_CLASS LiquidCrystalRus + #else + #include + #define LCD_CLASS LiquidCrystal + #endif + LCD_CLASS lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5,LCD_PINS_D6,LCD_PINS_D7); //RS,Enable,D4,D5,D6,D7 +#endif + +/* Custom characters defined in the first 8 characters of the LCD */ +#define LCD_STR_BEDTEMP "\x00" +#define LCD_STR_DEGREE "\x01" +#define LCD_STR_THERMOMETER "\x02" +#define LCD_STR_UPLEVEL "\x03" +#define LCD_STR_REFRESH "\x04" +#define LCD_STR_FOLDER "\x05" +#define LCD_STR_FEEDRATE "\x06" +#define LCD_STR_CLOCK "\x07" +#define LCD_STR_ARROW_RIGHT "\x7E" /* from the default character set */ + +static void lcd_implementation_init() +{ + byte bedTemp[8] = + { + B00000, + B11111, + B10101, + B10001, + B10101, + B11111, + B00000, + B00000 + }; //thanks Sonny Mounicou + byte degree[8] = + { + B01100, + B10010, + B10010, + B01100, + B00000, + B00000, + B00000, + B00000 + }; + byte thermometer[8] = + { + B00100, + B01010, + B01010, + B01010, + B01010, + B10001, + B10001, + B01110 + }; + byte uplevel[8]={ + B00100, + B01110, + B11111, + B00100, + B11100, + B00000, + B00000, + B00000 + }; //thanks joris + byte refresh[8]={ + B00000, + B00110, + B11001, + B11000, + B00011, + B10011, + B01100, + B00000, + }; //thanks joris + byte folder [8]={ + B00000, + B11100, + B11111, + B10001, + B10001, + B11111, + B00000, + B00000 + }; //thanks joris + byte feedrate [8]={ + B11100, + B10000, + B11000, + B10111, + B00101, + B00110, + B00101, + B00000 + }; //thanks Sonny Mounicou + byte clock [8]={ + B00000, + B01110, + B10011, + B10101, + B10001, + B01110, + B00000, + B00000 + }; //thanks Sonny Mounicou + +#if defined(LCDI2C_TYPE_PCF8575) + lcd.begin(LCD_WIDTH, LCD_HEIGHT); + #ifdef LCD_I2C_PIN_BL + lcd.setBacklightPin(LCD_I2C_PIN_BL,POSITIVE); + lcd.setBacklight(HIGH); + #endif + +#elif defined(LCD_I2C_TYPE_MCP23017) + lcd.setMCPType(LTI_TYPE_MCP23017); + lcd.begin(LCD_WIDTH, LCD_HEIGHT); + lcd.setBacklight(0); //set all the LEDs off to begin with + +#elif defined(LCD_I2C_TYPE_MCP23008) + lcd.setMCPType(LTI_TYPE_MCP23008); + lcd.begin(LCD_WIDTH, LCD_HEIGHT); + +#elif defined(LCD_I2C_TYPE_PCA8574) + lcd.init(); + lcd.backlight(); + +#else + lcd.begin(LCD_WIDTH, LCD_HEIGHT); +#endif + + lcd.createChar(LCD_STR_BEDTEMP[0], bedTemp); + lcd.createChar(LCD_STR_DEGREE[0], degree); + lcd.createChar(LCD_STR_THERMOMETER[0], thermometer); + lcd.createChar(LCD_STR_UPLEVEL[0], uplevel); + lcd.createChar(LCD_STR_REFRESH[0], refresh); + lcd.createChar(LCD_STR_FOLDER[0], folder); + lcd.createChar(LCD_STR_FEEDRATE[0], feedrate); + lcd.createChar(LCD_STR_CLOCK[0], clock); + lcd.clear(); +} +static void lcd_implementation_clear() +{ + lcd.clear(); +} +/* Arduino < 1.0.0 is missing a function to print PROGMEM strings, so we need to implement our own */ +static void lcd_printPGM(const char* str) +{ + char c; + while((c = pgm_read_byte(str++)) != '\0') + { + lcd.write(c); + } +} +/* +Possible status screens: +16x2 |0123456789012345| + |000/000 B000/000| + |Status line.....| + +16x4 |0123456789012345| + |000/000 B000/000| + |SD100% Z000.0| + |F100% T--:--| + |Status line.....| + +20x2 |01234567890123456789| + |T000/000D B000/000D | + |Status line.........| + +20x4 |01234567890123456789| + |T000/000D B000/000D | + |X+000.0 Y+000.0 Z+000.0| + |F100% SD100% T--:--| + |Status line.........| + +20x4 |01234567890123456789| + |T000/000D B000/000D | + |T000/000D Z000.0| + |F100% SD100% T--:--| + |Status line.........| +*/ +static void lcd_implementation_status_screen() +{ + int tHotend=int(degHotend(0) + 0.5); + int tTarget=int(degTargetHotend(0) + 0.5); + +#if LCD_WIDTH < 20 + lcd.setCursor(0, 0); + lcd.print(itostr3(tHotend)); + lcd.print('/'); + lcd.print(itostr3left(tTarget)); + +# if EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 + //If we have an 2nd extruder or heated bed, show that in the top right corner + lcd.setCursor(8, 0); +# if EXTRUDERS > 1 + tHotend = int(degHotend(1) + 0.5); + tTarget = int(degTargetHotend(1) + 0.5); + lcd.print(LCD_STR_THERMOMETER[0]); +# else//Heated bed + tHotend=int(degBed() + 0.5); + tTarget=int(degTargetBed() + 0.5); + lcd.print(LCD_STR_BEDTEMP[0]); +# endif + lcd.print(itostr3(tHotend)); + lcd.print('/'); + lcd.print(itostr3left(tTarget)); +# endif//EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 + +#else//LCD_WIDTH > 19 + lcd.setCursor(0, 0); + lcd.print(LCD_STR_THERMOMETER[0]); + lcd.print(itostr3(tHotend)); + lcd.print('/'); + lcd.print(itostr3left(tTarget)); + lcd_printPGM(PSTR(LCD_STR_DEGREE " ")); + if (tTarget < 10) + lcd.print(' '); + +# if EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 + //If we have an 2nd extruder or heated bed, show that in the top right corner + lcd.setCursor(10, 0); +# if EXTRUDERS > 1 + tHotend = int(degHotend(1) + 0.5); + tTarget = int(degTargetHotend(1) + 0.5); + lcd.print(LCD_STR_THERMOMETER[0]); +# else//Heated bed + tHotend=int(degBed() + 0.5); + tTarget=int(degTargetBed() + 0.5); + lcd.print(LCD_STR_BEDTEMP[0]); +# endif + lcd.print(itostr3(tHotend)); + lcd.print('/'); + lcd.print(itostr3left(tTarget)); + lcd_printPGM(PSTR(LCD_STR_DEGREE " ")); + if (tTarget < 10) + lcd.print(' '); +# endif//EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 +#endif//LCD_WIDTH > 19 + +#if LCD_HEIGHT > 2 +//Lines 2 for 4 line LCD +# if LCD_WIDTH < 20 +# ifdef SDSUPPORT + lcd.setCursor(0, 2); + lcd_printPGM(PSTR("SD")); + if (IS_SD_PRINTING) + lcd.print(itostr3(card.percentDone())); + else + lcd_printPGM(PSTR("---")); + lcd.print('%'); +# endif//SDSUPPORT +# else//LCD_WIDTH > 19 +# if EXTRUDERS > 1 && TEMP_SENSOR_BED != 0 + //If we both have a 2nd extruder and a heated bed, show the heated bed temp on the 2nd line on the left, as the first line is filled with extruder temps + tHotend=int(degBed() + 0.5); + tTarget=int(degTargetBed() + 0.5); + + lcd.setCursor(0, 1); + lcd.print(LCD_STR_BEDTEMP[0]); + lcd.print(itostr3(tHotend)); + lcd.print('/'); + lcd.print(itostr3left(tTarget)); + lcd_printPGM(PSTR(LCD_STR_DEGREE " ")); + if (tTarget < 10) + lcd.print(' '); +# else + lcd.setCursor(0,1); + lcd.print('X'); + lcd.print(ftostr3(current_position[X_AXIS])); + lcd_printPGM(PSTR(" Y")); + lcd.print(ftostr3(current_position[Y_AXIS])); +# endif//EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 +# endif//LCD_WIDTH > 19 + lcd.setCursor(LCD_WIDTH - 8, 1); + lcd.print('Z'); + lcd.print(ftostr32(current_position[Z_AXIS])); +#endif//LCD_HEIGHT > 2 + +#if LCD_HEIGHT > 3 + lcd.setCursor(0, 2); + lcd.print(LCD_STR_FEEDRATE[0]); + lcd.print(itostr3(feedmultiply)); + lcd.print('%'); +# if LCD_WIDTH > 19 +# ifdef SDSUPPORT + lcd.setCursor(7, 2); + lcd_printPGM(PSTR("SD")); + if (IS_SD_PRINTING) + lcd.print(itostr3(card.percentDone())); + else + lcd_printPGM(PSTR("---")); + lcd.print('%'); +# endif//SDSUPPORT +# endif//LCD_WIDTH > 19 + lcd.setCursor(LCD_WIDTH - 6, 2); + lcd.print(LCD_STR_CLOCK[0]); + if(starttime != 0) + { + uint16_t time = millis()/60000 - starttime/60000; + lcd.print(itostr2(time/60)); + lcd.print(':'); + lcd.print(itostr2(time%60)); + }else{ + lcd_printPGM(PSTR("--:--")); + } +#endif + + //Status message line on the last line + lcd.setCursor(0, LCD_HEIGHT - 1); + lcd.print(lcd_status_message); +} +static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, char pre_char, char post_char) +{ + char c; + //Use all characters in narrow LCDs + #if LCD_WIDTH < 20 + uint8_t n = LCD_WIDTH - 1 - 1; + #else + uint8_t n = LCD_WIDTH - 1 - 2; + #endif + lcd.setCursor(0, row); + lcd.print(pre_char); + while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) ) + { + lcd.print(c); + pstr++; + n--; + } + while(n--) + lcd.print(' '); + lcd.print(post_char); + lcd.print(' '); +} +static void lcd_implementation_drawmenu_setting_edit_generic(uint8_t row, const char* pstr, char pre_char, char* data) +{ + char c; + //Use all characters in narrow LCDs + #if LCD_WIDTH < 20 + uint8_t n = LCD_WIDTH - 1 - 1 - strlen(data); + #else + uint8_t n = LCD_WIDTH - 1 - 2 - strlen(data); + #endif + lcd.setCursor(0, row); + lcd.print(pre_char); + while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) ) + { + lcd.print(c); + pstr++; + n--; + } + lcd.print(':'); + while(n--) + lcd.print(' '); + lcd.print(data); +} +static void lcd_implementation_drawmenu_setting_edit_generic_P(uint8_t row, const char* pstr, char pre_char, const char* data) +{ + char c; + //Use all characters in narrow LCDs + #if LCD_WIDTH < 20 + uint8_t n = LCD_WIDTH - 1 - 1 - strlen_P(data); + #else + uint8_t n = LCD_WIDTH - 1 - 2 - strlen_P(data); + #endif + lcd.setCursor(0, row); + lcd.print(pre_char); + while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) ) + { + lcd.print(c); + pstr++; + n--; + } + lcd.print(':'); + while(n--) + lcd.print(' '); + lcd_printPGM(data); +} +#define lcd_implementation_drawmenu_setting_edit_int3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_int3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float32_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float32(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float52_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float52(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float51_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float51(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data))) +#define lcd_implementation_drawmenu_setting_edit_long5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_long5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_bool_selected(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) +#define lcd_implementation_drawmenu_setting_edit_bool(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) + +//Add version for callback functions +#define lcd_implementation_drawmenu_setting_edit_callback_int3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_int3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float32_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float32(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float52_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float52(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float51_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float51(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_long5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_long5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_bool_selected(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) +#define lcd_implementation_drawmenu_setting_edit_callback_bool(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) + + +void lcd_implementation_drawedit(const char* pstr, char* value) +{ + lcd.setCursor(1, 1); + lcd_printPGM(pstr); + lcd.print(':'); + #if LCD_WIDTH < 20 + lcd.setCursor(LCD_WIDTH - strlen(value), 1); + #else + lcd.setCursor(LCD_WIDTH -1 - strlen(value), 1); + #endif + lcd.print(value); +} +static void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename) +{ + char c; + uint8_t n = LCD_WIDTH - 1; + lcd.setCursor(0, row); + lcd.print('>'); + if (longFilename[0] != '\0') + { + filename = longFilename; + longFilename[LCD_WIDTH-1] = '\0'; + } + while( ((c = *filename) != '\0') && (n>0) ) + { + lcd.print(c); + filename++; + n--; + } + while(n--) + lcd.print(' '); +} +static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* pstr, const char* filename, char* longFilename) +{ + char c; + uint8_t n = LCD_WIDTH - 1; + lcd.setCursor(0, row); + lcd.print(' '); + if (longFilename[0] != '\0') + { + filename = longFilename; + longFilename[LCD_WIDTH-1] = '\0'; + } + while( ((c = *filename) != '\0') && (n>0) ) + { + lcd.print(c); + filename++; + n--; + } + while(n--) + lcd.print(' '); +} +static void lcd_implementation_drawmenu_sddirectory_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename) +{ + char c; + uint8_t n = LCD_WIDTH - 2; + lcd.setCursor(0, row); + lcd.print('>'); + lcd.print(LCD_STR_FOLDER[0]); + if (longFilename[0] != '\0') + { + filename = longFilename; + longFilename[LCD_WIDTH-2] = '\0'; + } + while( ((c = *filename) != '\0') && (n>0) ) + { + lcd.print(c); + filename++; + n--; + } + while(n--) + lcd.print(' '); +} +static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* pstr, const char* filename, char* longFilename) +{ + char c; + uint8_t n = LCD_WIDTH - 2; + lcd.setCursor(0, row); + lcd.print(' '); + lcd.print(LCD_STR_FOLDER[0]); + if (longFilename[0] != '\0') + { + filename = longFilename; + longFilename[LCD_WIDTH-2] = '\0'; + } + while( ((c = *filename) != '\0') && (n>0) ) + { + lcd.print(c); + filename++; + n--; + } + while(n--) + lcd.print(' '); +} +#define lcd_implementation_drawmenu_back_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0]) +#define lcd_implementation_drawmenu_back(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_UPLEVEL[0]) +#define lcd_implementation_drawmenu_submenu_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', LCD_STR_ARROW_RIGHT[0]) +#define lcd_implementation_drawmenu_submenu(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_ARROW_RIGHT[0]) +#define lcd_implementation_drawmenu_gcode_selected(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ') +#define lcd_implementation_drawmenu_gcode(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ') +#define lcd_implementation_drawmenu_function_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ') +#define lcd_implementation_drawmenu_function(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ') + +static void lcd_implementation_quick_feedback() +{ +#ifdef LCD_USE_I2C_BUZZER + lcd.buzz(60,1000/6); +#elif defined(BEEPER) && BEEPER > -1 + SET_OUTPUT(BEEPER); + for(int8_t i=0;i<10;i++) + { + WRITE(BEEPER,HIGH); + delay(3); + WRITE(BEEPER,LOW); + delay(3); + } +#endif +} + +#ifdef LCD_HAS_STATUS_INDICATORS +static void lcd_implementation_update_indicators() +{ + #if defined(LCD_I2C_PANELOLU2) || defined(LCD_I2C_VIKI) + //set the LEDS - referred to as backlights by the LiquidTWI2 library + static uint8_t ledsprev = 0; + uint8_t leds = 0; + if (target_temperature_bed > 0) leds |= LED_A; + if (target_temperature[0] > 0) leds |= LED_B; + if (fanSpeed) leds |= LED_C; + #if EXTRUDERS > 1 + if (target_temperature[1] > 0) leds |= LED_C; + #endif + if (leds != ledsprev) { + lcd.setBacklight(leds); + ledsprev = leds; + } + #endif +} +#endif + +#ifdef LCD_HAS_SLOW_BUTTONS +static uint8_t lcd_implementation_read_slow_buttons() +{ + #ifdef LCD_I2C_TYPE_MCP23017 + // Reading these buttons this is likely to be too slow to call inside interrupt context + // so they are called during normal lcd_update + return lcd.readButtons() << B_I2C_BTN_OFFSET; + #endif +} +#endif + +#endif//ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H