/*
MFS_QA.c: Quality Assurence program.

Compiler: BC++ 3.1, 
          Turbo C++ 1.01(3.01) (free from http://cc.codegear.com/free/cpp)
          MSC 6.0,
          MSVC 1.52.
      
Compile mode: large

Project: MFS_QA.c 
         ..\..\lib\7186el.lib
         ..\..\lib\MFS_V210.lib
         
Hardware: uPAC-7186EX-FD
    
[Oct 30, 2008] by Liam
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>

#include "..\..\lib\vp2k.h"
#include "..\..\lib\MFS.h"

#define _DISK_A     0
#define _DISK_B     1

// local prototype
// prompt user for a character to append to the file name, allow 0 to 9 and A to Z or a to z
void CreateFileName(char* FileName);
int DoEraseBlock(int block);

void Test_Dir(void);
void WriteFile(int Disk);
void AppendFile(int Disk);
void DeleteFile(int Disk);

void Test_WritingSpeed(int EnableWriteVerify);
void Test_ReadingSpeed(void);
void Test_PutsSpeed(int EnableWriteVerify);
void Test_GetsSpeed(void);
void Test_PutsGets(void);
void Test_Openfile(void);
void Test_Seek_Tell(void);
void Test_TimeStamp(void);
void Test_TimeStamp_Read(void);
void Test_PutsGets_SameTime(void);
void Test_PutsGets_EOF(void);

void Test_DumpFile(void);
void Test_DumpNVRAM(void);




#define _Test_Length 3276
#define _Test_Loop   1
char far sFileData[_Test_Length],sStandardData[_Test_Length];

void main(void)
{
    int iAction, iRet, iVer;
    char cData;
    char LibDate[16];
    unsigned char *MFS_QA_Date=__DATE__;

    InitLib();
    iRet=mfs_Init();
    if(iRet<0)
    {
        Print("The version of FAT is not suitable for the current version\r\n");
        Print("of function library.\r\n");
        Print("Please reset the Flash (all files will not be retained)\r\n");
        Print("Do you want to reset the Flash (Y/N)?");
        cData=Getch();
        if(cData=='y' || cData=='Y')
        {
            iRet=mfs_ResetFlash();
            if(iRet==NoError)
                Print("ResetFlash() ok.\r\n");
            else
                Print("ResetFlash() failed! Error code=%d\r\n", iRet);
        }
    }
    Print("There are  %d MB flash memory on the VP-2111\r\n",iRet);
    iVer=mfs_GetLibVersion();
    mfs_GetLibDate((unsigned char *) &LibDate);
    
    Print("==============================================\n\r");
    Print("  Quality Assurence Program for MFS. \n\r\n\r");
    Print("  MFS_V%03X.Lib built@[%s]           \n\r",iVer,LibDate);
    Print("  MFS_QA.exe    built@[%s] by Liam   \n\r",MFS_QA_Date);
    Print("==============================================\n\r");
    
    for(;;)
    {
        Print("\r\n");
        Print("0)Quit\n\r");
        Print("1)Dir\r\n");
        Print("2)Del all files\n\r");
        Print("3)WriteFile Speed(Disable WriteVerify)\n\r");
        Print("4)WriteFile Speed(Enable WriteVerify)\n\r");
        Print("5)ReadFile Speed\n\r");
        Print("6)Puts Speed(Disable WriteVerify)\n\r");
        Print("7)Puts Speed(Enable WriteVerify)\n\r");
        Print("8)Gets Speed\n\r");
        Print("9)Puts & Gets functionality\n\r");
        Print("10)Opening 10 file handles \n\r");
        Print("11)Tell & Seek\n\r");
        Print("12)Time Stamp\n\r");
        Print("==== beta testing ====\n\r");
        Print("13)Dump File\r\n");
        Print("14)Dump NVRAM\n\r");
        Print("15)Test_PutsGets_SameTime\n\r");
        Print("16)Test_PutsGets_EOF\n\r");
        
        
        Print("Please Select(0~14): ");
        Scanf("%d", &iAction);
        
        if(iAction==0)
        {
            mfs_Stop();
            break;
        }
            
        Print("\r\n");
        if(iAction==1) Test_Dir();
        if(iAction==2)
        {
            mfs_DeleteAllFiles(_DISK_A);
            mfs_DeleteAllFiles(_DISK_B);
        }
        if(iAction==3) Test_WritingSpeed(0); //DisableWriteVerify
        if(iAction==4) Test_WritingSpeed(1); //EnableWriteVerify
        if(iAction==5) Test_ReadingSpeed();
        if(iAction==6) Test_PutsSpeed(0); //DisableWriteVerify
        if(iAction==7) Test_PutsSpeed(1); //EnableWriteVerify
        if(iAction==8) Test_GetsSpeed();
        if(iAction==9) Test_PutsGets();
        if(iAction==10) Test_Openfile();
        if(iAction==11) Test_Seek_Tell();
        if(iAction==12) Test_TimeStamp();
        
        //==== beta testing =========
        if(iAction==13) Test_DumpFile();
        if(iAction==14) Test_DumpNVRAM();
        if(iAction==15) Test_PutsGets_SameTime();
        if(iAction==16) Test_PutsGets_EOF();
        
        Print("\r\n\n\rPress any key to continue...\r\n");
        Getch();
    }
}


void Test_Dir(void)
{
    int i,iRet,iFileno,iDisk;
    char FileName[20];
    FILE_DATA fdata;
    
    for(iDisk=_DISK_A;iDisk<=_DISK_B;iDisk++)
    {
        if(iDisk==_DISK_A) Print("DiskA file list:\n\r");
        if(iDisk==_DISK_B) Print("DiskB file list:\n\r");
        
        if((iFileno=mfs_GetFileNo(iDisk))>=0)
        {
            for(i=0;i<iFileno;i++)
            {
                iRet=mfs_GetFileInfoByNo(iDisk,i,(FILE_DATA *) &fdata);
                if(iRet==NoError)
                {
                    memset(FileName, 0x0, 14);
                    memcpy(FileName,fdata.fname, 12);
                    
                    Print("%d)%12s    %4ld bytes\r\n",i,FileName, fdata.size);
                }
            }  
            
            Print("\r\nThere are %d File(s)\r\n", iFileno);
            
            Print("%12lu bytes used\r\n", mfs_GetUsedSize(iDisk));
            Print("%12lu bytes free\r\n", mfs_GetFreeSize(iDisk));
            Print("%12lu bytes bad\r\n", mfs_GetBadSzie(iDisk));              
        }
        else 
        {
            Print("GetFileNo() failed! Error code= %d\r\n", iFileno);
        }
    }
}

void Test_PutsSpeed(int EnableWriteVerify)
{
    /*
    Test item: Puts
    Description:  
        Calls Puts to write strings to "String.txt".
    */
    int iFileHandle,i;
    int iRet,iFaile=0;
    long lLastTimeTicks,lTimeDiff;

    if(EnableWriteVerify) mfs_EnableWriteVerify();
    else                  mfs_DisableWriteVerify();
    
    if((iFileHandle=mfs_OpenFile(_DISK_A, "String.txt", "w"))>0)
    {
        Print("OpenFile() : A:String.txt ok, File handle=%d.....\r\n", iFileHandle);

        //Prepare data: 0,1,2,...,8,9,0,1,....
        for(i=0;i<_Test_Length-1;i++)
            sFileData[i]='0'+i%10;
        sFileData[_Test_Length-1]=0; //Add zero end to the string end.
        
        lLastTimeTicks=GetTimeTicks();
        for(i=0;i<_Test_Loop;i++)
        {
            iRet=mfs_Puts(iFileHandle,sFileData);
            if(iRet<=0)
            {
                Print("Loop%d Puts failed! Error code=%d\r\n",i, iRet);
                iFaile=1;
                break;
            }
            Print(".");
        }
        lTimeDiff=GetTimeTicks()-lLastTimeTicks;
        
        iRet=mfs_CloseFile(iFileHandle);
        if(iRet==NoError)
        {
            Print("\n\rCloseFile(): A:String.txt ok.\n\r");
            if(iFaile==0)
            {
                Print("\n\rTest result=ok. Puts %ld Bytes takes %ldms(%5.1fKB/Sec)\n\r",
                      (long)_Test_Loop*(long)_Test_Length,
                      lTimeDiff,
                      (float)_Test_Loop*(float)_Test_Length/lTimeDiff); 
            }
            else Print("\n\rTest result=failed!\n\r");
        }
        else
        {
            Print("\n\rCloseFile(): A:String.txt failed! Error code=%d\r\n", iRet);
            Print("\n\rTest result=failed!\n\r");
        } 
    }
    else
    {
        Print("OpenFile(): A:String.txt failed! Error:%d\r\n", iFileHandle);
        Print("\n\rTest result=failed!\n\r");
    }
}

void Test_GetsSpeed(void)
{
    /*
    Test item: Gets
    Description:  
        Calls Gets to get strings from "String.txt" and check its correction.
    */
    int iFileHandle,i,j;
    int iRet,iFaile=0;
    long lLastTimeTicks,lTimeDiff;
    
    //Prepare standard data: 0,1,2,...,8,9,0,1,.... 
    for(i=0;i<_Test_Length-1;i++)
        sStandardData[i]='0'+i%10;
    sFileData[_Test_Length-1]=0; //Add zero end to the string end.
       
    if((iFileHandle=mfs_OpenFile(_DISK_A, "String.txt", "r"))>0)
    {
        Print("OpenFile() : A:String.txt ok, File handle=%d.....\r\n", iFileHandle);
        
        lLastTimeTicks=GetTimeTicks();
        for(i=0;i<_Test_Loop;i++)
        {
            memset(sFileData,0,_Test_Length);
            
            iRet=mfs_Gets(iFileHandle,sFileData,_Test_Length);
            if(iRet<=0)
            {
                Print("Loop%d Gets failed! Error code=%u\r\n",i, iRet);
                iFaile=1;
                break;
            }
            else if(memcmp(sFileData,sStandardData,_Test_Length-1)!=NoError)
            {
                Print("Loop%d, Compare data failed! Error code=%u\r\n",i, iRet);
                Print("Standard :File\n\r");
                for(j=0;j<_Test_Length-1;j++)
                {
                    if(sStandardData[j]!=sFileData[j])
                    Print("{Data[%d]%c:%c[%02d]:[%02d]} ",j,sStandardData[j],sFileData[j],sStandardData[j],sFileData[j]);
                    if((j+1)%5==0) Print("\n\r");
                    Delay(3);
                }
                Print("\n\r");
                iFaile=1;
                break;
            }
            else Print(".");
        }
        
        if(iFaile==0)
        {
            lTimeDiff=GetTimeTicks()-lLastTimeTicks;
            iRet=mfs_CloseFile(iFileHandle);
            if(iRet==NoError)
            {
                Print("\n\rCloseFile(): A:String.txt ok.\n\r");
                if(iFaile==0)
                {
                    Print("\n\rTest result=ok. Gets %ld Bytes takes %ldms(%5.1fKB/Sec)\n\r",
                          (long)_Test_Loop*(long)_Test_Length,
                          lTimeDiff,
                          (float)_Test_Loop*(float)_Test_Length/lTimeDiff); 
                }
                else Print("\n\rTest result=failed!\n\r");
            }
            else
            {
                Print("\n\rCloseFile(): A:String.txt failed! Error code=%d\r\n", iRet);
                Print("\n\rTest result=failed!\n\r");
            }
        }
        else
        {
            Print("\n\rTest result=failed!\n\r");
        }
    }
    else
    {
        Print("OpenFile(): A:String.txt failed! Error:%d\r\n", iFileHandle);
        Print("\n\rTest result=failed!\n\r");
    }
}


void Test_PutsGets(void)
{
    int iFileHandle,i,j;
    int iRet,iFaile=0;
    long lLastTimeTicks,lTimeDiff;

    mfs_EnableWriteVerify();
    
    if((iFileHandle=mfs_OpenFile(_DISK_A, "PutsGets.txt", "w"))>0)
    {
        Print("OpenFile() : A:PutsGets.txt ok, File handle=%d.....\r\n", iFileHandle);
        for(i=0;i<100;i++)
        {
            iRet=mfs_Puts(iFileHandle,"0123456789abcdefghij"); //total 20 bytes
            if(iRet<=0)
            {
                Print("Loop%d Puts failed! Error code=%d\r\n",i, iRet);
                iFaile=1;
                break;
            }
            Print(".");
        }
        
        iRet=mfs_CloseFile(iFileHandle);
        if(iRet==NoError)
        {
            Print("\n\rCloseFile(): A:PutsGets.txt ok.\n\r");
            if(iFaile) Print("\n\rTest result=failed!\n\r");
        }
        else
        {
            iFaile=1;
            Print("\n\rCloseFile(): A:PutsGets.txt failed! Error code=%d\r\n", iRet);
            Print("\n\rTest result=failed!\n\r");
        } 
    }
    else
    {
        iFaile=1;
        Print("OpenFile(): A:PutsGets.txt failed! Error:%d\r\n", iFileHandle);
        Print("\n\rTest result=failed!\n\r");
    }
    
    //If Puts ok, then test Gets.
    if(iFaile==0)
    {
        if((iFileHandle=mfs_OpenFile(_DISK_A, "PutsGets.txt", "r"))>0)
        {
            Print("OpenFile() : A:PutsGets.txt ok, File handle=%d.....\r\n", iFileHandle);
            
            strcpy(sStandardData,"0123456789abcdefghij");
            for(i=0;i<100;i++)
            {
                memset(sFileData,0,30);//String length = 20 bytes, prepare more space.
                
                iRet=mfs_Gets(iFileHandle,sFileData,30);
                if(iRet<=0)
                {
                    Print("Loop%d Gets failed! Error code=%u\r\n",i, iRet);
                    iFaile=1;
                    break;
                }
                else if(memcmp(sFileData,sStandardData,20)!=NoError)
                {
                    Print("Loop%d, Compare data failed! Error code=%u\r\n",i, iRet);
                    Print("Standard :File\n\r");
                    for(j=0;j<20;j++)
                    {
                        if(sStandardData[j]!=sFileData[j])
                        Print("{Data[%d]%c:%c[%02d]:[%02d]} ",j,sStandardData[j],sFileData[j],sStandardData[j],sFileData[j]);
                        if((j+1)%5==0) Print("\n\r");
                        Delay(3);
                    }
                    Print("\n\r");
                    iFaile=1;
                    break;
                }
                else Print(".");
            }
            
            if(iFaile==0)
            {
                iRet=mfs_CloseFile(iFileHandle);
                if(iRet==NoError)
                {
                    Print("\n\rCloseFile(): A:PutsGets.txt ok.\n\r");
                    if(iFaile) Print("\n\rTest result=failed!\n\r");
                    else Print("\n\rTest result=ok!\n\r");
                }
                else
                {
                    iFaile=1;
                    Print("\n\rCloseFile(): A:PutsGets.txt failed! Error code=%d\r\n", iRet);
                    Print("\n\rTest result=failed!\n\r");
                }
            }
            else
            {
                Print("\n\rTest result=failed!\n\r");
            }
        }
        else
        {
            Print("OpenFile(): A:PutsGets.txt failed! Error:%d\r\n", iFileHandle);
            Print("\n\rTest result=failed!\n\r");
        }        
    }
}    
    

void Test_WritingSpeed(int EnableWriteVerify)
{
    /*
    Test item: Writing speed (calls WriteFile)
    Description:  
        Create a file "Speed.txt". 
    */
    
    int iFileHandle,i;
    int iRet,iFaile=0;
    long lLastTimeTicks,lTimeDiff;

    if(EnableWriteVerify) mfs_EnableWriteVerify();
    else                  mfs_DisableWriteVerify();
    
    if((iFileHandle=mfs_OpenFile(_DISK_A, "Speed.txt", "w"))>0)
    {
        Print("OpenFile() : A:Speed.txt ok, File handle=%d.....\r\n", iFileHandle);

        //Prepare data: 0,1,2,...,8,9,0,1,....
        for(i=0;i<_Test_Length;i++)
            sFileData[i]='0'+i%10;
        
        lLastTimeTicks=GetTimeTicks();
        for(i=0;i<_Test_Loop;i++)
        {
            iRet=mfs_WriteFile(iFileHandle,sFileData,_Test_Length);
            if(iRet<=0)
            {
                Print("Loop%d Write data failed! Error code=%d\r\n",i, iRet);
                iFaile=1;
                break;
            }
            Print(".");
        }
        lTimeDiff=GetTimeTicks()-lLastTimeTicks;
        
        iRet=mfs_CloseFile(iFileHandle);
        if(iRet==NoError)
        {
            Print("\n\rCloseFile(): A:Speed.txt ok.\n\r");
            if(iFaile==0)
            {
                Print("\n\rTest result=ok. WriteFile %ld Bytes takes %ldms(%5.1fKB/Sec)\n\r",
                      (long)_Test_Loop*(long)_Test_Length,
                      lTimeDiff,
                      (float)_Test_Loop*(float)_Test_Length/lTimeDiff); 
            }
            else Print("\n\rTest result=failed!\n\r");
        }
        else
        {
            Print("\n\rCloseFile(): A:Speed.txt failed! Error code=%d\r\n", iRet);
            Print("\n\rTest result=failed!\n\r");
        } 
    }
    else
    {
        Print("OpenFile(): A:Speed.txt failed! Error:%d\r\n", iFileHandle);
        Print("\n\rTest result=failed!\n\r");
    }
}

void Test_ReadingSpeed(void)
{
    /*
    Test item: Reading speed (calls ReadFile)
    Description:  
        Read data from A:Speed.txt and check its correction.
        "Speed.txt" should be created advanced by TestWritingSpeed().
    */
    int iFileHandle,i,j;
    int iRet,iFaile=0;
    long lLastTimeTicks,lTimeDiff;
    
    //Prepare standard data: 0,1,2,...,8,9,0,1,.... 
    for(i=0;i<_Test_Length;i++)
        sStandardData[i]='0'+i%10;
       
    if((iFileHandle=mfs_OpenFile(_DISK_A, "Speed.txt", "r"))>0)
    {
        Print("OpenFile() : A:Speed.txt ok, File handle=%d.....\r\n", iFileHandle);
        
        lLastTimeTicks=GetTimeTicks();
        for(i=0;i<_Test_Loop;i++)
        {
            memset(sFileData,0,_Test_Length);
            
            iRet=mfs_ReadFile(iFileHandle,sFileData,_Test_Length);
            if(iRet<=0)
            {
                Print("Loop%d Read data failed! Error code=%u\r\n",i, iRet);
                iFaile=1;
                break;
            }
            else if(memcmp(sFileData,sStandardData,_Test_Length)!=NoError)
            {
                Print("Loop%d, Compare data failed! Error code=%u\r\n",i, iRet);
                Print("Standard :File\n\r");
                for(j=0;j<_Test_Length;j++)
                {
                    if(sStandardData[j]!=sFileData[j])
                    Print("{Data[%d] %c:%c [%02d]:[%02d]} \n\r",j,sStandardData[j],sFileData[j],sStandardData[j],sFileData[j]);
                }
                Print("\n\r");
                iFaile=1;
                break;
            }
            else Print(".");
        }
        
        if(i==_Test_Loop)
        {
            lTimeDiff=GetTimeTicks()-lLastTimeTicks;
            iRet=mfs_CloseFile(iFileHandle);
            if(iRet==NoError)
            {
                Print("\n\rCloseFile(): A:Speed.txt ok.\n\r");
                if(iFaile==0)
                {
                    Print("\n\rTest result=ok. ReadFile %ld Bytes takes %ldms(%5.1fKB/Sec)\n\r",
                          (long)_Test_Loop*(long)_Test_Length,
                          lTimeDiff,
                          (float)_Test_Loop*(float)_Test_Length/lTimeDiff); 
                }
                else Print("\n\rTest result=failed!\n\r");
            }
            else
            {
                Print("\n\rCloseFile(): A:Speed.txt failed! Error code=%d\r\n", iRet);
                Print("\n\rTest result=failed!\n\r");
            }
        }
        else
        {
            Print("\n\rTest result=failed!\n\r");
        }
    }
    else
    {
        Print("OpenFile(): A:Speed.txt failed! Error:%d\r\n", iFileHandle);
        Print("\n\rTest result=failed!\n\r");
    }
}


void Test_DumpFile(void)
{
    int iFileHandle,i;
    int iRet,iLength,Reading=1;
    char Key,sFileName[13];
    long lPosition=0;
       
    Print("File name:");
    Scanf("%s",sFileName);
       
    if((iFileHandle=mfs_OpenFile(_DISK_A,sFileName, "r"))>0)
    {
        Print("OpenFile() : A:%s ok, File handle=%d.....\r\n",sFileName,iFileHandle);
        
        while(!mfs_EOF(iFileHandle) && Reading)
        {
            memset(sFileData,0,512);
        
            iLength=mfs_ReadFile(iFileHandle,sFileData,512);
            if(iLength<=0)
            {
                Print("Reading data failed! Error code=%d\r\n",iLength);
                Reading=0;
            }
            else
            {
                Print("Position:%ld(%lX), Page%ld(%lX)\n\r",lPosition,lPosition,
                                                            (lPosition+32)/512,
                                                            (lPosition+32)/512);
                Print("Offset(%03ld)= ",mfs_Tell(iFileHandle)-iLength);
                lPosition+=iLength;
                for(i=0;i<iLength;i++)
                {
                    if(sFileData[i]==0 || sFileData[i]==0x0A || sFileData[i]==0x0D)
                        Print(" [%02X] ",sFileData[i]);
                    else
                        Print("%c[%02X] ",sFileData[i],sFileData[i]);
                    if((i+1)%16==0) Print("\n\rOffset(%03ld)= ",mfs_Tell(iFileHandle)-iLength+(i+1));
                }
                Print("\n\rPress 'q' to quit, other key to next page:");
                Key=Getch();
                if(Key=='q' || Key=='Q') Reading=0;
                Print("%c\n\r",Key);
            }
        }
            
        iRet=mfs_CloseFile(iFileHandle);
        if(iRet==NoError) Print("\n\rCloseFile(): A:%s ok.\n\r",sFileName);
        else              Print("\n\rCloseFile(): A:%s failed! Error code=%d\r\n",sFileName,iRet);
    }
    else
        Print("OpenFile(): A:%s failed! Error:%d\r\n",sFileName,iFileHandle);
}

void Test_Openfile(void)
{
    /*
    Test item:DiskA,DiskB can open 10 files at the same time.
    Description:  
        1. Create 25 files on DiskA and DiskB
           Steps:Create 1 file ==> give data ==> close it, repeat to create 25 files.
        2. Open and read the 25 files to check whether its data is correct.
           Steps:Open 25 files ==> read and compare data for opend files 
             ==> Close opend files.
             
            Each disk can open 10 files at the same time,
            On step2, only the first 10 files of each disk can be opend.
            The rest 15 files should return error code when opening.
    */
    int iFileHandle[2][25],i,disk,iLength;
    int iRet;
    char sFileName[13],sData[80],sStandardData[80];
    int iFaile=0;
    
    Print("============================================================\n\r");
    Print("Testing for opening 10 files in diskA and 10 files in diskB.\n\r"); 
    Print("============================================================\n\r");
    
    
    for(disk=_DISK_A;disk<=_DISK_B;disk++)
    {
        if(disk==_DISK_A) Print("DiskA Creating files\n\r");
        if(disk==_DISK_B) Print("DiskB Creating files\n\r");
        
        for(i=0;i<25;i++)
        {
            sprintf(sFileName,"Test%02d.txt",i);
            iFileHandle[disk][i]=mfs_OpenFile(disk,sFileName, "w");
            if(iFileHandle[disk][i]>0)
            {
                sprintf(sData,"test data for disk%d:%s",disk,sFileName);
                iRet=mfs_Puts(iFileHandle[disk][i],sData);
                if(iRet<0) Print("Puts error\n\r");
                iRet=mfs_CloseFile(iFileHandle[disk][i]);
                if(iRet!=NoError) Print("CloseFile error\n\r");
                Print("%s ok. ",sFileName);
            }
            else
            {
                Print("OpenFile %s error\n\r",sFileName);
                iFaile=1;
            }
                
            if((i+1)%5==0) Print("\n\r");
        }
        Print("\n\r");
    }
    
    
    for(disk=_DISK_A;disk<=_DISK_B;disk++)
    {
        if(disk==_DISK_A) Print("DiskA Reading files\n\r");
        if(disk==_DISK_B) Print("DiskB Reading files\n\r");
        
        for(i=0;i<25;i++)
        {
            sprintf(sFileName,"Test%02d.txt",i);
            iFileHandle[disk][i]=mfs_OpenFile(disk,sFileName, "r");
            if(iFileHandle[disk][i]>0)
            {
                sprintf(sStandardData,"test data for disk%d:%s",disk,sFileName);
                iLength=strlen(sStandardData);
                
                memset(sData,0,80);
                iRet=mfs_Gets(iFileHandle[disk][i],sData,80);
                if(iRet==iLength)
                {
                    if(memcmp(sData,sStandardData,iLength)!=NoError)
                    {
                        Print("%s error!\n\r",sFileName);
                        iFaile=1;
                    }
                    else if(iFileHandle[disk][i]!=(disk*10+(i+1))) 
                    {
                        Print("File handle error!\n\r");
                        iFaile=1;
                    }
                    else Print("%s ok. ",sFileName);
                }    
                else 
                {
                    Print("%s Length error\n\r",sFileName);
                    iFaile=1;
                }
            }
            else
            {
                //The first 10 files should be opend ok.
                //The reset 15 files should not be opend.
                if(i<10) 
                {
                    Print("Open %s error(%d)\n\r",sFileName,iFileHandle[disk][i]);
                    iFaile=1;
                }
                else Print(".");
            }
            
            if((i+1)%5==0) Print("\n\r");    
        }
        Print("\n\r");
        
        if(disk==_DISK_A) Print("DiskA Closing files\n\r");
        if(disk==_DISK_B) Print("DiskB Closing files\n\r");
        for(i=0;i<25;i++)
        {
            if(iFileHandle[disk][i]>0)
            {
                iRet=mfs_CloseFile(iFileHandle[disk][i]);
                sprintf(sFileName,"Test%02d.txt",i);
                if(iRet==NoError)
                {
                    Print("%s ok. ",sFileName);
                }
                else
                {
                    Print("\n\rClose %s error(%d)\n\r",sFileName,iRet);
                    iFaile=1;
                }
            }
            else Print(".");
            
            if((i+1)%5==0) Print("\n\r"); 
        }
        Print("\n\r");
    }
    
    if(iFaile) Print("\n\rTest result=failed!\n\r");
    else       Print("\n\rTest result=ok.\n\r");
}


void Test_DumpNVRAM(void)
{
    int i;
    char Data[31],sFileName[13];
    long *lValue;
    int *iValue;
    
    
    for(i=0;i<31;i++)
    {
        Data[i]=ReadNVRAM(i);
        if(Data[i]>=0x21 && Data[i]<=0x7E) //Print visiable characters.
            Print("%c[%02X] ",Data[i]&0xFF,Data[i]&0xFF);
        else
            Print(" [%02X] ",Data[i]&0xFF);
        if((i+1)%10==0) Print("\n\r");
    }
    Print("\n\r");
    
    memcpy(sFileName,Data+6,12);
    sFileName[12]=0;
    
    Print("(0)  DiskA  FAT Current Index=%d\n\r",Data[0]);
    Print("(1)  DiskB  FAT Current Index=%d\n\r",Data[1]);
    Print("(2)  DiskA  FAT Previouse Index=%d\n\r",Data[2]);
    Print("(3)  DiskB  FAT Previouse Index=%d\n\r",Data[3]);
    
    iValue=(int*)(&Data[4]);
    Print("(4-5)Mark=%04X\n\r",iValue);
    
    Print("(6-17)File Name=%s\n\r",sFileName);
    
    lValue=(long*)(&Data[18]);
    Print("(18-21)[%02X] [%02X] [%02X] [%02X]File Size=%ld Bytes\n\r",
            Data[18]&0xFF,Data[19]&0xFF,Data[20]&0xFF,Data[21]&0xFF,*lValue);
    
    lValue=(long*)(&Data[22]);
    Print("(22-25)[%02X] [%02X] [%02X] [%02X]File Begin=%ld\n\r",
            Data[22]&0xFF,Data[23]&0xFF,Data[24]&0xFF,Data[25]&0xFF,*lValue);
            
    lValue=(long*)(&Data[26]);
    Print("(26-29)[%02X] [%02X] [%02X] [%02X]File Begin=%ld\n\r",
            Data[26]&0xFF,Data[27]&0xFF,Data[28]&0xFF,Data[29]&0xFF,*lValue);
    
    Print("File Operating Status:");
    switch(Data[30]&0xFF)
    {
        case 0: Print("0=_File_NonOpen\n\r"); break;
        case 1: Print("1=_File_Opening\n\r"); break;
        case 2: Print("2=_File_Writing\n\r"); break;
        case 3: Print("3=_File_WriteFinish\n\r"); break;
        case 30: Print("30=_FileStatusAddr\n\r"); break;
    }    
}
    
    
    
void Test_Seek_Tell(void)
{
    /*
    Test item: Seek & Tell
    Description:  
        Create a file "SeekTell.txt". Call Tell, Seek, then read data 
        to check whether Tell and Seek work.
    */
    
    int iFileHandle,i,j,iMode;
    int iRet,iFaile=0;
    long lPosition,lOffset;

    if((iFileHandle=mfs_OpenFile(_DISK_A, "SeekTell.txt", "w"))>0)
    {
        Print("OpenFile() : A:SeekTell.txt ok, File handle=%d.....\r\n", iFileHandle);

        //Prepare data: 0,1,2,...,8,9,0,1,....
        for(i=0;i<_Test_Length;i++)
            sFileData[i]='0'+i%10;
        
        iRet=mfs_WriteFile(iFileHandle,sFileData,_Test_Length);
        if(iRet==_Test_Length)
        {
            Print("Write data ok.\n\r");
        }
        else
        {
            Print("Write data failed! Error code=%d\r\n",iRet);
            iFaile=1;
        }
        
        if(iFaile==0)
        {
            iRet=mfs_CloseFile(iFileHandle);
            if(iRet==NoError)
            {
                Print("\n\rCloseFile(): A:SeekTell.txt ok.\n\r");
            }
            else
            {
                Print("\n\rCloseFile(): A:SeekTell.txt failed! Error code=%d\r\n", iRet);
                Print("\n\rTest result=failed!\n\r");
                iFaile=1;
            }
        } 
    }
    else
    {
        Print("OpenFile(): A:SeekTell.txt failed! Error:%d\r\n", iFileHandle);
        Print("\n\rTest result=failed!\n\r");
        iFaile=1;
    }
    
    if(iFaile==0)
    {
        for(i=0;i<_Test_Length;i++)
            sStandardData[i]='0'+i%10;
       
        if((iFileHandle=mfs_OpenFile(_DISK_A, "SeekTell.txt", "r"))>0)
        {
            Print("OpenFile() : A:SeekTell.txt ok, File handle=%d.....\r\n", iFileHandle);
            
            for(iMode=0;iMode<3;iMode++)   
            {
                if(iMode==_SEEK_SET) Print("\n\r_SEEK_SET mode:\n\r");
                if(iMode==_SEEK_CUR) Print("\n\r_SEEK_CUR mode:\n\r");
                if(iMode==_SEEK_END) Print("\n\r_SEEK_END mode:\n\r");
                
                for(i=0;i<10;i++)
                {    
                    memset(sFileData,0,10);
                
                    lOffset=i*(_Test_Length/10);
                    if(iMode==_SEEK_SET)
                    {
                        mfs_Seek(iFileHandle,lOffset,_SEEK_SET);
                    }
                    else if(iMode==_SEEK_CUR)
                    {
                        mfs_Seek(iFileHandle,lOffset,_SEEK_SET);
                        mfs_Seek(iFileHandle,10,_SEEK_CUR);
                        lOffset+=10;
                    }
                    else if(iMode==_SEEK_END)
                    {
                        mfs_Seek(iFileHandle,0L-lOffset-10L,_SEEK_END);
                        lOffset=_Test_Length-lOffset-10L;
                    }
                        
                    lPosition=mfs_Tell(iFileHandle);
                    if(lPosition!=lOffset)
                    {
                        Print("Tell error, Tell=%ld, lOffset=%ld\n\r",lPosition,lOffset);
                        Print("\n\rTest result=failed!\n\r");
                        iFaile=1;
                        break;
                    }
                    
                    iRet=mfs_ReadFile(iFileHandle,sFileData,10);
                    if(iRet<=0)
                    {
                        Print("Read data failed! Error code=%u\r\n",iRet);
                        iFaile=1;
                        break;
                    }
                
                    else if(memcmp(sFileData,sStandardData+lOffset,10)!=NoError)
                    {
                        Print("Compare data failed! Error code=%u\r\n",iRet);
                        Print("Standard :File\n\r");
                        for(j=0;j<10;j++)
                        {
                            if(sStandardData[lOffset+j]!=sFileData[j])
                            Print("{Data[%ld] %c:%c [%02d]:[%02d]} ",
                                    lOffset+j,
                                    sStandardData[lOffset+j],
                                    sFileData[j],
                                    sStandardData[lOffset+j],
                                    sFileData[j]);
                            Delay(5);
                        }
                        Print("\n\r");
                        iFaile=1;
                        break;
                    }
                    else 
                    {
                        Print("%05ld ok. ",lOffset); //Compare data ok.
                        if((i+1)%5==0) Print("\n\r");
                    }
                }
            }
            
        }
        
        if(iFaile==0)
        {
            iRet=mfs_CloseFile(iFileHandle);
            if(iRet==NoError)
            {
                Print("\n\rCloseFile(): A:SeekTell.txt ok.\n\r");
                Print("\n\rTest result=ok!\n\r");
            }
            else
            {
                Print("\n\rCloseFile(): A:SeekTell.txt failed! Error code=%d\r\n", iRet);
                Print("\n\rTest result=failed!\n\r");
            }
        }
        else
        {
            Print("\n\rTest result=failed!\n\r");
        }
    }
    else
    {
        Print("OpenFile(): A:SeekTell.txt failed! Error:%d\r\n", iFileHandle);
        Print("\n\rTest result=failed!\n\r");
    }
}


//=== Following are demo show how to use timer interrupt function
//=== to log data to the 64MB flash memory.
int iLoop=0,iLastReadLoop,iMaxLoop=400,iTimeInterval=25,iLoggingData=0,TimerFileHandle;
int iHour,iMinute,iSecond;

void TimerFun(void)
{
    char Data[80];
    
    iLoop++;
    GetTime(&iHour,&iMinute,&iSecond);
    sprintf(Data,"No%04d@%02d:%02d:%02d",iLoop,iHour,iMinute,iSecond);
    mfs_Puts(TimerFileHandle,Data);
    if(iLoop>=iMaxLoop)
    {
        iLoop=0;
        iLoggingData=0;
        StopUserTimerFun();
    }
}
    
    
void Test_TimeStamp(void)
{
    int iRet,iFaile=0;
    long lTimeTicks;
    
    
    mfs_EnableWriteVerify();
    
    if((TimerFileHandle=mfs_OpenFile(_DISK_A, "Timer.txt", "w"))>0)
    {
        Print("OpenFile() : A:Timer.txt ok, File handle=%d.....\r\n", TimerFileHandle);
        
        iLoggingData=1;
        GetTime(&iHour,&iMinute,&iSecond);
        Print("Begin to log data since %02d:%02d:%02d\n\r",iHour,iMinute,iSecond);
        InstallUserTimerFunction_ms(iTimeInterval,TimerFun);
    }
    else
    {
        iFaile=1;
        Print("OpenFile(): A:Timer.txt failed! Error:%d\r\n", TimerFileHandle);
        Print("\n\rTest result=failed!\n\r");
    }
    
    lTimeTicks=GetTimeTicks();
    while(iLoggingData)
    {
        // Do other things, for example:
        //   1. COM port communication
        //   2. I/O control to Xboard
        
        //Print (.) every second as a progress bar.
        if((GetTimeTicks()-lTimeTicks)>1000)
        {
            Print(".");
            lTimeTicks=GetTimeTicks();
        }
    }
    GetTime(&iHour,&iMinute,&iSecond);
    Print("End logging data at %02d:%02d:%02d\n\r",iHour,iMinute,iSecond);
    iRet=mfs_CloseFile(TimerFileHandle);
    if(iRet==NoError)
    {
        Print("\n\rCloseFile(): A:Timer.txt ok.\n\r");
        if(iFaile) Print("\n\rTest result=failed!\n\r");
        else
        {
          
            Print("\n\rTest result=ok!\n\r");
        }
    }
    else
    {
        iFaile=1;
        Print("\n\rCloseFile(): A:Timer.txt failed! Error code=%d\r\n", iRet);
        Print("\n\rTest result=failed!\n\r");
    }
}

int iReadFileHandle;
void Test_TimeStamp_Read(void)
{
	int iRet,iFaile=0,i;
    long lTimeTicks;
    
    char Data[80];
    
    
    mfs_EnableWriteVerify();
    
    if((TimerFileHandle=mfs_OpenFile(_DISK_A, "Timer.txt", "w"))>0)
    {
        Print("OpenFile() : A:Timer.txt ok, File handle=%d.....\r\n", TimerFileHandle);
        if((iReadFileHandle=mfs_OpenFile(_DISK_A, "Timer.txt", "r"))>0)
        {
            iLastReadLoop=0;
            Print("OpenFile(): A:Timer.txt for reading ok. File handle=%d....\n\r",iReadFileHandle);
        }
        iLoggingData=1;
        GetTime(&iHour,&iMinute,&iSecond);
        Print("Begin to log data since %02d:%02d:%02d\n\r",iHour,iMinute,iSecond);
        InstallUserTimerFunction_ms(iTimeInterval,TimerFun);
    }
    else
    {
        iFaile=1;
        Print("OpenFile(): A:Timer.txt failed! Error:%d\r\n", TimerFileHandle);
        Print("\n\rTest result=failed!\n\r");
    }
    
    lTimeTicks=GetTimeTicks();
    while(iLoggingData)
    {
        // Do other things, for example:
        //   1. COM port communication
        //   2. I/O control to Xboard
        
        //Print (.) every second as a progress bar.
        if((GetTimeTicks()-lTimeTicks)>1000)
        {
  
                    
            Print(".");
            lTimeTicks=GetTimeTicks();
        }
        
        if(iLoop>10)
        {
            if((iLoop+1)%10==0 && iLastReadLoop!=iLoop) 
            {
                mfs_Seek(iReadFileHandle,(iLoop-9)*16,_SEEK_SET);
                Print("Loop (%04d ==> %04d)\n\r",iLoop-9,iLoop);
                for(i=0;i<10;i++)
                {
                    mfs_Gets(iReadFileHandle,Data,80);
                    Print("%s\n\r",Data);
                }
                iLastReadLoop=iLoop;
            }
        }
        
    }
    GetTime(&iHour,&iMinute,&iSecond);
    Print("End logging data at %02d:%02d:%02d\n\r",iHour,iMinute,iSecond);
    iRet=mfs_CloseFile(TimerFileHandle);
    if(iRet==NoError)
    {
        Print("\n\rCloseFile(): A:Timer.txt ok.\n\r");
        if(iFaile) Print("\n\rTest result=failed!\n\r");
        else
        {
            if(iReadFileHandle>0)
            {
                iRet=mfs_CloseFile(iReadFileHandle);
                if(iRet==NoError)
                    Print("\n\rTest result=ok!\n\r");
                else
                    Print("\n\rTest result=failed!\n\r");
            }
        }
    }
    else
    {
        iFaile=1;
        Print("\n\rCloseFile(): A:Timer.txt failed! Error code=%d\r\n", iRet);
        Print("\n\rTest result=failed!\n\r");
    }
}


void Test_PutsGets_SameTime(void)
{
    int iFileHandle,iReadFileHandle,i,j;
    int iRet,iFaile=0;
    long lLastTimeTicks,lTimeDiff;
    long lPosition;
    char Data[80];

    mfs_EnableWriteVerify();
    
    if((iFileHandle=mfs_OpenFile(_DISK_A, "PutsGets.txt", "a"))>0)
    {
        Print("OpenFile() : A:PutsGets.txt ok, File handle=%d.....\r\n", iFileHandle);
        iReadFileHandle=mfs_OpenFile(_DISK_A, "PutsGets.txt", "r");
        Print("OpenFile() : A:PutsGets.txt ok, File handle=%d.....\r\n", iReadFileHandle);
        for(i=0;i<10;i++)
        {
            iRet=mfs_Puts(iFileHandle,"0123456789abcdefghij"); //total 20 bytes
            if(iRet<=0)
            {
                Print("Loop%d Puts failed! Error code=%d\r\n",i, iRet);
                iFaile=1;
                break;
            }
            
            lPosition=mfs_Tell(iReadFileHandle);
            iRet=mfs_Gets(iReadFileHandle,Data,80);
            if(iRet>0)
                Print("Loop%d(%ld)=%s\n\r",i,lPosition,Data);
            else
                Print("Loop%d(%ld)=non\n\r",i,lPosition);
        }
        
        iRet=mfs_CloseFile(iFileHandle);
        while(!mfs_EOF(iReadFileHandle))
        {
            lPosition=mfs_Tell(iReadFileHandle);
            iRet=mfs_Gets(iReadFileHandle,Data,80);
            if(iRet>0)
                Print("Loop%d(%ld)=%s\n\r",i,lPosition,Data);
            else
                Print("Loop%d(%ld)=non\n\r",i,lPosition);
        }
            
        iRet=mfs_CloseFile(iReadFileHandle);
        if(iRet==NoError)
        {
            Print("\n\rCloseFile(): A:PutsGets.txt ok.\n\r");
            if(iFaile) Print("\n\rTest result=failed!\n\r");
        }
        else
        {
            iFaile=1;
            Print("\n\rCloseFile(): A:PutsGets.txt failed! Error code=%d\r\n", iRet);
            Print("\n\rTest result=failed!\n\r");
        } 
    }
    else
    {
        iFaile=1;
        Print("OpenFile(): A:PutsGets.txt failed! Error:%d\r\n", iFileHandle);
        Print("\n\rTest result=failed!\n\r");
    }
}    


void Test_PutsGets_EOF(void)
{
    int iFileHandle,i,j;
    int iRet,iFaile=0;
    long lLastTimeTicks,lTimeDiff;
    long lPosition;

    mfs_EnableWriteVerify();
    
    if((iFileHandle=mfs_OpenFile(_DISK_A, "PutsGets.txt", "w"))>0)
    {
        Print("OpenFile() : A:PutsGets.txt ok, File handle=%d.....\r\n", iFileHandle);
        for(i=0;i<100;i++)
        {
            iRet=mfs_Puts(iFileHandle,"0123456789abcdefghij"); //total 20 bytes
            if(iRet<=0)
            {
                Print("Loop%d Puts failed! Error code=%d\r\n",i, iRet);
                iFaile=1;
                break;
            }
        }
        
        iRet=mfs_CloseFile(iFileHandle);
        if(iRet==NoError)
        {
            Print("\n\rCloseFile(): A:PutsGets.txt ok.\n\r");
            if(iFaile) Print("\n\rTest result=failed!\n\r");
        }
        else
        {
            iFaile=1;
            Print("\n\rCloseFile(): A:PutsGets.txt failed! Error code=%d\r\n", iRet);
            Print("\n\rTest result=failed!\n\r");
        } 
    }
    else
    {
        iFaile=1;
        Print("OpenFile(): A:PutsGets.txt failed! Error:%d\r\n", iFileHandle);
        Print("\n\rTest result=failed!\n\r");
    }
    
    //If Puts ok, then test Gets.
    if(iFaile==0)
    {
        if((iFileHandle=mfs_OpenFile(_DISK_A, "PutsGets.txt", "r"))>0)
        {
            Print("OpenFile() : A:PutsGets.txt ok, File handle=%d.....\r\n", iFileHandle);
            
            strcpy(sStandardData,"0123456789abcdefghij");
            //for(i=0;i<100;i++)
            while(!mfs_EOF(iFileHandle))
            {
                memset(sFileData,0,30);//String length = 20 bytes, prepare more space.
                
                iRet=mfs_Gets(iFileHandle,sFileData,30);
                if(iRet<=0)
                {
                    Print("Loop%d Gets failed! Error code=%u\r\n",i, iRet);
                    iFaile=1;
                    break;
                }
                else if(memcmp(sFileData,sStandardData,20)!=NoError)
                {
                    Print("Loop%d, Compare data failed! Error code=%u\r\n",i, iRet);
                    Print("Standard :File\n\r");
                    for(j=0;j<20;j++)
                    {
                        if(sStandardData[j]!=sFileData[j])
                        Print("{Data[%d]%c:%c[%02d]:[%02d]} ",j,sStandardData[j],sFileData[j],sStandardData[j],sFileData[j]);
                        if((j+1)%5==0) Print("\n\r");
                        Delay(3);
                    }
                    Print("\n\r");
                    iFaile=1;
                    break;
                }
                else Print(".");
            }
            
            if(iFaile==0)
            {
                iRet=mfs_CloseFile(iFileHandle);
                if(iRet==NoError)
                {
                    Print("\n\rCloseFile(): A:PutsGets.txt ok.\n\r");
                    if(iFaile) Print("\n\rTest result=failed!\n\r");
                    else Print("\n\rTest result=ok!\n\r");
                }
                else
                {
                    iFaile=1;
                    Print("\n\rCloseFile(): A:PutsGets.txt failed! Error code=%d\r\n", iRet);
                    Print("\n\rTest result=failed!\n\r");
                }
            }
            else
            {
                Print("\n\rTest result=failed!\n\r");
            }
        }
        else
        {
            Print("OpenFile(): A:PutsGets.txt failed! Error:%d\r\n", iFileHandle);
            Print("\n\rTest result=failed!\n\r");
        }        
    }
}    