|
|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Pin | Name | Direction | Function |
| 1 | CLKP | To display | Positive clock |
| 2 | Vdd | Power | +3.0V (2.9 to 3.1V, abs max 4.0) Current draw 3.5mA.
Slightly content dependent. Appears to work OK at 3.3v. Display starts washing out below 2.6v. Voltage has no obvious effect on brightness above 3.0v. I ran it up to 4.1V with no increase in current draw. |
| 3 | CLKN | To display | Negative clock |
| 4 | Vee | Power | +1.8v (1.7 to 1.9V, abs max 4.0) 1.8mA 48MHz clock, idle. 2mA updating at 15fps. Likely to be fairly clock-rate dependent. |
| 5 | GND | 0V | |
| 6 | SYNC | From display | Vertical sync.Goes low for 530uS at 60Hz. 1.8V level |
| 7 | DP | To display | Positive data |
| 8 | Reset | To display | Active low reset, 1.8v level. No internal pullup. |
| 9 | DN | To display | Negative data |
| 10 | LED+ | Power | Backlight +ve. Backlight is 4 LEDs in series. Typical Vf 14.8V
at 16mA Backlight current is specified at typ 10.5mA, max 25mA, Vf 15.5-17.0 max over this range. Derate 25 to 5mA over 40 to 80 deg.C ambient temp. |
| 11 | GND | 0V | |
| 12 | LED- | Backlight -ve. | |
| Shield | The four corner mechanical pads on the connector are connected to GND |
This is the initialisation sequence from the datasheet.

I reduced the 250mS initial delay to 15mS with no obvious problems. I also tried not
delaying the 3.0v supply turn-on, which also appeared to work OK.
The delay between reset and clock start sequence (see below) IS needed. I tested some
shorter timings, and problems started occurring if the delay between the reset rising edge
and clock start went below about 64uS.
So the mimimum intialiation would seem to be : +3v and +1.8v on, reset low, Wait >100uS, Reset High, Wait >100uS, Clock start sequence
I couldn't easily test any constraints on powerup to reset-high time due to FPGA configuration time.
Clock startup sequence
At startup, the following sequence is needed to enable the clock receiver. This is the
same as the sequence for the data bus.
On the ipod, the clock runs continuously - I don't know if this is necessary - it may be
possible to disable the clock between commands, or even during a command between btyes -
to be tested. Non-continuous clock is an optional feature of the DSI spec. However
it did work when the clock period varied from cycle to cycle when I was testing frequency
range, so clock gaps between bytes. I've tested at clock rates down to 2MHz. Issues below
that may have been due to my test setup.
In the ipod, the clock runs at 110MHz.
The framerate is NOT derived from this clock, but from an internal oscillator.
The absolute polarity of the LVDS clock does matter - the sync byte will not
correct for wrong clock phasing.

Data packet
A packet can contain one of more commands, Only one start byte (0xB8) is required to start the packet ( i.e. not between commands). I don't know if gaps are allowed between commands within a packet - if they are, they may need a new start byte.
The data lines must stay below 0.5V during high speed (LVDS) mode. LVDS swing is
typically +/-100mV relative to a +200mV baseline.
I have found that a small positive bias was needed on the DN line on some displays - not
investigated fully.
From MIPI D-PHY spec :

Data start - entry to high speed mode

Start byte sequence

End of data packet, exit from high-speed mode
A data line transition is needed at the end of the last byte. As the last byte will be
CRC, which is ignored, a simple way to achive this would be to set the second CRC byte to
0x00 and send an extra 0xFF byte (not included in the payload byte count) to generate this
transition.

This is the hardware configuration I used to drive the display from a Lattice MACHXO2
FPGA.. The 1K pullup on DN was a last-minute fix when I found some displays didn't work -
not looked in detail at the exact effect - could just have been ground shift pulling the
line slightly negative without it.
Note I didn't use the clock output from the DDR IO cell, as this shares tristate control
with the data line, so you can't tristate the data bus without also
tristating the clock.
The sequence to enter high speed mode on the data lines (Clock is same as data) is as
follows :
LVDS tristated,DN bias and DP bias high
DP bias low
DN bias low
LVDS output enable, output low (DP=0,DN=1)

Using non-differential signals
I have done a quick test to confirm that it does work with non-differential signals, i.e. holding one of the DP/DN and CLKN/CLKP lines to a fixed level. I haven't done any optimisation on component values yet.
Command protocol
Two commands are required to initialise the display - exit sleep and display on. They can be in either order. After this, sync pulses will start and the display will show random garbage unless previously sent a frame of image data.
| Command. Hex. | Italics are the ECC byte. First byte is DSI command, listed in
DSI spec Values in bold are DCS commands interpreted by the LCD controller, liste in the DCS spec. |
| 15 11 00 25 | Exit sleep mode. datasheet reccommends waiting >120mS after this command. I suspect this is just for display voltages to settle, to avoid visible effects |
| 15 29 00 0F | Display on. |
| 15 3A 55 02 | Set 16 bits per pixel mode |
| 15 3A 77 1F | Set 24 bits per pixel mode |
| 15 36 80 12 | RGB order (for 16bpp), display bottom to top (same as AVI) |
| 15 36 88 2A | BGR order (for 24bpp AVI), display bottom to top (as AVI) |
| Other bits for command 36 : Bit 0 : Flip vertical (seems to have no effect) Bit 1 : Flip horizontal (seems to have no effect) Bit 2 : Vertical line data latch order (seems to have no effect) Bit 3 : 0: RGB,. 1: BGR Bit 4 : Display refresh order, 1 = bottom to top Bit 5 : rotate 90 deg (affects order of next display data, not current display) Bit 6 : Flip column (affects order of next display data, not current display) Bit 7 : flip row (affects order of next display data, not current display) Bits 0 to 2 may affect the display refresh order, and so could be relevant for video applications to avoid tearing effects. |
|
| 39 E1 01 0B ss < 1E0 bytes > 00 00 | Write line of 16bpp display data (480 decimal bytes). ss=0x2C for first line, 0x3C for subsequent lines 00 00 is dummy CRC - this is not checked See this list for command strings with & ECC bytes to send multiple lines |
| 39 D1 02 07 ss < 2D0 bytes > 00 00 | Write line of 24bpp display data (720 decimal bytes). ss=0x2C for first line, 0x3C for subsequent lines |
| The ipod sends the following commands prior to each frame, but they don't appear to be necessary | |
| 29 05 00 25 2A 00 00 00 EF 48 03 | Set column address. First byte pair (MS first) is the start column, second
pair the end column (0 to 239 here). 48 03 is the CRC This command should be useable to write smaller windows of the display, and would be handy for font rendering by setting the window size to the font size I couldn't get this command to work for sub-fullscreen sizes- either it is not implemented, or it checks the CRC |
| 29 05 00 25 2b 00 00 00 EF 0C 08 | Set line address, as above - also couldn't get it to work. |
| 05 2C 00 25 | Write memory start. I think this is duplicated by the 2C in the first line of the image data |
The initialisation data can be merged with display data, which is useful if data is
coming from a preformatted source where commands can be embedded along with teh display
data, e.g. FPGA playing back from SPI flash.
So the full sequence to initialise and send a frame of 16bpp data would be :
| for y = 0 to 239 <enter high speed mode> send B8 15 29 00 0F 15 11 00 25 15 36 80 12 15 3A 55 02 39 E1 01
0B if y=0 then send 2C else send 3C Send 1E0 (=480 dec) bytes of pixel data <exit high speed mode> next y |
It is possible to send more than one line per command (tested with 2 lines, coudn't do
more due to FPGA buffer size limit), but there is a 64K limit imposed by the 16 bit
payload length field.
As multiple commands can be sent in one packet, it should be possible to send a whole
frame in one packet, i.e. only entering high-speed mode at the start and exiting at the
end.
It may also be possible to just stay in high speed mode all the time, which would be
useful if the clock doesn't mind being stopped between bytes, as you wouldn;t need to do
the enter/exit high-speed mode every time . *To be tested*
Packet formats from MIPI DSI spec
SoT is the entry to high-speed mode, plue the 0xB8 start byte. EoT is a transition after the last bit, then exit from high-speed mode.
Short packet

Long packet
The checksum (actually a CRC) is ignored by the display so does not need to be calculated.

ECC calculation
ECC values are listed for the basic comamnds in the table above. For others, they can be calculated as follows
The ECC byte comprises six parity bits calculated from various bits in the header as follows :
P7=0
P6=0
P5=D10^D11^D12^D13^D14^D15^D16^D17^D18^D19^D21^D22^D23
P4=D4^D5^D6^D7^D8^D9^D16^D17^D18^D19^D20^D22^D23
P3=D1^D2^D3^D7^D8^D9^D13^D14^D15^D19^D20^D21^D23
P2=D0^D2^D3^D5^D6^D9^D11^D12^D15^D18^D20^D21^D22
P1=D0^D1^D3^D4^D6^D8^D10^D12^D14^D17^D20^D21^D22^D23
P0=D0^D1^D2^D4^D5^D7^D10^D11^D13^D16^D20^D21^D22^D23
Here is some Visual Basic code (sorry!) to calculate the ECC.
It takes a 3 byte string of binary values for the packet header, and returns a 4 byte
string including the ECC
| Dim eccreg As Long Private Function add_ecc(s As String) As String |
Here is some C code
| char parity (unsigned long val) { // calc XOR parity bit of all '1's in 24 bit value unsigned long i,p; p=0;for(i=0;i!=24;i++) {p^=val;val>>=1;} return(p&1); } unsigned long add_ecc(unsigned long cmd) {// add ecc byte to b29-24 of 24 bit command packet (lsbyte first) cmd&=0x00ffffff; if(parity(cmd & 0b111100010010110010110111)) cmd|=0x01000000; if(parity(cmd & 0b111100100101010101011011)) cmd|=0x02000000; if(parity(cmd & 0b011101001001101001101101)) cmd|=0x04000000; if(parity(cmd & 0b101110001110001110001110)) cmd|=0x08000000; if(parity(cmd & 0b110111110000001111110000)) cmd|=0x10000000; if(parity(cmd & 0b111011111111110000000000)) cmd|=0x20000000; return(cmd); } void sendlcdcmd(unsigned long l) { // send command, sends MSByte first for readability // e.g. exit sleep 0x151100 l=((l&0xff)<<16) | (l&0xff00) | ((l&0xff0000)>>16); // reverse bytes to lsbyte first order l=add_ecc(l); sendpmp(l);sendpmp(l>>8);sendpmp(l>>16);sendpmp(l>>24); } |
Content creation
I highly reccommend Virtualdub
for creating uncompressed AVIs for playback. It supports oddball output resolutions, and
nonstandard formats like 1bppp mono and 16 bit RGB.
Virtualdub's 16 bit 565 format matches the input format for this LCD. 24 bit RGB matches
the LCD if the BGR order bit is set to 1.
To improve the quality of images displayed as 16bpp, I have written this filter for virtualdub,
which uses dithering to improve greyscaling, avoiding banding on colour gradients etc.
To format an arbitary video file :
Load file into virtualdub (accepts AVI,MPEG and bitmap sequences)
Video->filters->Add resize, set to 240x240 pixels.
Video->Colour Depth->16 bit RGB (565)
Audio -> No audio
Video->Compression->No compression
Set in and out markers if you only want a section of the file
File->Save as AVI
Parsing AVI files
Uncompressed AVIs are fairly easy to handle - after parsing the header, you get packed
frames of data, with an 8 byte header between each frame. The frames are in a format
suitable for sending directly to the display with no further processing.
Here is some sample code in C and VB6
Dimensions
List of commands with ECC for different numbers of lines (16bpp mode)
Lines (bytes = lines*480+1) : write command including ECC
| 01 : 39 E1 01 0B 02 : 39 C1 03 10 03 : 39 A1 05 15 04 : 39 81 07 0E 05 : 39 61 09 1F 06 : 39 41 0B 04 07 : 39 21 0D 01 08 : 39 01 0F 1A 09 : 39 E1 10 25 10 : 39 C1 12 3E 11 : 39 A1 14 3B 12 : 39 81 16 20 13 : 39 61 18 31 14 : 39 41 1A 2A 15 : 39 21 1C 2F 16 : 39 01 1E 34 17 : 39 E1 1F 2A 18 : 39 C1 21 0D 19 : 39 A1 23 3C 20 : 39 81 25 13 21 : 39 61 27 0E 22 : 39 41 29 19 23 : 39 21 2B 28 24 : 39 01 2D 07 25 : 39 E1 2E 2B 26 : 39 C1 30 23 27 : 39 A1 32 12 28 : 39 81 34 3D 29 : 39 61 36 20 30 : 39 41 38 37 31 : 39 21 3A 06 32 : 39 01 3C 29 |
33 : 39 E1 3D 37 34 : 39 C1 3F 2C 35 : 39 A1 41 16 36 : 39 81 43 0D 37 : 39 61 45 24 38 : 39 41 47 3F 39 : 39 21 49 02 40 : 39 01 4B 19 41 : 39 E1 4C 01 42 : 39 C1 4E 1A 43 : 39 A1 50 38 44 : 39 81 52 23 45 : 39 61 54 0A 46 : 39 41 56 11 47 : 39 21 58 2C 48 : 39 01 5A 37 49 : 39 E1 5B 29 50 : 39 C1 5D 06 51 : 39 A1 5F 37 52 : 39 81 61 10 53 : 39 61 63 0D 54 : 39 41 65 22 55 : 39 21 67 13 56 : 39 01 69 04 57 : 39 E1 6A 28 58 : 39 C1 6C 07 59 : 39 A1 6E 36 60 : 39 81 70 3E 61 : 39 61 72 23 62 : 39 41 74 0C 63 : 39 21 76 3D 64 : 39 01 78 2A |
65 : 39 E1 79 34 66 : 39 C1 7B 2F 67 : 39 A1 7D 2A 68 : 39 81 7F 31 69 : 39 61 81 1C 70 : 39 41 83 07 71 : 39 21 85 02 72 : 39 01 87 19 73 : 39 E1 88 39 74 : 39 C1 8A 22 75 : 39 A1 8C 27 76 : 39 81 8E 3C 77 : 39 61 90 32 78 : 39 41 92 29 79 : 39 21 94 2C 80 : 39 01 96 37 81 : 39 E1 97 29 82 : 39 C1 99 3E 83 : 39 A1 9B 0F 84 : 39 81 9D 20 85 : 39 61 9F 3D 86 : 39 41 A1 1A 87 : 39 21 A3 2B 88 : 39 01 A5 04 89 : 39 E1 A6 28 90 : 39 C1 A8 3F 91 : 39 A1 AA 0E 92 : 39 81 AC 21 93 : 39 61 AE 3C 94 : 39 41 B0 34 95 : 39 21 B2 05 96 : 39 01 B4 2A |
97 : 39 E1 B5 34 98 : 39 C1 B7 2F 99 : 39 A1 B9 12 100 : 39 81 BB 09 101 : 39 61 BD 20 102 : 39 41 BF 3B 103 : 39 21 C1 01 104 : 39 01 C3 1A 105 : 39 E1 C4 02 106 : 39 C1 C6 19 107 : 39 A1 C8 24 108 : 39 81 CA 3F 109 : 39 61 CC 16 110 : 39 41 CE 0D 111 : 39 21 D0 2F 112 : 39 01 D2 34 113 : 39 E1 D3 2A 114 : 39 C1 D5 05 115 : 39 A1 D7 34 116 : 39 81 D9 23 117 : 39 61 DB 3E 118 : 39 41 DD 11 119 : 39 21 DF 20 120 : 39 01 E1 07 121 : 39 E1 E2 2B 122 : 39 C1 E4 04 123 : 39 A1 E6 35 124 : 39 81 E8 22 125 : 39 61 EA 3F 126 : 39 41 EC 10 127 : 39 21 EE 21 128 : 39 01 F0 29 |
|