DDC2 interface – crafting your own EDID

Folowing on my Building a VGA monitor – DDC2 interface tests post, I went on to verify the information found on the Wikipedia page on EDID. I put together the specs of my monitor project, and encoded them accordingly. After shaking out all the bugs Ubuntu picked it up:

My EDID decoded by Ubuntu

Mind you, that the only thing I’m currently connecting to a VGA port is an EEPROM, with contents as specified few paragraphs below.

The still virtual monitor is specified to be 10×15 cm, and expects only to be used with 640×480@60Hz, which is the only option that Ubuntu dialogue is willing to serve it with, which is my great satisfaction.

The data I put together, as seen in Xorg log:

(II) intel(0): EDID for output VGA1
(II) intel(0): Manufacturer: FTB  Model: 100  Serial#: 16777216
(II) intel(0): Year: 2011  Week: 12
(II) intel(0): EDID Version: 1.2
(II) intel(0): Analog Display Input,  Input Voltage Level: 0.700/0.300 V
(II) intel(0): Sync:  Separate
(II) intel(0): Max Image Size [cm]: horiz.: 17  vert.: 13
(II) intel(0): Gamma: 2.20
(II) intel(0): No DPMS capabilities specified; Monochorome/GrayScale Display
(II) intel(0): Default color space is primary color space
(II) intel(0): GTF timings supported
(II) intel(0): redX: 0.000 redY: 0.000   greenX: 0.000 greenY: 0.000
(II) intel(0): blueX: 0.000 blueY: 0.000   whiteX: 0.000 whiteY: 0.000
(II) intel(0): Supported established timings:
(II) intel(0): 640x480@60Hz
(II) intel(0): Manufacturer's mask: 0
(II) intel(0): Supported standard timings:
(II) intel(0): #0: hsize: 640  vsize 480  refresh: 60  vid: 16433
(II) intel(0): Monitor name: flipthatbit01
(II) intel(0): EDID (in hex):
(II) intel(0):  00ffffffffffff001a82000100000001
(II) intel(0):  0c15010208110d780500000000000000
(II) intel(0):  00000020000031400101010101010101
(II) intel(0):  010101010101000000fc00666c697074
(II) intel(0):  68617462697430310000000000000000
(II) intel(0):  00000000000000000000000000000000
(II) intel(0):  00000000000000000000000000000000
(II) intel(0):  0000000000000000000000000000000a
(II) intel(0): EDID vendor "FTB", prod id 256
(II) intel(0): Printing DDC gathered Modelines:
(II) intel(0): Modeline "640x480"x0.0   25.18  640 656 752 800  480 490 492 525 -hsync -vsync (31.5 kHz)
(II) intel(0): Not using default mode "640x350" (vrefresh out of range)
[...]
(II) intel(0): Not using default mode "2048x1536" (vrefresh out of range)
(II) intel(0): Not using default mode "1024x768" (doublescan mode not supported)
(II) intel(0): Printing probed modes for output VGA1
(II) intel(0): Modeline "640x480"x60.0   25.20  640 656 752 800  480 490 492 525 -hsync -vsync (31.5 kHz)
(II) intel(0): Modeline "640x480"x59.9   25.18  640 656 752 800  480 489 492 525 -hsync -vsync (31.5 kHz)
(II) intel(0): Modeline "640x480"x59.9   25.18  640 656 752 800  480 490 492 525 -hsync -vsync (31.5 kHz)

I set all the fields accordingly, the monitor is being detected as mono, with separate syncs, no power saving (for now). I set the manufacturer to FTB for the blog name, similarly – the model name.

Accrding to E-EDID VESA Implementation Guide (useful doc for comparison against the Wiki article) to be EDID 1.3 compliant I would have to provide detailed timing description. I would have to fill at least three obligatory descriptor blocks toward the end of the data, but since my monitor just supports one mode which is an industry standard I decided to skip it and set my version to 1.2. The only descriptor block I’m providing is the monitor name, which I set to “flipthatbit01″.

I created few shell scripts on the way that you might find useful when creating your own EDIDs:

This “one-liner” computes the checksum of the EDID data contained in the data.txt file. Expected data.txt file format is such that the last line should contain an empty “checksum” byte, for head -n -1 to skip. This way the data.txt with an updated checksum can be used by another script to writhe it’s contents to EEPROM. The definition of the checksum byte from Wikipedia is “such that the sum of all 128 bytes equals 00h”. The computation is not self explanatory, but I preferred brevity over clarity for the ease of use.

head -n -1 data.txt | fold -2 | perl -e '
while (<STDIN>) {
$i+=hex($_);
}
$rest = 256 - ($i-int($i/256)*256);
printf("%x\n", $rest);'

And I used this script to write the contents of the data.txt file to the EEPROM:

#! /bin/sh

i=0

for d in `fold -2 data.txt`; do
ih=`echo -n $i | awk '{printf "%x", $1}'`
i2cset -y 0 0x50 0x$ih 0x$d b
i=$(($i+1))
done

Remember to re-calculate the checksum after any changes to the data.txt file, prior to writing it to the EEPROM. I once wrote the data with a wrong checksum, and on restarting X, the i2c bus got disabled, and in the dmesg I could see some warnings from one of the kernel modules.
Here’s my data.txt that gave the above results:

00ffffffffffff00
1a82
0001
00000001
0c15
0102
08110d7805
00000000000000000000
20
00
00
31400101010101010101010101010101
000000fc00666c6970746861746269743031
000000000000000000000000000000000000
000000000000000000000000000000000000
000000000000000000000000000000000000
00
0a

And in case you’d care to write your own EDID, perhaps you’ll find this Excel sheet handy: EDID data breakdown and some explanation (I wrote it in OpenOffice Calc, and it’s pure text). It contains the data broken down as much as I needed to understand what’s going on inside.

Now on to the signal processing. I my next post on this subject I will describe my progress on the display of the VGA image data using a Xilinx CPLD.