Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何优化oled显示器字体渲染的C for循环_C_Optimization - Fatal编程技术网

如何优化oled显示器字体渲染的C for循环

如何优化oled显示器字体渲染的C for循环,c,optimization,C,Optimization,我需要优化这个函数:有没有奇怪的方法来优化for循环?(我想提前休息是不可能的) void SeeedGrayOLED::putChar(无符号字符C) { if(C127)//忽略不可打印的ASCII字符。这可以针对多语言字体进行修改。 { C='';//空格 } uint8_t k,偏移量=0; 字符位1,位2,c=0; 对于(字符i=0;i>(8-k))&0x01; 比特2=(pgm_读取字节(&hallfetica_normal[C-32][j+offset])>>((8-k)-1

我需要优化这个函数:有没有奇怪的方法来优化for循环?(我想提前休息是不可能的)

void SeeedGrayOLED::putChar(无符号字符C)
{
if(C<32 | | C>127)//忽略不可打印的ASCII字符。这可以针对多语言字体进行修改。
{
C='';//空格
}   
uint8_t k,偏移量=0;
字符位1,位2,c=0;
对于(字符i=0;i>(8-k))&0x01;
比特2=(pgm_读取字节(&hallfetica_normal[C-32][j+offset])>>((8-k)-1))&0x01;
//每一位都变为一个半字节
c |=(位1)?灰色:0x00;
c |=(位2)?灰色:0x00;
sendData(c);
}
}
}
我在数组中有一个字体hallfetica\u normal,是一个uint8\u t数组,可能是压缩的还是类似的

这段代码在arduino上运行,我必须从500倒计时到0,每10/20毫秒倒一个单位

编辑

这是您指示后的新代码,谢谢大家: 我希望以不同的方式组织字体,以减少对pgm_read_byte的调用。。(比如改变方向……我想知道)

void SeeedGrayOLED::putChar(无符号字符C)
{
if(C<32 | | C>127)//忽略不可打印的ASCII字符。这可以针对多语言字体进行修改。
{
C='';//空格
}   
字符c,字节=0x00;
无符号字符半字节查找[]={0,grayL,grayH,grayH | grayL};

对于(int ii=0;ii嗯,您似乎通过
pgm_read_byte(&hallfetica_normal[C-32][j+offset])在一行中不必要地读取同一字节两次。
。您可以将其加载到局部变量中一次


此外,您可以通过将代码分成两个循环来避免每次迭代的
if(i>8){
检查;一个循环是
i
从0到8,另一个循环是从9到15。(尽管我怀疑您在这里真的打算
=
,将循环边界设为0-7,然后是8-15。)这也意味着像偏移量这样的东西变成常量,这会有所帮助。

好吧,你似乎通过pgm_read_byte(&hallfetica_normal[C-32][j+offset])不必要地连续读取同一字节两次。
。你可以将其加载到局部变量中一次


此外,您可以通过将代码分成两个循环来避免每次迭代的
if(i>8){
检查;一个循环是
i
从0到8,另一个循环是从9到15。(尽管我怀疑您在这里真的打算
=
,将循环边界设为0-7,然后是8-15。)这也意味着像偏移量之类的东西变成常量,这会有所帮助。

为了尽可能快地实现内部循环,我会尝试使用查找表消除所有分支,看看这是否有帮助

首先,我要在循环外部定义查找表:

/* outside the loop */
unsigned char h_lookup[] = { 0, grayH };
unsigned char l_lookup[] = { 0, grayL };
然后在循环内部,因为您正在测试最低有效位,所以可以将其用作查找表的索引。如果清除,则查找索引将为0。如果设置了,则查找索引将为1:

/* inside the loop */
byte = pgm_read_byte(&hallfetica_normal[C-32][j+offset]);
c = h_lookup[((byte >> (8-k)) & 0x01)] |
    l_lookup[((byte >> (8-k-1)) & 0x01)]
sendData(c);
由于您正在屏蔽和测试两个相邻位,
8-k
8-k-1
,因此可以在一个查找表中列出所有4种可能性:

/* Outside loop */
unsigned char nibble_lookup[] = { 0, grayL, grayH, grayH | grayL };
然后查找就大大简化了

/* loop */
byte = pgm_read_byte(&hallfetica_normal[C-32][j+offset]);
c = nibble_lookup[(byte >> (8-k)) & 3];
sendData(c);

另一个答案解决了如何处理内部循环顶部的分支。

为了尽可能快地完成内部循环,我会尝试使用查找表消除所有分支,看看这是否有帮助

首先,我要在循环外部定义查找表:

/* outside the loop */
unsigned char h_lookup[] = { 0, grayH };
unsigned char l_lookup[] = { 0, grayL };
然后在循环内部,因为您正在测试最低有效位,所以可以将其用作查找表的索引。如果清除,则查找索引将为0。如果设置了,则查找索引将为1:

/* inside the loop */
byte = pgm_read_byte(&hallfetica_normal[C-32][j+offset]);
c = h_lookup[((byte >> (8-k)) & 0x01)] |
    l_lookup[((byte >> (8-k-1)) & 0x01)]
sendData(c);
由于您正在屏蔽和测试两个相邻位,
8-k
8-k-1
,因此可以在一个查找表中列出所有4种可能性:

/* Outside loop */
unsigned char nibble_lookup[] = { 0, grayL, grayH, grayH | grayL };
然后查找就大大简化了

/* loop */
byte = pgm_read_byte(&hallfetica_normal[C-32][j+offset]);
c = nibble_lookup[(byte >> (8-k)) & 3];
sendData(c);

另一个答案解决了如何处理内部循环顶部的分支。

FYI,这类问题最适合。无需将
c
设置为零;用第一个或第二个变量初始化它。此外,无需将
0
1
移动到
c
中。您可以使用
&(1 sendData中有什么?是否可以一次发送数据块而不是一个字节?仅供参考,这类问题最适合于。无需将
c
设置为零;用第一个或第二个变量初始化它。此外,无需将
0
1
移动到
c
中。您可以使用
&(1 sendData中有什么?是否可以一次以块而不是一个字节的形式发送数据?我更改了删除pgm_read_byte的2 2调用,并将其替换为1,删除了对适合位的临时变量的赋值。然后,我添加了一个从0到2的for循环,其中包含其他两个循环。现在,它的速度并不比以前快首先,我将尝试indiv显示的解决方案,然后尝试优化字体数组。谢谢,我将很快升级。您也应该发布新代码,以帮助我们了解它是否如预期的那样。我已更改删除pgm_read_byte的2-2调用,并已替换为1,删除了对适合位的临时变量的赋值。然后我已经添加了一个从0到2的for循环,其中包含其他两个循环。现在它的速度并不比以前快,我将尝试indiv显示的解决方案,然后尝试优化字体数组。谢谢,我将很快升级。您也应该发布新代码,以帮助我们查看它是否符合预期。