#include #include #include "pico/stdlib.h" #include "hardware/spi.h" #include "hardware/dma.h" #define SPI_PORT spi0 #define PIN_MISO 16 #define PIN_CS 17 #define PIN_SCK 18 #define PIN_MOSI 19 #define TFT_DC 20 // LOW:Command | HIGH:Data #define TFT_RES 21 #define TFT_COMMAND false #define TFT_DATA true #define TFT_WIDTH 240 // LCD縦ピクセル数 #define TFT_HEIGHT 240 // LCD横ピクセル数 #define SSTCMD_SWRESET 0x01 #define SSTCMD_SLPOUT 0x11 #define SSTCMD_NORON 0x13 #define SSTCMD_INVOFF 0x20 #define SSTCMD_INVON 0x21 #define SSTCMD_DISPOFF 0x28 #define SSTCMD_DISPON 0x29 #define SSTCMD_MADCTL 0x36 #define SSTCMD_COLMOD 0x3A #define SSTCMD_INVCTR 0xB4 #define SSTCMD_CASET 0x2A #define SSTCMD_RASET 0x2B #define SSTCMD_RAMWR 0x2C typedef struct { uint8_t start_x; uint8_t start_y; uint8_t end_x; uint8_t end_y; } sst7735_rect; inline int sst7735_rect_len(sst7735_rect *r) { return (r->end_x-r->start_x) * (r->end_y - r->start_y); } static inline void sst7735_send_cmd(uint8_t cmd) { gpio_put(TFT_DC, TFT_COMMAND); spi_write_blocking(SPI_PORT, &cmd, sizeof(uint8_t)); gpio_put(TFT_DC, TFT_DATA); } static inline void sst7735_send_data8(uint8_t *data, size_t len) { gpio_put(TFT_DC, TFT_DATA); spi_write_blocking(SPI_PORT, data, len); // gpio_put(TFT_DC, TFT_DATA); } static inline void sst7735_send_data16(uint16_t *data, size_t len) { gpio_put(TFT_DC, TFT_DATA); spi_set_format (SPI_PORT, 16, SPI_CPOL_1 , SPI_CPHA_1,SPI_MSB_FIRST ); spi_write16_blocking(SPI_PORT, data, len); spi_set_format (SPI_PORT, 8, SPI_CPOL_1 , SPI_CPHA_1,SPI_MSB_FIRST ); // gpio_put(TFT_DC, TFT_DATA); } static inline void sst7735_reset() { gpio_put(TFT_RES, true); sleep_ms(500); // 500ms gpio_put(TFT_RES, false); sleep_ms(100); // RESET pulse 100ms gpio_put(TFT_RES, true); sleep_ms(500); // 500ms sst7735_send_cmd(SSTCMD_SWRESET); // Software Reset sleep_ms(100); // delay 100ms } static inline void sst7735_init(void) { uint8_t cmd_param[4]; sst7735_send_cmd(SSTCMD_DISPOFF); // Display Off sleep_ms(500); sst7735_send_cmd(SSTCMD_SLPOUT); // Sleep Out sleep_ms(500); sst7735_send_cmd(SSTCMD_DISPON); // Display on sleep_ms(100); sst7735_send_cmd(SSTCMD_COLMOD); // Color mode cmd_param[0] = 0x55; // 16bit mode sst7735_send_data8(cmd_param, 1); sleep_ms(100); sst7735_send_cmd(SSTCMD_MADCTL); cmd_param[0] = 0x00; sst7735_send_data8(cmd_param, 1); // RGB 16bit mode sleep_ms(100); // sst7735_send_cmd(SSTCMD_NORON); sst7735_send_cmd(SSTCMD_INVON); } void sst7735_draw_image(uint16_t *image, sst7735_rect *rect) { uint8_t cmd_param[4] = {0,0,0,0}; cmd_param[1] = rect->start_x; cmd_param[3] = rect->end_x; sst7735_send_cmd(SSTCMD_CASET); // Column Address Set sst7735_send_data8(cmd_param, 4); cmd_param[1] = rect->start_y; cmd_param[3] = rect->end_y; sst7735_send_cmd(SSTCMD_RASET); // Row Address Set sst7735_send_data8(cmd_param, 4); sst7735_send_cmd(SSTCMD_RAMWR); // RAM RW mode sleep_us(500); sst7735_send_data16((uint16_t *)image, sst7735_rect_len(rect)); } void sst7735_clear(void) { uint16_t *temp_buf; sst7735_rect r = {start_x:0, end_x:TFT_WIDTH, start_y:0, end_y:TFT_HEIGHT}; temp_buf = (uint16_t *)calloc(TFT_HEIGHT * TFT_WIDTH, sizeof(uint16_t)); sst7735_draw_image(temp_buf, &r); free(temp_buf); } int dma_ch; dma_channel_config dma_conf; // DMA割り込み void dma_irq_handler() { dma_irqn_acknowledge_channel(DMA_IRQ_0, dma_ch); spi_set_format (SPI_PORT, 16, SPI_CPOL_1 , SPI_CPHA_1,SPI_MSB_FIRST ); // CSをGPIOで手動操作しているならここでLOWに落とすこと } void sst7735_draw_dma(uint16_t *image, sst7735_rect *rect) { // SST77xxコマンド発行 uint8_t cmd_param[4] = {0,0,0,0}; cmd_param[1] = rect->start_x; cmd_param[3] = rect->end_x; sst7735_send_cmd(SSTCMD_CASET); // Column Address Set sst7735_send_data8(cmd_param, 4); cmd_param[1] = rect->start_y; cmd_param[3] = rect->end_y; sst7735_send_cmd(SSTCMD_RASET); // Row Address Set sst7735_send_data8(cmd_param, 4); sst7735_send_cmd(SSTCMD_RAMWR); // RAM RW mode sleep_us(500); dma_ch = dma_claim_unused_channel(true); dma_conf = dma_channel_get_default_config(dma_ch); channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_16); channel_config_set_read_increment(&dma_conf, true); channel_config_set_write_increment(&dma_conf, false); uint dreq = spi_get_dreq(SPI_PORT, true); channel_config_set_dreq(&dma_conf, dreq); // DMA割り込み設定 dma_channel_set_irq0_enabled(dma_ch, true); irq_set_exclusive_handler(DMA_IRQ_0, dma_irq_handler); irq_set_enabled(DMA_IRQ_0, true); // SPIを16bit転送に設定 spi_set_format (SPI_PORT, 16, SPI_CPOL_1 , SPI_CPHA_1,SPI_MSB_FIRST ); gpio_put(TFT_DC, TFT_DATA); // DMAスタート dma_channel_configure( dma_ch, &dma_conf, &spi_get_hw(SPI_PORT)->dr, // DATAレジスタ(SSPDR) image, sst7735_rect_len(rect), true ); } // サンプル画像を埋め込む __asm(\ ".section \".rodata\" \n" ".balign 4\n" ".global _sample_picture\n" ".global _picture_size\n" "_sample_picture:\n" ".incbin \"sample_picture.bin\"\n" ".set _picture_size, . - _sample_picture\n" ".section \".text\"\n" ); extern const uint16_t _sample_picture[]; extern uint32_t _picture_size[]; int main() { stdio_init_all(); spi_init(SPI_PORT, 50*1000*1000); // spi_init(SPI_PORT, 300*1000); gpio_set_function(PIN_MISO, GPIO_FUNC_SPI); gpio_set_function(PIN_CS, GPIO_FUNC_SPI); gpio_set_function(PIN_SCK, GPIO_FUNC_SPI); gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI); spi_set_format (SPI_PORT, 8, SPI_CPOL_1 , SPI_CPHA_1,SPI_MSB_FIRST ); // gpio_set_dir(PIN_CS, GPIO_OUT); // gpio_put(PIN_CS, 1); // TFT Pin Init gpio_init(TFT_DC); gpio_set_dir(TFT_DC, GPIO_OUT); gpio_init(TFT_RES); gpio_set_dir(TFT_RES, GPIO_OUT); sst7735_reset(); sst7735_init(); sst7735_clear(); sst7735_rect r = {start_x:0, end_x:240, start_y:0, end_y:240}; // sst7735_draw_image((uint16_t *)_sample_picture, &r); sst7735_draw_dma((uint16_t *)_sample_picture, &r); while (true) { tight_loop_contents(); } }