LS020.h is a MobileLCD library for the LS020 display (used in GSM Siemens S65 family). Resolution 176x132
Diff: LS020LCD.cpp
- 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))) +}