Adafruit_SPITFT.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /***************************************************
  2. This is our library for generic SPI TFT Displays with
  3. address windows and 16 bit color (e.g. ILI9341, HX8357D, ST7735...)
  4. Check out the links above for our tutorials and wiring diagrams
  5. These displays use SPI to communicate, 4 or 5 pins are required to
  6. interface (RST is optional)
  7. Adafruit invests time and resources providing this open source code,
  8. please support Adafruit and open-source hardware by purchasing
  9. products from Adafruit!
  10. Written by Limor Fried/Ladyada for Adafruit Industries.
  11. MIT license, all text above must be included in any redistribution
  12. ****************************************************/
  13. #include "Adafruit_SPITFT.h"
  14. #ifndef ARDUINO_STM32_FEATHER
  15. #include "pins_arduino.h"
  16. #ifndef RASPI
  17. #include "wiring_private.h"
  18. #endif
  19. #endif
  20. #include <limits.h>
  21. #include "Adafruit_SPITFT_Macros.h"
  22. // Pass 8-bit (each) R,G,B, get back 16-bit packed color
  23. uint16_t Adafruit_SPITFT::color565(uint8_t r, uint8_t g, uint8_t b) {
  24. return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
  25. }
  26. Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h,
  27. int8_t cs, int8_t dc, int8_t mosi,
  28. int8_t sclk, int8_t rst, int8_t miso)
  29. : Adafruit_GFX(w, h) {
  30. _cs = cs;
  31. _dc = dc;
  32. _rst = rst;
  33. _sclk = sclk;
  34. _mosi = mosi;
  35. _miso = miso;
  36. _freq = 0;
  37. #ifdef USE_FAST_PINIO
  38. csport = portOutputRegister(digitalPinToPort(_cs));
  39. cspinmask = digitalPinToBitMask(_cs);
  40. dcport = portOutputRegister(digitalPinToPort(_dc));
  41. dcpinmask = digitalPinToBitMask(_dc);
  42. clkport = portOutputRegister(digitalPinToPort(_sclk));
  43. clkpinmask = digitalPinToBitMask(_sclk);
  44. mosiport = portOutputRegister(digitalPinToPort(_mosi));
  45. mosipinmask = digitalPinToBitMask(_mosi);
  46. if(miso >= 0){
  47. misoport = portInputRegister(digitalPinToPort(_miso));
  48. misopinmask = digitalPinToBitMask(_miso);
  49. } else {
  50. misoport = 0;
  51. misopinmask = 0;
  52. }
  53. #endif
  54. }
  55. Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h,
  56. int8_t cs, int8_t dc, int8_t rst)
  57. : Adafruit_GFX(w, h) {
  58. _cs = cs;
  59. _dc = dc;
  60. _rst = rst;
  61. _sclk = -1;
  62. _mosi = -1;
  63. _miso = -1;
  64. _freq = 0;
  65. #ifdef USE_FAST_PINIO
  66. csport = portOutputRegister(digitalPinToPort(_cs));
  67. cspinmask = digitalPinToBitMask(_cs);
  68. dcport = portOutputRegister(digitalPinToPort(_dc));
  69. dcpinmask = digitalPinToBitMask(_dc);
  70. clkport = 0;
  71. clkpinmask = 0;
  72. mosiport = 0;
  73. mosipinmask = 0;
  74. misoport = 0;
  75. misopinmask = 0;
  76. #endif
  77. }
  78. void Adafruit_SPITFT::initSPI(uint32_t freq)
  79. {
  80. _freq = freq;
  81. // Control Pins
  82. pinMode(_dc, OUTPUT);
  83. digitalWrite(_dc, LOW);
  84. pinMode(_cs, OUTPUT);
  85. digitalWrite(_cs, HIGH);
  86. // Software SPI
  87. if(_sclk >= 0){
  88. pinMode(_mosi, OUTPUT);
  89. digitalWrite(_mosi, LOW);
  90. pinMode(_sclk, OUTPUT);
  91. digitalWrite(_sclk, HIGH);
  92. if(_miso >= 0){
  93. pinMode(_miso, INPUT);
  94. }
  95. }
  96. // Hardware SPI
  97. SPI_BEGIN();
  98. // toggle RST low to reset
  99. if (_rst >= 0) {
  100. pinMode(_rst, OUTPUT);
  101. digitalWrite(_rst, HIGH);
  102. delay(100);
  103. digitalWrite(_rst, LOW);
  104. delay(100);
  105. digitalWrite(_rst, HIGH);
  106. delay(200);
  107. }
  108. }
  109. uint8_t Adafruit_SPITFT::spiRead() {
  110. if(_sclk < 0){
  111. return HSPI_READ();
  112. }
  113. if(_miso < 0){
  114. return 0;
  115. }
  116. uint8_t r = 0;
  117. for (uint8_t i=0; i<8; i++) {
  118. SSPI_SCK_LOW();
  119. SSPI_SCK_HIGH();
  120. r <<= 1;
  121. if (SSPI_MISO_READ()){
  122. r |= 0x1;
  123. }
  124. }
  125. return r;
  126. }
  127. void Adafruit_SPITFT::spiWrite(uint8_t b) {
  128. if(_sclk < 0){
  129. HSPI_WRITE(b);
  130. return;
  131. }
  132. for(uint8_t bit = 0x80; bit; bit >>= 1){
  133. if((b) & bit){
  134. SSPI_MOSI_HIGH();
  135. } else {
  136. SSPI_MOSI_LOW();
  137. }
  138. SSPI_SCK_LOW();
  139. SSPI_SCK_HIGH();
  140. }
  141. }
  142. /*
  143. * Transaction API
  144. * */
  145. void Adafruit_SPITFT::startWrite(void){
  146. SPI_BEGIN_TRANSACTION();
  147. SPI_CS_LOW();
  148. }
  149. void Adafruit_SPITFT::endWrite(void){
  150. SPI_CS_HIGH();
  151. SPI_END_TRANSACTION();
  152. }
  153. void Adafruit_SPITFT::writeCommand(uint8_t cmd){
  154. SPI_DC_LOW();
  155. spiWrite(cmd);
  156. SPI_DC_HIGH();
  157. }
  158. void Adafruit_SPITFT::pushColor(uint16_t color) {
  159. startWrite();
  160. SPI_WRITE16(color);
  161. endWrite();
  162. }
  163. void Adafruit_SPITFT::writePixel(uint16_t color){
  164. SPI_WRITE16(color);
  165. }
  166. void Adafruit_SPITFT::writePixels(uint16_t * colors, uint32_t len){
  167. SPI_WRITE_PIXELS((uint8_t*)colors , len * 2);
  168. }
  169. void Adafruit_SPITFT::writeColor(uint16_t color, uint32_t len){
  170. #ifdef SPI_HAS_WRITE_PIXELS
  171. if(_sclk >= 0){
  172. for (uint32_t t=0; t<len; t++){
  173. writePixel(color);
  174. }
  175. return;
  176. }
  177. static uint16_t temp[SPI_MAX_PIXELS_AT_ONCE];
  178. size_t blen = (len > SPI_MAX_PIXELS_AT_ONCE)?SPI_MAX_PIXELS_AT_ONCE:len;
  179. uint16_t tlen = 0;
  180. for (uint32_t t=0; t<blen; t++){
  181. temp[t] = color;
  182. }
  183. while(len){
  184. tlen = (len>blen)?blen:len;
  185. writePixels(temp, tlen);
  186. len -= tlen;
  187. }
  188. #else
  189. uint8_t hi = color >> 8, lo = color;
  190. if(_sclk < 0){ //AVR Optimization
  191. for (uint32_t t=len; t; t--){
  192. HSPI_WRITE(hi);
  193. HSPI_WRITE(lo);
  194. }
  195. return;
  196. }
  197. for (uint32_t t=len; t; t--){
  198. spiWrite(hi);
  199. spiWrite(lo);
  200. }
  201. #endif
  202. }
  203. void Adafruit_SPITFT::writePixel(int16_t x, int16_t y, uint16_t color) {
  204. if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
  205. setAddrWindow(x,y,1,1);
  206. writePixel(color);
  207. }
  208. void Adafruit_SPITFT::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
  209. if((x >= _width) || (y >= _height)) return;
  210. int16_t x2 = x + w - 1, y2 = y + h - 1;
  211. if((x2 < 0) || (y2 < 0)) return;
  212. // Clip left/top
  213. if(x < 0) {
  214. x = 0;
  215. w = x2 + 1;
  216. }
  217. if(y < 0) {
  218. y = 0;
  219. h = y2 + 1;
  220. }
  221. // Clip right/bottom
  222. if(x2 >= _width) w = _width - x;
  223. if(y2 >= _height) h = _height - y;
  224. int32_t len = (int32_t)w * h;
  225. setAddrWindow(x, y, w, h);
  226. writeColor(color, len);
  227. }
  228. void Adafruit_SPITFT::writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color){
  229. writeFillRect(x, y, 1, h, color);
  230. }
  231. void Adafruit_SPITFT::writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color){
  232. writeFillRect(x, y, w, 1, color);
  233. }
  234. void Adafruit_SPITFT::drawPixel(int16_t x, int16_t y, uint16_t color){
  235. startWrite();
  236. writePixel(x, y, color);
  237. endWrite();
  238. }
  239. void Adafruit_SPITFT::drawFastVLine(int16_t x, int16_t y,
  240. int16_t h, uint16_t color) {
  241. startWrite();
  242. writeFastVLine(x, y, h, color);
  243. endWrite();
  244. }
  245. void Adafruit_SPITFT::drawFastHLine(int16_t x, int16_t y,
  246. int16_t w, uint16_t color) {
  247. startWrite();
  248. writeFastHLine(x, y, w, color);
  249. endWrite();
  250. }
  251. void Adafruit_SPITFT::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
  252. uint16_t color) {
  253. startWrite();
  254. writeFillRect(x,y,w,h,color);
  255. endWrite();
  256. }
  257. // Adapted from https://github.com/PaulStoffregen/ILI9341_t3
  258. // by Marc MERLIN. See examples/pictureEmbed to use this.
  259. // 5/6/2017: function name and arguments have changed for compatibility
  260. // with current GFX library and to avoid naming problems in prior
  261. // implementation. Formerly drawBitmap() with arguments in different order.
  262. void Adafruit_SPITFT::drawRGBBitmap(int16_t x, int16_t y,
  263. uint16_t *pcolors, int16_t w, int16_t h) {
  264. int16_t x2, y2; // Lower-right coord
  265. if(( x >= _width ) || // Off-edge right
  266. ( y >= _height) || // " top
  267. ((x2 = (x+w-1)) < 0 ) || // " left
  268. ((y2 = (y+h-1)) < 0) ) return; // " bottom
  269. int16_t bx1=0, by1=0, // Clipped top-left within bitmap
  270. saveW=w; // Save original bitmap width value
  271. if(x < 0) { // Clip left
  272. w += x;
  273. bx1 = -x;
  274. x = 0;
  275. }
  276. if(y < 0) { // Clip top
  277. h += y;
  278. by1 = -y;
  279. y = 0;
  280. }
  281. if(x2 >= _width ) w = _width - x; // Clip right
  282. if(y2 >= _height) h = _height - y; // Clip bottom
  283. pcolors += by1 * saveW + bx1; // Offset bitmap ptr to clipped top-left
  284. startWrite();
  285. setAddrWindow(x, y, w, h); // Clipped area
  286. while(h--) { // For each (clipped) scanline...
  287. writePixels(pcolors, w); // Push one (clipped) row
  288. pcolors += saveW; // Advance pointer by one full (unclipped) line
  289. }
  290. endWrite();
  291. }