// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 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 : reset 1 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 ; : cmd2 cmd &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 ;