#include "common.h"
#include "flash.h"
#include "stdio.h"
#include "stdlib.h"
#include "ff.h"
#include "integer.h"
#include "diskio.h"
//#include "stm32_eval.h"
#include "string.h"

void edit_file(void)
{
	FATFS fs;
	FIL	file;
	FRESULT res; 
	DIR dirs;
	FILINFO finfo;
	char key = 0;
	char path[20];

	uint32_t index = 0x00;
	uint32_t reindex = 0x00;
	uint8_t file_buff[512] = {0};

	uint32_t files_num = 0;
	uint8_t length = 0;
	res = f_mount(0,&fs);
	if (res != FR_OK)
	{
		printf("\r\n挂载文件系统失败,错误代码: %u",res);
		return;
	}
	res = f_opendir(&dirs,"/");
	printf("\r\n------------文件列表------------");
	if (res == FR_OK) 
	{
		while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.fname[0]) 
		{
			if (finfo.fattrib & AM_DIR)//如果是文件夹 
			{ 
				continue;
			} 
			else 
			{   
				files_num++;
				//显示文件名,显示文件实际大小 ,文件实际大小采用四舍五入法
				printf("\r\n/%12s%7ld KB ",  &finfo.fname[0],(finfo.fsize+512)/1024);
			}
		}
		if( files_num == 0 )//无文件
		{
			printf("\r\n无文件!");    
		}
	}
	else
	{
		printf("\r\n打开根目录失败!");
		printf("\r\n错误代码: %u",res);
	}
	printf("\r\n输入要编辑文件全名,以回车结束...");
	get_file_name((uint8_t *)path,length,FI);
	res = f_open(&file,path,FA_READ | FA_WRITE);
	if (res == FR_OK)
	{	
		printf("\r\n打开文件 %s 成功",path);
		printf("\r\n现在是文件编辑状态,请输入要写入的数据!");		
		printf("\r\n按ESC或者Ctrl+C结束编辑!\r\n");
		
		while(1)
		{
			key = GetKey();
			if ((key == 0x1B) && (index == 0x00))//key ESC
			{
				printf("\r\n数据还没有输入,现在处于编辑模式...");								
				continue;
			}
			else if ((key == 0x1B))	//key ESC
			{
				printf("\r\n保存数据...");
				res = f_write(&file,file_buff,index,&reindex);
				if ((res == FR_OK) && (reindex == index))
				{
					printf("\r\n保存数据成功!");
					f_close(&file);
					index = 0x00;
					reindex = 0x00;									
				}
				else
				{
					printf("\r\n保存数据失败!");
					printf("\r\n错误代码: %u",res);									
				}
				break;
			}
			else if (key == 0x03) //key Ctrl+C
			{
				printf("\r\n结束文件编辑!");
				printf("\r\n保存数据...");
				res = f_write(&file,file_buff,index,&reindex);
				if ((res == FR_OK) && (reindex == index))
				{
					printf("\r\n保存数据成功!");
					f_close(&file);
					index = 0x00;
					reindex = 0x00;									
				}
				else
				{
					printf("\r\n保存数据失败!");
					printf("\r\n错误代码: %u",res);									
				}
				break;
			}
			else if ((key < 0x21) || (key > 0x80))
			{
				continue;
			}
			else
			{
				file_buff[index++] = key;
				printf("%c",key);
				if (index > 512)
				{
					index = 0x00;
				}
			}
		}
	}
	else
	{
		printf("\r\n打开文件失败,错误代码: %u",res);
	}
}
void read_file(void)
{

	FATFS fs;
	FIL	file;
	FRESULT res; 
	DIR dirs;
	FILINFO finfo;
	char path[20];
	char buffer[512] = {0};
	uint32_t i;
	uint8_t length=0;
	uint32_t re,files_num = 0;
	res = f_mount(0,&fs);
	if (res != FR_OK)
	{
		printf("\r\n挂载文件系统失败,错误代码: %u",res);
		return;
	}
	res = f_opendir(&dirs,"/");
	if (res == FR_OK) 
	{
		//i = strlen(path);
		printf("\r\n-----------文件列表-------");
		while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.fname[0]) 
		{
			if (finfo.fattrib & AM_DIR)//如果是文件夹 
			{ 
				continue;
			} 
			else 
			{   
				files_num++;
				//显示文件名,显示文件实际大小 ,文件实际大小采用四舍五入法
				printf("\r\n/%12s%7ld KB ",  &finfo.fname[0],(finfo.fsize+512)/1024);
 			}
		}
		if( files_num == 0 )//无文件
		{
			printf("\r\n无文件,请返回先创建文件!");
			return;
		}
	}
	else
	{
		printf("\r\n打开根目录失败!");
		printf("\r\n错误代码: %u",res);
	}
	printf("\r\n输入文件全名,以回车结束...");
	get_file_name((uint8_t *)path,length,FI);
	res = f_open(&file,path,FA_READ);
	printf("\r\n正在打开文件,以下是文件数据:\r\n");

	if (res == FR_OK)
	{
		while (1)
		{
			for(i = 0;i < 512;i++)
			{
				buffer[i] = 0x00;
			}
			res = f_read(&file,buffer,512,&re);
			printf("%s",buffer);

			if (res || re == 0)
			{
				printf("\r\n文件读取结束,关闭文件!");
				f_close(&file);
				break;  
			}	
		}
	}
	f_mount(0,NULL);
}

void creat_dir(void)
{
	FATFS fs;        
	FRESULT res;     
	char path[20];
	uint8_t length=0;
	res = f_mount(0,&fs);
	if (res != FR_OK)
	{
		printf("\r\n挂载文件系统失败,错误代码: %u",res);
		return;
	}	
	printf("\r\n请输入文件夹名,回车确认...格式 8 + 3...");
	get_file_name((uint8_t *)path,length,DI);
	res = f_mkdir(path);
	if (res == FR_OK)
	{
		printf("\r\n创建文件目录成功!");
	}
	else
	{
		printf("\r\n创建目录失败...");
		printf("\r\n错误代码: %u",res);
	}
	f_mount(0,NULL);
}


void get_file_name(uint8_t *file_name,uint8_t length,uint8_t type)
{
	uint8_t key;
	uint8_t name_leng = 0;
	printf("\r\n");
	
	while (1)
	{
		key = GetKey();
		if ((key == 13) && (name_leng == 0))
		{
			printf("\r\n");
			continue;
		}
		else if ((key == 0x2F) || (key == 0x5C))
		{
			printf("%c",key);
			continue;
		}
		else if ((key == 13) && (name_leng > 0))
		{
			printf("\r\n");
			if (type == FI)
			{
				if (check_file_name(file_name,name_leng) == 0)
				{
					break;
				}
			}
			else
			{
				break;
			}			
			
		}
		else
		{
			printf("%c",key);
			file_name[name_leng] = key;
			name_leng++;
			if (name_leng > 12)
			{
				printf("\r\n文件名格式: 8 + 3，只支持8个字符,3个扩展名!");
				printf("\r\n请重新输入...");
				name_leng = 0;
				continue;
			}
		}
	}
}
void format_disk(void)
{
	FATFS fs;
	uint8_t res;
	res = f_mount(0,&fs);
	if (res != FR_OK)
	{
		printf("\r\n挂载文件系统失败,错误代码: %u",res);
		return;
	}	
	printf("\r\n正在格式化磁盘,请稍候...");

	res = f_mkfs(0,1,4096);
	if (res == FR_OK)
	{
		printf("\r\n格式化成功...");
	}
	else
	{
		printf("\r\n格式化失败...");
		printf("\r\n错误代码: %u\r\n",res);
	}
	f_mount(0,NULL);
}
void creat_file(void)
{
	FIL file;
	FIL *pf = &file;
	FATFS fs;
	uint8_t res;
	uint8_t name[16] = {0};
	uint8_t length = 0;
	printf("\r\n请输入文件名,回车确认...格式 8 + 3...");
	printf("\r\n例:123.dat\r\n");
	get_file_name(name,length,FI);	
	res = f_mount(0,&fs);		                           /* Mount a Logical Drive 0 */
	if (res != FR_OK)
	{
		printf("\r\n挂载文件系统失败,错误代码: %u",res);
		return;
	}	
	res = f_open(pf,(TCHAR *)name,FA_READ | FA_WRITE | FA_CREATE_NEW);
	if (res == FR_OK)
	{
		printf("\r\n创建文件成功!");
		res = f_close(pf);
		if (res != FR_OK)
		{
			printf("\r\n创建文件成功,但关闭文件时,失败!");
			printf("\r\n错误代码: %u",res);				
		}				
	}
	else
	{
		printf("\r\n创建文件失败!");
		printf("\r\n错误代码: %u",res);	
	}
	f_mount(0,NULL);
}
void delete_file(void)
{
	FATFS fs;
	FRESULT res;
	DIR dirs;
	FILINFO finfo;
	uint8_t name[16] = {0};
	uint8_t length = 0;
	uint32_t files_num = 0;

	res = f_mount(0,&fs);		      /* Mount a Logical Drive 0*/	 
	if (res != FR_OK)
	{
		printf("\r\n挂载文件系统失败,错误代码: %u",res);
		return;
	}

	res = f_opendir(&dirs,"/");		 /* Create a Directroy Object */
	if (res == FR_OK) 
	{
		printf("\r\n-----------文件列表-------");
		while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.fname[0]) 
		{
			if (finfo.fattrib & AM_DIR)//如果是文件夹 
			{ 
				continue;
			} 
			else 
			{   
				files_num++;
				//显示文件名,显示文件实际大小 ,文件实际大小采用四舍五入法
				printf("\r\n/%12s%7ld KB ",  &finfo.fname[0],(finfo.fsize+512)/1024);
 			}
		}
		if( files_num == 0 )//无文件
		{
			printf("\r\n无文件,请返回先创建文件!");
			return;
		}
	}

	get_file_name(name,length,FI);    /* Get file name */
	
	res = f_unlink((TCHAR *)name);	  /* Delete a File or Directory */

	if (res == FR_OK)
	{
		printf("\r\n删除文件成功!");
	}
	else if (res == FR_NO_FILE)
	{
		printf("\r\n找不到文件或目录!");
	}
	else if (res == FR_NO_PATH)
	{
		printf("\r\n找不到路径!");
	}
	else
	{
		printf("\r\n错误代码: %u",res);
	}
	f_mount(0,NULL);
}
void list_file(void)
{
	FATFS fs;
	FILINFO finfo;
	FRESULT res;
	DIR dirs;
	int i;
	int files_num=0;
	res = f_mount(0,&fs);
	if (res != FR_OK)
	{
		printf("\r\n挂载文件系统失败,错误代码: %u",res);
		return;
	}	
	res = f_opendir(&dirs,"/");							/* Create a Directroy Object */
	printf("\r\n------------文件列表------------");
	if (res == FR_OK)
	{
		while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.fname[0]) 	 /* Read Directory Entry in Sequense*/
		{
			i = strlen(finfo.fname);
			if (finfo.fattrib & AM_DIR)//如果是文件夹 
			{
				files_num++;
				printf("\r\n/%s", &finfo.fname[0]);
				switch(i)//作用：输出文件名左对齐
				{
				case 1:printf(" ");
				case 2:printf(" ");
				case 3:printf(" ");
				case 4:printf(" ");
				case 5:printf(" ");
				case 6:printf(" ");
				case 7:printf(" ");
				case 8:printf("%15s"," ");
				}	
			} 
			else 
			{
				continue;
			}	
		}
	}
	else
	{
		printf("\r\n打开根目录失败!");
		printf("\r\n错误代码: %u",res);
	}
	res = f_opendir(&dirs, "/");
	if (res == FR_OK) 
	{
		while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.fname[0]) 
		{
			if (finfo.fattrib & AM_DIR) 
			{ 
				continue;
			} 
			else 
			{   
				files_num++;				
				printf("\r\n/.%12s%7ld KB ",  &finfo.fname[0],(finfo.fsize+512)/1024);				
			}
		}
		if( files_num==0 )//无文件
		{
			printf("\r\n无文件!");    
		}
	}
	else
	{
		printf("\r\n打开根目录失败!");
		printf("\r\n错误代码: %u",res);
	}
	f_mount(0,NULL);

}
void get_disk_info(void)
{
	FATFS fs;
	FATFS *fls = &fs;
	FRESULT res;
	DWORD fre_clust;	
	
	res = f_mount(0,&fs);						 /* Mount a Logical Drive 0 */
	if (res != FR_OK)
	{
		printf("\r\n挂载文件系统失败,错误代码: %u",res);
		return;
	}	

	res = f_getfree("/",&fre_clust,&fls);		 /* Get Number of Free Clusters */
	if (res == FR_OK) 
	{
	                                             /* Print free space in unit of MB (assuming 4096 bytes/sector) */
        printf("\r\n%d KB Total Drive Space.\r\n"
               "%d KB Available Space.\r\n",
               ((fls->n_fatent-2)*fls->csize)*4,(fre_clust*fls->csize)*4);
	}
	else
	{
		printf("\r\n获得磁盘信息失败!");
		printf("\r\n错误代码: %u",res);
	}																									   
	f_mount(0,NULL);						     /*Unmount a Logical Drive 0 */ 
}
uint8_t check_file_name(uint8_t *file_name,uint8_t length)
{
	uint8_t res;
	if (length > 13)
	{
		res = 1;
	}
	else
	{
		if (file_name[length - 4] == '.')
		{
			res = 0;
		}
		else
		{
			res = 2;
		}
	}
	return res;

}

void SerialPutChar(uint8_t c)
{
	USART_SendData(USART1, c);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

void Serial_PutString(uint8_t *s)
{
	while (*s != '\0')
	{
		SerialPutChar(*s);
		s ++;
	}
}

/**
  * @brief  Test to see if a key has been pressed on the HyperTerminal
  * @param  key: The key pressed
  * @retval 1: Correct
  *         0: Error
  */
uint32_t SerialKeyPressed(uint8_t *key)
{

  if ( USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
  {
    *key = (uint8_t)USART1->DR;
    return 1;
  }
  else
  {
    return 0;
  }
}
/**
  * @brief  Get a key from the HyperTerminal
  * @param  None
  * @retval The Key Pressed
  */
uint8_t GetKey(void)
{
  uint8_t key = 0;

  /* Waiting for user input */
  while (1)
  {
    if (SerialKeyPressed((uint8_t*)&key)) break;
  }
  return key;

}
void Sys_Soft_Reset(void)
{   
	SCB->AIRCR =0X05FA0000|(u32)0x04;	  
}

#if 0
void GPIO_KEY_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure KEY1 Button */
  RCC_APB2PeriphClockCmd(RCC_KEY1, ENABLE);

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_InitStructure.GPIO_Pin = GPIO_KEY1;
  GPIO_Init(GPIO_KEY1_PORT, &GPIO_InitStructure);

  /* Configure KEY2 Button */
  RCC_APB2PeriphClockCmd(RCC_KEY2, ENABLE);

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_InitStructure.GPIO_Pin = GPIO_KEY2;
  GPIO_Init(GPIO_KEY2_PORT, &GPIO_InitStructure);

  /* Configure KEY3 Button */
  RCC_APB2PeriphClockCmd(RCC_KEY3, ENABLE);

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_InitStructure.GPIO_Pin = GPIO_KEY3;
  GPIO_Init(GPIO_KEY3_PORT, &GPIO_InitStructure);  

  /* Configure KEY4 Button */
  RCC_APB2PeriphClockCmd(RCC_KEY4, ENABLE);

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_InitStructure.GPIO_Pin = GPIO_KEY4;
  GPIO_Init(GPIO_KEY4_PORT, &GPIO_InitStructure);

}

void USART1_Init(void)
{
  USART_InitTypeDef USART_InitStructure;
  /* USARTx configured as follow:
        - BaudRate = 115200 baud  
        - Word Length = 8 Bits
        - One Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
  */
  USART_InitStructure.USART_BaudRate = 115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  STM_EVAL_COMInit(COM1, &USART_InitStructure);

}
#endif

int fputc(int ch, FILE *f)
{
   USART_SendData(USART1, (u8) ch);
   while(!(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == SET))
   {
   }
   return ch;
}

int fgetc(FILE *f)
{
   while(!(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET))
   {
   }
   return (USART_ReceiveData(USART1));
}

