The Display
If you need more information please take a look at the library sourcecode.
Please also note that everything explained here is already done for you by the library. If you just want to use the panel click here: [Quickstart]
On this page:
The LCD display is controlled via an UART and a LVDS (Data + Clock) connection simultaniously. (See pinout.) The LVDS interface is mainly used to load image data into the RAM of the display, the image data can then be displayed at different position and with different drawing modes. The UART interface is mainly used to execute small commands like backlight control and to announce data transfers over LVDS. Since the chip of the frontpanel does all the processing for drawing there is nearly no load on the system that the frontpanel is connected to as soon as the data has been loaded into RAM.
The settings for the LCD UART are as follows:
baudrate | bits | paritybit | stopbits |
---|---|---|---|
57600 | 8 | Even | 1 |
Commands for the LCD UART consist most of the time of 4 bytes, sometimes of 2 bytes. The panel acknowledges normal commands with 0x46, successful LVDS data transfers are acknowledged with 0x47 via UART.
command | command bytes | description |
---|---|---|
send LCD to standby 1/5 | 0x03,0x25,0x00,0x00 | backlight off |
send LCD to standby 2/5 | 0x03,0x1e,0x08,0x80 | |
send LCD to standby 3/5 | 0x03,0x1e,0x80,0x40 | |
send LCD to standby 4/5 | 0x03,0x1e,0x80,0xC0 | Display black/off |
send LCD to standby 5/5 | 0x03,0x0D,0x00,0x00 | |
show display buffer 0 | 0x03,0x09,0x00,0x00 | |
show display buffer 1 | 0x03,0x09,0x00,0x01 | |
backlight on | 0x03,0x25,0x00,0x02 | |
backlight off | 0x03,0x25,0x00,0x00 | |
set data destination | 0x03,0x02,0x00,0x06 | tells the panel we are going to send the destination-adress (in the ram of the panel) for the next image data transfer over lvds |
end command | 0x03,0x02,0x00,0x00 | seems to end command sequences involving image transfers |
announce image data | 0x03,0x02,0x00,0x04 | tells the panel we will send image data over lvds |
announce layout data | 0x03,0x02,0x00,0x05 | tells the panel we are going to send the objects to be drawn over lvds |
commit(?) | 0x03,0x27,0x00,0x24 | some kind of commit? is used directly before pageflip |
status query (?) | 0x0c,0x27 | kind of a status query(?), display responds with some bytes via UART |
reset UART comm. | 0xfe,0xdc | Seems to reset communication/synchronization over UART, Panels responds with 0x46 |
The following sequence of bytes is send to the display over UART to intialize it:
~~~~~~~~~~~~~~~~
byte UART_InitDisplay[] FLASH ={
//this needs to be cleaned up a bit as it
//contains displaying of images which is not really needed for startup
0x3, 0x25, 0x0, 0x0,
0x3, 0x24, 0x0, 0x0,
0x3, 0x1D, 0x11, 0x1F,
0x3, 0x0, 0x0, 0x2,
0x3, 0xE, 0x0, 0x3,
0x3, 0xF, 0x0, 0x2,
0x3, 0x10, 0xF, 0xBF,
0x3, 0x15, 0xEF, 0x7,
0x3, 0x11, 0x40, 0xF9,
0x3, 0x16, 0x0, 0x3,
0x3, 0x17, 0x0, 0xEF,
0x3, 0x14, 0x27, 0x45,
0x3, 0x19, 0x0, 0x0,
0x3, 0x3, 0x0, 0x0,
0x3, 0x4, 0x0, 0x20,
0x3, 0x5, 0x2, 0x7F,
0x3, 0x6, 0x0, 0x2,
0x3, 0x7, 0x60, 0x0,
0x3, 0x8, 0x2, 0x7F,
0x3, 0x1A, 0x0, 0x0,
0x3, 0x1B, 0xF8, 0x1F,
0x3, 0x2, 0x0, 0x0,
0x3, 0x26, 0x0, 0x0,
0x3, 0x2, 0x0, 0x6,
0x3, 0x2, 0x0, 0x0,
0x3, 0x2, 0x0, 0x5,
0xC, 0x27,
0x3, 0x2, 0x0, 0x0,
0xC, 0x27,
0x3, 0x27, 0x0, 0x24,
0x3, 0x2, 0x0, 0x6,
0x3, 0x2, 0x0, 0x0,
0x3, 0x2, 0x0, 0x5,
0xC, 0x27,
0x3, 0x2, 0x0, 0x0,
0xC, 0x27,
0x3, 0x27, 0x0, 0x24,
0x3, 0x2, 0x0, 0x6,
0x3, 0x2, 0x0, 0x6,
0x3, 0x2, 0x0, 0x0,
0x3, 0x2, 0x0, 0x4,
0x3, 0x2, 0x0, 0x0,
0x3, 0x9, 0x0, 0x0,
0x3, 0xD, 0x0, 0x0,
0x3, 0xD, 0x0, 0x1,
0x3, 0x1E, 0x0, 0x80,
0x3, 0x1E, 0x84, 0xC0,
0x3, 0x1E, 0xF7, 0xC0,
0x3, 0x1E, 0x1, 0x0,
0x3, 0x1E, 0x81, 0xC0,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x1, 0x80,
0x3, 0x1E, 0x85, 0x40,
0x3, 0x1E, 0x87, 0x40,
0x3, 0x1E, 0x5, 0x80,
0x3, 0x1E, 0xE8, 0x40,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x6, 0x0,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x82, 0xC0,
0x3, 0x1E, 0x6, 0x80,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x87, 0xC0,
0x3, 0x1E, 0x7, 0x0,
0x3, 0x1E, 0x97, 0x40,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x8, 0x80,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x9, 0x0,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0xAC, 0x40,
0x3, 0x1E, 0x9, 0x80,
0x3, 0x1E, 0x88, 0x40,
0x3, 0x1E, 0x81, 0x40,
0x3, 0x1E, 0xB, 0x0,
0x3, 0x1E, 0xCF, 0xC0,
0x3, 0x1E, 0xC6, 0x40,
0x3, 0x1E, 0xB, 0x80,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x82, 0x40,
0x3, 0x1E, 0xF, 0x0,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x14, 0x0,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x83, 0x40,
0x3, 0x1E, 0x15, 0x0,
0x3, 0x1E, 0x80, 0xC0,
0x3, 0x1E, 0xC3, 0xC0,
0x3, 0x1E, 0x18, 0x0,
0x3, 0x1E, 0x81, 0x40,
0x3, 0x1E, 0x82, 0x40,
0x3, 0x1E, 0x18, 0x80,
0x3, 0x1E, 0x80, 0xC0,
0x3, 0x1E, 0x83, 0xC0,
0x3, 0x1E, 0x19, 0x0,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x19, 0x80,
0x3, 0x1E, 0x80, 0xC0,
0x3, 0x1E, 0x82, 0xC0,
0x3, 0x1E, 0x1A, 0x0,
0x3, 0x1E, 0x83, 0xC0,
0x3, 0x1E, 0x83, 0xC0,
0x3, 0x1E, 0x1A, 0x80,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x83, 0x40,
0x3, 0x1E, 0x1B, 0x0,
0x3, 0x1E, 0x81, 0x40,
0x3, 0x1E, 0x82, 0xC0,
0x3, 0x1E, 0x1B, 0x80,
0x3, 0x1E, 0x83, 0xC0,
0x3, 0x1E, 0x83, 0xC0,
0x3, 0x1E, 0x1D, 0x0,
0x3, 0x1E, 0x8F, 0xC0,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x1D, 0x80,
0x3, 0x1E, 0x80, 0x40,
0x3, 0x1E, 0x80, 0x40,
0x3, 0xD, 0x0, 0x3,
0x3, 0x2, 0x0, 0x6,
0x3, 0x2, 0x0, 0x0,
0x3, 0x2, 0x0, 0x4,
0x3, 0x2, 0x0, 0x0,
0x3, 0x2, 0x0, 0x6,
0x3, 0x2, 0x0, 0x0,
0x3, 0x2, 0x0, 0x4,
0x3, 0x2, 0x0, 0x0,
0x3, 0x2, 0x0, 0x6,
0x3, 0x2, 0x0, 0x0,
0x3, 0x2, 0x0, 0x4,
0x3, 0x2, 0x0, 0x0,
0x3, 0x2, 0x0, 0x6,
0x3, 0x2, 0x0, 0x0,
0x3, 0x2, 0x0, 0x4,
0x3, 0x2, 0x0, 0x0,
0x3, 0x2, 0x0, 0x6,
0x3, 0x2, 0x0, 0x0,
0x3, 0x2, 0x0, 0x5,
0xC, 0x27,
0x3, 0x2, 0x0, 0x0,
0xC, 0x27,
0x3, 0x27, 0x0, 0x24,
0x3, 0x9, 0x0, 0x1,
0x3, 0xD, 0x0, 0x3,
0x3, 0x25, 0x0, 0x2,//BL on
};
~~~~~~~~~~~~~~~~~~
The frequency that is used by the printer for LVDS is about 45 MHz but lower frequencies also work. (Tested with ~18 MHz.) A usable LVDS driver chip to connect the display to low voltage TTL ouputs like on the olimexino/maple is the DS90LVDS049 that is now called SN65LVDS049 (Texas Instruments). Any other LVDS driver will probably also work.
The idle state of the both LVDS channels (clock+data) is interpreted as a logical 0, data is aquired with the falling edge of the clock line.
All data transfers over LVDS are announced via UART first. Successful transfers are acknowledged wit 0x47 via UART.
The data that is sent over LVDS consists of packets starting with a size followed by the data as 16 bit words and ending with the checksum. The size, the data words and the checksum are all framed with a leading 1 and a trailing 0. The most significant bits are sent first. The packets as a whole always start with 3 bytes 0xff without framing followed by a zero. After this the size of the data to be send minus one is sent twice as a 20 bit integer with framing. After that the data is sent as 16 bit words with framing. After the last data word a checksum is sent as 16 bit integer with framing. The checksum is calculated as a 16 bit int by adding all data fields ("real" data plus two times the size field) with the resulting overflows. The packet ends with zeros. (About 5 bytes or until the display acknowledges with 0x47)
So an LVDS packet will in general look like this:
11111111111111111111111101(20 bit Size n-1)01(20 Bit Size n-1)01(Data 1)01(Data 2)0...1(Data n)01(16 bit Checksum)00000000....
For more detailed info take a look at the startPacket(),sendWord() and endPacket() functions in the library source code.
The destination adress packet is sent over LVDS after it has been announced over UART by 0x03,0x02,0x00,0x06 (set data destination). It sets the adress of the RAM where the next arriving image data will be stored. The words to be sent are as follows:
1. 0x0a
2. most significant 16 bits of address
3. 0x0b
4. least significant 16 bits of address
5. 0x0c
6. 0x27f
7. 0x18
8. 0x280
9. 0x27
10. 0x3f
It is unknown what the other words in the packet do.
The packet is acknowledged over UART with 0x47 and is usually followed by the command 0x03,0x02,0x00,0x00 (end command) over UART.
Image data is announced with the command 0x03,0x02,0x00,0x04 (announce image data) over UART. The arriving data will be written to the RAM adress that was previously set by the destination address packet. Every 16 bit word that is send corresponds to one pixel, the pixel data is sent in RGB565 format (5 bit red, 6 bit green, 5 bit blue). The resolution and the position of the image on the screen are determined later via the layout packets. The image data packets just write data to RAM.
The packet is acknowledged over UART with 0x47 and is usually followed by the command 0x03,0x02,0x00,0x00 (end command) over UART.
The layout packets are announced by 0x03,0x02,0x00,0x05 (announce layout data) over UART. The layout packets basically instruct the display to copy data that has been previously loaded to RAM to one of the display buffers, so it can be displayed when the buffer is swapped the next time. For this different draw modes can be used like transparency/overlay and such.
Every "screenobject" to be copied consists of 9 16-bit words, which depend on things like resolution and which buffer is in use.The objects are drawn to the screen buffer in the same order in which they arrive and the packet ends with 9 16-bit words of value 0.
So a layout packet will consist of the following 16 bit words:
Object1_Word1,Object1_Word2,....,Object1_Word9,
Object2_Word1,Object2_Word2,....,Object2_Word9,
....
ObjectN_Word1,ObjectN_Word2,....,ObjectN_Word9,
0,0,0,0,0,0,0,0,0
The 9 16-bit words per object have the following meaning:
1. drawmode (see below)
2. most significant 16 bits of RAM address of image data
3. least significant 16 bits of RAM address of image data
4. image width multiplied with 2
5. most significant 16 bits of adress to write to (see below)
6. least significant 16 bits of adress to write to (see below)
7. 0x280
8. image width multiplied by 2 minus 1
9. image height minus 1
The address to write to is calculated by:
MemPosition = current_buffer_start + (yposition*320+xposition)*2
.
Where current_buffer_start is the start address of the display buffer to write to.
The currently known draw modes and adresses are as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/ Draw Modes for the Display, there are certainly some more,
be free to fool around with these, if we know more about these modes, maybe we
can use a macro instead to set the parameters more individually /
/ normal mode,all pixels are drawn, no fancy stuff /
/ Magenta pixels are not drawn /
/ Image is transparent /
/ Image is transparent /
/ Image is transparent + Magenta pixels are not drawn/
/ Image is transparent + Magenta pixels are not drawn/
/Start address of the usable RAM in the Frontpanel/
/ Last address of the usable RAM in the Frontpanel, currently unknown/
/where the memory address for the two screenbuffer starts/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The packet is acknowledged with 0x47. After that usually the display status is checked and the display seems to need some time to execute the commands needed for drawing. For details on this see "Drawing To The LCD" on this page.
After that the image data is visible if the buffer that has been written to is displayed via the corresponding UART command.
So after the basic communication with the display has been explained above this section explains how a typical image is drawn to the display step by step.
First the display needs to intialised as explained above. A reset of the UART via the appropriate command before intialisation is not necessary but recommended. (only after hard reset)
After that the currently displayed buffer is set via UART to the one that will not be used for drawing, so there will be no flickering screen while the data is copied later.
To see the buffer you have just written to just send "show display buffer 0" (0x03,0x09,0x00,0x00) or "show display buffer 1" (0x03,0x09,0x00,0x01) over UART and wait for acknowledge (0x46).
You can also draw directly to the currently displayed buffer if you want to see the data copied directly. (Not recommended for normal use because this causes flickering while writing to the buffer.)
If you need more information please take a look at the library sourcecode.