从EDID块中提取信息:5位到字母?

时间:2015-09-19 14:28:03

标签: c# encoding bit-manipulation edid

我正在从SetupAPI调用中收集EDID块(作为字节),以获取一些详细的监视器信息。

正如EDID documentation所说,一些字节存储" 5位字母"在他们里面。

为了让您免于头痛,我附上一个方案以便轻松理解:

2 bytes representing 3 letters in their bits

如您所见,我需要从字节中提取5位字母。

我可以设法将字节分成BitArray,但后来我不知道如何将这些位转换成字母。

Wiki也说:

"00001=A”; “00010=B”; ... “11010=Z”.

那么,转换这些位的最快,最无痛的方法是什么?

我想我可以预定义一个Dictionary对象,如:

Dictionary<BitArray, char> letters = new Dictionary<BitArray, char>();
letters.Add(new BitArray(new int[] { 0, 0, 0, 1 }),  Convert.ToChar("A"));
letters.Add(new BitArray(new int[] { 0, 0, 1, 0 }),  Convert.ToChar("B"));

然后搜索它,但首先我不知道如何在“00010 = B”到“11010 = Z”之后关注,第二我确定必须有更合适的方式。

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

要回答这个问题,必须理解C#中的位操作和bit&amp;小端机器中的字节布局。一个字节中的位0是最低有效奇数/偶数位,而不是符号位,如果您想将其视为16位数,则第二个字节是位15(符号)到位8,最不重要的是字节。但更重要的是,手头的问题。

在上面的好照片中,#s位是错误的。即使从规范我们可以看到这一点。 EX:“第二个字符(字母)位于位1和0(地址08h)和位7→5(地址09h)”。修正后的图表是: enter image description here

工作代码是(是的,我在我的s / w中使用了这个):

// in 2 bytes, [8,9], ignore top bit then three 5 bit characters
char[] convert = " ABCDEFGHIJKLMNOPQRSTUVWXYZ01234".ToCharArray();
result.AppendFormat("-8: Vendor ID#: {0}{1}{2}\n",
convert[(edid[8] >> 2) & 0x1F],
convert[((edid[8] << 3) & 0x18) | ((edid[9] >> 5) & 0x07)],
convert[edid[9] & 0x1F]);

我剩下的一个问题是,上面字符串中的“01234”应该是什么? 我只使用“01234”作为占位符。它们是未定义的特殊字符($ _- @#),是什么?

答案 1 :(得分:0)

要提取5位的组,可以使用标准的“从比特流中提取东西”技术(它更通用,但没关系),其中一个版本是这样的:(未经过测试,并不是真正意味着代码无论如何,更像是一个低级伪代码)

uint buffer = 0;
int emptybits = 32;
while (want_more_symbols) {
    while (emptybits >= 8 && can_read_more) {
        emptybits -= 8;
        buffer = buffer | ((uint)readByte() << emptybits)
    }
    int symbol = (int)(buffer >> (32 - 5));
    buffer <<= 5;
    emptybits += 5;
    use(symbol);
}

一般情况下,你可以放置任何东西,包括25,而不是5,它可以是变量。

或者更具体地说,对于这种情况,您可以计算您在数组中查看的位置并直接提取它:(未经测试)

// extract symbol n
int bitindex = n * 5;
int arrayindex = bitindex / 8;
int leftover = bitindex & 7;
if (leftover <= 3)
    // it's in one byte
    return (array[arrayindex] >> (3 - leftover)) & 32;
else
    // crosses byte boundary
    return ((array[arrayindex] << (leftover - 3)) | 
            (array[arrayindex + 1] >> (11 - leftover))) & 32;

要将5位值转换为字母,请将其添加到“A”中。但他们从A = 1开始,所以减去1:

char letter = (char)('A' + x - 1);

答案 2 :(得分:0)

BTW,对于任何感兴趣的人,我只是编写了一个C#EDIDParser,它可以很好地为您提供EDID二进制文件中提供的所有信息。

项目:https://github.com/falahati/EDIDParser

NuGet:https://www.nuget.org/packages/EDIDParser

您需要做的就是创建一个提供二进制数据的django-jsonfield类型的实例,然后使用该类的属性来获取信息,包括供应商的3个字母代码。

EDID

但是,如果您只对从供应商标识号中提取代码的部分感兴趣,可以从此处查看源代码: https://github.com/falahati/EDIDParser/blob/master/EDIDParser/EDID.cs

var edid = new EDID(bytes);
var vendorCode = edid.ManufacturerCode;