#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <piece.h>
#include <s1c33cpu.h>
#include "c33209.h"
//------------------------------------------------------------------------------
unsigned char vbuff[DISP_X * DISP_Y];
//------------------------------------------------------------------------------
void pceAppInit() {
	pceAppSetProcPeriod(1);
	pceLCDSetBuffer(vbuff);
	pceLCDDispStart();
	//USB SUSPEND信号がオフ⇒オンに変化したら、USBコントローラの割り込みを解除する処理を、IDMAを用いて実行するように設定する。
	//・HSDMAではダメで、IDMAを使う必要が有る。HSDMAではダメな理由は、以下の二つの理由です:
	//  1. K50をトリガとして起動するHSDMAは、HSDMA Ch.0ですが、HSDMA Ch.0はP/ECEカーネルがLCD転送のために使用しており、アプリケーションが使えないから。
	//  2. USBコントローラの割り込みを解除する処理は、少なくとも「書き込み＋読み出し」の二手順が必要で、そのためにはIDMAのリンク機能が必要だから。HSDMAにはリンク機能が無いから。
	{
		static const int TBL_IDMA[2][3]={{
			//IDMA Ch.0
			0x00000000,			//TC=0,LINKCHN=x,LINKEN=0	//実際にはconstではなく、IDMAによって書換えられる。(1^24)回サスペンドするまで終わらないので、実用上充分です。	//この構造体をフラッシュROM上に置けば、本当にconstにできると思うかも知れませんが、それは不可です。IDMAは常に(CPUが割り込み禁止でも)起動する可能性が有り、フラッシュROMの書き換え中にIDMAが起動する可能性も有り、フラッシュROMの書き換え中にフラッシュROMへのアクセスが生じ、フラッシュROMの書き換えが失敗するからです。この構造体をSRAM上に置いておけば、フラッシュROMの書き換え中にIDMAが起動しても問題は生じません。
			0x00400000,				//SRADR=D12_DATA,SRINC=DIN_FIXED,DATSIZ=byte,DINTEN=0
			0x01000000,				//DSADR=Areas 12-11,DSINC=DIN_FIXED,DMOD=DMOD_SINGLE
		},{	//IDMA Ch.1
			0x80000000,			//TC=0,LINKCHN=0,LINKEN=0	//実際にはconstではなく、IDMAによって書換えられる。(1^24)回サスペンドするまで終わらないので、実用上充分です。	//この構造体をフラッシュROM上に置けば、本当にconstにできると思うかも知れませんが、それは不可です。IDMAは常に(CPUが割り込み禁止でも)起動する可能性が有り、フラッシュROMの書き換え中にIDMAが起動する可能性も有り、フラッシュROMの書き換え中にフラッシュROMへのアクセスが生じ、フラッシュROMの書き換えが失敗するからです。この構造体をSRAM上に置いておけば、フラッシュROMの書き換え中にIDMAが起動しても問題は生じません。
			(int)(const unsigned char[]){0xF4},	//SRADR=READ_INTERRUPT_REGISTER,SRINC=DIN_FIXED,DATSIZ=byte,DINTEN=0
			0x00400004,				//DSADR=D12_COMMAND,DSINC=DIN_FIXED,DMOD=DMOD_SINGLE
		}};
	//DISABLE;	//IDMA割り込みは使用しないので、設定中の割り込み禁止は不要
		//Port input interrupt select register
		bPINTSEL_SPT03_SPT0 = 1/*K50*/;			//FPT0 interrupt input port selection
		//Port input interrupt input polarity select register
		bPINTPOL_SPPT_SPP0 = 1/*high*/;			//FPT0 input polarity selection
		//Port input interrupt edge/level select register
		bPINTEL_SEPT_SEPT0 = 1/*edge*/;			//FPT0 edge/level selection
		//IDMA control register
		IDMAEN_DISABLE;					//IDMA enable
		pIDMA_DBASE	= (int)TBL_IDMA;		//IDMA base address (0x48200)
		IDMAEN_ENABLE;					//IDMA enable
		//Port input 0-3, high-speed DMA, 16-bit timer 0 IDMA request register
		bIDMAREQ_RP03_RHS_R16T0_RP0	= 1;		//Port input 0 IDMA request
		//Port input 0-3, high-speed DMA, 16-bit timer 0 IDMA enable register
		bIDMAEN_DEP03_DEHS_DE16T0_DEP0	= 1;		//Port input 0 IDMA enable
	//ENABLE;	//IDMA割り込みは使用しないので、設定中の割り込み禁止は不要
	}
}
//------------------------------------------------------------------------------
void pceAppProc(int cnt) {
	int t;
	memset(vbuff, 0, sizeof vbuff);
	pceFontSetPos(0, 0);
	pceFontSetTxColor(3);
	pceFontSetBkColor(0);
	pceFontPrintf("割込許可 %d", cnt);
	pceLCDTrans();
	//Aボタンが押されたら、割り込みを禁止して、5秒間待つ。
	//・USB SUSPEND信号がオフ⇒オンに変化したら、IDMAが自動的にUSBコントローラの割り込みを解除する処理を行う。
	//  IDMAは、CPUの割り込みが禁止されていても動作するので、CPUが長期間割り込み禁止していても問題なく、2ミリ秒以内にUSBコントローラの割り込みを解除することができる。
	//・IDMAのトリガとして、USB割り込み信号(K51)ではなく、USB SUSPEND信号(K50)を使用する理由は、前者ではサスペンド以外のUSB割り込みにも反応してしまうからです。
	//  サスペンド以外のUSB割り込みにも反応してしまうと、普通のUSB通信で発生するUSB割り込みにも反応して割り込みをクリアしてしまい、正しく動作しません。
	//  従って、IDMAのトリガとして、USB割り込み信号(K51)ではなく、USB SUSPEND信号(K50)を使用する必要が有ります。
	//  都合の良いことに、K50をトリガとして起動するIDMA Ch.1でUSBコントローラに書き込み、リンクしてIDMA Ch.0を起動してUSBコントローラから読み出す、という最小限の手順でUSBコントローラの割り込みを解除するようにすると、
	//  使用するIDMAチャネルはCh.0とCh.1で、IDMAコントロール情報のメモリは先頭2チャネル分の最小限で済みます。偶然ですが、とても綺麗に纏まりました。
	if(pcePadGet() & TRG_A) {
DISABLE;
		memset(vbuff, 3, sizeof vbuff);
		pceFontSetPos(0, 0);
		pceFontSetTxColor(0);
		pceFontSetBkColor(3);
		pceFontPrintf("割込禁止開始");
		pceLCDTrans();
		t = pceTimerGetCount();
		do {
			/** no job **/
		} while((pceTimerGetCount() - t) < 5000);
		memset(vbuff, 3, sizeof vbuff);
		pceFontSetPos(0, 0);
		pceFontSetTxColor(0);
		pceFontSetBkColor(3);
		pceFontPrintf("割込禁止終了");
		pceLCDTrans();
ENABLE;
	}
	//SELECTボタンが押されたら終了する。
	if(pcePadGet() & TRG_SELECT) { pceAppReqExit(0); }
}
//------------------------------------------------------------------------------
void pceAppExit() {
	//USB SUSPEND信号がオフ⇒オンに変化したら、USBコントローラの割り込みを解除する処理を、IDMAを用いて実行する設定を解除する。
	{
	//DISABLE;	//IDMA割り込みは使用しないので、設定中の割り込み禁止は不要
		//IDMA control register
		IDMAEN_DISABLE;				//IDMA enable
		//Port input 0-3, high-speed DMA, 16-bit timer 0 IDMA request register	//┐
		bIDMAREQ_RP03_RHS_R16T0_RP0	= 0;	//Port input 0 IDMA request	//├動作上はIDMAEN_DISABLEだけでも良いが、一応こちらもクリアしておくことにした。
		//Port input 0-3, high-speed DMA, 16-bit timer 0 IDMA enable register	//│
		bIDMAEN_DEP03_DEHS_DE16T0_DEP0	= 0;	//Port input 0 IDMA enable	//┘
	//ENABLE;	//IDMA割り込みは使用しないので、設定中の割り込み禁止は不要
	}
}
