最近在做红外遥控器的学习功能, 需要记录红外的高/低电平持续时间, 我把它叫做时序(timing?)。
记录的时间单位为μs, 1μs=10^-6s。
由于遥控器发射的光持续时间不会超过65535μs, 于是选择8位单片机上的16位的unsigned int来存储每个高/低电平的持续时间。
经过计算, 遥控器发射的每一位, 一般改变高/低电平一次, 也就是说需要记录高/低电平各1个。
另外, 我有的空调遥控器最多不会超过112位, 也就是224个高/低电平, 加上同步码的2个高/低电平, 一共是226个高/低电平。因此, 我使用固定长度为256的unsigned int数组来存放时间信息。
这样一个记录就占掉了256*2=512bytes的存储器空间, 而在单片机上, 资源是十分紧张的, EEPROM只有1KB(flash有32KB但是不方便使用)。
于是EEPROM只能存储2个。
所以, 我需要一种压缩算法。
我的想法是:
时序中高/低电平持续时间的长度只有很少几种, 比如某编码的引导码有2种, 数据码有3种, 一共是5种。同时, 接收器接收的时候允许有一定的误差(具体数值未知)。
可以通过某种转换关系, 把相差不大的几个持续时间算为一种, 存放在一个数组中, 数组的下标就是该持续时间的id号码。由于时序中高/低电平持续时间的长度只有很少几种, id号码最大值也不会很大。
我假定id号码最大为15。于是这个数组大小就为(15-0+1)*2bytes=32bytes
这样就可以把长16bit的unsigned int转化为4bit的id号。256个数据就从512bytes变为了128bytes。
加上存放持续时间和id的数组32bytes, 一共需要160bytes, 压缩率为160/512=31.25%。
如果有持续时间很长的部分, 用unsigned long来存储, 那么原本需要1024bytes的数据只需要4*16+128=192bytes, 压缩率为192/1024=18.75%。
如果使用N字节的某数据类型来存储, 那么原本需要256N的数据, 现在只需要16N+128, 压缩率为(16N+128)/256N。
WDTCA=Wandai’s Timing Compression Algorithm
代码后附。
另外, 如果知道了红外的编码方式, 就可以解码之后再存储, 发射的时候重新编码, 这样比任何压缩算法都要好。可惜红外遥控器没有一个编码标准:(
发表评论