diff --git a/Marlin/AO_FT810_Constants.h b/Marlin/AO_FT810_Constants.h
index b0b82c13e..b873da7df 100644
--- a/Marlin/AO_FT810_Constants.h
+++ b/Marlin/AO_FT810_Constants.h
@@ -298,6 +298,20 @@ namespace FTDI {
const uint16_t OPT_NOHANDS = 49152;
}
+// GPIO Bits
+
+namespace FT800 {
+ const uint8_t GPIO_GP0 = 1 << 0;
+ const uint8_t GPIO_GP1 = 1 << 1;
+ const uint8_t GPIO_DISP = 1 << 7;
+}
+
+namespace FT810 {
+ const uint16_t GPIOX_GP0 = 1 << 0;
+ const uint16_t GPIOX_GP1 = 1 << 1;
+ const uint16_t GPIOX_DISP = 1 << 15;
+}
+
// GLOBAL LCD REGISTER SET VALUES FOR WQVGA 480x272 DISPLAY
/*
diff --git a/Marlin/AO_FT810_Functions.h b/Marlin/AO_FT810_Functions.h
index cbd051b67..ba69f68e3 100644
--- a/Marlin/AO_FT810_Functions.h
+++ b/Marlin/AO_FT810_Functions.h
@@ -105,13 +105,10 @@
#ifndef _AO_FT810_FUNC_H
#define _AO_FT810_FUNC_H
-#if defined(LCD_IS_FT800)
- #define DL_CACHE_START 0x035000
-#else
- #define DL_CACHE_START 0x0F5000
-#endif
+#define DL_CACHE_START RAM_G_SIZE - 0xFFFF
// Uncomment the following to disable the DL caching mechanism
+// (note, this will keep the LCD status message from working)
//#define DL_CACHE_DISABLED
#if defined(LCD_800x480)
@@ -272,7 +269,7 @@ class CLCD::CommandFifo {
void Cmd (uint32_t cmd32);
void Cmd (void* data, uint16_t len);
- void Cmd_Str (char* data);
+ void Cmd_Str (const char * const data);
void Cmd_Str (progmem_str data);
void Cmd_Clear_Color (uint32_t rgb);
void Cmd_Clear (bool Clr, bool Stl, bool Tag);
@@ -577,7 +574,7 @@ void CLCD::CommandFifo::Cmd_Append (uint32_t ptr, uint32_t size)
* The DLCache can be used like so:
*
* void some_function() {
- * static CLCD::DLCache dlcache;
+ * CLCD::DLCache dlcache(UNIQUE_ID);
*
* if(dlcache.hasData()) {
* dlcache.append();
@@ -585,26 +582,88 @@ void CLCD::CommandFifo::Cmd_Append (uint32_t ptr, uint32_t size)
* // Add stuff to the DL
* dlcache.store();
* }
+ *
+ *
+ * Layout of Cache memory:
+ *
+ * The cache memory begins with a table at
+ * DL_CACHE_START: each table entry contains
+ * an address and size for a cached DL slot.
+ *
+ * Immediately following the table is the
+ * DL_FREE_ADDR, which points to free cache
+ * space; following this is occupied DL space,
+ * and after that free space that is yet to
+ * be used.
+ *
+ * location data sizeof
+ *
+ * DL_CACHE_START slot0_addr 4
+ * slot0_size 4
+ * slot1_addr 4
+ * slot1_size 4
+ * ...
+ * slotN_addr 4
+ * slotN_size 4
+ * DL_FREE_ADDR dl_free_ptr 4
+ * cached data
+ * ...
+ * dl_free_ptr empty space
+ * ...
*/
class CLCD::DLCache {
private:
- static uint16_t dl_free;
- uint16_t dl_addr = 0;
- uint16_t dl_size = 0;
+ uint8_t dl_slot;
+ uint32_t dl_addr;
+ uint16_t dl_size;
+
+ void load_slot();
+ static void save_slot(uint8_t dl_slot, uint32_t dl_addr, uint32_t dl_size);
+
public:
+ static void init();
+
+ DLCache(uint8_t slot) {
+ dl_slot = slot;
+ load_slot();
+ }
+
bool hasData();
- void store();
+ bool store(uint32_t num_bytes = 0);
void append();
};
-uint16_t CLCD::DLCache::dl_free = 0;
+#define DL_CACHE_SLOTS 250
+#define DL_FREE_ADDR DL_CACHE_START + DL_CACHE_SLOTS * 8
+
+// The init function ensures all cache locatios are marked as empty
+
+void CLCD::DLCache::init() {
+ Mem_Write32(DL_FREE_ADDR, DL_FREE_ADDR + 4);
+ for(uint8_t slot = 0; slot < DL_CACHE_SLOTS; slot++) {
+ save_slot(slot, 0, 0);
+ }
+}
bool CLCD::DLCache::hasData() {
+ #if !defined(DL_CACHE_DISABLED)
return dl_size != 0;
+ #else
+ return false;
+ #endif
}
-void CLCD::DLCache::store() {
+/* This caches the current display list in RAMG so
+ * that it can be appended later. The memory is
+ * dynamically allocated following DL_FREE_ADDR.
+ *
+ * If num_bytes is provided, then that many bytes
+ * will be reserved so that the cache may be re-written
+ * later with potentially a bigger DL.
+ */
+
+bool CLCD::DLCache::store(uint32_t num_bytes /* = 0*/) {
#if !defined(DL_CACHE_DISABLED)
CLCD::CommandFifo cmd;
@@ -613,45 +672,79 @@ void CLCD::DLCache::store() {
cmd.Cmd_Wait_Until_Idle();
// Figure out how long the display list is
- dl_size = Mem_Read32(REG_CMD_DL) & 0x1FFF;
- dl_addr = dl_free;
+ uint32_t new_dl_size = Mem_Read32(REG_CMD_DL) & 0x1FFF;
+ uint32_t free_space = 0;
+ uint32_t dl_alloc = 0;
+
+ if(dl_addr == 0) {
+ // If we are allocating new space...
+ dl_addr = Mem_Read32(DL_FREE_ADDR);
+ free_space = RAM_G_SIZE - dl_addr;
+ dl_alloc = num_bytes ? num_bytes : new_dl_size;
+ dl_size = new_dl_size;
+ } else {
+ // Otherwise, we can only store as much space
+ // as was previously allocated.
+ free_space = num_bytes ? num_bytes : dl_size;
+ dl_alloc = 0;
+ dl_size = new_dl_size;
+ }
- if((dl_addr + dl_size) > RAM_G_SIZE) {
+ if(dl_size > free_space) {
// Not enough memory to cache the display list.
- dl_addr = 0;
- dl_size = 0;
#if defined(UI_FRAMEWORK_DEBUG)
#if defined (SERIAL_PROTOCOLLNPAIR)
- SERIAL_PROTOCOLLNPAIR("Not enough space in GRAM to cache display list, free space: ", RAM_G_SIZE - dl_free);
+ SERIAL_PROTOCOLPAIR("Not enough space in GRAM to cache display list, free space: ", free_space);
+ SERIAL_PROTOCOLLNPAIR(" Required: ", dl_size);
#else
Serial.print(F("Not enough space in GRAM to cache display list, free space:"));
- Serial.println(RAM_G_SIZE - dl_free);
+ Serial.print(free_space);
+ Serial.print(F(" Required: "));
+ Serial.println(dl_size);
#endif
#endif
+ return false;
} else {
#if defined(UI_FRAMEWORK_DEBUG)
#if defined (SERIAL_PROTOCOLLNPAIR)
SERIAL_PROTOCOLPAIR("Saving DL to RAMG cache, bytes: ", dl_size);
- SERIAL_PROTOCOLPAIR(" (Free space: ", RAM_G_SIZE - dl_free);
+ SERIAL_PROTOCOLPAIR(" (Free space: ", free_space);
SERIAL_PROTOCOLLNPGM(")");
#else
Serial.print(F("Saving DL to RAMG cache, bytes: "));
Serial.println(dl_size);
Serial.print(F(" (Free space: "));
- Serial.println(RAM_G_SIZE - dl_free);
+ Serial.println(free_space);
Serial.print(F(")"));
#endif
#endif
- cmd.Cmd_Mem_Cpy(DL_CACHE_START + dl_addr, RAM_DL, dl_size);
+ cmd.Cmd_Mem_Cpy(dl_addr, RAM_DL, dl_size);
cmd.Cmd_Execute();
- dl_free += dl_size;
+ save_slot(dl_slot, dl_addr, dl_size);
+ if(dl_alloc > 0) {
+ // If we allocated space dynamically, then adjust dl_free_addr.
+ Mem_Write32(DL_FREE_ADDR, dl_addr + dl_alloc);
+ }
+ return true;
}
#endif
}
+void CLCD::DLCache::save_slot(uint8_t dl_slot, uint32_t dl_addr, uint32_t dl_size) {
+ Mem_Write32(DL_CACHE_START + dl_slot * 8 + 0, dl_addr);
+ Mem_Write32(DL_CACHE_START + dl_slot * 8 + 4, dl_size);
+}
+
+void CLCD::DLCache::load_slot() {
+ dl_addr = Mem_Read32(DL_CACHE_START + dl_slot * 8 + 0);
+ dl_size = Mem_Read32(DL_CACHE_START + dl_slot * 8 + 4);
+}
+
void CLCD::DLCache::append() {
CLCD::CommandFifo cmd;
- cmd.Cmd_Append(DL_CACHE_START + dl_addr, dl_size);
+ #if !defined(DL_CACHE_DISABLED)
+ cmd.Cmd_Append(dl_addr, dl_size);
+ #endif
#if defined(UI_FRAMEWORK_DEBUG)
cmd.Cmd_Execute();
cmd.Cmd_Wait_Until_Idle();
@@ -758,14 +851,15 @@ void CLCD::Init (void) {
Mem_Write8(REG_DLSWAP, 0x02); // Swap on New Frame
/*
- * Turn On the Display
+ * Turn on the Display (set DISP high)
+ * Turn on the Audio Amplifier (set GP0 high; on the AO CLCD board, this is tied to the amplifier control)
*/
#if defined(LCD_IS_FT800)
- Mem_Write8(REG_GPIO_DIR, 0x80); // Turn ON Display Enable
- Mem_Write8(REG_GPIO, 0x80);
+ Mem_Write8(REG_GPIO_DIR, GPIO_DISP | GPIO_GP0);
+ Mem_Write8(REG_GPIO, GPIO_DISP | GPIO_GP0);
#else
- Mem_Write16(REG_GPIOX_DIR, 1 << 15); // Turn ON Display Enable
- Mem_Write16(REG_GPIOX, 1 << 15);
+ Mem_Write16(REG_GPIOX_DIR, GPIOX_DISP | GPIOX_GP0);
+ Mem_Write16(REG_GPIOX, GPIOX_DISP | GPIOX_GP0);
#endif
Enable(); // Turns on Clock by setting PCLK Register to 5
@@ -794,6 +888,8 @@ class CLCD::SoundPlayer {
uint8_t sixteenths; // Duration of note, in sixteeths of a second, or zero to play to completion
};
+ const uint8_t WAIT = 0;
+
private:
const sound_t *sequence;
uint32_t next;
@@ -838,18 +934,23 @@ bool CLCD::SoundPlayer::soundPlaying() {
void CLCD::SoundPlayer::onIdle() {
if(!sequence) return;
- const bool readyForNextNote = next != 0 ? (millis() > next) : !soundPlaying();
+ const bool readyForNextNote = (next == WAIT) ? !soundPlaying() : (millis() > next);
if(readyForNextNote) {
const effect_t fx = effect_t(pgm_read_byte_near(&sequence->effect));
- const note_t nt = note_t(pgm_read_byte_near(&sequence->note));
- const uint16_t ms = uint32_t(pgm_read_byte_near(&sequence->sixteenths)) * 1000 / 16;
+ const note_t nt = note_t(pgm_read_byte_near(&sequence->note));
+ const uint32_t ms = uint32_t(pgm_read_byte_near(&sequence->sixteenths)) * 1000 / 16;
if(ms == 0 && fx == SILENCE && nt == 0) {
sequence = 0;
} else {
- next = ms ? (millis() + ms) : 0;
- play(fx, nt != 0 ? nt : NOTE_C4);
+ #if defined(UI_FRAMEWORK_DEBUG)
+ #if defined (SERIAL_PROTOCOLLNPAIR)
+ SERIAL_PROTOCOLLNPAIR("Scheduling note in ", ms);
+ #endif
+ #endif
+ next = (ms == WAIT) ? 0 : (millis() + ms);
+ play(fx, (nt == 0) ? NOTE_C4 : nt);
sequence++;
}
}
diff --git a/Marlin/AO_FT810_SPI.h b/Marlin/AO_FT810_SPI.h
index 99cf1aff0..f436ac8a5 100644
--- a/Marlin/AO_FT810_SPI.h
+++ b/Marlin/AO_FT810_SPI.h
@@ -398,7 +398,7 @@ void CLCD::CommandFifo::Cmd (void* data, uint16_t len) {
}
-void CLCD::CommandFifo::Cmd_Str (char* data) {
+void CLCD::CommandFifo::Cmd_Str (const char * const data) {
write(data, strlen(data)+1);
}
diff --git a/Marlin/AO_FT810_UI_Screens.h b/Marlin/AO_FT810_UI_Screens.h
index 5c405a8f8..d47c836b5 100644
--- a/Marlin/AO_FT810_UI_Screens.h
+++ b/Marlin/AO_FT810_UI_Screens.h
@@ -16,12 +16,14 @@
* location: . *
****************************************************************************/
-#define STATUS_MESSAGE_BUFFER_LENGTH 32
-char lcd_status_message[STATUS_MESSAGE_BUFFER_LENGTH] = WELCOME_MSG;
+#define DISPLAY_UPDATE_INTERVAL 1000
+#define TOUCH_REPEATS_PER_SECOND 4
+
+// 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 RAMG_STATUS_SCREEN_DL_SIZE 2048
-static float marlin_x_axis = 100;
-static float marlin_y_axis = 50;
-static float marlin_z_axis = 170;
static float marlin_x_steps = 100;
static float marlin_y_steps = 100;
static float marlin_z_steps = 100;
@@ -94,6 +96,8 @@ static float marlin_z_offset = 0.150;
#define MENU_BTN_STYLE Theme::font_medium, OPT_3D
+#define EXEC_GCODE(cmd) Marlin_LCD_API::runGCode(cmd)
+
/************************* MENU SCREEN DECLARATIONS *************************/
class BootScreen : public UIScreen {
@@ -106,14 +110,14 @@ class AboutScreen : public UIScreen {
public:
static void onEntry();
static void onRefresh();
- static void onTouchStart(uint8_t tag);
- static void onIdle();
+ static bool onTouchStart(uint8_t tag);
};
-class KillScreen : public UIScreen {
+class KillScreen {
+ // The KillScreen is behaves differently than the
+ // others, so we do not bother extending UIScreen.
public:
- static void onEntry();
- static void onRefresh();
+ static void show(progmem_str msg);
};
class StatusScreen : public UIScreen {
@@ -122,24 +126,25 @@ class StatusScreen : public UIScreen {
static void static_temperature();
static void static_progress();
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_status_message();
public:
+ static void setStatusMessage(const char * message);
static void onRefresh();
static void onStartup();
static void onEntry();
static void onIdle();
- static void onTouchStart(uint8_t tag);
+ static bool onTouchStart(uint8_t tag);
};
class MenuScreen : public UIScreen {
public:
static void onRefresh();
- static void onTouchStart(uint8_t tag);
+ static bool onTouchStart(uint8_t tag);
};
class CalibrationScreen : public UIScreen {
@@ -151,13 +156,13 @@ class CalibrationScreen : public UIScreen {
class CalibrationRegistersScreen : public UIScreen {
public:
static void onRefresh();
- static void onTouchStart(uint8_t tag);
+ static bool onTouchStart(uint8_t tag);
};
class AdvancedSettingsScreen : public UIScreen {
public:
static void onRefresh();
- static void onTouchStart(uint8_t tag);
+ static bool onTouchStart(uint8_t tag);
};
class ValueAdjusters : public UIScreen {
@@ -199,31 +204,37 @@ class ValueAdjusters : public UIScreen {
static float getIncrement();
public:
- static void onTouchStart(uint8_t tag);
+ static bool onTouchStart(uint8_t tag);
};
class MoveAxisScreen : public ValueAdjusters {
public:
static void onRefresh();
- static void onTouchHeld(uint8_t tag);
+ static bool onTouchHeld(uint8_t tag);
};
class StepsScreen : public ValueAdjusters {
public:
static void onRefresh();
- static void onTouchHeld(uint8_t tag);
+ static bool onTouchHeld(uint8_t tag);
};
class ZOffsetScreen : public ValueAdjusters {
public:
static void onRefresh();
- static void onTouchHeld(uint8_t tag);
+ static bool onTouchHeld(uint8_t tag);
};
class TemperatureScreen : public ValueAdjusters {
public:
static void onRefresh();
- static void onTouchHeld(uint8_t tag);
+ static bool onTouchHeld(uint8_t tag);
+};
+
+class FilesScreen : public UIScreen {
+ public:
+ static void onRefresh();
+ static bool onTouchHeld(uint8_t tag);
};
/******************************* MENU SCREEN TABLE ******************************/
@@ -231,7 +242,6 @@ class TemperatureScreen : public ValueAdjusters {
SCREEN_TABLE {
DECL_SCREEN(BootScreen),
DECL_SCREEN(AboutScreen),
- DECL_SCREEN(KillScreen),
DECL_SCREEN(CalibrationScreen),
DECL_SCREEN(StatusScreen),
DECL_SCREEN(MenuScreen),
@@ -240,11 +250,29 @@ SCREEN_TABLE {
DECL_SCREEN(StepsScreen),
DECL_SCREEN(ZOffsetScreen),
DECL_SCREEN(TemperatureScreen),
- DECL_SCREEN(CalibrationRegistersScreen)
+ DECL_SCREEN(CalibrationRegistersScreen),
+ DECL_SCREEN(FilesScreen),
};
SCREEN_TABLE_POST
+/********************************* DL CACHE SLOTS ******************************/
+
+// In order to reduce SPI traffic, we cache display lists (DL) in RAMG. This
+// is done using the CLCD::DLCache class, which takes a unique ID for each
+// cache location. These IDs are defined here:
+
+enum {
+ STATUS_SCREEN_CACHE,
+ MENU_SCREEN_CACHE,
+ ADVANCED_SETTINGS_SCREEN_CACHE,
+ MOVE_AXIS_SCREEN_CACHE,
+ TEMPERATURE_SCREEN_CACHE,
+ STEPS_SCREEN_CACHE,
+ ZOFFSET_SCREEN_CACHE,
+ FILES_SCREEN_CACHE
+};
+
/************************************ MENU THEME ********************************/
namespace Theme {
@@ -345,37 +373,6 @@ void BootScreen::onIdle() {
CLCD::SoundPlayer sound;
-const PROGMEM CLCD::SoundPlayer::sound_t chimes[] = {
- {CHIMES, NOTE_G3, 13},
- {CHIMES, NOTE_E4, 13},
- {CHIMES, NOTE_C4, 19},
- {SILENCE, END_SONG, 0}
-};
-
-const PROGMEM CLCD::SoundPlayer::sound_t samples[] = {
- {HARP},
- {XYLOPHONE},
- {TUBA},
- {GLOCKENSPIEL},
- {ORGAN},
- {TRUMPET},
- {PIANO},
- {CHIMES},
- {MUSIC_BOX},
- {BELL},
- {CLICK},
- {SWITCH},
- {COWBELL},
- {NOTCH},
- {HIHAT},
- {KICKDRUM},
- {SWITCH},
- {POP},
- {CLACK},
- {CHACK},
- {SILENCE}
-};
-
void AboutScreen::onEntry() {
UIScreen::onEntry();
@@ -405,42 +402,22 @@ void AboutScreen::onRefresh() {
cmd.Cmd_Execute();
}
-void AboutScreen::onTouchStart(uint8_t tag) {
+bool AboutScreen::onTouchStart(uint8_t tag) {
switch(tag) {
- case 1: GOTO_PREVIOUS(); return;
- case 2: GOTO_SCREEN(CalibrationRegistersScreen); return;
+ case 1: GOTO_PREVIOUS(); return true;
+ case 2: GOTO_SCREEN(CalibrationRegistersScreen); return true;
}
}
-void AboutScreen::onIdle() {
- sound.onIdle();
-}
-
/************************************ KILL SCREEN *******************************/
-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}
-};
-
-void KillScreen::onEntry() {
- UIScreen::onEntry();
-
- CLCD::Mem_Write8(REG_VOL_SOUND, 0xFF);
- sound.play(sad_trombone);
+// The kill screen is an oddball that happens after Marlin has killed the events
+// loop. So we only have a show() method rather than onRefresh(). The KillScreen
+// should not be used as a model for other UI screens as it is an exception.
- // Marlin won't call the idle function anymore, so we
- // have to do it to play the sounds.
- while(sound.hasMoreNotes()) {
- sound.onIdle();
- }
-}
-
-void KillScreen::onRefresh() {
+void KillScreen::show(progmem_str message) {
CLCD::CommandFifo cmd;
+
cmd.Cmd(CMD_DLSTART);
cmd.Cmd_Clear_Color(Theme::about_bg);
cmd.Cmd_Clear(1,1,1);
@@ -448,7 +425,7 @@ void KillScreen::onRefresh() {
#define GRID_COLS 4
#define GRID_ROWS 8
- BTX( BTN_POS(1,2), BTN_SIZE(4,1), lcd_status_message, FONT_LRG);
+ BTX( BTN_POS(1,2), BTN_SIZE(4,1), message, FONT_LRG);
BTX( BTN_POS(1,3), BTN_SIZE(4,1), F("PRINTER HALTED"), FONT_LRG);
@@ -457,6 +434,14 @@ void KillScreen::onRefresh() {
cmd.Cmd(DL_DISPLAY);
cmd.Cmd(CMD_SWAP);
cmd.Cmd_Execute();
+
+ sound.play(sad_trombone);
+
+ // Marlin won't call the idle function anymore,
+ // so we have to loop here to play the sounds.
+ while(sound.hasMoreNotes()) {
+ sound.onIdle();
+ }
}
/*********************************** STATUS SCREEN ******************************/
@@ -590,7 +575,7 @@ void StatusScreen::dynamic_temperature() {
sprintf_P(
fan_str,
PSTR("%-3d %%"),
- Marlin_LCD_API::getFan_percent(0)
+ int8_t(Marlin_LCD_API::getFan_percent(0))
);
sprintf_P(
@@ -696,14 +681,39 @@ void StatusScreen::static_interaction_buttons() {
#define GRID_COLS 1
-void StatusScreen::dynamic_status_message() {
+void StatusScreen::static_status_message(const char * const message) {
+ CLCD::CommandFifo cmd;
+
+ #if defined(LCD_PORTRAIT)
+ THEME(status_msg) BTN( BTN_POS(1,4), BTN_SIZE(1,1), message, FONT_LRG, OPT_FLAT);
+ #else
+ THEME(status_msg) BTN( BTN_POS(1,3), BTN_SIZE(1,2), message, FONT_LRG, OPT_FLAT);
+ #endif
+}
+
+void StatusScreen::setStatusMessage(const char * const message) {
+ CLCD::DLCache dlcache(STATUS_SCREEN_CACHE);
+
CLCD::CommandFifo cmd;
+ cmd.Cmd(CMD_DLSTART);
- #if defined(LCD_PORTRAIT)
- THEME(status_msg) BTN( BTN_POS(1,4), BTN_SIZE(1,1), lcd_status_message, FONT_LRG, OPT_FLAT);
- #else
- THEME(status_msg) BTN( BTN_POS(1,3), BTN_SIZE(1,2), lcd_status_message, FONT_LRG, OPT_FLAT);
- #endif
+ cmd.Cmd_Clear_Color(Theme::background);
+ cmd.Cmd_Clear(1,1,1);
+
+ static_temperature();
+ static_progress();
+ static_axis_position();
+ static_interaction_buttons();
+ static_status_message(message);
+
+ if(!dlcache.store(RAMG_STATUS_SCREEN_DL_SIZE)) {
+ #if defined (SERIAL_PROTOCOLLNPAIR)
+ SERIAL_PROTOCOLLNPAIR("Unable to set the status message, not enough DL cache space: ",message);
+ #else
+ Serial.print(F("Unable to set the status message, not enough DL cache space: "));
+ Serial.println(message);
+ #endif
+ }
}
#if defined(LCD_PORTRAIT)
@@ -722,29 +732,21 @@ void StatusScreen::onStartup() {
}
void StatusScreen::onRefresh() {
- static CLCD::DLCache dlcache;
+ CLCD::DLCache dlcache(STATUS_SCREEN_CACHE);
CLCD::CommandFifo cmd;
cmd.Cmd(CMD_DLSTART);
if(dlcache.hasData()) {
dlcache.append();
} else {
- cmd.Cmd_Clear_Color(Theme::background);
- cmd.Cmd_Clear(1,1,1);
-
- static_temperature();
- static_progress();
- static_axis_position();
- static_interaction_buttons();
-
- dlcache.store();
+ // This should not happen, as setStatusMessage will
+ // populate the cache.
}
/* Dynamic content, non-cached data follows */
dynamic_temperature();
dynamic_progress();
- dynamic_status_message();
dynamic_axis_position();
cmd.Cmd(DL_DISPLAY);
@@ -760,12 +762,13 @@ void StatusScreen::onIdle() {
onRefresh();
}
-void StatusScreen::onTouchStart(uint8_t tag) {
+bool StatusScreen::onTouchStart(uint8_t tag) {
switch(tag) {
case 4: GOTO_SCREEN(MenuScreen); break;
case 5: GOTO_SCREEN(TemperatureScreen); break;
- case 6: GOTO_SCREEN(MoveAxisScreen); break;
+ case 6: GOTO_SCREEN(MoveAxisScreen); break;
}
+ return true;
}
/************************************ MENU SCREEN *******************************/
@@ -779,7 +782,7 @@ void StatusScreen::onTouchStart(uint8_t tag) {
#endif
void MenuScreen::onRefresh() {
- static CLCD::DLCache dlcache;
+ CLCD::DLCache dlcache(MENU_SCREEN_CACHE);
CLCD::CommandFifo cmd;
cmd.Cmd(CMD_DLSTART);
@@ -826,15 +829,20 @@ void MenuScreen::onRefresh() {
cmd.Cmd_Execute();
}
-void MenuScreen::onTouchStart(uint8_t tag) {
+bool MenuScreen::onTouchStart(uint8_t tag) {
switch(tag) {
case 1: GOTO_PREVIOUS(); break;
+ case 2: EXEC_GCODE(F("G28")); break;
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;
+ default:
+ return false;
}
+ return true;
}
/******************************* CONFIGURATION SCREEN ****************************/
@@ -848,7 +856,7 @@ void MenuScreen::onTouchStart(uint8_t tag) {
#endif
void AdvancedSettingsScreen::onRefresh() {
- static CLCD::DLCache dlcache;
+ CLCD::DLCache dlcache(ADVANCED_SETTINGS_SCREEN_CACHE);
CLCD::CommandFifo cmd;
cmd.Cmd(CMD_DLSTART);
@@ -889,13 +897,16 @@ void AdvancedSettingsScreen::onRefresh() {
cmd.Cmd_Execute();
}
-void AdvancedSettingsScreen::onTouchStart(uint8_t tag) {
+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;
+ default:
+ return false;
}
+ return true;
}
/******************************** CALIBRATION SCREEN ****************************/
@@ -984,10 +995,13 @@ void CalibrationRegistersScreen::onRefresh() {
cmd.Cmd_Execute();
}
-void CalibrationRegistersScreen::onTouchStart(uint8_t tag) {
+bool CalibrationRegistersScreen::onTouchStart(uint8_t tag) {
switch(tag) {
- case 1: GOTO_PREVIOUS(); return;
+ case 1: GOTO_PREVIOUS(); break;
+ default:
+ return false;
}
+ return true;
}
/*************************** GENERIC VALUE ADJUSTMENT SCREEN ******************************/
@@ -1135,13 +1149,14 @@ void ValueAdjusters::adjuster_t::dynamic_parts(stacker_t &s, float value) const
s.line++;
}
-void ValueAdjusters::onTouchStart(uint8_t tag) {
+bool ValueAdjusters::onTouchStart(uint8_t tag) {
switch(tag) {
- case 1: GOTO_PREVIOUS(); return;
+ case 1: GOTO_PREVIOUS(); return true;
case 240 ... 245: increment = tag; break;
- default: current_screen.onTouchHeld(tag); return;
+ default: return current_screen.onTouchHeld(tag);
}
current_screen.onRefresh();
+ return true;
}
float ValueAdjusters::getIncrement() {
@@ -1162,7 +1177,7 @@ uint8_t ValueAdjusters::increment = 20;
/******************************** MOVE AXIS SCREEN ******************************/
void MoveAxisScreen::onRefresh() {
- static CLCD::DLCache dlcache;
+ CLCD::DLCache dlcache(MOVE_AXIS_SCREEN_CACHE);
CLCD::CommandFifo cmd;
cmd.Cmd(CMD_DLSTART);
@@ -1187,9 +1202,9 @@ void MoveAxisScreen::onRefresh() {
}
s.dynamic_parts();
h.dynamic_parts(s);
- x.dynamic_parts(s,marlin_x_axis);
- y.dynamic_parts(s,marlin_y_axis);
- z.dynamic_parts(s,marlin_z_axis);
+ x.dynamic_parts(s,Marlin_LCD_API::getAxisPosition_mm(Marlin_LCD_API::X));
+ y.dynamic_parts(s,Marlin_LCD_API::getAxisPosition_mm(Marlin_LCD_API::Y));
+ z.dynamic_parts(s,Marlin_LCD_API::getAxisPosition_mm(Marlin_LCD_API::Z));
i.dynamic_parts(s);
cmd.Cmd(DL_DISPLAY);
@@ -1197,22 +1212,34 @@ void MoveAxisScreen::onRefresh() {
cmd.Cmd_Execute();
}
-void MoveAxisScreen::onTouchHeld(uint8_t tag) {
+bool MoveAxisScreen::onTouchHeld(uint8_t tag) {
+ // We don't want to stack up moves, so wait until the
+ // machine is idle before sending another.
+ if(Marlin_LCD_API::isMoving()) {
+ return false;
+ }
+
+ float inc = getIncrement();
+ Marlin_LCD_API::axis_t axis;
+ const float feedrate_mm_s = inc * TOUCH_REPEATS_PER_SECOND;
+
switch(tag) {
- case 2: marlin_x_axis -= getIncrement(); break;
- case 3: marlin_x_axis += getIncrement(); break;
- case 4: marlin_y_axis -= getIncrement(); break;
- case 5: marlin_y_axis += getIncrement(); break;
- case 6: marlin_z_axis -= getIncrement(); break;
- case 7: marlin_z_axis += getIncrement(); break;
+ case 2: axis = Marlin_LCD_API::X; inc *= -1; break;
+ case 3: axis = Marlin_LCD_API::X; inc *= 1; break;
+ case 4: axis = Marlin_LCD_API::Y; inc *= -1; break;
+ case 5: axis = Marlin_LCD_API::Y; inc *= 1; break;
+ case 6: axis = Marlin_LCD_API::Z; inc *= -1; break;
+ case 7: axis = Marlin_LCD_API::Z; inc *= 1; break;
}
+ Marlin_LCD_API::setAxisPosition_mm(axis, Marlin_LCD_API::getAxisPosition_mm(axis) + inc, feedrate_mm_s);
onRefresh();
+ return true;
}
/******************************* TEMPERATURE SCREEN ******************************/
void TemperatureScreen::onRefresh() {
- static CLCD::DLCache dlcache;
+ CLCD::DLCache dlcache(TEMPERATURE_SCREEN_CACHE);
CLCD::CommandFifo cmd;
cmd.Cmd(CMD_DLSTART);
@@ -1252,7 +1279,7 @@ void TemperatureScreen::onRefresh() {
cmd.Cmd_Execute();
}
-void TemperatureScreen::onTouchHeld(uint8_t tag) {
+bool TemperatureScreen::onTouchHeld(uint8_t tag) {
switch(tag) {
case 20: Marlin_LCD_API::setTargetTemp_celsius(0, Marlin_LCD_API::getTargetTemp_celsius(0) - getIncrement()); break;
case 21: Marlin_LCD_API::setTargetTemp_celsius(0, Marlin_LCD_API::getTargetTemp_celsius(0) + getIncrement()); break;
@@ -1262,14 +1289,17 @@ void TemperatureScreen::onTouchHeld(uint8_t tag) {
case 5: Marlin_LCD_API::setTargetTemp_celsius(2, Marlin_LCD_API::getTargetTemp_celsius(2) + getIncrement()); break;
case 10: Marlin_LCD_API::setFan_percent( 0, Marlin_LCD_API::getFan_percent(0) - getIncrement()); break;
case 11: Marlin_LCD_API::setFan_percent( 0, Marlin_LCD_API::getFan_percent(0) + getIncrement()); break;
+ default:
+ return false;
}
onRefresh();
+ return true;
}
/******************************* STEPS SCREEN ******************************/
void StepsScreen::onRefresh() {
- static CLCD::DLCache dlcache;
+ CLCD::DLCache dlcache(STEPS_SCREEN_CACHE);
CLCD::CommandFifo cmd;
cmd.Cmd(CMD_DLSTART);
@@ -1307,7 +1337,7 @@ void StepsScreen::onRefresh() {
cmd.Cmd_Execute();
}
-void StepsScreen::onTouchHeld(uint8_t tag) {
+bool StepsScreen::onTouchHeld(uint8_t tag) {
switch(tag) {
case 2: marlin_x_steps -= getIncrement(); break;
case 3: marlin_x_steps += getIncrement(); break;
@@ -1317,14 +1347,17 @@ void StepsScreen::onTouchHeld(uint8_t tag) {
case 7: marlin_z_steps += getIncrement(); break;
case 8: marlin_e0_steps -= getIncrement(); break;
case 9: marlin_e0_steps += getIncrement(); break;
+ default:
+ return false;
}
onRefresh();
+ return true;
}
/***************************** Z-OFFSET SCREEN ***************************/
void ZOffsetScreen::onRefresh() {
- static CLCD::DLCache dlcache;
+ CLCD::DLCache dlcache(ZOFFSET_SCREEN_CACHE);
CLCD::CommandFifo cmd;
cmd.Cmd(CMD_DLSTART);
@@ -1353,20 +1386,48 @@ void ZOffsetScreen::onRefresh() {
cmd.Cmd_Execute();
}
-void ZOffsetScreen::onTouchHeld(uint8_t tag) {
+bool ZOffsetScreen::onTouchHeld(uint8_t tag) {
switch(tag) {
case 4: marlin_z_offset -= getIncrement(); break;
case 5: marlin_z_offset += getIncrement(); break;
+ default:
+ return false;
}
onRefresh();
+ return true;
+}
+
+/***************************** FILES SCREEN ***************************/
+
+void FilesScreen::onRefresh() {
+ CLCD::DLCache dlcache(FILES_SCREEN_CACHE);
+ CLCD::CommandFifo cmd;
+ cmd.Cmd(CMD_DLSTART);
+
+ cmd.Cmd(DL_DISPLAY);
+ cmd.Cmd(CMD_SWAP);
+ cmd.Cmd_Execute();
+}
+
+bool FilesScreen::onTouchHeld(uint8_t tag) {
+ switch(tag) {
+ default:
+ return false;
+ }
+ onRefresh();
+ return true;
}
/******************************** MAIN EVENT HANDLER *******************************/
-#define DISPLAY_UPDATE_INTERVAL 1000
+void lcd_setstatusPGM(const char * const message, int8_t level = 0);
void lcd_init() {
CLCD::Init();
+ CLCD::DLCache::init();
+
+ lcd_setstatusPGM(PSTR(WELCOME_MSG));
+
current_screen.start();
}
@@ -1377,6 +1438,8 @@ void lcd_update() {
static uint32_t last_repeat = 0;
static uint32_t last_update = 0;
+ sound.onIdle();
+
if(millis() - last_update > DISPLAY_UPDATE_INTERVAL) {
current_screen.onIdle();
last_update = millis();
@@ -1418,19 +1481,20 @@ void lcd_update() {
else if(pressed == NONE) {
// When the user taps on a button, activate the onTouchStart handler
const uint8_t lastScreen = current_screen.getScreen();
- current_screen.onTouchStart(tag);
- last_repeat = millis();
- sound.play(Theme::press_sound);
+ if(current_screen.onTouchStart(tag)) {
+ last_repeat = millis();
+ sound.play(Theme::press_sound);
- #if defined(UI_FRAMEWORK_DEBUG)
- #if defined (SERIAL_PROTOCOLLNPAIR)
- SERIAL_PROTOCOLLNPAIR("Touch start: ", tag);
- #else
- Serial.print("Touch start: ");
- Serial.println(tag);
+ #if defined(UI_FRAMEWORK_DEBUG)
+ #if defined (SERIAL_PROTOCOLLNPAIR)
+ SERIAL_PROTOCOLLNPAIR("Touch start: ", tag);
+ #else
+ Serial.print("Touch start: ");
+ Serial.println(tag);
+ #endif
#endif
- #endif
+ }
if(lastScreen != current_screen.getScreen()) {
// In the case in which a touch event triggered a new screen to be
@@ -1442,10 +1506,11 @@ void lcd_update() {
}
} else if(tag == pressed) {
// The user is holding down a button.
- if((millis() - last_repeat) > 250) {
- current_screen.onTouchHeld(tag);
- sound.play(Theme::repeat_sound);
- last_repeat = millis();
+ if((millis() - last_repeat) > (1000 / TOUCH_REPEATS_PER_SECOND)) {
+ if(current_screen.onTouchHeld(tag)) {
+ sound.play(Theme::repeat_sound);
+ last_repeat = millis();
+ }
}
}
}
@@ -1453,18 +1518,22 @@ void lcd_update() {
inline bool lcd_hasstatus() { return true; }
void lcd_setstatus(const char * const message, const bool persist = false) {
- strncpy(lcd_status_message, message, STATUS_MESSAGE_BUFFER_LENGTH);
+ StatusScreen::setStatusMessage(message);
}
-void lcd_setstatusPGM(const char * const message, int8_t level = 0) {
- strncpy_P(lcd_status_message, message, STATUS_MESSAGE_BUFFER_LENGTH);
+void lcd_setstatusPGM(const char * const message, int8_t level /* = 0 */) {
+ char buff[64];
+ strncpy_P(buff, message, sizeof(buff));
+ StatusScreen::setStatusMessage(buff);
}
void lcd_status_printf_P(const uint8_t level, const char * const fmt, ...) {
+ char buff[64];
va_list args;
va_start(args, fmt);
- vsnprintf_P(lcd_status_message, STATUS_MESSAGE_BUFFER_LENGTH, fmt, args);
+ vsnprintf_P(buff, sizeof(buff), fmt, args);
va_end(args);
+ StatusScreen::setStatusMessage(buff);
}
void lcd_setalertstatusPGM(const char * const message) {
@@ -1478,6 +1547,5 @@ inline bool lcd_detected() { return true; }
inline void lcd_refresh() {current_screen.onIdle();}
void kill_screen(const char* lcd_msg) {
- strncpy_P(lcd_status_message, lcd_msg, STATUS_MESSAGE_BUFFER_LENGTH);
- GOTO_SCREEN(KillScreen);
+ KillScreen::show(progmem_str(lcd_msg));
}
diff --git a/Marlin/AO_FT810_UI_Sounds.h b/Marlin/AO_FT810_UI_Sounds.h
new file mode 100644
index 000000000..5cf333975
--- /dev/null
+++ b/Marlin/AO_FT810_UI_Sounds.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#ifndef _AO_FT810_SNDS_H
+#define _AO_FT810_SNDS_H
+
+/* A sound sequence consists of an array of the following:
+
+ struct sound_t {
+ effect_t effect; // The sound effect number
+ note_t note; // The MIDI note value, or C4 if 0
+ uint8_t sixteenths; // Note duration in 1/16th of a sec;
+ // If 0, play until sample is finished.
+ };
+
+ Constants are defined in "AO_FT810_Constants.h".
+
+ Both note and sixteenths are optional. If omitted, the compiler
+ will fill them in with 0 which will be interpreted by play C4
+ for the duration of the sample.
+
+ The sequence must be terminated by "{SILENCE, END_SONG, WAIT}", i.e
+ all zeros.
+ */
+
+const PROGMEM CLCD::SoundPlayer::sound_t chimes[] = {
+ {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}
+};
+
+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}
+};
+
+const PROGMEM CLCD::SoundPlayer::sound_t all_instruments[] = {
+ {HARP},
+ {XYLOPHONE},
+ {TUBA},
+ {GLOCKENSPIEL},
+ {ORGAN},
+ {TRUMPET},
+ {PIANO},
+ {CHIMES},
+ {MUSIC_BOX},
+ {BELL},
+ {CLICK},
+ {SWITCH},
+ {COWBELL},
+ {NOTCH},
+ {HIHAT},
+ {KICKDRUM},
+ {SWITCH},
+ {POP},
+ {CLACK},
+ {CHACK},
+ {SILENCE, END_SONG, 0}
+};
+
+#endif // _AO_FT810_SNDS_H
\ No newline at end of file
diff --git a/Marlin/AO_UI_Framework.h b/Marlin/AO_UI_Framework.h
index cc4e8844a..f559fc922 100644
--- a/Marlin/AO_UI_Framework.h
+++ b/Marlin/AO_UI_Framework.h
@@ -46,9 +46,9 @@ class ScreenRef {
typedef void onExit_func_t(void);
typedef void onIdle_func_t(void);
typedef void onRefresh_func_t(void);
- typedef void onTouchStart_func_t(uint8_t);
- typedef void onTouchHeld_func_t(uint8_t);
- typedef void onTouchEnd_func_t(uint8_t);
+ typedef bool onTouchStart_func_t(uint8_t);
+ typedef bool onTouchHeld_func_t(uint8_t);
+ typedef bool onTouchEnd_func_t(uint8_t);
private:
typedef struct {
@@ -103,9 +103,9 @@ class ScreenRef {
void onExit() {GET_METHOD(type, onExit)();}
void onIdle() {GET_METHOD(type, onIdle)();}
void onRefresh() {GET_METHOD(type, onRefresh)();}
- void onTouchStart(uint8_t tag) {GET_METHOD(type, onTouchStart)(tag);}
- void onTouchHeld(uint8_t tag) {GET_METHOD(type, onTouchHeld)(tag);}
- void onTouchEnd(uint8_t tag) {GET_METHOD(type, onTouchEnd)(tag);}
+ bool onTouchStart(uint8_t tag) {return GET_METHOD(type, onTouchStart)(tag);}
+ bool onTouchHeld(uint8_t tag) {return GET_METHOD(type, onTouchHeld)(tag);}
+ bool onTouchEnd(uint8_t tag) {return GET_METHOD(type, onTouchEnd)(tag);}
void initializeAll() {
for(uint8_t type = 0; type < functionTableSize; type++) {
@@ -171,9 +171,9 @@ class UIScreen {
static void onEntry() {current_screen.onRefresh();}
static void onExit() {}
static void onIdle() {}
- static void onTouchStart(uint8_t) {}
- static void onTouchHeld(uint8_t) {}
- static void onTouchEnd(uint8_t) {}
+ static bool onTouchStart(uint8_t) {return false;}
+ static bool onTouchHeld(uint8_t) {return false;}
+ static bool onTouchEnd(uint8_t) {return false;}
};
#define GOTO_SCREEN(screen) current_screen.goTo(screen::onRefresh);
diff --git a/Marlin/AO_UI_Marlin_LCD_API.h b/Marlin/AO_UI_Marlin_LCD_API.h
index 128c6cdfa..52e883631 100644
--- a/Marlin/AO_UI_Marlin_LCD_API.h
+++ b/Marlin/AO_UI_Marlin_LCD_API.h
@@ -41,11 +41,15 @@ class Marlin_LCD_API {
static const uint8_t getFeedRate_percent();
static const float getZOffset_mm();
static const bool isAxisPositionKnown(const axis_t axis);
+ static const bool isMoving();
static const 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 Marlin_LCD_API::axis_t axis, float position, float _feedrate_mm_s);
+
+ static const void runGCode(progmem_str gcode);
static float clamp(float value, float minimum, float maximum) {return max(min(value,maximum),minimum);};
@@ -86,6 +90,26 @@ 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) {
+ set_destination_from_current();
+ switch(axis) {
+ case X: destination[X_AXIS] = position; break;
+ case Y: destination[Y_AXIS] = position; break;
+ case Z: destination[Z_AXIS] = position; break;
+ case E0: destination[E_AXIS] = position; break;
+ case E1: destination[E_AXIS+1] = position; break;
+ }
+
+ const 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() {
+ return planner.blocks_queued();
+}
+
const float Marlin_LCD_API::getAxisSteps_per_mm(const Marlin_LCD_API::axis_t axis) {
return 0;
}
@@ -105,6 +129,10 @@ const uint8_t Marlin_LCD_API::getFeedRate_percent() {
return feedrate_percentage;
}
+const 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) {
switch(axis) {
case X: return axis_known_position[X_AXIS]; break;
diff --git a/Marlin/Conditionals_LulzBot.h b/Marlin/Conditionals_LulzBot.h
index 854d1544e..15f31fda2 100644
--- a/Marlin/Conditionals_LulzBot.h
+++ b/Marlin/Conditionals_LulzBot.h
@@ -13,7 +13,7 @@
* got disabled.
*/
-#define LULZBOT_FW_VERSION ".8" // Change this with each update
+#define LULZBOT_FW_VERSION ".9" // Change this with each update
#if ( \
!defined(LULZBOT_Gladiola_Mini) && \
diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp
index 47378a8b6..69aa9f55e 100644
--- a/Marlin/Marlin_main.cpp
+++ b/Marlin/Marlin_main.cpp
@@ -356,6 +356,7 @@
#include "AO_FT810_Pins.h"
#include "AO_FT810_SPI.h"
#include "AO_FT810_UI_Bitmaps.h"
+ #include "AO_FT810_UI_Sounds.h"
#include "AO_FT810_UI_Screens.h"
#endif