Browse Source

Detailed timings descriptor finished

master
Maximilian Stiefel 4 years ago
parent
commit
44b14682d6
  1. 63
      edid_stockach.json
  2. BIN
      main
  3. 309
      main.c

63
edid_stockach.json

@ -64,5 +64,68 @@
"m1024_768_75": true,
"m1280_1024_75": true,
"m1152_870_75": true
},
"timings": [
{
"x_resolution": 1680,
"aspect_ratio": "16:10",
"vertical_frequency": 60
},
{
"x_resolution": 1280,
"aspect_ratio": "5:4",
"vertical_frequency": 60
},
{
"x_resolution": 1440,
"aspect_ratio": "16:10",
"vertical_frequency": 60
},
{
"x_resolution": 1152,
"aspect_ratio": "4:3",
"vertical_frequency": 75
},
{
"x_resolution": 1600,
"aspect_ratio": "16:9",
"vertical_frequency": 60
},
{
"x_resolution": 1280,
"aspect_ratio": "16:10",
"vertical_frequency": 60
},
{
"x_resolution": 1280,
"aspect_ratio": "16:9",
"vertical_frequency": 60
},
{
"x_resolution": 1400,
"aspect_ratio": "4:3",
"vertical_frequency": 60
}
],
"detailed_timing_descriptor": {
"pixel_clock_mhz": 148.5,
"horizontal_active_pixels": 1920,
"horizontal_blanking_pixels": 280,
"vertical_active_lines": 1080,
"vertical_blanking_lines": 45,
"horizontal_front_porch_pixels": 88,
"horizontal_sync_pulse_pixels": 44,
"vertical_front_porch_lines": 4,
"vertical_sync_pulse_lines": 5,
"horizontal_image_size_mm": 521,
"vertical_image_size_mm": 293,
"horizontal_border_pixels": 0,
"vertical_border_lines": 0,
"stereo_mode": "none",
"interlaced": false,
"digital_seperate_sync": {
"vertical_sync_serration": true,
"horizontal_sync_polarity": "positive"
}
}
}

BIN
main

Binary file not shown.

309
main.c

@ -5,9 +5,6 @@
#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
enum edid_analog_display_t {
EDID_DISPLAY_TYPE_MONOCHROME_OR_GRAYSCALE = 0,
@ -16,12 +13,79 @@ enum edid_analog_display_t {
EDID_DISPLAY_TYPE_UNDEFINED = 3
};
enum edid_aspect_ratio_t {
EDID_ASPECT_RATIO_16_10 = 0,
EDID_ASPECT_RATIO_4_3 = 1,
EDID_ASPECT_RATIO_5_4 = 2,
EDID_ASPECT_RATIO_16_9 = 3
};
enum edid_sync_mode_t {
EDID_SYNC_MODE_ANALOG = 0,
EDID_SYNC_MODE_DIGITAL_COMPOSITE = 2,
EDID_SYNC_MODE_DIGITAL_SEPERATE = 3
};
typedef struct __attribute__ (( packed )) {
uint8_t resolution;
uint8_t image_aspect_ratio : 2;
uint8_t vertical_frequency : 6;
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 )) {
/*! Header information, 20 bytes */
struct __attribute__ (( packed )) {
@ -114,10 +178,13 @@ 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_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];
uint8_t number_extensions;
uint8_t checksum;
} edid_t;
@ -563,6 +630,231 @@ static int generate_common_timing_modes( edid_t* edid,
return 0;
}
static int generate_timings(edid_t* edid,
unsigned char* json_str,
size_t json_len)
{
struct json_token multi_use_token;
float multi_use_flt;
int multi_use_int;
char* multi_use_str;
if (edid && json_str) {
int i = 0;
for (i = 0; json_scanf_array_elem(json_str, json_len, ".timings", i, &multi_use_token) > 0; i++) {
// t.type == JSON_TYPE_OBJECT
// X resolution
json_scanf(multi_use_token.ptr, multi_use_token.len, "{x_resolution: %f}", &multi_use_flt);
edid->timings[i].x_resolution = stp_round(multi_use_flt/8-31);
printf("res> %f\n", multi_use_flt);
// Aspect ratio
json_scanf(multi_use_token.ptr, multi_use_token.len, "{aspect_ratio: %Q}", &multi_use_str);
if (strcmp(multi_use_str, "16:10") == 0) {
edid->timings[i].aspect_ratio = 0x3 & EDID_ASPECT_RATIO_16_10;
} else if (strcmp(multi_use_str, "4:3") == 0) {
edid->timings[i].aspect_ratio = 0x3 & EDID_ASPECT_RATIO_4_3;
} else if (strcmp(multi_use_str, "5:4") == 0) {
edid->timings[i].aspect_ratio = 0x3 & EDID_ASPECT_RATIO_5_4;
} else if (strcmp(multi_use_str, "16:9") == 0) {
edid->timings[i].aspect_ratio = 0x3 & EDID_ASPECT_RATIO_16_9;
} else {
printf("Error: Aspect ratio not supported");
return 1;
}
// Free string that has been allocated in memory
free(multi_use_str);
// Vertical frequency
json_scanf(multi_use_token.ptr, multi_use_token.len, "{vertical_frequency: %d}", &multi_use_int);
if (multi_use_int >= 60) {
edid->timings[i].vertical_frequency = multi_use_int-60;
} else {
printf("Error: Vertical frequency cannot be lower than 60 Hz.\n");
return 1;
}
}
} else {
printf("Error: One of either edid or json_str is NULL.\n");
return 1;
}
return 0;
}
static int generate_detailed_timing_descriptor(
edid_t* edid,
unsigned char* json_str,
size_t json_len)
{
unsigned int multi_use_int;
float multi_use_float;
struct json_token multi_use_token;
bool multi_use_bool;
char* multi_use_str;
if (edid && json_str) {
// Pixel clock
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {pixel_clock_mhz: %f}}",
&multi_use_float);
/* The data is stored as 10 kHz unitsi in the EDID structure.
It is a float representing MHz in the JSON file.
*/
edid->detailed_timing_descriptor.pixel_clock = stp_round(multi_use_float/0.01f);
// Horizontal active pixels
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {horizontal_active_pixels: %d}}",
&multi_use_int);
edid->detailed_timing_descriptor
.horizontal_active_pixels_lsbs = 0xFF & multi_use_int;
edid->detailed_timing_descriptor
.horizontal_active_pixels_msbs = 0x0F & (multi_use_int >> 8);
// Horizontal blanking pixels
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {horizontal_blanking_pixels: %d}}",
&multi_use_int);
edid->detailed_timing_descriptor
.horizontal_blanking_pixels_lsbs = 0xFF & multi_use_int;
edid->detailed_timing_descriptor
.horizontal_blanking_pixels_msbs = 0x0F & (multi_use_int >> 8);
// Vertical active lines
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {vertical_active_lines: %d}}",
&multi_use_int);
edid->detailed_timing_descriptor
.vertical_active_lines_lsbs = 0xFF & multi_use_int;
edid->detailed_timing_descriptor
.vertical_active_lines_msbs = 0x0F & (multi_use_int >> 8);
// Vertical blanking lines
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {vertical_blanking_lines: %d}}",
&multi_use_int);
edid->detailed_timing_descriptor
.vertical_blanking_lines_lsbs = 0xFF & multi_use_int;
edid->detailed_timing_descriptor
.vertical_blanking_lines_msbs = 0x0F & (multi_use_int >> 8);
// Horizontal front porch pixels
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {horizontal_front_porch_pixels: %d}}",
&multi_use_int);
edid->detailed_timing_descriptor
.horizontal_front_porch_pixels_lsbs = 0xFF & multi_use_int;
edid->detailed_timing_descriptor
.horizontal_front_porch_pixels_msbs = 0x03 & (multi_use_int >> 8);
// Horizontal sync pulse pixels
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {horizontal_sync_pulse_pixels: %d}}",
&multi_use_int);
edid->detailed_timing_descriptor
.horizontal_sync_pulse_pixels_lsbs = 0xFF & multi_use_int;
edid->detailed_timing_descriptor
.horizontal_sync_pulse_pixels_msbs = 0x03 & (multi_use_int >> 8);
// Vertical front porch lines
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {vertical_front_porch_lines: %d}}",
&multi_use_int);
edid->detailed_timing_descriptor
.vertical_front_porch_lines_lsbs = 0x0F & multi_use_int;
edid->detailed_timing_descriptor
.vertical_front_porch_lines_msbs = 0x03 & (multi_use_int >> 4);
// Vertical sync pulse lines
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {vertical_sync_pulse_lines: %d}}",
&multi_use_int);
edid->detailed_timing_descriptor
.vertical_sync_pulse_lines_lsbs = 0x0F & multi_use_int;
edid->detailed_timing_descriptor
.vertical_sync_pulse_lines_msbs = 0x03 & (multi_use_int >> 4);
// Horizontal image size
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {horizontal_image_size_mm: %d}}",
&multi_use_int);
edid->detailed_timing_descriptor
.horizontal_image_size_lsbs = 0xFF & multi_use_int;
edid->detailed_timing_descriptor
.horizontal_image_size_msbs = 0x0F & (multi_use_int >> 8);
// Vertical image size
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {vertical_image_size_mm: %d}}",
&multi_use_int);
edid->detailed_timing_descriptor
.vertical_image_size_lsbs = 0xFF & multi_use_int;
edid->detailed_timing_descriptor
.vertical_image_size_msbs = 0x0F & (multi_use_int >> 8);
// Horizontal border pixels
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {horizontal_border_pixels: %d}}",
&multi_use_int);
edid->detailed_timing_descriptor
.horizontal_border_pixels = 0xFF & multi_use_int;
// Vertical border lines
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {vertical_border_lines: %d}}",
&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}}",
&multi_use_str);
if (strcmp(multi_use_str, "none") == 0) {
multi_use_int = 0;
} else {
printf("Error: This stereo mode is not implemented yet.\n");
return 1;
}
free(multi_use_str);
edid->detailed_timing_descriptor
.features.digital_seperate.stereo_mode_lsb = 0x1 & multi_use_int;
edid->detailed_timing_descriptor
.features.digital_seperate.stereo_mode_msbs = 0x3 & (multi_use_int >> 1);
// Interlaced
json_scanf( json_str, json_len,
"{detailed_timing_descriptor: {interlaced: %B}}",
&multi_use_bool);
edid->detailed_timing_descriptor
.features.digital_seperate.interlaced = multi_use_bool;
// Sync details
if (json_scanf(json_str, json_len,
"{detailed_timing_descriptor: { digital_seperate_sync: %T}}",
&multi_use_token) > 0) {
// Set sync mode
edid->detailed_timing_descriptor
.features.digital_seperate.digital_seperate_sync = 0x3 & EDID_SYNC_MODE_DIGITAL_SEPERATE;
// Vertical sync serration
json_scanf( multi_use_token.ptr, multi_use_token.len,
"{vertical_sync_serration: %B}",
&multi_use_bool);
edid->detailed_timing_descriptor
.features.digital_seperate.vertical_sync_serration = multi_use_bool;
// Horizontal sync polarity
json_scanf( multi_use_token.ptr, multi_use_token.len,
"{horizontal_sync_polarity: %Q}",
&multi_use_str);
if (strcmp(multi_use_str, "positive") == 0) {
multi_use_bool = true;
} else if (strcmp(multi_use_str, "negative") == 0) {
multi_use_bool = false;
} else {
printf("Error: The horizontal sync polarity can either be positive or negative (JSON string).\n");
return 1;
}
edid->detailed_timing_descriptor
.features.digital_seperate.horizontal_sync_polarity = multi_use_bool;
free(multi_use_str);
} else {
printf("Error: Could not parse JSON file somewhere arround sync \
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;
}
int main(void)
{
//uint8_t edith[EDID_LENGTH];
@ -575,12 +867,13 @@ int main(void)
if (mystr) {
printf("%s\n", mystr);
printf("len> %d\n", len);
//free(mystr);
}
generate_header(&edith, mystr, len);
generate_basic_display_parameters(&edith, mystr, len);
generate_chromaticity_coordinates(&edith, mystr, len);
generate_common_timing_modes(&edith, mystr, len);
generate_timings(&edith, mystr, len);
generate_detailed_timing_descriptor(&edith, mystr, len);
disp_buf((uint8_t*)&edith, EDID_LENGTH);
free(mystr);
return 0;

Loading…
Cancel
Save