This is a port of Henning Kralsen's UTFT library for Arduino/chipKIT to mbed, refactored to make full use of C++ inheritance and access control, in order to reduce work when implementing new drivers and at the same time make the code more readable and easier to maintain. As of now supported are SSD1289 (16-bit interface), HX8340-B (serial interface) and ST7735 (serial interface). Drivers for other controllers will be added as time and resources to acquire the displays to test the code permit.

Dependents:   test SDCard capstone_display capstone_display_2 ... more

TFTLCD Library

NOTE (2013-03-25) Tested with both mbed LPC1768 and Freedom KL25Z. -todor

A TFT LCD driver library, which at the moment provides support for the following display controllers: HX8340-B (serial interface), SSD1289 (16-bit interface), ST7735-R (serial interface), ILI9325/ILI9328 (16-bit interface).

As I am acquiring and testing out new displays, I decided to combine all ported drivers into one library as with the original work done by Henning. However I also had as a goal to make the code maintenance and readability easier/better, so the code has been heavily refactored to make full use of C++ facilities as inheritance and access control. I extracted the common pieces of code into a base class, which every driver inherits and only the controller-specific side is provided in the actual driver - things like initialization, addressing, data transfer, etc.

Another nice extension is that the display's backlight can now be controlled through the driver. Either a simple on/off method of control could be selected, or the brightness can be set through use of PWM (the latter placing some restrictions on which pins can be used for this, as mbed offers hardware PWM on only 6 pins).

I also plan to add support for touch screens as part of the library. The goal is to grow this piece of software into a lightweight graphics widgets library, which can be used to construct control screens with buttons or menus in a speedy and intuitive way.

Changes

2013-07-21

  • Fixed the sleep/wake-up functions of the ILI9328 driver.

2013-06-15

  • Added driver for ILI9328 (works with ILI9325) controller, 16-bit data bus. Screen rotation works as usual with the TFTLCD library, but for now only RGB565 color depth is working and you can use both 65K and 262K color space with this driver. But for some reason the sleep function is not behaving as expected; I am working on this.
  • This is only on my to-do list for now - haven't really had the time yet - but I am going to refactor the library a bit to allow use of GPIO ports for data transfers instead of DigitalOut: faster and cleaner that way. For those who are using it already in a working design and cannot repurpose the pins anymore, the current way it's working will still be available; I am hoping not to tear up the public interfaces of the library (... too much). Anyway, since I am at it, I will also try to add support for multiple bus interfaces to drivers that support it (i.e. both 8bit and 16bit use of ILI932x or SSD1289). Thought this might be a good place to give you guys the heads-up.

2013-01-25

  • Replaced all existing fonts from the UTFT library with the free Terminus font. Two different sizes are provided: 8x12 pixels and 16x28 pixels. I found the old fonts not so good looking and then they supported only the ASCII codes in the range 30 (space) to 126 (the tilde ). The 7segment font didn't even implement anything else than the numbers from 0 to 9 - so it was unusable for anything (one couldn't even display the time or date as it lacked the colon [:] or the period [.] or the slash [/] or the space [ ] characters). So I completely revamped the fonts and added Terminus as the new default with its 2 sizes. Further more I added in both sizes most of the characters up to ASCII code 255. For any code not in there, the space character is substituted. In the case, when you already have provided your own fonts, please have a look at the API changes in the files <terminus.h> and <terminus.cpp>: I promise you whatever time you spent designing your own font, it is not wasted; you merely need to add a second array, which describes which ASCII codes are available in your font, and their byte offset in the original character bitmap array; and a struct to tie all parts together and describe the character size. I am sorry for breaking the old API, but you will like the change and new options it brings you. Now you can insert any char above 127 up to code 255 (if available, of course) with its hex representation, e.g displaying the current temperature would look something like 85\xB0 F or 26\xB0 C (the space in between degree and F or C is needed because both F and C are used in hex numbers, so \xB0F is interpreted as ASCII code 2831 instead of ASCII code 176, followed by the temperature scale denomination; if you insist on avoiding the space, you could write 85\xB0\x46 which will be displayed correctly as 85°F). You can either look up the ASCII code you need on Google or Bing, or just look at what's available - how it looks and its hex value - in the comments in <terminus.cpp>.
  • Added PWM backlight control. If you intend to use this, please make sure that control pin is either one of p21, p22, p23, p24, p25, or p26, as only they support hardware PWM. Please be aware that the mbed pins do not have much juice behind them, so if your display's backlight requires a lot of current, you are better off interfacing through as small signal transistor or a MOSFET. For the rest please consult the updated Doxygen documentation. NOTE The addition of PWM-controlled backlight will not break your existing code, the new options have default values, which initialize the used driver to behave as prior to PWM. Only if you want to use the new feature, some changes need to be made. The PWM is configured to be 120Hz (period of 8.33 milliseconds), in order to avoid noticeable flicker in the backlight. If in your opinion this value is too fine, then you can reduce the frequency in the LCD constructor in <lcd_base.cpp> by increasing the period value. My recommendation is to avoid frequencies lower than 60Hz.

2012-12-21

  • Internal-only changes in the way drivers transmit colors - done to simplify the bitmap drawing routines; client API remains unchanged.

2012-12-12

  • Added the driver for the ST7735 display controller.
  • Added the RGB18 color mode: choose between 16-bit (65K distinct colors) and 18-bit (262K distinct colors) color space [supported by all drivers]. NOTE This feature requires the image drawing functions to be changed, in order to account for differences between configured display color depth and the color depth of the image. Please review the API docs, in particular the new type bitmap_t and the DrawBitmap functions.
  • Changed display rotation to be achieved through the correspondent settings in the respective controller registers: no more software translation between width and height in different display orientations.
  • Extended the orientation options: PORTRAIT (top line to 12 o'clock/upright) and LANDSCAPE (top line to 9 o'clock) positions are the old options, PORTRAIT_REV (top line to 6 o'clock/upside-down) and LANDSCAPE_REV (top line to 3 o'clock) are the new orientations.
  • Added more pre-defined colors: available now are COLOR_BLACK, COLOR_WHITE, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_CYAN, COLOR_MAGENTA and COLOR_YELLOW.

TODO

  • Finish implementing PWM-controlled backlight (current-sink configuration).
  • Add a driver for the HX8352-A controller (ITDB02-3.2WD 16:9 240x400 pixel resolution display).

How to Use

The code is documented, so please review the API docs. There is a simple example to get you started...

Committer:
ttodorov
Date:
Fri Dec 21 06:05:15 2012 +0000
Revision:
20:4bdca8d8dadc
Parent:
13:5ceeba86bbe4
Child:
21:e5c1e8ffada1
- changed internals of SetPixelColor to allow more general and simple implementation of the bitmap drawing functions

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ttodorov 0:881ff0b71102 1 /*
ttodorov 0:881ff0b71102 2 * Copyright (C)2010-2012 Henning Karlsen. All right reserved.
ttodorov 0:881ff0b71102 3 * Copyright (C)2012 Todor Todorov.
ttodorov 0:881ff0b71102 4 *
ttodorov 0:881ff0b71102 5 * This library is free software; you can redistribute it and/or
ttodorov 0:881ff0b71102 6 * modify it under the terms of the GNU Lesser General Public
ttodorov 0:881ff0b71102 7 * License as published by the Free Software Foundation; either
ttodorov 0:881ff0b71102 8 * version 2.1 of the License, or (at your option) any later version.
ttodorov 0:881ff0b71102 9 *
ttodorov 0:881ff0b71102 10 * This library is distributed in the hope that it will be useful,
ttodorov 0:881ff0b71102 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ttodorov 0:881ff0b71102 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ttodorov 0:881ff0b71102 13 * Lesser General Public License for more details.
ttodorov 0:881ff0b71102 14 *
ttodorov 0:881ff0b71102 15 * You should have received a copy of the GNU Lesser General Public
ttodorov 0:881ff0b71102 16 * License along with this library; if not, write to:
ttodorov 0:881ff0b71102 17 *
ttodorov 0:881ff0b71102 18 * Free Software Foundation, Inc.
ttodorov 0:881ff0b71102 19 * 51 Franklin St, 5th Floor, Boston, MA 02110-1301, USA
ttodorov 0:881ff0b71102 20 *
ttodorov 0:881ff0b71102 21 *********************************************************************/
ttodorov 0:881ff0b71102 22 #include "lcd_base.h"
ttodorov 3:64a5b67d5b51 23 #include "helpers.h"
ttodorov 0:881ff0b71102 24
ttodorov 4:3ac4239f6c9c 25 LCD::LCD( unsigned short width, unsigned short height ,PinName CS, PinName RS, PinName RESET )
ttodorov 4:3ac4239f6c9c 26 : _disp_width( width ), _disp_height( height ), _lcd_pin_cs( CS ), _lcd_pin_rs( RS ), _lcd_pin_reset( RESET )
ttodorov 4:3ac4239f6c9c 27 {
ttodorov 4:3ac4239f6c9c 28 SetForeground();
ttodorov 4:3ac4239f6c9c 29 SetBackground();
ttodorov 4:3ac4239f6c9c 30 _font.font = 0;
ttodorov 4:3ac4239f6c9c 31 }
ttodorov 0:881ff0b71102 32
ttodorov 0:881ff0b71102 33 inline
ttodorov 12:d0978272a340 34 void LCD::SetForeground( unsigned int color )
ttodorov 0:881ff0b71102 35 {
ttodorov 0:881ff0b71102 36 _foreground = color;
ttodorov 0:881ff0b71102 37 }
ttodorov 0:881ff0b71102 38
ttodorov 0:881ff0b71102 39 inline
ttodorov 12:d0978272a340 40 void LCD::SetBackground( unsigned int color )
ttodorov 0:881ff0b71102 41 {
ttodorov 0:881ff0b71102 42 _background = color;
ttodorov 0:881ff0b71102 43 }
ttodorov 0:881ff0b71102 44
ttodorov 0:881ff0b71102 45 void LCD::SetFont( const char *font )
ttodorov 0:881ff0b71102 46 {
ttodorov 0:881ff0b71102 47 _font.font = font;
ttodorov 0:881ff0b71102 48 _font.width = font[ 0 ];
ttodorov 0:881ff0b71102 49 _font.height = font[ 1 ];
ttodorov 0:881ff0b71102 50 _font.offset = font[ 2 ];
ttodorov 0:881ff0b71102 51 _font.numchars = font[ 3 ];
ttodorov 0:881ff0b71102 52 }
ttodorov 0:881ff0b71102 53
ttodorov 0:881ff0b71102 54 inline
ttodorov 0:881ff0b71102 55 unsigned short LCD::GetWidth( void )
ttodorov 0:881ff0b71102 56 {
ttodorov 12:d0978272a340 57 if ( _orientation == LANDSCAPE || _orientation == LANDSCAPE_REV ) return _disp_height;
ttodorov 0:881ff0b71102 58 return _disp_width;
ttodorov 0:881ff0b71102 59 }
ttodorov 0:881ff0b71102 60
ttodorov 0:881ff0b71102 61 inline
ttodorov 0:881ff0b71102 62 unsigned short LCD::GetHeight( void )
ttodorov 0:881ff0b71102 63 {
ttodorov 12:d0978272a340 64 if ( _orientation == LANDSCAPE || _orientation == LANDSCAPE_REV ) return _disp_width;
ttodorov 0:881ff0b71102 65 return _disp_height;
ttodorov 0:881ff0b71102 66 }
ttodorov 0:881ff0b71102 67
ttodorov 0:881ff0b71102 68 void LCD::FillScreen( int color )
ttodorov 0:881ff0b71102 69 {
ttodorov 12:d0978272a340 70 unsigned int rgb = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
ttodorov 4:3ac4239f6c9c 71 Activate();
ttodorov 2:81ed304b7e9b 72 ClearXY();
ttodorov 1:14bef43daf6f 73 for ( int i = 0; i < ( ( _disp_width ) * ( _disp_height ) ); i++ )
ttodorov 10:69571adcfad5 74 SetPixelColor( rgb );
ttodorov 4:3ac4239f6c9c 75 Deactivate();
ttodorov 0:881ff0b71102 76 }
ttodorov 0:881ff0b71102 77
ttodorov 0:881ff0b71102 78 inline
ttodorov 0:881ff0b71102 79 void LCD::ClearScreen( void )
ttodorov 0:881ff0b71102 80 {
ttodorov 0:881ff0b71102 81 FillScreen( -1 );
ttodorov 0:881ff0b71102 82 }
ttodorov 0:881ff0b71102 83
ttodorov 0:881ff0b71102 84 void LCD::DrawPixel( unsigned short x, unsigned short y, int color )
ttodorov 0:881ff0b71102 85 {
ttodorov 4:3ac4239f6c9c 86 Activate();
ttodorov 2:81ed304b7e9b 87 SetXY( x, y, x, y );
ttodorov 10:69571adcfad5 88 SetPixelColor( color == -1 ? _background :
ttodorov 0:881ff0b71102 89 color == -2 ? _foreground : color );
ttodorov 4:3ac4239f6c9c 90 Deactivate();
ttodorov 0:881ff0b71102 91 }
ttodorov 0:881ff0b71102 92
ttodorov 0:881ff0b71102 93 void LCD::DrawLine( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
ttodorov 0:881ff0b71102 94 {
ttodorov 0:881ff0b71102 95
ttodorov 0:881ff0b71102 96 double delta, tx, ty;
ttodorov 0:881ff0b71102 97
ttodorov 0:881ff0b71102 98 if ( ( ( x2 - x1 ) < 0 ) )
ttodorov 0:881ff0b71102 99 {
ttodorov 0:881ff0b71102 100 swap( ushort, x1, x2 )
ttodorov 0:881ff0b71102 101 swap( ushort, y1, y2 )
ttodorov 0:881ff0b71102 102 }
ttodorov 0:881ff0b71102 103 if ( ( ( y2 - y1 ) < 0 ) )
ttodorov 0:881ff0b71102 104 {
ttodorov 0:881ff0b71102 105 swap( ushort, x1, x2 )
ttodorov 0:881ff0b71102 106 swap( ushort, y1, y2 )
ttodorov 0:881ff0b71102 107 }
ttodorov 0:881ff0b71102 108
ttodorov 0:881ff0b71102 109 if ( y1 == y2 )
ttodorov 0:881ff0b71102 110 {
ttodorov 0:881ff0b71102 111 if ( x1 > x2 )
ttodorov 0:881ff0b71102 112 swap( ushort, x1, x2 )
ttodorov 2:81ed304b7e9b 113 DrawHLine( x1, y1, x2 - x1, color );
ttodorov 0:881ff0b71102 114 }
ttodorov 0:881ff0b71102 115 else if ( x1 == x2 )
ttodorov 0:881ff0b71102 116 {
ttodorov 0:881ff0b71102 117 if ( y1 > y2 )
ttodorov 0:881ff0b71102 118 swap( ushort, y1, y2 )
ttodorov 2:81ed304b7e9b 119 DrawVLine( x1, y1, y2 - y1, color );
ttodorov 0:881ff0b71102 120 }
ttodorov 4:3ac4239f6c9c 121 else
ttodorov 0:881ff0b71102 122 {
ttodorov 12:d0978272a340 123 unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
ttodorov 4:3ac4239f6c9c 124 Activate();
ttodorov 4:3ac4239f6c9c 125 if ( abs( x2 - x1 ) > abs( y2 - y1 ) )
ttodorov 0:881ff0b71102 126 {
ttodorov 4:3ac4239f6c9c 127 delta = ( double( y2 - y1 ) / double( x2 - x1 ) );
ttodorov 4:3ac4239f6c9c 128 ty = double( y1 );
ttodorov 4:3ac4239f6c9c 129 if ( x1 > x2 )
ttodorov 0:881ff0b71102 130 {
ttodorov 4:3ac4239f6c9c 131 for ( int i = x1; i >= x2; i-- )
ttodorov 4:3ac4239f6c9c 132 {
ttodorov 4:3ac4239f6c9c 133 SetXY( i, int( ty + 0.5 ), i, int( ty + 0.5 ) );
ttodorov 10:69571adcfad5 134 SetPixelColor( usedColor );
ttodorov 4:3ac4239f6c9c 135 ty = ty - delta;
ttodorov 4:3ac4239f6c9c 136 }
ttodorov 4:3ac4239f6c9c 137 }
ttodorov 4:3ac4239f6c9c 138 else
ttodorov 4:3ac4239f6c9c 139 {
ttodorov 4:3ac4239f6c9c 140 for ( int i = x1; i <= x2; i++ )
ttodorov 4:3ac4239f6c9c 141 {
ttodorov 4:3ac4239f6c9c 142 SetXY( i, int( ty + 0.5 ), i, int( ty + 0.5 ) );
ttodorov 10:69571adcfad5 143 SetPixelColor( usedColor );
ttodorov 4:3ac4239f6c9c 144 ty = ty + delta;
ttodorov 4:3ac4239f6c9c 145 }
ttodorov 0:881ff0b71102 146 }
ttodorov 0:881ff0b71102 147 }
ttodorov 0:881ff0b71102 148 else
ttodorov 0:881ff0b71102 149 {
ttodorov 4:3ac4239f6c9c 150 delta = ( float( x2 - x1 ) / float( y2 - y1 ) );
ttodorov 4:3ac4239f6c9c 151 tx = float( x1 );
ttodorov 4:3ac4239f6c9c 152 if ( y1 > y2 )
ttodorov 0:881ff0b71102 153 {
ttodorov 4:3ac4239f6c9c 154 for ( int i = y2 + 1; i > y1; i-- )
ttodorov 4:3ac4239f6c9c 155 {
ttodorov 4:3ac4239f6c9c 156 SetXY( int( tx + 0.5 ), i, int( tx + 0.5 ), i );
ttodorov 10:69571adcfad5 157 SetPixelColor( usedColor );
ttodorov 4:3ac4239f6c9c 158 tx = tx + delta;
ttodorov 4:3ac4239f6c9c 159 }
ttodorov 4:3ac4239f6c9c 160 }
ttodorov 4:3ac4239f6c9c 161 else
ttodorov 4:3ac4239f6c9c 162 {
ttodorov 4:3ac4239f6c9c 163 for ( int i = y1; i < y2 + 1; i++ )
ttodorov 4:3ac4239f6c9c 164 {
ttodorov 4:3ac4239f6c9c 165 SetXY( int( tx + 0.5 ), i, int( tx + 0.5 ), i );
ttodorov 10:69571adcfad5 166 SetPixelColor( usedColor );
ttodorov 4:3ac4239f6c9c 167 tx = tx + delta;
ttodorov 4:3ac4239f6c9c 168 }
ttodorov 0:881ff0b71102 169 }
ttodorov 0:881ff0b71102 170 }
ttodorov 4:3ac4239f6c9c 171 Deactivate();
ttodorov 0:881ff0b71102 172 }
ttodorov 0:881ff0b71102 173 }
ttodorov 0:881ff0b71102 174
ttodorov 0:881ff0b71102 175 void LCD::DrawRect( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
ttodorov 0:881ff0b71102 176 {
ttodorov 0:881ff0b71102 177 if ( x1 > x2 ) swap( ushort, x1, x2 )
ttodorov 0:881ff0b71102 178 if ( y1 > y2 ) swap( ushort, y1, y2 )
ttodorov 0:881ff0b71102 179
ttodorov 2:81ed304b7e9b 180 DrawHLine( x1, y1, x2 - x1, color );
ttodorov 2:81ed304b7e9b 181 DrawHLine( x1, y2, x2 - x1, color );
ttodorov 2:81ed304b7e9b 182 DrawVLine( x1, y1, y2 - y1, color );
ttodorov 2:81ed304b7e9b 183 DrawVLine( x2, y1, y2 - y1, color );
ttodorov 0:881ff0b71102 184 }
ttodorov 0:881ff0b71102 185
ttodorov 0:881ff0b71102 186 void LCD::DrawRoundRect( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
ttodorov 0:881ff0b71102 187 {
ttodorov 0:881ff0b71102 188 if ( x1 > x2 ) swap( ushort, x1, x2 )
ttodorov 0:881ff0b71102 189 if ( y1 > y2 ) swap( ushort, y1, y2 )
ttodorov 0:881ff0b71102 190
ttodorov 0:881ff0b71102 191 if ( ( x2 - x1 ) > 4 && ( y2 - y1 ) > 4 )
ttodorov 0:881ff0b71102 192 {
ttodorov 0:881ff0b71102 193 DrawPixel( x1 + 1, y1 + 1, color );
ttodorov 0:881ff0b71102 194 DrawPixel( x2 - 1, y1 + 1, color );
ttodorov 0:881ff0b71102 195 DrawPixel( x1 + 1, y2 - 1, color );
ttodorov 0:881ff0b71102 196 DrawPixel( x2 - 1, y2 - 1, color );
ttodorov 2:81ed304b7e9b 197 DrawHLine( x1 + 2, y1, x2 - x1 - 4, color );
ttodorov 2:81ed304b7e9b 198 DrawHLine( x1 + 2, y2, x2 - x1 - 4, color );
ttodorov 2:81ed304b7e9b 199 DrawVLine( x1, y1 + 2, y2 - y1 - 4, color );
ttodorov 2:81ed304b7e9b 200 DrawVLine( x2, y1 + 2, y2 - y1 - 4, color );
ttodorov 0:881ff0b71102 201 }
ttodorov 0:881ff0b71102 202 }
ttodorov 0:881ff0b71102 203
ttodorov 0:881ff0b71102 204 void LCD::FillRect( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
ttodorov 0:881ff0b71102 205 {
ttodorov 0:881ff0b71102 206 if ( x1 > x2 ) swap( ushort, x1, x2 );
ttodorov 0:881ff0b71102 207 if ( y1 > y2 ) swap( ushort, y1, y2 );
ttodorov 0:881ff0b71102 208
ttodorov 12:d0978272a340 209 for ( int i = 0; i < ( ( y2 - y1 ) / 2 ) + 1; i++ )
ttodorov 0:881ff0b71102 210 {
ttodorov 12:d0978272a340 211 DrawHLine( x1, y1 + i, x2 - x1, color );
ttodorov 12:d0978272a340 212 DrawHLine( x1, y2 - i, x2 - x1, color );
ttodorov 0:881ff0b71102 213 }
ttodorov 0:881ff0b71102 214 }
ttodorov 0:881ff0b71102 215
ttodorov 0:881ff0b71102 216 void LCD::FillRoundRect( unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, int color )
ttodorov 0:881ff0b71102 217 {
ttodorov 0:881ff0b71102 218 if ( x1 > x2 ) swap( ushort, x1, x2 )
ttodorov 0:881ff0b71102 219 if ( y1 > y2 ) swap( ushort, y1, y2 )
ttodorov 0:881ff0b71102 220
ttodorov 0:881ff0b71102 221 if ( ( x2 - x1 ) > 4 && ( y2 - y1 ) > 4 )
ttodorov 0:881ff0b71102 222 {
ttodorov 0:881ff0b71102 223 for ( int i = 0; i < ( ( y2 - y1 ) / 2 ) + 1; i++ )
ttodorov 0:881ff0b71102 224 {
ttodorov 0:881ff0b71102 225 switch ( i )
ttodorov 0:881ff0b71102 226 {
ttodorov 0:881ff0b71102 227 case 0:
ttodorov 2:81ed304b7e9b 228 DrawHLine( x1 + 2, y1 + i, x2 - x1 - 4, color );
ttodorov 2:81ed304b7e9b 229 DrawHLine( x1 + 2, y2 - i, x2 - x1 - 4, color );
ttodorov 0:881ff0b71102 230 break;
ttodorov 0:881ff0b71102 231
ttodorov 0:881ff0b71102 232 case 1:
ttodorov 2:81ed304b7e9b 233 DrawHLine( x1 + 1, y1 + i, x2 - x1 - 2, color );
ttodorov 2:81ed304b7e9b 234 DrawHLine( x1 + 1, y2 - i, x2 - x1 - 2, color );
ttodorov 0:881ff0b71102 235 break;
ttodorov 0:881ff0b71102 236
ttodorov 0:881ff0b71102 237 default:
ttodorov 2:81ed304b7e9b 238 DrawHLine( x1, y1 + i, x2 - x1, color );
ttodorov 2:81ed304b7e9b 239 DrawHLine( x1, y2 - i, x2 - x1, color );
ttodorov 0:881ff0b71102 240 break;
ttodorov 0:881ff0b71102 241 }
ttodorov 0:881ff0b71102 242 }
ttodorov 0:881ff0b71102 243 }
ttodorov 0:881ff0b71102 244 }
ttodorov 0:881ff0b71102 245
ttodorov 0:881ff0b71102 246 void LCD::DrawCircle( unsigned short x, unsigned short y, unsigned short radius, int color )
ttodorov 0:881ff0b71102 247 {
ttodorov 0:881ff0b71102 248 int f = 1 - radius;
ttodorov 0:881ff0b71102 249 int ddF_x = 1;
ttodorov 0:881ff0b71102 250 int ddF_y = -2 * radius;
ttodorov 0:881ff0b71102 251 int x1 = 0;
ttodorov 0:881ff0b71102 252 int y1 = radius;
ttodorov 12:d0978272a340 253 unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
ttodorov 0:881ff0b71102 254
ttodorov 4:3ac4239f6c9c 255 Activate();
ttodorov 2:81ed304b7e9b 256 SetXY( x, y + radius, x, y + radius );
ttodorov 10:69571adcfad5 257 SetPixelColor( usedColor );
ttodorov 2:81ed304b7e9b 258 SetXY( x, y - radius, x, y - radius );
ttodorov 10:69571adcfad5 259 SetPixelColor( usedColor );
ttodorov 2:81ed304b7e9b 260 SetXY( x + radius, y, x + radius, y );
ttodorov 10:69571adcfad5 261 SetPixelColor( usedColor );
ttodorov 2:81ed304b7e9b 262 SetXY( x - radius, y, x - radius, y );
ttodorov 10:69571adcfad5 263 SetPixelColor( usedColor );
ttodorov 0:881ff0b71102 264
ttodorov 0:881ff0b71102 265 while ( x1 < y1 )
ttodorov 0:881ff0b71102 266 {
ttodorov 0:881ff0b71102 267 if ( f >= 0 )
ttodorov 0:881ff0b71102 268 {
ttodorov 0:881ff0b71102 269 y1--;
ttodorov 0:881ff0b71102 270 ddF_y += 2;
ttodorov 0:881ff0b71102 271 f += ddF_y;
ttodorov 0:881ff0b71102 272 }
ttodorov 0:881ff0b71102 273 x1++;
ttodorov 0:881ff0b71102 274 ddF_x += 2;
ttodorov 0:881ff0b71102 275 f += ddF_x;
ttodorov 2:81ed304b7e9b 276 SetXY( x + x1, y + y1, x + x1, y + y1 );
ttodorov 10:69571adcfad5 277 SetPixelColor( usedColor );
ttodorov 2:81ed304b7e9b 278 SetXY( x - x1, y + y1, x - x1, y + y1 );
ttodorov 10:69571adcfad5 279 SetPixelColor( usedColor );
ttodorov 2:81ed304b7e9b 280 SetXY( x + x1, y - y1, x + x1, y - y1 );
ttodorov 10:69571adcfad5 281 SetPixelColor( usedColor );
ttodorov 2:81ed304b7e9b 282 SetXY( x - x1, y - y1, x - x1, y - y1 );
ttodorov 10:69571adcfad5 283 SetPixelColor( usedColor );
ttodorov 2:81ed304b7e9b 284 SetXY( x + y1, y + x1, x + y1, y + x1 );
ttodorov 10:69571adcfad5 285 SetPixelColor( usedColor );
ttodorov 2:81ed304b7e9b 286 SetXY( x - y1, y + x1, x - y1, y + x1 );
ttodorov 10:69571adcfad5 287 SetPixelColor( usedColor );
ttodorov 2:81ed304b7e9b 288 SetXY( x + y1, y - x1, x + y1, y - x1 );
ttodorov 10:69571adcfad5 289 SetPixelColor( usedColor );
ttodorov 2:81ed304b7e9b 290 SetXY( x - y1, y - x1, x - y1, y - x1 );
ttodorov 10:69571adcfad5 291 SetPixelColor( usedColor );
ttodorov 0:881ff0b71102 292 }
ttodorov 4:3ac4239f6c9c 293 Deactivate();
ttodorov 0:881ff0b71102 294 }
ttodorov 0:881ff0b71102 295
ttodorov 0:881ff0b71102 296 void LCD::FillCircle( unsigned short x, unsigned short y, unsigned short radius, int color )
ttodorov 0:881ff0b71102 297 {
ttodorov 12:d0978272a340 298 unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
ttodorov 4:3ac4239f6c9c 299 Activate();
ttodorov 0:881ff0b71102 300 for ( int y1 = -radius; y1 <= radius; y1++ )
ttodorov 0:881ff0b71102 301 for ( int x1 = -radius; x1 <= radius; x1++ )
ttodorov 0:881ff0b71102 302 if ( x1 * x1 + y1 * y1 <= radius * radius )
ttodorov 0:881ff0b71102 303 {
ttodorov 2:81ed304b7e9b 304 SetXY( x + x1, y + y1, x + x1, y + y1 );
ttodorov 10:69571adcfad5 305 SetPixelColor( usedColor );
ttodorov 0:881ff0b71102 306 }
ttodorov 4:3ac4239f6c9c 307 Deactivate();
ttodorov 0:881ff0b71102 308 }
ttodorov 0:881ff0b71102 309
ttodorov 0:881ff0b71102 310 void LCD::Print( const char *str, unsigned short x, unsigned short y, int fgColor, int bgColor, unsigned short deg )
ttodorov 0:881ff0b71102 311 {
ttodorov 0:881ff0b71102 312 int stl, i;
ttodorov 0:881ff0b71102 313
ttodorov 0:881ff0b71102 314 stl = strlen( str );
ttodorov 0:881ff0b71102 315
ttodorov 12:d0978272a340 316 if ( x == RIGHT )
ttodorov 12:d0978272a340 317 x = GetWidth() - ( stl * _font.width );
ttodorov 12:d0978272a340 318 if ( x == CENTER )
ttodorov 12:d0978272a340 319 x = ( GetWidth() - ( stl * _font.width ) ) / 2;
ttodorov 0:881ff0b71102 320
ttodorov 0:881ff0b71102 321 for ( i = 0; i < stl; i++ )
ttodorov 0:881ff0b71102 322 if ( deg == 0 )
ttodorov 2:81ed304b7e9b 323 PrintChar( *str++, x + ( i * ( _font.width ) ), y, fgColor, bgColor );
ttodorov 0:881ff0b71102 324 else
ttodorov 2:81ed304b7e9b 325 RotateChar( *str++, x, y, i, fgColor, bgColor, deg );
ttodorov 0:881ff0b71102 326 }
ttodorov 0:881ff0b71102 327
ttodorov 12:d0978272a340 328 void LCD::DrawBitmap( unsigned short x, unsigned short y, const bitmap_t* img, unsigned char scale )
ttodorov 0:881ff0b71102 329 {
ttodorov 0:881ff0b71102 330 int tx, ty, tc, tsx, tsy;
ttodorov 0:881ff0b71102 331
ttodorov 4:3ac4239f6c9c 332 Activate();
ttodorov 0:881ff0b71102 333 if ( scale == 1 )
ttodorov 0:881ff0b71102 334 {
ttodorov 12:d0978272a340 335 SetXY( x, y, x + img->Width - 1, y + img->Height - 1 );
ttodorov 20:4bdca8d8dadc 336
ttodorov 13:5ceeba86bbe4 337 if ( img->Format == RGB16 )
ttodorov 0:881ff0b71102 338 {
ttodorov 13:5ceeba86bbe4 339 const unsigned short *pixel = ( const unsigned short* ) img->PixelData;
ttodorov 20:4bdca8d8dadc 340 for ( tc = 0; tc < ( img->Width * img->Height ); tc++ )
ttodorov 20:4bdca8d8dadc 341 SetPixelColor( *pixel++, img->Format );
ttodorov 13:5ceeba86bbe4 342 }
ttodorov 13:5ceeba86bbe4 343 else if ( img->Format == RGB18 )
ttodorov 13:5ceeba86bbe4 344 {
ttodorov 13:5ceeba86bbe4 345 const unsigned int *pixel = ( const unsigned int* ) img->PixelData;
ttodorov 20:4bdca8d8dadc 346 for ( tc = 0; tc < ( img->Width * img->Height ); tc++ )
ttodorov 20:4bdca8d8dadc 347 SetPixelColor( *pixel++, img->Format );
ttodorov 0:881ff0b71102 348 }
ttodorov 0:881ff0b71102 349 }
ttodorov 0:881ff0b71102 350 else
ttodorov 0:881ff0b71102 351 {
ttodorov 13:5ceeba86bbe4 352 if ( img->Format == RGB16 )
ttodorov 0:881ff0b71102 353 {
ttodorov 13:5ceeba86bbe4 354 const unsigned short *pixel = ( const unsigned short* ) img->PixelData;
ttodorov 13:5ceeba86bbe4 355
ttodorov 13:5ceeba86bbe4 356 for ( ty = 0; ty < img->Height; ty++ )
ttodorov 13:5ceeba86bbe4 357 {
ttodorov 13:5ceeba86bbe4 358 SetXY( x, y + ( ty * scale ), x + ( ( img->Width * scale ) - 1 ), y + ( ty * scale ) + scale );
ttodorov 13:5ceeba86bbe4 359 for ( tsy = 0; tsy < scale; tsy++ )
ttodorov 13:5ceeba86bbe4 360 {
ttodorov 13:5ceeba86bbe4 361 for ( tx = 0; tx < img->Width; tx++ )
ttodorov 13:5ceeba86bbe4 362 {
ttodorov 13:5ceeba86bbe4 363 for ( tsx = 0; tsx < scale; tsx++ )
ttodorov 20:4bdca8d8dadc 364 SetPixelColor( pixel[ ( ty * img->Width ) + tx ], img->Format );
ttodorov 20:4bdca8d8dadc 365 }
ttodorov 20:4bdca8d8dadc 366 }
ttodorov 20:4bdca8d8dadc 367 }
ttodorov 20:4bdca8d8dadc 368 }
ttodorov 20:4bdca8d8dadc 369 else if ( img->Format == RGB18 )
ttodorov 20:4bdca8d8dadc 370 {
ttodorov 20:4bdca8d8dadc 371 const unsigned int *pixel = ( const unsigned int* ) img->PixelData;
ttodorov 20:4bdca8d8dadc 372
ttodorov 20:4bdca8d8dadc 373 for ( ty = 0; ty < img->Height; ty++ )
ttodorov 20:4bdca8d8dadc 374 {
ttodorov 20:4bdca8d8dadc 375 SetXY( x, y + ( ty * scale ), x + ( ( img->Width * scale ) - 1 ), y + ( ty * scale ) + scale );
ttodorov 20:4bdca8d8dadc 376 for ( tsy = 0; tsy < scale; tsy++ )
ttodorov 20:4bdca8d8dadc 377 {
ttodorov 20:4bdca8d8dadc 378 for ( tx = 0; tx < img->Width; tx++ )
ttodorov 20:4bdca8d8dadc 379 {
ttodorov 20:4bdca8d8dadc 380 for ( tsx = 0; tsx < scale; tsx++ )
ttodorov 20:4bdca8d8dadc 381 SetPixelColor( pixel[ ( ty * img->Width ) + tx ], img->Format );
ttodorov 13:5ceeba86bbe4 382 }
ttodorov 13:5ceeba86bbe4 383 }
ttodorov 13:5ceeba86bbe4 384 }
ttodorov 13:5ceeba86bbe4 385 }
ttodorov 0:881ff0b71102 386 }
ttodorov 4:3ac4239f6c9c 387 Deactivate();
ttodorov 0:881ff0b71102 388 }
ttodorov 0:881ff0b71102 389
ttodorov 12:d0978272a340 390 void LCD::DrawBitmap( unsigned short x, unsigned short y, const bitmap_t* img, unsigned short deg, unsigned short rox, unsigned short roy )
ttodorov 0:881ff0b71102 391 {
ttodorov 0:881ff0b71102 392 int tx, ty, newx, newy;
ttodorov 0:881ff0b71102 393 double radian;
ttodorov 0:881ff0b71102 394 radian = deg * 0.0175;
ttodorov 0:881ff0b71102 395
ttodorov 0:881ff0b71102 396 if ( deg == 0 )
ttodorov 12:d0978272a340 397 DrawBitmap( x, y, img );
ttodorov 0:881ff0b71102 398 else
ttodorov 0:881ff0b71102 399 {
ttodorov 4:3ac4239f6c9c 400 Activate();
ttodorov 13:5ceeba86bbe4 401
ttodorov 13:5ceeba86bbe4 402 if ( img->Format == RGB16 )
ttodorov 13:5ceeba86bbe4 403 {
ttodorov 13:5ceeba86bbe4 404 const unsigned short *pixel = ( const unsigned short* ) img->PixelData;
ttodorov 13:5ceeba86bbe4 405
ttodorov 13:5ceeba86bbe4 406 for ( ty = 0; ty < img->Height; ty++ )
ttodorov 13:5ceeba86bbe4 407 for ( tx = 0; tx < img->Width; tx++ )
ttodorov 13:5ceeba86bbe4 408 {
ttodorov 13:5ceeba86bbe4 409 newx = x + rox + ( ( ( tx - rox ) * cos( radian ) ) - ( ( ty - roy ) * sin( radian ) ) );
ttodorov 13:5ceeba86bbe4 410 newy = y + roy + ( ( ( ty - roy ) * cos( radian ) ) + ( ( tx - rox ) * sin( radian ) ) );
ttodorov 13:5ceeba86bbe4 411
ttodorov 13:5ceeba86bbe4 412 SetXY( newx, newy, newx, newy );
ttodorov 20:4bdca8d8dadc 413 SetPixelColor( pixel[ ( ty * img->Width ) + tx ], img->Format );
ttodorov 13:5ceeba86bbe4 414 }
ttodorov 13:5ceeba86bbe4 415 }
ttodorov 13:5ceeba86bbe4 416 else if ( img->Format == RGB18 )
ttodorov 13:5ceeba86bbe4 417 {
ttodorov 13:5ceeba86bbe4 418 const unsigned int *pixel = ( const unsigned int* ) img->PixelData;
ttodorov 13:5ceeba86bbe4 419
ttodorov 13:5ceeba86bbe4 420 for ( ty = 0; ty < img->Height; ty++ )
ttodorov 13:5ceeba86bbe4 421 for ( tx = 0; tx < img->Width; tx++ )
ttodorov 13:5ceeba86bbe4 422 {
ttodorov 13:5ceeba86bbe4 423 newx = x + rox + ( ( ( tx - rox ) * cos( radian ) ) - ( ( ty - roy ) * sin( radian ) ) );
ttodorov 13:5ceeba86bbe4 424 newy = y + roy + ( ( ( ty - roy ) * cos( radian ) ) + ( ( tx - rox ) * sin( radian ) ) );
ttodorov 13:5ceeba86bbe4 425
ttodorov 13:5ceeba86bbe4 426 SetXY( newx, newy, newx, newy );
ttodorov 20:4bdca8d8dadc 427 SetPixelColor( pixel[ ( ty * img->Width ) + tx ], img->Format );
ttodorov 13:5ceeba86bbe4 428 }
ttodorov 13:5ceeba86bbe4 429 }
ttodorov 4:3ac4239f6c9c 430 Deactivate();
ttodorov 0:881ff0b71102 431 }
ttodorov 4:3ac4239f6c9c 432 }
ttodorov 4:3ac4239f6c9c 433
ttodorov 4:3ac4239f6c9c 434 inline
ttodorov 4:3ac4239f6c9c 435 void LCD::Activate( void )
ttodorov 4:3ac4239f6c9c 436 {
ttodorov 4:3ac4239f6c9c 437 _lcd_pin_cs = LOW;
ttodorov 4:3ac4239f6c9c 438 }
ttodorov 4:3ac4239f6c9c 439
ttodorov 4:3ac4239f6c9c 440 inline
ttodorov 4:3ac4239f6c9c 441 void LCD::Deactivate( void )
ttodorov 4:3ac4239f6c9c 442 {
ttodorov 4:3ac4239f6c9c 443 _lcd_pin_cs = HIGH;
ttodorov 0:881ff0b71102 444 }
ttodorov 0:881ff0b71102 445
ttodorov 0:881ff0b71102 446 inline
ttodorov 2:81ed304b7e9b 447 void LCD::WriteCmdData( unsigned short cmd, unsigned short data )
ttodorov 0:881ff0b71102 448 {
ttodorov 2:81ed304b7e9b 449 WriteCmd( cmd );
ttodorov 2:81ed304b7e9b 450 WriteData( data );
ttodorov 0:881ff0b71102 451 }
ttodorov 0:881ff0b71102 452
ttodorov 12:d0978272a340 453 inline
ttodorov 12:d0978272a340 454 void LCD::ClearXY( void )
ttodorov 0:881ff0b71102 455 {
ttodorov 12:d0978272a340 456 SetXY( 0, 0, GetWidth() - 1, GetHeight() - 1 );
ttodorov 0:881ff0b71102 457 }
ttodorov 0:881ff0b71102 458
ttodorov 2:81ed304b7e9b 459 void LCD::DrawHLine( unsigned short x, unsigned short y, unsigned short len, int color )
ttodorov 0:881ff0b71102 460 {
ttodorov 12:d0978272a340 461 unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
ttodorov 0:881ff0b71102 462
ttodorov 4:3ac4239f6c9c 463 Activate();
ttodorov 2:81ed304b7e9b 464 SetXY( x, y, x + len, y );
ttodorov 0:881ff0b71102 465 for ( int i = 0; i < len + 1; i++ )
ttodorov 10:69571adcfad5 466 SetPixelColor( usedColor );
ttodorov 4:3ac4239f6c9c 467 Deactivate();
ttodorov 0:881ff0b71102 468 }
ttodorov 0:881ff0b71102 469
ttodorov 2:81ed304b7e9b 470 void LCD::DrawVLine( unsigned short x, unsigned short y, unsigned short len, int color )
ttodorov 0:881ff0b71102 471 {
ttodorov 12:d0978272a340 472 unsigned int usedColor = color == -1 ? _background : color == -2 ? _foreground : ( unsigned int ) color;
ttodorov 0:881ff0b71102 473
ttodorov 4:3ac4239f6c9c 474 Activate();
ttodorov 2:81ed304b7e9b 475 SetXY( x, y, x, y + len );
ttodorov 0:881ff0b71102 476 for ( int i = 0; i < len; i++ )
ttodorov 10:69571adcfad5 477 SetPixelColor( usedColor );
ttodorov 4:3ac4239f6c9c 478 Deactivate();
ttodorov 0:881ff0b71102 479 }
ttodorov 0:881ff0b71102 480
ttodorov 2:81ed304b7e9b 481 void LCD::PrintChar( char c, unsigned short x, unsigned short y, int fgColor, int bgColor )
ttodorov 0:881ff0b71102 482 {
ttodorov 0:881ff0b71102 483 uint8_t i, ch;
ttodorov 0:881ff0b71102 484 uint16_t j;
ttodorov 0:881ff0b71102 485 uint16_t temp;
ttodorov 12:d0978272a340 486 unsigned int usedColorFG = fgColor == -1 ? _background : fgColor == -2 ? _foreground : ( unsigned int ) fgColor;
ttodorov 12:d0978272a340 487 unsigned int usedColorBG = bgColor == -1 ? _background : bgColor == -2 ? _foreground : ( unsigned int ) bgColor;
ttodorov 0:881ff0b71102 488
ttodorov 4:3ac4239f6c9c 489 Activate();
ttodorov 0:881ff0b71102 490
ttodorov 12:d0978272a340 491 SetXY( x, y, x + _font.width - 1, y + _font.height - 1 );
ttodorov 12:d0978272a340 492
ttodorov 12:d0978272a340 493 temp = ( ( c - _font.offset ) * ( ( _font.width / 8 ) * _font.height ) ) + 4;
ttodorov 12:d0978272a340 494 for ( j = 0; j < ( ( _font.width / 8 ) * _font.height ); j++ )
ttodorov 0:881ff0b71102 495 {
ttodorov 12:d0978272a340 496 ch = _font.font[ temp ];
ttodorov 12:d0978272a340 497 for ( i = 0; i < 8; i++ )
ttodorov 0:881ff0b71102 498 {
ttodorov 12:d0978272a340 499 if ( ( ch & ( 1 << ( 7 - i ) ) ) != 0 )
ttodorov 12:d0978272a340 500 SetPixelColor( usedColorFG );
ttodorov 12:d0978272a340 501 else
ttodorov 12:d0978272a340 502 SetPixelColor( usedColorBG );
ttodorov 0:881ff0b71102 503 }
ttodorov 12:d0978272a340 504 temp++;
ttodorov 0:881ff0b71102 505 }
ttodorov 4:3ac4239f6c9c 506 Deactivate();
ttodorov 0:881ff0b71102 507 }
ttodorov 0:881ff0b71102 508
ttodorov 2:81ed304b7e9b 509 void LCD::RotateChar( char c, unsigned short x, unsigned short y, int pos, int fgColor, int bgColor, unsigned short deg )
ttodorov 0:881ff0b71102 510 {
ttodorov 0:881ff0b71102 511 uint8_t i, j, ch;
ttodorov 0:881ff0b71102 512 uint16_t temp;
ttodorov 0:881ff0b71102 513 int newx, newy;
ttodorov 0:881ff0b71102 514 double radian;
ttodorov 0:881ff0b71102 515 radian = deg * 0.0175;
ttodorov 0:881ff0b71102 516
ttodorov 12:d0978272a340 517 unsigned int usedColorFG = fgColor == -1 ? _background : fgColor == -2 ? _foreground : ( unsigned int ) fgColor;
ttodorov 12:d0978272a340 518 unsigned int usedColorBG = bgColor == -1 ? _background : bgColor == -2 ? _foreground : ( unsigned int ) bgColor;
ttodorov 0:881ff0b71102 519
ttodorov 4:3ac4239f6c9c 520 Activate();
ttodorov 0:881ff0b71102 521
ttodorov 0:881ff0b71102 522 temp = ( ( c - _font.offset ) * ( ( _font.width / 8 ) * _font.height ) ) + 4;
ttodorov 0:881ff0b71102 523 for ( j = 0; j < _font.height; j++ )
ttodorov 0:881ff0b71102 524 {
ttodorov 0:881ff0b71102 525 for ( int zz = 0; zz < ( _font.width / 8 ); zz++ )
ttodorov 0:881ff0b71102 526 {
ttodorov 0:881ff0b71102 527 ch = _font.font[ temp + zz ];
ttodorov 0:881ff0b71102 528 for ( i = 0; i < 8; i++ )
ttodorov 0:881ff0b71102 529 {
ttodorov 0:881ff0b71102 530 newx = x + ( ( ( i + ( zz * 8 ) + ( pos * _font.width ) ) * cos( radian ) ) - ( ( j ) * sin( radian ) ) );
ttodorov 0:881ff0b71102 531 newy = y + ( ( ( j ) * cos( radian ) ) + ( ( i + ( zz * 8 ) + ( pos * _font.width ) ) * sin( radian ) ) );
ttodorov 0:881ff0b71102 532
ttodorov 2:81ed304b7e9b 533 SetXY( newx, newy, newx + 1, newy + 1 );
ttodorov 0:881ff0b71102 534
ttodorov 0:881ff0b71102 535 if ( ( ch & ( 1 << ( 7 - i ) ) ) != 0 )
ttodorov 10:69571adcfad5 536 SetPixelColor( usedColorFG );
ttodorov 0:881ff0b71102 537 else
ttodorov 10:69571adcfad5 538 SetPixelColor( usedColorBG );
ttodorov 0:881ff0b71102 539 }
ttodorov 0:881ff0b71102 540 }
ttodorov 0:881ff0b71102 541 temp += ( _font.width / 8 );
ttodorov 0:881ff0b71102 542 }
ttodorov 4:3ac4239f6c9c 543 Deactivate();
ttodorov 0:881ff0b71102 544 }