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))) }