spi_sample.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #include <stdio.h>
  2. #include <malloc.h>
  3. #include "pico/stdlib.h"
  4. #include "hardware/spi.h"
  5. #include "hardware/dma.h"
  6. #define SPI_PORT spi0
  7. #define PIN_MISO 16
  8. #define PIN_CS 17
  9. #define PIN_SCK 18
  10. #define PIN_MOSI 19
  11. #define TFT_DC 20 // LOW:Command | HIGH:Data
  12. #define TFT_RES 21
  13. #define TFT_COMMAND false
  14. #define TFT_DATA true
  15. #define TFT_WIDTH 240 // LCD縦ピクセル数
  16. #define TFT_HEIGHT 240 // LCD横ピクセル数
  17. #define SSTCMD_SWRESET 0x01
  18. #define SSTCMD_SLPOUT 0x11
  19. #define SSTCMD_NORON 0x13
  20. #define SSTCMD_INVOFF 0x20
  21. #define SSTCMD_INVON 0x21
  22. #define SSTCMD_DISPOFF 0x28
  23. #define SSTCMD_DISPON 0x29
  24. #define SSTCMD_MADCTL 0x36
  25. #define SSTCMD_COLMOD 0x3A
  26. #define SSTCMD_INVCTR 0xB4
  27. #define SSTCMD_CASET 0x2A
  28. #define SSTCMD_RASET 0x2B
  29. #define SSTCMD_RAMWR 0x2C
  30. typedef struct {
  31. uint8_t start_x;
  32. uint8_t start_y;
  33. uint8_t end_x;
  34. uint8_t end_y;
  35. } sst7735_rect;
  36. inline int sst7735_rect_len(sst7735_rect *r)
  37. {
  38. return (r->end_x-r->start_x) * (r->end_y - r->start_y);
  39. }
  40. static inline void sst7735_send_cmd(uint8_t cmd)
  41. {
  42. gpio_put(TFT_DC, TFT_COMMAND);
  43. spi_write_blocking(SPI_PORT, &cmd, sizeof(uint8_t));
  44. gpio_put(TFT_DC, TFT_DATA);
  45. }
  46. static inline void sst7735_send_data8(uint8_t *data, size_t len)
  47. {
  48. gpio_put(TFT_DC, TFT_DATA);
  49. spi_write_blocking(SPI_PORT, data, len);
  50. // gpio_put(TFT_DC, TFT_DATA);
  51. }
  52. static inline void sst7735_send_data16(uint16_t *data, size_t len)
  53. {
  54. gpio_put(TFT_DC, TFT_DATA);
  55. spi_set_format (SPI_PORT, 16, SPI_CPOL_1 , SPI_CPHA_1,SPI_MSB_FIRST );
  56. spi_write16_blocking(SPI_PORT, data, len);
  57. spi_set_format (SPI_PORT, 8, SPI_CPOL_1 , SPI_CPHA_1,SPI_MSB_FIRST );
  58. // gpio_put(TFT_DC, TFT_DATA);
  59. }
  60. static inline void sst7735_reset()
  61. {
  62. gpio_put(TFT_RES, true);
  63. sleep_ms(500); // 500ms
  64. gpio_put(TFT_RES, false);
  65. sleep_ms(100); // RESET pulse 100ms
  66. gpio_put(TFT_RES, true);
  67. sleep_ms(500); // 500ms
  68. sst7735_send_cmd(SSTCMD_SWRESET); // Software Reset
  69. sleep_ms(100); // delay 100ms
  70. }
  71. static inline void sst7735_init(void)
  72. {
  73. uint8_t cmd_param[4];
  74. sst7735_send_cmd(SSTCMD_DISPOFF); // Display Off
  75. sleep_ms(500);
  76. sst7735_send_cmd(SSTCMD_SLPOUT); // Sleep Out
  77. sleep_ms(500);
  78. sst7735_send_cmd(SSTCMD_DISPON); // Display on
  79. sleep_ms(100);
  80. sst7735_send_cmd(SSTCMD_COLMOD); // Color mode
  81. cmd_param[0] = 0x55; // 16bit mode
  82. sst7735_send_data8(cmd_param, 1);
  83. sleep_ms(100);
  84. sst7735_send_cmd(SSTCMD_MADCTL);
  85. cmd_param[0] = 0x00;
  86. sst7735_send_data8(cmd_param, 1); // RGB 16bit mode
  87. sleep_ms(100);
  88. // sst7735_send_cmd(SSTCMD_NORON);
  89. sst7735_send_cmd(SSTCMD_INVON);
  90. }
  91. void sst7735_draw_image(uint16_t *image, sst7735_rect *rect)
  92. {
  93. uint8_t cmd_param[4] = {0,0,0,0};
  94. cmd_param[1] = rect->start_x;
  95. cmd_param[3] = rect->end_x;
  96. sst7735_send_cmd(SSTCMD_CASET); // Column Address Set
  97. sst7735_send_data8(cmd_param, 4);
  98. cmd_param[1] = rect->start_y;
  99. cmd_param[3] = rect->end_y;
  100. sst7735_send_cmd(SSTCMD_RASET); // Row Address Set
  101. sst7735_send_data8(cmd_param, 4);
  102. sst7735_send_cmd(SSTCMD_RAMWR); // RAM RW mode
  103. sleep_us(500);
  104. sst7735_send_data16((uint16_t *)image, sst7735_rect_len(rect));
  105. }
  106. void sst7735_clear(void)
  107. {
  108. uint16_t *temp_buf;
  109. sst7735_rect r = {start_x:0, end_x:TFT_WIDTH, start_y:0, end_y:TFT_HEIGHT};
  110. temp_buf = (uint16_t *)calloc(TFT_HEIGHT * TFT_WIDTH, sizeof(uint16_t));
  111. sst7735_draw_image(temp_buf, &r);
  112. free(temp_buf);
  113. }
  114. int dma_ch;
  115. dma_channel_config dma_conf;
  116. // DMA割り込み
  117. void dma_irq_handler()
  118. {
  119. dma_irqn_acknowledge_channel(DMA_IRQ_0, dma_ch);
  120. spi_set_format (SPI_PORT, 16, SPI_CPOL_1 , SPI_CPHA_1,SPI_MSB_FIRST );
  121. // CSをGPIOで手動操作しているならここでLOWに落とすこと
  122. }
  123. void sst7735_draw_dma(uint16_t *image, sst7735_rect *rect)
  124. {
  125. // SST77xxコマンド発行
  126. uint8_t cmd_param[4] = {0,0,0,0};
  127. cmd_param[1] = rect->start_x;
  128. cmd_param[3] = rect->end_x;
  129. sst7735_send_cmd(SSTCMD_CASET); // Column Address Set
  130. sst7735_send_data8(cmd_param, 4);
  131. cmd_param[1] = rect->start_y;
  132. cmd_param[3] = rect->end_y;
  133. sst7735_send_cmd(SSTCMD_RASET); // Row Address Set
  134. sst7735_send_data8(cmd_param, 4);
  135. sst7735_send_cmd(SSTCMD_RAMWR); // RAM RW mode
  136. sleep_us(500);
  137. dma_ch = dma_claim_unused_channel(true);
  138. dma_conf = dma_channel_get_default_config(dma_ch);
  139. channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_16);
  140. channel_config_set_read_increment(&dma_conf, true);
  141. channel_config_set_write_increment(&dma_conf, false);
  142. uint dreq = spi_get_dreq(SPI_PORT, true);
  143. channel_config_set_dreq(&dma_conf, dreq);
  144. // DMA割り込み設定
  145. dma_channel_set_irq0_enabled(dma_ch, true);
  146. irq_set_exclusive_handler(DMA_IRQ_0, dma_irq_handler);
  147. irq_set_enabled(DMA_IRQ_0, true);
  148. // SPIを16bit転送に設定
  149. spi_set_format (SPI_PORT, 16, SPI_CPOL_1 , SPI_CPHA_1,SPI_MSB_FIRST );
  150. gpio_put(TFT_DC, TFT_DATA);
  151. // DMAスタート
  152. dma_channel_configure(
  153. dma_ch,
  154. &dma_conf,
  155. &spi_get_hw(SPI_PORT)->dr, // DATAレジスタ(SSPDR)
  156. image,
  157. sst7735_rect_len(rect),
  158. true
  159. );
  160. }
  161. // サンプル画像を埋め込む
  162. __asm(\
  163. ".section \".rodata\" \n"
  164. ".balign 4\n"
  165. ".global _sample_picture\n"
  166. ".global _picture_size\n"
  167. "_sample_picture:\n"
  168. ".incbin \"sample_picture.bin\"\n"
  169. ".set _picture_size, . - _sample_picture\n"
  170. ".section \".text\"\n"
  171. );
  172. extern const uint16_t _sample_picture[];
  173. extern uint32_t _picture_size[];
  174. int main()
  175. {
  176. stdio_init_all();
  177. spi_init(SPI_PORT, 50*1000*1000);
  178. // spi_init(SPI_PORT, 300*1000);
  179. gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);
  180. gpio_set_function(PIN_CS, GPIO_FUNC_SPI);
  181. gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
  182. gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
  183. spi_set_format (SPI_PORT, 8, SPI_CPOL_1 , SPI_CPHA_1,SPI_MSB_FIRST );
  184. // gpio_set_dir(PIN_CS, GPIO_OUT);
  185. // gpio_put(PIN_CS, 1);
  186. // TFT Pin Init
  187. gpio_init(TFT_DC);
  188. gpio_set_dir(TFT_DC, GPIO_OUT);
  189. gpio_init(TFT_RES);
  190. gpio_set_dir(TFT_RES, GPIO_OUT);
  191. sst7735_reset();
  192. sst7735_init();
  193. sst7735_clear();
  194. sst7735_rect r = {start_x:0, end_x:240, start_y:0, end_y:240};
  195. // sst7735_draw_image((uint16_t *)_sample_picture, &r);
  196. sst7735_draw_dma((uint16_t *)_sample_picture, &r);
  197. while (true) {
  198. tight_loop_contents();
  199. }
  200. }