mirror of
https://github.com/MarlinFirmware/Marlin.git
synced 2024-11-23 20:18:52 +00:00
a49c09a776
A new variable was introduced to allow fan animation on the GLCD. Add additional float to string conversion routine without sign character. This is used for the coordinates visualisation on the GLCD.
1055 lines
30 KiB
C++
1055 lines
30 KiB
C++
#include "temperature.h"
|
|
#include "ultralcd.h"
|
|
#ifdef ULTRA_LCD
|
|
#include "Marlin.h"
|
|
#include "language.h"
|
|
#include "cardreader.h"
|
|
#include "temperature.h"
|
|
#include "stepper.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) { \
|
|
const char* _label_pstr = PSTR(label); \
|
|
if ((encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr) { \
|
|
lcd_implementation_drawmenu_ ## type ## _selected (_drawLineNr, _label_pstr , ## args ); \
|
|
}else{\
|
|
lcd_implementation_drawmenu_ ## type (_drawLineNr, _label_pstr , ## args ); \
|
|
}\
|
|
}\
|
|
if (LCD_CLICKED && (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();
|
|
}
|
|
feedmultiply += int(encoderPosition);
|
|
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 (movesplanned() || IS_SD_PRINTING)
|
|
{
|
|
MENU_ITEM(submenu, MSG_TUNE, lcd_tune_menu);
|
|
}else{
|
|
MENU_ITEM(submenu, MSG_PREPARE, lcd_prepare_menu);
|
|
}
|
|
MENU_ITEM(submenu, MSG_CONTROL, lcd_control_menu);
|
|
#ifdef SDSUPPORT
|
|
if (card.cardOK)
|
|
{
|
|
if (card.isFileOpen())
|
|
{
|
|
if (card.sdprinting)
|
|
MENU_ITEM(function, MSG_PAUSE_PRINT, lcd_sdcard_pause);
|
|
else
|
|
MENU_ITEM(function, MSG_RESUME_PRINT, lcd_sdcard_resume);
|
|
MENU_ITEM(function, MSG_STOP_PRINT, lcd_sdcard_stop);
|
|
}else{
|
|
MENU_ITEM(submenu, MSG_CARD_MENU, lcd_sdcard_menu);
|
|
#if SDCARDDETECT < 1
|
|
MENU_ITEM(gcode, MSG_CNG_SDCARD, PSTR("M21")); // SD-card changed by user
|
|
#endif
|
|
}
|
|
}else{
|
|
MENU_ITEM(submenu, MSG_NO_CARD, lcd_sdcard_menu);
|
|
#if SDCARDDETECT < 1
|
|
MENU_ITEM(gcode, MSG_INIT_SDCARD, PSTR("M21")); // Manually initialize the SD-card via user interface
|
|
#endif
|
|
}
|
|
#endif
|
|
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);
|
|
fanSpeed = plaPreheatFanSpeed;
|
|
lcd_return_to_status();
|
|
}
|
|
|
|
void lcd_preheat_abs()
|
|
{
|
|
setTargetHotend0(absPreheatHotendTemp);
|
|
setTargetHotend1(absPreheatHotendTemp);
|
|
setTargetHotend2(absPreheatHotendTemp);
|
|
setTargetBed(absPreheatHPBTemp);
|
|
fanSpeed = absPreheatFanSpeed;
|
|
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);
|
|
#ifdef FILAMENTCHANGEENABLE
|
|
MENU_ITEM(gcode, MSG_FILAMENTCHANGE, PSTR("M600"));
|
|
#endif
|
|
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\nM140 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);
|
|
if (move_menu_scale < 10.0)
|
|
{
|
|
MENU_ITEM(submenu, "Move Z", lcd_move_z);
|
|
MENU_ITEM(submenu, "Extruder", lcd_move_e);
|
|
}
|
|
END_MENU();
|
|
}
|
|
|
|
static void lcd_move_menu_10mm()
|
|
{
|
|
move_menu_scale = 10.0;
|
|
lcd_move_menu_axis();
|
|
}
|
|
static void lcd_move_menu_1mm()
|
|
{
|
|
move_menu_scale = 1.0;
|
|
lcd_move_menu_axis();
|
|
}
|
|
static void lcd_move_menu_01mm()
|
|
{
|
|
move_menu_scale = 0.1;
|
|
lcd_move_menu_axis();
|
|
}
|
|
|
|
static void lcd_move_menu()
|
|
{
|
|
START_MENU();
|
|
MENU_ITEM(back, 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
|
|
#ifdef EEPROM_SETTINGS
|
|
MENU_ITEM(function, MSG_STORE_EPROM, Config_StoreSettings);
|
|
#endif
|
|
END_MENU();
|
|
}
|
|
|
|
static void lcd_control_temperature_preheat_abs_settings_menu()
|
|
{
|
|
START_MENU();
|
|
MENU_ITEM(back, 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
|
|
#ifdef EEPROM_SETTINGS
|
|
MENU_ITEM(function, MSG_STORE_EPROM, Config_StoreSettings);
|
|
#endif
|
|
END_MENU();
|
|
}
|
|
|
|
static void lcd_control_motion_menu()
|
|
{
|
|
START_MENU();
|
|
MENU_ITEM(back, 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);
|
|
#ifdef ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
|
|
MENU_ITEM_EDIT(bool, "Endstop abort", &abort_on_endstop_hit);
|
|
#endif
|
|
END_MENU();
|
|
}
|
|
|
|
#ifdef FWRETRACT
|
|
static void lcd_control_retract_menu()
|
|
{
|
|
START_MENU();
|
|
MENU_ITEM(back, 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)
|
|
lcd_buttons_update();
|
|
encoderDiff = 0;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// convert float to string with 123.4 format
|
|
char *ftostr31ns(const float &x)
|
|
{
|
|
int xx=x*10;
|
|
//conv[0]=(xx>=0)?'+':'-';
|
|
xx=abs(xx);
|
|
conv[0]=(xx/1000)%10+'0';
|
|
conv[1]=(xx/100)%10+'0';
|
|
conv[2]=(xx/10)%10+'0';
|
|
conv[3]='.';
|
|
conv[4]=(xx)%10+'0';
|
|
conv[5]=0;
|
|
return conv;
|
|
}
|
|
|
|
char *ftostr32(const float &x)
|
|
{
|
|
long xx=x*100;
|
|
if (xx >= 0)
|
|
conv[0]=(xx/10000)%10+'0';
|
|
else
|
|
conv[0]='-';
|
|
xx=abs(xx);
|
|
conv[1]=(xx/1000)%10+'0';
|
|
conv[2]=(xx/100)%10+'0';
|
|
conv[3]='.';
|
|
conv[4]=(xx/10)%10+'0';
|
|
conv[5]=(xx)%10+'0';
|
|
conv[6]=0;
|
|
return conv;
|
|
}
|
|
|
|
char *itostr31(const int &xx)
|
|
{
|
|
conv[0]=(xx>=0)?'+':'-';
|
|
conv[1]=(xx/1000)%10+'0';
|
|
conv[2]=(xx/100)%10+'0';
|
|
conv[3]=(xx/10)%10+'0';
|
|
conv[4]='.';
|
|
conv[5]=(xx)%10+'0';
|
|
conv[6]=0;
|
|
return conv;
|
|
}
|
|
|
|
char *itostr3(const int &xx)
|
|
{
|
|
if (xx >= 100)
|
|
conv[0]=(xx/100)%10+'0';
|
|
else
|
|
conv[0]=' ';
|
|
if (xx >= 10)
|
|
conv[1]=(xx/10)%10+'0';
|
|
else
|
|
conv[1]=' ';
|
|
conv[2]=(xx)%10+'0';
|
|
conv[3]=0;
|
|
return conv;
|
|
}
|
|
|
|
char *itostr3left(const int &xx)
|
|
{
|
|
if (xx >= 100)
|
|
{
|
|
conv[0]=(xx/100)%10+'0';
|
|
conv[1]=(xx/10)%10+'0';
|
|
conv[2]=(xx)%10+'0';
|
|
conv[3]=0;
|
|
}
|
|
else if (xx >= 10)
|
|
{
|
|
conv[0]=(xx/10)%10+'0';
|
|
conv[1]=(xx)%10+'0';
|
|
conv[2]=0;
|
|
}
|
|
else
|
|
{
|
|
conv[0]=(xx)%10+'0';
|
|
conv[1]=0;
|
|
}
|
|
return conv;
|
|
}
|
|
|
|
char *itostr4(const int &xx)
|
|
{
|
|
if (xx >= 1000)
|
|
conv[0]=(xx/1000)%10+'0';
|
|
else
|
|
conv[0]=' ';
|
|
if (xx >= 100)
|
|
conv[1]=(xx/100)%10+'0';
|
|
else
|
|
conv[1]=' ';
|
|
if (xx >= 10)
|
|
conv[2]=(xx/10)%10+'0';
|
|
else
|
|
conv[2]=' ';
|
|
conv[3]=(xx)%10+'0';
|
|
conv[4]=0;
|
|
return conv;
|
|
}
|
|
|
|
// convert float to string with 12345 format
|
|
char *ftostr5(const float &x)
|
|
{
|
|
long xx=abs(x);
|
|
if (xx >= 10000)
|
|
conv[0]=(xx/10000)%10+'0';
|
|
else
|
|
conv[0]=' ';
|
|
if (xx >= 1000)
|
|
conv[1]=(xx/1000)%10+'0';
|
|
else
|
|
conv[1]=' ';
|
|
if (xx >= 100)
|
|
conv[2]=(xx/100)%10+'0';
|
|
else
|
|
conv[2]=' ';
|
|
if (xx >= 10)
|
|
conv[3]=(xx/10)%10+'0';
|
|
else
|
|
conv[3]=' ';
|
|
conv[4]=(xx)%10+'0';
|
|
conv[5]=0;
|
|
return conv;
|
|
}
|
|
|
|
// convert float to string with +1234.5 format
|
|
char *ftostr51(const float &x)
|
|
{
|
|
long xx=x*10;
|
|
conv[0]=(xx>=0)?'+':'-';
|
|
xx=abs(xx);
|
|
conv[1]=(xx/10000)%10+'0';
|
|
conv[2]=(xx/1000)%10+'0';
|
|
conv[3]=(xx/100)%10+'0';
|
|
conv[4]=(xx/10)%10+'0';
|
|
conv[5]='.';
|
|
conv[6]=(xx)%10+'0';
|
|
conv[7]=0;
|
|
return conv;
|
|
}
|
|
|
|
// convert float to string with +123.45 format
|
|
char *ftostr52(const float &x)
|
|
{
|
|
long xx=x*100;
|
|
conv[0]=(xx>=0)?'+':'-';
|
|
xx=abs(xx);
|
|
conv[1]=(xx/10000)%10+'0';
|
|
conv[2]=(xx/1000)%10+'0';
|
|
conv[3]=(xx/100)%10+'0';
|
|
conv[4]='.';
|
|
conv[5]=(xx/10)%10+'0';
|
|
conv[6]=(xx)%10+'0';
|
|
conv[7]=0;
|
|
return conv;
|
|
}
|
|
|
|
#endif //ULTRA_LCD
|