LS020.h is a MobileLCD library for the LS020 display (used in GSM Siemens S65 family). Resolution 176x132

LS020LCD.cpp

Committer:
Wimpie
Date:
2010-12-06
Revision:
1:2269e07af50b
Parent:
0:d550841cd6eb
Child:
2:d048f09dcfb0

File content as of revision 1:2269e07af50b:

/* mbed LS020 Library, for driving the LCD display LS020 from SHARP used in 
 * GSM S65 Siemens
 *
 * Copyright (c) 2010, Wim De Roeve, thanks to Christian Kranz research
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "LS020LCD.h"
#include "mbed.h"

#include "fonts/font_6x8.h"
#include "fonts/font_8x8.h"
#include "fonts/font_8x12.h"
#include "fonts/font_clock.h"

#define TINYFONT                       (0)   //6x8
#define TINYFONT_NAME                  font0
#define TINYFONT_START                 FONT0_START
#define TINYFONT_WIDTH                 FONT0_WIDTH
#define TINYFONT_HEIGHT                FONT0_HEIGHT
#define SMALLFONT                      (1)  //8x8
#define SMALLFONT_NAME                 font1
#define SMALLFONT_START                FONT1_START
#define SMALLFONT_WIDTH                FONT1_WIDTH
#define SMALLFONT_HEIGHT               FONT1_HEIGHT
#define NORMALFONT                     (2)  //8x12
#define NORMALFONT_NAME                font2
#define NORMALFONT_START               FONT2_START
#define NORMALFONT_WIDTH               FONT2_WIDTH
#define NORMALFONT_HEIGHT              FONT2_HEIGHT
#define TIMEFONT                       (3)  //Clock
#define TIMEFONT_NAME                  font3
#define TIMEFONT_START                 FONT3_START
#define TIMEFONT_WIDTH                 FONT3_WIDTH
#define TIMEFONT_HEIGHT                FONT3_HEIGHT

// colors in 8 bit mode BGR off   RRRGGGBB
#define BLACK  0x00
#define WHITE  0xFF
#define RED    0xE0
#define GREEN  0x1C
#define BLUE   0x03

using namespace mbed;

unsigned int checkbit(const unsigned long *data, unsigned int nr);


LS020LCD::LS020LCD(PinName mosi, PinName miso, PinName clk, PinName cs, PinName rst, PinName rs)
        : _spi(mosi, miso, clk)
        , _rst(rst)
        , _cs(cs)
        , _rs(rs) {
    _rotate=false;
    _mirror=false;
    reset();
}

void LS020LCD::write_cmdRG(uint8_t reg, uint8_t param) {
    _rs = 1; //cmd
    _cs = 0;
    _spi.write(reg);
    _spi.write(param);
    _cs = 1;
}

void LS020LCD::write_cmd8(uint8_t cmd8) {
    _rs = 1; //cmd
    _cs = 0;
    _spi.write(cmd8);
    _cs = 1;
}

void LS020LCD::write_cmd16(uint16_t cmd16) {
    _rs = 1; //cmd
    _cs = 0;
    _spi.write((cmd16>>8)&0xFF);
    _spi.write(cmd16&0xFF);
    _cs = 1;
}

void LS020LCD::write_data8(char data) {
    _rs = 0; //data
    _cs = 0;
    _spi.write(data);
    _cs = 1;
}

void LS020LCD::write_data16(uint16_t cmd16) {
    _rs = 0; //data
    _cs = 0;
    _spi.write((cmd16>>8)&0xFF);
    _spi.write(cmd16&0xFF);
    _cs = 1;
}

void LS020LCD::draw(uint16_t cmd16) {
    _spi.write((cmd16>>8)&0xFF);
    _spi.write(cmd16&0xFF);
}

void LS020LCD::drawstop(void) {
    _cs = 1;
}


void LS020LCD::drawstart(void) {
    _rs = 0; //data
    _cs = 0;
}

void LS020LCD::locate(int column, int row) {
    _row = row;
    _column = column;
}

void LS020LCD::newline() {
    _column = 0;
    _row++;
    if (_row >= _rows) {
        _row = 0;
    }
}

int LS020LCD::columns() {
    return _columns;
}

int LS020LCD::rows() {
    return _rows;
}

// ***************** Init and reset

void LS020LCD::orientation(bool rotate, bool mirror) {
    _rotate=rotate;
    _mirror=mirror;

    if (rotate==0) {  //default = 176 x 132
        _width=132;
        _height=176;
    } else {          //132 x 176
        _width=176;
        _height=132;

    }
}

void LS020LCD::reset(void) {

    const unsigned char init_array_0[20]={
        0xEF, 0x00, 0xEE, 0x04, 0x1B, 0x04, 0xFE, 0xFE,
        0xFE, 0xFE, 0xEF, 0x90, 0x4A, 0x04, 0x7F, 0x3F,
        0xEE, 0x04, 0x43, 0x06
    };

    const unsigned char init_array_1[46]= {
        0xEF, 0x90, 0x09, 0x83, 0x08, 0x00, 0x0B, 0xAF,
        0x0A, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00,
        0xEF, 0x00, 0xEE, 0x0C, 0xEF, 0x90, 0x00, 0x80,
        0xEF, 0xB0, 0x49, 0x02, 0xEF, 0x00, 0x7F, 0x01,
        0xE1, 0x81, 0xE2, 0x02, 0xE2, 0x76, 0xE1, 0x83,
        0x80, 0x01, 0xEF, 0x90, 0x00, 0x00
    };

    int i;

    // Setup the spi for 8 bit data, high steady state clock,
    // second edge capture, with a 8MHz clock rate

    _spi.format(8,3);
    _spi.frequency(8000000);

    //reset
    _cs = 1;
    _rs = 1;
    _rst= 0;

    wait_ms(50);

    _rst = 1;
    wait_ms(50);
    _cs = 0;

    write_cmd16(0xFDFD);
    write_cmd16(0xFDFD);

    wait_ms(68);

    //init part 1
    for (i=0;i<20;i++) {
        write_cmd8(init_array_0[i]);
    }

    //important: wait 10ms
    wait_ms(10);

    //init part 2
    for (i=0;i<46;i++) {
        write_cmd8(init_array_1[i]);
    }

    orientation(_rotate,_mirror);
    set_window(0, 0, (_width-1), (_height-1));
    
    _foreground=BLACK;
    _background=WHITE;
    _row=0;
    _column=0;
    _font=1;
    
    cls();

    return;

};

// *****************  MODE settings

void LS020LCD::set_8bit_mode(char BGR) {
    // BGR=0 - disabled, BGR=1 - enabled.
    write_cmd16(0xE800+(BGR&0x01)*0x40);
}

void LS020LCD::set_16bit_mode(void) {
    write_cmd16(0xE80F);
}

void LS020LCD::set_8_color_mode(void) {
    write_cmd16(0x0401);
    write_cmd16(0x0000);
}

void LS020LCD::set_65k_color_mode(void) {
    write_cmd16(0x0400);
    write_cmd16(0x0000);
}

void LS020LCD::foreground(unsigned int color) {
    _foreground = color;
}

void LS020LCD::background(unsigned int color) {
    _background = color;
}

// ****************

void LS020LCD::set_cursor(unsigned int x, unsigned int y) {
    write_cmd16(0xEF90);

    if (_rotate) {
        if (_mirror) {
            write_cmdRG(0x06, (_width-1)-x);  //set x cursor pos
            write_cmdRG(0x07, (_height-1)-y); //set y cursor pos
        } else {
            write_cmdRG(0x06, x);             //set x cursor pos
            write_cmdRG(0x07, y);             //set y cursor pos
        }
    } else {
        if (_mirror) {
            write_cmdRG(0x06, (_height-1)-y); //set y cursor pos
            write_cmdRG(0x07, x);             //set x cursor pos
        } else {
            write_cmdRG(0x06, y);             //set y cursor pos
            write_cmdRG(0x07, (_width-1)-x);  //set x cursor pos
        }
    }
}

void LS020LCD::set_window(char x0, char y0, char x1,char y1) {
    // write_cmd16(0x0500);// Set Direction
    // write_cmd16(0x0A00+x1);
    // write_cmd16(0x0B00+x2);
    // write_cmd16(0x0800+y1);
    // write_cmd16(0x0900+y2);

    //set area
    write_cmd16(0xEF90);
    if (_rotate) {
        if (_mirror) {
            write_cmdRG(0x08, (_width-1)-x0);  //set x0
            write_cmdRG(0x09, (_width-1)-x1);  //set x1
            write_cmdRG(0x0A, (_height-1)-y0); //set y0
            write_cmdRG(0x0B, (_height-1)-y1); //set y1
        } else {
            write_cmdRG(0x08, x0);                //set x0
            write_cmdRG(0x09, x1);                //set x1
            write_cmdRG(0x0A, y0);                //set y0
            write_cmdRG(0x0B, y1);                //set y1
        }
    } else {
        if (_mirror) {
            write_cmdRG(0x08, (_height-1)-y0); //set y0
            write_cmdRG(0x09, (_height-1)-y1); //set y1
            write_cmdRG(0x0A, x0);                //set x0
            write_cmdRG(0x0B, x1);                //set x1
        } else {
            write_cmdRG(0x08, y0);                //set y0
            write_cmdRG(0x09, y1);                //set y1
            write_cmdRG(0x0A, (_width-1)-x0);  //set x0
            write_cmdRG(0x0B, (_width-1)-x1);  //set x1
        }
    }

    //set cursor
    set_cursor(x0, y0);

}

unsigned int LS020LCD::putc(unsigned int x, unsigned int y, unsigned int c, unsigned int size,unsigned int font, unsigned int color, unsigned int bgcolor) {
    unsigned int ret, i, j, width, height, w, h, wh;
    const unsigned long *ptr;

    switch (font) {
        case TINYFONT:
            c     -= TINYFONT_START;
            ptr    = (const unsigned long*)&TINYFONT_NAME[c*(TINYFONT_WIDTH*TINYFONT_HEIGHT/8)];
            width  = TINYFONT_WIDTH;
            height = TINYFONT_HEIGHT;
            break;
        case SMALLFONT:
            c     -= SMALLFONT_START;
            ptr    = (const unsigned long*)&SMALLFONT_NAME[c*(SMALLFONT_WIDTH*SMALLFONT_HEIGHT/8)];
            width  = SMALLFONT_WIDTH;
            height = SMALLFONT_HEIGHT;
            break;
        case NORMALFONT:
            c     -= NORMALFONT_START;
            ptr    = (const unsigned long*)&NORMALFONT_NAME[c*(NORMALFONT_WIDTH*NORMALFONT_HEIGHT/8)];
            width  = NORMALFONT_WIDTH;
            height = NORMALFONT_HEIGHT;
            break;
        case TIMEFONT:
            c     -= TIMEFONT_START;
            ptr    = (const unsigned long*)&TIMEFONT_NAME[c*(TIMEFONT_WIDTH*TIMEFONT_HEIGHT/8)];
            width  = TIMEFONT_WIDTH;
            height = TIMEFONT_HEIGHT;
            break;
    }

    ret = x+(width*size);
    if (ret > _width) {
        return _width+1;
    }

    if (size <= 1) {
        set_window(x, y, x+(+width-1), y+(height-1));
        drawstart();

        unsigned long data, mask;
        for (wh=(width*height)/32; wh!=0; wh--) {
            data = *ptr++;
            //data = ((data&0xFF000000UL)>>24)|((data&0x00FF0000UL)>>8)|((data&0x0000FF00UL)<<8)|((data&0x000000FFUL)<<24); //swap32
            for (mask=0x80000000UL; mask!=0UL; mask>>=1) {
                if (data & mask) {
                    draw(color);
                } else {
                    draw(bgcolor);
                }
            }
        }

        drawstop();
    } else {
        set_window(x, y, x+(width*size)-1, y+(height*size)-1);
        drawstart();

        unsigned int bit;
        wh = (width*height);
        for (h=0; h<wh; h+=width) {
            for (i=size; i!=0; i--) {
                bit = h;
                for (w=0; w<width; w++) {
                    if (checkbit(ptr, bit++)) {
                        for (j=size; j!=0; j--) {
                            draw(color);
                        }
                    } else {
                        for (j=size; j!=0; j--) {
                            draw(bgcolor);
                        }
                    }
                }
            }
        }

        drawstop();
    }

    return ret;
}


void LS020LCD::fillrectangle(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, unsigned int color) {
    unsigned int wh, tmp;

    if (x0 > x1) {
        tmp = x0;
        x0  = x1;
        x1  = tmp;
    }
    if (y0 > y1) {
        tmp = y0;
        y0  = y1;
        y1  = tmp;
    }

    if ((x1 >= _width) ||
            (y1 >= _height)) {
        return;
    }

    set_window(x0, y0, x1, y1);

    drawstart();
    for (wh=((1+(x1-x0))*(1+(y1-y0))); wh!=0; wh--) {
        draw(color);
    }
    drawstop();

    return;
}

void LS020LCD::drawpixel(unsigned int x, unsigned int y, unsigned int color) {
    if ((x >= _width) ||
            (y >= _height)) {
        return;
    }
    set_cursor(x, y);
    drawstart();
    draw(color);
    drawstop();

    return;
}

void LS020LCD::drawline(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, unsigned int color) {
    int dx, dy, dx2, dy2, stepx, stepy, err;

    if ((x0 == x1) ||
            (y0 == y1)) { //horizontal or vertical line
        fillrectangle(x0, y0, x1, y1, color);
    } else {
        //calculate direction
        dx = x1 - x0;
        dy = y1 - y0;
        if (dx < 0) {
            dx = -dx;
            stepx = -1;
        } else {
            stepx = +1;
        }
        if (dy < 0) {
            dy = -dy;
            stepy = -1;
        } else {
            stepy = +1;
        }
        dx2 = dx << 1;
        dy2 = dy << 1;
        //draw line
        set_window(0, 0, (_width-1), (_height-1));
        drawpixel(x0, y0, color);
        if (dx > dy) {
            err = dy2 - dx;
            while (x0 != x1) {
                if (err >= 0) {
                    err -= dx2;
                    y0  += stepy;
                }
                err += dy2;
                x0  += stepx;
                drawpixel(x0, y0, color);
            }
        } else {
            err = dx2 - dy;
            while (y0 != y1) {
                if (err >= 0) {
                    err -= dy2;
                    x0  += stepx;
                }
                err += dx2;
                y0  += stepy;
                drawpixel(x0, y0, color);
            }
        }
    }

    return;
}

void LS020LCD::drawrectangle(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, unsigned int color) {
    fillrectangle(x0, y0, x0, y1, color);
    fillrectangle(x0, y1, x1, y1, color);
    fillrectangle(x1, y0, x1, y1, color);
    fillrectangle(x0, y0, x1, y0, color);

    return;
}


void LS020LCD::fillcircle(unsigned int x0, unsigned int y0, unsigned int radius, unsigned int color) {
    int err, x, y;

    err = -radius;
    x   = radius;
    y   = 0;

    set_window(0, 0, (_width-1), (_height-1));

    while (x >= y) {
        drawline(x0 - x, y0 + y, x0 + x, y0 + y, color);
        drawline(x0 - x, y0 - y, x0 + x, y0 - y, color);
        drawline(x0 - y, y0 + x, x0 + y, y0 + x, color);
        drawline(x0 - y, y0 - x, x0 + y, y0 - x, color);

        err += y;
        y++;
        err += y;
        if (err >= 0) {
            x--;
            err -= x;
            err -= x;
        }
    }

    return;
}


void  LS020LCD::drawcircle(unsigned int x0, unsigned int y0, unsigned int radius, unsigned int color) {
    int err, x, y;

    err = -radius;
    x   = radius;
    y   = 0;

    set_window(0, 0, (_width-1), (_height-1));

    while (x >= y) {
        drawpixel(x0 + x, y0 + y, color);
        drawpixel(x0 - x, y0 + y, color);
        drawpixel(x0 + x, y0 - y, color);
        drawpixel(x0 - x, y0 - y, color);
        drawpixel(x0 + y, y0 + x, color);
        drawpixel(x0 - y, y0 + x, color);
        drawpixel(x0 + y, y0 - x, color);
        drawpixel(x0 - y, y0 - x, color);

        err += y;
        y++;
        err += y;
        if (err >= 0) {
            x--;
            err -= x;
            err -= x;
        }
    }

    return;
}

/*void LS020LCD::rectangle8(char x1, char y1, char x2, char y2, char color) {
    set_window(x1,y1,x2,y2);
    for (char y=y1;y<=y2;y++) {
        for (char x=x1;x<=x2;x++) {
            write_data8(color);
        }
    }
}


void LS020LCD::putpixel(unsigned char r,unsigned char g,unsigned char b, unsigned char x, unsigned char y) {
    uint16_t data;
    write_cmd16(0xEF90);
    write_cmd16(0x0500);
    write_cmd16(0x0800+ x);
    write_cmd16(0x0A00+ y);
    write_cmd16(0x0900+ x+1);
    write_cmd16(0x0B00+ y+1);
    data=0xffff-(((uint16_t)(31*b/255))*0x800)+(((uint16_t)(63*g/255))*0x20)+(((uint16_t)(31*r/255)));
    write_data16(data);

}
void LS020LCD::put_char8(char x, char y, char symbol, char color, char bkcolor) {
    set_window(x,y,x+5,y+7);
    int offset=6*(symbol-0x20);
    for (char i=0;i<6;i++) {
        for (char j=0;j<8;j++) {
            if (((font0[offset+i]<<j)&0x80)==0x80) {
                write_data8(color);
            } else {
                write_data8(bkcolor);
            }
        }
    }
}*/

void LS020LCD::drawtext(unsigned int x, unsigned int y, char* text, unsigned int size,unsigned int font, unsigned int color, unsigned int bgcolor) {
    char i=0;
    char x0=0;
    
    while (text[i]!=0) {
        x=putc(x+x0,y,text[i],size,font,color,bgcolor);
        i++;
       
    }
}

void LS020LCD::cls() {
    fillrectangle(0, 0, _width, _height, _background);
}

void LS020LCD::scroll(char offset) {
    write_cmd16(0x1100+offset);
}

unsigned int checkbit(const unsigned long *data, unsigned int nr) {
    return (data[nr/32] & (0x80000000UL>>(nr&31))); // (data[nr/32] & (1<<(nr&31)))
}