AtomSoft
Well-Known Member
hey guys im working on SD stuff and FAT16/32 on a PIC18F4620.. using chans code for petit fat fs..
Here is the code you need to get this working;
I called it mmc.c
On his site is code to list directories and files:
my Altered version to show icon and file name;
Also i just created a function which when you place a filename in it, it will return the extension ... great for looping through a directory and loading only txt files or images....
Here is the code you need to get this working;
I called it mmc.c
Code:
/*-----------------------------------------------------------------------*/
/* PFF - Low level disk control module for ATtiny85 (C)ChaN, 2009 */
/*-----------------------------------------------------------------------*/
#include <p18cxxx.h>
#include "diskio.h"
/* SPI control functions (defined in usi.S) */
void init_spi (void);
void xmit_spi (BYTE);
BYTE rcv_spi (void);
BYTE writeSPI( BYTE data_out) ;
/* Definitions for MMC/SDC command */
#define CMD0 (0x40+0) /* GO_IDLE_STATE */
#define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */
#define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */
#define CMD8 (0x40+8) /* SEND_IF_COND */
#define CMD9 (0x40+9) /* SEND_CSD */
#define CMD10 (0x40+10) /* SEND_CID */
#define CMD12 (0x40+12) /* STOP_TRANSMISSION */
#define ACMD13 (0xC0+13) /* SD_STATUS (SDC) */
#define CMD16 (0x40+16) /* SET_BLOCKLEN */
#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
#define CMD18 (0x40+18) /* READ_MULTIPLE_BLOCK */
#define CMD23 (0x40+23) /* SET_BLOCK_COUNT (MMC) */
#define ACMD23 (0xC0+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24 (0x40+24) /* WRITE_BLOCK */
#define CMD25 (0x40+25) /* WRITE_MULTIPLE_BLOCK */
#define CMD55 (0x40+55) /* APP_CMD */
#define CMD58 (0x40+58) /* READ_OCR */
/* Port Controls (Platform dependent) */
#define SELECT() MMC_CS=0 /* MMC CS = L */
void DESELECT(void){
MMC_CS=1; /* MMC CS = H */
writeSPI(0xFF);
}
/*--------------------------------------------------------------------------
Module Private Functions
---------------------------------------------------------------------------*/
BYTE CardType;
/*-----------------------------------------------------------------------*/
/* Wait for card ready */
/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* Deselect the card and release SPI bus */
/*-----------------------------------------------------------------------*/
static
void release_spi (void)
{
DESELECT();
TRISC = 0b00010000;
SSPSTAT = 0b01000000;
SSPCON1 = 0b00000010;
SSPCON1bits.SSPEN = 1;
}
/*-----------------------------------------------------------------------*/
/* Send a command packet to MMC */
/*-----------------------------------------------------------------------*/
static
BYTE send_cmd (
BYTE cmd, /* Command byte */
DWORD arg /* Argument */
)
{
BYTE res;
BYTE i;
DESELECT();
/* Select the card and wait for ready */
SELECT();
/* Send command packet */
xmit_spi(cmd); /* Start + Command index */
xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
xmit_spi((BYTE)arg); /* Argument[7..0] */
xmit_spi(0x95); /* Valid CRC for CMD0(0) */
for( i=0; i<10; i++)
{
res = rcv_spi();
if ( res != 0xFF)
break;
}
return res; /* Return with the response value */
}
void init_spi(void){
SSPCON1bits.SSPEN = 0;
TRISC = 0b00010000;
SSPSTAT = 0x00;
SSPSTATbits.CKE = 1;
SSPSTATbits.SMP = 0;
SSPCON1 = 0x00;
SSPCON1bits.CKP = 0;
SSPCON1bits.SSPM3 = 0;
SSPCON1bits.SSPM2 = 0;
SSPCON1bits.SSPM1 = 1;
SSPCON1bits.SSPM0 = 0;
SSPCON1bits.SSPEN = 1;
}
BYTE rcv_spi(void){
BYTE temp_data;
temp_data = writeSPI(0xFF);
return temp_data;
}
void xmit_spi (BYTE data){
writeSPI(data);
}
/*--------------------------------------------------------------------------
Public Functions
---------------------------------------------------------------------------*/
BYTE writeSPI( BYTE data_out )
{
BYTE tmp;
if(PIR1bits.SSPIF) PIR1bits.SSPIF = 0;
tmp = SSPBUF ;
SSPBUF = data_out;
if ( SSPCON1 & 0x80 ){ // test if write collision occurred
SSPCON1bits.WCOL = 0;
return ( 254 ); // if WCOL bit is set return FE
}
while(!PIR1bits.SSPIF); // wait transfer complete
PIR1bits.SSPIF = 0;
return SSPBUF; // read the received value
}
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (void)
{
WORD tmr;
BYTE r,i;
tmr = 10000;
r = 0;
init_spi();
// 1. with the card NOT selected
DESELECT();
// 2. send 80 clock cycles start up
for ( i=0; i<10; i++)
writeSPI(0xFF);
// 3. now select the card
SELECT();
// 4. send a single RESET command
r = send_cmd(CMD0, 0);
DESELECT();
if ( r != 1) // must return Idle
return 1; // comand rejected
// 5. send repeatedly INIT until Idle terminates
for (i=0; i<tmr; i++)
{
r = send_cmd(CMD1, 0); DESELECT();
if ( !r)
break;
}
if ( i == tmr)
return 2; // init timed out
return r;
}
/*-----------------------------------------------------------------------*/
/* Read partial sector */
/*-----------------------------------------------------------------------*/
DRESULT disk_readp (
BYTE *dest, /* Pointer to the destination object to put data */
DWORD lba, /* Start sector number (LBA) */
WORD ofs, /* Byte offset in the sector (0..511) */
WORD cnt /* Byte count (1..512), b15:destination flag */
)
{
DRESULT res;
BYTE *p, dev, rc;
WORD cf, tmr;
BYTE (*f)(BYTE);
dev = (cnt & 0x8000) ? 1 : 0; // Destination type
cnt &= 0x7FFF;
if (!cnt || ofs + cnt > 512) return RES_PARERR;
if (!(CardType & CT_BLOCK)) lba *= 512; // Convert to byte address if needed
res = RES_ERROR;
if (send_cmd(CMD17, lba) == 0) { // READ_SINGLE_BLOCK
tmr = 1000;
do { // Wait for data packet in timeout of 200ms
rc = rcv_spi();
} while (rc == 0xFF && --tmr);
if (rc == 0xFE) {
cf = 512 + 2 - ofs - cnt;
while (ofs--) rcv_spi(); // Skip top of sector
//if (dev) { // Receive middle of the sector
// f = *dest;
// do
// res = f(rcv_spi());
// while (--cnt && res);
// cf += cnt;
//} else {
p = dest;
do
*p++ = rcv_spi();
while (--cnt);
//}
do // Skip bottom of sector and CRC
rcv_spi();
while (--cf);
res = cnt ? RES_STRERR : RES_OK;
}
}
release_spi();
return cnt ? RES_ERROR : RES_OK;
}
On his site is code to list directories and files:
my Altered version to show icon and file name;
Code:
FRESULT scan_files (char* path)
{
FRESULT res;
FILINFO fno;
DIR dir;
int i,x;
int cnt;
unsigned char myext[4];
temp[0] = '/';
for(x=1;x<17;x++)
temp[x] = 0;
cnt = 5;
res = pf_opendir(&dir, path);
if (res == FR_OK) {
i = strlen(path);
while(1) {
res = pf_readdir(&dir, &fno);
if (res != FR_OK || fno.fname[0] == 0) break;
if (fno.fattrib & AM_DIR) {
//strcat(temp,fno.fname);
LCDWriteBMP(fold,cnt-1,2);
LCDPutStr(fno.fname,cnt,13,0,BLACK,WHITE);
cnt+=10;
} else {
LCDWriteBMP(file,cnt-1,2);
//get_ext(fno.fname,myext);
LCDPutStr(myext,cnt,13,0,BLACK,WHITE);
LCDPutStr(fno.fname,cnt,13,0,BLACK,WHITE);
cnt+=10;
//printf("%s/%s\n", path, fno.fname);
}
}
}
return res;
}
Also i just created a function which when you place a filename in it, it will return the extension ... great for looping through a directory and loading only txt files or images....
Code:
void get_ext (char* path,char* ext)
{
int i,x,end;
i = strlen(path);
for (x=0;x<i;x++){
if(*path++ == '.') break;
}
end = i - x;
for(x=0;x<end;x++)
*ext++ = *path++;
}
Last edited: