将C中的奇偶校验位从8位数据与1位奇偶校验位接在一起。

时间:2022-06-14 03:11:18

I have a buffer of bits with 8 bits of data followed by 1 parity bit. This pattern repeats itself. The buffer is currently stored as an array of octets.

我有一个比特的缓冲区,有8位数据,然后是一个奇偶校验位。这种模式重演。缓冲区当前存储为octets数组。

Example (p are parity bits):

示例(p为奇偶校验位):

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

0001 0001 0001 0001 0001

should become

应该成为

0001 0001 0000 1000 0000 0100 0111 00 ...

0001 0001 0000 0000 0100 0111 00…

Basically, I need to strip of every ninth bit to just obtain the data bits. How can I achieve this?

基本上,我需要把每9位的数据带出来才能得到数据位。我怎样才能做到这一点呢?

This is related to another question asked here sometime back.

这与后面的另一个问题有关。

This is on a 32 bit machine so the solution to the related question may not be applicable. The maximum possible number of bits is 45 i.e. 5 data octets

这是在一个32位机器上,所以解决相关问题的方法可能不适用。比特的最大可能数为45,即5个数据八进制。

This is what I have tried so far. I have created a "boolean" array and added the bits into the array based on the the bitset of the octet. I then look at every ninth index of the array and through it away. Then move the remaining array down one index. Then I've got only the data bits left. I was thinking there may be better ways of doing this.

这是我迄今为止尝试过的。我已经创建了一个“布尔”数组,并根据octet的位集将比特添加到数组中。然后,我查看数组的每一个9个索引,然后通过它。然后将剩下的数组向下移动一个索引。然后我只剩下数据位了。我想也许有更好的方法来做这件事。

4 个解决方案

#1


2  

Your idea of having an array of bits is good. Just implement the array of bits by a 32-bit number (buffer).

你有一个比特数组的想法很好。只需通过一个32位的数字(缓冲区)实现位元数组。

To remove a bit from the middle of the buffer:

从缓冲区中间移出一点:

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;
}

To add a byte to the buffer:

要向缓冲区添加一个字节:

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

To remove a byte from the buffer:

从缓冲区中删除一个字节:

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

You will have to arrange the calls so that the buffer never overflows. For example:

您将不得不安排调用,以便缓冲区不会溢出。例如:

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)

#2


2  

In pseudo-code (since you're not providing any proof you've tried something), I would probably do it like this, for simplicity:

在伪代码中(因为你没有提供任何你尝试过的证据),为了简单起见,我可能会这样做:

  • View the data (with parity bits included) as a stream of bits
  • 将数据(包含奇偶校验位)视为比特流。
  • While there are bits left to read:
    • Read the next 8 bits
    • 阅读下面的8位。
    • Write to the output
    • 写入输出
    • Read one more bit, and discard it
    • 再读一遍,把它丢掉。
  • 当剩下来读的时候:读下面的8位写到输出再读一点,然后丢弃它。

This "lifts you up" from worrying about reading bytes, which no longer is a useful operation since your bytes are interleaved with bits you want to discard.

这将使您不再担心读取字节,因为您的字节与您想要丢弃的字节交错在一起,因此不再是一个有用的操作。

#3


1  

I have written helper functions to read unaligned bit buffers (this was for AVC streams, see original source here). The code itself is GPL, I'm pasting interesting (modified) bits here.

我编写了helper函数来读取未对齐的位缓冲区(这是用于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;
}

You can use the structure like this:

你可以使用这样的结构:

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 */

I must stress that this code is quite perfectible, proper bound checking must be implemented, but it works fine in my use-case.

我必须强调,这段代码是非常完美的,必须进行适当的绑定检查,但是在我的用例中它运行良好。

I leave it as an exercise to you to implement a proper bit buffer reader using this for inspiration.

我把它作为一个练习留给您来实现一个适当的位缓冲读取器使用它来获得灵感。

#4


1  

This also works

这同样适用

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)
        }
    }
}

#1


2  

Your idea of having an array of bits is good. Just implement the array of bits by a 32-bit number (buffer).

你有一个比特数组的想法很好。只需通过一个32位的数字(缓冲区)实现位元数组。

To remove a bit from the middle of the buffer:

从缓冲区中间移出一点:

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;
}

To add a byte to the buffer:

要向缓冲区添加一个字节:

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

To remove a byte from the buffer:

从缓冲区中删除一个字节:

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

You will have to arrange the calls so that the buffer never overflows. For example:

您将不得不安排调用,以便缓冲区不会溢出。例如:

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)

#2


2  

In pseudo-code (since you're not providing any proof you've tried something), I would probably do it like this, for simplicity:

在伪代码中(因为你没有提供任何你尝试过的证据),为了简单起见,我可能会这样做:

  • View the data (with parity bits included) as a stream of bits
  • 将数据(包含奇偶校验位)视为比特流。
  • While there are bits left to read:
    • Read the next 8 bits
    • 阅读下面的8位。
    • Write to the output
    • 写入输出
    • Read one more bit, and discard it
    • 再读一遍,把它丢掉。
  • 当剩下来读的时候:读下面的8位写到输出再读一点,然后丢弃它。

This "lifts you up" from worrying about reading bytes, which no longer is a useful operation since your bytes are interleaved with bits you want to discard.

这将使您不再担心读取字节,因为您的字节与您想要丢弃的字节交错在一起,因此不再是一个有用的操作。

#3


1  

I have written helper functions to read unaligned bit buffers (this was for AVC streams, see original source here). The code itself is GPL, I'm pasting interesting (modified) bits here.

我编写了helper函数来读取未对齐的位缓冲区(这是用于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;
}

You can use the structure like this:

你可以使用这样的结构:

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 */

I must stress that this code is quite perfectible, proper bound checking must be implemented, but it works fine in my use-case.

我必须强调,这段代码是非常完美的,必须进行适当的绑定检查,但是在我的用例中它运行良好。

I leave it as an exercise to you to implement a proper bit buffer reader using this for inspiration.

我把它作为一个练习留给您来实现一个适当的位缓冲读取器使用它来获得灵感。

#4


1  

This also works

这同样适用

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)
        }
    }
}