A Circular Reference

Adventures of a vagabond electron.

PIC32 Drivers for ILI9486L and HX8347G TFT Controllers

| Comments

Introduction

This post builds upon the previous one, and expounds some of the details of the communication interface between the PIC32 Parallel Master Port module and LCD panel controllers – ILI9486L and HX8347G.

Implementation

Both the display controllers support the 16 bit Intel 8080 Mode with 16BPP. The Intel 8080 mode defines 4 control lines in addition to the 16 bit Data Bus and that is what I am using. The control lines are – RDS (Read Strobe, WRS (Write Strobe), Data/Command (D/C#) Select (also called Register Select). As is evident from the names, the Read and Write strobes are used to latch the data on the bus. So to Write data on the bus, the PMP loads data (D0 – D16) and then pulls the WRS line low, when the WRS is pulled High, the display controller latches the data on the bus. Similarly for a Read, the Host PMP pulls the RDS line Low, the controller outputs data on the bus and the host reads this data on the RDS Low to High transition. The D/C# line is used to indicate to the controller whether the master is sending a command or writing/reading data.

If you are using the PIC32′s PMP, the RDS and WRS strobes are generated automatically by the hardware when you Read and Write the PMP data register. Only the D/C# and CS lines need to be generated in the driver. Typical Write and Read operations with the PMP looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Delays execution for PMP cycle time.
#define PMPWaitBusy()   while(PMMODEbits.BUSY);

//Writes command.
void WriteCommand(cmd)
{
    CS_LAT_LCD = 0;
    DC_LAT_BIT = 0;  // To write data set this bit to 1       
    PMDIN1 = cmd; // Just writing data to PMDIN1 causes the WRS to be generated and data to be loaded on the bus        
    PMPWaitBusy();
    CS_LAT_LCD = 1;
}

UINT16 ReadData(cmd)
{
    CS_LAT_LCD = 0;
    DC_LAT_BIT = 1;
    ret = PMDIN1; // The first read gives you old data on the bus, need to do a second read to get the new data        
    PMPWaitBusy();
    ret = PMDIN1;
    PMPWaitBusy();
    CS_LAT_LCD = 1;
return (ret);
}

The next task is to write a pixel in the display controller GRAM. HX8342 defines the following table for writing pixel data in the 16 bit mode:

image

What this indicates is that the color depth is controlled by setting the register 0x17 to 3, 5 6 or 7. We use 65K so we set it at 0x05. The command 0x22 is the RAMWR command which should be followed with the 16BPP data. The pixel address is set by manipulating the Start Column and Start Page registers as mentioned in the introductory post. So PutPixel on HX8347 looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void PutPixel(short x, short y, UINT16 color)
{
CS_LAT_BIT = 0;
// 1. Adjust the start column and page registers
WriteCommand(0x02);
WriteParameter(((WORD_VAL) (WORD) x).v[1]);
WriteCommand(0x03);
WriteParameter(((WORD_VAL) (WORD) x).v[0]);
WriteCommand(0x06);
WriteParameter(((WORD_VAL) (WORD) y).v[1]);
WriteCommand(0x07);
WriteParameter(((WORD_VAL) (WORD) y).v[0]);

WriteCommand(0x22); // send the RAMRW command
WriteData(color);
CS_LAT_BIT = 1;
}

This can be extended to implement GetPixel and so on. In the case of IL9486 the SC/SP values are stored in one register, so you just need to send one command followed by the “parameters”. PutPixel looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void PutPixel(SHORT x, SHORT y, UINT16 color)
{

   // modify the StartPage and StartColumn values
    CS_LAT_BIT = 0; // select device
   // send command to modify sc and sp registers
    SetCommand(0x2A);
    // send data
    WriteParameter(((WORD_VAL) (WORD) x).v[1]);
    WriteParameter(((WORD_VAL) (WORD) x).v[0]);
    WriteParameter(((WORD_VAL) (WORD) y).v[1]);
    WriteParameter(((WORD_VAL) (WORD) y).v[0]);
    // Now update memory
    SetCommand(0x2C); // command for memory
    WriteData(color);
    CS_LAT_BIT = 1;
}

Finally, the display orientation depends on the setting of some bits usually denoted by MX, MY and MV. You should be able to see their significance from your controller datasheet..

Source code is here: HX8347G ILI9486L

Comments