Revision: 1501 Author: [email protected] Date: Wed Nov 25 00:01:04 2009 Log: added FAT32 with example 18f452_fat32_sd_card.jal into include\filesystem, let me know if it should be moved to another folder. http://code.google.com/p/jallib/source/detail?r=1501
Added: /trunk/include/filesystem /trunk/include/filesystem/fat32.jal /trunk/sample/18f452_fat32_sd_card.jal Modified: /trunk/sample/16f877_sd_card.jal /trunk/sample/18f452_sd_card.jal ======================================= --- /dev/null +++ /trunk/include/filesystem/fat32.jal Wed Nov 25 00:01:04 2009 @@ -0,0 +1,1173 @@ +-- Title: FAT32 library for reading fat32 filesystem +-- Author: Matthew Schinkel, copyright (c) 2009, all rights reserved. +-- Adapted-by: +-- Compiler: >=2.4k +-- +-- This file is part of jallib (http://jallib.googlecode.com) +-- Released under the ZLIB license (http://www.opensource.org/licenses/zlib-license.html) +-- +-- Description: this library reads files & folders from a fat32 formatted media +-- such as sd cards & hard disks. +-- +-- 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 +-- +-- Notes: +-- This lib does not create filename's on fat32 partitions, although it may +-- in the future. Please see this article http://www.desktoplinux.com/news/NS4980952387.html?kc=rss +-- before you think about implementing writing of filenames into your project. +-- + +-- known bugs: +-- must get rid of create_dword procedure + +------- GENERAL SETTINGS & VARS ------- + +const FAT32_DIR_FRAGMENTS_TO_ALLOW = 10 -- (0 = you must have a defragmented media), usually directories are fragmented. + -- uses 6 bytes memory per fragment allowed + -- windows defrag does not defragment directories. +const FAT32_FILE_FRAGMENTS_TO_ALLOW = 10 -- (0 = you must have a defragmented media) + -- uses 8 bytes memory per fragment allowed + +-- vars you can read info from +var dword fat32_file_size -- holds file size after file_read_info() +var byte file_ext[3] -- holds file extension after file_read_info() +var word fat32_dir_file_count -- number of files in current directory + +var dword fat32_root_dir -- sector location of the root dir +var dword fat32_current_dir_location -- sector location of last dir read +var dword fat32_fat_begin -- the location of the file alocation table for current partition +var byte fat32_sectors_per_cluster -- the number of sectors per cluster, usually 8 +var dword fat32_root_dir_first_cluster -- the location of the root dir's first cluster, should be 2 +var dword fat32_file_location -- holds file location after file_read_info() +var dword fat32_file_cluster -- file's start cluster number after file_read_info() +var dword fat32_cluster_begin -- the location of the beginning of clusters (where files & folders data is) + +-- Create file fat32_attribute variables +var byte fat32_attrib +var bit fat32_is_read_only at fat32_attrib : 0 +var bit fat32_is_hidden at fat32_attrib : 1 +var bit fat32_is_system at fat32_attrib : 2 +var bit fat32_is_volume_id at fat32_attrib : 3 +var bit fat32_is_directory at fat32_attrib : 4 +var bit fat32_is_archive at fat32_attrib : 5 + +-- filter file attributes +var byte fat32_attrib_filter +var bit fat32_filter_is_read_only at fat32_attrib_filter : 0 +var bit fat32_filter_is_hidden at fat32_attrib_filter : 1 +var bit fat32_filter_is_system at fat32_attrib_filter : 2 +var bit fat32_filter_is_volume_id at fat32_attrib_filter : 3 +var bit fat32_filter_is_directory at fat32_attrib_filter : 4 +var bit fat32_filter_is_archive at fat32_attrib_filter : 5 +-- you may change these filters here or also modify them in your main program +-- filters out unwanted file types +fat32_filter_is_read_only = FALSE +fat32_filter_is_hidden = FALSE +fat32_filter_is_system = FALSE +fat32_filter_is_volume_id = FALSE +fat32_filter_is_directory = FALSE +fat32_filter_is_archive = FALSE + +if (DATA_MEDIA == PATA_HARD_DISK) then + -- hard disk procedures + ALIAS fat32_start_read is pata_hd_start_read -- get hard disk ready for reading + ALIAS fat32_raw_read is pata_hd_read_data -- read one word from hard disk + ALIAS fat32_read_pulse is pata_hd_read_pulse -- go forward 2 bytes in current sector + ALIAS fat32_stop_read is pata_hd_stop_read -- tell hard disk we are done reading + -- hard disk vars + ALIAS fat32_word_count is pata_hd_word_count -- number of words read from current sector (byte var) +elsif DATA_MEDIA == SD_CARD then + -- sd card procedures + ALIAS fat32_start_read is sd_start_read -- get sd card ready for reading + ALIAS fat32_raw_read is sd_read_data -- read one word from sd card + ALIAS fat32_read_pulse is sd_read_pulse -- go forward 2 bytes in current sector + ALIAS fat32_stop_read is sd_stop_read -- tell sd card we are done reading + -- sd card vars + ALIAS fat32_word_count is sd_word_count -- number of words read from current sector (byte var) +end if + +-- choose the max filename length (uses ram space) +CONST BYTE FAT32_FILENAME_SIZE = 100 -- choose max filename size. if a filename is longer the this, beginning chars will be cut. short filenames are 12 bytes. +var byte LONGNAMELOCATION = 0 -- The start location for the filename if you are using eeprom or external memory source + +-- "file location list" +-- choose max number of files, choose highest entry address (filename's address). +-- eg. chosen -> FAT32_ENTRIES_MAX = 1, FAT32_FILES_MAX = 30 and there are 3 files A, B & C all in c:\ +-- File A is in sector 0, entry 6. file B is in sector 4, entry 2. file C is in sector 50, entry 2. +-- file A is entry address 0*16 + 6 = 6, file B is entry address 4*16 + 2 = 64, file C is entry address 50*16 + 2 = 802 +-- therefore, file C is out of range and will not be accessable due to fragmentation of the directory structure. +-- memory space required is byte*1 times 30 = 30bytes +-- the theoretical max number of files for this config is 256 if +-- there have been no deleted files and all names are short filenames. +-- if you choose FAT32_ENTRIES_MAX = 2 you will use 2 times 30 = 60bytes. If it multiply's + +-- bug, <= 26 doesn't work at read_file_info +const word FAT32_FILES_MAX = 100 -- the max number of files allowed in a directory, should not exceed highest entry address +;const byte FAT32_ENTRIES_MAX = 1 -- highest file entry address can be 256 +const byte FAT32_ENTRIES_MAX = 2 -- highest file entry address can be 65535 +;var byte*FAT32_ENTRIES_MAX entry_location[FAT32_FILES_MAX] -- we will use large_array library instead + +-- Use internal memory for file location list. FALSE IS NOT AVAILABLE YET. +-- external memory will later be used if you want to have a large amount +-- of files in a directory. +const bit FAT32_USE_INTERNAL_MEMORY = TRUE +IF FAT32_USE_INTERNAL_MEMORY == TRUE THEN + + -- Setup a large array for storing sector data, This is where filename locations are stored + const dword LARGE_ARRAY_1_SIZE = FAT32_FILES_MAX -- choose number of array variables + const dword LARGE_ARRAY_1_VARIABLE_SIZE = FAT32_ENTRIES_MAX -- choose bytes size of variables + include large_array_1 -- include the array library + ALIAS entry_location is large_array_1 +elsif FAT32_USE_INTERNAL_MEMORY == FALSE THEN + +-- work in progress +; -- note, external SPI memory must be on different SPI bus if using sd_card lib at the moment. +; if FAT32_ENTRIES_MAX == 1 then +; ALIAS entry_location is sram_23K256_byte -- Use as a 32K byte array +; elsif FAT32_ENTRIES_MAX == 2 then +; ALIAS entry_location is sram_23K256_word -- Use as a 16K word array +; elsif FAT32_ENTRIES_MAX == 4 then +; ALIAS entry_location is sram_23K256_dword -- Use as a 8K dword array +; end if + + -- for later use when writing sectors +; -- Setup a large array for storing sector data, This is where filename locations are stored +; const dword ARRAY_SIZE = 512 -- choose number of array variables +; const dword ARRAY_VARIABLE_SIZE = 1 -- choose bytes size of variables +; include large_array -- include the array library +; ALIAS fat32_sector_data is large_array_1 + +END IF + + +------- procedures ------- + + +-- ---------------------------------------------------------------------------- +-- choose a memory source to store 1 filename +-- ---------------------------------------------------------------------------- +const bit FAT_32_FILENAME_IN_EEPROM = TRUE -- PIC eeprom is slow, loads filenames slow, false = use internal memory +if FAT_32_FILENAME_IN_EEPROM == FALSE then -- use eeprom memory + ALIAS fat32_write_filename is data_eeprom_write -- alias the eeprom write rocedure + ALIAS fat32_get_filename is data_eeprom_read -- alias the eeprom read procedure +else -- use internal memory + var byte filename[FAT32_FILENAME_SIZE] -- make an array to hold filename characters + procedure fat32_write_filename(byte in address, byte in data1) is -- make procedure to store filename characters + if address < FAT32_FILENAME_SIZE then -- make sure we don't go over array size + filename[address] = data1 -- store 1 character/byte of filename at address + end if + end procedure + procedure fat32_get_filename(byte in address, byte out data1) is -- make procedure to read filename characters + if address < FAT32_FILENAME_SIZE then -- make sure we don't go over array size + data1 = filename[address] -- get 1 character/byte of filename at address + else + data1 = 0x00 -- if over max array size, send byte 0x00 + end if + end procedure +end if + +-- ---------------------------------------------------------------------------- +-- you can modify this and fat32_write_entry, fat32_read_entry procedures to +-- use internal memory or an external memory source. +-- define where to store the filename entry location list. +-- these procedures may get removed. +-- ---------------------------------------------------------------------------- +procedure fat32_write_entry(word in address, byte*FAT32_ENTRIES_MAX in entry_data) is + if FAT32_USE_INTERNAL_MEMORY == TRUE then + entry_location [address] = entry_data + else + -- your external memory source code goes here + end if +end procedure + +procedure fat32_read_entry(word in address, byte*FAT32_ENTRIES_MAX out entry_data) is + if FAT32_USE_INTERNAL_MEMORY == TRUE then + entry_data = entry_location [address] + else + -- your external memory source code goes here + end if +end procedure + + + +-- ---------------------------------------------------------------------------- +-- creates a dword from 4 bytes +-- old procedure, needs to be fixed or removed +-- ---------------------------------------------------------------------------- +procedure fat32_create_dword(byte in val4, byte in val3, byte in val2, byte in val1, dword out result1) is + var dword dval4, dval3, dval2, dval1 + dval4 = val4 + dval3 = val3 + dval2 = val2 + dval1 = val1 + result1 = dval4 * 0x1000000 + dval3 * 0x10000 + dval2 * 0x100 + dval1 +end procedure + +-- Send dword via serial port (for troubleshooting only) +procedure _fat32_send_dword(DWORD in dval1) is + var byte dval2[4] at dval1 + serial_hw_write (dval2[3]) + serial_hw_write (dval2[2]) + serial_hw_write (dval2[1]) + serial_hw_write (dval2[0]) +end procedure + +-- ---------------------------------------------------------------------------- +-- 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. +-- ---------------------------------------------------------------------------- +procedure fat32_read_boot_sector(byte in partition_select) is + -- variables + var byte partition_lba_begin1,partition_lba_begin2,partition_lba_begin3,partition_lba_begin4 + var byte byte_per_sector1, byte_per_sector2 -- always 200h = 512 + var byte reserved_sectors_1, reserved_sectors_2 -- usually 20h (may only need var reserved_sectors_1) + var byte number_of_fats -- always 2 + var byte sec_per_fat1, sec_per_fat2, sec_per_fat3, sec_per_fat4 -- usually 2 (may only need var sec_per_fat1) + var byte fat32_root_dir_first_cluster_1, fat32_root_dir_first_cluster_2, fat32_root_dir_first_cluster_3, fat32_root_dir_first_cluster_4 + var dword z + var dword reserved_sectors + var dword partition_lba_begin, sec_per_fat + + -- check if there is a master boot record, removable media does not have an MBR. + fat32_start_read (0)-- start read at sector 0 (master boot record) + fat32_raw_read (partition_lba_begin,z) + fat32_stop_read() -- finnished reading sector, set media idle + + if partition_lba_begin == 0xEB then + partition_lba_begin = 0 + else + fat32_start_read (0) -- start read at sector 0 (Master Boot Record) + fat32_read_pulse (227) + fat32_read_pulse ((partition_select - 1)* 16) -- select the partition number + fat32_raw_read (partition_lba_begin1, partition_lba_begin2) -- get fat of selected partition location - 3f 00 00 00 - lba1/lba2/lba3/lba4 - h3f = 63 + fat32_raw_read (partition_lba_begin3, partition_lba_begin4) + ;fat32_read_pulse (27 - ((partition_select - 1)* 16) ) -- get to end of sector + fat32_stop_read() -- finnished reading sector, set media idle + + fat32_create_dword (partition_lba_begin4, partition_lba_begin3, partition_lba_begin2, partition_lba_begin1, partition_lba_begin) -- get partition volume id location + + end if + + fat32_start_read (partition_lba_begin) -- start read at sector at volume id location + + -- If the program gets stuck here, there may be an issue with your partition. + -- removable media has a different MBR and is not supported yet. + fat32_read_pulse (5) + fat32_raw_read (z, byte_per_sector1) -- bytes per sector should be 02 00 = 512 + fat32_raw_read (byte_per_sector2, fat32_sectors_per_cluster) + fat32_raw_read (reserved_sectors_1, reserved_sectors_2) -- reserved sectors + + fat32_raw_read (number_of_fats, z) -- number_of_fats should be 2 + fat32_read_pulse (9) + fat32_raw_read (sec_per_fat1, sec_per_fat2) + fat32_raw_read (sec_per_fat3, sec_per_fat4) + + fat32_read_pulse (2) + fat32_raw_read (fat32_root_dir_first_cluster_1, fat32_root_dir_first_cluster_2) -- root dir first cluster usually = 00 00 00 02 + fat32_raw_read (fat32_root_dir_first_cluster_3, fat32_root_dir_first_cluster_4) + + fat32_stop_read() -- finnished reading sector, set media idle + -- you can send the following information to your pc + ;send_word (fat1, fat2) ; 00 3f + ;send_word (fat3, fat4) ; 00 00 + ;send_word (0xff, 0xff) ; + ;send_word (byte_per_sector2, byte_per_sector1) ; 02 00 + ;send_word (0xff, fat32_sectors_per_cluster) ; 08 + ;send_word (0xff, reserved_sectors_2) ; 26 + ;send_word (reserved_sectors_1, 0xff) ; 00 + ;send_word (number_of_fats, 0xff) ; 02 + ;send_word (sec_per_fat4, sec_per_fat3) ;00 00 + ;send_word (sec_per_fat2, sec_per_fat1) ;2f e5 + ;send_word (0xff, fat32_root_dir_first_cluster_4) ; 02 + ;send_word (fat32_root_dir_first_cluster_3, fat32_root_dir_first_cluster_2) ;00 00 + ;send_word (fat32_root_dir_first_cluster_1, 0xff) ;00 ff + + ;example output using my drive + ;3f 00 00 00 ff ff 02 00 ff 08 ff 00 26 ff 02 ff 00 00 2f e5 ff 00 00 00 02 ff + + + -- get root dir first cluster (usually 00 00 00 02) + fat32_create_dword (fat32_root_dir_first_cluster_4, fat32_root_dir_first_cluster_3, fat32_root_dir_first_cluster_2, fat32_root_dir_first_cluster_1, fat32_root_dir_first_cluster) + + -- get fat begin + fat32_create_dword (0, 0, reserved_sectors_2, reserved_sectors_1, reserved_sectors) -- put reserved sectors into dword + fat32_fat_begin = partition_lba_begin + reserved_sectors + + -- get cluster begin + fat32_create_dword (sec_per_fat4, sec_per_fat3, sec_per_fat2, sec_per_fat1, sec_per_fat) -- put into dword + fat32_root_dir = partition_lba_begin + reserved_sectors + (number_of_fats * sec_per_fat) + + -- you can send the following information to your pc + ;send_word (0xff, 0xff) + ;_fat32_send_dword (fat) ;00 00 00 3f + ;_fat32_send_dword (reserved_sectors) ;00 00 00 26 + ;_fat32_send_dword (fat32_fat_begin) ;00 00 00 65 + ;send_word (0xff, 0xff) + ;_fat32_send_dword (sec_per_fat) ;00 00 2f e5 + ;_fat32_send_dword (fat32_root_dir) ;00 00 60 2f + ;send_word (0xff, 0xff) + + ;example output using my drive + ;ff ff 00 00 00 3f 00 00 00 26 00 00 00 65 ff ff 00 00 2f e5 00 00 60 2f ff ff + + fat32_cluster_begin = fat32_root_dir - (2 * 8) + fat32_current_dir_location = fat32_root_dir -- same as cluster_begin + + fat32_file_cluster = fat32_root_dir_first_cluster +end procedure + + + +-- ---------------------------------------------------------------------------- +-- read fragment locations from fat, store in +-- fat32_dir_fragments_start & fat32_dir_fragment_cluster_count arrays +-- ---------------------------------------------------------------------------- +const byte FAT32_DIRECTORY = 0 +CONST BYTE FAT32_FILE = 1 +if FAT32_DIR_FRAGMENTS_TO_ALLOW > 0 then + -- start cluster location of each directory fragment + var dword fat32_dir_fragments_start[FAT32_DIR_FRAGMENTS_TO_ALLOW] + -- count clusters that are next to eachother, max 32 if byte (256/8), var fat32_dir_count_3 must be same (default byte) + var byte fat32_dir_fragment_cluster_count[FAT32_DIR_FRAGMENTS_TO_ALLOW] + + -- start cluster location of each file fragment + var dword fat32_file_fragments_start[FAT32_FILE_FRAGMENTS_TO_ALLOW] + -- count sectors that are next to eachother, max fragment size is 4.19 megabites if word, 274.878 gb if dword, var fat32_file_count_3 must be same (default dword) + var dword fat32_file_fragment_cluster_count[FAT32_FILE_FRAGMENTS_TO_ALLOW] + + procedure fat32_read_fragments(dword in dir_cluster_start, bit in file_or_dir) is + if file_or_dir == FAT32_DIRECTORY then + var byte fat32_dir_fragments_start_count = 0 + var byte cluster_location_in_sector + var dword current_cluster = dir_cluster_start + var bit done = false + var dword custers_sector + var byte custers_sector_array[4] at custers_sector + var byte fat32_dir_count_3 = 1 + + -- next cluster variables + var byte next_cluster_array[4] + var byte in_0, in_1, in_2, in_3 + var dword next_cluster at next_cluster_array + + var byte current_cluster_array[4] at current_cluster + + fat32_dir_fragments_start[0] = dir_cluster_start -- store the first cluster's start location in first array value + + fat32_dir_fragments_start_count = fat32_dir_fragments_start_count + 1 -- increment fat32_dir_fragments_start address + + while done == FALSE loop + + current_cluster = current_cluster << 1 + + custers_sector_array[0] = current_cluster_array[1] + custers_sector_array[1] = current_cluster_array[2] + custers_sector_array[2] = current_cluster_array[3] + custers_sector_array[3] = 0 + + cluster_location_in_sector = current_cluster_array[0] + + current_cluster = current_cluster >> 1 + + -- for troubleshooting only + ;_fat32_send_dword (custers_sector) + ;_fat32_send_dword (cluster_location_in_sector) + + + fat32_start_read (fat32_fat_begin + custers_sector) -- go to the fat's sector where the first cluster value is located + fat32_read_pulse (cluster_location_in_sector) -- go to the location of the value in the sector + + -- get the location of the next cluster + fat32_raw_read (in_0, in_1) -- read 2 data bytes + fat32_raw_read (in_2, in_3) -- read 2 data bytes + + -- put it into a dword + next_cluster_array[0] = in_0 + next_cluster_array[1] = in_1 + next_cluster_array[2] = in_2 + next_cluster_array[3] = in_3 + + -- for troubleshooting only + ;_fat32_send_dword (current_cluster) + ;_fat32_send_dword (next_cluster) + ;send_word (0xAA, 0xAA) + + -- store number of clusters that are beside eachother + fat32_dir_fragment_cluster_count[fat32_dir_fragments_start_count - 1] = 1 + + if next_cluster == 0x0F_FF_FF_FF then -- exit if the file is only 1 cluster + done = TRUE + end if + + while done == FALSE loop + if current_cluster + 1 == next_cluster then -- if no fragmentation + while current_cluster + 1 == next_cluster loop + current_cluster = next_cluster -- increment since we read the next cluster, no fragmentation + + -- get the location of the next cluster + fat32_raw_read (in_0, in_1) -- read 2 data bytes + fat32_raw_read (in_2, in_3) -- read 2 data bytes + + -- put it into a dword + next_cluster_array[0] = in_0 + next_cluster_array[1] = in_1 + next_cluster_array[2] = in_2 + next_cluster_array[3] = in_3 + + -- store number of clusters that are beside eachother + fat32_dir_count_3 = fat32_dir_count_3 + 1 + fat32_dir_fragment_cluster_count[fat32_dir_fragments_start_count - 1] = fat32_dir_count_3 + end loop + elsif next_cluster == 0x0F_FF_FF_FF then -- if end of clusters + done = TRUE -- we are done, quit all loops + else -- if fragmentation + fat32_dir_fragments_start[fat32_dir_fragments_start_count] = next_cluster -- store the location of the start of the next fragment + fat32_dir_fragments_start_count = fat32_dir_fragments_start_count + 1 -- increment fat32_dir_fragments_start address + current_cluster = next_cluster + + -- for troubleshooting only + ;_fat32_send_dword (current_cluster) + + exit loop -- exit this loop and go to the next fragment + end if + + end loop + fat32_stop_read() -- stop reading media + end loop + + -- set the rest of the values to 0x0F_FF_FF_FF + for FAT32_DIR_FRAGMENTS_TO_ALLOW - fat32_dir_fragments_start_count loop + fat32_dir_fragments_start[fat32_dir_fragments_start_count] = 0xFF_FF_FF_FF + ;fat32_dir_fragment_cluster_count[fat32_dir_fragments_start_count] = 0xFF + fat32_dir_fragments_start_count = fat32_dir_fragments_start_count + 1 + end loop + + else + + -- same as above but renamed variables to fat32_file_fragments_start, fat32_file_fragments_start_count + -- finds fragments in files + var byte fat32_file_fragments_start_count = 0 + var byte cluster_location_in_sector + var dword current_cluster = dir_cluster_start + var bit done = false + var dword custers_sector + var byte custers_sector_array[4] at custers_sector + var dword fat32_file_count_3 = 1 + + -- next cluster variables + var byte next_cluster_array[4] + var byte in_0, in_1, in_2, in_3 + var dword next_cluster at next_cluster_array + + var byte current_cluster_array[4] at current_cluster + + fat32_file_fragments_start[0] = dir_cluster_start -- store the first cluster's start location in first array value + fat32_file_fragments_start_count = fat32_file_fragments_start_count + 1 -- increment fat32_file_fragments_start address + + while done == FALSE loop + + current_cluster = current_cluster << 1 + + custers_sector_array[0] = current_cluster_array[1] + custers_sector_array[1] = current_cluster_array[2] + custers_sector_array[2] = current_cluster_array[3] + custers_sector_array[3] = 0 + + cluster_location_in_sector = current_cluster_array[0] + + current_cluster = current_cluster >> 1 + + -- for troubleshooting only + ;_fat32_send_dword (custers_sector) + ;_fat32_send_dword (cluster_location_in_sector) + + + fat32_start_read (fat32_fat_begin + custers_sector) -- go to the fat's sector where the first cluster value is located + fat32_read_pulse (cluster_location_in_sector) -- go to the location of the value in the sector + + -- get the location of the next cluster + fat32_raw_read (in_0, in_1) -- read 2 data bytes + fat32_raw_read (in_2, in_3) -- read 2 data bytes + + -- put it into a dword + next_cluster_array[0] = in_0 + next_cluster_array[1] = in_1 + next_cluster_array[2] = in_2 + next_cluster_array[3] = in_3 + + -- for troubleshooting only + ;_fat32_send_dword (current_cluster) + ;_fat32_send_dword (next_cluster) + ;send_word (0xAA, 0xAA) + + -- store number of clusters that are beside eachother + fat32_file_fragment_cluster_count[fat32_file_fragments_start_count - 1] = 1 + + if next_cluster == 0x0F_FF_FF_FF then -- exit if the file is only 1 cluster + done = TRUE + end if + + while done == FALSE loop + if current_cluster + 1 == next_cluster then -- if no fragmentation + while current_cluster + 1 == next_cluster loop + current_cluster = next_cluster -- increment since we read the next cluster, no fragmentation + + -- get the location of the next cluster + fat32_raw_read (in_0, in_1) -- read 2 data bytes + fat32_raw_read (in_2, in_3) -- read 2 data bytes + + -- put it into a dword + next_cluster_array[0] = in_0 + next_cluster_array[1] = in_1 + next_cluster_array[2] = in_2 + next_cluster_array[3] = in_3 + + -- store number of clusters that are beside eachother + fat32_file_count_3 = fat32_file_count_3 + 1 + fat32_file_fragment_cluster_count[fat32_file_fragments_start_count - 1] = fat32_file_count_3 + end loop + elsif next_cluster == 0x0F_FF_FF_FF then -- if end of clusters + done = TRUE -- we are done, quit all loops + else -- if fragmentation + fat32_file_fragments_start[fat32_file_fragments_start_count] = next_cluster -- store the location of the start of the next fragment + fat32_file_fragments_start_count = fat32_file_fragments_start_count + 1 -- increment fat32_file_fragments_start address + current_cluster = next_cluster + + -- for troubleshooting only + ;_fat32_send_dword (current_cluster) + + exit loop -- exit this loop and go to the next fragment + end if + + end loop + fat32_stop_read() -- stop reading media + end loop + + -- set the rest of the values to 0x0F_FF_FF_FF + for FAT32_DIR_FRAGMENTS_TO_ALLOW - fat32_file_fragments_start_count loop + fat32_file_fragments_start[fat32_file_fragments_start_count] = 0xFF_FF_FF_FF + fat32_file_fragment_cluster_count[fat32_file_fragments_start_count] = 0xFF_FF + fat32_file_fragments_start_count = fat32_file_fragments_start_count + 1 + end loop + end if + + fat32_stop_read() -- stop reading media + end procedure +end if + +-- ---------------------------------------------------------------------------- +-- READ DIR INFO, STORE INTO ENTRY_LOCATION ARRAY +-- refers to fat32 directory entry characters +-- ---------------------------------------------------------------------------- +const byte FAT32_ENTRY_NOT_IN_USE = 0xE5 -- usually from a deleted file +const byte FAT32_ENTRY_IS_PART_OF_LONG_NAME = 0x0F -- entry has a few characters of a long filename +procedure fat32_read_dir_info(dword in dir) is + var byte*FAT32_ENTRIES_MAX filename_location + var byte x + var bit send_it = false + var bit has_long_name = 0 + var byte long_name_check + var byte in_a + var byte in_b + var word sectors_read = 0 + var bit exit_procedure = FALSE + + var dword clusters_to_read = 1 -- number of clusters to read + var word fragment_number = 0 -- the fragment number being read + + var byte attrib -- this attrib is different var then fat32_attrib + var bit fat32_is_read_only at attrib : 0 + var bit fat32_is_hidden at attrib : 1 + var bit fat32_is_system at attrib : 2 + var bit fat32_is_volume_id at attrib : 3 + var bit fat32_is_directory at attrib : 4 + var bit fat32_is_archive at attrib : 5 + + fat32_dir_file_count = 0 + + if FAT32_DIR_FRAGMENTS_TO_ALLOW > 0 then + fat32_read_fragments (fat32_file_cluster , FAT32_DIRECTORY) -- read the fragment locations + else + fat32_start_read (dir) -- go to the dir and get ready to read + end if + + fat32_current_dir_location = dir + + while exit_procedure == FALSE loop + + if FAT32_DIR_FRAGMENTS_TO_ALLOW > 0 then + fat32_stop_read() -- stop the current read process if any + + -- start reading at the beginning of the fragment + fat32_start_read (fat32_cluster_begin + (fat32_dir_fragments_start[fragment_number] * fat32_sectors_per_cluster) ) + clusters_to_read = fat32_dir_fragment_cluster_count[fragment_number] -- the number of clusters beside eachother + fragment_number = fragment_number + 1 -- increment the fragment number being read + end if + + for clusters_to_read * fat32_sectors_per_cluster loop -- loop till end of fragment + for 16 loop -- loop once per sector & count sectors read + -- get 32 byte directory entry + fat32_raw_read (in_a,x) -- get first byte + fat32_read_pulse (1) + fat32_read_pulse (1) + fat32_raw_read (long_name_check,x) + fat32_read_pulse (1) + fat32_raw_read (x,attrib) -- get attrib + fat32_read_pulse (10) + + + if (in_a == 0) then -- exit if no more files in current directory + exit_procedure = TRUE + exit loop + end if + + if (fat32_dir_file_count > FAT32_FILES_MAX) then + fat32_dir_file_count = fat32_dir_file_count - 1 + exit_procedure = TRUE + exit loop + end if +; send_word (in_a,attrib) +; send_word (long_name_check,0xFF) +; _usec_delay (500_000) + + ;-- get the location of the start of the filename + + if in_a != FAT32_ENTRY_NOT_IN_USE & attrib == FAT32_ENTRY_IS_PART_OF_LONG_NAME then -- if longname, FAT32_ENTRY_NOT_IN_USE (unused entry), FAT32_ENTRY_IS_PART_OF_LONG_NAME (long filename) + if in_a >= 0x41 then + has_long_name = TRUE + ; long_name_entries = in_a - 0x40 + + -- calculate the entry location + if (fat32_word_count / 16) != 0 then -- do not decrement a zero value + filename_location = (fat32_word_count / 16) + (16 * sectors_read) - 1 + else + filename_location = FAT32_ENTRY_IS_PART_OF_LONG_NAME + (16 * sectors_read) + end if + + send_it = TRUE + ;send_word (0xFF,0xFF) + ;send_word (filename_location,fat32_word_count) + end if + elsif (in_a != FAT32_ENTRY_NOT_IN_USE) & (long_name_check != "~") then -- if shortname only ("~" = "~") + + has_long_name = false + + -- calculate the entry location + if (fat32_word_count / 16) != 0 then + filename_location = (fat32_word_count / 16) + (16 * sectors_read) - 1 + else -- do not decrement a zero value + filename_location = FAT32_ENTRY_IS_PART_OF_LONG_NAME + (16 * sectors_read) + end if + + send_it = TRUE + + -- fat32_attrib_filter out unwanted attributes + if (attrib & fat32_attrib_filter) > 0 then + send_it = false + end if + + elsif in_a != FAT32_ENTRY_NOT_IN_USE & long_name_check == "~" then -- if shortname entry that has a long name + + -- fat32_attrib_filter out unwanted attributes + if (attrib & fat32_attrib_filter) > 0 then + fat32_dir_file_count = fat32_dir_file_count - 1 + end if + + send_it = false + else + send_it = false + end if + + if send_it == TRUE then + -- reset stuff + send_it = false + has_long_name = false + + fat32_write_entry (fat32_dir_file_count,filename_location) + + ; send_word (fat32_dir_file_count,filename_location) + ; _usec_delay (1_000_000) + + fat32_dir_file_count = fat32_dir_file_count + 1 + end if + + end loop + + if (in_a == 0) | (fat32_dir_file_count > FAT32_FILES_MAX) | exit_procedure == TRUE then -- exit if no more files in current directory or if max files reached + exit_procedure = TRUE + exit loop + end if + sectors_read = sectors_read + 1 + end loop -- end sector loop + + if (in_a == 0) | (fat32_dir_file_count > FAT32_FILES_MAX) | exit_procedure == TRUE then -- exit if no more files in current directory or if max files reached + exit_procedure = TRUE + exit loop + end if + + end loop + fat32_write_entry (fat32_dir_file_count,0) -- put 0's in the last entry + fat32_stop_read() -- let media wait for next operation + +end procedure + + +-- ---------------------------------------------------------------------------- +-- reads file info such as filename, filesize, filelocation, etc. into memory. +-- ---------------------------------------------------------------------------- +procedure fat32_read_file_info(byte*FAT32_ENTRIES_MAX in file_number) is + var dword read_entry_location + var byte line[32] + var byte long_name_pos = FAT32_FILENAME_SIZE + longnamelocation - 1 + var byte long_filename_char[13] + var byte count1 + var byte long_name_entries + var byte x + fat32_read_entry(file_number,read_entry_location) -- get the entry location of the file number, in current dir + + if (FAT32_DIR_FRAGMENTS_TO_ALLOW > 0) then + -- start reading at the correct sector + -- calculate how many clusters forward the filename is + -- get how many sectors into the current dir the filename is located + + -- get the entrie's directory sector number + var dword entry_sector_number + entry_sector_number = read_entry_location >> 4 + + -- find what fragment the filename is located in + var word fragment_count = 0 + var dword sector_adder = 0 + var dword sector_prev_added = 0 + + sector_adder = fat32_dir_fragment_cluster_count[0] -- read location of first fragment + + -- not sure why this is needed here, if this is not here, + -- when files_max is = between 15-25 files don't list correctly. + if fat32_dir_fragment_cluster_count[0] == 0 then + sector_adder = 1 + end if + + forever loop + if (entry_sector_number < (sector_adder * fat32_sectors_per_cluster) ) then -- check if filename is in current fragment + exit loop + else + sector_prev_added = sector_adder -- remember number of sectors counted so far from last fragment + fragment_count = fragment_count + 1 -- go to next fragment + sector_adder = sector_adder + fat32_dir_fragment_cluster_count[fragment_count] -- add number of sectors in current fragment + end if + end loop + + -- start reading at the correct fragment and sector number + if !(entry_sector_number == 0) then -- not sure why this if is needed when files_max is < 8 + fat32_start_read (fat32_cluster_begin + fat32_dir_fragments_start[fragment_count]*fat32_sectors_per_cluster + (entry_sector_number - (sector_prev_added * fat32_sectors_per_cluster)) ) + else + fat32_start_read (fat32_current_dir_location + (read_entry_location >> 4)) + end if + else + -- start reading at the correct sector + fat32_start_read (fat32_current_dir_location + (read_entry_location >> 4)) + end if + -- start reading at the correct 32 byte entry + var byte temp_val[4] at read_entry_location -- get lower nibble out of read_entry_location + x = temp_val[0] + x = x << 4 + x = x >> 4 + + fat32_read_pulse (x * 16) + if FAT32_DIR_FRAGMENTS_TO_ALLOW > 0 then + var byte entry_count = x -- count entries read incase we go over a fragment boarder, may be able to get rid of this var + end if + -- CLEAR LAST filename ENTRY + count1 = 0 + FOR FAT32_FILENAME_SIZE + longnamelocation LOOP + fat32_write_filename ( count1, 0xFF) + count1 = count1 + 1 + END LOOP + + -- read the filename, fat32_attributes, location, ext + forever loop + -- GET LINE OF CLUSTER + fat32_raw_read (line[0], line[1]) + fat32_raw_read (line[2], line[3]) + fat32_raw_read (line[4], line[5]) + fat32_raw_read (line[6], line[7]) + fat32_raw_read (line[8], line[9]) + fat32_raw_read (line[10], line[11]) + fat32_raw_read (line[12], line[13]) -- var 13 never used + fat32_raw_read (line[14], line[15]) -- var 15 never not used + fat32_raw_read (line[16], line[17]) -- var 17 never not used + fat32_raw_read (line[18], line[19]) + fat32_raw_read (line[20], line[21]) -- var 21 never not used + fat32_raw_read (line[22], line[23]) -- var 23 never not used + fat32_raw_read (line[24], line[25]) + fat32_raw_read (line[26], line[27]) + fat32_raw_read (line[28], line[29]) + fat32_raw_read (line[30], line[31]) + + -- for troubleshooting, send the current 32 byte entry to serial port + ;send_word (line[0], line[1]) + ;send_word (line[2], line[3]) + ;send_word (line[4], line[5]) + ;send_word (line[6], line[7]) + ;send_word (line[8], line[9]) + ;send_word (line[10], line[11]) + ;send_word (line[12], line[13]) + ;send_word (line[14], line[15]) + ;send_word (line[16], line[17]) + ;send_word (line[18], line[19]) + ;send_word (line[20], line[21]) + ;send_word (line[22], line[23]) + ;send_word (line[24], line[25]) + ;send_word (line[26], line[27]) + ;send_word (line[28], line[29]) + ;send_word (line[30], line[31]) + + long_name_entries = line[0] -- get the number of entries a longname takes up if it is a long name + + fat32_attrib = line[11] -- get file fat32_attributes if short name, 0x0F if part of long name. + + -- if line is part of long filename + if fat32_attrib == FAT32_ENTRY_IS_PART_OF_LONG_NAME & line[0] != FAT32_ENTRY_NOT_IN_USE then + for long_name_entries - 0x40 loop + + long_filename_char[12] = line[1] + long_filename_char[11] = line[3] + long_filename_char[10] = line[5] + long_filename_char[9] = line[7] + long_filename_char[8] = line[9] + long_filename_char[7] = line[14] + long_filename_char[6] = line[16] + long_filename_char[5] = line[18] + long_filename_char[4] = line[20] + long_filename_char[3] = line[22] + long_filename_char[2] = line[24] + long_filename_char[1] = line[28] + long_filename_char[0] = line[30] + + -- for troubleshooting only, send long name chars via serial port + ; send_word (long_filename_char[12], long_filename_char[11]) + ; send_word (long_filename_char[10], long_filename_char[9]) + ; send_word (long_filename_char[8], long_filename_char[7]) + ; send_word (long_filename_char[6], long_filename_char[5]) + ; send_word (long_filename_char[4], long_filename_char[3]) + ; send_word (long_filename_char[2], long_filename_char[1]) + ; send_word (long_filename_char[0], 0) + ; send_word (1, 1) + + -- put zero's in long name characters if character is not valid + count1 = 0 + FOR 13 LOOP + IF long_filename_char[count1] == 0xFF THEN + long_filename_char[count1] = 0x00 -- may not need to do this + END IF + IF long_filename_char[count1] <= 0x1F THEN + IF long_filename_char[count1] >= 0x7F THEN + long_filename_char[count1] = 0x00 + END IF + END IF + count1 = count1 + 1 + END LOOP + + -- store the long filename into 'longname' + count1 = 0 + FOR 13 LOOP + IF long_filename_char[count1] == 0x00 THEN + long_filename_char[count1] = 0xFF + END IF + if (long_name_pos < FAT32_FILENAME_SIZE) then + fat32_write_filename ( long_name_pos, long_filename_char[count1]) + long_name_pos = long_name_pos - 1 + count1 = count1 + 1 + end if + END LOOP + + if FAT32_DIR_FRAGMENTS_TO_ALLOW > 0 then + -- if filename is going over a frabment boarder (if at last sector of current fragment), change to next fragment. + if (entry_sector_number - (sector_prev_added * fat32_sectors_per_cluster) ) == (sector_adder * fat32_sectors_per_cluster - 1) then + if entry_count == 15 then -- * dir_fragment_entry_count) -- if we finnished the last sector in fragment + fat32_stop_read() + -- start reading at the beginning of the next fragment + fat32_start_read (fat32_cluster_begin + (fat32_dir_fragments_start[fragment_count + 1]*fat32_sectors_per_cluster) ) + end if + end if + entry_count = entry_count + 1 -- increment entry counter + end if + + -- use this to get file info such as the longname's shortname, file ext, file fat32_attrib + fat32_raw_read (line[0], line[1]) + fat32_raw_read (line[2], line[3]) + fat32_raw_read (line[4], line[5]) + fat32_raw_read (line[6], line[7]) + fat32_raw_read (line[8], line[9]) + fat32_raw_read (line[10], line[11]) + fat32_raw_read (line[12], line[13]) + fat32_raw_read (line[14], line[15]) + fat32_raw_read (line[16], line[17]) + fat32_raw_read (line[18], line[19]) + fat32_raw_read (line[20], line[21]) + fat32_raw_read (line[22], line[23]) + fat32_raw_read (line[24], line[25]) + fat32_raw_read (line[26], line[27]) + fat32_raw_read (line[28], line[29]) + fat32_raw_read (line[30], line[31]) + + end loop + + exit loop + + ELSIF fat32_attrib != FAT32_ENTRY_IS_PART_OF_LONG_NAME & line[0] != FAT32_ENTRY_NOT_IN_USE THEN ; IF LINE IS SHORT FILENAME + fat32_write_filename (FAT32_FILENAME_SIZE + longnamelocation - 12, line[0]) -- first char + fat32_write_filename (FAT32_FILENAME_SIZE + longnamelocation - 11, line[1]) + fat32_write_filename (FAT32_FILENAME_SIZE + longnamelocation - 10, line[2]) + fat32_write_filename (FAT32_FILENAME_SIZE + longnamelocation - 9, line[3]) + fat32_write_filename (FAT32_FILENAME_SIZE + longnamelocation - 8, line[4]) + fat32_write_filename (FAT32_FILENAME_SIZE + longnamelocation - 7, line[5]) + fat32_write_filename (FAT32_FILENAME_SIZE + longnamelocation - 6, line[6]) + fat32_write_filename (FAT32_FILENAME_SIZE + longnamelocation - 5, line[7]) + + -- remove extra spaces from the end of a short filename + var byte check_for_space + var byte count_up = 0 -- count how many spaces + var byte count_up2 = 5 -- char address to read + for 8 loop + fat32_get_filename (FAT32_FILENAME_SIZE + longnamelocation - count_up2, check_for_space) -- read a character + if check_for_space == 0x20 then -- check for a "space" character + count_up = count_up + 1 -- increment spaces found + count_up2 = count_up2 + 1 -- increment char address + end if + end loop + + IF (fat32_is_directory == false) & (fat32_is_volume_id == false) THEN + fat32_write_filename (FAT32_FILENAME_SIZE + longnamelocation - 4 - count_up, 0x2E) -- add "." if it is a file + END IF + + fat32_write_filename (FAT32_FILENAME_SIZE + longnamelocation - 3 - count_up, line[8]) ;FILE EXTENSION + fat32_write_filename (FAT32_FILENAME_SIZE + longnamelocation - 2 - count_up, line[9]) + ;line[10] = 0x34 + fat32_write_filename (FAT32_FILENAME_SIZE + longnamelocation - 1 - count_up, line[10]) + + exit loop + + end if + end loop + + fat32_stop_read() -- let media wait for next operation + + ;Get Extension + file_ext[0] = line[8] + file_ext[1] = line[9] + file_ext[2] = line[10] + + ;Get Cluster high, Cluster low, file location + fat32_file_cluster = line[21] + fat32_file_cluster = fat32_file_cluster << 8 + fat32_file_cluster = fat32_file_cluster + line[20] + fat32_file_cluster = fat32_file_cluster << 8 + fat32_file_cluster = fat32_file_cluster + line[27] + fat32_file_cluster = fat32_file_cluster << 8 + fat32_file_cluster = fat32_file_cluster + line[26] + + if fat32_file_cluster == 0 then -- if dir cluster location = 0, file location is the root dir + fat32_file_cluster = 2 + end if + + fat32_file_location = fat32_cluster_begin + (fat32_file_cluster * fat32_sectors_per_cluster) + + ;Get File size + fat32_file_size = line[31] + fat32_file_size = fat32_file_size << 8 + fat32_file_size = fat32_file_size + line[30] + fat32_file_size = fat32_file_size << 8 + fat32_file_size = fat32_file_size + line[29] + fat32_file_size = fat32_file_size << 8 + fat32_file_size = fat32_file_size + line[28] + + fat32_attrib = line[11] ; GET FILE fat32_attributes + +end procedure + +-------------------------------------------------------------------------------- +-- read filename characters +-------------------------------------------------------------------------------- +var byte fat32_filename_count = 0 +function fat_32_read_filename_char() return byte is + var byte character = 0 ***The diff for this file has been truncated for email.*** ======================================= --- /dev/null +++ /trunk/sample/18f452_fat32_sd_card.jal Wed Nov 25 00:01:04 2009 @@ -0,0 +1,217 @@ +-- Title: FAT32 library for reading fat32 filesystem +-- Author: Matthew Schinkel, copyright (c) 2009, all rights reserved. +-- Adapted-by: +-- Compiler: >=2.4k +-- +-- This file is part of jallib (http://jallib.googlecode.com) +-- Released under the BSD license (http://www.opensource.org/licenses/bsd-license.php) +-- +-- Description: this example reads files & folders from a fat32 formatted sd card +-- using the fat32 library. +-- +-- 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 +-- +------- GENERAL SETTINGS & VARS ------- + +-- include chip +include 18f452 -- target picmicro + +-- this program assumes a 20 mhz resonator or crystal +-- is connected to pins osc1 and osc2. +pragma target osc hs -- hs crystal or resonator +pragma target clock 20_000_000 -- oscillator frequency +-- +pragma target wdt disabled +pragma target lvp disabled +-- + +enable_digital_io() -- disable all analog pins if any + +include delay -- include the delay library +include pic_data_eeprom + +-- setup uart for communication +const serial_hw_baudrate = 38400 -- set the baudrate +include serial_hardware +serial_hw_init() + +_usec_delay (100_000) -- wait for power to stablilize + +-- procedure for sending 80 "-----------------" via serial port +procedure next() is + serial_hw_write (13)-- send (carriage return, line feed) characters to serial port + serial_hw_write (10) + for 80 loop + serial_hw_write ("-") + end loop + serial_hw_write (13)-- send (carriage return, line feed) characters to serial port + serial_hw_write (10) +end procedure + +next() + +-- setup spi +include spi_master_hw -- includes the spi library + +-- define spi inputs/outputs +pin_sdi_direction = input -- spi input +pin_sdo_direction = output -- spi output +pin_sck_direction = output -- spi clock +-- spi chip select pin +ALIAS sd_chip_select_direction is pin_SS_direction +ALIAS sd_chip_select is pin_SS +sd_chip_select_direction = output -- chip select/slave select pin +sd_chip_select = high -- disable the sd card +-- +spi_init(SPI_MODE_11,SPI_RATE_FOSC_16) -- init spi, choose mode and speed + +include sd_card -- include the sd card ide hard disk library +sd_init() -- initialize startup settings + +------------------------------------------------------------------------------------ + +-- setup fat32 +-- large_array_1 lib is included within the fat32 lib file and is required as well. +-- select your data media +const PATA_HARD_DISK = 0 +const SD_CARD = 1 +const DATA_MEDIA = 1 +include format -- include format library +include fat32 -- include fat32 library +-- CHOOSE FILE ATTRIBUTES TO FILTER OUT +fat32_filter_is_read_only = FALSE +fat32_filter_is_hidden = FALSE +fat32_filter_is_system = FALSE +fat32_filter_is_volume_id = FALSE +fat32_filter_is_directory = FALSE +fat32_filter_is_archive = FALSE + +-- start of main program +var byte in_a, in_b -- vars for storing data read + +fat32_init(1) -- initialize fat32, go to 1st primary partition's root dir "\" + + +------------------------------------------------------------ +-- list a directory, send it via serial port +------------------------------------------------------------ + +-- we are now in the root dir of the 1st partition + +fat32_list_dir() -- see the procedure, sends dir listing via serial port + +;next() -- send "-----" and go to next example + +--------------------------------------------------------------------------------------------------------------- +-- example read filename, send it via serial port +------------------------------------------------------------ + +-- we are still in the root dir of the 1st partition + +;fat32_read_file_info(3) -- read 3rd file's name, location, size, attributes into memory + + +-- now send the filename via the serial port +;fat32_read_filename() + +;next() -- send "-----" and go to next example + +------------------------------------------------------------ +-- example select a file, +-- if dir then go into dir list it +-- if file then go into file and read it +------------------------------------------------------------ + +; var byte file_number = 13 +; -- choose a file for reading or dir for opening +; +; if fat32_cd(file_number) then -- if change directory is successful +; list_dir() -- sends dir listing via serial port +; end if +; +; if fat32_file_open(file_number) then -- if go into file is successful +; +; fat32_start_read (fat32_file_location) -- go in the file, get ready to read +; for (fat32_file_size / 2) loop -- reading 2 bytes at a time +; fat32_read_file (in_b, in_a) -- read 2 data bytes +; serial_hw_write (in_b) -- send 2 data bytes via serial port +; serial_hw_write (in_a) +; end loop +; +; -- if odd number of bytes in file, send last byte +; var bit odd_number at fat32_file_size : 0 +; if odd_number then +; fat32_read_file (in_b, in_a) -- read 2 data bytes +; serial_hw_write (in_b) -- send last data byte via serial port +; end if +; +; fat32_stop_read () -- end of file, set media idle +; end if +; +;serial_hw_write (13) -- send 2 data bytes via serial port +;serial_hw_write (10) + +;------------------------------------------------------------ +;-- example raw read one sector from anywhere on media +;------------------------------------------------------------ +;-- READ ONE SECTOR +;var byte low_byte +;var byte high_byte +; +;-- raw read the sector containing the root dir (sector 0) +;fat32_start_read(fat32_cluster_begin + (0x02 * 8)) +;for 256 loop -- read 1 sector (256 words) +; fat32_raw_read (low_byte, high_byte) -- read 2 bytes of data +; serial_hw_write (low_byte) -- send byte via serial port +; serial_hw_write (high_byte) -- send byte via serial port +;end loop +;fat32_stop_read() -- tell sd card you are done reading + +------------------------------------------------------------ +-- example user interaction, +-- send file/dir number via serial port to go into it +-- +-- if volume id selected, list the current dir (root dir) +-- if directory selected go into it and list it +-- if file selected go into file and read it +------------------------------------------------------------ + +var byte file_number2 = 0 +forever loop + + + next() -- send "-----" then loop and wait for user input + + while !serial_hw_data_available loop + end loop + + var byte x + x = serial_hw_read(file_number2) + -- choose a file for reading or dir for opening + + if fat32_cd(file_number2) then -- if change directory is successful + fat32_list_dir() -- sends dir listing via serial port + elsif fat32_file_open(file_number2) then -- if go into file is successful + + fat32_start_read (fat32_file_location) -- go in the file, get ready to read + for (fat32_file_size / 2) loop -- reading 2 bytes at a time + fat32_read_file (in_b, in_a) -- read 2 data bytes + serial_hw_write (in_b) -- send 2 data bytes via serial port + serial_hw_write (in_a) + end loop + + -- if odd number of bytes in file, send last byte + var bit odd_number at fat32_file_size : 0 + if odd_number then + fat32_read_file (in_b, in_a) -- read 2 data bytes + serial_hw_write (in_b) -- send last data byte via serial port + end if + + fat32_stop_read () -- end of file, set media idle + end if + + +end loop ======================================= --- /trunk/sample/16f877_sd_card.jal Sat Oct 31 23:35:32 2009 +++ /trunk/sample/16f877_sd_card.jal Wed Nov 25 00:01:04 2009 @@ -14,9 +14,9 @@ -- -- compiler dependant device definitions -include 16f877 +;include 16f877 ;include 16f877a -;include 18f452 +include 18f452 pragma target OSC HS -- HS crystal or resonator pragma target clock 20_000_000 -- oscillator frequency @@ -59,7 +59,7 @@ var byte low_byte, high_byte -- vars for sending and recieving data -- read the boot sector (sector 0) -sd_start_read(0) -- get sd card ready for read at sector 233 +sd_start_read(0) -- get sd card ready for read at sector 0 for 256 loop -- read 1 sector (256 words) sd_read_data (low_byte, high_byte) -- read 2 bytes of data serial_hw_write (low_byte) -- send byte via serial port ======================================= --- /trunk/sample/18f452_sd_card.jal Sat Oct 31 23:35:32 2009 +++ /trunk/sample/18f452_sd_card.jal Wed Nov 25 00:01:04 2009 @@ -14,9 +14,9 @@ -- -- compiler dependant device definitions -include 16f877 +;include 16f877 ;include 16f877a -;include 18f452 +include 18f452 pragma target OSC HS -- HS crystal or resonator pragma target clock 20_000_000 -- oscillator frequency @@ -59,7 +59,7 @@ var byte low_byte, high_byte -- vars for sending and recieving data -- read the boot sector (sector 0) -sd_start_read(0) -- get sd card ready for read at sector 233 +sd_start_read(0) -- get sd card ready for read at sector 0 for 256 loop -- read 1 sector (256 words) sd_read_data (low_byte, high_byte) -- read 2 bytes of data serial_hw_write (low_byte) -- send byte via serial port -- You received this message because you are subscribed to the Google Groups "jallib" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/jallib?hl=en.
