我需要优化此功能:优化for循环的任何奇怪方法? (我认为早期休息是不可能的)
void SeeedGrayOLED::putChar(unsigned char C)
{
if(C < 32 || C > 127) //Ignore non-printable ASCII characters. This can be modified for multilingual font.
{
C=' '; //Space
}
uint8_t k,offset = 0;
char bit1,bit2,c = 0;
for(char i=0;i<16;i++)
{
for(char j=0;j<32;j+=2)
{
if(i>8){
k=i-8;
offset = 1;
}else{
k=i;
}
// Character is constructed two pixel at a time using vertical mode from the default 8x8 font
c=0x00;
bit1=(pgm_read_byte(&hallfetica_normal[C-32][j+offset]) >> (8-k)) & 0x01;
bit2=(pgm_read_byte(&hallfetica_normal[C-32][j+offset]) >> ((8-k)-1)) & 0x01;
// Each bit is changed to a nibble
c|=(bit1)?grayH:0x00;
c|=(bit2)?grayL:0x00;
sendData(c);
}
}
}
我在数组hallfetica_normal中有一个字体,是一个uint8_t数组的数组,可能是压缩的还是类似的?
此代码在arduino上运行,ad我可以从500到0进行倒计时,每10 / 20ms一个单位减少。
修改
这是你的指示之后的新代码,谢谢大家: 我希望以不同的方式组织字体,以减少对pgm_read_byte的调用..(比如改变方向......我不知道)
void SeeedGrayOLED::putChar(unsigned char C)
{
if(C < 32 || C > 127) //Ignore non-printable ASCII characters. This can be modified for multilingual font.
{
C=' '; //Space
}
char c,byte = 0x00;
unsigned char nibble_lookup[] = { 0, grayL, grayH, grayH | grayL };
for(int ii=0;ii<2;ii++){
for(int i=0;i<8;i++)
{
for(int j=0;j<32;j+=2)
{
byte = pgm_read_byte(&hallfetica_normal[C-32][j+ii]);
c = nibble_lookup[(byte >> (8-i)) & 3];
sendData(c);
}
}
}
}
答案 0 :(得分:4)
好吧,你好像是通过pgm_read_byte(&hallfetica_normal[C-32][j+offset])
不必要地连续两次读取相同的字节。您可以将一次加载到局部变量中。
此外,您可以通过将代码分解为两个循环来避免每次迭代if(i>8){
检查;一个i
从0变为8,另一个从9变为15.(虽然我怀疑你真的打算>=
在这里,使循环边界0-7然后8-15。)也意味着像offset
这样的东西会变成常数值,这会有所帮助。
答案 1 :(得分:2)
为了尽可能快地使内循环,我试图用查找表去除所有分支,看看是否有帮助。
首先,我在循环外定义查找表:
/* 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);
由于您正在屏蔽和测试2个相邻位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);
另一个答案已经解决了如何处理内循环顶部的分支。