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

Revision:
0:d550841cd6eb
Child:
1:2269e07af50b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LS020LCD.cpp	Mon Dec 06 20:25:44 2010 +0000
@@ -0,0 +1,635 @@
+/* mbed LS020 Library, for driving the I2C I/O Expander
+ * Copyright (c) 2010, Wim De Roeve, port from Christian Kranz info
+ * 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)))
+}