Spieler splodiert.
[hackover2013-badge-firmware.git] / drivers / displays / tft / hw / hx8347d.c
1 /**************************************************************************/
2 /*!
3 @file hx8347d.c
4 @author Tauon {TauonTeilchen} Jabber ID Tauon[at]jabber.ccc.de
5
6 @section DESCRIPTION
7 Driver for hx8347h 240x320 pixel TFT LCD displays.
8 Is written for MI0283QT-2 LCD from watterott.com
9 More infos: http://www.watterott.com/de/MI0283QT-2-Adapter
10 http://www.watterott.com/index.php?page=product&info=1597&dl_media=3202
11
12 @section LICENSE
13
14 Software License Agreement (BSD License)
15
16 Copyright (c) 2012, TauonTeilchen
17 ----------------------------------------------------------------------------
18 "THE ClubMate-WARE LICENSE" (Revision 42):
19 JID: <Tauon@jabber.ccc.de> wrote this file. As long as you retain this notice you
20 can do whatever you want with this stuff. If we meet some day, and you think
21 this stuff is worth it, you can buy me a ClubMate in return Tauon
22 ----------------------------------------------------------------------------
23 ----------------------------------------------------------------------------
24 "THE ClubMate-WARE LICENSE" (Revision 42):
25 JID: <Tauon@jabber.ccc.de> schrieb diese Datei. Solange Sie diesen Vermerk nicht entfernen, k�nnen
26 Sie mit dem Material machen, was Sie m�chten. Wenn wir uns eines Tages treffen und Sie
27 denken, das Material ist es wert, k�nnen Sie mir daf�r ein ClubMate ausgeben. Tauon
28 ----------------------------------------------------------------------------
29
30 */
31 /**************************************************************************/
32 #include "drivers/displays/tft/hw/hx8347d.h"
33
34 #define LCD_ID (0x00)
35 #define LCD_DATA ((0x72)|(LCD_ID<<2))
36 #define LCD_REGISTER ((0x70)|(LCD_ID<<2))
37
38 #define LCD_BACK_LIGHT 6
39 #define LCD_RST 5
40 #define LCD_CS 4
41
42 // Macros for control line state
43 #define LCD_CS_ENABLE() GPIO_GPIO2DATA &= ~0x10 // gpioSetValue(2, 4, 0)
44 #define LCD_CS_DISABLE() GPIO_GPIO2DATA |= 0x10 // gpioSetValue(2, 4, 1)
45 #define LCD_RST_ENABLE() GPIO_GPIO2DATA &= ~0x20 // gpioSetValue(2, 5, 0)
46 #define LCD_RST_DISABLE() GPIO_GPIO2DATA |= 0x20 // gpioSetValue(2, 5, 1)
47
48 #define Himax ID 0x00
49 #define Display_Mode_Control 0x01
50
51 #define Column_Address_Start_2 0x02
52 #define Column_Address_Start_1 0x03
53 #define Column_Address_End_2 0x04
54 #define Column_Address_End_1 0x05
55
56 #define Row_Address_Start_2 0x06
57 #define Row_Address_Start_1 0x07
58 #define Row_Address_End_2 0x08
59 #define Row_Address_End_1 0x09
60
61 #define Partial_Area_Start_Row_2 0x0A
62 #define Partial_Area_Start_Row_1 0x0B
63 #define Partial_Area_End_Row_2 0x0C
64 #define Partial_Area_End_Row_1 0x0D
65
66 #define TFA_REGISTER 0x0E
67 #define VSA_REGISTER 0x10
68 #define BFA_REGISTER 0x12
69 #define VSP_REGISTER 0x14
70
71 #define COLMOD 0x17
72 #define OSC_Control_1 0x18
73 #define OSC_Control_2 0x19
74 #define Power_Control_1 0x1A
75 #define Power_Control_2 0x1B
76 #define Power_Control_3 0x1C
77 #define Power_Control_4 0x1D
78 #define Power_Control_5 0x1E
79 #define Power_Control_6 0x1F
80 #define VCOM_Control_1 0x23
81 #define VCOM_Control_2 0x24
82 #define VCOM_Control_3 0x25
83 #define Display_Control_1 0x26
84 #define Display_Control_2 0x27
85 #define Display_Control_3 0x28
86 #define Source_OP_Control_Normal 0xE8
87 #define Source_OP_Control_IDLE 0xE9
88 #define Power_Control_Internal_1 0xEA
89 #define Power_Control_Internal_2 0xEB
90 #define Source_Control_Internal_1 0xEC
91 #define Source_Control_Internal_2 0xED
92
93 #define OSC_Control_2_OSC_EN 0x01
94 #define Display_Control_3_GON 0x20
95 #define Display_Control_3_DTE 0x10
96 #define Display_Control_3_D0 0x04
97 #define Display_Control_3_D1 0x08
98 #define Power_Control_6_STB 0x01
99 #define Display_Mode_Control_DP_STB_S 0x40
100 #define Display_Mode_Control_DP_STB 0x80
101
102 uint16_t offset;
103
104 /*************************************************/
105 /* Private Methods */
106 /*************************************************/
107 void lcd_drawstart(void);
108 void lcd_cmd(uint16_t reg, uint16_t param);
109 void lcd_clear(uint16_t color);
110 void lcd_draw(uint16_t color);
111 void lcd_drawstart(void);
112 void lcd_drawstop(void);
113 void hx8347d_DisplayOnFlow(void);
114 void hx8347d_DisplayOffFlow(void);
115 void lcd_area(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
116
117
118 void hx8347d_Scroll(uint16_t tfa,uint16_t vsa,uint16_t bfa, uint16_t vsp)
119 {
120 lcd_cmd(TFA_REGISTER , tfa >> 8);
121 lcd_cmd(TFA_REGISTER + 1, tfa & 0xFF);
122
123 lcd_cmd(VSA_REGISTER , vsa >> 8);
124 lcd_cmd(VSA_REGISTER + 1, vsa & 0xFF);
125
126 lcd_cmd(BFA_REGISTER , bfa >> 8);
127 lcd_cmd(BFA_REGISTER + 1, bfa & 0xFF);
128
129 lcd_cmd(VSP_REGISTER , vsp>> 8);
130 lcd_cmd(VSP_REGISTER + 1, vsp & 0xFF);
131 lcd_cmd(0x01, 0x08); //scroll on
132 }
133
134 void displayOnFlow(void)
135 {
136 lcd_cmd(Display_Control_3, 0x0038);
137 systickDelay(4);
138 lcd_cmd(Display_Control_3, 0x003C);
139 }
140 void displayOffFlow(void)
141 {
142 lcd_cmd(Display_Control_3, Display_Control_3_GON | Display_Control_3_DTE | Display_Control_3_D1);
143 systickDelay(4);
144 lcd_cmd(Display_Control_3, Display_Control_3_D0);
145 }
146
147 void lcd_cmd(uint16_t reg, uint16_t param)
148 {
149 uint8_t b_first[2];
150 uint8_t b_sec[2];
151 LCD_CS_ENABLE();
152
153 b_first[0] = LCD_REGISTER;
154 b_first[1] = reg;
155
156 sspSend(0, b_first, 2);
157 LCD_CS_DISABLE();
158
159 b_sec[0] = LCD_DATA;
160 b_sec[1] = param;
161 LCD_CS_ENABLE();
162
163 sspSend(0, b_sec, 2);
164 LCD_CS_DISABLE();
165
166 return;
167 }
168
169 void lcd_clear(uint16_t color)
170 {
171 unsigned int i;
172
173 lcd_area(0, 0, (hx8347dProperties.width -1), (hx8347dProperties.height-1));
174
175 lcd_drawstart();
176 for(i=(hx8347dProperties.width*hx8347dProperties.height/8); i!=0; i--)
177 {
178 lcd_draw(color); //1
179 lcd_draw(color); //2
180 lcd_draw(color); //3
181 lcd_draw(color); //4
182 lcd_draw(color); //5
183 lcd_draw(color); //6
184 lcd_draw(color); //7
185 lcd_draw(color); //8
186 }
187 lcd_drawstop();
188
189 return;
190 }
191
192 void lcd_draw(uint16_t color)
193 {
194 // Writing data in 16Bit mode for saving a lot of time
195 /* Move on only if NOT busy and TX FIFO not full. */
196 while ((SSP_SSP0SR & (SSP_SSP0SR_TNF_NOTFULL | SSP_SSP0SR_BSY_BUSY)) != SSP_SSP0SR_TNF_NOTFULL);
197 SSP_SSP0DR = color;
198
199 while ( (SSP_SSP0SR & (SSP_SSP0SR_BSY_BUSY|SSP_SSP0SR_RNE_NOTEMPTY)) != SSP_SSP0SR_RNE_NOTEMPTY );
200 /* Whenever a byte is written, MISO FIFO counter increments, Clear FIFO
201 on MISO. Otherwise, when SSP0Receive() is called, previous data byte
202 is left in the FIFO. */
203 uint8_t Dummy = SSP_SSP0DR;
204 return;
205 }
206
207 void lcd_drawstop(void)
208 {
209 while ((SSP_SSP0SR & SSP_SSP0SR_TFE_MASK ) != SSP_SSP0SR_TFE_EMPTY );
210 LCD_CS_DISABLE();
211
212 // init 8Bit SPI Mode
213 SSP_SSP0CR0 &= ~SSP_SSP0CR0_DSS_MASK;
214 SSP_SSP0CR0 |= SSP_SSP0CR0_DSS_8BIT;
215
216 return;
217 }
218
219 void lcd_drawstart(void)
220 {
221 LCD_CS_ENABLE();
222 uint8_t b_first[2];
223 uint8_t b_sec[1];
224 b_first[0] = LCD_REGISTER;
225 b_first[1] = 0x22;
226 sspSend(0, b_first, 2);
227 LCD_CS_DISABLE();
228
229 LCD_CS_ENABLE();
230 b_sec[0] = LCD_DATA;
231 sspSend(0, b_sec, 1);
232
233
234 // Assign config values to SSP0CR0
235 // init 16Bit SPI Mode for fast data transmitting
236 SSP_SSP0CR0 &= ~SSP_SSP0CR0_DSS_MASK;
237 SSP_SSP0CR0 |= SSP_SSP0CR0_DSS_16BIT;
238
239 return;
240 }
241
242 void lcd_area(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
243 {
244 if(hx8347dPOrientation == LCD_ORIENTATION_PORTRAIT)
245 {
246 y0 = ((320-offset)+ y0) % 320;
247 y1 = ((320-offset)+ y1) % 320;
248 }
249 else
250 {
251 x0 = ((320-offset)+ x0) % 320;
252 x1 = ((320-offset)+ x1) % 320;
253 }
254 lcd_cmd(Column_Address_Start_1, (x0>>0)); //set x0
255 lcd_cmd(Column_Address_Start_2, (x0>>8)); //set x0
256 lcd_cmd(Column_Address_End_1 , (x1>>0)); //set x1
257 lcd_cmd(Column_Address_End_2 , (x1>>8)); //set x1
258 lcd_cmd(Row_Address_Start_1 , (y0>>0)); //set y0
259 lcd_cmd(Row_Address_Start_2 , (y0>>8)); //set y0
260 lcd_cmd(Row_Address_End_1 , (y1>>0)); //set y1
261 lcd_cmd(Row_Address_End_2 , (y1>>8)); //set y1
262
263 return;
264 }
265
266 void lcd_cursor(uint16_t x, uint16_t y)
267 {
268 lcd_area(x, y, x, y);
269 return;
270 }
271
272 void lcd_data(uint16_t c)
273 {
274 LCD_CS_ENABLE();
275 uint8_t b[3];
276 b[0] = LCD_DATA;
277 b[1] = c>>8;
278 b[2] = c;
279 sspSend(0, b, 3);
280
281 LCD_CS_DISABLE();
282
283 return;
284 }
285
286 void fillRect(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color)
287 {
288 uint32_t size;
289 uint16_t tmp, i;
290
291 if(x0 > x1)
292 {
293 tmp = x0;
294 x0 = x1;
295 x1 = tmp;
296 }
297 if(y0 > y1)
298 {
299 tmp = y0;
300 y0 = y1;
301 y1 = tmp;
302 }
303
304 if(x1 >= hx8347dProperties.width)
305 {
306 x1 = hx8347dProperties.width-1;
307 }
308 if(y1 >= hx8347dProperties.height)
309 {
310 y1 = hx8347dProperties.height-1;
311 }
312
313 lcd_area(x0, y0, x1, y1);
314
315 lcd_drawstart();
316 size = (uint32_t)(1+(x1-x0)) * (uint32_t)(1+(y1-y0));
317 tmp = size/8;
318 if(tmp != 0)
319 {
320 for(i=tmp; i!=0; i--)
321 {
322 lcd_draw(color); //1
323 lcd_draw(color); //2
324 lcd_draw(color); //3
325 lcd_draw(color); //4
326 lcd_draw(color); //5
327 lcd_draw(color); //6
328 lcd_draw(color); //7
329 lcd_draw(color); //8
330 }
331 for(i=size-tmp; i!=0; i--)
332 {
333 lcd_draw(color);
334 }
335 }
336 else
337 {
338 for(i=size; i!=0; i--)
339 {
340 lcd_draw(color);
341 }
342 }
343 lcd_drawstop();
344
345 return;
346 }
347
348 /*************************************************/
349 /* Public Methods */
350 /*************************************************/
351
352 /**************************************************************************/
353 /*!
354 @brief Configures any pins or HW and initialises the LCD controller
355 */
356 /**************************************************************************/
357 void lcdInit(void)
358 {
359 sspInit(0,0,0);
360
361 gpioSetDir(2, LCD_CS, gpioDirection_Output);
362 gpioSetDir(2, LCD_RST, gpioDirection_Output);
363 gpioSetDir(2, LCD_BACK_LIGHT, gpioDirection_Output);
364
365 //reset
366 LCD_CS_DISABLE();
367 systickDelay(1);
368 LCD_RST_ENABLE();
369 systickDelay(50);
370 LCD_RST_DISABLE();
371 systickDelay(50);
372
373 //driving ability
374 lcd_cmd(Power_Control_Internal_1 , 0x0000);
375 lcd_cmd(Power_Control_Internal_2 , 0x0020);
376 lcd_cmd(Source_Control_Internal_1, 0x000C);
377 lcd_cmd(Source_Control_Internal_2, 0x00C4);
378 lcd_cmd(Source_OP_Control_Normal , 0x0040);
379 lcd_cmd(Source_OP_Control_IDLE , 0x0038);
380 lcd_cmd(0xF1, 0x0001);
381 lcd_cmd(0xF2, 0x0010);
382 lcd_cmd(0x27, 0x00A3);
383
384 //power voltage
385 lcd_cmd(Power_Control_2, 0x001B);
386 lcd_cmd(Power_Control_1, 0x0001);
387 lcd_cmd(VCOM_Control_2 , 0x002F);
388 lcd_cmd(VCOM_Control_3 , 0x0057);
389
390 //VCOM offset
391 lcd_cmd(VCOM_Control_1, 0x008D); //for flicker adjust
392
393 //power on
394 lcd_cmd(OSC_Control_1 , 0x0036);
395 lcd_cmd(OSC_Control_2 , 0x0001); //start osc
396 lcd_cmd(Display_Mode_Control, 0x0000); //wakeup
397 lcd_cmd(Power_Control_6 , 0x0088);
398 systickDelay(5);
399 lcd_cmd(Power_Control_6, 0x0080);
400 systickDelay(5);
401 lcd_cmd(Power_Control_6, 0x0090);
402 systickDelay(5);
403 lcd_cmd(Power_Control_6, 0x00D0);
404 systickDelay(5);
405
406 //color selection
407 lcd_cmd(COLMOD, 0x0005); //0x0005=65k, 0x0006=262k
408
409 //panel characteristic
410 lcd_cmd(0x36, 0x0000);
411
412 //display on
413 lcd_cmd(0x28, 0x0038);
414 systickDelay(40);
415 lcd_cmd(0x28, 0x003C);
416
417 lcdSetOrientation(hx8347dPOrientation);
418 offset = 0;
419 return;
420 }
421 /**************************************************************************/
422 /*!
423 @brief Enables or disables the LCD backlight
424 */
425 /**************************************************************************/
426 void lcdBacklight(bool state)
427 {
428 gpioSetValue(2, LCD_BACK_LIGHT, state);
429 }
430
431 /**************************************************************************/
432 /*!
433 @brief Renders a simple test pattern on the LCD
434 */
435 /**************************************************************************/
436 void lcdTest(void)
437 {
438 lcdFillRGB(COLOR_CYAN);
439 }
440
441 /**************************************************************************/
442 /*!
443 @brief Fills the LCD with the specified 16-bit color
444 */
445 /**************************************************************************/
446 void lcdFillRGB(uint16_t data)
447 {
448 lcd_clear(data);
449 }
450
451 /**************************************************************************/
452 /*!
453 @brief Draws a single pixel at the specified X/Y location
454 */
455 /**************************************************************************/
456 void lcdDrawPixel(uint16_t x, uint16_t y, uint16_t color)
457 {
458 if((x >= hx8347dProperties.width) ||
459 (y >= hx8347dProperties.height))
460 {
461 return;
462 }
463
464 fillRect(x,y,x,y,color);
465
466 return;
467 }
468
469 /**************************************************************************/
470 /*!
471 @brief Draws an array of consecutive RGB565 pixels (much
472 faster than addressing each pixel individually)
473 */
474 /**************************************************************************/
475 void lcdDrawPixels(uint16_t x, uint16_t y, uint16_t *data, uint32_t len)
476 {
477 lcd_area(x, y, x + len, y);
478 int i;
479 lcd_drawstart();
480 for(i = 0; i < len; i++)
481 {
482 lcd_draw(*data);
483 data++;
484 }
485 lcd_drawstop();
486 }
487
488 /**************************************************************************/
489 /*!
490 @brief Optimised routine to draw a horizontal line faster than
491 setting individual pixels
492 */
493 /**************************************************************************/
494 void lcdDrawHLine(uint16_t x0, uint16_t x1, uint16_t y, uint16_t color)
495 {
496 if (x1 < x0)
497 {
498 // Switch x1 and x0
499 uint16_t x;
500 x = x1;
501 x1 = x0;
502 x0 = x;
503 }
504
505 if(x0 >= hx8347dProperties.width)
506 {
507 x0 = hx8347dProperties.width-1;
508 }
509 if(x1 >= hx8347dProperties.width)
510 {
511 x1 = hx8347dProperties.width-1;
512 }
513 if(y >= hx8347dProperties.height)
514 {
515 y = hx8347dProperties.height-1;
516 }
517
518 fillRect(x0, y, x1, y, color);
519 }
520
521 /**************************************************************************/
522 /*!
523 @brief Optimised routine to draw a vertical line faster than
524 setting individual pixels
525 */
526 /**************************************************************************/
527 void lcdDrawVLine(uint16_t x, uint16_t y0, uint16_t y1, uint16_t color)
528 {
529 if (y1 < y0)
530 {
531 // Switch y1 and y0
532 uint16_t y;
533 y = y1;
534 y1 = y0;
535 y0 = y;
536 }
537
538 if(x >= hx8347dProperties.width)
539 {
540 x = hx8347dProperties.width-1;
541 }
542
543 if(y0 >= hx8347dProperties.height)
544 {
545 y0 = hx8347dProperties.height-1;
546 }
547 if(y1 >= hx8347dProperties.height)
548 {
549 y1 = hx8347dProperties.height-1;
550 }
551
552 fillRect(x, y0, x, y1, color);
553 }
554
555 /**************************************************************************/
556 /*!
557 @brief Gets the 16-bit color of the pixel at the specified location
558 */
559 /**************************************************************************/
560 uint16_t lcdGetPixel(uint16_t x, uint16_t y)
561 {
562 return 0;
563 }
564
565 /**************************************************************************/
566 /*!
567 @brief Sets the LCD orientation to horizontal and vertical
568 */
569 /**************************************************************************/
570 void lcdSetOrientation(lcdOrientation_t orientation)
571 {
572 if(orientation == LCD_ORIENTATION_LANDSCAPE)
573 {
574 lcd_cmd(0x16, 0x00A8); //MY=1 MX=0 MV=1 ML=0 BGR=1
575 hx8347dProperties.width = 320;
576 hx8347dProperties.height = 240;
577 }
578 else
579 {
580 //lcd_cmd(0x16, 0x0008); //MY=0 MX=0 MV=0 ML=0 BGR=1
581 lcd_cmd(0x16, 0x00C8); //MY=1 MX=0 MV=1 ML=0 BGR=1
582 hx8347dProperties.width = 240;
583 hx8347dProperties.height = 320;
584 }
585 hx8347dPOrientation = orientation;
586 lcd_area(0, 0, (hx8347dProperties.width-1), (hx8347dProperties.height-1));
587 }
588
589 /**************************************************************************/
590 /*!
591 @brief Gets the current screen orientation (horizontal or vertical)
592 */
593 /**************************************************************************/
594 lcdOrientation_t lcdGetOrientation(void)
595 {
596 return hx8347dPOrientation;
597 }
598
599 /**************************************************************************/
600 /*!
601 @brief Gets the width in pixels of the LCD screen (varies depending
602 on the current screen orientation)
603 */
604 /**************************************************************************/
605 uint16_t lcdGetWidth(void)
606 {
607 return hx8347dProperties.width;
608 }
609
610 /**************************************************************************/
611 /*!
612 @brief Gets the height in pixels of the LCD screen (varies depending
613 on the current screen orientation)
614 */
615 /**************************************************************************/
616 uint16_t lcdGetHeight(void)
617 {
618 return hx8347dProperties.height;
619 }
620
621 /**************************************************************************/
622 /*!
623 @brief Scrolls the contents of the LCD screen vertically the
624 specified number of pixels using a HW optimised routine
625 */
626 /**************************************************************************/
627
628 void lcdScroll(int16_t pixels, uint16_t fillColor)
629 {
630 hx8347d_Scroll(0,320,0,(offset + pixels) % 320);
631 if(hx8347dPOrientation == LCD_ORIENTATION_PORTRAIT)
632 {
633 fillRect(0, hx8347dProperties.height-pixels, hx8347dProperties.width, hx8347dProperties.height, fillColor);
634 }
635 else
636 {
637 fillRect(hx8347dProperties.width-pixels, 0, hx8347dProperties.width, hx8347dProperties.height, fillColor);
638 }
639 offset = (offset + pixels) % 320;
640 }
641 /**************************************************************************/
642 /*!
643 @brief Set LCD into standby
644 In deep standby: LCD has lower power consumption
645 */
646 /**************************************************************************/
647 void hx8347d_Standby(bool deep)
648 {
649 displayOffFlow();
650 lcd_cmd(Power_Control_6 , Power_Control_6_STB);
651 if(deep)
652 {
653 lcd_cmd(Display_Mode_Control,Display_Mode_Control_DP_STB_S);
654 lcd_cmd(Display_Mode_Control, Display_Mode_Control_DP_STB);
655 }
656 lcd_cmd(OSC_Control_2, ~OSC_Control_2_OSC_EN);
657 }
658 /**************************************************************************/
659 /*!
660 @brief Wakeup LCD from standby
661 Wakeup from deep standby you need min. 20ms
662 */
663 /**************************************************************************/
664 void hx8347d_Wakeup(bool deep)
665 {
666 lcd_cmd(OSC_Control_2, OSC_Control_2_OSC_EN);
667
668 if(deep)
669 {
670 lcd_cmd(Display_Mode_Control,0x0000);
671 systickDelay(20);
672 lcd_cmd(Display_Mode_Control, 0x0000);
673 }
674 else
675 {
676 systickDelay(5);
677 }
678
679 lcd_cmd(Power_Control_6, 0x00D0);
680 displayOnFlow();
681 }
682
683 /**************************************************************************/
684 /*!
685 @brief Gets the controller's 16-bit (4 hexdigit) ID
686 */
687 /**************************************************************************/
688 uint16_t lcdGetControllerID(void)
689 {
690 return 0x0;
691 }
692
693 /**************************************************************************/
694 /*!
695 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
696 generic capabilities and dimensions
697 */
698 /**************************************************************************/
699 lcdProperties_t lcdGetProperties(void)
700 {
701 return hx8347dProperties;
702 }
703
This page took 0.082103 seconds and 5 git commands to generate.