/*****************************************************************************
 *
 * This document contains proprietary information and except with
 * written permission of Displaytech, Ltd., such information shall
 * not be published or disclosed to others or used for any purpose
 * other than for the operation and maintenance of the equipment
 * and software with which it was procured, and the document shall
 * not be copied in whole or in part.
 *
 * Copyright 2008-2015 Displaytech, Ltd. All Rights Reserved.
 *
 * Created on February 5, 2015, 3:36 PM
 * File:   main.c
 *
 *****************************************************************************/

#include <plib.h>

// Configuration Bits
#pragma config FNOSC    = PRIPLL        // Oscillator Selection
#pragma config FPLLIDIV = DIV_2         // PLL Input Divider (PIC32 Starter Kit: use divide by 2 only)
#pragma config FPLLMUL  = MUL_20        // PLL Multiplier
#pragma config FPLLODIV = DIV_1         // PLL Output Divider
#pragma config FPBDIV   = DIV_1         // Peripheral Clock divisor
#pragma config FWDTEN   = OFF           // Watchdog Timer
#pragma config WDTPS    = PS1           // Watchdog Timer Postscale
#pragma config FCKSM    = CSDCMD        // Clock Switching & Fail Safe Clock Monitor
#pragma config OSCIOFNC = OFF           // CLKO Enable
#pragma config POSCMOD  = XT            // Primary Oscillator
#pragma config IESO     = OFF           // Internal/External Switch-over
#pragma config FSOSCEN  = OFF           // Secondary Oscillator Enable
#pragma config CP       = OFF           // Code Protect
#pragma config BWP      = OFF           // Boot Flash Write Protect
#pragma config PWP      = OFF           // Program Flash Write Protect
#pragma config ICESEL   = ICS_PGx2      // ICE/ICD Comm Channel Select
#pragma config DEBUG    = OFF           // Debugger Disabled

//  The following is used by the main application
#define SYS_FREQ		(80000000)

#define  Lcm_H	 160
#define  Lcm_W	 128

// ------------------------------------------
//      I/O Macros - The following is to implement 3 Wire (9 bit data)
// ------------------------------------------
#define SclHigh()   LATEbits.LATE1=1; // SCL (Called SCL in ILI9163C Datasheet section 6.2.1)
#define SclLow()    LATEbits.LATE1=0;
#define DataHigh()  LATEbits.LATE0=1; // Data (Called SDA in ILI9163C Datasheet section 6.2.1)
#define DataLow()   LATEbits.LATE0=0;
#define CsHigh()    LATDbits.LATD8=1; // Chip Select (Called CSX in ILI9163C Datasheet section 6.2.1)
#define CsLow()     LATDbits.LATD8=0;
#define ResetHigh() LATDbits.LATD5=1; // Display Reset
#define ResetLow()  LATDbits.LATD5=0;

// Note: ILI9163C Datasheets improperly (not traditional) refer to SPI as a Serial Interface
//       Please see timing diagram in 6.2.1 called "3-line Serial Interface Protocol"
void SpiWrite8Bits(unsigned char d);
void WriteCom(unsigned char Com);
void WriteData(unsigned char Data);
void WriteData1(unsigned int Data);
void LCD_InitMain();
void Delay_ms(unsigned int count);
void ResetLCM();
void WriteRGB(unsigned int RGB_Data);
void black(void);
void Gray2(void);
void Gray(void);
void RGB(void);



int main(void)
{
    SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

    PORTSetPinsDigitalOut(IOPORT_D, BIT_8 | BIT_4 | BIT_5);
    PORTSetPinsDigitalOut(IOPORT_E, BIT_0 | BIT_1);

    ResetLCM();
    LCD_InitMain();



    while (1)
    {

        Gray();
        Delay_ms(400);

        black();
        Delay_ms(400);

        WriteRGB(0xFFFF);
        Delay_ms(400);

        RGB();
        Delay_ms(400);

        Gray2();
        Delay_ms(500);
        //  while(SW2);
        WriteRGB(0xF800);
        Delay_ms(400);
        //     while(SW2);
        WriteRGB(0x07e0);
        Delay_ms(400);
        //   while(SW2);
        WriteRGB(0x001f);
        Delay_ms(400);
    }

}

void SpiWrite8Bits(unsigned char d)
{
    unsigned char j;

    for (j = 0; j < 8; j++)
    {
        if (d & 0x80)
        {
            DataHigh();
        }
        else
        {
            DataLow();
        }
        SclHigh();
        SclLow();
        d <<= 1;
    }
}


// Write D/C (Command) + 8 bits data
void WriteCom(unsigned char Com)
{
    CsLow();
    
    // Begin D/C: Command bit
    DataLow(); // Low is for command bit
    SclHigh(); // Bit bang clock, high
    SclLow();  // Bit bang clock, then low
    // End D/C: Command bit
    
    // Write 8 data bits (D7-D0)
    SpiWrite8Bits(Com);
    CsHigh();
}

// Write D/C (Data) + (8 bits)
void WriteData(unsigned char Data)
{
    unsigned char j;

    CsLow();

    // Begin D/C: Data bit
    DataHigh(); // High is for data bit
    SclHigh();  // Bit bang clock, high
    SclLow();   // Bit bang clock, then low
    // End D/C: Data bit
    
    // Write 8 data bits (D7-D0)
    SpiWrite8Bits(Data);
    CsHigh();
}

// Write Data (16 bits)
void WriteData1(unsigned int Data)
{
    WriteData(Data >> 8);
    WriteData((unsigned char) Data);
}


// Initialize LCD
void LCD_InitMain()
{
    WriteCom(0x36);
    WriteData(0xC0);

    WriteCom(0x3a);
    WriteData(0x05);

    WriteCom(0xC0); //Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD
    WriteData(0x08);
    WriteData(0x00);

    WriteCom(0xC1); //Set BT[2:0] for AVDD & VCL & VGH & VGL
    WriteData(0x03);

    WriteCom(0xC2);
    WriteData(0x05);

    WriteCom(0xC5); //Set VMH[6:0] & VML[6:0] for VOMH & VCOML
    WriteData(0x43);
    WriteData(0x43);

    WriteCom(0xC7);
    WriteData(0xC5);

    WriteCom(0xB1);
    WriteData(0x08);
    WriteData(0x14);

    //WriteCom(0xB4);
    //WriteData(0x06);

    WriteCom(0xEC); //Set pumping clock frequence
    WriteData(0x0C);

    WriteCom(0xf2); //Enable Gamma bit
    WriteData(0x01);

    WriteCom(0xE0);
    WriteData(0x3E); //p63
    WriteData(0x1C); //p62
    WriteData(0x29); //p61
    WriteData(0x24); //p59
    WriteData(0x1D); //p57
    WriteData(0x09); //p50
    WriteData(0x50); //p43
    WriteData(0xC8); //p27/36
    WriteData(0x42); //p20
    WriteData(0x19); //p13
    WriteData(0x1C); //p6
    WriteData(0x0F); //p4
    WriteData(0x0E); //p2
    WriteData(0x05); //p1
    WriteData(0x00); //p0
    WriteCom(0xE1);
    WriteData(0x01); //p63
    WriteData(0x06); //p62
    WriteData(0x19); //p61
    WriteData(0x0B); //p59
    WriteData(0x12); //p57
    WriteData(0x10); //p50
    WriteData(0x27); //p43
    WriteData(0x58); //p27/36
    WriteData(0x3A); //p20
    WriteData(0x08); //p13
    WriteData(0x1A); //p6
    WriteData(0x1E); //p4
    WriteData(0x27); //p2
    WriteData(0x3A); //p1
    WriteData(0x3F); //p0
    WriteCom(0x11); //Exit Sleep
    Delay_ms(120);
    WriteCom(0x29); // Display On

    WriteCom(0x2A); //Set Column Address
    WriteData(0x00);
    WriteData(0x00);
    WriteData(0x00);
    WriteData(0x7F);

    WriteCom(0x2B); //Set Page Address
    WriteData(0x00);
    WriteData(0x00);
    WriteData(0x00);
    WriteData(0x9F);

    WriteCom(0x2c);

}


void Delay_ms(unsigned int count)//1ms
{
    int i, j;
    for (i = 0; i < count; i++)
    {
        for (j = 0; j < 8900; j++);
    }
}





//****************************************************//
//********************LCD TEST************************//
//****************************************************//

void ResetLCM()
{
    ResetLow();
    Delay_ms(5);
    ResetHigh();
    Delay_ms(80);
}

void WriteRGB(unsigned int RGB_Data)
{
    unsigned int Row, Column;
    //	AddressSetting();
    for (Row = 0; Row < Lcm_H; Row++)
    {
        for (Column = 0; Column < Lcm_W; Column++)
            WriteData1(RGB_Data);
    }
}

void black(void)
{
    unsigned int i, j;
    //	 AddressSetting();

    for (i = 0; i < Lcm_W; i++)
    {
        WriteData1(0xffff);
    }

    for (j = 0; j < (Lcm_H - 2); j++)
    {
        WriteData1(0xffff);

        for (i = 0; i < (Lcm_W - 2); i++)
        {
            WriteData1(0x0000);
        }
        WriteData1(0xffff);

    }
    for (i = 0; i < Lcm_W; i++)
    {
        WriteData1(0xffff);
    }
}



void Gray2(void)
{
    unsigned int Row, Column, aa;
    //   AddressSetting();
    aa = Lcm_H / 64;
    for (Row = 0; Row < aa * 64; Row++)
    {
        for (Column = 0; Column < (Lcm_W / 4); Column++)
            WriteData1((Row / (aa * 2)) << 11);
        for (Column = 0; Column < (Lcm_W / 4); Column++)
            WriteData1((Row / aa) << 5);
        for (Column = 0; Column < (Lcm_W / 4); Column++)
            WriteData1(Row / (aa * 2));
        for (Column = 0; Column < (Lcm_W / 4); Column++)
            WriteData1((Row / ((aa * 2) << 11)) | ((((Row / aa) / 2)*2) << 5) | (Row / (aa * 2)));
        //	WriteData1((Row/((aa*2)<<11))|((Row/aa)<<5)|(Row/(aa*2)));

        for (Column = 0; Column < (Lcm_W % 4); Column++)
            WriteData1((Row / ((aa * 2) << 11)) | ((((Row / aa) / 2)*2) << 5) | (Row / (aa * 2)));
    }

    for (Row = 0; Row < (Lcm_H % 64); Row++)
    {
        for (Column = 0; Column < (Lcm_W / 4); Column++)
            WriteData1(0xf800);
        for (Column = 0; Column < (Lcm_W / 4); Column++)
            WriteData1(0x07e0);
        for (Column = 0; Column < (Lcm_W / 4); Column++)
            WriteData1(0x001f);
        for (Column = 0; Column < (Lcm_W / 4); Column++)
            WriteData1(0xffff);
        for (Column = 0; Column < (Lcm_W % 4); Column++)
            WriteData1(0xffff);
    }
}


void Gray(void)
{
    unsigned int Row, Column, aa, bb;
    //   AddressSetting();
    aa = Lcm_W / 16; //	aa=Lcm_W/32;
    for (Row = 0; Row < Lcm_H; Row++)
    {
        for (bb = 0; bb < 16; bb++) //		 for(bb=0;bb<32;bb++)
            for (Column = 0; Column < aa; Column++)
                WriteData1((((bb * 2) << 11)) | ((bb * 4) << 5) | (bb * 2)); //	 WriteData16(((bb<<11))|((bb*2)<<5)|bb);

        bb = 0xffff;
        for (Column = 0; Column < Lcm_W % 16; Column++)
            WriteData1((((bb * 2) << 11)) | ((bb * 4) << 5) | (bb * 2)); //	WriteData16(((bb<<11))|((bb*2)<<5)|bb);
    }
}



void RGB(void)
{
    unsigned int Row, Column, aa;
    //   AddressSetting();
    aa = Lcm_H / 3;
    for (Row = 0; Row < aa; Row++)
    {
        for (Column = 0; Column < (Lcm_W / 3); Column++)
            WriteData1(0xf800);
        for (Column = 0; Column < (Lcm_W / 3); Column++)
            WriteData1(0x07e0);
        for (Column = 0; Column < (Lcm_W / 3); Column++)
            WriteData1(0x001f);
        for (Column = 0; Column < (Lcm_W % 3); Column++)
            WriteData1(0x001f);
    }

    for (Row = 0; Row < aa; Row++)
    {
        for (Column = 0; Column < (Lcm_W / 3); Column++)
            WriteData1(0x001f);
        for (Column = 0; Column < (Lcm_W / 3); Column++)
            WriteData1(0xf800);
        for (Column = 0; Column < (Lcm_W / 3); Column++)
            WriteData1(0x07e0);
        for (Column = 0; Column < (Lcm_W % 3); Column++)
            WriteData1(0x07e0);
    }

    for (Row = 0; Row < aa; Row++)
    {
        for (Column = 0; Column < (Lcm_W / 3); Column++)
            WriteData1(0x07e0);
        for (Column = 0; Column < (Lcm_W / 3); Column++)
            WriteData1(0x001f);
        for (Column = 0; Column < (Lcm_W / 3); Column++)
            WriteData1(0xf800);
        for (Column = 0; Column < (Lcm_W % 3); Column++)
            WriteData1(0xf800);
    }

    for (Row = 0; Row < (Lcm_H % 3); Row++)
    {
        for (Column = 0; Column < (Lcm_W / 3); Column++)
            WriteData1(0x07e0);
        for (Column = 0; Column < (Lcm_W / 3); Column++)
            WriteData1(0x001f);
        for (Column = 0; Column < (Lcm_W / 3); Column++)
            WriteData1(0xf800);
        for (Column = 0; Column < (Lcm_W % 3); Column++)
            WriteData1(0xf800);
    }
}

