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
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
);
118 void hx8347d_Scroll(uint16_t tfa
,uint16_t vsa
,uint16_t bfa
, uint16_t vsp
)
120 lcd_cmd(TFA_REGISTER
, tfa
>> 8);
121 lcd_cmd(TFA_REGISTER
+ 1, tfa
& 0xFF);
123 lcd_cmd(VSA_REGISTER
, vsa
>> 8);
124 lcd_cmd(VSA_REGISTER
+ 1, vsa
& 0xFF);
126 lcd_cmd(BFA_REGISTER
, bfa
>> 8);
127 lcd_cmd(BFA_REGISTER
+ 1, bfa
& 0xFF);
129 lcd_cmd(VSP_REGISTER
, vsp
>> 8);
130 lcd_cmd(VSP_REGISTER
+ 1, vsp
& 0xFF);
131 lcd_cmd(0x01, 0x08); //scroll on
134 void displayOnFlow(void)
136 lcd_cmd(Display_Control_3
, 0x0038);
138 lcd_cmd(Display_Control_3
, 0x003C);
140 void displayOffFlow(void)
142 lcd_cmd(Display_Control_3
, Display_Control_3_GON
| Display_Control_3_DTE
| Display_Control_3_D1
);
144 lcd_cmd(Display_Control_3
, Display_Control_3_D0
);
147 void lcd_cmd(uint16_t reg
, uint16_t param
)
153 b_first
[0] = LCD_REGISTER
;
156 sspSend(0, b_first
, 2);
163 sspSend(0, b_sec
, 2);
169 void lcd_clear(uint16_t color
)
173 lcd_area(0, 0, (hx8347dProperties
.width
-1), (hx8347dProperties
.height
-1));
176 for(i
=(hx8347dProperties
.width
*hx8347dProperties
.height
/8); i
!=0; i
--)
192 void lcd_draw(uint16_t color
)
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
);
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
;
207 void lcd_drawstop(void)
209 while ((SSP_SSP0SR
& SSP_SSP0SR_TFE_MASK
) != SSP_SSP0SR_TFE_EMPTY
);
212 // init 8Bit SPI Mode
213 SSP_SSP0CR0
&= ~SSP_SSP0CR0_DSS_MASK
;
214 SSP_SSP0CR0
|= SSP_SSP0CR0_DSS_8BIT
;
219 void lcd_drawstart(void)
224 b_first
[0] = LCD_REGISTER
;
226 sspSend(0, b_first
, 2);
231 sspSend(0, b_sec
, 1);
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
;
242 void lcd_area(uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
)
244 if(hx8347dPOrientation
== LCD_ORIENTATION_PORTRAIT
)
246 y0
= ((320-offset
)+ y0
) % 320;
247 y1
= ((320-offset
)+ y1
) % 320;
251 x0
= ((320-offset
)+ x0
) % 320;
252 x1
= ((320-offset
)+ x1
) % 320;
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
266 void lcd_cursor(uint16_t x
, uint16_t y
)
268 lcd_area(x
, y
, x
, y
);
272 void lcd_data(uint16_t c
)
286 void fillRect(uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
)
304 if(x1
>= hx8347dProperties
.width
)
306 x1
= hx8347dProperties
.width
-1;
308 if(y1
>= hx8347dProperties
.height
)
310 y1
= hx8347dProperties
.height
-1;
313 lcd_area(x0
, y0
, x1
, y1
);
316 size
= (uint32_t)(1+(x1
-x0
)) * (uint32_t)(1+(y1
-y0
));
320 for(i
=tmp
; i
!=0; i
--)
331 for(i
=size
-tmp
; i
!=0; i
--)
338 for(i
=size
; i
!=0; i
--)
348 /*************************************************/
350 /*************************************************/
352 /**************************************************************************/
354 @brief Configures any pins or HW and initialises the LCD controller
356 /**************************************************************************/
361 gpioSetDir(2, LCD_CS
, gpioDirection_Output
);
362 gpioSetDir(2, LCD_RST
, gpioDirection_Output
);
363 gpioSetDir(2, LCD_BACK_LIGHT
, gpioDirection_Output
);
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);
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);
391 lcd_cmd(VCOM_Control_1
, 0x008D); //for flicker adjust
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);
399 lcd_cmd(Power_Control_6
, 0x0080);
401 lcd_cmd(Power_Control_6
, 0x0090);
403 lcd_cmd(Power_Control_6
, 0x00D0);
407 lcd_cmd(COLMOD
, 0x0005); //0x0005=65k, 0x0006=262k
409 //panel characteristic
410 lcd_cmd(0x36, 0x0000);
413 lcd_cmd(0x28, 0x0038);
415 lcd_cmd(0x28, 0x003C);
417 lcdSetOrientation(hx8347dPOrientation
);
421 /**************************************************************************/
423 @brief Enables or disables the LCD backlight
425 /**************************************************************************/
426 void lcdBacklight(bool state
)
428 gpioSetValue(2, LCD_BACK_LIGHT
, state
);
431 /**************************************************************************/
433 @brief Renders a simple test pattern on the LCD
435 /**************************************************************************/
438 lcdFillRGB(COLOR_CYAN
);
441 /**************************************************************************/
443 @brief Fills the LCD with the specified 16-bit color
445 /**************************************************************************/
446 void lcdFillRGB(uint16_t data
)
451 /**************************************************************************/
453 @brief Draws a single pixel at the specified X/Y location
455 /**************************************************************************/
456 void lcdDrawPixel(uint16_t x
, uint16_t y
, uint16_t color
)
458 if((x
>= hx8347dProperties
.width
) ||
459 (y
>= hx8347dProperties
.height
))
464 fillRect(x
,y
,x
,y
,color
);
469 /**************************************************************************/
471 @brief Draws an array of consecutive RGB565 pixels (much
472 faster than addressing each pixel individually)
474 /**************************************************************************/
475 void lcdDrawPixels(uint16_t x
, uint16_t y
, uint16_t *data
, uint32_t len
)
477 lcd_area(x
, y
, x
+ len
, y
);
480 for(i
= 0; i
< len
; i
++)
488 /**************************************************************************/
490 @brief Optimised routine to draw a horizontal line faster than
491 setting individual pixels
493 /**************************************************************************/
494 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
);
521 /**************************************************************************/
523 @brief Optimised routine to draw a vertical line faster than
524 setting individual pixels
526 /**************************************************************************/
527 void lcdDrawVLine(uint16_t x
, uint16_t y0
, uint16_t y1
, uint16_t color
)
538 if(x
>= hx8347dProperties
.width
)
540 x
= hx8347dProperties
.width
-1;
543 if(y0
>= hx8347dProperties
.height
)
545 y0
= hx8347dProperties
.height
-1;
547 if(y1
>= hx8347dProperties
.height
)
549 y1
= hx8347dProperties
.height
-1;
552 fillRect(x
, y0
, x
, y1
, color
);
555 /**************************************************************************/
557 @brief Gets the 16-bit color of the pixel at the specified location
559 /**************************************************************************/
560 uint16_t lcdGetPixel(uint16_t x
, uint16_t y
)
565 /**************************************************************************/
567 @brief Sets the LCD orientation to horizontal and vertical
569 /**************************************************************************/
570 void lcdSetOrientation(lcdOrientation_t orientation
)
572 if(orientation
== LCD_ORIENTATION_LANDSCAPE
)
574 lcd_cmd(0x16, 0x00A8); //MY=1 MX=0 MV=1 ML=0 BGR=1
575 hx8347dProperties
.width
= 320;
576 hx8347dProperties
.height
= 240;
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;
585 hx8347dPOrientation
= orientation
;
586 lcd_area(0, 0, (hx8347dProperties
.width
-1), (hx8347dProperties
.height
-1));
589 /**************************************************************************/
591 @brief Gets the current screen orientation (horizontal or vertical)
593 /**************************************************************************/
594 lcdOrientation_t
lcdGetOrientation(void)
596 return hx8347dPOrientation
;
599 /**************************************************************************/
601 @brief Gets the width in pixels of the LCD screen (varies depending
602 on the current screen orientation)
604 /**************************************************************************/
605 uint16_t lcdGetWidth(void)
607 return hx8347dProperties
.width
;
610 /**************************************************************************/
612 @brief Gets the height in pixels of the LCD screen (varies depending
613 on the current screen orientation)
615 /**************************************************************************/
616 uint16_t lcdGetHeight(void)
618 return hx8347dProperties
.height
;
621 /**************************************************************************/
623 @brief Scrolls the contents of the LCD screen vertically the
624 specified number of pixels using a HW optimised routine
626 /**************************************************************************/
628 void lcdScroll(int16_t pixels
, uint16_t fillColor
)
630 hx8347d_Scroll(0,320,0,(offset
+ pixels
) % 320);
631 if(hx8347dPOrientation
== LCD_ORIENTATION_PORTRAIT
)
633 fillRect(0, hx8347dProperties
.height
-pixels
, hx8347dProperties
.width
, hx8347dProperties
.height
, fillColor
);
637 fillRect(hx8347dProperties
.width
-pixels
, 0, hx8347dProperties
.width
, hx8347dProperties
.height
, fillColor
);
639 offset
= (offset
+ pixels
) % 320;
641 /**************************************************************************/
643 @brief Set LCD into standby
644 In deep standby: LCD has lower power consumption
646 /**************************************************************************/
647 void hx8347d_Standby(bool deep
)
650 lcd_cmd(Power_Control_6
, Power_Control_6_STB
);
653 lcd_cmd(Display_Mode_Control
,Display_Mode_Control_DP_STB_S
);
654 lcd_cmd(Display_Mode_Control
, Display_Mode_Control_DP_STB
);
656 lcd_cmd(OSC_Control_2
, ~OSC_Control_2_OSC_EN
);
658 /**************************************************************************/
660 @brief Wakeup LCD from standby
661 Wakeup from deep standby you need min. 20ms
663 /**************************************************************************/
664 void hx8347d_Wakeup(bool deep
)
666 lcd_cmd(OSC_Control_2
, OSC_Control_2_OSC_EN
);
670 lcd_cmd(Display_Mode_Control
,0x0000);
672 lcd_cmd(Display_Mode_Control
, 0x0000);
679 lcd_cmd(Power_Control_6
, 0x00D0);
683 /**************************************************************************/
685 @brief Gets the controller's 16-bit (4 hexdigit) ID
687 /**************************************************************************/
688 uint16_t lcdGetControllerID(void)
693 /**************************************************************************/
695 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
696 generic capabilities and dimensions
698 /**************************************************************************/
699 lcdProperties_t
lcdGetProperties(void)
701 return hx8347dProperties
;