diff --git a/Marlin/AO_FT810_Constants.h b/Marlin/AO_FT810_Constants.h index 7b19e7b7f..cb29450e6 100644 --- a/Marlin/AO_FT810_Constants.h +++ b/Marlin/AO_FT810_Constants.h @@ -628,6 +628,69 @@ namespace FTDI { const uint32_t CMD_LOGO = 0xFFFFFF31; } +namespace FTDI { + enum effect_t { + SILENCE = 0x00, + SQUARE_WAVE = 0x01, + SINE_WAVE = 0x02, + SAWTOOTH_WAVE = 0x03, + TRIANGLE_WAVE = 0x04, + BEEPING = 0x05, + ALARM = 0x06, + WARBLE = 0x07, + CAROUSEL = 0x08, + SHORT_PIPS_1 = 0x10, + SHORT_PIPS_2 = 0x11, + SHORT_PIPS_3 = 0x12, + SHORT_PIPS_4 = 0x13, + SHORT_PIPS_5 = 0x14, + SHORT_PIPS_6 = 0x15, + SHORT_PIPS_7 = 0x16, + SHORT_PIPS_8 = 0x17, + SHORT_PIPS_9 = 0x18, + SHORT_PIPS_10 = 0x19, + SHORT_PIPS_11 = 0x1A, + SHORT_PIPS_12 = 0x1B, + SHORT_PIPS_13 = 0x1C, + SHORT_PIPS_14 = 0x1D, + SHORT_PIPS_15 = 0x1E, + SHORT_PIPS_16 = 0x1F, + DTMF_POUND = 0x23, + DTMF_STAR = 0x2C, + DTMF_0 = 0x30, + DTMF_1 = 0x31, + DTMF_2 = 0x32, + DTMF_3 = 0x33, + DTMF_4 = 0x34, + DTMF_5 = 0x35, + DTMF_6 = 0x36, + DTMF_7 = 0x37, + DTMF_8 = 0x38, + DTMF_9 = 0x39, + HARP = 0x40, + XYLOPHONE = 0x41, + TUBA = 0x42, + GLOCKENSPIEL = 0x43, + ORGAN = 0x44, + TRUMPET = 0x45, + PIANO = 0x46, + CHIMES = 0x47, + MUSIC_BOX = 0x48, + BELL = 0x49, + CLICK = 0x50, + SWITCH = 0x51, + COWBELL = 0x52, + NOTCH = 0x53, + HIHAT = 0x54, + KICKDRUM = 0x55, + POP = 0x56, + CLACK = 0x57, + CHACK = 0x58, + MUTE = 0x60, + UNMUTE = 0x61 + }; +} + // If LCD_IS_FT800 is defined, then copy the FT800 namespace into the FTDI namespace // If LCD_IS_FT810 is defined, then copy the FT810 namespace into the FTDI namespace diff --git a/Marlin/AO_FT810_Functions.h b/Marlin/AO_FT810_Functions.h index 9eec2e186..ebd260164 100644 --- a/Marlin/AO_FT810_Functions.h +++ b/Marlin/AO_FT810_Functions.h @@ -160,96 +160,9 @@ class CLCD { const uint16_t height; } bitmap_info_t; - class CommandFifo { - protected: - static uint32_t getRegCmdWrite(); - static uint32_t getRegCmdRead(); - - #if defined(LCD_IS_FT800) - static uint32_t command_write_ptr; - template void _write_unaligned(T data, uint16_t len); - #else - uint32_t getRegCmdBSpace(); - #endif - void Cmd_Start(void); - - public: - template void write(T data, uint16_t len); - - public: - CommandFifo() {Cmd_Start();} - - static void Cmd_Reset (void); - static bool Cmd_Is_Idle(); - static void Cmd_Wait_Until_Idle(); - - void Cmd_Execute(void); - - void Cmd (uint32_t cmd32); - void Cmd (void* data, uint16_t len); - void Cmd_Str (char* data); - void Cmd_Str (progmem_str data); - void Cmd_Clear_Color (uint32_t rgb); - void Cmd_Clear (bool Clr, bool Stl, bool Tag); - void Cmd_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); - void Cmd_Bitmap_Source (uint32_t RAM_G_Addr); - - // The following functions *must* be inlined since we are relying on the compiler to do - // substitution of the constants from the data structure rather than actually storing - // it in PROGMEM (which would fail, since we are not using pgm_read_near to read them). - // Plus, by inlining, all the equations are evaluated at compile-time as everything - // should be a constant. - - FORCEDINLINE void Cmd_Bitmap_Source (const bitmap_info_t& info) {Cmd_Bitmap_Source (info.RAMG_addr);}; - FORCEDINLINE void Cmd_Bitmap_Layout (const bitmap_info_t& info) {Cmd_Bitmap_Layout (info.format, info.linestride, info.height);}; - FORCEDINLINE void Cmd_Bitmap_Size(const bitmap_info_t& info) {Cmd_Bitmap_Size (info.filter, info.wrapx, info.wrapy, info.width, info.height);} - FORCEDINLINE void Cmd_Draw_Button_Icon(int16_t x, int16_t y, int16_t w, int16_t h, const bitmap_info_t& info, const float scale = 1) { - Cmd_Begin(BEGIN_BITMAPS); - if(scale != 1) { - Cmd(BITMAP_TRANSFORM_A | uint32_t(float(256)/scale) & 0xFFFF); - Cmd(BITMAP_TRANSFORM_E | uint32_t(float(256)/scale) & 0xFFFF); - } - Cmd_Bitmap_Size(info.filter, info.wrapx, info.wrapy, info.width*scale, info.height*scale); - Cmd_Vertex_2F((x + w/2 - info.width*scale/2)*16, (y + h/2 - info.height*scale/2)*16); - if(scale != 1) { - Cmd(BITMAP_TRANSFORM_A | 256); - 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); - } - - void Cmd_Bitmap_Layout (uint8_t format, uint16_t linestride, uint16_t height); - void Cmd_Bitmap_Size(uint8_t filter, uint8_t wrapx, uint8_t wrapy, uint16_t width, uint16_t height); - void Cmd_Bitmap_Handle (uint16_t Handle); - void Cmd_Begin (uint32_t Primitive); - void Cmd_Vertex_2F (uint16_t X_Coord, uint16_t Y_Coord); - void Cmd_Vertex_2II (uint16_t X_Coord, uint16_t Y_Coord, uint8_t B_Handle, uint8_t Cell); - - template void Cmd_Draw_Button(int16_t x, int16_t y, int16_t w, int16_t h, T text, int16_t font, uint16_t option); - template void Cmd_Draw_Text(int16_t x, int16_t y, T text, int16_t font, uint16_t options); - - void Cmd_Draw_Clock (int16_t x, int16_t y, int16_t r, uint16_t option, int16_t h, int16_t m, int16_t s, int16_t ms); - void Cmd_Draw_Progress_Bar (int16_t x, int16_t y, int16_t w, int16_t h, int16_t val, int16_t range); - void Cmd_Draw_Slider (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range); - void Cmd_Mem_Cpy (uint32_t dst, uint32_t src, uint32_t size); - void Cmd_Append (uint32_t ptr, uint32_t size); - }; - - class DLCache { - private: - static uint16_t dl_free; - uint16_t dl_addr = 0; - uint16_t dl_size = 0; - public: - bool hasData(); - void store(); - void append(); - }; + class CommandFifo; + class SoundPlayer; + class DLCache; public: static void Init (void); @@ -330,122 +243,87 @@ void CLCD::Flash_Write_RGB332_Bitmap(uint32_t Mem_Address, const unsigned char* } } -uint8_t Device_ID; - -void CLCD::Init (void) { - spiInit(); // Set Up I/O Lines for SPI and FT800/810 Control - delay(50); - - Reset(); // Power Down the FT800/810 for 50 ms - delay(50); - -/* - * If driving the 4D Systems 4DLCD-FT843 Board, the following Init sequence is needed for its FT800 Driver - */ - -#ifdef LCD_IS_FT800 // Use External Crystal and 48 MHz System Clock - Host_Cmd(CLKEXT, 0); - - delay(20); - Host_Cmd(CLK48M, 0); -#else - Host_Cmd(CLKINT, 0); - delay(20); - Host_Cmd(CLKSEL, Clksel); // Use Internal RC Oscillator and 48 MHz System Clock -#endif - - delay(20); +/******************* FT800/810 Graphic Commands *********************************/ - Host_Cmd(ACTIVE, 0); // Activate the System Clock - delay(50); +class CLCD::CommandFifo { + protected: + static uint32_t getRegCmdWrite(); + static uint32_t getRegCmdRead(); - delay(400); - Device_ID = Mem_Read8(REG_ID); // Read Device ID, Should Be 0x7C; - #if defined(UI_FRAMEWORK_DEBUG) - if(Device_ID != 0x7C) { - #if defined (SERIAL_PROTOCOLLNPAIR) - SERIAL_PROTOCOLLNPAIR("Incorrect device ID, should be 7C, got ", Device_ID); + #if defined(LCD_IS_FT800) + static uint32_t command_write_ptr; + template void _write_unaligned(T data, uint16_t len); #else - Serial.print(F("Incorrect device ID, should be 7C, got ")); - Serial.println(Device_ID, HEX); + uint32_t getRegCmdBSpace(); #endif - } else { - #if defined (SERIAL_PROTOCOLLNPGM) - SERIAL_PROTOCOLLNPGM("Device is correct "); - #else - Serial.println(F("Device is correct ")); - #endif - } - #endif - delay(400); - - Mem_Write8(REG_GPIO, 0x00); // Turn OFF Display Enable (GPIO Bit 7); - Mem_Write8(REG_PCLK, 0x00); // Turn OFF LCD PCLK - Set_Backlight(0x00FA, 0); - - /* - * Configure the FT800/810 Registers - */ - - Mem_Write16(REG_HCYCLE, Hcycle); - Mem_Write16(REG_HOFFSET, Hoffset); - Mem_Write16(REG_HSYNC0, Hsync0); - Mem_Write16(REG_HSYNC1, Hsync1); - Mem_Write16(REG_VCYCLE, Vcycle); - Mem_Write16(REG_VOFFSET, Voffset); - Mem_Write16(REG_VSYNC0, Vsync0); - Mem_Write16(REG_VSYNC1, Vsync1); - Mem_Write16(REG_HSIZE, Hsize); - Mem_Write16(REG_VSIZE, Vsize); - Mem_Write8(REG_SWIZZLE, Swizzle); - Mem_Write8(REG_PCLK_POL, Pclkpol); - Mem_Write8(REG_CSPREAD, 1); - - #if defined(LCD_PORTRAIT) && defined(LCD_UPSIDE_DOWN) - Mem_Write8(REG_ROTATE, 3); - #elif defined(LCD_PORTRAIT) && !defined(LCD_UPSIDE_DOWN) - Mem_Write8(REG_ROTATE, 2); - #elif !defined(LCD_PORTRAIT) && defined(LCD_UPSIDE_DOWN) - Mem_Write8(REG_ROTATE, 1); - #else !defined(LCD_PORTRAIT) && !defined(LCD_UPSIDE_DOWN) - Mem_Write8(REG_ROTATE, 0); - #endif - - Mem_Write8(REG_TOUCH_MODE, 0x03); // Configure the Touch Screen - Mem_Write8(REG_TOUCH_ADC_MODE, 0x01); - Mem_Write8(REG_TOUCH_OVERSAMPLE, 0x0F); - Mem_Write16(REG_TOUCH_RZTHRESH, 5000); - Mem_Write8(REG_VOL_SOUND, 0x00); // Turn Synthesizer Volume Off - Mem_Write8(REG_DLSWAP, 0x02); // Swap on New Frame - - /* - * Turn On the Display - */ - #if defined(LCD_IS_FT800) - Mem_Write8(REG_GPIO_DIR, 0x80); // Turn ON Display Enable - Mem_Write8(REG_GPIO, 0x80); - #else - Mem_Write16(REG_GPIOX_DIR, 1 << 15); // Turn ON Display Enable - Mem_Write16(REG_GPIOX, 1 << 15); - #endif - - Enable(); // Turns on Clock by setting PCLK Register to 5 - delay(50); + void Cmd_Start(void); - CommandFifo::Cmd_Reset(); - delay(50); - - // Set Initial Values for Touch Transform Registers - - CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_A, default_transform_a); - CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_B, default_transform_b); - CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_C, default_transform_c); - CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_D, default_transform_d); - CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_E, default_transform_e); - CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_F, default_transform_f); -} + public: + template void write(T data, uint16_t len); -/******************* FT800/810 Graphic Commands *********************************/ + public: + CommandFifo() {Cmd_Start();} + + static void Cmd_Reset (void); + static bool Cmd_Is_Idle(); + static void Cmd_Wait_Until_Idle(); + + void Cmd_Execute(void); + + void Cmd (uint32_t cmd32); + void Cmd (void* data, uint16_t len); + void Cmd_Str (char* data); + void Cmd_Str (progmem_str data); + void Cmd_Clear_Color (uint32_t rgb); + void Cmd_Clear (bool Clr, bool Stl, bool Tag); + void Cmd_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); + void Cmd_Bitmap_Source (uint32_t RAM_G_Addr); + + // The following functions *must* be inlined since we are relying on the compiler to do + // substitution of the constants from the data structure rather than actually storing + // it in PROGMEM (which would fail, since we are not using pgm_read_near to read them). + // Plus, by inlining, all the equations are evaluated at compile-time as everything + // should be a constant. + + FORCEDINLINE void Cmd_Bitmap_Source (const bitmap_info_t& info) {Cmd_Bitmap_Source (info.RAMG_addr);}; + FORCEDINLINE void Cmd_Bitmap_Layout (const bitmap_info_t& info) {Cmd_Bitmap_Layout (info.format, info.linestride, info.height);}; + FORCEDINLINE void Cmd_Bitmap_Size(const bitmap_info_t& info) {Cmd_Bitmap_Size (info.filter, info.wrapx, info.wrapy, info.width, info.height);} + FORCEDINLINE void Cmd_Draw_Button_Icon(int16_t x, int16_t y, int16_t w, int16_t h, const bitmap_info_t& info, const float scale = 1) { + Cmd_Begin(BEGIN_BITMAPS); + if(scale != 1) { + Cmd(BITMAP_TRANSFORM_A | uint32_t(float(256)/scale) & 0xFFFF); + Cmd(BITMAP_TRANSFORM_E | uint32_t(float(256)/scale) & 0xFFFF); + } + Cmd_Bitmap_Size(info.filter, info.wrapx, info.wrapy, info.width*scale, info.height*scale); + Cmd_Vertex_2F((x + w/2 - info.width*scale/2)*16, (y + h/2 - info.height*scale/2)*16); + if(scale != 1) { + Cmd(BITMAP_TRANSFORM_A | 256); + 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); + } + + void Cmd_Bitmap_Layout (uint8_t format, uint16_t linestride, uint16_t height); + void Cmd_Bitmap_Size(uint8_t filter, uint8_t wrapx, uint8_t wrapy, uint16_t width, uint16_t height); + void Cmd_Bitmap_Handle (uint16_t Handle); + void Cmd_Begin (uint32_t Primitive); + void Cmd_Vertex_2F (uint16_t X_Coord, uint16_t Y_Coord); + void Cmd_Vertex_2II (uint16_t X_Coord, uint16_t Y_Coord, uint8_t B_Handle, uint8_t Cell); + + template void Cmd_Draw_Button(int16_t x, int16_t y, int16_t w, int16_t h, T text, int16_t font, uint16_t option); + template void Cmd_Draw_Text(int16_t x, int16_t y, T text, int16_t font, uint16_t options); + + void Cmd_Draw_Clock (int16_t x, int16_t y, int16_t r, uint16_t option, int16_t h, int16_t m, int16_t s, int16_t ms); + void Cmd_Draw_Progress_Bar (int16_t x, int16_t y, int16_t w, int16_t h, int16_t val, int16_t range); + void Cmd_Draw_Slider (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range); + void Cmd_Mem_Cpy (uint32_t dst, uint32_t src, uint32_t size); + void Cmd_Append (uint32_t ptr, uint32_t size); +}; #if defined(LCD_IS_FT800) uint32_t CLCD::CommandFifo::command_write_ptr = 0xFFFFFFFFul; @@ -709,6 +587,17 @@ void CLCD::CommandFifo::Cmd_Append (uint32_t ptr, uint32_t size) * } */ +class CLCD::DLCache { + private: + static uint16_t dl_free; + uint16_t dl_addr = 0; + uint16_t dl_size = 0; + public: + bool hasData(); + void store(); + void append(); +}; + uint16_t CLCD::DLCache::dl_free = 0; bool CLCD::DLCache::hasData() { @@ -780,6 +669,192 @@ void CLCD::DLCache::append() { #endif } +/******************* LCD INITIALIZATION ************************/ + +void CLCD::Init (void) { + spiInit(); // Set Up I/O Lines for SPI and FT800/810 Control + delay(50); + + Reset(); // Power Down the FT800/810 for 50 ms + delay(50); + +/* + * If driving the 4D Systems 4DLCD-FT843 Board, the following Init sequence is needed for its FT800 Driver + */ + +#ifdef LCD_IS_FT800 // Use External Crystal and 48 MHz System Clock + Host_Cmd(CLKEXT, 0); + + delay(20); + Host_Cmd(CLK48M, 0); +#else + Host_Cmd(CLKINT, 0); + delay(20); + Host_Cmd(CLKSEL, Clksel); // Use Internal RC Oscillator and 48 MHz System Clock +#endif + + delay(20); + + Host_Cmd(ACTIVE, 0); // Activate the System Clock + delay(50); + + delay(400); + uint8_t Device_ID = Mem_Read8(REG_ID); // Read Device ID, Should Be 0x7C; + #if defined(UI_FRAMEWORK_DEBUG) + if(Device_ID != 0x7C) { + #if defined (SERIAL_PROTOCOLLNPAIR) + SERIAL_PROTOCOLLNPAIR("Incorrect device ID, should be 7C, got ", Device_ID); + #else + Serial.print(F("Incorrect device ID, should be 7C, got ")); + Serial.println(Device_ID, HEX); + #endif + } else { + #if defined (SERIAL_PROTOCOLLNPGM) + SERIAL_PROTOCOLLNPGM("Device is correct "); + #else + Serial.println(F("Device is correct ")); + #endif + } + #endif + delay(400); + + Mem_Write8(REG_GPIO, 0x00); // Turn OFF Display Enable (GPIO Bit 7); + Mem_Write8(REG_PCLK, 0x00); // Turn OFF LCD PCLK + Set_Backlight(0x00FA, 0); + + /* + * Configure the FT800/810 Registers + */ + + Mem_Write16(REG_HCYCLE, Hcycle); + Mem_Write16(REG_HOFFSET, Hoffset); + Mem_Write16(REG_HSYNC0, Hsync0); + Mem_Write16(REG_HSYNC1, Hsync1); + Mem_Write16(REG_VCYCLE, Vcycle); + Mem_Write16(REG_VOFFSET, Voffset); + Mem_Write16(REG_VSYNC0, Vsync0); + Mem_Write16(REG_VSYNC1, Vsync1); + Mem_Write16(REG_HSIZE, Hsize); + Mem_Write16(REG_VSIZE, Vsize); + Mem_Write8(REG_SWIZZLE, Swizzle); + Mem_Write8(REG_PCLK_POL, Pclkpol); + Mem_Write8(REG_CSPREAD, 1); + + #if defined(LCD_PORTRAIT) && defined(LCD_UPSIDE_DOWN) + Mem_Write8(REG_ROTATE, 3); + #elif defined(LCD_PORTRAIT) && !defined(LCD_UPSIDE_DOWN) + Mem_Write8(REG_ROTATE, 2); + #elif !defined(LCD_PORTRAIT) && defined(LCD_UPSIDE_DOWN) + Mem_Write8(REG_ROTATE, 1); + #else !defined(LCD_PORTRAIT) && !defined(LCD_UPSIDE_DOWN) + Mem_Write8(REG_ROTATE, 0); + #endif + + Mem_Write8(REG_TOUCH_MODE, 0x03); // Configure the Touch Screen + Mem_Write8(REG_TOUCH_ADC_MODE, 0x01); + Mem_Write8(REG_TOUCH_OVERSAMPLE, 0x0F); + Mem_Write16(REG_TOUCH_RZTHRESH, 5000); + Mem_Write8(REG_VOL_SOUND, 0x00); // Turn Synthesizer Volume Off + Mem_Write8(REG_DLSWAP, 0x02); // Swap on New Frame + + /* + * Turn On the Display + */ + #if defined(LCD_IS_FT800) + Mem_Write8(REG_GPIO_DIR, 0x80); // Turn ON Display Enable + Mem_Write8(REG_GPIO, 0x80); + #else + Mem_Write16(REG_GPIOX_DIR, 1 << 15); // Turn ON Display Enable + Mem_Write16(REG_GPIOX, 1 << 15); + #endif + + Enable(); // Turns on Clock by setting PCLK Register to 5 + delay(50); + + CommandFifo::Cmd_Reset(); + delay(50); + + // Set Initial Values for Touch Transform Registers + + CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_A, default_transform_a); + CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_B, default_transform_b); + CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_C, default_transform_c); + CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_D, default_transform_d); + CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_E, default_transform_e); + CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_F, default_transform_f); +} + +/******************* SOUND HELPER CLASS ************************/ + +class CLCD::SoundPlayer { + public: + struct sound_t { + effect_t effect; // The sound effect number + uint8_t note; // The MIDI note value + uint8_t sixteenths; // Duration of note, in sixteeths of a second, or zero to play to completion + }; + + private: + const sound_t *sequence; + uint32_t next; + + public: + static const uint8_t MIDDLE_C = 60; // C4 + + static void setVolume(uint8_t volume); + static void play(effect_t effect, uint8_t note = MIDDLE_C); + static bool soundPlaying(); + + void play(const sound_t* seq); + + void onIdle(); +}; + +void CLCD::SoundPlayer::setVolume(uint8_t vol) { + CLCD::Mem_Write8(REG_VOL_SOUND, vol); +} + +void CLCD::SoundPlayer::play(effect_t effect, uint8_t note) { + CLCD::Mem_Write16(REG_SOUND, (note << 8) | effect); + CLCD::Mem_Write8( REG_PLAY, 1); + + #if defined(UI_FRAMEWORK_DEBUG) + #if defined (SERIAL_PROTOCOLLNPAIR) + SERIAL_PROTOCOLPAIR("Playing note ", note); + SERIAL_PROTOCOLLNPAIR(", instrument ", effect); + #endif + #endif +} + +void CLCD::SoundPlayer::play(const sound_t* seq) { + sequence = seq; + next = 0; +} + +bool CLCD::SoundPlayer::soundPlaying() { + return CLCD::Mem_Read8( REG_PLAY ) & 0x1; +} + +void CLCD::SoundPlayer::onIdle() { + if(!sequence) return; + + const bool readyForNextNote = next != 0 ? (millis() > next) : !soundPlaying(); + + if(readyForNextNote) { + const effect_t fx = effect_t(pgm_read_byte_near(&sequence->effect)); + const uint8_t nt = pgm_read_byte_near(&sequence->note); + const uint16_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 : MIDDLE_C); + sequence++; + } + } +} + #endif // _AO_FT810_FUNC_H diff --git a/Marlin/AO_FT810_SPI.h b/Marlin/AO_FT810_SPI.h index 72180324c..99cf1aff0 100644 --- a/Marlin/AO_FT810_SPI.h +++ b/Marlin/AO_FT810_SPI.h @@ -67,7 +67,7 @@ void CLCD::spiDeselect (void) { // CLC void CLCD::Reset (void) { WRITE(CLCD_MOD_RESET, 0); - delay(50); + delay(100); WRITE(CLCD_MOD_RESET, 1); } diff --git a/Marlin/AO_FT810_UI_Screens.h b/Marlin/AO_FT810_UI_Screens.h index 596839a6f..816fe99f6 100644 --- a/Marlin/AO_FT810_UI_Screens.h +++ b/Marlin/AO_FT810_UI_Screens.h @@ -107,13 +107,11 @@ class BootScreen : public UIScreen { }; class AboutScreen : public UIScreen { - private: - static void playChime(); - static void draw(bool); public: static void onEntry(); static void onRefresh(); static void onTouchStart(uint8_t tag); + static void onIdle(); }; class StatusScreen : public UIScreen { @@ -301,6 +299,10 @@ namespace Theme { const float icon_scale = 0.6; #endif #endif + + const effect_t press_sound = CHACK; + const effect_t repeat_sound = CHACK; + const effect_t unpress_sound = POP; }; /******************************** BOOT SCREEN ****************************/ @@ -316,6 +318,7 @@ void BootScreen::onRefresh() { cmd.Cmd_Wait_Until_Idle(); CLCD::Turn_On_Backlight(); + CLCD::SoundPlayer::setVolume(255); } void BootScreen::onIdle() { @@ -324,32 +327,61 @@ void BootScreen::onIdle() { /******************************** ABOUT SCREEN ****************************/ +CLCD::SoundPlayer sound; + +const PROGMEM CLCD::SoundPlayer::sound_t chimes[] = { + {CHIMES, 55, 13}, + {CHIMES, 64, 13}, + {CHIMES, 60, 19} +}; + +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() { - draw(false); - playChime(); - draw(true); -} + UIScreen::onEntry(); -void AboutScreen::onRefresh() { - draw(true); + CLCD::Mem_Write8(REG_VOL_SOUND, 0xFF); + sound.play(chimes); } -void AboutScreen::draw(bool showOkay) { +void AboutScreen::onRefresh() { CLCD::CommandFifo cmd; cmd.Cmd(CMD_DLSTART); cmd.Cmd_Clear_Color(Theme::about_bg); cmd.Cmd_Clear(1,1,1); #define GRID_COLS 4 - #define GRID_ROWS 6 + #define GRID_ROWS 8 BTX( BTN_POS(1,2), BTN_SIZE(4,1), F("Color LCD Interface"), FONT_LRG); BTN_TAG(2) BTX( BTN_POS(1,3), BTN_SIZE(4,1), F("(c) 2018 Aleph Objects, Inc."), FONT_LRG); - if(showOkay) { - BTN_TAG(1) THEME(about_btn) BTN( BTN_POS(2,5), BTN_SIZE(2,1), F("Okay"), MENU_BTN_STYLE); - } + 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); cmd.Cmd(DL_DISPLAY); cmd.Cmd(CMD_SWAP); @@ -363,25 +395,8 @@ void AboutScreen::onTouchStart(uint8_t tag) { } } -void AboutScreen::playChime() { - CLCD::Mem_Write8(REG_VOL_SOUND, 0xFF); - CLCD::Mem_Write16(REG_SOUND, (0x37<< 8) | 0x47); // C8 MIDI note on xylophone 37 - CLCD::Mem_Write8(REG_PLAY, 1); - - delay(800); - - CLCD::Mem_Write16(REG_SOUND, (0x40<< 8) | 0x47); // C8 MIDI note on xylophone 40 - CLCD::Mem_Write8(REG_PLAY, 1); - - delay(800); - - CLCD::Mem_Write16(REG_SOUND, (0x3C<< 8) | 0x47); // C8 MIDI note on xylophone 3C - CLCD::Mem_Write8(REG_PLAY, 1); - - delay(1200); - - CLCD::Mem_Write16(REG_SOUND, 0); - CLCD::Mem_Write8(REG_PLAY, 1); +void AboutScreen::onIdle() { + sound.onIdle(); } /*********************************** STATUS SCREEN ******************************/ @@ -1255,8 +1270,11 @@ void lcd_update() { // 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) @@ -1275,6 +1293,8 @@ void lcd_update() { 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); @@ -1296,6 +1316,7 @@ void lcd_update() { // The user is holding down a button. if((millis() - last_repeat) > 250) { current_screen.onTouchHeld(tag); + sound.play(Theme::repeat_sound); last_repeat = millis(); } } diff --git a/Marlin/AO_UI_Marlin_LCD_API.h b/Marlin/AO_UI_Marlin_LCD_API.h index c93bf01c0..07ad5ddd3 100644 --- a/Marlin/AO_UI_Marlin_LCD_API.h +++ b/Marlin/AO_UI_Marlin_LCD_API.h @@ -41,6 +41,8 @@ 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 progmem_str getFirmwareName(); }; #if defined(MSG_MARLIN) @@ -103,4 +105,8 @@ const bool Marlin_LCD_API::isAxisPositionKnown(const axis_t axis) { case Z: return axis_known_position[Z_AXIS]; break; } } + +const Marlin_LCD_API::progmem_str Marlin_LCD_API::getFirmwareName() { + return F("Marlin " SHORT_BUILD_VERSION LULZBOT_FW_VERSION); +} #endif \ No newline at end of file