Marcio Teixeira
6 years ago
committed by
Scott Lahteine
356 changed files with 22195 additions and 58 deletions
@ -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 |
File diff suppressed because it is too large
@ -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
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue