# fat32

FAT32 library for reading fat32 filesystem (beta version)

Author | Matthew Schinkel, copyright © 2009, all rights reserved.
Adapted-by |
Compiler | >=2.4k

Description

    this library reads files & folders from a fat32 formatted media
                 such as sd cards & hard disks. BETA VERSION!

Sources

    http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
    http://www.pjrc.com/tech/8051/ide/fat32.html
    http://en.wikipedia.org/wiki/File_Allocation_Table
    http://en.wikipedia.org/wiki/8.3_filename
    http://www.ntfs.com/fat-filenames.htm

Notes

    exFAT & fat16 are not supported. ONLY USE FAT32!
    Windows won't format a sd_card > 32gb with FAT32. Use a 3rd party software (or linux?)

Dependencies

- storage_drivers
- print
- format

## Summary

### Global variables/contants

- `var bit fat32_is_read_only at fat32_file_attrib : 0`
- `const bit _FAT32_GET = 0`
- `var dword fat32_file_cluster_address`
- `const byte FAT32_ENTRY_DELETED = 0xE5`
- `const bit _fat32_read = 0`
- `var word fat32_fat_begin`
- `var byte fat32_file_extension[3] at fat32_full_short_file_name[8]`
- `var byte fat32_file_attrib`
- `const _FAT32_ALL = 255`
- `var word _fat32_file_byte_count`
- `const byte FAT32_ENTRY_IS_PART_OF_LONG_NAME = 0x0F`
- `var byte fat32_file_attrib_filter = 0`
- `var bit fat32_init_ok = FALSE`
- `const byte FAT32_DIRECTORY = 0`
- `var bit fat32_is_directory at fat32_file_attrib : 4`
- `var dword _fat32_dir_last_cluster`
- `var dword fat32_file_size`
- `var bit _fat32_last_operation`
- `var bit fat32_filter_is_hidden at fat32_file_attrib_filter : 1`
- `const FAT32_PRINT_ALL = 0xFF`
- `var byte*FAT32_ENTRIES_MAX fat32_current_file_number`
- `var byte _fat32_file_cluster_address[4] at fat32_file_cluster_address`
- `var dword _fat32_dir_sectors`
- `var dword fat32_current_sector = 20`
- `const _FAT32_SHORT_NAME = 2`
- `var bit fat32_filter_is_read_only at fat32_file_attrib_filter : 0`
- `var bit fat32_is_hidden at fat32_file_attrib : 1`
- `const FAT32_PRINT_NUMBER = 2`
- `const _FAT32_CLUSTER_LOCATION = 16`
- `var byte fat32_file_name_length`
- `const byte FAT32_VALID_CHARACTERS[] = {`
- `var dword fat32_root_dir_first_cluster`
- `const _FAT32_EXTENSION = 4`
- `const _FAT32_ATTRIB = 8`
- `const FAT32_PRINT_TABLE = 16`
- `var dword _fat32_dir_fragment_count`
- `var bit fat32_filter_is_archive at fat32_file_attrib_filter : 5`
- `var bit fat32_file_has_long_name`
- `var bit fat32_is_archive at fat32_file_attrib : 5`
- `var bit fat32_filter_is_system at fat32_file_attrib_filter : 2`
- `var byte fat32_short_file_name[8] at fat32_full_short_file_name[0]`
- `var bit fat32_filter_is_directory at fat32_file_attrib_filter : 4`
- `var dword fat32_sectors_per_fat`
- `var byte _fat32_dir_cluster_address[4] at fat32_dir_cluster_address`
- `var bit fat32_is_volume_id at fat32_file_attrib : 3`
- `var dword _fat32_file_last_cluster`
- `var volatile dword fat32_current_dir_location`
- `var byte fat32_sectors_per_cluster`
- `const FAT32_PRINT_LONG_FILE_NAME = 1`
- `var word fat32_dir_file_count`
- `var word _fat32_file_fragment_count`
- `var dword fat32_current_cluster`
- `const _FAT32_LONG_NAME = 1`
- `const bit _FAT32_PUT = 1`
- `var bit fat32_filter_is_volume_id at fat32_file_attrib_filter : 3`
- `var bit fat32_is_system at fat32_file_attrib : 2`
- `var dword fat32_cluster_begin`
- `var byte fat32_full_short_file_name[11]`
- `const bit _fat32_write = 1`
- `const FAT32_PRINT_SIZE = 4`
- `var dword current_address = 0xFFFFFFFF`
- `var byte*3 _fat32_file_sector_count`
- `const FAT32_PRINT_ATTRIBUTES = 64`
- `const _FAT32_SIZE = 32`
- `const FAT32_PRINT_DATE = 32`
- `const byte FAT32_FILE = 1`
- `const FAT32_PRINT_CLUSTER = 8`
- `var word _fat32_fragment_number`

### Procedures

- `fat32_read_file_sector()`
- `fat32_read_file_sector_number(dword in file_sector_number)`
- `fat32_start_file_write()`
- `fat32_file_close()`
- `fat32_dir_set_size(dword in dir_size)`
- `fat32_cluster'put(dword in address, dword in value)`
- `fat32_file_entry_data(bit in file_or_dir, bit in get_put, byte in data_type)`
- `fat32_cluster_in_sector_buffer'put(byte in address, dword in value)`
- `fat32_entry_delete(byte*FAT32_ENTRIES_MAX in file_number)`
- `fat32_print_file_info(volatile byte out output_device, byte in options)`
- `fat32_read_file_info(byte*FAT32_ENTRIES_MAX in file_number)`
- `fat32_file_set_size(dword in file_size)`
- `fat32_file_remove(word in file_number)`
- `fat32_file_delete()`
- `fat32_write_file_sector()`
- `fat32_write_file_sector_number(dword in file_sector_number)`
- `fat32_print_directory(volatile byte out output_device, byte in options)`
- `fat32_print_sector_buffer_hex(volatile byte out device,word in bytes_per_line)`
- `fat32_init(byte in primary_partition_number)`
- `fat32_start_file_read()`

Private

- `_fat32_create_fat_clusters(dword in clusters_to_make, bit in file_or_dir)`
- `_fat32_read_dir_info()`
- `_fat32_read_dir_sector_number(dword in dir_sector_number)`
- `_fat32_set_size(bit in file_or_dir, dword in file_size)`
- `_fat32_remove_fat_clusters(dword in clusters_to_remove, bit in file_or_dir)`
- `_fat32_write_dir_sector_number(dword in dir_sector_number)`
- `_fat32_read_boot_sector(byte in partition_select)`
- `_fat32_read_fragments(dword in cluster_start, bit in file_or_dir)`

### Functions

- `fat32_file_open(byte*FAT32_ENTRIES_MAX in file_number) return bit`
- `fat32_cluster'get(dword in address) return dword`
- `fat32_file_create(byte in file_name[], byte in file_extension[3]) return byte`
- `fat32_cluster_in_sector_buffer'get(byte in address) return dword`
- `fat32_dir_create(byte in dirname[]) return byte`
- `fat32_cd(byte*FAT32_ENTRIES_MAX in file_number) return bit`
- `fat32_read_file_byte() return byte`
- `fat32_read_file_byte_address(dword in address) return byte`

## API details

### Global variables/contants

- `var bit fat32_is_read_only at fat32_file_attrib : 0`

  No documentation found

- `const bit _FAT32_GET = 0`

  No documentation found

- `var dword fat32_file_cluster_address`

      hold the location of the files start cluster after file_read_info()

- `const byte FAT32_ENTRY_DELETED = 0xE5`

      Reads where file names in the current dir are stored, and stores them
      into fat32_entry_location[]

- `const bit _fat32_read = 0`

  No documentation found

- `var word fat32_fat_begin`

      the sector location of the file alocation table for current partition

- `var byte fat32_file_extension[3] at fat32_full_short_file_name[8]`

      holds file extension after file_read_info()

- `var byte fat32_file_attrib`

      Create file fat32_file_attribute variables

- `const _FAT32_ALL = 255`

      GET IS OK

- `var word _fat32_file_byte_count`

      a byte counter within a sector

- `const byte FAT32_ENTRY_IS_PART_OF_LONG_NAME = 0x0F`

      entry has a few characters of a long file_name

- `var byte fat32_file_attrib_filter = 0`

      filter file attributes

- `var bit fat32_init_ok = FALSE`

      tells you if fat32 initalized ok or not.

- `const byte FAT32_DIRECTORY = 0`

  No documentation found

- `var bit fat32_is_directory at fat32_file_attrib : 4`

  No documentation found

- `var dword _fat32_dir_last_cluster`

  No documentation found

- `var dword fat32_file_size`

      holds file size after file_read_info()

- `var bit _fat32_last_operation`

      last operation read or write

- `var bit fat32_filter_is_hidden at fat32_file_attrib_filter : 1`

  No documentation found

- `const FAT32_PRINT_ALL = 0xFF`

  No documentation found

- `var byte*FAT32_ENTRIES_MAX fat32_current_file_number`

  No documentation found

- `var byte _fat32_file_cluster_address[4] at fat32_file_cluster_address`

  No documentation found

- `var dword _fat32_dir_sectors`

      holds dir size (in sectors) after _fat32_read_dir_info

- `var dword fat32_current_sector = 20`

      get a cluster from anywhere within the fat (as an array of dwords)

- `const _FAT32_SHORT_NAME = 2`

      OK

- `var bit fat32_filter_is_read_only at fat32_file_attrib_filter : 0`

  No documentation found

- `var bit fat32_is_hidden at fat32_file_attrib : 1`

  No documentation found

- `const FAT32_PRINT_NUMBER = 2`

  No documentation found

- `const _FAT32_CLUSTER_LOCATION = 16`

      OK

- `var byte fat32_file_name_length`

      holds the size of the long file_name

- `const byte FAT32_VALID_CHARACTERS[] = {`

  No documentation found

- `var dword fat32_root_dir_first_cluster`

      the location of the root dir's first cluster, (should be 2 only after init)

- `const _FAT32_EXTENSION = 4`

      OK

- `const _FAT32_ATTRIB = 8`

      OK

- `const FAT32_PRINT_TABLE = 16`

  No documentation found

- `var dword _fat32_dir_fragment_count`

  No documentation found

- `var bit fat32_filter_is_archive at fat32_file_attrib_filter : 5`

  No documentation found

- `var bit fat32_file_has_long_name`

      holds if the file name has a long file name after file_read_info()

- `var bit fat32_is_archive at fat32_file_attrib : 5`

  No documentation found

- `var bit fat32_filter_is_system at fat32_file_attrib_filter : 2`

  No documentation found

- `var byte fat32_short_file_name[8] at fat32_full_short_file_name[0]`

      holds file short name after file_read_info()

- `var bit fat32_filter_is_directory at fat32_file_attrib_filter : 4`

  No documentation found

- `var dword fat32_sectors_per_fat`

      sectors per fat (fat32_sectors_per_fat * (512/4) * fat32_sectors_per_cluster = sectors available)

- `var byte _fat32_dir_cluster_address[4] at fat32_dir_cluster_address`

  No documentation found

- `var bit fat32_is_volume_id at fat32_file_attrib : 3`

  No documentation found

- `var dword _fat32_file_last_cluster`

  No documentation found

- `var volatile dword fat32_current_dir_location`

      sector location of last dir read

- `var byte fat32_sectors_per_cluster`

      the number of sectors per cluster, usually 8

- `const FAT32_PRINT_LONG_FILE_NAME = 1`

      Print a file_name to an output device. Use the following constants as
      input options.

- `var word fat32_dir_file_count`

      number of files in current directory

- `var word _fat32_file_fragment_count`

      read fragments of a file or directory

- `var dword fat32_current_cluster`

      read fragment locations from fat, store in
      fat32_dir_fragments_start & fat32_dir_fragment_cluster_count arrays

- `const _FAT32_LONG_NAME = 1`

      Get or put file information such as file name, extension, attributes, etc
      of the currently opened file or directory
      hopefully will replace file_get_info
      FAT32_DIR = Current Directory
      FAT32_file = Currently selected file number

- `const bit _FAT32_PUT = 1`

      PUT/SAVE FILE INFO

- `var bit fat32_filter_is_volume_id at fat32_file_attrib_filter : 3`

  No documentation found

- `var bit fat32_is_system at fat32_file_attrib : 2`

  No documentation found

- `var dword fat32_cluster_begin`

      the location of the beginning of clusters (where files & folders data is)

- `var byte fat32_full_short_file_name[11]`

      holds full file short name (name & extension) after file_read_info()

- `const bit _fat32_write = 1`

  No documentation found

- `const FAT32_PRINT_SIZE = 4`

  No documentation found

- `var dword current_address = 0xFFFFFFFF`

      reads selected byte from a file. fragmented files work.
      slower then fat32_read_file() procedure, but user friendly.

- `var byte*3 _fat32_file_sector_count`

      other intarnal vars

- `const FAT32_PRINT_ATTRIBUTES = 64`

  No documentation found

- `const _FAT32_SIZE = 32`

      OK

- `const FAT32_PRINT_DATE = 32`

  No documentation found

- `const byte FAT32_FILE = 1`

  No documentation found

- `const FAT32_PRINT_CLUSTER = 8`

  No documentation found

- `var word _fat32_fragment_number`

      the fragment number being used

### Procedures

- `fat32_read_file_sector()`

      read one sector from a file starting at the beginning of the file.
      auto increments to next sector in file. fragmented files work.
      requires: fat32_start_file_read(fat32_file_location), fat32_stop_file_read()
      faster then fat32_read_file_sector_number() procedure

- `fat32_read_file_sector_number(dword in file_sector_number)`

      reads selected sector from a file. fragmented files work.
      slower then fat32_read_file_sector() procedure, but user friendly.

- `fat32_start_file_write()`

      Start writing to a file

- `fat32_file_close()`

      close the currently opened file.

- `fat32_dir_set_size(dword in dir_size)`

      Sets the size of the currently opened directory

- `fat32_cluster'put(dword in address, dword in value)`

  No documentation found

- `fat32_file_entry_data(bit in file_or_dir, bit in get_put, byte in data_type)`

  No documentation found

- `fat32_cluster_in_sector_buffer'put(byte in address, dword in value)`

      get a cluster from the sector buffer (as an array of dwords)

- `fat32_entry_delete(byte*FAT32_ENTRIES_MAX in file_number)`

      Delete a fat32 directory entry. not finnished yet.
      requires dir refresh with _fat32_read_dir_info() after, otherwise
      file will still show in dir listing.

- `fat32_print_file_info(volatile byte out output_device, byte in options)`

  No documentation found

- `fat32_read_file_info(byte*FAT32_ENTRIES_MAX in file_number)`

      reads file info such as file_name, file size, filelocation, etc. into memory.

- `fat32_file_set_size(dword in file_size)`

      Sets the size of the currently opened file

- `fat32_file_remove(word in file_number)`

      not working, it's on the todo list

- `fat32_file_delete()`

      Delete a file. not finnished yet.
      requires dir refresh with _fat32_read_dir_info() after, otherwise
      file will still show in dir listing.

- `fat32_write_file_sector()`

      write one sector to a file starting at the beginning of the file.
      auto increments to next sector in file. fragmented files work.
      requires: fat32_start_file_write(fat32_file_location), fat32_stop_file_write
      faster then fat32_write_file_sector_number() procedure

- `fat32_write_file_sector_number(dword in file_sector_number)`

      writes selected sector to a file. fragmented files work.
      slower then fat32_write_file_sector() procedure, but user friendly.

- `fat32_print_directory(volatile byte out output_device, byte in options)`

      print the current directory to an output device. Use same options as
      in fat32_print_file_info

- `fat32_print_sector_buffer_hex(volatile byte out device,word in bytes_per_line)`

      print the sector buffer

- `fat32_init(byte in primary_partition_number)`

      initalize fat32

- `fat32_start_file_read()`

      Start reading a file

Private

- `_fat32_create_fat_clusters(dword in clusters_to_make, bit in file_or_dir)`

      Creates clusters for a file or directory

- `_fat32_read_dir_info()`

  No documentation found

- `_fat32_read_dir_sector_number(dword in dir_sector_number)`

      reads selected sector from a directory.
      fragmented dirs should work (not tested)

- `_fat32_set_size(bit in file_or_dir, dword in file_size)`

      Sets the size of the current file or directory

- `_fat32_remove_fat_clusters(dword in clusters_to_remove, bit in file_or_dir)`

      Removes clusters for a file or directory

- `_fat32_write_dir_sector_number(dword in dir_sector_number)`

      writes selected sector to a directory.
      fragmented dirs should work (not tested)

- `_fat32_read_boot_sector(byte in partition_select)`

      Reads a fat32 boot sector to get the location of the root directory
      and FAT Location on the media for the partition selected.
      Only primary partitions are supported. Secondary partitions are not.

- `_fat32_read_fragments(dword in cluster_start, bit in file_or_dir)`

  No documentation found

### Functions

- `fat32_file_open(byte*FAT32_ENTRIES_MAX in file_number) return bit`

      check if file is ok to start reading, returns 1 = success, 0 = not a file

- `fat32_cluster'get(dword in address) return dword`

      put a cluster into anywhere within the fat (as an array of dwords)

- `fat32_file_create(byte in file_name[], byte in file_extension[3]) return byte`

      create a file with a size of 0 bytes in the current directory.
      Set fat32_attrib before running this procedure
      If there is a file currently opened, it will be closed.
      not for directories. see fat32_dir_create()

- `fat32_cluster_in_sector_buffer'get(byte in address) return dword`

      put a cluster into the sector buffer (as an array of dwords)

- `fat32_dir_create(byte in dirname[]) return byte`

      Creates a directory.
      If a file was open previously, it will be closed.
      dir can hold up to 2048 short file names (65536/32), if no long file names.
      I have not tested adding more then that.
      For now, you may change the line "fat32_set_file_size(65536)" to suit your
      needs.

- `fat32_cd(byte*FAT32_ENTRIES_MAX in file_number) return bit`

      change directory, returns 1 = success, 0 = not a directory

- `fat32_read_file_byte() return byte`

      read one byte from a file starting at the beginning of the file.
      auto increments to next byte in file. fragmented files work.
      requires: fat32_start_file_read(fat32_file_location), fat32_stop_file_read()
      faster then fat32_read_file_address() procedure

- `fat32_read_file_byte_address(dword in address) return byte`

  No documentation found

## Related samples

Here are the list of samples which use this library:

16f18857 | 16f18857_glcd_ili9341_fat32_sd_card.jal
18f26j50 | 18f26j50_fat32_sd_card.jal
18f4525 | 18f4525_mp3_decoder_vs1053b_pata_hard_disk.jal
18f4525 | 18f4525_fat32_sd_card.jal
18f4525 | 18f4525_mp3_decoder_vs1053b_sd_card.jal
18f4525 | 18f4525_fat32_pata_hard_disk.jal
18f4620 | 18f4620_mp3_decoder_vs1053b_pata_hard_disk.jal
18f4620 | 18f4620_mp3_decoder_vs1053b_sd_card.jal
18f4620 | 18f4620_fat32_sd_card.jal
18f4620 | 18f4620_fat32_pata_hard_disk.jal
18f67j50 | 18f67j50_fat32_pata_hard_disk.jal
18f67j50 | 18f67j50_fat32_sd_card.jal
18f67j50 | 18f67j50_fat32_usb_msd_pata_hard_disk.jal
18f67j50 | 18f67j50_mp3_decoder_vs1053b_pata_hard_disk.jal
18f67j50 | 18f67j50_mp3_decoder_vs1053b_sd_card.jal
18f67j50 | 18f67j50_fat32_usb_msd_sd_card.jal
18f67j60 | 18f67j60_fat32_sd_card.jal