⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 用ATmega8 做的MP3播放器
💻 C
📖 第 1 页 / 共 2 页
字号:
// gets part of a file
// this function is dumb and does not check for errors.
// dont use on its own
// used by fget & co.
void fat_get_file_section(FILE *stream, u16 size, u08 *data)
{ // determine the sector that we need to read and which dword defines our  next cluster address
  u16 myh = stream->file_current_clusterh;
  u16 myl = stream->file_current_clusterl;
  u08 i   = 0;

  myl += first_data_sectorl;
  if(myl < first_data_sectorl) myh++;
  // get the data
  MMC_get_part_sec_start(myh, myl,stream->file_offset,size);
  for(;i<size;i++) data[i] = MMC_get_sec_next();
  MMC_get_sec_stop();
  // fine
};


// used to get info from the current directoy
// modes :
//  FAT_FILENAME - 0x02 - find file by name
//  FAT_DIRNAME - 0x03 - find dir by name
//  FAT_FILENUM - 0x04 - find file by number 0 based
//  FAT_DIRNUM - 0x05 - find dir by number 0 based

bool fat_dir_ctl(u08 mode, FILE *stream, DIR *dir, u08* name, u08 count)
{
  // the sector that we are on
  u16 myhfat;
  u16 mylfat;
  u16 myh;
  u16 myl;
  u08 mysec = 0;
  // how many files/dirs were foud
  u08 index = 0;
  // is there data worth looking for in another sector ?
  u08 loop = 1;
  // how many entries were read from this sector
  u08 len = 0;

  myhfat = directory.dir_currenth;
  mylfat = directory.dir_currentl;

  do
  { myl = mylfat;
    myh = myhfat;

    // calc cluster to sectors
    cluster_to_sector(&myh, &myl);

    // add Data section offset
    myl += first_data_sectorl+mysec;
    if(myl < first_data_sectorl) myh++;

    // start getting the data from the mmc
    MMC_get_sec_start(myh, myl);
    // there are 16 directory entries in each directory sector
    // checkout the msdoc of fat for info
    len = 0;
    while (len < 16)
    { u08 tmp[32];
      u08 i;
      // get next entry
      for(i =0; i< 32; i++)
        tmp[i] = MMC_get_sec_next();

      if(tmp[0] == 0x00) loop = 0; // no more directory entries

      // make sure that there is an entry and that we want to process it and that it is valid
      if((tmp[0] > 0x0) && (tmp[0] != 0xE5))
      { // check if this is a long dir entry
        if ((tmp[11]&FAT_LONG_NAME) == FAT_LONG_NAME)
        {
#ifdef LFN_SUPPORT
          // is this the first entry
          if(tmp[0] > 0x40)
          { tmp[0]-= 0x40;
            for(tmp[2] = 0; tmp[2] < 13*LFN_MAX_BLOCK; tmp[2]++)
            { lfn_tmp[tmp[2]] = 0x00;
            };
          };
          if(tmp[0] <= LFN_MAX_BLOCK)
          { // we can use a unicode 0 as a tmp var
            tmp[2] = (tmp[0] - 1) * 13;
            for(i=1; i<10; i+=2)
            { lfn_tmp[tmp[2]++] = tmp[i];
            };
            for(i=14; i<31; i+=2)
            { if(i != 26) lfn_tmp[tmp[2]++] = tmp[i];
            };
          };
#endif
        }
        // check if it is a file
        else if(((tmp[11]&(FAT_DIRECTORY|FAT_VOL_ID)) == 0x00))
        { // do we want to print ?
          if(mode == FAT_PRINT)
          { /*
            printf("Filename: '");
            for(i=0; i<11; i++)
            { if(tmp[i] != ' ')
                printf("%c", tmp[i]);
              if(i==7) printf(".");
            }
            printf("'\n");
            */
          }
          else if((mode == FAT_FILENUM)&&(loop))
          { // is this the file we are looking for ?
            if(index == count)
            { // check if we are supposed to use a mask
              if(name)
              { if(fat_cmp_names(tmp, name, &name[8]))
                { fat_load_file_ptr(tmp, stream);
                  loop = 0;
                };
              }
              else
              { fat_load_file_ptr(tmp, stream);
                loop = 0;
              };
            }
            else
            { if(!name)
              { index++;
              }
              else
              { if(fat_cmp_names(tmp, name, &name[8]))
                { index++;
                };
              }
            };
          }
          else if(mode == FAT_FILENAME)
          { if(fat_cmp_names(tmp, name, &name[8]))
            { fat_load_file_ptr(tmp, stream);
              loop = 0;
            };
          };
#ifdef LFN_SUPPORT
          lfn_tmp[0] = 0x00;
#endif
        // check if this is a volume id
        }
        else if((tmp[11]&FAT_VOL_ID)==FAT_VOL_ID)
        { /*
            printf("Vol-ID: '");
            for(i=0; i<11; i++)
            { if(tmp[i] != ' ')
                printf("%c", tmp[i]);
            }
            printf("'\n");
          */
        }
        // check if this is a pointer to another directory
        else if ((tmp[11]&FAT_DIRECTORY)==FAT_DIRECTORY)
        { // do we want to print ?
          //printf("Entry is a dir\n");
          if(mode == FAT_PRINT)
          { /*
            printf("Dirname: '");
            for(i=0; i<11; i++)
            { if(tmp[i] != ' ')
                printf("%c", tmp[i]);
              if(i==7) printf(".");
            }
            printf("'\n");
            */
          }
          else if((mode == FAT_DIRNUM)&&(loop))
          { // is this the file we are looking for ?
            if(index == count)
            { // check if we are supposed to use a mask
              if(name)
              { if(fat_cmp_names(tmp, name, 0x00))
                { fat_load_dir_ptr(tmp, dir);
                  loop = 0;
                };
              }
              else
              { fat_load_dir_ptr(tmp,dir);
                loop = 0;
              };
            }
            else
            { if(!name)
              { index++;
              }
              else
              { if(fat_cmp_names(tmp, name, 0x00))
                { index++;
                };
              }
            };
          }
          else if((mode == FAT_DIRNAME)&&(loop))
          { if(fat_cmp_names(tmp, name, 0x00))
            { fat_load_dir_ptr(tmp, dir);
              loop = 0;
            };
          };
#ifdef LFN_SUPPORT
          lfn_tmp[0] = 0x00;
#endif
        };

      };
      // inc loop counter
      len++;
      //getch();
    };
    // stop the reading process+
    MMC_get_sec_stop();

    if (mysec < sec_per_clus-1)
      mysec++;
    else
    { FAT_get_next_clus_addr(&myhfat, &mylfat);
      mysec=0;
    }

    //loop = 0;
  } while((myhfat!=0x0fff)&&(mylfat!=0xfffd)&&(loop));

  // if we just did some directory listing, we always return true
  if(mode == FAT_DIRNAME)
    return true;

  // we were looking for some file/directory. if loop is true, no data was found
  if(loop)
    return false;

  return true;
};

/*------------------ FIO API LAYER --------------*/

// only the 'r' mode is supported so far
bool fopen(u08 *filename, u08 mode, FILE *stream)
{ if(mode=='r')
    return fat_dir_ctl(FAT_FILENAME, stream, 0x00, filename, 0);
  return false;
};

// only the 'r' mode is supported so far
bool fopenc(u08 count, u08 mode, u08 *mask, FILE *stream)
{ if(mode=='r')
    return fat_dir_ctl(FAT_FILENUM, stream, 0x00, mask, count);
  return false;
};

// closes a filestream this is not really neccesarry, but alot tidier
void fclose(FILE *stream)
{ stream->file_first_clusterl =
  stream->file_first_clusterh =
  stream->file_current_clusterl =
  stream->file_current_clusterh =
  stream->file_current_sector =
  stream->file_sizel =
  stream->file_sizeh =
  stream->file_offset = 0x00;
};



// has the end of the file been reached ?
bool feof(FILE *stream)
{ return (stream->file_current_clusterh==0x0fff) &&
          (stream->file_current_clusterl>=0xfff8);
};

// checks if a file is open
bool fisopen(FILE *stream)
{ return (stream->file_first_clusterl == 0x00) &&
          (stream->file_first_clusterh == 0x00) &&
          (stream->file_current_clusterl == 0x00) &&
          (stream->file_current_clusterh == 0x00) &&
          (stream->file_current_sector == 0x00) &&
          (stream->file_sizel == 0x00) &&
          (stream->file_sizeh == 0x00) &&
          (stream->file_offset == 0x00);
};

// gets data from a file
u08* fget(FILE *stream, u16 size)
{ // make sure the FILE is open
  if((stream->file_current_clusterh==0x0)&&(stream->file_current_clusterl==0x0)) return 0x00;
  // are we at the end of a sector ?
  if(stream->file_offset == 0x200)
  { // load next sector
    if (stream->file_current_sector >= sec_per_clus-1)
    { FAT_get_next_clus_addr(&stream->file_current_clusterh, &stream->file_current_clusterl);
      if(feof(stream)) return 0x00;
      stream->file_current_sector = 0;
    }
    else
    { stream->file_current_sector++;
    }
    stream->file_offset = 0x00;
  }
  // make sure we are not reading in more than the max data buffer
  if(size > FAT_RD_BUF_SIZE) size = FAT_RD_BUF_SIZE;
  // make sure we are not reading past the end of a file
  if((stream->file_sizeh == 0) && (stream->file_sizel < size)) size = stream->file_sizel;

  // is all the data in this sector? or do we have to split over two sectors
  if((stream->file_offset+size) < 0x200)
  { // all in one
    fat_get_file_section(stream, size, fat_buf);
    stream->file_offset += size;
  }
  else
  { // workout where we need to split
    u08 split_pos = 0x200 - stream->file_offset;
    size -= split_pos;
    // get first half
    fat_get_file_section(stream, split_pos, fat_buf);
    // get second half
    if (stream->file_current_sector >= sec_per_clus-1)
    { FAT_get_next_clus_addr(&stream->file_current_clusterh, &stream->file_current_clusterl);
      stream->file_current_sector = 0;
    }
    else
    { stream->file_current_sector++;
    }
    fat_get_file_section(stream, size, &fat_buf[split_pos]);
    stream->file_offset = size;
    size += split_pos;
  };
  // update the stream struct
  if(stream->file_sizel < size)
  { // save as we checked for zero earlier
    stream->file_sizeh--;
  };
  stream->file_sizel = size - stream->file_sizel;

  fat_buf[size] = '\0';
  return fat_buf;
};

bool fplay_sector(FILE *stream)
{ u16 myh = stream->file_current_clusterh;
  u16 myl = stream->file_current_clusterl;

  // make sure the FILE is open
  if((stream->file_current_clusterh==0x0)&&(stream->file_current_clusterl==0x0)) return false;
  // make sure, that we are not past the last cluster of the file
  if((stream->file_current_clusterh==0x0fff)&&(stream->file_current_clusterl>=0xfff8)) return false;

  cluster_to_sector(&myh, &myl);

  myl += first_data_sectorl;
  if(myl < first_data_sectorl) myh++;

  u16 length;
  u08 tmp;
  u08 sec;

  for(sec=0; sec<sec_per_clus; sec++)
  { // start getting the data
    MMC_get_sec_start(myh, myl);
    length=0;
    tmp = spi_io(0xff);
    // disable the MMC to receive data
    MMC_disable();
    while(length<512)
    { if((512%32) == 0) VS1001_WHILE_NEEDS_NO_DATA;
      VS_BSYNC_HI;
      outp(tmp, SPDR);    // send data
      NOP;
      NOP;
      NOP;
      VS_BSYNC_LO;
      // wait for data to be sent
      while(((inp(SPSR))&(1<<SPIF))== 0x00){};
      tmp = inp(SPDR);
      length++;
    };
    // enables the MMC to receive data again
    MMC_enable();
    // get the 2nd CRC bytes
    spi_io(0xff);
    // give enough time
    MMC_cleanup();
    myl++;
    if (myl==0) myh++;
  }
  FAT_get_next_clus_addr(&stream->file_current_clusterh, &stream->file_current_clusterl);
  return true;
};


// step into a subfolder of the current folder
// if dirname is null function sets the root folder
bool dir_enter(u08 *dirname, DIR *dir)
{ if(!dir) dir = &directory;
  // set a folder
  if(dirname)
  { return fat_dir_ctl(FAT_DIRNAME, 0x00, dir, dirname, 0);
  }
  //set root folder ?
  else
  { dir_root(dir);
    return true;
  };
}

// step into a subfolder of the current folder
bool dir_leave(DIR *dir)
{ u08 tmp[9] = "..      ";
  return dir_enter(tmp, dir);
};

// list the current directory
void dir_list(DIR *dir)
{ if(!dir) dir = &directory;
  fat_dir_ctl(FAT_PRINT, 0x00, 0x00, 0x00, 0);
}

// sets the dir to root
void dir_root(DIR *dir)
{ if(!dir) dir = &directory;
  dir->dir_currentl = 0x00;
  dir->dir_currenth = 0x00;
};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -