Library for handling ILI9163 - based LCD displays.

Dependents:   TVZ_MU_Seminar

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ili9163lcd.cpp Source File

ili9163lcd.cpp

00001 /**
00002  * @file ili9163lcd.c
00003  * @brief ILI9163 128x128 LCD Driver
00004  *
00005  * This code has been ported from the ili9163lcd library for mbed
00006  * made by Jun Morita.
00007  * Source form <http://files.noccylabs.info/lib430/liblcd/ili9163lcd_8c.html>
00008  *
00009  * This code has been ported from the ili9163lcd library for avr made
00010  * by Simon Inns, to run on a msp430.
00011  *
00012  * This program is free software: you can redistribute it and/or modify
00013  * it under the terms of the GNU General Public License as published by
00014  * the Free Software Foundation, either version 3 of the License, or
00015  * (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  * GNU General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License
00023  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00024  *
00025  * @author Jun Morita (iccraft)
00026  * @author Simon Inns <simon.inns@gmail.com>
00027  * @author Christopher Vagnetoft (NoccyLabs)
00028  * @copyright (C) 2012 Simon Inns
00029  * @copyright parts (C) 2012 NoccyLabs
00030  */
00031 
00032 #include "ili9163lcd.h"
00033 #include "mbed.h"
00034 
00035 //--------------------------------------------------------------------------
00036 // Initialize the object
00037 //
00038 ILI9163::ILI9163(PinName SCK, PinName SDA, PinName A0, PinName RESET, PinName CS, PinName LED)
00039  : SPI_(SDA, NC, SCK), A0_(A0), RESET_(RESET), CS_(CS), LED_(LED)
00040 {
00041   SPI_.format(8);
00042   //TODO: allow user to change interface frequency
00043   SPI_.frequency(20000000);
00044   
00045   setFont((unsigned char*)font5x8);  
00046 }
00047 
00048 //--------------------------------------------------------------------------
00049 // Low-level LCD driving functions
00050 
00051 // Reset the LCD hardware
00052 void ILI9163::reset(void)
00053 {
00054     // Reset pin is active low (0 = reset, 1 = ready)
00055     RESET_ = 0;
00056     wait_ms(50);
00057 
00058     RESET_ = 1;
00059     wait_ms(120);
00060 }
00061 
00062 void ILI9163::writeCommand(uint8_t address)
00063 {
00064     CS_ = 0;
00065     A0_ = 0;
00066     SPI_.write(address);
00067     CS_ = 1;
00068 }
00069 
00070 void ILI9163::writeParameter(uint8_t parameter)
00071 {  
00072     CS_ = 0;
00073     A0_ = 1;
00074     SPI_.write(parameter);
00075     CS_ = 1;
00076 }
00077  
00078 void ILI9163::writeData(uint16_t data)
00079 {
00080     CS_ = 0;
00081     A0_ = 1;
00082     SPI_.write(data >> 8);
00083     SPI_.write(data & 0xFF);
00084     CS_ = 1;
00085 }
00086 
00087 // Initialize the display with the require screen orientation
00088 void ILI9163::init(uint8_t orientation)
00089 {   
00090     CS_ = 1;
00091     RESET_ = 1;
00092    
00093     // Hardware reset the LCD
00094     reset();
00095     
00096     writeCommand(EXIT_SLEEP_MODE);
00097     wait_ms(5); // Wait for the screen to wake up
00098     
00099     writeCommand(SET_PIXEL_FORMAT);
00100     writeParameter(0x05); // 16 bits per pixel
00101    
00102     writeCommand(SET_GAMMA_CURVE);
00103     writeParameter(0x04); // Select gamma curve 3
00104     
00105     writeCommand(GAM_R_SEL);
00106     writeParameter(0x01); // Gamma adjustment enabled
00107     
00108     writeCommand(POSITIVE_GAMMA_CORRECT);
00109     writeParameter(0x3f); // 1st Parameter
00110     writeParameter(0x25); // 2nd Parameter
00111     writeParameter(0x1c); // 3rd Parameter
00112     writeParameter(0x1e); // 4th Parameter
00113     writeParameter(0x20); // 5th Parameter
00114     writeParameter(0x12); // 6th Parameter
00115     writeParameter(0x2a); // 7th Parameter
00116     writeParameter(0x90); // 8th Parameter
00117     writeParameter(0x24); // 9th Parameter
00118     writeParameter(0x11); // 10th Parameter
00119     writeParameter(0x00); // 11th Parameter
00120     writeParameter(0x00); // 12th Parameter
00121     writeParameter(0x00); // 13th Parameter
00122     writeParameter(0x00); // 14th Parameter
00123     writeParameter(0x00); // 15th Parameter
00124      
00125     writeCommand(NEGATIVE_GAMMA_CORRECT);
00126     writeParameter(0x20); // 1st Parameter
00127     writeParameter(0x20); // 2nd Parameter
00128     writeParameter(0x20); // 3rd Parameter
00129     writeParameter(0x20); // 4th Parameter
00130     writeParameter(0x05); // 5th Parameter
00131     writeParameter(0x00); // 6th Parameter
00132     writeParameter(0x15); // 7th Parameter
00133     writeParameter(0xa7); // 8th Parameter
00134     writeParameter(0x3d); // 9th Parameter
00135     writeParameter(0x18); // 10th Parameter
00136     writeParameter(0x25); // 11th Parameter
00137     writeParameter(0x2a); // 12th Parameter
00138     writeParameter(0x2b); // 13th Parameter
00139     writeParameter(0x2b); // 14th Parameter
00140     writeParameter(0x3a); // 15th Parameter
00141     
00142     writeCommand(FRAME_RATE_CONTROL1);
00143     writeParameter(0x11); // DIVA = 17
00144     writeParameter(0x14); // VPA = 20
00145     
00146     writeCommand(DISPLAY_INVERSION);
00147     writeParameter(0x07); // NLA = 1, NLB = 1, NLC = 1 (all on Frame Inversion)
00148    
00149     writeCommand(POWER_CONTROL1);
00150     writeParameter(0x0a); // VRH = 10:  GVDD = 4.30
00151     writeParameter(0x02); // VC = 2: VCI1 = 2.65
00152       
00153     writeCommand(POWER_CONTROL2);
00154     writeParameter(0x02); // BT = 2: AVDD = 2xVCI1, VCL = -1xVCI1, VGH = 5xVCI1, VGL = -2xVCI1
00155 
00156     writeCommand(VCOM_CONTROL1);
00157     writeParameter(0x50); // VMH = 80: VCOMH voltage = 4.5
00158     writeParameter(0x5b); // VML = 91: VCOML voltage = -0.225
00159     
00160     writeCommand(VCOM_OFFSET_CONTROL);
00161     writeParameter(0x40); // nVM = 0, VMF = 64: VCOMH output = VMH, VCOML output = VML   
00162     
00163     writeCommand(SET_COLUMN_ADDRESS);
00164     writeParameter(0x00); // XSH
00165     writeParameter(0x00); // XSL
00166     writeParameter(0x00); // XEH
00167     writeParameter(0x7f); // XEL (128 pixels x)
00168    
00169     writeCommand(SET_PAGE_ADDRESS);
00170     writeParameter(0x00);
00171     writeParameter(0x00);
00172     writeParameter(0x00);
00173     writeParameter(0x7f); // 128 pixels y
00174     
00175     // Select display orientation
00176     writeCommand(SET_ADDRESS_MODE);
00177     writeParameter(orientation);
00178 
00179     // Set the display to on
00180     writeCommand(SET_DISPLAY_ON);
00181     writeCommand(WRITE_MEMORY_START);
00182 }
00183 
00184 // LCD graphics functions -----------------------------------------------------------------------------------
00185 
00186 void ILI9163::clearDisplay(uint16_t colour)
00187 {
00188     uint16_t pixel;
00189   
00190     // Set the column address to 0-127
00191     writeCommand(SET_COLUMN_ADDRESS);
00192     writeParameter(0x00);
00193     writeParameter(0x00);
00194     writeParameter(0x00);
00195     writeParameter(0x7f);
00196 
00197     // Set the page address to 0-127
00198     writeCommand(SET_PAGE_ADDRESS);
00199     writeParameter(0x00);
00200     writeParameter(0x00);
00201     writeParameter(0x00);
00202     writeParameter(0x7f);
00203   
00204     // Plot the pixels
00205     writeCommand(WRITE_MEMORY_START);
00206     
00207     for(pixel = 0; pixel < 128*128; pixel++)
00208         writeData(colour);
00209 }
00210 
00211 void ILI9163::plot(uint8_t x, uint8_t y, uint16_t colour)
00212 {
00213     // Horizontal Address Start Position
00214     writeCommand(SET_COLUMN_ADDRESS);
00215     writeParameter(0x00);
00216     writeParameter(x);
00217     writeParameter(0x00);
00218     writeParameter(0x7f);
00219   
00220     // Vertical Address end Position
00221     writeCommand(SET_PAGE_ADDRESS);
00222     writeParameter(0x00);
00223     writeParameter(y);
00224     writeParameter(0x00);
00225     writeParameter(0x7f);
00226 
00227     // Plot the point
00228     writeCommand(WRITE_MEMORY_START);
00229     writeData(colour);
00230 }
00231 
00232 // Draw a line from x0, y0 to x1, y1
00233 // Note:    This is a version of Bresenham's line drawing algorithm
00234 //          It only draws lines from left to right!
00235 void ILI9163::line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t colour)
00236 {
00237     int16_t dy = y1 - y0;
00238     int16_t dx = x1 - x0;
00239     int16_t stepx, stepy;
00240 
00241     if (dy < 0)
00242     {
00243         dy = -dy; stepy = -1; 
00244     }
00245     else stepy = 1; 
00246 
00247     if (dx < 0)
00248     {
00249         dx = -dx; stepx = -1; 
00250     }
00251     else stepx = 1; 
00252 
00253     dy <<= 1;                           // dy is now 2*dy
00254     dx <<= 1;                           // dx is now 2*dx
00255  
00256     plot(x0, y0, colour);
00257 
00258     if (dx > dy) {
00259         int fraction = dy - (dx >> 1);  // same as 2*dy - dx
00260         while (x0 != x1)
00261         {
00262             if (fraction >= 0)
00263             {
00264                 y0 += stepy;
00265                 fraction -= dx;         // same as fraction -= 2*dx
00266             }
00267 
00268             x0 += stepx;
00269             fraction += dy;                 // same as fraction -= 2*dy
00270             plot(x0, y0, colour);
00271         }
00272     }
00273     else
00274     {
00275         int fraction = dx - (dy >> 1);
00276         while (y0 != y1)
00277         {
00278             if (fraction >= 0)
00279             {
00280                 x0 += stepx;
00281                 fraction -= dy;
00282             }
00283 
00284             y0 += stepy;
00285             fraction += dx;
00286             plot(x0, y0, colour);
00287         }
00288     }
00289 }
00290 
00291 // Draw a rectangle between x0, y0 and x1, y1
00292 void ILI9163::rectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t colour)
00293 {
00294     line(x0, y0, x0, y1, colour);
00295     line(x0, y1, x1, y1, colour);
00296     line(x1, y0, x1, y1, colour);
00297     line(x0, y0, x1, y0, colour);
00298 }
00299 
00300 // Draw a filled rectangle
00301 // Note:    y1 must be greater than y0  and x1 must be greater than x0
00302 //          for this to work
00303 void ILI9163::filledRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t colour)
00304 {
00305     uint16_t pixels;
00306             
00307     // To speed up plotting we define a x window with the width of the 
00308     // rectangle and then just output the required number of bytes to
00309     // fill down to the end point
00310     
00311     writeCommand(SET_COLUMN_ADDRESS); // Horizontal Address Start Position
00312     writeParameter(0x00);
00313     writeParameter(x0);
00314     writeParameter(0x00);
00315     writeParameter(x1);
00316   
00317     writeCommand(SET_PAGE_ADDRESS); // Vertical Address end Position
00318     writeParameter(0x00);
00319     writeParameter(y0);
00320     writeParameter(0x00);
00321     writeParameter(0x7f);
00322         
00323     writeCommand(WRITE_MEMORY_START);
00324     
00325     for (pixels = 0; pixels < (((x1 - x0) + 1) * ((y1 - y0) + 1)); pixels++)
00326         writeData(colour);;
00327 }
00328 
00329 // Draw a circle
00330 // Note:    This is another version of Bresenham's line drawing algorithm.
00331 //          There's plenty of documentation on the web if you are curious
00332 //          how this works.
00333 void ILI9163::circle(int16_t xCentre, int16_t yCentre, int16_t radius, uint16_t colour)
00334 {
00335     int16_t x = 0, y = radius;
00336     int16_t d = 3 - (2 * radius);
00337  
00338     while(x <= y)
00339     {
00340         plot(xCentre + x, yCentre + y, colour);
00341         plot(xCentre + y, yCentre + x, colour);
00342         plot(xCentre - x, yCentre + y, colour);
00343         plot(xCentre + y, yCentre - x, colour);
00344         plot(xCentre - x, yCentre - y, colour);
00345         plot(xCentre - y, yCentre - x, colour);
00346         plot(xCentre + x, yCentre - y, colour);
00347         plot(xCentre - y, yCentre + x, colour);
00348 
00349         if (d < 0) d += (4 * x) + 6;
00350         else
00351         {
00352             d += (4 * (x - y)) + 10;
00353             y -= 1;
00354         }
00355 
00356         x++;
00357     }
00358 }
00359 
00360 // LCD text manipulation functions --------------------------------------------------------------------------
00361 
00362 // Change the font and store its size information
00363 void ILI9163::setFont(unsigned char* f) {
00364     font = f;
00365     font_bp_char = font[0];                   // bytes per character
00366     font_hor = font[1];                       // hor size of font
00367     font_vert = font[2];                      // vert size of font
00368     font_bp_line = font[3];                   // bytes per line
00369 }
00370 
00371 // Plot a character at the specified x, y co-ordinates (top left hand corner of character)
00372 void ILI9163::putCh(unsigned char c, uint8_t x, uint8_t y, uint16_t fgColour, uint16_t bgColour)
00373 {
00374     uint16_t sign;
00375     unsigned char z;
00376     unsigned int j,i,b;
00377     
00378     if ((c < 31) || (c > 127)) return;   //Check if character is printable
00379     
00380     // To speed up plotting we define a x window of 6 pixels and then
00381     // write out one row at a time.  This means the LCD will correctly
00382     // update the memory pointer saving us a good few bytes
00383     
00384     writeCommand(SET_COLUMN_ADDRESS); // Horizontal Address Start Position
00385     writeParameter(0x00);
00386     writeParameter(x);
00387     writeParameter(0x00);
00388     writeParameter(x+font_hor-1);  // x + w -1 >> XEnd
00389   
00390     writeCommand(SET_PAGE_ADDRESS); // Vertical Address end Position
00391     writeParameter(0x00);
00392     writeParameter(y);
00393     writeParameter(0x00);
00394     writeParameter(y+font_vert-1);  // y + h -1 >> YEnd  0x7F
00395         
00396     writeCommand(WRITE_MEMORY_START);
00397     
00398     sign = (((c -32) * font_bp_char) + 4); // start of char bitmap
00399   
00400     // Plot the font data
00401     for (j=0; j<font_vert; j++) {      //  vert line
00402         for (i=0; i<font_hor; i++) {   //  horz line
00403             z =  font[sign + (font_bp_line * i) + ((j & 0xF8) >> 3)+1];
00404             b = 1 << (j & 0x07);
00405             if (( z & b ) == 0x00)  writeData(fgColour);  
00406             else                    writeData(bgColour);
00407         }
00408     }
00409 }
00410 
00411 // Plot a string of characters to the LCD
00412 void ILI9163::putS(const char *str, uint8_t x, uint8_t y, uint16_t fgColour, uint16_t bgColour)
00413 {
00414     uint8_t origin = x;
00415 
00416     for (uint8_t i = 0; i < strlen(str); i++)
00417     {
00418         // Check if we are out of bounds and move to 
00419         // the next line if we are
00420         if (x + font_hor > 127)
00421         {
00422             x = origin;
00423             y += font_vert;
00424         }
00425 
00426         // If we move past the bottom of the screen just exit
00427         if (y + font_vert > 127) break;
00428         
00429         // Plot the current character
00430         putCh(str[i], x, y, fgColour, bgColour);
00431         x += font_hor;
00432     }
00433 }