///////////////////////////////////////////////////////////////////////////
// タッチパネル(UART)
//
// 2015/12/22
///////////////////////////////////////////////////////////////////////////
#define	MONITOR_DEF_UART
#include "Monitorbase.h"

#define	TOUCH_BPS				(38400)
#define	UART_PORT				(UART6_BASE)
#define	INTP_PORT				(INT_UART6)

#define	USE_TOUCH_TIMER	(0)							// 離した時の検出にタイマーを使う場合 1 ※指IDについて考えられていないので使用する時は注意！

#define	USE_MULTI_TOUCH	(0)							// マルチタッチ使用時は 1
#define	FINGER_NUMS			(USE_MULTI_TOUCH * 15 + 1)
BYTE	gbaTouchNow[FINGER_NUMS];
WORD	gwaTouchPosition[FINGER_NUMS][2];					// 指、XとY

#define	BUF_SIZE				(0x3F)
BYTE	gbaTouchBuf[BUF_SIZE + 1];				// 受信バッファー
BYTE	gbTouchBufPosition = 0;

DWORD	gdwOneShotTimeout;

#define	MOVE_LIMIT			(5)							// これより大きく移動していた場合を移動とする

// イベントが発生したら内容を関数渡しするためのポインター
static int32_t (*g_pfnTSHandler)(uint32_t ui32Message, int32_t i32X, int32_t i32Y);

const	BYTE	cbaMultiTouch[] = {					// マルチタッチの設定 0x04 / シングルタッチ 0x00
#if	USE_MULTI_TOUCH == 1		//[[[
	0xA3 , 0x02 , 0x04
#endif		//]]]
#if USE_MULTI_TOUCH == 0		//[[[
	0xA3 , 0x02 , 0x00
#endif		//]]]
};

bool	TouchSetCommand(const BYTE *pDat,BYTE bLength);

//////////////////////////////////////////////////////////// [[[
// 初期化関数
//	引数
//		クロックを設定した際の戻り値
//	戻り値
//		true / false
bool	TouchInit(uint32_t dwSysClock){
	BYTE	b;

	// イベント渡し用の関数は未定義（別途関数を呼ぶこと）
	g_pfnTSHandler = 0;
	
	// 通信速度等
	ROM_UARTConfigSetExpClk(UART_PORT,dwSysClock,TOUCH_BPS,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

	// FIFOの許可
	ROM_UARTFIFOEnable(UART_PORT);

	// 割り込みの許可設定 / RX:受信 / RT:受信タイムアウト
	ROM_UARTIntEnable(UART_PORT,(UART_INT_RX | UART_INT_RT));

#if USE_TOUCH_TIMER == 1		//[[[ プロトコル仕様書で離れた場合の取得が可能と解ったのでワンショットタイマー削除 2015/12/24
	// 使用許可
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
	// タイマー初期化 ワンショット
	ROM_TimerConfigure(TIMER2_BASE,TIMER_CFG_ONE_SHOT | TIMER_CFG_A_ACT_CLRSETTO);
	// 周期のセット SysCtlClockGet() = 1sec : 10msec = Clock / 100
	gdwOneShotTimeout = (DWORD)(dwSysClock / 100);		// 最適化ナシだと、何故か止まってしまう
	//gdwOneShotTimeout = 1200000;
	ROM_TimerLoadSet(TIMER2_BASE, TIMER_A, (uint32_t)gdwOneShotTimeout);
	// 割り込みの許可
	ROM_IntEnable(INT_TIMER2A);
	ROM_TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
#endif		//]]]
	
	// マルチタッチの設定送信
	TouchSetCommand(cbaMultiTouch,cbaMultiTouch[1]);
	
	for(b=0;b<FINGER_NUMS;b++){
		gbaTouchNow[b] = TOUCH_STATE_UP;
		gwaTouchPosition[b][0] = 0;
		gwaTouchPosition[b][1] = 0;
	}

	return true;
}

///////////////////////////////////////////////////////////////////////////
// 割り込み許可
// 引数
//		true : 許可 / false : 不許可
// 戻り値
//		ナシ
///////////////////////////////////////////////////////////////////////////
void	TouchInterruptEnable(bool blFlag){
	if(blFlag == true){
		ROM_IntEnable(INTP_PORT);
	} else {
		ROM_IntDisable(INTP_PORT);
	}
	return;
}

///////////////////////////////////////////////////////////////////////////
// UART許可
// 引数
//		true : 許可 / false : 不許可
// 戻り値
//		ナシ
///////////////////////////////////////////////////////////////////////////
void	TouchEnable(bool blFlag){
	if(blFlag == true){
		ROM_UARTEnable(UART_PORT);
	} else {
		ROM_UARTDisable(UART_PORT);
	}
	return;
}

///////////////////////////////////////////////////////////////////////////
// 送信処理（チェックサムの計算付き）
// 引数
//		送信データ（チェックサムナシ）へのポインター、長さ
// 戻り値
//		処置を行った場合、true
///////////////////////////////////////////////////////////////////////////
bool	TouchSetCommand(const BYTE *pDat,BYTE bLength){
	bool	bRet = false;
	BYTE	bChrPos;;
	WORD	wCheckSum = 0;

	if(ROM_UARTBusy(UART_PORT) == false){
		// 忙しくないようなので処理を行う
		IntDisable(INTP_PORT);												// 割り込み禁止
		for(bChrPos=0;bChrPos<bLength;bChrPos++){
			ROM_UARTCharPut(UART_PORT,*(pDat + bChrPos));
			wCheckSum += *(pDat + bChrPos);
		}
		ROM_UARTCharPut(UART_PORT,(BYTE)(wCheckSum & 0x007F));		// チェックサム
		ROM_UARTCharPut(UART_PORT,0x00);
		IntEnable(INTP_PORT);													// 割り込み禁止解除
		bRet = true;
	}
	return bRet;
}


///////////////////////////////////////////////////////////////////////////
// 受信割り込み処理
///////////////////////////////////////////////////////////////////////////
void	UartRxGetIntHandler(void){
	DWORD	dwIntStat;
	DWORD	dwGetData;
	//BYTE	baBuf[64];
	//BYTE	bPos = 0;
	WORD	wPositX = 0;
	WORD	wPositY = 0;
	BYTE	bGet = 0xFF;
	bool	blValGet = false;
	bool	blMove;
	BYTE	bFingerID = 0;
	bool	blRelease = false;			// 離れた時、true

	// 割り込み要因の取得 false(raw)側は要らないのか？
	dwIntStat = ROM_UARTIntStatus(UART_PORT,true);
	// 割り込みフラグのクリア
	ROM_UARTIntClear(UART_PORT,dwIntStat);

	while(ROM_UARTCharsAvail(UART_PORT)){
		// 受信データアリ
		dwGetData = ROM_UARTCharGetNonBlocking(UART_PORT);					// 受信データの取得
		/*
		gbaTouchBuf[gwTouchBufPosition] = (BYTE)dw;
		gwTouchBufPosition++;
		gwTouchBufPosition &= 0x3FF;
		*/
		gbaTouchBuf[gbTouchBufPosition] = (BYTE)dwGetData;
		if((BYTE)(dwGetData & 0x00C0) == 0x80){										// 0x8X で指検出
			if(gbTouchBufPosition >= 3){
				if( (gbaTouchBuf[gbTouchBufPosition-1] == 0x14) &&		// 固定値
					 	(gbaTouchBuf[gbTouchBufPosition-2] == 0x07) &&		// 長さ
						(gbaTouchBuf[gbTouchBufPosition-3] == 0xDC) ){		// ヘッダー
					bGet = 0;
#if USE_MULTI_TOUCH == 1		//[[[
					bFingerID = (BYTE)(dwGetData & 0x03C) >> 2;
#endif		//]]]
					if((BYTE)(dwGetData & 0x001) == 0){
						blRelease = true;
					}
				}
			}
		}
		if(bGet != 0xFF){	bGet++;	}
		if(bGet == 4){
			if(gbTouchBufPosition > 3){
				wPositX = MAKEWORD(gbaTouchBuf[gbTouchBufPosition],gbaTouchBuf[gbTouchBufPosition-1]);
				wPositY = MAKEWORD(gbaTouchBuf[gbTouchBufPosition-2],gbaTouchBuf[gbTouchBufPosition-3]);
				blValGet = true;
			}
		}
		gbTouchBufPosition++;
		gbTouchBufPosition &= BUF_SIZE;
	}
	if(blValGet == true){
		wPositX = (WORD)(wPositX / 20.24);				// 0〜3F3Fなので20.24で割ると座標が出てくる（ただし逆方向）
		wPositY = (WORD)(wPositY / 33.74);				// 0〜3F3Fなので33.733...で割ると座標が出てくる
		if(wPositX >= 800){	wPositX = 799;	}
		if(wPositY >= 480){	wPositY = 479;	}
		wPositX = 800 - wPositX;
		blMove = false;									// 移動したかの判定
		if(gwaTouchPosition[bFingerID][0] > wPositX){
			if(gwaTouchPosition[bFingerID][0] - wPositX > MOVE_LIMIT){
				blMove = true;
			}
		} else {
			if(wPositX - gwaTouchPosition[bFingerID][0] > MOVE_LIMIT){
				blMove = true;
			}
		}
		if(gwaTouchPosition[bFingerID][1] > wPositY){
			if(gwaTouchPosition[bFingerID][1] - wPositY > MOVE_LIMIT){
				blMove = true;
			}
		} else {
			if(wPositY - gwaTouchPosition[bFingerID][1] > MOVE_LIMIT){
				blMove = true;
			}
		}																// 移動したかの判定（ここまで）
		gwaTouchPosition[bFingerID][0] = wPositX;
		gwaTouchPosition[bFingerID][1] = wPositY;
		switch(gbaTouchNow[bFingerID]){
		case TOUCH_STATE_DOWN:
			if(blMove == true){						// 座標が異なるので移動した
				if(blRelease == true){			// 指が離れた
					gbaTouchNow[bFingerID] = TOUCH_STATE_UP;
				} else {
					gbaTouchNow[bFingerID] = TOUCH_STATE_MOVE;
				}
				if(g_pfnTSHandler){					// イベント渡し
					g_pfnTSHandler(gbaTouchNow[bFingerID], gwaTouchPosition[bFingerID][0], gwaTouchPosition[bFingerID][1]);
				}
			} else {
				if(blRelease == true){			// 指が離れた
					gbaTouchNow[bFingerID] = TOUCH_STATE_UP;
					if(g_pfnTSHandler){				// イベント渡し
						g_pfnTSHandler(gbaTouchNow[bFingerID], gwaTouchPosition[bFingerID][0], gwaTouchPosition[bFingerID][1]);
					}
				}
			}
			break;
		case TOUCH_STATE_MOVE:
			if(blMove == false){					// 座標が異なるので移動していない
				//gbaTouchNow[0] = TOUCH_STATE_DOWN;
				//if(g_pfnTSHandler){					// イベント渡し
				//	g_pfnTSHandler(gbaTouchNow[0], gwaTouchPosition[0][0], gwaTouchPosition[0][1]);
				//}
			}
			if(blRelease == true){				// 指が離れた
				gbaTouchNow[bFingerID] = TOUCH_STATE_UP;
				if(g_pfnTSHandler){					// イベント渡し
					g_pfnTSHandler(gbaTouchNow[bFingerID], gwaTouchPosition[bFingerID][0], gwaTouchPosition[bFingerID][1]);
				}
			}
			break;
		case TOUCH_STATE_UP:
			gbaTouchNow[bFingerID] = TOUCH_STATE_DOWN;
			if(g_pfnTSHandler){						// イベント渡し
				g_pfnTSHandler(gbaTouchNow[bFingerID], gwaTouchPosition[bFingerID][0], gwaTouchPosition[bFingerID][1]);
			}
			break;
		}
		gbTouchBufPosition = 0;
	}
	//gblTouchNow[0] = blValGet;			// タッチ状態の取得になるかと思ったが、そうは行かない模様

#if USE_TOUCH_TIMER == 1		//[[[
	ROM_TimerDisable(TIMER2_BASE,TIMER_A);
	ROM_TimerLoadSet(TIMER2_BASE, TIMER_A, (uint32_t)gdwOneShotTimeout);
	ROM_TimerEnable(TIMER2_BASE,TIMER_A);
#endif		//]]]
	return;
}

///////////////////////////////////////////////////////////////////////////
// ワンショットタイマー割り込み処理
///////////////////////////////////////////////////////////////////////////
#if USE_TOUCH_TIMER == 1		//[[[
void	OneShotIntHandler(void){
	ROM_TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
	ROM_TimerDisable(TIMER2_BASE,TIMER_A);

	gbaTouchNow[0] = TOUCH_STATE_UP;
	if(g_pfnTSHandler){								// イベント渡し
		g_pfnTSHandler(gbaTouchNow[0], gwaTouchPosition[0][0], gwaTouchPosition[0][1]);
	}
	return;
}
#endif		//]]]

///////////////////////////////////////////////////////////////////////////
// イベント渡し用関数のセット（UP、DWON、MOVEと座標が渡されることになる）
///////////////////////////////////////////////////////////////////////////
void	TouchScreenCallbackSet(int32_t (*pfnCallback)(uint32_t ui32Message, int32_t i32X, int32_t i32Y)){
	// Save the pointer to the callback function.
	g_pfnTSHandler = pfnCallback;
	return;
}
