/*
flash.c : User can read/write integer , float and string data to flash

Compiler: BC++ 3.1,                                                            
          Turbo C ++ 1.01(3.01) (free from http://community.borland.com/museum)
          MSC 6.0,                                                             
          MSVC 1.52.                                                           
                                                                               
Compile mode: large                                                            
                                                                               
Project: flash.c                                                               
         ..\..\Lib\(8000E.Lib,7188XAL.Lib,7188XBL.Lib,7188XCL.Lib or 7188EL.Lib)    
                                                                               
Hardware: 7188/8000

Detail description:
        To write the flash,user must know the segment number and offset address of the data which will write to flash
        for 8000 system, the flash size may be 256K or 512K
        and there ar 64K for each segment
        For 256K Flash, the segment adddress
        0xC000 (os load files from here)
        0xD000  
        0xE000 (reserve n ,segment start from here)
        0xF000 (always reserved by os image)
        
        For 512K Flash, the segment adddress
        0x8000 (os load files from here)
        0x9000   
        0xA000  
        0xB000      
        0xC000
        0xD000   
        0xE000 (reserve n ,segment start from here)
        0xF000 (always reserved by os image)   
        
        Note : The MiniOS7 command "reserve n" 
            can notify the os not to overwrite the files or data 
            to the segments which have been reserved.
        For example:
            reserve 2 ; this command will tell os not to 
            overwrite or delete data which located at segment 0xE000 and 0xD000  
            And os will load files from 0x8000 (for 512K flash) ; 0xC000 (for 256K flash)
        
        Note : The MiniOS7 cmmand use flash --> erase E000 will erase the data directly on flash
        Note : FlashErase(0xe000); will erase the data directly on flash also. 
[1 Jun,2006] by martin
----------------------------------------------------------------------
*/

#include "..\..\..\lib\vp2k.h"
#include <string.h>

unsigned base=0xE000; /* 256K type,seg can be 0xC0000~0xE0000. 512K type,seg can be 0x80000~0xE0000 */
//unsigned offset=0;    /* 0 to 65535(0xffff). */

void Flash_MultiRead(int iSeg,int iOffset, int iCount, char* cData)
{
    int i;
    
    for(i=iOffset;i<(iOffset+iCount);i++)
    {
        *cData=FlashRead(iSeg,i);
        cData++;
    }
}

int Flash_MultiWrite(int iSeg,int iOffset,int iCount, char* cData)
{
    int i,iRet;
    
    for(i=iOffset;i<(iOffset+iCount);i++)
    {
        iRet=FlashWrite(iSeg,i,*cData & 0xff);
        if(iRet<0)
            return iRet;            
        else            
            cData++;                
        RefreshWDT();
    }
    return 0;
}
// return the begin address of next data 
int Flash_ReadInt(int iSeg,int iOffset,int* iData) 
{ 
    //int iData;  
    Flash_MultiRead(iSeg, iOffset, 2, (char*)iData);      
    return iOffset+2;
}
// return the begin address of next data 
int Flash_WriteInt(int iSeg,int iOffset, int iData)
{
    int iRet;
    
    iRet=Flash_MultiWrite(iSeg, iOffset, 2, (char*)&iData);
    if(iRet<0)
        return iRet; 
   
    return iOffset+2;
}
// return the begin address of next data 
int Flash_ReadFloat(int iSeg,int iOffset,float* fData) 
{ 
      
    Flash_MultiRead(iSeg, iOffset, 4, (char*)fData);      
    return iOffset+4;
}
// return the begin address of next data 
int Flash_WriteFloat(int iSeg,int iOffset, float fData)
{
    int iRet;
    
    iRet=Flash_MultiWrite(iSeg, iOffset, 4, (char*)&fData);
    if(iRet<0)
        return iRet; 
   
    return iOffset+4;
}
// first byte save the string length (not more than 256), toatl bytes need string length +1 bytes
// return the begin address of next data 
int Flash_ReadString(int iSeg,int iOffset,char *sData) 
{ 
     
    int len=0;
    len=FlashRead(iSeg, iOffset);
    Flash_MultiRead(iSeg, iOffset+1, len, sData); 
    sData[len]='\0';   //add null terminate char  
    return iOffset+1+len;
}
// first byte save the string length (not more than 256), toatl bytes need string length +1 bytes
// return the begin address of next data 
int Flash_WriteString(int iSeg,int iOffset, char* sData)
{
    int iRet;
    int len;
    len=strlen(sData) & 0xff;
    FlashWrite(iSeg,iOffset,len);
    Flash_MultiWrite(iSeg, iOffset+1, len, sData);
    if(iRet<0)
        return iRet; 
   
    return iOffset+1+len;
}

void showMenu(void)
{
    printCom1("\n\n****************************************************\n\r");
    printCom1("*  Warning don't Erase and Write flash frequently. *\n\r");
    printCom1("*  It can be rewrited about 1,000,000 times!       *\n\r");
    printCom1("****************************************************\n\r");    
    printCom1("Enter 'E' or 'e' to Erase the flash.\n\r");
    printCom1("Enter 'R' or 'r' to Read the flash.\n\r");
    printCom1("Enter 'W' or 'w' to Write the flash.\n\r"); 
    printCom1("Enter 'Q' or 'q' to Exit the program.\n\r");
 
}

int main(void)
{
    int nextIndex;
    int curIndex=0;
    int iData=0;
    float fData=0;
    char sData[26];
    unsigned i;
    char ch;
    int len;
    char buf[256];
    unsigned int id,fid;
    char str[]="demo to read/write from flash";

    
    InitLib();
    InstallCom1(115200L,8,0,1);
    showMenu();
    while(1)
    {
        ch=ReadCom(1);
        switch(ch)
        {
            case 'E':case 'e'://erase
                // Erase the test segment of flash before wirte data
                FlashErase(base); 
                printCom1("\nErase Flash OK \n\r");
                showMenu();   
                     
            break;
            case 'R':case 'r'://read
                printCom1("\n\nRead Data from Flash\n");
                
                curIndex=0;
                
                //Read String data
                nextIndex=Flash_ReadString(base,curIndex,buf);
                printCom1("String[%d]:%s ==>Next[%d]; \n\r",curIndex,buf,nextIndex);
                
                //Read Integer data
                for(i=0;i<10;i++)
                {
                    curIndex=nextIndex;  
                    nextIndex=Flash_ReadInt(base,curIndex,&iData);
                    printCom1("Integer[%d]:%d ==>Next[%d];\n\r",curIndex,iData,nextIndex);   
                }    
                //Read Float data
                for(i=0;i<10;i++)
                {
                    curIndex=nextIndex; 
                    nextIndex=Flash_ReadFloat(base,curIndex,&fData);
                    printCom1("Float[%d]:%f ==>Next[%d];\n\r",curIndex,fData,nextIndex);             
                }
                showMenu();
            break;
            case 'W':case 'w'://write
                printCom1("\n\nWrite Data to Flash\n");
                
                
                curIndex=0;
                
               //write string data                
                nextIndex=Flash_WriteString(base,curIndex,str);    
                printCom1("\n\nString[%d]:%s ==>Next[%d]; \n\r",curIndex,str,nextIndex);
                
                //write Integer data
                for(i=0;i<10;i++)
                {
                    curIndex=nextIndex;
                    nextIndex=Flash_WriteInt(base,curIndex,i*30);   
                    printCom1("Integer[%d]:%d ==>Next[%d];\n\r",curIndex,i*30,nextIndex);   
                }
                    
                //write Float data
                for(i=0;i<10;i++)
                {                
                    curIndex=nextIndex;
                    nextIndex=Flash_WriteFloat(base,curIndex,i*3.3);
                    printCom1("Float[%d]:%f ==>Next[%d];\n\r",curIndex,i*3.3,nextIndex);            
                }
                showMenu();
            break;
            case 'Q':case 'q':
                exit(0);
            break;
        
        
        }
    
    }
   
    RestoreCom1();
    return 1;   /* any value will be accept */
}
