1 /**************************************************************************/
4 @author Tauon {TauonTeilchen} Jabber ID Tauon[at]jabber.ccc.de
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
14 Software License Agreement (BSD License)
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 ----------------------------------------------------------------------------
31 /**************************************************************************/
32 #include "drivers/displays/tft/hw/hx8347d.h"
35 #define LCD_DATA ((0x72)|(LCD_ID<<2))
36 #define LCD_REGISTER ((0x70)|(LCD_ID<<2))
38 #define LCD_BACK_LIGHT 6
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)
49 #define Display_Mode_Control 0x01
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
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
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
66 #define TFA_REGISTER 0x0E
67 #define VSA_REGISTER 0x10
68 #define BFA_REGISTER 0x12
69 #define VSP_REGISTER 0x14
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
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
103 /*************************************************/
104 /* Private Methods */
105 /*************************************************/
106 void lcd_drawstart(void);
107 void lcd_cmd(uint16_t reg
, uint16_t param
);
108 void lcd_clear(uint16_t color
);
109 void lcd_draw(uint16_t color
);
110 void lcd_drawstart(void);
111 void lcd_drawstop(void);
112 void hx8347d_DisplayOnFlow(void);
113 void hx8347d_DisplayOffFlow(void);
114 void lcd_area(uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
);
117 void hx8347d_Scroll(uint16_t tfa
,uint16_t vsa
,uint16_t bfa
, uint16_t vsp
)
119 lcd_cmd(TFA_REGISTER
, tfa
>> 8);
120 lcd_cmd(TFA_REGISTER
+ 1, tfa
& 0xFF);
122 lcd_cmd(VSA_REGISTER
, vsa
>> 8);
123 lcd_cmd(VSA_REGISTER
+ 1, vsa
& 0xFF);
125 lcd_cmd(BFA_REGISTER
, bfa
>> 8);
126 lcd_cmd(BFA_REGISTER
+ 1, bfa
& 0xFF);
128 lcd_cmd(VSP_REGISTER
, vsp
>> 8);
129 lcd_cmd(VSP_REGISTER
+ 1, vsp
& 0xFF);
130 lcd_cmd(0x01, 0x08); //scroll on
133 void displayOnFlow(void)
135 lcd_cmd(Display_Control_3
, 0x0038);
137 lcd_cmd(Display_Control_3
, 0x003C);
139 void displayOffFlow(void)
141 lcd_cmd(Display_Control_3
, Display_Control_3_GON
| Display_Control_3_DTE
| Display_Control_3_D1
);
143 lcd_cmd(Display_Control_3
, Display_Control_3_D0
);
146 void lcd_cmd(uint16_t reg
, uint16_t param
)
152 b_first
[0] = LCD_REGISTER
;
155 sspSend(0, b_first
, 2);
162 sspSend(0, b_sec
, 2);
167 void lcd_clear(uint16_t color
)
171 lcd_area(0, 0, (hx8347dProperties
.width
-1), (hx8347dProperties
.height
-1));
174 for(i
=(hx8347dProperties
.width
*hx8347dProperties
.height
/8); i
!=0; i
--)
190 void lcd_draw(uint16_t color
)
192 // Writing data in 16Bit mode for saving a lot of time
193 /* Move on only if NOT busy and TX FIFO not full. */
194 while ((SSP_SSP0SR
& (SSP_SSP0SR_TNF_NOTFULL
| SSP_SSP0SR_BSY_BUSY
)) != SSP_SSP0SR_TNF_NOTFULL
);
197 while ( (SSP_SSP0SR
& (SSP_SSP0SR_BSY_BUSY
|SSP_SSP0SR_RNE_NOTEMPTY
)) != SSP_SSP0SR_RNE_NOTEMPTY
);
198 /* Whenever a byte is written, MISO FIFO counter increments, Clear FIFO
199 on MISO. Otherwise, when SSP0Receive() is called, previous data byte
200 is left in the FIFO. */
201 uint8_t Dummy
= SSP_SSP0DR
;
205 void lcd_drawstop(void)
207 while ((SSP_SSP0SR
& SSP_SSP0SR_TFE_MASK
) != SSP_SSP0SR_TFE_EMPTY
);
210 // init 8Bit SPI Mode
211 SSP_SSP0CR0
&= ~SSP_SSP0CR0_DSS_MASK
;
212 SSP_SSP0CR0
|= SSP_SSP0CR0_DSS_8BIT
;
216 void lcd_drawstart(void)
221 b_first
[0] = LCD_REGISTER
;
223 sspSend(0, b_first
, 2);
228 sspSend(0, b_sec
, 1);
231 // Assign config values to SSP0CR0
232 // init 16Bit SPI Mode for fast data transmitting
233 SSP_SSP0CR0
&= ~SSP_SSP0CR0_DSS_MASK
;
234 SSP_SSP0CR0
|= SSP_SSP0CR0_DSS_16BIT
;
240 void lcd_area(uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
)
242 if(hx8347dPOrientation
== LCD_ORIENTATION_PORTRAIT
)
244 y0
= ((320-offset
)+ y0
) % 320;
245 y1
= ((320-offset
)+ y1
) % 320;
249 x0
= ((320-offset
)+ x0
) % 320;
250 x1
= ((320-offset
)+ x1
) % 320;
252 lcd_cmd(Column_Address_Start_1
, (x0
>>0)); //set x0
253 lcd_cmd(Column_Address_Start_2
, (x0
>>8)); //set x0
254 lcd_cmd(Column_Address_End_1
, (x1
>>0)); //set x1
255 lcd_cmd(Column_Address_End_2
, (x1
>>8)); //set x1
256 lcd_cmd(Row_Address_Start_1
, (y0
>>0)); //set y0
257 lcd_cmd(Row_Address_Start_2
, (y0
>>8)); //set y0
258 lcd_cmd(Row_Address_End_1
, (y1
>>0)); //set y1
259 lcd_cmd(Row_Address_End_2
, (y1
>>8)); //set y1
263 void lcd_cursor(uint16_t x
, uint16_t y
)
265 lcd_area(x
, y
, x
, y
);
268 void lcd_data(uint16_t c
)
283 void fillRect(uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
)
301 if(x1
>= hx8347dProperties
.width
)
303 x1
= hx8347dProperties
.width
-1;
305 if(y1
>= hx8347dProperties
.height
)
307 y1
= hx8347dProperties
.height
-1;
310 lcd_area(x0
, y0
, x1
, y1
);
313 size
= (uint32_t)(1+(x1
-x0
)) * (uint32_t)(1+(y1
-y0
));
317 for(i
=tmp
; i
!=0; i
--)
328 for(i
=size
-tmp
; i
!=0; i
--)
335 for(i
=size
; i
!=0; i
--)
345 /*************************************************/
347 /*************************************************/
349 /**************************************************************************/
351 @brief Configures any pins or HW and initialises the LCD controller
353 /**************************************************************************/
358 gpioSetDir(2, LCD_CS
, gpioDirection_Output
);
359 gpioSetDir(2, LCD_RST
, gpioDirection_Output
);
360 gpioSetDir(2, LCD_BACK_LIGHT
, gpioDirection_Output
);
371 lcd_cmd(Power_Control_Internal_1
, 0x0000);
372 lcd_cmd(Power_Control_Internal_2
, 0x0020);
373 lcd_cmd(Source_Control_Internal_1
, 0x000C);
374 lcd_cmd(Source_Control_Internal_2
, 0x00C4);
375 lcd_cmd(Source_OP_Control_Normal
, 0x0040);
376 lcd_cmd(Source_OP_Control_IDLE
, 0x0038);
377 lcd_cmd(0xF1, 0x0001);
378 lcd_cmd(0xF2, 0x0010);
379 lcd_cmd(0x27, 0x00A3);
382 lcd_cmd(Power_Control_2
, 0x001B);
383 lcd_cmd(Power_Control_1
, 0x0001);
384 lcd_cmd(VCOM_Control_2
, 0x002F);
385 lcd_cmd(VCOM_Control_3
, 0x0057);
388 lcd_cmd(VCOM_Control_1
, 0x008D); //for flicker adjust
391 lcd_cmd(OSC_Control_1
, 0x0036);
392 lcd_cmd(OSC_Control_2
, 0x0001); //start osc
393 lcd_cmd(Display_Mode_Control
, 0x0000); //wakeup
394 lcd_cmd(Power_Control_6
, 0x0088);
396 lcd_cmd(Power_Control_6
, 0x0080);
398 lcd_cmd(Power_Control_6
, 0x0090);
400 lcd_cmd(Power_Control_6
, 0x00D0);
404 lcd_cmd(COLMOD
, 0x0005); //0x0005=65k, 0x0006=262k
406 //panel characteristic
407 lcd_cmd(0x36, 0x0000);
410 lcd_cmd(0x28, 0x0038);
412 lcd_cmd(0x28, 0x003C);
414 lcdSetOrientation(hx8347dPOrientation
);
418 /**************************************************************************/
420 @brief Enables or disables the LCD backlight
422 /**************************************************************************/
423 void lcdBacklight(bool state
)
425 gpioSetValue(2, LCD_BACK_LIGHT
, state
);
428 /**************************************************************************/
430 @brief Renders a simple test pattern on the LCD
432 /**************************************************************************/
435 lcdFillRGB(COLOR_CYAN
);
439 /**************************************************************************/
441 @brief Fills the LCD with the specified 16-bit color
443 /**************************************************************************/
444 void lcdFillRGB(uint16_t data
)
449 /**************************************************************************/
451 @brief Draws a single pixel at the specified X/Y location
453 /**************************************************************************/
454 void lcdDrawPixel(uint16_t x
, uint16_t y
, uint16_t color
)
456 if((x
>= hx8347dProperties
.width
) ||
457 (y
>= hx8347dProperties
.height
))
462 fillRect(x
,y
,x
,y
,color
);
467 /**************************************************************************/
469 @brief Draws an array of consecutive RGB565 pixels (much
470 faster than addressing each pixel individually)
472 /**************************************************************************/
473 void lcdDrawPixels(uint16_t x
, uint16_t y
, uint16_t *data
, uint32_t len
)
475 lcd_area(x
, y
, x
+ len
, y
);
478 for(i
= 0; i
< len
; i
++)
487 /**************************************************************************/
489 @brief Optimised routine to draw a horizontal line faster than
490 setting individual pixels
492 /**************************************************************************/
493 void lcdDrawHLine(uint16_t x0
, uint16_t x1
, uint16_t y
, uint16_t color
)
505 if(x0
>= hx8347dProperties
.width
)
507 x0
= hx8347dProperties
.width
-1;
509 if(x1
>= hx8347dProperties
.width
)
511 x1
= hx8347dProperties
.width
-1;
513 if(y
>= hx8347dProperties
.height
)
515 y
= hx8347dProperties
.height
-1;
518 fillRect(x0
, y
, x1
, y
, color
);
522 /**************************************************************************/
524 @brief Optimised routine to draw a vertical line faster than
525 setting individual pixels
527 /**************************************************************************/
528 void lcdDrawVLine(uint16_t x
, uint16_t y0
, uint16_t y1
, uint16_t color
)
540 if(x
>= hx8347dProperties
.width
)
542 x
= hx8347dProperties
.width
-1;
545 if(y0
>= hx8347dProperties
.height
)
547 y0
= hx8347dProperties
.height
-1;
549 if(y1
>= hx8347dProperties
.height
)
551 y1
= hx8347dProperties
.height
-1;
554 fillRect(x
, y0
, x
, y1
, color
);
557 /**************************************************************************/
559 @brief Gets the 16-bit color of the pixel at the specified location
561 /**************************************************************************/
562 uint16_t lcdGetPixel(uint16_t x
, uint16_t y
)
567 /**************************************************************************/
569 @brief Sets the LCD orientation to horizontal and vertical
571 /**************************************************************************/
572 void lcdSetOrientation(lcdOrientation_t orientation
)
574 if(orientation
== LCD_ORIENTATION_LANDSCAPE
)
576 lcd_cmd(0x16, 0x00A8); //MY=1 MX=0 MV=1 ML=0 BGR=1
577 hx8347dProperties
.width
= 320;
578 hx8347dProperties
.height
= 240;
582 //lcd_cmd(0x16, 0x0008); //MY=0 MX=0 MV=0 ML=0 BGR=1
583 lcd_cmd(0x16, 0x00C8); //MY=1 MX=0 MV=1 ML=0 BGR=1
584 hx8347dProperties
.width
= 240;
585 hx8347dProperties
.height
= 320;
587 hx8347dPOrientation
= orientation
;
588 lcd_area(0, 0, (hx8347dProperties
.width
-1), (hx8347dProperties
.height
-1));
591 /**************************************************************************/
593 @brief Gets the current screen orientation (horizontal or vertical)
595 /**************************************************************************/
596 lcdOrientation_t
lcdGetOrientation(void)
598 return hx8347dPOrientation
;
601 /**************************************************************************/
603 @brief Gets the width in pixels of the LCD screen (varies depending
604 on the current screen orientation)
606 /**************************************************************************/
607 uint16_t lcdGetWidth(void)
609 return hx8347dProperties
.width
;
612 /**************************************************************************/
614 @brief Gets the height in pixels of the LCD screen (varies depending
615 on the current screen orientation)
617 /**************************************************************************/
618 uint16_t lcdGetHeight(void)
620 return hx8347dProperties
.height
;
623 /**************************************************************************/
625 @brief Scrolls the contents of the LCD screen vertically the
626 specified number of pixels using a HW optimised routine
628 /**************************************************************************/
630 void lcdScroll(int16_t pixels
, uint16_t fillColor
)
633 hx8347d_Scroll(0,320,0,(offset
+ pixels
) % 320);
634 if(hx8347dPOrientation
== LCD_ORIENTATION_PORTRAIT
)
636 fillRect(0, hx8347dProperties
.height
-pixels
, hx8347dProperties
.width
, hx8347dProperties
.height
, fillColor
);
640 fillRect(hx8347dProperties
.width
-pixels
, 0, hx8347dProperties
.width
, hx8347dProperties
.height
, fillColor
);
642 offset
= (offset
+ pixels
) % 320;
644 /**************************************************************************/
646 @brief Set LCD into standby
647 In deep standby: LCD has lower power consumption
649 /**************************************************************************/
650 void hx8347d_Standby(bool deep
)
653 lcd_cmd(Power_Control_6
, Power_Control_6_STB
);
656 lcd_cmd(Display_Mode_Control
,Display_Mode_Control_DP_STB_S
);
657 lcd_cmd(Display_Mode_Control
, Display_Mode_Control_DP_STB
);
659 lcd_cmd(OSC_Control_2
, ~OSC_Control_2_OSC_EN
);
661 /**************************************************************************/
663 @brief Wakeup LCD from standby
664 Wakeup from deep standby you need min. 20ms
666 /**************************************************************************/
667 void hx8347d_Wakeup(bool deep
)
669 lcd_cmd(OSC_Control_2
, OSC_Control_2_OSC_EN
);
673 lcd_cmd(Display_Mode_Control
,0x0000);
675 lcd_cmd(Display_Mode_Control
, 0x0000);
682 lcd_cmd(Power_Control_6
, 0x00D0);
686 /**************************************************************************/
688 @brief Gets the controller's 16-bit (4 hexdigit) ID
690 /**************************************************************************/
691 uint16_t lcdGetControllerID(void)
696 /**************************************************************************/
698 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
699 generic capabilities and dimensions
701 /**************************************************************************/
702 lcdProperties_t
lcdGetProperties(void)
704 return hx8347dProperties
;