| // Copyright (c) Microsoft Corporation |
| |
| #include "Edid.h" |
| #include <cassert> |
| |
| namespace display::test { |
| bool EdidTimingEntry::SetMode(unsigned short width, |
| unsigned short height, |
| unsigned short freq) { |
| if (width < 256 || width > 2288) { |
| return false; |
| } |
| if (freq < 60 || freq > 123) { |
| return false; |
| } |
| if (height == (width / 16) * 10) { |
| aspect_ratio = 0b00; // 16:10 |
| } else if (height == (width / 4) * 3) { |
| aspect_ratio = 0b01; // 4:3 |
| } else if (height == (width / 5) * 4) { |
| aspect_ratio = 0b10; // 5:4 |
| } else if (height == (width / 16) * 9) { |
| aspect_ratio = 0b11; // 16:9 |
| } else { |
| return false; // Invalid aspect ratio. |
| } |
| x_pixels = static_cast<unsigned char>((width / 8) - 31); |
| vertical_frequency = static_cast<unsigned char>(freq - 60); |
| return true; |
| } |
| |
| int EdidTimingEntry::GetWidth() { |
| return (x_pixels + 31) * 8; |
| } |
| |
| int EdidTimingEntry::GetHeight() { |
| switch (aspect_ratio) { |
| default: |
| case 0b00: |
| return (GetWidth() / 16) * 10; // 16:10 (EDID >= 1.3; 1:1 otherwise). |
| case 0b01: |
| return (GetWidth() / 4) * 3; // 4:3 |
| case 0b10: |
| return (GetWidth() / 5) * 4; // 5:4 |
| case 0b11: |
| return (GetWidth() / 16) * 9; // 16:9 |
| } |
| } |
| |
| int EdidTimingEntry::GetVerticalFrequency() { |
| return vertical_frequency + 60; |
| } |
| |
| EdidTimingEntry* Edid::GetTimingEntry(int entry) { |
| assert(0 <= entry && entry < 8); |
| // Timing entries start at byte 38. |
| return reinterpret_cast<EdidTimingEntry*>(edidBlock.data() + 38 + |
| (entry * sizeof(EdidTimingEntry))); |
| } |
| |
| void Edid::SetProductCode(uint16_t code) { |
| // Manufacturer product code is bytes 10-11. |
| *(reinterpret_cast<uint16_t*>(edidBlock.data() + 10)) = code; |
| } |
| |
| void Edid::SetSerialNumber(uint32_t serial) { |
| // Serial number is bytes 12-15. |
| *(reinterpret_cast<uint32_t*>(edidBlock.data() + 12)) = serial; |
| } |
| |
| void Edid::UpdateChecksum() { |
| assert(edidBlock.size() == kBlockSize); |
| // Sum all bytes except the last. |
| int sum = 0; |
| for (int i = 0; i < edidBlock.size() - 1; i++) { |
| sum += edidBlock.at(i); |
| } |
| // Set the last byte to make the sum of ALL bytes mod 256 equal 0. |
| edidBlock[edidBlock.size() - 1] = |
| (sum % 256) == 0 ? 0 : static_cast<unsigned char>(256 - (sum % 256)); |
| assert((sum + edidBlock[edidBlock.size() - 1]) % 256 == 0); |
| } |
| |
| } // namespace display::test |