/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"

#if USE_FATFS_RECORD

#include "dev_spi_sdcard.h"
#include "func_spi_w25qxx.h"
#include "func_fatfs.h"
#include "func_fatfs_record.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/


/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/

/* USER CODE BEGIN PFP */

FATFS fileSystem;
FIL 	testFile;
uint8_t testBuffer[16] = "SD write success";


char 		fatfs_buf[4*1024];

#if  USE_SPI_SD
const char FATFS_Path[4] = "0:/"; 					//挂载SD卡 
#else
const char FATFS_Path[4] ;//= "1:/"; 					//挂载FLASH.
#endif
char readnrf,reafsd;

/* USER CODE END PFP */


void 	func_fatfs_Get_Capacity(void);
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */
/**
  * @brief  The application entry point.
  * @retval int
  */
int func_fatfs_init(void)
{
	FRESULT res;
	 
	uint8_t format_disk = 0;

  /* Initialize all configured peripherals */
	
  FATFS_Init();

	//res = f_mkfs ( FATFS_Path, FM_ANY, 0, fatfs_buf, sizeof(fatfs_buf));
  /* USER CODE BEGIN 2 */
	res = f_mount(&fileSystem, (const TCHAR*)FATFS_Path, 1);
	
  if(res != FR_OK)
  {
			func_record_fatfs_set_OK(false);
	}
	if(res == FR_NO_FILESYSTEM)//FLASH磁盘,FAT文件系统错误,重新格式化FLASH
	{
//		
		while(res != FR_OK)
		{
			if(format_disk)
			{
				func_w25q_erase_ship();
				format_disk = 0;
			}
			
			if(format_disk)
			{
				res = f_mkfs (FATFS_Path, FM_ANY, 0, fatfs_buf, sizeof(fatfs_buf));
				format_disk = 0;
			}
			
			res = f_mount(&fileSystem, (const TCHAR*)FATFS_Path, 1);
		};
		
	}	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
 
  /* USER CODE END 3 */
	return res;
}

/**
  * @brief  The application entry point.
  * @retval int
  */
int func_fatfs_main(void)
{
  /* USER CODE BEGIN 1 */
	
	//func_fatfs_Get_Capacity();

  /* USER CODE END 1 */
	
	return 0;
 
}


typedef struct fatfs_st
{
	DWORD 		TotalSpace;	
	DWORD 		AvailableSize;
	DWORD 		UsedSize;
}fatfs_st;

fatfs_st fatfs_run_st;

void func_fatfs_Capacity(void)
{
		FATFS *hFatfs = &fileSystem;
	
		fatfs_run_st.TotalSpace=((hFatfs->n_fatent - 2) * hFatfs->ssize *hFatfs->csize)/1024;
		fatfs_run_st.AvailableSize=(hFatfs->free_clst*hFatfs->ssize*hFatfs->csize)/1024;
		fatfs_run_st.UsedSize=fatfs_run_st.TotalSpace-fatfs_run_st.AvailableSize;  
} 

uint32_t func_fatfs_get_free(void)
{
	return (fileSystem.free_clst*fileSystem.ssize*fileSystem.csize)/1024;
}


void func_fatfs_Get_Capacity(void)
{
//	FRESULT result;
//	FATFS FS;
	FATFS *fs;
	DWORD fre_clust;	

	FRESULT res;
	
	res = f_getfree(FATFS_Path, &fre_clust, &fs);  /* 根目录 */
	if ( res == FR_OK ) 
	{
		fatfs_run_st.TotalSpace=(fs->n_fatent - 2);
		fatfs_run_st.AvailableSize=fre_clust;
		fatfs_run_st.UsedSize=fatfs_run_st.TotalSpace-fatfs_run_st.AvailableSize;              
		/* Print free space in unit of MB (assuming 512 bytes/sector) */
//		printf("\r\n%d MB total drive space.\r\n""%d MB available.\r\n""%d MB  used.\r\n",TotalSpace, AvailableSize,UsedSize);
	}
	else 
	{
//		printf("Get SDCard Capacity Failed (%d)\r\n", result);
	}	
	return;
} 

void func_fatfs_Get_Capacity_Sample(void)
{
//	FRESULT result;
//	FATFS FS;
	FATFS *fs;
	DWORD fre_clust;	

	FRESULT res;
	
	res = f_getfree(FATFS_Path, &fre_clust, &fs);  /* 根目录 */
	if ( res == FR_OK ) 
	{
		fatfs_run_st.TotalSpace=(uint16_t)(((fs->n_fatent - 2) * fs->csize ) / 2 /1024);
		fatfs_run_st.AvailableSize=(uint16_t)((fre_clust * fs->csize) / 2 /1024);
		fatfs_run_st.UsedSize=fatfs_run_st.TotalSpace-fatfs_run_st.AvailableSize;              
		/* Print free space in unit of MB (assuming 512 bytes/sector) */
//		printf("\r\n%d MB total drive space.\r\n""%d MB available.\r\n""%d MB  used.\r\n",TotalSpace, AvailableSize,UsedSize);
	}
	else 
	{
//		printf("Get SDCard Capacity Failed (%d)\r\n", result);
	}	
	return;
} 

FIL file;													/* 文件对象 */
/* FatFs多项功能测试 */
FRESULT func_fatfs_miscellaneous(void)
{
	FRESULT f_res;                    /* 文件操作结果 */
	UINT fnum;            					  /* 文件成功读写数量 */

	DIR dir;
  FATFS *pfs;
  DWORD fre_clust, fre_sect, tot_sect;
  
  printf("\n*************** 设备信息获取 ***************\r\n");
  /* 获取设备信息和空簇大小 */
  f_res = f_getfree((TCHAR const*)FATFS_Path, &fre_clust, &pfs);

  /* 计算得到总的扇区个数和空扇区个数 */
  tot_sect = (pfs->n_fatent - 2) * pfs->csize;
  fre_sect = fre_clust * pfs->csize;

  /* 打印信息(4096 字节/扇区) */
  printf("》设备总空间：%10lu KB。\n》可用空间：  %10lu KB。\n", tot_sect *4, fre_sect *4);
  
  printf("\n******** 文件定位和格式化写入功能测试 ********\r\n");
  f_res = f_open(&file, "FatFs读写测试文件.txt",
                            FA_OPEN_EXISTING|FA_WRITE|FA_READ );
	if ( f_res == FR_OK )
	{
    /*  文件定位 */
    f_res = f_lseek(&file,f_size(&file)-1);
    if (f_res == FR_OK)
    {
      /* 格式化写入，参数格式类似printf函数 */
      f_printf(&file,"\n在原来文件新添加一行内容\n");
      f_printf(&file,"》设备总空间：%10lu KB。\n》可用空间：  %10lu KB。\n", tot_sect *4, fre_sect *4);
      /*  文件定位到文件起始位置 */
      f_res = f_lseek(&file,0);
      /* 读取文件所有内容到缓存区 */
      f_res = f_read(&file,fatfs_buf,f_size(&file),&fnum);
      if(f_res == FR_OK)
      {
        printf("》文件内容：\n%s\n",fatfs_buf);
      }
    }
    f_close(&file);    
    
    printf("\n********** 目录创建和重命名功能测试 **********\r\n");
    /* 尝试打开目录 */
    f_res=f_opendir(&dir,"TestDir");
    if(f_res!=FR_OK)
    {
      /* 打开目录失败，就创建目录 */
      f_res=f_mkdir("TestDir");
    }
    else
    {
      /* 如果目录已经存在，关闭它 */
      f_res=f_closedir(&dir);
      /* 删除文件 */
      f_unlink("TestDir/testdir.txt");
    }
    if(f_res==FR_OK)
    {
      /* 重命名并移动文件 */
      f_res=f_rename("FatFs读写测试文件.txt","TestDir/testdir.txt");      
    } 
	}
  else
  {
    printf("!! 打开文件失败：%d\n",f_res);
    printf("!! 或许需要再次运行“FatFs移植与读写测试”工程\n");
  }
  return f_res;
}


/**
  * 文件信息获取
  */
FRESULT func_fatfs_file_check(void)
{ 
	FRESULT f_res;                    /* 文件操作结果 */	
  static FILINFO finfo;
  /* 获取文件信息 */
  f_res=f_stat("TestDir/testdir.txt",&finfo);
  if(f_res==FR_OK)
  {
    printf("“testdir.txt”文件信息：\n");
    printf("》文件大小: %ld(字节)\n", finfo.fsize);
    printf("》时间戳: %u/%02u/%02u, %02u:%02u\n",
           (finfo.fdate >> 9) + 1980, finfo.fdate >> 5 & 15, finfo.fdate & 31,finfo.ftime >> 11, finfo.ftime >> 5 & 63);
    printf("》属性: %c%c%c%c%c\n\n",
           (finfo.fattrib & AM_DIR) ? 'D' : '-',      // 是一个目录
           (finfo.fattrib & AM_RDO) ? 'R' : '-',      // 只读文件
           (finfo.fattrib & AM_HID) ? 'H' : '-',      // 隐藏文件
           (finfo.fattrib & AM_SYS) ? 'S' : '-',      // 系统文件
           (finfo.fattrib & AM_ARC) ? 'A' : '-');     // 档案文件
  }
  return f_res;
}

/**
  * @brief  scan_files 递归扫描FatFs内的文件
  * @param  path:初始扫描路径
  * @retval result:文件系统的返回值
  */
FRESULT func_fatfs_scan_files (char* path) 
{ 
  FRESULT res; 		//部分在递归过程被修改的变量，不用全局变量	
  FILINFO fno; 
	DIR 		dir;	
  int i;            
  char *fn;        // 文件名	
	
#if _USE_LFN 
  /* 长文件名支持 */
  /* 简体中文需要2个字节保存一个“字”*/
  static char lfn[_MAX_LFN*2 + 1]; 	
  fno.fname = lfn; 
  fno.fsize = sizeof(lfn); 
#endif 
  //打开目录
  res = f_opendir(&dir, path); 
  if (res == FR_OK) 
	{ 
    i = strlen(path); 
    for (;;) 
		{ 
      //读取目录下的内容，再读会自动读下一个文件
      res = f_readdir(&dir, &fno); 								
      //为空时表示所有项目读取完毕，跳出
      if (res != FR_OK || fno.fname[0] == 0) break; 	
#if _USE_LFN 
      fn = *fno.lfname ? fno.lfname : fno.fname; 
#else 
      fn = fno.fname; 
#endif 
      //点表示当前目录，跳过			
      if (*fn == '.') continue; 	
      //目录，递归读取      
      if (fno.fattrib & AM_DIR)         
			{ 			
        //合成完整目录名        
        sprintf(&path[i], "/%s", fn); 		
        //递归遍历         
        res = func_fatfs_scan_files(path);	
        path[i] = 0;         
        //打开失败，跳出循环        
        if (res != FR_OK) 
					break;			
      } 
			else 
			{ 
				printf("%s/%s\n", path, fn);								//输出文件名	
        /* 可以在这里提取特定格式的文件路径 */        
      }//else
    } //for
  } 
  return res; 
}


/*------------------------------------------------------
 读取指定目录下所有的文件
 说明:
  f_readdir    按顺序读取目录内文件，
 重复调用此函数可读取目录内所有文件；
---------------------------------------------------------*/
void func_fatfs_ReadDirTest(char*path)
{
// FRESULT res; /* FatFs 函数通用结果代码 */
		DIR 		dir;	
	  FILINFO fno; 
#if _USE_LFN//如果使能支持长文件名 先对下面两项初始化
    fileinfo.lfsize=_MAX_LFN * 2 + 1;//
    fileinfo.lfname=(TCHAR*)FileName;//
#endif
    if(f_opendir(&dir,(const char*)path) == FR_OK)/* 打开文件夹目录成功，目录信息已经在dir结构体中保存 */
    {
        while(f_readdir(&dir, &fno) == FR_OK)  /* 读文件信息到文件状态结构体中 */
        {
            if(!fno.fname[0]) break; /* 如果文件名为‘\0'，说明读取完成结束 */
            printf("%s/",path);//打印路径
#if _USE_LFN
            printf("文件名：%s\r\n",fileinfo.lfname );//打印信息到串口
#else
            printf("文件名：%s\r\n", fno.fname);//
#endif
        }
    }
}


char*  pstr = 0;
char*  pidx = 0;
void func_record_fatfs_str(void)
{
	char  str_name[] ="20221112.TXT" ;

	while(1)
	{
		pstr =  strstr(str_name,FILE_START);
		
		pidx =  strstr(str_name,FILE_END);
		UNUSED(pstr);
		UNUSED(pidx);
	}
}

#if 0
static int qsort_cmp(const void *a,const void *b)
{
    return strcmp(( char * ) a, (const char* )b);
}
#define MAX_FILE_COUNT 20
char fileList[MAX_FILE_COUNT][30];//保存文件名
void func_fatfs_dir_qsort(uint32_t fcount)
{
	qsort(fileList, fcount, sizeof(fileList[0]), qsort_cmp);
}
#endif

#endif //--------------------------USE_FATFS_RECORD------------------------------
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
