Added custom fonts. Added triangle drawing function

Dependents:   sc100016x4lcd REVO_Updated_Steering Driving_game Arkanoid_v1 ... more

KS0108.cpp

Committer:
DimiterK
Date:
2011-01-28
Revision:
2:03d27b3fce6e
Parent:
1:a368f2688222
Child:
3:366a6b7d6259

File content as of revision 2:03d27b3fce6e:

/*************************************************************************
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);
}