#include "HardwareProfile.h"
#include "spi.h"
#include "mmc2.h"
#include "UART.h"
// Written by Ed Waugh 2004,
www.edwaugh.co.uk
// for the original source, and hundreds more examples of PIC C code, see:
//
https://www.microchipc.com/sourcecode/#mmc
/************************** MMC Init **************************************/
/* Initialises the MMC into SPI mode and sets block size, returns 0 on success */
int mmc_init(void)
{
int i, a1, a2;
SD_CS_IO = 1; // ensure SPI memory device
// Chip Select is reset
OpenSPI1(SPI_FOSC_64, MODE_00, SMPMID);
for(i=0;i<10;i++) // initialise the MMC card into SPI mode by sending clks on
{
WriteSPI1(0xFF);
}
putrsUART("Initialization\n\r");
SD_CS_IO = 0; // set SS = 0 (on) tells card to go to spi mode when it receives reset
WriteSPI1(0x40); // send reset command
WriteSPI1(0x00); // all the arguments are 0x00 for the reset command
WriteSPI1(0x00);
WriteSPI1(0x00);
WriteSPI1(0x00);
WriteSPI1(0x95); // precalculated checksum as we are still in MMC mode
if(mmc_response(0x01)==1)
return 1; // if = 1 then there was a timeout waiting for 0x01 from the mmc
SD_CS_IO = 1; // set SS = 1 (off)
putrsUART("Got response from MMC\n\r");
i = 0;
while(i < 255) // must keep sending command if response
{
putrsUART("trying response 0x00 from MMC\n\r");
WriteSPI(0xFF);
SD_CS_IO = 0; // set SS = 0 (on) tells card to go to spi mode when it receives reset
WriteSPI(0x77); // CMD55
WriteSPI(0x00);
WriteSPI(0x00);
WriteSPI(0x00);
WriteSPI(0x00);
WriteSPI(0xFF);
SD_CS_IO = 1; // set SS = 1 (off)
WriteSPI(0xFF);
SD_CS_IO = 0; // set SS = 0 (on) tells card to go to spi mode when it receives reset
WriteSPI(0x69); // CMD41
WriteSPI(0x40); // HCS=1
WriteSPI(0x00);
WriteSPI(0x00);
WriteSPI(0x00);
WriteSPI(0xFF);
if (mmc_response(0x00) == 0)
break;
SD_CS_IO = 1; // set SS = 1 (off)
i++;
}
if(i >= 254)
return 1; // if >= 254 then there was a timeout waiting for 0x00 from the mmc
putrsUART("Got out of idle response from MMC\n\r");
SD_CS_IO = 1; // set SS = 1 (off)
WriteSPI1(0xFF); // extra clocks to allow mmc to finish off what it is doing
SD_CS_IO = 0; // set SS = 0 (on)
WriteSPI1(0x50); // send mmc command one to bring out of idle state
WriteSPI1(0x00);
WriteSPI1(0x00);
WriteSPI1(0x02); // high block length bits - 512 bytes
WriteSPI1(0x00); // low block length bits
WriteSPI1(0xFF); // checksum is no longer required but we always send 0xFF
if((mmc_response(0x00))==1)
return 1;
SD_CS_IO = 1; // set SS = 1 (off)
putrsUART("Got set block length response from MMC\n\r");
CloseSPI1();
OpenSPI1(SPI_FOSC_4, MODE_00, SMPMID);
return 0;
}
/************************** MMC get response **************************************/
/**** Repeatedly reads the MMC until we get the response we want or timeout ****/
int mmc_response(unsigned char response)
{
unsigned long count = 0xFFFF; // 16bit repeat, it may be possible to shrink this to 8 bit but there is not much point
while(ReadSPI1() != response && --count > 0);
if(count==0)
return 1; // loop was exited due to timeout
else
return 0; // loop was exited before timeout
}