You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1220 lines
33 KiB
1220 lines
33 KiB
/****************
|
|
* 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: <https://www.gnu.org/licenses/>. *
|
|
****************************************************************************/
|
|
|
|
#include "ftdi_basic.h"
|
|
|
|
#ifdef FTDI_BASIC
|
|
|
|
#define MULTIPLE_OF_4(val) ((((val)+3)>>2)<<2)
|
|
|
|
using namespace FTDI;
|
|
using namespace FTDI::SPI;
|
|
|
|
void CLCD::enable() {
|
|
mem_write_8(REG::PCLK, Pclk);
|
|
}
|
|
|
|
void CLCD::disable() {
|
|
mem_write_8(REG::PCLK, 0x00);
|
|
}
|
|
|
|
void CLCD::set_brightness(uint8_t brightness) {
|
|
mem_write_8(REG::PWM_DUTY, min(128,brightness));
|
|
}
|
|
|
|
uint8_t CLCD::get_brightness() {
|
|
return mem_read_8(REG::PWM_DUTY);
|
|
}
|
|
|
|
void CLCD::turn_on_backlight() {
|
|
mem_write_8(REG::PWM_DUTY, 128);
|
|
}
|
|
|
|
void CLCD::FontMetrics::load(const uint8_t font) {
|
|
static_assert(sizeof(FontMetrics) == 148, "Sizeof font metrics is incorrect");
|
|
uint32_t rom_fontroot = mem_read_32(MAP::ROM_FONT_ADDR);
|
|
mem_read_bulk(rom_fontroot + 148 * (font - 16), (uint8_t*) this, 148);
|
|
}
|
|
|
|
uint16_t CLCD::FontMetrics::get_text_width(const char *str, size_t n) const {
|
|
uint16_t width = 0;
|
|
const uint8_t *p = (const uint8_t *) str;
|
|
for (;;) {
|
|
const uint8_t val = *p++; n--;
|
|
if (!val || n == 0) break;
|
|
width += val < 128 ? char_widths[val] : 0;
|
|
}
|
|
return width;
|
|
}
|
|
|
|
uint16_t CLCD::FontMetrics::get_text_width(progmem_str str, size_t n) const {
|
|
uint16_t width = 0;
|
|
const uint8_t *p = (const uint8_t *) str;
|
|
for (;;) {
|
|
const uint8_t val = pgm_read_byte(p++); n--;
|
|
if (!val || n == 0) break;
|
|
width += val < 128 ? char_widths[val] : 0;
|
|
}
|
|
return width;
|
|
}
|
|
|
|
/************************** HOST COMMAND FUNCTION *********************************/
|
|
|
|
void CLCD::host_cmd(unsigned char host_command, unsigned char byte2) { // Sends 24-Bit Host Command to LCD
|
|
if (host_command != FTDI::ACTIVE) {
|
|
host_command |= 0x40;
|
|
}
|
|
spi_ftdi_select();
|
|
spi_send(host_command);
|
|
spi_send(byte2);
|
|
spi_send(0x00);
|
|
spi_ftdi_deselect();
|
|
}
|
|
|
|
/************************** MEMORY READ FUNCTIONS *********************************/
|
|
|
|
void CLCD::spi_read_addr(uint32_t reg_address) {
|
|
spi_send((reg_address >> 16) & 0x3F); // Address [21:16]
|
|
spi_send((reg_address >> 8 ) & 0xFF); // Address [15:8]
|
|
spi_send((reg_address >> 0) & 0xFF); // Address [7:0]
|
|
spi_send(0x00); // Dummy Byte
|
|
}
|
|
|
|
// Write 4-Byte Address, Read Multiple Bytes
|
|
void CLCD::mem_read_bulk(uint32_t reg_address, uint8_t *data, uint16_t len) {
|
|
spi_ftdi_select();
|
|
spi_read_addr(reg_address);
|
|
spi_read_bulk (data, len);
|
|
spi_ftdi_deselect();
|
|
}
|
|
|
|
// Write 4-Byte Address, Read 1-Byte Data
|
|
uint8_t CLCD::mem_read_8(uint32_t reg_address) {
|
|
spi_ftdi_select();
|
|
spi_read_addr(reg_address);
|
|
uint8_t r_data = spi_read_8();
|
|
spi_ftdi_deselect();
|
|
return r_data;
|
|
}
|
|
|
|
// Write 4-Byte Address, Read 2-Bytes Data
|
|
uint16_t CLCD::mem_read_16(uint32_t reg_address) {
|
|
using namespace SPI::least_significant_byte_first;
|
|
spi_ftdi_select();
|
|
spi_read_addr(reg_address);
|
|
uint16_t r_data = spi_read_16();
|
|
spi_ftdi_deselect();
|
|
return r_data;
|
|
}
|
|
|
|
// Write 4-Byte Address, Read 4-Bytes Data
|
|
uint32_t CLCD::mem_read_32(uint32_t reg_address) {
|
|
using namespace SPI::least_significant_byte_first;
|
|
spi_ftdi_select();
|
|
spi_read_addr(reg_address);
|
|
uint32_t r_data = spi_read_32();
|
|
spi_ftdi_deselect();
|
|
return r_data;
|
|
}
|
|
|
|
/************************** MEMORY WRITE FUNCTIONS *********************************/
|
|
|
|
// Generic operations for transforming a byte, for use with _mem_write_bulk:
|
|
static inline uint8_t reverse_byte(uint8_t a) {
|
|
return ((a & 0x1) << 7) | ((a & 0x2) << 5) |
|
|
((a & 0x4) << 3) | ((a & 0x8) << 1) |
|
|
((a & 0x10) >> 1) | ((a & 0x20) >> 3) |
|
|
((a & 0x40) >> 5) | ((a & 0x80) >> 7);
|
|
}
|
|
static inline uint8_t xbm_write(const uint8_t *p) {return reverse_byte(pgm_read_byte(p));}
|
|
|
|
void CLCD::spi_write_addr(uint32_t reg_address) {
|
|
spi_send((reg_address >> 16) | 0x80); // Address [21:16]
|
|
spi_send((reg_address >> 8 ) & 0xFF); // Address [15:8]
|
|
spi_send((reg_address >> 0) & 0xFF); // Address [7:0]
|
|
}
|
|
|
|
// Write 3-Byte Address, Multiple Bytes, plus padding bytes, from RAM
|
|
void CLCD::mem_write_bulk(uint32_t reg_address, const void *data, uint16_t len, uint8_t padding) {
|
|
spi_ftdi_select();
|
|
spi_write_addr(reg_address);
|
|
spi_write_bulk<ram_write>(data, len, padding);
|
|
spi_ftdi_deselect();
|
|
}
|
|
|
|
// Write 3-Byte Address, Multiple Bytes, plus padding bytes, from PROGMEM
|
|
void CLCD::mem_write_bulk(uint32_t reg_address, progmem_str str, uint16_t len, uint8_t padding) {
|
|
spi_ftdi_select();
|
|
spi_write_addr(reg_address);
|
|
spi_write_bulk<pgm_write>(str, len, padding);
|
|
spi_ftdi_deselect();
|
|
}
|
|
|
|
// Write 3-Byte Address, Multiple Bytes, plus padding bytes, from PROGMEM
|
|
void CLCD::mem_write_pgm(uint32_t reg_address, const void *data, uint16_t len, uint8_t padding) {
|
|
spi_ftdi_select();
|
|
spi_write_addr(reg_address);
|
|
spi_write_bulk<pgm_write>(data, len, padding);
|
|
spi_ftdi_deselect();
|
|
}
|
|
|
|
// Write 3-Byte Address, Multiple Bytes, plus padding bytes, from PROGMEM, reversing bytes (suitable for loading XBM images)
|
|
void CLCD::mem_write_xbm(uint32_t reg_address, progmem_str data, uint16_t len, uint8_t padding) {
|
|
spi_ftdi_select();
|
|
spi_write_addr(reg_address);
|
|
spi_write_bulk<xbm_write>(data, len, padding);
|
|
spi_ftdi_deselect();
|
|
}
|
|
|
|
// Write 3-Byte Address, Write 1-Byte Data
|
|
void CLCD::mem_write_8(uint32_t reg_address, uint8_t data) {
|
|
spi_ftdi_select();
|
|
spi_write_addr(reg_address);
|
|
spi_write_8(data);
|
|
spi_ftdi_deselect();
|
|
}
|
|
|
|
// Write 3-Byte Address, Write 2-Bytes Data
|
|
void CLCD::mem_write_16(uint32_t reg_address, uint16_t data) {
|
|
using namespace SPI::least_significant_byte_first;
|
|
spi_ftdi_select();
|
|
spi_write_addr(reg_address);
|
|
spi_write_16(data);
|
|
spi_ftdi_deselect();
|
|
}
|
|
|
|
// Write 3-Byte Address, Write 4-Bytes Data
|
|
void CLCD::mem_write_32(uint32_t reg_address, uint32_t data) {
|
|
using namespace SPI::least_significant_byte_first;
|
|
spi_ftdi_select();
|
|
spi_write_addr(reg_address);
|
|
spi_write_32(data);
|
|
spi_ftdi_deselect();
|
|
}
|
|
|
|
// Fill area of len size with repeated data bytes
|
|
void CLCD::mem_write_fill(uint32_t reg_address, uint8_t data, uint16_t len) {
|
|
spi_ftdi_select();
|
|
spi_write_addr(reg_address);
|
|
while (len--) spi_write_8(data);
|
|
spi_ftdi_deselect();
|
|
}
|
|
|
|
/******************* FT800/810 Co-processor Commands *********************************/
|
|
|
|
#if FTDI_API_LEVEL == 800
|
|
uint32_t CLCD::CommandFifo::command_write_ptr = 0xFFFFFFFFul;
|
|
#endif
|
|
|
|
void CLCD::CommandFifo::cmd(uint32_t cmd32) {
|
|
write((void*)&cmd32, sizeof(uint32_t));
|
|
}
|
|
|
|
void CLCD::CommandFifo::cmd(void *data, uint16_t len) {
|
|
write(data, len);
|
|
}
|
|
|
|
void CLCD::CommandFifo::bgcolor(uint32_t rgb) {
|
|
cmd(CMD_BGCOLOR);
|
|
cmd(rgb);
|
|
}
|
|
|
|
void CLCD::CommandFifo::fgcolor(uint32_t rgb) {
|
|
cmd(CMD_FGCOLOR);
|
|
cmd(rgb);
|
|
}
|
|
|
|
void CLCD::CommandFifo::gradcolor(uint32_t rgb) {
|
|
cmd(CMD_GRADCOLOR);
|
|
cmd(rgb);
|
|
}
|
|
|
|
// This sends the a text command to the command preprocessor, must be followed by str()
|
|
void CLCD::CommandFifo::button(int16_t x, int16_t y, int16_t w, int16_t h, int16_t font, uint16_t option) {
|
|
struct {
|
|
int32_t type = CMD_BUTTON;
|
|
int16_t x;
|
|
int16_t y;
|
|
int16_t w;
|
|
int16_t h;
|
|
int16_t font;
|
|
uint16_t option;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.w = w;
|
|
cmd_data.h = h;
|
|
cmd_data.font = font;
|
|
cmd_data.option = option;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
// This sends the a text command to the command preprocessor, must be followed by str()
|
|
void CLCD::CommandFifo::text(int16_t x, int16_t y, int16_t font, uint16_t options) {
|
|
struct {
|
|
int32_t type = CMD_TEXT;
|
|
int16_t x;
|
|
int16_t y;
|
|
int16_t font;
|
|
uint16_t options;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.font = font;
|
|
cmd_data.options = options;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
// This sends the a toggle command to the command preprocessor, must be followed by str()
|
|
void CLCD::CommandFifo::toggle(int16_t x, int16_t y, int16_t w, int16_t font, uint16_t options, bool state) {
|
|
struct {
|
|
int32_t type = CMD_TOGGLE;
|
|
int16_t x;
|
|
int16_t y;
|
|
int16_t w;
|
|
int16_t font;
|
|
uint16_t options;
|
|
uint16_t state;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.w = w;
|
|
cmd_data.font = font;
|
|
cmd_data.options = options;
|
|
cmd_data.state = state ? 65535 : 0;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
// This sends the a keys command to the command preprocessor, must be followed by str()
|
|
void CLCD::CommandFifo::keys(int16_t x, int16_t y, int16_t w, int16_t h, int16_t font, uint16_t options) {
|
|
struct {
|
|
int32_t type = CMD_KEYS;
|
|
int16_t x;
|
|
int16_t y;
|
|
int16_t w;
|
|
int16_t h;
|
|
int16_t font;
|
|
uint16_t options;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.w = w;
|
|
cmd_data.h = h;
|
|
cmd_data.font = font;
|
|
cmd_data.options = options;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::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)
|
|
{
|
|
struct {
|
|
int32_t type = CMD_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;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.r = r;
|
|
cmd_data.options = options;
|
|
cmd_data.h = h;
|
|
cmd_data.m = m;
|
|
cmd_data.s = s;
|
|
cmd_data.ms = ms;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::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)
|
|
{
|
|
struct {
|
|
int32_t type = CMD_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;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.r = r;
|
|
cmd_data.options = options;
|
|
cmd_data.major = major;
|
|
cmd_data.minor = minor;
|
|
cmd_data.val = val;
|
|
cmd_data.range = range;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::dial(int16_t x, int16_t y, int16_t r, uint16_t options, uint16_t val)
|
|
{
|
|
struct {
|
|
int32_t type = CMD_DIAL;
|
|
int16_t x;
|
|
int16_t y;
|
|
int16_t r;
|
|
uint16_t options;
|
|
uint16_t val;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.r = r;
|
|
cmd_data.options = options;
|
|
cmd_data.val = val;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::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) {
|
|
struct {
|
|
int32_t type = CMD_SCROLLBAR;
|
|
int16_t x;
|
|
int16_t y;
|
|
int16_t w;
|
|
uint16_t h;
|
|
uint16_t options;
|
|
uint16_t val;
|
|
uint16_t size;
|
|
uint16_t range;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.w = w;
|
|
cmd_data.h = h;
|
|
cmd_data.options = options;
|
|
cmd_data.val = val;
|
|
cmd_data.size = size;
|
|
cmd_data.range = range;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::progress(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range) {
|
|
struct {
|
|
int32_t type = CMD_PROGRESS;
|
|
int16_t x;
|
|
int16_t y;
|
|
int16_t w;
|
|
int16_t h;
|
|
uint16_t options;
|
|
uint16_t val;
|
|
uint16_t range;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.w = w;
|
|
cmd_data.h = h;
|
|
cmd_data.options = options;
|
|
cmd_data.val = val;
|
|
cmd_data.range = range;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::slider(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range) {
|
|
struct {
|
|
int32_t type = CMD_SLIDER;
|
|
int16_t x;
|
|
int16_t y;
|
|
int16_t w;
|
|
int16_t h;
|
|
uint16_t options;
|
|
uint16_t val;
|
|
uint16_t range;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.w = w;
|
|
cmd_data.h = h;
|
|
cmd_data.options = options;
|
|
cmd_data.val = val;
|
|
cmd_data.range = range;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::gradient(int16_t x0, int16_t y0, uint32_t rgb0, int16_t x1, int16_t y1, uint32_t rgb1) {
|
|
struct {
|
|
int32_t type = CMD_GRADIENT;
|
|
int16_t x0;
|
|
int16_t y0;
|
|
uint32_t rgb0;
|
|
int16_t x1;
|
|
int16_t y1;
|
|
uint32_t rgb1;
|
|
} cmd_data;
|
|
|
|
cmd_data.x0 = x0;
|
|
cmd_data.y0 = y0;
|
|
cmd_data.rgb0 = rgb0;
|
|
cmd_data.x1 = x1;
|
|
cmd_data.y1 = y1;
|
|
cmd_data.rgb1 = rgb1;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::number(int16_t x, int16_t y, int16_t font, uint16_t options, int32_t n) {
|
|
struct {
|
|
int32_t type = CMD_NUMBER;
|
|
int16_t x;
|
|
int16_t y;
|
|
int16_t font;
|
|
uint16_t options;
|
|
int16_t n;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.font = font;
|
|
cmd_data.options = options;
|
|
cmd_data.n = n;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::memzero(uint32_t ptr, uint32_t size) {
|
|
struct {
|
|
uint32_t type = CMD_MEMZERO;
|
|
uint32_t ptr;
|
|
uint32_t size;
|
|
} cmd_data;
|
|
|
|
cmd_data.ptr = ptr;
|
|
cmd_data.size = size;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::memset(uint32_t ptr, uint32_t val, uint32_t size) {
|
|
struct {
|
|
uint32_t type = CMD_MEMSET;
|
|
uint32_t ptr;
|
|
uint32_t val;
|
|
uint32_t size;
|
|
} cmd_data;
|
|
|
|
cmd_data.ptr = ptr;
|
|
cmd_data.val = val;
|
|
cmd_data.size = size;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::memcpy(uint32_t dst, uint32_t src, uint32_t size) {
|
|
struct {
|
|
uint32_t type = CMD_MEMCPY;
|
|
uint32_t dst;
|
|
uint32_t src;
|
|
uint32_t size;
|
|
} cmd_data;
|
|
|
|
cmd_data.dst = dst;
|
|
cmd_data.src = src;
|
|
cmd_data.size = size;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::memcrc(uint32_t ptr, uint32_t num, uint32_t result) {
|
|
struct {
|
|
uint32_t type = CMD_MEMCRC;
|
|
uint32_t ptr;
|
|
uint32_t num;
|
|
uint32_t result;
|
|
} cmd_data;
|
|
|
|
cmd_data.ptr = ptr;
|
|
cmd_data.num = num;
|
|
cmd_data.result = result;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::memwrite(uint32_t ptr, uint32_t value) {
|
|
struct {
|
|
uint32_t type = CMD_MEMWRITE;
|
|
uint32_t ptr;
|
|
uint32_t num;
|
|
uint32_t value;
|
|
} cmd_data;
|
|
|
|
cmd_data.ptr = ptr;
|
|
cmd_data.num = 4;
|
|
cmd_data.value = value;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::append(uint32_t ptr, uint32_t size) {
|
|
struct {
|
|
uint32_t type = CMD_APPEND;
|
|
uint32_t ptr;
|
|
uint32_t size;
|
|
} cmd_data;
|
|
|
|
cmd_data.ptr = ptr;
|
|
cmd_data.size = size;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::inflate(uint32_t ptr) {
|
|
struct {
|
|
uint32_t type = CMD_INFLATE;
|
|
uint32_t ptr;
|
|
} cmd_data;
|
|
|
|
cmd_data.ptr = ptr;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::getptr(uint32_t result) {
|
|
struct {
|
|
uint32_t type = CMD_GETPTR;
|
|
uint32_t result;
|
|
} cmd_data;
|
|
|
|
cmd_data.result = result;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::track(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t tag) {
|
|
struct {
|
|
uint32_t type = CMD_TRACK;
|
|
int16_t x;
|
|
int16_t y;
|
|
int16_t w;
|
|
int16_t h;
|
|
int16_t tag;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.w = w;
|
|
cmd_data.h = h;
|
|
cmd_data.tag = tag;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::sketch(int16_t x, int16_t y, uint16_t w, uint16_t h, uint32_t ptr, uint16_t format) {
|
|
struct {
|
|
uint32_t type = CMD_SKETCH;
|
|
int16_t x;
|
|
int16_t y;
|
|
uint16_t w;
|
|
uint16_t h;
|
|
uint32_t ptr;
|
|
uint16_t format;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.w = w;
|
|
cmd_data.h = h;
|
|
cmd_data.ptr = ptr;
|
|
cmd_data.format = format;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::snapshot(uint32_t ptr) {
|
|
struct {
|
|
uint32_t type = CMD_SNAPSHOT;
|
|
uint32_t ptr;
|
|
} cmd_data;
|
|
|
|
cmd_data.ptr = ptr;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::spinner(int16_t x, int16_t y, uint16_t style, uint16_t scale) {
|
|
struct {
|
|
uint32_t type = CMD_SPINNER;
|
|
uint16_t x;
|
|
uint16_t y;
|
|
uint16_t style;
|
|
uint16_t scale;
|
|
} cmd_data;
|
|
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.style = style;
|
|
cmd_data.scale = scale;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::loadimage(uint32_t ptr, uint32_t options) {
|
|
struct {
|
|
uint32_t type = CMD_LOADIMAGE;
|
|
uint32_t ptr;
|
|
uint32_t options;
|
|
} cmd_data;
|
|
|
|
cmd_data.ptr = ptr;
|
|
cmd_data.options = options;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::getprops(uint32_t ptr, uint32_t width, uint32_t height) {
|
|
struct {
|
|
uint32_t type = CMD_GETPROPS;
|
|
uint32_t ptr;
|
|
uint32_t width;
|
|
uint32_t height;
|
|
} cmd_data;
|
|
|
|
cmd_data.ptr = ptr;
|
|
cmd_data.width = width;
|
|
cmd_data.height = height;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::scale(int32_t sx, int32_t sy) {
|
|
struct {
|
|
uint32_t type = CMD_SCALE;
|
|
int32_t sx;
|
|
int32_t sy;
|
|
} cmd_data;
|
|
|
|
cmd_data.sx = sx;
|
|
cmd_data.sy = sy;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::rotate(int32_t a) {
|
|
struct {
|
|
uint32_t type = CMD_ROTATE;
|
|
int32_t a;
|
|
} cmd_data;
|
|
|
|
cmd_data.a = a;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
void CLCD::CommandFifo::translate(int32_t tx, int32_t ty) {
|
|
struct {
|
|
uint32_t type = CMD_TRANSLATE;
|
|
int32_t tx;
|
|
int32_t ty;
|
|
} cmd_data;
|
|
|
|
cmd_data.tx = tx;
|
|
cmd_data.ty = ty;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
|
|
#if FTDI_API_LEVEL >= 810
|
|
void CLCD::CommandFifo::setbase(uint8_t base) {
|
|
struct {
|
|
int32_t type = CMD_SETBASE;
|
|
uint32_t base;
|
|
} cmd_data;
|
|
|
|
cmd_data.base = base;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
#endif
|
|
|
|
#if FTDI_API_LEVEL >= 810
|
|
void CLCD::CommandFifo::setbitmap(uint32_t addr, uint16_t fmt, uint16_t w, uint16_t h) {
|
|
struct {
|
|
uint32_t type = CMD_SETBITMAP;
|
|
uint32_t addr;
|
|
uint16_t fmt;
|
|
uint16_t w;
|
|
uint16_t h;
|
|
uint16_t dummy;
|
|
} cmd_data;
|
|
|
|
cmd_data.addr = addr;
|
|
cmd_data.fmt = fmt;
|
|
cmd_data.w = w;
|
|
cmd_data.h = h;
|
|
cmd_data.dummy = 0;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
#endif
|
|
|
|
#if FTDI_API_LEVEL >= 810
|
|
void CLCD::CommandFifo::snapshot2(uint32_t format, uint32_t ptr, int16_t x, int16_t y, uint16_t w, uint16_t h) {
|
|
struct {
|
|
uint32_t type = CMD_SNAPSHOT2;
|
|
uint32_t format;
|
|
uint32_t ptr;
|
|
int16_t x;
|
|
int16_t y;
|
|
uint16_t w;
|
|
uint16_t h;
|
|
} cmd_data;
|
|
|
|
cmd_data.format = format;
|
|
cmd_data.ptr = ptr;
|
|
cmd_data.x = x;
|
|
cmd_data.y = y;
|
|
cmd_data.w = w;
|
|
cmd_data.h = h;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
#endif
|
|
|
|
#if FTDI_API_LEVEL >= 810
|
|
void CLCD::CommandFifo::mediafifo(uint32_t ptr, uint32_t size) {
|
|
struct {
|
|
uint32_t type = CMD_MEDIAFIFO;
|
|
uint32_t ptr;
|
|
uint32_t size;
|
|
} cmd_data;
|
|
|
|
cmd_data.ptr = ptr;
|
|
cmd_data.size = size;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
#endif
|
|
|
|
#if FTDI_API_LEVEL >= 810
|
|
void CLCD::CommandFifo::videostart() {
|
|
cmd( CMD_VIDEOSTART );
|
|
}
|
|
#endif
|
|
|
|
#if FTDI_API_LEVEL >= 810
|
|
void CLCD::CommandFifo::videoframe(uint32_t dst, uint32_t ptr) {
|
|
struct {
|
|
uint32_t type = CMD_VIDEOFRAME;
|
|
uint32_t dst;
|
|
uint32_t ptr;
|
|
} cmd_data;
|
|
|
|
cmd_data.dst = dst;
|
|
cmd_data.ptr = ptr;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
#endif
|
|
|
|
#if FTDI_API_LEVEL >= 810
|
|
void CLCD::CommandFifo::playvideo(uint32_t options) {
|
|
struct {
|
|
uint32_t type = CMD_PLAYVIDEO;
|
|
uint32_t options;
|
|
} cmd_data;
|
|
|
|
cmd_data.options = options;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
#endif
|
|
|
|
#if FTDI_API_LEVEL >= 810
|
|
void CLCD::CommandFifo::setrotate(uint8_t rotation) {
|
|
struct {
|
|
uint32_t type = CMD_SETROTATE;
|
|
uint32_t rotation;
|
|
} cmd_data;
|
|
|
|
cmd_data.rotation = rotation;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
#endif
|
|
|
|
#if FTDI_API_LEVEL >= 810
|
|
void CLCD::CommandFifo::romfont(uint8_t font, uint8_t romslot) {
|
|
struct {
|
|
uint32_t type = CMD_ROMFONT;
|
|
uint32_t font;
|
|
uint32_t romslot;
|
|
} cmd_data;
|
|
|
|
cmd_data.font = font;
|
|
cmd_data.romslot = romslot;
|
|
|
|
cmd( &cmd_data, sizeof(cmd_data) );
|
|
}
|
|
#endif
|
|
|
|
/**************************** FT800/810 Co-Processor Command FIFO ****************************/
|
|
|
|
bool CLCD::CommandFifo::is_processing() {
|
|
return (mem_read_32(REG::CMD_READ) & 0x0FFF) != (mem_read_32(REG::CMD_WRITE) & 0x0FFF);
|
|
}
|
|
|
|
bool CLCD::CommandFifo::has_fault() {
|
|
uint16_t Cmd_Read_Reg = mem_read_32(REG::CMD_READ) & 0x0FFF;
|
|
return Cmd_Read_Reg == 0x0FFF;
|
|
}
|
|
|
|
#if FTDI_API_LEVEL == 800
|
|
|
|
void CLCD::CommandFifo::start() {
|
|
if (command_write_ptr == 0xFFFFFFFFul) {
|
|
command_write_ptr = mem_read_32(REG::CMD_WRITE) & 0x0FFF;
|
|
}
|
|
}
|
|
|
|
void CLCD::CommandFifo::execute() {
|
|
if (command_write_ptr != 0xFFFFFFFFul) {
|
|
mem_write_32(REG::CMD_WRITE, command_write_ptr);
|
|
}
|
|
}
|
|
|
|
void CLCD::CommandFifo::reset() {
|
|
safe_delay(100);
|
|
mem_write_32(REG::CPURESET, 0x00000001);
|
|
mem_write_32(REG::CMD_WRITE, 0x00000000);
|
|
mem_write_32(REG::CMD_READ, 0x00000000);
|
|
mem_write_32(REG::CPURESET, 0x00000000);
|
|
safe_delay(300);
|
|
command_write_ptr = 0xFFFFFFFFul;
|
|
};
|
|
|
|
template <class T> bool CLCD::CommandFifo::_write_unaligned(T data, uint16_t len) {
|
|
const char *ptr = (const char*)data;
|
|
uint32_t bytes_tail, bytes_head;
|
|
uint32_t command_read_ptr;
|
|
|
|
#if ENABLED(TOUCH_UI_DEBUG)
|
|
if (command_write_ptr == 0xFFFFFFFFul)
|
|
SERIAL_ECHO_MSG("Attempt to write to FIFO before CommandFifo::Cmd_Start().");
|
|
#endif
|
|
|
|
/* Wait until there is enough space in the circular buffer for the transfer */
|
|
do {
|
|
command_read_ptr = mem_read_32(REG::CMD_READ) & 0x0FFF;
|
|
if (command_read_ptr <= command_write_ptr) {
|
|
bytes_tail = 4096U - command_write_ptr;
|
|
bytes_head = command_read_ptr;
|
|
}
|
|
else {
|
|
bytes_tail = command_read_ptr - command_write_ptr;
|
|
bytes_head = 0;
|
|
}
|
|
// Check for faults which can lock up the command processor
|
|
if (has_fault()) {
|
|
#if ENABLED(TOUCH_UI_DEBUG)
|
|
SERIAL_ECHOLNPGM("Fault waiting for space in the command processor");
|
|
#endif
|
|
return false;
|
|
}
|
|
} while ((bytes_tail + bytes_head) < len);
|
|
|
|
/* Write as many bytes as possible following REG::CMD_WRITE */
|
|
uint16_t bytes_to_write = min(len, bytes_tail);
|
|
mem_write_bulk (MAP::RAM_CMD + command_write_ptr, T(ptr), bytes_to_write);
|
|
command_write_ptr += bytes_to_write;
|
|
ptr += bytes_to_write;
|
|
len -= bytes_to_write;
|
|
|
|
if (len > 0) {
|
|
/* Write remaining bytes at start of circular buffer */
|
|
mem_write_bulk (MAP::RAM_CMD, T(ptr), len);
|
|
command_write_ptr = len;
|
|
}
|
|
|
|
if (command_write_ptr == 4096U) {
|
|
command_write_ptr = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Writes len bytes into the FIFO, if len is not
|
|
// divisible by four, zero bytes will be written
|
|
// to align to the boundary.
|
|
|
|
template <class T> bool CLCD::CommandFifo::write(T data, uint16_t len) {
|
|
const uint8_t padding = MULTIPLE_OF_4(len) - len;
|
|
const uint8_t pad_bytes[] = { 0, 0, 0, 0 };
|
|
return _write_unaligned(data, len) &&
|
|
_write_unaligned(pad_bytes, padding);
|
|
}
|
|
|
|
#else // FTDI_API_LEVEL != 800 ...
|
|
|
|
void CLCD::CommandFifo::start() {
|
|
}
|
|
|
|
void CLCD::CommandFifo::execute() {
|
|
}
|
|
|
|
void CLCD::CommandFifo::reset() {
|
|
#if ENABLED(TOUCH_UI_DEBUG)
|
|
SERIAL_ECHOLNPGM("Resetting command processor");
|
|
#endif
|
|
safe_delay(100);
|
|
mem_write_32(REG::CPURESET, 0x00000001);
|
|
mem_write_32(REG::CMD_WRITE, 0x00000000);
|
|
mem_write_32(REG::CMD_READ, 0x00000000);
|
|
mem_write_32(REG::CPURESET, 0x00000000);
|
|
safe_delay(300);
|
|
};
|
|
|
|
// Writes len bytes into the FIFO, if len is not
|
|
// divisible by four, zero bytes will be written
|
|
// to align to the boundary.
|
|
|
|
template <class T> bool CLCD::CommandFifo::write(T data, uint16_t len) {
|
|
const uint8_t padding = MULTIPLE_OF_4(len) - len;
|
|
|
|
if (has_fault()) {
|
|
#if ENABLED(TOUCH_UI_DEBUG)
|
|
SERIAL_ECHOLNPGM("Faulted... ignoring write.");
|
|
#endif
|
|
return false;
|
|
}
|
|
// The FT810 provides a special register that can be used
|
|
// for writing data without us having to do our own FIFO
|
|
// management.
|
|
uint16_t Command_Space = mem_read_32(REG::CMDB_SPACE) & 0x0FFF;
|
|
if (Command_Space < (len + padding)) {
|
|
#if ENABLED(TOUCH_UI_DEBUG)
|
|
SERIAL_ECHO_START();
|
|
SERIAL_ECHOPAIR("Waiting for ", len + padding);
|
|
SERIAL_ECHOLNPAIR(" bytes in command queue, now free: ", Command_Space);
|
|
#endif
|
|
do {
|
|
Command_Space = mem_read_32(REG::CMDB_SPACE) & 0x0FFF;
|
|
if (has_fault()) {
|
|
#if ENABLED(TOUCH_UI_DEBUG)
|
|
SERIAL_ECHOLNPGM("... fault");
|
|
#endif
|
|
return false;
|
|
}
|
|
} while (Command_Space < len + padding);
|
|
#if ENABLED(TOUCH_UI_DEBUG)
|
|
SERIAL_ECHOLNPGM("... done");
|
|
#endif
|
|
}
|
|
mem_write_bulk(REG::CMDB_WRITE, data, len, padding);
|
|
return true;
|
|
}
|
|
|
|
#endif // ... FTDI_API_LEVEL != 800
|
|
|
|
template bool CLCD::CommandFifo::write(const void*, uint16_t);
|
|
template bool CLCD::CommandFifo::write(progmem_str, uint16_t);
|
|
|
|
// CO_PROCESSOR COMMANDS
|
|
|
|
void CLCD::CommandFifo::str(const char * data, size_t maxlen) {
|
|
// Write the string without the terminating '\0'
|
|
const size_t len = strnlen(data, maxlen);
|
|
write(data, len);
|
|
|
|
// If padding was added by the previous write, then
|
|
// the string is terminated. Otherwise write four
|
|
// more zeros.
|
|
const uint8_t padding = MULTIPLE_OF_4(len) - len;
|
|
if (padding == 0) {
|
|
const uint8_t pad_bytes[] = {0, 0, 0, 0};
|
|
write(pad_bytes, 4);
|
|
}
|
|
}
|
|
|
|
void CLCD::CommandFifo::str(const char * data) {
|
|
write(data, strlen(data)+1);
|
|
}
|
|
|
|
void CLCD::CommandFifo::str(progmem_str data) {
|
|
write(data, strlen_P((const char*)data)+1);
|
|
}
|
|
|
|
/******************* LCD INITIALIZATION ************************/
|
|
|
|
void CLCD::init() {
|
|
spi_init(); // Set Up I/O Lines for SPI and FT800/810 Control
|
|
ftdi_reset(); // Power down/up the FT8xx with the appropriate delays
|
|
|
|
host_cmd(Use_Crystal ? CLKEXT : CLKINT, 0);
|
|
host_cmd(FTDI::ACTIVE, 0); // Activate the System Clock
|
|
|
|
delay(40); // FTDI/BRT recommendation: no SPI traffic during startup. EVE needs at the very least 45ms to start, so leave her alone for a little while.
|
|
|
|
/* read the device-id until it returns 0x7C or times out, should take less than 150ms */
|
|
uint8_t counter;
|
|
for (counter = 0; counter < 250; counter++) {
|
|
uint8_t device_id = mem_read_8(REG::ID); // Read Device ID, Should Be 0x7C;
|
|
if (device_id == 0x7C) {
|
|
if (ENABLED(TOUCH_UI_DEBUG)) SERIAL_ECHO_MSG("FTDI chip initialized ");
|
|
break;
|
|
}
|
|
else
|
|
delay(1);
|
|
|
|
if (TERN0(TOUCH_UI_DEBUG, counter > 248))
|
|
SERIAL_ECHO_MSG("Timeout waiting for device ID, should be 124, got ", device_id);
|
|
}
|
|
|
|
/* Ensure all units are in working condition, usually the touch-controller needs a little more time */
|
|
for (counter = 0; counter < 100; counter++) {
|
|
uint8_t reset_status = mem_read_8(REG::CPURESET) & 0x03;
|
|
if (reset_status == 0x00) {
|
|
if (ENABLED(TOUCH_UI_DEBUG)) SERIAL_ECHO_MSG("FTDI chip all units running ");
|
|
break;
|
|
}
|
|
else
|
|
delay(1);
|
|
|
|
if (TERN0(TOUCH_UI_DEBUG, counter > 98))
|
|
SERIAL_ECHO_MSG("Timeout waiting for reset status. Should be 0x00, got ", reset_status);
|
|
}
|
|
|
|
#if ENABLED(USE_GT911) /* switch BT815 to use Goodix GT911 touch controller */
|
|
mem_write_32(REG::TOUCH_CONFIG, 0x000005D1);
|
|
#endif
|
|
|
|
#if ENABLED(PATCH_GT911) /* patch FT813 use Goodix GT911 touch controller */
|
|
mem_write_pgm(REG::CMDB_WRITE, GT911_data, sizeof(GT911_data)); /* write binary blob to command-fifo */
|
|
delay(10);
|
|
mem_write_8(REG::TOUCH_OVERSAMPLE, 0x0F); /* setup oversample to 0x0f as "hidden" in binary-blob for AN_336 */
|
|
mem_write_16(REG::TOUCH_CONFIG, 0x05d0); /* write magic cookie as requested by AN_336 */
|
|
|
|
/* specific to the EVE2 modules from Matrix-Orbital we have to use GPIO3 to reset GT911 */
|
|
mem_write_16(REG::GPIOX_DIR,0x8008); /* Reset-Value is 0x8000, adding 0x08 sets GPIO3 to output, default-value for REG_GPIOX is 0x8000 -> Low output on GPIO3 */
|
|
delay(1); /* wait more than 100µs */
|
|
mem_write_8(REG::CPURESET, 0x00); /* clear all resets */
|
|
delay(56); /* wait more than 55ms */
|
|
mem_write_16(REG::GPIOX_DIR,0x8000); /* setting GPIO3 back to input */
|
|
#endif
|
|
|
|
mem_write_8(REG::PWM_DUTY, 0); // turn off Backlight, Frequency already is set to 250Hz default
|
|
|
|
/* Configure the FT8xx Registers */
|
|
mem_write_16(REG::HCYCLE, FTDI::Hcycle);
|
|
mem_write_16(REG::HOFFSET, FTDI::Hoffset);
|
|
mem_write_16(REG::HSYNC0, FTDI::Hsync0);
|
|
mem_write_16(REG::HSYNC1, FTDI::Hsync1);
|
|
mem_write_16(REG::VCYCLE, FTDI::Vcycle);
|
|
mem_write_16(REG::VOFFSET, FTDI::Voffset);
|
|
mem_write_16(REG::VSYNC0, FTDI::Vsync0);
|
|
mem_write_16(REG::VSYNC1, FTDI::Vsync1);
|
|
mem_write_16(REG::HSIZE, FTDI::Hsize);
|
|
mem_write_16(REG::VSIZE, FTDI::Vsize);
|
|
mem_write_8(REG::SWIZZLE, FTDI::Swizzle);
|
|
mem_write_8(REG::PCLK_POL, FTDI::Pclkpol);
|
|
mem_write_8(REG::CSPREAD, FTDI::CSpread);
|
|
|
|
/* write a basic display-list to get things started */
|
|
mem_write_32(MAP::RAM_DL, DL::CLEAR_COLOR_RGB);
|
|
mem_write_32(MAP::RAM_DL + 4, (DL::CLEAR | 0x07)); /* clear color, stencil and tag buffer */
|
|
mem_write_32(MAP::RAM_DL + 8, DL::DL_DISPLAY); /* end of display list */
|
|
|
|
mem_write_8(REG::DLSWAP, 0x02); // activate display list, Bad Magic Cookie 2 = switch to new list after current frame is scanned out
|
|
|
|
//mem_write_8(REG::TOUCH_MODE, 0x03); // Configure the Touch Screen, Bad Magic Cookie, 3 = CONTINUOUS = Reset Default
|
|
//mem_write_8(REG::TOUCH_ADC_MODE, 0x01); // Bad Magic Cookie, 1 = single touch = Reset Default
|
|
//mem_write_8(REG::TOUCH_OVERSAMPLE, 0x0F); // Reset Default = 7 - why 15?
|
|
mem_write_16(REG::TOUCH_RZTHRESH, touch_threshold); /* setup touch sensitivity */
|
|
mem_write_8(REG::VOL_SOUND, 0x00); // Turn Synthesizer Volume Off
|
|
|
|
/* turn on the display by setting DISP high */
|
|
/* turn on the Audio Amplifier by setting GPIO_1 high for the select few modules supporting this */
|
|
/* no need to use GPIOX here since DISP/GPIO_0 and GPIO_1 are on REG::GPIO for FT81x as well */
|
|
if (GPIO_1_Audio_Shutdown) {
|
|
mem_write_8(REG::GPIO_DIR, GPIO_DISP | GPIO_GP1);
|
|
mem_write_8(REG::GPIO, GPIO_DISP | GPIO_GP1);
|
|
}
|
|
else if (GPIO_0_Audio_Enable) {
|
|
mem_write_8(REG::GPIO_DIR, GPIO_DISP | GPIO_GP0);
|
|
mem_write_8(REG::GPIO, GPIO_DISP | GPIO_GP0);
|
|
}
|
|
else
|
|
mem_write_8(REG::GPIO, GPIO_DISP); /* REG::GPIO_DIR is set to output for GPIO_DISP by default */
|
|
|
|
mem_write_8(REG::PCLK, Pclk); // Turns on Clock by setting PCLK Register to the value necessary for the module
|
|
|
|
mem_write_16(REG::PWM_HZ, 0x00FA);
|
|
|
|
// Turning off dithering seems to help prevent horizontal line artifacts on certain colors
|
|
mem_write_8(REG::DITHER, 0);
|
|
|
|
default_touch_transform();
|
|
default_display_orientation();
|
|
}
|
|
|
|
void CLCD::default_touch_transform() {
|
|
// Set Initial Values for Touch Transform Registers
|
|
mem_write_32(REG::ROTATE, 0);
|
|
mem_write_32(REG::TOUCH_TRANSFORM_A, FTDI::default_transform_a);
|
|
mem_write_32(REG::TOUCH_TRANSFORM_B, FTDI::default_transform_b);
|
|
mem_write_32(REG::TOUCH_TRANSFORM_C, FTDI::default_transform_c);
|
|
mem_write_32(REG::TOUCH_TRANSFORM_D, FTDI::default_transform_d);
|
|
mem_write_32(REG::TOUCH_TRANSFORM_E, FTDI::default_transform_e);
|
|
mem_write_32(REG::TOUCH_TRANSFORM_F, FTDI::default_transform_f);
|
|
}
|
|
|
|
void CLCD::default_display_orientation() {
|
|
#if FTDI_API_LEVEL >= 810
|
|
// Set the initial display orientation. On the FT810, we use the command
|
|
// processor to do this since it will also update the transform matrices.
|
|
CommandFifo cmd;
|
|
cmd.setrotate(
|
|
ENABLED(TOUCH_UI_MIRRORED) * 4
|
|
+ ENABLED(TOUCH_UI_PORTRAIT) * 2
|
|
+ ENABLED(TOUCH_UI_INVERTED) * 1
|
|
);
|
|
cmd.execute();
|
|
#elif ANY(TOUCH_UI_PORTRAIT, TOUCH_UI_MIRRORED)
|
|
#error "PORTRAIT or MIRRORED orientation not supported on the FT800."
|
|
#elif ENABLED(TOUCH_UI_INVERTED)
|
|
mem_write_32(REG::ROTATE, 1);
|
|
#endif
|
|
}
|
|
|
|
#endif // FTDI_BASIC
|
|
|