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

/* CPU UART入出力ヘッダ */
#include "cpu_uart.h"

/* UARTコントローラ */

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


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

#define	_NEW_BPSSET	 // GrphText2からModify

// GrphText2から
#ifdef	_NEW_BPSSET

#if (USE_BPS == 19200)
	#define SCBRR_SET 155
#endif
#if (USE_BPS == 38400)
	#define SCBRR_SET 77
#endif
#if (USE_BPS == 115200)
	#define SCBRR_SET 25
#endif
#if (USE_BPS == 230400)
	#define SCBRR_SET 12
#endif

#else

// ORG
#if (USE_BPS == 38400)
	#define SCBRR_SET 19
#endif
#if (USE_BPS == 19200)
	#define SCBRR_SET 38
#endif
#if (USE_BPS == 250000) // Not tested
	#define SCBRR_SET 5
#endif

#endif



#if (USE_UART_CH == 0)
	/* FIFO付きシリアルコントローラSCIF(SCIF0) */
	#define BaseAddr (0xFFFE8000)
#endif
#if (USE_UART_CH == 2)
	/* FIFO付きシリアルコントローラSCIF(SCIF2) */
	#define BaseAddr (0xFFFE9000)
#endif
#if (USE_UART_CH == 3)
	/* FIFO付きシリアルコントローラSCIF(SCIF3) */
	#define BaseAddr (0xFFFE9800)
#endif

/* FIFO付きシリアルコントローラSCIF(SCIFx) */
#define SCSMR	((volatile unsigned short int *)(BaseAddr+0x000))
#define SCBRR	((volatile unsigned char      *)(BaseAddr+0x004))
#define SCSCR	((volatile unsigned short int *)(BaseAddr+0x008))
#define SCFTDR	((volatile unsigned char      *)(BaseAddr+0x00C))
#define SCFSR	((volatile unsigned short int *)(BaseAddr+0x010))
#define SCFRDR	((volatile unsigned char      *)(BaseAddr+0x014))
#define SCFCR	((volatile unsigned short int *)(BaseAddr+0x018))
#define SCFDR	((volatile unsigned short int *)(BaseAddr+0x01C))
#define SCSPTR	((volatile unsigned short int *)(BaseAddr+0x020))
#define SCLSR	((volatile unsigned short int *)(BaseAddr+0x024))
#define SCEMR	((volatile unsigned short int *)(BaseAddr+0x028))

/* ポートコントローラ制御レジスタ */
#define PFCR1	((volatile unsigned short int *)(0xFFFE38AC))
#define PFCR0	((volatile unsigned short int *)(0xFFFE38AE))
#define PJCR0	((volatile unsigned short int *)(0xFFFE390E))

/* モジュールスタンバイコントローラ制御レジスタ */
#define STBCR4	((volatile unsigned char *)(0xFFFE040C))


/* コンソール(UART)初期化 */
void CPU_UartInitialize(void)
{
	unsigned short int sts;
#if (USE_UART_CH == 0)
	/* ポート設定(RXD0(PJ1),TXD0(PJ0)) */
	*PJCR0 = (*PFCR0&0xFF00)|0x0044;
	/* SCIF0スタンバイ解除 */
	*STBCR4 = (*STBCR4 & 0x7F);	/* SCIF0動作 */
#endif
#if (USE_UART_CH == 2)
	/* ポート設定(RXD2(PF2),TXD2(PF1))→(CQBB P2コネクタ) */
	*PFCR0 = (*PFCR0&0xF00F)|0x0440;
	/* SCIF2スタンバイ解除 */
	*STBCR4 = (*STBCR4 & 0xDF);	/* SCIF2動作 */
#endif
#if (USE_UART_CH == 3)
	/* ポート設定(RXD3(PF3))→(CQBB P1コネクタ)*/
	*PFCR0 = (*PFCR0&0x0FFF)|0x4000;
	/* ポート設定(TXD3(PF4))→(CQBB P1コネクタ)*/
	*PFCR1 = (*PFCR1&0xFFF0)|0x0004;
	/* SCIF3スタンバイ解除 */
	*STBCR4 = (*STBCR4 & 0xEF);	/* SCIF3動作 */
#endif
	/* SCIFx設定 */
	*SCSCR = 0x0000;	/* TE=0,RE=0,CKE1=0 */
	*SCFCR = 0x0006;	/* TFRST=1,RFRST=1 */
	sts    = *SCFSR;	/* 受信ステータス空読み */
	*SCFSR = 0x0000;	/* 受信ステータスクリア */
	*SCSMR = 0x0000;	/* CHR=0,PE=0,STOP=0,CKS=00(Pφ/1) */
#ifdef	_NEW_BPSSET
	*SCEMR = 0x0081;	/* BGDM=1(倍速モード) ABCS=1(bpsの8倍) */
#endif
	*SCBRR = SCBRR_SET;	/* 分周設定 */
	*SCFCR = 0x0000;	/* TREG:8bytes RTRG:1bytes */
	*SCSCR = 0x0030;	/* TIE=0,RIE=0,TE=1,RE=1, RIE=0 */
}

/* コンソール1文字出力 */
void CPU_UartPutch(unsigned char data)
{
	while(1){
		if (*SCFSR & 0x0020 ) {	/* 送信バッファが空いているか */
			*SCFTDR = data;		/* 送信データ書き込み */
			*SCFSR  = *SCFSR & 0xFFDF;	/* 送信フラグクリア */
			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 (*SCLSR & 1) {	/* 受信オーバランエラー状態確認 */
		*SCLSR = 0; /* 受信オーバランエラークリア */
	}
	sts = *SCFSR;	/* 受信ステータス取得 */
	if (sts & 0x0009C ) {	/* 受信エラー/ブレーク/フレーミングエラー/パリティエラー状態確認 */
		*SCFSR = 3;	/* 各種エラークリア */
		/* エラーデータの空読みはしていないので、*/
		/* この後でエラーデータのまま受信処理をする */
	}
	if (sts & 0x0002 ) {/* データを受信したか */
		return 1;	/* 受信データあり */
	} else {
		return 0;	/* 受信データなし */
	}
}

/* コンソール1文字入力(エコーバックなし) */
unsigned char CPU_UartGetch(void)
{
	unsigned char data;
	while(1){
		if (CPU_UartRecvCheck()) {	/* データを受信したか */
			data = *SCFRDR;		/* 受信データ読み出し */
			*SCFSR = *SCFSR & 0xFFFC;	/* 受信フラグクリア */
			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;					/* 入力文字数 */
}

