
#include "base_core.h"
#include "base_core_user.h"
#include "platform_interface.h"
#include "base_pc_protocol.h"
#include "function_interface.h"


#ifdef RF_5G8
#include "string.h"
//queue
struct link_queue_STR keypad_info;

#ifdef BUF_ALERT2
struct buf_alert_get_STR buf_get_info;

//寻找是否有键盘buf告警需要单独处理
unsigned char check_buf_alert(struct link_queue_STR *queue,unsigned char offset)
{ unsigned char i;
	unsigned int sn;
	
	struct link_node_STR *p =queue->front;
	for(i=0;i<offset;i++){
		if(p->next ==NULL) return 0;	
		p = p->next;
	}
	
	while(p->next!=NULL){

		if (p->next->element.buf_warnning ==1) //if ((p->next->element.buf_warnning ==1)) //des by Pei; 去掉一对括号，解决编译报警20210221 Gavin;
		{
			memcpy(buf_get_info.SN,p->next->element.id_sn,4);
			buf_get_info.GetT=0;
			buf_get_info.Status=1;
			//sn=(buf_get_info.SN[0]<<24)+(buf_get_info.SN[1]<<16)+(buf_get_info.SN[2]<<8)+(buf_get_info.SN[3]);
			//DEBUG_LOG(">>>SN[%10d] @%d BufAlert Get Start!\n",sn,offset+1);
			return offset+1;
		}
		p =p->next;
		offset++;
	}//while		
	return 0;	
}


#endif

#ifdef VOICE_PROTOCOL_3RD
/* 20200924 移植整合第三版协议;
*a,协议中增加了键盘buf告警标志，基站收到后给予此键盘更多的时间片; buf_warnning
*b,模糊了点名和重传的区别;点名也会将上次的re_send_offset发送给键盘;
*c,键盘在收到要求重传时,会将重传slot+新的数据 =8slot重新发送;
*d,基站发送重传信息不满10个时,会按点名的方式补满，并记录fill_10_offset位置，
***遇到同样情景时就会接着fill_10_offset继续补满10，直到补满或者遍历完queue!!!
*f,接着d,为避免同一个键盘SN重传和补满10重复的情况(不会出错,影响效率),用ask_resend_state来区别
*/

unsigned char fill_10_offset=0;	//补10读取到queue中位置偏移
/*
* 重传个数不满10个时，调用此函数补满10(如果queue有足够名单的话)
* 点名个数不满10个时,
* 如何避免：a,某个键盘的重传和点名不在同一个周期内?
*/
unsigned char fill_10_list(struct link_queue_STR *queue,unsigned char *out,unsigned char count)
{
	unsigned char i;
	struct link_node_STR *p =queue->front;
	
	for(i=0;i<fill_10_offset;i++){
		if(p->next ==NULL) return 0;
		p = p->next;	
	}
	
	while( count <10){		
		if(p->next==NULL){ //到尾了?
			fill_10_offset =0;
			return 0;
		}
		if(p->next->element.ask_resend_state==1){//刚刚已经重传了;补齐10个里就不要包括它了;
			p =p->next;	
			continue;	
		}
		//4byte sn +1byte re_send_slot;
		mem_cpy(p->next->element.id_sn,&out[count*5],4);
		#ifdef VOICE_PROTOCOL_3RD
		out[count*5+4] = p->next->element.re_send_slot;	
		#else
		out[count*5+4] = 0x00;//此字节表示重传，此处为点名，输出0x00;  p->next->element.re_send_slot;
		#endif
		p->next->element.re_send_slot =0xff;		
#ifdef 	_DBG_VOICE_KP
			if( base_core.get_run_status() ==_STA_VOICE_VOTEING  )//投票状态下才记录
				p->next->element.send_beacon_cnt++;
#endif
		fill_10_offset++;
		count++;
		p =p->next;		
	}//while
	
	return 0;		
}
#endif 


/*
连续取出10 个element 数据：sn,re-send;
* out 		---keypad sn and re-send-slot;
* offset 	---start search from queue offset;
*return :下一个节点 在队列中的偏移;
*/
unsigned char link_queue_outN(struct link_queue_STR *queue,unsigned char *out,unsigned char offset)
{
	unsigned char i;
	unsigned char len=0;
	unsigned char count=0;	
	struct link_node_STR *p =queue->front;
	
	for(i=0;i<offset;i++){
		if(p->next ==NULL) return 0;
		p = p->next;	
	}	
	
	while(p->next!=NULL){
		len++;
		//4byte sn +1byte re_send_slot;
		mem_cpy(p->next->element.id_sn,&out[count*5],4);
		#ifdef VOICE_PROTOCOL_3RD
		p->next->element.ask_resend_state =0;
		out[count*5+4] = p->next->element.re_send_slot;	
		#else
		out[count*5+4] = 0x00;//此字节表示重传，此处为点名，输出0x00;  p->next->element.re_send_slot;
		#endif
		p->next->element.re_send_slot =0xff;		
#ifdef 	_DBG_VOICE_KP
			if( base_core.get_run_status() ==_STA_VOICE_VOTEING  )//投票状态下才记录
				p->next->element.send_beacon_cnt++;
#endif		
		p =p->next;
		if(++count>=10){
			if(p->next!=NULL)
				return (offset+len);//(p->next->next - queue->front);
			else
				return 0;
		}			
	}//while	
	
	
	
	return 0;	
}


/*
查找是否存在需要重传的键盘，如果有就复制其数据
每次最多复制10个，
然后继续遍历之后的队列，直到找到还有重传的或者没有重传的了*/
unsigned char link_queue_outN_re_send(struct link_queue_STR *queue,unsigned char *out,unsigned char offset)
{
	unsigned char i;
	unsigned char len=0;
	unsigned char count=0;	
	struct link_node_STR *p =queue->front;
	
	for(i=0;i<offset;i++){
		if(p->next ==NULL) return 0;	//add 20200924??
		p = p->next;
	}
	while(p->next!=NULL){
			len++;
			#ifdef VOICE_PROTOCOL_3RD
			if( (p->next->element.re_send_slot ==0)&&(p->next->element.buf_warnning==0) )
			#else
			if(p->next->element.re_send_slot ==0)
			#endif
			{
				p =p->next;	continue; 
			}			
			#ifdef _DBG_VOICE_KP
			p->next->element.re_send_timers++;
			#endif
			
			#ifdef BUF_ALERT2
			if ((p->next->element.buf_warnning==1)&&(buf_get_info.Status==0))
					{//优化重传中有buf告警，一定执行点名，即使键盘又不告警了
						//DEBUG_MSG("SN[%10d] Buf Alert!-PreSET-\n",sn);
						memcpy(buf_get_info.SN,p->next->element.id_sn,4);
						buf_get_info.GetT=0;
						buf_get_info.Status=1;
					}
			#endif
					
			mem_cpy(p->next->element.id_sn,&out[count*5],4);//4byte sn +1byte re_send_slot;
			out[count*5+4] = p->next->element.re_send_slot;
			/* 此处不同的原因是键盘对重传的处理不同了:
			a,befor 键盘收到重传信号后，就发送基站告知的那几个slot就可以了;
			b,Now 键盘收到重传信号后,将基站告知的那几个slot和新的数据凑齐7slot发送;	*/
			#ifdef VOICE_PROTOCOL_3RD 
			p->next->element.re_send_slot=0xFF; //pei漏了就导致原来的丢包！！
			p->next->element.ask_resend_state =1;
			#endif			
			p =p->next;	
			if(++count>=10){				
				while(p->next !=NULL){//继续查找看后面是否还有数据;					
					if( p->next->element.re_send_slot !=0) return len+offset;//(p->next->next - queue->front);
					len++;
					p =p->next;
				}//while
				return 0;
			}				
	}//while
	
	#ifdef VOICE_PROTOCOL_3RD
	//重传不满10个时，会用点名来代替;
	fill_10_list(queue,out,count);
	#endif 
	
	return 0;	
}


/*
检测队列中是否有需要重传的键盘*/
unsigned char link_queue_check_re_send(struct link_queue_STR *queue,unsigned char offset)
{
	unsigned char remain_re_send=0;
	
	struct link_node_STR *p =queue->front;
//	for(i=0;i<offset;i++)//????????????????????
//		p = p->next;	
	
	while(p->next!=NULL){
		#ifdef VOICE_PROTOCOL_3RD
		if( (p->next->element.re_send_slot !=0) ||(p->next->element.buf_warnning==1) )
		#else				
		if( p->next->element.re_send_slot !=0)
		#endif
		{
			remain_re_send++;//return 1;
		}
		p =p->next;
	}//while		
	return remain_re_send;	
}


/*
* 检测键盘在线/离线
* check keypad on/offline 
*/
void link_queue_check_online(struct link_queue_STR *queue)
{	
	struct link_node_STR *p_tmp,*p =queue->front;
	
	while(p->next!=NULL){
		if( ++p->next->element.offline_count >= OFFLINE_COUNT){//连续N个大周期没有收到数据
			p_tmp =p->next;		
			if(p_tmp == queue->rear)//如果是尾指针，更新
				queue->rear =p;
			
			p->next = p->next->next;
			p_tmp->status=0;
			p_tmp->next=NULL;
			continue;			
		}
		p =p->next;
	}//while	
}






/*
*遍历整个队列，复制有效键盘的sn号
* return 键盘的个数
*/
unsigned char get_link_queue_sn(unsigned char *sn)
{
	unsigned char length=0;
	struct link_node_STR *p =keypad_info.front;
	
	while(p->next!=NULL){
		length++;
		mem_cpy(p->next->element.id_sn,sn,4);
		sn +=4;
		p =p->next;
	}//while	
	
	return length;
}



/* 重新开始一次DATEpos变化; 初始化重发标志! 
* 其实在非语音状态下，基站收到键盘的心跳时也会初始化重传标志为0;
*/
void re_init_all_resend_slot(void)
{
	struct link_node_STR *p =keypad_info.front;
	#ifdef VOICE_PROTOCOL_3RD
	fill_10_offset=0;	 //
	#endif
	while(p->next!=NULL){
		p->next->element.re_send_slot=0;
		
		p =p->next;
	}//while	
}





/*-----------------------------------------------------------
基站处理键盘无线数据	*/
/*
void keypad_rf_data_process(void)
{
	unsigned char buf[64+4];	
//	unsigned char *tmp;	
//	unsigned char rfid;		
	

	if(!keypad_rf_data_fetch(buf) )return;	
	
	keypad_rf_data_process_NO_fifo(buf);
}	
*/

/*

*/
void keypad_rf_data_process_NO_fifo(unsigned char *buf)
{	
	//unsigned char buf[64+4];	
	unsigned char *tmp;	
	unsigned char rfid;		
	

//	if(!keypad_rf_data_fetch(buf) )return;	

	//buf0 		-modual id
	//buf1-3 	-match code
	//buf5    CMD type
	tmp= buf+4;
	
	//将来自硬件的id转化成 核心记录硬件id的数组下标！！！！ 
	rfid= conver_id(buf[0]);
	
	//monitor same freq
	if(function.monitor__rf_data(tmp)!=0) //if( function.monitor__SW &&(function.monitor__rf_data(tmp)!=0) )
		return;
	
	//check_matchcode(tmp);
	if(mem_compare(buf+1,base_mac.match_code,3) ==0){
		//mem_cpy(buf+1,rx_error_match_code,3);		
		return;
	}
	
	refresh_rcvRF_indicate();
	
	switch(tmp[1]){
		case 0x96: //是键盘的入网信息
			{
				ELEMENT ele_tmp[1];
				struct link_node_STR *node;
				
				platform.disable_interrupt();
				if( (node =link_queue_find_special_sn(&keypad_info,tmp+2) ) ==NULL){//队列中没有此键盘sn,就记录下来
					mem_cpy(tmp+2,ele_tmp->id_sn,4);
					ele_tmp->re_send_slot=0xff;
					ele_tmp->offline_count =0; //clear offline count
					
					#ifdef  _DBG_VOICE_KP//debug only.	
					_debug_voice_kp__init_keypad_parameter(ele_tmp);
					#endif
					link_queue_input(&keypad_info,ele_tmp);
				}
				else{ //收到已经入网的键盘入网信息,how to process?????s	
					#ifdef  _DBG_VOICE_KP	//debug only!!
					_debug_voice_kp__init_keypad_parameter(& node->element);
					#endif
				}
				platform.enable_interrupt();
			}
			break;
			
		#if 1//#ifndef KEYPAD60
		case 0x95:	//是语音数据 --第一版语言协议
			{
				unsigned char total,slot_seq;
				struct link_node_STR *node;			
				
				platform.disable_interrupt();
				//收到的键盘数据不在SN list中， 不做任何处理!
				if( (node =link_queue_find_special_sn(&keypad_info,tmp+2)) ==NULL)goto _proce_voice_exit;//  break;							
								
				if( tmp[8]==0){	//是心跳包
					node->element.re_send_slot =0; 	 	//清除重传标志!!!!
					node->element.offline_count =0;		//复位离线在线计数器
				
					//过滤心跳包,30包上报1包
					if( ++node->element.filt_heart_pkt_count>= 30){ 
						node->element.filt_heart_pkt_count=0;
					}							
					else
						goto _proce_voice_exit;//break;

					if( get_pc_connect_status()==0)//没有连接sdk时，心跳包就不进缓冲器
						goto _proce_voice_exit;//break;
				}
				else{ //是语音数据包
					node->element.filt_heart_pkt_count=0;//清除过滤心跳包计数器
					
					#ifdef  _DBG_VOICE_KP
					node->element.rxkp_cnt++;
					#endif
			
					total =tmp[10]>>4;							
					total = 0xff>>(8-total);//conver to bit 	
					slot_seq =tmp[10]&0x0f;
					slot_seq = 1<<(slot_seq-1);	
					
					node->element.offline_count =0;
					node->element.re_send_slot &= (~slot_seq)&total;
				}			
				platform.enable_interrupt();	
				
				//将数据加入到上报到pc的缓冲区中
				if( vote_data_store(tmp+1) ==0){
					#ifdef _DBG_VOICE_KP
					kernel.rx_buf_overflow++;//debug only
					#endif					
				}											
			}
			break;
_proce_voice_exit:
			platform.enable_interrupt();			
			break;
			#endif 
		
		#if 1//defined(KEYPAD60)&& !defined(VOICE_PROTOCOL_3RD)
		case 0x97:	//是语音数据 -第二版协议
			{
				unsigned char total,slot_seq;
				struct link_node_STR *node;			
#define 	PACKH_INDEX 6//8	
#define 	SLOTN_INDEX 8//10					
				platform.disable_interrupt();
				//收到的键盘数据不在SN list中， 不做任何处理!
				if( (node =link_queue_find_special_sn(&keypad_info,tmp+2)) ==NULL)goto _proce_voice_exit2;//  break;							
								
				if( tmp[PACKH_INDEX]==0){	//是心跳包
					node->element.re_send_slot =0; 	 	//清除重传标志!!!!
					node->element.offline_count =0;		//复位离线在线计数器
					
					//过滤心跳包,30包上报1包
					if( ++node->element.filt_heart_pkt_count>= 30){ 
						node->element.filt_heart_pkt_count=0;
					}							
					else
						goto _proce_voice_exit2;//break;

					if( get_pc_connect_status()==0)//没有连接sdk时，心跳包就不进缓冲器
						goto _proce_voice_exit2;//break;
				}
				else{ //是语音数据包
					node->element.filt_heart_pkt_count=0;//清除过滤心跳包计数器
					
					#ifdef  _DBG_VOICE_KP
					node->element.rxkp_cnt++;
					#endif
			
					total =tmp[SLOTN_INDEX]>>4;							
					total = 0xff>>(8-total);//conver to bit 	
					slot_seq =tmp[SLOTN_INDEX]&0x0f;
					slot_seq = 1<<(slot_seq-1);	
					
					node->element.offline_count =0;
					node->element.re_send_slot &= (~slot_seq)&total;
				}			
				platform.enable_interrupt();	
				
				//将数据加入到上报到pc的缓冲区中
				if( vote_data_store(tmp+1) ==0){
					#ifdef _DBG_VOICE_KP
					kernel.rx_buf_overflow++;//debug only
					#endif
				}											
			}
			break;
_proce_voice_exit2:
			platform.enable_interrupt();			
			break;
			#endif 
					
		#if defined(KEYPAD60)&& defined(VOICE_PROTOCOL_3RD)
		case 0x98:		//是语音数据 -第三版协议
			{
				unsigned char total,slot_seq;
				struct link_node_STR *node;			
				
				platform.disable_interrupt();
				//收到的键盘数据不在SN list中， 不做任何处理!
				if( (node =link_queue_find_special_sn(&keypad_info,tmp+2)) ==NULL)goto _proce_voice_exit3;//  break;							
				
				node->element.offline_count =0;		//复位离线在线计数器
				if( tmp[8]==0xff){	//是心跳包
					node->element.re_send_slot =0; 	 	//清除重传标志!!!!	
					
					#ifdef BUF_ALERT2
					//0x15单独点名提前终止，节约一点时间
					if (buf_get_info.Status)
					{
						if (mem_compare(tmp+2,buf_get_info.SN,4))//SN相同
						{
							//DEBUG_MSG("--- BufAlert QuickExit!--%d\n",BUF_GET_T-buf_get_info.GetT);
							buf_get_info.GetT=BUF_GET_T;
							buf_get_info.Status=0;
						}
					}
					#endif
					
					//过滤心跳包,30包上报1包
					if( ++node->element.filt_heart_pkt_count>= 30){ 
						node->element.filt_heart_pkt_count=0;
					}							
					else
						goto _proce_voice_exit3;//break;

					if( get_pc_connect_status()==0)//没有连接sdk时，心跳包就不进缓冲器
						goto _proce_voice_exit3;//break;
				}
				else{ //是语音数据包
					node->element.filt_heart_pkt_count=0;//清除过滤心跳包计数器					
					#ifdef  _DBG_VOICE_KP
					node->element.rxkp_cnt++;
					#endif			
//					total =tmp[10]>>4;							
//					total = 0xff>>(8-total);//conver to bit 	
//					slot_seq =tmp[10]&0x0f;
//					slot_seq = 1<<(slot_seq-1);
//					node->element.offline_count =0;
//					node->element.re_send_slot &= (~slot_seq)&total;					
					total =((tmp[8]>>4)&7)+1;							
					total = 0xff>>(8-total);//conver to bit 	
					slot_seq =tmp[8]&0x0f;//SLOTN
					slot_seq = 1<<(slot_seq);//-1);
					
					//记录语音buf告警
					node->element.buf_warnning =(tmp[8]&0x80)?1:0;
				}			
				platform.enable_interrupt();	
				
				//将数据加入到上报到pc的缓冲区中
				if( vote_data_store(tmp+1) ==0){
					#if 1 //#ifdef _DBG_VOICE_KP
					kernel.rx_buf_overflow++;//debug only
					#endif					
				}
				else{
					node->element.re_send_slot &= ((~slot_seq)&total);	//收到的片号bit置0	
				}				
			}
			break;
_proce_voice_exit3:
			platform.enable_interrupt();														
			break;			
		#endif 

		//普通投票数据	
		case 0x93: 
		case 0x94:	//store vote data and record SN that using at base ack;
			{
				struct link_node_STR *node;
				if( (node =link_queue_find_special_sn(&keypad_info,tmp+3) ) ==NULL){
					#ifdef _DBG_VOICE_KP
					_debug_voice_kp__record_illegal_rx_idsn(tmp+3);	
					#endif
				}
				else{	
					#ifndef _DBG_VOICE_KP
					vote_data_store(tmp+1);					
					keypad_idsn_save(&tmp[3],4,rfid);
					#else
					if(vote_data_store(tmp+1) )
						node->element.rxkp_cnt++;
					else
						kernel.rx_buf_overflow++;//debug only
					
					if(keypad_idsn_save(&tmp[3],4,rfid) )	
						node->element.ackkp_in_cnt++;					
					else
						kernel.rx_idsnbuf_overflow++;//test only
					#endif			
				}
			}
			break;
		
		case 0xB0://single packet download
			keypad_transfer2pc_data_save(tmp);//store to transfer buffer 
			//operation_debug_io(4);//test only
			break;
		
		case 0xC0://multi packet download ,using keypad firmware update!
			if(function.updatekp__SW && function.update__save_keypad_ack_data(tmp) )return;
			break;
		
		default:
			break;
	}//sw
}


/*初始化 用于组呼的 链表*/
void base_process_5G8_keyapd_init_queue(void)
{
	link_queue_init(&keypad_info);	
}


unsigned short get_rx_buf_overflow(void) //debug only
{
return kernel.rx_buf_overflow;//
}


//-----------------------------------------------------------------------------------------
//----------------------- debug start -----------------------------------------------------
/*
2020.05.20由于语音键盘没有id模式(至少在语音模式下没有)，并且sn号是有NFC卡号决定的，没法用户编号!
从而导致debug检测键盘数据时不能使用常规的内核检测方法(或者说用起来很麻烦而且检测可能会影响运行速度)
所以需要单独写debug检测方法：
a,利用键盘名单keypad list，增加变量记录信息;
b,当debug app发送对应的SN查询时，在keypad list中搜索然后取出对应的调试信息;
c，输入ff 88 (十进制SN-5bytes)
d，开启新一轮投票时，开启debug功能，并且清除所有相关变量;


_DBG_VOICE_KP :
从键盘单体来看，检测的参数有：包括语音和非语音
	重传次数
	收到的数据包个数
	基站ack个数
	上报给sdk数据包个数
	被sdk确认的数据包个数		
*/


#ifdef _DBG_VOICE_KP

/*
清除 某个键盘的debug参数;	入网时被调用！！
*/
void _debug_voice_kp__init_keypad_parameter(ELEMENT *ele_tmp)
{
		ele_tmp->re_send_timers =0; 
		ele_tmp->rxkp_cnt =0;
		ele_tmp->ackkp_cnt =0; 
		ele_tmp->ackkp_in_cnt =0;	
		ele_tmp->tx_pc_cnt =0;
	
		ele_tmp->send_beacon_cnt=0;
}

/*
* 清除所有的debug 参数；新一轮投票开始时被调用!!!
*/
void _debug_voice_kp__init_all_parameter(void)
{
	struct link_node_STR *p_tmp,*p =keypad_info.front;// queue->front;
	
	//a,clear all keypad parameter
	while(p->next!=NULL){
		_debug_voice_kp__init_keypad_parameter(&p->next->element);
		p =p->next;
	}//while	
	
	//b,clear other parameter
	kernel.re_rpt_pc_count=0;
	kernel.rx_buf_overflow =0;
	kernel.rx_idsnbuf_overflow =0;
}



/*
*监测某个键盘数据上报个sdk的次数!!
*/
void _debug_voice_kp__tx_pc(unsigned char *sn)
{	
	struct link_node_STR *node;			
	
	//收到的键盘数据不在SN list中， 不做任何处理!
	if( (node =link_queue_find_special_sn(&keypad_info,sn)) ==NULL)return;
		node->element.tx_pc_cnt++;					
}

/*
*监测某个键盘被基站确认的次数,语音模式下没有确认，所以无效!!
*/
void _debug_voice_kp__ack_keypad(unsigned char *sn)	
{	
	struct link_node_STR *node;			
	
	//收到的键盘数据不在SN list中， 不做任何处理!
	if( (node =link_queue_find_special_sn(&keypad_info,sn)) ==NULL)return;
		node->element.ackkp_cnt++;					
}


void _debug_voice_kp__record_illegal_rx_idsn(unsigned char *sn)
{

}








/*
* offset偏移位置上的键盘信息
*/
static void get_5g8_keypad_info__basic(unsigned char offset, unsigned char *info)
{
//    struct _debug_keypad_info_STR p =_dbg_core_.kp_info[offset];
//		mem_cpy(p.kp_idsn,info+0,6);
//    info[6] = p.rx_kp_cnt>>8;
//    info[7] = p.rx_kp_cnt;
//    info[8] = p.ack_kp_cnt>>8;
//    info[9] = p.ack_kp_cnt;
//    info[10] = p.tx_pc_cnt>>8;
//    info[11] = p.tx_pc_cnt;
//    info[12] = p.acked_pc_cnt>>8;
//    info[13] = p.acked_pc_cnt; 
	
		struct link_node_STR *node;	
		//mem_cpy(p.kp_idsn,info+0,6);
    info[6] = node->element.rxkp_cnt>>8;	//rx packet count;
    info[7] = node->element.rxkp_cnt;	
  
}

/*------------------------------------------------------------------
*
*/
void _debug_core__process_5G8_keypad(unsigned char* pc)
{
	unsigned char tmp[64],cmd_type;
	unsigned char start_offset =6;

	mem_set(tmp,64,' ');
	mem_cpy(pc+8,tmp,start_offset);
	cmd_type =pc[12];
	//pc[13] ==':'
	//pc[14] ---有效数据开始....
	if(mem_compare(pc+8,(unsigned char*)"READ",4) ){//read keypad info
			unsigned char index;
			index = pc[14];
			switch (cmd_type){
				case '1':   //read键盘基础信息
					get_5g8_keypad_info__basic(index,tmp+start_offset);                    
					break;
				case '2':   //rx keypad  sn error
					//get_SNerror_info(_dbg_core_.rx_idsn_err_cnt,_dbg_core_.rx_idsn_err,index,tmp+start_offset);
					break;
				case '3':   //ack keypad sn error
					//get_SNerror_info(_dbg_core_.ack_idsn_err_cnt,_dbg_core_.ack_idsn_err,index,tmp+start_offset);
					break;					
				case '4':   //tx pc sn error
					//get_SNerror_info(_dbg_core_.txpc_idsn_err_cnt,_dbg_core_.txpc_idsn_err,index,tmp+start_offset);
					break;					
				
				default:
					mem_cpy("ERR",tmp+start_offset,3);
					break;
			}//sw
	}//if
	else if(mem_compare(pc+8,(unsigned char*)"STAT",4) ){
			switch (cmd_type){
				case '1'://setting
					if( (pc[14] ==0)||(pc[14] ==1)||(pc[14] ==2) ){
//						_dbg_core_.status =pc[14];
						mem_cpy("ok ",tmp+start_offset,3);
					}
					else
						mem_cpy("ERR",tmp+start_offset,3);                   
						break;
				case '3':	//inquire
//					tmp[start_offset] = _dbg_core_.status;
//					tmp[start_offset+1] = _dbg_core_.valid_kp_cnt;
//					tmp[start_offset+2] = _dbg_core_.idsn_len;
//					tmp[start_offset+3] = _dbg_core_.rx_idsn_err_cnt;
//					tmp[start_offset+4] = _dbg_core_.ack_idsn_err_cnt;				
//					tmp[start_offset+5] = _dbg_core_.txpc_idsn_err_cnt;				
					break;
				default:
					mem_cpy("ERR",tmp+start_offset,3);
					break;
			}//sw            
	}
	else{
			mem_cpy("ERR",tmp+start_offset,3);
	}

	//response pc cmd 
	response_pc_cmd("5g8",tmp,64);


}










#include "stdio.h"
#include "stdlib.h"
#include "string.h"
/*
输入的十六进制数（5字节），当成10进制（只有4字节）; 
例如 :
输入 12 34; 实际是0x1234；但是用户想要的是十进制的1234；
*/
//static void Dec_to_Hex(unsigned char *sn,unsigned char *dec )
//{
//	int tmp;
//	char buf[10];
//	unsigned char i;
//	
//	//a,hex conver to string
//	for(i=0;i<5;i++)
//		sprintf( (char *)(buf + (i<<1)),"%02x",sn[i]);
//	//b,string conver to integer
//	tmp =atoi(buf);
//	
//	dec[0] = tmp>>24;
//	dec[1] = tmp>>16;	
//	dec[2] = tmp>>8;	
//	dec[3] = tmp>>0;	
//}

/*------------------------------------------------------------
此函数解决debug时 显示字符
1 line: inquired keypad SN
2 line: keypad list count
3 line: 
app 发送查询某个键盘信息的命令
基站收到命令后:在keypad list中搜索键盘，如果存在,复制该键盘数据上报给app;
*/
void _debug_voice_kp__app_get_keypad_debug_info(unsigned char *sn_dec)
{
	struct link_node_STR *node;			

	unsigned char i,j,count;
	unsigned char tmp[256];
	unsigned char sn[4];
	
	count=0;
	memset(tmp,' ',200);
	
	Dec_to_Hex(sn_dec,5,sn);
	
	//1 line
	sprintf( (char *)(tmp),"SN: ");
	sprintf( (char *)(tmp+4),"%010d",(sn[0]<<24)+(sn[1]<<16)+(sn[2]<<8)+sn[3]);
	if( (node =link_queue_find_special_sn(&keypad_info,sn)) ==NULL){
		//查询的SN不在 keypad SN list中
		sprintf( (char *)(tmp+16),"Err:SN nonexst!"); //2 line
	}		
	else{
		//2 line 接收到的键盘数据包个数
		sprintf( (char *)(tmp+16),"RXKP:");
		sprintf( (char *)(tmp+16+5),"%011d",node->element.rxkp_cnt);
		//3 line 键盘重发次数
		sprintf( (char *)(tmp+32),"KPRETX:");
		sprintf( (char *)(tmp+32+7),"%09d",node->element.re_send_timers);

		//4 line 十六进制 上报给sdk的数据包个数
		sprintf( (char *)(tmp+48),"TXPC:");
		sprintf( (char *)(tmp+48+5),"%011d",node->element.tx_pc_cnt);
	
		//5 line 因缓冲器溢出丢失的数据包 总个数
		sprintf( (char *)(tmp+64),"RX_OV:");
		sprintf( (char *)(tmp+64+6),"%010d",kernel.rx_buf_overflow);		

		//6 line 在线键盘个数
		sprintf( (char *)(tmp+80),"KP_CNT:");
		sprintf( (char *)(tmp+80+7),"%09d",get_link_queue_length(&keypad_info) );
		
		//7 line 数据重发给sdk的总次数
		sprintf( (char *)(tmp+96),"REPC:");
		sprintf( (char *)(tmp+96+5),"%011d",kernel.re_rpt_pc_count );	


		//8 line 点名次数
		sprintf( (char *)(tmp+112),"CALL:");
		sprintf( (char *)(tmp+112+6),"%010d",node->element.send_beacon_cnt );
	}

	tmp[189]=0xa5;	//调试时，bushound监测到此数据串就停下来，便于观察！！
	tmp[190]=0x5a;
	tmp[191]=0xa5;
	
	platform.base_send_data_to_pc(tmp+0,256);	
}
#endif 
//-------------------------- debug end --------------------------------------------




#endif //RF_5G8

