【发布时间】:2021-10-30 18:27:26
【问题描述】:
我正在实现 EEG(时序采集设备)的串行驱动程序。该设备以 12 位 x 26 个总通道对数据进行编码,采样率为 200Hz
串行数据流由信令字节 0xA0 后跟 45 个字节组成,这些字节承载 26 个通道的数据,每个通道用 12 位编码。
但这里有一个问题,这 12 位在 45 字节块中的位置并不固定。第一个字节仅使用 4 LSB,而其余 44 7 LSB。
为了使这一点更具说明性,我将尝试在下面以图形方式表示它。假设我们已经启动了放大器,它总是给我们所有通道的 4095(用 12 位表示的最大 int 值)(所以我们的数据都是“1”),那么我们有这样的东西:
a0 0f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f a0 下一个样本...
这必须映射到值为 4095 的 int(1,...,26)。
所以,我编写了一个 python 代码,首先找到块的开头,然后将所有内容保存在一个 int/long 中,然后我删除了固定位置的位,附加 8 个最高有效位 0 以形成 16 位表示并将字节数组转换为整数列表。
效果很好,但问题在于速度。似乎代码需要花费大量时间来处理单个样本,并且必须在一秒钟内执行 200 次。让我们包括一些真正的串行读取方法的其他延迟,所有 200 个样本的一切都必须保持在 1 秒以下
#Python code
def readByte():
#mockup
return 0xA0
def read45bytes():
return int(0x0f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f)
def remove_bit(num, i):
mask = num >> (i + 1)
mask = mask << i
right = ((1 << i) - 1) & num
return mask | right
def insert_mult_bits(num, bits, len, i):
mask = num >> i
mask = (mask << len) | bits
mask = mask << i
right = ((1 << i) - 1) & num
return right | mask
def main():
while(readByte()!=0xA0):
print("Searching for the beginning of the packet of 45 bytes...")
print("Beginning of the packet of 45 bytes found")
#read whole sample
sample=read45bytes()
#remove unused bits
corr=0;
for i in range(7, sample.bit_length(), 8):
sample=remove_bit(sample,i-corr);
corr=corr+1;
#add HSB to make 2byte representation
corr=0;
for i in range(12,sample.bit_length(),12):
sample=insert_mult_bits(sample,0,4,i+corr)
corr=corr+4;
#convert to bytes 26channels x 2 bytes, bigendian
bt=sample.to_bytes(26*2,'big');
#assign the result to int list
idx=0;
out=[];
for i in range(0,26*2-1,2):
out.append(int(int((bt[i]<<8 | bt[i+1]))))
idx=idx+1;
#print first sample of the channel 1
print(out.pop(0))
【问题讨论】:
-
我很好奇,为什么这 12 位的间隔如此不规则? 3 个字节 = 24 位,应该与 2 个通道完美对齐。跳过的 0 是否可能是您应该检查的某种错误检测?
-
我不确定,我想是带宽限制。我还认为“0”是某种纠错,但后来我意识到这是一个设计限制,因为标记字节使用 MSB 来标记序列的开始。此外,串行主要是逐字节读取,也许他们认为一旦收到一个字节就很容易丢弃第一个字节?!很遗憾,我无法更改设备的通信协议。
-
您是否尝试过profile您的代码?如果不是,请这样做,因为这会让您找到最耗时的部分(所谓的瓶颈),您应该集中精力。
标签: python bit-manipulation deserialization bitwise-operators data-stream