diff --git a/edid_stockach.json b/edid_stockach.json index 9856eb6..22d755d 100644 --- a/edid_stockach.json +++ b/edid_stockach.json @@ -127,5 +127,26 @@ "vertical_sync_serration": true, "horizontal_sync_polarity": "positive" } + }, + "range_limits_descriptor": { + "rate_offsets": { + "vertical": "none", + "horizontal": "none" + }, + "rates": { + "vertical": { + "minimum_hz": 56, + "maximum_hz": 75 + }, + "horizontal": { + "minimum_khz": 30, + "maximum_khz": 83 + } + }, + "maximum_pixel_clock_mhz": 150, + "extended_timing_information_type": "default_gtf" + }, + "display_name_descriptor": { + "name": "24EN33" } } diff --git a/main.c b/main.c index 52e5dce..2782db3 100644 --- a/main.c +++ b/main.c @@ -86,6 +86,36 @@ typedef struct __attribute__ (( packed )) { } 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[13]; +} display_descriptor_t; + typedef struct __attribute__ (( packed )) { /*! Header information, 20 bytes */ struct __attribute__ (( packed )) { @@ -178,13 +208,10 @@ typedef struct __attribute__ (( packed )) { /*! 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]; -*/ detailed_timing_descriptor_t detailed_timing_descriptor; - detailed_timing_descriptor_t descriptors[3]; + 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; @@ -791,8 +818,6 @@ static int generate_detailed_timing_descriptor( &multi_use_int); edid->detailed_timing_descriptor .vertical_border_lines = 0xFF & multi_use_int; -#define PETER -#ifdef PETER // Sync features bitmap json_scanf( json_str, json_len, "{detailed_timing_descriptor: {stereo_mode: %Q}}", @@ -847,7 +872,122 @@ static int generate_detailed_timing_descriptor( features in detailed timing descriptor.\n"); return 1; } -#endif + } else { + printf("Error: One of either edid or json_str is NULL.\n"); + return 1; + } + return 0; +} + +static int generate_range_limit_descriptor( + edid_t* edid, + unsigned char* json_str, + size_t json_len) +{ + char* multi_use_str; + unsigned multi_use_int; + + if (edid && json_str) { + edid->range_limits_descriptor.display_descriptor = 0; + edid->range_limits_descriptor.reserved = 0; + edid->range_limits_descriptor.display_range_limits_descriptor = 0xFD; + // Range offsets + int n = json_scanf( json_str, json_len, + "{range_limits_descriptor: {rate_offsets: {vertical: %Q}}}", + &multi_use_str); + printf("n>%d\n", n); + if (strcmp(multi_use_str, "none") == 0) { + edid->range_limits_descriptor.rate_offsets.vertical = 0; + } else { + printf("Error: Range limit offset other than none is not yet implemented.\n"); + return 1; + } + free(multi_use_str); + json_scanf( json_str, json_len, + "{range_limits_descriptor: {rate_offsets: {horizontal: %Q}}}", + &multi_use_str); + if (strcmp(multi_use_str, "none") == 0) { + edid->range_limits_descriptor.rate_offsets.horizontal = 0; + } else { + printf("Error: Range limit offset other than none is not yet implemented.\n"); + return 1; + } + free(multi_use_str); + // Vertical and horizontal lines + json_scanf( json_str, json_len, + "{range_limits_descriptor: {rates: {vertical: {minimum_hz: %d}}}}", + &multi_use_int); + edid->range_limits_descriptor.vertical_field_rate.minimum = 0xFF & multi_use_int; + json_scanf( json_str, json_len, + "{range_limits_descriptor: {rates: {vertical: {maximum_hz: %d}}}}", + &multi_use_int); + edid->range_limits_descriptor.vertical_field_rate.maximum = 0xFF & multi_use_int; + json_scanf( json_str, json_len, + "{range_limits_descriptor: {rates: {horizontal: {minimum_khz: %d}}}}", + &multi_use_int); + edid->range_limits_descriptor.horizontal_line_rate.minimum = 0xFF & multi_use_int; + json_scanf( json_str, json_len, + "{range_limits_descriptor: {rates: {horizontal: {maximum_khz: %d}}}}", + &multi_use_int); + edid->range_limits_descriptor.horizontal_line_rate.maximum = 0xFF & multi_use_int; + // Maximum pixel clock rate + json_scanf( json_str, json_len, + "{range_limits_descriptor: {maximum_pixel_clock_mhz: %d}}", + &multi_use_int); + // Multiples of 10 MHz + edid->range_limits_descriptor.maximum_pixel_clock_mhz = 0xFF & (multi_use_int/10); + json_scanf( json_str, json_len, + "{range_limits_descriptor: {extended_timing_information_type: %Q}}", + &multi_use_str); + if (strcmp(multi_use_str, "default_gtf") == 0) { + edid->range_limits_descriptor.extended_timing_information_type = 0; + // Apply padding for video timing parameters + edid->range_limits_descriptor.video_timing_params[0] = 0x0A; + memset(edid->range_limits_descriptor.video_timing_params + 1, 0x20, 6); + } else { + printf("Error: Any other timing information type than default_gtf is currently not implemented.\n"); + return 1; + } + free(multi_use_str); + } else { + printf("Error: One of either edid or json_str is NULL.\n"); + return 1; + } + return 0; +} + +static int generate_display_name_descriptor( + edid_t* edid, + unsigned char* json_str, + size_t json_len) +{ + char* display_name = NULL; + + if (edid && json_str) { + edid->display_name_descriptor.display_descriptor = 0; + edid->display_name_descriptor.reserved0 = 0; + edid->display_name_descriptor.descriptor_type = 0xFC; + edid->display_name_descriptor.reserved1 = 0; + json_scanf( json_str, json_len, + "{display_name_descriptor: {name: %Q}}", + &display_name); + if (display_name != NULL) { + if (strlen(display_name) <= 13) { + memcpy(edid->display_name_descriptor.descriptor_data, display_name, strlen(display_name)); + if (strlen(display_name) < 13) { + memset( edid->display_name_descriptor.descriptor_data + + strlen(display_name), 0x0A, 1); + memset( edid->display_name_descriptor.descriptor_data + + strlen(display_name) + 1, 0x20, 13-strlen(display_name)-1); + } + } else { + printf("Error: Display name is too long.\n"); + return 1; + } + } else { + printf("Error: Could not parse JSON file somewhere around display_name_descriptor.\n"); + return 1; + } } else { printf("Error: One of either edid or json_str is NULL.\n"); return 1; @@ -874,6 +1014,8 @@ int main(void) generate_common_timing_modes(&edith, mystr, len); generate_timings(&edith, mystr, len); generate_detailed_timing_descriptor(&edith, mystr, len); + generate_range_limit_descriptor(&edith, mystr, len); + generate_display_name_descriptor(&edith, mystr, len); disp_buf((uint8_t*)&edith, EDID_LENGTH); free(mystr); return 0;