summaryrefslogtreecommitdiff
path: root/components/hx8347/hx8347.c
blob: bc80d08e84f44925d54c8770b86b606acc03f564 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
/* ----------------------------------------------------------------------------
 *         ATMEL Microcontroller Software Support
 * ----------------------------------------------------------------------------
 * Copyright (c) 2008, Atmel Corporation
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaimer below.
 *
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ----------------------------------------------------------------------------
 */

//------------------------------------------------------------------------------
/// \unit
///
/// !Purpose
/// 
/// HX8347 driver
/// 
/// !Usage
/// 
/// Explanation on the usage of the code made available through the header file.
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//         Headers
//------------------------------------------------------------------------------
#include <board.h>
#include <stdio.h>

#ifdef BOARD_LCD_HX8347

#include "hx8347.h"

//------------------------------------------------------------------------------
//         Types
//------------------------------------------------------------------------------
typedef volatile unsigned short REG16;

//------------------------------------------------------------------------------
//         Definitions
//------------------------------------------------------------------------------
/// LCD index register address
#define LCD_IR(baseAddr) (*((REG16 *)(baseAddr)))
/// LCD status register address
#define LCD_SR(baseAddr) (*((REG16 *)(baseAddr)))
/// LCD data address
#define LCD_D(baseAddr)  (*((REG16 *)((unsigned int)(baseAddr) + BOARD_LCD_RS)))

/// HX8347 ID code
#define HX8347_HIMAXID_CODE    0x47

/// HX8347 LCD Registers
#define HX8347_R00H        0x00
#define HX8347_R01H        0x01
#define HX8347_R02H        0x02
#define HX8347_R03H        0x03
#define HX8347_R04H        0x04
#define HX8347_R05H        0x05
#define HX8347_R06H        0x06
#define HX8347_R07H        0x07
#define HX8347_R08H        0x08
#define HX8347_R09H        0x09
#define HX8347_R0AH        0x0A
#define HX8347_R0CH        0x0C
#define HX8347_R0DH        0x0D
#define HX8347_R0EH        0x0E
#define HX8347_R0FH        0x0F
#define HX8347_R10H        0x10
#define HX8347_R11H        0x11
#define HX8347_R12H        0x12
#define HX8347_R13H        0x13
#define HX8347_R14H        0x14
#define HX8347_R15H        0x15
#define HX8347_R16H        0x16
#define HX8347_R18H        0x18
#define HX8347_R19H        0x19
#define HX8347_R1AH        0x1A
#define HX8347_R1BH        0x1B
#define HX8347_R1CH        0x1C
#define HX8347_R1DH        0x1D
#define HX8347_R1EH        0x1E
#define HX8347_R1FH        0x1F
#define HX8347_R20H        0x20
#define HX8347_R21H        0x21
#define HX8347_R22H        0x22
#define HX8347_R23H        0x23
#define HX8347_R24H        0x24
#define HX8347_R25H        0x25
#define HX8347_R26H        0x26
#define HX8347_R27H        0x27
#define HX8347_R28H        0x28
#define HX8347_R29H        0x29
#define HX8347_R2AH        0x2A
#define HX8347_R2BH        0x2B
#define HX8347_R2CH        0x2C
#define HX8347_R2DH        0x2D
#define HX8347_R35H        0x35
#define HX8347_R36H        0x36
#define HX8347_R37H        0x37
#define HX8347_R38H        0x38
#define HX8347_R39H        0x39
#define HX8347_R3AH        0x3A
#define HX8347_R3BH        0x3B
#define HX8347_R3CH        0x3C
#define HX8347_R3DH        0x3D
#define HX8347_R3EH        0x3E
#define HX8347_R40H        0x40
#define HX8347_R41H        0x41
#define HX8347_R42H        0x42
#define HX8347_R43H        0x43
#define HX8347_R44H        0x44
#define HX8347_R45H        0x45
#define HX8347_R46H        0x46
#define HX8347_R47H        0x47
#define HX8347_R48H        0x48
#define HX8347_R49H        0x49
#define HX8347_R4AH        0x4A
#define HX8347_R4BH        0x4B
#define HX8347_R4CH        0x4C
#define HX8347_R4DH        0x4D
#define HX8347_R4EH        0x4E
#define HX8347_R4FH        0x4F
#define HX8347_R50H        0x50
#define HX8347_R51H        0x51
#define HX8347_R64H        0x64
#define HX8347_R65H        0x65
#define HX8347_R66H        0x66
#define HX8347_R67H        0x67
#define HX8347_R70H        0x70
#define HX8347_R72H        0x72
#define HX8347_R90H        0x90
#define HX8347_R91H        0x91
#define HX8347_R93H        0x93
#define HX8347_R94H        0x94
#define HX8347_R95H        0x95

//------------------------------------------------------------------------------
//         External functions
//------------------------------------------------------------------------------
// External delay 1 ms function
extern void DelayMS(unsigned int ms);
#define Delay(ms) DelayMS(ms)

//------------------------------------------------------------------------------
//         Global functions
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
/// Write data to LCD Register.
/// \param pLcdBase   LCD base address.
/// \param reg        Register address.
/// \param data       Data to be written.
//------------------------------------------------------------------------------
void LCD_WriteReg(void *pLcdBase, unsigned char reg, unsigned short data)
{
    LCD_IR(pLcdBase) = reg;
    LCD_D(pLcdBase)  = data;
}

//------------------------------------------------------------------------------
/// Read data from LCD Register.
/// \param pLcdBase   LCD base address.
/// \param reg        Register address.
/// \return data      Data to be read.
//------------------------------------------------------------------------------
unsigned short LCD_ReadReg(void *pLcdBase, unsigned char reg)
{
    LCD_IR(pLcdBase) = reg;
    return LCD_D(pLcdBase);
}

//------------------------------------------------------------------------------
/// Read LCD status Register.
/// \param pLcdBase   LCD base address.
/// \param reg        Register address.
/// \return data      Status Data.
//------------------------------------------------------------------------------
unsigned short LCD_ReadStatus(void *pLcdBase)
{
    return LCD_SR(pLcdBase);
}

//------------------------------------------------------------------------------
/// Prepare to write GRAM data.
/// \param pLcdBase   LCD base address.
//------------------------------------------------------------------------------
void LCD_WriteRAM_Prepare(void *pLcdBase)
{
    LCD_IR(pLcdBase) = HX8347_R22H;
}

//------------------------------------------------------------------------------
/// Write data to LCD GRAM.
/// \param pLcdBase   LCD base address.
/// \param color      16-bits RGB color.
//------------------------------------------------------------------------------
void LCD_WriteRAM(void *pLcdBase, unsigned short color)
{
    // Write 16-bit GRAM Reg
    LCD_D(pLcdBase) = color;
}

//------------------------------------------------------------------------------
/// Prepare to read GRAM data.
/// \param pLcdBase   LCD base address.
//------------------------------------------------------------------------------
void LCD_ReadRAM_Prepare(void *pLcdBase)
{
    LCD_IR(pLcdBase) = HX8347_R22H;
}

//------------------------------------------------------------------------------
/// Read GRAM data.
/// \param pLcdBase   LCD base address.
/// \return           16-bits RGB color.
//------------------------------------------------------------------------------
unsigned short LCD_ReadRAM(void *pLcdBase)
{
    // Read 16-bit GRAM Reg
    return LCD_D(pLcdBase);
}

//------------------------------------------------------------------------------
/// Dump register data.
/// \param pLcdBase   LCD base address.
/// \param startAddr  Register start address.
/// \param endAddr    Register end address.
//------------------------------------------------------------------------------
void LCD_DumpReg(void *pLcdBase, unsigned char startAddr, unsigned char endAddr)
{
    unsigned short tmp;
    unsigned char addr;

    for (addr = startAddr; addr <= endAddr; addr++) {

        tmp = LCD_ReadReg(pLcdBase, addr);
        printf("LCD.r 0x%x = 0x%x\n\r", addr, tmp);
    }
}

//------------------------------------------------------------------------------
/// Initialize the LCD controller.
/// \param pLcdBase   LCD base address.
//------------------------------------------------------------------------------
void LCD_Initialize(void *pLcdBase)
{
    unsigned short chipid;

    // Check HX8347 chipid
    chipid = LCD_ReadReg(pLcdBase, HX8347_R67H);
    if(chipid != HX8347_HIMAXID_CODE) {

        printf("Read HX8347 chip ID error, skip initialization.\r\n");
        return ;
    }

    // Start internal OSC
    LCD_WriteReg(pLcdBase, HX8347_R19H, 0x49); // OSCADJ=10 0000, OSD_EN=1 //60Hz
    LCD_WriteReg(pLcdBase, HX8347_R93H, 0x0C); // RADJ=1100

    // Power on flow
    LCD_WriteReg(pLcdBase, HX8347_R44H, 0x4D); // VCM=100 1101
    LCD_WriteReg(pLcdBase, HX8347_R45H, 0x11); // VDV=1 0001
    LCD_WriteReg(pLcdBase, HX8347_R20H, 0x40); // BT=0100
    LCD_WriteReg(pLcdBase, HX8347_R1DH, 0x07); // VC1=111
    LCD_WriteReg(pLcdBase, HX8347_R1EH, 0x00); // VC3=000
    LCD_WriteReg(pLcdBase, HX8347_R1FH, 0x04); // VRH=0100

    LCD_WriteReg(pLcdBase, HX8347_R1CH, 0x04); // AP=100
    LCD_WriteReg(pLcdBase, HX8347_R1BH, 0x10); // GASENB=0, PON=1, DK=0, XDK=0, DDVDH_TRI=0, STB=0
    Delay(50);

    LCD_WriteReg(pLcdBase, HX8347_R43H, 0x80); // Set VCOMG=1
    Delay(50);

    // Gamma for CMO 2.8
    LCD_WriteReg(pLcdBase, HX8347_R46H, 0x95);
    LCD_WriteReg(pLcdBase, HX8347_R47H, 0x51);
    LCD_WriteReg(pLcdBase, HX8347_R48H, 0x00);
    LCD_WriteReg(pLcdBase, HX8347_R49H, 0x36);
    LCD_WriteReg(pLcdBase, HX8347_R4AH, 0x11);
    LCD_WriteReg(pLcdBase, HX8347_R4BH, 0x66);
    LCD_WriteReg(pLcdBase, HX8347_R4CH, 0x14);
    LCD_WriteReg(pLcdBase, HX8347_R4DH, 0x77);
    LCD_WriteReg(pLcdBase, HX8347_R4EH, 0x13);
    LCD_WriteReg(pLcdBase, HX8347_R4FH, 0x4C);
    LCD_WriteReg(pLcdBase, HX8347_R50H, 0x46);
    LCD_WriteReg(pLcdBase, HX8347_R51H, 0x46);

    //240x320 window setting
    LCD_WriteReg(pLcdBase, HX8347_R02H, 0x00); // Column address start2
    LCD_WriteReg(pLcdBase, HX8347_R03H, 0x00); // Column address start1
    LCD_WriteReg(pLcdBase, HX8347_R04H, 0x00); // Column address end2
    LCD_WriteReg(pLcdBase, HX8347_R05H, 0xEF); // Column address end1
    LCD_WriteReg(pLcdBase, HX8347_R06H, 0x00); // Row address start2
    LCD_WriteReg(pLcdBase, HX8347_R07H, 0x00); // Row address start1
    LCD_WriteReg(pLcdBase, HX8347_R08H, 0x01); // Row address end2
    LCD_WriteReg(pLcdBase, HX8347_R09H, 0x3F); // Row address end1

    // Display Setting
    LCD_WriteReg(pLcdBase, HX8347_R01H, 0x06); // IDMON=0, INVON=1, NORON=1, PTLON=0
    LCD_WriteReg(pLcdBase, HX8347_R16H, 0xC8); // MY=1, MX=1, MV=0, BGR=1
    LCD_WriteReg(pLcdBase, HX8347_R23H, 0x95); // N_DC=1001 0101
    LCD_WriteReg(pLcdBase, HX8347_R24H, 0x95); // P_DC=1001 0101
    LCD_WriteReg(pLcdBase, HX8347_R25H, 0xFF); // I_DC=1111 1111
    LCD_WriteReg(pLcdBase, HX8347_R27H, 0x06); // N_BP=0000 0110
    LCD_WriteReg(pLcdBase, HX8347_R28H, 0x06); // N_FP=0000 0110
    LCD_WriteReg(pLcdBase, HX8347_R29H, 0x06); // P_BP=0000 0110
    LCD_WriteReg(pLcdBase, HX8347_R2AH, 0x06); // P_FP=0000 0110
    LCD_WriteReg(pLcdBase, HX8347_R2CH, 0x06); // I_BP=0000 0110
    LCD_WriteReg(pLcdBase, HX8347_R2DH, 0x06); // I_FP=0000 0110
    LCD_WriteReg(pLcdBase, HX8347_R3AH, 0x01); // N_RTN=0000, N_NW=001
    LCD_WriteReg(pLcdBase, HX8347_R3BH, 0x01); // P_RTN=0000, P_NW=001
    LCD_WriteReg(pLcdBase, HX8347_R3CH, 0xF0); // I_RTN=1111, I_NW=000
    LCD_WriteReg(pLcdBase, HX8347_R3DH, 0x00); // DIV=00
    LCD_WriteReg(pLcdBase, HX8347_R3EH, 0x38); // SON=38h
    LCD_WriteReg(pLcdBase, HX8347_R40H, 0x0F); // GDON=0Fh
    LCD_WriteReg(pLcdBase, HX8347_R41H, 0xF0); // GDOF=F0h
}

//------------------------------------------------------------------------------
/// Turn on the LCD.
/// \param pLcdBase   LCD base address.
//------------------------------------------------------------------------------
void LCD_On(void *pLcdBase)
{
    // Display ON Setting
    LCD_WriteReg(pLcdBase, HX8347_R90H, 0x7F); // SAP=0111 1111
    LCD_WriteReg(pLcdBase, HX8347_R26H, 0x04); // GON=0, DTE=0, D=01
    Delay(100);
    LCD_WriteReg(pLcdBase, HX8347_R26H, 0x24); // GON=1, DTE=0, D=01
    LCD_WriteReg(pLcdBase, HX8347_R26H, 0x2C); // GON=1, DTE=0, D=11
    Delay(100);
    LCD_WriteReg(pLcdBase, HX8347_R26H, 0x3C); // GON=1, DTE=1, D=11
}

//------------------------------------------------------------------------------
/// Turn off the LCD.
/// \param pLcdBase   LCD base address.
//------------------------------------------------------------------------------
void LCD_Off(void *pLcdBase)
{
    LCD_WriteReg(pLcdBase, HX8347_R90H, 0x00); // SAP=0000 0000
    LCD_WriteReg(pLcdBase, HX8347_R26H, 0x00); // GON=0, DTE=0, D=00
}

//------------------------------------------------------------------------------
/// Set cursor of LCD srceen.
/// \param pLcdBase   LCD base address.
/// \param x          X-coordinate of upper-left corner on LCD.
/// \param y          Y-coordinate of upper-left corner on LCD.
//------------------------------------------------------------------------------
void LCD_SetCursor(void *pLcdBase, unsigned short x, unsigned short y)
{
    unsigned char x1, x2, y1, y2;

    x1 = x & 0xff;
    x2 = (x & 0xff00) >>8;
    y1 = y & 0xff;
    y2 = (y & 0xff00) >>8;
    LCD_WriteReg(pLcdBase, HX8347_R02H, x2); // column high
    LCD_WriteReg(pLcdBase, HX8347_R03H, x1); // column low
    LCD_WriteReg(pLcdBase, HX8347_R06H, y2); // row high
    LCD_WriteReg(pLcdBase, HX8347_R07H, y1); // row low
}

//------------------------------------------------------------------------------
/// Set the window size user can access.
/// \param pLcdBase   LCD base address.
/// \param x_start    X-coordinate of upper-left corner on LCD.
/// \param y_start    Y-coordinate of upper-left corner on LCD.
/// \param x_end      X-coordinate of bottom-right corner on LCD.
/// \param y_end      Y-coordinate of bottom-right corner on LCD.
//------------------------------------------------------------------------------
void LCD_SetWindow(void *pLcdBase,unsigned short x_start, unsigned short y_start,unsigned short x_end, unsigned short y_end)
{
    unsigned char x1, x2, y1, y2;

        x1 = x_start & 0xff;
        x2 = (x_start & 0xff00) >>8;
        y1 = y_start & 0xff;
        y2 = (y_start & 0xff00) >>8;
        LCD_WriteReg(pLcdBase, 0x02, x2); // column high
        LCD_WriteReg(pLcdBase, 0x03, x1); // column low
        LCD_WriteReg(pLcdBase, 0x06, y2); // row high
        LCD_WriteReg(pLcdBase, 0x07, y1); // row low

        x1 = x_end & 0xff;
        x2 = (x_end & 0xff00) >>8;
        y1 = y_end & 0xff;
        y2 = (y_end & 0xff00) >>8;
        LCD_WriteReg(pLcdBase, 0x04, x2); // column high
        LCD_WriteReg(pLcdBase, 0x05, x1); // column low
        LCD_WriteReg(pLcdBase, 0x08, y2); // row high
        LCD_WriteReg(pLcdBase, 0x09, y1); // row low
}
#endif //#ifdef BOARD_LCD_HX8347
personal git repositories of Harald Welte. Your mileage may vary