Ryan Tseng
/
DisplayTest
Diff: KS0108/KS0108.cpp
- Revision:
- 0:87b78725a6dd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/KS0108/KS0108.cpp Mon Mar 05 06:00:16 2012 +0000 @@ -0,0 +1,835 @@ +#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)); + } +} + + + + + + +