To use this file copy and paste this:    // #URL-lib "http://pin1.org/forthlib/flb/SD-Card/fat-2.flb"   into BV Terminal 3 or here to download.

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // FAT formmatted SD card access // ========== P A R T 2 ====================================== // This is the directory listing and handleing, uses the device // buffer to read and write the directory sections. The operations // performed in this section are for reading, directory writing // is in a later section. // NOTE This shares many words with fat-1-a and so the SID numbers // Must be the same. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

// HISTORY: // Mar 2008 * Replaced [char] : with 58 emit because BVT gets confused

// 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" //

// CONSTANTS: // convenient to hold current file name here i think 12 vspace$ dir$ // // constants used as an offset into the directory for either creation // or modification times. 14 constant created // offset for creation and modifed dates 22 constant modified //


Full Contents of File

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// FAT formmatted SD card access
// ========== P A R T 2 ======================================
// This is the directory listing and handleing, uses the device
// buffer to read and write the directory sections. The operations
// performed in this section are for reading, directory writing
// is in a later section.
// NOTE This shares many words with fat-1-a and so the SID numbers
// Must be the same.
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

// HISTORY:
// Mar 2008 * Replaced [char] : with 58 emit because BVT gets confused

// 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"
//

// CONSTANTS:
// convenient to hold current file name here i think
12  vspace$  dir$
//
// constants used as an offset into the directory for either creation
// or modification times.
14  constant  created      // offset for creation and modifed dates
22  constant  modified
//

// Converts an entry number to a Dbuff address, en# is the
// entry number 0 being the first 1 the second etc. Returns the address
// into the buffer
// ***** Note this will also make sure that the correct
// sector is loaded for writing
: dir-entry ( en# -- address )
    32  *          // address of current entry
    BytesSec  d  @  u/mod // split to entry+sector
    Dir  d  @  +          // add director offset
    dup  d-sec  <>    // need to get another sector?
        if
            dsec@      // get next sector
        else
            drop        // current sector
        then
    dbuff  +   
;

// useful for obtaining the directory entry address for the current
// file handle
: dirAdd ( [handle] -- add )   direntry  f  ;  // get the address
   
// ========= directory operations ==============
// does not do subdirectories or long file names
//
// routines for extracting a directory entry information, all the words
// expect to be given the starting adedress of the entry
: filename@ ( add - string )   dir$  11  move  0  dir$  12  +  c!  dir$  ; 
: attrib@ ( add -- )   11  +  c@  ;
: start-clust@ ( add --clust )   dup  20  +  word16  16  lshift  swap  26  +  word16  +  ;
// returns a time word, set type to the constant for either created or
// modified to obtain the desired result
: c-dir-time ( add -- tword )   created  +  word16  ;  // this the modified time
: m-dir-time ( add -- tword )   modified  +  word16  ;  // this the modified time
: c-hours@ ( add -- hours )   c-dir-time  11  rshift  ;
: m-hours@ ( add -- hours )   m-dir-time  11  rshift  ;
: c-minutes@ ( add -- mins )   c-dir-time  5    rshift  &3f  and  ;
: m-minutes@ ( add -- mins )   m-dir-time  5    rshift  &3f  and  ;
: c-seconds@ ( add -- sec )   c-dir-time  &1f  and  ;
: m-seconds@ ( add -- sec )   m-dir-time  &1f  and  ;
: c-dir-date ( add -- tword )   created  +  2  +  word16  ;  // the modified time
: m-dir-date ( add -- tword )   modified  +  2  +  word16  ;  // he modified time
: c-year@ ( add -- year )   c-dir-date  9  rshift  1980  +  ;
: m-year@ ( add -- year )   m-dir-date  9  rshift  1980  +  ;
: c-month@ ( add -- month )   c-dir-date  5    rshift  &f  and  ; 
: m-month@ ( add -- month )   m-dir-date  5    rshift  &f  and  ; 
: c-day@ ( add -- sec )   c-dir-date  &1f  and  ;
: m-day@ ( add -- sec )   m-dir-date  &1f  and  ;
: filesize@ ( add -- size )   dup  28  +  word16  swap  30  +  word16  16  lshift  +  ; 
//
// creates a packed time and date word, opposite to above
// date and time for new directry entries
: packtime { h m s -- ptime }
    h  11  lshift
    m  5  lshift  +
    s  +
;
: packdate { y m d -- pdate }
    y  1980  -  9  lshift
    m  5  lshift  +
    d  +
;

// --- storing into entry
: filename! ( string add -- )   11  move  ;
: attrib!    ( val add -- )   11  +  c!  ;
: start-clust! ( val add -- )  
    >r  dup  16  rshift  r@  20  +  word16!  // high
    &ffff  and  r>  26  +  word16!  ;  // low
: c-time! ( addr h m s -- [packtime] )   packtime  swap  14  +  word16!  ;
: c-date! ( addr y m d -- [packtime] )   packdate  swap  16  +  word16!  ;
: m-time! ( addr h m s -- [packtime] )   packtime  swap  22  +  word16!  ;
: m-date! ( addr y m d -- [packtime] )   packdate  swap  24  +  word16!  ;
: filesize! ( size add -- )  
    >r  dup  16  rshift  r@  20  +  word16!  // high
    &0000ffff  and  r>  28  +  word16!  ;  // low


// =========== Directory printing =========================
// prints out date entry
: dir-date. ( add -- )
    dup  m-day@  <#  #  #  #>  stype  [char]  / emit
    dup  m-month@  <#  #  #  #>  stype  [char]  / emit
            m-year@  <#  #  #  #  #  #>  stype
;           
                   
// prints out time entry
: dir-time. ( add -- )
    dup  m-hours@  <#  #  #  #>  stype  58  emit
    dup  m-minutes@  <#  #  #  #>  stype  58  emit
            m-seconds@  <#  #  #  #>  stype
;

// dir entry will print out modified time and date with an offset of 6
// This prints whatever is in the array
: dir. ( add -- )
    dup  cr  filename@  stype  tab      // name
    dup  dir-date.  space  dup  dir-time.  tab 
    dup  start-clust@  .
    tab  filesize@  .
;               

// list the root directory of a card. The device buffer is used for this
// it has been set to here - see fat-1-a. Device is the device attached
// and is a number that begins with 0
// ( device ---)
: ls ( -- )
    -1  =>  d-sec      // force new read
    RootEntries  d  @      // number of directory entries
    for
        i  dir-entry    // need address to check for first byte
        dup  c@  0= 
        if 
            drop 
            unloop  escape 
        then
        c@  &e5  <>  if  i  dir-entry  dir.  then
    next
;

// =============== searching and finding =================
// This word takes a doted input and produces an output
// suitable for using as a serch string within a directory
// buffer
// input is s-add and output is also s-add, takes a standard
// 8+3 dotted format and converts it to 2 words with
// psaces, s-add1 sould be able to take 11 charaters +
// the 0 terminator
// S-ADD MUST BE MIN 12 CHARATCERS
: dot2pad { s-add --- s-add1 }
int len  Ic  Oc        // lenght of string in count, out count
v$ tmp  13              // string holder
        %@  tmp  11  bl  fill      // set tmp to all spaces
        s-add  length  =>  len   
        begin             
                s-add  Ic  +  c@        // fetch character
                dup  46  =                // check for .
                if
                        1  +>  Ic          // just inc input past .
                        8  =>  Oc          // for ext
                        drop
                else       
                        %@  tmp  Oc  +  c!
                        1  +>  Ic          // increment counters
                        1  +>  Oc 
                then       
        Ic  len  1-  > 
        until
        0  %@  tmp  11  +  c!        // terminator
        %@  tmp  toupper          // covert to upper case
; 

// given a dotted string e.g. fred.txt, this searches through
// the directory and returns with -1 and ad pointing to the start
// of the directory entry within the buffer, this also fills
// dir# array and dir$ string, but returns the address as well
// in case the directory needs to be updated
: dir-search ( string --- en# -1 |0)
int str
        dot2pad  =>  str      // convert string to padded
        RootEntries  d  @  // search all
        for
            i  dir-entry      // get entry address to test for 1st char
            dup  c@  0=  if  drop  0  unloop  escape  then      // get out end of search
            str  swap  s=          // see if match - dont care about deleted entries
            if
                i 
                -1  leave      // leave address and -1
            then                   
        next
;

// ================ Public interface ==========================
: <0>f.device ( device -- )   =>  d#  ;  // set device
: <0>f.find ( name -- [array] ad -1|0 )   dir-search  ;
: <0>f.ls ( -- )   ls  ;    // dir of current device