#include "fattester.h"	 
#include "sd_card.h"
#include "usart.h"
#include "exfuns.h"
#include "malloc.h"		  
#include "ff.h"
#include "string.h"


/*********************************************************************************
			  ___   _     _____  _____  _   _  _____  _____  _   __
			 / _ \ | |   |_   _||  ___|| \ | ||_   _||  ___|| | / /
			/ /_\ \| |     | |  | |__  |  \| |  | |  | |__  | |/ /
			|  _  || |     | |  |  __| | . ` |  | |  |  __| |    \
			| | | || |_____| |_ | |___ | |\  |  | |  | |___ | |\  \
			\_| |_/\_____/\___/ \____/ \_| \_/  \_/  \____/ \_| \_/

 *	******************************************************************************
 *	本程序只供学习使用，未经作者许可，不得用于其它任何用途
 *	ALIENTEK Pandora STM32L475 IOT开发板
 *	FATFS 测试代码
 *	正点原子@ALIENTEK
 *	技术论坛:www.openedv.com
 *	创建日期:2018/10/27
 *	版本：V1.0
 *	版权所有，盗版必究。
 *	Copyright(C) 广州市星翼电子科技有限公司 2014-2024
 *	All rights reserved
 *	******************************************************************************
 *	初始版本
 *	******************************************************************************/


/**
 * @brief	为磁盘注册工作区
 *
 * @param   path	磁盘路径，比如"0:"、"1:"
 * @param   mt		0，不立即注册（稍后注册）；1，立即注册
 *
 * @return  u8		执行结果
 */
u8 mf_mount(u8* path,u8 mt)
{		   
	return f_mount(fs[1],(const TCHAR*)path,mt); 
}

/**
 * @brief	打开路径下的文件
 *
 * @param   path	路径+文件名
 * @param   mode	打开模式
 *
 * @return  u8		执行结果
 */
u8 mf_open(u8*path,u8 mode)
{
	u8 res;	 
	res=f_open(file,(const TCHAR*)path,mode);//打开文件夹
	return res;
}

/**
 * @brief	关闭文件
 *
 * @param   void
 *
 * @return  u8		执行结果
 */
u8 mf_close(void)
{
	f_close(file);
	return 0;
}

/**
 * @brief	读出数据
 *
 * @param   len		读出的长度
 *
 * @return  u8		执行结果
 */
u8 mf_read(u16 len)
{
	u16 i,t;
	u8 res=0;
	u16 tlen=0;
	printf("\r\nRead file data is:\r\n");
	for(i=0;i<len/512;i++)
	{
		res=f_read(file,fatbuf,512,&br);
		if(res)
		{
			printf("Read Error:%d\r\n",res);
			break;
		}else
		{
			tlen+=br;
			for(t=0;t<br;t++)printf("%c",fatbuf[t]); 
		}
	}
	if(len%512)
	{
		res=f_read(file,fatbuf,len%512,&br);
		if(res)	//读数据出错了
		{
			printf("\r\nRead Error:%d\r\n",res);   
		}else
		{
			tlen+=br;
			for(t=0;t<br;t++)printf("%c",fatbuf[t]); 
		}	 
	}
	if(tlen)printf("\r\nReaded data len:%d\r\n",tlen);//读到的数据长度
	printf("Read data over\r\n");	 
	return res;
}

/**
 * @brief	写入数据
 *
 * @param   dat		数据缓存区
 * @param   len		写入长度
 *
 * @return  u8		执行结果
 */
u8 mf_write(u8*dat,u16 len)
{			    
	u8 res;	   					   

	printf("\r\nBegin Write file...\r\n");
	printf("Write data len:%d\r\n",len);	 
	res=f_write(file,dat,len,&bw);
	if(res)
	{
		printf("Write Error:%d\r\n",res);   
	}else printf("Writed data len:%d\r\n",bw);
	printf("Write data over.\r\n");
	return res;
}


/**
 * @brief	打开目录
 *
 * @param   path	路径
 *
 * @return  u8		执行结果
 */
u8 mf_opendir(u8* path)
{
	return f_opendir(&dir,(const TCHAR*)path);	
}


/**
 * @brief	关闭目录
 *
 * @param   void
 *
 * @return  u8		执行结果
 */
u8 mf_closedir(void)
{
	return f_closedir(&dir);	
}

/**
 * @brief	打读取文件夹
 *
 * @param   void
 *
 * @return  u8		执行结果
 */
u8 mf_readdir(void)
{
	u8 res;    
	res=f_readdir(&dir,&fileinfo);	//读取一个文件的信息
	if(res!=FR_OK)return res;		//出错了 
	printf("\r\n DIR info:\r\n");

	printf("dir.dptr:%d\r\n",dir.dptr);
	printf("dir.obj.id:%d\r\n",dir.obj.id);
	printf("dir.obj.sclust:%d\r\n",dir.obj.sclust);
	printf("dir.obj.objsize:%lld\r\n",dir.obj.objsize);
	printf("dir.obj.c_ofs:%d\r\n",dir.obj.c_ofs);
	printf("dir.clust:%d\r\n",dir.clust);
	printf("dir.sect:%d\r\n",dir.sect);	  
	printf("dir.blk_ofs:%d\r\n",dir.blk_ofs);	  

	printf("\r\n");
	printf("File Name is:%s\r\n",fileinfo.fname);
	printf("File Size is:%lld\r\n",fileinfo.fsize);
	printf("File data is:%d\r\n",fileinfo.fdate);
	printf("File time is:%d\r\n",fileinfo.ftime);
	printf("File Attr is:%d\r\n",fileinfo.fattrib);
	printf("\r\n"); 
	return 0;
}			 

/**
 * @brief	遍历文件
 *
 * @param   path	路径
 *
 * @return  u8		执行结果
 */
u8 mf_scan_files(u8 * path)
{
	FRESULT res;	 
    res = f_opendir(&dir,(const TCHAR*)path); //打开一个目录
    if (res == FR_OK) 
	{	
		printf("\r\n"); 
		while(1)
		{
	        res = f_readdir(&dir, &fileinfo);                   //读取目录下的一个文件
	        if (res != FR_OK || fileinfo.fname[0] == 0) break;  //错误了/到末尾了,退出
	        //if (fileinfo.fname[0] == '.') continue;             //忽略上级目录
 			printf("%s/", path);//打印路径	
			printf("%s\r\n",fileinfo.fname);//打印文件名	  
		} 
    }	   
    return res;	  
}


/**
 * @brief	显示剩余容量
 *
 * @param   drv		盘符
 *
 * @return  u8		剩余容量(字节)
 */
u32 mf_showfree(u8 *drv)
{
	FATFS *fs1;
	u8 res;
    u32 fre_clust=0, fre_sect=0, tot_sect=0;
    //得到磁盘信息及空闲簇数量
    res = f_getfree((const TCHAR*)drv,(DWORD*)&fre_clust, &fs1);
    if(res==0)
	{											   
	    tot_sect = (fs1->n_fatent - 2) * fs1->csize;//得到总扇区数
	    fre_sect = fre_clust * fs1->csize;			//得到空闲扇区数	   
#if _MAX_SS!=512
		tot_sect*=fs1->ssize/512;
		fre_sect*=fs1->ssize/512;
#endif	  
		if(tot_sect<20480)//总容量小于10M
		{
		    /* Print free space in unit of KB (assuming 512 bytes/sector) */
		    printf("\r\n磁盘总容量:%d KB\r\n"
		           "可用空间:%d KB\r\n",
		           tot_sect>>1,fre_sect>>1);
		}else
		{
		    /* Print free space in unit of KB (assuming 512 bytes/sector) */
		    printf("\r\n磁盘总容量:%d MB\r\n"
		           "可用空间:%d MB\r\n",
		           tot_sect>>11,fre_sect>>11);
		}
	}
	return fre_sect;
}

/**
 * @brief	文件读写指针偏移
 *
 * @param   offset	相对首地址的偏移量
 *
 * @return  u8		执行结果
 */
u8 mf_lseek(u32 offset)
{
	return f_lseek(file,offset);
}

/**
 * @brief	读取文件当前读写指针的位置
 *
 * @param   void
 *
 * @return  u32		位置
 */
u32 mf_tell(void)
{
	return f_tell(file);
}
/**
 * @brief	读取文件大小
 *
 * @param   void
 *
 * @return  u32		文件大小
 */
u32 mf_size(void)
{
	return f_size(file);
}

/**
 * @brief	创建目录
 *
 * @param   pname	目录路径+名字
 *
 * @return  u8		执行结果
 */
u8 mf_mkdir(u8*pname)
{
	return f_mkdir((const TCHAR *)pname);
}
/**
 * @brief	格式化
 *
 * @param   path	磁盘路径，比如"0:"、"1:"
 * @param   mode	模式
 * @param   au		簇大小
 *
 * @return  u8		执行结果
 */
u8 mf_fmkfs(u8* path,u8 mode,u16 au)
{
	return f_mkfs((const TCHAR*)path,mode,au);//格式化,drv:盘符;mode:模式;au:簇大小
}
/**
 * @brief	删除文件/目录
 *
 * @param   pname	文件/目录路径+名字
 *
 * @return  u8		执行结果
 */
u8 mf_unlink(u8 *pname)
{
	return  f_unlink((const TCHAR *)pname);
}
/**
 * @brief	修改文件/目录名字(如果目录不同,还可以移动文件哦!)
 *
 * @param   oldname:之前的名字
 * @param   newname:新名字
 *
 * @return  u8		执行结果
 */
u8 mf_rename(u8 *oldname,u8* newname)
{
	return  f_rename((const TCHAR *)oldname,(const TCHAR *)newname);
}
/**
 * @brief	获取盘符（磁盘名字）
 *
 * @param   path	磁盘路径，比如"0:"、"1:"  
 *
 * @return  void
 */
void mf_getlabel(u8 *path)
{
	u8 buf[20];
	u32 sn=0;
	u8 res;
	res=f_getlabel ((const TCHAR *)path,(TCHAR *)buf,(DWORD*)&sn);
	if(res==FR_OK)
	{
		printf("\r\n磁盘%s 的盘符为:%s\r\n",path,buf);
		printf("磁盘%s 的序列号:%X\r\n\r\n",path,sn); 
	}else printf("\r\n获取失败，错误码:%X\r\n",res);
}
/**
 * @brief	设置盘符（磁盘名字），最长11个字符！！，支持数字和大写字母组合以及汉字等
 *
 * @param   path	磁盘号+名字，比如"0:ALIENTEK"、"1:OPENEDV"   
 *
 * @return  void
 */
void mf_setlabel(u8 *path)
{
	u8 res;
	res=f_setlabel ((const TCHAR *)path);
	if(res==FR_OK)
	{
		printf("\r\n磁盘盘符设置成功:%s\r\n",path);
	}else printf("\r\n磁盘盘符设置失败，错误码:%X\r\n",res);
} 
/**
 * @brief	从文件里面读取一段字符串
 *
 * @param   size	要读取的长度
 *
 * @return  void
 */
void mf_gets(u16 size)
{
 	TCHAR* rbuf;
	rbuf=f_gets((TCHAR*)fatbuf,size,file);
	if(*rbuf==0)return  ;//没有数据读到
	else
	{
		printf("\r\nThe String Readed Is:%s\r\n",rbuf);  	  
	}			    	
}

/**
 * @brief	需要_USE_STRFUNC>=1,写一个字符到文件
 *
 * @param   c:		要写入的字符
 *
 * @return  u8		执行结果
 */
u8 mf_putc(u8 c)
{
	return f_putc((TCHAR)c,file);
}
/**
 * @brief	写字符串到文件
 *
 * @param   c:		要写入的字符串
 *
 * @return  u8		写入的字符串长度
 */
u8 mf_puts(u8*c)
{
	return f_puts((TCHAR*)c,file);
}













