Building a VGA monitor – DDC2 interface tests

I wanted to see if adding Display Data Channel information to my monitor project wasn’t too hard to implement. DDC2 is basically a standard I²C bus that video cards use to find out what kind of monitor is connected. I found out that the card reads the info from the I²C address 0x50. I did a quick lookup on the addresses of the I²C EEPROMs, and they all seemed to support this address. I checked my electronic parts and found 24LC16B 16kbit EEPROM in DIP package. This prompted a quick test to verify the theory.

I found out that under Ubuntu Linux, /var/log/Xorg.log contains the hex dump of the EDID (which is the data carried over DDC2, containing information about supported screen resolutions and so on). For example my Xorg.0.log on contains:

clock: 108.0 MHz   Image Size:  376 x 301 mm [...]
Monitor name: DELL 1907FP [...]
EDID (in hex):
   00ffffffffffff0010ac144032303042
   0e1001030e261e78ee6875a25a499f23
   135054a54b00714f8180010101010101
   010101010101302a009851002a403070
   1300782d1100001e000000ff00434332
   3838363433423030320a000000fc0044
   454c4c203139303746500a20000000fd
   00384c1e510e000a2020202020200084
EDID vendor "DEL", prod id 16404

So what I wanted to find out, was: if I wrote that to an EEPROM, and connect it to a VGA card, would the card think there is a Dell monitor on that port?

I first decided to test my old trusted I²C connector I soldered to the DDR RAM port on the keymaster‘s motherboard (more info on how to do similar thing can be found in Hardware Hacking section of the lm_sensors page). I dusted off an I²C-controlled 7-segment LED display and plugged it in. Issued modprobe i2c-dev as root, and using i2cset (of lm_sensors package) I was able to write to the display ok.

I2C-controlled 7-segment display

So I soldered some wires to my EEPROM, and replaced the display with it. I wrote 0xa5 to the first byte:

keymaster ~ # i2cset -y 2 0x50 0x00 0xa5
No size specified (using byte-data access)
Value 0xa5 written, readback matched
keymaster ~ # i2cget -y 2 0x50 0x00
0xa5

Despite the reassuring message, I read it back explicitly to make sure. So far so good.

I put the hexdump I obtained from the Xorg.log into data.txt file and sketched a small script:

#! /bin/bash

for byte in `fold -2 data.txt`
do
 hex=`printf "%x\n" $i`
 echo $hex $byte
 i2cset -y 2 0x50 0x$hex 0x$byte b
 let 'i=i+1'
done

Surprisingly enough running it resulted in a lot of success:

0x0 0x00
Value 0x00 written, readback matched
0x1 0xff
Value 0xff written, readback matched
[...]
0x7F 0x84
Value 0x84 written, readback matched

So I made use of the SDA and SCL pins I left for “future purposes” on my handy VGA RGB to Mono converter PCB, and connected the EEPROM there.

VGA adapter board with I2C

Imagine my surprise, when after I connected the VGA output of my test laptop to my board and restarting X, I wasn’t able to see the XDM login window, as it automatically appeared on the invisible Dell display :) . I logged from another machine to make sure the Xorg.log looks the same as with the real display, and the contents matched very nicely.

Next thing will be to alter the EEPROM contents to reflect the real capabilities of the display I will be connecting. So far I have found an easier way to write to the EEPROM – a direct one, straight from the VGA port. For more information, see: Interfacing I2c the easy way.

Update:

I successfully computed my own EDID and wrote it to an EEPROM. My OS detected the chip and my virtual monitor, for more details see: DDC2 interface – crafting your own EDID.