See changelog v0.9.8
[hackover2013-badge-firmware.git] / drivers / displays / tft / hw / st7783.c
1 /**************************************************************************/
2 /*!
3 @file st7783.c
4 @author K. Townsend (microBuilder.eu)
5
6 @section DESCRIPTION
7
8 Driver for st7783 240x320 pixel TFT LCD displays.
9
10 This driver uses an 8-bit interface and a 16-bit RGB565 colour palette.
11
12 @section UPDATES
13
14 26-11-2010: st7783ReadData contributed by Adafruit Industries
15
16 @section LICENSE
17
18 Software License Agreement (BSD License)
19
20 Copyright (c) 2010, microBuilder SARL
21 All rights reserved.
22
23 Redistribution and use in source and binary forms, with or without
24 modification, are permitted provided that the following conditions are met:
25 1. Redistributions of source code must retain the above copyright
26 notice, this list of conditions and the following disclaimer.
27 2. Redistributions in binary form must reproduce the above copyright
28 notice, this list of conditions and the following disclaimer in the
29 documentation and/or other materials provided with the distribution.
30 3. Neither the name of the copyright holders nor the
31 names of its contributors may be used to endorse or promote products
32 derived from this software without specific prior written permission.
33
34 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
35 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
38 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
40 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
43 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 */
45 /**************************************************************************/
46 #include "st7783.h"
47 #include "core/systick/systick.h"
48 #include "drivers/displays/tft/touchscreen.h"
49
50 static lcdOrientation_t lcdOrientation = LCD_ORIENTATION_PORTRAIT;
51 static lcdProperties_t st7783Properties = { 240, 320, TRUE, TRUE, FALSE };
52
53 /*************************************************/
54 /* Private Methods */
55 /*************************************************/
56
57 /*************************************************/
58 void st7783Delay(unsigned int t)
59 {
60 unsigned char t1;
61 while(t--)
62 for ( t1=10; t1 > 0; t1-- )
63 {
64 __asm("nop");
65 }
66 }
67
68 /*************************************************/
69 void st7783WriteCmd(uint16_t command)
70 {
71 // Compiled with -Os on GCC 4.4 this works out to 25 cycles
72 // (versus 36 compiled with no optimisations). I'm not sure it
73 // can be improved further, so that means 25 cycles/350nS for
74 // continuous writes (cmd, data, data, data, ...) or ~150 cycles/
75 // ~2.1uS for a random pixel (Set X [cmd+data], Set Y [cmd+data],
76 // Set color [cmd+data]) (times assumes 72MHz clock).
77
78 CLR_CS_CD_SET_RD_WR; // Saves 18 commands compared to "CLR_CS; CLR_CD; SET_RD; SET_WR;"
79 ST7783_GPIO2DATA_DATA = (command >> (8 - ST7783_DATA_OFFSET));
80 CLR_WR;
81 SET_WR;
82 ST7783_GPIO2DATA_DATA = command << ST7783_DATA_OFFSET;
83 CLR_WR;
84 SET_WR_CS; // Saves 7 commands compared to "SET_WR; SET_CS;"
85 }
86
87 /*************************************************/
88 void st7783WriteData(uint16_t data)
89 {
90 CLR_CS_SET_CD_RD_WR; // Saves 18 commands compared to SET_CD; SET_RD; SET_WR; CLR_CS"
91 ST7783_GPIO2DATA_DATA = (data >> (8 - ST7783_DATA_OFFSET));
92 CLR_WR;
93 SET_WR;
94 ST7783_GPIO2DATA_DATA = data << ST7783_DATA_OFFSET;
95 CLR_WR;
96 SET_WR_CS; // Saves 7 commands compared to "SET_WR, SET_CS;"
97 }
98
99 /*************************************************/
100 uint16_t st7783ReadData(void)
101 {
102 // ToDo: Optimise this method!
103
104 uint16_t high, low;
105 high = low = 0;
106 uint16_t d;
107
108 SET_CD_RD_WR; // Saves 14 commands compared to "SET_CD; SET_RD; SET_WR"
109 CLR_CS;
110
111 // set inputs
112 ST7783_GPIO2DATA_SETINPUT;
113 CLR_RD;
114 st7783Delay(100);
115 high = ST7783_GPIO2DATA_DATA;
116 high >>= ST7783_DATA_OFFSET;
117 high &= 0xFF;
118 SET_RD;
119
120 CLR_RD;
121 st7783Delay(100);
122 low = ST7783_GPIO2DATA_DATA;
123 low >>= ST7783_DATA_OFFSET;
124 low &=0xFF;
125 SET_RD;
126
127 SET_CS;
128 ST7783_GPIO2DATA_SETOUTPUT;
129
130 d = high;
131 d <<= 8;
132 d |= low;
133
134 return d;
135 }
136
137 /*************************************************/
138 uint16_t st7783Read(uint16_t addr)
139 {
140 st7783WriteCmd(addr);
141 return st7783ReadData();
142 }
143
144 /*************************************************/
145 void st7783Command(uint16_t command, uint16_t data)
146 {
147 st7783WriteCmd(command);
148 st7783WriteData(data);
149 }
150
151 /*************************************************/
152 /* Returns the 4-hexdigit controller code */
153 /*************************************************/
154 uint16_t st7783Type(void)
155 {
156 st7783WriteCmd(0x0);
157 return st7783ReadData();
158 }
159
160 /*************************************************/
161 void st7783SetCursor(uint16_t x, uint16_t y)
162 {
163 uint16_t he, ve, al, ah;
164
165 switch (lcdOrientation)
166 {
167 case LCD_ORIENTATION_LANDSCAPE:
168 he = st7783Properties.width-1-y;
169 ve = st7783Properties.height-1-x;
170 al = y;
171 ah = x;
172 break;
173 case LCD_ORIENTATION_PORTRAIT:
174 default:
175 he = st7783Properties.width-1;
176 ve = st7783Properties.height-1;
177 al = x;
178 ah = y;
179 break;
180 }
181 st7783Command(0x0051, he);
182 st7783Command(0x0053, ve);
183 st7783Command(0x0020, al);
184 st7783Command(0x0021, ah);
185 }
186
187 /*************************************************/
188 void st7783InitDisplay(void)
189 {
190 // Clear data line
191 GPIO_GPIO2DATA &= ~ST7783_DATA_MASK;
192
193 SET_RD;
194 SET_WR;
195 SET_CS;
196 SET_CD;
197
198 // Reset display
199 CLR_RESET;
200 st7783Delay(10000);
201 SET_RESET;
202 st7783Delay(500);
203
204 st7783Command(0x00FF, 0x0001);
205 st7783Command(0x00F3, 0x0008);
206 st7783WriteCmd(0x00F3);
207
208 st7783Command(0x0001, 0x0100); // Driver Output Control Register (R01h)
209 st7783Command(0x0002, 0x0700); // LCD Driving Waveform Control (R02h)
210 st7783Command(0x0003, 0x1030); // Entry Mode (R03h)
211 st7783Command(0x0008, 0x0302);
212 st7783Command(0x0009, 0x0000);
213 st7783Command(0x0010, 0x0000); // Power Control 1 (R10h)
214 st7783Command(0x0011, 0x0007); // Power Control 2 (R11h)
215 st7783Command(0x0012, 0x0000); // Power Control 3 (R12h)
216 st7783Command(0x0013, 0x0000); // Power Control 4 (R13h)
217 st7783Delay(1000);
218 st7783Command(0x0010, 0x14B0); // Power Control 1 (R10h)
219 st7783Delay(500);
220 st7783Command(0x0011, 0x0007); // Power Control 2 (R11h)
221 st7783Delay(500);
222 st7783Command(0x0012, 0x008E); // Power Control 3 (R12h)
223 st7783Command(0x0013, 0x0C00); // Power Control 4 (R13h)
224 st7783Command(0x0029, 0x0015); // NVM read data 2 (R29h)
225 st7783Delay(500);
226 st7783Command(0x0030, 0x0000); // Gamma Control 1
227 st7783Command(0x0031, 0x0107); // Gamma Control 2
228 st7783Command(0x0032, 0x0000); // Gamma Control 3
229 st7783Command(0x0035, 0x0203); // Gamma Control 6
230 st7783Command(0x0036, 0x0402); // Gamma Control 7
231 st7783Command(0x0037, 0x0000); // Gamma Control 8
232 st7783Command(0x0038, 0x0207); // Gamma Control 9
233 st7783Command(0x0039, 0x0000); // Gamma Control 10
234 st7783Command(0x003C, 0x0203); // Gamma Control 13
235 st7783Command(0x003D, 0x0403); // Gamma Control 14
236 st7783Command(0x0050, 0x0000); // Window Horizontal RAM Address Start (R50h)
237 st7783Command(0x0051, st7783Properties.width - 1); // Window Horizontal RAM Address End (R51h)
238 st7783Command(0x0052, 0X0000); // Window Vertical RAM Address Start (R52h)
239 st7783Command(0x0053, st7783Properties.height - 1); // Window Vertical RAM Address End (R53h)
240 st7783Command(0x0060, 0xa700); // Driver Output Control (R60h)
241 st7783Command(0x0061, 0x0001); // Driver Output Control (R61h)
242 st7783Command(0x0090, 0X0029); // Panel Interface Control 1 (R90h)
243
244 // Display On
245 st7783Command(0x0007, 0x0133); // Display Control (R07h)
246 st7783Delay(500);
247 st7783WriteCmd(0x0022);
248 }
249
250 /*************************************************/
251 void st7783Home(void)
252 {
253 st7783SetCursor(0, 0);
254 st7783WriteCmd(0x0022); // Write Data to GRAM (R22h)
255 }
256
257 /*************************************************/
258 void st7783SetWindow(uint16_t x, uint16_t y, uint16_t height, uint16_t width)
259 {
260 // Window horizontal RAM address start
261 if (x >= height) st7783Command(0x50, (x - height + 1));
262 else st7783Command(0x50, 0);
263 // Window horizontal GRAM address end
264 st7783Command(0x51, x);
265 // Window vertical GRAM address start
266 if (y >= width) st7783Command(0x52, (y - width + 1));
267 else st7783Command(0x52, 0);
268 // Window vertical GRAM address end
269 st7783Command(0x53, y);
270
271 st7783SetCursor(x, y);
272 }
273
274 /*************************************************/
275 /* Public Methods */
276 /*************************************************/
277
278 /*************************************************/
279 void lcdInit(void)
280 {
281 // Set control line pins to output
282 gpioSetDir(ST7783_CS_PORT, ST7783_CS_PIN, 1);
283 gpioSetDir(ST7783_CD_PORT, ST7783_CD_PIN, 1);
284 gpioSetDir(ST7783_WR_PORT, ST7783_WR_PIN, 1);
285 gpioSetDir(ST7783_RD_PORT, ST7783_RD_PIN, 1);
286
287 // Set data port pins to output
288 ST7783_GPIO2DATA_SETOUTPUT;
289
290 // Disable pullups
291 ST7783_DISABLEPULLUPS();
292
293 // Set backlight pin to output and turn it on
294 gpioSetDir(ST7783_BL_PORT, ST7783_BL_PIN, 1); // set to output
295 lcdBacklight(TRUE);
296
297 // Set reset pin to output
298 gpioSetDir(ST7783_RES_PORT, ST7783_RES_PIN, 1); // Set to output
299 gpioSetValue(ST7783_RES_PORT, ST7783_RES_PIN, 0); // Low to reset
300 systickDelay(50);
301 gpioSetValue(ST7783_RES_PORT, ST7783_RES_PIN, 1); // High to exit
302
303 // Initialize the display
304 st7783InitDisplay();
305
306 // Set lcd to default orientation
307 lcdSetOrientation(lcdOrientation);
308
309 // Fill black
310 lcdFillRGB(COLOR_BLACK);
311
312 // Initialise the touch screen (and calibrate if necessary)
313 tsInit();
314 }
315
316 /*************************************************/
317 void lcdBacklight(bool state)
318 {
319 // Set the backlight
320 gpioSetValue(ST7783_BL_PORT, ST7783_BL_PIN, state ? 0 : 1);
321 }
322
323 /*************************************************/
324 void lcdTest(void)
325 {
326 uint32_t i,j;
327 st7783Home();
328
329 for(i=0;i<320;i++)
330 {
331 for(j=0;j<240;j++)
332 {
333 if(i>279)st7783WriteData(COLOR_WHITE);
334 else if(i>239)st7783WriteData(COLOR_BLUE);
335 else if(i>199)st7783WriteData(COLOR_GREEN);
336 else if(i>159)st7783WriteData(COLOR_CYAN);
337 else if(i>119)st7783WriteData(COLOR_RED);
338 else if(i>79)st7783WriteData(COLOR_MAGENTA);
339 else if(i>39)st7783WriteData(COLOR_YELLOW);
340 else st7783WriteData(COLOR_BLACK);
341 }
342 }
343 }
344
345 /*************************************************/
346 void lcdFillRGB(uint16_t data)
347 {
348 unsigned int i;
349 st7783Home();
350
351 uint32_t pixels = 320*240;
352 for ( i=0; i < pixels; i++ )
353 {
354 st7783WriteData(data);
355 }
356 }
357
358 /*************************************************/
359 void lcdDrawPixel(uint16_t x, uint16_t y, uint16_t color)
360 {
361 st7783SetCursor(x, y);
362 st7783WriteCmd(0x0022); // Write Data to GRAM (R22h)
363 st7783WriteData(color);
364 }
365
366 /**************************************************************************/
367 /*!
368 @brief Draws an array of consecutive RGB565 pixels (much
369 faster than addressing each pixel individually)
370 */
371 /**************************************************************************/
372 void lcdDrawPixels(uint16_t x, uint16_t y, uint16_t *data, uint32_t len)
373 {
374 uint32_t i = 0;
375 st7783SetCursor(x, y);
376 st7783WriteCmd(0x0022); // Write Data to GRAM (R22h)
377 do
378 {
379 st7783WriteData(data[i]);
380 i++;
381 } while (i<len);
382 }
383
384 /*************************************************/
385 void lcdDrawHLine(uint16_t x0, uint16_t x1, uint16_t y, uint16_t color)
386 {
387 // Allows for slightly better performance than setting individual pixels
388 uint16_t x, pixels;
389
390 if (x1 < x0)
391 {
392 // Switch x1 and x0
393 x = x1;
394 x1 = x0;
395 x0 = x;
396 }
397 st7783SetCursor(x0, y);
398 st7783WriteCmd(0x0022); // Write Data to GRAM (R22h)
399 for (pixels = 0; pixels < x1 - x0 + 1; pixels++)
400 {
401 st7783WriteData(color);
402 }
403 }
404
405 /*************************************************/
406 void lcdDrawVLine(uint16_t x, uint16_t y0, uint16_t y1, uint16_t color)
407 {
408 // Allows for slightly better performance than setting individual pixels
409 lcdOrientation_t orientation = lcdOrientation;
410
411 // Switch orientation
412 lcdSetOrientation(orientation == LCD_ORIENTATION_PORTRAIT ? LCD_ORIENTATION_LANDSCAPE : LCD_ORIENTATION_PORTRAIT);
413
414 // Draw horizontal line like usual
415 lcdDrawHLine(y0, y1, lcdGetHeight() - x, color);
416
417 // Switch orientation back
418 lcdSetOrientation(orientation);
419 }
420
421 /*************************************************/
422 uint16_t lcdGetPixel(uint16_t x, uint16_t y)
423 {
424 uint16_t preFetch = 0;
425
426 st7783SetCursor(x, y);
427 st7783WriteCmd(0x0022);
428 preFetch = st7783ReadData();
429
430 // Eeek ... why does this need to be done twice for a proper value?!?
431 st7783SetCursor(x, y);
432 st7783WriteCmd(0x0022);
433 return st7783ReadData();
434 }
435
436 /*************************************************/
437 void lcdSetOrientation(lcdOrientation_t orientation)
438 {
439 uint16_t entryMode = 0x1030;
440
441 switch (orientation)
442 {
443 case LCD_ORIENTATION_PORTRAIT:
444 entryMode = 0x1030;
445 break;
446 case LCD_ORIENTATION_LANDSCAPE:
447 entryMode = 0x1028;
448 break;
449 }
450 st7783WriteCmd(0x0003);
451 st7783WriteData(entryMode);
452 lcdOrientation = orientation;
453 st7783SetCursor(0, 0);
454 }
455
456 /*************************************************/
457 lcdOrientation_t lcdGetOrientation(void)
458 {
459 return lcdOrientation;
460 }
461
462 /*************************************************/
463 uint16_t lcdGetWidth(void)
464 {
465 switch (lcdOrientation)
466 {
467 case LCD_ORIENTATION_PORTRAIT:
468 return st7783Properties.width;
469 break;
470 case LCD_ORIENTATION_LANDSCAPE:
471 default:
472 return st7783Properties.height;
473 }
474 }
475
476 /*************************************************/
477 uint16_t lcdGetHeight(void)
478 {
479 switch (lcdOrientation)
480 {
481 case LCD_ORIENTATION_PORTRAIT:
482 return st7783Properties.height;
483 break;
484 case LCD_ORIENTATION_LANDSCAPE:
485 default:
486 return st7783Properties.width;
487 }
488 }
489
490 /*************************************************/
491 void lcdScroll(int16_t pixels, uint16_t fillColor)
492 {
493 // Not implemented in ST7783
494 }
495
496 /*************************************************/
497 uint16_t lcdGetControllerID(void)
498 {
499 return st7783Type();
500 }
501
502 /*************************************************/
503 lcdProperties_t lcdGetProperties(void)
504 {
505 return st7783Properties;
506 }
This page took 0.064387 seconds and 5 git commands to generate.