Latest news: September 25, 2008
WinI2C/DDC Lite v3.21 released!
September 24, 2008
WiFi-Manager v4.5 released!
September 15, 2008
Advanced WiFi-Manager v3.0 released!
September 14, 2008
WinI2C/DDC v3.21 released!
August 27, 2008
WinI2C/DDC Lite v3.20 released!
August 21, 2008
WinI2C/DDC v3.20 released!
| | |
WinI2C/DDC - Getting monitor information
Contents
Introduction
WinI2C/DDC library provides an easy way to enumerate available monitors and directly get their EDID (extended display identification data).
EDID describes monitor's capabilites, such as supported resolutions, manufacturer name, timings supported by the display, display size, etc.
This article explains how to work with WinI2C/DDC, read EDID v1 and parse it in Visual Basic, though this sample can be translated to any other language,
of course. You can download Visual Basic project for this article at the bottom of the page.
|
Monitors enumeration
Firstly, it's necessary to call InitDDCHelper function and check its result:
|
Dim res As Integer
res = InitDDCHelper()
If res <> S_Ok Then 'some error occured
ShowError (res)
End If
|
Now we can enumerate available monitors with EnumGetFirst
and EnumGetNext functions:
|
Dim Displays(10) As Long
Dim DispCnt As Long
...
Dim res As Integer
Dim d As EDISP
DispCnt = 0
cbDisplays.Clear
If EnumGetFirst(Displays(DispCnt)) = S_Ok Then 'at least one monitor found
cbDisplays.AddItem GetMonitorName(Displays(DispCnt))
DispCnt = DispCnt + 1
Do While EnumGetNext(Displays(DispCnt)) = S_Ok 'other monitors
cbDisplays.AddItem GetMonitorName(Displays(DispCnt))
DispCnt = DispCnt + 1
Loop
If cbDisplays.ListCount > 0 Then cbDisplays.ListIndex = 0 'select first monitor
End If
|
Function "GetMonitorName" just copies the monitor name from Description field of EDISP structure:
|
Function GetMonitorName(disp As Long) As String
Dim d As EDISP
CopyMemory d, disp, 300 'size of EDISP
s = ""
i = 0
Do While d.Description(i) <> 0
s = s + Chr$(d.Description(i))
i = i + 1
Loop
GetMonitorName = s
End Function
|
|
EDID parsing
It's possible to use EDID stored in EDID field of EDISP structure,
or you can re-read EDID by using of ReadEDID function:
|
Dim EDID(128) As Byte
Dim mon As Long
mon = Displays(cbDisplays.ListIndex)
addr = VarPtr(EDID(0)) 'get address of first byte of the array
res = ReadEDID(mon, addr) 'read edid to the array
If res <> S_Ok Then 'some error
ShowError (res)
Exit Sub
End If
|
Now we can parse EDID, for EDID format description please see
this article. The code below extracts manufacturer ID, monitor ID,
manufacture date, EDID version, display size and the list of resolutions that monitor supports:
|
Function GetHeight(ByVal w As Long, ByVal aspectflag As Byte) As Long
Select Case aspectflag
Case 0
GetHeight = w
Case 64
GetHeight = (w * 3) / 4
Case 128
GetHeight = (w * 5) / 4
Case 192
GetHeight = (w * 9) / 16
End Select
End Function
Sub ParseEDID_v1(Index As Long)
Dim mon As Long
Dim res As Long
Dim addr As Long
Dim str As String
mon = Displays(cbDisplays.ListIndex)
Dim b, i As Byte
Dim w, h As Long
addr = VarPtr(EDID(0))
res = ReadEDID(mon, addr) 'read edid
If res <> S_Ok Then 'some error
ShowError (res)
Exit Sub
End If
lbManID.Caption = GetManufacturerNameID 'get manufacturer ID (three characters)
str = Hex$(EDID(10) + EDID(11) * 256) ' get monitor code ID (word)
If Len(str) < 4 Then str = String$(4 - Len(str), "0") & str
lbProductID.Caption = str
lbSerial.Caption = GetMonitorName(mon)
lbManufactured.Caption = CStr(EDID(17) + 1990) & ", week " & CStr(EDID(16)) 'manufacture date
lbEDIDver.Caption = CStr(EDID(18)) & "." & CStr(EDID(19)) 'EDID version
lbSize.Caption = CStr(EDID(21)) & " cm x " & CStr(EDID(22)) & " cm" 'display size
lbResolutions.Clear
b = EDID(35) 'first byte of "established timings" block
If (b And 1) <> 0 Then lbResolutions.AddItem ("800 x 600 @ 60Hz")
If (b And 2) <> 0 Then lbResolutions.AddItem ("800 x 600 @ 56Hz")
If (b And 4) <> 0 Then lbResolutions.AddItem ("640 x 480 @ 75Hz")
If (b And 8) <> 0 Then lbResolutions.AddItem ("640 x 480 @ 72Hz")
If (b And 16) <> 0 Then lbResolutions.AddItem ("640 x 480 @ 67Hz")
If (b And 32) <> 0 Then lbResolutions.AddItem ("640 x 480 @ 60Hz")
If (b And 64) <> 0 Then lbResolutions.AddItem ("720 x 400 @ 88Hz")
If (b And 128) <> 0 Then lbResolutions.AddItem ("720 x 400 @ 80Hz")
b = EDID(36) 'second byte of "established timings" block
If (b And 1) <> 0 Then lbResolutions.AddItem ("1280 x 1024 @ 75Hz")
If (b And 2) <> 0 Then lbResolutions.AddItem ("1024 x 768 @ 75Hz")
If (b And 4) <> 0 Then lbResolutions.AddItem ("1024 x 768 @ 70Hz")
If (b And 8) <> 0 Then lbResolutions.AddItem ("1024 x 768 @ 60Hz")
If (b And 16) <> 0 Then lbResolutions.AddItem ("1024 x 768 @ 87(I)")
If (b And 32) <> 0 Then lbResolutions.AddItem ("832 x 624 @ 75Hz")
If (b And 64) <> 0 Then lbResolutions.AddItem ("800 x 600 @ 75Hz")
If (b And 128) <> 0 Then lbResolutions.AddItem ("800 x 600 @ 72Hz")
b = EDID(37) 'third byte of "established timings" block
If (b And 128) <> 0 Then lbResolutions.AddItem ("1152 x 870 @ 75Hz")
For i = 0 To 7 'parse "standart timing" block
b = EDID(38 + 2 * i)
If b <> 1 Then 'not empty field
w = (b + 31) * 8
b = EDID(38 + 2 * i + 1)
h = GetHeight(w, b And 192)
str = CStr(w) & " x " & CStr(h) & " @ " & CStr((b And 63) + 60) & "Hz"
lbResolutions.AddItem (str)
End If
Next i
End Sub
|
|
VB Project
That's all! With WinI2C/DDC the most difficult thing is to parse EDID instead of detecting monitors and reading their EDIDs.
Please download sample VB6 project that enumerates available monitors and displays EDID information: vbedid.zip (12KB)
|
Keywords
EDID, DDC, Windows, VESA, DDC/CI, read EDID, DDC for Windows, EDID format, ATI, NVIDIA, Intel, S3, SiS,
parse EDID, monitor resolution, get EDID, display, get monitor, library, monitor capabilities,
read EDID directly, DDC CI tool, I2C DDC, DDC/CI windows, I2C EDID, Windows DDC, video card,
manufacturer ID, DDC/CI software, VCP, CI in Windows, DDC API, VGA, DVI, HDMI, MCCS, get display size,
VCP Windows, WinI2C-DDC.
|
|
|