
#include "base_core.h"
#include "base_core_user.h"
#include "platform.h"
#include "string.h"
	

//定义用于记录投票数据的缓冲区
#ifdef 	RF_5G8 
	#define 	VOTE_NODE_SIZE		1024//512		//节点个数，即缓冲区长度
	#define 	VOTE_DATA_SIZE  	64		//数据的最大长度，来自无线键盘的数据，5,8G MAX=64bytes
	
	#define 	_1PKT_NKEYPAD 		15		//一个数据包里有多少个键盘数量;
	#define 	_1KAYPAD_BYTES		60		//1个键盘的数据长度是60字节;

#else
	#define 	VOTE_NODE_SIZE		200	//节点个数，即缓冲区长度
	#define 	VOTE_DATA_SIZE  	32	//数据的最大长度,来自无线键盘的数据，
#endif 

//static 
	struct fifo_queue_STR  vote_queue;
static unsigned char vote_buf[VOTE_NODE_SIZE][VOTE_DATA_SIZE];


/*
初始化缓冲区，队列与数组建立关联 */
void vote_init_queue(void)
{
		queue_init(&vote_queue,(unsigned char**)vote_buf,VOTE_NODE_SIZE,VOTE_DATA_SIZE);
}

/*
保持数据到队列中;
called by 基站接收处理键盘数据函数
*/
unsigned char vote_data_store(unsigned char *vote_data)
{
	return queue_in(&vote_queue,vote_data,VOTE_NODE_SIZE,VOTE_DATA_SIZE);
}

//模拟成键盘数据向PC发送基站状态报告,借用一问十答确认机制，确保不丢包
unsigned char Core_PC_active_rpt(const unsigned char *info,unsigned char len)
{
    unsigned char tmp[64];
	memset(tmp,0,64);
	tmp[0] =0x94; //byte1
	tmp[1] =11;		//基站报告状态
//	tmp[2] =rslt;		
////	tmp[3] =0x38;	
	memcpy(tmp+2,info,len);
    vote_data_store(tmp);//vote_data_store(tmp);
}

/*
定义一个专门上报给pc的缓冲区，优点：保持原有队列！！ */
static unsigned char packet_count=0;
struct packet_STR{
#ifdef RF_5G8	
	unsigned char count;	//packet中包含的键盘个数;<=_1PKT_NKEYPAD;
	unsigned char data[60*_1PKT_NKEYPAD];//usb PHY max length =1024bytes
#else
	unsigned char data[64];	//full usb max length=64max
	unsigned char valid_len;	
#endif 	
	unsigned char status;	//0-init,reported ;1-reporting and wait ack;2- re-report;
	unsigned char rpt_len;
};

struct packet_STR packet[11]={ //从1开始，10个数据
	{.status =0,}, //.valid_len =0,??
	{.status =0,},
	{.status =0,},
	{.status =0,},
	{.status =0,},
	{.status =0,},
	{.status =0,},
	{.status =0,},
	{.status =0,},
	{.status =0,},
	{.status =0,},
};



#ifdef RF_5G8
/*
加载发送数据，通过usb 发送出去!!!		*/
unsigned char vote_data_packing( unsigned char pkt_seq)
{
		//专门用于usb数据上报的长buf 1024;
		unsigned char rpt_buf[USB_REPORT_MAX];	
		unsigned short i;
		unsigned short total_len;
		
//		for(i=0;i<USB_REPORT_MAX;i++)
//			rpt_buf[i] =0;	
	
		rpt_buf[0] =0xF5;	
		rpt_buf[1] =0xAA;
		rpt_buf[2] =0xAB;	
	
		rpt_buf[3]=0x00;
		rpt_buf[4]=0x07;	//length
		rpt_buf[5]=0xE0;	
		rpt_buf[6]= get_base_id();
		rpt_buf[7]=5;		
		rpt_buf[8]=pkt_seq;
		rpt_buf[9]=30;	
		rpt_buf[10]=1;	//count 
		rpt_buf[11]=0x00;

		//a,报告之前没有被确认的数据包(已经打包好的)
		if( (packet_count >= pkt_seq) &&(packet[pkt_seq].status ==2)) {
			for(i=0;i<packet[pkt_seq].count;i++)
				mem_cpy(packet[pkt_seq].data+MULTIx60(i),rpt_buf+12+MULTIx60(i),60);//mem_cpy(packet[pkt_seq].data+60*i,rpt_buf+12+60*i,60);
			
			
			rpt_buf[10]=packet[pkt_seq].count;			
			total_len = MULTIx60(packet[pkt_seq].count) + 7;//packet[pkt_seq].count*60 +7;
			rpt_buf[3]=total_len>>8;
			rpt_buf[4]=total_len;			
			
			platform.base_send_data_to_pc(rpt_buf,USB_REPORT_MAX);
			return 1;						
		}
			
		//b,
		if( queue_out(&vote_queue,rpt_buf+12,VOTE_NODE_SIZE,VOTE_DATA_SIZE) ==0 ){
			rpt_buf[8]=0xff;//pkt seq
			rpt_buf[9]=0;   //type			
			rpt_buf[10]=0; 	//count
			rpt_buf[11]=0; 
			platform.base_send_data_to_pc(rpt_buf,USB_REPORT_MAX);
			return 0;					
		}
		else{
			//保存packet的第一个键盘数据 
			mem_cpy(rpt_buf+12,packet[pkt_seq].data,60);
			packet[pkt_seq].count=1;
			
			#ifdef _DBG_VOICE_KP
				#ifdef 	KEYPAD60
				if(rpt_buf[17]!=0)
				#else
				if(rpt_buf[19]!=0)
				#endif
					_debug_voice_kp__tx_pc(rpt_buf+13);
			#endif
			
			for(i=1;i<_1PKT_NKEYPAD;i++){
				//if( queue_out(&vote_queue,rpt_buf+12+60*i,VOTE_NODE_SIZE,VOTE_DATA_SIZE)==0)break;
				if( queue_out(&vote_queue,rpt_buf+12+MULTIx60(i),VOTE_NODE_SIZE,VOTE_DATA_SIZE)==0)break;								
	
				#ifdef _DBG_VOICE_KP
					#ifdef 	KEYPAD60
					if(rpt_buf[17+MULTIx60(i)]!=0)
					#else
					if(rpt_buf[19+MULTIx60(i)]!=0)
					#endif				
						_debug_voice_kp__tx_pc(rpt_buf+13+MULTIx60(i));
				#endif	
				
				mem_cpy(rpt_buf+12+MULTIx60(i),packet[pkt_seq].data+MULTIx60(i),60);
				packet[pkt_seq].count++;												
			}//for			
			
			packet[pkt_seq].status =1;
			packet_count =pkt_seq;		
			rpt_buf[10]=packet[pkt_seq].count;
			total_len = MULTIx60(packet[pkt_seq].count)	 +7;//60*packet[pkt_seq].count +7;
			rpt_buf[3]=total_len>>8;
			rpt_buf[4]=total_len;			
						
			#ifdef  _DBG_PHYUSB_RPT_ERROR
			rpt_buf[1016]= 0xff;
			rpt_buf[1017]= kernel.re_rpt_pc_count;
			rpt_buf[1018]= kernel.re_rpt_pc_count>>8;			
			rpt_buf[1019]= packet_count;//test only
			
			rpt_buf[1020]=  kernel.keypad_online_cnt;	//debug			
			rpt_buf[1021]= 0xff;
			rpt_buf[1022]= kernel.rx_buf_overflow;		//test only	
			rpt_buf[1023]= kernel.rx_buf_overflow>>8;	
			#endif
				
			
			platform.base_send_data_to_pc(rpt_buf,USB_REPORT_MAX);
			return 1;
		}
}
#else
unsigned char pkt_cnt=0;	//#ifdef 	_RPT_PKT_CNT_ ;第60字节报告有效数据包累计数
/*
从队列中取出投票数据，到上报缓冲区packet;
*/
unsigned char vote_data_packing( unsigned char pkt_seq)
{	
		unsigned char tmp[64];		
		unsigned char type,type_len,_1pkt_keypad_cnt,rpt_type;	
		unsigned char j;//i;
	
		mem_set(tmp,sizeof(tmp)/sizeof(tmp[0]),0);
		tmp[0]=31;
		tmp[1]=0xE0;	
		tmp[2]= get_base_id();
		tmp[3]=5;		
		tmp[4]=pkt_seq;
	
		//a,报告之前没有被确认的数据包(已经打包好的)
		if( (packet_count >= pkt_seq) &&(packet[pkt_seq].status ==2)) {			
			mem_cpy(packet[pkt_seq].data,tmp+5,packet[pkt_seq].valid_len);
			#if	defined(_DBG_2G4_KP_)//new
			_debug_core__record_txpc_info_report(tmp);
			#endif		
			#ifdef	_RPT_PKT_CNT_			
			pkt_cnt++;
			tmp[60] =	pkt_cnt;	
			#endif
			tmp[0] = packet[pkt_seq].rpt_len;
			base_tx_to_pc_sub(tmp);
			return 1;						
		}
		
		//b,从队列头取出type类型并判断是否为空
//		platform.disable_interrupt();
		type =queue_out_get_type(&vote_queue,VOTE_DATA_SIZE);
//		platform.enable_interrupt();
		if( type==0){	
		//if( (type =queue_out_get_type(&vote_queue,VOTE_DATA_SIZE) ) ==0){	
			//队列为空的处理,
			tmp[4]=0xff;//pkt seq
			tmp[5]=0;   //type			
			tmp[6]=0; 	//id
			tmp[7]=0; 				
			base_tx_to_pc_sub(tmp);
			return 0;							
		}

		//c 队列不为空，由type得出相关的打包参数
		rpt_type =type;
		tmp[0] =get_packing_parameter(&rpt_type,&_1pkt_keypad_cnt,&type_len);
		
		//d,初始化打包相关参数：reset packet buf,set data TYPE,init packet len, init status.....
		mem_set(packet[pkt_seq].data,64,0);		
		packet[pkt_seq].data[0] =rpt_type;//type
		packet[pkt_seq].valid_len =1;	//len =1 is type;
		packet[pkt_seq].status =1;	
		packet_count =pkt_seq;
		
		//e,read vote buf then packing them!
		for(j=0;j<_1pkt_keypad_cnt;){		//for(i=0;i<_1pkt_keypad_cnt;i++){
			unsigned char store_buf[VOTE_DATA_SIZE];
			unsigned char out_rslt;
			j++;
			//read keypad data from VOTE buf, Notice:first bytes is data type;
//			platform.disable_interrupt();
			out_rslt =queue_out_special(&vote_queue,store_buf,VOTE_NODE_SIZE,VOTE_DATA_SIZE,type);
//			platform.enable_interrupt();	
			if( out_rslt ==1){
			//if( queue_out_special(&vote_queue,store_buf,VOTE_NODE_SIZE,VOTE_DATA_SIZE,type) ==1){
				#if	defined(_DBG_2G4_KP_)//new
				_debug_core__record_txpc_info(pkt_seq,store_buf);
				#endif
				if( rpt_type == 0x0D){/*特殊处理测验题报告状态，rpt_type后面1字节强制写1;报告长度加1*/
					packet[pkt_seq].data[packet[pkt_seq].valid_len] = 1;		//fix =1 specially!!!
					packet[pkt_seq].valid_len++;	//length+1  specially!!!
				}
				mem_cpy(store_buf+1,packet[pkt_seq].data + packet[pkt_seq].valid_len,type_len);				
				packet[pkt_seq].valid_len +=type_len;
			}
			if( (out_rslt==0) ||(j>=_1pkt_keypad_cnt) ){	//else {
				//=0 or =2 数据为空 或者type不一致;
				packet[pkt_seq].data[packet[pkt_seq].valid_len] =0xff;
				packet[pkt_seq].data[packet[pkt_seq].valid_len+1] =0xff;				
				packet[pkt_seq].valid_len +=2;
				break;
			}
		
		}//for
		
		//f, load data to report buf,then send them.
		mem_cpy(packet[pkt_seq].data,tmp+5,packet[pkt_seq].valid_len);
		packet[pkt_seq].rpt_len =tmp[0];
		#if	defined(_DBG_2G4_KP_)//new
		_debug_core__record_txpc_info_report(tmp);
		#endif
		#ifdef 	_RPT_PKT_CNT_		
		pkt_cnt++;
		tmp[60] =	pkt_cnt;
		#endif 		
		base_tx_to_pc_sub(tmp);
		return 1;		
}
#endif

//unsigned short sdk_ack_err_cnt=0;
/*
收到来自sdk的确认信标后，清除被确认的， 复位没有被确认的，准备下个周期重发 */
void vote_status_clear_confirmed(const unsigned char *rx_ack)
{
		unsigned char i,j,confirmed[10];
		unsigned char confirmed_cnt=0;
			
		//1 得到有效确认数据包个数 confirm_cnt
		for(i=0;i<10;i++){
			if( (rx_ack[i]==0)||(rx_ack[i]>10) ) break;
			confirmed[i] =rx_ack[i];
			confirmed_cnt++;
		}//for		
		if(confirmed_cnt==0) return;

//if( (confirmed_cnt==1)&&(confirmed[0] ==0x0A)){
//	sdk_ack_err_cnt++;
//	return;
//}	

		PLATFORM_DISABLE_IRQ();//platform.disable_interrupt();
		//2,设置被确认的packet[]
		for(i=0;i<confirmed_cnt;i++){
			packet[ confirmed[i] ].status =0;
			#if	defined(_DBG_2G4_KP_)//new
			_debug_core__record_pcack_info(confirmed[i]);
			#endif
		}

		if( confirmed_cnt >= packet_count)//all packet confirmed!!
			packet_count =0;
		else{
			unsigned char remain_offset=1;
			//3，检查没有被确认的packet并且按顺序排列到packet，从[1]开始;

			for(i=1;i<=packet_count;i++){
					if( packet[i].status ==0) continue;
				
					kernel.re_rpt_pc_count++; //debug only
					//a,copy data and other parameter 		
					packet[remain_offset].status =  2;				
					if(i==remain_offset){//source and dist is equl in packet[],so noneed copy 
						remain_offset++;		//2021.01.12 修复此情况下status没有置2的bug;
						continue;
					}
									
					#ifdef 	RF_5G8 
					packet[remain_offset].count = packet[i].count;					
					for(j=0;j<packet[i].count;j++) //
						mem_cpy(packet[i].data+MULTIx60(j),packet[remain_offset].data+MULTIx60(j),60);//mem_cpy(packet[i].data+60*j,packet[remain_offset].data+60*j,60);
					#else
						//b,copy packet data
						mem_cpy(packet[i].data,packet[remain_offset].data,packet[i].valid_len);
						//c,copy packet valid len
						packet[remain_offset].valid_len = packet[i].valid_len;
						packet[remain_offset].rpt_len = packet[i].rpt_len;
					#endif
					
					packet[i].status =0;//复制数据后复位状态//add by Gavin 2019.12.06					
					remain_offset++;								
			}//for
			
			packet_count -=confirmed_cnt;	//没有被确认的packet个数
		}
		PLATFORM_ENABLE_IRQ();//platform.enable_interrupt();
}


void vote_status_reset_NOconfirmed(void)
{

}




