diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 1fe970a660c6..d2a1db9dc58f 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -50,6 +50,7 @@ // 35 = RAMPS 1.3 / 1.4 (Power outputs: Extruder, Fan, Fan) // 36 = RAMPS 1.3 / 1.4 (Power outputs: Extruder0, Extruder1, Fan) // 4 = Duemilanove w/ ATMega328P pin assignment +// 42 = Invent-A-Part RigidBoard // 5 = Gen6 // 51 = Gen6 deluxe // 6 = Sanguinololu < 1.2 @@ -148,7 +149,7 @@ #define TEMP_SENSOR_2 0 #define TEMP_SENSOR_BED 0 -// This makes temp sensor 1 a redundant sensor for sensor 0. If the temperatures difference between these sensors is to high the print will be aborted. +// This makes temp sensor 1 a redundant sensor for sensor 0. If the temperatures difference between these sensors is too high the print will be aborted. //#define TEMP_SENSOR_1_AS_REDUNDANT #define MAX_REDUNDANT_TEMP_SENSOR_DIFF 10 @@ -211,6 +212,11 @@ // #define DEFAULT_Kp 63.0 // #define DEFAULT_Ki 2.25 // #define DEFAULT_Kd 440 + +// RigidBot redesigned hot end +// #define DEFAULT_Kp 14.36 +// #define DEFAULT_Ki 0.66 +// #define DEFAULT_Kd 79.25 #endif // PIDTEMP // Bed Temperature Control @@ -246,6 +252,10 @@ // #define DEFAULT_bedKi 1.41 // #define DEFAULT_bedKd 1675.16 +//RigidBot, from pid autotune +// #define DEFAULT_bedKp 355 +// #define DEFAULT_bedKi 66.5 +// #define DEFAULT_bedKd 480 // FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles. #endif // PIDTEMPBED @@ -317,7 +327,7 @@ your extruder heater takes 2 minutes to hit the target on heating. // #define ENDSTOPPULLUP_YMIN // #define ENDSTOPPULLUP_ZMIN #endif - + #ifdef ENDSTOPPULLUPS #define ENDSTOPPULLUP_XMAX #define ENDSTOPPULLUP_YMAX @@ -326,7 +336,7 @@ your extruder heater takes 2 minutes to hit the target on heating. #define ENDSTOPPULLUP_YMIN #define ENDSTOPPULLUP_ZMIN #endif - + // The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. const bool X_MIN_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop. const bool Y_MIN_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop. @@ -336,12 +346,12 @@ const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop. //#define DISABLE_MAX_ENDSTOPS //#define DISABLE_MIN_ENDSTOPS - + // Disable max endstops for compatibility with endstop checking routine #if defined(COREXY) && !defined(DISABLE_MAX_ENDSTOPS) #define DISABLE_MAX_ENDSTOPS #endif - + // For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 #define X_ENABLE_ON 0 #define Y_ENABLE_ON 0 @@ -379,9 +389,48 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of #define Z_MAX_POS 200 #define Z_MIN_POS 0 +// The position of the homing switches +//#define MANUAL_HOME_POSITIONS // If defined, MANUAL_*_HOME_POS below will be used +//#define BED_CENTER_AT_0_0 // If defined, the center of the bed is at (X=0, Y=0) + +//Manual homing switch locations: +// For deltabots this means top and center of the Cartesian print volume. +#define MANUAL_X_HOME_POS 0 +#define MANUAL_Y_HOME_POS 0 +#define MANUAL_Z_HOME_POS 0 +//#define MANUAL_Z_HOME_POS 402 // For delta: Distance between nozzle and print surface after homing. + +//// MOVEMENT SETTINGS +#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E +#define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0} // set the homing speeds (mm/min) + +// default settings + +#define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200.0*8/3,760*1.1} // default steps per unit for Ultimaker +#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 25} // (mm/sec) +#define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for Skeinforge 40+, for older versions raise them a lot. + +#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_RETRACT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for retracts + +// Offset of the extruders (uncomment if using more than one and relying on firmware to position when changing). +// The offset has to be X=0, Y=0 for the extruder 0 hotend (default extruder). +// For the other hotends it is their distance from the extruder 0 hotend. +// #define EXTRUDER_OFFSET_X {0.0, 20.00} // (in mm) for each extruder, offset of the hotend on the X axis +// #define EXTRUDER_OFFSET_Y {0.0, 5.00} // (in mm) for each extruder, offset of the hotend on the Y axis + +// The speed change that does not require acceleration (i.e. the software might assume it can be done instantaneously) +#define DEFAULT_XYJERK 20.0 // (mm/sec) +#define DEFAULT_ZJERK 0.4 // (mm/sec) +#define DEFAULT_EJERK 5.0 // (mm/sec) + #define X_MAX_LENGTH (X_MAX_POS - X_MIN_POS) #define Y_MAX_LENGTH (Y_MAX_POS - Y_MIN_POS) #define Z_MAX_LENGTH (Z_MAX_POS - Z_MIN_POS) + +#define X_CENTER_POS ((X_MIN_POS + X_MAX_POS) / 2) +#define Y_CENTER_POS ((Y_MIN_POS + Y_MAX_POS) / 2) + //============================= Bed Auto Leveling =========================== //#define ENABLE_AUTO_BED_LEVELING // Delete the comment to enable (remove // at the start of the line) @@ -476,45 +525,13 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of #endif // ENABLE_AUTO_BED_LEVELING -// The position of the homing switches -//#define MANUAL_HOME_POSITIONS // If defined, MANUAL_*_HOME_POS below will be used -//#define BED_CENTER_AT_0_0 // If defined, the center of the bed is at (X=0, Y=0) - -//Manual homing switch locations: -// For deltabots this means top and center of the Cartesian print volume. -#define MANUAL_X_HOME_POS 0 -#define MANUAL_Y_HOME_POS 0 -#define MANUAL_Z_HOME_POS 0 -//#define MANUAL_Z_HOME_POS 402 // For delta: Distance between nozzle and print surface after homing. - -//// MOVEMENT SETTINGS -#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -#define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0} // set the homing speeds (mm/min) - -// default settings - -#define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200.0*8/3,760*1.1} // default steps per unit for Ultimaker -#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 25} // (mm/sec) -#define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for Skeinforge 40+, for older versions raise them a lot. - -#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves -#define DEFAULT_RETRACT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for retracts - -// Offset of the extruders (uncomment if using more than one and relying on firmware to position when changing). -// The offset has to be X=0, Y=0 for the extruder 0 hotend (default extruder). -// For the other hotends it is their distance from the extruder 0 hotend. -// #define EXTRUDER_OFFSET_X {0.0, 20.00} // (in mm) for each extruder, offset of the hotend on the X axis -// #define EXTRUDER_OFFSET_Y {0.0, 5.00} // (in mm) for each extruder, offset of the hotend on the Y axis - -// The speed change that does not require acceleration (i.e. the software might assume it can be done instantaneously) -#define DEFAULT_XYJERK 20.0 // (mm/sec) -#define DEFAULT_ZJERK 0.4 // (mm/sec) -#define DEFAULT_EJERK 5.0 // (mm/sec) - //=========================================================================== //=============================Additional Features=========================== //=========================================================================== +// Disable stepper drivers until voltage has stabilized +//#define STEPPER_RESET_FIX + // Custom M code points #define CUSTOM_M_CODES #ifdef CUSTOM_M_CODES @@ -529,11 +546,18 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of // M500 - stores parameters in EEPROM // M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). // M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. -//define this to enable EEPROM support +// +// Define this to enable EEPROM support //#define EEPROM_SETTINGS -//to disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out: +// +// To disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out: // please keep turned on if you can. //#define EEPROM_CHITCHAT +// +// Define EEPROM_OVERWRITE to have EEPROM overwritten with firmware-compiled defaults any time the firmware +// build date+time changes (default behavior is to overwrite EEPROM only when EEPROM_VERSION in +// ConfigurationStore.cpp changes +//#define EEPROM_OVERWRITE // Preheat Constants #define PLA_PREHEAT_HOTEND_TEMP 180 @@ -585,6 +609,10 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of // REMEMBER TO INSTALL LiquidCrystal_I2C.h in your ARUDINO library folder: https://github.com/kiyoshigawa/LiquidCrystal_I2C //#define RA_CONTROL_PANEL +// RigidBot Panel V1.0 +// http://www.inventapart.com/ +//#define RIGIDPANEL + //automatic expansion #if defined (MAKRPANEL) #define DOGLCD @@ -616,6 +644,16 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of #define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander #endif +#if defined(RIGIDPANEL) + #define ULTIPANEL + #define SDSPEED SPI_EIGHTH_SPEED // full/half/quarter/sixteenth, or 0-6 (0 = full speed) + #define SDSUPPORT + #define ULTRA_LCD + #define LCD_WIDTH 20 + #define LCD_HEIGHT 4 + #define USB_LCD // Get USB-centric strings from language.h +#endif + //I2C PANELS //#define LCD_I2C_SAINSMART_YWROBOT diff --git a/Marlin/LiquidCrystalFast_Mod.cpp b/Marlin/LiquidCrystalFast_Mod.cpp new file mode 100755 index 000000000000..d3733780abd1 --- /dev/null +++ b/Marlin/LiquidCrystalFast_Mod.cpp @@ -0,0 +1,443 @@ +/* + * LiquidCrystalFast.cpp, version 1.1 + * + Copyright (c) 2010 John Raines + + Minor changes by Paul Stoffregen , Copyright 2011 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + */ + +//#include "LiquidCrystalFast.h" +#include "LiquidCrystalFast_Mod.h" +#include +#include +#include +#include "Arduino.h" +//#include +//#include + + +/******************************************/ +/** hardware initialization **/ +/******************************************/ + +// When the display powers up, it is configured as follows: +// +// 1. Display clear +// 2. Function set: +// DL = 1; 8-bit interface data +// N = 0; 1-line display +// F = 0; 5x8 dot character font +// 3. Display on/off control: +// D = 0; Display off +// C = 0; Cursor off +// B = 0; Blinking off +// 4. Entry mode set: +// I/D = 1; Increment by 1 +// S = 0; No shift +// +// Note, however, that resetting the Arduino doesn't reset the LCD, so we +// can't assume that its in that state when a sketch starts (and the +// LiquidCrystalFast constructor is called). + +void LiquidCrystalFast::init(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t en2, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) +{ + _rs_pin = rs; + _rw_pin = 255; + _enable_pin = enable; + _en2 = en2; + _chip = 0; + _scroll_count = 0; //to fix the bug if we scroll and then setCursor w/o home() or clear() + _x = 0; + _y = 0; + + _setCursFlag = 0; + _direction = LCD_Right; + + _data_pins[0] = d0; + _data_pins[1] = d1; + _data_pins[2] = d2; + _data_pins[3] = d3; + + pinMode(d0, OUTPUT); //set data pin modes + pinMode(d1, OUTPUT); + pinMode(d2, OUTPUT); + pinMode(d3, OUTPUT); + + row_offsets[0] = 00; // DDRAM addresses inside the HD44780 are strange: 0-nColumns-1 on line 0 + row_offsets[1] = 0x40; // 64-(63+nColumns) for line 1 + row_offsets[2] = 0x14; // 20- (19+nColumns) for line 2 --- NOTHING FROM 40-63 ! + row_offsets[3] = 0x54; // 84 - (83+nColumns) for line 3 -- so 80 characters tops out at #103 ! + + pinMode(_rs_pin, OUTPUT); + // we can save 1 pin by not using RW. Indicate by passing 255 instead of pin# + if (rw != 255) { + pinMode(rw, OUTPUT); //once in init does it + digitalWrite(rw,LOW); //write data to LCD mode + } + pinMode(_enable_pin, OUTPUT); + if( en2 != 255) pinMode(en2,OUTPUT); //4X40 LCD + + begin(20, 1); + _rw_pin = rw; //the game to initialize the 40x4 is over +} + +void LiquidCrystalFast::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) +{ + numcols=_numcols=cols; //there is an implied lack of trust; the private version can't be munged up by the user. + numlines=_numlines=lines; + row_offsets[2] = cols + row_offsets[0]; //should autoadjust for 16/20 or whatever columns now + row_offsets[3] = cols + row_offsets[1]; + begin2( cols, lines, dotsize, _enable_pin); + + if (_en2 != 255) { //if we were called with a 2nd enable line i.e. 4x40 LCD + row_offsets[2] = 0; + row_offsets[3] = 0x40; //each line gets its own little 40 char section of DDRAM--would be fine if there were a 4x32, I suppose + _chip = 2; + begin2( cols, lines, dotsize,_en2);//initialize the second HD44780 chip + } +} + +void LiquidCrystalFast::begin2(uint8_t cols, uint8_t lines, uint8_t dotsize, uint8_t enable) +{ + uint8_t displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; + + if (lines > 1) { + displayfunction |= LCD_2LINE; + } + + // for some 1 line displays you can select a 10 pixel high font + if ((dotsize != 0) && (lines == 1)) { + displayfunction |= LCD_5x10DOTS; + } + + // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! + // according to datasheet, we need at least 40ms after power rises above 2.7V + // before sending commands. Arduino can turn on way before 4.5V. + // is this delay long enough for all cases?? + for (uint8_t i=0;i<18;i++) { + delayMicroseconds(7500); + } + + // Now we pull both RS and R/W low to begin commands + digitalWrite(_rs_pin, LOW); + digitalWrite(enable, LOW); + + //put the LCD into 4 bit mode + // this is according to the hitachi HD44780 datasheet + // figure 24, pg 46 + + // we start in 8bit mode, try to set 4 bit mode + // at this point we are in 8 bit mode but of course in this + // interface 4 pins are dangling unconnected and the values + // on them don't matter for these instructions. + digitalWrite(_rs_pin, LOW); + write4bits(0x03); + delayMicroseconds(5000); // I have one LCD for which 4500 here was not long enough. + // second try + write4bits(0x03); + delayMicroseconds(150); // wait + // third go! + write4bits(0x03); + delayMicroseconds(150); + // finally, set to 4-bit interface + write4bits(0x02); + delayMicroseconds(150); + + + // finally, set # lines, font size, etc. + command(LCD_FUNCTIONSET | displayfunction); + + // turn the display on with no cursor or blinking default + _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; display(); + + // clear it off + clear(); + + // Initialize to default text direction (for romance languages) + _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; + // set the entry mode + command(LCD_ENTRYMODESET | _displaymode); +} + + +/******************************************/ +/** high level commands, for the user! */ +/******************************************/ + +void LiquidCrystalFast::clear() +{ + if (_en2 != 255) { + _chip=2; + command(LCD_CLEARDISPLAY); + _chip=0; + command(LCD_CLEARDISPLAY); + delayPerHome(); + setCursor(0,0); + } else { + command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero + delayPerHome(); + } + _scroll_count = 0; +} + +void LiquidCrystalFast::home() +{ + commandBoth(LCD_RETURNHOME); // set cursor position to zero both chips. + delayPerHome(); + _scroll_count = 0; + if (_en2 != 255) setCursor(0,0); +} + + +// Turn the display on/off (quickly) +void LiquidCrystalFast::noDisplay() { + _displaycontrol &= ~LCD_DISPLAYON; + commandBoth(LCD_DISPLAYCONTROL | _displaycontrol); //both chips +} +void LiquidCrystalFast::display() { + _displaycontrol |= LCD_DISPLAYON; + commandBoth(LCD_DISPLAYCONTROL | _displaycontrol); //both chips +} + +// Turns the underline cursor on/off +void LiquidCrystalFast::noCursor() { + _displaycontrol &= ~LCD_CURSORON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} +void LiquidCrystalFast::cursor() { + _displaycontrol |= LCD_CURSORON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// Turn on and off the blinking cursor +void LiquidCrystalFast::noBlink() { + _displaycontrol &= ~LCD_BLINKON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} +void LiquidCrystalFast::blink() { + _displaycontrol |= LCD_BLINKON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// These commands scroll the display without changing the RAM +void LiquidCrystalFast::scrollDisplayLeft(void) { + commandBoth(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); //both chips + _scroll_count++; + if (_scroll_count >= 40) _scroll_count -= 40; // -39< scroll_count<39 +} +void LiquidCrystalFast::scrollDisplayRight(void) { + commandBoth(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); //both chips + _scroll_count--; + if (_scroll_count <= -40) _scroll_count += 40; +} + +// This is for text that flows Left to Right +void LiquidCrystalFast::leftToRight(void) { + _displaymode |= LCD_ENTRYLEFT; + _direction = LCD_Right; + commandBoth(LCD_ENTRYMODESET | _displaymode); //both chips +} + +// This is for text that flows Right to Left +void LiquidCrystalFast::rightToLeft(void) { + _displaymode &= ~LCD_ENTRYLEFT; + _direction = LCD_Left; + commandBoth(LCD_ENTRYMODESET | _displaymode); //both chips +} + + +// Allows us to fill the first 8 CGRAM locations +// with custom characters +void LiquidCrystalFast::createChar(uint8_t location, uint8_t charmap[]) { + location &= 0x7; // we only have 8 locations 0-7 + if (_en2 == 255) { + command(LCD_SETCGRAMADDR | (location << 3)); + for (int i=0; i<8; i++) { + send(charmap[i],HIGH); + } + } + else { + uint8_t chipSave = _chip; + _chip = 0; + command(LCD_SETCGRAMADDR | (location << 3)); + for (uint8_t i=0; i<8; i++) { + send(charmap[i],HIGH); + } + _chip = 2; + command(LCD_SETCGRAMADDR | (location << 3)); + for (uint8_t i=0; i<8; i++) { + send(charmap[i],HIGH); + } + _chip = chipSave; + } +} + +void LiquidCrystalFast::setCursor(uint8_t col, uint8_t row) // this can be called by the user but is also called before writing some characters. +{ + if ( row > _numlines ) { + row = _numlines-1; // we count rows starting w/0 + } + _y = row; + _x = col; + _setCursFlag = 0; //user did a setCursor--clear the flag that may have been set in write() + int8_t high_bit = row_offsets[row] & 0x40; // this keeps coordinates pegged to a spot on the LCD screen even if the user scrolls right or + int8_t offset = col + (row_offsets[row] &0x3f) + _scroll_count; //left under program control. Previously setCursor was pegged to a location in DDRAM + //the 3 quantities we add are each <40 + if (offset > 39) offset -= 40; // if the display is autoscrolled this method does not work, however. + if (offset < 0) offset += 40; + offset |= high_bit; + if (_chip != (row & 0b10)) noCursor(); //turn off cursor on chip we are leaving + _chip = row & 0b10; //if it is row 0 or 1 this is 0; if it is row 2 or 3 this is 2 + command(LCD_SETDDRAMADDR | (byte) offset ); +} + +// This will 'right justify' text from the cursor +void LiquidCrystalFast::autoscroll(void) { //to count the number of times we scrolled; here we'd need to keep track of microseconds and divide. I'm not going there. + _displaymode |= LCD_ENTRYSHIFTINCREMENT; + commandBoth(LCD_ENTRYMODESET | _displaymode); //both chips +} + +// This will 'left justify' text from the cursor +void LiquidCrystalFast::noAutoscroll(void) { + _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; //both chips + commandBoth(LCD_ENTRYMODESET | _displaymode); +} + + +/*************************************************/ +/** mid level commands, for sending data/cmds */ +/*************************************************/ + +inline void LiquidCrystalFast::command(uint8_t value) { + send(value, LOW); +} + +//for many of the commands that need to be sent twice if 2 controller chips +void LiquidCrystalFast::commandBoth(uint8_t value) +{ + if (_en2 == 255) { + send(value, LOW); // normal LCD, single controller chip + } else { + uint8_t chipSave = _chip; + _chip = 0; + send(value,LOW); //send command to first HD44780 + _chip = 2; + send(value,LOW); //send to 2nd HD44780 + _chip=chipSave; + } +} + +//print calls this to send characters to the LCD +#if defined(ARDUINO) && ARDUINO >= 100 +size_t LiquidCrystalFast::write(uint8_t value) { +#else +void LiquidCrystalFast::write(uint8_t value) { +#endif + + if ((_scroll_count != 0) || (_setCursFlag != 0) ) setCursor(_x,_y); //first we call setCursor and send the character + if ((value != '\r') && (value != '\n') ) send(value, HIGH); + + _setCursFlag = 0; + if (_direction == LCD_Right) { // then we update the x & y location for the NEXT character + _x++; + if ((value == '\r') ||(_x >= _numcols) ) { //romance languages go left to right + + _x = 0; + _y++; + _setCursFlag = 1; //we'll need a setCursor() before the next char to move to begin of next line + } + } else { + _x--; + if ( (value == '\n') || (_x < 0)) { //emulate right to left text mode which is built in but would be defeated by my code above + _x = _numcols-1; + _y++; + _setCursFlag = 1; + } + } + if (_y >= _numlines) _y = 0; //wrap last line up to line 0 +#if defined(ARDUINO) && ARDUINO >= 100 + return 1; +#endif +} + + +/****************************************/ +/** low level data pushing commands **/ +/****************************************/ + +// write either command or data, with automatic 4/8-bit selection +void LiquidCrystalFast::send(uint8_t value, uint8_t mode) { + uint8_t en = _enable_pin; + if ((_en2 != 255) && (_chip)) en = _en2; + if (_rw_pin == 255) { + delayMicroseconds(DELAYPERCHAR); + } else { + pinMode(_data_pins[0], INPUT); + pinMode(_data_pins[1], INPUT); + pinMode(_data_pins[2], INPUT); + pinMode(_data_pins[3], INPUT); + digitalWrite(_rw_pin, HIGH); + digitalWrite(_rs_pin, LOW); + uint8_t busy; + do { + digitalWrite(en, HIGH); + busy = digitalRead(_data_pins[3]); + digitalWrite(en, LOW); + digitalWrite(en, HIGH); + digitalWrite(en, LOW); + } while (busy == HIGH); + pinMode(_data_pins[0], OUTPUT); + pinMode(_data_pins[1], OUTPUT); + pinMode(_data_pins[2], OUTPUT); + pinMode(_data_pins[3], OUTPUT); + digitalWrite(_rw_pin, LOW); + } + digitalWrite(_rs_pin, mode); + + digitalWrite(_data_pins[0], value & 0x10); + digitalWrite(_data_pins[1], value & 0x20); + digitalWrite(_data_pins[2], value & 0x40); + digitalWrite(_data_pins[3], value & 0x80); + digitalWrite(en, HIGH); // enable pulse must be >450ns + digitalWrite(en, LOW); + + digitalWrite(_data_pins[0], value & 0x01); + digitalWrite(_data_pins[1], value & 0x02); + digitalWrite(_data_pins[2], value & 0x04); + digitalWrite(_data_pins[3], value & 0x08); + digitalWrite(en, HIGH); // enable pulse must be >450ns + digitalWrite(en, LOW); +} + +// used during init +void LiquidCrystalFast::write4bits(uint8_t value) +{ + uint8_t v=value; + uint8_t *pinptr = _data_pins; + digitalWrite(*pinptr++, v & 1 ); + digitalWrite(*pinptr++,( v >>= 1) & 1 ); + digitalWrite(*pinptr++,( v >>= 1) & 1 ); + digitalWrite(*pinptr++,( v >>= 1) & 1 ); + byte en = _enable_pin; + if ((_en2 != 255) && (_chip)) en = _en2; // 4x40 LCD with 2 controller chips with separate enable lines if we called w 2 enable pins and are on lines 2 or 3 enable chip 2 + digitalWrite(en, HIGH); // enable pulse must be >450ns + digitalWrite(en, LOW); +} + diff --git a/Marlin/LiquidCrystalFast_Mod.h b/Marlin/LiquidCrystalFast_Mod.h new file mode 100755 index 000000000000..ef8778d435d0 --- /dev/null +++ b/Marlin/LiquidCrystalFast_Mod.h @@ -0,0 +1,147 @@ +#ifndef LiquidCrystalFast_h +#define LiquidCrystalFast_h + +#include +#include "Print.h" +#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" // for digitalRead, digitalWrite, pinMode, delayMicroseconds +#else +#include "WProgram.h" +#endif + +// commands +#define LCD_CLEARDISPLAY 0x01 +#define LCD_RETURNHOME 0x02 +#define LCD_ENTRYMODESET 0x04 +#define LCD_DISPLAYCONTROL 0x08 +#define LCD_CURSORSHIFT 0x10 +#define LCD_FUNCTIONSET 0x20 +#define LCD_SETCGRAMADDR 0x40 +#define LCD_SETDDRAMADDR 0x80 + +// flags for display entry mode +#define LCD_ENTRYRIGHT 0x00 +#define LCD_ENTRYLEFT 0x02 +#define LCD_ENTRYSHIFTINCREMENT 0x01 +#define LCD_ENTRYSHIFTDECREMENT 0x00 + +// flags for display on/off control +#define LCD_DISPLAYON 0x04 +#define LCD_DISPLAYOFF 0x00 +#define LCD_CURSORON 0x02 +#define LCD_CURSOROFF 0x00 +#define LCD_BLINKON 0x01 +#define LCD_BLINKOFF 0x00 + +// flags for display/cursor shift +#define LCD_DISPLAYMOVE 0x08 +#define LCD_CURSORMOVE 0x00 +#define LCD_MOVERIGHT 0x04 +#define LCD_MOVELEFT 0x00 + +// flags for function set +//#define LCD_8BITMODE 0x10 +#define LCD_4BITMODE 0x00 +#define LCD_2LINE 0x08 +#define LCD_1LINE 0x00 +#define LCD_5x10DOTS 0x04 +#define LCD_5x8DOTS 0x00 +#define LCD_Right 0 +#define LCD_Left 1 + +#define DELAYPERCHAR 320 + +class LiquidCrystalFast : public Print { +public: + // 6 pin connection (slow): normal LCD, single HD44780 controller + LiquidCrystalFast(uint8_t rs, uint8_t enable, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) { + init(rs, 255, enable, 255, d4, d5, d6, d7); + } + // 7 pin connection (fast): normal LCD, single HD44780 controller + LiquidCrystalFast(uint8_t rs, uint8_t rw, uint8_t enable, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) { + init(rs, rw, enable, 255, d4, d5, d6, d7); + } + // 8 pin connection (fast): 4x40 LCD, two HD44780 controller chips + LiquidCrystalFast(uint8_t rs, uint8_t rw, uint8_t enable1, uint8_t enable2, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) { + init(rs, rw, enable1, enable2, d4, d5, d6, d7); + } + // 10 pin connection - not recommended, for backwards compatibility only + LiquidCrystalFast(uint8_t rs, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) { + init(rs, 255, enable, 255, d4, d5, d6, d7); + } + // 11 pin connection - not recommended, for backwards compatibility only + LiquidCrystalFast(uint8_t rs, uint8_t rw, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) { + init(rs, rw, enable, 255, d4, d5, d6, d7); + } + void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); + void clear(); + void home(); + + void noDisplay(); + void display(); + void noBlink(); + void blink(); + void noCursor(); + void cursor(); + void scrollDisplayLeft(); + void scrollDisplayRight(); + void leftToRight(); + void rightToLeft(); + void autoscroll(); + void noAutoscroll(); + + void createChar(uint8_t, uint8_t[]); + void setCursor(uint8_t, uint8_t); +#if defined(ARDUINO) && ARDUINO >= 100 + virtual size_t write(uint8_t); + inline size_t write(unsigned long n) { return write((uint8_t)n); } + inline size_t write(long n) { return write((uint8_t)n); } + inline size_t write(unsigned int n) { return write((uint8_t)n); } + inline size_t write(int n) { return write((uint8_t)n); } +#else + virtual void write(uint8_t); + inline void write(unsigned long n) { write((uint8_t)n); } + inline void write(long n) { write((uint8_t)n); } + inline void write(unsigned int n) { write((uint8_t)n); } + inline void write(int n) { write((uint8_t)n); } +#endif + using Print::write; + void command(uint8_t); + void commandBoth(uint8_t); + inline LiquidCrystalFast& operator() (uint8_t x, uint8_t y) {setCursor(x,y); return *this;} //use along w Streaming.h to support: lcd(col,line)<<"a="< 2 +#endif + +#if RIGIDBOT_SIZE == 1 // 10x10 Regular + #define X_MAX_POS (254 - X_DUAL_REDUCTION) + #define Y_MAX_POS 248 + #define Z_MAX_POS 254 +#elif RIGIDBOT_SIZE == 2 // 12x16 Big + #define X_MAX_POS (406 - X_DUAL_REDUCTION) + #define Y_MAX_POS 304 + #define Z_MAX_POS 254 +#endif +#define X_MIN_POS 0 +#define Y_MIN_POS 0 +#define Z_MIN_POS 0 + +// The position of the homing switches +//#define MANUAL_HOME_POSITIONS // If defined, MANUAL_*_HOME_POS below will be used +//#define BED_CENTER_AT_0_0 // If defined, the center of the bed is at (X=0, Y=0) + +//Manual homing switch locations: +// For deltabots this means top and center of the Cartesian print volume. +#define MANUAL_X_HOME_POS 0 +#define MANUAL_Y_HOME_POS 0 +#define MANUAL_Z_HOME_POS 0 +//#define MANUAL_Z_HOME_POS 402 // For delta: Distance between nozzle and print surface after homing. + +//// MOVEMENT SETTINGS +#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E +#define HOMING_FEEDRATE {50*60, 50*60, 15*60, 0} // set the homing speeds (mm/min) + +// default settings + +#define DEFAULT_AXIS_STEPS_PER_UNIT {44.3090,22.1545,1600,53.5} // default steps per unit for Ultimaker +#define DEFAULT_MAX_FEEDRATE {500, 500, 4, 25} // (mm/sec) +#define DEFAULT_MAX_ACCELERATION {800,600,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for Skeinforge 40+, for older versions raise them a lot. + +#define DEFAULT_ACCELERATION 600 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_RETRACT_ACCELERATION 1000 // X, Y, Z and E max acceleration in mm/s^2 for retracts + +// Offset of the extruders (uncomment if using more than one and relying on firmware to position when changing). +// The offset has to be X=0, Y=0 for the extruder 0 hotend (default extruder). +// For the other hotends it is their distance from the extruder 0 hotend. +// #define EXTRUDER_OFFSET_X {0.0, 20.00} // (in mm) for each extruder, offset of the hotend on the X axis +// #define EXTRUDER_OFFSET_Y {0.0, 5.00} // (in mm) for each extruder, offset of the hotend on the Y axis + +// The speed change that does not require acceleration (i.e. the software might assume it can be done instantaneously) +#define DEFAULT_XYJERK 5.0 // (mm/sec) +#define DEFAULT_ZJERK 0.4 // (mm/sec) +#define DEFAULT_EJERK 5.0 // (mm/sec) + +#define X_MAX_LENGTH (X_MAX_POS - X_MIN_POS) +#define Y_MAX_LENGTH (Y_MAX_POS - Y_MIN_POS) +#define Z_MAX_LENGTH (Z_MAX_POS - Z_MIN_POS) + +#define X_CENTER_POS ((X_MIN_POS + X_MAX_POS) / 2) +#define Y_CENTER_POS ((Y_MIN_POS + Y_MAX_POS) / 2) + +//============================= Bed Auto Leveling =========================== + +//#define ENABLE_AUTO_BED_LEVELING // Delete the comment to enable (remove // at the start of the line) +#define Z_PROBE_REPEATABILITY_TEST // If not commented out, Z-Probe Repeatability test will be included if Auto Bed Leveling is Enabled. + +#ifdef ENABLE_AUTO_BED_LEVELING + +// There are 2 different ways to pick the X and Y locations to probe: + +// - "grid" mode +// Probe every point in a rectangular grid +// You must specify the rectangle, and the density of sample points +// This mode is preferred because there are more measurements. +// It used to be called ACCURATE_BED_LEVELING but "grid" is more descriptive + +// - "3-point" mode +// Probe 3 arbitrary points on the bed (that aren't colinear) +// You must specify the X & Y coordinates of all 3 points + + #define AUTO_BED_LEVELING_GRID + // with AUTO_BED_LEVELING_GRID, the bed is sampled in a + // AUTO_BED_LEVELING_GRID_POINTSxAUTO_BED_LEVELING_GRID_POINTS grid + // and least squares solution is calculated + // Note: this feature occupies 10'206 byte + #ifdef AUTO_BED_LEVELING_GRID + + // set the rectangle in which to probe + #define LEFT_PROBE_BED_POSITION 15 + #define RIGHT_PROBE_BED_POSITION 170 + #define BACK_PROBE_BED_POSITION 180 + #define FRONT_PROBE_BED_POSITION 20 + + // set the number of grid points per dimension + // I wouldn't see a reason to go above 3 (=9 probing points on the bed) + #define AUTO_BED_LEVELING_GRID_POINTS 2 + + + #else // not AUTO_BED_LEVELING_GRID + // with no grid, just probe 3 arbitrary points. A simple cross-product + // is used to esimate the plane of the print bed + + #define ABL_PROBE_PT_1_X 15 + #define ABL_PROBE_PT_1_Y 180 + #define ABL_PROBE_PT_2_X 15 + #define ABL_PROBE_PT_2_Y 20 + #define ABL_PROBE_PT_3_X 170 + #define ABL_PROBE_PT_3_Y 20 + + #endif // AUTO_BED_LEVELING_GRID + + + // these are the offsets to the probe relative to the extruder tip (Hotend - Probe) + #define X_PROBE_OFFSET_FROM_EXTRUDER -25 + #define Y_PROBE_OFFSET_FROM_EXTRUDER -29 + #define Z_PROBE_OFFSET_FROM_EXTRUDER -12.35 + + #define Z_RAISE_BEFORE_HOMING 4 // (in mm) Raise Z before homing (G28) for Probe Clearance. + // Be sure you have this distance over your Z_MAX_POS in case + + #define XY_TRAVEL_SPEED 8000 // X and Y axis travel speed between probes, in mm/min + + #define Z_RAISE_BEFORE_PROBING 15 //How much the extruder will be raised before traveling to the first probing point. + #define Z_RAISE_BETWEEN_PROBINGS 5 //How much the extruder will be raised when traveling from between next probing points + + //#define Z_PROBE_SLED // turn on if you have a z-probe mounted on a sled like those designed by Charles Bell + //#define SLED_DOCKING_OFFSET 5 // the extra distance the X axis must travel to pickup the sled. 0 should be fine but you can push it further if you'd like. + + //If defined, the Probe servo will be turned on only during movement and then turned off to avoid jerk + //The value is the delay to turn the servo off after powered on - depends on the servo speed; 300ms is good value, but you can try lower it. + // You MUST HAVE the SERVO_ENDSTOPS defined to use here a value higher than zero otherwise your code will not compile. + +// #define PROBE_SERVO_DEACTIVATION_DELAY 300 + + +//If you have enabled the Bed Auto Leveling and are using the same Z Probe for Z Homing, +//it is highly recommended you let this Z_SAFE_HOMING enabled!!! + + #define Z_SAFE_HOMING // This feature is meant to avoid Z homing with probe outside the bed area. + // When defined, it will: + // - Allow Z homing only after X and Y homing AND stepper drivers still enabled + // - If stepper drivers timeout, it will need X and Y homing again before Z homing + // - Position the probe in a defined XY point before Z Homing when homing all axis (G28) + // - Block Z homing only when the probe is outside bed area. + + #ifdef Z_SAFE_HOMING + + #define Z_SAFE_HOMING_X_POINT (X_MAX_LENGTH/2) // X point for Z homing when homing all axis (G28) + #define Z_SAFE_HOMING_Y_POINT (Y_MAX_LENGTH/2) // Y point for Z homing when homing all axis (G28) + + #endif + +#endif // ENABLE_AUTO_BED_LEVELING + + +//=========================================================================== +//=============================Additional Features=========================== +//=========================================================================== + +// Disable stepper drivers until voltage has stabilized +#define STEPPER_RESET_FIX + +// Custom M code points +#define CUSTOM_M_CODES +#ifdef CUSTOM_M_CODES + #define CUSTOM_M_CODE_SET_Z_PROBE_OFFSET 851 + #define Z_PROBE_OFFSET_RANGE_MIN -15 + #define Z_PROBE_OFFSET_RANGE_MAX -5 +#endif + + +// EEPROM +// The microcontroller can store settings in the EEPROM, e.g. max velocity... +// M500 - stores parameters in EEPROM +// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). +// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. +// +// Define this to enable EEPROM support +#define EEPROM_SETTINGS +// +// To disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out: +// please keep turned on if you can. +#define EEPROM_CHITCHAT +// +// Define EEPROM_OVERWRITE to have EEPROM overwritten with firmware-compiled defaults any time the firmware +// build date+time changes (default behavior is to overwrite EEPROM only when EEPROM_VERSION in +// ConfigurationStore.cpp changes +//#define EEPROM_OVERWRITE + +// Preheat Constants +#define PLA_PREHEAT_HOTEND_TEMP 200 +#define PLA_PREHEAT_HPB_TEMP 70 +#define PLA_PREHEAT_FAN_SPEED 255 // Insert Value between 0 and 255 + +#define ABS_PREHEAT_HOTEND_TEMP 230 +#define ABS_PREHEAT_HPB_TEMP 100 +#define ABS_PREHEAT_FAN_SPEED 255 // Insert Value between 0 and 255 + +//LCD and SD support +//#define ULTRA_LCD //general LCD support, also 16x2 +//#define DOGLCD // Support for SPI LCD 128x64 (Controller ST7565R graphic Display Family) +//#define SDSUPPORT // Enable SD Card Support in Hardware Console +//#define SDSLOW // Use slower SD transfer mode (not normally needed - uncomment if you're getting volume init error) +//#define SD_CHECK_AND_RETRY // Use CRC checks and retries on the SD communication +//#define ENCODER_PULSES_PER_STEP 1 // Increase if you have a high resolution encoder +//#define ENCODER_STEPS_PER_MENU_ITEM 5 // Set according to ENCODER_PULSES_PER_STEP or your liking +//#define ULTIMAKERCONTROLLER //as available from the Ultimaker online store. +//#define ULTIPANEL //the UltiPanel as on Thingiverse +//#define LCD_FEEDBACK_FREQUENCY_HZ 1000 // this is the tone frequency the buzzer plays when on UI feedback. ie Screen Click +//#define LCD_FEEDBACK_FREQUENCY_DURATION_MS 100 // the duration the buzzer plays the UI feedback sound. ie Screen Click + +// The MaKr3d Makr-Panel with graphic controller and SD support +// http://reprap.org/wiki/MaKr3d_MaKrPanel +//#define MAKRPANEL + +// The RepRapDiscount Smart Controller (white PCB) +// http://reprap.org/wiki/RepRapDiscount_Smart_Controller +//#define REPRAP_DISCOUNT_SMART_CONTROLLER + +// The GADGETS3D G3D LCD/SD Controller (blue PCB) +// http://reprap.org/wiki/RAMPS_1.3/1.4_GADGETS3D_Shield_with_Panel +//#define G3D_PANEL + +// The RepRapDiscount FULL GRAPHIC Smart Controller (quadratic white PCB) +// http://reprap.org/wiki/RepRapDiscount_Full_Graphic_Smart_Controller +// +// ==> REMEMBER TO INSTALL U8glib to your ARDUINO library folder: http://code.google.com/p/u8glib/wiki/u8glib +//#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER + +// The RepRapWorld REPRAPWORLD_KEYPAD v1.1 +// http://reprapworld.com/?products_details&products_id=202&cPath=1591_1626 +//#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 + +// RigidBot Panel V1.0 +// http://www.inventapart.com/ +#define RIGIDPANEL + +//automatic expansion +#if defined (MAKRPANEL) + #define DOGLCD + #define SDSUPPORT + #define ULTIPANEL + #define NEWPANEL + #define DEFAULT_LCD_CONTRAST 17 +#endif + +#if defined (REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER) + #define DOGLCD + #define U8GLIB_ST7920 + #define REPRAP_DISCOUNT_SMART_CONTROLLER +#endif + +#if defined(ULTIMAKERCONTROLLER) || defined(REPRAP_DISCOUNT_SMART_CONTROLLER) || defined(G3D_PANEL) + #define ULTIPANEL + #define NEWPANEL +#endif + +#if defined(REPRAPWORLD_KEYPAD) + #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 + +#if defined(RIGIDPANEL) + #define ULTIPANEL + #define SDSPEED SPI_EIGHTH_SPEED // full/half/quarter/sixteenth, or 0-6 (0 = full speed) + #define SDSUPPORT + #define ULTRA_LCD + #define LCD_WIDTH 20 + #define LCD_HEIGHT 4 + #define USB_LCD // Get USB-centric strings from language.h +#endif + +//I2C PANELS + +//#define LCD_I2C_SAINSMART_YWROBOT +#ifdef LCD_I2C_SAINSMART_YWROBOT + // This uses the LiquidCrystal_I2C library ( https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home ) + // Make sure it is placed in the Arduino libraries directory. + #define LCD_I2C_TYPE_PCF8575 + #define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander + #define NEWPANEL + #define ULTIPANEL +#endif + +// PANELOLU2 LCD with status LEDs, separate encoder and click inputs +//#define LCD_I2C_PANELOLU2 +#ifdef LCD_I2C_PANELOLU2 + // This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 ) + // Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory. + // (v1.2.3 no longer requires you to define PANELOLU in the LiquidTWI2.h library header file) + // Note: The PANELOLU2 encoder click input can either be directly connected to a pin + // (if BTN_ENC defined to != -1) or read through I2C (when BTN_ENC == -1). + #define LCD_I2C_TYPE_MCP23017 + #define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander + #define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD + #define NEWPANEL + #define ULTIPANEL + + #ifndef ENCODER_PULSES_PER_STEP + #define ENCODER_PULSES_PER_STEP 4 + #endif + + #ifndef ENCODER_STEPS_PER_MENU_ITEM + #define ENCODER_STEPS_PER_MENU_ITEM 1 + #endif + + + #ifdef LCD_USE_I2C_BUZZER + #define LCD_FEEDBACK_FREQUENCY_HZ 1000 + #define LCD_FEEDBACK_FREQUENCY_DURATION_MS 100 + #endif + +#endif + +// Panucatt VIKI LCD with status LEDs, integrated click & L/R/U/P buttons, separate encoder inputs +//#define LCD_I2C_VIKI +#ifdef LCD_I2C_VIKI + // This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 ) + // Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory. + // Note: The pause/stop/resume LCD button pin should be connected to the Arduino + // BTN_ENC pin (or set BTN_ENC to -1 if not used) + #define LCD_I2C_TYPE_MCP23017 + #define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander + #define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD (requires LiquidTWI2 v1.2.3 or later) + #define NEWPANEL + #define ULTIPANEL +#endif + +// Shift register panels +// --------------------- +// 2 wire Non-latching LCD SR from: +// https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/schematics#!shiftregister-connection +//#define SR_LCD +#ifdef SR_LCD + #define SR_LCD_2W_NL // Non latching 2 wire shift register + //#define NEWPANEL +#endif + + +#ifdef ULTIPANEL +// #define NEWPANEL //enable this if you have a click-encoder panel + #define SDSUPPORT + #define ULTRA_LCD + #ifdef DOGLCD // Change number of lines to match the DOG graphic display + #define LCD_WIDTH 20 + #define LCD_HEIGHT 5 + #else + #define LCD_WIDTH 20 + #define LCD_HEIGHT 4 + #endif +#else //no panel but just LCD + #ifdef ULTRA_LCD + #ifdef DOGLCD // Change number of lines to match the 128x64 graphics display + #define LCD_WIDTH 20 + #define LCD_HEIGHT 5 + #else + #define LCD_WIDTH 16 + #define LCD_HEIGHT 2 + #endif + #endif +#endif + +// default LCD contrast for dogm-like LCD displays +#ifdef DOGLCD +# ifndef DEFAULT_LCD_CONTRAST +# define DEFAULT_LCD_CONTRAST 32 +# endif +#endif + +// Increase the FAN pwm frequency. Removes the PWM noise but increases heating in the FET/Arduino +//#define FAST_PWM_FAN + +// Temperature status LEDs that display the hotend and bet temperature. +// If all hotends and bed temperature and temperature setpoint are < 54C then the BLUE led is on. +// Otherwise the RED led is on. There is 1C hysteresis. +//#define TEMP_STAT_LEDS + +// Use software PWM to drive the fan, as for the heaters. This uses a very low frequency +// which is not ass annoying as with the hardware PWM. On the other hand, if this frequency +// is too low, you should also increment SOFT_PWM_SCALE. +//#define FAN_SOFT_PWM + +// Incrementing this by 1 will double the software PWM frequency, +// affecting heaters, and the fan if FAN_SOFT_PWM is enabled. +// However, control resolution will be halved for each increment; +// at zero value, there are 128 effective control positions. +#define SOFT_PWM_SCALE 0 + +// 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 23 + +// SF send wrong arc g-codes when using Arc Point as fillet procedure +//#define SF_ARC_FIX + +// Support for the BariCUDA Paste Extruder. +//#define BARICUDA + +//define BlinkM/CyzRgb Support +//#define BLINKM + +/*********************************************************************\ +* R/C SERVO support +* Sponsored by TrinityLabs, Reworked by codexmas +**********************************************************************/ + +// Number of servos +// +// If you select a configuration below, this will receive a default value and does not need to be set manually +// set it manually if you have more servos than extruders and wish to manually control some +// leaving it undefined or defining as 0 will disable the servo subsystem +// If unsure, leave commented / disabled +// +//#define NUM_SERVOS 3 // Servo index starts with 0 for M280 command + +// Servo Endstops +// +// This allows for servo actuated endstops, primary usage is for the Z Axis to eliminate calibration or bed height changes. +// Use M206 command to correct for switch height offset to actual nozzle height. Store that setting with M500. +// +//#define SERVO_ENDSTOPS {-1, -1, 0} // Servo index for X, Y, Z. Disable with -1 +//#define SERVO_ENDSTOP_ANGLES {0,0, 0,0, 70,0} // X,Y,Z Axis Extend and Retract angles + +#include "Configuration_adv.h" +#include "thermistortables.h" + +#endif //__CONFIGURATION_H diff --git a/Marlin/example_configurations/rigidbot/makeallrigidbots.sh b/Marlin/example_configurations/rigidbot/makeallrigidbots.sh new file mode 100755 index 000000000000..8540c30f0a14 --- /dev/null +++ b/Marlin/example_configurations/rigidbot/makeallrigidbots.sh @@ -0,0 +1,152 @@ +#!/bin/bash + +RBCE_PREFIX="RBCE_v0.4" + +MAKEFILE="Makefile" +CONFIGURATION_H="Configuration.h" +CONFIGURATION_ADV_H="Configuration_adv.h" + +# Move to working directory (lazy approach compared to allowing defined source and build directories) +cd ../.. + +# Preserve originals +cp -p $MAKEFILE ${MAKEFILE}.premangle +cp -p $CONFIGURATION_H ${CONFIGURATION_H}.premangle +cp -p $CONFIGURATION_ADV_H ${CONFIGURATION_ADV_H}.premangle + +# Prep makefile for all RigidBot builds +sed -i '' -e 's/^HARDWARE_MOTHERBOARD .*/HARDWARE_MOTHERBOARD \?= 42/' $MAKEFILE +sed -i '' -e 's/^AVR_TOOLS_PATH .*/AVR_TOOLS_PATH \?= \/Applications\/Arduino.app\/Contents\/Resources\/Java\/hardware\/tools\/avr\/bin\//' $MAKEFILE +sed -i '' -e 's/^LIQUID_TWI2 .*/LIQUID_TWI2 \?= 0/' $MAKEFILE +sed -i '' -e 's/^WIRE .*/WIRE \?= 0/' $MAKEFILE + +BUILD_DIR=`grep "^BUILD_DIR" $MAKEFILE | cut -d\= -f2` +echo "Build dir is $BUILD_DIR/" + +# Prep Configuration.h for all RigidBot builds +sed -i '' -e 's/^#define BAUDRATE.*/#define BAUDRATE 115200/' $CONFIGURATION_H +### If HARDWARE_MOTHERBOARD is set in Makefile, this isn't really needed +sed -i '' -e 's/^#define MOTHERBOARD.*/#define MOTHERBOARD 42/' $CONFIGURATION_H +### Thermistor types +sed -i '' -e 's/^#define TEMP_SENSOR_0.*/#define TEMP_SENSOR_0 1/' $CONFIGURATION_H +sed -i '' -e 's/^#define TEMP_SENSOR_1.*/#define TEMP_SENSOR_1 1/' $CONFIGURATION_H +sed -i '' -e 's/^#define TEMP_SENSOR_2.*/#define TEMP_SENSOR_2 0/' $CONFIGURATION_H +sed -i '' -e 's/^#define TEMP_SENSOR_BED.*/#define TEMP_SENSOR_BED 1/' $CONFIGURATION_H +### Community sourced PID constants for IAP redesigned hotend +sed -i '' -e 's/^[ ]*#define[ ]*DEFAULT_Kp.*/#define DEFAULT_Kp 14.36/' $CONFIGURATION_H +sed -i '' -e 's/^[ ]*#define[ ]*DEFAULT_Ki.*/#define DEFAULT_Ki 0.66/' $CONFIGURATION_H +sed -i '' -e 's/^[ ]*#define[ ]*DEFAULT_Kd.*/#define DEFAULT_Kd 79.25/' $CONFIGURATION_H +### IAP default heated bed PID constants +sed -i '' -e 's/^[ ]*#define[ ]*DEFAULT_bedKp.*/#define DEFAULT_bedKp 355/' $CONFIGURATION_H +sed -i '' -e 's/^[ ]*#define[ ]*DEFAULT_bedKi.*/#define DEFAULT_bedKi 66.5/' $CONFIGURATION_H +sed -i '' -e 's/^[ ]*#define[ ]*DEFAULT_bedKd.*/#define DEFAULT_bedKd 480/' $CONFIGURATION_H +### Enable thermal runaway protection +sed -i '' -e 's/^#define THERMAL_RUNAWAY_PROTECTION_PERIOD.*/#define THERMAL_RUNAWAY_PROTECTION_PERIOD 40/' $CONFIGURATION_H +sed -i '' -e 's/^#define THERMAL_RUNAWAY_PROTECTION_HYSTERESIS.*/#define THERMAL_RUNAWAY_PROTECTION_HYSTERESIS 4/' $CONFIGURATION_H +sed -i '' -e 's/^#define THERMAL_RUNAWAY_PROTECTION_BED_PERIOD.*/#define THERMAL_RUNAWAY_PROTECTION_BED_PERIOD 20/' $CONFIGURATION_H +sed -i '' -e 's/^#define THERMAL_RUNAWAY_PROTECTION_BED_HYSTERESIS.*/#define THERMAL_RUNAWAY_PROTECTION_BED_HYSTERESIS 2/' $CONFIGURATION_H +### Use "predefined mechanics" bundle for the RigidBot: endstops, build volume, feedrate, acceleration, jerk +sed -i '' -e 's/^\/\/#include \"mechanics/rigidbot.h\"/#include \"mechanics/rigidbot.h\"/' $CONFIGURATION_H +### Enable IAP's "Stepper Reset Fix" +sed -i '' -e 's/^\/\/#define STEPPER_RESET_FIX.*/#define STEPPER_RESET_FIX/' $CONFIGURATION_H +### Enable EEPROM support, chitchat, but not overwrite +sed -i '' -e 's/^\/\/#define EEPROM_SETTINGS.*/#define EEPROM_SETTINGS/' $CONFIGURATION_H +sed -i '' -e 's/^\/\/#define EEPROM_CHITCHAT.*/#define EEPROM_CHITCHAT/' $CONFIGURATION_H +sed -i '' -e 's/^.*#define EEPROM_OVERWRITE.*/\/\/#define EEPROM_OVERWRITE/' $CONFIGURATION_H +### Preheat settings for the LCD +sed -i '' -e 's/^#define PLA_PREHEAT_HOTEND_TEMP.*/#define PLA_PREHEAT_HOTEND_TEMP 200/' $CONFIGURATION_H +sed -i '' -e 's/^#define ABS_PREHEAT_HOTEND_TEMP.*/#define ABS_PREHEAT_HOTEND_TEMP 230/' $CONFIGURATION_H + + +# Prep Configuration_adv.h for all RigidBot builds +sed -i '' -e 's/^#define ENDSTOPS_ONLY_FOR_HOMING.*/\/\/#define ENDSTOPS_ONLY_FOR_HOMING/' $CONFIGURATION_ADV_H +sed -i '' -e 's/^#define BUFSIZE.*/#define BUFSIZE 8/' $CONFIGURATION_ADV_H + + +################## +## RigidPanel LCD +################## +sed -i '' -e 's/^U8GLIB .*/U8GLIB \?= 0/' $MAKEFILE +sed -i '' -e 's/^RIGIDPANEL .*/RIGIDPANEL \?= 1/' $MAKEFILE +sed -i '' -e 's/^#define REPRAP_DISCOUNT_SMART_CONTROLLER/\/\/#define REPRAP_DISCOUNT_SMART_CONTROLLER/' $CONFIGURATION_H +sed -i '' -e 's/^\/\/#define RIGIDPANEL/#define RIGIDPANEL/' $CONFIGURATION_H + ############### + ## Regular Single + ############### + sed -i '' -e 's/^[\/]*#define RIGIDBOT_SIZE.*/#define RIGIDBOT_SIZE 1/' $CONFIGURATION_H + sed -i '' -e 's/^#define EXTRUDERS.*/#define EXTRUDERS 1/' $CONFIGURATION_H + make clean + make + mv -f ${BUILD_DIR}/Marlin.hex ${RBCE_PREFIX}_Regular_Single_RigidPanel.hex + ############### + ## Regular Dual + ############### + sed -i '' -e 's/^[\/]*#define RIGIDBOT_SIZE.*/#define RIGIDBOT_SIZE 1/' $CONFIGURATION_H + sed -i '' -e 's/^#define EXTRUDERS.*/#define EXTRUDERS 2/' $CONFIGURATION_H + make clean + make + mv -f ${BUILD_DIR}/Marlin.hex ${RBCE_PREFIX}_Regular_Dual_RigidPanel.hex + ############### + ## Big Single + ############### + sed -i '' -e 's/^[\/]*#define RIGIDBOT_SIZE.*/#define RIGIDBOT_SIZE 2/' $CONFIGURATION_H + sed -i '' -e 's/^#define EXTRUDERS.*/#define EXTRUDERS 1/' $CONFIGURATION_H + make clean + make + mv -f ${BUILD_DIR}/Marlin.hex ${RBCE_PREFIX}_Big_Single_RigidPanel.hex + ############### + ## Big Dual + ############### + sed -i '' -e 's/^[\/]*#define RIGIDBOT_SIZE.*/#define RIGIDBOT_SIZE 2/' $CONFIGURATION_H + sed -i '' -e 's/^#define EXTRUDERS.*/#define EXTRUDERS 2/' $CONFIGURATION_H + make clean + make + mv -f ${BUILD_DIR}/Marlin.hex ${RBCE_PREFIX}_Big_Dual_RigidPanel.hex + + +################## +## RepRap Discount Full Graphic LCD +################## +sed -i '' -e 's/^U8GLIB .*/U8GLIB \?= 1/' $MAKEFILE +sed -i '' -e 's/^RIGIDPANEL .*/RIGIDPANEL \?= 0/' $MAKEFILE +sed -i '' -e 's/^\/\/#define REPRAP_DISCOUNT_SMART_CONTROLLER/#define REPRAP_DISCOUNT_SMART_CONTROLLER/' $CONFIGURATION_H +sed -i '' -e 's/^#define RIGIDPANEL/\/\/#define RIGIDPANEL/' $CONFIGURATION_H + ############### + ## Regular Single + ############### + sed -i '' -e 's/^[\/]*#define RIGIDBOT_SIZE.*/#define RIGIDBOT_SIZE 1/' $CONFIGURATION_H + sed -i '' -e 's/^#define EXTRUDERS.*/#define EXTRUDERS 1/' $CONFIGURATION_H + make clean + make + mv -f ${BUILD_DIR}/Marlin.hex ${RBCE_PREFIX}_Regular_Single_FullGfx.hex + ############### + ## Regular Dual + ############### + sed -i '' -e 's/^[\/]*#define RIGIDBOT_SIZE.*/#define RIGIDBOT_SIZE 1/' $CONFIGURATION_H + sed -i '' -e 's/^#define EXTRUDERS.*/#define EXTRUDERS 2/' $CONFIGURATION_H + make clean + make + mv -f ${BUILD_DIR}/Marlin.hex ${RBCE_PREFIX}_Regular_Dual_FullGfx.hex + ############### + ## Big Single + ############### + sed -i '' -e 's/^[\/]*#define RIGIDBOT_SIZE.*/#define RIGIDBOT_SIZE 2/' $CONFIGURATION_H + sed -i '' -e 's/^#define EXTRUDERS.*/#define EXTRUDERS 1/' $CONFIGURATION_H + make clean + make + mv -f ${BUILD_DIR}/Marlin.hex ${RBCE_PREFIX}_Big_Single_FullGfx.hex + ############### + ## Big Dual + ############### + sed -i '' -e 's/^[\/]*#define RIGIDBOT_SIZE.*/#define RIGIDBOT_SIZE 2/' $CONFIGURATION_H + sed -i '' -e 's/^#define EXTRUDERS.*/#define EXTRUDERS 2/' $CONFIGURATION_H + make clean + make + mv -f ${BUILD_DIR}/Marlin.hex ${RBCE_PREFIX}_Big_Dual_FullGfx.hex + + +# Clean up +mv ${MAKEFILE}.premangle $MAKEFILE +mv ${CONFIGURATION_H}.premangle $CONFIGURATION_H +mv ${CONFIGURATION_ADV_H}.premangle $CONFIGURATION_ADV_H + diff --git a/Marlin/language.h b/Marlin/language.h index 3e6e1704384b..52311366eebe 100644 --- a/Marlin/language.h +++ b/Marlin/language.h @@ -1,5 +1,6 @@ #ifndef LANGUAGE_H #define LANGUAGE_H +#include "Configuration.h" // NOTE: IF YOU CHANGE THIS FILE / MERGE THIS FILE WITH CHANGES // @@ -39,6 +40,9 @@ #elif MOTHERBOARD == 88 #define MACHINE_NAME "Makibox" #define FIRMWARE_URL "https://github.com/ErikZalm/Marlin/" +#elif MOTHERBOARD == 42 + #define MACHINE_NAME "RigidBot" + #define FIRMWARE_URL "http://inventapart.com" #else #ifdef CUSTOM_MENDEL_NAME #define MACHINE_NAME CUSTOM_MENDEL_NAME @@ -143,6 +147,17 @@ #define MSG_BABYSTEPPING_Z "Babystepping Z" #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Error in menu structure" +#ifdef USB_LCD + #undef MSG_SD_INIT_FAIL + #define MSG_SD_INIT_FAIL "USB Drive init fail" + #undef MSG_SD_CARD_OK + #define MSG_SD_CARD_OK "USB Drive ok" + #undef MSG_SD_PRINTING_BYTE + #define MSG_SD_PRINTING_BYTE "USB Drive printing byte " + #undef MSG_SD_NOT_PRINTING + #define MSG_SD_NOT_PRINTING "Not USB Drive printing" +#endif + #if LANGUAGE_CHOICE == 1 // LCD Menu Messages @@ -196,7 +211,7 @@ #define MSG_FLOW0 "Flow 0" #define MSG_FLOW1 "Flow 1" #define MSG_FLOW2 "Flow 2" - #define MSG_CONTROL "Control" + #define MSG_CONTROL "Settings" #define MSG_MIN " \002 Min" #define MSG_MAX " \002 Max" #define MSG_FACTOR " \002 Fact" @@ -228,9 +243,9 @@ #define MSG_TEMPERATURE "Temperature" #define MSG_MOTION "Motion" #define MSG_CONTRAST "LCD contrast" - #define MSG_STORE_EPROM "Store memory" - #define MSG_LOAD_EPROM "Load memory" - #define MSG_RESTORE_FAILSAFE "Restore failsafe" + #define MSG_STORE_EPROM "Store settings" + #define MSG_LOAD_EPROM "Load settings" + #define MSG_RESTORE_FAILSAFE "Restore defaults" #define MSG_REFRESH "Refresh" #define MSG_WATCH "Info screen" #define MSG_PREPARE "Prepare" @@ -265,6 +280,23 @@ #define MSG_BABYSTEP_Y "Babystep Y" #define MSG_BABYSTEP_Z "Babystep Z" #define MSG_ENDSTOP_ABORT "Endstop abort" + #define MSG_HEAT_COOL "Heat/Cool" + #define MSG_UTILITIES "Utilities" + + #ifdef USB_LCD + #undef MSG_SD_INSERTED + #define MSG_SD_INSERTED "USB inserted" + #undef MSG_SD_REMOVED + #define MSG_SD_REMOVED "USB removed" + #undef MSG_CARD_MENU + #define MSG_CARD_MENU "Print from USB" + #undef MSG_NO_CARD + #define MSG_NO_CARD "No USB drive" + #undef MSG_INIT_SDCARD + #define MSG_INIT_SDCARD "Init. USB Drive" + #undef MSG_CNG_SDCARD + #define MSG_CNG_SDCARD "Change USB Drive" + #endif #endif @@ -393,7 +425,23 @@ #define MSG_BABYSTEP_Y "Babystep Y" #define MSG_BABYSTEP_Z "Babystep Z" #define MSG_ENDSTOP_ABORT "Blad wyl. kranc." - #define MSG_CONTRAST "Kontrast" + #define MSG_HEAT_COOL "Heat/Cool" + #define MSG_UTILITIES "Utilities" + + #ifdef USB_LCD + #undef MSG_SD_INSERTED + #define MSG_SD_INSERTED "USB inserted" + #undef MSG_SD_REMOVED + #define MSG_SD_REMOVED "USB removed" + #undef MSG_CARD_MENU + #define MSG_CARD_MENU "Print from USB" + #undef MSG_NO_CARD + #define MSG_NO_CARD "No USB drive" + #undef MSG_INIT_SDCARD + #define MSG_INIT_SDCARD "Init. USB Drive" + #undef MSG_CNG_SDCARD + #define MSG_CNG_SDCARD "Change USB Drive" + #endif #endif @@ -522,7 +570,23 @@ #define MSG_BABYSTEP_Y "Babystep Y" #define MSG_BABYSTEP_Z "Babystep Z" #define MSG_ENDSTOP_ABORT "Butee abandon" - #define MSG_CONTRAST "Contrast" + #define MSG_HEAT_COOL "Heat/Cool" + #define MSG_UTILITIES "Utilities" + + #ifdef USB_LCD + #undef MSG_SD_INSERTED + #define MSG_SD_INSERTED "USB inserted" + #undef MSG_SD_REMOVED + #define MSG_SD_REMOVED "USB removed" + #undef MSG_CARD_MENU + #define MSG_CARD_MENU "Print from USB" + #undef MSG_NO_CARD + #define MSG_NO_CARD "No USB drive" + #undef MSG_INIT_SDCARD + #define MSG_INIT_SDCARD "Init. USB Drive" + #undef MSG_CNG_SDCARD + #define MSG_CNG_SDCARD "Change USB Drive" + #endif #endif @@ -652,7 +716,23 @@ #define MSG_BABYSTEP_Y "Babystep Y" #define MSG_BABYSTEP_Z "Babystep Z" #define MSG_ENDSTOP_ABORT "Endstop abort" - #define MSG_CONTRAST "Contrast" + #define MSG_HEAT_COOL "Heat/Cool" + #define MSG_UTILITIES "Utilities" + + #ifdef USB_LCD + #undef MSG_SD_INSERTED + #define MSG_SD_INSERTED "USB inserted" + #undef MSG_SD_REMOVED + #define MSG_SD_REMOVED "USB removed" + #undef MSG_CARD_MENU + #define MSG_CARD_MENU "Print from USB" + #undef MSG_NO_CARD + #define MSG_NO_CARD "No USB drive" + #undef MSG_INIT_SDCARD + #define MSG_INIT_SDCARD "Init. USB Drive" + #undef MSG_CNG_SDCARD + #define MSG_CNG_SDCARD "Change USB Drive" + #endif #endif @@ -788,6 +868,23 @@ #define MSG_BABYSTEP_Z "Babystep Z" #define MSG_ENDSTOP_ABORT "Endstop abort" #define MSG_CONTRAST "Contraste" + #define MSG_HEAT_COOL "Heat/Cool" + #define MSG_UTILITIES "Utilities" + + #ifdef USB_LCD + #undef MSG_SD_INSERTED + #define MSG_SD_INSERTED "USB inserted" + #undef MSG_SD_REMOVED + #define MSG_SD_REMOVED "USB removed" + #undef MSG_CARD_MENU + #define MSG_CARD_MENU "Print from USB" + #undef MSG_NO_CARD + #define MSG_NO_CARD "No USB drive" + #undef MSG_INIT_SDCARD + #define MSG_INIT_SDCARD "Init. USB Drive" + #undef MSG_CNG_SDCARD + #define MSG_CNG_SDCARD "Change USB Drive" + #endif #endif @@ -914,7 +1011,23 @@ #define MSG_BABYSTEP_Y "Babystep Y" #define MSG_BABYSTEP_Z "Babystep Z" #define MSG_ENDSTOP_ABORT "Endstop abort" - #define MSG_CONTRAST "Contrast" + #define MSG_HEAT_COOL "Heat/Cool" + #define MSG_UTILITIES "Utilities" + + #ifdef USB_LCD + #undef MSG_SD_INSERTED + #define MSG_SD_INSERTED "USB inserted" + #undef MSG_SD_REMOVED + #define MSG_SD_REMOVED "USB removed" + #undef MSG_CARD_MENU + #define MSG_CARD_MENU "Print from USB" + #undef MSG_NO_CARD + #define MSG_NO_CARD "No USB drive" + #undef MSG_INIT_SDCARD + #define MSG_INIT_SDCARD "Init. USB Drive" + #undef MSG_CNG_SDCARD + #define MSG_CNG_SDCARD "Change USB Drive" + #endif #endif @@ -1041,7 +1154,23 @@ #define MSG_BABYSTEP_Y "Babystep Y" #define MSG_BABYSTEP_Z "Babystep Z" #define MSG_ENDSTOP_ABORT "Endstop abort" - #define MSG_CONTRAST "Contrast" + #define MSG_HEAT_COOL "Heat/Cool" + #define MSG_UTILITIES "Utilities" + + #ifdef USB_LCD + #undef MSG_SD_INSERTED + #define MSG_SD_INSERTED "USB inserted" + #undef MSG_SD_REMOVED + #define MSG_SD_REMOVED "USB removed" + #undef MSG_CARD_MENU + #define MSG_CARD_MENU "Print from USB" + #undef MSG_NO_CARD + #define MSG_NO_CARD "No USB drive" + #undef MSG_INIT_SDCARD + #define MSG_INIT_SDCARD "Init. USB Drive" + #undef MSG_CNG_SDCARD + #define MSG_CNG_SDCARD "Change USB Drive" + #endif #endif @@ -1175,6 +1304,23 @@ #define MSG_BABYSTEP_Z "Babystep Z" #define MSG_ENDSTOP_ABORT "Endstop abort" #define MSG_CONTRAST "Contrast" + #define MSG_HEAT_COOL "Heat/Cool" + #define MSG_UTILITIES "Utilities" + + #ifdef USB_LCD + #undef MSG_SD_INSERTED + #define MSG_SD_INSERTED "USB inserted" + #undef MSG_SD_REMOVED + #define MSG_SD_REMOVED "USB removed" + #undef MSG_CARD_MENU + #define MSG_CARD_MENU "Print from USB" + #undef MSG_NO_CARD + #define MSG_NO_CARD "No USB drive" + #undef MSG_INIT_SDCARD + #define MSG_INIT_SDCARD "Init. USB Drive" + #undef MSG_CNG_SDCARD + #define MSG_CNG_SDCARD "Change USB Drive" + #endif #endif @@ -1389,6 +1535,7 @@ #define MSG_RECTRACT "Retraer" #define MSG_TEMPERATURE "Temperatura" #define MSG_MOTION "Movimiento" + #define MSG_CONTRAST "Contrast" #define MSG_STORE_EPROM "Alzar Memoria" #define MSG_LOAD_EPROM "Cargar Memoria" #define MSG_RESTORE_FAILSAFE "Rest. d'emerchen." @@ -1435,7 +1582,23 @@ #define MSG_BABYSTEP_Y "Babystep Y" #define MSG_BABYSTEP_Z "Babystep Z" #define MSG_ENDSTOP_ABORT "Endstop abort" - #define MSG_CONTRAST "Contrast" + #define MSG_HEAT_COOL "Heat/Cool" + #define MSG_UTILITIES "Utilities" + + #ifdef USB_LCD + #undef MSG_SD_INSERTED + #define MSG_SD_INSERTED "USB inserted" + #undef MSG_SD_REMOVED + #define MSG_SD_REMOVED "USB removed" + #undef MSG_CARD_MENU + #define MSG_CARD_MENU "Print from USB" + #undef MSG_NO_CARD + #define MSG_NO_CARD "No USB drive" + #undef MSG_INIT_SDCARD + #define MSG_INIT_SDCARD "Init. USB Drive" + #undef MSG_CNG_SDCARD + #define MSG_CNG_SDCARD "Change USB Drive" + #endif #endif @@ -1561,6 +1724,23 @@ #define MSG_BABYSTEP_Y "Babystap Y" #define MSG_BABYSTEP_Z "Babystap Z" #define MSG_ENDSTOP_ABORT "Endstop afbr." + #define MSG_HEAT_COOL "Heat/Cool" + #define MSG_UTILITIES "Utilities" + + #ifdef USB_LCD + #undef MSG_SD_INSERTED + #define MSG_SD_INSERTED "USB inserted" + #undef MSG_SD_REMOVED + #define MSG_SD_REMOVED "USB removed" + #undef MSG_CARD_MENU + #define MSG_CARD_MENU "Print from USB" + #undef MSG_NO_CARD + #define MSG_NO_CARD "No USB drive" + #undef MSG_INIT_SDCARD + #define MSG_INIT_SDCARD "Init. USB Drive" + #undef MSG_CNG_SDCARD + #define MSG_CNG_SDCARD "Change USB Drive" + #endif #endif @@ -1687,6 +1867,23 @@ #define MSG_BABYSTEP_Y "Babystep Y" #define MSG_BABYSTEP_Z "Babystep Z" #define MSG_ENDSTOP_ABORT "Endstop abort" + #define MSG_HEAT_COOL "Heat/Cool" + #define MSG_UTILITIES "Utilities" + + #ifdef USB_LCD + #undef MSG_SD_INSERTED + #define MSG_SD_INSERTED "USB inserted" + #undef MSG_SD_REMOVED + #define MSG_SD_REMOVED "USB removed" + #undef MSG_CARD_MENU + #define MSG_CARD_MENU "Print from USB" + #undef MSG_NO_CARD + #define MSG_NO_CARD "No USB drive" + #undef MSG_INIT_SDCARD + #define MSG_INIT_SDCARD "Init. USB Drive" + #undef MSG_CNG_SDCARD + #define MSG_CNG_SDCARD "Change USB Drive" + #endif #endif @@ -1812,6 +2009,23 @@ #define MSG_BABYSTEP_Y "Babystep Y" #define MSG_BABYSTEP_Z "Babystep Z" #define MSG_ENDSTOP_ABORT "Endstop deuseztat" + #define MSG_HEAT_COOL "Heat/Cool" + #define MSG_UTILITIES "Utilities" + + #ifdef USB_LCD + #undef MSG_SD_INSERTED + #define MSG_SD_INSERTED "USB inserted" + #undef MSG_SD_REMOVED + #define MSG_SD_REMOVED "USB removed" + #undef MSG_CARD_MENU + #define MSG_CARD_MENU "Print from USB" + #undef MSG_NO_CARD + #define MSG_NO_CARD "No USB drive" + #undef MSG_INIT_SDCARD + #define MSG_INIT_SDCARD "Init. USB Drive" + #undef MSG_CNG_SDCARD + #define MSG_CNG_SDCARD "Change USB Drive" + #endif #endif diff --git a/Marlin/pins.h b/Marlin/pins.h index 13cb9053e942..966c18667494 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -2889,6 +2889,154 @@ DaveX plan for Teensylu/printrboard-type pinouts (ref teensylu & sprinter) for a #endif +/**************************************************************************************** +* RigidBot Arduino Mega pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 42 + #define KNOWN_BOARD 1 + + #define LARGE_FLASH true + + #define X_STEP_PIN 54 + #define X_DIR_PIN 55 + #define X_ENABLE_PIN 38 + #define X_MIN_PIN 3 + #define X_MAX_PIN 2 + + #define Y_STEP_PIN 60 + #define Y_DIR_PIN 61 + #define Y_ENABLE_PIN 56 + #define Y_MIN_PIN 14 + #define Y_MAX_PIN 15 + + #define Z_STEP_PIN 46 + #define Z_DIR_PIN 48 + #define Z_ENABLE_PIN 62 + #define Z_MIN_PIN 18 + #define Z_MAX_PIN 19 + + #define Z2_STEP_PIN 36 + #define Z2_DIR_PIN 34 + #define Z2_ENABLE_PIN 30 + + #define E0_STEP_PIN 36 // 26 + #define E0_DIR_PIN 34 // 28 + #define E0_ENABLE_PIN 30 // 24 + + #define E1_STEP_PIN 26 //36 + #define E1_DIR_PIN 28 //34 + #define E1_ENABLE_PIN 24 //30 + + #define SDPOWER -1 + #define SDSS 53 + #define LED_PIN 13 + + #define FAN_PIN 8 //11 // IO pin. Buffer needed + + #define PS_ON_PIN -1 + + #define HEATER_0_PIN 9 // EXTRUDER 1 + #define HEATER_1_PIN 12 // EXTRUDER 2 (FAN On Sprinter) + #define HEATER_2_PIN -1 + #define TEMP_0_PIN 14 // ANALOG NUMBERING + #define TEMP_1_PIN 13 // ANALOG NUMBERING + #define TEMP_2_PIN -1 // ANALOG NUMBERING + #define HEATER_BED_PIN 10 // BED + #define TEMP_BED_PIN 15 // ANALOG NUMBERING + + #ifdef NUM_SERVOS + #define SERVO0_PIN 11 + #if NUM_SERVOS > 1 + #define SERVO1_PIN 6 + #endif + #if NUM_SERVOS > 2 + #define SERVO2_PIN 5 + #endif + #if NUM_SERVOS > 3 + #define SERVO3_PIN 4 + #endif + #endif + + #define STEPPER_RESET_PIN 41 // #define STEPPER_RESET_FIX in Configuration.h to use this during boot + + // LCD Panel options for the RigidBoard + #define LCD_PINS_RS 16 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 23 + #define LCD_PINS_D5 25 + #define LCD_PINS_D6 27 + #define LCD_PINS_D7 29 + + #ifdef REPRAP_DISCOUNT_SMART_CONTROLLER + #define BEEPER 37 + + #define BTN_EN1 31 + #define BTN_EN2 33 + #define BTN_ENC 35 + + #define SDCARDDETECT 22 + + #define KILL_PIN 32 + + #elif defined(RIGIDPANEL) + #define BEEPER -1 + + #define BTN_UP 37 + #define BTN_DWN 35 + #define BTN_LFT 33 + #define BTN_RT 32 + + #define BTN_EN1 -1 + #define BTN_EN2 -1 + #define BTN_ENC 31 + + #define SDCARDDETECT 22 + + #define KILL_PIN -1 + + #else + #define BEEPER 33 // Beeper on AUX-4 + #define KILL_PIN -1 + + //buttons are directly attached using AUX-2 + #ifdef REPRAPWORLD_KEYPAD + #define BTN_EN1 64 // encoder + #define BTN_EN2 59 // encoder + #define BTN_ENC 63 // enter button + #define SHIFT_OUT 40 // shift register + #define SHIFT_CLK 44 // shift register + #define SHIFT_LD 42 // shift register + #else + #define BTN_UP 37 + #define BTN_DWN 35 + #define BTN_LFT 33 + #define BTN_RT 32 + #define BTN_ENT 31 + //#define BTN_EN1 37 + //#define BTN_EN2 35 + //#define BTN_ENC 31 //the click + #endif + + #ifdef G3D_PANEL + #define SDCARDDETECT 49 + #else + #define SDCARDDETECT -1 // Ramps does not use this port + #endif + + #endif + + #ifndef SDSUPPORT + // these pins are defined in the SD library if building with SD support + #define MAX_SCK_PIN 52 + #define MAX_MISO_PIN 50 + #define MAX_MOSI_PIN 51 + #define MAX6675_SS 53 + #else + #define MAX6675_SS 49 + #endif + +#endif //MOTHERBOARD == 42 (RIGID_BOARD) #ifndef KNOWN_BOARD diff --git a/Marlin/rigidpanel.cpp b/Marlin/rigidpanel.cpp new file mode 100755 index 000000000000..becf7ae789db --- /dev/null +++ b/Marlin/rigidpanel.cpp @@ -0,0 +1,1411 @@ +#include "temperature.h" +#include "rigidpanel.h" + +#ifdef RIGIDPANEL + +#include "Marlin.h" +#include "language.h" +#include "cardreader.h" +#include "temperature.h" +#include "stepper.h" +#include "ConfigurationStore.h" + +bool lcdFastUpdate = false; // Used for higher update scrolling of SD card filenames +bool timeoutSuspend = false; // Used to disable tomeout to status screen (for leveling & filament change, etc.) +bool invertEncoderDir = false; // Used to invert encoder direction for menu navigation when used with up/down buttons +bool encoderCoarseEnabled = false; // Used to invert encoder direction for menu navigation when used with up/down buttons + +/* Configuration settings */ +int plaPreheatHotendTemp; +int plaPreheatHPBTemp; +int plaPreheatFanSpeed; + +int absPreheatHotendTemp; +int absPreheatHPBTemp; +int absPreheatFanSpeed; +/* !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_MSG; + +#include "ultralcd_implementation_RigidPanel.h" + +/** forward declerations **/ + +void copy_and_scalePID_i(); +void copy_and_scalePID_d(); + +/* Different menus */ +static void lcd_status_screen(); +static void lcd_main_menu(); +static void lcd_tune_menu(); +static void lcd_prepare_menu(); +static void lcd_heat_cool_menu(); +static void lcd_bed_level_menu(); +static void lcd_move_menu(); +static void lcd_control_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_retract_menu(); +static void lcd_utilities_menu(); +static void lcd_sdcard_menu(); + +static void lcd_quick_feedback();//Cause an LCD refresh, and give the user visual or audiable feedback that something has happend + +/* Different types of actions that can be used in menuitems. */ +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_sdfile(const char* filename, char* longFilename, uint8_t item); +static void menu_action_sddirectory(const char* filename, char* longFilename, uint8_t item); +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_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_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 +#define ENCODER_FEEDRATE_DEADZONE 0 +#define ENCODER_STEPS_PER_MENU_ITEM 1 + +/* Helper macros for menus */ +#define START_MENU() do { \ + invertEncoderDir = true; \ + 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; \ + 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 = 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 ((LCD_CLICKED || buttons&B_RI) && (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr) {\ + lcd_quick_feedback(); \ + menu_action_ ## type ( args ); \ + return;\ + }\ + }\ + _menuItemNr++;\ +} while(0) +#define MENU_ITEM_BACK_HIDDEN(type, label, args...) do { \ + if ( buttons&B_LE ) { \ + lcd_quick_feedback(); \ + menu_action_ ## type ( args ); \ + return;\ + } \ +} while(0) +#ifdef HIDE_BACK_MENUS +#define MENU_ITEM_BACK MENU_ITEM_BACK_HIDDEN +#else +#define MENU_ITEM_BACK(type, label, args...) do { \ + MENU_ITEM_BACK_HIDDEN(type, label, ## args); \ + MENU_ITEM(type, label, ## args); \ +} while(0) +#endif +#define MENU_ITEM_DUMMY() do { _menuItemNr++; } while(0) +#define MENU_ITEM_EDIT(type, label, args...) MENU_ITEM(setting_edit_ ## type, label, PSTR(label) , ## args ) +#define MENU_ITEM_EDIT_CALLBACK(type, label, args...) MENU_ITEM(setting_edit_callback_ ## type, label, PSTR(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 */ +volatile uint8_t buttons;//Contains the bits of the currently pressed buttons. + +uint8_t currentMenuViewOffset; /* scroll offset in the current menu */ +uint32_t blocking_enc; +uint8_t lastEncoderBits; +int8_t encoderDiff; /* encoderDiff is updated from interrupt context and added to encoderPosition every LCD update */ +int8_t encoderDiff2; +uint32_t encoderPosition; +#if (SDCARDDETECT > 0) +bool lcd_oldcardstatus; +#endif + +menuFunc_t currentMenu = lcd_status_screen; /* function pointer to the currently active menu */ +menuFunc_t backMenu = currentMenu; +uint32_t lcd_next_update_millis; +uint32_t lcd_status_update_millis; +//uint8_t lcd_status_update_delay; +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 atleast 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; + +// placeholders for Ki and Kd edits +float raw_Ki, raw_Kd; + +/* Main status screen. It's up to the implementation specific part to show what is needed. As this is very display dependend */ +static void lcd_status_screen() +{ + static int feedLast = 0; // For tracking feedmultiply changes + + //if (lcd_status_update_delay) + //lcd_status_update_delay--; + //else + //lcdDrawUpdate = 1; + + if ( millis() >= lcd_status_update_millis ) + lcdDrawUpdate = 1; + + if (lcdDrawUpdate) + { + lcd_implementation_status_screen(); +// lcd_status_update_delay = 10; /* redraw the main screen every second. This is easier then trying keep track of all things that change on the screen */ + lcd_status_update_millis = millis() + LCD_STATUS_UPDATE_INTERVAL; + } + + if (LCD_CLICKED) + { + currentMenu = lcd_main_menu; + encoderPosition = 0; + lcd_quick_feedback(); + } + + // 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; + } + + if (feedmultiply < 10) + feedmultiply = 10; + if (feedmultiply > 999) + feedmultiply = 999; + + if ( feedmultiply != feedLast ) + lcd_status_update_millis = 0; // Force update on next cycle + //lcd_status_update_delay = 0; // Force update on next cycle + feedLast = feedmultiply; +} + +//#################################################################################################### +// Main status display screen +//#################################################################################################### + +static void lcd_return_to_status() +{ + encoderPosition = 0; + currentMenu = lcd_status_screen; +} + +static void lcd_sdcard_pause() +{ + card.pauseSDPrint(); +} +static void lcd_sdcard_resume() +{ + card.startFileprint(); +} +static void lcd_sdcard_stop() +{ + card.sdprinting = false; + card.closefile(); + quickStop(); + if(SD_FINISHED_STEPPERRELEASE) + { + enquecommand_P(PSTR(SD_FINISHED_RELEASECOMMAND)); + } + autotempShutdown(); +} + +/* Menu implementation */ +static void lcd_main_menu() +{ + START_MENU(); + MENU_ITEM_BACK(back, MSG_WATCH, lcd_status_screen); +#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(function, MSG_STOP_PRINT, lcd_sdcard_stop); + }else{ + 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 //SDSUPPORT + + if (movesplanned() || IS_SD_PRINTING) + { + MENU_ITEM(submenu, MSG_TUNE, lcd_tune_menu); + }else{ + MENU_ITEM(submenu, MSG_PREPARE, lcd_prepare_menu); + } + MENU_ITEM(submenu, MSG_CONTROL, lcd_control_menu); + MENU_ITEM(submenu, MSG_UTILITIES, lcd_utilities_menu); + END_MENU(); +} + +#ifdef SDSUPPORT +static void lcd_autostart_sd() +{ + card.lastnr=0; + card.setroot(); + card.checkautostart(true); +} +#endif + +//#################################################################################################### +// Bed leveling routines +//#################################################################################################### +int levelStep = 0; +int levelStepLast = 0; +int levelType = 0; +bool levelHomed = false; +bool moveHead = false; +char cmd[30]; + +#define BED_LEVEL_Z_LIFT 5 + +// Point list for bed leveling script +const uint16_t LEVEL_POINTS[][2] = { + { BED_LEVEL_Z_LIFT, 4 }, // First record is { Z_LIFT, NUM_POINTS } + { X_MIN_POS+35, Y_CENTER_POS-50 }, + { X_MIN_POS+35, Y_CENTER_POS+50 }, + { X_MAX_POS-35, Y_CENTER_POS+50 }, + { X_MAX_POS-35, Y_CENTER_POS-50 } +}; + +// Point list for bed leveling extents script +const uint16_t LEVEL_EXTENTS[][2] = { + { BED_LEVEL_Z_LIFT, 5 }, // First record is { Z_LIFT, NUM_POINTS } + { X_MIN_POS+10, Y_MIN_POS+10 }, + { X_MIN_POS+10, Y_MAX_POS-10 }, + { X_MAX_POS-10, Y_MAX_POS-10 }, + { X_MAX_POS-10, Y_MIN_POS+10 }, + { X_CENTER_POS, Y_CENTER_POS } +}; + +static void lcd_bed_level_doCurrent() +{ + // Always move up a little first, and set high speed + sprintf_P(cmd, PSTR("G0 Z%d F10000"), LEVEL_POINTS[0][0]); + enquecommand(cmd); + // Home axes if not already homed + if ( !levelHomed ) + { + enquecommand_P(PSTR("G28")); // Home axes + levelHomed = true; + sprintf_P(cmd, PSTR("G0 Z%d F10000"), LEVEL_POINTS[0][0]); + enquecommand(cmd); + } + if ( levelType == 0 ) + { + if ( levelStep < LEVEL_POINTS[0][1] ) + { + sprintf_P(cmd, PSTR("G0 X%d Y%d"), LEVEL_POINTS[levelStep+1][0], LEVEL_POINTS[levelStep+1][1]); + enquecommand(cmd); + enquecommand_P(PSTR("G0 Z0")); + } + else + { + currentMenu = &lcd_bed_level_menu; + } + } + else + { + if ( levelStep < LEVEL_EXTENTS[0][1] ) + { + sprintf_P(cmd, PSTR("G0 X%d Y%d"), LEVEL_EXTENTS[levelStep+1][0], LEVEL_EXTENTS[levelStep+1][1]); + enquecommand(cmd); + enquecommand_P(PSTR("G0 Z0")); + } + else + { + currentMenu = &lcd_bed_level_menu; + } + } +} +static void lcd_bed_level_doNext() +{ + levelStep++; + lcd_bed_level_doCurrent(); +} +static void lcd_bed_level_doLast() +{ + levelStep--; + lcd_bed_level_doCurrent(); +} +static void lcd_bed_level_moveHead() +{ + moveHead = true; + sprintf_P(cmd, PSTR("G0 Z%d F10000"), BED_LEVEL_Z_LIFT); + enquecommand(cmd); + sprintf_P(cmd, PSTR("G0 X%d Y%d"), X_CENTER_POS, Y_CENTER_POS); + enquecommand(cmd); + encoderPosition = 0; +} +static void lcd_bed_level_moveHead_return() +{ + moveHead = false; + lcd_bed_level_doCurrent(); +} +static void lcd_bed_level_disable_steppers() +{ + levelStep--; + enquecommand_P(PSTR("M84")); + levelHomed = false; + encoderPosition = 0; +} +static void lcd_bed_level_start() +{ + levelStep = -1; + levelType = 0; + lcd_bed_level_doNext(); +} +static void lcd_bed_level_extents() +{ + levelStep = -1; + levelType = 1; + lcd_bed_level_doNext(); +} +static void lcd_bed_level_cancel() +{ + lcd_bed_level_moveHead(); + lcd_bed_level_menu(); +} +static void lcd_bed_level_syncZ() +{ + +} +static void lcd_bed_level_run() +{ + if ( levelStep != levelStepLast ) + { + lcd_quick_feedback(); + encoderPosition = 0; + } + levelStepLast = levelStep; + + START_MENU(); + if ( moveHead || (!levelHomed && levelStep >= 0) ) + { + if ( moveHead ) + MENU_ITEM(function, "Resume", lcd_bed_level_moveHead_return); + else + MENU_ITEM(function, "Resume", lcd_bed_level_doNext); + MENU_ITEM_BACK(back, "Cancel", lcd_bed_level_menu); + } + else if ( levelStep == -1 ) + { + MENU_ITEM_BACK(back, MSG_UTILITIES, lcd_utilities_menu); + MENU_ITEM(function, "Level Bed", lcd_bed_level_start); + MENU_ITEM(function, "Check Extents", lcd_bed_level_extents); +// MENU_ITEM(submenu, "Sync Z Steppers", lcd_bed_level_syncZ); + } + else + { + timeoutSuspend = true; + MENU_ITEM(function, "Continue", lcd_bed_level_doNext); + MENU_ITEM(function, "Move Head", lcd_bed_level_moveHead); + if ( levelStep > 0 ) + { + MENU_ITEM(function, "Go Back", lcd_bed_level_doLast); + } + MENU_ITEM(function, MSG_DISABLE_STEPPERS, lcd_bed_level_disable_steppers); + MENU_ITEM_BACK(back, "Cancel", lcd_bed_level_cancel); + } + END_MENU(); +} + +static void lcd_bed_level_menu() +{ + timeoutSuspend = false; + levelStep = -1; + levelStepLast = 0; + levelType = 0; + levelHomed = false; + moveHead = false; + currentMenu = &lcd_bed_level_run; +} + +//#################################################################################################### +// Tune / Prepare +//#################################################################################################### +// Prepare will show when not running +static void lcd_prepare_menu() +{ + START_MENU(); + MENU_ITEM_BACK(back, MSG_MAIN, lcd_main_menu); + MENU_ITEM(submenu, MSG_HEAT_COOL, lcd_heat_cool_menu); + MENU_ITEM(submenu, MSG_MOVE_AXIS, lcd_move_menu); + MENU_ITEM(gcode, MSG_AUTO_HOME, PSTR("G28")); + MENU_ITEM(gcode, MSG_DISABLE_STEPPERS, PSTR("M84")); + //MENU_ITEM(gcode, MSG_SET_ORIGIN, PSTR("G92 X0 Y0 Z0")); + END_MENU(); +} +// Tune will show while running +static void lcd_tune_menu() +{ + START_MENU(); + MENU_ITEM_BACK(back, MSG_MAIN, lcd_main_menu); + MENU_ITEM_EDIT(int3, MSG_SPEED, &feedmultiply, 10, 999); + MENU_ITEM_EDIT(int3, MSG_NOZZLE, &target_temperature[0], 0, HEATER_0_MAXTEMP - 15); +#if TEMP_SENSOR_1 != 0 + MENU_ITEM_EDIT(int3, MSG_NOZZLE1, &target_temperature[1], 0, HEATER_1_MAXTEMP - 15); +#endif +#if TEMP_SENSOR_2 != 0 + MENU_ITEM_EDIT(int3, MSG_NOZZLE2, &target_temperature[2], 0, HEATER_2_MAXTEMP - 15); +#endif +#if TEMP_SENSOR_BED != 0 + MENU_ITEM_EDIT(int3, MSG_BED, &target_temperature_bed, 0, BED_MAXTEMP - 15); +#endif + MENU_ITEM_EDIT(int3, MSG_FAN_SPEED, &fanSpeed, 0, 255); + MENU_ITEM_EDIT(int3, MSG_FLOW, &extrudemultiply, 10, 999); +#ifdef FILAMENTCHANGEENABLE + MENU_ITEM(gcode, MSG_FILAMENTCHANGE, PSTR("M600")); +#endif + END_MENU(); +} + +//#################################################################################################### +// Temperature control routines +//#################################################################################################### + +void lcd_preheat_pla() +{ + setTargetHotend0(plaPreheatHotendTemp); + setTargetHotend1(plaPreheatHotendTemp); + setTargetHotend2(plaPreheatHotendTemp); + setTargetBed(plaPreheatHPBTemp); + fanSpeed = plaPreheatFanSpeed; + lcd_return_to_status(); + setWatch(); // heater sanity check timer +} +void lcd_preheat_abs() +{ + setTargetHotend0(absPreheatHotendTemp); + setTargetHotend1(absPreheatHotendTemp); + setTargetHotend2(absPreheatHotendTemp); + setTargetBed(absPreheatHPBTemp); + fanSpeed = absPreheatFanSpeed; + lcd_return_to_status(); + setWatch(); // heater sanity check timer +} +static void lcd_cooldown() +{ + setTargetHotend0(0); + setTargetHotend1(0); + setTargetHotend2(0); + setTargetBed(0); + lcd_return_to_status(); +} + +static void lcd_heat_cool_menu() +{ + START_MENU(); + MENU_ITEM_BACK(back, MSG_PREPARE, lcd_prepare_menu); + MENU_ITEM(function, MSG_PREHEAT_PLA, lcd_preheat_pla); + MENU_ITEM(function, MSG_PREHEAT_ABS, lcd_preheat_abs); + MENU_ITEM(function, MSG_COOLDOWN, lcd_cooldown); + MENU_ITEM_EDIT(int3, MSG_NOZZLE, &target_temperature[0], 0, HEATER_0_MAXTEMP - 15); + #if TEMP_SENSOR_1 != 0 + MENU_ITEM_EDIT(int3, MSG_NOZZLE1, &target_temperature[1], 0, HEATER_1_MAXTEMP - 15); + #endif +// if ( EX2_ENABLED ) +// MENU_ITEM_EDIT(int3, MSG_NOZZLE1, &target_temperature[1], 0, HEATER_1_MAXTEMP - 15); + #if TEMP_SENSOR_2 != 0 + MENU_ITEM_EDIT(int3, MSG_NOZZLE2, &target_temperature[2], 0, HEATER_2_MAXTEMP - 15); + #endif + #if TEMP_SENSOR_BED != 0 + MENU_ITEM_EDIT(int3, MSG_BED, &target_temperature_bed, 0, BED_MAXTEMP - 15); + #endif + MENU_ITEM_EDIT(int3, MSG_FAN_SPEED, &fanSpeed, 0, 255); + END_MENU(); +} + + +static void lcd_utilities_menu() +{ + START_MENU(); + MENU_ITEM_BACK(back, MSG_MAIN, lcd_main_menu); + MENU_ITEM(submenu, "Bed Leveling", lcd_bed_level_menu); +#ifdef FILAMENTCHANGEENABLE + MENU_ITEM(gcode, MSG_FILAMENTCHANGE, PSTR("M600")); +#endif + END_MENU(); +} + + +//#################################################################################################### +// Manual movement routines +//#################################################################################################### +float move_menu_scale; +static void lcd_move_menu_axis(); + +static void lcd_move_x() +{ + if (encoderPosition != 0) + { + current_position[X_AXIS] += float((int)encoderPosition) * move_menu_scale; + if (current_position[X_AXIS] < X_MIN_POS) + current_position[X_AXIS] = X_MIN_POS; + if (current_position[X_AXIS] > X_MAX_POS) + current_position[X_AXIS] = X_MAX_POS; + encoderPosition = 0; + plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 600, active_extruder); + lcdDrawUpdate = 1; + } + if (lcdDrawUpdate) + { + lcd_implementation_drawedit(PSTR("X"), ftostr31(current_position[X_AXIS])); + } + if (LCD_CLICKED) + { + lcd_quick_feedback(); + currentMenu = lcd_move_menu_axis; + encoderPosition = 0; + } +} +static void lcd_move_y() +{ + if (encoderPosition != 0) + { + current_position[Y_AXIS] += float((int)encoderPosition) * move_menu_scale; + if (current_position[Y_AXIS] < Y_MIN_POS) + current_position[Y_AXIS] = Y_MIN_POS; + if (current_position[Y_AXIS] > Y_MAX_POS) + current_position[Y_AXIS] = Y_MAX_POS; + encoderPosition = 0; + plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 600, active_extruder); + lcdDrawUpdate = 1; + } + if (lcdDrawUpdate) + { + lcd_implementation_drawedit(PSTR("Y"), ftostr31(current_position[Y_AXIS])); + } + if (LCD_CLICKED) + { + lcd_quick_feedback(); + currentMenu = lcd_move_menu_axis; + encoderPosition = 0; + } +} +static void lcd_move_z() +{ + if (encoderPosition != 0) + { + current_position[Z_AXIS] += float((int)encoderPosition) * move_menu_scale; + if (current_position[Z_AXIS] < Z_MIN_POS) + current_position[Z_AXIS] = Z_MIN_POS; + if (current_position[Z_AXIS] > Z_MAX_POS) + current_position[Z_AXIS] = Z_MAX_POS; + encoderPosition = 0; + plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 60, active_extruder); + lcdDrawUpdate = 1; + } + if (lcdDrawUpdate) + { + lcd_implementation_drawedit(PSTR("Z"), ftostr31(current_position[Z_AXIS])); + } + if (LCD_CLICKED) + { + lcd_quick_feedback(); + currentMenu = lcd_move_menu_axis; + encoderPosition = 0; + } +} +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], 20, active_extruder); + lcdDrawUpdate = 1; + } + if (lcdDrawUpdate) + { + lcd_implementation_drawedit(PSTR("Extruder"), ftostr31(current_position[E_AXIS])); + } + if (LCD_CLICKED) + { + lcd_quick_feedback(); + currentMenu = lcd_move_menu_axis; + encoderPosition = 0; + } +} + +static void lcd_move_menu_axis() +{ + START_MENU(); + MENU_ITEM_BACK(back, MSG_MOVE_AXIS, lcd_move_menu); + MENU_ITEM(submenu, "Move X", lcd_move_x); + MENU_ITEM(submenu, "Move Y", lcd_move_y); +// if (move_menu_scale < 10.0) +// { + MENU_ITEM(submenu, "Move Z", lcd_move_z); + MENU_ITEM(submenu, "Extruder", lcd_move_e); +// } + END_MENU(); +} + +static void lcd_move_menu_10mm() +{ + move_menu_scale = 10.0; + lcd_move_menu_axis(); +} +static void lcd_move_menu_1mm() +{ + move_menu_scale = 1.0; + lcd_move_menu_axis(); +} +static void lcd_move_menu_01mm() +{ + move_menu_scale = 0.1; + lcd_move_menu_axis(); +} + +static void lcd_move_menu() +{ + START_MENU(); + MENU_ITEM_BACK(back, MSG_PREPARE, lcd_prepare_menu); + MENU_ITEM(submenu, "Move 10mm", lcd_move_menu_10mm); + MENU_ITEM(submenu, "Move 1mm", lcd_move_menu_1mm); + MENU_ITEM(submenu, "Move 0.1mm", lcd_move_menu_01mm); + //TODO:X,Y,Z,E + END_MENU(); +} + + +static void lcd_control_menu() +{ + START_MENU(); + MENU_ITEM_BACK(back, MSG_MAIN, lcd_main_menu); + MENU_ITEM(submenu, MSG_TEMPERATURE, lcd_control_temperature_menu); + MENU_ITEM(submenu, MSG_MOTION, lcd_control_motion_menu); +#ifdef FWRETRACT + MENU_ITEM(submenu, MSG_RETRACT, lcd_control_retract_menu); +#endif +#ifdef EEPROM_SETTINGS + MENU_ITEM(function, MSG_STORE_EPROM, Config_StoreSettings); + MENU_ITEM(function, MSG_LOAD_EPROM, Config_RetrieveSettings); +#endif + MENU_ITEM(function, MSG_RESTORE_FAILSAFE, Config_ResetDefault); + END_MENU(); +} + +static void lcd_control_temperature_menu() +{ + // set up temp variables - undo the default scaling + raw_Ki = unscalePID_i(Ki); + raw_Kd = unscalePID_d(Kd); + + START_MENU(); + MENU_ITEM_BACK(back, MSG_CONTROL, lcd_control_menu); + MENU_ITEM(submenu, MSG_PREHEAT_PLA_SETTINGS, lcd_control_temperature_preheat_pla_settings_menu); + MENU_ITEM(submenu, MSG_PREHEAT_ABS_SETTINGS, lcd_control_temperature_preheat_abs_settings_menu); +#ifdef AUTOTEMP + MENU_ITEM_EDIT(bool, MSG_AUTOTEMP, &autotemp_enabled); + MENU_ITEM_EDIT(float3, MSG_MIN, &autotemp_min, 0, HEATER_0_MAXTEMP - 15); + MENU_ITEM_EDIT(float3, MSG_MAX, &autotemp_max, 0, HEATER_0_MAXTEMP - 15); + MENU_ITEM_EDIT(float32, MSG_FACTOR, &autotemp_factor, 0.0, 1.0); +#endif +#ifdef PIDTEMP + MENU_ITEM_EDIT(float52, MSG_PID_P, &Kp, 1, 9990); + // i is typically a small value so allows values below 1 + MENU_ITEM_EDIT_CALLBACK(float52, MSG_PID_I, &raw_Ki, 0.01, 9990, copy_and_scalePID_i); + MENU_ITEM_EDIT_CALLBACK(float52, MSG_PID_D, &raw_Kd, 1, 9990, copy_and_scalePID_d); +# ifdef PID_ADD_EXTRUSION_RATE + MENU_ITEM_EDIT(float3, MSG_PID_C, &Kc, 1, 9990); +# endif//PID_ADD_EXTRUSION_RATE +#endif//PIDTEMP + END_MENU(); +} + +static void lcd_control_temperature_preheat_pla_settings_menu() +{ + START_MENU(); + MENU_ITEM_BACK(back, MSG_TEMPERATURE, lcd_control_temperature_menu); + MENU_ITEM_EDIT(int3, MSG_NOZZLE, &plaPreheatHotendTemp, 0, HEATER_0_MAXTEMP - 15); +#if TEMP_SENSOR_BED != 0 + MENU_ITEM_EDIT(int3, MSG_BED, &plaPreheatHPBTemp, 0, BED_MAXTEMP - 15); +#endif + MENU_ITEM_EDIT(int3, MSG_FAN_SPEED, &plaPreheatFanSpeed, 0, 255); +#ifdef EEPROM_SETTINGS + MENU_ITEM(function, MSG_STORE_EPROM, Config_StoreSettings); +#endif + END_MENU(); +} + +static void lcd_control_temperature_preheat_abs_settings_menu() +{ + START_MENU(); + MENU_ITEM_BACK(back, MSG_TEMPERATURE, lcd_control_temperature_menu); + MENU_ITEM_EDIT(int3, MSG_NOZZLE, &absPreheatHotendTemp, 0, HEATER_0_MAXTEMP - 15); +#if TEMP_SENSOR_BED != 0 + MENU_ITEM_EDIT(int3, MSG_BED, &absPreheatHPBTemp, 0, BED_MAXTEMP - 15); +#endif + MENU_ITEM_EDIT(int3, MSG_FAN_SPEED, &absPreheatFanSpeed, 0, 255); +#ifdef EEPROM_SETTINGS + MENU_ITEM(function, MSG_STORE_EPROM, Config_StoreSettings); +#endif + END_MENU(); +} + +static void lcd_control_motion_menu() +{ + START_MENU(); + MENU_ITEM_BACK(back, MSG_CONTROL, lcd_control_menu); + MENU_ITEM_EDIT(float5, MSG_ACC, &acceleration, 500, 99000); + MENU_ITEM_EDIT(float3, MSG_VXY_JERK, &max_xy_jerk, 1, 990); + MENU_ITEM_EDIT(float52, MSG_VZ_JERK, &max_z_jerk, 0.1, 990); + MENU_ITEM_EDIT(float3, MSG_VE_JERK, &max_e_jerk, 1, 990); + MENU_ITEM_EDIT(float3, MSG_VMAX MSG_X, &max_feedrate[X_AXIS], 1, 999); + MENU_ITEM_EDIT(float3, MSG_VMAX MSG_Y, &max_feedrate[Y_AXIS], 1, 999); + MENU_ITEM_EDIT(float3, MSG_VMAX MSG_Z, &max_feedrate[Z_AXIS], 1, 999); + MENU_ITEM_EDIT(float3, MSG_VMAX MSG_E, &max_feedrate[E_AXIS], 1, 999); + MENU_ITEM_EDIT(float3, MSG_VMIN, &minimumfeedrate, 0, 999); + MENU_ITEM_EDIT(float3, MSG_VTRAV_MIN, &mintravelfeedrate, 0, 999); + MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_X, &max_acceleration_units_per_sq_second[X_AXIS], 100, 99000, reset_acceleration_rates); + MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_Y, &max_acceleration_units_per_sq_second[Y_AXIS], 100, 99000, reset_acceleration_rates); + MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_Z, &max_acceleration_units_per_sq_second[Z_AXIS], 100, 99000, reset_acceleration_rates); + MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_E, &max_acceleration_units_per_sq_second[E_AXIS], 100, 99000, reset_acceleration_rates); + MENU_ITEM_EDIT(float5, MSG_A_RETRACT, &retract_acceleration, 100, 99000); + MENU_ITEM_EDIT(float52, MSG_XSTEPS, &axis_steps_per_unit[X_AXIS], 5, 9999); + MENU_ITEM_EDIT(float52, MSG_YSTEPS, &axis_steps_per_unit[Y_AXIS], 5, 9999); + MENU_ITEM_EDIT(float51, MSG_ZSTEPS, &axis_steps_per_unit[Z_AXIS], 5, 9999); + MENU_ITEM_EDIT(float51, MSG_ESTEPS, &axis_steps_per_unit[E_AXIS], 5, 9999); +#ifdef ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED + MENU_ITEM_EDIT(bool, "Endstop abort", &abort_on_endstop_hit); +#endif + END_MENU(); +} + +#ifdef FWRETRACT +static void lcd_control_retract_menu() +{ + START_MENU(); + MENU_ITEM_BACK(back, MSG_CONTROL, lcd_control_menu); + MENU_ITEM_EDIT(bool, MSG_AUTORETRACT, &autoretract_enabled); + MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT, &retract_length, 0, 100); + MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACTF, &retract_feedrate, 1, 999); + MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_ZLIFT, &retract_zlift, 0, 999); + MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_RECOVER, &retract_recover_length, 0, 100); + MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACT_RECOVERF, &retract_recover_feedrate, 1, 999); + END_MENU(); +} +#endif + +#if SDCARDDETECT == -1 +static void lcd_sd_refresh() +{ + card.initsd(); + currentMenuViewOffset = 0; +} +#endif +static void lcd_sd_updir() +{ + card.updir(); + currentMenuViewOffset = 0; +} + +void lcd_sdcard_menu() +{ + lcdFastUpdate = true; + + uint16_t fileCnt = card.getnrfilenames(); + START_MENU(); + MENU_ITEM_BACK(back, MSG_MAIN, lcd_main_menu); + card.getWorkDirName(); + if(card.filename[0]=='/') + { +#if SDCARDDETECT == -1 + MENU_ITEM(function, LCD_STR_REFRESH MSG_REFRESH, lcd_sd_refresh); +#endif + }else{ + MENU_ITEM(function, LCD_STR_FOLDER "..", lcd_sd_updir); + } + + for(uint16_t i=0;i maxEditValue) \ + encoderPosition = maxEditValue; \ + if (lcdDrawUpdate) \ + lcd_implementation_drawedit(editLabel, _strFunc(((_type)encoderPosition) / scale)); \ + if (LCD_CLICKED) \ + { \ + *((_type*)editValue) = ((_type)encoderPosition) / scale; \ + lcd_quick_feedback(); \ + currentMenu = prevMenu; \ + encoderPosition = prevEncoderPosition; \ + } \ + } \ + void menu_edit_callback_ ## _name () \ + { \ + encoderCoarseEnabled = true; \ + if ((int32_t)encoderPosition < minEditValue) \ + encoderPosition = minEditValue; \ + if ((int32_t)encoderPosition > maxEditValue) \ + encoderPosition = maxEditValue; \ + if (lcdDrawUpdate) \ + lcd_implementation_drawedit(editLabel, _strFunc(((_type)encoderPosition) / scale)); \ + if (LCD_CLICKED) \ + { \ + *((_type*)editValue) = ((_type)encoderPosition) / scale; \ + lcd_quick_feedback(); \ + currentMenu = prevMenu; \ + encoderPosition = prevEncoderPosition; \ + (*callbackFunc)();\ + } \ + } \ + static void menu_action_setting_edit_ ## _name (const char* pstr, _type* ptr, _type minValue, _type maxValue) \ + { \ + encoderCoarseEnabled = true; \ + prevMenu = currentMenu; \ + prevEncoderPosition = encoderPosition; \ + \ + lcdDrawUpdate = 2; \ + currentMenu = menu_edit_ ## _name; \ + \ + editLabel = pstr; \ + editValue = ptr; \ + minEditValue = minValue * scale; \ + maxEditValue = maxValue * scale; \ + encoderPosition = (*ptr) * scale; \ + }\ + static void menu_action_setting_edit_callback_ ## _name (const char* pstr, _type* ptr, _type minValue, _type maxValue, menuFunc_t callback) \ + { \ + encoderCoarseEnabled = true; \ + prevMenu = currentMenu; \ + prevEncoderPosition = encoderPosition; \ + \ + lcdDrawUpdate = 2; \ + currentMenu = menu_edit_callback_ ## _name; \ + \ + editLabel = pstr; \ + editValue = ptr; \ + minEditValue = minValue * scale; \ + maxEditValue = maxValue * scale; \ + encoderPosition = (*ptr) * scale; \ + 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, 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) + + +/** 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) +{ + currentMenu = data; + encoderPosition = 0; +} +static void menu_action_submenu(menuFunc_t data) +{ + currentMenu = data; + encoderPosition = 0; +} +static void menu_action_gcode(const char* pgcode) +{ + enquecommand_P(pgcode); +} +static void menu_action_function(menuFunc_t data) +{ + (*data)(); +} +static void menu_action_sdfile(const char* filename, char* longFilename, uint8_t item) +{ + 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, uint8_t item) +{ + card.chdir(filename); + encoderPosition = 0; +} +static void menu_action_setting_edit_bool(const char* pstr, bool* ptr) +{ + *ptr = !(*ptr); +} + +/** LCD API **/ +void lcd_init() +{ + lcd_implementation_init(); + #if BTN_ENC > 0 + pinMode(BTN_ENC,INPUT); + WRITE(BTN_ENC,HIGH); + #endif + pinMode(BTN_UP,INPUT); + pinMode(BTN_DWN,INPUT); + pinMode(BTN_LFT,INPUT); + pinMode(BTN_RT,INPUT); + // pinMode(BTN_ENT,INPUT) + +#if (SDCARDDETECT > 0) + pinMode(SDCARDDETECT,INPUT); + WRITE(SDCARDDETECT, HIGH); + lcd_oldcardstatus = IS_SD_INSERTED; +#endif//(SDCARDDETECT > 0) + lcd_buttons_update(); + encoderDiff = 0; +} + +void lcd_update() +{ + static unsigned long timeoutToStatus = 0; + + lcd_buttons_update(); + + #ifdef LCD_HAS_SLOW_BUTTONS + buttons |= lcd_implementation_read_slow_buttons(); // buttons which take too long to read in interrupt context + #endif + + #if (SDCARDDETECT > 0) + if((IS_SD_INSERTED != lcd_oldcardstatus)) + { + lcdDrawUpdate = 2; + lcd_oldcardstatus = IS_SD_INSERTED; + lcd_implementation_init(); // to maybe revive the lcd if static electricty killed it. + + if(lcd_oldcardstatus) + { + card.initsd(); + LCD_MESSAGEPGM(MSG_SD_INSERTED); + } + else + { + card.release(); + LCD_MESSAGEPGM(MSG_SD_REMOVED); + } + } + #endif//CARDINSERTED + + if (lcd_next_update_millis < millis()) + { + if (encoderDiff || encoderDiff2) + { + encoderDiff = invertEncoderDir?-encoderDiff:encoderDiff; // Check for direction inversion if set by a menu + if ( encoderCoarseEnabled ) // Check if left/right encoder is being used + { + encoderDiff2 *= 5; + encoderDiff += encoderDiff2; + } + + lcdDrawUpdate = 1; + encoderPosition += encoderDiff; // Get difference, + encoderDiff = 0; + encoderDiff2 = 0; + timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS; + } + if (LCD_CLICKED) + timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS; + + encoderCoarseEnabled = false; // Clear encoder coarse enable to allow a menu to set it + invertEncoderDir = false; // Clear encoder inversion to allow a menu to set it + (*currentMenu)(); + +#ifdef LCD_HAS_STATUS_INDICATORS + lcd_implementation_update_indicators(); +#endif + + if(timeoutToStatus < millis() && currentMenu != lcd_status_screen && !timeoutSuspend) + { + lcd_return_to_status(); + lcdDrawUpdate = 2; + } + + if (lcdDrawUpdate == 2) + lcd_implementation_clear(); + if (lcdDrawUpdate) + lcdDrawUpdate--; + lcd_next_update_millis = millis() + LCD_UPDATE_INTERVAL; + + if ( lcdFastUpdate ) // Set up for update on next cycle + lcdDrawUpdate = 1; + + } + lcdFastUpdate = false; +} + +void lcd_setstatus(const char* message) +{ + if (lcd_status_message_level > 0) + return; + strncpy(lcd_status_message, message, LCD_WIDTH); + lcdDrawUpdate = 2; +} +void lcd_setstatuspgm(const char* message) +{ + if (lcd_status_message_level > 0) + return; + strncpy_P(lcd_status_message, message, LCD_WIDTH); + lcdDrawUpdate = 2; +} +void lcd_setalertstatuspgm(const char* message) +{ + lcd_setstatuspgm(message); + lcd_status_message_level = 1; + lcd_return_to_status(); +} +void lcd_reset_alert_level() +{ + lcd_status_message_level = 0; +} + +/* Warning: This function is called from interrupt context */ +void lcd_buttons_update() +{ + uint8_t newbuttons=0; + + if ( millis() > blocking_enc ) + { + if(READ(BTN_ENC)==0) + newbuttons |= EN_C; + if(READ(BTN_UP)==0) + newbuttons |= B_UP; + if(READ(BTN_DWN)==0) + newbuttons |= B_DW; + if(READ(BTN_RT)==0) + newbuttons |= B_RI; + if(READ(BTN_LFT)==0) + newbuttons |= B_LE; + } + + if ( newbuttons != buttons ) + { + // Up/down buttons form main encoder + if(newbuttons&B_UP) + encoderDiff++; + if(newbuttons&B_DW) + encoderDiff--; + + // Left/right buttons form secondary encoder (if needed) + if(newbuttons&B_RI) + encoderDiff2++; + if(newbuttons&B_LE) + encoderDiff2--; + } + + buttons = newbuttons; +} + +void lcd_buzz(long duration, uint16_t freq) +{ +#ifdef LCD_USE_I2C_BUZZER + lcd.buzz(duration,freq); +#endif +} + +bool lcd_clicked() +{ + return LCD_CLICKED; +} + +/********************************/ +/** Float conversion utilities **/ +/********************************/ +// convert float to string with +123.4 format +char 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 +char *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 format +char *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; +} + +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; +} + +char *itostr3(const int &xx) +{ + 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; +} + +char *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; +} + +char *itostr4(const int &xx) +{ + if (xx >= 1000) + conv[0]=(xx/1000)%10+'0'; + else + conv[0]=' '; + if (xx >= 100) + conv[1]=(xx/100)%10+'0'; + else + conv[1]=' '; + if (xx >= 10) + conv[2]=(xx/10)%10+'0'; + else + conv[2]=' '; + conv[3]=(xx)%10+'0'; + conv[4]=0; + return conv; +} + +// convert float to string with 12345 format +char *ftostr5(const float &x) +{ + long xx=abs(x); + if (xx >= 10000) + conv[0]=(xx/10000)%10+'0'; + else + conv[0]=' '; + if (xx >= 1000) + conv[1]=(xx/1000)%10+'0'; + else + conv[1]=' '; + if (xx >= 100) + conv[2]=(xx/100)%10+'0'; + else + conv[2]=' '; + if (xx >= 10) + conv[3]=(xx/10)%10+'0'; + else + conv[3]=' '; + conv[4]=(xx)%10+'0'; + conv[5]=0; + return conv; +} + +// convert float to string with +1234.5 format +char *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 format +char *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 driver +void copy_and_scalePID_i() +{ + Ki = scalePID_i(raw_Ki); + updatePID(); +} + +// Callback for after editing PID d value +// grab the pid d value out of the temp variable; scale it; then update the PID driver +void copy_and_scalePID_d() +{ + Kd = scalePID_d(raw_Kd); + updatePID(); +} + +#endif //RIGIDPANEL diff --git a/Marlin/rigidpanel.h b/Marlin/rigidpanel.h new file mode 100755 index 000000000000..a0be2271215d --- /dev/null +++ b/Marlin/rigidpanel.h @@ -0,0 +1,57 @@ +#ifndef RIGIDPANEL_H +#define RIGIDPANEL_H + +#include "Marlin.h" + +#ifdef RIGIDPANEL + +void lcd_update(); +void lcd_init(); +void lcd_setstatus(const char* message); +void lcd_setstatuspgm(const char* message); +void lcd_setalertstatuspgm(const char* message); +void lcd_reset_alert_level(); + +static unsigned char blink = 0; // Variable for visualisation of fan rotation in GLCD + +#define HIDE_BACK_MENUS // Uncomment to hide back menus (left button will still trigger them) + +#define LCD_MESSAGEPGM(x) lcd_setstatuspgm(PSTR(x)) +#define LCD_ALERTMESSAGEPGM(x) lcd_setalertstatuspgm(PSTR(x)) + +#define LCD_UPDATE_INTERVAL 100 +#define LCD_STATUS_UPDATE_INTERVAL 1000 +#define LCD_TIMEOUT_TO_STATUS 30000 +#define FILE_SCROLL_START_DELAY 1000 +#define FILE_SCROLL_DELAY 400 + +void lcd_buttons_update(); + +extern int plaPreheatHotendTemp; +extern int plaPreheatHPBTemp; +extern int plaPreheatFanSpeed; + +extern int absPreheatHotendTemp; +extern int absPreheatHPBTemp; +extern int absPreheatFanSpeed; + +void lcd_buzz(long duration,uint16_t freq); +bool lcd_clicked(); + +char *itostr2(const uint8_t &x); +char *itostr31(const int &xx); +char *itostr3(const int &xx); +char *itostr3left(const int &xx); +char *itostr4(const int &xx); + +char *ftostr3(const float &x); +char *ftostr31ns(const float &x); // float to string without sign character +char *ftostr31(const float &x); +char *ftostr32(const float &x); +char *ftostr5(const float &x); +char *ftostr51(const float &x); +char *ftostr52(const float &x); + +#endif //RIGIDPANEL + +#endif //RIGIDPANEL_H diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index 195d52bc430b..ef8bafa44df8 100644 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -1,6 +1,6 @@ #include "temperature.h" #include "ultralcd.h" -#ifdef ULTRA_LCD +#if defined(ULTRA_LCD) && !defined(RIGIDPANEL) #include "Marlin.h" #include "language.h" #include "cardreader.h" diff --git a/Marlin/ultralcd_implementation_RigidPanel.h b/Marlin/ultralcd_implementation_RigidPanel.h new file mode 100755 index 000000000000..48da77f0d305 --- /dev/null +++ b/Marlin/ultralcd_implementation_RigidPanel.h @@ -0,0 +1,627 @@ +#ifndef ULTRALCD_IMPLEMENTATION_RIGIDPANEL_H +#define ULTRALCD_IMPLEMENTATION_RIGIDPANEL_H + +/** +* Implementation of the LCD display routines for the Invent-A-Part RigidPanel LCD controller. +**/ + +extern volatile uint8_t buttons; //the last checked buttons in a bit array. + +//////////////////////////////////// +// 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. + +// 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< + #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 "LiquidCrystalFast_Mod.h" + #define LCD_CLASS LiquidCrystalFast + #endif + LiquidCrystalFast 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); + + + 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 below + lcd.setCursor(0, 1); +# 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 + +//Lines 2 for 4 line LCD +# 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(11, 0); + 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(11,0); + 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 + + lcd.setCursor(11, 1); + lcd.print('Z'); + lcd.print(ftostr32(current_position[Z_AXIS])); + + + lcd.setCursor(0, 2); + lcd.print(LCD_STR_FEEDRATE[0]); + lcd.print(itostr3(feedmultiply)); + lcd.print('%'); + +# ifdef SDSUPPORT + lcd.setCursor(6, 2); + lcd_printPGM(PSTR("USB")); + if (IS_SD_PRINTING) + lcd.print(itostr3(card.percentDone())); + else + lcd_printPGM(PSTR("---")); + lcd.print('%'); +# endif//SDSUPPORT + + 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("--:--")); + } + + + //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_base(uint8_t row, const char* pstr, const char* filename, char* longFilename, uint8_t item, bool isFolder, bool isSelected ) +{ + static uint32_t scrollDelay; + static uint8_t offset; + static uint8_t lastItem = -1; + static bool scrollDone = false; + + static const char* lastPstr = '\0'; + + + if (longFilename[0] != '\0') + filename = longFilename; + + char c; + uint8_t n = LCD_WIDTH - 1; + lcd.setCursor(0, row); + if ( isSelected ) + { + if( item != lastItem ) + { + offset = 0; + scrollDone = false; + scrollDelay = millis() + FILE_SCROLL_START_DELAY; + } + lastItem = item; + filename += offset; + lcd.print('>'); + } + else + { + lcd.print(' '); + } + if ( isFolder ) + { + lcd.print(LCD_STR_FOLDER[0]); + n--; + } + while( ((c = *filename) != '\0') && (n>0) ) + { + lcd.print(c); + filename++; + n--; + } + if ( millis() > scrollDelay ) + { + if ( scrollDone ) + { + offset = 0; + scrollDone = false; + scrollDelay = millis() + FILE_SCROLL_START_DELAY; + } + else + { + offset++; + scrollDelay = millis() + FILE_SCROLL_DELAY; + } + } + while(n--) + { + lcd.print(' '); + if ( isSelected & !scrollDone ) + { + scrollDone = true; + scrollDelay = millis() + FILE_SCROLL_START_DELAY; + } + } +} + +#define lcd_implementation_drawmenu_sdfile_selected(row, pstr, filename, longFilename, item) \ + lcd_implementation_drawmenu_sdfile_base(row, pstr, filename, longFilename, item, false, true); + +#define lcd_implementation_drawmenu_sdfile(row, pstr, filename, longFilename, item) \ + lcd_implementation_drawmenu_sdfile_base(row, pstr, filename, longFilename, item, false, false); + +#define lcd_implementation_drawmenu_sddirectory_selected(row, pstr, filename, longFilename, item) \ + lcd_implementation_drawmenu_sdfile_base(row, pstr, filename, longFilename, item, true, true); + +#define lcd_implementation_drawmenu_sddirectory(row, pstr, filename, longFilename, item) \ + lcd_implementation_drawmenu_sdfile_base(row, pstr, filename, longFilename, item, true, false); + + +#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 //ULTRALCD_IMPLEMENTATION_RIGIDPANEL_H