/*==============================================================================
	Copyright (C) 2010 IT Access.,Co.Ltd. All Rights Reserved.
	
	This software is the confidential and proprietary information 
	of IT Access.,Co.Ltd.
	
	Note:
		For Interface SH-2A board + LCD board without OS.

   Spec: SH7262 144MHz, 1MB RAM, LCD QVGA 320x240 RGB565

	2010/08 T.Kou IT-Access

==============================================================================*/


#include "SH7262.h"
//#include "cpu.h"
#include "cpu_init.h"
#include "cpu_uart.h"
#include "tinylib.h"

/* FatFs関数ヘッダ */
#include "diskio.h"
#include "ff.h"

#include "GealTypes.h"
#include "GealAPI.h"
#include "GealConfigAPI.h"
#include "TargetTypes.h"
#include "GealRsxConfig.h"
#include "GealRsxEnum.h"


// 現ボードではタッチパネル非対応なので、量産ボードが来るまで、とりあえずOFF
#define	USE_TOUCH_PANEL

#ifndef	false
	#define	false	0
#endif

#ifndef	true
	#define	true	1
#endif

// DEBUG print out 
// #define	_DEBUG

/*==============================================================================
	  SH7262 VDC3 テスト1
==============================================================================*/
#ifdef	_WKLCD	//若松通商 WKLCD-2A　
/* TFT-LCD PT035TN23 V.1 */
#define LCD_HORIZONTAL_PERIOD         408	/* 水平同期周期 */
#define LCD_HORIZONTAL_DISPLAY_PERIOD 320	/* 水平表示期間 */
#define LCD_HORIZONTAL_BACK_PORCH      70	/* 水平バックポーチ */
#define LCD_HORIZONTAL_PULSE_WIDTH      1	/* 水平同期期間 */
#define LCD_VERTICAL_PERIOD           263	/* 垂直同期周期 */
#define LCD_VERTICAL_DISPLAY_PERIOD   240	/* 垂直表示期間 */
#define LCD_VERTICAL_BACK_PORCH        13	/* 垂直バックポーチ */
#define LCD_VERTICAL_PULSE_WIDTH        1	/* 垂直同期期間 */

#else	// 北斗電子 HSB7264LCD
/* TFT-LCD GPG3224012QS4 */
#define LCD_HORIZONTAL_PERIOD         408	/* 水平同期周期 */
#define LCD_HORIZONTAL_DISPLAY_PERIOD 320	/* 水平表示期間 */
#define LCD_HORIZONTAL_BACK_PORCH      38	/* 水平バックポーチ */
#define LCD_HORIZONTAL_PULSE_WIDTH      1	/* 水平同期期間 */
#define LCD_VERTICAL_PERIOD           262	/* 垂直同期周期 */
#define LCD_VERTICAL_DISPLAY_PERIOD   240	/* 垂直表示期間 */
#define LCD_VERTICAL_BACK_PORCH        18	/* 垂直バックポーチ */
#define LCD_VERTICAL_PULSE_WIDTH        1	/* 垂直同期期間 */

#endif


/* グラフィック部1 */
#define GRA1_VRAM_BASE         0x3C078000	/* 大容量内蔵RAM ページ4(240KB) */
#define GRA1_HORIZONTAL_SIZE		320	/* 水平表示サイズ */
#define GRA1_HORIZONTAL_OFFSET		512	/* 水平改行幅 2N乗にして高速化 */
#define GRA1_VERTICAL_SIZE			240	/* 垂直表示サイズ */
#define GRA1_HORIZONTAL_POS			0	/* 水平表示位置 */
#define GRA1_VERTICAL_POS			0	/* 垂直表示位置 */

/* グラフィック部2 */
#define GRA2_HORIZONTAL_SIZE          320	/* 水平表示サイズ */
#define GRA2_VERTICAL_SIZE            240	/* 垂直表示サイズ */
#define GRA2_HORIZONTAL_POS             0	/* 水平表示位置 */
#define GRA2_VERTICAL_POS               0	/* 垂直表示位置 */
#define GRA2_VRAM_BASE         0x3C050000	/* 大容量内蔵RAM ページ3(160KB) */

/*==============================================================================
	Geal関連
==============================================================================*/
//　mallocがないので、とりあえず定数で確保。Ver1.3で480Byte
#define	GEAL_SYSMEM_SIZE	512
static unsigned char GXSysMem[GEAL_SYSMEM_SIZE] ;

#define DISPLAY_WIDTH	(GRA1_HORIZONTAL_SIZE)
#define DISPLAY_HEIGHT	(GRA1_VERTICAL_SIZE)

// とりあえず設定
#define		LCD_OFFSET		GRA1_VRAM_BASE
#define		LCD_LINEINT		(GRA1_HORIZONTAL_OFFSET*2)	//改行幅指定　RGB16=2byte 

static TARGET		m_sTarget;


/*==============================================================================
　その他
==============================================================================*/

static unsigned short  oldTx, oldTy ;
static unsigned char Ttgl, Told, Ton ;

//static int			bExitFlg;



/*==============================================================================
==============================================================================*/




/*==============================================================================
		LCD　サンプル描画
==============================================================================*/

static void	draw_colorbar(void)
{
	int i, j;
	unsigned short *gra_vram;
	unsigned short *gra_pos;

	/* グラフィックス部1 描画(カラーバー) */
//	gra_vram = GRA1_VRAM_BASE;
	gra_pos = (unsigned short *)GRA1_VRAM_BASE;
	for(j = 0; j < GRA1_VERTICAL_SIZE / 2; j++)
	{
		gra_vram = gra_pos ;
		for(i = 0; i < GRA1_HORIZONTAL_SIZE; i++)
		{
			if(i < GRA1_HORIZONTAL_SIZE / 8)
				*gra_vram++ = 0x0000;	/* Black */
			else if(i < GRA1_HORIZONTAL_SIZE / 8 * 2)
				*gra_vram++ = 0x001F;	/* Blue */
			else if(i < GRA1_HORIZONTAL_SIZE / 8 * 3)
				*gra_vram++ = 0x07E0;	/* Green */
			else if(i < GRA1_HORIZONTAL_SIZE / 8 * 4)
				*gra_vram++ = 0x07FF;	/* Cyan */
			else if(i < GRA1_HORIZONTAL_SIZE / 8 * 5)
				*gra_vram++ = 0xF800;	/* Red */
			else if(i < GRA1_HORIZONTAL_SIZE / 8 * 6)
				*gra_vram++ = 0xF81F;	/* Magenta */
			else if(i < GRA1_HORIZONTAL_SIZE / 8 * 7)
				*gra_vram++ = 0xFFE0;	/* Yellow */
			else
				*gra_vram++ = 0xFFFF;	/* White */
		}
		gra_pos += GRA1_HORIZONTAL_OFFSET ;
	}

	for(j = 0; j < GRA1_VERTICAL_SIZE / 2; j++)
	{
		gra_vram = gra_pos ;
		for(i = 0; i < GRA1_HORIZONTAL_SIZE; i++)
		{
			*gra_vram++ = (((i & 0xF8) >> 3) << 11)
			            | (((i & 0xFC) >> 2) << 5)
			            |  ((i & 0xF8) >> 3);
		}
		gra_pos += GRA1_HORIZONTAL_OFFSET ;
	}

}

/*==============================================================================
	LCD拡張ボードLCD初期化
==============================================================================*/
void LCD_Initialize(void)
{
	unsigned int i;

	/*LCDコントローラ部*/
	/* LCDバックライトイネーブル(PB21(LCD_BLE)信号,正論理) */
	PBCR5 = PBCR5 & 0xFFCF;
	PBIOR1= PBIOR1 | 0x0020;
	PBDR1 = PBDR1 | 0x0020;

	/* VDC3 初期化 */
	PGCR7 = 0x5A01;	/* LCD_DATA0 */
	PGCR4 = 0x1111;	/* LCD_CLK, LCD_DE, LCD_HSYNC, LCD_VSYNC */
	PGCR3 = 0x1111;	/* LCD_DATA15-12 */
	PGCR2 = 0x1111;	/* LCD_DATA11-8 */
	PGCR1 = 0x1111;	/* LCD_DATA7-4 */
	PGCR0 = 0x1110;	/* LCD_DATA3-1 */

	STBCR7 = STBCR7 & ~(1 << 4);	/* VDC3へのクロック供給 */

	/* 表示制御部 初期化 */
	SGMODE           = 0x00000001;
	SYNCNT           = 0x010F000C;
	PANEL_CLKSEL     = PANEL_CLKSEL & ~(1 << 12);
	PANEL_CLKSEL     = 0x00002008;		/* 6MHz(48MHz / 8) ≒ 6.4MHz(typ) */
	PANEL_CLKSEL     = PANEL_CLKSEL | (1 << 12);
	SYN_SIZE         = (LCD_VERTICAL_PERIOD << 16) | (LCD_HORIZONTAL_PERIOD);
	PANEL_VSYNC_TIM  = (0 << 16) | (LCD_VERTICAL_PULSE_WIDTH);
	PANEL_HSYNC_TIM  = (0 << 16) | (LCD_HORIZONTAL_PULSE_WIDTH);
	DE_SIZE          = (LCD_VERTICAL_DISPLAY_PERIOD << 16) | (LCD_HORIZONTAL_DISPLAY_PERIOD);
	DE_START         = (LCD_VERTICAL_BACK_PORCH << 16) | (LCD_HORIZONTAL_BACK_PORCH);
	GRA_VSYNC_TIM    = 0;

	/* グラフィックス部1 初期化 */
	GRCMEN1      = 0x00000002;	/* カレントレイヤ許可、下位レイヤー不許可 */
	GRCBUSCNT1   = 0x00000000;	/* RGB565 */
	GROPSADR1    = GRA1_VRAM_BASE;
	GROPSWH1     = (GRA1_VERTICAL_SIZE << 16) | (GRA1_HORIZONTAL_SIZE);
//	*GROPSOFST1   = GRA1_HORIZONTAL_SIZE * 2;
	GROPSOFST1   = GRA1_HORIZONTAL_OFFSET * 2;
	GROPDPHV1    = ((LCD_VERTICAL_BACK_PORCH - 1 + GRA1_VERTICAL_POS) << 16)
	                    | (LCD_HORIZONTAL_BACK_PORCH - 16 + GRA1_HORIZONTAL_POS);
	GROPBASERGB1 = 0x0000FFFF;	/* グラフィックス画像外色(White) */
	GRCMEN1      = GRCMEN1 | (1 << 31);	/* レジスタ値転送許可 */

	/* グラフィックス部2 初期化 */
	GRCMEN2      = 0x00000001;	/* カレントレイヤ不許可、下位レイヤー許可 */
	GRCMEN2      = GRCMEN2 | (1 << 31);	/* レジスタ値転送許可 */
#if 0
	/* グラフィックス部2 初期化 New */
	GRCMEN2      = 0x00000003;	/* カレントレイヤ許可、下位レイヤー許可 */
	GRCBUSCNT2   = 0x00000010;	/* aRGB:4444 */
	GROPSADR2    = GRA2_VRAM_BASE;
	GROPSWH2     = (GRA2_VERTICAL_SIZE << 16) | (GRA2_HORIZONTAL_SIZE);
	GROPSOFST2   = GRA2_HORIZONTAL_SIZE * 2;
	GROPDPHV2    = ((LCD_VERTICAL_BACK_PORCH - 1 + GRA2_VERTICAL_POS) << 16)
	                    | (LCD_HORIZONTAL_BACK_PORCH - 16 + GRA2_HORIZONTAL_POS);
	GROPBASERGB2 = 0x00000000;	/* グラフィックス画像外色(下位レイヤー許可で無効) */
	GRCMEN2      = *GRCMEN2 | (1 << 31);	/* レジスタ値転送許可 */
#endif
	draw_colorbar(); 
}

/* LCDバックライトON/OFF */
void LCD_SetBackLight( int bool )
{
	/* LCDバックライトイネーブル(PB21(LCD_BLE)信号,正論理) */
//	PBCR5 = PBCR5 & 0xFFCF;
//	PBIOR1= PBIOR1 | 0x0020;

	if ( bool )
		PBDR1 = PBDR1 | 0x0020;
	else
		PBDR1 = PBDR1 & ( ~0x0020 );
}

/*==============================================================================
	LCD拡張ボード搭載プッシュスイッチ制御 

 タクトスイッチですが、タッチパネル制御信号と同じGPIOを使っているので、
 同時使用はできません。タッチパネルを使うか、タクトスイッチを使うかの
 排他使用となります。

 J15とJ8をSWｎの側に切り替えてください。
 ※このサンプルは古いLCD基板用で、SWのI/Oが異なるかも
 
==============================================================================*/
static int SWx, SWxd;
static int SW1, SW2, SW3, SW4, SW5, SW6;

static void PUSHSW_Initialize(void)
{
	/* ポート機能初期化 */
	/* カーソルキー */
	/* ポートPC7,6,5 GPIO選択 */
	PCCR1 = (PCCR1 & 0x000F);
	/* ポートPC2 GPIO選択 */
	PCCR0 = (PCCR0 & 0xF0FF);
	/* 入力方向設定 */
	PCIOR0= PCIOR0 & 0xFF1B;
	/* 選択キー */
	/* ポートPH1,0 GPIO選択 */
	PHCR0 = PHCR0 & 0xFF00;
	/* 入力方向設定(ポートHは入力専用) */

	SWx = SWxd = 0;
	SW1 = SW2 = SW3 = SW4 = SW5 = SW6 = 0 ;
}

/* LCD拡張ボード搭載プッシュスイッチ状態取得 */
static int PUSHSW_GetSW(void)
{
	int i,l;
	/* すべて負論理入力なので反転 */
	i = ~(PCPR0);
	i = ((i>>4)&0xE) | ((i>>2)&1);
	l = (~(PHPR0)) & 3;
	return ((l<<4)|i);
}

static void LCD_GetKey(void)
{
	int code ;

	code = PUSHSW_GetSW();	/* 最新状態取得 */
	/* 7回サンプリングで連続して押されていれば状態確定 */
	if ( code & 0x01 ) SW1++;
	else        SW1=0;
	if ( code & 0x02 ) SW2++;
	else        SW2=0;
	if ( code & 0x04 ) SW3++;
	else        SW3=0;
	if ( code & 0x08 ) SW4++;
	else        SW4=0;
	if ( code & 0x10 ) SW5++;
	else        SW5=0;
	if ( code & 0x20 ) SW6++;
	else        SW6 = 0;

	if (SW1>=7) {
		SWx = SWx | 0x01; SW1 = 7;
	} else {
		SWx = SWx & 0x3E;
	}
	if (SW2>=7) {
		SWx = SWx | 0x02; SW2 = 7;
	} else {
		SWx = SWx & 0x3D;
	}
	if (SW3>=7) {
		SWx = SWx | 0x04; SW3 = 7;
	} else {
		SWx = SWx & 0x3B;
	}
	if (SW4>=7) {
		SWx = SWx | 0x08; SW4 = 7;
	} else {
		SWx = SWx & 0x37;
	}
	if (SW5>=7) {
		SWx = SWx | 0x10; SW5 = 7;
	} else {
		SWx = SWx & 0x2F;
	}
	if (SW6>=7) {
		SWx = SWx | 0x20; SW6 = 7;
	} else {
		SWx = SWx & 0x1F;
	}

	if ((SWx != SWxd) && ( SWx != 0)){/* 状態変化検出&押されているときのみ判定 */
		t_printf("code=%02Xh ･･･ ", SWx);
		if ( SWx & 0x01 ) {
			CPU_UartPuts("SW1(Left) ");
			GxMsgSend(eGEMSG_USEREVENT, eEVTID_KEY_LEFT, 0);
		}
		if ( SWx & 0x02 ) {
			CPU_UartPuts("SW2(Right) ");
			GxMsgSend(eGEMSG_USEREVENT, eEVTID_KEY_RIGHT, 0);
		}
		if ( SWx & 0x04 ) {
			CPU_UartPuts("SW3(Down) ");
			GxMsgSend(eGEMSG_USEREVENT, eEVTID_KEY_DOWN, 0);
		}
		if ( SWx & 0x08 ) {
			CPU_UartPuts("SW4(Up) ");
			GxMsgSend(eGEMSG_USEREVENT, eEVTID_KEY_UP, 0);
		}
		if ( SWx & 0x10 ) {
			CPU_UartPuts("SW5(SelectA) ");
			// とりあえずステージChangeをボタンBに
//			GxMsgSend(eGEMSG_USEREVENT, eEVTID_KEY_CANCEL, 0);
			GxMsgSend(eGEMSG_USEREVENT, eEVTID_KEY_STAGE, 0);
		}
		if ( SWx & 0x20 ) {
			CPU_UartPuts("SW6(SelectB) ");
			GxMsgSend(eGEMSG_USEREVENT, eEVTID_KEY_OK, 0);
		}
		CPU_UartPuts("\n");
	}
	SWxd = SWx;	/* 現在の状態保存 */
}



/*==============================================================================
	Geal初期化
==============================================================================*/
static void init_Geal( void ) 
{
	// Graphicターゲット初期化
	UGxMemset( &m_sTarget, 0, sizeof(m_sTarget) ) ;
	m_sTarget.wX = DISPLAY_WIDTH ;
	m_sTarget.wY = DISPLAY_HEIGHT ;
	m_sTarget.pBits = (GE_VOID *)LCD_OFFSET ;
	m_sTarget.dwLineByte = LCD_LINEINT ;

	// GEAL Engine のシステムメモリを上位側で確保する
	UGxMemset( GXSysMem, 0, sizeof(GXSysMem) ) ;
}

/*==============================================================================
	Message処理
==============================================================================*/
int DispatchMessage(void)
{
	int ret;
	unsigned short  Tx, Ty ;
	unsigned int l;

#ifndef	USE_TOUCH_PANEL
	LCD_GetKey() ;
#else

	if (TOUCH_GetPenDown()) {
		l = TOUCH_GetXY();
		Tx = (unsigned short )(l & 0xFFFF) ;
		Ty = ( unsigned short )(l >> 16) ;
#ifdef	_DEBUG
		t_printf("X=%04Xh  Y=%04Xh\n", Tx , Ty );
#endif
		// 押されている
		oldTx = Tx ;
		oldTy = Ty ;
		Told = Ton ;
		Ton = 1 ;
//		Ttgl = (~Told) & Ton ;
		if (! Ttgl) {	// 押された初回だけ
			GxMsgSend(eGEMSG_MOUSEDOWN, 0, l );
			Ttgl = 1 ;
		}
	}
	else { // 押されていない
		Told = Ton ;
		Ttgl = Ton = 0 ;
		if ( oldTx | oldTy ) {	// 最後の座標=MOUSEUP
			GxMsgSend(eGEMSG_MOUSEUP, 0,
					(((GE_UINT16)oldTy) << 16) | ((GE_UINT16)oldTx));
			oldTx = oldTy = 0 ;
		}
	}
#endif
}


/*==============================================================================
	Main
==============================================================================*/
int main(int argc, char * argv[])
{
	GE_POINT pos ;

	/* CPU 初期化 */
	CPU_BusInitialize();

	/* コンソール(UART)初期化 */
	CPU_UartInitialize();
	CPU_UartPuts("\n\nSH7262 Geal sample demo\n");

	/* LCD拡張ボード初期化 */
	LCD_Initialize();

#ifdef	USE_TOUCH_PANEL
	/* タッチパネル制御初期化 */
	TOUCH_Initialize();
#else
	PUSHSW_Initialize();
#endif

	oldTx = oldTy = 0 ;
	Ttgl = Told = Ton = 0;

	init_Geal() ;
	CPU_UartPuts("\nGeal Init OK\n");

#ifdef	_DEBUG
	// Test draw
	UGxDrawLineHV(&m_sTarget, 60, 60,   0,	20, 0xffff);
	UGxDrawLineHV(&m_sTarget, 60, 60+1,  1, 20, 0xffff);
	UGxDrawLineHV(&m_sTarget, 60+1, 80, 0,	20, 0xffff);
	UGxDrawLineHV(&m_sTarget, 80, 60+1,    1, 20, 0xffff);
	CPU_UartPuts("\nGeal Draw test OK\n");
#endif

	GxInitialize(GXSysMem);
	CPU_UartPuts("\nGeal Menu draw OK\n");

	CPU_EnableInterrupt();

	init_fs();	// FileSystem init 
#ifdef	_DEBUG
	/* 起動メッセージ */
	delay_ms(10);
	CPU_UartPuts(_USE_LFN ? "LFN Enabled" : "LFN Disabled");
	auto_test();	/* FileSystem 自動テストの実行 */
#endif

#ifdef	_WKLCD	//若松通商 WKLCD-2A　PF3->PF7
	CPU_UartPuts("\nGUI JPEG FatFs demo for SH7262 + WKLCD-2A\n");
#else
	CPU_UartPuts("\nGUI JPEG FatFs demo for SH7262 + HSB7264LCD\n");
#endif

	// イベントループ
	while (1)
	{
		DispatchMessage();
		GxProcess();
	}

	// Geal終了
	GxFinalize();

	return 0;
}

/*------------------------------------------------------------------------------
	This API gets current target.
------------------------------------------------------------------------------*/
HTARGET UGxTargetGet()
{
	return (HTARGET)&m_sTarget;
}

