// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // FAT formmatted SD card access // ========== P A R T 3 ====================================== // This section is for reading existing files on the card // it also has the beginnings of operastions with the FAT that // is also necessary for writing. This file introduces logical // sectors, sectors within files rather then physical sectors on // the card. // This shares many words with fat-1-a and fat-2 so it should // have the same SID number // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // HISTORY: // Mar 2008 * found extra ; in f.open - removed // REQUIRES: // #URL-Inc "http://pin1.org/forthlib/flb/General/soft1.flb" sid=99 // #URL-lib "http://pin1.org/forthlib/flb/General/pinsel.flb" sid=100 // #URL-lib "http://pin1.org/forthlib/flb/General/SPI.flb" sid=101 // #URL-lib "http://pin1.org/forthlib/flb/SD-Card/MMC.flb" sid=102 // #URL-lib "http://pin1.org/forthlib/flb/SD-Card/fat-1.flb" // #URL-lib "http://pin1.org/forthlib/flb/SD-Card/fat-2.flb" // ========== FAT - Read ========================== // this gets an address and sector where the adress was found // so that the cluster can either be fetchd or stored to, eing word16 // this can be considered the cluster variable : fatClust ( clust -- address ) 2* // calc cluster # BytesSec d @ u/mod // [offset fat] FatTable1 d @ + // load correct sector ** only if not current dup d-sec <> if Dsec@ else drop then Dbuff + // offset into table ; // fat cluster fetch, given a cluster number this will fetch its // value, the table starts at 0, 0 fatClust@ will fect the value // of the first cluster. Note in a chain the value fetched will be the // next cluster : fatClust@ ( clust# -- val ) fatClust word16 // fetch ; // a Logical sector is the sector into that file, translates // a logical sector to a physical sector using the FAT table // file must be open with File handle fillled // returns -1 if trying to read beyond available sectors // logical sector to physical sector : Ls2Phys ( lSec -- PhySec|-1 ) SectClust d @ u/mod // get jump and offset dirAdd start-clust@ swap // 12 dir# @ swap ?dup // for will iterate even if 0 if for fatClust@ // iterate Jump times dup &fff7 > if drop drop -1 unloop escape then // end of file next then SectClust d @ * // convert back to sectors + // add offset into sector fileSpace d @ + // add filespace offset ; // opens a file and sets up the file handle structure, does not read any // data in at this stage but simply sets up the buffer and file variables // Opens file on CURRENT device // File handle is also loaded with the directory entry so that it does // not need to be read again and only needs writing on close. : r-open ( string, handle -- [error] ) => f# // file buffer dir-search // serch dir of that device if dup en# f ! // save entry number dir-entry dirEntry f 32 move // copy dir entry d-sec dirSec f ! // for later writing, on close -1 isOpen f ! // indicate opened d# device f ! // associate device with file 0 EOF f ! // not eof 0 error else 20 error 0 IsOpen f ! then ; // calculates actual file size as calculated ffrom the fat table. // : fileSize ( --- sectors ) // IsOpen f @ 0 > if 110 error then // TotalSec d @ // for // i Ls2Phys 0 < if leave then // next // ii // ; // random read - reads a file at a given logical sector, this is a sector // within that particular file regardless of where it is on the card // it uses Ls2Phys to calculate its actual position // return -1 if trying to read past end of clutser // **** can be improoved by looking at file size **** : r-random ( handle LogicalSec --- [buff]0|-1) swap => f# Ls2Phys // convert dup 0 < if drop -1 else sec@ 0 then ; // --------------- Public interfaces from this module ------------------ // note on file operations -1 is eof so this is opposite to what is norm : <0>f.open ( string handle -- -1|0) dup 0 devices between if r-open error# 0= // -1 okay else drop drop ." Handle value wrong " then ; : <0>f.rrandom ( handle sector -- 0|-1) // -1 on past end of file r-random ; : <0>f.fileSize ( handle -- sectors ) // file size => f# dirAdd filesize@ bytessec d @ / ; : <0>f.size ( handle -- bytes ) => f# dirAdd fileSize@ ; // size : <0>f.fb ( handle -- file-buffer ) => f# fatb ; // file buffer