#include 	<sys/bios.h>
#include	<stdio.h>
#include 	<fcntl.h>
#include	<stdlib.h>
#include	<string.h>
#include	"pattern.h"

#define		BUF_SIZE	40960
#define		MENU_ITEMS	6
#define		SPEED_ITEMS	3
#define		TEST_ITEMS	2

/*
	モニタデータ格納バッファ
*/
static char		line_buf[BUF_SIZE];
static unsigned	byte_count = 0, err_count = 0;
static char		*line_p, *line_max;

/*
	仮想画面バッファ
*/
static int		vmap[16][28];

static BOOL		fchecked = FALSE;
static BOOL		ftest = FALSE;
static BOOL		fhex = TRUE;
static unsigned	view_top, view_bottom, view_temp;

static int		menu_top = 0;
static int		menu_cur_pos = 0;
static int		menu_view_pos = 0;

static char		font_buf[8];

/*
	シリアル受信割り込み処理
*/
void far rx_interrupt(void)
{
	int		rc;

	switch((rc = comm_receive_char()))
	{
		case ERR_SIO_TIMEOUT:
			break;
		case ERR_SIO_CANCEL:
		case ERR_SIO_OVERRUN:
			err_count++;
			break;
		default:
			if(byte_count < BUF_SIZE)
			{
				*(line_p++) = (char)rc;
				byte_count++;
			}
	}
}

/*
	シリアル受信割り込み処理(テストモード)
*/
void far rx_interrupt_test(void)
{
	int		rc;

	switch((rc = comm_receive_char()))
	{
		case ERR_SIO_TIMEOUT:
			break;
		case ERR_SIO_CANCEL:
		case ERR_SIO_OVERRUN:
			err_count++;
			break;
		default:
			if(byte_count < BUF_SIZE)
			{
				*(line_p++) = (char)((rc >> 4) | 0xA0);
				*(line_p++) = (char)((rc & 0x0F) | 0xB0);
				byte_count += 2;
			}
	}
}

/*
	シリアルから指定バイト受信
*/
int comm_recv(char far* recv_p, int len)
{
	int		rc, rlen = 0;

	while(rlen < len)
	{
		switch((rc = comm_receive_char()))
		{
			case ERR_SIO_CANCEL:
			case ERR_SIO_TIMEOUT:
			case ERR_SIO_OVERRUN:
				return rc;
		}

		*(recv_p++) = (char)rc;
		rlen++;
	}

	return rlen;
}

/*
	ラインステータスLEDのON/OFF
*/
void set_led(int no, int stat)
{
	screen_set_char(SCREEN2, 12 + (no * 2), 1, 2, 1, led + (stat ? 2 : 0));
}

/*
	画面初期化
*/
void init(void)
{
	display_control(DCM_SCR1|DCM_SCR2|DCM_SPR);
	lcd_set_color(0x6420, 0xFCA8);
	palette_set_color( 0, 0x7520);
	text_screen_init();
}

/*
	ログ一行表示
*/
int view_line(unsigned log_count, int row)
{
	char		c1, c2;
	int			i, dir, len = 0;
	unsigned	code;
	char far	*log_p;

	log_p = line_buf + log_count;

	for(i = 0; i < 9; i++)
	{
		c1 = *(log_p++);
		c2 = *(log_p++);
		if(i == 0)
		{
			dir = ((c1 & 0xF0) == 0xA0) ? 0 : 1;
			vmap[row][0] = ab[dir * 2];				/* A->B / A<-B */
			vmap[row][1] = ab[dir * 2 + 1];
		}
		else
		{
			if(dir != (((c1 & 0xF0) == 0xA0) ? 0 : 1)) break;
			vmap[row][i * 3 + 1] = dir;				/* 空白 */
		}
		if(fhex)
		{
			vmap[row][i * 3 + 2] = digit[(c1 & 0x0F) + dir * 16];
			vmap[row][i * 3 + 3] = digit[(c2 & 0x0F) + dir * 16];
		}
		else
		{
			vmap[row][i * 3 + 2] = dir;
			code = ((c1 & 0x0F) << 4) | (c2 & 0x0F);
			if((code >= 0x20)&&(code <= 0x7F))
				vmap[row][i * 3 + 3] = ascii[code - 0x20 + dir * 96];
			else
				vmap[row][i * 3 + 3] = P_GAP + dir;
		}

		len += 2;
		log_count += 2;
		if(log_count >= byte_count) break;
	}
	return len;
}

/*
	ログ一画面表示
*/
void view_screen(unsigned start)
{
	int			i;
	unsigned	lc;

	/*
		仮想VRAM初期化
	*/
	memset(vmap, 0, sizeof(vmap));

	view_top = lc = start;
	for(i = 0; i < 16; i++)
	{
		view_bottom = lc;
		lc += view_line(lc, i);
		if(lc >= byte_count) break;
	}

	screen_set_char(SCREEN2, 0, 2, 28, 16, vmap);
	text_put_numeric(0, 1, 5, NUM_ALIGN_RIGHT, (start >> 1) + 1);
}

/*
	前の行
*/
int skip_prev(unsigned *log_pos)
{
	int			i, dir1, dir2, len, mod;
	unsigned	pos;

	pos = *log_pos;
	if(pos == 0) return -1;						/* データの先頭 */
	if(pos == 2)
	{
		*log_pos = 0;
	 	return 0;								/* データの先頭 */
	}
	line_p = line_buf + pos;
	dir1 = ((*line_p & 0xF0) == 0xA0) ? 0 : 1;	/* 現在の方向 */
	line_p -= 2;
	dir2 = ((*line_p & 0xF0) == 0xA0) ? 0 : 1;	/* 一個前の方向 */
	if(dir1 != dir2)
	{
		/*
			直前のデータが違う方向のデータブロック
		*/
		while(line_p != line_buf)		/* ブロックの先頭まで遡る */
		{
			line_p -= 2;
			if(dir2 != (((*line_p & 0xF0) == 0xA0) ? 0 : 1))
			{
				line_p += 2;
				break;
			}
		}
		len = (pos - (line_p - line_buf));		/* ブロック長 */
		if((mod = len % 18) != 0)
			*log_pos = pos - mod;				/* 一行18バイトで割った余り */
		else
			*log_pos = pos - 18;				/* 割り切れる時は一行分戻す */
	}
	else
	{
		/*
			直前のデータが同じ方向のデータブロック
		*/
		for(i = 0; i < 8; i++)
		{
			if(dir1 != (((*line_p & 0xF0) == 0xA0) ? 0 : 1))
			{
				line_p += 2;
				break;
			}
			if(line_p == line_buf) break;		/* データの先頭 */
			line_p -= 2;
		}
		*log_pos = line_p - line_buf;
	}
	return 0;
}

/*
	次の行
*/
int skip_next(unsigned *log_pos)
{
	int		i, dir;

	line_p = line_buf + (*log_pos);
	dir = ((*line_p & 0xF0) == 0xA0) ? 0 : 1;
	line_p += 2;
	if(line_p >= line_max) return -1;			/* データの最後 */
	for(i = 0; i < 8; i++)
	{
		if(dir != (((*line_p & 0xF0) == 0xA0) ? 0 : 1)) break;
		line_p += 2;
		if(line_p >= line_max) return -1;		/* データの最後 */
	}
	*log_pos = line_p - line_buf;
	return 0;
}

/*
	最後の行
*/
int skip_last(unsigned *log_pos)
{
	int			dir, mod;
	unsigned	pos, len;

	pos = *log_pos;
	if(!ftest)
	{
		if(pos == 0) return -1;						/* データの先頭 */
		if(pos == 2)
		{
			*log_pos = 0;
		 	return 0;								/* データの先頭 */
		}
		line_p = line_buf + pos;
		dir = ((*line_p & 0xF0) == 0xA0) ? 0 : 1;	/* 現在の方向 */
		while(line_p != line_buf)		/* ブロックの先頭まで遡る */
		{
			line_p -= 2;
			if(dir != (((*line_p & 0xF0) == 0xA0) ? 0 : 1))
			{
				line_p += 2;
				break;
			}
		}
		len = (pos - (line_p - line_buf));		/* ブロック長 */
	}
	else
	{
		len = pos;
	}
	if((mod = len % 18) != 0)
		*log_pos = pos - mod;				/* 一行18バイトで割った余り */
	else
		*log_pos = pos - 18;				/* 割り切れる時は一行分戻す */
	return 0;
}

/*
	ログ一行スクロールアップ
*/
void view_rollup(int lc)
{
	int		i;

	for(i = 0; i < lc; i++)
	{
		if(skip_next(&view_bottom) == -1)				/* 次の行の先頭 */
		{
			break;
		}

		/*
			仮想VRAMをスクロール
		*/
		memcpy(vmap, vmap[1], sizeof(vmap) - 56);

		/*
			最下行表示
		*/
		memset(vmap[15], 0, 56);
		view_line(view_bottom, 15);

		/*
			表示
		*/
		screen_set_char(SCREEN2, 0, 2, 28, 16, vmap);

		/*
			表示位置ポインタ更新
		*/
		skip_next(&view_top);
	}
}

/*
	ログ一行スクロールダウン
*/
void view_rolldown(int lc)
{
	int		i;

	for(i = 0; i < lc; i++)
	{
		if(skip_prev(&view_top) == -1)				/* 前の行の先頭 */
		{
			break;
		}

		/*
			仮想VRAMをスクロール（手抜き、遅いようならアセンブラで書き直す）
		*/
		memcpy(vmap[15], vmap[14], 56);
		memcpy(vmap[14], vmap[13], 56);
		memcpy(vmap[13], vmap[12], 56);
		memcpy(vmap[12], vmap[11], 56);
		memcpy(vmap[11], vmap[10], 56);
		memcpy(vmap[10], vmap[9], 56);
		memcpy(vmap[9], vmap[8], 56);
		memcpy(vmap[8], vmap[7], 56);
		memcpy(vmap[7], vmap[6], 56);
		memcpy(vmap[6], vmap[5], 56);
		memcpy(vmap[5], vmap[4], 56);
		memcpy(vmap[4], vmap[3], 56);
		memcpy(vmap[3], vmap[2], 56);
		memcpy(vmap[2], vmap[1], 56);
		memcpy(vmap[1], vmap[0], 56);

		/*
			最上行表示
		*/
		memset(vmap, 0, 56);
		view_line(view_top, 0);

		/*
			表示
		*/
		screen_set_char(SCREEN2, 0, 2, 28, 16, vmap);

		/*
			表示位置ポインタ更新
		*/
		skip_prev(&view_bottom);
	}
}

/*
	ログチェック
*/
BOOL log_check(void)
{
	int		i, rc;

	line_p = line_buf;
	for(i = 0; i < byte_count; i++)
	{
		rc = *(line_p++);
		switch(rc & 0xF0)
		{
			case 0x80:
				if(i % 2)
				{
					return FALSE;		/* 偶数バイト目でなければエラー */
				}
				break;
			case 0x90:
				if(!(i % 2)) {
					return FALSE;		/* 奇数バイト目でなければエラー */
				}
				break;
			case 0xA0:
				if(i % 2) {
					return FALSE;		/* 偶数バイト目でなければエラー */
				}
				break;
			case 0xB0:
				if(!(i % 2))
				{
					return FALSE;		/* 奇数バイト目でなければエラー */
				}
				break;
			case 0xF0:
				i = byte_count;
				break;
			default:
				return FALSE;
		}
	}

	return TRUE;
}

/*
	ログ表示メイン
*/
void view_main(void)
{
	int		i, key;

	if(byte_count == 0)
	{
		text_put_string(0, 0, "◆ログデータが　　　◆");
		text_put_string(0, 1, "◆ありません　　　　◆");
		key_wait();
		return;
	}

	/*
		チェック済みでなければログデータをチェック
	*/
	if(!fchecked)
	{
		font_set_color(0x0c);	/* 反転 */
		text_put_string(0, 0, "◆ログチェック中−−◆");
		font_set_color(0x03);	/* 通常 */
		text_put_string(0, 1, "　　　　　　　　　　　");

		if(!log_check())
		{
			font_set_color(0x0c);	/* 反転 */
			text_put_string(0, 0, "◆受信データエラー　◆");
			key_wait();
			return;
		}
		fchecked = TRUE;
	}

	/*
		表示開始
	*/
	font_set_color(0x0c);	/* 反転 */
	text_put_string(0, 0, "◆モニタログ表示中−◆");
	font_set_color(0x03);	/* 通常 */
	text_put_string(0, 1, "　　　　　[B]:終了");

	/*
		一画面表示
	*/
	view_screen(0);

	while(TRUE)
	{
		key = key_wait();
		if((key & KEY_B)||(key & KEY_START))
		{
			break;
		}
		else if(key & KEY_A)
		{
			/*
				表示切換
			*/
			fhex = !fhex;
			view_screen(view_top);
		}
		else if(key & KEY_DOWN1)
		{
			/*
				１行スクロールアップ
			*/
			view_rollup(1);
		}
		else if(key & KEY_UP1)
		{
			/*
				１行スクロールダウン
			*/
			view_rolldown(1);
		}
		else if(key & KEY_DOWN2)
		{
			/*
				１０行スクロールアップ
			*/
			view_rollup(10);
		}
		else if(key & KEY_UP2)
		{
			/*
				１０行スクロールダウン
			*/
			view_rolldown(10);
		}
		else if(key & KEY_LEFT2)
		{
			/*
				ログの先頭
			*/
			view_screen(0);
		}
		else if(key & KEY_RIGHT2)
		{
			/*
				ログの最後
			*/
			view_temp = byte_count - 2;
			skip_last(&view_temp);
			for(i = 0; i< 15; i++)
			{
				if(skip_prev(&view_temp) == -1) break;
			}
			view_screen(view_temp);
		}

		text_put_numeric(0, 1, 5, NUM_ALIGN_RIGHT, (view_top >> 1) + 1);
	}
}

/*
	モニタ開始
*/
void mon_start()
{
	static intvector_t 	iv;
	char		rbuf[10];
	int			result;
	int			key;

	/*
		初期化
	*/
	lcd_set_segments(0);
	byte_count = err_count = 0;
	line_p = line_buf;
	fchecked = FALSE;

	/*
		割り込みフックを設定
	*/
	if(!ftest)
		iv.callback = (void (near *)())FP_OFF(rx_interrupt);
	else
		iv.callback = (void (near *)())FP_OFF(rx_interrupt_test);
	iv.cs =  _asm_inline("mov ax, cs");
	iv.ds =  _asm_inline("mov ax, ds");
	sys_interrupt_set_hook(SYS_INT_RECEIVEREADY, &iv, NULL);

	/*
		モニタ開始コマンド
	*/
	if(!ftest)
	{
 		comm_send_char('\x47');			/* 'G' */
	}

	while(byte_count < BUF_SIZE)
	{
		key = key_hit_check();
		if(key & KEY_B)
		{
			break;
		}
		lcd_set_segments(byte_count & (LCDSEG_AUX3|LCDSEG_AUX2|LCDSEG_AUX1));
	}

	/*
		割り込みフックを解除
	*/
	sys_interrupt_reset_hook(SYS_INT_RECEIVEREADY, NULL);

	/*
		モニタ終了コマンド
	*/
	if(!ftest)
	{
	 	comm_send_char('\x45');			/* 'E' */
		result = comm_recv(rbuf, 1);
	}

	/*
		終了処理
	*/
	font_set_color(0x0c);	/* 反転 */
	text_put_string(0, 0, "◆終了処理中　　　　◆");
	font_set_color(0x03);	/* 通常 */
	text_put_string(0, 1, "　　　　　　　　　　　");
	comm_close();
	comm_open();

	/*
		LCDセグメントクリア
	*/
	lcd_set_segments(0);

	/*
		バッファフル
	*/
	if(byte_count == BUF_SIZE)
	{
		font_set_color(0x0c);	/* 反転 */
		text_put_string(0, 0, "◆受信バッファフル　◆");
		font_set_color(0x03);	/* 通常 */
		text_put_string(0, 1, "　　　　　　　　　　　");
		key_wait();
	}

	/*
		モニタ結果
	*/
	text_put_string(0, 0, "◆　　　　　b受信　◆");
	text_put_string(0, 1, "◆　　　　　bエラー◆");
	text_put_numeric(1, 0, 5, 0, byte_count >> 1);
	text_put_numeric(1, 1, 5, 0, err_count);
	key_wait();

	line_max = line_buf + byte_count;		/* 受信バッファの最後+1の番地 */
}

/*
	モニタ準備
*/
void mon_line()
{
	char	rbuf[30];
	int		result;

	font_set_color(0x0c);	/* 反転 */
	text_put_string(0, 0, "◆モニタを開始します◆");
	font_set_color(0x03);	/* 通常 */
	text_put_string(0, 1, "　　　　　[A]:OK");
	if(key_wait() != KEY_A) return;

	font_set_color(0x0c);	/* 反転 */
	text_put_string(0, 0, "◆モニタ中−−−−−◆");
	font_set_color(0x03);	/* 通常 */
	text_put_string(0, 1, "　　　　　[B]:中断");

	/*
		接続チェック
	*/
	if(!ftest)
	{
	 	comm_send_char('\x56');			/* 'V' */
		result = comm_recv(rbuf, 22);

		switch(result)
		{
			case ERR_SIO_CANCEL:
			case ERR_SIO_TIMEOUT:
			case ERR_SIO_OVERRUN:
				text_put_string(0, 0, "◆ラインモニタが　　◆");
				text_put_string(0, 1, "◆接続されていません◆");
				key_wait();
				return;
		}
	}
	/*
		モニタ開始
	*/
	mon_start();
}

/*
	ライン状態取得
*/
void get_status()
{
	char		rbuf[10], sc, mask;
	int			i, result;

	if(ftest) return;

	font_set_color(0x0c);	/* 反転 */
	text_put_string(0, 0, "◆ライン状態取得中−◆");
	font_set_color(0x03);	/* 通常 */
	text_put_string(0, 1, "　　　　　　　　　　　");

	/*
		ライン状態を取得
	*/
 	comm_send_char('\x53');			/* 'S' */
	result = comm_recv(rbuf, 2);

	switch(result)
	{
		case ERR_SIO_CANCEL:
		case ERR_SIO_TIMEOUT:
		case ERR_SIO_OVERRUN:
			text_put_string(0, 0, "◆ラインモニタが　　◆");
			text_put_string(0, 1, "◆接続されていません◆");
			key_wait();
			break;
		default:
			sc = rbuf[0];	/* LでON */
			for(i = 0, mask = 0x01; i < 8; i++, mask <<= 1)
			{
				set_led(i, !(sc & mask));
			}
	}
}

/*
	モニタ速度設定
*/
int speed_menu(void)
{
	static char	*speed_menu[] = { "　　4800bps　　",
								  "　　9600bps　　",
								  "　19200bps　　"
						};
	static char	*speed_test[] = { "　　9600bps　　",
								  "　38400bps　　"
						};
	static int	speed_top = 0;
	static int	speed_cur_pos = 1;
	static int	speed_view_pos = 1;

	int		i, key, items;
	BOOL	fChange = TRUE;
	char	**menu_p;

	items = (ftest) ? TEST_ITEMS : SPEED_ITEMS;
	menu_p = (ftest) ? speed_test : speed_menu;

	while(TRUE)
	{
		if(fChange)
		{
			for(i = 0; i < 2; i++)
			{
				if(speed_cur_pos == (speed_top + i))
				{
					font_set_color(0x0c);	/* 反転 */
					text_put_string(0, i, menu_p[speed_top + i]);
					font_set_color(0x03);	/* 通常 */
				}
				else
				{
					text_put_string(0, i, menu_p[speed_top + i]);
				}
			}
			fChange = FALSE;
		}

		if((key = key_wait()) != 0)
		{
			if((key == KEY_UP1)&&(speed_cur_pos > 0))
			{
				speed_cur_pos--;
				if(speed_view_pos == 1)
				{
					speed_view_pos = 0;
				}
				else
				{
					speed_top--;
				}
				fChange = TRUE;
			}
			else if((key == KEY_DOWN1)&&(speed_cur_pos < items - 1))
			{
				speed_cur_pos++;
				if(speed_view_pos == 0)
				{
					speed_view_pos = 1;
				}
				else
				{
					speed_top++;
				}
				fChange = TRUE;
			}
			else if(key == KEY_A)
			{
				return speed_cur_pos;
			}
			else if(key == KEY_START)
			{
				return -1;
			}
		}
	}
}

/*
	ログ保存
*/
void save_log()
{
	static char filename[30];
	unsigned	i;
	FILE far 	*fp;

	if(byte_count == 0)
	{
		text_put_string(0, 0, "◆ログデータが　　　◆");
		text_put_string(0, 1, "◆ありません　　　　◆");
		key_wait();
		return;
	}

	font_set_color(0x0c);	/* 反転 */
	text_put_string(0, 0, "◆ログを保存します　◆");
	font_set_color(0x03);	/* 通常 */
	text_put_string(0, 1, "　　　　　[A]:OK");
	if(key_wait() != KEY_A) return;

	font_set_color(0x0c);	/* 反転 */
	text_put_string(0, 0, "◆ログ保存中−−−−◆");
	font_set_color(0x03);	/* 通常 */
	text_put_string(0, 1, "　　　　　　　　　　　");

	strcpy(filename, "/ram0/rsmon.dat");
	unlink(filename);
	if(creat(filename, 6, (byte_count + 127) / 128) != E_FS_SUCCESS)
	{
		text_put_string(0, 0, "◆ファイル作成で　　◆");
		text_put_string(0, 1, "◆エラーが発生　　　◆");
		key_wait();
	 	return;
	}
	fs_setinfo(filename, "ラインモニタログ");
	if(!(fp = fopen(filename, "w")))
	{
		text_put_string(0, 0, "◆ファイルオープンで◆");
		text_put_string(0, 1, "◆エラーが発生　　　◆");
		key_wait();
	 	return;
	}
	line_p = line_buf;
	for(i = 0; i < ((byte_count + 127) / 128) * 128; i++)
	{
		if(i < byte_count)
		{
			if(fputc(*(line_p++), fp) == EOF)
			{
				text_put_string(0, 0, "◆ファイル書込で　　◆");
				text_put_string(0, 1, "◆エラーが発生　　　◆");
				key_wait();
			 	return;
			}
		}
		else
		{
			fputc(0, fp);
		}
		lcd_set_segments(i & (LCDSEG_AUX3|LCDSEG_AUX2|LCDSEG_AUX1));
	}
	fclose(fp);
	lcd_set_segments(0);

	return;
}

/*
	モニタメニュー選択
*/
int mon_menu(void)
{
	static char	*menu[] = { "　　モニタ速度設定　　",
							"　　　モニタ開始　　　",
							"　　ライン状態取得　　",
							"　　モニタログ表示　　",
							"　　　　保　存　　　　",
							"　　　　終　了　　　　"
						};

	int		i, key;
	BOOL	fChange = TRUE;

	while(TRUE)
	{
		if(fChange)
		{
			for(i = 0; i < 2; i++)
			{
				if(menu_cur_pos == (menu_top + i))
				{
					font_set_color(0x0c);	/* 反転 */
					text_put_string(0, i, menu[menu_top + i]);
					font_set_color(0x03);	/* 通常 */
				}
				else
				{
					text_put_string(0, i, menu[menu_top + i]);
				}
			}
			fChange = FALSE;
		}

		if((key = key_wait()) != 0)
		{
			if((key == KEY_UP1)&&(menu_cur_pos > 0))
			{
				menu_cur_pos--;
				if(menu_view_pos == 1)
				{
					menu_view_pos = 0;
				}
				else
				{
					menu_top--;
				}
				fChange = TRUE;
			}
			else if((key == KEY_DOWN1)&&(menu_cur_pos < MENU_ITEMS - 1))
			{
				menu_cur_pos++;
				if(menu_view_pos == 0)
				{
					menu_view_pos = 1;
				}
				else
				{
					menu_top++;
				}
				fChange = TRUE;
			}
			else if(key == KEY_A)
			{
				return menu_cur_pos;
			}
			else if(key == KEY_START)
			{
				return -1;
			}
		}
	}
}

/*
	モニタメイン
*/
void mon_main(void)
{
	int			i, result;
	char		rbuf[10];
	BOOL		fQuit = FALSE;

	display_control(0);

	/*
		キャラクタパターン設定
	*/
	font_set_monodata( 0, 40, bmp_pat);				/* 通常 */
	font_set_color(0x0c);
	font_set_monodata(40, 18, bmp_pat + 40 * 8);	/* 反転 */
	font_set_color(0x03);
	font_set_monodata(58,  2, bmp_pat + 58 * 8);

	for(i = 0; i < 96; i++)
	{
		text_get_fontdata(i + 0x20, font_buf);
		font_set_monodata(P_ASCII + i, 1, font_buf);
		font_set_color(0x0c);
		font_set_monodata(P_ASCII + 96 + i, 1, font_buf);
		font_set_color(0x03);
	}

	/*
		モニタ画面初期化
	*/
	display_control(DCM_SCR1|DCM_SCR2|DCM_SPR);
	screen_fill_char(SCREEN2, 0, 0, 28, 18, 0);
	text_window_init(0, 0, 12, 2, 256);

	/*
		ラインステータス
	*/
	for(i = 0; i < 8; i++)
	{
		screen_set_char(SCREEN2, 12 + (i * 2), 0, 2, 1, line + (i * 2));
		set_led(i, 0);
	}

	/*
		入力待ち
	*/
	while(!fQuit)
	{
		switch(mon_menu())
		{
			case -1:
			case 5:
				fQuit = TRUE;
				break;
			case 0:
				result = speed_menu();	/* モニタ速度 */
				if(result >= 0)
				{
					/*
						モニタ速度を設定
					*/
					if(!ftest)
					{
					 	comm_send_char('\x30' + result);	/* '0'〜'2' */
						result = comm_recv(rbuf, 1);

						switch(result)
						{
							case ERR_SIO_CANCEL:
							case ERR_SIO_TIMEOUT:
							case ERR_SIO_OVERRUN:
								text_put_string(0, 0, "◆ラインモニタが　　◆");
								text_put_string(0, 1, "◆接続されていません◆");
								key_wait();
						}
					}
					else
					{
						comm_close();
					    comm_set_baudrate(COMM_SPEED_9600 + result);
					    comm_open();
					}
				}
				break;
			case 1:
				mon_line();				/* モニタ開始 */
				menu_top = 3;			/* メニュー位置をログ表示に設定 */
				menu_cur_pos = 3;
				menu_view_pos = 0;
				break;
			case 2:
				get_status();			/* ライン状態取得 */
				break;
			case 3:
				view_main();			/* ログ表示 */
				break;
			case 4:
				save_log();				/* ログ保存 */
				break;
		}
	}
}

/*
	メイン
*/
void main(void)
{
	int		result;
	char	rbuf[30];

	/*
		初期化
	*/
	init();

	/*
		COMポートを開く
	*/
    comm_set_baudrate(COMM_SPEED_38400);
    comm_open();
	comm_set_timeout(10, 1);
	text_put_string(9,  7, "┏━━━━━━━┓");
	text_put_string(9,  8, "┃接続チェック中┃");
	text_put_string(9,  9, "┗━━━━━━━┛");

	/*
		バージョンを取得
	*/
 	comm_send_char('\x56');			/* 'V' */
	result = comm_recv(rbuf, 22);

	switch(result)
	{
		case ERR_SIO_CANCEL:
		case ERR_SIO_TIMEOUT:
		case ERR_SIO_OVERRUN:
			text_put_string(5,  7, "┏━━━━━━━━━━━━━━━━┓");
			text_put_string(5,  8, "┃ラインモニタが接続されていません┃");
			text_put_string(5,  9, "┗━━━━━━━━━━━━━━━━┛");
			key_wait();
			text_put_string(5,  7, "　　┏━━━━━━━━━━━━┓　　");
			text_put_string(5,  8, "　　┃テストモードで起動します┃　　");
			text_put_string(5,  9, "　　┗━━━━━━━━━━━━┛　　");
			key_wait();
			ftest = TRUE;
	}

	/*
		モニタ速度のデフォルトを設定
	*/
	if(!ftest)
	{
	 	comm_send_char('\x31');			/* 9600bps */
		result = comm_recv(rbuf, 1);
	}

	/*
		モニタメイン
	*/
	mon_main();				/* モニタのメイン */

	/*
		COMポートを閉じる
	*/
	comm_close();
}
