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