Sun Jan 11, 2015 6:48 pm
for(byte x = 0; x < LCDWIDTH; x++){
for(byte y = 0; y < LCDHEIGHT; y++){
gb.display.drawPixel(x,y);
}
}
void Display::drawFastVLine(int8_t x, int8_t y, int8_t h) {
// stupidest/slowest version :
//drawLine(x, y, x, y + h - 1);
//new version :
for(int8_t i=0; i<h; i++){
drawPixel(x,y+i);
}
}
Sun Jan 11, 2015 9:23 pm
for (int y=y1; y<y2; y++, dst+=84, src+=w)
for (int x=x1; x<x2; x++)
dst[x] |= src[x];
for (int y=0; y<h; y++, dst+=84, src+=w)
for (int x=0; x<w; x++)
dst[x] |= (src[x] << shift1) | (src[x+w] >> shift2);
int scale1 = 1 << (shift1 + 8);
int scale2 = 1 << (8 - shift2);
for (int y=0; y<h; y++, dst+=84, src+=w)
for (int x=0; x<w; x++)
dst[x] |= (src[x] * scale1 | src[x+w] * scale2) >> 8;
Sun Jan 11, 2015 9:52 pm
Mon Jan 12, 2015 12:34 am
#include <SPI.h>
#include <Gamebuino.h>
Gamebuino gb;
const byte sprite[] PROGMEM = {
16, 16, 0x1f,0xf8,0x1f,0xf8,0x1f,0xfc,0x1f,0xff,0x1f,0xff,0xf,0xff,0xf,0xff,0x7,0xff,0x87,0xff,0x3,0xff,0x1,0xff,0x0,0x7f,0x2,0x1f,0x0,0x0,0x0,0x0,0x40,0x0,};
void setup(){
gb.begin();
}
void loop(){
long start, finish;
int drawTime;
if(gb.update()){
const int count = 100;
start = millis();
for (int i=0; i<count; i++)
gb.display.drawBitmap(1, 31, sprite);
finish = millis();
drawTime = 1000L*(finish-start)/count;
gb.display.print(F("drawBitmap: "));
gb.display.print(drawTime);
gb.display.println(F("ns"));
start = millis();
for (int i=0; i<count; i++)
drawBitmapUnrolled(17, 31, sprite);
finish = millis();
drawTime = 1000L*(finish-start)/count;
gb.display.print(F("unrolled: "));
gb.display.print(drawTime);
gb.display.println(F("ns"));
}
}
inline void drawPixelFast(int8_t x, int8_t y) {
gb.display.getBuffer()[x + (y / 8) * LCDWIDTH_NOROT] |= _BV(y % 8);
}
void drawBitmapUnrolled(int8_t x, int8_t y, const uint8_t *bitmap) {
int8_t w = pgm_read_byte(bitmap);
int8_t h = pgm_read_byte(bitmap + 1);
bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
int8_t i, j, byteWidth = (w + 7) / 8;
uint8_t * line = gb.display.getBuffer() + x;
const uint8_t * bitmap_line = bitmap;
Display display = gb.display;
for (j = 0; j < h; j++, bitmap_line+=byteWidth) {
int dsty = y + j;
int ofs = (dsty / 8) * LCDWIDTH_NOROT;
int dstx = x;
const uint8_t * bitmap_src = bitmap_line;
uint8_t * ptr = line + ofs;
uint8_t mask = _BV(dsty % 8);
int i = w;
while (i >= 8)
{
unsigned pixels = pgm_read_byte(bitmap_src++);
if (pixels & 0x80)
ptr[0] |= mask;
if (pixels & 0x40)
ptr[1] |= mask;
if (pixels & 0x20)
ptr[2] |= mask;
if (pixels & 0x10)
ptr[3] |= mask;
if (pixels & 0x08)
ptr[4] |= mask;
if (pixels & 0x04)
ptr[5] |= mask;
if (pixels & 0x02)
ptr[6] |= mask;
if (pixels & 0x01)
ptr[7] |= mask;
ptr += 8;
i -= 8;
dstx += 8;
}
if (i)
{
unsigned pixels = pgm_read_byte(bitmap_src);
while (i--)
{
if (pixels & 0x80)
gb.display.drawPixel(dstx, dsty);
pixels <<= 1;
dst++;
}
}
}
}
Mon Jan 12, 2015 3:03 pm
int scale1 = 1 << (shift1 + 8);
int scale2 = 1 << (8 - shift2);
for (int y=0; y<h; y++, dst+=84, src+=w)
for (int x=0; x<w; x++)
dst[x] |= (src[x] * scale1 | src[x+w] * scale2) >> 8;
Mon Jan 12, 2015 10:15 pm
Tue Jan 13, 2015 12:25 am
#include <SPI.h>
#include <Gamebuino.h>
Gamebuino gb;
const byte sprite[] PROGMEM = {
16, 16, 0x1f,0xf8,0x1f,0xf8,0x1f,0xfc,0x1f,0xff,0x1f,0xff,0xf,0xff,0xf,0xff,0x7,0xff,0x87,0xff,0x3,0xff,0x1,0xff,0x0,0x7f,0x2,0x1f,0x0,0x0,0x0,0x0,0x40,0x0,};
void setup(){
gb.begin();
}
void loop(){
long start, finish;
int drawTime;
if(gb.update()){
const int count = 100;
start = millis();
for (int i=0; i<count; i++)
gb.display.drawBitmap(1, 31, sprite);
finish = millis();
drawTime = 1000L*(finish-start)/count;
gb.display.print(F("drawBitmap: "));
gb.display.print(drawTime);
gb.display.println(F("ns"));
start = millis();
for (int i=0; i<count; i++)
drawBitmapUnrolled(17, 31, sprite);
finish = millis();
drawTime = 1000L*(finish-start)/count;
gb.display.print(F("unrolled: "));
gb.display.print(drawTime);
gb.display.println(F("ns"));
}
}
void drawBitmapUnrolled(int8_t x, int8_t y, const uint8_t *bitmap) {
int8_t w = pgm_read_byte(bitmap);
int8_t h = pgm_read_byte(bitmap + 1);
bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
int8_t i, j, byteWidth = (w + 7) >> 3;
uint8_t * screen_line = gb.display.getBuffer() + x;
const uint8_t * bitmap_line = bitmap;
uint8_t dsty = y;
uint8_t mask = _BV(y & 7);
for (j = 0; j < h; j++, dsty++, bitmap_line+=byteWidth, mask = (mask & 0x80) ? 1 : (mask<<1))
{
int ofs = (dsty >> 3) * LCDWIDTH_NOROT;
int8_t dstx = x;
const uint8_t * bitmap_src = bitmap_line;
uint8_t * ptr = screen_line + ofs;
int8_t i = w;
while (i >= 8)
{
uint8_t pixels = pgm_read_byte(bitmap_src++);
if (pixels & 0x80)
ptr[0] |= mask;
if (pixels & 0x40)
ptr[1] |= mask;
if (pixels & 0x20)
ptr[2] |= mask;
if (pixels & 0x10)
ptr[3] |= mask;
if (pixels & 0x08)
ptr[4] |= mask;
if (pixels & 0x04)
ptr[5] |= mask;
if (pixels & 0x02)
ptr[6] |= mask;
if (pixels & 0x01)
ptr[7] |= mask;
ptr += 8;
i -= 8;
dstx += 8;
}
if (i)
{
uint8_t pixels = pgm_read_byte(bitmap_src);
while (i--)
{
if (pixels & 0x80)
gb.display.drawPixel(dstx, dsty);
pixels <<= 1;
}
}
}
}
Tue Jan 13, 2015 4:46 pm
Myndale wrote:A few more optimizations, this version of the drawBitmap routine runs ~6.5 times faster than the library version (i.e. ~330ns vs ~2155ns):
if (pixels & 0x80)
ptr[0] |= mask;
if (pixels & 0x40)
ptr[1] |= mask;
if (pixels & 0x20)
ptr[2] |= mask;
[...]
if (pixels & 0x80)
ptr[7] |= mask;
if (pixels & 0x40)
ptr[6] |= mask;
if (pixels & 0x20)
ptr[5] |= mask;
[...]
Wed Jan 14, 2015 1:24 am
Wed Jan 14, 2015 2:22 am