From 11db77b79485041a00b3cacce8d3e80991f76e2c Mon Sep 17 00:00:00 2001 From: Stefan Bek Date: Wed, 19 Apr 2017 12:30:55 +0200 Subject: [PATCH] Fix display string length for M117 / Status messages --- Constants.h | 137 ++ ui.cpp | 4937 +++++++++++++++++++++++++++++++++++++++++++++++++++ ui.h | 654 +++++++ 3 files changed, 5728 insertions(+) create mode 100644 Constants.h create mode 100644 ui.cpp create mode 100644 ui.h diff --git a/Constants.h b/Constants.h new file mode 100644 index 000000000..ae7894389 --- /dev/null +++ b/Constants.h @@ -0,0 +1,137 @@ +/* + This file is part of the Repetier-Firmware for RF devices from Conrad Electronic SE. + + Repetier-Firmware is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Repetier-Firmware 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Repetier-Firmware. If not, see . +*/ + + +#ifndef CONSTANTS_H +#define CONSTANTS_H + + +#define REPETIER_VERSION "RF.01.37i3.Mod" +#define UI_PRINTER_COMPANY "Conrad SE" +#define UI_VERSION_STRING "V " REPETIER_VERSION + + +// ########################################################################################## +// ## basic definitions +// ########################################################################################## + +#define DEVICE_TYPE_RF1000 13 +#define DEVICE_TYPE_RF2000 14 + +#define OPERATING_MODE_PRINT 1 // the firmware works in mode "print" +#define OPERATING_MODE_MILL 2 // the firmware works in mode "mill" + +#define HOTEND_TYPE_1 1 // hotend V1 + messing ring +#define HOTEND_TYPE_V1 2 // hotend V1 +#define HOTEND_TYPE_V2_SINGLE 3 // hotend V2 for single extruder +#define HOTEND_TYPE_V2_DUAL 4 // hotend V2 for dual extruder + +#define MILLER_TYPE_ONE_TRACK 1 // one track in x- and y-direction +#define MILLER_TYPE_TWO_TRACKS 2 // two tracks in x- and y-direction + +#define ENDSTOP_TYPE_SINGLE 1 // there is only one endstop attached (either the min- or the max-endstop) +#define ENDSTOP_TYPE_CIRCUIT 2 // the min- and max-endstops are attached in a single circuit + +#define ENDSTOP_NOT_HIT 0 +#define ENDSTOP_IS_HIT 1 +#define ENDSTOP_WAS_HIT 2 + +#define X_AXIS 0 +#define Y_AXIS 1 +#define Z_AXIS 2 +#define E_AXIS 3 +#define VIRTUAL_AXIS 4 + +#define HOME_ORDER_XYZ 1 +#define HOME_ORDER_XZY 2 +#define HOME_ORDER_YXZ 3 +#define HOME_ORDER_YZX 4 +#define HOME_ORDER_ZXY 5 +#define HOME_ORDER_ZYX 6 + +#define MENU_MODE_SD_MOUNTED 1 +#define MENU_MODE_SD_PRINTING 2 +#define MENU_MODE_SD_PAUSED 4 +#define MENU_MODE_FAN_RUNNING 8 +#define MENU_MODE_PRINTING 16 +#define MENU_MODE_PRINTER 32 // we have to show the printer menu +#define MENU_MODE_MILLER 64 // we have to show the miller menu + +#define IGNORE_COORDINATE 99999 + +#define TASK_NO_TASK 0 +#define TASK_ENABLE_Z_COMPENSATION 1 +#define TASK_DISABLE_Z_COMPENSATION 2 +#define TASK_PAUSE_PRINT 4 +#define TASK_PAUSE_PRINT_AND_MOVE 5 +#define TASK_MOVE_FROM_BUTTON 10 + +#define PAUSE_STATUS_NONE 0 // we are not paused at the moment +#define PAUSE_STATUS_WAIT_FOR_QUEUE_MOVE 1 // we are waiting until the last queue move is finished +#define PAUSE_STATUS_PREPARE_PAUSE_1 2 // we are going to pause the print (= moving to the pause position) +#define PAUSE_STATUS_PREPARE_PAUSE_2 3 // we are going to pause the print (= moving to the pause position) +#define PAUSE_STATUS_PREPARE_PAUSE_3 4 // we are going to pause the print (= moving to the pause position) +#define PAUSE_STATUS_PAUSED 5 // we have paused the print (= pause position reached) +#define PAUSE_STATUS_PREPARE_CONTINUE_1 6 // we are going to continue the print (= moving to the continue position) +#define PAUSE_STATUS_PREPARE_CONTINUE_2 7 // we are going to continue the print (= moving to the continue position) + +#define PAUSE_MODE_NONE 0 // we are not paused at the moment +#define PAUSE_MODE_PAUSED 1 // stopp at the last printing position +#define PAUSE_MODE_PAUSED_AND_MOVED 2 // move away from the last printing position + +#define RGB_MODE_OFF 0 +#define RGB_MODE_WHITE 1 +#define RGB_MODE_AUTOMATIC 2 +#define RGB_MODE_MANUAL 3 + +#define RGB_STATUS_NOT_AUTOMATIC 0 +#define RGB_STATUS_AUTOMATIC 1 +#define RGB_STATUS_PRINTING 11 +#define RGB_STATUS_HEATING 12 +#define RGB_STATUS_COOLING 13 +#define RGB_STATUS_IDLE 14 +#define RGB_STATUS_COLOR_CHANGE 15 + +#define MOVE_MODE_SINGLE_STEPS 1 +#define MOVE_MODE_SINGLE_MOVE 2 +#define MOVE_MODE_1_MM 3 +#define MOVE_MODE_10_MM 4 +#define MOVE_MODE_50_MM 5 + +#define HEAT_BED_SCAN_MODE_PLA 1 +#define HEAT_BED_SCAN_MODE_ABS 2 + +#define Z_VALUE_MODE_Z_MIN 1 // show the z-distance to z-min (print) +#define Z_VALUE_MODE_Z_ORIGIN 1 // show the z-distance to the z-origin (mill) +#define Z_VALUE_MODE_SURFACE 2 // show the z-distance to the surface of the heat bed (print) or work part (mill) + +#define STOP_BECAUSE_OF_Z_MIN 1 +#define STOP_BECAUSE_OF_Z_BLOCK 2 + + +// ########################################################################################## +// ## data types +// ########################################################################################## + +#define uint uint16_t +#define uint8 uint8_t +#define int8 int8_t +#define uint32 uint32_t +#define int32 int32_t + + +#endif // CONSTANTS_H diff --git a/ui.cpp b/ui.cpp new file mode 100644 index 000000000..7d2e9ee33 --- /dev/null +++ b/ui.cpp @@ -0,0 +1,4937 @@ +/* + This file is part of the Repetier-Firmware for RF devices from Conrad Electronic SE. + + Repetier-Firmware is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Repetier-Firmware 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Repetier-Firmware. If not, see . +*/ + + +#define UI_MAIN +#include "Repetier.h" +extern const int8_t encoder_table[16] PROGMEM ; + +#include +#include +#include +#include + + +#if BEEPER_TYPE==2 && defined(UI_HAS_I2C_KEYS) && UI_I2C_KEY_ADDRESS!=BEEPER_ADDRESS +#error Beeper address and i2c key address must be identical +#else +#if BEEPER_TYPE==2 +#define UI_I2C_KEY_ADDRESS BEEPER_ADDRESS +#endif // BEEPER_TYPE==2 +#endif // BEEPER_TYPE==2 && defined(UI_HAS_I2C_KEYS) && UI_I2C_KEY_ADDRESS!=BEEPER_ADDRESS + +#if UI_PRINT_AUTORETURN_TO_MENU_AFTER || UI_MILL_AUTORETURN_TO_MENU_AFTER +millis_t g_nAutoReturnTime = 0; +#endif // UI_PRINT_AUTORETURN_TO_MENU_AFTER || UI_MILL_AUTORETURN_TO_MENU_AFTER + +char g_nYesNo = 0; // 0 = no, 1 = yes +volatile char g_nContinueButtonPressed = 0; +char g_nServiceRequest = 0; +char g_nPrinterReady = 0; + +void beep(uint8_t duration,uint8_t count) +{ +#if FEATURE_BEEPER + if( !Printer::enableBeeper ) + { + // we shall not beep + return; + } + +#if BEEPER_TYPE!=0 +#if BEEPER_TYPE==1 && defined(BEEPER_PIN) && BEEPER_PIN>=0 + SET_OUTPUT(BEEPER_PIN); +#endif // BEEPER_TYPE==1 && defined(BEEPER_PIN) && BEEPER_PIN>=0 + +#if BEEPER_TYPE==2 + HAL::i2cStartWait(BEEPER_ADDRESS+I2C_WRITE); +#if UI_DISPLAY_I2C_CHIPTYPE==1 + HAL::i2cWrite( 0x14); // Start at port a +#endif // UI_DISPLAY_I2C_CHIPTYPE==1 +#endif // BEEPER_TYPE==2 + + for(uint8_t i=0; i=0 +#if defined(BEEPER_TYPE_INVERTING) && BEEPER_TYPE_INVERTING + WRITE(BEEPER_PIN,LOW); +#else + WRITE(BEEPER_PIN,HIGH); +#endif // defined(BEEPER_TYPE_INVERTING) && BEEPER_TYPE_INVERTING +#else +#if UI_DISPLAY_I2C_CHIPTYPE==0 +#if BEEPER_ADDRESS == UI_DISPLAY_I2C_ADDRESS + HAL::i2cWrite(uid.outputMask & ~BEEPER_PIN); +#else + HAL::i2cWrite(~BEEPER_PIN); +#endif // BEEPER_ADDRESS == UI_DISPLAY_I2C_ADDRESS +#endif // UI_DISPLAY_I2C_CHIPTYPE==0 + +#if UI_DISPLAY_I2C_CHIPTYPE==1 + HAL::i2cWrite((BEEPER_PIN) | uid.outputMask); + HAL::i2cWrite(((BEEPER_PIN) | uid.outputMask)>>8); +#endif // UI_DISPLAY_I2C_CHIPTYPE==1 +#endif // BEEPER_TYPE==1 && defined(BEEPER_PIN) && BEEPER_PIN>=0 + + HAL::delayMilliseconds(duration); + +#if BEEPER_TYPE==1 && defined(BEEPER_PIN) && BEEPER_PIN>=0 +#if defined(BEEPER_TYPE_INVERTING) && BEEPER_TYPE_INVERTING + WRITE(BEEPER_PIN,HIGH); +#else + WRITE(BEEPER_PIN,LOW); +#endif // defined(BEEPER_TYPE_INVERTING) && BEEPER_TYPE_INVERTING +#else +#if UI_DISPLAY_I2C_CHIPTYPE==0 + +#if BEEPER_ADDRESS == UI_DISPLAY_I2C_ADDRESS + HAL::i2cWrite((BEEPER_PIN) | uid.outputMask); +#else + HAL::i2cWrite(255); +#endif // BEEPER_ADDRESS == UI_DISPLAY_I2C_ADDRESS +#endif // UI_DISPLAY_I2C_CHIPTYPE==0 + +#if UI_DISPLAY_I2C_CHIPTYPE==1 + HAL::i2cWrite( uid.outputMask); + HAL::i2cWrite(uid.outputMask>>8); +#endif // UI_DISPLAY_I2C_CHIPTYPE==1 +#endif // BEEPER_TYPE==1 && defined(BEEPER_PIN) && BEEPER_PIN>=0 + + HAL::delayMilliseconds(duration); + } + +#if BEEPER_TYPE==2 + HAL::i2cStop(); +#endif // BEEPER_TYPE==2 +#endif // BEEPER_TYPE!=0 +#endif // FEATURE_BEEPER + +} // beep + + +bool UIMenuEntry::showEntry() const +{ + bool ret = true; + uint8_t f, f2; + + + f = HAL::readFlashByte((const prog_char*)&filter); + if(f!=0) + ret = (f & Printer::menuMode) != 0; + f2 = HAL::readFlashByte((const prog_char*)&nofilter); + if(ret && f2!=0) + { + ret = (f2 & Printer::menuMode) == 0; + } + return ret; + +} // showEntry + + +#if UI_DISPLAY_TYPE!=0 +UIDisplay uid; +char displayCache[UI_ROWS][MAX_COLS+1]; + +// Menu up sign - code 1 +// ..*.. 4 +// .***. 14 +// *.*.* 21 +// ..*.. 4 +// ***.. 28 +// ..... 0 +// ..... 0 +// ..... 0 +const uint8_t character_back[8] PROGMEM = {4,14,21,4,28,0,0,0}; + +// Degrees sign - code 2 +// ..*.. 4 +// .*.*. 10 +// ..*.. 4 +// ..... 0 +// ..... 0 +// ..... 0 +// ..... 0 +// ..... 0 +const uint8_t character_degree[8] PROGMEM = {4,10,4,0,0,0,0,0}; + +// selected - code 3 +// ..... 0 +// ***** 31 +// ***** 31 +// ***** 31 +// ***** 31 +// ***** 31 +// ***** 31 +// ..... 0 +// ..... 0 +const uint8_t character_selected[8] PROGMEM = {0,31,31,31,31,31,0,0}; + +// unselected - code 4 +// ..... 0 +// ***** 31 +// *...* 17 +// *...* 17 +// *...* 17 +// *...* 17 +// ***** 31 +// ..... 0 +// ..... 0 +const uint8_t character_unselected[8] PROGMEM = {0,31,17,17,17,31,0,0}; + +// unselected - code 5 +// ..*.. 4 +// .*.*. 10 +// .*.*. 10 +// .*.*. 10 +// .*.*. 10 +// .***. 14 +// ***** 31 +// ***** 31 +// .***. 14 +const uint8_t character_temperature[8] PROGMEM = {4,10,10,10,14,31,31,14}; + +// unselected - code 6 +// ..... 0 +// ***.. 28 +// ***** 31 +// *...* 17 +// *...* 17 +// ***** 31 +// ..... 0 +// ..... 0 +const uint8_t character_folder[8] PROGMEM = {0,28,31,17,17,31,0,0}; + +// printer ready - code 7 +// *...* 17 +// .*.*. 10 +// ..*.. 4 +// *...* 17 +// ..*.. 4 +// .*.*. 10 +// *...* 17 +// *...* 17 +const byte character_ready[8] PROGMEM = {17,10,4,17,4,10,17,17}; + +const long baudrates[] PROGMEM = {9600,14400,19200,28800,38400,56000,57600,76800,111112,115200,128000,230400,250000,256000, + 460800,500000,921600,1000000,1500000,0 + }; + +#define LCD_ENTRYMODE 0x04 /**< Set entrymode */ + +/** @name GENERAL COMMANDS */ +/*@{*/ +#define LCD_CLEAR 0x01 /**< Clear screen */ +#define LCD_HOME 0x02 /**< Cursor move to first digit */ +/*@}*/ + +/** @name ENTRYMODES */ +/*@{*/ +#define LCD_ENTRYMODE 0x04 /**< Set entrymode */ +#define LCD_INCREASE LCD_ENTRYMODE | 0x02 /**< Set cursor move direction -- Increase */ +#define LCD_DECREASE LCD_ENTRYMODE | 0x00 /**< Set cursor move direction -- Decrease */ +#define LCD_DISPLAYSHIFTON LCD_ENTRYMODE | 0x01 /**< Display is shifted */ +#define LCD_DISPLAYSHIFTOFF LCD_ENTRYMODE | 0x00 /**< Display is not shifted */ +/*@}*/ + +/** @name DISPLAYMODES */ +/*@{*/ +#define LCD_DISPLAYMODE 0x08 /**< Set displaymode */ +#define LCD_DISPLAYON LCD_DISPLAYMODE | 0x04 /**< Display on */ +#define LCD_DISPLAYOFF LCD_DISPLAYMODE | 0x00 /**< Display off */ +#define LCD_CURSORON LCD_DISPLAYMODE | 0x02 /**< Cursor on */ +#define LCD_CURSOROFF LCD_DISPLAYMODE | 0x00 /**< Cursor off */ +#define LCD_BLINKINGON LCD_DISPLAYMODE | 0x01 /**< Blinking on */ +#define LCD_BLINKINGOFF LCD_DISPLAYMODE | 0x00 /**< Blinking off */ +/*@}*/ + +/** @name SHIFTMODES */ +/*@{*/ +#define LCD_SHIFTMODE 0x10 /**< Set shiftmode */ +#define LCD_DISPLAYSHIFT LCD_SHIFTMODE | 0x08 /**< Display shift */ +#define LCD_CURSORMOVE LCD_SHIFTMODE | 0x00 /**< Cursor move */ +#define LCD_RIGHT LCD_SHIFTMODE | 0x04 /**< Right shift */ +#define LCD_LEFT LCD_SHIFTMODE | 0x00 /**< Left shift */ +/*@}*/ + +/** @name DISPLAY_CONFIGURATION */ +/*@{*/ +#define LCD_CONFIGURATION 0x20 /**< Set function */ +#define LCD_8BIT LCD_CONFIGURATION | 0x10 /**< 8 bits interface */ +#define LCD_4BIT LCD_CONFIGURATION | 0x00 /**< 4 bits interface */ +#define LCD_2LINE LCD_CONFIGURATION | 0x08 /**< 2 line display */ +#define LCD_1LINE LCD_CONFIGURATION | 0x00 /**< 1 line display */ +#define LCD_5X10 LCD_CONFIGURATION | 0x04 /**< 5 X 10 dots */ +#define LCD_5X7 LCD_CONFIGURATION | 0x00 /**< 5 X 7 dots */ + +#define LCD_SETCGRAMADDR 0x40 + +#define lcdPutChar(value) lcdWriteByte(value,1) +#define lcdCommand(value) lcdWriteByte(value,0) + +static const uint8_t LCDLineOffsets[] PROGMEM = UI_LINE_OFFSETS; +static const char versionString[] PROGMEM = UI_VERSION_STRING; + + +#if UI_DISPLAY_TYPE==1 || UI_DISPLAY_TYPE==2 + +void lcdWriteNibble(uint8_t value) +{ + WRITE(UI_DISPLAY_D4_PIN,value & 1); + WRITE(UI_DISPLAY_D5_PIN,value & 2); + WRITE(UI_DISPLAY_D6_PIN,value & 4); + WRITE(UI_DISPLAY_D7_PIN,value & 8); + WRITE(UI_DISPLAY_ENABLE_PIN, HIGH);// enable pulse must be >450ns + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + WRITE(UI_DISPLAY_ENABLE_PIN, LOW); + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + +} // lcdWriteNibble + + +void lcdWriteByte(uint8_t c,uint8_t rs) +{ +#if UI_DISPLAY_RW_PIN<0 + HAL::delayMicroseconds(UI_DELAYPERCHAR); +#else + SET_INPUT(UI_DISPLAY_D4_PIN); + SET_INPUT(UI_DISPLAY_D5_PIN); + SET_INPUT(UI_DISPLAY_D6_PIN); + SET_INPUT(UI_DISPLAY_D7_PIN); + WRITE(UI_DISPLAY_RW_PIN, HIGH); + WRITE(UI_DISPLAY_RS_PIN, LOW); + uint8_t busy; + do + { + WRITE(UI_DISPLAY_ENABLE_PIN, HIGH); + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + busy = READ(UI_DISPLAY_D7_PIN); + WRITE(UI_DISPLAY_ENABLE_PIN, LOW); + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + WRITE(UI_DISPLAY_ENABLE_PIN, HIGH); + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + WRITE(UI_DISPLAY_ENABLE_PIN, LOW); + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + } + while (busy); + SET_OUTPUT(UI_DISPLAY_D4_PIN); + SET_OUTPUT(UI_DISPLAY_D5_PIN); + SET_OUTPUT(UI_DISPLAY_D6_PIN); + SET_OUTPUT(UI_DISPLAY_D7_PIN); + WRITE(UI_DISPLAY_RW_PIN, LOW); +#endif // UI_DISPLAY_RW_PIN<0 + + WRITE(UI_DISPLAY_RS_PIN, rs); + WRITE(UI_DISPLAY_D4_PIN, c & 0x10); + WRITE(UI_DISPLAY_D5_PIN, c & 0x20); + WRITE(UI_DISPLAY_D6_PIN, c & 0x40); + WRITE(UI_DISPLAY_D7_PIN, c & 0x80); + WRITE(UI_DISPLAY_ENABLE_PIN, HIGH); // enable pulse must be >450ns + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + WRITE(UI_DISPLAY_ENABLE_PIN, LOW); + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + + WRITE(UI_DISPLAY_D4_PIN, c & 0x01); + WRITE(UI_DISPLAY_D5_PIN, c & 0x02); + WRITE(UI_DISPLAY_D6_PIN, c & 0x04); + WRITE(UI_DISPLAY_D7_PIN, c & 0x08); + WRITE(UI_DISPLAY_ENABLE_PIN, HIGH); // enable pulse must be >450ns + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + WRITE(UI_DISPLAY_ENABLE_PIN, LOW); + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + +} // lcdWriteByte + + +void initializeLCD() +{ + // bring all display pins into a defined state + SET_INPUT(UI_DISPLAY_D4_PIN); + SET_INPUT(UI_DISPLAY_D5_PIN); + SET_INPUT(UI_DISPLAY_D6_PIN); + SET_INPUT(UI_DISPLAY_D7_PIN); + SET_INPUT(UI_DISPLAY_RS_PIN); + +#if UI_DISPLAY_RW_PIN>-1 + SET_INPUT(UI_DISPLAY_RW_PIN); +#endif // UI_DISPLAY_RW_PIN>-1 + + SET_INPUT(UI_DISPLAY_ENABLE_PIN); + + // 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?? + HAL::delayMilliseconds(500); + SET_OUTPUT(UI_DISPLAY_D4_PIN); + SET_OUTPUT(UI_DISPLAY_D5_PIN); + SET_OUTPUT(UI_DISPLAY_D6_PIN); + SET_OUTPUT(UI_DISPLAY_D7_PIN); + SET_OUTPUT(UI_DISPLAY_RS_PIN); + +#if UI_DISPLAY_RW_PIN>-1 + SET_OUTPUT(UI_DISPLAY_RW_PIN); +#endif // UI_DISPLAY_RW_PIN>-1 + + SET_OUTPUT(UI_DISPLAY_ENABLE_PIN); + + // Now we pull both RS and R/W low to begin commands + WRITE(UI_DISPLAY_RS_PIN, LOW); + WRITE(UI_DISPLAY_ENABLE_PIN, 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. + WRITE(UI_DISPLAY_RS_PIN, LOW); + HAL::delayMicroseconds(10); + lcdWriteNibble(0x03); + HAL::delayMicroseconds(5000); // I have one LCD for which 4500 here was not long enough. + // second try + lcdWriteNibble(0x03); + HAL::delayMicroseconds(150); // wait + // third go! + lcdWriteNibble(0x03); + HAL::delayMicroseconds(150); + // finally, set to 4-bit interface + lcdWriteNibble(0x02); + HAL::delayMicroseconds(150); + // finally, set # lines, font size, etc. + lcdCommand(LCD_4BIT | LCD_2LINE | LCD_5X7); + + lcdCommand(LCD_CLEAR); //- Clear Screen + HAL::delayMilliseconds(2); // clear is slow operation + lcdCommand(LCD_INCREASE | LCD_DISPLAYSHIFTOFF); //- Entrymode (Display Shift: off, Increment Address Counter) + lcdCommand(LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKINGOFF); //- Display on + uid.lastSwitch = uid.lastRefresh = HAL::timeInMilliseconds(); + uid.createChar(1,character_back); + uid.createChar(2,character_degree); + uid.createChar(3,character_selected); + uid.createChar(4,character_unselected); + uid.createChar(5,character_temperature); + uid.createChar(6,character_folder); + uid.createChar(7,character_ready); + +} // initializeLCD + +// ----------- end direct LCD driver +#endif // UI_DISPLAY_TYPE==1 || UI_DISPLAY_TYPE==2 + + +#if UI_DISPLAY_TYPE<4 +void UIDisplay::printRow(uint8_t r,char *txt,char *txt2,uint8_t changeAtCol) +{ + changeAtCol = RMath::min(UI_COLS,changeAtCol); + uint8_t col=0; + + // Set row + if(r >= UI_ROWS) return; + +#if UI_DISPLAY_TYPE==3 + lcdStartWrite(); +#endif // UI_DISPLAY_TYPE==3 + + lcdWriteByte(128 + HAL::readFlashByte((const char *)&LCDLineOffsets[r]),0); // Position cursor + char c; + while((c=*txt) != 0x00 && col0 + ui_check_slow_encoder(); +#endif // UI_HAS_KEYS==1 && UI_HAS_I2C_ENCODER>0 + +} // printRow +#endif // UI_DISPLAY_TYPE<4 + + +char printCols[MAX_COLS+1]; +UIDisplay::UIDisplay() +{ + locked = 0; +} // UIDisplay + + +#if UI_ANIMATION +void slideIn(uint8_t row,FSTRINGPARAM(text)) +{ + char *empty=""; + int8_t i = 0; + uid.col=0; + uid.addStringP(text); + printCols[uid.col]=0; + for(i=UI_COLS-1; i>=0; i--) + { + uid.printRow(row,empty,printCols,i); + HAL::delayMilliseconds(10); + } + +} // slideIn +#endif // UI_ANIMATION + + +void UIDisplay::initialize() +{ + oldMenuLevel = -2; + flags = 0; + menuLevel = 0; + shift = -2; + menuPos[0] = 0; + lastAction = 0; + lastButtonAction = 0; + activeAction = 0; + statusMsg[0] = 0; + + messageLine1 = NULL; + messageLine2 = NULL; + messageLine3 = NULL; + messageLine4 = NULL; + + ui_init_keys(); + +#if SDSUPPORT + cwd[0]='/'; + cwd[1]=0; + folderLevel=0; +#endif // SDSUPPORT + +#if UI_DISPLAY_TYPE>0 + initializeLCD(); + +#if UI_ANIMATION==false || UI_DISPLAY_TYPE==5 +#if UI_DISPLAY_TYPE == 5 + //u8g picture loop + u8g_FirstPage(&u8g); + do + { +#endif // UI_DISPLAY_TYPE == 5 + + for(uint8_t y=0; y2 + printRowP(UI_ROWS-1, PSTR(UI_PRINTER_COMPANY)); +#endif // UI_ROWS>2 + +#if UI_DISPLAY_TYPE == 5 + } + while( u8g_NextPage(&u8g) ); //end picture loop +#endif // UI_DISPLAY_TYPE == 5 +#else + slideIn(0, versionString); + strcpy(displayCache[0], printCols); + slideIn(1, PSTR(UI_PRINTER_NAME)); + strcpy(displayCache[1], printCols); + +#if UI_ROWS>2 + slideIn(UI_ROWS-1, PSTR(UI_PRINTER_COMPANY)); + strcpy(displayCache[UI_ROWS-1], printCols); +#endif // UI_ROWS>2 +#endif // UI_ANIMATION==false || UI_DISPLAY_TYPE==5 + + HAL::delayMilliseconds(UI_START_SCREEN_DELAY); +#endif // UI_DISPLAY_TYPE>0 + +#if UI_DISPLAY_I2C_CHIPTYPE==0 && (BEEPER_TYPE==2 || defined(UI_HAS_I2C_KEYS)) + // Make sure the beeper is off + HAL::i2cStartWait(UI_I2C_KEY_ADDRESS+I2C_WRITE); + HAL::i2cWrite(255); // Disable beeper, enable read for other pins. + HAL::i2cStop(); +#endif // UI_DISPLAY_I2C_CHIPTYPE==0 && (BEEPER_TYPE==2 || defined(UI_HAS_I2C_KEYS)) + + if( READ(5) == 0 && READ(11) == 0 && READ(42) == 0 ) + { + g_nServiceRequest = 1; + } + +} // initialize + + +#if UI_DISPLAY_TYPE==1 || UI_DISPLAY_TYPE==2 || UI_DISPLAY_TYPE==3 +void UIDisplay::createChar(uint8_t location,const uint8_t charmap[]) +{ + location &= 0x7; // we only have 8 locations 0-7 + lcdCommand(LCD_SETCGRAMADDR | (location << 3)); + for (int i=0; i<8; i++) + { + lcdPutChar(pgm_read_byte(&(charmap[i]))); + } + +} // createChar +#endif // UI_DISPLAY_TYPE==1 || UI_DISPLAY_TYPE==2 || UI_DISPLAY_TYPE==3 + + +void UIDisplay::waitForKey() +{ + int nextAction = 0; + + + lastButtonAction = 0; + while(lastButtonAction==nextAction) + { + ui_check_slow_keys(nextAction); + } + +} // waitForKey + + +void UIDisplay::printRowP(uint8_t r,PGM_P txt) +{ + if(r >= UI_ROWS) return; + col=0; + addStringP(txt); + printCols[col]=0; + printRow(r,printCols,NULL,UI_COLS); + +} // printRowP + + +void UIDisplay::addInt(int value,uint8_t digits,char fillChar) +{ + uint8_t dig=0,neg=0; + if(value<0) + { + value = -value; + neg=1; + dig++; + } + char buf[7]; // Assumes 8-bit chars plus zero byte. + char *str = &buf[6]; + buf[6]=0; + do + { + unsigned int m = value; + value /= 10; + char c = m - 10 * value; + *--str = c + '0'; + dig++; + } + while(value); + if(neg) + printCols[col++]='-'; + if(digits<6) + while(dig=MAX_COLS) return; + number = -number; + fixdigits--; + } + number += pgm_read_float(&roundingTable[digits]); // for correct rounding + + // Extract the integer part of the number and print it + unsigned long int_part = (unsigned long)number; + float remainder = number - (float)int_part; + addLong(int_part,fixdigits); + if(col>=UI_COLS) return; + + // Print the decimal point, but only if there are digits beyond + if (digits > 0) + { + printCols[col++]='.'; + } + + // Extract digits from the remainder one at a time + while (col 0) + { + remainder *= 10.0; + uint8_t toPrint = uint8_t(remainder); + printCols[col++] = '0'+toPrint; + remainder -= toPrint; + } + +} // addFloat + + +void UIDisplay::addStringP(FSTRINGPARAM(text)) +{ + while(coltempControl.currentTemperatureC; // %ec : Current extruder temperature + else if(c2>='0' && c2<='9') fvalue=extruder[c2-'0'].tempControl.currentTemperatureC; // %e0..9 : Temp. of extruder 0..9 + else if(c2=='b') fvalue=Extruder::getHeatedBedTemperature(); // %eb : Current heated bed temperature + else if(c2=='B') + { + ivalue=0; + fvalue=Extruder::getHeatedBedTemperature(); + } + addFloat(fvalue,3,0 /*ivalue*/); + break; + } + case 'E': // Target extruder temperature + { +#if FEATURE_MILLING_MODE + if( Printer::operatingMode == OPERATING_MODE_MILL ) + { + // we do not maintain temperatures in milling mode + addStringP( PSTR( " " )); + break; + } +#endif // FEATURE_MILLING_MODE + + if(c2=='c') fvalue=Extruder::current->tempControl.targetTemperatureC; // %Ec : Target temperature of current extruder + else if(c2>='0' && c2<='9') fvalue=extruder[c2-'0'].tempControl.targetTemperatureC; // %E0-9 : Target temperature of extruder 0..9 + +#if HAVE_HEATED_BED + else if(c2=='b') fvalue=heatedBedController.targetTemperatureC; // %Eb : Target temperature of heated bed +#endif // HAVE_HEATED_BED + + addFloat(fvalue,3,0 /*UI_TEMP_PRECISION*/); + break; + } + +#if FAN_PIN > -1 + case 'F': // FAN speed + { + if(c2=='s') addInt(Printer::getFanSpeed()*100/255,3); // %Fs : Fan speed + break; + } +#endif // FAN_PIN > -1 + + case 'f': + { + if(c2=='x') addFloat(Printer::maxFeedrate[X_AXIS],5,0); // %fx : Max. feedrate x direction + else if(c2=='y') addFloat(Printer::maxFeedrate[Y_AXIS],5,0); // %fy : Max. feedrate y direction + else if(c2=='z') addFloat(Printer::maxFeedrate[Z_AXIS],5,0); // %fz : Max. feedrate z direction + else if(c2=='X') addFloat(Printer::homingFeedrate[X_AXIS],5,0); // %fX : Homing feedrate x direction + else if(c2=='Y') addFloat(Printer::homingFeedrate[Y_AXIS],5,0); // %fY : Homing feedrate y direction + else if(c2=='Z') addFloat(Printer::homingFeedrate[Z_AXIS],5,0); // %fZ : Homing feedrate z direction + break; + } + case 'i': + { + if(c2=='s') addLong(stepperInactiveTime/1000,4); // %is : Stepper inactive time in seconds + else if(c2=='p') addLong(maxInactiveTime/1000,4); // %ip : Max. inactive time in seconds + break; + } + case 'O': // ops related stuff + { +#if NUM_EXTRUDER>1 + if(c2=='a') // %Oa : Active Extruder + { + if( Extruder::current->id == 0 ) + { + addStringP(ui_text_0); + } + else + { + addStringP(ui_text_1); + } + } +#endif // NUM_EXTRUDER>1 + +#if NUM_EXTRUDER>1 + if(c2=='E') // %OE : Extruder offset X [mm] + { + addFloat(extruder[1].xOffset/Printer::axisStepsPerMM[X_AXIS],4,3); + } + if(c2=='F') // %OF : Extruder offset Y [mm] + { + addFloat(extruder[1].yOffset/Printer::axisStepsPerMM[Y_AXIS],4,3); + } +#endif // NUM_EXTRUDER>1 + + if(c2=='M') // %OM : operating mode + { +#if FEATURE_MILLING_MODE + addStringP(Printer::operatingMode==OPERATING_MODE_PRINT?ui_text_print_mode:ui_text_mill_mode); +#else + addStringP(ui_text_print_mode); +#endif // FEATURE_MILLING_MODE + } + if(c2=='Z') // %OZ : z endstop type + { +#if FEATURE_CONFIGURABLE_Z_ENDSTOPS + addStringP(Printer::ZEndstopType==ENDSTOP_TYPE_SINGLE?ui_text_z_single:ui_text_z_circuit); +#else + addStringP(ui_text_z_single); +#endif // FEATURE_CONFIGURABLE_Z_ENDSTOPS + } + break; + } + case 'h': + { + if(c2=='t') // %ht : hotend type + { +#if FEATURE_CONFIGURABLE_HOTEND_TYPE + switch(Printer::HotendType) + { + case HOTEND_TYPE_V1: addStringP(ui_text_hotend_v1); break; + case HOTEND_TYPE_V2_SINGLE: addStringP(ui_text_hotend_v2); break; + case HOTEND_TYPE_V2_DUAL: addStringP(ui_text_hotend_v2); break; + } +#endif // FEATURE_CONFIGURABLE_HOTEND_TYPE + } + break; + } + case 'l': + { + if(c2=='a') addInt(lastAction,4); + +#if FEATURE_CASE_LIGHT + else if(c2=='o') addStringP(Printer::enableCaseLight?ui_text_on:ui_text_off); // %lo : Lights on/off +#endif // FEATURE_CASE_LIGHT + +#if FEATURE_RGB_LIGHT_EFFECTS + else if(c2=='i') // %li : Light: White/Color + { + if( Printer::RGBLightModeForceWhite ) + { + addStringP(ui_text_white); + } + else + { + switch(Printer::RGBLightMode) + { + case RGB_MODE_OFF: addStringP(ui_text_off); break; + case RGB_MODE_WHITE: addStringP(ui_text_white); break; + case RGB_MODE_AUTOMATIC: addStringP(ui_text_color); break; + case RGB_MODE_MANUAL: addStringP(ui_text_manual); break; + } + } + } +#endif // FEATURE_RGB_LIGHT_EFFECTS + + break; + } + + case 'm': + { + if(c2=='Y') // %mY : menu yes + { + if(g_nYesNo) printCols[col++]=CHAR_SELECTED; + else printCols[col++]=' '; + } + else if(c2=='N') // %mN : menu no + { + if(g_nYesNo) printCols[col++]=' '; + else printCols[col++]=CHAR_SELECTED; + } + else if(c2=='t') // %mt : miller type + { +#if FEATURE_CONFIGURABLE_MILLER_TYPE + addStringP(Printer::MillerType==MILLER_TYPE_ONE_TRACK?ui_text_miller_one_track:ui_text_miller_two_tracks); +#endif // FEATURE_CONFIGURABLE_MILLER_TYPE + } + else if(c2=='1') // %m1 : message line 1 + { + if(messageLine1!=0) addStringP((char PROGMEM *)messageLine1); + break; + } + else if(c2=='2') // %m2 : message line 2 + { + if(messageLine2!=0) addStringP((char PROGMEM *)messageLine2); + break; + } + else if(c2=='3') // %m3 : message line 3 + { + if(messageLine3!=0) addStringP((char PROGMEM *)messageLine3); + break; + } + else if(c2=='4') // %m4 : message line 4 + { + if(messageLine4!=0) addStringP((char PROGMEM *)messageLine4); + break; + } + break; + } + case 'o': + { + if(c2=='s') // %os : Status message + { + if(locked) + { + //Com::printFLN( PSTR( "locked" ) ); + // do not change the status message in case it is locked + parse(statusMsg,true); + } + else + { +#if SDSUPPORT + if(sd.sdactive && sd.sdmode) + { + if( g_pauseMode >= PAUSE_MODE_PAUSED ) + { + // do not show the printing/milling progress while we are paused + parse(statusMsg,true); + } + else + { +#if FEATURE_MILLING_MODE + if( Printer::operatingMode == OPERATING_MODE_PRINT ) + { + addStringP(PSTR(UI_TEXT_PRINT_POS)); + unsigned long percent; + if(sd.filesize<20000000) percent=sd.sdpos*100/sd.filesize; + else percent = (sd.sdpos>>8)*100/(sd.filesize>>8); + addInt((int)percent,3); + if(col>8)*100/(sd.filesize>>8); + addInt((int)percent,3); + if(col>8)*100/(sd.filesize>>8); + addInt((int)percent,3); + if(col='0' && c2<='9') // %o0..9 : Output level extruder 0..9 is % including %sign + { + ivalue=pwm_pos[c2-'0']; + } + +#if HAVE_HEATED_BED + else if(c2=='b') // %ob : Output level heated bed + { + ivalue=pwm_pos[heatedBedController.pwmIndex]; + } +#endif // HAVE_HEATED_BED + + else if(c2=='C') // %oC : Output level current extruder + { + ivalue=pwm_pos[Extruder::current->id]; + } + + ivalue=(ivalue*100)/255; + addInt(ivalue,3); + if(col='0' && c2<='3') + { + if(c2=='0') // %x0 : X position + { + if( Printer::blockAll ) + { + // we can not move any more + bDefect = true; + } + else + { + fvalue = Printer::currentXPosition(); + } + } + else if(c2=='1') // %x1 : Y position + { + if( Printer::blockAll ) + { + // we can not move any more + bDefect = true; + } + else + { + fvalue = Printer::currentYPosition(); + } + } + else if(c2=='2') // %x2 : Z position + { + if( Printer::blockAll ) + { + // we can not move any more + bDefect = true; + } + else + { + fvalue = Printer::currentZPosition(); + } + } + else // %x3 : Current extruder position + { + if( Printer::blockAll ) + { + // we can not move any more + bDefect = true; + } + else + { + fvalue = (float)Printer::queuePositionLastSteps[E_AXIS]*Printer::invAxisStepsPerMM[E_AXIS]; + } + } + + if( bDefect ) + { + addStringP( PSTR(" def") ); + } + else + { + addFloat(fvalue,4,2); + } + } + break; + } + case 'y': + { + break; + } + case 'z': // %z0 : Z Offset + { + if(c2=='0') + { + addInt(Printer::ZOffset,4); + } + else if(c2=='m') // %zm : Z Scale + { +#if FEATURE_MILLING_MODE + if( Printer::operatingMode == OPERATING_MODE_MILL ) + { + addStringP(Printer::ZMode==Z_VALUE_MODE_Z_ORIGIN?ui_text_z_mode_z_origin:ui_text_z_mode_surface); + } + else +#endif // FEATURE_MILLING_MODE + { + addStringP(Printer::ZMode==Z_VALUE_MODE_Z_MIN?ui_text_z_mode_min:ui_text_z_mode_surface); + } + } + break; + } + case 'X': // Extruder related + { +#if NUM_EXTRUDER>0 + if(c2>='0' && c2<='9') // %X0..9 : Extruder selected marker + { + addStringP(Extruder::current->id==c2-'0'?ui_selected:ui_unselected); + } + +#ifdef TEMP_PID + else if(c2=='i') // %Xi : PID I gain + { + addFloat(Extruder::current->tempControl.pidIGain,4,2); + } + else if(c2=='p') // %Xp : PID P gain + { + addFloat(Extruder::current->tempControl.pidPGain,4,2); + } + else if(c2=='d') // %Xd : PID D gain + { + addFloat(Extruder::current->tempControl.pidDGain,4,2); + } + else if(c2=='m') // %Xm : PID drive min + { + addInt(Extruder::current->tempControl.pidDriveMin,3); + } + else if(c2=='M') // %XM : PID drive max + { + addInt(Extruder::current->tempControl.pidDriveMax,3); + } + else if(c2=='D') // %XD : PID max + { + addInt(Extruder::current->tempControl.pidMax,3); + } +#endif // TEMP_PID + + else if(c2=='w') // %Xw : Extruder watch period in seconds + { + addInt(Extruder::current->watchPeriod,4); + } + +#if RETRACT_DURING_HEATUP + else if(c2=='T') // %XT : Extruder wait retract temperature + { + addInt(Extruder::current->waitRetractTemperature,4); + } + else if(c2=='U') // %XU : Extruder wait retract unit + { + addInt(Extruder::current->waitRetractUnits,2); + } +#endif // RETRACT_DURING_HEATUP + + else if(c2=='h') // %Xh : Extruder heat manager (BangBang/PID) + { + uint8_t hm = Extruder::current->tempControl.heatManager; + if(hm == 1) + addStringP(PSTR(UI_TEXT_STRING_HM_PID)); + else if(hm == 3) + addStringP(PSTR(UI_TEXT_STRING_HM_DEADTIME)); + else if(hm == 2) + addStringP(PSTR(UI_TEXT_STRING_HM_SLOWBANG)); + else + addStringP(PSTR(UI_TEXT_STRING_HM_BANGBANG)); + } + +#ifdef USE_ADVANCE +#ifdef ENABLE_QUADRATIC_ADVANCE + else if(c2=='a') + { + addFloat(Extruder::current->advanceK,3,0); + } +#endif // ENABLE_QUADRATIC_ADVANCE + + else if(c2=='l') // %Xl : Advance L value + { + addFloat(Extruder::current->advanceL,3,0); + } +#endif // USE_ADVANCE + + else if(c2=='f') // %Xf : Extruder max. start feedrate + { + addFloat(Extruder::current->maxStartFeedrate,5,0); + } + else if(c2=='F') // %XF : Extruder max. feedrate + { + addFloat(Extruder::current->maxFeedrate,5,0); + } + else if(c2=='A') // %XA : Extruder max. acceleration + { + addFloat(Extruder::current->maxAcceleration,5,0); + } +#endif // NUM_EXTRUDER>0 + + break; + } + case 's': // Endstop positions + { + if(c2=='x') // %sx : State of x min endstop + { +#if (X_MIN_PIN > -1) && MIN_HARDWARE_ENDSTOP_X + addStringP(Printer::isXMinEndstopHit()?ui_text_on:ui_text_off); +#else + addStringP(ui_text_na); +#endif // (X_MIN_PIN > -1) && MIN_HARDWARE_ENDSTOP_X + } + if(c2=='X') // %sX : State of x max endstop +#if (X_MAX_PIN > -1) && MAX_HARDWARE_ENDSTOP_X + addStringP(Printer::isXMaxEndstopHit()?ui_text_on:ui_text_off); +#else + addStringP(ui_text_na); +#endif // (X_MAX_PIN > -1) && MAX_HARDWARE_ENDSTOP_X + + if(c2=='y') // %sy : State of y min endstop +#if (Y_MIN_PIN > -1)&& MIN_HARDWARE_ENDSTOP_Y + addStringP(Printer::isYMinEndstopHit()?ui_text_on:ui_text_off); +#else + addStringP(ui_text_na); +#endif // (Y_MIN_PIN > -1)&& MIN_HARDWARE_ENDSTOP_Y + + if(c2=='Y') // %sY : State of y max endstop +#if (Y_MAX_PIN > -1) && MAX_HARDWARE_ENDSTOP_Y + addStringP(Printer::isYMaxEndstopHit()?ui_text_on:ui_text_off); +#else + addStringP(ui_text_na); +#endif // (Y_MAX_PIN > -1) && MAX_HARDWARE_ENDSTOP_Y + + if(c2=='z') // %sz : State of z min endstop + { +#if (Z_MIN_PIN > -1) && MIN_HARDWARE_ENDSTOP_Z + +#if FEATURE_CONFIGURABLE_Z_ENDSTOPS + if( Printer::ZEndstopUnknown ) + { + addStringP(ui_text_unknown); + } + else + { + addStringP(Printer::isZMinEndstopHit()?ui_text_on:ui_text_off); + } +#else + addStringP(Printer::isZMinEndstopHit()?ui_text_on:ui_text_off); +#endif // FEATURE_CONFIGURABLE_Z_ENDSTOPS + +#else + addStringP(ui_text_na); +#endif // (Z_MIN_PIN > -1) && MIN_HARDWARE_ENDSTOP_Z + } + if(c2=='Z') // %sZ : State of z max endstop + { +#if (Z_MAX_PIN > -1) && MAX_HARDWARE_ENDSTOP_Z + +#if FEATURE_CONFIGURABLE_Z_ENDSTOPS + if( Printer::ZEndstopUnknown ) + { + addStringP(ui_text_unknown); + } + else + { + addStringP(Printer::isZMaxEndstopHit()?ui_text_on:ui_text_off); + } +#else + addStringP(Printer::isZMaxEndstopHit()?ui_text_on:ui_text_off); +#endif // FEATURE_CONFIGURABLE_Z_ENDSTOPS + +#else + addStringP(ui_text_na); +#endif // (Z_MAX_PIN > -1) && MAX_HARDWARE_ENDSTOP_Z + } + if(c2=='C') // %sC : State of the z compensation + { +#if FEATURE_HEAT_BED_Z_COMPENSATION + if( Printer::doHeatBedZCompensation ) + { + addStringP(ui_text_z_compensation_active); + } +#endif // FEATURE_HEAT_BED_Z_COMPENSATION + +#if FEATURE_WORK_PART_Z_COMPENSATION + if( Printer::doWorkPartZCompensation ) + { + addStringP(ui_text_z_compensation_active); + } +#endif // FEATURE_WORK_PART_Z_COMPENSATION + } + + if(c2=='S') // %sS : State of the sensible offset + { +#if FEATURE_SENSIBLE_PRESSURE + if( Printer::doHeatBedZCompensation ) + { + addInt((int)g_nSensiblePressureOffset,3); + }else{ + addInt(0,3); + } +#endif // FEATURE_SENSIBLE_PRESSURE + } + + if(c2=='M') // %sM : State of the sensible offset + { +#if FEATURE_SENSIBLE_PRESSURE + if( Printer::doHeatBedZCompensation && g_nSensiblePressureDigits > 0 ) + { + addInt((int)g_nSensiblePressureDigits,5); + }else{ + addStringP(ui_text_off); + } +#endif // FEATURE_SENSIBLE_PRESSURE + } + + if(c2=='1') // %s1 : current value of the strain gauge + { + addInt(readStrainGauge(I2C_ADDRESS_STRAIN_GAUGE),5); + } + + break; + } + case 'S': + { + if(c2=='e') addFloat(Extruder::current->stepsPerMM,3,1); // %Se : Steps per mm current extruder + if(c2=='z') addFloat(g_nManualSteps[Z_AXIS] * Printer::invAxisStepsPerMM[Z_AXIS] * 1000,4,0); // %Sz : Mikrometer per Z-Single_Step (Z_Axis) + break; + } + case 'p': + { + if(c2=='x') // %px: mode of the Position X menu + { + switch( Printer::moveMode[X_AXIS] ) + { + case MOVE_MODE_SINGLE_STEPS: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_SINGLE_STEPS)); + break; + } + case MOVE_MODE_SINGLE_MOVE: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_SINGLE_MOVE)); + break; + } + case MOVE_MODE_1_MM: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_1_MM)); + break; + } + case MOVE_MODE_10_MM: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_10_MM)); + break; + } + case MOVE_MODE_50_MM: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_50_MM)); + break; + } + } + } + if(c2=='y') // %py: mode of the Position Y menu + { + switch( Printer::moveMode[Y_AXIS] ) + { + case MOVE_MODE_SINGLE_STEPS: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_SINGLE_STEPS)); + break; + } + case MOVE_MODE_SINGLE_MOVE: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_SINGLE_MOVE)); + break; + } + case MOVE_MODE_1_MM: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_1_MM)); + break; + } + case MOVE_MODE_10_MM: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_10_MM)); + break; + } + case MOVE_MODE_50_MM: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_50_MM)); + break; + } + } + } + if(c2=='z') // %pz: mode of the Position Z menu + { + switch( Printer::moveMode[Z_AXIS] ) + { + case MOVE_MODE_SINGLE_STEPS: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_SINGLE_STEPS)); + break; + } + case MOVE_MODE_SINGLE_MOVE: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_SINGLE_MOVE)); + break; + } + case MOVE_MODE_1_MM: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_1_MM)); + break; + } + case MOVE_MODE_10_MM: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_10_MM)); + break; + } + case MOVE_MODE_50_MM: + { + addStringP(PSTR(UI_TEXT_MOVE_MODE_50_MM)); + break; + } + } + } + break; + } + case 'P': + { + if(c2=='N') addStringP(PSTR(UI_PRINTER_NAME)); // %PN : Printer name + break; + } + case 'U': // %U1: Page1 + { + if(c2=='1') // temperature icon + { + char mode = OPERATING_MODE_PRINT; + + +#if FEATURE_MILLING_MODE + mode = Printer::operatingMode; +#endif // FEATURE_MILLING_MODE + + if ( mode == OPERATING_MODE_PRINT ) + { + addStringP(PSTR("\005")); + break; + } + else if ( mode == OPERATING_MODE_MILL ) + { + addStringP( PSTR( " " )); + break; + } + } + break; + } + case 'Z': // %Z1-Z4: Page5 service intervall, %Z5-Z8: Page4 printing/milling time + { + if(c2=='1') // Shows text printing/milling time since last service + { +#if FEATURE_SERVICE_INTERVAL + addStringP(PSTR(UI_TEXT_SERVICE_TIME)); +#endif // FEATURE_SERVICE_INTERVAL + } + else if(c2=='2') // Shows printing/milling time since last service + { +#if FEATURE_SERVICE_INTERVAL +#if EEPROM_MODE!=0 + char mode = OPERATING_MODE_PRINT; + + +#if FEATURE_MILLING_MODE + mode = Printer::operatingMode; +#endif // FEATURE_MILLING_MODE + + if ( mode == OPERATING_MODE_PRINT ) + { + bool alloff = true; + for(uint8_t i=0; itargetTemperatureC>15) alloff = false; + + long uSecondsServicePrint = (alloff ? 0 : (HAL::timeInMilliseconds()-Printer::msecondsPrinting)/1000) + HAL::eprGetInt32(EPR_PRINTING_TIME_SERVICE); + long tmp_service = uSecondsServicePrint/86400; + uSecondsServicePrint-=tmp_service*86400; + addInt(tmp_service,5); + addStringP(PSTR(UI_TEXT_PRINTTIME_DAYS)); + tmp_service=uSecondsServicePrint/3600; + addInt(tmp_service,2); + addStringP(PSTR(UI_TEXT_PRINTTIME_HOURS)); + uSecondsServicePrint-=tmp_service*3600; + tmp_service = uSecondsServicePrint/60; + addInt(tmp_service,2,'0'); + addStringP(PSTR(UI_TEXT_PRINTTIME_MINUTES)); + } + else + { + long uSecondsServicePrint = (HAL::timeInMilliseconds()-Printer::msecondsMilling)/1000 + HAL::eprGetInt32(EPR_MILLING_TIME_SERVICE); + long tmp_service = uSecondsServicePrint/86400; + uSecondsServicePrint-=tmp_service*86400; + addInt(tmp_service,5); + addStringP(PSTR(UI_TEXT_PRINTTIME_DAYS)); + tmp_service=uSecondsServicePrint/3600; + addInt(tmp_service,2); + addStringP(PSTR(UI_TEXT_PRINTTIME_HOURS)); + uSecondsServicePrint-=tmp_service*3600; + tmp_service = uSecondsServicePrint/60; + addInt(tmp_service,2,'0'); + addStringP(PSTR(UI_TEXT_PRINTTIME_MINUTES)); + } +#endif // EEPROM_MODE +#endif // FEATURE_SERVICE_INTERVAL + } + else if(c2=='3') // Shows text printed filament since last service + { +#if FEATURE_SERVICE_INTERVAL + char mode = OPERATING_MODE_PRINT; + + +#if FEATURE_MILLING_MODE + mode = Printer::operatingMode; +#endif // FEATURE_MILLING_MODE + + if ( mode == OPERATING_MODE_PRINT ) + { + addStringP(PSTR(UI_TEXT_PRINT_FILAMENT)); + } + else if ( mode == OPERATING_MODE_MILL ) + { + addStringP( PSTR( "" )); + } +#endif // FEATURE_SERVICE_INTERVAL + } + else if(c2=='4') // Shows printed filament since last service + { +#if FEATURE_SERVICE_INTERVAL + char mode = OPERATING_MODE_PRINT; + + +#if FEATURE_MILLING_MODE + mode = Printer::operatingMode; +#endif // FEATURE_MILLING_MODE + + if ( mode == OPERATING_MODE_PRINT ) + { +#if EEPROM_MODE!=0 + float dist_service = Printer::filamentPrinted*0.001+HAL::eprGetFloat(EPR_PRINTING_DISTANCE_SERVICE); + addFloat(dist_service,6,1); + addStringP( PSTR( " m" )); +#endif // EEPROM_MODE + } + else if ( mode == OPERATING_MODE_MILL ) + { + addStringP( PSTR( "" )); + } +#endif // FEATURE_SERVICE_INTERVAL + } + else if(c2=='5') // Shows text printing/milling time + { + char mode = OPERATING_MODE_PRINT; + + +#if FEATURE_MILLING_MODE + mode = Printer::operatingMode; +#endif // FEATURE_MILLING_MODE + + if ( mode == OPERATING_MODE_PRINT ) + { + addStringP(PSTR(UI_TEXT_PRINT_TIME)); + } + else if ( mode == OPERATING_MODE_MILL ) + { + addStringP(PSTR(UI_TEXT_MILL_TIME)); + } + } + else if(c2=='6') // Shows printing/milling time + { +#if EEPROM_MODE!=0 + char mode = OPERATING_MODE_PRINT; + + +#if FEATURE_MILLING_MODE + mode = Printer::operatingMode; +#endif // FEATURE_MILLING_MODE + + if ( mode == OPERATING_MODE_PRINT ) + { + bool alloff = true; + for(uint8_t i=0; itargetTemperatureC>15) alloff = false; + + long seconds = (alloff ? 0 : (HAL::timeInMilliseconds()-Printer::msecondsPrinting)/1000) + HAL::eprGetInt32(EPR_PRINTING_TIME); + long tmp = seconds/86400; + seconds-=tmp*86400; + addInt(tmp,5); + addStringP(PSTR(UI_TEXT_PRINTTIME_DAYS)); + tmp=seconds/3600; + addInt(tmp,2); + addStringP(PSTR(UI_TEXT_PRINTTIME_HOURS)); + seconds-=tmp*3600; + tmp = seconds/60; + addInt(tmp,2,'0'); + addStringP(PSTR(UI_TEXT_PRINTTIME_MINUTES)); + } + else + { + long seconds = (HAL::timeInMilliseconds()-Printer::msecondsMilling)/1000 + HAL::eprGetInt32(EPR_MILLING_TIME); + long tmp = seconds/86400; + seconds-=tmp*86400; + addInt(tmp,5); + addStringP(PSTR(UI_TEXT_PRINTTIME_DAYS)); + tmp=seconds/3600; + addInt(tmp,2); + addStringP(PSTR(UI_TEXT_PRINTTIME_HOURS)); + seconds-=tmp*3600; + tmp = seconds/60; + addInt(tmp,2,'0'); + addStringP(PSTR(UI_TEXT_PRINTTIME_MINUTES)); + } +#endif // EEPROM_MODE + } + else if(c2=='7') // Shows text printed filament + { + char mode = OPERATING_MODE_PRINT; + + +#if FEATURE_MILLING_MODE + mode = Printer::operatingMode; +#endif // FEATURE_MILLING_MODE + + if ( mode == OPERATING_MODE_PRINT ) + { + addStringP(PSTR(UI_TEXT_PRINT_FILAMENT)); + } + else if ( mode == OPERATING_MODE_MILL ) + { + addStringP( PSTR( "" )); + } + } + else if(c2=='8') // Shows printed filament + { + char mode = OPERATING_MODE_PRINT; + + +#if FEATURE_MILLING_MODE + mode = Printer::operatingMode; +#endif // FEATURE_MILLING_MODE + + if ( mode == OPERATING_MODE_PRINT ) + { +#if EEPROM_MODE!=0 + float dist = Printer::filamentPrinted*0.001+HAL::eprGetFloat(EPR_PRINTING_DISTANCE); + addFloat(dist,6,1); + addStringP( PSTR( " m" )); +#endif // EEPROM_MODE + } + else if ( mode == OPERATING_MODE_MILL ) + { + addStringP( PSTR( "" )); + } + } + break; + } + } + } + printCols[col] = 0; + +} // parse + + +void UIDisplay::setStatusP(PGM_P txt,bool error) +{ + if( locked ) + { + // we shall not update the display + return; + } + if(!error && Printer::isUIErrorMessage()) + { + return; + } + + uint8_t i=0; + while(irewind(); + nFilesOnCard = 0; + while ((p = root->getLongFilename(p, NULL, 0, NULL))) + { + if (! (DIR_IS_FILE(p) || DIR_IS_SUBDIR(p))) + continue; + if (folderLevel>=SD_MAX_FOLDER_DEPTH && DIR_IS_SUBDIR(p) && !(p->name[0]=='.' && p->name[1]=='.')) + continue; + nFilesOnCard++; + if (nFilesOnCard==254) + return; + } + +} // updateSDFileCount + + +void getSDFilenameAt(byte filePos,char *filename) +{ + dir_t* p = NULL; + //byte c=0; + SdBaseFile *root = sd.fat.vwd(); + + root->rewind(); + while ((p = root->getLongFilename(p, tempLongFilename, 0, NULL))) + { + if (!DIR_IS_FILE(p) && !DIR_IS_SUBDIR(p)) continue; + if(uid.folderLevel>=SD_MAX_FOLDER_DEPTH && DIR_IS_SUBDIR(p) && !(p->name[0]=='.' && p->name[1]=='.')) continue; + if (filePos--) + continue; + strcpy(filename, tempLongFilename); + if(DIR_IS_SUBDIR(p)) strcat(filename, "/"); // Set marker for directory + break; + } + +} // getSDFilenameAt + + +bool UIDisplay::isDirname(char *name) +{ + while(*name) name++; + name--; + return *name=='/'; + +} // isDirname + + +void UIDisplay::goDir(char *name) +{ + char *p = cwd; + while(*p)p++; + if(name[0]=='.' && name[1]=='.') + { + if(folderLevel==0) return; + p--; + p--; + while(*p!='/') p--; + p++; + *p = 0; + folderLevel--; + } + else + { + if(folderLevel>=SD_MAX_FOLDER_DEPTH) return; + while(*name) *p++ = *name++; + *p = 0; + folderLevel++; + } + sd.fat.chdir(cwd); + updateSDFileCount(); + +} // goDir + + +void sdrefresh(uint8_t &r,char cache[UI_ROWS][MAX_COLS+1]) +{ + dir_t* p = NULL; + byte offset = uid.menuTop[uid.menuLevel]; + SdBaseFile *root; + byte length, skip; + + sd.fat.chdir(uid.cwd); + root = sd.fat.vwd(); + root->rewind(); + + skip = (offset>0?offset-1:0); + + while (r+offsetgetLongFilename(p, tempLongFilename, 0, NULL))) + { + // done if past last used entry + // skip deleted entry and entries for . and .. + // only list subdirectories and files + if ((DIR_IS_FILE(p) || DIR_IS_SUBDIR(p))) + { + if(uid.folderLevel >= SD_MAX_FOLDER_DEPTH && DIR_IS_SUBDIR(p) && !(p->name[0]=='.' && p->name[1]=='.')) + continue; + if(skip>0) + { + skip--; + continue; + } + + printCols[0] = ' '; + uid.col = 1; + + if(DIR_IS_SUBDIR(p)) + printCols[uid.col++] = 6; // Prepend folder symbol + length = RMath::min((int)strlen(tempLongFilename), MAX_COLS-uid.col); + memcpy(printCols+uid.col, tempLongFilename, length); + uid.col += length; + printCols[uid.col] = 0; + + uint8_t curShift = (uid.shift<=0 ? 0 : uid.shift); + uint8_t curLen = strlen(printCols); + + if(curLen>UI_COLS) + { + // this file name is longer than the available width of the display + curShift = RMath::min(curLen-UI_COLS,curShift); + } + else + { + curShift = 0; + } + + if(r+offset == uid.menuPos[uid.menuLevel]) + { + // the menu cursor is placed at this file name at the moment + printCols[curShift] = (char)CHAR_SELECTOR; + } + else + { + // this file name is above/below the current menu cursor item + printCols[curShift] = ' '; + } + + if(DIR_IS_SUBDIR(p)) + printCols[curShift+1] = 6; // Prepend folder symbol + + strcpy(cache[r++],printCols); + } + } + +} // sdrefresh +#endif // SDSUPPORT + + +// Refresh current menu page +void UIDisplay::refreshPage() +{ + uint8_t r; + uint8_t mtype = 0; + char cache[UI_ROWS][MAX_COLS+1]; + adjustMenuPos(); + +#if FEATURE_MILLING_MODE + if( Printer::operatingMode == OPERATING_MODE_PRINT ) + { +#if UI_PRINT_AUTORETURN_TO_MENU_AFTER + // Reset timeout on menu back when user active on menu + if (uid.encoderLast != encoderStartScreen) + g_nAutoReturnTime=HAL::timeInMilliseconds()+UI_PRINT_AUTORETURN_TO_MENU_AFTER; +#endif // UI_PRINT_AUTORETURN_TO_MENU_AFTER + } + else + { +#if UI_MILL_AUTORETURN_TO_MENU_AFTER + // Reset timeout on menu back when user active on menu + if (uid.encoderLast != encoderStartScreen) + g_nAutoReturnTime=HAL::timeInMilliseconds()+UI_MILL_AUTORETURN_TO_MENU_AFTER; +#endif // UI_MILL_AUTORETURN_TO_MENU_AFTER + } +#else +#if UI_PRINT_AUTORETURN_TO_MENU_AFTER + // Reset timeout on menu back when user active on menu + if (uid.encoderLast != encoderStartScreen) + g_nAutoReturnTime=HAL::timeInMilliseconds()+UI_PRINT_AUTORETURN_TO_MENU_AFTER; +#endif // UI_PRINT_AUTORETURN_TO_MENU_AFTER +#endif // FEATURE_MILLING_MODE + + encoderStartScreen = uid.encoderLast; + + // Copy result into cache + if(menuLevel==0) + { + UIMenu *men = (UIMenu*)pgm_read_word(&(ui_pages[menuPos[0]])); + short nr = pgm_read_word_near(&(men->numEntries)); + UIMenuEntry **entries = (UIMenuEntry**)pgm_read_word(&(men->entries)); + for(r=0; rtext)),false); + strcpy(cache[r],printCols); + } + } + else + { + UIMenu *men = (UIMenu*)menu[menuLevel]; + short nr = pgm_read_word_near((void*)&(men->numEntries)); + mtype = pgm_read_byte((void*)&(men->menuType)); + uint8_t offset = menuTop[menuLevel]; + UIMenuEntry **entries = (UIMenuEntry**)pgm_read_word(&(men->entries)); + + for(r=0; r+offsetshowEntry()) + { + offset++; + continue; + } + + unsigned char entType = pgm_read_byte(&(ent->menuType)); + int entAction = (int)pgm_read_word(&(ent->action)); + + printCols[0] = ' '; + col = 1; + parse((char*)pgm_read_word(&(ent->text)),false); + while(col=2 && entType<=4) + { + // this is a menu item + uint8_t curShift = (shift<=0 ? 0 : shift); + uint8_t curLen = strlen(printCols); + + if(entType==2) + { + // this menu item contains submenus + curLen ++; // one additional character is needed for the submenu marker + } + + if(curLen>UI_COLS) + { + // this menu item is longer than the available width of the display + curShift = RMath::min(curLen-UI_COLS,curShift); + } + else + { + curShift = 0; + } + + if(r+offset==menuPos[menuLevel] && activeAction!=entAction) + { + // the menu cursor is placed at this item at the moment + printCols[curShift] = (char)CHAR_SELECTOR; + } + else if(activeAction==entAction) + { + // this menu item is selected (and can be changed) at the moment + printCols[curShift] = CHAR_SELECTED; + } + else + { + // this menu item is above/below the current menu cursor item + printCols[curShift] = ' '; + } + + if(entType==2) + { + printCols[UI_COLS-1 + curShift] = (char)CHAR_RIGHT; // arrow right + printCols[UI_COLS + curShift] = 0; // arrow right + } + } + + strcpy(cache[r],printCols); + r++; + } + } + +#if SDSUPPORT + if(mtype==1) + { + sdrefresh(r,cache); + } +#endif // SDSUPPORT + + printCols[0]=0; + while(roldMenuLevel) + transition = 3; + else + transition = 4; + } +#endif // UI_ANIMATION + + uint8_t loops = 1; + uint8_t dt = 1,y; + if(transition == 1 || transition == 2) loops = UI_ROWS; + else if(transition>2) + { + dt = (UI_COLS+UI_COLS-1)/16; + loops = UI_COLS+1/dt; + } + uint8_t off0 = (shift<=0 ? 0 : shift); + uint8_t scroll = dt; + uint8_t off[UI_ROWS]; + if(transition == 0) + { + for(y=0; yUI_COLS ? RMath::min(len-UI_COLS,off0) : 0; + +#if UI_ANIMATION + if(transition == 3) + { + for(r=len; r UI_ROWS) + { + scroll = UI_ROWS; + l = loops; + } + for(y=0; y UI_ROWS) + { + scroll = UI_ROWS; + l = loops; + } + for(y=0; y UI_COLS) + { + scroll = UI_COLS; + l = loops; + } + for(y=0; y UI_COLS) + { + scroll = UI_COLS; + l = loops; + } + for(y=0; ymenuType))==1) // Open files list + updateSDFileCount(); +#endif // SDSUPPORT + + if(refresh) + refreshPage(); + +} // pushMenu + + +void UIDisplay::okAction() +{ + if(Printer::isUIErrorMessage()) + { + Printer::setUIErrorMessage(false); + return; + } + +#if UI_HAS_KEYS==1 + if(menuLevel==0) // Enter menu + { + menuLevel = 1; + menuTop[1] = menuPos[1] = 0; + menu[1] = (void*)&ui_menu_main; + BEEP_SHORT + return; + } + + UIMenu *men = (UIMenu*)menu[menuLevel]; + uint8_t mtype = pgm_read_byte(&(men->menuType)); + UIMenuEntry **entries = (UIMenuEntry**)pgm_read_word(&(men->entries)); + UIMenuEntry *ent =(UIMenuEntry *)pgm_read_word(&(entries[menuPos[menuLevel]])); + unsigned char entType = pgm_read_byte(&(ent->menuType));// 0 = Info, 1 = Headline, 2 = submenu ref, 3 = direct action command, 4 = modify action + int action = pgm_read_word(&(ent->action)); + + if(mtype==3) // action menu + { + action = pgm_read_word(&(men->id)); + finishAction(action); + executeAction(UI_ACTION_BACK); + return; + } + if(mtype==2 && entType==4) // Modify action + { + if(activeAction) // finish action + { + finishAction(action); + activeAction = 0; + } + else + activeAction = action; + return; + } + +#if SDSUPPORT + if(mtype==1) + { + if(menuPos[menuLevel]==0) // Selected back instead of file + { + executeAction(UI_ACTION_BACK); + return; + } + if(!sd.sdactive) + return; + + uint8_t filePos = menuPos[menuLevel]-1; + char filename[LONG_FILENAME_LENGTH+1]; + + getSDFilenameAt(filePos, filename); + if(isDirname(filename)) // Directory change selected + { + goDir(filename); + menuTop[menuLevel]=0; + menuPos[menuLevel]=1; + refreshPage(); + oldMenuLevel = -1; + return; + } + + int16_t action; + if (Printer::isAutomount()) + action = UI_ACTION_SD_PRINT; + else + { + men = (UIMenu*)menu[menuLevel-1]; + entries = (UIMenuEntry**)pgm_read_word(&(men->entries)); + ent =(UIMenuEntry *)pgm_read_word(&(entries[menuPos[menuLevel-1]])); + action = pgm_read_word(&(ent->action)); + } + sd.file.close(); + sd.fat.chdir(cwd); + switch(action) + { + case UI_ACTION_SD_PRINT: + { + if (sd.selectFile(filename, false)) + { + sd.startPrint(); + BEEP_START_PRINTING + menuLevel = 0; + } + break; + } + case UI_ACTION_SD_DELETE: + { + if(sd.sdactive) + { + if(Printer::isMenuMode(MENU_MODE_SD_PRINTING)) + { + // we do not allow to delete a file while we are printing/milling from the SD card + if( Printer::debugErrors() ) + { + Com::printFLN(PSTR("It is not possible to delete a file from the SD card until the current processing has finished.")); + } + + showError( (void*)ui_text_delete_file, (void*)ui_text_operation_denied ); + break; + } + + sd.sdmode = false; + sd.file.close(); + if(sd.fat.remove(filename)) + { + if( Printer::debugInfo() ) + { + Com::printFLN(Com::tFileDeleted); + } + BEEP_LONG + } + else + { + if( Printer::debugErrors() ) + { + Com::printFLN(Com::tDeletionFailed); + } + } + } + break; + } + } + return; + } +#endif // SDSUPPORT + + if(entType==2) // Enter submenu + { + pushMenu((void*)action,false); + BEEP_SHORT + return; + } + if(entType==3) + { + executeAction(action); + return; + } + executeAction(UI_ACTION_BACK); +#endif // UI_HAS_KEYS==1 + +} // okAction + + +void UIDisplay::rightAction() +{ +#if FEATURE_SENSIBLE_PRESSURE + if( uid.menuLevel == 0 && uid.menuPos[0] == 1 ){ //wenn im Mod-Menü für Z-Offset/Matrix Sense-Offset/Limiter, dann anders! + //we are in the Mod menu + if(g_nSensiblePressureDigits == EMERGENCY_PAUSE_DIGITS_MAX * 0.8 || g_nSensiblePressureDigits == 32767){ + //ist max, dann auf 0. + g_nSensiblePressureDigits = 0; + }else if(g_nSensiblePressureDigits > EMERGENCY_PAUSE_DIGITS_MAX * 0.8 - 250 || g_nSensiblePressureDigits > 32767 - 250){ + //stößt oben an, hier noch check auf overflow: + if(EMERGENCY_PAUSE_DIGITS_MAX * 0.8 < 32767){ + g_nSensiblePressureDigits = EMERGENCY_PAUSE_DIGITS_MAX * 0.8; //maximalstellung, das ist aber schon irre hoch. abhängig von messdose und maximaltragkraft vs. genauigkeit der zelle. + }else{ + g_nSensiblePressureDigits = 32767; //die variable ist short, nie mehr rein als nötig ^^. + } + }else{ + //TPE braucht mini werte, wenn es sinnvoll sein soll. Darum der Ternary, sodass man per Knopf auch kleinste Zahlen justieren kann. + g_nSensiblePressureDigits += (g_nSensiblePressureDigits >= 2000) ? 250 : (g_nSensiblePressureDigits >= 500) ? 100 : 50 ; //decrement pro Knopfklick. Man kann ja auf der Taste bleiben. + //g_nSensiblePressureDigits += 250; //decrement pro Knopfklick. Man kann ja auf der Taste bleiben. + } + beep(1,4); + }else{ +#endif +#if UI_HAS_KEYS==1 + if( menu[menuLevel] == &ui_menu_xpos ) + { + Printer::moveMode[X_AXIS] ++; + if( Printer::moveMode[X_AXIS] > MOVE_MODE_50_MM ) + { + Printer::moveMode[X_AXIS] = MOVE_MODE_SINGLE_STEPS; + } + refreshPage(); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetByte(EPR_RF_MOVE_MODE_X,Printer::moveMode[X_AXIS]); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + } + else if( menu[menuLevel] == &ui_menu_ypos ) + { + Printer::moveMode[Y_AXIS] ++; + if( Printer::moveMode[Y_AXIS] > MOVE_MODE_50_MM ) + { + Printer::moveMode[Y_AXIS] = MOVE_MODE_SINGLE_STEPS; + } + refreshPage(); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetByte(EPR_RF_MOVE_MODE_Y,Printer::moveMode[Y_AXIS]); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + } + else if( menu[menuLevel] == &ui_menu_zpos ) + { + Printer::moveMode[Z_AXIS] ++; + if( Printer::moveMode[Z_AXIS] > MOVE_MODE_50_MM ) + { + Printer::moveMode[Z_AXIS] = MOVE_MODE_SINGLE_STEPS; + } + refreshPage(); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetByte(EPR_RF_MOVE_MODE_Z,Printer::moveMode[Z_AXIS]); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + } +#endif // UI_HAS_KEYS==1 +#if FEATURE_SENSIBLE_PRESSURE + } +#endif +} // rightAction + + +#define INCREMENT_MIN_MAX(a,steps,_min,_max) if ( (increment<0) && (_min>=0) && (a<_min-increment*steps) ) {a=_min;} else { a+=increment*steps; if(a<_min) a=_min; else if(a>_max) a=_max;}; +//increment ist ne variable, global. +#define INCREMENT_MAX(a,steps,_max) if ( (increment<0) && (a<=-1*increment*steps) ) {a=0;} else { a+=increment*steps; if(a>_max) a=_max;}; + +void UIDisplay::adjustMenuPos() +{ + if(menuLevel == 0) return; + UIMenu *men = (UIMenu*)menu[menuLevel]; + UIMenuEntry **entries = (UIMenuEntry**)pgm_read_word(&(men->entries)); + uint8_t mtype = HAL::readFlashByte((const prog_char*)&(men->menuType)); + if(mtype != 2) return; + + while(menuPos[menuLevel]>0) + { + if(((UIMenuEntry *)pgm_read_word(&(entries[menuPos[menuLevel]])))->showEntry()) + break; + + menuPos[menuLevel]--; + } + while(1) + { + if(((UIMenuEntry *)pgm_read_word(&(entries[menuPos[menuLevel]])))->showEntry()) + break; + + menuPos[menuLevel]++; + } + uint8_t skipped = 0; + bool modified; + + if(menuTop[menuLevel] > menuPos[menuLevel]) + menuTop[menuLevel] = menuPos[menuLevel]; + do + { + skipped = 0; + modified = false; + for(uint8_t r=menuTop[menuLevel]; rshowEntry()) + skipped++; + } + if(menuTop[menuLevel] + skipped + UI_ROWS - 1 < menuPos[menuLevel]) { + menuTop[menuLevel] = menuPos[menuLevel] + 1 - UI_ROWS; + modified = true; + } + + }while(modified); + +} // adjustMenuPos + + +void UIDisplay::nextPreviousAction(int8_t next) +{ + if(Printer::isUIErrorMessage()) + { + Printer::setUIErrorMessage(false); + return; + } + millis_t actTime = HAL::timeInMilliseconds(); + millis_t dtReal; + millis_t dt = dtReal = actTime-lastNextPrev; + lastNextPrev = actTime; + + if(dtSPEED_MIN_MILLIS) + { + dt = SPEED_MIN_MILLIS; + lastNextAccumul = 1; + } + float f = (float)(SPEED_MIN_MILLIS-dt)/(float)(SPEED_MIN_MILLIS-SPEED_MAX_MILLIS); + lastNextAccumul = 1.0f+(float)SPEED_MAGNIFICATION*f*f*f; + +#if UI_HAS_KEYS==1 + if(menuLevel==0) + { + char mode = OPERATING_MODE_PRINT; + + +#if FEATURE_MILLING_MODE + mode = Printer::operatingMode; +#endif // FEATURE_MILLING_MODE + + lastSwitch = HAL::timeInMilliseconds(); + if((UI_INVERT_MENU_DIRECTION && next<0) || (!UI_INVERT_MENU_DIRECTION && next>0)) + { + if ( mode == OPERATING_MODE_PRINT ) + { + menuPos[0]++; + if(menuPos[0]>=UI_NUM_PAGES) + menuPos[0]=0; + } + else if ( mode == OPERATING_MODE_MILL ) + { + menuPos[0]++; + if ( menuPos[0] == 2 ) + { + menuPos[0]++; + } + if(menuPos[0]>=UI_NUM_PAGES) + { + menuPos[0]=0; + } + } + } + else + { + if ( mode == OPERATING_MODE_PRINT ) + { + menuPos[0] = (menuPos[0]==0 ? UI_NUM_PAGES-1 : menuPos[0]-1); + } + else if ( mode == OPERATING_MODE_MILL ) + { + menuPos[0] = (menuPos[0]==0 ? UI_NUM_PAGES-1 : menuPos[0]-1); + if ( menuPos[0] == 2 ) + { + menuPos[0]--; + } + } + } + return; + } + + UIMenu *men = (UIMenu*)menu[menuLevel]; + short nr = pgm_read_word_near(&(men->numEntries)); + uint8_t mtype = HAL::readFlashByte((const prog_char*)&(men->menuType)); + UIMenuEntry **entries = (UIMenuEntry**)pgm_read_word(&(men->entries)); + UIMenuEntry *ent =(UIMenuEntry *)pgm_read_word(&(entries[menuPos[menuLevel]])); + UIMenuEntry *testEnt; + uint8_t entType = HAL::readFlashByte((const prog_char*)&(ent->menuType)); // 0 = Info, 1 = Headline, 2 = submenu ref, 3 = direct action command + (void)entType; //ignore unused error Nibbels + int action = pgm_read_word(&(ent->action)); + + if(mtype==2 && activeAction==0) // browse through menu items + { + if((UI_INVERT_MENU_DIRECTION && next < 0) || (!UI_INVERT_MENU_DIRECTION && next > 0)) + { + //up-to-bottom-Patch + uint8_t vorher = menuPos[menuLevel]; + if(menuPos[menuLevel] < nr-1) menuPos[menuLevel]++; + else menuPos[menuLevel] = 0; + //gehe maximal einmal im kreis, auch wenn keins der menüpunkte sauber konfiguriert ist ^^. + while(menuPos[menuLevel] != vorher) + { + testEnt = (UIMenuEntry *)pgm_read_word(&(entries[menuPos[menuLevel]])); + if(testEnt->showEntry()) break; + + if(menuPos[menuLevel] < nr-1) menuPos[menuLevel]++; + else menuPos[menuLevel] = 0; //0..nr-1; nr ist anzahl submenüpunkte + } + //alle untermenüpunkte sind entweder nicht vorhanden oder falsch oder unzulässig: also geh einfach zurück auf das was anfangs dastand. + testEnt = (UIMenuEntry *)pgm_read_word(&(entries[menuPos[menuLevel]])); + if(!testEnt->showEntry()) + { + // this new chosen menu item shall not be displayed - revert the so-far used menu item + menuPos[menuLevel] = vorher; + } + //up-to-bottom-Patch + } + else + { + //down-to-top-Patch + uint8_t vorher = menuPos[menuLevel]; + if(menuPos[menuLevel] > 0) menuPos[menuLevel]--; + else menuPos[menuLevel] = nr-1; //0..nr-1; nr ist anzahl submenüpunkte + //gehe maximal einmal im kreis, auch wenn keins der menüpunkte sauber konfiguriert ist ^^. + while(menuPos[menuLevel] != vorher) + { + testEnt = (UIMenuEntry *)pgm_read_word(&(entries[menuPos[menuLevel]])); + if(testEnt->showEntry()) break; + + if(menuPos[menuLevel] > 0) menuPos[menuLevel]--; + else menuPos[menuLevel] = nr-1; //0..nr-1; nr ist anzahl submenüpunkte + } + //alle untermenüpunkte sind entweder nicht vorhanden oder falsch oder unzulässig: also geh einfach zurück auf das was anfangs dastand. + testEnt = (UIMenuEntry *)pgm_read_word(&(entries[menuPos[menuLevel]])); + if(!testEnt->showEntry()) + { + // this new chosen menu item shall not be displayed - revert the so-far used menu item + menuPos[menuLevel] = vorher; + } + //down-to-top-Patch ende + } + adjustMenuPos(); + return; + } + +#if SDSUPPORT + if(mtype==1) // SD listing + { + if((UI_INVERT_MENU_DIRECTION && next<0) || (!UI_INVERT_MENU_DIRECTION && next>0)) + { + if(menuPos[menuLevel]0) + { + menuPos[menuLevel]--; + + if( Printer::debugInfo() ) + { + Com::printF( PSTR( "SD listing: " ), menuPos[menuLevel] ); + Com::printFLN( PSTR( " / " ), menuLevel ); + } + } + if(menuTop[menuLevel]>menuPos[menuLevel]) + menuTop[menuLevel]=menuPos[menuLevel]; + else if(menuTop[menuLevel]+UI_ROWS-1id)); + else action=activeAction; + +#if UI_INVERT_INCREMENT_DIRECTION + int8_t increment = -next; +#else + int8_t increment = next; +#endif // UI_INVERT_INCREMENT_DIRECTION + + switch(action) + { + case UI_ACTION_FANSPEED: + { + Commands::setFanSpeed(Printer::getFanSpeed()+increment*3,false); + break; + } + case UI_ACTION_XPOSITION: + { + /* + XYZ_POSITION_BUTTON_DIRECTION = -1 : This fits to you if you want more intuitivity when choosing the Up-Down-Buttons. + XYZ_POSITION_BUTTON_DIRECTION = 1 : This fits more if you stick to coordinates direction. + see configuration.h + */ + nextPreviousXAction( XYZ_POSITION_BUTTON_DIRECTION*increment ); + break; + } + case UI_ACTION_YPOSITION: + { + /* + XYZ_POSITION_BUTTON_DIRECTION = -1 : This fits to you if you want more intuitivity when choosing the Up-Down-Buttons. + XYZ_POSITION_BUTTON_DIRECTION = 1 : This fits more if you stick to coordinates direction. + see configuration.h + */ + nextPreviousYAction( XYZ_POSITION_BUTTON_DIRECTION*increment ); + break; + } + case UI_ACTION_ZPOSITION: + { + /* + XYZ_POSITION_BUTTON_DIRECTION = -1 : This fits to you if you want more intuitivity when choosing the Up-Down-Buttons. + XYZ_POSITION_BUTTON_DIRECTION = 1 : This fits more if you stick to coordinates direction. + see configuration.h + */ + nextPreviousZAction( XYZ_POSITION_BUTTON_DIRECTION*increment ); + break; + } + case UI_ACTION_ZOFFSET: + { + //INCREMENT_MIN_MAX(Printer::ZOffset,Z_OFFSET_STEP,-5000,5000); + INCREMENT_MIN_MAX(Printer::ZOffset,Z_OFFSET_STEP,-(HEAT_BED_Z_COMPENSATION_MAX_MM * 1000),(HEAT_BED_Z_COMPENSATION_MAX_MM * 1000)); + #if FEATURE_SENSIBLE_PRESSURE + g_staticZSteps = ((Printer::ZOffset+g_nSensiblePressureOffset) * Printer::axisStepsPerMM[Z_AXIS]) / 1000; + #else + g_staticZSteps = (Printer::ZOffset * Printer::axisStepsPerMM[Z_AXIS]) / 1000; + #endif +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetInt32( EPR_RF_Z_OFFSET, Printer::ZOffset ); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + break; + } + case UI_ACTION_XPOSITION_FAST: + { + PrintLine::moveRelativeDistanceInStepsReal(Printer::axisStepsPerMM[X_AXIS]*increment,0,0,0,Printer::homingFeedrate[X_AXIS],true); + Commands::printCurrentPosition(); + break; + } + case UI_ACTION_YPOSITION_FAST: + { + PrintLine::moveRelativeDistanceInStepsReal(0,Printer::axisStepsPerMM[Y_AXIS]*increment,0,0,Printer::homingFeedrate[Y_AXIS],true); + Commands::printCurrentPosition(); + break; + } + case UI_ACTION_ZPOSITION_FAST: + { + PrintLine::moveRelativeDistanceInStepsReal(0,0,Printer::axisStepsPerMM[Z_AXIS]*increment,0,Printer::homingFeedrate[Z_AXIS],true); + Commands::printCurrentPosition(); + break; + } + case UI_ACTION_EPOSITION: + { +#if EXTRUDER_ALLOW_COLD_MOVE + PrintLine::moveRelativeDistanceInSteps(0,0,0,Printer::axisStepsPerMM[E_AXIS]*increment,UI_SET_EXTRUDER_FEEDRATE,true,false); + Commands::printCurrentPosition(); +#else + if( Extruder::current->tempControl.targetTemperatureC > UI_SET_MIN_EXTRUDER_TEMP ) + { + PrintLine::moveRelativeDistanceInSteps(0,0,0,Printer::axisStepsPerMM[E_AXIS]*increment,UI_SET_EXTRUDER_FEEDRATE,true,false); + Commands::printCurrentPosition(); + } + else + { + showError( (void*)ui_text_extruder, (void*)ui_text_operation_denied ); + } +#endif // EXTRUDER_ALLOW_COLD_MOVE + break; + } + case UI_ACTION_ZPOSITION_NOTEST: + { + Printer::setNoDestinationCheck(true); + +#if UI_SPEEDDEPENDENT_POSITIONING + float d = 0.01*(float)increment*lastNextAccumul; + if(fabs(d)*2000>Printer::maxFeedrate[Z_AXIS]*dtReal) + d *= Printer::maxFeedrate[Z_AXIS]*dtReal/(2000*fabs(d)); + long steps = (long)(d*Printer::axisStepsPerMM[Z_AXIS]); + steps = ( increment<0 ? RMath::min(steps,(long)increment) : RMath::max(steps,(long)increment)); + PrintLine::moveRelativeDistanceInStepsReal(0,0,steps,0,Printer::maxFeedrate[Z_AXIS],true); +#else + PrintLine::moveRelativeDistanceInStepsReal(0,0,increment,0,Printer::homingFeedrate[Z_AXIS],true); +#endif // UI_SPEEDDEPENDENT_POSITIONING + + Commands::printCurrentPosition(); + Printer::setNoDestinationCheck(false); + break; + } + case UI_ACTION_ZPOSITION_FAST_NOTEST: + { + Printer::setNoDestinationCheck(true); + PrintLine::moveRelativeDistanceInStepsReal(0,0,Printer::axisStepsPerMM[Z_AXIS]*increment,0,Printer::homingFeedrate[Z_AXIS],true); + Commands::printCurrentPosition(); + Printer::setNoDestinationCheck(false); + break; + } + case UI_ACTION_HEATED_BED_TEMP: + { +#if HAVE_HEATED_BED==true + int tmp = (int)heatedBedController.targetTemperatureC; + if(tmpUI_SET_MAX_HEATED_BED_TEMP) tmp = UI_SET_MAX_HEATED_BED_TEMP; + Extruder::setHeatedBedTemperature(tmp); +#endif // HAVE_HEATED_BED + + break; + } + case UI_ACTION_EXTRUDER0_TEMP: + { + int tmp = (int)extruder[0].tempControl.targetTemperatureC; + if(tmpUI_SET_MAX_EXTRUDER_TEMP) tmp = UI_SET_MAX_EXTRUDER_TEMP; + Extruder::setTemperatureForExtruder(tmp,0); + break; + } + case UI_ACTION_EXTRUDER1_TEMP: + { +#if NUM_EXTRUDER>1 + int tmp = (int)extruder[1].tempControl.targetTemperatureC; + tmp+=increment; + if(tmp==1) tmp = UI_SET_MIN_EXTRUDER_TEMP; + if(tmpUI_SET_MAX_EXTRUDER_TEMP) tmp = UI_SET_MAX_EXTRUDER_TEMP; + Extruder::setTemperatureForExtruder(tmp,1); +#endif // NUM_EXTRUDER>1 + + break; + } + +#if NUM_EXTRUDER>1 + case UI_ACTION_EXTRUDER_OFFSET_X: + { + float fTemp = extruder[1].xOffset / Printer::axisStepsPerMM[X_AXIS]; + + + INCREMENT_MIN_MAX(fTemp,0.01,32,36); + extruder[1].xOffset = int32_t(fTemp * Printer::axisStepsPerMM[X_AXIS]); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EEPROM_EXTRUDER_LENGTH+EEPROM_EXTRUDER_OFFSET+EPR_EXTRUDER_X_OFFSET,fTemp); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_EXTRUDER_OFFSET_Y: + { + float fTemp = extruder[1].yOffset / Printer::axisStepsPerMM[Y_AXIS]; + + + INCREMENT_MIN_MAX(fTemp,0.01,-2,2); + extruder[1].yOffset = int32_t(fTemp * Printer::axisStepsPerMM[Y_AXIS]); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EEPROM_EXTRUDER_LENGTH+EEPROM_EXTRUDER_OFFSET+EPR_EXTRUDER_Y_OFFSET,fTemp); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } +#endif // NUM_EXTRUDER>1 + + case UI_ACTION_FEEDRATE_MULTIPLY: + { + int fr = Printer::feedrateMultiply; + INCREMENT_MIN_MAX(fr,1,25,500); + Commands::changeFeedrateMultiply(fr); + break; + } + case UI_ACTION_FLOWRATE_MULTIPLY: + { + int er = Printer::extrudeMultiply; + INCREMENT_MIN_MAX(er,1,25,200); + Commands::changeFlowateMultiply(er); + break; + } + case UI_ACTION_STEPPER_INACTIVE: + { + stepperInactiveTime -= stepperInactiveTime % 1000; + INCREMENT_MAX(stepperInactiveTime,60000UL,10080000UL); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetInt32(EPR_STEPPER_INACTIVE_TIME,stepperInactiveTime); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_MAX_INACTIVE: + { + maxInactiveTime -= maxInactiveTime % 1000; + INCREMENT_MAX(maxInactiveTime,60000UL,10080000UL); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetInt32(EPR_MAX_INACTIVE_TIME,maxInactiveTime); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_PRINT_ACCEL_X: + { + INCREMENT_MIN_MAX(Printer::maxAccelerationMMPerSquareSecond[X_AXIS],100,0,10000); + Printer::updateDerivedParameter(); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EPR_X_MAX_ACCEL,Printer::maxAccelerationMMPerSquareSecond[X_AXIS]); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_PRINT_ACCEL_Y: + { + INCREMENT_MIN_MAX(Printer::maxAccelerationMMPerSquareSecond[Y_AXIS],100,0,10000); + Printer::updateDerivedParameter(); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EPR_Y_MAX_ACCEL,Printer::maxAccelerationMMPerSquareSecond[Y_AXIS]); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_PRINT_ACCEL_Z: + { + INCREMENT_MIN_MAX(Printer::maxAccelerationMMPerSquareSecond[Z_AXIS],100,0,10000); + Printer::updateDerivedParameter(); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EPR_Z_MAX_ACCEL,Printer::maxAccelerationMMPerSquareSecond[Z_AXIS]); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_MOVE_ACCEL_X: + { + INCREMENT_MIN_MAX(Printer::maxTravelAccelerationMMPerSquareSecond[X_AXIS],100,0,10000); + Printer::updateDerivedParameter(); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EPR_X_MAX_TRAVEL_ACCEL,Printer::maxTravelAccelerationMMPerSquareSecond[X_AXIS]); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_MOVE_ACCEL_Y: + { + INCREMENT_MIN_MAX(Printer::maxTravelAccelerationMMPerSquareSecond[Y_AXIS],100,0,10000); + Printer::updateDerivedParameter(); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EPR_Y_MAX_TRAVEL_ACCEL,Printer::maxTravelAccelerationMMPerSquareSecond[Y_AXIS]); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_MOVE_ACCEL_Z: + { + INCREMENT_MIN_MAX(Printer::maxTravelAccelerationMMPerSquareSecond[Z_AXIS],100,0,10000); + Printer::updateDerivedParameter(); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EPR_Z_MAX_TRAVEL_ACCEL,Printer::maxTravelAccelerationMMPerSquareSecond[Z_AXIS]); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_MAX_JERK: + { + INCREMENT_MIN_MAX(Printer::maxJerk,0.1,1,99.9); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EPR_MAX_JERK,Printer::maxJerk); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_MAX_ZJERK: + { + INCREMENT_MIN_MAX(Printer::maxZJerk,0.1,0.1,99.9); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EPR_MAX_ZJERK,Printer::maxZJerk); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_HOMING_FEEDRATE_X: + { + INCREMENT_MIN_MAX(Printer::homingFeedrate[X_AXIS],1,5,1000); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE +#if FEATURE_MILLING_MODE + if( Printer::operatingMode == OPERATING_MODE_PRINT ) + { + HAL::eprSetFloat(EPR_X_HOMING_FEEDRATE_PRINT,Printer::homingFeedrate[X_AXIS]); + } + else + { + HAL::eprSetFloat(EPR_X_HOMING_FEEDRATE_MILL,Printer::homingFeedrate[X_AXIS]); + } +#else + HAL::eprSetFloat(EPR_X_HOMING_FEEDRATE_PRINT,Printer::homingFeedrate[X_AXIS]); +#endif // FEATURE_MILLING_MODE + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_HOMING_FEEDRATE_Y: + { + INCREMENT_MIN_MAX(Printer::homingFeedrate[Y_AXIS],1,5,1000); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE +#if FEATURE_MILLING_MODE + if( Printer::operatingMode == OPERATING_MODE_PRINT ) + { + HAL::eprSetFloat(EPR_Y_HOMING_FEEDRATE_PRINT,Printer::homingFeedrate[Y_AXIS]); + } + else + { + HAL::eprSetFloat(EPR_Y_HOMING_FEEDRATE_MILL,Printer::homingFeedrate[Y_AXIS]); + } +#else + HAL::eprSetFloat(EPR_Y_HOMING_FEEDRATE_PRINT,Printer::homingFeedrate[Y_AXIS]); +#endif // FEATURE_MILLING_MODE + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_HOMING_FEEDRATE_Z: + { + INCREMENT_MIN_MAX(Printer::homingFeedrate[Z_AXIS],1,1,1000); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE +#if FEATURE_MILLING_MODE + if( Printer::operatingMode == OPERATING_MODE_PRINT ) + { + HAL::eprSetFloat(EPR_Z_HOMING_FEEDRATE_PRINT,Printer::homingFeedrate[Z_AXIS]); + } + else + { + HAL::eprSetFloat(EPR_Z_HOMING_FEEDRATE_MILL,Printer::homingFeedrate[Z_AXIS]); + } +#else + HAL::eprSetFloat(EPR_Z_HOMING_FEEDRATE_PRINT,Printer::homingFeedrate[Z_AXIS]); +#endif // FEATURE_MILLING_MODE + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_MAX_FEEDRATE_X: + { + INCREMENT_MIN_MAX(Printer::maxFeedrate[X_AXIS],1,1,1000); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EPR_X_MAX_FEEDRATE,Printer::maxFeedrate[X_AXIS]); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_MAX_FEEDRATE_Y: + { + INCREMENT_MIN_MAX(Printer::maxFeedrate[Y_AXIS],1,1,1000); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EPR_Y_MAX_FEEDRATE,Printer::maxFeedrate[Y_AXIS]); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_MAX_FEEDRATE_Z: + { + INCREMENT_MIN_MAX(Printer::maxFeedrate[Z_AXIS],1,1,1000); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EPR_Z_MAX_FEEDRATE,Printer::maxFeedrate[Z_AXIS]); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_BAUDRATE: + { +#if EEPROM_MODE!=0 + unsigned char p=0; + int32_t rate; + do + { + rate = pgm_read_dword(&(baudrates[p])); + if(rate==baudrate) break; + p++; + + }while(rate!=0); + + if(rate==0 && p>=2) p-=2; + else if(rate==0 && p==1) p=0; + + if(p+increment >= 0) p+=increment; + else if(p+increment <= 0) p=0; + + //if(p<0) p = 0; + rate = pgm_read_dword(&(baudrates[p])); + if(rate==0 && p>=1) p--; + baudrate = pgm_read_dword(&(baudrates[p])); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetInt32(EPR_BAUDRATE,baudrate); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE +#endif // EEPROM_MODE!=0 + + break; + } + +#if FEATURE_RGB_LIGHT_EFFECTS + case UI_ACTION_RGB_LIGHT_MODE: + { + INCREMENT_MIN_MAX(Printer::RGBLightMode,1,0,3); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetByte( EPR_RF_RGB_LIGHT_MODE, Printer::RGBLightMode ); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + switch( Printer::RGBLightMode ) + { + case RGB_MODE_OFF: + { + Printer::RGBLightStatus = RGB_STATUS_NOT_AUTOMATIC; + Printer::RGBLightModeForceWhite = 0; + setRGBTargetColors( 0, 0, 0 ); + break; + } + case RGB_MODE_WHITE: + { + Printer::RGBLightStatus = RGB_STATUS_NOT_AUTOMATIC; + Printer::RGBLightModeForceWhite = 0; + setRGBTargetColors( 255, 255, 255 ); + break; + } + case RGB_MODE_AUTOMATIC: + { + // the firmware will determine the current RGB colors automatically + Printer::RGBLightStatus = RGB_STATUS_AUTOMATIC; + Printer::RGBLightModeForceWhite = 0; + break; + } + case RGB_MODE_MANUAL: + { + Printer::RGBLightStatus = RGB_STATUS_NOT_AUTOMATIC; + Printer::RGBLightModeForceWhite = 0; + setRGBTargetColors( g_uRGBManualR, g_uRGBManualG, g_uRGBManualB ); + break; + } + } + break; + } +#endif // FEATURE_RGB_LIGHT_EFFECTS + + case UI_ACTION_EXTR_STEPS: + { + INCREMENT_MIN_MAX(Extruder::current->stepsPerMM,1,1,9999); + Extruder::selectExtruderById(Extruder::current->id); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EEPROM::getExtruderOffset(Extruder::current->id)+EPR_EXTRUDER_STEPS_PER_MM,Extruder::current->stepsPerMM); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_EXTR_ACCELERATION: + { + INCREMENT_MIN_MAX(Extruder::current->maxAcceleration,10,10,99999); + Extruder::selectExtruderById(Extruder::current->id); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EEPROM::getExtruderOffset(Extruder::current->id)+EPR_EXTRUDER_MAX_ACCELERATION,Extruder::current->maxAcceleration); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_EXTR_MAX_FEEDRATE: + { + INCREMENT_MIN_MAX(Extruder::current->maxFeedrate,1,1,999); + Extruder::selectExtruderById(Extruder::current->id); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EEPROM::getExtruderOffset(Extruder::current->id)+EPR_EXTRUDER_MAX_FEEDRATE,Extruder::current->maxFeedrate); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_EXTR_START_FEEDRATE: + { + INCREMENT_MIN_MAX(Extruder::current->maxStartFeedrate,1,1,999); + Extruder::selectExtruderById(Extruder::current->id); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EEPROM::getExtruderOffset(Extruder::current->id)+EPR_EXTRUDER_MAX_START_FEEDRATE,Extruder::current->maxStartFeedrate); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_EXTR_HEATMANAGER: + { + INCREMENT_MIN_MAX(Extruder::current->tempControl.heatManager,1,0,3); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EEPROM::getExtruderOffset(Extruder::current->id)+EPR_EXTRUDER_HEAT_MANAGER,Extruder::current->tempControl.heatManager); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_EXTR_WATCH_PERIOD: + { + INCREMENT_MIN_MAX(Extruder::current->watchPeriod,1,0,999); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EEPROM::getExtruderOffset(Extruder::current->id)+EPR_EXTRUDER_WATCH_PERIOD,Extruder::current->watchPeriod); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + +#if RETRACT_DURING_HEATUP + case UI_ACTION_EXTR_WAIT_RETRACT_TEMP: + { + INCREMENT_MIN_MAX(Extruder::current->waitRetractTemperature,1,100,UI_SET_MAX_EXTRUDER_TEMP); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EEPROM::getExtruderOffset(Extruder::current->id)+EPR_EXTRUDER_WAIT_RETRACT_TEMP,Extruder::current->waitRetractTemperature); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } + case UI_ACTION_EXTR_WAIT_RETRACT_UNITS: + { + INCREMENT_MIN_MAX(Extruder::current->waitRetractUnits,1,0,99); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EEPROM::getExtruderOffset(Extruder::current->id)+EPR_EXTRUDER_WAIT_RETRACT_UNITS,Extruder::current->waitRetractUnits); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } +#endif // RETRACT_DURING_HEATUP + +#ifdef USE_ADVANCE +#ifdef ENABLE_QUADRATIC_ADVANCE + case UI_ACTION_ADVANCE_K: + { + INCREMENT_MIN_MAX(Extruder::current->advanceK,1,0,200); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EEPROM::getExtruderOffset(Extruder::current->id)+EPR_EXTRUDER_ADVANCE_K,Extruder::current->advanceK); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + break; + } +#endif // ENABLE_QUADRATIC_ADVANCE + + case UI_ACTION_ADVANCE_L: + { + INCREMENT_MIN_MAX(Extruder::current->advanceL,1,0,600); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetFloat(EEPROM::getExtruderOffset(Extruder::current->id)+EPR_EXTRUDER_ADVANCE_L,Extruder::current->advanceL); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } +#endif // USE_ADVANCE + +#if FEATURE_WORK_PART_Z_COMPENSATION + case UI_ACTION_RF_SET_Z_MATRIX_WORK_PART: + { + if( Printer::doWorkPartZCompensation ) + { + // do not allow to change the current work part z-compensation matrix while the z-compensation is active + showError( (void*)ui_text_z_compensation, (void*)ui_text_operation_denied ); + break; + } + + INCREMENT_MIN_MAX(g_nActiveWorkPart,1,1,EEPROM_MAX_WORK_PART_SECTORS); + switchActiveWorkPart(g_nActiveWorkPart); + break; + } + case UI_ACTION_RF_SET_SCAN_DELTA_X: + { + INCREMENT_MIN_MAX(g_nScanXStepSizeMm,1,WORK_PART_SCAN_X_STEP_SIZE_MIN_MM,100); + g_nScanXStepSizeSteps = (long)((float)g_nScanXStepSizeMm * Printer::axisStepsPerMM[X_AXIS]); + break; + } + case UI_ACTION_RF_SET_SCAN_DELTA_Y: + { + INCREMENT_MIN_MAX(g_nScanYStepSizeMm,1,WORK_PART_SCAN_Y_STEP_SIZE_MIN_MM,100); + g_nScanYStepSizeSteps = (long)((float)g_nScanYStepSizeMm * Printer::axisStepsPerMM[Y_AXIS]); + break; + } +#endif // FEATURE_WORK_PART_Z_COMPENSATION + +#if FEATURE_HEAT_BED_Z_COMPENSATION + case UI_ACTION_RF_SET_Z_MATRIX_HEAT_BED: + { + if( Printer::doHeatBedZCompensation ) + { + // do not allow to change the current heat bed z-compensation matrix while the z-compensation is active + showError( (void*)ui_text_z_compensation, (void*)ui_text_operation_denied ); + break; + } + + INCREMENT_MIN_MAX(g_nActiveHeatBed,1,1,EEPROM_MAX_HEAT_BED_SECTORS); + switchActiveHeatBed(g_nActiveHeatBed); + break; + } +#endif // FEATURE_HEAT_BED_Z_COMPENSATION + + case UI_ACTION_RF_RESET_ACK: + { + INCREMENT_MIN_MAX(g_nYesNo,1,0,1); + break; + } + case UI_ACTION_SD_STOP_ACK: + { + INCREMENT_MIN_MAX(g_nYesNo,1,0,1); + break; + } + } + +#if FEATURE_MILLING_MODE + if( Printer::operatingMode == OPERATING_MODE_PRINT ) + { +#if UI_PRINT_AUTORETURN_TO_MENU_AFTER!=0 + g_nAutoReturnTime=HAL::timeInMilliseconds()+UI_PRINT_AUTORETURN_TO_MENU_AFTER; +#endif // UI_PRINT_AUTORETURN_TO_MENU_AFTER!=0 + } + else + { +#if UI_MILL_AUTORETURN_TO_MENU_AFTER!=0 + g_nAutoReturnTime=HAL::timeInMilliseconds()+UI_MILL_AUTORETURN_TO_MENU_AFTER; +#endif // UI_MILL_AUTORETURN_TO_MENU_AFTER!=0 + } +#else +#if UI_PRINT_AUTORETURN_TO_MENU_AFTER!=0 + g_nAutoReturnTime=HAL::timeInMilliseconds()+UI_PRINT_AUTORETURN_TO_MENU_AFTER; +#endif // UI_PRINT_AUTORETURN_TO_MENU_AFTER!=0 +#endif // FEATURE_MILLING_MODE +#endif // UI_HAS_KEYS==1 + +} // nextPreviousAction + + +void UIDisplay::finishAction(int action) +{ + switch( action ) + { +#if FEATURE_RESET_VIA_MENU + case UI_ACTION_RF_RESET_ACK: + { + if( g_nYesNo != 1 ) + { + // continue only in case the user has chosen "Yes" + break; + } + + if( Printer::debugInfo() ) + { + Com::printFLN( PSTR( "processButton(): restart" ) ); + } + HAL::delayMilliseconds( 100 ); + Commands::emergencyStop(); + break; + } +#endif // FEATURE_RESET_VIA_MENU + + case UI_ACTION_SD_STOP_ACK: + { + if( g_nYesNo != 1 ) + { + // continue only in case the user has chosen "Yes" + break; + } + + sd.abortPrint(); + break; + } + } + +} // finishAction + + +// Actions are events from user input. Depending on the current state, each +// action can behave differently. Other actions do always the same like home, disable extruder etc. +void UIDisplay::executeAction(int action) +{ + if( Printer::blockAll ) + { + // do not allow any user inputs when we have been blocked + return; + } + +#if UI_HAS_KEYS==1 + bool skipBeep = false; + if(action & UI_ACTION_TOPMENU) // Go to start menu + { + action -= UI_ACTION_TOPMENU; + menuLevel = 0; + } +/* if(action>=2000 && action<3000) + { + setStatusP(ui_action); + } +*/ else if((action>=UI_ACTION_RF_MIN_REPEATABLE && action<=UI_ACTION_RF_MAX_REPEATABLE) || + (action>=UI_ACTION_RF_MIN_SINGLE && action<=UI_ACTION_RF_MAX_SINGLE)) + { + processButton( action ); + } + else + { + switch(action) + { + case UI_ACTION_OK: + { + okAction(); + skipBeep=true; // Prevent double beep + g_nYesNo = 0; + break; + } + case UI_ACTION_BACK: + { +#if FEATURE_SENSIBLE_PRESSURE + if( uid.menuLevel == 0 && uid.menuPos[0] == 1 ){ //wenn im Mod-Menü für Z-Offset/Matrix Sense-Offset/Limiter, dann anders! + //we are in the Mod menu + //verkleinern des Digit-Limits + if(g_nSensiblePressureDigits == 0){ + if(EMERGENCY_PAUSE_DIGITS_MAX * 0.8 < 32767){ + g_nSensiblePressureDigits = EMERGENCY_PAUSE_DIGITS_MAX * 0.8; //maximalstellung, das ist aber schon irre hoch. abhängig von messdose und maximaltragkraft vs. genauigkeit der zelle. + }else{ + g_nSensiblePressureDigits = 32767; //die variable ist short, nie mehr rein als nötig ^^. + } + }else if(g_nSensiblePressureDigits < 50){ // ex 250 + g_nSensiblePressureDigits = 0; + }else{ + //TPE braucht mini werte, wenn es sinnvoll sein soll. Darum der Ternary, sodass man per Knopf auch kleinste Zahlen justieren kann. + //g_nSensiblePressureDigits -= 250; //decrement pro Knopfklick. Man kann ja auf der Taste bleiben. + g_nSensiblePressureDigits -= (g_nSensiblePressureDigits >= 2000) ? 250 : (g_nSensiblePressureDigits >= 500) ? 100 : 50 ; //decrement pro Knopfklick. Man kann ja auf der Taste bleiben. + } + beep(1,4); + //skipBeep=true; + }else{ +#endif + +#if FEATURE_RGB_LIGHT_EFFECTS + if ( menuLevel == 0 ) + { + Printer::RGBButtonBackPressed = 1; + } +#endif // FEATURE_RGB_LIGHT_EFFECTS + if ( menuLevel == 1 && uid.menuPos[0] == 1 ){ + //der würde in das modmenü zurückgehen, da sind aber die rechtst links tasten anders belegt, daher nicht da rein! sonst evtl. verstellen von DigitLimit. + uid.menuPos[0] = 0; + } + if(menuLevel>0) menuLevel--; + Printer::setAutomount(false); + activeAction = 0; + g_nYesNo = 0; + +#if FEATURE_SENSIBLE_PRESSURE + } +#endif + break; + } + case UI_ACTION_NEXT: + { + nextPreviousAction(1); + break; + } + case UI_ACTION_RIGHT: + { + rightAction(); + break; + } + case UI_ACTION_PREVIOUS: + { + nextPreviousAction(-1); + break; + } + case UI_ACTION_MENU_UP: + { + if(menuLevel>0) menuLevel--; + break; + } + case UI_ACTION_TOP_MENU: + { + menuLevel = 0; + break; + } + case UI_ACTION_EMERGENCY_STOP: + { + Commands::emergencyStop(); + break; + } + case UI_ACTION_HOME_ALL: + { + if( PrintLine::linesCount ) + { + // do not allow homing via the menu while we are printing + if( Printer::debugErrors() ) + { + Com::printFLN( PSTR( "executeAction(): Home all is not available while the printing is in progress" ) ); + } + + showError( (void*)ui_text_home, (void*)ui_text_operation_denied ); + break; + } + if( !isHomingAllowed( NULL, 1 ) ) + { + break; + } + +#if FEATURE_CONFIGURABLE_Z_ENDSTOPS + if( Printer::ZEndstopUnknown ) + { + // in case the z-endstop is unknown, we home only in z-direction + Printer::homeAxis(false,false,true); + } + else + { + Printer::homeAxis(true,true,true); + } +#else + Printer::homeAxis(true,true,true); +#endif // FEATURE_CONFIGURABLE_Z_ENDSTOPS + + Commands::printCurrentPosition(); + break; + } + case UI_ACTION_HOME_X: + { + if( PrintLine::linesCount ) + { + // do not allow homing via the menu while we are printing + if( Printer::debugErrors() ) + { + Com::printFLN( PSTR( "executeAction(): Home X is not available while the printing is in progress" ) ); + } + + showError( (void*)ui_text_home, (void*)ui_text_operation_denied ); + break; + } + if( !isHomingAllowed( NULL, 1 ) ) + { + break; + } + + Printer::homeAxis(true,false,false); + Commands::printCurrentPosition(); + break; + } + case UI_ACTION_HOME_Y: + { + if( PrintLine::linesCount ) + { + // do not allow homing via the menu while we are printing + if( Printer::debugErrors() ) + { + Com::printFLN( PSTR( "executeAction(): Home Y is not available while the printing is in progress" ) ); + } + + showError( (void*)ui_text_home, (void*)ui_text_operation_denied ); + break; + } + if( !isHomingAllowed( NULL, 1 ) ) + { + break; + } + + Printer::homeAxis(false,true,false); + Commands::printCurrentPosition(); + break; + } + case UI_ACTION_HOME_Z: + { + if( PrintLine::linesCount ) + { + // do not allow homing via the menu while we are printing + if( Printer::debugErrors() ) + { + Com::printFLN( PSTR( "executeAction(): Home Z is not available while the printing is in progress" ) ); + } + + showError( (void*)ui_text_home, (void*)ui_text_operation_denied ); + break; + } + if( !isHomingAllowed( NULL, 1 ) ) + { + break; + } + + Printer::homeAxis(false,false,true); + Commands::printCurrentPosition(); + break; + } + case UI_ACTION_SET_XY_ORIGIN: + { + if( Printer::setOrigin(-Printer::queuePositionLastMM[X_AXIS],-Printer::queuePositionLastMM[Y_AXIS],Printer::originOffsetMM[Z_AXIS]) ) + { + BEEP_ACCEPT_SET_POSITION + } + break; + } + case UI_ACTION_DEBUG_ECHO: + { + if(Printer::debugEcho()) Printer::debugLevel-=1; + else Printer::debugLevel+=1; + break; + } + case UI_ACTION_DEBUG_INFO: + { + if(Printer::debugInfo()) Printer::debugLevel-=2; + else Printer::debugLevel+=2; + break; + } + case UI_ACTION_DEBUG_ERROR: + { + if(Printer::debugErrors()) Printer::debugLevel-=4; + else Printer::debugLevel+=4; + break; + } + case UI_ACTION_DEBUG_DRYRUN: + { + if(Printer::debugDryrun()) Printer::debugLevel-=8; + else Printer::debugLevel+=8; + if(Printer::debugDryrun()) // simulate movements without printing + { + Extruder::setTemperatureForExtruder(0,0); +#if NUM_EXTRUDER>1 + Extruder::setTemperatureForExtruder(0,1); +#endif // NUM_EXTRUDER>1 + +#if NUM_EXTRUDER>2 + Extruder::setTemperatureForExtruder(0,2); +#endif // NUM_EXTRUDER>2 + +#if HAVE_HEATED_BED==true + Extruder::setHeatedBedTemperature(0); +#endif // HAVE_HEATED_BED==true + } + break; + } + case UI_ACTION_POWER: + { +#if PS_ON_PIN>=0 // avoid compiler errors when the power supply pin is disabled + Commands::waitUntilEndOfAllMoves(); + SET_OUTPUT(PS_ON_PIN); //GND + TOGGLE(PS_ON_PIN); +#endif // PS_ON_PIN>=0 + + break; + } + +#if FEATURE_CASE_LIGHT + case UI_ACTION_LIGHTS_ONOFF: + { + if( Printer::enableCaseLight ) Printer::enableCaseLight = 0; + else Printer::enableCaseLight = 1; + WRITE(CASE_LIGHT_PIN, Printer::enableCaseLight); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetByte( EPR_RF_CASE_LIGHT_MODE, Printer::enableCaseLight ); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } +#endif // FEATURE_CASE_LIGHT + +#if FEATURE_230V_OUTPUT + case UI_ACTION_230V_OUTPUT: + { + if( Printer::enable230VOutput ) Printer::enable230VOutput = 0; + else Printer::enable230VOutput = 1; + WRITE(OUTPUT_230V_PIN, Printer::enable230VOutput); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + // after a power-on, the 230 V plug always shall be turned off - thus, we do not store this setting to the EEPROM + // HAL::eprSetByte( EPR_RF_230V_OUTPUT_MODE, Printer::enable230VOutput ); + // EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } +#endif // FEATURE_230V_OUTPUT + +#if FEATURE_24V_FET_OUTPUTS + case UI_ACTION_FET1_OUTPUT: + { + if( Printer::enableFET1 ) Printer::enableFET1 = 0; + else Printer::enableFET1 = 1; + WRITE(FET1, Printer::enableFET1); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetByte( EPR_RF_FET1_MODE , Printer::enableFET1 ); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + break; + } + + case UI_ACTION_FET2_OUTPUT: + { + if( Printer::enableFET2 ) Printer::enableFET2 = 0; + else Printer::enableFET2 = 1; + WRITE(FET2, Printer::enableFET2); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetByte( EPR_RF_FET2_MODE , Printer::enableFET2 ); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + break; + } +#endif // FEATURE_24V_FET_OUTPUTS + + +#if FEATURE_EXTENDED_BUTTONS + case UI_ACTION_CONFIG_SINGLE_STEPS: + { + configureMANUAL_STEPS_Z( 1 ); + } +#endif // FEATURE_EXTENDED_BUTTONS + +#if FEATURE_MILLING_MODE + case UI_ACTION_OPERATING_MODE: + { + char deny = 0; + + + if( PrintLine::linesCount ) deny = 1; // the operating mode can not be switched while the printing is in progress + +#if FEATURE_HEAT_BED_Z_COMPENSATION + if( g_nHeatBedScanStatus || g_ZOSScanStatus ) deny = 1; // the operating mode can not be switched while a heat bed scan / ZOS is in progress +#endif // FEATURE_HEAT_BED_Z_COMPENSATION + +#if FEATURE_WORK_PART_Z_COMPENSATION + if( g_nWorkPartScanStatus ) deny = 1; // the operating mode can not be switched while a work part scan is in progress +#endif // FEATURE_WORK_PART_Z_COMPENSATION + +#if FEATURE_FIND_Z_ORIGIN + if( g_nFindZOriginStatus ) deny = 1; // the operating mode can not be switched while the z-origin is searched +#endif // FEATURE_FIND_Z_ORIGIN + +#if FEATURE_TEST_STRAIN_GAUGE + if( g_nTestStrainGaugeStatus ) deny = 1; // the operating mode can not be switched while the strain gauge is tested +#endif // FEATURE_TEST_STRAIN_GAUGE + + if( deny ) + { + if( Printer::debugErrors() ) + { + Com::printFLN( PSTR( "executeAction(): The operating mode can not be switched while the printing is in progress" ) ); + } + + showError( (void*)ui_text_change_mode, (void*)ui_text_operation_denied ); + break; + } + + // disable and turn off everything before we switch the operating mode + Printer::kill( false ); + + if( Printer::operatingMode == OPERATING_MODE_PRINT ) + { + switchOperatingMode( OPERATING_MODE_MILL ); + } + else + { + switchOperatingMode( OPERATING_MODE_PRINT ); + } + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetByte( EPR_RF_OPERATING_MODE, Printer::operatingMode ); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + break; + } +#endif // FEATURE_MILLING_MODE + +#if FEATURE_CONFIGURABLE_Z_ENDSTOPS + case UI_ACTION_Z_ENDSTOP_TYPE: + { + if( PrintLine::linesCount ) + { + // the z-endstop type can not be switched while the printing is in progress + if( Printer::debugErrors() ) + { + Com::printFLN( PSTR( "executeAction(): The z-endstop type can not be switched while the printing is in progress" ) ); + } + + showError( (void*)ui_text_change_z_type, (void*)ui_text_operation_denied ); + break; + } + + Printer::lastZDirection = 0; + Printer::endstopZMinHit = ENDSTOP_NOT_HIT; + Printer::endstopZMaxHit = ENDSTOP_NOT_HIT; + + if( Printer::ZEndstopType == ENDSTOP_TYPE_SINGLE ) + { + Printer::ZEndstopType = ENDSTOP_TYPE_CIRCUIT; + + if( Printer::isZMinEndstopHit() || Printer::isZMaxEndstopHit() ) + { + // a z-endstop is active at the moment, but both z-endstops are within one circuit so we do not know which one is the pressed one + // in this situation we do not allow any moving into z-direction before a z-homing has been performed + Printer::ZEndstopUnknown = 1; + } + } + else + { + Printer::ZEndstopType = ENDSTOP_TYPE_SINGLE; + Printer::ZEndstopUnknown = 0; + } + + // update our information about the currently active Z-endstop + Printer::isZMinEndstopHit(); + Printer::isZMaxEndstopHit(); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetByte( EPR_RF_Z_ENDSTOP_TYPE, Printer::ZEndstopType ); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + break; + } +#endif // FEATURE_CONFIGURABLE_Z_ENDSTOPS + + case UI_ACTION_ZMODE: + { + if( Printer::ZMode == 1 ) Printer::ZMode = 2; + else Printer::ZMode = 1; +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetByte( EPR_RF_Z_MODE, Printer::ZMode ); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + break; + } + +#if FEATURE_CONFIGURABLE_HOTEND_TYPE + case UI_ACTION_HOTEND_TYPE: + { + Extruder *e; + + + if( PrintLine::linesCount ) + { + // the hotend type can not be switched while the printing is in progress + if( Printer::debugErrors() ) + { + Com::printFLN( PSTR( "executeAction(): The hotend type can not be switched while the printing is in progress" ) ); + } + + showError( (void*)ui_text_change_hotend_type, (void*)ui_text_operation_denied ); + break; + } + + if( Printer::HotendType == HOTEND_TYPE_V1 ) + { +#if MOTHERBOARD == DEVICE_TYPE_RF1000 + Printer::HotendType = HOTEND_TYPE_V2_SINGLE; +#endif // #if MOTHERBOARD == DEVICE_TYPE_RF1000 + +#if MOTHERBOARD == DEVICE_TYPE_RF2000 + Printer::HotendType = HOTEND_TYPE_V2_DUAL; +#endif // #if MOTHERBOARD == DEVICE_TYPE_RF2000 + +#ifdef TEMP_PID +#if NUM_EXTRUDER>0 + e = &extruder[0]; + + e->tempControl.pidDriveMax = HT3_PID_INTEGRAL_DRIVE_MAX; + e->tempControl.pidDriveMin = HT3_PID_INTEGRAL_DRIVE_MIN; + e->tempControl.pidPGain = HT3_PID_P; + e->tempControl.pidIGain = HT3_PID_I; + e->tempControl.pidDGain = HT3_PID_D; + e->tempControl.pidMax = EXT0_PID_MAX; +#endif // #if NUM_EXTRUDER>0 + +#if NUM_EXTRUDER>1 + e = &extruder[1]; + + e->tempControl.pidDriveMax = HT3_PID_INTEGRAL_DRIVE_MAX; + e->tempControl.pidDriveMin = HT3_PID_INTEGRAL_DRIVE_MIN; + e->tempControl.pidPGain = HT3_PID_P; + e->tempControl.pidIGain = HT3_PID_I; + e->tempControl.pidDGain = HT3_PID_D; + e->tempControl.pidMax = EXT0_PID_MAX; +#endif // #if NUM_EXTRUDER>1 +#endif // TEMP_PID + } + else + { + Printer::HotendType = HOTEND_TYPE_V1; + +#ifdef TEMP_PID +#if NUM_EXTRUDER>0 + e = &extruder[0]; + + e->tempControl.pidDriveMax = HT2_PID_INTEGRAL_DRIVE_MAX; + e->tempControl.pidDriveMin = HT2_PID_INTEGRAL_DRIVE_MIN; + e->tempControl.pidPGain = HT2_PID_P; + e->tempControl.pidIGain = HT2_PID_I; + e->tempControl.pidDGain = HT2_PID_D; + e->tempControl.pidMax = EXT0_PID_MAX; +#endif // NUM_EXTRUDER>0 + +#if NUM_EXTRUDER>1 + e = &extruder[1]; + + e->tempControl.pidDriveMax = HT2_PID_INTEGRAL_DRIVE_MAX; + e->tempControl.pidDriveMin = HT2_PID_INTEGRAL_DRIVE_MIN; + e->tempControl.pidPGain = HT2_PID_P; + e->tempControl.pidIGain = HT2_PID_I; + e->tempControl.pidDGain = HT2_PID_D; + e->tempControl.pidMax = EXT0_PID_MAX; +#endif // NUM_EXTRUDER>1 +#endif // TEMP_PID + } + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetByte( EPR_RF_HOTEND_TYPE, Printer::HotendType ); + +#ifdef TEMP_PID + for(uint8_t i=0; itempControl.pidDriveMax ); + HAL::eprSetByte( o+EPR_EXTRUDER_DRIVE_MIN, e->tempControl.pidDriveMin ); + HAL::eprSetFloat( o+EPR_EXTRUDER_PID_PGAIN, e->tempControl.pidPGain ); + HAL::eprSetFloat( o+EPR_EXTRUDER_PID_IGAIN, e->tempControl.pidIGain ); + HAL::eprSetFloat( o+EPR_EXTRUDER_PID_DGAIN, e->tempControl.pidDGain ); + HAL::eprSetByte( o+EPR_EXTRUDER_PID_MAX, e->tempControl.pidMax ); + } +#endif // TEMP_PID + + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + break; + } +#endif // FEATURE_CONFIGURABLE_HOTEND_TYPE + +#if FEATURE_CONFIGURABLE_MILLER_TYPE + case UI_ACTION_MILLER_TYPE: + { + if( PrintLine::linesCount ) + { + // the hotend type can not be switched while the printing is in progress + if( Printer::debugErrors() ) + { + Com::printFLN( PSTR( "executeAction(): The miller type can not be switched while the milling is in progress" ) ); + } + + showError( (void*)ui_text_change_miller_type, (void*)ui_text_operation_denied ); + break; + } + + if( Printer::MillerType == MILLER_TYPE_ONE_TRACK ) + { + Printer::MillerType = MILLER_TYPE_TWO_TRACKS; + g_nScanContactPressureDelta = MT2_WORK_PART_SCAN_CONTACT_PRESSURE_DELTA; + g_nScanRetryPressureDelta = MT2_WORK_PART_SCAN_RETRY_PRESSURE_DELTA; + } + else + { + Printer::MillerType = MILLER_TYPE_ONE_TRACK; + g_nScanContactPressureDelta = MT1_WORK_PART_SCAN_CONTACT_PRESSURE_DELTA; + g_nScanRetryPressureDelta = MT1_WORK_PART_SCAN_RETRY_PRESSURE_DELTA; + } + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetByte( EPR_RF_MILLER_TYPE, Printer::MillerType ); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + break; + } +#endif // FEATURE_CONFIGURABLE_MILLER_TYPE + + case UI_ACTION_PREHEAT_PLA: + { + UI_STATUS_UPD( UI_TEXT_PREHEAT_PLA ); + Extruder::setTemperatureForExtruder(UI_SET_PRESET_EXTRUDER_TEMP_PLA,0); + +#if NUM_EXTRUDER>1 + Extruder::setTemperatureForExtruder(UI_SET_PRESET_EXTRUDER_TEMP_PLA,1); +#endif // NUM_EXTRUDER>1 + +#if NUM_EXTRUDER>2 + Extruder::setTemperatureForExtruder(UI_SET_PRESET_EXTRUDER_TEMP_PLA,2); +#endif // NUM_EXTRUDER>2 + +#if HAVE_HEATED_BED==true + Extruder::setHeatedBedTemperature(UI_SET_PRESET_HEATED_BED_TEMP_PLA); +#endif // HAVE_HEATED_BED==true + + break; + } + case UI_ACTION_PREHEAT_ABS: + { + UI_STATUS_UPD( UI_TEXT_PREHEAT_ABS ); + Extruder::setTemperatureForExtruder(UI_SET_PRESET_EXTRUDER_TEMP_ABS,0); + +#if NUM_EXTRUDER>1 + Extruder::setTemperatureForExtruder(UI_SET_PRESET_EXTRUDER_TEMP_ABS,1); +#endif // NUM_EXTRUDER>1 + +#if NUM_EXTRUDER>2 + Extruder::setTemperatureForExtruder(UI_SET_PRESET_EXTRUDER_TEMP_ABS,2); +#endif // NUM_EXTRUDER>2 + +#if HAVE_HEATED_BED==true + Extruder::setHeatedBedTemperature(UI_SET_PRESET_HEATED_BED_TEMP_ABS); +#endif // HAVE_HEATED_BED==true + + break; + } + case UI_ACTION_COOLDOWN: + { + UI_STATUS_UPD( UI_TEXT_COOLDOWN ); + Extruder::setTemperatureForExtruder(0,0); + +#if NUM_EXTRUDER>1 + Extruder::setTemperatureForExtruder(0,1); +#endif // NUM_EXTRUDER>1 + +#if NUM_EXTRUDER>2 + Extruder::setTemperatureForExtruder(0,2); +#endif // NUM_EXTRUDER>2 + +#if HAVE_HEATED_BED==true + Extruder::setHeatedBedTemperature(0); +#endif // HAVE_HEATED_BED==true + + break; + } + case UI_ACTION_HEATED_BED_OFF: + { +#if HAVE_HEATED_BED==true + Extruder::setHeatedBedTemperature(0); +#endif // HAVE_HEATED_BED==true + + break; + } + case UI_ACTION_EXTRUDER0_OFF: + { + Extruder::setTemperatureForExtruder(0,0); + break; + } + case UI_ACTION_EXTRUDER1_OFF: + { +#if NUM_EXTRUDER>1 + Extruder::setTemperatureForExtruder(0,1); +#endif // NUM_EXTRUDER>1 + + break; + } + case UI_ACTION_EXTRUDER2_OFF: + { +#if NUM_EXTRUDER>2 + Extruder::setTemperatureForExtruder(0,2); +#endif // NUM_EXTRUDER>2 + + break; + } + case UI_ACTION_DISABLE_STEPPER: + { + Printer::kill( true ); + break; + } + case UI_ACTION_UNMOUNT_FILAMENT: + { + if( Extruder::current->tempControl.targetTemperatureC == 0 ) + { + char unlock = !uid.locked; + + + uid.executeAction(UI_ACTION_TOP_MENU); + UI_STATUS_UPD( UI_TEXT_UNMOUNT_FILAMENT ); + uid.lock(); + + GCode::executeFString(Com::tUnmountFilamentWithHeating); + + if( unlock ) + { + uid.unlock(); + } + g_uStartOfIdle = HAL::timeInMilliseconds(); + } + else + { +#if !EXTRUDER_ALLOW_COLD_MOVE + if( Extruder::current->tempControl.currentTemperatureC < UI_SET_EXTRUDER_TEMP_UNMOUNT ) + { + // we do not allow to move the extruder in case it is not heated up enough + if( Printer::debugErrors() ) + { + Com::printFLN( PSTR( "Unload Filament: extruder output: aborted" ) ); + } + + showError( (void*)ui_text_extruder, (void*)ui_text_operation_denied ); + break; + } +#endif // !EXTRUDER_ALLOW_COLD_MOVE + + char unlock = !uid.locked; + + + uid.executeAction(UI_ACTION_TOP_MENU); + UI_STATUS_UPD( UI_TEXT_UNMOUNT_FILAMENT ); + uid.lock(); + + GCode::executeFString(Com::tUnmountFilamentWithoutHeating); + + if( unlock ) + { + uid.unlock(); + } + g_uStartOfIdle = HAL::timeInMilliseconds(); + } + break; + } + case UI_ACTION_MOUNT_FILAMENT: + { + if( Extruder::current->tempControl.targetTemperatureC == 0 ) + { + char unlock = !uid.locked; + + + uid.executeAction(UI_ACTION_TOP_MENU); + UI_STATUS_UPD( UI_TEXT_MOUNT_FILAMENT ); + uid.lock(); + + GCode::executeFString(Com::tMountFilamentWithHeating); + + if( unlock ) + { + uid.unlock(); + } + g_uStartOfIdle = HAL::timeInMilliseconds(); + } + else + { +#if !EXTRUDER_ALLOW_COLD_MOVE + if( Extruder::current->tempControl.currentTemperatureC < UI_SET_MIN_EXTRUDER_TEMP ) + { + // we do not allow to move the extruder in case it is not heated up enough + if( Printer::debugErrors() ) + { + Com::printFLN( PSTR( "Load Filament: aborted" ) ); + } + + showError( (void*)ui_text_extruder, (void*)ui_text_operation_denied ); + break; + } +#endif // !EXTRUDER_ALLOW_COLD_MOVE + + char unlock = !uid.locked; + + + uid.executeAction(UI_ACTION_TOP_MENU); + UI_STATUS_UPD( UI_TEXT_MOUNT_FILAMENT ); + uid.lock(); + + GCode::executeFString(Com::tMountFilamentWithoutHeating); + + if( unlock ) + { + uid.unlock(); + } + g_uStartOfIdle = HAL::timeInMilliseconds(); + } + break; + } + case UI_ACTION_SET_E_ORIGIN: + { + Printer::queuePositionLastSteps[E_AXIS] = 0; + break; + } + case UI_ACTION_EXTRUDER_RELATIVE: + { + Printer::relativeExtruderCoordinateMode=!Printer::relativeExtruderCoordinateMode; + break; + } + case UI_ACTION_SELECT_EXTRUDER0: + { + Extruder::selectExtruderById(0); + break; + } + case UI_ACTION_SELECT_EXTRUDER1: + { +#if NUM_EXTRUDER>1 + Extruder::selectExtruderById(1); +#endif // NUM_EXTRUDER>1 + + break; + } + case UI_ACTION_SELECT_EXTRUDER2: + { +#if NUM_EXTRUDER>2 + Extruder::selectExtruderById(2); +#endif // NUM_EXTRUDER>2 + + break; + } + +#if NUM_EXTRUDER == 2 + case UI_ACTION_ACTIVE_EXTRUDER: + { + if( Extruder::current->id == 0 ) Extruder::selectExtruderById( 1 ); + else Extruder::selectExtruderById( 0 ); + break; + } +#endif // NUM_EXTRUDER == 2 + +#if SDSUPPORT + case UI_ACTION_SD_DELETE: + { + if(sd.sdactive) + { + pushMenu((void*)&ui_menu_sd_fileselector,false); + } + else + { + UI_ERROR(UI_TEXT_NOSDCARD); + } + break; + } + +#if FEATURE_RIGHT_BUTTON_MENU + case UI_ACTION_RIGHT: // fall through +#endif // FEATURE_RIGHT_BUTTON_MENU + case UI_ACTION_SD_PRINT: + { + if(sd.sdactive) + { + pushMenu((void*)&ui_menu_sd_fileselector,false); + } + break; + } + case UI_ACTION_SD_PAUSE: + { + pausePrint(); + break; + } + case UI_ACTION_SD_CONTINUE: + { + continuePrint(); + break; + } + +#if FEATURE_BEEPER + case UI_ACTION_BEEPER: + { + if( Printer::enableBeeper ) Printer::enableBeeper = 0; + else Printer::enableBeeper = 1; + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + HAL::eprSetByte( EPR_RF_BEEPER_MODE, Printer::enableBeeper ); + EEPROM::updateChecksum(); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + break; + } +#endif // FEATURE_BEEPER + + case UI_ACTION_SD_UNMOUNT: + { + sd.unmount(); + break; + } + case UI_ACTION_SD_MOUNT: + { + sd.mount(); + break; + } + case UI_ACTION_MENU_SDCARD: + { + pushMenu((void*)&ui_menu_sd,false); + break; + } +#endif // SDSUPPORT + +#if FAN_PIN>-1 + case UI_ACTION_FAN_OFF: + { + Commands::setFanSpeed(0,false); + break; + } + case UI_ACTION_FAN_25: + { + Commands::setFanSpeed(64,false); + break; + } + case UI_ACTION_FAN_50: + { + Commands::setFanSpeed(128,false); + break; + } + case UI_ACTION_FAN_75: + { + Commands::setFanSpeed(192,false); + break; + } + case UI_ACTION_FAN_FULL: + { + Commands::setFanSpeed(255,false); + break; + } +#endif // FAN_PIN>-1 + + case UI_ACTION_MENU_XPOS: + { + pushMenu((void*)&ui_menu_xpos,false); + break; + } + case UI_ACTION_MENU_YPOS: + { + pushMenu((void*)&ui_menu_ypos,false); + break; + } + case UI_ACTION_MENU_ZPOS: + { + pushMenu((void*)&ui_menu_zpos,false); + break; + } + case UI_ACTION_MENU_XPOSFAST: + { + pushMenu((void*)&ui_menu_xpos_fast,false); + break; + } + case UI_ACTION_MENU_YPOSFAST: + { + pushMenu((void*)&ui_menu_ypos_fast,false); + break; + } + case UI_ACTION_MENU_ZPOSFAST: + { + pushMenu((void*)&ui_menu_zpos_fast,false); + break; + } + case UI_ACTION_MENU_QUICKSETTINGS: + { + pushMenu((void*)&ui_menu_quick,false); + break; + } + case UI_ACTION_MENU_EXTRUDER: + { + pushMenu((void*)&ui_menu_extruder,false); + break; + } + case UI_ACTION_MENU_POSITIONS: + { + pushMenu((void*)&ui_menu_positions,false); + break; + } + +#ifdef UI_USERMENU1 + case UI_ACTION_SHOW_USERMENU1: + { + pushMenu((void*)&UI_USERMENU1,false); + break; + } +#endif // UI_USERMENU1 + +#ifdef UI_USERMENU2 + case UI_ACTION_SHOW_USERMENU2: + { + pushMenu((void*)&UI_USERMENU2,false); + break; + } +#endif // UI_USERMENU2 + +#ifdef UI_USERMENU3 + case UI_ACTION_SHOW_USERMENU3: + { + pushMenu((void*)&UI_USERMENU3,false); + break; + } +#endif // UI_USERMENU3 + +#ifdef UI_USERMENU4 + case UI_ACTION_SHOW_USERMENU4: + { + pushMenu((void*)&UI_USERMENU4,false); + break; + } +#endif // UI_USERMENU4 + +#ifdef UI_USERMENU5 + case UI_ACTION_SHOW_USERMENU5: + { + pushMenu((void*)&UI_USERMENU5,false); + break; + } +#endif // UI_USERMENU5 + +#ifdef UI_USERMENU6 + case UI_ACTION_SHOW_USERMENU6: + { + pushMenu((void*)&UI_USERMENU6,false); + break; + } +#endif // UI_USERMENU6 + +#ifdef UI_USERMENU7 + case UI_ACTION_SHOW_USERMENU7: + { + pushMenu((void*)&UI_USERMENU7,false); + break; + } +#endif // UI_USERMENU7 + +#ifdef UI_USERMENU8 + case UI_ACTION_SHOW_USERMENU8: + { + pushMenu((void*)&UI_USERMENU8,false); + break; + } +#endif // UI_USERMENU8 + +#ifdef UI_USERMENU9 + case UI_ACTION_SHOW_USERMENU9: + { + pushMenu((void*)&UI_USERMENU9,false); + break; + } +#endif // UI_USERMENU9 + +#ifdef UI_USERMENU10 + case UI_ACTION_SHOW_USERMENU10: + { + pushMenu((void*)&UI_USERMENU10,false); + break; + } +#endif // UI_USERMENU10 + +#if MAX_HARDWARE_ENDSTOP_Z + case UI_ACTION_SET_Z_ORIGIN: + { + setZOrigin(); + break; + } +#endif // MAX_HARDWARE_ENDSTOP_Z + + case UI_ACTION_RESTORE_DEFAULTS: + { + EEPROM::restoreEEPROMSettingsFromConfiguration(); + +#if FEATURE_AUTOMATIC_EEPROM_UPDATE + EEPROM::storeDataIntoEEPROM(false); +#endif // FEATURE_AUTOMATIC_EEPROM_UPDATE + + EEPROM::initializeAllOperatingModes(); + break; + } + +#ifdef DEBUG_PRINT + case UI_ACTION_WRITE_DEBUG: + { + Com::printF(PSTR("Buf. Read Idx:"),(int)GCode::bufferReadIndex); + Com::printF(PSTR(" Buf. Write Idx:"),(int)GCode::bufferWriteIndex); + Com::printF(PSTR(" Comment:"),(int)GCode::commentDetected); + Com::printF(PSTR(" Buf. Len:"),(int)GCode::bufferLength); + Com::printF(PSTR(" Wait resend:"),(int)GCode::waitingForResend); + Com::printFLN(PSTR(" Recv. Write Pos:"),(int)GCode::commandsReceivingWritePosition); + Com::printF(PSTR("Min. XY Speed:"),Printer::minimumSpeed); + Com::printF(PSTR(" Min. Z Speed:"),Printer::minimumZSpeed); + Com::printF(PSTR(" Buffer:"),PrintLine::linesCount); + Com::printF(PSTR(" Lines pos:"),(int)PrintLine::linesPos); + Com::printFLN(PSTR(" Write Pos:"),(int)PrintLine::linesWritePos); + Com::printFLN(PSTR("Wait loop:"),debugWaitLoop); + Com::printF(PSTR("sd mode:"),(int)sd.sdmode); + Com::printF(PSTR(" pos:"),sd.sdpos); + Com::printFLN(PSTR(" of "),sd.filesize); + break; + } +#endif // DEBUG_PRINT + +#if FEATURE_HEAT_BED_Z_COMPENSATION + case UI_ACTION_RF_DO_MHIER_BED_SCAN: + { + //macht an, wenn an, macht aus: + startZOScan(); + //gehe zurück und zeige dem User was passiert. + uid.menuLevel = 0; + uid.menuPos[0] = 0; + //wartet nur wenn an: + //Commands::waitUntilEndOfZOS(); -> Nein, weil der Nutzer das aktiv steuern und abbrechen können soll. Ist ja hier kein M-code in Reihe. + break; + } + case UI_ACTION_RF_DO_SAVE_ACTIVE_ZMATRIX: + { + // save the determined values to the EEPROM + if(g_ZMatrixChangedInRam){ + uid.executeAction(UI_ACTION_TOP_MENU); + saveCompensationMatrix( (unsigned int)(EEPROM_SECTOR_SIZE * g_nActiveHeatBed) ); + if( Printer::debugInfo() ) + { + Com::printFLN( PSTR( "Manual Input: the heat bed compensation matrix has been saved" ) ); + } + showInformation( (void*)ui_text_manual, (void*)ui_text_saving_success ); + }else{ + showInformation( (void*)ui_text_manual, (void*)ui_text_saving_needless ); + } + } +#endif // FEATURE_HEAT_BED_Z_COMPENSATION + } + } + + refreshPage(); + if(!skipBeep) + BEEP_SHORT + +#if FEATURE_MILLING_MODE + if( Printer::operatingMode == OPERATING_MODE_PRINT ) + { +#if UI_PRINT_AUTORETURN_TO_MENU_AFTER!=0 + g_nAutoReturnTime=HAL::timeInMilliseconds()+UI_PRINT_AUTORETURN_TO_MENU_AFTER; +#endif // UI_PRINT_AUTORETURN_TO_MENU_AFTER!=0 + } + else + { +#if UI_MILL_AUTORETURN_TO_MENU_AFTER!=0 + g_nAutoReturnTime=HAL::timeInMilliseconds()+UI_MILL_AUTORETURN_TO_MENU_AFTER; +#endif // UI_MILL_AUTORETURN_TO_MENU_AFTER!=0 + } +#else +#if UI_PRINT_AUTORETURN_TO_MENU_AFTER!=0 + g_nAutoReturnTime=HAL::timeInMilliseconds()+UI_PRINT_AUTORETURN_TO_MENU_AFTER; +#endif // UI_PRINT_AUTORETURN_TO_MENU_AFTER!=0 +#endif // FEATURE_MILLING_MODE +#endif // UI_HAS_KEYS==1 + +} // executeAction + + +void UIDisplay::mediumAction() +{ +#if UI_HAS_I2C_ENCODER>0 + ui_check_slow_encoder(); +#endif // UI_HAS_I2C_ENCODER>0 + +} // mediumAction + + +void UIDisplay::slowAction() +{ + unsigned long time = HAL::timeInMilliseconds(); + uint8_t refresh = 0; + + +#if UI_HAS_KEYS==1 + // Update key buffer + HAL::forbidInterrupts(); + if((flags & 9)==0) + { + flags|=UI_FLAG_KEY_TEST_RUNNING; + HAL::allowInterrupts(); + + int nextAction = 0; + ui_check_slow_keys(nextAction); //Nibbels: Das macht garnix. + if(lastButtonAction!=nextAction) + { + lastButtonStart = time; + lastButtonAction = nextAction; + HAL::forbidInterrupts(); + flags|=UI_FLAG_SLOW_KEY_ACTION; + } + HAL::forbidInterrupts(); + flags-=UI_FLAG_KEY_TEST_RUNNING; + } + HAL::forbidInterrupts(); + + if((flags & UI_FLAG_SLOW_ACTION_RUNNING)==0) + { + flags |= UI_FLAG_SLOW_ACTION_RUNNING; + + // Reset click encoder + HAL::forbidInterrupts(); + int8_t epos = encoderPos; + encoderPos=0; + HAL::allowInterrupts(); + if(epos) + { + nextPreviousAction(epos); //Nibbels: Funktion, die rechts links auswertet oder Errors wegklicken lässt. abhängig von this->encoderPos .. sonst verwendet mit -1 oder 1 + BEEP_SHORT + refresh=1; + } + if(lastAction!=lastButtonAction) + { + if(lastButtonAction==0) + { +/* if(lastAction>=2000 && lastAction<3000) + { + statusMsg[0] = 0; + } +*/ + lastAction = 0; + HAL::forbidInterrupts(); + flags &= ~3; + } + else if(time-lastButtonStart>UI_KEY_BOUNCETIME) // New key pressed + { + lastAction = lastButtonAction; + executeAction(lastAction); + nextRepeat = time+UI_KEY_FIRST_REPEAT; + repeatDuration = UI_KEY_FIRST_REPEAT; + } + } + else if(lastAction<1000 && lastAction) // Repeatable key + { + if(time-nextRepeat<10000) + { + executeAction(lastAction); + repeatDuration -= UI_KEY_REDUCE_REPEAT; + if(repeatDuration0 && g_nAutoReturnTime && g_nAutoReturnTime4000) + { + if(time-lastSwitch>UI_PAGES_DURATION) + { + lastSwitch = time; + +#if !defined(UI_DISABLE_AUTO_PAGESWITCH) || !UI_DISABLE_AUTO_PAGESWITCH + menuPos[0]++; + if(menuPos[0]>=UI_NUM_PAGES) + menuPos[0]=0; +#endif // !defined(UI_DISABLE_AUTO_PAGESWITCH) || !UI_DISABLE_AUTO_PAGESWITCH + + refresh = 1; + } + else if(time-lastRefresh>=1000) refresh=1; + } + else if(time-lastRefresh>=800) + { + UIMenu *men = (UIMenu*)menu[menuLevel]; + uint8_t mtype = pgm_read_byte((void*)&(men->menuType)); + (void)mtype; //ignore unused error Nibbels + refresh=1; + } + + if(refresh) + { + if (menuLevel > 1 || Printer::isAutomount()) + { + shift++; + if(shift+UI_COLS>MAX_COLS+1) + shift = -2; + } + else + shift = -2; + + refreshPage(); + lastRefresh = time; + } + +} // slowAction + + +void UIDisplay::fastAction() +{ +#if UI_HAS_KEYS==1 + // Check keys + HAL::forbidInterrupts(); + + if((flags & 10)==0) + { + flags |= UI_FLAG_KEY_TEST_RUNNING; + HAL::allowInterrupts(); + int nextAction = 0; + ui_check_keys(nextAction); + + if(lastButtonAction!=nextAction) + { + lastButtonStart = HAL::timeInMilliseconds(); + lastButtonAction = nextAction; + HAL::forbidInterrupts(); + flags|=UI_FLAG_FAST_KEY_ACTION; + if( nextAction == UI_ACTION_RF_CONTINUE ) + { + g_nContinueButtonPressed = 1; + } + } + + if(!nextAction) + { + // no key is pressed at the moment + if(PrintLine::direct.task == TASK_MOVE_FROM_BUTTON) + { + // the current direct movement has been started via a hardware or menu button - these movements shall be stopped as soon as the button is released + PrintLine::stopDirectMove(); + } + } + + HAL::forbidInterrupts(); + flags-=UI_FLAG_KEY_TEST_RUNNING; + } + HAL::allowInterrupts(); +#endif // UI_HAS_KEYS==1 + +} // fastAction + + +void UIDisplay::lock() +{ + locked = 1; + return; + +} // lock + + +void UIDisplay::unlock() +{ + locked = 0; + return; + +} // unlock + + +#if UI_ENCODER_SPEED==0 +const int8_t encoder_table[16] PROGMEM = {0,1,-1,0,-1,0,0,1,1,0,0,-1,0,-1,1,0}; // Full speed +#elif UI_ENCODER_SPEED==1 +const int8_t encoder_table[16] PROGMEM = {0,0,-1,0,0,0,0,1,1,0,0,0,0,-1,0,0}; // Half speed +#else +const int8_t encoder_table[16] PROGMEM = {0,0,0,0,0,0,0,0,0,0,0,-1,0,0,1,0}; // Quart speed +#endif // UI_ENCODER_SPEED==0 + +#endif // UI_DISPLAY_TYPE!=0 diff --git a/ui.h b/ui.h new file mode 100644 index 000000000..e4263a64f --- /dev/null +++ b/ui.h @@ -0,0 +1,654 @@ +/* + This file is part of the Repetier-Firmware for RF devices from Conrad Electronic SE. + + Repetier-Firmware is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Repetier-Firmware 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Repetier-Firmware. If not, see . +*/ + + +#ifndef UI_H +#define UI_H + +#include "gcode.h" + +// ---------------------------------------------------------------------------- +// Action codes +// 1-999 : Autorepeat +// 1000-1999 : Execute +// 2000-2999 : Write code +// 4000-4999 : Show menu +// Add UI_ACTION_TOPMENU to show a menu as top menu +// ---------------------------------------------------------------------------- + +#define UI_ACTION_TOPMENU 8192 + +#define UI_ACTION_NEXT 1 +#define UI_ACTION_PREVIOUS 2 + +#define UI_ACTION_DUMMY 10000 +#define UI_ACTION_BACK 1000 +#define UI_ACTION_OK 1001 +#define UI_ACTION_MENU_UP 1002 +#define UI_ACTION_TOP_MENU 1003 +#define UI_ACTION_EMERGENCY_STOP 1004 +#define UI_ACTION_XPOSITION 1005 +#define UI_ACTION_YPOSITION 1006 +#define UI_ACTION_ZPOSITION 1007 +#define UI_ACTION_EPOSITION 1008 +#define UI_ACTION_BED_TEMP 1009 +#define UI_ACTION_EXTRUDER_TEMP 1010 +#define UI_ACTION_SD_DELETE 1012 +#define UI_ACTION_SD_PRINT 1013 +#define UI_ACTION_SD_PAUSE 1014 +#define UI_ACTION_SD_CONTINUE 1015 +#define UI_ACTION_SD_UNMOUNT 1016 +#define UI_ACTION_SD_MOUNT 1017 +#define UI_ACTION_XPOSITION_FAST 1018 +#define UI_ACTION_YPOSITION_FAST 1019 +#define UI_ACTION_ZPOSITION_FAST 1020 +#define UI_ACTION_HOME_ALL 1021 +#define UI_ACTION_HOME_X 1022 +#define UI_ACTION_HOME_Y 1023 +#define UI_ACTION_HOME_Z 1024 +#define UI_ACTION_SELECT_EXTRUDER1 1025 +#define UI_ACTION_PRINT_ACCEL_X 1032 +#define UI_ACTION_PRINT_ACCEL_Y 1033 +#define UI_ACTION_PRINT_ACCEL_Z 1034 +#define UI_ACTION_MOVE_ACCEL_X 1035 +#define UI_ACTION_MOVE_ACCEL_Y 1036 +#define UI_ACTION_MOVE_ACCEL_Z 1037 +#define UI_ACTION_MAX_JERK 1038 +#define UI_ACTION_MAX_ZJERK 1039 +#define UI_ACTION_BAUDRATE 1040 +#define UI_ACTION_HOMING_FEEDRATE_X 1041 +#define UI_ACTION_HOMING_FEEDRATE_Y 1042 +#define UI_ACTION_HOMING_FEEDRATE_Z 1043 +#define UI_ACTION_MAX_FEEDRATE_X 1044 +#define UI_ACTION_MAX_FEEDRATE_Y 1045 +#define UI_ACTION_MAX_FEEDRATE_Z 1046 +#define UI_ACTION_FAN_OFF 1050 +#define UI_ACTION_FAN_25 1051 +#define UI_ACTION_FAN_50 1052 +#define UI_ACTION_FAN_75 1053 +#define UI_ACTION_FAN_FULL 1054 +#define UI_ACTION_FEEDRATE_MULTIPLY 1055 +#define UI_ACTION_STEPPER_INACTIVE 1056 +#define UI_ACTION_X_OFFSET 1063 +#define UI_ACTION_Y_OFFSET 1064 +#define UI_ACTION_EXTR_STEPS 1065 +#define UI_ACTION_EXTR_ACCELERATION 1066 +#define UI_ACTION_EXTR_MAX_FEEDRATE 1067 +#define UI_ACTION_EXTR_START_FEEDRATE 1068 +#define UI_ACTION_EXTR_HEATMANAGER 1069 +#define UI_ACTION_EXTR_WATCH_PERIOD 1070 +#define UI_ACTION_ADVANCE_K 1072 +#define UI_ACTION_DEBUG_ECHO 1074 +#define UI_ACTION_DEBUG_INFO 1075 +#define UI_ACTION_DEBUG_ERROR 1076 +#define UI_ACTION_DEBUG_DRYRUN 1077 +#define UI_ACTION_POWER 1078 +#define UI_ACTION_PREHEAT_PLA 1079 +#define UI_ACTION_COOLDOWN 1080 +#define UI_ACTION_HEATED_BED_OFF 1081 +#define UI_ACTION_EXTRUDER0_OFF 1082 +#define UI_ACTION_EXTRUDER1_OFF 1083 +#define UI_ACTION_HEATED_BED_TEMP 1084 +#define UI_ACTION_EXTRUDER0_TEMP 1085 +#define UI_ACTION_EXTRUDER1_TEMP 1086 +#define UI_ACTION_OPS_OFF 1087 +#define UI_ACTION_OPS_CLASSIC 1088 +#define UI_ACTION_OPS_FAST 1089 +#define UI_ACTION_DISABLE_STEPPER 1090 +#define UI_ACTION_SET_E_ORIGIN 1091 +#define UI_ACTION_EXTRUDER_RELATIVE 1092 +#define UI_ACTION_SELECT_EXTRUDER0 1093 +#define UI_ACTION_ADVANCE_L 1094 +#define UI_ACTION_PREHEAT_ABS 1095 +#define UI_ACTION_FLOWRATE_MULTIPLY 1096 +#define UI_ACTION_EXTR_WAIT_RETRACT_TEMP 1100 +#define UI_ACTION_EXTR_WAIT_RETRACT_UNITS 1101 +#define UI_ACTION_EXTRUDER2_OFF 1102 +#define UI_ACTION_EXTRUDER2_TEMP 1103 +#define UI_ACTION_SELECT_EXTRUDER2 1104 +#define UI_ACTION_WRITE_DEBUG 1105 +#define UI_ACTION_FANSPEED 1106 +#define UI_ACTION_LIGHTS_ONOFF 1107 +#define UI_ACTION_SD_STOP 1108 +#define UI_ACTION_SD_STOP_ACK 1109 +#define UI_ACTION_ZPOSITION_NOTEST 1110 +#define UI_ACTION_ZPOSITION_FAST_NOTEST 1111 +#define UI_ACTION_MAX_INACTIVE 1113 +#define UI_ACTION_BEEPER 1114 +#define UI_ACTION_UNMOUNT_FILAMENT 1115 +#define UI_ACTION_MOUNT_FILAMENT 1116 +#define UI_ACTION_OPERATING_MODE 1117 +#define UI_ACTION_SET_XY_ORIGIN 1118 +#define UI_ACTION_Z_ENDSTOP_TYPE 1119 +#define UI_ACTION_HOTEND_TYPE 1120 +#define UI_ACTION_MILLER_TYPE 1121 +#define UI_ACTION_230V_OUTPUT 1122 +#define UI_ACTION_RGB_LIGHT_MODE 1123 +#define UI_ACTION_EXTRUDER_OFFSET_X 1124 +#define UI_ACTION_EXTRUDER_OFFSET_Y 1125 +#define UI_ACTION_RESTORE_DEFAULTS 1126 +#define UI_ACTION_ACTIVE_EXTRUDER 1127 +#define UI_ACTION_ZOFFSET 1128 +#define UI_ACTION_RIGHT 1129 +#define UI_ACTION_ZMODE 1130 + +//Nibbels : nicht in processbutton sondern in executeaction! +#define UI_ACTION_RF_DO_MHIER_BED_SCAN 1666 +#define UI_ACTION_CONFIG_SINGLE_STEPS 1667 +#define UI_ACTION_RF_DO_SAVE_ACTIVE_ZMATRIX 1668 + +#define UI_ACTION_FET1_OUTPUT 2001 +#define UI_ACTION_FET2_OUTPUT 2002 + + +#define UI_ACTION_MENU_XPOS 4000 +#define UI_ACTION_MENU_YPOS 4001 +#define UI_ACTION_MENU_ZPOS 4002 +#define UI_ACTION_MENU_XPOSFAST 4003 +#define UI_ACTION_MENU_YPOSFAST 4004 +#define UI_ACTION_MENU_ZPOSFAST 4005 +#define UI_ACTION_MENU_SDCARD 4006 +#define UI_ACTION_MENU_QUICKSETTINGS 4007 +#define UI_ACTION_MENU_EXTRUDER 4008 +#define UI_ACTION_MENU_POSITIONS 4009 +#define UI_ACTION_SET_Z_ORIGIN 4012 + +#define UI_ACTION_SHOW_USERMENU1 4101 +#define UI_ACTION_SHOW_USERMENU2 4102 +#define UI_ACTION_SHOW_USERMENU3 4103 +#define UI_ACTION_SHOW_USERMENU4 4104 +#define UI_ACTION_SHOW_USERMENU5 4105 +#define UI_ACTION_SHOW_USERMENU6 4106 +#define UI_ACTION_SHOW_USERMENU7 4107 +#define UI_ACTION_SHOW_USERMENU8 4108 +#define UI_ACTION_SHOW_USERMENU9 4109 +#define UI_ACTION_SHOW_USERMENU10 4110 + +// Load basic language definition to make sure all values are defined +#include "uilang.h" + + +typedef struct +{ + const char* text; // Menu text + uint8_t menuType; // 0 = Info, 1 = Headline, 2 = submenu ref, 3 = direct action command, 4 = modify action command + unsigned int action; // must be int so it gets 32 bit on arm! + uint8_t filter; // allows dynamic menu filtering based on Printer::menuMode bits set. + uint8_t nofilter; // Hide if one of these bits are set + + bool showEntry() const; + +}const UIMenuEntry; + + +typedef struct +{ + // 0 = info page + // 1 = file selector + // 2 = submenu + // 3 = modification menu + unsigned char menuType; + int id; // Type of modification + int numEntries; + + const UIMenuEntry * const * entries; + +}const UIMenu; + + +extern const int8_t encoder_table[16] PROGMEM; + +extern char g_nYesNo; +extern volatile char g_nContinueButtonPressed; +extern char g_nServiceRequest; +extern char g_nPrinterReady; + +// Key codes +#define UI_KEYS_INIT_CLICKENCODER_LOW(pinA,pinB) SET_INPUT(pinA);SET_INPUT(pinB); PULLUP(pinA,HIGH);PULLUP(pinB,HIGH); +#define UI_KEYS_INIT_BUTTON_LOW(pin) SET_INPUT(pin);PULLUP(pin,HIGH); +#define UI_KEYS_INIT_CLICKENCODER_HIGH(pinA,pinB) SET_INPUT(pinA);SET_INPUT(pinB); PULLUP(pinA,LOW);PULLUP(pinB,LOW); +#define UI_KEYS_INIT_BUTTON_HIGH(pin) SET_INPUT(pin);PULLUP(pin,LOW); + +#define UI_KEYS_CLICKENCODER_LOW(pinA,pinB) uid.encoderLast = (uid.encoderLast << 2) & 0x0F;if (!READ(pinA)) uid.encoderLast |=2;if (!READ(pinB)) uid.encoderLast |=1; uid.encoderPos += pgm_read_byte(&encoder_table[uid.encoderLast]); +#define UI_KEYS_CLICKENCODER_LOW_REV(pinA,pinB) uid.encoderLast = (uid.encoderLast << 2) & 0x0F;if (!READ(pinA)) uid.encoderLast |=2;if (!READ(pinB)) uid.encoderLast |=1; uid.encoderPos -= pgm_read_byte(&encoder_table[uid.encoderLast]); +#define UI_KEYS_BUTTON_LOW(pin,action_) if(READ(pin)==0) action=action_; +#define UI_KEYS_CLICKENCODER_HIGH(pinA,pinB) uid.encoderLast = (uid.encoderLast << 2) & 0x0F;if (READ(pinA)) uid.encoderLast |=2;if (READ(pinB)) uid.encoderLast |=1; uid.encoderPos += pgm_read_byte(&encoder_table[uid.encoderLast]); +#define UI_KEYS_CLICKENCODER_HIGH_REV(pinA,pinB) uid.encoderLast = (uid.encoderLast << 2) & 0x0F;if (READ(pinA)) uid.encoderLast |=2;if (READ(pinB)) uid.encoderLast |=1; uid.encoderPos -= pgm_read_byte(&encoder_table[uid.encoderLast]); +#define UI_KEYS_BUTTON_HIGH(pin,action_) if(READ(pin)!=0) action=action_; +#define UI_KEYS_INIT_MATRIX(r1,r2,r3,r4,c1,c2,c3,c4) if(c1>=0){SET_INPUT(c1);WRITE(c1,HIGH);}if(c2>=0){SET_INPUT(c2);WRITE(c2,HIGH);}if(c3>=0){SET_INPUT(c3);WRITE(c3,HIGH);}\ + if(c4>=0) {SET_INPUT(c4);WRITE(c4,HIGH);}if(r1>=0)SET_OUTPUT(r1);if(r2>=0)SET_OUTPUT(r2);if(r3>=0)SET_OUTPUT(r3);if(r4>=0)SET_OUTPUT(r4);\ + if(r1>=0)WRITE(r1,LOW);if(r2>=0)WRITE(r2,LOW);if(r3>=0)WRITE(r3,LOW);if(r4>=0)WRITE(r4,LOW); + +#define UI_KEYS_MATRIX(r1,r2,r3,r4,c1,c2,c3,c4) {uint8_t r = (c1>=0?READ(c1):0) && (c2>=0?READ(c2):0) && (c3>=0?READ(c3):0) && (c4>=0?READ(c4):0);\ + if(!r) {\ + r = 255;\ + if(r2>=0)WRITE(r2,HIGH);if(r3>=0)WRITE(r3,HIGH);if(r4>=0)WRITE(r4,HIGH);\ + if(r1>=0) {\ + asm volatile ("nop\nnop\nnop\nnop\nnop");\ + if(!((c1>=0?READ(c1):1) && (c2>=0?READ(c2):1) && (c3>=0?READ(c3):1) && (c4>=0?READ(c4):1))) r = 0;\ + else WRITE(r1,HIGH);\ + }\ + if(r==255 && r2>=0) {\ + WRITE(r2,LOW);asm volatile ("nop\nnop\nnop\nnop\nnop");\ + if(!((c1>=0?READ(c1):1) && (c2>=0?READ(c2):1) && (c3>=0?READ(c3):1) && (c4>=0?READ(c4):1))) r = 4;\ + else WRITE(r2,HIGH);\ + }\ + if(r==255 && r3>=0) {\ + WRITE(r3,LOW);asm volatile ("nop\nnop\nnop\nnop\nnop");\ + if(!((c1>=0?READ(c1):0) && (c2>=0?READ(c2):1) && (c3>=0?READ(c3):1) && (c4>=0?READ(c4):1))) r = 8;\ + else WRITE(r3,HIGH);\ + }\ + if(r==255 && r4>=0) {\ + WRITE(r4,LOW);asm volatile ("nop\nnop\nnop\nnop\nnop");\ + if(!((c1>=0?READ(c1):1) && (c2>=0?READ(c2):1) && (c3>=0?READ(c3):1) && (c4>=0?READ(c4):1))) r = 12;\ + else WRITE(r4,HIGH);\ + }\ + if(c2>=0 && !READ(c2)) r+=1;\ + else if(c3>=0 && !READ(c3)) r+=2;\ + else if(c4>=0 && !READ(c4)) r+=3;\ + if(r<16) {action = pgm_read_word(&(matrixActions[r]));}\ + }if(r1>=0)WRITE(r1,LOW);if(r2>=0)WRITE(r2,LOW);if(r3>=0)WRITE(r3,LOW);if(r4>=0)WRITE(r4,LOW);} + +// I2C keymask tests +#define UI_KEYS_I2C_CLICKENCODER_LOW(pinA,pinB) uid.encoderLast = (uid.encoderLast << 2) & 0x0F;if (!(keymask & pinA)) uid.encoderLast |=2;if (!(keymask & pinB)) uid.encoderLast |=1; uid.encoderPos += pgm_read_byte(&encoder_table[uid.encoderLast]); +#define UI_KEYS_I2C_CLICKENCODER_LOW_REV(pinA,pinB) uid.encoderLast = (uid.encoderLast << 2) & 0x0F;if (!(keymask & pinA)) uid.encoderLast |=2;if (!(keymask & pinB)) uid.encoderLast |=1; uid.encoderPos -= pgm_read_byte(&encoder_table[uid.encoderLast]); +#define UI_KEYS_I2C_BUTTON_LOW(pin,action_) if((keymask & pin)==0) action=action_; +#define UI_KEYS_I2C_CLICKENCODER_HIGH(pinA,pinB) uid.encoderLast = (uid.encoderLast << 2) & 0x0F;if (keymask & pinA) uid.encoderLast |=2;if (keymask & pinB) uid.encoderLast |=1; uid.encoderPos += pgm_read_byte(&encoder_table[uid.encoderLast]); +#define UI_KEYS_I2C_CLICKENCODER_HIGH_REV(pinA,pinB) uid.encoderLast = (uid.encoderLast << 2) & 0x0F;if (keymask & pinA) uid.encoderLast |=2;if (keymask & pinB) uid.encoderLast |=1; uid.encoderPos -= pgm_read_byte(&encoder_table[uid.encoderLast]); +#define UI_KEYS_I2C_BUTTON_HIGH(pin,action_) if((pin & keymask)!=0) action=action_; + +#define UI_STRING(name,text) const char PROGMEM name[] = text; + +#define UI_PAGE6(name,row1,row2,row3,row4,row5,row6) UI_STRING(name ## _1txt,row1) UI_STRING(name ## _2txt,row2) UI_STRING(name ## _3txt,row3) UI_STRING(name ## _4txt,row4) UI_STRING(name ## _5txt,row5) UI_STRING(name ## _6txt,row6) \ + UIMenuEntry name ## _1 PROGMEM ={name ## _1txt,0,0,0,0};\ + UIMenuEntry name ## _2 PROGMEM ={name ## _2txt,0,0,0,0};\ + UIMenuEntry name ## _3 PROGMEM ={name ## _3txt,0,0,0,0};\ + UIMenuEntry name ## _4 PROGMEM ={name ## _4txt,0,0,0,0};\ + UIMenuEntry name ## _5 PROGMEM ={name ## _5txt,0,0,0,0};\ + UIMenuEntry name ## _6 PROGMEM ={name ## _6txt,0,0,0,0};\ + const UIMenuEntry * const name ## _entries [] PROGMEM = {&name ## _1,&name ## _2,&name ## _3,&name ## _4,&name ## _5,&name ## _6};\ + const UIMenu name PROGMEM = {0,0,6,name ## _entries}; + +#define UI_PAGE4(name,row1,row2,row3,row4) UI_STRING(name ## _1txt,row1) UI_STRING(name ## _2txt,row2) UI_STRING(name ## _3txt,row3) UI_STRING(name ## _4txt,row4) \ + UIMenuEntry name ## _1 PROGMEM ={name ## _1txt,0,0,0,0};\ + UIMenuEntry name ## _2 PROGMEM ={name ## _2txt,0,0,0,0};\ + UIMenuEntry name ## _3 PROGMEM ={name ## _3txt,0,0,0,0};\ + UIMenuEntry name ## _4 PROGMEM ={name ## _4txt,0,0,0,0};\ + const UIMenuEntry * const name ## _entries [] PROGMEM = {&name ## _1,&name ## _2,&name ## _3,&name ## _4};\ + const UIMenu name PROGMEM = {0,0,4,name ## _entries}; + +#define UI_PAGE2(name,row1,row2) UI_STRING(name ## _1txt,row1) UI_STRING(name ## _2txt,row2) \ + UIMenuEntry name ## _1 PROGMEM ={name ## _1txt,0,0,0,0};\ + UIMenuEntry name ## _2 PROGMEM ={name ## _2txt,0,0,0,0};\ + const UIMenuEntry * const name ## _entries[] PROGMEM = {&name ## _1,&name ## _2};\ + const UIMenu name PROGMEM = {0,0,2,name ## _entries}; + +#define UI_MENU_ACTION4C(name,action,rows) UI_MENU_ACTION4(name,action,rows) +#define UI_MENU_ACTION2C(name,action,rows) UI_MENU_ACTION2(name,action,rows) + +#define UI_MENU_ACTION4(name,action,row1,row2,row3,row4) UI_STRING(name ## _1txt,row1) UI_STRING(name ## _2txt,row2) UI_STRING(name ## _3txt,row3) UI_STRING(name ## _4txt,row4) \ + UIMenuEntry name ## _1 PROGMEM ={name ## _1txt,0,0,0,0};\ + UIMenuEntry name ## _2 PROGMEM ={name ## _2txt,0,0,0,0};\ + UIMenuEntry name ## _3 PROGMEM ={name ## _3txt,0,0,0,0};\ + UIMenuEntry name ## _4 PROGMEM ={name ## _4txt,0,0,0,0};\ + const UIMenuEntry * const name ## _entries[] PROGMEM = {&name ## _1,&name ## _2,&name ## _3,&name ## _4};\ + const UIMenu name PROGMEM = {3,action,4,name ## _entries}; + +#define UI_MENU_ACTION2(name,action,row1,row2) UI_STRING(name ## _1txt,row1) UI_STRING(name ## _2txt,row2) \ + UIMenuEntry name ## _1 PROGMEM ={name ## _1txt,0,0,0,0};\ + UIMenuEntry name ## _2 PROGMEM ={name ## _2txt,0,0,0,0};\ + const UIMenuEntry * const name ## _entries[] PROGMEM = {&name ## _1,&name ## _2};\ + const UIMenu name PROGMEM = {3,action,2,name ## _entries}; + +#define UI_MENU_HEADLINE(name,text) UI_STRING(name ## _txt,text) UIMenuEntry name PROGMEM = {name ## _txt,1,0,0,0}; +#define UI_MENU_CHANGEACTION(name,row,action) UI_STRING(name ## _txt,row) UIMenuEntry name PROGMEM = {name ## _txt,4,action,0,0}; +#define UI_MENU_ACTIONCOMMAND(name,row,action) UI_STRING(name ## _txt,row) UIMenuEntry name PROGMEM = {name ## _txt,3,action,0,0}; +#define UI_MENU_ACTIONSELECTOR(name,row,entries) UI_STRING(name ## _txt,row) UIMenuEntry name PROGMEM = {name ## _txt,2,(unsigned int)&entries,0,0}; +#define UI_MENU_SUBMENU(name,row,entries) UI_STRING(name ## _txt,row) UIMenuEntry name PROGMEM = {name ## _txt,2,(unsigned int)&entries,0,0}; +#define UI_MENU_CHANGEACTION_FILTER(name,row,action,filter,nofilter) UI_STRING(name ## _txt,row) UIMenuEntry name PROGMEM = {name ## _txt,4,action,filter,nofilter}; +#define UI_MENU_ACTIONCOMMAND_FILTER(name,row,action,filter,nofilter) UI_STRING(name ## _txt,row) UIMenuEntry name PROGMEM = {name ## _txt,3,action,filter,nofilter}; +#define UI_MENU_ACTIONSELECTOR_FILTER(name,row,entries,filter,nofilter) UI_STRING(name ## _txt,row) UIMenuEntry name PROGMEM = {name ## _txt,2,(unsigned int)&entries,filter,nofilter}; +#define UI_MENU_SUBMENU_FILTER(name,row,entries,filter,nofilter) UI_STRING(name ## _txt,row) UIMenuEntry name PROGMEM = {name ## _txt,2,(unsigned int)&entries,filter,nofilter}; +#define UI_MENU(name,items,itemsCnt) const UIMenuEntry * const name ## _entries[] PROGMEM = items;const UIMenu name PROGMEM = {2,0,itemsCnt,name ## _entries}; +#define UI_MENU_FILESELECT(name,items,itemsCnt) const UIMenuEntry * const name ## _entries[] PROGMEM = items;const UIMenu name PROGMEM = {1,0,itemsCnt,name ## _entries}; + +// Maximum size of a row - if row is larger, text gets scrolled +#define MAX_COLS 20 + +#define UI_FLAG_FAST_KEY_ACTION 1 +#define UI_FLAG_SLOW_KEY_ACTION 2 +#define UI_FLAG_SLOW_ACTION_RUNNING 4 +#define UI_FLAG_KEY_TEST_RUNNING 8 + +#define MAX_MENU_LEVELS 6 + + +class UIDisplay +{ +public: + volatile uint8_t flags; + uint8_t col; // current col for buffer prefill + uint8_t menuLevel; // current menu level, 0 = info, 1 = group, 2 = groupdata select, 3 = value change + uint8_t menuPos[MAX_MENU_LEVELS]; // Positions in menu + void* menu[MAX_MENU_LEVELS]; // Menus active + uint8_t menuTop[MAX_MENU_LEVELS]; // Top row in menu + int8_t shift; // Display shift for scrolling text + int pageDelay; // Counter. If 0 page is refreshed if menuLevel is 0. + void* messageLine1; + void* messageLine2; + void* messageLine3; + void* messageLine4; + int activeAction; // action for ok/next/previous + int lastAction; + millis_t lastSwitch; // Last time display switched pages + millis_t lastRefresh; + volatile int lastButtonAction; + volatile millis_t lastButtonStart; + millis_t nextRepeat; // Time of next autorepeat + millis_t lastNextPrev; // for increasing speed settings + float lastNextAccumul; // Accumulated value + unsigned int outputMask; // Output mask for backlight, leds etc. + int repeatDuration; // Time beween to actions if autorepeat is enabled + int8_t oldMenuLevel; + uint8_t encoderStartScreen; + char statusMsg[MAX_COLS + 1]; + int8_t encoderPos; + int8_t encoderLast; + PGM_P statusText; + char locked; + + void addInt(int value,uint8_t digits,char fillChar=' '); // Print int into printCols + void addLong(long value,char digits); + void addFloat(float number, char fixdigits,uint8_t digits); + void addStringP(PGM_P text); + void okAction(); + void rightAction(); + void nextPreviousAction(int8_t next); + UIDisplay(); + void createChar(uint8_t location,const uint8_t charmap[]); + void initialize(); // Initialize display and keys + void waitForKey(); + void printRow(uint8_t r,char *txt,char *txt2,uint8_t changeAtCol); // Print row on display + void printRowP(uint8_t r,PGM_P txt); + void parse(char *txt,bool ram); /// Parse output and write to printCols; + void refreshPage(); + void executeAction(int action); + void finishAction(int action); + void slowAction(); + void fastAction(); + void mediumAction(); + void showMessage(bool refresh); + void pushMenu(void *men,bool refresh); + void adjustMenuPos(); + void setStatusP(PGM_P txt,bool error = false); + void setStatus(char *txt,bool error = false,bool force = false); + + inline void setOutputMaskBits(unsigned int bits) + { + outputMask|=bits; + } // setOutputMaskBits + + inline void unsetOutputMaskBits(unsigned int bits) + { + outputMask&=~bits; + } // unsetOutputMaskBits + +#if SDSUPPORT + char cwd[SD_MAX_FOLDER_DEPTH*LONG_FILENAME_LENGTH+2]; + uint8_t folderLevel; + + void updateSDFileCount(); + void goDir(char *name); + bool isDirname(char *name); +#endif // SDSUPPORT + + void lock(); + void unlock(); + +}; + +extern UIDisplay uid; + +// initializeLCD() +void initializeLCD(); + + +#if MOTHERBOARD == DEVICE_TYPE_RF1000 +#define UI_HAS_KEYS 1 // 1 = Some keys attached +#define UI_HAS_BACK_KEY 1 +#define UI_DISPLAY_TYPE 1 // 1 = LCD Display with 4 bit data bus +//#define UI_DISPLAY_CHARSET 1 +#define UI_COLS 16 +#define UI_ROWS 4 +#define UI_DELAYPERCHAR 320 +#define UI_INVERT_MENU_DIRECTION false +#define UI_INVERT_INCREMENT_DIRECTION true + +#ifdef UI_MAIN +void ui_init_keys() +{ + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_1); // push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_2); // push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_3); // push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_4); // push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_5); // push button, connects gnd to pin + +#if FEATURE_EXTENDED_BUTTONS + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_E1); // PINJ.2, 80, X12.1 - push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_E2); // PINJ.4, 81, X12.2 - push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_E3); // PINJ.5, 82, X12.3 - push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_E4); // PINJ.6, 83, X12.4 - push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_E5); // PINH.7, 85, X12.6 - push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_E6); // PINH.2, 86, X12.7 - push button, connects gnd to pin +#endif // FEATURE_EXTENDED_BUTTONS + +} // ui_init_keys + + +void ui_check_keys(int &action) +{ + UI_KEYS_BUTTON_LOW(ENABLE_KEY_1,UI_ACTION_OK); // push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_2,UI_ACTION_NEXT); // push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_5,UI_ACTION_PREVIOUS); // push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_4,UI_ACTION_BACK); // push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_3,UI_ACTION_RIGHT ); // push button, connects gnd to pin + +#if FEATURE_EXTENDED_BUTTONS + UI_KEYS_BUTTON_LOW(ENABLE_KEY_E1,UI_ACTION_RF_HEAT_BED_UP); // PINJ.2, 80, X12.1 - push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_E2,UI_ACTION_RF_HEAT_BED_DOWN); // PINJ.4, 81, X12.2 - push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_E3,UI_ACTION_RF_EXTRUDER_RETRACT); // PINJ.5, 82, X12.3 - push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_E4,UI_ACTION_RF_EXTRUDER_OUTPUT); // PINJ.6, 83, X12.4 - push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_E5,UI_ACTION_RF_CONTINUE); // PINH.7, 85, X12.6 - push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_E6,UI_ACTION_RF_PAUSE); // PINH.2, 86, X12.7 - push button, connects gnd to pin +#endif // FEATURE_EXTENDED_BUTTONS + +} // ui_check_keys + +inline void ui_check_slow_encoder() {} +void ui_check_slow_keys(int &action) { + (void)action; +} +#endif // UI_MAIN +#endif // MOTHERBOARD == DEVICE_TYPE_RF1000 + + +#if MOTHERBOARD == DEVICE_TYPE_RF2000 +#define UI_HAS_KEYS 1 // 1 = Some keys attached +#define UI_HAS_BACK_KEY 1 +#define UI_DISPLAY_TYPE 1 // 1 = LCD Display with 4 bit data bus +//#define UI_DISPLAY_CHARSET 1 +#define UI_COLS 20 +#define UI_ROWS 4 +#define UI_DELAYPERCHAR 320 +#define UI_INVERT_MENU_DIRECTION false +#define UI_INVERT_INCREMENT_DIRECTION true + +#ifdef UI_MAIN +void ui_init_keys() +{ + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_1); // push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_2); // push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_3); // push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_4); // push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_5); // push button, connects gnd to pin + +#if FEATURE_EXTENDED_BUTTONS + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_E1); // PINJ.2, 80, X12.1 - push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_E2); // PINJ.4, 81, X12.2 - push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_E3); // PINJ.5, 82, X12.3 - push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_E4); // PINJ.6, 83, X12.4 - push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_E5); // PINH.7, 85, X12.6 - push button, connects gnd to pin + UI_KEYS_INIT_BUTTON_LOW(ENABLE_KEY_E6); // PINH.2, 86, X12.7 - push button, connects gnd to pin +#endif // FEATURE_EXTENDED_BUTTONS + +} // ui_init_keys + + +void ui_check_keys(int &action) +{ + UI_KEYS_BUTTON_LOW(ENABLE_KEY_1,UI_ACTION_OK); // push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_2,UI_ACTION_NEXT); // push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_5,UI_ACTION_PREVIOUS); // push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_4,UI_ACTION_BACK); // push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_3,UI_ACTION_RIGHT ); // push button, connects gnd to pin + +#if FEATURE_EXTENDED_BUTTONS + UI_KEYS_BUTTON_LOW(ENABLE_KEY_E1,UI_ACTION_RF_HEAT_BED_UP); // PINJ.2, 80, X12.1 - push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_E2,UI_ACTION_RF_HEAT_BED_DOWN); // PINJ.4, 81, X12.2 - push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_E3,UI_ACTION_RF_EXTRUDER_RETRACT); // PINJ.5, 82, X12.3 - push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_E4,UI_ACTION_RF_EXTRUDER_OUTPUT); // PINJ.6, 83, X12.4 - push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_E5,UI_ACTION_RF_CONTINUE); // PINH.7, 85, X12.6 - push button, connects gnd to pin + UI_KEYS_BUTTON_LOW(ENABLE_KEY_E6,UI_ACTION_RF_PAUSE); // PINH.2, 86, X12.7 - push button, connects gnd to pin +#endif // FEATURE_EXTENDED_BUTTONS + +} // ui_check_keys + +inline void ui_check_slow_encoder() {} +void ui_check_slow_keys(int &action) { + (void)action; +} +#endif // UI_MAIN +#endif // MOTHERBOARD == DEVICE_TYPE_RF2000 + + +#if UI_ROWS==4 +#if UI_COLS==16 +#define UI_LINE_OFFSETS {0,0x40,0x10,0x50} // 4x16 +#elif UI_COLS==20 +//#define UI_LINE_OFFSETS {0,0x20,0x40,0x60} // 4x20 with KS0073 +#define UI_LINE_OFFSETS {0,0x40,0x14,0x54} // 4x20 with HD44780 +#else +#error Unknown combination of rows/columns - define UI_LINE_OFFSETS manually. +#endif // UI_COLS==16 +#else +#define UI_LINE_OFFSETS {0,0x40,0x10,0x50} // 2x16, 2x20, 2x24 +#endif // UI_ROWS==4 + +#include "uilang.h" +#include "uimenu.h" + +#ifdef UI_HAS_I2C_KEYS +#define COMPILE_I2C_DRIVER +#endif // UI_HAS_I2C_KEYS + +#if UI_DISPLAY_TYPE!=0 +#if UI_DISPLAY_TYPE==3 +#define COMPILE_I2C_DRIVER +#endif // UI_DISPLAY_TYPE==3 + +#ifndef UI_TEMP_PRECISION +#if UI_COLS>16 +#define UI_TEMP_PRECISION 1 +#else +#define UI_TEMP_PRECISION 0 +#endif // UI_COLS>16 +#endif // UI_TEMP_PRECISION + +#define UI_INITIALIZE uid.initialize(); +#define UI_FAST if(pwm_count_heater & 4) {uid.fastAction();} +#define UI_MEDIUM uid.mediumAction(); +#define UI_SLOW uid.slowAction(); +#define UI_STATUS(status) uid.setStatusP(PSTR(status)); +#define UI_STATUS_UPD(status) {uid.setStatusP(PSTR(status));uid.refreshPage();} +#define UI_STATUS_RAM(status) uid.setStatus(status); +#define UI_STATUS_UPD_RAM(status) {uid.setStatus(status);uid.refreshPage();} +#define UI_ERROR(status) uid.setStatusP(PSTR(status),true); +#define UI_ERROR_UPD(status) {uid.setStatusP(PSTR(status),true);uid.refreshPage();} +#define UI_ERROR_RAM(status) uid.setStatus(status,true); +#define UI_ERROR_UPD_RAM(status) {uid.setStatus(status,true);uid.refreshPage();} +#define UI_CLEAR_STATUS {uid.statusMsg[0]=0;} +#else +#define UI_INITIALIZE {} +#define UI_FAST {} +#define UI_MEDIUM {} +#define UI_SLOW {} +#define UI_STATUS(status) {} +#define UI_STATUS_RAM(status) {} +#define UI_STATUS_UPD(status) {} +#define UI_STATUS_UPD_RAM(status) {} +#define UI_CLEAR_STATUS {} +#define UI_ERROR(msg) {} +#define UI_ERROR_UPD(status) {} +#define UI_ERROR_RAM(status) {} +#define UI_ERROR_UPD_RAM(status) {} +#endif // UI_DISPLAY_TYPE!=0 + +// Beeper methods +#if BEEPER_TYPE==0 +#define BEEP_SHORT {} +#define BEEP_LONG {} +#define BEEP_START_PRINTING {} +#define BEEP_ABORT_PRINTING {} +#define BEEP_STOP_PRINTING {} +#define BEEP_PAUSE {} +#define BEEP_CONTINUE {} +#define BEEP_START_HEAT_BED_SCAN {} +#define BEEP_ABORT_HEAT_BED_SCAN {} +#define BEEP_STOP_HEAT_BED_SCAN {} +#define BEEP_START_WORK_PART_SCAN {} +#define BEEP_ABORT_WORK_PART_SCAN {} +#define BEEP_STOP_WORK_PART_SCAN {} +#define BEEP_ABORT_SET_POSITION {} +#define BEEP_ACCEPT_SET_POSITION {} +#define BEEP_SERVICE_INTERVALL {} +#define BEEP_ALIGN_EXTRUDERS {} +#define BEEP_WRONG_FIRMWARE {} +#else +#define BEEP_SHORT beep(BEEPER_SHORT_SEQUENCE); +#define BEEP_LONG beep(BEEPER_LONG_SEQUENCE); +#define BEEP_START_PRINTING beep(BEEPER_START_PRINTING_SEQUENCE); +#define BEEP_ABORT_PRINTING beep(BEEPER_ABORT_PRINTING_SEQUENCE); +#define BEEP_STOP_PRINTING beep(BEEPER_STOP_PRINTING_SEQUENCE); +#define BEEP_PAUSE beep(BEEPER_PAUSE_SEQUENCE); +#define BEEP_CONTINUE beep(BEEPER_CONTINUE_SEQUENCE); +#define BEEP_START_HEAT_BED_SCAN beep(BEEPER_START_HEAT_BED_SCAN_SEQUENCE); +#define BEEP_ABORT_HEAT_BED_SCAN beep(BEEPER_ABORT_HEAT_BED_SCAN_SEQUENCE); +#define BEEP_STOP_HEAT_BED_SCAN beep(BEEPER_STOP_HEAT_BED_SCAN_SEQUENCE); +#define BEEP_START_WORK_PART_SCAN beep(BEEPER_START_WORK_PART_SCAN_SEQUENCE); +#define BEEP_ABORT_WORK_PART_SCAN beep(BEEPER_ABORT_WORK_PART_SCAN_SEQUENCE); +#define BEEP_STOP_WORK_PART_SCAN beep(BEEPER_STOP_WORK_PART_SCAN_SEQUENCE); +#define BEEP_ABORT_SET_POSITION beep(BEEPER_ABORT_SET_POSITION_SEQUENCE); +#define BEEP_ACCEPT_SET_POSITION beep(BEEPER_ACCEPT_SET_POSITION_SEQUENCE); +#define BEEP_SERVICE_INTERVALL beep(BEEPER_SERVICE_INTERVALL_SEQUNCE); +#define BEEP_ALIGN_EXTRUDERS beep(BEEPER_ALIGN_EXTRUDERS_SEQUNCE); +#define BEEP_WRONG_FIRMWARE beep(BEEPER_WRONG_FIRMWARE_SEQUNCE); +#endif // BEEPER_TYPE==0 + +extern void beep(uint8_t duration,uint8_t count); + +#endif // UI_H +