Fork of Dimiter program. "Wait" commands adjusted and added Arial 10 font.
Fork of KS0108 by
KS0108.cpp
- Committer:
- DimiterK
- Date:
- 2011-02-04
- Revision:
- 3:366a6b7d6259
- Parent:
- 2:03d27b3fce6e
- Child:
- 4:bdc04bb2ffc1
File content as of revision 3:366a6b7d6259:
/************************************************************************* Copyright (c) 2010 Dimiter Kentri 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 "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 } 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); // 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::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::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 the start and end 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::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); } } void KS0108::CustomImage(Image* image,unsigned int x, unsigned int y, unsigned int color){ unsigned int i, j, bit_idx, pixelByte, imgHeight, imgSize; imgHeight = image->imgHeight; //get height of the image array imgSize = (image->imgWidth)>>3; //number of bytes = width of icon/8 for(i=0;i<imgHeight;i++){ for(j=0;j<imgSize;j++){ pixelByte = image->imgarray[i*imgSize+j]; for(bit_idx=0;bit_idx<8;bit_idx++){ if(pixelByte&(0x80>>bit_idx)) SetPixel(x+bit_idx+8*j, y+i, color); else SetPixel(x+bit_idx+8*j, y+i, !color); } } } } /******************************************************************************************/ void KS0108::CursorXY(unsigned int x, unsigned int y){ if( (x > SCREEN_WIDTH-1) || (y > SCREEN_HEIGHT-1) ) // exit if coordinates are not legal return; if(y<(SCREEN_WIDTH/2)){ SelectSide(LEFT); WriteInstruction(LCD_SET_PAGE|(y/8),RIGHT); WriteInstruction(LCD_SET_ADD|x,RIGHT); }else{ SelectSide(RIGHT); WriteInstruction(LCD_SET_PAGE|(y/8),RIGHT); WriteInstruction(LCD_SET_ADD|x,RIGHT); } } void KS0108::Putc (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){ Putc(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); }