To use this file copy and paste this:
// #URL-lib "http://pin1.org/forthlib/flb/SD-Card/fat-1.flb" into BV Terminal 3
or here to download.
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// FAT formmatted SD card access
// ========== P A R T 1 ======================================
// This has the buffers and low level sector handeling. Use this for
// mounting the device and reserving space in RAM for the buffers
// Unusually in this file there are a lot of non colon words that are
// compiled as the file is read
// This file will compile stand alone as there are no duplicated
// words used
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// REQUIRES:
// #URL-lib "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
// CONSTANTS:
// The main access is via static buffers which simplifies file handleing
// operations. Set the constant below to the number of buffers required,
// one buffer is required for each file open but beware thay take
// about 300 bytes each.
1 constant devices // number of devices
2 constant fileBuffers // number of file buffers
2 constant rclust // always 2 don't know why or how to determine otherwise
512 vspace$ dbuff // buffer used for system
//
// These are of major importance and simplyfy coding considerably
// the last sector read is always known so that it can be easily
// updated - I got a long way before realising this
integer d-sec // current sector being worked on for Dbuff
integer f-sec // current sector being worked on for fatb
integer error# // error number
integer d# // this is the current file handle makes access much easier
integer f# // this is the current file handle makes access much easier
//
// <><><><><><><><><><><><><><><<><><><><><><><><><><><><>
// This is an array to store the device geometry, is is an array so that
// more than one device is possible. Note that *array uses the variable
// space so this can be saved to flash withou loosing the buffer
0 constant MBR // address of start of MBR
4 constant FATTable1 // address of start of FAT1
8 constant FATTable2 // address of start of FAT1
12 constant Dir // address of start of root dir
16 constant RootEntries // number of directory entries
20 constant FileSpace // address of start of filespace - rclust
24 constant BytesSec // number of bytes per sector
28 constant SectClust // number of sectors per cluster
32 constant SectFat // number of sectors per fat
36 constant ReservedSectors //
40 constant TotalSec // Total size in sectors
44 constant Fat# // fat 12 or fat 16
48 constant csel // cs line for this device -ve is port 1
devices 56 *array device#
// <><><><><><><><><><><><><><><<><><><><><><><><><><><><>
//
// <><><><><><><><><><><><><><><<><><><><><><><><><><><><>
// The buffers are accessed via a file hanlde that simply
// points to the array index
// A buffer can access more than one device
4 constant EOF // kept as part of array to prevent reading past end
8 constant device // when open points to a particular device
12 constant isOpen // -1 if file is open
// has a directory connection so that a file can be associated to
// a directory that can be wriiten back only at file close
// the whole 32 byte directory entry is kept in this buffer
16 constant dirSec // sector where this entry is stored
20 constant en# // entry number for wtiting back
24 constant dirEntry // copy of root entry
60 constant fatbb // note space for dir-entry
Full Contents of File
1  constant  devices       
2  constant  fileBuffers   
2  constant  rclust     
512  vspace$  dbuff     
integer  d-sec         
integer  f-sec         
integer  error#       
integer  d#       
integer  f#       
0  constant  MBR                       
4  constant  FATTable1           
8  constant  FATTable2           
12  constant  Dir                       
16  constant  RootEntries       
20  constant  FileSpace           
24  constant  BytesSec       
28  constant  SectClust     
32  constant  SectFat       
36  constant  ReservedSectors 
40  constant  TotalSec             
44  constant  Fat#             
48  constant  csel             
devices  56  *array  device#
4  constant  EOF     
8  constant  device     
12  constant  isOpen     
16  constant  dirSec     
20  constant  en#           
24  constant  dirEntry 
60  constant  fatbb   
fileBuffers  572  *array  file#   
: error
    dup  =>  error#
    100  >  if  cr  ."  error  number  "  error#  .  abort  then
;   
: dd  device#  +  ;
: d  d#  device#  +  ;
: f  f#  file#  +  ;
: fatb  fatbb  f  ;
: word16
        dup  c@     
        swap  1+  c@  &100  *  +
;
: word16!
    >r       
    dup  &ff  and    r@  c!       
    8  rshift  &ff  and  r>  1+  c!   
;   
: (sec@) 
        csel  d  @  mmc.cs     
        rot  over  *
        mmc.read       
        -1  <>  abort"  Can't  read  MMC  Card"
;
: Dsec@
    dup  =>  d-sec       
    dbuff  BytesSec  d  @
   
;
   
: secfetch   
        dup  =>  f-sec       
        device  f  @  =>  d#       
        fatb     
        BytesSec  d  @ 
       
;
: (sec!) 
    BytesSec  d  @  swap  over  *               
    swap       
    mmc.write
    -1  <>  abort"  Can't  write  MMC  Card"
;
: secstore     
    fatb  swap 
;
: Dsec!
    dbuff  swap 
;       
: MBRsec
       
       
        512  BytesSec  d  !           
        0  Dsec@     
        dbuff  c@  &eb  =
        if
                0
        else
                dbuff  454  +  c@
        then
;
: Hword16dbuff  +  word16  ; 
: Geo
        MBRSec  dup  MBR  d  ! 
       
       
        Dsec@         
       
        &b  Hword16 
        BytesSec  d  !     
       
        dbuff  &39  +  c@  48  -  10  *     
        dbuff  &3a  +  c@  48  -     
        + 
        fat#  d  !           
        &e  Hword16  dup  ReservedSectors  d  ! 
        mbr  d  @  +  FatTable1  d  ! 
        &16  Hword16  dup  SectFat  d  ! 
        FatTable1  d  @  +  FatTable2  d  !
        &16  Hword16  FatTable2  d  @  +  Dir  d  ! 
        dbuff  &d  +  c@    SectClust  d  !         
        &11  Hword16  dup  RootEntries  d  !
        32  *                               
        BytesSec  d  @ 
        SectClust  d  @  rclust  *  -   
        FileSpace  d  !
        &13  Hword16  dup  0=
        if  drop  &20  Hword16  &22  Hword16  16  lshift  +  then   
        TotalSec  d  !     
;                   
: tab9  emit  ;
: (geo.)dup  ph.  tab  pd.  ;
: geodot
    cr  ."  name        "  tab  ."  size
    cr  ."  MBR              "  tab  mbr  d  @ 
    cr  ."  FatTable1  "  tab  FatTable1  d  @ 
    cr  ."  FatTable2  "  tab  FatTable2  d  @ 
    cr  ."  Dir              "  tab  Dir  d  @ 
    cr  ."  RootEntries"    tab  RootEntries  d  @ 
    cr  ."  FileSpace  "  tab  FileSpace  d  @ 
    cr  ."  Bytes
    cr  ."  Sect
    cr  ."  Sect
    cr  ."  ReservedSect"  tab  ReservedSectors  d  @ 
    cr  ."  Fat  type
    cr
    cr  ."  Sectors  Total  "  tab  TotalSec  d  @ 
    cr  ."  Size  MB      "  tab  TotalSec  d  @  BytesSec  d  @  *  1000000 
;
: <0>mmc.mount
    =>  d#         
    dup  csel  d  !       
    mmc.start         
    if
        geo                     
    else
        cr  ."  can't  start  mmc  card  "
        101  error
    then               
;
: <0>fb  fatb  ;
: <0>geo.  geodot  ;     
: <0>sec@  secfetch  ; 
: <0>sec!  secstore  ;