forked from m3x1m0m/edid
				
			
				 4 changed files with 324 additions and 0 deletions
			
			
		@ -0,0 +1,3 @@ | 
				
			|||||
 | 
					[submodule "frozen"] | 
				
			||||
 | 
						path = frozen | 
				
			||||
 | 
						url = https://github.com/cesanta/frozen.git | 
				
			||||
@ -0,0 +1,20 @@ | 
				
			|||||
 | 
					{ | 
				
			||||
 | 
					  "header": { | 
				
			||||
 | 
					    "manufacturer_id": "GSM", | 
				
			||||
 | 
					    "product_code": 22997, | 
				
			||||
 | 
					    "serial_number": 607492, | 
				
			||||
 | 
					    "week_of_manufacture": 3, | 
				
			||||
 | 
					    "year_of_manufacture": 2013, | 
				
			||||
 | 
					    "edid_version": 1, | 
				
			||||
 | 
					    "edid_revision": 3 | 
				
			||||
 | 
					  }, | 
				
			||||
 | 
					  "video_input_parameters": { | 
				
			||||
 | 
					    "input_type": "analog", | 
				
			||||
 | 
					    "levels": 3, | 
				
			||||
 | 
					    "blank_to_black": false, | 
				
			||||
 | 
					    "seperate_sync": true, | 
				
			||||
 | 
					    "composite_sync": false, | 
				
			||||
 | 
					    "sync_on_green": false, | 
				
			||||
 | 
					    "vsync_serrated": false | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					} | 
				
			||||
@ -0,0 +1,300 @@ | 
				
			|||||
 | 
					#include <stdio.h> | 
				
			||||
 | 
					#include <stdint.h> | 
				
			||||
 | 
					#include <string.h> | 
				
			||||
 | 
					#include <stdlib.h> | 
				
			||||
 | 
					#include "frozen/frozen.h" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#define EDID_LENGTH 128 | 
				
			||||
 | 
					#define EDID_BYTES_OFFSET_HEADER_PREAMBLE 0 | 
				
			||||
 | 
					#define EDID_BYTES_OFFSET_HEADER_MANUFACTURER_ID 8 | 
				
			||||
 | 
					#define EDID_BYTES_OFFSET_HEADER_PRODUCT_CODE 10 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					typedef  struct __attribute__ (( packed )) { | 
				
			||||
 | 
					  uint8_t resolution; | 
				
			||||
 | 
					  uint8_t image_aspect_ratio : 2; | 
				
			||||
 | 
					  uint8_t vertical_frequency : 6; | 
				
			||||
 | 
					} standard_timing_information_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 h_screen_size; | 
				
			||||
 | 
					    uint8_t v_screen_size; | 
				
			||||
 | 
					    uint8_t gamma; | 
				
			||||
 | 
					    struct __attribute__ (( packed )) { | 
				
			||||
 | 
					      uint8_t dpms_standby          : 1; | 
				
			||||
 | 
					      uint8_t dpms_suspend          : 1; | 
				
			||||
 | 
					      uint8_t dpms_active_off       : 1; | 
				
			||||
 | 
					      uint8_t display_type          : 2; | 
				
			||||
 | 
					      uint8_t standard_srgb         : 1; | 
				
			||||
 | 
					      uint8_t preferred_timing_mode : 1; | 
				
			||||
 | 
					      uint8_t continuous_timings    : 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 red_x   : 2; | 
				
			||||
 | 
					      uint8_t red_y   : 2; | 
				
			||||
 | 
					      uint8_t green_x : 2; | 
				
			||||
 | 
					      uint8_t green_y : 2; | 
				
			||||
 | 
					    } red_green_lsbs; | 
				
			||||
 | 
					    struct __attribute__ (( packed )) { | 
				
			||||
 | 
					      uint8_t blue_x  : 2; | 
				
			||||
 | 
					      uint8_t blue_y  : 2; | 
				
			||||
 | 
					      uint8_t white_x : 2; | 
				
			||||
 | 
					      uint8_t white_y : 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; | 
				
			||||
 | 
					  } chromacity_cordinates; | 
				
			||||
 | 
					  /*! Established timing bitmap. Supported bitmap for (formerly) very common
 | 
				
			||||
 | 
					      timing modes. 3 bytes */ | 
				
			||||
 | 
					  struct __attribute__ (( packed )) { | 
				
			||||
 | 
					    uint8_t m720_400_70  : 1; | 
				
			||||
 | 
					    uint8_t m720_400_80  : 1; | 
				
			||||
 | 
					    uint8_t m640_480_60  : 1; | 
				
			||||
 | 
					    uint8_t m640_480_67  : 1; | 
				
			||||
 | 
					    uint8_t m640_480_72  : 1; | 
				
			||||
 | 
					    uint8_t m640_480_75  : 1; | 
				
			||||
 | 
					    uint8_t m800_600_56  : 1; | 
				
			||||
 | 
					    uint8_t m800_600_60  : 1; | 
				
			||||
 | 
					    uint8_t m800_600_72  : 1; | 
				
			||||
 | 
					    uint8_t m800_600_75  : 1; | 
				
			||||
 | 
					    uint8_t m832_624_75  : 1; | 
				
			||||
 | 
					    uint8_t m1024_768_87 : 1; | 
				
			||||
 | 
					    uint8_t m1024_768_60 : 1; | 
				
			||||
 | 
					    uint8_t m1024_768_70 : 1; | 
				
			||||
 | 
					    uint8_t m1024_768_75 : 1; | 
				
			||||
 | 
					    uint8_t m1280_1024_75: 1; | 
				
			||||
 | 
					    uint8_t m1152_870_75 : 1; | 
				
			||||
 | 
					    uint8_t reserved     : 7; | 
				
			||||
 | 
					  } 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]; | 
				
			||||
 | 
					  uint8_t descriptor_1[18]; | 
				
			||||
 | 
					  uint8_t descriptor_2[18]; | 
				
			||||
 | 
					  uint8_t descriptor_3[18]; | 
				
			||||
 | 
					  uint8_t descriptor_4[18]; | 
				
			||||
 | 
					  uint8_t number_extensions; | 
				
			||||
 | 
					  uint8_t checksum; | 
				
			||||
 | 
					} edid_t; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/**
 | 
				
			||||
 | 
					 * @brief test 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"); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					static size_t file_to_str(unsigned char** str, const char const* filename) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					  size_t length; | 
				
			||||
 | 
					  FILE * f = fopen (filename, "rb"); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  if (f) { | 
				
			||||
 | 
					    fseek (f, 0, SEEK_END); | 
				
			||||
 | 
					    length = ftell (f); | 
				
			||||
 | 
					    fseek (f, 0, SEEK_SET); | 
				
			||||
 | 
					    *str = (unsigned char*)malloc(length); | 
				
			||||
 | 
					    if (*str) { | 
				
			||||
 | 
					      fread (*str, 1, length, f); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    fclose (f); | 
				
			||||
 | 
					  } else { | 
				
			||||
 | 
					    printf("File pointer is NULL..\n"); | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					  return length; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					static void generate_preamble(edid_t* edid) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					  memset((uint8_t*)&(edid->header.preamble)+0, 0x00, 1); | 
				
			||||
 | 
					  memset((uint8_t*)&(edid->header.preamble)+1, 0xFF, 6); | 
				
			||||
 | 
					  memset((uint8_t*)&(edid->header.preamble)+7, 0x00, 1); | 
				
			||||
 | 
					/*memset( edid + EDID_BYTES_OFFSET_HEADER_PREAMBLE,
 | 
				
			||||
 | 
					          0x00, 1); | 
				
			||||
 | 
					  memset( edid + EDID_BYTES_OFFSET_HEADER_PREAMBLE + 1, | 
				
			||||
 | 
					          0xFF, 6); | 
				
			||||
 | 
					  memset( edid + EDID_BYTES_OFFSET_HEADER_PREAMBLE + 7, | 
				
			||||
 | 
					          0x00, 1); | 
				
			||||
 | 
					*/ | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					static int generate_header(edid_t* edid, unsigned char* json_str, size_t json_len) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					  char* multi_use_str; | 
				
			||||
 | 
					  unsigned int multi_use_int; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  if (edid && json_str) { | 
				
			||||
 | 
					    // Manufacturer ID
 | 
				
			||||
 | 
					    json_scanf( json_str, json_len, "{header: {manufacturer_id: %Q}", | 
				
			||||
 | 
					                &multi_use_str); | 
				
			||||
 | 
					    if (strlen(multi_use_str) == 3) { | 
				
			||||
 | 
					      multi_use_int = 0; | 
				
			||||
 | 
					      multi_use_int |= | 
				
			||||
 | 
					      ((0x1F & (multi_use_str[0]-64)) << 10)|        // First letter
 | 
				
			||||
 | 
					      ((0x1F & (multi_use_str[1]-64)) << 5) |        // Second letter
 | 
				
			||||
 | 
					      ((0x1F & (multi_use_str[2]-64)) << 0);         // Third letter
 | 
				
			||||
 | 
					      edid->header.manufacturer_id[0] = multi_use_int >> 8; | 
				
			||||
 | 
					      edid->header.manufacturer_id[1] = multi_use_int; | 
				
			||||
 | 
					    } else { | 
				
			||||
 | 
					      printf("Error: JSON file format is wrong somewhere arround manufacturer\
 | 
				
			||||
 | 
					              ID.\n"); | 
				
			||||
 | 
					      return 1; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    // Product code
 | 
				
			||||
 | 
					    json_scanf(json_str, json_len, "{header: {product_code: %d}", &multi_use_int); | 
				
			||||
 | 
					    edid->header.product_code = 0xFFFF & multi_use_int; | 
				
			||||
 | 
					    // Serial number
 | 
				
			||||
 | 
					    json_scanf(json_str, json_len, "{header: {serial_number: %d}", &multi_use_int); | 
				
			||||
 | 
					    edid->header.serial_number = 0xFFFFFFFF & multi_use_int; | 
				
			||||
 | 
					    // Week of manufacture
 | 
				
			||||
 | 
					    json_scanf( json_str, json_len, "{header: {week_of_manufacture: %d}", | 
				
			||||
 | 
					                &multi_use_int); | 
				
			||||
 | 
					    edid->header.week_of_manufacture = 0xFF & multi_use_int; | 
				
			||||
 | 
					    // Year of manufacture
 | 
				
			||||
 | 
					    json_scanf( json_str, json_len, "{header: {year_of_manufacture: %d}", | 
				
			||||
 | 
					                &multi_use_int); | 
				
			||||
 | 
					    edid->header.year_of_manufacture = 0xFF & (multi_use_int - 1990); | 
				
			||||
 | 
					    // EDID version
 | 
				
			||||
 | 
					    json_scanf(json_str, json_len, "{header: {edid_version: %d}", &multi_use_int); | 
				
			||||
 | 
					    edid->header.edid_version = 0xFF & multi_use_int; | 
				
			||||
 | 
					    // EDID revision
 | 
				
			||||
 | 
					    json_scanf(json_str, json_len, "{header: {edid_revision: %d}", &multi_use_int); | 
				
			||||
 | 
					    edid->header.edid_revision = 0xFF & multi_use_int; | 
				
			||||
 | 
					  } else { | 
				
			||||
 | 
					    printf("One of either edid or json_str is NULL.\n"); | 
				
			||||
 | 
					    return 2; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					  return 0; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					static int generate_video_input_parameters( edid_t* edid, | 
				
			||||
 | 
					                                            unsigned char* json_str, | 
				
			||||
 | 
					                                            size_t json_len) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					  char* multi_use_str; | 
				
			||||
 | 
					  unsigned int multi_use_int; | 
				
			||||
 | 
					  bool multi_use_bool; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  if (edid && json_str) { | 
				
			||||
 | 
					    // Input type analog or digital
 | 
				
			||||
 | 
					    json_scanf( json_str, json_len, "{video_input_parameters: {input_type: %Q}", | 
				
			||||
 | 
					                &multi_use_str); | 
				
			||||
 | 
					    if (strcmp(multi_use_str, "analog") == 0) { | 
				
			||||
 | 
					      edid->basic_display_parameters.video_input_parameters | 
				
			||||
 | 
					        .analog.input_type = 0; | 
				
			||||
 | 
					      // Levels
 | 
				
			||||
 | 
					      json_scanf( json_str, json_len, "{video_input_parameters: {levels: %d}", | 
				
			||||
 | 
					                &multi_use_int); | 
				
			||||
 | 
					      edid->basic_display_parameters.video_input_parameters | 
				
			||||
 | 
					        .analog.levels = 0x3 & multi_use_int; | 
				
			||||
 | 
					      // Blank to black
 | 
				
			||||
 | 
					      json_scanf( json_str, json_len, | 
				
			||||
 | 
					                  "{video_input_parameters: {blank_to_black: %B}", | 
				
			||||
 | 
					                  &multi_use_bool); | 
				
			||||
 | 
					      edid->basic_display_parameters.video_input_parameters | 
				
			||||
 | 
					        .analog.blank_to_black = 0x1 & multi_use_bool; | 
				
			||||
 | 
					      // Seperate sync
 | 
				
			||||
 | 
					      json_scanf( json_str, json_len, | 
				
			||||
 | 
					                  "{video_input_parameters: {seperate_sync: %B}", | 
				
			||||
 | 
					                  &multi_use_bool); | 
				
			||||
 | 
					      edid->basic_display_parameters.video_input_parameters | 
				
			||||
 | 
					        .analog.seperate_sync = 0x1 & multi_use_bool; | 
				
			||||
 | 
					      // Composite sync
 | 
				
			||||
 | 
					      json_scanf( json_str, json_len, | 
				
			||||
 | 
					                  "{video_input_parameters: {composite_sync: %B}", | 
				
			||||
 | 
					                  &multi_use_bool); | 
				
			||||
 | 
					      edid->basic_display_parameters.video_input_parameters | 
				
			||||
 | 
					        .analog.composite_sync = 0x1 & multi_use_bool; | 
				
			||||
 | 
					      // Sync on green
 | 
				
			||||
 | 
					      json_scanf( json_str, json_len, | 
				
			||||
 | 
					                  "{video_input_parameters: {sync_on_green: %B}", | 
				
			||||
 | 
					                  &multi_use_bool); | 
				
			||||
 | 
					      edid->basic_display_parameters.video_input_parameters | 
				
			||||
 | 
					        .analog.sync_on_green = 0x1 & multi_use_bool; | 
				
			||||
 | 
					      // Vsync serrated
 | 
				
			||||
 | 
					      json_scanf( json_str, json_len, | 
				
			||||
 | 
					                  "{video_input_parameters: {blank_to_black: %B}", | 
				
			||||
 | 
					                  &multi_use_bool); | 
				
			||||
 | 
					      edid->basic_display_parameters.video_input_parameters | 
				
			||||
 | 
					        .analog.blank_to_black = 0x1 & multi_use_bool; | 
				
			||||
 | 
					    } else if (strcmp(multi_use_str, "digital") == 0) { | 
				
			||||
 | 
					      printf("Digital video configuration is not yet supported.\n"); | 
				
			||||
 | 
					      return 1; | 
				
			||||
 | 
					    } else { | 
				
			||||
 | 
					      printf("Error: JSON file format is wrong somewhere around\
 | 
				
			||||
 | 
					              the video input params.\n"); | 
				
			||||
 | 
					      return 2; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					  } else { | 
				
			||||
 | 
					    printf("One of either edid or json_str is NULL.\n"); | 
				
			||||
 | 
					    return 3; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					  return 0; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					int main(void) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					  //uint8_t edith[EDID_LENGTH];
 | 
				
			||||
 | 
					  edid_t edith; | 
				
			||||
 | 
					  memset(&edith, 0x00, sizeof(edith)); | 
				
			||||
 | 
					  printf("size> %d bytes\n", sizeof(edith)); | 
				
			||||
 | 
					  generate_preamble(&edith); | 
				
			||||
 | 
					  unsigned char* mystr = NULL; | 
				
			||||
 | 
					  size_t len = file_to_str(&mystr, "edid.json"); | 
				
			||||
 | 
					  if (mystr) { | 
				
			||||
 | 
					    printf("%s\n", mystr); | 
				
			||||
 | 
					    printf("len> %d\n", len); | 
				
			||||
 | 
					    //free(mystr);
 | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					  generate_header(&edith, mystr, len); | 
				
			||||
 | 
					  generate_video_input_parameters(&edith, mystr, len); | 
				
			||||
 | 
					  disp_buf((uint8_t*)&edith, EDID_LENGTH); | 
				
			||||
 | 
					  return 0; | 
				
			||||
 | 
					} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue