Browse Source

Integration as a library now possible

master
Maximilian Stiefel 4 years ago
parent
commit
543b076b9e
  1. 299
      edid.c
  2. 208
      edid.h
  3. 0
      edid0.json
  4. BIN
      edid_wiki.pdf
  5. 78
      unit_test.c

299
main.c → edid.c

@ -1,11 +1,4 @@
#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
#include "edid.h"
enum edid_analog_display_t {
EDID_DISPLAY_TYPE_MONOCHROME_OR_GRAYSCALE = 0,
@ -27,217 +20,12 @@ enum edid_sync_mode_t {
EDID_SYNC_MODE_DIGITAL_SEPERATE = 3
};
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;
static int stp_round(const float in)
{
return (int)(in < 0 ? (in - 0.5) : (in + 0.5));
}
/**
* @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)
static size_t file_to_str(char** str, const char const* filename)
{
size_t length;
FILE * f = fopen (filename, "rb");
@ -674,7 +462,6 @@ static int generate_timings(edid_t* edid,
// 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) {
@ -896,7 +683,6 @@ static int generate_range_limit_descriptor(
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 {
@ -1057,29 +843,66 @@ static int generate_checksum(
return 0;
}
int main(void)
int generate_edid(edid_t* const edid, const char* const filename)
{
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_stockach.json");
if (mystr) {
printf("%s\n", mystr);
printf("len> %d\n", len);
char* json_str = NULL;
size_t len = 0;
if (edid && filename) {
// Initialize with all 0x00
memset(edid, 0x00, EDID_LEN);
len = file_to_str(&json_str, filename);
if (json_str) {
generate_preamble(edid);
if (generate_header(edid, json_str, len)) {
printf("Error: Problem generating header.\n");
return 1;
}
if (generate_basic_display_parameters(edid, json_str, len)) {
printf("Error: Problem generating basic display parameters.\n");
return 1;
}
if (generate_chromaticity_coordinates(edid, json_str, len)) {
printf("Error: Problem generating cromaticity coordinates.\n");
return 1;
}
if (generate_common_timing_modes(edid, json_str, len)) {
printf("Error: Problem generating commong timing modes.\n");
return 1;
}
if (generate_timings(edid, json_str, len)) {
printf("Error: Problem generating timings.\n");
return 1;
}
if (generate_detailed_timing_descriptor(edid, json_str, len)) {
printf("Error: Problem generating timing descriptor.\n");
return 1;
}
if (generate_range_limit_descriptor(edid, json_str, len)) {
printf("Error: Problem generating range limit descriptor.\n");
return 1;
}
if (generate_display_name_descriptor(edid, json_str, len)) {
printf("Error: Problem generating display name descriptor.\n");
return 1;
}
if (generate_display_serial_number_descriptor(edid, json_str, len)) {
printf("Error: Problem generating serial number descriptor.\n");
return 1;
}
if (generate_checksum(edid, json_str, len)) {
printf("Error: Problem generating checksum.\n");
return 1;
}
// We do not need the JSON string anymore
free(json_str);
} else {
printf("Error: json_str is NULL");
return 1;
}
} else {
printf("Error: One of either edid or filename is NULL.\n");
return 1;
}
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);
generate_range_limit_descriptor(&edith, mystr, len);
generate_display_name_descriptor(&edith, mystr, len);
generate_display_serial_number_descriptor(&edith, mystr, len);
generate_checksum(&edith, mystr, len);
disp_buf((uint8_t*)&edith, EDID_LEN);
free(mystr);
return 0;
}

208
edid.h

@ -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

0
edid_stockach.json → edid0.json

BIN
edid_wiki.pdf

Binary file not shown.

78
unit_test.c

@ -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…
Cancel
Save