#include "iodefine.h"
#include <stdio.h>
#include "intSCI_rx220.h"
#include "intCMT_rx220.h"

/*32MHz,1分周期を前提としたプログラムです*/

#define KEY_PRCR 0xA500	//プロテクト解除で使用するキー 0xA5 固定
#define PRCR_CLK 0x0001	//クロック関連
#define PRCR_MOD 0x0002	//動作モード、消費電力低減機能、ソフトウェアリセット関連
#define PRCR_LVD 0x0008	//電圧監視関連
#define PRCR_ALL (PRCR_CLK|PRCR_MOD|PRCR_LVD)	//全て

#define PROTECTOFF		(KEY_PRCR|PRCR_MOD)
#define PROTECTON		(KEY_PRCR)

//SCI1 P26,P30
//SCI5 PC3,PC2

//ここからSCI1の変数
//ファイル内で使いまわす変数
char _sci1_tx_data[255];	//送信文字バッファー(最大255文字)
int _sci1_tx_num;			//送信したい文字数
int _sci1_tx_now=0;			//送信済み文字数
//受信中に使用
char _sci1_rx_temp[255];	//受信中文字バッファー(最大255文字)
int _sci1_rx_now;			//受信中の文字数
int _sci1_rx_state;			//受信状況　0:待機状態、1:受信開始、2:受信中、3:受信完了、4:受信完了
//受信完了時に使用
char _sci1_rx_data[255];	//受信完了文字バッファー(最大255文字)
int _sci1_rx_num;			//受信完了した文字数
int _sci1_rx_fin_f;			//受信完了フラグ


//ここからSCI5の変数
//ファイル内で使いまわす変数
char _sci5_tx_data[255];	//送信文字バッファー(最大255文字)
int _sci5_tx_num;			//送信したい文字数
int _sci5_tx_now=0;			//送信済み文字数
//受信中に使用
char _sci5_rx_temp[255];	//受信中文字バッファー(最大255文字)
int _sci5_rx_now;			//受信中の文字数
int _sci5_rx_state;			//受信状況　0:待機状態、1:受信開始、2:受信中、3:受信完了、4:受信完了
//受信完了時に使用
char _sci5_rx_data[255];	//受信完了文字バッファー(最大255文字)
int _sci5_rx_num;			//受信完了した文字数
int _sci5_rx_fin_f;			//受信完了フラグ


#define MAX_RECIVE_DATA	10	//とりあえず10 ID分のデータを記録する
static unsigned char _recive_dlc[MAX_RECIVE_DATA];		//DLC
static unsigned char _recive_data[MAX_RECIVE_DATA][20];	//受信データ 20個
static unsigned long _recive_time[MAX_RECIVE_DATA];		//最終受信時刻
static unsigned char _recive_timeout[MAX_RECIVE_DATA];	//受信タイムアウト

static unsigned long _timer_ms=0;	//タイムアウトチェック用


//XBee api関連
static unsigned short api_count=0;
static unsigned short api_count_end=0xFFFF;
int _xbee_api_mode=0;
volatile int _xbee_api_recived;
unsigned char _api_rx_buf[255];		//受信バッファ
unsigned short _api_data_di=0;		//di受信データ
unsigned short _api_data_ad[6]={0};	//ad受信データ


/*ここからSCI1の設定*/
//シリアル通信１初期化関数
void init_SCI1(void){
	int k;
	
	SYSTEM.PRCR.WORD = PROTECTOFF;		//プロテクト解除
	MSTP(SCI1) = 0;						//SCI1モジュール停止解除
	SYSTEM.PRCR.WORD = PROTECTON;		//プロテクト

	//ピン設定　TxD(P26),RxD(P30)
	PORT2.PDR.BIT.B6 = 1;				//TxDなので出力設定
	PORT3.PDR.BIT.B0 = 0;				//RxDなので入力設定

	MPC.PWPR.BIT.B0WI = 0;				//PFSレジスタの保護解除をするPFSWEレジスタの保護解除
	MPC.PWPR.BIT.PFSWE = 1;				//PFSレジスタの保護解除

	MPC.P26PFS.BIT.PSEL = 0xA;			//P26の周辺機能を設定
	MPC.P30PFS.BIT.PSEL = 0xA;			//P30の周辺機能を設定

	MPC.PWPR.BIT.PFSWE = 0;				//PFSレジスタの保護;
	MPC.PWPR.BIT.B0WI = 1;				//PFSレジスタの保護をするPFSWEレジスタの保護

	PORT2.PMR.BIT.B6 = 1;				//P26だけ周辺機能ポートにする
	PORT3.PMR.BIT.B0 = 1;				//P30だけ周辺機能ポートにする

	//SCI設定
	SCI1.SCR.BYTE = 0;					//[TIE,RIE,TE,RE,TEIE]を0にする．かつCKEでクロックを内部ボーレートジェネレータ(BBRで設定)とする

	SCI1.SMR.BIT.STOP=0;	//0:1ストップビット
	SCI1.SMR.BIT.PE=1;		//0:パリティー無効 1:パリティー有効
	SCI1.SMR.BIT.PM=0;		//0:偶数パリティー 1:奇数パリティー
	SCI1.SMR.BIT.CKS=0;		//クロックセレクト 0:PCLKクロック

	SCI1.SCMR.BYTE = 0xf2;				//いろいろ
	
	//ボーレート
	//PCLK:**(MHz)÷*分周期
	//n:クロックセレクト0の時0
	//B:ボーレート
	//設定値(20MHz,2分周期)=10*1e6/(64*2^(2n-1)*B)-1 => 312500/B - 1
	//設定値(32MHz,1分周期)=32*1e6/(64*2^(2n-1)*B)-1 => 1000000/B - 1
/*20MHz,2分周期*//*
//	SCI1.BRR = 31;			// 9600bps
//	SCI1.BRR = 15;			//19200bps
	SCI1.BRR = 7;			//38400bps
/*32MHz,1分周期*/
//	SCI1.BRR = 103;			// 9600bps
//	SCI1.BRR = 51;			//19200bps
	SCI1.BRR = 25;			//38400bps
//	SCI1.BRR = 8;			//115200bps

/**/
	for(k=0; k<100;k++);				//ちょっと待機

	SCI1.SSR.BYTE &= 0xC7;				// ORER,PER,FERをクリアする

	//SCI受信割り込み設定
	IPR(SCI1,RXI1) = 0x1;				//SCI1のRXI1の割り込み優先度を7に設定
	IEN(SCI1,RXI1) = 0x1;				//SCI1のRXI1の割り込みを有効化
	IR(SCI1,RXI1) = 0x0;				//SCI1のRXI1の割り込みフラグをクリア

	//SCI受信エラー割り込み設定
	IPR(SCI1,ERI1) = 0x1;				//SCI1のERI1の割り込み優先度を7に設定
	IEN(SCI1,ERI1) = 0x1;				//SCI1のERI1の割り込みを有効化
	IR(SCI1,ERI1) = 0x0;				//SCI1のERI1の割り込みフラグをクリア

	IPR(SCI1,TXI1) = 0x6;				//SCI1のRXI1の割り込み優先度を7に設定
	IEN(SCI1,TXI1) = 0x1;				//SCI1のRXI1の割り込みを有効化
	IR(SCI1,TXI1) = 0x0;				//SCI1のRXI1の割り込みフラグをクリア

	SCI1.SCR.BIT.TE = 0x1u;				//送信許可
	SCI1.SCR.BIT.RE = 0x1u;				//受信許可
	SCI1.SCR.BIT.TIE = 0x1u;			//送信割込み許可
	SCI1.SCR.BIT.RIE = 0x1u;			//受信割込み許可

	init_recive_data_all();
}


//文字列送信関数
void write_sci1(char* trans_buf){
	if(_sci1_tx_now)	//文字列の送信が終わっていない
		return;			//関数を強制終了

	_sci1_tx_num=sprintf(_sci1_tx_data,"%s",trans_buf);	//送信文字を設定＋文字数をカウント
	SCI1.SCR.BIT.TIE  = 1;					//送信終了割り込み許可
	IR(SCI1,TXI1) = 0x1;				//SCI1のRXI1の割り込みフラグを立てる

}

//文字列送信関数(sum付)
void write_sci1_sum(char* trans_buf){
	static char buf[255];
	short sum;

	sum=calc_sum(trans_buf);

	if(sum==-1)	//文字列設定がおかしい
		return;

	sprintf(buf,"%c%s%02X%c\n",STX1,trans_buf,sum,ETX1);
	write_sci1(buf);
}

//専用フォーマットでデータを送信
void send_data_sci1(int id,int dlc,short*data){
	static char trans_buf[255];
	static char temp_buf[10];
	int i;

	if(id>255)	return;	//IDがおかしいので終了
	if(id<0)	return;
	if(dlc<0)	return; //DLCがおかしいので終了
	if(dlc>100)	return;

	sprintf(trans_buf,"%02X%02X",id,dlc);	//IDとDLCを記述

	for(i=0;i<dlc;i++){
		sprintf(temp_buf,"%02X",(unsigned char)(data[i]&0xFF));	//データ1つ分を文字化
		strcat(trans_buf, temp_buf);	//連結
	}

	write_sci1_sum(trans_buf);	//SUM付きで送信
}


/*ここからSCI5の設定*/
//シリアル通信5初期化関数
void init_SCI5(void){
	int k;
	
	SYSTEM.PRCR.WORD = PROTECTOFF;		//プロテクト解除
	MSTP(SCI5) = 0;						//SCI5モジュール停止解除
	SYSTEM.PRCR.WORD = PROTECTON;		//プロテクト

	//ピン設定　TxD(PC3),RxD(PC2)
	PORTC.PDR.BIT.B2 = 0;				//RxDなので入力設定
	PORTC.PDR.BIT.B3 = 1;				//TxDなので出力設定

	MPC.PWPR.BIT.B0WI = 0;				//PFSレジスタの保護解除をするPFSWEレジスタの保護解除
	MPC.PWPR.BIT.PFSWE = 1;				//PFSレジスタの保護解除

	MPC.PC2PFS.BIT.PSEL = 0xA;			//PC2の周辺機能を設定
	MPC.PC3PFS.BIT.PSEL = 0xA;			//PC3の周辺機能を設定

	MPC.PWPR.BIT.PFSWE = 0;				//PFSレジスタの保護
	MPC.PWPR.BIT.B0WI = 1;				//PFSレジスタの保護をするPFSWEレジスタの保護

	PORTC.PMR.BIT.B2 = 1;				//PC2だけ周辺機能ポートにする
	PORTC.PMR.BIT.B3 = 1;				//PC3だけ周辺機能ポートにする

	//SCI設定
	SCI5.SCR.BYTE = 0;					//[TIE,RIE,TE,RE,TEIE]を0にする．かつCKEでクロックを内部ボーレートジェネレータ(BBRで設定)とする

	SCI5.SMR.BIT.STOP=0;	//0:1ストップビット
	SCI5.SMR.BIT.PE=1;		//0:パリティー無効 1:パリティー有効
	SCI5.SMR.BIT.PM=0;		//0:偶数パリティー 1:奇数パリティー
	SCI5.SMR.BIT.CKS=0;		//クロックセレクト 0:PCLKクロック

	SCI5.SCMR.BYTE = 0xf2;				//いろいろ
	
	//ボーレート
	//PCLK:**(MHz)÷*分周期
	//n:クロックセレクト0の時0
	//B:ボーレート
	//設定値(20MHz,2分周期)=10*1e6/(64*2^(2n-1)*B)-1 => 312500/B - 1
	//設定値(32MHz,1分周期)=32*1e6/(64*2^(2n-1)*B)-1 => 1000000/B - 1
/*20MHz,2分周期*//*
//	SCI5.BRR = 31;			// 9600bps
//	SCI5.BRR = 15;			//19200bps
	SCI5.BRR = 7;			//38400bps
/*32MHz,1分周期*/
//	SCI5.BRR = 103;			// 9600bps
//	SCI5.BRR = 51;			//19200bps
	SCI5.BRR = 25;			//38400bps
//	SCI5.BRR = 8;			//115200bps

	for(k=0; k<100;k++);				//ちょっと待機

	SCI5.SSR.BYTE &= 0xC7;				// ORER,PER,FERをクリアする

	//SCI受信割り込み設定
	IPR(SCI5,RXI5) = 0x1;				//SCI5のRXI5の割り込み優先度を7に設定
	IEN(SCI5,RXI5) = 0x1;				//SCI5のRXI5の割り込みを有効化
	IR(SCI5,RXI5) = 0x0;				//SCI5のRXI5の割り込みフラグをクリア

	//SCI受信エラー割り込み設定
	IPR(SCI5,ERI5) = 0x1;				//SCI5のERI5の割り込み優先度を7に設定
	IEN(SCI5,ERI5) = 0x1;				//SCI5のERI5の割り込みを有効化
	IR(SCI5,ERI5) = 0x0;				//SCI5のERI5の割り込みフラグをクリア

	//SCI送信割り込み設定
	IPR(SCI5,TXI5) = 0x6;				//SCI5のTXI5の割り込み優先度を7に設定
	IEN(SCI5,TXI5) = 0x1;				//SCI5のTXI5の割り込みを有効化
	IR(SCI5,TXI5) = 0x0;				//SCI5のRXI5の割り込みフラグをクリア

	SCI5.SCR.BIT.TE = 0x1u;				//送信許可
	SCI5.SCR.BIT.RE = 0x1u;				//受信許可
	SCI5.SCR.BIT.TIE = 0x1u;			//送信割込み許可
	SCI5.SCR.BIT.RIE = 0x1u;			//受信割込み許可

	init_recive_data_all();
	init_xbee_api();
}


//文字列送信関数
void write_sci5(char* trans_buf){
	if(_sci5_tx_now)	//文字列の送信が終わっていない
		return;			//関数を強制終了

	_sci5_tx_num=sprintf(_sci5_tx_data,"%s",trans_buf);	//送信文字を設定＋文字数をカウント
	SCI5.SCR.BIT.TIE  = 1;				//送信終了割り込み許可
	IR(SCI5,TXI5) = 0x1;				//SCI5のRXI5の割り込みフラグを立てる
}

//文字列送信関数(sum付)
void write_sci5_sum(char* trans_buf){
	static char buf[255];
	short sum;

	sum=calc_sum(trans_buf);

	if(sum==-1)	//文字列設定がおかしい
		return;

	sprintf(buf,"%c%s%02X%c\n",STX1,trans_buf,sum,ETX1);
	write_sci5(buf);
}

//専用フォーマットでデータを送信
void send_data_sci5(int id,int dlc,short*data){
	static char trans_buf[255];
	static char temp_buf[10];
	int i;

	if(id>255)	return;	//IDがおかしいので終了
	if(id<0)	return;
	if(dlc<0)	return; //DLCがおかしいので終了
	if(dlc>100)	return;

	sprintf(trans_buf,"%02X%02X",id,dlc);	//IDとDLCを記述

	for(i=0;i<dlc;i++){
		sprintf(temp_buf,"%02X",(unsigned char)(data[i]&0xFF));	//データ1つ分を文字化
		strcat(trans_buf, temp_buf);	//連結
	}

	write_sci5_sum(trans_buf);	//SUM付きで送信
}



/*ここからSCI1の割り込み関数*/
//送信割り込み処理関数
//intprg.cのExcep_SCI1_TXI1へ登録が必要
void SCI1_INT_TXI1(void){
	if(_sci1_tx_now<_sci1_tx_num){	//まだ送信する文字がある
		SCI1.TDR=_sci1_tx_data[_sci1_tx_now];		//送信データを設定
		_sci1_tx_now++;				//送信済み文字数をカウントアップ
	}else{					//送信する文字がなくなった
		_sci1_tx_now=0;				//送信済み文字数をリセット
		SCI1.SCR.BIT.TIE = 0;		// 送信割り込み要求を禁止
	}//end if
}


//受信割り込み処理関数
//intprg.cのExcep_SCI1_RXI1へ登録が必要
void SCI1_INT_RXI1(void){
	char c;
	int code_type=0;
	c=SCI1.RDR;	//受信文字を格納

	switch(c){		//文字の種別判定
		case STX0:	//開始文字を受信
		case STX1:
			code_type=TYPE_STX;
			break;
		case ETX0:	//終了文字を受信
		case ETX1:
			code_type=TYPE_ETX;
			break;
		case '\n':	//改行文字を受信
		case '\r':
			code_type=TYPE_BRK;
			break;			
		default:	//それ以外の文字
			code_type=TYPE_STD;
			break;
	}//end switch

	if(code_type==TYPE_STX){
		_sci1_rx_now=0;		//受信中の文字数をリセット
	}

	if(code_type!=TYPE_BRK){	//改行文字以外
		_sci1_rx_temp[_sci1_rx_now]=c;	//受信した文字をバッファへ格納
		_sci1_rx_now++;			//受信した文字数をカウントアップ
	}

	if(code_type==TYPE_ETX || (_sci1_rx_now>=1 && code_type==TYPE_BRK)){	//終了文字または1文字以上受信後の改行文字
		_sci1_rx_temp[_sci1_rx_now]='\0';			//null文字を追加
		sprintf(_sci1_rx_data,"%s",_sci1_rx_temp);	//受信中バッファーから受信完了バッファへコピー
		_sci1_rx_num=_sci1_rx_now;	//受信文字数を格納
		_sci1_rx_fin_f=1;			//受信完了フラグを立てる
		_sci1_rx_now=0;				//受信中の文字数をリセット
	}//end TYPE_ETX		
}//SCI1_INT_RXI1

//受信エラー割り込み関数
//intprg.cのExcep_SCI1_ERI1へ登録が必要
void SCI1_INT_ERI1(void){
	if(SCI1.SSR.BIT.ORER==1)
		SCI1.SSR.BIT.ORER=0;
	if(SCI1.SSR.BIT.FER==1)
		SCI1.SSR.BIT.FER=0;
	if(SCI1.SSR.BIT.PER==1)
		SCI1.SSR.BIT.PER=0;
}

//送信割り込み処理関数
//intprg.cのExcep_SCI25_TXI5へ登録が必要
void SCI5_INT_TXI5(void){
	if(_sci5_tx_now<_sci5_tx_num){	//まだ送信する文字がある
		SCI5.TDR=_sci5_tx_data[_sci5_tx_now];		//送信データを設定
		_sci5_tx_now++;				//送信済み文字数をカウントアップ
	}else{					//送信する文字がなくなった
		_sci5_tx_now=0;				//送信済み文字数をリセット
		SCI5.SCR.BIT.TIE = 0;		// 送信割り込み要求を禁止
	}//end if
}

//受信割り込み処理関数
//intprg.cのExcep_SCI5_RXI5へ登録が必要
void SCI5_INT_RXI5(void){
	char c;
	int code_type=0;
	int timeout;

	c=SCI5.RDR;	//受信文字を格納

	//xbee api処理
	timeout=check_timeout_ms(1);	//前回からのタイムアウトを確認
	if(recive_api(c,timeout)) return;	//apiを受信中は処理終了


	switch(c){		//文字の種別判定
		case STX0:	//開始文字を受信
		case STX1:
			code_type=TYPE_STX;
			break;
		case ETX0:	//終了文字を受信
		case ETX1:
			code_type=TYPE_ETX;
			break;
		case '\n':	//改行文字を受信
		case '\r':
			code_type=TYPE_BRK;
			break;			
		default:	//それ以外の文字
			code_type=TYPE_STD;
			break;
	}//end switch

	if(code_type==TYPE_STX){
		_sci5_rx_now=0;		//受信中の文字数をリセット
	}

	if(code_type!=TYPE_BRK){	//改行文字以外
		_sci5_rx_temp[_sci5_rx_now]=c;	//受信した文字をバッファへ格納
		_sci5_rx_now++;			//受信した文字数をカウントアップ
	}

	if(code_type==TYPE_ETX || (_sci5_rx_now>=1 && code_type==TYPE_BRK)){	//終了文字または1文字以上受信後の改行文字
		_sci5_rx_temp[_sci5_rx_now]='\0';			//null文字を追加
		sprintf(_sci5_rx_data,"%s",_sci5_rx_temp);	//受信中バッファーから受信完了バッファへコピー
		_sci5_rx_num=_sci5_rx_now;	//受信文字数を格納
		_sci5_rx_fin_f=1;			//受信完了フラグを立てる
		_sci5_rx_now=0;				//受信中の文字数をリセット
	}//end TYPE_ETX		
}//SCI5_INT_RXI5

//受信エラー割り込み関数
//intprg.cのExcep_SCI5_ERI5へ登録が必要
void SCI5_INT_ERI5(void){
	if(SCI5.SSR.BIT.ORER==1)
		SCI5.SSR.BIT.ORER=0;
	if(SCI5.SSR.BIT.FER==1)
		SCI5.SSR.BIT.FER=0;
	if(SCI5.SSR.BIT.PER==1)
		SCI5.SSR.BIT.PER=0;
}


/*ここから受信解析関連*/
//受信フラグを確認
int get_recive_f(int port){
	int value=0;
	switch (port){
		case 1:
			value=_sci1_rx_fin_f;
			break;
		case 5:
			value=_sci5_rx_fin_f;
			break;
		default:
			value=0;
			break;
	}
	return value;
}
//受信フラグをクリア
void clr_recive_f(int port){
	switch (port){
		case 1:
			_sci1_rx_fin_f=0;
			break;
		case 5:
			_sci5_rx_fin_f=0;
			break;
		default:
			break;
	}
}

//受信データをコピー
void get_recive_buf(int port,char* buf){
	switch (port){
		case 1:
			sprintf(buf,"%s",_sci1_rx_data);
			break;
		case 5:
			sprintf(buf,"%s",_sci5_rx_data);
			break;
		default:
			sprintf(buf,"");
			break;
	}
}



/*共通の計算*/

//SUM計算関数
short calc_sum(char* buf){
	int i;
	short sum_16bit=0;
	short sum_8bit=0;
	short buf_size=0;

	buf_size=strlen(buf);	//文字数をカウント

	if(buf_size<=0)			//計算できない場合
		return -1;

	if(buf_size>255)		//文字設定がおかしい場合
		return -1;

	for(i=0;i<buf_size;i++){
		sum_16bit+=buf[i];		//文字を加算する
	}
	
	sum_8bit=(sum_16bit&0xFF);	//下位8bitを取り出し

	return sum_8bit;			//SUM値を返す
}

//SUMチェック関数
int check_sum(char *buf){
	char check_buf[255];	//文字列部分のみ切り出し用
	char sum_c[3];			//SUM部分のみ切り出し用
	int len;
	int sum1;
	int sum2;

	len=strlen(buf);	//文字数を取得

	if(len<4)			//短すぎて計算できない
		return -2;

	if( buf[0]!=STX0 && buf[0]!=STX1 )		//フォーマットが違う
		return -1;

	if( buf[len-1]!=ETX0 && buf[len-1]!=ETX1 )	//フォーマットが違う
		return -1;

	strncpy( check_buf, buf+1, len-4 );	//純粋な文字部分を切り出し
	check_buf[len-4]='\0';
	sum1=calc_sum(check_buf);			//SUMを計算

	strncpy( sum_c, buf+len-3, 2 );		//SUM部分を切り出し
	sum_c[2]='\0';
	sum2=strto0x(sum_c);				//SUMを数値に変換

	if(sum1==sum2)						//SUMが一致する
		return 1;
	else
		return 0;
}

//指定範囲を16進文字から数字に変換(最大4文字)
short str_to_num(char *buf,int start,int num){
	char sub_buf[5];	//部分切り出し用
	int len;
	short value;

	len=strlen(buf);	//文字数を取得
	if(num>4)			return -1;	//指定数が多すぎる
	if(start<0)			return -1;	//変換できない範囲を指定している
	if(start+num>len)	return -1;	//変換できない範囲を指定している

	strncpy( sub_buf, buf+start, num );	//純粋な文字部分を切り出し
	sub_buf[num]='\0';
	value=strto0x(sub_buf);				//文字を数値に変換

	return value;
}

/*データ解析関連*/

//受信データの解析(定期的に実行されることが前提)
short analysys_sci(short port){
	char recive_buf[255];
	short len;	//文字列長
	short rtn;	//関数の戻り値
	short ID;
	short DLC;

	check_timeout_all();

	if(get_recive_f(port)){				//SCI1で新しく受信したか確認
		get_recive_buf(port,recive_buf);	//受信データをrecive_bufにコピー
		clr_recive_f(port);				//受信完了フラグをリセット
		if(check_sum(recive_buf)==1){	//SUMチェック合格
			len=strlen(recive_buf);

			ID=str_to_num(recive_buf,1,2);	//IDを取得
			DLC=str_to_num(recive_buf,3,2);	//DLCを取得

			if(ID==0x00)
				return 1;	//文字列を受信した

			if(len!=(1+2+2+DLC*2+2+1))	//DLCと文字数が一致しない
				return -2;

			switch(ID){		//この中に各IDにおける解析処理を追加していく
				case ID_OPE:
					rtn=analysys_0x10(recive_buf,ID,DLC);
					break;
				default:
					rtn=ID;
					break;
			}//end ID

			return rtn;
		}//end check_sum
		return -1;	//受信したけどSUMチェックが不合格
	}//end get_recive_f
	return 0;	//受信していない
}

//ID:0x10に対する解析処置
short analysys_0x10(char *buf,int id,int dlc){
	int i;
	int data_num=DATA_NUM_OPE;

	if(id!=ID_OPE)	return -3;	//一致しないはずがないのでプログラムミス

	_recive_dlc[data_num]=dlc;				//DLCを格納
	_recive_time[data_num]=getsystime();	//最終受信時刻を更新
	_recive_timeout[data_num]=0;			//タイムアウトフラグを解除

	for(i=0;i<dlc;i++){
		if(i>20)
			return ID_OPE;	//多すぎたら終了

		_recive_data[data_num][i]=str_to_num(buf,1+2+2+i*2,2);	//受信データを順次格納
	}
	return ID_OPE;
}

//専用フォーマットでデータをまるごと取得
void recv_data_sci(int id,int dlc,short*data){
	int data_num;
	int i;

	if(id>255)	return;	//IDがおかしいので終了
	if(id<0)	return;
	if(dlc<0)	return; //DLCがおかしいので終了
	if(dlc>100)	return;

	switch(id){		//この中に各IDにおける解析処理を追加していく
		case ID_OPE:
			data_num=DATA_NUM_OPE;
			break;
		default:	//登録が無いので終了
			return;
			break;
	}//end ID

	if(get_recive_timeout(data_num)==0){	//操作情報がタイムアウトしていない
		for(i=0;i<dlc;i++){
			data[i]=get_recive_data(data_num,i);	//受信したデータを取得0-255
		}//end for
	}else{		//操作情報がタイムアウトしている
		for(i=0;i<dlc;i++){
			data[i]=0;	//0に設定する。
		}//end for
	}//end get_recive_timeout
}

//別の関数名でも実行させる
void recv_data_sci1(int id,int dlc,short*data){
	recv_data_sci(id,dlc,data);
}
//別の関数名でも実行させる
void recv_data_sci5(int id,int dlc,short*data){
	recv_data_sci(id,dlc,data);
}

//受信データを指定して取得
unsigned char get_recive_data(int data_num,int data_pos){
	if(_recive_dlc[data_num]<data_pos)
		return -1;	//ありえない位置を参照した

	return _recive_data[data_num][data_pos];
}

//受信データ長を取得
unsigned char get_recive_dlc(int data_num){
	return _recive_dlc[data_num];
}

//タイムアウト状態を取得
unsigned char get_recive_timeout(int data_num){
	return _recive_timeout[data_num];
}

//受信データ1セット分を初期化
void init_recive_data(int data_num){
	int i;
	_recive_dlc[data_num]=0;
	_recive_time[data_num]=0;
	_recive_timeout[data_num]=1;

	for(i=0;i<20;i++){
		_recive_data[data_num][i]=0;
	}
}

//受信データ全部を初期化
void init_recive_data_all(void){
	int i;
	for(i=0;i<MAX_RECIVE_DATA;i++){
		init_recive_data(i);
	}
}

//各データごとのタイムアウトチェック
void check_timeout(int data_num){
	if(_recive_timeout[data_num]==1)	//元々タイムアウトしている場合
		return;

	if(_recive_time[data_num]+500<getsystime()){
		init_recive_data(data_num);
		_recive_timeout[data_num]=1;
	}
}

//全データのタイムアウトチェック
void check_timeout_all(void){
	int i;
	for(i=0;i<MAX_RECIVE_DATA;i++){
		check_timeout(i);
	}
}

/*ここからXBee API受信関連*/
//前回の受信からのタイムアウトを確認
int check_timeout_ms(int ms){
	int value;
	value=(ms+_timer_ms<getsystime())?1:0;	//前回から設定時間を経過した
	_timer_ms=getsystime();
	return value;
}

//apiの受信状態を初期化
void init_xbee_api(void){
	int i;
	api_count=0;
	api_count_end=0xFFFF;
	_xbee_api_mode=0;
	for(i=0;i<255;i++){
		_api_rx_buf[i]=0;
	}
}

//apiの受信データを初期化
void init_api_data(void){
	int i;
	_api_data_di=0;
	for(i=0;i<8;i++){
		_api_data_ad[i]=0;
	}
}

//apiの受信状態を確認
int check_api_receved(void){
	int value;

	value=_xbee_api_recived;	//受信状態
	_xbee_api_recived=0;		//受信状態をクリア

	if(_timer_ms+500<getsystime()){	//最終受信時刻から500ms経過
		value|=0x10;
	}
	return value;
}

//apiの受信処理戻り値：apiモード時１、それ以外0
int recive_api(char c,int timeout){

	char trans_buf[255];
	char trans_buf2[255];
	int i;
	unsigned char sum;

	if(timeout){
		init_xbee_api();
		if((unsigned char)c==0x7E){
			_xbee_api_mode=1;		//apiモードへ移行
		}
	}

	if(_xbee_api_mode!=1) return 0;

	if(api_count==1){
		api_count_end&=((((unsigned char)c)*0x100)|0x00FF);//受信予定数Hを更新
	}
	if(api_count==2){
		api_count_end&=(((unsigned char)c)|0xFF00);//受信予定数Lを更新
	}

	_api_rx_buf[api_count]=c;	//受信データを格納
	api_count++;				//受信数を加算

	if(api_count>=api_count_end+4){	//最後まで到達

		if(check_sum_api(_api_rx_buf)){	//sumチェック
			analysys_api(_api_rx_buf);
			_xbee_api_recived=1;
		}

		//受信完了処理
		init_xbee_api();
	}
	return 1;
}

//apiフォーマットのSUMを計算
unsigned char calc_sum_api(unsigned char* buf){
	unsigned char sum=0;
	unsigned short dlc;
	int i;

	//データ長取得
	dlc=buf[1]*0x100+buf[2];

	for(i=0;i<dlc;i++){
		sum+=buf[i+3];	//加算
	}
	sum=~sum;			//反転
	return sum;
}

//apiフォーマットのSUMをチェック
int check_sum_api(unsigned char* buf){
	unsigned char sum,sum_c;
	unsigned short dlc;
	int i;

	//データ長取得
	dlc=buf[1]*0x100+buf[2];

	sum_c=buf[dlc+3];		//受信したSUM
	sum=calc_sum_api(buf);	//計算したSUM

	if(sum!=sum_c)	return 0;	//計算結果が合わない
	
	return 1;					//計算結果が一致した
}

//apiの受信データを解析
void analysys_api(unsigned char* buf){
	unsigned short dlc;
	unsigned short value;
	int i;
	short di_port;	//diポート数
	int ad_count;	//adポート数
	int ad_start;	//ad情報が始まる個所;

	if(buf[3]!=0x83)	return;	//定期送信以外の場合は関数終了

	//diポート数の取得
	di_port=(buf[9]&0x01)*0x100+buf[10];
	//diの取得
	if(di_port){	//diポートが設定されている
		value=buf[11]*0x100+buf[12];
		ad_start=13;
	}else{
		value=0;
		ad_start=11;
	}
	_api_data_di=value;

	//adポート数の取得
	ad_count=0;
	for(i=0;i<6;i++){
		if(buf[9]&(0x02<<i)){
			ad_count++;
		}
	}
	//adデータを格納
	for(i=0;i<ad_count;i++){
		value=buf[ad_start+i*2]*0x100+buf[ad_start+i*2+1];	//ad値を取得
		_api_data_ad[i]=value;
	}
}

//di値を取得
unsigned short get_api_di(void){
	return _api_data_di;
}

//ad値を取得
unsigned short get_api_ad(int port){
	if(port<0||port>6)	return 0;

	return _api_data_ad[port];
}