12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202 |
- /****************
- * 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;
-
- 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
-
- 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
|