From 2dc232fcc3048120a120b94218309529072ad7e6 Mon Sep 17 00:00:00 2001 From: Maximilian Stiefel Date: Sun, 7 Jun 2020 19:12:46 +0200 Subject: [PATCH] Commiting work done so far --- .gitmodules | 3 + edid.json | 20 ++++ frozen | 1 + main.c | 300 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 324 insertions(+) create mode 100644 .gitmodules create mode 100644 edid.json create mode 160000 frozen create mode 100644 main.c diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..fc66cb0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "frozen"] + path = frozen + url = https://github.com/cesanta/frozen.git diff --git a/edid.json b/edid.json new file mode 100644 index 0000000..d51df62 --- /dev/null +++ b/edid.json @@ -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 + } +} \ No newline at end of file diff --git a/frozen b/frozen new file mode 160000 index 0000000..87beaaf --- /dev/null +++ b/frozen @@ -0,0 +1 @@ +Subproject commit 87beaaf0f0c93b2199e10e6f4a955803a6a035ba diff --git a/main.c b/main.c new file mode 100644 index 0000000..5f2015e --- /dev/null +++ b/main.c @@ -0,0 +1,300 @@ +#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; +}