/***************************************************************
 CPU UART シリアルコンソール入出力ドライバ(FM3 MFS用)
***************************************************************/

/* UARTコントローラ */

#define	USE_BPS		115200	/* 通信速度 115200 or 38400 */

#define	USE_UART_CH		4	/* UARTチャネル0 or 3 or 4 */


#if (USE_BPS == 115200)
	/* APB2バスクロック36MHz時 */
	#define MFSx_BGR_SET (312)
#endif
#if (USE_BPS == 38400)
	/* APB2バスクロック36MHz時 */
	#define MFSx_BGR_SET (936)
#endif

#if (USE_UART_CH == 0)
	/* MFSコントローラ0 */
	#define BaseAddr (0x40038000)
#endif
#if (USE_UART_CH == 3)
	/* MFSコントローラ3 */
	#define BaseAddr (0x40038300)
#endif
#if (USE_UART_CH == 4)
	/* MFSコントローラ4 */
	#define BaseAddr (0x40038400)
#endif


/* FIFO付きシリアルコントローラSCIF(SCIFx) */
#define MFSx_SMR	((volatile unsigned char      *)(BaseAddr+0x000))
#define MFSx_SCR	((volatile unsigned char      *)(BaseAddr+0x001))
#define MFSx_ESCR	((volatile unsigned char      *)(BaseAddr+0x004))
#define MFSx_SSR	((volatile unsigned char      *)(BaseAddr+0x005))
#define MFSx_RDR	((volatile unsigned char      *)(BaseAddr+0x008))
#define MFSx_TDR	((volatile unsigned char      *)(BaseAddr+0x008))
#define MFSx_BGR	((volatile unsigned short int *)(BaseAddr+0x00C))
#define MFSx_FCR0	((volatile unsigned char      *)(BaseAddr+0x014))
#define MFSx_FCR1	((volatile unsigned char      *)(BaseAddr+0x015))
#define MFSx_FBYTE	((volatile unsigned short int *)(BaseAddr+0x018))

/* ポートコントローラ制御レジスタ */
#define GPIO_PFR0	((volatile unsigned int       *)(0x40033000))
#define GPIO_PFR2	((volatile unsigned int       *)(0x40033008))
#define GPIO_PFR4	((volatile unsigned int       *)(0x40033010))
#define GPIO_ADE	((volatile unsigned int       *)(0x40033500))
#define GPIO_EPFR07	((volatile unsigned int       *)(0x4003361C))
#define GPIO_EPFR08	((volatile unsigned int       *)(0x40033620))



/* コンソール(UART)初期化 */
void CPU_UartInitialize(void)
{
	unsigned short int sts;
#if (USE_UART_CH == 0)
	/* リロケートピン選択  SIN0_0(入力)，SOT0_0(出力)を使用 */
	*GPIO_EPFR07 = (*GPIO_EPFR07 & 0xFFFFFF00) | 0x00000000;
	/* ポート2ファンクション選択 */
	*GPIO_PFR2 = *GPIO_PFR2 | 0x00000006;	/* P22とP21を周辺機能として使用 */
	/* A-D入力禁止 */
	*GPIO_ADE  = *GPIO_ADE & 0x7FFFFFFF;	/* AN31ディセーブル(SOT0_0有効) */
#endif
#if (USE_UART_CH == 3)
	/* リロケートピン選択  SIN3_2(入力)，SOT3_2(出力)を使用 */
	*GPIO_EPFR07 = (*GPIO_EPFR07 & 0xFC3FFF00) | 0x03C00000;
	/* ポート2ファンクション選択 */
	*GPIO_PFR4 = *GPIO_PFR4 | 0x00000300;	/* P49とP48を周辺機能として使用 */
#endif
#if (USE_UART_CH == 4)
	/* リロケートピン選択  SIN4_2(入力)，SOT4_2(出力)を使用 */
	*GPIO_EPFR08 = (*GPIO_EPFR08 & 0xFFFFFF0F) | 0x000000F0;
	/* ポート0ファンクション選択 */
	*GPIO_PFR0 = *GPIO_PFR0 | 0x00000060;	/* P06とP05を周辺機能として使用 */
/*	   リロケートピン選択  SIN4_2(入力)，SOT4_2(出力)，CTS4_2(入力)，RTS4_2(出力)を使用 */
/*	*GPIO_EPFR08 = (*GPIO_EPFR08 & 0xFFFFFF00) | 0x000000FF; */
/*     ポート0ファンクション選択 */
/*	*GPIO_PFR0 = *GPIO_PFR0 | 0x00000360;	/* P09,P08,P06,P05を周辺機能として使用 */
	/* ↑フロー制御信号まで使用する場合 */

#endif

	/* MFSx設定 */
	*MFSx_SCR = 0x80;	/* MFSソフトウェアリセット */
	*MFSx_SCR = 0x00;	/* MFSソフトウェアリセット解除 */
	*MFSx_SMR = 0x00;	/* UART0モード，ストップビット1，LSBファースト */
	*MFSx_ESCR= 0x00;	/* ストップビット1，NRZ，パリティ無，データビット8 */
	*MFSx_BGR = MFSx_BGR_SET; /* 分周設定 */
	*MFSx_FCR0= 0x00;	/* FIFOディセーブル */
	*MFSx_FCR1= 0x00;
	*MFSx_SMR = 0x01;	/* UART0モード，ストップビット1，LSBファースト，送信出力許可 */
	*MFSx_SCR = 0x03;	/* 送受信許可 */
}

/* コンソール1文字出力 */
void CPU_UartPutch(unsigned char data)
{
	while(1){
		if (*MFSx_SSR & 0x02 ) {	/* 送信バッファが空いているか */
			*MFSx_TDR = data;		/* 送信データ書き込み */
			break;
		}
	}
}

/* コンソール文字列出力(\nだけで CR+LF出力) */
void CPU_UartPuts(unsigned char *buffer)
{
	unsigned char data;
	while( (data = *(buffer++)) != 0){	/* nullまで出力 */
		if (data == 0x0a) {
			CPU_UartPutch(0x0d);	/* CR出力 */
			CPU_UartPutch(0x0a);	/* LF出力 */
		} else {
			CPU_UartPutch(data);	/* 1文字出力 */
		}
	}
}

/* コンソール文字列出力(文字列長さ指定付き/\nだけで CR+LF出力) */
void CPU_UartPutsL(unsigned char *buffer, int len)
{
	int i;
	unsigned char data;
	for(i=0;i<len;i++){
		data=*(buffer++);
		if (data == 0x0a) {
			CPU_UartPutch(0x0d);	/* CR出力 */
			CPU_UartPutch(0x0a);	/* LF出力 */
		} else {
			CPU_UartPutch(data);	/* 1文字出力 */
		}
	}
}

/* コンソール入力バッファチェック */
int CPU_UartRecvCheck(void)
{
	unsigned short int sts;
	if (*MFSx_SSR & 0x38) {	/* 各種エラー状態確認 */
		*MFSx_SSR = 0x80; /* 各種受信エラークリア */
	}
	if (*MFSx_SSR & 0x04) {	/* 受信データあり */
		return 1;	/* 受信データあり */
	} else {
		return 0;	/* 受信データなし */
	}
}

/* コンソール1文字入力(エコーバックなし) */
unsigned char CPU_UartGetch(void)
{
	unsigned char data;
	while(1){
		if (CPU_UartRecvCheck()) {	/* データを受信したか */
			data = *MFSx_RDR;	/* 受信データ読み出し */
			break;
		}
	}
	return data;
}

/* コンソール文字列入力(CRコードまで/最大255文字/エコーバックあり) */
int CPU_UartGets(unsigned char *buffer)
{
	unsigned char data;
	int i;
	i=0;
	while(1){
		data = CPU_UartGetch();	/* 1文字入力 */
		*buffer = data;
		CPU_UartPutch(data);	/* 1文字出力(エコーバック) */
		buffer++;
		i++;
		if (i > 255) break;		/* 最大文字数に達した */
		if (data == 0x0D) break;/* CRコードまで受信 */
	}
	*buffer=(unsigned char)0;	/* nullコード */
	return i;					/* 入力文字数 */
}

