# include "temperature.h"
# include "ultralcd.h"
# ifdef ULTRA_LCD
# include "Marlin.h"
# include "language.h"
# include "cardreader.h"
# include "temperature.h"
# include "ConfigurationStore.h"
/* Configuration settings */
int plaPreheatHotendTemp ;
int plaPreheatHPBTemp ;
int plaPreheatFanSpeed ;
int absPreheatHotendTemp ;
int absPreheatHPBTemp ;
int absPreheatFanSpeed ;
/* !Configuration settings */
//Function pointer to menu functions.
typedef void ( * menuFunc_t ) ( ) ;
uint8_t lcd_status_message_level ;
char lcd_status_message [ LCD_WIDTH + 1 ] = WELCOME_MSG ;
# include "ultralcd_implementation_hitachi_HD44780.h"
/** forward declerations **/
/* Different menus */
static void lcd_status_screen ( ) ;
# ifdef ULTIPANEL
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_retract_menu ( ) ;
static void lcd_sdcard_menu ( ) ;
static void lcd_quick_feedback ( ) ; //Cause an LCD refresh, and give the user visual or audiable feedback that something has happend
/* Different types of actions that can be used in menuitems. */
static void menu_action_back ( menuFunc_t data ) ;
static void menu_action_submenu ( menuFunc_t data ) ;
static void menu_action_gcode ( const char * pgcode ) ;
static void menu_action_function ( menuFunc_t data ) ;
static void menu_action_sdfile ( const char * filename , char * longFilename ) ;
static void menu_action_sddirectory ( const char * filename , char * longFilename ) ;
static void menu_action_setting_edit_bool ( const char * pstr , bool * ptr ) ;
static void menu_action_setting_edit_int3 ( const char * pstr , int * ptr , int minValue , int maxValue ) ;
static void menu_action_setting_edit_float3 ( const char * pstr , float * ptr , float minValue , float maxValue ) ;
static void menu_action_setting_edit_float32 ( const char * pstr , float * ptr , float minValue , float maxValue ) ;
static void menu_action_setting_edit_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 ) ;
# define ENCODER_STEPS_PER_MENU_ITEM 5
/* Helper macros for menus */
# define START_MENU() do { \
if ( encoderPosition > 0x8000 ) encoderPosition = 0 ; \
if ( encoderPosition / ENCODER_STEPS_PER_MENU_ITEM < currentMenuViewOffset ) currentMenuViewOffset = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM ; \
uint8_t _lineNr = currentMenuViewOffset , _menuItemNr ; \
for ( uint8_t _drawLineNr = 0 ; _drawLineNr < LCD_HEIGHT ; _drawLineNr + + , _lineNr + + ) { \
_menuItemNr = 0 ;
# define MENU_ITEM(type, label, args...) do { \
if ( _menuItemNr = = _lineNr ) { \
if ( lcdDrawUpdate ) { \
if ( ( encoderPosition / ENCODER_STEPS_PER_MENU_ITEM ) = = _menuItemNr ) { \
lcd_implementation_drawmenu_ # # type # # _selected ( _drawLineNr , PSTR ( label ) , # # args ) ; \
} else { \
lcd_implementation_drawmenu_ # # type ( _drawLineNr , PSTR ( label ) , # # args ) ; \
} \
} \
if ( LCD_CLICKED & & ( encoderPosition / ENCODER_STEPS_PER_MENU_ITEM ) = = _menuItemNr ) { \
lcd_quick_feedback ( ) ; \
menu_action_ # # type ( args ) ; \
return ; \
} \
} \
_menuItemNr + + ; \
} while ( 0 )
# define MENU_ITEM_DUMMY() do { _menuItemNr++; } while(0)
# define MENU_ITEM_EDIT(type, label, args...) MENU_ITEM(setting_edit_ ## type, label, PSTR(label) , ## args )
# define END_MENU() \
if ( encoderPosition / ENCODER_STEPS_PER_MENU_ITEM > = _menuItemNr ) encoderPosition = _menuItemNr * ENCODER_STEPS_PER_MENU_ITEM - 1 ; \
if ( ( uint8_t ) ( encoderPosition / ENCODER_STEPS_PER_MENU_ITEM ) > = currentMenuViewOffset + LCD_HEIGHT ) { currentMenuViewOffset = ( encoderPosition / ENCODER_STEPS_PER_MENU_ITEM ) - LCD_HEIGHT + 1 ; lcdDrawUpdate = 1 ; _lineNr = currentMenuViewOffset - 1 ; _drawLineNr = - 1 ; } \
} } while ( 0 )
/** Used variables to keep track of the menu */
volatile uint8_t buttons ; //Contains the bits of the currently pressed buttons.
uint8_t currentMenuViewOffset ; /* scroll offset in the current menu */
uint32_t blocking_enc ;
uint8_t lastEncoderBits ;
int8_t encoderDiff ; /* encoderDiff is updated from interrupt context and added to encoderPosition every LCD update */
uint32_t encoderPosition ;
# if (SDCARDDETECT > -1)
bool lcd_oldcardstatus ;
# endif
# endif //ULTIPANEL
menuFunc_t currentMenu = lcd_status_screen ; /* function pointer to the currently active menu */
uint32_t lcd_next_update_millis ;
uint8_t lcd_status_update_delay ;
uint8_t lcdDrawUpdate = 2 ; /* Set to none-zero when the LCD needs to draw, decreased after every draw. Set to 2 in LCD routines so the LCD gets atleast 1 full redraw (first redraw is partial) */
//prevMenu and prevEncoderPosition are used to store the previous menu location when editing settings.
menuFunc_t prevMenu = NULL ;
uint16_t prevEncoderPosition ;
//Variables used when editing values.
const char * editLabel ;
void * editValue ;
int32_t minEditValue , maxEditValue ;
/* Main status screen. It's up to the implementation specific part to show what is needed. As this is very display dependend */
static void lcd_status_screen ( )
{
if ( lcd_status_update_delay )
lcd_status_update_delay - - ;
else
lcdDrawUpdate = 1 ;
if ( lcdDrawUpdate )
{
lcd_implementation_status_screen ( ) ;
lcd_status_update_delay = 10 ; /* redraw the main screen every second. This is easier then trying keep track of all things that change on the screen */
}
# ifdef ULTIPANEL
if ( LCD_CLICKED )
{
currentMenu = lcd_main_menu ;
lcd_quick_feedback ( ) ;
}
if ( abs ( encoderPosition / 2 ) > 1 )
feedmultiply + = encoderPosition / 2 ;
encoderPosition = 0 ;
if ( feedmultiply < 10 )
feedmultiply = 10 ;
if ( feedmultiply > 999 )
feedmultiply = 999 ;
# endif //ULTIPANEL
}
# ifdef ULTIPANEL
static void lcd_return_to_status ( )
{
encoderPosition = 0 ;
currentMenu = lcd_status_screen ;
}
static void lcd_sdcard_pause ( )
{
card . pauseSDPrint ( ) ;
}
static void lcd_sdcard_resume ( )
{
card . startFileprint ( ) ;
}
static void lcd_sdcard_stop ( )
{
card . sdprinting = false ;
card . closefile ( ) ;
quickStop ( ) ;
if ( SD_FINISHED_STEPPERRELEASE )
{
enquecommand_P ( PSTR ( SD_FINISHED_RELEASECOMMAND ) ) ;
}
autotempShutdown ( ) ;
}
/* Menu implementation */
static void lcd_main_menu ( )
{
START_MENU ( ) ;
MENU_ITEM ( back , MSG_WATCH , lcd_status_screen ) ;
if ( IS_SD_PRINTING )
{
MENU_ITEM ( submenu , MSG_TUNE , lcd_tune_menu ) ;
} else {
MENU_ITEM ( submenu , MSG_PREPARE , lcd_prepare_menu ) ;
}
MENU_ITEM ( submenu , MSG_CONTROL , lcd_control_menu ) ;
# ifdef SDSUPPORT
if ( card . cardOK )
{
if ( card . isFileOpen ( ) )
{
if ( card . sdprinting )
MENU_ITEM ( function , MSG_PAUSE_PRINT , lcd_sdcard_pause ) ;
else
MENU_ITEM ( function , MSG_RESUME_PRINT , lcd_sdcard_resume ) ;
MENU_ITEM ( function , MSG_STOP_PRINT , lcd_sdcard_stop ) ;
} else {
MENU_ITEM ( submenu , MSG_CARD_MENU , lcd_sdcard_menu ) ;
}
} else {
MENU_ITEM ( submenu , MSG_NO_CARD , lcd_sdcard_menu ) ;
}
# endif
END_MENU ( ) ;
}
# ifdef SDSUPPORT
static void lcd_autostart_sd ( )
{
card . lastnr = 0 ;
card . setroot ( ) ;
card . checkautostart ( true ) ;
}
# endif
void lcd_preheat_pla ( )
{
setTargetHotend0 ( plaPreheatHotendTemp ) ;
setTargetHotend1 ( plaPreheatHotendTemp ) ;
setTargetHotend2 ( plaPreheatHotendTemp ) ;
setTargetBed ( plaPreheatHPBTemp ) ;
# if FAN_PIN > -1
fanSpeed = plaPreheatFanSpeed ;
analogWrite ( FAN_PIN , fanSpeed ) ;
# endif
lcd_return_to_status ( ) ;
}
void lcd_preheat_abs ( )
{
setTargetHotend0 ( absPreheatHotendTemp ) ;
setTargetHotend1 ( absPreheatHotendTemp ) ;
setTargetHotend2 ( absPreheatHotendTemp ) ;
setTargetBed ( absPreheatHPBTemp ) ;
# if FAN_PIN > -1
fanSpeed = absPreheatFanSpeed ;
analogWrite ( FAN_PIN , fanSpeed ) ;
# endif
lcd_return_to_status ( ) ;
}
static void lcd_tune_menu ( )
{
START_MENU ( ) ;
MENU_ITEM ( back , MSG_MAIN , lcd_main_menu ) ;
MENU_ITEM_EDIT ( int3 , MSG_SPEED , & feedmultiply , 10 , 999 ) ;
MENU_ITEM_EDIT ( int3 , MSG_NOZZLE , & target_temperature [ 0 ] , 0 , HEATER_0_MAXTEMP - 15 ) ;
# if TEMP_SENSOR_1 != 0
MENU_ITEM_EDIT ( int3 , MSG_NOZZLE1 , & target_temperature [ 1 ] , 0 , HEATER_1_MAXTEMP - 15 ) ;
# endif
# if TEMP_SENSOR_2 != 0
MENU_ITEM_EDIT ( int3 , MSG_NOZZLE2 , & target_temperature [ 2 ] , 0 , HEATER_2_MAXTEMP - 15 ) ;
# endif
# if TEMP_SENSOR_BED != 0
MENU_ITEM_EDIT ( int3 , MSG_BED , & target_temperature_bed , 0 , BED_MAXTEMP - 15 ) ;
# endif
MENU_ITEM_EDIT ( int3 , MSG_FAN_SPEED , & fanSpeed , 0 , 255 ) ;
MENU_ITEM_EDIT ( int3 , MSG_FLOW , & extrudemultiply , 10 , 999 ) ;
END_MENU ( ) ;
}
static void lcd_prepare_menu ( )
{
START_MENU ( ) ;
MENU_ITEM ( back , MSG_MAIN , lcd_main_menu ) ;
# ifdef SDSUPPORT
//MENU_ITEM(function, MSG_AUTOSTART, lcd_autostart_sd);
# endif
MENU_ITEM ( gcode , MSG_DISABLE_STEPPERS , PSTR ( " M84 " ) ) ;
MENU_ITEM ( gcode , MSG_AUTO_HOME , PSTR ( " G28 " ) ) ;
//MENU_ITEM(gcode, MSG_SET_ORIGIN, PSTR("G92 X0 Y0 Z0"));
MENU_ITEM ( function , MSG_PREHEAT_PLA , lcd_preheat_pla ) ;
MENU_ITEM ( function , MSG_PREHEAT_ABS , lcd_preheat_abs ) ;
MENU_ITEM ( gcode , MSG_COOLDOWN , PSTR ( " M104 S0 \n M140 S0 " ) ) ;
MENU_ITEM ( submenu , MSG_MOVE_AXIS , lcd_move_menu ) ;
END_MENU ( ) ;
}
float move_menu_scale ;
static void lcd_move_menu_axis ( ) ;
static void lcd_move_x ( )
{
if ( encoderPosition ! = 0 )
{
current_position [ X_AXIS ] + = float ( ( int ) encoderPosition ) * move_menu_scale ;
if ( current_position [ X_AXIS ] < X_MIN_POS )
current_position [ X_AXIS ] = X_MIN_POS ;
if ( current_position [ X_AXIS ] > X_MAX_POS )
current_position [ X_AXIS ] = X_MAX_POS ;
encoderPosition = 0 ;
plan_buffer_line ( current_position [ X_AXIS ] , current_position [ Y_AXIS ] , current_position [ Z_AXIS ] , current_position [ E_AXIS ] , 600 , active_extruder ) ;
lcdDrawUpdate = 1 ;
}
if ( lcdDrawUpdate )
{
lcd_implementation_drawedit ( PSTR ( " X " ) , ftostr31 ( current_position [ X_AXIS ] ) ) ;
}
if ( LCD_CLICKED )
{
lcd_quick_feedback ( ) ;
currentMenu = lcd_move_menu_axis ;
encoderPosition = 0 ;
}
}
static void lcd_move_y ( )
{
if ( encoderPosition ! = 0 )
{
current_position [ Y_AXIS ] + = float ( ( int ) encoderPosition ) * move_menu_scale ;
if ( current_position [ Y_AXIS ] < Y_MIN_POS )
current_position [ Y_AXIS ] = Y_MIN_POS ;
if ( current_position [ Y_AXIS ] > Y_MAX_POS )
current_position [ Y_AXIS ] = Y_MAX_POS ;
encoderPosition = 0 ;
plan_buffer_line ( current_position [ X_AXIS ] , current_position [ Y_AXIS ] , current_position [ Z_AXIS ] , current_position [ E_AXIS ] , 600 , active_extruder ) ;
lcdDrawUpdate = 1 ;
}
if ( lcdDrawUpdate )
{
lcd_implementation_drawedit ( PSTR ( " Y " ) , ftostr31 ( current_position [ Y_AXIS ] ) ) ;
}
if ( LCD_CLICKED )
{
lcd_quick_feedback ( ) ;
currentMenu = lcd_move_menu_axis ;
encoderPosition = 0 ;
}
}
static void lcd_move_z ( )
{
if ( encoderPosition ! = 0 )
{
current_position [ Z_AXIS ] + = float ( ( int ) encoderPosition ) * move_menu_scale ;
if ( current_position [ Z_AXIS ] < Z_MIN_POS )
current_position [ Z_AXIS ] = Z_MIN_POS ;
if ( current_position [ Z_AXIS ] > Z_MAX_POS )
current_position [ Z_AXIS ] = Z_MAX_POS ;
encoderPosition = 0 ;
plan_buffer_line ( current_position [ X_AXIS ] , current_position [ Y_AXIS ] , current_position [ Z_AXIS ] , current_position [ E_AXIS ] , 60 , active_extruder ) ;
lcdDrawUpdate = 1 ;
}
if ( lcdDrawUpdate )
{
lcd_implementation_drawedit ( PSTR ( " Z " ) , ftostr31 ( current_position [ Z_AXIS ] ) ) ;
}
if ( LCD_CLICKED )
{
lcd_quick_feedback ( ) ;
currentMenu = lcd_move_menu_axis ;
encoderPosition = 0 ;
}
}
static void lcd_move_e ( )
{
if ( encoderPosition ! = 0 )
{
current_position [ E_AXIS ] + = float ( ( int ) encoderPosition ) * move_menu_scale ;
encoderPosition = 0 ;
plan_buffer_line ( current_position [ X_AXIS ] , current_position [ Y_AXIS ] , current_position [ Z_AXIS ] , current_position [ E_AXIS ] , 20 , active_extruder ) ;
lcdDrawUpdate = 1 ;
}
if ( lcdDrawUpdate )
{
lcd_implementation_drawedit ( PSTR ( " Extruder " ) , ftostr31 ( current_position [ E_AXIS ] ) ) ;
}
if ( LCD_CLICKED )
{
lcd_quick_feedback ( ) ;
currentMenu = lcd_move_menu_axis ;
encoderPosition = 0 ;
}
}
static void lcd_move_menu_axis ( )
{
START_MENU ( ) ;
MENU_ITEM ( back , MSG_MOVE_AXIS , lcd_move_menu ) ;
MENU_ITEM ( submenu , " Move X " , lcd_move_x ) ;
MENU_ITEM ( submenu , " Move Y " , lcd_move_y ) ;
MENU_ITEM ( submenu , " Move Z " , lcd_move_z ) ;
if ( move_menu_scale < 10.0 )
{
MENU_ITEM ( submenu , " Extruder " , lcd_move_e ) ;
}
END_MENU ( ) ;
}
static void lcd_move_menu_10mm ( )
{
move_menu_scale = 10.0 ;
lcd_move_menu_axis ( ) ;
}
static void lcd_move_menu_1mm ( )
{
move_menu_scale = 1.0 ;
lcd_move_menu_axis ( ) ;
}
static void lcd_move_menu_01mm ( )
{
move_menu_scale = 0.1 ;
lcd_move_menu_axis ( ) ;
}
static void lcd_move_menu ( )
{
START_MENU ( ) ;
MENU_ITEM ( back , MSG_PREPARE , lcd_prepare_menu ) ;
MENU_ITEM ( submenu , " Move 10mm " , lcd_move_menu_10mm ) ;
MENU_ITEM ( submenu , " Move 1mm " , lcd_move_menu_1mm ) ;
MENU_ITEM ( submenu , " Move 0.1mm " , lcd_move_menu_01mm ) ;
//TODO:X,Y,Z,E
END_MENU ( ) ;
}
static void lcd_control_menu ( )
{
START_MENU ( ) ;
MENU_ITEM ( back , MSG_MAIN , lcd_main_menu ) ;
MENU_ITEM ( submenu , MSG_TEMPERATURE , lcd_control_temperature_menu ) ;
MENU_ITEM ( submenu , MSG_MOTION , lcd_control_motion_menu ) ;
# ifdef FWRETRACT
MENU_ITEM ( submenu , MSG_RETRACT , lcd_control_retract_menu ) ;
# endif
# ifdef EEPROM_SETTINGS
MENU_ITEM ( function , MSG_STORE_EPROM , Config_StoreSettings ) ;
MENU_ITEM ( function , MSG_LOAD_EPROM , Config_RetrieveSettings ) ;
# endif
MENU_ITEM ( function , MSG_RESTORE_FAILSAFE , Config_ResetDefault ) ;
END_MENU ( ) ;
}
static void lcd_control_temperature_menu ( )
{
START_MENU ( ) ;
MENU_ITEM ( back , MSG_CONTROL , lcd_control_menu ) ;
MENU_ITEM_EDIT ( int3 , MSG_NOZZLE , & target_temperature [ 0 ] , 0 , HEATER_0_MAXTEMP - 15 ) ;
# if TEMP_SENSOR_1 != 0
MENU_ITEM_EDIT ( int3 , MSG_NOZZLE1 , & target_temperature [ 1 ] , 0 , HEATER_1_MAXTEMP - 15 ) ;
# endif
# if TEMP_SENSOR_2 != 0
MENU_ITEM_EDIT ( int3 , MSG_NOZZLE2 , & target_temperature [ 2 ] , 0 , HEATER_2_MAXTEMP - 15 ) ;
# endif
# if TEMP_SENSOR_BED != 0
MENU_ITEM_EDIT ( int3 , MSG_BED , & target_temperature_bed , 0 , BED_MAXTEMP - 15 ) ;
# endif
MENU_ITEM_EDIT ( int3 , MSG_FAN_SPEED , & fanSpeed , 0 , 255 ) ;
# ifdef AUTOTEMP
MENU_ITEM_EDIT ( bool , MSG_AUTOTEMP , & autotemp_enabled ) ;
MENU_ITEM_EDIT ( float3 , MSG_MIN , & autotemp_min , 0 , HEATER_0_MAXTEMP - 15 ) ;
MENU_ITEM_EDIT ( float3 , MSG_MAX , & autotemp_max , 0 , HEATER_0_MAXTEMP - 15 ) ;
MENU_ITEM_EDIT ( float32 , MSG_FACTOR , & autotemp_factor , 0.0 , 1.0 ) ;
# endif
# ifdef PIDTEMP
MENU_ITEM_EDIT ( float52 , MSG_PID_P , & Kp , 1 , 9990 ) ;
//TODO, I and D should have a PID_dT multiplier (Ki = PID_I * PID_dT, Kd = PID_D / PID_dT)
MENU_ITEM_EDIT ( float52 , MSG_PID_I , & Ki , 1 , 9990 ) ;
MENU_ITEM_EDIT ( float52 , MSG_PID_D , & Kd , 1 , 9990 ) ;
# ifdef PID_ADD_EXTRUSION_RATE
MENU_ITEM_EDIT ( float3 , MSG_PID_C , & Kc , 1 , 9990 ) ;
# endif //PID_ADD_EXTRUSION_RATE
# endif //PIDTEMP
MENU_ITEM ( submenu , MSG_PREHEAT_PLA_SETTINGS , lcd_control_temperature_preheat_pla_settings_menu ) ;
MENU_ITEM ( submenu , MSG_PREHEAT_ABS_SETTINGS , lcd_control_temperature_preheat_abs_settings_menu ) ;
END_MENU ( ) ;
}
static void lcd_control_temperature_preheat_pla_settings_menu ( )
{
START_MENU ( ) ;
MENU_ITEM ( back , MSG_TEMPERATURE , lcd_control_temperature_menu ) ;
MENU_ITEM_EDIT ( int3 , MSG_FAN_SPEED , & plaPreheatFanSpeed , 0 , 255 ) ;
MENU_ITEM_EDIT ( int3 , MSG_NOZZLE , & plaPreheatHotendTemp , 0 , HEATER_0_MAXTEMP - 15 ) ;
# if TEMP_SENSOR_BED != 0
MENU_ITEM_EDIT ( int3 , MSG_BED , & plaPreheatHPBTemp , 0 , BED_MAXTEMP - 15 ) ;
# endif
# if EEPROM_SETTINGS
MENU_ITEM ( function , MSG_STORE_EPROM , Config_StoreSettings ) ;
# endif
END_MENU ( ) ;
}
static void lcd_control_temperature_preheat_abs_settings_menu ( )
{
START_MENU ( ) ;
MENU_ITEM ( back , MSG_TEMPERATURE , lcd_control_temperature_menu ) ;
MENU_ITEM_EDIT ( int3 , MSG_FAN_SPEED , & absPreheatFanSpeed , 0 , 255 ) ;
MENU_ITEM_EDIT ( int3 , MSG_NOZZLE , & absPreheatHotendTemp , 0 , HEATER_0_MAXTEMP - 15 ) ;
# if TEMP_SENSOR_BED != 0
MENU_ITEM_EDIT ( int3 , MSG_BED , & absPreheatHPBTemp , 0 , BED_MAXTEMP - 15 ) ;
# endif
# if EEPROM_SETTINGS
MENU_ITEM ( function , MSG_STORE_EPROM , Config_StoreSettings ) ;
# endif
END_MENU ( ) ;
}
static void lcd_control_motion_menu ( )
{
START_MENU ( ) ;
MENU_ITEM ( back , MSG_CONTROL , lcd_control_menu ) ;
MENU_ITEM_EDIT ( float5 , MSG_ACC , & acceleration , 500 , 99000 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VXY_JERK , & max_xy_jerk , 1 , 990 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VMAX MSG_X , & max_feedrate [ X_AXIS ] , 1 , 999 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VMAX MSG_Y , & max_feedrate [ Y_AXIS ] , 1 , 999 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VMAX MSG_Z , & max_feedrate [ Z_AXIS ] , 1 , 999 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VMAX MSG_E , & max_feedrate [ E_AXIS ] , 1 , 999 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VMIN , & minimumfeedrate , 0 , 999 ) ;
MENU_ITEM_EDIT ( float3 , MSG_VTRAV_MIN , & mintravelfeedrate , 0 , 999 ) ;
MENU_ITEM_EDIT ( long5 , MSG_AMAX MSG_X , & max_acceleration_units_per_sq_second [ X_AXIS ] , 100 , 99000 ) ;
MENU_ITEM_EDIT ( long5 , MSG_AMAX MSG_Y , & max_acceleration_units_per_sq_second [ Y_AXIS ] , 100 , 99000 ) ;
MENU_ITEM_EDIT ( long5 , MSG_AMAX MSG_Z , & max_acceleration_units_per_sq_second [ Z_AXIS ] , 100 , 99000 ) ;
MENU_ITEM_EDIT ( long5 , MSG_AMAX MSG_E , & max_acceleration_units_per_sq_second [ E_AXIS ] , 100 , 99000 ) ;
MENU_ITEM_EDIT ( float5 , MSG_A_RETRACT , & retract_acceleration , 100 , 99000 ) ;
MENU_ITEM_EDIT ( float52 , MSG_XSTEPS , & axis_steps_per_unit [ X_AXIS ] , 5 , 9999 ) ;
MENU_ITEM_EDIT ( float52 , MSG_YSTEPS , & axis_steps_per_unit [ Y_AXIS ] , 5 , 9999 ) ;
MENU_ITEM_EDIT ( float51 , MSG_ZSTEPS , & axis_steps_per_unit [ Z_AXIS ] , 5 , 9999 ) ;
MENU_ITEM_EDIT ( float51 , MSG_ESTEPS , & axis_steps_per_unit [ E_AXIS ] , 5 , 9999 ) ;
END_MENU ( ) ;
}
# ifdef FWRETRACT
static void lcd_control_retract_menu ( )
{
START_MENU ( ) ;
MENU_ITEM ( back , MSG_CONTROL , lcd_control_menu ) ;
MENU_ITEM_EDIT ( bool , MSG_AUTORETRACT , & autoretract_enabled ) ;
MENU_ITEM_EDIT ( float52 , MSG_CONTROL_RETRACT , & retract_length , 0 , 100 ) ;
MENU_ITEM_EDIT ( float3 , MSG_CONTROL_RETRACTF , & retract_feedrate , 1 , 999 ) ;
MENU_ITEM_EDIT ( float52 , MSG_CONTROL_RETRACT_ZLIFT , & retract_zlift , 0 , 999 ) ;
MENU_ITEM_EDIT ( float52 , MSG_CONTROL_RETRACT_RECOVER , & retract_recover_length , 0 , 100 ) ;
MENU_ITEM_EDIT ( float3 , MSG_CONTROL_RETRACT_RECOVERF , & retract_recover_feedrate , 1 , 999 ) ;
END_MENU ( ) ;
}
# endif
# if SDCARDDETECT == -1
static void lcd_sd_refresh ( )
{
card . initsd ( ) ;
currentMenuViewOffset = 0 ;
}
# endif
static void lcd_sd_updir ( )
{
card . updir ( ) ;
currentMenuViewOffset = 0 ;
}
void lcd_sdcard_menu ( )
{
uint16_t fileCnt = card . getnrfilenames ( ) ;
START_MENU ( ) ;
MENU_ITEM ( back , MSG_MAIN , lcd_main_menu ) ;
card . getWorkDirName ( ) ;
if ( card . filename [ 0 ] = = ' / ' )
{
# if SDCARDDETECT == -1
MENU_ITEM ( function , LCD_STR_REFRESH MSG_REFRESH , lcd_sd_refresh ) ;
# endif
} else {
MENU_ITEM ( function , LCD_STR_FOLDER " .. " , lcd_sd_updir ) ;
}
for ( uint16_t i = 0 ; i < fileCnt ; i + + )
{
if ( _menuItemNr = = _lineNr )
{
card . getfilename ( 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 ( ) ;
}
# define menu_edit_type(_type, _name, _strFunc, scale) \
void menu_edit_ # # _name ( ) \
{ \
if ( ( int32_t ) encoderPosition < minEditValue ) \
encoderPosition = minEditValue ; \
if ( ( int32_t ) encoderPosition > maxEditValue ) \
encoderPosition = maxEditValue ; \
if ( lcdDrawUpdate ) \
lcd_implementation_drawedit ( editLabel , _strFunc ( ( ( _type ) encoderPosition ) / scale ) ) ; \
if ( LCD_CLICKED ) \
{ \
* ( ( _type * ) editValue ) = ( ( _type ) encoderPosition ) / scale ; \
lcd_quick_feedback ( ) ; \
currentMenu = prevMenu ; \
encoderPosition = prevEncoderPosition ; \
} \
} \
static void menu_action_setting_edit_ # # _name ( const char * pstr , _type * ptr , _type minValue , _type maxValue ) \
{ \
prevMenu = currentMenu ; \
prevEncoderPosition = encoderPosition ; \
\
lcdDrawUpdate = 2 ; \
currentMenu = menu_edit_ # # _name ; \
\
editLabel = pstr ; \
editValue = ptr ; \
minEditValue = minValue * scale ; \
maxEditValue = maxValue * scale ; \
encoderPosition = ( * ptr ) * scale ; \
}
menu_edit_type ( int , int3 , itostr3 , 1 )
menu_edit_type ( float , float3 , ftostr3 , 1 )
menu_edit_type ( float , float32 , ftostr32 , 100 )
menu_edit_type ( float , float5 , ftostr5 , 0.01 )
menu_edit_type ( float , float51 , ftostr51 , 10 )
menu_edit_type ( float , float52 , ftostr52 , 100 )
menu_edit_type ( unsigned long , long5 , ftostr5 , 0.01 )
/** End of menus **/
static void lcd_quick_feedback ( )
{
lcdDrawUpdate = 2 ;
blocking_enc = millis ( ) + 500 ;
lcd_implementation_quick_feedback ( ) ;
}
/** Menu action functions **/
static void menu_action_back ( menuFunc_t data )
{
currentMenu = data ;
encoderPosition = 0 ;
}
static void menu_action_submenu ( menuFunc_t data )
{
currentMenu = data ;
encoderPosition = 0 ;
}
static void menu_action_gcode ( const char * pgcode )
{
enquecommand_P ( pgcode ) ;
}
static void menu_action_function ( menuFunc_t data )
{
( * data ) ( ) ;
}
static void menu_action_sdfile ( const char * filename , char * longFilename )
{
char cmd [ 30 ] ;
char * c ;
sprintf_P ( cmd , PSTR ( " M23 %s " ) , filename ) ;
for ( c = & cmd [ 4 ] ; * c ; c + + )
* c = tolower ( * c ) ;
enquecommand ( cmd ) ;
enquecommand_P ( PSTR ( " M24 " ) ) ;
lcd_return_to_status ( ) ;
}
static void menu_action_sddirectory ( const char * filename , char * longFilename )
{
card . chdir ( filename ) ;
encoderPosition = 0 ;
}
static void menu_action_setting_edit_bool ( const char * pstr , bool * ptr )
{
* ptr = ! ( * ptr ) ;
}
# endif //ULTIPANEL
/** LCD API **/
void lcd_init ( )
{
lcd_implementation_init ( ) ;
# ifdef NEWPANEL
pinMode ( BTN_EN1 , INPUT ) ;
pinMode ( BTN_EN2 , INPUT ) ;
pinMode ( BTN_ENC , INPUT ) ;
pinMode ( SDCARDDETECT , INPUT ) ;
WRITE ( BTN_EN1 , HIGH ) ;
WRITE ( BTN_EN2 , HIGH ) ;
WRITE ( BTN_ENC , HIGH ) ;
# else
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 //!NEWPANEL
# if (SDCARDDETECT > -1)
WRITE ( SDCARDDETECT , HIGH ) ;
lcd_oldcardstatus = IS_SD_INSERTED ;
# endif //(SDCARDDETECT > -1)
}
void lcd_update ( )
{
static unsigned long timeoutToStatus = 0 ;
lcd_buttons_update ( ) ;
# if (SDCARDDETECT > -1)
if ( ( IS_SD_INSERTED ! = lcd_oldcardstatus ) )
{
lcdDrawUpdate = 2 ;
lcd_oldcardstatus = IS_SD_INSERTED ;
lcd_implementation_init ( ) ; // to maybe revive the lcd if static electricty killed it.
if ( lcd_oldcardstatus )
{
card . initsd ( ) ;
LCD_MESSAGEPGM ( MSG_SD_INSERTED ) ;
}
else
{
card . release ( ) ;
LCD_MESSAGEPGM ( MSG_SD_REMOVED ) ;
}
}
# endif //CARDINSERTED
if ( lcd_next_update_millis < millis ( ) )
{
# ifdef ULTIPANEL
if ( encoderDiff )
{
lcdDrawUpdate = 1 ;
encoderPosition + = encoderDiff ;
encoderDiff = 0 ;
timeoutToStatus = millis ( ) + LCD_TIMEOUT_TO_STATUS ;
}
if ( LCD_CLICKED )
timeoutToStatus = millis ( ) + LCD_TIMEOUT_TO_STATUS ;
# endif //ULTIPANEL
( * currentMenu ) ( ) ;
# ifdef ULTIPANEL
if ( timeoutToStatus < millis ( ) & & currentMenu ! = lcd_status_screen )
{
lcd_return_to_status ( ) ;
lcdDrawUpdate = 2 ;
}
# endif //ULTIPANEL
if ( lcdDrawUpdate = = 2 )
lcd_implementation_clear ( ) ;
if ( lcdDrawUpdate )
lcdDrawUpdate - - ;
lcd_next_update_millis = millis ( ) + 100 ;
}
}
void lcd_setstatus ( const char * message )
{
if ( lcd_status_message_level > 0 )
return ;
strncpy ( lcd_status_message , message , LCD_WIDTH ) ;
lcdDrawUpdate = 2 ;
}
void lcd_setstatuspgm ( const char * message )
{
if ( lcd_status_message_level > 0 )
return ;
strncpy_P ( lcd_status_message , message , LCD_WIDTH ) ;
lcdDrawUpdate = 2 ;
}
void lcd_setalertstatuspgm ( const char * message )
{
lcd_setstatuspgm ( message ) ;
lcd_status_message_level = 1 ;
# ifdef ULTIPANEL
lcd_return_to_status ( ) ;
# endif //ULTIPANEL
}
void lcd_reset_alert_level ( )
{
lcd_status_message_level = 0 ;
}
# ifdef ULTIPANEL
/* Warning: This function is called from interrupt context */
void lcd_buttons_update ( )
{
# ifdef NEWPANEL
uint8_t newbutton = 0 ;
if ( READ ( BTN_EN1 ) = = 0 ) newbutton | = EN_A ;
if ( READ ( BTN_EN2 ) = = 0 ) newbutton | = EN_B ;
if ( ( blocking_enc < millis ( ) ) & & ( READ ( BTN_ENC ) = = 0 ) )
newbutton | = EN_C ;
buttons = newbutton ;
# else //read it from the shift register
uint8_t newbutton = 0 ;
WRITE ( SHIFT_LD , LOW ) ;
WRITE ( SHIFT_LD , HIGH ) ;
unsigned char tmp_buttons = 0 ;
for ( int8_t i = 0 ; i < 8 ; i + + )
{
newbutton = newbutton > > 1 ;
if ( READ ( SHIFT_OUT ) )
newbutton | = ( 1 < < 7 ) ;
WRITE ( SHIFT_CLK , HIGH ) ;
WRITE ( SHIFT_CLK , LOW ) ;
}
buttons = ~ newbutton ; //invert it, because a pressed switch produces a logical 0
# endif //!NEWPANEL
//manage encoder rotation
uint8_t enc = 0 ;
if ( buttons & EN_A )
enc | = ( 1 < < 0 ) ;
if ( buttons & EN_B )
enc | = ( 1 < < 1 ) ;
if ( enc ! = lastEncoderBits )
{
switch ( enc )
{
case encrot0 :
if ( lastEncoderBits = = encrot3 )
encoderDiff + + ;
else if ( lastEncoderBits = = encrot1 )
encoderDiff - - ;
break ;
case encrot1 :
if ( lastEncoderBits = = encrot0 )
encoderDiff + + ;
else if ( lastEncoderBits = = encrot2 )
encoderDiff - - ;
break ;
case encrot2 :
if ( lastEncoderBits = = encrot1 )
encoderDiff + + ;
else if ( lastEncoderBits = = encrot3 )
encoderDiff - - ;
break ;
case encrot3 :
if ( lastEncoderBits = = encrot2 )
encoderDiff + + ;
else if ( lastEncoderBits = = encrot0 )
encoderDiff - - ;
break ;
}
}
lastEncoderBits = enc ;
}
# endif //ULTIPANEL
/********************************/
/** Float conversion utilities **/
/********************************/
// convert float to string with +123.4 format
char conv [ 8 ] ;
char * ftostr3 ( const float & x )
{
return itostr3 ( ( int ) x ) ;
}
char * itostr2 ( const uint8_t & x )
{
//sprintf(conv,"%5.1f",x);
int xx = x ;
conv [ 0 ] = ( xx / 10 ) % 10 + ' 0 ' ;
conv [ 1 ] = ( xx ) % 10 + ' 0 ' ;
conv [ 2 ] = 0 ;
return conv ;
}
// convert float to string with +123.4 format
char * ftostr31 ( const float & x )
{
int xx = x * 10 ;
conv [ 0 ] = ( xx > = 0 ) ? ' + ' : ' - ' ;
xx = abs ( xx ) ;
conv [ 1 ] = ( xx / 1000 ) % 10 + ' 0 ' ;
conv [ 2 ] = ( xx / 100 ) % 10 + ' 0 ' ;
conv [ 3 ] = ( xx / 10 ) % 10 + ' 0 ' ;
conv [ 4 ] = ' . ' ;
conv [ 5 ] = ( xx ) % 10 + ' 0 ' ;
conv [ 6 ] = 0 ;
return conv ;
}
char * ftostr32 ( const float & x )
{
long xx = x * 100 ;
conv [ 0 ] = ( xx > = 0 ) ? ' + ' : ' - ' ;
xx = abs ( xx ) ;
conv [ 1 ] = ( xx / 100 ) % 10 + ' 0 ' ;
conv [ 2 ] = ' . ' ;
conv [ 3 ] = ( xx / 10 ) % 10 + ' 0 ' ;
conv [ 4 ] = ( xx ) % 10 + ' 0 ' ;
conv [ 5 ] = 0 ;
return conv ;
}
char * itostr31 ( const int & xx )
{
conv [ 0 ] = ( xx > = 0 ) ? ' + ' : ' - ' ;
conv [ 1 ] = ( xx / 1000 ) % 10 + ' 0 ' ;
conv [ 2 ] = ( xx / 100 ) % 10 + ' 0 ' ;
conv [ 3 ] = ( xx / 10 ) % 10 + ' 0 ' ;
conv [ 4 ] = ' . ' ;
conv [ 5 ] = ( xx ) % 10 + ' 0 ' ;
conv [ 6 ] = 0 ;
return conv ;
}
char * itostr3 ( const int & xx )
{
if ( xx > = 100 )
conv [ 0 ] = ( xx / 100 ) % 10 + ' 0 ' ;
else
conv [ 0 ] = ' ' ;
if ( xx > = 10 )
conv [ 1 ] = ( xx / 10 ) % 10 + ' 0 ' ;
else
conv [ 1 ] = ' ' ;
conv [ 2 ] = ( xx ) % 10 + ' 0 ' ;
conv [ 3 ] = 0 ;
return conv ;
}
char * itostr3left ( const int & xx )
{
if ( xx > = 100 )
{
conv [ 0 ] = ( xx / 100 ) % 10 + ' 0 ' ;
conv [ 1 ] = ( xx / 10 ) % 10 + ' 0 ' ;
conv [ 2 ] = ( xx ) % 10 + ' 0 ' ;
conv [ 3 ] = 0 ;
}
else if ( xx > = 10 )
{
conv [ 0 ] = ( xx / 10 ) % 10 + ' 0 ' ;
conv [ 1 ] = ( xx ) % 10 + ' 0 ' ;
conv [ 2 ] = 0 ;
}
else
{
conv [ 0 ] = ( xx ) % 10 + ' 0 ' ;
conv [ 1 ] = 0 ;
}
return conv ;
}
char * itostr4 ( const int & xx )
{
if ( xx > = 1000 )
conv [ 0 ] = ( xx / 1000 ) % 10 + ' 0 ' ;
else
conv [ 0 ] = ' ' ;
if ( xx > = 100 )
conv [ 1 ] = ( xx / 100 ) % 10 + ' 0 ' ;
else
conv [ 1 ] = ' ' ;
if ( xx > = 10 )
conv [ 2 ] = ( xx / 10 ) % 10 + ' 0 ' ;
else
conv [ 2 ] = ' ' ;
conv [ 3 ] = ( xx ) % 10 + ' 0 ' ;
conv [ 4 ] = 0 ;
return conv ;
}
// convert float to string with 12345 format
char * ftostr5 ( const float & x )
{
long xx = abs ( x ) ;
if ( xx > = 10000 )
conv [ 0 ] = ( xx / 10000 ) % 10 + ' 0 ' ;
else
conv [ 0 ] = ' ' ;
if ( xx > = 1000 )
conv [ 1 ] = ( xx / 1000 ) % 10 + ' 0 ' ;
else
conv [ 1 ] = ' ' ;
if ( xx > = 100 )
conv [ 2 ] = ( xx / 100 ) % 10 + ' 0 ' ;
else
conv [ 2 ] = ' ' ;
if ( xx > = 10 )
conv [ 3 ] = ( xx / 10 ) % 10 + ' 0 ' ;
else
conv [ 3 ] = ' ' ;
conv [ 4 ] = ( xx ) % 10 + ' 0 ' ;
conv [ 5 ] = 0 ;
return conv ;
}
// convert float to string with +1234.5 format
char * ftostr51 ( const float & x )
{
long xx = x * 10 ;
conv [ 0 ] = ( xx > = 0 ) ? ' + ' : ' - ' ;
xx = abs ( xx ) ;
conv [ 1 ] = ( xx / 10000 ) % 10 + ' 0 ' ;
conv [ 2 ] = ( xx / 1000 ) % 10 + ' 0 ' ;
conv [ 3 ] = ( xx / 100 ) % 10 + ' 0 ' ;
conv [ 4 ] = ( xx / 10 ) % 10 + ' 0 ' ;
conv [ 5 ] = ' . ' ;
conv [ 6 ] = ( xx ) % 10 + ' 0 ' ;
conv [ 7 ] = 0 ;
return conv ;
}
// convert float to string with +123.45 format
char * ftostr52 ( const float & x )
{
long xx = x * 100 ;
conv [ 0 ] = ( xx > = 0 ) ? ' + ' : ' - ' ;
xx = abs ( xx ) ;
conv [ 1 ] = ( xx / 10000 ) % 10 + ' 0 ' ;
conv [ 2 ] = ( xx / 1000 ) % 10 + ' 0 ' ;
conv [ 3 ] = ( xx / 100 ) % 10 + ' 0 ' ;
conv [ 4 ] = ' . ' ;
conv [ 5 ] = ( xx / 10 ) % 10 + ' 0 ' ;
conv [ 6 ] = ( xx ) % 10 + ' 0 ' ;
conv [ 7 ] = 0 ;
return conv ;
}
# endif //ULTRA_LCD