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

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Low level access for MMC and SD cards. Provides basic // reading and writing to card using physical addresses // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

// REQUIRES: // #URL-lib "http://pin1.org/forthlib/flb/General/soft1.flb" // #URL-lib "http://pin1.org/forthlib/flb/General/pinsel.flb" // #URL-lib "http://pin1.org/forthlib/flb/General/SPI.flb"

// CONSTANTS: integer cspin // used for chip select integer inital // indicator for initalisation of card


Full Contents of File

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// Low level access for MMC and SD cards. Provides basic
// reading and writing to card using physical addresses
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

// REQUIRES:
// #URL-lib "http://pin1.org/forthlib/flb/General/soft1.flb"
// #URL-lib "http://pin1.org/forthlib/flb/General/pinsel.flb"
// #URL-lib "http://pin1.org/forthlib/flb/General/SPI.flb"

// CONSTANTS:
integer  cspin      // used for chip select
integer  inital    // indicator for initalisation of card

// chip select
: cs ( 0|1 -- )   cspin  p!  ;    // uses -ve if port 1 -- see pinsel-a

// after power up this is required
: reset1  cs  20  for  &ff  spi  drop  next  ;     

// initialise mmc stage one
// (---)
: init
        cspin  io-out        // cs set to o/p
        spi.init
        reset           
;
// card should return fe, leaves true if this is the case
// ( --- 0|-1)
: result
        0  // error value for result
        500  for
                &ff  spi  &fe  =  if  drop  -1  leave  then
        next       
;
// Send command to the mmc device followed by the data
// the data is packed into a 32 bit word, dummy CRC is
// used. NOTE send Most significant byte goes first
// ( 32data cmd -- result)
: cmd
        &ff  spi  drop        // flush
        &40  or  spi  drop  // cmd
        dup  24  rshift  &ff  and  spi  drop  // 4
        dup  16  rshift  &ff  and  spi  drop  // 3
        dup    8  rshift  &ff  and  spi  drop  // 2
        &ff  and  spi  drop  // 1
        &95  spi  drop        // dummy crc
        &ff  spi  drop
        &ff  spi                  // return code
;
: cmd2cmd  &ff  spi  ;    // 2 byte return

// set block length, specified as a 32 bit
// number, normally 512
// (len---)
: blocklen
        0  cs 
        16  cmd  drop
        1  cs
;

// resets card and returns counter of how many times
// cmd1 was tried, if 0 then card was not reset.
// This is the main start up command when a card is inserted
// all commands can be performed after this.
// (---x)
: start
        init
        0  cs                        // enable
        0                              // return value
        0  0  cmd  1  =        // cmd0
        if
                500  for
                        1  ms              // send cmd1 until 0
                        0  1  cmd  0=
                        if  i  +  leave  then
                next
        then                       
        1  cs                        // disable
        dup  0  >  if  512  blocklen  then  // set block length
;

// read and display card id
// (---[to display])
: id.
        0  cs
        0  10  cmd  drop
        result
        if
                16  for
                        &ff  spi  ph.
                next
                cr
        else
                ."  Cant  initialise  card"               
        then
        1  cs
;
               
// Reads a block of data into buffer from DevAddress
// for u number of bytes
// returns true on success
// ( buffer u DevAddress ---0|-1)
: readblock
        0  cs
        17  cmd  drop          // read device
        result                    // wait for &fe
        if
                over  +  swap    do  // buf+u, buf
                        &ff  spi  i  c!
                loop
                2  for  &ff  spi  drop  next          // check sum
                -1
        else
                2drop  0               
        then
        1  cs
; 

// ============ writing ====================
// writefrom buffer to a specified
// device address u number of bytes
// returns -1 on success
// (buf addr u ----1|0)
: writeblock
        >r            // number of bytes
        0  cs
        24  cmd  0=        // write command
        if
                &fe  spi  drop                // marker
                r>  over  +  swap
                do
                        i  c@  spi  drop
                next
                2  for  &ff  spi  drop  next      // crc bytes
                5000  for  &ff  spi  &ff  =  if  leave  then  next          // clear
                leave?  -1  *      // leave -1 if left loop
                1  cs
        else
                r>  drop      // number of bytes
                1  cs
                drop        // buffer
                0
                ."  Problem  with  MMC  Write"
        then               
; 

// ========================= debug =================================
// 516 vspace$ b1
// : xx 3 => cspin start . ;
// : x
// 5
// for
// b1 512 512000 readblock cr 0= if abort then
// ." read " i . space
// b1 512000 512 writeblock . ." written " i .
// next
// ;

// ------------- Public interface --------------------------
// sets chip select pin uses -ve for port 1
: <0>mmc.cs ( pin -- )   =>  cspin  ;      // for switching betwen devices
: <0>mmc.start ( cs -- x )   =>  cspin  start  ;        // initialise mmc card
: <0>mmc.id. ( -- id's )   id.  ;    // just card id, not much use really
// reads a bloc of data u bytes big, buff is an area of memory to put
// the data inot and addr is the address of memory in the device to read
: <0>mmc.read ( Buff, u, addr --- 0|-1)   readblock  ;
: <0>mmc.write ( buf addr u --- 0|-1 )   writeblock  ;