ILI9341 display driver (with SPI DMA) for STM32F4 targets. Fork of https://os.mbed.com/users/beaglescout007/code/Nucleo_Ex06_EMU/file/3dac1f1bc9e0/TFT/. Added support for STM32F407 (Seeed Arch Max).
Dependents: STM32F407VET6_Pong
tft.cpp@0:5c2870105122, 2019-04-11 (annotated)
- Committer:
- hudakz
- Date:
- Thu Apr 11 20:10:38 2019 +0000
- Revision:
- 0:5c2870105122
Added support for STM32F407.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
hudakz | 0:5c2870105122 | 1 | /*===================================================================*/ |
hudakz | 0:5c2870105122 | 2 | /* */ |
hudakz | 0:5c2870105122 | 3 | /* tft.cpp : TFT(ILI9341) function */ |
hudakz | 0:5c2870105122 | 4 | /* */ |
hudakz | 0:5c2870105122 | 5 | /* 2016/1/20 Racoon */ |
hudakz | 0:5c2870105122 | 6 | /* */ |
hudakz | 0:5c2870105122 | 7 | /*===================================================================*/ |
hudakz | 0:5c2870105122 | 8 | #include "mbed.h" |
hudakz | 0:5c2870105122 | 9 | #include "tft.h" |
hudakz | 0:5c2870105122 | 10 | |
hudakz | 0:5c2870105122 | 11 | DigitalOut cs(PB_7, PullUp); // TFT chipselect pin |
hudakz | 0:5c2870105122 | 12 | DigitalOut dc(PB_6, PullUp); // TFT data command select pin |
hudakz | 0:5c2870105122 | 13 | DigitalOut rst(PB_8, PullUp); // TFT reset pin |
hudakz | 0:5c2870105122 | 14 | |
hudakz | 0:5c2870105122 | 15 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 16 | /* Write command */ |
hudakz | 0:5c2870105122 | 17 | |
hudakz | 0:5c2870105122 | 18 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 19 | void write_cmd(uint8_t cmd) |
hudakz | 0:5c2870105122 | 20 | { |
hudakz | 0:5c2870105122 | 21 | dc = 0; |
hudakz | 0:5c2870105122 | 22 | spi_write(cmd); |
hudakz | 0:5c2870105122 | 23 | } |
hudakz | 0:5c2870105122 | 24 | |
hudakz | 0:5c2870105122 | 25 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 26 | /* Write data */ |
hudakz | 0:5c2870105122 | 27 | |
hudakz | 0:5c2870105122 | 28 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 29 | void write_data(uint8_t data) |
hudakz | 0:5c2870105122 | 30 | { |
hudakz | 0:5c2870105122 | 31 | dc = 1; |
hudakz | 0:5c2870105122 | 32 | spi_write(data); |
hudakz | 0:5c2870105122 | 33 | } |
hudakz | 0:5c2870105122 | 34 | |
hudakz | 0:5c2870105122 | 35 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 36 | /* TFT reset */ |
hudakz | 0:5c2870105122 | 37 | |
hudakz | 0:5c2870105122 | 38 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 39 | void tft_reset() |
hudakz | 0:5c2870105122 | 40 | { |
hudakz | 0:5c2870105122 | 41 | wait_ms(200); |
hudakz | 0:5c2870105122 | 42 | cs = 1; |
hudakz | 0:5c2870105122 | 43 | dc = 1; |
hudakz | 0:5c2870105122 | 44 | rst = 1; |
hudakz | 0:5c2870105122 | 45 | wait_ms(200); |
hudakz | 0:5c2870105122 | 46 | rst = 0; |
hudakz | 0:5c2870105122 | 47 | wait_us(10); |
hudakz | 0:5c2870105122 | 48 | rst = 1; |
hudakz | 0:5c2870105122 | 49 | wait_ms(120); |
hudakz | 0:5c2870105122 | 50 | cs = 0; |
hudakz | 0:5c2870105122 | 51 | wait_ms(10); |
hudakz | 0:5c2870105122 | 52 | |
hudakz | 0:5c2870105122 | 53 | write_cmd(0x3A); // Pixel Format |
hudakz | 0:5c2870105122 | 54 | write_data(0x55); // 16bit Color |
hudakz | 0:5c2870105122 | 55 | write_cmd(0xB1); // Frame Control |
hudakz | 0:5c2870105122 | 56 | write_data(0); |
hudakz | 0:5c2870105122 | 57 | write_data(0x1f); |
hudakz | 0:5c2870105122 | 58 | |
hudakz | 0:5c2870105122 | 59 | write_cmd(0x36); // Memory Access Control |
hudakz | 0:5c2870105122 | 60 | write_data(0xE8); // MY MX MV BGR |
hudakz | 0:5c2870105122 | 61 | write_cmd(0x11); // Sleep Out |
hudakz | 0:5c2870105122 | 62 | wait_ms(5); |
hudakz | 0:5c2870105122 | 63 | |
hudakz | 0:5c2870105122 | 64 | write_cmd(0x29); // Display On |
hudakz | 0:5c2870105122 | 65 | } |
hudakz | 0:5c2870105122 | 66 | |
hudakz | 0:5c2870105122 | 67 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 68 | /* Set windows size, start memory write */ |
hudakz | 0:5c2870105122 | 69 | |
hudakz | 0:5c2870105122 | 70 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 71 | void tft_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) |
hudakz | 0:5c2870105122 | 72 | { |
hudakz | 0:5c2870105122 | 73 | write_cmd(0x2A); // Column Address Set |
hudakz | 0:5c2870105122 | 74 | write_data(x0 >> 8); |
hudakz | 0:5c2870105122 | 75 | write_data(x0); |
hudakz | 0:5c2870105122 | 76 | write_data(x1 >> 8); |
hudakz | 0:5c2870105122 | 77 | write_data(x1); |
hudakz | 0:5c2870105122 | 78 | |
hudakz | 0:5c2870105122 | 79 | write_cmd(0x2B); // Page Address Set |
hudakz | 0:5c2870105122 | 80 | write_data(y0 >> 8); |
hudakz | 0:5c2870105122 | 81 | write_data(y0); |
hudakz | 0:5c2870105122 | 82 | write_data(y1 >> 8); |
hudakz | 0:5c2870105122 | 83 | write_data(y1); |
hudakz | 0:5c2870105122 | 84 | |
hudakz | 0:5c2870105122 | 85 | write_cmd(0x2C); // Memory Write |
hudakz | 0:5c2870105122 | 86 | wait_us(20); |
hudakz | 0:5c2870105122 | 87 | |
hudakz | 0:5c2870105122 | 88 | dc = 1; |
hudakz | 0:5c2870105122 | 89 | } |
hudakz | 0:5c2870105122 | 90 | |
hudakz | 0:5c2870105122 | 91 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 92 | /* Clear screen */ |
hudakz | 0:5c2870105122 | 93 | |
hudakz | 0:5c2870105122 | 94 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 95 | void tft_clear(uint16_t color) |
hudakz | 0:5c2870105122 | 96 | { |
hudakz | 0:5c2870105122 | 97 | uint16_t pixel[320]; |
hudakz | 0:5c2870105122 | 98 | |
hudakz | 0:5c2870105122 | 99 | tft_set_window(0, 0, TFT_WIDTH, TFT_HEIGHT); |
hudakz | 0:5c2870105122 | 100 | |
hudakz | 0:5c2870105122 | 101 | //for (int i = 0; i < TFT_WIDTH * TFT_HEIGHT; ++i) { |
hudakz | 0:5c2870105122 | 102 | //pixel[i++] = color; |
hudakz | 0:5c2870105122 | 103 | //} |
hudakz | 0:5c2870105122 | 104 | |
hudakz | 0:5c2870105122 | 105 | |
hudakz | 0:5c2870105122 | 106 | for (int i = 0; i < TFT_HEIGHT; i++) { |
hudakz | 0:5c2870105122 | 107 | for (int j = 0; j < TFT_WIDTH; j++) { |
hudakz | 0:5c2870105122 | 108 | pixel[j] = color; |
hudakz | 0:5c2870105122 | 109 | } |
hudakz | 0:5c2870105122 | 110 | HAL_SPI_Transmit(&SpiHandle, (uint8_t*)pixel, TFT_WIDTH * 2, 100); |
hudakz | 0:5c2870105122 | 111 | } |
hudakz | 0:5c2870105122 | 112 | |
hudakz | 0:5c2870105122 | 113 | } |
hudakz | 0:5c2870105122 | 114 | |
hudakz | 0:5c2870105122 | 115 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 116 | /* Put char */ |
hudakz | 0:5c2870105122 | 117 | |
hudakz | 0:5c2870105122 | 118 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 119 | void tft_put_char(int x, int y, char chr, uint16_t color, uint16_t bgcolor) |
hudakz | 0:5c2870105122 | 120 | { |
hudakz | 0:5c2870105122 | 121 | if (chr < 0x20 || chr > 0x7f) { |
hudakz | 0:5c2870105122 | 122 | chr = 0x3f; |
hudakz | 0:5c2870105122 | 123 | } |
hudakz | 0:5c2870105122 | 124 | else { |
hudakz | 0:5c2870105122 | 125 | chr = (chr < 0x60) ? chr - 0x20 : chr - 0x40; |
hudakz | 0:5c2870105122 | 126 | } |
hudakz | 0:5c2870105122 | 127 | |
hudakz | 0:5c2870105122 | 128 | tft_set_window(x, y, x + 7, y + 6); |
hudakz | 0:5c2870105122 | 129 | |
hudakz | 0:5c2870105122 | 130 | for (int dy = 0; dy < 7; ++dy) { |
hudakz | 0:5c2870105122 | 131 | unsigned char img = chrimg[chr][dy]; |
hudakz | 0:5c2870105122 | 132 | for (int dx = 0; dx < 8; ++dx) { |
hudakz | 0:5c2870105122 | 133 | if (img & 0x80) { |
hudakz | 0:5c2870105122 | 134 | spi_writew(color); |
hudakz | 0:5c2870105122 | 135 | } |
hudakz | 0:5c2870105122 | 136 | else { |
hudakz | 0:5c2870105122 | 137 | spi_writew(bgcolor); |
hudakz | 0:5c2870105122 | 138 | } |
hudakz | 0:5c2870105122 | 139 | |
hudakz | 0:5c2870105122 | 140 | img <<= 1; |
hudakz | 0:5c2870105122 | 141 | } |
hudakz | 0:5c2870105122 | 142 | } |
hudakz | 0:5c2870105122 | 143 | } |
hudakz | 0:5c2870105122 | 144 | |
hudakz | 0:5c2870105122 | 145 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 146 | /* Text out */ |
hudakz | 0:5c2870105122 | 147 | |
hudakz | 0:5c2870105122 | 148 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 149 | void tft_text(int x, int y, char* text, uint16_t color, uint16_t bgcolor) |
hudakz | 0:5c2870105122 | 150 | { |
hudakz | 0:5c2870105122 | 151 | while (*text != 0) { |
hudakz | 0:5c2870105122 | 152 | tft_put_char(x, y, *text, color, bgcolor); |
hudakz | 0:5c2870105122 | 153 | x += 8; |
hudakz | 0:5c2870105122 | 154 | text++; |
hudakz | 0:5c2870105122 | 155 | } |
hudakz | 0:5c2870105122 | 156 | } |
hudakz | 0:5c2870105122 | 157 | |
hudakz | 0:5c2870105122 | 158 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 159 | /* Horizontal Line */ |
hudakz | 0:5c2870105122 | 160 | |
hudakz | 0:5c2870105122 | 161 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 162 | void tft_hline(int x1, int y, int x2, uint16_t color) |
hudakz | 0:5c2870105122 | 163 | { |
hudakz | 0:5c2870105122 | 164 | uint16_t pixel[320]; |
hudakz | 0:5c2870105122 | 165 | int i = 0; |
hudakz | 0:5c2870105122 | 166 | |
hudakz | 0:5c2870105122 | 167 | tft_set_window(x1, y, x2, y); |
hudakz | 0:5c2870105122 | 168 | |
hudakz | 0:5c2870105122 | 169 | for (; x1 < x2; ++x1) { |
hudakz | 0:5c2870105122 | 170 | //spi_writew(color); |
hudakz | 0:5c2870105122 | 171 | pixel[i++] = color; |
hudakz | 0:5c2870105122 | 172 | } |
hudakz | 0:5c2870105122 | 173 | HAL_SPI_Transmit(&SpiHandle, (uint8_t*)pixel, (i - 1) * 2, 100); |
hudakz | 0:5c2870105122 | 174 | } |
hudakz | 0:5c2870105122 | 175 | |
hudakz | 0:5c2870105122 | 176 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 177 | /* Vertical Line */ |
hudakz | 0:5c2870105122 | 178 | |
hudakz | 0:5c2870105122 | 179 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 180 | void tft_vline(int x, int y1, int y2, uint16_t color) |
hudakz | 0:5c2870105122 | 181 | { |
hudakz | 0:5c2870105122 | 182 | uint16_t pixel[240]; |
hudakz | 0:5c2870105122 | 183 | int i = 0; |
hudakz | 0:5c2870105122 | 184 | |
hudakz | 0:5c2870105122 | 185 | tft_set_window(x, y1, x, y2); |
hudakz | 0:5c2870105122 | 186 | |
hudakz | 0:5c2870105122 | 187 | for (; y1 < y2; ++y1) { |
hudakz | 0:5c2870105122 | 188 | //spi_writew(color); |
hudakz | 0:5c2870105122 | 189 | pixel[i++] = color; |
hudakz | 0:5c2870105122 | 190 | } |
hudakz | 0:5c2870105122 | 191 | HAL_SPI_Transmit(&SpiHandle, (uint8_t*)pixel, (i - 1) * 2, 100); |
hudakz | 0:5c2870105122 | 192 | } |
hudakz | 0:5c2870105122 | 193 | |
hudakz | 0:5c2870105122 | 194 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 195 | /* Box */ |
hudakz | 0:5c2870105122 | 196 | |
hudakz | 0:5c2870105122 | 197 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 198 | void tft_box(int x1, int y1, int x2, int y2, uint16_t color) |
hudakz | 0:5c2870105122 | 199 | { |
hudakz | 0:5c2870105122 | 200 | tft_hline(x1, y1, x2, color); |
hudakz | 0:5c2870105122 | 201 | tft_vline(x1, y1, y2, color); |
hudakz | 0:5c2870105122 | 202 | tft_vline(x2, y1, y2, color); |
hudakz | 0:5c2870105122 | 203 | tft_hline(x1, y2, x2, color); |
hudakz | 0:5c2870105122 | 204 | } |
hudakz | 0:5c2870105122 | 205 | |
hudakz | 0:5c2870105122 | 206 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 207 | /* Box Fill */ |
hudakz | 0:5c2870105122 | 208 | |
hudakz | 0:5c2870105122 | 209 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 210 | void tft_boxfill(int x1, int y1, int x2, int y2, uint16_t color) |
hudakz | 0:5c2870105122 | 211 | { |
hudakz | 0:5c2870105122 | 212 | uint16_t pixel[320]; |
hudakz | 0:5c2870105122 | 213 | int i; |
hudakz | 0:5c2870105122 | 214 | int j; |
hudakz | 0:5c2870105122 | 215 | |
hudakz | 0:5c2870105122 | 216 | tft_set_window(x1, y1, x2, y2); |
hudakz | 0:5c2870105122 | 217 | |
hudakz | 0:5c2870105122 | 218 | //for (int i = 0; i < (x2 - x1 + 1) * (y2 - y1 + 1); ++i) { |
hudakz | 0:5c2870105122 | 219 | //spi_writew(color); |
hudakz | 0:5c2870105122 | 220 | //} |
hudakz | 0:5c2870105122 | 221 | |
hudakz | 0:5c2870105122 | 222 | for (i = 0; i < (y2 - y1 + 1); i++) { |
hudakz | 0:5c2870105122 | 223 | for (j = 0; j < (x2 - x1 + 1); j++) { |
hudakz | 0:5c2870105122 | 224 | pixel[j] = color; |
hudakz | 0:5c2870105122 | 225 | } |
hudakz | 0:5c2870105122 | 226 | HAL_SPI_Transmit(&SpiHandle, (uint8_t*)pixel, (j - 1) * 2, 100); |
hudakz | 0:5c2870105122 | 227 | } |
hudakz | 0:5c2870105122 | 228 | } |
hudakz | 0:5c2870105122 | 229 | |
hudakz | 0:5c2870105122 | 230 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 231 | /* Draw 4bit BMP */ |
hudakz | 0:5c2870105122 | 232 | |
hudakz | 0:5c2870105122 | 233 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 234 | bool draw_bmp_4bpp(const unsigned char* imgdata, int x, int y) |
hudakz | 0:5c2870105122 | 235 | { |
hudakz | 0:5c2870105122 | 236 | BITMAPFILEHEADER* bf = (BITMAPFILEHEADER*)imgdata; |
hudakz | 0:5c2870105122 | 237 | BITMAPINFOHEADER* bi = (BITMAPINFOHEADER *) (imgdata + sizeof(BITMAPFILEHEADER)); |
hudakz | 0:5c2870105122 | 238 | |
hudakz | 0:5c2870105122 | 239 | if (bi->biBitCount != 4) { |
hudakz | 0:5c2870105122 | 240 | return false; |
hudakz | 0:5c2870105122 | 241 | } |
hudakz | 0:5c2870105122 | 242 | |
hudakz | 0:5c2870105122 | 243 | unsigned char* pRGBPal = (unsigned char*)imgdata + sizeof(BITMAPFILEHEADER) + bi->biSize; |
hudakz | 0:5c2870105122 | 244 | unsigned short palette[16]; |
hudakz | 0:5c2870105122 | 245 | |
hudakz | 0:5c2870105122 | 246 | for (int i = 0; pRGBPal < imgdata + bf->bfOffBits && i < 16; ++i) { |
hudakz | 0:5c2870105122 | 247 | unsigned short r, g, b; |
hudakz | 0:5c2870105122 | 248 | b = *pRGBPal++ >> 3; |
hudakz | 0:5c2870105122 | 249 | g = *pRGBPal++ >> 2; |
hudakz | 0:5c2870105122 | 250 | r = *pRGBPal++ >> 3; |
hudakz | 0:5c2870105122 | 251 | pRGBPal++; |
hudakz | 0:5c2870105122 | 252 | palette[i] = ((g & 7) << 13) | (b << 8) | (r << 3) | (g >> 3); |
hudakz | 0:5c2870105122 | 253 | } |
hudakz | 0:5c2870105122 | 254 | |
hudakz | 0:5c2870105122 | 255 | unsigned short HLine[320]; |
hudakz | 0:5c2870105122 | 256 | int linesize = (bi->biWidth / 2 + 3) & 0xfffc; |
hudakz | 0:5c2870105122 | 257 | |
hudakz | 0:5c2870105122 | 258 | tft_set_window(x, y, x + bi->biWidth - 1, y + bi->biHeight - 1); |
hudakz | 0:5c2870105122 | 259 | |
hudakz | 0:5c2870105122 | 260 | unsigned char* bmp; |
hudakz | 0:5c2870105122 | 261 | |
hudakz | 0:5c2870105122 | 262 | for (int y = bi->biHeight - 1; y >= 0; --y) { |
hudakz | 0:5c2870105122 | 263 | bmp = (unsigned char*)imgdata + bf->bfOffBits + y * linesize; |
hudakz | 0:5c2870105122 | 264 | |
hudakz | 0:5c2870105122 | 265 | for (int x = 0; x < bi->biWidth; ++x) { |
hudakz | 0:5c2870105122 | 266 | char pal; |
hudakz | 0:5c2870105122 | 267 | if (x & 1) { |
hudakz | 0:5c2870105122 | 268 | pal = *bmp & 0xf; |
hudakz | 0:5c2870105122 | 269 | bmp++; |
hudakz | 0:5c2870105122 | 270 | } |
hudakz | 0:5c2870105122 | 271 | else { |
hudakz | 0:5c2870105122 | 272 | pal = *bmp >> 4; |
hudakz | 0:5c2870105122 | 273 | } |
hudakz | 0:5c2870105122 | 274 | |
hudakz | 0:5c2870105122 | 275 | HLine[x] = palette[pal]; |
hudakz | 0:5c2870105122 | 276 | } |
hudakz | 0:5c2870105122 | 277 | |
hudakz | 0:5c2870105122 | 278 | HAL_SPI_Transmit(&SpiHandle, (uint8_t*)HLine, bi->biWidth * 2, 100); |
hudakz | 0:5c2870105122 | 279 | } |
hudakz | 0:5c2870105122 | 280 | |
hudakz | 0:5c2870105122 | 281 | return true; |
hudakz | 0:5c2870105122 | 282 | } |
hudakz | 0:5c2870105122 | 283 | |
hudakz | 0:5c2870105122 | 284 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 285 | /* Initialize TFT */ |
hudakz | 0:5c2870105122 | 286 | |
hudakz | 0:5c2870105122 | 287 | /*-------------------------------------------------------------------*/ |
hudakz | 0:5c2870105122 | 288 | void tft_init(void) |
hudakz | 0:5c2870105122 | 289 | { |
hudakz | 0:5c2870105122 | 290 | spi_init(); |
hudakz | 0:5c2870105122 | 291 | |
hudakz | 0:5c2870105122 | 292 | tft_reset(); |
hudakz | 0:5c2870105122 | 293 | } |