/*****************************************************
test.c : 
  μITRONトレーナcmtoy サンプルプログラム
  Copyright(C) 2002 佐々木芳

タスクの実装

Windowsのシミュレーション環境上で動作するアプリケーションプログラムのコンパイル時には以下のマクロ定義が必要
	_CMTOY
*****************************************************/
#include "hal.h"
#include "itron.h"
#include "debug.h"
#include "test.h"

void DisplayContext(void);

void Task1(VP_INT exinf)
{
	/*DisplayContext();*/
	CMTRACE("app: Task1 started.\n");
}

void Task2(VP_INT exinf)
{
	/*DisplayContext();*/
	CMTRACE("app: Task2 started.\n");
}

void Task3(VP_INT exinf)
{
	/*DisplayContext();*/
	CMTRACE("app: Task3 started.\n");
}



void AnyCpuReadOrWriteTest(DWORD addr)
{
	WORD sw = halGetSwitch();
	DWORD pB = addr;
	DWORD pW = addr;
	DWORD pD = addr;
	int i;
	DebugPrintf("=== AnyCpuReadOrWriteTest %xH", addr);
	DebugPrintf(NEWLINE);
	if((sw & SW_READ_OR_WRITE) == 0){
		//read
		DebugPrintf("read bytes from %X:" NEWLINE , addr);
		for(i=0; i<0x10; ++i){
			DebugPrintf("%02x ", READ_BYTE(pB));
			pB += 1;
			//DebugPrintf(NEWLINE);
		}
		DebugPrintf(NEWLINE);
		DebugPrintf("read words from %X:" NEWLINE , addr);
		for(i=0; i<0x8; ++i){
			DebugPrintf("%04x ", READ_WORD(pW));
			pW += 2;
		}
		DebugPrintf(NEWLINE);
		DebugPrintf("read dwords from %X:" NEWLINE , addr);
		for(i=0; i<0x4; ++i){
			DebugPrintf("%08x ", READ_DWORD(pD));
			pD += 4;
		}
		DebugPrintf(NEWLINE);
	}else{
		//write
		BYTE start = (BYTE)halGetVolume(0);
		DebugPrintf("write bytes(%02x) to %X:" NEWLINE, start, addr);
		for(i=0; i<0x10; ++i){
			WRITE_BYTE(pB, start++);
			pB += 1;
			//DebugPrintf("%04x ", *pRecvMes++);
		}
		DebugPrintf(NEWLINE);
	}
}

void x86ReadOrWriteTest(DWORD addr)
{
	WORD sw = halGetSwitch();
	BYTE *pRegB = BYTE_PTR(addr);
	WORD *pRegW = (WORD *)(pRegB);
	DWORD *pRegD = (DWORD *)(pRegB);
	int i;
	DebugPrintf("=== x86ReadOrWriteTest %xH", addr);
	DebugPrintf(NEWLINE);
	if(INVALIDPTR(pRegB)){
		DebugPrintf("ReadOrWriteTest: invalid address %08x", pRegB);
		return;
	}
	if((sw & SW_READ_OR_WRITE) == 0){
		//read
		DebugPrintf("read bytes from %X:" NEWLINE , addr);
		for(i=0; i<0x10; ++i){
			DebugPrintf("%02x ", *pRegB++);
			//DebugPrintf(NEWLINE);
		}
		DebugPrintf(NEWLINE);
		DebugPrintf("read words from %X:" NEWLINE , addr);
		for(i=0; i<0x8; ++i){
			DebugPrintf("%04x ", *pRegW++);
		}
		DebugPrintf(NEWLINE);
		DebugPrintf("read dwords from %X:" NEWLINE , addr);
		for(i=0; i<0x4; ++i){
			DebugPrintf("%08x ", *pRegD++);
		}
		DebugPrintf(NEWLINE);
	}else{
		//write
		BYTE start = (BYTE)halGetVolume(0);
		DebugPrintf("write bytes(%02x) to @%X:" NEWLINE, start, addr);
		for(i=0; i<0x10; ++i){
			*pRegB++ = start++;
			//DebugPrintf("%04x ", *pRecvMes++);
		}
		DebugPrintf(NEWLINE);
	}
}

void ReadOrWriteTest(DWORD addr)
{
	WORD sw = halGetSwitch();
	AnyCpuReadOrWriteTest(addr);
}

void IO_ReadOrWriteTest(DWORD addr)
{
	WORD sw = halGetSwitch();
	DWORD pB = addr;
	DWORD pW = addr;
	DWORD pD = addr;
	int i;
	DebugPrintf("=== IO_ReadOrWriteTest %xH", addr);
	DebugPrintf(NEWLINE);
	if((sw & SW_READ_OR_WRITE) == 0){
		//read
		DebugPrintf("input bytes from %X:" NEWLINE , addr);
		for(i=0; i<0x10; ++i){
			DebugPrintf("%02x ", IN_BYTE(pB));
			pB += 1;
			//DebugPrintf(NEWLINE);
		}
		DebugPrintf(NEWLINE);
		DebugPrintf("input words from %X:" NEWLINE , addr);
		for(i=0; i<0x8; ++i){
			DebugPrintf("%04x ", IN_WORD(pW));
			pW += 2;
		}
		DebugPrintf(NEWLINE);
		DebugPrintf("input dwords from %X:" NEWLINE , addr);
		for(i=0; i<0x4; ++i){
			DebugPrintf("%08x ", IN_DWORD(pD));
			pD += 4;
		}
		DebugPrintf(NEWLINE);
	}else{
		//write
		BYTE start = (BYTE)halGetVolume(0);
		DebugPrintf("output bytes(%02x) to @%X:" NEWLINE, start, addr);
		for(i=0; i<0x10; ++i){
			OUT_BYTE(pB, start++);
			pB += 1;
			//DebugPrintf("%04x ", *pRecvMes++);
		}
		DebugPrintf(NEWLINE);
	}
}

BOOL g_PN_type;
WORD g_PN_value;

void SetPnCode(BYTE* addr, int size)
{
	int i;
	WORD pncode = g_PN_value;
	for(i=0; i<size; ++i){
		if(g_PN_type){
			//PN15
			pncode = halCalcPN15(pncode);
		}else{
			//PN9
			pncode = halCalcPN9(pncode);
		}
		WRITE_BYTE(addr, pncode);
		++addr;
	}
	g_PN_value = pncode;
}

//スイッチ2がONならPNコードの初期値を設定
void InitPnCode()
{
	WORD sw = halGetSwitch();
	if(sw & 0x02){
		g_PN_type = TRUE;
	}else{
		g_PN_type = FALSE;
	}
	if(sw & 0x04){
		if(g_PN_type){
			CMTRACE("app: PN15 init\n");
			g_PN_value = 0;
		}else{
			CMTRACE("app: PN9 init\n");
			g_PN_value = -1;
		}
	}
}

/*****************************************************
//割込み2のハンドラ
//・reg area(ADDR_REG番地)を読む
*****************************************************/
int Int2_Count = 0;
void Int2(void)
{
	++Int2_Count;
	CMTRACE("app: Int2 invoked. %d\n", Int2_Count);
	ReadOrWriteTest(ADDR_REG);

}

/*****************************************************
//割込み3のハンドラ
//・ADDR_RO番地へ書き込む
*****************************************************/
int Int3_Count = 0;
void Int3(void)
{
	++Int3_Count;
	CMTRACE("app: Int3 invoked. %d\n", Int3_Count);
	ReadOrWriteTest(ADDR_RO);

}

/*****************************************************
//割込み4のハンドラ
//・reg area(ADDR_MEM_IO番地)を読む
*****************************************************/
int Int4_Count = 0;
void Int4(void)
{
	++Int4_Count;
	CMTRACE("app: Int4 invoked. %d\n", Int4_Count);
	ReadOrWriteTest(ADDR_MEM_IO);

}

/*****************************************************
//割込み5のハンドラ
//・ADDR_EXRAM番地へ書き込む
*****************************************************/
int Int5_Count = 0;
void Int5(void)
{
	++Int5_Count;
	CMTRACE("app: Int5 invoked. %d\n", Int5_Count);
	ReadOrWriteTest(ADDR_EXRAM);

}

/*****************************************************
//割込み6のハンドラ
//・IOメモリADDR_IO番地へ書き込む
*****************************************************/
int Int6_Count = 0;
void Int6(void)
{
	++Int6_Count;
	CMTRACE("app: Int6 invoked. %d\n", Int6_Count);
//	IO_ReadOrWriteTest(ADDR_IO);

}

/*****************************************************
//割込み１のハンドラ
//・バンク切り替え
*****************************************************/
int Int1_Count = 0;
int bankno = 0;
void Int1(void)
{
	/*DisplayContext();*/
	int cur_bank = bankno;
	++Int1_Count;
	++bankno; bankno &= 0x07;
	CMTRACE("app: Int1 invoked. %d\n", Int1_Count);
//	SELECT_8000_MEM(bankno);
	InitPnCode();
	SetPnCode((BYTE*)ADDR_EXRAM, SIZE_EXRAM);
	CMTRACE("app: Int1 fill %04X.%d by PN%s\n", ADDR_EXRAM, cur_bank, g_PN_type ? "15" : "9");
	SELECT_c000_MEM(bankno);//8 banks
	CMTRACE("app: Int1 selected bank %d\n", bankno);
	DisplayDecimal(bankno);//表示器
//	CMTRACE("app: Serial MS=%02x, LS=%02x\n", halSerialGetSignal(0), halSerialGetStatus(0));
}

typedef unsigned char	BYTE;	/* 8ビット*/

/*****************************************************
//割込み7のハンドラ
//・x86方式メモリへのアクセスの例
*****************************************************/
int Int7_Count = 0;
BYTE temp_buf[SIZE_EXRAM];
void Int7(void)
{
//	WRITE_BYTE(0x000, 0);
	BYTE* src;
	BYTE* pB = BYTE_PTR(0x0000);//
	WORD* pW;
	DWORD* pD;
	DebugPrintf("app: Int7 invoked. %d" NEWLINE, Int7_Count++);
	*pB++ = 0x00;	//
	*pB++ = 0x55;	//
	*pB++ = 0xaa;	//
	*pB++ = 0x00;	//
	pW = (WORD*)pB;
	*pW++ = 0x1234;
	*pW++ = 0x5678;
	pD = (DWORD*)pW;
	*pD = 0x9abcdef0;

	DebugPrintf("app: Int7 copy from %08X. " NEWLINE, ADDR_EXRAM);
	src = VOID_PTR(ADDR_EXRAM);
	memcpy(temp_buf, src, sizeof(temp_buf));

}
