Merge remote-tracking branch 'upstream/bugfix-2.0.x' into bf2_granty_fix_15017
This commit is contained in:
		
						commit
						09ee5a5da1
					
				| @ -242,12 +242,12 @@ jobs: | ||||
|             echo testing STM32F1 targets... | ||||
|             export TEST_PLATFORM="-e STM32F1" | ||||
|             restore_configs | ||||
|             echo use_example_configs STM32F10 | ||||
|             use_example_configs STM32F10 | ||||
|             echo use_example_configs STM32/STM32F10 | ||||
|             use_example_configs STM32/STM32F10 | ||||
|             build_marlin_pio ./ ${TEST_PLATFORM} | ||||
|             restore_configs | ||||
|             echo use_example_configs stm32f103ret6 | ||||
|             use_example_configs stm32f103ret6 | ||||
|             echo use_example_configs STM32/stm32f103ret6 | ||||
|             use_example_configs STM32/stm32f103ret6 | ||||
|             build_marlin_pio ./ ${TEST_PLATFORM} | ||||
|             restore_configs | ||||
| 
 | ||||
|  | ||||
| @ -359,6 +359,7 @@ | ||||
|  *    -1 : thermocouple with AD595 | ||||
|  *     0 : not used | ||||
|  *     1 : 100k thermistor - best choice for EPCOS 100k (4.7k pullup) | ||||
|  *   331 : (3.3V scaled thermistor 1 table) | ||||
|  *     2 : 200k thermistor - ATC Semitec 204GT-2 (4.7k pullup) | ||||
|  *     3 : Mendel-parts thermistor (4.7k pullup) | ||||
|  *     4 : 10k thermistor !! do not use it for a hotend. It gives bad resolution at high temp. !! | ||||
| @ -402,7 +403,7 @@ | ||||
|  *   998 : Dummy Table that ALWAYS reads 25°C or the temperature defined below. | ||||
|  *   999 : Dummy Table that ALWAYS reads 100°C or the temperature defined below. | ||||
|  * | ||||
|  * :{ '0':"Not used", '1':"100k / 4.7k - EPCOS", '2':"200k / 4.7k - ATC Semitec 204GT-2", '3':"Mendel-parts / 4.7k", '4':"10k !! do not use for a hotend. Bad resolution at high temp. !!", '5':"100K / 4.7k - ATC Semitec 104GT-2 (Used in ParCan & J-Head)", '501':"100K Zonestar (Tronxy X3A)", '512':"100k RPW-Ultra hotend thermistor", '6':"100k / 4.7k EPCOS - Not as accurate as Table 1", '7':"100k / 4.7k Honeywell 135-104LAG-J01", '8':"100k / 4.7k 0603 SMD Vishay NTCS0603E3104FXT", '9':"100k / 4.7k GE Sensing AL03006-58.2K-97-G1", '10':"100k / 4.7k RS 198-961", '11':"100k / 4.7k beta 3950 1%", '12':"100k / 4.7k 0603 SMD Vishay NTCS0603E3104FXT (calibrated for Makibox hot bed)", '13':"100k Hisens 3950  1% up to 300°C for hotend 'Simple ONE ' & hotend 'All In ONE'", '18':"ATC Semitec 204GT-2 (4.7k pullup) Dagoma.Fr - MKS_Base_DKU001327" '20':"Pt100 (Ultimainboard V2.x)", '201':"Pt100 (Overlord)", '51':"100k / 1k - EPCOS", '52':"200k / 1k - ATC Semitec 204GT-2", '55':"100k / 1k - ATC Semitec 104GT-2 (Used in ParCan & J-Head)", '60':"100k Maker's Tool Works Kapton Bed Thermistor beta=3950", '61':"100k Formbot / Vivedino 3950 350C thermistor 4.7k pullup", '66':"Dyze Design 4.7M High Temperature thermistor", '67':"Slice Engineering 450C High Temperature thermistor", '70':"the 100K thermistor found in the bq Hephestos 2", '71':"100k / 4.7k Honeywell 135-104LAF-J01", '147':"Pt100 / 4.7k", '1047':"Pt1000 / 4.7k", '110':"Pt100 / 1k (non-standard)", '1010':"Pt1000 / 1k (non standard)", '-4':"Thermocouple + AD8495", '-3':"Thermocouple + MAX31855 (only for sensor 0)", '-2':"Thermocouple + MAX6675 (only for sensor 0)", '-1':"Thermocouple + AD595", '998':"Dummy 1", '999':"Dummy 2", '1000':"Custom thermistor params" } | ||||
|  * :{ '0':"Not used", '1':"100k / 4.7k - EPCOS", '331':"(3.3V thermistor 1)", '2':"200k / 4.7k - ATC Semitec 204GT-2", '3':"Mendel-parts / 4.7k", '4':"10k !! do not use for a hotend. Bad resolution at high temp. !!", '5':"100K / 4.7k - ATC Semitec 104GT-2 (Used in ParCan & J-Head)", '501':"100K Zonestar (Tronxy X3A)", '512':"100k RPW-Ultra hotend thermistor", '6':"100k / 4.7k EPCOS - Not as accurate as Table 1", '7':"100k / 4.7k Honeywell 135-104LAG-J01", '8':"100k / 4.7k 0603 SMD Vishay NTCS0603E3104FXT", '9':"100k / 4.7k GE Sensing AL03006-58.2K-97-G1", '10':"100k / 4.7k RS 198-961", '11':"100k / 4.7k beta 3950 1%", '12':"100k / 4.7k 0603 SMD Vishay NTCS0603E3104FXT (calibrated for Makibox hot bed)", '13':"100k Hisens 3950  1% up to 300°C for hotend 'Simple ONE ' & hotend 'All In ONE'", '18':"ATC Semitec 204GT-2 (4.7k pullup) Dagoma.Fr - MKS_Base_DKU001327" '20':"Pt100 (Ultimainboard V2.x)", '201':"Pt100 (Overlord)", '51':"100k / 1k - EPCOS", '52':"200k / 1k - ATC Semitec 204GT-2", '55':"100k / 1k - ATC Semitec 104GT-2 (Used in ParCan & J-Head)", '60':"100k Maker's Tool Works Kapton Bed Thermistor beta=3950", '61':"100k Formbot / Vivedino 3950 350C thermistor 4.7k pullup", '66':"Dyze Design 4.7M High Temperature thermistor", '67':"Slice Engineering 450C High Temperature thermistor", '70':"the 100K thermistor found in the bq Hephestos 2", '71':"100k / 4.7k Honeywell 135-104LAF-J01", '147':"Pt100 / 4.7k", '1047':"Pt1000 / 4.7k", '110':"Pt100 / 1k (non-standard)", '1010':"Pt1000 / 1k (non standard)", '-4':"Thermocouple + AD8495", '-3':"Thermocouple + MAX31855 (only for sensor 0)", '-2':"Thermocouple + MAX6675 (only for sensor 0)", '-1':"Thermocouple + AD595", '998':"Dummy 1", '999':"Dummy 2", '1000':"Custom thermistor params" } | ||||
|  */ | ||||
| #define TEMP_SENSOR_0 1 | ||||
| #define TEMP_SENSOR_1 0 | ||||
| @ -2033,6 +2034,12 @@ | ||||
| //
 | ||||
| //#define MALYAN_LCD
 | ||||
| 
 | ||||
| //
 | ||||
| // LulzBot Color Touch UI for FTDI EVE (FT800/FT810) displays
 | ||||
| // See Configuration_adv.h for all configuration options.
 | ||||
| //
 | ||||
| //#define LULZBOT_TOUCH_UI
 | ||||
| 
 | ||||
| //
 | ||||
| // Third-party or vendor-customized controller interfaces.
 | ||||
| // Sources should be installed in 'src/lcd/extensible_ui'.
 | ||||
|  | ||||
| @ -279,9 +279,10 @@ | ||||
|  */ | ||||
| //#define USE_CONTROLLER_FAN
 | ||||
| #if ENABLED(USE_CONTROLLER_FAN) | ||||
|   //#define CONTROLLER_FAN_PIN -1        // Set a custom pin for the controller fan
 | ||||
|   #define CONTROLLERFAN_SECS 60          // Duration in seconds for the fan to run after all motors are disabled
 | ||||
|   #define CONTROLLERFAN_SPEED 255        // 255 == full speed
 | ||||
|   //#define CONTROLLER_FAN_PIN -1           // Set a custom pin for the controller fan
 | ||||
|   #define CONTROLLERFAN_SECS 60             // Duration in seconds for the fan to run after all motors are disabled
 | ||||
|   #define CONTROLLERFAN_SPEED 255           // 255 == full speed
 | ||||
|   //#define CONTROLLERFAN_SPEED_Z_ONLY 127  // Reduce noise on machines that keep Z enabled
 | ||||
| #endif | ||||
| 
 | ||||
| // When first starting the main fan, run it at full speed for the
 | ||||
| @ -657,10 +658,10 @@ | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // @section extras
 | ||||
| // @section motion
 | ||||
| 
 | ||||
| // minimum time in microseconds that a movement needs to take if the buffer is emptied.
 | ||||
| #define DEFAULT_MINSEGMENTTIME        20000 | ||||
| // Minimum time that a segment needs to take if the buffer is emptied
 | ||||
| #define DEFAULT_MINSEGMENTTIME        20000   // (ms)
 | ||||
| 
 | ||||
| // If defined the movements slow down when the look ahead buffer is only half full
 | ||||
| #define SLOWDOWN | ||||
| @ -850,11 +851,35 @@ | ||||
|   #define FEEDRATE_CHANGE_BEEP_FREQUENCY 440 | ||||
| #endif | ||||
| 
 | ||||
| // Include a page of printer information in the LCD Main Menu
 | ||||
| //#define LCD_INFO_MENU
 | ||||
| #if ENABLED(LCD_INFO_MENU) | ||||
|   //#define LCD_PRINTER_INFO_IS_BOOTSCREEN // Show bootscreen(s) instead of Printer Info pages
 | ||||
| #endif | ||||
| #if HAS_LCD_MENU | ||||
| 
 | ||||
|   // Include a page of printer information in the LCD Main Menu
 | ||||
|   //#define LCD_INFO_MENU
 | ||||
|   #if ENABLED(LCD_INFO_MENU) | ||||
|     //#define LCD_PRINTER_INFO_IS_BOOTSCREEN // Show bootscreen(s) instead of Printer Info pages
 | ||||
|   #endif | ||||
| 
 | ||||
|   // BACK menu items keep the highlight at the top
 | ||||
|   //#define TURBO_BACK_MENU_ITEM
 | ||||
| 
 | ||||
|   /**
 | ||||
|    * LED Control Menu | ||||
|    * Add LED Control to the LCD menu | ||||
|    */ | ||||
|   //#define LED_CONTROL_MENU
 | ||||
|   #if ENABLED(LED_CONTROL_MENU) | ||||
|     #define LED_COLOR_PRESETS                 // Enable the Preset Color menu option
 | ||||
|     #if ENABLED(LED_COLOR_PRESETS) | ||||
|       #define LED_USER_PRESET_RED        255  // User defined RED value
 | ||||
|       #define LED_USER_PRESET_GREEN      128  // User defined GREEN value
 | ||||
|       #define LED_USER_PRESET_BLUE         0  // User defined BLUE value
 | ||||
|       #define LED_USER_PRESET_WHITE      255  // User defined WHITE value
 | ||||
|       #define LED_USER_PRESET_BRIGHTNESS 255  // User defined intensity
 | ||||
|       //#define LED_USER_PRESET_STARTUP       // Have the printer display the user preset color on startup
 | ||||
|     #endif | ||||
|   #endif | ||||
| 
 | ||||
| #endif // HAS_LCD_MENU
 | ||||
| 
 | ||||
| // Scroll a longer status message into view
 | ||||
| //#define STATUS_MESSAGE_SCROLLING
 | ||||
| @ -879,23 +904,6 @@ | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * LED Control Menu | ||||
|  * Enable this feature to add LED Control to the LCD menu | ||||
|  */ | ||||
| //#define LED_CONTROL_MENU
 | ||||
| #if ENABLED(LED_CONTROL_MENU) | ||||
|   #define LED_COLOR_PRESETS                 // Enable the Preset Color menu option
 | ||||
|   #if ENABLED(LED_COLOR_PRESETS) | ||||
|     #define LED_USER_PRESET_RED        255  // User defined RED value
 | ||||
|     #define LED_USER_PRESET_GREEN      128  // User defined GREEN value
 | ||||
|     #define LED_USER_PRESET_BLUE         0  // User defined BLUE value
 | ||||
|     #define LED_USER_PRESET_WHITE      255  // User defined WHITE value
 | ||||
|     #define LED_USER_PRESET_BRIGHTNESS 255  // User defined intensity
 | ||||
|     //#define LED_USER_PRESET_STARTUP       // Have the printer display the user preset color on startup
 | ||||
|   #endif | ||||
| #endif // LED_CONTROL_MENU
 | ||||
| 
 | ||||
| #if ENABLED(SDSUPPORT) | ||||
| 
 | ||||
|   // Some RAMPS and other boards don't detect when an SD card is inserted. You can work
 | ||||
| @ -930,6 +938,7 @@ | ||||
|   #if ENABLED(POWER_LOSS_RECOVERY) | ||||
|     //#define POWER_LOSS_PIN         44 // Pin to detect power loss
 | ||||
|     //#define POWER_LOSS_STATE     HIGH // State of pin indicating power loss
 | ||||
|     //#define POWER_LOSS_PULL           // Set pullup / pulldown as appropriate
 | ||||
|     //#define POWER_LOSS_PURGE_LEN   20 // (mm) Length of filament to purge on resume
 | ||||
|     //#define POWER_LOSS_RETRACT_LEN 10 // (mm) Length of filament to retract on fail. Requires backup power.
 | ||||
| 
 | ||||
| @ -1134,6 +1143,7 @@ | ||||
|   //#define STATUS_FAN_FRAMES 3       // :[0,1,2,3,4] Number of fan animation frames
 | ||||
|   //#define STATUS_HEAT_PERCENT       // Show heating in a progress bar
 | ||||
|   //#define BOOT_MARLIN_LOGO_SMALL    // Show a smaller Marlin logo on the Boot Screen (saving 399 bytes of flash)
 | ||||
|   //#define BOOT_MARLIN_LOGO_ANIMATED // Animated Marlin logo. Costs ~3260 (or ~940) bytes of PROGMEM.
 | ||||
| 
 | ||||
|   // Frivolous Game Options
 | ||||
|   //#define MARLIN_BRICKOUT
 | ||||
| @ -1143,6 +1153,53 @@ | ||||
| 
 | ||||
| #endif // HAS_GRAPHICAL_LCD
 | ||||
| 
 | ||||
| //
 | ||||
| // Lulzbot Touch UI
 | ||||
| //
 | ||||
| #if ENABLED(LULZBOT_TOUCH_UI) | ||||
|   // Display board used
 | ||||
|   //#define LCD_FTDI_VM800B35A        // FTDI 3.5" with FT800 (320x240)
 | ||||
|   //#define LCD_4DSYSTEMS_4DLCD_FT843 // 4D Systems 4.3" (480x272)
 | ||||
|   //#define LCD_HAOYU_FT800CB         // Haoyu with 4.3" or 5" (480x272)
 | ||||
|   //#define LCD_HAOYU_FT810CB         // Haoyu with 5" (800x480)
 | ||||
|   //#define LCD_ALEPHOBJECTS_CLCD_UI  // Aleph Objects Color LCD UI
 | ||||
| 
 | ||||
|   // Correct the resolution if not using the stock TFT panel.
 | ||||
|   //#define TOUCH_UI_320x240
 | ||||
|   //#define TOUCH_UI_480x272
 | ||||
|   //#define TOUCH_UI_800x480
 | ||||
| 
 | ||||
|   // Mappings for boards with a standard RepRapDiscount Display connector
 | ||||
|   //#define AO_EXP1_PINMAP    // AlephObjects CLCD UI EXP1 mapping
 | ||||
|   //#define AO_EXP2_PINMAP    // AlephObjects CLCD UI EXP2 mapping
 | ||||
|   //#define CR10_TFT_PINMAP   // Rudolph Riedel's CR10 pin mapping
 | ||||
|   //#define OTHER_PIN_LAYOUT  // Define pins manually below
 | ||||
|   #if ENABLED(OTHER_PIN_LAYOUT) | ||||
|     // The pins for CS and MOD_RESET (PD) must be chosen.
 | ||||
|     #define CLCD_MOD_RESET  9 | ||||
|     #define CLCD_SPI_CS    10 | ||||
| 
 | ||||
|     // If using software SPI, specify pins for SCLK, MOSI, MISO
 | ||||
|     //#define CLCD_USE_SOFT_SPI
 | ||||
|     #if ENABLED(CLCD_USE_SOFT_SPI) | ||||
|       #define CLCD_SOFT_SPI_MOSI 11 | ||||
|       #define CLCD_SOFT_SPI_MISO 12 | ||||
|       #define CLCD_SOFT_SPI_SCLK 13 | ||||
|     #endif | ||||
|   #endif | ||||
| 
 | ||||
|   // Display Orientation. An inverted (i.e. upside-down) display
 | ||||
|   // is supported on the FT800. The FT810 and beyond also support
 | ||||
|   // portrait and mirrored orientations.
 | ||||
|   //#define TOUCH_UI_INVERTED
 | ||||
|   //#define TOUCH_UI_PORTRAIT
 | ||||
|   //#define TOUCH_UI_MIRRORED
 | ||||
| 
 | ||||
|   // Use a numeric passcode for "Screen lock" keypad.
 | ||||
|   // (recommended for smaller displays)
 | ||||
|   //#define TOUCH_UI_PASSCODE
 | ||||
| #endif | ||||
| 
 | ||||
| // @section safety
 | ||||
| 
 | ||||
| /**
 | ||||
| @ -2242,6 +2299,13 @@ | ||||
|  */ | ||||
| #define EXTENDED_CAPABILITIES_REPORT | ||||
| 
 | ||||
| /**
 | ||||
|  * Expected Printer Check | ||||
|  * Add the M16 G-code to compare a string to the MACHINE_NAME. | ||||
|  * M16 with a non-matching string causes the printer to halt. | ||||
|  */ | ||||
| //#define EXPECTED_PRINTER_CHECK
 | ||||
| 
 | ||||
| /**
 | ||||
|  * Disable all Volumetric extrusion options | ||||
|  */ | ||||
| @ -2296,6 +2360,13 @@ | ||||
|   //#define VARIABLE_G0_FEEDRATE // The G0 feedrate is set by F in G0 motion mode
 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Startup commands | ||||
|  * | ||||
|  * Execute certain G-code commands immediately after power-on. | ||||
|  */ | ||||
| //#define STARTUP_COMMANDS "M17 Z"
 | ||||
| 
 | ||||
| /**
 | ||||
|  * G-code Macros | ||||
|  * | ||||
|  | ||||
| @ -281,42 +281,44 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1205) | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1300) | ||||
| # Cartesio CN Controls V12
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1301) | ||||
| # Cheaptronic v1.0
 | ||||
| # Cartesio CN Controls V15
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1302) | ||||
| # Cheaptronic v2.0
 | ||||
| # Cheaptronic v1.0
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1303) | ||||
| # Makerbot Mightyboard Revision E
 | ||||
| # Cheaptronic v2.0
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1304) | ||||
| # Megatronics
 | ||||
| # Makerbot Mightyboard Revision E
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1305) | ||||
| # Megatronics v2.0
 | ||||
| # Megatronics
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1306) | ||||
| # Megatronics v3.0
 | ||||
| # Megatronics v2.0
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1307) | ||||
| # Megatronics v3.1
 | ||||
| # Megatronics v3.0
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1308) | ||||
| # Megatronics v3.2
 | ||||
| # Megatronics v3.1
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1309) | ||||
| # Elefu Ra Board (v3)
 | ||||
| # Megatronics v3.2
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1310) | ||||
| # Leapfrog
 | ||||
| # Elefu Ra Board (v3)
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1311) | ||||
| # Mega controller
 | ||||
| # Leapfrog
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1312) | ||||
| # Geeetech GT2560 Rev B for Mecreator2
 | ||||
| # Mega controller
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1313) | ||||
| # Geeetech GT2560 Rev. A
 | ||||
| # Geeetech GT2560 Rev B for Mecreator2
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1314) | ||||
| # Geeetech GT2560 Rev. A+ (with auto level probe)
 | ||||
| # Geeetech GT2560 Rev. A
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1315) | ||||
| # Geeetech GT2560 Rev B for A10(M/D)
 | ||||
| # Geeetech GT2560 Rev. A+ (with auto level probe)
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1316) | ||||
| # Geeetech GT2560 Rev B for A20(M/D)
 | ||||
| # Geeetech GT2560 Rev B for A10(M/D)
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1317) | ||||
| # Einstart retrofit
 | ||||
| # Geeetech GT2560 Rev B for A20(M/D)
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1318) | ||||
| # Wanhao 0ne+ i3 Mini
 | ||||
| # Einstart retrofit
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1319) | ||||
| # Wanhao 0ne+ i3 Mini
 | ||||
| else ifeq ($(HARDWARE_MOTHERBOARD),1320) | ||||
| 
 | ||||
| #
 | ||||
| # ATmega1281, ATmega2561
 | ||||
|  | ||||
| @ -23,6 +23,7 @@ | ||||
| 
 | ||||
| #include "../../../inc/MarlinConfigPre.h" | ||||
| #include "../../shared/Marduino.h" | ||||
| #include <U8glib.h> | ||||
| 
 | ||||
| void u8g_SetPIOutput_DUE(u8g_t *u8g, uint8_t pin_index); | ||||
| void u8g_SetPILevel_DUE(u8g_t *u8g, uint8_t pin_index, uint8_t level); | ||||
|  | ||||
| @ -70,7 +70,7 @@ | ||||
|   const uint32_t mask = MASK(DIO ## IO ## _PIN); \ | ||||
|   if (V) port->PIO_SODR = mask; \ | ||||
|   else port->PIO_CODR = mask; \ | ||||
| } while(0) | ||||
| }while(0) | ||||
| 
 | ||||
| // Toggle a pin
 | ||||
| #define _TOGGLE(IO) _WRITE(IO, !READ(IO)) | ||||
|  | ||||
| @ -112,7 +112,7 @@ | ||||
|  * \def unused | ||||
|  * \brief Marking \a v as a unused parameter or value. | ||||
|  */ | ||||
| #define unused(v)          do { (void)(v); } while(0) | ||||
| #define unused(v)          do { (void)(v); }while(0) | ||||
| 
 | ||||
| /**
 | ||||
|  * \def barrier | ||||
| @ -169,7 +169,7 @@ | ||||
|  * heuristics and inline the function no matter how big it thinks it | ||||
|  * becomes. | ||||
|  */ | ||||
| #if defined(__CC_ARM) | ||||
| #ifdef __CC_ARM | ||||
| #   define __always_inline   __forceinline | ||||
| #elif (defined __GNUC__) | ||||
| #ifdef __always_inline | ||||
| @ -187,7 +187,7 @@ | ||||
|  * This annotation instructs the compiler to ignore its inlining | ||||
|  * heuristics and not inline the function. | ||||
|  */ | ||||
| #if defined(__CC_ARM) | ||||
| #ifdef __CC_ARM | ||||
| #   define __no_inline   __attribute__((noinline)) | ||||
| #elif (defined __GNUC__) | ||||
| #	define __no_inline   __attribute__((__noinline__)) | ||||
| @ -204,7 +204,7 @@ | ||||
|  * | ||||
|  * \param expr  Expression to evaluate and supposed to be nonzero. | ||||
|  */ | ||||
| #if defined(_ASSERT_ENABLE_) | ||||
| #ifdef _ASSERT_ENABLE_ | ||||
| #  if defined(TEST_SUITE_DEFINE_ASSERT_MACRO) | ||||
|      // Assert() is defined in unit_test/suite.h
 | ||||
| #    include "unit_test/suite.h" | ||||
| @ -998,14 +998,14 @@ typedef U8                  Byte;       //!< 8-bit unsigned integer. | ||||
| #endif  // #ifndef __ASSEMBLY__
 | ||||
| 
 | ||||
| 
 | ||||
| #if defined(__ICCARM__) | ||||
| #ifdef __ICCARM__ | ||||
| #define SHORTENUM           __packed | ||||
| #elif defined(__GNUC__) | ||||
| #define SHORTENUM           __attribute__((packed)) | ||||
| #endif | ||||
| 
 | ||||
| /* No operation */ | ||||
| #if defined(__ICCARM__) | ||||
| #ifdef __ICCARM__ | ||||
| #define nop()               __no_operation() | ||||
| #elif defined(__GNUC__) | ||||
| #define nop()               (__NOP()) | ||||
|  | ||||
| @ -142,10 +142,10 @@ public: | ||||
|   void print_bin(uint32_t value, uint8_t num_digits) { | ||||
|     uint32_t mask = 1 << (num_digits -1); | ||||
|     for (uint8_t i = 0; i < num_digits; i++) { | ||||
|       if (!(i % 4) && i)    write(' '); | ||||
|       if (!(i % 16)  && i)  write(' '); | ||||
|       if (value & mask)     write('1'); | ||||
|       else                  write('0'); | ||||
|       if (!(i %  4) && i) write(' '); | ||||
|       if (!(i % 16) && i) write(' '); | ||||
|       if (value & mask)   write('1'); | ||||
|       else                write('0'); | ||||
|       value <<= 1; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @ -1,13 +1,37 @@ | ||||
| /**
 | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
 | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * 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. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #ifdef TARGET_LPC1768 | ||||
| 
 | ||||
| #include "../../inc/MarlinConfigPre.h" | ||||
| 
 | ||||
| #if ENABLED(EMERGENCY_PARSER) | ||||
|   #include "../../feature/emergency_parser.h" | ||||
|   EmergencyParser::State emergency_state; | ||||
|   bool CDC_RecvCallback(const char buffer) { | ||||
|     emergency_parser.update(emergency_state, buffer); | ||||
|     return true; | ||||
|   } | ||||
| #endif // ENABLED(EMERGENCY_PARSER)
 | ||||
| 
 | ||||
| #include "../../feature/emergency_parser.h" | ||||
| EmergencyParser::State emergency_state; | ||||
| bool CDC_RecvCallback(const char buffer) { | ||||
|   emergency_parser.update(emergency_state, buffer); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| #endif // EMERGENCY_PARSER
 | ||||
| #endif // TARGET_LPC1768
 | ||||
|  | ||||
| @ -115,12 +115,12 @@ HAL_SERVO_TIMER_ISR() { | ||||
|       tc->COUNT16.CC[tcChannel].reg = (uint16_t)(tcCounterValue - 4UL);               // at least REFRESH_INTERVAL has elapsed
 | ||||
|   } | ||||
|   if (tcChannel == 0) { | ||||
|     SYNC(tc->COUNT16.SYNCBUSY.bit.CC0);  | ||||
|     SYNC(tc->COUNT16.SYNCBUSY.bit.CC0); | ||||
|     // Clear the interrupt
 | ||||
|     tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0; | ||||
|   } | ||||
|   else { | ||||
|     SYNC(tc->COUNT16.SYNCBUSY.bit.CC1);  | ||||
|     SYNC(tc->COUNT16.SYNCBUSY.bit.CC1); | ||||
|     // Clear the interrupt
 | ||||
|     tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC1; | ||||
|   } | ||||
|  | ||||
| @ -243,6 +243,7 @@ | ||||
|   #define DIO5_PIN    PIN_PC21 | ||||
|   #define DIO16_PIN   PIN_PC22 | ||||
|   #define DIO17_PIN   PIN_PC23 | ||||
|   #define DIO88_PIN   PIN_PC24    // NEOPIXEL
 | ||||
|   // PORTD
 | ||||
|   #define DIO22_PIN   PIN_PD12 | ||||
|   #define DIO6_PIN    PIN_PD20 | ||||
|  | ||||
| @ -32,7 +32,7 @@ | ||||
| #endif | ||||
| 
 | ||||
| #if ENABLED(EMERGENCY_PARSER) | ||||
|   #error "EMERGENCY_PARSER is not yet implemented for STM32F4. Disable EMERGENCY_PARSER to continue." | ||||
|   #error "EMERGENCY_PARSER is not yet implemented for SAMD51. Disable EMERGENCY_PARSER to continue." | ||||
| #endif | ||||
| 
 | ||||
| #if ENABLED(SDIO_SUPPORT) | ||||
|  | ||||
| @ -22,7 +22,6 @@ | ||||
|  */ | ||||
| #if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) | ||||
| 
 | ||||
| 
 | ||||
| #include "../../inc/MarlinConfig.h" | ||||
| 
 | ||||
| #include <SPI.h> | ||||
| @ -73,16 +72,22 @@ void spiInit(uint8_t spiRate) { | ||||
|   // Use datarates Marlin uses
 | ||||
|   uint32_t clock; | ||||
|   switch (spiRate) { | ||||
|   case SPI_FULL_SPEED:    clock = 20000000; break; // 13.9mhz=20000000  6.75mhz=10000000  3.38mhz=5000000  .833mhz=1000000
 | ||||
|   case SPI_HALF_SPEED:    clock =  5000000; break; | ||||
|   case SPI_QUARTER_SPEED: clock =  2500000; break; | ||||
|   case SPI_EIGHTH_SPEED:  clock =  1250000; break; | ||||
|   case SPI_SPEED_5:       clock =   625000; break; | ||||
|   case SPI_SPEED_6:       clock =   300000; break; | ||||
|   default: | ||||
|     clock = 4000000; // Default from the SPI library
 | ||||
|     case SPI_FULL_SPEED:    clock = 20000000; break; // 13.9mhz=20000000  6.75mhz=10000000  3.38mhz=5000000  .833mhz=1000000
 | ||||
|     case SPI_HALF_SPEED:    clock =  5000000; break; | ||||
|     case SPI_QUARTER_SPEED: clock =  2500000; break; | ||||
|     case SPI_EIGHTH_SPEED:  clock =  1250000; break; | ||||
|     case SPI_SPEED_5:       clock =   625000; break; | ||||
|     case SPI_SPEED_6:       clock =   300000; break; | ||||
|     default: | ||||
|       clock = 4000000; // Default from the SPI library
 | ||||
|   } | ||||
|   spiConfig = SPISettings(clock, MSBFIRST, SPI_MODE0); | ||||
|   #if defined(MISO_PIN) && defined(SDSS) && defined(MOSI_PIN) && defined(SCK_PIN) | ||||
|     SPI.setMISO(MISO_PIN); | ||||
|     SPI.setSSEL(SDSS); | ||||
|     SPI.setMOSI(MOSI_PIN); | ||||
|     SPI.setSCLK(SCK_PIN); | ||||
|   #endif | ||||
|   SPI.begin(); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -53,7 +53,7 @@ void FastIO_init(); // Must be called before using fast io macros | ||||
|   #define _WRITE(IO, V) do { \ | ||||
|     if (V) FastIOPortMap[STM_PORT(digitalPin[IO])]->BSRR = _BV32(STM_PIN(digitalPin[IO])) ; \ | ||||
|     else   FastIOPortMap[STM_PORT(digitalPin[IO])]->BRR  = _BV32(STM_PIN(digitalPin[IO])) ; \ | ||||
|   } while(0) | ||||
|   }while(0) | ||||
| #else | ||||
|   #define _WRITE(IO, V) (FastIOPortMap[STM_PORT(digitalPin[IO])]->BSRR = _BV32(STM_PIN(digitalPin[IO]) + (V ? 0 : 16))) | ||||
| #endif | ||||
|  | ||||
| @ -189,7 +189,7 @@ void port_print(const pin_t Ard_num) { | ||||
|   for (Index = 0; Index < NUMBER_PINS_TOTAL; Index++) | ||||
|     if (Ard_num == GET_PIN_MAP_PIN_M43(Index)) break; | ||||
| 
 | ||||
|   char * const ppa = pin_xref[Index].Port_pin_alpha; | ||||
|   const char * ppa = pin_xref[Index].Port_pin_alpha; | ||||
|   sprintf_P(buffer, PSTR("%s"), ppa); | ||||
|   SERIAL_ECHO(buffer); | ||||
|   if (ppa[3] == '\0') SERIAL_CHAR(' '); | ||||
|  | ||||
| @ -33,7 +33,7 @@ | ||||
| #ifdef __STM32F1__ | ||||
| 
 | ||||
| #include "../../inc/MarlinConfig.h" | ||||
| #include <SPI.h> | ||||
| #include "SPI.h" | ||||
| 
 | ||||
| // ------------------------
 | ||||
| // Public functions
 | ||||
|  | ||||
							
								
								
									
										741
									
								
								Marlin/src/HAL/HAL_STM32F1/SPI.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										741
									
								
								Marlin/src/HAL/HAL_STM32F1/SPI.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,741 @@ | ||||
| /******************************************************************************
 | ||||
|  * The MIT License | ||||
|  * | ||||
|  * Copyright (c) 2010 Perry Hung. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person | ||||
|  * obtaining a copy of this software and associated documentation | ||||
|  * files (the "Software"), to deal in the Software without | ||||
|  * restriction, including without limitation the rights to use, copy, | ||||
|  * modify, merge, publish, distribute, sublicense, and/or sell copies | ||||
|  * of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||||
|  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  *****************************************************************************/ | ||||
| 
 | ||||
| /**
 | ||||
|  * @author Marti Bolivar <mbolivar@leaflabs.com> | ||||
|  * @brief Wirish SPI implementation. | ||||
|  */ | ||||
| 
 | ||||
| #ifdef __STM32F1__ | ||||
| 
 | ||||
| #include "SPI.h" | ||||
| 
 | ||||
| #include <libmaple/timer.h> | ||||
| #include <libmaple/util.h> | ||||
| #include <libmaple/rcc.h> | ||||
| 
 | ||||
| #include <boards.h> | ||||
| #include <wirish.h> | ||||
| 
 | ||||
| /** Time in ms for DMA receive timeout */ | ||||
| #define DMA_TIMEOUT 100 | ||||
| 
 | ||||
| #if CYCLES_PER_MICROSECOND != 72 | ||||
|   #warning "Unexpected clock speed; SPI frequency calculation will be incorrect" | ||||
| #endif | ||||
| 
 | ||||
| struct spi_pins { | ||||
|   uint8_t nss; | ||||
|   uint8_t sck; | ||||
|   uint8_t miso; | ||||
|   uint8_t mosi; | ||||
| }; | ||||
| 
 | ||||
| static const spi_pins* dev_to_spi_pins(spi_dev *dev); | ||||
| static void configure_gpios(spi_dev *dev, bool as_master); | ||||
| static spi_baud_rate determine_baud_rate(spi_dev *dev, uint32_t freq); | ||||
| 
 | ||||
| #if (BOARD_NR_SPI >= 3) && !defined(STM32_HIGH_DENSITY) | ||||
|   #error "The SPI library is misconfigured: 3 SPI ports only available on high density STM32 devices" | ||||
| #endif | ||||
| 
 | ||||
| static const spi_pins board_spi_pins[] __FLASH__ = { | ||||
|   #if BOARD_NR_SPI >= 1 | ||||
|   { BOARD_SPI1_NSS_PIN, | ||||
|     BOARD_SPI1_SCK_PIN, | ||||
|     BOARD_SPI1_MISO_PIN, | ||||
|     BOARD_SPI1_MOSI_PIN }, | ||||
|   #endif | ||||
|   #if BOARD_NR_SPI >= 2 | ||||
|   { BOARD_SPI2_NSS_PIN, | ||||
|     BOARD_SPI2_SCK_PIN, | ||||
|     BOARD_SPI2_MISO_PIN, | ||||
|     BOARD_SPI2_MOSI_PIN }, | ||||
|   #endif | ||||
|   #if BOARD_NR_SPI >= 3 | ||||
|   { BOARD_SPI3_NSS_PIN, | ||||
|     BOARD_SPI3_SCK_PIN, | ||||
|     BOARD_SPI3_MISO_PIN, | ||||
|     BOARD_SPI3_MOSI_PIN }, | ||||
|   #endif | ||||
| }; | ||||
| 
 | ||||
| #if BOARD_NR_SPI >= 1 | ||||
|   static void (*_spi1_this); | ||||
| #endif | ||||
| #if BOARD_NR_SPI >= 2 | ||||
|   static void (*_spi2_this); | ||||
| #endif | ||||
| #if BOARD_NR_SPI >= 3 | ||||
|   static void (*_spi3_this); | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Constructor | ||||
|  */ | ||||
| SPIClass::SPIClass(uint32_t spi_num) { | ||||
|   _currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed
 | ||||
| 
 | ||||
|   switch (spi_num) { | ||||
|     #if BOARD_NR_SPI >= 1 | ||||
|       case 1: | ||||
|         _currentSetting->spi_d = SPI1; | ||||
|         _spi1_this = (void*)this; | ||||
|         break; | ||||
|     #endif | ||||
|     #if BOARD_NR_SPI >= 2 | ||||
|       case 2: | ||||
|         _currentSetting->spi_d = SPI2; | ||||
|         _spi2_this = (void*)this; | ||||
|         break; | ||||
|     #endif | ||||
|     #if BOARD_NR_SPI >= 3 | ||||
|       case 3: | ||||
|         _currentSetting->spi_d = SPI3; | ||||
|         _spi3_this = (void*)this; | ||||
|         break; | ||||
|     #endif | ||||
|     default: ASSERT(0); | ||||
|   } | ||||
| 
 | ||||
|   // Init things specific to each SPI device
 | ||||
|   // clock divider setup is a bit of hack, and needs to be improved at a later date.
 | ||||
|   #if BOARD_NR_SPI >= 1 | ||||
|     _settings[0].spi_d = SPI1; | ||||
|     _settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock); | ||||
|     _settings[0].spiDmaDev = DMA1; | ||||
|     _settings[0].spiTxDmaChannel = DMA_CH3; | ||||
|     _settings[0].spiRxDmaChannel = DMA_CH2; | ||||
|   #endif | ||||
|   #if BOARD_NR_SPI >= 2 | ||||
|     _settings[1].spi_d = SPI2; | ||||
|     _settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock); | ||||
|     _settings[1].spiDmaDev = DMA1; | ||||
|     _settings[1].spiTxDmaChannel = DMA_CH5; | ||||
|     _settings[1].spiRxDmaChannel = DMA_CH4; | ||||
|   #endif | ||||
|   #if BOARD_NR_SPI >= 3 | ||||
|     _settings[2].spi_d = SPI3; | ||||
|     _settings[2].clockDivider = determine_baud_rate(_settings[2].spi_d, _settings[2].clock); | ||||
|     _settings[2].spiDmaDev = DMA2; | ||||
|     _settings[2].spiTxDmaChannel = DMA_CH2; | ||||
|     _settings[2].spiRxDmaChannel = DMA_CH1; | ||||
|   #endif | ||||
| 
 | ||||
|   // added for DMA callbacks.
 | ||||
|   _currentSetting->state = SPI_STATE_IDLE; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Set up/tear down | ||||
|  */ | ||||
| void SPIClass::updateSettings() { | ||||
|   uint32_t flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize | SPI_SW_SLAVE | SPI_SOFT_SS); | ||||
|   spi_master_enable(_currentSetting->spi_d, (spi_baud_rate)_currentSetting->clockDivider, (spi_mode)_currentSetting->dataMode, flags); | ||||
| } | ||||
| 
 | ||||
| void SPIClass::begin() { | ||||
|   spi_init(_currentSetting->spi_d); | ||||
|   configure_gpios(_currentSetting->spi_d, 1); | ||||
|   updateSettings(); | ||||
|   // added for DMA callbacks.
 | ||||
|   _currentSetting->state = SPI_STATE_READY; | ||||
| } | ||||
| 
 | ||||
| void SPIClass::beginSlave() { | ||||
|   spi_init(_currentSetting->spi_d); | ||||
|   configure_gpios(_currentSetting->spi_d, 0); | ||||
|   uint32_t flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize); | ||||
|   spi_slave_enable(_currentSetting->spi_d, (spi_mode)_currentSetting->dataMode, flags); | ||||
|   // added for DMA callbacks.
 | ||||
|   _currentSetting->state = SPI_STATE_READY; | ||||
| } | ||||
| 
 | ||||
| void SPIClass::end() { | ||||
|   if (!spi_is_enabled(_currentSetting->spi_d)) | ||||
|     return; | ||||
| 
 | ||||
|   // Follows RM0008's sequence for disabling a SPI in master/slave
 | ||||
|   // full duplex mode.
 | ||||
|   while (spi_is_rx_nonempty(_currentSetting->spi_d)) { | ||||
|     // FIXME [0.1.0] remove this once you have an interrupt based driver
 | ||||
|     volatile uint16_t rx __attribute__((unused)) = spi_rx_reg(_currentSetting->spi_d); | ||||
|   } | ||||
|   while (!spi_is_tx_empty(_currentSetting->spi_d)) {}; | ||||
|   while (spi_is_busy(_currentSetting->spi_d)) {}; | ||||
| 
 | ||||
|   spi_peripheral_disable(_currentSetting->spi_d); | ||||
|   // added for DMA callbacks.
 | ||||
|   // Need to add unsetting the callbacks for the DMA channels.
 | ||||
|   _currentSetting->state = SPI_STATE_IDLE; | ||||
| } | ||||
| 
 | ||||
| /* Roger Clark added  3 functions */ | ||||
| void SPIClass::setClockDivider(uint32_t clockDivider) { | ||||
|   _currentSetting->clockDivider = clockDivider; | ||||
|   uint32_t cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_BR); | ||||
|   _currentSetting->spi_d->regs->CR1 = cr1 | (clockDivider & SPI_CR1_BR); | ||||
| } | ||||
| 
 | ||||
| void SPIClass::setBitOrder(BitOrder bitOrder) { | ||||
|   _currentSetting->bitOrder = bitOrder; | ||||
|   uint32_t cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_LSBFIRST); | ||||
|   if (bitOrder == LSBFIRST) cr1 |= SPI_CR1_LSBFIRST; | ||||
|   _currentSetting->spi_d->regs->CR1 = cr1; | ||||
| } | ||||
| 
 | ||||
| /*  Victor Perez. Added to test changing datasize from 8 to 16 bit modes on the fly.
 | ||||
| * Input parameter should be SPI_CR1_DFF set to 0 or 1 on a 32bit word. | ||||
| * | ||||
| */ | ||||
| void SPIClass::setDataSize(uint32_t datasize) { | ||||
|   _currentSetting->dataSize = datasize; | ||||
|   uint32_t cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_DFF); | ||||
|   uint8_t en = spi_is_enabled(_currentSetting->spi_d); | ||||
|   spi_peripheral_disable(_currentSetting->spi_d); | ||||
|   _currentSetting->spi_d->regs->CR1 = cr1 | (datasize & SPI_CR1_DFF) | en; | ||||
| } | ||||
| 
 | ||||
| void SPIClass::setDataMode(uint8_t dataMode) { | ||||
|   /* Notes:
 | ||||
|   As far as I can tell, the AVR numbers for dataMode appear to match the numbers required by the STM32 | ||||
|   From the AVR doc http://www.atmel.com/images/doc2585.pdf section 2.4
 | ||||
|   SPI Mode  CPOL  CPHA  Shift SCK-edge  Capture SCK-edge | ||||
|   0       0     0     Falling     Rising | ||||
|   1       0     1     Rising      Falling | ||||
|   2       1     0     Rising      Falling | ||||
|   3       1     1     Falling     Rising | ||||
| 
 | ||||
|   On the STM32 it appears to be | ||||
| 
 | ||||
|   bit 1 - CPOL : Clock polarity | ||||
|     (This bit should not be changed when communication is ongoing) | ||||
|     0 : CLK to 0 when idle | ||||
|     1 : CLK to 1 when idle | ||||
| 
 | ||||
|   bit 0 - CPHA : Clock phase | ||||
|     (This bit should not be changed when communication is ongoing) | ||||
|     0 : The first clock transition is the first data capture edge | ||||
|     1 : The second clock transition is the first data capture edge | ||||
| 
 | ||||
|   If someone finds this is not the case or sees a logic error with this let me know ;-) | ||||
|   */ | ||||
|   _currentSetting->dataMode = dataMode; | ||||
|   uint32_t cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_CPOL|SPI_CR1_CPHA); | ||||
|   _currentSetting->spi_d->regs->CR1 = cr1 | (dataMode & (SPI_CR1_CPOL|SPI_CR1_CPHA)); | ||||
| } | ||||
| 
 | ||||
| void SPIClass::beginTransaction(uint8_t pin, SPISettings settings) { | ||||
|   setBitOrder(settings.bitOrder); | ||||
|   setDataMode(settings.dataMode); | ||||
|   setDataSize(settings.dataSize); | ||||
|   setClockDivider(determine_baud_rate(_currentSetting->spi_d, settings.clock)); | ||||
|   begin(); | ||||
| } | ||||
| 
 | ||||
| void SPIClass::beginTransactionSlave(SPISettings settings) { | ||||
|   setBitOrder(settings.bitOrder); | ||||
|   setDataMode(settings.dataMode); | ||||
|   setDataSize(settings.dataSize); | ||||
|   beginSlave(); | ||||
| } | ||||
| 
 | ||||
| void SPIClass::endTransaction() { } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * I/O | ||||
|  */ | ||||
| 
 | ||||
| uint16_t SPIClass::read() { | ||||
|   while ( spi_is_rx_nonempty(_currentSetting->spi_d)==0 ) ; | ||||
|   return (uint16)spi_rx_reg(_currentSetting->spi_d); | ||||
| } | ||||
| 
 | ||||
| void SPIClass::read(uint8_t *buf, uint32_t len) { | ||||
|   if (len == 0) return; | ||||
|   spi_rx_reg(_currentSetting->spi_d);   // clear the RX buffer in case a byte is waiting on it.
 | ||||
|   spi_reg_map * regs = _currentSetting->spi_d->regs; | ||||
|   // start sequence: write byte 0
 | ||||
|   regs->DR = 0x00FF;            // write the first byte
 | ||||
|   // main loop
 | ||||
|   while ( (--len) ) { | ||||
|     while( !(regs->SR & SPI_SR_TXE) ); // wait for TXE flag
 | ||||
|     noInterrupts();    // go atomic level - avoid interrupts to surely get the previously received data
 | ||||
|     regs->DR = 0x00FF; // write the next data item to be transmitted into the SPI_DR register. This clears the TXE flag.
 | ||||
|     while ( !(regs->SR & SPI_SR_RXNE) ); // wait till data is available in the DR register
 | ||||
|     *buf++ = (uint8)(regs->DR); // read and store the received byte. This clears the RXNE flag.
 | ||||
|     interrupts();      // let systick do its job
 | ||||
|   } | ||||
|   // read remaining last byte
 | ||||
|   while ( !(regs->SR & SPI_SR_RXNE) ) {} // wait till data is available in the Rx register
 | ||||
|   *buf++ = (uint8)(regs->DR);  // read and store the received byte
 | ||||
| } | ||||
| 
 | ||||
| void SPIClass::write(uint16_t data) { | ||||
|   /* Added for 16bit data Victor Perez. Roger Clark
 | ||||
|    * Improved speed by just directly writing the single byte to the SPI data reg and wait for completion, | ||||
|    * by taking the Tx code from transfer(byte) | ||||
|    * This almost doubles the speed of this function. | ||||
|    */ | ||||
|   spi_tx_reg(_currentSetting->spi_d, data); // write the data to be transmitted into the SPI_DR register (this clears the TXE flag)
 | ||||
|   while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..."
 | ||||
|   while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
 | ||||
| } | ||||
| 
 | ||||
| void SPIClass::write16(uint16_t data) { | ||||
|   // Added by stevestrong: write two consecutive bytes in 8 bit mode (DFF=0)
 | ||||
|   spi_tx_reg(_currentSetting->spi_d, data>>8); // write high byte
 | ||||
|   while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // Wait until TXE=1
 | ||||
|   spi_tx_reg(_currentSetting->spi_d, data); // write low byte
 | ||||
|   while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // Wait until TXE=1
 | ||||
|   while (spi_is_busy(_currentSetting->spi_d) != 0); // wait until BSY=0
 | ||||
| } | ||||
| 
 | ||||
| void SPIClass::write(uint16_t data, uint32_t n) { | ||||
|   // Added by stevstrong: Repeatedly send same data by the specified number of times
 | ||||
|   spi_reg_map * regs = _currentSetting->spi_d->regs; | ||||
|   while ( (n--)>0 ) { | ||||
|     regs->DR = data; // write the data to be transmitted into the SPI_DR register (this clears the TXE flag)
 | ||||
|     while ( (regs->SR & SPI_SR_TXE)==0 ) ; // wait till Tx empty
 | ||||
|   } | ||||
|   while ( (regs->SR & SPI_SR_BSY) != 0); // wait until BSY=0 before returning
 | ||||
| } | ||||
| 
 | ||||
| void SPIClass::write(const void *data, uint32_t length) { | ||||
|   spi_dev * spi_d = _currentSetting->spi_d; | ||||
|   spi_tx(spi_d, data, length); // data can be array of bytes or words
 | ||||
|   while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..."
 | ||||
|   while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
 | ||||
| } | ||||
| 
 | ||||
| uint8_t SPIClass::transfer(uint8_t byte) const { | ||||
|   spi_dev * spi_d = _currentSetting->spi_d; | ||||
|   spi_rx_reg(spi_d); // read any previous data
 | ||||
|   spi_tx_reg(spi_d, byte); // Write the data item to be transmitted into the SPI_DR register
 | ||||
|   while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..."
 | ||||
|   while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
 | ||||
|   return (uint8)spi_rx_reg(spi_d); // "... and read the last received data."
 | ||||
| } | ||||
| 
 | ||||
| uint16_t SPIClass::transfer16(uint16_t data) const { | ||||
|   // Modified by stevestrong: write & read two consecutive bytes in 8 bit mode (DFF=0)
 | ||||
|   // This is more effective than two distinct byte transfers
 | ||||
|   spi_dev * spi_d = _currentSetting->spi_d; | ||||
|   spi_rx_reg(spi_d);                   // read any previous data
 | ||||
|   spi_tx_reg(spi_d, data>>8);          // write high byte
 | ||||
|   while (spi_is_tx_empty(spi_d) == 0); // wait until TXE=1
 | ||||
|   while (spi_is_busy(spi_d) != 0);     // wait until BSY=0
 | ||||
|   uint16_t ret = spi_rx_reg(spi_d)<<8; // read and shift high byte
 | ||||
|   spi_tx_reg(spi_d, data);             // write low byte
 | ||||
|   while (spi_is_tx_empty(spi_d) == 0); // wait until TXE=1
 | ||||
|   while (spi_is_busy(spi_d) != 0);     // wait until BSY=0
 | ||||
|   ret += spi_rx_reg(spi_d);            // read low byte
 | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| /*  Roger Clark and Victor Perez, 2015
 | ||||
| * Performs a DMA SPI transfer with at least a receive buffer. | ||||
| * If a TX buffer is not provided, FF is sent over and over for the lenght of the transfer. | ||||
| * On exit TX buffer is not modified, and RX buffer cotains the received data. | ||||
| * Still in progress. | ||||
| */ | ||||
| void SPIClass::dmaTransferSet(const void *transmitBuf, void *receiveBuf) { | ||||
|   dma_init(_currentSetting->spiDmaDev); | ||||
|   //spi_rx_dma_enable(_currentSetting->spi_d);
 | ||||
|   //spi_tx_dma_enable(_currentSetting->spi_d);
 | ||||
|   dma_xfer_size dma_bit_size = (_currentSetting->dataSize==DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS; | ||||
|   dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &_currentSetting->spi_d->regs->DR, | ||||
|       dma_bit_size, receiveBuf, dma_bit_size, (DMA_MINC_MODE | DMA_TRNS_CMPLT ));// receive buffer DMA
 | ||||
|   if (!transmitBuf) { | ||||
|     transmitBuf = &ff; | ||||
|     dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, | ||||
|         dma_bit_size, (volatile void*)transmitBuf, dma_bit_size, (DMA_FROM_MEM));// Transmit FF repeatedly
 | ||||
|   } | ||||
|   else { | ||||
|     dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, | ||||
|         dma_bit_size, (volatile void*)transmitBuf, dma_bit_size, (DMA_MINC_MODE |  DMA_FROM_MEM ));// Transmit buffer DMA
 | ||||
|   } | ||||
|   dma_set_priority(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, DMA_PRIORITY_LOW); | ||||
|   dma_set_priority(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, DMA_PRIORITY_VERY_HIGH); | ||||
| } | ||||
| 
 | ||||
| uint8_t SPIClass::dmaTransferRepeat(uint16_t length) { | ||||
|   if (length == 0) return 0; | ||||
|   if (spi_is_rx_nonempty(_currentSetting->spi_d) == 1) spi_rx_reg(_currentSetting->spi_d); | ||||
|   _currentSetting->state = SPI_STATE_TRANSFER; | ||||
|   dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, length); | ||||
|   dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); | ||||
|   dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel);// enable receive
 | ||||
|   dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit
 | ||||
|   spi_rx_dma_enable(_currentSetting->spi_d); | ||||
|   spi_tx_dma_enable(_currentSetting->spi_d); | ||||
|   if (_currentSetting->receiveCallback) | ||||
|     return 0; | ||||
| 
 | ||||
|   //uint32_t m = millis();
 | ||||
|   uint8_t b = 0; | ||||
|   uint32_t m = millis(); | ||||
|   while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & DMA_ISR_TCIF1) == 0) { | ||||
|     //Avoid interrupts and just loop waiting for the flag to be set.
 | ||||
|     if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; } | ||||
|   } | ||||
| 
 | ||||
|   while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..."
 | ||||
|   while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
 | ||||
|   spi_tx_dma_disable(_currentSetting->spi_d); | ||||
|   spi_rx_dma_disable(_currentSetting->spi_d); | ||||
|   dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); | ||||
|   dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel); | ||||
|   dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel); | ||||
|   dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); | ||||
|   _currentSetting->state = SPI_STATE_READY; | ||||
|   return b; | ||||
| } | ||||
| 
 | ||||
| /* Roger Clark and Victor Perez, 2015
 | ||||
|  * Performs a DMA SPI transfer with at least a receive buffer. | ||||
|  * If a TX buffer is not provided, FF is sent over and over for the length of the transfer. | ||||
|  * On exit TX buffer is not modified, and RX buffer contains the received data. | ||||
|  * Still in progress. | ||||
|  */ | ||||
| uint8_t SPIClass::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length) { | ||||
|   dmaTransferSet(transmitBuf, receiveBuf); | ||||
|   return dmaTransferRepeat(length); | ||||
| } | ||||
| 
 | ||||
| /* Roger Clark and Victor Perez, 2015
 | ||||
|  * Performs a DMA SPI send using a TX buffer. | ||||
|  * On exit TX buffer is not modified. | ||||
|  * Still in progress. | ||||
|  * 2016 - stevstrong - reworked to automatically detect bit size from SPI setting | ||||
|  */ | ||||
| void SPIClass::dmaSendSet(const void * transmitBuf, bool minc) { | ||||
|   uint32_t flags = ( (DMA_MINC_MODE*minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT); | ||||
|   dma_init(_currentSetting->spiDmaDev); | ||||
|   dma_xfer_size dma_bit_size = (_currentSetting->dataSize==DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS; | ||||
|   dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size, | ||||
|              (volatile void*)transmitBuf, dma_bit_size, flags);// Transmit buffer DMA
 | ||||
|   dma_set_priority(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, DMA_PRIORITY_LOW); | ||||
| } | ||||
| 
 | ||||
| uint8_t SPIClass::dmaSendRepeat(uint16_t length) { | ||||
|   if (length == 0) return 0; | ||||
| 
 | ||||
|   dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); | ||||
|   dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); | ||||
|   _currentSetting->state = SPI_STATE_TRANSMIT; | ||||
|   dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit
 | ||||
|   spi_tx_dma_enable(_currentSetting->spi_d); | ||||
|   if (_currentSetting->transmitCallback) | ||||
|     return 0; | ||||
| 
 | ||||
|   uint32_t m = millis(); | ||||
|   uint8_t b = 0; | ||||
|   while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & DMA_ISR_TCIF1)==0) { | ||||
|     //Avoid interrupts and just loop waiting for the flag to be set.
 | ||||
|     if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; } | ||||
|   } | ||||
|   while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..."
 | ||||
|   while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
 | ||||
|   spi_tx_dma_disable(_currentSetting->spi_d); | ||||
|   dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); | ||||
|   dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); | ||||
|   _currentSetting->state = SPI_STATE_READY; | ||||
|   return b; | ||||
| } | ||||
| 
 | ||||
| uint8_t SPIClass::dmaSend(const void * transmitBuf, uint16_t length, bool minc) { | ||||
|   dmaSendSet(transmitBuf, minc); | ||||
|   return dmaSendRepeat(length); | ||||
| } | ||||
| 
 | ||||
| uint8_t SPIClass::dmaSendAsync(const void * transmitBuf, uint16_t length, bool minc) { | ||||
|   uint8_t b = 0; | ||||
| 
 | ||||
|   if (_currentSetting->state != SPI_STATE_READY) { | ||||
|     uint32_t m = millis(); | ||||
|     while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & DMA_ISR_TCIF1)==0) { | ||||
|       //Avoid interrupts and just loop waiting for the flag to be set.
 | ||||
|       //delayMicroseconds(10);
 | ||||
|       if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; } | ||||
|     } | ||||
| 
 | ||||
|     while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..."
 | ||||
|     while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
 | ||||
|     spi_tx_dma_disable(_currentSetting->spi_d); | ||||
|     dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); | ||||
|     _currentSetting->state = SPI_STATE_READY; | ||||
|   } | ||||
| 
 | ||||
|   if (length == 0) return 0; | ||||
|   uint32_t flags = ( (DMA_MINC_MODE*minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT); | ||||
| 
 | ||||
|   dma_init(_currentSetting->spiDmaDev); | ||||
|   // TX
 | ||||
|   dma_xfer_size dma_bit_size = (_currentSetting->dataSize==DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS; | ||||
|   dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, | ||||
|       dma_bit_size, (volatile void*)transmitBuf, dma_bit_size, flags);// Transmit buffer DMA
 | ||||
|   dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); | ||||
|   dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); | ||||
|   dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit
 | ||||
|   spi_tx_dma_enable(_currentSetting->spi_d); | ||||
| 
 | ||||
|   _currentSetting->state = SPI_STATE_TRANSMIT; | ||||
|   return b; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  *  New functions added to manage callbacks. | ||||
|  *  Victor Perez 2017 | ||||
|  */ | ||||
| void SPIClass::onReceive(void(*callback)(void)) { | ||||
|   _currentSetting->receiveCallback = callback; | ||||
|   if (callback) { | ||||
|     switch (_currentSetting->spi_d->clk_id) { | ||||
|     #if BOARD_NR_SPI >= 1 | ||||
|     case RCC_SPI1: | ||||
|       dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi1EventCallback); | ||||
|       break; | ||||
|     #endif | ||||
|     #if BOARD_NR_SPI >= 2 | ||||
|     case RCC_SPI2: | ||||
|       dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi2EventCallback); | ||||
|       break; | ||||
|     #endif | ||||
|     #if BOARD_NR_SPI >= 3 | ||||
|     case RCC_SPI3: | ||||
|       dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi3EventCallback); | ||||
|       break; | ||||
|     #endif | ||||
|     default: | ||||
|       ASSERT(0); | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|     dma_detach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void SPIClass::onTransmit(void(*callback)(void)) { | ||||
|   _currentSetting->transmitCallback = callback; | ||||
|   if (callback) { | ||||
|     switch (_currentSetting->spi_d->clk_id) { | ||||
|     #if BOARD_NR_SPI >= 1 | ||||
|     case RCC_SPI1: | ||||
|       dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi1EventCallback); | ||||
|       break; | ||||
|     #endif | ||||
|     #if BOARD_NR_SPI >= 2 | ||||
|      case RCC_SPI2: | ||||
|       dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi2EventCallback); | ||||
|       break; | ||||
|     #endif | ||||
|     #if BOARD_NR_SPI >= 3 | ||||
|     case RCC_SPI3: | ||||
|       dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi3EventCallback); | ||||
|       break; | ||||
|     #endif | ||||
|     default: | ||||
|       ASSERT(0); | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|     dma_detach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * TODO: check if better to first call the customer code, next disable the DMA requests. | ||||
|  * Also see if we need to check whether callbacks are set or not, may be better to be checked | ||||
|  * during the initial setup and only set the callback to EventCallback if they are set. | ||||
|  */ | ||||
| void SPIClass::EventCallback() { | ||||
|   while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..."
 | ||||
|   while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0"
 | ||||
|   switch (_currentSetting->state) { | ||||
|   case SPI_STATE_TRANSFER: | ||||
|     while (spi_is_rx_nonempty(_currentSetting->spi_d)); | ||||
|     _currentSetting->state = SPI_STATE_READY; | ||||
|     spi_tx_dma_disable(_currentSetting->spi_d); | ||||
|     spi_rx_dma_disable(_currentSetting->spi_d); | ||||
|     //dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
 | ||||
|     //dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel);
 | ||||
|     if (_currentSetting->receiveCallback) | ||||
|       _currentSetting->receiveCallback(); | ||||
|     break; | ||||
|   case SPI_STATE_TRANSMIT: | ||||
|     _currentSetting->state = SPI_STATE_READY; | ||||
|     spi_tx_dma_disable(_currentSetting->spi_d); | ||||
|     //dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
 | ||||
|     if (_currentSetting->transmitCallback) | ||||
|       _currentSetting->transmitCallback(); | ||||
|     break; | ||||
|   default: | ||||
|     break; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void SPIClass::attachInterrupt() { | ||||
|   // Should be enableInterrupt()
 | ||||
| } | ||||
| 
 | ||||
| void SPIClass::detachInterrupt() { | ||||
|   // Should be disableInterrupt()
 | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Pin accessors | ||||
|  */ | ||||
| 
 | ||||
| uint8_t SPIClass::misoPin() { | ||||
|   return dev_to_spi_pins(_currentSetting->spi_d)->miso; | ||||
| } | ||||
| 
 | ||||
| uint8_t SPIClass::mosiPin() { | ||||
|   return dev_to_spi_pins(_currentSetting->spi_d)->mosi; | ||||
| } | ||||
| 
 | ||||
| uint8_t SPIClass::sckPin() { | ||||
|   return dev_to_spi_pins(_currentSetting->spi_d)->sck; | ||||
| } | ||||
| 
 | ||||
| uint8_t SPIClass::nssPin() { | ||||
|   return dev_to_spi_pins(_currentSetting->spi_d)->nss; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Deprecated functions | ||||
|  */ | ||||
| 
 | ||||
| uint8_t SPIClass::send(uint8_t data) { | ||||
|   this->write(data); | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| uint8_t SPIClass::send(uint8_t *buf, uint32_t len) { | ||||
|   this->write(buf, len); | ||||
|   return len; | ||||
| } | ||||
| 
 | ||||
| uint8_t SPIClass::recv() { | ||||
|   return this->read(); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * DMA call back functions, one per port. | ||||
|  */ | ||||
| #if BOARD_NR_SPI >= 1 | ||||
|   void SPIClass::_spi1EventCallback() { | ||||
|     reinterpret_cast<class SPIClass*>(_spi1_this)->EventCallback(); | ||||
|   } | ||||
| #endif | ||||
| #if BOARD_NR_SPI >= 2 | ||||
|   void SPIClass::_spi2EventCallback() { | ||||
|     reinterpret_cast<class SPIClass*>(_spi2_this)->EventCallback(); | ||||
|   } | ||||
| #endif | ||||
| #if BOARD_NR_SPI >= 3 | ||||
|   void SPIClass::_spi3EventCallback() { | ||||
|     reinterpret_cast<class SPIClass*>(_spi3_this)->EventCallback(); | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * Auxiliary functions | ||||
|  */ | ||||
| static const spi_pins* dev_to_spi_pins(spi_dev *dev) { | ||||
|   switch (dev->clk_id) { | ||||
|     #if BOARD_NR_SPI >= 1 | ||||
|       case RCC_SPI1: return board_spi_pins; | ||||
|     #endif | ||||
|     #if BOARD_NR_SPI >= 2 | ||||
|       case RCC_SPI2: return board_spi_pins + 1; | ||||
|     #endif | ||||
|     #if BOARD_NR_SPI >= 3 | ||||
|       case RCC_SPI3: return board_spi_pins + 2; | ||||
|     #endif | ||||
|     default: return NULL; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static void disable_pwm(const stm32_pin_info *i) { | ||||
|   if (i->timer_device) | ||||
|     timer_set_mode(i->timer_device, i->timer_channel, TIMER_DISABLED); | ||||
| } | ||||
| 
 | ||||
| static void configure_gpios(spi_dev *dev, bool as_master) { | ||||
|   const spi_pins *pins = dev_to_spi_pins(dev); | ||||
|   if (!pins) return; | ||||
| 
 | ||||
|   const stm32_pin_info *nssi = &PIN_MAP[pins->nss], | ||||
|                        *scki = &PIN_MAP[pins->sck], | ||||
|                        *misoi = &PIN_MAP[pins->miso], | ||||
|                        *mosii = &PIN_MAP[pins->mosi]; | ||||
| 
 | ||||
|   disable_pwm(nssi); | ||||
|   disable_pwm(scki); | ||||
|   disable_pwm(misoi); | ||||
|   disable_pwm(mosii); | ||||
| 
 | ||||
|   spi_config_gpios(dev, as_master, nssi->gpio_device, nssi->gpio_bit, | ||||
|   scki->gpio_device, scki->gpio_bit, misoi->gpio_bit, | ||||
|   mosii->gpio_bit); | ||||
| } | ||||
| 
 | ||||
| static const spi_baud_rate baud_rates[8] __FLASH__ = { | ||||
|   SPI_BAUD_PCLK_DIV_2, | ||||
|   SPI_BAUD_PCLK_DIV_4, | ||||
|   SPI_BAUD_PCLK_DIV_8, | ||||
|   SPI_BAUD_PCLK_DIV_16, | ||||
|   SPI_BAUD_PCLK_DIV_32, | ||||
|   SPI_BAUD_PCLK_DIV_64, | ||||
|   SPI_BAUD_PCLK_DIV_128, | ||||
|   SPI_BAUD_PCLK_DIV_256, | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
| * Note: This assumes you're on a LeafLabs-style board | ||||
| * (CYCLES_PER_MICROSECOND == 72, APB2 at 72MHz, APB1 at 36MHz). | ||||
| */ | ||||
| static spi_baud_rate determine_baud_rate(spi_dev *dev, uint32_t freq) { | ||||
|   uint32_t clock = 0; | ||||
|   switch (rcc_dev_clk(dev->clk_id)) { | ||||
|     case RCC_AHB: | ||||
|     case RCC_APB2: clock = STM32_PCLK2; break; // 72 Mhz
 | ||||
|     case RCC_APB1: clock = STM32_PCLK1; break; // 36 Mhz
 | ||||
|   } | ||||
|   clock >>= 1; | ||||
| 
 | ||||
|   uint8_t i = 0; | ||||
|   while (i < 7 && freq < clock) { clock >>= 1; i++; } | ||||
|   return baud_rates[i]; | ||||
| } | ||||
| 
 | ||||
| SPIClass SPI(1); | ||||
| 
 | ||||
| #endif // __STM32F1__
 | ||||
							
								
								
									
										409
									
								
								Marlin/src/HAL/HAL_STM32F1/SPI.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										409
									
								
								Marlin/src/HAL/HAL_STM32F1/SPI.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,409 @@ | ||||
| /******************************************************************************
 | ||||
|  * The MIT License | ||||
|  * | ||||
|  * Copyright (c) 2010 Perry Hung. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person | ||||
|  * obtaining a copy of this software and associated documentation | ||||
|  * files (the "Software"), to deal in the Software without | ||||
|  * restriction, including without limitation the rights to use, copy, | ||||
|  * modify, merge, publish, distribute, sublicense, and/or sell copies | ||||
|  * of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||||
|  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  *****************************************************************************/ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <libmaple/libmaple_types.h> | ||||
| #include <libmaple/spi.h> | ||||
| #include <libmaple/dma.h> | ||||
| 
 | ||||
| #include <boards.h> | ||||
| #include <stdint.h> | ||||
| #include <wirish.h> | ||||
| 
 | ||||
| // SPI_HAS_TRANSACTION means SPI has
 | ||||
| //   - beginTransaction()
 | ||||
| //   - endTransaction()
 | ||||
| //   - usingInterrupt()
 | ||||
| //   - SPISetting(clock, bitOrder, dataMode)
 | ||||
| //#define SPI_HAS_TRANSACTION
 | ||||
| 
 | ||||
| #define SPI_CLOCK_DIV2   SPI_BAUD_PCLK_DIV_2 | ||||
| #define SPI_CLOCK_DIV4   SPI_BAUD_PCLK_DIV_4 | ||||
| #define SPI_CLOCK_DIV8   SPI_BAUD_PCLK_DIV_8 | ||||
| #define SPI_CLOCK_DIV16  SPI_BAUD_PCLK_DIV_16 | ||||
| #define SPI_CLOCK_DIV32  SPI_BAUD_PCLK_DIV_32 | ||||
| #define SPI_CLOCK_DIV64  SPI_BAUD_PCLK_DIV_64 | ||||
| #define SPI_CLOCK_DIV128 SPI_BAUD_PCLK_DIV_128 | ||||
| #define SPI_CLOCK_DIV256 SPI_BAUD_PCLK_DIV_256 | ||||
| 
 | ||||
| /*
 | ||||
|  * Roger Clark. 20150106 | ||||
|  * Commented out redundant AVR defined | ||||
|  * | ||||
| #define SPI_MODE_MASK 0x0C     // CPOL = bit 3, CPHA = bit 2 on SPCR
 | ||||
| #define SPI_CLOCK_MASK 0x03    // SPR1 = bit 1, SPR0 = bit 0 on SPCR
 | ||||
| #define SPI_2XCLOCK_MASK 0x01  // SPI2X = bit 0 on SPSR
 | ||||
| 
 | ||||
| // define SPI_AVR_EIMSK for AVR boards with external interrupt pins
 | ||||
| #if defined(EIMSK) | ||||
|   #define SPI_AVR_EIMSK EIMSK | ||||
| #elif defined(GICR) | ||||
|   #define SPI_AVR_EIMSK GICR | ||||
| #elif defined(GIMSK) | ||||
|   #define SPI_AVR_EIMSK GIMSK | ||||
| #endif | ||||
| */ | ||||
| 
 | ||||
| #ifndef STM32_LSBFIRST | ||||
|   #define STM32_LSBFIRST 0 | ||||
| #endif | ||||
| #ifndef STM32_MSBFIRST | ||||
|   #define STM32_MSBFIRST 1 | ||||
| #endif | ||||
| 
 | ||||
| // PC13 or PA4
 | ||||
| #define BOARD_SPI_DEFAULT_SS PA4 | ||||
| //#define BOARD_SPI_DEFAULT_SS PC13
 | ||||
| 
 | ||||
| #define SPI_MODE0 SPI_MODE_0 | ||||
| #define SPI_MODE1 SPI_MODE_1 | ||||
| #define SPI_MODE2 SPI_MODE_2 | ||||
| #define SPI_MODE3 SPI_MODE_3 | ||||
| 
 | ||||
| #define DATA_SIZE_8BIT SPI_CR1_DFF_8_BIT | ||||
| #define DATA_SIZE_16BIT SPI_CR1_DFF_16_BIT | ||||
| 
 | ||||
| typedef enum { | ||||
|   SPI_STATE_IDLE, | ||||
|   SPI_STATE_READY, | ||||
|   SPI_STATE_RECEIVE, | ||||
|   SPI_STATE_TRANSMIT, | ||||
|   SPI_STATE_TRANSFER | ||||
| } spi_mode_t; | ||||
| 
 | ||||
| class SPISettings { | ||||
| public: | ||||
|   SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { | ||||
|     if (__builtin_constant_p(clock)) | ||||
|       init_AlwaysInline(clock, bitOrder, dataMode, DATA_SIZE_8BIT); | ||||
|     else | ||||
|       init_MightInline(clock, bitOrder, dataMode, DATA_SIZE_8BIT); | ||||
|   } | ||||
|   SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) { | ||||
|     if (__builtin_constant_p(clock)) | ||||
|       init_AlwaysInline(clock, bitOrder, dataMode, dataSize); | ||||
|     else | ||||
|       init_MightInline(clock, bitOrder, dataMode, dataSize); | ||||
|   } | ||||
|   SPISettings(uint32_t clock) { | ||||
|     if (__builtin_constant_p(clock)) | ||||
|       init_AlwaysInline(clock, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT); | ||||
|     else | ||||
|       init_MightInline(clock, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT); | ||||
|   } | ||||
|   SPISettings() { | ||||
|     init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT); | ||||
|   } | ||||
| private: | ||||
|   void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) { | ||||
|     init_AlwaysInline(clock, bitOrder, dataMode, dataSize); | ||||
|   } | ||||
|   void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) __attribute__((__always_inline__)) { | ||||
|     this->clock = clock; | ||||
|     this->bitOrder = bitOrder; | ||||
|     this->dataMode = dataMode; | ||||
|     this->dataSize = dataSize; | ||||
|   } | ||||
|   uint32_t clock; | ||||
|   uint32_t dataSize; | ||||
|   uint32_t clockDivider; | ||||
|   BitOrder bitOrder; | ||||
|   uint8_t dataMode; | ||||
|   uint8_t _SSPin; | ||||
|   volatile spi_mode_t state; | ||||
|   spi_dev *spi_d; | ||||
|   dma_channel spiRxDmaChannel, spiTxDmaChannel; | ||||
|   dma_dev* spiDmaDev; | ||||
|   void (*receiveCallback)(void) = NULL; | ||||
|   void (*transmitCallback)(void) = NULL; | ||||
| 
 | ||||
|   friend class SPIClass; | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * Kept for compat. | ||||
|  */ | ||||
| static const uint8_t ff = 0xFF; | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Wirish SPI interface. | ||||
|  * | ||||
|  * This implementation uses software slave management, so the caller | ||||
|  * is responsible for controlling the slave select line. | ||||
|  */ | ||||
| class SPIClass { | ||||
| 
 | ||||
| public: | ||||
|   /**
 | ||||
|    * @param spiPortNumber Number of the SPI port to manage. | ||||
|    */ | ||||
|   SPIClass(uint32_t spiPortNumber); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0). | ||||
|    */ | ||||
|   void begin(); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Turn on a SPI port and set its GPIO pin modes for use as a slave. | ||||
|    * | ||||
|    * SPI port is enabled in full duplex mode, with software slave management. | ||||
|    * | ||||
|    * @param bitOrder Either LSBFIRST (little-endian) or MSBFIRST(big-endian) | ||||
|    * @param mode SPI mode to use | ||||
|    */ | ||||
|   void beginSlave(uint32_t bitOrder, uint32_t mode); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Equivalent to beginSlave(MSBFIRST, 0). | ||||
|    */ | ||||
|   void beginSlave(); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Disables the SPI port, but leaves its GPIO pin modes unchanged. | ||||
|    */ | ||||
|   void end(); | ||||
| 
 | ||||
|   void beginTransaction(SPISettings settings) { beginTransaction(BOARD_SPI_DEFAULT_SS, settings); } | ||||
|   void beginTransaction(uint8_t pin, SPISettings settings); | ||||
|   void endTransaction(); | ||||
| 
 | ||||
|   void beginTransactionSlave(SPISettings settings); | ||||
| 
 | ||||
|   void setClockDivider(uint32_t clockDivider); | ||||
|   void setBitOrder(BitOrder bitOrder); | ||||
|   void setDataMode(uint8_t dataMode); | ||||
| 
 | ||||
|   // SPI Configuration methods
 | ||||
|   void attachInterrupt(); | ||||
|   void detachInterrupt(); | ||||
| 
 | ||||
|   /* Victor Perez. Added to change datasize from 8 to 16 bit modes on the fly.
 | ||||
|    * Input parameter should be SPI_CR1_DFF set to 0 or 1 on a 32bit word. | ||||
|    * Requires an added function spi_data_size on STM32F1 / cores / maple / libmaple / spi.c | ||||
|    */ | ||||
|   void setDataSize(uint32_t ds); | ||||
| 
 | ||||
|   /* Victor Perez 2017. Added to set and clear callback functions for callback
 | ||||
|    * on DMA transfer completion. | ||||
|    * onReceive used to set the callback in case of dmaTransfer (tx/rx), once rx is completed | ||||
|    * onTransmit used to set the callback in case of dmaSend (tx only). That function | ||||
|    * will NOT be called in case of TX/RX | ||||
|    */ | ||||
|   void onReceive(void(*)(void)); | ||||
|   void onTransmit(void(*)(void)); | ||||
| 
 | ||||
|   /*
 | ||||
|    * I/O | ||||
|    */ | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Return the next unread byte/word. | ||||
|    * | ||||
|    * If there is no unread byte/word waiting, this function will block | ||||
|    * until one is received. | ||||
|    */ | ||||
|   uint16_t read(); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Read length bytes, storing them into buffer. | ||||
|    * @param buffer Buffer to store received bytes into. | ||||
|    * @param length Number of bytes to store in buffer. This | ||||
|    *               function will block until the desired number of | ||||
|    *               bytes have been read. | ||||
|    */ | ||||
|   void read(uint8_t *buffer, uint32_t length); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Transmit one byte/word. | ||||
|    * @param data to transmit. | ||||
|    */ | ||||
|   void write(uint16_t data); | ||||
|   void write16(uint16_t data); // write 2 bytes in 8 bit mode (DFF=0)
 | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Transmit one byte/word a specified number of times. | ||||
|    * @param data to transmit. | ||||
|    */ | ||||
|   void write(uint16_t data, uint32_t n); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Transmit multiple bytes/words. | ||||
|    * @param buffer Bytes/words to transmit. | ||||
|    * @param length Number of bytes/words in buffer to transmit. | ||||
|    */ | ||||
|   void write(const void * buffer, uint32_t length); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Transmit a byte, then return the next unread byte. | ||||
|    * | ||||
|    * This function transmits before receiving. | ||||
|    * | ||||
|    * @param data Byte to transmit. | ||||
|    * @return Next unread byte. | ||||
|    */ | ||||
|   uint8_t transfer(uint8_t data) const; | ||||
|   uint16_t transfer16(uint16_t data) const; | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Sets up a DMA Transfer for "length" bytes. | ||||
|    * The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting. | ||||
|    * | ||||
|    * This function transmits and receives to buffers. | ||||
|    * | ||||
|    * @param transmitBuf buffer Bytes to transmit. If passed as 0, it sends FF repeatedly for "length" bytes | ||||
|    * @param receiveBuf buffer Bytes to save received data. | ||||
|    * @param length Number of bytes in buffer to transmit. | ||||
|    */ | ||||
|   uint8_t dmaTransfer(const void * transmitBuf, void * receiveBuf, uint16_t length); | ||||
|   void dmaTransferSet(const void *transmitBuf, void *receiveBuf); | ||||
|   uint8_t dmaTransferRepeat(uint16_t length); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Sets up a DMA Transmit for SPI 8 or 16 bit transfer mode. | ||||
|    * The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting. | ||||
|    * | ||||
|    * This function only transmits and does not care about the RX fifo. | ||||
|    * | ||||
|    * @param data buffer half words to transmit, | ||||
|    * @param length Number of bytes in buffer to transmit. | ||||
|    * @param minc Set to use Memory Increment mode, clear to use Circular mode. | ||||
|    */ | ||||
|   uint8_t dmaSend(const void * transmitBuf, uint16_t length, bool minc = 1); | ||||
|   void dmaSendSet(const void * transmitBuf, bool minc); | ||||
|   uint8_t dmaSendRepeat(uint16_t length); | ||||
| 
 | ||||
|   uint8_t dmaSendAsync(const void * transmitBuf, uint16_t length, bool minc = 1); | ||||
|   /*
 | ||||
|    * Pin accessors | ||||
|    */ | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Return the number of the MISO (master in, slave out) pin | ||||
|    */ | ||||
|   uint8_t misoPin(); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Return the number of the MOSI (master out, slave in) pin | ||||
|    */ | ||||
|   uint8_t mosiPin(); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Return the number of the SCK (serial clock) pin | ||||
|    */ | ||||
|   uint8_t sckPin(); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Return the number of the NSS (slave select) pin | ||||
|    */ | ||||
|   uint8_t nssPin(); | ||||
| 
 | ||||
|   /* Escape hatch */ | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Get a pointer to the underlying libmaple spi_dev for | ||||
|    *        this HardwareSPI instance. | ||||
|    */ | ||||
|   spi_dev* c_dev(void) { return _currentSetting->spi_d; } | ||||
| 
 | ||||
|   spi_dev* dev() { return _currentSetting->spi_d; } | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Sets the number of the SPI peripheral to be used by | ||||
|    *        this HardwareSPI instance. | ||||
|    * | ||||
|    * @param spi_num Number of the SPI port. 1-2 in low density devices | ||||
|    *     or 1-3 in high density devices. | ||||
|    */ | ||||
|   void setModule(int spi_num) { | ||||
|     _currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed
 | ||||
|   } | ||||
| 
 | ||||
|   /* -- The following methods are deprecated --------------------------- */ | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Deprecated. | ||||
|    * | ||||
|    * Use HardwareSPI::transfer() instead. | ||||
|    * | ||||
|    * @see HardwareSPI::transfer() | ||||
|    */ | ||||
|   uint8_t send(uint8_t data); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Deprecated. | ||||
|    * | ||||
|    * Use HardwareSPI::write() in combination with | ||||
|    * HardwareSPI::read() (or HardwareSPI::transfer()) instead. | ||||
|    * | ||||
|    * @see HardwareSPI::write() | ||||
|    * @see HardwareSPI::read() | ||||
|    * @see HardwareSPI::transfer() | ||||
|    */ | ||||
|   uint8_t send(uint8_t *data, uint32_t length); | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief Deprecated. | ||||
|    * | ||||
|    * Use HardwareSPI::read() instead. | ||||
|    * | ||||
|    * @see HardwareSPI::read() | ||||
|    */ | ||||
|   uint8_t recv(); | ||||
| 
 | ||||
| private: | ||||
| 
 | ||||
|   SPISettings _settings[BOARD_NR_SPI]; | ||||
|   SPISettings *_currentSetting; | ||||
| 
 | ||||
|   void updateSettings(); | ||||
| 
 | ||||
|   /*
 | ||||
|    * Functions added for DMA transfers with Callback. | ||||
|    * Experimental. | ||||
|    */ | ||||
| 
 | ||||
|   void EventCallback(); | ||||
| 
 | ||||
|   #if BOARD_NR_SPI >= 1 | ||||
|     static void _spi1EventCallback(); | ||||
|   #endif | ||||
|   #if BOARD_NR_SPI >= 2 | ||||
|     static void _spi2EventCallback(); | ||||
|   #endif | ||||
|   #if BOARD_NR_SPI >= 3 | ||||
|     static void _spi3EventCallback(); | ||||
|   #endif | ||||
|   /*
 | ||||
|   spi_dev *spi_d; | ||||
|   uint8_t _SSPin; | ||||
|   uint32_t clockDivider; | ||||
|   uint8_t dataMode; | ||||
|   BitOrder bitOrder; | ||||
|   */ | ||||
| }; | ||||
| 
 | ||||
| extern SPIClass SPI; | ||||
| @ -38,8 +38,8 @@ | ||||
| #define _SET_OUTPUT(IO)       _SET_MODE(IO, GPIO_OUTPUT_PP) | ||||
| #define _SET_OUTPUT_OD(IO)    _SET_MODE(IO, GPIO_OUTPUT_OD) | ||||
| 
 | ||||
| #define OUT_WRITE(IO,V)       do{ _SET_OUTPUT(IO); WRITE(IO,V); } while(0) | ||||
| #define OUT_WRITE_OD(IO,V)    do{ _SET_OUTPUT_OD(IO); WRITE(IO,V); } while(0) | ||||
| #define OUT_WRITE(IO,V)       do{ _SET_OUTPUT(IO); WRITE(IO,V); }while(0) | ||||
| #define OUT_WRITE_OD(IO,V)    do{ _SET_OUTPUT_OD(IO); WRITE(IO,V); }while(0) | ||||
| 
 | ||||
| #define SET_INPUT(IO)         _SET_MODE(IO, GPIO_INPUT_FLOATING) | ||||
| #define SET_INPUT_PULLUP(IO)  _SET_MODE(IO, GPIO_INPUT_PU) | ||||
|  | ||||
| @ -42,7 +42,6 @@ | ||||
| // Store settings in the last two pages
 | ||||
| // Flash pages must be erased before writing, so keep track.
 | ||||
| bool firstWrite = false; | ||||
| uint32_t pageBase = EEPROM_START_ADDRESS; | ||||
| 
 | ||||
| bool PersistentStore::access_start() { | ||||
|   firstWrite = true; | ||||
| @ -67,42 +66,27 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui | ||||
|     firstWrite = false; | ||||
|   } | ||||
| 
 | ||||
|   // First write full words
 | ||||
|   int i = 0; | ||||
|   int wordsToWrite = size / sizeof(uint16_t); | ||||
|   uint16_t* wordBuffer = (uint16_t *)value; | ||||
|   while (wordsToWrite) { | ||||
|     status = FLASH_ProgramHalfWord(pageBase + pos + (i * 2), wordBuffer[i]); | ||||
|     if (status != FLASH_COMPLETE) return true; | ||||
|     wordsToWrite--; | ||||
|     i++; | ||||
|   } | ||||
| 
 | ||||
|   // Now, write any remaining single byte
 | ||||
|   const uint16_t odd = size & 1; | ||||
|   if (odd) { | ||||
|     uint16_t temp = value[size - 1]; | ||||
|     status = FLASH_ProgramHalfWord(pageBase + pos + i, temp); | ||||
|     if (status != FLASH_COMPLETE) return true; | ||||
|   for (size_t i = 0; i < size; i++) { | ||||
|     if (FLASH_ProgramHalfWord(EEPROM_PAGE0_BASE + (pos + i) * 2, value[i]) != FLASH_COMPLETE) | ||||
|       return true; | ||||
|   } | ||||
| 
 | ||||
|   crc16(crc, value, size); | ||||
|   pos += size + odd; | ||||
|   pos += size; | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| bool PersistentStore::read_data(int &pos, uint8_t* value, const size_t size, uint16_t *crc, const bool writing/*=true*/) { | ||||
|   for (uint16_t i = 0; i < size; i++) { | ||||
|     byte* accessPoint = (byte*)(pageBase + pos + i); | ||||
|     uint8_t c = *accessPoint; | ||||
|     if (writing) value[i] = c; | ||||
|     crc16(crc, &c, 1); | ||||
|   for (size_t i = 0; i < size; i++) { | ||||
|     uint8_t v = *(uint16_t *)(EEPROM_PAGE0_BASE + (pos + i) * 2); | ||||
|     if (writing) value[i] = v; | ||||
|     crc16(crc, &v, 1); | ||||
|   } | ||||
|   pos += ((size + 1) & ~1); // i.e., size+(size&1), round up odd values
 | ||||
|   pos += size; | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| size_t PersistentStore::capacity() { return E2END + 1; } | ||||
| size_t PersistentStore::capacity() { return size_t(E2END + 1); } | ||||
| 
 | ||||
| #endif // EEPROM_SETTINGS && EEPROM FLASH
 | ||||
| #endif // __STM32F1__
 | ||||
|  | ||||
| @ -53,56 +53,40 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { | ||||
|     switch (timer_num) { | ||||
|       case STEP_TIMER_NUM: | ||||
|         // STEPPER TIMER TIM5 - use a 32bit timer
 | ||||
|         #ifdef STM32GENERIC | ||||
|           __HAL_RCC_TIM5_CLK_ENABLE(); | ||||
|           TimerHandle[timer_num].handle.Instance            = TIM5; | ||||
|           TimerHandle[timer_num].handle.Init.Prescaler      = step_prescaler; | ||||
|           TimerHandle[timer_num].handle.Init.CounterMode    = TIM_COUNTERMODE_UP; | ||||
|           TimerHandle[timer_num].handle.Init.ClockDivision  = TIM_CLOCKDIVISION_DIV1; | ||||
|           TimerHandle[timer_num].callback = (uint32_t)TC5_Handler; | ||||
|         #else | ||||
|           TimerHandle[timer_num].timer = TIM5; | ||||
|           TimerHandle[timer_num].irqHandle = TC5_Handler; | ||||
|           TimerHandleInit(&TimerHandle[timer_num], (((HAL_TIMER_RATE) / step_prescaler) / frequency) - 1, step_prescaler); | ||||
|         #endif | ||||
|         __HAL_RCC_TIM5_CLK_ENABLE(); | ||||
|         TimerHandle[timer_num].handle.Instance            = TIM5; | ||||
|         TimerHandle[timer_num].handle.Init.Prescaler      = step_prescaler; | ||||
|         TimerHandle[timer_num].handle.Init.CounterMode    = TIM_COUNTERMODE_UP; | ||||
|         TimerHandle[timer_num].handle.Init.ClockDivision  = TIM_CLOCKDIVISION_DIV1; | ||||
|         TimerHandle[timer_num].callback = (uint32_t)TC5_Handler; | ||||
|         HAL_NVIC_SetPriority(STEP_TIMER_IRQ_ID, 1, 0); | ||||
|         break; | ||||
| 
 | ||||
|       case TEMP_TIMER_NUM: | ||||
|         // TEMP TIMER TIM7 - any available 16bit Timer (1 already used for PWM)
 | ||||
|         #ifdef STM32GENERIC | ||||
|           __HAL_RCC_TIM7_CLK_ENABLE(); | ||||
|           TimerHandle[timer_num].handle.Instance            = TIM7; | ||||
|           TimerHandle[timer_num].handle.Init.Prescaler      = temp_prescaler; | ||||
|           TimerHandle[timer_num].handle.Init.CounterMode    = TIM_COUNTERMODE_UP; | ||||
|           TimerHandle[timer_num].handle.Init.ClockDivision  = TIM_CLOCKDIVISION_DIV1; | ||||
|           TimerHandle[timer_num].callback = (uint32_t)TC7_Handler; | ||||
|         #else | ||||
|           TimerHandle[timer_num].timer = TIM7; | ||||
|           TimerHandle[timer_num].irqHandle = TC7_Handler; | ||||
|           TimerHandleInit(&TimerHandle[timer_num], (((HAL_TIMER_RATE) / temp_prescaler) / frequency) - 1, temp_prescaler); | ||||
|         #endif | ||||
|         __HAL_RCC_TIM7_CLK_ENABLE(); | ||||
|         TimerHandle[timer_num].handle.Instance            = TIM7; | ||||
|         TimerHandle[timer_num].handle.Init.Prescaler      = temp_prescaler; | ||||
|         TimerHandle[timer_num].handle.Init.CounterMode    = TIM_COUNTERMODE_UP; | ||||
|         TimerHandle[timer_num].handle.Init.ClockDivision  = TIM_CLOCKDIVISION_DIV1; | ||||
|         TimerHandle[timer_num].callback = (uint32_t)TC7_Handler; | ||||
|         HAL_NVIC_SetPriority(TEMP_TIMER_IRQ_ID, 2, 0); | ||||
|         break; | ||||
|     } | ||||
|     timers_initialized[timer_num] = true; | ||||
|   } | ||||
| 
 | ||||
|   #ifdef STM32GENERIC | ||||
|     TimerHandle[timer_num].handle.Init.Period = (((HAL_TIMER_RATE) / TimerHandle[timer_num].handle.Init.Prescaler) / frequency) - 1; | ||||
|     if (HAL_TIM_Base_Init(&TimerHandle[timer_num].handle) == HAL_OK) | ||||
|       HAL_TIM_Base_Start_IT(&TimerHandle[timer_num].handle); | ||||
|   #endif | ||||
|   TimerHandle[timer_num].handle.Init.Period = (((HAL_TIMER_RATE) / TimerHandle[timer_num].handle.Init.Prescaler) / frequency) - 1; | ||||
|   if (HAL_TIM_Base_Init(&TimerHandle[timer_num].handle) == HAL_OK) | ||||
|     HAL_TIM_Base_Start_IT(&TimerHandle[timer_num].handle); | ||||
| } | ||||
| 
 | ||||
| #ifdef STM32GENERIC | ||||
|   extern "C" void TIM5_IRQHandler() { | ||||
|     ((void(*)(void))TimerHandle[0].callback)(); | ||||
|   } | ||||
|   extern "C" void TIM7_IRQHandler() { | ||||
|     ((void(*)(void))TimerHandle[1].callback)(); | ||||
|   } | ||||
| #endif | ||||
| extern "C" void TIM5_IRQHandler() { | ||||
|   ((void(*)(void))TimerHandle[0].callback)(); | ||||
| } | ||||
| extern "C" void TIM7_IRQHandler() { | ||||
|   ((void(*)(void))TimerHandle[1].callback)(); | ||||
| } | ||||
| 
 | ||||
| void HAL_timer_enable_interrupt(const uint8_t timer_num) { | ||||
|   switch (timer_num) { | ||||
|  | ||||
| @ -59,8 +59,9 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { | ||||
|       timerConfig[0].IRQ_Id = TIM5_IRQn; | ||||
|       timerConfig[0].callback = (uint32_t)TC5_Handler; | ||||
|       HAL_NVIC_SetPriority(timerConfig[0].IRQ_Id, 1, 0); | ||||
|       SET_OUTPUT(STEPPER_ENABLE_PIN); | ||||
|       WRITE(STEPPER_ENABLE_PIN); | ||||
|       #if PIN_EXISTS(STEPPER_ENABLE) | ||||
|         OUT_WRITE(STEPPER_ENABLE_PIN, HIGH); | ||||
|       #endif | ||||
|       break; | ||||
|     case TEMP_TIMER_NUM: | ||||
|       //TEMP TIMER TIM7 // any available 16bit Timer (1 already used for PWM)
 | ||||
|  | ||||
| @ -189,7 +189,6 @@ void TMC26XStepper::start() { | ||||
|   pinMode(step_pin, OUTPUT); | ||||
|   pinMode(dir_pin, OUTPUT); | ||||
|   pinMode(cs_pin, OUTPUT); | ||||
|   //SET_OUTPUT(STEPPER_ENABLE_PIN);
 | ||||
|   extDigitalWrite(step_pin, LOW); | ||||
|   extDigitalWrite(dir_pin, LOW); | ||||
|   extDigitalWrite(cs_pin, HIGH); | ||||
|  | ||||
| @ -86,6 +86,8 @@ uint16_t EE_Initialize(void) { | ||||
|   pEraseInit.NbSectors = 1; | ||||
|   pEraseInit.VoltageRange = VOLTAGE_RANGE; | ||||
| 
 | ||||
|   HAL_StatusTypeDef FlashStatus; // = HAL_OK
 | ||||
| 
 | ||||
|   /* Check for invalid header states and repair if necessary */ | ||||
|   uint32_t SectorError; | ||||
|   switch (PageStatus0) { | ||||
| @ -135,7 +137,7 @@ uint16_t EE_Initialize(void) { | ||||
|           } | ||||
|         } | ||||
|         /* Mark Page0 as valid */ | ||||
|         HAL_StatusTypeDef FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE); | ||||
|         FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE); | ||||
|         /* If program operation was failed, a Flash error code is returned */ | ||||
|         if (FlashStatus != HAL_OK) return FlashStatus; | ||||
|         pEraseInit.Sector = PAGE1_ID; | ||||
|  | ||||
| @ -65,7 +65,7 @@ | ||||
|   #include "feature/host_actions.h" | ||||
| #endif | ||||
| 
 | ||||
| #if HAS_BUZZER && DISABLED(LCD_USE_I2C_BUZZER) | ||||
| #if USE_BEEPER | ||||
|   #include "libs/buzzer.h" | ||||
| #endif | ||||
| 
 | ||||
| @ -290,6 +290,15 @@ void enable_all_steppers() { | ||||
|   enable_E5(); | ||||
| } | ||||
| 
 | ||||
| void enable_e_steppers() { | ||||
|   enable_E0(); | ||||
|   enable_E1(); | ||||
|   enable_E2(); | ||||
|   enable_E3(); | ||||
|   enable_E4(); | ||||
|   enable_E5(); | ||||
| } | ||||
| 
 | ||||
| void disable_e_steppers() { | ||||
|   disable_E0(); | ||||
|   disable_E1(); | ||||
| @ -539,28 +548,28 @@ void manage_inactivity(const bool ignore_stepper_queue/*=false*/) { | ||||
|       #if ENABLED(SWITCHING_EXTRUDER) | ||||
|         bool oldstatus; | ||||
|         switch (active_extruder) { | ||||
|           default: oldstatus = E0_ENABLE_READ; enable_E0(); break; | ||||
|           default: oldstatus = E0_ENABLE_READ(); enable_E0(); break; | ||||
|           #if E_STEPPERS > 1 | ||||
|             case 2: case 3: oldstatus = E1_ENABLE_READ; enable_E1(); break; | ||||
|             case 2: case 3: oldstatus = E1_ENABLE_READ(); enable_E1(); break; | ||||
|             #if E_STEPPERS > 2 | ||||
|               case 4: case 5: oldstatus = E2_ENABLE_READ; enable_E2(); break; | ||||
|               case 4: case 5: oldstatus = E2_ENABLE_READ(); enable_E2(); break; | ||||
|             #endif // E_STEPPERS > 2
 | ||||
|           #endif // E_STEPPERS > 1
 | ||||
|         } | ||||
|       #else // !SWITCHING_EXTRUDER
 | ||||
|         bool oldstatus; | ||||
|         switch (active_extruder) { | ||||
|           default: oldstatus = E0_ENABLE_READ; enable_E0(); break; | ||||
|           default: oldstatus = E0_ENABLE_READ(); enable_E0(); break; | ||||
|           #if E_STEPPERS > 1 | ||||
|             case 1: oldstatus = E1_ENABLE_READ; enable_E1(); break; | ||||
|             case 1: oldstatus = E1_ENABLE_READ(); enable_E1(); break; | ||||
|             #if E_STEPPERS > 2 | ||||
|               case 2: oldstatus = E2_ENABLE_READ; enable_E2(); break; | ||||
|               case 2: oldstatus = E2_ENABLE_READ(); enable_E2(); break; | ||||
|               #if E_STEPPERS > 3 | ||||
|                 case 3: oldstatus = E3_ENABLE_READ; enable_E3(); break; | ||||
|                 case 3: oldstatus = E3_ENABLE_READ(); enable_E3(); break; | ||||
|                 #if E_STEPPERS > 4 | ||||
|                   case 4: oldstatus = E4_ENABLE_READ; enable_E4(); break; | ||||
|                   case 4: oldstatus = E4_ENABLE_READ(); enable_E4(); break; | ||||
|                   #if E_STEPPERS > 5 | ||||
|                     case 5: oldstatus = E5_ENABLE_READ; enable_E5(); break; | ||||
|                     case 5: oldstatus = E5_ENABLE_READ(); enable_E5(); break; | ||||
|                   #endif // E_STEPPERS > 5
 | ||||
|                 #endif // E_STEPPERS > 4
 | ||||
|               #endif // E_STEPPERS > 3
 | ||||
| @ -693,7 +702,7 @@ void idle( | ||||
|     print_job_timer.tick(); | ||||
|   #endif | ||||
| 
 | ||||
|   #if HAS_BUZZER && DISABLED(LCD_USE_I2C_BUZZER) && DISABLED(PCA9632_BUZZER) | ||||
|   #if USE_BEEPER | ||||
|     buzzer.tick(); | ||||
|   #endif | ||||
| 
 | ||||
| @ -877,6 +886,10 @@ void setup() { | ||||
|     runout.setup(); | ||||
|   #endif | ||||
| 
 | ||||
|   #if ENABLED(POWER_LOSS_RECOVERY) | ||||
|     recovery.setup(); | ||||
|   #endif | ||||
| 
 | ||||
|   setup_killpin(); | ||||
| 
 | ||||
|   #if HAS_TMC220x | ||||
| @ -1117,6 +1130,10 @@ void setup() { | ||||
|     init_closedloop(); | ||||
|   #endif | ||||
| 
 | ||||
|   #ifdef STARTUP_COMMANDS | ||||
|     queue.inject_P(PSTR(STARTUP_COMMANDS)); | ||||
|   #endif | ||||
| 
 | ||||
|   #if ENABLED(INIT_SDCARD_ON_BOOT) && !HAS_SPI_LCD | ||||
|     card.beginautostart(); | ||||
|   #endif | ||||
|  | ||||
| @ -316,6 +316,7 @@ void manage_inactivity(const bool ignore_stepper_queue=false); | ||||
| /**
 | ||||
|  * The axis order in all axis related arrays is X, Y, Z, E | ||||
|  */ | ||||
| void enable_e_steppers(); | ||||
| void enable_all_steppers(); | ||||
| void disable_e_stepper(const uint8_t e); | ||||
| void disable_e_steppers(); | ||||
|  | ||||
| @ -95,7 +95,7 @@ | ||||
| #define BOARD_Z_BOLT_X_SERIES         1141  // Z-Bolt X Series
 | ||||
| #define BOARD_TT_OSCAR                1142  // TT OSCAR
 | ||||
| #define BOARD_OVERLORD                1143  // Overlord/Overlord Pro
 | ||||
| #define BOARD_ULTIMAKER               1144  // ADIMLab Granty v1
 | ||||
| #define BOARD_HJC2560C_REV1           1144  // ADIMLab Granty v1
 | ||||
| #define BOARD_HJC2560C_REV2           1145  // ADIMLab Granty v2
 | ||||
| 
 | ||||
| //
 | ||||
| @ -115,24 +115,25 @@ | ||||
| 
 | ||||
| #define BOARD_CNCONTROLS_11           1300  // Cartesio CN Controls V11
 | ||||
| #define BOARD_CNCONTROLS_12           1301  // Cartesio CN Controls V12
 | ||||
| #define BOARD_CHEAPTRONIC             1302  // Cheaptronic v1.0
 | ||||
| #define BOARD_CHEAPTRONIC_V2          1303  // Cheaptronic v2.0
 | ||||
| #define BOARD_MIGHTYBOARD_REVE        1304  // Makerbot Mightyboard Revision E
 | ||||
| #define BOARD_MEGATRONICS             1305  // Megatronics
 | ||||
| #define BOARD_MEGATRONICS_2           1306  // Megatronics v2.0
 | ||||
| #define BOARD_MEGATRONICS_3           1307  // Megatronics v3.0
 | ||||
| #define BOARD_MEGATRONICS_31          1308  // Megatronics v3.1
 | ||||
| #define BOARD_MEGATRONICS_32          1309  // Megatronics v3.2
 | ||||
| #define BOARD_ELEFU_3                 1310  // Elefu Ra Board (v3)
 | ||||
| #define BOARD_LEAPFROG                1311  // Leapfrog
 | ||||
| #define BOARD_MEGACONTROLLER          1312  // Mega controller
 | ||||
| #define BOARD_GT2560_REV_A            1313  // Geeetech GT2560 Rev. A
 | ||||
| #define BOARD_GT2560_REV_A_PLUS       1314  // Geeetech GT2560 Rev. A+ (with auto level probe)
 | ||||
| #define BOARD_GT2560_V3               1315  // Geeetech GT2560 Rev B for A10(M/D)
 | ||||
| #define BOARD_GT2560_V3_MC2           1316  // Geeetech GT2560 Rev B for Mecreator2
 | ||||
| #define BOARD_GT2560_V3_A20           1317  // Geeetech GT2560 Rev B for A20(M/D)
 | ||||
| #define BOARD_EINSTART_S              1318  // Einstart retrofit
 | ||||
| #define BOARD_WANHAO_ONEPLUS          1319  // Wanhao 0ne+ i3 Mini
 | ||||
| #define BOARD_CNCONTROLS_15           1302  // Cartesio CN Controls V15
 | ||||
| #define BOARD_CHEAPTRONIC             1303  // Cheaptronic v1.0
 | ||||
| #define BOARD_CHEAPTRONIC_V2          1304  // Cheaptronic v2.0
 | ||||
| #define BOARD_MIGHTYBOARD_REVE        1305  // Makerbot Mightyboard Revision E
 | ||||
| #define BOARD_MEGATRONICS             1306  // Megatronics
 | ||||
| #define BOARD_MEGATRONICS_2           1307  // Megatronics v2.0
 | ||||
| #define BOARD_MEGATRONICS_3           1308  // Megatronics v3.0
 | ||||
| #define BOARD_MEGATRONICS_31          1309  // Megatronics v3.1
 | ||||
| #define BOARD_MEGATRONICS_32          1310  // Megatronics v3.2
 | ||||
| #define BOARD_ELEFU_3                 1311  // Elefu Ra Board (v3)
 | ||||
| #define BOARD_LEAPFROG                1312  // Leapfrog
 | ||||
| #define BOARD_MEGACONTROLLER          1313  // Mega controller
 | ||||
| #define BOARD_GT2560_REV_A            1314  // Geeetech GT2560 Rev. A
 | ||||
| #define BOARD_GT2560_REV_A_PLUS       1315  // Geeetech GT2560 Rev. A+ (with auto level probe)
 | ||||
| #define BOARD_GT2560_V3               1316  // Geeetech GT2560 Rev B for A10(M/D)
 | ||||
| #define BOARD_GT2560_V3_MC2           1317  // Geeetech GT2560 Rev B for Mecreator2
 | ||||
| #define BOARD_GT2560_V3_A20           1318  // Geeetech GT2560 Rev B for A20(M/D)
 | ||||
| #define BOARD_EINSTART_S              1319  // Einstart retrofit
 | ||||
| #define BOARD_WANHAO_ONEPLUS          1320  // Wanhao 0ne+ i3 Mini
 | ||||
| 
 | ||||
| //
 | ||||
| // ATmega1281, ATmega2561
 | ||||
| @ -292,6 +293,7 @@ | ||||
| #define BOARD_BLACK_STM32F407ZE       4205  // BLACK_STM32F407ZE
 | ||||
| #define BOARD_STEVAL                  4206  // STEVAL-3DP001V1 3D PRINTER BOARD
 | ||||
| #define BOARD_BIGTREE_SKR_PRO_V1_1    4207  // BigTreeTech SKR Pro v1.1 (STM32F407ZG)
 | ||||
| #define BOARD_BIGTREE_BTT002_V1_0     4208  // BigTreeTech BTT002 v1.0 (STM32F407VE)
 | ||||
| 
 | ||||
| //
 | ||||
| // ARM Cortex M7
 | ||||
|  | ||||
| @ -67,12 +67,14 @@ | ||||
| 
 | ||||
| #define AXIS_DRIVER_TYPE(A,T) AXIS_DRIVER_TYPE_##A(T) | ||||
| 
 | ||||
| #define HAS_E_DRIVER(T) (  AXIS_DRIVER_TYPE_E0(T) || AXIS_DRIVER_TYPE_E1(T) \ | ||||
|                         || AXIS_DRIVER_TYPE_E2(T) || AXIS_DRIVER_TYPE_E3(T) \ | ||||
|                         || AXIS_DRIVER_TYPE_E4(T) || AXIS_DRIVER_TYPE_E5(T) ) | ||||
| 
 | ||||
| #define HAS_DRIVER(T) (    AXIS_DRIVER_TYPE_X(T)  || AXIS_DRIVER_TYPE_X2(T) \ | ||||
|                         || AXIS_DRIVER_TYPE_Y(T)  || AXIS_DRIVER_TYPE_Y2(T) \ | ||||
|                         || AXIS_DRIVER_TYPE_Z(T)  || AXIS_DRIVER_TYPE_Z2(T) || AXIS_DRIVER_TYPE_Z3(T) \ | ||||
|                         || AXIS_DRIVER_TYPE_E0(T) || AXIS_DRIVER_TYPE_E1(T) \ | ||||
|                         || AXIS_DRIVER_TYPE_E2(T) || AXIS_DRIVER_TYPE_E3(T) \ | ||||
|                         || AXIS_DRIVER_TYPE_E4(T) || AXIS_DRIVER_TYPE_E5(T) ) | ||||
|                         || HAS_E_DRIVER(T) ) | ||||
| 
 | ||||
| // Test for supported TMC drivers that require advanced configuration
 | ||||
| // Does not match standalone configurations
 | ||||
|  | ||||
| @ -118,24 +118,24 @@ | ||||
|   // Using GCC extensions, but Travis GCC version does not like it and gives
 | ||||
|   //  "error: statement-expressions are not allowed outside functions nor in template-argument lists"
 | ||||
|   #define NOLESS(v, n) \ | ||||
|     do { \ | ||||
|     do{ \ | ||||
|       __typeof__(n) _n = (n); \ | ||||
|       if (v < _n) v = _n; \ | ||||
|     } while(0) | ||||
|     }while(0) | ||||
| 
 | ||||
|   #define NOMORE(v, n) \ | ||||
|     do { \ | ||||
|     do{ \ | ||||
|       __typeof__(n) _n = (n); \ | ||||
|       if (v > _n) v = _n; \ | ||||
|     } while(0) | ||||
|     }while(0) | ||||
| 
 | ||||
|   #define LIMIT(v, n1, n2) \ | ||||
|     do { \ | ||||
|     do{ \ | ||||
|       __typeof__(n1) _n1 = (n1); \ | ||||
|       __typeof__(n2) _n2 = (n2); \ | ||||
|       if (v < _n1) v = _n1; \ | ||||
|       else if (v > _n2) v = _n2; \ | ||||
|     } while(0) | ||||
|     }while(0) | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|  | ||||
| @ -184,5 +184,5 @@ void print_bin(const uint16_t val); | ||||
| 
 | ||||
| void print_xyz(PGM_P const prefix, PGM_P const suffix, const float x, const float y, const float z); | ||||
| void print_xyz(PGM_P const prefix, PGM_P const suffix, const float xyz[]); | ||||
| #define SERIAL_POS(SUFFIX,VAR) do { print_xyz(PSTR("  " STRINGIFY(VAR) "="), PSTR(" : " SUFFIX "\n"), VAR); } while(0) | ||||
| #define SERIAL_XYZ(PREFIX,V...) do { print_xyz(PSTR(PREFIX), nullptr, V); } while(0) | ||||
| #define SERIAL_POS(SUFFIX,VAR) do { print_xyz(PSTR("  " STRINGIFY(VAR) "="), PSTR(" : " SUFFIX "\n"), VAR); }while(0) | ||||
| #define SERIAL_XYZ(PREFIX,V...) do { print_xyz(PSTR(PREFIX), nullptr, V); }while(0) | ||||
|  | ||||
| @ -752,16 +752,15 @@ | ||||
|       save_ubl_active_state_and_disable();  // No bed level correction so only raw data is obtained
 | ||||
|       DEPLOY_PROBE(); | ||||
| 
 | ||||
|       uint8_t count = GRID_MAX_POINTS, current = 1; | ||||
|       uint8_t count = GRID_MAX_POINTS; | ||||
| 
 | ||||
|       do { | ||||
|         current = (GRID_MAX_POINTS) - count + 1; | ||||
| 
 | ||||
|         if (do_ubl_mesh_map) display_map(g29_map_type); | ||||
| 
 | ||||
|         SERIAL_ECHOLNPAIR("\nProbing mesh point ", int(current), "/", int(GRID_MAX_POINTS), ".\n"); | ||||
|         const int current = (GRID_MAX_POINTS) - count + 1; | ||||
|         SERIAL_ECHOLNPAIR("\nProbing mesh point ", current, "/", int(GRID_MAX_POINTS), ".\n"); | ||||
|         #if HAS_DISPLAY | ||||
|           ui.status_printf_P(0, PSTR(MSG_PROBING_MESH " %i/%i"), int(current), int(GRID_MAX_POINTS)); | ||||
|           ui.status_printf_P(0, PSTR(MSG_PROBING_MESH " %i/%i"), current, int(GRID_MAX_POINTS)); | ||||
|         #endif | ||||
| 
 | ||||
|         #if HAS_LCD_MENU | ||||
| @ -1500,8 +1499,7 @@ | ||||
|                 DEBUG_ECHO_F(rx, 7); | ||||
|                 DEBUG_CHAR(','); | ||||
|                 DEBUG_ECHO_F(ry, 7); | ||||
|                 DEBUG_ECHOPGM(")   logical: "); | ||||
|                 DEBUG_CHAR('('); | ||||
|                 DEBUG_ECHOPGM(")   logical: ("); | ||||
|                 DEBUG_ECHO_F(LOGICAL_X_POSITION(rx), 7); | ||||
|                 DEBUG_CHAR(','); | ||||
|                 DEBUG_ECHO_F(LOGICAL_Y_POSITION(ry), 7); | ||||
|  | ||||
| @ -36,35 +36,37 @@ void controllerfan_update() { | ||||
|   if (ELAPSED(ms, nextMotorCheck)) { | ||||
|     nextMotorCheck = ms + 2500UL; // Not a time critical function, so only check every 2.5s
 | ||||
| 
 | ||||
|     const bool xory = X_ENABLE_READ() == X_ENABLE_ON || Y_ENABLE_READ() == Y_ENABLE_ON; | ||||
| 
 | ||||
|     // If any of the drivers or the bed are enabled...
 | ||||
|     if (X_ENABLE_READ == X_ENABLE_ON || Y_ENABLE_READ == Y_ENABLE_ON || Z_ENABLE_READ == Z_ENABLE_ON | ||||
|     if (xory || Z_ENABLE_READ() == Z_ENABLE_ON | ||||
|       #if HAS_HEATED_BED | ||||
|         || thermalManager.temp_bed.soft_pwm_amount > 0 | ||||
|       #endif | ||||
|         #if HAS_X2_ENABLE | ||||
|           || X2_ENABLE_READ == X_ENABLE_ON | ||||
|           || X2_ENABLE_READ() == X_ENABLE_ON | ||||
|         #endif | ||||
|         #if HAS_Y2_ENABLE | ||||
|           || Y2_ENABLE_READ == Y_ENABLE_ON | ||||
|           || Y2_ENABLE_READ() == Y_ENABLE_ON | ||||
|         #endif | ||||
|         #if HAS_Z2_ENABLE | ||||
|           || Z2_ENABLE_READ == Z_ENABLE_ON | ||||
|           || Z2_ENABLE_READ() == Z_ENABLE_ON | ||||
|         #endif | ||||
|         #if HAS_Z3_ENABLE | ||||
|           || Z3_ENABLE_READ == Z_ENABLE_ON | ||||
|           || Z3_ENABLE_READ() == Z_ENABLE_ON | ||||
|         #endif | ||||
|         #if E_STEPPERS | ||||
|           || E0_ENABLE_READ == E_ENABLE_ON | ||||
|           || E0_ENABLE_READ() == E_ENABLE_ON | ||||
|           #if E_STEPPERS > 1 | ||||
|             || E1_ENABLE_READ == E_ENABLE_ON | ||||
|             || E1_ENABLE_READ() == E_ENABLE_ON | ||||
|             #if E_STEPPERS > 2 | ||||
|               || E2_ENABLE_READ == E_ENABLE_ON | ||||
|               || E2_ENABLE_READ() == E_ENABLE_ON | ||||
|               #if E_STEPPERS > 3 | ||||
|                 || E3_ENABLE_READ == E_ENABLE_ON | ||||
|                 || E3_ENABLE_READ() == E_ENABLE_ON | ||||
|                 #if E_STEPPERS > 4 | ||||
|                   || E4_ENABLE_READ == E_ENABLE_ON | ||||
|                   || E4_ENABLE_READ() == E_ENABLE_ON | ||||
|                   #if E_STEPPERS > 5 | ||||
|                     || E5_ENABLE_READ == E_ENABLE_ON | ||||
|                     || E5_ENABLE_READ() == E_ENABLE_ON | ||||
|                   #endif // E_STEPPERS > 5
 | ||||
|                 #endif // E_STEPPERS > 4
 | ||||
|               #endif // E_STEPPERS > 3
 | ||||
| @ -76,12 +78,17 @@ void controllerfan_update() { | ||||
|     } | ||||
| 
 | ||||
|     // Fan off if no steppers have been enabled for CONTROLLERFAN_SECS seconds
 | ||||
|     uint8_t speed = (!lastMotorOn || ELAPSED(ms, lastMotorOn + (CONTROLLERFAN_SECS) * 1000UL)) ? 0 : CONTROLLERFAN_SPEED; | ||||
|     controllerfan_speed = speed; | ||||
|     controllerfan_speed = (!lastMotorOn || ELAPSED(ms, lastMotorOn + (CONTROLLERFAN_SECS) * 1000UL)) ? 0 : ( | ||||
|       #ifdef CONTROLLERFAN_SPEED_Z_ONLY | ||||
|         xory ? CONTROLLERFAN_SPEED : CONTROLLERFAN_SPEED_Z_ONLY | ||||
|       #else | ||||
|         CONTROLLERFAN_SPEED | ||||
|       #endif | ||||
|     ); | ||||
| 
 | ||||
|     // allows digital or PWM fan output to be used (see M42 handling)
 | ||||
|     WRITE(CONTROLLER_FAN_PIN, speed); | ||||
|     analogWrite(pin_t(CONTROLLER_FAN_PIN), speed); | ||||
|     // Allow digital or PWM fan output (see M42 handling)
 | ||||
|     WRITE(CONTROLLER_FAN_PIN, controllerfan_speed); | ||||
|     analogWrite(pin_t(CONTROLLER_FAN_PIN), controllerfan_speed); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -125,7 +125,7 @@ void LEDLights::set_color(const LEDColor &incol | ||||
|     // If the pins can do PWM then their intensity will be set.
 | ||||
|     #define UPDATE_RGBW(C,c) do { if (PWM_PIN(RGB_LED_##C##_PIN)) \ | ||||
|         analogWrite(pin_t(RGB_LED_##C##_PIN), incol.c); \ | ||||
|       else WRITE(RGB_LED_##C##_PIN, incol.c ? HIGH : LOW); } while(0) | ||||
|       else WRITE(RGB_LED_##C##_PIN, incol.c ? HIGH : LOW); }while(0) | ||||
|     UPDATE_RGBW(R,r); | ||||
|     UPDATE_RGBW(G,g); | ||||
|     UPDATE_RGBW(B,b); | ||||
|  | ||||
| @ -137,13 +137,15 @@ void pca9632_set_led_color(const LEDColor &color) { | ||||
| } | ||||
| 
 | ||||
| #if ENABLED(PCA9632_BUZZER) | ||||
|   void pca9632_buzz(uint16_t const f, uint16_t d) { | ||||
|     UNUSED(f); UNUSED(d); | ||||
| 
 | ||||
|   void pca9632_buzz(const long duration, const uint16_t freq) { | ||||
|     UNUSED(duration); UNUSED(freq); | ||||
|     uint8_t data[] = PCA9632_BUZZER_DATA; | ||||
|     Wire.beginTransmission(I2C_ADDRESS(PCA9632_ADDRESS)); | ||||
|     Wire.write(data, sizeof(data)); | ||||
|     Wire.endTransmission(); | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
| #endif // PCA9632_BUZZER
 | ||||
| 
 | ||||
| #endif // PCA9632
 | ||||
|  | ||||
| @ -32,5 +32,6 @@ typedef LEDColor LEDColor; | ||||
| void pca9632_set_led_color(const LEDColor &color); | ||||
| 
 | ||||
| #if ENABLED(PCA9632_BUZZER) | ||||
|   void pca9632_buzz(uint16_t const, uint16_t); | ||||
|   #include <stdint.h> | ||||
|   void pca9632_buzz(const long, const uint16_t); | ||||
| #endif | ||||
|  | ||||
| @ -187,6 +187,9 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l | ||||
|       host_action_prompt_button(PSTR("Continue")); | ||||
|       host_action_prompt_show(); | ||||
|     #endif | ||||
|     #if ENABLED(EXTENSIBLE_UI) | ||||
|       ExtUI::onStatusChanged(PSTR("Load Filament")); | ||||
|     #endif | ||||
|     while (wait_for_user) { | ||||
|       #if HAS_BUZZER | ||||
|         filament_change_beep(max_beep_count); | ||||
| @ -239,6 +242,9 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l | ||||
|     #if ENABLED(HOST_PROMPT_SUPPORT) | ||||
|       host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Continuous Purge Running..."), PSTR("Continue")); | ||||
|     #endif | ||||
|     #if ENABLED(EXTENSIBLE_UI) | ||||
|       ExtUI::onStatusChanged(PSTR("Continuous Purge Running...")); | ||||
|     #endif | ||||
|     for (float purge_count = purge_length; purge_count > 0 && wait_for_user; --purge_count) | ||||
|       do_pause_e_move(1, ADVANCED_PAUSE_PURGE_FEEDRATE); | ||||
|     wait_for_user = false; | ||||
| @ -353,8 +359,8 @@ bool unload_filament(const float &unload_length, const bool show_lcd/*=false*/, | ||||
|     planner.settings.retract_acceleration = saved_acceleration; | ||||
|   #endif | ||||
| 
 | ||||
|   // Disable extruders steppers for manual filament changing (only on boards that have separate ENABLE_PINS)
 | ||||
|   #if (E0_ENABLE_PIN != X_ENABLE_PIN && E1_ENABLE_PIN != Y_ENABLE_PIN) || AXIS_DRIVER_TYPE_E0(TMC2660) || AXIS_DRIVER_TYPE_E1(TMC2660) || AXIS_DRIVER_TYPE_E2(TMC2660) || AXIS_DRIVER_TYPE_E3(TMC2660) || AXIS_DRIVER_TYPE_E4(TMC2660) || AXIS_DRIVER_TYPE_E5(TMC2660) | ||||
|   // Disable E steppers for manual change
 | ||||
|   #if HAS_E_STEPPER_ENABLE | ||||
|     disable_e_stepper(active_extruder); | ||||
|     safe_delay(100); | ||||
|   #endif | ||||
| @ -517,6 +523,9 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep | ||||
|   #if ENABLED(HOST_PROMPT_SUPPORT) | ||||
|     host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Nozzle Parked"), PSTR("Continue")); | ||||
|   #endif | ||||
|   #if ENABLED(EXTENSIBLE_UI) | ||||
|     ExtUI::onStatusChanged(PSTR("Nozzle Parked")); | ||||
|   #endif | ||||
|   while (wait_for_user) { | ||||
|     #if HAS_BUZZER | ||||
|       filament_change_beep(max_beep_count); | ||||
| @ -538,6 +547,10 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep | ||||
|         host_prompt_do(PROMPT_USER_CONTINUE, PSTR("HeaterTimeout"), PSTR("Reheat")); | ||||
|       #endif | ||||
| 
 | ||||
|       #if ENABLED(EXTENSIBLE_UI) | ||||
|         ExtUI::onStatusChanged(PSTR("HeaterTimeout")); | ||||
|       #endif | ||||
| 
 | ||||
|       // Wait for LCD click or M108
 | ||||
|       while (wait_for_user) idle(true); | ||||
| 
 | ||||
|  | ||||
| @ -55,31 +55,31 @@ bool Power::is_power_needed() { | ||||
|   #endif | ||||
| 
 | ||||
|   // If any of the drivers or the bed are enabled...
 | ||||
|   if (X_ENABLE_READ == X_ENABLE_ON || Y_ENABLE_READ == Y_ENABLE_ON || Z_ENABLE_READ == Z_ENABLE_ON | ||||
|   if (X_ENABLE_READ() == X_ENABLE_ON || Y_ENABLE_READ() == Y_ENABLE_ON || Z_ENABLE_READ() == Z_ENABLE_ON | ||||
|     #if HAS_HEATED_BED | ||||
|       || thermalManager.temp_bed.soft_pwm_amount > 0 | ||||
|     #endif | ||||
|       #if HAS_X2_ENABLE | ||||
|         || X2_ENABLE_READ == X_ENABLE_ON | ||||
|         || X2_ENABLE_READ() == X_ENABLE_ON | ||||
|       #endif | ||||
|       #if HAS_Y2_ENABLE | ||||
|         || Y2_ENABLE_READ == Y_ENABLE_ON | ||||
|         || Y2_ENABLE_READ() == Y_ENABLE_ON | ||||
|       #endif | ||||
|       #if HAS_Z2_ENABLE | ||||
|         || Z2_ENABLE_READ == Z_ENABLE_ON | ||||
|         || Z2_ENABLE_READ() == Z_ENABLE_ON | ||||
|       #endif | ||||
|       #if E_STEPPERS | ||||
|         || E0_ENABLE_READ == E_ENABLE_ON | ||||
|         || E0_ENABLE_READ() == E_ENABLE_ON | ||||
|         #if E_STEPPERS > 1 | ||||
|           || E1_ENABLE_READ == E_ENABLE_ON | ||||
|           || E1_ENABLE_READ() == E_ENABLE_ON | ||||
|           #if E_STEPPERS > 2 | ||||
|             || E2_ENABLE_READ == E_ENABLE_ON | ||||
|             || E2_ENABLE_READ() == E_ENABLE_ON | ||||
|             #if E_STEPPERS > 3 | ||||
|               || E3_ENABLE_READ == E_ENABLE_ON | ||||
|               || E3_ENABLE_READ() == E_ENABLE_ON | ||||
|               #if E_STEPPERS > 4 | ||||
|                 || E4_ENABLE_READ == E_ENABLE_ON | ||||
|                 || E4_ENABLE_READ() == E_ENABLE_ON | ||||
|                 #if E_STEPPERS > 5 | ||||
|                   || E5_ENABLE_READ == E_ENABLE_ON | ||||
|                   || E5_ENABLE_READ() == E_ENABLE_ON | ||||
|                 #endif // E_STEPPERS > 5
 | ||||
|               #endif // E_STEPPERS > 4
 | ||||
|             #endif // E_STEPPERS > 3
 | ||||
|  | ||||
| @ -26,12 +26,16 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "../sd/cardreader.h" | ||||
| #include "../inc/MarlinConfigPre.h" | ||||
| #include "../inc/MarlinConfig.h" | ||||
| 
 | ||||
| #if ENABLED(MIXING_EXTRUDER) | ||||
|   #include "../feature/mixing.h" | ||||
| #endif | ||||
| 
 | ||||
| #if !defined(POWER_LOSS_STATE) && PIN_EXISTS(POWER_LOSS) | ||||
|   #define POWER_LOSS_STATE HIGH | ||||
| #endif | ||||
| 
 | ||||
| //#define DEBUG_POWER_LOSS_RECOVERY
 | ||||
| //#define SAVE_EACH_CMD_MODE
 | ||||
| //#define SAVE_INFO_INTERVAL_MS 0
 | ||||
| @ -110,6 +114,20 @@ class PrintJobRecovery { | ||||
| 
 | ||||
|     static void init(); | ||||
| 
 | ||||
|     static inline void setup() { | ||||
|       #if PIN_EXISTS(POWER_LOSS) | ||||
|         #if ENABLED(POWER_LOSS_PULL) | ||||
|           #if POWER_LOSS_STATE == LOW | ||||
|             SET_INPUT_PULLUP(POWER_LOSS_PIN); | ||||
|           #else | ||||
|             SET_INPUT_PULLDOWN(POWER_LOSS_PIN); | ||||
|           #endif | ||||
|         #else | ||||
|           SET_INPUT(POWER_LOSS_PIN); | ||||
|         #endif | ||||
|       #endif | ||||
|     } | ||||
| 
 | ||||
|     static bool enabled; | ||||
|     static void enable(const bool onoff); | ||||
|     static void changed(); | ||||
|  | ||||
| @ -42,6 +42,10 @@ MMU2 mmu2; | ||||
|   #include "../../feature/host_actions.h" | ||||
| #endif | ||||
| 
 | ||||
| #if ENABLED(EXTENSIBLE_UI) | ||||
|   #include "../../lcd/extensible_ui/ui_api.h" | ||||
| #endif | ||||
| 
 | ||||
| #define DEBUG_OUT ENABLED(MMU2_DEBUG) | ||||
| #include "../../core/debug_out.h" | ||||
| 
 | ||||
| @ -711,6 +715,9 @@ void MMU2::filament_runout() { | ||||
|       #if ENABLED(HOST_PROMPT_SUPPORT) | ||||
|         host_prompt_do(PROMPT_USER_CONTINUE, PSTR("MMU2 Eject Recover"), PSTR("Continue")); | ||||
|       #endif | ||||
|       #if ENABLED(EXTENSIBLE_UI) | ||||
|         ExtUI::onStatusChanged(PSTR("MMU2 Eject Recover")); | ||||
|       #endif | ||||
|       while (wait_for_user) idle(); | ||||
|       BUZZ(200, 404); | ||||
|       BUZZ(200, 404); | ||||
|  | ||||
| @ -249,6 +249,8 @@ class FilamentSensorBase { | ||||
|               && (dual_x_carriage_mode == DXC_DUPLICATION_MODE || dual_x_carriage_mode == DXC_MIRRORED_MODE) | ||||
|             #elif ENABLED(MULTI_NOZZLE_DUPLICATION) | ||||
|               && extruder_duplication_enabled | ||||
|             #else | ||||
|               && false | ||||
|             #endif | ||||
|           #endif | ||||
|         ) return runout_states;               // Any extruder
 | ||||
|  | ||||
| @ -445,7 +445,7 @@ void GcodeSuite::G33() { | ||||
|              _tower_results       = (_4p_calibration && towers_set) || probe_points >= 3, | ||||
|              _opposite_results    = (_4p_calibration && !towers_set) || probe_points >= 3, | ||||
|              _endstop_results     = probe_points != 1 && probe_points != -1 && probe_points != 0, | ||||
|              _angle_results       = probe_points >= 3  && towers_set; | ||||
|              _angle_results       = probe_points >= 3 && towers_set; | ||||
|   static const char save_message[] PROGMEM = "Save with M500 and/or copy to Configuration.h"; | ||||
|   int8_t iterations = 0; | ||||
|   float test_precision, | ||||
|  | ||||
| @ -284,7 +284,7 @@ void GcodeSuite::G34() { | ||||
|     // Home Z after the alignment procedure
 | ||||
|     process_subcommands_now_P(PSTR("G28 Z")); | ||||
| 
 | ||||
|   } while(0); | ||||
|   }while(0); | ||||
| 
 | ||||
|   if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("<<< G34"); | ||||
| } | ||||
|  | ||||
| @ -42,6 +42,10 @@ | ||||
|   #include "../../feature/host_actions.h" | ||||
| #endif | ||||
| 
 | ||||
| #if ENABLED(EXTENSIBLE_UI) | ||||
|   #include "../../lcd/extensible_ui/ui_api.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifndef GET_PIN_MAP_PIN_M43 | ||||
|   #define GET_PIN_MAP_PIN_M43(Q) GET_PIN_MAP_PIN(Q) | ||||
| #endif | ||||
| @ -329,6 +333,9 @@ void GcodeSuite::M43() { | ||||
|       #if ENABLED(HOST_PROMPT_SUPPORT) | ||||
|         host_prompt_do(PROMPT_USER_CONTINUE, PSTR("M43 Wait Called"), PSTR("Continue")); | ||||
|       #endif | ||||
|       #if ENABLED(EXTENSIBLE_UI) | ||||
|         ExtUI::onStatusChanged(PSTR("M43 Wait Called")); | ||||
|       #endif | ||||
|     #endif | ||||
| 
 | ||||
|     for (;;) { | ||||
|  | ||||
| @ -30,11 +30,21 @@ | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * M17: Enable power on all stepper motors | ||||
|  * M17: Enable stepper motors | ||||
|  */ | ||||
| void GcodeSuite::M17() { | ||||
|   LCD_MESSAGEPGM(MSG_NO_MOVE); | ||||
|   enable_all_steppers(); | ||||
|   if (parser.seen("XYZE")) { | ||||
|     if (parser.seen('X')) enable_X(); | ||||
|     if (parser.seen('Y')) enable_Y(); | ||||
|     if (parser.seen('Z')) enable_Z(); | ||||
|     #if HAS_E_STEPPER_ENABLE | ||||
|       if (parser.seen('E')) enable_e_steppers(); | ||||
|     #endif | ||||
|   } | ||||
|   else { | ||||
|     LCD_MESSAGEPGM(MSG_NO_MOVE); | ||||
|     enable_all_steppers(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
| @ -45,20 +55,17 @@ void GcodeSuite::M18_M84() { | ||||
|     stepper_inactive_time = parser.value_millis_from_seconds(); | ||||
|   } | ||||
|   else { | ||||
|     bool all_axis = !(parser.seen('X') || parser.seen('Y') || parser.seen('Z') || parser.seen('E')); | ||||
|     if (all_axis) { | ||||
|       planner.finish_and_disable(); | ||||
|     } | ||||
|     else { | ||||
|     if (parser.seen("XYZE")) { | ||||
|       planner.synchronize(); | ||||
|       if (parser.seen('X')) disable_X(); | ||||
|       if (parser.seen('Y')) disable_Y(); | ||||
|       if (parser.seen('Z')) disable_Z(); | ||||
|       // Only disable on boards that have separate ENABLE_PINS or another method for disabling the driver
 | ||||
|       #if (E0_ENABLE_PIN != X_ENABLE_PIN && E1_ENABLE_PIN != Y_ENABLE_PIN) || AXIS_DRIVER_TYPE_E0(TMC2660) || AXIS_DRIVER_TYPE_E1(TMC2660) || AXIS_DRIVER_TYPE_E2(TMC2660) || AXIS_DRIVER_TYPE_E3(TMC2660) || AXIS_DRIVER_TYPE_E4(TMC2660) || AXIS_DRIVER_TYPE_E5(TMC2660) | ||||
|       #if HAS_E_STEPPER_ENABLE | ||||
|         if (parser.seen('E')) disable_e_steppers(); | ||||
|       #endif | ||||
|     } | ||||
|     else | ||||
|       planner.finish_and_disable(); | ||||
| 
 | ||||
|     #if HAS_LCD_MENU && ENABLED(AUTO_BED_LEVELING_UBL) | ||||
|       if (ubl.lcd_map_control) { | ||||
|  | ||||
| @ -52,7 +52,7 @@ void GcodeSuite::M502() { | ||||
|    * M503: print settings currently in memory | ||||
|    */ | ||||
|   void GcodeSuite::M503() { | ||||
|     (void)settings.report(parser.boolval('S', true)); | ||||
|     (void)settings.report(!parser.boolval('S', true)); | ||||
|   } | ||||
| 
 | ||||
| #endif // !DISABLE_M503
 | ||||
|  | ||||
| @ -342,6 +342,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { | ||||
|         case 12: M12(); break;                                    // M12: Synchronize and optionally force a CLC set
 | ||||
|       #endif | ||||
| 
 | ||||
|       #if ENABLED(EXPECTED_PRINTER_CHECK) | ||||
|         case 16: M16(); break;                                    // M16: Expected printer check
 | ||||
|       #endif | ||||
| 
 | ||||
|       case 17: M17(); break;                                      // M17: Enable all stepper motors
 | ||||
| 
 | ||||
|       #if ENABLED(SDSUPPORT) | ||||
|  | ||||
| @ -83,6 +83,7 @@ | ||||
|  * M8   - Turn flood coolant ON. (Requires COOLANT_CONTROL) | ||||
|  * M9   - Turn coolant OFF. (Requires COOLANT_CONTROL) | ||||
|  * M12  - Set up closed loop control system. (Requires EXTERNAL_CLOSED_LOOP_CONTROLLER) | ||||
|  * M16  - Expected printer check. (Requires EXPECTED_PRINTER_CHECK) | ||||
|  * M17  - Enable/Power all stepper motors | ||||
|  * M18  - Disable all stepper motors; same as M84 | ||||
|  * M20  - List SD card. (Requires SDSUPPORT) | ||||
| @ -472,6 +473,10 @@ private: | ||||
|     static void M12(); | ||||
|   #endif | ||||
| 
 | ||||
|   #if ENABLED(EXPECTED_PRINTER_CHECK) | ||||
|     static void M16(); | ||||
|   #endif | ||||
| 
 | ||||
|   static void M17(); | ||||
| 
 | ||||
|   static void M18_M84(); | ||||
|  | ||||
							
								
								
									
										40
									
								
								Marlin/src/gcode/host/M16.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								Marlin/src/gcode/host/M16.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| /**
 | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
 | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * 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. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "../../inc/MarlinConfigPre.h" | ||||
| 
 | ||||
| #if ENABLED(EXPECTED_PRINTER_CHECK) | ||||
| 
 | ||||
| #include "../gcode.h" | ||||
| #include "../../Marlin.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * M16: Expected Printer Check | ||||
|  */ | ||||
| void GcodeSuite::M16() { | ||||
| 
 | ||||
|   if (strcmp_P(parser.string_arg, PSTR(MACHINE_NAME))) | ||||
|     kill(PSTR(MSG_EXPECTED_PRINTER)); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| @ -97,6 +97,9 @@ void GcodeSuite::M0_M1() { | ||||
|   #if ENABLED(HOST_PROMPT_SUPPORT) | ||||
|     host_prompt_do(PROMPT_USER_CONTINUE, PSTR("M0/1 Break Called"), PSTR("Continue")); | ||||
|   #endif | ||||
|   #if ENABLED(EXTENSIBLE_UI) | ||||
|     ExtUI::onStatusChanged(PSTR("M0/1 Break Called")); | ||||
|   #endif | ||||
| 
 | ||||
|   if (ms > 0) { | ||||
|     ms += millis();  // wait until this time for a click
 | ||||
|  | ||||
| @ -225,6 +225,9 @@ void GCodeParser::parse(char *p) { | ||||
|       case 810: case 811: case 812: case 813: case 814: | ||||
|       case 815: case 816: case 817: case 818: case 819: | ||||
|     #endif | ||||
|     #if ENABLED(EXPECTED_PRINTER_CHECK) | ||||
|       case 16: | ||||
|     #endif | ||||
|     case 23: case 28: case 30: case 117: case 118: case 928: string_arg = p; return; | ||||
|     default: break; | ||||
|   } | ||||
|  | ||||
| @ -30,9 +30,9 @@ | ||||
| 
 | ||||
|   #define DOGLCD | ||||
|   #define IS_ULTIPANEL | ||||
|   #define DEFAULT_LCD_CONTRAST 90 | ||||
|   #define LCD_CONTRAST_MIN 60 | ||||
|   #define LCD_CONTRAST_MIN  60 | ||||
|   #define LCD_CONTRAST_MAX 140 | ||||
|   #define LCD_CONTRAST_INIT 90 | ||||
| 
 | ||||
| #elif ENABLED(ZONESTAR_LCD) | ||||
| 
 | ||||
| @ -65,23 +65,23 @@ | ||||
|   #if ENABLED(miniVIKI) | ||||
|     #define LCD_CONTRAST_MIN      75 | ||||
|     #define LCD_CONTRAST_MAX     115 | ||||
|     #define DEFAULT_LCD_CONTRAST  95 | ||||
|     #define LCD_CONTRAST_INIT     95 | ||||
|     #define U8GLIB_ST7565_64128N | ||||
|   #elif ENABLED(VIKI2) | ||||
|     #define LCD_CONTRAST_MIN       0 | ||||
|     #define LCD_CONTRAST_MAX     255 | ||||
|     #define DEFAULT_LCD_CONTRAST 140 | ||||
|     #define LCD_CONTRAST_INIT    140 | ||||
|     #define U8GLIB_ST7565_64128N | ||||
|   #elif ENABLED(ELB_FULL_GRAPHIC_CONTROLLER) | ||||
|     #define LCD_CONTRAST_MIN      90 | ||||
|     #define LCD_CONTRAST_MAX     130 | ||||
|     #define DEFAULT_LCD_CONTRAST 110 | ||||
|     #define LCD_CONTRAST_INIT    110 | ||||
|     #define U8GLIB_LM6059_AF | ||||
|     #define SD_DETECT_INVERTED | ||||
|   #elif ENABLED(AZSMZ_12864) | ||||
|     #define LCD_CONTRAST_MIN     120 | ||||
|     #define LCD_CONTRAST_MAX     255 | ||||
|     #define DEFAULT_LCD_CONTRAST 190 | ||||
|     #define LCD_CONTRAST_INIT    190 | ||||
|     #define U8GLIB_ST7565_64128N | ||||
|   #endif | ||||
| 
 | ||||
| @ -128,17 +128,17 @@ | ||||
| #elif ENABLED(MKS_MINI_12864) | ||||
| 
 | ||||
|   #define MINIPANEL | ||||
|   #define DEFAULT_LCD_CONTRAST 150 | ||||
|   #define LCD_CONTRAST_MAX 255 | ||||
|   #define LCD_CONTRAST_MAX  255 | ||||
|   #define LCD_CONTRAST_INIT 150 | ||||
| 
 | ||||
| #elif ANY(FYSETC_MINI_12864_X_X, FYSETC_MINI_12864_1_2, FYSETC_MINI_12864_2_0, FYSETC_MINI_12864_2_1) | ||||
| 
 | ||||
|   #define FYSETC_MINI_12864 | ||||
|   #define DOGLCD | ||||
|   #define IS_ULTIPANEL | ||||
|   #define LCD_CONTRAST_MIN 0 | ||||
|   #define LCD_CONTRAST_MAX 255 | ||||
|   #define DEFAULT_LCD_CONTRAST 220 | ||||
|   #define LCD_CONTRAST_MIN    0 | ||||
|   #define LCD_CONTRAST_MAX  255 | ||||
|   #define LCD_CONTRAST_INIT 220 | ||||
|   #define LED_COLORS_REDUCE_GREEN | ||||
|   #if HAS_POWER_SWITCH && EITHER(FYSETC_MINI_12864_2_0, FYSETC_MINI_12864_2_1) | ||||
|     #define LED_BACKLIGHT_TIMEOUT 10000 | ||||
| @ -166,9 +166,9 @@ | ||||
|   #define IS_ULTIPANEL | ||||
|   #define U8GLIB_SSD1309 | ||||
|   #define LCD_RESET_PIN LCD_PINS_D6 //  This controller need a reset pin
 | ||||
|   #define LCD_CONTRAST_MIN 0 | ||||
|   #define LCD_CONTRAST_MAX 254 | ||||
|   #define DEFAULT_LCD_CONTRAST 127 | ||||
|   #define LCD_CONTRAST_MIN    0 | ||||
|   #define LCD_CONTRAST_MAX  254 | ||||
|   #define LCD_CONTRAST_INIT 127 | ||||
|   #define ENCODER_PULSES_PER_STEP 2 | ||||
|   #define ENCODER_STEPS_PER_MENU_ITEM 2 | ||||
| 
 | ||||
| @ -190,8 +190,8 @@ | ||||
|   #if ENABLED(MAKRPANEL) | ||||
|     #define U8GLIB_ST7565_64128N | ||||
|   #endif | ||||
|   #ifndef DEFAULT_LCD_CONTRAST | ||||
|     #define DEFAULT_LCD_CONTRAST 17 | ||||
|   #ifndef LCD_CONTRAST_INIT | ||||
|     #define LCD_CONTRAST_INIT    17 | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| @ -368,7 +368,7 @@ | ||||
| #endif | ||||
| 
 | ||||
| // Extensible UI serial touch screens. (See src/lcd/extensible_ui)
 | ||||
| #if EITHER(MALYAN_LCD, DGUS_LCD) | ||||
| #if ANY(MALYAN_LCD, DGUS_LCD, LULZBOT_TOUCH_UI) | ||||
|   #define IS_EXTUI | ||||
|   #define EXTENSIBLE_UI | ||||
| #endif | ||||
| @ -381,22 +381,6 @@ | ||||
| #define HAS_LCD_MENU        (ENABLED(ULTIPANEL) && DISABLED(NO_LCD_MENUS)) | ||||
| #define HAS_ADC_BUTTONS      ENABLED(ADC_KEYPAD) | ||||
| 
 | ||||
| /**
 | ||||
|  * Default LCD contrast for Graphical LCD displays | ||||
|  */ | ||||
| #define HAS_LCD_CONTRAST (HAS_GRAPHICAL_LCD && defined(DEFAULT_LCD_CONTRAST)) | ||||
| #if HAS_LCD_CONTRAST | ||||
|   #ifndef LCD_CONTRAST_MIN | ||||
|     #define LCD_CONTRAST_MIN 0 | ||||
|   #endif | ||||
|   #ifndef LCD_CONTRAST_MAX | ||||
|     #define LCD_CONTRAST_MAX 63 | ||||
|   #endif | ||||
|   #ifndef DEFAULT_LCD_CONTRAST | ||||
|     #define DEFAULT_LCD_CONTRAST 32 | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Extruders have some combination of stepper motors and hotends | ||||
|  * so we separate these concepts into the defines: | ||||
| @ -594,32 +578,6 @@ | ||||
|   #define INVERT_E_DIR false | ||||
| #endif | ||||
| 
 | ||||
| #if ENABLED(HOST_ACTION_COMMANDS) | ||||
|   #ifndef ACTION_ON_PAUSE | ||||
|     #define ACTION_ON_PAUSE   "pause" | ||||
|   #endif | ||||
|   #ifndef ACTION_ON_RESUME | ||||
|     #define ACTION_ON_RESUME  "resume" | ||||
|   #endif | ||||
|   #ifndef ACTION_ON_PAUSED | ||||
|     #define ACTION_ON_PAUSED  "paused" | ||||
|   #endif | ||||
|   #ifndef ACTION_ON_RESUMED | ||||
|     #define ACTION_ON_RESUMED "resumed" | ||||
|   #endif | ||||
|   #ifndef ACTION_ON_CANCEL | ||||
|     #define ACTION_ON_CANCEL  "cancel" | ||||
|   #endif | ||||
|   #if ENABLED(G29_RETRY_AND_RECOVER) | ||||
|     #ifndef ACTION_ON_G29_RECOVER | ||||
|       #define ACTION_ON_G29_RECOVER "probe_rewipe" | ||||
|     #endif | ||||
|     #ifndef ACTION_ON_G29_FAILURE | ||||
|       #define ACTION_ON_G29_FAILURE "probe_failed" | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #if ENABLED(SLIM_LCD_MENUS) | ||||
|   #define BOOT_MARLIN_LOGO_SMALL | ||||
| #endif | ||||
|  | ||||
| @ -99,3 +99,6 @@ | ||||
|     #define LED_USER_PRESET_BRIGHTNESS 255 | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Extensible UI pin mapping for RepRapDiscount
 | ||||
| #define TOUCH_UI_ULTIPANEL ENABLED(LULZBOT_TOUCH_UI) && ANY(AO_EXP1_PINMAP, AO_EXP2_PINMAP, CR10_TFT_PINMAP) | ||||
|  | ||||
| @ -246,6 +246,22 @@ | ||||
|   #define MAX_AUTORETRACT 99 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Default LCD contrast for Graphical LCD displays | ||||
|  */ | ||||
| #define HAS_LCD_CONTRAST defined(LCD_CONTRAST_INIT) | ||||
| #if HAS_LCD_CONTRAST | ||||
|   #ifndef DEFAULT_LCD_CONTRAST | ||||
|     #define DEFAULT_LCD_CONTRAST LCD_CONTRAST_INIT | ||||
|   #endif | ||||
|   #ifndef LCD_CONTRAST_MIN | ||||
|     #define LCD_CONTRAST_MIN 0 | ||||
|   #endif | ||||
|   #ifndef LCD_CONTRAST_MAX | ||||
|     #define LCD_CONTRAST_MAX MAX(63, LCD_CONTRAST_INIT) | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Override here because this is set in Configuration_adv.h | ||||
|  */ | ||||
| @ -927,6 +943,11 @@ | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #define HAS_E_STEPPER_ENABLE (HAS_E_DRIVER(TMC2660) \ | ||||
|   || ( E0_ENABLE_PIN != X_ENABLE_PIN && E1_ENABLE_PIN != X_ENABLE_PIN   \ | ||||
|     && E0_ENABLE_PIN != Y_ENABLE_PIN && E1_ENABLE_PIN != Y_ENABLE_PIN ) \ | ||||
| ) | ||||
| 
 | ||||
| // Endstops and bed probe
 | ||||
| #define _HAS_STOP(A,M) (PIN_EXISTS(A##_##M) && !IS_X2_ENDSTOP(A,M) && !IS_Y2_ENDSTOP(A,M) && !IS_Z2_OR_PROBE(A,M)) | ||||
| #define HAS_X_MIN _HAS_STOP(X,MIN) | ||||
| @ -996,7 +1017,21 @@ | ||||
| #define HAS_AUTO_FAN_4 (HOTENDS > 4 && PIN_EXISTS(E4_AUTO_FAN)) | ||||
| #define HAS_AUTO_FAN_5 (HOTENDS > 5 && PIN_EXISTS(E5_AUTO_FAN)) | ||||
| #define HAS_AUTO_CHAMBER_FAN (HAS_TEMP_CHAMBER && PIN_EXISTS(CHAMBER_AUTO_FAN)) | ||||
| 
 | ||||
| #define HAS_AUTO_FAN (HAS_AUTO_FAN_0 || HAS_AUTO_FAN_1 || HAS_AUTO_FAN_2 || HAS_AUTO_FAN_3 || HAS_AUTO_FAN_4 || HAS_AUTO_FAN_5 || HAS_AUTO_CHAMBER_FAN) | ||||
| #if HAS_AUTO_FAN | ||||
|   #define AUTO_CHAMBER_IS_0 (CHAMBER_AUTO_FAN_PIN == E0_AUTO_FAN_PIN) | ||||
|   #define AUTO_CHAMBER_IS_1 (CHAMBER_AUTO_FAN_PIN == E1_AUTO_FAN_PIN) | ||||
|   #define AUTO_CHAMBER_IS_2 (CHAMBER_AUTO_FAN_PIN == E2_AUTO_FAN_PIN) | ||||
|   #define AUTO_CHAMBER_IS_3 (CHAMBER_AUTO_FAN_PIN == E3_AUTO_FAN_PIN) | ||||
|   #define AUTO_CHAMBER_IS_4 (CHAMBER_AUTO_FAN_PIN == E4_AUTO_FAN_PIN) | ||||
|   #define AUTO_CHAMBER_IS_5 (CHAMBER_AUTO_FAN_PIN == E5_AUTO_FAN_PIN) | ||||
|   #define AUTO_CHAMBER_IS_E (AUTO_CHAMBER_IS_0 || AUTO_CHAMBER_IS_1 || AUTO_CHAMBER_IS_2 || AUTO_CHAMBER_IS_3 || AUTO_CHAMBER_IS_4 || AUTO_CHAMBER_IS_5) | ||||
| #endif | ||||
| 
 | ||||
| #if !HAS_AUTO_CHAMBER_FAN || AUTO_CHAMBER_IS_E | ||||
|   #undef AUTO_POWER_CHAMBER_FAN | ||||
| #endif | ||||
| 
 | ||||
| // Other fans
 | ||||
| #define HAS_FAN0 (PIN_EXISTS(FAN)) | ||||
| @ -1029,7 +1064,8 @@ | ||||
| #define HAS_KILL        (PIN_EXISTS(KILL)) | ||||
| #define HAS_SUICIDE     (PIN_EXISTS(SUICIDE)) | ||||
| #define HAS_PHOTOGRAPH  (PIN_EXISTS(PHOTOGRAPH)) | ||||
| #define HAS_BUZZER      (PIN_EXISTS(BEEPER) || ENABLED(LCD_USE_I2C_BUZZER) || ENABLED(PCA9632_BUZZER)) | ||||
| #define HAS_BUZZER      (PIN_EXISTS(BEEPER) || EITHER(LCD_USE_I2C_BUZZER, PCA9632_BUZZER)) | ||||
| #define USE_BEEPER      (HAS_BUZZER && DISABLED(LCD_USE_I2C_BUZZER, PCA9632_BUZZER)) | ||||
| #define HAS_CASE_LIGHT  (PIN_EXISTS(CASE_LIGHT) && ENABLED(CASE_LIGHT_ENABLE)) | ||||
| 
 | ||||
| // Digital control
 | ||||
| @ -1551,7 +1587,7 @@ | ||||
|   #ifndef LCD_FEEDBACK_FREQUENCY_DURATION_MS | ||||
|     #define LCD_FEEDBACK_FREQUENCY_DURATION_MS 100 | ||||
|   #endif | ||||
| #else | ||||
| #elif HAS_BUZZER | ||||
|   #ifndef LCD_FEEDBACK_FREQUENCY_HZ | ||||
|     #define LCD_FEEDBACK_FREQUENCY_HZ 5000 | ||||
|   #endif | ||||
|  | ||||
| @ -1892,6 +1892,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS | ||||
|   + ENABLED(OVERLORD_OLED) \ | ||||
|   + ENABLED(DGUS_LCD) \ | ||||
|   + ENABLED(MALYAN_LCD) \ | ||||
|   + ENABLED(LULZBOT_TOUCH_UI) \ | ||||
|   + ENABLED(FSMC_GRAPHICAL_TFT) | ||||
|   #error "Please select no more than one LCD controller option." | ||||
| #endif | ||||
|  | ||||
| @ -51,7 +51,7 @@ | ||||
|    * here we define this default string as the date where the latest release | ||||
|    * version was tagged. | ||||
|    */ | ||||
|   #define STRING_DISTRIBUTION_DATE "2019-08-08" | ||||
|   #define STRING_DISTRIBUTION_DATE "2019-08-21" | ||||
| 
 | ||||
|   /**
 | ||||
|    * Required minimum Configuration.h and Configuration_adv.h file versions. | ||||
|  | ||||
| @ -877,7 +877,7 @@ static int pf_bsearch_cb_comp_hd4map_pgm(void *userdata, size_t idx, void * data | ||||
|   return hd44780_charmap_compare(&localval, (hd44780_charmap_t *)data_pin); | ||||
| } | ||||
| 
 | ||||
| void lcd_moveto(const uint8_t col, const uint8_t row) { lcd.setCursor(col, row); } | ||||
| void lcd_moveto(const lcd_uint_t col, const lcd_uint_t row) { lcd.setCursor(col, row); } | ||||
| 
 | ||||
| void lcd_put_int(const int i) { lcd.print(i); } | ||||
| 
 | ||||
|  | ||||
| @ -269,7 +269,7 @@ void MarlinUI::set_custom_characters(const HD44780CharSet screen_charset/*=CHARS | ||||
| 
 | ||||
|   #endif // LCD_PROGRESS_BAR
 | ||||
| 
 | ||||
|   #if ENABLED(SDSUPPORT) | ||||
|   #if ENABLED(SDSUPPORT) && HAS_LCD_MENU | ||||
| 
 | ||||
|     // CHARSET_MENU
 | ||||
|     const static PROGMEM byte refresh[8] = { | ||||
| @ -319,7 +319,7 @@ void MarlinUI::set_custom_characters(const HD44780CharSet screen_charset/*=CHARS | ||||
|       #endif | ||||
|         { | ||||
|           createChar_P(LCD_STR_UPLEVEL[0], uplevel); | ||||
|           #if ENABLED(SDSUPPORT) | ||||
|           #if ENABLED(SDSUPPORT) && HAS_LCD_MENU | ||||
|             // SD Card sub-menu special characters
 | ||||
|             createChar_P(LCD_STR_REFRESH[0], refresh); | ||||
|             createChar_P(LCD_STR_FOLDER[0], folder); | ||||
| @ -360,23 +360,48 @@ void MarlinUI::init_lcd() { | ||||
|   lcd.clear(); | ||||
| } | ||||
| 
 | ||||
| bool MarlinUI::detected() { | ||||
|   return true | ||||
|     #if EITHER(LCD_I2C_TYPE_MCP23017, LCD_I2C_TYPE_MCP23008) && defined(DETECT_DEVICE) | ||||
|       && lcd.LcdDetected() == 1 | ||||
|     #endif | ||||
|   ; | ||||
| } | ||||
| 
 | ||||
| #if HAS_SLOW_BUTTONS | ||||
|   uint8_t MarlinUI::read_slow_buttons() { | ||||
|     #if ENABLED(LCD_I2C_TYPE_MCP23017) | ||||
|       // Reading these buttons this is likely to be too slow to call inside interrupt context
 | ||||
|       // so they are called during normal lcd_update
 | ||||
|       uint8_t slow_bits = lcd.readButtons() | ||||
|         #if !BUTTON_EXISTS(ENC) | ||||
|           << B_I2C_BTN_OFFSET | ||||
|         #endif | ||||
|       ; | ||||
|       #if ENABLED(LCD_I2C_VIKI) | ||||
|         if ((slow_bits & (B_MI | B_RI)) && PENDING(millis(), next_button_update_ms)) // LCD clicked
 | ||||
|           slow_bits &= ~(B_MI | B_RI); // Disable LCD clicked buttons if screen is updated
 | ||||
|       #endif // LCD_I2C_VIKI
 | ||||
|       return slow_bits; | ||||
|     #endif // LCD_I2C_TYPE_MCP23017
 | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
| void MarlinUI::clear_lcd() { lcd.clear(); } | ||||
| 
 | ||||
| #if ENABLED(SHOW_BOOTSCREEN) | ||||
| 
 | ||||
|   void lcd_erase_line(const int16_t line) { | ||||
|   void lcd_erase_line(const lcd_uint_t line) { | ||||
|     lcd_moveto(0, line); | ||||
|     for (uint8_t i = LCD_WIDTH + 1; --i;) | ||||
|       lcd_put_wchar(' '); | ||||
|   } | ||||
| 
 | ||||
|   // Scroll the PSTR 'text' in a 'len' wide field for 'time' milliseconds at position col,line
 | ||||
|   void lcd_scroll(const uint8_t col, const uint8_t line, PGM_P const text, const uint8_t len, const int16_t time) { | ||||
|   void lcd_scroll(const lcd_uint_t col, const lcd_uint_t line, PGM_P const text, const uint8_t len, const int16_t time) { | ||||
|     uint8_t slen = utf8_strlen_P(text); | ||||
|     if (slen < len) { | ||||
|       // Fits into,
 | ||||
|       lcd_moveto(col, line); | ||||
|       lcd_put_u8str_max_P(text, len); | ||||
|       lcd_put_u8str_max_P(col, line, text, len); | ||||
|       for (; slen < len; ++slen) lcd_put_wchar(' '); | ||||
|       safe_delay(time); | ||||
|     } | ||||
| @ -385,11 +410,8 @@ void MarlinUI::clear_lcd() { lcd.clear(); } | ||||
|       int dly = time / _MAX(slen, 1); | ||||
|       for (uint8_t i = 0; i <= slen; i++) { | ||||
| 
 | ||||
|         // Go to the correct place
 | ||||
|         lcd_moveto(col, line); | ||||
| 
 | ||||
|         // Print the text
 | ||||
|         lcd_put_u8str_max_P(p, len); | ||||
|         // Print the text at the correct place
 | ||||
|         lcd_put_u8str_max_P(col, line, p, len); | ||||
| 
 | ||||
|         // Fill with spaces
 | ||||
|         for (uint8_t ix = slen - i; ix < len; ++ix) lcd_put_wchar(' '); | ||||
| @ -406,9 +428,9 @@ void MarlinUI::clear_lcd() { lcd.clear(); } | ||||
| 
 | ||||
|   static void logo_lines(PGM_P const extra) { | ||||
|     int16_t indent = (LCD_WIDTH - 8 - utf8_strlen_P(extra)) / 2; | ||||
|     lcd_moveto(indent, 0); lcd_put_wchar('\x00'); lcd_put_u8str_P(PSTR( "------" ));  lcd_put_wchar('\x01'); | ||||
|     lcd_moveto(indent, 1);                        lcd_put_u8str_P(PSTR("|Marlin|"));  lcd_put_u8str_P(extra); | ||||
|     lcd_moveto(indent, 2); lcd_put_wchar('\x02'); lcd_put_u8str_P(PSTR( "------" ));  lcd_put_wchar('\x03'); | ||||
|     lcd_put_wchar(indent, 0, '\x00'); lcd_put_u8str_P(PSTR( "------" ));  lcd_put_wchar('\x01'); | ||||
|     lcd_put_u8str_P(indent, 1, PSTR("|Marlin|"));  lcd_put_u8str_P(extra); | ||||
|     lcd_put_wchar(indent, 2, '\x02'); lcd_put_u8str_P(PSTR( "------" ));  lcd_put_wchar('\x03'); | ||||
|   } | ||||
| 
 | ||||
|   void MarlinUI::show_bootscreen() { | ||||
| @ -420,8 +442,7 @@ void MarlinUI::clear_lcd() { lcd.clear(); } | ||||
|     #define CENTER_OR_SCROLL(STRING,DELAY) \ | ||||
|       lcd_erase_line(3); \ | ||||
|       if (utf8_strlen(STRING) <= LCD_WIDTH) { \ | ||||
|         lcd_moveto((LCD_WIDTH - utf8_strlen_P(PSTR(STRING))) / 2, 3); \ | ||||
|         lcd_put_u8str_P(PSTR(STRING)); \ | ||||
|         lcd_put_u8str_P((LCD_WIDTH - utf8_strlen_P(PSTR(STRING))) / 2, 3, PSTR(STRING)); \ | ||||
|         safe_delay(DELAY); \ | ||||
|       } \ | ||||
|       else { \ | ||||
| @ -491,16 +512,12 @@ void MarlinUI::clear_lcd() { lcd.clear(); } | ||||
| #endif // SHOW_BOOTSCREEN
 | ||||
| 
 | ||||
| void MarlinUI::draw_kill_screen() { | ||||
|   lcd_moveto(0, 0); | ||||
|   lcd_put_u8str(status_message); | ||||
|   #if LCD_HEIGHT < 4 | ||||
|     lcd_moveto(0, 2); | ||||
|   #else | ||||
|     lcd_moveto(0, 2); | ||||
|     lcd_put_u8str_P(PSTR(MSG_HALTED)); | ||||
|     lcd_moveto(0, 3); | ||||
|   lcd_put_u8str(0, 0, status_message); | ||||
|   lcd_uint_t y = 2; | ||||
|   #if LCD_HEIGHT >= 4 | ||||
|     lcd_put_u8str_P(0, y++, PSTR(MSG_HALTED)); | ||||
|   #endif | ||||
|   lcd_put_u8str_P(PSTR(MSG_PLEASE_RESET)); | ||||
|   lcd_put_u8str_P(0, y, PSTR(MSG_PLEASE_RESET)); | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| @ -859,8 +876,7 @@ void MarlinUI::draw_status_screen() { | ||||
| 
 | ||||
|     #if LCD_HEIGHT > 3 | ||||
| 
 | ||||
|       lcd_moveto(0, 2); | ||||
|       lcd_put_wchar(LCD_STR_FEEDRATE[0]); | ||||
|       lcd_put_wchar(0, 2, LCD_STR_FEEDRATE[0]); | ||||
|       lcd_put_u8str(i16tostr3(feedrate_percentage)); | ||||
|       lcd_put_wchar('%'); | ||||
| 
 | ||||
| @ -868,8 +884,7 @@ void MarlinUI::draw_status_screen() { | ||||
|       duration_t elapsed = print_job_timer.duration(); | ||||
|       const uint8_t len = elapsed.toDigital(buffer), | ||||
|                     timepos = LCD_WIDTH - len - 1; | ||||
|       lcd_moveto(timepos, 2); | ||||
|       lcd_put_wchar(LCD_STR_CLOCK[0]); | ||||
|       lcd_put_wchar(timepos, 2, LCD_STR_CLOCK[0]); | ||||
|       lcd_put_u8str(buffer); | ||||
| 
 | ||||
|       #if LCD_WIDTH >= 20 | ||||
| @ -918,8 +933,7 @@ void MarlinUI::draw_status_screen() { | ||||
|     _draw_axis_value(Z_AXIS, ftostr52sp(LOGICAL_Z_POSITION(current_position[Z_AXIS])), blink); | ||||
| 
 | ||||
|     #if HAS_LEVELING && (HOTENDS > 1 || !HAS_HEATED_BED) | ||||
|       lcd_moveto(LCD_WIDTH - 1, 0); | ||||
|       lcd_put_wchar(planner.leveling_active || blink ? '_' : ' '); | ||||
|       lcd_put_wchar(LCD_WIDTH - 1, 0, planner.leveling_active || blink ? '_' : ' '); | ||||
|     #endif | ||||
| 
 | ||||
|     // ========== Line 2 ==========
 | ||||
| @ -934,8 +948,7 @@ void MarlinUI::draw_status_screen() { | ||||
|       _draw_bed_status(blink); | ||||
|     #endif | ||||
| 
 | ||||
|     lcd_moveto(LCD_WIDTH - 9, 1); | ||||
|     lcd_put_wchar(LCD_STR_FEEDRATE[0]); | ||||
|     lcd_put_wchar(LCD_WIDTH - 9, 1, LCD_STR_FEEDRATE[0]); | ||||
|     lcd_put_u8str(i16tostr3(feedrate_percentage)); | ||||
|     lcd_put_wchar('%'); | ||||
| 
 | ||||
| @ -1006,8 +1019,7 @@ void MarlinUI::draw_status_screen() { | ||||
| 
 | ||||
|   void draw_menu_item(const bool sel, const uint8_t row, PGM_P pstr, const char pre_char, const char post_char) { | ||||
|     uint8_t n = LCD_WIDTH - 2; | ||||
|     lcd_moveto(0, row); | ||||
|     lcd_put_wchar(sel ? pre_char : ' '); | ||||
|     lcd_put_wchar(0, row, sel ? pre_char : ' '); | ||||
|     n -= lcd_put_u8str_max_P(pstr, n); | ||||
|     for (; n; --n) lcd_put_wchar(' '); | ||||
|     lcd_put_wchar(post_char); | ||||
| @ -1015,8 +1027,7 @@ void MarlinUI::draw_status_screen() { | ||||
| 
 | ||||
|   void _draw_menu_item_edit(const bool sel, const uint8_t row, PGM_P pstr, const char* const data, const bool pgm) { | ||||
|     uint8_t n = LCD_WIDTH - 2 - (pgm ? utf8_strlen_P(data) : utf8_strlen(data)); | ||||
|     lcd_moveto(0, row); | ||||
|     lcd_put_wchar(sel ? LCD_STR_ARROW_RIGHT[0] : ' '); | ||||
|     lcd_put_wchar(0, row, sel ? LCD_STR_ARROW_RIGHT[0] : ' '); | ||||
|     n -= lcd_put_u8str_max_P(pstr, n); | ||||
|     lcd_put_wchar(':'); | ||||
|     for (; n; --n) lcd_put_wchar(' '); | ||||
| @ -1026,14 +1037,12 @@ void MarlinUI::draw_status_screen() { | ||||
|   void draw_edit_screen(PGM_P const pstr, const char* const value/*=nullptr*/) { | ||||
|     ui.encoder_direction_normal(); | ||||
| 
 | ||||
|     lcd_moveto(0, 1); | ||||
|     lcd_put_u8str_P(pstr); | ||||
|     lcd_put_u8str_P(0, 1, pstr); | ||||
|     if (value != nullptr) { | ||||
|       lcd_put_wchar(':'); | ||||
|       int len = utf8_strlen(value); | ||||
|       const uint8_t valrow = (utf8_strlen_P(pstr) + 1 + len + 1) > (LCD_WIDTH - 2) ? 2 : 1;   // Value on the next row if it won't fit
 | ||||
|       lcd_moveto((LCD_WIDTH - 1) - (len + 1), valrow);                                        // Right-justified, padded by spaces
 | ||||
|       lcd_put_wchar(' ');                                                                     // Overwrite char if value gets shorter
 | ||||
|       const lcd_uint_t valrow = (utf8_strlen_P(pstr) + 1 + len + 1) > (LCD_WIDTH - 2) ? 2 : 1;   // Value on the next row if it won't fit
 | ||||
|       lcd_put_wchar((LCD_WIDTH - 1) - (len + 1), valrow, ' ');                                   // Right-justified, padded, add a leading space
 | ||||
|       lcd_put_u8str(value); | ||||
|     } | ||||
|   } | ||||
| @ -1051,8 +1060,7 @@ void MarlinUI::draw_status_screen() { | ||||
|     void draw_sd_menu_item(const bool sel, const uint8_t row, PGM_P const pstr, CardReader &theCard, const bool isDir) { | ||||
|       UNUSED(pstr); | ||||
| 
 | ||||
|       lcd_moveto(0, row); | ||||
|       lcd_put_wchar(sel ? LCD_STR_ARROW_RIGHT[0] : ' '); | ||||
|       lcd_put_wchar(0, row, sel ? LCD_STR_ARROW_RIGHT[0] : ' '); | ||||
|       constexpr uint8_t maxlen = LCD_WIDTH - 2; | ||||
|       uint8_t n = maxlen - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, row, sel), maxlen); | ||||
|       for (; n; --n) lcd_put_wchar(' '); | ||||
| @ -1063,7 +1071,7 @@ void MarlinUI::draw_status_screen() { | ||||
| 
 | ||||
|   #if ENABLED(LCD_HAS_STATUS_INDICATORS) | ||||
| 
 | ||||
|     static void MarlinUI::update_indicators() { | ||||
|     void MarlinUI::update_indicators() { | ||||
|       // Set the LEDS - referred to as backlights by the LiquidTWI2 library
 | ||||
|       static uint8_t ledsprev = 0; | ||||
|       uint8_t leds = 0; | ||||
| @ -1144,9 +1152,9 @@ void MarlinUI::draw_status_screen() { | ||||
|     } custom_char; | ||||
| 
 | ||||
|     typedef struct { | ||||
|       uint8_t column, row, | ||||
|               x_pixel_offset, y_pixel_offset, | ||||
|               x_pixel_mask; | ||||
|       lcd_uint_t column, row, | ||||
|                  x_pixel_offset, y_pixel_offset; | ||||
|       uint8_t x_pixel_mask; | ||||
|     } coordinate; | ||||
| 
 | ||||
|     void add_edges_to_custom_char(custom_char &custom, const coordinate &ul, const coordinate &lr, const coordinate &brc, const uint8_t cell_location); | ||||
| @ -1174,22 +1182,21 @@ void MarlinUI::draw_status_screen() { | ||||
|       return ret_val; | ||||
|     } | ||||
| 
 | ||||
|     inline coordinate pixel_location(const uint8_t x, const uint8_t y) { return pixel_location((int16_t)x, (int16_t)y); } | ||||
|     inline coordinate pixel_location(const lcd_uint_t x, const lcd_uint_t y) { return pixel_location((int16_t)x, (int16_t)y); } | ||||
| 
 | ||||
|     void prep_and_put_map_char(custom_char &chrdata, const coordinate &ul, const coordinate &lr, const coordinate &brc, const uint8_t cl, const char c, const uint8_t x, const uint8_t y) { | ||||
|     void prep_and_put_map_char(custom_char &chrdata, const coordinate &ul, const coordinate &lr, const coordinate &brc, const uint8_t cl, const char c, const lcd_uint_t x, const lcd_uint_t y) { | ||||
|       add_edges_to_custom_char(chrdata, ul, lr, brc, cl); | ||||
|       lcd.createChar(c, (uint8_t*)&chrdata); | ||||
|       lcd_moveto(x, y); | ||||
|       lcd_put_wchar(c); | ||||
|       lcd_put_wchar(x, y, c); | ||||
|     } | ||||
| 
 | ||||
|     void MarlinUI::ubl_plot(const uint8_t x, const uint8_t inverted_y) { | ||||
|     void MarlinUI::ubl_plot(const uint8_t x_plot, const uint8_t y_plot) { | ||||
| 
 | ||||
|       #if LCD_WIDTH >= 20 | ||||
|         #define _LCD_W_POS 12 | ||||
|         #define _PLOT_X 1 | ||||
|         #define _MAP_X 3 | ||||
|         #define _LABEL(C,X,Y) lcd_moveto(X, Y); lcd_put_u8str(C) | ||||
|         #define _LABEL(C,X,Y) lcd_put_u8str(X, Y, C) | ||||
|         #define _XLABEL(X,Y) _LABEL("X:",X,Y) | ||||
|         #define _YLABEL(X,Y) _LABEL("Y:",X,Y) | ||||
|         #define _ZLABEL(X,Y) _LABEL("Z:",X,Y) | ||||
| @ -1197,7 +1204,7 @@ void MarlinUI::draw_status_screen() { | ||||
|         #define _LCD_W_POS 8 | ||||
|         #define _PLOT_X 0 | ||||
|         #define _MAP_X 1 | ||||
|         #define _LABEL(X,Y,C) lcd_moveto(X, Y); lcd_put_wchar(C) | ||||
|         #define _LABEL(X,Y,C) lcd_put_wchar(X, Y, C) | ||||
|         #define _XLABEL(X,Y) _LABEL('X',X,Y) | ||||
|         #define _YLABEL(X,Y) _LABEL('Y',X,Y) | ||||
|         #define _ZLABEL(X,Y) _LABEL('Z',X,Y) | ||||
| @ -1209,10 +1216,10 @@ void MarlinUI::draw_status_screen() { | ||||
|          * Show X and Y positions | ||||
|          */ | ||||
|         _XLABEL(_PLOT_X, 0); | ||||
|         lcd_put_u8str(ftostr52(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x])))); | ||||
|         lcd_put_u8str(ftostr52(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot])))); | ||||
| 
 | ||||
|         _YLABEL(_LCD_W_POS, 0); | ||||
|         lcd_put_u8str(ftostr52(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[inverted_y])))); | ||||
|         lcd_put_u8str(ftostr52(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot])))); | ||||
| 
 | ||||
|         lcd_moveto(_PLOT_X, 0); | ||||
| 
 | ||||
| @ -1220,13 +1227,13 @@ void MarlinUI::draw_status_screen() { | ||||
| 
 | ||||
|         coordinate upper_left, lower_right, bottom_right_corner; | ||||
|         custom_char new_char; | ||||
|         uint8_t i, j, k, l, m, n, n_rows, n_cols, y, | ||||
|                 bottom_line, right_edge, | ||||
|                 x_map_pixels, y_map_pixels, | ||||
|                 pixels_per_x_mesh_pnt, pixels_per_y_mesh_pnt, | ||||
|                 suppress_x_offset = 0, suppress_y_offset = 0; | ||||
|         uint8_t i, n, n_rows, n_cols; | ||||
|         lcd_uint_t j, k, l, m, bottom_line, right_edge, | ||||
|                    x_map_pixels, y_map_pixels, | ||||
|                    pixels_per_x_mesh_pnt, pixels_per_y_mesh_pnt, | ||||
|                    suppress_x_offset = 0, suppress_y_offset = 0; | ||||
| 
 | ||||
|         y = GRID_MAX_POINTS_Y - inverted_y - 1; | ||||
|         const uint8_t y_plot_inv = (GRID_MAX_POINTS_Y - 1) - y_plot; | ||||
| 
 | ||||
|         upper_left.column  = 0; | ||||
|         upper_left.row     = 0; | ||||
| @ -1261,17 +1268,13 @@ void MarlinUI::draw_status_screen() { | ||||
|         n_cols = right_edge / (HD44780_CHAR_WIDTH) + 1; | ||||
| 
 | ||||
|         for (i = 0; i < n_cols; i++) { | ||||
|           lcd_moveto(i, 0); | ||||
|           lcd_put_wchar(CHAR_LINE_TOP);                                     // Box Top line
 | ||||
|           lcd_moveto(i, n_rows - 1); | ||||
|           lcd_put_wchar(CHAR_LINE_BOT);                                     // Box Bottom line
 | ||||
|           lcd_put_wchar(i, 0, CHAR_LINE_TOP);                               // Box Top line
 | ||||
|           lcd_put_wchar(i, n_rows - 1, CHAR_LINE_BOT);                      // Box Bottom line
 | ||||
|         } | ||||
| 
 | ||||
|         for (j = 0; j < n_rows; j++) { | ||||
|           lcd_moveto(0, j); | ||||
|           lcd_put_wchar(CHAR_EDGE_L);                                       // Box Left edge
 | ||||
|           lcd_moveto(n_cols - 1, j); | ||||
|           lcd_put_wchar(CHAR_EDGE_R);                                       // Box Right edge
 | ||||
|           lcd_put_wchar(0, j, CHAR_EDGE_L);                                 // Box Left edge
 | ||||
|           lcd_put_wchar(n_cols - 1, j, CHAR_EDGE_R);                        // Box Right edge
 | ||||
|         } | ||||
| 
 | ||||
|         /**
 | ||||
| @ -1281,10 +1284,8 @@ void MarlinUI::draw_status_screen() { | ||||
|         k = pixels_per_y_mesh_pnt * (GRID_MAX_POINTS_Y) + 2; | ||||
|         l = (HD44780_CHAR_HEIGHT) * n_rows; | ||||
|         if (l > k && l - k >= (HD44780_CHAR_HEIGHT) / 2) { | ||||
|           lcd_moveto(0, n_rows - 1);                                        // Box Left edge
 | ||||
|           lcd_put_wchar(' '); | ||||
|           lcd_moveto(n_cols - 1, n_rows - 1);                               // Box Right edge
 | ||||
|           lcd_put_wchar(' '); | ||||
|           lcd_put_wchar(0, n_rows - 1, ' ');                                // Box Left edge
 | ||||
|           lcd_put_wchar(n_cols - 1, n_rows - 1, ' ');                       // Box Right edge
 | ||||
|         } | ||||
| 
 | ||||
|         clear_custom_char(&new_char); | ||||
| @ -1310,12 +1311,12 @@ void MarlinUI::draw_status_screen() { | ||||
|           new_char.custom_char_bits[j] = (uint8_t)_BV(i);                   // Char #3 is used for the box right edge
 | ||||
|         lcd.createChar(CHAR_EDGE_R, (uint8_t*)&new_char); | ||||
| 
 | ||||
|         i = x * pixels_per_x_mesh_pnt - suppress_x_offset; | ||||
|         j = y * pixels_per_y_mesh_pnt - suppress_y_offset; | ||||
|         i = x_plot * pixels_per_x_mesh_pnt - suppress_x_offset; | ||||
|         j = y_plot_inv * pixels_per_y_mesh_pnt - suppress_y_offset; | ||||
|         upper_left = pixel_location(i, j); | ||||
| 
 | ||||
|         k = (x + 1) * pixels_per_x_mesh_pnt - 1 - suppress_x_offset; | ||||
|         l = (y + 1) * pixels_per_y_mesh_pnt - 1 - suppress_y_offset; | ||||
|         k = (x_plot + 1) * pixels_per_x_mesh_pnt - 1 - suppress_x_offset; | ||||
|         l = (y_plot_inv + 1) * pixels_per_y_mesh_pnt - 1 - suppress_y_offset; | ||||
|         lower_right = pixel_location(k, l); | ||||
| 
 | ||||
|         bottom_right_corner = pixel_location(x_map_pixels, y_map_pixels); | ||||
| @ -1327,7 +1328,7 @@ void MarlinUI::draw_status_screen() { | ||||
|          */ | ||||
| 
 | ||||
|         clear_custom_char(&new_char); | ||||
|         const uint8_t ypix = _MIN(upper_left.y_pixel_offset + pixels_per_y_mesh_pnt, HD44780_CHAR_HEIGHT); | ||||
|         const lcd_uint_t ypix = _MIN(upper_left.y_pixel_offset + pixels_per_y_mesh_pnt, HD44780_CHAR_HEIGHT); | ||||
|         for (j = upper_left.y_pixel_offset; j < ypix; j++) { | ||||
|           i = upper_left.x_pixel_mask; | ||||
|           for (k = 0; k < pixels_per_x_mesh_pnt; k++) { | ||||
| @ -1398,11 +1399,10 @@ void MarlinUI::draw_status_screen() { | ||||
|       /**
 | ||||
|        * Print plot position | ||||
|        */ | ||||
|       lcd_moveto(_LCD_W_POS, 0); | ||||
|       lcd_put_wchar('('); | ||||
|       lcd_put_u8str(ui8tostr3(x)); | ||||
|       lcd_put_wchar(_LCD_W_POS, 0, '('); | ||||
|       lcd_put_u8str(ui8tostr3(x_plot)); | ||||
|       lcd_put_wchar(','); | ||||
|       lcd_put_u8str(ui8tostr3(inverted_y)); | ||||
|       lcd_put_u8str(ui8tostr3(y_plot)); | ||||
|       lcd_put_wchar(')'); | ||||
| 
 | ||||
|       #if LCD_HEIGHT <= 3   // 16x2 or 20x2 display
 | ||||
| @ -1411,8 +1411,8 @@ void MarlinUI::draw_status_screen() { | ||||
|          * Print Z values | ||||
|          */ | ||||
|         _ZLABEL(_LCD_W_POS, 1); | ||||
|         if (!isnan(ubl.z_values[x][inverted_y])) | ||||
|           lcd_put_u8str(ftostr43sign(ubl.z_values[x][inverted_y])); | ||||
|         if (!isnan(ubl.z_values[x_plot][y_plot])) | ||||
|           lcd_put_u8str(ftostr43sign(ubl.z_values[x_plot][y_plot])); | ||||
|         else | ||||
|           lcd_put_u8str_P(PSTR(" -----")); | ||||
| 
 | ||||
| @ -1422,16 +1422,16 @@ void MarlinUI::draw_status_screen() { | ||||
|          * Show all values at right of screen | ||||
|          */ | ||||
|         _XLABEL(_LCD_W_POS, 1); | ||||
|         lcd_put_u8str(ftostr52(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x])))); | ||||
|         lcd_put_u8str(ftostr52(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot])))); | ||||
|         _YLABEL(_LCD_W_POS, 2); | ||||
|         lcd_put_u8str(ftostr52(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[inverted_y])))); | ||||
|         lcd_put_u8str(ftostr52(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot])))); | ||||
| 
 | ||||
|         /**
 | ||||
|          * Show the location value | ||||
|          */ | ||||
|         _ZLABEL(_LCD_W_POS, 3); | ||||
|         if (!isnan(ubl.z_values[x][inverted_y])) | ||||
|           lcd_put_u8str(ftostr43sign(ubl.z_values[x][inverted_y])); | ||||
|         if (!isnan(ubl.z_values[x_plot][y_plot])) | ||||
|           lcd_put_u8str(ftostr43sign(ubl.z_values[x_plot][y_plot])); | ||||
|         else | ||||
|           lcd_put_u8str_P(PSTR(" -----")); | ||||
| 
 | ||||
|  | ||||
| @ -40,10 +40,14 @@ | ||||
|     #define U8G_COM_ST7920_HAL_SW_SPI u8g_com_std_sw_spi_fn | ||||
|     #define U8G_COM_ST7920_HAL_HW_SPI u8g_com_stm32duino_hw_spi_fn | ||||
|   #elif defined(ARDUINO_ARCH_STM32) | ||||
|     uint8_t u8g_com_arduino_std_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); | ||||
|     #define U8G_COM_HAL_SW_SPI_FN u8g_com_arduino_std_sw_spi_fn | ||||
|     uint8_t u8g_com_stm32duino_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); | ||||
|     #define U8G_COM_HAL_HW_SPI_FN u8g_com_stm32duino_hw_spi_fn | ||||
|     uint8_t u8g_com_arduino_st7920_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); | ||||
|     #define U8G_COM_ST7920_HAL_SW_SPI u8g_com_arduino_st7920_spi_fn | ||||
|     #define U8G_COM_ST7920_HAL_HW_SPI u8g_com_stm32duino_hw_spi_fn | ||||
|     uint8_t u8g_com_arduino_st7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); | ||||
|     #define U8G_COM_ST7920_HAL_HW_SPI u8g_com_arduino_st7920_hw_spi_fn | ||||
|   #elif defined(__AVR__) | ||||
|     uint8_t u8g_com_HAL_AVR_sw_sp_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); | ||||
|     #define U8G_COM_HAL_SW_SPI_FN  u8g_com_HAL_AVR_sw_sp_fn | ||||
|  | ||||
| @ -35,7 +35,7 @@ | ||||
|   #include "../../../_Bootscreen.h" | ||||
| 
 | ||||
|   #ifndef CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH | ||||
|     #define CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH ((CUSTOM_BOOTSCREEN_BMPWIDTH + 7) / 8) | ||||
|     #define CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH CEILING(CUSTOM_BOOTSCREEN_BMPWIDTH, 8) | ||||
|   #endif | ||||
|   #ifndef CUSTOM_BOOTSCREEN_BMPHEIGHT | ||||
|     #define CUSTOM_BOOTSCREEN_BMPHEIGHT (sizeof(custom_start_bmp) / (CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH)) | ||||
| @ -69,6 +69,142 @@ | ||||
|     B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 | ||||
|   }; | ||||
| 
 | ||||
|   #if ENABLED(BOOT_MARLIN_LOGO_ANIMATED) | ||||
| 
 | ||||
|     const unsigned char start_bmp1[] PROGMEM = { | ||||
|       B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, | ||||
|       B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, | ||||
|       B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 | ||||
|     }; | ||||
| 
 | ||||
|     const unsigned char start_bmp2[] PROGMEM = { | ||||
|       B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, | ||||
|       B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, | ||||
|       B10000011,B11001111,B00000000,B00000000,B00000000,B00000000,B00111111, | ||||
|       B10000111,B11111111,B10000000,B00000000,B00000000,B00000000,B00011111, | ||||
|       B10000110,B01111001,B10000000,B00000000,B00000000,B00000000,B00001111, | ||||
|       B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11000000,B00000000,B00000000,B00000000,B00000001, | ||||
|       B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, | ||||
|       B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 | ||||
|     }; | ||||
| 
 | ||||
|     const unsigned char start_bmp3[] PROGMEM = { | ||||
|       B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, | ||||
|       B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, | ||||
|       B10000011,B11001111,B00000000,B00000000,B00000000,B00000000,B00111111, | ||||
|       B10000111,B11111111,B10000000,B00000000,B00000000,B00000000,B00011111, | ||||
|       B10000110,B01111001,B10000000,B00000000,B00000000,B00000000,B00001111, | ||||
|       B10001100,B00110000,B11000111,B10000000,B00000000,B00000000,B00000111, | ||||
|       B10001100,B00110000,B11001111,B11000000,B00000000,B00000000,B00000011, | ||||
|       B10001100,B00110000,B11011100,B11100000,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11011000,B01100000,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11010000,B01100000,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11011000,B01100000,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11011100,B01100000,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11001111,B01110000,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11000111,B01110000,B00000000,B00000000,B00000001, | ||||
|       B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, | ||||
|       B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 | ||||
|     }; | ||||
| 
 | ||||
|     const unsigned char start_bmp4[] PROGMEM = { | ||||
|       B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, | ||||
|       B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, | ||||
|       B10000011,B11001111,B00000000,B00000000,B00000000,B00000000,B00111111, | ||||
|       B10000111,B11111111,B10000000,B00000000,B00000000,B00000000,B00011111, | ||||
|       B10000110,B01111001,B10000000,B00000000,B00000000,B00000000,B00001111, | ||||
|       B10001100,B00110000,B11000111,B10000011,B10000000,B00000000,B00000111, | ||||
|       B10001100,B00110000,B11001111,B11000111,B11000000,B00000000,B00000011, | ||||
|       B10001100,B00110000,B11011100,B11101100,B11100000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11011000,B01101100,B01100000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11010000,B01101100,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11011000,B01101100,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11011100,B01101100,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11001111,B01111100,B00000000,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11000111,B01111100,B00000000,B00000000,B00000001, | ||||
|       B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, | ||||
|       B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 | ||||
|     }; | ||||
| 
 | ||||
|     const unsigned char start_bmp5[] PROGMEM = { | ||||
|       B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, | ||||
|       B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, | ||||
|       B10000011,B11001111,B00000000,B00000000,B00001100,B00000000,B00111111, | ||||
|       B10000111,B11111111,B10000000,B00000000,B00001100,B00000000,B00011111, | ||||
|       B10000110,B01111001,B10000000,B00000000,B00001100,B00000000,B00001111, | ||||
|       B10001100,B00110000,B11000111,B10000011,B10001100,B00000000,B00000111, | ||||
|       B10001100,B00110000,B11001111,B11000111,B11001100,B00000000,B00000011, | ||||
|       B10001100,B00110000,B11011100,B11101100,B11101100,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11011000,B01101100,B01101100,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11010000,B01101100,B00001100,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11011000,B01101100,B00001100,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11011100,B01101100,B00001110,B00000000,B00000001, | ||||
|       B10001100,B00110000,B11001111,B01111100,B00000111,B10000000,B00000001, | ||||
|       B10001100,B00110000,B11000111,B01111100,B00000011,B10000000,B00000001, | ||||
|       B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, | ||||
|       B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 | ||||
|     }; | ||||
| 
 | ||||
|     const unsigned char start_bmp6[] PROGMEM = { | ||||
|       B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, | ||||
|       B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, | ||||
|       B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, | ||||
|       B10000011,B11001111,B00000000,B00000000,B00001100,B00110000,B00111111, | ||||
|       B10000111,B11111111,B10000000,B00000000,B00001100,B00110000,B00011111, | ||||
|       B10000110,B01111001,B10000000,B00000000,B00001100,B00000000,B00001111, | ||||
|       B10001100,B00110000,B11000111,B10000011,B10001100,B00110000,B00000111, | ||||
|       B10001100,B00110000,B11001111,B11000111,B11001100,B00110000,B00000011, | ||||
|       B10001100,B00110000,B11011100,B11101100,B11101100,B00110000,B00000001, | ||||
|       B10001100,B00110000,B11011000,B01101100,B01101100,B00110000,B00000001, | ||||
|       B10001100,B00110000,B11010000,B01101100,B00001100,B00110000,B00000001, | ||||
|       B10001100,B00110000,B11011000,B01101100,B00001100,B00110000,B00000001, | ||||
|       B10001100,B00110000,B11011100,B01101100,B00001110,B00111000,B00000001, | ||||
|       B10001100,B00110000,B11001111,B01111100,B00000111,B10011100,B00000001, | ||||
|       B10001100,B00110000,B11000111,B01111100,B00000011,B10001100,B00000001, | ||||
|       B01000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, | ||||
|       B00011111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111000 | ||||
|     }; | ||||
| 
 | ||||
|   #endif | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
|   #define START_BMPWIDTH      112 | ||||
| @ -114,10 +250,269 @@ | ||||
|     B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 | ||||
|   }; | ||||
| 
 | ||||
|   #if ENABLED(BOOT_MARLIN_LOGO_ANIMATED) | ||||
| 
 | ||||
|     const unsigned char start_bmp1[] PROGMEM = { | ||||
|       B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111, | ||||
|       B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11111111, | ||||
|       B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111,B11111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111,B11111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, | ||||
|       B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001110, | ||||
|       B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100, | ||||
|       B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000, | ||||
|       B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11110000, | ||||
|       B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 | ||||
|     }; | ||||
| 
 | ||||
|     const unsigned char start_bmp2[] PROGMEM = { | ||||
|       B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111, | ||||
|       B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11111111, | ||||
|       B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111,B11111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111, | ||||
|       B11000000,B00001111,B11000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111, | ||||
|       B11000000,B00111111,B11100001,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111,B11111111, | ||||
|       B11000000,B01111111,B11110011,B11111111,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111, | ||||
|       B11000000,B11111111,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111, | ||||
|       B11000001,B11111000,B01111111,B10000111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, | ||||
|       B11000001,B11110000,B00111111,B00000011,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, | ||||
|       B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001110, | ||||
|       B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100, | ||||
|       B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000, | ||||
|       B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11110000, | ||||
|       B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 | ||||
|     }; | ||||
| 
 | ||||
|     const unsigned char start_bmp3[] PROGMEM = { | ||||
|       B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111, | ||||
|       B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11111111, | ||||
|       B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111,B11111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111, | ||||
|       B11000000,B00001111,B11000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111, | ||||
|       B11000000,B00111111,B11100001,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111,B11111111, | ||||
|       B11000000,B01111111,B11110011,B11111111,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111, | ||||
|       B11000000,B11111111,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111, | ||||
|       B11000001,B11111000,B01111111,B10000111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, | ||||
|       B11000001,B11110000,B00111111,B00000011,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00011111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11110011,B11111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B11100000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B01111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B01111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B00111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11100000,B00111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B00111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B00111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B11111111,B00111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B00111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, | ||||
|       B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001110, | ||||
|       B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100, | ||||
|       B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000, | ||||
|       B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11110000, | ||||
|       B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 | ||||
|     }; | ||||
| 
 | ||||
|     const unsigned char start_bmp4[] PROGMEM = { | ||||
|       B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111, | ||||
|       B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11111111, | ||||
|       B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111,B11111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111, | ||||
|       B11000000,B00001111,B11000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111, | ||||
|       B11000000,B00111111,B11100001,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001111,B11111111, | ||||
|       B11000000,B01111111,B11110011,B11111111,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111, | ||||
|       B11000000,B11111111,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111, | ||||
|       B11000001,B11111000,B01111111,B10000111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111, | ||||
|       B11000001,B11110000,B00111111,B00000011,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00011111,B00000000,B00000011,B11100000,B00000000,B00000000,B00000000,B00000000,B01111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B11000000,B00001111,B11111000,B00000000,B00000000,B00000000,B00000000,B00111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B11100000,B00011111,B11111100,B00000000,B00000000,B00000000,B00000000,B00011111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B11110000,B00111111,B11111110,B00000000,B00000000,B00000000,B00000000,B00001111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11110011,B11111000,B00111111,B00111110,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B11100000,B11111100,B01111100,B00011111,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B01111100,B01111100,B00001111,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B01111100,B01111000,B00001111,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B00111100,B01111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11100000,B00111100,B01111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B00111111,B11111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B00111111,B11111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B11111111,B00111111,B11111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B00111111,B11111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, | ||||
|       B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001110, | ||||
|       B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100, | ||||
|       B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000, | ||||
|       B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11110000, | ||||
|       B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 | ||||
|     }; | ||||
| 
 | ||||
|     const unsigned char start_bmp5[] PROGMEM = { | ||||
|       B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111, | ||||
|       B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11111111, | ||||
|       B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111,B11111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00111111,B11111111, | ||||
|       B11000000,B00001111,B11000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00011111,B11111111, | ||||
|       B11000000,B00111111,B11100001,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00001111,B11111111, | ||||
|       B11000000,B01111111,B11110011,B11111111,B10000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000111,B11111111, | ||||
|       B11000000,B11111111,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000011,B11111111, | ||||
|       B11000001,B11111000,B01111111,B10000111,B11100000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000001,B11111111, | ||||
|       B11000001,B11110000,B00111111,B00000011,B11100000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000000,B11111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00011111,B00000000,B00000011,B11100000,B01111000,B00000000,B00000000,B00000000,B01111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B11000000,B00001111,B11111000,B01111000,B00000000,B00000000,B00000000,B00111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B11100000,B00011111,B11111100,B01111000,B00000000,B00000000,B00000000,B00011111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B11110000,B00111111,B11111110,B01111000,B00000000,B00000000,B00000000,B00001111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11110011,B11111000,B00111111,B00111110,B01111000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B11100000,B11111100,B01111100,B00011111,B01111000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B01111100,B01111100,B00001111,B01111000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B01111100,B01111000,B00001111,B01111000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B00111100,B01111000,B00000000,B01111000,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11100000,B00111100,B01111000,B00000000,B01111100,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B00111111,B11111000,B00000000,B01111111,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B00111111,B11111000,B00000000,B00111111,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B11111111,B00111111,B11111000,B00000000,B00011111,B00000000,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B00111111,B11111000,B00000000,B00001111,B00000000,B00000000,B00000000,B00000011, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, | ||||
|       B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001110, | ||||
|       B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100, | ||||
|       B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000, | ||||
|       B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11110000, | ||||
|       B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 | ||||
|     }; | ||||
| 
 | ||||
|     const unsigned char start_bmp6[] PROGMEM = { | ||||
|       B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111, | ||||
|       B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111, | ||||
|       B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11111111, | ||||
|       B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000001,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111111,B11111111, | ||||
|       B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00111111,B11111111, | ||||
|       B11000000,B00001111,B11000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00011000,B00000000,B00011111,B11111111, | ||||
|       B11000000,B00111111,B11100001,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00111100,B00000000,B00001111,B11111111, | ||||
|       B11000000,B01111111,B11110011,B11111111,B10000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00111100,B00000000,B00000111,B11111111, | ||||
|       B11000000,B11111111,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000,B00000000,B01111000,B00111100,B00000000,B00000011,B11111111, | ||||
|       B11000001,B11111000,B01111111,B10000111,B11100000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000001,B11111111, | ||||
|       B11000001,B11110000,B00111111,B00000011,B11100000,B00000000,B00000000,B00000000,B00000000,B01111000,B00000000,B00000000,B00000000,B11111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B00011111,B00000000,B00000011,B11100000,B01111000,B00111100,B00000000,B00000000,B01111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B11000000,B00001111,B11111000,B01111000,B00111100,B00000000,B00000000,B00111111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B11100000,B00011111,B11111100,B01111000,B00111100,B00000000,B00000000,B00011111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B11110000,B00111111,B11111110,B01111000,B00111100,B00000000,B00000000,B00001111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11110011,B11111000,B00111111,B00111110,B01111000,B00111100,B00000000,B00000000,B00000111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B11100000,B11111100,B01111100,B00011111,B01111000,B00111100,B00000000,B00000000,B00000111, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B01111100,B01111100,B00001111,B01111000,B00111100,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B01111100,B01111000,B00001111,B01111000,B00111100,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00111100,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00111100,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B10000000,B00111100,B01111000,B00000000,B01111000,B00111100,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100111,B11000000,B00111100,B01111000,B00000000,B01111000,B00111100,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11100000,B00111100,B01111000,B00000000,B01111100,B00111100,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100011,B11111111,B00111111,B11111000,B00000000,B01111111,B10111100,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100001,B11111111,B00111111,B11111000,B00000000,B00111111,B10111111,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B11111111,B00111111,B11111000,B00000000,B00011111,B10111111,B00000000,B00000000,B00000011, | ||||
|       B11000001,B11100000,B00011110,B00000001,B11100000,B01111111,B00111111,B11111000,B00000000,B00001111,B10111111,B00000000,B00000000,B00000011, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111, | ||||
|       B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110, | ||||
|       B01110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001110, | ||||
|       B00111000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100, | ||||
|       B00011110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111000, | ||||
|       B00001111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11110000, | ||||
|       B00000001,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B10000000 | ||||
|     }; | ||||
| 
 | ||||
|   #endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #if ENABLED(BOOT_MARLIN_LOGO_ANIMATED) | ||||
|   #ifndef MARLIN_BOOTSCREEN_FRAME_TIME | ||||
|     #define MARLIN_BOOTSCREEN_FRAME_TIME 100 // (ms)
 | ||||
|   #endif | ||||
|   const unsigned char * const marlin_bootscreen_animation[] PROGMEM = { | ||||
|     start_bmp1, start_bmp2, start_bmp3, start_bmp4, start_bmp5, start_bmp6, start_bmp | ||||
|   }; | ||||
| #endif | ||||
| 
 | ||||
| #ifndef START_BMP_BYTEWIDTH | ||||
|   #define START_BMP_BYTEWIDTH ((START_BMPWIDTH + 7) / 8) | ||||
|   #define START_BMP_BYTEWIDTH CEILING(START_BMPWIDTH, 8) | ||||
| #endif | ||||
| #ifndef START_BMPHEIGHT | ||||
|   #define START_BMPHEIGHT (sizeof(start_bmp) / (START_BMP_BYTEWIDTH)) | ||||
|  | ||||
| @ -1220,10 +1220,10 @@ | ||||
|     #define STATUS_HOTEND4_WIDTH STATUS_HOTEND3_WIDTH | ||||
|   #endif | ||||
|   #ifndef STATUS_HOTEND5_WIDTH | ||||
|     #define STATUS_HOTEND5_WIDTH STATUS_HOTEND5_WIDTH | ||||
|     #define STATUS_HOTEND5_WIDTH STATUS_HOTEND4_WIDTH | ||||
|   #endif | ||||
|   #ifndef STATUS_HOTEND6_WIDTH | ||||
|     #define STATUS_HOTEND6_WIDTH STATUS_HOTEND6_WIDTH | ||||
|     #define STATUS_HOTEND6_WIDTH STATUS_HOTEND5_WIDTH | ||||
|   #endif | ||||
| 
 | ||||
|   constexpr uint8_t status_hotend_width[HOTENDS] = ARRAY_N(HOTENDS, STATUS_HOTEND1_WIDTH, STATUS_HOTEND2_WIDTH, STATUS_HOTEND3_WIDTH, STATUS_HOTEND4_WIDTH, STATUS_HOTEND5_WIDTH, STATUS_HOTEND6_WIDTH); | ||||
| @ -1264,10 +1264,10 @@ | ||||
|     #define STATUS_HOTEND4_X STATUS_HOTEND3_X + STATUS_HEATERS_XSPACE | ||||
|   #endif | ||||
|   #ifndef STATUS_HOTEND5_X | ||||
|     #define STATUS_HOTEND5_X STATUS_HOTEND5_X + STATUS_HEATERS_XSPACE | ||||
|     #define STATUS_HOTEND5_X STATUS_HOTEND4_X + STATUS_HEATERS_XSPACE | ||||
|   #endif | ||||
|   #ifndef STATUS_HOTEND6_X | ||||
|     #define STATUS_HOTEND6_X STATUS_HOTEND6_X + STATUS_HEATERS_XSPACE | ||||
|     #define STATUS_HOTEND6_X STATUS_HOTEND5_X + STATUS_HEATERS_XSPACE | ||||
|   #endif | ||||
| 
 | ||||
|   #if HOTENDS > 2 | ||||
| @ -1291,10 +1291,10 @@ | ||||
|         #define STATUS_HOTEND4_TEXT_X STATUS_HOTEND3_TEXT_X + STATUS_HEATERS_XSPACE | ||||
|       #endif | ||||
|       #ifndef STATUS_HOTEND5_TEXT_X | ||||
|         #define STATUS_HOTEND5_TEXT_X STATUS_HOTEND5_TEXT_X + STATUS_HEATERS_XSPACE | ||||
|         #define STATUS_HOTEND5_TEXT_X STATUS_HOTEND4_TEXT_X + STATUS_HEATERS_XSPACE | ||||
|       #endif | ||||
|       #ifndef STATUS_HOTEND6_TEXT_X | ||||
|         #define STATUS_HOTEND6_TEXT_X STATUS_HOTEND6_TEXT_X + STATUS_HEATERS_XSPACE | ||||
|         #define STATUS_HOTEND6_TEXT_X STATUS_HOTEND5_TEXT_X + STATUS_HEATERS_XSPACE | ||||
|       #endif | ||||
|       constexpr uint8_t status_hotend_text_x[] = ARRAY_N(HOTENDS, STATUS_HOTEND1_TEXT_X, STATUS_HOTEND2_TEXT_X, STATUS_HOTEND3_TEXT_X, STATUS_HOTEND4_TEXT_X, STATUS_HOTEND5_TEXT_X, STATUS_HOTEND6_TEXT_X); | ||||
|       #define STATUS_HOTEND_TEXT_X(N) status_hotend_text_x[N] | ||||
|  | ||||
| @ -22,7 +22,7 @@ | ||||
| 
 | ||||
| int lcd_glyph_height(void) { return u8g_GetFontBBXHeight(u8g.getU8g()); } | ||||
| 
 | ||||
| void lcd_moveto(const uint8_t col, const uint8_t row) { u8g.setPrintPos(col, row); } | ||||
| void lcd_moveto(const lcd_uint_t col, const lcd_uint_t row) { u8g.setPrintPos(col, row); } | ||||
| 
 | ||||
| void lcd_put_int(const int i) { u8g.print(i); } | ||||
| 
 | ||||
| @ -33,26 +33,22 @@ int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) { | ||||
|     u8g.print((char)c); | ||||
|     return u8g_GetFontBBXWidth(u8g.getU8g()); | ||||
|   } | ||||
|   unsigned int x = u8g.getPrintCol(), | ||||
|                y = u8g.getPrintRow(), | ||||
|                ret = uxg_DrawWchar(u8g.getU8g(), x, y, c, max_length); | ||||
|   u8g_uint_t x = u8g.getPrintCol(), y = u8g.getPrintRow(), | ||||
|            ret = uxg_DrawWchar(u8g.getU8g(), x, y, c, max_length); | ||||
|   u8g.setPrintPos(x + ret, y); | ||||
| 
 | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| int lcd_put_u8str_max(const char * utf8_str, pixel_len_t max_length) { | ||||
|   unsigned int x = u8g.getPrintCol(), | ||||
|                y = u8g.getPrintRow(), | ||||
|                ret = uxg_DrawUtf8Str(u8g.getU8g(), x, y, utf8_str, max_length); | ||||
|   u8g_uint_t x = u8g.getPrintCol(), y = u8g.getPrintRow(), | ||||
|            ret = uxg_DrawUtf8Str(u8g.getU8g(), x, y, utf8_str, max_length); | ||||
|   u8g.setPrintPos(x + ret, y); | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| int lcd_put_u8str_max_P(PGM_P utf8_str_P, pixel_len_t max_length) { | ||||
|   unsigned int x = u8g.getPrintCol(), | ||||
|                y = u8g.getPrintRow(), | ||||
|                ret = uxg_DrawUtf8StrP(u8g.getU8g(), x, y, utf8_str_P, max_length); | ||||
|   u8g_uint_t x = u8g.getPrintCol(), y = u8g.getPrintRow(), | ||||
|            ret = uxg_DrawUtf8StrP(u8g.getU8g(), x, y, utf8_str_P, max_length); | ||||
|   u8g.setPrintPos(x + ret, y); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| @ -100,8 +100,7 @@ | ||||
| FORCE_INLINE void _draw_centered_temp(const int16_t temp, const uint8_t tx, const uint8_t ty) { | ||||
|   const char *str = i16tostr3(temp); | ||||
|   const uint8_t len = str[0] != ' ' ? 3 : str[1] != ' ' ? 2 : 1; | ||||
|   lcd_moveto(tx - len * (INFO_FONT_WIDTH) / 2 + 1, ty); | ||||
|   lcd_put_u8str(&str[3-len]); | ||||
|   lcd_put_u8str(tx - len * (INFO_FONT_WIDTH) / 2 + 1, ty, &str[3-len]); | ||||
|   lcd_put_wchar(LCD_STR_DEGREE[0]); | ||||
| } | ||||
| 
 | ||||
| @ -264,8 +263,7 @@ FORCE_INLINE void _draw_heater_status(const heater_ind_t heater, const bool blin | ||||
| //
 | ||||
| FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const bool blink) { | ||||
|   const uint8_t offs = (XYZ_SPACING) * axis; | ||||
|   lcd_moveto(X_LABEL_POS + offs, XYZ_BASELINE); | ||||
|   lcd_put_wchar('X' + axis); | ||||
|   lcd_put_wchar(X_LABEL_POS + offs, XYZ_BASELINE, 'X' + axis); | ||||
|   lcd_moveto(X_VALUE_POS + offs, XYZ_BASELINE); | ||||
|   if (blink) | ||||
|     lcd_put_u8str(value); | ||||
| @ -429,8 +427,7 @@ void MarlinUI::draw_status_screen() { | ||||
|               c = '*'; | ||||
|             } | ||||
|           #endif | ||||
|           lcd_moveto(STATUS_FAN_TEXT_X, STATUS_FAN_TEXT_Y); | ||||
|           lcd_put_u8str(i16tostr3(thermalManager.fanPercent(spd))); | ||||
|           lcd_put_u8str(STATUS_FAN_TEXT_X, STATUS_FAN_TEXT_Y, i16tostr3(thermalManager.fanPercent(spd))); | ||||
|           lcd_put_wchar(c); | ||||
|         } | ||||
|       } | ||||
| @ -488,8 +485,7 @@ void MarlinUI::draw_status_screen() { | ||||
|       #if ENABLED(DOGM_SD_PERCENT) | ||||
|         if (PAGE_CONTAINS(41, 48)) { | ||||
|           // Percent complete
 | ||||
|           lcd_moveto(55, 48); | ||||
|           lcd_put_u8str(ui8tostr3(progress)); | ||||
|           lcd_put_u8str(55, 48, ui8tostr3(progress)); | ||||
|           lcd_put_wchar('%'); | ||||
|         } | ||||
|       #endif | ||||
| @ -510,8 +506,7 @@ void MarlinUI::draw_status_screen() { | ||||
|       duration_t elapsed = print_job_timer.duration(); | ||||
|       bool has_days = (elapsed.value >= 60*60*24L); | ||||
|       uint8_t len = elapsed.toDigital(buffer, has_days); | ||||
|       lcd_moveto(SD_DURATION_X, EXTRAS_BASELINE); | ||||
|       lcd_put_u8str(buffer); | ||||
|       lcd_put_u8str(SD_DURATION_X, EXTRAS_BASELINE, buffer); | ||||
|     } | ||||
| 
 | ||||
|   #endif // HAS_PRINT_PROGRESS
 | ||||
| @ -520,10 +515,6 @@ void MarlinUI::draw_status_screen() { | ||||
|   // XYZ Coordinates
 | ||||
|   //
 | ||||
| 
 | ||||
|   #define X_LABEL_POS  3 | ||||
|   #define X_VALUE_POS 11 | ||||
|   #define XYZ_SPACING 37 | ||||
| 
 | ||||
|   #if ENABLED(XYZ_HOLLOW_FRAME) | ||||
|     #define XYZ_FRAME_TOP 29 | ||||
|     #define XYZ_FRAME_HEIGHT INFO_FONT_ASCENT + 3 | ||||
| @ -550,8 +541,6 @@ void MarlinUI::draw_status_screen() { | ||||
| 
 | ||||
|         // Two-component mix / gradient instead of XY
 | ||||
| 
 | ||||
|         lcd_moveto(X_LABEL_POS, XYZ_BASELINE); | ||||
| 
 | ||||
|         char mixer_messages[12]; | ||||
|         const char *mix_label; | ||||
|         #if ENABLED(GRADIENT_MIX) | ||||
| @ -566,7 +555,7 @@ void MarlinUI::draw_status_screen() { | ||||
|             mix_label = "Mx"; | ||||
|           } | ||||
|         sprintf_P(mixer_messages, PSTR("%s %d;%d%% "), mix_label, int(mixer.mix[0]), int(mixer.mix[1])); | ||||
|         lcd_put_u8str(mixer_messages); | ||||
|         lcd_put_u8str(X_LABEL_POS, XYZ_BASELINE, mixer_messages); | ||||
| 
 | ||||
|       #else | ||||
| 
 | ||||
| @ -591,28 +580,22 @@ void MarlinUI::draw_status_screen() { | ||||
| 
 | ||||
|   if (PAGE_CONTAINS(EXTRAS_2_BASELINE - INFO_FONT_ASCENT, EXTRAS_2_BASELINE - 1)) { | ||||
|     set_font(FONT_MENU); | ||||
|     lcd_moveto(3, EXTRAS_2_BASELINE); | ||||
|     lcd_put_wchar(LCD_STR_FEEDRATE[0]); | ||||
|     lcd_put_wchar(3, EXTRAS_2_BASELINE, LCD_STR_FEEDRATE[0]); | ||||
| 
 | ||||
|     set_font(FONT_STATUSMENU); | ||||
|     lcd_moveto(12, EXTRAS_2_BASELINE); | ||||
|     lcd_put_u8str(i16tostr3(feedrate_percentage)); | ||||
|     lcd_put_u8str(12, EXTRAS_2_BASELINE, i16tostr3(feedrate_percentage)); | ||||
|     lcd_put_wchar('%'); | ||||
| 
 | ||||
|     //
 | ||||
|     // Filament sensor display if SD is disabled
 | ||||
|     //
 | ||||
|     #if ENABLED(FILAMENT_LCD_DISPLAY) && DISABLED(SDSUPPORT) | ||||
|       lcd_moveto(56, EXTRAS_2_BASELINE); | ||||
|       lcd_put_u8str(wstring); | ||||
|       lcd_moveto(102, EXTRAS_2_BASELINE); | ||||
|       lcd_put_u8str(mstring); | ||||
|       lcd_put_u8str(56, EXTRAS_2_BASELINE, wstring); | ||||
|       lcd_put_u8str(102, EXTRAS_2_BASELINE, mstring); | ||||
|       lcd_put_wchar('%'); | ||||
|       set_font(FONT_MENU); | ||||
|       lcd_moveto(47, EXTRAS_2_BASELINE); | ||||
|       lcd_put_wchar(LCD_STR_FILAM_DIA[0]); // lcd_put_u8str_P(PSTR(LCD_STR_FILAM_DIA));
 | ||||
|       lcd_moveto(93, EXTRAS_2_BASELINE); | ||||
|       lcd_put_wchar(LCD_STR_FILAM_MUL[0]); | ||||
|       lcd_put_wchar(47, EXTRAS_2_BASELINE, LCD_STR_FILAM_DIA[0]); // lcd_put_u8str_P(PSTR(LCD_STR_FILAM_DIA));
 | ||||
|       lcd_put_wchar(93, EXTRAS_2_BASELINE, LCD_STR_FILAM_MUL[0]); | ||||
|     #endif | ||||
|   } | ||||
| 
 | ||||
|  | ||||
| @ -102,30 +102,29 @@ void MarlinUI::set_font(const MarlinFont font_nr) { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| bool MarlinUI::detected() { return true; } | ||||
| 
 | ||||
| #if ENABLED(SHOW_BOOTSCREEN) | ||||
| 
 | ||||
|   #if ENABLED(SHOW_CUSTOM_BOOTSCREEN) | ||||
|     // Draws a slice of a particular frame of the custom bootscreen, without the u8g loop
 | ||||
|     void MarlinUI::draw_custom_bootscreen(const uint8_t frame/*=0*/) { | ||||
|       constexpr u8g_uint_t left = u8g_uint_t((LCD_PIXEL_WIDTH  - (CUSTOM_BOOTSCREEN_BMPWIDTH)) / 2), | ||||
|                            top = u8g_uint_t((LCD_PIXEL_HEIGHT - (CUSTOM_BOOTSCREEN_BMPHEIGHT)) / 2); | ||||
|                             top = u8g_uint_t((LCD_PIXEL_HEIGHT - (CUSTOM_BOOTSCREEN_BMPHEIGHT)) / 2); | ||||
|       #if ENABLED(CUSTOM_BOOTSCREEN_INVERTED) | ||||
|         constexpr u8g_uint_t right = left + CUSTOM_BOOTSCREEN_BMPWIDTH, | ||||
|                             bottom = top + CUSTOM_BOOTSCREEN_BMPHEIGHT; | ||||
|       #endif | ||||
| 
 | ||||
|       const u8g_pgm_uint8_t * const bmp = | ||||
|         #if ENABLED(ANIMATED_BOOTSCREEN) | ||||
|         #if ENABLED(CUSTOM_BOOTSCREEN_ANIMATED) | ||||
|           (u8g_pgm_uint8_t*)pgm_read_ptr(&custom_bootscreen_animation[frame]) | ||||
|         #else | ||||
|           custom_start_bmp | ||||
|         #endif | ||||
|       ; | ||||
| 
 | ||||
|       u8g.drawBitmapP( | ||||
|         left, top, | ||||
|         CEILING(CUSTOM_BOOTSCREEN_BMPWIDTH, 8), CUSTOM_BOOTSCREEN_BMPHEIGHT, bmp | ||||
|       ); | ||||
|       u8g.drawBitmapP(left, top, CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH, CUSTOM_BOOTSCREEN_BMPHEIGHT, bmp); | ||||
| 
 | ||||
|       #if ENABLED(CUSTOM_BOOTSCREEN_INVERTED) | ||||
|         if (frame == 0) { | ||||
| @ -140,7 +139,7 @@ void MarlinUI::set_font(const MarlinFont font_nr) { | ||||
| 
 | ||||
|     // Shows the custom bootscreen, with the u8g loop, animations and delays
 | ||||
|     void MarlinUI::show_custom_bootscreen() { | ||||
|       #if DISABLED(ANIMATED_BOOTSCREEN) | ||||
|       #if DISABLED(CUSTOM_BOOTSCREEN_ANIMATED) | ||||
|         constexpr millis_t d = 0; | ||||
|         constexpr uint8_t f = 0; | ||||
|       #else | ||||
| @ -163,23 +162,22 @@ void MarlinUI::set_font(const MarlinFont font_nr) { | ||||
|   // Draws a slice of the Marlin bootscreen, without the u8g loop
 | ||||
|   void MarlinUI::draw_marlin_bootscreen() { | ||||
|     // Screen dimensions.
 | ||||
|     //const uint8_t width = u8g.getWidth(), height = u8g.getHeight();
 | ||||
|     constexpr uint8_t width = LCD_PIXEL_WIDTH, height = LCD_PIXEL_HEIGHT; | ||||
|     //const u8g_uint_t width = u8g.getWidth(), height = u8g.getHeight();
 | ||||
|     constexpr u8g_uint_t width = LCD_PIXEL_WIDTH, height = LCD_PIXEL_HEIGHT; | ||||
| 
 | ||||
|     // Determine text space needed
 | ||||
|     #ifndef STRING_SPLASH_LINE2 | ||||
|       constexpr uint8_t text_total_height = MENU_FONT_HEIGHT, | ||||
|                         text_width_1 = uint8_t(sizeof(STRING_SPLASH_LINE1) - 1) * uint8_t(MENU_FONT_WIDTH), | ||||
|                         text_width_2 = 0; | ||||
|       constexpr u8g_uint_t text_total_height = MENU_FONT_HEIGHT, | ||||
|                            text_width_2 = 0; | ||||
|     #else | ||||
|       constexpr uint8_t text_total_height = uint8_t(MENU_FONT_HEIGHT) * 2, | ||||
|                         text_width_1 = uint8_t(sizeof(STRING_SPLASH_LINE1) - 1) * uint8_t(MENU_FONT_WIDTH), | ||||
|                         text_width_2 = uint8_t(sizeof(STRING_SPLASH_LINE2) - 1) * uint8_t(MENU_FONT_WIDTH); | ||||
|       constexpr u8g_uint_t text_total_height = (MENU_FONT_HEIGHT) * 2, | ||||
|                            text_width_2 = u8g_uint_t((sizeof(STRING_SPLASH_LINE2) - 1) * (MENU_FONT_WIDTH)); | ||||
|     #endif | ||||
|     constexpr uint8_t text_max_width = _MAX(text_width_1, text_width_2), | ||||
|                       rspace = width - (START_BMPWIDTH); | ||||
|     constexpr u8g_uint_t text_width_1 = u8g_uint_t((sizeof(STRING_SPLASH_LINE1) - 1) * (MENU_FONT_WIDTH)), | ||||
|                          text_max_width = _MAX(text_width_1, text_width_2), | ||||
|                          rspace = width - (START_BMPWIDTH); | ||||
| 
 | ||||
|     int8_t offx, offy, txt_base, txt_offx_1, txt_offx_2; | ||||
|     u8g_int_t offx, offy, txt_base, txt_offx_1, txt_offx_2; | ||||
| 
 | ||||
|     // Can the text fit to the right of the bitmap?
 | ||||
|     if (text_max_width < rspace) { | ||||
| @ -200,13 +198,29 @@ void MarlinUI::set_font(const MarlinFont font_nr) { | ||||
|     NOLESS(offx, 0); | ||||
|     NOLESS(offy, 0); | ||||
| 
 | ||||
|     u8g.drawBitmapP(offx, offy, (START_BMPWIDTH + 7) / 8, START_BMPHEIGHT, start_bmp); | ||||
|     set_font(FONT_MENU); | ||||
|     #ifndef STRING_SPLASH_LINE2 | ||||
|       u8g.drawStr(txt_offx_1, txt_base, STRING_SPLASH_LINE1); | ||||
|     auto draw_bootscreen_bmp = [&](const uint8_t *bitmap) { | ||||
|       u8g.drawBitmapP(offx, offy, START_BMP_BYTEWIDTH, START_BMPHEIGHT, bitmap); | ||||
|       set_font(FONT_MENU); | ||||
|       #ifndef STRING_SPLASH_LINE2 | ||||
|         lcd_put_u8str_P(txt_offx_1, txt_base, PSTR(STRING_SPLASH_LINE1)); | ||||
|       #else | ||||
|         lcd_put_u8str_P(txt_offx_1, txt_base - (MENU_FONT_HEIGHT), PSTR(STRING_SPLASH_LINE1)); | ||||
|         lcd_put_u8str_P(txt_offx_2, txt_base, PSTR(STRING_SPLASH_LINE2)); | ||||
|       #endif | ||||
|     }; | ||||
| 
 | ||||
|     #if DISABLED(BOOT_MARLIN_LOGO_ANIMATED) | ||||
|       draw_bootscreen_bmp(start_bmp); | ||||
|     #else | ||||
|       u8g.drawStr(txt_offx_1, txt_base - (MENU_FONT_HEIGHT), STRING_SPLASH_LINE1); | ||||
|       u8g.drawStr(txt_offx_2, txt_base, STRING_SPLASH_LINE2); | ||||
|       constexpr millis_t d = MARLIN_BOOTSCREEN_FRAME_TIME; | ||||
|       LOOP_L_N(f, COUNT(marlin_bootscreen_animation)) { | ||||
|         u8g.firstPage(); | ||||
|         do { | ||||
|           const u8g_pgm_uint8_t * const bmp = (u8g_pgm_uint8_t*)pgm_read_ptr(&marlin_bootscreen_animation[f]); | ||||
|           draw_bootscreen_bmp(bmp); | ||||
|         } while (u8g.nextPage()); | ||||
|         if (d) safe_delay(d); | ||||
|       } | ||||
|     #endif | ||||
|   } | ||||
| 
 | ||||
| @ -286,16 +300,13 @@ void MarlinUI::draw_kill_screen() { | ||||
|   #if ENABLED(LIGHTWEIGHT_UI) | ||||
|     ST7920_Lite_Status_Screen::clear_text_buffer(); | ||||
|   #endif | ||||
|   const uint8_t h4 = u8g.getHeight() / 4; | ||||
|   const u8g_uint_t h4 = u8g.getHeight() / 4; | ||||
|   u8g.firstPage(); | ||||
|   do { | ||||
|     set_font(FONT_MENU); | ||||
|     lcd_moveto(0, h4 * 1); | ||||
|     lcd_put_u8str(status_message); | ||||
|     lcd_moveto(0, h4 * 2); | ||||
|     lcd_put_u8str_P(PSTR(MSG_HALTED)); | ||||
|     lcd_moveto(0, h4 * 3); | ||||
|     lcd_put_u8str_P(PSTR(MSG_PLEASE_RESET)); | ||||
|     lcd_put_u8str(0, h4 * 1, status_message); | ||||
|     lcd_put_u8str_P(0, h4 * 2, PSTR(MSG_HALTED)); | ||||
|     lcd_put_u8str_P(0, h4 * 3, PSTR(MSG_PLEASE_RESET)); | ||||
|   } while (u8g.nextPage()); | ||||
| } | ||||
| 
 | ||||
| @ -303,7 +314,7 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop | ||||
| 
 | ||||
| #if HAS_LCD_MENU | ||||
| 
 | ||||
|   uint8_t row_y1, row_y2; | ||||
|   u8g_uint_t row_y1, row_y2; | ||||
| 
 | ||||
|   #if ENABLED(ADVANCED_PAUSE_FEATURE) | ||||
| 
 | ||||
| @ -313,8 +324,7 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop | ||||
| 
 | ||||
|       if (!PAGE_CONTAINS(row_y1 + 1, row_y2 + 2)) return; | ||||
| 
 | ||||
|       lcd_moveto(LCD_PIXEL_WIDTH - 11 * (MENU_FONT_WIDTH), row_y2); | ||||
|       lcd_put_wchar('E'); | ||||
|       lcd_put_wchar(LCD_PIXEL_WIDTH - 11 * (MENU_FONT_WIDTH), row_y2, 'E'); | ||||
|       lcd_put_wchar((char)('1' + extruder)); | ||||
|       lcd_put_wchar(' '); | ||||
|       lcd_put_u8str(i16tostr3(thermalManager.degHotend(extruder))); | ||||
| @ -360,7 +370,7 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop | ||||
| 
 | ||||
|     if (mark_as_selected(row, invert)) { | ||||
| 
 | ||||
|       uint8_t n = LCD_PIXEL_WIDTH; // pixel width of string allowed
 | ||||
|       u8g_uint_t n = LCD_PIXEL_WIDTH; // pixel width of string allowed
 | ||||
| 
 | ||||
|       if (center && !valstr) { | ||||
|         int8_t pad = (LCD_WIDTH - utf8_strlen_P(pstr)) / 2; | ||||
| @ -377,11 +387,10 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop | ||||
|     UNUSED(pre_char); | ||||
| 
 | ||||
|     if (mark_as_selected(row, sel)) { | ||||
|       uint8_t n = (LCD_WIDTH - 2) * (MENU_FONT_WIDTH); | ||||
|       u8g_uint_t n = (LCD_WIDTH - 2) * (MENU_FONT_WIDTH); | ||||
|       n -= lcd_put_u8str_max_P(pstr, n); | ||||
|       while (n > MENU_FONT_WIDTH) n -= lcd_put_wchar(' '); | ||||
|       lcd_moveto(LCD_PIXEL_WIDTH - (MENU_FONT_WIDTH), row_y2); | ||||
|       lcd_put_wchar(post_char); | ||||
|       lcd_put_wchar(LCD_PIXEL_WIDTH - (MENU_FONT_WIDTH), row_y2, post_char); | ||||
|       lcd_put_wchar(' '); | ||||
|     } | ||||
|   } | ||||
| @ -390,7 +399,7 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop | ||||
|   void _draw_menu_item_edit(const bool sel, const uint8_t row, PGM_P const pstr, const char* const data, const bool pgm) { | ||||
|     if (mark_as_selected(row, sel)) { | ||||
|       const uint8_t vallen = (pgm ? utf8_strlen_P(data) : utf8_strlen((char*)data)); | ||||
|       uint8_t n = (LCD_WIDTH - 2 - vallen) * (MENU_FONT_WIDTH); | ||||
|       u8g_uint_t n = (LCD_WIDTH - 2 - vallen) * (MENU_FONT_WIDTH); | ||||
|       n -= lcd_put_u8str_max_P(pstr, n); | ||||
|       lcd_put_wchar(':'); | ||||
|       while (n > MENU_FONT_WIDTH) n -= lcd_put_wchar(' '); | ||||
| @ -402,13 +411,13 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop | ||||
|   void draw_edit_screen(PGM_P const pstr, const char* const value/*=nullptr*/) { | ||||
|     ui.encoder_direction_normal(); | ||||
| 
 | ||||
|     const uint8_t labellen = utf8_strlen_P(pstr), vallen = utf8_strlen(value); | ||||
|     const u8g_uint_t labellen = utf8_strlen_P(pstr), vallen = utf8_strlen(value); | ||||
|     bool extra_row = labellen > LCD_WIDTH - 2 - vallen; | ||||
| 
 | ||||
|     #if ENABLED(USE_BIG_EDIT_FONT) | ||||
|       // Use the menu font if the label won't fit on a single line
 | ||||
|       constexpr uint8_t lcd_edit_width = (LCD_PIXEL_WIDTH) / (EDIT_FONT_WIDTH); | ||||
|       uint8_t lcd_chr_fit, one_chr_width; | ||||
|       constexpr u8g_uint_t lcd_edit_width = (LCD_PIXEL_WIDTH) / (EDIT_FONT_WIDTH); | ||||
|       u8g_uint_t lcd_chr_fit, one_chr_width; | ||||
|       if (labellen <= lcd_edit_width - 1) { | ||||
|         if (labellen + vallen + 1 > lcd_edit_width) extra_row = true; | ||||
|         lcd_chr_fit = lcd_edit_width + 1; | ||||
| @ -421,20 +430,17 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop | ||||
|         ui.set_font(FONT_MENU); | ||||
|       } | ||||
|     #else | ||||
|       constexpr uint8_t lcd_chr_fit = LCD_WIDTH, | ||||
|                         one_chr_width = MENU_FONT_WIDTH; | ||||
|       constexpr u8g_uint_t lcd_chr_fit = LCD_WIDTH, | ||||
|                            one_chr_width = MENU_FONT_WIDTH; | ||||
|     #endif | ||||
| 
 | ||||
|     // Center the label and value lines on the middle line
 | ||||
|     uint8_t baseline = extra_row ? (LCD_PIXEL_HEIGHT) / 2 - 1 | ||||
|                                  : (LCD_PIXEL_HEIGHT + EDIT_FONT_ASCENT) / 2; | ||||
|     u8g_uint_t baseline = extra_row ? (LCD_PIXEL_HEIGHT) / 2 - 1 | ||||
|                                     : (LCD_PIXEL_HEIGHT + EDIT_FONT_ASCENT) / 2; | ||||
| 
 | ||||
|     // Assume the label is alpha-numeric (with a descender)
 | ||||
|     bool onpage = PAGE_CONTAINS(baseline - (EDIT_FONT_ASCENT - 1), baseline + EDIT_FONT_DESCENT); | ||||
|     if (onpage) { | ||||
|       lcd_moveto(0, baseline); | ||||
|       lcd_put_u8str_P(pstr); | ||||
|     } | ||||
|     if (onpage) lcd_put_u8str_P(0, baseline, pstr); | ||||
| 
 | ||||
|     // If a value is included, print a colon, then print the value right-justified
 | ||||
|     if (value != nullptr) { | ||||
| @ -445,23 +451,21 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop | ||||
|         onpage = PAGE_CONTAINS(baseline - (EDIT_FONT_ASCENT - 1), baseline); | ||||
|       } | ||||
|       if (onpage) { | ||||
|         lcd_moveto(((lcd_chr_fit - 1) - (vallen + 1)) * one_chr_width, baseline); // Right-justified, leaving padded by spaces
 | ||||
|         lcd_put_wchar(' '); // overwrite char if value gets shorter
 | ||||
|         lcd_put_wchar(((lcd_chr_fit - 1) - (vallen + 1)) * one_chr_width, baseline, ' '); // Right-justified, padded, add a leading space
 | ||||
|         lcd_put_u8str(value); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   inline void draw_boxed_string(const uint8_t x, const uint8_t y, PGM_P const pstr, const bool inv) { | ||||
|     const uint8_t len = utf8_strlen_P(pstr), bw = len * (MENU_FONT_WIDTH), | ||||
|                   bx = x * (MENU_FONT_WIDTH), by = (y + 1) * (MENU_FONT_HEIGHT); | ||||
|   inline void draw_boxed_string(const u8g_uint_t x, const u8g_uint_t y, PGM_P const pstr, const bool inv) { | ||||
|     const u8g_uint_t len = utf8_strlen_P(pstr), bw = len * (MENU_FONT_WIDTH), | ||||
|                      bx = x * (MENU_FONT_WIDTH), by = (y + 1) * (MENU_FONT_HEIGHT); | ||||
|     if (inv) { | ||||
|       u8g.setColorIndex(1); | ||||
|       u8g.drawBox(bx - 1, by - (MENU_FONT_ASCENT) + 1, bw + 2, MENU_FONT_HEIGHT - 1); | ||||
|       u8g.setColorIndex(0); | ||||
|     } | ||||
|     lcd_moveto(bx, by); | ||||
|     lcd_put_u8str_P(pstr); | ||||
|     lcd_put_u8str_P(bx, by, pstr); | ||||
|     if (inv) u8g.setColorIndex(1); | ||||
|   } | ||||
| 
 | ||||
| @ -479,8 +483,8 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop | ||||
|       if (mark_as_selected(row, sel)) { | ||||
|         if (isDir) lcd_put_wchar(LCD_STR_FOLDER[0]); | ||||
|         constexpr uint8_t maxlen = LCD_WIDTH - 1; | ||||
|         const uint8_t pixw = maxlen * (MENU_FONT_WIDTH); | ||||
|         uint8_t n = pixw - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, row, sel), pixw); | ||||
|         const u8g_uint_t pixw = maxlen * (MENU_FONT_WIDTH); | ||||
|         u8g_uint_t n = pixw - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, row, sel), pixw); | ||||
|         while (n > MENU_FONT_WIDTH) n -= lcd_put_wchar(' '); | ||||
|       } | ||||
|     } | ||||
| @ -499,8 +503,8 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop | ||||
| 
 | ||||
|     void MarlinUI::ubl_plot(const uint8_t x_plot, const uint8_t y_plot) { | ||||
|       // Scale the box pixels appropriately
 | ||||
|       uint8_t x_map_pixels = ((MAP_MAX_PIXELS_X - 4) / (GRID_MAX_POINTS_X)) * (GRID_MAX_POINTS_X), | ||||
|               y_map_pixels = ((MAP_MAX_PIXELS_Y - 4) / (GRID_MAX_POINTS_Y)) * (GRID_MAX_POINTS_Y), | ||||
|       u8g_uint_t x_map_pixels = ((MAP_MAX_PIXELS_X - 4) / (GRID_MAX_POINTS_X)) * (GRID_MAX_POINTS_X), | ||||
|                  y_map_pixels = ((MAP_MAX_PIXELS_Y - 4) / (GRID_MAX_POINTS_Y)) * (GRID_MAX_POINTS_Y), | ||||
| 
 | ||||
|               pixels_per_x_mesh_pnt = x_map_pixels / (GRID_MAX_POINTS_X), | ||||
|               pixels_per_y_mesh_pnt = y_map_pixels / (GRID_MAX_POINTS_Y), | ||||
| @ -522,8 +526,8 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop | ||||
|       // Display Mesh Point Locations
 | ||||
| 
 | ||||
|       u8g.setColorIndex(1); | ||||
|       const uint8_t sx = x_offset + pixels_per_x_mesh_pnt / 2; | ||||
|             uint8_t  y = y_offset + pixels_per_y_mesh_pnt / 2; | ||||
|       const u8g_uint_t sx = x_offset + pixels_per_x_mesh_pnt / 2; | ||||
|             u8g_uint_t  y = y_offset + pixels_per_y_mesh_pnt / 2; | ||||
|       for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++, y += pixels_per_y_mesh_pnt) | ||||
|         if (PAGE_CONTAINS(y, y)) | ||||
|           for (uint8_t i = 0, x = sx; i < GRID_MAX_POINTS_X; i++, x += pixels_per_x_mesh_pnt) | ||||
| @ -531,10 +535,10 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop | ||||
| 
 | ||||
|       // Fill in the Specified Mesh Point
 | ||||
| 
 | ||||
|       uint8_t inverted_y = GRID_MAX_POINTS_Y - y_plot - 1;  // The origin is typically in the lower right corner.  We need to
 | ||||
|                                                             // invert the Y to get it to plot in the right location.
 | ||||
|       const uint8_t y_plot_inv = (GRID_MAX_POINTS_Y - 1) - y_plot;  // The origin is typically in the lower right corner.  We need to
 | ||||
|                                                                     // invert the Y to get it to plot in the right location.
 | ||||
| 
 | ||||
|       const uint8_t by = y_offset + inverted_y * pixels_per_y_mesh_pnt; | ||||
|       const u8g_uint_t by = y_offset + y_plot_inv * pixels_per_y_mesh_pnt; | ||||
|       if (PAGE_CONTAINS(by, by + pixels_per_y_mesh_pnt)) | ||||
|         u8g.drawBox( | ||||
|           x_offset + x_plot * pixels_per_x_mesh_pnt, by, | ||||
| @ -546,26 +550,22 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop | ||||
|       // Show X and Y positions at top of screen
 | ||||
|       u8g.setColorIndex(1); | ||||
|       if (PAGE_UNDER(7)) { | ||||
|         lcd_moveto(5, 7); | ||||
|         lcd_put_u8str("X:"); | ||||
|         lcd_put_u8str(5, 7, "X:"); | ||||
|         lcd_put_u8str(ftostr52(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot])))); | ||||
|         lcd_moveto(74, 7); | ||||
|         lcd_put_u8str("Y:"); | ||||
|         lcd_put_u8str(74, 7, "Y:"); | ||||
|         lcd_put_u8str(ftostr52(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot])))); | ||||
|       } | ||||
| 
 | ||||
|       // Print plot position
 | ||||
|       if (PAGE_CONTAINS(LCD_PIXEL_HEIGHT - (INFO_FONT_HEIGHT - 1), LCD_PIXEL_HEIGHT)) { | ||||
|         lcd_moveto(5, LCD_PIXEL_HEIGHT); | ||||
|         lcd_put_wchar('('); | ||||
|         lcd_put_wchar(5, LCD_PIXEL_HEIGHT, '('); | ||||
|         u8g.print(x_plot); | ||||
|         lcd_put_wchar(','); | ||||
|         u8g.print(y_plot); | ||||
|         lcd_put_wchar(')'); | ||||
| 
 | ||||
|         // Show the location value
 | ||||
|         lcd_moveto(74, LCD_PIXEL_HEIGHT); | ||||
|         lcd_put_u8str("Z:"); | ||||
|         lcd_put_u8str(74, LCD_PIXEL_HEIGHT, "Z:"); | ||||
|         if (!isnan(ubl.z_values[x_plot][y_plot])) | ||||
|           lcd_put_u8str(ftostr43sign(ubl.z_values[x_plot][y_plot])); | ||||
|         else | ||||
|  | ||||
| @ -0,0 +1,560 @@ | ||||
| /*********************
 | ||||
|  * flash_storage.cpp * | ||||
|  *********************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #include "../compat.h" | ||||
| 
 | ||||
| #if ENABLED(LULZBOT_TOUCH_UI) | ||||
| 
 | ||||
| #include "../ftdi_eve_lib/ftdi_eve_lib.h" | ||||
| 
 | ||||
| #include "media_file_reader.h" | ||||
| #include "flash_storage.h" | ||||
| 
 | ||||
| // The following must be changed whenever the layout of the flash
 | ||||
| // data is changed in a manner that would render the data invalid.
 | ||||
| 
 | ||||
| constexpr uint32_t flash_eeprom_version = 1; | ||||
| 
 | ||||
| /* SPI Flash Memory Map:
 | ||||
|  * | ||||
|  * The following offsets and sizes are specified in 4k erase units: | ||||
|  * | ||||
|  * Page    Size     Description | ||||
|  * 0       16       DATA STORAGE AREA | ||||
|  * 16      1        VERSIONING DATA | ||||
|  * 17      inf      MEDIA STORAGE AREA | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #define DATA_STORAGE_SIZE_64K | ||||
| 
 | ||||
| using namespace FTDI::SPI; | ||||
| using namespace FTDI::SPI::most_significant_byte_first; | ||||
| 
 | ||||
| bool UIFlashStorage::is_present = false; | ||||
| 
 | ||||
| #ifdef SPI_FLASH_SS | ||||
| /************************** SPI Flash Chip Interface **************************/ | ||||
| 
 | ||||
|   void SPIFlash::wait_while_busy() { | ||||
|     uint8_t status; | ||||
|     safe_delay(1); | ||||
|     do { | ||||
|      spi_flash_select(); | ||||
|      spi_write_8(READ_STATUS_1); | ||||
|      status = spi_read_8(); | ||||
|      spi_flash_deselect(); | ||||
|      safe_delay(1); | ||||
|     } while (status & 1); | ||||
|   } | ||||
| 
 | ||||
|   void SPIFlash::erase_sector_4k(uint32_t addr) { | ||||
|     spi_flash_select(); | ||||
|     spi_write_8(WRITE_ENABLE); | ||||
|     spi_flash_deselect(); | ||||
| 
 | ||||
|     spi_flash_select(); | ||||
|     spi_write_8(ERASE_4K); | ||||
|     spi_write_24(addr); | ||||
|     spi_flash_deselect(); | ||||
| 
 | ||||
|     wait_while_busy(); | ||||
|   } | ||||
| 
 | ||||
|   void SPIFlash::erase_sector_64k(uint32_t addr) { | ||||
|     spi_flash_select(); | ||||
|     spi_write_8(WRITE_ENABLE); | ||||
|     spi_flash_deselect(); | ||||
| 
 | ||||
|     spi_flash_select(); | ||||
|     spi_write_8(ERASE_64K); | ||||
|     spi_write_24(addr); | ||||
|     spi_flash_deselect(); | ||||
| 
 | ||||
|     wait_while_busy(); | ||||
|   } | ||||
| 
 | ||||
|   void SPIFlash::spi_write_begin(uint32_t addr) { | ||||
|     spi_flash_select(); | ||||
|     spi_write_8(WRITE_ENABLE); | ||||
|     spi_flash_deselect(); | ||||
| 
 | ||||
|     spi_flash_select(); | ||||
|     spi_write_8(PAGE_PROGRAM); | ||||
|     spi_write_24(addr); | ||||
|   } | ||||
| 
 | ||||
|   void SPIFlash::spi_write_end() { | ||||
|     spi_flash_deselect(); | ||||
|     wait_while_busy(); | ||||
|   } | ||||
| 
 | ||||
|   void SPIFlash::spi_read_begin(uint32_t addr) { | ||||
|     spi_flash_select(); | ||||
|     spi_write_8(READ_DATA); | ||||
|     spi_write_24(addr); | ||||
|   } | ||||
| 
 | ||||
|   void SPIFlash::spi_read_end() { | ||||
|     spi_flash_deselect(); | ||||
|   } | ||||
| 
 | ||||
|   void SPIFlash::erase_chip() { | ||||
|     spi_flash_select(); | ||||
|     spi_write_8(WRITE_ENABLE); | ||||
|     spi_flash_deselect(); | ||||
| 
 | ||||
|     spi_flash_select(); | ||||
|     spi_write_8(ERASE_CHIP); | ||||
|     spi_flash_deselect(); | ||||
|     wait_while_busy(); | ||||
|   } | ||||
| 
 | ||||
|   void SPIFlash::read_jedec_id(uint8_t &manufacturer_id, uint8_t &device_type, uint8_t &capacity) { | ||||
|     spi_flash_select(); | ||||
|     spi_write_8(READ_JEDEC_ID); | ||||
|     manufacturer_id = spi_recv(); | ||||
|     device_type     = spi_recv(); | ||||
|     capacity        = spi_recv(); | ||||
|     spi_flash_deselect (); | ||||
|   } | ||||
| 
 | ||||
|   /* This function writes "size" bytes from "data" starting at addr, while properly
 | ||||
|    * taking into account the special case of writing across a 256 byte page boundary. | ||||
|    * Returns the addr directly after the write. | ||||
|    */ | ||||
|   uint32_t SPIFlash::write(uint32_t addr, const void *_data, size_t size) { | ||||
|     const uint8_t *data = (const uint8_t*) _data; | ||||
|     while (size) { | ||||
|       const uint32_t page_start = addr & 0xFFFF00ul; | ||||
|       const uint32_t page_end   = page_start + 256; | ||||
|       const uint32_t write_size = min(page_end - addr, size); | ||||
|       spi_write_begin(addr); | ||||
|       spi_write_bulk<ram_write>(data, write_size); | ||||
|       spi_write_end(); | ||||
|       addr += write_size; | ||||
|       size -= write_size; | ||||
|       data += write_size; | ||||
|     } | ||||
|     return addr; | ||||
|   } | ||||
| 
 | ||||
|   uint32_t SPIFlash::read(uint32_t addr, void *data, size_t size) { | ||||
|     spi_read_begin(addr); | ||||
|     spi_read_bulk(data, size); | ||||
|     spi_read_end(); | ||||
|     return addr + size; | ||||
|   } | ||||
| 
 | ||||
|   /********************************** UTILITY ROUTINES *********************************/ | ||||
| 
 | ||||
|   bool UIFlashStorage::check_known_device() { | ||||
|     uint8_t manufacturer_id, device_type, capacity; | ||||
|     read_jedec_id(manufacturer_id, device_type, capacity); | ||||
| 
 | ||||
|     const bool is_known = | ||||
|         ((manufacturer_id == 0xEF) && (device_type == 0x40) && (capacity == 0x15)) || // unknown
 | ||||
|         ((manufacturer_id == 0x01) && (device_type == 0x40) && (capacity == 0x15)) || // Cypress S25FL116K
 | ||||
|         ((manufacturer_id == 0xEF) && (device_type == 0x14) && (capacity == 0x15)) || // Winbond W25Q16JV
 | ||||
|         ((manufacturer_id == 0x1F) && (device_type == 0x86) && (capacity == 0x01)) ;  // Adesto AT255F161
 | ||||
| 
 | ||||
|     if (!is_known) { | ||||
|       SERIAL_ECHO_START(); SERIAL_ECHOLNPGM("Unable to locate supported SPI Flash Memory."); | ||||
|       SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR("  Manufacturer ID, got: ", manufacturer_id); | ||||
|       SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR("  Device Type    , got: ", device_type); | ||||
|       SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR("  Capacity       , got: ", capacity); | ||||
|     } | ||||
| 
 | ||||
|     return is_known; | ||||
|   } | ||||
| 
 | ||||
|   void UIFlashStorage::initialize() { | ||||
|     for(uint8_t i = 0; i < 10; i++) { | ||||
|       if (check_known_device()) { | ||||
|         is_present = true; | ||||
|         break; | ||||
|       } | ||||
|       safe_delay(1000); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /**************************** DATA STORAGE AREA (first 4K or 64k) ********************/ | ||||
| 
 | ||||
|   #ifdef DATA_STORAGE_SIZE_64K | ||||
|     constexpr uint32_t data_storage_area_size = 64 * 1024; // Large erase unit
 | ||||
|   #else | ||||
|     constexpr uint32_t data_storage_area_size =  4 * 1024; // Small erase unit
 | ||||
|   #endif | ||||
| 
 | ||||
|   /* In order to provide some degree of wear leveling, each data write to the
 | ||||
|    * SPI Flash chip is appended to data that was already written before, until | ||||
|    * the data storage area is completely filled. New data is written preceeded | ||||
|    * with a 32-bit delimiter 'LULZ', so that we can distinguish written and | ||||
|    * unwritten data: | ||||
|    * | ||||
|    *        'LULZ'         <--- 1st record delimiter | ||||
|    *        <data_byte> | ||||
|    *        <data_byte> | ||||
|    *        <data_byte> | ||||
|    *        'LULZ'         <--- 2nd record delimiter | ||||
|    *        <data_byte> | ||||
|    *        <data_byte> | ||||
|    *        <data_byte> | ||||
|    *           ... | ||||
|    *        'LULZ'         <--- Last record delimiter | ||||
|    *        <data_byte> | ||||
|    *        <data_byte> | ||||
|    *        <data_byte> | ||||
|    *        0xFF           <--- Start of free space | ||||
|    *        0xFF | ||||
|    *           ... | ||||
|    * | ||||
|    * This function walks down the data storage area, verifying that the | ||||
|    * delimiters are either 'LULZ' or 0xFFFFFFFF. In the case that an invalid | ||||
|    * delimiter is found, this function returns -1, indicating that the Flash | ||||
|    * data is invalid (this will happen if the block_size changed with respect | ||||
|    * to earlier firmware). Otherwise, it returns the offset of the last | ||||
|    * valid delimiter 'LULZ', indicating the most recently written data. | ||||
|    */ | ||||
|   int32_t UIFlashStorage::get_config_read_offset(uint32_t block_size) { | ||||
|     uint16_t stride = 4 + block_size; | ||||
|     int32_t read_offset = -1; | ||||
| 
 | ||||
|     for(uint32_t offset = 0; offset < (data_storage_area_size - stride); offset += stride) { | ||||
|       uint32_t delim; | ||||
|       spi_read_begin(offset); | ||||
|       spi_read_bulk (&delim, sizeof(delim)); | ||||
|       spi_read_end(); | ||||
|       switch (delim) { | ||||
|         case 0xFFFFFFFFul: return read_offset; | ||||
|         case delimiter:    read_offset = offset; break; | ||||
|         default: | ||||
|           SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR("Invalid delimiter in Flash: ", delim); | ||||
|           return -1; | ||||
|       } | ||||
|     } | ||||
|     SERIAL_ECHO_START(); SERIAL_ECHOLNPGM("No LULZ delimiter found."); | ||||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   /* This function returns the offset at which new data should be
 | ||||
|    * appended, or -1 if the Flash needs to be erased */ | ||||
|   int32_t UIFlashStorage::get_config_write_offset(uint32_t block_size) { | ||||
|     int32_t read_offset = get_config_read_offset(block_size); | ||||
|     if (read_offset == -1) return -1; // The SPI flash is invalid
 | ||||
| 
 | ||||
|     int32_t write_offset = read_offset + 4 + block_size; | ||||
|     if ((write_offset + 4 + block_size) > data_storage_area_size) { | ||||
|       SERIAL_ECHO_START(); SERIAL_ECHOLNPGM("Not enough free space in Flash."); | ||||
|       return -1; // Not enough free space
 | ||||
|     } | ||||
|     return write_offset; | ||||
|   } | ||||
| 
 | ||||
|   bool UIFlashStorage::verify_config_data(const void *data, size_t size) { | ||||
|     if (!is_present) return false; | ||||
| 
 | ||||
|     int32_t read_addr = get_config_read_offset(size); | ||||
|     if (read_addr == -1) return false; | ||||
| 
 | ||||
|     uint32_t delim; | ||||
|     spi_read_begin(read_addr); | ||||
|     spi_read_bulk (&delim, sizeof(delim)); | ||||
|     bool ok = spi_verify_bulk(data,size); | ||||
|     spi_read_end(); | ||||
|     return ok && delim == delimiter; | ||||
|   } | ||||
| 
 | ||||
|   bool UIFlashStorage::read_config_data(void *data, size_t size) { | ||||
|     if (!is_present) return false; | ||||
| 
 | ||||
|     int32_t read_addr = get_config_read_offset(size); | ||||
|     if (read_addr == -1) return false; | ||||
| 
 | ||||
|     uint32_t delim; | ||||
|     spi_read_begin(read_addr); | ||||
|     spi_read_bulk (&delim, sizeof(delim)); | ||||
|     spi_read_bulk (data, size); | ||||
|     spi_read_end(); | ||||
|     return delim == delimiter; | ||||
|   } | ||||
| 
 | ||||
|   void UIFlashStorage::write_config_data(const void *data, size_t size) { | ||||
|     if (!is_present) { | ||||
|       SERIAL_ECHO_START(); SERIAL_ECHOLNPGM("SPI Flash chip not present. Not saving UI settings."); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     // Since Flash storage has a limited number of write cycles,
 | ||||
|     // make sure that the data is different before rewriting.
 | ||||
| 
 | ||||
|     if (verify_config_data(data, size)) { | ||||
|       SERIAL_ECHO_START(); SERIAL_ECHOLNPGM("UI settings already written, skipping write."); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     int16_t write_addr = get_config_write_offset(size); | ||||
|     if (write_addr == -1) { | ||||
|       SERIAL_ECHO_START(); | ||||
|       SERIAL_ECHOPGM("Erasing UI settings from SPI Flash... "); | ||||
|       #ifdef DATA_STORAGE_SIZE_64K | ||||
|         erase_sector_64k(0); | ||||
|       #else | ||||
|         erase_sector_4k(0); | ||||
|       #endif | ||||
|       write_addr = 0; | ||||
|       SERIAL_ECHOLNPGM("DONE"); | ||||
|     } | ||||
| 
 | ||||
|     SERIAL_ECHO_START(); | ||||
|     SERIAL_ECHOPAIR("Writing UI settings to SPI Flash (offset ", write_addr); | ||||
|     SERIAL_ECHOPGM(")..."); | ||||
| 
 | ||||
|     const uint32_t delim = delimiter; | ||||
|     write_addr = write(write_addr, &delim, sizeof(delim)); | ||||
|     write_addr = write(write_addr, data, size); | ||||
| 
 | ||||
|     SERIAL_ECHOLNPGM("DONE"); | ||||
|   } | ||||
| 
 | ||||
|   /************************** VERSIONING INFO AREA ************************/ | ||||
| 
 | ||||
|   /* The version info area follows the data storage area. If the version
 | ||||
|    * is incorrect, the data on the chip is invalid and format_flash should | ||||
|    * be called. | ||||
|    */ | ||||
| 
 | ||||
|   typedef struct { | ||||
|     uint32_t magic; | ||||
|     uint32_t version; | ||||
|   } flash_version_info; | ||||
| 
 | ||||
|   constexpr uint32_t version_info_addr = data_storage_area_size; | ||||
|   constexpr uint32_t version_info_size = 4 * 1024; // Small erase unit
 | ||||
| 
 | ||||
|   bool UIFlashStorage::is_valid() { | ||||
|     flash_version_info info; | ||||
| 
 | ||||
|     spi_read_begin(version_info_addr); | ||||
|     spi_read_bulk (&info, sizeof(flash_version_info)); | ||||
|     spi_read_end(); | ||||
| 
 | ||||
|     return info.magic == delimiter && info.version == flash_eeprom_version; | ||||
|   } | ||||
| 
 | ||||
|   void UIFlashStorage::write_version_info() { | ||||
|     flash_version_info info; | ||||
| 
 | ||||
|     info.magic   = delimiter; | ||||
|     info.version = flash_eeprom_version; | ||||
| 
 | ||||
|     spi_write_begin(version_info_addr); | ||||
|     spi_write_bulk<ram_write>(&info, sizeof(flash_version_info)); | ||||
|     spi_write_end(); | ||||
|   } | ||||
| 
 | ||||
|   /**************************** MEDIA STORAGE AREA *****************************/ | ||||
| 
 | ||||
|   /* The media storage area follows the versioning info area. It consists
 | ||||
|    * of a file index followed by the data for one or more media files. | ||||
|    * | ||||
|    * The file index consists of an array of 32-bit file sizes. If a file | ||||
|    * is not present, the file's size will be set to 0xFFFFFFFF | ||||
|    */ | ||||
| 
 | ||||
|   constexpr uint32_t media_storage_addr    = version_info_addr + version_info_size; | ||||
|   constexpr uint8_t  media_storage_slots   = 4; | ||||
| 
 | ||||
|   void UIFlashStorage::format_flash() { | ||||
|     SERIAL_ECHO_START(); SERIAL_ECHOPGM("Erasing SPI Flash..."); | ||||
|     SPIFlash::erase_chip(); | ||||
|     SERIAL_ECHOLNPGM("DONE"); | ||||
| 
 | ||||
|     write_version_info(); | ||||
|   } | ||||
| 
 | ||||
|   uint32_t UIFlashStorage::get_media_file_start(uint8_t slot) { | ||||
|     uint32_t addr = media_storage_addr + sizeof(uint32_t) * media_storage_slots; | ||||
|     spi_read_begin(media_storage_addr); | ||||
|     for(uint8_t i = 0; i < slot; i++) { | ||||
|       addr += spi_read_32(); | ||||
|     } | ||||
|     spi_read_end(); | ||||
|     return addr; | ||||
|   } | ||||
| 
 | ||||
|   void UIFlashStorage::set_media_file_size(uint8_t slot, uint32_t size) { | ||||
|     spi_write_begin(media_storage_addr + sizeof(uint32_t) * slot); | ||||
|     spi_write_32(size); | ||||
|     spi_write_end(); | ||||
|   } | ||||
| 
 | ||||
|   uint32_t UIFlashStorage::get_media_file_size(uint8_t slot) { | ||||
|     spi_read_begin(media_storage_addr + sizeof(uint32_t) * slot); | ||||
|     uint32_t size = spi_read_32(); | ||||
|     spi_read_end(); | ||||
|     return size; | ||||
|   } | ||||
| 
 | ||||
|   /* Writes a media file from the SD card/USB flash drive into a slot on the SPI Flash. Media
 | ||||
|    * files must be written sequentially following by a chip erase and it is not possible to | ||||
|    * overwrite files. */ | ||||
|   UIFlashStorage::error_t UIFlashStorage::write_media_file(progmem_str filename, uint8_t slot) { | ||||
|     #if ENABLED(SDSUPPORT) | ||||
|       uint32_t addr; | ||||
|       uint8_t buff[write_page_size]; | ||||
| 
 | ||||
|       strcpy_P( (char*) buff, (const char*) filename); | ||||
| 
 | ||||
|       MediaFileReader reader; | ||||
|       if (!reader.open((char*) buff)) { | ||||
|         SERIAL_ECHO_START(); SERIAL_ECHOLNPGM("Unable to find media file"); | ||||
|         return FILE_NOT_FOUND; | ||||
|       } | ||||
| 
 | ||||
|       if (get_media_file_size(slot) != 0xFFFFFFFFUL) { | ||||
|         SERIAL_ECHO_START(); SERIAL_ECHOLNPGM("Media file already exists"); | ||||
|         return WOULD_OVERWRITE; | ||||
|       } | ||||
| 
 | ||||
|       SERIAL_ECHO_START(); SERIAL_ECHOPGM("Writing SPI Flash..."); | ||||
| 
 | ||||
|       set_media_file_size(slot, reader.size()); | ||||
|       addr = get_media_file_start(slot); | ||||
| 
 | ||||
|       // Write out the file itself
 | ||||
|       for(;;) { | ||||
|         const int16_t nBytes = reader.read(buff, write_page_size); | ||||
|         if (nBytes == -1) { | ||||
|           SERIAL_ECHOLNPGM("Failed to read from file"); | ||||
|           return READ_ERROR; | ||||
|         } | ||||
| 
 | ||||
|         addr = write(addr, buff, nBytes); | ||||
|         if (nBytes != write_page_size) | ||||
|           break; | ||||
| 
 | ||||
|         #if ENABLED(EXTENSIBLE_UI) | ||||
|           ExtUI::yield(); | ||||
|         #endif | ||||
|       } | ||||
| 
 | ||||
|       SERIAL_ECHOLNPGM("DONE"); | ||||
| 
 | ||||
|       SERIAL_ECHO_START(); SERIAL_ECHOPGM("Verifying SPI Flash..."); | ||||
| 
 | ||||
|       bool verifyOk = true; | ||||
| 
 | ||||
|       // Verify the file index
 | ||||
| 
 | ||||
|       if (get_media_file_start(slot+1) != (get_media_file_start(slot) + reader.size())) { | ||||
|         SERIAL_ECHOLNPGM("File index verification failed. "); | ||||
|         verifyOk = false; | ||||
|       } | ||||
| 
 | ||||
|       // Verify the file itself
 | ||||
|       addr = get_media_file_start(slot); | ||||
|       reader.rewind(); | ||||
| 
 | ||||
|       while (verifyOk) { | ||||
|         const int16_t nBytes = reader.read(buff, write_page_size); | ||||
|         if (nBytes == -1) { | ||||
|           SERIAL_ECHOPGM("Failed to read from file"); | ||||
|           verifyOk = false; | ||||
|           break; | ||||
|         } | ||||
| 
 | ||||
|         spi_read_begin(addr); | ||||
|         if (!spi_verify_bulk(buff, nBytes)) { | ||||
|           verifyOk = false; | ||||
|           spi_read_end(); | ||||
|           break; | ||||
|         } | ||||
|         spi_read_end(); | ||||
| 
 | ||||
|         addr += nBytes; | ||||
|         if (nBytes != write_page_size) break; | ||||
|         #if ENABLED(EXTENSIBLE_UI) | ||||
|           ExtUI::yield(); | ||||
|         #endif | ||||
|       }; | ||||
| 
 | ||||
|       if (verifyOk) { | ||||
|         SERIAL_ECHOLNPGM("DONE"); | ||||
|         return SUCCESS; | ||||
|       } else { | ||||
|         SERIAL_ECHOLNPGM("FAIL"); | ||||
|         return VERIFY_ERROR; | ||||
|       } | ||||
|     #else | ||||
|       return VERIFY_ERROR; | ||||
|     #endif // ENABLED(SDSUPPORT)
 | ||||
|   } | ||||
| 
 | ||||
|   bool UIFlashStorage::BootMediaReader::isAvailable(uint32_t slot) { | ||||
|     if (!is_present) return false; | ||||
| 
 | ||||
|     bytes_remaining = get_media_file_size(slot); | ||||
|     if (bytes_remaining != 0xFFFFFFFFUL) { | ||||
|       SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR("Boot media file size:", bytes_remaining); | ||||
|       addr = get_media_file_start(slot); | ||||
|       return true; | ||||
|     } else { | ||||
|       return false; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   int16_t UIFlashStorage::BootMediaReader::read(void *data, const size_t size) { | ||||
|     if (bytes_remaining == 0xFFFFFFFFUL) return -1; | ||||
| 
 | ||||
|     if (size > bytes_remaining) | ||||
|       return read(data, bytes_remaining); | ||||
| 
 | ||||
|     if (size > 0) { | ||||
|       spi_read_begin(addr); | ||||
|       spi_read_bulk(data, size); | ||||
|       spi_read_end(); | ||||
|       addr += size; | ||||
|       bytes_remaining -= size; | ||||
|     } | ||||
| 
 | ||||
|     return size; | ||||
|   } | ||||
| 
 | ||||
|   int16_t UIFlashStorage::BootMediaReader::read(void *obj, void *data, const size_t size) { | ||||
|     return reinterpret_cast<UIFlashStorage::BootMediaReader*>(obj)->read(data, size); | ||||
|   } | ||||
| 
 | ||||
| #else | ||||
|   void UIFlashStorage::initialize()                                           {} | ||||
|   bool UIFlashStorage::is_valid()                                             {return true;} | ||||
|   void UIFlashStorage::write_config_data(const void *, size_t)                {} | ||||
|   bool UIFlashStorage::verify_config_data(const void *, size_t)               {return false;} | ||||
|   bool UIFlashStorage::read_config_data(void *, size_t )                      {return false;} | ||||
|   UIFlashStorage::error_t UIFlashStorage::write_media_file(progmem_str, uint8_t) {return FILE_NOT_FOUND;} | ||||
|   void UIFlashStorage::format_flash()                                         {} | ||||
| 
 | ||||
|   bool UIFlashStorage::BootMediaReader::isAvailable(uint32_t)                 {return false;} | ||||
|   int16_t UIFlashStorage::BootMediaReader::read(void *, const size_t)         {return -1;} | ||||
|   int16_t UIFlashStorage::BootMediaReader::read(void *, void *, const size_t) {return -1;} | ||||
| #endif // SPI_FLASH_SS
 | ||||
| #endif // LULZBOT_TOUCH_UI
 | ||||
| @ -0,0 +1,106 @@ | ||||
| /*******************
 | ||||
|  * flash_storage.h * | ||||
|  *******************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| class SPIFlash { | ||||
|   public: | ||||
|     static constexpr uint32_t erase_unit_size = 4 * 1024; // Minimum erase unit
 | ||||
|     static constexpr uint32_t write_page_size = 256;      // Minimum page write unit
 | ||||
| 
 | ||||
|     enum { | ||||
|       READ_STATUS_1 = 0x05, | ||||
|       READ_STATUS_2 = 0x35, | ||||
|       READ_STATUS_3 = 0x33, | ||||
|       WRITE_ENABLE  = 0x06, | ||||
|       WRITE_DISABLE = 0x04, | ||||
|       READ_ID       = 0x90, | ||||
|       READ_JEDEC_ID = 0x9F, | ||||
|       READ_DATA     = 0x03, | ||||
|       PAGE_PROGRAM  = 0x02, | ||||
|       ERASE_4K      = 0x20, | ||||
|       ERASE_64K     = 0xD8, | ||||
|       ERASE_CHIP    = 0xC7 | ||||
|     }; | ||||
| 
 | ||||
|     static void wait_while_busy(); | ||||
|     static void erase_sector_4k(uint32_t addr); | ||||
|     static void erase_sector_64k(uint32_t addr); | ||||
|     static void erase_chip  (); | ||||
| 
 | ||||
|     static void read_jedec_id(uint8_t &manufacturer_id, uint8_t &device_type, uint8_t &capacity); | ||||
| 
 | ||||
|     static void spi_read_begin(uint32_t addr); | ||||
|     static void spi_read_end(); | ||||
| 
 | ||||
|     static void spi_write_begin(uint32_t addr); | ||||
|     static void spi_write_end(); | ||||
| 
 | ||||
|     static uint32_t write(uint32_t addr, const void *data, size_t size); | ||||
|     static uint32_t read(uint32_t addr, void *data, size_t size); | ||||
| }; | ||||
| 
 | ||||
| class UIFlashStorage : private SPIFlash { | ||||
|   private: | ||||
| 
 | ||||
|     static bool is_present; | ||||
|     static int32_t  get_config_read_offset(uint32_t block_size); | ||||
|     static int32_t  get_config_write_offset(uint32_t block_size); | ||||
| 
 | ||||
|     static uint32_t get_media_file_start(uint8_t slot); | ||||
|     static void     set_media_file_size(uint8_t slot, uint32_t size); | ||||
|     static uint32_t get_media_file_size(uint8_t slot); | ||||
| 
 | ||||
|     static constexpr uint32_t delimiter = 0x4C554C5A; // 'LULZ'
 | ||||
|   public: | ||||
|     enum error_t { | ||||
|       SUCCESS, | ||||
|       FILE_NOT_FOUND, | ||||
|       READ_ERROR, | ||||
|       VERIFY_ERROR, | ||||
|       WOULD_OVERWRITE | ||||
|     }; | ||||
| 
 | ||||
|     static void    initialize  (); | ||||
|     static void    format_flash (); | ||||
|     static bool    check_known_device(); | ||||
| 
 | ||||
|     static bool    is_valid (); | ||||
|     static void    write_version_info(); | ||||
| 
 | ||||
|     static void    write_config_data  (const void *data, size_t size); | ||||
|     static bool    verify_config_data (const void *data, size_t size); | ||||
|     static bool    read_config_data   (void *data, size_t size); | ||||
|     static error_t write_media_file   (progmem_str filename, uint8_t slot = 0); | ||||
| 
 | ||||
|     class BootMediaReader; | ||||
| }; | ||||
| 
 | ||||
| class UIFlashStorage::BootMediaReader { | ||||
|   private: | ||||
|     uint32_t addr; | ||||
|     uint32_t bytes_remaining; | ||||
| 
 | ||||
|   public: | ||||
|     bool isAvailable(uint32_t slot = 0); | ||||
|     int16_t read(void *buffer, size_t const size); | ||||
| 
 | ||||
|     static int16_t read(void *obj, void *buffer, const size_t size); | ||||
| }; | ||||
| @ -0,0 +1,63 @@ | ||||
| /************************
 | ||||
|  * media_filereader.cpp * | ||||
|  ************************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #include "../compat.h" | ||||
| 
 | ||||
| #if ENABLED(LULZBOT_TOUCH_UI) | ||||
|   #include "media_file_reader.h" | ||||
| 
 | ||||
|   #if ENABLED(SDSUPPORT) | ||||
|     bool MediaFileReader::open(const char* filename) { | ||||
|       card.init(SPI_SPEED, SDSS); | ||||
|       volume.init(&card); | ||||
|       root.openRoot(&volume); | ||||
|       return file.open(&root, filename, O_READ); | ||||
|     } | ||||
| 
 | ||||
|     int16_t MediaFileReader::read(void *buff, size_t bytes) { | ||||
|       return file.read(buff, bytes); | ||||
|     } | ||||
| 
 | ||||
|     void MediaFileReader::close() { | ||||
|       file.close(); | ||||
|     } | ||||
| 
 | ||||
|     uint32_t MediaFileReader::size() { | ||||
|       return file.fileSize(); | ||||
|     } | ||||
| 
 | ||||
|     void MediaFileReader::rewind() { | ||||
|       file.rewind(); | ||||
|     } | ||||
| 
 | ||||
|     int16_t MediaFileReader::read(void *obj, void *buff, size_t bytes) { | ||||
|       return reinterpret_cast<MediaFileReader*>(obj)->read(buff, bytes); | ||||
|     } | ||||
|   #else | ||||
|     bool MediaFileReader::open(const char*)               {return -1;} | ||||
|     int16_t MediaFileReader::read(void *, size_t)         {return 0;} | ||||
|     void MediaFileReader::close()                         {} | ||||
|     uint32_t MediaFileReader::size()                      {return 0;} | ||||
|     void MediaFileReader::rewind()                        {} | ||||
|     int16_t MediaFileReader::read(void *, void *, size_t) {return 0;} | ||||
|   #endif | ||||
| #endif // LULZBOT_TOUCH_UI
 | ||||
| @ -0,0 +1,48 @@ | ||||
| /**********************
 | ||||
|  * media_filereader.h * | ||||
|  **********************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "../../../../../inc/MarlinConfigPre.h" | ||||
| 
 | ||||
| #if ENABLED(SDSUPPORT) | ||||
|   #include "../../../../../sd/SdFile.h" | ||||
|   #include "../../../../../sd/cardreader.h" | ||||
| #endif | ||||
| 
 | ||||
| class MediaFileReader { | ||||
|   private: | ||||
|     #if ENABLED(SDSUPPORT) | ||||
|       Sd2Card  card; | ||||
|       SdVolume volume; | ||||
|       SdFile   root, file; | ||||
|     #endif | ||||
| 
 | ||||
|   public: | ||||
|     bool open(const char* filename); | ||||
|     int16_t read(void *buff, size_t bytes); | ||||
|     uint32_t size(); | ||||
|     void rewind(); | ||||
|     void close(); | ||||
| 
 | ||||
|     static int16_t read(void *obj, void *buff, size_t bytes); | ||||
| }; | ||||
							
								
								
									
										53
									
								
								Marlin/src/lcd/extensible_ui/lib/lulzbot/compat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								Marlin/src/lcd/extensible_ui/lib/lulzbot/compat.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | ||||
| /************
 | ||||
|  * compat.h * | ||||
|  ************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| /**
 | ||||
|  * This following provides compatibility whether compiling | ||||
|  * as a part of Marlin or outside it | ||||
|  */ | ||||
| 
 | ||||
| #if defined __has_include | ||||
|   #if __has_include ("../../ui_api.h") | ||||
|     #include "../../ui_api.h" | ||||
|   #endif | ||||
| #else | ||||
|   #include "../../ui_api.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __MARLIN_FIRMWARE__ | ||||
|   // __MARLIN_FIRMWARE__ exists when compiled within Marlin.
 | ||||
|   #include "pin_mappings.h" | ||||
| #else | ||||
|   // Messages that are declared in Marlin
 | ||||
|   #define WELCOME_MSG        "Printer Ready" | ||||
|   #define MSG_MEDIA_INSERTED "Media Inserted" | ||||
|   #define MSG_MEDIA_REMOVED  "Media Removed" | ||||
| 
 | ||||
|   namespace UI { | ||||
|     static inline uint32_t safe_millis() {return millis();}; | ||||
|     static inline void     yield()       {}; | ||||
|   }; | ||||
| #endif | ||||
| 
 | ||||
| class __FlashStringHelper; | ||||
| typedef const __FlashStringHelper *progmem_str; | ||||
							
								
								
									
										97
									
								
								Marlin/src/lcd/extensible_ui/lib/lulzbot/config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								Marlin/src/lcd/extensible_ui/lib/lulzbot/config.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,97 @@ | ||||
| /************
 | ||||
|  * config.h * | ||||
|  ************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "compat.h" | ||||
| 
 | ||||
| // Define the display board used (see "ftdi_eve_boards.h" for definitions)
 | ||||
| 
 | ||||
| //#define LCD_FTDI_VM800B35A        // FTDI 3.5" 320x240 with FT800
 | ||||
| //#define LCD_4DSYSTEMS_4DLCD_FT843 // 4D Systems 4.3" 480x272
 | ||||
| //#define LCD_HAOYU_FT800CB         // Haoyu with 4.3" or 5" 480x272
 | ||||
| //#define LCD_HAOYU_FT810CB         // Haoyu with 5" 800x480
 | ||||
| //#define LCD_ALEPHOBJECTS_CLCD_UI  // Aleph Objects Color LCD User Interface
 | ||||
| 
 | ||||
| // Leave the following commented out to use a board's default resolution.
 | ||||
| // If you have changed the LCD panel, you may override the resolution
 | ||||
| // below (see "ftdi_eve_resolutions.h" for definitions):
 | ||||
| 
 | ||||
| //#define TOUCH_UI_320x240
 | ||||
| //#define TOUCH_UI_480x272
 | ||||
| //#define TOUCH_UI_800x480
 | ||||
| 
 | ||||
| // Define the printer interface or pins used (see "ui_pin_mappings.h" for definitions):
 | ||||
| 
 | ||||
| //#define CR10_TFT_PINMAP
 | ||||
| //#define AO_EXP1_DEPRECATED_PINMAP  // UltraLCD EXP1 connector, old AlephObject's wiring
 | ||||
| //#define AO_EXP1_PINMAP  // UltraLCD EXP1 connector, new AlephObject's wiring
 | ||||
| //#define AO_EXP2_PINMAP  // UltraLCD EXP2 connector, new AlephObject's wiring
 | ||||
| //#define OTHER_PIN_LAYOUT
 | ||||
| 
 | ||||
| // Otherwise. Define all the pins manually:
 | ||||
| 
 | ||||
| #ifdef OTHER_PIN_LAYOUT | ||||
|     // Select interfacing pins, the following pin specifiers are supported:
 | ||||
|     //
 | ||||
|     //     ARDUINO_DIGITAL_1  - Arduino pin via digitalWrite/digitalRead
 | ||||
|     //     AVR_A1             - Fast AVR port access via PORTA/PINA/DDRA
 | ||||
|     //     1                  - When compiling Marlin, use Marlin pin IDs.
 | ||||
| 
 | ||||
|     // The pins for CS and MOD_RESET (PD) must be chosen.
 | ||||
|     #define CLCD_MOD_RESET                      9 | ||||
|     #define CLCD_SPI_CS                        10 | ||||
| 
 | ||||
|     // If using software SPI, specify pins for SCLK, MOSI, MISO
 | ||||
|     //#define CLCD_USE_SOFT_SPI
 | ||||
|     #ifdef CLCD_USE_SOFT_SPI | ||||
|         #define CLCD_SOFT_SPI_MOSI             11 | ||||
|         #define CLCD_SOFT_SPI_MISO             12 | ||||
|         #define CLCD_SOFT_SPI_SCLK             13 | ||||
|     #endif | ||||
| #endif | ||||
| 
 | ||||
| // Defines how to orient the display. An inverted (i.e. upside-down) display
 | ||||
| // is supported on the FT800. The FT810 or better also support a portrait
 | ||||
| // and mirrored orientation.
 | ||||
| //#define TOUCH_UI_INVERTED
 | ||||
| //#define TOUCH_UI_PORTRAIT
 | ||||
| //#define TOUCH_UI_MIRRORED
 | ||||
| 
 | ||||
| // Use a numeric passcode for "Parental lock".
 | ||||
| // This is a recommended for smaller displays.
 | ||||
| //#define TOUCH_UI_PASSCODE
 | ||||
| 
 | ||||
| // The timeout (in ms) to return to the status screen from sub-menus
 | ||||
| //#define LCD_TIMEOUT_TO_STATUS 15000
 | ||||
| 
 | ||||
| // Enable this to debug the event framework
 | ||||
| //#define UI_FRAMEWORK_DEBUG
 | ||||
| 
 | ||||
| // Enable the developer's menu and screens
 | ||||
| //#define DEVELOPER_SCREENS
 | ||||
| 
 | ||||
| // Maximum feed rate for manual extrusion (mm/s)
 | ||||
| //#define MAX_MANUAL_FEEDRATE 240
 | ||||
| 
 | ||||
| // Sets the SPI speed in Hz
 | ||||
| 
 | ||||
| #define SPI_FREQUENCY 8000000 >> SPI_SPEED | ||||
| @ -0,0 +1,674 @@ | ||||
|                     GNU GENERAL PUBLIC LICENSE | ||||
|                        Version 3, 29 June 2007 | ||||
| 
 | ||||
|  Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> | ||||
|  Everyone is permitted to copy and distribute verbatim copies | ||||
|  of this license document, but changing it is not allowed. | ||||
| 
 | ||||
|                             Preamble | ||||
| 
 | ||||
|   The GNU General Public License is a free, copyleft license for | ||||
| software and other kinds of works. | ||||
| 
 | ||||
|   The licenses for most software and other practical works are designed | ||||
| to take away your freedom to share and change the works.  By contrast, | ||||
| the GNU General Public License is intended to guarantee your freedom to | ||||
| share and change all versions of a program--to make sure it remains free | ||||
| software for all its users.  We, the Free Software Foundation, use the | ||||
| GNU General Public License for most of our software; it applies also to | ||||
| any other work released this way by its authors.  You can apply it to | ||||
| your programs, too. | ||||
| 
 | ||||
|   When we speak of free software, we are referring to freedom, not | ||||
| price.  Our General Public Licenses are designed to make sure that you | ||||
| have the freedom to distribute copies of free software (and charge for | ||||
| them if you wish), that you receive source code or can get it if you | ||||
| want it, that you can change the software or use pieces of it in new | ||||
| free programs, and that you know you can do these things. | ||||
| 
 | ||||
|   To protect your rights, we need to prevent others from denying you | ||||
| these rights or asking you to surrender the rights.  Therefore, you have | ||||
| certain responsibilities if you distribute copies of the software, or if | ||||
| you modify it: responsibilities to respect the freedom of others. | ||||
| 
 | ||||
|   For example, if you distribute copies of such a program, whether | ||||
| gratis or for a fee, you must pass on to the recipients the same | ||||
| freedoms that you received.  You must make sure that they, too, receive | ||||
| or can get the source code.  And you must show them these terms so they | ||||
| know their rights. | ||||
| 
 | ||||
|   Developers that use the GNU GPL protect your rights with two steps: | ||||
| (1) assert copyright on the software, and (2) offer you this License | ||||
| giving you legal permission to copy, distribute and/or modify it. | ||||
| 
 | ||||
|   For the developers' and authors' protection, the GPL clearly explains | ||||
| that there is no warranty for this free software.  For both users' and | ||||
| authors' sake, the GPL requires that modified versions be marked as | ||||
| changed, so that their problems will not be attributed erroneously to | ||||
| authors of previous versions. | ||||
| 
 | ||||
|   Some devices are designed to deny users access to install or run | ||||
| modified versions of the software inside them, although the manufacturer | ||||
| can do so.  This is fundamentally incompatible with the aim of | ||||
| protecting users' freedom to change the software.  The systematic | ||||
| pattern of such abuse occurs in the area of products for individuals to | ||||
| use, which is precisely where it is most unacceptable.  Therefore, we | ||||
| have designed this version of the GPL to prohibit the practice for those | ||||
| products.  If such problems arise substantially in other domains, we | ||||
| stand ready to extend this provision to those domains in future versions | ||||
| of the GPL, as needed to protect the freedom of users. | ||||
| 
 | ||||
|   Finally, every program is threatened constantly by software patents. | ||||
| States should not allow patents to restrict development and use of | ||||
| software on general-purpose computers, but in those that do, we wish to | ||||
| avoid the special danger that patents applied to a free program could | ||||
| make it effectively proprietary.  To prevent this, the GPL assures that | ||||
| patents cannot be used to render the program non-free. | ||||
| 
 | ||||
|   The precise terms and conditions for copying, distribution and | ||||
| modification follow. | ||||
| 
 | ||||
|                        TERMS AND CONDITIONS | ||||
| 
 | ||||
|   0. Definitions. | ||||
| 
 | ||||
|   "This License" refers to version 3 of the GNU General Public License. | ||||
| 
 | ||||
|   "Copyright" also means copyright-like laws that apply to other kinds of | ||||
| works, such as semiconductor masks. | ||||
| 
 | ||||
|   "The Program" refers to any copyrightable work licensed under this | ||||
| License.  Each licensee is addressed as "you".  "Licensees" and | ||||
| "recipients" may be individuals or organizations. | ||||
| 
 | ||||
|   To "modify" a work means to copy from or adapt all or part of the work | ||||
| in a fashion requiring copyright permission, other than the making of an | ||||
| exact copy.  The resulting work is called a "modified version" of the | ||||
| earlier work or a work "based on" the earlier work. | ||||
| 
 | ||||
|   A "covered work" means either the unmodified Program or a work based | ||||
| on the Program. | ||||
| 
 | ||||
|   To "propagate" a work means to do anything with it that, without | ||||
| permission, would make you directly or secondarily liable for | ||||
| infringement under applicable copyright law, except executing it on a | ||||
| computer or modifying a private copy.  Propagation includes copying, | ||||
| distribution (with or without modification), making available to the | ||||
| public, and in some countries other activities as well. | ||||
| 
 | ||||
|   To "convey" a work means any kind of propagation that enables other | ||||
| parties to make or receive copies.  Mere interaction with a user through | ||||
| a computer network, with no transfer of a copy, is not conveying. | ||||
| 
 | ||||
|   An interactive user interface displays "Appropriate Legal Notices" | ||||
| to the extent that it includes a convenient and prominently visible | ||||
| feature that (1) displays an appropriate copyright notice, and (2) | ||||
| tells the user that there is no warranty for the work (except to the | ||||
| extent that warranties are provided), that licensees may convey the | ||||
| work under this License, and how to view a copy of this License.  If | ||||
| the interface presents a list of user commands or options, such as a | ||||
| menu, a prominent item in the list meets this criterion. | ||||
| 
 | ||||
|   1. Source Code. | ||||
| 
 | ||||
|   The "source code" for a work means the preferred form of the work | ||||
| for making modifications to it.  "Object code" means any non-source | ||||
| form of a work. | ||||
| 
 | ||||
|   A "Standard Interface" means an interface that either is an official | ||||
| standard defined by a recognized standards body, or, in the case of | ||||
| interfaces specified for a particular programming language, one that | ||||
| is widely used among developers working in that language. | ||||
| 
 | ||||
|   The "System Libraries" of an executable work include anything, other | ||||
| than the work as a whole, that (a) is included in the normal form of | ||||
| packaging a Major Component, but which is not part of that Major | ||||
| Component, and (b) serves only to enable use of the work with that | ||||
| Major Component, or to implement a Standard Interface for which an | ||||
| implementation is available to the public in source code form.  A | ||||
| "Major Component", in this context, means a major essential component | ||||
| (kernel, window system, and so on) of the specific operating system | ||||
| (if any) on which the executable work runs, or a compiler used to | ||||
| produce the work, or an object code interpreter used to run it. | ||||
| 
 | ||||
|   The "Corresponding Source" for a work in object code form means all | ||||
| the source code needed to generate, install, and (for an executable | ||||
| work) run the object code and to modify the work, including scripts to | ||||
| control those activities.  However, it does not include the work's | ||||
| System Libraries, or general-purpose tools or generally available free | ||||
| programs which are used unmodified in performing those activities but | ||||
| which are not part of the work.  For example, Corresponding Source | ||||
| includes interface definition files associated with source files for | ||||
| the work, and the source code for shared libraries and dynamically | ||||
| linked subprograms that the work is specifically designed to require, | ||||
| such as by intimate data communication or control flow between those | ||||
| subprograms and other parts of the work. | ||||
| 
 | ||||
|   The Corresponding Source need not include anything that users | ||||
| can regenerate automatically from other parts of the Corresponding | ||||
| Source. | ||||
| 
 | ||||
|   The Corresponding Source for a work in source code form is that | ||||
| same work. | ||||
| 
 | ||||
|   2. Basic Permissions. | ||||
| 
 | ||||
|   All rights granted under this License are granted for the term of | ||||
| copyright on the Program, and are irrevocable provided the stated | ||||
| conditions are met.  This License explicitly affirms your unlimited | ||||
| permission to run the unmodified Program.  The output from running a | ||||
| covered work is covered by this License only if the output, given its | ||||
| content, constitutes a covered work.  This License acknowledges your | ||||
| rights of fair use or other equivalent, as provided by copyright law. | ||||
| 
 | ||||
|   You may make, run and propagate covered works that you do not | ||||
| convey, without conditions so long as your license otherwise remains | ||||
| in force.  You may convey covered works to others for the sole purpose | ||||
| of having them make modifications exclusively for you, or provide you | ||||
| with facilities for running those works, provided that you comply with | ||||
| the terms of this License in conveying all material for which you do | ||||
| not control copyright.  Those thus making or running the covered works | ||||
| for you must do so exclusively on your behalf, under your direction | ||||
| and control, on terms that prohibit them from making any copies of | ||||
| your copyrighted material outside their relationship with you. | ||||
| 
 | ||||
|   Conveying under any other circumstances is permitted solely under | ||||
| the conditions stated below.  Sublicensing is not allowed; section 10 | ||||
| makes it unnecessary. | ||||
| 
 | ||||
|   3. Protecting Users' Legal Rights From Anti-Circumvention Law. | ||||
| 
 | ||||
|   No covered work shall be deemed part of an effective technological | ||||
| measure under any applicable law fulfilling obligations under article | ||||
| 11 of the WIPO copyright treaty adopted on 20 December 1996, or | ||||
| similar laws prohibiting or restricting circumvention of such | ||||
| measures. | ||||
| 
 | ||||
|   When you convey a covered work, you waive any legal power to forbid | ||||
| circumvention of technological measures to the extent such circumvention | ||||
| is effected by exercising rights under this License with respect to | ||||
| the covered work, and you disclaim any intention to limit operation or | ||||
| modification of the work as a means of enforcing, against the work's | ||||
| users, your or third parties' legal rights to forbid circumvention of | ||||
| technological measures. | ||||
| 
 | ||||
|   4. Conveying Verbatim Copies. | ||||
| 
 | ||||
|   You may convey verbatim copies of the Program's source code as you | ||||
| receive it, in any medium, provided that you conspicuously and | ||||
| appropriately publish on each copy an appropriate copyright notice; | ||||
| keep intact all notices stating that this License and any | ||||
| non-permissive terms added in accord with section 7 apply to the code; | ||||
| keep intact all notices of the absence of any warranty; and give all | ||||
| recipients a copy of this License along with the Program. | ||||
| 
 | ||||
|   You may charge any price or no price for each copy that you convey, | ||||
| and you may offer support or warranty protection for a fee. | ||||
| 
 | ||||
|   5. Conveying Modified Source Versions. | ||||
| 
 | ||||
|   You may convey a work based on the Program, or the modifications to | ||||
| produce it from the Program, in the form of source code under the | ||||
| terms of section 4, provided that you also meet all of these conditions: | ||||
| 
 | ||||
|     a) The work must carry prominent notices stating that you modified | ||||
|     it, and giving a relevant date. | ||||
| 
 | ||||
|     b) The work must carry prominent notices stating that it is | ||||
|     released under this License and any conditions added under section | ||||
|     7.  This requirement modifies the requirement in section 4 to | ||||
|     "keep intact all notices". | ||||
| 
 | ||||
|     c) You must license the entire work, as a whole, under this | ||||
|     License to anyone who comes into possession of a copy.  This | ||||
|     License will therefore apply, along with any applicable section 7 | ||||
|     additional terms, to the whole of the work, and all its parts, | ||||
|     regardless of how they are packaged.  This License gives no | ||||
|     permission to license the work in any other way, but it does not | ||||
|     invalidate such permission if you have separately received it. | ||||
| 
 | ||||
|     d) If the work has interactive user interfaces, each must display | ||||
|     Appropriate Legal Notices; however, if the Program has interactive | ||||
|     interfaces that do not display Appropriate Legal Notices, your | ||||
|     work need not make them do so. | ||||
| 
 | ||||
|   A compilation of a covered work with other separate and independent | ||||
| works, which are not by their nature extensions of the covered work, | ||||
| and which are not combined with it such as to form a larger program, | ||||
| in or on a volume of a storage or distribution medium, is called an | ||||
| "aggregate" if the compilation and its resulting copyright are not | ||||
| used to limit the access or legal rights of the compilation's users | ||||
| beyond what the individual works permit.  Inclusion of a covered work | ||||
| in an aggregate does not cause this License to apply to the other | ||||
| parts of the aggregate. | ||||
| 
 | ||||
|   6. Conveying Non-Source Forms. | ||||
| 
 | ||||
|   You may convey a covered work in object code form under the terms | ||||
| of sections 4 and 5, provided that you also convey the | ||||
| machine-readable Corresponding Source under the terms of this License, | ||||
| in one of these ways: | ||||
| 
 | ||||
|     a) Convey the object code in, or embodied in, a physical product | ||||
|     (including a physical distribution medium), accompanied by the | ||||
|     Corresponding Source fixed on a durable physical medium | ||||
|     customarily used for software interchange. | ||||
| 
 | ||||
|     b) Convey the object code in, or embodied in, a physical product | ||||
|     (including a physical distribution medium), accompanied by a | ||||
|     written offer, valid for at least three years and valid for as | ||||
|     long as you offer spare parts or customer support for that product | ||||
|     model, to give anyone who possesses the object code either (1) a | ||||
|     copy of the Corresponding Source for all the software in the | ||||
|     product that is covered by this License, on a durable physical | ||||
|     medium customarily used for software interchange, for a price no | ||||
|     more than your reasonable cost of physically performing this | ||||
|     conveying of source, or (2) access to copy the | ||||
|     Corresponding Source from a network server at no charge. | ||||
| 
 | ||||
|     c) Convey individual copies of the object code with a copy of the | ||||
|     written offer to provide the Corresponding Source.  This | ||||
|     alternative is allowed only occasionally and noncommercially, and | ||||
|     only if you received the object code with such an offer, in accord | ||||
|     with subsection 6b. | ||||
| 
 | ||||
|     d) Convey the object code by offering access from a designated | ||||
|     place (gratis or for a charge), and offer equivalent access to the | ||||
|     Corresponding Source in the same way through the same place at no | ||||
|     further charge.  You need not require recipients to copy the | ||||
|     Corresponding Source along with the object code.  If the place to | ||||
|     copy the object code is a network server, the Corresponding Source | ||||
|     may be on a different server (operated by you or a third party) | ||||
|     that supports equivalent copying facilities, provided you maintain | ||||
|     clear directions next to the object code saying where to find the | ||||
|     Corresponding Source.  Regardless of what server hosts the | ||||
|     Corresponding Source, you remain obligated to ensure that it is | ||||
|     available for as long as needed to satisfy these requirements. | ||||
| 
 | ||||
|     e) Convey the object code using peer-to-peer transmission, provided | ||||
|     you inform other peers where the object code and Corresponding | ||||
|     Source of the work are being offered to the general public at no | ||||
|     charge under subsection 6d. | ||||
| 
 | ||||
|   A separable portion of the object code, whose source code is excluded | ||||
| from the Corresponding Source as a System Library, need not be | ||||
| included in conveying the object code work. | ||||
| 
 | ||||
|   A "User Product" is either (1) a "consumer product", which means any | ||||
| tangible personal property which is normally used for personal, family, | ||||
| or household purposes, or (2) anything designed or sold for incorporation | ||||
| into a dwelling.  In determining whether a product is a consumer product, | ||||
| doubtful cases shall be resolved in favor of coverage.  For a particular | ||||
| product received by a particular user, "normally used" refers to a | ||||
| typical or common use of that class of product, regardless of the status | ||||
| of the particular user or of the way in which the particular user | ||||
| actually uses, or expects or is expected to use, the product.  A product | ||||
| is a consumer product regardless of whether the product has substantial | ||||
| commercial, industrial or non-consumer uses, unless such uses represent | ||||
| the only significant mode of use of the product. | ||||
| 
 | ||||
|   "Installation Information" for a User Product means any methods, | ||||
| procedures, authorization keys, or other information required to install | ||||
| and execute modified versions of a covered work in that User Product from | ||||
| a modified version of its Corresponding Source.  The information must | ||||
| suffice to ensure that the continued functioning of the modified object | ||||
| code is in no case prevented or interfered with solely because | ||||
| modification has been made. | ||||
| 
 | ||||
|   If you convey an object code work under this section in, or with, or | ||||
| specifically for use in, a User Product, and the conveying occurs as | ||||
| part of a transaction in which the right of possession and use of the | ||||
| User Product is transferred to the recipient in perpetuity or for a | ||||
| fixed term (regardless of how the transaction is characterized), the | ||||
| Corresponding Source conveyed under this section must be accompanied | ||||
| by the Installation Information.  But this requirement does not apply | ||||
| if neither you nor any third party retains the ability to install | ||||
| modified object code on the User Product (for example, the work has | ||||
| been installed in ROM). | ||||
| 
 | ||||
|   The requirement to provide Installation Information does not include a | ||||
| requirement to continue to provide support service, warranty, or updates | ||||
| for a work that has been modified or installed by the recipient, or for | ||||
| the User Product in which it has been modified or installed.  Access to a | ||||
| network may be denied when the modification itself materially and | ||||
| adversely affects the operation of the network or violates the rules and | ||||
| protocols for communication across the network. | ||||
| 
 | ||||
|   Corresponding Source conveyed, and Installation Information provided, | ||||
| in accord with this section must be in a format that is publicly | ||||
| documented (and with an implementation available to the public in | ||||
| source code form), and must require no special password or key for | ||||
| unpacking, reading or copying. | ||||
| 
 | ||||
|   7. Additional Terms. | ||||
| 
 | ||||
|   "Additional permissions" are terms that supplement the terms of this | ||||
| License by making exceptions from one or more of its conditions. | ||||
| Additional permissions that are applicable to the entire Program shall | ||||
| be treated as though they were included in this License, to the extent | ||||
| that they are valid under applicable law.  If additional permissions | ||||
| apply only to part of the Program, that part may be used separately | ||||
| under those permissions, but the entire Program remains governed by | ||||
| this License without regard to the additional permissions. | ||||
| 
 | ||||
|   When you convey a copy of a covered work, you may at your option | ||||
| remove any additional permissions from that copy, or from any part of | ||||
| it.  (Additional permissions may be written to require their own | ||||
| removal in certain cases when you modify the work.)  You may place | ||||
| additional permissions on material, added by you to a covered work, | ||||
| for which you have or can give appropriate copyright permission. | ||||
| 
 | ||||
|   Notwithstanding any other provision of this License, for material you | ||||
| add to a covered work, you may (if authorized by the copyright holders of | ||||
| that material) supplement the terms of this License with terms: | ||||
| 
 | ||||
|     a) Disclaiming warranty or limiting liability differently from the | ||||
|     terms of sections 15 and 16 of this License; or | ||||
| 
 | ||||
|     b) Requiring preservation of specified reasonable legal notices or | ||||
|     author attributions in that material or in the Appropriate Legal | ||||
|     Notices displayed by works containing it; or | ||||
| 
 | ||||
|     c) Prohibiting misrepresentation of the origin of that material, or | ||||
|     requiring that modified versions of such material be marked in | ||||
|     reasonable ways as different from the original version; or | ||||
| 
 | ||||
|     d) Limiting the use for publicity purposes of names of licensors or | ||||
|     authors of the material; or | ||||
| 
 | ||||
|     e) Declining to grant rights under trademark law for use of some | ||||
|     trade names, trademarks, or service marks; or | ||||
| 
 | ||||
|     f) Requiring indemnification of licensors and authors of that | ||||
|     material by anyone who conveys the material (or modified versions of | ||||
|     it) with contractual assumptions of liability to the recipient, for | ||||
|     any liability that these contractual assumptions directly impose on | ||||
|     those licensors and authors. | ||||
| 
 | ||||
|   All other non-permissive additional terms are considered "further | ||||
| restrictions" within the meaning of section 10.  If the Program as you | ||||
| received it, or any part of it, contains a notice stating that it is | ||||
| governed by this License along with a term that is a further | ||||
| restriction, you may remove that term.  If a license document contains | ||||
| a further restriction but permits relicensing or conveying under this | ||||
| License, you may add to a covered work material governed by the terms | ||||
| of that license document, provided that the further restriction does | ||||
| not survive such relicensing or conveying. | ||||
| 
 | ||||
|   If you add terms to a covered work in accord with this section, you | ||||
| must place, in the relevant source files, a statement of the | ||||
| additional terms that apply to those files, or a notice indicating | ||||
| where to find the applicable terms. | ||||
| 
 | ||||
|   Additional terms, permissive or non-permissive, may be stated in the | ||||
| form of a separately written license, or stated as exceptions; | ||||
| the above requirements apply either way. | ||||
| 
 | ||||
|   8. Termination. | ||||
| 
 | ||||
|   You may not propagate or modify a covered work except as expressly | ||||
| provided under this License.  Any attempt otherwise to propagate or | ||||
| modify it is void, and will automatically terminate your rights under | ||||
| this License (including any patent licenses granted under the third | ||||
| paragraph of section 11). | ||||
| 
 | ||||
|   However, if you cease all violation of this License, then your | ||||
| license from a particular copyright holder is reinstated (a) | ||||
| provisionally, unless and until the copyright holder explicitly and | ||||
| finally terminates your license, and (b) permanently, if the copyright | ||||
| holder fails to notify you of the violation by some reasonable means | ||||
| prior to 60 days after the cessation. | ||||
| 
 | ||||
|   Moreover, your license from a particular copyright holder is | ||||
| reinstated permanently if the copyright holder notifies you of the | ||||
| violation by some reasonable means, this is the first time you have | ||||
| received notice of violation of this License (for any work) from that | ||||
| copyright holder, and you cure the violation prior to 30 days after | ||||
| your receipt of the notice. | ||||
| 
 | ||||
|   Termination of your rights under this section does not terminate the | ||||
| licenses of parties who have received copies or rights from you under | ||||
| this License.  If your rights have been terminated and not permanently | ||||
| reinstated, you do not qualify to receive new licenses for the same | ||||
| material under section 10. | ||||
| 
 | ||||
|   9. Acceptance Not Required for Having Copies. | ||||
| 
 | ||||
|   You are not required to accept this License in order to receive or | ||||
| run a copy of the Program.  Ancillary propagation of a covered work | ||||
| occurring solely as a consequence of using peer-to-peer transmission | ||||
| to receive a copy likewise does not require acceptance.  However, | ||||
| nothing other than this License grants you permission to propagate or | ||||
| modify any covered work.  These actions infringe copyright if you do | ||||
| not accept this License.  Therefore, by modifying or propagating a | ||||
| covered work, you indicate your acceptance of this License to do so. | ||||
| 
 | ||||
|   10. Automatic Licensing of Downstream Recipients. | ||||
| 
 | ||||
|   Each time you convey a covered work, the recipient automatically | ||||
| receives a license from the original licensors, to run, modify and | ||||
| propagate that work, subject to this License.  You are not responsible | ||||
| for enforcing compliance by third parties with this License. | ||||
| 
 | ||||
|   An "entity transaction" is a transaction transferring control of an | ||||
| organization, or substantially all assets of one, or subdividing an | ||||
| organization, or merging organizations.  If propagation of a covered | ||||
| work results from an entity transaction, each party to that | ||||
| transaction who receives a copy of the work also receives whatever | ||||
| licenses to the work the party's predecessor in interest had or could | ||||
| give under the previous paragraph, plus a right to possession of the | ||||
| Corresponding Source of the work from the predecessor in interest, if | ||||
| the predecessor has it or can get it with reasonable efforts. | ||||
| 
 | ||||
|   You may not impose any further restrictions on the exercise of the | ||||
| rights granted or affirmed under this License.  For example, you may | ||||
| not impose a license fee, royalty, or other charge for exercise of | ||||
| rights granted under this License, and you may not initiate litigation | ||||
| (including a cross-claim or counterclaim in a lawsuit) alleging that | ||||
| any patent claim is infringed by making, using, selling, offering for | ||||
| sale, or importing the Program or any portion of it. | ||||
| 
 | ||||
|   11. Patents. | ||||
| 
 | ||||
|   A "contributor" is a copyright holder who authorizes use under this | ||||
| License of the Program or a work on which the Program is based.  The | ||||
| work thus licensed is called the contributor's "contributor version". | ||||
| 
 | ||||
|   A contributor's "essential patent claims" are all patent claims | ||||
| owned or controlled by the contributor, whether already acquired or | ||||
| hereafter acquired, that would be infringed by some manner, permitted | ||||
| by this License, of making, using, or selling its contributor version, | ||||
| but do not include claims that would be infringed only as a | ||||
| consequence of further modification of the contributor version.  For | ||||
| purposes of this definition, "control" includes the right to grant | ||||
| patent sublicenses in a manner consistent with the requirements of | ||||
| this License. | ||||
| 
 | ||||
|   Each contributor grants you a non-exclusive, worldwide, royalty-free | ||||
| patent license under the contributor's essential patent claims, to | ||||
| make, use, sell, offer for sale, import and otherwise run, modify and | ||||
| propagate the contents of its contributor version. | ||||
| 
 | ||||
|   In the following three paragraphs, a "patent license" is any express | ||||
| agreement or commitment, however denominated, not to enforce a patent | ||||
| (such as an express permission to practice a patent or covenant not to | ||||
| sue for patent infringement).  To "grant" such a patent license to a | ||||
| party means to make such an agreement or commitment not to enforce a | ||||
| patent against the party. | ||||
| 
 | ||||
|   If you convey a covered work, knowingly relying on a patent license, | ||||
| and the Corresponding Source of the work is not available for anyone | ||||
| to copy, free of charge and under the terms of this License, through a | ||||
| publicly available network server or other readily accessible means, | ||||
| then you must either (1) cause the Corresponding Source to be so | ||||
| available, or (2) arrange to deprive yourself of the benefit of the | ||||
| patent license for this particular work, or (3) arrange, in a manner | ||||
| consistent with the requirements of this License, to extend the patent | ||||
| license to downstream recipients.  "Knowingly relying" means you have | ||||
| actual knowledge that, but for the patent license, your conveying the | ||||
| covered work in a country, or your recipient's use of the covered work | ||||
| in a country, would infringe one or more identifiable patents in that | ||||
| country that you have reason to believe are valid. | ||||
| 
 | ||||
|   If, pursuant to or in connection with a single transaction or | ||||
| arrangement, you convey, or propagate by procuring conveyance of, a | ||||
| covered work, and grant a patent license to some of the parties | ||||
| receiving the covered work authorizing them to use, propagate, modify | ||||
| or convey a specific copy of the covered work, then the patent license | ||||
| you grant is automatically extended to all recipients of the covered | ||||
| work and works based on it. | ||||
| 
 | ||||
|   A patent license is "discriminatory" if it does not include within | ||||
| the scope of its coverage, prohibits the exercise of, or is | ||||
| conditioned on the non-exercise of one or more of the rights that are | ||||
| specifically granted under this License.  You may not convey a covered | ||||
| work if you are a party to an arrangement with a third party that is | ||||
| in the business of distributing software, under which you make payment | ||||
| to the third party based on the extent of your activity of conveying | ||||
| the work, and under which the third party grants, to any of the | ||||
| parties who would receive the covered work from you, a discriminatory | ||||
| patent license (a) in connection with copies of the covered work | ||||
| conveyed by you (or copies made from those copies), or (b) primarily | ||||
| for and in connection with specific products or compilations that | ||||
| contain the covered work, unless you entered into that arrangement, | ||||
| or that patent license was granted, prior to 28 March 2007. | ||||
| 
 | ||||
|   Nothing in this License shall be construed as excluding or limiting | ||||
| any implied license or other defenses to infringement that may | ||||
| otherwise be available to you under applicable patent law. | ||||
| 
 | ||||
|   12. No Surrender of Others' Freedom. | ||||
| 
 | ||||
|   If conditions are imposed on you (whether by court order, agreement or | ||||
| otherwise) that contradict the conditions of this License, they do not | ||||
| excuse you from the conditions of this License.  If you cannot convey a | ||||
| covered work so as to satisfy simultaneously your obligations under this | ||||
| License and any other pertinent obligations, then as a consequence you may | ||||
| not convey it at all.  For example, if you agree to terms that obligate you | ||||
| to collect a royalty for further conveying from those to whom you convey | ||||
| the Program, the only way you could satisfy both those terms and this | ||||
| License would be to refrain entirely from conveying the Program. | ||||
| 
 | ||||
|   13. Use with the GNU Affero General Public License. | ||||
| 
 | ||||
|   Notwithstanding any other provision of this License, you have | ||||
| permission to link or combine any covered work with a work licensed | ||||
| under version 3 of the GNU Affero General Public License into a single | ||||
| combined work, and to convey the resulting work.  The terms of this | ||||
| License will continue to apply to the part which is the covered work, | ||||
| but the special requirements of the GNU Affero General Public License, | ||||
| section 13, concerning interaction through a network will apply to the | ||||
| combination as such. | ||||
| 
 | ||||
|   14. Revised Versions of this License. | ||||
| 
 | ||||
|   The Free Software Foundation may publish revised and/or new versions of | ||||
| the GNU General Public License from time to time.  Such new versions will | ||||
| be similar in spirit to the present version, but may differ in detail to | ||||
| address new problems or concerns. | ||||
| 
 | ||||
|   Each version is given a distinguishing version number.  If the | ||||
| Program specifies that a certain numbered version of the GNU General | ||||
| Public License "or any later version" applies to it, you have the | ||||
| option of following the terms and conditions either of that numbered | ||||
| version or of any later version published by the Free Software | ||||
| Foundation.  If the Program does not specify a version number of the | ||||
| GNU General Public License, you may choose any version ever published | ||||
| by the Free Software Foundation. | ||||
| 
 | ||||
|   If the Program specifies that a proxy can decide which future | ||||
| versions of the GNU General Public License can be used, that proxy's | ||||
| public statement of acceptance of a version permanently authorizes you | ||||
| to choose that version for the Program. | ||||
| 
 | ||||
|   Later license versions may give you additional or different | ||||
| permissions.  However, no additional obligations are imposed on any | ||||
| author or copyright holder as a result of your choosing to follow a | ||||
| later version. | ||||
| 
 | ||||
|   15. Disclaimer of Warranty. | ||||
| 
 | ||||
|   THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY | ||||
| APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT | ||||
| HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY | ||||
| OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, | ||||
| THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||||
| PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM | ||||
| IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF | ||||
| ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | ||||
| 
 | ||||
|   16. Limitation of Liability. | ||||
| 
 | ||||
|   IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | ||||
| WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS | ||||
| THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY | ||||
| GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE | ||||
| USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF | ||||
| DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD | ||||
| PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), | ||||
| EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF | ||||
| SUCH DAMAGES. | ||||
| 
 | ||||
|   17. Interpretation of Sections 15 and 16. | ||||
| 
 | ||||
|   If the disclaimer of warranty and limitation of liability provided | ||||
| above cannot be given local legal effect according to their terms, | ||||
| reviewing courts shall apply local law that most closely approximates | ||||
| an absolute waiver of all civil liability in connection with the | ||||
| Program, unless a warranty or assumption of liability accompanies a | ||||
| copy of the Program in return for a fee. | ||||
| 
 | ||||
|                      END OF TERMS AND CONDITIONS | ||||
| 
 | ||||
|             How to Apply These Terms to Your New Programs | ||||
| 
 | ||||
|   If you develop a new program, and you want it to be of the greatest | ||||
| possible use to the public, the best way to achieve this is to make it | ||||
| free software which everyone can redistribute and change under these terms. | ||||
| 
 | ||||
|   To do so, attach the following notices to the program.  It is safest | ||||
| to attach them to the start of each source file to most effectively | ||||
| state the exclusion of warranty; and each file should have at least | ||||
| the "copyright" line and a pointer to where the full notice is found. | ||||
| 
 | ||||
|     <one line to give the program's name and a brief idea of what it does.> | ||||
|     Copyright (C) <year>  <name of author> | ||||
| 
 | ||||
|     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. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| Also add information on how to contact you by electronic and paper mail. | ||||
| 
 | ||||
|   If the program does terminal interaction, make it output a short | ||||
| notice like this when it starts in an interactive mode: | ||||
| 
 | ||||
|     <program>  Copyright (C) <year>  <name of author> | ||||
|     This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | ||||
|     This is free software, and you are welcome to redistribute it | ||||
|     under certain conditions; type `show c' for details. | ||||
| 
 | ||||
| The hypothetical commands `show w' and `show c' should show the appropriate | ||||
| parts of the General Public License.  Of course, your program's commands | ||||
| might be different; for a GUI interface, you would use an "about box". | ||||
| 
 | ||||
|   You should also get your employer (if you work as a programmer) or school, | ||||
| if any, to sign a "copyright disclaimer" for the program, if necessary. | ||||
| For more information on this, and how to apply and follow the GNU GPL, see | ||||
| <http://www.gnu.org/licenses/>. | ||||
| 
 | ||||
|   The GNU General Public License does not permit incorporating your program | ||||
| into proprietary programs.  If your program is a subroutine library, you | ||||
| may consider it more useful to permit linking proprietary applications with | ||||
| the library.  If this is what you want to do, use the GNU Lesser General | ||||
| Public License instead of this License.  But first, please read | ||||
| <http://www.gnu.org/philosophy/why-not-lgpl.html>. | ||||
| @ -0,0 +1,28 @@ | ||||
| FTDI EVE Library | ||||
| ---------------- | ||||
| 
 | ||||
| The FTDI EVE Library is a fully open-source library and UI framework for the FTDI | ||||
| FT800 and FT810 graphics processor. | ||||
| 
 | ||||
| Although the library has been developed within Lulzbot for providing a user interface | ||||
| for Marlin, the library has been written so that it can be used in any Arduino sketch. | ||||
| 
 | ||||
| The library is split into two parts. The "basic" API provides a shallow interface to | ||||
| the underlying FTDI hardware and command FIFO and provides low-level access to the | ||||
| hardware as closely as possible to the API described in the FTDI Programmer's Guide. | ||||
| 
 | ||||
| The "extended" API builds on top of the "basic" API to provide a GUI framework for | ||||
| handling common challenges in building a usable GUI. The GUI framework provides the | ||||
| following features: | ||||
| 
 | ||||
| - Macros for a resolution-independent placement of widgets based on a grid. | ||||
| - Class-based UI screens, with press and unpress touch events, as well as touch repeat. | ||||
| - Event loop with button debouncing and button push visual and auditory feedback. | ||||
| - Easy screen-to-screen navigation including a navigation stack for going backwards. | ||||
| - Visual feedback for disabled vs enabled buttons, and custom button styles. | ||||
| - A sound player class for playing individual notes or complete sound sequences. | ||||
| - Display list caching, for storing static background elements of a screen in RAM_G. | ||||
| 
 | ||||
| See the "examples" folder for Arduino sketches. Modify the "src/config.h" file in | ||||
| each to suit your particular setup. The "sample_configs" contain sample configuration | ||||
| files for running the sketches on our 3D printer boards. | ||||
| @ -0,0 +1,183 @@ | ||||
| /************
 | ||||
|  * boards.h * | ||||
|  ************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #define HAS_RESOLUTION (defined(TOUCH_UI_320x240) || defined(TOUCH_UI_480x272) || defined(TOUCH_UI_800x480)) | ||||
| 
 | ||||
| #define IS_FT800 \ | ||||
|     constexpr uint16_t ftdi_chip = 800; \ | ||||
|     using namespace FTDI_FT800; \ | ||||
|     namespace DL { \ | ||||
|       using namespace FTDI_FT800_DL; \ | ||||
|     } \ | ||||
|     typedef ft800_memory_map ftdi_memory_map; \ | ||||
|     typedef ft800_registers  ftdi_registers; | ||||
| 
 | ||||
| #define IS_FT810 \ | ||||
|     constexpr uint16_t ftdi_chip = 810; \ | ||||
|     using namespace FTDI_FT810; \ | ||||
|     namespace DL { \ | ||||
|       using namespace FTDI_FT800_DL; \ | ||||
|       using namespace FTDI_FT810_DL; \ | ||||
|     } \ | ||||
|     typedef ft810_memory_map ftdi_memory_map; \ | ||||
|     typedef ft810_registers  ftdi_registers; | ||||
| 
 | ||||
| 
 | ||||
| #ifdef LCD_FTDI_VM800B35A | ||||
|   #if !HAS_RESOLUTION | ||||
|     #define TOUCH_UI_320x240 | ||||
|   #endif | ||||
|   #ifndef FTDI_API_LEVEL | ||||
|     #define FTDI_API_LEVEL                800 | ||||
|   #endif | ||||
|   namespace FTDI { | ||||
|     IS_FT800 | ||||
|     constexpr bool Use_Crystal              = true;  // 0 = use internal oscillator, 1 = module has a crystal populated
 | ||||
|     constexpr bool GPIO_0_Audio_Enable      = false; /* 1 = does use GPIO00 for amplifier control, 0 = not in use for Audio */ | ||||
|     constexpr bool GPIO_1_Audio_Shutdown    = true;  /* 1 = does use GPIO01 for amplifier control, 0 = not in use for Audio */ | ||||
|     constexpr uint8_t Swizzle               = 2; | ||||
|     constexpr uint8_t CSpread               = 1; | ||||
| 
 | ||||
|     constexpr uint16_t touch_threshold      = 1200; /* touch-sensitivity */ | ||||
|   } | ||||
| 
 | ||||
| /*
 | ||||
|  * Settings for the Haoyu Electronics, 4.3" Graphical LCD Touchscreen,       480x272, SPI, FT800 (FT800CB-HY43B) | ||||
|  *                  Haoyu Electronics,   5" Graphical LCD Touchscreen,       480x272, SPI, FT800 (FT800CB-HY50B) | ||||
|  * | ||||
|  *    http://www.hotmcu.com/43-graphical-lcd-touchscreen-480x272-spi-ft800-p-111.html?cPath=6_16
 | ||||
|  *    http://www.hotmcu.com/5-graphical-lcd-touchscreen-480x272-spi-ft800-p-124.html?cPath=6_16
 | ||||
|  * | ||||
|  * Datasheet: | ||||
|  * | ||||
|  *    http://www.hantronix.com/files/data/1278363262430-3.pdf
 | ||||
|  *    http://www.haoyuelectronics.com/Attachment/HY43-LCD/LCD%20DataSheet.pdf
 | ||||
|  *    http://www.haoyuelectronics.com/Attachment/HY5-LCD-HD/KD50G21-40NT-A1.pdf
 | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #elif defined(LCD_HAOYU_FT800CB) | ||||
|   #if !HAS_RESOLUTION | ||||
|     #define TOUCH_UI_480x272 | ||||
|   #endif | ||||
|   #ifndef FTDI_API_LEVEL | ||||
|     #define FTDI_API_LEVEL                800 | ||||
|   #endif | ||||
|   namespace FTDI { | ||||
|     IS_FT800 | ||||
|     constexpr bool Use_Crystal              = true; // 0 = use internal oscillator, 1 = module has a crystal populated
 | ||||
|     constexpr bool GPIO_0_Audio_Enable      = false; | ||||
|     constexpr bool GPIO_1_Audio_Shutdown    = false; | ||||
|     constexpr uint8_t Swizzle               = 0; | ||||
|     constexpr uint8_t CSpread               = 1; | ||||
|     constexpr uint16_t touch_threshold      = 2000; /* touch-sensitivity */ | ||||
|   } | ||||
| 
 | ||||
| /*
 | ||||
|  * Settings for the Haoyu Electronics, 5" Graphical LCD Touchscreen, 800x480, SPI, FT810 | ||||
|  * | ||||
|  *    http://www.hotmcu.com/5-graphical-lcd-touchscreen-800x480-spi-ft810-p-286.html
 | ||||
|  * | ||||
|  * Datasheet: | ||||
|  * | ||||
|  *    http://www.haoyuelectronics.com/Attachment/HY5-LCD-HD/KD50G21-40NT-A1.pdf
 | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #elif defined(LCD_HAOYU_FT810CB) | ||||
|   #if !HAS_RESOLUTION | ||||
|     #define TOUCH_UI_800x480 | ||||
|   #endif | ||||
|   #ifndef FTDI_API_LEVEL | ||||
|     #define FTDI_API_LEVEL                810 | ||||
|   #endif | ||||
|   namespace FTDI { | ||||
|     IS_FT810 | ||||
|     constexpr bool Use_Crystal              = true; // 0 = use internal oscillator, 1 = module has a crystal populated
 | ||||
|     constexpr bool GPIO_0_Audio_Enable      = false; | ||||
|     constexpr bool GPIO_1_Audio_Shutdown    = false; | ||||
|     constexpr uint8_t Swizzle               = 0; | ||||
|     constexpr uint8_t CSpread               = 1; | ||||
|     constexpr uint16_t touch_threshold      = 2000; /* touch-sensitivity */ | ||||
|   } | ||||
| 
 | ||||
| /*
 | ||||
|  * Settings for the 4D Systems,        4.3" Embedded SPI Display             480x272, SPI, FT800 (4DLCD-FT843) | ||||
|  * | ||||
|  *    http://www.4dsystems.com.au/product/4DLCD_FT843/
 | ||||
|  * | ||||
|  * Datasheet: | ||||
|  * | ||||
|  *    http://www.4dsystems.com.au/productpages/4DLCD-FT843/downloads/FT843-4.3-Display_datasheet_R_1_2.pdf
 | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #elif defined(LCD_4DSYSTEMS_4DLCD_FT843) | ||||
|   #if !HAS_RESOLUTION | ||||
|     #define TOUCH_UI_480x272 | ||||
|   #endif | ||||
|   #ifndef FTDI_API_LEVEL | ||||
|     #define FTDI_API_LEVEL                800 | ||||
|   #endif | ||||
|   namespace FTDI { | ||||
|     IS_FT800 | ||||
|     constexpr bool Use_Crystal              = true; // 0 = use internal oscillator, 1 = module has a crystal populated
 | ||||
|     constexpr bool GPIO_0_Audio_Enable      = false; | ||||
|     constexpr bool GPIO_1_Audio_Shutdown    = true; | ||||
|     constexpr uint8_t Swizzle               = 0; | ||||
|     constexpr uint8_t CSpread               = 1; | ||||
|     constexpr uint16_t touch_threshold      = 1200; /* touch-sensitivity */ | ||||
|   } | ||||
| 
 | ||||
| /*
 | ||||
|  * Settings for the Aleph Objects Color LCD User Interface | ||||
|  * | ||||
|  *    https://code.alephobjects.com/source/aotctl/
 | ||||
|  * | ||||
|  * Datasheet: | ||||
|  * | ||||
|  *    http://www.hantronix.com/files/data/s1501799605s500-gh7.pdf
 | ||||
|  * | ||||
|  */ | ||||
| #elif defined(LCD_ALEPHOBJECTS_CLCD_UI) | ||||
|   #if !HAS_RESOLUTION | ||||
|     #define TOUCH_UI_800x480 | ||||
|   #endif | ||||
|   #ifndef FTDI_API_LEVEL | ||||
|     #define FTDI_API_LEVEL                810 | ||||
|   #endif | ||||
|   namespace FTDI { | ||||
|     IS_FT810 | ||||
|     constexpr bool Use_Crystal              = false; // 0 = use internal oscillator, 1 = module has a crystal populated
 | ||||
|     constexpr bool GPIO_0_Audio_Enable      = true;  // The AO CLCD uses GPIO0 to enable audio
 | ||||
|     constexpr bool GPIO_1_Audio_Shutdown    = false; | ||||
|     constexpr uint8_t Swizzle               = 0; | ||||
|     constexpr uint8_t CSpread               = 0; | ||||
|     constexpr uint16_t touch_threshold      = 2000; /* touch-sensitivity */ | ||||
|   } | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
|   #error Unknown or no LULZBOT_TOUCH_UI board specified. To add a new board, modify "ftdi_eve_boards.h" | ||||
| #endif | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -0,0 +1,258 @@ | ||||
| /****************
 | ||||
|  * commands.cpp * | ||||
|  ****************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
|   /****************************************************************************
 | ||||
|   *                       FUNCTION MAP                                        * | ||||
|   *                                                                           * | ||||
|   * SPI and FT800/810 Commands                                                * | ||||
|   *                                                                           * | ||||
|   * CLCD::spi_select()                 Set CS line to 0                       * | ||||
|   * CLCD::spi_deselect()               Set CS Line to 1                       * | ||||
|   * CLCD::reset()                      Toggle FT800/810 Power Down Line 50 ms * | ||||
|   * CLCD::spi_init()                   Configure I/O Lines for SPI            * | ||||
|   * CLCD::spi_transfer()               Send/Receive 1 SPI Byte                * | ||||
|   * CLCD::init()                       Set FT800/810 Registers                * | ||||
|   * CLCD::enable()                     Turn On FT800/810 PCLK                 * | ||||
|   * CLCD::disable()                    Turn Off FT8880/810 PCLK               * | ||||
|   * CLCD::set_backlight()              Set LCD Backlight Level                * | ||||
|   *                                                                           * | ||||
|   * MEMORY READ FUNCTIONS                                                     * | ||||
|   *                                                                           * | ||||
|   * CLCD::mem_read_addr()              Send 32-Bit Address                    * | ||||
|   * CLCD::mem_read_8()                 Read 1 Byte                            * | ||||
|   * CLCD::mem_read_16()                Read 2 Bytes                           * | ||||
|   * CLCD::mem_read_32()                Read 4 Bytes                           * | ||||
|   *                                                                           * | ||||
|   * MEMORY WRITE FUNCTIONS                                                    * | ||||
|   *                                                                           * | ||||
|   * CLCD::mem_write_addr()             Send 24-Bit Address                    * | ||||
|   * CLCD::mem_write_8()                Write 1 Byte                           * | ||||
|   * CLCD::mem_write_16()               Write 2 Bytes                          * | ||||
|   * CLCD::mem_write_32()               Write 4 Bytes                          * | ||||
|   *                                                                           * | ||||
|   * HOST COMMAND FUNCTION                                                     * | ||||
|   *                                                                           * | ||||
|   * CLCD::host_cmd()                   Send 24-Bit Host Command               * | ||||
|   *                                                                           * | ||||
|   * COMMAND BUFFER FUNCTIONS                                                  * | ||||
|   *                                                                           * | ||||
|   * CLCD::cmd()                        Send 32-Bit Value(4 Bytes)CMD Buffer   * | ||||
|   * CLCD::cmd()                        Send Data Structure with 32-Bit Cmd    * | ||||
|   * CLCD::str()                        Send Text String in 32-Bit Multiples   * | ||||
| 
 | ||||
|   *                                                                           * | ||||
|   * FT800/810 GRAPHIC COMMANDS                                                * | ||||
|   *                                                                           * | ||||
|   * class CLCD:CommandFifo {}          Class to control Cmd FIFO              * | ||||
| 
 | ||||
|   * CommandFifo::start()               Wait for CP finish - Set FIFO Ptr      * | ||||
|   * CommandFifo::execute()             Set REG_CMD_WRITE and start CP         * | ||||
|   * CommandFifo::reset()               Set Cmd Buffer Pointers to 0           * | ||||
|   * | ||||
|   * CommandFifo::fgcolor               Set Graphic Item Foreground Color      * | ||||
|   * CommandFifo::bgcolor               Set Graphic Item Background Color      * | ||||
|   * CommandFifo::begin()               Begin Drawing a Primative              * | ||||
|   * CommandFifo::mem_copy()            Copy a Block of Memory                 * | ||||
|   * CommandFifo::append()              Append Commands to Current DL          * | ||||
|   * CommandFifo::gradient_color()      Set 3D Button Highlight Color          * | ||||
|   * CommandFifo::button()              Draw Button with Bulk Write            * | ||||
|   * CommandFifo::text()                Draw Text with Bulk Write              * | ||||
|   *****************************************************************************/ | ||||
| 
 | ||||
|  /**************************************************
 | ||||
|   * RAM_G Graphics RAM Allocation                  * | ||||
|   *                                                * | ||||
|   * Address    Use                                 * | ||||
|   *                                                * | ||||
|   *    8000    Extruder Bitmap                     * | ||||
|   *    8100    Bed Heat Bitmap                     * | ||||
|   *    8200    Fan Bitmap                          * | ||||
|   *    8300    Thumb Drive Symbol Bitmap           * | ||||
|   *   35000    Static DL Space (FT800)             * | ||||
|   *   F5000    Static DL Space (FT810)             * | ||||
|   **************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| typedef const __FlashStringHelper *progmem_str; | ||||
| 
 | ||||
| class UIStorage; | ||||
| 
 | ||||
| class CLCD { | ||||
|   friend class UIStorage; | ||||
| 
 | ||||
|   public: | ||||
|     typedef FTDI::ftdi_registers  REG; | ||||
|     typedef FTDI::ftdi_memory_map MAP; | ||||
| 
 | ||||
|     static void     spi_write_addr (uint32_t reg_address); | ||||
|     static void     spi_read_addr  (uint32_t reg_address); | ||||
| 
 | ||||
|     static uint8_t  mem_read_8     (uint32_t reg_address); | ||||
|     static uint16_t mem_read_16    (uint32_t reg_address); | ||||
|     static uint32_t mem_read_32    (uint32_t reg_address); | ||||
|     static void     mem_read_bulk  (uint32_t reg_address, uint8_t *data, uint16_t len); | ||||
| 
 | ||||
|     static void     mem_write_8    (uint32_t reg_address, uint8_t w_data); | ||||
|     static void     mem_write_16   (uint32_t reg_address, uint16_t w_data); | ||||
|     static void     mem_write_32   (uint32_t reg_address, uint32_t w_data); | ||||
|     static void     mem_write_bulk (uint32_t reg_address, const void *data, uint16_t len, uint8_t padding = 0); | ||||
|     static void     mem_write_pgm  (uint32_t reg_address, const void *data, uint16_t len, uint8_t padding = 0); | ||||
|     static void     mem_write_bulk (uint32_t reg_address, progmem_str str, uint16_t len, uint8_t padding = 0); | ||||
|     static void     mem_write_xbm  (uint32_t reg_address, progmem_str str, uint16_t len, uint8_t padding = 0); | ||||
| 
 | ||||
|   public: | ||||
|     class CommandFifo; | ||||
|     class FontMetrics; | ||||
| 
 | ||||
|     static void init (void); | ||||
|     static void default_touch_transform (void); | ||||
|     static void default_display_orientation (void); | ||||
|     static void turn_on_backlight (void); | ||||
|     static void enable (void); | ||||
|     static void disable (void); | ||||
|     static void set_brightness (uint8_t brightness); | ||||
|     static uint8_t get_brightness(); | ||||
|     static void host_cmd (unsigned char host_command, unsigned char byte2); | ||||
| 
 | ||||
|     static void get_font_metrics (uint8_t font, struct FontMetrics &fm); | ||||
|     static uint16_t get_text_width(const uint8_t font, const char *str); | ||||
|     static uint16_t get_text_width_P(const uint8_t font, const char *str); | ||||
| 
 | ||||
|     static uint8_t get_tag ()     {return mem_read_8(REG::TOUCH_TAG);} | ||||
|     static bool is_touching ()    {return (mem_read_32(REG::TOUCH_DIRECT_XY) & 0x80000000) == 0;} | ||||
| 
 | ||||
|     static uint8_t get_tracker (uint16_t &value) { | ||||
|       uint32_t tracker = mem_read_32(REG::TRACKER); | ||||
|       value            = tracker >> 16; | ||||
|       return tracker & 0xFF; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| /*************************** FT800/810 Font Metrics ****************************/ | ||||
| 
 | ||||
| class CLCD::FontMetrics { | ||||
|   public: | ||||
|     uint8_t   char_widths[128]; | ||||
|     uint32_t  format; | ||||
|     uint32_t  stride; | ||||
|     uint32_t  width; | ||||
|     uint32_t  height; | ||||
|     uint32_t  ptr; | ||||
| 
 | ||||
|     FontMetrics(uint8_t font) {load(font);} | ||||
| 
 | ||||
|     void load(uint8_t font); | ||||
| 
 | ||||
|     // Returns width of string, up to a maximum of n characters.
 | ||||
|     uint16_t get_text_width(const char *str, size_t n = SIZE_MAX) const; | ||||
|     uint16_t get_text_width_P(const char *str, size_t n = SIZE_MAX) const; | ||||
| }; | ||||
| 
 | ||||
| /******************* FT800/810 Graphic Commands *********************************/ | ||||
| 
 | ||||
| class CLCD::CommandFifo { | ||||
|   protected: | ||||
|     #if FTDI_API_LEVEL >= 810 | ||||
|       uint32_t getRegCmdBSpace(); | ||||
|     #else | ||||
|       static uint32_t command_write_ptr; | ||||
|       template <class T> bool _write_unaligned(T data, uint16_t len); | ||||
|     #endif | ||||
|     void start(void); | ||||
| 
 | ||||
|   public: | ||||
|     template <class T> bool write(T data, uint16_t len); | ||||
| 
 | ||||
|   public: | ||||
|     CommandFifo() {start();} | ||||
| 
 | ||||
|     static void reset (void); | ||||
|     static bool is_processing(); | ||||
|     static bool has_fault(); | ||||
| 
 | ||||
|     void execute(void); | ||||
| 
 | ||||
|     void cmd(uint32_t cmd32); | ||||
|     void cmd(void* data, uint16_t len); | ||||
| 
 | ||||
|     void dlstart()      {cmd(FTDI::CMD_DLSTART);} | ||||
|     void swap()         {cmd(FTDI::CMD_SWAP);} | ||||
|     void coldstart()    {cmd(FTDI::CMD_COLDSTART);} | ||||
|     void screensaver()  {cmd(FTDI::CMD_SCREENSAVER);} | ||||
|     void stop()         {cmd(FTDI::CMD_STOP);} | ||||
|     void loadidentity() {cmd(FTDI::CMD_LOADIDENTITY);} | ||||
|     void setmatrix()    {cmd(FTDI::CMD_SETMATRIX);} | ||||
| 
 | ||||
|     void fgcolor     (uint32_t rgb); | ||||
|     void bgcolor     (uint32_t rgb); | ||||
|     void gradcolor   (uint32_t rgb); | ||||
| 
 | ||||
|     void track       (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t tag); | ||||
|     void clock       (int16_t x, int16_t y, int16_t r,            uint16_t options, int16_t h, int16_t m, int16_t s, int16_t ms); | ||||
|     void gauge       (int16_t x, int16_t y, int16_t r,            uint16_t options, uint16_t major, uint16_t minor, uint16_t val, uint16_t range); | ||||
|     void dial        (int16_t x, int16_t y, int16_t r,            uint16_t options, uint16_t val); | ||||
|     void slider      (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range); | ||||
|     void progress    (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range); | ||||
|     void scrollbar   (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t size, uint16_t range); | ||||
|     void number      (int16_t x, int16_t y, int16_t font, uint16_t options, int32_t n); | ||||
|     void spinner     (int16_t x, int16_t y, uint16_t style, uint16_t scale); | ||||
|     void sketch      (int16_t x, int16_t y, uint16_t w, uint16_t h, uint32_t ptr, uint16_t format); | ||||
|     void gradient    (int16_t x0, int16_t y0, uint32_t rgb0, int16_t x1, int16_t y1, uint32_t rgb1); | ||||
|     void snapshot    (uint32_t ptr); | ||||
|     void loadimage   (uint32_t ptr, uint32_t options); | ||||
|     void getprops    (uint32_t ptr, uint32_t width, uint32_t height); | ||||
| 
 | ||||
|     void scale       (int32_t sx, int32_t sy); | ||||
|     void rotate      (int32_t a); | ||||
|     void translate   (int32_t tx, int32_t ty); | ||||
| 
 | ||||
|     #if FTDI_API_LEVEL >= 810 | ||||
|       void setbase   (uint8_t base); | ||||
|       void setrotate (uint8_t rotation); | ||||
|       void setbitmap (uint32_t ptr, uint16_t fmt, uint16_t w, uint16_t h); | ||||
|       void snapshot2 (uint32_t fmt, uint32_t ptr, int16_t x, int16_t y, uint16_t w, uint16_t h); | ||||
|       void mediafifo (uint32_t ptr, uint32_t size); | ||||
|       void playvideo (uint32_t options); | ||||
|       void videostart(); | ||||
|       void videoframe(uint32_t dst, uint32_t ptr); | ||||
|     #endif | ||||
| 
 | ||||
|     // All the following must be followed by str()
 | ||||
|     void text      (int16_t x, int16_t y,                       int16_t font, uint16_t options); | ||||
|     void button    (int16_t x, int16_t y, int16_t w, int16_t h, int16_t font, uint16_t option); | ||||
|     void toggle    (int16_t x, int16_t y, int16_t w,            int16_t font, uint16_t options, bool state); | ||||
|     void keys      (int16_t x, int16_t y, int16_t w, int16_t h, int16_t font, uint16_t options); | ||||
| 
 | ||||
|     // Sends the string portion of text, button, toggle and keys.
 | ||||
|     void str (const char * data); | ||||
|     void str (progmem_str data); | ||||
| 
 | ||||
|     void memzero  (uint32_t ptr, uint32_t size); | ||||
|     void memset   (uint32_t ptr, uint32_t value, uint32_t size); | ||||
|     void memcpy   (uint32_t dst, uint32_t src, uint32_t size); | ||||
|     void memcrc   (uint32_t ptr, uint32_t num, uint32_t result); | ||||
|     void memwrite (uint32_t ptr, uint32_t value); | ||||
|     void inflate  (uint32_t ptr); | ||||
|     void getptr   (uint32_t result); | ||||
|     void append   (uint32_t ptr, uint32_t size); | ||||
| }; | ||||
| @ -0,0 +1,411 @@ | ||||
| /***************
 | ||||
|  * constants.h * | ||||
|  ***************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  * This header defines constants and commands for the FTDI FT810 LCD Driver * | ||||
|  * chip.                                                                    * | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| // OPTIONS
 | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   constexpr uint16_t OPT_3D           = 0x0000; | ||||
|   constexpr uint16_t OPT_RGB565       = 0x0000; | ||||
|   constexpr uint16_t OPT_MONO         = 0x0001; | ||||
|   constexpr uint16_t OPT_NODL         = 0x0002; | ||||
|   constexpr uint16_t OPT_FLAT         = 0x0100; | ||||
|   constexpr uint16_t OPT_SIGNED       = 0x0100; | ||||
|   constexpr uint16_t OPT_CENTERX      = 0x0200; | ||||
|   constexpr uint16_t OPT_CENTERY      = 0x0400; | ||||
|   constexpr uint16_t OPT_CENTER       = (OPT_CENTERX | OPT_CENTERY); | ||||
|   constexpr uint16_t OPT_RIGHTX       = 0x0800; | ||||
|   constexpr uint16_t OPT_NOBACK       = 0x1000; | ||||
|   constexpr uint16_t OPT_NOTICKS      = 0x2000; | ||||
|   constexpr uint16_t OPT_NOHM         = 0x4000; | ||||
|   constexpr uint16_t OPT_NOPOINTER    = 0x4000; | ||||
|   constexpr uint16_t OPT_NOSECS       = 0x8000; | ||||
|   constexpr uint16_t OPT_NOHANDS      = (OPT_NOPOINTER | OPT_NOSECS); | ||||
| } | ||||
| 
 | ||||
| namespace FTDI_FT810 { | ||||
|   constexpr uint16_t OPT_NOTEAR      = 0x0004; | ||||
|   constexpr uint16_t OPT_FULLSCREEN  = 0x0008; | ||||
|   constexpr uint16_t OPT_MEDIAFIFO   = 0x0010; | ||||
|   constexpr uint16_t OPT_SOUND       = 0x0020; | ||||
| } | ||||
| 
 | ||||
| // GPIO Bits
 | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   constexpr uint8_t GPIO_GP0         = 1 << 0; | ||||
|   constexpr uint8_t GPIO_GP1         = 1 << 1; | ||||
|   constexpr uint8_t GPIO_DISP        = 1 << 7; | ||||
| } | ||||
| 
 | ||||
| namespace FTDI_FT810 { | ||||
|   constexpr uint16_t GPIOX_GP0       = 1 << 0; | ||||
|   constexpr uint16_t GPIOX_GP1       = 1 << 1; | ||||
|   constexpr uint16_t GPIOX_DISP      = 1 << 15; | ||||
| } | ||||
| 
 | ||||
| // HOST COMMANDS
 | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   constexpr uint8_t ACTIVE  = 0x00; | ||||
|   constexpr uint8_t STANDBY = 0x41; | ||||
|   constexpr uint8_t SLEEP   = 0x42; | ||||
|   constexpr uint8_t PWRDOWN = 0x50; | ||||
|   constexpr uint8_t CLKEXT  = 0x44; | ||||
|   constexpr uint8_t CLKINT  = 0x48; | ||||
|   constexpr uint8_t CORESET = 0x68; | ||||
| } | ||||
| 
 | ||||
| namespace FTDI_FT800 { | ||||
|     constexpr uint8_t CLK48M  = 0x62; | ||||
|     constexpr uint8_t CLK36M  = 0x61; | ||||
| } | ||||
| 
 | ||||
| namespace FTDI_FT810 { | ||||
|     constexpr uint8_t CLKSEL  = 0x61; | ||||
| } | ||||
| 
 | ||||
| // DISPLAY LIST COMMANDS
 | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   constexpr uint8_t ARGB1555                           = 0; | ||||
|   constexpr uint8_t L1                                 = 1; | ||||
|   constexpr uint8_t L4                                 = 2; | ||||
|   constexpr uint8_t L8                                 = 3; | ||||
|   constexpr uint8_t RGB332                             = 4; | ||||
|   constexpr uint8_t ARGB2                              = 5; | ||||
|   constexpr uint8_t ARGB4                              = 6; | ||||
|   constexpr uint8_t RGB565                             = 7; | ||||
|   constexpr uint8_t PALETTED                           = 8; | ||||
|   constexpr uint8_t TEXT8X8                            = 9; | ||||
|   constexpr uint8_t TEXTVGA                            = 10; | ||||
|   constexpr uint8_t BARGRAPH                           = 11; | ||||
| 
 | ||||
|   constexpr uint8_t ALPHA_FUNC_NEVER                   = 0; | ||||
|   constexpr uint8_t ALPHA_FUNC_LESS                    = 1; | ||||
|   constexpr uint8_t ALPHA_FUNC_LEQUAL                  = 2; | ||||
|   constexpr uint8_t ALPHA_FUNC_GREATER                 = 3; | ||||
|   constexpr uint8_t ALPHA_FUNC_GEQUAL                  = 4; | ||||
|   constexpr uint8_t ALPHA_FUNC_EQUAL                   = 5; | ||||
|   constexpr uint8_t ALPHA_FUNC_NOTEQUAL                = 6; | ||||
|   constexpr uint8_t ALPHA_FUNC_ALWAYS                  = 7; | ||||
| 
 | ||||
|   constexpr uint8_t NEAREST                            = 0; | ||||
|   constexpr uint8_t BILINEAR                           = 1; | ||||
|   constexpr uint8_t BORDER                             = 0; | ||||
|   constexpr uint8_t REPEAT                             = 1; | ||||
| 
 | ||||
|   constexpr uint8_t BLEND_FUNC_ZERO                    = 0; | ||||
|   constexpr uint8_t BLEND_FUNC_ONE                     = 1; | ||||
|   constexpr uint8_t BLEND_FUNC_SRC_ALPHA               = 2; | ||||
|   constexpr uint8_t BLEND_FUNC_DST_ALPHA               = 3; | ||||
|   constexpr uint8_t BLEND_FUNC_ONE_MINUS_SRC_ALPHA     = 4; | ||||
|   constexpr uint8_t BLEND_FUNC_ONE_MINUS_DST_ALPHA     = 5; | ||||
| 
 | ||||
|   constexpr uint32_t COLOR_MASK_RED                    = 8; | ||||
|   constexpr uint32_t COLOR_MASK_GRN                    = 4; | ||||
|   constexpr uint32_t COLOR_MASK_BLU                    = 2; | ||||
|   constexpr uint32_t COLOR_MASK_ALPHA                  = 1; | ||||
| 
 | ||||
|   constexpr uint8_t STENCIL_FUNC_NEVER                 = 0; | ||||
|   constexpr uint8_t STENCIL_FUNC_LESS                  = 1; | ||||
|   constexpr uint8_t STENCIL_FUNC_LEQUAL                = 2; | ||||
|   constexpr uint8_t STENCIL_FUNC_GREATER               = 3; | ||||
|   constexpr uint8_t STENCIL_FUNC_GEQUAL                = 4; | ||||
|   constexpr uint8_t STENCIL_FUNC_EQUAL                 = 5; | ||||
|   constexpr uint8_t STENCIL_FUNC_NOTEQUAL              = 6; | ||||
|   constexpr uint8_t STENCIL_FUNC_ALWAYS                = 7; | ||||
| 
 | ||||
|   constexpr uint8_t STENCIL_OP_ZERO                    = 0; | ||||
|   constexpr uint8_t STENCIL_OP_KEEP                    = 1; | ||||
|   constexpr uint8_t STENCIL_OP_REPLACE                 = 2; | ||||
|   constexpr uint8_t STENCIL_OP_INCR                    = 3; | ||||
|   constexpr uint8_t STENCIL_OP_DECR                    = 4; | ||||
|   constexpr uint8_t STENCIL_OP_INVERT                  = 5; | ||||
| 
 | ||||
|   typedef enum: uint32_t { | ||||
|    BITMAPS                                             = 1, | ||||
|    POINTS                                              = 2, | ||||
|    LINES                                               = 3, | ||||
|    LINE_STRIP                                          = 4, | ||||
|    EDGE_STRIP_R                                        = 5, | ||||
|    EDGE_STRIP_L                                        = 6, | ||||
|    EDGE_STRIP_A                                        = 7, | ||||
|    EDGE_STRIP_B                                        = 8, | ||||
|    RECTS                                               = 9 | ||||
|   } begin_t; | ||||
| } | ||||
| 
 | ||||
| namespace FTDI_FT800_DL { | ||||
|   constexpr uint32_t ALPHA_FUNC                         = 0x09000000; | ||||
|   constexpr uint32_t BEGIN                              = 0x1F000000; | ||||
|   constexpr uint32_t BITMAP_HANDLE                      = 0x05000000; | ||||
|   constexpr uint32_t BITMAP_LAYOUT                      = 0x07000000; | ||||
|   constexpr uint32_t BITMAP_SIZE                        = 0x08000000; | ||||
|   constexpr uint32_t BITMAP_SOURCE                      = 0x01000000; | ||||
|   constexpr uint32_t BITMAP_TRANSFORM_A                 = 0x15000000; | ||||
|   constexpr uint32_t BITMAP_TRANSFORM_B                 = 0x16000000; | ||||
|   constexpr uint32_t BITMAP_TRANSFORM_C                 = 0x17000000; | ||||
|   constexpr uint32_t BITMAP_TRANSFORM_D                 = 0x18000000; | ||||
|   constexpr uint32_t BITMAP_TRANSFORM_E                 = 0x19000000; | ||||
|   constexpr uint32_t BITMAP_TRANSFORM_F                 = 0x1A000000; | ||||
|   constexpr uint32_t BLEND_FUNC                         = 0x0B000000; | ||||
|   constexpr uint32_t CALL                               = 0x1D000000; | ||||
|   constexpr uint32_t CELL                               = 0x06000000; | ||||
|   constexpr uint32_t CLEAR                              = 0x26000000; | ||||
|   constexpr uint32_t CLEAR_COLOR_BUFFER                 = 0x00000004; | ||||
|   constexpr uint32_t CLEAR_STENCIL_BUFFER               = 0x00000002; | ||||
|   constexpr uint32_t CLEAR_TAG_BUFFER                   = 0x00000001; | ||||
|   constexpr uint32_t CLEAR_COLOR_A                      = 0x0F000000; | ||||
|   constexpr uint32_t CLEAR_COLOR_RGB                    = 0x02000000; | ||||
|   constexpr uint32_t CLEAR_STENCIL                      = 0x11000000; | ||||
|   constexpr uint32_t CLEAR_TAG                          = 0x12000000; | ||||
|   constexpr uint32_t COLOR_A                            = 0x10000000; | ||||
|   constexpr uint32_t COLOR_MASK                         = 0x20000000; | ||||
|   constexpr uint32_t COLOR_RGB                          = 0x04000000; | ||||
|   constexpr uint32_t DL_DISPLAY                         = 0x00000000; | ||||
|   constexpr uint32_t END                                = 0x21000000; | ||||
|   constexpr uint32_t JUMP                               = 0x1E000000; | ||||
|   constexpr uint32_t LINE_WIDTH                         = 0x0E000000; | ||||
|   constexpr uint32_t MACRO                              = 0x25000000; | ||||
|   constexpr uint32_t POINT_SIZE                         = 0x0D000000; | ||||
|   constexpr uint32_t RESTORE_CONTEXT                    = 0x23000000; | ||||
|   constexpr uint32_t RETURN                             = 0x24000000; | ||||
|   constexpr uint32_t SAVE_CONTEXT                       = 0x22000000; | ||||
|   constexpr uint32_t SCISSOR_SIZE                       = 0x1C000000; | ||||
|   constexpr uint32_t SCISSOR_XY                         = 0x1B000000; | ||||
|   constexpr uint32_t STENCIL_FUNC                       = 0x0A000000; | ||||
|   constexpr uint32_t STENCIL_MASK                       = 0x13000000; | ||||
|   constexpr uint32_t STENCIL_OP                         = 0x0C000000; | ||||
|   constexpr uint32_t TAG                                = 0x03000000; | ||||
|   constexpr uint32_t TAG_MASK                           = 0x14000000; | ||||
|   constexpr uint32_t VERTEX2F                           = 0x40000000; | ||||
|   constexpr uint32_t VERTEX2II                          = 0x80000000; | ||||
| } | ||||
| 
 | ||||
| namespace FTDI_FT810_DL { | ||||
|   constexpr uint32_t NOP                                = 0x25000000; | ||||
|   constexpr uint32_t BITMAP_LAYOUT_H                    = 0x28000000; | ||||
|   constexpr uint32_t BITMAP_SIZE_H                      = 0x29000000; | ||||
|   constexpr uint32_t VERTEX_FORMAT                      = 0x27000000; | ||||
|   constexpr uint32_t VERTEX_TRANSLATE_X                 = 0x2B000000; | ||||
|   constexpr uint32_t VERTEX_TRANSLATE_Y                 = 0x2C000000; | ||||
| } | ||||
| 
 | ||||
| // CO-PROCESSOR ENGINE COMMANDS
 | ||||
| namespace FTDI { | ||||
|   constexpr uint32_t CMD_DLSTART                        = 0xFFFFFF00; | ||||
|   constexpr uint32_t CMD_SWAP                           = 0xFFFFFF01; | ||||
|   constexpr uint32_t CMD_COLDSTART                      = 0xFFFFFF32; | ||||
|   constexpr uint32_t CMD_INTERRUPT                      = 0xFFFFFF02; | ||||
|   constexpr uint32_t CMD_APPEND                         = 0xFFFFFF1E; | ||||
|   constexpr uint32_t CMD_REGREAD                        = 0xFFFFFF19; | ||||
|   constexpr uint32_t CMD_MEMWRITE                       = 0xFFFFFF1A; | ||||
|   constexpr uint32_t CMD_INFLATE                        = 0xFFFFFF22; | ||||
|   constexpr uint32_t CMD_LOADIMAGE                      = 0xFFFFFF24; | ||||
|   constexpr uint32_t CMD_MEMCRC                         = 0xFFFFFF18; | ||||
|   constexpr uint32_t CMD_MEMZERO                        = 0xFFFFFF1C; | ||||
|   constexpr uint32_t CMD_MEMSET                         = 0xFFFFFF1B; | ||||
|   constexpr uint32_t CMD_MEMCPY                         = 0xFFFFFF1D; | ||||
|   constexpr uint32_t CMD_BUTTON                         = 0xFFFFFF0D; | ||||
|   constexpr uint32_t CMD_CLOCK                          = 0xFFFFFF14; | ||||
|   constexpr uint32_t CMD_FGCOLOR                        = 0xFFFFFF0A; | ||||
|   constexpr uint32_t CMD_BGCOLOR                        = 0xFFFFFF09; | ||||
|   constexpr uint32_t CMD_GRADCOLOR                      = 0xFFFFFF34; | ||||
|   constexpr uint32_t CMD_GAUGE                          = 0xFFFFFF13; | ||||
|   constexpr uint32_t CMD_GRADIENT                       = 0xFFFFFF0B; | ||||
|   constexpr uint32_t CMD_KEYS                           = 0xFFFFFF0E; | ||||
|   constexpr uint32_t CMD_PROGRESS                       = 0xFFFFFF0F; | ||||
|   constexpr uint32_t CMD_SCROLLBAR                      = 0xFFFFFF11; | ||||
|   constexpr uint32_t CMD_SLIDER                         = 0xFFFFFF10; | ||||
|   constexpr uint32_t CMD_DIAL                           = 0xFFFFFF2D; | ||||
|   constexpr uint32_t CMD_TOGGLE                         = 0xFFFFFF12; | ||||
|   constexpr uint32_t CMD_TEXT                           = 0xFFFFFF0C; | ||||
|   constexpr uint32_t CMD_NUMBER                         = 0xFFFFFF2E; | ||||
|   constexpr uint32_t CMD_LOADIDENTITY                   = 0xFFFFFF26; | ||||
|   constexpr uint32_t CMD_SETMATRIX                      = 0xFFFFFF2A; | ||||
|   constexpr uint32_t CMD_GETMATRIX                      = 0xFFFFFF33; | ||||
|   constexpr uint32_t CMD_GETPTR                         = 0xFFFFFF23; | ||||
|   constexpr uint32_t CMD_GETPROPS                       = 0xFFFFFF25; | ||||
|   constexpr uint32_t CMD_SCALE                          = 0xFFFFFF28; | ||||
|   constexpr uint32_t CMD_ROTATE                         = 0xFFFFFF29; | ||||
|   constexpr uint32_t CMD_TRANSLATE                      = 0xFFFFFF27; | ||||
|   constexpr uint32_t CMD_CALIBRATE                      = 0xFFFFFF15; | ||||
|   constexpr uint32_t CMD_SPINNER                        = 0xFFFFFF16; | ||||
|   constexpr uint32_t CMD_SCREENSAVER                    = 0xFFFFFF2F; | ||||
|   constexpr uint32_t CMD_SKETCH                         = 0xFFFFFF30; | ||||
|   constexpr uint32_t CMD_STOP                           = 0xFFFFFF17; | ||||
|   constexpr uint32_t CMD_SETFONT                        = 0xFFFFFF2B; | ||||
|   constexpr uint32_t CMD_TRACK                          = 0xFFFFFF2C; | ||||
|   constexpr uint32_t CMD_SNAPSHOT                       = 0xFFFFFF1F; | ||||
|   constexpr uint32_t CMD_LOGO                           = 0xFFFFFF31; | ||||
| } | ||||
| 
 | ||||
| namespace FTDI_FT810 { | ||||
|   constexpr uint32_t CMD_SETROTATE                    = 0xFFFFFF36; | ||||
|   constexpr uint32_t CMD_SNAPSHOT2                    = 0xFFFFFF37; | ||||
|   constexpr uint32_t CMD_SETBASE                      = 0xFFFFFF38; | ||||
|   constexpr uint32_t CMD_MEDIAFIFO                    = 0xFFFFFF39; | ||||
|   constexpr uint32_t CMD_PLAYVIDEO                    = 0xFFFFFF3A; | ||||
|   constexpr uint32_t CMD_VIDEOSTART                   = 0xFFFFFF40; | ||||
|   constexpr uint32_t CMD_VIDEOFRAME                   = 0xFFFFFF41; | ||||
|   constexpr uint32_t CMD_SETBITMAP                    = 0xFFFFFF43; | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
|   }; | ||||
| 
 | ||||
|   enum note_t { | ||||
|     END_SONG                                        = 0xFF, | ||||
|     REST                                            = 0x00, | ||||
| 
 | ||||
|     NOTE_C1                                         = 0x18, // 24
 | ||||
|     NOTE_C1S                                        = 0x19, | ||||
|     NOTE_D1                                         = 0x1A, | ||||
|     NOTE_D1S                                        = 0x1B, | ||||
|     NOTE_E1                                         = 0x1C, | ||||
|     NOTE_F1                                         = 0x1D, | ||||
|     NOTE_F1S                                        = 0x1E, | ||||
|     NOTE_G1                                         = 0x1F, | ||||
|     NOTE_G1S                                        = 0x20, | ||||
|     NOTE_A1                                         = 0x21, | ||||
|     NOTE_A1S                                        = 0x22, | ||||
|     NOTE_B1                                         = 0x23, | ||||
| 
 | ||||
|     NOTE_C2                                         = 0x24,  //36
 | ||||
|     NOTE_C2S                                        = 0x25, | ||||
|     NOTE_D2                                         = 0x26, | ||||
|     NOTE_D2S                                        = 0x27, | ||||
|     NOTE_E2                                         = 0x28, | ||||
|     NOTE_F2                                         = 0x29, | ||||
|     NOTE_F2S                                        = 0x2A, | ||||
|     NOTE_G2                                         = 0x2B, | ||||
|     NOTE_G2S                                        = 0x2C, | ||||
|     NOTE_A2                                         = 0x2D, | ||||
|     NOTE_A2S                                        = 0x2E, | ||||
|     NOTE_B2                                         = 0x2F, | ||||
| 
 | ||||
|     NOTE_C3                                         = 0x30, | ||||
|     NOTE_C3S                                        = 0x31, | ||||
|     NOTE_D3                                         = 0x32, | ||||
|     NOTE_D3S                                        = 0x33, | ||||
|     NOTE_E3                                         = 0x34, | ||||
|     NOTE_F3                                         = 0x35, | ||||
|     NOTE_F3S                                        = 0x36, | ||||
|     NOTE_G3                                         = 0x37, | ||||
|     NOTE_G3S                                        = 0x38, | ||||
|     NOTE_A3                                         = 0x39, | ||||
|     NOTE_A3S                                        = 0x3A, | ||||
|     NOTE_B3                                         = 0x3B, | ||||
| 
 | ||||
|     NOTE_C4                                         = 0x3C, | ||||
|     NOTE_C4S                                        = 0x3D, | ||||
|     NOTE_D4                                         = 0x3E, | ||||
|     NOTE_D4S                                        = 0x3F, | ||||
|     NOTE_E4                                         = 0x40, | ||||
|     NOTE_F4                                         = 0x41, | ||||
|     NOTE_F4S                                        = 0x42, | ||||
|     NOTE_G4                                         = 0x43, | ||||
|     NOTE_G4S                                        = 0x44, | ||||
|     NOTE_A4                                         = 0x45, | ||||
|     NOTE_A4S                                        = 0x46, | ||||
|     NOTE_B4                                         = 0x47, | ||||
| 
 | ||||
|     NOTE_C5                                         = 0x48, | ||||
|     NOTE_C5S                                        = 0x49, | ||||
|     NOTE_D5                                         = 0x4A, | ||||
|     NOTE_D5S                                        = 0x4B, | ||||
|     NOTE_E5                                         = 0x4C, | ||||
|     NOTE_F5                                         = 0x4D, | ||||
|     NOTE_F5S                                        = 0x4E, | ||||
|     NOTE_G5                                         = 0x4F, | ||||
|     NOTE_G5S                                        = 0x50, | ||||
|     NOTE_A5                                         = 0x51, | ||||
|     NOTE_A5S                                        = 0x52, | ||||
|     NOTE_B5                                         = 0x53, | ||||
|   }; | ||||
| } | ||||
| @ -0,0 +1,118 @@ | ||||
| /******************
 | ||||
|  * display_list.h * | ||||
|  *****************/ | ||||
| 
 | ||||
| /**********************************************************************************
 | ||||
|  * Adapted from:                                                                  * | ||||
|  *     https://github.com/RudolphRiedel/FT800-FT813                               *
 | ||||
|  *     By Rudolph Riedel                                                          * | ||||
|  *                                                                                * | ||||
|  * MIT License                                                                    * | ||||
|  *                                                                                * | ||||
|  * Copyright (c) 2017                                                             * | ||||
|  *                                                                                * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy   * | ||||
|  * of this software and associated documentation files (the "Software"), to deal  * | ||||
|  * in the Software without restriction, including without limitation the rights   * | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell      * | ||||
|  * copies of the Software, and to permit persons to whom the Software is          * | ||||
|  * furnished to do so, subject to the following conditions:                       * | ||||
|  *                                                                                * | ||||
|  * The above copyright notice and this permission notice shall be included in all * | ||||
|  * copies or substantial portions of the Software.                                * | ||||
|  *                                                                                * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     * | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,       * | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    * | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         * | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  * | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  * | ||||
|  * SOFTWARE.                                                                      * | ||||
|  *                                                                                * | ||||
|  **********************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   /* FT8xx graphics engine specific macros useful for static display list generation */ | ||||
|   inline uint32_t ALPHA_FUNC(uint8_t func, uint8_t ref)        {return DL::ALPHA_FUNC|((func&7UL)<<8)|(ref&255UL);} | ||||
|   inline uint32_t BEGIN(begin_t prim)                          {return DL::BEGIN|(prim&15UL);} | ||||
| 
 | ||||
|   inline uint32_t BITMAP_SOURCE(uint32_t ram_g_addr)           {return DL::BITMAP_SOURCE|(ram_g_addr & (FTDI::ftdi_memory_map::RAM_G_SIZE-1));} | ||||
|   inline uint32_t BITMAP_HANDLE(uint8_t handle)                {return DL::BITMAP_HANDLE|(handle&31UL);} | ||||
|   inline uint32_t BITMAP_LAYOUT(uint8_t format, uint16_t linestride, uint16_t height) | ||||
|                                                                {return DL::BITMAP_LAYOUT|((format&31UL)<<19)|((linestride&1023UL)<<9)|(height&511UL);} | ||||
| 
 | ||||
|   inline uint32_t BITMAP_SIZE(uint8_t filter, uint8_t wrapx, uint8_t wrapy, uint16_t width, uint16_t height) | ||||
|                                                                {return DL::BITMAP_SIZE|((filter&1UL)<<20)|((wrapx&1UL)<<19)|((wrapy&1UL)<<18)|((width&511UL)<<9)|(height&511UL);} | ||||
|   #if FTDI_API_LEVEL >= 810 | ||||
|   inline uint32_t BITMAP_LAYOUT_H(uint8_t linestride, uint8_t height) | ||||
|                                                                {return DL::BITMAP_LAYOUT_H|((linestride&3UL)<<2)|(height&3UL);} | ||||
|   inline uint32_t BITMAP_SIZE_H(uint8_t width, uint8_t height) | ||||
|                                                                {return DL::BITMAP_SIZE_H|((width&3UL)<<2)|(height&3UL);} | ||||
|   #endif | ||||
|   inline uint32_t BITMAP_TRANSFORM_A(uint16_t a)               {return DL::BITMAP_TRANSFORM_A|(a&131071UL);} | ||||
|   inline uint32_t BITMAP_TRANSFORM_B(uint16_t b)               {return DL::BITMAP_TRANSFORM_B|(b&131071UL);} | ||||
|   inline uint32_t BITMAP_TRANSFORM_C(uint32_t c)               {return DL::BITMAP_TRANSFORM_C|(c&16777215UL);} | ||||
|   inline uint32_t BITMAP_TRANSFORM_D(uint16_t d)               {return DL::BITMAP_TRANSFORM_D|(d&131071UL);} | ||||
|   inline uint32_t BITMAP_TRANSFORM_E(uint16_t e)               {return DL::BITMAP_TRANSFORM_E|(e&131071UL);} | ||||
|   inline uint32_t BITMAP_TRANSFORM_F(uint32_t f)               {return DL::BITMAP_TRANSFORM_F|(f&16777215UL);} | ||||
|   inline uint32_t BLEND_FUNC(uint8_t src,uint8_t dst)          {return DL::BLEND_FUNC|((src&7UL)<<3)|(dst&7UL);} | ||||
|   inline uint32_t CALL(uint16_t dest)                          {return DL::CALL|(dest&65535UL);} | ||||
|   inline uint32_t CELL(uint8_t cell)                           {return DL::CELL|(cell&127UL);} | ||||
|   inline uint32_t CLEAR(bool c,bool s,bool t)                  {return DL::CLEAR|((c?1UL:0UL)<<2)|((s?1UL:0UL)<<1)|(t?1UL:0UL);} | ||||
|   inline uint32_t CLEAR_COLOR_A(uint8_t alpha)                 {return DL::CLEAR_COLOR_A|(alpha&255UL);} | ||||
|   inline uint32_t CLEAR_COLOR_RGB(uint8_t red, uint8_t green, uint8_t blue) | ||||
|                                                                {return DL::CLEAR_COLOR_RGB|((red&255UL)<<16)|((green&255UL)<<8)|(blue&255UL);} | ||||
|   inline uint32_t CLEAR_COLOR_RGB(uint32_t rgb)                {return DL::CLEAR_COLOR_RGB|rgb;} | ||||
|   inline uint32_t CLEAR_STENCIL(uint8_t s)                     {return DL::CLEAR_STENCIL|(s&255UL);} | ||||
|   inline uint32_t CLEAR_TAG(uint8_t s)                         {return DL::CLEAR_TAG|(s&255UL);} | ||||
|   inline uint32_t COLOR_A(uint8_t alpha)                       {return DL::COLOR_A|(alpha&255UL);} | ||||
|   inline uint32_t COLOR_MASK(bool r, bool g, bool b, bool a)   {return DL::COLOR_MASK|((r?1UL:0UL)<<3)|((g?1UL:0UL)<<2)|((b?1UL:0UL)<<1)|(a?1UL:0UL);} | ||||
|   inline uint32_t COLOR_RGB(uint8_t red,uint8_t green,uint8_t blue) | ||||
|                                                                {return DL::COLOR_RGB|((red&255UL)<<16)|((green&255UL)<<8)|(blue&255UL);} | ||||
|   inline uint32_t COLOR_RGB(uint32_t rgb)                      {return DL::COLOR_RGB|rgb;} | ||||
|   /* inline uint32_t DISPLAY()                                 {return (0UL<<24)) */ | ||||
|   inline uint32_t END()                                        {return DL::END;} | ||||
|   inline uint32_t JUMP(uint16_t dest)                          {return DL::JUMP|(dest&65535UL);} | ||||
|   inline uint32_t LINE_WIDTH(uint16_t width)                   {return DL::LINE_WIDTH|(width&4095UL);} | ||||
|   inline uint32_t MACRO(uint8_t m)                             {return DL::MACRO|(m&1UL);} | ||||
|   inline uint32_t POINT_SIZE(uint16_t size)                    {return DL::POINT_SIZE|(size&8191UL);} | ||||
|   inline uint32_t RESTORE_CONTEXT()                            {return DL::RESTORE_CONTEXT;} | ||||
|   inline uint32_t RETURN ()                                    {return DL::RETURN;} | ||||
|   inline uint32_t SAVE_CONTEXT()                               {return DL::SAVE_CONTEXT;} | ||||
|   inline uint32_t SCISSOR_XY(uint16_t x,uint16_t y) { | ||||
|     return DL::SCISSOR_XY | | ||||
|       (FTDI::ftdi_chip >= 810 | ||||
|         ? ((x&2047UL)<<11)|(y&2047UL) | ||||
|         : ((x& 511UL)<<10)|(y&511UL)); | ||||
|   } | ||||
|   inline uint32_t SCISSOR_SIZE(uint16_t w,uint16_t h) { | ||||
|     return DL::SCISSOR_SIZE | | ||||
|       (FTDI::ftdi_chip >= 810 | ||||
|         ? ((w&4095UL)<<12)|(h&4095UL) | ||||
|         : ((w&1023UL)<<10)|(h&1023UL)); | ||||
|   } | ||||
|   inline uint32_t SCISSOR_XY()                                 {return DL::SCISSOR_XY;} | ||||
|   inline uint32_t SCISSOR_SIZE() { | ||||
|     return DL::SCISSOR_SIZE | | ||||
|       (FTDI::ftdi_chip >= 810 | ||||
|         ? (2048UL<<12)|(2048UL) | ||||
|         : ( 512UL<<10)|( 512UL)); | ||||
|   } | ||||
|   inline uint32_t STENCIL_FUNC(uint16_t func, uint8_t ref, uint8_t mask) | ||||
|                                                                {return DL::STENCIL_FUNC|((func&7UL)<<16)|((ref&255UL)<<8)|(mask&255UL);} | ||||
|   inline uint32_t STENCIL_MASK(uint8_t mask)                   {return DL::STENCIL_MASK|(mask&255UL);} | ||||
|   inline uint32_t STENCIL_OP(uint8_t sfail, uint8_t spass)     {return DL::STENCIL_OP|(((sfail)&7UL)<<3)|(spass&7UL);} | ||||
|   inline uint32_t TAG(uint8_t s)                               {return DL::TAG|(s&255UL);} | ||||
|   inline uint32_t TAG_MASK(bool mask)                          {return DL::TAG_MASK|(mask?1:0);} | ||||
|   inline uint32_t VERTEX2F(uint16_t x, uint16_t y)             {return DL::VERTEX2F|((x&32767UL)<<15)|(y&32767UL);} | ||||
|   inline uint32_t VERTEX2II(uint16_t x,uint16_t y, uint8_t handle = 0, uint8_t cell = 0) | ||||
|                                                                {return DL::VERTEX2II|((x&511UL)<<21)|((y&511UL)<<12)|((handle&31UL)<<7)|(cell&127UL);} | ||||
| 
 | ||||
|   #if FTDI_API_LEVEL >= 810 | ||||
|   inline uint32_t VERTEX_FORMAT(uint8_t frac)                  {return DL::VERTEX_FORMAT|(frac&7UL);} | ||||
|   inline uint32_t VERTEX_TRANSLATE_X(int32_t x)                {return DL::VERTEX_TRANSLATE_X|(x&131071UL);} | ||||
|   inline uint32_t VERTEX_TRANSLATE_Y(int32_t y)                {return DL::VERTEX_TRANSLATE_Y|(y&131071UL);} | ||||
|   #endif | ||||
| } | ||||
| @ -0,0 +1,40 @@ | ||||
| /****************
 | ||||
|  * ftdi_basic.h * | ||||
|  ****************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2019 - Aleph Objects, Inc.                  * | ||||
|  *   Written By Marcio Teixeira 2019 - 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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "../compat.h" | ||||
| 
 | ||||
| #if !defined(__MARLIN_FIRMWARE__) | ||||
|   #define FTDI_BASIC | ||||
| #endif | ||||
| 
 | ||||
| #ifdef FTDI_BASIC | ||||
|   #include "registers_ft800.h" | ||||
|   #include "registers_ft810.h" | ||||
|   #include "constants.h" | ||||
|   #include "boards.h" | ||||
|   #include "commands.h" | ||||
|   #include "spi.h" | ||||
|   #include "display_list.h" | ||||
|   #include "resolutions.h" | ||||
| #endif | ||||
| @ -0,0 +1,150 @@ | ||||
| /*********************
 | ||||
|  * registers_ft800.h * | ||||
|  *********************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  * This header defines registers for the FTDI FT800 LCD Driver chip.        * | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| /*******************************************************************************
 | ||||
|  * FT810                                                                       * | ||||
|  *                                                                             * | ||||
|  * START    END ADDR   SIZE    NAME           DESCRIPTION                      * | ||||
|  *                                                                             * | ||||
|  * 0x000000 0x03FFFF   256 kB  RAM_G          Main Graphics RAM                * | ||||
|  *                                                                             * | ||||
|  * 0x0C0000 0x0C0003     4  B  ROM_CHIPID     [0:1] 0x800   Chip Id            * | ||||
|  *                                            [1:2] 0x0100  Vers ID            * | ||||
|  *                                                                             * | ||||
|  * 0x0BB23C 0x0FFFFB   275 kB  ROM_FONT       Font table and bitmap            * | ||||
|  *                                                                             * | ||||
|  * 0x0FFFFC 0x0FFFFF     4  B  ROM_FONT_ADDR  Font table pointer address       * | ||||
|  *                                                                             * | ||||
|  * 0x100000 0x101FFF     8 kB  RAM_DL         Display List RAM                 * | ||||
|  *                                                                             * | ||||
|  * 0x102000 0x1023FF     1 kB  RAM_PAL        Palette RAM                      * | ||||
|  *                                                                             * | ||||
|  * 0x102400 0x10257F   380  B  *          Registers                        * | ||||
|  *                                                                             * | ||||
|  * 0x108000 0x108FFF     4 kB  RAM_CMD        Command Buffer                   * | ||||
|  *                                                                             * | ||||
|  *******************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   struct ft800_memory_map { | ||||
| 
 | ||||
|     //         MEMORY LOCATIONS     FT800
 | ||||
|     static constexpr uint32_t RAM_G          = 0x000000;   // Main Graphics RAM
 | ||||
|     static constexpr uint32_t ROM_CHIPID     = 0x0C0000;   // Chip ID/Version ID
 | ||||
|     static constexpr uint32_t ROM_FONT       = 0x0BB23C;   // Font ROM
 | ||||
|     static constexpr uint32_t ROM_FONT_ADDR  = 0x0FFFFC;   // Font Table Pointer
 | ||||
|     static constexpr uint32_t RAM_DL         = 0x100000;   // Display List RAM
 | ||||
|     static constexpr uint32_t RAM_PAL        = 0x102000;   // Palette RAM
 | ||||
|     static constexpr uint32_t RAM_REG        = 0x102400;   // Registers
 | ||||
|     static constexpr uint32_t RAM_CMD        = 0x108000;   // Command Buffer
 | ||||
| 
 | ||||
|     static constexpr uint32_t RAM_G_SIZE     = 256*1024l;  // 256k
 | ||||
|   }; | ||||
| 
 | ||||
|   struct ft800_registers { | ||||
|     // REGISTERS AND ADDRESSES    FT800
 | ||||
| 
 | ||||
|     //             REGISTER              ADDRESS       SIZE    RESET VALUE     TYPE     DESCRIPTION
 | ||||
| 
 | ||||
|     static constexpr uint32_t ID                = 0x102400;  //    8    0x7C               r     Identification Register, Always 0x7C
 | ||||
|     static constexpr uint32_t FRAMES            = 0x102404;  //   32    0x00000000         r     Frame Counter, Since Reset
 | ||||
|     static constexpr uint32_t CLOCK             = 0x102408;  //   32    0x00000000         r     Clock cycles, Since Reset
 | ||||
|     static constexpr uint32_t FREQUENCY         = 0x10240C;  //   28    0x03938700       r/w     Main Clock Frequency
 | ||||
|     static constexpr uint32_t RENDERMODE        = 0x102410;  //    1    0x00             r/w     Rendering Mode: 0 = normal, 1 = single-line
 | ||||
|     static constexpr uint32_t SNAPY             = 0x102414;  //   11    0x0000           r/w     Scan Line Select for RENDERMODE 1
 | ||||
|     static constexpr uint32_t SNAPSHOT          = 0x102418;  //    1    -                  r     Trigger for RENDERMODE 1
 | ||||
|     static constexpr uint32_t CPURESET          = 0x10241C;  //    3    0x02             r/w     RESET Bit2 Audio - Bit1 Touch - Bit0 Graphics
 | ||||
|     static constexpr uint32_t TAP_CRC           = 0x102420;  //   32    -                  r     Live Video Tap
 | ||||
|     static constexpr uint32_t TAP_MASK          = 0x102424;  //   32    0xFFFFFFFF       r/w     Live Video Tap Mask
 | ||||
|     static constexpr uint32_t HCYCLE            = 0x102428;  //   12    0x224            r/w     Horizontal Total Cycle Count
 | ||||
|     static constexpr uint32_t HOFFSET           = 0x10242C;  //   12    0x02B            r/w     Horizontal Display Start Offset
 | ||||
|     static constexpr uint32_t HSIZE             = 0x102430;  //   12    0x1E0            r/w     Horizontal Display Pixel Count
 | ||||
|     static constexpr uint32_t HSYNC0            = 0x102434;  //   12    0x000            r/w     Horizontal Sync Fall Offset
 | ||||
|     static constexpr uint32_t HSYNC1            = 0x102438;  //   12    0x029            r/w     Horizontal Sync Rise Offset
 | ||||
|     static constexpr uint32_t VCYCLE            = 0x10243C;  //   12    0x124            r/w     Vertical Total Cycle Count
 | ||||
|     static constexpr uint32_t VOFFSET           = 0x102440;  //   12    0x00C            r/w     Vertical Display Start Offset
 | ||||
|     static constexpr uint32_t VSIZE             = 0x102444;  //   12    0x110            r/w     Vertical Display Line Count
 | ||||
|     static constexpr uint32_t VSYNC0            = 0x102448;  //   10    0x000            r/w     Vertical Sync Fall Offset
 | ||||
|     static constexpr uint32_t VSYNC1            = 0x10244C;  //   10    0x00A            r/w     Vertical Sync Rise Offset
 | ||||
|     static constexpr uint32_t DLSWAP            = 0x102450;  //    2    0x00             r/w     Display List Swap Control
 | ||||
|     static constexpr uint32_t ROTATE            = 0x102454;  //    3    0x00             r/w     Screen 90,180, 270 degree rotate
 | ||||
|     static constexpr uint32_t OUTBITS           = 0x102458;  //    9    0x1B6            r/w     Output Resolution, 3x3x3 Bits
 | ||||
|     static constexpr uint32_t DITHER            = 0x10245C;  //    1    0x01             r/w     Output Dither Enable
 | ||||
|     static constexpr uint32_t SWIZZLE           = 0x102460;  //    4    0x00             r/w     Output RGB Swizzle, Pin Change for PCB Routing
 | ||||
|     static constexpr uint32_t CSPREAD           = 0x102464;  //    1    0x01             r/w     Output Clock Spreading Enable
 | ||||
|     static constexpr uint32_t PCLK_POL          = 0x102468;  //    1    0x00             r/w     PCLK Polarity: 0 = Rising Edge, 1 = Falling Edge
 | ||||
|     static constexpr uint32_t PCLK              = 0x10246C;  //    8    0x00             r/w     PCLK Frequency Divider, 0 = Disable Clock
 | ||||
|     static constexpr uint32_t TAG_X             = 0x102470;  //   11    0x000            r/w     Tag Query X Coordinate
 | ||||
|     static constexpr uint32_t TAG_Y             = 0x102474;  //   11    0x000            r/w     Tag Query Y Coordinate
 | ||||
|     static constexpr uint32_t TAG               = 0x102478;  //    8    0x00               r     Tag Query Result
 | ||||
|     static constexpr uint32_t VOL_PB            = 0x10247C;  //    8    0xFF             r/w     Audio Playback Volume
 | ||||
|     static constexpr uint32_t VOL_SOUND         = 0x102480;  //    8    0xFF             r/w     Audio Synthesizer Volume
 | ||||
|     static constexpr uint32_t SOUND             = 0x102484;  //   16    0x0000           r/w     Audio Sound Effect Select
 | ||||
|     static constexpr uint32_t PLAY              = 0x102488;  //    1    0x00             r/w     Audio Start Effect Playback
 | ||||
|     static constexpr uint32_t GPIO_DIR          = 0x10248C;  //    8    0x80             r/w     GPIO Pin Direction: 0 = Input , 1 = Output
 | ||||
|     static constexpr uint32_t GPIO              = 0x102490;  //    8    0x00             r/w     GPIO Pin Values for 0, 1, 7 Drive Strength 2, 3, 4, 5, 6
 | ||||
|     static constexpr uint32_t INT_FLAGS         = 0x102498;  //    8    0x00               r     Interrupt Flags, Clear by Reading
 | ||||
|     static constexpr uint32_t INT_EN            = 0x10249C;  //    1    0x00             r/w     Global Interrupt Enable
 | ||||
|     static constexpr uint32_t INT_MASK          = 0x1024A0;  //    8    0xFF             r/w     Interrupt Enable Mask
 | ||||
|     static constexpr uint32_t PLAYBACK_START    = 0x1024A4;  //   20    0x00000          r/w     Audio Playback RAM Start Address
 | ||||
|     static constexpr uint32_t PLAYBACK_LENGTH   = 0x1024A8;  //   20    0x00000          r/w     Audio Playback Sample Length (Bytes)
 | ||||
|     static constexpr uint32_t PLAYBACK_READPTR  = 0x1024AC;  //   20    -                  r     Audio Playback Read Pointer
 | ||||
|     static constexpr uint32_t PLAYBACK_FREQ     = 0x1024B0;  //   16    0x1F40           r/w     Audio Playback Frequency (Hz)
 | ||||
|     static constexpr uint32_t PLAYBACK_FORMAT   = 0x1024B4;  //    2    0x00             r/w     Audio Playback Format
 | ||||
|     static constexpr uint32_t PLAYBACK_LOOP     = 0x1024B8;  //    1    0x00             r/w     Audio Playback Loop Enable
 | ||||
|     static constexpr uint32_t PLAYBACK_PLAY     = 0x1024BC;  //    1    0x00               r     Audio Start Playback
 | ||||
|     static constexpr uint32_t PWM_HZ            = 0x1024C0;  //   14    0x00FA           r/w     Backlight PWM Frequency (Hz)
 | ||||
|     static constexpr uint32_t PWM_DUTY          = 0x1024C4;  //    8    0x80             r/w     Backlight PWM Duty Cycle: 0 = 0%, 128 = 100%
 | ||||
|     static constexpr uint32_t MACRO_0           = 0x1024C8;  //   32    0x00000000       r/w     Display List Macro Command 0
 | ||||
|     static constexpr uint32_t MACRO_1           = 0x1024CC;  //   32    0x00000000       r/w     Display List Macro Command 1
 | ||||
|     static constexpr uint32_t CMD_READ          = 0x1024E4;  //   12    0x000            r/w     Command Buffer Read Pointer
 | ||||
|     static constexpr uint32_t CMD_WRITE         = 0x1024E8;  //   12    0x000            r/w     Command Buffer Write Pointer
 | ||||
|     static constexpr uint32_t CMD_DL            = 0x1024EC;  //   13    0x0000           r/w     Command Display List Offset
 | ||||
|     static constexpr uint32_t TOUCH_MODE        = 0x1024F0;  //    2    0x03             r/w     Touch-Screen Sampling Mode
 | ||||
|     static constexpr uint32_t TOUCH_ADC_MODE    = 0x1024F4;  //    1    0x01             r/w     Select Single Ended or Differential Sampling
 | ||||
|     static constexpr uint32_t TOUCH_CHARGE      = 0x1024F8;  //   16    0x1770           r/w     Touch Screen Charge Time, n x 6 Clocks
 | ||||
|     static constexpr uint32_t TOUCH_SETTLE      = 0x1024FC;  //    4    0x03             r/w     Touch-Screen Settle Time, n x 6 Clocks
 | ||||
|     static constexpr uint32_t TOUCH_OVERSAMPLE  = 0x102500;  //    4    0x07             r/w     Touch-Screen Oversample Factor
 | ||||
|     static constexpr uint32_t TOUCH_RZTHRESH    = 0x102504;  //   16    0xFFFF           r/w     Touch-Screen Resistance Threshold
 | ||||
|     static constexpr uint32_t TOUCH_RAW_XY      = 0x102508;  //   32    -                  r     Touch-Screen Raw (x-MSB16; y-LSB16)
 | ||||
|     static constexpr uint32_t TOUCH_RZ          = 0x10250C;  //   16    -                  r     Touch-Screen Resistance
 | ||||
|     static constexpr uint32_t TOUCH_SCREEN_XY   = 0x102510;  //   32    -                  r     Touch-Screen Screen (x-MSB16; y-LSB16)
 | ||||
|     static constexpr uint32_t TOUCH_TAG_XY      = 0x102514;  //   32    -                  r     Touch-Screen Tag 0 Lookup (x-MSB16; y-LSB16)
 | ||||
|     static constexpr uint32_t TOUCH_TAG         = 0x102518;  //    8    -                  r     Touch-Screen Tag 0 Result
 | ||||
|     static constexpr uint32_t TOUCH_TRANSFORM_A = 0x10251C;  //   32    0x00010000       r/w     Touch-Screen Transform Coefficient A (s15.16)
 | ||||
|     static constexpr uint32_t TOUCH_TRANSFORM_B = 0x102520;  //   32    0x00000000       r/w     Touch-Screen Transform Coefficient B (s15.16)
 | ||||
|     static constexpr uint32_t TOUCH_TRANSFORM_C = 0x102524;  //   32    0x00000000       r/w     Touch-Screen Transform Coefficient C (s15.16)
 | ||||
|     static constexpr uint32_t TOUCH_TRANSFORM_D = 0x102528;  //   32    0x00000000       r/w     Touch-Screen Transform Coefficient D (s15.16)
 | ||||
|     static constexpr uint32_t TOUCH_TRANSFORM_E = 0x10252C;  //   32    0x00010000       r/w     Touch-Screen Transform Coefficient E (s15.16)
 | ||||
|     static constexpr uint32_t TOUCH_TRANSFORM_F = 0x102530;  //   32    0x00000000       r/w     Touch-Screen Transform Coefficient F (s15.16)
 | ||||
|   //               Reserved Addresses      0x102434 - 0x102470
 | ||||
|     static constexpr uint32_t TOUCH_DIRECT_XY   = 0x102574;  //   32    -                  r     Touch-Screen Direct Conversions XY (x-MSB16; y-LSB16)
 | ||||
|     static constexpr uint32_t TOUCH_DIRECT_Z1Z2 = 0x102578;  //   32    -                  r     Touch-Screen Direct Conversions Z (z1-MSB16; z2-LSB16)
 | ||||
|     static constexpr uint32_t TRACKER           = 0x109000;  //   32    0x00000000       r/w     Track Register (Track Value MSB16; Tag Value - LSB8)
 | ||||
|   }; | ||||
| } | ||||
| @ -0,0 +1,185 @@ | ||||
| /*********************
 | ||||
|  * registers_ft810.h * | ||||
|  *********************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  * This header defines registers for the FTDI FT810 LCD Driver chip.        * | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| /*******************************************************************************
 | ||||
|  * FT810                                                                       * | ||||
|  *                                                                             * | ||||
|  * START    END ADDR   SIZE    NAME           DESCRIPTION                      * | ||||
|  *                                                                             * | ||||
|  * 0x000000 0x0FFFFF  1024 kB  RAM_G          Main Graphics RAM (0 to 1048572) * | ||||
|  *                                                                             * | ||||
|  * 0x0C0000 0x0C0003     4  B  ROM_CHIPID     [0:1] 0x800   Chip Id            * | ||||
|  *                                            [1:2] 0x0100  Vers ID            * | ||||
|  *                                                                             * | ||||
|  * 0x1E0000 0x2FFFFB  1152 kB  ROM_FONT       Font table and bitmap            * | ||||
|  *                                                                             * | ||||
|  * 0x2FFFFC 0x2FFFFF     4  B  ROM_FONT_ADDR  Font table pointer address       * | ||||
|  *                                                                             * | ||||
|  * 0x300000 0x301FFF     8 kB  RAM_DL         Display List RAM                 * | ||||
|  *                                                                             * | ||||
|  * 0x302000 0x302FFF     4 kB  *          Registers                        * | ||||
|  *                                                                             * | ||||
|  * 0x308000 0x308FFF     4 kB  RAM_CMD        Command Buffer                   * | ||||
|  *                                                                             * | ||||
|  *******************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   struct ft810_memory_map { | ||||
|     //         MEMORY LOCATIONS     FT810
 | ||||
|     static constexpr uint32_t RAM_G          = 0x000000;   // Main Graphics RAM
 | ||||
|     static constexpr uint32_t ROM_CHIPID     = 0x0C0000;   // Chip ID/Version ID
 | ||||
|     static constexpr uint32_t ROM_FONT       = 0x1E0000;   // Font ROM
 | ||||
|     static constexpr uint32_t ROM_FONT_ADDR  = 0x2FFFFC;   // Font Table Pointer
 | ||||
|     static constexpr uint32_t RAM_DL         = 0x300000;   // Display List RAM
 | ||||
|     static constexpr uint32_t RAM_REG        = 0x302000;   // Registers
 | ||||
|     static constexpr uint32_t RAM_CMD        = 0x308000;   // Command Buffer
 | ||||
| 
 | ||||
|     static constexpr uint32_t RAM_G_SIZE     = 1024*1024l; // 1024k
 | ||||
|   }; | ||||
| 
 | ||||
|   struct ft810_registers { | ||||
|     // REGISTERS AND ADDRESSES    FT810
 | ||||
| 
 | ||||
|     //             REGISTER              ADDRESS       SIZE    RESET VALUE     TYPE     DESCRIPTION
 | ||||
| 
 | ||||
|     static constexpr uint32_t ID                = 0x302000;  //    8    0x7C               r     Identification Register, Always 0x7C
 | ||||
|     static constexpr uint32_t FRAMES            = 0x302004;  //   32    0x00000000         r     Frame Counter, Since Reset
 | ||||
|     static constexpr uint32_t CLOCK             = 0x302008;  //   32    0x00000000         r     Clock cycles, Since Reset
 | ||||
|     static constexpr uint32_t FREQUENCY         = 0x30200C;  //   28    0x03938700       r/w     Main Clock Frequency
 | ||||
|     static constexpr uint32_t RENDERMODE        = 0x302010;  //    1    0x00             r/w     Rendering Mode: 0 = normal, 1 = single-line
 | ||||
|     static constexpr uint32_t SNAPY             = 0x302014;  //   11    0x0000           r/w     Scan Line Select for RENDERMODE 1
 | ||||
|     static constexpr uint32_t SNAPSHOT          = 0x302018;  //    1    -                  r     Trigger for RENDERMODE 1
 | ||||
|     static constexpr uint32_t SNAPFORMAT        = 0x30201C;  //    6    0x20             r/w     Pixel Format for Scanline Readout
 | ||||
|     static constexpr uint32_t CPURESET          = 0x302020;  //    3    0x02             r/w     RESET Bit2 Audio - Bit1 Touch - Bit0 Graphics
 | ||||
|     static constexpr uint32_t TAP_CRC           = 0x302024;  //   32    -                  r     Live Video Tap
 | ||||
|     static constexpr uint32_t TAP_MASK          = 0x302028;  //   32    0xFFFFFFFF       r/w     Live Video Tap Mask
 | ||||
|     static constexpr uint32_t HCYCLE            = 0x30202C;  //   12    0x224            r/w     Horizontal Total Cycle Count
 | ||||
|     static constexpr uint32_t HOFFSET           = 0x302030;  //   12    0x02B            r/w     Horizontal Display Start Offset
 | ||||
|     static constexpr uint32_t HSIZE             = 0x302034;  //   12    0x1E0            r/w     Horizontal Display Pixel Count
 | ||||
|     static constexpr uint32_t HSYNC0            = 0x302038;  //   12    0x000            r/w     Horizontal Sync Fall Offset
 | ||||
|     static constexpr uint32_t HSYNC1            = 0x30203C;  //   12    0x029            r/w     Horizontal Sync Rise Offset
 | ||||
|     static constexpr uint32_t VCYCLE            = 0x302040;  //   12    0x124            r/w     Vertical Total Cycle Count
 | ||||
|     static constexpr uint32_t VOFFSET           = 0x302044;  //   12    0x00C            r/w     Vertical Display Start Offset
 | ||||
|     static constexpr uint32_t VSIZE             = 0x302048;  //   12    0x110            r/w     Vertical Display Line Count
 | ||||
|     static constexpr uint32_t VSYNC0            = 0x30204C;  //   10    0x000            r/w     Vertical Sync Fall Offset
 | ||||
|     static constexpr uint32_t VSYNC1            = 0x302050;  //   10    0x00A            r/w     Vertical Sync Rise Offset
 | ||||
|     static constexpr uint32_t DLSWAP            = 0x302054;  //    2    0x00             r/w     Display List Swap Control
 | ||||
|     static constexpr uint32_t ROTATE            = 0x302058;  //    3    0x00             r/w     Screen 90,180, 270 degree rotate
 | ||||
|     static constexpr uint32_t OUTBITS           = 0x30205C;  //    9    0x1B6            r/w     Output Resolution, 3x3x3 Bits
 | ||||
|     static constexpr uint32_t DITHER            = 0x302060;  //    1    0x01             r/w     Output Dither Enable
 | ||||
|     static constexpr uint32_t SWIZZLE           = 0x302064;  //    4    0x00             r/w     Output RGB Swizzle, Pin Change for PCB Routing
 | ||||
|     static constexpr uint32_t CSPREAD           = 0x302068;  //    1    0x01             r/w     Output Clock Spreading Enable
 | ||||
|     static constexpr uint32_t PCLK_POL          = 0x30206C;  //    1    0x00             r/w     PCLK Polarity: 0 = Rising Edge, 1 = Falling Edge
 | ||||
|     static constexpr uint32_t PCLK              = 0x302070;  //    8    0x00             r/w     PCLK Frequency Divider, 0 = Disable Clock
 | ||||
|     static constexpr uint32_t TAG_X             = 0x302074;  //   11    0x000            r/w     Tag Query X Coordinate
 | ||||
|     static constexpr uint32_t TAG_Y             = 0x302078;  //   11    0x000            r/w     Tag Query Y Coordinate
 | ||||
|     static constexpr uint32_t TAG               = 0x30207C;  //    8    0x00               r     Tag Query Result
 | ||||
|     static constexpr uint32_t VOL_PB            = 0x302080;  //    8    0xFF             r/w     Audio Playback Volume
 | ||||
|     static constexpr uint32_t VOL_SOUND         = 0x302084;  //    8    0xFF             r/w     Audio Synthesizer Volume
 | ||||
|     static constexpr uint32_t SOUND             = 0x302088;  //   16    0x0000           r/w     Audio Sound Effect Select
 | ||||
|     static constexpr uint32_t PLAY              = 0x30208C;  //    1    0x00             r/w     Audio Start Effect Playback
 | ||||
|     static constexpr uint32_t GPIO_DIR          = 0x302090;  //    8    0x80             r/w     GPIO Pin Direction: 0 = Input , 1 = Output
 | ||||
|     static constexpr uint32_t GPIO              = 0x302094;  //    8    0x00             r/w     GPIO Pin Values for 0, 1, 7 Drive Strength 2, 3, 4, 5, 6
 | ||||
|     static constexpr uint32_t GPIOX_DIR         = 0x302098;  //   16    0x8000           r/w     Extended GPIO Pin Direction
 | ||||
|     static constexpr uint32_t GPIOX             = 0x30209C;  //   16    0x0080           r/w     Extended GPIO Pin Values
 | ||||
|     //             Reserved Addr           0x3020A0
 | ||||
|     //             Reserved Addr           0x3020A4
 | ||||
|     static constexpr uint32_t INT_FLAGS         = 0x3020A8;  //    8    0x00               r     Interrupt Flags, Clear by Reading
 | ||||
|     static constexpr uint32_t INT_EN            = 0x3020AC;  //    1    0x00             r/w     Global Interrupt Enable
 | ||||
|     static constexpr uint32_t INT_MASK          = 0x3020B0;  //    8    0xFF             r/w     Interrupt Enable Mask
 | ||||
|     static constexpr uint32_t PLAYBACK_START    = 0x3020B4;  //   20    0x00000          r/w     Audio Playback RAM Start Address
 | ||||
|     static constexpr uint32_t PLAYBACK_LENGTH   = 0x3020B8;  //   20    0x00000          r/w     Audio Playback Sample Length (Bytes)
 | ||||
|     static constexpr uint32_t PLAYBACK_READPTR  = 0x3020BC;  //   20    -                  r     Audio Playback Read Pointer
 | ||||
|     static constexpr uint32_t PLAYBACK_FREQ     = 0x3020C0;  //   16    0x1F40           r/w     Audio Playback Frequency (Hz)
 | ||||
|     static constexpr uint32_t PLAYBACK_FORMAT   = 0x3020C4;  //    2    0x00             r/w     Audio Playback Format
 | ||||
|     static constexpr uint32_t PLAYBACK_LOOP     = 0x3020C8;  //    1    0x00             r/w     Audio Playback Loop Enable
 | ||||
|     static constexpr uint32_t PLAYBACK_PLAY     = 0x3020CC;  //    1    0x00               r     Audio Start Playback
 | ||||
|     static constexpr uint32_t PWM_HZ            = 0x3020D0;  //   14    0x00FA           r/w     Backlight PWM Frequency (Hz)
 | ||||
|     static constexpr uint32_t PWM_DUTY          = 0x3020D4;  //    8    0x80             r/w     Backlight PWM Duty Cycle: 0 = 0%, 128 = 100%
 | ||||
|     static constexpr uint32_t MACRO_0           = 0x3020D8;  //   32    0x00000000       r/w     Display List Macro Command 0
 | ||||
|     static constexpr uint32_t MACRO_1           = 0x3020DC;  //   32    0x00000000       r/w     Display List Macro Command 1
 | ||||
|     //             Reserved Addr           0x3020E0
 | ||||
|     //             Reserved Addr           0x3020E4
 | ||||
|     //             Reserved Addr           0x3020E8
 | ||||
|     //             Reserved Addr           0x3020EC
 | ||||
|     //             Reserved Addr           0x3020F0
 | ||||
|     //             Reserved Addr           0x3020F4
 | ||||
|     static constexpr uint32_t CMD_READ          = 0x3020F8;  //   12    0x000            r/w     Command Buffer Read Pointer
 | ||||
|     static constexpr uint32_t CMD_WRITE         = 0x3020FC;  //   12    0x000            r/w     Command Buffer Write Pointer
 | ||||
|     static constexpr uint32_t CMD_DL            = 0x302100;  //   13    0x0000           r/w     Command Display List Offset
 | ||||
|     static constexpr uint32_t TOUCH_MODE        = 0x302104;  //    2    0x03             r/w     Touch-Screen Sampling Mode
 | ||||
|     static constexpr uint32_t TOUCH_ADC_MODE    = 0x302108;  //    1    0x01             r/w     Select Single Ended or Differential Sampling
 | ||||
|     static constexpr uint32_t TOUCH_CHARGE      = 0x30210C;  //   16    0x1770           r/w     Touch Screen Charge Time, n x 6 Clocks
 | ||||
|     static constexpr uint32_t TOUCH_SETTLE      = 0x302110;  //    4    0x03             r/w     Touch-Screen Settle Time, n x 6 Clocks
 | ||||
|     static constexpr uint32_t TOUCH_OVERSAMPLE  = 0x302114;  //    4    0x07             r/w     Touch-Screen Oversample Factor
 | ||||
|     static constexpr uint32_t TOUCH_RZTHRESH    = 0x302118;  //   16    0xFFFF           r/w     Touch-Screen Resistance Threshold
 | ||||
|     static constexpr uint32_t TOUCH_RAW_XY      = 0x30211C;  //   32    -                  r     Touch-Screen Raw (x-MSB16; y-LSB16)
 | ||||
|     static constexpr uint32_t TOUCH_RZ          = 0x302120;  //   16    -                  r     Touch-Screen Resistance
 | ||||
|     static constexpr uint32_t TOUCH_SCREEN_XY   = 0x302124;  //   32    -                  r     Touch-Screen Screen (x-MSB16; y-LSB16)
 | ||||
|     static constexpr uint32_t TOUCH_TAG_XY      = 0x302128;  //   32    -                  r     Touch-Screen Tag 0 Lookup (x-MSB16; y-LSB16)
 | ||||
|     static constexpr uint32_t TOUCH_TAG         = 0x30212C;  //    8    -                  r     Touch-Screen Tag 0 Result
 | ||||
|     static constexpr uint32_t TOUCH_TAG1_XY     = 0x302130;  //   32    -                  r     Touch-Screen Tag 1 Lookup
 | ||||
|     static constexpr uint32_t TOUCH_TAG1        = 0x302134;  //    8    -                  r     Touch-Screen Tag 1 Result
 | ||||
|     static constexpr uint32_t TOUCH_TAG2_XY     = 0x302138;  //   32    -                  r     Touch-Screen Tag 2 Lookup
 | ||||
|     static constexpr uint32_t TOUCH_TAG2        = 0x30213C;  //    8    -                  r     Touch-Screen Tag 2 Result
 | ||||
|     static constexpr uint32_t TOUCH_TAG3_XY     = 0x302140;  //   32    -                  r     Touch-Screen Tag 3 Lookup
 | ||||
|     static constexpr uint32_t TOUCH_TAG3        = 0x302144;  //    8    -                  r     Touch-Screen Tag 3 Result
 | ||||
|     static constexpr uint32_t TOUCH_TAG4_XY     = 0x302148;  //   32    -                  r     Touch-Screen Tag 4 Lookup
 | ||||
|     static constexpr uint32_t TOUCH_TAG4        = 0x30214C;  //    8    -                  r     Touch-Screen Tag 4 Result
 | ||||
|     static constexpr uint32_t TOUCH_TRANSFORM_A = 0x302150;  //   32    0x00010000       r/w     Touch-Screen Transform Coefficient A (s15.16)
 | ||||
|     static constexpr uint32_t TOUCH_TRANSFORM_B = 0x302154;  //   32    0x00000000       r/w     Touch-Screen Transform Coefficient B (s15.16)
 | ||||
|     static constexpr uint32_t TOUCH_TRANSFORM_C = 0x302158;  //   32    0x00000000       r/w     Touch-Screen Transform Coefficient C (s15.16)
 | ||||
|     static constexpr uint32_t TOUCH_TRANSFORM_D = 0x30215C;  //   32    0x00000000       r/w     Touch-Screen Transform Coefficient D (s15.16)
 | ||||
|     static constexpr uint32_t TOUCH_TRANSFORM_E = 0x302160;  //   32    0x00010000       r/w     Touch-Screen Transform Coefficient E (s15.16)
 | ||||
|     static constexpr uint32_t TOUCH_TRANSFORM_F = 0x302164;  //   32    0x00000000       r/w     Touch-Screen Transform Coefficient F (s15.16)
 | ||||
|     static constexpr uint32_t TOUCH_CONFIG      = 0x302168;  //   16    0x8381           r/w     Touch Configuration
 | ||||
|     static constexpr uint32_t CTOUCH_TOUCH4_X   = 0x30216C;  //   16    -                  r     Extended Mode Touch Screen
 | ||||
|     //             Reserved Addresses      0x302170
 | ||||
|     static constexpr uint32_t BIST_EN           = 0x302174;  //    1    0                r/w     BIST Memory Mapping Enable
 | ||||
|     //             Reserved Addr           0x302178
 | ||||
|     //             Reserved Addr           0x30217C
 | ||||
|     static constexpr uint32_t TRIM              = 0x302180;  //    8    0                r/w     Internal Clock Trimming
 | ||||
|     static constexpr uint32_t ANA_COMP          = 0x302184;  //    8    0                r/w     Analog Control Register
 | ||||
|     static constexpr uint32_t SPI_WIDTH         = 0x302188;  //    3    0                r/w     QSPI Bus Width Setting
 | ||||
|     static constexpr uint32_t TOUCH_DIRECT_XY   = 0x30218C;  //   32    -                  r     Touch-Screen Direct Conversions XY (x-MSB16; y-LSB16)
 | ||||
|     static constexpr uint32_t TOUCH_DIRECT_Z1Z2 = 0x302190;  //   32    -                  r     Touch-Screen Direct Conversions Z (z1-MSB16; z2-LSB16)
 | ||||
|     //             Reserved Addresses      0x302194 - 0x302560
 | ||||
|     static constexpr uint32_t DATESTAMP         = 0x320564;  //  128    -                  r     Stamp Date Code
 | ||||
|     static constexpr uint32_t CMDB_SPACE        = 0x302574;  //   12    0xFFC            r/w     Command DL Space Available
 | ||||
|     static constexpr uint32_t CMDB_WRITE        = 0x302578;  //   32    0                  w     Command DL Write
 | ||||
| 
 | ||||
|     static constexpr uint32_t TRACKER           = 0x309000;  //   32    0x00000000       r/w     Track Register (Track Value MSB16; Tag Value - LSB8)
 | ||||
|     static constexpr uint32_t TRACKER_1         = 0x309004;  //   32    0x00000000       r/w     Track Register (Track Value MSB16; Tag Value - LSB8)
 | ||||
|     static constexpr uint32_t TRACKER_2         = 0x309008;  //   32    0x00000000       r/w     Track Register (Track Value MSB16; Tag Value - LSB8)
 | ||||
|     static constexpr uint32_t TRACKER_3         = 0x30900C;  //   32    0x00000000       r/w     Track Register (Track Value MSB16; Tag Value - LSB8)
 | ||||
|     static constexpr uint32_t TRACKER_4         = 0x309010;  //   32    0x00000000       r/w     Track Register (Track Value MSB16; Tag Value - LSB8)
 | ||||
| 
 | ||||
|     static constexpr uint32_t MEDIAFIFO_READ    = 0x309014;  //   32    0x00000000       r/w     Media FIFO read pointer
 | ||||
|     static constexpr uint32_t MEDIAFIFO_WRITE   = 0x309018;  //   32    0x00000000       r/w     Media FIFO write pointer
 | ||||
|   }; | ||||
| } | ||||
| @ -0,0 +1,128 @@ | ||||
| /*****************
 | ||||
|  * resolutions.h * | ||||
|  *****************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2019 - Aleph Objects, Inc.                  * | ||||
|  *   Written By Marcio Teixeira 2019 - 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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| /***
 | ||||
|  * The FT8xx has odd registers that don't correspond to timing values in | ||||
|  * display datasheets. This macro computes the register values using the | ||||
|  * formulas given in the document: | ||||
|  * | ||||
|  *     Bridgetek Application Note | ||||
|  *     AN_336 FT8xx | ||||
|  *     Selecting an LCD Display | ||||
|  *     Version 2.1 | ||||
|  *     Issue Date: 2017-11-14 | ||||
|  * | ||||
|  */ | ||||
| #define COMPUTE_REGS_FROM_DATASHEET \ | ||||
|     constexpr uint16_t Hoffset              = thfp + thb - 1; \ | ||||
|     constexpr uint16_t Hcycle               = th; \ | ||||
|     constexpr uint16_t Hsync0               = thfp - 1 ; \ | ||||
|     constexpr uint16_t Hsync1               = thfp + thpw - 1; \ | ||||
|     constexpr uint16_t Voffset              = tvfp + tvb - 1; \ | ||||
|     constexpr uint16_t Vcycle               = tv; \ | ||||
|     constexpr uint16_t Vsync0               = tvfp - 1; \ | ||||
|     constexpr uint16_t Vsync1               = tvfp + tvpw - 1; \ | ||||
|     static_assert(thfp + thb + Hsize == th, "Mismatch in display th"); \ | ||||
|     static_assert(tvfp + tvb + Vsize == tv, "Mismatch in display tv"); | ||||
| 
 | ||||
| #ifdef TOUCH_UI_320x240 | ||||
|   namespace FTDI { | ||||
|     constexpr uint8_t Pclk                 =    8; | ||||
|     constexpr uint8_t Pclkpol              =    0; | ||||
|     constexpr uint16_t Hsize               =  320; | ||||
|     constexpr uint16_t Vsize               =  240; | ||||
|     constexpr uint16_t Vsync0              =    0; | ||||
|     constexpr uint16_t Vsync1              =    2; | ||||
|     constexpr uint16_t Voffset             =   13; | ||||
|     constexpr uint16_t Vcycle              =  263; | ||||
|     constexpr uint16_t Hsync0              =    0; | ||||
|     constexpr uint16_t Hsync1              =   10; | ||||
|     constexpr uint16_t Hoffset             =   70; | ||||
|     constexpr uint16_t Hcycle              =  408; | ||||
| 
 | ||||
|     constexpr uint32_t default_transform_a =  0x000054ad; | ||||
|     constexpr uint32_t default_transform_b =  0xffffff52; | ||||
|     constexpr uint32_t default_transform_c =  0xfff7f6e4; | ||||
|     constexpr uint32_t default_transform_d =  0x00000065; | ||||
|     constexpr uint32_t default_transform_e =  0xffffbe3b; | ||||
|     constexpr uint32_t default_transform_f =  0x00f68e75; | ||||
|   } | ||||
| 
 | ||||
| #elif defined(TOUCH_UI_480x272) | ||||
|   namespace FTDI { | ||||
|     constexpr uint8_t  Pclk                 =    7; | ||||
|     constexpr uint8_t  Pclkpol              =    1; | ||||
|     constexpr uint16_t Hsize                =  480; | ||||
|     constexpr uint16_t Vsize                =  272; | ||||
| 
 | ||||
|     constexpr uint16_t th                   =  525; // One horizontal line
 | ||||
|     constexpr uint16_t thfp                 =   43; // HS Front porch
 | ||||
|     constexpr uint16_t thb                  =    2; // HS Back porch (blanking)
 | ||||
|     constexpr uint16_t thpw                 =   41; // HS pulse width
 | ||||
| 
 | ||||
|     constexpr uint16_t tv                   =  286; // Vertical period time
 | ||||
|     constexpr uint16_t tvfp                 =   12; // VS Front porch
 | ||||
|     constexpr uint16_t tvb                  =    2; // VS Back porch (blanking)
 | ||||
|     constexpr uint16_t tvpw                 =   10; // VS pulse width
 | ||||
| 
 | ||||
|     COMPUTE_REGS_FROM_DATASHEET | ||||
| 
 | ||||
|     constexpr uint32_t default_transform_a  =  0x00008100; | ||||
|     constexpr uint32_t default_transform_b  =  0x00000000; | ||||
|     constexpr uint32_t default_transform_c  =  0xFFF18000; | ||||
|     constexpr uint32_t default_transform_d  =  0x00000000; | ||||
|     constexpr uint32_t default_transform_e  =  0xFFFFB100; | ||||
|     constexpr uint32_t default_transform_f  =  0x0120D000; | ||||
|   } | ||||
| 
 | ||||
| #elif defined(TOUCH_UI_800x480) | ||||
|   namespace FTDI { | ||||
|     constexpr uint8_t  Pclk                 =    3; | ||||
|     constexpr uint8_t  Pclkpol              =    1; | ||||
|     constexpr uint16_t Hsize                =  800; | ||||
|     constexpr uint16_t Vsize                =  480; | ||||
| 
 | ||||
|     constexpr uint16_t th                   = 1056; // One horizontal line
 | ||||
|     constexpr uint16_t thfp                 =  210; // HS Front porch
 | ||||
|     constexpr uint16_t thb                  =   46; // HS Back porch (blanking)
 | ||||
|     constexpr uint16_t thpw                 =   23; // HS pulse width
 | ||||
| 
 | ||||
|     constexpr uint16_t tv                   =  525; // Vertical period time
 | ||||
|     constexpr uint16_t tvfp                 =   22; // VS Front porch
 | ||||
|     constexpr uint16_t tvb                  =   23; // VS Back porch (blanking)
 | ||||
|     constexpr uint16_t tvpw                 =   10; // VS pulse width
 | ||||
| 
 | ||||
|     COMPUTE_REGS_FROM_DATASHEET | ||||
| 
 | ||||
|     constexpr uint32_t default_transform_a  =  0x0000D8B9; | ||||
|     constexpr uint32_t default_transform_b  =  0x00000124; | ||||
|     constexpr uint32_t default_transform_c  =  0xFFE23926; | ||||
|     constexpr uint32_t default_transform_d  =  0xFFFFFF51; | ||||
|     constexpr uint32_t default_transform_e  =  0xFFFF7E4F; | ||||
|     constexpr uint32_t default_transform_f  =  0x01F0AF70; | ||||
|   } | ||||
| 
 | ||||
| #else | ||||
|   #error Unknown or no LULZBOT_TOUCH_UI display resolution specified. To add a display resolution, modify "ftdi_eve_resolutions.h" | ||||
| #endif | ||||
| @ -0,0 +1,178 @@ | ||||
| /***********
 | ||||
|  * spi.cpp * | ||||
|  ***********/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #include "ftdi_basic.h" | ||||
| 
 | ||||
| #ifdef FTDI_BASIC | ||||
| 
 | ||||
| /********************************* SPI Functions *********************************/ | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   #if !defined(CLCD_USE_SOFT_SPI) | ||||
|     SPISettings SPI::spi_settings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0); | ||||
|   #endif | ||||
| 
 | ||||
|   void SPI::spi_init (void) { | ||||
|     SET_OUTPUT(CLCD_MOD_RESET); // Module Reset (a.k.a. PD, not SPI)
 | ||||
|     WRITE(CLCD_MOD_RESET, 0); // start with module in power-down
 | ||||
| 
 | ||||
|     SET_OUTPUT(CLCD_SPI_CS); | ||||
|     WRITE(CLCD_SPI_CS, 1); | ||||
| 
 | ||||
|     #ifdef SPI_FLASH_SS | ||||
|       SET_OUTPUT(SPI_FLASH_SS); | ||||
|       WRITE(SPI_FLASH_SS, 1); | ||||
|     #endif | ||||
| 
 | ||||
|     #ifdef CLCD_USE_SOFT_SPI | ||||
|       SET_OUTPUT(CLCD_SOFT_SPI_MOSI); | ||||
|       WRITE(CLCD_SOFT_SPI_MOSI, 1); | ||||
| 
 | ||||
|       SET_OUTPUT(CLCD_SOFT_SPI_SCLK); | ||||
|       WRITE(CLCD_SOFT_SPI_SCLK, 0); | ||||
| 
 | ||||
|       SET_INPUT_PULLUP(CLCD_SOFT_SPI_MISO); | ||||
|     #else | ||||
|       ::SPI.begin(); | ||||
|     #endif | ||||
|   } | ||||
| 
 | ||||
|   #ifdef CLCD_USE_SOFT_SPI | ||||
|     uint8_t SPI::_soft_spi_xfer (uint8_t spiOutByte) { | ||||
|       uint8_t spiIndex  = 0x80; | ||||
|       uint8_t spiInByte = 0; | ||||
|       uint8_t k; | ||||
| 
 | ||||
|       noInterrupts(); | ||||
|       for(k = 0; k <8; k++) {  // Output and Read each bit of spiOutByte and spiInByte
 | ||||
|         if (spiOutByte & spiIndex) {   // Output MOSI Bit
 | ||||
|           WRITE(CLCD_SOFT_SPI_MOSI, 1); | ||||
|         } | ||||
|         else { | ||||
|           WRITE(CLCD_SOFT_SPI_MOSI, 0); | ||||
|         } | ||||
|         WRITE(CLCD_SOFT_SPI_SCLK, 1);   // Pulse Clock
 | ||||
|         WRITE(CLCD_SOFT_SPI_SCLK, 0); | ||||
| 
 | ||||
|         if (READ(CLCD_SOFT_SPI_MISO)) { | ||||
|           spiInByte |= spiIndex; | ||||
|         } | ||||
| 
 | ||||
|         spiIndex >>= 1; | ||||
|       } | ||||
|       interrupts(); | ||||
|       return spiInByte; | ||||
|     } | ||||
|   #endif | ||||
| 
 | ||||
|   #ifdef CLCD_USE_SOFT_SPI | ||||
|     void SPI::_soft_spi_send (uint8_t spiOutByte) { | ||||
|       uint8_t spiIndex  = 0x80; | ||||
|       uint8_t k; | ||||
| 
 | ||||
|       noInterrupts(); | ||||
|       for(k = 0; k <8; k++) {         // Output each bit of spiOutByte
 | ||||
|         if (spiOutByte & spiIndex) {   // Output MOSI Bit
 | ||||
|           WRITE(CLCD_SOFT_SPI_MOSI, 1); | ||||
|         } | ||||
|         else { | ||||
|           WRITE(CLCD_SOFT_SPI_MOSI, 0); | ||||
|         } | ||||
|         WRITE(CLCD_SOFT_SPI_SCLK, 1);   // Pulse Clock
 | ||||
|         WRITE(CLCD_SOFT_SPI_SCLK, 0); | ||||
| 
 | ||||
|         spiIndex >>= 1; | ||||
|       } | ||||
|       interrupts(); | ||||
|     } | ||||
|   #endif | ||||
| 
 | ||||
|   void SPI::spi_read_bulk (void *data, uint16_t len) { | ||||
|     uint8_t* p = (uint8_t *)data; | ||||
|     #if !defined(CLCD_USE_SOFT_SPI) | ||||
|       ::SPI.transfer(p, len); | ||||
|     #else | ||||
|       while (len--) *p++ = spi_recv(); | ||||
|     #endif | ||||
|   } | ||||
| 
 | ||||
|   bool SPI::spi_verify_bulk (const void *data, uint16_t len) { | ||||
|     const uint8_t* p = (const uint8_t *)data; | ||||
|     while (len--) if (*p++ != spi_recv()) return false; | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   // CLCD SPI - Chip Select
 | ||||
|   void SPI::spi_ftdi_select (void) { | ||||
|     #if !defined(CLCD_USE_SOFT_SPI) | ||||
|       ::SPI.beginTransaction(spi_settings); | ||||
|     #endif | ||||
|     WRITE(CLCD_SPI_CS, 0); | ||||
|     delayMicroseconds(1); | ||||
|   } | ||||
| 
 | ||||
|   // CLCD SPI - Chip Deselect
 | ||||
|   void SPI::spi_ftdi_deselect (void) { | ||||
|     WRITE(CLCD_SPI_CS, 1); | ||||
|     #if !defined(CLCD_USE_SOFT_SPI) | ||||
|       ::SPI.endTransaction(); | ||||
|     #endif | ||||
|   } | ||||
| 
 | ||||
|   #ifdef SPI_FLASH_SS | ||||
|   // Serial SPI Flash SPI - Chip Select
 | ||||
|   void SPI::spi_flash_select () { | ||||
|     #if !defined(CLCD_USE_SOFT_SPI) | ||||
|     ::SPI.beginTransaction(spi_settings); | ||||
|     #endif | ||||
|     WRITE(SPI_FLASH_SS, 0); | ||||
|     delayMicroseconds(1); | ||||
|   } | ||||
| 
 | ||||
|   // Serial SPI Flash SPI - Chip Deselect
 | ||||
|   void SPI::spi_flash_deselect () { | ||||
|     WRITE(SPI_FLASH_SS, 1); | ||||
|     #if !defined(CLCD_USE_SOFT_SPI) | ||||
|     ::SPI.endTransaction(); | ||||
|     #endif | ||||
|   } | ||||
|   #endif | ||||
| 
 | ||||
|   // Not really a SPI signal...
 | ||||
|   void SPI::ftdi_reset (void) { | ||||
|     WRITE(CLCD_MOD_RESET, 0); | ||||
|     delay(6); /* minimum time for power-down is 5ms */ | ||||
|     WRITE(CLCD_MOD_RESET, 1); | ||||
|     delay(21); /* minimum time to allow from rising PD_N to first access is 20ms */ | ||||
|   } | ||||
| 
 | ||||
|   // Not really a SPI signal...
 | ||||
|   void SPI::test_pulse(void) | ||||
|   { | ||||
|     #ifdef CLCD_AUX_0 | ||||
|       WRITE(CLCD_AUX_0, 1); | ||||
|       delayMicroseconds(10); | ||||
|       WRITE(CLCD_AUX_0, 0); | ||||
|     #endif | ||||
|   } | ||||
| } | ||||
| #endif // FTDI_BASIC
 | ||||
| @ -0,0 +1,128 @@ | ||||
| /*********
 | ||||
|  * spi.h * | ||||
|  *********/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #if !defined(CLCD_USE_SOFT_SPI) | ||||
|   #include <SPI.h> | ||||
| #endif | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   namespace SPI { | ||||
|     #if !defined(CLCD_USE_SOFT_SPI) | ||||
|       extern SPISettings spi_settings; | ||||
|     #endif | ||||
| 
 | ||||
|     uint8_t  _soft_spi_xfer (uint8_t val); | ||||
|     void     _soft_spi_send (uint8_t val); | ||||
| 
 | ||||
|     void     spi_init           (); | ||||
| 
 | ||||
|     void     spi_ftdi_select    (); | ||||
|     void     spi_ftdi_deselect  (); | ||||
| 
 | ||||
|     void     spi_flash_select   (); | ||||
|     void     spi_flash_deselect (); | ||||
| 
 | ||||
|     inline uint8_t spi_recv() { | ||||
|       #ifdef CLCD_USE_SOFT_SPI | ||||
|         return _soft_spi_xfer(0x00); | ||||
|       #else | ||||
|         return ::SPI.transfer(0x00); | ||||
|       #endif | ||||
|     }; | ||||
| 
 | ||||
|     inline void spi_send (uint8_t val) { | ||||
|       #ifdef CLCD_USE_SOFT_SPI | ||||
|         _soft_spi_send(val); | ||||
|       #else | ||||
|         ::SPI.transfer(val); | ||||
|       #endif | ||||
|     }; | ||||
| 
 | ||||
|     inline void       spi_write_8    (uint8_t val)    {spi_send(val);}; | ||||
|     inline uint8_t    spi_read_8     ()               {return spi_recv();}; | ||||
| 
 | ||||
|     namespace least_significant_byte_first { | ||||
|       inline void     spi_write_16   (uint16_t val)   {spi_send(val >> 0); | ||||
|                                                        spi_send(val >> 8);}; | ||||
|       inline void     spi_write_32   (uint32_t val)   {spi_send(val >> 0); | ||||
|                                                        spi_send(val >> 8); | ||||
|                                                        spi_send(val >> 16); | ||||
|                                                        spi_send(val >> 24);}; | ||||
| 
 | ||||
|       inline uint8_t  spi_read_8     ()               {return spi_recv();}; | ||||
|       inline uint16_t spi_read_16    ()               {return (((uint16_t) spi_recv()) <<  0) | | ||||
|                                                               (((uint16_t) spi_recv()) <<  8);}; | ||||
|       inline uint32_t spi_read_32    ()               {return (((uint32_t) spi_recv()) <<  0) | | ||||
|                                                               (((uint32_t) spi_recv()) <<  8) | | ||||
|                                                               (((uint32_t) spi_recv()) << 16) | | ||||
|                                                               (((uint32_t) spi_recv()) << 24);}; | ||||
|     } | ||||
| 
 | ||||
|     namespace most_significant_byte_first { | ||||
|       inline void     spi_write_16   (uint16_t val)   {spi_send(val >> 8); | ||||
|                                                        spi_send(val >> 0);}; | ||||
|       inline void     spi_write_24   (uint32_t val)   {spi_send(val >> 16); | ||||
|                                                        spi_send(val >> 8); | ||||
|                                                        spi_send(val >> 0);}; | ||||
|       inline void     spi_write_32   (uint32_t val)   {spi_send(val >> 24); | ||||
|                                                        spi_send(val >> 16); | ||||
|                                                        spi_send(val >> 8); | ||||
|                                                        spi_send(val >> 0);}; | ||||
| 
 | ||||
|       inline uint16_t spi_read_16    ()               {return (((uint16_t) spi_recv()) <<  8) | | ||||
|                                                               (((uint16_t) spi_recv()) <<  0);}; | ||||
|       inline uint32_t spi_read_32    ()               {return (((uint32_t) spi_recv()) << 24) | | ||||
|                                                               (((uint32_t) spi_recv()) << 16) | | ||||
|                                                               (((uint32_t) spi_recv()) <<  8) | | ||||
|                                                               (((uint32_t) spi_recv()) <<  0);}; | ||||
|     } | ||||
| 
 | ||||
|     inline uint8_t ram_write(const uint8_t *p) {return *p;} | ||||
|     inline uint8_t pgm_write(const uint8_t *p) {return pgm_read_byte(p);} | ||||
| 
 | ||||
|     typedef uint8_t (*bulk_write_op)(const uint8_t*); | ||||
| 
 | ||||
|     // Generic template for function for writing multiple bytes, plus padding bytes.
 | ||||
|     // The template parameter op is an inlineable function which is applied to each byte.
 | ||||
| 
 | ||||
|     template<bulk_write_op byte_op> | ||||
|     void spi_write_bulk(const void *data, uint16_t len, uint8_t padding) { | ||||
|       const uint8_t* p = (const uint8_t *)data; | ||||
|       while (len--)     spi_send(byte_op(p++)); | ||||
|       while (padding--) spi_send(0); | ||||
|     } | ||||
| 
 | ||||
|     template<bulk_write_op byte_op> | ||||
|     void spi_write_bulk(const void *data, uint16_t len) { | ||||
|       const uint8_t* p = (const uint8_t *)data; | ||||
|       while (len--) spi_send(byte_op(p++)); | ||||
|     } | ||||
| 
 | ||||
|     void spi_read_bulk(      void *data, uint16_t len); | ||||
|     bool spi_verify_bulk(const void *data, uint16_t len); | ||||
| 
 | ||||
|     void ftdi_reset(void); | ||||
|     void test_pulse(void); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										222
									
								
								Marlin/src/lcd/extensible_ui/lib/lulzbot/ftdi_eve_lib/compat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								Marlin/src/lcd/extensible_ui/lib/lulzbot/ftdi_eve_lib/compat.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,222 @@ | ||||
| /****************************************************************************
 | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "../config.h" | ||||
| 
 | ||||
| #ifdef __MARLIN_FIRMWARE__ | ||||
| 
 | ||||
|   // Marlin will define the I/O functions for us
 | ||||
|   #if ENABLED(LULZBOT_TOUCH_UI) | ||||
|     #define FTDI_BASIC | ||||
|     #define FTDI_EXTENDED | ||||
|   #endif | ||||
| 
 | ||||
| #else // !__MARLIN_FIRMWARE__
 | ||||
| 
 | ||||
|   #include "Arduino.h" | ||||
| 
 | ||||
|   #if !defined(CLCD_USE_SOFT_SPI) | ||||
|     #include "SPI.h" | ||||
|   #endif | ||||
| 
 | ||||
|   namespace fast_io { | ||||
| 
 | ||||
|     template<typename port_t,uint8_t bits> | ||||
|     struct port_pin { | ||||
|       typedef port_t port; | ||||
|       static inline void set_high()         {port::port() = (port::port() |   bits);} | ||||
|       static inline void set_low()          {port::port() = (port::port() & (~bits));} | ||||
|       static inline void set_input()        {port::ddr()  = (port::ddr()  & (~bits));} | ||||
|       static inline void set_input_pullup() {set_input(); set_high();} | ||||
|       static inline void set_output()       {port::ddr()  = (port::ddr()  |   bits);} | ||||
|       static inline uint8_t read()          {return port::pin() & bits;} | ||||
|       static inline void write(bool v)      {if (v) set_high(); else set_low();} | ||||
|     }; | ||||
| 
 | ||||
|     #define MAKE_AVR_PORT_PINS(ID) \ | ||||
|       struct port_##ID { \ | ||||
|         static volatile uint8_t &pin()  {return PIN##ID;}; \ | ||||
|         static volatile uint8_t &port() {return PORT##ID;}; \ | ||||
|         static volatile uint8_t &ddr()  {return DDR##ID;}; \ | ||||
|       }; \ | ||||
|       typedef port_pin<port_##ID, 0b00000001> AVR_##ID##0; \ | ||||
|       typedef port_pin<port_##ID, 0b00000010> AVR_##ID##1; \ | ||||
|       typedef port_pin<port_##ID, 0b00000100> AVR_##ID##2; \ | ||||
|       typedef port_pin<port_##ID, 0b00001000> AVR_##ID##3; \ | ||||
|       typedef port_pin<port_##ID, 0b00010000> AVR_##ID##4; \ | ||||
|       typedef port_pin<port_##ID, 0b00100000> AVR_##ID##5; \ | ||||
|       typedef port_pin<port_##ID, 0b01000000> AVR_##ID##6; \ | ||||
|       typedef port_pin<port_##ID, 0b10000000> AVR_##ID##7; | ||||
| 
 | ||||
|     #ifdef PORTA | ||||
|       MAKE_AVR_PORT_PINS(A); | ||||
|     #endif | ||||
|     #ifdef PORTB | ||||
|       MAKE_AVR_PORT_PINS(B); | ||||
|     #endif | ||||
|     #ifdef PORTC | ||||
|       MAKE_AVR_PORT_PINS(C); | ||||
|     #endif | ||||
|     #ifdef PORTD | ||||
|       MAKE_AVR_PORT_PINS(D); | ||||
|     #endif | ||||
|     #ifdef PORTE | ||||
|       MAKE_AVR_PORT_PINS(E); | ||||
|     #endif | ||||
|     #ifdef PORTF | ||||
|       MAKE_AVR_PORT_PINS(F); | ||||
|     #endif | ||||
|     #ifdef PORTG | ||||
|       MAKE_AVR_PORT_PINS(G); | ||||
|     #endif | ||||
|     #ifdef PORTH | ||||
|       MAKE_AVR_PORT_PINS(H); | ||||
|     #endif | ||||
|     #ifdef PORTJ | ||||
|       MAKE_AVR_PORT_PINS(J); | ||||
|     #endif | ||||
|     #ifdef PORTK | ||||
|       MAKE_AVR_PORT_PINS(K); | ||||
|     #endif | ||||
|     #ifdef PORTL | ||||
|       MAKE_AVR_PORT_PINS(L); | ||||
|     #endif | ||||
|     #ifdef PORTQ | ||||
|       MAKE_AVR_PORT_PINS(Q); | ||||
|     #endif | ||||
|     #ifdef PORTR | ||||
|       MAKE_AVR_PORT_PINS(R); | ||||
|     #endif | ||||
| 
 | ||||
|     #undef MAKE_AVR_PORT_PINS | ||||
| 
 | ||||
|     template<uint8_t p> | ||||
|     struct arduino_digital_pin { | ||||
|       static constexpr uint8_t pin = p; | ||||
|       static inline void set_high()          {digitalWrite(p, HIGH);} | ||||
|       static inline void set_low()           {digitalWrite(p, LOW);} | ||||
|       static inline void set_input()         {pinMode(p, INPUT);} | ||||
|       static inline void set_input_pullup()  {pinMode(p, INPUT_PULLUP);} | ||||
|       static inline void set_output()        {pinMode(p, OUTPUT);} | ||||
|       static inline uint8_t read()           {return digitalRead(p);} | ||||
|       static inline void write(bool v)       {digitalWrite(p, v ? HIGH : LOW);} | ||||
|     }; | ||||
| 
 | ||||
|     #define MAKE_ARDUINO_PINS(ID) typedef arduino_digital_pin<ID> ARDUINO_DIGITAL_##ID; | ||||
|     MAKE_ARDUINO_PINS( 0); | ||||
|     MAKE_ARDUINO_PINS( 1); | ||||
|     MAKE_ARDUINO_PINS( 2); | ||||
|     MAKE_ARDUINO_PINS( 3); | ||||
|     MAKE_ARDUINO_PINS( 4); | ||||
|     MAKE_ARDUINO_PINS( 5); | ||||
|     MAKE_ARDUINO_PINS( 6); | ||||
|     MAKE_ARDUINO_PINS( 7); | ||||
|     MAKE_ARDUINO_PINS( 8); | ||||
|     MAKE_ARDUINO_PINS( 9); | ||||
|     MAKE_ARDUINO_PINS(10); | ||||
|     MAKE_ARDUINO_PINS(11); | ||||
|     MAKE_ARDUINO_PINS(12); | ||||
|     MAKE_ARDUINO_PINS(13); | ||||
|     MAKE_ARDUINO_PINS(14); | ||||
|     MAKE_ARDUINO_PINS(15); | ||||
|     MAKE_ARDUINO_PINS(16); | ||||
|     MAKE_ARDUINO_PINS(17); | ||||
|     MAKE_ARDUINO_PINS(18); | ||||
|     MAKE_ARDUINO_PINS(19); | ||||
|     MAKE_ARDUINO_PINS(10); | ||||
|     MAKE_ARDUINO_PINS(21); | ||||
|     MAKE_ARDUINO_PINS(22); | ||||
|     MAKE_ARDUINO_PINS(23); | ||||
|     MAKE_ARDUINO_PINS(24); | ||||
|     MAKE_ARDUINO_PINS(25); | ||||
|     MAKE_ARDUINO_PINS(26); | ||||
|     MAKE_ARDUINO_PINS(27); | ||||
|     MAKE_ARDUINO_PINS(28); | ||||
|     MAKE_ARDUINO_PINS(29); | ||||
|     MAKE_ARDUINO_PINS(30); | ||||
|     MAKE_ARDUINO_PINS(31); | ||||
|     MAKE_ARDUINO_PINS(32); | ||||
|     MAKE_ARDUINO_PINS(33); | ||||
|     MAKE_ARDUINO_PINS(34); | ||||
|     MAKE_ARDUINO_PINS(35); | ||||
|     MAKE_ARDUINO_PINS(36); | ||||
|     MAKE_ARDUINO_PINS(37); | ||||
|     MAKE_ARDUINO_PINS(38); | ||||
|     MAKE_ARDUINO_PINS(39); | ||||
|     MAKE_ARDUINO_PINS(40); | ||||
|     MAKE_ARDUINO_PINS(41); | ||||
|     MAKE_ARDUINO_PINS(42); | ||||
|     MAKE_ARDUINO_PINS(43); | ||||
|     MAKE_ARDUINO_PINS(44); | ||||
|     MAKE_ARDUINO_PINS(45); | ||||
|     MAKE_ARDUINO_PINS(46); | ||||
|     MAKE_ARDUINO_PINS(47); | ||||
|     MAKE_ARDUINO_PINS(48); | ||||
|     MAKE_ARDUINO_PINS(49); | ||||
|     MAKE_ARDUINO_PINS(50); | ||||
|     MAKE_ARDUINO_PINS(51); | ||||
|     MAKE_ARDUINO_PINS(52); | ||||
|     MAKE_ARDUINO_PINS(53); | ||||
|     #undef MAKE_ARDUINO_PINS | ||||
|   } // namespace fast_io
 | ||||
| 
 | ||||
|   #define SET_INPUT(pin)               fast_io::pin::set_input() | ||||
|   #define SET_INPUT_PULLUP(pin)        fast_io::pin::set_input(); fast_io::pin::set_high() | ||||
|   #define SET_OUTPUT(pin)              fast_io::pin::set_output() | ||||
|   #define READ(pin)                    fast_io::pin::read() | ||||
|   #define WRITE(pin, value)            fast_io::pin::write(value) | ||||
| 
 | ||||
|   #ifndef pgm_read_word_far | ||||
|   #define pgm_read_word_far pgm_read_word | ||||
|   #endif | ||||
| 
 | ||||
|   #ifndef pgm_read_dword_far | ||||
|   #define pgm_read_dword_far pgm_read_dword | ||||
|   #endif | ||||
| 
 | ||||
|   #ifndef pgm_read_ptr_far | ||||
|   #define pgm_read_ptr_far pgm_read_ptr | ||||
|   #endif | ||||
| 
 | ||||
|   #define SERIAL_ECHO_START() | ||||
|   #define SERIAL_ECHOLNPGM(str)        Serial.println(F(str)) | ||||
|   #define SERIAL_ECHOPGM(str)          Serial.print(F(str)) | ||||
|   #define SERIAL_ECHOLNPAIR(str, val) {Serial.print(F(str)); Serial.println(val);} | ||||
|   #define SERIAL_ECHOPAIR(str, val)   {Serial.print(F(str)); Serial.print(val);} | ||||
| 
 | ||||
|   #define safe_delay delay | ||||
| 
 | ||||
|   // Define macros for compatibility
 | ||||
| 
 | ||||
|   #define _CAT(a, ...)       a ## __VA_ARGS__ | ||||
|   #define SWITCH_ENABLED_    1 | ||||
|   #define ENABLED(b)         _CAT(SWITCH_ENABLED_, b) | ||||
|   #define DISABLED(b)        !ENABLED(b) | ||||
|   #define ANY(A,B)           ENABLED(A) || ENABLED(B) | ||||
| 
 | ||||
|   // Remove compiler warning on an unused variable
 | ||||
|   #ifndef UNUSED | ||||
|     #if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) | ||||
|       #define UNUSED(X) (void)X | ||||
|     #else | ||||
|       #define UNUSED(x) ((void)(x)) | ||||
|     #endif | ||||
|   #endif | ||||
| 
 | ||||
| #endif // !__MARLIN_FIRMWARE__
 | ||||
| @ -0,0 +1,49 @@ | ||||
| /*****************
 | ||||
|  * bitmap_info.h * | ||||
|  *****************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Marcio Teixeira 2019 - 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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #ifndef FORCEDINLINE | ||||
|   #define FORCEDINLINE __attribute__((always_inline)) inline | ||||
| #endif | ||||
| 
 | ||||
| namespace FTDI { | ||||
|    // 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 to read them).
 | ||||
|    // Plus, by inlining, all the equations are evaluated at compile-time as everything
 | ||||
|    // should be a constant.
 | ||||
| 
 | ||||
|    typedef struct { | ||||
|      const uint8_t  format; | ||||
|      const uint16_t linestride; | ||||
|      const uint8_t  filter; | ||||
|      const uint8_t  wrapx; | ||||
|      const uint8_t  wrapy; | ||||
|      const uint32_t RAMG_offset; | ||||
|      const uint16_t width; | ||||
|      const uint16_t height; | ||||
|    } bitmap_info_t; | ||||
| 
 | ||||
|    FORCEDINLINE uint32_t BITMAP_SOURCE (const bitmap_info_t& info) {return BITMAP_SOURCE (ftdi_memory_map::RAM_G + info.RAMG_offset);}; | ||||
|    FORCEDINLINE uint32_t BITMAP_LAYOUT (const bitmap_info_t& info) {return BITMAP_LAYOUT (info.format, info.linestride, info.height);}; | ||||
|    FORCEDINLINE uint32_t BITMAP_SIZE   (const bitmap_info_t& info) {return BITMAP_SIZE   (info.filter, info.wrapx, info.wrapy, info.width, info.height);} | ||||
| } | ||||
| @ -0,0 +1,29 @@ | ||||
| /*************************
 | ||||
|  * command_processor.cpp * | ||||
|  *************************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Marcio Teixeira 2018                                        * | ||||
|  *                                                                          * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #include "ftdi_extended.h" | ||||
| 
 | ||||
| #ifdef FTDI_EXTENDED | ||||
| 
 | ||||
| CommandProcessor::btn_style_func_t  *CommandProcessor::_btn_style_callback = CommandProcessor::default_button_style_func; | ||||
| bool CommandProcessor::is_tracking = false; | ||||
| 
 | ||||
| #endif // FTDI_EXTENDED
 | ||||
| @ -0,0 +1,347 @@ | ||||
| /***********************
 | ||||
|  * command_processor.h * | ||||
|  ***********************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| typedef struct { | ||||
|   uint32_t bg; | ||||
|   uint32_t grad; | ||||
|   uint32_t fg; | ||||
|   uint32_t rgb; | ||||
| } btn_colors; | ||||
| 
 | ||||
| /**************************** Enhanced Command Processor **************************/ | ||||
| 
 | ||||
| /* The CommandProcessor class wraps the CommandFifo with several features to make
 | ||||
|  * defining user interfaces much easier. | ||||
|  * | ||||
|  *   - Implements chaining on all methods | ||||
|  *   - Automatically adds text to button, toggle, text and keys. | ||||
|  *   - Constrains all widgets to fit inside a box for ease of layout. | ||||
|  *   - Font size is specified using a chained modifier. | ||||
|  *   - Option argument is given the default OPT_3D value. | ||||
|  */ | ||||
| 
 | ||||
| class CommandProcessor : public CLCD::CommandFifo { | ||||
|   public: | ||||
|     static constexpr uint8_t STYLE_DISABLED = 0x80; | ||||
| 
 | ||||
|   private: | ||||
|     static bool default_button_style_func(CommandProcessor &, uint8_t tag, uint8_t & /*style*/, uint16_t &options, bool) { | ||||
|       if (tag != 0 && FTDI::EventLoop::get_pressed_tag() == tag) { | ||||
|         options = FTDI::OPT_FLAT; | ||||
|       } | ||||
|       return false; | ||||
|     } | ||||
| 
 | ||||
|     typedef bool btn_style_func_t(CommandProcessor &cmd, uint8_t tag, uint8_t &style, uint16_t &options, bool post); | ||||
| 
 | ||||
|     static btn_style_func_t  *_btn_style_callback; | ||||
|     static bool is_tracking; | ||||
|     int8_t  _font = 26, _tag = 0; | ||||
|     uint8_t _style = 0; | ||||
| 
 | ||||
|   protected: | ||||
|     // Returns the cannonical thickness of a widget (i.e. the height of a toggle element)
 | ||||
|     uint16_t widget_thickness() { | ||||
|       CLCD::FontMetrics fm(_font); | ||||
|       return fm.height * 20.0/16; | ||||
|     } | ||||
| 
 | ||||
|     FORCEDINLINE void linear_widget_box(int16_t &x, int16_t &y, int16_t &w, int16_t &h, bool tracker = false) { | ||||
|       const uint16_t th = widget_thickness()/2; | ||||
|       if (w > h) { | ||||
|         x += tracker ? th * 2.5 : th; | ||||
|         y += h/2  - th/2; | ||||
|         w -= tracker ? th * 5.0 : th * 2; | ||||
|         h  = th; | ||||
|       } else { | ||||
|         x += w/2  - th/2; | ||||
|         y += tracker ? th * 2.5 : th; | ||||
|         w  = th; | ||||
|         h -= tracker ? th * 5.0 : th * 2; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     FORCEDINLINE uint16_t circular_widget_box(int16_t &x, int16_t &y, int16_t &w, int16_t &h) { | ||||
|       const uint16_t r = min(w,h)/2; | ||||
|       x += w/2; | ||||
|       y += h/2; | ||||
|       w  = 1; | ||||
|       h  = 1; | ||||
|       return r; | ||||
|     } | ||||
| 
 | ||||
|   public: | ||||
|     // Helper method for setting all colors at once
 | ||||
|     inline CommandProcessor& colors(const btn_colors &colors) { | ||||
|       cmd(FTDI::COLOR_RGB(colors.rgb)) | ||||
|         .gradcolor(colors.grad) | ||||
|         .fgcolor(colors.fg) | ||||
|         .bgcolor(colors.bg); | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     inline CommandProcessor& bitmap_size(uint8_t filter, uint8_t wrapx, uint8_t wrapy, uint16_t width, uint16_t height) { | ||||
|       cmd(FTDI::BITMAP_SIZE(filter, wrapx, wrapy, width, height)); | ||||
|       #if FTDI_API_LEVEL >= 810 | ||||
|         if (FTDI::ftdi_chip >= 810) | ||||
|           cmd(FTDI::BITMAP_SIZE_H(width >> 9, height >> 9)); | ||||
|       #endif | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     inline CommandProcessor& bitmap_layout(uint8_t format, uint16_t linestride, uint16_t height) { | ||||
|       cmd(FTDI::BITMAP_LAYOUT(format, linestride, height)); | ||||
|       #if FTDI_API_LEVEL >= 810 | ||||
|         if (FTDI::ftdi_chip >= 810) | ||||
|           cmd(FTDI::BITMAP_LAYOUT_H(linestride >> 10, height >> 9)); | ||||
|       #endif | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     inline CommandProcessor& set_button_style_callback(const btn_style_func_t *func) { | ||||
|       _btn_style_callback = func ? func : default_button_style_func; | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     inline CommandProcessor& tag      (uint8_t  tag)              {_tag = tag; cmd(FTDI::TAG(tag)); return *this;} | ||||
| 
 | ||||
|     inline CommandProcessor& font     (int16_t  font)             {_font = font; return *this;} | ||||
| 
 | ||||
|     inline CommandProcessor& enabled  (bool enabled) { | ||||
|       if (enabled) | ||||
|         _style &= ~STYLE_DISABLED; | ||||
|       else | ||||
|         _style |= STYLE_DISABLED; | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     inline CommandProcessor& style    (uint8_t style) { | ||||
|       _style = (_style & STYLE_DISABLED) | style; | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     // Wrap all the CommandFifo routines to allow method chaining
 | ||||
| 
 | ||||
|     inline CommandProcessor& cmd      (uint32_t cmd32)            {CLCD::CommandFifo::cmd(cmd32); return *this;} | ||||
|     inline CommandProcessor& cmd      (void* data, uint16_t len)  {CLCD::CommandFifo::cmd(data, len); return *this;} | ||||
|     inline CommandProcessor& execute()                            {CLCD::CommandFifo::execute(); return *this;} | ||||
| 
 | ||||
|     inline CommandProcessor& fgcolor  (uint32_t rgb)              {CLCD::CommandFifo::fgcolor(rgb); return *this;} | ||||
|     inline CommandProcessor& bgcolor  (uint32_t rgb)              {CLCD::CommandFifo::bgcolor(rgb); return *this;} | ||||
|     inline CommandProcessor& gradcolor(uint32_t rgb)              {CLCD::CommandFifo::gradcolor(rgb); return *this;} | ||||
| 
 | ||||
|     inline CommandProcessor& snapshot (uint32_t ptr)              {CLCD::CommandFifo::snapshot(ptr); return *this;} | ||||
| 
 | ||||
|     inline CommandProcessor& loadimage(uint32_t ptr, uint32_t options) | ||||
|                                                                   {CLCD::CommandFifo::loadimage(ptr, options); return *this;} | ||||
|     inline CommandProcessor& sketch   (int16_t x, int16_t y, uint16_t w, uint16_t h, uint32_t ptr, uint16_t format) | ||||
|                                                                   {CLCD::CommandFifo::sketch(x, y, w, h, ptr, format); return *this;} | ||||
|     inline CommandProcessor& screensaver  ()                      {CLCD::CommandFifo::screensaver(); return *this;} | ||||
|     #if FTDI_API_LEVEL >= 810 | ||||
|     inline CommandProcessor& setbase  (uint8_t base)              {CLCD::CommandFifo::setbase(base); return *this;} | ||||
|     #endif | ||||
|     inline CommandProcessor& loadidentity ()                      {CLCD::CommandFifo::loadidentity(); return *this;} | ||||
|     inline CommandProcessor& scale    (int32_t sx, int32_t sy)    {CLCD::CommandFifo::scale(sx,sy); return *this;} | ||||
|     inline CommandProcessor& rotate   (int32_t a)                 {CLCD::CommandFifo::rotate(a); return *this;} | ||||
|     inline CommandProcessor& translate(int32_t tx, int32_t ty)    {CLCD::CommandFifo::translate(tx,ty); return *this;} | ||||
|     inline CommandProcessor& setmatrix ()                         {CLCD::CommandFifo::setmatrix(); return *this;} | ||||
|     inline CommandProcessor& stop ()                              {CLCD::CommandFifo::stop(); return *this;} | ||||
| 
 | ||||
|     inline CommandProcessor& memzero  (uint32_t ptr, uint32_t size) | ||||
|                                                                   {CLCD::CommandFifo::memzero(ptr, size); return *this;} | ||||
|     inline CommandProcessor& memset   (uint32_t ptr, uint32_t val, uint32_t size) | ||||
|                                                                   {CLCD::CommandFifo::memset(ptr, val, size); return *this;} | ||||
|     inline CommandProcessor& memcpy   (uint32_t src, uint32_t dst, uint32_t size) | ||||
|                                                                   {CLCD::CommandFifo::memcpy(src, dst, size); return *this;} | ||||
|     inline CommandProcessor& memcrc   (uint32_t ptr, uint32_t num, uint32_t result) | ||||
|                                                                   {CLCD::CommandFifo::memcrc(ptr, num, result); return *this;} | ||||
|     inline CommandProcessor& memwrite (uint32_t ptr, uint32_t value) | ||||
|                                                                   {CLCD::CommandFifo::memwrite(ptr, value); return *this;} | ||||
|     inline CommandProcessor& inflate  (uint32_t ptr) | ||||
|                                                                   {CLCD::CommandFifo::inflate(ptr); return *this;} | ||||
|     inline CommandProcessor& getptr   (uint32_t result) | ||||
|                                                                   {CLCD::CommandFifo::getptr(result); return *this;} | ||||
|     inline CommandProcessor& getprops (uint32_t ptr, uint32_t width, uint32_t height) | ||||
|                                                                   {CLCD::CommandFifo::getprops(ptr, width, height); return *this;} | ||||
| 
 | ||||
|     #if FTDI_API_LEVEL >= 810 | ||||
|     inline CommandProcessor& setbitmap (uint32_t ptr, uint16_t fmt, uint16_t w, uint16_t h) | ||||
|                                                                   {CLCD::CommandFifo::setbitmap(ptr,fmt,w,h); return *this;} | ||||
|     inline CommandProcessor& snapshot2 (uint32_t fmt, uint32_t ptr, int16_t x, int16_t y, uint16_t w, uint16_t h) | ||||
|                                                                   {CLCD::CommandFifo::snapshot2(fmt,ptr,x,y,w,h); return *this;} | ||||
|     inline CommandProcessor& mediafifo (uint32_t p, uint32_t s)   {CLCD::CommandFifo::mediafifo(p, s); return *this;} | ||||
|     inline CommandProcessor& playvideo(uint32_t options)          {CLCD::CommandFifo::playvideo(options); return *this;} | ||||
|     #endif | ||||
| 
 | ||||
|     inline CommandProcessor& gradient(int16_t x0, int16_t y0, uint32_t rgb0, int16_t x1, int16_t y1, uint32_t rgb1) | ||||
|                                                                   {CLCD::CommandFifo::gradient(x0,y0,rgb0,x1,y1,rgb1); return *this;} | ||||
| 
 | ||||
|     inline CommandProcessor& rectangle(int16_t x, int16_t y, int16_t w, int16_t h) { | ||||
|       using namespace FTDI; | ||||
|       CLCD::CommandFifo::cmd(BEGIN(RECTS)); | ||||
|       CLCD::CommandFifo::cmd(VERTEX2F(x*16,y*16)); | ||||
|       CLCD::CommandFifo::cmd(VERTEX2F((x+w)*16,(y+h)*16)); | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     FORCEDINLINE CommandProcessor& toggle(int16_t x, int16_t y, int16_t w, int16_t h, T text, bool state, uint16_t options = FTDI::OPT_3D) { | ||||
|       CLCD::FontMetrics fm(_font); | ||||
|       const int16_t widget_h = fm.height * 20.0/16; | ||||
|       //const int16_t outer_bar_r = widget_h / 2;
 | ||||
|       //const int16_t knob_r      = outer_bar_r - 1.5;
 | ||||
|       // The y coordinate of the toggle is the baseline of the text,
 | ||||
|       // so we must introduce a fudge factor based on the line height to
 | ||||
|       // actually center the control.
 | ||||
|       const int16_t fudge_y = fm.height*5/16; | ||||
|       CLCD::CommandFifo::toggle(x + h/2, y + h/2 - widget_h/2 + fudge_y, w - h, _font, options, state); | ||||
|       CLCD::CommandFifo::str(text); | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     // Contrained drawing routines. These constrain the widget inside a box for easier layout.
 | ||||
|     // The FORCEDINLINE ensures that the code is inlined so that all the math is done at compile time.
 | ||||
| 
 | ||||
|     FORCEDINLINE CommandProcessor& track_linear(int16_t x, int16_t y, int16_t w, int16_t h, int16_t tag) { | ||||
|       linear_widget_box(x, y, w, h, true); | ||||
|       CLCD::CommandFifo::track(x, y, w, h, tag); | ||||
|       is_tracking = true; | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     FORCEDINLINE CommandProcessor& track_circular(int16_t x, int16_t y, int16_t w, int16_t h, int16_t tag) { | ||||
|       circular_widget_box(x,y, w, h); | ||||
|       CLCD::CommandFifo::track(x, y, w, h, tag); | ||||
|       is_tracking = true; | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     uint8_t track_tag (uint16_t &value) { | ||||
|       if (is_tracking) { | ||||
|         if (FTDI::EventLoop::is_touch_held()) { | ||||
|           return CLCD::get_tracker(value); | ||||
|         } else { | ||||
|           CLCD::CommandFifo::track(0, 0, 0, 0, 0); | ||||
|           CLCD::CommandFifo::execute(); | ||||
|           is_tracking = false; | ||||
|         } | ||||
|       } | ||||
|       return 0; | ||||
|     } | ||||
| 
 | ||||
|     FORCEDINLINE CommandProcessor& clock(int16_t x, int16_t y, int16_t w, int16_t h, int16_t hr, int16_t m, int16_t s, int16_t ms, uint16_t options = FTDI::OPT_3D) { | ||||
|       const uint16_t r = circular_widget_box(x, y, w, h); | ||||
|       CLCD::CommandFifo::clock(x, y, r, options, hr, m, s, ms); | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     FORCEDINLINE CommandProcessor& gauge(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t major, uint16_t minor, uint16_t val, uint16_t range, uint16_t options = FTDI::OPT_3D) { | ||||
|       const uint16_t r = circular_widget_box(x, y, w, h); | ||||
|       CLCD::CommandFifo::gauge(x, y, r, options, major, minor, val, range); | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     FORCEDINLINE CommandProcessor& dial(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t val, uint16_t options = FTDI::OPT_3D) { | ||||
|       const uint16_t r = circular_widget_box(x, y, w, h); | ||||
|       CLCD::CommandFifo::dial(x, y, r, options, val); | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     FORCEDINLINE CommandProcessor& slider(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t val, uint16_t range, uint16_t options = FTDI::OPT_3D) { | ||||
|       linear_widget_box(x, y, w, h); | ||||
|       CLCD::CommandFifo::slider(x, y, w, h, options, val, range); | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     FORCEDINLINE CommandProcessor& progress(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t val, uint16_t range, uint16_t options = FTDI::OPT_3D) { | ||||
|       linear_widget_box(x, y, w, h); | ||||
|       CLCD::CommandFifo::progress(x, y, w, h, options, val, range); | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     FORCEDINLINE CommandProcessor& scrollbar(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t val, uint16_t size, uint16_t range, uint16_t options = 0) { | ||||
|       linear_widget_box(x, y, w, h); | ||||
|       CLCD::CommandFifo::scrollbar(x, y, w, h, options, val, size, range); | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     CommandProcessor& number(int16_t x, int16_t y, int16_t w, int16_t h, int32_t n, uint16_t options = FTDI::OPT_CENTER) { | ||||
|       using namespace FTDI; | ||||
|       CLCD::CommandFifo::number( | ||||
|         x + ((options & OPT_CENTERX) ? w/2 : ((options & OPT_RIGHTX) ? w : 0)), | ||||
|         y + ((options & OPT_CENTERY) ? h/2 : h), | ||||
|         _font, options, n); | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     template<typename T> FORCEDINLINE | ||||
|     CommandProcessor& text(int16_t x, int16_t y, int16_t w, int16_t h, T text, uint16_t options = FTDI::OPT_CENTER) { | ||||
|       using namespace FTDI; | ||||
|       CLCD::CommandFifo::text( | ||||
|         x + ((options & OPT_CENTERX) ? w/2 : ((options & OPT_RIGHTX) ? w : 0)), | ||||
|         y + ((options & OPT_CENTERY) ? h/2 : h), | ||||
|         _font, options); | ||||
|       CLCD::CommandFifo::str(text); | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     FORCEDINLINE CommandProcessor& icon(int16_t x, int16_t y, int16_t w, int16_t h, const FTDI::bitmap_info_t& info, const float scale = 1) { | ||||
|       using namespace FTDI; | ||||
|       cmd(BEGIN(BITMAPS)); | ||||
|       if (scale != 1) { | ||||
|         cmd(BITMAP_TRANSFORM_A(uint32_t(float(256)/scale))); | ||||
|         cmd(BITMAP_TRANSFORM_E(uint32_t(float(256)/scale))); | ||||
|       } | ||||
|       cmd(BITMAP_SIZE(info.filter, info.wrapx, info.wrapy, info.width*scale, info.height*scale)); | ||||
|       cmd(VERTEX2F((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)); | ||||
|       } | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     CommandProcessor& button(int16_t x, int16_t y, int16_t w, int16_t h, T text, uint16_t options = FTDI::OPT_3D) { | ||||
|       using namespace FTDI; | ||||
|       bool styleModified = false; | ||||
|       if (_btn_style_callback) styleModified = _btn_style_callback(*this, _tag, _style, options, false); | ||||
|       CLCD::CommandFifo::button(x, y, w, h, _font, options); | ||||
|       CLCD::CommandFifo::str(text); | ||||
|       if (_btn_style_callback && styleModified) _btn_style_callback(*this, _tag, _style, options, true); | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     CommandProcessor& keys(int16_t x, int16_t y, int16_t w, int16_t h, T keys, uint16_t options = FTDI::OPT_3D) { | ||||
|       CLCD::CommandFifo::keys(x, y, w, h, _font, options); | ||||
|       CLCD::CommandFifo::str(keys); | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
|     FORCEDINLINE CommandProcessor& spinner(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t style = 0, uint16_t scale = 0) { | ||||
|       circular_widget_box(x, y, w, h); | ||||
|       CLCD::CommandFifo::spinner(x, y, style, scale); | ||||
|       return *this; | ||||
|     } | ||||
| }; | ||||
| @ -0,0 +1,176 @@ | ||||
| /****************
 | ||||
|  * dl_cache.cpp * | ||||
|  ****************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #include "ftdi_extended.h" | ||||
| 
 | ||||
| #ifdef FTDI_EXTENDED | ||||
| 
 | ||||
| /* The Display List Cache mechanism stores the display list corresponding
 | ||||
|  * to a menu into RAM_G so that on subsequent calls drawing the menu does | ||||
|  * not require as much SPI traffic. | ||||
|  * | ||||
|  * 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 | ||||
|  *                      ... | ||||
|  */ | ||||
| 
 | ||||
| #define DL_CACHE_START   MAP::RAM_G_SIZE - 0xFFFF | ||||
| #define DL_FREE_ADDR     DL_CACHE_START + DL_CACHE_SLOTS * 8 | ||||
| 
 | ||||
| using namespace FTDI; | ||||
| 
 | ||||
| // The init function ensures all cache locations are marked as empty
 | ||||
| 
 | ||||
| void DLCache::init() { | ||||
|   CLCD::mem_write_32(DL_FREE_ADDR, DL_FREE_ADDR + 4); | ||||
|   for(uint8_t slot = 0; slot < DL_CACHE_SLOTS; slot++) { | ||||
|     save_slot(slot, 0, 0); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| bool DLCache::has_data() { | ||||
|   return dl_size != 0; | ||||
| } | ||||
| 
 | ||||
| bool DLCache::wait_until_idle() { | ||||
|   const unsigned long startTime = millis(); | ||||
|   do { | ||||
|     if ((millis() - startTime) > 250) { | ||||
|       SERIAL_ECHO_START(); | ||||
|       SERIAL_ECHOLNPGM("Timeout on DL_Cache::Wait_Until_Idle()"); | ||||
|       CLCD::CommandFifo::reset(); | ||||
|       return false; | ||||
|     } | ||||
|     #ifdef __MARLIN_FIRMWARE__ | ||||
|       ExtUI::yield(); | ||||
|     #endif | ||||
|   } while (CLCD::CommandFifo::is_processing()); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| /* 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 DLCache::store(uint32_t num_bytes /* = 0*/) { | ||||
|   CLCD::CommandFifo cmd; | ||||
| 
 | ||||
|   // Execute any commands already in the FIFO
 | ||||
|   cmd.execute(); | ||||
|   if (!wait_until_idle()) | ||||
|     return false; | ||||
| 
 | ||||
|   // Figure out how long the display list is
 | ||||
|   uint32_t new_dl_size = CLCD::mem_read_32(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     = CLCD::mem_read_32(DL_FREE_ADDR); | ||||
|     free_space  = MAP::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_size > free_space) { | ||||
|     // Not enough memory to cache the display list.
 | ||||
|     #ifdef UI_FRAMEWORK_DEBUG | ||||
|       SERIAL_ECHO_START(); | ||||
|       SERIAL_ECHOPAIR("Not enough space in GRAM to cache display list, free space: ", free_space); | ||||
|       SERIAL_ECHOLNPAIR(" Required: ", dl_size); | ||||
|     #endif | ||||
|     return false; | ||||
|   } else { | ||||
|     #ifdef UI_FRAMEWORK_DEBUG | ||||
|       SERIAL_ECHO_START(); | ||||
|       SERIAL_ECHOPAIR("Saving DL to RAMG cache, bytes: ", dl_size); | ||||
|       SERIAL_ECHOLNPAIR(" Free space: ", free_space); | ||||
|     #endif | ||||
|     cmd.memcpy(dl_addr, MAP::RAM_DL, dl_size); | ||||
|     cmd.execute(); | ||||
|     save_slot(dl_slot, dl_addr, dl_size); | ||||
|     if (dl_alloc > 0) { | ||||
|       // If we allocated space dynamically, then adjust dl_free_addr.
 | ||||
|       CLCD::mem_write_32(DL_FREE_ADDR, dl_addr + dl_alloc); | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void DLCache::save_slot(uint8_t dl_slot, uint32_t dl_addr, uint32_t dl_size) { | ||||
|   CLCD::mem_write_32(DL_CACHE_START + dl_slot * 8 + 0, dl_addr); | ||||
|   CLCD::mem_write_32(DL_CACHE_START + dl_slot * 8 + 4, dl_size); | ||||
| } | ||||
| 
 | ||||
| void DLCache::load_slot() { | ||||
|   dl_addr  = CLCD::mem_read_32(DL_CACHE_START + dl_slot * 8 + 0); | ||||
|   dl_size  = CLCD::mem_read_32(DL_CACHE_START + dl_slot * 8 + 4); | ||||
| } | ||||
| 
 | ||||
| void DLCache::append() { | ||||
|   CLCD::CommandFifo cmd; | ||||
|   cmd.append(dl_addr, dl_size); | ||||
|   #ifdef UI_FRAMEWORK_DEBUG | ||||
|     cmd.execute(); | ||||
|     wait_until_idle(); | ||||
|     SERIAL_ECHO_START(); | ||||
|     SERIAL_ECHOPAIR("Appending to DL from RAMG cache, bytes: ", dl_size); | ||||
|     SERIAL_ECHOLNPAIR(" REG_CMD_DL: ", CLCD::mem_read_32(REG::CMD_DL)); | ||||
|   #endif | ||||
| } | ||||
| 
 | ||||
| #endif // FTDI_EXTENDED
 | ||||
| @ -0,0 +1,69 @@ | ||||
| /**************
 | ||||
|  * dl_cache.h * | ||||
|  **************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| /******************* DISPLAY LIST CACHE MANAGEMENT ************************/ | ||||
| /* The Display List Cache mechanism stores the display list corresponding
 | ||||
|  * to a menu into RAM_G so that on subsequent calls drawing the menu does | ||||
|  * not require as much SPI traffic. Dynamic content, such as indicators, | ||||
|  * should not be cached. | ||||
|  * | ||||
|  * The DLCache can be used like so: | ||||
|  * | ||||
|  *   void some_function() { | ||||
|  *     DLCache dlcache(UNIQUE_ID); | ||||
|  * | ||||
|  *     if (dlcache.hasData()) { | ||||
|  *        dlcache.append(); | ||||
|  *     } else { | ||||
|  *        // Add stuff to the DL
 | ||||
|  *        dlcache.store(); | ||||
|  *     } | ||||
|  */ | ||||
| class DLCache { | ||||
|   private: | ||||
|     typedef FTDI::ftdi_registers  REG; | ||||
|     typedef FTDI::ftdi_memory_map MAP; | ||||
| 
 | ||||
|     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); | ||||
| 
 | ||||
|     bool wait_until_idle(); | ||||
| 
 | ||||
|   public: | ||||
|     static void init(); | ||||
| 
 | ||||
|     DLCache(uint8_t slot) { | ||||
|       dl_slot = slot; | ||||
|       load_slot(); | ||||
|     } | ||||
| 
 | ||||
|     bool has_data(); | ||||
|     bool store(uint32_t num_bytes = 0); | ||||
|     void append(); | ||||
| }; | ||||
| 
 | ||||
| #define DL_CACHE_SLOTS   250 | ||||
| @ -0,0 +1,230 @@ | ||||
| /******************
 | ||||
|  * event_loop.cpp * | ||||
|  ******************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #include "ftdi_extended.h" | ||||
| 
 | ||||
| #ifdef FTDI_EXTENDED | ||||
| using namespace FTDI; | ||||
| 
 | ||||
| enum { | ||||
|   UNPRESSED       = 0x00 | ||||
| }; | ||||
| 
 | ||||
| tiny_timer_t touch_timer; | ||||
| UIData::flags_t UIData::flags; | ||||
| uint8_t pressed_tag  = UNPRESSED; | ||||
| 
 | ||||
| uint8_t UIData::get_persistent_data_mask() { | ||||
|   // A bit mask for flags that should be stored to the EEPROM.
 | ||||
|   // Others are considered temporarily values that need not be
 | ||||
|   // saved.
 | ||||
|   constexpr flags_t persistent_flags = { | ||||
|     bits: { | ||||
|       touch_start_sound:  true, | ||||
|       touch_end_sound:    true, | ||||
|       touch_repeat_sound: true, | ||||
|       show_animations:    true | ||||
|     } | ||||
|   }; | ||||
|   return persistent_flags.value; | ||||
| } | ||||
| 
 | ||||
| void UIData::reset_persistent_data() { | ||||
|   // Default values for persistent data
 | ||||
|   constexpr flags_t default_flags = { | ||||
|     bits: { | ||||
|       touch_start_sound:  true, | ||||
|       touch_end_sound:    true, | ||||
|       touch_repeat_sound: true, | ||||
|       show_animations:    true, | ||||
|       touch_debouncing:   false, | ||||
|       ignore_unpress:     false | ||||
|     } | ||||
|   }; | ||||
|   flags.value = default_flags.value; | ||||
| } | ||||
| 
 | ||||
| uint8_t UIData::get_persistent_data() { | ||||
|   return flags.value & get_persistent_data_mask(); | ||||
| } | ||||
| 
 | ||||
| void UIData::set_persistent_data(uint8_t value) { | ||||
|   flags.value = value & get_persistent_data_mask(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void UIData::enable_touch_sounds(bool enabled) { | ||||
|   UIData::flags.bits.touch_start_sound  = enabled; | ||||
|   UIData::flags.bits.touch_end_sound    = enabled; | ||||
|   UIData::flags.bits.touch_repeat_sound = enabled; | ||||
| } | ||||
| 
 | ||||
| bool UIData::touch_sounds_enabled() { | ||||
|   return UIData::flags.bits.touch_start_sound || UIData::flags.bits.touch_end_sound || UIData::flags.bits.touch_repeat_sound; | ||||
| } | ||||
| 
 | ||||
| void UIData::enable_animations(bool enabled) { | ||||
|     UIData::flags.bits.show_animations = enabled; | ||||
| } | ||||
| 
 | ||||
| bool UIData::animations_enabled() { | ||||
|   return UIData::flags.bits.show_animations; | ||||
| } | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   uint8_t EventLoop::get_pressed_tag() { | ||||
|     return pressed_tag; | ||||
|   } | ||||
| 
 | ||||
|   bool EventLoop::is_touch_held() { | ||||
|     return pressed_tag != 0; | ||||
|   } | ||||
| 
 | ||||
|   /**
 | ||||
|    * process_events(): Process events from the touch panel. | ||||
|    * | ||||
|    * This function consists of a state machine that accomplishes the following: | ||||
|    * | ||||
|    *  - Reads the tag register from the touch panel | ||||
|    *  - Dispatches onTouchStart and onTouchEnd events to the active screen. | ||||
|    *  - Handles auto-repetition by sending onTouchHeld to the active screen periodically. | ||||
|    *  - Plays touch feedback "click" sounds when appropriate. | ||||
|    *  - Performs debouncing to supress spurious touch events. | ||||
|    * | ||||
|    */ | ||||
|   void EventLoop::process_events() { | ||||
|     // If the LCD is processing commands, don't check
 | ||||
|     // for tags since they may be changing and could
 | ||||
|     // cause spurious events.
 | ||||
|     if (!touch_timer.elapsed(TOUCH_UPDATE_INTERVAL) || CLCD::CommandFifo::is_processing()) { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     const uint8_t tag = CLCD::get_tag(); | ||||
| 
 | ||||
|     switch (pressed_tag) { | ||||
|       case UNPRESSED: | ||||
|         if (tag != 0) { | ||||
|           #ifdef UI_FRAMEWORK_DEBUG | ||||
|             SERIAL_ECHO_START(); | ||||
|             SERIAL_ECHOLNPAIR("Touch start: ", tag); | ||||
|           #endif | ||||
| 
 | ||||
|           pressed_tag = tag; | ||||
|           current_screen.onRefresh(); | ||||
| 
 | ||||
|           // 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.start(); | ||||
|             if (UIData::flags.bits.touch_start_sound) sound.play(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.
 | ||||
|             UIData::flags.bits.ignore_unpress = true; | ||||
|           } else { | ||||
|             UIData::flags.bits.ignore_unpress = false; | ||||
|           } | ||||
|         } else { | ||||
|           touch_timer.start(); | ||||
|         } | ||||
|         break; | ||||
|       default: // PRESSED
 | ||||
|         if (!UIData::flags.bits.touch_debouncing) { | ||||
|           if (tag == pressed_tag) { | ||||
|             // The user is holding down a button.
 | ||||
|             if (touch_timer.elapsed(1000 / TOUCH_REPEATS_PER_SECOND) && current_screen.onTouchHeld(tag)) { | ||||
|               current_screen.onRefresh(); | ||||
|               if (UIData::flags.bits.touch_repeat_sound) sound.play(repeat_sound); | ||||
|               touch_timer.start(); | ||||
|             } | ||||
|           } | ||||
|           else if (tag == 0) { | ||||
|             touch_timer.start(); | ||||
|             UIData::flags.bits.touch_debouncing = true; | ||||
|           } | ||||
|         } | ||||
| 
 | ||||
|         else { | ||||
|           // Debouncing...
 | ||||
| 
 | ||||
|           if (tag == pressed_tag) { | ||||
|             // If while debouncing, we detect a press, then cancel debouncing.
 | ||||
|             UIData::flags.bits.touch_debouncing = false; | ||||
|           } | ||||
| 
 | ||||
|           else if (touch_timer.elapsed(DEBOUNCE_PERIOD)) { | ||||
|             UIData::flags.bits.touch_debouncing = false; | ||||
| 
 | ||||
|             if (UIData::flags.bits.ignore_unpress) { | ||||
|               UIData::flags.bits.ignore_unpress = false; | ||||
|               pressed_tag = UNPRESSED; | ||||
|               break; | ||||
|             } | ||||
| 
 | ||||
|             if (UIData::flags.bits.touch_end_sound) sound.play(unpress_sound); | ||||
| 
 | ||||
|             #ifdef UI_FRAMEWORK_DEBUG | ||||
|               SERIAL_ECHO_START(); | ||||
|               SERIAL_ECHOLNPAIR("Touch end: ", tag); | ||||
|             #endif | ||||
| 
 | ||||
|             const uint8_t saved_pressed_tag = pressed_tag; | ||||
|             pressed_tag = UNPRESSED; | ||||
|             current_screen.onTouchEnd(saved_pressed_tag); | ||||
|             current_screen.onRefresh(); | ||||
|           } | ||||
|         } | ||||
|         break; | ||||
|     } // switch (pressed_tag)
 | ||||
| 
 | ||||
|   } // processEvents()
 | ||||
| 
 | ||||
|   void EventLoop::setup() { | ||||
|     CLCD::init(); | ||||
|     DLCache::init(); | ||||
|     UIData::reset_persistent_data(); | ||||
|     current_screen.start(); | ||||
|   } | ||||
| 
 | ||||
|   void EventLoop::loop() { | ||||
|     sound.onIdle(); | ||||
| 
 | ||||
|     /**
 | ||||
|       * Guard against re-entry of UI methods, which can | ||||
|       * crash. Re-entry can happen because some functions | ||||
|       * (e.g. planner.synchronize) call idle(). | ||||
|       */ | ||||
|     if (!UIData::flags.bits.prevent_reentry) { | ||||
|       UIData::flags.bits.prevent_reentry = true; | ||||
|       current_screen.onIdle(); | ||||
|       process_events(); | ||||
|       UIData::flags.bits.prevent_reentry = false; | ||||
|     } | ||||
|   } | ||||
| } // namespace FTDI
 | ||||
| 
 | ||||
| #endif // FTDI_EXTENDED
 | ||||
| @ -0,0 +1,74 @@ | ||||
| /****************
 | ||||
|  * event_loop.h * | ||||
|  ****************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #define STATUS_UPDATE_INTERVAL     1000 | ||||
| #define TOUCH_UPDATE_INTERVAL        50 | ||||
| #define TOUCH_REPEATS_PER_SECOND      4 | ||||
| #define DEBOUNCE_PERIOD             150 | ||||
| 
 | ||||
| class UIData { | ||||
|   private: | ||||
|     typedef union { | ||||
|       struct { | ||||
|         uint8_t touch_start_sound  : 1; | ||||
|         uint8_t touch_end_sound    : 1; | ||||
|         uint8_t touch_repeat_sound : 1; | ||||
|         uint8_t show_animations    : 1; | ||||
|         uint8_t touch_debouncing   : 1; | ||||
|         uint8_t ignore_unpress     : 1; | ||||
|         uint8_t prevent_reentry    : 1; | ||||
|       } bits; | ||||
|       uint8_t value; | ||||
|     } flags_t; | ||||
| 
 | ||||
|   public: | ||||
|     static flags_t flags; | ||||
| 
 | ||||
|     static uint8_t get_persistent_data_mask(); | ||||
|     static uint8_t get_persistent_data(); | ||||
|     static void set_persistent_data(uint8_t value); | ||||
|     static void reset_persistent_data(); | ||||
| 
 | ||||
|     static void enable_touch_sounds(bool enabled); | ||||
|     static bool touch_sounds_enabled(); | ||||
|     static void enable_animations(bool enabled); | ||||
|     static bool animations_enabled(); | ||||
| }; | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   class EventLoop { | ||||
|     private: | ||||
|       static constexpr FTDI::effect_t press_sound   = FTDI::CHACK; | ||||
|       static constexpr FTDI::effect_t repeat_sound  = FTDI::CHACK; | ||||
|       static constexpr FTDI::effect_t unpress_sound = FTDI::POP; | ||||
|       static void process_events(); | ||||
| 
 | ||||
|     public: | ||||
|       static void setup(); | ||||
|       static void loop(); | ||||
| 
 | ||||
|       static uint8_t get_pressed_tag(); | ||||
|       static bool is_touch_held(); | ||||
|   }; | ||||
| } | ||||
| @ -0,0 +1,45 @@ | ||||
| /*******************
 | ||||
|  * ftdi_extended.h * | ||||
|  *******************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2019 - Aleph Objects, Inc.                  * | ||||
|  *   Written By Marcio Teixeira 201( - 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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "../compat.h" | ||||
| #include "../basic/ftdi_basic.h" | ||||
| 
 | ||||
| #if !defined(__MARLIN_FIRMWARE__) | ||||
|   #define FTDI_EXTENDED | ||||
| #endif | ||||
| 
 | ||||
| #ifdef FTDI_EXTENDED | ||||
|   #include "rgb_t.h" | ||||
|   #include "bitmap_info.h" | ||||
|   #include "tiny_timer.h" | ||||
|   #include "grid_layout.h" | ||||
|   #include "dl_cache.h" | ||||
|   #include "screen_types.h" | ||||
|   #include "event_loop.h" | ||||
|   #include "command_processor.h" | ||||
|   #include "sound_player.h" | ||||
|   #include "sound_list.h" | ||||
|   #include "polygon.h" | ||||
|   #include "text_box.h" | ||||
| #endif | ||||
| @ -0,0 +1,98 @@ | ||||
| /*****************
 | ||||
|  * grid_layout.h * | ||||
|  *****************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| /* The grid layout macros allow buttons to be arranged on a grid so
 | ||||
|  * that their locations become independent of the display size. The | ||||
|  * layout model is similar to that of HTML TABLEs. | ||||
|  * | ||||
|  * These macros are meant to be evaluated into constants at compile | ||||
|  * time, so resolution independence can be as efficient as using | ||||
|  * hard-coded coordinates. | ||||
|  */ | ||||
| 
 | ||||
| // Margin defines the margin (in pixels) on each side of a button in
 | ||||
| // the layout
 | ||||
| 
 | ||||
| #ifdef TOUCH_UI_800x480 | ||||
|   #define MARGIN_L         5 | ||||
|   #define MARGIN_R         5 | ||||
|   #define MARGIN_T         5 | ||||
|   #define MARGIN_B         5 | ||||
|   #define MARGIN_DEFAULT   5 | ||||
| #else | ||||
|   #define MARGIN_L         3 | ||||
|   #define MARGIN_R         3 | ||||
|   #define MARGIN_T         3 | ||||
|   #define MARGIN_B         3 | ||||
|   #define MARGIN_DEFAULT   3 | ||||
| #endif | ||||
| 
 | ||||
| // EDGE_R adds some black space on the right edge of the display
 | ||||
| // This shifts some of the screens left to visually center them.
 | ||||
| 
 | ||||
| #define EDGE_R           0 | ||||
| 
 | ||||
| // GRID_X and GRID_Y computes the positions of the divisions on
 | ||||
| // the layout grid.
 | ||||
| #define GRID_X(x)        ((x)*(FTDI::display_width-EDGE_R)/GRID_COLS) | ||||
| #define GRID_Y(y)        ((y)*FTDI::display_height/GRID_ROWS) | ||||
| 
 | ||||
| // BTN_X, BTN_Y, BTN_W and BTN_X returns the top-left and width
 | ||||
| // and height of a button, taking into account the button margins.
 | ||||
| 
 | ||||
| #define BTN_X(x)         (GRID_X((x)-1) + MARGIN_L) | ||||
| #define BTN_Y(y)         (GRID_Y((y)-1) + MARGIN_T) | ||||
| #define BTN_W(w)         (GRID_X(w)   - MARGIN_L - MARGIN_R) | ||||
| #define BTN_H(h)         (GRID_Y(h)   - MARGIN_T - MARGIN_B) | ||||
| 
 | ||||
| // Abbreviations for common phrases, to allow a button to be
 | ||||
| // defined in one line of source.
 | ||||
| #define BTN_POS(x,y)     BTN_X(x), BTN_Y(y) | ||||
| #define BTN_SIZE(w,h)    BTN_W(w), BTN_H(h) | ||||
| 
 | ||||
| // Draw a reference grid for ease of spacing out widgets.
 | ||||
| #define DRAW_LAYOUT_GRID \ | ||||
|   { \ | ||||
|     cmd.cmd(LINE_WIDTH(4)); \ | ||||
|     for(int i = 1; i <= GRID_COLS; i++) { \ | ||||
|       cmd.cmd(BEGIN(LINES)); \ | ||||
|       cmd.cmd(VERTEX2F(GRID_X(i) *16, 0             *16)); \ | ||||
|       cmd.cmd(VERTEX2F(GRID_X(i) *16, FTDI::display_height *16)); \ | ||||
|     } \ | ||||
|     for(int i = 1; i < GRID_ROWS; i++) { \ | ||||
|       cmd.cmd(BEGIN(LINES)); \ | ||||
|       cmd.cmd(VERTEX2F(0                       *16, GRID_Y(i) *16)); \ | ||||
|       cmd.cmd(VERTEX2F(FTDI::display_width     *16, GRID_Y(i) *16)); \ | ||||
|     } \ | ||||
|     cmd.cmd(LINE_WIDTH(16)); \ | ||||
|   } | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   #ifdef TOUCH_UI_PORTRAIT | ||||
|     constexpr uint16_t display_width  = Vsize; | ||||
|     constexpr uint16_t display_height = Hsize; | ||||
|   #else | ||||
|     constexpr uint16_t display_width  = Hsize; | ||||
|     constexpr uint16_t display_height = Vsize; | ||||
|   #endif | ||||
| } | ||||
| @ -0,0 +1,96 @@ | ||||
| /*************
 | ||||
|  * polygon.h * | ||||
|  *************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Marcio Teixeira 2019 - 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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| /**
 | ||||
|  * The Polygon class helps drawing filled or stroked polygons on the FTDI EVE: | ||||
|  * | ||||
|  *   CommandProcessor cmd; | ||||
|  *   cmd.cmd(COLOR_RGB(0x00FF00)); | ||||
|  * | ||||
|  *   Polygon p(cmd); | ||||
|  *   p.begin_fill(); | ||||
|  *     p.begin_loop(); | ||||
|  *      p(10,10); | ||||
|  *      p(20,10); | ||||
|  *      p(20,20); | ||||
|  *      p(10,20); | ||||
|  *     p.end_loop(); | ||||
|  *     p.begin_loop(); | ||||
|  *        ...  // Additional closed paths
 | ||||
|  *     p.end_loop(); | ||||
|  *        ... | ||||
|  *   p.end_fill(); | ||||
|  * | ||||
|  * Based on the example from "Applicaton Note AN_334, FT801 Polygon Application": | ||||
|  * | ||||
|  *   https://brtchip.com/wp-content/uploads/Support/Documentation/Application_Notes/ICs/EVE/AN_334-FT801_Polygon_Application.pdf
 | ||||
|  */ | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   class Polygon { | ||||
|     private: | ||||
|       FTDI::begin_t path_initiator = FTDI::LINE_STRIP; | ||||
| 
 | ||||
|     public: | ||||
|       CommandProcessor &cmd; | ||||
| 
 | ||||
|       Polygon(CommandProcessor &c) : cmd(c) {} | ||||
| 
 | ||||
|       void begin_fill() { | ||||
|         using namespace FTDI; | ||||
|         cmd.cmd(SAVE_CONTEXT()); | ||||
|         cmd.cmd(TAG_MASK(0)); | ||||
|         cmd.cmd(CLEAR(0,1,0)); | ||||
|         cmd.cmd(COLOR_MASK(0,0,0,0)); | ||||
|         cmd.cmd(STENCIL_OP(STENCIL_OP_KEEP, STENCIL_OP_INVERT)); | ||||
|         cmd.cmd(STENCIL_FUNC(STENCIL_FUNC_ALWAYS, 255, 255)); | ||||
|         // Drawing the edge strip along scan lines
 | ||||
|         // seems to yield the best performance
 | ||||
|         #ifdef TOUCH_UI_PORTRAIT | ||||
|           path_initiator = EDGE_STRIP_B; | ||||
|         #else | ||||
|           path_initiator = EDGE_STRIP_R; | ||||
|         #endif | ||||
|       } | ||||
| 
 | ||||
|       // Specify a clipping rectangle to paint fewer pixels and reduce rendering time, otherwise all pixels will be painted.
 | ||||
|       void end_fill(const int16_t x1 = 0, const int16_t y1 = 0, const int16_t x2 = display_width * 16, const int16_t y2 = display_height * 16) { | ||||
|         using namespace FTDI; | ||||
|         cmd.cmd(RESTORE_CONTEXT()); | ||||
| 
 | ||||
|         cmd.cmd(SAVE_CONTEXT()); | ||||
|         cmd.cmd(STENCIL_FUNC(STENCIL_FUNC_NOTEQUAL, 0, 255)); | ||||
|         cmd.cmd(BEGIN(RECTS)); | ||||
|         cmd.cmd(VERTEX2F(x1, y1)); | ||||
|         cmd.cmd(VERTEX2F(x2, y2)); | ||||
|         cmd.cmd(RESTORE_CONTEXT()); | ||||
|       } | ||||
| 
 | ||||
|       void begin_stroke() {path_initiator = FTDI::LINE_STRIP;} | ||||
|       void begin_loop()   {cmd.cmd(FTDI::BEGIN(path_initiator));} | ||||
|       void end_stroke()   {} | ||||
|       void end_loop()     {} | ||||
| 
 | ||||
|       void operator()(const uint16_t x, const uint16_t y) {cmd.cmd(FTDI::VERTEX2F(x, y));} | ||||
|   }; | ||||
| } | ||||
| @ -0,0 +1,44 @@ | ||||
| /***********
 | ||||
|  * rgb_t.h * | ||||
|  ***********/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| struct rgb_t { | ||||
|     union { | ||||
|       struct { | ||||
|         uint8_t  b,g,r,a; | ||||
|       }; | ||||
|       uint32_t packed; | ||||
|     }; | ||||
| 
 | ||||
|     rgb_t()                                : packed(0)              {} | ||||
|     rgb_t(uint32_t rgb)                    : packed(rgb)            {} | ||||
|     rgb_t(uint8_t r, uint8_t g, uint8_t b) : b(b), g(g), r(r), a(0) {} | ||||
|     operator uint32_t() const              {return packed;}; | ||||
| 
 | ||||
|     static void lerp(float t, const rgb_t a, const rgb_t b, rgb_t &c) { | ||||
|       c.r = a.r + t * (b.r - a.r); | ||||
|       c.g = a.g + t * (b.g - a.g); | ||||
|       c.b = a.b + t * (b.b - a.b); | ||||
|     } | ||||
| 
 | ||||
|     uint8_t luminance() const {return 0.299*r + 0.587*g + 0.114*b;} | ||||
| }; | ||||
| @ -0,0 +1,106 @@ | ||||
| /******************
 | ||||
|  * screen_types.h * | ||||
|  ******************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #include "ftdi_extended.h" | ||||
| 
 | ||||
| #ifdef FTDI_EXTENDED | ||||
| 
 | ||||
| /********************** VIRTUAL DISPATCH DATA TYPE  ******************************/ | ||||
| 
 | ||||
| uint8_t ScreenRef::lookupScreen(onRedraw_func_t onRedraw_ptr) { | ||||
|   for(uint8_t type = 0; type < functionTableSize; type++) { | ||||
|     if (GET_METHOD(type, onRedraw) == onRedraw_ptr) { | ||||
|       return type; | ||||
|     } | ||||
|   } | ||||
|   #ifdef UI_FRAMEWORK_DEBUG | ||||
|     SERIAL_ECHO_START(); | ||||
|     SERIAL_ECHOPAIR("Screen not found: ", (uintptr_t) onRedraw_ptr); | ||||
|   #endif | ||||
|   return 0xFF; | ||||
| } | ||||
| 
 | ||||
| void ScreenRef::setScreen(onRedraw_func_t onRedraw_ptr) { | ||||
|   uint8_t type = lookupScreen(onRedraw_ptr); | ||||
|   if (type != 0xFF) { | ||||
|     setType(type); | ||||
|     #ifdef UI_FRAMEWORK_DEBUG | ||||
|       SERIAL_ECHO_START(); | ||||
|       SERIAL_ECHOLNPAIR("New screen: ", type); | ||||
|     #endif | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void ScreenRef::initializeAll() { | ||||
|   for(uint8_t type = 0; type < functionTableSize; type++) { | ||||
|     GET_METHOD(type, onStartup)(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /********************** SCREEN STACK  ******************************/ | ||||
| 
 | ||||
| void ScreenStack::start() { | ||||
|   initializeAll(); | ||||
|   onEntry(); | ||||
| } | ||||
| 
 | ||||
| void ScreenStack::push(onRedraw_func_t onRedraw_ptr) { | ||||
|   stack[3] = stack[2]; | ||||
|   stack[2] = stack[1]; | ||||
|   stack[1] = stack[0]; | ||||
|   stack[0] = lookupScreen(onRedraw_ptr); | ||||
| } | ||||
| 
 | ||||
| void ScreenStack::push() { | ||||
|   stack[3] = stack[2]; | ||||
|   stack[2] = stack[1]; | ||||
|   stack[1] = stack[0]; | ||||
|   stack[0] = getType(); | ||||
| } | ||||
| 
 | ||||
| void ScreenStack::pop() { | ||||
|   setType(stack[0]); | ||||
|   forget(); | ||||
| } | ||||
| 
 | ||||
| void ScreenStack::forget() { | ||||
|   stack[0] = stack[1]; | ||||
|   stack[1] = stack[2]; | ||||
|   stack[2] = stack[3]; | ||||
|   stack[3] = 0; | ||||
| } | ||||
| 
 | ||||
| void ScreenStack::goTo(onRedraw_func_t s) { | ||||
|   push(); | ||||
|   onExit(); | ||||
|   setScreen(s); | ||||
|   onEntry(); | ||||
| } | ||||
| 
 | ||||
| void ScreenStack::goBack() { | ||||
|   onExit(); | ||||
|   pop(); | ||||
|   onEntry(); | ||||
| } | ||||
| 
 | ||||
| ScreenStack current_screen; | ||||
| 
 | ||||
| #endif // FTDI_EXTENDED
 | ||||
| @ -0,0 +1,215 @@ | ||||
| /********************
 | ||||
|  * screen_types.cpp * | ||||
|  ********************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| typedef enum { | ||||
|   BACKGROUND  = 1, | ||||
|   FOREGROUND  = 2, | ||||
|   BOTH        = 3 | ||||
| } draw_mode_t; | ||||
| 
 | ||||
|  /********************** VIRTUAL DISPATCH DATA TYPE  ******************************/ | ||||
| 
 | ||||
| // True virtual classes are extremely expensive on the Arduino
 | ||||
| // as the compiler stores the virtual function tables in RAM.
 | ||||
| // We invent a data type called ScreenRef that gives us
 | ||||
| // polymorphism by mapping an ID to virtual methods on various
 | ||||
| // classes. This works by keeping a table in PROGMEM of pointers
 | ||||
| // to static methods.
 | ||||
| 
 | ||||
| #define DECL_SCREEN(className) { \ | ||||
|   className::onStartup, \ | ||||
|   className::onEntry, \ | ||||
|   className::onExit, \ | ||||
|   className::onIdle, \ | ||||
|   className::onRefresh, \ | ||||
|   className::onRedraw, \ | ||||
|   className::onTouchStart, \ | ||||
|   className::onTouchHeld, \ | ||||
|   className::onTouchEnd \ | ||||
| } | ||||
| 
 | ||||
| #define GET_METHOD(type, method) reinterpret_cast<method##_func_t*>(pgm_read_ptr_far(&functionTable[type].method##_ptr)) | ||||
| #define SCREEN_TABLE             PROGMEM const ScreenRef::table_t ScreenRef::functionTable[] = | ||||
| #define SCREEN_TABLE_POST        const uint8_t ScreenRef::functionTableSize = sizeof(ScreenRef::functionTable)/sizeof(ScreenRef::functionTable[0]); | ||||
| 
 | ||||
| class ScreenRef { | ||||
|   protected: | ||||
|     typedef void onStartup_func_t(void); | ||||
|     typedef void onEntry_func_t(void); | ||||
|     typedef void onExit_func_t(void); | ||||
|     typedef void onIdle_func_t(void); | ||||
|     typedef void onRefresh_func_t(void); | ||||
|     typedef void onRedraw_func_t(draw_mode_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 { | ||||
|       onStartup_func_t     *onStartup_ptr; | ||||
|       onEntry_func_t       *onEntry_ptr; | ||||
|       onExit_func_t        *onExit_ptr; | ||||
|       onIdle_func_t        *onIdle_ptr; | ||||
|       onRefresh_func_t     *onRefresh_ptr; | ||||
|       onRedraw_func_t      *onRedraw_ptr; | ||||
|       onTouchStart_func_t  *onTouchStart_ptr; | ||||
|       onTouchHeld_func_t   *onTouchHeld_ptr; | ||||
|       onTouchEnd_func_t    *onTouchEnd_ptr; | ||||
|     } table_t; | ||||
| 
 | ||||
|     uint8_t type = 0; | ||||
|     static PROGMEM const table_t functionTable[]; | ||||
|     static const uint8_t functionTableSize; | ||||
| 
 | ||||
|   public: | ||||
|     uint8_t getType() {return type;} | ||||
| 
 | ||||
|     void setType(uint8_t t) { | ||||
|       type = t; | ||||
|     } | ||||
| 
 | ||||
|     uint8_t lookupScreen(onRedraw_func_t onRedraw_ptr); | ||||
| 
 | ||||
|     void setScreen(onRedraw_func_t onRedraw_ptr); | ||||
| 
 | ||||
|     void onStartup()               {GET_METHOD(type, onStartup)();} | ||||
|     void onEntry()                 {GET_METHOD(type, onEntry)();} | ||||
|     void onExit()                  {GET_METHOD(type, onExit)();} | ||||
|     void onIdle()                  {GET_METHOD(type, onIdle)();} | ||||
|     void onRefresh()               {GET_METHOD(type, onRefresh)();} | ||||
|     void onRedraw(draw_mode_t dm)  {GET_METHOD(type, onRedraw)(dm);} | ||||
|     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(); | ||||
| }; | ||||
| 
 | ||||
| /********************** SCREEN STACK  ******************************/ | ||||
| 
 | ||||
| // To conserve dynamic memory, the screen stack is hard-coded to
 | ||||
| // have four values, allowing a menu of up to four levels.
 | ||||
| 
 | ||||
| class ScreenStack : public ScreenRef { | ||||
|   private: | ||||
|     uint8_t stack[4]; | ||||
| 
 | ||||
|   public: | ||||
|     void start(); | ||||
|     void push(onRedraw_func_t); | ||||
|     void push(); | ||||
|     void pop(); | ||||
|     void forget(); | ||||
|     void goTo(onRedraw_func_t); | ||||
|     void goBack(); | ||||
| 
 | ||||
|     uint8_t peek()      {return stack[0];} | ||||
|     uint8_t getScreen() {return getType();} | ||||
| }; | ||||
| 
 | ||||
| extern ScreenStack current_screen; | ||||
| 
 | ||||
| /********************** BASE SCREEN CLASS ******************************/ | ||||
| 
 | ||||
| /* UIScreen is the base class for all user interface screens.
 | ||||
|  */ | ||||
| class UIScreen { | ||||
|   public: | ||||
|     static void onStartup()            {} | ||||
|     static void onEntry()              {current_screen.onRefresh();} | ||||
|     static void onExit()               {} | ||||
|     static void onIdle()               {} | ||||
|     static bool onTouchStart(uint8_t)  {return true;} | ||||
|     static bool onTouchHeld(uint8_t)   {return false;} | ||||
|     static bool onTouchEnd(uint8_t)    {return true;} | ||||
| }; | ||||
| 
 | ||||
| #define PUSH_SCREEN(screen)   current_screen.push(screen::onRedraw); | ||||
| #define GOTO_SCREEN(screen)   current_screen.goTo(screen::onRedraw); | ||||
| #define GOTO_PREVIOUS()       current_screen.goBack(); | ||||
| #define AT_SCREEN(screen)     (current_screen.getType() == current_screen.lookupScreen(screen::onRedraw)) | ||||
| #define IS_PARENT_SCREEN(screen) (current_screen.peek() == current_screen.lookupScreen(screen::onRedraw)) | ||||
| 
 | ||||
| /************************** CACHED VS UNCHACHED SCREENS ***************************/ | ||||
| 
 | ||||
| class UncachedScreen { | ||||
|   public: | ||||
|     static void onRefresh() { | ||||
|       using namespace FTDI; | ||||
|       CLCD::CommandFifo cmd; | ||||
|       cmd.cmd(CMD_DLSTART); | ||||
| 
 | ||||
|       current_screen.onRedraw(BOTH); | ||||
| 
 | ||||
|       cmd.cmd(DL::DL_DISPLAY); | ||||
|       cmd.cmd(CMD_SWAP); | ||||
|       cmd.execute(); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| template<uint8_t DL_SLOT,uint32_t DL_SIZE = 0> | ||||
| class CachedScreen { | ||||
|   protected: | ||||
|     static bool storeBackground(){ | ||||
|       DLCache dlcache(DL_SLOT); | ||||
|       if (!dlcache.store(DL_SIZE)) { | ||||
|         SERIAL_ECHO_START(); | ||||
|         SERIAL_ECHOLNPGM("CachedScreen::storeBackground() failed: not enough DL cache space"); | ||||
|         return false; | ||||
|       } | ||||
|       return true; | ||||
|     } | ||||
| 
 | ||||
|     static void repaintBackground(){ | ||||
|       using namespace FTDI; | ||||
|       DLCache dlcache(DL_SLOT); | ||||
|       CLCD::CommandFifo cmd; | ||||
| 
 | ||||
|       cmd.cmd(CMD_DLSTART); | ||||
|       current_screen.onRedraw(BACKGROUND); | ||||
| 
 | ||||
|       dlcache.store(DL_SIZE); | ||||
|     } | ||||
| 
 | ||||
|   public: | ||||
|     static void onRefresh(){ | ||||
|       using namespace FTDI; | ||||
|       DLCache dlcache(DL_SLOT); | ||||
|       CLCD::CommandFifo cmd; | ||||
| 
 | ||||
|       cmd.cmd(CMD_DLSTART); | ||||
| 
 | ||||
|       if (dlcache.has_data()) { | ||||
|         dlcache.append(); | ||||
|       } else { | ||||
|         current_screen.onRedraw(BACKGROUND); | ||||
|         dlcache.store(DL_SIZE); | ||||
|       } | ||||
| 
 | ||||
|       current_screen.onRedraw(FOREGROUND); | ||||
| 
 | ||||
|       cmd.cmd(DL::DL_DISPLAY); | ||||
|       cmd.cmd(CMD_SWAP); | ||||
|       cmd.execute(); | ||||
|     } | ||||
| }; | ||||
| @ -0,0 +1,38 @@ | ||||
| /****************
 | ||||
|  * sound_list.h * | ||||
|  ****************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| class SoundList { | ||||
|   private: | ||||
|     static PROGMEM const struct list_t { | ||||
|       const char *const PROGMEM name; | ||||
|       const FTDI::SoundPlayer::sound_t* data; | ||||
|     } list[]; | ||||
|   public: | ||||
|     static const uint8_t n; | ||||
|     static inline const char* name(uint8_t val) { | ||||
|       return (const char* ) pgm_read_ptr_near(&list[val].name); | ||||
|     } | ||||
|     static inline FTDI::SoundPlayer::sound_t* data(uint8_t val) { | ||||
|       return (FTDI::SoundPlayer::sound_t*) pgm_read_ptr_near(&list[val].data); | ||||
|     } | ||||
| }; | ||||
| @ -0,0 +1,111 @@ | ||||
| /********************
 | ||||
|  * sound_player.cpp * | ||||
|  ********************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #include "ftdi_extended.h" | ||||
| 
 | ||||
| #ifdef FTDI_EXTENDED | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   SoundPlayer sound; // Global sound player object
 | ||||
| 
 | ||||
|   void SoundPlayer::set_volume(uint8_t vol) { | ||||
|     CLCD::mem_write_8(REG::VOL_SOUND, vol); | ||||
|   } | ||||
| 
 | ||||
|   uint8_t SoundPlayer::get_volume() { | ||||
|     return CLCD::mem_read_8(REG::VOL_SOUND); | ||||
|   } | ||||
| 
 | ||||
|   void SoundPlayer::play(effect_t effect, note_t note) { | ||||
| 
 | ||||
|     #ifdef UI_FRAMEWORK_DEBUG | ||||
|       SERIAL_ECHO_START(); | ||||
|       SERIAL_ECHOPAIR("Playing note ", note); | ||||
|       SERIAL_ECHOLNPAIR(", instrument ", effect); | ||||
|     #endif | ||||
| 
 | ||||
|     // Play the note
 | ||||
|     CLCD::mem_write_16(REG::SOUND, (note == REST) ? 0 : (((note ? note : NOTE_C4) << 8) | effect)); | ||||
|     CLCD::mem_write_8(REG::PLAY, 1); | ||||
|   } | ||||
| 
 | ||||
|   note_t SoundPlayer::frequency_to_midi_note(const uint16_t frequency_hz) { | ||||
|     const float f0 = 440; | ||||
|     return note_t(NOTE_A4 + (log(frequency_hz)-log(f0))*12/log(2) + 0.5); | ||||
|   } | ||||
| 
 | ||||
|   // Plays a tone of a given frequency and duration. Since the FTDI FT810 only
 | ||||
|   // supports MIDI notes, we round down to the nearest note.
 | ||||
| 
 | ||||
|   void SoundPlayer::play_tone(const uint16_t frequency_hz, const uint16_t duration_ms) { | ||||
|     play(ORGAN, frequency_to_midi_note(frequency_hz)); | ||||
| 
 | ||||
|     // Schedule silence to squelch the note after the duration expires.
 | ||||
|     sequence = silence; | ||||
|     wait = duration_ms; | ||||
|     timer.start(); | ||||
|   } | ||||
| 
 | ||||
|   void SoundPlayer::play(const sound_t* seq, play_mode_t mode) { | ||||
|     sequence = seq; | ||||
|     wait     = 250; // Adding this delay causes the note to not be clipped, not sure why.
 | ||||
|     timer.start(); | ||||
| 
 | ||||
|     if (mode == PLAY_ASYNCHRONOUS) return; | ||||
| 
 | ||||
|     // If playing synchronously, then play all the notes here
 | ||||
| 
 | ||||
|     while (has_more_notes()) { | ||||
|       onIdle(); | ||||
|       #ifdef EXTENSIBLE_UI | ||||
|         ExtUI::yield(); | ||||
|       #endif | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   bool SoundPlayer::is_sound_playing() { | ||||
|     return CLCD::mem_read_8( REG::PLAY ) & 0x1; | ||||
|   } | ||||
| 
 | ||||
|   void SoundPlayer::onIdle() { | ||||
|     if (!sequence) return; | ||||
| 
 | ||||
|     const bool ready_for_next_note = (wait == 0) ? !is_sound_playing() : timer.elapsed(wait); | ||||
| 
 | ||||
|     if (ready_for_next_note) { | ||||
|       const effect_t fx = effect_t(pgm_read_byte(&sequence->effect)); | ||||
|       const note_t   nt =   note_t(pgm_read_byte(&sequence->note)); | ||||
|       const uint32_t ms = uint32_t(pgm_read_byte(&sequence->sixteenths)) * 1000 / 16; | ||||
| 
 | ||||
|       if (ms == 0 && fx == SILENCE && nt == END_SONG) { | ||||
|         sequence = 0; | ||||
|         play(SILENCE, REST); | ||||
|       } else { | ||||
|         wait = ms; | ||||
|         timer.start(); | ||||
|         play(fx, nt); | ||||
|         sequence++; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } // namespace FTDI
 | ||||
| 
 | ||||
| #endif // FTDI_EXTENDED
 | ||||
| @ -0,0 +1,70 @@ | ||||
| /******************
 | ||||
|  * sound_player.h * | ||||
|  ******************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Mark Pelletier  2017 - Aleph Objects, Inc.                  * | ||||
|  *   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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   typedef enum { | ||||
|     PLAY_ASYNCHRONOUS, | ||||
|     PLAY_SYNCHRONOUS | ||||
|   } play_mode_t; | ||||
| 
 | ||||
|   class SoundPlayer { | ||||
|     typedef FTDI::ftdi_registers  REG; | ||||
|     typedef FTDI::ftdi_memory_map MAP; | ||||
| 
 | ||||
|     public: | ||||
|       struct sound_t { | ||||
|         effect_t  effect;      // The sound effect number
 | ||||
|         note_t    note;        // The MIDI note value
 | ||||
|         uint16_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; | ||||
|       tiny_timer_t     timer; | ||||
|       tiny_time_t      wait; | ||||
| 
 | ||||
|       note_t frequency_to_midi_note(const uint16_t frequency); | ||||
| 
 | ||||
|     public: | ||||
|       static void set_volume(uint8_t volume); | ||||
|       static uint8_t get_volume(); | ||||
| 
 | ||||
|       static void play(effect_t effect, note_t note = NOTE_C4); | ||||
|       static bool is_sound_playing(); | ||||
| 
 | ||||
|       void play(const sound_t* seq, play_mode_t mode = PLAY_SYNCHRONOUS); | ||||
|       void play_tone(const uint16_t frequency_hz, const uint16_t duration_ms); | ||||
|       bool has_more_notes() {return sequence != 0;}; | ||||
| 
 | ||||
|       void onIdle(); | ||||
|   }; | ||||
| 
 | ||||
|   extern SoundPlayer sound; | ||||
| 
 | ||||
|   const PROGMEM SoundPlayer::sound_t silence[] = { | ||||
|     {SILENCE,      END_SONG, 0} | ||||
|   }; | ||||
| } | ||||
| @ -0,0 +1,129 @@ | ||||
| /****************
 | ||||
|  * text_box.cpp * | ||||
|  ****************/ | ||||
| 
 | ||||
| /****************************************************************************
 | ||||
|  *   Written By Marcio Teixeira 2019 - 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: <http://www.gnu.org/licenses/>.                              *
 | ||||
|  ****************************************************************************/ | ||||
| 
 | ||||
| #include "ftdi_extended.h" | ||||
| 
 | ||||
| #ifdef FTDI_EXTENDED | ||||
| 
 | ||||
| namespace FTDI { | ||||
|   /**
 | ||||
|    * Given a str, end will be set to the position at which a line needs to | ||||
|    * be broken so that the display width is less than w. The line will also | ||||
|    * be broken after a '\n'. Returns the display width of the line. | ||||
|    */ | ||||
|   static uint16_t find_line_break(const CLCD::FontMetrics &fm, uint16_t w, const char *str, const char *&end) { | ||||
|     const char *p = str; | ||||
|     end = str + strlen(str); | ||||
|     uint16_t width = fm.get_text_width(str); | ||||
|     for(;;) { | ||||
|       // Find next tentative line break.
 | ||||
|       char delim = *(p); | ||||
|       while (delim && delim != ' ' && delim != '\n') { | ||||
|         delim = *(++p); | ||||
|       } | ||||
|       // Check to see whether to break the line.
 | ||||
|       const uint16_t margin = fm.get_text_width("  "); | ||||
|       const uint16_t lw = p > str ? fm.get_text_width(str, p - str) + margin : 0; | ||||
|       if (lw < w) { | ||||
|         width = lw; | ||||
|         switch (delim) { | ||||
|           case '\0': | ||||
|             end = p; | ||||
|             break; | ||||
|           case '\n': | ||||
|             end = ++p; | ||||
|             break; | ||||
|           case ' ': | ||||
|             end = ++p; | ||||
|             continue; | ||||
|         } | ||||
|       } | ||||
|       return width; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /**
 | ||||
|    * This function returns a measurements of the word-wrapped text box. | ||||
|    */ | ||||
|   static void measure_text_box(const CLCD::FontMetrics &fm, const char *str, uint16_t &width, uint16_t &height) { | ||||
|     const char *line_start = (const char*)str; | ||||
|     const char *line_end; | ||||
|     const uint16_t wrap_width = width; | ||||
|     width = height = 0; | ||||
|     for(;;) { | ||||
|       uint16_t line_width = find_line_break(fm, wrap_width, line_start, line_end); | ||||
|       if (line_end == line_start) break; | ||||
|       width  = max(width, line_width); | ||||
|       height += fm.height; | ||||
|       line_start = line_end; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /**
 | ||||
|    * This function draws text inside a bounding box, doing word wrapping and using the largest font that will fit. | ||||
|    */ | ||||
|   void draw_text_box(CommandProcessor& cmd, int x, int y, int w, int h, const char *str, uint16_t options, uint8_t font) { | ||||
|     CLCD::FontMetrics fm(font); | ||||
| 
 | ||||
|     uint16_t box_width, box_height; | ||||
| 
 | ||||
|     for(;;) { | ||||
|       box_width = w; | ||||
|       measure_text_box(fm, str, box_width, box_height); | ||||
|       if (box_width <= (uint16_t)w && box_height <= (uint16_t)h) break; | ||||
|       fm.load(--font); | ||||
|       if (font == 26) break; | ||||
|     } | ||||
| 
 | ||||
|     const uint16_t dx = (options & OPT_RIGHTX) ? w : (options & OPT_CENTERX) ? w/2 : 0; | ||||
|     const uint16_t dy = (options & OPT_CENTERY) ? (h - box_height)/2 : 0; | ||||
| 
 | ||||
|     const char *line_start = str; | ||||
|     const char *line_end; | ||||
|     for(;;) { | ||||
|       find_line_break(fm, w, line_start, line_end); | ||||
|       if (line_end == line_start) break; | ||||
| 
 | ||||
|       const size_t line_len = line_end - line_start; | ||||
|       if (line_len) { | ||||
|         char line[line_len + 1]; | ||||
|         strncpy(line, line_start, line_len); | ||||
|         line[line_len] = 0; | ||||
|         if (line[line_len - 1] == '\n' || line[line_len - 1] == ' ') | ||||
|           line[line_len - 1] = 0; | ||||
| 
 | ||||
|         cmd.CLCD::CommandFifo::text(x + dx, y + dy, font, options & ~OPT_CENTERY); | ||||
|         cmd.CLCD::CommandFifo::str(line); | ||||
|       } | ||||
|       y += fm.height; | ||||
| 
 | ||||
|       line_start = line_end; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   void draw_text_box(CommandProcessor& cmd, int x, int y, int w, int h, progmem_str pstr, uint16_t options, uint8_t font) { | ||||
|     char str[strlen_P((const char*)pstr) + 1]; | ||||
|     strcpy_P(str, (const char*)pstr); | ||||
|     draw_text_box(cmd, x, y, w, h, (const char*) str, options, font); | ||||
|   } | ||||
| } // namespace FTDI
 | ||||
| 
 | ||||
| #endif // FTDI_EXTENDED
 | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user