123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188 |
- /****************
- * 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/>. *
- ****************************************************************************/
-
- #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 != 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_32(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();
- }
-
- /******************* 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;
-
- uint8_t pad_bytes[] = {0, 0, 0, 0};
- return _write_unaligned(data, len) &&
- _write_unaligned(pad_bytes, padding);
- }
- #else
- 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
-
- 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) {
- 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 apropriate delays
-
- if (Use_Crystal == 1) {
- host_cmd(CLKEXT, 0);
- }
- else {
- host_cmd(CLKINT, 0);
- }
-
- host_cmd(ACTIVE, 0); // Activate the System Clock
-
- /* 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 ");
- #endif
- break;
- }
- else {
- delay(1);
- }
- if (counter == 249) {
- #if ENABLED(TOUCH_UI_DEBUG)
- SERIAL_ECHO_START();
- SERIAL_ECHOLNPAIR("Timeout waiting for device ID, should be 124, got ", device_id);
- #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);
-
- // Initialize the command FIFO
- CommandFifo::reset();
-
- 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.
- if (FTDI::ftdi_chip >= 810) {
- CommandFifo cmd;
- cmd.setrotate(0
- #if ENABLED(TOUCH_UI_MIRRORED)
- + 4
- #endif
- #if ENABLED(TOUCH_UI_PORTRAIT)
- + 2
- #endif
- #if ENABLED(TOUCH_UI_INVERTED)
- + 1
- #endif
- );
- cmd.execute();
- }
- else {
- #if ENABLED(TOUCH_UI_INVERTED)
- mem_write_32(REG::ROTATE, 1);
- #endif
- }
- #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
|