Adafruit_SPITFT.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. /*!
  2. * @file Adafruit_SPITFT.cpp
  3. *
  4. * @mainpage Adafruit SPI TFT Displays
  5. *
  6. * @section intro_sec Introduction
  7. This is our library for generic SPI TFT Displays with
  8. address windows and 16 bit color (e.g. ILI9341, HX8357D, ST7735...)
  9. Check out the links above for our tutorials and wiring diagrams
  10. These displays use SPI to communicate, 4 or 5 pins are required to
  11. interface (RST is optional)
  12. Adafruit invests time and resources providing this open source code,
  13. please support Adafruit and open-source hardware by purchasing
  14. products from Adafruit!
  15. Written by Limor Fried/Ladyada for Adafruit Industries.
  16. MIT license, all text above must be included in any redistribution
  17. * @section dependencies Dependencies
  18. *
  19. * This library depends on <a href="https://github.com/adafruit/Adafruit_GFX">
  20. * Adafruit_GFX</a> being present on your system. Please make sure you have
  21. * installed the latest version before using this library.
  22. *
  23. * @section author Author
  24. *
  25. * Written by Limor "ladyada" Fried for Adafruit Industries.
  26. *
  27. * @section license License
  28. *
  29. * BSD license, all text here must be included in any redistribution.
  30. *
  31. */
  32. #ifndef __AVR_ATtiny85__ // NOT A CHANCE of this stuff working on ATtiny!
  33. #include "Adafruit_SPITFT.h"
  34. #ifndef ARDUINO_STM32_FEATHER
  35. #include "pins_arduino.h"
  36. #ifndef RASPI
  37. #include "wiring_private.h"
  38. #endif
  39. #endif
  40. #include <limits.h>
  41. #include "Adafruit_SPITFT_Macros.h"
  42. /**************************************************************************/
  43. /*!
  44. @brief Pass 8-bit (each) R,G,B, get back 16-bit packed color
  45. This function converts 8-8-8 RGB data to 16-bit 5-6-5
  46. @param red Red 8 bit color
  47. @param green Green 8 bit color
  48. @param blue Blue 8 bit color
  49. @return Unsigned 16-bit down-sampled color in 5-6-5 format
  50. */
  51. /**************************************************************************/
  52. uint16_t Adafruit_SPITFT::color565(uint8_t red, uint8_t green, uint8_t blue) {
  53. return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3);
  54. }
  55. /**************************************************************************/
  56. /*!
  57. @brief Instantiate Adafruit SPI display driver with software SPI
  58. @param w Display width in pixels
  59. @param h Display height in pixels
  60. @param cs Chip select pin #
  61. @param dc Data/Command pin #
  62. @param mosi SPI MOSI pin #
  63. @param sclk SPI Clock pin #
  64. @param rst Reset pin # (optional, pass -1 if unused)
  65. @param miso SPI MISO pin # (optional, pass -1 if unused)
  66. */
  67. /**************************************************************************/
  68. Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h,
  69. int8_t cs, int8_t dc, int8_t mosi,
  70. int8_t sclk, int8_t rst, int8_t miso)
  71. : Adafruit_GFX(w, h) {
  72. _cs = cs;
  73. _dc = dc;
  74. _rst = rst;
  75. _sclk = sclk;
  76. _mosi = mosi;
  77. _miso = miso;
  78. _freq = 0;
  79. #ifdef USE_FAST_PINIO
  80. dcport = (RwReg *)portOutputRegister(digitalPinToPort(dc));
  81. dcpinmask = digitalPinToBitMask(dc);
  82. clkport = (RwReg *)portOutputRegister(digitalPinToPort(sclk));
  83. clkpinmask = digitalPinToBitMask(sclk);
  84. mosiport = (RwReg *)portOutputRegister(digitalPinToPort(mosi));
  85. mosipinmask = digitalPinToBitMask(mosi);
  86. if(miso >= 0){
  87. misoport = (RwReg *)portInputRegister(digitalPinToPort(miso));
  88. misopinmask = digitalPinToBitMask(miso);
  89. } else {
  90. misoport = 0;
  91. misopinmask = 0;
  92. }
  93. if(cs >= 0) {
  94. csport = (RwReg *)portOutputRegister(digitalPinToPort(cs));
  95. cspinmask = digitalPinToBitMask(cs);
  96. } else {
  97. // No chip-select line defined; might be permanently tied to GND.
  98. // Assign a valid GPIO register (though not used for CS), and an
  99. // empty pin bitmask...the nonsense bit-twiddling might be faster
  100. // than checking _cs and possibly branching.
  101. csport = dcport;
  102. cspinmask = 0;
  103. }
  104. #endif
  105. }
  106. /**************************************************************************/
  107. /*!
  108. @brief Instantiate Adafruit SPI display driver with hardware SPI
  109. @param w Display width in pixels
  110. @param h Display height in pixels
  111. @param cs Chip select pin #
  112. @param dc Data/Command pin #
  113. @param rst Reset pin # (optional, pass -1 if unused)
  114. */
  115. /**************************************************************************/
  116. Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h,
  117. int8_t cs, int8_t dc, int8_t rst)
  118. : Adafruit_GFX(w, h) {
  119. _cs = cs;
  120. _dc = dc;
  121. _rst = rst;
  122. _sclk = -1;
  123. _mosi = -1;
  124. _miso = -1;
  125. _freq = 0;
  126. #ifdef USE_FAST_PINIO
  127. clkport = 0;
  128. clkpinmask = 0;
  129. mosiport = 0;
  130. mosipinmask = 0;
  131. misoport = 0;
  132. misopinmask = 0;
  133. dcport = (RwReg *)portOutputRegister(digitalPinToPort(dc));
  134. dcpinmask = digitalPinToBitMask(dc);
  135. if(cs >= 0) {
  136. csport = (RwReg *)portOutputRegister(digitalPinToPort(cs));
  137. cspinmask = digitalPinToBitMask(cs);
  138. } else {
  139. // See notes in prior constructor.
  140. csport = dcport;
  141. cspinmask = 0;
  142. }
  143. #endif
  144. }
  145. /**************************************************************************/
  146. /*!
  147. @brief Initialiaze the SPI interface (hardware or software)
  148. @param freq The desired maximum SPI hardware clock frequency
  149. */
  150. /**************************************************************************/
  151. void Adafruit_SPITFT::initSPI(uint32_t freq) {
  152. _freq = freq;
  153. // Control Pins
  154. if(_cs >= 0) {
  155. pinMode(_cs, OUTPUT);
  156. digitalWrite(_cs, HIGH); // Deselect
  157. }
  158. pinMode(_dc, OUTPUT);
  159. digitalWrite(_dc, LOW);
  160. // Software SPI
  161. if(_sclk >= 0){
  162. pinMode(_mosi, OUTPUT);
  163. digitalWrite(_mosi, LOW);
  164. pinMode(_sclk, OUTPUT);
  165. digitalWrite(_sclk, HIGH);
  166. if(_miso >= 0){
  167. pinMode(_miso, INPUT);
  168. }
  169. }
  170. // Hardware SPI
  171. SPI_BEGIN();
  172. // toggle RST low to reset
  173. if (_rst >= 0) {
  174. pinMode(_rst, OUTPUT);
  175. digitalWrite(_rst, HIGH);
  176. delay(100);
  177. digitalWrite(_rst, LOW);
  178. delay(100);
  179. digitalWrite(_rst, HIGH);
  180. delay(200);
  181. }
  182. }
  183. /**************************************************************************/
  184. /*!
  185. @brief Read one byte from SPI interface (hardware or software
  186. @returns One byte, MSB order
  187. */
  188. /**************************************************************************/
  189. uint8_t Adafruit_SPITFT::spiRead() {
  190. if(_sclk < 0){
  191. return HSPI_READ();
  192. }
  193. if(_miso < 0){
  194. return 0;
  195. }
  196. uint8_t r = 0;
  197. for (uint8_t i=0; i<8; i++) {
  198. SSPI_SCK_LOW();
  199. SSPI_SCK_HIGH();
  200. r <<= 1;
  201. if (SSPI_MISO_READ()){
  202. r |= 0x1;
  203. }
  204. }
  205. return r;
  206. }
  207. /**************************************************************************/
  208. /*!
  209. @brief Write one byte to SPI interface (hardware or software
  210. @param b One byte to send, MSB order
  211. */
  212. /**************************************************************************/
  213. void Adafruit_SPITFT::spiWrite(uint8_t b) {
  214. if(_sclk < 0){
  215. HSPI_WRITE(b);
  216. return;
  217. }
  218. for(uint8_t bit = 0x80; bit; bit >>= 1){
  219. if((b) & bit){
  220. SSPI_MOSI_HIGH();
  221. } else {
  222. SSPI_MOSI_LOW();
  223. }
  224. SSPI_SCK_LOW();
  225. SSPI_SCK_HIGH();
  226. }
  227. }
  228. /*
  229. * Transaction API
  230. * */
  231. /**************************************************************************/
  232. /*!
  233. @brief Begin an SPI transaction & set CS low.
  234. */
  235. /**************************************************************************/
  236. void inline Adafruit_SPITFT::startWrite(void){
  237. SPI_BEGIN_TRANSACTION();
  238. SPI_CS_LOW();
  239. }
  240. /**************************************************************************/
  241. /*!
  242. @brief Begin an SPI transaction & set CS high.
  243. */
  244. /**************************************************************************/
  245. void inline Adafruit_SPITFT::endWrite(void){
  246. SPI_CS_HIGH();
  247. SPI_END_TRANSACTION();
  248. }
  249. /**************************************************************************/
  250. /*!
  251. @brief Write a command byte (must have a transaction in progress)
  252. @param cmd The 8-bit command to send
  253. */
  254. /**************************************************************************/
  255. void Adafruit_SPITFT::writeCommand(uint8_t cmd){
  256. SPI_DC_LOW();
  257. spiWrite(cmd);
  258. SPI_DC_HIGH();
  259. }
  260. /**************************************************************************/
  261. /*!
  262. @brief Push a 2-byte color to the framebuffer RAM, will start transaction
  263. @param color 16-bit 5-6-5 Color to draw
  264. */
  265. /**************************************************************************/
  266. void Adafruit_SPITFT::pushColor(uint16_t color) {
  267. startWrite();
  268. SPI_WRITE16(color);
  269. endWrite();
  270. }
  271. /**************************************************************************/
  272. /*!
  273. @brief Blit multiple 2-byte colors (must have a transaction in progress)
  274. @param colors Array of 16-bit 5-6-5 Colors to draw
  275. @param len How many pixels to draw - 2 bytes per pixel!
  276. */
  277. /**************************************************************************/
  278. void Adafruit_SPITFT::writePixels(uint16_t * colors, uint32_t len){
  279. SPI_WRITE_PIXELS((uint8_t*)colors , len * 2);
  280. }
  281. /**************************************************************************/
  282. /*!
  283. @brief Blit a 2-byte color many times (must have a transaction in progress)
  284. @param color The 16-bit 5-6-5 Color to draw
  285. @param len How many pixels to draw
  286. */
  287. /**************************************************************************/
  288. void Adafruit_SPITFT::writeColor(uint16_t color, uint32_t len){
  289. #ifdef SPI_HAS_WRITE_PIXELS
  290. if(_sclk >= 0){
  291. for (uint32_t t=0; t<len; t++){
  292. writePixel(color);
  293. }
  294. return;
  295. }
  296. static uint16_t temp[SPI_MAX_PIXELS_AT_ONCE];
  297. size_t blen = (len > SPI_MAX_PIXELS_AT_ONCE)?SPI_MAX_PIXELS_AT_ONCE:len;
  298. uint16_t tlen = 0;
  299. for (uint32_t t=0; t<blen; t++){
  300. temp[t] = color;
  301. }
  302. while(len){
  303. tlen = (len>blen)?blen:len;
  304. writePixels(temp, tlen);
  305. len -= tlen;
  306. }
  307. #else
  308. uint8_t hi = color >> 8, lo = color;
  309. if(_sclk < 0){ //AVR Optimization
  310. for (uint32_t t=len; t; t--){
  311. HSPI_WRITE(hi);
  312. HSPI_WRITE(lo);
  313. }
  314. return;
  315. }
  316. for (uint32_t t=len; t; t--){
  317. spiWrite(hi);
  318. spiWrite(lo);
  319. }
  320. #endif
  321. }
  322. /**************************************************************************/
  323. /*!
  324. @brief Write a pixel (must have a transaction in progress)
  325. @param x x coordinate
  326. @param y y coordinate
  327. @param color 16-bit 5-6-5 Color to draw with
  328. */
  329. /**************************************************************************/
  330. void Adafruit_SPITFT::writePixel(int16_t x, int16_t y, uint16_t color) {
  331. if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
  332. setAddrWindow(x,y,1,1);
  333. writePixel(color);
  334. }
  335. /**************************************************************************/
  336. /*!
  337. @brief Write a filled rectangle (must have a transaction in progress)
  338. @param x Top left corner x coordinate
  339. @param y Top left corner y coordinate
  340. @param w Width in pixels
  341. @param h Height in pixels
  342. @param color 16-bit 5-6-5 Color to fill with
  343. */
  344. /**************************************************************************/
  345. void Adafruit_SPITFT::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
  346. if((x >= _width) || (y >= _height)) return;
  347. int16_t x2 = x + w - 1, y2 = y + h - 1;
  348. if((x2 < 0) || (y2 < 0)) return;
  349. // Clip left/top
  350. if(x < 0) {
  351. x = 0;
  352. w = x2 + 1;
  353. }
  354. if(y < 0) {
  355. y = 0;
  356. h = y2 + 1;
  357. }
  358. // Clip right/bottom
  359. if(x2 >= _width) w = _width - x;
  360. if(y2 >= _height) h = _height - y;
  361. int32_t len = (int32_t)w * h;
  362. setAddrWindow(x, y, w, h);
  363. writeColor(color, len);
  364. }
  365. /**************************************************************************/
  366. /*!
  367. @brief Write a perfectly vertical line (must have a transaction in progress)
  368. @param x Top-most x coordinate
  369. @param y Top-most y coordinate
  370. @param h Height in pixels
  371. @param color 16-bit 5-6-5 Color to fill with
  372. */
  373. /**************************************************************************/
  374. void inline Adafruit_SPITFT::writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color){
  375. writeFillRect(x, y, 1, h, color);
  376. }
  377. /**************************************************************************/
  378. /*!
  379. @brief Write a perfectly horizontal line (must have a transaction in progress)
  380. @param x Left-most x coordinate
  381. @param y Left-most y coordinate
  382. @param w Width in pixels
  383. @param color 16-bit 5-6-5 Color to fill with
  384. */
  385. /**************************************************************************/
  386. void inline Adafruit_SPITFT::writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color){
  387. writeFillRect(x, y, w, 1, color);
  388. }
  389. /**************************************************************************/
  390. /*!
  391. @brief Draw a pixel - sets up transaction
  392. @param x x coordinate
  393. @param y y coordinate
  394. @param color 16-bit 5-6-5 Color to draw with
  395. */
  396. /**************************************************************************/
  397. void Adafruit_SPITFT::drawPixel(int16_t x, int16_t y, uint16_t color){
  398. startWrite();
  399. writePixel(x, y, color);
  400. endWrite();
  401. }
  402. /**************************************************************************/
  403. /*!
  404. @brief Write a perfectly vertical line - sets up transaction
  405. @param x Top-most x coordinate
  406. @param y Top-most y coordinate
  407. @param h Height in pixels
  408. @param color 16-bit 5-6-5 Color to fill with
  409. */
  410. /**************************************************************************/
  411. void Adafruit_SPITFT::drawFastVLine(int16_t x, int16_t y,
  412. int16_t h, uint16_t color) {
  413. startWrite();
  414. writeFastVLine(x, y, h, color);
  415. endWrite();
  416. }
  417. /**************************************************************************/
  418. /*!
  419. @brief Write a perfectly horizontal line - sets up transaction
  420. @param x Left-most x coordinate
  421. @param y Left-most y coordinate
  422. @param w Width in pixels
  423. @param color 16-bit 5-6-5 Color to fill with
  424. */
  425. /**************************************************************************/
  426. void Adafruit_SPITFT::drawFastHLine(int16_t x, int16_t y,
  427. int16_t w, uint16_t color) {
  428. startWrite();
  429. writeFastHLine(x, y, w, color);
  430. endWrite();
  431. }
  432. /**************************************************************************/
  433. /*!
  434. @brief Fill a rectangle completely with one color.
  435. @param x Top left corner x coordinate
  436. @param y Top left corner y coordinate
  437. @param w Width in pixels
  438. @param h Height in pixels
  439. @param color 16-bit 5-6-5 Color to fill with
  440. */
  441. /**************************************************************************/
  442. void Adafruit_SPITFT::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
  443. uint16_t color) {
  444. startWrite();
  445. writeFillRect(x,y,w,h,color);
  446. endWrite();
  447. }
  448. /**************************************************************************/
  449. /*!
  450. @brief Invert the display using built-in hardware command
  451. @param i True if you want to invert, false to make 'normal'
  452. */
  453. /**************************************************************************/
  454. void Adafruit_SPITFT::invertDisplay(boolean i) {
  455. startWrite();
  456. writeCommand(i ? invertOnCommand : invertOffCommand);
  457. endWrite();
  458. }
  459. /**************************************************************************/
  460. /*!
  461. @brief Draw a 16-bit image (RGB 5/6/5) at the specified (x,y) position.
  462. For 16-bit display devices; no color reduction performed.
  463. Adapted from https://github.com/PaulStoffregen/ILI9341_t3
  464. by Marc MERLIN. See examples/pictureEmbed to use this.
  465. 5/6/2017: function name and arguments have changed for compatibility
  466. with current GFX library and to avoid naming problems in prior
  467. implementation. Formerly drawBitmap() with arguments in different order.
  468. @param x Top left corner x coordinate
  469. @param y Top left corner y coordinate
  470. @param pcolors 16-bit array with 16-bit color bitmap
  471. @param w Width of bitmap in pixels
  472. @param h Height of bitmap in pixels
  473. */
  474. /**************************************************************************/
  475. void Adafruit_SPITFT::drawRGBBitmap(int16_t x, int16_t y,
  476. uint16_t *pcolors, int16_t w, int16_t h) {
  477. int16_t x2, y2; // Lower-right coord
  478. if(( x >= _width ) || // Off-edge right
  479. ( y >= _height) || // " top
  480. ((x2 = (x+w-1)) < 0 ) || // " left
  481. ((y2 = (y+h-1)) < 0) ) return; // " bottom
  482. int16_t bx1=0, by1=0, // Clipped top-left within bitmap
  483. saveW=w; // Save original bitmap width value
  484. if(x < 0) { // Clip left
  485. w += x;
  486. bx1 = -x;
  487. x = 0;
  488. }
  489. if(y < 0) { // Clip top
  490. h += y;
  491. by1 = -y;
  492. y = 0;
  493. }
  494. if(x2 >= _width ) w = _width - x; // Clip right
  495. if(y2 >= _height) h = _height - y; // Clip bottom
  496. pcolors += by1 * saveW + bx1; // Offset bitmap ptr to clipped top-left
  497. startWrite();
  498. setAddrWindow(x, y, w, h); // Clipped area
  499. while(h--) { // For each (clipped) scanline...
  500. writePixels(pcolors, w); // Push one (clipped) row
  501. pcolors += saveW; // Advance pointer by one full (unclipped) line
  502. }
  503. endWrite();
  504. }
  505. #endif // !__AVR_ATtiny85__