//  Copyright (C) 2016, mituhiromatuura all right reserved.

#include <kernel.h>
#include "iodefine.h"

#include "bt.h"
#include "button.h"
#include "gpio.h"
#include "lcd.h"
#include "wait.h"

#define Delayms(msec) wait_busy(msec)

#define wr_cmd(index)	lcd_wr_cmd(index)
#define wr_data(data)	lcd_wr_data(data)
#define rd_data(dmy)	lcd_rd_data(dmy)

#define RESET_PDOR		*reset_pdor
#define RESET_DDR		*reset_ddr

#define RSTTFT_H		RESET_PDOR = 1
#define RSTTFT_L		RESET_PDOR = 0

static v32_t *reset_pdor;
static v32_t *reset_ddr;

void wr_cmd(volatile unsigned short index)
{
	*(volatile unsigned char*)LCD_CMD_REG_ADDR = (index >> 8) & 0xff;
	*(volatile unsigned char*)LCD_CMD_REG_ADDR = (index >> 0) & 0xff;
	return;
}

void wr_data(volatile unsigned short data)
{
	*(volatile unsigned char*)LCD_DAT_REG_ADDR = (data >> 8) & 0xff;
	*(volatile unsigned char*)LCD_DAT_REG_ADDR = (data >> 0) & 0xff;
	return;
}

unsigned char rd_data(void)
{
	return *(volatile unsigned char*)LCD_DAT_REG_ADDR;
}

static
void lcd_initialize(void)
{
	RSTTFT_L;
	Delayms(30);
	RSTTFT_H;
	Delayms(30);

	//--------------------------------ST7781 Internal Register Initial---------------------------------------//
	wr_cmd(0x00ff);wr_data(0x0001);
	wr_cmd(0x00f3);wr_data(0x0008);
	//LCD_CtrlRead_ST7781 (0x00f3); //Read Parameter
	//---------------------------End ST7781 Internal Register Initial--------------------------------------//
	//------------------------------------Display Control Setting----------------------------------------------//
	wr_cmd(0x0001);wr_data(0x0100); //Output Direct
	wr_cmd(0x0002);wr_data(0x0700); //Line Inversion
//	wr_cmd(0x0003);wr_data(0x1030); //Entry Mode (65K, BGR)
//	wr_cmd(0x0003);wr_data(0x1018); //Entry Mode (65K, BGR)
	wr_cmd(0x0003);wr_data(0x1028); //Entry Mode (65K, BGR)
	wr_cmd(0x0008);wr_data(0x0807); // Porch Setting
	wr_cmd(0x0009);wr_data(0x0000); //Scan Cycle
	wr_cmd(0x000A);wr_data(0x0000); //FMARK off
	//-----------------------------------End Display Control setting-----------------------------------------//
	//-------------------------------- Power Control Registers Initial --------------------------------------//
	wr_cmd(0x0010);wr_data(0x0790); //Power Control1
	wr_cmd(0x0011);wr_data(0x0005); //Power Control2
	wr_cmd(0x0012);wr_data(0x0000); //Power Control3
	wr_cmd(0x0013);wr_data(0x0000); //Power Control4
	//---------------------------------End Power Control Registers Initial -------------------------------//
	Delayms(100);; //Delay 100ms
	//--------------------------------- Power Supply Startup 1 Setting------------------------------------//
	wr_cmd(0x0010);wr_data(0x1490); //Power Control1
	Delayms(50); //Delay 50ms
	wr_cmd(0x0011);wr_data(0x0227); //Power Control2
	//--------------------------------- End Power Supply Startup 1 Setting------------------------------//
	Delayms(50); //Delay 50ms
	//--------------------------------- Power Supply Startup 2 Setting------------------------------------//
	wr_cmd(0x0012);wr_data(0x0089); //Power Control3
	wr_cmd(0x0013);wr_data(0x1900); //Power Control4
	wr_cmd(0x0029);wr_data(0x0021); //VCOMH setting
	//--------------------------------- End Power Supply Startup 2 Setting------------------------------//
	Delayms(50); //Delay 50ms
	//-------------------------------------Gamma Cluster Setting-------------------------------------------//
	wr_cmd(0x0030);wr_data(0x0000);
	wr_cmd(0x0031);wr_data(0x0006);
	wr_cmd(0x0032);wr_data(0x0100);
	wr_cmd(0x0035);wr_data(0x0001);
	wr_cmd(0x0036);wr_data(0x0000);
	wr_cmd(0x0037);wr_data(0x0000);
	wr_cmd(0x0038);wr_data(0x0406);
	wr_cmd(0x0039);wr_data(0x0202);
	wr_cmd(0x003c);wr_data(0x0001);
	wr_cmd(0x003d);wr_data(0x0000);
	//---------------------------------------End Gamma Setting---------------------------------------------//
	//----------------------------------Display Windows 240 X 320----------------------------------------//
	wr_cmd(0x0050);wr_data(0x0000); // Horizontal Address Start Position
	wr_cmd(0x0051);wr_data(0x00ef); // Horizontal Address End Position
	wr_cmd(0x0052);wr_data(0x0000); // Vertical Address Start Position
	wr_cmd(0x0053);wr_data(0x013f); // Vertical Address End Position
	//----------------------------------End Display Windows 240 X 320----------------------------------//
	//-------------------------------------------Frame Rate Setting-------------------------------------------//
	wr_cmd(0x0060);wr_data(0xa700); //Gate scan control
	wr_cmd(0x0061);wr_data(0x0001); //Non-display Area setting
	wr_cmd(0x0090);wr_data(0x0033); //RTNI setting
	//-------------------------------------------END Frame Rate setting------------------------------------//
	wr_cmd(0x0007);wr_data(0x0133); //Display Control1
	Delayms(50); //Delay 50ms
	
	wr_cmd(0x0022);
}

void init_display(void)
{
#if 0
	gpio_pdor_set(LCD_LED_PORT, LCD_LED_BIT, 1);
	gpio_ddr_set(LCD_LED_PORT, LCD_LED_BIT, 1);
	gpio_ade_set(LCD_LED_PORT, LCD_LED_BIT, 0);

	gpio_ade_set(LCD_RESET_PORT, LCD_RESET_BIT, 0);
#else
	init_pwm();
#endif

	reset_ddr	= bit_band(GPIO_DDR  + 4 * LCD_RESET_PORT, LCD_RESET_BIT);
	reset_pdor	= bit_band(GPIO_PDOR + 4 * LCD_RESET_PORT, LCD_RESET_BIT);

	RESET_PDOR	= 0;
	RESET_DDR	= 1;

	lcd_initialize();

	unsigned int i,n,m;
	unsigned short color[8]={0xf800,0x07e0,0x001f,0x07ff,0xf81f,0xffe0,0x0000,0xffff};
//	int x = 100;

//	while(x--)
	{
		wr_cmd(0x0022);	

		for(n=0;n<8;n++)
			for(i=0;i<320/8;i++)
				for(m=0;m<240;m++)
					wr_data(0xffff);

		for(n=0;n<8;n++)
			for(i=0;i<320/8;i++)
				for(m=0;m<240;m++)
					wr_data(color[n]);
	}

	return;
}

void display_area_set(int xs, int ys, int xe, int ye)
{
	wr_cmd(0x0003);wr_data(0x1028); //Entry Mode (65K, BGR)

	wr_cmd(0x0050);wr_data(xs);	// Horizontal GRAM Start Address 
	wr_cmd(0x0051);wr_data(xe);	// Horizontal GRAM End Address 
	wr_cmd(0x0052);wr_data(ys);	// Vertical GRAM Start Address 
	wr_cmd(0x0053);wr_data(ye);	// Vertical GRAM End Address 

	wr_cmd(0x0020);wr_data(xs);	// GRAM horizontal Address 
	wr_cmd(0x0021);wr_data(ys);	// GRAM Vertical Address  

	wr_cmd(0x0022);
	return;
}

void display_area_set_m(int xs, int ys, int xe, int ye)
{
	if(mirror){
		wr_cmd(0x0003);wr_data(0x1008); //Entry Mode (65K, BGR)
	}else{
		wr_cmd(0x0003);wr_data(0x1028); //Entry Mode (65K, BGR)
	}

	wr_cmd(0x0050);wr_data(xs);	// Horizontal GRAM Start Address 
	wr_cmd(0x0051);wr_data(xe);	// Horizontal GRAM End Address 
	wr_cmd(0x0052);wr_data(ys);	// Vertical GRAM Start Address 
	wr_cmd(0x0053);wr_data(ye);	// Vertical GRAM End Address 

	wr_cmd(0x0020);wr_data(xs);	// GRAM horizontal Address 
	wr_cmd(0x0021);wr_data(ys);	// GRAM Vertical Address  

	wr_cmd(0x0022);
	return;
}

void display_read_set_m(int xs, int ys, int xe, int ye)
{
	if(mirror){
		wr_cmd(0x0003);wr_data(0x1038); //Entry Mode (65K, BGR)
	}else{
		wr_cmd(0x0003);wr_data(0x1018); //Entry Mode (65K, BGR)
	}

	wr_cmd(0x0050);wr_data(xs);	// Horizontal GRAM Start Address 
	wr_cmd(0x0051);wr_data(xe);	// Horizontal GRAM End Address 
	wr_cmd(0x0052);wr_data(ys);	// Vertical GRAM Start Address 
	wr_cmd(0x0053);wr_data(ye);	// Vertical GRAM End Address 

	wr_cmd(0x0020);wr_data(xs);	// GRAM horizontal Address 
	wr_cmd(0x0021);wr_data(ys);	// GRAM Vertical Address  

	wr_cmd(0x0022);
	return;
}

static
unsigned short color_table[] =
{
	0x0000,	//BLACK,
	0xf800,	//RED,
	0x07e0,	//GREEN,
	0x001f,	//BLUE,
	0xffe0,	//YELLOW,
	0x07ff,	//CYAN,
	0xf81f,	//MAGENTA,
	0xffff,	//WHITE,
};

void pset(int color)
{
	wr_data(color_table[color]);
	return;
}

void display_clr(int color)
{
	int x, y;

	wr_cmd(0x0022);

	for(y = 0;y < 240; y++)
	{
		for(x = 0;x < 320; x++)
		{
			wr_data(color_table[color]);
		}
	}
	return;
}
