2016-03-25 07:19:46 +01:00
/**
2016-03-24 19:01:20 +01:00
* Marlin 3 D Printer Firmware
* Copyright ( C ) 2016 MarlinFirmware [ https : //github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl .
* Copyright ( C ) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program 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 .
*
* This program 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 this program . If not , see < http : //www.gnu.org/licenses/>.
*
*/
2011-12-12 19:34:37 +01:00
# include "ultralcd.h"
2015-07-31 07:26:53 +02:00
# if ENABLED(ULTRA_LCD)
2011-12-22 14:55:45 +01:00
# include "Marlin.h"
2012-05-03 14:22:43 +02:00
# include "language.h"
2012-12-12 11:47:03 +01:00
# include "cardreader.h"
2012-05-03 14:22:43 +02:00
# include "temperature.h"
2013-01-31 16:43:03 +01:00
# include "stepper.h"
2015-04-26 06:04:54 +02:00
# include "configuration_store.h"
2012-11-06 12:06:41 +01:00
2016-06-30 11:24:29 +02:00
# if ENABLED(PRINTCOUNTER)
# include "printcounter.h"
# endif
2016-07-10 00:20:12 +02:00
int preheatHotendTemp1 , preheatBedTemp1 , preheatFanSpeed1 ,
preheatHotendTemp2 , preheatBedTemp2 , preheatFanSpeed2 ;
2013-07-30 14:33:30 +02:00
2015-07-31 07:26:53 +02:00
# if ENABLED(FILAMENT_LCD_DISPLAY)
2015-04-13 03:07:08 +02:00
millis_t previous_lcd_status_ms = 0 ;
2014-11-11 04:43:58 +01:00
# endif
2012-12-12 11:47:03 +01:00
uint8_t lcd_status_message_level ;
2016-03-13 07:38:55 +01:00
char lcd_status_message [ 3 * ( LCD_WIDTH ) + 1 ] = WELCOME_MSG ; // worst case is kana with up to 3*LCD_WIDTH+1
2011-12-12 19:34:37 +01:00
2015-07-31 07:26:53 +02:00
# if ENABLED(DOGLCD)
2015-03-28 04:29:05 +01:00
# include "dogm_lcd_implementation.h"
2013-03-19 20:59:21 +01:00
# else
2015-03-28 04:29:05 +01:00
# include "ultralcd_implementation_hitachi_HD44780.h"
2013-03-19 20:59:21 +01:00
# endif
2011-12-12 19:34:37 +01:00
2015-03-28 04:29:05 +01:00
// The main status screen
2012-12-12 11:47:03 +01:00
static void lcd_status_screen ( ) ;
2015-03-28 04:29:05 +01:00
2016-06-11 23:12:00 +02:00
millis_t next_lcd_update_ms ;
enum LCDViewAction {
LCDVIEW_NONE ,
LCDVIEW_REDRAW_NOW ,
LCDVIEW_CALL_REDRAW_NEXT ,
LCDVIEW_CLEAR_CALL_REDRAW ,
LCDVIEW_CALL_NO_REDRAW
} ;
uint8_t lcdDrawUpdate = LCDVIEW_CLEAR_CALL_REDRAW ; // Set when the LCD needs to draw, decrements after every draw. Set to 2 in LCD routines so the LCD gets at least 1 full redraw (first redraw is partial)
2015-07-31 07:26:53 +02:00
# if ENABLED(ULTIPANEL)
2015-03-28 04:29:05 +01:00
2016-06-11 23:12:00 +02:00
// place-holders for Ki and Kd edits
float raw_Ki , raw_Kd ;
/**
* REVERSE_MENU_DIRECTION
*
* To reverse the menu direction we need a general way to reverse
* the direction of the encoder everywhere . So encoderDirection is
* added to allow the encoder to go the other way .
*
* This behavior is limited to scrolling Menus and SD card listings ,
* and is disabled in other contexts .
*/
# if ENABLED(REVERSE_MENU_DIRECTION)
int8_t encoderDirection = 1 ;
# define ENCODER_DIRECTION_NORMAL() (encoderDirection = 1)
# define ENCODER_DIRECTION_MENUS() (encoderDirection = -1)
# else
# define ENCODER_DIRECTION_NORMAL() ;
# define ENCODER_DIRECTION_MENUS() ;
# endif
int8_t encoderDiff ; // updated from interrupt context and added to encoderPosition every LCD update
millis_t manual_move_start_time = 0 ;
2016-06-13 01:51:28 +02:00
int8_t manual_move_axis = ( int8_t ) NO_AXIS ;
# if EXTRUDERS > 1
int8_t manual_move_e_index = 0 ;
# else
# define manual_move_e_index 0
# endif
2016-06-11 23:12:00 +02:00
bool encoderRateMultiplierEnabled ;
int32_t lastEncoderMovementMillis ;
2015-03-31 01:50:05 +02:00
# if HAS_POWER_SWITCH
extern bool powersupply ;
# endif
2015-07-23 00:14:40 +02:00
const float manual_feedrate [ ] = MANUAL_FEEDRATE ;
2015-03-28 04:29:05 +01:00
static void lcd_main_menu ( ) ;
static void lcd_tune_menu ( ) ;
static void lcd_prepare_menu ( ) ;
static void lcd_move_menu ( ) ;
static void lcd_control_menu ( ) ;
static void lcd_control_temperature_menu ( ) ;
static void lcd_control_temperature_preheat_pla_settings_menu ( ) ;
static void lcd_control_temperature_preheat_abs_settings_menu ( ) ;
static void lcd_control_motion_menu ( ) ;
static void lcd_control_volumetric_menu ( ) ;
2015-09-11 11:18:42 +02:00
2016-06-30 11:24:29 +02:00
# if ENABLED(LCD_INFO_MENU)
# if ENABLED(PRINTCOUNTER)
static void lcd_info_stats_menu ( ) ;
# endif
static void lcd_info_thermistors_menu ( ) ;
static void lcd_info_board_menu ( ) ;
static void lcd_info_menu ( ) ;
2016-04-28 18:57:21 +02:00
# endif // LCD_INFO_MENU
# if ENABLED(FILAMENT_CHANGE_FEATURE)
static void lcd_filament_change_option_menu ( ) ;
static void lcd_filament_change_init_message ( ) ;
static void lcd_filament_change_unload_message ( ) ;
static void lcd_filament_change_insert_message ( ) ;
static void lcd_filament_change_load_message ( ) ;
static void lcd_filament_change_extrude_message ( ) ;
static void lcd_filament_change_resume_message ( ) ;
# endif
2016-06-30 11:24:29 +02:00
2016-05-31 20:47:02 +02:00
# if HAS_LCD_CONTRAST
2015-03-28 04:29:05 +01:00
static void lcd_set_contrast ( ) ;
2013-12-08 21:34:56 +01:00
# endif
2015-09-11 11:18:42 +02:00
2015-07-31 07:26:53 +02:00
# if ENABLED(FWRETRACT)
2015-03-28 04:29:05 +01:00
static void lcd_control_retract_menu ( ) ;
2013-09-23 23:25:11 +02:00
# endif
2015-03-28 04:29:05 +01:00
2015-07-31 07:26:53 +02:00
# if ENABLED(DELTA_CALIBRATION_MENU)
2015-03-28 04:29:05 +01:00
static void lcd_delta_calibrate_menu ( ) ;
2013-12-08 21:34:56 +01:00
# endif
2015-03-28 04:29:05 +01:00
2015-07-31 07:26:53 +02:00
# if ENABLED(MANUAL_BED_LEVELING)
2015-03-28 04:29:05 +01:00
# include "mesh_bed_leveling.h"
2013-09-23 23:25:11 +02:00
# endif
2012-12-12 11:47:03 +01:00
2016-06-11 23:12:00 +02:00
// Function pointer to menu functions.
2016-06-11 23:19:17 +02:00
typedef void ( * screenFunc_t ) ( ) ;
2016-06-11 23:12:00 +02:00
// Different types of actions that can be used in menu items.
2016-04-03 06:12:18 +02:00
static void menu_action_back ( ) ;
2016-06-11 23:19:17 +02:00
static void menu_action_submenu ( screenFunc_t data ) ;
2015-03-28 04:29:05 +01:00
static void menu_action_gcode ( const char * pgcode ) ;
2016-06-11 23:19:17 +02:00
static void menu_action_function ( screenFunc_t data ) ;
2015-03-28 04:29:05 +01:00
static void menu_action_setting_edit_bool ( const char * pstr , bool * ptr ) ;
static void menu_action_setting_edit_int3 ( const char * pstr , int * ptr , int minValue , int maxValue ) ;
static void menu_action_setting_edit_float3 ( const char * pstr , float * ptr , float minValue , float maxValue ) ;
static void menu_action_setting_edit_float32 ( const char * pstr , float * ptr , float minValue , float maxValue ) ;
static void menu_action_setting_edit_float43 ( const char * pstr , float * ptr , float minValue , float maxValue ) ;
static void menu_action_setting_edit_float5 ( const char * pstr , float * ptr , float minValue , float maxValue ) ;
static void menu_action_setting_edit_float51 ( const char * pstr , float * ptr , float minValue , float maxValue ) ;
static void menu_action_setting_edit_float52 ( const char * pstr , float * ptr , float minValue , float maxValue ) ;
static void menu_action_setting_edit_long5 ( const char * pstr , unsigned long * ptr , unsigned long minValue , unsigned long maxValue ) ;
2016-06-11 23:19:17 +02:00
static void menu_action_setting_edit_callback_bool ( const char * pstr , bool * ptr , screenFunc_t callbackFunc ) ;
static void menu_action_setting_edit_callback_int3 ( const char * pstr , int * ptr , int minValue , int maxValue , screenFunc_t callbackFunc ) ;
static void menu_action_setting_edit_callback_float3 ( const char * pstr , float * ptr , float minValue , float maxValue , screenFunc_t callbackFunc ) ;
static void menu_action_setting_edit_callback_float32 ( const char * pstr , float * ptr , float minValue , float maxValue , screenFunc_t callbackFunc ) ;
static void menu_action_setting_edit_callback_float43 ( const char * pstr , float * ptr , float minValue , float maxValue , screenFunc_t callbackFunc ) ;
static void menu_action_setting_edit_callback_float5 ( const char * pstr , float * ptr , float minValue , float maxValue , screenFunc_t callbackFunc ) ;
static void menu_action_setting_edit_callback_float51 ( const char * pstr , float * ptr , float minValue , float maxValue , screenFunc_t callbackFunc ) ;
static void menu_action_setting_edit_callback_float52 ( const char * pstr , float * ptr , float minValue , float maxValue , screenFunc_t callbackFunc ) ;
static void menu_action_setting_edit_callback_long5 ( const char * pstr , unsigned long * ptr , unsigned long minValue , unsigned long maxValue , screenFunc_t callbackFunc ) ;
2015-03-28 04:29:05 +01:00
2015-09-11 11:18:42 +02:00
# if ENABLED(SDSUPPORT)
static void lcd_sdcard_menu ( ) ;
static void menu_action_sdfile ( const char * filename , char * longFilename ) ;
static void menu_action_sddirectory ( const char * filename , char * longFilename ) ;
# endif
2015-03-28 04:29:05 +01:00
# define ENCODER_FEEDRATE_DEADZONE 10
2015-07-31 07:26:53 +02:00
# if DISABLED(LCD_I2C_VIKI)
2015-03-28 04:29:05 +01:00
# ifndef ENCODER_STEPS_PER_MENU_ITEM
# define ENCODER_STEPS_PER_MENU_ITEM 5
# endif
# ifndef ENCODER_PULSES_PER_STEP
# define ENCODER_PULSES_PER_STEP 1
# endif
# else
# ifndef ENCODER_STEPS_PER_MENU_ITEM
# define ENCODER_STEPS_PER_MENU_ITEM 2 // VIKI LCD rotary encoder uses a different number of steps per rotation
# endif
# ifndef ENCODER_PULSES_PER_STEP
# define ENCODER_PULSES_PER_STEP 1
# endif
# endif
2012-12-12 11:47:03 +01:00
2015-03-16 06:02:33 +01:00
2015-03-28 04:29:05 +01:00
/* Helper macros for menus */
2015-03-16 06:02:33 +01:00
/**
2016-07-04 00:12:21 +02:00
* START_SCREEN generates the init code for a screen function
2016-06-30 11:24:29 +02:00
*
* encoderLine is the position based on the encoder
2016-07-09 00:08:56 +02:00
* encoderTopLine is the top menu line to display
2016-07-09 21:26:20 +02:00
* _lcdLineNr is the index of the LCD line ( e . g . , 0 - 3 )
* _menuLineNr is the menu item to draw and process
* _thisItemNr is the index of each MENU_ITEM or STATIC_ITEM
2015-03-16 06:02:33 +01:00
*/
2016-07-09 00:08:56 +02:00
# define _START_SCREEN(CODE) \
2016-03-09 10:04:24 +01:00
ENCODER_DIRECTION_MENUS ( ) ; \
2015-03-28 04:29:05 +01:00
encoderRateMultiplierEnabled = false ; \
if ( encoderPosition > 0x8000 ) encoderPosition = 0 ; \
2016-07-09 21:25:53 +02:00
int8_t encoderLine = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM ; \
2016-07-09 00:08:56 +02:00
NOMORE ( encoderTopLine , encoderLine ) ; \
2016-07-09 21:26:20 +02:00
int8_t _menuLineNr = encoderTopLine , _thisItemNr ; \
2016-07-04 00:12:21 +02:00
CODE ; \
2016-07-09 21:26:20 +02:00
for ( int8_t _lcdLineNr = 0 ; _lcdLineNr < LCD_HEIGHT ; _lcdLineNr + + , _menuLineNr + + ) { \
_thisItemNr = 0 ;
2015-03-28 04:29:05 +01:00
2016-04-30 11:51:18 +02:00
# define START_SCREEN() _START_SCREEN(NOOP)
2016-07-04 00:12:21 +02:00
/**
* START_MENU generates the init code for a menu function
*
* wasClicked indicates the controller was clicked
*/
# define START_MENU() _START_SCREEN(bool wasClicked = LCD_CLICKED)
2015-03-28 04:29:05 +01:00
/**
* MENU_ITEM generates draw & handler code for a menu item , potentially calling :
*
* lcd_implementation_drawmenu_ [ type ] ( sel , row , label , arg3 . . . )
* menu_action_ [ type ] ( arg3 . . . )
*
* Examples :
2016-04-03 06:12:18 +02:00
* MENU_ITEM ( back , MSG_WATCH )
* lcd_implementation_drawmenu_back ( sel , row , PSTR ( MSG_WATCH ) )
* menu_action_back ( )
2015-03-28 04:29:05 +01:00
*
* MENU_ITEM ( function , MSG_PAUSE_PRINT , lcd_sdcard_pause )
* lcd_implementation_drawmenu_function ( sel , row , PSTR ( MSG_PAUSE_PRINT ) , lcd_sdcard_pause )
* menu_action_function ( lcd_sdcard_pause )
*
2015-04-14 02:17:36 +02:00
* MENU_ITEM_EDIT ( int3 , MSG_SPEED , & feedrate_multiplier , 10 , 999 )
* MENU_ITEM ( setting_edit_int3 , MSG_SPEED , PSTR ( MSG_SPEED ) , & feedrate_multiplier , 10 , 999 )
* lcd_implementation_drawmenu_setting_edit_int3 ( sel , row , PSTR ( MSG_SPEED ) , PSTR ( MSG_SPEED ) , & feedrate_multiplier , 10 , 999 )
* menu_action_setting_edit_int3 ( PSTR ( MSG_SPEED ) , & feedrate_multiplier , 10 , 999 )
2015-03-28 04:29:05 +01:00
*
*/
2016-07-09 21:26:20 +02:00
# define _MENU_ITEM_PART_1(TYPE, LABEL, ARGS...) \
if ( _menuLineNr = = _thisItemNr ) { \
2015-03-16 06:02:33 +01:00
if ( lcdDrawUpdate ) \
2016-07-09 21:26:20 +02:00
lcd_implementation_drawmenu_ # # TYPE ( encoderLine = = _thisItemNr , _lcdLineNr , PSTR ( LABEL ) , # # ARGS ) ; \
if ( wasClicked & & encoderLine = = _thisItemNr ) { \
2016-04-12 08:28:20 +02:00
lcd_quick_feedback ( )
2016-07-09 21:26:20 +02:00
# define _MENU_ITEM_PART_2(TYPE, ARGS...) \
menu_action_ # # TYPE ( ARGS ) ; \
2015-02-20 11:17:16 +01:00
return ; \
} \
} \
2016-07-09 21:26:20 +02:00
_thisItemNr + +
2016-04-12 08:28:20 +02:00
2016-07-09 21:26:20 +02:00
# define MENU_ITEM(TYPE, LABEL, ARGS...) do { \
_MENU_ITEM_PART_1 ( TYPE , LABEL , # # ARGS ) ; \
_MENU_ITEM_PART_2 ( TYPE , # # ARGS ) ; \
2016-04-12 08:28:20 +02:00
} while ( 0 )
2015-03-28 04:29:05 +01:00
2016-06-30 11:24:29 +02:00
// Used to print static text with no visible cursor.
2016-07-09 21:26:20 +02:00
# define STATIC_ITEM(LABEL, ARGS...) \
if ( _menuLineNr = = _thisItemNr ) { \
if ( encoderLine = = _thisItemNr & & _thisItemNr < LCD_HEIGHT - 1 ) { \
2016-06-30 11:24:29 +02:00
encoderPosition + = ENCODER_STEPS_PER_MENU_ITEM ; \
2016-07-08 23:02:59 +02:00
lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT ; \
} \
2016-06-30 11:24:29 +02:00
if ( lcdDrawUpdate ) \
2016-07-09 21:26:20 +02:00
lcd_implementation_drawmenu_static ( _lcdLineNr , PSTR ( LABEL ) , # # ARGS ) ; \
2016-06-30 11:24:29 +02:00
} \
2016-07-09 21:26:20 +02:00
_thisItemNr + +
2016-06-30 11:24:29 +02:00
2016-07-09 21:26:20 +02:00
/**
*
* END_SCREEN Closing code for a screen having only static items .
* Do simplified scrolling of the entire screen .
*
* END_MENU Closing code for a screen with menu items .
* Scroll as - needed to keep the selected line in view .
*
* At this point _thisItemNr equals the total number of items .
*
*/
// Simple-scroll by using encoderLine as encoderTopLine
2016-07-04 00:12:21 +02:00
# define END_SCREEN() \
2016-07-09 00:08:56 +02:00
} \
2016-07-09 21:26:20 +02:00
NOMORE ( encoderLine , _thisItemNr - LCD_HEIGHT ) ; \
2016-07-09 00:08:56 +02:00
NOLESS ( encoderLine , 0 ) ; \
encoderPosition = encoderLine * ( ENCODER_STEPS_PER_MENU_ITEM ) ; \
if ( encoderTopLine ! = encoderLine ) { \
encoderTopLine = encoderLine ; \
lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT ; \
}
2016-07-04 00:12:21 +02:00
2016-07-09 21:26:20 +02:00
// Scroll through menu items, scrolling as-needed to stay in view
2016-07-09 00:08:56 +02:00
# define END_MENU() \
} \
2016-07-09 21:26:20 +02:00
if ( encoderLine > = _thisItemNr ) { \
encoderLine = _thisItemNr - 1 ; \
2016-07-09 00:08:56 +02:00
encoderPosition = encoderLine * ( ENCODER_STEPS_PER_MENU_ITEM ) ; \
} \
if ( encoderLine > = encoderTopLine + LCD_HEIGHT ) { \
encoderTopLine = encoderLine - ( LCD_HEIGHT - 1 ) ; \
lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT ; \
}
2016-07-04 00:12:21 +02:00
2015-07-31 07:26:53 +02:00
# if ENABLED(ENCODER_RATE_MULTIPLIER)
2015-04-28 04:11:25 +02:00
//#define ENCODER_RATE_MULTIPLIER_DEBUG // If defined, output the encoder steps per second value
2015-03-28 04:29:05 +01:00
/**
* MENU_MULTIPLIER_ITEM generates drawing and handling code for a multiplier menu item
*/
# define MENU_MULTIPLIER_ITEM(type, label, args...) do { \
2016-04-12 08:28:20 +02:00
_MENU_ITEM_PART_1 ( type , label , # # args ) ; \
encoderRateMultiplierEnabled = true ; \
lastEncoderMovementMillis = 0 ; \
_MENU_ITEM_PART_2 ( type , # # args ) ; \
} while ( 0 )
2015-03-28 04:29:05 +01:00
# endif //ENCODER_RATE_MULTIPLIER
2016-07-09 21:26:20 +02:00
# define MENU_ITEM_DUMMY() do { _thisItemNr++; } while(0)
2015-03-28 04:29:05 +01:00
# define MENU_ITEM_EDIT(type, label, args...) MENU_ITEM(setting_edit_ ## type, label, PSTR(label), ## args)
# define MENU_ITEM_EDIT_CALLBACK(type, label, args...) MENU_ITEM(setting_edit_callback_ ## type, label, PSTR(label), ## args)
2015-07-31 07:26:53 +02:00
# if ENABLED(ENCODER_RATE_MULTIPLIER)
2015-03-28 04:29:05 +01:00
# define MENU_MULTIPLIER_ITEM_EDIT(type, label, args...) MENU_MULTIPLIER_ITEM(setting_edit_ ## type, label, PSTR(label), ## args)
# define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(type, label, args...) MENU_MULTIPLIER_ITEM(setting_edit_callback_ ## type, label, PSTR(label), ## args)
# else //!ENCODER_RATE_MULTIPLIER
# define MENU_MULTIPLIER_ITEM_EDIT(type, label, args...) MENU_ITEM(setting_edit_ ## type, label, PSTR(label), ## args)
# define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(type, label, args...) MENU_ITEM(setting_edit_callback_ ## type, label, PSTR(label), ## args)
# endif //!ENCODER_RATE_MULTIPLIER
/** Used variables to keep track of the menu */
2015-05-05 11:03:20 +02:00
volatile uint8_t buttons ; //the last checked buttons in a bit array.
2015-07-31 07:26:53 +02:00
# if ENABLED(REPRAPWORLD_KEYPAD)
2015-05-05 11:03:20 +02:00
volatile uint8_t buttons_reprapworld_keypad ; // to store the keypad shift register values
2015-03-28 04:29:05 +01:00
# endif
2015-10-03 08:08:58 +02:00
2015-07-31 07:26:53 +02:00
# if ENABLED(LCD_HAS_SLOW_BUTTONS)
2015-03-28 04:29:05 +01:00
volatile uint8_t slow_buttons ; // Bits of the pressed buttons.
# endif
2016-07-09 00:08:56 +02:00
int8_t encoderTopLine ; /* scroll offset in the current menu */
2015-04-13 03:07:08 +02:00
millis_t next_button_update_ms ;
2015-03-28 04:29:05 +01:00
uint8_t lastEncoderBits ;
2016-04-21 21:40:22 +02:00
uint32_t encoderPosition ;
2015-08-01 01:40:50 +02:00
# if PIN_EXISTS(SD_DETECT)
2015-09-14 01:43:14 +02:00
uint8_t lcd_sd_status ;
2015-03-28 04:29:05 +01:00
# endif
2016-06-11 23:12:00 +02:00
typedef struct {
2016-06-11 23:19:17 +02:00
screenFunc_t menu_function ;
2016-04-03 06:12:18 +02:00
uint32_t encoder_position ;
2016-06-11 23:12:00 +02:00
} menuPosition ;
2016-04-03 06:12:18 +02:00
2016-06-11 23:19:17 +02:00
screenFunc_t currentScreen = lcd_status_screen ; // pointer to the currently active menu handler
2016-04-03 06:12:18 +02:00
2016-06-11 23:19:17 +02:00
menuPosition screen_history [ 10 ] ;
uint8_t screen_history_depth = 0 ;
2016-04-03 01:09:56 +02:00
2016-06-11 23:12:00 +02:00
bool ignore_click = false ;
bool wait_for_unclick ;
bool defer_return_to_status = false ;
2016-04-03 01:09:56 +02:00
2016-06-11 23:12:00 +02:00
// Variables used when editing values.
const char * editLabel ;
void * editValue ;
int32_t minEditValue , maxEditValue ;
2016-06-11 23:19:17 +02:00
screenFunc_t callbackFunc ; // call this after editing
2012-12-12 11:47:03 +01:00
2016-06-11 23:12:00 +02:00
/**
* General function to go directly to a menu
* Remembers the previous position
*/
2016-06-11 23:19:17 +02:00
static void lcd_goto_screen ( screenFunc_t screen , const bool feedback = false , const uint32_t encoder = 0 ) {
if ( currentScreen ! = screen ) {
currentScreen = screen ;
2016-06-11 23:12:00 +02:00
lcdDrawUpdate = LCDVIEW_CLEAR_CALL_REDRAW ;
2016-07-11 02:28:58 +02:00
encoderPosition = encoder ;
if ( feedback ) lcd_quick_feedback ( ) ;
2016-06-11 23:19:17 +02:00
if ( screen = = lcd_status_screen ) {
2016-06-11 23:12:00 +02:00
defer_return_to_status = false ;
2016-06-11 23:19:17 +02:00
screen_history_depth = 0 ;
2016-06-11 23:12:00 +02:00
}
# if ENABLED(LCD_PROGRESS_BAR)
// For LCD_PROGRESS_BAR re-initialize custom characters
2016-06-11 23:19:17 +02:00
lcd_set_custom_characters ( screen = = lcd_status_screen ) ;
2016-06-11 23:12:00 +02:00
# endif
}
}
Allow Edit menu to call fn after edit; Fix PID Ki and Kd display in menus; Actually use changed PID and Max Accel values
Add new 'callback' edit-menu types that call a function after the edit is done. Use this to display and edit Ki and Kd correctly (removing the scaling first and reapplying it after). Also use it to reset maximum stepwise acceleration rates, after updating mm/s^2 rates via menus. (Previously, changes did nothing to affect planner unless saved back to EEPROM, and the machine reset).
Add calls to updatePID() so that PID loop uses updated values whether set by gcode (it already did this), or by restoring defaults, or loading from EEPROM (it didn't do those last two). Similarly, update the maximum step/s^2 accel rates when the mm/s^2 values are changed - whether by menu edits, restore defaults, or EEPROM read.
Refactor the acceleration rate update logic, and the PID scaling logic, into new functions that can be called from wherever, including the callbacks.
Add menu items to allow the z jerk and e jerk to be viewed/edited in the Control->Motion menu, as per xy jerk.
Conflicts:
Marlin/language.h
2013-03-19 15:05:11 +01:00
2016-06-11 23:19:17 +02:00
static void lcd_return_to_status ( ) { lcd_goto_screen ( lcd_status_screen ) ; }
2012-12-12 11:47:03 +01:00
2016-06-11 23:12:00 +02:00
inline void lcd_save_previous_menu ( ) {
2016-06-11 23:19:17 +02:00
if ( screen_history_depth < COUNT ( screen_history ) ) {
screen_history [ screen_history_depth ] . menu_function = currentScreen ;
2016-07-11 02:28:58 +02:00
screen_history [ screen_history_depth ] . encoder_position = encoderPosition ;
2016-06-11 23:19:17 +02:00
+ + screen_history_depth ;
2016-04-05 23:05:41 +02:00
}
2014-12-18 16:30:05 +01:00
}
2016-03-09 12:52:05 +01:00
2016-06-11 23:12:00 +02:00
static void lcd_goto_previous_menu ( bool feedback = false ) {
2016-06-11 23:19:17 +02:00
if ( screen_history_depth > 0 ) {
- - screen_history_depth ;
2016-07-11 02:28:58 +02:00
lcd_goto_screen (
screen_history [ screen_history_depth ] . menu_function ,
feedback ,
screen_history [ screen_history_depth ] . encoder_position
2016-06-11 23:12:00 +02:00
) ;
}
else
lcd_return_to_status ( ) ;
2016-04-03 06:12:18 +02:00
}
2016-06-11 23:12:00 +02:00
void lcd_ignore_click ( bool b ) {
ignore_click = b ;
wait_for_unclick = false ;
2016-04-03 06:12:18 +02:00
}
2016-06-11 23:12:00 +02:00
# endif // ULTIPANEL
2016-03-09 12:52:05 +01:00
2015-04-28 04:11:25 +02:00
/**
*
* " Info Screen "
*
* This is very display - dependent , so the lcd implementation draws this .
*/
2015-04-04 22:02:24 +02:00
static void lcd_status_screen ( ) {
2016-06-11 23:12:00 +02:00
# if ENABLED(ULTIPANEL)
ENCODER_DIRECTION_NORMAL ( ) ;
encoderRateMultiplierEnabled = false ;
# endif
2015-03-31 03:00:54 +02:00
2015-07-31 07:26:53 +02:00
# if ENABLED(LCD_PROGRESS_BAR)
2015-04-13 03:07:08 +02:00
millis_t ms = millis ( ) ;
2015-08-03 21:30:37 +02:00
# if DISABLED(PROGRESS_MSG_ONCE)
2016-04-11 00:55:12 +02:00
if ( ELAPSED ( ms , progress_bar_ms + PROGRESS_BAR_MSG_TIME + PROGRESS_BAR_BAR_TIME ) ) {
2015-04-25 07:16:09 +02:00
progress_bar_ms = ms ;
2014-12-28 07:26:14 +01:00
}
# endif
# if PROGRESS_MSG_EXPIRE > 0
2015-03-31 03:00:54 +02:00
// Handle message expire
2015-04-25 06:51:10 +02:00
if ( expire_status_ms > 0 ) {
2015-09-05 02:40:12 +02:00
# if ENABLED(SDSUPPORT)
if ( card . isFileOpen ( ) ) {
2015-03-31 03:00:54 +02:00
// Expire the message when printing is active
2015-09-05 02:40:12 +02:00
if ( IS_SD_PRINTING ) {
2016-04-11 00:55:12 +02:00
if ( ELAPSED ( ms , expire_status_ms ) ) {
2015-09-05 02:40:12 +02:00
lcd_status_message [ 0 ] = ' \0 ' ;
expire_status_ms = 0 ;
}
}
else {
expire_status_ms + = LCD_UPDATE_INTERVAL ;
2014-12-28 07:26:14 +01:00
}
}
else {
2015-09-05 02:40:12 +02:00
expire_status_ms = 0 ;
2014-12-28 07:26:14 +01:00
}
2015-09-05 02:40:12 +02:00
# else
2015-04-25 06:51:10 +02:00
expire_status_ms = 0 ;
2015-09-05 02:40:12 +02:00
# endif //SDSUPPORT
2014-12-28 07:26:14 +01:00
}
# endif
# endif //LCD_PROGRESS_BAR
2015-04-11 13:45:04 +02:00
lcd_implementation_status_screen ( ) ;
2015-01-10 03:16:56 +01:00
2015-07-31 07:26:53 +02:00
# if ENABLED(ULTIPANEL)
2014-11-25 01:56:37 +01:00
2014-11-25 02:12:08 +01:00
bool current_click = LCD_CLICKED ;
if ( ignore_click ) {
2015-04-11 13:45:04 +02:00
if ( wait_for_unclick ) {
2015-04-11 13:56:08 +02:00
if ( ! current_click )
2015-04-11 13:45:04 +02:00
ignore_click = wait_for_unclick = false ;
2015-04-11 13:56:08 +02:00
else
2015-04-11 13:45:04 +02:00
current_click = false ;
}
else if ( current_click ) {
lcd_quick_feedback ( ) ;
wait_for_unclick = true ;
current_click = false ;
}
2014-11-25 02:12:08 +01:00
}
2015-04-11 13:45:04 +02:00
if ( current_click ) {
2016-06-11 23:19:17 +02:00
lcd_goto_screen ( lcd_main_menu , true ) ;
2015-04-11 13:45:04 +02:00
lcd_implementation_init ( // to maybe revive the LCD if static electricity killed it.
2016-06-11 23:12:00 +02:00
# if ENABLED(LCD_PROGRESS_BAR) && ENABLED(ULTIPANEL)
2016-06-11 23:19:17 +02:00
currentScreen = = lcd_status_screen
2014-12-28 07:26:14 +01:00
# endif
2015-04-11 13:45:04 +02:00
) ;
2015-07-31 07:26:53 +02:00
# if ENABLED(FILAMENT_LCD_DISPLAY)
2015-04-13 03:07:08 +02:00
previous_lcd_status_ms = millis ( ) ; // get status message to show up for a while
2015-04-11 13:45:04 +02:00
# endif
2012-12-12 11:47:03 +01:00
}
2013-06-07 00:49:25 +02:00
2015-07-31 07:26:53 +02:00
# if ENABLED(ULTIPANEL_FEEDMULTIPLY)
2016-04-09 05:47:12 +02:00
int new_frm = feedrate_multiplier + ( int32_t ) encoderPosition ;
2015-04-11 13:45:04 +02:00
// Dead zone at 100% feedrate
2016-04-05 23:06:52 +02:00
if ( ( feedrate_multiplier < 100 & & new_frm > 100 ) | | ( feedrate_multiplier > 100 & & new_frm < 100 ) ) {
2015-04-14 02:17:36 +02:00
feedrate_multiplier = 100 ;
2016-04-05 23:06:52 +02:00
encoderPosition = 0 ;
2015-04-11 13:45:04 +02:00
}
2016-04-05 23:06:52 +02:00
else if ( feedrate_multiplier = = 100 ) {
2016-04-09 05:47:12 +02:00
if ( ( int32_t ) encoderPosition > ENCODER_FEEDRATE_DEADZONE ) {
feedrate_multiplier + = ( int32_t ) encoderPosition - ( ENCODER_FEEDRATE_DEADZONE ) ;
2015-04-11 13:56:08 +02:00
encoderPosition = 0 ;
}
2016-04-09 05:47:12 +02:00
else if ( ( int32_t ) encoderPosition < - ( ENCODER_FEEDRATE_DEADZONE ) ) {
feedrate_multiplier + = ( int32_t ) encoderPosition + ENCODER_FEEDRATE_DEADZONE ;
2015-04-11 13:56:08 +02:00
encoderPosition = 0 ;
}
2015-04-11 13:45:04 +02:00
}
2015-04-11 13:56:08 +02:00
else {
2016-04-05 23:06:52 +02:00
feedrate_multiplier = new_frm ;
2013-06-07 00:49:25 +02:00
encoderPosition = 0 ;
2015-04-11 13:45:04 +02:00
}
# endif // ULTIPANEL_FEEDMULTIPLY
2015-04-14 02:17:36 +02:00
feedrate_multiplier = constrain ( feedrate_multiplier , 10 , 999 ) ;
2013-06-07 00:49:25 +02:00
2015-04-11 13:45:04 +02:00
# endif //ULTIPANEL
2011-12-12 19:34:37 +01:00
}
2016-07-10 04:50:45 +02:00
/**
*
* draw the kill screen
*
*/
void kill_screen ( const char * lcd_msg ) {
lcd_init ( ) ;
lcd_setalertstatuspgm ( lcd_msg ) ;
# if ENABLED(DOGLCD)
u8g . firstPage ( ) ;
do {
lcd_kill_screen ( ) ;
} while ( u8g . nextPage ( ) ) ;
# else
lcd_kill_screen ( ) ;
# endif
}
2015-07-31 07:26:53 +02:00
# if ENABLED(ULTIPANEL)
2014-12-28 07:26:14 +01:00
2016-06-11 23:12:00 +02:00
inline void line_to_current ( AxisEnum axis ) {
# if ENABLED(DELTA)
calculate_delta ( current_position ) ;
planner . buffer_line ( delta [ X_AXIS ] , delta [ Y_AXIS ] , delta [ Z_AXIS ] , current_position [ E_AXIS ] , manual_feedrate [ axis ] / 60 , active_extruder ) ;
# else // !DELTA
planner . buffer_line ( current_position [ X_AXIS ] , current_position [ Y_AXIS ] , current_position [ Z_AXIS ] , current_position [ E_AXIS ] , manual_feedrate [ axis ] / 60 , active_extruder ) ;
# endif // !DELTA
2016-05-30 01:56:39 +02:00
}
2011-12-12 19:34:37 +01:00
2016-06-11 23:12:00 +02:00
# if ENABLED(SDSUPPORT)
2015-09-05 02:40:12 +02:00
2016-06-11 23:12:00 +02:00
static void lcd_sdcard_pause ( ) {
card . pauseSDPrint ( ) ;
print_job_timer . pause ( ) ;
}
2015-09-05 02:40:12 +02:00
2016-06-11 23:12:00 +02:00
static void lcd_sdcard_resume ( ) {
card . startFileprint ( ) ;
print_job_timer . start ( ) ;
}
2011-12-12 19:34:37 +01:00
2016-06-11 23:12:00 +02:00
static void lcd_sdcard_stop ( ) {
2016-06-18 03:27:14 +02:00
card . stopSDPrint ( ) ;
2016-06-11 23:12:00 +02:00
clear_command_queue ( ) ;
2016-07-06 21:00:28 +02:00
quickstop_stepper ( ) ;
2016-06-11 23:12:00 +02:00
print_job_timer . stop ( ) ;
thermalManager . autotempShutdown ( ) ;
2016-07-06 18:17:50 +02:00
wait_for_heatup = false ;
2016-06-11 23:12:00 +02:00
lcd_setstatus ( MSG_PRINT_ABORTED , true ) ;
}
2015-04-28 04:11:25 +02:00
2016-06-11 23:12:00 +02:00
# endif //SDSUPPORT
2015-02-22 02:38:56 +01:00
2016-06-11 23:12:00 +02:00
/**
*
* " Main " menu
*
*/
static void lcd_main_menu ( ) {
START_MENU ( ) ;
MENU_ITEM ( back , MSG_WATCH ) ;
if ( planner . movesplanned ( ) | | IS_SD_PRINTING ) {
MENU_ITEM ( submenu , MSG_TUNE , lcd_tune_menu ) ;
}
else {
MENU_ITEM ( submenu , MSG_PREPARE , lcd_prepare_menu ) ;
# if ENABLED(DELTA_CALIBRATION_MENU)
MENU_ITEM ( submenu , MSG_DELTA_CALIBRATE , lcd_delta_calibrate_menu ) ;
# endif
}
MENU_ITEM ( submenu , MSG_CONTROL , lcd_control_menu ) ;
# if ENABLED(SDSUPPORT)
if ( card . cardOK ) {
if ( card . isFileOpen ( ) ) {
if ( card . sdprinting )
MENU_ITEM ( function , MSG_PAUSE_PRINT , lcd_sdcard_pause ) ;
else
MENU_ITEM ( function , MSG_RESUME_PRINT , lcd_sdcard_resume ) ;
MENU_ITEM ( function , MSG_STOP_PRINT , lcd_sdcard_stop ) ;
}
else {
MENU_ITEM ( submenu , MSG_CARD_MENU , lcd_sdcard_menu ) ;
# if !PIN_EXISTS(SD_DETECT)
MENU_ITEM ( gcode , MSG_CNG_SDCARD , PSTR ( " M21 " ) ) ; // SD-card changed by user
# endif
}
2015-02-22 02:38:56 +01:00
}
else {
2016-06-11 23:12:00 +02:00
MENU_ITEM ( submenu , MSG_NO_CARD , lcd_sdcard_menu ) ;
2015-08-01 01:40:50 +02:00
# if !PIN_EXISTS(SD_DETECT)
2016-06-11 23:12:00 +02:00
MENU_ITEM ( gcode , MSG_INIT_SDCARD , PSTR ( " M21 " ) ) ; // Manually initialize the SD-card via user interface
2015-02-22 02:38:56 +01:00
# endif
}
2016-06-11 23:12:00 +02:00
# endif //SDSUPPORT
2016-04-19 05:39:15 +02:00
2016-06-30 11:24:29 +02:00
# if ENABLED(LCD_INFO_MENU)
MENU_ITEM ( submenu , MSG_INFO_MENU , lcd_info_menu ) ;
# endif
2016-06-11 23:12:00 +02:00
END_MENU ( ) ;
2014-12-18 16:30:05 +01:00
}
2016-03-11 06:35:44 +01:00
2016-06-11 23:12:00 +02:00
/**
*
* " Tune " submenu items
*
*/
Add the socalled "Babystepping" feature.
It is a realtime control over the head position via the LCD menu system that works _while_ printing.
Using it, one can e.g. tune the z-position in realtime, while printing the first layer.
Also, lost steps can be manually added/removed, but thats not the prime feature.
Stuff is placed into the Tune->Babystep *
It is not possible to have realtime control via gcode sending due to the buffering, so I did not include a gcode yet. However, it could be added, but it movements will not be realtime then.
Historically, a very similar thing was implemented for the "Kaamermaker" project, while Joris was babysitting his offspring, hence the name.
say goodby to fuddling around with the z-axis.
2013-10-06 21:14:51 +02:00
2016-06-11 23:12:00 +02:00
/**
* Set the home offset based on the current_position
*/
void lcd_set_home_offsets ( ) {
// M428 Command
enqueue_and_echo_commands_P ( PSTR ( " M428 " ) ) ;
lcd_return_to_status ( ) ;
}
2015-12-04 01:31:22 +01:00
2016-06-11 23:12:00 +02:00
# if ENABLED(BABYSTEPPING)
2016-04-15 18:27:18 +02:00
2016-06-13 11:28:16 +02:00
long babysteps_done = 0 ;
2015-12-04 01:31:22 +01:00
2016-06-11 23:12:00 +02:00
static void _lcd_babystep ( const AxisEnum axis , const char * msg ) {
2016-07-11 02:53:11 +02:00
if ( LCD_CLICKED ) { lcd_goto_previous_menu ( true ) ; return ; }
2016-06-11 23:12:00 +02:00
ENCODER_DIRECTION_NORMAL ( ) ;
if ( encoderPosition ) {
2016-06-13 11:28:16 +02:00
int babystep_increment = ( int32_t ) encoderPosition * BABYSTEP_MULTIPLICATOR ;
2016-06-11 23:12:00 +02:00
encoderPosition = 0 ;
lcdDrawUpdate = LCDVIEW_REDRAW_NOW ;
2016-06-13 11:28:16 +02:00
thermalManager . babystep_axis ( axis , babystep_increment ) ;
babysteps_done + = babystep_increment ;
2016-06-11 23:12:00 +02:00
}
2016-06-13 11:28:16 +02:00
if ( lcdDrawUpdate )
lcd_implementation_drawedit ( msg , ftostr43sign (
( ( 1000 * babysteps_done ) / planner . axis_steps_per_mm [ axis ] ) * 0.001f
) ) ;
2016-06-11 23:12:00 +02:00
}
2015-12-04 01:31:22 +01:00
2016-06-11 23:12:00 +02:00
# if ENABLED(BABYSTEP_XY)
static void _lcd_babystep_x ( ) { _lcd_babystep ( X_AXIS , PSTR ( MSG_BABYSTEPPING_X ) ) ; }
static void _lcd_babystep_y ( ) { _lcd_babystep ( Y_AXIS , PSTR ( MSG_BABYSTEPPING_Y ) ) ; }
2016-06-11 23:19:17 +02:00
static void lcd_babystep_x ( ) { babysteps_done = 0 ; lcd_goto_screen ( _lcd_babystep_x ) ; }
static void lcd_babystep_y ( ) { babysteps_done = 0 ; lcd_goto_screen ( _lcd_babystep_y ) ; }
2016-06-11 23:12:00 +02:00
# endif
static void _lcd_babystep_z ( ) { _lcd_babystep ( Z_AXIS , PSTR ( MSG_BABYSTEPPING_Z ) ) ; }
2016-06-11 23:19:17 +02:00
static void lcd_babystep_z ( ) { babysteps_done = 0 ; lcd_goto_screen ( _lcd_babystep_z ) ; }
2015-12-04 01:31:22 +01:00
2016-06-11 23:12:00 +02:00
# endif //BABYSTEPPING
2016-03-24 22:16:09 +01:00
2016-06-11 23:12:00 +02:00
/**
* Watch temperature callbacks
*/
# if ENABLED(THERMAL_PROTECTION_HOTENDS) && WATCH_TEMP_PERIOD > 0
2015-09-12 04:52:01 +02:00
# if TEMP_SENSOR_0 != 0
2016-06-11 23:12:00 +02:00
void watch_temp_callback_E0 ( ) { thermalManager . start_watching_heater ( 0 ) ; }
2015-09-12 04:52:01 +02:00
# endif
2016-06-11 23:12:00 +02:00
# if HOTENDS > 1 && TEMP_SENSOR_1 != 0
void watch_temp_callback_E1 ( ) { thermalManager . start_watching_heater ( 1 ) ; }
# endif // HOTENDS > 1
# if HOTENDS > 2 && TEMP_SENSOR_2 != 0
void watch_temp_callback_E2 ( ) { thermalManager . start_watching_heater ( 2 ) ; }
# endif // HOTENDS > 2
# if HOTENDS > 3 && TEMP_SENSOR_3 != 0
void watch_temp_callback_E3 ( ) { thermalManager . start_watching_heater ( 3 ) ; }
# endif // HOTENDS > 3
# else
2015-09-12 04:52:01 +02:00
# if TEMP_SENSOR_0 != 0
2016-06-11 23:12:00 +02:00
void watch_temp_callback_E0 ( ) { }
2015-09-12 04:52:01 +02:00
# endif
2016-06-11 23:12:00 +02:00
# if HOTENDS > 1 && TEMP_SENSOR_1 != 0
void watch_temp_callback_E1 ( ) { }
# endif // HOTENDS > 1
# if HOTENDS > 2 && TEMP_SENSOR_2 != 0
void watch_temp_callback_E2 ( ) { }
2016-05-27 02:43:20 +02:00
# endif // HOTENDS > 2
2016-06-11 23:12:00 +02:00
# if HOTENDS > 3 && TEMP_SENSOR_3 != 0
void watch_temp_callback_E3 ( ) { }
# endif // HOTENDS > 3
2015-02-22 02:38:56 +01:00
# endif
2015-09-07 02:14:02 +02:00
2016-06-11 23:12:00 +02:00
# if ENABLED(THERMAL_PROTECTION_BED) && WATCH_BED_TEMP_PERIOD > 0
# if TEMP_SENSOR_BED != 0
void watch_temp_callback_bed ( ) { thermalManager . start_watching_bed ( ) ; }
2016-03-06 03:27:45 +01:00
# endif
2016-06-11 23:12:00 +02:00
# else
# if TEMP_SENSOR_BED != 0
void watch_temp_callback_bed ( ) { }
2016-03-06 03:27:45 +01:00
# endif
2015-02-22 02:38:56 +01:00
# endif
2015-09-07 02:14:02 +02:00
2016-06-11 23:12:00 +02:00
/**
*
* " Tune " submenu
*
*/
static void lcd_tune_menu ( ) {
START_MENU ( ) ;
2011-12-12 19:34:37 +01:00
2016-06-11 23:12:00 +02:00
//
// ^ Main
//
MENU_ITEM ( back , MSG_MAIN ) ;
2015-09-11 11:18:42 +02:00
2016-06-11 23:12:00 +02:00
//
// Speed:
//
MENU_ITEM_EDIT ( int3 , MSG_SPEED , & feedrate_multiplier , 10 , 999 ) ;
2014-03-17 18:37:46 +01:00
2016-06-11 23:12:00 +02:00
// Manual bed leveling, Bed Z:
# if ENABLED(MANUAL_BED_LEVELING)
MENU_ITEM_EDIT ( float43 , MSG_BED_Z , & mbl . z_offset , - 1 , 1 ) ;
2015-07-19 21:07:12 +02:00
# endif
2015-01-23 23:13:06 +01:00
2016-06-11 23:12:00 +02:00
//
// Nozzle:
// Nozzle [1-4]:
//
# if HOTENDS == 1
# if TEMP_SENSOR_0 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( int3 , MSG_NOZZLE , & thermalManager . target_temperature [ 0 ] , 0 , HEATER_0_MAXTEMP - 15 , watch_temp_callback_E0 ) ;
# endif
# else //HOTENDS > 1
# if TEMP_SENSOR_0 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( int3 , MSG_NOZZLE MSG_N1 , & thermalManager . target_temperature [ 0 ] , 0 , HEATER_0_MAXTEMP - 15 , watch_temp_callback_E0 ) ;
# endif
# if TEMP_SENSOR_1 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( int3 , MSG_NOZZLE MSG_N2 , & thermalManager . target_temperature [ 1 ] , 0 , HEATER_1_MAXTEMP - 15 , watch_temp_callback_E1 ) ;
2016-04-29 03:18:13 +02:00
# endif
2016-05-27 02:43:20 +02:00
# if HOTENDS > 2
2016-06-11 23:12:00 +02:00
# if TEMP_SENSOR_2 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( int3 , MSG_NOZZLE MSG_N3 , & thermalManager . target_temperature [ 2 ] , 0 , HEATER_2_MAXTEMP - 15 , watch_temp_callback_E2 ) ;
# endif
2016-05-27 02:43:20 +02:00
# if HOTENDS > 3
2016-06-11 23:12:00 +02:00
# if TEMP_SENSOR_3 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( int3 , MSG_NOZZLE MSG_N4 , & thermalManager . target_temperature [ 3 ] , 0 , HEATER_3_MAXTEMP - 15 , watch_temp_callback_E3 ) ;
# endif
# endif // HOTENDS > 3
# endif // HOTENDS > 2
# endif // HOTENDS > 1
//
// Bed:
//
# if TEMP_SENSOR_BED != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( int3 , MSG_BED , & thermalManager . target_temperature_bed , 0 , BED_MAXTEMP - 15 , watch_temp_callback_bed ) ;
# endif
//
// Fan Speed:
//
# if FAN_COUNT > 0
# if HAS_FAN0
# if FAN_COUNT > 1
# define MSG_1ST_FAN_SPEED MSG_FAN_SPEED " 1"
# else
# define MSG_1ST_FAN_SPEED MSG_FAN_SPEED
2016-04-29 03:18:13 +02:00
# endif
2016-06-11 23:12:00 +02:00
MENU_MULTIPLIER_ITEM_EDIT ( int3 , MSG_1ST_FAN_SPEED , & fanSpeeds [ 0 ] , 0 , 255 ) ;
# endif
# if HAS_FAN1
MENU_MULTIPLIER_ITEM_EDIT ( int3 , MSG_FAN_SPEED " 2 " , & fanSpeeds [ 1 ] , 0 , 255 ) ;
2016-04-29 03:18:13 +02:00
# endif
2016-06-11 23:12:00 +02:00
# if HAS_FAN2
MENU_MULTIPLIER_ITEM_EDIT ( int3 , MSG_FAN_SPEED " 3 " , & fanSpeeds [ 2 ] , 0 , 255 ) ;
# endif
# endif // FAN_COUNT > 0
//
// Flow:
// Flow 1:
// Flow 2:
// Flow 3:
// Flow 4:
//
# if EXTRUDERS == 1
MENU_ITEM_EDIT ( int3 , MSG_FLOW , & extruder_multiplier [ 0 ] , 10 , 999 ) ;
# else // EXTRUDERS > 1
MENU_ITEM_EDIT ( int3 , MSG_FLOW , & extruder_multiplier [ active_extruder ] , 10 , 999 ) ;
MENU_ITEM_EDIT ( int3 , MSG_FLOW MSG_N1 , & extruder_multiplier [ 0 ] , 10 , 999 ) ;
MENU_ITEM_EDIT ( int3 , MSG_FLOW MSG_N2 , & extruder_multiplier [ 1 ] , 10 , 999 ) ;
# if EXTRUDERS > 2
MENU_ITEM_EDIT ( int3 , MSG_FLOW MSG_N3 , & extruder_multiplier [ 2 ] , 10 , 999 ) ;
# if EXTRUDERS > 3
MENU_ITEM_EDIT ( int3 , MSG_FLOW MSG_N4 , & extruder_multiplier [ 3 ] , 10 , 999 ) ;
# endif //EXTRUDERS > 3
# endif //EXTRUDERS > 2
# endif //EXTRUDERS > 1
//
// Babystep X:
// Babystep Y:
// Babystep Z:
//
# if ENABLED(BABYSTEPPING)
# if ENABLED(BABYSTEP_XY)
MENU_ITEM ( submenu , MSG_BABYSTEP_X , lcd_babystep_x ) ;
MENU_ITEM ( submenu , MSG_BABYSTEP_Y , lcd_babystep_y ) ;
# endif //BABYSTEP_XY
MENU_ITEM ( submenu , MSG_BABYSTEP_Z , lcd_babystep_z ) ;
2016-04-14 08:40:21 +02:00
# endif
2014-03-17 18:37:46 +01:00
2016-06-11 23:12:00 +02:00
//
// Change filament
//
2016-04-28 18:57:21 +02:00
# if ENABLED(FILAMENT_CHANGE_FEATURE)
2016-06-11 23:12:00 +02:00
MENU_ITEM ( gcode , MSG_FILAMENTCHANGE , PSTR ( " M600 " ) ) ;
2015-09-11 11:18:42 +02:00
# endif
2016-06-11 23:12:00 +02:00
2015-09-11 11:18:42 +02:00
END_MENU ( ) ;
}
2015-03-28 04:29:05 +01:00
2016-06-11 23:12:00 +02:00
/**
*
* " Prepare " submenu items
*
*/
void _lcd_preheat ( int endnum , const float temph , const float tempb , const int fan ) {
if ( temph > 0 ) thermalManager . setTargetHotend ( temph , endnum ) ;
# if TEMP_SENSOR_BED != 0
thermalManager . setTargetBed ( tempb ) ;
2015-09-11 11:18:42 +02:00
# else
2016-06-11 23:12:00 +02:00
UNUSED ( tempb ) ;
2015-07-19 21:07:12 +02:00
# endif
2016-06-11 23:12:00 +02:00
# if FAN_COUNT > 0
# if FAN_COUNT > 1
fanSpeeds [ active_extruder < FAN_COUNT ? active_extruder : 0 ] = fan ;
# else
fanSpeeds [ 0 ] = fan ;
# endif
# else
UNUSED ( fan ) ;
2015-09-11 11:18:42 +02:00
# endif
2016-06-11 23:12:00 +02:00
lcd_return_to_status ( ) ;
2015-09-11 11:18:42 +02:00
}
2016-06-11 23:12:00 +02:00
# if TEMP_SENSOR_0 != 0
2016-07-10 00:20:12 +02:00
void lcd_preheat_pla0 ( ) { _lcd_preheat ( 0 , preheatHotendTemp1 , preheatBedTemp1 , preheatFanSpeed1 ) ; }
void lcd_preheat_abs0 ( ) { _lcd_preheat ( 0 , preheatHotendTemp2 , preheatBedTemp2 , preheatFanSpeed2 ) ; }
2016-03-06 03:27:45 +01:00
# endif
2014-03-17 18:37:46 +01:00
2016-06-11 23:12:00 +02:00
# if HOTENDS > 1
2016-07-10 00:20:12 +02:00
void lcd_preheat_pla1 ( ) { _lcd_preheat ( 1 , preheatHotendTemp1 , preheatBedTemp1 , preheatFanSpeed1 ) ; }
void lcd_preheat_abs1 ( ) { _lcd_preheat ( 1 , preheatHotendTemp2 , preheatBedTemp2 , preheatFanSpeed2 ) ; }
2016-06-11 23:12:00 +02:00
# if HOTENDS > 2
2016-07-10 00:20:12 +02:00
void lcd_preheat_pla2 ( ) { _lcd_preheat ( 2 , preheatHotendTemp1 , preheatBedTemp1 , preheatFanSpeed1 ) ; }
void lcd_preheat_abs2 ( ) { _lcd_preheat ( 2 , preheatHotendTemp2 , preheatBedTemp2 , preheatFanSpeed2 ) ; }
2016-06-11 23:12:00 +02:00
# if HOTENDS > 3
2016-07-10 00:20:12 +02:00
void lcd_preheat_pla3 ( ) { _lcd_preheat ( 3 , preheatHotendTemp1 , preheatBedTemp1 , preheatFanSpeed1 ) ; }
void lcd_preheat_abs3 ( ) { _lcd_preheat ( 3 , preheatHotendTemp2 , preheatBedTemp2 , preheatFanSpeed2 ) ; }
2016-06-11 23:12:00 +02:00
# endif
# endif
2016-04-03 07:45:14 +02:00
2016-06-11 23:12:00 +02:00
void lcd_preheat_pla0123 ( ) {
# if HOTENDS > 1
2016-07-10 00:20:12 +02:00
thermalManager . setTargetHotend ( preheatHotendTemp1 , 1 ) ;
2016-06-11 23:12:00 +02:00
# if HOTENDS > 2
2016-07-10 00:20:12 +02:00
thermalManager . setTargetHotend ( preheatHotendTemp1 , 2 ) ;
2016-06-11 23:12:00 +02:00
# if HOTENDS > 3
2016-07-10 00:20:12 +02:00
thermalManager . setTargetHotend ( preheatHotendTemp1 , 3 ) ;
2016-06-11 23:12:00 +02:00
# endif
# endif
# endif
lcd_preheat_pla0 ( ) ;
}
void lcd_preheat_abs0123 ( ) {
# if HOTENDS > 1
2016-07-10 00:20:12 +02:00
thermalManager . setTargetHotend ( preheatHotendTemp2 , 1 ) ;
2016-06-11 23:12:00 +02:00
# if HOTENDS > 2
2016-07-10 00:20:12 +02:00
thermalManager . setTargetHotend ( preheatHotendTemp2 , 2 ) ;
2016-06-11 23:12:00 +02:00
# if HOTENDS > 3
2016-07-10 00:20:12 +02:00
thermalManager . setTargetHotend ( preheatHotendTemp2 , 3 ) ;
2016-06-11 23:12:00 +02:00
# endif
# endif
# endif
lcd_preheat_abs0 ( ) ;
}
2016-04-03 07:45:14 +02:00
2016-06-11 23:12:00 +02:00
# endif // HOTENDS > 1
2016-04-03 07:46:15 +02:00
2016-06-11 23:12:00 +02:00
# if TEMP_SENSOR_BED != 0
2016-07-10 00:20:12 +02:00
void lcd_preheat_pla_bedonly ( ) { _lcd_preheat ( 0 , 0 , preheatBedTemp1 , preheatFanSpeed1 ) ; }
void lcd_preheat_abs_bedonly ( ) { _lcd_preheat ( 0 , 0 , preheatBedTemp2 , preheatFanSpeed2 ) ; }
2016-06-11 23:12:00 +02:00
# endif
2016-04-03 07:46:15 +02:00
2016-06-11 23:12:00 +02:00
# if TEMP_SENSOR_0 != 0 && (TEMP_SENSOR_1 != 0 || TEMP_SENSOR_2 != 0 || TEMP_SENSOR_3 != 0 || TEMP_SENSOR_BED != 0)
2016-04-03 07:46:15 +02:00
2016-06-11 23:12:00 +02:00
static void lcd_preheat_pla_menu ( ) {
START_MENU ( ) ;
MENU_ITEM ( back , MSG_PREPARE ) ;
# if HOTENDS == 1
2016-07-10 00:20:12 +02:00
MENU_ITEM ( function , MSG_PREHEAT_1 , lcd_preheat_pla0 ) ;
2016-06-11 23:12:00 +02:00
# else
2016-07-10 00:20:12 +02:00
MENU_ITEM ( function , MSG_PREHEAT_1_N MSG_H1 , lcd_preheat_pla0 ) ;
MENU_ITEM ( function , MSG_PREHEAT_1_N MSG_H2 , lcd_preheat_pla1 ) ;
2016-06-11 23:12:00 +02:00
# if HOTENDS > 2
2016-07-10 00:20:12 +02:00
MENU_ITEM ( function , MSG_PREHEAT_1_N MSG_H3 , lcd_preheat_pla2 ) ;
2016-06-11 23:12:00 +02:00
# if HOTENDS > 3
2016-07-10 00:20:12 +02:00
MENU_ITEM ( function , MSG_PREHEAT_1_N MSG_H4 , lcd_preheat_pla3 ) ;
2016-06-11 23:12:00 +02:00
# endif
# endif
2016-07-10 00:20:12 +02:00
MENU_ITEM ( function , MSG_PREHEAT_1_ALL , lcd_preheat_pla0123 ) ;
2016-06-11 23:12:00 +02:00
# endif
# if TEMP_SENSOR_BED != 0
2016-07-10 00:20:12 +02:00
MENU_ITEM ( function , MSG_PREHEAT_1_BEDONLY , lcd_preheat_pla_bedonly ) ;
2016-06-11 23:12:00 +02:00
# endif
END_MENU ( ) ;
}
2016-04-13 11:37:41 +02:00
2016-06-11 23:12:00 +02:00
static void lcd_preheat_abs_menu ( ) {
START_MENU ( ) ;
MENU_ITEM ( back , MSG_PREPARE ) ;
# if HOTENDS == 1
2016-07-10 00:20:12 +02:00
MENU_ITEM ( function , MSG_PREHEAT_2 , lcd_preheat_abs0 ) ;
2016-06-11 23:12:00 +02:00
# else
2016-07-10 00:20:12 +02:00
MENU_ITEM ( function , MSG_PREHEAT_2_N MSG_H1 , lcd_preheat_abs0 ) ;
MENU_ITEM ( function , MSG_PREHEAT_2_N MSG_H2 , lcd_preheat_abs1 ) ;
2016-06-11 23:12:00 +02:00
# if HOTENDS > 2
2016-07-10 00:20:12 +02:00
MENU_ITEM ( function , MSG_PREHEAT_2_N MSG_H3 , lcd_preheat_abs2 ) ;
2016-06-11 23:12:00 +02:00
# if HOTENDS > 3
2016-07-10 00:20:12 +02:00
MENU_ITEM ( function , MSG_PREHEAT_2_N MSG_H4 , lcd_preheat_abs3 ) ;
2016-06-11 23:12:00 +02:00
# endif
# endif
2016-07-10 00:20:12 +02:00
MENU_ITEM ( function , MSG_PREHEAT_2_ALL , lcd_preheat_abs0123 ) ;
2016-04-16 23:17:06 +02:00
# endif
2016-06-11 23:12:00 +02:00
# if TEMP_SENSOR_BED != 0
2016-07-10 00:20:12 +02:00
MENU_ITEM ( function , MSG_PREHEAT_2_BEDONLY , lcd_preheat_abs_bedonly ) ;
2016-06-11 23:12:00 +02:00
# endif
END_MENU ( ) ;
}
# endif // TEMP_SENSOR_0 && (TEMP_SENSOR_1 || TEMP_SENSOR_2 || TEMP_SENSOR_3 || TEMP_SENSOR_BED)
void lcd_cooldown ( ) {
# if FAN_COUNT > 0
for ( uint8_t i = 0 ; i < FAN_COUNT ; i + + ) fanSpeeds [ i ] = 0 ;
2016-04-13 11:37:41 +02:00
# endif
2016-06-11 23:12:00 +02:00
thermalManager . disable_all_heaters ( ) ;
lcd_return_to_status ( ) ;
2016-04-21 00:55:36 +02:00
}
2016-06-11 23:12:00 +02:00
# if ENABLED(SDSUPPORT) && ENABLED(MENU_ADDAUTOSTART)
2016-04-21 00:55:36 +02:00
2016-06-11 23:12:00 +02:00
static void lcd_autostart_sd ( ) {
card . autostart_index = 0 ;
card . setroot ( ) ;
card . checkautostart ( true ) ;
}
2016-04-03 07:46:15 +02:00
2016-06-11 23:12:00 +02:00
# endif
2016-04-03 07:46:15 +02:00
2016-06-11 23:12:00 +02:00
# if ENABLED(MANUAL_BED_LEVELING)
/**
*
* " Prepare " > " Bed Leveling " handlers
*
*/
static uint8_t _lcd_level_bed_position ;
// Utility to go to the next mesh point
// A raise is added between points if MIN_Z_HEIGHT_FOR_HOMING is in use
// Note: During Manual Bed Leveling the homed Z position is MESH_HOME_SEARCH_Z
// Z position will be restored with the final action, a G28
inline void _mbl_goto_xy ( float x , float y ) {
2016-07-08 15:08:32 +02:00
current_position [ Z_AXIS ] = MESH_HOME_SEARCH_Z + MIN_Z_HEIGHT_FOR_HOMING ;
2016-04-03 07:46:15 +02:00
line_to_current ( Z_AXIS ) ;
2016-06-11 23:12:00 +02:00
current_position [ X_AXIS ] = x + home_offset [ X_AXIS ] ;
current_position [ Y_AXIS ] = y + home_offset [ Y_AXIS ] ;
line_to_current ( manual_feedrate [ X_AXIS ] < = manual_feedrate [ Y_AXIS ] ? X_AXIS : Y_AXIS ) ;
# if MIN_Z_HEIGHT_FOR_HOMING > 0
2016-07-08 15:08:32 +02:00
current_position [ Z_AXIS ] = MESH_HOME_SEARCH_Z ; // How do condition and action match?
2016-06-11 23:12:00 +02:00
line_to_current ( Z_AXIS ) ;
# endif
stepper . synchronize ( ) ;
}
static void _lcd_level_goto_next_point ( ) ;
static void _lcd_level_bed_done ( ) {
if ( lcdDrawUpdate ) lcd_implementation_drawedit ( PSTR ( MSG_LEVEL_BED_DONE ) ) ;
2016-04-21 21:40:22 +02:00
lcdDrawUpdate =
# if ENABLED(DOGLCD)
LCDVIEW_CALL_REDRAW_NEXT
# else
2016-06-11 23:12:00 +02:00
LCDVIEW_CALL_NO_REDRAW
2016-04-21 21:40:22 +02:00
# endif
;
2016-04-03 07:46:15 +02:00
}
2016-06-11 23:12:00 +02:00
/**
* Step 7 : Get the Z coordinate , then goto next point or exit
*/
static void _lcd_level_bed_get_z ( ) {
ENCODER_DIRECTION_NORMAL ( ) ;
// Encoder wheel adjusts the Z position
if ( encoderPosition ) {
refresh_cmd_timeout ( ) ;
current_position [ Z_AXIS ] + = float ( ( int32_t ) encoderPosition ) * ( MBL_Z_STEP ) ;
NOLESS ( current_position [ Z_AXIS ] , 0 ) ;
NOMORE ( current_position [ Z_AXIS ] , MESH_HOME_SEARCH_Z * 2 ) ;
line_to_current ( Z_AXIS ) ;
lcdDrawUpdate =
# if ENABLED(DOGLCD)
LCDVIEW_CALL_REDRAW_NEXT
# else
LCDVIEW_REDRAW_NOW
2016-04-21 00:55:36 +02:00
# endif
2016-06-11 23:12:00 +02:00
;
encoderPosition = 0 ;
}
static bool debounce_click = false ;
if ( LCD_CLICKED ) {
if ( ! debounce_click ) {
debounce_click = true ; // ignore multiple "clicks" in a row
mbl . set_zigzag_z ( _lcd_level_bed_position + + , current_position [ Z_AXIS ] ) ;
if ( _lcd_level_bed_position = = ( MESH_NUM_X_POINTS ) * ( MESH_NUM_Y_POINTS ) ) {
2016-06-11 23:19:17 +02:00
lcd_goto_screen ( _lcd_level_bed_done , true ) ;
2016-06-11 23:12:00 +02:00
2016-07-08 15:08:32 +02:00
current_position [ Z_AXIS ] = MESH_HOME_SEARCH_Z + MIN_Z_HEIGHT_FOR_HOMING ;
2016-06-11 23:12:00 +02:00
line_to_current ( Z_AXIS ) ;
stepper . synchronize ( ) ;
mbl . set_has_mesh ( true ) ;
enqueue_and_echo_commands_P ( PSTR ( " G28 " ) ) ;
lcd_return_to_status ( ) ;
//LCD_MESSAGEPGM(MSG_LEVEL_BED_DONE);
# if HAS_BUZZER
buzzer . tone ( 200 , 659 ) ;
buzzer . tone ( 200 , 698 ) ;
# endif
}
else {
2016-06-11 23:19:17 +02:00
lcd_goto_screen ( _lcd_level_goto_next_point , true ) ;
2016-06-11 23:12:00 +02:00
}
2016-04-03 07:46:15 +02:00
}
}
2016-06-11 23:12:00 +02:00
else {
debounce_click = false ;
}
// Update on first display, then only on updates to Z position
// Show message above on clicks instead
if ( lcdDrawUpdate ) {
float v = current_position [ Z_AXIS ] - MESH_HOME_SEARCH_Z ;
lcd_implementation_drawedit ( PSTR ( MSG_MOVE_Z ) , ftostr43sign ( v + ( v < 0 ? - 0.0001 : 0.0001 ) , ' + ' ) ) ;
}
2016-04-21 00:55:36 +02:00
}
2016-06-11 23:12:00 +02:00
/**
* Step 6 : Display " Next point: 1 / 9 " while waiting for move to finish
*/
static void _lcd_level_bed_moving ( ) {
if ( lcdDrawUpdate ) {
char msg [ 10 ] ;
sprintf_P ( msg , PSTR ( " %i / %u " ) , ( int ) ( _lcd_level_bed_position + 1 ) , ( MESH_NUM_X_POINTS ) * ( MESH_NUM_Y_POINTS ) ) ;
lcd_implementation_drawedit ( PSTR ( MSG_LEVEL_BED_NEXT_POINT ) , msg ) ;
}
2016-04-21 00:55:36 +02:00
2016-06-11 23:12:00 +02:00
lcdDrawUpdate =
# if ENABLED(DOGLCD)
LCDVIEW_CALL_REDRAW_NEXT
# else
LCDVIEW_CALL_NO_REDRAW
# endif
;
2016-04-21 00:55:36 +02:00
}
2016-04-21 21:40:22 +02:00
2016-06-11 23:12:00 +02:00
/**
* Step 5 : Initiate a move to the next point
*/
static void _lcd_level_goto_next_point ( ) {
// Set the menu to display ahead of blocking call
2016-06-11 23:19:17 +02:00
lcd_goto_screen ( _lcd_level_bed_moving ) ;
2016-04-03 07:46:15 +02:00
2016-06-11 23:12:00 +02:00
// _mbl_goto_xy runs the menu loop until the move is done
int8_t px , py ;
mbl . zigzag ( _lcd_level_bed_position , px , py ) ;
_mbl_goto_xy ( mbl . get_probe_x ( px ) , mbl . get_probe_y ( py ) ) ;
2016-04-21 00:55:36 +02:00
2016-06-11 23:12:00 +02:00
// After the blocking function returns, change menus
2016-06-11 23:19:17 +02:00
lcd_goto_screen ( _lcd_level_bed_get_z ) ;
2016-06-11 23:12:00 +02:00
}
2016-04-21 00:55:36 +02:00
2016-06-11 23:12:00 +02:00
/**
* Step 4 : Display " Click to Begin " , wait for click
* Move to the first probe position
*/
static void _lcd_level_bed_homing_done ( ) {
if ( lcdDrawUpdate ) lcd_implementation_drawedit ( PSTR ( MSG_LEVEL_BED_WAITING ) ) ;
if ( LCD_CLICKED ) {
_lcd_level_bed_position = 0 ;
2016-06-25 21:58:02 +02:00
current_position [ Z_AXIS ] = MESH_HOME_SEARCH_Z
# if Z_HOME_DIR > 0
+ Z_MAX_POS
# endif
;
2016-06-11 23:12:00 +02:00
planner . set_position_mm ( current_position [ X_AXIS ] , current_position [ Y_AXIS ] , current_position [ Z_AXIS ] , current_position [ E_AXIS ] ) ;
2016-06-11 23:19:17 +02:00
lcd_goto_screen ( _lcd_level_goto_next_point , true ) ;
2016-06-11 23:12:00 +02:00
}
}
2016-04-21 00:55:36 +02:00
2016-06-11 23:12:00 +02:00
/**
* Step 3 : Display " Homing XYZ " - Wait for homing to finish
*/
static void _lcd_level_bed_homing ( ) {
if ( lcdDrawUpdate ) lcd_implementation_drawedit ( PSTR ( MSG_LEVEL_BED_HOMING ) , NULL ) ;
lcdDrawUpdate =
# if ENABLED(DOGLCD)
LCDVIEW_CALL_REDRAW_NEXT
# else
LCDVIEW_CALL_NO_REDRAW
# endif
;
if ( axis_homed [ X_AXIS ] & & axis_homed [ Y_AXIS ] & & axis_homed [ Z_AXIS ] )
2016-06-11 23:19:17 +02:00
lcd_goto_screen ( _lcd_level_bed_homing_done ) ;
2016-04-03 07:46:15 +02:00
}
2016-06-11 23:12:00 +02:00
/**
* Step 2 : Continue Bed Leveling . . .
*/
static void _lcd_level_bed_continue ( ) {
defer_return_to_status = true ;
axis_homed [ X_AXIS ] = axis_homed [ Y_AXIS ] = axis_homed [ Z_AXIS ] = false ;
mbl . reset ( ) ;
enqueue_and_echo_commands_P ( PSTR ( " G28 " ) ) ;
2016-06-11 23:19:17 +02:00
lcd_goto_screen ( _lcd_level_bed_homing ) ;
2016-06-11 23:12:00 +02:00
}
2016-04-03 07:46:15 +02:00
2016-06-11 23:12:00 +02:00
/**
* Step 1 : MBL entry - point : " Cancel " or " Level Bed "
*/
static void lcd_level_bed ( ) {
START_MENU ( ) ;
MENU_ITEM ( back , MSG_LEVEL_BED_CANCEL ) ;
MENU_ITEM ( submenu , MSG_LEVEL_BED , _lcd_level_bed_continue ) ;
END_MENU ( ) ;
}
# endif // MANUAL_BED_LEVELING
2016-04-03 07:46:15 +02:00
/**
2016-06-11 23:12:00 +02:00
*
* " Prepare " submenu
*
2016-04-03 07:46:15 +02:00
*/
2016-06-11 23:12:00 +02:00
static void lcd_prepare_menu ( ) {
2016-04-03 07:46:15 +02:00
START_MENU ( ) ;
2016-06-11 23:12:00 +02:00
//
// ^ Main
//
MENU_ITEM ( back , MSG_MAIN ) ;
2016-04-03 07:46:15 +02:00
2016-06-11 23:12:00 +02:00
//
// Auto Home
//
MENU_ITEM ( gcode , MSG_AUTO_HOME , PSTR ( " G28 " ) ) ;
# if ENABLED(INDIVIDUAL_AXIS_HOMING_MENU)
MENU_ITEM ( gcode , MSG_AUTO_HOME_X , PSTR ( " G28 X " ) ) ;
MENU_ITEM ( gcode , MSG_AUTO_HOME_Y , PSTR ( " G28 Y " ) ) ;
MENU_ITEM ( gcode , MSG_AUTO_HOME_Z , PSTR ( " G28 Z " ) ) ;
# endif
2015-04-28 04:11:25 +02:00
2016-06-11 23:12:00 +02:00
//
// Set Home Offsets
//
MENU_ITEM ( function , MSG_SET_HOME_OFFSETS , lcd_set_home_offsets ) ;
//MENU_ITEM(gcode, MSG_SET_ORIGIN, PSTR("G92 X0 Y0 Z0"));
//
// Level Bed
//
# if ENABLED(AUTO_BED_LEVELING_FEATURE)
MENU_ITEM ( gcode , MSG_LEVEL_BED ,
axis_homed [ X_AXIS ] & & axis_homed [ Y_AXIS ] ? PSTR ( " G29 " ) : PSTR ( " G28 \n G29 " )
) ;
# elif ENABLED(MANUAL_BED_LEVELING)
MENU_ITEM ( submenu , MSG_LEVEL_BED , lcd_level_bed ) ;
# endif
2015-04-28 04:11:25 +02:00
2016-06-11 23:12:00 +02:00
//
// Move Axis
//
MENU_ITEM ( submenu , MSG_MOVE_AXIS , lcd_move_menu ) ;
2015-04-28 04:11:25 +02:00
2016-06-11 23:12:00 +02:00
//
// Disable Steppers
//
MENU_ITEM ( gcode , MSG_DISABLE_STEPPERS , PSTR ( " M84 " ) ) ;
2015-04-28 04:11:25 +02:00
2016-06-11 23:12:00 +02:00
//
// Preheat PLA
// Preheat ABS
//
# if TEMP_SENSOR_0 != 0
# if TEMP_SENSOR_1 != 0 || TEMP_SENSOR_2 != 0 || TEMP_SENSOR_3 != 0 || TEMP_SENSOR_BED != 0
2016-07-10 00:20:12 +02:00
MENU_ITEM ( submenu , MSG_PREHEAT_1 , lcd_preheat_pla_menu ) ;
MENU_ITEM ( submenu , MSG_PREHEAT_2 , lcd_preheat_abs_menu ) ;
2016-06-11 23:12:00 +02:00
# else
2016-07-10 00:20:12 +02:00
MENU_ITEM ( function , MSG_PREHEAT_1 , lcd_preheat_pla0 ) ;
MENU_ITEM ( function , MSG_PREHEAT_2 , lcd_preheat_abs0 ) ;
2016-06-11 23:12:00 +02:00
# endif
# endif
2015-04-28 04:11:25 +02:00
2016-06-11 23:12:00 +02:00
//
// Cooldown
//
MENU_ITEM ( function , MSG_COOLDOWN , lcd_cooldown ) ;
//
// Switch power on/off
//
# if HAS_POWER_SWITCH
if ( powersupply )
MENU_ITEM ( gcode , MSG_SWITCH_PS_OFF , PSTR ( " M81 " ) ) ;
else
MENU_ITEM ( gcode , MSG_SWITCH_PS_ON , PSTR ( " M80 " ) ) ;
2015-02-22 02:38:56 +01:00
# endif
2015-03-31 01:39:47 +02:00
2016-06-11 23:12:00 +02:00
//
// Autostart
//
# if ENABLED(SDSUPPORT) && ENABLED(MENU_ADDAUTOSTART)
MENU_ITEM ( function , MSG_AUTOSTART , lcd_autostart_sd ) ;
# endif
2015-03-31 01:39:47 +02:00
2016-06-11 23:12:00 +02:00
END_MENU ( ) ;
}
2015-03-31 01:39:47 +02:00
2016-06-11 23:12:00 +02:00
# if ENABLED(DELTA_CALIBRATION_MENU)
2015-04-28 04:11:25 +02:00
2016-06-11 23:12:00 +02:00
static void lcd_delta_calibrate_menu ( ) {
START_MENU ( ) ;
MENU_ITEM ( back , MSG_MAIN ) ;
MENU_ITEM ( gcode , MSG_AUTO_HOME , PSTR ( " G28 " ) ) ;
MENU_ITEM ( gcode , MSG_DELTA_CALIBRATE_X , PSTR ( " G0 F8000 X-77.94 Y-45 Z0 " ) ) ;
MENU_ITEM ( gcode , MSG_DELTA_CALIBRATE_Y , PSTR ( " G0 F8000 X77.94 Y-45 Z0 " ) ) ;
MENU_ITEM ( gcode , MSG_DELTA_CALIBRATE_Z , PSTR ( " G0 F8000 X0 Y90 Z0 " ) ) ;
MENU_ITEM ( gcode , MSG_DELTA_CALIBRATE_CENTER , PSTR ( " G0 F8000 X0 Y0 Z0 " ) ) ;
END_MENU ( ) ;
}
2011-12-12 19:34:37 +01:00
2016-06-11 23:12:00 +02:00
# endif // DELTA_CALIBRATION_MENU
2015-04-09 13:32:14 +02:00
2016-06-11 23:12:00 +02:00
/**
* If the most recent manual move hasn ' t been fed to the planner yet ,
* and the planner can accept one , send immediately
*/
inline void manage_manual_move ( ) {
if ( manual_move_axis ! = ( int8_t ) NO_AXIS & & millis ( ) > = manual_move_start_time & & ! planner . is_full ( ) ) {
# if ENABLED(DELTA)
calculate_delta ( current_position ) ;
2016-06-13 01:51:28 +02:00
planner . buffer_line ( delta [ X_AXIS ] , delta [ Y_AXIS ] , delta [ Z_AXIS ] , current_position [ E_AXIS ] , manual_feedrate [ manual_move_axis ] / 60 , manual_move_e_index ) ;
2016-06-11 23:12:00 +02:00
# else
2016-06-13 01:51:28 +02:00
planner . buffer_line ( current_position [ X_AXIS ] , current_position [ Y_AXIS ] , current_position [ Z_AXIS ] , current_position [ E_AXIS ] , manual_feedrate [ manual_move_axis ] / 60 , manual_move_e_index ) ;
2016-06-11 23:12:00 +02:00
# endif
manual_move_axis = ( int8_t ) NO_AXIS ;
}
2015-04-09 13:32:14 +02:00
}
2016-06-11 23:12:00 +02:00
/**
* Set a flag that lcd_update ( ) should start a move
* to " current_position " after a short delay .
*/
2016-06-13 01:51:28 +02:00
inline void manual_move_to_current ( AxisEnum axis
# if EXTRUDERS > 1
, int8_t eindex = - 1
# endif
) {
# if EXTRUDERS > 1
if ( axis = = E_AXIS ) manual_move_e_index = eindex > = 0 ? eindex : active_extruder ;
# endif
2016-06-11 23:12:00 +02:00
manual_move_start_time = millis ( ) + 500UL ; // 1/2 second delay
manual_move_axis = ( int8_t ) axis ;
2016-03-08 05:11:56 +01:00
}
2016-06-11 23:12:00 +02:00
/**
*
* " Prepare " > " Move Axis " submenu
*
*/
2016-03-08 05:11:56 +01:00
2016-06-11 23:12:00 +02:00
float move_menu_scale ;
2015-04-28 04:11:25 +02:00
2016-06-13 01:51:39 +02:00
static void _lcd_move_xyz ( const char * name , AxisEnum axis , float min , float max ) {
2016-07-11 02:53:11 +02:00
if ( LCD_CLICKED ) { lcd_goto_previous_menu ( true ) ; return ; }
2016-06-11 23:12:00 +02:00
ENCODER_DIRECTION_NORMAL ( ) ;
if ( encoderPosition ) {
refresh_cmd_timeout ( ) ;
current_position [ axis ] + = float ( ( int32_t ) encoderPosition ) * move_menu_scale ;
if ( min_software_endstops ) NOLESS ( current_position [ axis ] , min ) ;
if ( max_software_endstops ) NOMORE ( current_position [ axis ] , max ) ;
encoderPosition = 0 ;
manual_move_to_current ( axis ) ;
lcdDrawUpdate = LCDVIEW_REDRAW_NOW ;
}
if ( lcdDrawUpdate ) lcd_implementation_drawedit ( name , ftostr41sign ( current_position [ axis ] ) ) ;
2014-12-18 16:30:05 +01:00
}
2016-06-11 23:12:00 +02:00
# if ENABLED(DELTA)
static float delta_clip_radius_2 = ( DELTA_PRINTABLE_RADIUS ) * ( DELTA_PRINTABLE_RADIUS ) ;
static int delta_clip ( float a ) { return sqrt ( delta_clip_radius_2 - a * a ) ; }
2016-06-13 01:51:39 +02:00
static void lcd_move_x ( ) { int clip = delta_clip ( current_position [ Y_AXIS ] ) ; _lcd_move_xyz ( PSTR ( MSG_MOVE_X ) , X_AXIS , max ( sw_endstop_min [ X_AXIS ] , - clip ) , min ( sw_endstop_max [ X_AXIS ] , clip ) ) ; }
static void lcd_move_y ( ) { int clip = delta_clip ( current_position [ X_AXIS ] ) ; _lcd_move_xyz ( PSTR ( MSG_MOVE_Y ) , Y_AXIS , max ( sw_endstop_min [ Y_AXIS ] , - clip ) , min ( sw_endstop_max [ Y_AXIS ] , clip ) ) ; }
2016-06-11 23:12:00 +02:00
# else
2016-06-13 01:51:39 +02:00
static void lcd_move_x ( ) { _lcd_move_xyz ( PSTR ( MSG_MOVE_X ) , X_AXIS , sw_endstop_min [ X_AXIS ] , sw_endstop_max [ X_AXIS ] ) ; }
static void lcd_move_y ( ) { _lcd_move_xyz ( PSTR ( MSG_MOVE_Y ) , Y_AXIS , sw_endstop_min [ Y_AXIS ] , sw_endstop_max [ Y_AXIS ] ) ; }
2015-08-20 18:37:00 +02:00
# endif
2016-06-13 01:51:39 +02:00
static void lcd_move_z ( ) { _lcd_move_xyz ( PSTR ( MSG_MOVE_Z ) , Z_AXIS , sw_endstop_min [ Z_AXIS ] , sw_endstop_max [ Z_AXIS ] ) ; }
2016-06-11 23:12:00 +02:00
static void lcd_move_e (
# if EXTRUDERS > 1
2016-06-13 01:51:28 +02:00
int8_t eindex = - 1
2016-06-11 23:12:00 +02:00
# endif
) {
2016-07-11 02:53:11 +02:00
if ( LCD_CLICKED ) { lcd_goto_previous_menu ( true ) ; return ; }
2016-06-11 23:12:00 +02:00
ENCODER_DIRECTION_NORMAL ( ) ;
if ( encoderPosition ) {
current_position [ E_AXIS ] + = float ( ( int32_t ) encoderPosition ) * move_menu_scale ;
encoderPosition = 0 ;
2016-06-13 01:51:28 +02:00
manual_move_to_current ( E_AXIS
# if EXTRUDERS > 1
, eindex
# endif
) ;
2016-06-11 23:12:00 +02:00
lcdDrawUpdate = LCDVIEW_REDRAW_NOW ;
}
if ( lcdDrawUpdate ) {
PGM_P pos_label ;
# if EXTRUDERS == 1
pos_label = PSTR ( MSG_MOVE_E ) ;
# else
2016-06-15 11:11:16 +02:00
switch ( eindex ) {
2016-06-11 23:12:00 +02:00
case 0 : pos_label = PSTR ( MSG_MOVE_E MSG_MOVE_E1 ) ; break ;
case 1 : pos_label = PSTR ( MSG_MOVE_E MSG_MOVE_E2 ) ; break ;
# if EXTRUDERS > 2
case 2 : pos_label = PSTR ( MSG_MOVE_E MSG_MOVE_E3 ) ; break ;
# if EXTRUDERS > 3
case 3 : pos_label = PSTR ( MSG_MOVE_E MSG_MOVE_E4 ) ; break ;
# endif //EXTRUDERS > 3
# endif //EXTRUDERS > 2
}
# endif //EXTRUDERS > 1
lcd_implementation_drawedit ( pos_label , ftostr41sign ( current_position [ E_AXIS ] ) ) ;
}
2015-09-11 09:37:32 +02:00
}
2014-12-18 16:30:05 +01:00
2016-06-11 23:12:00 +02:00
# if EXTRUDERS > 1
static void lcd_move_e0 ( ) { lcd_move_e ( 0 ) ; }
static void lcd_move_e1 ( ) { lcd_move_e ( 1 ) ; }
# if EXTRUDERS > 2
static void lcd_move_e2 ( ) { lcd_move_e ( 2 ) ; }
# if EXTRUDERS > 3
static void lcd_move_e3 ( ) { lcd_move_e ( 3 ) ; }
# endif
2015-08-20 18:37:00 +02:00
# endif
2016-06-11 23:12:00 +02:00
# endif // EXTRUDERS > 1
2015-08-20 18:37:00 +02:00
2016-06-11 23:12:00 +02:00
/**
*
* " Prepare " > " Move Xmm " > " Move XYZ " submenu
*
*/
2015-04-28 04:11:25 +02:00
2016-06-11 23:12:00 +02:00
# if ENABLED(DELTA) || ENABLED(SCARA)
# define _MOVE_XYZ_ALLOWED (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS])
# else
# define _MOVE_XYZ_ALLOWED true
# endif
2016-04-07 10:58:23 +02:00
2016-06-11 23:12:00 +02:00
static void _lcd_move_menu_axis ( ) {
START_MENU ( ) ;
MENU_ITEM ( back , MSG_MOVE_AXIS ) ;
2016-04-07 10:58:23 +02:00
2016-06-11 23:12:00 +02:00
if ( _MOVE_XYZ_ALLOWED ) {
MENU_ITEM ( submenu , MSG_MOVE_X , lcd_move_x ) ;
MENU_ITEM ( submenu , MSG_MOVE_Y , lcd_move_y ) ;
}
if ( move_menu_scale < 10.0 ) {
if ( _MOVE_XYZ_ALLOWED ) MENU_ITEM ( submenu , MSG_MOVE_Z , lcd_move_z ) ;
# if EXTRUDERS == 1
MENU_ITEM ( submenu , MSG_MOVE_E , lcd_move_e ) ;
# else
MENU_ITEM ( submenu , MSG_MOVE_E MSG_MOVE_E1 , lcd_move_e0 ) ;
MENU_ITEM ( submenu , MSG_MOVE_E MSG_MOVE_E2 , lcd_move_e1 ) ;
# if EXTRUDERS > 2
MENU_ITEM ( submenu , MSG_MOVE_E MSG_MOVE_E3 , lcd_move_e2 ) ;
# if EXTRUDERS > 3
MENU_ITEM ( submenu , MSG_MOVE_E MSG_MOVE_E4 , lcd_move_e3 ) ;
# endif
2015-08-20 18:37:00 +02:00
# endif
2016-06-11 23:12:00 +02:00
# endif // EXTRUDERS > 1
}
END_MENU ( ) ;
2015-04-10 04:33:16 +02:00
}
2016-04-07 10:58:23 +02:00
2016-06-11 23:12:00 +02:00
static void lcd_move_menu_10mm ( ) {
move_menu_scale = 10.0 ;
_lcd_move_menu_axis ( ) ;
}
static void lcd_move_menu_1mm ( ) {
move_menu_scale = 1.0 ;
_lcd_move_menu_axis ( ) ;
}
static void lcd_move_menu_01mm ( ) {
move_menu_scale = 0.1 ;
_lcd_move_menu_axis ( ) ;
}
2015-04-28 04:11:25 +02:00
2016-06-11 23:12:00 +02:00
/**
*
* " Prepare " > " Move Axis " submenu
*
*/
2016-03-22 02:10:08 +01:00
2016-06-11 23:12:00 +02:00
static void lcd_move_menu ( ) {
START_MENU ( ) ;
MENU_ITEM ( back , MSG_PREPARE ) ;
2016-03-22 02:10:08 +01:00
2016-06-11 23:12:00 +02:00
if ( _MOVE_XYZ_ALLOWED )
MENU_ITEM ( submenu , MSG_MOVE_10MM , lcd_move_menu_10mm ) ;
2016-03-22 02:10:08 +01:00
2016-06-11 23:12:00 +02:00
MENU_ITEM ( submenu , MSG_MOVE_1MM , lcd_move_menu_1mm ) ;
MENU_ITEM ( submenu , MSG_MOVE_01MM , lcd_move_menu_01mm ) ;
//TODO:X,Y,Z,E
END_MENU ( ) ;
2016-03-22 02:10:08 +01:00
}
2016-06-11 23:12:00 +02:00
/**
*
* " Control " submenu
*
*/
2016-03-22 02:10:08 +01:00
2016-06-11 23:12:00 +02:00
static void lcd_control_menu ( ) {
START_MENU ( ) ;
MENU_ITEM ( back , MSG_MAIN ) ;
MENU_ITEM ( submenu , MSG_TEMPERATURE , lcd_control_temperature_menu ) ;
MENU_ITEM ( submenu , MSG_MOTION , lcd_control_motion_menu ) ;
MENU_ITEM ( submenu , MSG_VOLUMETRIC , lcd_control_volumetric_menu ) ;
2015-02-20 09:00:19 +01:00
2016-06-11 23:12:00 +02:00
# if HAS_LCD_CONTRAST
//MENU_ITEM_EDIT(int3, MSG_CONTRAST, &lcd_contrast, 0, 63);
MENU_ITEM ( submenu , MSG_CONTRAST , lcd_set_contrast ) ;
2016-04-02 23:28:17 +02:00
# endif
2016-06-11 23:12:00 +02:00
# if ENABLED(FWRETRACT)
MENU_ITEM ( submenu , MSG_RETRACT , lcd_control_retract_menu ) ;
# endif
# if ENABLED(EEPROM_SETTINGS)
MENU_ITEM ( function , MSG_STORE_EPROM , Config_StoreSettings ) ;
MENU_ITEM ( function , MSG_LOAD_EPROM , Config_RetrieveSettings ) ;
2016-04-02 23:28:17 +02:00
# endif
2016-06-11 23:12:00 +02:00
MENU_ITEM ( function , MSG_RESTORE_FAILSAFE , Config_ResetDefault ) ;
END_MENU ( ) ;
2015-02-20 08:54:06 +01:00
}
2016-03-26 03:22:33 +01:00
2016-06-11 23:12:00 +02:00
/**
*
* " Temperature " submenu
*
*/
2015-02-20 09:00:19 +01:00
2016-06-11 23:12:00 +02:00
# if ENABLED(PID_AUTOTUNE_MENU)
2015-02-20 08:54:06 +01:00
2016-06-11 23:12:00 +02:00
# if ENABLED(PIDTEMP)
int autotune_temp [ HOTENDS ] = ARRAY_BY_HOTENDS1 ( 150 ) ;
const int heater_maxtemp [ HOTENDS ] = ARRAY_BY_HOTENDS ( HEATER_0_MAXTEMP , HEATER_1_MAXTEMP , HEATER_2_MAXTEMP , HEATER_3_MAXTEMP ) ;
2015-12-04 01:31:22 +01:00
# endif
2016-06-11 23:12:00 +02:00
# if ENABLED(PIDTEMPBED)
int autotune_temp_bed = 70 ;
2015-12-04 01:31:22 +01:00
# endif
2016-06-11 23:12:00 +02:00
static void _lcd_autotune ( int e ) {
char cmd [ 30 ] ;
sprintf_P ( cmd , PSTR ( " M303 U1 E%i S%i " ) , e ,
# if HAS_PID_FOR_BOTH
e < 0 ? autotune_temp_bed : autotune_temp [ e ]
# elif ENABLED(PIDTEMPBED)
autotune_temp_bed
# else
autotune_temp [ e ]
# endif
) ;
enqueue_and_echo_command ( cmd ) ;
}
2015-12-04 01:31:22 +01:00
2016-06-11 23:12:00 +02:00
# endif //PID_AUTOTUNE_MENU
2015-05-13 03:46:16 +02:00
2015-07-31 07:26:53 +02:00
# if ENABLED(PIDTEMP)
2015-09-12 04:52:01 +02:00
2016-06-11 23:12:00 +02:00
// Helpers for editing PID Ki & Kd values
// grab the PID value out of the temp variable; scale it; then update the PID driver
void copy_and_scalePID_i ( int e ) {
# if DISABLED(PID_PARAMS_PER_HOTEND)
UNUSED ( e ) ;
# endif
PID_PARAM ( Ki , e ) = scalePID_i ( raw_Ki ) ;
thermalManager . updatePID ( ) ;
}
void copy_and_scalePID_d ( int e ) {
# if DISABLED(PID_PARAMS_PER_HOTEND)
UNUSED ( e ) ;
# endif
PID_PARAM ( Kd , e ) = scalePID_d ( raw_Kd ) ;
thermalManager . updatePID ( ) ;
}
# define _PIDTEMP_BASE_FUNCTIONS(eindex) \
void copy_and_scalePID_i_E # # eindex ( ) { copy_and_scalePID_i ( eindex ) ; } \
void copy_and_scalePID_d_E # # eindex ( ) { copy_and_scalePID_d ( eindex ) ; }
2015-02-20 08:54:06 +01:00
2016-03-26 03:22:33 +01:00
# if ENABLED(PID_AUTOTUNE_MENU)
2016-06-11 23:12:00 +02:00
# define _PIDTEMP_FUNCTIONS(eindex) \
_PIDTEMP_BASE_FUNCTIONS ( eindex ) ; \
void lcd_autotune_callback_E # # eindex ( ) { _lcd_autotune ( eindex ) ; }
2016-03-26 03:22:33 +01:00
# else
2016-06-11 23:12:00 +02:00
# define _PIDTEMP_FUNCTIONS(eindex) _PIDTEMP_BASE_FUNCTIONS(eindex)
2016-03-26 03:22:33 +01:00
# endif
2016-03-22 02:10:08 +01:00
2016-06-11 23:12:00 +02:00
_PIDTEMP_FUNCTIONS ( 0 ) ;
# if ENABLED(PID_PARAMS_PER_HOTEND)
# if HOTENDS > 1
_PIDTEMP_FUNCTIONS ( 1 ) ;
# if HOTENDS > 2
_PIDTEMP_FUNCTIONS ( 2 ) ;
# if HOTENDS > 3
_PIDTEMP_FUNCTIONS ( 3 ) ;
# endif //HOTENDS > 3
# endif //HOTENDS > 2
# endif //HOTENDS > 1
# endif //PID_PARAMS_PER_HOTEND
2015-02-20 08:54:06 +01:00
2015-09-12 04:52:01 +02:00
# endif //PIDTEMP
2015-05-13 03:46:16 +02:00
2016-06-11 23:12:00 +02:00
/**
*
* " Control " > " Temperature " submenu
*
*/
static void lcd_control_temperature_menu ( ) {
START_MENU ( ) ;
2011-12-12 19:34:37 +01:00
2016-06-11 23:12:00 +02:00
//
// ^ Control
//
MENU_ITEM ( back , MSG_CONTROL ) ;
2011-12-12 19:34:37 +01:00
2016-06-11 23:12:00 +02:00
//
// Nozzle:
// Nozzle [1-4]:
//
# if HOTENDS == 1
# if TEMP_SENSOR_0 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( int3 , MSG_NOZZLE , & thermalManager . target_temperature [ 0 ] , 0 , HEATER_0_MAXTEMP - 15 , watch_temp_callback_E0 ) ;
# endif
# else //HOTENDS > 1
# if TEMP_SENSOR_0 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( int3 , MSG_NOZZLE MSG_N1 , & thermalManager . target_temperature [ 0 ] , 0 , HEATER_0_MAXTEMP - 15 , watch_temp_callback_E0 ) ;
# endif
# if TEMP_SENSOR_1 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( int3 , MSG_NOZZLE MSG_N2 , & thermalManager . target_temperature [ 1 ] , 0 , HEATER_1_MAXTEMP - 15 , watch_temp_callback_E1 ) ;
# endif
# if HOTENDS > 2
# if TEMP_SENSOR_2 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( int3 , MSG_NOZZLE MSG_N3 , & thermalManager . target_temperature [ 2 ] , 0 , HEATER_2_MAXTEMP - 15 , watch_temp_callback_E2 ) ;
# endif
# if HOTENDS > 3
# if TEMP_SENSOR_3 != 0
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( int3 , MSG_NOZZLE MSG_N4 , & thermalManager . target_temperature [ 3 ] , 0 , HEATER_3_MAXTEMP - 15 , watch_temp_callback_E3 ) ;
# endif
# endif // HOTENDS > 3
# endif // HOTENDS > 2
# endif // HOTENDS > 1
2011-12-12 19:34:37 +01:00
2016-06-11 23:12:00 +02:00
//
// Bed:
//
# if TEMP_SENSOR_BED != 0
MENU_MULTIPLIER_ITEM_EDIT ( int3 , MSG_BED , & thermalManager . target_temperature_bed , 0 , BED_MAXTEMP - 15 ) ;
# endif
2016-04-28 03:06:32 +02:00
2016-06-11 23:12:00 +02:00
//
// Fan Speed:
//
# if FAN_COUNT > 0
# if HAS_FAN0
# if FAN_COUNT > 1
# define MSG_1ST_FAN_SPEED MSG_FAN_SPEED " 1"
# else
# define MSG_1ST_FAN_SPEED MSG_FAN_SPEED
# endif
MENU_MULTIPLIER_ITEM_EDIT ( int3 , MSG_1ST_FAN_SPEED , & fanSpeeds [ 0 ] , 0 , 255 ) ;
# endif
# if HAS_FAN1
MENU_MULTIPLIER_ITEM_EDIT ( int3 , MSG_FAN_SPEED " 2 " , & fanSpeeds [ 1 ] , 0 , 255 ) ;
# endif
# if HAS_FAN2
MENU_MULTIPLIER_ITEM_EDIT ( int3 , MSG_FAN_SPEED " 3 " , & fanSpeeds [ 2 ] , 0 , 255 ) ;
# endif
# endif // FAN_COUNT > 0
//
// Autotemp, Min, Max, Fact
//
# if ENABLED(AUTOTEMP) && (TEMP_SENSOR_0 != 0)
MENU_ITEM_EDIT ( bool , MSG_AUTOTEMP , & planner . autotemp_enabled ) ;
MENU_ITEM_EDIT ( float3 , MSG_MIN , & planner . autotemp_min , 0 , HEATER_0_MAXTEMP - 15 ) ;
MENU_ITEM_EDIT ( float3 , MSG_MAX , & planner . autotemp_max , 0 , HEATER_0_MAXTEMP - 15 ) ;
MENU_ITEM_EDIT ( float32 , MSG_FACTOR , & planner . autotemp_factor , 0.0 , 1.0 ) ;
# endif
2011-12-12 19:34:37 +01:00
2016-06-11 23:12:00 +02:00
//
// PID-P, PID-I, PID-D, PID-C, PID Autotune
// PID-P E1, PID-I E1, PID-D E1, PID-C E1, PID Autotune E1
// PID-P E2, PID-I E2, PID-D E2, PID-C E2, PID Autotune E2
// PID-P E3, PID-I E3, PID-D E3, PID-C E3, PID Autotune E3
// PID-P E4, PID-I E4, PID-D E4, PID-C E4, PID Autotune E4
//
# if ENABLED(PIDTEMP)
# define _PID_BASE_MENU_ITEMS(ELABEL, eindex) \
raw_Ki = unscalePID_i ( PID_PARAM ( Ki , eindex ) ) ; \
raw_Kd = unscalePID_d ( PID_PARAM ( Kd , eindex ) ) ; \
MENU_ITEM_EDIT ( float52 , MSG_PID_P ELABEL , & PID_PARAM ( Kp , eindex ) , 1 , 9990 ) ; \
MENU_ITEM_EDIT_CALLBACK ( float52 , MSG_PID_I ELABEL , & raw_Ki , 0.01 , 9990 , copy_and_scalePID_i_E # # eindex ) ; \
MENU_ITEM_EDIT_CALLBACK ( float52 , MSG_PID_D ELABEL , & raw_Kd , 1 , 9990 , copy_and_scalePID_d_E # # eindex )
# if ENABLED(PID_ADD_EXTRUSION_RATE)
# define _PID_MENU_ITEMS(ELABEL, eindex) \
_PID_BASE_MENU_ITEMS ( ELABEL , eindex ) ; \
MENU_ITEM_EDIT ( float3 , MSG_PID_C ELABEL , & PID_PARAM ( Kc , eindex ) , 1 , 9990 )
# else
# define _PID_MENU_ITEMS(ELABEL, eindex) _PID_BASE_MENU_ITEMS(ELABEL, eindex)
# endif
2015-02-22 02:38:56 +01:00
2016-06-11 23:12:00 +02:00
# if ENABLED(PID_AUTOTUNE_MENU)
# define PID_MENU_ITEMS(ELABEL, eindex) \
_PID_MENU_ITEMS ( ELABEL , eindex ) ; \
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( int3 , MSG_PID_AUTOTUNE ELABEL , & autotune_temp [ eindex ] , 150 , heater_maxtemp [ eindex ] - 15 , lcd_autotune_callback_E # # eindex )
# else
# define PID_MENU_ITEMS(ELABEL, eindex) _PID_MENU_ITEMS(ELABEL, eindex)
# endif
2015-02-22 02:38:56 +01:00
2016-06-11 23:12:00 +02:00
# if ENABLED(PID_PARAMS_PER_HOTEND) && HOTENDS > 1
PID_MENU_ITEMS ( MSG_E1 , 0 ) ;
PID_MENU_ITEMS ( MSG_E2 , 1 ) ;
# if HOTENDS > 2
PID_MENU_ITEMS ( MSG_E3 , 2 ) ;
# if HOTENDS > 3
PID_MENU_ITEMS ( MSG_E4 , 3 ) ;
# endif //HOTENDS > 3
# endif //HOTENDS > 2
# else //!PID_PARAMS_PER_HOTEND || HOTENDS == 1
PID_MENU_ITEMS ( " " , 0 ) ;
# endif //!PID_PARAMS_PER_HOTEND || HOTENDS == 1
# endif //PIDTEMP
//
// Preheat PLA conf
//
2016-07-10 00:20:12 +02:00
MENU_ITEM ( submenu , MSG_PREHEAT_1_SETTINGS , lcd_control_temperature_preheat_pla_settings_menu ) ;
2016-06-11 23:12:00 +02:00
//
// Preheat ABS conf
//
2016-07-10 00:20:12 +02:00
MENU_ITEM ( submenu , MSG_PREHEAT_2_SETTINGS , lcd_control_temperature_preheat_abs_settings_menu ) ;
2016-06-11 23:12:00 +02:00
END_MENU ( ) ;
2015-02-22 02:38:56 +01:00
}
2016-06-11 23:12:00 +02:00
/**
*
* " Temperature " > " Preheat PLA conf " submenu
*
*/
static void lcd_control_temperature_preheat_pla_settings_menu ( ) {
START_MENU ( ) ;
MENU_ITEM ( back , MSG_TEMPERATURE ) ;
2016-07-10 00:20:12 +02:00
MENU_ITEM_EDIT ( int3 , MSG_FAN_SPEED , & preheatFanSpeed1 , 0 , 255 ) ;
2016-06-11 23:12:00 +02:00
# if TEMP_SENSOR_0 != 0
2016-07-10 00:20:12 +02:00
MENU_ITEM_EDIT ( int3 , MSG_NOZZLE , & preheatHotendTemp1 , HEATER_0_MINTEMP , HEATER_0_MAXTEMP - 15 ) ;
2016-06-11 23:12:00 +02:00
# endif
# if TEMP_SENSOR_BED != 0
2016-07-10 00:20:12 +02:00
MENU_ITEM_EDIT ( int3 , MSG_BED , & preheatBedTemp1 , BED_MINTEMP , BED_MAXTEMP - 15 ) ;
2016-06-11 23:12:00 +02:00
# endif
# if ENABLED(EEPROM_SETTINGS)
MENU_ITEM ( function , MSG_STORE_EPROM , Config_StoreSettings ) ;
# endif
END_MENU ( ) ;
}
2015-02-22 02:38:56 +01:00
2016-06-11 23:12:00 +02:00
/**
*
* " Temperature " > " Preheat ABS conf " submenu
*
*/
static void lcd_control_temperature_preheat_abs_settings_menu ( ) {
START_MENU ( ) ;
MENU_ITEM ( back , MSG_TEMPERATURE ) ;
2016-07-10 00:20:12 +02:00
MENU_ITEM_EDIT ( int3 , MSG_FAN_SPEED , & preheatFanSpeed2 , 0 , 255 ) ;
2016-06-11 23:12:00 +02:00
# if TEMP_SENSOR_0 != 0
2016-07-10 00:20:12 +02:00
MENU_ITEM_EDIT ( int3 , MSG_NOZZLE , & preheatHotendTemp2 , HEATER_0_MINTEMP , HEATER_0_MAXTEMP - 15 ) ;
2016-06-11 23:12:00 +02:00
# endif
# if TEMP_SENSOR_BED != 0
2016-07-10 00:20:12 +02:00
MENU_ITEM_EDIT ( int3 , MSG_BED , & preheatBedTemp2 , BED_MINTEMP , BED_MAXTEMP - 15 ) ;
2016-06-11 23:12:00 +02:00
# endif
# if ENABLED(EEPROM_SETTINGS)
MENU_ITEM ( function , MSG_STORE_EPROM , Config_StoreSettings ) ;
# endif
END_MENU ( ) ;
2015-02-22 02:38:56 +01:00
}
2013-07-14 10:28:26 +02:00
2016-06-11 23:12:00 +02:00
static void _reset_acceleration_rates ( ) { planner . reset_acceleration_rates ( ) ; }
/**
*
* " Control " > " Motion " submenu
*
*/
static void lcd_control_motion_menu ( ) {
2015-04-08 06:11:03 +02:00
START_MENU ( ) ;
2016-04-03 06:12:18 +02:00
MENU_ITEM ( back , MSG_CONTROL ) ;
2016-06-15 03:05:20 +02:00
# if HAS_BED_PROBE
2016-06-11 23:12:00 +02:00
MENU_ITEM_EDIT ( float32 , MSG_ZPROBE_ZOFFSET , & zprobe_zoffset , Z_PROBE_OFFSET_RANGE_MIN , Z_PROBE_OFFSET_RANGE_MAX ) ;
2015-04-08 06:11:03 +02:00
# endif
2016-06-11 23:12:00 +02:00
// Manual bed leveling, Bed Z:
# if ENABLED(MANUAL_BED_LEVELING)
MENU_ITEM_EDIT ( float43 , MSG_BED_Z , & mbl . z_offset , - 1 , 1 ) ;
# endif
MENU_ITEM_EDIT ( float5 , MSG_ACC , & planner . acceleration , 10 , 99000 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VXY_JERK , & planner . max_xy_jerk , 1 , 990 ) ;
# if ENABLED(DELTA)
MENU_ITEM_EDIT ( float3 , MSG_VZ_JERK , & planner . max_z_jerk , 1 , 990 ) ;
# else
MENU_ITEM_EDIT ( float52 , MSG_VZ_JERK , & planner . max_z_jerk , 0.1 , 990 ) ;
# endif
MENU_ITEM_EDIT ( float3 , MSG_VE_JERK , & planner . max_e_jerk , 1 , 990 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VMAX MSG_X , & planner . max_feedrate [ X_AXIS ] , 1 , 999 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VMAX MSG_Y , & planner . max_feedrate [ Y_AXIS ] , 1 , 999 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VMAX MSG_Z , & planner . max_feedrate [ Z_AXIS ] , 1 , 999 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VMAX MSG_E , & planner . max_feedrate [ E_AXIS ] , 1 , 999 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VMIN , & planner . min_feedrate , 0 , 999 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VTRAV_MIN , & planner . min_travel_feedrate , 0 , 999 ) ;
MENU_ITEM_EDIT_CALLBACK ( long5 , MSG_AMAX MSG_X , & planner . max_acceleration_mm_per_s2 [ X_AXIS ] , 100 , 99000 , _reset_acceleration_rates ) ;
MENU_ITEM_EDIT_CALLBACK ( long5 , MSG_AMAX MSG_Y , & planner . max_acceleration_mm_per_s2 [ Y_AXIS ] , 100 , 99000 , _reset_acceleration_rates ) ;
MENU_ITEM_EDIT_CALLBACK ( long5 , MSG_AMAX MSG_Z , & planner . max_acceleration_mm_per_s2 [ Z_AXIS ] , 10 , 99000 , _reset_acceleration_rates ) ;
MENU_ITEM_EDIT_CALLBACK ( long5 , MSG_AMAX MSG_E , & planner . max_acceleration_mm_per_s2 [ E_AXIS ] , 100 , 99000 , _reset_acceleration_rates ) ;
MENU_ITEM_EDIT ( float5 , MSG_A_RETRACT , & planner . retract_acceleration , 100 , 99000 ) ;
MENU_ITEM_EDIT ( float5 , MSG_A_TRAVEL , & planner . travel_acceleration , 100 , 99000 ) ;
MENU_ITEM_EDIT ( float52 , MSG_XSTEPS , & planner . axis_steps_per_mm [ X_AXIS ] , 5 , 9999 ) ;
MENU_ITEM_EDIT ( float52 , MSG_YSTEPS , & planner . axis_steps_per_mm [ Y_AXIS ] , 5 , 9999 ) ;
# if ENABLED(DELTA)
MENU_ITEM_EDIT ( float52 , MSG_ZSTEPS , & planner . axis_steps_per_mm [ Z_AXIS ] , 5 , 9999 ) ;
# else
MENU_ITEM_EDIT ( float51 , MSG_ZSTEPS , & planner . axis_steps_per_mm [ Z_AXIS ] , 5 , 9999 ) ;
# endif
MENU_ITEM_EDIT ( float51 , MSG_ESTEPS , & planner . axis_steps_per_mm [ E_AXIS ] , 5 , 9999 ) ;
# if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
MENU_ITEM_EDIT ( bool , MSG_ENDSTOP_ABORT , & stepper . abort_on_endstop_hit ) ;
# endif
# if ENABLED(SCARA)
MENU_ITEM_EDIT ( float74 , MSG_XSCALE , & axis_scaling [ X_AXIS ] , 0.5 , 2 ) ;
MENU_ITEM_EDIT ( float74 , MSG_YSCALE , & axis_scaling [ Y_AXIS ] , 0.5 , 2 ) ;
2015-04-08 06:11:03 +02:00
# endif
END_MENU ( ) ;
}
2011-12-12 19:34:37 +01:00
2016-06-11 23:12:00 +02:00
/**
*
* " Control " > " Filament " submenu
*
*/
static void lcd_control_volumetric_menu ( ) {
START_MENU ( ) ;
MENU_ITEM ( back , MSG_CONTROL ) ;
2015-02-22 02:38:56 +01:00
2016-06-11 23:12:00 +02:00
MENU_ITEM_EDIT_CALLBACK ( bool , MSG_VOLUMETRIC_ENABLED , & volumetric_enabled , calculate_volumetric_multipliers ) ;
if ( volumetric_enabled ) {
# if EXTRUDERS == 1
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( float43 , MSG_FILAMENT_DIAM , & filament_size [ 0 ] , 1.5 , 3.25 , calculate_volumetric_multipliers ) ;
# else //EXTRUDERS > 1
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( float43 , MSG_FILAMENT_DIAM MSG_DIAM_E1 , & filament_size [ 0 ] , 1.5 , 3.25 , calculate_volumetric_multipliers ) ;
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( float43 , MSG_FILAMENT_DIAM MSG_DIAM_E2 , & filament_size [ 1 ] , 1.5 , 3.25 , calculate_volumetric_multipliers ) ;
# if EXTRUDERS > 2
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( float43 , MSG_FILAMENT_DIAM MSG_DIAM_E3 , & filament_size [ 2 ] , 1.5 , 3.25 , calculate_volumetric_multipliers ) ;
# if EXTRUDERS > 3
MENU_MULTIPLIER_ITEM_EDIT_CALLBACK ( float43 , MSG_FILAMENT_DIAM MSG_DIAM_E4 , & filament_size [ 3 ] , 1.5 , 3.25 , calculate_volumetric_multipliers ) ;
# endif //EXTRUDERS > 3
# endif //EXTRUDERS > 2
# endif //EXTRUDERS > 1
2015-09-05 02:40:12 +02:00
}
2011-12-12 19:34:37 +01:00
2016-06-11 23:12:00 +02:00
END_MENU ( ) ;
2015-02-22 02:38:56 +01:00
}
2013-12-08 21:34:56 +01:00
2015-09-05 02:40:12 +02:00
/**
*
2016-06-11 23:12:00 +02:00
* " Control " > " Contrast " submenu
2015-09-05 02:40:12 +02:00
*
*/
2016-06-11 23:12:00 +02:00
# if HAS_LCD_CONTRAST
static void lcd_set_contrast ( ) {
2016-07-11 02:53:11 +02:00
if ( LCD_CLICKED ) { lcd_goto_previous_menu ( true ) ; return ; }
2016-06-11 23:12:00 +02:00
ENCODER_DIRECTION_NORMAL ( ) ;
if ( encoderPosition ) {
set_lcd_contrast ( lcd_contrast + encoderPosition ) ;
encoderPosition = 0 ;
lcdDrawUpdate = LCDVIEW_REDRAW_NOW ;
}
if ( lcdDrawUpdate ) {
lcd_implementation_drawedit ( PSTR ( MSG_CONTRAST ) ,
# if LCD_CONTRAST_MAX >= 100
itostr3 ( lcd_contrast )
# else
itostr2 ( lcd_contrast )
# endif
) ;
}
2011-12-12 19:34:37 +01:00
}
2016-06-11 23:12:00 +02:00
# endif // HAS_LCD_CONTRAST
/**
*
* " Control " > " Retract " submenu
*
*/
# if ENABLED(FWRETRACT)
static void lcd_control_retract_menu ( ) {
START_MENU ( ) ;
MENU_ITEM ( back , MSG_CONTROL ) ;
MENU_ITEM_EDIT ( bool , MSG_AUTORETRACT , & autoretract_enabled ) ;
MENU_ITEM_EDIT ( float52 , MSG_CONTROL_RETRACT , & retract_length , 0 , 100 ) ;
# if EXTRUDERS > 1
MENU_ITEM_EDIT ( float52 , MSG_CONTROL_RETRACT_SWAP , & retract_length_swap , 0 , 100 ) ;
# endif
2016-06-22 12:27:31 +02:00
MENU_ITEM_EDIT ( float3 , MSG_CONTROL_RETRACTF , & retract_feedrate_mm_s , 1 , 999 ) ;
2016-06-11 23:12:00 +02:00
MENU_ITEM_EDIT ( float52 , MSG_CONTROL_RETRACT_ZLIFT , & retract_zlift , 0 , 999 ) ;
MENU_ITEM_EDIT ( float52 , MSG_CONTROL_RETRACT_RECOVER , & retract_recover_length , 0 , 100 ) ;
# if EXTRUDERS > 1
MENU_ITEM_EDIT ( float52 , MSG_CONTROL_RETRACT_RECOVER_SWAP , & retract_recover_length_swap , 0 , 100 ) ;
# endif
MENU_ITEM_EDIT ( float3 , MSG_CONTROL_RETRACT_RECOVERF , & retract_recover_feedrate , 1 , 999 ) ;
END_MENU ( ) ;
2015-09-05 02:40:12 +02:00
}
2016-06-11 23:12:00 +02:00
# endif // FWRETRACT
2015-09-05 02:40:12 +02:00
2016-06-11 23:12:00 +02:00
# if ENABLED(SDSUPPORT)
2016-04-21 21:40:22 +02:00
2016-06-11 23:12:00 +02:00
# if !PIN_EXISTS(SD_DETECT)
static void lcd_sd_refresh ( ) {
card . initsd ( ) ;
2016-07-09 00:08:56 +02:00
encoderTopLine = 0 ;
2016-06-11 23:12:00 +02:00
}
# endif
static void lcd_sd_updir ( ) {
card . updir ( ) ;
2016-07-09 00:08:56 +02:00
encoderTopLine = 0 ;
2016-06-11 23:12:00 +02:00
}
/**
*
* " Print from SD " submenu
*
*/
void lcd_sdcard_menu ( ) {
ENCODER_DIRECTION_MENUS ( ) ;
if ( lcdDrawUpdate = = 0 & & LCD_CLICKED = = 0 ) return ; // nothing to do (so don't thrash the SD card)
uint16_t fileCnt = card . getnrfilenames ( ) ;
START_MENU ( ) ;
MENU_ITEM ( back , MSG_MAIN ) ;
card . getWorkDirName ( ) ;
if ( card . filename [ 0 ] = = ' / ' ) {
# if !PIN_EXISTS(SD_DETECT)
MENU_ITEM ( function , LCD_STR_REFRESH MSG_REFRESH , lcd_sd_refresh ) ;
# endif
2015-09-05 02:40:12 +02:00
}
else {
2016-06-11 23:12:00 +02:00
MENU_ITEM ( function , LCD_STR_FOLDER " .. " , lcd_sd_updir ) ;
2015-09-05 02:40:12 +02:00
}
2016-06-11 23:12:00 +02:00
for ( uint16_t i = 0 ; i < fileCnt ; i + + ) {
2016-07-09 21:26:20 +02:00
if ( _menuLineNr = = _thisItemNr ) {
2016-06-11 23:12:00 +02:00
card . getfilename (
# if ENABLED(SDCARD_RATHERRECENTFIRST)
fileCnt - 1 -
# endif
i
) ;
if ( card . filenameIsDir )
MENU_ITEM ( sddirectory , MSG_CARD_MENU , card . filename , card . longFilename ) ;
else
MENU_ITEM ( sdfile , MSG_CARD_MENU , card . filename , card . longFilename ) ;
}
else {
MENU_ITEM_DUMMY ( ) ;
}
}
END_MENU ( ) ;
2015-02-22 02:38:56 +01:00
}
2015-09-05 02:40:12 +02:00
2016-06-11 23:12:00 +02:00
# endif //SDSUPPORT
2011-12-12 19:34:37 +01:00
2016-06-30 11:24:29 +02:00
# if ENABLED(LCD_INFO_MENU)
2016-07-02 23:04:18 +02:00
2016-06-30 11:24:29 +02:00
# if ENABLED(PRINTCOUNTER)
/**
*
2016-07-11 02:53:11 +02:00
* About Printer > Statistics submenu
2016-06-30 11:24:29 +02:00
*
*/
static void lcd_info_stats_menu ( ) {
2016-07-11 02:53:11 +02:00
if ( LCD_CLICKED ) { lcd_goto_previous_menu ( true ) ; return ; }
2016-06-30 11:24:29 +02:00
PrintCounter print_job_counter = PrintCounter ( ) ;
print_job_counter . loadStats ( ) ;
printStatistics stats = print_job_counter . getStats ( ) ;
2016-07-02 23:04:18 +02:00
char printTime [ 6 ] ;
2016-07-10 13:08:05 +02:00
sprintf ( printTime , " %02d:%02d " , int ( stats . printTime / 3600 ) , int ( stats . printTime / 60 ) % 60 ) ;
2016-06-30 11:24:29 +02:00
2016-07-04 00:12:21 +02:00
START_SCREEN ( ) ;
2016-07-09 03:18:40 +02:00
STATIC_ITEM ( MSG_INFO_PRINT_COUNT " : " , false , false , itostr3left ( stats . totalPrints ) ) ; // Print Count : 999
STATIC_ITEM ( MSG_INFO_FINISHED_PRINTS " : " , false , false , itostr3left ( stats . finishedPrints ) ) ; // Finished : 666
STATIC_ITEM ( MSG_INFO_PRINT_TIME " : " , false , false , printTime ) ; // Total Time : 12:34
2016-07-04 00:12:21 +02:00
END_SCREEN ( ) ;
2016-06-30 11:24:29 +02:00
}
2016-07-02 23:04:18 +02:00
# endif // PRINTCOUNTER
2016-06-30 11:24:29 +02:00
/**
*
2016-07-02 23:04:18 +02:00
* About Printer > Thermistors
2016-06-30 11:24:29 +02:00
*
*/
static void lcd_info_thermistors_menu ( ) {
2016-07-11 02:53:11 +02:00
if ( LCD_CLICKED ) { lcd_goto_previous_menu ( true ) ; return ; }
2016-07-04 00:12:21 +02:00
START_SCREEN ( ) ;
2016-06-30 11:24:29 +02:00
# define THERMISTOR_ID TEMP_SENSOR_0
# include "thermistornames.h"
2016-07-09 03:20:15 +02:00
STATIC_ITEM ( " T0: " THERMISTOR_NAME , false , true ) ;
STATIC_ITEM ( MSG_INFO_MIN_TEMP " : " STRINGIFY ( HEATER_0_MINTEMP ) , false ) ;
STATIC_ITEM ( MSG_INFO_MAX_TEMP " : " STRINGIFY ( HEATER_0_MAXTEMP ) , false ) ;
2016-06-30 11:24:29 +02:00
# if TEMP_SENSOR_1 != 0
# undef THERMISTOR_ID
# define THERMISTOR_ID TEMP_SENSOR_1
# include "thermistornames.h"
2016-07-09 03:20:15 +02:00
STATIC_ITEM ( " T1: " THERMISTOR_NAME , false , true ) ;
STATIC_ITEM ( MSG_INFO_MIN_TEMP " : " STRINGIFY ( HEATER_1_MINTEMP ) , false ) ;
STATIC_ITEM ( MSG_INFO_MAX_TEMP " : " STRINGIFY ( HEATER_1_MAXTEMP ) , false ) ;
2016-06-30 11:24:29 +02:00
# endif
# if TEMP_SENSOR_2 != 0
# undef THERMISTOR_ID
# define THERMISTOR_ID TEMP_SENSOR_2
# include "thermistornames.h"
2016-07-09 03:20:15 +02:00
STATIC_ITEM ( " T2: " THERMISTOR_NAME , false , true ) ;
STATIC_ITEM ( MSG_INFO_MIN_TEMP " : " STRINGIFY ( HEATER_2_MINTEMP ) , false ) ;
STATIC_ITEM ( MSG_INFO_MAX_TEMP " : " STRINGIFY ( HEATER_2_MAXTEMP ) , false ) ;
2016-06-30 11:24:29 +02:00
# endif
# if TEMP_SENSOR_3 != 0
# undef THERMISTOR_ID
# define THERMISTOR_ID TEMP_SENSOR_3
# include "thermistornames.h"
2016-07-09 03:20:15 +02:00
STATIC_ITEM ( " T3: " THERMISTOR_NAME , false , true ) ;
STATIC_ITEM ( MSG_INFO_MIN_TEMP " : " STRINGIFY ( HEATER_3_MINTEMP ) , false ) ;
STATIC_ITEM ( MSG_INFO_MAX_TEMP " : " STRINGIFY ( HEATER_3_MAXTEMP ) , false ) ;
2016-06-30 11:24:29 +02:00
# endif
2016-07-02 23:04:18 +02:00
2016-06-30 11:24:29 +02:00
# if TEMP_SENSOR_BED != 0
# undef THERMISTOR_ID
# define THERMISTOR_ID TEMP_SENSOR_BED
# include "thermistornames.h"
2016-07-09 03:20:15 +02:00
STATIC_ITEM ( " TBed: " THERMISTOR_NAME , false , true ) ;
STATIC_ITEM ( MSG_INFO_MIN_TEMP " : " STRINGIFY ( BED_MINTEMP ) , false ) ;
STATIC_ITEM ( MSG_INFO_MAX_TEMP " : " STRINGIFY ( BED_MAXTEMP ) , false ) ;
2016-06-30 11:24:29 +02:00
# endif
2016-07-04 00:12:21 +02:00
END_SCREEN ( ) ;
2016-06-30 11:24:29 +02:00
}
/**
*
2016-07-02 23:04:18 +02:00
* About Printer > Board Info
2016-06-30 11:24:29 +02:00
*
*/
static void lcd_info_board_menu ( ) {
2016-07-11 02:53:11 +02:00
if ( LCD_CLICKED ) { lcd_goto_previous_menu ( true ) ; return ; }
2016-07-04 00:12:21 +02:00
START_SCREEN ( ) ;
2016-07-09 03:18:40 +02:00
STATIC_ITEM ( BOARD_NAME , true , true ) ; // MyPrinterController
2016-06-30 11:24:29 +02:00
STATIC_ITEM ( MSG_INFO_BAUDRATE " : " STRINGIFY ( BAUDRATE ) ) ; // Baud: 250000
STATIC_ITEM ( MSG_INFO_PROTOCOL " : " PROTOCOL_VERSION ) ; // Protocol: 1.0
# ifdef POWER_SUPPLY
# if (POWER_SUPPLY == 1)
STATIC_ITEM ( MSG_INFO_PSU " : ATX " ) ; // Power Supply: ATX
# elif (POWER_SUPPLY == 2)
STATIC_ITEM ( MSG_INFO_PSU " : XBox " ) ; // Power Supply: XBox
# endif
# endif // POWER_SUPPLY
2016-07-04 00:12:21 +02:00
END_SCREEN ( ) ;
2016-06-30 11:24:29 +02:00
}
/**
*
2016-07-02 23:04:18 +02:00
* About Printer > Printer Info
2016-06-30 11:24:29 +02:00
*
*/
2016-07-02 23:04:18 +02:00
static void lcd_info_printer_menu ( ) {
2016-07-11 02:53:11 +02:00
if ( LCD_CLICKED ) { lcd_goto_previous_menu ( true ) ; return ; }
2016-07-04 00:12:21 +02:00
START_SCREEN ( ) ;
2016-07-09 03:18:40 +02:00
STATIC_ITEM ( MSG_MARLIN , true , true ) ; // Marlin
2016-06-30 11:24:29 +02:00
STATIC_ITEM ( SHORT_BUILD_VERSION ) ; // x.x.x-Branch
STATIC_ITEM ( STRING_DISTRIBUTION_DATE ) ; // YYYY-MM-DD HH:MM
STATIC_ITEM ( MACHINE_NAME ) ; // My3DPrinter
STATIC_ITEM ( WEBSITE_URL ) ; // www.my3dprinter.com
STATIC_ITEM ( MSG_INFO_EXTRUDERS " : " STRINGIFY ( EXTRUDERS ) ) ; // Extruders: 2
2016-07-04 00:12:21 +02:00
END_SCREEN ( ) ;
2016-07-02 23:04:18 +02:00
}
2016-06-30 11:24:29 +02:00
2016-07-02 23:04:18 +02:00
/**
*
* " About Printer " submenu
*
*/
static void lcd_info_menu ( ) {
START_MENU ( ) ;
MENU_ITEM ( back , MSG_MAIN ) ;
MENU_ITEM ( submenu , MSG_INFO_PRINTER_MENU , lcd_info_printer_menu ) ; // Printer Info >
MENU_ITEM ( submenu , MSG_INFO_BOARD_MENU , lcd_info_board_menu ) ; // Board Info >
MENU_ITEM ( submenu , MSG_INFO_THERMISTOR_MENU , lcd_info_thermistors_menu ) ; // Thermistors >
2016-06-30 11:24:29 +02:00
# if ENABLED(PRINTCOUNTER)
2016-07-02 23:04:18 +02:00
MENU_ITEM ( submenu , MSG_INFO_STATS_MENU , lcd_info_stats_menu ) ; // Printer Statistics >
2016-06-30 11:24:29 +02:00
# endif
END_MENU ( ) ;
}
# endif // LCD_INFO_MENU
2016-04-28 18:57:21 +02:00
# if ENABLED(FILAMENT_CHANGE_FEATURE)
static void lcd_filament_change_resume_print ( ) {
filament_change_menu_response = FILAMENT_CHANGE_RESPONSE_RESUME_PRINT ;
lcdDrawUpdate = 2 ;
lcd_goto_screen ( lcd_status_screen ) ;
}
static void lcd_filament_change_extrude_more ( ) {
filament_change_menu_response = FILAMENT_CHANGE_RESPONSE_EXTRUDE_MORE ;
}
static void lcd_filament_change_option_menu ( ) {
START_MENU ( ) ;
2016-06-25 04:24:24 +02:00
# if LCD_HEIGHT > 2
2016-07-09 03:18:40 +02:00
STATIC_ITEM ( MSG_FILAMENT_CHANGE_OPTION_HEADER , true , false ) ;
2016-06-25 04:24:24 +02:00
# endif
2016-04-28 18:57:21 +02:00
MENU_ITEM ( function , MSG_FILAMENT_CHANGE_OPTION_RESUME , lcd_filament_change_resume_print ) ;
MENU_ITEM ( function , MSG_FILAMENT_CHANGE_OPTION_EXTRUDE , lcd_filament_change_extrude_more ) ;
END_MENU ( ) ;
}
static void lcd_filament_change_init_message ( ) {
2016-07-04 00:12:21 +02:00
START_SCREEN ( ) ;
2016-07-09 03:18:40 +02:00
STATIC_ITEM ( MSG_FILAMENT_CHANGE_HEADER , true , true ) ;
2016-06-25 04:24:24 +02:00
STATIC_ITEM ( MSG_FILAMENT_CHANGE_INIT_1 ) ;
# ifdef MSG_FILAMENT_CHANGE_INIT_2
STATIC_ITEM ( MSG_FILAMENT_CHANGE_INIT_2 ) ;
# endif
# ifdef MSG_FILAMENT_CHANGE_INIT_3
STATIC_ITEM ( MSG_FILAMENT_CHANGE_INIT_3 ) ;
# endif
2016-07-04 00:12:21 +02:00
END_SCREEN ( ) ;
2016-04-28 18:57:21 +02:00
}
static void lcd_filament_change_unload_message ( ) {
2016-07-04 00:12:21 +02:00
START_SCREEN ( ) ;
2016-07-09 03:18:40 +02:00
STATIC_ITEM ( MSG_FILAMENT_CHANGE_HEADER , true , true ) ;
2016-06-25 04:24:24 +02:00
STATIC_ITEM ( MSG_FILAMENT_CHANGE_UNLOAD_1 ) ;
# ifdef MSG_FILAMENT_CHANGE_UNLOAD_2
STATIC_ITEM ( MSG_FILAMENT_CHANGE_UNLOAD_2 ) ;
# endif
# ifdef MSG_FILAMENT_CHANGE_UNLOAD_3
STATIC_ITEM ( MSG_FILAMENT_CHANGE_UNLOAD_3 ) ;
# endif
2016-07-04 00:12:21 +02:00
END_SCREEN ( ) ;
2016-04-28 18:57:21 +02:00
}
static void lcd_filament_change_insert_message ( ) {
2016-07-04 00:12:21 +02:00
START_SCREEN ( ) ;
2016-07-09 03:18:40 +02:00
STATIC_ITEM ( MSG_FILAMENT_CHANGE_HEADER , true , true ) ;
2016-06-25 04:24:24 +02:00
STATIC_ITEM ( MSG_FILAMENT_CHANGE_INSERT_1 ) ;
# ifdef MSG_FILAMENT_CHANGE_INSERT_2
STATIC_ITEM ( MSG_FILAMENT_CHANGE_INSERT_2 ) ;
# endif
# ifdef MSG_FILAMENT_CHANGE_INSERT_3
STATIC_ITEM ( MSG_FILAMENT_CHANGE_INSERT_3 ) ;
# endif
2016-07-04 00:12:21 +02:00
END_SCREEN ( ) ;
2016-04-28 18:57:21 +02:00
}
static void lcd_filament_change_load_message ( ) {
2016-07-04 00:12:21 +02:00
START_SCREEN ( ) ;
2016-07-09 03:18:40 +02:00
STATIC_ITEM ( MSG_FILAMENT_CHANGE_HEADER , true , true ) ;
2016-06-25 04:24:24 +02:00
STATIC_ITEM ( MSG_FILAMENT_CHANGE_LOAD_1 ) ;
# ifdef MSG_FILAMENT_CHANGE_LOAD_2
STATIC_ITEM ( MSG_FILAMENT_CHANGE_LOAD_2 ) ;
# endif
# ifdef MSG_FILAMENT_CHANGE_LOAD_3
STATIC_ITEM ( MSG_FILAMENT_CHANGE_LOAD_3 ) ;
# endif
2016-07-04 00:12:21 +02:00
END_SCREEN ( ) ;
2016-04-28 18:57:21 +02:00
}
static void lcd_filament_change_extrude_message ( ) {
2016-07-04 00:12:21 +02:00
START_SCREEN ( ) ;
2016-07-09 03:18:40 +02:00
STATIC_ITEM ( MSG_FILAMENT_CHANGE_HEADER , true , true ) ;
2016-06-25 04:24:24 +02:00
STATIC_ITEM ( MSG_FILAMENT_CHANGE_EXTRUDE_1 ) ;
# ifdef MSG_FILAMENT_CHANGE_EXTRUDE_2
STATIC_ITEM ( MSG_FILAMENT_CHANGE_EXTRUDE_2 ) ;
# endif
# ifdef MSG_FILAMENT_CHANGE_EXTRUDE_3
STATIC_ITEM ( MSG_FILAMENT_CHANGE_EXTRUDE_3 ) ;
# endif
2016-07-04 00:12:21 +02:00
END_SCREEN ( ) ;
2016-04-28 18:57:21 +02:00
}
static void lcd_filament_change_resume_message ( ) {
2016-07-04 00:12:21 +02:00
START_SCREEN ( ) ;
2016-07-09 03:18:40 +02:00
STATIC_ITEM ( MSG_FILAMENT_CHANGE_HEADER , true , true ) ;
2016-06-25 04:24:24 +02:00
STATIC_ITEM ( MSG_FILAMENT_CHANGE_RESUME_1 ) ;
# ifdef MSG_FILAMENT_CHANGE_RESUME_2
STATIC_ITEM ( MSG_FILAMENT_CHANGE_RESUME_2 ) ;
# endif
# ifdef MSG_FILAMENT_CHANGE_RESUME_3
STATIC_ITEM ( MSG_FILAMENT_CHANGE_RESUME_3 ) ;
# endif
2016-07-04 00:12:21 +02:00
END_SCREEN ( ) ;
2016-04-28 18:57:21 +02:00
}
void lcd_filament_change_show_message ( FilamentChangeMessage message ) {
switch ( message ) {
case FILAMENT_CHANGE_MESSAGE_INIT :
defer_return_to_status = true ;
lcd_goto_screen ( lcd_filament_change_init_message ) ;
break ;
case FILAMENT_CHANGE_MESSAGE_UNLOAD :
lcd_goto_screen ( lcd_filament_change_unload_message ) ;
break ;
case FILAMENT_CHANGE_MESSAGE_INSERT :
lcd_goto_screen ( lcd_filament_change_insert_message ) ;
break ;
case FILAMENT_CHANGE_MESSAGE_LOAD :
lcd_goto_screen ( lcd_filament_change_load_message ) ;
break ;
case FILAMENT_CHANGE_MESSAGE_EXTRUDE :
lcd_goto_screen ( lcd_filament_change_extrude_message ) ;
break ;
case FILAMENT_CHANGE_MESSAGE_OPTION :
filament_change_menu_response = FILAMENT_CHANGE_RESPONSE_WAIT_FOR ;
lcd_goto_screen ( lcd_filament_change_option_menu ) ;
break ;
case FILAMENT_CHANGE_MESSAGE_RESUME :
lcd_goto_screen ( lcd_filament_change_resume_message ) ;
break ;
case FILAMENT_CHANGE_MESSAGE_STATUS :
lcd_return_to_status ( ) ;
break ;
}
}
# endif // FILAMENT_CHANGE_FEATURE
2016-06-11 23:12:00 +02:00
/**
*
* Functions for editing single values
*
* The " menu_edit_type " macro generates the functions needed to edit a numerical value .
*
* For example , menu_edit_type ( int , int3 , itostr3 , 1 ) expands into these functions :
*
* bool _menu_edit_int3 ( ) ;
* void menu_edit_int3 ( ) ; // edit int (interactively)
* void menu_edit_callback_int3 ( ) ; // edit int (interactively) with callback on completion
* static void _menu_action_setting_edit_int3 ( const char * pstr , int * ptr , int minValue , int maxValue ) ;
* static void menu_action_setting_edit_int3 ( const char * pstr , int * ptr , int minValue , int maxValue ) ;
2016-06-11 23:19:17 +02:00
* static void menu_action_setting_edit_callback_int3 ( const char * pstr , int * ptr , int minValue , int maxValue , screenFunc_t callback ) ; // edit int with callback
2016-06-11 23:12:00 +02:00
*
* You can then use one of the menu macros to present the edit interface :
* MENU_ITEM_EDIT ( int3 , MSG_SPEED , & feedrate_multiplier , 10 , 999 )
*
* This expands into a more primitive menu item :
* MENU_ITEM ( setting_edit_int3 , MSG_SPEED , PSTR ( MSG_SPEED ) , & feedrate_multiplier , 10 , 999 )
*
*
* Also : MENU_MULTIPLIER_ITEM_EDIT , MENU_ITEM_EDIT_CALLBACK , and MENU_MULTIPLIER_ITEM_EDIT_CALLBACK
*
* menu_action_setting_edit_int3 ( PSTR ( MSG_SPEED ) , & feedrate_multiplier , 10 , 999 )
*/
# define menu_edit_type(_type, _name, _strFunc, scale) \
bool _menu_edit_ # # _name ( ) { \
ENCODER_DIRECTION_NORMAL ( ) ; \
bool isClicked = LCD_CLICKED ; \
if ( ( int32_t ) encoderPosition < 0 ) encoderPosition = 0 ; \
if ( ( int32_t ) encoderPosition > maxEditValue ) encoderPosition = maxEditValue ; \
if ( lcdDrawUpdate ) \
lcd_implementation_drawedit ( editLabel , _strFunc ( ( ( _type ) ( ( int32_t ) encoderPosition + minEditValue ) ) / scale ) ) ; \
if ( isClicked ) { \
* ( ( _type * ) editValue ) = ( ( _type ) ( ( int32_t ) encoderPosition + minEditValue ) ) / scale ; \
lcd_goto_previous_menu ( true ) ; \
} \
return isClicked ; \
Allow Edit menu to call fn after edit; Fix PID Ki and Kd display in menus; Actually use changed PID and Max Accel values
Add new 'callback' edit-menu types that call a function after the edit is done. Use this to display and edit Ki and Kd correctly (removing the scaling first and reapplying it after). Also use it to reset maximum stepwise acceleration rates, after updating mm/s^2 rates via menus. (Previously, changes did nothing to affect planner unless saved back to EEPROM, and the machine reset).
Add calls to updatePID() so that PID loop uses updated values whether set by gcode (it already did this), or by restoring defaults, or loading from EEPROM (it didn't do those last two). Similarly, update the maximum step/s^2 accel rates when the mm/s^2 values are changed - whether by menu edits, restore defaults, or EEPROM read.
Refactor the acceleration rate update logic, and the PID scaling logic, into new functions that can be called from wherever, including the callbacks.
Add menu items to allow the z jerk and e jerk to be viewed/edited in the Control->Motion menu, as per xy jerk.
Conflicts:
Marlin/language.h
2013-03-19 15:05:11 +01:00
} \
2016-06-11 23:12:00 +02:00
void menu_edit_ # # _name ( ) { _menu_edit_ # # _name ( ) ; } \
void menu_edit_callback_ # # _name ( ) { if ( _menu_edit_ # # _name ( ) ) ( * callbackFunc ) ( ) ; } \
static void _menu_action_setting_edit_ # # _name ( const char * pstr , _type * ptr , _type minValue , _type maxValue ) { \
lcd_save_previous_menu ( ) ; \
\
lcdDrawUpdate = LCDVIEW_CLEAR_CALL_REDRAW ; \
\
editLabel = pstr ; \
editValue = ptr ; \
minEditValue = minValue * scale ; \
maxEditValue = maxValue * scale - minEditValue ; \
encoderPosition = ( * ptr ) * scale - minEditValue ; \
} \
static void menu_action_setting_edit_ # # _name ( const char * pstr , _type * ptr , _type minValue , _type maxValue ) { \
_menu_action_setting_edit_ # # _name ( pstr , ptr , minValue , maxValue ) ; \
2016-06-11 23:19:17 +02:00
currentScreen = menu_edit_ # # _name ; \
2016-06-11 23:12:00 +02:00
} \
2016-06-11 23:19:17 +02:00
static void menu_action_setting_edit_callback_ # # _name ( const char * pstr , _type * ptr , _type minValue , _type maxValue , screenFunc_t callback ) { \
2016-06-11 23:12:00 +02:00
_menu_action_setting_edit_ # # _name ( pstr , ptr , minValue , maxValue ) ; \
2016-06-11 23:19:17 +02:00
currentScreen = menu_edit_callback_ # # _name ; \
2016-06-11 23:12:00 +02:00
callbackFunc = callback ; \
}
menu_edit_type ( int , int3 , itostr3 , 1 ) ;
menu_edit_type ( float , float3 , ftostr3 , 1 ) ;
menu_edit_type ( float , float32 , ftostr32 , 100 ) ;
menu_edit_type ( float , float43 , ftostr43sign , 1000 ) ;
menu_edit_type ( float , float5 , ftostr5rj , 0.01 ) ;
menu_edit_type ( float , float51 , ftostr51sign , 10 ) ;
menu_edit_type ( float , float52 , ftostr52sign , 100 ) ;
menu_edit_type ( unsigned long , long5 , ftostr5rj , 0.01 ) ;
2011-12-12 19:34:37 +01:00
2016-06-11 23:12:00 +02:00
/**
*
* Handlers for RepRap World Keypad input
*
*/
# if ENABLED(REPRAPWORLD_KEYPAD)
static void reprapworld_keypad_move_z_up ( ) {
encoderPosition = 1 ;
move_menu_scale = REPRAPWORLD_KEYPAD_MOVE_STEP ;
lcd_move_z ( ) ;
}
static void reprapworld_keypad_move_z_down ( ) {
encoderPosition = - 1 ;
move_menu_scale = REPRAPWORLD_KEYPAD_MOVE_STEP ;
lcd_move_z ( ) ;
}
static void reprapworld_keypad_move_x_left ( ) {
encoderPosition = - 1 ;
move_menu_scale = REPRAPWORLD_KEYPAD_MOVE_STEP ;
lcd_move_x ( ) ;
}
static void reprapworld_keypad_move_x_right ( ) {
encoderPosition = 1 ;
move_menu_scale = REPRAPWORLD_KEYPAD_MOVE_STEP ;
lcd_move_x ( ) ;
}
static void reprapworld_keypad_move_y_down ( ) {
encoderPosition = 1 ;
move_menu_scale = REPRAPWORLD_KEYPAD_MOVE_STEP ;
lcd_move_y ( ) ;
}
static void reprapworld_keypad_move_y_up ( ) {
encoderPosition = - 1 ;
move_menu_scale = REPRAPWORLD_KEYPAD_MOVE_STEP ;
lcd_move_y ( ) ;
}
static void reprapworld_keypad_move_home ( ) {
enqueue_and_echo_commands_P ( PSTR ( " G28 " ) ) ; // move all axes home
}
# endif // REPRAPWORLD_KEYPAD
2015-06-17 16:31:14 +02:00
2016-06-11 23:12:00 +02:00
/**
*
* Audio feedback for controller clicks
*
*/
2015-10-03 08:08:58 +02:00
2015-07-31 07:26:53 +02:00
# if ENABLED(LCD_USE_I2C_BUZZER)
2016-06-11 23:12:00 +02:00
void lcd_buzz ( long duration , uint16_t freq ) { // called from buzz() in Marlin_main.cpp where lcd is unknown
lcd . buzz ( duration , freq ) ;
}
2015-03-26 09:00:34 +01:00
# endif
2015-09-05 02:40:12 +02:00
2016-06-11 23:12:00 +02:00
void lcd_quick_feedback ( ) {
lcdDrawUpdate = LCDVIEW_CLEAR_CALL_REDRAW ;
next_button_update_ms = millis ( ) + 500 ;
2015-09-05 02:40:12 +02:00
2016-07-11 04:25:23 +02:00
// Buzz and wait. The delay is needed for buttons to settle!
2016-06-11 23:12:00 +02:00
# if ENABLED(LCD_USE_I2C_BUZZER)
lcd . buzz ( LCD_FEEDBACK_FREQUENCY_DURATION_MS , LCD_FEEDBACK_FREQUENCY_HZ ) ;
2016-07-11 04:25:23 +02:00
delay ( 10 ) ;
2016-06-11 23:12:00 +02:00
# elif PIN_EXISTS(BEEPER)
buzzer . tone ( LCD_FEEDBACK_FREQUENCY_DURATION_MS , LCD_FEEDBACK_FREQUENCY_HZ ) ;
2016-07-11 04:25:23 +02:00
for ( int8_t i = 5 ; i - - ; ) { buzzer . tick ( ) ; delay ( 2 ) ; }
2016-06-11 23:12:00 +02:00
# endif
2015-09-11 11:18:42 +02:00
}
2016-06-11 23:12:00 +02:00
/**
*
* Menu actions
*
*/
static void menu_action_back ( ) { lcd_goto_previous_menu ( ) ; }
2016-06-11 23:19:17 +02:00
static void menu_action_submenu ( screenFunc_t func ) { lcd_save_previous_menu ( ) ; lcd_goto_screen ( func ) ; }
2016-06-11 23:12:00 +02:00
static void menu_action_gcode ( const char * pgcode ) { enqueue_and_echo_commands_P ( pgcode ) ; }
2016-06-11 23:19:17 +02:00
static void menu_action_function ( screenFunc_t func ) { ( * func ) ( ) ; }
2015-09-05 02:40:12 +02:00
2016-06-11 23:12:00 +02:00
# if ENABLED(SDSUPPORT)
2015-09-05 02:40:12 +02:00
2016-06-11 23:12:00 +02:00
static void menu_action_sdfile ( const char * filename , char * longFilename ) {
UNUSED ( longFilename ) ;
card . openAndPrintFile ( filename ) ;
lcd_return_to_status ( ) ;
}
static void menu_action_sddirectory ( const char * filename , char * longFilename ) {
UNUSED ( longFilename ) ;
card . chdir ( filename ) ;
encoderPosition = 0 ;
}
# endif //SDSUPPORT
static void menu_action_setting_edit_bool ( const char * pstr , bool * ptr ) { UNUSED ( pstr ) ; * ptr = ! ( * ptr ) ; }
2016-06-11 23:19:17 +02:00
static void menu_action_setting_edit_callback_bool ( const char * pstr , bool * ptr , screenFunc_t callback ) {
2016-06-11 23:12:00 +02:00
menu_action_setting_edit_bool ( pstr , ptr ) ;
( * callback ) ( ) ;
}
2015-02-22 02:38:56 +01:00
# endif //ULTIPANEL
2011-12-12 19:34:37 +01:00
2012-12-12 11:47:03 +01:00
/** LCD API **/
2015-02-22 02:38:56 +01:00
void lcd_init ( ) {
2015-10-03 08:08:58 +02:00
2015-02-22 02:38:56 +01:00
lcd_implementation_init ( ) ;
2015-07-31 07:26:53 +02:00
# if ENABLED(NEWPANEL)
2016-03-27 13:25:33 +02:00
# if BUTTON_EXISTS(EN1)
2015-12-13 02:57:36 +01:00
SET_INPUT ( BTN_EN1 ) ;
WRITE ( BTN_EN1 , HIGH ) ;
# endif
2011-12-12 19:34:37 +01:00
2016-03-27 13:25:33 +02:00
# if BUTTON_EXISTS(EN2)
2015-12-13 02:57:36 +01:00
SET_INPUT ( BTN_EN2 ) ;
WRITE ( BTN_EN2 , HIGH ) ;
# endif
2015-10-03 08:08:58 +02:00
2016-03-27 13:25:33 +02:00
# if BUTTON_EXISTS(ENC)
2015-10-03 08:08:58 +02:00
SET_INPUT ( BTN_ENC ) ;
WRITE ( BTN_ENC , HIGH ) ;
# endif
# if ENABLED(REPRAPWORLD_KEYPAD)
pinMode ( SHIFT_CLK , OUTPUT ) ;
pinMode ( SHIFT_LD , OUTPUT ) ;
pinMode ( SHIFT_OUT , INPUT ) ;
WRITE ( SHIFT_OUT , HIGH ) ;
WRITE ( SHIFT_LD , HIGH ) ;
# endif
2016-05-03 21:50:49 +02:00
# if BUTTON_EXISTS(UP)
2015-12-24 18:12:25 +01:00
SET_INPUT ( BTN_UP ) ;
2016-05-03 21:50:49 +02:00
# endif
# if BUTTON_EXISTS(DWN)
2015-12-24 18:12:25 +01:00
SET_INPUT ( BTN_DWN ) ;
2016-05-03 21:50:49 +02:00
# endif
# if BUTTON_EXISTS(LFT)
2015-12-24 18:12:25 +01:00
SET_INPUT ( BTN_LFT ) ;
2016-05-03 21:50:49 +02:00
# endif
# if BUTTON_EXISTS(RT)
2015-12-24 18:12:25 +01:00
SET_INPUT ( BTN_RT ) ;
2015-12-13 02:57:36 +01:00
# endif
2016-07-11 02:28:58 +02:00
# else // !NEWPANEL
2015-10-03 08:08:58 +02:00
# if ENABLED(SR_LCD_2W_NL) // Non latching 2 wire shift register
pinMode ( SR_DATA_PIN , OUTPUT ) ;
pinMode ( SR_CLK_PIN , OUTPUT ) ;
# elif defined(SHIFT_CLK)
pinMode ( SHIFT_CLK , OUTPUT ) ;
pinMode ( SHIFT_LD , OUTPUT ) ;
pinMode ( SHIFT_EN , OUTPUT ) ;
pinMode ( SHIFT_OUT , INPUT ) ;
WRITE ( SHIFT_OUT , HIGH ) ;
WRITE ( SHIFT_LD , HIGH ) ;
WRITE ( SHIFT_EN , LOW ) ;
# endif // SR_LCD_2W_NL
2016-07-11 02:28:58 +02:00
# endif // !NEWPANEL
2013-10-30 11:45:32 +01:00
2015-08-01 01:40:50 +02:00
# if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT)
2016-03-06 07:03:16 +01:00
SET_INPUT ( SD_DETECT_PIN ) ;
2015-08-01 01:40:50 +02:00
WRITE ( SD_DETECT_PIN , HIGH ) ;
2015-09-14 01:43:14 +02:00
lcd_sd_status = 2 ; // UNKNOWN
2015-08-01 00:09:36 +02:00
# endif
2015-02-22 02:38:56 +01:00
2015-07-31 07:26:53 +02:00
# if ENABLED(LCD_HAS_SLOW_BUTTONS)
2013-11-17 17:41:30 +01:00
slow_buttons = 0 ;
2015-02-22 02:38:56 +01:00
# endif
lcd_buttons_update ( ) ;
2015-07-31 07:26:53 +02:00
# if ENABLED(ULTIPANEL)
2012-12-21 16:14:47 +01:00
encoderDiff = 0 ;
2015-02-22 02:38:56 +01:00
# endif
2012-12-12 11:47:03 +01:00
}
2011-12-12 19:34:37 +01:00
2016-03-19 11:36:53 +01:00
int lcd_strlen ( const char * s ) {
2015-02-22 02:38:56 +01:00
int i = 0 , j = 0 ;
while ( s [ i ] ) {
2016-07-12 19:59:03 +02:00
# ifdef MAPPER_NON
j + + ;
# else
if ( ( s [ i ] & 0xc0 ) ! = 0x80 ) j + + ;
# endif
2015-02-22 02:38:56 +01:00
i + + ;
}
return j ;
2015-02-16 13:53:58 +01:00
}
2015-10-03 08:08:58 +02:00
int lcd_strlen_P ( const char * s ) {
2015-02-22 02:38:56 +01:00
int j = 0 ;
while ( pgm_read_byte ( s ) ) {
2016-07-12 19:59:03 +02:00
# ifdef MAPPER_NON
j + + ;
# else
if ( ( pgm_read_byte ( s ) & 0xc0 ) ! = 0x80 ) j + + ;
# endif
2015-02-22 02:38:56 +01:00
s + + ;
}
return j ;
2015-02-16 13:53:58 +01:00
}
2016-03-29 04:33:04 +02:00
bool lcd_blink ( ) {
static uint8_t blink = 0 ;
static millis_t next_blink_ms = 0 ;
2016-04-01 23:20:47 +02:00
millis_t ms = millis ( ) ;
2016-04-11 00:55:12 +02:00
if ( ELAPSED ( ms , next_blink_ms ) ) {
2016-03-29 04:33:04 +02:00
blink ^ = 0xFF ;
2016-04-01 23:20:47 +02:00
next_blink_ms = ms + 1000 - LCD_UPDATE_INTERVAL / 2 ;
2016-03-29 04:33:04 +02:00
}
return blink ! = 0 ;
}
2015-04-28 04:11:25 +02:00
/**
* Update the LCD , read encoder buttons , etc .
* - Read button states
* - Check the SD Card slot state
* - Act on RepRap World keypad input
* - Update the encoder position
* - Apply acceleration to the encoder position
2016-04-21 04:49:00 +02:00
* - Set lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NOW on controller events
2015-04-28 04:11:25 +02:00
* - Reset the Info Screen timeout if there ' s any input
* - Update status indicators , if any
*
2016-04-03 01:09:56 +02:00
* Run the current LCD menu handler callback function :
2016-04-09 04:52:40 +02:00
* - Call the handler only if lcdDrawUpdate ! = LCDVIEW_NONE
* - Before calling the handler , LCDVIEW_CALL_NO_REDRAW = > LCDVIEW_NONE
2016-04-03 01:09:56 +02:00
* - Call the menu handler . Menu handlers should do the following :
2016-04-21 04:49:00 +02:00
* - If a value changes , set lcdDrawUpdate to LCDVIEW_REDRAW_NOW and draw the value
* ( Encoder events automatically set lcdDrawUpdate for you . )
2016-04-03 01:09:56 +02:00
* - if ( lcdDrawUpdate ) { redraw }
* - Before exiting the handler set lcdDrawUpdate to :
2016-04-09 04:52:40 +02:00
* - LCDVIEW_CLEAR_CALL_REDRAW to clear screen and set LCDVIEW_CALL_REDRAW_NEXT .
2016-04-21 04:49:00 +02:00
* - LCDVIEW_REDRAW_NOW or LCDVIEW_NONE to keep drawingm but only in this loop .
* - LCDVIEW_REDRAW_NEXT to keep drawing and draw on the next loop also .
* - LCDVIEW_CALL_NO_REDRAW to keep drawing ( or start drawing ) with no redraw on the next loop .
* - NOTE : For graphical displays menu handlers may be called 2 or more times per loop ,
* so don ' t change lcdDrawUpdate without considering this .
2016-04-03 01:09:56 +02:00
*
* After the menu handler callback runs ( or not ) :
2016-04-09 04:52:40 +02:00
* - Clear the LCD if lcdDrawUpdate = = LCDVIEW_CLEAR_CALL_REDRAW
2016-04-21 21:40:22 +02:00
* - Update lcdDrawUpdate for the next loop ( i . e . , move one state down , usually )
2016-04-03 01:09:56 +02:00
*
* No worries . This function is only called from the main thread .
2015-04-28 04:11:25 +02:00
*/
2015-02-22 02:38:56 +01:00
void lcd_update ( ) {
2016-06-11 23:12:00 +02:00
2015-07-31 07:26:53 +02:00
# if ENABLED(ULTIPANEL)
2015-04-13 03:07:08 +02:00
static millis_t return_to_status_ms = 0 ;
2016-06-10 23:36:57 +02:00
manage_manual_move ( ) ;
2015-04-09 12:26:45 +02:00
# endif
2015-02-16 13:53:58 +01:00
2015-02-22 02:38:56 +01:00
lcd_buttons_update ( ) ;
2013-12-08 21:34:56 +01:00
2015-09-05 02:40:12 +02:00
# if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT)
2015-09-12 06:53:07 +02:00
bool sd_status = IS_SD_INSERTED ;
if ( sd_status ! = lcd_sd_status & & lcd_detected ( ) ) {
2016-04-09 04:52:40 +02:00
lcdDrawUpdate = LCDVIEW_CLEAR_CALL_REDRAW ;
2015-02-22 02:38:56 +01:00
lcd_implementation_init ( // to maybe revive the LCD if static electricity killed it.
2016-06-11 23:12:00 +02:00
# if ENABLED(LCD_PROGRESS_BAR) && ENABLED(ULTIPANEL)
2016-06-11 23:19:17 +02:00
currentScreen = = lcd_status_screen
2015-02-22 02:38:56 +01:00
# endif
) ;
2013-12-08 21:34:56 +01:00
2015-09-14 01:43:14 +02:00
if ( sd_status ) {
2015-02-22 02:38:56 +01:00
card . initsd ( ) ;
2015-09-14 01:43:14 +02:00
if ( lcd_sd_status ! = 2 ) LCD_MESSAGEPGM ( MSG_SD_INSERTED ) ;
2015-02-22 02:38:56 +01:00
}
else {
card . release ( ) ;
2015-09-14 01:43:14 +02:00
if ( lcd_sd_status ! = 2 ) LCD_MESSAGEPGM ( MSG_SD_REMOVED ) ;
2015-02-22 02:38:56 +01:00
}
2015-09-14 01:43:14 +02:00
lcd_sd_status = sd_status ;
2012-12-12 11:47:03 +01:00
}
2015-09-05 02:40:12 +02:00
# endif //SDSUPPORT && SD_DETECT_PIN
2015-10-03 08:08:58 +02:00
2015-04-13 03:07:08 +02:00
millis_t ms = millis ( ) ;
2016-04-11 00:55:12 +02:00
if ( ELAPSED ( ms , next_lcd_update_ms ) ) {
2015-02-22 02:38:56 +01:00
2016-04-09 04:52:40 +02:00
next_lcd_update_ms = ms + LCD_UPDATE_INTERVAL ;
# if ENABLED(LCD_HAS_STATUS_INDICATORS)
lcd_implementation_update_indicators ( ) ;
# endif
2015-10-09 21:35:36 +02:00
# if ENABLED(LCD_HAS_SLOW_BUTTONS)
slow_buttons = lcd_implementation_read_slow_buttons ( ) ; // buttons which take too long to read in interrupt context
# endif
2015-07-31 07:26:53 +02:00
# if ENABLED(ULTIPANEL)
2015-02-22 02:38:56 +01:00
2015-07-31 07:26:53 +02:00
# if ENABLED(REPRAPWORLD_KEYPAD)
2016-04-08 02:40:01 +02:00
# if ENABLED(DELTA) || ENABLED(SCARA)
# define _KEYPAD_MOVE_ALLOWED (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS])
# else
# define _KEYPAD_MOVE_ALLOWED true
# endif
if ( REPRAPWORLD_KEYPAD_MOVE_HOME ) reprapworld_keypad_move_home ( ) ;
if ( _KEYPAD_MOVE_ALLOWED ) {
if ( REPRAPWORLD_KEYPAD_MOVE_Z_UP ) reprapworld_keypad_move_z_up ( ) ;
if ( REPRAPWORLD_KEYPAD_MOVE_Z_DOWN ) reprapworld_keypad_move_z_down ( ) ;
if ( REPRAPWORLD_KEYPAD_MOVE_X_LEFT ) reprapworld_keypad_move_x_left ( ) ;
if ( REPRAPWORLD_KEYPAD_MOVE_X_RIGHT ) reprapworld_keypad_move_x_right ( ) ;
if ( REPRAPWORLD_KEYPAD_MOVE_Y_DOWN ) reprapworld_keypad_move_y_down ( ) ;
if ( REPRAPWORLD_KEYPAD_MOVE_Y_UP ) reprapworld_keypad_move_y_up ( ) ;
}
2015-02-22 05:18:49 +01:00
# endif
2015-02-22 02:38:56 +01:00
bool encoderPastThreshold = ( abs ( encoderDiff ) > = ENCODER_PULSES_PER_STEP ) ;
if ( encoderPastThreshold | | LCD_CLICKED ) {
if ( encoderPastThreshold ) {
2015-02-22 05:18:49 +01:00
int32_t encoderMultiplier = 1 ;
2015-07-31 07:26:53 +02:00
# if ENABLED(ENCODER_RATE_MULTIPLIER)
2015-02-22 05:18:49 +01:00
if ( encoderRateMultiplierEnabled ) {
int32_t encoderMovementSteps = abs ( encoderDiff ) / ENCODER_PULSES_PER_STEP ;
if ( lastEncoderMovementMillis ! = 0 ) {
2015-12-13 18:40:48 +01:00
// Note that the rate is always calculated between to passes through the
2015-02-22 05:18:49 +01:00
// loop and that the abs of the encoderDiff value is tracked.
float encoderStepRate = ( float ) ( encoderMovementSteps ) / ( ( float ) ( ms - lastEncoderMovementMillis ) ) * 1000.0 ;
if ( encoderStepRate > = ENCODER_100X_STEPS_PER_SEC ) encoderMultiplier = 100 ;
else if ( encoderStepRate > = ENCODER_10X_STEPS_PER_SEC ) encoderMultiplier = 10 ;
2015-07-31 07:26:53 +02:00
# if ENABLED(ENCODER_RATE_MULTIPLIER_DEBUG)
2015-02-22 05:18:49 +01:00
SERIAL_ECHO_START ;
2016-06-28 01:29:35 +02:00
SERIAL_ECHOPAIR ( " Enc Step Rate: " , encoderStepRate ) ;
SERIAL_ECHOPAIR ( " Multiplier: " , encoderMultiplier ) ;
SERIAL_ECHOPAIR ( " ENCODER_10X_STEPS_PER_SEC: " , ENCODER_10X_STEPS_PER_SEC ) ;
SERIAL_ECHOPAIR ( " ENCODER_100X_STEPS_PER_SEC: " , ENCODER_100X_STEPS_PER_SEC ) ;
SERIAL_EOL ;
2015-02-22 05:18:49 +01:00
# endif //ENCODER_RATE_MULTIPLIER_DEBUG
}
lastEncoderMovementMillis = ms ;
2015-03-31 01:39:47 +02:00
} // encoderRateMultiplierEnabled
2015-02-22 05:18:49 +01:00
# endif //ENCODER_RATE_MULTIPLIER
encoderPosition + = ( encoderDiff * encoderMultiplier ) / ENCODER_PULSES_PER_STEP ;
2015-02-22 02:38:56 +01:00
encoderDiff = 0 ;
2012-08-22 00:46:10 +02:00
}
2015-04-13 03:07:08 +02:00
return_to_status_ms = ms + LCD_TIMEOUT_TO_STATUS ;
2016-04-09 04:52:40 +02:00
lcdDrawUpdate = LCDVIEW_REDRAW_NOW ;
2015-02-22 02:38:56 +01:00
}
# endif //ULTIPANEL
2016-05-15 02:37:42 +02:00
// We arrive here every ~100ms when idling often enough.
2016-05-19 15:41:09 +02:00
// Instead of tracking the changes simply redraw the Info Screen ~1 time a second.
static int8_t lcd_status_update_delay = 1 ; // first update one loop delayed
2016-06-11 23:12:00 +02:00
if (
# if ENABLED(ULTIPANEL)
2016-06-11 23:19:17 +02:00
currentScreen = = lcd_status_screen & &
2016-06-11 23:12:00 +02:00
# endif
! lcd_status_update_delay - - ) {
2016-05-19 15:41:09 +02:00
lcd_status_update_delay = 9 ;
2016-04-09 04:52:40 +02:00
lcdDrawUpdate = LCDVIEW_REDRAW_NOW ;
2016-05-19 15:41:09 +02:00
}
2016-03-29 04:33:04 +02:00
if ( lcdDrawUpdate ) {
2016-04-03 01:09:56 +02:00
2016-04-09 04:52:40 +02:00
switch ( lcdDrawUpdate ) {
case LCDVIEW_CALL_NO_REDRAW :
lcdDrawUpdate = LCDVIEW_NONE ;
break ;
case LCDVIEW_CLEAR_CALL_REDRAW : // set by handlers, then altered after (rarely occurs here)
case LCDVIEW_CALL_REDRAW_NEXT : // set by handlers, then altered after (never occurs here?)
lcdDrawUpdate = LCDVIEW_REDRAW_NOW ;
case LCDVIEW_REDRAW_NOW : // set above, or by a handler through LCDVIEW_CALL_REDRAW_NEXT
case LCDVIEW_NONE :
break ;
}
2016-04-03 01:09:56 +02:00
2016-03-29 04:33:04 +02:00
# if ENABLED(DOGLCD) // Changes due to different driver architecture of the DOGM display
2016-04-21 03:57:17 +02:00
static int8_t dot_color = 0 ;
dot_color = 1 - dot_color ;
2016-03-29 04:33:04 +02:00
u8g . firstPage ( ) ;
do {
lcd_setFont ( FONT_MENU ) ;
u8g . setPrintPos ( 125 , 0 ) ;
2016-04-21 03:57:17 +02:00
u8g . setColorIndex ( dot_color ) ; // Set color for the alive dot
2016-03-29 04:33:04 +02:00
u8g . drawPixel ( 127 , 63 ) ; // draw alive dot
u8g . setColorIndex ( 1 ) ; // black on white
2016-06-12 01:50:06 +02:00
( * currentScreen ) ( ) ;
2016-03-29 04:33:04 +02:00
} while ( u8g . nextPage ( ) ) ;
2016-06-12 01:50:06 +02:00
# elif ENABLED(ULTIPANEL)
( * currentScreen ) ( ) ;
2016-03-29 04:33:04 +02:00
# else
2016-06-12 01:50:06 +02:00
lcd_status_screen ( ) ;
2016-03-29 04:33:04 +02:00
# endif
}
2013-03-19 20:19:16 +01:00
2015-07-31 07:26:53 +02:00
# if ENABLED(ULTIPANEL)
2015-04-13 03:07:08 +02:00
// Return to Status Screen after a timeout
2016-06-11 23:19:17 +02:00
if ( currentScreen = = lcd_status_screen | | defer_return_to_status )
2016-04-03 01:09:56 +02:00
return_to_status_ms = ms + LCD_TIMEOUT_TO_STATUS ;
2016-04-09 04:52:40 +02:00
else if ( ELAPSED ( ms , return_to_status_ms ) )
2015-02-22 02:38:56 +01:00
lcd_return_to_status ( ) ;
2015-04-13 03:07:08 +02:00
# endif // ULTIPANEL
2015-02-22 02:38:56 +01:00
2016-04-03 01:09:56 +02:00
switch ( lcdDrawUpdate ) {
2016-04-09 04:52:40 +02:00
case LCDVIEW_CLEAR_CALL_REDRAW :
2016-04-03 01:09:56 +02:00
lcd_implementation_clear ( ) ;
2016-04-09 04:52:40 +02:00
case LCDVIEW_CALL_REDRAW_NEXT :
lcdDrawUpdate = LCDVIEW_REDRAW_NOW ;
2016-04-03 01:09:56 +02:00
break ;
2016-04-09 04:52:40 +02:00
case LCDVIEW_REDRAW_NOW :
lcdDrawUpdate = LCDVIEW_NONE ;
break ;
case LCDVIEW_NONE :
2016-04-03 01:09:56 +02:00
break ;
}
2015-02-22 02:38:56 +01:00
}
2012-12-12 11:47:03 +01:00
}
2012-08-22 00:46:10 +02:00
2015-03-31 03:00:54 +02:00
void lcd_finishstatus ( bool persist = false ) {
2016-04-02 23:28:17 +02:00
# if !(ENABLED(LCD_PROGRESS_BAR) && (PROGRESS_MSG_EXPIRE > 0))
UNUSED ( persist ) ;
# endif
2015-07-31 07:26:53 +02:00
# if ENABLED(LCD_PROGRESS_BAR)
2015-04-25 07:16:09 +02:00
progress_bar_ms = millis ( ) ;
2014-12-28 07:26:14 +01:00
# if PROGRESS_MSG_EXPIRE > 0
2015-04-25 07:16:09 +02:00
expire_status_ms = persist ? 0 : progress_bar_ms + PROGRESS_MSG_EXPIRE ;
2014-12-28 07:26:14 +01:00
# endif
# endif
2016-04-09 04:52:40 +02:00
lcdDrawUpdate = LCDVIEW_CLEAR_CALL_REDRAW ;
2014-12-28 07:26:14 +01:00
2015-07-31 07:26:53 +02:00
# if ENABLED(FILAMENT_LCD_DISPLAY)
2015-04-13 03:07:08 +02:00
previous_lcd_status_ms = millis ( ) ; //get status message to show up for a while
2014-12-28 07:26:14 +01:00
# endif
}
2015-02-22 02:38:56 +01:00
2015-07-31 07:26:53 +02:00
# if ENABLED(LCD_PROGRESS_BAR) && PROGRESS_MSG_EXPIRE > 0
2015-04-25 06:51:10 +02:00
void dontExpireStatus ( ) { expire_status_ms = 0 ; }
2015-03-31 03:00:54 +02:00
# endif
2015-10-03 08:08:58 +02:00
void set_utf_strlen ( char * s , uint8_t n ) {
2015-04-07 02:33:34 +02:00
uint8_t i = 0 , j = 0 ;
while ( s [ i ] & & ( j < n ) ) {
if ( ( s [ i ] & 0xc0u ) ! = 0x80u ) j + + ;
i + + ;
}
while ( j + + < n ) s [ i + + ] = ' ' ;
2016-06-08 21:50:12 +02:00
s [ i ] = ' \0 ' ;
2015-04-07 02:33:34 +02:00
}
2015-04-25 05:13:01 +02:00
bool lcd_hasstatus ( ) { return ( lcd_status_message [ 0 ] ! = ' \0 ' ) ; }
2015-03-31 03:00:54 +02:00
void lcd_setstatus ( const char * message , bool persist ) {
2015-02-22 02:38:56 +01:00
if ( lcd_status_message_level > 0 ) return ;
2016-03-13 07:38:55 +01:00
strncpy ( lcd_status_message , message , 3 * ( LCD_WIDTH ) ) ;
2015-04-07 02:33:34 +02:00
set_utf_strlen ( lcd_status_message , LCD_WIDTH ) ;
2015-03-31 03:00:54 +02:00
lcd_finishstatus ( persist ) ;
2012-12-12 11:47:03 +01:00
}
2015-02-22 02:38:56 +01:00
2015-03-31 03:00:54 +02:00
void lcd_setstatuspgm ( const char * message , uint8_t level ) {
if ( level > = lcd_status_message_level ) {
2016-03-13 07:38:55 +01:00
strncpy_P ( lcd_status_message , message , 3 * ( LCD_WIDTH ) ) ;
2015-04-07 02:33:34 +02:00
set_utf_strlen ( lcd_status_message , LCD_WIDTH ) ;
2015-03-31 03:00:54 +02:00
lcd_status_message_level = level ;
lcd_finishstatus ( level > 0 ) ;
}
2012-12-12 11:47:03 +01:00
}
2015-02-22 02:38:56 +01:00
void lcd_setalertstatuspgm ( const char * message ) {
2015-03-31 03:00:54 +02:00
lcd_setstatuspgm ( message , 1 ) ;
2015-07-31 07:26:53 +02:00
# if ENABLED(ULTIPANEL)
2012-12-12 11:47:03 +01:00
lcd_return_to_status ( ) ;
2015-02-22 02:38:56 +01:00
# endif
2012-12-12 11:47:03 +01:00
}
2012-08-22 00:46:10 +02:00
2015-02-22 02:38:56 +01:00
void lcd_reset_alert_level ( ) { lcd_status_message_level = 0 ; }
2016-05-31 20:47:02 +02:00
# if HAS_LCD_CONTRAST
2016-06-02 23:34:51 +02:00
void set_lcd_contrast ( int value ) {
lcd_contrast = constrain ( value , LCD_CONTRAST_MIN , LCD_CONTRAST_MAX ) ;
2013-12-08 21:34:56 +01:00
u8g . setContrast ( lcd_contrast ) ;
2015-02-22 02:38:56 +01:00
}
2013-07-14 10:28:26 +02:00
# endif
2015-07-31 07:26:53 +02:00
# if ENABLED(ULTIPANEL)
2015-02-22 02:38:56 +01:00
2015-04-28 04:11:25 +02:00
/**
* Setup Rotary Encoder Bit Values ( for two pin encoders to indicate movement )
* These values are independent of which pins are used for EN_A and EN_B indications
* The rotary encoder part is also independent to the chipset used for the LCD
*/
# if defined(EN_A) && defined(EN_B)
# define encrot0 0
# define encrot1 2
# define encrot2 3
# define encrot3 1
2015-06-12 13:12:55 +02:00
# endif
2015-04-28 04:11:25 +02:00
2016-03-27 13:25:33 +02:00
# define GET_BUTTON_STATES(DST) \
uint8_t new_ # # DST = 0 ; \
WRITE ( SHIFT_LD , LOW ) ; \
WRITE ( SHIFT_LD , HIGH ) ; \
for ( int8_t i = 0 ; i < 8 ; i + + ) { \
new_ # # DST > > = 1 ; \
if ( READ ( SHIFT_OUT ) ) SBI ( new_ # # DST , 7 ) ; \
WRITE ( SHIFT_CLK , HIGH ) ; \
WRITE ( SHIFT_CLK , LOW ) ; \
} \
DST = ~ new_ # # DST ; //invert it, because a pressed switch produces a logical 0
2015-04-28 04:11:25 +02:00
/**
* Read encoder buttons from the hardware registers
* Warning : This function is called from interrupt context !
*/
void lcd_buttons_update ( ) {
2015-07-31 07:26:53 +02:00
# if ENABLED(NEWPANEL)
2015-04-28 04:11:25 +02:00
uint8_t newbutton = 0 ;
2016-03-27 13:25:33 +02:00
# if BUTTON_EXISTS(EN1)
if ( BUTTON_PRESSED ( EN1 ) ) newbutton | = EN_A ;
2015-12-13 02:57:36 +01:00
# endif
2016-03-27 13:25:33 +02:00
# if BUTTON_EXISTS(EN2)
if ( BUTTON_PRESSED ( EN2 ) ) newbutton | = EN_B ;
2015-12-13 02:57:36 +01:00
# endif
2016-05-03 21:50:49 +02:00
# if LCD_HAS_DIRECTIONAL_BUTTONS || BUTTON_EXISTS(ENC)
2015-12-13 18:40:48 +01:00
millis_t now = millis ( ) ;
2015-12-14 04:06:03 +01:00
# endif
2016-05-03 21:50:49 +02:00
# if LCD_HAS_DIRECTIONAL_BUTTONS
2016-04-11 00:55:12 +02:00
if ( ELAPSED ( now , next_button_update_ms ) ) {
2016-05-03 21:50:49 +02:00
if ( false ) {
// for the else-ifs below
2015-12-13 18:40:48 +01:00
}
2016-05-03 21:50:49 +02:00
# if BUTTON_EXISTS(UP)
else if ( BUTTON_PRESSED ( UP ) ) {
encoderDiff = - ( ENCODER_STEPS_PER_MENU_ITEM ) ;
next_button_update_ms = now + 300 ;
}
# endif
# if BUTTON_EXISTS(DWN)
else if ( BUTTON_PRESSED ( DWN ) ) {
encoderDiff = ENCODER_STEPS_PER_MENU_ITEM ;
next_button_update_ms = now + 300 ;
}
# endif
# if BUTTON_EXISTS(LFT)
else if ( BUTTON_PRESSED ( LFT ) ) {
encoderDiff = - ( ENCODER_PULSES_PER_STEP ) ;
next_button_update_ms = now + 300 ;
}
# endif
# if BUTTON_EXISTS(RT)
else if ( BUTTON_PRESSED ( RT ) ) {
encoderDiff = ENCODER_PULSES_PER_STEP ;
next_button_update_ms = now + 300 ;
}
# endif
2015-12-13 02:57:36 +01:00
}
# endif
2016-05-03 21:50:49 +02:00
2016-03-27 13:25:33 +02:00
# if BUTTON_EXISTS(ENC)
2016-04-11 00:55:12 +02:00
if ( ELAPSED ( now , next_button_update_ms ) & & BUTTON_PRESSED ( ENC ) ) newbutton | = EN_C ;
2015-04-28 04:11:25 +02:00
# endif
2016-05-03 21:50:49 +02:00
2015-04-28 04:11:25 +02:00
buttons = newbutton ;
2015-07-31 07:26:53 +02:00
# if ENABLED(LCD_HAS_SLOW_BUTTONS)
2015-04-28 04:11:25 +02:00
buttons | = slow_buttons ;
# endif
2015-07-31 07:26:53 +02:00
# if ENABLED(REPRAPWORLD_KEYPAD)
2016-03-27 13:25:33 +02:00
GET_BUTTON_STATES ( buttons_reprapworld_keypad ) ;
2015-04-28 04:11:25 +02:00
# endif
2016-03-27 13:25:33 +02:00
# else
GET_BUTTON_STATES ( buttons ) ;
2015-04-28 04:11:25 +02:00
# endif //!NEWPANEL
2016-07-11 02:28:58 +02:00
// Manage encoder rotation
2016-05-12 00:39:28 +02:00
# if ENABLED(REVERSE_MENU_DIRECTION) && ENABLED(REVERSE_ENCODER_DIRECTION)
# define ENCODER_DIFF_CW (encoderDiff -= encoderDirection)
# define ENCODER_DIFF_CCW (encoderDiff += encoderDirection)
# elif ENABLED(REVERSE_MENU_DIRECTION)
2016-03-09 10:04:24 +01:00
# define ENCODER_DIFF_CW (encoderDiff += encoderDirection)
# define ENCODER_DIFF_CCW (encoderDiff -= encoderDirection)
2016-05-12 00:39:28 +02:00
# elif ENABLED(REVERSE_ENCODER_DIRECTION)
# define ENCODER_DIFF_CW (encoderDiff--)
# define ENCODER_DIFF_CCW (encoderDiff++)
2016-03-09 10:04:24 +01:00
# else
# define ENCODER_DIFF_CW (encoderDiff++)
# define ENCODER_DIFF_CCW (encoderDiff--)
# endif
# define ENCODER_SPIN(_E1, _E2) switch (lastEncoderBits) { case _E1: ENCODER_DIFF_CW; break; case _E2: ENCODER_DIFF_CCW; }
2015-10-03 08:08:58 +02:00
uint8_t enc = 0 ;
2015-04-28 04:11:25 +02:00
if ( buttons & EN_A ) enc | = B01 ;
if ( buttons & EN_B ) enc | = B10 ;
if ( enc ! = lastEncoderBits ) {
2015-10-03 08:08:58 +02:00
switch ( enc ) {
2016-03-09 10:04:24 +01:00
case encrot0 : ENCODER_SPIN ( encrot3 , encrot1 ) ; break ;
case encrot1 : ENCODER_SPIN ( encrot0 , encrot2 ) ; break ;
case encrot2 : ENCODER_SPIN ( encrot1 , encrot3 ) ; break ;
case encrot3 : ENCODER_SPIN ( encrot2 , encrot0 ) ; break ;
2015-04-28 04:11:25 +02:00
}
2012-12-12 11:47:03 +01:00
}
2015-04-28 04:11:25 +02:00
lastEncoderBits = enc ;
2015-02-22 02:38:56 +01:00
}
2014-03-03 22:01:27 +01:00
2015-04-28 04:11:25 +02:00
bool lcd_detected ( void ) {
2015-07-31 07:26:53 +02:00
# if (ENABLED(LCD_I2C_TYPE_MCP23017) || ENABLED(LCD_I2C_TYPE_MCP23008)) && ENABLED(DETECT_DEVICE)
2015-04-28 04:11:25 +02:00
return lcd . LcdDetected ( ) = = 1 ;
2015-04-20 11:11:13 +02:00
# else
2015-04-28 04:11:25 +02:00
return true ;
2015-04-20 11:11:13 +02:00
# endif
}
2015-04-28 04:11:25 +02:00
2015-06-15 00:12:02 +02:00
bool lcd_clicked ( ) { return LCD_CLICKED ; }
# endif // ULTIPANEL
2015-03-31 01:39:47 +02:00
/*********************************/
/** Number to string conversion **/
/*********************************/
2016-06-08 21:50:12 +02:00
# define DIGIT(n) ('0' + (n))
# define DIGIMOD(n) DIGIT((n) % 10)
2012-12-12 11:47:03 +01:00
char conv [ 8 ] ;
2015-03-31 01:39:47 +02:00
2015-11-03 12:06:05 +01:00
// Convert float to rj string with 123 or -12 format
char * ftostr3 ( const float & x ) { return itostr3 ( ( int ) x ) ; }
// Convert float to rj string with _123, -123, _-12, or __-1 format
char * ftostr4sign ( const float & x ) { return itostr4sign ( ( int ) x ) ; }
2011-12-12 19:34:37 +01:00
2016-04-02 01:43:41 +02:00
// Convert unsigned int to string with 12 format
2015-10-03 08:08:58 +02:00
char * itostr2 ( const uint8_t & x ) {
2015-03-31 01:39:47 +02:00
int xx = x ;
2016-06-08 21:50:12 +02:00
conv [ 0 ] = DIGIMOD ( xx / 10 ) ;
conv [ 1 ] = DIGIMOD ( xx ) ;
conv [ 2 ] = ' \0 ' ;
2011-12-12 19:34:37 +01:00
return conv ;
}
2016-04-02 01:43:41 +02:00
// Convert float to string with +123.4 / -123.4 format
2016-06-08 21:50:12 +02:00
char * ftostr41sign ( const float & x ) {
int xx = int ( abs ( x * 10 ) ) % 10000 ;
conv [ 0 ] = x > = 0 ? ' + ' : ' - ' ;
conv [ 1 ] = DIGIMOD ( xx / 1000 ) ;
conv [ 2 ] = DIGIMOD ( xx / 100 ) ;
conv [ 3 ] = DIGIMOD ( xx / 10 ) ;
2015-03-31 01:39:47 +02:00
conv [ 4 ] = ' . ' ;
2016-06-08 21:50:12 +02:00
conv [ 5 ] = DIGIMOD ( xx ) ;
conv [ 6 ] = ' \0 ' ;
2013-03-19 20:13:23 +01:00
return conv ;
}
2016-04-02 01:43:41 +02:00
// Convert signed float to string with 023.45 / -23.45 format
2015-11-03 12:06:05 +01:00
char * ftostr32 ( const float & x ) {
2015-03-31 01:39:47 +02:00
long xx = abs ( x * 100 ) ;
2016-06-08 21:50:12 +02:00
conv [ 0 ] = x > = 0 ? DIGIMOD ( xx / 10000 ) : ' - ' ;
conv [ 1 ] = DIGIMOD ( xx / 1000 ) ;
conv [ 2 ] = DIGIMOD ( xx / 100 ) ;
2015-03-31 01:39:47 +02:00
conv [ 3 ] = ' . ' ;
2016-06-08 21:50:12 +02:00
conv [ 4 ] = DIGIMOD ( xx / 10 ) ;
conv [ 5 ] = DIGIMOD ( xx ) ;
conv [ 6 ] = ' \0 ' ;
2011-12-12 19:34:37 +01:00
return conv ;
}
2016-04-03 01:06:37 +02:00
// Convert signed float to string (6 digit) with -1.234 / _0.000 / +1.234 format
2016-06-08 21:50:12 +02:00
char * ftostr43sign ( const float & x , char plus /*=' '*/ ) {
2015-10-03 08:08:58 +02:00
long xx = x * 1000 ;
2016-04-03 01:06:37 +02:00
if ( xx = = 0 )
conv [ 0 ] = ' ' ;
else if ( xx > 0 )
conv [ 0 ] = plus ;
2016-04-02 01:43:41 +02:00
else {
xx = - xx ;
2016-04-02 02:54:16 +02:00
conv [ 0 ] = ' - ' ;
2016-04-02 01:43:41 +02:00
}
2016-06-08 21:50:12 +02:00
conv [ 1 ] = DIGIMOD ( xx / 1000 ) ;
2016-04-02 01:43:41 +02:00
conv [ 2 ] = ' . ' ;
2016-06-08 21:50:12 +02:00
conv [ 3 ] = DIGIMOD ( xx / 100 ) ;
conv [ 4 ] = DIGIMOD ( xx / 10 ) ;
conv [ 5 ] = DIGIMOD ( xx ) ;
conv [ 6 ] = ' \0 ' ;
2016-04-03 01:06:37 +02:00
return conv ;
2014-12-29 02:43:14 +01:00
}
2016-04-02 01:43:41 +02:00
// Convert unsigned float to string with 1.23 format
2015-10-03 08:08:58 +02:00
char * ftostr12ns ( const float & x ) {
long xx = x * 100 ;
xx = abs ( xx ) ;
2016-06-08 21:50:12 +02:00
conv [ 0 ] = DIGIMOD ( xx / 100 ) ;
2015-10-03 08:08:58 +02:00
conv [ 1 ] = ' . ' ;
2016-06-08 21:50:12 +02:00
conv [ 2 ] = DIGIMOD ( xx / 10 ) ;
conv [ 3 ] = DIGIMOD ( xx ) ;
conv [ 4 ] = ' \0 ' ;
2014-12-08 10:43:44 +01:00
return conv ;
2014-12-07 05:59:06 +01:00
}
2016-04-19 05:39:15 +02:00
// Convert signed int to lj string with +012 / -012 format
char * itostr3sign ( const int & x ) {
2016-04-02 01:43:41 +02:00
int xx ;
if ( x > = 0 ) {
conv [ 0 ] = ' + ' ;
xx = x ;
}
else {
conv [ 0 ] = ' - ' ;
xx = - x ;
}
2016-06-08 21:50:12 +02:00
conv [ 1 ] = DIGIMOD ( xx / 100 ) ;
conv [ 2 ] = DIGIMOD ( xx / 10 ) ;
conv [ 3 ] = DIGIMOD ( xx ) ;
2015-03-31 01:39:47 +02:00
conv [ 4 ] = ' . ' ;
conv [ 5 ] = ' 0 ' ;
2016-06-08 21:50:12 +02:00
conv [ 6 ] = ' \0 ' ;
2011-12-12 19:34:37 +01:00
return conv ;
}
2016-04-02 01:43:41 +02:00
// Convert signed int to rj string with 123 or -12 format
2015-10-03 08:08:58 +02:00
char * itostr3 ( const int & x ) {
2014-06-24 14:31:15 +02:00
int xx = x ;
if ( xx < 0 ) {
2015-10-03 08:08:58 +02:00
conv [ 0 ] = ' - ' ;
xx = - xx ;
2015-03-31 01:39:47 +02:00
}
2012-12-12 11:47:03 +01:00
else
2016-06-08 21:50:12 +02:00
conv [ 0 ] = xx > = 100 ? DIGIMOD ( xx / 100 ) : ' ' ;
2015-03-31 01:39:47 +02:00
2016-06-08 21:50:12 +02:00
conv [ 1 ] = xx > = 10 ? DIGIMOD ( xx / 10 ) : ' ' ;
conv [ 2 ] = DIGIMOD ( xx ) ;
conv [ 3 ] = ' \0 ' ;
2011-12-12 19:34:37 +01:00
return conv ;
}
2016-04-02 01:43:41 +02:00
// Convert unsigned int to lj string with 123 format
2016-06-08 21:50:12 +02:00
char * itostr3left ( const int & xx ) {
if ( xx > = 100 ) {
conv [ 0 ] = DIGIMOD ( xx / 100 ) ;
conv [ 1 ] = DIGIMOD ( xx / 10 ) ;
conv [ 2 ] = DIGIMOD ( xx ) ;
conv [ 3 ] = ' \0 ' ;
}
else if ( xx > = 10 ) {
conv [ 0 ] = DIGIMOD ( xx / 10 ) ;
conv [ 1 ] = DIGIMOD ( xx ) ;
conv [ 2 ] = ' \0 ' ;
2012-12-12 11:47:03 +01:00
}
2015-03-31 01:39:47 +02:00
else {
2016-06-08 21:50:12 +02:00
conv [ 0 ] = DIGIMOD ( xx ) ;
conv [ 1 ] = ' \0 ' ;
2012-12-12 11:47:03 +01:00
}
return conv ;
}
2016-04-02 01:43:41 +02:00
// Convert signed int to rj string with _123, -123, _-12, or __-1 format
2015-11-03 12:06:05 +01:00
char * itostr4sign ( const int & x ) {
int xx = abs ( x ) ;
int sign = 0 ;
if ( xx > = 100 ) {
2016-06-08 21:50:12 +02:00
conv [ 1 ] = DIGIMOD ( xx / 100 ) ;
conv [ 2 ] = DIGIMOD ( xx / 10 ) ;
2015-11-03 12:06:05 +01:00
}
else if ( xx > = 10 ) {
conv [ 0 ] = ' ' ;
sign = 1 ;
2016-06-08 21:50:12 +02:00
conv [ 2 ] = DIGIMOD ( xx / 10 ) ;
2015-11-03 12:06:05 +01:00
}
else {
conv [ 0 ] = ' ' ;
conv [ 1 ] = ' ' ;
sign = 2 ;
}
conv [ sign ] = x < 0 ? ' - ' : ' ' ;
2016-06-08 21:50:12 +02:00
conv [ 3 ] = DIGIMOD ( xx ) ;
conv [ 4 ] = ' \0 ' ;
2015-11-03 12:06:05 +01:00
return conv ;
}
2016-04-02 01:43:41 +02:00
// Convert unsigned float to rj string with 12345 format
2016-06-08 21:50:12 +02:00
char * ftostr5rj ( const float & x ) {
2014-12-18 16:30:05 +01:00
long xx = abs ( x ) ;
2016-06-08 21:50:12 +02:00
conv [ 0 ] = xx > = 10000 ? DIGIMOD ( xx / 10000 ) : ' ' ;
conv [ 1 ] = xx > = 1000 ? DIGIMOD ( xx / 1000 ) : ' ' ;
conv [ 2 ] = xx > = 100 ? DIGIMOD ( xx / 100 ) : ' ' ;
conv [ 3 ] = xx > = 10 ? DIGIMOD ( xx / 10 ) : ' ' ;
conv [ 4 ] = DIGIMOD ( xx ) ;
conv [ 5 ] = ' \0 ' ;
2012-12-12 11:47:03 +01:00
return conv ;
}
2016-04-02 01:43:41 +02:00
// Convert signed float to string with +1234.5 format
2016-06-08 21:50:12 +02:00
char * ftostr51sign ( const float & x ) {
2015-03-31 01:39:47 +02:00
long xx = abs ( x * 10 ) ;
conv [ 0 ] = ( x > = 0 ) ? ' + ' : ' - ' ;
2016-06-08 21:50:12 +02:00
conv [ 1 ] = DIGIMOD ( xx / 10000 ) ;
conv [ 2 ] = DIGIMOD ( xx / 1000 ) ;
conv [ 3 ] = DIGIMOD ( xx / 100 ) ;
conv [ 4 ] = DIGIMOD ( xx / 10 ) ;
2015-03-31 01:39:47 +02:00
conv [ 5 ] = ' . ' ;
2016-06-08 21:50:12 +02:00
conv [ 6 ] = DIGIMOD ( xx ) ;
conv [ 7 ] = ' \0 ' ;
2011-12-12 19:34:37 +01:00
return conv ;
}
2016-04-02 01:43:41 +02:00
// Convert signed float to string with +123.45 format
2016-06-08 21:50:12 +02:00
char * ftostr52sign ( const float & x ) {
2015-03-31 01:39:47 +02:00
long xx = abs ( x * 100 ) ;
2016-06-08 21:50:12 +02:00
conv [ 0 ] = ( x > = 0 ) ? ' + ' : ' - ' ;
conv [ 1 ] = DIGIMOD ( xx / 10000 ) ;
conv [ 2 ] = DIGIMOD ( xx / 1000 ) ;
conv [ 3 ] = DIGIMOD ( xx / 100 ) ;
2015-03-31 01:39:47 +02:00
conv [ 4 ] = ' . ' ;
2016-06-08 21:50:12 +02:00
conv [ 5 ] = DIGIMOD ( xx / 10 ) ;
conv [ 6 ] = DIGIMOD ( xx ) ;
conv [ 7 ] = ' \0 ' ;
return conv ;
}
// Convert signed float to space-padded string with -_23.4_ format
char * ftostr52sp ( const float & x ) {
long xx = x * 100 ;
uint8_t dig ;
if ( xx < 0 ) { // negative val = -_0
xx = - xx ;
conv [ 0 ] = ' - ' ;
dig = ( xx / 1000 ) % 10 ;
conv [ 1 ] = dig ? DIGIT ( dig ) : ' ' ;
}
else { // positive val = __0
dig = ( xx / 10000 ) % 10 ;
if ( dig ) {
conv [ 0 ] = DIGIT ( dig ) ;
conv [ 1 ] = DIGIMOD ( xx / 1000 ) ;
}
else {
conv [ 0 ] = ' ' ;
dig = ( xx / 1000 ) % 10 ;
conv [ 1 ] = dig ? DIGIT ( dig ) : ' ' ;
}
}
conv [ 2 ] = DIGIMOD ( xx / 100 ) ; // lsd always
dig = xx % 10 ;
if ( dig ) { // 2 decimal places
conv [ 5 ] = DIGIT ( dig ) ;
conv [ 4 ] = DIGIMOD ( xx / 10 ) ;
conv [ 3 ] = ' . ' ;
}
else { // 1 or 0 decimal place
dig = ( xx / 10 ) % 10 ;
if ( dig ) {
conv [ 4 ] = DIGIT ( dig ) ;
conv [ 3 ] = ' . ' ;
}
else {
conv [ 3 ] = conv [ 4 ] = ' ' ;
}
conv [ 5 ] = ' ' ;
}
conv [ 6 ] = ' \0 ' ;
2012-02-21 23:05:43 +01:00
return conv ;
}
2011-12-12 19:34:37 +01:00
2015-04-09 13:32:14 +02:00
# endif // ULTRA_LCD