1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Graphic LCD 96x64 w/ SED1565 Controller

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

  1. AtomSoft

    AtomSoft Well-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;
        int y = radius;

        lcd_setpixel(top, left + radius);
        lcd_setpixel(top, left - radius);
        lcd_setpixel(top + radius, left);
        lcd_setpixel(top - radius, left);
        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. millwood

    millwood Banned

    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. AtomSoft

    AtomSoft Well-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 :D and tend to forget a lot of things. This just helps... hence why i changed again to

    Top0, Left0
    Top1, Left1
     
  4. dave

    Dave New Member

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


     
  5. AtomSoft

    AtomSoft Well-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. AtomSoft

    AtomSoft Well-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:
     

    Attached Files:

  7. AtomSoft

    AtomSoft Well-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:
    [​IMG]

    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,7,"Menu1",NORMAL);
            lcd_str(55,60,"Menu2",NORMAL);
            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;
        int y = radius;

        left += 18;

        lcd_setpixel(top, left + radius);
        lcd_setpixel(top, left - radius);
        lcd_setpixel(top + radius, left);
        lcd_setpixel(top - radius, left);
        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 :D
     

    Attached Files:

    • menu.jpg
      menu.jpg
      File size:
      32.3 KB
      Views:
      570
    Last edited: Jun 20, 2009
  8. millwood

    millwood Banned

    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. AtomSoft

    AtomSoft Well-Known Member

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

    you can simply add :
    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;
        int y = radius;
    #ifdef NOKIA7110
        left += 18;
    #endif
        lcd_setpixel(top, left + radius);
        lcd_setpixel(top, left - radius);
        lcd_setpixel(top + radius, left);
        lcd_setpixel(top - radius, left);
        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...
    [​IMG]

    and when you do:
    [​IMG]

    EDIT

    what setrect?
    I didnt get that code :D
     

    Attached Files:

    Last edited: Jun 20, 2009
  10. millwood

    millwood Banned

    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.
     

    Attached Files:

  11. millwood

    millwood Banned

    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. AtomSoft

    AtomSoft Well-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. AtomSoft

    AtomSoft Well-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);
     
     

    Attached Files:

    • asd.jpg
      asd.jpg
      File size:
      16.1 KB
      Views:
      194
  14. DirtyLude

    DirtyLude Well-Known Member

    Joined:
    Aug 5, 2003
    Messages:
    1,904
    Likes:
    56
    Location:
    Toronto, Canada
    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. millwood

    millwood Banned

    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. millwood

    millwood Banned

    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. DirtyLude

    DirtyLude Well-Known Member

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

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    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. DirtyLude

    DirtyLude Well-Known Member

    Joined:
    Aug 5, 2003
    Messages:
    1,904
    Likes:
    56
    Location:
    Toronto, Canada
    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. DirtyLude

    DirtyLude Well-Known Member

    Joined:
    Aug 5, 2003
    Messages:
    1,904
    Likes:
    56
    Location:
    Toronto, Canada
    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. AtomSoft

    AtomSoft Well-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 :D

    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

Share This Page