#include "iodefine.h"
#include "dma_ctrl.h"
#ifdef USE_CHECK
#include "check.h"
#endif

#define MP3_FRAME_SIZE 1152
static int frame_buf[2][MP3_FRAME_SIZE];
static short* p;
static int size;
static int status;

void init_dma()
{
	DMAC.DMAOR.BIT.DME = 0;

	/* CH0 優先度最高 SRCからSSIFへのデータ供給 */
	DMAC.CHCR0.BIT.DE = 0;

	DMAC.SAR0.LONG			= (unsigned long)&SRC0.SRCOD.LONG;	/* ソースアドレスレジスタ */
	DMAC.RSAR0.LONG			= (unsigned long)&SRC0.SRCOD.LONG;	/* リロードソースアドレスレジスタ */
	DMAC.DAR0.LONG			= (unsigned long)&SSIF2.SSIFTDR;	/* デスティネーションアドレスレジスタ */
	DMAC.DMATCR0.LONG		= 1;	/* トランスファカウントレジスタ */
	DMAC.RDMATCR0.LONG		= 1;	/* リロードトランスファカウントレジスタ */

	DMAC.CHCR0.BIT.TC		= 0;	/* トランスファカウントモード */
	DMAC.CHCR0.BIT.RLDSAR	= 1;	/* SARリロード機能ON/OFF:リロードする */
	DMAC.CHCR0.BIT.RLDDAR	= 0;	/* DARリロード機能ON/OFF */
//	DMAC.CHCR0.BIT.DAF		= 0;	/* デスティネーションアドレス固定16バイト転送 */
//	DMAC.CHCR0.BIT.SAF		= 0;	/* ソースアドレス固定16バイト転送 */
//	DMAC.CHCR0.BIT.DO		= 0;	/* DMAオーバラン */
//	DMAC.CHCR0.BIT.TL		= 0;	/* トランスファエンドレベル */
	DMAC.CHCR0.BIT.TEMASK	= 1;	/* TEセットマスク:停止しない(エンドレス) */
//	DMAC.CHCR0.BIT.HE		= 0;	/* ハーフエンドフラグ */
	DMAC.CHCR0.BIT.HIE		= 0;	/* ハーフエンドインタラプトイネーブル */
//	DMAC.CHCR0.BIT.AM		= 0;	/* アクノリッジモード */
//	DMAC.CHCR0.BIT.AL		= 0;	/* アクノリッジレベル */
	DMAC.CHCR0.BIT.DM		= 0;	/* デスティネーションアドレスモード */
	DMAC.CHCR0.BIT.SM		= 0;	/* ソースアドレスモード */
	DMAC.CHCR0.BIT.RS		= 8;	/* リソースセレクト:DMA拡張リソース */
//	DMAC.CHCR0.BIT.DL		= 0;	/* DREQレベル */
//	DMAC.CHCR0.BIT.DS		= 0;	/* DREQエッジセレクト */
	DMAC.CHCR0.BIT.TB		= 0;	/* トランスファバスモード */
	DMAC.CHCR0.BIT.TS		= 2;	/* トランスファサイズ:ロングワード */
	DMAC.CHCR0.BIT.IE		= 0;	/* インタラプトイネーブル */
//	DMAC.CHCR0.BIT.TE		= 0;	/* トランスファエンドフラグ */
	DMAC.CHCR0.BIT.DE		= 1;	/* DMAイネーブル */

	DMAC.DMARS0.BIT.CH0MID	= 0x0a;	/* SSIF2 */
	DMAC.DMARS0.BIT.CH0RID	= 3;	/* SSIF2 */

	/* CH1 MADLIBデコードバッファからSRCへのデータ供給 */
	DMAC.CHCR1.BIT.DE = 0;

	DMAC.SAR1.LONG			= (unsigned long)frame_buf;	/* ソースアドレスレジスタ */
	DMAC.RSAR1.LONG			= (unsigned long)frame_buf;	/* リロードソースアドレスレジスタ */
	DMAC.DAR1.LONG			= (unsigned long)&SRC0.SRCID.LONG;	/* デスティネーションアドレスレジスタ */
	DMAC.DMATCR1.LONG		= 2 * MP3_FRAME_SIZE;	/* トランスファカウントレジスタ */
	DMAC.RDMATCR1.LONG		= 2 * MP3_FRAME_SIZE;	/* リロードトランスファカウントレジスタ */

	DMAC.CHCR1.BIT.TC		= 0;	/* トランスファカウントモード */
	DMAC.CHCR1.BIT.RLDSAR	= 1;	/* SARリロード機能ON/OFF:リロードする */
	DMAC.CHCR1.BIT.RLDDAR	= 0;	/* DARリロード機能ON/OFF */
//	DMAC.CHCR1.BIT.DAF		= 0;	/* デスティネーションアドレス固定16バイト転送 */
//	DMAC.CHCR1.BIT.SAF		= 0;	/* ソースアドレス固定16バイト転送 */
////	DMAC.CHCR1.BIT.DO		= 0;	/* DMAオーバラン */
////	DMAC.CHCR1.BIT.TL		= 0;	/* トランスファエンドレベル */
	DMAC.CHCR1.BIT.TEMASK	= 1;	/* TEセットマスク:停止しない(エンドレス) */
//	DMAC.CHCR1.BIT.HE		= 0;	/* ハーフエンドフラグ */
	DMAC.CHCR1.BIT.HIE		= 0;	/* ハーフエンドインタラプトイネーブル */
////	DMAC.CHCR1.BIT.AM		= 0;	/* アクノリッジモード */
////	DMAC.CHCR1.BIT.AL		= 0;	/* アクノリッジレベル */
	DMAC.CHCR1.BIT.DM		= 0;	/* デスティネーションアドレスモード */
	DMAC.CHCR1.BIT.SM		= 1;	/* ソースアドレスモード:増加 */
	DMAC.CHCR1.BIT.RS		= 8;	/* リソースセレクト:DMA拡張リソース */
////	DMAC.CHCR1.BIT.DL		= 0;	/* DREQレベル */
////	DMAC.CHCR1.BIT.DS		= 0;	/* DREQエッジセレクト */
	DMAC.CHCR1.BIT.TB		= 0;	/* トランスファバスモード */
	DMAC.CHCR1.BIT.TS		= 2;	/* トランスファサイズ:ロングワード */
	DMAC.CHCR1.BIT.IE		= 0;	/* インタラプトイネーブル */
//	DMAC.CHCR1.BIT.TE		= 0;	/* トランスファエンドフラグ */
	DMAC.CHCR1.BIT.DE		= 0;	/* DMAイネーブル */

	DMAC.DMARS0.BIT.CH1MID	= 0x10;	/* SRC0 */
	DMAC.DMARS0.BIT.CH1RID	= 1;	/* 入力データエンプティ */

	/* 全チャンネル共通 */
	DMAC.DMAOR.BIT.CMS		= 0;	/* サイクルスチールモードセレクト */
	DMAC.DMAOR.BIT.PR		= 0;	/* プライオリティモード */
//	DMAC.DMAOR.BIT.AE		= 0;	/* アドレスエラーフラグ */
//	DMAC.DMAOR.BIT.NMIF		= 0;	/* NMIフラグ */
	DMAC.DMAOR.BIT.DME		= 1;	/* DMAマスタイネーブル */

	status = 0;
	#ifdef USE_CHECK
	init_check();
	#endif
	return;
}

void dma1_buf_control(void)
{
	if(status == 0)
	{
		p = (short*)&frame_buf[0];
		status = 1;
	}
	else
	if(status == 1)
	{
		DMAC.DMATCR1.LONG = 2 * MP3_FRAME_SIZE;
		DMAC.CHCR1.BIT.DE = 1;
		p = (short*)&frame_buf[1];
		status = 2;
	}
	else
	if(status == 2)
	{
		while(DMAC.CHCR1.BIT.HE == 0)
		{
			#ifdef USE_CHECK
			check1_toggle()
			#endif
			;
			if(SSIF2.SSISR.BIT.TUIRQ)
				printf("2h")
			;
		}
		#ifdef USE_CHECK
		check2_toggle();
		#endif
		DMAC.CHCR1.BIT.HE = 0;
		p = (short*)&frame_buf[0];
		status = 3;
	}
	else
	if(status == 3)
	{
		while(DMAC.CHCR1.BIT.TE == 0)
		{
			#ifdef USE_CHECK
			check3_toggle()
			#endif
			;
			if(SSIF2.SSISR.BIT.TUIRQ)
				printf("2e")
			;
		}
		#ifdef USE_CHECK
		check4_toggle();
		#endif
		DMAC.CHCR1.BIT.TE = 0;
		p = (short*)&frame_buf[1];
		status = 2;
	}
	size = 0;
	return;
}

void dma1_buf_put(short sample_l, short sample_r)
{
	*p++ = sample_l;
	*p++ = sample_r;
	size++;
	return;
}

void dma1_start(void)
{
	DMAC.CHCR1.BIT.DE = 1;
	return;
}

void dma1_stop(void)
{
	DMAC.CHCR1.BIT.DE = 0;
	return;
}

void dma1_end(void)
{
	int n;

	if(status == 2)
	{
		while(DMAC.CHCR1.BIT.HE == 0)
		{
			;
		}
		DMAC.CHCR1.BIT.HE = 0;
		for(n = 0; n < MP3_FRAME_SIZE; n++)
		{
			frame_buf[0][n] = 0;
		}
		while(DMAC.CHCR1.BIT.TE == 0)
		{
			;
		}
		DMAC.CHCR1.BIT.TE = 0;
		while(DMAC.CHCR1.BIT.HE == 0)
		{
			;
		}
		DMAC.CHCR1.BIT.HE = 0;
		for(n = 0; n < MP3_FRAME_SIZE; n++)
		{
			frame_buf[1][n] = 0;
		}
		while(DMAC.CHCR1.BIT.TE == 0)
		{
			;
		}
		DMAC.CHCR1.BIT.TE = 0;
	}
	else
	if(status == 3)
	{
		while(DMAC.CHCR1.BIT.TE == 0)
		{
			;
		}
		DMAC.CHCR1.BIT.TE = 0;
		for(n = 0; n < MP3_FRAME_SIZE; n++)
		{
			frame_buf[1][n] = 0;
		}
		while(DMAC.CHCR1.BIT.HE == 0)
		{
			;
		}
		DMAC.CHCR1.BIT.HE = 0;
		while(DMAC.CHCR1.BIT.TE == 0)
		{
			;
		}
		DMAC.CHCR1.BIT.TE = 0;
	}
	status = 0;

	DMAC.CHCR1.BIT.DE = 0;
	return;
}
