st7789.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. #include "lcd.h"
  2. #include "log.h"
  3. #define COL_ADDR_SET 0x2A
  4. #define ROW_ADDR_SET 0x2B
  5. #define MEMORY_WRITE 0x2C
  6. /**
  7. * MADCTL(36H):
  8. * +---------------------------------------+
  9. * | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
  10. * | MY | MX | MV | ML | RGB| MH | - | - |
  11. * +---------------------------------------+
  12. * [3] 0=RGB,1=BGR
  13. */
  14. #define DATA_ACCESS 0x36
  15. /**
  16. * COLMOD(3AH):
  17. * +---------------------------------------+
  18. * | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
  19. * | 0 | D6 | D5 | D4 | 0 | D2 | D1 | D0 |
  20. * +---------------------------------------+
  21. * [6:4] RGB interface Color format:
  22. * 101=65K RGB
  23. * 110=262K RGB
  24. * [2:0] Control interface color format:
  25. * 011=12bit/pixel
  26. * 101=16bit/pixel
  27. * 110=18bit/pixel
  28. * 111=16M truncated
  29. */
  30. #define PIXEL_FORMAT 0x3A
  31. static int lcd_hw_init(lcd_handle_t *h)
  32. {
  33. h->dev = rt_device_find("lcd");
  34. if (h->dev < 0) {
  35. LOGE("___ open %s failed\n", DEV_PATH);
  36. return -1;
  37. }
  38. h->buflen = h->width*h->height/8;
  39. h->buf = (uint8_t*)calloc(1, h->buflen);
  40. if (!h->buf) {
  41. LOGE("malloc buffer falied\n");
  42. return -1;
  43. }
  44. return 0;
  45. }
  46. static void write_reg(lcd_handle_t *h, uint8_t reg)
  47. {
  48. LCD_DC_CLR;
  49. rt_spi_send(h->dev, &reg, 1);
  50. }
  51. static void write_data(uint8_t data)
  52. {
  53. LCD_DC_SET;
  54. rt_spi_send(h->dev, &data, 1);
  55. }
  56. static void write_reg_data(lcd_handle_t *h, uint8_t reg, uint16_t data)
  57. {
  58. write_reg(reg);
  59. write_data(data);
  60. }
  61. static void read_data(lcd_handle_t *h, uint8_t *data, int length)
  62. {
  63. LCD_DC_SET;
  64. rt_spi_transfer(lcd_dev, RT_NULL, data, length);
  65. }
  66. static void write_16bit(lcd_handle_t *h, uint16_t data)
  67. {
  68. uint8_t buf[2];
  69. buf[0] = data >> 8;
  70. buf[1] = data & 0xff;
  71. LCD_DC_SET;
  72. rt_spi_send(h->dev, buf, 2);
  73. }
  74. void st7789_rotate(lcd_handle_t *h, int rotate)
  75. {
  76. switch (rotate)
  77. {
  78. case rotate:
  79. lcddev.width = LCD_W;
  80. lcddev.height = LCD_H;
  81. LCD_WriteReg(DATA_ACCESS, (0 << 3) | (0 << 5) | (0 << 6) | (0 << 7)); /* BGR==0,MV==0,MX==0,MY==0 */
  82. break;
  83. case 90:
  84. lcddev.width = LCD_H;
  85. lcddev.height = LCD_W;
  86. LCD_WriteReg(DATA_ACCESS, (0 << 3) | (1 << 5) | (1 << 6) | (0 << 7)); /* BGR==0,MV==1,MX==0,MY==1 */
  87. break;
  88. case 180:
  89. lcddev.width = LCD_W;
  90. lcddev.height = LCD_H;
  91. LCD_WriteReg(DATA_ACCESS, (0 << 3) | (0 << 5) | (1 << 6) | (1 << 7)); /* BGR==0,MV==0,MX==1,MY==1 */
  92. break;
  93. case 270:
  94. lcddev.width = LCD_H;
  95. lcddev.height = LCD_W;
  96. LCD_WriteReg(DATA_ACCESS, (0 << 3) | (1 << 5) | (0 << 6) | (1 << 7)); /* BGR==0,MV==1,MX==0,MY==1 */
  97. break;
  98. default:
  99. break;
  100. }
  101. }
  102. void st7789_set_win(lcd_handle_t *h, int x, int y, int w, int h)
  103. {
  104. write_reg(COL_ADDR_SET);
  105. write_data(x>>8);
  106. write_data(x&0xff);
  107. write_data((x+w-1)>>8);
  108. write_data((x+w-1)&0xff);
  109. write_reg(ROW_ADDR_SET);
  110. write_data(y>>8);
  111. write_data(y&0xff);
  112. write_data((y+h-1)>>8);
  113. write_data((y+h-1)&0xff);
  114. write_reg(MEMORY_WRITE);
  115. }
  116. void st7789_refresh(lcd_handle_t *h, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
  117. {
  118. uint16_t i, j;
  119. LCD_SetWindows(x, y, x + w - 1, y + h - 1);
  120. LCD_DC_SET;
  121. for (i = 0; i < h; i++)
  122. {
  123. rt_spi_send(h->dev, (uint8_t *)h->buf, w * 2);
  124. }
  125. }
  126. static void reg_init(lcd_handle_t *h)
  127. {
  128. write_reg(h, DATA_ACCESS);
  129. write_data(h, 0x00);
  130. LCD_WR_REG(h, PIXEL_FORMAT);
  131. LCD_WR_DATA(h, 0X05); //03=RGB444,05=RGB565,06=RGB666
  132. LCD_WR_REG(h, 0xB2); //Porch Setting
  133. LCD_WR_DATA(h, 0x0C);
  134. LCD_WR_DATA(h, 0x0C);
  135. LCD_WR_DATA(h, 0X00);
  136. LCD_WR_DATA(h, 0X33);
  137. LCD_WR_DATA(h, 0X33);
  138. LCD_WR_REG(h, 0xB7); //Gate Control
  139. LCD_WR_DATA(h, 0x46);
  140. LCD_WR_REG(h, 0xBB); //VCOM Setting
  141. LCD_WR_DATA(h, 0x1B);
  142. LCD_WR_REG(h, 0xC0); //LCM Control
  143. LCD_WR_DATA(h, 0x2C);
  144. LCD_WR_REG(h, 0xC2); //VDV and VRH Command Enable
  145. LCD_WR_DATA(h, 0x01);
  146. LCD_WR_REG(h, 0xC3); //VRH set
  147. LCD_WR_DATA(h, 0x0F);
  148. LCD_WR_REG(h, 0xC4); //VDV set
  149. LCD_WR_DATA(h, 0x20);
  150. LCD_WR_REG(h, 0xC6); //Frame Rate Control
  151. LCD_WR_DATA(h, 0x0F);
  152. LCD_WR_REG(h, 0xD0); //Power Control 1
  153. LCD_WR_DATA(h, 0xA4);
  154. LCD_WR_DATA(h, 0xA1);
  155. LCD_WR_REG(h, 0xD6);
  156. LCD_WR_DATA(0xA1);
  157. LCD_WR_REG(h, 0xE0); /* set Positive Voltage Gamma */
  158. LCD_WR_DATA(h, 0xF0);
  159. LCD_WR_DATA(h, 0x00);
  160. LCD_WR_DATA(h, 0x06);
  161. LCD_WR_DATA(h, 0x04);
  162. LCD_WR_DATA(h, 0x05);
  163. LCD_WR_DATA(h, 0x05);
  164. LCD_WR_DATA(h, 0x31);
  165. LCD_WR_DATA(h, 0x44);
  166. LCD_WR_DATA(h, 0x48);
  167. LCD_WR_DATA(h, 0x36);
  168. LCD_WR_DATA(h, 0x12);
  169. LCD_WR_DATA(h, 0x12);
  170. LCD_WR_DATA(h, 0x2B);
  171. LCD_WR_DATA(h, 0x34);
  172. LCD_WR_REG(h, 0xE1); /* set Negative Voltage Gamma */
  173. LCD_WR_DATA(h, 0XF0);
  174. LCD_WR_DATA(h, 0X0B);
  175. LCD_WR_DATA(h, 0X0F);
  176. LCD_WR_DATA(h, 0X0F);
  177. LCD_WR_DATA(h, 0X0D);
  178. LCD_WR_DATA(h, 0X26);
  179. LCD_WR_DATA(h, 0X31);
  180. LCD_WR_DATA(h, 0X43);
  181. LCD_WR_DATA(h, 0X47);
  182. LCD_WR_DATA(h, 0X38);
  183. LCD_WR_DATA(h, 0X14);
  184. LCD_WR_DATA(h, 0X14);
  185. LCD_WR_DATA(h, 0X2C);
  186. LCD_WR_DATA(h, 0X32);
  187. LCD_WR_REG(h, 0x21); // Dispaly Inversion On
  188. LCD_WR_REG(h, 0x29); // Display On
  189. LCD_WR_REG(MEMORY_WRITE); // Memory Write
  190. }
  191. static void Lcd_pin_init(void)
  192. {
  193. rt_pin_mode(PKG_ST_7789_DC_PIN, PIN_MODE_OUTPUT);
  194. rt_pin_mode(PKG_ST_7789_RES_PIN, PIN_MODE_OUTPUT);
  195. rt_pin_mode(PKG_ST_7789_BLK_PIN, PIN_MODE_OUTPUT);
  196. }
  197. static void LCD_Init(void)
  198. {
  199. Lcd_pin_init();
  200. LCD_RESET(); /* LCD Hardware Reset */
  201. DELAY(120); /* Delay 120ms */
  202. LCD_WR_REG(0x11); /* Sleep out */
  203. DELAY(120); /* Delay 120ms */
  204. _st7789_init(); /* IlI9341 init */
  205. LCD_BLK_CLR; /* Open Backlight */
  206. LCD_direction(USE_DIRECTION);
  207. }
  208. rt_err_t spi_device_attach(const char *bus_name, const char *device_name, rt_base_t cs_pin)
  209. {
  210. RT_ASSERT(bus_name != RT_NULL);
  211. RT_ASSERT(device_name != RT_NULL);
  212. rt_err_t result = RT_EOK;
  213. struct rt_spi_device *spi_device;
  214. /* attach the device to spi bus*/
  215. spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
  216. RT_ASSERT(spi_device != RT_NULL);
  217. result = rt_spi_bus_attach_device_cspin(spi_device, device_name, bus_name, cs_pin, RT_NULL);
  218. if (RT_EOK != result)
  219. {
  220. LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result);
  221. }
  222. else
  223. {
  224. LOG_I("%s attach to %s done", device_name, bus_name);
  225. }
  226. return result;
  227. }
  228. rt_err_t spi_lcd_init(uint32_t freq)
  229. {
  230. rt_err_t res = RT_EOK;
  231. spi_device_attach(PKG_ST_7789_SPI_BUS_NAME, PKG_ST_7789_SPI_DEVICE_NAME, PKG_ST_7789_CS_PIN);
  232. lcd_dev = (struct rt_spi_device *)rt_device_find(PKG_ST_7789_SPI_DEVICE_NAME);
  233. if (lcd_dev != RT_NULL)
  234. {
  235. struct rt_spi_configuration spi_config;
  236. spi_config.data_width = 8;
  237. spi_config.max_hz = freq * 1000 * 1000;
  238. spi_config.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
  239. rt_spi_configure(lcd_dev, &spi_config);
  240. }
  241. else
  242. {
  243. res = -RT_ERROR;
  244. }
  245. LCD_Init();
  246. return res;
  247. }
  248. static void lcd_ops_blit_line(const char *pixel, int x, int y, rt_size_t size)
  249. {
  250. LCD_SetWindows(x, y, x + size, y);
  251. rt_spi_send(lcd_dev, pixel, size * 2);
  252. }
  253. struct rt_device_graphic_ops lcd_graphic_ops =
  254. {
  255. .set_pixel = RT_NULL,//lcd_ops_set_pixel ,
  256. .get_pixel = RT_NULL,//lcd_ops_get_pixel ,
  257. .draw_hline = RT_NULL,//lcd_ops_draw_hline,
  258. .draw_vline = RT_NULL,//lcd_ops_draw_vline,
  259. .blit_line = lcd_ops_blit_line ,
  260. };
  261. static int st7789_dev_init(void)
  262. {
  263. #ifdef RT_USING_DEVICE_OPS
  264. lcddev.parent.ops = &lcd_dev_ops;
  265. #else
  266. lcddev.parent.init = lcd_dev_ops_init ;
  267. lcddev.parent.open = lcd_dev_ops_open ;
  268. lcddev.parent.close = lcd_dev_ops_close ;
  269. lcddev.parent.read = lcd_dev_ops_read ;
  270. lcddev.parent.write = lcd_dev_ops_write ;
  271. lcddev.parent.control = lcd_dev_ops_control;
  272. #endif
  273. lcddev.parent.type = RT_Device_Class_Graphic;
  274. lcddev.parent.user_data = &lcd_graphic_ops;
  275. rt_device_register(&lcddev.parent, "lcd", RT_DEVICE_FLAG_RDWR);
  276. return RT_EOK;
  277. }