Navigation Menu

Skip to content

Commit

Permalink
added some speedup optimizations, and begin()
Browse files Browse the repository at this point in the history
  • Loading branch information
ladyada committed Jan 26, 2011
1 parent fa79812 commit 418df7f
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 40 deletions.
181 changes: 145 additions & 36 deletions ST7565/ST7565.cpp
Expand Up @@ -30,6 +30,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

#include "ST7565.h"

#define ST7565_STARTBYTES 1

uint8_t is_reversed = 0;

// a handy reference to where the pages are on the screen
Expand Down Expand Up @@ -112,17 +114,38 @@ uint8_t st7565_buffer[1024] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,};

// reduces how much is refreshed, which speeds it up!
// originally derived from Steve Evans/JCW's mod but cleaned up and
// optimized
#define enablePartialUpdate

#ifdef enablePartialUpdate
static uint8_t xUpdateMin, xUpdateMax, yUpdateMin, yUpdateMax;
#endif



static void updateBoundingBox(uint8_t xmin, uint8_t ymin, uint8_t xmax, uint8_t ymax) {
#ifdef enablePartialUpdate
if (xmin < xUpdateMin) xUpdateMin = xmin;
if (xmax > xUpdateMax) xUpdateMax = xmax;
if (ymin < yUpdateMin) yUpdateMin = ymin;
if (ymax > yUpdateMax) yUpdateMax = ymax;
#endif
}

void ST7565::drawbitmap(uint8_t x, uint8_t y,
const uint8_t *bitmap, uint8_t w, uint8_t h,
uint8_t color) {
for (uint8_t j=0; j<h; j++) {
for (uint8_t i=0; i<w; i++ ) {
if (pgm_read_byte(bitmap + i + (j/8)*w) & _BV(j%8)) {
setpixel(x+i, y+j, color);
my_setpixel(x+i, y+j, color);
}
}
}

updateBoundingBox(x, y, x+w, y+h);
}

void ST7565::drawstring(uint8_t x, uint8_t line, char *c) {
Expand All @@ -137,14 +160,32 @@ void ST7565::drawstring(uint8_t x, uint8_t line, char *c) {
if (line >= (LCDHEIGHT/8))
return; // ran out of space :(
}
}


void ST7565::drawstring_P(uint8_t x, uint8_t line, const char *str) {
while (1) {
char c = pgm_read_byte(str++);
if (! c)
return;
drawchar(x, line, c);
x += 6; // 6 pixels wide
if (x + 6 >= LCDWIDTH) {
x = 0; // ran out of this line
line++;
}
if (line >= (LCDHEIGHT/8))
return; // ran out of space :(
}
}

void ST7565::drawchar(uint8_t x, uint8_t line, char c) {
for (uint8_t i =0; i<5; i++ ) {
st7565_buffer[x + (line*128) ] = pgm_read_byte(font+(c*5)+i);
x++;
}

updateBoundingBox(x, line*8, x+5, line*8 + 8);
}


Expand All @@ -162,6 +203,9 @@ void ST7565::drawline(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1,
swap(y0, y1);
}

// much faster to put the test here, since we've already sorted the points
updateBoundingBox(x0, y0, x1, y1);

uint8_t dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
Expand All @@ -174,11 +218,11 @@ void ST7565::drawline(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1,
} else {
ystep = -1;}

for (; x0<x1; x0++) {
for (; x0<=x1; x0++) {
if (steep) {
setpixel(y0, x0, color);
my_setpixel(y0, x0, color);
} else {
setpixel(x0, y0, color);
my_setpixel(x0, y0, color);
}
err -= dy;
if (err < 0) {
Expand All @@ -195,38 +239,44 @@ void ST7565::fillrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,
// stupidest version - just pixels - but fast with internal buffer!
for (uint8_t i=x; i<x+w; i++) {
for (uint8_t j=y; j<y+h; j++) {
setpixel(i, j, color);
my_setpixel(i, j, color);
}
}

updateBoundingBox(x, y, x+w, y+h);
}

// draw a rectangle
void ST7565::drawrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,
uint8_t color) {
// stupidest version - just pixels - but fast with internal buffer!
for (uint8_t i=x; i<x+w; i++) {
setpixel(i, y, color);
setpixel(i, y+h-1, color);
my_setpixel(i, y, color);
my_setpixel(i, y+h-1, color);
}
for (uint8_t i=y; i<y+h; i++) {
setpixel(x, i, color);
setpixel(x+w-1, i, color);
my_setpixel(x, i, color);
my_setpixel(x+w-1, i, color);
}

updateBoundingBox(x, y, x+w, y+h);
}

// draw a circle outline
void ST7565::drawcircle(uint8_t x0, uint8_t y0, uint8_t r,
uint8_t color) {
updateBoundingBox(x0-r, y0-r, x0+r, y0+r);

int8_t f = 1 - r;
int8_t ddF_x = 1;
int8_t ddF_y = -2 * r;
int8_t x = 0;
int8_t y = r;

setpixel(x0, y0+r, color);
setpixel(x0, y0-r, color);
setpixel(x0+r, y0, color);
setpixel(x0-r, y0, color);
my_setpixel(x0, y0+r, color);
my_setpixel(x0, y0-r, color);
my_setpixel(x0+r, y0, color);
my_setpixel(x0-r, y0, color);

while (x<y) {
if (f >= 0) {
Expand All @@ -238,29 +288,34 @@ void ST7565::drawcircle(uint8_t x0, uint8_t y0, uint8_t r,
ddF_x += 2;
f += ddF_x;

setpixel(x0 + x, y0 + y, color);
setpixel(x0 - x, y0 + y, color);
setpixel(x0 + x, y0 - y, color);
setpixel(x0 - x, y0 - y, color);
my_setpixel(x0 + x, y0 + y, color);
my_setpixel(x0 - x, y0 + y, color);
my_setpixel(x0 + x, y0 - y, color);
my_setpixel(x0 - x, y0 - y, color);

setpixel(x0 + y, y0 + x, color);
setpixel(x0 - y, y0 + x, color);
setpixel(x0 + y, y0 - x, color);
setpixel(x0 - y, y0 - x, color);
my_setpixel(x0 + y, y0 + x, color);
my_setpixel(x0 - y, y0 + x, color);
my_setpixel(x0 + y, y0 - x, color);
my_setpixel(x0 - y, y0 - x, color);

}



}

void ST7565::fillcircle(uint8_t x0, uint8_t y0, uint8_t r,
uint8_t color) {
updateBoundingBox(x0-r, y0-r, x0+r, y0+r);

int8_t f = 1 - r;
int8_t ddF_x = 1;
int8_t ddF_y = -2 * r;
int8_t x = 0;
int8_t y = r;

for (uint8_t i=y0-r; i<=y0+r; i++) {
setpixel(x0, i, color);
my_setpixel(x0, i, color);
}

while (x<y) {
Expand All @@ -274,16 +329,27 @@ void ST7565::fillcircle(uint8_t x0, uint8_t y0, uint8_t r,
f += ddF_x;

for (uint8_t i=y0-y; i<=y0+y; i++) {
setpixel(x0+x, i, color);
setpixel(x0-x, i, color);
my_setpixel(x0+x, i, color);
my_setpixel(x0-x, i, color);
}
for (uint8_t i=y0-x; i<=y0+x; i++) {
setpixel(x0+y, i, color);
setpixel(x0-y, i, color);
my_setpixel(x0+y, i, color);
my_setpixel(x0-y, i, color);
}
}
}

void ST7565::my_setpixel(uint8_t x, uint8_t y, uint8_t color) {
if ((x >= LCDWIDTH) || (y >= LCDHEIGHT))
return;

// x is which column
if (color)
st7565_buffer[x+ (y/8)*128] |= _BV(7-(y%8));
else
st7565_buffer[x+ (y/8)*128] &= ~_BV(7-(y%8));
}

// the most basic function, set a single pixel
void ST7565::setpixel(uint8_t x, uint8_t y, uint8_t color) {
if ((x >= LCDWIDTH) || (y >= LCDHEIGHT))
Expand All @@ -294,6 +360,8 @@ void ST7565::setpixel(uint8_t x, uint8_t y, uint8_t color) {
st7565_buffer[x+ (y/8)*128] |= _BV(7-(y%8));
else
st7565_buffer[x+ (y/8)*128] &= ~_BV(7-(y%8));

updateBoundingBox(x,y,x,y);
}


Expand All @@ -305,6 +373,12 @@ uint8_t ST7565::getpixel(uint8_t x, uint8_t y) {
return (st7565_buffer[x+ (y/8)*128] >> (7-(y%8))) & 0x1;
}

void ST7565::begin(uint8_t contrast) {
st7565_init();
st7565_command(CMD_DISPLAY_ON);
st7565_command(CMD_SET_ALLPTS_NORMAL);
st7565_set_brightness(contrast);
}

void ST7565::st7565_init(void) {
// set pin directions
Expand Down Expand Up @@ -353,6 +427,10 @@ void ST7565::st7565_init(void) {
// set page address
// set column address
// write display data

// set up a bounding box for screen updates

updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1);
}

inline void ST7565::spiwrite(uint8_t c) {
Expand Down Expand Up @@ -449,35 +527,66 @@ void ST7565::st7565_set_brightness(uint8_t val) {


void ST7565::display(void) {
uint8_t c, p;
uint8_t col, maxcol, p;

/*
Serial.print("Refresh ("); Serial.print(xUpdateMin, DEC);
Serial.print(", "); Serial.print(xUpdateMax, DEC);
Serial.print(","); Serial.print(yUpdateMin, DEC);
Serial.print(", "); Serial.print(yUpdateMax, DEC); Serial.println(")");
*/

for(p = 0; p < 8; p++) {
/*
putstring("new page! ");
uart_putw_dec(p);
putstring_nl("");
*/
#ifdef enablePartialUpdate
// check if this page is part of update
if ( yUpdateMin >= ((p+1)*8) ) {
continue; // nope, skip it!
}
if (yUpdateMax < p*8) {
break;
}
#endif

st7565_command(CMD_SET_PAGE | pagemap[p]);
st7565_command(CMD_SET_COLUMN_LOWER | (0x0 & 0xf));
st7565_command(CMD_SET_COLUMN_UPPER | ((0x0 >> 4) & 0xf));


#ifdef enablePartialUpdate
col = xUpdateMin;
maxcol = xUpdateMax;
#else
// start at the beginning of the row
col = 0;
maxcol = LCDWIDTH-1;
#endif

st7565_command(CMD_SET_COLUMN_LOWER | ((col+ST7565_STARTBYTES) & 0xf));
st7565_command(CMD_SET_COLUMN_UPPER | (((col+ST7565_STARTBYTES) >> 4) & 0x0F));
st7565_command(CMD_RMW);
st7565_data(0xff);

//st7565_data(0x80);
//continue;

for(c = 0; c < 128; c++) {
//uart_putw_dec(c);
for(; col <= maxcol; col++) {
//uart_putw_dec(col);
//uart_putchar(' ');
st7565_data(st7565_buffer[(128*p)+c]);
st7565_data(st7565_buffer[(128*p)+col]);
}
}

#ifdef enablePartialUpdate
xUpdateMin = LCDWIDTH - 1;
xUpdateMax = 0;
yUpdateMin = LCDHEIGHT-1;
yUpdateMax = 0;
#endif
}

// clear everything
void ST7565::clear(void) {
memset(st7565_buffer, 0, 1024);
updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1);
}


Expand Down
4 changes: 4 additions & 0 deletions ST7565/ST7565.h
Expand Up @@ -78,6 +78,7 @@ class ST7565 {


void st7565_init(void);
void begin(uint8_t contrast);
void st7565_command(uint8_t c);
void st7565_data(uint8_t c);
void st7565_set_brightness(uint8_t val);
Expand All @@ -99,6 +100,7 @@ class ST7565 {
uint8_t color);
void drawchar(uint8_t x, uint8_t line, char c);
void drawstring(uint8_t x, uint8_t line, char *c);
void drawstring_P(uint8_t x, uint8_t line, const char *c);

void drawbitmap(uint8_t x, uint8_t y,
const uint8_t *bitmap, uint8_t w, uint8_t h,
Expand All @@ -108,5 +110,7 @@ class ST7565 {
int8_t sid, sclk, a0, rst, cs;
void spiwrite(uint8_t c);

void my_setpixel(uint8_t x, uint8_t y, uint8_t color);

//uint8_t buffer[128*64/8];
};
5 changes: 1 addition & 4 deletions ST7565/examples/st7565lcd/st7565lcd.pde
Expand Up @@ -31,10 +31,7 @@ void setup() {
digitalWrite(BACKLIGHT_LED, HIGH);

// initialize and set the contrast to 0x18
glcd.st7565_init();
glcd.st7565_command(CMD_DISPLAY_ON);
glcd.st7565_command(CMD_SET_ALLPTS_NORMAL);
glcd.st7565_set_brightness(0x18);
glcd.begin(0x18);

glcd.display(); // show splashscreen
delay(2000);
Expand Down

0 comments on commit 418df7f

Please sign in to comment.