//XBee AD値定期受信機能に対応(2018/10/08)

#include "iodefine.h"
#include <stdio.h>
#include "intSCI.h"
#include "intCMT.h"

//SCI0 PA0,PA1
//SCI1 PA3,PA4
//SCI2 PA8,PA9 カウンタポートと重複

//ここからSCI1の変数
//ファイル内で使いまわす変数
char _sci0_tx_data[255];	//送信文字バッファー(最大255文字)
int _sci0_tx_num;			//送信したい文字数
int _sci0_tx_now=0;			//送信済み文字数
//受信中に使用
char _sci0_rx_temp[255];	//受信中文字バッファー(最大255文字)
int _sci0_rx_now;			//受信中の文字数
int _sci0_rx_state;			//受信状況　0:待機状態、1:受信開始、2:受信中、3:受信完了、4:受信完了
//受信完了時に使用
char _sci0_rx_data[255];	//受信完了文字バッファー(最大255文字)
int _sci0_rx_num;			//受信完了した文字数
int _sci0_rx_fin_f;			//受信完了フラグ


//ここから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;			//受信完了フラグ


//ここからSCI1の変数
//ファイル内で使いまわす変数
char _sci2_tx_data[255];	//送信文字バッファー(最大255文字)
int _sci2_tx_num;			//送信したい文字数
int _sci2_tx_now=0;			//送信済み文字数
//受信中に使用
char _sci2_rx_temp[255];	//受信中文字バッファー(最大255文字)
int _sci2_rx_now;			//受信中の文字数
int _sci2_rx_state;			//受信状況　0:待機状態、1:受信開始、2:受信中、3:受信完了、4:受信完了
//受信完了時に使用
char _sci2_rx_data[255];	//受信完了文字バッファー(最大255文字)
int _sci2_rx_num;			//受信完了した文字数
int _sci2_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受信データ



/*ここからSCI0の設定*/
//シリアル通信０初期化関数
void init_SCI0(void){
	STB.CR3.BIT._SCI0=0;	//モジュールスタンバイ解除
	PFC.PACRL1.BIT.PA0MD=1;	//PA0をRXD1入力に設定
	PFC.PACRL1.BIT.PA1MD=1;	//PA1をTXD1出力に設定
	SCI0.SCSCR.BYTE=0x00;	//設定中のため送受信割込禁止、送受信禁止

	SCI0.SCSMR.BYTE=0x00;	//とりあえず全部0(標準設定)にしておく
	SCI0.SCSMR.BIT._PE	= 1;	// パリティー有効:1／無効:0
	SCI0.SCSMR.BIT.OE	= 0;	// パリティー奇数:1／偶数:0

//	25MHz,9600bpsの時、BRR=(25000000/(32*9600)) - 1 => 80
//	SCI0.SCBRR=80;		//9600bps
//	SCI0.SCBRR=39;		//19200bps
	SCI0.SCBRR=19;		//38400bps
//	SCI0.SCBRR=6;		//115200bps

	SCI0.SCSCR.BIT.TE  = 1;		// トランスミットイネーブル:送信動作を許可
	SCI0.SCSCR.BIT.RE  = 1;		// レシーブイネーブル:受信動作を許可   
	INTC.IPRL.BIT._SCI0 = 0x6;	// 割り込み優先度(0x0:最低〜0xF:最高)
	_sci0_tx_now=0;		//送信済み文字数をリセットする

	SCI0.SCSCR.BIT.RIE = 1;		// 受信割り込み要求を許可

	init_recive_data_all();
	init_xbee_api();
}


//文字列送信関数
void write_sci0(char* trans_buf){
	if(_sci0_tx_now)	//文字列の送信が終わっていない
		return;			//関数を強制終了

	_sci0_tx_num=sprintf(_sci0_tx_data,"%s",trans_buf);	//送信文字を設定＋文字数をカウント
	SCI0.SCSCR.BIT.TIE = 1;		// 送信割り込み要求を許可
}

//文字列送信関数(sum付)
void write_sci0_sum(char* trans_buf){
	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_sci0(buf);
}

//専用フォーマットでデータを送信
void send_data_sci0(int id,int dlc,short*data){
	char trans_buf[255];
	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_sci0_sum(trans_buf);	//SUM付きで送信
}


/*ここからSCI1の設定*/
//シリアル通信１初期化関数
void init_SCI1(void){
	STB.CR3.BIT._SCI1=0;	//モジュールスタンバイ解除
	PFC.PACRL1.BIT.PA3MD=1;	//PA3をRXD1入力に設定
	PFC.PACRL2.BIT.PA4MD=1;	//PA4をTXD1出力に設定
	SCI1.SCSCR.BYTE=0x00;	//設定中のため送受信割込禁止、送受信禁止

	SCI1.SCSMR.BYTE=0x00;	//とりあえず全部0(標準設定)にしておく
	SCI1.SCSMR.BIT._PE	= 1;	// パリティー有効:1／無効:0
	SCI1.SCSMR.BIT.OE	= 0;	// パリティー奇数:1／偶数:0

//	25MHz,9600bpsの時、BRR=(25000000/(32*9600)) - 1 => 80
//	SCI1.SCBRR=80;		//9600bps
//	SCI1.SCBRR=39;		//19200bps
	SCI1.SCBRR=19;		//38400bps
//	SCI1.SCBRR=6;		//115200bps

	SCI1.SCSCR.BIT.TE  = 1;		// トランスミットイネーブル:送信動作を許可
	SCI1.SCSCR.BIT.RE  = 1;		// レシーブイネーブル:受信動作を許可   
	INTC.IPRL.BIT._SCI1 = 0x7;	// 割り込み優先度(0x0:最低〜0xF:最高)
	_sci1_tx_now=0;		//送信済み文字数をリセットする

	SCI1.SCSCR.BIT.RIE = 1;		// 受信割り込み要求を許可

	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.SCSCR.BIT.TIE = 1;		// 送信割り込み要求を許可
}

//文字列送信関数(sum付)
void write_sci1_sum(char* trans_buf){
	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){
	char trans_buf[255];
	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付きで送信
}


/*ここからSCI2の設定*/
//シリアル通信２初期化関数
void init_SCI2(void){
	STB.CR3.BIT._SCI2=0;	//モジュールスタンバイ解除
	PFC.PACRL3.BIT.PA8MD=6;	//PA8をRXD2入力に設定
	PFC.PACRL3.BIT.PA9MD=6;	//PA9をTXD2出力に設定
	SCI2.SCSCR.BYTE=0x00;	//設定中のため送受信割込禁止、送受信禁止

	SCI2.SCSMR.BYTE=0x00;	//とりあえず全部0(標準設定)にしておく
	SCI2.SCSMR.BIT._PE	= 1;	// パリティー有効:1／無効:0
	SCI2.SCSMR.BIT.OE	= 0;	// パリティー奇数:1／偶数:0

//	25MHz,9600bpsの時、BRR=(25000000/(32*9600)) - 1 => 80
//	SCI2.SCBRR=80;		//9600bps
//	SCI2.SCBRR=39;		//19200bps
	SCI2.SCBRR=19;		//38400bps
//	SCI2.SCBRR=6;		//115200bps

	SCI2.SCSCR.BIT.TE  = 1;		// トランスミットイネーブル:送信動作を許可
	SCI2.SCSCR.BIT.RE  = 1;		// レシーブイネーブル:受信動作を許可   
	INTC.IPRL.BIT._SCI2 = 0x5;	// 割り込み優先度(0x0:最低〜0xF:最高)
	_sci2_tx_now=0;		//送信済み文字数をリセットする

	SCI2.SCSCR.BIT.RIE = 1;		// 受信割り込み要求を許可

	init_recive_data_all();
}


//文字列送信関数
void write_sci2(char* trans_buf){
	if(_sci2_tx_now)	//文字列の送信が終わっていない
		return;			//関数を強制終了

	_sci2_tx_num=sprintf(_sci2_tx_data,"%s",trans_buf);	//送信文字を設定＋文字数をカウント
	SCI2.SCSCR.BIT.TIE = 1;		// 送信割り込み要求を許可
}

//文字列送信関数(sum付)
void write_sci2_sum(char* trans_buf){
	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_sci2(buf);
}

//専用フォーマットでデータを送信
void send_data_sci2(int id,int dlc,short*data){
	char trans_buf[255];
	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_sci2_sum(trans_buf);	//SUM付きで送信
}



/*ここからSCI0の割り込み関数*/
//送信割り込み処理関数
//intprog.cのINT_SCI0_TXI0へ登録が必要
void SCI0_INT_TXI0(void){
	if(SCI0.SCSSR.BIT.TDRE){	//送信可能
		if(_sci0_tx_now<_sci0_tx_num){	//まだ送信する文字がある
			SCI0.SCTDR=_sci0_tx_data[_sci0_tx_now];		//送信データを設定
			SCI0.SCSSR.BIT.TDRE = 0;	//送信開始
			_sci0_tx_now++;				//送信済み文字数をカウントアップ
		}else{					//送信する文字がなくなった
			_sci0_tx_now=0;				//送信済み文字数をリセット
			SCI0.SCSCR.BIT.TIE = 0;		// 送信割り込み要求を禁止
		}//end if
	}//end if
}


//受信割り込み処理関数
//intprog.cのINT_SCI1_RXI1へ登録が必要
void SCI0_INT_RXI0(void){
	char c;
	int code_type=0;
	int timeout=0;

	if(SCI0.SCSSR.BIT.RDRF){	//何か受信している
		SCI0.SCSSR.BIT.RDRF=0;	//受信フラグを解除
		c=SCI0.SCRDR;	//受信文字を格納

		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){
			_sci0_rx_now=0;		//受信中の文字数をリセット
		}

		if(code_type!=TYPE_BRK){	//改行文字以外
			_sci0_rx_temp[_sci0_rx_now]=c;	//受信した文字をバッファへ格納
			_sci0_rx_now++;			//受信した文字数をカウントアップ
		}

		if(code_type==TYPE_ETX || (_sci1_rx_now>=1 && code_type==TYPE_BRK)){	//終了文字または1文字以上受信後の改行文字
			_sci0_rx_temp[_sci0_rx_now]='\0';			//null文字を追加
			sprintf(_sci0_rx_data,"%s",_sci0_rx_temp);	//受信中バッファーから受信完了バッファへコピー
			_sci0_rx_num=_sci0_rx_now;	//受信文字数を格納
			_sci0_rx_fin_f=1;			//受信完了フラグを立てる
			_sci0_rx_now=0;				//受信中の文字数をリセット
		}//end TYPE_ETX		
	}//end RDRF
}//SCI0_INT_RXI0

//受信エラー割り込み関数
//intprog.cのINT_SCI0_ERI0へ登録が必要
void SCI0_INT_ERI0(void){
	if(SCI0.SCSSR.BIT.ORER==1)	//オーバーランエラーあり
		SCI0.SCSSR.BIT.ORER=0;	//オーバーランエラーフラグを解除
	if(SCI0.SCSSR.BIT.FER==1)	//フレーミングエラーあり
		SCI0.SCSSR.BIT.FER=0;	//フレーミングエラーフラグを解除
	if(SCI0.SCSSR.BIT.PER==1)	//パリティーエラーあり
		SCI0.SCSSR.BIT.PER=0;	//パリティーエラーフラグを解除
}



/*ここからSCI1の割り込み関数*/
//送信割り込み処理関数
//intprog.cのINT_SCI1_TXI1へ登録が必要
void SCI1_INT_TXI1(void){
	if(SCI1.SCSSR.BIT.TDRE){	//送信可能
		if(_sci1_tx_now<_sci1_tx_num){	//まだ送信する文字がある
			SCI1.SCTDR=_sci1_tx_data[_sci1_tx_now];		//送信データを設定
			SCI1.SCSSR.BIT.TDRE = 0;	//送信開始
			_sci1_tx_now++;				//送信済み文字数をカウントアップ
		}else{					//送信する文字がなくなった
			_sci1_tx_now=0;				//送信済み文字数をリセット
			SCI1.SCSCR.BIT.TIE = 0;		// 送信割り込み要求を禁止
		}//end if
	}//end if
}


//受信割り込み処理関数
//intprog.cのINT_SCI1_RXI1へ登録が必要
void SCI1_INT_RXI1(void){
	char c;
	int code_type=0;
	if(SCI1.SCSSR.BIT.RDRF){	//何か受信している
		SCI1.SCSSR.BIT.RDRF=0;	//受信フラグを解除
		c=SCI1.SCRDR;	//受信文字を格納

		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		
	}//end RDRF
}//SCI1_INT_RXI1

//受信エラー割り込み関数
//intprog.cのINT_SCI1_ERI1へ登録が必要
void SCI1_INT_ERI1(void){
	if(SCI1.SCSSR.BIT.ORER==1)	//オーバーランエラーあり
		SCI1.SCSSR.BIT.ORER=0;	//オーバーランエラーフラグを解除
	if(SCI1.SCSSR.BIT.FER==1)	//フレーミングエラーあり
		SCI1.SCSSR.BIT.FER=0;	//フレーミングエラーフラグを解除
	if(SCI1.SCSSR.BIT.PER==1)	//パリティーエラーあり
		SCI1.SCSSR.BIT.PER=0;	//パリティーエラーフラグを解除
}



/*ここからSCI2の割り込み関数*/
//送信割り込み処理関数
//intprog.cのINT_SCI2_TXI2へ登録が必要
void SCI2_INT_TXI2(void){
	if(SCI2.SCSSR.BIT.TDRE){	//送信可能
		if(_sci2_tx_now<_sci2_tx_num){	//まだ送信する文字がある
			SCI2.SCTDR=_sci2_tx_data[_sci2_tx_now];		//送信データを設定
			SCI2.SCSSR.BIT.TDRE = 0;	//送信開始
			_sci2_tx_now++;				//送信済み文字数をカウントアップ
		}else{					//送信する文字がなくなった
			_sci2_tx_now=0;				//送信済み文字数をリセット
			SCI2.SCSCR.BIT.TIE = 0;		// 送信割り込み要求を禁止
		}//end if
	}//end if
}


//受信割り込み処理関数
//intprog.cのINT_SCI2_RXI2へ登録が必要
void SCI2_INT_RXI2(void){
	char c;
	int code_type=0;
	if(SCI2.SCSSR.BIT.RDRF){	//何か受信している
		SCI2.SCSSR.BIT.RDRF=0;	//受信フラグを解除
		c=SCI2.SCRDR;	//受信文字を格納

		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){
			_sci2_rx_now=0;		//受信中の文字数をリセット
		}

		if(code_type!=TYPE_BRK){	//改行文字以外
			_sci2_rx_temp[_sci2_rx_now]=c;	//受信した文字をバッファへ格納
			_sci2_rx_now++;			//受信した文字数をカウントアップ
		}

		if(code_type==TYPE_ETX || (_sci2_rx_now>=1 && code_type==TYPE_BRK)){	//終了文字または1文字以上受信後の改行文字
			_sci2_rx_temp[_sci2_rx_now]='\0';			//null文字を追加
			sprintf(_sci2_rx_data,"%s",_sci2_rx_temp);	//受信中バッファーから受信完了バッファへコピー
			_sci2_rx_num=_sci2_rx_now;	//受信文字数を格納
			_sci2_rx_fin_f=1;			//受信完了フラグを立てる
			_sci2_rx_now=0;				//受信中の文字数をリセット
		}//end TYPE_ETX		
	}//end RDRF
}//SCI2_INT_RXI2

//受信エラー割り込み関数
//intprog.cのINT_SCI2_ERI2へ登録が必要
void SCI2_INT_ERI2(void){
	if(SCI2.SCSSR.BIT.ORER==1)	//オーバーランエラーあり
		SCI2.SCSSR.BIT.ORER=0;	//オーバーランエラーフラグを解除
	if(SCI2.SCSSR.BIT.FER==1)	//フレーミングエラーあり
		SCI2.SCSSR.BIT.FER=0;	//フレーミングエラーフラグを解除
	if(SCI2.SCSSR.BIT.PER==1)	//パリティーエラーあり
		SCI2.SCSSR.BIT.PER=0;	//パリティーエラーフラグを解除
}

/*ここから受信解析関連*/
//受信フラグを確認
int get_recive_f(int port){
	int value=0;
	switch (port){
		case 0:
			value=_sci0_rx_fin_f;
			break;
		case 1:
			value=_sci1_rx_fin_f;
			break;
		case 2:
			value=_sci2_rx_fin_f;
			break;
		default:
			value=0;
			break;
	}
	return value;
}
//受信フラグをクリア
void clr_recive_f(int port){
	switch (port){
		case 0:
			_sci0_rx_fin_f=0;
			break;
		case 1:
			_sci1_rx_fin_f=0;
			break;
		case 2:
			_sci2_rx_fin_f=0;
			break;
		default:
			break;
	}
}

//受信データをコピー
void get_recive_buf(int port,char* buf){
	switch (port){
		case 0:
			sprintf(buf,"%s",_sci0_rx_data);
			break;
		case 1:
			sprintf(buf,"%s",_sci1_rx_data);
			break;
		case 2:
			sprintf(buf,"%s",_sci2_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_sci0(int id,int dlc,short*data){
	recv_data_sci(id,dlc,data);
}
//別の関数名でも実行させる
void recv_data_sci1(int id,int dlc,short*data){
	recv_data_sci(id,dlc,data);
}
//別の関数名でも実行させる
void recv_data_sci2(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];
}