/***************************************************
//Web: http://www.buydisplay.com
EastRising Technology Co.,LTD
****************************************************/

#include <bcm2835.h>
#include <stdio.h>
#include "nv3030b.h"

char buffer[TFT_WIDTH * TFT_HEIGHT * 2];

void command(char cmd) {
    bcm2835_gpio_write(DC, LOW);
    bcm2835_spi_transfer(cmd);
}

void data(char cmd) {
    bcm2835_gpio_write(DC, HIGH);
    bcm2835_spi_transfer(cmd);
}

void nv3030b_begin()
{
    bcm2835_gpio_fsel(RST, BCM2835_GPIO_FSEL_OUTP);
    bcm2835_gpio_fsel(DC, BCM2835_GPIO_FSEL_OUTP);

    bcm2835_spi_begin();
    bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);     //The default
    bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);                  //The default
    bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_64);  //The default
    bcm2835_spi_chipSelect(BCM2835_SPI_CS0);                     //The default
    bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);     //the default

    bcm2835_gpio_write(RST, HIGH);
    bcm2835_delay(10);
    bcm2835_gpio_write(RST, LOW);
    bcm2835_delay(20);
    bcm2835_gpio_write(RST, HIGH);
    bcm2835_delay(50);





    command(0xfd);//private_access
	data(0x06);
	data(0x08);

	command(0x61);//add
	data(0x07);//
	data(0x04);//
//bias
	command(0x62);//bias setting
	data(0x00);//01
	data(0x44);//04 44
	data(0x45);//44 65 40

	command(0x63);//
	data(0x41);//
	data(0x07);//
	data(0x12);//
	data(0x12);//

	command(0x64);//
	data(0x37);//
//VSP
	command(0x65);//Pump1=4.7MHz //PUMP1 VSP
	data(0x09);//D6-5:pump1_clk[1:0] clamp 28 2b
	data(0x10);//6.26
	data(0x21);
//VSN
	command(0x66); //pump=2 AVCL
	data(0x09); //clamp 08 0b 09
	data(0x10); //10
	data(0x21);
//add source_neg_time
	command(0x67);//pump_sel
	data(0x20);//21 20
	data(0x40);
//gamma vap/van
	command(0x68);//gamma vap/van
	data(0x90);//
	data(0x4c);//
	data(0x7c);//
	data(0x66);//66  46  VCOM

	command(0xb1);//frame rate
	data(0x0F);//0x0f fr_h[5:0] 0F
	data(0x02);//0x02 fr_v[4:0] 02
	data(0x01);//0x04 fr_div[2:0] 03

	command(0xB4);
	data(0x01); //01:1dot 00:column
////porch
	command(0xB5);
	data(0x02);//0x02 vfp[6:0]
	data(0x02);//0x02 vbp[6:0]
	data(0x0a);//0x0A hfp[6:0]
	data(0x14);//0x14 hbp[6:0]

	command(0xB6);
	data(0x04);//
	data(0x01);//
	data(0x9f);//
	data(0x00);//
	data(0x02);//
////gamme sel
	command(0xdf);//
	data(0x11);//gofc_gamma_en_sel=1
////gamma_test1 A1#_wangly
//3030b_gamma_new_
//GAMMA---------------------------------/////////////

//GAMMA---------------------------------/////////////
	command(0xE2);	
	data(0x13);//vrp0[5:0]	V0
	data(0x00);//vrp1[5:0]	V1  
	data(0x00);//vrp2[5:0]	V2 
	data(0x30);//vrp3[5:0]	V61 
	data(0x33);//vrp4[5:0]	V62
	data(0x3f);//vrp5[5:0]	V63

	command(0xE5);	
	data(0x3f);//vrn0[5:0]	V63
	data(0x33);//vrn1[5:0]	V62	
	data(0x30);//vrn2[5:0]	V61 
	data(0x00);//vrn3[5:0]	V2 
	data(0x00);//vrn4[5:0]	V1	
	data(0x13);//vrn5[5:0]  V0

	command(0xE1);	
	data(0x00);//prp0[6:0]	V15
	data(0x57);//prp1[6:0]	V51 

	command(0xE4);	
	data(0x58);//prn0[6:0]	V51 
	data(0x00);//prn1[6:0]  V15

	command(0xE0);
	data(0x01);//pkp0[4:0]	V3 
	data(0x03);//pkp1[4:0]	V7  
	data(0x0d);//pkp2[4:0]	V21 
	data(0x0e);//pkp3[4:0]	V29 //
	data(0x0e);//pkp4[4:0]	V37 
	data(0x0c);//pkp5[4:0]	V45 
	data(0x15);//pkp6[4:0]	V56 
	data(0x19);//pkp7[4:0]	V60 

	command(0xE3);	
	data(0x1a);//pkn0[4:0]	V60 
	data(0x16);//pkn1[4:0]	V56 
	data(0x0c);//pkn2[4:0]	V45 
	data(0x0f);//pkn3[4:0]	V37 
	data(0x0e);//pkn4[4:0]	V29 //
	data(0x0d);//pkn5[4:0]	V21 
	data(0x02);//pkn6[4:0]	V7  
	data(0x01);//pkn7[4:0]	V3 
//GAMMA---------------------------------/////////////


//source
	command(0xE6);
	data(0x00);
	data(0xff);//SC_EN_START[7:0] f0

	command(0xE7);
	data(0x01);//CS_START[3:0] 01
	data(0x04);//scdt_inv_sel cs_vp_en
	data(0x03);//CS1_WIDTH[7:0] 12
	data(0x03);//CS2_WIDTH[7:0] 12
	data(0x00);//PREC_START[7:0] 06
	data(0x12);//PREC_WIDTH[7:0] 12

	command(0xE8); //source
	data(0x00); //VCMP_OUT_EN 81-
	data(0x70); //chopper_sel[6:4]
	data(0x00); //gchopper_sel[6:4] 60
////gate
	command(0xEc);
	data(0x52);//52

	command(0xF1);
	data(0x01);//te_pol tem_extend 00 01 03
	data(0x01);
	data(0x02);

	command(0xF6);//
	data(0x09);//
	data(0x10);//
	data(0x00);//
	data(0x00);//40 3线2通道

	command(0xfd);
	data(0xfa);
	data(0xfc);

	command(0x3a);
	data(0x05);//SH 0x66

	command(0x35);
	data(0x00);

	command(0x36);//bgr_[3]
	data(0x08);//c0 
 
	command(0x21); 
   	

  command(0x11); 
    bcm2835_delay(120);
  command(0x29); 


  
  nv3030b_clear();


}

void nv3030b_clear() {
    int i;
    for(i = 0; i < sizeof(buffer); i++)
    {
        buffer[i] = 0;
    }
}

void nv3030b_draw_point(int x, int y, uint16_t hwColor) {
    if(x >= TFT_WIDTH || y >= TFT_HEIGHT)
    {
        return;
    }
    buffer[x * 2 + y * TFT_WIDTH * 2] = hwColor >> 8;
    buffer[x * 2 + y * TFT_WIDTH * 2 + 1] = hwColor;
}

void nv3030b_char1616(uint16_t x, uint16_t y, uint8_t chChar, uint16_t hwColor) {
    uint8_t i, j;
    uint8_t chTemp = 0, y0 = y;

    for (i = 0; i < 32; i ++) {
        chTemp = Font1612[chChar - 0x30][i];
        for (j = 0; j < 8; j ++) {
            if (chTemp & 0x80) {
                nv3030b_draw_point(x, y, hwColor);
            } else {
                nv3030b_draw_point(x, y, 0);
            }
            chTemp <<= 1;
            y++;
            if ((y - y0) == 16) {
                y = y0;
                x++;
                break;
            }
        }
    }
}

void nv3030b_char3216(uint16_t x, uint16_t y, uint8_t chChar, uint16_t hwColor) {
    uint8_t i, j;
    uint8_t chTemp = 0, y0 = y; 

    for (i = 0; i < 64; i++) {
        chTemp = Font3216[chChar - 0x30][i];
        for (j = 0; j < 8; j++) {
            if (chTemp & 0x80) {
                nv3030b_draw_point(x, y, hwColor);
            } else {
                nv3030b_draw_point(x, y, 0);
            }

            chTemp <<= 1;
            y++;
            if ((y - y0) == 32) {
                y = y0;
                x++;
                break;
            }
        }
    }
}

void nv3030b_char(uint16_t x, uint16_t y, char acsii, char size, char mode, uint16_t hwColor) {
    uint16_t i, j, y0=y;
    char temp;
    uint8_t ch = acsii - ' ';
    for(i = 0;i<size;i++) {
        if(size == 12)
        {
            if(mode)temp=Font1206[ch][i];
            else temp = ~Font1206[ch][i];
        }
        else 
        {            
            if(mode)temp=Font1608[ch][i];
            else temp = ~Font1608[ch][i];
        }
        for(j =0;j<8;j++)
        {
            if(temp & 0x80) nv3030b_draw_point(x, y, hwColor);
            else nv3030b_draw_point(x, y, 0);
            temp <<=1;
            y++;
            if((y-y0)==size)
            {
                y = y0;
                x ++;
                break;
            }
        }
    }
}

void nv3030b_string(uint16_t x, uint16_t y, const char *pString, uint8_t Size, uint8_t Mode, uint16_t hwColor) {
    while (*pString != '\0') {       
        if (x > (TFT_WIDTH - Size / 2)) {
            x = 0;
            y += Size;
            if (y > (TFT_HEIGHT - Size)) {
                y = x = 0;
            }
        }
        
        nv3030b_char(x, y, *pString, Size, Mode, hwColor);
        x += Size / 2;
        pString ++;
    }
}

void nv3030b_mono_bitmap(uint16_t x, uint16_t y, const uint8_t *pBmp, uint16_t chWidth, uint16_t chHeight, uint16_t hwColor) {
    uint16_t i, j, byteWidth = (chWidth + 7) / 8;
    for(j = 0; j < chHeight; j++) {
        for(i = 0; i <chWidth; i ++) {
            if(*(pBmp + j * byteWidth + i / 8) & (128 >> (i & 7))) {
                nv3030b_draw_point(x + i, y + j, hwColor);
            }
        }
    }        
}

void nv3030b_bitmap24(uint16_t x, uint16_t y, uint8_t *pBmp, uint16_t chWidth, uint16_t chHeight) {
    uint16_t i, j;
    uint16_t hwColor;
    uint32_t temp;

    for(j = 0; j < chHeight; j++) {
        for(i = 0; i < chWidth; i ++) {
            temp = *(unsigned int*)(pBmp + i * 3 + j * 3 * chWidth);
            hwColor = RGB(((temp >> 16) & 0xFF),
                          ((temp >> 8) & 0xFF),
                           (temp & 0xFF));
            nv3030b_draw_point(x + i, y + chHeight - 1 - j, hwColor);
        }
    }
}

void nv3030b_display() {
 
    command(0x2a);
    data(0);
    data(0);
    data((TFT_WIDTH-1) >> 8);
    data((TFT_WIDTH-1) & 0xFF);

    command(0x2b);
    data(0);
    data(20);
    data((TFT_HEIGHT+19) >> 8);
    data((TFT_HEIGHT+19)& 0xFF);

    command(0x2C);
    bcm2835_gpio_write(DC, HIGH);
    bcm2835_spi_transfern(buffer, sizeof(buffer));
}

void nv3030b_clear_screen(uint16_t hwColor) {
    uint16_t i, j;
    for(i = 0; i < TFT_HEIGHT; i++) {
        for(j = 0; j < TFT_WIDTH; j ++) {
            nv3030b_draw_point(j, i, hwColor);
        }
    }
}

