A modifiedversion of TFTLCD by Todor Todorov with ultra-fast operation for SSD1289 controller. TODO: speed-up fonts, add my own fonts Can work out-of-the-box with ST Nucleo F401RE

Dependents:   TFT_320QVT_Window_Drag_Demo TFT_320QVT_HelloWorld

Fork of TFTLCD by Todor Todorov

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lcd_base.cpp Source File

lcd_base.cpp

00001 /*
00002  * Copyright (C)2010-2012 Henning Karlsen. All right reserved.
00003  * Copyright (C)2012 Todor Todorov.
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to:
00017  *
00018  * Free Software Foundation, Inc.
00019  * 51 Franklin St, 5th Floor, Boston, MA 02110-1301, USA
00020  *
00021  *********************************************************************/
00022 #include "lcd_base.h"
00023 #include "helpers.h"
00024 
00025 LCD::LCD( unsigned short width, unsigned short height ,PinName CS, PinName RS, PinName RESET, PinName BL, backlight_t blType, float defaultBacklight )
00026     : _disp_width( width ), _disp_height( height ), _lcd_pin_cs( CS ), _lcd_pin_rs( RS ), _lcd_pin_reset( RESET ), _bl_type( blType )
00027 {
00028     SetForeground();
00029     SetBackground();
00030     _font = &TerminusFont;
00031     if ( defaultBacklight < 0 ) _bl_pwm_default = 0;
00032     else if ( defaultBacklight > 1.0 ) _bl_pwm_default = 1.0;
00033     else _bl_pwm_default = defaultBacklight;
00034     if ( BL != NC )
00035     {
00036         if ( blType == Constant )
00037         {
00038             _bl_pwm = 0;
00039             _lcd_pin_bl = new DigitalOut( BL );
00040         }
00041         else
00042         {
00043             _lcd_pin_bl = 0;
00044             _bl_pwm = new PwmOut( BL );
00045             _bl_pwm->period_ms( 8.33 ); // 120 Hz
00046             _bl_pwm_current = _bl_pwm_default;
00047             // initially off
00048             *_bl_pwm = 0;
00049         }
00050         
00051     }
00052     else
00053     {
00054         _lcd_pin_bl = 0;
00055         _bl_pwm = 0;
00056     }
00057 }
00058 
00059 void LCD::Sleep( void )
00060 {
00061     if ( _lcd_pin_bl != 0 )
00062         *_lcd_pin_bl = LOW;
00063     else if ( _bl_pwm != 0 )
00064         *_bl_pwm = 0;
00065 }
00066 
00067 void LCD::WakeUp( void )
00068 {
00069     if ( _lcd_pin_bl != 0 )
00070         *_lcd_pin_bl = HIGH;
00071     else if ( _bl_pwm != 0 )
00072         *_bl_pwm = _bl_pwm_current;
00073 }
00074 
00075 inline
00076 void LCD::SetForeground( unsigned int color )
00077 {
00078     _foreground = color;
00079 }
00080 
00081 inline
00082 void LCD::SetBackground( unsigned int color )
00083 {
00084     _background = color;
00085 }
00086 
00087 void LCD::SetFont( const font_t *font )
00088 {
00089     _font = font;
00090 }
00091 
00092 inline
00093 unsigned short LCD::GetWidth( void )
00094 {
00095     if ( _orientation == LANDSCAPE || _orientation == LANDSCAPE_REV ) return _disp_height;
00096     return _disp_width;
00097 }
00098 
00099 inline
00100 unsigned short LCD::GetHeight( void )
00101 {
00102     if ( _orientation == LANDSCAPE || _orientation == LANDSCAPE_REV ) return _disp_width;
00103     return _disp_height;
00104 }
00105 
00106 inline
00107 uint8_t LCD::GetFontWidth( void )
00108 {
00109     if ( _font != 0 ) return _font->Width;
00110     return 0;
00111 }
00112 
00113 inline
00114 uint8_t LCD::GetFontHeight( void )
00115 {
00116     if ( _font != 0 ) return _font->Height;
00117     return 0;
00118 }
00119 
00120 void LCD::SetBacklightLevel( float level )
00121 {
00122     switch ( _bl_type )
00123     {
00124         case Direct:
00125             if ( _bl_pwm != 0 )
00126             {
00127                 *_bl_pwm = level;
00128                 _bl_pwm_current = level;
00129             }
00130             break;
00131             
00132         case Indirect:
00133             break;
00134         case Constant:
00135         default:
00136             break;
00137     }
00138 }
00139 
00140 void LCD::FillScreen( int color )
00141 {
00142     unsigned int rgb = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
00143     Activate();
00144     ClearXY();
00145     for ( int i = 0; i < ( ( _disp_width ) * ( _disp_height ) ); i++ )
00146         SetPixelColor( rgb );
00147     Deactivate();
00148 }
00149 
00150 inline
00151 void LCD::ClearScreen( void )
00152 {
00153     FillScreen( -1 );
00154 }
00155 
00156 void LCD::DrawPixel( unsigned short x, unsigned short y, int color )
00157 {
00158     Activate();
00159     SetXY( x, y, x, y );
00160     SetPixelColor( color == -1 ? _background :
00161                     color == -2 ? _foreground : color );
00162     Deactivate();
00163 }
00164 
00165 void LCD::DrawLine( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
00166 {
00167     
00168     double delta, tx, ty;
00169 
00170     if ( ( ( x2 - x1 ) < 0 ) )
00171     {
00172         swap( ushort, x1, x2 )
00173         swap( ushort, y1, y2 )
00174     }
00175     if ( ( ( y2 - y1 ) < 0 ) )
00176     {
00177         swap( ushort, x1, x2 )
00178         swap( ushort, y1, y2 )
00179     }
00180 
00181     if ( y1 == y2 )
00182     {
00183         if ( x1 > x2 )
00184             swap( ushort, x1, x2 )
00185         DrawHLine( x1, y1, x2 - x1, color );
00186     }
00187     else if ( x1 == x2 )
00188     {
00189         if ( y1 > y2 )
00190             swap( ushort, y1, y2 )
00191         DrawVLine( x1, y1, y2 - y1, color );
00192     }
00193     else
00194     {
00195         unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
00196         Activate();
00197         if ( abs( x2 - x1 ) > abs( y2 - y1 ) )
00198         {
00199             delta = ( double( y2 - y1 ) / double( x2 - x1 ) );
00200             ty = double( y1 );
00201             if ( x1 > x2 )
00202             {
00203                 for ( int i = x1; i >= x2; i-- )
00204                 {
00205                     SetXY( i, int( ty + 0.5 ), i, int( ty + 0.5 ) );
00206                     SetPixelColor( usedColor );
00207                     ty = ty - delta;
00208                 }
00209             }
00210             else
00211             {
00212                 for ( int i = x1; i <= x2; i++ )
00213                 {
00214                     SetXY( i, int( ty + 0.5 ), i, int( ty + 0.5 ) );
00215                     SetPixelColor( usedColor );
00216                     ty = ty + delta;
00217                 }
00218             }
00219         }
00220         else
00221         {
00222             delta = ( float( x2 - x1 ) / float( y2 - y1 ) );
00223             tx = float( x1 );
00224             if ( y1 > y2 )
00225             {
00226                 for ( int i = y2 + 1; i > y1; i-- )
00227                 {
00228                     SetXY( int( tx + 0.5 ), i, int( tx + 0.5 ), i );
00229                     SetPixelColor( usedColor );
00230                     tx = tx + delta;
00231                 }
00232             }
00233             else
00234             {
00235                 for ( int i = y1; i < y2 + 1; i++ )
00236                 {
00237                     SetXY( int( tx + 0.5 ), i, int( tx + 0.5 ), i );
00238                     SetPixelColor( usedColor );
00239                     tx = tx + delta;
00240                 }
00241             }
00242         }
00243         Deactivate();
00244     }
00245 }
00246 
00247 void LCD::DrawRect( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
00248 {
00249     if ( x1 > x2 ) swap( ushort, x1, x2 )
00250     if ( y1 > y2 ) swap( ushort, y1, y2 )
00251 
00252     DrawHLine( x1, y1, x2 - x1, color );
00253     DrawHLine( x1, y2, x2 - x1, color );
00254     DrawVLine( x1, y1, y2 - y1, color );
00255     DrawVLine( x2, y1, y2 - y1, color );
00256 }
00257 
00258 void LCD::DrawRoundRect( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
00259 {
00260     if ( x1 > x2 ) swap( ushort, x1, x2 )
00261     if ( y1 > y2 ) swap( ushort, y1, y2 )
00262 
00263     if ( ( x2 - x1 ) > 4 && ( y2 - y1 ) > 4 )
00264     {
00265         DrawPixel( x1 + 1, y1 + 1, color );
00266         DrawPixel( x2 - 1, y1 + 1, color );
00267         DrawPixel( x1 + 1, y2 - 1, color );
00268         DrawPixel( x2 - 1, y2 - 1, color );
00269         DrawHLine( x1 + 2, y1, x2 - x1 - 4, color );
00270         DrawHLine( x1 + 2, y2, x2 - x1 - 4, color );
00271         DrawVLine( x1, y1 + 2, y2 - y1 - 4, color );
00272         DrawVLine( x2, y1 + 2, y2 - y1 - 4, color );
00273     }
00274 }
00275 
00276 void LCD::FillRect( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
00277 {
00278     if ( x1 > x2 ) swap( ushort, x1, x2 );
00279     if ( y1 > y2 ) swap( ushort, y1, y2 );
00280 
00281     for ( int i = 0; i < ( ( y2 - y1 ) / 2 ) + 1; i++ )
00282     {
00283         DrawHLine( x1, y1 + i, x2 - x1, color );
00284         DrawHLine( x1, y2 - i, x2 - x1, color );
00285     }
00286 }
00287 
00288 void LCD::FillRoundRect( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
00289 {
00290     if ( x1 > x2 ) swap( ushort, x1, x2 )
00291     if ( y1 > y2 ) swap( ushort, y1, y2 )
00292 
00293     if ( ( x2 - x1 ) > 4 && ( y2 - y1 ) > 4 )
00294     {
00295         for ( int i = 0; i < ( ( y2 - y1 ) / 2 ) + 1; i++ )
00296         {
00297             switch ( i )
00298             {
00299                 case 0:
00300                     DrawHLine( x1 + 2, y1 + i, x2 - x1 - 4, color );
00301                     DrawHLine( x1 + 2, y2 - i, x2 - x1 - 4, color );
00302                     break;
00303 
00304                 case 1:
00305                     DrawHLine( x1 + 1, y1 + i, x2 - x1 - 2, color );
00306                     DrawHLine( x1 + 1, y2 - i, x2 - x1 - 2, color );
00307                     break;
00308 
00309                 default:
00310                     DrawHLine( x1, y1 + i, x2 - x1, color );
00311                     DrawHLine( x1, y2 - i, x2 - x1, color );
00312                     break;
00313             }
00314         }
00315     }
00316 }
00317 
00318 void LCD::DrawCircle( unsigned short x, unsigned short y, unsigned short radius, int color )
00319 {
00320     int f = 1 - radius;
00321     int ddF_x = 1;
00322     int ddF_y = -2 * radius;
00323     int x1 = 0;
00324     int y1 = radius;
00325     unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
00326 
00327     Activate();
00328     SetXY( x, y + radius, x, y + radius );
00329     SetPixelColor( usedColor );
00330     SetXY( x, y - radius, x, y - radius );
00331     SetPixelColor( usedColor );
00332     SetXY( x + radius, y, x + radius, y );
00333     SetPixelColor( usedColor );
00334     SetXY( x - radius, y, x - radius, y );
00335     SetPixelColor( usedColor );
00336 
00337     while ( x1 < y1 )
00338     {
00339         if ( f >= 0 )
00340         {
00341             y1--;
00342             ddF_y += 2;
00343             f += ddF_y;
00344         }
00345         x1++;
00346         ddF_x += 2;
00347         f += ddF_x;
00348         SetXY( x + x1, y + y1, x + x1, y + y1 );
00349         SetPixelColor( usedColor );
00350         SetXY( x - x1, y + y1, x - x1, y + y1 );
00351         SetPixelColor( usedColor );
00352         SetXY( x + x1, y - y1, x + x1, y - y1 );
00353         SetPixelColor( usedColor );
00354         SetXY( x - x1, y - y1, x - x1, y - y1 );
00355         SetPixelColor( usedColor );
00356         SetXY( x + y1, y + x1, x + y1, y + x1 );
00357         SetPixelColor( usedColor );
00358         SetXY( x - y1, y + x1, x - y1, y + x1 );
00359         SetPixelColor( usedColor );
00360         SetXY( x + y1, y - x1, x + y1, y - x1 );
00361         SetPixelColor( usedColor );
00362         SetXY( x - y1, y - x1, x - y1, y - x1 );
00363         SetPixelColor( usedColor );
00364     }
00365     Deactivate();
00366 }
00367 
00368 void LCD::FillCircle( unsigned short x, unsigned short y, unsigned short radius, int color )
00369 {
00370     unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
00371     Activate();
00372     for ( int y1 = -radius; y1 <= radius; y1++ )
00373         for ( int x1 = -radius; x1 <= radius; x1++ )
00374             if ( x1 * x1 + y1 * y1 <= radius * radius )
00375             {
00376                 SetXY( x + x1, y + y1, x + x1, y + y1 );
00377                 SetPixelColor( usedColor );
00378             }
00379     Deactivate();
00380 }
00381 
00382 void LCD::Print( const char *str, unsigned short x, unsigned short y, int fgColor, int bgColor, unsigned short deg )
00383 {
00384     int stl, i;
00385 
00386     stl = strlen( str );
00387 
00388     if ( x == RIGHT )
00389         x = GetWidth() - ( stl * _font->Width );
00390     if ( x == CENTER )
00391         x = ( GetWidth() - ( stl * _font->Width ) ) / 2;
00392 
00393     for ( i = 0; i < stl; i++ )
00394         if ( deg == 0 )
00395             PrintChar( *str++, x + ( i * ( _font->Width ) ), y, fgColor, bgColor );
00396         else
00397             RotateChar( *str++, x, y, i, fgColor, bgColor, deg );
00398 }
00399 
00400 void LCD::DrawBitmap( unsigned short x, unsigned short y, const bitmap_t* img, unsigned char scale )
00401 {
00402     int tx, ty, tc, tsx, tsy;
00403 
00404     Activate();
00405     if ( scale == 1 )
00406     {
00407         SetXY( x, y, x + img->Width - 1, y + img->Height - 1 );
00408 
00409         if ( img->Format == RGB16 )
00410         {
00411             const unsigned short *pixel = ( const unsigned short* ) img->PixelData;
00412             for ( tc = 0; tc < ( img->Width * img->Height ); tc++ )
00413                 SetPixelColor( *pixel++, img->Format );
00414         }
00415         else if ( img->Format == RGB18 )
00416         {
00417             const unsigned int *pixel = ( const unsigned int* ) img->PixelData;
00418             for ( tc = 0; tc < ( img->Width * img->Height ); tc++ )
00419                 SetPixelColor( *pixel++, img->Format );
00420         }
00421     }
00422     else
00423     {
00424         if ( img->Format == RGB16 )
00425         {
00426             const unsigned short *pixel = ( const unsigned short* ) img->PixelData;
00427             
00428             for ( ty = 0; ty < img->Height; ty++ )
00429             {
00430                 SetXY( x, y + ( ty * scale ), x + ( ( img->Width * scale ) - 1 ), y + ( ty * scale ) + scale );
00431                 for ( tsy = 0; tsy < scale; tsy++ )
00432                 {
00433                     for ( tx = 0; tx < img->Width; tx++ )
00434                     {
00435                         for ( tsx = 0; tsx < scale; tsx++ )
00436                             SetPixelColor( pixel[ ( ty * img->Width ) + tx ], img->Format );
00437                     }
00438                 }
00439             }
00440         }
00441         else if ( img->Format == RGB18 )
00442         {
00443             const unsigned int *pixel = ( const unsigned int* ) img->PixelData;
00444             
00445             for ( ty = 0; ty < img->Height; ty++ )
00446             {
00447                 SetXY( x, y + ( ty * scale ), x + ( ( img->Width * scale ) - 1 ), y + ( ty * scale ) + scale );
00448                 for ( tsy = 0; tsy < scale; tsy++ )
00449                 {
00450                     for ( tx = 0; tx < img->Width; tx++ )
00451                     {
00452                         for ( tsx = 0; tsx < scale; tsx++ )
00453                             SetPixelColor( pixel[ ( ty * img->Width ) + tx ], img->Format );
00454                     }
00455                 }
00456             }
00457         }
00458     }
00459     Deactivate();
00460 }
00461 
00462 void LCD::DrawBitmap( unsigned short x, unsigned short y, const bitmap_t* img, unsigned short deg, unsigned short rox, unsigned short roy )
00463 {
00464     int tx, ty, newx, newy;
00465     double radian;
00466     radian = deg * 0.0175;
00467 
00468     if ( deg == 0 )
00469         DrawBitmap( x, y, img );
00470     else
00471     {
00472         Activate();
00473         
00474         if ( img->Format == RGB16 )
00475         {
00476             const unsigned short *pixel = ( const unsigned short* ) img->PixelData;
00477             
00478             for ( ty = 0; ty < img->Height; ty++ )
00479                 for ( tx = 0; tx < img->Width; tx++ )
00480                 {
00481                     newx = x + rox + ( ( ( tx - rox ) * cos( radian ) ) - ( ( ty - roy ) * sin( radian ) ) );
00482                     newy = y + roy + ( ( ( ty - roy ) * cos( radian ) ) + ( ( tx - rox ) * sin( radian ) ) );
00483     
00484                     SetXY( newx, newy, newx, newy );
00485                     SetPixelColor( pixel[ ( ty * img->Width ) + tx ], img->Format );
00486                 }
00487         }
00488         else if ( img->Format == RGB18 )
00489         {
00490             const unsigned int *pixel = ( const unsigned int* ) img->PixelData;
00491             
00492             for ( ty = 0; ty < img->Height; ty++ )
00493                 for ( tx = 0; tx < img->Width; tx++ )
00494                 {
00495                     newx = x + rox + ( ( ( tx - rox ) * cos( radian ) ) - ( ( ty - roy ) * sin( radian ) ) );
00496                     newy = y + roy + ( ( ( ty - roy ) * cos( radian ) ) + ( ( tx - rox ) * sin( radian ) ) );
00497     
00498                     SetXY( newx, newy, newx, newy );
00499                     SetPixelColor( pixel[ ( ty * img->Width ) + tx ], img->Format );
00500                 }
00501         }
00502         Deactivate();
00503     }
00504 }
00505 
00506 inline
00507 void LCD::Activate( void )
00508 {
00509     _lcd_pin_cs = LOW;
00510 }
00511 
00512 inline
00513 void LCD::Deactivate( void )
00514 {
00515     _lcd_pin_cs = HIGH;
00516 }
00517 
00518 inline
00519 void LCD::WriteCmdData( unsigned short cmd, unsigned short data )
00520 {
00521     WriteCmd( cmd );
00522     WriteData( data );
00523 }
00524 
00525 inline
00526 void LCD::ClearXY( void )
00527 {
00528     SetXY( 0, 0, GetWidth() - 1, GetHeight() - 1 );
00529 }
00530 
00531 void LCD::DrawHLine( unsigned short x, unsigned short y, unsigned short len, int color )
00532 {
00533     unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
00534     
00535     Activate();
00536     SetXY( x, y, x + len, y );
00537     for ( int i = 0; i < len + 1; i++ )
00538         SetPixelColor( usedColor );
00539     Deactivate();
00540 }
00541 
00542 void LCD::DrawVLine( unsigned short x, unsigned short y, unsigned short len, int color )
00543 {
00544     unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
00545     
00546     Activate();
00547     SetXY( x, y, x, y + len );
00548     for ( int i = 0; i < len; i++ )
00549         SetPixelColor( usedColor );
00550     Deactivate();
00551 }
00552 
00553 void LCD::PrintChar( char c, unsigned short x, unsigned short y, int fgColor, int bgColor )
00554 {
00555     uint8_t i, ch;
00556     uint16_t j;
00557     unsigned int usedColorFG = fgColor == -1 ? _background : fgColor == -2 ? _foreground : ( unsigned int ) fgColor;
00558     unsigned int usedColorBG = bgColor == -1 ? _background : bgColor == -2 ? _foreground : ( unsigned int ) bgColor;
00559     
00560     uint16_t totalCharBytes = ( _font->Width * _font->Height ) / 8;
00561     int16_t position = _font->Position[ c - _font->Offset ];
00562     if ( position == -1 ) position = 0; // will print space character
00563     
00564     Activate();
00565 
00566     SetXY( x, y, x + _font->Width - 1, y + _font->Height - 1 );
00567     
00568     for ( j = 0; j < totalCharBytes; j++ )
00569     {
00570         ch = _font->Data[ position ];
00571         for ( i = 0; i < 8; i++ )
00572         {
00573             if ( ( ch & ( 1 << ( 7 - i ) ) ) != 0 ) SetPixelColor( usedColorFG );
00574             else SetPixelColor( usedColorBG );
00575         }
00576         position++;
00577     }
00578     Deactivate();
00579 }
00580 
00581 void LCD::RotateChar( char c, unsigned short x, unsigned short y, int pos, int fgColor, int bgColor, unsigned short deg )
00582 {
00583     uint8_t i, j, ch;
00584     int newx, newy;
00585     double radian;
00586     radian = deg * 0.0175;
00587     
00588     unsigned int usedColorFG = fgColor == -1 ? _background : fgColor == -2 ? _foreground : ( unsigned int ) fgColor;
00589     unsigned int usedColorBG = bgColor == -1 ? _background : bgColor == -2 ? _foreground : ( unsigned int ) bgColor;
00590 
00591     int16_t position = _font->Position[ c - _font->Offset ];
00592     if ( position == -1 ) position = 0; // will print space character
00593     
00594     Activate();
00595     
00596     for ( j = 0; j < _font->Height; j++ )
00597     {
00598         for ( uint16_t zz = 0; zz < ( ( double ) _font->Width / 8 ); zz++ )
00599         {
00600             ch = _font->Data[ position + zz ];
00601             for ( i = 0; i < 8; i++ )
00602             {
00603                 newx = x + ( ( ( i + ( zz * 8 ) + ( pos * _font->Width ) ) * cos( radian ) ) - ( ( j ) * sin( radian ) ) );
00604                 newy = y + ( ( ( j ) * cos( radian ) ) + ( ( i + ( zz * 8 ) + ( pos * _font->Width ) ) * sin( radian ) ) );
00605 
00606                 SetXY( newx, newy, newx + 1, newy + 1 );
00607 
00608                 if ( ( ch & ( 1 << ( 7 - i ) ) ) != 0 ) SetPixelColor( usedColorFG );
00609                 else SetPixelColor( usedColorBG );
00610             }
00611         }
00612         position += ( _font->Width / 8 );
00613     }
00614 
00615     Deactivate();
00616 }