/***************************************************************
	タッチパネル制御ルーチン
***************************************************************/

/* CPU固有レジスタ定義ヘッダ */
#include "cpu.h"

/* CPU初期化/割り込み制御関数ヘッダ */
#include "cpu_init.h"


/* タッチパネル制御変数 */
volatile int TOUCH_Xmin;
volatile int TOUCH_Xmax;
volatile int TOUCH_Ymin;
volatile int TOUCH_Ymax;
volatile int TOUCH_stat;
volatile int TOUCH_PD;
volatile int TOUCH_nPDcnt;
volatile int TOUCH_Xtmp;
volatile int TOUCH_X;
volatile int TOUCH_Ytmp;
volatile int TOUCH_Y;

/* キャリブレーションデフォルト値 */
#define TOUCH_Xmindefault 0x060
#define TOUCH_Xmaxdefault 0x3AF;
#define TOUCH_Ymindefault 0x070;
#define TOUCH_Ymaxdefault 0x38F;

/* パネル解像度(ドット/ライン) */
#define LCD_WIDTH 320
#define LCD_HIGHT 240



/* Y座標入力(XIN) A-D入力変換開始 */
void TOUCH_ADXstart(void)
{
	*ADCSR = 0x2000; /* チャネル0変換開始 */
}

/* Y座標入力(XIN) A-D入力変換結果取得 */
unsigned short int TOUCH_ADXin(void)
{
	unsigned short int value;
	value = *ADCSR;  /* 空読み */
	*ADCSR = 0x0000; /* 変換終了 */
	value = *ADDRA;
	return (value>>6);
}

/* X座標入力(YIN) A-D入力変換開始 */
void TOUCH_ADYstart(void)
{
	*ADCSR = 0x2001; /* チャネル1変換開始 */
}

/* X座標入力(YIN) A-D入力変換結果取得 */
unsigned short int TOUCH_ADYin(void)
{
	unsigned short int value;
	value = *ADCSR;  /* 空読み */
	*ADCSR = 0x0001; /* 変換終了 */
	value = *ADDRB;
	return (value>>6);
}

/* ハイインピーダンス処理 */
void TOUCH_AllHiZ(void)
{
	/* X1:PC2 X2:PC6 Y1:PC5 Y2:PC7 All input */
	*PCIOR0 = (*PCIOR0 & 0xFF1B);
}

/* X座標取得用X方向電圧差生成処理 */
void TOUCH_X1X2(int i)
{
	if (i) {
		/* X1:PC2='H' X2:PC6='L' */
		*PCDR0 = (*PCDR0 & 0xFF1B) | 0x0004;
	} else {
		/* X1:PC2='L' X2:PC6='H' */
		*PCDR0 = (*PCDR0 & 0xFF1B) | 0x0040;
	}
	/* X1:PC2 X2:PC6  PC5,PC7:input */
	*PCIOR0 = (*PCIOR0 & 0xFF1B) | 0x0044;
}

/* Y座標取得用Y方向電圧差生成処理 */
void TOUCH_Y1Y2(int i)
{
	if (i) {
		/* Y1:PC5='H' Y2:PC7='L' */
		*PCDR0 = (*PCDR0 & 0xFF1B) | 0x0020;
	} else {
		/* Y1:PC5='L' Y2:PC7='H' */
		*PCDR0 = (*PCDR0 & 0xFF1B) | 0x0080;
	}
	/* Y1:PC5 Y2:PC7  PC6,PC2:input */
	*PCIOR0 = (*PCIOR0 & 0xFF1B) | 0x00A0;
}

/* タッチパネル ペンダウン検出準備 */
void TOUCH_PenDownInitialize(void)
{
	/* ペンダウン検出用プルダウン抵抗制御ポートPE3='L' */
	*PECR0 = *PECR0  & 0x0FFF;	/* GPIO選択 */
	*PEIOR0= *PEIOR0 | 0x0008;	/* PE3 出力 */
	*PEDR0 = *PEDR0  & 0xFFF7;	/* PE3 出力レジスタ'L' */
	/* ペンダウン検出用'H'レベル出力処理 */
	/* Y1:PC7='H' Y2:PC5='H' */
	*PCDR0 = (*PCDR0 & 0xFF1B) | 0x00A0;
	/* Y1:PC7 Y2:PC5  PC6,PC2:input */
	*PCIOR0 = (*PCIOR0 & 0xFF1B) | 0x00A0;
}

/* タッチパネル ペンダウン検出 */
int TOUCH_PenDownCheck(void)
{
	int i;
	/* LCD_X2(ポートPC6)状態判定 */
	i = *PCPR0 & 0x40;	/* 押されていたら0以外 */
	/* ペンダウン検出用プルダウン抵抗制御ポートPE3 HiZ */
	*PEIOR0= *PEIOR0 & 0xFFF7;	/* PE3 入力 */
	return i;
}

/* タッチパネル処理用タイマ割り込み処理(数ms周期でコールすること) */
void TOUCH_Interrupt(void)
{
	switch(TOUCH_stat) {

	case 0 :
		/* タッチパネル ペンダウン検出準備 */
		TOUCH_PenDownInitialize();
		TOUCH_stat++;
		break;
	case 1 :
		/* タッチパネル ペンダウン検出 */
		if (TOUCH_PenDownCheck()) {
			/* タッチパネル ペンダウン検出準備 */
			TOUCH_PenDownInitialize();
			TOUCH_stat++;

//			/* 割り込み周期が長くなっていた場合は戻す */
//			if (TOUCH_nPDcnt >= 200) {
//				CMT0_TimerSet(1); /* 割り込み周期を元に戻す */
//			}
			TOUCH_nPDcnt = 0;

		} else {
			/* ハイインピーダンス処理 */
			TOUCH_AllHiZ();
			TOUCH_PD = 0;
			TOUCH_stat = 0;

			/* 長時間ペンダウンが検出されない場合 */
//			if (TOUCH_nPDcnt == 200) {	/* 数秒経過 */
//				CMT0_TimerSet(100);	/* 割り込み周期を遅くする */
//			} else if (TOUCH_nPDcnt < 200) {
				TOUCH_nPDcnt++;
//			}

		}
		break;
	case 2 :
		/* タッチパネル ペンダウン検出 */
		if (TOUCH_PenDownCheck()) {
			/* X座標判定準備 */
			TOUCH_X1X2(1);
			TOUCH_stat++;
		} else {
			/* ハイインピーダンス処理 */
			TOUCH_AllHiZ();
			TOUCH_PD = 0;
			TOUCH_stat = 0;
		}
		break;

	case 3 :
		/* X座標入力(YIN) A-D入力変換開始 */
		TOUCH_ADYstart();
		TOUCH_stat++;
		break;
	case 4 :
		/* X座標入力(YIN) A-D入力変換結果取得 */
		TOUCH_Xtmp = TOUCH_ADYin();
		/* Y座標判定準備 */
		TOUCH_Y1Y2(1);
		TOUCH_stat++;
		break;
	case 5 :
		/* Y座標入力(XIN) A-D入力変換開始 */
		TOUCH_ADXstart();
		TOUCH_stat++;
		break;
	case 6 :
		/* Y座標入力(XIN) A-D入力変換結果取得 */
		TOUCH_Ytmp = TOUCH_ADXin();
		/* タッチパネル ペンダウン検出準備 */
		TOUCH_PenDownInitialize();
		TOUCH_stat++;
		break;
	case 7 :
		/* タッチパネル ペンダウン検出 */
		if (TOUCH_PenDownCheck()) {
			/* タッチパネル ペンダウン検出準備 */
			TOUCH_PenDownInitialize();
			TOUCH_stat++;
		} else {
			/* ハイインピーダンス処理 */
			TOUCH_AllHiZ();
			TOUCH_PD = 0;
			TOUCH_stat = 0;
		}
		break;
	case 8 :
		/* タッチパネル ペンダウン検出 */
		if (TOUCH_PenDownCheck()) {
			/* 最終確定座標保持 */
			TOUCH_PD = 1;
			TOUCH_X = TOUCH_Xtmp;
			TOUCH_Y = TOUCH_Ytmp;
		} else {
			/* ハイインピーダンス処理 */
			TOUCH_AllHiZ();
			TOUCH_PD = 0;
		}
		TOUCH_stat = 0;
		break;
	}

}

/* タッチパネル制御初期化 */
void TOUCH_Initialize(void)
{
	/* ポートPC7,6,5 GPIO選択 */
	*PCCR1 = (*PCCR1 & 0x000F);
	/* ポートPC2 GPIO選択 */
	*PCCR0 = (*PCCR0 & 0xF0FF);
	TOUCH_AllHiZ();
	/* ポートAN0とAN1をA-D変換ポートとして利用する */
	*PHCR0 = (*PHCR0 & 0xFF00) | 0x0011;
	/* ペンダウン検出用プルダウン抵抗制御ポートPE3 HiZ */
	*PECR0 = *PECR0  & 0x0FFF;	/* GPIO選択 */
	*PEIOR0= *PEIOR0 & 0xFFF7;	/* PE3 入力 */
	*PEDR0 = *PEDR0  & 0xFFF7;	/* PE3 出力レジスタ'L' */
	/* A-Dコンバータ スタンバイ解除 */
	*STBCR3= *STBCR3 & 0xFB;

	/* 使用変数初期化 */
	/* 最大/最小値のデフォルト値を代入 */
	TOUCH_Xmin = TOUCH_Xmindefault;
	TOUCH_Xmax = TOUCH_Xmaxdefault;
	TOUCH_Ymin = TOUCH_Ymindefault;
	TOUCH_Ymax = TOUCH_Ymaxdefault;
	/* ↑変数に格納しているので、ユーザ操作でキャリブレーションさせることも可能 */
	TOUCH_stat = 0;
	TOUCH_PD = TOUCH_nPDcnt = 0;
	TOUCH_Xtmp = TOUCH_X = 0;
	TOUCH_Ytmp = TOUCH_Y = 0;

//	/* コンペアマッチタイマ0 初期化 */
//	CMT0_Initialize();
}


/* タッチパネル ペンダウン状態取得 */
int TOUCH_GetPenDown(void)
{
	return TOUCH_PD;
}

/* タッチパネル タッチ座標取得(A-D変換値) */
unsigned int TOUCH_GetXYvalue(void)
{
	return ((TOUCH_Y) << 16) | TOUCH_X;
}

/* タッチパネル タッチ座標取得(ドット座標) */
unsigned int TOUCH_GetXY(void)
{
	int x, y;
	double xd, yd;
	xd = (double)TOUCH_X;
	yd = (double)TOUCH_Y;
	xd = ((xd - TOUCH_Xmin) / (TOUCH_Xmax - TOUCH_Xmin)) * 320;
	yd = ((yd - TOUCH_Ymin) / (TOUCH_Ymax - TOUCH_Ymin)) * 240;
	x = (int)xd;
	if (x < 0) x = 0;
	if (x > (LCD_WIDTH - 1)) x = (LCD_WIDTH - 1);
	y = LCD_HIGHT - (int)yd; /* Y軸のみひっくり返す */
	if (y < 0) y = 0;
	if (y > (LCD_HIGHT - 1)) y = (LCD_HIGHT - 1);
	return (y << 16) | x;
}


