ST7735.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. #include <ST7735.h>
  2. int16_t _width; ///< Display width as modified by current rotation
  3. int16_t _height; ///< Display height as modified by current rotation
  4. int16_t cursor_x; ///< x location to start print()ing text
  5. int16_t cursor_y; ///< y location to start print()ing text
  6. uint8_t rotation; ///< Display rotation (0 thru 3)
  7. uint8_t _colstart; ///< Some displays need this changed to offset
  8. uint8_t _rowstart; ///< Some displays need this changed to offset
  9. uint8_t _xstart;
  10. uint8_t _ystart;
  11. const uint8_t
  12. init_cmds1[] = { // Init for 7735R, part 1 (red or green tab)
  13. 15, // 15 commands in list:
  14. ST7735_SWRESET, DELAY, // 1: Software reset, 0 args, w/delay
  15. 150, // 150 ms delay
  16. ST7735_SLPOUT , DELAY, // 2: Out of sleep mode, 0 args, w/delay
  17. 255, // 500 ms delay
  18. ST7735_FRMCTR1, 3 , // 3: Frame rate ctrl - normal mode, 3 args:
  19. 0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D)
  20. ST7735_FRMCTR2, 3 , // 4: Frame rate control - idle mode, 3 args:
  21. 0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D)
  22. ST7735_FRMCTR3, 6 , // 5: Frame rate ctrl - partial mode, 6 args:
  23. 0x01, 0x2C, 0x2D, // Dot inversion mode
  24. 0x01, 0x2C, 0x2D, // Line inversion mode
  25. ST7735_INVCTR , 1 , // 6: Display inversion ctrl, 1 arg, no delay:
  26. 0x07, // No inversion
  27. ST7735_PWCTR1 , 3 , // 7: Power control, 3 args, no delay:
  28. 0xA2,
  29. 0x02, // -4.6V
  30. 0x84, // AUTO mode
  31. ST7735_PWCTR2 , 1 , // 8: Power control, 1 arg, no delay:
  32. 0xC5, // VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
  33. ST7735_PWCTR3 , 2 , // 9: Power control, 2 args, no delay:
  34. 0x0A, // Opamp current small
  35. 0x00, // Boost frequency
  36. ST7735_PWCTR4 , 2 , // 10: Power control, 2 args, no delay:
  37. 0x8A, // BCLK/2, Opamp current small & Medium low
  38. 0x2A,
  39. ST7735_PWCTR5 , 2 , // 11: Power control, 2 args, no delay:
  40. 0x8A, 0xEE,
  41. ST7735_VMCTR1 , 1 , // 12: Power control, 1 arg, no delay:
  42. 0x0E,
  43. ST7735_INVOFF , 0 , // 13: Don't invert display, no args, no delay
  44. ST7735_COLMOD , 1 , // 15: set color mode, 1 arg, no delay:
  45. 0x05 }, // 16-bit color
  46. #if (defined(ST7735_IS_128X128) || defined(ST7735_IS_160X128))
  47. init_cmds2[] = { // Init for 7735R, part 2 (1.44" display)
  48. 2, // 2 commands in list:
  49. ST7735_CASET , 4 , // 1: Column addr set, 4 args, no delay:
  50. 0x00, 0x00, // XSTART = 0
  51. 0x00, 0x7F, // XEND = 127
  52. ST7735_RASET , 4 , // 2: Row addr set, 4 args, no delay:
  53. 0x00, 0x00, // XSTART = 0
  54. 0x00, 0x7F }, // XEND = 127
  55. #endif // ST7735_IS_128X128
  56. #ifdef ST7735_IS_160X80
  57. init_cmds2[] = { // Init for 7735S, part 2 (160x80 display)
  58. 3, // 3 commands in list:
  59. ST7735_CASET , 4 , // 1: Column addr set, 4 args, no delay:
  60. 0x00, 0x00, // XSTART = 0
  61. 0x00, 0x4F, // XEND = 79
  62. ST7735_RASET , 4 , // 2: Row addr set, 4 args, no delay:
  63. 0x00, 0x00, // XSTART = 0
  64. 0x00, 0x9F , // XEND = 159
  65. ST7735_INVON, 0 }, // 3: Invert colors
  66. #endif
  67. init_cmds3[] = { // Init for 7735R, part 3 (red or green tab)
  68. 4, // 4 commands in list:
  69. ST7735_GMCTRP1, 16 , // 1: Magical unicorn dust, 16 args, no delay:
  70. 0x02, 0x1c, 0x07, 0x12,
  71. 0x37, 0x32, 0x29, 0x2d,
  72. 0x29, 0x25, 0x2B, 0x39,
  73. 0x00, 0x01, 0x03, 0x10,
  74. ST7735_GMCTRN1, 16 , // 2: Sparkles and rainbows, 16 args, no delay:
  75. 0x03, 0x1d, 0x07, 0x06,
  76. 0x2E, 0x2C, 0x29, 0x2D,
  77. 0x2E, 0x2E, 0x37, 0x3F,
  78. 0x00, 0x00, 0x02, 0x10,
  79. ST7735_NORON , DELAY, // 3: Normal display on, no args, w/delay
  80. 10, // 10 ms delay
  81. ST7735_DISPON , DELAY, // 4: Main screen turn on, no args w/delay
  82. 100 }; // 100 ms delay
  83. void ST7735_Select()
  84. {
  85. HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_RESET);
  86. }
  87. void ST7735_Unselect()
  88. {
  89. HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_SET);
  90. }
  91. void ST7735_Reset()
  92. {
  93. HAL_GPIO_WritePin(RST_PORT, RST_PIN, GPIO_PIN_RESET);
  94. HAL_Delay(5);
  95. HAL_GPIO_WritePin(RST_PORT, RST_PIN, GPIO_PIN_SET);
  96. }
  97. void ST7735_WriteCommand(uint8_t cmd)
  98. {
  99. HAL_GPIO_WritePin(DC_PORT, DC_PIN, GPIO_PIN_RESET);
  100. HAL_SPI_Transmit(&ST7735_SPI_PORT, &cmd, sizeof(cmd), HAL_MAX_DELAY);
  101. }
  102. void ST7735_WriteData(uint8_t* buff, size_t buff_size)
  103. {
  104. HAL_GPIO_WritePin(DC_PORT, DC_PIN, GPIO_PIN_SET);
  105. HAL_SPI_Transmit(&ST7735_SPI_PORT, buff, buff_size, HAL_MAX_DELAY);
  106. }
  107. void DisplayInit(const uint8_t *addr)
  108. {
  109. uint8_t numCommands, numArgs;
  110. uint16_t ms;
  111. numCommands = *addr++;
  112. while(numCommands--) {
  113. uint8_t cmd = *addr++;
  114. ST7735_WriteCommand(cmd);
  115. numArgs = *addr++;
  116. // If high bit set, delay follows args
  117. ms = numArgs & DELAY;
  118. numArgs &= ~DELAY;
  119. if(numArgs) {
  120. ST7735_WriteData((uint8_t*)addr, numArgs);
  121. addr += numArgs;
  122. }
  123. if(ms) {
  124. ms = *addr++;
  125. if(ms == 255) ms = 500;
  126. HAL_Delay(ms);
  127. }
  128. }
  129. }
  130. void ST7735_SetAddressWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
  131. {
  132. // column address set
  133. ST7735_WriteCommand(ST7735_CASET);
  134. uint8_t data[] = { 0x00, x0 + _xstart, 0x00, x1 + _xstart };
  135. ST7735_WriteData(data, sizeof(data));
  136. // row address set
  137. ST7735_WriteCommand(ST7735_RASET);
  138. data[1] = y0 + _ystart;
  139. data[3] = y1 + _ystart;
  140. ST7735_WriteData(data, sizeof(data));
  141. // write to RAM
  142. ST7735_WriteCommand(ST7735_RAMWR);
  143. }
  144. void ST7735_Init(uint8_t rotation)
  145. {
  146. ST7735_Select();
  147. ST7735_Reset();
  148. DisplayInit(init_cmds1);
  149. DisplayInit(init_cmds2);
  150. DisplayInit(init_cmds3);
  151. #if ST7735_IS_160X80
  152. _colstart = 24;
  153. _rowstart = 0;
  154. /***** IF Doesn't work, remove the code below (before #elif) *****/
  155. uint8_t data = 0xC0;
  156. ST7735_Select();
  157. ST7735_WriteCommand(ST7735_MADCTL);
  158. ST7735_WriteData(&data,1);
  159. ST7735_Unselect();
  160. #elif ST7735_IS_128X128
  161. _colstart = 2;
  162. _rowstart = 3;
  163. #else
  164. _colstart = 0;
  165. _rowstart = 0;
  166. #endif
  167. ST7735_SetRotation (rotation);
  168. ST7735_Unselect();
  169. }
  170. void ST7735_SetRotation(uint8_t m)
  171. {
  172. uint8_t madctl = 0;
  173. rotation = m % 4; // can't be higher than 3
  174. switch (rotation)
  175. {
  176. case 0:
  177. #if ST7735_IS_160X80
  178. madctl = ST7735_MADCTL_MX | ST7735_MADCTL_MY | ST7735_MADCTL_BGR;
  179. #else
  180. madctl = ST7735_MADCTL_MX | ST7735_MADCTL_MY | ST7735_MADCTL_RGB;
  181. _height = ST7735_HEIGHT;
  182. _width = ST7735_WIDTH;
  183. _xstart = _colstart;
  184. _ystart = _rowstart;
  185. #endif
  186. break;
  187. case 1:
  188. #if ST7735_IS_160X80
  189. madctl = ST7735_MADCTL_MY | ST7735_MADCTL_MV | ST7735_MADCTL_BGR;
  190. #else
  191. madctl = ST7735_MADCTL_MY | ST7735_MADCTL_MV | ST7735_MADCTL_RGB;
  192. _width = ST7735_HEIGHT;
  193. _height = ST7735_WIDTH;
  194. _ystart = _colstart;
  195. _xstart = _rowstart;
  196. #endif
  197. break;
  198. case 2:
  199. #if ST7735_IS_160X80
  200. madctl = ST7735_MADCTL_BGR;
  201. #else
  202. madctl = ST7735_MADCTL_RGB;
  203. _height = ST7735_HEIGHT;
  204. _width = ST7735_WIDTH;
  205. _xstart = _colstart;
  206. _ystart = _rowstart;
  207. #endif
  208. break;
  209. case 3:
  210. #if ST7735_IS_160X80
  211. madctl = ST7735_MADCTL_MX | ST7735_MADCTL_MV | ST7735_MADCTL_BGR;
  212. #else
  213. madctl = ST7735_MADCTL_MX | ST7735_MADCTL_MV | ST7735_MADCTL_RGB;
  214. _width = ST7735_HEIGHT;
  215. _height = ST7735_WIDTH;
  216. _ystart = _colstart;
  217. _xstart = _rowstart;
  218. #endif
  219. break;
  220. }
  221. ST7735_Select();
  222. ST7735_WriteCommand(ST7735_MADCTL);
  223. ST7735_WriteData(&madctl,1);
  224. ST7735_Unselect();
  225. }
  226. void ST7735_DrawPixel(uint16_t x, uint16_t y, uint16_t color) {
  227. if((x >= _width) || (y >= _height))
  228. return;
  229. ST7735_Select();
  230. ST7735_SetAddressWindow(x, y, x+1, y+1);
  231. uint8_t data[] = { color >> 8, color & 0xFF };
  232. ST7735_WriteData(data, sizeof(data));
  233. ST7735_Unselect();
  234. }
  235. void ST7735_WriteChar(uint16_t x, uint16_t y, char ch, FontDef font, uint16_t color, uint16_t bgcolor) {
  236. uint32_t i, b, j;
  237. ST7735_SetAddressWindow(x, y, x+font.width-1, y+font.height-1);
  238. for(i = 0; i < font.height; i++) {
  239. b = font.data[(ch - 32) * font.height + i];
  240. for(j = 0; j < font.width; j++) {
  241. if((b << j) & 0x8000) {
  242. uint8_t data[] = { color >> 8, color & 0xFF };
  243. ST7735_WriteData(data, sizeof(data));
  244. } else {
  245. uint8_t data[] = { bgcolor >> 8, bgcolor & 0xFF };
  246. ST7735_WriteData(data, sizeof(data));
  247. }
  248. }
  249. }
  250. }
  251. void ST7735_WriteString(uint16_t x, uint16_t y, const char* str, FontDef font, uint16_t color, uint16_t bgcolor) {
  252. ST7735_Select();
  253. while(*str) {
  254. if(x + font.width >= _width) {
  255. x = 0;
  256. y += font.height;
  257. if(y + font.height >= _height) {
  258. break;
  259. }
  260. if(*str == ' ') {
  261. // skip spaces in the beginning of the new line
  262. str++;
  263. continue;
  264. }
  265. }
  266. ST7735_WriteChar(x, y, *str, font, color, bgcolor);
  267. x += font.width;
  268. str++;
  269. }
  270. ST7735_Unselect();
  271. }
  272. void ST7735_FillRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color)
  273. {
  274. if((x >= _width) || (y >= _height)) return;
  275. if((x + w - 1) >= _width) w = _width - x;
  276. if((y + h - 1) >= _height) h = _height - y;
  277. ST7735_Select();
  278. ST7735_SetAddressWindow(x, y, x+w-1, y+h-1);
  279. uint8_t data[] = { color >> 8, color & 0xFF };
  280. HAL_GPIO_WritePin(DC_PORT, DC_PIN, GPIO_PIN_SET);
  281. for(y = h; y > 0; y--) {
  282. for(x = w; x > 0; x--) {
  283. HAL_SPI_Transmit(&ST7735_SPI_PORT, data, sizeof(data), HAL_MAX_DELAY);
  284. }
  285. }
  286. ST7735_Unselect();
  287. }
  288. void ST7735_DrawImage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t* data) {
  289. if((x >= _width) || (y >= _height)) return;
  290. if((x + w - 1) >= _width) return;
  291. if((y + h - 1) >= _height) return;
  292. ST7735_Select();
  293. ST7735_SetAddressWindow(x, y, x+w-1, y+h-1);
  294. ST7735_WriteData((uint8_t*)data, sizeof(uint16_t)*w*h);
  295. ST7735_Unselect();
  296. }
  297. void ST7735_InvertColors(bool invert) {
  298. ST7735_Select();
  299. ST7735_WriteCommand(invert ? ST7735_INVON : ST7735_INVOFF);
  300. ST7735_Unselect();
  301. }
  302. void ST7735_SendByte(uint8_t data)
  303. {
  304. // HAL_SPI_Transmit(&hspi1, &data, 1, ST7735_SPI_TIMEOUT);
  305. while((SPI1->SR & SPI_SR_TXE) == RESET);
  306. SPI1->DR = data;
  307. }
  308. /*----------------------------------------------------------------------------*/
  309. void ST7735_WaitLastData()
  310. {
  311. while((SPI1->SR & SPI_SR_TXE) == RESET);
  312. while((SPI1->SR & SPI_SR_BSY) != RESET);
  313. }
  314. /*----------------------------------------------------------------------------*/
  315. void ST7735_SendCommand(uint8_t data)
  316. {
  317. HAL_GPIO_WritePin(DC_PORT, DC_PIN, GPIO_PIN_RESET);
  318. ST7735_SendByte(data);
  319. ST7735_WaitLastData();
  320. }
  321. /*----------------------------------------------------------------------------*/
  322. void ST7735_SendData(uint8_t data)
  323. {
  324. HAL_GPIO_WritePin(DC_PORT, DC_PIN, GPIO_PIN_SET);
  325. ST7735_SendByte(data);
  326. ST7735_WaitLastData();
  327. }
  328. /*----------------------------------------------------------------------------*/
  329. void ST7735_SendDataMultiple(uint8_t *data, uint32_t num)
  330. {
  331. HAL_GPIO_WritePin(DC_PORT, DC_PIN, GPIO_PIN_SET);
  332. for (uint32_t i = 0; i < num; i++)
  333. {
  334. ST7735_SendByte(*data);
  335. data++;
  336. }
  337. ST7735_WaitLastData();
  338. }
  339. void ST7735_SetColAddr(uint16_t cStart, uint16_t cStop)
  340. {
  341. uint8_t data[4];
  342. data[0] = (cStart & 0xFF00) >> 8;
  343. data[1] = cStart & 0x00FF;
  344. data[2] = (cStop & 0xFF00) >> 8;
  345. data[3] = cStop & 0x00FF;
  346. ST7735_SendCommand(ST7735_CASET);
  347. ST7735_SendDataMultiple(data, 4);
  348. }
  349. /*----------------------------------------------------------------------------*/
  350. void ST7735_SetRowAddr(uint16_t rStart, uint16_t rStop)
  351. {
  352. uint8_t data[4];
  353. data[0] = (rStart & 0xFF00) >> 8;
  354. data[1] = rStart & 0x00FF;
  355. data[2] = (rStop & 0xFF00) >> 8;
  356. data[3] = rStop & 0x00FF;
  357. ST7735_SendCommand(ST7735_RASET);
  358. ST7735_SendDataMultiple(data, 4);
  359. }
  360. /*----------------------------------------------------------------------------*/
  361. void ST7735_DrawRect(uint16_t cStart, uint16_t rStart, uint16_t cStop, uint16_t rStop, uint16_t color)
  362. {
  363. HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_RESET);
  364. ST7735_SetColAddr(cStart, cStop - 1);
  365. ST7735_SetRowAddr(rStart, rStop - 1);
  366. ST7735_SendCommand(ST7735_RAMWR);
  367. uint32_t size = (cStop - cStart) * (rStop - rStart);
  368. uint8_t colorBytes[2];
  369. colorBytes[0] = (color & 0xFF00) >> 8;
  370. colorBytes[1] = color & 0x00FF;
  371. HAL_GPIO_WritePin(DC_PORT, DC_PIN, GPIO_PIN_SET);
  372. for (uint32_t i = 0; i < size; i++)
  373. {
  374. ST7735_SendByte(colorBytes[0]);
  375. ST7735_SendByte(colorBytes[1]);
  376. }
  377. ST7735_WaitLastData();
  378. HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_SET);
  379. }
  380. void ST7735_SetBackgroundImage(uint16_t cStart, uint16_t rStart, uint16_t cStop, uint16_t rStop, uint16_t *image)
  381. {
  382. HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_RESET);
  383. ST7735_SetColAddr(cStart, cStop - 1);
  384. ST7735_SetRowAddr(rStart, rStop - 1);
  385. ST7735_SendCommand(ST7735_RAMWR);
  386. uint32_t size = (cStop - cStart) * (rStop - rStart);
  387. uint8_t colorBytes[2];
  388. HAL_GPIO_WritePin(DC_PORT, DC_PIN, GPIO_PIN_SET);
  389. for (uint32_t i = 0; i < size; i++)
  390. {
  391. colorBytes[0] = (image[i] & 0xFF00) >> 8;
  392. colorBytes[1] = image[i] & 0x00FF;
  393. ST7735_SendByte(colorBytes[0]);
  394. ST7735_SendByte(colorBytes[1]);
  395. }
  396. ST7735_WaitLastData();
  397. HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_SET);
  398. }