Объединение 17-битных данных в байтовый массив - PullRequest
3 голосов
/ 20 мая 2011

У меня возникла небольшая проблема с попыткой переместить группы 17-битных данных в байтовый массив.Я не хочу проходить пошаговые инструкции, но не могу понять логический цикл.
Мне это нужно, потому что мне нужно вычислить контрольную сумму, сложив всезначения байтов после объединения их вот так.
Итак, вот с чем я борюсь.

У меня есть 16 байтовых массивов.Первые 3 байта массива содержат 17 бит, которые мне нужны.(8 битов от [0], 8 битов от [1] и MSB от [2].)

Мне нужно переместить эти 16 17-битных значений в один отдельный байтовый массив.

Первый из них прост:

int index = 0;
myArray[index++] = driverData[driver][0];            //First byte
myArray[index++] = driverData[driver][1];            //Second byte
myArray[index] = (driverData[driver][2] & 0x80) << 7;  //First bit of the third byte.

Отсюда, хотя и становится все труднее пытаться перемещать их любым циклом.

driver++;<br>
//Take the 7 MSBs from the data array.
myArray[index++] |= (byte)(driverData[driver][0] & 0x7e >> 1);
//This leaves a single bit left over on driverData[driver][0].
myArray[index] = (byte)(driverData[driver][1] & 0x1 << 7);

Я думаю, вы понимаете картину.Я делаю все это неправильно?Кто-нибудь может указать мне правильное направление?

Ответы [ 3 ]

2 голосов
/ 20 мая 2011

ОК, похоже, это работает.Мне, наверное, нужно больше тестировать, но это, кажется, дает мне результат, которого я ожидаю до сих пор.Я уверен, что мог бы сделать это как-нибудь лучше.

// ... //
void foo()
{
    //Lets start by getting all the 17bit values from each driver for the board.
    int bitIndex = 7;
    int byteIndex = 0;
    int stopIndex = chipIndex + GetChipCount();
    //Now we start the shiftyness.
    for (int driver = chipIndex; driver < stopIndex; driver++) {
        int userBits =
            (driverData[driver][0] & 0xff) << 9 | (driverData[driver][1]
                               & 0xff)
            << 1 | (driverData[driver][2] & 0x80) >> 7;
        AddBitsToArray(userBits, ref bitIndex, ref byteIndex);

    }
}

/// <summary>
/// Takes the 17 bits, and adds them to the byte array.
/// </summary>
private void AddBitsToArray(int userBits, ref int bitIndex, ref int byteIndex)
{
    int bitCount = 17;
    while (bitCount > 0) {
        //First 8 bytes.
        checksumBytes[byteIndex] |=
            (byte) (((userBits & bitValue(bitCount - 1)) >>
                 (bitCount - 1)) << bitIndex);
        //Move up the bit index to be written to.
        bitIndex--;
        //Decrement the number of bits left to shift.
        bitCount--;
        //If we have gone past the 8th bit, reset the bitIndex and increment the byteIndex.
        if (bitIndex >= 0)
            continue;
        bitIndex = 7;
        byteIndex++;
    }
}

/// <summary>
/// Returns the value of a single bit at the given index.
/// </summary>
private int bitValue(int bitIndex)
{
    return (int)(Math.Pow(2, bitIndex));
}
2 голосов
/ 20 мая 2011

Звучит так, будто у вас достаточно большой цикл простых чисел, чтобы сделать кодирование отдельных случаев плохой идеей. Это классическая проблема упаковки. Вам нужен цикл, который проходит через пункт назначения, и некоторый внутренний код, который получает больше битов для упаковки. Ваш упаковочный код должен знать, сколько битов доступно ему с последней итерации, сколько ему нужно, и должен иметь возможность увеличивать указатель источника, если его недостаточно.

1 голос
/ 20 мая 2011

Вот что я придумал.Первая часть метода просто устанавливает некоторые ложные входные данные, поэтому удалите их и добавьте аргументы по мере необходимости.Массив OutputData неоправданно велик, но я не тратил время на вычисление его фактической длины.

Я использовал 170 в качестве входного значения, которое равно 10101010 и было полезно при проверке.

private void BitShift17()
{
    const int NumChunks = 16;
    byte[] DriverData = new byte[]
        {
            170,
            170,
            170
        };
    byte[][] InputData = new byte[NumChunks][];
    for (int n = 0; n < NumChunks; n++)
        InputData[n] = DriverData;

    byte[] OutputData = new byte[NumChunks * 3]; // Unnecessarily large

    int OutputIndex = 0;
    int BitPosition = 0;
    for (int Driver = 0; Driver < InputData.Length; Driver++)
    {
        for (int InputIndex = 0; InputIndex < 3; InputIndex++)
        {
            byte InputByte = InputIndex == 2 ? (byte)(InputData[Driver][InputIndex] & 128) : InputData[Driver][InputIndex];
            if (BitPosition == 0)
            {
                OutputData[OutputIndex] = InputByte;
                if (InputIndex == 2)
                    BitPosition++;
                else
                    OutputIndex++;
            }
            else
            {
                if (InputIndex == 2)
                {
                    OutputData[OutputIndex] |= (byte)(InputByte >> BitPosition);
                    BitPosition++;
                }
                else
                {
                    OutputData[OutputIndex] |= (byte)(InputByte >> BitPosition);
                    OutputIndex++;
                    OutputData[OutputIndex] = (byte)(InputByte << 8 - BitPosition);
                }
            }
        }
        if (BitPosition > 7) BitPosition = 0;
    }
}
...