/*******************************************************************************
版权所有：	
版本号：    1.00 
文件名：    down_panel_prog.c
生成日期： 2010-04-25
作者：      
功能说明： 下载面板程序处理
	
修改日志：  
日志1：           
修改者：    
修改日期：
修改内容：
修改原因：
****************************************************************************/
#include "head.h"

#define RECV_TIMEOUT	(USTIMER_SEC*5)

enum 
{
	SEND=1,
	RECV
};


static int g_down_flag = 0; //下载标志

struct down_program_comm g_down_program;


/**************************************************************************
函数名称：is_down_program
函数版本：1.00 
作者：   
创建日期：2015.05.15     
函数功能说明：是否正在下载程序
输入参数：
输出参数：
返回值： 返回1表示要下载程序,返回0表示没有下载程序

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/
int is_down_program(void)
{

	return g_down_flag;
}

/**************************************************************************
函数名称：init_down_program
函数版本：1.00 
作者：   
创建日期：2013.05.16     
函数功能说明：程序文件解析
输入参数：
输出参数：
返回值：

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/
int init_down_program(s32 index)
{
	u32 len;
	u16 crc;
	u8 *buf;
	char file_name[64];

	struct file * pfile;
	loff_t pos;

	sprintf(file_name,"%s%s",g_file_item[index].file_dir,g_file_item[index].file_name);

	// 打开文件
	pfile = rt_file_open(file_name,O_RDONLY ,0);

	//pfile = rt_file_open("/app/data/F308_HMI.bin",O_RDONLY ,0);
	if(IS_ERR(pfile))
	{
		return -1;
	}

	// 得到文件长度
	len = rt_file_getfile_size(pfile);
	if(len <= 0)
	{
		rt_file_close(pfile,0);
		return -11;
	}
	
	// 分配内存
	buf = rt_malloc(len);
	if((buf) == NULL)
	{
		rt_file_close(pfile,0);
		return -2; 	
	}

	// 读出内容
	pos = 0;
	if(rt_file_read(pfile,buf,len,&pos) != len)
	{
		rt_file_close(pfile,0);
		rt_free(buf);
		return -3;
	}
	// 关闭文件
	rt_file_close(pfile,0);

	// 检查CRC
	crc = CrcStr(buf+64,len-2-64);
	
#ifdef MODE_LITTLE_ENDIAN
	swap16(&crc);
#endif

	if(crc != *(u16*)(buf+len-2))
	{
		rt_printf("init_down_program:CRC=%x, %x", crc,  *(u16*)(buf+len-2));
		rt_free(buf);
		return -4;
	}
	memset(&g_down_program, 0, sizeof(g_down_program));
	g_down_program.file_name = g_file_item[index].file_name;
	g_down_program.num = len;
	if (len % (DOWN_FRAME_LEN_MAX-10) == 0)
	{
		g_down_program.framenum = len/(DOWN_FRAME_LEN_MAX-10);
	}
	else
	{
		g_down_program.framenum = len/(DOWN_FRAME_LEN_MAX-10)+1;
	}
	g_down_program.frameno = 0;
	g_down_program.probuf = buf;
	g_down_program.crc16 = crc;
	g_down_program.status = DOWN_CMD_START_DOWN;
	g_down_program.comm = SEND;

	 g_down_program.bit_prog = 1;
	g_down_program.bit_echo= 1;

	g_down_flag = 1;  //标志要下载程序

	return 0;
}


int down_program_exit(void)
{
	g_down_flag = 0;
	rt_free(g_down_program.probuf);

	return 0;
}

/**************************************************************************
函数名称：down_program_update_send
函数版本：1.00 
作者：   
创建日期：2013.05.16     
函数功能说明：子板程序更新
输入参数：
输出参数：
返回值：

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/
extern void _hmi_uart_send(void);
int down_program_update_send(u8 cmd, u16 frameno, u8 lenth, u8 *buffer)
{

	BYTE srcbuf[UART_FRAME_LEN];
	BYTE dstbuf[UART_FRAME_LEN];
	BYTE *pd=srcbuf;	
	
	*pd++=HMI_CMD_DOWN;
	*pd++=cmd;
	*pd++=(BYTE)frameno>>8;          // 帧序号
	*pd++=(BYTE)frameno;  	  // 帧序号

	memcpy(pd, buffer, lenth);


	(void)protocol_packet(srcbuf, (int)lenth+4,  MAIN_BOARD, HMI_BOARD, dstbuf);	

	//添加到缓存区
	Add_Uart_Frame(HMI_BOARD, (int)dstbuf[1] + 6, dstbuf);		

	return  0;
}


/**************************************************************************
函数名称：Is_down_program_Frame
函数版本：1.00 
作者：   
创建日期：2008.8.20    
函数功能说明：判断是否是下载命令码
输入参数：
输出参数：无
返回值： 成功时返回1，否则，0
函数扇入清单：
***************************************************************************/
static bool Is_down_program_Frame(BYTE cmd)
{

	if(cmd==DOWN_CMD_START_DOWN)	return true;
	if(cmd==DOWN_CMD_ERASE_FLASH)		return true;
	if(cmd==DOWN_CMD_WRITE_DATA)		return true;
	if(cmd==DOWN_CMD_READ_DATA)		return true;
	if(cmd==DOWN_CMD_RUN_PROG)		return true;


	return false;
}

int down_program_recv_timeout(void)
{

	// 超时处理
	if(ustimer_get_duration(g_down_program.us_recv) > RECV_TIMEOUT && g_down_program.comm == RECV)
	{
		//rt_printf("program_check_period timeout:bit_prog=0x%08x,bit_echo=0x%08x.\r\n",g_program.bit_prog,g_program.bit_echo);

		#if 0
		if(g_down_program.bit_echo == 0)
		{
			// TODO:
			rt_printf("下载终止!\r\n");
			g_program.bit_prog = 0;
			g_program.bit_echo = 0;
			
			g_program.comm = 0;
			g_prog_up.bit_echo = g_program.bit_echo;
			rt_file_del("/tmp/DTU-DIDO.elf.bin");
			down_exit();
			return -1;
		}
		#endif

		//g_down_program.bit_prog = g_down_program.bit_echo;
		//g_down_program.bit_echo = 0;
		rt_file_del("/tmp/F308_HMI.bin");
		down_program_exit();
		g_down_program.comm = SEND;

	}

	return 0;
}

int down_program_recv(u8 *buf)
{
	int recvok;

	g_down_program.us_recv = ustimer_get_origin();

	recvok = false;
	if(Is_down_program_Frame(buf[5]))
	{
		u8 *p=&buf[5];
		if(g_down_program.status ==p[0]&& p[1] == DOWN_CMD_OK)
		{
			recvok = true;	
		}
	}


	
	if (g_down_program.comm == RECV && recvok)
	{	
		//g_program.bit_echo |= 1<<cfh->src;
		//if((g_down_program.bit_echo&g_program.bit_prog) != g_program.bit_prog)
		//{
		//	return 0;
		//}
		
		// 接收完成，进行状态转换
		switch (g_down_program.status)
		{
			case DOWN_CMD_START_DOWN://启动下载
				g_down_program.status = DOWN_CMD_ERASE_FLASH;
				break;
				
			case DOWN_CMD_ERASE_FLASH: //擦除flash
				g_down_program.status = DOWN_CMD_WRITE_DATA;
				break;

			case DOWN_CMD_WRITE_DATA:
				if(g_down_program.frameno == g_down_program.framenum)
				{
					g_down_program.status = DOWN_CMD_RUN_PROG;

				}
				//g_prog_up.frameno = g_program.frameno;
				//g_prog_up.bit_echo = g_program.bit_echo;
				break;
				
			case DOWN_CMD_RUN_PROG:	//启动程序
				break;

			case DOWN_CMD_READ_DATA: //读设备信息
			//	g_program.status = ErsFSH;
				break;
			default:
				break;
 		}

 		

		// 重新进入发送状态
		//g_program.bit_echo = 0;
		g_down_program.comm = SEND;
		
 	}
	
	return 0;
}



/**************************************************************************
函数名称：down_program_send
函数版本：1.00 
作者：   
创建日期：2013.05.18    
函数功能说明：程序上传、下载
输入参数：
输出参数：无
返回值： 成功时返回1，否则，0
函数扇入清单：
***************************************************************************/
int down_program_send (void)
{
	if (g_down_program.comm == SEND)
	{		
		g_down_program.comm = RECV;
		g_down_program.us_recv = ustimer_get_origin();
		switch (g_down_program.status)
		{
			case DOWN_CMD_START_DOWN://启动下载
			case DOWN_CMD_RUN_PROG:	//启动程序
			{
				u8 buf[20]={0};
				strcpy(buf, g_down_program.file_name);
				//memcpy(buf, g_down_program.file_name, 16);
				//memcpy(buf+16,&g_down_program.bit_prog,4);
				down_program_update_send(g_down_program.status, 0, 20, buf);
				if (g_down_program.status == DOWN_CMD_RUN_PROG)
				{	
					g_down_program.status = 0;
					g_down_program.comm = 0;
					down_program_exit();
				}
				break;
			}

			case DOWN_CMD_ERASE_FLASH: //擦除flash
			{
				u8 len[8];
				u8 i;
				
				for (i=0; i<4; i++)
				{
					len[3-i] =g_down_program.num>>(i*8);					
				}
					
				down_program_update_send( g_down_program.status, 0, 4, len);			
				break;
			}

			case DOWN_CMD_WRITE_DATA:
			{
				u8 buf[DOWN_FRAME_LEN_MAX];
				u8 lenth;
				
				//rt_printf("frameno = %d,framenum = %d\r\n", g_down_program.frameno,g_down_program.framenum);
				if(g_down_program.frameno == g_down_program.framenum)
				{
					g_down_program.status = DOWN_CMD_RUN_PROG;
					break;
				}
				else if (g_down_program.frameno < (g_down_program.framenum-1))
				{
					lenth = DOWN_FRAME_LEN_MAX-10;
				}
				else
				{
					lenth = g_down_program.num - g_down_program.frameno*(DOWN_FRAME_LEN_MAX-10);
				}
				memcpy(&buf[0], g_down_program.probuf+g_down_program.frameno*(DOWN_FRAME_LEN_MAX-10), lenth);
				down_program_update_send(g_down_program.status, g_down_program.frameno, lenth, buf);
				
				g_down_program.frameno++;
				
				break;
			}

			case DOWN_CMD_READ_DATA://读数据
			{
				break;
			}
		}
		
	}
	
	return 0;
}

void down_program_task(void)
{
		
}

