forked from m3x1m0m/edid
				
			
				 5 changed files with 347 additions and 238 deletions
			
			
		@ -0,0 +1,208 @@ | 
				
			|||||
 | 
					#ifndef INCLUDED_MAX_EDID | 
				
			||||
 | 
					#define INCLUDED_MAX_EDID | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#include <stdio.h> | 
				
			||||
 | 
					#include <stdint.h> | 
				
			||||
 | 
					#include <string.h> | 
				
			||||
 | 
					#include <stdlib.h> | 
				
			||||
 | 
					#include "frozen/frozen.h" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#define EDID_LEN 128 | 
				
			||||
 | 
					#define EDID_DISPLAY_DESCRIPTOR_DATA_LEN 13 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// EDID data structure
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					typedef  struct __attribute__ (( packed )) { | 
				
			||||
 | 
					  uint8_t x_resolution; | 
				
			||||
 | 
					  uint8_t vertical_frequency:6; | 
				
			||||
 | 
					  uint8_t aspect_ratio      :2; | 
				
			||||
 | 
					} standard_timing_information_t; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					typedef struct __attribute__ (( packed )) { | 
				
			||||
 | 
					  uint16_t pixel_clock;                           // 0-1
 | 
				
			||||
 | 
					  uint8_t horizontal_active_pixels_lsbs;          // 2
 | 
				
			||||
 | 
					  uint8_t horizontal_blanking_pixels_lsbs;        // 3
 | 
				
			||||
 | 
					  uint8_t horizontal_blanking_pixels_msbs     :4; // 4
 | 
				
			||||
 | 
					  uint8_t horizontal_active_pixels_msbs       :4; | 
				
			||||
 | 
					  uint8_t vertical_active_lines_lsbs;             // 5
 | 
				
			||||
 | 
					  uint8_t vertical_blanking_lines_lsbs;           // 6
 | 
				
			||||
 | 
					  uint8_t vertical_blanking_lines_msbs        :4; // 7
 | 
				
			||||
 | 
					  uint8_t vertical_active_lines_msbs          :4; | 
				
			||||
 | 
					  uint8_t horizontal_front_porch_pixels_lsbs;     // 8
 | 
				
			||||
 | 
					  uint8_t horizontal_sync_pulse_pixels_lsbs;      // 9
 | 
				
			||||
 | 
					  uint8_t vertical_sync_pulse_lines_lsbs      :4; // 10
 | 
				
			||||
 | 
					  uint8_t vertical_front_porch_lines_lsbs     :4; | 
				
			||||
 | 
					  uint8_t vertical_sync_pulse_lines_msbs      :2; // 11
 | 
				
			||||
 | 
					  uint8_t vertical_front_porch_lines_msbs     :2; | 
				
			||||
 | 
					  uint8_t horizontal_sync_pulse_pixels_msbs   :2; | 
				
			||||
 | 
					  uint8_t horizontal_front_porch_pixels_msbs  :2; | 
				
			||||
 | 
					  uint8_t horizontal_image_size_lsbs;             // 12
 | 
				
			||||
 | 
					  uint8_t vertical_image_size_lsbs; | 
				
			||||
 | 
					  uint8_t vertical_image_size_msbs            :4; | 
				
			||||
 | 
					  uint8_t horizontal_image_size_msbs          :4; | 
				
			||||
 | 
					  uint8_t horizontal_border_pixels; | 
				
			||||
 | 
					  uint8_t vertical_border_lines; | 
				
			||||
 | 
					  // Feature bitmap
 | 
				
			||||
 | 
					  union __attribute__ (( packed )) { | 
				
			||||
 | 
					    struct __attribute__ (( packed )) { | 
				
			||||
 | 
					      uint8_t stereo_mode_lsb                 :1; | 
				
			||||
 | 
					      uint8_t sync_on_red_blue                :1; | 
				
			||||
 | 
					      uint8_t vertical_sync_serration         :1; | 
				
			||||
 | 
					      uint8_t sync_type                       :1; | 
				
			||||
 | 
					      uint8_t analog_sync                     :1; | 
				
			||||
 | 
					      uint8_t stereo_mode_msbs                :2; | 
				
			||||
 | 
					      uint8_t interlaced                      :1; | 
				
			||||
 | 
					    } analog; | 
				
			||||
 | 
					    struct __attribute__ (( packed )) { | 
				
			||||
 | 
					      uint8_t stereo_mode_lsb                 :1; | 
				
			||||
 | 
					      uint8_t reserved                        :1; | 
				
			||||
 | 
					      uint8_t vertical_sync_polarity          :1; | 
				
			||||
 | 
					      uint8_t digital_composite_sync          :2; | 
				
			||||
 | 
					      uint8_t stereo_mode_msbs                :2; | 
				
			||||
 | 
					      uint8_t interlaced                      :1; | 
				
			||||
 | 
					    } digital_composite; | 
				
			||||
 | 
					    struct __attribute__ (( packed )) { | 
				
			||||
 | 
					      uint8_t stereo_mode_lsb                 :1; | 
				
			||||
 | 
					      uint8_t horizontal_sync_polarity        :1; | 
				
			||||
 | 
					      uint8_t vertical_sync_serration         :1; | 
				
			||||
 | 
					      uint8_t digital_seperate_sync           :2; | 
				
			||||
 | 
					      uint8_t stereo_mode_msbs                :2; | 
				
			||||
 | 
					      uint8_t interlaced                      :1; | 
				
			||||
 | 
					    } digital_seperate; | 
				
			||||
 | 
					  } features; | 
				
			||||
 | 
					} detailed_timing_descriptor_t; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					typedef struct __attribute__ (( packed )) { | 
				
			||||
 | 
					  uint16_t display_descriptor; | 
				
			||||
 | 
					  uint8_t reserved; | 
				
			||||
 | 
					  uint8_t display_range_limits_descriptor; | 
				
			||||
 | 
					  struct __attribute__ (( packed )) { | 
				
			||||
 | 
					    uint8_t vertical    :2; | 
				
			||||
 | 
					    uint8_t horizontal  :2; | 
				
			||||
 | 
					    uint8_t reserved    :4; | 
				
			||||
 | 
					  } rate_offsets; | 
				
			||||
 | 
					  struct __attribute__ (( packed )) { | 
				
			||||
 | 
					    uint8_t minimum; | 
				
			||||
 | 
					    uint8_t maximum; | 
				
			||||
 | 
					  } vertical_field_rate; | 
				
			||||
 | 
					  struct __attribute__ (( packed )) { | 
				
			||||
 | 
					    uint8_t minimum; | 
				
			||||
 | 
					    uint8_t maximum; | 
				
			||||
 | 
					  } horizontal_line_rate; | 
				
			||||
 | 
					  uint8_t maximum_pixel_clock_mhz; // In 10 MHz units
 | 
				
			||||
 | 
					  uint8_t extended_timing_information_type; | 
				
			||||
 | 
					  uint8_t video_timing_params[7]; | 
				
			||||
 | 
					} range_limits_descriptor_t; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					typedef struct __attribute__ (( packed )) { | 
				
			||||
 | 
					  uint16_t display_descriptor; | 
				
			||||
 | 
					  uint8_t reserved0; | 
				
			||||
 | 
					  uint8_t descriptor_type; | 
				
			||||
 | 
					  uint8_t reserved1; | 
				
			||||
 | 
					  uint8_t descriptor_data[EDID_DISPLAY_DESCRIPTOR_DATA_LEN]; | 
				
			||||
 | 
					} display_descriptor_t; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					typedef struct __attribute__ (( packed )) { | 
				
			||||
 | 
					  /*! Header information, 20 bytes */ | 
				
			||||
 | 
					  struct __attribute__ (( packed )) { | 
				
			||||
 | 
					    uint64_t preamble; | 
				
			||||
 | 
					    uint8_t manufacturer_id[2]; | 
				
			||||
 | 
					    uint16_t product_code; | 
				
			||||
 | 
					    uint32_t serial_number; | 
				
			||||
 | 
					    uint8_t week_of_manufacture; | 
				
			||||
 | 
					    uint8_t year_of_manufacture; | 
				
			||||
 | 
					    uint8_t edid_version; | 
				
			||||
 | 
					    uint8_t edid_revision; | 
				
			||||
 | 
					  } header; | 
				
			||||
 | 
					  /*! Basic display parameters, 5 bytes */ | 
				
			||||
 | 
					  struct __attribute__ (( packed )) { | 
				
			||||
 | 
					    union __attribute__ (( packed )) { | 
				
			||||
 | 
					      struct __attribute__ (( packed )) { | 
				
			||||
 | 
					        uint8_t video_interface : 4; | 
				
			||||
 | 
					        uint8_t bit_depth       : 3; | 
				
			||||
 | 
					        uint8_t input_type      : 1; // 1 for digital
 | 
				
			||||
 | 
					      } digital; | 
				
			||||
 | 
					      struct __attribute__ (( packed )) { | 
				
			||||
 | 
					        uint8_t vsync_serrated: 1; | 
				
			||||
 | 
					        uint8_t sync_on_green : 1; | 
				
			||||
 | 
					        uint8_t composite_sync: 1; | 
				
			||||
 | 
					        uint8_t seperate_sync : 1; | 
				
			||||
 | 
					        uint8_t blank_to_black: 1; | 
				
			||||
 | 
					        uint8_t levels        : 2; | 
				
			||||
 | 
					        uint8_t input_type    : 1; // 0 for analog
 | 
				
			||||
 | 
					      } analog; | 
				
			||||
 | 
					    } video_input_parameters; // 1 byte
 | 
				
			||||
 | 
					    uint8_t horizontal_screen_size; | 
				
			||||
 | 
					    uint8_t vertical_screen_size; | 
				
			||||
 | 
					    uint8_t gamma; | 
				
			||||
 | 
					    struct __attribute__ (( packed )) { | 
				
			||||
 | 
					      uint8_t continuous_timings        : 1; | 
				
			||||
 | 
					      uint8_t preferred_timing_mode     : 1; | 
				
			||||
 | 
					      uint8_t standard_srgb             : 1; | 
				
			||||
 | 
					      uint8_t display_type              : 2; | 
				
			||||
 | 
					      uint8_t dpms_active_off_supported : 1; | 
				
			||||
 | 
					      uint8_t dpms_suspend_supported    : 1; | 
				
			||||
 | 
					      uint8_t dpms_standby_supported    : 1; | 
				
			||||
 | 
					    } features; | 
				
			||||
 | 
					  } basic_display_parameters; | 
				
			||||
 | 
					  /*! Chromaticity coordinates. 10-bit CIE 1931 xy coordinates for red, green,
 | 
				
			||||
 | 
					   *  blue, and white point, 10 bytes */ | 
				
			||||
 | 
					  struct __attribute__ (( packed )) { | 
				
			||||
 | 
					    struct __attribute__ (( packed )) { | 
				
			||||
 | 
					      uint8_t green_y : 2; | 
				
			||||
 | 
					      uint8_t green_x : 2; | 
				
			||||
 | 
					      uint8_t red_y   : 2; | 
				
			||||
 | 
					      uint8_t red_x   : 2; | 
				
			||||
 | 
					    } red_green_lsbs; | 
				
			||||
 | 
					    struct __attribute__ (( packed )) { | 
				
			||||
 | 
					      uint8_t white_y : 2; | 
				
			||||
 | 
					      uint8_t white_x : 2; | 
				
			||||
 | 
					      uint8_t blue_y  : 2; | 
				
			||||
 | 
					      uint8_t blue_x  : 2; | 
				
			||||
 | 
					    } blue_white_lsbs; | 
				
			||||
 | 
					    uint8_t red_x_msbs; | 
				
			||||
 | 
					    uint8_t red_y_msbs; | 
				
			||||
 | 
					    uint8_t green_x_msbs; | 
				
			||||
 | 
					    uint8_t green_y_msbs; | 
				
			||||
 | 
					    uint8_t blue_x_msbs; | 
				
			||||
 | 
					    uint8_t blue_y_msbs; | 
				
			||||
 | 
					    uint8_t white_x_msbs; | 
				
			||||
 | 
					    uint8_t white_y_msbs; | 
				
			||||
 | 
					  } chromaticity_coordinates; | 
				
			||||
 | 
					  /*! Established timing bitmap. Supported bitmap for (formerly) very common
 | 
				
			||||
 | 
					      timing modes. 3 bytes */ | 
				
			||||
 | 
					  struct __attribute__ (( packed )) { | 
				
			||||
 | 
					    uint8_t m800_600_60  : 1; | 
				
			||||
 | 
					    uint8_t m800_600_56  : 1; | 
				
			||||
 | 
					    uint8_t m640_480_75  : 1; | 
				
			||||
 | 
					    uint8_t m640_480_72  : 1; | 
				
			||||
 | 
					    uint8_t m640_480_67  : 1; | 
				
			||||
 | 
					    uint8_t m640_480_60  : 1; | 
				
			||||
 | 
					    uint8_t m720_400_88  : 1; | 
				
			||||
 | 
					    uint8_t m720_400_70  : 1; | 
				
			||||
 | 
					    uint8_t m1280_1024_75: 1; | 
				
			||||
 | 
					    uint8_t m1024_768_75 : 1; | 
				
			||||
 | 
					    uint8_t m1024_768_70 : 1; | 
				
			||||
 | 
					    uint8_t m1024_768_60 : 1; | 
				
			||||
 | 
					    uint8_t m1024_768_87 : 1; | 
				
			||||
 | 
					    uint8_t m832_624_75  : 1; | 
				
			||||
 | 
					    uint8_t m800_600_75  : 1; | 
				
			||||
 | 
					    uint8_t m800_600_72  : 1; | 
				
			||||
 | 
					    uint8_t reserved     : 7; | 
				
			||||
 | 
					    uint8_t m1152_870_75 : 1; | 
				
			||||
 | 
					  } common_timing_modes; | 
				
			||||
 | 
					  /*! Standard timing information. Up to 8 2-byte fields describing standard
 | 
				
			||||
 | 
					      display modes. Unused fields are filled with 01 01 hex. 16 bytes */ | 
				
			||||
 | 
					  standard_timing_information_t timings[8]; | 
				
			||||
 | 
					  detailed_timing_descriptor_t detailed_timing_descriptor; | 
				
			||||
 | 
					  range_limits_descriptor_t range_limits_descriptor; | 
				
			||||
 | 
					  display_descriptor_t display_name_descriptor; | 
				
			||||
 | 
					  display_descriptor_t display_serial_number_descriptor; | 
				
			||||
 | 
					  uint8_t number_extensions; | 
				
			||||
 | 
					  uint8_t checksum; | 
				
			||||
 | 
					} edid_t; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// Interface
 | 
				
			||||
 | 
					int generate_edid(edid_t* const edid, const char* const filename); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#endif | 
				
			||||
								
									Binary file not shown.
								
							
						
					@ -0,0 +1,78 @@ | 
				
			|||||
 | 
					#include <stdio.h> | 
				
			||||
 | 
					#include "edid.h" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#define FAILURE(buf_str, line)                                    \ | 
				
			||||
 | 
					  fprintf(stderr, "X Failed on line %d: [%s]\n", line, buf_str);  \ | 
				
			||||
 | 
					  return EXIT_FAILURE;                                           | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#define SUCCESS(buf_str, line)                                    \ | 
				
			||||
 | 
					  fprintf(stdout, "✓ Success on line %d: [%s]\n", line, buf_str);  | 
				
			||||
 | 
					   | 
				
			||||
 | 
					#define CHECK_TRUE(expr)        \ | 
				
			||||
 | 
					    if (!(expr)) {              \ | 
				
			||||
 | 
					      FAILURE(#expr, __LINE__); \ | 
				
			||||
 | 
					    } else {                    \ | 
				
			||||
 | 
					      SUCCESS(#expr, __LINE__); \ | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					static const uint8_t i2c_data_screen_0[EDID_LEN] = { | 
				
			||||
 | 
					  0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1e, 0x6d, 0xd5, 0x59, 0x04, 0x45, 0x09, 0x00, | 
				
			||||
 | 
					  0x03, 0x17, 0x01, 0x03, 0x68, 0x35, 0x1e, 0x78, 0xea, 0x33, 0x31, 0xa4, 0x57, 0x51, 0xa0, 0x26, | 
				
			||||
 | 
					  0x10, 0x50, 0x54, 0xa7, 0x6b, 0x80, 0xb3, 0x00, 0x81, 0x80, 0x95, 0x00, 0x71, 0x4f, 0xa9, 0xc0, | 
				
			||||
 | 
					  0x81, 0x00, 0x81, 0xc0, 0x90, 0x40, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, | 
				
			||||
 | 
					  0x45, 0x00, 0x09, 0x25, 0x21, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4b, 0x1e, | 
				
			||||
 | 
					  0x53, 0x0f, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x32, | 
				
			||||
 | 
					  0x34, 0x45, 0x4e, 0x33, 0x33, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xff, | 
				
			||||
 | 
					  0x00, 0x33, 0x30, 0x33, 0x4e, 0x44, 0x51, 0x41, 0x48, 0x56, 0x34, 0x39, 0x32, 0x0a, 0x00, 0xf1   | 
				
			||||
 | 
					};     | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/**
 | 
				
			||||
 | 
					 * @brief Helper function to compare EDID data structure with golden design data structure extracted from real  | 
				
			||||
 | 
					 *        VGA screen. | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					static int compare_edid(const uint8_t* const edid, const uint8_t* const edid_golden)  | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					  for (int sanny=0; sanny<EDID_LEN; sanny++) { | 
				
			||||
 | 
					    CHECK_TRUE(edid[sanny] == edid_golden[sanny]); | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					  return 0; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/**
 | 
				
			||||
 | 
					 * @brief Helper function to show buffer | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					static void disp_buf(uint8_t *buf, int len) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					  int i; | 
				
			||||
 | 
					  for (i = 0; i < len; i++) { | 
				
			||||
 | 
					    printf("%02x ", buf[i]); | 
				
			||||
 | 
					    if ((i + 1) % 16 == 0) { | 
				
			||||
 | 
					      printf("\n"); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					  printf("\n"); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					int main(void) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					  edid_t edith; | 
				
			||||
 | 
					  const char* const json_file = "edid0.json"; | 
				
			||||
 | 
					   | 
				
			||||
 | 
					  /* 1) If check fails the structure has been build up in the wrong way on the target platform. 
 | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  CHECK_TRUE(sizeof(edid_t) == EDID_LEN); | 
				
			||||
 | 
					  /* 2) If check fails the EDID data structure could not be generated. 
 | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  CHECK_TRUE(generate_edid(&edith, json_file) == 0); | 
				
			||||
 | 
					  /* 3) 128 checks in one function to probe every single byte.  
 | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  int ret = 0; | 
				
			||||
 | 
					  if (ret = compare_edid((uint8_t*)&edith, i2c_data_screen_0)) { | 
				
			||||
 | 
					    printf("ret> %d\n", ret); | 
				
			||||
 | 
					    return ret; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					  printf("\n"); | 
				
			||||
 | 
					  printf("Generated EDID data from %s:\n", json_file); | 
				
			||||
 | 
					  disp_buf((uint8_t*)&edith, EDID_LEN); | 
				
			||||
 | 
					  return 0; | 
				
			||||
 | 
					} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue