?? fat16driver.bas
字號:
' **
' * Title: FAT16Driver.bas
' * Date: 02/08/03
' * Author: Larry Wolcott
' * email: objectcoder@hotmail.com
' * web: http://www.larrywolcott.com
' *
' * Description: A functional reference implementation of FAT16. Requires
' * FlashCardDrive.bas by Josef Franz Vogel found at http://www.mcselec.com
in the
' * Application Notes area listed as AN-123. A simple CompactFlash hardware
' * inteface is also required. See additional documentation enclosed or
refer
' * to the "Accessing a Compact Flash Card from BASCOM" (AN-123) on the
site.
' * see http://www.mcselec.com/an_123.htm
' *
' * This has been developed for the Atmega103/128 AVRs. Memory requirements
' * are such that this driver should work with any AVR that has 2K SRAM or
more.
' * Furthermore, there is currently no cluster chaninig support other than
' * basic, linear linking. That means the code will not reuse space created
' * by deleting files. When the storage device reaches maximun capacity, it
' * should be formated. This is the safest way to ensure cross-linked
cluster
' * chains do not occur.
' *
' * NOTE: Be sure to set the 'Frame Size' parameter to 256 or this driver
will
' * not work properly.
' **
'include the low-level comms driver for the flash card (AN-123 by Josef
Franz)
$Include "FlashCardDrive.bas"
'This function is used to return a long datatype from the buffer
Declare Function Getlongfrombuffer(pbsramarray As Byte , Byval Pbpos As
Word) As Long
'This function is used to return a word datatype from the buffer
Declare Function Getwordfrombuffer(pbsramarray As Byte , Byval Pbpos As
Word) As Word
'This function is used to read the Master Boot Record
Declare Sub Readmbr()
'This function is used init the storage device
Declare Sub Init()
'used to convert a long value to 4 bytes
Declare Sub Convertlong(byval Longvalue As Long)
'used to convert a word value to 2 bytes
Declare Sub Convertword(byval Wordvalue As Word)
'this sub prints a message to the RS232 or LCD if the debug is set
Declare Sub Debug(byval Debugtext As String)
'this sub sets the debug output device
Declare Sub Setdebug(byval Debugvalue As Byte)
'this sub is used to read boot record for a given partition
Declare Sub Readbootrecord()
'this function is used to parse a 512 byte sector for the 32 byte fat record
Declare Function Parsefatrecord(byval Recordnum As Word) As Byte
'this function is used to search the root dir for a file
Declare Function Searchrootdir(byval Searchname As String) As Byte
'this function is used to calculate the sector from the cluster
Declare Function Findsector(byval Clusternumber As Word) As Long
'checks to see if a file exists, if not, it gets created
Declare Sub Createorappendtofile(byval Fname As String)
'finds the sector and entry number on the root that is available
Declare Sub Pointtofreeentry()
'creates a new directory entry on the root
Declare Sub Createrootentry(byval Touchname As String)
'writes data to the storage device
Declare Function Writedata(byval Texttowrite As String , Byval Linefeed As
Byte) As Byte
'calculates the next cluster/sector to use for a new file
Declare Sub Findnextavailable()
'updates the allocation table
Declare Sub Updateallocationtable(byval Isnew As Byte)
'loads the databuffer
Declare Sub Loaddatabuffer()
'this sub is used to list the files on the root dir
Declare Sub Listrootdir()
'sets the dir values to a record on a speficied sector
Declare Sub Setdirvalues()
'finds the next available cluster
Declare Sub Findlastusedsector()
'This function is used to dump an arbitrary sector as hex
Declare Sub Dumpsectorashex(byval Dumpsect As Long)
'This function is used to dump an arbitrary sector as chr
Declare Sub Dumpsectoraschr(byval Dumpsect As Long)
'lists a file contents as ascii text
Declare Sub Listfile(byval Fname As String)
'This function is used to read the Master Boot Record
Declare Sub Dumpfile(byval Startcluster As Word , Byval Filelen As Long)
'values used by the hex conversion routines
Dim Conv_long As Long
Dim Conv_string As String * 8
Dim Conv_bytes(4) As Byte
Dim Conv_strbytes(4) As String * 2
Dim Convw_word As Word
Dim Convw_string As String * 4
Dim Convw_bytes(2) As Byte
Dim Convw_strbytes(2) As String * 2
'master boot record (MBR) values of interest
Dim Mbr_fstype As Byte
Dim Mbr_sectfrom As Long
Dim Mbr_fatoffset As Long
Dim Mbr_sectorsinroot As Byte
Dim Mbr_totalsectors As Long
'boot record values of interest
Dim Br_bytespersector As Word
Dim Br_sectorspercluster As Byte
Dim Br_reservedsectors As Word
Dim Br_copiesoffat As Byte
Dim Br_sectorsperfat As Word
Dim Br_rootcluster As Long
Dim Br_maxrootentries As Word
Dim Br_sectorsinroot As Word
Dim Br_actualstartsector As Long
Dim Br_sectorsinallfats As Long
'define the standard FAT entry fields
Dim Fat_shortname(8) As Byte
Dim Fat_extension(3) As Byte
Dim Fat_attribute As Byte
Dim Fat_createdms As Byte
Dim Fat_createdtm As Word
Dim Fat_createddt As Word
Dim Fat_accessdt As Word
Dim Fat_fathighcluster As Word
Dim Fat_updatetime As Word
Dim Fat_updatedate As Word
Dim Fat_cluster As Word
Dim Fat_filesize As Long
Dim Fat_volumename As String * 11
Dim Fat_filename As String * 12
Dim Fat_dirname As String * 12
Dim Fat_direntry As Word
Dim Fat_dirsector As Long
'vlues for the update allocation table routine
Dim Alloc_currentcluster As Word
Dim Alloc_currentsector As Long
Dim Alloc_lastcluster As Word
Dim Allocpointer As Word
Dim Alloc_clustoffset As Word
Dim Alloc_clustcalc1 As Long
Dim Alloc_clustcalc2 As Long
Dim Alloc_cntr As Byte
Dim Alloc_temp1 As Long
Dim Alloc_isnewsector As Byte
'values for the last used sector routing
Dim Lus_cluster As Word
Dim Lus_prevcluster As Word
Dim Lus_sector As Long
Dim Lus_fatsector As Long
Dim Lus_cntr As Long
Dim Lus_rec As Word
Dim Lus_loop As Word
Dim Lus_bytes As Long
Dim Lus_sectorincluster As Byte
Dim Lus_isnewfile As Byte
Dim Lus_calc1 As Long
Dim Lus_calc2 As Long
Dim Lus_sectoroffset As Word
'values for the write routine
Dim Wr_len As Word
Dim Wr_text As String * 128
Dim Wr_text2 As String * 128
Dim Wr_calc1 As Long
Dim Wr_calc2 As Long
Dim Wr_calc3 As Long
Dim Wr_calc4 As Long
Dim Wr_cntr As Word
Dim Wr_char As String * 1
Dim Wr_sectloop As Byte
Dim Wr_sectcount As Byte
'values for the dump file routine
Dim Df_totalsecinfile As Long
Dim Df_secinfilebytes As Long
Dim Df_sectcount As Byte
Dim Df_modbytesinfile As Word
Dim Df_bytestoread As Word
Dim Df_cntr As Long
Dim Df_cntr2 As Word
Dim Df_startcluster As Long
Dim Df_startsector As Long
Dim Df_length As Long
'various global values
Dim G_debug As Byte
Dim G_debugtext As String * 80
Dim G_offset As Word
Dim G_cntr As Long
Dim G_rootloop As Byte
Dim G_pointer As Word
Dim G_datapointer As Word
Dim G_sectnum As Long
Dim G_sectcount As Byte
Dim G_parse_temp As Long
Dim G_attribute As Byte
Dim G_attribreturn As Byte
Dim G_temp_cntr As Byte
Dim G_temp_val As Long
Dim G_volumerecord As Word
Dim G_touchvalue As Byte
Dim G_touchholder As String * 12
Dim G_dotposition As Byte
Dim G_dotloop As Byte
Dim G_dotextcount As Byte
Dim G_dotchar As String * 1
'values for the find sector routine
Dim Fnd_sectorcalc As Long
Dim Fnd_spcoffset As Long
Dim Set_diroffset As Word
'data buffer values
Dim Data_sectoffset As Long
Dim Data_sector As Long
Dim Data_sectorcluster As Long
'global 512 byte transfer buffers
Dim G_xferbuffer(512) As Byte
Dim G_databuffer(512) As Byte
Dim G_allocbuffer(512) As Byte
' **
' * This function is used init the storage device
' **
Sub Init()
Print "Init()"
'first, read the MBR (Master Boot Record)
Call Readmbr()
'second, read the boot record of the first partition
Call Readbootrecord()
'find the last used cluster/sector in the dir entry
Call Findlastusedsector()
End Sub
' **
' * This function is used to read the Master Boot Record
' **
Sub Dumpfile(byval Startcluster As Word , Byval Filelen As Long)
Df_length = Filelen
Df_startsector = Findsector(startcluster)
Print "Dumping File, sect: " ; Df_startsector ; " bytes: " ; Df_length
'if the file is larger than a single sector, calculate how many
If Df_length > 512 Then
'figure out how man 512 byte sectors and the mod bytes
Df_totalsecinfile = Df_length / 512
Df_secinfilebytes = Df_totalsecinfile * 512
Df_modbytesinfile = Df_length - Df_secinfilebytes
Else
'the file fits on a single sector
Df_totalsecinfile = 0
Df_modbytesinfile = Df_length
End If
Print "Total sec: " ; Df_totalsecinfile ; " mod: " ; Df_modbytesinfile ;
" bytes"
'point to the first byte of the array
G_datapointer = Varptr(g_databuffer(1))
'MBR fits on a simgle 512 byte sector
Df_sectcount = 1
Df_totalsecinfile = Df_totalsecinfile + 1
Df_bytestoread = 512
'for each of the sectors
For Df_cntr = 1 To Df_totalsecinfile
If Df_cntr = Df_totalsecinfile Then
Df_bytestoread = Df_modbytesinfile
End If
'read sector number 1 into the 512 byte array starting at the pointer
address
Readsector G_datapointer , Df_startsector , Df_sectcount
For Df_cntr2 = 1 To Df_bytestoread
Print Chr(g_databuffer(df_cntr2)) ;
Next Df_cntr2
Df_startsector = Df_startsector + 1
Next Df_cntr
Print ""
Print "*EOF*"
End Sub
' **
' * This function is used to dump an arbitrary sector as chr
' **
Sub Dumpsectoraschr(byval Dumpsect As Long)
Print "Dumping Sector: " ; Dumpsect
'point to the first byte of the array
G_pointer = Varptr(g_xferbuffer(1))
'read sector number 1 into the 512 byte array starting at the pointer
address
Readsector G_pointer , Dumpsect , 1
For G_cntr = 1 To 512
Print Chr(g_xferbuffer(g_cntr)) ;
Next G_cntr
Print ""
Print "*EOF*"
End Sub
' **
' * This function is used to dump an arbitrary sector as hex
' **
Sub Dumpsectorashex(byval Dumpsect As Long)
Print "Dumping Sector: " ; Dumpsect
'point to the first byte of the array
G_pointer = Varptr(g_xferbuffer(1))
'read sector number 1 into the 512 byte array starting at the pointer
address
Readsector G_pointer , Dumpsect , 1
For G_cntr = 1 To 512
Print Hex(g_xferbuffer(g_cntr)) ; " " ;
Next G_cntr
Print ""
Print "*EOF*"
End Sub
' **
' * Writes data to the storage device
' **
Function Writedata(byval Texttowrite As String , Byval Linefeed As Byte) As
Byte
'Set The Value Outside Of The Current Frame
Wr_text = Texttowrite
Wr_len = Len(wr_text)
Print "Writing " ; Wr_len ; " bytes: '" ; Wr_text ; "'"
If Linefeed > 0 Then
Wr_text = Wr_text + Chr(13)
Wr_text = Wr_text + Chr(10)
Print "Adding 2 byte linefeed to text"
End If
'Point To The First Byte Of The Array
G_pointer = Varptr(g_xferbuffer(1))
'Set The Filesize To + Length Of Bytes
Wr_len = Len(wr_text)
'update the fat file size
Fat_filesize = Fat_filesize + Wr_len
Print "Loading data buffer to write"
'update the data buffer
Call Loaddatabuffer()
Print "Setting the directory entry values"
'set the dir values to the xfer buffer before writing
Call Setdirvalues()
Print "Writing the directory entry values"
'write the xferbuffer to the appropriate sector on the storage media
Writesector G_pointer , Fat_dirsector , 1
'extend the cluster chain if required
If Lus_sectorincluster > Br_sectorspercluster Then
'save the previous cluster number
Lus_prevcluster = Lus_cluster
'update the last used cluster
Lus_cluster = Lus_cluster + 1
'point th the first sector in the cluster
Lus_sectorincluster = 1
Print "UPDATE ALLOC, prev:" ; Lus_prevcluster ; " new:" ; Lus_cluster
'update the allocation table
Call Updateallocationtable(1)
End If
End Function
' **
' * loads the databuffer
' **
Sub Loaddatabuffer()
'Print "Loading data buffer"
'reset the calculator value
Wr_calc2 = 0
Wr_text2 = ""
'Point To The First Byte Of The Array
G_datapointer = Varptr(g_databuffer(1))
'add the test length to the current sector offset
Wr_calc1 = Lus_sectoroffset + Wr_len
'see if the total exceeds a single sector
If Wr_calc1 > 512 Then
Wr_sectcount = 2
Wr_calc3 = Wr_calc1 - 512
Wr_calc4 = Wr_len - Wr_calc3
Else
Wr_calc3 = 0
Wr_sectcount = 1
End If
'for each sector we are writing. 1 or 2, really
For Wr_sectloop = 1 To Wr_sectcount
'read sector number 1 into the 512 byte array starting at the pointer
address
Readsector G_datapointer , Lus_sector , 1
'Print "Chars: '" ;
'write the buytes
For Wr_cntr = 1 To Wr_len
'inc the calc
'Wr_calc2 = Lus_sectoroffset + Wr_cntr
Lus_sectoroffset = Lus_sectoroffset + 1
'get the character from the string position as a byte
Wr_char = Mid(wr_text , Wr_cntr , 1)
If Lus_sectoroffset < 513 Then
'set the bytes in the buffer
G_databuffer(lus_sectoroffset) = Wr_char
'Print Wr_char ;
Else
Wr_text2 = Wr_text2 + Wr_char
End If
Next Wr_cntr
'Print "'"
Print "Writing sector " ; Lus_sector ; " sectinclust: " ;
Lus_sectorincluster
'write the xferbuffer to the appropriate setcor on the storage media
Writesector G_datapointer , Lus_sector , 1
'if there is another sector, set the values for a second pass
If Wr_sectcount > 1 Then
If Wr_sectloop < 2 Then
Lus_sector = Lus_sector + 1
Lus_sectorincluster = Lus_sectorincluster + 1
Wr_text = Wr_text2
Wr_len = Len(wr_text)
Lus_sectoroffset = 0
End If
End If
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -