Running FAT16 on the Ti Launchpad

9.3K109

Intro: Running FAT16 on the Ti Launchpad


This video demonstates the code in action for reading a SD card

you will need the following:
Any MSP430 chip with USI and 4k or more flash
an SD Card
a capcitor (anything more than 10uf)
Code Composer Studio 5 (grace makes things easier)

STEP 1: Start Up Filesystem

You need to download the code and include the files in the SD folder of the project:
MMC.c
MMC.h
ThinFAT.c
ThinFAT.h

#include "mmc.h"
#include "ThinFAT.h"


then you have to edit the MMC.h file at the beginning where you want your card select port to be:
//card select currently set to P2.7
#define SD_CSn_PxOUT    P2OUT
#define SD_CSn_PxDIR    P2DIR
#define SD_CSn_PIN      BIT7

Wireing:
P1.2 - TA0.1 - Left Channel Out
P1.3 - Input for Playing and Changing Music File
P1.4 - TA0.2 - Right Channel Out
P1.5 - SMCLK out - SD Card Pin 5
P1.6 - SDO - SD Card Pin 2 MOSI
P1.7 - SDA - SD Card Pin 7 MISO
P2.7 - CS - SD Card Pin 1 Card Select
VCC - SD Card Pin 3,6
Ground - SD Card Pin 4

Next you initilise the FAT file system and the SD card for reading:
ThinFAT_Init();

STEP 2: Index Files on SD Card

First you need to write a callback for the Filesystem to capture data on each file as it is read:

struct sPlaylist {
unsigned int CurrentFile;
unsigned int FileCount;
unsigned int FileIndex;
} Playlist;

char IndexWavFile(unsigned char Filename[],unsigned char Extension[])
{
if(Extension[0]==87 && Extension[1]==65 && Extension[2]==86)
{
  Playlist.FileCount++;
}
return ThinFAT_Fail;
}
The code above recive the filename and extension of the file being opened.  it then checks the file extension if it is 'wav' you can check any file extension useing the following table as it's acsii encoded:
http://www.asciitable.com/

the callback returns a fail for all of the files as it's only meant to index files.  you can use this same callback for indexing folders too.

once you have made the callback for indexing these files you can then hand this callback to the filesystem to be run for each of the files or folders found in the current folder.  the end of file callback needs to be included even if it's not going to be used.

// Find a file
ThinFAT_FindFile((*IndexWavFile), (*EndWavFile));
// Find a folder
ThinFAT_FindFolder((*IndexFolders), (*EndWavFile));

STEP 3: Open a File for Reading

now that you have indexed the files on your current folder, you need to open one of them which you need another callback for which can return ThinFAT_Success for.  you can do this with a simple index to check which one it is as the callback will be called in the same order for all of the files in a given folder.

char CheckWavFile(unsigned char Filename[],unsigned char Extension[])
{
if(Extension[0]==87 && Extension[1]==65 && Extension[2]==86)
{
  if(Playlist.FileIndex==Playlist.CurrentFile)
  {
   Playlist.FileIndex=0;
return ThinFAT_Success;
  }else
  {
   Playlist.FileIndex++;
return ThinFAT_Fail;
  }
}
return ThinFAT_Fail;
}

next what you need is an end of file callback for when you reach the end of the file you are playing.  you can also include a function to dectect if the file is active or not so you can use this same callback for closeing the file manualy yourself partway through reading.  you first test in this fuction with ThinFAT_ActiveFile() if the file is active and then run ThinFAT_CloseFile() if the file is active.
void EndWavFile()
{
WDTCTL = WDTPW + WDTHOLD;  // Pause Updating Samples
// Check if file is active and close it
if(ThinFAT_ActiveFile()==ThinFAT_Success)
{ThinFAT_CloseFile();}
Playlist.FileIndex=0;
}

once you have both callbacks ready you can call the command to search and open the file.
ThinFAT_FindFile((*CheckWavFile), (*EndWavFile));

STEP 4: Read a File Stream

once a file is opened for streaming you only need to call the following command to read a byte from a file:
audioOut.CurrentSample =ThinFATReadByte();

you can also read Int and Long values from a file but you will need to know if they are big or little endian format.  in each of the commands a lower case B or a L prefix the type of value being read.

// Read a Little-endian Int
audioOut.CurrentSample =ThinFATReadlInt()

// Read a Big Endian Int
audioOut.CurrentSample =ThinFATReadbInt()

// Read a Little-endian Long
audioOut.CurrentSample =ThinFATReadlLong()

// Read a Big-endian Long
audioOut.CurrentSample =ThinFATReadbLong()

to check on the progress of reading the file you can call ThinFAT_FileProgress() which will return the current sector of the file being read from the SD card.  you can then compare this to the file size which is returned by ThinFAT_FileSize():
CurrentFileSector = ThinFAT_FileProgress();
CurrentFileSize = ThinFAT_FileSize();

When you are finished with the file you can call:
ThinFAT_CloseFile();
but you also need a callback ready for when the file is finished that can also tidy up the function your performing.

STEP 5: Factors to Consider

There are some important things to consider about useing this filesystem:
it only reads FAT16 filesystems - no SDHC support
it wont read long filenames - keep file names less than 8 characters, extensions below 3 characters
it has no support for file fragments - defrag your SD card before reading
it uses 3K of flash - use a microcontroller with 3K or more flash space

This Project is Based on the Following:
http://www.secure-digital-card-source-code-driver.com/layout-of-a-mmc-or-sd-card-with-fat/the-master-boot-record
http://www.tavi.co.uk/phobos/fat.html
http://www.maverick-os.dk/FileSystemFormats/FAT16_FileSystem.html
http://www.diylife.com/2008/04/25/make-a-talking-msp430-microcontroller/
http://www.ti.com/mcu/docs/litabsmultiplefilelist.tsp?sectionId=96&tabId=1502&literatureNumber=slaa281b&docCategoryId=1&familyId=342

With the Watchdog timer on a 512 divider you have about the maximum sample rate that your processor should be able to handle without skipping some bytes.  you can reach:
2kHz Sample rate on 1MHz
16kHz Sample rate on 8MHz
24kHz Sample rate on 12MHz
32kHz Sample rate on 16MHz
however keep in mind that the power useage is detirmined by your DCO frequency, the faster you run your system the more power that you use.  and that soldering directly to the pins of a Micro-SD adaptor makes a fantastic Micro-SD Slot.

9 Comments

Could you give us a schematic of this project? Thanks :)

hi!

My compiler cannot find the declarions of USISRL and USICNT ... where can i find the file with those variables?

Thx

Fávero
Hi! Thanks for making this instructable.

I am wondering if you were able to get a read/write system working? Or perhaps just a write?

Thanks in advance!
sorry, I could only handle read only - writing needs to at least store a whole block or you lose everything that was on that block. that makes it difficult to write to the file system without it screwing up all the other files.
Thanks for the information! =)
hey dude... i don't understand why all the wires.. can you tell me what are the funtionality?
and the FAT file system.. where i do that?? sorry, but i'm REALLY new in this.... i'm lost.
Hey, it's a great project that i want to reproduce... of course, if you let me jeje
basically the FAT16 file system is how regular SD cards, not SDHC are formatted. this allows you to with the right adaptor and power supply to the card to search for files and folders and then read from them. it dosen't support long file names. but you can make any kind of search function you feel like.

on your microcontoller you'll have pins that you can wire to different things and they all have names. this is just the lables for what they go to in this programmed example. you should look up how SPI works, it'll be a good start to understanding how this works. also SD cards have the same voltage tolerances (excluding micro) as the MSP430.

Thanks for making this an instructable.
Helps people like me who are learning about the msp430 in their spare time.
Will be trying this very soon. Built my own sdcard holder yesterday after reading this.
Thanks again. :)