TO CHECKOUT

Dependencies:   mbed

lcd.c

Committer:
chrish
Date:
2014-12-02
Revision:
1:6a77fc8e1389
Parent:
0:785c2b62c4d1

File content as of revision 1:6a77fc8e1389:

#include <stdarg.h>
#include "lcd.h"

void lcd_init(lcd_t * lcd, spi_t * spi, PinName CS, PinName CD) {
    //Prepare pins
    gpio_init_out(&(lcd->CS), CS );
    gpio_init_out(&(lcd->CD), CD);

    gpio_write(&(lcd->CS), 1);
    gpio_write(&(lcd->CD), 1);
    //
    
    lcd->mode = PORTRAIT;
    //lcd->mode = LANDSCAPE;
    lcd->spi = spi;
        
    wait_ms(500);
    lcd_writeCommand(lcd, 0x01);
    wait_ms(200);
    

    lcd_writeCommand(lcd, 0xCF);
    lcd_writeData(lcd, 0x00);
    lcd_writeData(lcd, 0x8B);
    lcd_writeData(lcd, 0x30);
    
    lcd_writeCommand(lcd, 0xED);
    lcd_writeData(lcd, 0x67);
    lcd_writeData(lcd, 0x03);
    lcd_writeData(lcd, 0x12);
    lcd_writeData(lcd, 0x81);

    lcd_writeCommand(lcd, 0xE8);
    lcd_writeData(lcd, 0x85);
    lcd_writeData(lcd, 0x10);
    lcd_writeData(lcd, 0x7A);

    lcd_writeCommand(lcd, 0xCB);
    lcd_writeData(lcd, 0x39);
    lcd_writeData(lcd, 0x2C);
    lcd_writeData(lcd, 0x00);
    lcd_writeData(lcd, 0x34);
    lcd_writeData(lcd, 0x02);

    lcd_writeCommand(lcd, 0xF7);
    lcd_writeData(lcd, 0x20);

    lcd_writeCommand(lcd, 0xEA);
    lcd_writeData(lcd, 0x00);
    lcd_writeData(lcd, 0x00);

    lcd_writeCommand(lcd, 0xC0); /* Power control */
    lcd_writeData(lcd, 0x1B); /* VRH[5:0] */

    lcd_writeCommand(lcd, 0xC1); /* Power control */
    lcd_writeData(lcd, 0x10); /* SAP[2:0];BT[3:0] */

    lcd_writeCommand(lcd, 0xC5); /* VCM control */
    lcd_writeData(lcd, 0x3F);
    lcd_writeData(lcd, 0x3C);

    lcd_writeCommand(lcd, 0xC7); /* VCM control2 */
    lcd_writeData(lcd, 0xB7);

    lcd_writeCommand(lcd, 0x36); /* Memory Access Control */
    lcd_writeData(lcd, 0x08);

    lcd_writeCommand(lcd, 0x3A);
    lcd_writeData(lcd, 0x55);

    lcd_writeCommand(lcd, 0xB1);
    lcd_writeData(lcd, 0x00);
    lcd_writeData(lcd, 0x1B);

    lcd_writeCommand(lcd, 0xB6); /* Display Function Control */
    lcd_writeData(lcd, 0x0A);
    lcd_writeData(lcd, 0xA2);

    lcd_writeCommand(lcd, 0xF2); /* 3Gamma Function Disable */
    lcd_writeData(lcd, 0x00);

    lcd_writeCommand(lcd, 0x26); /* Gamma curve selected */
    lcd_writeData(lcd, 0x01);

    lcd_writeCommand(lcd, 0xE0); /* Set Gamma */
    lcd_writeData(lcd, 0x0F);
    lcd_writeData(lcd, 0x2A);
    lcd_writeData(lcd, 0x28);
    lcd_writeData(lcd, 0x08);
    lcd_writeData(lcd, 0x0E);
    lcd_writeData(lcd, 0x08);
    lcd_writeData(lcd, 0x54);
    lcd_writeData(lcd, 0xA9);
    lcd_writeData(lcd, 0x43);
    lcd_writeData(lcd, 0x0A);
    lcd_writeData(lcd, 0x0F);
    lcd_writeData(lcd, 0x00);
    lcd_writeData(lcd, 0x00);
    lcd_writeData(lcd, 0x00);
    lcd_writeData(lcd, 0x00);

    lcd_writeCommand(lcd, 0xE1); /* Set Gamma */
    lcd_writeData(lcd, 0x00);
    lcd_writeData(lcd, 0x15);
    lcd_writeData(lcd, 0x17);
    lcd_writeData(lcd, 0x07);
    lcd_writeData(lcd, 0x11);
    lcd_writeData(lcd, 0x06);
    lcd_writeData(lcd, 0x2B);
    lcd_writeData(lcd, 0x56);
    lcd_writeData(lcd, 0x3C);
    lcd_writeData(lcd, 0x05);
    lcd_writeData(lcd, 0x10);
    lcd_writeData(lcd, 0x0F);
    lcd_writeData(lcd, 0x3F);
    lcd_writeData(lcd, 0x3F);
    lcd_writeData(lcd, 0x0F);

    lcd_writeCommand(lcd, 0x11); /* Exit Sleep */
    wait_ms(120);
    lcd_writeCommand(lcd, 0x29);
    lcd_fillScreen(lcd);
}

void lcd_cs(lcd_t * lcd, int value) {
    while(spi_busy(lcd->spi));
    gpio_write(&(lcd->CS), value);
}

void lcd_cd(lcd_t * lcd, int value) {
    while(spi_busy(lcd->spi));
    gpio_write(&(lcd->CD), value);
}

void lcd_setMode(lcd_t * lcd, lcd_mode mode) {
    lcd->mode = mode;
}

void lcd_writeCommand(lcd_t * lcd, int value) {  
    lcd_cd(lcd, 0);
    lcd_cs(lcd, 0);
    
    spi_master_write(lcd->spi, value);
    
    lcd_cs(lcd, 1);
}

void lcd_writeData(lcd_t * lcd, int value) {
    lcd_cd(lcd, 1);
    lcd_cs(lcd, 0);
    
    spi_master_write(lcd->spi, value);
    
    lcd_cs(lcd, 1);
}

void lcd_writeData16(lcd_t * lcd, int value) {
    int data1 = value >> 8;
    int data2 = value & 0xff;
    lcd_cd(lcd, 1);
    lcd_cs(lcd, 0);
    
    spi_master_write(lcd->spi, data1);
    spi_master_write(lcd->spi, data2);
    
    lcd_cs(lcd, 1);
}

void lcd_setColumn(lcd_t * lcd, int start, int end) {
    lcd_writeCommand(lcd, 0x2A);  /* column command address */
    lcd_writeData16(lcd, start);
    lcd_writeData16(lcd, end);
}

void lcd_setPage(lcd_t * lcd, int start, int end) {
    lcd_writeCommand(lcd, 0x2B);  /* column command address */
    lcd_writeData16(lcd, start);
    lcd_writeData16(lcd, end);
}

void lcd_setXY(lcd_t * lcd, int x, int y) {
    lcd_setColumn(lcd, x, x);
    lcd_setPage(lcd, y, y);
    lcd_writeCommand(lcd, 0x2c);
}

void lcd_setPixel(lcd_t * lcd, int x, int y, int color) {
    lcd_setXY(lcd, x, y);
    lcd_writeData16(lcd, color);
}

void lcd_setLandscape(lcd_t * lcd) {
    lcd->mode = LANDSCAPE;
}

void lcd_setPortrait(lcd_t * lcd) {
    lcd->mode = PORTRAIT;
}

void lcd_fillScreen(lcd_t * lcd) {
    lcd_setColumn(lcd, 0, 239);
    lcd_setPage(lcd, 0, 319);
    lcd_writeCommand(lcd, 0x2c);  /* start to write to display ram */

    lcd_cd(lcd, 1);
    lcd_cs(lcd, 0);
    for(int i = 0; i < 76800; i++)
    {
        spi_master_write(lcd->spi, 0xFF); 
        spi_master_write(lcd->spi, 0xFF); 
    }
    while(spi_busy(lcd->spi));
    lcd_cs(lcd, 1);
}

void lcd_drawLine(lcd_t * lcd, int x0, int y0, int x1, int y1, int color) {
    if (x0 == x1) {
        lcd_drawVerticalLine(lcd, x0, y0, y1-y0, color);
    }else if (y0 == y1) {
        lcd_drawHorizontalLine(lcd, x0, y0, x1-x0, color);
    }else {  
        if(lcd->mode == LANDSCAPE) {
            y0 = y0^x0;
            x0 = y0^x0;
            y0 = y0^x0;
            
            y1 = y1^x1;
            x1 = y1^x1;
            y1 = y1^x1;
            
            x0 = 239-(x0);
            x1 = 239-(x1);
        }
        int x = x1-x0;
        int y = y1-y0;
        int dx = abs(x), sx = x0 < x1 ? 1 : -1;
        int dy = -abs(y), sy = y0 < y1 ? 1 : -1;
        int err = dx + dy, e2;                          /* error value e_xy */

        lcd_setPixel(lcd, x0, y0, color);
    
        do
        {
            e2 = 2*err;
            
            if (e2 >= dy) {                              /* e_xy+e_x > 0 */
                err += dy; x0 += sx;
            }
            
            if (e2 <= dx) {                              /* e_xy+e_y < 0 */
                err += dx; y0 += sy;
            }
            
            lcd_setPixel(lcd, x0, y0, color);
        } while (x0 != x1 || y0 != y1);
    }
}

void lcd_drawVerticalLine(lcd_t * lcd, int x, int y, int length, int color) {
    if(lcd->mode == LANDSCAPE) {
        y = y^x;
        x = y^x;
        y = y^x;
        x = 239-(x);
    }

    lcd_setColumn(lcd, x, x);
    lcd_setPage(lcd, y, y + length);
    
    lcd_writeCommand(lcd, 0x2c);
    for(int i=0; i<length; i++)
        lcd_writeData16(lcd, color);
}

void lcd_drawHorizontalLine(lcd_t * lcd, int x, int y, int length, int color) {
    if(lcd->mode == LANDSCAPE) {
        y = y^x;
        x = y^x;
        y = y^x;
        x = 239-x;
        lcd_setColumn(lcd, x - length, x);
    }else {
        lcd_setColumn(lcd, x, x + length);
    }
    
    lcd_setPage(lcd, y, y);
    
    lcd_writeCommand(lcd, 0x2c);
    for(int i=0; i<length; i++)
        lcd_writeData16(lcd, color);
}

void lcd_drawRectangle(lcd_t * lcd , int x0, int y0, int x1, int y1, int color) {
    if(x0>x1) {
        x0=x0^x1;
        x1=x0^x1;
        x0=x0^x1;
    }
    
    if(y0>y1) {
        y0=y0^y1;
        y1=y0^y1;
        y0=y0^y1;
    }  
    
    lcd_drawVerticalLine(lcd, x0, y0, y1-y0, color);
    lcd_drawVerticalLine(lcd, x0, y1, y1-y0, color);
    lcd_drawHorizontalLine(lcd, x0, y0, x1-x0, color);
    lcd_drawHorizontalLine(lcd, x1, y0, x1-x0, color);
}

void lcd_fillRectangle(lcd_t * lcd, int x0, int y0, int length, int width, int color) {    
    int XY=0;
    
    int x1 = x0+length;
    int y1 = y0+width;

    if(x0 > x1)
    {
        x0 = x0^x1;
        x1 = x0^x1;
        x0 = x0^x1;
    }
    
    if(y0 > y1)
    {
        y0 = y0^y1;
        y1 = y0^y1;
        y0 = y0^y1;
    }
    
    if(lcd->mode == LANDSCAPE) {
        y0 = y0^x0;
        x0 = y0^x0;
        y0 = y0^x0;
        
        y1 = y1^x1;
        x1 = y1^x1;
        y1 = y1^x1;
        
        x0 = x0^x1;
        x1 = x0^x1;
        x0 = x0^x1;
        x0 = 239-x0;
        x1 = 239-x1;
    }
    
    //XL = constrain(XL, MIN_X, MAX_X);
    //x1 = constrain(x1, MIN_X, MAX_X);
    //y0 = constrain(y0, MIN_Y, MAX_Y);
    //y1 = constrain(y1, MIN_Y, MAX_Y);

    XY = (x1-x0+1);
    XY = XY*(y1-y0+1);

    lcd_setColumn(lcd, x0, x1);
    lcd_setPage(lcd, y0, y1);
    lcd_writeCommand(lcd, 0x2c); /* start to write to display ram */
   
    for(int i = 0; i < XY; i++)
    {
        lcd_writeData16(lcd, color);
    }
}

void lcd_fillSprite(lcd_t * lcd, int x0, int y0, int length, int width, short int *pColor) {    
    int XY=0;
    
    int x1 = x0+length;
    int y1 = y0+width;
    short int color;
    if(x0 > x1)
    {
        x0 = x0^x1;
        x1 = x0^x1;
        x0 = x0^x1;
    }
    
    if(y0 > y1)
    {
        y0 = y0^y1;
        y1 = y0^y1;
        y0 = y0^y1;
    }
    
    if(lcd->mode == LANDSCAPE) {
        y0 = y0^x0;
        x0 = y0^x0;
        y0 = y0^x0;
        
        y1 = y1^x1;
        x1 = y1^x1;
        y1 = y1^x1;
        
        x0 = x0^x1;
        x1 = x0^x1;
        x0 = x0^x1;
        x0 = 239-x0;
        x1 = 239-x1;
    }
    
    //XL = constrain(XL, MIN_X, MAX_X);
    //x1 = constrain(x1, MIN_X, MAX_X);
    //y0 = constrain(y0, MIN_Y, MAX_Y);
    //y1 = constrain(y1, MIN_Y, MAX_Y);

    XY = (x1-x0+1);
    XY = XY*(y1-y0+1);

    lcd_setColumn(lcd, x0, x1);
    lcd_setPage(lcd, y0, y1);
    lcd_writeCommand(lcd, 0x2c); /* start to write to display ram */
   
#if 1 /* speed up */
    lcd_cd(lcd, 1);
    lcd_cs(lcd, 0);
    for(int i = 0; i < XY; i++)
    {
        color = *pColor++;
        spi_master_write(lcd->spi, (color >> 8));
        spi_master_write(lcd->spi, (color & 0xff));
    }
    lcd_cs(lcd, 1);
#else
    for(int i = 0; i < XY; i++)
    {
        lcd_writeData16(lcd, *color++);
    }
#endif
}


void lcd_drawTraingle(lcd_t * lcd, int x0, int y0, int x1, int y1, int x2, int y2, int color)
{
    lcd_drawLine(lcd, x0, y0, x1, y1, color);
    lcd_drawLine(lcd, x0, y0, x2, y2, color);
    lcd_drawLine(lcd, x1, y1, x2, y2, color);
}

void lcd_fillTraingle(lcd_t * lcd, int x0, int y0, int x1, int y1, int x2, int y2, int color)
{
    if(lcd->mode == LANDSCAPE) {
        y0 = y0^x0;
        x0 = y0^x0;
        y0 = y0^x0;

        y1 = y1^x1;
        x1 = y1^x1;
        y1 = y1^x1;

        y2 = y2^x2;
        x2 = y2^x2;
        y2 = y2^x2;
        
        x0 = 239-x0;
        x1 = 239-x1;
        x2 = 239-x2;
    }
    
    if(y0 > y1) {
        y0 = y0^y1;
        y1 = y0^y1;
        y0 = y0^y1;
        
        x0 = x0^x1;
        x1 = x0^x1;
        x0 = x0^x1;
    }
    
    if(y1 > y2) {
        y2 = y2^y1;
        y1 = y2^y1;
        y2 = y2^y1;
        
        x2 = x2^x1;
        x1 = x2^x1;
        x2 = x2^x1;
    }
    
    if(y0 > y1) {
        y0 = y0^y1;
        y1 = y0^y1;
        y0 = y0^y1;
        
        x0 = x0^x1;
        x1 = x0^x1;
        x0 = x0^x1;
    }
    
    if(x1 > x2) {
        x1 = x1^x2;
        x2 = x1^x2;
        x1 = x1^x2;
        
        y1 = y1^y2;
        y2 = y1^y2;
        y1 = y1^y2;
    }

    int xl = x0;
    int yl = y0;
    int xle = x1;
    int yle = y1;
    int dxl = abs(x1-x0), sxl = x0 < x1 ? 1 : -1;
    int dyl = -abs(y1-y0), syl = y0 < y1 ? 1 : -1;
    int errl = dxl + dyl, e2l;

    int xr = x0;
    int yr = y0;
    int xre = x2;
    int yre = y2;
    int dxr = abs(x2-x0), sxr = x0 < x2 ? 1 : -1;
    int dyr = -abs(y2-y0), syr = y0 < y2 ? 1 : -1;
    int errr = dxr + dyr, e2r;

    int xlp = xl;
    int xrp = xr;

    do {
        if(yl <= yr && (xl != xle || yl != yle)) {
            e2l = 2*errl;
            if (e2l >= dyl && xl != xle) {
                errl += dyl; xl += sxl;
            }

            if (e2l <= dxl && yl != yle) {
                errl += dxl; yl += syl;

                if(yl == yr) {
                    //lcd_drawHorizontalLine(lcd, xlp, yl-1, xrp-xlp+1, color);
                    
                    lcd_setColumn(lcd, xlp, xrp);
                    lcd_setPage(lcd, yl-1, yl-1);
                    lcd_writeCommand(lcd, 0x2c);
                    for(int i=0; i < xrp-xlp; i++)
                        lcd_writeData16(lcd, color);
                    
                    xlp = xl;
                    xrp = xr;
                }
            }else {
                if(sxl < 0) {
                    xlp = xl;
                }
            }
        }else if (yle < yre) {
            dxl = abs(xl-x2);
            sxl = xl < x2 ? 1 : -1;
            dyl = -abs(yl-y2);
            syl = 1;
            xle = x2;
            yle = y2;
            errl = dxl + dyl;
        }

        if(yr <= yl && (xr != xre || yr != yre)) {
            e2r = 2*errr;
            if (e2r >= dyr && xr != xre) {
                errr += dyr; xr += sxr;
            }

            if (e2r <= dxr && yr != yre) {
                errr += dxr; yr += syr;

                if(yl==yr) {
                    //lcd_drawHorizontalLine(lcd, xlp, yl-1, xrp-xlp+1, color);
                        
                    lcd_setColumn(lcd, xlp, xrp);
                    lcd_setPage(lcd, yl-1, yl-1);
                    lcd_writeCommand(lcd, 0x2c);
                    for(int i=0; i < xrp-xlp; i++)
                        lcd_writeData16(lcd, color);
                    
                    xlp = xl;
                    xrp = xr;
                }
            }else {
                if(sxr > 0) {
                    xrp = xr;
                }
            }

        }else if (yre < yle) {
            dxr = abs(xr-x1);
            dyr = -abs(yr-y1);
            sxr = xr < x1 ? 1 : -1;
            syr = 1;
            xre = x1;
            yre = y1;
            errr = dxr + dyr;
        }
    }while ((xl < xle || yl < yle || xr < xre || yr < yre));

    lcd_setColumn(lcd, xlp, xrp);
    lcd_setPage(lcd, yl, yl);
    lcd_writeCommand(lcd, 0x2c);
    for(int i=0; i < xrp-xlp; i++)
        lcd_writeData16(lcd, color);
}

void lcd_drawCircle(lcd_t * lcd, int x, int y, int radius, int color)
{
    if(lcd->mode==LANDSCAPE) {
        y=x^y;
        x=x^y;
        y=x^y;
        x=239-x;
    }

    int dx = -radius, dy = 0, err = 2-2*radius, e2;
    do {
        lcd_setPixel(lcd, x-dx, y+dy, color);
        lcd_setPixel(lcd, x+dx, y+dy, color);
        lcd_setPixel(lcd, x+dx, y-dy, color);
        lcd_setPixel(lcd, x-dx, y-dy, color);
        e2 = err;
        if (e2 <= dy) {
            err += ++dy*2+1;
            if (-dx == dy && e2 <= dx) e2 = 0;
        }
        if (e2 > dx) err += ++dx*2+1;
    } while (dx <= 0);
}

void lcd_drawChar(lcd_t * lcd, char c, int x, int y, uint16_t size, uint16_t color)
{
    if(!(c >= 32) && (c <= 127)) {
        c = '?'-32;
    }
    
    for (int i =0; i < FONT_X; i++ ) {
        uint8_t temp = simpleFont[c-32][i];
        for(uint8_t f = 0; f < 8; f++) {
            if((temp>>f)&0x01) {
                lcd_fillRectangle(lcd, x+i*size, y+f*size, size, size, color);
                }
#if 1 /* Hintergrund ebenfalls setzen */
            else{
                lcd_fillRectangle(lcd, x+i*size, y+f*size, size, size, WHITE);
                }
#endif
        }
    }
}

void lcd_drawString(lcd_t * lcd, char * ca, int x, int y, uint16_t size, uint16_t color)
{
    while(*ca) {
        lcd_drawChar(lcd, *ca, x, y, size, color);
        *ca++;

        if(x < MAX_X) {
            x += FONT_SPACE*size; /* Move cursor right */
        }
    }
}

uint8_t lcd_drawNumber(lcd_t * lcd, long long_num, int x, int y, uint16_t size, uint16_t color)
{
    uint8_t char_buffer[10] = "";
    uint8_t i = 0;
    uint8_t f = 0;

    if(long_num < 0) {
        f = 1;
        lcd_drawChar(lcd, '-', x, y, size, color);
        long_num = -long_num;
        
        if(x < MAX_X) {
            x += FONT_SPACE*size; /* Move cursor right */
        }
    }else if(long_num == 0) {
        f = 1;
        lcd_drawChar(lcd, '0', x, y, size, color);
        return f; //<-- Bullshit -->
        
        //if(x < MAX_X) {
        //    x += FONT_SPACE*size; /* Move cursor right */
        //}
    }

    while (long_num > 0) {
        char_buffer[i++] = long_num % 10;
        long_num /= 10;
    }

    f = f+i;
    
    for(; i > 0; i--) {
        lcd_drawChar(lcd, '0' + char_buffer[i - 1], x, y, size, color);
        
        if(x < MAX_X) {
            x += FONT_SPACE*size; /* Move cursor right */
        }
    }
    
    return f;
}

uint8_t lcd_drawFloat(lcd_t * lcd, float floatNumber, uint8_t decimal, int x, int y, uint16_t size, uint16_t color)
{
    uint16_t temp = 0;
    float decy = 0.0;
    float rounding = 0.5;
    uint8_t f = 0;
    
    if(floatNumber < 0.0)
    {
        lcd_drawChar(lcd, '-', x, y, size, color);
        floatNumber = -floatNumber;
        if(x < MAX_X)
        {
            x += FONT_SPACE * size;                                       /* Move cursor right            */
        }
        f = 1;
    }
    
    for(uint8_t i = 0; i < decimal; ++i)
    {
        rounding /= 10.0;
    }
    floatNumber += rounding;

    temp = (uint16_t)floatNumber;
    uint8_t howlong = lcd_drawNumber(lcd, temp, x, y, size, color);
    f += howlong;
    
    if((x+8*size*howlong) < MAX_X)
    {
        x += FONT_SPACE * size * howlong;                                   /* Move cursor right            */
    }

    if(decimal > 0)
    {
        lcd_drawChar(lcd, '.', x, y, size, color);
        if(x < MAX_X)
        {
            x += FONT_SPACE * size;                                       /* Move cursor right            */
        }
        f += 1;
    }
    
    decy = floatNumber - temp;
                                            /* decimal part,  4             */
    for(uint8_t i = 0; i < decimal; i++)                                      
    {
        decy *= 10;                                                      /* for the next decimal         */
        temp = decy;                                                    /* get the decimal              */
        lcd_drawNumber(lcd, temp, x, y, size, color);
        floatNumber = -floatNumber;
        
        if(x < MAX_X)
        {
            x += FONT_SPACE * size;                                       /* Move cursor right            */
        }
        
        decy -= temp;
    }
    
    f += decimal;
    return f;
}