#include "LCD_2000_9225.h"


LCD_2000_9225::LCD_2000_9225(uint8_t cs,uint8_t wr ,uint8_t rs , uint8_t rest  ,uint8_t pmw ,uint8_t le)
	: Adafruit_GFX(LCD_2000_9225_TFTWIDTH, LCD_2000_9225_TFTHEIGHT)
{
	this->_cs = cs;
	//this->_rd = rd;
	this->_wr = wr;
	this->_rs = rs;
	this->_rest = rest;
	this->_pmw = pmw;
	this->_le = le;
	
	pinMode(this->_cs,OUTPUT);
	//pinMode(this->_rd,OUTPUT);
	pinMode(this->_wr,OUTPUT);
	pinMode(this->_rs,OUTPUT);
	pinMode(this->_rest,OUTPUT);
	pinMode(this->_pmw,OUTPUT);
	pinMode(this->_le,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->leport = portOutputRegister(digitalPinToPort(this->_le));
	
	this->cspinmask  = digitalPinToBitMask(this->_cs);
	this->wrpinmask  = digitalPinToBitMask(this->_wr);
	this->rspinmask  = digitalPinToBitMask(this->_rs);
	this->restpinmask  = digitalPinToBitMask(this->_rest);
	this->lepinmask  = digitalPinToBitMask(this->_le);
	
	
	*(this->csport) |= this->cspinmask;
	*(this->wrport) |= this->wrpinmask;
	*(this->rsport) |= this->rspinmask;
	*(this->restport) |= this->restpinmask;
	*(this->leport) |= this->lepinmask;
	this->setbracklight(255);
}

LCD_2000_9225::LCD_2000_9225(uint8_t cs,uint8_t wr ,uint8_t rs , uint8_t rest ,uint8_t le)
	: Adafruit_GFX(LCD_2000_9225_TFTWIDTH, LCD_2000_9225_TFTHEIGHT)
{
	this->_cs = cs;
	//this->_rd = rd;
	this->_wr = wr;
	this->_rs = rs;
	this->_rest = rest;
	//this->_pmw = pmw;
	this->_le = le;
	
	pinMode(this->_cs,OUTPUT);
	//pinMode(this->_rd,OUTPUT);
	pinMode(this->_wr,OUTPUT);
	pinMode(this->_rs,OUTPUT);
	pinMode(this->_rest,OUTPUT);
	//pinMode(this->_pmw,OUTPUT);
	pinMode(this->_le,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->leport = portOutputRegister(digitalPinToPort(this->_le));
	
	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->lepinmask  = digitalPinToBitMask(this->_le);
	
	
	*(this->csport) |= this->cspinmask;
	*(this->pmwport) |= this->pmwpinmask;
	*(this->wrport) |= this->wrpinmask;
	*(this->rsport) |= this->rspinmask;
	*(this->restport) |= this->restpinmask;
	*(this->leport) |= this->lepinmask;
}

LCD_2000_9225::LCD_2000_9225(uint8_t cs,uint8_t wr ,uint8_t rs ,uint8_t le)
	: Adafruit_GFX(LCD_2000_9225_TFTWIDTH, LCD_2000_9225_TFTHEIGHT)
{
	this->_cs = cs;
	this->_wr = wr;
	this->_rs = rs;
	this->_le = le;
	this->_rest = 0;
	
	pinMode(this->_cs,OUTPUT);
	pinMode(this->_wr,OUTPUT);
	pinMode(this->_rs,OUTPUT);
	pinMode(this->_le,OUTPUT);
	
	this->csport = portOutputRegister(digitalPinToPort(this->_cs));
	this->wrport = portOutputRegister(digitalPinToPort(this->_wr));
	this->rsport = portOutputRegister(digitalPinToPort(this->_rs));
	this->leport = portOutputRegister(digitalPinToPort(this->_le));
	
	this->cspinmask  = digitalPinToBitMask(this->_cs);
	this->wrpinmask  = digitalPinToBitMask(this->_wr);
	this->rspinmask  = digitalPinToBitMask(this->_rs);
	this->lepinmask  = digitalPinToBitMask(this->_le);
	
	
	*(this->csport) |= this->cspinmask;
	*(this->wrport) |= this->wrpinmask;
	*(this->rsport) |= this->rspinmask;
	*(this->leport) |= this->lepinmask;
}

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

void LCD_2000_9225::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]);
}

void LCD_2000_9225::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]);
}

void LCD_2000_9225::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->leport) |= this->lepinmask;
 	write_delay();
 	*(this->leport) &= (~this->lepinmask);
 	write_delay();
 	this->write_spi( data );
 	write_delay();
 	
 	*(this->wrport) &= (~this->wrpinmask);
 	write_delay();
	*(this->wrport) |= this->wrpinmask;
	write_delay();
	
 	*(this->csport) |= this->cspinmask;
 	write_delay();
 	
}

void LCD_2000_9225::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->leport) |= this->lepinmask;
	write_delay();
	*(this->leport) &= (~this->lepinmask);
	write_delay();
	this->write_spi( data );
	write_delay();
	
	*(this->wrport) &= (~this->wrpinmask);
	write_delay();
	*(this->wrport) |= this->wrpinmask;
	write_delay();
	
	*(this->csport) |= this->cspinmask;
	write_delay();
}

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

void LCD_2000_9225::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_9225::drawPixel(int16_t x, int16_t y, uint16_t color)
{
	set_window(x,y,x+1,y+1);
	//this->write_wr_reg(0x0022);
	//this->write_wr_data(color);
	this->write_cmd(0x22,color);
}

void LCD_2000_9225::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_9225::setbracklight(uint8_t pmw)
{
	analogWrite(this->_pmw,pmw);
}

void  LCD_2000_9225::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_9225::begin()
{
		if( this->_rest )
		{
			 	*(this->restport) &= (~this->restpinmask);					
			 	delay(50); //     Delay 50ms
			 	*(this->restport) |= this->restpinmask;		
			 	delay(10); //     Delay 10ms
		}
			
		this->write_cmd(0x00D0, 0x0003);  
    this->write_cmd(0x00EB, 0x0B00); 
    this->write_cmd(0x00EC, 0x000F);   
    this->write_cmd(0x00C7, 0x030F); 
         
    this->write_cmd(0x0001, 0x011C); 
    this->write_cmd(0x0002, 0x0100); 
    this->write_cmd(0x0003, 0x1030);   
    this->write_cmd(0x0008, 0x0808); 
    this->write_cmd(0x000F, 0x0901);   
    delay(10); 
    this->write_cmd(0x0010, 0x0000); 
    this->write_cmd(0x0011, 0x1B41); //The register setting is suitable for VCI=2.8V 
    delay(120); 
    this->write_cmd(0x0012, 0x200E);//The register setting is suitable for VCI=2.8V 
    this->write_cmd(0x0013, 0x0052); //The register setting is suitable for VCI=2.8V 
    this->write_cmd(0x0014, 0x4B5C); //The register setting is suitable for VCI=2.8V 
 
    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);   
    this->write_cmd(0x0036, 0x00AF);   
    this->write_cmd(0x0037, 0x0000);   
    this->write_cmd(0x0038, 0x00DB);   
    this->write_cmd(0x0039, 0x0000);  
    this->write_cmd(0x0050, 0x0000); 
    this->write_cmd(0x0051, 0x0705); 
    this->write_cmd(0x0052, 0x0C0A); 
    this->write_cmd(0x0053, 0x0401); 
    this->write_cmd(0x0054, 0x040C); 
    this->write_cmd(0x0055, 0x0608); 
    this->write_cmd(0x0056, 0x0000); 
    this->write_cmd(0x0057, 0x0104); 
    this->write_cmd(0x0058, 0x0E06); 
    this->write_cmd(0x0059, 0x060E);;      
               
    this->write_cmd(0x0020, 0x0000);       
    this->write_cmd(0x0021, 0x0000);   
    this->write_cmd(0x0007, 0x1017);
	
		
		this->fillRect(0,0,LCD_2000_9225_TFTWIDTH,LCD_2000_9225_TFTHEIGHT,0xffff);
}


/*********************************fuction******************************/
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;
}