My Marlin configs for Fabrikator Mini and CTC i3 Pro B
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.

commands.cpp 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188
  1. /****************
  2. * commands.cpp *
  3. ****************/
  4. /****************************************************************************
  5. * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
  6. * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
  7. * *
  8. * This program is free software: you can redistribute it and/or modify *
  9. * it under the terms of the GNU General Public License as published by *
  10. * the Free Software Foundation, either version 3 of the License, or *
  11. * (at your option) any later version. *
  12. * *
  13. * This program is distributed in the hope that it will be useful, *
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  16. * GNU General Public License for more details. *
  17. * *
  18. * To view a copy of the GNU General Public License, go to the following *
  19. * location: <http://www.gnu.org/licenses/>. *
  20. ****************************************************************************/
  21. #include "ftdi_basic.h"
  22. #ifdef FTDI_BASIC
  23. #define MULTIPLE_OF_4(val) ((((val)+3)>>2)<<2)
  24. using namespace FTDI;
  25. using namespace FTDI::SPI;
  26. void CLCD::enable() {
  27. mem_write_8(REG::PCLK, Pclk);
  28. }
  29. void CLCD::disable() {
  30. mem_write_8(REG::PCLK, 0x00);
  31. }
  32. void CLCD::set_brightness(uint8_t brightness) {
  33. mem_write_8(REG::PWM_DUTY, min(128,brightness));
  34. }
  35. uint8_t CLCD::get_brightness() {
  36. return mem_read_8(REG::PWM_DUTY);
  37. }
  38. void CLCD::turn_on_backlight() {
  39. mem_write_8(REG::PWM_DUTY, 128);
  40. }
  41. void CLCD::FontMetrics::load(const uint8_t font) {
  42. static_assert(sizeof(FontMetrics) == 148, "Sizeof font metrics is incorrect");
  43. uint32_t rom_fontroot = mem_read_32(MAP::ROM_FONT_ADDR);
  44. mem_read_bulk(rom_fontroot + 148 * (font - 16), (uint8_t*) this, 148);
  45. }
  46. uint16_t CLCD::FontMetrics::get_text_width(const char *str, size_t n) const {
  47. uint16_t width = 0;
  48. const uint8_t *p = (const uint8_t *) str;
  49. for(;;) {
  50. const uint8_t val = *p++; n--;
  51. if (!val || n == 0) break;
  52. width += val < 128 ? char_widths[val] : 0;
  53. }
  54. return width;
  55. }
  56. uint16_t CLCD::FontMetrics::get_text_width(progmem_str str, size_t n) const {
  57. uint16_t width = 0;
  58. const uint8_t *p = (const uint8_t *) str;
  59. for(;;) {
  60. const uint8_t val = pgm_read_byte(p++); n--;
  61. if (!val || n == 0) break;
  62. width += val < 128 ? char_widths[val] : 0;
  63. }
  64. return width;
  65. }
  66. /************************** HOST COMMAND FUNCTION *********************************/
  67. void CLCD::host_cmd (unsigned char host_command, unsigned char byte2) { // Sends 24-Bit Host Command to LCD
  68. if (host_command != ACTIVE) {
  69. host_command |= 0x40;
  70. }
  71. spi_ftdi_select();
  72. spi_send(host_command);
  73. spi_send(byte2);
  74. spi_send(0x00);
  75. spi_ftdi_deselect();
  76. }
  77. /************************** MEMORY READ FUNCTIONS *********************************/
  78. void CLCD::spi_read_addr (uint32_t reg_address) {
  79. spi_send((reg_address >> 16) & 0x3F); // Address [21:16]
  80. spi_send((reg_address >> 8 ) & 0xFF); // Address [15:8]
  81. spi_send((reg_address >> 0) & 0xFF); // Address [7:0]
  82. spi_send(0x00); // Dummy Byte
  83. }
  84. // Write 4-Byte Address, Read Multiple Bytes
  85. void CLCD::mem_read_bulk (uint32_t reg_address, uint8_t *data, uint16_t len) {
  86. spi_ftdi_select();
  87. spi_read_addr(reg_address);
  88. spi_read_bulk (data, len);
  89. spi_ftdi_deselect();
  90. }
  91. // Write 4-Byte Address, Read 1-Byte Data
  92. uint8_t CLCD::mem_read_8 (uint32_t reg_address) {
  93. spi_ftdi_select();
  94. spi_read_addr(reg_address);
  95. uint8_t r_data = spi_read_8();
  96. spi_ftdi_deselect();
  97. return r_data;
  98. }
  99. // Write 4-Byte Address, Read 2-Bytes Data
  100. uint16_t CLCD::mem_read_16 (uint32_t reg_address) {
  101. using namespace SPI::least_significant_byte_first;
  102. spi_ftdi_select();
  103. spi_read_addr(reg_address);
  104. uint16_t r_data = spi_read_16();
  105. spi_ftdi_deselect();
  106. return r_data;
  107. }
  108. // Write 4-Byte Address, Read 4-Bytes Data
  109. uint32_t CLCD::mem_read_32 (uint32_t reg_address) {
  110. using namespace SPI::least_significant_byte_first;
  111. spi_ftdi_select();
  112. spi_read_addr(reg_address);
  113. uint32_t r_data = spi_read_32();
  114. spi_ftdi_deselect();
  115. return r_data;
  116. }
  117. /************************** MEMORY WRITE FUNCTIONS *********************************/
  118. // Generic operations for transforming a byte, for use with _mem_write_bulk:
  119. static inline uint8_t reverse_byte(uint8_t a) {
  120. return ((a & 0x1) << 7) | ((a & 0x2) << 5) |
  121. ((a & 0x4) << 3) | ((a & 0x8) << 1) |
  122. ((a & 0x10) >> 1) | ((a & 0x20) >> 3) |
  123. ((a & 0x40) >> 5) | ((a & 0x80) >> 7);
  124. }
  125. static inline uint8_t xbm_write(const uint8_t *p) {return reverse_byte(pgm_read_byte(p));}
  126. void CLCD::spi_write_addr (uint32_t reg_address) {
  127. spi_send((reg_address >> 16) | 0x80); // Address [21:16]
  128. spi_send((reg_address >> 8 ) & 0xFF); // Address [15:8]
  129. spi_send((reg_address >> 0) & 0xFF); // Address [7:0]
  130. }
  131. // Write 3-Byte Address, Multiple Bytes, plus padding bytes, from RAM
  132. void CLCD::mem_write_bulk (uint32_t reg_address, const void *data, uint16_t len, uint8_t padding) {
  133. spi_ftdi_select();
  134. spi_write_addr(reg_address);
  135. spi_write_bulk<ram_write>(data, len, padding);
  136. spi_ftdi_deselect();
  137. }
  138. // Write 3-Byte Address, Multiple Bytes, plus padding bytes, from PROGMEM
  139. void CLCD::mem_write_bulk (uint32_t reg_address, progmem_str str, uint16_t len, uint8_t padding) {
  140. spi_ftdi_select();
  141. spi_write_addr(reg_address);
  142. spi_write_bulk<pgm_write>(str, len, padding);
  143. spi_ftdi_deselect();
  144. }
  145. // Write 3-Byte Address, Multiple Bytes, plus padding bytes, from PROGMEM
  146. void CLCD::mem_write_pgm (uint32_t reg_address, const void *data, uint16_t len, uint8_t padding) {
  147. spi_ftdi_select();
  148. spi_write_addr(reg_address);
  149. spi_write_bulk<pgm_write>(data, len, padding);
  150. spi_ftdi_deselect();
  151. }
  152. // Write 3-Byte Address, Multiple Bytes, plus padding bytes, from PROGMEM, reversing bytes (suitable for loading XBM images)
  153. void CLCD::mem_write_xbm (uint32_t reg_address, progmem_str data, uint16_t len, uint8_t padding) {
  154. spi_ftdi_select();
  155. spi_write_addr(reg_address);
  156. spi_write_bulk<xbm_write>(data, len, padding);
  157. spi_ftdi_deselect();
  158. }
  159. // Write 3-Byte Address, Write 1-Byte Data
  160. void CLCD::mem_write_8 (uint32_t reg_address, uint8_t data) {
  161. spi_ftdi_select();
  162. spi_write_addr(reg_address);
  163. spi_write_8(data);
  164. spi_ftdi_deselect();
  165. }
  166. // Write 3-Byte Address, Write 2-Bytes Data
  167. void CLCD::mem_write_16 (uint32_t reg_address, uint16_t data) {
  168. using namespace SPI::least_significant_byte_first;
  169. spi_ftdi_select();
  170. spi_write_addr(reg_address);
  171. spi_write_32(data);
  172. spi_ftdi_deselect();
  173. }
  174. // Write 3-Byte Address, Write 4-Bytes Data
  175. void CLCD::mem_write_32 (uint32_t reg_address, uint32_t data) {
  176. using namespace SPI::least_significant_byte_first;
  177. spi_ftdi_select();
  178. spi_write_addr(reg_address);
  179. spi_write_32(data);
  180. spi_ftdi_deselect();
  181. }
  182. /******************* FT800/810 Co-processor Commands *********************************/
  183. #if FTDI_API_LEVEL == 800
  184. uint32_t CLCD::CommandFifo::command_write_ptr = 0xFFFFFFFFul;
  185. #endif
  186. void CLCD::CommandFifo::cmd(uint32_t cmd32) {
  187. write((void*)&cmd32, sizeof(uint32_t));
  188. }
  189. void CLCD::CommandFifo::cmd(void* data, uint16_t len) {
  190. write(data, len);
  191. }
  192. void CLCD::CommandFifo::bgcolor(uint32_t rgb) {
  193. cmd(CMD_BGCOLOR);
  194. cmd(rgb);
  195. }
  196. void CLCD::CommandFifo::fgcolor(uint32_t rgb) {
  197. cmd(CMD_FGCOLOR);
  198. cmd(rgb);
  199. }
  200. void CLCD::CommandFifo::gradcolor(uint32_t rgb) {
  201. cmd(CMD_GRADCOLOR);
  202. cmd(rgb);
  203. }
  204. // This sends the a text command to the command preprocessor, must be followed by str()
  205. void CLCD::CommandFifo::button(int16_t x, int16_t y, int16_t w, int16_t h, int16_t font, uint16_t option) {
  206. struct {
  207. int32_t type = CMD_BUTTON;
  208. int16_t x;
  209. int16_t y;
  210. int16_t w;
  211. int16_t h;
  212. int16_t font;
  213. uint16_t option;
  214. } cmd_data;
  215. cmd_data.x = x;
  216. cmd_data.y = y;
  217. cmd_data.w = w;
  218. cmd_data.h = h;
  219. cmd_data.font = font;
  220. cmd_data.option = option;
  221. cmd( &cmd_data, sizeof(cmd_data) );
  222. }
  223. // This sends the a text command to the command preprocessor, must be followed by str()
  224. void CLCD::CommandFifo::text(int16_t x, int16_t y, int16_t font, uint16_t options) {
  225. struct {
  226. int32_t type = CMD_TEXT;
  227. int16_t x;
  228. int16_t y;
  229. int16_t font;
  230. uint16_t options;
  231. } cmd_data;
  232. cmd_data.x = x;
  233. cmd_data.y = y;
  234. cmd_data.font = font;
  235. cmd_data.options = options;
  236. cmd( &cmd_data, sizeof(cmd_data) );
  237. }
  238. // This sends the a toggle command to the command preprocessor, must be followed by str()
  239. void CLCD::CommandFifo::toggle (int16_t x, int16_t y, int16_t w, int16_t font, uint16_t options, bool state) {
  240. struct {
  241. int32_t type = CMD_TOGGLE;
  242. int16_t x;
  243. int16_t y;
  244. int16_t w;
  245. int16_t font;
  246. uint16_t options;
  247. uint16_t state;
  248. } cmd_data;
  249. cmd_data.x = x;
  250. cmd_data.y = y;
  251. cmd_data.w = w;
  252. cmd_data.font = font;
  253. cmd_data.options = options;
  254. cmd_data.state = state ? 65535 : 0;
  255. cmd( &cmd_data, sizeof(cmd_data) );
  256. }
  257. // This sends the a keys command to the command preprocessor, must be followed by str()
  258. void CLCD::CommandFifo::keys (int16_t x, int16_t y, int16_t w, int16_t h, int16_t font, uint16_t options) {
  259. struct {
  260. int32_t type = CMD_KEYS;
  261. int16_t x;
  262. int16_t y;
  263. int16_t w;
  264. int16_t h;
  265. int16_t font;
  266. uint16_t options;
  267. } cmd_data;
  268. cmd_data.x = x;
  269. cmd_data.y = y;
  270. cmd_data.w = w;
  271. cmd_data.h = h;
  272. cmd_data.font = font;
  273. cmd_data.options = options;
  274. cmd( &cmd_data, sizeof(cmd_data) );
  275. }
  276. 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)
  277. {
  278. struct {
  279. int32_t type = CMD_CLOCK;
  280. int16_t x;
  281. int16_t y;
  282. int16_t r;
  283. uint16_t options;
  284. int16_t h;
  285. int16_t m;
  286. int16_t s;
  287. int16_t ms;
  288. } cmd_data;
  289. cmd_data.x = x;
  290. cmd_data.y = y;
  291. cmd_data.r = r;
  292. cmd_data.options = options;
  293. cmd_data.h = h;
  294. cmd_data.m = m;
  295. cmd_data.s = s;
  296. cmd_data.ms = ms;
  297. cmd( &cmd_data, sizeof(cmd_data) );
  298. }
  299. 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)
  300. {
  301. struct {
  302. int32_t type = CMD_GAUGE;
  303. int16_t x;
  304. int16_t y;
  305. int16_t r;
  306. uint16_t options;
  307. uint16_t major;
  308. uint16_t minor;
  309. uint16_t val;
  310. uint16_t range;
  311. } cmd_data;
  312. cmd_data.x = x;
  313. cmd_data.y = y;
  314. cmd_data.r = r;
  315. cmd_data.options = options;
  316. cmd_data.major = major;
  317. cmd_data.minor = minor;
  318. cmd_data.val = val;
  319. cmd_data.range = range;
  320. cmd( &cmd_data, sizeof(cmd_data) );
  321. }
  322. void CLCD::CommandFifo::dial (int16_t x, int16_t y, int16_t r, uint16_t options, uint16_t val)
  323. {
  324. struct {
  325. int32_t type = CMD_DIAL;
  326. int16_t x;
  327. int16_t y;
  328. int16_t r;
  329. uint16_t options;
  330. uint16_t val;
  331. } cmd_data;
  332. cmd_data.x = x;
  333. cmd_data.y = y;
  334. cmd_data.r = r;
  335. cmd_data.options = options;
  336. cmd_data.val = val;
  337. cmd( &cmd_data, sizeof(cmd_data) );
  338. }
  339. 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) {
  340. struct {
  341. int32_t type = CMD_SCROLLBAR;
  342. int16_t x;
  343. int16_t y;
  344. int16_t w;
  345. uint16_t h;
  346. uint16_t options;
  347. uint16_t val;
  348. uint16_t size;
  349. uint16_t range;
  350. } cmd_data;
  351. cmd_data.x = x;
  352. cmd_data.y = y;
  353. cmd_data.w = w;
  354. cmd_data.h = h;
  355. cmd_data.options = options;
  356. cmd_data.val = val;
  357. cmd_data.size = size;
  358. cmd_data.range = range;
  359. cmd( &cmd_data, sizeof(cmd_data) );
  360. }
  361. 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) {
  362. struct {
  363. int32_t type = CMD_PROGRESS;
  364. int16_t x;
  365. int16_t y;
  366. int16_t w;
  367. int16_t h;
  368. uint16_t options;
  369. uint16_t val;
  370. uint16_t range;
  371. } cmd_data;
  372. cmd_data.x = x;
  373. cmd_data.y = y;
  374. cmd_data.w = w;
  375. cmd_data.h = h;
  376. cmd_data.options = options;
  377. cmd_data.val = val;
  378. cmd_data.range = range;
  379. cmd( &cmd_data, sizeof(cmd_data) );
  380. }
  381. 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) {
  382. struct {
  383. int32_t type = CMD_SLIDER;
  384. int16_t x;
  385. int16_t y;
  386. int16_t w;
  387. int16_t h;
  388. uint16_t options;
  389. uint16_t val;
  390. uint16_t range;
  391. } cmd_data;
  392. cmd_data.x = x;
  393. cmd_data.y = y;
  394. cmd_data.w = w;
  395. cmd_data.h = h;
  396. cmd_data.options = options;
  397. cmd_data.val = val;
  398. cmd_data.range = range;
  399. cmd( &cmd_data, sizeof(cmd_data) );
  400. }
  401. void CLCD::CommandFifo::gradient (int16_t x0, int16_t y0, uint32_t rgb0, int16_t x1, int16_t y1, uint32_t rgb1) {
  402. struct {
  403. int32_t type = CMD_GRADIENT;
  404. int16_t x0;
  405. int16_t y0;
  406. uint32_t rgb0;
  407. int16_t x1;
  408. int16_t y1;
  409. uint32_t rgb1;
  410. } cmd_data;
  411. cmd_data.x0 = x0;
  412. cmd_data.y0 = y0;
  413. cmd_data.rgb0 = rgb0;
  414. cmd_data.x1 = x1;
  415. cmd_data.y1 = y1;
  416. cmd_data.rgb1 = rgb1;
  417. cmd( &cmd_data, sizeof(cmd_data) );
  418. }
  419. void CLCD::CommandFifo::number (int16_t x, int16_t y, int16_t font, uint16_t options, int32_t n) {
  420. struct {
  421. int32_t type = CMD_NUMBER;
  422. int16_t x;
  423. int16_t y;
  424. int16_t font;
  425. uint16_t options;
  426. int16_t n;
  427. } cmd_data;
  428. cmd_data.x = x;
  429. cmd_data.y = y;
  430. cmd_data.font = font;
  431. cmd_data.options = options;
  432. cmd_data.n = n;
  433. cmd( &cmd_data, sizeof(cmd_data) );
  434. }
  435. void CLCD::CommandFifo::memzero (uint32_t ptr, uint32_t size) {
  436. struct {
  437. uint32_t type = CMD_MEMZERO;
  438. uint32_t ptr;
  439. uint32_t size;
  440. } cmd_data;
  441. cmd_data.ptr = ptr;
  442. cmd_data.size = size;
  443. cmd( &cmd_data, sizeof(cmd_data) );
  444. }
  445. void CLCD::CommandFifo::memset (uint32_t ptr, uint32_t val, uint32_t size) {
  446. struct {
  447. uint32_t type = CMD_MEMSET;
  448. uint32_t ptr;
  449. uint32_t val;
  450. uint32_t size;
  451. } cmd_data;
  452. cmd_data.ptr = ptr;
  453. cmd_data.val = val;
  454. cmd_data.size = size;
  455. cmd( &cmd_data, sizeof(cmd_data) );
  456. }
  457. void CLCD::CommandFifo::memcpy (uint32_t dst, uint32_t src, uint32_t size) {
  458. struct {
  459. uint32_t type = CMD_MEMCPY;
  460. uint32_t dst;
  461. uint32_t src;
  462. uint32_t size;
  463. } cmd_data;
  464. cmd_data.dst = dst;
  465. cmd_data.src = src;
  466. cmd_data.size = size;
  467. cmd( &cmd_data, sizeof(cmd_data) );
  468. }
  469. void CLCD::CommandFifo::memcrc (uint32_t ptr, uint32_t num, uint32_t result) {
  470. struct {
  471. uint32_t type = CMD_MEMCRC;
  472. uint32_t ptr;
  473. uint32_t num;
  474. uint32_t result;
  475. } cmd_data;
  476. cmd_data.ptr = ptr;
  477. cmd_data.num = num;
  478. cmd_data.result = result;
  479. cmd( &cmd_data, sizeof(cmd_data) );
  480. }
  481. void CLCD::CommandFifo::memwrite (uint32_t ptr, uint32_t value) {
  482. struct {
  483. uint32_t type = CMD_MEMWRITE;
  484. uint32_t ptr;
  485. uint32_t num;
  486. uint32_t value;
  487. } cmd_data;
  488. cmd_data.ptr = ptr;
  489. cmd_data.num = 4;
  490. cmd_data.value = value;
  491. cmd( &cmd_data, sizeof(cmd_data) );
  492. }
  493. void CLCD::CommandFifo::append (uint32_t ptr, uint32_t size) {
  494. struct {
  495. uint32_t type = CMD_APPEND;
  496. uint32_t ptr;
  497. uint32_t size;
  498. } cmd_data;
  499. cmd_data.ptr = ptr;
  500. cmd_data.size = size;
  501. cmd( &cmd_data, sizeof(cmd_data) );
  502. }
  503. void CLCD::CommandFifo::inflate (uint32_t ptr) {
  504. struct {
  505. uint32_t type = CMD_INFLATE;
  506. uint32_t ptr;
  507. } cmd_data;
  508. cmd_data.ptr = ptr;
  509. cmd( &cmd_data, sizeof(cmd_data) );
  510. }
  511. void CLCD::CommandFifo::getptr (uint32_t result) {
  512. struct {
  513. uint32_t type = CMD_GETPTR;
  514. uint32_t result;
  515. } cmd_data;
  516. cmd_data.result = result;
  517. cmd( &cmd_data, sizeof(cmd_data) );
  518. }
  519. void CLCD::CommandFifo::track(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t tag) {
  520. struct {
  521. uint32_t type = CMD_TRACK;
  522. int16_t x;
  523. int16_t y;
  524. int16_t w;
  525. int16_t h;
  526. int16_t tag;
  527. } cmd_data;
  528. cmd_data.x = x;
  529. cmd_data.y = y;
  530. cmd_data.w = w;
  531. cmd_data.h = h;
  532. cmd_data.tag = tag;
  533. cmd( &cmd_data, sizeof(cmd_data) );
  534. }
  535. void CLCD::CommandFifo::sketch(int16_t x, int16_t y, uint16_t w, uint16_t h, uint32_t ptr, uint16_t format) {
  536. struct {
  537. uint32_t type = CMD_SKETCH;
  538. int16_t x;
  539. int16_t y;
  540. uint16_t w;
  541. uint16_t h;
  542. uint32_t ptr;
  543. uint16_t format;
  544. } cmd_data;
  545. cmd_data.x = x;
  546. cmd_data.y = y;
  547. cmd_data.w = w;
  548. cmd_data.h = h;
  549. cmd_data.ptr = ptr;
  550. cmd_data.format = format;
  551. cmd( &cmd_data, sizeof(cmd_data) );
  552. }
  553. void CLCD::CommandFifo::snapshot(uint32_t ptr) {
  554. struct {
  555. uint32_t type = CMD_SNAPSHOT;
  556. uint32_t ptr;
  557. } cmd_data;
  558. cmd_data.ptr = ptr;
  559. cmd( &cmd_data, sizeof(cmd_data) );
  560. }
  561. void CLCD::CommandFifo::spinner(int16_t x, int16_t y, uint16_t style, uint16_t scale) {
  562. struct {
  563. uint32_t type = CMD_SPINNER;
  564. uint16_t x;
  565. uint16_t y;
  566. uint16_t style;
  567. uint16_t scale;
  568. } cmd_data;
  569. cmd_data.x = x;
  570. cmd_data.y = y;
  571. cmd_data.style = style;
  572. cmd_data.scale = scale;
  573. cmd( &cmd_data, sizeof(cmd_data) );
  574. }
  575. void CLCD::CommandFifo::loadimage(uint32_t ptr, uint32_t options) {
  576. struct {
  577. uint32_t type = CMD_LOADIMAGE;
  578. uint32_t ptr;
  579. uint32_t options;
  580. } cmd_data;
  581. cmd_data.ptr = ptr;
  582. cmd_data.options = options;
  583. cmd( &cmd_data, sizeof(cmd_data) );
  584. }
  585. void CLCD::CommandFifo::getprops (uint32_t ptr, uint32_t width, uint32_t height) {
  586. struct {
  587. uint32_t type = CMD_GETPROPS;
  588. uint32_t ptr;
  589. uint32_t width;
  590. uint32_t height;
  591. } cmd_data;
  592. cmd_data.ptr = ptr;
  593. cmd_data.width = width;
  594. cmd_data.height = height;
  595. cmd( &cmd_data, sizeof(cmd_data) );
  596. }
  597. void CLCD::CommandFifo::scale(int32_t sx, int32_t sy) {
  598. struct {
  599. uint32_t type = CMD_SCALE;
  600. int32_t sx;
  601. int32_t sy;
  602. } cmd_data;
  603. cmd_data.sx = sx;
  604. cmd_data.sy = sy;
  605. cmd( &cmd_data, sizeof(cmd_data) );
  606. }
  607. void CLCD::CommandFifo::rotate(int32_t a) {
  608. struct {
  609. uint32_t type = CMD_ROTATE;
  610. int32_t a;
  611. } cmd_data;
  612. cmd_data.a = a;
  613. cmd( &cmd_data, sizeof(cmd_data) );
  614. }
  615. void CLCD::CommandFifo::translate (int32_t tx, int32_t ty) {
  616. struct {
  617. uint32_t type = CMD_TRANSLATE;
  618. int32_t tx;
  619. int32_t ty;
  620. } cmd_data;
  621. cmd_data.tx = tx;
  622. cmd_data.ty = ty;
  623. cmd( &cmd_data, sizeof(cmd_data) );
  624. }
  625. #if FTDI_API_LEVEL >= 810
  626. void CLCD::CommandFifo::setbase (uint8_t base) {
  627. struct {
  628. int32_t type = CMD_SETBASE;
  629. uint32_t base;
  630. } cmd_data;
  631. cmd_data.base = base;
  632. cmd( &cmd_data, sizeof(cmd_data) );
  633. }
  634. #endif
  635. #if FTDI_API_LEVEL >= 810
  636. void CLCD::CommandFifo::setbitmap(uint32_t addr, uint16_t fmt, uint16_t w, uint16_t h) {
  637. struct {
  638. uint32_t type = CMD_SETBITMAP;
  639. uint32_t addr;
  640. uint16_t fmt;
  641. uint16_t w;
  642. uint16_t h;
  643. uint16_t dummy;
  644. } cmd_data;
  645. cmd_data.addr = addr;
  646. cmd_data.fmt = fmt;
  647. cmd_data.w = w;
  648. cmd_data.h = h;
  649. cmd_data.dummy = 0;
  650. cmd( &cmd_data, sizeof(cmd_data) );
  651. }
  652. #endif
  653. #if FTDI_API_LEVEL >= 810
  654. void CLCD::CommandFifo::snapshot2(uint32_t format, uint32_t ptr, int16_t x, int16_t y, uint16_t w, uint16_t h) {
  655. struct {
  656. uint32_t type = CMD_SNAPSHOT2;
  657. uint32_t format;
  658. uint32_t ptr;
  659. int16_t x;
  660. int16_t y;
  661. uint16_t w;
  662. uint16_t h;
  663. } cmd_data;
  664. cmd_data.format = format;
  665. cmd_data.ptr = ptr;
  666. cmd_data.x = x;
  667. cmd_data.y = y;
  668. cmd_data.w = w;
  669. cmd_data.h = h;
  670. cmd( &cmd_data, sizeof(cmd_data) );
  671. }
  672. #endif
  673. #if FTDI_API_LEVEL >= 810
  674. void CLCD::CommandFifo::mediafifo(uint32_t ptr, uint32_t size) {
  675. struct {
  676. uint32_t type = CMD_MEDIAFIFO;
  677. uint32_t ptr;
  678. uint32_t size;
  679. } cmd_data;
  680. cmd_data.ptr = ptr;
  681. cmd_data.size = size;
  682. cmd( &cmd_data, sizeof(cmd_data) );
  683. }
  684. #endif
  685. #if FTDI_API_LEVEL >= 810
  686. void CLCD::CommandFifo::videostart() {
  687. cmd( CMD_VIDEOSTART );
  688. }
  689. #endif
  690. #if FTDI_API_LEVEL >= 810
  691. void CLCD::CommandFifo::videoframe(uint32_t dst, uint32_t ptr) {
  692. struct {
  693. uint32_t type = CMD_VIDEOFRAME;
  694. uint32_t dst;
  695. uint32_t ptr;
  696. } cmd_data;
  697. cmd_data.dst = dst;
  698. cmd_data.ptr = ptr;
  699. cmd( &cmd_data, sizeof(cmd_data) );
  700. }
  701. #endif
  702. #if FTDI_API_LEVEL >= 810
  703. void CLCD::CommandFifo::playvideo(uint32_t options) {
  704. struct {
  705. uint32_t type = CMD_PLAYVIDEO;
  706. uint32_t options;
  707. } cmd_data;
  708. cmd_data.options = options;
  709. cmd( &cmd_data, sizeof(cmd_data) );
  710. }
  711. #endif
  712. #if FTDI_API_LEVEL >= 810
  713. void CLCD::CommandFifo::setrotate (uint8_t rotation) {
  714. struct {
  715. uint32_t type = CMD_SETROTATE;
  716. uint32_t rotation;
  717. } cmd_data;
  718. cmd_data.rotation = rotation;
  719. cmd( &cmd_data, sizeof(cmd_data) );
  720. }
  721. #endif
  722. #if FTDI_API_LEVEL >= 810
  723. void CLCD::CommandFifo::romfont (uint8_t font, uint8_t romslot) {
  724. struct {
  725. uint32_t type = CMD_ROMFONT;
  726. uint32_t font;
  727. uint32_t romslot;
  728. } cmd_data;
  729. cmd_data.font = font;
  730. cmd_data.romslot = romslot;
  731. cmd( &cmd_data, sizeof(cmd_data) );
  732. }
  733. #endif
  734. /**************************** FT800/810 Co-Processor Command FIFO ****************************/
  735. bool CLCD::CommandFifo::is_processing() {
  736. return (mem_read_32(REG::CMD_READ) & 0x0FFF) != (mem_read_32(REG::CMD_WRITE) & 0x0FFF);
  737. }
  738. bool CLCD::CommandFifo::has_fault() {
  739. uint16_t Cmd_Read_Reg = mem_read_32(REG::CMD_READ) & 0x0FFF;
  740. return Cmd_Read_Reg == 0x0FFF;
  741. }
  742. #if FTDI_API_LEVEL == 800
  743. void CLCD::CommandFifo::start() {
  744. if (command_write_ptr == 0xFFFFFFFFul) {
  745. command_write_ptr = mem_read_32(REG::CMD_WRITE) & 0x0FFF;
  746. }
  747. }
  748. void CLCD::CommandFifo::execute() {
  749. if (command_write_ptr != 0xFFFFFFFFul) {
  750. mem_write_32(REG::CMD_WRITE, command_write_ptr);
  751. }
  752. }
  753. void CLCD::CommandFifo::reset() {
  754. safe_delay(100);
  755. mem_write_32(REG::CPURESET, 0x00000001);
  756. mem_write_32(REG::CMD_WRITE, 0x00000000);
  757. mem_write_32(REG::CMD_READ, 0x00000000);
  758. mem_write_32(REG::CPURESET, 0x00000000);
  759. safe_delay(300);
  760. command_write_ptr = 0xFFFFFFFFul;
  761. };
  762. template <class T> bool CLCD::CommandFifo::_write_unaligned(T data, uint16_t len) {
  763. const char *ptr = (const char*)data;
  764. uint32_t bytes_tail, bytes_head;
  765. uint32_t command_read_ptr;
  766. #if ENABLED(TOUCH_UI_DEBUG)
  767. if (command_write_ptr == 0xFFFFFFFFul) {
  768. SERIAL_ECHO_MSG("Attempt to write to FIFO before CommandFifo::Cmd_Start().");
  769. }
  770. #endif
  771. /* Wait until there is enough space in the circular buffer for the transfer */
  772. do {
  773. command_read_ptr = mem_read_32(REG::CMD_READ) & 0x0FFF;
  774. if (command_read_ptr <= command_write_ptr) {
  775. bytes_tail = 4096U - command_write_ptr;
  776. bytes_head = command_read_ptr;
  777. } else {
  778. bytes_tail = command_read_ptr - command_write_ptr;
  779. bytes_head = 0;
  780. }
  781. // Check for faults which can lock up the command processor
  782. if (has_fault()) {
  783. #if ENABLED(TOUCH_UI_DEBUG)
  784. SERIAL_ECHOLNPGM("Fault waiting for space in the command processor");
  785. #endif
  786. return false;
  787. }
  788. } while ((bytes_tail + bytes_head) < len);
  789. /* Write as many bytes as possible following REG::CMD_WRITE */
  790. uint16_t bytes_to_write = min(len, bytes_tail);
  791. mem_write_bulk (MAP::RAM_CMD + command_write_ptr, T(ptr), bytes_to_write);
  792. command_write_ptr += bytes_to_write;
  793. ptr += bytes_to_write;
  794. len -= bytes_to_write;
  795. if (len > 0) {
  796. /* Write remaining bytes at start of circular buffer */
  797. mem_write_bulk (MAP::RAM_CMD, T(ptr), len);
  798. command_write_ptr = len;
  799. }
  800. if (command_write_ptr == 4096U) {
  801. command_write_ptr = 0;
  802. }
  803. return true;
  804. }
  805. // Writes len bytes into the FIFO, if len is not
  806. // divisible by four, zero bytes will be written
  807. // to align to the boundary.
  808. template <class T> bool CLCD::CommandFifo::write(T data, uint16_t len) {
  809. const uint8_t padding = MULTIPLE_OF_4(len) - len;
  810. uint8_t pad_bytes[] = {0, 0, 0, 0};
  811. return _write_unaligned(data, len) &&
  812. _write_unaligned(pad_bytes, padding);
  813. }
  814. #else
  815. void CLCD::CommandFifo::start() {
  816. }
  817. void CLCD::CommandFifo::execute() {
  818. }
  819. void CLCD::CommandFifo::reset() {
  820. #if ENABLED(TOUCH_UI_DEBUG)
  821. SERIAL_ECHOLNPGM("Resetting command processor");
  822. #endif
  823. safe_delay(100);
  824. mem_write_32(REG::CPURESET, 0x00000001);
  825. mem_write_32(REG::CMD_WRITE, 0x00000000);
  826. mem_write_32(REG::CMD_READ, 0x00000000);
  827. mem_write_32(REG::CPURESET, 0x00000000);
  828. safe_delay(300);
  829. };
  830. // Writes len bytes into the FIFO, if len is not
  831. // divisible by four, zero bytes will be written
  832. // to align to the boundary.
  833. template <class T> bool CLCD::CommandFifo::write(T data, uint16_t len) {
  834. const uint8_t padding = MULTIPLE_OF_4(len) - len;
  835. if (has_fault()) {
  836. #if ENABLED(TOUCH_UI_DEBUG)
  837. SERIAL_ECHOLNPGM("Faulted... ignoring write.");
  838. #endif
  839. return false;
  840. }
  841. // The FT810 provides a special register that can be used
  842. // for writing data without us having to do our own FIFO
  843. // management.
  844. uint16_t Command_Space = mem_read_32(REG::CMDB_SPACE) & 0x0FFF;
  845. if (Command_Space < (len + padding)) {
  846. #if ENABLED(TOUCH_UI_DEBUG)
  847. SERIAL_ECHO_START();
  848. SERIAL_ECHOPAIR("Waiting for ", len + padding);
  849. SERIAL_ECHOLNPAIR(" bytes in command queue, now free: ", Command_Space);
  850. #endif
  851. do {
  852. Command_Space = mem_read_32(REG::CMDB_SPACE) & 0x0FFF;
  853. if (has_fault()) {
  854. #if ENABLED(TOUCH_UI_DEBUG)
  855. SERIAL_ECHOLNPGM("... fault");
  856. #endif
  857. return false;
  858. }
  859. } while (Command_Space < len + padding);
  860. #if ENABLED(TOUCH_UI_DEBUG)
  861. SERIAL_ECHOLNPGM("... done");
  862. #endif
  863. }
  864. mem_write_bulk(REG::CMDB_WRITE, data, len, padding);
  865. return true;
  866. }
  867. #endif
  868. template bool CLCD::CommandFifo::write(const void*, uint16_t);
  869. template bool CLCD::CommandFifo::write(progmem_str, uint16_t);
  870. // CO_PROCESSOR COMMANDS
  871. void CLCD::CommandFifo::str(const char * data) {
  872. write(data, strlen(data)+1);
  873. }
  874. void CLCD::CommandFifo::str(progmem_str data) {
  875. write(data, strlen_P((const char*)data)+1);
  876. }
  877. /******************* LCD INITIALIZATION ************************/
  878. void CLCD::init() {
  879. spi_init(); // Set Up I/O Lines for SPI and FT800/810 Control
  880. ftdi_reset(); // Power down/up the FT8xx with the apropriate delays
  881. if (Use_Crystal == 1) {
  882. host_cmd(CLKEXT, 0);
  883. }
  884. else {
  885. host_cmd(CLKINT, 0);
  886. }
  887. host_cmd(ACTIVE, 0); // Activate the System Clock
  888. /* read the device-id until it returns 0x7c or times out, should take less than 150ms */
  889. uint8_t counter;
  890. for(counter = 0; counter < 250; counter++) {
  891. uint8_t device_id = mem_read_8(REG::ID); // Read Device ID, Should Be 0x7C;
  892. if (device_id == 0x7c) {
  893. #if ENABLED(TOUCH_UI_DEBUG)
  894. SERIAL_ECHO_MSG("FTDI chip initialized ");
  895. #endif
  896. break;
  897. }
  898. else {
  899. delay(1);
  900. }
  901. if (counter == 249) {
  902. #if ENABLED(TOUCH_UI_DEBUG)
  903. SERIAL_ECHO_START();
  904. SERIAL_ECHOLNPAIR("Timeout waiting for device ID, should be 124, got ", device_id);
  905. #endif
  906. }
  907. }
  908. mem_write_8(REG::PWM_DUTY, 0); // turn off Backlight, Frequency already is set to 250Hz default
  909. /* Configure the FT8xx Registers */
  910. mem_write_16(REG::HCYCLE, FTDI::Hcycle);
  911. mem_write_16(REG::HOFFSET, FTDI::Hoffset);
  912. mem_write_16(REG::HSYNC0, FTDI::Hsync0);
  913. mem_write_16(REG::HSYNC1, FTDI::Hsync1);
  914. mem_write_16(REG::VCYCLE, FTDI::Vcycle);
  915. mem_write_16(REG::VOFFSET, FTDI::Voffset);
  916. mem_write_16(REG::VSYNC0, FTDI::Vsync0);
  917. mem_write_16(REG::VSYNC1, FTDI::Vsync1);
  918. mem_write_16(REG::HSIZE, FTDI::Hsize);
  919. mem_write_16(REG::VSIZE, FTDI::Vsize);
  920. mem_write_8(REG::SWIZZLE, FTDI::Swizzle);
  921. mem_write_8(REG::PCLK_POL, FTDI::Pclkpol);
  922. mem_write_8(REG::CSPREAD, FTDI::CSpread);
  923. /* write a basic display-list to get things started */
  924. mem_write_32(MAP::RAM_DL, DL::CLEAR_COLOR_RGB);
  925. mem_write_32(MAP::RAM_DL + 4, (DL::CLEAR | 0x07)); /* clear color, stencil and tag buffer */
  926. mem_write_32(MAP::RAM_DL + 8, DL::DL_DISPLAY); /* end of display list */
  927. mem_write_8(REG::DLSWAP, 0x02); // activate display list, Bad Magic Cookie 2 = switch to new list after current frame is scanned out
  928. //mem_write_8(REG::TOUCH_MODE, 0x03); // Configure the Touch Screen, Bad Magic Cookie, 3 = CONTINUOUS = Reset Default
  929. //mem_write_8(REG::TOUCH_ADC_MODE, 0x01); // Bad Magic Cookie, 1 = single touch = Reset Default
  930. //mem_write_8(REG::TOUCH_OVERSAMPLE, 0x0F); // Reset Default = 7 - why 15?
  931. mem_write_16(REG::TOUCH_RZTHRESH, touch_threshold); /* setup touch sensitivity */
  932. mem_write_8(REG::VOL_SOUND, 0x00); // Turn Synthesizer Volume Off
  933. /* turn on the display by setting DISP high */
  934. /* turn on the Audio Amplifier by setting GPIO_1 high for the select few modules supporting this */
  935. /* no need to use GPIOX here since DISP/GPIO_0 and GPIO_1 are on REG::GPIO for FT81x as well */
  936. if (GPIO_1_Audio_Shutdown) {
  937. mem_write_8(REG::GPIO_DIR, GPIO_DISP | GPIO_GP1);
  938. mem_write_8(REG::GPIO, GPIO_DISP | GPIO_GP1);
  939. } else if (GPIO_0_Audio_Enable) {
  940. mem_write_8(REG::GPIO_DIR, GPIO_DISP | GPIO_GP0);
  941. mem_write_8(REG::GPIO, GPIO_DISP | GPIO_GP0);
  942. }
  943. else {
  944. mem_write_8(REG::GPIO, GPIO_DISP); /* REG::GPIO_DIR is set to output for GPIO_DISP by default */
  945. }
  946. mem_write_8(REG::PCLK, Pclk); // Turns on Clock by setting PCLK Register to the value necessary for the module
  947. mem_write_16(REG::PWM_HZ, 0x00FA);
  948. // Turning off dithering seems to help prevent horizontal line artifacts on certain colors
  949. mem_write_8(REG::DITHER, 0);
  950. // Initialize the command FIFO
  951. CommandFifo::reset();
  952. default_touch_transform();
  953. default_display_orientation();
  954. }
  955. void CLCD::default_touch_transform() {
  956. // Set Initial Values for Touch Transform Registers
  957. mem_write_32(REG::ROTATE, 0);
  958. mem_write_32(REG::TOUCH_TRANSFORM_A, FTDI::default_transform_a);
  959. mem_write_32(REG::TOUCH_TRANSFORM_B, FTDI::default_transform_b);
  960. mem_write_32(REG::TOUCH_TRANSFORM_C, FTDI::default_transform_c);
  961. mem_write_32(REG::TOUCH_TRANSFORM_D, FTDI::default_transform_d);
  962. mem_write_32(REG::TOUCH_TRANSFORM_E, FTDI::default_transform_e);
  963. mem_write_32(REG::TOUCH_TRANSFORM_F, FTDI::default_transform_f);
  964. }
  965. void CLCD::default_display_orientation() {
  966. #if FTDI_API_LEVEL >= 810
  967. // Set the initial display orientation. On the FT810, we use the command
  968. // processor to do this since it will also update the transform matrices.
  969. if (FTDI::ftdi_chip >= 810) {
  970. CommandFifo cmd;
  971. cmd.setrotate(0
  972. #if ENABLED(TOUCH_UI_MIRRORED)
  973. + 4
  974. #endif
  975. #if ENABLED(TOUCH_UI_PORTRAIT)
  976. + 2
  977. #endif
  978. #if ENABLED(TOUCH_UI_INVERTED)
  979. + 1
  980. #endif
  981. );
  982. cmd.execute();
  983. }
  984. else {
  985. #if ENABLED(TOUCH_UI_INVERTED)
  986. mem_write_32(REG::ROTATE, 1);
  987. #endif
  988. }
  989. #elif ANY(TOUCH_UI_PORTRAIT, TOUCH_UI_MIRRORED)
  990. #error "PORTRAIT or MIRRORED orientation not supported on the FT800."
  991. #elif ENABLED(TOUCH_UI_INVERTED)
  992. mem_write_32(REG::ROTATE, 1);
  993. #endif
  994. }
  995. #endif // FTDI_BASIC