问题描述
如何从22个字节中解码16个11位数字?
这是数据表中的描述。
有效载荷:
- 11位通道1
- 11位通道2
- ...
- 11位16频道
16个频道打包为22个字节
我的C代码
#include <stdio.h>
int main(void)
{
// There are 16 11-bit channels encoded in these 22 numbers.
// Example data
/* NEW INFORMATION
This data arrived from a serial connection
420,000 baud
non-inverted
8 bit
1 stop
Big Endian*/
int data[22] = {224,11,223,47,194,199,10,86,176,130,21,192,6,48,128,1,62,240,129,15,124};
int channels[16] = 0;
// decode and set each channel
return 0;
}
解决方法
假设您每次像这样从左到右工作一个字节:
| 0 | 1 | 2 |
-------------------------------------------------------------------------------------------------
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ...
-------------------------------------------------------------------------------------------------
| 0 | 1 | ...
您需要执行以下转换:
int i,j;
for (i=0,j=0; i<16; i+=8,j+=11) {
channels[i+0] = ((data[j+0] & 0xFF) << 3) | ((data[j+1] & 0xE0) >> 5);
channels[i+1] = ((data[j+1] & 0x1F) << 6) | ((data[j+2] & 0xFA) >> 2);
channels[i+2] = ((data[j+2] & 0x03) << 9) | ((data[j+3] & 0xFF) << 1) | ((data[j+4] & 0x80) >> 7);
channels[i+3] = ((data[j+4] & 0x7F) << 4) | ((data[j+5] & 0xF0) >> 4);
channels[i+4] = ((data[j+5] & 0x0F) << 7) | ((data[j+6] & 0xFE) >> 1);
channels[i+5] = ((data[j+6] & 0x01) << 10) | ((data[j+7] & 0xFF) << 1) | ((data[j+8] & 0xA0) >> 6);
channels[i+6] = ((data[j+8] & 0x3F) << 5) | ((data[j+9] & 0xF8) >> 3);
channels[i+7] = ((data[j+9] & 0x07) << 8) | ((data[j+10] & 0xFF) >> 0);
}
对于11位的组,您需要经过8组的11位才能在循环重复之前在整个字节上结束,因此在此我们对16组进行两次
,首先,具有要解码数据的数组必须unsigned char
而不是int
这是一个提取特定值的函数(由于测试为时已晚,因此未进行测试)
#define mask ((1 << 12) - 1)
unsigned getval(unsigned char *array,int pos)
{
int bitpos = pos * 11;
int byte = pos / 8;
int startbyte;
int startbit = 0;
uint32_t buff;
if(byte + 4 > 21)
{
startbyte = 21 - 4;
startbit = (byte - startbyte) * 8;
}
else
{
startbyte = byte;
}
startbit += bitpos & 7;
memcpy(&buff,array + startbyte,sizeof(buff));
buff &= mask << startbit;
buff >>= startbit;
return buff;
}
假设:小尾数法