C++ lcd屏幕旋转1位位图
我正在我的微控制器(Arduino Mega)上的阵列中存储日立HD44780 LCD控制器的一些自定义字符。字符基本上是一个颜色深度为一位的位图,宽5像素,高8像素 为了尽可能节省宝贵的内存,我决定存储数据。否则,我将浪费每行三位。例如,一个É的存储方式如下:C++ lcd屏幕旋转1位位图,c++,c,arrays,arduino,atmega,C++,C,Arrays,Arduino,Atmega,我正在我的微控制器(Arduino Mega)上的阵列中存储日立HD44780 LCD控制器的一些自定义字符。字符基本上是一个颜色深度为一位的位图,宽5像素,高8像素 为了尽可能节省宝贵的内存,我决定存储数据。否则,我将浪费每行三位。例如,一个É的存储方式如下: ---##### 0x1F -#-#-#-# 0x55 #--#-#-# 0x95 ---#-#-# 0x15 ---#---# 0x11 -----#-- 0x04 ----#--- 0x08 -----
---##### 0x1F
-#-#-#-# 0x55
#--#-#-# 0x95
---#-#-# 0x15
---#---# 0x11
-----#-- 0x04
----#--- 0x08
-------- 0x00
---##### 0x1F
---#---- 0x10
---####- 0x1E
---#---- 0x10
---##### 0x1F
输出应如下所示:
---##### 0x1F
-#-#-#-# 0x55
#--#-#-# 0x95
---#-#-# 0x15
---#---# 0x11
-----#-- 0x04
----#--- 0x08
-------- 0x00
---##### 0x1F
---#---- 0x10
---####- 0x1E
---#---- 0x10
---##### 0x1F
我的问题是,怎样才能最有效地将这一切变回现实。我们这里说的是一个只有8KB内存的16MHz处理器,所以保持它尽可能快和小是关键。编程语言是C++
我个人的想法是创建所需的8字节数组,从左到右扫描行,用一些位掩码设置位。这就是为什么我还镜像了这些字母,这样我就可以轻松地将我的位掩码右移,并将其用于两个数组
基本上扫描第一个输入字节,相应地设置输出数组的第三位,扫描第二行,设置输出数组的第四位,依此类推
但是有没有更好的方法来实现这一点呢?首先,谢谢。这是我几个月来看到的最有趣的问题 因此,空间是制约因素。在我看来,主要的问题是位提取和插入的成本会很快消耗代码内存。一个循环从一个5字节的数组中提取一个位,然后插入到一个8字节的数组中,这可能需要大量的可执行代码来完成 我建议另一种表示数据的方法是支持一种输出字符,这种输出字符可以被认为是一个单位字符串,由0/1的流组成,然后是其他0/1的流,直到64位被填充 实际上,您正在编码状态更改,而不是实际的位模式。 数据将为1位宽,表示0或1,长度为3位宽,表示长度1。。8. 因此
-----#-- 0x04
----#--- 0x08
-------- 0x00
---##### 0x1F
编码将是
- 0101-0位,共6位位置,编码为6-1(-----)
- 1000-1位,总共1位位置,编码为1-1(#)
- 0101-0位,共6位位置,编码为6-1(-----)
- 1000-1位,总共1位位置,编码为1-1(#)
- 0111-0位,共8位位置,编码为8-1(-----)
- 0101-0位,共6位位置,编码为6-1(-----)
- 1100-1位,共5位位置,编码为5-1
该主题的一个变体是不编码每个字节的前导3位。当可执行代码达到这一点时,它会自动将三个0放入其中。这将使上面这个小示例的编码成本降低到大约2.5字节,而代价是一些额外的可执行代码
我认为这样做的好处是,每次从字节的一个半字节中精确地提取位,然后将它们放入单个字节的位中。我想这将是一个最划算的价格。首先,谢谢。这是我几个月来看到的最有趣的问题 因此,空间是制约因素。在我看来,主要的问题是位提取和插入的成本会很快消耗代码内存。一个循环从一个5字节的数组中提取一个位,然后插入到一个8字节的数组中,这可能需要大量的可执行代码来完成 我建议另一种表示数据的方法是支持一种输出字符,这种输出字符可以被认为是一个单位字符串,由0/1的流组成,然后是其他0/1的流,直到64位被填充 实际上,您正在编码状态更改,而不是实际的位模式。 数据将为1位宽,表示0或1,长度为3位宽,表示长度1。。8. 因此
-----#-- 0x04
----#--- 0x08
-------- 0x00
---##### 0x1F
编码将是
- 0101-0位,共6位位置,编码为6-1(-----)
- 1000-1位,总共1位位置,编码为1-1(#)
- 0101-0位,共6位位置,编码为6-1(-----)
- 1000-1位,总共1位位置,编码为1-1(#)
- 0111-0位,共8位位置,编码为8-1(-----)
- 0101-0位,共6位位置,编码为6-1(-----)
- 1100-1位,共5位位置,编码为5-1
该主题的一个变体是不编码每个字节的前导3位。当可执行代码达到这一点时,它会自动将三个0放入其中。这将使上面这个小示例的编码成本降低到大约2.5字节,而代价是一些额外的可执行代码 我认为这样做的好处是,每次从字节的一个半字节中精确地提取位,然后将它们放入单个字节的位中。这将是最大的规模爆炸为美元 有没有更好的方法来实现这一点 与其以旋转的方式保存字符位图,不如将其压缩为5个字节 要在编译时打包,请执行以下操作:
eunm
)
#define PACK8_5(a,b,c,d,e,f,g,h) \
((((((uint64_t)(a) << 5) + (b)) << 5) + (c)) << 5) + (d) ...
#define UNPACK40_5(a) \
((a) >> 32) & 31, ((a) >> 24) & 31, ((a) >> 16) & 31, ((a) >> 8) & 31, (a) & 31
#define CHBM(a,b,c,d,e,f,g,h) (UNPACK40_5(PACK8_5((a),(b),(c),(d),(e),(f),(g),(h))))
void unpack5to8(unsigned char dest[8], const unsigned char src[5]) {
uint64_t pack = src[0];
for (unsigned i=1; i<5; i++) {
pack <<= 8;
pack += src[i];
}
for (unsigned i=8; i>0; ) {
i--;
dest[i] = pack & 31;
pack >>= 5;
}
void unpack5to8(unsigned char dest[8],const unsigned char src[5]){
uint64_t pack=src[0];
对于(无符号i=1;i=5;
}
另一个想法是使用更多的代码,但使用32位变量。这是OP可以分析不同代码的地方
有没有更好的方法来实现这一点
与其以旋转的方式保存字符位图,不如将其压缩为5个字节
要在编译时打包,请执行以下操作:
eunm