Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Nucleo_LCD_mcufriend_test
Fork of 24_TFT_STMNUCLEO by
lcd_base.cpp
- Committer:
- ttodorov
- Date:
- 2012-12-06
- Revision:
- 8:7a4791dbb065
- Parent:
- 7:5c418fc1879f
- Child:
- 9:58b328831d0a
File content as of revision 8:7a4791dbb065:
/*
* Copyright (C)2010-2012 Henning Karlsen. All right reserved.
* Copyright (C)2012 Todor Todorov.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to:
*
* Free Software Foundation, Inc.
* 51 Franklin St, 5th Floor, Boston, MA 02110-1301, USA
*
*********************************************************************/
#include "lcd_base.h"
#include "helpers.h"
LCD::LCD( unsigned short width, unsigned short height ,PinName CS, PinName RS, PinName RESET )
: _disp_width( width ), _disp_height( height ), _lcd_pin_cs( CS ), _lcd_pin_rs( RS ), _lcd_pin_reset( RESET )
{
SetForeground();
SetBackground();
_font.font = 0;
}
inline
void LCD::SetForeground( unsigned int color )
{
_foreground = color;
}
inline
void LCD::SetBackground( unsigned int color )
{
_background = color;
}
void LCD::SetFont( const char *font )
{
_font.font = font;
_font.width = font[ 0 ];
_font.height = font[ 1 ];
_font.offset = font[ 2 ];
_font.numchars = font[ 3 ];
}
inline
unsigned short LCD::GetWidth( void )
{
if ( _orientation == LANDSCAPE ) return _disp_height;
return _disp_width;
}
inline
unsigned short LCD::GetHeight( void )
{
if ( _orientation == LANDSCAPE ) return _disp_width;
return _disp_height;
}
void LCD::FillScreen( int color )
{
unsigned int rgb = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
Activate();
ClearXY();
for ( int i = 0; i < ( ( _disp_width ) * ( _disp_height ) ); i++ )
WriteData( rgb );
Deactivate();
}
inline
void LCD::ClearScreen( void )
{
FillScreen( -1 );
}
void LCD::DrawPixel( unsigned short x, unsigned short y, int color )
{
Activate();
SetXY( x, y, x, y );
WriteData( color == -1 ? _background :
color == -2 ? _foreground : color );
Deactivate();
}
void LCD::DrawLine( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
{
double delta, tx, ty;
if ( ( ( x2 - x1 ) < 0 ) )
{
swap( ushort, x1, x2 )
swap( ushort, y1, y2 )
}
if ( ( ( y2 - y1 ) < 0 ) )
{
swap( ushort, x1, x2 )
swap( ushort, y1, y2 )
}
if ( y1 == y2 )
{
if ( x1 > x2 )
swap( ushort, x1, x2 )
DrawHLine( x1, y1, x2 - x1, color );
}
else if ( x1 == x2 )
{
if ( y1 > y2 )
swap( ushort, y1, y2 )
DrawVLine( x1, y1, y2 - y1, color );
}
else
{
unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
Activate();
if ( abs( x2 - x1 ) > abs( y2 - y1 ) )
{
delta = ( double( y2 - y1 ) / double( x2 - x1 ) );
ty = double( y1 );
if ( x1 > x2 )
{
for ( int i = x1; i >= x2; i-- )
{
SetXY( i, int( ty + 0.5 ), i, int( ty + 0.5 ) );
WriteData( usedColor );
ty = ty - delta;
}
}
else
{
for ( int i = x1; i <= x2; i++ )
{
SetXY( i, int( ty + 0.5 ), i, int( ty + 0.5 ) );
WriteData( usedColor );
ty = ty + delta;
}
}
}
else
{
delta = ( float( x2 - x1 ) / float( y2 - y1 ) );
tx = float( x1 );
if ( y1 > y2 )
{
for ( int i = y2 + 1; i > y1; i-- )
{
SetXY( int( tx + 0.5 ), i, int( tx + 0.5 ), i );
WriteData( usedColor );
tx = tx + delta;
}
}
else
{
for ( int i = y1; i < y2 + 1; i++ )
{
SetXY( int( tx + 0.5 ), i, int( tx + 0.5 ), i );
WriteData( usedColor );
tx = tx + delta;
}
}
}
Deactivate();
}
}
void LCD::DrawRect( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
{
if ( x1 > x2 ) swap( ushort, x1, x2 )
if ( y1 > y2 ) swap( ushort, y1, y2 )
DrawHLine( x1, y1, x2 - x1, color );
DrawHLine( x1, y2, x2 - x1, color );
DrawVLine( x1, y1, y2 - y1, color );
DrawVLine( x2, y1, y2 - y1, color );
}
void LCD::DrawRoundRect( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
{
if ( x1 > x2 ) swap( ushort, x1, x2 )
if ( y1 > y2 ) swap( ushort, y1, y2 )
if ( ( x2 - x1 ) > 4 && ( y2 - y1 ) > 4 )
{
DrawPixel( x1 + 1, y1 + 1, color );
DrawPixel( x2 - 1, y1 + 1, color );
DrawPixel( x1 + 1, y2 - 1, color );
DrawPixel( x2 - 1, y2 - 1, color );
DrawHLine( x1 + 2, y1, x2 - x1 - 4, color );
DrawHLine( x1 + 2, y2, x2 - x1 - 4, color );
DrawVLine( x1, y1 + 2, y2 - y1 - 4, color );
DrawVLine( x2, y1 + 2, y2 - y1 - 4, color );
}
}
void LCD::FillRect( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
{
if ( x1 > x2 ) swap( ushort, x1, x2 );
if ( y1 > y2 ) swap( ushort, y1, y2 );
if ( _orientation == PORTRAIT )
{
for ( int i = 0; i < ( ( y2 - y1 ) / 2 ) + 1; i++ )
{
DrawHLine( x1, y1 + i, x2 - x1, color );
DrawHLine( x1, y2 - i, x2 - x1, color );
}
}
else
{
for ( int i = 0; i < ( ( x2 - x1 ) / 2 ) + 1; i++ )
{
DrawVLine( x1 + i, y1, y2 - y1, color );
DrawVLine( x2 - i, y1, y2 - y1, color );
}
}
}
void LCD::FillRoundRect( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
{
if ( x1 > x2 ) swap( ushort, x1, x2 )
if ( y1 > y2 ) swap( ushort, y1, y2 )
if ( ( x2 - x1 ) > 4 && ( y2 - y1 ) > 4 )
{
for ( int i = 0; i < ( ( y2 - y1 ) / 2 ) + 1; i++ )
{
switch ( i )
{
case 0:
DrawHLine( x1 + 2, y1 + i, x2 - x1 - 4, color );
DrawHLine( x1 + 2, y2 - i, x2 - x1 - 4, color );
break;
case 1:
DrawHLine( x1 + 1, y1 + i, x2 - x1 - 2, color );
DrawHLine( x1 + 1, y2 - i, x2 - x1 - 2, color );
break;
default:
DrawHLine( x1, y1 + i, x2 - x1, color );
DrawHLine( x1, y2 - i, x2 - x1, color );
break;
}
}
}
}
void LCD::DrawCircle( unsigned short x, unsigned short y, unsigned short radius, int color )
{
int f = 1 - radius;
int ddF_x = 1;
int ddF_y = -2 * radius;
int x1 = 0;
int y1 = radius;
unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
Activate();
SetXY( x, y + radius, x, y + radius );
WriteData( usedColor );
SetXY( x, y - radius, x, y - radius );
WriteData( usedColor );
SetXY( x + radius, y, x + radius, y );
WriteData( usedColor );
SetXY( x - radius, y, x - radius, y );
WriteData( usedColor );
while ( x1 < y1 )
{
if ( f >= 0 )
{
y1--;
ddF_y += 2;
f += ddF_y;
}
x1++;
ddF_x += 2;
f += ddF_x;
SetXY( x + x1, y + y1, x + x1, y + y1 );
WriteData( usedColor );
SetXY( x - x1, y + y1, x - x1, y + y1 );
WriteData( usedColor );
SetXY( x + x1, y - y1, x + x1, y - y1 );
WriteData( usedColor );
SetXY( x - x1, y - y1, x - x1, y - y1 );
WriteData( usedColor );
SetXY( x + y1, y + x1, x + y1, y + x1 );
WriteData( usedColor );
SetXY( x - y1, y + x1, x - y1, y + x1 );
WriteData( usedColor );
SetXY( x + y1, y - x1, x + y1, y - x1 );
WriteData( usedColor );
SetXY( x - y1, y - x1, x - y1, y - x1 );
WriteData( usedColor );
}
Deactivate();
}
void LCD::FillCircle( unsigned short x, unsigned short y, unsigned short radius, int color )
{
unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
Activate();
for ( int y1 = -radius; y1 <= radius; y1++ )
for ( int x1 = -radius; x1 <= radius; x1++ )
if ( x1 * x1 + y1 * y1 <= radius * radius )
{
SetXY( x + x1, y + y1, x + x1, y + y1 );
WriteData( usedColor );
}
Deactivate();
}
void LCD::Print( const char *str, unsigned short x, unsigned short y, int fgColor, int bgColor, unsigned short deg )
{
int stl, i;
stl = strlen( str );
if ( _orientation == PORTRAIT )
{
if ( x == RIGHT )
x = _disp_width - ( stl * _font.width );
if ( x == CENTER )
x = ( _disp_width - ( stl * _font.width ) ) / 2;
}
else
{
if ( x == RIGHT )
x = _disp_height - ( stl * _font.width );
if ( x == CENTER )
x = ( _disp_height - ( stl * _font.width ) ) / 2;
}
for ( i = 0; i < stl; i++ )
if ( deg == 0 )
PrintChar( *str++, x + ( i * ( _font.width ) ), y, fgColor, bgColor );
else
RotateChar( *str++, x, y, i, fgColor, bgColor, deg );
}
void LCD::DrawBitmap( unsigned short x, unsigned short y, unsigned short sx, unsigned short sy, const unsigned short* imgPixelData, unsigned char scale )
{
int tx, ty, tc, tsx, tsy;
Activate();
if ( scale == 1 )
{
if ( _orientation == PORTRAIT )
{
SetXY( x, y, x + sx - 1, y + sy - 1 );
for ( tc = 0; tc < ( sx * sy ); tc++ )
WriteData( imgPixelData[ tc ] );
}
else
{
for ( ty = 0; ty < sy; ty++ )
{
SetXY( x, y + ty, x + sx - 1, y + ty );
for ( tx = sx; tx >= 0; tx-- )
WriteData( imgPixelData[ ( ty * sx ) + tx ] );
}
}
}
else
{
if ( _orientation == PORTRAIT )
{
for ( ty = 0; ty < sy; ty++ )
{
SetXY( x, y + ( ty * scale ), x + ( ( sx * scale ) - 1 ), y + ( ty * scale ) + scale );
for ( tsy = 0; tsy < scale; tsy++ )
for ( tx = 0; tx < sx; tx++ )
for ( tsx = 0; tsx < scale; tsx++ )
WriteData( imgPixelData[ ( ty * sx ) + tx ] );
}
}
else
{
for ( ty = 0; ty < sy; ty++ )
{
for ( tsy = 0; tsy < scale; tsy++ )
{
SetXY( x, y + ( ty * scale ) + tsy, x + ( ( sx * scale ) - 1 ), y + ( ty * scale ) + tsy );
for ( tx = sx; tx >= 0; tx-- )
for ( tsx = 0; tsx < scale; tsx++ )
WriteData( imgPixelData[ ( ty * sx ) + tx ] );
}
}
}
}
Deactivate();
}
void LCD::DrawBitmap( unsigned short x, unsigned short y, unsigned short sx, unsigned short sy, const unsigned short* imgPixelData, unsigned short deg, unsigned short rox, unsigned short roy )
{
int tx, ty, newx, newy;
double radian;
radian = deg * 0.0175;
if ( deg == 0 )
DrawBitmap( x, y, sx, sy, imgPixelData );
else
{
Activate();
for ( ty = 0; ty < sy; ty++ )
for ( tx = 0; tx < sx; tx++ )
{
newx = x + rox + ( ( ( tx - rox ) * cos( radian ) ) - ( ( ty - roy ) * sin( radian ) ) );
newy = y + roy + ( ( ( ty - roy ) * cos( radian ) ) + ( ( tx - rox ) * sin( radian ) ) );
SetXY( newx, newy, newx, newy );
WriteData( imgPixelData[ ( ty * sx ) + tx ] );
}
Deactivate();
}
}
inline
void LCD::Activate( void )
{
_lcd_pin_cs = LOW;
}
inline
void LCD::Deactivate( void )
{
_lcd_pin_cs = HIGH;
}
/*
void LCD::WriteCmd( unsigned short cmd )
{
_lcd_pin_rs = LOW;
_lcd_port->write( cmd );
pulseLow( _lcd_pin_wr );
}
*/
/*
void LCD::WriteData( unsigned short data )
{
_lcd_pin_rs = HIGH;
_lcd_port->write( data );
pulseLow( _lcd_pin_wr );
}
*/
inline
void LCD::WriteCmdData( unsigned short cmd, unsigned short data )
{
WriteCmd( cmd );
WriteData( data );
}
/*
void LCD::SetXY( uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2 )
{
if ( _orientation == LANDSCAPE )
{
swap( uint16_t, x1, y1 )
swap( uint16_t, x2, y2 )
y1 = _disp_height - y1;
y2 = _disp_height - y2;
swap( uint16_t, y1, y2 )
}
WriteCmdData( 0x44, ( x2 << 8 ) + x1 );
WriteCmdData( 0x45, y1 );
WriteCmdData( 0x46, y2 );
WriteCmdData( 0x4e, x1 );
WriteCmdData( 0x4f, y1 );
WriteCmd( 0x22 );
}
*/
void LCD::ClearXY()
{
if ( _orientation == PORTRAIT )
SetXY( 0, 0, _disp_width - 1, _disp_height - 1 );
else
SetXY( 0, 0, _disp_height - 1, _disp_width - 1 );
}
void LCD::DrawHLine( unsigned short x, unsigned short y, unsigned short len, int color )
{
unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
Activate();
SetXY( x, y, x + len, y );
for ( int i = 0; i < len + 1; i++ )
WriteData( usedColor );
Deactivate();
}
void LCD::DrawVLine( unsigned short x, unsigned short y, unsigned short len, int color )
{
unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
Activate();
SetXY( x, y, x, y + len );
for ( int i = 0; i < len; i++ )
WriteData( usedColor );
Deactivate();
}
void LCD::PrintChar( char c, unsigned short x, unsigned short y, int fgColor, int bgColor )
{
uint8_t i, ch;
uint16_t j;
uint16_t temp;
unsigned int usedColorFG = fgColor == -1 ? _background : fgColor == -2 ? _foreground : ( unsigned int ) fgColor;
unsigned int usedColorBG = bgColor == -1 ? _background : bgColor == -2 ? _foreground : ( unsigned int ) bgColor;
Activate();
if ( _orientation == PORTRAIT )
{
SetXY( x, y, x + _font.width - 1, y + _font.height - 1 );
temp = ( ( c - _font.offset ) * ( ( _font.width / 8 ) * _font.height ) ) + 4;
for ( j = 0; j < ( ( _font.width / 8 ) * _font.height ); j++ )
{
ch = _font.font[ temp ];
for ( i = 0; i < 8; i++ )
{
if ( ( ch & ( 1 << ( 7 - i ) ) ) != 0 )
WriteData( usedColorFG );
else
WriteData( usedColorBG );
}
temp++;
}
}
else
{
temp = ( ( c - _font.offset ) * ( ( _font.width / 8 ) * _font.height ) ) + 4;
for ( j = 0; j < ( ( _font.width / 8 ) * _font.height ); j += ( _font.width / 8 ) )
{
SetXY( x, y + ( j / ( _font.width / 8 ) ), x + _font.width - 1, y + ( j / ( _font.width / 8 ) ) );
for ( int zz = ( _font.width / 8 ) - 1; zz >= 0; zz-- )
{
ch = _font.font[ temp + zz ];
for ( i = 0; i < 8; i++ )
{
if ( ( ch & ( 1 << i ) ) != 0 )
WriteData( usedColorFG );
else
WriteData( usedColorBG );
}
}
temp += ( _font.width / 8 );
}
}
Deactivate();
}
void LCD::RotateChar( char c, unsigned short x, unsigned short y, int pos, int fgColor, int bgColor, unsigned short deg )
{
uint8_t i, j, ch;
uint16_t temp;
int newx, newy;
double radian;
radian = deg * 0.0175;
unsigned int usedColorFG = fgColor == -1 ? _background : fgColor == -2 ? _foreground : ( unsigned int ) fgColor;
unsigned int usedColorBG = bgColor == -1 ? _background : bgColor == -2 ? _foreground : ( unsigned int ) bgColor;
Activate();
temp = ( ( c - _font.offset ) * ( ( _font.width / 8 ) * _font.height ) ) + 4;
for ( j = 0; j < _font.height; j++ )
{
for ( int zz = 0; zz < ( _font.width / 8 ); zz++ )
{
ch = _font.font[ temp + zz ];
for ( i = 0; i < 8; i++ )
{
newx = x + ( ( ( i + ( zz * 8 ) + ( pos * _font.width ) ) * cos( radian ) ) - ( ( j ) * sin( radian ) ) );
newy = y + ( ( ( j ) * cos( radian ) ) + ( ( i + ( zz * 8 ) + ( pos * _font.width ) ) * sin( radian ) ) );
SetXY( newx, newy, newx + 1, newy + 1 );
if ( ( ch & ( 1 << ( 7 - i ) ) ) != 0 )
WriteData( usedColorFG );
else
WriteData( usedColorBG );
}
}
temp += ( _font.width / 8 );
}
Deactivate();
}
