簡體   English   中英

從8位數據后跟1位奇偶校驗位中剝離C中的奇偶校驗位

[英]Strip parity bits in C from 8 bits of data followed by 1 parity bit

我有一個帶8位數據的位緩沖區,后跟1個奇偶校驗位。 這種模式會重復。 緩沖區當前存儲為八位字節數組。

示例(p是奇偶校驗位):

0001 0001 p000 0100 0p00 0001 00p01 1100 ...

應該成為

0001 0001 0000 1000 0000 0100 0111 00 ...

基本上,我需要剝離第九個位才能獲取數據位。 我該如何實現?

這與有時返回這里的另一個問題有關。

這是在32位計算機上,因此相關問題的解決方案可能不適用。 可能的最大位數為45,即5個數據八位位組

到目前為止,這是我嘗試過的。 我創建了一個“布爾”數組,並根據八位位的位集將這些位添加到該數組中。 然后,我查看數組的第九個索引並通過它。 然后將剩余的數組向下移動一個索引。 然后我只剩下了數據位。 我當時在想可能會有更好的方法。

在偽代碼中(因為您沒有提供嘗試過的證明),為簡單起見,我可能會這樣做:

  • 以位流的形式查看數據(包括奇偶校驗位)
  • 雖然還有一些要讀取的內容:
    • 讀取接下來的8位
    • 寫入輸出
    • 再讀一點,然后丟棄

這使您不必擔心讀取字節,這不再是有用的操作,因為您的字節與要丟棄的位交錯在一起。

您的想法是有一個好的位數組。 只需用32位數字(緩沖區)實現位數組即可。

要從緩沖區中間刪除一點:

void remove_bit(uint32_t* buffer, int* occupancy, int pos)
{
    assert(*occupancy > 0);
    uint32_t high_half = *buffer >> pos >> 1;
    uint32_t low_half = *buffer << (32 - pos) >> (32 - pos);
    *buffer = high_half | low_half;
    --*occupancy;
}

要將字節添加到緩沖區:

void add_byte(uint32_t* buffer, int* occupancy, uint8_t byte)
{
    assert(*occupancy <= 24);
    *buffer = (*buffer << 8) | byte;
    *occupancy += 8;
}

要從緩沖區中刪除一個字節:

uint8_t remove_byte(uint32_t* buffer, int* occupancy)
{
    uint8_t result = *buffer >> (*occupancy - 8);
    assert(*occupancy >= 8);
    *occupancy -= 8;
    return result;
}

您將必須安排調用,以使緩沖區永遠不會溢出。 例如:

buffer = 0;
occupancy = 0;
add_byte(buffer, occupancy, *input++);
add_byte(buffer, occupancy, *input++);
remove_bit(buffer, occupancy, 7);
*output++ = remove_byte(buffer, occupancy);
add_byte(buffer, occupancy, *input++);
remove_bit(buffer, occupancy, 6);
*output++ = remove_byte(buffer, occupancy);
... (there are only 6 input bytes, so this should be easy)

我已經編寫了輔助函數來讀取未對齊的位緩沖區(這是針對AVC流的,請參見此處的原始源代碼)。 代碼本身是GPL,我在這里粘貼了一些有趣的(修改過的)位。

typedef struct bit_buffer_ {
  uint8_t * start;
  size_t size;
  uint8_t * current;
  uint8_t read_bits;
} bit_buffer;

/* reads one bit and returns its value as a 8-bit integer */
uint8_t get_bit(bit_buffer * bb) {
  uint8_t ret;
  ret = (*(bb->current) >> (7 - bb->read_bits)) & 0x1;
  if (bb->read_bits == 7) {
      bb->read_bits = 0;
      bb->current++;
  }
  else {
      bb->read_bits++;
  }
  return ret;
}

/* reads up to 32 bits and returns the value as a 32-bit integer */
uint32_t get_bits(bit_buffer * bb, size_t nbits) {
  uint32_t i, ret;
  ret = 0;
  for (i = 0; i < nbits; i++) {
    ret = (ret << 1) + get_bit(bb);
  }
  return ret;
}

您可以使用如下結構:

uint_8 * buffer;
size_t buffer_size;
/* assumes buffer points to your data */

bit_buffer bb;
bb.start = buffer;
bb.size = buffer_size;
bb.current = buffer;
bb.read_bits = 0;

uint32_t value = get_bits(&bb, 8);
uint8_t parity = get_bit(&bb);

uint32_t value2 = get_bits(&bb, 8);
uint8_t parity2 = get_bit(&bb);

/* etc */

我必須強調,此代碼非常完美,必須實現適當的邊界檢查,但是在我的用例中它可以正常工作。

我將其作為練習來實現,以以此為靈感實現適當的位緩沖區讀取器。

這也有效

void RemoveParity(unsigned char buffer[], int size)
{
    int offset = 0;
    int j = 0;

    for(int i = 1; i + j < size; i++)
    {
        if (offset == 0)
        {
            printf("%u\n", buffer[i + j - 1]);
        }
        else
        {
            unsigned char left = buffer[i + j - 1] << offset;
            unsigned char right = buffer[i + j] >> (8 - offset);
            printf("%u\n", (unsigned char)(left | right));
        }
        offset++;
        if (offset == 8)
        {
            offset = 0;
            j++; // advance buffer (8 parity bit consumed)
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM