Connector pinout. Mating connector is Molex 503548-1220. (Connector on display is
503552-1220)
View looking at rear of mated connector
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 0025
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 000F
Display on.
15 3A 5502
Set 16 bits per pixel mode
15 3A 771F
Set 24 bits per pixel mode
15 36 8012
RGB order (for 16bpp), display bottom to top (same as AVI)
15 36 882A
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 0Bss < 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 07ss < 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 252A 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 252b 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 :
Send 1E0 (=480 dec) bytes of pixel data
Send 00 00 FF ; dummy checksum plus data-end transition
<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 :
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
Dim p0 As Byte
eccreg = Asc(Mid$(s, 1, 1)) Or (CLng(Asc(Mid$(s, 2, 1))) * 256) Or (CLng(Asc(Mid$(s, 3,
1))) * 65536)
p0 = 0
If ((gb(10) + gb(11) + gb(12) + gb(13) + gb(14) + gb(15) + gb(16) + gb(17) + gb(18) +
gb(19) + gb(21) + gb(22) + gb(23)) And 1) = 1 Then p0 = p0 Or 32
If ((gb(4) + gb(5) + gb(6) + gb(7) + gb(8) + gb(9) + gb(16) + gb(17) + gb(18) + gb(19) +
gb(20) + gb(22) + gb(23)) And 1) = 1 Then p0 = p0 Or 16
If ((gb(1) + gb(2) + gb(3) + gb(7) + gb(8) + gb(9) + gb(13) + gb(14) + gb(15) + gb(19) +
gb(20) + gb(21) + gb(23)) And 1) = 1 Then p0 = p0 Or 8
If ((gb(0) + gb(2) + gb(3) + gb(5) + gb(6) + gb(9) + gb(11) + gb(12) + gb(15) + gb(18) +
gb(20) + gb(21) + gb(22)) And 1) = 1 Then p0 = p0 Or 4
If ((gb(0) + gb(1) + gb(3) + gb(4) + gb(6) + gb(8) + gb(10) + gb(12) + gb(14) + gb(17) +
gb(20) + gb(21) + gb(22) + gb(23)) And 1) = 1 Then p0 = p0 Or 2
If ((gb(0) + gb(1) + gb(2) + gb(4) + gb(5) + gb(7) + gb(10) + gb(11) + gb(13) + gb(16) +
gb(20) + gb(21) + gb(22) + gb(23)) And 1) = 1 Then p0 = p0 Or 1
add_ecc = s + Chr$(p0)
End Function
Function gb(bit As Long)
gb = (eccreg \ (2 ^ bit)) And 1
End Function
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