# Graphic LCD 96x64 w/ SED1565 Controller

Discussion in 'Microcontrollers' started by AtomSoft, May 23, 2009.

1. ### AtomSoftWell-Known Member

Joined:
Feb 7, 2008
Messages:
5,670
Likes:
41
Location:
Brooklyn, NY US
i think i got it now lol im so dumb lol

Its cool i edited like this : (cuz i forget everything trust me lol )
Code (text):

/**********************************************************
draw a line between two points
code shamelessly stolen from Jim Lynch's 6100 driver
which itself is based on Jack Bresenham's line algorithm
**********************************************************/
void lcd_setline(char top0, char left0, char top1, char left1) {

int dy = left1 - left0;
int dx = top1 - top0;
int stepx, stepy;

if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
dy <<= 1; // dy is now 2*dy
dx <<= 1; // dx is now 2*dx
lcd_setpixel(top0, left0);

if (dx > dy) {
int fraction = dy - (dx >> 1); // same as 2*dy - dx
while (top0 != top1) {
if (fraction >= 0) {
left0 += stepy;
fraction -= dx; // same as fraction -= 2*dx
}
top0 += stepx;
fraction += dy; // same as fraction -= 2*dy
lcd_setpixel(top0, left0);
}
} else {
int fraction = dx - (dy >> 1);
while (left0 != left1) {
if (fraction >= 0) {
top0 += stepx;
fraction -= dy;
}
left0 += stepy;
fraction += dx;
lcd_setpixel(top0, left0);
}
}
}
/**********************************************************
draw a circle between two points
code shamelessly stolen from Jim Lynch's 6100 driver
which itself is based on Jack Bresenham's line algorithm
**********************************************************/
void lcd_setcircle(char top, char left, char radius) {

int f = 1 - radius;
int ddF_x = 0;
int ddF_y = -2 * radius;
int x = 0;

while(x < y) {
if(f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x + 1;
lcd_setpixel(top + x, left + y);
lcd_setpixel(top - x, left + y);
lcd_setpixel(top + x, left - y);
lcd_setpixel(top - x, left - y);
lcd_setpixel(top + y, left + x);
lcd_setpixel(top - y, left + x);
lcd_setpixel(top + y, left - x);
lcd_setpixel(top - y, left - x);
}
}

Last edited: Jun 20, 2009
2. ### millwoodBanned

Joined:
Jun 17, 2009
Messages:
191
Likes:
2
it would be quite nice to develop a structure type like that. not terribly important but nice. in my last iteration, I added another parameter to decide on if I want to set or clear the line / circle / rect / ..., rather than using a set() and then a clr().

Last edited: Jun 20, 2009
3. ### AtomSoftWell-Known Member

Joined:
Feb 7, 2008
Messages:
5,670
Likes:
41
Location:
Brooklyn, NY US
heh i like the normal names because i might be smart sometimes but im dumb the rest and tend to forget a lot of things. This just helps... hence why i changed again to

Top0, Left0
Top1, Left1

Joined:
Jan 12, 1997
Messages:
-
Likes:
0

5. ### AtomSoftWell-Known Member

Joined:
Feb 7, 2008
Messages:
5,670
Likes:
41
Location:
Brooklyn, NY US

why not just +18 like:

Code (text):

void lcd_setline(char top0, char left0, char top1, char left1) {

int dy;
int dx;
int stepx, stepy;

left0 = left0 + 18;
left1 = left1 + 18;

dy = left1 - left0;
dx = top1 - top0;

if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
dy <<= 1; // dy is now 2*dy
dx <<= 1; // dx is now 2*dx
lcd_setpixel(top0, left0);

if (dx > dy) {
int fraction = dy - (dx >> 1); // same as 2*dy - dx
while (top0 != top1) {
if (fraction >= 0) {
left0 += stepy;
fraction -= dx; // same as fraction -= 2*dx
}
top0 += stepx;
fraction += dy; // same as fraction -= 2*dy
lcd_setpixel(top0, left0);
}
} else {
int fraction = dx - (dy >> 1);
while (left0 != left1) {
if (fraction >= 0) {
top0 += stepx;
fraction -= dy;
}
left0 += stepy;
fraction += dx;
lcd_setpixel(top0, left0);
}
}
}

6. ### AtomSoftWell-Known Member

Joined:
Feb 7, 2008
Messages:
5,670
Likes:
41
Location:
Brooklyn, NY US
Now you can:

Code (text):

lcd_setline(0,95,64,95);
lcd_setline(64,0,64,95);
lcd_setline(0,0,64,0);
lcd_setline(0,0,0,95);

to get:

File size:
129.7 KB
Views:
208
7. ### AtomSoftWell-Known Member

Joined:
Feb 7, 2008
Messages:
5,670
Likes:
41
Location:
Brooklyn, NY US
I am going to edit some of the code with the +18 because its a few functions with that issue.

More coding would give you:

Code:
Code (text):

lcd_setline(0,95,64,95);
lcd_setline(64,0,64,95);
lcd_setline(0,0,64,0);
lcd_setline(0,0,0,95);

lcd_setline(52,0,52,95);

lcd_setline(52,40,64,40);
lcd_setline(52,54,64,54);

lcd_str(55,46,"k",NORMAL);

lcd_setcircle(58,47,5);

using this altered code:
Code (text):

/**********************************************************
draw a line between two points
code shamelessly stolen from Jim Lynch's 6100 driver
which itself is based on Jack Bresenham's line algorithm
**********************************************************/
void lcd_setline(char top0, char left0, char top1, char left1) {

int dy;
int dx;
int stepx, stepy;

left0 += 18;
left1 += 18;

dy = left1 - left0;
dx = top1 - top0;

if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
dy <<= 1; // dy is now 2*dy
dx <<= 1; // dx is now 2*dx
lcd_setpixel(top0, left0);

if (dx > dy) {
int fraction = dy - (dx >> 1); // same as 2*dy - dx
while (top0 != top1) {
if (fraction >= 0) {
left0 += stepy;
fraction -= dx; // same as fraction -= 2*dx
}
top0 += stepx;
fraction += dy; // same as fraction -= 2*dy
lcd_setpixel(top0, left0);
}
} else {
int fraction = dx - (dy >> 1);
while (left0 != left1) {
if (fraction >= 0) {
top0 += stepx;
fraction -= dy;
}
left0 += stepy;
fraction += dx;
lcd_setpixel(top0, left0);
}
}
}
/**********************************************************
draw a circle between two points
code shamelessly stolen from Jim Lynch's 6100 driver
which itself is based on Jack Bresenham's line algorithm
**********************************************************/
void lcd_setcircle(char top, char left, char radius) {

int f = 1 - radius;
int ddF_x = 0;
int ddF_y = -2 * radius;
int x = 0;

left += 18;

while(x < y) {
if(f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x + 1;
lcd_setpixel(top + x, left + y);
lcd_setpixel(top - x, left + y);
lcd_setpixel(top + x, left - y);
lcd_setpixel(top - x, left - y);
lcd_setpixel(top + y, left + x);
lcd_setpixel(top - y, left + x);
lcd_setpixel(top + y, left - x);
lcd_setpixel(top - y, left - x);
}
}
/**********************************************************
Write a string at current screen position
**********************************************************/
void lcd_str(char lcd_row, char lcd_col, const char *str, char attribute) {

char i=0;
lcd_col += 18;
while (*str) {
lcd_chr(lcd_row, lcd_col+i, *str++, attribute);
i+=6;
}

}

I didnt touch lcd_chr just incase it gets called somewhere else in the future

#### Attached Files:

File size:
32.3 KB
Views:
597
Last edited: Jun 20, 2009
8. ### millwoodBanned

Joined:
Jun 17, 2009
Messages:
191
Likes:
2
Jason: that will work. you can also use the lcd_setrect() function to draw a box.

I didn't +18 so the same code can be ported to true sed1565-based displays.

9. ### AtomSoftWell-Known Member

Joined:
Feb 7, 2008
Messages:
5,670
Likes:
41
Location:
Brooklyn, NY US
oh ok i see now... lol

Code (text):

#ifdef NOKIA7110
left += 18;
#endif

remember to
Code (text):
#define NOKIA7110
Code (text):

/**********************************************************
Write a string at current screen position
**********************************************************/
void lcd_str(char lcd_row, char lcd_col, const char *str, char attribute) {

char i=0;
#ifdef NOKIA7110
lcd_col += 18;
#endif
while (*str) {
lcd_chr(lcd_row, lcd_col+i, *str++, attribute);
i+=6;
}

}

/**********************************************************
draw a line between two points
code shamelessly stolen from Jim Lynch's 6100 driver
which itself is based on Jack Bresenham's line algorithm
**********************************************************/
void lcd_setline(char top0, char left0, char top1, char left1) {

int dy;
int dx;
int stepx, stepy;

#ifdef NOKIA7110
left0 += 18;
left1 += 18;
#endif
dy = left1 - left0;
dx = top1 - top0;

if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
dy <<= 1; // dy is now 2*dy
dx <<= 1; // dx is now 2*dx
lcd_setpixel(top0, left0);

if (dx > dy) {
int fraction = dy - (dx >> 1); // same as 2*dy - dx
while (top0 != top1) {
if (fraction >= 0) {
left0 += stepy;
fraction -= dx; // same as fraction -= 2*dx
}
top0 += stepx;
fraction += dy; // same as fraction -= 2*dy
lcd_setpixel(top0, left0);
}
} else {
int fraction = dx - (dy >> 1);
while (left0 != left1) {
if (fraction >= 0) {
top0 += stepx;
fraction -= dy;
}
left0 += stepy;
fraction += dx;
lcd_setpixel(top0, left0);
}
}
}
/**********************************************************
draw a circle between two points
code shamelessly stolen from Jim Lynch's 6100 driver
which itself is based on Jack Bresenham's line algorithm
**********************************************************/
void lcd_setcircle(char top, char left, char radius) {

int f = 1 - radius;
int ddF_x = 0;
int ddF_y = -2 * radius;
int x = 0;
#ifdef NOKIA7110
left += 18;
#endif
while(x < y) {
if(f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x + 1;
lcd_setpixel(top + x, left + y);
lcd_setpixel(top - x, left + y);
lcd_setpixel(top + x, left - y);
lcd_setpixel(top - x, left - y);
lcd_setpixel(top + y, left + x);
lcd_setpixel(top - y, left + x);
lcd_setpixel(top + y, left - x);
lcd_setpixel(top - y, left - x);
}
}

This is what happens when you dont define the NOKIA7110...

and when you do:

EDIT

what setrect?
I didnt get that code

#### Attached Files:

File size:
32.3 KB
Views:
614
• ###### noDEfine.jpg
File size:
28.7 KB
Views:
566
Last edited: Jun 20, 2009
10. ### millwoodBanned

Joined:
Jun 17, 2009
Messages:
191
Likes:
2
sorry, I may have added it after I posted it.

here is the latest. I just started but haven't finished yet the bmp function, lcd_setbmp(), so as is the program doesn't compile.

File size:
6.2 KB
Views:
185
11. ### millwoodBanned

Joined:
Jun 17, 2009
Messages:
191
Likes:
2
it would be easier and more flexible to just drop the bmp, but it will take up tons of memory - a trade-off.

12. ### AtomSoftWell-Known Member

Joined:
Feb 7, 2008
Messages:
5,670
Likes:
41
Location:
Brooklyn, NY US
if you leave the BMP as one big block then you can just:
Code (text):

void lcd_setbmp(const char *bmp, char set_clr) {
char i, j;

for (i=0; i<=8; i++)
for (j=0; j<=132; j++)
lcd_write_byte(i, j, *bmp++, NORMAL);//[i][j], NORMAL);

}

also why are you using 132? if its 96 pixels wide? or is this another thing to fit that controller

Last edited: Jun 20, 2009
13. ### AtomSoftWell-Known Member

Joined:
Feb 7, 2008
Messages:
5,670
Likes:
41
Location:
Brooklyn, NY US
Hey i was using your new code and notice it doesnt let me write a character pass a certain point look:

Code (text):

lcd_setrect(0,0,95,64,SET);
lcd_setrect(52,0,95,64,SET);
lcd_setrect(52,40,16,64,SET);

lcd_str(55,42,"OK",NORMAL);
lcd_str(55,7,"ItemA",NORMAL);
lcd_str(55,58,"ItemA",NORMAL);

File size:
16.1 KB
Views:
205
14. ### DirtyLudeWell-Known Member

Joined:
Aug 5, 2003
Messages:
1,904
Likes:
56
Location:
Ya, those are the line and circle functions I used. rectangle too:

Code (text):
void lcd7110_set_rect(int x0, int y0, int x1, int y1)
{
lcd7110_set_line(x0, y0, x1, y0);
lcd7110_set_line(x0, y1, x1, y1);
lcd7110_set_line(x0, y0, x0, y1);
lcd7110_set_line(x1, y0, x1, y1);
}
Writing each pixel individually just doesn't work for me. For an 8x6 character you are setting/clearing each bit individually and doing 4 writes to the LCD for each pixel. That's 192 writes to the LCD for each character. I'd like to do scrolling and that would totally kill a large write of characters to the screen.

Currently I'm tracking each page that is changed and doing a quick write of the page lines that have changed when I call a refresh. I'd like to have it track more specific page/columns that changed, but I'm not certain if that's necessary. A page line refresh is quicker than I can detect and even when writing a circle or rectangle that goes over multiple pages, I can't actually see the writing.

Here's my code. AT91SAM7S256 - Compiles under Crossworks or GCC ARM.
I was going to clean this up and add some comments, but I went out all day today. I don't know when I'll get to this again, so here it is.
http://www.higginstribe.com/sam7/lcd7110/lcd7110_0.1.zip

15. ### millwoodBanned

Joined:
Jun 17, 2009
Messages:
191
Likes:
2
Jason:

I think I was limiting the right edge to a certain point, it is in either lcd_write_byte() or lcd_write_chr() - they do a boundary check, on illegal char or illegal address at the begining of the function call.

I think the lcd_write_byte() can be significantly improved while preserving portability. it is literally drawing the char bit by bit, thus the slow speed.

16. ### millwoodBanned

Joined:
Jun 17, 2009
Messages:
191
Likes:
2
"I'd like to do scrolling and that would totally kill a large write of characters to the screen."

on scrolling: if you dynamically move the comm line, it will cause the entire screen to scroll - it is mentioned in the datasheet and it worked when I tried it.

17. ### DirtyLudeWell-Known Member

Joined:
Aug 5, 2003
Messages:
1,904
Likes:
56
Location:
Cool, thanks. I don't know if I'll have time to look at all this again for a few days at least.

18. ### TriodeMember

Joined:
Feb 11, 2009
Messages:
943
Likes:
22
Location:
Bay Area
I just ordered two of these from dipmicro. I just need something to read out the values of a few variables, hopefully with all the code you guys have posted that shouldn't be too hard. Thanks!

19. ### DirtyLudeWell-Known Member

Joined:
Aug 5, 2003
Messages:
1,904
Likes:
56
Location:
The smooth scroll works, but it's a little disappointing. It looks like the refresh rate of the LCD itself is to blame, but it kinda blinks as it moves from one frame to another. Sending a whole page of data to the screen is actually very fast, and there is no detectable delay from the top of the screen to the bottom.

The slight blink makes the scroll a little jarring to look at.

20. ### DirtyLudeWell-Known Member

Joined:
Aug 5, 2003
Messages:
1,904
Likes:
56
Location:
Back to this old thread, but I found out something pretty bizarre just now. I took off my LCD PCB off the breadboard in order measure how much current it pulls, because my ground and power lines are hidden under the PCB, only to find that I've never attached the power wire, only the ground. All this time, it looks like my LCD has been powered by the data lines alone. Not certain how this works, but it does. So, I'm just shrugging my shoulders over this one.

I ported over a simplified text only library to the MSP430 and I have the whole processor and LCD running on a CR2032 battery. It's pretty cool, because with no sleep mode or any power saving and full clock, it all takes 2.3mA, which should last 95 hours on a CR2032 coin cell battery.

21. ### AtomSoftWell-Known Member

Joined:
Feb 7, 2008
Messages:
5,670
Likes:
41
Location:
Brooklyn, NY US
awesome! so my remote is very do-able with 2-4AA batteries

I plan on buying a XLP:
PIC MCUs with nanoWatt XLP(tm) technology for extreme low power and battery applications

Since it can save alot of energy and have it in DEEP sleep most of the time and 1 button to wakeup. this way it will last long without a recharge.

EDIT:

Most likely ill get a PIC18F46J50 to test it out and see how much current the entire project takes in sleep/deep sleep/normal operations

Last edited: Jun 29, 2009