Prep for v1.2.0
[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, true, true};
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 void st7783SetCursor(uint16_t x, uint16_t y)
153 {
154 uint16_t he, ve, al, ah;
155
156 switch (lcdOrientation)
157 {
158 case LCD_ORIENTATION_LANDSCAPE:
159 he = st7783Properties.width-1-y;
160 ve = st7783Properties.height-1-x;
161 al = y;
162 ah = x;
163 break;
164 case LCD_ORIENTATION_PORTRAIT:
165 default:
166 he = st7783Properties.width-1;
167 ve = st7783Properties.height-1;
168 al = x;
169 ah = y;
170 break;
171 }
172 st7783Command(0x0051, he);
173 st7783Command(0x0053, ve);
174 st7783Command(0x0020, al);
175 st7783Command(0x0021, ah);
176 }
177
178 /*************************************************/
179 void st7783InitDisplay(void)
180 {
181 // Clear data line
182 GPIO_GPIO2DATA &= ~ST7783_DATA_MASK;
183
184 SET_RD;
185 SET_WR;
186 SET_CS;
187 SET_CD;
188
189 // Reset display
190 CLR_RESET;
191 st7783Delay(10000);
192 SET_RESET;
193 st7783Delay(500);
194
195 st7783Command(0x00FF, 0x0001);
196 st7783Command(0x00F3, 0x0008);
197 st7783WriteCmd(0x00F3);
198
199 st7783Command(0x0001, 0x0100); // Driver Output Control Register (R01h)
200 st7783Command(0x0002, 0x0700); // LCD Driving Waveform Control (R02h)
201 st7783Command(0x0003, 0x1030); // Entry Mode (R03h)
202 st7783Command(0x0008, 0x0302);
203 st7783Command(0x0009, 0x0000);
204 st7783Command(0x0010, 0x0000); // Power Control 1 (R10h)
205 st7783Command(0x0011, 0x0007); // Power Control 2 (R11h)
206 st7783Command(0x0012, 0x0000); // Power Control 3 (R12h)
207 st7783Command(0x0013, 0x0000); // Power Control 4 (R13h)
208 st7783Delay(1000);
209 st7783Command(0x0010, 0x14B0); // Power Control 1 (R10h)
210 st7783Delay(500);
211 st7783Command(0x0011, 0x0007); // Power Control 2 (R11h)
212 st7783Delay(500);
213 st7783Command(0x0012, 0x008E); // Power Control 3 (R12h)
214 st7783Command(0x0013, 0x0C00); // Power Control 4 (R13h)
215 st7783Command(0x0029, 0x0015); // NVM read data 2 (R29h)
216 st7783Delay(500);
217 st7783Command(0x0030, 0x0000); // Gamma Control 1
218 st7783Command(0x0031, 0x0107); // Gamma Control 2
219 st7783Command(0x0032, 0x0000); // Gamma Control 3
220 st7783Command(0x0035, 0x0203); // Gamma Control 6
221 st7783Command(0x0036, 0x0402); // Gamma Control 7
222 st7783Command(0x0037, 0x0000); // Gamma Control 8
223 st7783Command(0x0038, 0x0207); // Gamma Control 9
224 st7783Command(0x0039, 0x0000); // Gamma Control 10
225 st7783Command(0x003C, 0x0203); // Gamma Control 13
226 st7783Command(0x003D, 0x0403); // Gamma Control 14
227 st7783Command(0x0050, 0x0000); // Window Horizontal RAM Address Start (R50h)
228 st7783Command(0x0051, st7783Properties.width - 1); // Window Horizontal RAM Address End (R51h)
229 st7783Command(0x0052, 0X0000); // Window Vertical RAM Address Start (R52h)
230 st7783Command(0x0053, st7783Properties.height - 1); // Window Vertical RAM Address End (R53h)
231 st7783Command(0x0060, 0xa700); // Driver Output Control (R60h)
232 st7783Command(0x0061, 0x0001); // Driver Output Control (R61h)
233 st7783Command(0x0090, 0X0029); // Panel Interface Control 1 (R90h)
234
235 // Display On
236 st7783Command(0x0007, 0x0133); // Display Control (R07h)
237 st7783Delay(500);
238 st7783WriteCmd(0x0022);
239 }
240
241 /*************************************************/
242 void st7783Home(void)
243 {
244 st7783SetCursor(0, 0);
245 st7783WriteCmd(0x0022); // Write Data to GRAM (R22h)
246 }
247
248 /*************************************************/
249 void st7783SetWindow(uint16_t x, uint16_t y, uint16_t height, uint16_t width)
250 {
251 // Window horizontal RAM address start
252 if (x >= height) st7783Command(0x50, (x - height + 1));
253 else st7783Command(0x50, 0);
254 // Window horizontal GRAM address end
255 st7783Command(0x51, x);
256 // Window vertical GRAM address start
257 if (y >= width) st7783Command(0x52, (y - width + 1));
258 else st7783Command(0x52, 0);
259 // Window vertical GRAM address end
260 st7783Command(0x53, y);
261
262 st7783SetCursor(x, y);
263 }
264
265 /*************************************************/
266 /* Public Methods */
267 /*************************************************/
268
269 /*************************************************/
270 void lcdInit(void)
271 {
272 // Set control line pins to output
273 gpioSetDir(ST7783_CS_PORT, ST7783_CS_PIN, 1);
274 gpioSetDir(ST7783_CD_PORT, ST7783_CD_PIN, 1);
275 gpioSetDir(ST7783_WR_PORT, ST7783_WR_PIN, 1);
276 gpioSetDir(ST7783_RD_PORT, ST7783_RD_PIN, 1);
277
278 // Set data port pins to output
279 ST7783_GPIO2DATA_SETOUTPUT;
280
281 // Disable pullups
282 ST7783_DISABLEPULLUPS();
283
284 // Set backlight pin to output and turn it on
285 gpioSetDir(ST7783_BL_PORT, ST7783_BL_PIN, 1); // set to output
286 lcdBacklight(TRUE);
287
288 // Set reset pin to output
289 gpioSetDir(ST7783_RES_PORT, ST7783_RES_PIN, 1); // Set to output
290 gpioSetValue(ST7783_RES_PORT, ST7783_RES_PIN, 0); // Low to reset
291 systickDelay(50);
292 gpioSetValue(ST7783_RES_PORT, ST7783_RES_PIN, 1); // High to exit
293
294 // Initialize the display
295 st7783InitDisplay();
296
297 // Set lcd to default orientation
298 lcdSetOrientation(lcdOrientation);
299
300 // Fill black
301 lcdFillRGB(COLOR_BLACK);
302
303 // Initialise the touch screen (and calibrate if necessary)
304 tsInit();
305 }
306
307 /*************************************************/
308 void lcdBacklight(bool state)
309 {
310 // Set the backlight
311 gpioSetValue(ST7783_BL_PORT, ST7783_BL_PIN, state ? 0 : 1);
312 }
313
314 /*************************************************/
315 void lcdTest(void)
316 {
317 uint32_t i,j;
318 st7783Home();
319
320 for(i=0;i<320;i++)
321 {
322 for(j=0;j<240;j++)
323 {
324 if(i>279)st7783WriteData(COLOR_WHITE);
325 else if(i>239)st7783WriteData(COLOR_BLUE);
326 else if(i>199)st7783WriteData(COLOR_GREEN);
327 else if(i>159)st7783WriteData(COLOR_CYAN);
328 else if(i>119)st7783WriteData(COLOR_RED);
329 else if(i>79)st7783WriteData(COLOR_MAGENTA);
330 else if(i>39)st7783WriteData(COLOR_YELLOW);
331 else st7783WriteData(COLOR_BLACK);
332 }
333 }
334 }
335
336 /*************************************************/
337 void lcdFillRGB(uint16_t data)
338 {
339 unsigned int i;
340 st7783Home();
341
342 uint32_t pixels = 320*240;
343 for ( i=0; i < pixels; i++ )
344 {
345 st7783WriteData(data);
346 }
347 }
348
349 /*************************************************/
350 void lcdDrawPixel(uint16_t x, uint16_t y, uint16_t color)
351 {
352 st7783SetCursor(x, y);
353 st7783WriteCmd(0x0022); // Write Data to GRAM (R22h)
354 st7783WriteData(color);
355 }
356
357 /**************************************************************************/
358 /*!
359 @brief Draws an array of consecutive RGB565 pixels (much
360 faster than addressing each pixel individually)
361 */
362 /**************************************************************************/
363 void lcdDrawPixels(uint16_t x, uint16_t y, uint16_t *data, uint32_t len)
364 {
365 uint32_t i = 0;
366 st7783SetCursor(x, y);
367 st7783WriteCmd(0x0022); // Write Data to GRAM (R22h)
368 do
369 {
370 st7783WriteData(data[i]);
371 i++;
372 } while (i<len);
373 }
374
375 /*************************************************/
376 void lcdDrawHLine(uint16_t x0, uint16_t x1, uint16_t y, uint16_t color)
377 {
378 // Allows for slightly better performance than setting individual pixels
379 uint16_t x, pixels;
380
381 if (x1 < x0)
382 {
383 // Switch x1 and x0
384 x = x1;
385 x1 = x0;
386 x0 = x;
387 }
388 st7783SetCursor(x0, y);
389 st7783WriteCmd(0x0022); // Write Data to GRAM (R22h)
390 for (pixels = 0; pixels < x1 - x0 + 1; pixels++)
391 {
392 st7783WriteData(color);
393 }
394 }
395
396 /*************************************************/
397 void lcdDrawVLine(uint16_t x, uint16_t y0, uint16_t y1, uint16_t color)
398 {
399 // Allows for slightly better performance than setting individual pixels
400 lcdOrientation_t orientation = lcdOrientation;
401
402 // Switch orientation
403 lcdSetOrientation(orientation == LCD_ORIENTATION_PORTRAIT ? LCD_ORIENTATION_LANDSCAPE : LCD_ORIENTATION_PORTRAIT);
404
405 // Draw horizontal line like usual
406 lcdDrawHLine(y0, y1, lcdGetHeight() - x, color);
407
408 // Switch orientation back
409 lcdSetOrientation(orientation);
410 }
411
412 /*************************************************/
413 uint16_t lcdGetPixel(uint16_t x, uint16_t y)
414 {
415 uint16_t preFetch = 0;
416
417 st7783SetCursor(x, y);
418 st7783WriteCmd(0x0022);
419 preFetch = st7783ReadData();
420
421 // Eeek ... why does this need to be done twice for a proper value?!?
422 st7783SetCursor(x, y);
423 st7783WriteCmd(0x0022);
424 return st7783ReadData();
425 }
426
427 /*************************************************/
428 void lcdSetOrientation(lcdOrientation_t orientation)
429 {
430 uint16_t entryMode = 0x1030;
431
432 switch (orientation)
433 {
434 case LCD_ORIENTATION_PORTRAIT:
435 entryMode = 0x1030;
436 break;
437 case LCD_ORIENTATION_LANDSCAPE:
438 entryMode = 0x1028;
439 break;
440 }
441 st7783WriteCmd(0x0003);
442 st7783WriteData(entryMode);
443 lcdOrientation = orientation;
444 st7783SetCursor(0, 0);
445 }
446
447 /*************************************************/
448 lcdOrientation_t lcdGetOrientation(void)
449 {
450 return lcdOrientation;
451 }
452
453 /*************************************************/
454 uint16_t lcdGetWidth(void)
455 {
456 switch (lcdOrientation)
457 {
458 case LCD_ORIENTATION_PORTRAIT:
459 return st7783Properties.width;
460 break;
461 case LCD_ORIENTATION_LANDSCAPE:
462 default:
463 return st7783Properties.height;
464 }
465 }
466
467 /*************************************************/
468 uint16_t lcdGetHeight(void)
469 {
470 switch (lcdOrientation)
471 {
472 case LCD_ORIENTATION_PORTRAIT:
473 return st7783Properties.height;
474 break;
475 case LCD_ORIENTATION_LANDSCAPE:
476 default:
477 return st7783Properties.width;
478 }
479 }
480
481 /*************************************************/
482 void lcdScroll(int16_t pixels, uint16_t fillColor)
483 {
484 // Not implemented in ST7783
485 }
486
487 /*************************************************/
488 uint16_t lcdGetControllerID(void)
489 {
490 return 0x7783;
491 }
492
493 /*************************************************/
494 lcdProperties_t lcdGetProperties(void)
495 {
496 return st7783Properties;
497 }
This page took 0.084863 seconds and 5 git commands to generate.