#include "LCD_2000_7775.h"


LCD_2000_7775::LCD_2000_7775(uint8_t cs,uint8_t wr ,uint8_t rs , uint8_t rest ,uint8_t pmw)
	: Adafruit_GFX(176, 220)
{
	this->_cs = cs;
	//this->_rd = rd;
	this->_wr = wr;
	this->_rs = rs;
	this->_rest = rest;
	this->_pmw = pmw;
	
	pinMode(this->_cs,OUTPUT);
	//pinMode(this->_rd,OUTPUT);
	pinMode(this->_wr,OUTPUT);
	pinMode(this->_rs,OUTPUT);
	pinMode(this->_rest,OUTPUT);
	pinMode(this->_pmw,OUTPUT);
	
	
	this->csport = portOutputRegister(digitalPinToPort(this->_cs));
	//this->pmwport = portOutputRegister(digitalPinToPort(this->_pmw));
	this->wrport = portOutputRegister(digitalPinToPort(this->_wr));
	this->rsport = portOutputRegister(digitalPinToPort(this->_rs));
	this->restport = portOutputRegister(digitalPinToPort(this->_rest));
	
	
	this->cspinmask  = digitalPinToBitMask(this->_cs);
	//this->pmwpinmask  = digitalPinToBitMask(this->_pmw);
	this->wrpinmask  = digitalPinToBitMask(this->_wr);
	this->rspinmask  = digitalPinToBitMask(this->_rs);
	this->restpinmask  = digitalPinToBitMask(this->_rest);
	
	*(this->csport) |= this->cspinmask;
	//*(this->pmwport) |= this->pmwpinmask;
	*(this->wrport) |= this->wrpinmask;
	*(this->rsport) |= this->rspinmask;
	*(this->restport) |= this->restpinmask;		
}

LCD_2000_7775::LCD_2000_7775(uint8_t cs,uint8_t wr ,uint8_t rs , uint8_t rest )
	: Adafruit_GFX(176, 220)
{
	this->_cs = cs;
	//this->_rd = rd;
	this->_wr = wr;
	this->_rs = rs;
	this->_rest = rest;
	
	pinMode(this->_cs,OUTPUT);
	//pinMode(this->_rd,OUTPUT);
	pinMode(this->_wr,OUTPUT);
	pinMode(this->_rs,OUTPUT);
	pinMode(this->_rest,OUTPUT);
	
	
	this->csport = portOutputRegister(digitalPinToPort(this->_cs));
	this->wrport = portOutputRegister(digitalPinToPort(this->_wr));
	this->rsport = portOutputRegister(digitalPinToPort(this->_rs));
	this->restport = portOutputRegister(digitalPinToPort(this->_rest));
		
	this->cspinmask  = digitalPinToBitMask(this->_cs);
	this->wrpinmask  = digitalPinToBitMask(this->_wr);
	this->rspinmask  = digitalPinToBitMask(this->_rs);
	this->restpinmask  = digitalPinToBitMask(this->_rest);
	
	*(this->csport) |= this->cspinmask;
	*(this->wrport) |= this->wrpinmask;
	*(this->rsport) |= this->rspinmask;
	*(this->restport) |= this->restpinmask;		
}

LCD_2000_7775::LCD_2000_7775(uint8_t cs,uint8_t wr ,uint8_t rs)
	: Adafruit_GFX(176, 220)
{
	this->_cs = cs;
	this->_wr = wr;
	this->_rs = rs;
	this->_rest = 0;
	
	pinMode(this->_cs,OUTPUT);
	pinMode(this->_wr,OUTPUT);
	pinMode(this->_rs,OUTPUT);
	
	this->csport = portOutputRegister(digitalPinToPort(this->_cs));
	this->wrport = portOutputRegister(digitalPinToPort(this->_wr));
	this->rsport = portOutputRegister(digitalPinToPort(this->_rs));
		
	this->cspinmask  = digitalPinToBitMask(this->_cs);
	this->wrpinmask  = digitalPinToBitMask(this->_wr);
	this->rspinmask  = digitalPinToBitMask(this->_rs);
	
	*(this->csport) |= this->cspinmask;
	*(this->wrport) |= this->wrpinmask;
	*(this->rsport) |= this->rspinmask;
}


#if 0 //defined(ARDUINO_ARCH_SAM)
	void LCD_2000_7775::write_delay()
	{	
		volatile uint32_t delaycnt = 10;
		while( delaycnt-- );
	}
#endif


void LCD_2000_7775::write_spi(const uint8_t data)
{
	uint8_t bit,i;
	for(bit = 0x01,i = 0 ; bit ; i++,bit <<= 1)	
	{
		if(data & bit) *(this->dataport[i]) |= this->datapinmask[i];
    else   *(this->dataport[i]) &= (~this->datapinmask[i]);
    	
    //write_delay();
  }
}

void LCD_2000_7775::setdatapin(uint8_t b0,uint8_t b1, uint8_t b2 , uint8_t b3,
													uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7)
{
	uint8_t i;
	this->data[0] = b0;
	this->data[1] = b1;
	this->data[2] = b2;
	this->data[3] = b3;
	this->data[4] = b4;
	this->data[5] = b5;
	this->data[6] = b6;
	this->data[7] = b7;
	for(i = 0; i < 8 ;i++)
		pinMode(this->data[i],OUTPUT);
	for(i = 0; i < 8 ;i++)
		dataport[i] = portOutputRegister(digitalPinToPort(this->data[i]));
	for(i = 0; i < 8 ;i++)
		datapinmask[i] = digitalPinToBitMask(this->data[i]);
	
	this->setbracklight(255);
}

void LCD_2000_7775::write_wr_reg(uint16_t data)
{
 	
 	*(this->rsport) &= (~this->rspinmask);
 	write_delay();
 	*(this->csport) &= (~this->cspinmask);
 	write_delay();
 	this->write_spi( data >> 8 );
 	write_delay();
 	*(this->wrport) &= (~this->wrpinmask);
 	write_delay(); 	
	*(this->wrport) |= this->wrpinmask;
 	write_delay();
 	this->write_spi( (data&0x00ff) );
 	write_delay();
 	*(this->wrport) &= (~this->wrpinmask);
 	write_delay();
	*(this->wrport) |= this->wrpinmask;
	write_delay();
 	*(this->csport) |= this->cspinmask;
 	write_delay();
}

void LCD_2000_7775::write_wr_data(uint16_t data)
{
	*(this->rsport) |= this->rspinmask;
	write_delay();
	*(this->csport) &= (~this->cspinmask);
	write_delay();
	
	this->write_spi( data >> 8 );
	write_delay();
	*(this->wrport) &= (~this->wrpinmask);
	write_delay();
	*(this->wrport) |= this->wrpinmask;
	write_delay();
	
	this->write_spi( (data&0x00ff) );
	write_delay();
	*(this->wrport) &= (~this->wrpinmask);
	write_delay();
	*(this->wrport) |= this->wrpinmask;
	write_delay();
	
	*(this->csport) |= this->cspinmask;
	write_delay();
}

void LCD_2000_7775::write_cmd(uint16_t cmd ,uint16_t data)
{
	this->write_wr_reg(cmd);
	this->write_wr_data(data);
}

void LCD_2000_7775::set_window(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2)
{
	this->write_wr_reg(0x0037);this->write_wr_data(x1); // windows address 
	this->write_wr_reg(0x0036);this->write_wr_data(x2);
	this->write_wr_reg(0x0039);this->write_wr_data(y1);    
	this->write_wr_reg(0x0038);this->write_wr_data(y2);	
	this->write_wr_reg(0x0020);  //HS
	this->write_wr_data(x1); 		 
	this->write_wr_reg(0x0021);  //VS
	this->write_wr_data(y1);
}

void LCD_2000_7775::drawPixel(int16_t x, int16_t y, uint16_t color)
{
	set_window(x,y,x,y);
	//this->write_wr_reg(0x0022);
	//this->write_wr_data(color);
	this->write_cmd(0x22,color);
}

void LCD_2000_7775::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, 
		uint16_t color)
{
	set_window(x,y,x+w-1,y+h-1);
	this->write_wr_reg(0x22);
	int i = w*h;
	while(i--)
		this->write_wr_data(color);
}

void LCD_2000_7775::setbracklight(uint8_t pmw)
{
	analogWrite(this->_pmw,pmw);
}

void  LCD_2000_7775::drawbitmap(uint16_t* data, uint16_t x ,uint16_t y,uint16_t with , uint16_t height)
{
	uint32_t i;
	this->set_window(x,y,x+with-1,y+height-1);
	this->write_wr_reg(0x22);
	i = with * height;
	while(i--)
	{
		this->write_wr_data(*data);
		data++;
	}
	
}

void LCD_2000_7775::begin()
{
		if( this->_rest )
		{
			 	*(this->restport) &= (~this->restpinmask);					
			 	delay(50); //     Delay 50ms
			 	*(this->restport) |= this->restpinmask;		
			 	delay(10); //     Delay 10ms
		}
	
		this->write_cmd(0x0001, 0x011C); // set SS and NL bit
    this->write_cmd(0x0002, 0x0100); // set 1 line inversion
    this->write_cmd(0x0003, 0x1030); // set GRAM write direction and BGR=1,??16BIT 65K?MDT1=0,MDT0=0
    this->write_cmd(0x0008, 0x0808); // set BP and FP
    this->write_cmd(0x000C, 0x0000); // RGB interface setting R0Ch=0x0110 for RGB 18Bit and R0Ch=0111for

    this->write_cmd(0x000F, 0x0e01); // Set frame rate
   
//*************Power On sequence ****************//
    delay(50); //     Delay 50ms
    this->write_cmd(0x0010, 0x0A00); // Set SAP,DSTB,STB
    this->write_cmd(0x0011, 0x1038); // Set APON,PON,AON,VCI1EN,VC
    //delay(50); //     Delay 50ms
    this->write_cmd(0x00ff, 0x0003);    //
    this->write_cmd(0x00b0, 0x1411);    //Set VCOM 1d
    this->write_cmd(0x00b1, 0x0202);    //GVCL/GVDD voltage setting
    this->write_cmd(0x00b2, 0x0313);  //VCL voltage setting

//------------------------ Set GRAM area  set window --------------------------------//
    this->write_cmd (0x0030, 0x0000);//???????
    this->write_cmd (0x0031, 0x00db);
    this->write_cmd (0x0032, 0x0000);
    this->write_cmd (0x0033, 0x0000);//??????
    this->write_cmd (0x0034, 0x00db);
    this->write_cmd (0x0035, 0x0000);//R34H,R35H???????
    this->write_cmd (0x0036, 0x00AF);
    this->write_cmd (0x0037, 0x0000);
    this->write_cmd (0x0038, 0x00DB);
    this->write_cmd (0x0039, 0x0000);
    delay(20);
   
    this->write_cmd(0x00ff, 0x0003);
//    WriteRegister(0x00b0, 0x1d01);
// ----------- Adjust the Gamma Curve ----------//
     this->write_cmd(0x0050, 0x0000);
     this->write_cmd(0x0051, 0x0300);
     this->write_cmd(0x0052, 0x0103);
     this->write_cmd(0x0053, 0x2011);
     this->write_cmd(0x0054, 0x0703);
     this->write_cmd(0x0055, 0x0000);
     this->write_cmd(0x0056, 0x0400);
     this->write_cmd(0x0057, 0x0107);
     this->write_cmd(0x0058, 0x2011);
     this->write_cmd(0x0059, 0x0703);
     delay(50); //     Delay 50ms
     this->write_cmd(0x0020, 0x0000); // Set GRAM Address
     this->write_cmd(0x0021, 0x0000); // Set GRAM Address
     this->write_cmd(0x0007, 0x1017);
	
		
		this->fillRect(0,0,LCD_2000_7775_TFTWIDTH,LCD_2000_7775_TFTHEIGHT,0xffff);
}


/*********************************º¯Êý******************************/
uint16_t RGB(uint16_t r,uint16_t g , uint16_t b)
{
	uint16_t rgb = 0;
	r *= 31;
	r /= 255;
	
	g *= 63;
	g /= 255;
	
	b *= 31;
	b /= 255;
	
	rgb |= (r<<11);
	rgb |= (g<<6);
	rgb |= b;
	return rgb;
}

