Added custom fonts. Added triangle drawing function

Dependents:   sc100016x4lcd REVO_Updated_Steering Driving_game Arkanoid_v1 ... more

Revision:
5:e4b50f4c13a8
Parent:
4:bdc04bb2ffc1
--- a/KS0108.cpp	Thu Feb 10 03:06:19 2011 +0000
+++ b/KS0108.cpp	Mon May 02 19:05:30 2011 +0000
@@ -1,28 +1,3 @@
-/*************************************************************************
-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.
-*******************************************************************************/
-
-/*
- *@Includes
- */
 #include "KS0108.h"     
 
 
@@ -33,10 +8,11 @@
     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       
+    RST.write(1);                         //reset screen
+    E.write(0);                       
+    ClearScreen();                      //clear display
+    WriteInstruction(LCD_ON, BOTH);     //turn on lcd  
+    Inverted = 0;     
 }
 
 
@@ -48,7 +24,7 @@
         
     SelectSide(side);   //select controller
 
-    wait(0.0000003); // 300ns
+    wait(0.0000003);     //wait 300ns
     E.write(1);
     DB.output();
     DB.write(Command);        
@@ -72,6 +48,79 @@
     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){
     
@@ -82,7 +131,7 @@
     if(col<(SCREEN_WIDTH/2)){
     SelectSide(LEFT);           
     WriteInstruction(LCD_SET_PAGE|page,LEFT);     
-    WriteInstruction(LCD_SET_ADD|col,LEFT);            //set page and column position
+    WriteInstruction(LCD_SET_ADD|col,LEFT);          //set page and column position
     WriteData(data,LEFT);                            //output data to D0-D7
     }else{
     
@@ -90,19 +139,21 @@
     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
+    WriteData(data,RIGHT);                          //output data to D0-D7
     }    
                            
     SelectSide(NONE);
 }
 
 
+
 unsigned int KS0108::ReadData(){
    unsigned int data;
    DB.input();
-   DI.write(1);
 
+   DI.write(1);     
    RW.write(1);
+
    E.write(1);
    wait(0.00000045);
       
@@ -114,7 +165,6 @@
    return data;     
 }
 
-
 unsigned int KS0108::ReadStatus(){
    unsigned int status;
    DB.input();
@@ -131,7 +181,8 @@
    DB.output();
    
    return status;     
-}
+}                    
+
 
 
 void KS0108::SelectSide(unsigned char side){
@@ -165,6 +216,7 @@
     WriteInstruction(LCD_OFF,BOTH);
 }
 
+
 /*******************************************************************************************/      
 
  
@@ -178,19 +230,19 @@
   if(x>=64){           
   WriteInstruction(LCD_SET_PAGE|(y/8),RIGHT);
   WriteInstruction(LCD_SET_ADD|x,RIGHT);
-  position = ReadData();            //dummy read 
-  position = ReadData();            //actual read 
+  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
+  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 
+  position = ReadData();                            //dummy read 
+  position = ReadData();                            //actual read 
   WriteInstruction(LCD_SET_ADD|x,LEFT);
   if(color==WHITE)                                
   WriteData(position&(~(1<<(y%8))),LEFT);              
@@ -333,7 +385,7 @@
 
    
     // If the starting X coordinate is larger than the ending X coordinate,
-    // swap the start and end coordinates.
+    // swap coordinates.
     if(lX1 > lX2){
         lError = lX1;
         lX1 = lX2;
@@ -349,7 +401,7 @@
                                                                    
     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.
+    if(lY1 < lY2){                   // Determine the direction to step in the Y axis when required.
         lYStep = 1;
     }else{
         lYStep = -1;
@@ -373,11 +425,11 @@
         
         lError += lDeltaY; 
                     
-        if(lError > 0){        // See if the error term is now greater than zero.
+        if(lError > 0){                // See if the error term is now greater than zero.
                      
-            lY1 += lYStep;        // Take a step in the Y axis.
+            lY1 += lYStep;            // Take a step in the Y axis.
                                                                        
-            lError -= lDeltaX;     // Decrement the error term by the X delta.
+            lError -= lDeltaX;         // Decrement the error term by the X delta.
         }
     }
 }
@@ -501,7 +553,7 @@
   StoppingX = TwoBSquare*XRadius;
   StoppingY = 0;
 
-  while ( StoppingX >=StoppingY ) //first set of points,y'>-1
+  while ( StoppingX >=StoppingY )                 //first set of points,y'>-1
   {
     Plot4EllipsePoints(CX,CY,X,Y,color);
     Y++;
@@ -524,7 +576,7 @@
   StoppingY = TwoASquare*YRadius;
   StoppingX = 0;
 
-  while ( StoppingY >=StoppingX ) //{2nd set of points, y'< -1}
+  while ( StoppingY >=StoppingX )                 //{2nd set of points, y'< -1}
   {
     Plot4EllipsePoints(CX,CY,X,Y,color);
     X++;
@@ -547,8 +599,32 @@
   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
+    
+}
+
+
+
+
 /***********************************************************************************/
 
 
@@ -574,44 +650,58 @@
     }    
 }
 
-void KS0108::CustomImage(Image* image,unsigned int x, unsigned int y, unsigned int color){
-    unsigned int i, j, bit_idx, pixelByte, imgHeight, imgSize;
+unsigned int KS0108::ReadArrayData(const unsigned int* ptr) { 
+    return (*ptr);
+}
 
-    imgHeight  = image->imgHeight;      //get height of the image array
-    imgSize   = (image->imgWidth)>>3;    //number of bytes = width of icon/8
+void KS0108::DrawBitmap(const unsigned int * bitmap, unsigned int x, unsigned int y, unsigned int color){
+unsigned int width, height;
+unsigned int i, j;
 
-    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);
-                }
-        }
-    }
-}   
+  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::CursorXY(unsigned int x, unsigned int y){   
+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;  
+    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        
 
-  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) {
+
+/*****************************************************************************************/
+
+
+
+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]);
@@ -624,15 +714,13 @@
 void KS0108::PutString(unsigned int x, unsigned int y,char* str){
 
     while(*str != 0){
-     Putc(x,y,*str);
+     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);
@@ -646,3 +734,102 @@
    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));      
+   }
+}
+
+
+
+            
+
+    
+