Add LULZBOT_TOUCH_UI (#14967)

2.0.x
Marcio Teixeira 5 years ago committed by Scott Lahteine
parent 179d6c4ed1
commit 274934ad81

@ -2033,6 +2033,12 @@
// //
//#define MALYAN_LCD //#define MALYAN_LCD
//
// LulzBot Color Touch UI for FTDI EVE (FT800/FT810) displays
// See Configuration_adv.h for all configuration options.
//
//#defined LULZBOT_TOUCH_UI
// //
// Third-party or vendor-customized controller interfaces. // Third-party or vendor-customized controller interfaces.
// Sources should be installed in 'src/lcd/extensible_ui'. // Sources should be installed in 'src/lcd/extensible_ui'.

@ -1143,6 +1143,53 @@
#endif // HAS_GRAPHICAL_LCD #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 // @section safety
/** /**

@ -169,7 +169,7 @@
* heuristics and inline the function no matter how big it thinks it * heuristics and inline the function no matter how big it thinks it
* becomes. * becomes.
*/ */
#if defined(__CC_ARM) #ifdef __CC_ARM
# define __always_inline __forceinline # define __always_inline __forceinline
#elif (defined __GNUC__) #elif (defined __GNUC__)
#ifdef __always_inline #ifdef __always_inline
@ -187,7 +187,7 @@
* This annotation instructs the compiler to ignore its inlining * This annotation instructs the compiler to ignore its inlining
* heuristics and not inline the function. * heuristics and not inline the function.
*/ */
#if defined(__CC_ARM) #ifdef __CC_ARM
# define __no_inline __attribute__((noinline)) # define __no_inline __attribute__((noinline))
#elif (defined __GNUC__) #elif (defined __GNUC__)
# define __no_inline __attribute__((__noinline__)) # define __no_inline __attribute__((__noinline__))
@ -204,7 +204,7 @@
* *
* \param expr Expression to evaluate and supposed to be nonzero. * \param expr Expression to evaluate and supposed to be nonzero.
*/ */
#if defined(_ASSERT_ENABLE_) #ifdef _ASSERT_ENABLE_
# if defined(TEST_SUITE_DEFINE_ASSERT_MACRO) # if defined(TEST_SUITE_DEFINE_ASSERT_MACRO)
// Assert() is defined in unit_test/suite.h // Assert() is defined in unit_test/suite.h
# include "unit_test/suite.h" # include "unit_test/suite.h"
@ -998,14 +998,14 @@ typedef U8 Byte; //!< 8-bit unsigned integer.
#endif // #ifndef __ASSEMBLY__ #endif // #ifndef __ASSEMBLY__
#if defined(__ICCARM__) #ifdef __ICCARM__
#define SHORTENUM __packed #define SHORTENUM __packed
#elif defined(__GNUC__) #elif defined(__GNUC__)
#define SHORTENUM __attribute__((packed)) #define SHORTENUM __attribute__((packed))
#endif #endif
/* No operation */ /* No operation */
#if defined(__ICCARM__) #ifdef __ICCARM__
#define nop() __no_operation() #define nop() __no_operation()
#elif defined(__GNUC__) #elif defined(__GNUC__)
#define nop() (__NOP()) #define nop() (__NOP())

@ -368,7 +368,7 @@
#endif #endif
// Extensible UI serial touch screens. (See src/lcd/extensible_ui) // 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 IS_EXTUI
#define EXTENSIBLE_UI #define EXTENSIBLE_UI
#endif #endif

@ -99,3 +99,6 @@
#define LED_USER_PRESET_BRIGHTNESS 255 #define LED_USER_PRESET_BRIGHTNESS 255
#endif #endif
#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)

@ -1892,6 +1892,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
+ ENABLED(OVERLORD_OLED) \ + ENABLED(OVERLORD_OLED) \
+ ENABLED(DGUS_LCD) \ + ENABLED(DGUS_LCD) \
+ ENABLED(MALYAN_LCD) \ + ENABLED(MALYAN_LCD) \
+ ENABLED(LULZBOT_TOUCH_UI) \
+ ENABLED(FSMC_GRAPHICAL_TFT) + ENABLED(FSMC_GRAPHICAL_TFT)
#error "Please select no more than one LCD controller option." #error "Please select no more than one LCD controller option."
#endif #endif

@ -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,110 @@
/*******************
* 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/>. *
****************************************************************************/
#ifdef LULZBOT_TOUCH_UI
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);
};
#endif // LULZBOT_TOUCH_UI

@ -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,44 @@
/**********************
* 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 "../../../../../sd/SdFile.h"
#include "../../../../../sd/cardreader.h"
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);
};

@ -0,0 +1,61 @@
/************
* 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__
// If __MARLIN_FIRMWARE__ exists, then we are being
// compiled inside Marlin.
#include "pin_mappings.h"
#else
// Messages that are declared in Marlin
#define WELCOME_MSG "Printer Ready"
#define MSG_SD_INSERTED "Media Inserted"
#define MSG_SD_REMOVED "Media Removed"
// Define macros for compatibility
#define EXTENSIBLE_UI
#define _CAT(a, ...) a ## __VA_ARGS__
#define SWITCH_ENABLED_ 1
#define ENABLED(b) _CAT(SWITCH_ENABLED_, b)
#define DISABLED(b) !ENABLED(b)
namespace UI {
static inline uint32_t safe_millis() {return millis();};
static inline void yield() {};
};
#endif
class __FlashStringHelper;
typedef const __FlashStringHelper *progmem_str;

@ -0,0 +1,98 @@
/************
* 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
// Define number of seconds after which the menu screens
// timeout and returns the user to the status screen
//#define LCD_TIMEOUT_TO_STATUS 120
// 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

@ -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);
}
}

@ -0,0 +1,211 @@
/****************************************************************************
* 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
#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
// 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 //!defined(__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

@ -0,0 +1,30 @@
/**************
* text_box.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
/**
* This function draws text inside a bounding box, doing word wrapping and using the largest font that will fit.
*/
namespace FTDI {
void draw_text_box(class CommandProcessor& cmd, int x, int y, int w, int h, progmem_str str, uint16_t options = 0, uint8_t font = 31);
void draw_text_box(class CommandProcessor& cmd, int x, int y, int w, int h, const char *str, uint16_t options = 0, uint8_t font = 31);
}

@ -0,0 +1,51 @@
/******************
* tiny_timer.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
bool tiny_timer_t::elapsed(tiny_time_t duration) {
uint8_t now = tiny_time_t::tiny_time(
#ifdef __MARLIN_FIRMWARE__
ExtUI::safe_millis()
#else
millis()
#endif
);
uint8_t elapsed = now - _start;
if (elapsed >= duration._duration) {
return true;
} else {
return false;
}
}
void tiny_timer_t::start() {
_start = tiny_time_t::tiny_time(
#ifdef __MARLIN_FIRMWARE__
ExtUI::safe_millis()
#else
millis()
#endif
);
}
#endif // FTDI_EXTENDED

@ -0,0 +1,56 @@
/****************
* tiny_timer.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
/* Helpful Reference:
*
* https://arduino.stackexchange.com/questions/12587/how-can-i-handle-the-millis-rollover
*/
/* tiny_interval_t downsamples a 32-bit millis() value
into a 8-bit value which can record periods of
a few seconds with a rougly 1/16th of second
resolution. This allows us to measure small
intervals without needing to use four-byte counters.
*/
class tiny_time_t {
private:
friend class tiny_timer_t;
uint8_t _duration;
static uint8_t tiny_time(uint32_t ms) {return ceil(float(ms) / 64);};
public:
tiny_time_t() : _duration(0) {}
tiny_time_t(uint32_t ms) : _duration(tiny_time(ms)) {}
tiny_time_t & operator= (uint32_t ms) {_duration = tiny_time(ms); return *this;}
bool operator == (uint32_t ms) {return _duration == tiny_time(ms);}
};
class tiny_timer_t {
private:
uint8_t _start;
public:
void start();
bool elapsed(tiny_time_t interval);
};

@ -0,0 +1,100 @@
/***********************
* circular_progress.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
/* This function draws a circular progress "ring" */
void draw_circular_progress(CommandProcessor& cmd, int x, int y, int w, int h, uint8_t percent, uint32_t bgcolor, uint32_t fgcolor, float rim = 0.3) {
using namespace FTDI;
const float a = float(percent)/100.0*2.0*PI;
const float a1 = min(PI/2, a);
const float a2 = min(PI/2, a-a1);
const float a3 = min(PI/2, a-a1-a2);
const float a4 = min(PI/2, a-a1-a2-a3);
const int ro = min(w,h) * 8;
const int rr = ro * rim;
const int cx = x * 16 + w * 8;
const int cy = y * 16 + h * 8;
// Load a rim shape into stencil buffer
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));
cmd.cmd(BEGIN(POINTS));
cmd.cmd(POINT_SIZE(ro));
cmd.cmd(VERTEX2F(cx, cy));
cmd.cmd(POINT_SIZE(ro - rr));
cmd.cmd(VERTEX2F(cx, cy));
cmd.cmd(RESTORE_CONTEXT());
// Mask further drawing by stencil buffer
cmd.cmd(SAVE_CONTEXT());
cmd.cmd(STENCIL_FUNC(STENCIL_FUNC_NOTEQUAL, 0, 255));
// Fill the background
cmd.cmd(COLOR_RGB(bgcolor));
cmd.cmd(BEGIN(POINTS));
cmd.cmd(POINT_SIZE(ro));
cmd.cmd(VERTEX2F(cx, cy));
cmd.cmd(COLOR_RGB(fgcolor));
// Paint upper-right quadrant
cmd.cmd(BEGIN(EDGE_STRIP_A));
cmd.cmd(VERTEX2F(cx, cy));
cmd.cmd(VERTEX2F(cx + ro*sin(a1) + 16,cy - ro*cos(a1) + 8));
// Paint lower-right quadrant
if (a > PI/2) {
cmd.cmd(BEGIN(EDGE_STRIP_R));
cmd.cmd(VERTEX2F(cx, cy));
cmd.cmd(VERTEX2F(cx + ro*cos(a2),cy + ro*sin(a2) + 16));
}
// Paint lower-left quadrant
if (a > PI) {
cmd.cmd(BEGIN(EDGE_STRIP_B));
cmd.cmd(VERTEX2F(cx, cy));
cmd.cmd(VERTEX2F(cx - ro*sin(a3) - 8,cy + ro*cos(a3)));
}
// Paint upper-left quadrant
if (a > 1.5*PI) {
cmd.cmd(BEGIN(EDGE_STRIP_L));
cmd.cmd(VERTEX2F(cx, cy));
cmd.cmd(VERTEX2F(cx - ro*cos(a4),cy - ro*sin(a4)));
}
cmd.cmd(RESTORE_CONTEXT());
// Draw the text
char str[5];
sprintf(str,"%d\%%",percent);
cmd.cmd(SAVE_CONTEXT());
cmd.cmd(COLOR_RGB(fgcolor));
cmd.text(x,y,w,h,str, OPT_CENTERX | OPT_CENTERY);
cmd.cmd(RESTORE_CONTEXT());
}

@ -0,0 +1,395 @@
/*************
* poly_ui.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 PolyReader class iterates over an array of (x,y) pairs.
* For supporting polygons with holes an end-of-loop marker may
* be embedded into the data stream:
*
* const PROGMEM uint16_t data[] = {
* x, y, x, y, ..., eol,
* ...
* x, y, x, y, ..., eol
* }
*
* The PolyReader object can be used to iterate over the points.
*
* PolyReader r(data, N_ELEMENTS(data));
*
* for(r.start();r.has_more(); r.next()) {
* uint16_t x = r.x;
* uint16_t y = r.y;
*
* // Do something with the point
* ...
*
* // Do something else if this point
* // closes a loop.
* if (r.end_of_loop()) {
* ...
* }
* }
*
*/
class PolyReader {
private:
typedef uint16_t type_t;
static constexpr type_t eol = 0xFFFF;
const type_t *p, *top, *end;
type_t start_x, start_y;
void close_loop() {
x = start_x;
y = start_y;
start_x = eol;
start_y = eol;
}
public:
type_t x, y;
// Begin reading a polygon data structure
PolyReader(const uint16_t data[], const size_t n_elements) : top(data), end(data + n_elements) {
start();
}
void start() {
p = top;
start_x = eol;
next();
}
// Reads the next point in the polygon data structure
void next() {
if (!p) return;
if (p == end) {
if (start_x != eol)
close_loop();
else
p = NULL;
} else {
x = pgm_read_word_far(p++);
if (x == eol)
close_loop();
else {
y = pgm_read_word_far(p++);
if (start_x == eol) {
start_x = x;
start_y = y;
}
}
}
}
bool has_more() {return p != NULL;}
bool end_of_loop() {return start_x == eol;}
};
/**
* The TransformedPolyReader class works like the PolyReader,
* but the (x,y) input is assumed to be normalized onto a
* unit square and then mapped to the full 16-bits, i.e.
* (0.0,1.0) => (0x0000,0xFFFE). This class will scale the
* data to fit the entire display, a bounding box, or apply
* some arbitrary affine transform.
*
* This class is suitable for reading data from "svg2cpp.py"
*/
class TransformedPolyReader : public PolyReader {
private:
/**
* Fixed point type for fast transformations, supports
* values from 0 to 1024, with 1/32 precision.
*/
static constexpr uint8_t fract_bits = 5;
typedef int16_t fix_t;
fix_t makefix(float f) {return f * (1 << fract_bits);}
// First two rows of 3x3 transformation matrix
fix_t a, b, c;
fix_t d, e, f;
void transform() {
/**
* Values from PolyReader vary from 0 to FFFE.
* As an approximation to dividing by FFFE,
* we perform a bit shift right by 16.
*/
const int32_t px = PolyReader::x;
const int32_t py = PolyReader::y;
const int32_t round = 1 << (fract_bits-1);
x = (((((a * px) + (b * py)) >> 16) + c) + round) >> fract_bits;
y = (((((d * px) + (e * py)) >> 16) + f) + round) >> fract_bits;
}
void set_transform(
fix_t A, fix_t B, fix_t C,
fix_t D, fix_t E, fix_t F
) {
a = A; b = B; c = C;
d = D; e = E; f = F;
}
public:
typedef int16_t type_t;
type_t x, y;
TransformedPolyReader(const uint16_t data[], const size_t n) : PolyReader(data, n) {
scale_to_fit();
transform();
}
// Set an arbitrary affine transform
void set_transform(
float A, float B, float C,
float D, float E, float F
) {
set_transform(
makefix(A), makefix(B), makefix(C),
makefix(D), makefix(E), makefix(F)
);
}
// Scale the data to fit a specified bounding box
void scale_to_fit(type_t x_min, type_t y_min, type_t x_max, type_t y_max) {
fix_t sx = makefix(x_max - x_min);
fix_t sy = makefix(y_max - y_min);
fix_t tx = makefix(x_min);
fix_t ty = makefix(y_min);
set_transform(
sx, 0, tx,
0, sy, ty
);
}
// Scale to fit the entire display (default)
void scale_to_fit() {
scale_to_fit(0, 0, FTDI::display_width, FTDI::display_height);
}
void next() {
PolyReader::next();
transform();
}
};
/**
* The DeduplicatedPolyReader wraps around another PolyReader
* class to remove repeated points from the data. This could
* happen when scaling down using TransformedPolyReader, for
* example.
*/
template<class POLY_READER>
class DeduplicatedPolyReader : public POLY_READER {
private:
typename POLY_READER::type_t last_x, last_y;
static constexpr typename POLY_READER::type_t eol = 0xFFFF;
public:
DeduplicatedPolyReader(const uint16_t data[], const size_t n) : POLY_READER(data, n) {
last_x = POLY_READER::x;
last_y = POLY_READER::y;
}
void next() {
do {
if (!POLY_READER::has_more()) return;
POLY_READER::next();
} while (POLY_READER::x == last_x && POLY_READER::y == last_y && !POLY_READER::end_of_loop());
if (POLY_READER::end_of_loop()) {
last_x = last_y = eol;
} else {
last_x = POLY_READER::x;
last_y = POLY_READER::y;
}
}
};
/**
* The helper class allows you to build an interface based on arbitrary
* shapes.
*/
template<class POLY_READER=DeduplicatedPolyReader<TransformedPolyReader>>
class GenericPolyUI {
private:
CommandProcessor &cmd;
// Attributes used to paint buttons
uint32_t btn_fill_color = 0x000000;
uint32_t btn_shadow_color = 0xF3E0E0;
uint8_t btn_shadow_depth = 5;
uint32_t btn_stroke_color = 0x000000;
uint8_t btn_stroke_width = 28;
draw_mode_t mode;
public:
typedef POLY_READER poly_reader_t;
GenericPolyUI(CommandProcessor &c, draw_mode_t what = BOTH) : cmd(c), mode(what) {}
// Fills a polygon with the current COLOR_RGB
void fill(poly_reader_t r, bool clip = true) {
using namespace FTDI;
int16_t x, y, w, h;
if (clip) {
// Clipping reduces the number of pixels that are
// filled, allowing more complex shapes to be drawn
// in the alloted time.
bounds(r, x, y, w, h);
cmd.cmd(SAVE_CONTEXT());
cmd.cmd(SCISSOR_XY(x, y));
cmd.cmd(SCISSOR_SIZE(w, h));
}
Polygon p(cmd);
p.begin_fill();
p.begin_loop();
for(r.start();r.has_more();r.next()) {
p(r.x * 16, r.y * 16);
if (r.end_of_loop()) {
p.end_loop();
p.begin_loop();
}
}
p.end_loop();
p.end_fill();
if (clip)
cmd.cmd(RESTORE_CONTEXT());
}
void shadow(poly_reader_t r, uint8_t offset) {
#if FTDI_API_LEVEL >= 810
using namespace FTDI;
cmd.cmd(VERTEX_TRANSLATE_X(offset * 16));
cmd.cmd(VERTEX_TRANSLATE_Y(offset * 16));
fill(r, false);
cmd.cmd(VERTEX_TRANSLATE_X(0));
cmd.cmd(VERTEX_TRANSLATE_Y(0));
#endif
}
// Strokes a polygon with the current COLOR_RGB
void stroke(poly_reader_t r) {
using namespace FTDI;
Polygon p(cmd);
p.begin_stroke();
p.begin_loop();
for(r.start();r.has_more(); r.next()) {
p(r.x * 16, r.y * 16);
if (r.end_of_loop()) {
p.end_loop();
p.begin_loop();
}
}
p.end_loop();
p.end_stroke();
}
// Compute the bounds of a polygon
void bounds(poly_reader_t r, int16_t &x, int16_t &y, int16_t &w, int16_t &h) {
int16_t x_min = INT16_MAX;
int16_t y_min = INT16_MAX;
int16_t x_max = INT16_MIN;
int16_t y_max = INT16_MIN;
for(r.start(); r.has_more(); r.next()) {
x_min = min(x_min, r.x);
x_max = max(x_max, r.x);
y_min = min(y_min, r.y);
y_max = max(y_max, r.y);
}
x = x_min;
y = y_min;
w = x_max - x_min;
h = y_max - y_min;
}
/**
* Draw shaped buttons. Buttons are drawn out of a polygon which is
* filled and stroked on top of a drop shadow. The button will
* become "pushed" when touched.
*/
void button_fill(const uint32_t color) {
btn_fill_color = color;
}
void button_stroke(const uint32_t color, const uint8_t width) {
btn_stroke_color = color;
btn_stroke_width = width;
}
void button_shadow(const uint32_t color, const uint8_t depth) {
btn_shadow_color = color;
btn_shadow_depth = depth;
}
void button(const uint8_t tag, poly_reader_t r) {
using namespace FTDI;
// Draw the shadow
#if FTDI_API_LEVEL >= 810
if (mode & BACKGROUND) {
cmd.cmd(SAVE_CONTEXT());
cmd.cmd(TAG(tag));
cmd.cmd(VERTEX_TRANSLATE_X(btn_shadow_depth * 16));
cmd.cmd(VERTEX_TRANSLATE_Y(btn_shadow_depth * 16));
cmd.cmd(COLOR_RGB(btn_shadow_color));
fill(r, false);
cmd.cmd(RESTORE_CONTEXT());
}
#endif
if (mode & FOREGROUND) {
cmd.cmd(SAVE_CONTEXT());
#if FTDI_API_LEVEL >= 810
if (EventLoop::get_pressed_tag() == tag) {
// "Push" the button
cmd.cmd(VERTEX_TRANSLATE_X(btn_shadow_depth * 16));
cmd.cmd(VERTEX_TRANSLATE_Y(btn_shadow_depth * 16));
}
#endif
// Draw the fill and stroke
cmd.cmd(TAG(tag));
cmd.cmd(COLOR_RGB(btn_fill_color));
fill(r, false);
cmd.cmd(COLOR_RGB(btn_stroke_color));
cmd.cmd(LINE_WIDTH(btn_stroke_width));
stroke(r);
cmd.cmd(RESTORE_CONTEXT());
}
}
void color(const uint32_t color) {
cmd.cmd(FTDI::COLOR_RGB(color));
}
};
typedef GenericPolyUI<> PolyUI;

@ -0,0 +1,278 @@
#!/usr/bin/python
# 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/>.
from __future__ import print_function
import argparse, re, sys
usage = '''
This program extracts line segments from a SVG file and writes
them as coordinates in a C array. The x and y values will be
scaled from 0x0000 to 0xFFFE. 0xFFFF is used as path separator.
This program can only interpret straight segments, not curves.
It also cannot handle SVG transform attributes. To convert an
SVG file into the proper format, use the following procedure:
- Load SVG file into Inkscape
- Convert all Objects to Paths (Path -> Object to Path)
- Convert all Strokes to Paths (Path -> Stroke to Path)
- Combine all paths into one (Path -> Combine) [1]
- Convert all curves into short line segments
(Extensions -> Modify Paths -> Flatten Beziers...)
- Save as new SVG
- Convert into a header file using this utility
- To give paths individual names, break apart paths and
use the XML Editor to set the "id" attributes.
[1] Combining paths is necessary to remove transforms. You
could also use inkscape-applytransforms Inkscape extension.
'''
header = '''
/****************************************************************************
* 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 file was auto-generated using "svg2cpp.pl"
*
* The encoding consists of x,y pairs with the min and max scaled to
* 0x0000 and 0xFFFE. A single 0xFFFF in the data stream indicates the
* start of a new closed path.
*/
#pragma once
'''
class ComputeBoundingBox:
def reset(self):
self.x_min = float(" inf")
self.y_min = float(" inf")
self.x_max = float("-inf")
self.y_max = float("-inf")
self.n_points = 0
self.n_paths = 0
def command(self, type, x, y):
self.x_min = min(self.x_min, x)
self.x_max = max(self.x_max, x)
self.y_min = min(self.y_min, y)
self.y_max = max(self.y_max, y)
if type == "M":
self.n_paths += 1
self.n_points += 1
def scale(self, x, y):
x -= self.x_min
y -= self.y_min
x /= self.x_max - self.x_min
y /= self.y_max - self.y_min
#y = 1 - y # Flip upside down
return (x, y)
def path_finished(self, id):
pass
def write(self):
print("constexpr float x_min = %f;\n" % self.x_min)
print("constexpr float x_max = %f;\n" % self.x_max)
print("constexpr float y_min = %f;\n" % self.y_min)
print("constexpr float y_max = %f;\n" % self.y_max)
def from_svg_view_box(self, svg):
s = re.search('<svg[^>]+>', svg);
if s:
m = re.search('viewBox="([0-9-.]+) ([0-9-.]+) ([0-9-.]+) ([0-9-.]+)"', svg)
if m:
self.x_min = float(m.group(1))
self.y_min = float(m.group(2))
self.x_max = float(m.group(3))
self.y_max = float(m.group(4))
return True
return False
class WriteDataStructure:
def __init__(self, bounding_box):
self.bounds = bounding_box
def reset(self, ):
self.hex_words = []
def push(self, value):
self.hex_words.append("0x%04X" % value)
def command(self, type, x, y):
if type == "M":
self.push(0xFFFF)
x, y = self.bounds.scale(x,y)
self.push(x * 0xFFFE)
self.push(y * 0xFFFE)
def path_finished(self, id):
if self.hex_words and self.hex_words[0] == "0xFFFF":
self.hex_words.pop(0)
print("const PROGMEM uint16_t", id + "[] = {" + ", ".join (self.hex_words) + "};\n")
self.hex_words = []
class Parser:
def __init__(self, op):
self.op = op
self.reset()
def reset(self):
self.last_x = 0
self.last_y = 0
self.initial_x = 0
self.initial_y = 0
def process_svg_path_L_or_M(self, cmd, x, y):
self.op.command(cmd, x, y)
self.last_x = x
self.last_y = y
if cmd == "M":
self.initial_x = x
self.initial_y = y
def process_svg_path_data_cmd(self, id, cmd, a, b):
"""Converts the various types of moves into L or M commands
and dispatches to process_svg_path_L_or_M for futher processing."""
if cmd == "Z" or cmd == "z":
self.process_svg_path_L_or_M("L", self.initial_x, self.initial_y)
elif cmd == "H":
self.process_svg_path_L_or_M("L", a, self.last_y)
elif cmd == "V":
self.process_svg_path_L_or_M("L", self.last_x, a)
elif cmd == "h":
self.process_svg_path_L_or_M("L", self.last_x + a, self.last_y)
elif cmd == "v":
self.process_svg_path_L_or_M("L", self.last_x, self.last_y + a)
elif cmd == "L":
self.process_svg_path_L_or_M("L", a, b)
elif cmd == "l":
self.process_svg_path_L_or_M("L", self.last_x + a, self.last_y + b)
elif cmd == "M":
self.process_svg_path_L_or_M("M", a, b)
elif cmd == "m":
self.process_svg_path_L_or_M("M", self.last_x + a, self.last_y + b)
else:
print("Unsupported path data command:", cmd, "in path", id, "\n", file=sys.stderr)
quit()
def eat_token(self, regex):
"""Looks for a token at the start of self.d.
If found, the token is removed."""
self.m = re.match(regex,self.d)
if self.m:
self.d = self.d[self.m.end():]
return self.m
def process_svg_path_data(self, id, d):
"""Breaks up the "d" attribute into individual commands
and calls "process_svg_path_data_cmd" for each"""
self.d = d
while (self.d):
if self.eat_token('\s+'):
pass # Just eat the spaces
elif self.eat_token('([LMHVZlmhvz])'):
cmd = self.m.group(1)
# The following commands take no arguments
if cmd == "Z" or cmd == "z":
self.process_svg_path_data_cmd(id, cmd, 0, 0)
elif self.eat_token('([CScsQqTtAa])'):
print("Unsupported path data command:", self.m.group(1), "in path", id, "\n", file=sys.stderr)
quit()
elif self.eat_token('([ ,]*[-0-9e.]+)+'):
# Process list of coordinates following command
coords = re.split('[ ,]+', self.m.group(0))
# The following commands take two arguments
if cmd == "L" or cmd == "l":
while coords:
self.process_svg_path_data_cmd(id, cmd, float(coords.pop(0)), float(coords.pop(0)))
elif cmd == "M":
while coords:
self.process_svg_path_data_cmd(id, cmd, float(coords.pop(0)), float(coords.pop(0)))
# If a MOVETO has multiple points, the subsequent ones are assumed to be LINETO
cmd = "L"
elif cmd == "m":
while coords:
self.process_svg_path_data_cmd(id, cmd, float(coords.pop(0)), float(coords.pop(0)))
# If a MOVETO has multiple points, the subsequent ones are assumed to be LINETO
cmd = "l"
# Assume all other commands are single argument
else:
while coords:
self.process_svg_path_data_cmd(id, cmd, float(coords.pop(0)), 0)
else:
print("Syntax error:", d, "in path", id, "\n", file=sys.stderr)
quit()
def process_svg_paths(self, svg):
self.op.reset()
for path in re.findall('<path[^>]+>', svg):
id = "<none>"
m = re.search(' id="(.*)"', path)
if m:
id = m.group(1)
m = re.search(' transform="(.*)"', path)
if m:
print("Found transform in path", id, "! Cannot process file!", file=sys.stderr)
quit()
m = re.search(' d="(.*)"', path)
if m:
self.process_svg_path_data(id, m.group(1))
self.op.path_finished(id)
self.reset()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("filename")
args = parser.parse_args()
f = open(args.filename, "r")
data = f.read()
print(header)
b = ComputeBoundingBox()
if not b.from_svg_view_box(data):
# Can't find the view box, so use the bounding box of the elements themselves.
p = Parser(b)
p.process_svg_paths(data)
b.write()
w = WriteDataStructure(b)
p = Parser(w)
p.process_svg_paths(data)

@ -0,0 +1,27 @@
/******************
* ftdi_eve_lib.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"
#include "basic/ftdi_basic.h"
#include "extended/ftdi_extended.h"

@ -0,0 +1,128 @@
/*********************
* marlin_events.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 "screens/screens.h"
namespace ExtUI {
using namespace Theme;
using namespace FTDI;
void onStartup() {
EventLoop::setup();
}
void onIdle() {
EventLoop::loop();
}
void onPrinterKilled(PGM_P lcd_msg) {
KillScreen::show(progmem_str(lcd_msg));
}
void onMediaInserted() {
if (AT_SCREEN(StatusScreen))
StatusScreen::setStatusMessage(F(MSG_MEDIA_INSERTED));
sound.play(media_inserted, PLAY_ASYNCHRONOUS);
}
void onMediaRemoved() {
if (AT_SCREEN(StatusScreen))
StatusScreen::setStatusMessage(F(MSG_MEDIA_REMOVED));
sound.play(media_removed, PLAY_ASYNCHRONOUS);
if (AT_SCREEN(FilesScreen)) {
GOTO_SCREEN(StatusScreen)
}
}
void onMediaError() {
sound.play(sad_trombone, PLAY_ASYNCHRONOUS);
AlertDialogBox::showError(F("Unable to read media."));
}
void onStatusChanged(const char* lcd_msg) {
StatusScreen::setStatusMessage(lcd_msg);
}
void onStatusChanged(progmem_str lcd_msg) {
StatusScreen::setStatusMessage(lcd_msg);
}
void onPrintTimerStarted() {
InterfaceSoundsScreen::playEventSound(InterfaceSoundsScreen::PRINTING_STARTED);
}
void onPrintTimerStopped() {
InterfaceSoundsScreen::playEventSound(InterfaceSoundsScreen::PRINTING_FINISHED);
}
void onPrintTimerPaused() {
}
void onFilamentRunout(const extruder_t extruder) {
char lcd_msg[30];
sprintf_P(lcd_msg, PSTR("Extruder %d Filament Error"), extruder + 1);
StatusScreen::setStatusMessage(lcd_msg);
InterfaceSoundsScreen::playEventSound(InterfaceSoundsScreen::PRINTING_FAILED);
}
void onFactoryReset() {
InterfaceSettingsScreen::defaultSettings();
}
void onStoreSettings(char *buff) {
InterfaceSettingsScreen::saveSettings(buff);
}
void onLoadSettings(const char *buff) {
InterfaceSettingsScreen::loadSettings(buff);
}
void onConfigurationStoreWritten(bool success) {
#ifdef LULZBOT_EEPROM_BACKUP_SIZE
if (success && InterfaceSettingsScreen::backupEEPROM()) {
SERIAL_ECHOLNPGM("Made backup of EEPROM to SPI Flash");
}
#else
UNUSED(success);
#endif
}
void onConfigurationStoreRead(bool) {
}
void onPlayTone(const uint16_t frequency, const uint16_t duration) {
sound.play_tone(frequency, duration);
}
void onUserConfirmRequired(const char * const msg) {
if (msg)
ConfirmUserRequestAlertBox::show(msg);
else
ConfirmUserRequestAlertBox::hide();
}
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,142 @@
/******************
* pin_mappings.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 file defines mappings from the ULTRA_LCD pins functions to new
* functions for the FTDI display. These mappings allows any board that
* support ULTRA_LCD via EXP1 and EXP2 connectors to use FTDI modules
* without adding new pin definitions to the board.
*/
#ifdef CR10_TFT_PINMAP
#ifndef __MARLIN_FIRMWARE__
#error This pin mapping requires Marlin.
#endif
#define CLCD_USE_SOFT_SPI
#define CLCD_SOFT_SPI_SCLK LCD_PINS_D4 // PORTA1 Pin 6
#define CLCD_SOFT_SPI_MOSI LCD_PINS_ENABLE // PORTC1 Pin 8
#define CLCD_SPI_CS LCD_PINS_RS // PORTA3 Pin 7
#define CLCD_SOFT_SPI_MISO 16 // PORTC0 BTN_ENC Pin 2
#define CLCD_MOD_RESET 11 // PORTD3 BTN_EN1 Pin 3
#define CLCD_AUX_0 10 // PORTD2 BTN_EN2 Pin 5
#define CLCD_AUX_1 BEEPER_PIN // PORTA4 Pin 1
#endif
/**
* The AlephObjects pinout for re-purposing the UltraLCD
* connector EXP1 for software SPI (rev B, obsolete)
*/
#ifdef AO_EXP1_DEPRECATED_PINMAP
#ifndef __MARLIN_FIRMWARE__
#error This pin mapping requires Marlin.
#endif
#define CLCD_MOD_RESET LCD_PINS_D4
#define CLCD_SPI_CS LCD_PINS_D5
#define CLCD_AUX_0 LCD_PINS_ENABLE
#define CLCD_AUX_1 BTN_ENC
#define CLCD_AUX_2 BEEPER_PIN
#define CLCD_USE_SOFT_SPI
#define CLCD_SOFT_SPI_SCLK LCD_PINS_D7
#define CLCD_SOFT_SPI_MOSI LCD_PINS_D6
#define CLCD_SOFT_SPI_MISO LCD_PINS_RS
#endif
/**
* AO_EXP1_PINMAP
*
* The AlephObjects mapping for re-purposing the UltraLCD
* connector EXP1 for software SPI for display (rev C):
*
* EXP2: FTDI: SD -or- USB [1]: ULTRA_LCD:
* 1 MISO MISO MISO --> BEEPER
* 2 SCLK SCLK SCLK --> BTN_ENC
* 3 PD_N - - --> LCDE
* 4 - CS_N CS_N --> LCDRS
* 5 CS_N - - --> LCD4
* 6 MOSI MOSI MOSI --> LCD5
* 7 - SD_DET INT --> LCD6
* 8 RESET - RESET --> LCD4
* 9 GND GND GND --> GND
* 10 5V 5V 5V --> 5V
*
* [1] At the moment, Marlin does not support SD or USB
* functionality over software SPI.
*/
#ifdef AO_EXP1_PINMAP
#ifndef __MARLIN_FIRMWARE__
#error This pin mapping requires Marlin.
#endif
#define CLCD_MOD_RESET LCD_PINS_ENABLE
#define CLCD_SPI_CS LCD_PINS_D4
#define CLCD_USE_SOFT_SPI
#define CLCD_SOFT_SPI_SCLK BTN_ENC
#define CLCD_SOFT_SPI_MOSI LCD_PINS_D5
#define CLCD_SOFT_SPI_MISO BEEPER_PIN
#endif
/**
* AO_EXP2_PINMAP
*
* The AlephObjects mapping for re-purposing the UltraLCD
* connector EXP2 for hardware SPI for display and SD card
* or USB (rev C):
*
* EXP2: FTDI: SD -or- USB: ULTRA_LCD:
* 1 MISO MISO MISO --> MISO
* 2 SCLK SCLK SCLK --> SCLK
* 3 PD_N - - --> BTN_EN2
* 4 - CS_N CS_N --> SD_CSEL
* 5 CS_N - - --> BTN_EN1
* 6 MOSI MOSI MOSI --> MOSI
* 7 - SD_DET INT --> SD_DET
* 8 RESET - RESET --> RESET
* 9 GND GND GND --> GND
* 10 5V 5V 5V --> KILL [3]
*
* [1] This configuration is not compatible with the
* EinsyRetro 1.1a because there is a level shifter
* on MISO enabled by SD/USB chip select.
*
* [2] This configuration allows daisy-chaining of the
* display and SD/USB on EXP2.
*
* [3] Archim Rambo provides 5V on this pin. On any other
* board, divert this wire from the ribbon cable and
* connect it to 5V at an endstop.
*/
#ifdef AO_EXP2_PINMAP
#ifndef __MARLIN_FIRMWARE__
#error This pin mapping requires Marlin.
#endif
#define CLCD_SPI_CS BTN_EN1
#define CLCD_MOD_RESET BTN_EN2
#endif

@ -0,0 +1,80 @@
/********************
* about_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
#define GRID_COLS 4
#define GRID_ROWS 9
using namespace FTDI;
using namespace Theme;
using namespace ExtUI;
void AboutScreen::onEntry() {
BaseScreen::onEntry();
sound.play(chimes, PLAY_ASYNCHRONOUS);
}
void AboutScreen::onRedraw(draw_mode_t) {
CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(CLEAR(true,true,true))
.cmd(COLOR_RGB(bg_text_enabled))
.tag(0);
draw_text_box(cmd, BTN_POS(1,2), BTN_SIZE(4,1), F(
#ifdef LULZBOT_LCD_MACHINE_NAME
LULZBOT_LCD_MACHINE_NAME
#else
"Color Touch Panel"
#endif
), OPT_CENTER, font_xlarge);
cmd.tag(2);
draw_text_box(cmd, BTN_POS(1,3), BTN_SIZE(4,3), F(
#ifdef LULZBOT_LCD_TOOLHEAD_NAME
"Firmware for toolhead:\n" LULZBOT_LCD_TOOLHEAD_NAME "\n\n"
#endif
"(C) 2019 Aleph Objects, Inc.\n\nwww.lulzbot.com"
), OPT_CENTER, font_medium);
cmd.tag(0);
draw_text_box(cmd, BTN_POS(1,6), BTN_SIZE(4,2), progmem_str(getFirmwareName_str()), OPT_CENTER, font_medium);
cmd.font(font_medium).colors(action_btn).tag(1).button(BTN_POS(2,8), BTN_SIZE(2,1), F("Okay"));
}
bool AboutScreen::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1: GOTO_PREVIOUS(); return true;
#if ENABLED(DEVELOPER_SCREENS)
case 2: GOTO_SCREEN(DeveloperMenu); return true;
#endif
default: return false;
}
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,191 @@
/*****************************
* advance_settings_menu.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && !defined(LULZBOT_USE_BIOPRINTER_UI)
#include "screens.h"
using namespace FTDI;
using namespace ExtUI;
using namespace Theme;
void AdvancedSettingsMenu::onRedraw(draw_mode_t what) {
if (what & BACKGROUND) {
CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(Theme::bg_color))
.cmd(CLEAR(true,true,true));
}
if (what & FOREGROUND) {
CommandProcessor cmd;
cmd.colors(normal_btn)
.font(Theme::font_medium)
#ifdef TOUCH_UI_PORTRAIT
#define GRID_ROWS 9
#define GRID_COLS 2
#if HAS_BED_PROBE
.enabled(1)
#else
.enabled(0)
#endif
.tag(2) .button( BTN_POS(1,1), BTN_SIZE(1,1), F("Z Offset "))
.enabled(1)
.tag(3) .button( BTN_POS(2,1), BTN_SIZE(1,1), F("Steps/mm"))
#if HAS_TRINAMIC
.enabled(1)
#else
.enabled(0)
#endif
.tag(13).button( BTN_POS(1,5), BTN_SIZE(1,1), F("Motor mA"))
#if HAS_TRINAMIC
.enabled(1)
#else
.enabled(0)
#endif
.tag(14).button( BTN_POS(1,4), BTN_SIZE(1,1), F("Bump Sense"))
#if HOTENDS > 1
.enabled(1)
#else
.enabled(0)
#endif
.tag(4) .button( BTN_POS(1,2), BTN_SIZE(1,1), F("Nozzle Offset"))
#if ENABLED(LIN_ADVANCE) || ENABLED(FILAMENT_RUNOUT_SENSOR)
.enabled(1)
#else
.enabled(0)
#endif
.tag(11).button( BTN_POS(1,3), BTN_SIZE(1,1), F("Filament"))
.tag(12).button( BTN_POS(1,6), BTN_SIZE(1,1), F("Endstops"))
.tag(15).button( BTN_POS(2,6), BTN_SIZE(1,1), F("Display"))
.tag(9) .button( BTN_POS(1,7), BTN_SIZE(2,1), F("Interface Settings"))
.tag(10).button( BTN_POS(1,8), BTN_SIZE(2,1), F("Restore Factory Defaults"))
.tag(5) .button( BTN_POS(2,2), BTN_SIZE(1,1), F("Velocity "))
.tag(6) .button( BTN_POS(2,3), BTN_SIZE(1,1), F("Acceleration"))
#if ENABLED(JUNCTION_DEVIATION)
.tag(7) .button( BTN_POS(2,4), BTN_SIZE(1,1), F("Junc Dev"))
#else
.tag(7) .button( BTN_POS(2,4), BTN_SIZE(1,1), F("Jerk"))
#endif
#if ENABLED(BACKLASH_GCODE)
.enabled(1)
#else
.enabled(0)
#endif
.tag(8).button( BTN_POS(2,5), BTN_SIZE(1,1), F("Backlash"))
.colors(action_btn)
.tag(1) .button( BTN_POS(1,9), BTN_SIZE(2,1), F("Back"));
#undef GRID_COLS
#undef GRID_ROWS
#else
#define GRID_ROWS 6
#define GRID_COLS 3
#if HAS_BED_PROBE
.enabled(1)
#else
.enabled(0)
#endif
.tag(2) .button( BTN_POS(1,1), BTN_SIZE(1,2), F("Z Offset "))
.enabled(1)
.tag(3) .button( BTN_POS(2,1), BTN_SIZE(1,1), F("Steps/mm"))
#if HAS_TRINAMIC
.enabled(1)
#else
.enabled(0)
#endif
.tag(13).button( BTN_POS(3,1), BTN_SIZE(1,1), F("Motor mA"))
#if HAS_TRINAMIC
.enabled(1)
#else
.enabled(0)
#endif
.tag(14).button( BTN_POS(3,2), BTN_SIZE(1,1), F("Bump Sense"))
#if ENABLED(BACKLASH_GCODE)
.enabled(1)
#else
.enabled(0)
#endif
.tag(8).button( BTN_POS(3,3), BTN_SIZE(1,1), F("Backlash"))
#if HOTENDS > 1
.enabled(1)
#else
.enabled(0)
#endif
.tag(4) .button( BTN_POS(1,3), BTN_SIZE(1,1), F("Nozzle Offsets"))
.tag(12).button( BTN_POS(3,4), BTN_SIZE(1,1), F("Endstops"))
.tag(5) .button( BTN_POS(2,2), BTN_SIZE(1,1), F("Velocity "))
.tag(6) .button( BTN_POS(2,3), BTN_SIZE(1,1), F("Acceleration"))
#if ENABLED(JUNCTION_DEVIATION)
.tag(7) .button( BTN_POS(2,4), BTN_SIZE(1,1), F("Junc Dev"))
#else
.tag(7) .button( BTN_POS(2,4), BTN_SIZE(1,1), F("Jerk"))
#endif
.tag(11).button( BTN_POS(1,4), BTN_SIZE(1,1), F("Filament"))
.tag(15).button( BTN_POS(3,5), BTN_SIZE(1,1), F("Display"))
.tag(9) .button( BTN_POS(1,5), BTN_SIZE(2,1), F("Interface Settings"))
.tag(10).button( BTN_POS(1,6), BTN_SIZE(2,1), F("Restore Defaults"))
.colors(action_btn)
.tag(1) .button( BTN_POS(3,6), BTN_SIZE(1,1), F("Back"));
#endif
}
}
bool AdvancedSettingsMenu::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1: SaveSettingsDialogBox::promptToSaveSettings(); break;
#if HAS_BED_PROBE
case 2: GOTO_SCREEN(ZOffsetScreen); break;
#endif
case 3: GOTO_SCREEN(StepsScreen); break;
#if HOTENDS > 1
case 4: GOTO_SCREEN(NozzleOffsetScreen); break;
#endif
case 5: GOTO_SCREEN(MaxVelocityScreen); break;
case 6: GOTO_SCREEN(DefaultAccelerationScreen); break;
case 7:
#if ENABLED(JUNCTION_DEVIATION)
GOTO_SCREEN(JunctionDeviationScreen);
#else
GOTO_SCREEN(JerkScreen);
#endif
break;
#if ENABLED(BACKLASH_GCODE)
case 8: GOTO_SCREEN(BacklashCompensationScreen); break;
#endif
case 9: GOTO_SCREEN(InterfaceSettingsScreen); LockScreen::check_passcode(); break;
case 10: GOTO_SCREEN(RestoreFailsafeDialogBox); LockScreen::check_passcode(); break;
#if ENABLED(LIN_ADVANCE) || ENABLED(FILAMENT_RUNOUT_SENSOR)
case 11: GOTO_SCREEN(FilamentMenu); break;
#endif
case 12: GOTO_SCREEN(EndstopStatesScreen); break;
#if HAS_TRINAMIC
case 13: GOTO_SCREEN(StepperCurrentScreen); break;
case 14: GOTO_SCREEN(StepperBumpSensitivityScreen); break;
#endif
case 15: GOTO_SCREEN(DisplayTuningScreen); break;
default: return false;
}
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,70 @@
/************************
* alert_dialog_box.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
#include "screen_data.h"
using namespace FTDI;
using namespace Theme;
void AlertDialogBox::onEntry() {
BaseScreen::onEntry();
sound.play(screen_data.AlertDialogBox.isError ? sad_trombone : twinkle, PLAY_ASYNCHRONOUS);
}
void AlertDialogBox::onRedraw(draw_mode_t what) {
if (what & FOREGROUND) {
drawOkayButton();
}
}
template<typename T>
void AlertDialogBox::show(const T message) {
drawMessage(message);
storeBackground();
screen_data.AlertDialogBox.isError = false;
GOTO_SCREEN(AlertDialogBox);
}
template<typename T>
void AlertDialogBox::showError(const T message) {
drawMessage(message);
storeBackground();
screen_data.AlertDialogBox.isError = true;
GOTO_SCREEN(AlertDialogBox);
}
void AlertDialogBox::hide() {
if (AT_SCREEN(AlertDialogBox))
GOTO_PREVIOUS();
}
template void AlertDialogBox::show(const char *);
template void AlertDialogBox::show(const progmem_str);
template void AlertDialogBox::showError(const char *);
template void AlertDialogBox::showError(const progmem_str);
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,72 @@
/************************************
* backlash_compensation_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && ENABLED(BACKLASH_GCODE)
#include "screens.h"
using namespace FTDI;
using namespace ExtUI;
using namespace Theme;
void BacklashCompensationScreen::onRedraw(draw_mode_t what) {
widgets_t w(what);
w.precision(2).units(PSTR("mm"));
w.heading( PSTR("Axis Backlash"));
w.color(x_axis).adjuster(2, PSTR("X:"), getAxisBacklash_mm(X));
w.color(y_axis).adjuster(4, PSTR("Y:"), getAxisBacklash_mm(Y));
w.color(z_axis).adjuster(6, PSTR("Z:"), getAxisBacklash_mm(Z));
#if ENABLED(CALIBRATION_GCODE)
w.button(12, PSTR("Measure automatically"));
#endif
w.color(other).adjuster(8, PSTR("Smoothing:"), getBacklashSmoothing_mm());
w.precision(0).units(PSTR("%"))
.adjuster(10, PSTR("Correction:"), getBacklashCorrection_percent());
w.precision(2).increments();
}
bool BacklashCompensationScreen::onTouchHeld(uint8_t tag) {
const float increment = getIncrement();
switch (tag) {
case 2: UI_DECREMENT(AxisBacklash_mm, X); break;
case 3: UI_INCREMENT(AxisBacklash_mm, X); break;
case 4: UI_DECREMENT(AxisBacklash_mm, Y); break;
case 5: UI_INCREMENT(AxisBacklash_mm, Y); break;
case 6: UI_DECREMENT(AxisBacklash_mm, Z); break;
case 7: UI_INCREMENT(AxisBacklash_mm, Z); break;
case 8: UI_DECREMENT(BacklashSmoothing_mm); break;
case 9: UI_INCREMENT(BacklashSmoothing_mm); break;
case 10: UI_DECREMENT_BY(BacklashCorrection_percent, increment*100); break;
case 11: UI_INCREMENT_BY(BacklashCorrection_percent, increment*100); break;
#if ENABLED(CALIBRATION_GCODE)
case 12: GOTO_SCREEN(ConfirmAutoCalibrationDialogBox); return true;
#endif
default:
return false;
}
SaveSettingsDialogBox::settingsChanged();
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,342 @@
/**************************************
* base_numeric_adjustment_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
#include "screen_data.h"
using namespace FTDI;
using namespace Theme;
#ifdef TOUCH_UI_PORTRAIT
#define GRID_COLS 13
#define GRID_ROWS 10
#else
#define GRID_COLS 18
#define GRID_ROWS 7
#endif
BaseNumericAdjustmentScreen::widgets_t::widgets_t(draw_mode_t what) : _what(what) {
if (what & BACKGROUND) {
CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(CLEAR(true,true,true));
}
if (what & FOREGROUND) {
CommandProcessor cmd;
cmd.font(font_medium)
.colors(action_btn)
#ifdef TOUCH_UI_PORTRAIT
.tag(1).button( BTN_POS(1,10), BTN_SIZE(13,1), F("Back"))
#else
.tag(1).button( BTN_POS(15,7), BTN_SIZE(4,1), F("Back"))
#endif
.colors(normal_btn);
}
_line = 1;
_units = PSTR("");
}
BaseNumericAdjustmentScreen::widgets_t &BaseNumericAdjustmentScreen::widgets_t::precision(uint8_t decimals, precision_default_t initial) {
_decimals = decimals;
if (screen_data.BaseNumericAdjustmentScreen.increment == 0) {
screen_data.BaseNumericAdjustmentScreen.increment = 243 + (initial - DEFAULT_LOWEST) - _decimals;
}
return *this;
}
void BaseNumericAdjustmentScreen::widgets_t::heading(const char *label) {
CommandProcessor cmd;
cmd.font(font_medium).cmd(COLOR_RGB(bg_text_enabled));
if (_what & BACKGROUND) {
#ifdef TOUCH_UI_PORTRAIT
cmd.tag(0).fgcolor(bg_color).button( BTN_POS(1, _line), BTN_SIZE(12,1), progmem_str(label), OPT_FLAT);
#else
cmd.tag(0).fgcolor(bg_color).button( BTN_POS(5, _line), BTN_SIZE(8,1), progmem_str(label), OPT_FLAT);
#endif
}
_line++;
}
#ifdef TOUCH_UI_PORTRAIT
#ifdef TOUCH_UI_800x480
#undef EDGE_R
#define EDGE_R 20
#else
#undef EDGE_R
#define EDGE_R 10
#endif
#endif
void BaseNumericAdjustmentScreen::widgets_t::_draw_increment_btn(uint8_t, const uint8_t tag) {
CommandProcessor cmd;
const char *label = PSTR("?");
uint8_t pos;
uint8_t & increment = screen_data.BaseNumericAdjustmentScreen.increment;
if (increment == 0) {
increment = tag; // Set the default value to be the first.
}
switch (tag) {
case 240: label = PSTR( ".001"); pos = _decimals - 3; break;
case 241: label = PSTR( ".01" ); pos = _decimals - 2; break;
case 242: label = PSTR( "0.1" ); pos = _decimals - 1; break;
case 243: label = PSTR( "1" ); pos = _decimals + 0; break;
case 244: label = PSTR( "10" ); pos = _decimals + 1; break;
default: label = PSTR("100" ); pos = _decimals + 2; break;
}
cmd.tag(tag)
.colors(increment == tag ? action_btn : normal_btn)
#ifdef TOUCH_UI_PORTRAIT
.font(font_small);
#else
.font(font_medium);
#endif
switch (pos) {
#ifdef TOUCH_UI_PORTRAIT
case 0: cmd.button( BTN_POS(5,_line), BTN_SIZE(2,1), progmem_str(label)); break;
case 1: cmd.button( BTN_POS(7,_line), BTN_SIZE(2,1), progmem_str(label)); break;
case 2: cmd.button( BTN_POS(9,_line), BTN_SIZE(2,1), progmem_str(label)); break;
#else
case 0: cmd.button( BTN_POS(15,2), BTN_SIZE(4,1), progmem_str(label)); break;
case 1: cmd.button( BTN_POS(15,3), BTN_SIZE(4,1), progmem_str(label)); break;
case 2: cmd.button( BTN_POS(15,4), BTN_SIZE(4,1), progmem_str(label)); break;
#endif
}
cmd.colors(normal_btn);
}
void BaseNumericAdjustmentScreen::widgets_t::increments() {
if (_what & BACKGROUND) {
CommandProcessor cmd;
cmd.fgcolor(bg_color)
.tag(0)
#ifdef TOUCH_UI_PORTRAIT
.font(font_small).button( BTN_POS(1, _line), BTN_SIZE(4,1), F("Increment:"), OPT_FLAT);
#else
.font(font_medium).button( BTN_POS(15,1), BTN_SIZE(4,1), F("Increment:"), OPT_FLAT);
#endif
}
if (_what & FOREGROUND) {
_draw_increment_btn(_line+1, 245 - _decimals);
_draw_increment_btn(_line+1, 244 - _decimals);
_draw_increment_btn(_line+1, 243 - _decimals);
}
#ifdef TOUCH_UI_PORTRAIT
_line++;
#endif
}
void BaseNumericAdjustmentScreen::widgets_t::adjuster_sram_val(uint8_t tag, const char *label, const char *value, bool is_enabled) {
CommandProcessor cmd;
if (_what & BACKGROUND) {
cmd.enabled(1)
.font(font_small)
.fgcolor(_color) .tag(0).button( BTN_POS(5,_line), BTN_SIZE(5,1), F(""), OPT_FLAT)
.cmd(COLOR_RGB(bg_text_enabled))
.fgcolor(bg_color) .tag(0).button( BTN_POS(1,_line), BTN_SIZE(4,1), (progmem_str) label, OPT_FLAT);
}
if (_what & FOREGROUND) {
cmd.colors(normal_btn)
.font(font_medium)
.tag(is_enabled ? tag : 0).enabled(is_enabled).button( BTN_POS(10,_line), BTN_SIZE(2,1), F("-"))
.tag(is_enabled ? tag+1 : 0).enabled(is_enabled).button( BTN_POS(12,_line), BTN_SIZE(2,1), F("+"))
.tag(0).font(font_small) .text ( BTN_POS(5,_line), BTN_SIZE(5,1), is_enabled ? value : "-");
}
_line++;
}
void BaseNumericAdjustmentScreen::widgets_t::adjuster(uint8_t tag, const char *label, const char *value, bool is_enabled) {
if (_what & BACKGROUND) {
adjuster_sram_val(tag, label, nullptr);
}
if (_what & FOREGROUND) {
char b[strlen_P(value)+1];
strcpy_P(b,value);
adjuster_sram_val(tag, label, b, is_enabled);
}
}
void BaseNumericAdjustmentScreen::widgets_t::adjuster(uint8_t tag, const char *label, float value, bool is_enabled) {
if (_what & BACKGROUND) {
adjuster_sram_val(tag, label, nullptr);
}
if (_what & FOREGROUND) {
char b[32];
dtostrf(value, 5, _decimals, b);
strcat_P(b, PSTR(" "));
strcat_P(b, (const char*) _units);
adjuster_sram_val(tag, label, b, is_enabled);
}
}
void BaseNumericAdjustmentScreen::widgets_t::button(uint8_t tag, const char *label, bool is_enabled) {
if (_what & FOREGROUND) {
CommandProcessor cmd;
cmd.colors(normal_btn)
.tag(is_enabled ? tag : 0)
.enabled(is_enabled)
#ifdef TOUCH_UI_PORTRAIT
.font(font_small)
#else
.font(font_medium)
#endif
.button(BTN_POS(5,_line), BTN_SIZE(9,1), progmem_str(label));
}
_line++;
}
void BaseNumericAdjustmentScreen::widgets_t::text_field(uint8_t tag, const char *label, const char *value, bool is_enabled) {
CommandProcessor cmd;
if (_what & BACKGROUND) {
cmd.enabled(1)
.font(font_small)
.cmd(COLOR_RGB(bg_text_enabled))
.fgcolor(_color).tag(0).button( BTN_POS(5,_line), BTN_SIZE(9,1), F(""), OPT_FLAT)
.fgcolor(bg_color) .tag(0).button( BTN_POS(1,_line), BTN_SIZE(4,1), (progmem_str) label, OPT_FLAT);
}
if (_what & FOREGROUND) {
cmd.colors(normal_btn)
.font(font_medium)
.tag(tag).font(font_small).text ( BTN_POS(5,_line), BTN_SIZE(9,1), is_enabled ? value : "-");
}
_line++;
}
void BaseNumericAdjustmentScreen::widgets_t::two_buttons(uint8_t tag1, const char *label1, uint8_t tag2, const char *label2, bool is_enabled) {
if (_what & FOREGROUND) {
CommandProcessor cmd;
cmd.enabled(is_enabled)
#ifdef TOUCH_UI_PORTRAIT
.font(font_small)
#else
.font(font_medium)
#endif
.tag(is_enabled ? tag1: 0).button(BTN_POS(5,_line), BTN_SIZE(4.5,1), progmem_str(label1))
.tag(is_enabled ? tag2: 0).button(BTN_POS(9.5,_line), BTN_SIZE(4.5,1), progmem_str(label2));
}
_line++;
}
void BaseNumericAdjustmentScreen::widgets_t::toggle(uint8_t tag, const char *label, const char *text, bool value, bool is_enabled) {
if (_what & BACKGROUND) {
CommandProcessor cmd;
cmd.fgcolor(bg_color)
.tag(0)
.font(font_small)
#ifdef TOUCH_UI_PORTRAIT
.button( BTN_POS(1, _line), BTN_SIZE( 8,1), progmem_str(label), OPT_FLAT);
#else
.button( BTN_POS(1, _line), BTN_SIZE(10,1), progmem_str(label), OPT_FLAT);
#endif
}
if (_what & FOREGROUND) {
CommandProcessor cmd;
cmd.tag(is_enabled ? tag : 0)
.enabled(is_enabled)
.font(font_small)
.colors(ui_toggle)
#ifdef TOUCH_UI_PORTRAIT
.toggle(BTN_POS( 9,_line), BTN_SIZE(5,1), progmem_str(text), value);
#else
.toggle(BTN_POS(10,_line), BTN_SIZE(4,1), progmem_str(text), value);
#endif
}
_line++;
}
void BaseNumericAdjustmentScreen::widgets_t::home_buttons(uint8_t tag) {
if (_what & BACKGROUND) {
CommandProcessor cmd;
cmd.fgcolor(bg_color)
.tag(0)
.font(font_small)
.button( BTN_POS(1, _line), BTN_SIZE(4,1), F("Home:"), OPT_FLAT);
}
if (_what & FOREGROUND) {
CommandProcessor cmd;
cmd
#ifdef TOUCH_UI_PORTRAIT
.font(font_small)
#else
.font(font_medium)
#endif
.tag(tag+0).button(BTN_POS(5,_line), BTN_SIZE(2,1), F("X"))
.tag(tag+1).button(BTN_POS(7,_line), BTN_SIZE(2,1), F("Y"))
.tag(tag+2).button(BTN_POS(9,_line), BTN_SIZE(2,1), F("Z"))
.tag(tag+3).button(BTN_POS(11,_line), BTN_SIZE(3,1), F("All"));
}
_line++;
}
void BaseNumericAdjustmentScreen::onEntry() {
screen_data.BaseNumericAdjustmentScreen.increment = 0; // This will force the increment to be picked while drawing.
BaseScreen::onEntry();
}
bool BaseNumericAdjustmentScreen::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1: GOTO_PREVIOUS(); return true;
case 240 ... 245: screen_data.BaseNumericAdjustmentScreen.increment = tag; break;
default: return current_screen.onTouchHeld(tag);
}
return true;
}
float BaseNumericAdjustmentScreen::getIncrement() {
switch (screen_data.BaseNumericAdjustmentScreen.increment) {
case 240: return 0.001;
case 241: return 0.01;
case 242: return 0.1;
case 243: return 1.0;
case 244: return 10.0;
case 245: return 100.0;
default: return 0.0;
}
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,83 @@
/*******************
* base_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
using namespace FTDI;
using namespace Theme;
void BaseScreen::onEntry() {
CommandProcessor cmd;
cmd.set_button_style_callback(buttonStyleCallback);
UIScreen::onEntry();
}
bool BaseScreen::buttonStyleCallback(CommandProcessor &cmd, uint8_t tag, uint8_t &style, uint16_t &options, bool post) {
if (post) {
cmd.colors(normal_btn);
return false;
}
#ifdef LCD_TIMEOUT_TO_STATUS
if (EventLoop::get_pressed_tag() != 0) {
reset_menu_timeout();
}
#endif
if (tag != 0 && EventLoop::get_pressed_tag() == tag) {
options = OPT_FLAT;
}
if (style & cmd.STYLE_DISABLED) {
cmd.tag(0);
style &= ~cmd.STYLE_DISABLED;
cmd.colors(disabled_btn);
return true; // Call me again to reset the colors
}
return false;
}
void BaseScreen::onIdle() {
#ifdef LCD_TIMEOUT_TO_STATUS
const uint32_t elapsed = millis() - last_interaction;
if (elapsed > uint32_t(LCD_TIMEOUT_TO_STATUS) * 1000) {
reset_menu_timeout();
GOTO_SCREEN(StatusScreen);
}
#endif
}
void BaseScreen::reset_menu_timeout() {
#ifdef LCD_TIMEOUT_TO_STATUS
last_interaction = millis();
#endif
}
#ifdef LCD_TIMEOUT_TO_STATUS
uint32_t BaseScreen::last_interaction;
#endif
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,137 @@
/*****************************
* bio_advanced_settings.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && defined(LULZBOT_USE_BIOPRINTER_UI)
#include "screens.h"
using namespace FTDI;
using namespace Theme;
void AdvancedSettingsMenu::onRedraw(draw_mode_t what) {
if (what & BACKGROUND) {
CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(Theme::bg_color))
.cmd(CLEAR(true,true,true));
}
if (what & FOREGROUND) {
CommandProcessor cmd;
cmd.colors(normal_btn)
.font(Theme::font_medium)
#define GRID_ROWS 9
#define GRID_COLS 2
.tag(2) .button( BTN_POS(1,1), BTN_SIZE(1,1), F("Display"))
#if HAS_TRINAMIC
.enabled(1)
#else
.enabled(0)
#endif
.tag(3) .button( BTN_POS(1,2), BTN_SIZE(1,1), F("Motor mA"))
#if HAS_TRINAMIC
.enabled(1)
#else
.enabled(0)
#endif
.tag(4) .button( BTN_POS(1,3), BTN_SIZE(1,1), F("Bump Sense"))
.tag(5) .button( BTN_POS(1,4), BTN_SIZE(1,1), F("Endstops"))
#if HOTENDS > 1
.enabled(1)
#else
.enabled(0)
#endif
.tag(6) .button( BTN_POS(1,5), BTN_SIZE(1,1), F("Nozzle Offset"))
.tag(7) .button( BTN_POS(2,1), BTN_SIZE(1,1), F("Steps/mm"))
.tag(8) .button( BTN_POS(2,2), BTN_SIZE(1,1), F("Velocity "))
.tag(9) .button( BTN_POS(2,3), BTN_SIZE(1,1), F("Acceleration"))
#if ENABLED(JUNCTION_DEVIATION)
.tag(10) .button( BTN_POS(2,4), BTN_SIZE(1,1), F("Junc Dev"))
#else
.tag(10) .button( BTN_POS(2,4), BTN_SIZE(1,1), F("Jerk"))
#endif
#if ENABLED(BACKLASH_GCODE)
.enabled(1)
#else
.enabled(0)
#endif
.tag(11) .button( BTN_POS(2,5), BTN_SIZE(1,1), F("Backlash"))
#if ENABLED(LIN_ADVANCE)
.enabled(1)
#else
.enabled(0)
#endif
.tag(12) .button( BTN_POS(1,6), BTN_SIZE(2,1), F("Linear Advance"))
.tag(13) .button( BTN_POS(1,7), BTN_SIZE(2,1), F("Interface Settings"))
.tag(14) .button( BTN_POS(1,8), BTN_SIZE(2,1), F("Restore Factory Defaults"))
.colors(action_btn)
.tag(1). button( BTN_POS(1,9), BTN_SIZE(2,1), F("Back"));
#undef GRID_COLS
#undef GRID_ROWS
}
}
bool AdvancedSettingsMenu::onTouchEnd(uint8_t tag) {
using namespace ExtUI;
switch (tag) {
case 1: SaveSettingsDialogBox::promptToSaveSettings(); break;
case 2: GOTO_SCREEN(DisplayTuningScreen); break;
#if HAS_TRINAMIC
case 3: GOTO_SCREEN(StepperCurrentScreen); break;
case 4: GOTO_SCREEN(StepperBumpSensitivityScreen); break;
#endif
case 5: GOTO_SCREEN(EndstopStatesScreen); break;
#if HOTENDS > 1
case 6: GOTO_SCREEN(NozzleOffsetScreen); break;
#endif
case 7: GOTO_SCREEN(StepsScreen); break;
case 8: GOTO_SCREEN(MaxVelocityScreen); break;
case 9: GOTO_SCREEN(DefaultAccelerationScreen); break;
case 10:
#if ENABLED(JUNCTION_DEVIATION)
GOTO_SCREEN(JunctionDeviationScreen);
#else
GOTO_SCREEN(JerkScreen);
#endif
break;
#if ENABLED(BACKLASH_GCODE)
case 11: GOTO_SCREEN(BacklashCompensationScreen); break;
#endif
#if ENABLED(LIN_ADVANCE)
case 12: GOTO_SCREEN(LinearAdvanceScreen); break;
#endif
case 13: GOTO_SCREEN(InterfaceSettingsScreen); break;
case 14: GOTO_SCREEN(RestoreFailsafeDialogBox); break;
default:
return false;
}
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,56 @@
/****************************
* bio_confirm_home_xyz.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && defined(LULZBOT_USE_BIOPRINTER_UI)
#include "screens.h"
using namespace FTDI;
void BioConfirmHomeE::onRedraw(draw_mode_t) {
drawMessage(F("About to re-home plunger and auto-level. Remove syringe prior to proceeding.\n\nContinue?"));
drawYesNoButtons(1);
}
bool BioConfirmHomeE::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1:
SpinnerDialogBox::enqueueAndWait_P(F(
"G112\n" /* Home extruder */
LULZBOT_AXIS_LEVELING_COMMANDS /* Level X axis */
"G0 X115 Z50 F6000\n" /* Goto loading position */
"M400\n" /* Wait for moves to finish */
"M18 X Y" /* Unlock motors */
));
current_screen.forget();
break;
case 2:
GOTO_SCREEN(StatusScreen);
break;
default:
return DialogBoxBaseClass::onTouchEnd(tag);
}
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,53 @@
/****************************
* bio_confirm_home_xyz.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && defined(LULZBOT_USE_BIOPRINTER_UI)
#include "screens.h"
using namespace FTDI;
void BioConfirmHomeXYZ::onRedraw(draw_mode_t) {
drawMessage(F("About to home to loading position.\nEnsure the top and the bed of the printer are clear.\n\nContinue?"));
drawYesNoButtons(1);
}
bool BioConfirmHomeXYZ::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1:
SpinnerDialogBox::enqueueAndWait_P(F(
"G28 X Y Z\n" /* Home all axis */
"G0 X115 Z50 F6000" /* Move to park position */
));
current_screen.forget();
break;
case 2:
GOTO_SCREEN(StatusScreen);
break;
default:
return DialogBoxBaseClass::onTouchEnd(tag);
}
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,79 @@
/*********************
* bio_main_menu.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && defined(LULZBOT_USE_BIOPRINTER_UI)
#include "screens.h"
using namespace FTDI;
using namespace Theme;
void MainMenu::onRedraw(draw_mode_t what) {
#define GRID_ROWS 8
#define GRID_COLS 2
if (what & BACKGROUND) {
CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(Theme::bg_color))
.cmd(CLEAR(true,true,true));
}
if (what & FOREGROUND) {
CommandProcessor cmd;
cmd.cmd(COLOR_RGB(bg_text_enabled))
.font(font_large).text( BTN_POS(1,1), BTN_SIZE(2,1), F("Main Menu"))
.colors(normal_btn)
.font(font_medium)
.tag(2).button( BTN_POS(1,2), BTN_SIZE(2,1), F("Load Syringe"))
.tag(3).button( BTN_POS(1,3), BTN_SIZE(2,1), F("Unlock XY Axis"))
.tag(4).button( BTN_POS(1,4), BTN_SIZE(2,1), F("Bed Temperature"))
.tag(5).button( BTN_POS(1,5), BTN_SIZE(2,1), F("Interface Settings"))
.tag(6).button( BTN_POS(1,6), BTN_SIZE(2,1), F("Advanced Settings"))
.tag(7).button( BTN_POS(1,7), BTN_SIZE(2,1), F("About Printer"))
.colors(action_btn)
.tag(1).button( BTN_POS(1,8), BTN_SIZE(2,1), F("Back"));
}
#undef GRID_COLS
#undef GRID_ROWS
}
bool MainMenu::onTouchEnd(uint8_t tag) {
using namespace ExtUI;
switch (tag) {
case 1: SaveSettingsDialogBox::promptToSaveSettings(); break;
case 2: GOTO_SCREEN(BioConfirmHomeXYZ); break;
case 3: StatusScreen::unlockMotors(); break;
case 4: GOTO_SCREEN(TemperatureScreen); break;
case 5: GOTO_SCREEN(InterfaceSettingsScreen); break;
case 6: GOTO_SCREEN(AdvancedSettingsMenu); break;
case 7: GOTO_SCREEN(AboutScreen); break;
default:
return false;
}
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,75 @@
/****************************************************************************
* 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 file was auto-generated using "svg2cpp.pl"
*
* The encoding consists of x,y pairs with the min and max scaled to
* 0x0000 and 0xFFFE. A single 0xFFFF in the data stream indicates the
* start of a new closed path.
*/
#pragma once
constexpr float x_min = 0.000000;
constexpr float x_max = 272.000000;
constexpr float y_min = 0.000000;
constexpr float y_max = 480.000000;
const PROGMEM uint16_t z_neg[] = {0xC9B1, 0x96B3, 0xD990, 0x96B3, 0xD990, 0xA8D0, 0xE17F, 0xA8D0, 0xD1A0, 0xB1DF, 0xC1C2, 0xA8D0, 0xC9B1, 0xA8D0, 0xC9B1, 0x96B3};
const PROGMEM uint16_t z_pos[] = {0xC9B1, 0x8DA4, 0xD990, 0x8DA4, 0xD990, 0x7B86, 0xE17F, 0x7B86, 0xD1A0, 0x7277, 0xC1C2, 0x7B86, 0xC9B1, 0x7B86, 0xC9B1, 0x8DA4};
const PROGMEM uint16_t y_neg[] = {0x5037, 0x9979, 0x6264, 0x9979, 0x5529, 0xA92A, 0x5E3F, 0xA92A, 0x4575, 0xB103, 0x39E6, 0xA92A, 0x42FC, 0xA92A, 0x5037, 0x9979};
const PROGMEM uint16_t y_pos[] = {0x5D72, 0x89C7, 0x6F9F, 0x89C7, 0x7CDA, 0x7A15, 0x85F0, 0x7A15, 0x7A61, 0x723D, 0x6197, 0x7A15, 0x6AAD, 0x7A15, 0x5D72, 0x89C7};
const PROGMEM uint16_t x_neg[] = {0x513D, 0x8DB3, 0x4AA0, 0x958C, 0x2647, 0x958C, 0x22F8, 0x9979, 0x1769, 0x91A0, 0x3033, 0x89C7, 0x2CE4, 0x8DB3, 0x513D, 0x8DB3};
const PROGMEM uint16_t x_pos[] = {0x7566, 0x8DB3, 0x6EC9, 0x958C, 0x9322, 0x958C, 0x8FD4, 0x9979, 0xA89E, 0x91A0, 0x9D0E, 0x89C7, 0x99C0, 0x8DB3, 0x7566, 0x8DB3};
const PROGMEM uint16_t syringe_fluid[] = {0x7D1D, 0x4A0F, 0x87FC, 0x4C0E, 0x8CF4, 0x4C0E, 0x9801, 0x4A0F, 0x9801, 0x1AA2, 0x7D1D, 0x1AA2, 0x7D1D, 0x4A0F};
const PROGMEM uint16_t syringe[] = {0x83C2, 0x42AA, 0x83C2, 0x43FF, 0x8D2C, 0x43FF, 0x8D2C, 0x42AA, 0xFFFF, 0x83C2, 0x3D54, 0x83C2, 0x3EAA, 0x8D2C, 0x3EAA, 0x8D2C, 0x3D54, 0xFFFF, 0x83C2, 0x37FF, 0x83C2, 0x3954, 0x8D2C, 0x3954, 0x8D2C, 0x37FF, 0xFFFF, 0x83C2, 0x32AA, 0x83C2, 0x33FF, 0x8D2C, 0x33FF, 0x8D2C, 0x32AA, 0xFFFF, 0x83C2, 0x2D54, 0x83C2, 0x2EAA, 0x8D2C, 0x2EAA, 0x8D2C, 0x2D54, 0xFFFF, 0x83C2, 0x27FF, 0x83C2, 0x2955, 0x8D2C, 0x2955, 0x8D2C, 0x27FF, 0xFFFF, 0x83C2, 0x22AA, 0x83C2, 0x23FF, 0x8D2C, 0x23FF, 0x8D2C, 0x22AA, 0xFFFF, 0x7AC7, 0x0F4B, 0x7AC7, 0x134A, 0x855B, 0x134A, 0x855B, 0x1949, 0x7AC7, 0x1949, 0x7AC7, 0x4B40, 0x855B, 0x4D40, 0x855B, 0x533F, 0x88E2, 0x533F, 0x88E2, 0x653C, 0x8C69, 0x673C, 0x8C69, 0x533F, 0x8FF0, 0x533F, 0x8FF0, 0x4D40, 0x9A85, 0x4B40, 0x9A85, 0x1949, 0x8FF0, 0x1949, 0x8FF0, 0x134A, 0x9A85, 0x134A, 0x9A85, 0x0F4B, 0xFFFF, 0x88E2, 0x134A, 0x8C69, 0x134A, 0x8C69, 0x1949, 0x88E2, 0x1949, 0x88E2, 0x134A, 0xFFFF, 0x7E4D, 0x1B49, 0x96FE, 0x1B49, 0x96FE, 0x4941, 0x8C69, 0x4B40, 0x88E2, 0x4B40, 0x7E4D, 0x4941, 0x7E4D, 0x1B49};
const PROGMEM uint16_t syringe_outline[] = {0x7AC7, 0x0F4B, 0x7AC7, 0x134A, 0x855B, 0x134A, 0x855B, 0x1949, 0x7AC7, 0x1949, 0x7AC7, 0x4B40, 0x855B, 0x4D40, 0x855B, 0x533F, 0x88E2, 0x533F, 0x88E2, 0x653C, 0x8C69, 0x673C, 0x8C69, 0x533F, 0x8FF0, 0x533F, 0x8FF0, 0x4D40, 0x9A85, 0x4B40, 0x9A85, 0x1949, 0x8FF0, 0x1949, 0x8FF0, 0x134A, 0x9A85, 0x134A, 0x9A85, 0x0F4B, 0x7AC7, 0x0F4B};
const PROGMEM uint16_t padlock[] = {0x645A, 0x8017, 0x5F9E, 0x80A1, 0x5BBA, 0x821B, 0x5911, 0x844A, 0x580A, 0x86F7, 0x580A, 0x8931, 0x5970, 0x8A98, 0x5C49, 0x8A98, 0x5DB0, 0x8931, 0x5DB0, 0x8703, 0x5E3C, 0x858E, 0x5FAA, 0x845F, 0x61C5, 0x8394, 0x645A, 0x834A, 0x66F0, 0x8394, 0x690C, 0x845F, 0x6A7A, 0x858D, 0x6B07, 0x8703, 0x6B07, 0x8F23, 0x57C8, 0x8F23, 0x551E, 0x8FC3, 0x5404, 0x9145, 0x5404, 0x9C8F, 0x551E, 0x9E11, 0x57C8, 0x9EB1, 0x70EE, 0x9EB1, 0x7398, 0x9E11, 0x74B2, 0x9C8F, 0x74B2, 0x9145, 0x7398, 0x8FC3, 0x70EE, 0x8F23, 0x70AC, 0x86FA, 0x6FA5, 0x844A, 0x6CFD, 0x821B, 0x6917, 0x80A1};
const PROGMEM uint16_t home_z[] = {0xD6C9, 0x80CC, 0xBB53, 0x905B, 0xC231, 0x905B, 0xC231, 0x9FEB, 0xCFEC, 0x9FEB, 0xCFEC, 0x9823, 0xDDA7, 0x9823, 0xDDA7, 0x9FEB, 0xEB62, 0x9FEB, 0xEB62, 0x905B, 0xF240, 0x905B, 0xE7A3, 0x8A58, 0xE7A3, 0x82CD, 0xE0C6, 0x82CD, 0xE0C6, 0x8674};
const PROGMEM uint16_t home_e[] = {0xB94F, 0x25AA, 0x9DD8, 0x353A, 0xA4B6, 0x353A, 0xA4B6, 0x44C9, 0xB271, 0x44C9, 0xB271, 0x3D02, 0xC02C, 0x3D02, 0xC02C, 0x44C9, 0xCDE7, 0x44C9, 0xCDE7, 0x353A, 0xD4C5, 0x353A, 0xCA28, 0x2F36, 0xCA28, 0x27AB, 0xC34B, 0x27AB, 0xC34B, 0x2B53};
const PROGMEM uint16_t bed_icon[] = {0x1764, 0x2C4C, 0x6135, 0x2C4C, 0x6135, 0x40A8, 0x1764, 0x40A8};
const PROGMEM uint16_t actual_temp[] = {0x1764, 0x466F, 0x6135, 0x466F, 0x6135, 0x5ACB, 0x1764, 0x5ACB};
const PROGMEM uint16_t target_temp[] = {0x1764, 0x1228, 0x6135, 0x1228, 0x6135, 0x2684, 0x1764, 0x2684};
const PROGMEM uint16_t fine_label[] = {0x1AA7, 0xC6D2, 0x9387, 0xC6D2, 0x9387, 0xD316, 0x1AA7, 0xD316};
const PROGMEM uint16_t fine_toggle[] = {0x9C10, 0xC6D2, 0xE4A3, 0xC6D2, 0xE4A3, 0xD316, 0x9C10, 0xD316};
const PROGMEM uint16_t usb_btn[] = {0x0B68, 0xE880, 0x7B1A, 0xE880, 0x7B1A, 0xF94B, 0x0B68, 0xF94B, 0x0B68, 0xE880};
const PROGMEM uint16_t menu_btn[] = {0x84E3, 0xE880, 0xF495, 0xE880, 0xF495, 0xF94B, 0x84E3, 0xF94B, 0x84E3, 0xE880};
const PROGMEM uint16_t e_pos[] = {0xC9B1, 0x3B2D, 0xD990, 0x3B2D, 0xD990, 0x4D4B, 0xE17F, 0x4D4B, 0xD1A0, 0x565A, 0xC1C2, 0x4D4B, 0xC9B1, 0x4D4B, 0xC9B1, 0x3B2D};
const PROGMEM uint16_t e_neg[] = {0xC9B1, 0x321E, 0xD990, 0x321E, 0xD990, 0x2000, 0xE17F, 0x2000, 0xD1A0, 0x16F1, 0xC1C2, 0x2000, 0xC9B1, 0x2000, 0xC9B1, 0x321E};

@ -0,0 +1,155 @@
/*******************************
* bio_printing_dialog_box.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && defined(LULZBOT_USE_BIOPRINTER_UI)
#include "screens.h"
#include "../ftdi_eve_lib/extras/circular_progress.h"
using namespace FTDI;
using namespace ExtUI;
using namespace Theme;
#define GRID_COLS 2
#define GRID_ROWS 9
void BioPrintingDialogBox::draw_status_message(draw_mode_t what, const char* message) {
if (what & BACKGROUND) {
CommandProcessor cmd;
cmd.cmd(COLOR_RGB(bg_text_enabled));
draw_text_box(cmd, BTN_POS(1,2), BTN_SIZE(2,2), message, OPT_CENTER, font_large);
}
}
void BioPrintingDialogBox::draw_progress(draw_mode_t what) {
if (what & FOREGROUND) {
CommandProcessor cmd;
cmd.font(font_large)
.text(BTN_POS(1,1), BTN_SIZE(2,2), isPrinting() ? F("Printing...") : F("Finished."))
.tag(1)
.font(font_xlarge);
draw_circular_progress(cmd, BTN_POS(1,4), BTN_SIZE(2,3), getProgress_percent(), theme_dark, theme_darkest);
}
}
void BioPrintingDialogBox::draw_time_remaining(draw_mode_t what) {
if (what & FOREGROUND) {
const uint32_t elapsed = getProgress_seconds_elapsed();
const uint8_t hrs = elapsed/3600;
const uint8_t min = (elapsed/60)%60;
char time_str[10];
sprintf_P(time_str, PSTR("%02dh %02dm"), hrs, min);
CommandProcessor cmd;
cmd.font(font_large)
.text(BTN_POS(1,7), BTN_SIZE(2,2), time_str);
}
}
void BioPrintingDialogBox::draw_interaction_buttons(draw_mode_t what) {
if (what & FOREGROUND) {
CommandProcessor cmd;
cmd.colors(normal_btn)
.font(font_medium)
.colors(isPrinting() ? action_btn : normal_btn)
.tag(2).button(BTN_POS(1,9), BTN_SIZE(1,1), F("Menu"))
#if ENABLED(SDSUPPORT)
.enabled(isPrinting() ? isPrintingFromMedia() : 1)
#else
.enabled(isPrinting() ? 0 : 1)
#endif
.tag(3)
.colors(isPrinting() ? normal_btn : action_btn)
.button( BTN_POS(2,9), BTN_SIZE(1,1), isPrinting() ? F("Cancel") : F("Back"));
}
}
void BioPrintingDialogBox::onRedraw(draw_mode_t what) {
if (what & FOREGROUND) {
draw_progress(FOREGROUND);
draw_time_remaining(FOREGROUND);
draw_interaction_buttons(FOREGROUND);
}
}
bool BioPrintingDialogBox::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1: GOTO_SCREEN(FeedratePercentScreen); break;
case 2: GOTO_SCREEN(TuneMenu); break;
case 3:
if (isPrinting()) {
GOTO_SCREEN(ConfirmAbortPrintDialogBox);
} else {
GOTO_SCREEN(StatusScreen);
}
break;
default: return false;
}
return true;
}
void BioPrintingDialogBox::setStatusMessage(progmem_str message) {
char buff[strlen_P((const char * const)message)+1];
strcpy_P(buff, (const char * const) message);
setStatusMessage(buff);
}
void BioPrintingDialogBox::setStatusMessage(const char* message) {
CommandProcessor cmd;
cmd.cmd(CMD_DLSTART)
.cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(CLEAR(true,true,true));
draw_status_message(BACKGROUND, message);
draw_progress(BACKGROUND);
draw_time_remaining(BACKGROUND);
draw_interaction_buttons(BACKGROUND);
storeBackground();
#ifdef UI_FRAMEWORK_DEBUG
SERIAL_ECHO_START();
SERIAL_ECHOLNPAIR("New status message: ", message);
#endif
if (AT_SCREEN(BioPrintingDialogBox)) {
current_screen.onRefresh();
}
}
void BioPrintingDialogBox::onIdle() {
if (refresh_timer.elapsed(STATUS_UPDATE_INTERVAL)) {
onRefresh();
refresh_timer.start();
}
BaseScreen::onIdle();
}
void BioPrintingDialogBox::show() {
GOTO_SCREEN(BioPrintingDialogBox);
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,349 @@
/*************************
* bio_status_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && defined(LULZBOT_USE_BIOPRINTER_UI)
#include "screens.h"
#include "../ftdi_eve_lib/extras/poly_ui.h"
#include "bio_printer_ui.h"
#define E_TRAVEL_LIMIT 60
#define GRID_COLS 2
#define GRID_ROWS 9
#define POLY(A) PolyUI::poly_reader_t(A, sizeof(A)/sizeof(A[0]))
#if ENABLED(SDSUPPORT) && defined(LULZBOT_MANUAL_USB_STARTUP)
#include "../../../../sd/cardreader.h"
#endif
const uint8_t shadow_depth = 5;
using namespace FTDI;
using namespace Theme;
using namespace ExtUI;
float StatusScreen::increment;
bool StatusScreen::jog_xy;
bool StatusScreen::fine_motion;
void StatusScreen::unlockMotors() {
injectCommands_P(PSTR("M84 XY"));
jog_xy = false;
}
void StatusScreen::draw_temperature(draw_mode_t what) {
CommandProcessor cmd;
PolyUI ui(cmd, what);
int16_t x, y, h, v;
cmd.tag(15);
if (what & BACKGROUND) {
cmd.cmd(COLOR_RGB(bg_color));
// Draw touch surfaces
ui.bounds(POLY(target_temp), x, y, h, v);
cmd.rectangle(x, y, h, v);
ui.bounds(POLY(actual_temp), x, y, h, v);
cmd.rectangle(x, y, h, v);
ui.bounds(POLY(bed_icon), x, y, h, v);
cmd.rectangle(x, y, h, v);
// Draw bed icon
cmd.cmd(BITMAP_SOURCE(Bed_Heat_Icon_Info))
.cmd(BITMAP_LAYOUT(Bed_Heat_Icon_Info))
.cmd(BITMAP_SIZE (Bed_Heat_Icon_Info))
.cmd(COLOR_RGB(shadow_rgb))
.icon (x + 2, y + 2, h, v, Bed_Heat_Icon_Info, icon_scale * 2)
.cmd(COLOR_RGB(bg_text_enabled))
.icon (x, y, h, v, Bed_Heat_Icon_Info, icon_scale * 2);
}
if (what & FOREGROUND) {
char bed_str[15];
cmd.font(font_xlarge)
.cmd(COLOR_RGB(bg_text_enabled));
if (!isHeaterIdle(BED) && getTargetTemp_celsius(BED) > 0) {
sprintf_P(bed_str, PSTR("%-3d C"), ROUND(getTargetTemp_celsius(BED)));
ui.bounds(POLY(target_temp), x, y, h, v);
cmd.text(x, y, h, v, bed_str);
}
sprintf_P(bed_str, PSTR("%-3d C"), ROUND(getActualTemp_celsius(BED)));
ui.bounds(POLY(actual_temp), x, y, h, v);
cmd.text(x, y, h, v, bed_str);
}
}
void StatusScreen::draw_syringe(draw_mode_t what) {
int16_t x, y, h, v;
const float fill_level = 1.0 - min(1.0, max(0.0, getAxisPosition_mm(E0) / E_TRAVEL_LIMIT));
const bool e_homed = isAxisPositionKnown(E0);
CommandProcessor cmd;
PolyUI ui(cmd, what);
if (what & BACKGROUND) {
// Paint the shadow for the syringe
ui.color(shadow_rgb);
ui.shadow(POLY(syringe_outline), shadow_depth);
}
if (what & FOREGROUND && e_homed) {
// Paint the syringe icon
ui.color(syringe_rgb);
ui.fill(POLY(syringe_outline));
ui.color(fill_rgb);
ui.bounds(POLY(syringe_fluid), x, y, h, v);
cmd.cmd(SAVE_CONTEXT());
cmd.cmd(SCISSOR_XY(x,y + v * (1.0 - fill_level)));
cmd.cmd(SCISSOR_SIZE(h, v * fill_level));
ui.fill(POLY(syringe_fluid), false);
cmd.cmd(RESTORE_CONTEXT());
ui.color(stroke_rgb);
ui.fill(POLY(syringe));
}
}
void StatusScreen::draw_arrows(draw_mode_t what) {
const bool e_homed = isAxisPositionKnown(E0);
const bool z_homed = isAxisPositionKnown(Z);
CommandProcessor cmd;
PolyUI ui(cmd, what);
ui.button_fill (fill_rgb);
ui.button_stroke(stroke_rgb, 28);
ui.button_shadow(shadow_rgb, shadow_depth);
if ((what & BACKGROUND) || jog_xy) {
ui.button(1, POLY(x_neg));
ui.button(2, POLY(x_pos));
ui.button(3, POLY(y_neg));
ui.button(4, POLY(y_pos));
}
if ((what & BACKGROUND) || z_homed) {
ui.button(5, POLY(z_neg));
ui.button(6, POLY(z_pos));
}
if ((what & BACKGROUND) || e_homed) {
ui.button(7, POLY(e_neg));
ui.button(8, POLY(e_pos));
}
}
void StatusScreen::draw_fine_motion(draw_mode_t what) {
int16_t x, y, h, v;
CommandProcessor cmd;
PolyUI ui(cmd, what);
cmd.font(font_medium)
.tag(16);
if (what & BACKGROUND) {
ui.bounds(POLY(fine_label), x, y, h, v);
cmd.cmd(COLOR_RGB(bg_text_enabled))
.text(x, y, h, v, F("Fine motion:"));
}
if (what & FOREGROUND) {
ui.bounds(POLY(fine_toggle), x, y, h, v);
cmd.colors(ui_toggle)
.toggle(x, y, h, v, F("no\xFFyes"), fine_motion);
}
}
void StatusScreen::draw_overlay_icons(draw_mode_t what) {
const bool e_homed = isAxisPositionKnown(E0);
const bool z_homed = isAxisPositionKnown(Z);
CommandProcessor cmd;
PolyUI ui(cmd, what);
if (what & FOREGROUND) {
ui.button_fill (fill_rgb);
ui.button_stroke(stroke_rgb, 28);
ui.button_shadow(shadow_rgb, shadow_depth);
if (!jog_xy) {
ui.button(12, POLY(padlock));
}
if (!e_homed) {
ui.button(13, POLY(home_e));
}
if (!z_homed) {
ui.button(14, POLY(home_z));
}
}
}
void StatusScreen::draw_buttons(draw_mode_t) {
const bool has_media = isMediaInserted() && !isPrintingFromMedia();
CommandProcessor cmd;
cmd.font(font_medium)
.colors(normal_btn)
#if ENABLED(USB_FLASH_DRIVE_SUPPORT) && defined(LULZBOT_MANUAL_USB_STARTUP)
.enabled(!Sd2Card::ready() || has_media)
#else
.enabled(has_media)
#endif
.colors(has_media ? action_btn : normal_btn)
.tag(9).button(BTN_POS(1,9), BTN_SIZE(1,1),
isPrintingFromMedia() ?
F("Printing") :
#if ENABLED(USB_FLASH_DRIVE_SUPPORT)
#ifdef LULZBOT_MANUAL_USB_STARTUP
(Sd2Card::ready() ? F("USB Drive") : F("Enable USB"))
#else
F("USB Drive")
#endif
#else
F("SD Card")
#endif
);
cmd.colors(!has_media ? action_btn : normal_btn).tag(10).button(BTN_POS(2,9), BTN_SIZE(1,1), F("Menu"));
}
void StatusScreen::onStartup() {
// Load the bitmaps for the status screen
constexpr uint32_t base = ftdi_memory_map::RAM_G;
CLCD::mem_write_pgm(base + Bed_Heat_Icon_Info.RAMG_offset, Bed_Heat_Icon, sizeof(Bed_Heat_Icon));
}
void StatusScreen::onRedraw(draw_mode_t what) {
if (what & BACKGROUND) {
CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(bg_color));
cmd.cmd(CLEAR(true,true,true));
}
draw_syringe(what);
draw_temperature(what);
draw_arrows(what);
draw_overlay_icons(what);
draw_buttons(what);
draw_fine_motion(what);
}
bool StatusScreen::onTouchStart(uint8_t) {
increment = fine_motion ? 0.25 : 1;
return true;
}
bool StatusScreen::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1:
case 2:
case 3:
case 4:
case 12:
if (!jog_xy) {
jog_xy = true;
injectCommands_P(PSTR("M17"));
}
break;
case 9:
#if ENABLED(USB_FLASH_DRIVE_SUPPORT) && defined(LULZBOT_MANUAL_USB_STARTUP)
if (!Sd2Card::ready()) {
StatusScreen::setStatusMessage(F("Insert USB drive..."));
Sd2Card::usbStartup();
} else {
GOTO_SCREEN(FilesScreen);
}
#else
GOTO_SCREEN(FilesScreen);
#endif
break;
case 10: GOTO_SCREEN(MainMenu); break;
case 13: SpinnerDialogBox::enqueueAndWait_P(F("G112")); break;
case 14: SpinnerDialogBox::enqueueAndWait_P(F("G28 Z")); break;
case 15: GOTO_SCREEN(TemperatureScreen); break;
case 16: fine_motion = !fine_motion; break;
default: return false;
}
// If a passcode is enabled, the LockScreen will prevent the
// user from proceeding.
LockScreen::check_passcode();
return true;
}
bool StatusScreen::onTouchHeld(uint8_t tag) {
if (tag >= 1 && tag <= 4 && !jog_xy) return false;
if (ExtUI::isMoving()) return false; // Don't allow moves to accumulate
#define UI_INCREMENT_AXIS(axis) MoveAxisScreen::setManualFeedrate(axis, increment); UI_INCREMENT(AxisPosition_mm, axis);
#define UI_DECREMENT_AXIS(axis) MoveAxisScreen::setManualFeedrate(axis, increment); UI_DECREMENT(AxisPosition_mm, axis);
switch (tag) {
case 1: UI_DECREMENT_AXIS(X); break;
case 2: UI_INCREMENT_AXIS(X); break;
case 4: UI_DECREMENT_AXIS(Y); break; // NOTE: Y directions inverted because bed rather than needle moves
case 3: UI_INCREMENT_AXIS(Y); break;
case 5: UI_DECREMENT_AXIS(Z); break;
case 6: UI_INCREMENT_AXIS(Z); break;
case 7: UI_DECREMENT_AXIS(E0); break;
case 8: UI_INCREMENT_AXIS(E0); break;
default: return false;
}
#undef UI_DECREMENT_AXIS
#undef UI_INCREMENT_AXIS
if (increment < 10 && !fine_motion)
increment += 0.5;
current_screen.onRefresh();
return false;
}
void StatusScreen::setStatusMessage(progmem_str pstr) {
BioPrintingDialogBox::setStatusMessage(pstr);
}
void StatusScreen::setStatusMessage(const char * const str) {
BioPrintingDialogBox::setStatusMessage(str);
}
void StatusScreen::onIdle() {
if (isPrintingFromMedia())
BioPrintingDialogBox::show();
if (refresh_timer.elapsed(STATUS_UPDATE_INTERVAL)) {
onRefresh();
refresh_timer.start();
}
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,87 @@
/*********************
* bio_tune_menu.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && defined(LULZBOT_USE_BIOPRINTER_UI)
#include "screens.h"
using namespace FTDI;
using namespace Theme;
using namespace ExtUI;
void TuneMenu::onRedraw(draw_mode_t what) {
if (what & BACKGROUND) {
CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(CLEAR(true,true,true))
.font(font_medium);
}
#define GRID_ROWS 8
#define GRID_COLS 2
if (what & FOREGROUND) {
CommandProcessor cmd;
cmd.cmd(COLOR_RGB(bg_text_enabled))
.font(font_large).text ( BTN_POS(1,1), BTN_SIZE(2,1), F("Print Menu"))
.colors(normal_btn)
.font(font_medium)
.enabled(!isPrinting()).tag(2).button( BTN_POS(1,2), BTN_SIZE(2,1), isPrinting() ? F("Printing...") : F("Print Again"))
.enabled( isPrinting()).tag(3).button( BTN_POS(1,3), BTN_SIZE(2,1), F("Print Speed"))
.tag(4).button( BTN_POS(1,4), BTN_SIZE(2,1), F("Bed Temperature"))
#if ENABLED(BABYSTEPPING)
.enabled(true)
#else
.enabled(false)
#endif
.tag(5).button( BTN_POS(1,5), BTN_SIZE(2,1), F("Nudge Nozzle"))
.enabled(!isPrinting()).tag(6).button( BTN_POS(1,6), BTN_SIZE(2,1), F("Load Syringe"))
.enabled(!isPrinting()).tag(7).button( BTN_POS(1,7), BTN_SIZE(2,1), F("Unlock XY Axis"))
.colors(action_btn) .tag(1).button( BTN_POS(1,8), BTN_SIZE(2,1), F("Back"));
}
#undef GRID_COLS
#undef GRID_ROWS
}
bool TuneMenu::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1: GOTO_PREVIOUS(); break;
case 2: {
FileList files;
printFile(files.shortFilename());
GOTO_PREVIOUS();
break;
}
case 3: GOTO_SCREEN(FeedratePercentScreen); break;
case 4: GOTO_SCREEN(TemperatureScreen); break;
case 5: GOTO_SCREEN(NudgeNozzleScreen); break;
case 6: GOTO_SCREEN(BioConfirmHomeXYZ); break;
case 7: StatusScreen::unlockMotors(); break;
default:
return false;
}
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,113 @@
/*******************
* boot_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
#include "../ftdi_eve_lib/extras/poly_ui.h"
#include "../archim2-flash/flash_storage.h"
#ifdef TOUCH_UI_PORTRAIT
#include "../theme/bootscreen_logo_portrait.h"
#else
#include "../theme/bootscreen_logo_landscape.h"
#endif
using namespace FTDI;
void BootScreen::onRedraw(draw_mode_t) {
CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(0x000000));
cmd.cmd(CLEAR(true,true,true));
CLCD::turn_on_backlight();
SoundPlayer::set_volume(255);
}
void BootScreen::onIdle() {
if (CLCD::is_touching()) {
// If the user is touching the screen at startup, then
// assume the user wants to re-calibrate the screen.
// This gives the user the ability to recover a
// miscalibration that has been stored to EEPROM.
// Also reset display parameters to defaults, just
// in case the display is borked.
InterfaceSettingsScreen::failSafeSettings();
GOTO_SCREEN(TouchCalibrationScreen);
current_screen.forget();
PUSH_SCREEN(StatusScreen);
} else {
if (!UIFlashStorage::is_valid()) {
SpinnerDialogBox::show(F("Please wait..."));
UIFlashStorage::format_flash();
SpinnerDialogBox::hide();
}
if (UIData::animations_enabled()) {
// If there is a startup video in the flash SPI, play
// that, otherwise show a static splash screen.
if (!MediaPlayerScreen::playBootMedia())
showSplashScreen();
}
#ifdef LULZBOT_USE_BIOPRINTER_UI
GOTO_SCREEN(BioConfirmHomeXYZ);
current_screen.forget();
PUSH_SCREEN(StatusScreen);
PUSH_SCREEN(BioConfirmHomeE);
#else
GOTO_SCREEN(StatusScreen);
#endif
}
}
void BootScreen::showSplashScreen() {
CommandProcessor cmd;
cmd.cmd(CMD_DLSTART);
cmd.cmd(CLEAR_COLOR_RGB(0xDEEA5C));
cmd.cmd(CLEAR(true,true,true));
#define POLY(A) PolyUI::poly_reader_t(A, sizeof(A)/sizeof(A[0]))
PolyUI ui(cmd);
cmd.cmd(COLOR_RGB(0xC1D82F));
ui.fill(POLY(logo_green));
cmd.cmd(COLOR_RGB(0x000000));
ui.fill(POLY(logo_black));
ui.fill(POLY(logo_type));
ui.fill(POLY(logo_mark));
cmd.cmd(COLOR_RGB(0xFFFFFF));
ui.fill(POLY(logo_white));
cmd.cmd(DL::DL_DISPLAY);
cmd.cmd(CMD_SWAP);
cmd.execute();
ExtUI::delay_ms(2500);
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,323 @@
/******************************
* change_filament_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
#include "screen_data.h"
using namespace ExtUI;
using namespace FTDI;
using namespace Theme;
#define COOL_TEMP 40
#define LOW_TEMP 180
#define MED_TEMP 200
#define HIGH_TEMP 220
/****************** COLOR SCALE ***********************/
uint32_t getWarmColor(uint16_t temp, uint16_t cool, uint16_t low, uint16_t med, uint16_t high) {
rgb_t R0, R1, mix;
float t;
if (temp < cool) {
R0 = cool_rgb;
R1 = low_rgb;
t = 0;
}
else if (temp < low) {
R0 = cool_rgb;
R1 = low_rgb;
t = (float(temp)-cool)/(low-cool);
}
else if (temp < med) {
R0 = low_rgb;
R1 = med_rgb;
t = (float(temp)-low)/(med-low);
}
else if (temp < high) {
R0 = med_rgb;
R1 = high_rgb;
t = (float(temp)-med)/(high-med);
}
else if (temp >= high) {
R0 = med_rgb;
R1 = high_rgb;
t = 1;
}
rgb_t::lerp(t, R0, R1, mix);
return mix;
}
void ChangeFilamentScreen::drawTempGradient(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
CommandProcessor cmd;
cmd.cmd(SCISSOR_XY (x, y))
.cmd(SCISSOR_SIZE (w, h/2))
.gradient (x, y, high_rgb, x, y+h/2, med_rgb)
.cmd(SCISSOR_XY (x, y+h/2))
.cmd(SCISSOR_SIZE (w, h/2))
.gradient (x, y+h/2, med_rgb, x, y+h, low_rgb)
.cmd(SCISSOR_XY ())
.cmd(SCISSOR_SIZE ());
}
void ChangeFilamentScreen::onEntry() {
screen_data.ChangeFilamentScreen.e_tag = ExtUI::getActiveTool() + 10;
screen_data.ChangeFilamentScreen.t_tag = 0;
screen_data.ChangeFilamentScreen.repeat_tag = 0;
screen_data.ChangeFilamentScreen.saved_extruder = getActiveTool();
}
void ChangeFilamentScreen::onExit() {
setActiveTool(screen_data.ChangeFilamentScreen.saved_extruder, true);
}
void ChangeFilamentScreen::onRedraw(draw_mode_t what) {
CommandProcessor cmd;
#ifdef TOUCH_UI_PORTRAIT
#define GRID_COLS 2
#define GRID_ROWS 11
#else
#define GRID_COLS 4
#define GRID_ROWS 6
#endif
if (what & BACKGROUND) {
cmd.cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(CLEAR(true,true,true))
.tag(0)
#ifdef TOUCH_UI_PORTRAIT
.font(font_large)
#else
.font(font_medium)
#endif
.text(BTN_POS(1,1), BTN_SIZE(2,1), F("Extruder Selection:"))
#ifdef TOUCH_UI_PORTRAIT
.text(BTN_POS(1,7), BTN_SIZE(1,1), F("Current Temp:"))
#else
.text(BTN_POS(3,1), BTN_SIZE(2,1), F("Current Temp:"))
.font(font_small)
#endif
.text(BTN_POS(1,3), BTN_SIZE(2,1), F("Removal Temp:"));
drawTempGradient(BTN_POS(1,4), BTN_SIZE(1,3));
}
if (what & FOREGROUND) {
char e_str[15];
const char *idle = PSTR("%-3d C / idle");
const char *not_idle = PSTR("%-3d / %-3d C");
sprintf_P(
e_str,
isHeaterIdle(getExtruder()) ? idle : not_idle,
ROUND(getActualTemp_celsius(getExtruder())),
ROUND(getTargetTemp_celsius(getExtruder()))
);
const rgb_t tcol = getWarmColor(getActualTemp_celsius(getExtruder()), COOL_TEMP, LOW_TEMP, MED_TEMP, HIGH_TEMP);
cmd.cmd(COLOR_RGB(tcol))
.tag(15)
#ifdef TOUCH_UI_PORTRAIT
.rectangle(BTN_POS(2,7), BTN_SIZE(1,1))
#else
.rectangle(BTN_POS(3,2), BTN_SIZE(2,1))
#endif
.cmd(COLOR_RGB(tcol.luminance() > 128 ? 0x000000 : 0xFFFFFF))
.font(font_medium)
#ifdef TOUCH_UI_PORTRAIT
.text(BTN_POS(2,7), BTN_SIZE(1,1), e_str)
#else
.text(BTN_POS(3,2), BTN_SIZE(2,1), e_str)
#endif
.colors(normal_btn);
const bool t_ok = getActualTemp_celsius(getExtruder()) > getSoftenTemp() - 10;
if (screen_data.ChangeFilamentScreen.t_tag && !t_ok) {
cmd.text(BTN_POS(1,6), BTN_SIZE(1,1), F("Heating..."));
} else if (getActualTemp_celsius(getExtruder()) > 100) {
cmd.cmd(COLOR_RGB(0xFF0000))
.text(BTN_POS(1,4), BTN_SIZE(1,1), F("Caution:"))
.colors(normal_btn)
.text(BTN_POS(1,6), BTN_SIZE(1,1), F("Hot!"));
}
#define TOG_STYLE(A) colors(A ? action_btn : normal_btn)
const bool tog2 = screen_data.ChangeFilamentScreen.t_tag == 2;
const bool tog3 = screen_data.ChangeFilamentScreen.t_tag == 3;
const bool tog4 = screen_data.ChangeFilamentScreen.t_tag == 4;
const bool tog10 = screen_data.ChangeFilamentScreen.e_tag == 10;
#if HOTENDS > 1
const bool tog11 = screen_data.ChangeFilamentScreen.e_tag == 11;
#endif
#ifdef TOUCH_UI_PORTRAIT
cmd.font(font_large)
#else
cmd.font(font_medium)
#endif
.TOG_STYLE(tog10)
.tag(10) .button (BTN_POS(1,2), BTN_SIZE(1,1), F("1"))
#if HOTENDS < 2
.enabled(false)
#else
.TOG_STYLE(tog11)
#endif
.tag(11) .button (BTN_POS(2,2), BTN_SIZE(1,1), F("2"));
if (!t_ok) reset_menu_timeout();
const bool tog7 = screen_data.ChangeFilamentScreen.repeat_tag == 7;
const bool tog8 = screen_data.ChangeFilamentScreen.repeat_tag == 8;
#ifdef TOUCH_UI_PORTRAIT
cmd.font(font_large)
#else
cmd.font(font_small)
#endif
.tag(2) .TOG_STYLE(tog2) .button (BTN_POS(2,6), BTN_SIZE(1,1), F( STRINGIFY(LOW_TEMP) "C (PLA)"))
.tag(3) .TOG_STYLE(tog3) .button (BTN_POS(2,5), BTN_SIZE(1,1), F( STRINGIFY(MED_TEMP) "C (ABS)"))
.tag(4) .TOG_STYLE(tog4) .button (BTN_POS(2,4), BTN_SIZE(1,1), F( STRINGIFY(HIGH_TEMP) "C (High)"))
.colors(normal_btn)
// Add tags to color gradient
.cmd(COLOR_MASK(0,0,0,0))
.tag(2) .rectangle(BTN_POS(1,6), BTN_SIZE(1,1))
.tag(3) .rectangle(BTN_POS(1,5), BTN_SIZE(1,1))
.tag(4) .rectangle(BTN_POS(1,4), BTN_SIZE(1,1))
.cmd(COLOR_MASK(1,1,1,1))
.cmd(COLOR_RGB(t_ok ? bg_text_enabled : bg_text_disabled))
#ifdef TOUCH_UI_PORTRAIT
.font(font_large)
.tag(0) .text (BTN_POS(1,8), BTN_SIZE(1,1), F("Unload"))
.text (BTN_POS(2,8), BTN_SIZE(1,1), F("Load/Extrude"))
.tag(5) .enabled(t_ok).button (BTN_POS(1,9), BTN_SIZE(1,1), F("Momentary"))
.tag(6) .enabled(t_ok).button (BTN_POS(2,9), BTN_SIZE(1,1), F("Momentary"))
.tag(7).TOG_STYLE(tog7).enabled(t_ok).button (BTN_POS(1,10), BTN_SIZE(1,1), F("Continuous"))
.tag(8).TOG_STYLE(tog8).enabled(t_ok).button (BTN_POS(2,10), BTN_SIZE(1,1), F("Continuous"))
.tag(1).colors(action_btn) .button (BTN_POS(1,11), BTN_SIZE(2,1), F("Back"));
#else
.font(font_small)
.tag(0) .text (BTN_POS(3,3), BTN_SIZE(1,1), F("Unload"))
.text (BTN_POS(4,3), BTN_SIZE(1,1), F("Load/Extrude"))
.tag(5) .enabled(t_ok).button (BTN_POS(3,4), BTN_SIZE(1,1), F("Momentary"))
.tag(6) .enabled(t_ok).button (BTN_POS(4,4), BTN_SIZE(1,1), F("Momentary"))
.tag(7).TOG_STYLE(tog7).enabled(t_ok).button (BTN_POS(3,5), BTN_SIZE(1,1), F("Continuous"))
.tag(8).TOG_STYLE(tog8).enabled(t_ok).button (BTN_POS(4,5), BTN_SIZE(1,1), F("Continuous"))
.font(font_medium)
.tag(1).colors(action_btn) .button (BTN_POS(3,6), BTN_SIZE(2,1), F("Back"));
#endif
}
#undef GRID_COLS
#undef GRID_ROWS
}
uint8_t ChangeFilamentScreen::getSoftenTemp() {
switch (screen_data.ChangeFilamentScreen.t_tag) {
case 2: return LOW_TEMP;
case 3: return MED_TEMP;
case 4: return HIGH_TEMP;
default: return EXTRUDE_MINTEMP;
}
}
ExtUI::extruder_t ChangeFilamentScreen::getExtruder() {
switch (screen_data.ChangeFilamentScreen.e_tag) {
case 13: return ExtUI::E3;
case 12: return ExtUI::E2;
case 11: return ExtUI::E1;
default: return ExtUI::E0;
}
}
bool ChangeFilamentScreen::onTouchStart(uint8_t tag) {
// Make the Momentary and Continuous buttons slightly more responsive
switch (tag) {
case 5: case 6: case 7: case 8:
return ChangeFilamentScreen::onTouchHeld(tag);
default:
return false;
}
}
bool ChangeFilamentScreen::onTouchEnd(uint8_t tag) {
using namespace ExtUI;
switch (tag) {
case 1: GOTO_PREVIOUS(); break;
case 2:
case 3:
case 4:
// Change temperature
screen_data.ChangeFilamentScreen.t_tag = tag;
setTargetTemp_celsius(getSoftenTemp(), getExtruder());
break;
case 7:
screen_data.ChangeFilamentScreen.repeat_tag = (screen_data.ChangeFilamentScreen.repeat_tag == 7) ? 0 : 7;
break;
case 8:
screen_data.ChangeFilamentScreen.repeat_tag = (screen_data.ChangeFilamentScreen.repeat_tag == 8) ? 0 : 8;
break;
case 10:
case 11:
// Change extruder
screen_data.ChangeFilamentScreen.e_tag = tag;
screen_data.ChangeFilamentScreen.t_tag = 0;
screen_data.ChangeFilamentScreen.repeat_tag = 0;
setActiveTool(getExtruder(), true);
break;
case 15: GOTO_SCREEN(TemperatureScreen); break;
}
return true;
}
bool ChangeFilamentScreen::onTouchHeld(uint8_t tag) {
if (ExtUI::isMoving()) return false; // Don't allow moves to accumulate
constexpr float increment = 1;
#define UI_INCREMENT_AXIS(axis) MoveAxisScreen::setManualFeedrate(axis, increment); UI_INCREMENT(AxisPosition_mm, axis);
#define UI_DECREMENT_AXIS(axis) MoveAxisScreen::setManualFeedrate(axis, increment); UI_DECREMENT(AxisPosition_mm, axis);
switch (tag) {
case 5: case 7: UI_DECREMENT_AXIS(getExtruder()); break;
case 6: case 8: UI_INCREMENT_AXIS(getExtruder()); break;
default: return false;
}
#undef UI_DECREMENT_AXIS
#undef UI_INCREMENT_AXIS
return false;
}
void ChangeFilamentScreen::onIdle() {
if (screen_data.ChangeFilamentScreen.repeat_tag) onTouchHeld(screen_data.ChangeFilamentScreen.repeat_tag);
if (refresh_timer.elapsed(STATUS_UPDATE_INTERVAL)) {
onRefresh();
refresh_timer.start();
}
BaseScreen::onIdle();
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,47 @@
/**************************************
* confirm_abort_print_dialog_box.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
using namespace ExtUI;
void ConfirmAbortPrintDialogBox::onRedraw(draw_mode_t) {
drawMessage(F("Are you sure you want to cancel the print?"));
drawYesNoButtons();
}
bool ConfirmAbortPrintDialogBox::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1:
GOTO_PREVIOUS();
stopPrint();
return true;
default:
return DialogBoxBaseClass::onTouchEnd(tag);
}
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,48 @@
/*******************************************
* confirm_auto_calibration_dialog_box.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && ENABLED(CALIBRATION_GCODE)
#include "screens.h"
using namespace ExtUI;
using namespace Theme;
void ConfirmAutoCalibrationDialogBox::onRedraw(draw_mode_t) {
drawMessage(F("For best results, unload the filament and clean the hotend prior to starting calibration. Continue?"));
drawYesNoButtons();
}
bool ConfirmAutoCalibrationDialogBox::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1:
GOTO_SCREEN(StatusScreen);
injectCommands_P(PSTR(LULZBOT_CALIBRATION_COMMANDS));
return true;
default:
return DialogBoxBaseClass::onTouchEnd(tag);
}
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,54 @@
/**************************************
* confirm_erase_flash_dialog_box.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && ENABLED(DEVELOPER_SCREENS)
#include "screens.h"
#include "../archim2-flash/flash_storage.h"
using namespace FTDI;
void ConfirmEraseFlashDialogBox::onRedraw(draw_mode_t) {
drawMessage(F("Are you sure? SPI flash will be erased."));
drawYesNoButtons();
}
bool ConfirmEraseFlashDialogBox::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1:
SpinnerDialogBox::show(F("Erasing..."));
UIFlashStorage::format_flash();
SpinnerDialogBox::hide();
AlertDialogBox::show(F("SPI flash erased"));
// Remove ConfirmEraseFlashDialogBox from the stack
// so the alert box doesn't return to me.
current_screen.forget();
return true;
default:
return DialogBoxBaseClass::onTouchEnd(tag);
}
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,58 @@
/**************************************
* confirm_user_request_alert_box.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
#include "screen_data.h"
using namespace FTDI;
void ConfirmUserRequestAlertBox::onRedraw(draw_mode_t mode) {
AlertDialogBox::onRedraw(mode); // Required for the GOTO_SCREEN function to work
}
bool ConfirmUserRequestAlertBox::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1:
ExtUI::setUserConfirmed();
GOTO_PREVIOUS();
return true;
case 2: GOTO_PREVIOUS(); return true;
default: return false;
}
}
void ConfirmUserRequestAlertBox::show(const char* msg) {
drawMessage(msg);
storeBackground();
screen_data.AlertDialogBox.isError = false;
GOTO_SCREEN(ConfirmUserRequestAlertBox);
}
void ConfirmUserRequestAlertBox::hide() {
if (AT_SCREEN(ConfirmUserRequestAlertBox))
GOTO_PREVIOUS();
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,63 @@
/***********************************
* default_acceleration_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
using namespace FTDI;
using namespace ExtUI;
using namespace Theme;
void DefaultAccelerationScreen::onRedraw(draw_mode_t what) {
widgets_t w(what);
w.precision(0);
w.units(PSTR("mm/s^2"));
w.heading( PSTR("Default Acceleration"));
w.color(other);
w.adjuster( 2, PSTR("Printing:"), getPrintingAcceleration_mm_s2() );
w.adjuster( 4, PSTR("Travel:"), getTravelAcceleration_mm_s2() );
w.adjuster( 6, PSTR("Retraction:"), getRetractAcceleration_mm_s2() );
w.increments();
w.button( 8, PSTR("Set Axis Maximum"));
}
bool DefaultAccelerationScreen::onTouchHeld(uint8_t tag) {
const float increment = getIncrement();
switch (tag) {
case 2: UI_DECREMENT(PrintingAcceleration_mm_s2); break;
case 3: UI_INCREMENT(PrintingAcceleration_mm_s2); break;
case 4: UI_DECREMENT(TravelAcceleration_mm_s2); break;
case 5: UI_INCREMENT(TravelAcceleration_mm_s2); break;
case 6: UI_DECREMENT(RetractAcceleration_mm_s2); break;
case 7: UI_INCREMENT(RetractAcceleration_mm_s2); break;
case 8: GOTO_SCREEN(MaxAccelerationScreen); break;
default:
return false;
}
SaveSettingsDialogBox::settingsChanged();
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,150 @@
/**********************
* developer_menu.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && ENABLED(DEVELOPER_SCREENS)
#include "screens.h"
#include "../archim2-flash/flash_storage.h"
using namespace FTDI;
using namespace Theme;
void DeveloperMenu::onRedraw(draw_mode_t what) {
if (what & BACKGROUND) {
CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(CLEAR(true,true,true))
.font(font_medium)
.tag(0);
#ifdef SPI_FLASH_SS
constexpr bool has_flash = true;
#else
constexpr bool has_flash = false;
#endif
#if ENABLED(SDSUPPORT)
constexpr bool has_media = true;
#else
constexpr bool has_media = false;
#endif
cmd.cmd(COLOR_RGB(bg_text_enabled));
#ifdef TOUCH_UI_PORTRAIT
#define GRID_ROWS 10
#define GRID_COLS 1
cmd.font(font_large) .text ( BTN_POS(1,1), BTN_SIZE(1,1), F("Developer Menu"))
.colors(normal_btn)
.tag(2).font(font_medium) .button( BTN_POS(1,2), BTN_SIZE(1,1), F("Show All Widgets"))
.tag(3) .button( BTN_POS(1,3), BTN_SIZE(1,1), F("Stress Test"))
.tag(4) .button( BTN_POS(1,4), BTN_SIZE(1,1), F("Show Touch Registers"))
.tag(5) .button( BTN_POS(1,5), BTN_SIZE(1,1), F("Play Song"))
.tag(6).enabled(has_media).button( BTN_POS(1,6), BTN_SIZE(1,1), F("Play Video from Media"))
.tag(7).enabled(has_flash).button( BTN_POS(1,7), BTN_SIZE(1,1), F("Play Video from SPI Flash"))
.tag(8).enabled(has_flash).button( BTN_POS(1,8), BTN_SIZE(1,1), F("Load Video to SPI Flash"))
.tag(9).enabled(has_flash).button( BTN_POS(1,9), BTN_SIZE(1,1), F("Erase SPI Flash"))
.tag(1).colors(action_btn)
.button( BTN_POS(1,10), BTN_SIZE(1,1), F("Back"));
#else
#define GRID_ROWS 6
#define GRID_COLS 2
cmd.font(font_medium) .text ( BTN_POS(1,1), BTN_SIZE(2,1), F("Developer Menu"))
.colors(normal_btn)
.tag(2).font(font_small) .button( BTN_POS(1,2), BTN_SIZE(1,1), F("Show All Widgets"))
.tag(3) .button( BTN_POS(1,3), BTN_SIZE(1,1), F("Show Touch Registers"))
.tag(9) .button( BTN_POS(1,4), BTN_SIZE(1,1), F("Show Pin States"))
.tag(4) .button( BTN_POS(1,5), BTN_SIZE(1,1), F("Play Song"))
.tag(5).enabled(has_media).button( BTN_POS(2,2), BTN_SIZE(1,1), F("Play Video from Media"))
.tag(6).enabled(has_flash).button( BTN_POS(2,3), BTN_SIZE(1,1), F("Play Video from SPI Flash"))
.tag(7).enabled(has_flash).button( BTN_POS(2,4), BTN_SIZE(1,1), F("Load Video to SPI Flash"))
.tag(8).enabled(has_flash).button( BTN_POS(2,5), BTN_SIZE(1,1), F("Erase SPI Flash"))
.tag(1).colors(action_btn)
.button( BTN_POS(1,6), BTN_SIZE(2,1), F("Back"));
#endif
}
}
bool DeveloperMenu::onTouchEnd(uint8_t tag) {
using namespace Theme;
switch (tag) {
case 1: GOTO_PREVIOUS(); break;
case 2: GOTO_SCREEN(WidgetsScreen); break;
case 3:
PUSH_SCREEN(StressTestScreen);
AlertDialogBox::show(F("Please do not run this test unattended as it may cause your printer to malfunction."));
current_screen.forget();
break;
case 4: GOTO_SCREEN(TouchRegistersScreen); break;
case 5: sound.play(js_bach_joy, PLAY_ASYNCHRONOUS); break;
#if ENABLED(SDSUPPORT)
case 6:
if (!MediaPlayerScreen::playCardMedia())
AlertDialogBox::showError(F("Cannot open STARTUP.AVI"));
break;
#endif
#ifdef SPI_FLASH_SS
case 7:
if (!MediaPlayerScreen::playBootMedia())
AlertDialogBox::showError(F("No boot media available"));
break;
case 8:
{
SpinnerDialogBox::show(F("Saving..."));
UIFlashStorage::error_t res = UIFlashStorage::write_media_file(F("STARTUP.AVI"));
SpinnerDialogBox::hide();
reset_menu_timeout();
switch (res) {
case UIFlashStorage::SUCCESS:
AlertDialogBox::show(F("File copied!"));
break;
case UIFlashStorage::READ_ERROR:
AlertDialogBox::showError(F("Failed to read file"));
break;
case UIFlashStorage::VERIFY_ERROR:
AlertDialogBox::showError(F("Failed to verify file"));
break;
case UIFlashStorage::FILE_NOT_FOUND:
AlertDialogBox::showError(F("Cannot open STARTUP.AVI"));
break;
case UIFlashStorage::WOULD_OVERWRITE:
AlertDialogBox::showError(F("Cannot overwrite existing media."));
break;
}
break;
}
case 9: GOTO_SCREEN(ConfirmEraseFlashDialogBox); break;
#endif
case 10: GOTO_SCREEN(EndstopStatesScreen); break;
default: return false;
}
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,83 @@
/*****************************
* dialog_box_base_class.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
using namespace FTDI;
using namespace Theme;
#define GRID_COLS 2
#define GRID_ROWS 8
template<typename T>
void DialogBoxBaseClass::drawMessage(const T message, int16_t font) {
CommandProcessor cmd;
cmd.cmd(CMD_DLSTART)
.cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(CLEAR(true,true,true))
.cmd(COLOR_RGB(bg_text_enabled))
.tag(0);
draw_text_box(cmd, BTN_POS(1,1), BTN_SIZE(2,3), message, OPT_CENTER, font ? font : font_large);
cmd.colors(normal_btn);
}
template void DialogBoxBaseClass::drawMessage(const char *, int16_t font);
template void DialogBoxBaseClass::drawMessage(const progmem_str, int16_t font);
void DialogBoxBaseClass::drawYesNoButtons(uint8_t default_btn) {
CommandProcessor cmd;
cmd.font(font_medium)
.colors(default_btn == 1 ? action_btn : normal_btn).tag(1).button( BTN_POS(1,8), BTN_SIZE(1,1), F("Yes"))
.colors(default_btn == 2 ? action_btn : normal_btn).tag(2).button( BTN_POS(2,8), BTN_SIZE(1,1), F("No"));
}
void DialogBoxBaseClass::drawOkayButton() {
CommandProcessor cmd;
cmd.font(font_medium)
.tag(1).button( BTN_POS(1,8), BTN_SIZE(2,1), F("Okay"));
}
void DialogBoxBaseClass::drawButton(const progmem_str label) {
CommandProcessor cmd;
cmd.font(font_medium)
.tag(1).button( BTN_POS(1,8), BTN_SIZE(2,1), label);
}
void DialogBoxBaseClass::drawSpinner() {
CommandProcessor cmd;
cmd.cmd(COLOR_RGB(bg_text_enabled))
.spinner(BTN_POS(1,4), BTN_SIZE(2,3)).execute();
}
bool DialogBoxBaseClass::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1: GOTO_PREVIOUS(); return true;
case 2: GOTO_PREVIOUS(); return true;
default: return false;
}
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,61 @@
/*****************************
* display_tuning_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
using namespace FTDI;
using namespace Theme;
void DisplayTuningScreen::onRedraw(draw_mode_t what) {
widgets_t w(what);
w.precision(0, BaseNumericAdjustmentScreen::DEFAULT_LOWEST);
w.units(PSTR(""));
w.heading( PSTR("Display Tuning"));
w.color(other);
w.adjuster( 2, PSTR("H Offset:"), CLCD::mem_read_16(CLCD::REG::HOFFSET) );
w.adjuster( 4, PSTR("V Offset:"), CLCD::mem_read_16(CLCD::REG::VOFFSET) );
w.increments();
w.heading( PSTR("Touch Screen"));
w.button(6, PSTR("Calibrate"));
}
bool DisplayTuningScreen::onTouchHeld(uint8_t tag) {
#define REG_INCREMENT(a,i) CLCD::mem_write_16(CLCD::REG::a, CLCD::mem_read_16(CLCD::REG::a) + i)
const float increment = getIncrement();
switch (tag) {
case 2: REG_INCREMENT(HOFFSET, -increment); break;
case 3: REG_INCREMENT(HOFFSET, increment); break;
case 4: REG_INCREMENT(VOFFSET, -increment); break;
case 5: REG_INCREMENT(VOFFSET, increment); break;
case 6: GOTO_SCREEN(TouchCalibrationScreen); break;
default:
return false;
}
SaveSettingsDialogBox::settingsChanged();
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,155 @@
/****************************
* endstop_state_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
using namespace FTDI;
using namespace Theme;
using namespace ExtUI;
void EndstopStatesScreen::onEntry() {
BaseScreen::onEntry();
#ifdef LULZBOT_SET_PROBE_PINS_STATE
LULZBOT_SET_PROBE_PINS_STATE(true)
#endif
}
void EndstopStatesScreen::onExit() {
BaseScreen::onExit();
#ifdef LULZBOT_SET_PROBE_PINS_STATE
LULZBOT_SET_PROBE_PINS_STATE(false)
#endif
}
void EndstopStatesScreen::onRedraw(draw_mode_t) {
CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(COLOR_RGB(bg_text_enabled))
.cmd(CLEAR(true,true,true))
.tag(0);
#define GRID_ROWS 7
#define GRID_COLS 6
#define PIN_BTN(X,Y,PIN,LABEL) button(BTN_POS(X,Y), BTN_SIZE(2,1), F(LABEL))
#define PIN_ENABLED(LABEL,PIN,INV,X,Y) cmd.enabled(1).colors(READ(PIN##_PIN) != INV ? action_btn : normal_btn).PIN_BTN(X,Y,PIN,LABEL);
#define PIN_DISABLED(LABEL,PIN,INV,X,Y) cmd.enabled(0).PIN_BTN(X,Y,PIN,LABEL);
#ifdef TOUCH_UI_PORTRAIT
cmd.font(font_large)
#else
cmd.font(font_medium)
#endif
.text(BTN_POS(1,1), BTN_SIZE(6,1), F("Endstop States:"))
.font(font_tiny);
#if PIN_EXISTS(X_MAX)
PIN_ENABLED ("X Max", X_MAX,X_MAX_ENDSTOP_INVERTING,1,2)
#else
PIN_DISABLED("X Max",X_MAX,X_MAX_ENDSTOP_INVERTING,1,2)
#endif
#if PIN_EXISTS(Y_MAX)
PIN_ENABLED ("Y Max",Y_MAX,Y_MAX_ENDSTOP_INVERTING,3,2)
#else
PIN_DISABLED("Y Max",Y_MAX,Y_MAX_ENDSTOP_INVERTING,3,2)
#endif
#if PIN_EXISTS(Z_MAX)
PIN_ENABLED ("Z Max",Z_MAX,Z_MAX_ENDSTOP_INVERTING,5,2)
#else
PIN_DISABLED("Z Max",Z_MAX,Z_MAX_ENDSTOP_INVERTING,5,2)
#endif
#if PIN_EXISTS(X_MIN)
PIN_ENABLED ("X Min",X_MIN,X_MIN_ENDSTOP_INVERTING,1,3)
#else
PIN_DISABLED("X Min",X_MIN,X_MIN_ENDSTOP_INVERTING,1,3)
#endif
#if PIN_EXISTS(Y_MIN)
PIN_ENABLED ("Y Min",Y_MIN,Y_MIN_ENDSTOP_INVERTING,3,3)
#else
PIN_DISABLED("Y Min",Y_MIN,Y_MIN_ENDSTOP_INVERTING,3,3)
#endif
#if PIN_EXISTS(Z_MIN)
PIN_ENABLED ("Z Min",Z_MIN,Z_MIN_ENDSTOP_INVERTING,5,3)
#else
PIN_DISABLED("Z Min",Z_MIN,Z_MIN_ENDSTOP_INVERTING,5,3)
#endif
#if ENABLED(FILAMENT_RUNOUT_SENSOR) && PIN_EXISTS(FIL_RUNOUT)
PIN_ENABLED ("Runout 1",FIL_RUNOUT, FIL_RUNOUT_INVERTING,1,4)
#else
PIN_DISABLED("Runout 1",FIL_RUNOUT, FIL_RUNOUT_INVERTING,1,4)
#endif
#if ENABLED(FILAMENT_RUNOUT_SENSOR) && PIN_EXISTS(FIL_RUNOUT2)
PIN_ENABLED ("Runout 2",FIL_RUNOUT2,FIL_RUNOUT_INVERTING,3,4)
#else
PIN_DISABLED("Runout 2",FIL_RUNOUT2,FIL_RUNOUT_INVERTING,3,4)
#endif
#if PIN_EXISTS(Z_MIN_PROBE)
PIN_ENABLED ("Z Probe",Z_MIN_PROBE,Z_MIN_PROBE_ENDSTOP_INVERTING,5,4)
#else
PIN_DISABLED("Z Probe",Z_MIN_PROBE,Z_MIN_PROBE_ENDSTOP_INVERTING,5,4)
#endif
#if HAS_SOFTWARE_ENDSTOPS
#undef EDGE_R
#define EDGE_R 30
cmd.font(font_small)
.text (BTN_POS(1,5), BTN_SIZE(3,1), F("Soft Limits:"), OPT_RIGHTX | OPT_CENTERY)
.colors(ui_toggle)
.tag(2).toggle(BTN_POS(4,5), BTN_SIZE(3,1), F("off\xFFon"), getSoftEndstopState());
#undef EDGE_R
#define EDGE_R 0
#endif
cmd.font(font_medium)
.colors(action_btn)
.tag(1).button( BTN_POS(1,7), BTN_SIZE(6,1), F("Back"));
#undef GRID_COLS
#undef GRID_ROWS
}
bool EndstopStatesScreen::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1: GOTO_PREVIOUS(); break;
#if HAS_SOFTWARE_ENDSTOPS
case 2: setSoftEndstopState(!getSoftEndstopState());
#endif
default:
return false;
}
return true;
}
void EndstopStatesScreen::onIdle() {
constexpr uint32_t DIAGNOSTICS_UPDATE_INTERVAL = 100;
if (refresh_timer.elapsed(DIAGNOSTICS_UPDATE_INTERVAL)) {
onRefresh();
refresh_timer.start();
reset_menu_timeout();
}
BaseScreen::onIdle();
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,52 @@
/*******************************
* feedrate_percent_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
using namespace FTDI;
using namespace ExtUI;
void FeedratePercentScreen::onRedraw(draw_mode_t what) {
widgets_t w(what);
w.precision(0).units(PSTR("%"));
w.heading(PSTR("Print Speed"));
w.adjuster(4, PSTR("Speed"), getFeedrate_percent());
w.increments();
}
bool FeedratePercentScreen::onTouchHeld(uint8_t tag) {
const float increment = getIncrement();
switch (tag) {
case 4: UI_DECREMENT(Feedrate_percent); break;
case 5: UI_INCREMENT(Feedrate_percent); break;
default:
return false;
}
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,101 @@
/*********************
* filament_menu.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && ANY(LIN_ADVANCE, FILAMENT_RUNOUT_SENSOR)
#include "screens.h"
using namespace FTDI;
using namespace ExtUI;
using namespace Theme;
void FilamentMenu::onRedraw(draw_mode_t what) {
if (what & BACKGROUND) {
CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(Theme::bg_color))
.cmd(CLEAR(true,true,true));
}
if (what & FOREGROUND) {
CommandProcessor cmd;
cmd.font(font_large)
#ifdef TOUCH_UI_PORTRAIT
#define GRID_ROWS 9
#define GRID_COLS 2
.text ( BTN_POS(1,1), BTN_SIZE(2,1), F("Filament Options:"))
.font(font_medium).colors(normal_btn)
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
.enabled(1)
#else
.enabled(0)
#endif
.tag(2).button( BTN_POS(1,2), BTN_SIZE(2,1), F("Runout Sensor"))
#if ENABLED(LIN_ADVANCE)
.enabled(1)
#else
.enabled(0)
#endif
.tag(3).button( BTN_POS(1,3), BTN_SIZE(2,1), F("Linear Advance"))
.colors(action_btn)
.tag(1) .button( BTN_POS(1,9), BTN_SIZE(2,1), F("Back"));
#undef GRID_COLS
#undef GRID_ROWS
#else
#define GRID_ROWS 6
#define GRID_COLS 3
.text ( BTN_POS(1,1), BTN_SIZE(3,1), F("Filament Options:"))
.font(font_medium).colors(normal_btn)
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
.enabled(1)
#else
.enabled(0)
#endif
.tag(2).button( BTN_POS(1,2), BTN_SIZE(3,1), F("Filament Runout"))
#if ENABLED(LIN_ADVANCE)
.enabled(1)
#else
.enabled(0)
#endif
.tag(3).button( BTN_POS(1,3), BTN_SIZE(3,1), F("Linear Advance"))
.colors(action_btn)
.tag(1) .button( BTN_POS(1,6), BTN_SIZE(3,1), F("Back"));
#endif
}
}
bool FilamentMenu::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1: GOTO_PREVIOUS(); break;
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
case 2: GOTO_SCREEN(FilamentRunoutScreen); break;
#endif
#if ENABLED(LIN_ADVANCE)
case 3: GOTO_SCREEN(LinearAdvanceScreen); break;
#endif
default: return false;
}
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,65 @@
/******************************
* filament_runout_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && ENABLED(FILAMENT_RUNOUT_SENSOR)
#include "screens.h"
using namespace FTDI;
using namespace ExtUI;
using namespace Theme;
void FilamentRunoutScreen::onRedraw(draw_mode_t what) {
widgets_t w(what);
w.heading( PSTR("Runout Detection:"));
w.toggle( 2, PSTR("Filament Sensor:"), PSTR("off\xFFon"), getFilamentRunoutEnabled());
#ifdef FILAMENT_RUNOUT_DISTANCE_MM
w.heading(PSTR("Detection Threshold:"));
w.units(PSTR("mm"));
w.precision(0);
w.color(e_axis);
w.adjuster( 10, PSTR("Distance:"), getFilamentRunoutDistance_mm(), getFilamentRunoutEnabled());
w.increments();
#endif
}
bool FilamentRunoutScreen::onTouchHeld(uint8_t tag) {
using namespace ExtUI;
const float increment = getIncrement();
switch (tag) {
case 2: setFilamentRunoutEnabled(!getFilamentRunoutEnabled()); break;
#ifdef FILAMENT_RUNOUT_DISTANCE_MM
case 10: UI_DECREMENT(FilamentRunoutDistance_mm); break;
case 11: UI_INCREMENT(FilamentRunoutDistance_mm); break;
#endif
default:
return false;
}
SaveSettingsDialogBox::settingsChanged();
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,264 @@
/********************
* files_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
#include "screen_data.h"
using namespace FTDI;
using namespace ExtUI;
using namespace Theme;
void FilesScreen::onEntry() {
screen_data.FilesScreen.cur_page = 0;
screen_data.FilesScreen.selected_tag = 0xFF;
#if ENABLED(SCROLL_LONG_FILENAMES) && (FTDI_API_LEVEL >= 810)
CLCD::mem_write_32(CLCD::REG::MACRO_0,DL::NOP);
#endif
gotoPage(0);
BaseScreen::onEntry();
}
const char *FilesScreen::getSelectedShortFilename() {
FileList files;
files.seek(getFileForTag(screen_data.FilesScreen.selected_tag), true);
return files.shortFilename();
}
const char *FilesScreen::getSelectedLongFilename() {
FileList files;
files.seek(getFileForTag(screen_data.FilesScreen.selected_tag), true);
return files.longFilename();
}
void FilesScreen::drawSelectedFile() {
FileList files;
files.seek(getFileForTag(screen_data.FilesScreen.selected_tag), true);
screen_data.FilesScreen.flags.is_dir = files.isDir();
drawFileButton(
files.filename(),
screen_data.FilesScreen.selected_tag,
screen_data.FilesScreen.flags.is_dir,
true
);
}
uint16_t FilesScreen::getFileForTag(uint8_t tag) {
return screen_data.FilesScreen.cur_page * files_per_page + tag - 2;
}
#ifdef TOUCH_UI_PORTRAIT
#define GRID_COLS 6
#define GRID_ROWS (files_per_page + header_h + footer_h)
#else
#define GRID_COLS 6
#define GRID_ROWS (files_per_page + header_h + footer_h)
#endif
void FilesScreen::drawFileButton(const char* filename, uint8_t tag, bool is_dir, bool is_highlighted) {
const uint8_t line = getLineForTag(tag)+1;
CommandProcessor cmd;
cmd.tag(tag);
cmd.cmd(COLOR_RGB(is_highlighted ? fg_action : bg_color));
cmd.font(font_medium)
.rectangle( 0, BTN_Y(header_h+line), display_width, BTN_H(1));
cmd.cmd(COLOR_RGB(is_highlighted ? normal_btn.rgb : bg_text_enabled));
#if ENABLED(SCROLL_LONG_FILENAMES)
if (is_highlighted) {
cmd.cmd(SAVE_CONTEXT());
cmd.cmd(MACRO(0));
}
#endif
cmd.text (BTN_POS(1,header_h+line), BTN_SIZE(6,1), filename, OPT_CENTERY);
if (is_dir) {
cmd.text(BTN_POS(1,header_h+line), BTN_SIZE(6,1), F("> "), OPT_CENTERY | OPT_RIGHTX);
}
#if ENABLED(SCROLL_LONG_FILENAMES)
if (is_highlighted) {
cmd.cmd(RESTORE_CONTEXT());
}
#endif
}
void FilesScreen::drawFileList() {
FileList files;
screen_data.FilesScreen.num_page = max(1,(ceil)(float(files.count()) / files_per_page));
screen_data.FilesScreen.cur_page = min(screen_data.FilesScreen.cur_page, screen_data.FilesScreen.num_page-1);
screen_data.FilesScreen.flags.is_root = files.isAtRootDir();
#undef MARGIN_T
#undef MARGIN_B
#define MARGIN_T 0
#define MARGIN_B 0
uint16_t fileIndex = screen_data.FilesScreen.cur_page * files_per_page;
for(uint8_t i = 0; i < files_per_page; i++, fileIndex++) {
if (files.seek(fileIndex)) {
drawFileButton(files.filename(), getTagForLine(i), files.isDir(), false);
} else {
break;
}
}
}
void FilesScreen::drawHeader() {
const bool prev_enabled = screen_data.FilesScreen.cur_page > 0;
const bool next_enabled = screen_data.FilesScreen.cur_page < (screen_data.FilesScreen.num_page - 1);
#undef MARGIN_T
#undef MARGIN_B
#define MARGIN_T 0
#define MARGIN_B 2
char str[16];
sprintf_P(str, PSTR("Page %d of %d"),
screen_data.FilesScreen.cur_page + 1, screen_data.FilesScreen.num_page);
CommandProcessor cmd;
cmd.colors(normal_btn)
.font(font_small)
.tag(0).button( BTN_POS(2,1), BTN_SIZE(4,header_h), str, OPT_CENTER | OPT_FLAT)
.font(font_medium)
.colors(action_btn)
.tag(241).enabled(prev_enabled).button( BTN_POS(1,1), BTN_SIZE(1,header_h), F("<"))
.tag(242).enabled(next_enabled).button( BTN_POS(6,1), BTN_SIZE(1,header_h), F(">"));
}
void FilesScreen::drawFooter() {
#undef MARGIN_T
#undef MARGIN_B
#ifdef TOUCH_UI_PORTRAIT
#define MARGIN_T 15
#define MARGIN_B 5
#else
#define MARGIN_T 5
#define MARGIN_B 5
#endif
const bool has_selection = screen_data.FilesScreen.selected_tag != 0xFF;
const uint8_t back_tag = screen_data.FilesScreen.flags.is_root ? 240 : 245;
const uint8_t y = GRID_ROWS - footer_h + 1;
const uint8_t h = footer_h;
CommandProcessor cmd;
cmd.colors(normal_btn)
.font(font_medium)
.colors(has_selection ? normal_btn : action_btn)
.tag(back_tag).button( BTN_POS(4,y), BTN_SIZE(3,h), F("Back"))
.enabled(has_selection)
.colors(has_selection ? action_btn : normal_btn);
if (screen_data.FilesScreen.flags.is_dir) {
cmd.tag(244).button( BTN_POS(1, y), BTN_SIZE(3,h), F("Open"));
} else {
cmd.tag(243).button( BTN_POS(1, y), BTN_SIZE(3,h), F("Print"));
}
}
void FilesScreen::onRedraw(draw_mode_t what) {
if (what & FOREGROUND) {
drawHeader();
drawSelectedFile();
drawFooter();
}
}
void FilesScreen::gotoPage(uint8_t page) {
screen_data.FilesScreen.selected_tag = 0xFF;
screen_data.FilesScreen.cur_page = page;
CommandProcessor cmd;
cmd.cmd(CMD_DLSTART)
.cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(CLEAR(true,true,true))
.colors(normal_btn);
drawFileList();
storeBackground();
}
bool FilesScreen::onTouchEnd(uint8_t tag) {
switch (tag) {
case 240: GOTO_PREVIOUS(); return true;
case 241:
if (screen_data.FilesScreen.cur_page > 0) {
gotoPage(screen_data.FilesScreen.cur_page-1);
}
break;
case 242:
if (screen_data.FilesScreen.cur_page < (screen_data.FilesScreen.num_page-1)) {
gotoPage(screen_data.FilesScreen.cur_page+1);
}
break;
case 243:
printFile(getSelectedShortFilename());
StatusScreen::setStatusMessage(F("Print Starting"));
GOTO_SCREEN(StatusScreen);
return true;
case 244:
{
FileList files;
files.changeDir(getSelectedShortFilename());
gotoPage(0);
}
break;
case 245:
{
FileList files;
files.upDir();
gotoPage(0);
}
break;
default:
if (tag < 240) {
screen_data.FilesScreen.selected_tag = tag;
#if ENABLED(SCROLL_LONG_FILENAMES) && (FTDI_API_LEVEL >= 810)
if (FTDI::ftdi_chip >= 810) {
const char *longFilename = getSelectedLongFilename();
if (longFilename[0]) {
CLCD::FontMetrics fm(font_medium);
uint16_t text_width = fm.get_text_width(longFilename);
screen_data.FilesScreen.scroll_pos = 0;
if (text_width > display_width)
screen_data.FilesScreen.scroll_max = text_width - display_width + MARGIN_L + MARGIN_R;
else
screen_data.FilesScreen.scroll_max = 0;
}
}
#endif
}
break;
}
return true;
}
void FilesScreen::onIdle() {
#if ENABLED(SCROLL_LONG_FILENAMES) && (FTDI_API_LEVEL >= 810)
if (FTDI::ftdi_chip >= 810) {
CLCD::mem_write_32(CLCD::REG::MACRO_0,
VERTEX_TRANSLATE_X(-int32_t(screen_data.FilesScreen.scroll_pos)));
if (screen_data.FilesScreen.scroll_pos < screen_data.FilesScreen.scroll_max * 16)
screen_data.FilesScreen.scroll_pos++;
}
#endif
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,285 @@
/*********************************
* interface_settings_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
#include "screen_data.h"
#include "../archim2-flash/flash_storage.h"
#include "../../../../../module/configuration_store.h"
#if ENABLED(LULZBOT_PRINTCOUNTER)
#include "../../../../../module/printcounter.h"
#endif
bool restoreEEPROM();
using namespace FTDI;
using namespace ExtUI;
using namespace Theme;
constexpr bool PERSISTENT_STORE_SUCCESS = false; // persistentStore uses true for error
void InterfaceSettingsScreen::onStartup() {
}
void InterfaceSettingsScreen::onEntry() {
screen_data.InterfaceSettingsScreen.brightness = CLCD::get_brightness();
screen_data.InterfaceSettingsScreen.volume = SoundPlayer::get_volume();
BaseScreen::onEntry();
}
void InterfaceSettingsScreen::onRedraw(draw_mode_t what) {
CommandProcessor cmd;
if (what & BACKGROUND) {
#define GRID_COLS 4
#ifdef TOUCH_UI_PORTRAIT
#define GRID_ROWS 7
#else
#define GRID_ROWS 6
#endif
cmd.cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(CLEAR(true,true,true))
.cmd(COLOR_RGB(bg_text_enabled))
.tag(0)
.font(font_medium)
.text(BTN_POS(1,1), BTN_SIZE(4,1), F("Interface Settings"))
#undef EDGE_R
#define EDGE_R 30
.font(font_small)
.tag(0)
.text(BTN_POS(1,2), BTN_SIZE(2,1), F("LCD brightness:"), OPT_RIGHTX | OPT_CENTERY)
.text(BTN_POS(1,3), BTN_SIZE(2,1), F("Sound volume:"), OPT_RIGHTX | OPT_CENTERY)
.text(BTN_POS(1,4), BTN_SIZE(2,1), F("Screen lock:"), OPT_RIGHTX | OPT_CENTERY);
cmd.text(BTN_POS(1,5), BTN_SIZE(2,1), F("Boot screen:"), OPT_RIGHTX | OPT_CENTERY);
#undef EDGE_R
}
if (what & FOREGROUND) {
#ifdef TOUCH_UI_PORTRAIT
constexpr uint8_t w = 2;
#else
constexpr uint8_t w = 1;
#endif
cmd.font(font_medium)
#define EDGE_R 30
.colors(ui_slider)
.tag(2).slider(BTN_POS(3,2), BTN_SIZE(2,1), screen_data.InterfaceSettingsScreen.brightness, 128)
.tag(3).slider(BTN_POS(3,3), BTN_SIZE(2,1), screen_data.InterfaceSettingsScreen.volume, 0xFF)
.colors(ui_toggle)
.tag(4).toggle(BTN_POS(3,4), BTN_SIZE(w,1), F("off\xFFon"), LockScreen::is_enabled())
.tag(5).toggle(BTN_POS(3,5), BTN_SIZE(w,1), F("off\xFFon"), UIData::animations_enabled())
#undef EDGE_R
#define EDGE_R 0
#ifdef TOUCH_UI_PORTRAIT
.colors(normal_btn)
.tag(6).button (BTN_POS(1,6), BTN_SIZE(4,1), F("Customize Sounds"))
.colors(action_btn)
.tag(1).button (BTN_POS(1,7), BTN_SIZE(4,1), F("Back"));
#else
.tag(6).button (BTN_POS(1,6), BTN_SIZE(2,1), F("Customize Sounds"))
.colors(action_btn)
.tag(1).button (BTN_POS(3,6), BTN_SIZE(2,1), F("Back"));
#endif
}
}
bool InterfaceSettingsScreen::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1: GOTO_PREVIOUS(); return true;
case 4:
if (!LockScreen::is_enabled())
LockScreen::enable();
else
LockScreen::disable();
break;
case 5: UIData::enable_animations(!UIData::animations_enabled());; break;
case 6: GOTO_SCREEN(InterfaceSoundsScreen); return true;
default:
return false;
}
SaveSettingsDialogBox::settingsChanged();
return true;
}
bool InterfaceSettingsScreen::onTouchStart(uint8_t tag) {
#undef EDGE_R
#define EDGE_R 30
CommandProcessor cmd;
switch (tag) {
case 2: cmd.track_linear(BTN_POS(3,3), BTN_SIZE(2,1), 2).execute(); break;
case 3: cmd.track_linear(BTN_POS(3,4), BTN_SIZE(2,1), 3).execute(); break;
default: break;
}
#undef EDGE_R
#define EDGE_R 0
#undef GRID_COLS
#undef GRID_ROWS
return true;
}
void InterfaceSettingsScreen::onIdle() {
if (refresh_timer.elapsed(TOUCH_UPDATE_INTERVAL)) {
refresh_timer.start();
uint16_t value;
CommandProcessor cmd;
switch (cmd.track_tag(value)) {
case 2:
screen_data.InterfaceSettingsScreen.brightness = float(value) * 128 / 0xFFFF;
CLCD::set_brightness(screen_data.InterfaceSettingsScreen.brightness);
SaveSettingsDialogBox::settingsChanged();
break;
case 3:
screen_data.InterfaceSettingsScreen.volume = value >> 8;
SoundPlayer::set_volume(screen_data.InterfaceSettingsScreen.volume);
SaveSettingsDialogBox::settingsChanged();
break;
default:
return;
}
onRefresh();
}
BaseScreen::onIdle();
}
void InterfaceSettingsScreen::failSafeSettings() {
// Reset settings that may make the printer interface
// unusable.
CLCD::mem_write_32(CLCD::REG::ROTATE, 0);
CLCD::default_touch_transform();
CLCD::default_display_orientation();
CLCD::set_brightness(255);
UIData::reset_persistent_data();
CLCD::mem_write_16(CLCD::REG::HOFFSET, FTDI::Hoffset);
CLCD::mem_write_16(CLCD::REG::VOFFSET, FTDI::Voffset);
}
void InterfaceSettingsScreen::defaultSettings() {
LockScreen::passcode = 0;
SoundPlayer::set_volume(255);
CLCD::set_brightness(255);
UIData::reset_persistent_data();
InterfaceSoundsScreen::defaultSettings();
CLCD::mem_write_16(CLCD::REG::HOFFSET, FTDI::Hoffset);
CLCD::mem_write_16(CLCD::REG::VOFFSET, FTDI::Voffset);
}
void InterfaceSettingsScreen::saveSettings(char *buff) {
static_assert(
ExtUI::eeprom_data_size >= sizeof(persistent_data_t),
"Insufficient space in EEPROM for UI parameters"
);
SERIAL_ECHOLNPGM("Writing setting to EEPROM");
persistent_data_t eeprom;
eeprom.passcode = LockScreen::passcode;
eeprom.sound_volume = SoundPlayer::get_volume();
eeprom.display_brightness = CLCD::get_brightness();
eeprom.bit_flags = UIData::get_persistent_data();
eeprom.touch_transform_a = CLCD::mem_read_32(CLCD::REG::TOUCH_TRANSFORM_A);
eeprom.touch_transform_b = CLCD::mem_read_32(CLCD::REG::TOUCH_TRANSFORM_B);
eeprom.touch_transform_c = CLCD::mem_read_32(CLCD::REG::TOUCH_TRANSFORM_C);
eeprom.touch_transform_d = CLCD::mem_read_32(CLCD::REG::TOUCH_TRANSFORM_D);
eeprom.touch_transform_e = CLCD::mem_read_32(CLCD::REG::TOUCH_TRANSFORM_E);
eeprom.touch_transform_f = CLCD::mem_read_32(CLCD::REG::TOUCH_TRANSFORM_F);
eeprom.display_h_offset_adj = CLCD::mem_read_16(CLCD::REG::HOFFSET) - FTDI::Hoffset;
eeprom.display_v_offset_adj = CLCD::mem_read_16(CLCD::REG::VOFFSET) - FTDI::Voffset;
for(uint8_t i = 0; i < InterfaceSoundsScreen::NUM_EVENTS; i++)
eeprom.event_sounds[i] = InterfaceSoundsScreen::event_sounds[i];
memcpy(buff, &eeprom, sizeof(eeprom));
}
void InterfaceSettingsScreen::loadSettings(const char *buff) {
static_assert(
ExtUI::eeprom_data_size >= sizeof(persistent_data_t),
"Insufficient space in EEPROM for UI parameters"
);
persistent_data_t eeprom;
memcpy(&eeprom, buff, sizeof(eeprom));
SERIAL_ECHOLNPGM("Loading setting from EEPROM");
LockScreen::passcode = eeprom.passcode;
SoundPlayer::set_volume(eeprom.sound_volume);
UIData::set_persistent_data(eeprom.bit_flags);
CLCD::set_brightness(eeprom.display_brightness);
CLCD::mem_write_32(CLCD::REG::TOUCH_TRANSFORM_A, eeprom.touch_transform_a);
CLCD::mem_write_32(CLCD::REG::TOUCH_TRANSFORM_B, eeprom.touch_transform_b);
CLCD::mem_write_32(CLCD::REG::TOUCH_TRANSFORM_C, eeprom.touch_transform_c);
CLCD::mem_write_32(CLCD::REG::TOUCH_TRANSFORM_D, eeprom.touch_transform_d);
CLCD::mem_write_32(CLCD::REG::TOUCH_TRANSFORM_E, eeprom.touch_transform_e);
CLCD::mem_write_32(CLCD::REG::TOUCH_TRANSFORM_F, eeprom.touch_transform_f);
CLCD::mem_write_16(CLCD::REG::HOFFSET, eeprom.display_h_offset_adj + FTDI::Hoffset);
CLCD::mem_write_16(CLCD::REG::VOFFSET, eeprom.display_v_offset_adj + FTDI::Voffset);
for(uint8_t i = 0; i < InterfaceSoundsScreen::NUM_EVENTS; i++)
InterfaceSoundsScreen::event_sounds[i] = eeprom.event_sounds[i];
#if ENABLED(DEVELOPER_SCREENS)
StressTestScreen::startupCheck();
#endif
}
#ifdef LULZBOT_EEPROM_BACKUP_SIZE
#include "../../../../../HAL/shared/persistent_store_api.h"
bool restoreEEPROM() {
uint8_t data[LULZBOT_EEPROM_BACKUP_SIZE];
bool success = UIFlashStorage::read_config_data(data, LULZBOT_EEPROM_BACKUP_SIZE);
if (success)
success = persistentStore.write_data(0, data, LULZBOT_EEPROM_BACKUP_SIZE) == PERSISTENT_STORE_SUCCESS;
if (success)
StatusScreen::setStatusMessage(F("Settings restored from backup"));
else
StatusScreen::setStatusMessage(F("Settings restored to default"));
return success;
}
bool InterfaceSettingsScreen::backupEEPROM() {
uint8_t data[LULZBOT_EEPROM_BACKUP_SIZE];
if (persistentStore.read_data(0, data, LULZBOT_EEPROM_BACKUP_SIZE) != PERSISTENT_STORE_SUCCESS)
return false;
UIFlashStorage::write_config_data(data, LULZBOT_EEPROM_BACKUP_SIZE);
return true;
}
#endif
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,160 @@
/*******************************
* interface_sounds_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
#include "screen_data.h"
using namespace FTDI;
using namespace Theme;
using namespace ExtUI;
uint8_t InterfaceSoundsScreen::event_sounds[];
const char* InterfaceSoundsScreen::getSoundSelection(event_t event) {
return SoundList::name(event_sounds[event]);
}
void InterfaceSoundsScreen::toggleSoundSelection(event_t event) {
event_sounds[event] = (event_sounds[event]+1) % SoundList::n;
playEventSound(event);
}
void InterfaceSoundsScreen::setSoundSelection(event_t event, const SoundPlayer::sound_t* sound) {
for(uint8_t i = 0; i < SoundList::n; i++)
if (SoundList::data(i) == sound)
event_sounds[event] = i;
}
void InterfaceSoundsScreen::playEventSound(event_t event, play_mode_t mode) {
sound.play(SoundList::data(event_sounds[event]), mode);
}
void InterfaceSoundsScreen::defaultSettings() {
setSoundSelection(PRINTING_STARTED, twinkle);
setSoundSelection(PRINTING_FINISHED, fanfare);
setSoundSelection(PRINTING_FAILED, sad_trombone);
}
void InterfaceSoundsScreen::onRedraw(draw_mode_t what) {
CommandProcessor cmd;
if (what & BACKGROUND) {
cmd.cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(CLEAR(true,true,true))
.cmd(COLOR_RGB(bg_text_enabled))
.tag(0)
#define GRID_COLS 4
#define GRID_ROWS 9
.font(font_medium)
.text(BTN_POS(1,1), BTN_SIZE(4,1), F("Interface Sounds"))
#undef EDGE_R
#define EDGE_R 30
.font(font_small)
.tag(0).text (BTN_POS(1,2), BTN_SIZE(2,1), F("Sound volume:"), OPT_RIGHTX | OPT_CENTERY)
.text (BTN_POS(1,3), BTN_SIZE(2,1), F("Click sounds:"), OPT_RIGHTX | OPT_CENTERY)
.text (BTN_POS(1,5), BTN_SIZE(2,1), F("Print starting:"), OPT_RIGHTX | OPT_CENTERY)
.text (BTN_POS(1,6), BTN_SIZE(2,1), F("Print finished:"), OPT_RIGHTX | OPT_CENTERY)
.text (BTN_POS(1,7), BTN_SIZE(2,1), F("Print error:"), OPT_RIGHTX | OPT_CENTERY);
#undef EDGE_R
}
if (what & FOREGROUND) {
#ifdef TOUCH_UI_PORTRAIT
constexpr uint8_t w = 2;
#else
constexpr uint8_t w = 1;
#endif
cmd.font(font_medium)
.colors(ui_slider)
#define EDGE_R 30
.tag(2).slider (BTN_POS(3,2), BTN_SIZE(2,1), screen_data.InterfaceSettingsScreen.volume, 0xFF)
.colors(ui_toggle)
.tag(3).toggle (BTN_POS(3,3), BTN_SIZE(w,1), F("off\xFFon"), UIData::touch_sounds_enabled())
#undef EDGE_R
.colors(normal_btn)
#define EDGE_R 0
.tag(4).button (BTN_POS(3,5), BTN_SIZE(2,1), getSoundSelection(PRINTING_STARTED))
.tag(5).button (BTN_POS(3,6), BTN_SIZE(2,1), getSoundSelection(PRINTING_FINISHED))
.tag(6).button (BTN_POS(3,7), BTN_SIZE(2,1), getSoundSelection(PRINTING_FAILED))
.colors(action_btn)
.tag(1).button (BTN_POS(1,9), BTN_SIZE(4,1), F("Back"));
}
}
void InterfaceSoundsScreen::onEntry() {
screen_data.InterfaceSettingsScreen.volume = SoundPlayer::get_volume();
BaseScreen::onEntry();
}
bool InterfaceSoundsScreen::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1: GOTO_PREVIOUS(); return true;
case 3: UIData::enable_touch_sounds(!UIData::touch_sounds_enabled()); break;
case 4: toggleSoundSelection(PRINTING_STARTED); break;
case 5: toggleSoundSelection(PRINTING_FINISHED); break;
case 6: toggleSoundSelection(PRINTING_FAILED); break;
default:
return false;
}
SaveSettingsDialogBox::settingsChanged();
return true;
}
bool InterfaceSoundsScreen::onTouchStart(uint8_t tag) {
CommandProcessor cmd;
#undef EDGE_R
#define EDGE_R 30
switch (tag) {
case 2: cmd.track_linear(BTN_POS(3,2), BTN_SIZE(2,1), 2).execute(); break;
default: break;
}
return true;
}
void InterfaceSoundsScreen::onIdle() {
if (refresh_timer.elapsed(TOUCH_UPDATE_INTERVAL)) {
refresh_timer.start();
uint16_t value;
CommandProcessor cmd;
switch (cmd.track_tag(value)) {
case 2:
screen_data.InterfaceSettingsScreen.volume = value >> 8;
SoundPlayer::set_volume(screen_data.InterfaceSettingsScreen.volume);
SaveSettingsDialogBox::settingsChanged();
break;
default:
return;
}
onRefresh();
}
BaseScreen::onIdle();
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,65 @@
/*******************
* jerk_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && DISABLED(JUNCTION_DEVIATION)
#include "screens.h"
using namespace FTDI;
using namespace ExtUI;
using namespace Theme;
void JerkScreen::onRedraw(draw_mode_t what) {
widgets_t w(what);
w.precision(1);
w.units(PSTR("mm/s"));
w.heading( PSTR("Maximum Jerk"));
w.color(x_axis) .adjuster( 2, PSTR("X:"), getAxisMaxJerk_mm_s(X) );
w.color(y_axis) .adjuster( 4, PSTR("Y:"), getAxisMaxJerk_mm_s(Y) );
w.color(z_axis) .adjuster( 6, PSTR("Z:"), getAxisMaxJerk_mm_s(Z) );
w.color(e_axis) .adjuster( 8, PSTR("E:"), getAxisMaxJerk_mm_s(E0) );
w.increments();
}
bool JerkScreen::onTouchHeld(uint8_t tag) {
using namespace ExtUI;
const float increment = getIncrement();
switch (tag) {
case 2: UI_DECREMENT(AxisMaxJerk_mm_s, X); break;
case 3: UI_INCREMENT(AxisMaxJerk_mm_s, X); break;
case 4: UI_DECREMENT(AxisMaxJerk_mm_s, Y); break;
case 5: UI_INCREMENT(AxisMaxJerk_mm_s, Y); break;
case 6: UI_DECREMENT(AxisMaxJerk_mm_s, Z); break;
case 7: UI_INCREMENT(AxisMaxJerk_mm_s, Z); break;
case 8: UI_DECREMENT(AxisMaxJerk_mm_s, E0); break;
case 9: UI_INCREMENT(AxisMaxJerk_mm_s, E0); break;
default:
return false;
}
SaveSettingsDialogBox::settingsChanged();
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,54 @@
/*******************
* boot_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && ENABLED(JUNCTION_DEVIATION)
#include "screens.h"
using namespace FTDI;
using namespace ExtUI;
using namespace Theme;
void JunctionDeviationScreen::onRedraw(draw_mode_t what) {
widgets_t w(what);
w.precision(2);
w.units(PSTR("mm"));
w.heading( PSTR("Junction Deviation"));
w.color(other) .adjuster( 2, PSTR(""), getJunctionDeviation_mm() );
w.increments();
}
bool JunctionDeviationScreen::onTouchHeld(uint8_t tag) {
const float increment = getIncrement();
switch (tag) {
case 2: UI_DECREMENT(JunctionDeviation_mm); break;
case 3: UI_INCREMENT(JunctionDeviation_mm); break;
default:
return false;
}
SaveSettingsDialogBox::settingsChanged();
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,62 @@
/*******************
* kill_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
using namespace FTDI;
// The kill screen is an oddball that happens after Marlin has killed the events
// loop. So we only have a show() method rather than onRedraw(). The KillScreen
// should not be used as a model for other UI screens as it is an exception.
void KillScreen::show(progmem_str message) {
CommandProcessor cmd;
cmd.cmd(CMD_DLSTART)
.cmd(CLEAR_COLOR_RGB(Theme::bg_color))
.cmd(CLEAR(true,true,true))
.tag(0);
#define GRID_COLS 4
#define GRID_ROWS 8
cmd.font(Theme::font_large)
.cmd(COLOR_RGB(Theme::bg_text_enabled))
.text(BTN_POS(1,2), BTN_SIZE(4,1), message)
.text(BTN_POS(1,3), BTN_SIZE(4,1), F("PRINTER HALTED"))
.text(BTN_POS(1,6), BTN_SIZE(4,1), F("Please reset"));
#undef GRID_COLS
#undef GRID_ROWS
cmd.cmd(DL::DL_DISPLAY)
.cmd(CMD_SWAP)
.execute();
InterfaceSoundsScreen::playEventSound(InterfaceSoundsScreen::PRINTING_FAILED, PLAY_SYNCHRONOUS);
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,77 @@
/*****************************
* linear_advance_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && ENABLED(LIN_ADVANCE)
#include "screens.h"
using namespace FTDI;
using namespace ExtUI;
using namespace Theme;
void LinearAdvanceScreen::onRedraw(draw_mode_t what) {
widgets_t w(what);
w.precision(2, DEFAULT_LOWEST).color(e_axis);
w.heading( PSTR("Linear Advance:"));
#if EXTRUDERS == 1
w.adjuster( 2, PSTR("K:"), getLinearAdvance_mm_mm_s(E0) );
#else
w.adjuster( 2, PSTR("K E1:"), getLinearAdvance_mm_mm_s(E0) );
w.adjuster( 4, PSTR("K E2:"), getLinearAdvance_mm_mm_s(E1) );
#if EXTRUDERS > 2
w.adjuster( 6, PSTR("K E3:"), getLinearAdvance_mm_mm_s(E2) );
#if EXTRUDERS > 3
w.adjuster( 8, PSTR("K E4:"), getLinearAdvance_mm_mm_s(E3) );
#endif
#endif
#endif
w.increments();
}
bool LinearAdvanceScreen::onTouchHeld(uint8_t tag) {
using namespace ExtUI;
const float increment = getIncrement();
switch (tag) {
case 2: UI_DECREMENT(LinearAdvance_mm_mm_s, E0); break;
case 3: UI_INCREMENT(LinearAdvance_mm_mm_s, E0); break;
#if EXTRUDERS > 1
case 4: UI_DECREMENT(LinearAdvance_mm_mm_s, E1); break;
case 5: UI_INCREMENT(LinearAdvance_mm_mm_s, E1); break;
#if EXTRUDERS > 2
case 6: UI_DECREMENT(LinearAdvance_mm_mm_s, E2); break;
case 7: UI_INCREMENT(LinearAdvance_mm_mm_s, E2); break;
#if EXTRUDERS > 3
case 8: UI_DECREMENT(LinearAdvance_mm_mm_s, E3); break;
case 9: UI_INCREMENT(LinearAdvance_mm_mm_s, E3); break;
#endif
#endif
#endif
default:
return false;
}
SaveSettingsDialogBox::settingsChanged();
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,214 @@
/*******************
* lock_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
#include "screen_data.h"
using namespace FTDI;
using namespace Theme;
uint16_t LockScreen::passcode = 0;
void LockScreen::onEntry() {
const uint8_t siz = sizeof(screen_data.LockScreen.passcode);
memset(screen_data.LockScreen.passcode, '_', siz-1);
screen_data.LockScreen.passcode[siz-1] = '\0';
BaseScreen::onEntry();
}
void LockScreen::onRedraw(draw_mode_t what) {
CommandProcessor cmd;
if (what & BACKGROUND) {
cmd.cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(CLEAR(true,true,true))
.tag(0);
}
if (what & FOREGROUND) {
#ifdef TOUCH_UI_PORTRAIT
#define GRID_COLS 1
#define GRID_ROWS 10
#else
#define GRID_COLS 1
#define GRID_ROWS 7
#endif
#undef MARGIN_T
#undef MARGIN_B
#define MARGIN_T 3
#define MARGIN_B 3
progmem_str message;
switch (message_style()) {
case 'w':
message = F("Wrong passcode!");
break;
case 'g':
message = F("Passcode accepted!");
break;
default:
if (passcode == 0) {
message = F("Select Passcode:");
} else {
message = F("Enter Passcode:");
}
}
message_style() = '\0'; // Terminate the string.
#ifdef TOUCH_UI_PORTRAIT
constexpr uint8_t l = 6;
#else
constexpr uint8_t l = 3;
#endif
const uint8_t pressed = EventLoop::get_pressed_tag();
cmd.font(font_large)
.cmd(COLOR_RGB(bg_text_enabled))
#ifdef TOUCH_UI_PORTRAIT
.text(BTN_POS(1,2), BTN_SIZE(1,1), message)
.font(font_xlarge)
.text(BTN_POS(1,4), BTN_SIZE(1,1), screen_data.LockScreen.passcode)
#else
.text(BTN_POS(1,1), BTN_SIZE(1,1), message)
.font(font_xlarge)
.text(BTN_POS(1,2), BTN_SIZE(1,1), screen_data.LockScreen.passcode)
#endif
.font(font_large)
.colors(normal_btn)
#ifdef TOUCH_UI_PASSCODE
.keys(BTN_POS(1,l+1), BTN_SIZE(1,1), F("123"), pressed)
.keys(BTN_POS(1,l+2), BTN_SIZE(1,1), F("456"), pressed)
.keys(BTN_POS(1,l+3), BTN_SIZE(1,1), F("789"), pressed)
.keys(BTN_POS(1,l+4), BTN_SIZE(1,1), F("0.<"), pressed);
#else
.keys(BTN_POS(1,l+1), BTN_SIZE(1,1), F("1234567890"), pressed)
.keys(BTN_POS(1,l+2), BTN_SIZE(1,1), F("qwertyuiop"), pressed)
.keys(BTN_POS(1,l+3), BTN_SIZE(1,1), F("asdfghjkl "), pressed)
.keys(BTN_POS(1,l+4), BTN_SIZE(1,1), F("zxcvbnm!?<"), pressed);
#endif
#undef MARGIN_T
#undef MARGIN_B
#define MARGIN_T MARGIN_DEFAULT
#define MARGIN_B MARGIN_DEFAULT
#undef GRID_COLS
#undef GRID_ROWS
}
}
char &LockScreen::message_style() {
// We use the last byte of the passcode string as a flag to indicate,
// which message to show.
constexpr uint8_t last_char = sizeof(screen_data.LockScreen.passcode)-1;
return screen_data.LockScreen.passcode[last_char];
}
void LockScreen::onPasscodeEntered() {
if (passcode == 0) {
// We are defining a passcode
message_style() = 0;
onRefresh();
sound.play(twinkle, PLAY_SYNCHRONOUS);
passcode = compute_checksum();
GOTO_PREVIOUS();
} else {
// We are verifying a passcode
if (passcode == compute_checksum()) {
message_style() = 'g';
onRefresh();
sound.play(twinkle, PLAY_SYNCHRONOUS);
GOTO_PREVIOUS();
} else {
message_style() = 'w';
onRefresh();
sound.play(sad_trombone, PLAY_SYNCHRONOUS);
current_screen.forget(); // Discard the screen the user was trying to go to.
GOTO_PREVIOUS();
}
}
}
bool LockScreen::onTouchEnd(uint8_t tag) {
char *c = strchr(screen_data.LockScreen.passcode,'_');
if (c) {
if (tag == '<') {
if (c != screen_data.LockScreen.passcode) {
// Backspace deletes previous entered characters.
*--c = '_';
}
} else {
// Append character to passcode
*c++ = tag;
if (*c == '\0') {
// If at last character, then process the code.
onPasscodeEntered();
}
}
}
return true;
}
uint16_t LockScreen::compute_checksum() {
uint16_t checksum = 0;
const char* c = screen_data.LockScreen.passcode;
while (*c) {
checksum = (checksum << 2) ^ *c++;
}
if (checksum == 0) checksum = 0xFFFF; // Prevent a zero checksum
return checksum;
}
// This function should be called *after* calling GOTO_SCREEN
// to move to new screen. If a passcode is enabled, it will
// immediately jump to the keypad screen, pushing the previous
// screen onto the stack. If the code is entered correctly,
// the stack will be popped, allowing the user to proceed to
// the new screen. Otherwise it will be popped twice, taking
// the user back to where they were before.
void LockScreen::check_passcode() {
if (passcode == 0) return;
message_style() = 0;
GOTO_SCREEN(LockScreen);
}
bool LockScreen::is_enabled() {
return passcode != 0;
}
void LockScreen::disable() {
passcode = 0;
}
void LockScreen::enable() {
message_style() = 0;
passcode = 0;
GOTO_SCREEN(LockScreen);
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,123 @@
/*****************
* main_menu.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && !defined(LULZBOT_USE_BIOPRINTER_UI)
#include "screens.h"
using namespace FTDI;
using namespace Theme;
void MainMenu::onRedraw(draw_mode_t what) {
if (what & BACKGROUND) {
CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(Theme::bg_color))
.cmd(CLEAR(true,true,true));
}
if (what & FOREGROUND) {
CommandProcessor cmd;
cmd.colors(normal_btn)
.font(Theme::font_medium)
#ifdef TOUCH_UI_PORTRAIT
#define GRID_ROWS 8
#define GRID_COLS 2
.tag(2).button( BTN_POS(1,1), BTN_SIZE(1,1), F("Auto Home"))
#ifdef NOZZLE_CLEAN_FEATURE
.enabled(1)
#else
.enabled(0)
#endif
.tag(3).button( BTN_POS(2,1), BTN_SIZE(1,1), F("Clean Nozzle"))
.tag(4).button( BTN_POS(1,2), BTN_SIZE(1,1), F("Move Axis"))
.tag(5).button( BTN_POS(2,2), BTN_SIZE(1,1), F("Motors Off"))
.tag(6).button( BTN_POS(1,3), BTN_SIZE(2,1), F("Temperature"))
.tag(7).button( BTN_POS(1,4), BTN_SIZE(2,1), F("Change Filament"))
.tag(8).button( BTN_POS(1,5), BTN_SIZE(2,1), F("Advanced Settings"))
#ifdef PRINTCOUNTER
.enabled(1)
#else
.enabled(0)
#endif
.tag(9).button( BTN_POS(1,7), BTN_SIZE(2,1), F("Printer Statistics"))
.tag(10).button( BTN_POS(1,6), BTN_SIZE(2,1), F("About Printer"))
.colors(action_btn)
.tag(1).button( BTN_POS(1,8), BTN_SIZE(2,1), F("Back"));
#undef GRID_COLS
#undef GRID_ROWS
#else
#define GRID_ROWS 5
#define GRID_COLS 2
.tag(2).button( BTN_POS(1,1), BTN_SIZE(1,1), F("Auto Home"))
#if ENABLED(NOZZLE_CLEAN_FEATURE)
.enabled(1)
#else
.enabled(0)
#endif
.tag(3).button( BTN_POS(2,1), BTN_SIZE(1,1), F("Clean Nozzle"))
.tag(4).button( BTN_POS(1,2), BTN_SIZE(1,1), F("Move Axis"))
.tag(5).button( BTN_POS(2,2), BTN_SIZE(1,1), F("Motors Off"))
.tag(6).button( BTN_POS(1,3), BTN_SIZE(1,1), F("Temperature"))
.tag(7).button( BTN_POS(2,3), BTN_SIZE(1,1), F("Change Filament"))
.tag(8).button( BTN_POS(1,4), BTN_SIZE(1,1), F("Advanced Settings"))
#ifdef PRINTCOUNTER
.enabled(1)
#else
.enabled(0)
#endif
.tag(9).button( BTN_POS(2,4), BTN_SIZE(1,1), F("Printer Statistics"))
.tag(10).button( BTN_POS(1,5), BTN_SIZE(1,1), F("About Printer"))
.colors(action_btn)
.tag(1).button( BTN_POS(2,5), BTN_SIZE(1,1), F("Back"));
#undef GRID_COLS
#undef GRID_ROWS
#endif
}
}
bool MainMenu::onTouchEnd(uint8_t tag) {
using namespace ExtUI;
switch (tag) {
case 1: GOTO_PREVIOUS(); break;
case 2: SpinnerDialogBox::enqueueAndWait_P(F("G28")); break;
#if ENABLED(NOZZLE_CLEAN_FEATURE)
case 3: injectCommands_P(PSTR("G12")); GOTO_SCREEN(StatusScreen); break;
#endif
case 4: GOTO_SCREEN(MoveAxisScreen); break;
case 5: injectCommands_P(PSTR("M84")); break;
case 6: GOTO_SCREEN(TemperatureScreen); break;
case 7: GOTO_SCREEN(ChangeFilamentScreen); break;
case 8: GOTO_SCREEN(AdvancedSettingsMenu); break;
#if ENABLED(PRINTCOUNTER)
case 9: GOTO_SCREEN(StatisticsScreen); break;
#endif
case 10: GOTO_SCREEN(AboutScreen); break;
default:
return false;
}
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,85 @@
/*******************************
* max_acceleration_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
using namespace FTDI;
using namespace ExtUI;
using namespace Theme;
void MaxAccelerationScreen::onRedraw(draw_mode_t what) {
widgets_t w(what);
w.precision(0);
w.units(PSTR("mm/s^2"));
w.heading( PSTR("Maximum Acceleration"));
w.color(x_axis) .adjuster( 2, PSTR("X:"), getAxisMaxAcceleration_mm_s2(X) );
w.color(y_axis) .adjuster( 4, PSTR("Y:"), getAxisMaxAcceleration_mm_s2(Y) );
w.color(z_axis) .adjuster( 6, PSTR("Z:"), getAxisMaxAcceleration_mm_s2(Z) );
#if EXTRUDERS == 1 || DISABLED(DISTINCT_E_FACTORS)
w.color(e_axis).adjuster( 8, PSTR("E:"), getAxisMaxAcceleration_mm_s2(E0) );
#elif EXTRUDERS > 1
w.color(e_axis).adjuster( 8, PSTR("E1:"), getAxisMaxAcceleration_mm_s2(E0) );
w.color(e_axis).adjuster(10, PSTR("E2:"), getAxisMaxAcceleration_mm_s2(E1) );
#if EXTRUDERS > 2
w.color(e_axis).adjuster(12, PSTR("E3:"), getAxisMaxAcceleration_mm_s2(E2) );
#endif
#if EXTRUDERS > 3
w.color(e_axis).adjuster(14, PSTR("E4:"), getAxisMaxAcceleration_mm_s2(E3) );
#endif
#endif
w.increments();
}
bool MaxAccelerationScreen::onTouchHeld(uint8_t tag) {
const float increment = getIncrement();
switch (tag) {
case 2: UI_DECREMENT(AxisMaxAcceleration_mm_s2, X ); break;
case 3: UI_INCREMENT(AxisMaxAcceleration_mm_s2, X ); break;
case 4: UI_DECREMENT(AxisMaxAcceleration_mm_s2, Y ); break;
case 5: UI_INCREMENT(AxisMaxAcceleration_mm_s2, Y ); break;
case 6: UI_DECREMENT(AxisMaxAcceleration_mm_s2, Z ); break;
case 7: UI_INCREMENT(AxisMaxAcceleration_mm_s2, Z ); break;
case 8: UI_DECREMENT(AxisMaxAcceleration_mm_s2, E0); break;
case 9: UI_INCREMENT(AxisMaxAcceleration_mm_s2, E0); break;
#if EXTRUDERS > 1 && ENABLED(DISTINCT_E_FACTORS)
case 10: UI_DECREMENT(AxisMaxAcceleration_mm_s2, E1); break;
case 11: UI_INCREMENT(AxisMaxAcceleration_mm_s2, E1); break;
#endif
#if EXTRUDERS > 2 && ENABLED(DISTINCT_E_FACTORS)
case 12: UI_DECREMENT(AxisMaxAcceleration_mm_s2, E2); break;
case 13: UI_INCREMENT(AxisMaxAcceleration_mm_s2, E2); break;
#endif
#if EXTRUDERS > 3 && ENABLED(DISTINCT_E_FACTORS)
case 14: UI_DECREMENT(AxisMaxAcceleration_mm_s2, E3); break;
case 15: UI_INCREMENT(AxisMaxAcceleration_mm_s2, E3); break;
#endif
default:
return false;
}
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,87 @@
/***************************
* max_velocity_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
using namespace FTDI;
using namespace ExtUI;
using namespace Theme;
void MaxVelocityScreen::onRedraw(draw_mode_t what) {
using namespace ExtUI;
widgets_t w(what);
w.precision(0);
w.units(PSTR("mm/s"));
w.heading( PSTR("Maximum Velocity"));
w.color(x_axis) .adjuster( 2, PSTR("X:"), getAxisMaxFeedrate_mm_s(X) );
w.color(y_axis) .adjuster( 4, PSTR("Y:"), getAxisMaxFeedrate_mm_s(Y) );
w.color(z_axis) .adjuster( 6, PSTR("Z:"), getAxisMaxFeedrate_mm_s(Z) );
#if EXTRUDERS == 1 || DISABLED(DISTINCT_E_FACTORS)
w.color(e_axis) .adjuster( 8, PSTR("E:"), getAxisMaxFeedrate_mm_s(E0) );
#elif EXTRUDERS > 1
w.color(e_axis) .adjuster( 8, PSTR("E1:"), getAxisMaxFeedrate_mm_s(E0) );
w.color(e_axis) .adjuster( 10, PSTR("E2:"), getAxisMaxFeedrate_mm_s(E1) );
#if EXTRUDERS > 2
w.color(e_axis).adjuster( 12, PSTR("E3:"), getAxisMaxFeedrate_mm_s(E2) );
#endif
#if EXTRUDERS > 3
w.color(e_axis).adjuster( 14, PSTR("E4:"), getAxisMaxFeedrate_mm_s(E3) );
#endif
#endif
w.increments();
}
bool MaxVelocityScreen::onTouchHeld(uint8_t tag) {
const float increment = getIncrement();
switch (tag) {
case 2: UI_DECREMENT(AxisMaxFeedrate_mm_s, X); break;
case 3: UI_INCREMENT(AxisMaxFeedrate_mm_s, X); break;
case 4: UI_DECREMENT(AxisMaxFeedrate_mm_s, Y); break;
case 5: UI_INCREMENT(AxisMaxFeedrate_mm_s, Y); break;
case 6: UI_DECREMENT(AxisMaxFeedrate_mm_s, Z); break;
case 7: UI_INCREMENT(AxisMaxFeedrate_mm_s, Z); break;
case 8: UI_DECREMENT(AxisMaxFeedrate_mm_s, E0); break;
case 9: UI_INCREMENT(AxisMaxFeedrate_mm_s, E0); break;
#if EXTRUDERS > 1 && ENABLED(DISTINCT_E_FACTORS)
case 10: UI_DECREMENT(AxisMaxFeedrate_mm_s, E1); break;
case 11: UI_INCREMENT(AxisMaxFeedrate_mm_s, E1); break;
#endif
#if EXTRUDERS > 2 && ENABLED(DISTINCT_E_FACTORS)
case 12: UI_DECREMENT(AxisMaxFeedrate_mm_s, E2); break;
case 13: UI_INCREMENT(AxisMaxFeedrate_mm_s, E2); break;
#endif
#if EXTRUDERS > 3 && ENABLED(DISTINCT_E_FACTORS)
case 14: UI_DECREMENT(AxisMaxFeedrate_mm_s, E3); break;
case 15: UI_INCREMENT(AxisMaxFeedrate_mm_s, E3); break;
#endif
default:
return false;
}
SaveSettingsDialogBox::settingsChanged();
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,169 @@
/***************************
* media_player_screen.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 "../config.h"
/**
* The MediaPlayerScreen allows an AVI to be played.
*
* It requires a special AVI file. The following video
* and audio codecs must be used:
*
* -vcodec mjpeg -pix_fmt yuvj420p
* -acodec adpcm_ima_wav
*
* To generate a 2 second static screen from a png file:
*
* ffmpeg -i startup.png -vcodec mjpeg -pix_fmt yuvj420p -r 1 video.avi
* sox -n -r 44100 -b 8 -c 2 -L silence.wav trim 0.0 2.000
* ffmpeg -i silence.wav -acodec adpcm_ima_wav silence.avi
* ffmpeg -i video.avi -i silence.wav -c copy -map 0:v:0 -map 1:a:0 startup.avi
*/
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
#include "../archim2-flash/flash_storage.h"
#include "../archim2-flash/media_file_reader.h"
using namespace FTDI;
void MediaPlayerScreen::onEntry() {
BaseScreen::onEntry();
CLCD::turn_on_backlight();
SoundPlayer::set_volume(255);
}
void MediaPlayerScreen::onRedraw(draw_mode_t) {
}
bool MediaPlayerScreen::playCardMedia() {
#if ENABLED(SDSUPPORT)
char fname[15];
strcpy_P(fname, PSTR("STARTUP.AVI"));
MediaFileReader reader;
if (!reader.open(fname))
return false;
SERIAL_ECHO_START();
SERIAL_ECHOLNPGM("Starting to play STARTUP.AVI");
playStream(&reader, MediaFileReader::read);
reader.close();
#endif
return true;
}
// Attempt to play media from the onboard SPI flash chip
bool MediaPlayerScreen::playBootMedia() {
UIFlashStorage::BootMediaReader reader;
if (!reader.isAvailable()) return false;
SERIAL_ECHO_START();
SERIAL_ECHOLNPGM("Starting to play boot video");
playStream(&reader, UIFlashStorage::BootMediaReader::read);
return true;
}
void MediaPlayerScreen::playStream(void *obj, media_streamer_func_t *data_stream) {
#if FTDI_API_LEVEL >= 810
if (FTDI::ftdi_chip >= 810) {
// Set up the media FIFO on the end of RAMG, as the top of RAMG
// will be used as the framebuffer.
uint8_t buf[512];
const uint32_t block_size = 512;
const uint32_t fifo_size = block_size * 2;
const uint32_t fifo_start = CLCD::MAP::RAM_G + CLCD::MAP::RAM_G_SIZE - fifo_size;
CommandProcessor cmd;
cmd.cmd(CMD_DLSTART)
.cmd(CLEAR_COLOR_RGB(0x000000))
.cmd(CLEAR(true,true,true))
.cmd(DL::DL_DISPLAY)
.cmd(CMD_SWAP)
.execute()
.cmd(CMD_DLSTART)
.mediafifo(fifo_start, fifo_size)
.playvideo(OPT_FULLSCREEN | OPT_MEDIAFIFO | OPT_NOTEAR | OPT_SOUND)
.cmd(DL::DL_DISPLAY)
.cmd(CMD_SWAP)
.execute();
uint32_t writePtr = 0;
int16_t nBytes;
uint32_t t = millis();
uint8_t timeouts;
spiInit(SPI_HALF_SPEED); // Boost SPI speed for video playback
do {
// Write block n
nBytes = (*data_stream)(obj, buf, block_size);
if (nBytes == -1) break;
if (millis() - t > 10) {
ExtUI::yield();
t = millis();
}
CLCD::mem_write_bulk (fifo_start + writePtr, buf, nBytes);
// Wait for FTDI810 to finish playing block n-1
timeouts = 20;
do {
if (millis() - t > 10) {
ExtUI::yield();
t = millis();
timeouts--;
if (timeouts == 0) {
SERIAL_ECHO_START();
SERIAL_ECHOLNPGM("Timeout playing video");
cmd.reset();
goto exit;
}
}
} while (CLCD::mem_read_32(CLCD::REG::MEDIAFIFO_READ) != writePtr);
// Start playing block n
writePtr = (writePtr + nBytes) % fifo_size;
CLCD::mem_write_32(CLCD::REG::MEDIAFIFO_WRITE, writePtr);
} while (nBytes == block_size);
SERIAL_ECHO_START();
SERIAL_ECHOLNPGM("Done playing video");
exit:
spiInit(SPI_SPEED); // Restore default speed
// Since playing media overwrites RAMG, we need to reinitialize
// everything that is stored in RAMG.
cmd.cmd(CMD_DLSTART).execute();
DLCache::init();
StatusScreen::onStartup();
}
#endif // FTDI_API_LEVEL >= 810
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,132 @@
/************************
* move_axis_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
#include "screen_data.h"
using namespace FTDI;
using namespace ExtUI;
void MoveAxisScreen::onEntry() {
// Since Marlin keeps only one absolute position for all the extruders,
// we have to keep track of the relative motion of individual extruders
// ourselves. The relative distances are reset to zero whenever this
// screen is entered.
for(uint8_t i = 0; i < ExtUI::extruderCount; i++) {
screen_data.MoveAxisScreen.e_rel[i] = 0;
}
BaseNumericAdjustmentScreen::onEntry();
}
void MoveAxisScreen::onRedraw(draw_mode_t what) {
widgets_t w(what);
w.precision(1);
w.units(PSTR("mm"));
w.heading( PSTR("Move Axis"));
w.home_buttons(20);
w.color(Theme::x_axis ) .adjuster( 2, PSTR("X:"), getAxisPosition_mm(X), canMove(X));
w.color(Theme::y_axis ) .adjuster( 4, PSTR("Y:"), getAxisPosition_mm(Y), canMove(Y));
w.color(Theme::z_axis ) .adjuster( 6, PSTR("Z:"), getAxisPosition_mm(Z), canMove(Z));
#if EXTRUDERS == 1
w.color(Theme::e_axis) .adjuster( 8, PSTR("E:"), screen_data.MoveAxisScreen.e_rel[0], canMove(E0));
#elif EXTRUDERS > 1
w.color(Theme::e_axis) .adjuster( 8, PSTR("E1:"), screen_data.MoveAxisScreen.e_rel[0], canMove(E0));
w.color(Theme::e_axis) .adjuster( 10, PSTR("E2:"), screen_data.MoveAxisScreen.e_rel[1], canMove(E1));
#if EXTRUDERS > 2
w.color(Theme::e_axis) .adjuster( 12, PSTR("E3:"), screen_data.MoveAxisScreen.e_rel[2], canMove(E2));
#endif
#if EXTRUDERS > 3
w.color(Theme::e_axis) .adjuster( 14, PSTR("E4:"), screen_data.MoveAxisScreen.e_rel[3], canMove(E3));
#endif
#endif
w.increments();
}
bool MoveAxisScreen::onTouchHeld(uint8_t tag) {
#define UI_INCREMENT_AXIS(axis) setManualFeedrate(axis, increment); UI_INCREMENT(AxisPosition_mm, axis);
#define UI_DECREMENT_AXIS(axis) setManualFeedrate(axis, increment); UI_DECREMENT(AxisPosition_mm, axis);
const float increment = getIncrement();
switch (tag) {
case 2: UI_DECREMENT_AXIS(X); break;
case 3: UI_INCREMENT_AXIS(X); break;
case 4: UI_DECREMENT_AXIS(Y); break;
case 5: UI_INCREMENT_AXIS(Y); break;
case 6: UI_DECREMENT_AXIS(Z); break;
case 7: UI_INCREMENT_AXIS(Z); break;
// For extruders, also update relative distances.
case 8: UI_DECREMENT_AXIS(E0); screen_data.MoveAxisScreen.e_rel[0] -= increment; break;
case 9: UI_INCREMENT_AXIS(E0); screen_data.MoveAxisScreen.e_rel[0] += increment; break;
#if EXTRUDERS > 1
case 10: UI_DECREMENT_AXIS(E1); screen_data.MoveAxisScreen.e_rel[1] -= increment; break;
case 11: UI_INCREMENT_AXIS(E1); screen_data.MoveAxisScreen.e_rel[1] += increment; break;
#endif
#if EXTRUDERS > 2
case 12: UI_DECREMENT_AXIS(E2); screen_data.MoveAxisScreen.e_rel[2] -= increment; break;
case 13: UI_INCREMENT_AXIS(E2); screen_data.MoveAxisScreen.e_rel[2] += increment; break;
#endif
#if EXTRUDERS > 3
case 14: UI_DECREMENT_AXIS(E3); screen_data.MoveAxisScreen.e_rel[3] -= increment; break;
case 15: UI_INCREMENT_AXIS(E3); screen_data.MoveAxisScreen.e_rel[3] += increment; break;
#endif
case 20: injectCommands_P(PSTR("G28 X")); break;
case 21: injectCommands_P(PSTR("G28 Y")); break;
case 22: injectCommands_P(PSTR("G28 Z")); break;
case 23: injectCommands_P(PSTR("G28")); break;
default:
return false;
}
#undef UI_DECREMENT_AXIS
#undef UI_INCREMENT_AXIS
return true;
}
float MoveAxisScreen::getManualFeedrate(uint8_t axis, float increment_mm) {
// Compute feedrate so that the tool lags the adjuster when it is
// being held down, this allows enough margin for the planner to
// connect segments and even out the motion.
constexpr float max_manual_feedrate[XYZE] = MAX_MANUAL_FEEDRATE;
return min(max_manual_feedrate[axis]/60, abs(increment_mm * TOUCH_REPEATS_PER_SECOND * 0.80));
}
void MoveAxisScreen::setManualFeedrate(ExtUI::axis_t axis, float increment_mm) {
ExtUI::setFeedrate_mm_s(getManualFeedrate(X_AXIS + (axis - ExtUI::X), increment_mm));
}
void MoveAxisScreen::setManualFeedrate(ExtUI::extruder_t, float increment_mm) {
ExtUI::setFeedrate_mm_s(getManualFeedrate(E_AXIS, increment_mm));
}
void MoveAxisScreen::onIdle() {
if (refresh_timer.elapsed(STATUS_UPDATE_INTERVAL)) {
onRefresh();
refresh_timer.start();
}
BaseScreen::onIdle();
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,73 @@
/*****************************
* nozzle_offsets_screen.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && HOTENDS > 1
#include "screens.h"
using namespace FTDI;
using namespace ExtUI;
void NozzleOffsetScreen::onEntry() {
// Since we don't allow the user to edit the offsets for E0,
// make sure they are all zero.
normalizeNozzleOffset(X);
normalizeNozzleOffset(Y);
normalizeNozzleOffset(Z);
}
void NozzleOffsetScreen::onRedraw(draw_mode_t what) {
widgets_t w(what);
w.precision(2).units(PSTR("mm"));
w.heading( PSTR("Nozzle Offset"));
w.color(Theme::x_axis).adjuster(2, PSTR("X:"), ExtUI::getNozzleOffset_mm(X, E1));
w.color(Theme::y_axis).adjuster(4, PSTR("Y:"), ExtUI::getNozzleOffset_mm(Y, E1));
w.color(Theme::z_axis).adjuster(6, PSTR("Z:"), ExtUI::getNozzleOffset_mm(Z, E1));
#if ENABLED(CALIBRATION_GCODE)
w.button(8, PSTR("Measure automatically"), !isPrinting());
#endif
w.increments();
}
bool NozzleOffsetScreen::onTouchHeld(uint8_t tag) {
const float increment = getIncrement();
switch (tag) {
case 2: UI_DECREMENT(NozzleOffset_mm, X, E1); break;
case 3: UI_INCREMENT(NozzleOffset_mm, X, E1); break;
case 4: UI_DECREMENT(NozzleOffset_mm, Y, E1); break;
case 5: UI_INCREMENT(NozzleOffset_mm, Y, E1); break;
case 6: UI_DECREMENT(NozzleOffset_mm, Z, E1); break;
case 7: UI_INCREMENT(NozzleOffset_mm, Z, E1); break;
#if ENABLED(CALIBRATION_GCODE)
case 8: GOTO_SCREEN(ConfirmAutoCalibrationDialogBox); return true;
#endif
default:
return false;
}
SaveSettingsDialogBox::settingsChanged();
return true;
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,128 @@
/********************
* nudge_nozzle.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI) && ENABLED(BABYSTEPPING)
#include "screens.h"
#include "screen_data.h"
using namespace FTDI;
using namespace Theme;
using namespace ExtUI;
void NudgeNozzleScreen::onEntry() {
screen_data.NudgeNozzleScreen.show_offsets = false;
#if EXTRUDERS > 1
screen_data.NudgeNozzleScreen.link_nozzles = true;
#endif
LOOP_XYZ(i) {
screen_data.NudgeNozzleScreen.rel[i] = 0;
}
BaseNumericAdjustmentScreen::onEntry();
}
void NudgeNozzleScreen::onRedraw(draw_mode_t what) {
widgets_t w(what);
w.precision(2, BaseNumericAdjustmentScreen::DEFAULT_MIDRANGE).units(PSTR("mm"));
w.heading( PSTR("Nudge Nozzle"));
#if ENABLED(BABYSTEP_XY)
w.color(x_axis).adjuster(2, PSTR("X:"), screen_data.NudgeNozzleScreen.rel[0] / getAxisSteps_per_mm(X));
w.color(y_axis).adjuster(4, PSTR("Y:"), screen_data.NudgeNozzleScreen.rel[1] / getAxisSteps_per_mm(Y));
#endif
w.color(z_axis).adjuster(6, PSTR("Z:"), screen_data.NudgeNozzleScreen.rel[2] / getAxisSteps_per_mm(Z));
w.increments();
#if EXTRUDERS > 1
w.toggle (8, PSTR("Adjust Both Nozzles:"), PSTR("no\xFFyes"), screen_data.NudgeNozzleScreen.link_nozzles, PSTR("Yes\nNo"));
#endif
#if EXTRUDERS > 1 || HAS_BED_PROBE
w.toggle (9, PSTR("Show Offsets:"), PSTR("no\xFFyes"), screen_data.NudgeNozzleScreen.show_offsets, PSTR("Yes\nNo"));
if (screen_data.NudgeNozzleScreen.show_offsets) {
char str[19], num1[7];
w.draw_mode(BOTH);
w.color(other);
#if HAS_BED_PROBE
dtostrf(getZOffset_mm(), 4, 2, num1);
sprintf_P(str, PSTR("%s mm"), num1);
w.text_field (0, PSTR("Z Offset"), str);
#endif
#if EXTRUDERS > 1
char num2[7], num3[7];
dtostrf(getNozzleOffset_mm(X, E1), 4, 2, num1);
dtostrf(getNozzleOffset_mm(Y, E1), 4, 2, num2);
dtostrf(getNozzleOffset_mm(Z, E1), 4, 2, num3);
sprintf_P(str, PSTR("%s; %s; %s mm"), num1, num2, num3);
w.text_field (0, PSTR("Noz. Offset"), str);
#endif
}
#endif
}
bool NudgeNozzleScreen::onTouchHeld(uint8_t tag) {
const float inc = getIncrement();
#if EXTRUDERS > 1
const bool link = screen_data.NudgeNozzleScreen.link_nozzles;
#else
constexpr bool link = true;
#endif
int16_t steps;
switch (tag) {
case 2: steps = mmToWholeSteps(inc, X); smartAdjustAxis_steps(-steps, X, link); screen_data.NudgeNozzleScreen.rel[0] -= steps; break;
case 3: steps = mmToWholeSteps(inc, X); smartAdjustAxis_steps( steps, X, link); screen_data.NudgeNozzleScreen.rel[0] += steps; break;
case 4: steps = mmToWholeSteps(inc, Y); smartAdjustAxis_steps(-steps, Y, link); screen_data.NudgeNozzleScreen.rel[1] -= steps; break;
case 5: steps = mmToWholeSteps(inc, Y); smartAdjustAxis_steps( steps, Y, link); screen_data.NudgeNozzleScreen.rel[1] += steps; break;
case 6: steps = mmToWholeSteps(inc, Z); smartAdjustAxis_steps(-steps, Z, link); screen_data.NudgeNozzleScreen.rel[2] -= steps; break;
case 7: steps = mmToWholeSteps(inc, Z); smartAdjustAxis_steps( steps, Z, link); screen_data.NudgeNozzleScreen.rel[2] += steps; break;
#if EXTRUDERS > 1
case 8: screen_data.NudgeNozzleScreen.link_nozzles = !link; break;
#endif
case 9: screen_data.NudgeNozzleScreen.show_offsets = !screen_data.NudgeNozzleScreen.show_offsets; break;
default:
return false;
}
#if EXTRUDERS > 1 || HAS_BED_PROBE
SaveSettingsDialogBox::settingsChanged();
#endif
return true;
}
bool NudgeNozzleScreen::onTouchEnd(uint8_t tag) {
if (tag == 1) {
SaveSettingsDialogBox::promptToSaveSettings();
return true;
} else {
return BaseNumericAdjustmentScreen::onTouchEnd(tag);
}
}
void NudgeNozzleScreen::onIdle() {
reset_menu_timeout();
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,51 @@
/***********************************
* restore_failsafe_dialog_box.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
using namespace ExtUI;
void RestoreFailsafeDialogBox::onRedraw(draw_mode_t) {
drawMessage(F("Are you sure? Customizations will be lost."));
drawYesNoButtons();
}
bool RestoreFailsafeDialogBox::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1:
ExtUI::injectCommands_P(PSTR("M502\nM117 Factory settings restored."));
AlertDialogBox::show(F("Factory settings restored."));
// Remove RestoreFailsafeDialogBox from the stack
// so the alert box doesn't return to it.
current_screen.forget();
SaveSettingsDialogBox::settingsChanged();
return true;
default:
return DialogBoxBaseClass::onTouchEnd(tag);
}
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,65 @@
/********************************
* save_settings_dialog_box.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
using namespace ExtUI;
bool SaveSettingsDialogBox::needs_save = false;
void SaveSettingsDialogBox::onRedraw(draw_mode_t) {
drawMessage(F("Do you wish to save these settings as defaults?"));
drawYesNoButtons();
}
bool SaveSettingsDialogBox::onTouchEnd(uint8_t tag) {
needs_save = false;
switch (tag) {
case 1:
injectCommands_P(PSTR("M500"));
AlertDialogBox::show(F("Settings saved!"));
// Remove SaveSettingsDialogBox from the stack
// so the alert box doesn't return to me.
current_screen.forget();
return true;
default:
return DialogBoxBaseClass::onTouchEnd(tag);
}
}
void SaveSettingsDialogBox::promptToSaveSettings() {
if (needs_save) {
// Remove current screen from the stack
// so SaveSettingsDialogBox doesn't return here.
GOTO_SCREEN(SaveSettingsDialogBox);
current_screen.forget();
} else {
// No save needed.
GOTO_PREVIOUS();
}
}
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,77 @@
/*****************
* screen_data.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 "../ftdi_eve_lib/ftdi_eve_lib.h"
// To save RAM, store state information related to a particular screen
// in a union. The values should be initialized in the onEntry method.
struct base_numeric_adjustment_t {uint8_t increment;};
union screen_data_t {
struct base_numeric_adjustment_t BaseNumericAdjustmentScreen;
struct {uint8_t volume; uint8_t brightness;} InterfaceSettingsScreen;
struct {char passcode[5];} LockScreen;
struct {bool isError;} AlertDialogBox;
struct {bool auto_hide;} SpinnerDialogBox;
struct {
uint8_t e_tag, t_tag, repeat_tag;
ExtUI::extruder_t saved_extruder;
} ChangeFilamentScreen;
struct {
struct {
uint8_t is_dir : 1;
uint8_t is_root : 1;
} flags;
uint8_t selected_tag;
uint8_t num_page;
uint8_t cur_page;
#if ENABLED(SCROLL_LONG_FILENAMES) && (FTDI_API_LEVEL >= 810)
uint16_t scroll_pos;
uint16_t scroll_max;
#endif
} FilesScreen;
struct {
struct base_numeric_adjustment_t placeholder;
float e_rel[ExtUI::extruderCount];
} MoveAxisScreen;
#if ENABLED(DEVELOPER_SCREENS)
struct {
uint32_t next_watchdog_trigger;
const char* message;
} StressTestScreen;
#endif
#if ENABLED(BABYSTEPPING)
struct {
struct base_numeric_adjustment_t placeholder;
int16_t rel[XYZ];
#if EXTRUDERS > 1
bool link_nozzles;
#endif
bool show_offsets;
} NudgeNozzleScreen;
#endif
};
extern screen_data_t screen_data;

@ -0,0 +1,113 @@
/***************
* screens.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 "../config.h"
#if ENABLED(LULZBOT_TOUCH_UI)
#include "screens.h"
#include "screen_data.h"
tiny_timer_t refresh_timer;
screen_data_t screen_data;
SCREEN_TABLE {
DECL_SCREEN(BootScreen),
DECL_SCREEN(TouchCalibrationScreen),
DECL_SCREEN(StatusScreen),
DECL_SCREEN(MainMenu),
DECL_SCREEN(TuneMenu),
DECL_SCREEN(AdvancedSettingsMenu),
DECL_SCREEN(AlertDialogBox),
DECL_SCREEN(ConfirmUserRequestAlertBox),
DECL_SCREEN(RestoreFailsafeDialogBox),
DECL_SCREEN(SaveSettingsDialogBox),
DECL_SCREEN(ConfirmAbortPrintDialogBox),
#if ENABLED(CALIBRATION_GCODE)
DECL_SCREEN(ConfirmAutoCalibrationDialogBox),
#endif
DECL_SCREEN(SpinnerDialogBox),
DECL_SCREEN(AboutScreen),
#if ENABLED(PRINTCOUNTER)
DECL_SCREEN(StatisticsScreen),
#endif
#if ENABLED(BABYSTEPPING)
DECL_SCREEN(NudgeNozzleScreen),
#endif
DECL_SCREEN(MoveAxisScreen),
DECL_SCREEN(StepsScreen),
#if HAS_TRINAMIC
DECL_SCREEN(StepperCurrentScreen),
DECL_SCREEN(StepperBumpSensitivityScreen),
#endif
#if HAS_BED_PROBE
DECL_SCREEN(ZOffsetScreen),
#endif
#if HOTENDS > 1
DECL_SCREEN(NozzleOffsetScreen),
#endif
#if ENABLED(BACKLASH_GCODE)
DECL_SCREEN(BacklashCompensationScreen),
#endif
DECL_SCREEN(FeedratePercentScreen),
DECL_SCREEN(MaxVelocityScreen),
DECL_SCREEN(MaxAccelerationScreen),
DECL_SCREEN(DefaultAccelerationScreen),
#if ENABLED(JUNCTION_DEVIATION)
DECL_SCREEN(JunctionDeviationScreen),
#else
DECL_SCREEN(JerkScreen),
#endif
#if ENABLED(LIN_ADVANCE) || ENABLED(FILAMENT_RUNOUT_SENSOR)
DECL_SCREEN(FilamentMenu),
#endif
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
DECL_SCREEN(FilamentRunoutScreen),
#endif
#if ENABLED(LIN_ADVANCE)
DECL_SCREEN(LinearAdvanceScreen),
#endif
DECL_SCREEN(TemperatureScreen),
DECL_SCREEN(ChangeFilamentScreen),
DECL_SCREEN(InterfaceSettingsScreen),
DECL_SCREEN(InterfaceSoundsScreen),
DECL_SCREEN(LockScreen),
DECL_SCREEN(FilesScreen),
DECL_SCREEN(EndstopStatesScreen),
#ifdef LULZBOT_USE_BIOPRINTER_UI
DECL_SCREEN(BioPrintingDialogBox),
DECL_SCREEN(BioConfirmHomeXYZ),
DECL_SCREEN(BioConfirmHomeE),
#endif
#if ENABLED(DEVELOPER_SCREENS)
DECL_SCREEN(DeveloperMenu),
DECL_SCREEN(ConfirmEraseFlashDialogBox),
DECL_SCREEN(WidgetsScreen),
DECL_SCREEN(TouchRegistersScreen),
DECL_SCREEN(StressTestScreen),
#endif
DECL_SCREEN(MediaPlayerScreen),
DECL_SCREEN(DisplayTuningScreen)
};
SCREEN_TABLE_POST
#endif // LULZBOT_TOUCH_UI

@ -0,0 +1,712 @@
/*************
* screens.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 "../ftdi_eve_lib/ftdi_eve_lib.h"
#include "../theme/theme.h"
#define ROUND(val) uint16_t((val)+0.5)
extern tiny_timer_t refresh_timer;
/********************************* DL CACHE SLOTS ******************************/
// In order to reduce SPI traffic, we cache display lists (DL) in RAMG. This
// is done using the CLCD::DLCache class, which takes a unique ID for each
// cache location. These IDs are defined here:
enum {
STATUS_SCREEN_CACHE,
MENU_SCREEN_CACHE,
TUNE_SCREEN_CACHE,
ADJUST_OFFSETS_SCREEN_CACHE,
ALERT_BOX_CACHE,
SPINNER_CACHE,
ADVANCED_SETTINGS_SCREEN_CACHE,
MOVE_AXIS_SCREEN_CACHE,
TEMPERATURE_SCREEN_CACHE,
STEPS_SCREEN_CACHE,
STEPPER_CURRENT_SCREEN_CACHE,
STEPPER_BUMP_SENSITIVITY_SCREEN_CACHE,
ZOFFSET_SCREEN_CACHE,
NOZZLE_OFFSET_SCREEN_CACHE,
BACKLASH_COMPENSATION_SCREEN_CACHE,
MAX_FEEDRATE_SCREEN_CACHE,
MAX_VELOCITY_SCREEN_CACHE,
MAX_ACCELERATION_SCREEN_CACHE,
DEFAULT_ACCELERATION_SCREEN_CACHE,
#if ENABLED(JUNCTION_DEVIATION)
JUNC_DEV_SCREEN_CACHE,
#else
JERK_SCREEN_CACHE,
#endif
#if ENABLED(LIN_ADVANCE) || ENABLED(FILAMENT_RUNOUT_SENSOR)
FILAMENT_MENU_CACHE,
#endif
#if ENABLED(LIN_ADVANCE)
LINEAR_ADVANCE_SCREEN_CACHE,
#endif
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
FILAMENT_RUNOUT_SCREEN_CACHE,
#endif
#ifdef LULZBOT_USE_BIOPRINTER_UI
PRINTING_SCREEN_CACHE,
#endif
CHANGE_FILAMENT_SCREEN_CACHE,
INTERFACE_SETTINGS_SCREEN_CACHE,
INTERFACE_SOUNDS_SCREEN_CACHE,
LOCK_SCREEN_CACHE,
FILES_SCREEN_CACHE,
DISPLAY_TIMINGS_SCREEN_CACHE
};
// To save MCU RAM, the status message is "baked" in to the status screen
// cache, so we reserve a large chunk of memory for the DL cache
#define STATUS_SCREEN_DL_SIZE 2048
#define ALERT_BOX_DL_SIZE 3072
#define SPINNER_DL_SIZE 3072
#define FILE_SCREEN_DL_SIZE 3072
#define PRINTING_SCREEN_DL_SIZE 2048
/************************* MENU SCREEN DECLARATIONS *************************/
class BaseScreen : public UIScreen {
protected:
#ifdef LCD_TIMEOUT_TO_STATUS
static uint32_t last_interaction;
#endif
public:
static bool buttonStyleCallback(CommandProcessor &, uint8_t, uint8_t &, uint16_t &, bool);
static void reset_menu_timeout();
static void onEntry();
static void onIdle();
};
class BootScreen : public BaseScreen, public UncachedScreen {
private:
static void showSplashScreen();
public:
static void onRedraw(draw_mode_t);
static void onIdle();
};
class AboutScreen : public BaseScreen, public UncachedScreen {
public:
static void onEntry();
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
#if ENABLED(PRINTCOUNTER)
class StatisticsScreen : public BaseScreen, public UncachedScreen {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
#endif
class KillScreen {
// The KillScreen is behaves differently than the
// others, so we do not bother extending UIScreen.
public:
static void show(progmem_str msg);
};
class DialogBoxBaseClass : public BaseScreen {
protected:
template<typename T> static void drawMessage(const T, int16_t font = 0);
static void drawYesNoButtons(uint8_t default_btn = 0);
static void drawOkayButton();
static void drawSpinner();
static void drawButton(const progmem_str);
static void onRedraw(draw_mode_t) {};
public:
static bool onTouchEnd(uint8_t tag);
};
class AlertDialogBox : public DialogBoxBaseClass, public CachedScreen<ALERT_BOX_CACHE,ALERT_BOX_DL_SIZE> {
public:
static void onEntry();
static void onRedraw(draw_mode_t);
template<typename T> static void show(T);
template<typename T> static void showError(T);
static void hide();
};
class RestoreFailsafeDialogBox : public DialogBoxBaseClass, public UncachedScreen {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
class SaveSettingsDialogBox : public DialogBoxBaseClass, public UncachedScreen {
private:
static bool needs_save;
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
static void promptToSaveSettings();
static void settingsChanged() {needs_save = true;}
};
class ConfirmAbortPrintDialogBox : public DialogBoxBaseClass, public UncachedScreen {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
#if ENABLED(CALIBRATION_GCODE)
class ConfirmAutoCalibrationDialogBox : public DialogBoxBaseClass, public UncachedScreen {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
#endif
class ConfirmUserRequestAlertBox : public AlertDialogBox {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t);
static void hide();
static void show(const char*);
};
class SpinnerDialogBox : public DialogBoxBaseClass, public CachedScreen<SPINNER_CACHE,SPINNER_DL_SIZE> {
public:
static void onRedraw(draw_mode_t);
static void onIdle();
static void show(const progmem_str);
static void hide();
static void enqueueAndWait_P(const progmem_str commands);
static void enqueueAndWait_P(const progmem_str message, const progmem_str commands);
};
#if !defined(LULZBOT_USE_BIOPRINTER_UI)
class StatusScreen : public BaseScreen, public CachedScreen<STATUS_SCREEN_CACHE,STATUS_SCREEN_DL_SIZE> {
private:
static void draw_axis_position(draw_mode_t);
static void draw_temperature(draw_mode_t);
static void draw_progress(draw_mode_t);
static void draw_interaction_buttons(draw_mode_t);
static void draw_status_message(draw_mode_t, const char * const);
public:
static void setStatusMessage(const char *);
static void setStatusMessage(progmem_str);
static void onRedraw(draw_mode_t);
static void onStartup();
static void onEntry();
static void onIdle();
static bool onTouchEnd(uint8_t tag);
};
#else
class StatusScreen : public BaseScreen, public CachedScreen<STATUS_SCREEN_CACHE> {
private:
static float increment;
static bool jog_xy;
static bool fine_motion;
static void draw_temperature(draw_mode_t what);
static void draw_syringe(draw_mode_t what);
static void draw_arrows(draw_mode_t what);
static void draw_overlay_icons(draw_mode_t what);
static void draw_fine_motion(draw_mode_t what);
static void draw_buttons(draw_mode_t what);
public:
static void unlockMotors();
static void setStatusMessage(const char *);
static void setStatusMessage(progmem_str);
static void onStartup();
static void onRedraw(draw_mode_t);
static bool onTouchStart(uint8_t tag);
static bool onTouchHeld(uint8_t tag);
static bool onTouchEnd(uint8_t tag);
static void onIdle();
};
class BioPrintingDialogBox : public BaseScreen, public CachedScreen<PRINTING_SCREEN_CACHE,PRINTING_SCREEN_DL_SIZE> {
private:
static void draw_status_message(draw_mode_t, const char * const);
static void draw_progress(draw_mode_t);
static void draw_time_remaining(draw_mode_t);
static void draw_interaction_buttons(draw_mode_t);
public:
static void onRedraw(draw_mode_t);
static void show();
static void setStatusMessage(const char *);
static void setStatusMessage(progmem_str);
static void onIdle();
static bool onTouchEnd(uint8_t tag);
};
class BioConfirmHomeXYZ : public DialogBoxBaseClass, public UncachedScreen {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
class BioConfirmHomeE : public DialogBoxBaseClass, public UncachedScreen {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
#endif
class MainMenu : public BaseScreen, public CachedScreen<MENU_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
class TuneMenu : public BaseScreen, public CachedScreen<TUNE_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
class TouchCalibrationScreen : public BaseScreen, public UncachedScreen {
public:
static void onRefresh();
static void onEntry();
static void onRedraw(draw_mode_t);
static void onIdle();
};
class TouchRegistersScreen : public BaseScreen, public UncachedScreen {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
class AdvancedSettingsMenu : public BaseScreen, public CachedScreen<ADVANCED_SETTINGS_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
class ChangeFilamentScreen : public BaseScreen, public CachedScreen<CHANGE_FILAMENT_SCREEN_CACHE> {
private:
static uint8_t getSoftenTemp();
static ExtUI::extruder_t getExtruder();
static void drawTempGradient(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
static uint32_t getTempColor(uint32_t temp);
public:
static void onEntry();
static void onExit();
static void onRedraw(draw_mode_t);
static bool onTouchStart(uint8_t tag);
static bool onTouchEnd(uint8_t tag);
static bool onTouchHeld(uint8_t tag);
static void onIdle();
};
class BaseNumericAdjustmentScreen : public BaseScreen {
public:
enum precision_default_t {
DEFAULT_LOWEST,
DEFAULT_MIDRANGE,
DEFAULT_HIGHEST
};
protected:
class widgets_t {
private:
draw_mode_t _what;
uint8_t _line;
uint32_t _color;
uint8_t _decimals;
const char *_units;
protected:
void _draw_increment_btn(uint8_t line, const uint8_t tag);
public:
widgets_t(draw_mode_t);
widgets_t &color(uint32_t color) {_color = color; return *this;}
widgets_t &units(const char *units) {_units = units; return *this;}
widgets_t &draw_mode(draw_mode_t what) {_what = what; return *this;}
widgets_t &precision(uint8_t decimals, precision_default_t = DEFAULT_HIGHEST);
void heading (const char *label);
void adjuster_sram_val (uint8_t tag, const char *label, const char *value, bool is_enabled = true);
void adjuster (uint8_t tag, const char *label, const char *value, bool is_enabled = true);
void adjuster (uint8_t tag, const char *label, float value=0, bool is_enabled = true);
void button (uint8_t tag, const char *label, bool is_enabled = true);
void text_field (uint8_t tag, const char *label, const char *value, bool is_enabled = true);
void two_buttons (uint8_t tag1, const char *label1,
uint8_t tag2, const char *label2, bool is_enabled = true);
void toggle (uint8_t tag, const char *label, const char *text, bool value, bool is_enabled = true);
void home_buttons (uint8_t tag);
void increments ();
};
static float getIncrement();
public:
static void onEntry();
static bool onTouchEnd(uint8_t tag);
};
class MoveAxisScreen : public BaseNumericAdjustmentScreen, public CachedScreen<MOVE_AXIS_SCREEN_CACHE> {
private:
static float getManualFeedrate(uint8_t axis, float increment_mm);
public:
static void setManualFeedrate(ExtUI::axis_t, float increment_mm);
static void setManualFeedrate(ExtUI::extruder_t, float increment_mm);
static void onEntry();
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
static void onIdle();
};
class StepsScreen : public BaseNumericAdjustmentScreen, public CachedScreen<STEPS_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
#if HAS_TRINAMIC
class StepperCurrentScreen : public BaseNumericAdjustmentScreen, public CachedScreen<STEPPER_CURRENT_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
class StepperBumpSensitivityScreen : public BaseNumericAdjustmentScreen, public CachedScreen<STEPPER_BUMP_SENSITIVITY_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
#endif
#if HAS_BED_PROBE
class ZOffsetScreen : public BaseNumericAdjustmentScreen, public CachedScreen<ZOFFSET_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
#endif
#if HOTENDS > 1
class NozzleOffsetScreen : public BaseNumericAdjustmentScreen, public CachedScreen<NOZZLE_OFFSET_SCREEN_CACHE> {
public:
static void onEntry();
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
#endif
#if ENABLED(BABYSTEPPING)
class NudgeNozzleScreen : public BaseNumericAdjustmentScreen, public CachedScreen<ADJUST_OFFSETS_SCREEN_CACHE> {
public:
static void onEntry();
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
static bool onTouchHeld(uint8_t tag);
static void onIdle();
};
#endif
#if ENABLED(BACKLASH_GCODE)
class BacklashCompensationScreen : public BaseNumericAdjustmentScreen, public CachedScreen<BACKLASH_COMPENSATION_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
#endif
class FeedratePercentScreen : public BaseNumericAdjustmentScreen, public CachedScreen<MAX_FEEDRATE_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
class MaxVelocityScreen : public BaseNumericAdjustmentScreen, public CachedScreen<MAX_VELOCITY_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
class MaxAccelerationScreen : public BaseNumericAdjustmentScreen, public CachedScreen<MAX_ACCELERATION_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
class DefaultAccelerationScreen : public BaseNumericAdjustmentScreen, public CachedScreen<DEFAULT_ACCELERATION_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
#if ENABLED(JUNCTION_DEVIATION)
class JunctionDeviationScreen : public BaseNumericAdjustmentScreen, public CachedScreen<JUNC_DEV_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
#else
class JerkScreen : public BaseNumericAdjustmentScreen, public CachedScreen<JERK_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
#endif
#if ENABLED(LIN_ADVANCE) || ENABLED(FILAMENT_RUNOUT_SENSOR)
class FilamentMenu : public BaseNumericAdjustmentScreen, public CachedScreen<FILAMENT_MENU_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
#endif
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
class FilamentRunoutScreen : public BaseNumericAdjustmentScreen, public CachedScreen<FILAMENT_RUNOUT_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
#endif
#if ENABLED(LIN_ADVANCE)
class LinearAdvanceScreen : public BaseNumericAdjustmentScreen, public CachedScreen<LINEAR_ADVANCE_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
#endif
class TemperatureScreen : public BaseNumericAdjustmentScreen, public CachedScreen<TEMPERATURE_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
class InterfaceSoundsScreen : public BaseScreen, public CachedScreen<INTERFACE_SOUNDS_SCREEN_CACHE> {
public:
enum event_t {
PRINTING_STARTED = 0,
PRINTING_FINISHED = 1,
PRINTING_FAILED = 2,
NUM_EVENTS
};
private:
friend class InterfaceSettingsScreen;
static uint8_t event_sounds[NUM_EVENTS];
static const char* getSoundSelection(event_t);
static void toggleSoundSelection(event_t);
static void setSoundSelection(event_t, const FTDI::SoundPlayer::sound_t*);
public:
static void playEventSound(event_t, FTDI::play_mode_t = FTDI::PLAY_ASYNCHRONOUS);
static void defaultSettings();
static void onEntry();
static void onRedraw(draw_mode_t);
static bool onTouchStart(uint8_t tag);
static bool onTouchEnd(uint8_t tag);
static void onIdle();
};
class InterfaceSettingsScreen : public BaseScreen, public CachedScreen<INTERFACE_SETTINGS_SCREEN_CACHE> {
private:
struct persistent_data_t {
uint32_t touch_transform_a;
uint32_t touch_transform_b;
uint32_t touch_transform_c;
uint32_t touch_transform_d;
uint32_t touch_transform_e;
uint32_t touch_transform_f;
uint16_t passcode;
uint8_t display_brightness;
int8_t display_h_offset_adj;
int8_t display_v_offset_adj;
uint8_t sound_volume;
uint8_t bit_flags;
uint8_t event_sounds[InterfaceSoundsScreen::NUM_EVENTS];
};
public:
#ifdef LULZBOT_EEPROM_BACKUP_SIZE
static bool backupEEPROM();
#endif
static void saveSettings(char *);
static void loadSettings(const char *);
static void defaultSettings();
static void failSafeSettings();
static void onStartup();
static void onEntry();
static void onRedraw(draw_mode_t);
static bool onTouchStart(uint8_t tag);
static bool onTouchEnd(uint8_t tag);
static void onIdle();
};
class LockScreen : public BaseScreen, public CachedScreen<LOCK_SCREEN_CACHE> {
private:
friend InterfaceSettingsScreen;
static uint16_t passcode;
static char & message_style();
static uint16_t compute_checksum();
static void onPasscodeEntered();
public:
static bool is_enabled();
static void check_passcode();
static void enable();
static void disable();
static void set_hash(uint16_t pass) {passcode = pass;};
static uint16_t get_hash() {return passcode;};
static void onEntry();
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
class FilesScreen : public BaseScreen, public CachedScreen<FILES_SCREEN_CACHE, FILE_SCREEN_DL_SIZE> {
private:
#ifdef TOUCH_UI_PORTRAIT
static constexpr uint8_t header_h = 2;
static constexpr uint8_t footer_h = 2;
static constexpr uint8_t files_per_page = 11;
#else
static constexpr uint8_t header_h = 1;
static constexpr uint8_t footer_h = 1;
static constexpr uint8_t files_per_page = 6;
#endif
static uint8_t getTagForLine(uint8_t line) {return line + 2;}
static uint8_t getLineForTag(uint8_t tag) {return tag - 2;}
static uint16_t getFileForTag(uint8_t tag);
static const char *getSelectedShortFilename();
static const char *getSelectedLongFilename();
static void drawFileButton(const char* filename, uint8_t tag, bool is_dir, bool is_highlighted);
static void drawFileList();
static void drawHeader();
static void drawFooter();
static void drawSelectedFile();
static void gotoPage(uint8_t);
public:
static void onEntry();
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
static void onIdle();
};
class EndstopStatesScreen : public BaseScreen, public UncachedScreen {
public:
static void onEntry();
static void onExit();
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
static void onIdle();
};
class DisplayTuningScreen : public BaseNumericAdjustmentScreen, public CachedScreen<DISPLAY_TIMINGS_SCREEN_CACHE> {
public:
static void onRedraw(draw_mode_t);
static bool onTouchHeld(uint8_t tag);
};
#if ENABLED(DEVELOPER_SCREENS)
class DeveloperMenu : public BaseScreen, public UncachedScreen {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
class ConfirmEraseFlashDialogBox : public DialogBoxBaseClass, public UncachedScreen {
public:
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
};
class WidgetsScreen : public BaseScreen, public UncachedScreen {
public:
static void onEntry();
static void onRedraw(draw_mode_t);
static bool onTouchStart(uint8_t tag);
static void onIdle();
};
class StressTestScreen : public BaseScreen, public UncachedScreen {
private:
static void drawDots(uint16_t x, uint16_t y, uint16_t h, uint16_t v);
static bool watchDogTestNow();
static void recursiveLockup();
static void iterativeLockup();
static void runTestOnBootup(bool enable);
public:
static void startupCheck();
static void onEntry();
static void onRedraw(draw_mode_t);
static bool onTouchEnd(uint8_t tag);
static void onIdle();
};
#endif
class MediaPlayerScreen : public BaseScreen, public UncachedScreen {
private:
typedef int16_t media_streamer_func_t(void *obj, void *buff, size_t bytes);
public:
static bool playCardMedia();
static bool playBootMedia();
static void onEntry();
static void onRedraw(draw_mode_t);
static void playStream(void *obj, media_streamer_func_t*);
};

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save