diff --git a/Marlin/AO_FT810_Constants.h b/Marlin/AO_FT810_Constants.h index b873da7df..9c5c67aed 100644 --- a/Marlin/AO_FT810_Constants.h +++ b/Marlin/AO_FT810_Constants.h @@ -280,22 +280,22 @@ namespace FT810 { // OPTIONS namespace FTDI { - const uint16_t OPT_3D = 0; - const uint16_t OPT_RGB565 = 0; - const uint16_t OPT_MONO = 1; - const uint16_t OPT_NODL = 2; - const uint16_t OPT_FLAT = 256; - const uint16_t OPT_SIGNED = 256; - const uint16_t OPT_CENTERX = 512; - const uint16_t OPT_CENTERY = 1024; - const uint16_t OPT_CENTER = 1536; - const uint16_t OPT_RIGHTX = 2048; - const uint16_t OPT_NOBACK = 4096; - const uint16_t OPT_NOTICKS = 8192; - const uint16_t OPT_NOHM = 16384; - const uint16_t OPT_NOPOINTER = 16384; - const uint16_t OPT_NOSECS = 32768; - const uint16_t OPT_NOHANDS = 49152; + const uint16_t OPT_3D = 0x0000; + const uint16_t OPT_RGB565 = 0x0000; + const uint16_t OPT_MONO = 0x0001; + const uint16_t OPT_NODL = 0x0002; + const uint16_t OPT_FLAT = 0x0100; + const uint16_t OPT_SIGNED = 0x0100; + const uint16_t OPT_CENTERX = 0x0200; + const uint16_t OPT_CENTERY = 0x0400; + const uint16_t OPT_CENTER = (OPT_CENTERX | OPT_CENTERY); + const uint16_t OPT_RIGHTX = 0x0800; + const uint16_t OPT_NOBACK = 0x1000; + const uint16_t OPT_NOTICKS = 0x2000; + const uint16_t OPT_NOHM = 0x4000; + const uint16_t OPT_NOPOINTER = 0x4000; + const uint16_t OPT_NOSECS = 0x8000; + const uint16_t OPT_NOHANDS = (OPT_NOPOINTER | OPT_NOSECS); } // GPIO Bits @@ -348,12 +348,21 @@ namespace FTDI_LCD_480x272 { const int Pclk = 5; const int Clksel = 0x44; - const uint32_t default_transform_a = 0x00008100; - const uint32_t default_transform_b = 0x00000000; - const uint32_t default_transform_c = 0xFFF18000; - const uint32_t default_transform_d = 0x00000000; - const uint32_t default_transform_e = 0xFFFFB100; - const uint32_t default_transform_f = 0x0120D000; + #if defined(LCD_PORTRAIT) + const uint32_t default_transform_a = 0xFFFFFEA3; + const uint32_t default_transform_b = 0xFFFFB05D; + const uint32_t default_transform_c = 0x012C5254; + const uint32_t default_transform_d = 0xFFFF8303; + const uint32_t default_transform_e = 0xFFFFFDF8; + const uint32_t default_transform_f = 0x01F32984; + #else + const uint32_t default_transform_a = 0x00008100; + const uint32_t default_transform_b = 0x00000000; + const uint32_t default_transform_c = 0xFFF18000; + const uint32_t default_transform_d = 0x00000000; + const uint32_t default_transform_e = 0xFFFFB100; + const uint32_t default_transform_f = 0x0120D000; + #endif } // GLOBAL LCD REGISTER SET VALUES FOR 800x480 DISPLAY @@ -706,6 +715,7 @@ namespace FTDI { enum note_t { END_SONG = 0x00, + NOTE_C3 = 0x32, NOTE_D3 = 0x33, NOTE_D3S = 0x34, NOTE_F3 = 0x35, diff --git a/Marlin/AO_FT810_Functions.h b/Marlin/AO_FT810_Functions.h index 8bd24ac3a..d3200e4cf 100644 --- a/Marlin/AO_FT810_Functions.h +++ b/Marlin/AO_FT810_Functions.h @@ -175,6 +175,7 @@ class CLCD { static void Flash_Write_RGB332_Bitmap(uint32_t Mem_Address, const unsigned char* pRGB332_Array, uint16_t Num_Bytes); static uint8_t Get_Tag() {return Mem_Read8(REG_TOUCH_TAG);} + static bool Is_Touching() {return (Mem_Read32(REG_TOUCH_DIRECT_XY) & 0x80000000) == 0;} }; /********************************* FT800/810 Commands *********************************/ @@ -271,9 +272,9 @@ class CLCD::CommandFifo { void Cmd (void* data, uint16_t len); void Cmd_Str (const char * const data); void Cmd_Str (progmem_str data); - void Cmd_Clear_Color (uint32_t rgb); + void Cmd_Set_Clear_Color (uint32_t rgb); void Cmd_Clear (bool Clr, bool Stl, bool Tag); - void Cmd_Color (uint32_t rgb); + void Cmd_Set_Color (uint32_t rgb); void Cmd_Set_Foreground_Color (uint32_t rgb); void Cmd_Set_Background_Color (uint32_t rgb); void Cmd_Set_Tag (uint8_t Tag); @@ -301,8 +302,11 @@ class CLCD::CommandFifo { Cmd(BITMAP_TRANSFORM_E | 256); } } - template FORCEDINLINE void Cmd_Draw_Button_Text(int16_t x, int16_t y, int16_t w, int16_t h, T text, int16_t font) { - Cmd_Draw_Text(x + w/2, y + h/2, text, font, OPT_CENTER); + template FORCEDINLINE void Cmd_Draw_Button_Text(int16_t x, int16_t y, int16_t w, int16_t h, T text, int16_t font, uint16_t options = OPT_CENTER) { + Cmd_Draw_Text( + x + ((options & OPT_CENTERX) ? w/2 : 0), + y + ((options & OPT_CENTERY) ? h/2 : h), + text, font, options); } void Cmd_Bitmap_Layout (uint8_t format, uint16_t linestride, uint16_t height); @@ -330,7 +334,7 @@ inline uint32_t CLCD::pack_rgb(uint8_t r, uint8_t g, uint8_t b) { return (uint32_t(r) << 16) | (uint32_t(g) << 8) | uint32_t(b); } -void CLCD::CommandFifo::Cmd_Clear_Color (uint32_t rgb) // DL Command - Set Clear Screen Color +void CLCD::CommandFifo::Cmd_Set_Clear_Color (uint32_t rgb) // DL Command - Set Clear Screen Color { Cmd(CLEAR_COLOR_RGB | rgb); } @@ -344,7 +348,7 @@ void CLCD::CommandFifo::Cmd_Clear (bool Clr, bool Stl, bool Tag) // ); } -void CLCD::CommandFifo::Cmd_Color (uint32_t rgb) // DL Command - Set Current Color +void CLCD::CommandFifo::Cmd_Set_Color (uint32_t rgb) // DL Command - Set Current Color { Cmd(COLOR_RGB | rgb); } @@ -878,17 +882,42 @@ void CLCD::Init (void) { CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_F, default_transform_f); } -/******************* SOUND HELPER CLASS ************************/ +/******************* TINY INTERVAL CLASS ***********************/ /* tiny_interval() downsamples a 32-bit millis() value into a 8-bit value which can record periods of up to 4.096 seconds with a rougly 16 millisecond resolution. This allows us to measure small intervals without needing to use four-byte counters. + + However, dues to wrap-arounds, this class may misfire + often and thus should only be used where memory savings + outweigh accuracy. */ -inline uint8_t tiny_interval(uint32_t ms) { - return uint8_t(ms / 64); -} +class tiny_interval_t { + private: + uint8_t end; + public: + static inline uint8_t tiny_interval(uint32_t ms) { + return uint8_t(ms / 64); + } + + inline void wait_for(uint32_t ms) { + end = tiny_interval(millis() + ms); + } + + inline bool elapsed() { + if(end == 0 || tiny_interval(millis()) > end) { + end = 0; + return true; + } else { + return false; + } + } +}; + +/******************* SOUND HELPER CLASS ************************/ + class CLCD::SoundPlayer { public: @@ -934,7 +963,7 @@ void CLCD::SoundPlayer::play(effect_t effect, note_t note) { void CLCD::SoundPlayer::play(const sound_t* seq) { sequence = seq; - next = tiny_interval(millis()) + 1; + next = tiny_interval_t::tiny_interval(millis()) + 1; } bool CLCD::SoundPlayer::soundPlaying() { @@ -944,7 +973,7 @@ bool CLCD::SoundPlayer::soundPlaying() { void CLCD::SoundPlayer::onIdle() { if(!sequence) return; - const uint8_t tiny_millis = tiny_interval(millis()); + const uint8_t tiny_millis = tiny_interval_t::tiny_interval(millis()); const bool readyForNextNote = (next == WAIT) ? !soundPlaying() : (tiny_millis > next); if(readyForNextNote) { @@ -960,7 +989,7 @@ void CLCD::SoundPlayer::onIdle() { SERIAL_PROTOCOLLNPAIR("Scheduling note in ", ms); #endif #endif - next = (ms == WAIT) ? 0 : (tiny_millis + tiny_interval(ms)); + next = (ms == WAIT) ? 0 : (tiny_millis + tiny_interval_t::tiny_interval(ms)); play(fx, (nt == 0) ? NOTE_C4 : nt); sequence++; } diff --git a/Marlin/AO_FT810_UI_Screens.h b/Marlin/AO_FT810_UI_Screens.h index ce3903954..f82aa1f22 100644 --- a/Marlin/AO_FT810_UI_Screens.h +++ b/Marlin/AO_FT810_UI_Screens.h @@ -18,12 +18,13 @@ #define DISPLAY_UPDATE_INTERVAL 1000 #define TOUCH_REPEATS_PER_SECOND 4 +#define DEBOUNCE_PERIOD 100 // To save MCU RAM, the status message is "baked" in to the status screen // cache, so we reserve a large chunk of memory for the DL cache #define STATUS_SCREEN_DL_SIZE 2048 -#define CONFIRMATION_SCREEN_DL_SIZE 2048 +#define CONFIRMATION_SCREEN_DL_SIZE 3072 #define N_ELEMENTS(a) (sizeof(a)/sizeof(a[0])) @@ -86,6 +87,14 @@ #define BTN_TAG(t) cmd.Cmd_Set_Tag(t); #define RGB(rgb) cmd.Cmd_Set_Foreground_Color(rgb); #define THEME(color) cmd.Cmd_Set_Foreground_Color(Theme::color); +#define BTN_ENABLED(en) if(en) { \ + cmd.Cmd_Set_Color(Theme::btn_rgb_enabled); \ + cmd.Cmd_Set_Foreground_Color(Theme::btn_fg_enabled); \ + } else { \ + cmd.Cmd_Set_Color(Theme::btn_rgb_disabled); \ + cmd.Cmd_Set_Foreground_Color(Theme::btn_fg_disabled); \ + cmd.Cmd_Set_Tag(0); \ + } #define FONT_SML Theme::font_small #define FONT_MED Theme::font_medium @@ -95,6 +104,16 @@ #define EXEC_GCODE(cmd) Marlin_LCD_API::runGCode(cmd) +/****************************** SCREEN STATIC DATA *************************/ + +// To save RAM, store state information related to a particular screen +// in a union. The values should be initialized in the onEntry method. + +static union { + struct {uint8_t increment;} ValueAdjusters; + struct {uint8_t page, selected;} FilesScreen; +} screen_data; + /************************* MENU SCREEN DECLARATIONS *************************/ class BootScreen : public UIScreen { @@ -117,20 +136,30 @@ class KillScreen { static void show(progmem_str msg); }; -class ConfirmationScreen : public UIScreen { +class DialogBoxBaseClass : public UIScreen { protected: - static void onEntry(); static void show(const progmem_str message[], size_t lines, progmem_str btn1, progmem_str btn2 ); + static void onRefresh(); + public: static bool onTouchStart(uint8_t tag); +}; +class AlertBoxScreen : public DialogBoxBaseClass { public: static void onRefresh(); + static void show(const progmem_str line1, const progmem_str line2 = 0, const progmem_str line3 = 0); }; -class RestoreFailsafeScreen : public ConfirmationScreen { - protected: - static void showCompletion(); +class RestoreFailsafeScreen : public DialogBoxBaseClass { public: + static void onRefresh(); + static void onEntry(); + static bool onTouchStart(uint8_t tag); +}; + +class ConfirmAbortPrint : public DialogBoxBaseClass { + public: + static void onRefresh(); static void onEntry(); static bool onTouchStart(uint8_t tag); }; @@ -140,12 +169,14 @@ class StatusScreen : public UIScreen { static void static_axis_position(); static void static_temperature(); static void static_progress(); + static void static_media_button(); static void static_interaction_buttons(); static void static_status_message(const char * const message); static void dynamic_axis_position(); static void dynamic_temperature(); static void dynamic_progress(); + static void dynamic_interaction_buttons(); public: static void setStatusMessage(const char * message); @@ -164,6 +195,7 @@ class MenuScreen : public UIScreen { class CalibrationScreen : public UIScreen { public: + static void onEntry(); static void onRefresh(); static void onIdle(); }; @@ -182,7 +214,6 @@ class AdvancedSettingsScreen : public UIScreen { class ValueAdjusters : public UIScreen { private: - static uint8_t increment; static void draw_increment_btn(uint8_t line, const uint8_t tag, uint8_t decimals); protected: struct stacker_t { @@ -219,6 +250,7 @@ class ValueAdjusters : public UIScreen { static float getIncrement(); public: + static void onEntry(); static bool onTouchStart(uint8_t tag); }; @@ -247,9 +279,12 @@ class TemperatureScreen : public ValueAdjusters { }; class FilesScreen : public UIScreen { + private: + static const char *getSelectedShortFilename(); public: + static void onEntry(); static void onRefresh(); - static bool onTouchHeld(uint8_t tag); + static bool onTouchStart(uint8_t tag); }; /******************************* MENU SCREEN TABLE ******************************/ @@ -257,7 +292,9 @@ class FilesScreen : public UIScreen { SCREEN_TABLE { DECL_SCREEN(BootScreen), DECL_SCREEN(AboutScreen), + DECL_SCREEN(AlertBoxScreen), DECL_SCREEN(RestoreFailsafeScreen), + DECL_SCREEN(ConfirmAbortPrint), DECL_SCREEN(CalibrationScreen), DECL_SCREEN(StatusScreen), DECL_SCREEN(MenuScreen), @@ -293,32 +330,38 @@ enum { /************************************ MENU THEME ********************************/ namespace Theme { - const uint32_t olive_darkest = 0x2A2F0A; - const uint32_t olive_dark = 0x495212; - const uint32_t olive_light = 0x8C9D22; + const uint32_t theme_darkest = 0x2A2F0A; + const uint32_t theme_dark = 0x495212; + const uint32_t theme_light = 0x8C9D22; + + const uint32_t background = theme_dark; + const uint32_t back_btn = theme_light; - const uint32_t background = 0x707070; const uint32_t x_axis = 0x500000; const uint32_t y_axis = 0x005000; const uint32_t z_axis = 0x000050; const uint32_t e_axis = 0x000000; - const uint32_t menu_btn = olive_dark; - const uint32_t navi_btn = olive_light; - const uint32_t toggle_on = olive_light; - const uint32_t toggle_off = olive_darkest; - const uint32_t disabled = background; + const uint32_t toggle_on = theme_light; + const uint32_t toggle_off = theme_darkest; - // About screen - const uint32_t about_bg = olive_dark; - const uint32_t about_btn = olive_darkest; + // Disabled vs enabled buttons + const uint32_t btn_rgb_enabled = 0xFFFFFF; + const uint32_t btn_fg_enabled = theme_darkest; + const uint32_t btn_rgb_disabled = theme_dark; + const uint32_t btn_fg_disabled = theme_dark; + + // Files screens + + const uint32_t files_selected = theme_light; // Adjustment Screens - const uint32_t adjust_bg = olive_dark; - const uint32_t incr_btn = olive_darkest; + const uint32_t incr_btn = theme_darkest; // Status screen + const uint32_t status_bg = 0x707070; + const uint32_t status_dark = 0x404040; const uint32_t stop_btn = 0xF02020; const uint32_t prnt_btn = 0x20D020; const uint32_t progress = 0x404040; @@ -371,7 +414,7 @@ namespace Theme { void BootScreen::onRefresh() { CLCD::CommandFifo cmd; cmd.Cmd(CMD_DLSTART); - cmd.Cmd_Clear_Color(Theme::background); + cmd.Cmd_Set_Clear_Color(Theme::background); cmd.Cmd_Clear(1,1,1); cmd.Cmd(DL_DISPLAY); cmd.Cmd(CMD_SWAP); @@ -383,7 +426,15 @@ void BootScreen::onRefresh() { } void BootScreen::onIdle() { - GOTO_SCREEN(CalibrationScreen); + if(CLCD::Is_Touching()) { + // If the user is touching the screen at startup, then + // assume the user wants to re-calibrate the screen. + // This gives the user the ability to recover a + // miscalibration that has been stored to EEPROM. + GOTO_SCREEN(CalibrationScreen); + } else { + GOTO_SCREEN(StatusScreen); + } } /******************************** ABOUT SCREEN ****************************/ @@ -400,7 +451,7 @@ void AboutScreen::onEntry() { void AboutScreen::onRefresh() { CLCD::CommandFifo cmd; cmd.Cmd(CMD_DLSTART); - cmd.Cmd_Clear_Color(Theme::about_bg); + cmd.Cmd_Set_Clear_Color(Theme::background); cmd.Cmd_Clear(1,1,1); #define GRID_COLS 4 @@ -412,7 +463,7 @@ void AboutScreen::onRefresh() { BTX( BTN_POS(1,5), BTN_SIZE(4,1), Marlin_LCD_API::getFirmwareName(), FONT_LRG); - BTN_TAG(1) THEME(about_btn) BTN( BTN_POS(2,7), BTN_SIZE(2,1), F("Okay"), MENU_BTN_STYLE); + BTN_TAG(1) BTN_ENABLED(1) BTN( BTN_POS(2,7), BTN_SIZE(2,1), F("Okay"), MENU_BTN_STYLE); cmd.Cmd(DL_DISPLAY); cmd.Cmd(CMD_SWAP); @@ -426,21 +477,14 @@ bool AboutScreen::onTouchStart(uint8_t tag) { } } -/**************************** GENERIC CONFIRMATION SCREEN ****************************/ - -void ConfirmationScreen::onEntry() { - progmem_str lines[] = { - F("Are you sure?") - }; - ConfirmationScreen::show(lines, N_ELEMENTS(lines), F("Yes"), F("No")); -} +/**************************** GENERIC DIALOG BOX SCREEN ****************************/ -void ConfirmationScreen::show(const progmem_str lines[], size_t n_lines, progmem_str btn1, progmem_str btn2 ) { +void DialogBoxBaseClass::show(const progmem_str lines[], size_t n_lines, progmem_str btn1, progmem_str btn2 ) { CLCD::DLCache dlcache(CONFIRMATION_SCREEN_CACHE); CLCD::CommandFifo cmd; cmd.Cmd(CMD_DLSTART); - cmd.Cmd_Clear_Color(Theme::about_bg); + cmd.Cmd_Set_Clear_Color(Theme::background); cmd.Cmd_Clear(1,1,1); #define GRID_COLS 2 @@ -451,12 +495,12 @@ void ConfirmationScreen::show(const progmem_str lines[], size_t n_lines, progmem } if(btn1 && btn2) { - BTN_TAG(1) THEME(about_btn) BTN( BTN_POS(1,8), BTN_SIZE(1,1), btn1, MENU_BTN_STYLE); - BTN_TAG(2) THEME(about_btn) BTN( BTN_POS(2,8), BTN_SIZE(1,1), btn2, MENU_BTN_STYLE); + BTN_TAG(1) BTN_ENABLED(1) BTN( BTN_POS(1,8), BTN_SIZE(1,1), btn1, MENU_BTN_STYLE); + BTN_TAG(2) BTN_ENABLED(1) BTN( BTN_POS(2,8), BTN_SIZE(1,1), btn2, MENU_BTN_STYLE); } else if(btn1) { - BTN_TAG(1) THEME(about_btn) BTN( BTN_POS(1,8), BTN_SIZE(2,1), btn1, MENU_BTN_STYLE); + BTN_TAG(1) BTN_ENABLED(1) BTN( BTN_POS(1,8), BTN_SIZE(2,1), btn1, MENU_BTN_STYLE); } else if(btn2) { - BTN_TAG(2) THEME(about_btn) BTN( BTN_POS(1,8), BTN_SIZE(2,1), btn2, MENU_BTN_STYLE); + BTN_TAG(2) BTN_ENABLED(1) BTN( BTN_POS(1,8), BTN_SIZE(2,1), btn2, MENU_BTN_STYLE); } cmd.Cmd(DL_DISPLAY); @@ -474,7 +518,7 @@ void ConfirmationScreen::show(const progmem_str lines[], size_t n_lines, progmem } } -void ConfirmationScreen::onRefresh() { +void DialogBoxBaseClass::onRefresh() { CLCD::DLCache dlcache(CONFIRMATION_SCREEN_CACHE); CLCD::CommandFifo cmd; cmd.Cmd(CMD_DLSTART); @@ -488,13 +532,27 @@ void ConfirmationScreen::onRefresh() { cmd.Cmd_Execute(); } -bool ConfirmationScreen::onTouchStart(uint8_t tag) { +bool DialogBoxBaseClass::onTouchStart(uint8_t tag) { switch(tag) { case 1: GOTO_PREVIOUS(); return true; case 2: GOTO_PREVIOUS(); return true; } } +/****************************** ALERT BOX SCREEN *****************************/ + +void AlertBoxScreen::onRefresh() { + DialogBoxBaseClass::onRefresh(); +} + +void AlertBoxScreen::show(const progmem_str line1, const progmem_str line2, const progmem_str line3) { + progmem_str lines[] = {line1, line2, line3}; + + DialogBoxBaseClass::show(lines, line3 ? 3 : line2 ? 2 : 1, F("Okay"), 0); + sound.play(c_maj_arpeggio); + GOTO_SCREEN(AlertBoxScreen); +} + /**************************** RESTORE FAILSAFE SCREEN ***************************/ void RestoreFailsafeScreen::onEntry() { @@ -503,26 +561,57 @@ void RestoreFailsafeScreen::onEntry() { F("Customizations will be lost.") }; - ConfirmationScreen::show(lines, N_ELEMENTS(lines), F("Yes"), F("No")); + DialogBoxBaseClass::show(lines, N_ELEMENTS(lines), F("Yes"), F("No")); +} + +void RestoreFailsafeScreen::onRefresh() { + DialogBoxBaseClass::onRefresh(); } -void RestoreFailsafeScreen::showCompletion() { +bool RestoreFailsafeScreen::onTouchStart(uint8_t tag) { + switch(tag) { + case 1: + EXEC_GCODE(F("M502\nM500")); + AlertBoxScreen::show(F("Factory settings restored.")); + // Remove RestoreFailsafeScreen from the stack + // so the alert box doesn't return to it. + current_screen.forget(); + return true; + default: + return DialogBoxBaseClass::onTouchStart(tag); + } +} + +/**************************** RESTORE FAILSAFE SCREEN ***************************/ + +void ConfirmAbortPrint::onEntry() { progmem_str lines[] = { - F("Default settings restored.") + F("Are you sure you want"), + F("to stop the print?") }; - sound.play(c_maj_arpeggio); - ConfirmationScreen::show(lines, N_ELEMENTS(lines), 0, F("Okay")); + DialogBoxBaseClass::show(lines, N_ELEMENTS(lines), F("Yes"), F("No")); } -bool RestoreFailsafeScreen::onTouchStart(uint8_t tag) { +void ConfirmAbortPrint::onRefresh() { + DialogBoxBaseClass::onRefresh(); +} + +bool ConfirmAbortPrint::onTouchStart(uint8_t tag) { switch(tag) { case 1: - EXEC_GCODE(F("M502\nM500")); - showCompletion(); + #if defined (SERIAL_PROTOCOLLNPAIR) + SERIAL_PROTOCOLLN("Abort confirmed"); + #else + #if defined(UI_FRAMEWORK_DEBUG) + Serial.print(F("Abort confirmed")); + #endif + #endif + GOTO_PREVIOUS(); + Marlin_LCD_API::stopPrint(); return true; default: - ConfirmationScreen::onTouchStart(tag); + return DialogBoxBaseClass::onTouchStart(tag); } } @@ -536,7 +625,7 @@ void KillScreen::show(progmem_str message) { CLCD::CommandFifo cmd; cmd.Cmd(CMD_DLSTART); - cmd.Cmd_Clear_Color(Theme::about_bg); + cmd.Cmd_Set_Clear_Color(Theme::background); cmd.Cmd_Clear(1,1,1); #define GRID_COLS 4 @@ -769,26 +858,34 @@ void StatusScreen::dynamic_progress() { #define GRID_COLS 4 -void StatusScreen::static_interaction_buttons() { +void StatusScreen::static_media_button() { CLCD::CommandFifo cmd; + if(Marlin_LCD_API::isMediaInserted()) { + BTN_TAG(3) + BTN_ENABLED(1) + } else { + BTN_TAG(0) + cmd.Cmd_Set_Color(Theme::status_bg); + cmd.Cmd_Set_Foreground_Color(Theme::status_bg); + } + #if defined(LCD_PORTRAIT) - BTN_TAG(1) THEME(stop_btn) BTN( BTN_POS(1,8), BTN_SIZE(4,1), F("STOP"), MENU_BTN_STYLE); - BTN_TAG(3) THEME(navi_btn) BTN( BTN_POS(1,9), BTN_SIZE(2,1), F(""), MENU_BTN_STYLE); - BTN_TAG(4) THEME(navi_btn) BTN( BTN_POS(3,9), BTN_SIZE(2,1), F("MENU"), MENU_BTN_STYLE); - #else - BTN_TAG(1) THEME(stop_btn) BTN( BTN_POS(1,7), BTN_SIZE(2,2), F("STOP"), MENU_BTN_STYLE); - BTN_TAG(3) THEME(navi_btn) BTN( BTN_POS(3,7), BTN_SIZE(1,2), F(""), MENU_BTN_STYLE); - BTN_TAG(4) THEME(navi_btn) BTN( BTN_POS(4,7), BTN_SIZE(1,2), F("MENU"), MENU_BTN_STYLE); + BTN( BTN_POS(1,9), BTN_SIZE(2,1), F(""), MENU_BTN_STYLE); + #else + BTN( BTN_POS(3,7), BTN_SIZE(1,2), F(""), MENU_BTN_STYLE); #endif + if(!Marlin_LCD_API::isMediaInserted()) { + cmd.Cmd_Set_Color(Theme::status_dark); + } + // Draw Thumb Drive Bitmap on USB Button cmd.Cmd_Bitmap_Source(TD_Icon_Info); cmd.Cmd_Bitmap_Layout(TD_Icon_Info); cmd.Cmd_Bitmap_Size (TD_Icon_Info); - BTN_TAG(3) #if defined(LCD_PORTRAIT) BTI(BTN_POS(1,9), BTN_SIZE(2,1), TD_Icon_Info, Theme::icon_scale); #else @@ -796,11 +893,41 @@ void StatusScreen::static_interaction_buttons() { #endif } +void StatusScreen::static_interaction_buttons() { + CLCD::CommandFifo cmd; + + #if defined(LCD_PORTRAIT) + BTN_TAG(4) BTN_ENABLED(1) BTN( BTN_POS(3,9), BTN_SIZE(2,1), F("MENU"), MENU_BTN_STYLE); + #else + BTN_TAG(4) THEME(back_btn) BTN( BTN_POS(4,7), BTN_SIZE(1,2), F("MENU"), MENU_BTN_STYLE); + #endif +} + +void StatusScreen::dynamic_interaction_buttons() { + CLCD::CommandFifo cmd; + + if(Marlin_LCD_API::isPrintingFromMedia()) { + BTN_TAG(1) + THEME(stop_btn) + } else { + BTN_TAG(0) + cmd.Cmd_Set_Color(Theme::status_bg); + cmd.Cmd_Set_Foreground_Color(Theme::status_bg); + } + + #if defined(LCD_PORTRAIT) + BTN( BTN_POS(1,8), BTN_SIZE(4,1), F("STOP"), MENU_BTN_STYLE); + #else + BTN( BTN_POS(1,7), BTN_SIZE(2,2), F("STOP"), MENU_BTN_STYLE); + #endif +} + #define GRID_COLS 1 void StatusScreen::static_status_message(const char * const message) { CLCD::CommandFifo cmd; + BTN_TAG(0) #if defined(LCD_PORTRAIT) THEME(status_msg) BTN( BTN_POS(1,4), BTN_SIZE(1,1), message, FONT_LRG, OPT_FLAT); #else @@ -814,12 +941,13 @@ void StatusScreen::setStatusMessage(const char * const message) { CLCD::CommandFifo cmd; cmd.Cmd(CMD_DLSTART); - cmd.Cmd_Clear_Color(Theme::background); + cmd.Cmd_Set_Clear_Color(Theme::status_bg); cmd.Cmd_Clear(1,1,1); static_temperature(); static_progress(); static_axis_position(); + static_media_button(); static_interaction_buttons(); static_status_message(message); @@ -833,6 +961,10 @@ void StatusScreen::setStatusMessage(const char * const message) { #endif #endif } + + if(current_screen.getType() == current_screen.lookupScreen(StatusScreen::onRefresh)) { + onRefresh(); + } } #if defined(LCD_PORTRAIT) @@ -867,6 +999,7 @@ void StatusScreen::onRefresh() { dynamic_temperature(); dynamic_progress(); dynamic_axis_position(); + dynamic_interaction_buttons(); cmd.Cmd(DL_DISPLAY); cmd.Cmd(CMD_SWAP); @@ -883,6 +1016,15 @@ void StatusScreen::onIdle() { bool StatusScreen::onTouchStart(uint8_t tag) { switch(tag) { + case 1: + #if defined(UI_FRAMEWORK_DEBUG) + #if defined (SERIAL_PROTOCOLLNPGM) + SERIAL_PROTOCOLLNPGM("Aborting print"); + #endif + #endif + GOTO_SCREEN(ConfirmAbortPrint); + break; + case 3: GOTO_SCREEN(FilesScreen); break; case 4: GOTO_SCREEN(MenuScreen); break; case 5: GOTO_SCREEN(TemperatureScreen); break; case 6: GOTO_SCREEN(MoveAxisScreen); break; @@ -908,34 +1050,34 @@ void MenuScreen::onRefresh() { if(dlcache.hasData()) { dlcache.append(); } else { - cmd.Cmd_Clear_Color(Theme::background); + cmd.Cmd_Set_Clear_Color(Theme::background); cmd.Cmd_Clear(1,1,1); #if defined(LCD_PORTRAIT) - BTN_TAG(2) THEME(menu_btn) BTN( BTN_POS(1,1), BTN_SIZE(1,1), F("Auto Home"), MENU_BTN_STYLE); - BTN_TAG(3) THEME(menu_btn) BTN( BTN_POS(2,1), BTN_SIZE(1,1), F("Move Axis"), MENU_BTN_STYLE); - BTN_TAG(4) THEME(menu_btn) BTN( BTN_POS(1,2), BTN_SIZE(2,1), F("Disable Steppers"), MENU_BTN_STYLE); - - BTN_TAG(5) THEME(menu_btn) BTN( BTN_POS(1,3), BTN_SIZE(2,1), F("Temperature"), MENU_BTN_STYLE); - BTN_TAG(6) THEME(menu_btn) BTN( BTN_POS(1,4), BTN_SIZE(2,1), F("Advanced Settings"), MENU_BTN_STYLE); - BTN_TAG(8) THEME(menu_btn) BTN( BTN_POS(1,5), BTN_SIZE(2,1), F("Recalibrate Screen"), MENU_BTN_STYLE); - BTN_TAG(7) THEME(menu_btn) BTN( BTN_POS(1,6), BTN_SIZE(2,1), F("About Firmware"), MENU_BTN_STYLE); + BTN_TAG(2) BTN_ENABLED(1) BTN( BTN_POS(1,1), BTN_SIZE(1,1), F("Auto Home"), MENU_BTN_STYLE); + BTN_TAG(3) BTN_ENABLED(1) BTN( BTN_POS(2,1), BTN_SIZE(1,1), F("Move Axis"), MENU_BTN_STYLE); + BTN_TAG(5) BTN_ENABLED(1) BTN( BTN_POS(1,2), BTN_SIZE(2,1), F("Temperature"), MENU_BTN_STYLE); + BTN_TAG(6) BTN_ENABLED(0) BTN( BTN_POS(1,3), BTN_SIZE(2,1), F("Change Filament"), MENU_BTN_STYLE); + BTN_TAG(4) BTN_ENABLED(1) BTN( BTN_POS(1,4), BTN_SIZE(2,1), F("Disable Steppers"), MENU_BTN_STYLE); + BTN_TAG(7) BTN_ENABLED(1) BTN( BTN_POS(1,5), BTN_SIZE(2,1), F("Advanced Settings"), MENU_BTN_STYLE); + BTN_TAG(8) BTN_ENABLED(1) BTN( BTN_POS(1,6), BTN_SIZE(2,1), F("About Firmware"), MENU_BTN_STYLE); #else - BTN_TAG(2) THEME(menu_btn) BTN( BTN_POS(1,1), BTN_SIZE(1,1), F("Auto Home"), MENU_BTN_STYLE); - BTN_TAG(3) THEME(menu_btn) BTN( BTN_POS(1,2), BTN_SIZE(1,1), F("Move Axis"), MENU_BTN_STYLE); - BTN_TAG(4) THEME(menu_btn) BTN( BTN_POS(1,3), BTN_SIZE(1,1), F("Disable Steppers"), MENU_BTN_STYLE); - - BTN_TAG(5) THEME(menu_btn) BTN( BTN_POS(2,1), BTN_SIZE(1,1), F("Temperature"), MENU_BTN_STYLE); - BTN_TAG(6) THEME(menu_btn) BTN( BTN_POS(2,2), BTN_SIZE(1,1), F("Configuration"), MENU_BTN_STYLE); - BTN_TAG(7) THEME(menu_btn) BTN( BTN_POS(2,3), BTN_SIZE(1,1), F("About Firmware"), MENU_BTN_STYLE); + BTN_TAG(2) BTN_ENABLED(1) BTN( BTN_POS(1,1), BTN_SIZE(1,1), F("Auto Home"), MENU_BTN_STYLE); + BTN_TAG(3) BTN_ENABLED(1) BTN( BTN_POS(1,2), BTN_SIZE(1,1), F("Move Axis"), MENU_BTN_STYLE); + BTN_TAG(4) BTN_ENABLED(1) BTN( BTN_POS(1,3), BTN_SIZE(1,1), F("Disable Steppers"), MENU_BTN_STYLE); + BTN_TAG(6) BTN_ENABLED(0) BTN( BTN_POS(1,4), BTN_SIZE(2,1), F("Change Filament"), MENU_BTN_STYLE); + + BTN_TAG(5) BTN_ENABLED(1) BTN( BTN_POS(2,1), BTN_SIZE(1,1), F("Temperature"), MENU_BTN_STYLE); + BTN_TAG(7) BTN_ENABLED(1) BTN( BTN_POS(2,2), BTN_SIZE(1,1), F("Advanced Settings"), MENU_BTN_STYLE); + BTN_TAG(8) BTN_ENABLED(1) BTN( BTN_POS(2,3), BTN_SIZE(1,1), F("About Firmware"), MENU_BTN_STYLE); #endif #define MARGIN_T 15 #if defined(LCD_PORTRAIT) - BTN_TAG(1) THEME(navi_btn) BTN( BTN_POS(1,7), BTN_SIZE(2,1), F("Back"), MENU_BTN_STYLE); + BTN_TAG(1) THEME(back_btn) BTN( BTN_POS(1,7), BTN_SIZE(2,1), F("Back"), MENU_BTN_STYLE); #else - BTN_TAG(1) THEME(navi_btn) BTN( BTN_POS(1,4), BTN_SIZE(2,1), F("Back"), MENU_BTN_STYLE); + BTN_TAG(1) THEME(back_btn) BTN( BTN_POS(2,4), BTN_SIZE(1,1), F("Back"), MENU_BTN_STYLE); #endif #define MARGIN_T 5 @@ -955,9 +1097,8 @@ bool MenuScreen::onTouchStart(uint8_t tag) { case 3: GOTO_SCREEN(MoveAxisScreen); break; case 4: EXEC_GCODE(F("M84")); break; case 5: GOTO_SCREEN(TemperatureScreen); break; - case 6: GOTO_SCREEN(AdvancedSettingsScreen); break; - case 7: GOTO_SCREEN(AboutScreen); break; - case 8: GOTO_SCREEN(CalibrationScreen); break; + case 7: GOTO_SCREEN(AdvancedSettingsScreen); break; + case 8: GOTO_SCREEN(AboutScreen); break; default: return false; } @@ -967,7 +1108,7 @@ bool MenuScreen::onTouchStart(uint8_t tag) { /******************************* CONFIGURATION SCREEN ****************************/ #if defined(LCD_PORTRAIT) - #define GRID_ROWS 6 + #define GRID_ROWS 7 #define GRID_COLS 2 #else #define GRID_ROWS 4 @@ -982,30 +1123,31 @@ void AdvancedSettingsScreen::onRefresh() { if(dlcache.hasData()) { dlcache.append(); } else { - cmd.Cmd_Clear_Color(Theme::background); + cmd.Cmd_Set_Clear_Color(Theme::background); cmd.Cmd_Clear(1,1,1); #if defined(LCD_PORTRAIT) - BTN_TAG(3) THEME(menu_btn) BTN( BTN_POS(1,1), BTN_SIZE(1,2), F("Z Offset "), MENU_BTN_STYLE); - BTN_TAG(4) THEME(menu_btn) BTN( BTN_POS(1,3), BTN_SIZE(1,2), F("Steps/mm"), MENU_BTN_STYLE); - - BTN_TAG(5) THEME(disabled) BTN( BTN_POS(2,1), BTN_SIZE(1,1), F("Velocity "), MENU_BTN_STYLE); - BTN_TAG(6) THEME(disabled) BTN( BTN_POS(2,2), BTN_SIZE(1,1), F("Acceleration"), MENU_BTN_STYLE); - BTN_TAG(7) THEME(disabled) BTN( BTN_POS(2,3), BTN_SIZE(1,1), F("Jerk"), MENU_BTN_STYLE); - BTN_TAG(8) THEME(menu_btn) BTN( BTN_POS(1,5), BTN_SIZE(2,1), F("Restore Failsafe"), MENU_BTN_STYLE); - BTN_TAG(1) THEME(navi_btn) BTN( BTN_POS(1,6), BTN_SIZE(1,1), F("Save"), MENU_BTN_STYLE); - BTN_TAG(2) THEME(navi_btn) BTN( BTN_POS(2,6), BTN_SIZE(1,1), F("Back"), MENU_BTN_STYLE); + BTN_TAG(4) BTN_ENABLED(1) BTN( BTN_POS(1,1), BTN_SIZE(1,2), F("Z Offset "), MENU_BTN_STYLE); + BTN_TAG(5) BTN_ENABLED(1) BTN( BTN_POS(1,3), BTN_SIZE(1,1), F("Steps/mm"), MENU_BTN_STYLE); + + BTN_TAG(6) BTN_ENABLED(0) BTN( BTN_POS(2,1), BTN_SIZE(1,1), F("Velocity "), MENU_BTN_STYLE); + BTN_TAG(7) BTN_ENABLED(0) BTN( BTN_POS(2,2), BTN_SIZE(1,1), F("Acceleration"), MENU_BTN_STYLE); + BTN_TAG(8) BTN_ENABLED(0) BTN( BTN_POS(2,3), BTN_SIZE(1,1), F("Jerk"), MENU_BTN_STYLE); + BTN_TAG(9) BTN_ENABLED(1) BTN( BTN_POS(1,4), BTN_SIZE(2,1), F("Recalibrate Screen"), MENU_BTN_STYLE); + BTN_TAG(10) BTN_ENABLED(1) BTN( BTN_POS(1,5), BTN_SIZE(2,1), F("Restore Factory Settings"), MENU_BTN_STYLE); + BTN_TAG(2) BTN_ENABLED(1) BTN( BTN_POS(1,6), BTN_SIZE(2,1), F("Save As Default"), MENU_BTN_STYLE); + BTN_TAG(1) THEME(back_btn) BTN( BTN_POS(1,7), BTN_SIZE(2,1), F("Back"), MENU_BTN_STYLE); #else - BTN_TAG(3) THEME(menu_btn) BTN( BTN_POS(1,1), BTN_SIZE(1,1), F("Z Offset "), MENU_BTN_STYLE); - BTN_TAG(4) THEME(menu_btn) BTN( BTN_POS(1,2), BTN_SIZE(1,1), F("Steps/mm"), MENU_BTN_STYLE); + BTN_TAG(3) BTN_ENABLED(1) BTN( BTN_POS(1,1), BTN_SIZE(1,1), F("Z Offset "), MENU_BTN_STYLE); + BTN_TAG(4) BTN_ENABLED(1) BTN( BTN_POS(1,2), BTN_SIZE(1,1), F("Steps/mm"), MENU_BTN_STYLE); - BTN_TAG(5) THEME(disabled) BTN( BTN_POS(2,1), BTN_SIZE(1,1), F("Velocity "), MENU_BTN_STYLE); - BTN_TAG(6) THEME(disabled) BTN( BTN_POS(2,2), BTN_SIZE(1,1), F("Acceleration"), MENU_BTN_STYLE); - BTN_TAG(7) THEME(disabled) BTN( BTN_POS(2,3), BTN_SIZE(1,1), F("Jerk"), MENU_BTN_STYLE); - BTN_TAG(8) THEME(menu_btn) BTN( BTN_POS(1,3), BTN_SIZE(1,1), F("Restore Failsafe"), MENU_BTN_STYLE); + BTN_TAG(5) BTN_ENABLED(0) BTN( BTN_POS(2,1), BTN_SIZE(1,1), F("Velocity "), MENU_BTN_STYLE); + BTN_TAG(6) BTN_ENABLED(0) BTN( BTN_POS(2,2), BTN_SIZE(1,1), F("Acceleration"), MENU_BTN_STYLE); + BTN_TAG(7) BTN_ENABLED(0) BTN( BTN_POS(2,3), BTN_SIZE(1,1), F("Jerk"), MENU_BTN_STYLE); + BTN_TAG(8) BTN_ENABLED(1) BTN( BTN_POS(1,3), BTN_SIZE(1,1), F("Restore Failsafe"), MENU_BTN_STYLE); - BTN_TAG(1) THEME(navi_btn) BTN( BTN_POS(1,4), BTN_SIZE(1,1), F("Save"), MENU_BTN_STYLE); - BTN_TAG(2) THEME(navi_btn) BTN( BTN_POS(2,4), BTN_SIZE(1,1), F("Back"), MENU_BTN_STYLE); + BTN_TAG(2) BTN_ENABLED(1) BTN( BTN_POS(1,4), BTN_SIZE(1,1), F("Save"), MENU_BTN_STYLE); + BTN_TAG(1) THEME(back_btn) BTN( BTN_POS(2,4), BTN_SIZE(1,1), F("Back"), MENU_BTN_STYLE); #endif dlcache.store(); @@ -1019,10 +1161,15 @@ void AdvancedSettingsScreen::onRefresh() { bool AdvancedSettingsScreen::onTouchStart(uint8_t tag) { switch(tag) { case 1: GOTO_PREVIOUS(); break; - case 2: GOTO_PREVIOUS(); break; - case 3: GOTO_SCREEN(ZOffsetScreen); break; - case 4: GOTO_SCREEN(StepsScreen); break; - case 8: GOTO_SCREEN(RestoreFailsafeScreen); break; + case 2: + current_screen.pop(); + EXEC_GCODE(F("M500")); + AlertBoxScreen::show(F("Settings saved!")); + break; + case 4: GOTO_SCREEN(ZOffsetScreen); break; + case 5: GOTO_SCREEN(StepsScreen); break; + case 9: GOTO_SCREEN(CalibrationScreen); break; + case 10: GOTO_SCREEN(RestoreFailsafeScreen); break; default: return false; } @@ -1034,10 +1181,33 @@ bool AdvancedSettingsScreen::onTouchStart(uint8_t tag) { #define GRID_COLS 4 #define GRID_ROWS 16 +void CalibrationScreen::onEntry() { + // Clear the display + CLCD::CommandFifo cmd; + cmd.Cmd(CMD_DLSTART); + cmd.Cmd_Set_Clear_Color(Theme::background); + cmd.Cmd_Clear(1,1,1); + cmd.Cmd(DL_DISPLAY); + cmd.Cmd(CMD_SWAP); + cmd.Cmd_Execute(); + + // Wait for the touch to release before starting, + // as otherwise the first calibration point could + // be misinterpreted. + while(CLCD::Is_Touching()) { + #if defined(UI_FRAMEWORK_DEBUG) + #if defined (SERIAL_PROTOCOLLNPGM) + SERIAL_PROTOCOLLNPGM("Waiting for touch release"); + #endif + #endif + } + UIScreen::onEntry(); +} + void CalibrationScreen::onRefresh() { CLCD::CommandFifo cmd; cmd.Cmd(CMD_DLSTART); - cmd.Cmd_Clear_Color(Theme::background); + cmd.Cmd_Set_Clear_Color(Theme::background); cmd.Cmd_Clear(1,1,1); #if defined(LCD_PORTRAIT) @@ -1059,8 +1229,20 @@ void CalibrationScreen::onRefresh() { void CalibrationScreen::onIdle() { if(CLCD::CommandFifo::Cmd_Is_Idle()) { + #if defined(UI_FRAMEWORK_DEBUG) + #if defined (SERIAL_PROTOCOLLNPGM) + SERIAL_PROTOCOLLNPGM("Calibration finished"); + #endif + #endif GOTO_SCREEN(StatusScreen); } + #if defined(UI_FRAMEWORK_DEBUG) + else { + #if defined (SERIAL_PROTOCOLLNPGM) + SERIAL_PROTOCOLLNPGM("Waiting for calibration to finish."); + #endif + } + #endif } /***************************** CALIBRATION REGISTERS SCREEN ****************************/ @@ -1080,7 +1262,7 @@ void CalibrationRegistersScreen::onRefresh() { CLCD::CommandFifo cmd; cmd.Cmd(CMD_DLSTART); - cmd.Cmd_Clear_Color(Theme::background); + cmd.Cmd_Set_Clear_Color(Theme::background); cmd.Cmd_Clear(1,1,1); BTN_TAG(0) @@ -1107,11 +1289,13 @@ void CalibrationRegistersScreen::onRefresh() { #define GRID_COLS 3 - BTN_TAG(1) THEME(navi_btn) BTN( BTN_POS(3,7), BTN_SIZE(1,1), F("Back"), MENU_BTN_STYLE); + BTN_TAG(1) THEME(back_btn) BTN( BTN_POS(3,7), BTN_SIZE(1,1), F("Back"), MENU_BTN_STYLE); cmd.Cmd(DL_DISPLAY); cmd.Cmd(CMD_SWAP); cmd.Cmd_Execute(); + + sound.play(js_bach_joy); } bool CalibrationRegistersScreen::onTouchStart(uint8_t tag) { @@ -1135,13 +1319,13 @@ bool CalibrationRegistersScreen::onTouchStart(uint8_t tag) { void ValueAdjusters::stacker_t::static_parts() { CLCD::CommandFifo cmd; - cmd.Cmd_Clear_Color(Theme::adjust_bg); + cmd.Cmd_Set_Clear_Color(Theme::background); cmd.Cmd_Clear(1,1,1); #if defined(LCD_PORTRAIT) - BTN_TAG(1) THEME(navi_btn) BTN( BTN_POS(1,10), BTN_SIZE(6,1), F("Back"), MENU_BTN_STYLE); + BTN_TAG(1) THEME(back_btn) BTN( BTN_POS(1,10), BTN_SIZE(6,1), F("Back"), MENU_BTN_STYLE); #else - BTN_TAG(1) THEME(navi_btn) BTN( BTN_POS(8,6), BTN_SIZE(2,1), F("Back"), MENU_BTN_STYLE); + BTN_TAG(1) THEME(back_btn) BTN( BTN_POS(8,6), BTN_SIZE(2,1), F("Back"), MENU_BTN_STYLE); #endif line = 1; @@ -1193,9 +1377,9 @@ void ValueAdjusters::increment_t::static_parts(stacker_t &s) const { CLCD::CommandFifo cmd; #if defined(LCD_PORTRAIT) - BTN_TAG(0) THEME(adjust_bg) BTN( BTN_POS(1, s.line), BTN_SIZE(6,1), F("Increment:"), FONT_MED, OPT_FLAT); + BTN_TAG(0) THEME(background) BTN( BTN_POS(1, s.line), BTN_SIZE(6,1), F("Increment:"), FONT_MED, OPT_FLAT); #else - BTN_TAG(0) THEME(adjust_bg) BTN( BTN_POS(8,1), BTN_SIZE(2,1), F("Increment"), FONT_MED, OPT_FLAT); + BTN_TAG(0) THEME(background) BTN( BTN_POS(8,1), BTN_SIZE(2,1), F("Increment"), FONT_MED, OPT_FLAT); #endif // Draw all the buttons in the off state. @@ -1205,14 +1389,14 @@ void ValueAdjusters::increment_t::static_parts(stacker_t &s) const { draw_increment_btn(s.line+1, 245 - decimals, decimals); s.line += 2; - increment = 243 - decimals; + screen_data.ValueAdjusters.increment = 243 - decimals; } void ValueAdjusters::increment_t::dynamic_parts(stacker_t &s) const { CLCD::CommandFifo cmd; THEME(toggle_on); - draw_increment_btn(s.line+1, increment, decimals); + draw_increment_btn(s.line+1, screen_data.ValueAdjusters.increment, decimals); s.line += 2; } @@ -1220,9 +1404,9 @@ void ValueAdjusters::heading_t::static_parts(stacker_t &s) const { CLCD::CommandFifo cmd; #if defined(LCD_PORTRAIT) - BTN_TAG(0) THEME(adjust_bg) BTN( BTN_POS(1, s.line), BTN_SIZE(6,1), (progmem_str) label, FONT_MED, OPT_FLAT); + BTN_TAG(0) THEME(background) BTN( BTN_POS(1, s.line), BTN_SIZE(6,1), (progmem_str) label, FONT_MED, OPT_FLAT); #else - BTN_TAG(0) THEME(adjust_bg) BTN( BTN_POS(3, s.line), BTN_SIZE(4,1), (progmem_str) label, FONT_MED, OPT_FLAT); + BTN_TAG(0) THEME(background) BTN( BTN_POS(3, s.line), BTN_SIZE(4,1), (progmem_str) label, FONT_MED, OPT_FLAT); #endif s.line++; } @@ -1248,10 +1432,10 @@ void ValueAdjusters::heading_t::dynamic_parts(stacker_t &s) const { void ValueAdjusters::adjuster_t::static_parts(stacker_t &s) const { CLCD::CommandFifo cmd; progmem_str str = (progmem_str) label; - BTN_TAG( 0 ) RGB(color) BTN( BTN_POS(3,s.line), BTN_SIZE(2,1), F(""), FONT_SML, OPT_FLAT); - BTN_TAG( 0 ) THEME(adjust_bg) BTN( BTN_POS(1,s.line), BTN_SIZE(2,1), str, FONT_SML, OPT_FLAT); - BTN_TAG(tag ) THEME(incr_btn) BTN( BTN_POS(5,s.line), BTN_SIZE(1,1), F("-"), FONT_MED, OPT_3D); - BTN_TAG(tag + 1) THEME(incr_btn) BTN( BTN_POS(6,s.line), BTN_SIZE(1,1), F("+"), FONT_MED, OPT_3D); + BTN_TAG( 0 ) RGB(color) BTN( BTN_POS(3,s.line), BTN_SIZE(2,1), F(""), FONT_SML, OPT_FLAT); + BTN_TAG( 0 ) THEME(background) BTN( BTN_POS(1,s.line), BTN_SIZE(2,1), str, FONT_SML, OPT_FLAT); + BTN_TAG(tag ) BTN_ENABLED(1) BTN( BTN_POS(5,s.line), BTN_SIZE(1,1), F("-"), FONT_MED, OPT_3D); + BTN_TAG(tag + 1) BTN_ENABLED(1) BTN( BTN_POS(6,s.line), BTN_SIZE(1,1), F("+"), FONT_MED, OPT_3D); s.line++; } @@ -1268,10 +1452,15 @@ void ValueAdjusters::adjuster_t::dynamic_parts(stacker_t &s, float value) const s.line++; } +void ValueAdjusters::onEntry() { + screen_data.ValueAdjusters.increment = 242; + UIScreen::onEntry(); +} + bool ValueAdjusters::onTouchStart(uint8_t tag) { switch(tag) { - case 1: GOTO_PREVIOUS(); return true; - case 240 ... 245: increment = tag; break; + case 1: GOTO_PREVIOUS(); return true; + case 240 ... 245: screen_data.ValueAdjusters.increment = tag; break; default: return current_screen.onTouchHeld(tag); } current_screen.onRefresh(); @@ -1279,7 +1468,7 @@ bool ValueAdjusters::onTouchStart(uint8_t tag) { } float ValueAdjusters::getIncrement() { - switch(increment) { + switch(screen_data.ValueAdjusters.increment) { case 240: return 0.001; case 241: return 0.01; case 242: return 0.1; @@ -1289,8 +1478,6 @@ float ValueAdjusters::getIncrement() { } } -uint8_t ValueAdjusters::increment = 20; - #define EDGE_R 0 /******************************** MOVE AXIS SCREEN ******************************/ @@ -1540,20 +1727,111 @@ bool ZOffsetScreen::onTouchHeld(uint8_t tag) { /***************************** FILES SCREEN ***************************/ +#if defined(LCD_PORTRAIT) + #define GRID_COLS 6 + #define GRID_ROWS 14 +#else + #define GRID_COLS 3 + #define GRID_ROWS 6 +#endif + +const uint16_t filesPerPage = GRID_ROWS - 4; + +void FilesScreen::onEntry() { + screen_data.FilesScreen.page = 0; + screen_data.FilesScreen.selected = 0xFF; + UIScreen::onEntry(); +} + +const char *FilesScreen::getSelectedShortFilename() { + Marlin_LCD_API::Marlin_LCD_API::Media_Iterator iterator(screen_data.FilesScreen.page * filesPerPage); + + while(iterator.hasMore()) { + if(screen_data.FilesScreen.selected == iterator.value() + 1) { + return iterator.shortFilename(); + } + iterator.next(); + } +} + void FilesScreen::onRefresh() { CLCD::DLCache dlcache(FILES_SCREEN_CACHE); CLCD::CommandFifo cmd; cmd.Cmd(CMD_DLSTART); + cmd.Cmd_Set_Clear_Color(Theme::background); + cmd.Cmd_Clear(1,1,1); + + Marlin_LCD_API::Marlin_LCD_API::Media_Iterator iterator(screen_data.FilesScreen.page * filesPerPage); + + #define MARGIN_T 0 + #define MARGIN_B 0 + + while(iterator.hasMore()) { + const uint16_t tag = iterator.value() + 1; + BTN_TAG(tag) + RGB(screen_data.FilesScreen.selected == tag ? Theme::files_selected : Theme::background) + BTN( BTN_POS(1,tag+2), BTN_SIZE(6,1), F(""), FONT_SML, OPT_FLAT); + BTX( BTN_POS(1,tag+2), BTN_SIZE(6,1), iterator.filename(), FONT_LRG, OPT_CENTERY); + iterator.next(); + } + + #define MARGIN_T 5 + #define MARGIN_B 5 + + const uint16_t pageCount = iterator.count() / filesPerPage + 1; + const bool prevEnabled = screen_data.FilesScreen.page > 0; + const bool nextEnabled = screen_data.FilesScreen.page < (pageCount - 1); + const bool fileSelected = screen_data.FilesScreen.selected != 0xFF; + + char page_str[15]; + sprintf_P(page_str, PSTR("Page %d of %d"), screen_data.FilesScreen.page + 1, pageCount); + + #if defined(LCD_PORTRAIT) + BTN_TAG(0) + BTX( BTN_POS(1,1), BTN_SIZE(6,1), page_str, FONT_LRG, OPT_CENTER); + + if(prevEnabled) {BTN_TAG(241); BTN( BTN_POS(1,1), BTN_SIZE(1,2), F("<"), MENU_BTN_STYLE);} + if(nextEnabled) {BTN_TAG(242); BTN( BTN_POS(6,1), BTN_SIZE(1,2), F(">"), MENU_BTN_STYLE);} + + #define MARGIN_T 15 + + BTN_TAG(240) THEME(back_btn) + BTN( BTN_POS(5,13), BTN_SIZE(2,2), F("Back"), MENU_BTN_STYLE); + + BTN_ENABLED(fileSelected) + BTN_TAG(243); BTN( BTN_POS(1,13), BTN_SIZE(4,2), F("Print"), MENU_BTN_STYLE); + #else + BTN_TAG(240) THEME(back_btn) BTN( BTN_POS(1,4), BTN_SIZE(1,1), F("Back"), MENU_BTN_STYLE); + #endif + + #define MARGIN_T 5 + cmd.Cmd(DL_DISPLAY); cmd.Cmd(CMD_SWAP); cmd.Cmd_Execute(); } -bool FilesScreen::onTouchHeld(uint8_t tag) { +bool FilesScreen::onTouchStart(uint8_t tag) { switch(tag) { + case 240: GOTO_PREVIOUS(); return true; + case 241: screen_data.FilesScreen.page--; break; + case 242: screen_data.FilesScreen.page++; break; + case 243: + Marlin_LCD_API::printFromSDCard(getSelectedShortFilename()); + sound.play(start_print); + lcd_setstatusPGM(PSTR("Print Starting"), 0); + GOTO_SCREEN(StatusScreen); + return true; default: - return false; + if(tag < 240) { + if(screen_data.FilesScreen.selected != tag) { + screen_data.FilesScreen.selected = tag; + } else { + // Double clicked. + } + } + break; } onRefresh(); return true; @@ -1566,6 +1844,7 @@ void lcd_setstatusPGM(const char * const message, int8_t level = 0); void lcd_init() { CLCD::Init(); CLCD::DLCache::init(); + Marlin_LCD_API::initMedia(); lcd_setstatusPGM(PSTR(WELCOME_MSG)); @@ -1573,21 +1852,25 @@ void lcd_init() { } void lcd_update() { - const uint8_t NONE = 0xFF; - const uint8_t IGNORE = 0xFE; - static uint8_t pressed = NONE; - static uint8_t last_repeat = 0; - static uint8_t last_update = 0; + enum { + UNPRESSED = 0xFF, //255 + IGNORE_UNPRESS = 0xFE, //254 + DEBOUNCING = 0xFD //253 + }; + static uint8_t pressed_state = UNPRESSED; - const uint8_t tiny_millis = tiny_interval(millis()); + static tiny_interval_t touch_timer; + static tiny_interval_t refresh_timer; sound.onIdle(); - if(tiny_millis - last_update > tiny_interval(DISPLAY_UPDATE_INTERVAL)) { + if(refresh_timer.elapsed()) { + refresh_timer.wait_for(DISPLAY_UPDATE_INTERVAL); current_screen.onIdle(); - last_update = tiny_millis; } + Marlin_LCD_API::checkMedia(); + // If the LCD is processing commands, don't check // for tags since they may be changing and could // cause spurious events. @@ -1595,72 +1878,93 @@ void lcd_update() { return; } - CLCD::Test_Pulse(); - const uint8_t tag = CLCD::Get_Tag(); - if(tag == 0) { - // When the user lifts their finger, activate the onTouchEnd handler, - // except when pressed is IGNORE. - if(pressed == IGNORE) { - pressed = NONE; - sound.play(Theme::unpress_sound); - } - else if(pressed != NONE) { - sound.play(Theme::unpress_sound); - - current_screen.onTouchEnd(pressed); - pressed = NONE; - #if defined(UI_FRAMEWORK_DEBUG) - #if defined (SERIAL_PROTOCOLLNPAIR) - SERIAL_PROTOCOLLNPAIR("Touch end: ", tag); - #else - Serial.print(F("Touch end: ")); - Serial.println(tag); + switch(pressed_state) { + case UNPRESSED: + if(tag != 0) { + #if defined(UI_FRAMEWORK_DEBUG) + #if defined (SERIAL_PROTOCOLLNPAIR) + SERIAL_PROTOCOLLNPAIR("Touch start: ", tag); + #else + Serial.print(F("Touch start: ")); + Serial.println(tag); + #endif #endif - #endif - } - } - else if(pressed == NONE) { - // When the user taps on a button, activate the onTouchStart handler - const uint8_t lastScreen = current_screen.getScreen(); - - if(current_screen.onTouchStart(tag)) { - last_repeat = tiny_millis; - sound.play(Theme::press_sound); - #if defined(UI_FRAMEWORK_DEBUG) - #if defined (SERIAL_PROTOCOLLNPAIR) - SERIAL_PROTOCOLLNPAIR("Touch start: ", tag); - #else - Serial.print(F("Touch start: ")); - Serial.println(tag); + // When the user taps on a button, activate the onTouchStart handler + const uint8_t lastScreen = current_screen.getScreen(); + + if(current_screen.onTouchStart(tag)) { + touch_timer.wait_for(1000 / TOUCH_REPEATS_PER_SECOND); + sound.play(Theme::press_sound); + } + + if(lastScreen != current_screen.getScreen()) { + // In the case in which a touch event triggered a new screen to be + // drawn, we don't issue a touchEnd since it would be sent to the + // wrong screen. + pressed_state = IGNORE_UNPRESS; + #if defined(UI_FRAMEWORK_DEBUG) + #if defined (SERIAL_PROTOCOLLNPAIR) + SERIAL_PROTOCOLLNPAIR("Ignoring press", tag); + #else + Serial.print(F("Ignoring press")); + Serial.println(tag); + #endif + #endif + } else { + pressed_state = tag; + } + } + break; + case DEBOUNCING: + if(tag == 0) { + if(touch_timer.elapsed()) { + pressed_state = UNPRESSED; + sound.play(Theme::unpress_sound); + } + } else { + pressed_state = IGNORE_UNPRESS; + } + break; + case IGNORE_UNPRESS: + if(tag == 0) { + // Ignore subsequent presses for a while to avoid bouncing + touch_timer.wait_for(DEBOUNCE_PERIOD); + pressed_state = DEBOUNCING; + } + break; + default: // PRESSED + if(tag == pressed_state) { + // The user is holding down a button. + if(touch_timer.elapsed() && current_screen.onTouchHeld(tag)) { + sound.play(Theme::repeat_sound); + touch_timer.wait_for(1000 / TOUCH_REPEATS_PER_SECOND); + } + } + else if(tag == 0) { + #if defined(UI_FRAMEWORK_DEBUG) + #if defined (SERIAL_PROTOCOLLNPAIR) + SERIAL_PROTOCOLLNPAIR("Touch end: ", pressed_state); + #else + Serial.print(F("Touch end: ")); + Serial.println(pressed_state); + #endif #endif - #endif - } - if(lastScreen != current_screen.getScreen()) { - // In the case in which a touch event triggered a new screen to be - // drawn, we don't issue a touchEnd since it would be sent to the - // wrong screen. - pressed = IGNORE; - } else { - pressed = tag; - } - } else if(tag == pressed) { - // The user is holding down a button. - if((tiny_millis - last_repeat) > tiny_interval(1000 / TOUCH_REPEATS_PER_SECOND)) { - if(current_screen.onTouchHeld(tag)) { - sound.play(Theme::repeat_sound); - last_repeat = tiny_millis; + current_screen.onTouchEnd(pressed_state); + // Ignore subsequent presses for a while to avoid bouncing + touch_timer.wait_for(DEBOUNCE_PERIOD); + pressed_state = DEBOUNCING; } - } + break; } } inline bool lcd_hasstatus() { return true; } -void lcd_setstatus(const char * const message, const bool persist = false) { +void lcd_setstatus(const char * const message, const bool persist /* = false */) { StatusScreen::setStatusMessage(message); } @@ -1686,9 +1990,18 @@ void lcd_setalertstatusPGM(const char * const message) { void lcd_buttons_update() {} inline void lcd_reset_alert_level() {} -inline bool lcd_detected() { return true; } inline void lcd_refresh() {current_screen.onIdle();} -void kill_screen(const char* lcd_msg) { +void Marlin_LCD_API::onPrinterKilled(const char* lcd_msg) { KillScreen::show(progmem_str(lcd_msg)); } + +void Marlin_LCD_API::onCardInserted() { + lcd_setstatusPGM(PSTR(MSG_SD_INSERTED), 0); + sound.play(card_inserted); +} + +void Marlin_LCD_API::onCardRemoved() { + lcd_setstatusPGM(PSTR(MSG_SD_REMOVED), 0); + sound.play(card_removed); +} diff --git a/Marlin/AO_FT810_UI_Sounds.h b/Marlin/AO_FT810_UI_Sounds.h index 174250365..211e40a28 100644 --- a/Marlin/AO_FT810_UI_Sounds.h +++ b/Marlin/AO_FT810_UI_Sounds.h @@ -38,56 +38,76 @@ */ const PROGMEM CLCD::SoundPlayer::sound_t chimes[] = { - {CHIMES, NOTE_G3, 5}, - {CHIMES, NOTE_E4, 5}, - {CHIMES, NOTE_C4, 5}, - {SILENCE, END_SONG, 0} + {CHIMES, NOTE_G3, 5}, + {CHIMES, NOTE_E4, 5}, + {CHIMES, NOTE_C4, 5}, + {SILENCE, END_SONG, 0} }; const PROGMEM CLCD::SoundPlayer::sound_t sad_trombone[] = { - {TRUMPET, NOTE_A3S, 10}, - {TRUMPET, NOTE_A3 , 10}, - {TRUMPET, NOTE_G3S, 10}, - {TRUMPET, NOTE_G3, 20}, - {SILENCE, END_SONG, 0} + {TRUMPET, NOTE_A3S, 10}, + {TRUMPET, NOTE_A3 , 10}, + {TRUMPET, NOTE_G3S, 10}, + {TRUMPET, NOTE_G3, 20}, + {SILENCE, END_SONG, 0} }; const PROGMEM CLCD::SoundPlayer::sound_t c_maj_arpeggio[] = { - {GLOCKENSPIEL, NOTE_C4, 1}, - {GLOCKENSPIEL, NOTE_E4, 1}, - {GLOCKENSPIEL, NOTE_G4, 16}, - {SILENCE, END_SONG, 0} + {GLOCKENSPIEL, NOTE_C4, 1}, + {GLOCKENSPIEL, NOTE_E4, 1}, + {GLOCKENSPIEL, NOTE_G4, 16}, + {SILENCE, END_SONG, 0} +}; + +const PROGMEM CLCD::SoundPlayer::sound_t start_print[] = { + {TRUMPET, NOTE_A3, 4}, + {TRUMPET, NOTE_A3, 2}, + {TRUMPET, NOTE_A3, 2}, + {TRUMPET, NOTE_E4, 16}, + {SILENCE, END_SONG, 0} +}; + +const PROGMEM CLCD::SoundPlayer::sound_t card_inserted[] = { + {MUSIC_BOX, NOTE_C4, 2}, + {MUSIC_BOX, NOTE_E4, 2}, + {SILENCE, END_SONG, 0} +}; + +const PROGMEM CLCD::SoundPlayer::sound_t card_removed[] = { + {MUSIC_BOX, NOTE_E4, 2}, + {MUSIC_BOX, NOTE_C4, 2}, + {SILENCE, END_SONG, 0} }; const PROGMEM CLCD::SoundPlayer::sound_t js_bach_joy[] = { - {PIANO, NOTE_G3, 10}, - {PIANO, NOTE_A3, 10}, - {PIANO, NOTE_B3, 10}, - {PIANO, NOTE_D4, 10}, - {PIANO, NOTE_C4, 10}, - {PIANO, NOTE_C4, 10}, - {PIANO, NOTE_E4, 10}, - {PIANO, NOTE_D4, 10}, - {PIANO, NOTE_D4, 10}, - {PIANO, NOTE_G4 , 10}, - {PIANO, NOTE_F4S, 10}, - {PIANO, NOTE_G4, 10}, - {PIANO, NOTE_D4, 10}, - {PIANO, NOTE_B3, 10}, - {PIANO, NOTE_G3, 10}, - {PIANO, NOTE_A3, 10}, - {PIANO, NOTE_B3, 10}, - {PIANO, NOTE_C4, 10}, - {PIANO, NOTE_D4, 10}, - {PIANO, NOTE_E4, 10}, - {PIANO, NOTE_D4, 10}, - {PIANO, NOTE_C4, 10}, - {PIANO, NOTE_B3, 10}, - {PIANO, NOTE_A3, 10}, - {PIANO, NOTE_B3, 10}, - {PIANO, NOTE_G3, 10}, - {PIANO, NOTE_G3, 10}, - {SILENCE, END_SONG, 0} + {PIANO, NOTE_G3, 4}, + {PIANO, NOTE_A3, 4}, + {PIANO, NOTE_B3, 4}, + {PIANO, NOTE_D4, 4}, + {PIANO, NOTE_C4, 4}, + {PIANO, NOTE_C4, 4}, + {PIANO, NOTE_E4, 4}, + {PIANO, NOTE_D4, 4}, + {PIANO, NOTE_D4, 4}, + {PIANO, NOTE_G4 , 4}, + {PIANO, NOTE_F4S, 4}, + {PIANO, NOTE_G4, 4}, + {PIANO, NOTE_D4, 4}, + {PIANO, NOTE_B3, 4}, + {PIANO, NOTE_G3, 4}, + {PIANO, NOTE_A3, 4}, + {PIANO, NOTE_B3, 4}, + {PIANO, NOTE_C4, 4}, + {PIANO, NOTE_D4, 4}, + {PIANO, NOTE_E4, 4}, + {PIANO, NOTE_D4, 4}, + {PIANO, NOTE_C4, 4}, + {PIANO, NOTE_B3, 4}, + {PIANO, NOTE_A3, 4}, + {PIANO, NOTE_B3, 4}, + {PIANO, NOTE_G3, 4}, + {PIANO, NOTE_G3, 4}, + {SILENCE, END_SONG, 0} }; const PROGMEM CLCD::SoundPlayer::sound_t all_instruments[] = { diff --git a/Marlin/AO_UI_Framework.h b/Marlin/AO_UI_Framework.h index f559fc922..25478e1e1 100644 --- a/Marlin/AO_UI_Framework.h +++ b/Marlin/AO_UI_Framework.h @@ -73,19 +73,10 @@ class ScreenRef { type = t; } - void setScreen(onEntry_func_t onRefresh_ptr) { + uint8_t lookupScreen(onEntry_func_t onRefresh_ptr) { for(uint8_t type = 0; type < functionTableSize; type++) { if(GET_METHOD(type, onRefresh) == onRefresh_ptr) { - setType(type); - #if defined(UI_FRAMEWORK_DEBUG) - #if defined(SERIAL_PROTOCOLLNPAIR) - SERIAL_PROTOCOLLNPAIR("New screen: ",type); - #else - Serial.print("New screen: "); - Serial.println(type); - #endif - #endif - return; + return type; } } #if defined(UI_FRAMEWORK_DEBUG) @@ -96,6 +87,31 @@ class ScreenRef { Serial.println((uint16_t) onRefresh_ptr, HEX); #endif #endif + return 0xFF; + } + + void setScreen(onEntry_func_t onRefresh_ptr) { + uint8_t type = lookupScreen(onRefresh_ptr); + if(type != 0xFF) { + setType(type); + #if defined(UI_FRAMEWORK_DEBUG) + #if defined(SERIAL_PROTOCOLLNPAIR) + SERIAL_PROTOCOLLNPAIR("New screen: ",type); + #else + Serial.print("New screen: "); + Serial.println(type); + #endif + #endif + return; + } + #if defined(UI_FRAMEWORK_DEBUG) + #if defined(SERIAL_PROTOCOLLNPAIR) + SERIAL_PROTOCOLLNPAIR("Screen not found: ", (uint16_t) onRefresh_ptr); + #else + Serial.print("Screen not found: "); + Serial.println((uint16_t) onRefresh_ptr, HEX); + #endif + #endif } void onStartup() {GET_METHOD(type, onStartup)();} @@ -138,6 +154,10 @@ class ScreenStack : public ScreenRef { void pop() { setType(stack[0]); + forget(); + } + + void forget() { stack[0] = stack[1]; stack[1] = stack[2]; stack[2] = stack[3]; diff --git a/Marlin/AO_UI_Marlin_LCD_API.h b/Marlin/AO_UI_Marlin_LCD_API.h index 944574c12..5aaa3f41a 100644 --- a/Marlin/AO_UI_Marlin_LCD_API.h +++ b/Marlin/AO_UI_Marlin_LCD_API.h @@ -30,39 +30,71 @@ class Marlin_LCD_API { static const uint8_t extruderCount; static const uint8_t fanCount; - static const float getActualTemp_celsius(const uint8_t extruder); - static const float getTargetTemp_celsius(const uint8_t extruder); - static const float getFan_percent(const uint8_t fan); + static float getActualTemp_celsius(const uint8_t extruder); + static float getTargetTemp_celsius(const uint8_t extruder); + static float getFan_percent(const uint8_t fan); - static const float getAxisPosition_mm(const axis_t axis); - static const float getAxisSteps_per_mm(const axis_t axis); - static const uint8_t getProgress_percent(); - static const uint32_t getProgress_seconds_elapsed(); - static const uint8_t getFeedRate_percent(); - static const float getZOffset_mm(); - static const bool isAxisPositionKnown(const axis_t axis); - static const bool isMoving(); + static float getAxisPosition_mm(const axis_t axis); + static float getAxisSteps_per_mm(const axis_t axis); + static uint8_t getProgress_percent(); + static uint32_t getProgress_seconds_elapsed(); + static uint8_t getFeedRate_percent(); + static float getZOffset_mm(); + static bool isAxisPositionKnown(const axis_t axis); + static bool isMoving(); - static const progmem_str getFirmwareName(); + static progmem_str getFirmwareName(); - static const void setTargetTemp_celsius(const uint8_t extruder, float temp); - static const void setFan_percent(const uint8_t fan, float percent); - static const void setAxisPosition_mm(const axis_t axis, float position, float _feedrate_mm_s); - static const void setAxisSteps_per_mm(const axis_t axis, float steps_per_mm); - static const void incrementZOffset_mm(const float z_offset); + static void setTargetTemp_celsius(const uint8_t extruder, float temp); + static void setFan_percent(const uint8_t fan, float percent); + static void setAxisPosition_mm(const axis_t axis, float position, float _feedrate_mm_s); + static void setAxisSteps_per_mm(const axis_t axis, float steps_per_mm); + static void incrementZOffset_mm(const float z_offset); - static const void runGCode(progmem_str gcode); + static void runGCode(progmem_str gcode); static float clamp(float value, float minimum, float maximum) {return max(min(value,maximum),minimum);}; - static void showKillScreen(const char* lcd_msg); + static void initMedia(); + static void checkMedia(); + static bool isPrintingFromMedia(); + static bool isMediaInserted(); + static void stopPrint(); + static void pausePrint(); + static void resumePrint(); + + static void onCardInserted(); + static void onCardRemoved(); + static void onPrinterKilled(const char* lcd_msg); + + static uint16_t getMediaFileCount(); + + static void printFromSDCard(const char *filename); + + class Media_Iterator; +}; + +class Marlin_LCD_API::Media_Iterator { + private: + uint16_t index; + uint16_t num_files; + public: + Media_Iterator(uint16_t start_index = 0); + bool hasMore(); + void seek(uint16_t); + void next(); + const char *longFilename(); + const char *shortFilename(); + const char *filename(); + uint16_t value() {return index;} + uint16_t count() {return num_files;} }; #if defined(MSG_MARLIN) const uint8_t Marlin_LCD_API::extruderCount = EXTRUDERS; const uint8_t Marlin_LCD_API::fanCount = 1; -const float Marlin_LCD_API::getActualTemp_celsius(const uint8_t extruder) { +float Marlin_LCD_API::getActualTemp_celsius(const uint8_t extruder) { if(extruder) { return thermalManager.degHotend(extruder-1); } else { @@ -70,7 +102,7 @@ const float Marlin_LCD_API::getActualTemp_celsius(const uint8_t extruder) { } } -const float Marlin_LCD_API::getTargetTemp_celsius(const uint8_t extruder) { +float Marlin_LCD_API::getTargetTemp_celsius(const uint8_t extruder) { if(extruder) { return thermalManager.degTargetHotend(extruder-1); } else { @@ -78,11 +110,11 @@ const float Marlin_LCD_API::getTargetTemp_celsius(const uint8_t extruder) { } } -const float Marlin_LCD_API::getFan_percent(const uint8_t fan) { +float Marlin_LCD_API::getFan_percent(const uint8_t fan) { return ((float(fanSpeeds[fan]) + 1) * 100) / 256; } -const float Marlin_LCD_API::getAxisPosition_mm(const Marlin_LCD_API::axis_t axis) { +float Marlin_LCD_API::getAxisPosition_mm(const Marlin_LCD_API::axis_t axis) { switch(axis) { case X: return current_position[X_AXIS]; break; case Y: return current_position[Y_AXIS]; break; @@ -92,7 +124,7 @@ const float Marlin_LCD_API::getAxisPosition_mm(const Marlin_LCD_API::axis_t axis } } -const void Marlin_LCD_API::setAxisPosition_mm(const Marlin_LCD_API::axis_t axis, float position, float _feedrate_mm_s) { +void Marlin_LCD_API::setAxisPosition_mm(const Marlin_LCD_API::axis_t axis, float position, float _feedrate_mm_s) { set_destination_from_current(); switch(axis) { case X: destination[X_AXIS] = position; break; @@ -102,17 +134,17 @@ const void Marlin_LCD_API::setAxisPosition_mm(const Marlin_LCD_API::axis_t axis, case E1: destination[E_AXIS+1] = position; break; } - const float old_feedrate = feedrate_mm_s; + float old_feedrate = feedrate_mm_s; feedrate_mm_s = _feedrate_mm_s; prepare_move_to_destination(); feedrate_mm_s = old_feedrate; } -const bool Marlin_LCD_API::isMoving() { +bool Marlin_LCD_API::isMoving() { return planner.blocks_queued(); } -const float Marlin_LCD_API::getAxisSteps_per_mm(const Marlin_LCD_API::axis_t axis) { +float Marlin_LCD_API::getAxisSteps_per_mm(const Marlin_LCD_API::axis_t axis) { switch(axis) { case X: return planner.axis_steps_per_mm[X_AXIS]; case Y: return planner.axis_steps_per_mm[Y_AXIS]; @@ -122,7 +154,7 @@ const float Marlin_LCD_API::getAxisSteps_per_mm(const Marlin_LCD_API::axis_t axi } } -const void Marlin_LCD_API::setAxisSteps_per_mm(const Marlin_LCD_API::axis_t axis, float steps_per_mm) { +void Marlin_LCD_API::setAxisSteps_per_mm(const Marlin_LCD_API::axis_t axis, float steps_per_mm) { switch(axis) { case X: planner.axis_steps_per_mm[X_AXIS] = steps_per_mm; break; case Y: planner.axis_steps_per_mm[Y_AXIS] = steps_per_mm; break; @@ -133,7 +165,7 @@ const void Marlin_LCD_API::setAxisSteps_per_mm(const Marlin_LCD_API::axis_t axis } -const void Marlin_LCD_API::incrementZOffset_mm(float babystep_increment) { +void Marlin_LCD_API::incrementZOffset_mm(float babystep_increment) { const float new_zoffset = zprobe_zoffset + babystep_increment; if (WITHIN(new_zoffset, Z_PROBE_OFFSET_RANGE_MIN, Z_PROBE_OFFSET_RANGE_MAX)) { #if ENABLED(BABYSTEP_ZPROBE_OFFSET) @@ -145,30 +177,30 @@ const void Marlin_LCD_API::incrementZOffset_mm(float babystep_increment) { } } -const uint8_t Marlin_LCD_API::getProgress_percent() { +uint8_t Marlin_LCD_API::getProgress_percent() { #if ENABLED(SDSUPPORT) return card.percentDone(); #endif } -const uint32_t Marlin_LCD_API::getProgress_seconds_elapsed() { +uint32_t Marlin_LCD_API::getProgress_seconds_elapsed() { const duration_t elapsed = print_job_timer.duration(); return elapsed.value; } -const uint8_t Marlin_LCD_API::getFeedRate_percent() { +uint8_t Marlin_LCD_API::getFeedRate_percent() { return feedrate_percentage; } -const float Marlin_LCD_API::getZOffset_mm() { +float Marlin_LCD_API::getZOffset_mm() { return zprobe_zoffset; } -const void Marlin_LCD_API::runGCode(progmem_str gcode) { +void Marlin_LCD_API::runGCode(progmem_str gcode) { enqueue_and_echo_commands_P((const char*)gcode); } -const bool Marlin_LCD_API::isAxisPositionKnown(const axis_t axis) { +bool Marlin_LCD_API::isAxisPositionKnown(const axis_t axis) { switch(axis) { case X: return axis_known_position[X_AXIS]; break; case Y: return axis_known_position[Y_AXIS]; break; @@ -176,11 +208,11 @@ const bool Marlin_LCD_API::isAxisPositionKnown(const axis_t axis) { } } -const Marlin_LCD_API::progmem_str Marlin_LCD_API::getFirmwareName() { +Marlin_LCD_API::progmem_str Marlin_LCD_API::getFirmwareName() { return F("Marlin " SHORT_BUILD_VERSION LULZBOT_FW_VERSION); } -const void Marlin_LCD_API::setTargetTemp_celsius(const uint8_t extruder, float temp) { +void Marlin_LCD_API::setTargetTemp_celsius(const uint8_t extruder, float temp) { if(extruder) { thermalManager.setTargetHotend(clamp(temp,0,500), extruder-1); } else { @@ -188,9 +220,143 @@ const void Marlin_LCD_API::setTargetTemp_celsius(const uint8_t extruder, float t } } -const void Marlin_LCD_API::setFan_percent(const uint8_t fan, float percent) { +void Marlin_LCD_API::setFan_percent(const uint8_t fan, float percent) { if (fan < FAN_COUNT) { fanSpeeds[fan] = clamp(round(percent*256/100-1), 0, 255); } } + +void Marlin_LCD_API::printFromSDCard(const char *filename) { + card.openAndPrintFile(filename); +} + +void lcd_setstatusPGM(const char * const message, int8_t level /* = 0 */); + +uint8_t lcd_sd_status; + +void Marlin_LCD_API::initMedia() { + #if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT) + SET_INPUT_PULLUP(SD_DETECT_PIN); + lcd_sd_status = 2; // UNKNOWN + #endif +} + +void Marlin_LCD_API::checkMedia() { + #if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT) + const bool sd_status = IS_SD_INSERTED; + if (sd_status != lcd_sd_status) { + + SERIAL_PROTOCOLLNPAIR("SD Status: ", sd_status); + + if (sd_status) { + card.initsd(); + if (lcd_sd_status != 2) onCardInserted(); + SERIAL_PROTOCOLLNPAIR("Card: ",1); + } + else { + card.release(); + if (lcd_sd_status != 2) onCardRemoved(); + SERIAL_PROTOCOLLNPAIR("Card: ",0); + } + + lcd_sd_status = sd_status; + } + #endif // SDSUPPORT && SD_DETECT_PIN +} + +bool Marlin_LCD_API::isPrintingFromMedia() { + #if ENABLED(SDSUPPORT) + return card.cardOK && card.isFileOpen() && card.sdprinting; + #else + return false; + #endif +} + +bool Marlin_LCD_API::isMediaInserted() { + #if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT) + return IS_SD_INSERTED; + #else + return false; + #endif +} + +void Marlin_LCD_API::pausePrint() { + #if ENABLED(SDSUPPORT) + card.pauseSDPrint(); + print_job_timer.pause(); + #if ENABLED(PARK_HEAD_ON_PAUSE) + enqueue_and_echo_commands_P(PSTR("M125")); + #endif + lcd_setstatusPGM(PSTR(MSG_PRINT_PAUSED), -1); + #endif +} + +void Marlin_LCD_API::resumePrint() { + #if ENABLED(SDSUPPORT) + #if ENABLED(PARK_HEAD_ON_PAUSE) + enqueue_and_echo_commands_P(PSTR("M24")); + #else + card.startFileprint(); + print_job_timer.start(); + #endif + #endif +} + +void Marlin_LCD_API::stopPrint() { + #if ENABLED(SDSUPPORT) + card.stopSDPrint(); + clear_command_queue(); + quickstop_stepper(); + print_job_timer.stop(); + thermalManager.disable_all_heaters(); + #if FAN_COUNT > 0 + for (uint8_t i = 0; i < FAN_COUNT; i++) fanSpeeds[i] = 0; + #endif + wait_for_heatup = false; + lcd_setstatusPGM(PSTR(MSG_PRINT_ABORTED), -1); + #endif +} + +Marlin_LCD_API::Media_Iterator::Media_Iterator(uint16_t start_index /* = 0*/) { + num_files = card.get_num_Files(); + index = min(start_index, num_files-1); + seek(index); +} + +bool Marlin_LCD_API::Media_Iterator::hasMore() { + return index < (num_files - 1); +} + +void Marlin_LCD_API::Media_Iterator::next() { + if(hasMore()) { + index++; + seek(index); + } +} + +void Marlin_LCD_API::Media_Iterator::seek(uint16_t index) { + const uint16_t nr = + #if ENABLED(SDCARD_RATHERRECENTFIRST) && DISABLED(SDCARD_SORT_ALPHA) + num_files - 1 - + #endif + index; + + #if ENABLED(SDCARD_SORT_ALPHA) + card.getfilename_sorted(nr); + #else + card.getfilename(nr); + #endif +} + +const char *Marlin_LCD_API::Media_Iterator::filename() { + return card.longFilename[0] ? card.longFilename : card.filename; +} + +const char *Marlin_LCD_API::Media_Iterator::shortFilename() { + return card.filename; +} + +const char *Marlin_LCD_API::Media_Iterator::longFilename() { + return card.longFilename; +} #endif \ No newline at end of file diff --git a/Marlin/Conditionals_LulzBot.h b/Marlin/Conditionals_LulzBot.h index 5a8973aeb..84309a9cc 100644 --- a/Marlin/Conditionals_LulzBot.h +++ b/Marlin/Conditionals_LulzBot.h @@ -13,7 +13,7 @@ * got disabled. */ -#define LULZBOT_FW_VERSION ".10" // Change this with each update +#define LULZBOT_FW_VERSION ".11" // Change this with each update #if ( \ !defined(LULZBOT_Gladiola_Mini) && \ @@ -130,7 +130,7 @@ #define LULZBOT_USE_EINSYRAMBO #define LULZBOT_USE_EINSY_RETRO #define LULZBOT_USE_TOUCH_UI - //#define LULZBOT_USE_HIGH_RES + #define LULZBOT_USE_HIGH_RES #define LULZBOT_TWO_PIECE_BED #define LULZBOT_USE_AUTOLEVELING #define LULZBOT_SENSORLESS_HOMING @@ -195,6 +195,7 @@ #define LULZBOT_AUTO_REPORT_TEMPERATURES #define LULZBOT_ADVANCED_OK #define LULZBOT_TX_BUFFER_SIZE 32 +#define LULZBOT_BUFSIZE 10 #define LULZBOT_HOST_KEEPALIVE_FEATURE_DISABLED #define LULZBOT_CLARIFY_ERROR_MESSAGES @@ -1759,7 +1760,9 @@ #endif #define LCD_PORTRAIT #define LCD_UPSIDE_DOWN - //#define UI_FRAMEWORK_DEBUG + #define UI_FRAMEWORK_DEBUG + #define LULZBOT_SDSUPPORT + #define LULZBOT_DISABLE_SD_DETECT_INVERTED #endif /***************************** CUSTOM SPLASH SCREEN *****************************/ diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index ece0f252c..be3220caf 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -518,7 +518,7 @@ // as SD_DETECT_PIN in your board's pins definitions. // This setting should be disabled unless you are using a push button, pulling the pin to ground. // Note: This is always disabled for ULTIPANEL (except ELB_FULL_GRAPHIC_CONTROLLER). - #define SD_DETECT_INVERTED + //#define SD_DETECT_INVERTED LULZBOT_DISABLE_SD_DETECT_INVERTED #define SD_FINISHED_STEPPERRELEASE true // Disable steppers when SD Print is finished #define SD_FINISHED_RELEASECOMMAND "M84 X Y Z E" // You might want to keep the z enabled so your bed stays in place. @@ -792,7 +792,7 @@ // The ASCII buffer for serial input #define MAX_CMD_SIZE 96 -#define BUFSIZE 4 +#define BUFSIZE LULZBOT_BUFSIZE // Transmission to Host Buffer Size // To save 386 bytes of PROGMEM (and TX_BUFFER_SIZE+3 bytes of RAM) set to 0. diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 69aa9f55e..d47396079 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -14379,7 +14379,9 @@ void kill(const char* lcd_msg) { thermalManager.disable_all_heaters(); disable_all_steppers(); - #if ENABLED(ULTRA_LCD) || ENABLED(LULZBOT_USE_TOUCH_UI) + #if ENABLED(LULZBOT_USE_TOUCH_UI) + Marlin_LCD_API::onPrinterKilled(lcd_msg); + #elif ENABLED(ULTRA_LCD) kill_screen(lcd_msg); #else UNUSED(lcd_msg); diff --git a/Marlin/pins_EINSYRAMBO.h b/Marlin/pins_EINSYRAMBO.h index 81c86eaaf..e56d75743 100644 --- a/Marlin/pins_EINSYRAMBO.h +++ b/Marlin/pins_EINSYRAMBO.h @@ -187,11 +187,11 @@ // // LCD / Controller // -#if ENABLED(ULTRA_LCD) +#if ENABLED(ULTRA_LCD) || defined(LULZBOT_USE_TOUCH_UI) #define KILL_PIN 32 - #if ENABLED(NEWPANEL) + #if ENABLED(NEWPANEL) || defined(LULZBOT_USE_TOUCH_UI) // Beeper on AUX-4 #define BEEPER_PIN 84 diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index ed7b101f3..564c71d35 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -187,6 +187,7 @@ #elif defined(LULZBOT_USE_TOUCH_UI) // We will use our own definitions for these functions. + void lcd_setstatus(const char* message, const bool persist=false); #else // no LCD inline void lcd_update() {} inline void lcd_init() {}