diff options
author | Tom <tomut@yahoo.com> | 2021-12-26 22:19:55 -0700 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-01-23 22:45:21 +0000 |
commit | 8184870f93522e53e719a34861cad6337ae35cf0 (patch) | |
tree | 3764809487148ca025d93a1dbcd87f8425424149 /Tests | |
parent | c468a9cc2de5cf73b4724527740f7fd612728137 (diff) | |
download | serenity-8184870f93522e53e719a34861cad6337ae35cf0.zip |
LibEDID: Add a library to parse EDID blobs
This library can be used (for the most part) by kernel drivers as well
as user mode. For this reason FixedPoint is used rather than floating
point, but kept to a minimum.
Diffstat (limited to 'Tests')
-rw-r--r-- | Tests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Tests/LibEDID/CMakeLists.txt | 7 | ||||
-rw-r--r-- | Tests/LibEDID/TestEDID.cpp | 408 |
3 files changed, 416 insertions, 0 deletions
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index b7b2951385..17e076de14 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -4,6 +4,7 @@ add_subdirectory(LibC) add_subdirectory(LibCompress) add_subdirectory(LibCore) add_subdirectory(LibCpp) +add_subdirectory(LibEDID) add_subdirectory(LibELF) add_subdirectory(LibGfx) add_subdirectory(LibGL) diff --git a/Tests/LibEDID/CMakeLists.txt b/Tests/LibEDID/CMakeLists.txt new file mode 100644 index 0000000000..3349120f98 --- /dev/null +++ b/Tests/LibEDID/CMakeLists.txt @@ -0,0 +1,7 @@ +set(TEST_SOURCES + TestEDID.cpp +) + +foreach(source IN LISTS TEST_SOURCES) + serenity_test("${source}" LibEDID LIBS LibEDID) +endforeach() diff --git a/Tests/LibEDID/TestEDID.cpp b/Tests/LibEDID/TestEDID.cpp new file mode 100644 index 0000000000..aebde9f68f --- /dev/null +++ b/Tests/LibEDID/TestEDID.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2022, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibEDID/DMT.h> +#include <LibEDID/EDID.h> +#include <LibTest/TestCase.h> + +static const u8 edid1_bin[] = { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x49, 0x14, 0x34, 0x12, + 0x00, 0x00, 0x00, 0x00, 0x2a, 0x18, 0x01, 0x04, 0xa5, 0x1a, 0x13, 0x78, + 0x06, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0x21, + 0x08, 0x00, 0xe1, 0xc0, 0xd1, 0xc0, 0xd1, 0x00, 0xa9, 0x40, 0xb3, 0x00, + 0x95, 0x00, 0x81, 0x80, 0x81, 0x40, 0x25, 0x20, 0x00, 0x66, 0x41, 0x00, + 0x1a, 0x30, 0x00, 0x1e, 0x33, 0x40, 0x04, 0xc3, 0x10, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32, 0x7d, 0x1e, 0xa0, 0x78, 0x01, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x51, + 0x45, 0x4d, 0x55, 0x20, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x0a, + 0x00, 0x00, 0x00, 0xf7, 0x00, 0x0a, 0x00, 0x40, 0x82, 0x00, 0x28, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc4, 0x02, 0x03, 0x0a, 0x00, + 0x45, 0x7d, 0x65, 0x60, 0x59, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf2 +}; + +TEST_CASE(edid1) +{ + auto edid_load_result = EDID::Parser::from_bytes({ edid1_bin, sizeof(edid1_bin) }); + EXPECT(!edid_load_result.is_error()); + auto edid = edid_load_result.release_value(); + EXPECT(edid.legacy_manufacturer_id() == "RHT"); + EXPECT(!edid.aspect_ratio().has_value()); + auto screen_size = edid.screen_size(); + EXPECT(screen_size.has_value()); + EXPECT(screen_size.value().horizontal_cm() == 26); + EXPECT(screen_size.value().vertical_cm() == 19); + auto gamma = edid.gamma(); + EXPECT(gamma.has_value()); + EXPECT(gamma.value() >= 2.19f && gamma.value() <= 2.21f); + EXPECT(edid.display_product_name() == "QEMU Monitor"); + + { + static constexpr struct { + unsigned width; + unsigned height; + unsigned refresh_rate; + EDID::Parser::EstablishedTiming::Source source; + u8 dmt_id { 0 }; + } expected_established_timings[] = { + { 640, 480, 60, EDID::Parser::EstablishedTiming::Source::IBM, 0x4 }, + { 800, 600, 60, EDID::Parser::EstablishedTiming::Source::VESA, 0x9 }, + { 1024, 768, 60, EDID::Parser::EstablishedTiming::Source::VESA, 0x10 }, + { 1280, 768, 60, EDID::Parser::EstablishedTiming::Source::VESA, 0x17 }, + { 1360, 768, 60, EDID::Parser::EstablishedTiming::Source::VESA, 0x27 }, + { 1400, 1050, 60, EDID::Parser::EstablishedTiming::Source::VESA, 0x2a }, + { 1792, 1344, 60, EDID::Parser::EstablishedTiming::Source::VESA, 0x3e }, + { 1856, 1392, 60, EDID::Parser::EstablishedTiming::Source::VESA, 0x41 }, + { 1920, 1440, 60, EDID::Parser::EstablishedTiming::Source::VESA, 0x49 } + }; + static constexpr size_t expected_established_timings_count = sizeof(expected_established_timings) / sizeof(expected_established_timings[0]); + size_t established_timings_found = 0; + auto result = edid.for_each_established_timing([&](auto& established_timings) { + EXPECT(established_timings_found < expected_established_timings_count); + auto& expected_timings = expected_established_timings[established_timings_found]; + EXPECT(established_timings.width() == expected_timings.width); + EXPECT(established_timings.height() == expected_timings.height); + EXPECT(established_timings.refresh_rate() == expected_timings.refresh_rate); + EXPECT(established_timings.source() == expected_timings.source); + EXPECT(established_timings.dmt_id() == expected_timings.dmt_id); + established_timings_found++; + return IterationDecision::Continue; + }); + EXPECT(!result.is_error()); + EXPECT(result.value() == IterationDecision::Continue); + EXPECT(established_timings_found == expected_established_timings_count); + } + + { + static constexpr struct { + unsigned width; + unsigned height; + unsigned refresh_rate; + u8 dmt_id { 0 }; + } expected_standard_established_timings[] = { + { 2048, 1152, 60, 0x54 }, + { 1920, 1080, 60, 0x52 }, + { 1920, 1200, 60, 0x45 }, + { 1600, 1200, 60, 0x33 }, + { 1680, 1050, 60, 0x3a }, + { 1440, 900, 60, 0x2f }, + { 1280, 1024, 60, 0x23 }, + { 1280, 960, 60, 0x20 } + }; + static constexpr size_t expected_standard_timings_count = sizeof(expected_standard_established_timings) / sizeof(expected_standard_established_timings[0]); + size_t standard_timings_found = 0; + auto result = edid.for_each_standard_timing([&](auto& standard_timings) { + EXPECT(standard_timings_found < expected_standard_timings_count); + auto& expected_timings = expected_standard_established_timings[standard_timings_found]; + EXPECT(standard_timings.dmt_id() == expected_timings.dmt_id); + EXPECT(standard_timings.width() == expected_timings.width); + EXPECT(standard_timings.height() == expected_timings.height); + EXPECT(standard_timings.refresh_rate() == expected_timings.refresh_rate); + standard_timings_found++; + return IterationDecision::Continue; + }); + EXPECT(!result.is_error()); + EXPECT(result.value() == IterationDecision::Continue); + EXPECT(standard_timings_found == expected_standard_timings_count); + } + + { + static constexpr struct { + unsigned block_id; + unsigned width; + unsigned height; + unsigned refresh_rate; + } expected_detailed_timings[] = { + { 0, 1024, 768, 75 } + }; + static constexpr size_t expected_detailed_timings_count = sizeof(expected_detailed_timings) / sizeof(expected_detailed_timings[0]); + size_t detailed_timings_found = 0; + auto result = edid.for_each_detailed_timing([&](auto& detailed_timing, unsigned block_id) { + EXPECT(detailed_timings_found < expected_detailed_timings_count); + auto& expected_timings = expected_detailed_timings[detailed_timings_found]; + EXPECT(block_id == expected_timings.block_id); + EXPECT(detailed_timing.horizontal_addressable_pixels() == expected_timings.width); + EXPECT(detailed_timing.vertical_addressable_lines() == expected_timings.height); + EXPECT(detailed_timing.refresh_rate().lround() == expected_timings.refresh_rate); + detailed_timings_found++; + return IterationDecision::Continue; + }); + EXPECT(!result.is_error()); + EXPECT(result.value() == IterationDecision::Continue); + EXPECT(detailed_timings_found == expected_detailed_timings_count); + } + + { + static constexpr u8 expected_vic_ids[] = { 125, 101, 96, 89, 31 }; + static constexpr size_t expected_vic_ids_count = sizeof(expected_vic_ids) / sizeof(expected_vic_ids[0]); + size_t vic_ids_found = 0; + auto result = edid.for_each_short_video_descriptor([&](unsigned block_id, bool is_native, EDID::VIC::Details const& vic) { + EXPECT(vic_ids_found < expected_vic_ids_count); + EXPECT(block_id == 1); + EXPECT(!is_native); // none are marked as native + EXPECT(vic.vic_id == expected_vic_ids[vic_ids_found]); + vic_ids_found++; + return IterationDecision::Continue; + }); + EXPECT(!result.is_error()); + EXPECT(result.value() == IterationDecision::Continue); + EXPECT(vic_ids_found == expected_vic_ids_count); + } + + { + // This edid has one CEA861 extension block only + size_t extension_blocks_found = 0; + auto result = edid.for_each_extension_block([&](unsigned block_id, u8 tag, u8 revision, ReadonlyBytes) { + EXPECT(block_id == 1); + EXPECT(tag == 0x2); + EXPECT(revision == 3); + extension_blocks_found++; + return IterationDecision::Continue; + }); + EXPECT(!result.is_error()); + EXPECT(result.value() == IterationDecision::Continue); + EXPECT(extension_blocks_found == 1); + } +} + +static const u8 edid2_bin[] = { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x72, 0x1d, 0x08, + 0xd2, 0x02, 0x96, 0x49, 0x20, 0x1e, 0x01, 0x04, 0xb5, 0x3c, 0x22, 0x78, + 0x3b, 0xff, 0x15, 0xa6, 0x53, 0x4a, 0x98, 0x26, 0x0f, 0x50, 0x54, 0xbf, + 0xef, 0x80, 0xd1, 0xc0, 0xb3, 0x00, 0x95, 0x00, 0x81, 0x80, 0x81, 0x40, + 0x81, 0xc0, 0x01, 0x01, 0x01, 0x01, 0x86, 0x6f, 0x00, 0x3c, 0xa0, 0xa0, + 0x0f, 0x50, 0x08, 0x20, 0x35, 0x00, 0x55, 0x50, 0x21, 0x00, 0x00, 0x1e, + 0x56, 0x5e, 0x00, 0xa0, 0xa0, 0xa0, 0x29, 0x50, 0x30, 0x20, 0x35, 0x00, + 0x55, 0x50, 0x21, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x30, + 0x4b, 0x78, 0x78, 0x1e, 0x01, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x43, 0x42, 0x32, 0x37, 0x32, 0x55, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xc5, 0x02, 0x03, 0x33, 0x71, + 0x4c, 0x12, 0x13, 0x04, 0x1f, 0x90, 0x14, 0x05, 0x01, 0x11, 0x02, 0x03, + 0x4a, 0x23, 0x09, 0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0xe2, 0x00, 0xc0, + 0x67, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x38, 0x3c, 0xe3, 0x05, 0xe3, 0x01, + 0xe3, 0x0f, 0x00, 0x00, 0xe6, 0x06, 0x07, 0x01, 0x60, 0x60, 0x45, 0x01, + 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0x55, + 0x50, 0x21, 0x00, 0x00, 0x1e, 0x01, 0x1d, 0x00, 0xbc, 0x52, 0xd0, 0x1e, + 0x20, 0xb8, 0x28, 0x55, 0x40, 0x55, 0x50, 0x21, 0x00, 0x00, 0x1e, 0x56, + 0x5e, 0x00, 0xa0, 0xa0, 0xa0, 0x29, 0x50, 0x30, 0x20, 0x35, 0x00, 0x55, + 0x50, 0x21, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe1 +}; + +TEST_CASE(edid2) +{ + auto edid_load_result = EDID::Parser::from_bytes({ edid2_bin, sizeof(edid2_bin) }); + EXPECT(!edid_load_result.is_error()); + auto edid = edid_load_result.release_value(); + EXPECT(edid.legacy_manufacturer_id() == "ACR"); + EXPECT(edid.serial_number() == 1234567890); + auto digital_interface = edid.digital_display(); + EXPECT(digital_interface.has_value()); + EXPECT(digital_interface.value().color_bit_depth() == EDID::Parser::DigitalDisplay::ColorBitDepth::BPP_10); + EXPECT(digital_interface.value().supported_interface() == EDID::Parser::DigitalDisplay::SupportedInterface::DisplayPort); + EXPECT(!digital_interface.value().features().supports_standby()); + EXPECT(!digital_interface.value().features().supports_suspend()); + EXPECT(digital_interface.value().features().supports_off()); + EXPECT(digital_interface.value().features().preferred_timing_mode_includes_pixel_format_and_refresh_rate()); + EXPECT(!digital_interface.value().features().srgb_is_default_color_space()); + EXPECT(digital_interface.value().features().frequency() == EDID::Parser::DigitalDisplayFeatures::Frequency::Continuous); + EXPECT(digital_interface.value().features().supported_color_encodings() == EDID::Parser::DigitalDisplayFeatures::SupportedColorEncodings::RGB444_YCrCb444_YCrCb422); + EXPECT(!edid.aspect_ratio().has_value()); + auto screen_size = edid.screen_size(); + EXPECT(screen_size.has_value()); + EXPECT(screen_size.value().horizontal_cm() == 60); + EXPECT(screen_size.value().vertical_cm() == 34); + auto gamma = edid.gamma(); + EXPECT(gamma.has_value()); + EXPECT(gamma.value() >= 2.19f && gamma.value() <= 2.21f); + EXPECT(edid.display_product_name() == "CB272U"); + + { + static constexpr struct { + unsigned width; + unsigned height; + unsigned refresh_rate; + EDID::Parser::EstablishedTiming::Source source; + u8 dmt_id { 0 }; + } expected_established_timings[] = { + { 720, 400, 70, EDID::Parser::EstablishedTiming::Source::IBM }, + { 640, 480, 60, EDID::Parser::EstablishedTiming::Source::IBM, 0x4 }, + { 640, 480, 67, EDID::Parser::EstablishedTiming::Source::Apple }, + { 640, 480, 73, EDID::Parser::EstablishedTiming::Source::VESA, 0x5 }, + { 640, 480, 75, EDID::Parser::EstablishedTiming::Source::VESA, 0x6 }, + { 800, 600, 56, EDID::Parser::EstablishedTiming::Source::VESA, 0x8 }, + { 800, 600, 60, EDID::Parser::EstablishedTiming::Source::VESA, 0x9 }, + { 800, 600, 72, EDID::Parser::EstablishedTiming::Source::VESA, 0xa }, + { 800, 600, 75, EDID::Parser::EstablishedTiming::Source::VESA, 0xb }, + { 832, 624, 75, EDID::Parser::EstablishedTiming::Source::Apple }, + { 1024, 768, 60, EDID::Parser::EstablishedTiming::Source::VESA, 0x10 }, + { 1024, 768, 70, EDID::Parser::EstablishedTiming::Source::VESA, 0x11 }, + { 1024, 768, 75, EDID::Parser::EstablishedTiming::Source::VESA, 0x12 }, + { 1280, 1024, 75, EDID::Parser::EstablishedTiming::Source::VESA, 0x24 }, + { 1152, 870, 75, EDID::Parser::EstablishedTiming::Source::Apple } + }; + static constexpr size_t expected_established_timings_count = sizeof(expected_established_timings) / sizeof(expected_established_timings[0]); + size_t established_timings_found = 0; + auto result = edid.for_each_established_timing([&](auto& established_timings) { + EXPECT(established_timings_found < expected_established_timings_count); + auto& expected_timings = expected_established_timings[established_timings_found]; + EXPECT(established_timings.width() == expected_timings.width); + EXPECT(established_timings.height() == expected_timings.height); + EXPECT(established_timings.refresh_rate() == expected_timings.refresh_rate); + EXPECT(established_timings.source() == expected_timings.source); + EXPECT(established_timings.dmt_id() == expected_timings.dmt_id); + established_timings_found++; + return IterationDecision::Continue; + }); + EXPECT(!result.is_error()); + EXPECT(result.value() == IterationDecision::Continue); + EXPECT(established_timings_found == expected_established_timings_count); + } + + { + static constexpr struct { + unsigned width; + unsigned height; + unsigned refresh_rate; + u8 dmt_id { 0 }; + } expected_standard_established_timings[] = { + { 1920, 1080, 60, 0x52 }, + { 1680, 1050, 60, 0x3a }, + { 1440, 900, 60, 0x2f }, + { 1280, 1024, 60, 0x23 }, + { 1280, 960, 60, 0x20 }, + { 1280, 720, 60, 0x55 }, + }; + static constexpr size_t expected_standard_timings_count = sizeof(expected_standard_established_timings) / sizeof(expected_standard_established_timings[0]); + size_t standard_timings_found = 0; + auto result = edid.for_each_standard_timing([&](auto& standard_timings) { + EXPECT(standard_timings_found < expected_standard_timings_count); + auto& expected_timings = expected_standard_established_timings[standard_timings_found]; + EXPECT(standard_timings.dmt_id() == expected_timings.dmt_id); + EXPECT(standard_timings.width() == expected_timings.width); + EXPECT(standard_timings.height() == expected_timings.height); + EXPECT(standard_timings.refresh_rate() == expected_timings.refresh_rate); + standard_timings_found++; + return IterationDecision::Continue; + }); + EXPECT(!result.is_error()); + EXPECT(result.value() == IterationDecision::Continue); + EXPECT(standard_timings_found == expected_standard_timings_count); + } + + { + static constexpr struct { + unsigned block_id; + unsigned width; + unsigned height; + unsigned refresh_rate; + } expected_detailed_timings[] = { + { 0, 2560, 1440, 75 }, + { 0, 2560, 1440, 60 }, + { 1, 1280, 720, 60 }, + { 1, 1280, 720, 50 }, + { 1, 2560, 1440, 60 } + }; + static constexpr size_t expected_detailed_timings_count = sizeof(expected_detailed_timings) / sizeof(expected_detailed_timings[0]); + size_t detailed_timings_found = 0; + auto result = edid.for_each_detailed_timing([&](auto& detailed_timing, unsigned block_id) { + EXPECT(detailed_timings_found < expected_detailed_timings_count); + auto& expected_timings = expected_detailed_timings[detailed_timings_found]; + EXPECT(block_id == expected_timings.block_id); + EXPECT(detailed_timing.horizontal_addressable_pixels() == expected_timings.width); + EXPECT(detailed_timing.vertical_addressable_lines() == expected_timings.height); + EXPECT(detailed_timing.refresh_rate().lround() == expected_timings.refresh_rate); + detailed_timings_found++; + return IterationDecision::Continue; + }); + EXPECT(!result.is_error()); + EXPECT(result.value() == IterationDecision::Continue); + EXPECT(detailed_timings_found == expected_detailed_timings_count); + } + + { + static constexpr u8 expected_vic_ids[] = { 18, 19, 4, 31, 16, 20, 5, 1, 17, 2, 3, 74 }; + static constexpr size_t expected_vic_ids_count = sizeof(expected_vic_ids) / sizeof(expected_vic_ids[0]); + size_t vic_ids_found = 0; + auto result = edid.for_each_short_video_descriptor([&](unsigned block_id, bool is_native, EDID::VIC::Details const& vic) { + EXPECT(vic_ids_found < expected_vic_ids_count); + EXPECT(block_id == 1); + EXPECT(is_native == (vic_ids_found == 4)); // the 5th value is marked native + EXPECT(vic.vic_id == expected_vic_ids[vic_ids_found]); + vic_ids_found++; + return IterationDecision::Continue; + }); + EXPECT(!result.is_error()); + EXPECT(result.value() == IterationDecision::Continue); + EXPECT(vic_ids_found == expected_vic_ids_count); + } + + { + // This edid has one CEA861 extension block only + size_t extension_blocks_found = 0; + auto result = edid.for_each_extension_block([&](unsigned block_id, u8 tag, u8 revision, ReadonlyBytes) { + EXPECT(block_id == 1); + EXPECT(tag == 0x2); + EXPECT(revision == 3); + extension_blocks_found++; + return IterationDecision::Continue; + }); + EXPECT(!result.is_error()); + EXPECT(result.value() == IterationDecision::Continue); + EXPECT(extension_blocks_found == 1); + } +} + +TEST_CASE(dmt_find_std_id) +{ + auto* dmt = EDID::DMT::find_timing_by_std_id(0xd1, 0xf); + EXPECT(dmt); + EXPECT(dmt->dmt_id == 0x46); + EXPECT(dmt->horizontal_pixels == 1920 && dmt->vertical_lines == 1200); +} + +TEST_CASE(dmt_frequency) +{ + auto* dmt = EDID::DMT::find_timing_by_dmt_id(0x4); + EXPECT(dmt); + static constexpr FixedPoint<16, u32> expected_vertical_frequency(59.940); + EXPECT(dmt->vertical_frequency_hz() == expected_vertical_frequency); + static constexpr FixedPoint<16, u32> expected_horizontal_frequency(31.469); + EXPECT(dmt->horizontal_frequency_khz() == expected_horizontal_frequency); +} + +TEST_CASE(vic) +{ + EXPECT(!EDID::VIC::find_details_by_vic_id(0)); // invalid + EXPECT(!EDID::VIC::find_details_by_vic_id(160)); // forbidden range + EXPECT(!EDID::VIC::find_details_by_vic_id(250)); // reserved + auto* vic_def_32 = EDID::VIC::find_details_by_vic_id(32); + EXPECT(vic_def_32); + EXPECT(vic_def_32->vic_id == 32); + auto* vic_def_200 = EDID::VIC::find_details_by_vic_id(200); + EXPECT(vic_def_200); + EXPECT(vic_def_200->vic_id == 200); + + for (unsigned vic_id = 0; vic_id <= 0xff; vic_id++) { + auto* vic_def = EDID::VIC::find_details_by_vic_id((u8)vic_id); + if (vic_def) { + EXPECT((vic_id >= 1 && vic_id <= 127) || (vic_id >= 193 && vic_id <= 219)); + EXPECT(vic_def->vic_id == vic_id); + } else { + EXPECT(vic_id == 0 || (vic_id >= 128 && vic_id <= 192) || (vic_id >= 220)); + } + } +} |