#include "iodefine.h"
#include <stdio.h>
#include "intI2C_rx220.h"
#include "intCMT_rx220.h"
//#include "intSCI_rx220.h"

//簡易I2Cはシングルマスターのみ可能

int _i2c_stop;					//通信停止(終了)
int _trans_now;					//通信中
int _trans_fin;					//通信完了

char _trans_buf[128];			//送信制御文字列
unsigned short _set_data[64];	//送信データ(コード＋数値)
volatile short* _recive_buf;	//格納先のアドレス
short _dummy_buf[10];			//ダミーの格納先
int _set_len;					//送信するデータ数(スタートコンデション等を含む)
int _recive_len_set;			//受信するデータ数
int _recive_len_now;			//受信したデータ数
int _trans_count;				//送信したデータ数

//char debug_buf[255];

#define	strto0x(s)		strtol(s,0,16)	//16進数表記文字列を数字に変換

//送信内容判別コード
#define I2C_ST	0x0100	//開始
#define I2C_SP	0x0200	//終了
#define I2C_RS	0x0400	//リスタート
#define I2C_WX	0x0800	//待機
#define I2C_RD	0x1000	//受信
#define I2C_WD	0x2000	//送信

#define I2C_RECIVE_SET		0x0100
#define I2C_RECIVE_START	0x0200


void init_I2C()
{

	//入出力の設定
	PORTB.PDR.BIT.B6=1;				//PB6 SSCLを出力設定
	PORTB.PDR.BIT.B7=1;				//PB7 SSDAを出力設定

	PORTB.ODR1.BIT.B4=1;			//PB6をオープンドレインに設定
	PORTB.ODR1.BIT.B6=1;			//PB7をオープンドレインに設定

	//マイコン内蔵プルアップを利用する
	//PORTB.PCR.BIT.B6=1;				//PB6をプルアップ
	//PORTB.PCR.BIT.B7=1;				//PB7をプルアップ

	//特殊機能を使用する端子の設定
	PORTB.PMR.BIT.B6=1;				//PB6を周辺機能モードに変更
	PORTB.PMR.BIT.B7=1;				//PB7を周辺機能モードに変更

	//特殊機能設定開始
	MPC.PWPR.BIT.B0WI = 0;			//PFSレジスタの保護解除をするPFSWEレジスタの保護解除
	MPC.PWPR.BIT.PFSWE = 1;			//PFSレジスタの保護解除

	//Pxx 端子機能制御レジスタ（PxxPFS）
	MPC.PB6PFS.BIT.PSEL = 0xA;		//PB6の周辺機能を設定(SSCL)
	MPC.PB7PFS.BIT.PSEL = 0xA;		//PB7の周辺機能を設定(SSDA)

	//特殊機能設定終了
	MPC.PWPR.BIT.PFSWE = 0;			//PFSレジスタの保護
	MPC.PWPR.BIT.B0WI = 1;			//PFSレジスタの保護をするPFSWEレジスタの保護

	//SCI9の_簡易IIC設定----
	SYSTEM.PRCR.WORD = 0x0A503;		//クロックと動作モードの保護解除
	MSTP(SCI9) = 0;					//SCI9モジュール停止解除
	SYSTEM.PRCR.WORD = 0x0A500;		//クロックと動作モードの保護

	SCI9.SCR.BIT.CKE = 0x00;		//内部クロックを使用
	SCI9.SCR.BYTE&=~0x30;			//送信禁止＋受信禁止
	//[2]
	SCI9.SIMR3.BIT.IICSDAS=0x3;		//SSDAn端子はハイインピーダンス状態
	SCI9.SIMR3.BIT.IICSCLS=0x3;		//SSCLn端子はハイインピーダンス状態

	//[3]
	SCI9.SMR.BIT.CM=1;			//0：調歩同期式　1：クロック同期式
	SCI9.SMR.BIT.CKS=0x0;		//0：PLCK、1：PLCK/4、2：PLCK/16、3：PLCK/64
	SCI9.SCMR.BIT.SDIR=1;		//MSBファーストで送受信
	SCI9.SCMR.BIT.SINV=0;		//そのまま送信
	SCI9.SCMR.BIT.SMIF=0;		//SCIモード

	//[4]
/*32MHz,1分周期*/
//	SCI9.BRR = 103;			// 9600bps
//	SCI9.BRR = 51;			//19200bps
//	SCI9.BRR = 25;			//38400bps
	SCI9.BRR = 8;			//115200bps


	//[5]
	SCI9.SEMR.BIT.NFEN=1;		//ノイズ除去フィルタあり
	SCI9.SNFR.BIT.NFCS=1;		//1分周のクロックをノイズフィルタに使用

	SCI9.SIMR1.BIT.IICM=1;		//簡易I2Cモード
	SCI9.SIMR1.BIT.IICDL=1;		//SCLから1サイクル遅れてSDAを変化させる

	SCI9.SIMR2.BIT.IICACKT=1;	//NACK送信またはACK/NACK受信（受信終了/送信用設定）
	SCI9.SIMR2.BIT.IICCSC=1;	//クロック同期を行う（スレーブからのクロックストレッチを受け入れる）
	SCI9.SIMR2.BIT.IICINTM=1;	//送受信割込みを使う？

	SCI9.SPMR.BYTE=0;			//SPI機能全停止
/**/
	//SCI受信割り込み設定
	IPR(SCI9,RXI9) = 0x1;				//SCI9のRXI9の割り込み優先度を設定(0:禁止〜15:最優先)
	IEN(SCI9,RXI9) = 0x1;				//SCI9のRXI9の割り込みを有効化
	IR(SCI9,RXI9) = 0x0;				//SCI9のRXI9の割り込みフラグをクリア

	//SCI受信エラー割り込み設定
	IPR(SCI9,ERI9) = 0x1;				//SCI9のERI9の割り込み優先度を設定(0:禁止〜15:最優先)
	IEN(SCI9,ERI9) = 0x1;				//SCI9のERI9の割り込みを有効化
	IR(SCI9,ERI9) = 0x0;				//SCI9のERI9の割り込みフラグをクリア

	//SCI送信割り込み設定
	IPR(SCI9,TXI9) = 0x6;				//SCI9のTXI9の割り込み優先度を設定(0:禁止〜15:最優先)
	IEN(SCI9,TXI9) = 0x1;				//SCI9のTXI9の割り込みを有効化
	IR(SCI9,TXI9) = 0x0;				//SCI9のTXI9の割り込みフラグをクリア

	//SCI送信完了割り込み設定(コンディション発行完了)※割込みにすると動作が速すぎた
	//IPR(SCI9,TEI9) = 0x6;				//SCI9のTEI9の割り込み優先度を設定(0:禁止〜15:最優先)
	//IEN(SCI9,TEI9) = 0x1;				//SCI9のTEI9の割り込みを有効化
	//IR(SCI9,TEI9) = 0x0;				//SCI9のTEI9の割り込みフラグをクリア
/**/
	SCI9.SCR.BYTE|=0x30;		//送信許可＋受信許可

	_trans_now=0;

}

void i2c_set_condition(int mode){	//0:start 1:stop 2:restart

	SCI9.SIMR3.BIT.IICSTIF=0;	//フラグクリア

	switch(mode){
		case 0:
			SCI9.SIMR3.BIT.IICSTAREQ=1;	//スタートコンディション生成指令
			break;
		case 1:
			SCI9.SIMR3.BIT.IICSTPREQ=1;	//ストップコンディション
			break;
		case 2:
			SCI9.SIMR3.BIT.IICRSTAREQ=1;	//リスタートコンディション生成指令
			break;
		default:
			return;	
	}

	SCI9.SIMR3.BIT.IICSDAS=0x1;	//SSDAn端子は開始条件、再開始条件、停止条件
	SCI9.SIMR3.BIT.IICSCLS=0x1;	//SSCLn端子は開始条件、再開始条件、停止条件
	while(SCI9.SIMR3.BIT.IICSTIF==0);	//開始/再開始/停止条件生成が完了するまで待機
	SCI9.SIMR3.BIT.IICSTIF=0;	//条件発行完了フラグクリア
//	SCI9.SCR.BIT.TEIE = 0x1u;	//発行割込み許可

}

void i2c_close(void){
	SCI9.SIMR3.BIT.IICSTIF=0;	//フラグクリア
	SCI9.SIMR3.BIT.IICSDAS=0x3;	//SSDAn端子はハイインピーダンス状態
	SCI9.SIMR3.BIT.IICSCLS=0x3;	//SSCLn端子はハイインピーダンス状態
}

void i2c_write_byte(unsigned char data){
//	int i;

	//データ送信準備
	SCI9.SIMR3.BIT.IICSTIF=0;	//フラグクリア
	SCI9.SIMR3.BIT.IICSDAS=0x0;	//SSDAn端子はデータ出力
	SCI9.SIMR3.BIT.IICSCLS=0x0;	//SSCLn端子はクロック出力

	SCI9.TDR=data;	//宛先アドレス
//	for(i=0;i<100;i++);	//ちょっとだけ空ループ
//	while(SCI9.SSR.BIT.TEND==0);	//送信完了まで待機
	SCI9.SCR.BIT.TIE = 0x1u;		//送信割込み許可
}


//I2C送信の設定
void write_i2c(short* buff_address,char* data){
	int i;
	char sub_buf[3];


	while(_trans_now);	//通信完了待ち

	_trans_now=1;	//送信開始
	_trans_fin=0;	//送信完了
	_trans_count=0;	//送信データ数リセット
	_i2c_stop=0;	//送信停止フラグ解除
	_set_len=0;

	_recive_len_now=0;	//受信済みデータ数リセット
	_recive_len_set=0;	//受信予定数リセット

	_set_len=sprintf(_trans_buf,"%s",data);	//送信命令をコピー
	_set_len/=2;
	_recive_buf=buff_address;		//格納先の先頭アドレスをコピー

	for(i=0;i<_set_len;i++){	//1回の送信データ最大64(指令128字)
		strncpy(sub_buf, _trans_buf+i*2, 2 );	//2文字切り出し
		sub_buf[2]='\0';
		if(sub_buf[0]=='S'&&sub_buf[1]=='T'){		//スタート
			_set_data[i]=I2C_ST;
		}else if(sub_buf[0]=='S'&&sub_buf[1]=='P'){	//ストップ
			_set_data[i]=I2C_SP;
		}else if(sub_buf[0]=='R'&&sub_buf[1]=='S'){	//リスタート
			_set_data[i]=I2C_RS;
		}else if(sub_buf[0]=='W'){	//ウェイト
			sub_buf[0]=' ';
			_set_data[i]=I2C_WX|strto0x(sub_buf);
		}else if(sub_buf[0]=='R'&&sub_buf[1]=='D'){	//リード
			if(buff_address==NULL){	//受信しない予定なのに受信制御が含まれている
				_recive_buf=_dummy_buf;
			}
			_recive_buf[_recive_len_set]=I2C_RECIVE_SET;	//受信待機
			_set_data[i]=I2C_RD;
			_recive_len_set++;
		}else{										//データ
			_set_data[i]=I2C_WD|strto0x(sub_buf);
		}
	} //end for
	_set_data[_set_len]=0;			//エンドキャップ

	i2c_ctrl();

}

//通信開始時と送信完了時に自動実行される
void i2c_ctrl(){
	unsigned long timer;

	while(_trans_now){	//continueさせるために不思議な構造にした

		//ストップ発行後は一旦バスを開放してみる
		if(_trans_count>1){
			if((_set_data[_trans_count-1]&0xFF00)==I2C_SP){
				i2c_close();
			}
		}
	
		//最後まで処理した
		if(_set_len<=_trans_count){
			_trans_now=0;	//送信終了
			_trans_fin=1;	//送信完了
			return;
		}
	
	
		switch(_set_data[_trans_count]&0xFF00){
			case I2C_ST:
				i2c_set_condition(0);	//スタート発行
				_trans_count++;
				continue;	//whileからやり直し
				break;
			case I2C_SP:
				i2c_set_condition(1);	//ストップ発行
				_trans_count++;
				continue;	//whileからやり直し
				break;
			case I2C_RS:
				i2c_set_condition(2);	//リスタート発行
				_trans_count++;
				continue;	//whileからやり直し
				break;
			case I2C_WX:				//待機(1ms単位)
				timer=getsystime()+(_set_data[_trans_count]&0x00FF);	//最大16ms
				while(timer>getsystime());	//設定時刻になるまで空ループ
				_trans_count++;
				continue;	//whileからやり直し
				break;
			case I2C_RD:				//受信
				if((_set_data[_trans_count+1]&0xFF00)==I2C_RD){	//次も受信の時
					SCI9.SIMR2.BIT.IICACKT=0;	//ACK送信
				}else{
					SCI9.SIMR2.BIT.IICACKT=1;	//NACK送信
				}
				SCI9.SCR.BIT.RIE = 0x1u;	//受信割込み許可
				i2c_write_byte(0xFF);
				//i2c_set_recvdata(SCI9.RDR);
				break;
			case I2C_WD:				//送信
				i2c_write_byte(_set_data[_trans_count]&0x00FF);
				break;
		}
		_trans_count++;
		return;
	}//end while
}

//受信データを格納
void i2c_set_recvdata(unsigned char data){
	_recive_buf[_recive_len_now]=(unsigned short)data;
	_recive_len_now++;
}

//受信完了をチェック
int check_i2c_fin(){
	int value;
	value=_trans_fin;
	//_trans_fin=0;
	return value;
}

//受信完了まで待機
void i2c_wait_recv(){
	//送信処理してない場合は終了
	if(_trans_now==0)	return;

	//受信完了するまで空ループ
	while(_trans_fin==0);
}


/**/
void SCI9_INT_ERI9(void){
	if(SCI9.SSR.BIT.ORER==1)
		SCI9.SSR.BIT.ORER=0;
	if(SCI9.SSR.BIT.FER==1)
		SCI9.SSR.BIT.FER=0;
	if(SCI9.SSR.BIT.PER==1)
		SCI9.SSR.BIT.PER=0;
}

void SCI9_INT_RXI9(void){
	SCI9.SCR.BIT.RIE = 0x0u;		//受信割込み停止
	i2c_set_recvdata(SCI9.RDR);
}

void SCI9_INT_TXI9(void){
	SCI9.SCR.BIT.TIE = 0x0u;		//送信割込み停止
	i2c_ctrl();
}
void SCI9_INT_TEI9(void){
	SCI9.SCR.BIT.TEIE = 0x0u;		//発行割込み停止
}
