TFT 1.44

Dependencies:   mbed

Fork of DL144128_LCD by Jun Morita

ili9163lcd.cpp

Committer:
rs27
Date:
2015-02-28
Revision:
1:b64c81071d96
Parent:
0:c0be4e018a09

File content as of revision 1:b64c81071d96:

/**
 * @file ili9163lcd.c
 * @brief ILI9163 128x128 LCD Driver
 *
 * This code has been ported from the ili9163lcd library for mbed
 * made by Jun Morita.
 * Source form <http://files.noccylabs.info/lib430/liblcd/ili9163lcd_8c.html>
 *
 * This code has been ported from the ili9163lcd library for avr made
 * by Simon Inns, to run on a msp430.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Jun Morita (iccraft)
 * @author Simon Inns <simon.inns@gmail.com>
 * @author Christopher Vagnetoft (NoccyLabs)
 * @copyright (C) 2012 Simon Inns
 * @copyright parts (C) 2012 NoccyLabs
 */

#include "ili9163lcd.h"
#include "mbed.h"

//--------------------------------------------------------------------------
// Construktor Objekt initialisieren
//
ILI9163::ILI9163(PinName SCK, PinName SDA, PinName A0, PinName RESET, PinName CS)
 : SCK_(SCK), SDA_(SDA), A0_(A0), RESET_(RESET), CS_(CS)
{
  tm=10;
  R=0,G=0,B=0;
  RGB_state=0;
  
  font_size = 2;
  
  set_font((unsigned char*)font11x16);  
}

//--------------------------------------------------------------------------
// Low-level LCD driving functions
// Reset the LCD hardware
void ILI9163::lcdReset(void)
{
    // Reset pin is active low (0 = reset, 1 = ready)
    RESET_ = 0;
    wait_ms(50);

    RESET_ = 1;
    wait_ms(120);
}

void ILI9163::lcdWriteCommand(uint8_t address)
{
    uint8_t i;

    CS_ = 0;
    A0_ = 0;
    for(i=0;i<8;i++){
        if(address & 128)SDA_= 1; else SDA_ = 0;
        SCK_ = 1;
        address <<= 1;
        SCK_ = 0;
    }
    wait_us(1);
    CS_ = 1;
}

void ILI9163::lcdWriteParameter(uint8_t parameter)
{  
    uint8_t i;

    CS_ = 0;
    A0_ = 1;
    for(i=0;i<8;i++){
        if(parameter & 128)SDA_= 1; else SDA_ = 0;
        SCK_ = 1;
        parameter <<= 1;
        SCK_ = 0;
    }
    wait_us(1);
    CS_ = 1;
}
 
void ILI9163::lcdWriteData(uint8_t dataByte1, uint8_t dataByte2)
{  
    uint8_t i;

    CS_ = 0;
    A0_ = 1;
    for(i=0;i<8;i++){
        if(dataByte1 & 128)SDA_= 1; else SDA_ = 0;
        SCK_ = 1;
        dataByte1 <<= 1;
        SCK_ = 0;
    }
    wait_us(1);
    for(i=0;i<8;i++){
        if(dataByte2 & 128)SDA_= 1; else SDA_ = 0;
        SCK_ = 1;
        dataByte2 <<= 1;
        SCK_ = 0;
    }
    wait_us(1);
    CS_ = 1;
}

// Initialise the display with the require screen orientation
void ILI9163::lcdInitialise(uint8_t orientation)
{   
    CS_ = 1;
    SCK_ = 0;
    RESET_ = 1;
   
    // Hardware reset the LCD
    lcdReset();
    
    lcdWriteCommand(EXIT_SLEEP_MODE);
    wait_ms(5); // Wait for the screen to wake up
    
    lcdWriteCommand(SET_PIXEL_FORMAT);
    lcdWriteParameter(0x05); // 16 bits per pixel
   
    lcdWriteCommand(SET_GAMMA_CURVE);
    lcdWriteParameter(0x04); // Select gamma curve 3
    
    lcdWriteCommand(GAM_R_SEL);
    lcdWriteParameter(0x01); // Gamma adjustment enabled
    
    lcdWriteCommand(POSITIVE_GAMMA_CORRECT);
    lcdWriteParameter(0x3f); // 1st Parameter
    lcdWriteParameter(0x25); // 2nd Parameter
    lcdWriteParameter(0x1c); // 3rd Parameter
    lcdWriteParameter(0x1e); // 4th Parameter
    lcdWriteParameter(0x20); // 5th Parameter
    lcdWriteParameter(0x12); // 6th Parameter
    lcdWriteParameter(0x2a); // 7th Parameter
    lcdWriteParameter(0x90); // 8th Parameter
    lcdWriteParameter(0x24); // 9th Parameter
    lcdWriteParameter(0x11); // 10th Parameter
    lcdWriteParameter(0x00); // 11th Parameter
    lcdWriteParameter(0x00); // 12th Parameter
    lcdWriteParameter(0x00); // 13th Parameter
    lcdWriteParameter(0x00); // 14th Parameter
    lcdWriteParameter(0x00); // 15th Parameter
     
    lcdWriteCommand(NEGATIVE_GAMMA_CORRECT);
    lcdWriteParameter(0x20); // 1st Parameter
    lcdWriteParameter(0x20); // 2nd Parameter
    lcdWriteParameter(0x20); // 3rd Parameter
    lcdWriteParameter(0x20); // 4th Parameter
    lcdWriteParameter(0x05); // 5th Parameter
    lcdWriteParameter(0x00); // 6th Parameter
    lcdWriteParameter(0x15); // 7th Parameter
    lcdWriteParameter(0xa7); // 8th Parameter
    lcdWriteParameter(0x3d); // 9th Parameter
    lcdWriteParameter(0x18); // 10th Parameter
    lcdWriteParameter(0x25); // 11th Parameter
    lcdWriteParameter(0x2a); // 12th Parameter
    lcdWriteParameter(0x2b); // 13th Parameter
    lcdWriteParameter(0x2b); // 14th Parameter
    lcdWriteParameter(0x3a); // 15th Parameter
    
    lcdWriteCommand(FRAME_RATE_CONTROL1);
    lcdWriteParameter(0x08); // DIVA = 8
    lcdWriteParameter(0x08); // VPA = 8
    
    lcdWriteCommand(DISPLAY_INVERSION);
    lcdWriteParameter(0x07); // NLA = 1, NLB = 1, NLC = 1 (all on Frame Inversion)
   
    lcdWriteCommand(POWER_CONTROL1);
    lcdWriteParameter(0x0a); // VRH = 10:  GVDD = 4.30
    lcdWriteParameter(0x02); // VC = 2: VCI1 = 2.65
      
    lcdWriteCommand(POWER_CONTROL2);
    lcdWriteParameter(0x02); // BT = 2: AVDD = 2xVCI1, VCL = -1xVCI1, VGH = 5xVCI1, VGL = -2xVCI1

    lcdWriteCommand(VCOM_CONTROL1);
    lcdWriteParameter(0x50); // VMH = 80: VCOMH voltage = 4.5
    lcdWriteParameter(0x5b); // VML = 91: VCOML voltage = -0.225
    
    lcdWriteCommand(VCOM_OFFSET_CONTROL);
    lcdWriteParameter(0x40); // nVM = 0, VMF = 64: VCOMH output = VMH, VCOML output = VML   
    
    lcdWriteCommand(SET_COLUMN_ADDRESS);
    lcdWriteParameter(0x00); // XSH
    lcdWriteParameter(0x00); // XSL
    lcdWriteParameter(0x00); // XEH
    lcdWriteParameter(0x7f); // XEL (128 pixels x)
   
    lcdWriteCommand(SET_PAGE_ADDRESS);
    lcdWriteParameter(0x00);
    lcdWriteParameter(0x00);
    lcdWriteParameter(0x00);
    lcdWriteParameter(0x7f); // 128 pixels y
    
    // Select display orientation
    lcdWriteCommand(SET_ADDRESS_MODE);
    lcdWriteParameter(orientation);

    // Set the display to on
    lcdWriteCommand(SET_DISPLAY_ON);
    lcdWriteCommand(WRITE_MEMORY_START);
}

// LCD graphics functions -----------------------------------------------------------------------------------

void ILI9163::lcdClearDisplay(uint16_t colour)
{
    uint16_t pixel;
  
    // Set the column address to 0-127
    lcdWriteCommand(SET_COLUMN_ADDRESS);
    lcdWriteParameter(0x00);
    lcdWriteParameter(0x00);
    lcdWriteParameter(0x00);
    lcdWriteParameter(0x7f);

    // Set the page address to 0-127
    lcdWriteCommand(SET_PAGE_ADDRESS);
    lcdWriteParameter(0x00);
    lcdWriteParameter(0x00);
    lcdWriteParameter(0x00);
    lcdWriteParameter(0x7f);
  
    // Plot the pixels
    lcdWriteCommand(WRITE_MEMORY_START);
    for(pixel = 0; pixel < 16385; pixel++) lcdWriteData(colour >> 8, colour);
}

void ILI9163::lcdPlot(uint8_t x, uint8_t y, uint16_t colour)
{
    // Horizontal Address Start Position
    lcdWriteCommand(SET_COLUMN_ADDRESS);
    lcdWriteParameter(0x00);
    lcdWriteParameter(x);
    lcdWriteParameter(0x00);
    lcdWriteParameter(0x7f);
  
    // Vertical Address end Position
    lcdWriteCommand(SET_PAGE_ADDRESS);
    lcdWriteParameter(0x00);
    lcdWriteParameter(y);
    lcdWriteParameter(0x00);
    lcdWriteParameter(0x7f);

    // Plot the point
    lcdWriteCommand(WRITE_MEMORY_START);
    lcdWriteData(colour >> 8, colour);
}

// Draw a line from x0, y0 to x1, y1
// Note:    This is a version of Bresenham's line drawing algorithm
//          It only draws lines from left to right!
void ILI9163::lcdLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t colour)
{
    int16_t dy = y1 - y0;
    int16_t dx = x1 - x0;
    int16_t stepx, stepy;

    if (dy < 0)
    {
        dy = -dy; stepy = -1; 
    }
    else stepy = 1; 

    if (dx < 0)
    {
        dx = -dx; stepx = -1; 
    }
    else stepx = 1; 

    dy <<= 1;                           // dy is now 2*dy
    dx <<= 1;                           // dx is now 2*dx
 
    lcdPlot(x0, y0, colour);

    if (dx > dy) {
        int fraction = dy - (dx >> 1);  // same as 2*dy - dx
        while (x0 != x1)
        {
            if (fraction >= 0)
            {
                y0 += stepy;
                fraction -= dx;         // same as fraction -= 2*dx
            }

            x0 += stepx;
            fraction += dy;                 // same as fraction -= 2*dy
            lcdPlot(x0, y0, colour);
        }
    }
    else
    {
        int fraction = dx - (dy >> 1);
        while (y0 != y1)
        {
            if (fraction >= 0)
            {
                x0 += stepx;
                fraction -= dy;
            }

            y0 += stepy;
            fraction += dx;
            lcdPlot(x0, y0, colour);
        }
    }
}

// Draw a rectangle between x0, y0 and x1, y1
void ILI9163::lcdRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t colour)
{
    lcdLine(x0, y0, x0, y1, colour);
    lcdLine(x0, y1, x1, y1, colour);
    lcdLine(x1, y0, x1, y1, colour);
    lcdLine(x0, y0, x1, y0, colour);
}

// Draw a filled rectangle
// Note:    y1 must be greater than y0  and x1 must be greater than x0
//          for this to work
void ILI9163::lcdFilledRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t colour)
{
    uint16_t pixels;
            
    // To speed up plotting we define a x window with the width of the 
    // rectangle and then just output the required number of bytes to
    // fill down to the end point
    
    lcdWriteCommand(SET_COLUMN_ADDRESS); // Horizontal Address Start Position
    lcdWriteParameter(0x00);
    lcdWriteParameter(x0);
    lcdWriteParameter(0x00);
    lcdWriteParameter(x1);
  
    lcdWriteCommand(SET_PAGE_ADDRESS); // Vertical Address end Position
    lcdWriteParameter(0x00);
    lcdWriteParameter(y0);
    lcdWriteParameter(0x00);
    lcdWriteParameter(0x7f);
        
    lcdWriteCommand(WRITE_MEMORY_START);
    
    for (pixels = 0; pixels < (((x1 - x0) + 1) * ((y1 - y0) + 1)); pixels++)
        lcdWriteData(colour >> 8, colour);;
}

// Draw a circle
// Note:    This is another version of Bresenham's line drawing algorithm.
//          There's plenty of documentation on the web if you are curious
//          how this works.
void ILI9163::lcdCircle(int16_t xCentre, int16_t yCentre, int16_t radius, uint16_t colour)
{
    int16_t x = 0, y = radius;
    int16_t d = 3 - (2 * radius);
 
    while(x <= y)
    {
        lcdPlot(xCentre + x, yCentre + y, colour);
        lcdPlot(xCentre + y, yCentre + x, colour);
        lcdPlot(xCentre - x, yCentre + y, colour);
        lcdPlot(xCentre + y, yCentre - x, colour);
        lcdPlot(xCentre - x, yCentre - y, colour);
        lcdPlot(xCentre - y, yCentre - x, colour);
        lcdPlot(xCentre + x, yCentre - y, colour);
        lcdPlot(xCentre - y, yCentre + x, colour);

        if (d < 0) d += (4 * x) + 6;
        else
        {
            d += (4 * (x - y)) + 10;
            y -= 1;
        }

        x++;
    }
}

// LCD text manipulation functions --------------------------------------------------------------------------

// die Schriftgröße definieren
void ILI9163::set_font(unsigned char* f) {
    font = f;
    font_bp_char = font[0];                   // Anzal der Bytes pro Zeichen
    font_hor = font[1];                       // get hor size of font
    font_vert = font[2];                      // get vert size of font
    font_bp_line = font[3];                   // bytes per line
}

// Plot a character at the specified x, y co-ordinates (top left hand corner of character)
void ILI9163::lcdPutCh(unsigned char c, uint8_t x, uint8_t y, uint16_t fgColour, uint16_t bgColour)
{
    uint8_t row, column;
    uint16_t sign;
    unsigned char z,w;
    unsigned int j,i,b;
    
    if ((c < 31) || (c > 127)) return;   // auf druckbares Zeichen prüfen   
    
    // To speed up plotting we define a x window of 6 pixels and then
    // write out one row at a time.  This means the LCD will correctly
    // update the memory pointer saving us a good few bytes
    
    lcdWriteCommand(SET_COLUMN_ADDRESS); // Horizontal Address Start Position
    lcdWriteParameter(0x00);
    lcdWriteParameter(x);
    lcdWriteParameter(0x00);
    lcdWriteParameter(x+font_hor-1);  // x + w -1 >> XEnd
  
    lcdWriteCommand(SET_PAGE_ADDRESS); // Vertical Address end Position
    lcdWriteParameter(0x00);
    lcdWriteParameter(y);
    lcdWriteParameter(0x00);
    lcdWriteParameter(y+font_vert-1);  // y + h -1 >> YEnd  0x7F
        
    lcdWriteCommand(WRITE_MEMORY_START);
    
    sign = (((c -32) * font_bp_char) + 4); // start of char bitmap
  
    // Plot the font data
    for (j=0; j<font_vert; j++) {      //  vert line
        for (i=0; i<font_hor; i++) {   //  horz line
            z =  font[sign + (font_bp_line * i) + ((j & 0xF8) >> 3)+1];
            b = 1 << (j & 0x07);
            if (( z & b ) == 0x00)  lcdWriteData(fgColour >> 8, fgColour);  
            else                    lcdWriteData(bgColour >> 8, bgColour);
        }
    }
    
/*     
    // Plot the font data
    for (row = 0; row < font_vert; row++)
    {
        for (column = 0; column < font_hor; column++)
        {
            if ((font[sign + column]) & (1 << row))
                lcdWriteData(fgColour >> 8, fgColour);
            else lcdWriteData(bgColour >> 8, bgColour);
        }
    }
*/
}

// Plot a string of characters to the LCD
void ILI9163::lcdPutS(const char *string, uint8_t x, uint8_t y, uint16_t fgColour, uint16_t bgColour)
{
    uint8_t origin = x;

    for (uint8_t characterNumber = 0; characterNumber < strlen(string); characterNumber++)
    {
        // Check if we are out of bounds and move to 
        // the next line if we are
        if (x > (127 - font_vert))
        {
            x = origin;
            y += font_vert;
        }

        // If we move past the bottom of the screen just exit
        if (y > (127 - font_hor)) break;

        // Plot the current character
        lcdPutCh(string[characterNumber], x, y, fgColour, bgColour);
        x += font_hor;
    }
}