#include <p18f4620.h>
#include <stdio.h>
#include <delays.h>
#pragma config WDT = OFF, OSC = INTIO67, MCLRE = ON, XINST = OFF
#define CSel LATDbits.LATD2 //chip select line
#define LED LATDbits.LATD1
typedef unsigned long LBA;
void main(void);
int writeSector(LBA,char *,char *);
int readSector(LBA, char *,char *);
int initMedia(void);
int sendSDCmd(unsigned char,LBA);
void delay_s(unsigned char);
void delay_ms(unsigned char);
void delay_us(unsigned char);
unsigned char writeSPI(unsigned char);
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
#pragma udata data1
char data1[256];
#pragma udata data2
char data2[256];
#pragma udata buffer1
char buffer1[256];
#pragma udata buffer2
char buffer2[256];
void main(void){
LBA addr;
int i,r;
TRISD = 0;
TRISC = 0b00010000;
CSel=1; //init chip select (active low)
LED=0; //LED off
OSCCON = 0x72; //8MHz clock
OSCTUNEbits.PLLEN = 0; //disable PLL
while(!OSCCONbits.IOFS); //wait for osc stable
SSPSTAT = 0b00000000; //SMP(7)=0, CKE(6)=0 (clock edge idle to active)
SSPCON1 = 0b00010010; //CKP(4)=1 clock polarity (idle high)
//SSPM3:SSPM0(3:0)=010 spi clock FOSC/64 (<400kHz)
SSPCON1bits.SSPEN=1; //SSPEN(5)=1 enable SPI
for(i=0;i<256;i++){ //fill the send buffers
data1[i]=i;
data2[i]=i;
buffer1[i]=0; //and clear the receive buffers
buffer2[i]=0;
}
r=initMedia();
if(r){ //card init failed - 1 blink
while(1){
LED=1;
delay_ms(150);
LED=0;
delay_s(1);
}
}
else
{
//card init passed all good now use it lol
if(!readSector(0,buffer1,buffer2)){ //addr+i,buffer1,buffer2)){
while(1){ //verify failed - 3 blinks
LED=1;
delay_ms(150);
LED=0;
delay_ms(150);
LED=1;
delay_ms(150);
LED=0;
delay_ms(150);
LED=1;
delay_ms(150);
LED=0;
delay_s(1);
}
}
}
while(1){ //success!
LED=1;
delay_s(1);
LED=0;
delay_s(1);
}
}
int writeSector(LBA a,char *p1,char *p2)
{
unsigned r,i;
LED=1; //turn on write LED
r=sendSDCmd(24,(a<<9));
if(r==0){
writeSPI(0xfe); //send Data Start byte
for(i=0;i<256;i++) //first 256 bytes
writeSPI(*p1++);
for(i=0;i<256;i++) //second 256 bytes
writeSPI(*p2++);
writeSPI(0xff); //send dummy CRC
writeSPI(0xff);
if((r=writeSPI(0xff) & 0x0f) == 0x05){ //check if data accepted
for(i=10000;i>0;i--){
if(r=writeSPI(0xff))
break;
}
}
else
r=0; //fail
}
CSel=1;writeSPI(0xff); //disable SD
LED = 0; //LED off
return(r);
}
int readSector(LBA a, char *p1, char *p2)
{
int r,i;
LED = 1; //turn on read LED
r = sendSDCmd(17,(a<<9));
if(r==0){ //check if command was accepted
i=10000; //wait for a response
do{
r = writeSPI(0xff);
if(r==0xfe)
break;
}while(--i > 0);
if(i){ //if no timeout, read 512 byte sector
for(i=0;i<256;i++)
*p1++ = writeSPI(0xff);
for(i=0;i<256;i++)
*p2++ = writeSPI(0xff);
writeSPI(0xff); //ignore CRC
writeSPI(0xff);
}
}
CSel=1;writeSPI(0xff); //disable SD
LED = 0; //read LED off
return(r == 0xfe);
}
int initMedia(void)
{
int i,r;
CSel=1;writeSPI(0xff); //while card is not selected
for(i=0;i<16;i++) //send 80 clock cycles to start up
writeSPI(0xff);
CSel=0; //then select the card
r = sendSDCmd(0,0); //send reset command to enter SPI mode
CSel=1;writeSPI(0xff); //disable SD
if(r != 1) //error check - need 1
return 0x84;
i = 10000; //send init for up to 0.3s
CSel=0;
do{
r = sendSDCmd(1,0); //send init command
CSel=1;writeSPI(0xff); //disable SD
if(!r) break;
}while(--i > 0);
if(i==0) //time out error 0x85
return 0x85;
SSPCON1 = 0b00010000; //speed up spi clock
SSPCON1bits.SSPEN=1;
return 0;
}
int sendSDCmd(unsigned char c,LBA a)
{
int i,r;
CSel=0; //send command packet (6 bytes)
writeSPI(c|0x40); //send command & frame bit
writeSPI(a>>24); //send 32-bit address
writeSPI(a>>16);
writeSPI(a>>8);
writeSPI(a);
writeSPI(0x95); //send CRC
i=9; //wait for response
do{
r=writeSPI(0xff); //check if ready
if(r != 0xff)
break;
}while(--i > 0);
return(r);
}
unsigned char writeSPI(unsigned char send)
{
SSPBUF=send;
while(!SSPSTATbits.BF);
return SSPBUF;
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
void delay_s(unsigned char x)
{
char var1;
for(var1=0;var1<x;var1++)
{
Delay10KTCYx(200); //2,000,000 cycles = 1 second
}
}
void delay_ms(unsigned char x)
{
char var1;
for(var1=0;var1<x;var1++)
{
Delay1KTCYx(2); //2,000 cycles = 1 us
}
}
void delay_us(unsigned char x)
{
char var1;
for(var1=0;var1<x;var1++)
{
Delay1TCY(); //2 cycle = 1 us
Delay1TCY();
}
}