Advertisement
Guest User

FAT32.c

a guest
Nov 5th, 2010
777
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 26.32 KB | None | 0 0
  1. //*******************************************************
  2. // **** ROUTINES FOR FAT32 IMPLEMATATION OF SD CARD ****
  3. //*******************************************************
  4. //Controller: ATmega168 (Clock: 8 Mhz-internal)
  5. //Compiler: AVR-GCC
  6. //Version : 2.0
  7. //Author: CC Dharmani, Chennai (India)
  8. // www.dharmanitech.com
  9. // With some changes by Mujda
  10. //Date: 26 Feb 2009
  11. //*******************************************************
  12.  
  13.  
  14.  
  15. //Link to the Post: http://www.dharmanitech.com/2009/01/sd-card-interfacing-with-atmega8-fat32.html
  16.  
  17. //**************************************************
  18. // ***** SOURCE FILE : FAT32.c ******
  19. //**************************************************
  20.  
  21. #include <avr/io.h>
  22. #include <avr/pgmspace.h>
  23. #include <util/delay.h>
  24. #include "FAT32.h"
  25. #include "UART_routines.h"
  26. #include "SD_routines.h"
  27.  
  28. volatile uint16_t digitala, digitalb;
  29. volatile int seconds, minutes, hours, days, months, years;
  30. volatile int sample;
  31.  
  32. //***************************************************************************
  33. //Function: to read data from boot sector of SD card, to determine important
  34. //parameters like bytesPerSector, sectorsPerCluster etc.
  35. //Arguments: none
  36. //return: none
  37. //***************************************************************************
  38. unsigned char getBootSectorData (void)
  39. {
  40. struct BS_Structure *bpb; //mapping the buffer onto the structure
  41. struct MBRinfo_Structure *mbr;
  42. struct partitionInfo_Structure *partition;
  43. unsigned long dataSectors;
  44.  
  45. unusedSectors = 0;
  46.  
  47. SD_readSingleBlock(0);
  48. bpb = (struct BS_Structure *)buffer;
  49.  
  50. if(bpb->jumpBoot[0]!=0xE9 && bpb->jumpBoot[0]!=0xEB) //check if it is boot sector
  51. {
  52.   mbr = (struct MBRinfo_Structure *) buffer;         //if it is not boot sector, it must be MBR
  53.  
  54.   if(mbr->signature != 0xaa55) return 1;            //if it is not even MBR then it's not FAT32
  55.      
  56.   partition = (struct partitionInfo_Structure *)(mbr->partitionData);//first partition
  57.   unusedSectors = partition->firstSector; //the unused sectors, hidden to the FAT
  58.  
  59.   SD_readSingleBlock(partition->firstSector);//read the bpb sector
  60.   bpb = (struct BS_Structure *)buffer;
  61.   if(bpb->jumpBoot[0]!=0xE9 && bpb->jumpBoot[0]!=0xEB)  return 1;
  62. }
  63.  
  64. bytesPerSector      = bpb->bytesPerSector;
  65. sectorPerCluster    = bpb->sectorPerCluster;
  66. reservedSectorCount = bpb->reservedSectorCount;
  67. rootCluster         = bpb->rootCluster;// + (sector / sectorPerCluster) +1;
  68. firstDataSector     = bpb->hiddenSectors + reservedSectorCount + (bpb->numberofFATs * bpb->FATsize_F32);
  69.  
  70. dataSectors   = bpb->totalSectors_F32 - bpb->reservedSectorCount - ( bpb->numberofFATs * bpb->FATsize_F32);
  71. totalClusters = dataSectors / sectorPerCluster;
  72.  
  73. if((getSetFreeCluster (TOTAL_FREE, GET, 0)) > totalClusters)  //check if FSinfo free clusters count is valid
  74.   freeClusterCountUpdated = 0;
  75. else
  76.   freeClusterCountUpdated = 1;
  77. return 0;
  78. }
  79.  
  80. //***************************************************************************
  81. //Function: to calculate first sector address of any given cluster
  82. //Arguments: cluster number for which first sector is to be found
  83. //return: first sector address
  84. //***************************************************************************
  85. unsigned long getFirstSector(unsigned long clusterNumber)
  86. {
  87.   return (((clusterNumber - 2) * sectorPerCluster) + firstDataSector);
  88. }
  89.  
  90. //***************************************************************************
  91. //Function: get cluster entry value from FAT to find out the next cluster in the chain
  92. //or set new cluster entry in FAT
  93. //Arguments: 1. current cluster number, 2. get_set (=GET, if next cluster is to be found or = SET,
  94. //if next cluster is to be set 3. next cluster number, if argument#2 = SET, else 0
  95. //return: next cluster number, if if argument#2 = GET, else 0
  96. //****************************************************************************
  97. unsigned long getSetNextCluster (unsigned long clusterNumber,
  98.                                  unsigned char get_set,
  99.                                  unsigned long clusterEntry)
  100. {
  101. unsigned int  FATEntryOffset;
  102. unsigned long *FATEntryValue;
  103. unsigned long FATEntrySector;
  104. unsigned char retry = 0;
  105.  
  106. //get sector number of the cluster entry in the FAT
  107. FATEntrySector = unusedSectors + reservedSectorCount + ((clusterNumber * 4) / bytesPerSector) ;
  108.  
  109. //get the offset address in that sector number
  110. FATEntryOffset = (unsigned int) ((clusterNumber * 4) % bytesPerSector);
  111.  
  112. //read the sector into a buffer
  113. while(retry <10)
  114. { if(!SD_readSingleBlock(FATEntrySector)) break; retry++;}
  115.  
  116. //get the cluster address from the buffer
  117. FATEntryValue = (unsigned long *) &buffer[FATEntryOffset];
  118.  
  119. if(get_set == GET)
  120.   return ((*FATEntryValue) & 0x0fffffff);
  121.  
  122. *FATEntryValue = clusterEntry;   //for setting new value in cluster entry in FAT
  123.  
  124. SD_writeSingleBlock(FATEntrySector);
  125.  
  126. return (0);
  127. }
  128.  
  129. //********************************************************************************************
  130. //Function: to get or set next free cluster or total free clusters in FSinfo sector of SD card
  131. //Arguments: 1.flag:TOTAL_FREE or NEXT_FREE,
  132. //           2.flag: GET or SET
  133. //           3.new FS entry, when argument2 is SET; or 0, when argument2 is GET
  134. //return: -next free cluster, if arg1 is NEXT_FREE & arg2 is GET
  135. //        -total number of free clusters, if arg1 is TOTAL_FREE & arg2 is GET
  136. //        -0xffffffff, if any error or if arg2 is SET
  137. //********************************************************************************************
  138. unsigned long getSetFreeCluster(unsigned char totOrNext, unsigned char get_set, unsigned long FSEntry)
  139. {
  140. struct FSInfo_Structure *FS = (struct FSInfo_Structure *) &buffer;
  141. unsigned char error;
  142.  
  143. SD_readSingleBlock(unusedSectors + 1);
  144.  
  145. if((FS->leadSignature != 0x41615252) || (FS->structureSignature != 0x61417272) || (FS->trailSignature !=0xaa550000))
  146.   return 0xffffffff;
  147.  
  148.  if(get_set == GET)
  149.  {
  150.    if(totOrNext == TOTAL_FREE)
  151.       return(FS->freeClusterCount);
  152.    else // when totOrNext = NEXT_FREE
  153.       return(FS->nextFreeCluster);
  154.  }
  155.  else
  156.  {
  157.    if(totOrNext == TOTAL_FREE)
  158.       FS->freeClusterCount = FSEntry;
  159.    else // when totOrNext = NEXT_FREE
  160.       FS->nextFreeCluster = FSEntry;
  161.  
  162.    error = SD_writeSingleBlock(unusedSectors + 1);    //update FSinfo
  163.  }
  164.  return 0xffffffff;
  165. }
  166.  
  167. //***************************************************************************
  168. //Function: to get DIR/FILE list or a single file address (cluster number) or to delete a specified file
  169. //Arguments: #1 - flag: GET_LIST, GET_FILE or DELETE #2 - pointer to file name (0 if arg#1 is GET_LIST)
  170. //return: first cluster of the file, if flag = GET_FILE
  171. //        print file/dir list of the root directory, if flag = GET_LIST
  172. //        Delete the file mentioned in arg#2, if flag = DELETE
  173. //****************************************************************************
  174. struct dir_Structure* findFiles (unsigned char flag, unsigned char *fileName)
  175. {
  176. unsigned long cluster, sector, firstSector, firstCluster, nextCluster;
  177. struct dir_Structure *dir;
  178. unsigned int i;
  179. unsigned char j;
  180.  
  181. cluster = rootCluster; //root cluster
  182.  
  183. while(1)
  184. {
  185.    firstSector = getFirstSector (cluster);
  186.  
  187.    for(sector = 0; sector < sectorPerCluster; sector++)
  188.    {
  189.      SD_readSingleBlock (firstSector + sector);
  190.    
  191.      for(i=0; i<bytesPerSector; i+=32)
  192.      {
  193.         dir = (struct dir_Structure *) &buffer[i];
  194.  
  195.         if(dir->name[0] == EMPTY) //indicates end of the file list of the directory
  196.         {
  197.            if((flag == GET_FILE) || (flag == DELETE))
  198. //                transmitString_F(PSTR("File does not exist!"));
  199.            return 0;  
  200.         }
  201.        
  202.  
  203.         if((dir->name[0] != DELETED) && (dir->attrib != ATTR_LONG_NAME))
  204.         {
  205.           if((flag == GET_FILE) || (flag == DELETE))
  206.           {
  207.             for(j=0; j<11; j++)
  208.               if(dir->name[j] != fileName[j]) break;
  209.             if(j == 11)
  210.             {
  211.                if(flag == GET_FILE)
  212.                   return (dir);
  213.                else    //when flag = DELETE
  214.                {
  215.                   TX_NEWLINE;
  216.                   transmitString_F(PSTR("Deleting.."));
  217.                   TX_NEWLINE;
  218.                   TX_NEWLINE;
  219.                   firstCluster = (((unsigned long) dir->firstClusterHI) << 16) | dir->firstClusterLO;
  220.                
  221.                   //mark file as 'deleted' in FAT table
  222.                   dir->name[0] = DELETED;  
  223.                   SD_writeSingleBlock (firstSector+sector);
  224.                                            
  225.                   freeMemoryUpdate (ADD, dir->fileSize);
  226.  
  227.                   //update next free cluster entry in FSinfo sector
  228.                   cluster = getSetFreeCluster (NEXT_FREE, GET, 0);
  229.                   if(firstCluster < cluster)
  230.                      getSetFreeCluster (NEXT_FREE, SET, firstCluster);
  231.  
  232.                   //mark all the clusters allocated to the file as 'free'
  233.                   while(1)
  234.                   {
  235.                      nextCluster = getSetNextCluster (firstCluster, GET, 0);
  236.                      getSetNextCluster (firstCluster, SET, 0);
  237.                      if(nextCluster > 0x0ffffff6)
  238.                        {transmitString_F(PSTR("File deleted!"));return 0;}
  239.                      firstCluster = nextCluster;
  240.                   }
  241.                }
  242.             }
  243.           }
  244.           else  //when flag = GET_LIST
  245.           {
  246.              TX_NEWLINE;
  247.               for(j=0; j<11; j++)
  248.               {
  249.                 if(j == 8) transmitByte(' ');
  250.                 transmitByte (dir->name[j]);
  251.               }
  252.               transmitString_F (PSTR("   "));
  253.               if((dir->attrib != 0x10) && (dir->attrib != 0x08))
  254.               {
  255.                  transmitString_F (PSTR("FILE" ));
  256.                  transmitString_F (PSTR("   "));
  257.                  displayMemory (dir->fileSize);
  258.               }
  259.               else
  260.                  transmitString_F ((dir->attrib == 0x10)? PSTR("DIR") : PSTR("ROOT"));
  261.           }
  262.        }
  263.      }
  264.    }
  265.  
  266.    cluster = (getSetNextCluster (cluster, GET, 0));
  267.  
  268.    if(cluster > 0x0ffffff6)
  269.        return 0;
  270.    if(cluster == 0)
  271.    {transmitString_F(PSTR("Error in getting cluster"));  return 0;}
  272.  }
  273. return 0;
  274. }
  275.  
  276. //***************************************************************************
  277. //Function: if flag=READ then to read file from SD card and send contents to UART
  278. //if flag=VERIFY then functions will verify whether a specified file is already existing
  279. //Arguments: flag (READ or VERIFY) and pointer to the file name
  280. //return: 0, if normal operation or flag is READ
  281. //        1, if file is already existing and flag = VERIFY
  282. //        2, if file name is incompatible
  283. //***************************************************************************
  284. unsigned char readFile (unsigned char flag, unsigned char *fileName)
  285. {
  286. struct dir_Structure *dir;
  287. unsigned long cluster, byteCounter = 0, fileSize, firstSector;
  288. unsigned int k;
  289. unsigned char j, error;
  290.  
  291. error = convertFileName (fileName); //convert fileName into FAT format
  292. if(error) return 2;
  293.  
  294. dir = findFiles (GET_FILE, fileName); //get the file location
  295. if(dir == 0)
  296.   return (0);
  297.  
  298. if(flag == VERIFY) return (1);      //specified file name is already existing
  299.  
  300. cluster = (((unsigned long) dir->firstClusterHI) << 16) | dir->firstClusterLO;
  301.  
  302. fileSize = dir->fileSize;
  303.  
  304. TX_NEWLINE;
  305. TX_NEWLINE;
  306.  
  307. while(1)
  308. {
  309.   firstSector = getFirstSector (cluster);
  310.  
  311.   for(j=0; j<8; j++)
  312.   {
  313.     SD_readSingleBlock(firstSector + j);
  314.  
  315.     for(k=0; k<512; k++)
  316.     {
  317.       transmitByte(buffer[k]);
  318.       if ((byteCounter++) >= fileSize ) return 0;
  319.     }
  320.   }
  321.   cluster = getSetNextCluster (cluster, GET, 0);
  322.   if(cluster == 0) {transmitString_F(PSTR("Error in getting cluster")); return 0;}
  323. }
  324. return 0;
  325. }
  326.  
  327. //***************************************************************************
  328. //Function: to convert normal short file name into FAT format
  329. //Arguments: pointer to the file name
  330. //return: 0-if no error, 1-if error
  331. //****************************************************************************
  332. unsigned char convertFileName (unsigned char *fileName)
  333. {
  334. unsigned char fileNameFAT[11];
  335. unsigned char j, k;
  336.  
  337. for(j=0; j<12; j++)
  338. if(fileName[j] == '.') break;
  339.  
  340. if(j>8) {transmitString_F(PSTR("Invalid fileName..")); return 1;}
  341.  
  342. for(k=0; k<j; k++) //setting file name
  343.   fileNameFAT[k] = fileName[k];
  344.  
  345. for(k=j; k<=7; k++) //filling file name trail with blanks
  346.   fileNameFAT[k] = ' ';
  347.  
  348. j++;
  349. for(k=8; k<11; k++) //setting file extention
  350. {
  351.   if(fileName[j] != 0)
  352.     fileNameFAT[k] = fileName[j++];
  353.   else //filling extension trail with blanks
  354.     while(k<11)
  355.       fileNameFAT[k++] = ' ';
  356. }
  357.  
  358. for(j=0; j<11; j++) //converting small letters to caps
  359.   if((fileNameFAT[j] >= 0x61) && (fileNameFAT[j] <= 0x7a))
  360.     fileNameFAT[j] -= 0x20;
  361.  
  362. for(j=0; j<11; j++)
  363.   fileName[j] = fileNameFAT[j];
  364.  
  365. return 0;
  366. }
  367.  
  368. //***************************************************************************
  369. //Function: to create a file in FAT32 format in the root directory
  370. //Arguments: pointer to the file name
  371. //return: none
  372. //***************************************************************************
  373. void createFile (unsigned char *fileName)
  374. {
  375. unsigned char j, data, error, fileCreatedFlag = 0, line[43], loc;
  376. unsigned int i, firstClusterHigh, firstClusterLow;
  377. struct dir_Structure *dir;
  378. unsigned long cluster, prevCluster, firstSector, sector;
  379. unsigned long size;
  380.  
  381. line[0] = 'D';
  382. line[1] = 'D';
  383. line[2] = '/';
  384. line[3] = 'M';
  385. line[4] = 'M';
  386. line[5] = '/';
  387. line[6] = 'Y';
  388. line[7] = 'Y';
  389. line[8] = ',';
  390. line[9] = 'H';
  391. line[10] = 'H';
  392. line[11] = ':';
  393. line[12] = 'M';
  394. line[13] = 'M';
  395. line[14] = ':';
  396. line[15] = '0';
  397. line[16] = '0';
  398. line[17] = ',';
  399. line[18] = '1'; // Digital1
  400. line[19] = '2';
  401. line[20] = '3';
  402. line[21] = '4';
  403. line[22] = ',';
  404. line[23] = '1'; // Digital2
  405. line[24] = '2';
  406. line[25] = '3';
  407. line[26] = '4';
  408. line[27] = ',';
  409. line[28] = '1'; // Analog1
  410. line[29] = '2';
  411. line[30] = '3';
  412. line[31] = '4';
  413. line[32] = ',';
  414. line[33] = '1'; // Analog2
  415. line[34] = '2';
  416. line[35] = '3';
  417. line[36] = '4';
  418. line[37] = ',';
  419. line[38] = '1'; // Analog3
  420. line[39] = '2';
  421. line[40] = '3';
  422. line[41] = '4';
  423. line[42] = '\r';
  424. loc = 0;
  425. // Define data to be line feed to start sampling process
  426. data = '\r';
  427.  
  428. j = readFile (VERIFY, fileName);
  429.  
  430. if(j == 1) {transmitString_F(PSTR("  File already existing")); return;}
  431. if(j == 2) return; //invalid file name
  432.  
  433. TX_NEWLINE;
  434. transmitString_F(PSTR(" Creating File.."));
  435.  
  436. cluster = getSetFreeCluster (NEXT_FREE, GET, 0);
  437. if(cluster > totalClusters)
  438.   cluster = rootCluster;
  439.  
  440. cluster = searchNextFreeCluster(cluster);
  441.    if(cluster == 0)
  442.    {
  443.       TX_NEWLINE;
  444.       transmitString_F(PSTR(" No free cluster!"));
  445.       return;
  446.    }
  447. //transmitHex(LONG, cluster);
  448.  
  449. firstClusterHigh = (unsigned int) ((cluster & 0xffff0000) >> 16 );
  450. firstClusterLow = (unsigned int) ( cluster & 0x0000ffff);
  451.  
  452. size = 0;
  453.  
  454. while(1)
  455. {
  456.    getSetNextCluster (cluster, SET, EOF);   //last cluster of the file, marked EOF
  457.    startBlock = getFirstSector (cluster);
  458.  
  459.    TX_NEWLINE;
  460.    transmitString_F(PSTR(" End sampling with button press longer than 1sec:"));
  461.    
  462.    i=0;
  463.    j=0;
  464.    
  465.    do
  466.    {
  467. // If there's been a line feed (/n) then get new line of data,
  468. // wait 1 second, reset location
  469.      if(data == '\r'){
  470.        PORTC |= 0b00100000; // Turn on LED1
  471.        sampleData(line);    // Acquire data and write it to formatted string
  472.        digitala = 0;        // Reset digital counters
  473.        digitalb = 0;
  474.        sample = 0;          // Reset sample flag
  475.        
  476.        _delay_ms(50);
  477.        PORTC &= 0b11011111; // Turn off LED1
  478.        
  479.        while(sample == 0){};       // Wait for flag from RTC interrupt routine
  480.  
  481.        loc = 0;}
  482.        data = line[loc];
  483. // Check for button press, if so exit with exit character
  484.      if((PINC & 1) == 0) data = '~';
  485.      loc++;
  486.      if(data == 0x08)    //'Back Space' key pressed
  487.      {
  488.        if(i != 0)
  489.        {
  490.          transmitByte(data);
  491.          transmitByte(' ');
  492.          transmitByte(data);
  493.          i--;
  494.          size--;
  495.        }
  496.        continue;    
  497.      }
  498.      transmitByte(data);
  499.      buffer[i++] = data;
  500.      size++;
  501.      if(data == '\r')  //'Carriage Return (CR)' character
  502.      {
  503.         transmitByte('\n');
  504.         buffer[i++] = '\n'; //appending 'Line Feed (LF)' character
  505.         size++;
  506.      }
  507.    
  508.      if(i == 512)
  509.      {
  510.        i=0;
  511.        error = SD_writeSingleBlock (startBlock);
  512.        j++;
  513.        if(j == sectorPerCluster) {j = 0; break;}
  514.        startBlock++;
  515.      }
  516.     }while (data != '~');
  517.  
  518.    if(data == '~')
  519. //   if((PINC & 1) == 1)
  520.    {
  521.       size--;    //to remove the last entered '~' character
  522.       i--;
  523.       for(;i<512;i++)  //fill the rest of the buffer with 0x00
  524.         buffer[i]= 0x00;
  525.          error = SD_writeSingleBlock (startBlock);
  526.  
  527.       break;
  528.    }
  529.      
  530.    prevCluster = cluster;
  531.  
  532.    cluster = searchNextFreeCluster(prevCluster); //look for a free cluster starting from the current cluster
  533.  
  534.    if(cluster == 0)
  535.    {
  536.       TX_NEWLINE;
  537.       transmitString_F(PSTR(" No free cluster!"));
  538.       return;
  539.    }
  540.  
  541.    getSetNextCluster(prevCluster, SET, cluster);
  542. }            
  543.  
  544. getSetFreeCluster (NEXT_FREE, SET, cluster); //update FSinfo next free cluster entry
  545.  
  546. prevCluster = rootCluster; //root cluster
  547.  
  548. while(1)
  549. {
  550.    firstSector = getFirstSector (prevCluster);
  551.  
  552.    for(sector = 0; sector < sectorPerCluster; sector++)
  553.    {
  554.      SD_readSingleBlock (firstSector + sector);
  555.    
  556.  
  557.      for(i=0; i<bytesPerSector; i+=32)
  558.      {
  559.         dir = (struct dir_Structure *) &buffer[i];
  560.  
  561.         if(fileCreatedFlag)   //to mark last directory entry with 0x00 (empty) mark
  562.          {                       //indicating end of the directory file list
  563.            dir->name[0] = 0x00;
  564.            return;
  565.          }
  566.  
  567.         if((dir->name[0] == EMPTY) || (dir->name[0] == DELETED))  //looking for an empty slot to enter file info
  568.         {
  569.           for(j=0; j<11; j++)
  570.               dir->name[j] = fileName[j];
  571.           dir->attrib = ATTR_ARCHIVE;    //settting file attribute as 'archive'
  572.           dir->NTreserved = 0;            //always set to 0
  573.           dir->timeTenth = 0;            //always set to 0
  574.           dir->createTime = 0x9684;        //fixed time of creation
  575.           dir->createDate = 0x3a37;        //fixed date of creation
  576.           dir->lastAccessDate = 0x3a37;    //fixed date of last access
  577.           dir->writeTime = 0x9684;        //fixed time of last write
  578.           dir->writeDate = 0x3a37;        //fixed date of last write
  579.           dir->firstClusterHI = firstClusterHigh;
  580.           dir->firstClusterLO = firstClusterLow;
  581.           dir->fileSize = size;
  582.  
  583.           SD_writeSingleBlock (firstSector + sector);
  584.           fileCreatedFlag = 1;
  585.  
  586.           TX_NEWLINE;
  587.           TX_NEWLINE;
  588.           transmitString_F(PSTR(" File Created!"));
  589.  
  590.           freeMemoryUpdate (REMOVE, size); //updating free memory count in FSinfo sector
  591.          
  592.         }
  593.      }
  594.    }
  595.  
  596.    cluster = getSetNextCluster (prevCluster, GET, 0);
  597.  
  598.    if(cluster > 0x0ffffff6)
  599.    {
  600.       if(cluster == EOF)   //this situation will come when total files in root is multiple of (32*sectorPerCluster)
  601.       {  
  602.         cluster = searchNextFreeCluster(prevCluster); //find next cluster for root directory entries
  603.         getSetNextCluster(prevCluster, SET, cluster); //link the new cluster of root to the previous cluster
  604.         getSetNextCluster(cluster, SET, EOF);  //set the new cluster as end of the root directory
  605.       }
  606.  
  607.       else
  608.       {    
  609.         transmitString_F(PSTR("End of Cluster Chain"));
  610.         return;
  611.       }
  612.    }
  613.    if(cluster == 0) {transmitString_F(PSTR("Error in getting cluster")); return;}
  614.    
  615.    prevCluster = cluster;
  616.  }
  617.  
  618.  return;
  619. }
  620.  
  621.  
  622.  
  623. //***************************************************************************
  624. //Function: to search for the next free cluster in the root directory
  625. //          starting from a specified cluster
  626. //Arguments: Starting cluster
  627. //return: the next free cluster
  628. //****************************************************************
  629. unsigned long searchNextFreeCluster (unsigned long startCluster)
  630. {
  631.   unsigned long cluster, *value, sector;
  632.   unsigned char i;
  633.    
  634.       startCluster -=  (startCluster % 128);   //to start with the first file in a FAT sector
  635.     for(cluster =startCluster; cluster <totalClusters; cluster+=128)
  636.     {
  637.       sector = unusedSectors + reservedSectorCount + ((cluster * 4) / bytesPerSector);
  638.       SD_readSingleBlock(sector);
  639.       for(i=0; i<128; i++)
  640.       {
  641.          value = (unsigned long *) &buffer[i*4];
  642.          if(((*value) & 0x0fffffff) == 0)
  643.             return(cluster+i);
  644.       }
  645.     }
  646.  
  647.   return 0;
  648. }
  649.  
  650. //***************************************************************************
  651. //Function: to display total memory and free memory of SD card, using UART
  652. //Arguments: none
  653. //return: none
  654. //Note: this routine may take upto 15sec for 1GB card (@8MHz clock)
  655. //it tries to read from SD whether a free cluster count is stored, if it is stored
  656. //then it will return immediately. Otherwise it will count the total number of
  657. //free clusters, which takes time
  658. //****************************************************************************
  659. void memoryStatistics (void)
  660. {
  661. unsigned long totalMemory, freeMemory, freeClusters, totalClusterCount, cluster;
  662. unsigned long sector, *value;
  663. unsigned int i;
  664.  
  665. totalMemory = totalClusters * sectorPerCluster * bytesPerSector;
  666.  
  667. TX_NEWLINE;
  668. TX_NEWLINE;
  669. transmitString_F(PSTR("Total Memory: "));
  670.  
  671. displayMemory (totalMemory);
  672.  
  673. freeClusters = getSetFreeCluster (TOTAL_FREE, GET, 0);
  674. //freeClusters = 0xffffffff;  
  675.  
  676. if(freeClusters > totalClusters)
  677. {
  678.    freeClusterCountUpdated = 0;
  679.    freeClusters = 0;
  680.    totalClusterCount = 0;
  681.    cluster = rootCluster;  
  682.     while(1)
  683.     {
  684.       sector = unusedSectors + reservedSectorCount + ((cluster * 4) / bytesPerSector) ;
  685.       SD_readSingleBlock(sector);
  686.       for(i=0; i<128; i++)
  687.       {
  688.          value = (unsigned long *) &buffer[i*4];
  689.          if(((*value)& 0x0fffffff) == 0)
  690.             freeClusters++;;
  691.        
  692.          totalClusterCount++;
  693.          if(totalClusterCount == (totalClusters+2)) break;
  694.       }
  695.       if(i < 128) break;
  696.       cluster+=128;
  697.     }
  698. }
  699.  
  700. if(!freeClusterCountUpdated)
  701.   getSetFreeCluster (TOTAL_FREE, SET, freeClusters); //update FSinfo total free cluster entry
  702. freeClusterCountUpdated = 1;  //set flag
  703. freeMemory = freeClusters * sectorPerCluster * bytesPerSector;
  704. TX_NEWLINE;
  705. transmitString_F(PSTR(" Free Memory: "));
  706. displayMemory (freeMemory);
  707. TX_NEWLINE;
  708. }
  709.  
  710. //************************************************************
  711. //Function: To convert the unsigned long value of memory into
  712. //          text string and send to UART
  713. //Arguments: unsigned long memory value
  714. //return: none
  715. //************************************************************
  716. void displayMemory (unsigned long memory)
  717. {
  718.   unsigned char memoryString[] = "             Bytes"; //18 character long string for memory display
  719.   unsigned char i;
  720.   for(i=12; i>0; i--) //converting freeMemory into ASCII string
  721.   {
  722.     if(i == 5 || i == 9)
  723.     {
  724.        memoryString[i-1] = ',';
  725.        i--;
  726.     }
  727.     memoryString[i-1] = (memory % 10) | 0x30;
  728.     memory /= 10;
  729.     if(memory == 0) break;
  730.   }
  731.  
  732.   transmitString(memoryString);
  733. }
  734.  
  735. //********************************************************************
  736. //Function: to delete a specified file from the root directory
  737. //Arguments: pointer to the file name
  738. //return: none
  739. //********************************************************************
  740. void deleteFile (unsigned char *fileName)
  741. {
  742.   unsigned char error;
  743.  
  744.   error = convertFileName (fileName);
  745.   if(error) return;
  746.  
  747.   findFiles (DELETE, fileName);
  748. }
  749.  
  750. //********************************************************************
  751. //Function: update the free memory count in the FSinfo sector.
  752. //          Whenever a file is deleted or created, this function will be called
  753. //          to ADD or REMOVE clusters occupied by the file
  754. //Arguments: #1.flag ADD or REMOVE #2.file size in Bytes
  755. //return: none
  756. //********************************************************************
  757. void freeMemoryUpdate (unsigned char flag, unsigned long size)
  758. {
  759.   unsigned long freeClusters;
  760.   //convert file size into number of clusters occupied
  761.   if((size % 512) == 0) size = size / 512;
  762.   else size = (size / 512) +1;
  763.   if((size % 8) == 0) size = size / 8;
  764.   else size = (size / 8) +1;
  765.  
  766.   if(freeClusterCountUpdated)
  767.   {
  768.       freeClusters = getSetFreeCluster (TOTAL_FREE, GET, 0);
  769.       if(flag == ADD)
  770.          freeClusters = freeClusters + size;
  771.       else  //when flag = REMOVE
  772.          freeClusters = freeClusters - size;
  773.       getSetFreeCluster (TOTAL_FREE, SET, freeClusters);
  774.   }
  775. }
  776. //********************************************************************
  777. //Function: Read ADC Value
  778. //Arguments: ADC Channel
  779. //return: none
  780. //********************************************************************
  781. int readadc(uint8_t channel)
  782. {
  783.    ADMUX = channel;                // Select ADC Channel to multiplex, Reference to AREF
  784.    ADCSRA |= (1<<ADSC);           // Set ADSC bit to get the next conversion started
  785.    while(ADCSRA & (1<<ADSC)) {};  // Wait for ADC to finish
  786.    uint16_t result = ADCL;         // Read LSB first
  787.    uint16_t temp = ADCH;           // Read MSB next
  788.    result = result + (temp<<8);   // Shift MSB up 8 bits then add to LSB
  789. //   int cresult = result;
  790.    return result;
  791. }
  792.  
  793. //********************************************************************
  794. //Function: Write sampled data
  795. //Arguments: line
  796. //return: none
  797. //********************************************************************
  798. void sampleData (unsigned char *line)
  799. {  
  800. // Write time stamp
  801.   convertToAscii (line, 15, seconds, 2);      // Write seconds
  802.   convertToAscii (line, 12, minutes, 2);      // Write minutes
  803.   convertToAscii (line,  9, hours  , 2);      // Write hours
  804.   convertToAscii (line,  6, years  , 2);      // Write years
  805.   convertToAscii (line,  3, months , 2);      // Write monhts
  806.   convertToAscii (line,  0, days   , 2);      // Write days
  807.    
  808. // Write sampled data
  809.   convertToAscii (line, 18, digitala, 4);     // Write Digital channel 1
  810.   convertToAscii (line, 23, digitalb, 4);     // Write Digital channel 2  
  811.   convertToAscii (line, 28, readadc(1), 4);   // Write Analog channel 1
  812.   convertToAscii (line, 33, readadc(2), 4);   // Write Analog channel 2
  813.   convertToAscii (line, 38, readadc(3), 4);   // Write Analog channel 3
  814. }
  815.  
  816. //********************************************************************
  817. //Function: Convert a 10 bit number into a 2 or 4 character ascii string
  818. //Arguments: line, location of most significant digit, value to be formatted
  819. //return: none
  820. //********************************************************************
  821. void convertToAscii (unsigned char *line, unsigned int start, int val, int places)
  822. {  
  823.   unsigned int i;
  824.   int k = 0;
  825.  
  826.   for(i=0; i < places; i++){
  827.     line[start+i] = '0';
  828.     if(places == 4){
  829.       if(i == 0) k = 1000;
  830.       if(i == 1) k = 100;
  831.       if(i == 2) k = 10;
  832.       if(i == 3) k = 1;
  833.     }
  834.     else {
  835.       if(i == 0) k = 10;
  836.       if(i == 1) k = 1;
  837.     }
  838.     while(1){
  839.       if((val - k) < 0) break;
  840.       line[start+i]++;
  841.       val = val - k;
  842.     }
  843.   }
  844. }
  845.  
  846.  
  847. //******** END ****** www.dharmanitech.com *****
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement