わかりました、ユーザーが 100x64 LCD にピクセルを設定できるクラスがあります。
// (U8 = unsigned char)
inline void pixelOn(const U8 X, const U8 Y) {
*(disp + ((Y / LCD_DEPTH) * LCD_WIDTH + X)) |= (1 << (Y % LCD_DEPTH));
}
inline void pixelOff(const U8 X, const U8 Y) {
*(disp + ((Y / LCD_DEPTH) * LCD_WIDTH + X)) &= !(1 << (Y % LCD_DEPTH));
}
これで、液晶に線を引くクラスができました。異なるピクセルの「設定機能」を使用する 3 つの機能があります: show、erease、invert
void NLine::show(bool update) const {
if(lcd == 0) return;
if (!NLcd::pixelInLcd(x, y) && !NLcd::pixelInLcd(endX, endY))
return;
if ((x == endX) || (y == endY)) {
straight(&NLcd::pixelOn);
} else {
bresenham(&NLcd::pixelOn);
}
visible = true;
if (update) {
display_update();
}
}
現時点では、関数ポインターでピクセルを設定するためにプライベート関数が呼び出されます。
void NLine::bresenham(void (NLcd::*fpPixelState)(const U8, const U8)) const {
// predetermine function to avoid ifs during calculation!
// low level pixel functions use U8!
S8 ix = x;
S8 iy = y;
S8 sx = ix < endX ? 1 : -1;
S8 sy = iy < endY ? 1 : -1;
S16 err = width + (-height), e2;
for (;;) {
// how to get the compiler to inline this (template?)!
(lcd->*fpPixelState)(static_cast<U8>(ix), static_cast<U8>(iy));
if (ix == endX && iy == endY)
break;
e2 = 2 * err;
if (e2 > (-height)) {
err += (-height);
ix += sx;
}
if (e2 < width) {
err += width;
iy += sy;
}
}
}
コンパイラが for ループでこの関数をインライン化することを望んでいるのは理解できると思います。テンプレートでこの問題を解決しようとしましたが、コンパイラがインラインを使用しているかどうかわからないという同じ問題があります。完全に異なる設計を使用する必要がありますか、またはこの問題をどのように解決できますか? 次の問題は、インラインが異なるために show erase と invert を呼び出すと、コンパイラが大量のコードを生成することです。別のコード設計を使用する必要があると思いますか?
編集:
まず、デザインの提案については、Dietmar Kühl に感謝します。だからここに結論があります:
これはテストコードです:
NLine line(lcd, 0, 0, 99, 0);
t0 = timer.now();
for(S8 i=0; i<NLcd::LCD_HEIGHT; ++i) {
// x0, y0, xend, yend
line.setPosition(NLine::keep, i, NLine::keep, i);
// call only straight not the bigger bresenham function
line.show();
line.erase();
line.invert();
}
t1 = timer.now();
方法 1: funciton-pointers を使用する (最初の)
メモリ: 26384
RT: 51 ms
方法 2: 関数オブジェクトを使用する (Dietmar
Kühl) メモリ: 26592
RT: 27 ミリ秒
方法 3: switch in for ループを使用して、ピクセル操作関数を決定します
。 メモリ: 26416
RT: 36 ms
方法 2: 最良の RT ですが、特にブレセンハムの場合、描画メソッド周辺の実装が非常に大きくなると、プログラムが非常に大きくなることが判明しました。これは、テンプレートの実装によって 3 つのピクセル関数すべての完全なコードが生成されるために発生します。
方法 3: 最も単純な方法が適切なトレードオフのようです。
さらなる提案を歓迎します。