#include #include #include #include #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; }