6
6
#
7
7
import sys
8
8
import board
9
- import busio
9
+ import busio
10
10
11
- # Functions used for EDID parsing
12
11
def parse_established_timings (edid ):
12
+ # pylint: disable=redefined-outer-name
13
+ # pylint: disable=too-many-branches
13
14
"""Parse established timings from EDID bytes 35-37"""
14
15
modes = []
15
-
16
+
16
17
# Byte 35 (established timings I)
17
18
if edid [35 ] & 0x80 :
18
19
modes .append ("720x400 @70Hz" )
@@ -30,7 +31,7 @@ def parse_established_timings(edid):
30
31
modes .append ("800x600 @56Hz" )
31
32
if edid [35 ] & 0x01 :
32
33
modes .append ("800x600 @60Hz" )
33
-
34
+
34
35
# Byte 36 (established timings II)
35
36
if edid [36 ] & 0x80 :
36
37
modes .append ("800x600 @72Hz" )
@@ -48,31 +49,32 @@ def parse_established_timings(edid):
48
49
modes .append ("1024x768 @75Hz" )
49
50
if edid [36 ] & 0x01 :
50
51
modes .append ("1280x1024 @75Hz" )
51
-
52
+
52
53
# Byte 37 (manufacturer timings)
53
54
if edid [37 ] & 0x80 :
54
55
modes .append ("1152x870 @75Hz" )
55
-
56
+
56
57
return modes
57
58
58
59
def parse_standard_timings (edid ):
60
+ # pylint: disable=redefined-outer-name
59
61
"""Parse standard timings from EDID bytes 38-53"""
60
62
modes = []
61
-
63
+
62
64
for i in range (38 , 54 , 2 ): # 8 standard timing descriptors, 2 bytes each
63
65
if edid [i ] == 0x01 and edid [i + 1 ] == 0x01 :
64
66
continue # Unused timing
65
-
67
+
66
68
if edid [i ] == 0x00 :
67
69
continue # Invalid timing
68
-
70
+
69
71
# Calculate horizontal resolution
70
72
h_res = (edid [i ] + 31 ) * 8
71
-
73
+
72
74
# Calculate aspect ratio and vertical resolution
73
75
aspect_ratio = (edid [i + 1 ] & 0xC0 ) >> 6
74
76
refresh_rate = (edid [i + 1 ] & 0x3F ) + 60
75
-
77
+
76
78
if aspect_ratio == 0 : # 16:10
77
79
aspect = "16:10"
78
80
v_res = (h_res * 10 ) // 16
@@ -85,100 +87,103 @@ def parse_standard_timings(edid):
85
87
else : # aspect_ratio == 3, 16:9
86
88
aspect = "16:9"
87
89
v_res = (h_res * 9 ) // 16
88
-
90
+
89
91
modes .append (f"{ h_res } x{ v_res } @{ refresh_rate } Hz, Aspect: { aspect } " )
90
-
92
+
91
93
return modes
92
94
93
95
def parse_detailed_timings (edid ):
96
+ # pylint: disable=redefined-outer-name
94
97
# pylint: disable=unused-variable
98
+ # pylint: disable=too-many-locals
99
+
95
100
"""Parse detailed timing descriptors from EDID bytes 54-125"""
96
101
modes = []
97
-
102
+
98
103
for i in range (54 , 126 , 18 ): # 4 detailed timing descriptors, 18 bytes each
99
104
# Check if this is a timing descriptor (pixel clock != 0)
100
105
pixel_clock = edid [i ] | (edid [i + 1 ] << 8 )
101
106
if pixel_clock == 0 :
102
107
continue # Not a timing descriptor
103
-
108
+
104
109
# Parse horizontal resolution
105
110
h_active_low = edid [i + 2 ]
106
111
h_active_high = (edid [i + 4 ] & 0xF0 ) >> 4
107
112
h_active = h_active_low | (h_active_high << 8 )
108
-
113
+
109
114
# Parse vertical resolution
110
115
v_active_low = edid [i + 5 ]
111
116
v_active_high = (edid [i + 7 ] & 0xF0 ) >> 4
112
117
v_active = v_active_low | (v_active_high << 8 )
113
-
118
+
114
119
# Parse horizontal sync
115
120
h_sync_offset_low = edid [i + 8 ]
116
121
h_sync_width_low = edid [i + 9 ]
117
122
h_sync_high = (edid [i + 11 ] & 0xC0 ) >> 6
118
123
h_sync_offset = h_sync_offset_low | ((h_sync_high & 0x3 ) << 8 )
119
124
h_sync_width = h_sync_width_low | ((h_sync_high & 0xC ) << 6 )
120
-
125
+
121
126
# Parse vertical sync
122
127
v_sync_offset_low = (edid [i + 10 ] & 0xF0 ) >> 4
123
128
v_sync_width_low = edid [i + 10 ] & 0x0F
124
129
v_sync_high = (edid [i + 11 ] & 0x0C ) >> 2
125
130
v_sync_offset = v_sync_offset_low | ((v_sync_high & 0x3 ) << 4 )
126
131
v_sync_width = v_sync_width_low | ((v_sync_high & 0xC ) << 2 )
127
-
132
+
128
133
# Calculate refresh rate (approximate)
129
134
h_blank_low = edid [i + 3 ]
130
135
h_blank_high = edid [i + 4 ] & 0x0F
131
136
h_blank = h_blank_low | (h_blank_high << 8 )
132
137
h_total = h_active + h_blank
133
-
138
+
134
139
v_blank_low = edid [i + 6 ]
135
140
v_blank_high = edid [i + 7 ] & 0x0F
136
141
v_blank = v_blank_low | (v_blank_high << 8 )
137
142
v_total = v_active + v_blank
138
-
143
+
139
144
if h_total > 0 and v_total > 0 :
140
145
refresh_rate = (pixel_clock * 10000 ) // (h_total * v_total )
141
146
modes .append (f"{ h_active } x{ v_active } @{ refresh_rate } Hz" )
142
-
147
+
143
148
return modes
144
149
145
150
# Main EDID reading code
146
- i2c = busio .I2C (board .SCL , board .SDA )
151
+ i2c = busio .I2C (board .SCL , board .SDA )
147
152
if not i2c :
148
153
print ("Board doesn't have I2C" )
149
154
sys .exit (1 )
150
155
if not i2c .try_lock ():
151
156
print ("Cannot lock I2C" )
152
157
sys .exit (1 )
153
-
154
- print ("\n I2C Present" )
155
-
158
+
159
+ print ("\n I2C Present" )
160
+
156
161
devices = i2c .scan ()
157
- if not ( 0x50 in devices ) :
162
+ if not 0x50 in devices :
158
163
print ("No device found at EDID address 0x50, is the monitor plugged in " +
159
164
"& board power cycled?" )
160
165
sys .exit (1 )
161
-
166
+
162
167
print ("Device 0x50 found!" )
163
168
device = 0x50
164
169
edid = bytearray (128 )
165
170
out = bytearray ([0 ])
166
171
i2c .writeto_then_readfrom (device , out , edid )
167
-
172
+ # pylint: disable=too-many-boolean-expressions
168
173
if edid [0 ] != 0x00 or edid [1 ] != 0xFF or edid [2 ] != 0xFF or \
169
174
edid [3 ] != 0xFF or edid [4 ] != 0xFF or edid [5 ] != 0xFF or \
170
175
edid [6 ] != 0xFF or edid [7 ] != 0x00 :
171
176
print ("EDID signature not recognized" )
172
177
sys .exit (1 )
173
-
178
+
174
179
print ("Valid EDID signature!" )
175
180
176
181
# Verify checksum
177
182
checksum = sum (edid ) & 0xFF
178
183
if checksum != 0 :
179
184
print ("Bad EDID checksum detected" )
180
185
sys .exit (1 )
181
-
186
+
182
187
print ("Good EDID checksum!" )
183
188
184
189
# Parse all supported modes
0 commit comments