Fork of Dimiter program. "Wait" commands adjusted and added Arial 10 font.
Fork of KS0108 by
KS0108.cpp
- Committer:
- DimiterK
- Date:
- 2011-05-02
- Revision:
- 5:e4b50f4c13a8
- Parent:
- 4:bdc04bb2ffc1
- Child:
- 6:7c0770d5639d
File content as of revision 5:e4b50f4c13a8:
#include "KS0108.h" KS0108::KS0108 (PinName _RST,PinName _DI, PinName _RW, PinName _E, PinName _CS2, PinName _CS1, PinName DB0, PinName DB1, PinName DB2, PinName DB3, PinName DB4, PinName DB5, PinName DB6, PinName DB7) : DB(DB0,DB1,DB2,DB3,DB4,DB5,DB6,DB7),RST (_RST),DI(_DI), RW(_RW), E(_E), CS2(_CS2), CS1(_CS1) { DB.output(); CS1.output(); CS2.output(); RST.write(0); wait_us(10); RST.write(1); //reset screen E.write(0); ClearScreen(); //clear display WriteInstruction(LCD_ON, BOTH); //turn on lcd Inverted = 0; } void KS0108::WriteInstruction(unsigned int Command,unsigned int side){ E.write(0); DI.write(0); RW.write(0); SelectSide(side); //select controller wait(0.0000003); //wait 300ns E.write(1); DB.output(); DB.write(Command); wait(0.0000001); E.write(0); } void KS0108::WriteData(unsigned int data,unsigned char side){ E.write(0); DI.write(1); RW.write(0); SelectSide(side); wait(0.0000003); // 300ns E = 1; DB.output(); DB.write(data); wait(0.0000001); E = 0; } void KS0108::WriteData(unsigned int data) { unsigned int displayData, yOffset, chip; if(Coord.x >= SCREEN_WIDTH) return; chip = Coord.x/CHIP_WIDTH; wait(0.000000450); // 300ns if(Coord.x % CHIP_WIDTH == 0 && chip > 0){ GotoXY(Coord.x, Coord.y); } DI.write(1); // D/I = 1 RW.write(0); // R/W = 0 DB.output(); // data port is output yOffset = Coord.y%8; if(yOffset != 0) { // first page displayData = ReadData(); DI.write(1); // D/I = 1 RW.write(0); // R/W = 0 SelectSide(chip); DB.output(); // data port is output displayData |= data << yOffset; if(Inverted) displayData = ~displayData; DB.write(displayData); // write data wait(0.0000003); // 300ns E.write(1); wait(0.0000001); E.write(0); // second page GotoXY(Coord.x, Coord.y+8); displayData = ReadData(); DI.write(1); // D/I = 1 RW.write(0); // R/W = 0 SelectSide(chip); DB.output(); // data port is output displayData |= data >> (8-yOffset); if(Inverted) displayData = ~displayData; DB.write(displayData); // write data wait(0.0000003); // 300ns E.write(1); wait(0.0000001); E.write(0); GotoXY(Coord.x+1, Coord.y-8); }else { // just this code gets executed if the write is on a single page if(Inverted) data = ~data; wait(0.0000003); // 300nsEN_DELAY(); DB.write(data); // write data wait(0.0000003); // 300ns E = 1; wait(0.0000001); E = 0; Coord.x++; } } void KS0108::WriteDataColPag(unsigned int page, unsigned int col, unsigned int data){ SelectSide(NONE); col = col%SCREEN_WIDTH; page = page%8; if(col<(SCREEN_WIDTH/2)){ SelectSide(LEFT); WriteInstruction(LCD_SET_PAGE|page,LEFT); WriteInstruction(LCD_SET_ADD|col,LEFT); //set page and column position WriteData(data,LEFT); //output data to D0-D7 }else{ SelectSide(RIGHT); col -= (SCREEN_WIDTH/2); WriteInstruction(LCD_SET_PAGE|page,RIGHT); WriteInstruction(LCD_SET_ADD|col,RIGHT); //set page and column position WriteData(data,RIGHT); //output data to D0-D7 } SelectSide(NONE); } unsigned int KS0108::ReadData(){ unsigned int data; DB.input(); DI.write(1); RW.write(1); E.write(1); wait(0.00000045); data = DB.read(); wait(0.0000001); E.write(0); DB.output(); return data; } unsigned int KS0108::ReadStatus(){ unsigned int status; DB.input(); DI.write(0); RW.write(1); E.write(1); wait(0.00000045); status = DB.read(); E.write(0); wait(0.0000001); DB.output(); return status; } void KS0108::SelectSide(unsigned char side){ if(side==LEFT) {CS1.write(1);CS2.write(0);} else if(side==RIGHT) {CS1.write(0);CS2.write(1);} else if (side==BOTH) {CS1.write(1);CS2.write(1);} else if (side==NONE) {CS1.write(0);CS2.write(0);} } void KS0108::ClearScreen(){ for (int col=0;col<128;col++) { for (int page=0;page<8;page++) { WriteDataColPag(page,col,WHITE); } } } void KS0108::TurnOn(){ WriteInstruction(LCD_ON,BOTH); } void KS0108::TurnOff(){ WriteInstruction(LCD_OFF,BOTH); } /*******************************************************************************************/ void KS0108::SetPixel(unsigned int x, unsigned int y, unsigned int color){ unsigned int position; SelectSide(NONE); WriteInstruction(LCD_SET_ADD,NONE); if(x>=64){ WriteInstruction(LCD_SET_PAGE|(y/8),RIGHT); WriteInstruction(LCD_SET_ADD|x,RIGHT); position = ReadData(); //dummy read position = ReadData(); //actual read WriteInstruction(LCD_SET_ADD|x,RIGHT); if(color==WHITE) WriteData(position&(~(1<<(y%8))),RIGHT); // draw a white pixel else WriteData(position|(1<<(y%8)),RIGHT); wait_us(450); }else{ WriteInstruction(LCD_SET_PAGE|(y/8),LEFT); WriteInstruction(LCD_SET_ADD|x,LEFT); position = ReadData(); //dummy read position = ReadData(); //actual read WriteInstruction(LCD_SET_ADD|x,LEFT); if(color==WHITE) WriteData(position&(~(1<<(y%8))),LEFT); else WriteData(position|(1<<(y%8)),LEFT); wait_us(450); } } void KS0108::FullRectangle(unsigned int Xaxis1, unsigned int Yaxis1, unsigned int Xaxis2 ,unsigned int Yaxis2,unsigned int color){ for(unsigned int i=Xaxis1;i<=Xaxis2;i++){ for(unsigned int j=Yaxis1;j<=Yaxis2;j++){ SetPixel(i,j,color); } } } void KS0108::EmptyRectangle(unsigned int Xaxis1,unsigned int Yaxis1, unsigned int Xaxis2,unsigned int Yaxis2,unsigned int color){ unsigned int CurrentValue; /* Draw the two horizontal lines */ for (CurrentValue = 0; CurrentValue < Xaxis2 - Xaxis1+ 1; CurrentValue++) { SetPixel(Xaxis1 + CurrentValue, Yaxis1,color); SetPixel(Xaxis1 + CurrentValue, Yaxis2,color); } /* draw the two vertical lines */ for (CurrentValue = 0; CurrentValue < Yaxis2 - Yaxis1 + 1; CurrentValue++) { SetPixel(Xaxis1, Yaxis1 + CurrentValue,color); SetPixel(Xaxis2, Yaxis1 + CurrentValue,color); } } void KS0108::RoundRectangle(unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned int radius, unsigned int color) { int tSwitch, x1 = 0, y1 = radius; tSwitch = 3 - 2 * radius; while (x1 <= y1) { SetPixel(x+radius - x1, y+radius - y1, color); SetPixel(x+radius - y1, y+radius - x1, color); SetPixel(x+width-radius + x1, y+radius - y1, color); SetPixel(x+width-radius + y1, y+radius - x1, color); SetPixel(x+width-radius + x1, y+height-radius + y1, color); SetPixel(x+width-radius + y1, y+height-radius + x1, color); SetPixel(x+radius - x1, y+height-radius + y1, color); SetPixel(x+radius - y1, y+height-radius + x1, color); if (tSwitch < 0) { tSwitch += (4 * x1 + 6); } else { tSwitch += (4 * (x1 - y1) + 10); y1--; } x1++; } HLineShort(x+radius,y, width-(2*radius), color); // top HLineShort(x+radius,y+height, width-(2*radius), color); // bottom VLineShort(x,y+radius,height-(2*radius), color); // left VLineShort(x+width, y+radius,height-(2*radius), color); // right } void KS0108::HLine(unsigned int Xaxis1, unsigned int Xaxis2 ,unsigned int Yaxis,unsigned int color){ FullRectangle(Xaxis1,Yaxis,Xaxis2,Yaxis,color); } void KS0108::HLineShort(unsigned int Xaxis, unsigned int Yaxis,unsigned int width ,unsigned int color){ FullRectangle(Xaxis,Yaxis,Xaxis+width,Yaxis,color); } void KS0108::VLine(unsigned int Xaxis, unsigned int Yaxis1 ,unsigned int Yaxis2,unsigned int color){ FullRectangle(Xaxis,Yaxis1,Xaxis,Yaxis2,color); } void KS0108::VLineShort(unsigned int Xaxis,unsigned int Yaxis, unsigned int height ,unsigned int color){ FullRectangle(Xaxis,Yaxis,Xaxis,Yaxis+height,color); } void KS0108::DegreeLine(unsigned int x, int y,unsigned int degree,unsigned int inner_radius,unsigned int outer_radius, unsigned int color){ int fx,fy,tx,ty; fx = x + dfloor(inner_radius * sin(degree * 3.14 / 180)); fy = y - dfloor(inner_radius * cos(degree * 3.14 / 180)); tx = x + dfloor(outer_radius * sin(degree * 3.14 / 180)); ty = y - dfloor(outer_radius * cos(degree * 3.14 / 180)); SlantyLine(fx,fy,tx,ty,color); } double KS0108::dfloor( double value ) { if (value < 0.0) return ceil( value ); else return floor( value ); } void KS0108::SlantyLine(unsigned int lX1, unsigned int lY1, unsigned int lX2,unsigned int lY2,unsigned int color){ long lError, lDeltaX, lDeltaY, lYStep, bSteep; // A steep line has a bigger ordinate. if(((lY2 > lY1) ? (lY2 - lY1) : (lY1 - lY2)) > ((lX2 > lX1) ? (lX2 - lX1) : (lX1 - lX2))){ bSteep = 1; }else { bSteep = 0; } // If line is steep, swap the X and Y coordinates. if(bSteep){ lError = lX1; lX1 = lY1; lY1 = lError; lError = lX2; lX2 = lY2; lY2 = lError; } // If the starting X coordinate is larger than the ending X coordinate, // swap coordinates. if(lX1 > lX2){ lError = lX1; lX1 = lX2; lX2 = lError; lError = lY1; lY1 = lY2; lY2 = lError; } // Compute the difference between the start and end coordinates. lDeltaX = lX2 - lX1; lDeltaY = (lY2 > lY1) ? (lY2 - lY1) : (lY1 - lY2); lError = -lDeltaX / 2; // Initialize the error term to negative half the X delta. if(lY1 < lY2){ // Determine the direction to step in the Y axis when required. lYStep = 1; }else{ lYStep = -1; } for(; lX1 <= lX2; lX1++){ // Loop through all the points along the X axis of the line. // See if this is a steep line. if(bSteep){ // Plot this point of the line, swapping the X and Y coordinates. SetPixel(lY1, lX1,color); } else { // Plot this point of the line, using the coordinates as is. SetPixel(lX1, lY1,color); } // Increment the error term by the Y delta. lError += lDeltaY; if(lError > 0){ // See if the error term is now greater than zero. lY1 += lYStep; // Take a step in the Y axis. lError -= lDeltaX; // Decrement the error term by the X delta. } } } void KS0108::Line(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int color){ unsigned int deltax, deltay, x,y, steep; int lerror, ystep; steep = absDiff(y1,y2) > absDiff(x1,x2); //check slope if ( steep ){ swap(x1, y1); swap(x2, y2); } if (x1 > x2){ swap(x1, x2); swap(y1, y2); } deltax = x2 - x1; deltay = absDiff(y2,y1); lerror = deltax / 2; y = y1; if(y1 < y2) ystep = 1; else ystep = -1; for(x = x1; x <= x2; x++){ if (steep) SetPixel(y,x, color); else SetPixel(x,y, color); lerror -= deltay; if (lerror < 0){ y = y + ystep; lerror += deltax; } } } void KS0108::EmptyCircle(unsigned int CenterX, unsigned int CenterY, unsigned int Radius,unsigned int color){ unsigned int y=0, x=0, d = 0; int part; d = CenterY - CenterX; y = Radius; part = 3 - 2 * Radius; while (x <= y) { SetPixel(CenterX + x, CenterY + y,color); SetPixel(CenterX + x, CenterY - y,color); SetPixel(CenterX - x, CenterY + y,color); SetPixel(CenterX - x, CenterY - y,color); SetPixel(CenterY + y - d, CenterY + x,color); SetPixel(CenterY + y - d, CenterY - x,color); SetPixel(CenterY - y - d, CenterY + x,color); SetPixel(CenterY - y - d, CenterY - x,color); if (part < 0) part += (4 * x + 6); else { part += (4 * (x - y) + 10); y--; } x++; } } void KS0108::FullCircle(unsigned int CenterX, unsigned int CenterY, unsigned int Radius,unsigned int color){ int f = 1 - Radius; int ddF_x = 1; int ddF_y = 2 * Radius; //changed sign of -2 unsigned int x = 0; unsigned int y = Radius; //Fill in the center between the two halves Line(CenterX, CenterY-Radius, CenterX, CenterY+Radius, color); while(x < y){ if(f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x; /* * Now draw vertical lines between the points on the circle rather than * draw the points of the circle. This draws lines between the * perimeter points on the upper and lower quadrants of the 2 halves of the circle. */ Line(CenterX+x, CenterY+y, CenterX+x, CenterY-y, color); Line(CenterX-x, CenterY+y, CenterX-x, CenterY-y, color); Line(CenterX+y, CenterY+x, y+CenterX, CenterY-x, color); Line(CenterX-y, CenterY+x, CenterX-y, CenterY-x, color); } } void KS0108::PlotEllipse(long CX, long CY, long XRadius,long YRadius, int color) { long X, Y; long XChange, YChange; long EllipseError; long TwoASquare,TwoBSquare; long StoppingX, StoppingY; TwoASquare = 2*XRadius*XRadius; TwoBSquare = 2*YRadius*YRadius; X = XRadius; Y = 0; XChange = YRadius*YRadius*(1-2*XRadius); YChange = XRadius*XRadius; EllipseError = 0; StoppingX = TwoBSquare*XRadius; StoppingY = 0; while ( StoppingX >=StoppingY ) //first set of points,y'>-1 { Plot4EllipsePoints(CX,CY,X,Y,color); Y++; StoppingY=StoppingY+ TwoASquare; EllipseError = EllipseError+ YChange; YChange=YChange+TwoASquare; if ((2*EllipseError + XChange) > 0 ) { X--; StoppingX=StoppingX- TwoBSquare; EllipseError=EllipseError+ XChange; XChange=XChange+TwoBSquare; } } Y = YRadius; X = 0; YChange = XRadius*XRadius*(1-2*YRadius); XChange = YRadius*YRadius; EllipseError = 0; StoppingY = TwoASquare*YRadius; StoppingX = 0; while ( StoppingY >=StoppingX ) //{2nd set of points, y'< -1} { Plot4EllipsePoints(CX,CY,X,Y,color); X++; StoppingX=StoppingX + TwoBSquare; EllipseError=EllipseError+ XChange; XChange=XChange+TwoBSquare; if ((2*EllipseError + YChange) > 0 ) { Y--; StoppingY=StoppingY- TwoASquare; EllipseError=EllipseError+ YChange; YChange=YChange+TwoASquare; } } } void KS0108::Plot4EllipsePoints(long CX,long CY, long X, long Y, int color){ SetPixel(CX+X, CY+Y, color); //{point in quadrant 1} SetPixel(CX-X, CY+Y, color); //{point in quadrant 2} SetPixel(CX-X, CY-Y, color); //{point in quadrant 3} SetPixel(CX+X, CY-Y, color); //{point in quadrant 4} } void KS0108::RightTriangle ( int topx, int topy, int rightx, int righty) { //draw rectangle one line at a time Line( topx,topy, rightx,righty,BLACK ); //draw hypotenuse Line ( topx,righty,topx,topy,BLACK); //draw perpendicular Line (topx,righty, rightx,righty,BLACK); // draw base } void KS0108::Triangle ( int topx, int topy, int rightx, int righty) { int base =0; base = 2* rightx-topx; //draw rectangle one line at a time Line( topx,topy, rightx,righty,BLACK ); //draw hypotenuse Line ( topx,righty,topx,topy,BLACK); //draw perpendicular Line(topx-base/2,righty, rightx,righty,BLACK); // draw base Line(topx-base/2, righty, topx,topy,BLACK); // draw hypotenuse } /***********************************************************************************/ void KS0108::FullScreenBMP (unsigned char *PictureData){ unsigned int Page=0; unsigned int Column=0; // Draw left side of the picture SelectSide(LEFT); for (Page = 0; Page < 8; Page++){ /* loop on the 8 pages */ WriteInstruction(LCD_SET_PAGE | Page,LEFT); /* Set the page */ for (Column = 0; Column < 64; Column++) WriteData(PictureData[(128*Page)+Column],LEFT); } // Draw right side of the picture SelectSide(RIGHT); for (Page = 0; Page < 8; Page++){ /* loop on the 8 pages */ WriteInstruction(LCD_SET_PAGE| Page,RIGHT); /* Set the page */ for (Column = 64; Column < 128; Column++) WriteData(PictureData[(128*Page)+Column],RIGHT); } } unsigned int KS0108::ReadArrayData(const unsigned int* ptr) { return (*ptr); } void KS0108::DrawBitmap(const unsigned int * bitmap, unsigned int x, unsigned int y, unsigned int color){ unsigned int width, height; unsigned int i, j; width = ReadArrayData(bitmap++); height = ReadArrayData(bitmap++); for(j = 0; j < height / 8; j++) { GotoXY(x, y + (j*8) ); for(i = 0; i < width; i++) { unsigned int displayData = ReadArrayData(bitmap++); if(color == BLACK) WriteData(displayData); else WriteData(~displayData); } } } /******************************************************************************************/ void KS0108::GotoXY(unsigned int x, unsigned int y) { unsigned int chip, cmd; if( (x > SCREEN_WIDTH-1) || (y > SCREEN_HEIGHT-1) ) // exit if coordinates are not legal return; Coord.x = x; // save new coordinates Coord.y = y; if(y/8 != Coord.page) { Coord.page = y/8; cmd = LCD_SET_PAGE | Coord.page; // set y address on all chips for(chip=0; chip < 2; chip++){ WriteInstruction(cmd, chip); } } chip = Coord.x/64; x = x % 64; cmd = LCD_SET_ADD | x; WriteInstruction(cmd, chip); // set x address on active chip } /*****************************************************************************************/ void KS0108::Putchar (int page, int col,unsigned char c) { if (c>31 && c<127){ for(int i=0;i<5;i++){ WriteDataColPag(page,col+i,System5x7[((c-32)*5+i)+6]); } } } void KS0108::PutString(unsigned int x, unsigned int y,char* str){ while(*str != 0){ Putchar(x,y,*str); str++; y+=System5x7[2]; } } void KS0108::PrintFloat(float val, unsigned int x,unsigned int y){ char buf[20] = {}; // prints up to 20 digits sprintf(buf,"%f",val); PutString(x,y,buf); } void KS0108::PrintInteger(int val,unsigned int x,unsigned int y){ char buf[20] = {}; // prints up to 20 digits sprintf(buf,"%d",val); PutString(x,y,buf); } void KS0108::SelectFont(unsigned int* font,unsigned int color, FontCallback callback) { Font = font; FontRead = callback; FontColor = color; } int KS0108::PrintChar(char c) { unsigned int width = 0; unsigned int height = FontRead(Font+FONT_HEIGHT); unsigned int bytes = (height+7)/8; unsigned int firstChar = FontRead(Font+FONT_FIRST_CHAR); unsigned int charCount = FontRead(Font+FONT_CHAR_COUNT); unsigned int index = 0; unsigned int x=Coord.x , y=Coord.y; if(c < firstChar || c >= (firstChar+charCount)) { return 1; } c-= firstChar; if( FontRead(Font+FONT_LENGTH) == 0 && FontRead(Font+FONT_LENGTH+1) == 0) { // zero length is flag indicating fixed width font (array does not contain width data entries) width = FontRead(Font+FONT_FIXED_WIDTH); index = c*bytes*width+FONT_WIDTH_TABLE; } else{ // variable width font, read width data, to get the index for(unsigned int i=0; i<c; i++) { index += FontRead(Font+FONT_WIDTH_TABLE+i); } index = index*bytes+charCount+FONT_WIDTH_TABLE; width = FontRead(Font+FONT_WIDTH_TABLE+c); } // last but not least, draw the character for(unsigned int i=0; i<bytes; i++) { unsigned int page = i*width; for(unsigned int j=0; j<width; j++) { unsigned int data = FontRead(Font+index+page+j); if(height > 8 && height < (i+1)*8) { data >>= (i+1)*8-height; } WriteData(data); } // 1px gap between chars WriteData(0x00); GotoXY(x,Coord.y+8); } GotoXY(x+width+1, y); return 0; } void KS0108::PrintString(char* str) { int x = Coord.x; while(*str != 0) { if(*str == '\n') { GotoXY(x, Coord.y+ FontRead(Font+FONT_HEIGHT)); } else { PrintChar(*str); } str++; } } void KS0108::PrintNumber(long n){ char buf[10]; // prints up to 10 digits char i=0; if(n==0) PrintChar('0'); else{ if(n < 0){ PrintChar('-'); n = -n; } while(n>0 && i <= 10){ buf[i++] = n % 10; // n % base n /= 10; // n/= base } for(; i >0; i--) PrintChar((char) (buf[i-1] < 10 ? '0' + buf[i-1] : 'A' + buf[i-1] - 10)); } }