LCD TFT for ssd0139 driver 8 bit mode - using portout for max speed

Fork of LCDTFT_ssd0139 by chris stevens

LCDTFT.cpp

Committer:
cstevens
Date:
2015-06-10
Revision:
4:1c2f9e3b9b12
Parent:
3:f999653c1069

File content as of revision 4:1c2f9e3b9b12:

/*
  @file LCDTFT.cpp
  @version: 1.0
 
  @web www.micros-designs.com.ar
  @date 30/01/11
  
*- Version Log --------------------------------------------------------------*
*   Fecha       Autor                Comentarios                             *
*----------------------------------------------------------------------------*
* 30/01/11      Suky        Original                                         *
*----------------------------------------------------------------------------*/ 
///////////////////////////////////////////////////////////////////////////
////                                                                   ////
////                                                                   ////
////        (C) Copyright 2011 www.micros-designs.com.ar               ////
//// Este c�digo puede ser usado, modificado y distribuido libremente  ////
//// sin eliminar esta cabecera y  sin garant�a de ning�n tipo.        ////
////                                                                   ////
////                                                                   ////
/////////////////////////////////////////////////////////////////////////// 
#include "LCDTFT.h"

LCDTFT::LCDTFT(PinName PIN_RD,PinName PIN_WR,PinName PIN_RS,PinName PIN_CS,PinName PIN_RESET, PortOut *PORTLCD)
    : LCD_PIN_RD(PIN_RD),LCD_PIN_WR(PIN_WR),LCD_PIN_RS(PIN_RS),LCD_PIN_CS(PIN_CS),LCD_PIN_RESET(PIN_RESET){
    LCD_PORT=PORTLCD;
    X=0;
    Y=0;
    X_min=0;
    X_max=LCD_X_MAX;
    _Alto=1;
    _Color=0x0000;
}
// global variable for screen orientation set by init
bool orient=0;

 static const unsigned short regValues[] = {
    0x0000, 0x0001, // start oscillation
    0x00FF, 0x0010, // wait 16 ms
    0x0007, 0x0000, //display control - zeros everything ??? 
    0x0013, 0x0000, // power control 3 setting = all zero
    0x0011, 0x2604, //power control 2 seting = gvd voltage 0x26 vci1 voltage 0x04
    0x0014, 0x0015, // power contrlol 4 setting vcmr=0 vcomh=0 vml=13 = amplitude of vcom voltage
    0x0010, 0x3C00, // power control 1 bt3=0 sap=7 (0b111) bt=4 (0b100)
    0x0013, 0x0040, //power control 3 PON=1 PON1=0 AON=0
    0x00FF,0x0010, // wait 16ms
    0x0013, 0x0060, // power control 3 PON=1 PON1=1 AON=0    
    0x00FF, 0x0032, // wait 50ms
    0x0013, 0x0070, //power control 3 PON=1 PON1=1 AON=1
    0x00FF, 0x0028, // wait 40ms
       
    0x0001, 0x0127,  // driver ouptut control
    0x0002, 0x0700,  //LCD driving waveform settings
    0x0003, 0x1030,  // entry mode settingtri=0 dfm=0 bgr=1 id1:id0=11
    0x0007, 0x0000,  // display control 1 pt1-0=0 vle2-1=0 spt=0 gon=0 rev=0 d1-0=0
    0x0008, 0x0404,  //black period control fp3-0=4 bp3-0=4
    0x000B, 0x0200,  //frame cycle setting nd1-0=0 sdt1-0=2 ecs2-0=0 div1-0=0 dcr_ex=0 dcr2-0=0 rtn1-0=0
    0x000C, 0x0000,  //external interface controlrm=0 dm1-0=0 rim1-0=0
    0x00015,0x0000,  //sub panel control sub_im1-0=0 stn_en=0 mpu_mode=0 fcv_en=0
       
    //gamma setting    
    0x0030, 0x0000,      
    0x0031, 0x0606,    
    0x0032, 0x0006,    
    0x0033, 0x0403,  
    0x0034, 0x0107,  
    0x0035, 0x0101, 
    0x0036, 0x0707,   
    0x0037, 0x0304,   
    0x0038, 0x0A00,     
    0x0039, 0x0706,     
       // end of gamma settings
    0x0040, 0x0000,   // gate scan position (start g1 scan) scn5-0=0
    0x0041, 0x0000,   // vertical scroll setting vl8-0=0
    0x0042, 0x013F,   // screen end position se18-10=0x13F
    0x0043, 0x0000,   // screen_start position ss28-20=0
    0x0044, 0x0000,   // 2nd screen driving position end 00
    0x0045, 0x0000,   //2nd screen driving position start =00
    0x0046, 0xEF00,   //window addre horizontal ram for x0,x1 HEA=0xEF HSA=00 ie x=0 and x=239
    0x0047, 0x013F,   //vertical ram address end vea=0x13F ie y=319
    0x0048, 0x0000,    //vertical ram address start=00 ie y=0
    0x0007, 0x0011,  //dispaly control 1
    0x00FF, 0x0028, //wait 40ms
    0x0007, 0x0017,    //display control 1

};


void LCDTFT::vLCDTFTSetParametersPrintf(unsigned short Xo,unsigned short Yo,unsigned short Xmin,unsigned short Xmax,unsigned char Alto, unsigned short Color,unsigned short BackColor){

    X=Xo;
    Y=Yo;
    X_min=Xmin;
    X_max=Xmax;
    _Alto=Alto;
    _Color=Color;
    _Background=BackColor;
}

int LCDTFT::_putc(int value){
    char Fmt[2]={value,0};

    if(value=='\n'){
        X=X_min;
        Y+=8*_Alto + 1;
    }else{
        vLCDTFTText(X,Y,(const char *)&Fmt[0],&ARIAL[0],_Alto,_Color,_Background);
        X+=5*_Alto+1;
        if(X >= X_max){
            X = X_min;                           
            Y += 8*_Alto + 1;                
        }
    }
    return(value);
}

int LCDTFT::_getc(){
    return(-1);
}

void LCDTFT::vLCDTFTWriteCommand(unsigned short Data){   
    
    LCD_PIN_RS=0;
    LCD_PIN_CS=0;   
    LCD_PORT->write(Data>>8);   // MSB so with an 8 bit port we need to write here the high and ,low bytes successively
    LCD_PIN_WR=0;
    LCD_PIN_WR=1;
    LCD_PORT->write(Data & 0x00FF);   // LSB
    LCD_PIN_WR=0;
    LCD_PIN_WR=1;
    
    LCD_PIN_CS=1;   
}

void LCDTFT::vLCDTFTWriteData(unsigned short Data){
    LCD_PIN_RS=1;
    LCD_PIN_CS=0;   
    LCD_PORT->write(Data>>8);   // MSB so with an 8 bit port we need to write here the high and ,low bytes successively
    LCD_PIN_WR=0;
    LCD_PIN_WR=1;
    LCD_PORT->write(Data & 0x00FF);   // LSB
    LCD_PIN_WR=0;
    LCD_PIN_WR=1;
    LCD_PIN_CS =1;   
}


void LCDTFT::vLCDTFTWriteCommandData(unsigned short CMD,unsigned short Data){
    vLCDTFTWriteCommand(CMD);
    vLCDTFTWriteData(Data);
}

void LCDTFT::vLCDTFTAddressSet(unsigned short x1,unsigned short y1,unsigned short x2,unsigned short y2){ 

    vLCDTFTWriteCommandData(0x0044,(x2<<8)+x1);
    vLCDTFTWriteCommandData(0x0045,y1);
    vLCDTFTWriteCommandData(0x0046,y2);
    vLCDTFTWriteCommandData(0x004e,x1);
    vLCDTFTWriteCommandData(0x004f,y1);
    vLCDTFTWriteCommand(0x0022);       
}  

void LCDTFT::vLCDTFTAddressSetPoint(unsigned short x,unsigned short y){ 

// CGRAM addresses are given by (x+y*256) - for some reason the y cordinate 
// addresses require 17 bits
// equiv if y is given by 0xYYY and x by 0xXX
// then address of point x,y is 0xYYYXXX
     int add;
     int adl,adh;
     if(orient==0){ // portrait
            add=x+y*256; //240 x 320 y but 256 bytes for each x row
         
            }
    else{
            add=(239-y)+x*256;
        }   
      adl=add & 0x00FF; // selects the 8 low bits
            adh=(add >>8); // the 9 high bits
   vLCDTFTWriteCommandData(0x0020,adl); // 8 lsb of address
   vLCDTFTWriteCommandData(0x0021,adh); //9 msb of address
    vLCDTFTWriteCommand(0x0022);       // prepare to send rgb data
}  

void LCDTFT::vLCDTFTInit(bool format){

    int i;
    unsigned short  address,data;
    orient=format;
    LCD_PIN_RESET=1;
    wait_ms(5);   // must hold for at least 1ms after reset
    LCD_PIN_RESET=0;
    wait_ms(10); // wait for stable R-C oscillation
    LCD_PIN_RESET=1;
    wait_ms(5); // final wait for rest to be acitvated
    LCD_PIN_CS=1;
    LCD_PIN_RD=1;
    LCD_PIN_WR=1;
    wait_ms(20);
    
    for(i=0;i<sizeof(regValues)/4;i++)
    {
        address=regValues[i*2];
        data=regValues[i*2+1];
        
        if(address==0xFF)
        {
            wait_ms(data);
            }
            else {
                vLCDTFTWriteCommandData(address,data);
                }
        }
        wait_ms(3); // changed from 1
        

/*
    vLCDTFTWriteCommandData(0x0000,0x0001);    wait_ms(1);  
    vLCDTFTWriteCommandData(0x0003,0xA8A4);    wait_ms(1);  
    vLCDTFTWriteCommandData(0x000C,0x0000);    wait_ms(1);   
    vLCDTFTWriteCommandData(0x000D,0x080C);    wait_ms(1);   
    vLCDTFTWriteCommandData(0x000E,0x2B00);    wait_ms(1);   
    vLCDTFTWriteCommandData(0x001E,0x00B0);    wait_ms(1);   
    vLCDTFTWriteCommandData(0x0001,0x2B3F);    wait_ms(1);   
    vLCDTFTWriteCommandData(0x0002,0x0600);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0010,0x0000);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0011,0x6070);    wait_ms(1);        
    vLCDTFTWriteCommandData(0x0005,0x0000);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0006,0x0000);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0016,0xEF1C);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0017,0x0003);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0007,0x0233);    wait_ms(1);          
    vLCDTFTWriteCommandData(0x000B,0x0000);    wait_ms(1);
    vLCDTFTWriteCommandData(0x000F,0x0000);    wait_ms(1);        
    vLCDTFTWriteCommandData(0x0041,0x0000);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0042,0x0000);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0048,0x0000);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0049,0x013F);    wait_ms(1);
    vLCDTFTWriteCommandData(0x004A,0x0000);    wait_ms(1);
    vLCDTFTWriteCommandData(0x004B,0x0000);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0044,0xEF00);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0045,0x0000);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0046,0x013F);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0030,0x0707);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0031,0x0204);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0032,0x0204);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0033,0x0502);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0034,0x0507);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0035,0x0204);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0036,0x0204);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0037,0x0502);    wait_ms(1);
    vLCDTFTWriteCommandData(0x003A,0x0302);    wait_ms(1);
    vLCDTFTWriteCommandData(0x003B,0x0302);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0023,0x0000);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0024,0x0000);    wait_ms(1);
    vLCDTFTWriteCommandData(0x0025,0x8000);    wait_ms(1);
    vLCDTFTWriteCommandData(0x004f,0);        
    vLCDTFTWriteCommandData(0x004e,0);        
    vLCDTFTWriteCommand(0x0022);
    */
}

void LCDTFT::vLCDTFTFillScreen(unsigned short Color){
    unsigned short i,j;

     vLCDTFTWriteCommandData(0x0020,00); //set x=0
    vLCDTFTWriteCommandData(0x0021,00); // set y=0
    vLCDTFTWriteCommand(0x0022);       

    for(i=0;i<320;i++){
        for (j=0;j<240;j++){
            vLCDTFTWriteData(Color);
        }
    }      
}

void LCDTFT::vLCDTFTPoint(unsigned short x,unsigned short y,unsigned short Color){

    vLCDTFTAddressSetPoint(x,y);
    vLCDTFTWriteData(Color);
}
 
void LCDTFT::vLCDTFTText(unsigned short x,unsigned short y,const char *PtrText,const char (*Fuente)[5],unsigned char Alto,unsigned short Color,unsigned short BackColor){
   unsigned short i, j, k, l, m, temp,lmax;           
   char DataPunto[5]; 
   const char *Ptr;
   if(orient==0) lmax=LCD_X_MAX;
   else lmax=LCD_Y_MAX;
    
   while(*PtrText!='\0'){
      Ptr=(Fuente+*PtrText-' ')[0];
      for(i=0;i<5;i++){DataPunto[i]=*Ptr++;}
      switch(*PtrText){
         case '\n':
            y += 7*Alto + 1;
         break;
         case '\r':
            x = 0;
         break;
         default:
            if(x+5*Alto >= lmax){
                 x = 0;                           
                 y += 7*Alto + 1;                
              }
              for(j=0; j<5; ++j, x+=Alto){
                 for(k=0; k < 7; k++){
                    temp=(0x01<<k);
                    if((DataPunto[j]&temp)==temp){
                       for(l=0; l < Alto; ++l){                         
                          for(m=0; m < Alto; ++m){
                             vLCDTFTPoint(x+m,y+k*Alto+l,Color);
                          }//endform
                       }//endforl
                    }//endif
                    else{
                        for(l=0; l < Alto; ++l){                         
                          for(m=0; m < Alto; ++m){
                             vLCDTFTPoint(x+m,y+k*Alto+l,BackColor);
                          }//endform
                       }//endforl
                        }
                 }
              }
              x++;
          break;
      } 
      *PtrText++;     
   }
}

void LCDTFT::vLCDTFTLine(unsigned short x1,unsigned short y1,unsigned short x2,unsigned short y2,unsigned short Color){

   unsigned short dy, dx;
   short addx=1, addy=1;
   short P, diff;
   unsigned short i=0;

   diff=((short)x2-x1);
   if(diff<0) diff*=-1;
   dx=diff;
   diff=((short)y2-y1);
   if(diff<0) diff*=-1;
   dy=diff;


   if(x1 > x2)addx = -1;
   if(y1 > y2)addy = -1;
   if(dx >= dy){
      dy *= 2;
      P = dy - dx;
      diff = P - dx;
      for(;i<=dx;++i){
         vLCDTFTPoint(x1, y1, Color);
         if(P < 0){
            P  += dy;
            x1 += addx;
         }else{
            P  += diff;
            x1 += addx;
            y1 += addy;
         }
      }
   }else{
      dx *= 2;
      P = dx - dy;
      diff = P - dy;
      for(; i<=dy; ++i){
         vLCDTFTPoint(x1, y1, Color);
         if(P < 0){
            P  += dx;
            y1 += addy;
         }else{
            P  += diff;
            x1 += addx;
            y1 += addy;
         }
      }
   }
}


void LCDTFT::vLCDTFTRectangle(unsigned short x1,unsigned short y1,unsigned short x2,unsigned short y2,bool Filled,unsigned short Color){
   
    if(Filled){
        int Lenght=(int)(x2-x1);  
       
            
        for(int i=0;i<Lenght;i++){
            vLCDTFTLine(x1,y1+i,x2,y1+i,Color);                         
        }   
    }else{
        vLCDTFTLine(x1, y1, x2, y1, Color);     
        vLCDTFTLine(x1, y2, x2, y2, Color);
        vLCDTFTLine(x1, y1, x1, y2, Color);
        vLCDTFTLine(x2, y1, x2, y2, Color);
    }
}


void LCDTFT::vLCDTFTCircle(unsigned short x,unsigned short y,unsigned short Radius,bool Filled,unsigned short Color){
    short  a, b, P;

    a = 0;
    b = Radius;
    P = 1 - Radius;

    do{
        if(Filled){
            vLCDTFTLine(x-a, y+b, x+a, y+b, Color);
            vLCDTFTLine(x-a, y-b, x+a, y-b, Color);
            vLCDTFTLine(x-b, y+a, x+b, y+a, Color);
            vLCDTFTLine(x-b, y-a, x+b, y-a, Color);
        }else{
            vLCDTFTPoint(a+x, b+y, Color);
            vLCDTFTPoint(b+x, a+y, Color);
            vLCDTFTPoint(x-a, b+y, Color);
            vLCDTFTPoint(x-b, a+y, Color);
            vLCDTFTPoint(b+x, y-a, Color);
            vLCDTFTPoint(a+x, y-b, Color);
            vLCDTFTPoint(x-a, y-b, Color);
            vLCDTFTPoint(x-b, y-a, Color);
        }
        if(P < 0) P += 3 + 2 * a++;
        else P += 5 + 2 * (a++ - b--);
    }while(a <= b);
}
/*
void LCDTFT::vDrawImageBMP24Bits(const char *NameImagen){

    #define OffsetWidthPixel    18
    #define OffsetHeighPixel    22
    #define OffsetSizeFile      34
    #define OffsetInitData      10
    #define OffserTipeFile      28
    char Nombre[80],k;
    unsigned short PosXImagen,PosYImagen;
    unsigned char Temp,BufferHeader[54],BufferTemp[3],Adicional;
    unsigned int WidthPixel,HeighPixel;
    unsigned short TipeFile,InitData,Temp16bits;
    union{
        unsigned short Val;
        struct{
            unsigned Blue:5;
            unsigned Green:6;
            unsigned Red:5;
        };
    }Color; 

    LocalFileSystem local("mbedMemory");
    sprintf(&Nombre[0],"/mbedMemory/");
    k=12;
    while(*NameImagen!='\0'){
        Nombre[k++]=*NameImagen++;
    }
    
    FILE *Imagen = fopen((const char *)&Nombre[0], "r"); // Abrimos archivo para lectura.
    // Si no se pudo encontrar archivo:
    if(!Imagen) {
        vLCDTFTFillScreen(ColorBlack);
        return;
    }
    // Leemos cabecera de archivo
    fread(&BufferHeader[0],1,54,Imagen);
    
    WidthPixel = ((unsigned int)BufferHeader[OffsetWidthPixel + 3]*16777216+BufferHeader[OffsetWidthPixel + 2]*65536+BufferHeader[OffsetWidthPixel + 1]*256+BufferHeader[OffsetWidthPixel]);
    HeighPixel = ((unsigned int)BufferHeader[OffsetHeighPixel + 3]*16777216+BufferHeader[OffsetHeighPixel + 2]*65536+BufferHeader[OffsetHeighPixel + 1]*256+BufferHeader[OffsetHeighPixel]);
    InitData = ((unsigned short)BufferHeader[OffsetInitData]);
    TipeFile = ((unsigned short)BufferHeader[OffserTipeFile + 1]*256 + BufferHeader[OffserTipeFile]);
    
    if((WidthPixel>LCD_X_MAX) || (HeighPixel>LCD_Y_MAX) || (TipeFile!=24)){
        fclose(Imagen);
        return;
    }
    
    if(InitData!=54){
        for(int k=54;k<InitData;k++){
            fread(&Temp,1,1,Imagen);
        }
    }
    
    PosXImagen=(LCD_X_MAX/2)-(WidthPixel/2);
    PosYImagen=(LCD_Y_MAX/2)+(HeighPixel/2);
    
    Temp16bits=WidthPixel*3;
    Adicional=0;
    while(((Temp16bits)%4)!=0){
        Adicional++;
        Temp16bits++;
    }
    
    for(int k=0,y=PosYImagen;k<HeighPixel;k++,y--){
        vLCDTFTAddressSet(PosXImagen,y,PosXImagen+WidthPixel-1,y);
        for(int i=0;i<WidthPixel;i++){
            fread(&BufferTemp[0],1,3,Imagen); // Leemos 3 bytes (R,G,B)
            Color.Blue=BufferTemp[0]>>3;Color.Green=BufferTemp[1]>>2;Color.Red=BufferTemp[2]>>3; // Conversion de 24-bits a 16-bits.-
            vLCDTFTWriteData(Color.Val);
        }
        // Bytes adicionales para que linea sea multiplo de 4.-
        for(int p=0;p<Adicional;p++){
            fread(&Temp,1,1,Imagen);
        }
    }
    fclose(Imagen);
}
*/
void LCDTFT::vLCDTFTDrawImage(unsigned short x,unsigned short y, unsigned short Width, unsigned short Heigh, unsigned int Lenght, const unsigned short *Imagen){

    vLCDTFTAddressSet(x,y,x+Width-1,y+Heigh-1);      
    for(int i=0;i<Lenght;i++){
        vLCDTFTWriteData(*Imagen++);                         
    }
}