CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

SD card problem dsPIC33FJ128GP710A

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Neo2a



Joined: 02 May 2009
Posts: 7
Location: Hungary

View user's profile Send private message Send e-mail MSN Messenger

SD card problem dsPIC33FJ128GP710A
PostPosted: Tue Aug 21, 2012 3:09 am     Reply with quote

Dear programmers,
I have a problem with uSD card handling.
The program is initialized a SD card well.
After it write a file ("cmc.txt")
Answer on serial line is "OK" but the card is still empty.
Please help me what's wrong in my code?
http://juropnet.hu/~ipucz/Project.zip
Thank you!
Best regards
Steve
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Tue Aug 21, 2012 7:31 am     Reply with quote

Hi,

Post your code here. No one is interested to go out to a random Hungarian website to download your .zip file. Don't make helping you to solve your problem more difficult than it has to be - if you do, your plea for help will just be ignored by a majority of the forum users.

I also noticed that you asked almost exactly the same question back in May. You had one response asking for a copy of your schematic in PDF format (because your posted schematic was in a proprietary format), but you never responded to the request. Are you really serious about solving this problem?

John
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Aug 21, 2012 8:37 am     Reply with quote

What is the size of your SD card? The CCS library only supports standard SD cards up to 4Gb, not the High Capacity cards.

Perhaps your card has a Master Boot Record? The CCS driver often has problems in handling these. Try formatting the card in a photo camera.

Have a look at the Code Library section of this forum you will find other SD drivers there. Also a few bugfixes have been posted for the CCS library: http://www.ccsinfo.com/forum/viewtopic.php?t=43402

Before posting your answers on this forum, check the first sticky post in this forum. It gives some guidelines for posting questions here.
Neo2a



Joined: 02 May 2009
Posts: 7
Location: Hungary

View user's profile Send private message Send e-mail MSN Messenger

Mikromedia
PostPosted: Tue Aug 21, 2012 10:01 am     Reply with quote

Hello
I have a Mikromedia for dsPIC33 card.
The schematics is here: http://www.mikroe.com/eng/downloads/get/1250/mikromedia_dspic33_schematic_v110.pdf
Card size is 2Gb and formatted with windows xp for FAT32
Because the problem was not changed, formatted a card by
SDformatter 3.1 software but the result was same.
Thank you
Best regards
Steve
Neo2a



Joined: 02 May 2009
Posts: 7
Location: Hungary

View user's profile Send private message Send e-mail MSN Messenger

All modification is done
PostPosted: Wed Aug 22, 2012 2:34 am     Reply with quote

Modifications in mmcsd.c

Search for uint32_t g_mmcsdBufferAddress;
and add under it:
Code:

uint32_t g_mmcsdPartitionOffset;

Next, just before the "mmcsd_init" function add a new function:
Code:

void mmcsd_check_part(uint16_t off)
{
if (g_mmcsd_buffer[off + 0] == 0x80)
{
// active partition
uint8_t t;
t = g_mmcsd_buffer[off + 4];
if (t == 0x04 || t == 0x06 || t == 0x0B)
{
// FAT16 or FAT32 partition
g_mmcsdPartitionOffset = make32(
g_mmcsd_buffer[off + 11], g_mmcsd_buffer[off + 10],
g_mmcsd_buffer[off + 9], g_mmcsd_buffer[off + 8]) * MMCSD_MAX_BLOCK_SIZE;
}
}
}


In the "mmcsd_init" function, right after the line:
Code:

r1 = mmcsd_load_buffer();


Add the lines:
Code:

g_mmcsdPartitionOffset = 0;
mmcsd_check_part(0x1EE);
mmcsd_check_part(0x1DE);
mmcsd_check_part(0x1CE);
mmcsd_check_part(0x1BE);


Finally, in the function "mmcsd_move_buffer", after the line:
Code:

new_block = new_addr - (new_addr % MMCSD_MAX_BLOCK_SIZE);

Add the line:
Code:

new_block += g_mmcsdPartitionOffset;


Modifications in mmcsd.c

The CCS "fat.c" functions "get_next_addr" and "get_prev_addr" do not correctly handle cluster transitions. The following are corrected functions, so replace the function with the following code:
Code:

signed int get_next_addr(int32* my_addr)
{
int32 temp;
#ifdef FAT32
int32 c;
#else
int16 c;
#endif
// check to make sure that the next iteration will give us a contiguous address
temp = *my_addr + 1;
if((temp > Data_Start) && ((temp - Data_Start) % Bytes_Per_Cluster == 0))
{
// convert the current address into the address of where information about
//  the address is stored in the FAT, and put this value into the current address
c = addr_to_cluster(temp - 1);
if(get_next_cluster(&c) == EOF)
return EOF;
if (c >=
#ifdef FAT32
0x0FFFFFF8
#else
0xFFF8
#endif
)
return EOF;
temp = cluster_to_addr(c);
}
*my_addr = temp;
return GOODEC;
}


Further, get_prev_addr() needs to be updated:

Code:

signed int8 get_prev_addr(int32* my_addr)
{
int32 temp;
#ifdef FAT32
int32 c;
#else
int16 c;
#endif
temp = *my_addr;
// if we're trying to go backwards one entry from the beginning of the root,
//  we won't be able to...
if(temp <= Root_Dir)
return GOODEC;
// check to make sure that the next iteration will give us a contiguous address
if((temp >= Data_Start) && ((temp - Data_Start) % Bytes_Per_Cluster == 0))
{
c = addr_to_cluster(temp);
if(get_prev_cluster(&c) == EOF)
return EOF;
temp = cluster_to_addr(c) + Bytes_Per_Cluster;
}
*my_addr = temp - 1;
return GOODEC;
}


In fat_init() function search for the following lines

Code:

#ifdef FAT32
Data_Start = Bytes_Per_Cluster + Root_Dir;
#else // FAT16


and replace it with the following code (i.e. remove "Bytes_Per_Cluster +"):

Code:

#ifdef FAT32
Data_Start = Root_Dir;
#else // FAT16


And finally, get_short_file_name() needs to be replaced with the following code:

Code:

signed int get_short_file_name(int32 file_entry_addr, char sname[], int8 type)
{
int
buf,
i,
j = 0;
// one short file name has, at the most, 11 characters
for(i = 0; i < 11; ++i)
{
// read in a character
if(mmcsd_read_data(i + file_entry_addr, 1, &buf) != GOODEC)
return EOF;
// convert the character
if(buf != ' ')
{
if (i == 8 && type != 0x10) sname[j++] = '.';
sname[j++] = tolower(buf);
}
}
if (sname[j - 1] == '.') --j;
sname[j] = '\0';
return GOODEC;
}
[/code]
Neo2a



Joined: 02 May 2009
Posts: 7
Location: Hungary

View user's profile Send private message Send e-mail MSN Messenger

After all modification
PostPosted: Wed Aug 22, 2012 2:36 am     Reply with quote

After all modification implemented into the code
The fat.c

Code:

#ifndef FAT_PIC_C
#define FAT_PIC_C



++++++++++++++++++++++++
Code deleted.

Sorry, modified code is still CCS code. Rule #10 applies:
10. Don't post the CCS example code or drivers, or ask for such code and drivers.

A list of mods is OK, but not the complete driver file.

Forum Rules:
http://www.ccsinfo.com/forum/viewtopic.php?t=26245

- Forum Moderator
++++++++++++++++++++++++
Neo2a



Joined: 02 May 2009
Posts: 7
Location: Hungary

View user's profile Send private message Send e-mail MSN Messenger

MMCSD content
PostPosted: Wed Aug 22, 2012 2:40 am     Reply with quote

After modifications implemented the
mmcsd.c content is

Code:

#ifndef FAT_PIC_C
#define FAT_PIC_C

#include <ctype.h>
#include <string.h>
#case

//////////////////////
///                ///
/// Useful Defines ///
///                ///
//////////////////////

/// Define your FAT type here ///
#define FAT16
//#define FAT32

/// For faster single-file writing, uncomment this line below ///
//#define FAST_FAT

/// Everything else ///
#define MAX_FILE_NAME_LENGTH 0x20  // the maximum length of a file name for our FAT, including /0 terminator
#define STREAM_BUF_SIZE 0x20       // how big the FILE buffer is. 0x20 is optimal

//////////////////////////////////////////////////////////////////

#define EOF -1
#define GOODEC 0
#define fatpos_t int32
#define SEEK_CUR 0
#define SEEK_END 1
#define SEEK_SET 2

////////////////////////
///                  ///
/// Global Variables ///
///                  ///
////////////////////////

int16
   Bytes_Per_Cluster,   // number of addressable bytes per cluster
   FAT_Start;           // when the first FAT begins

int32
   Data_Start,          // when data starts
   FAT_Length,          // the length of one FAT
   Next_Free_Clust,     // where the next free cluster is
   Root_Dir;            // when the root directory starts

enum filetype
{
   Data_File,  // the stream is pointing to a binary, data file
   Directory,  // the stream is pointing to a directory
   None        // the stream isn't currently pointing to anything
};

enum ioflags
{
   Closed = 0x00,
   Read = 0x01,
   Write = 0x02,
   Append = 0x04,
   Binary = 0x08,
   EOF_Reached = 0x10,
   Read_Error = 0x20,
   Write_Error = 0x40,
   File_Not_Found = 0x80
};

struct iobuf
{
   fatpos_t
      Bytes_Until_EOF,     // how many bytes until the stream's end of file
      Cur_Char,            // the current byte that the stream is pointing at
      Entry_Addr,          // the entry address of the file that is associated with the stream
      Parent_Start_Addr,   // the parent's start adddress of the file that is associated with the stream
      Size,                // the size of the file that is associated with the stream
      Start_Addr;          // the beginning of the data in the file that is associated with the stream

   enum filetype File_Type;   // the type of file that is associated with the stream

   enum ioflags Flags;        // any associated input/output flag

   int Buf[STREAM_BUF_SIZE];  // this is a buffer so that during fatputc() or fatgetc()
                              //  the media won't have to be read at every character
};
typedef struct iobuf FILE;

///////////////////////////
///                     ///
/// Function Prototypes ///
///                     ///
///////////////////////////

/// Standard C Functions ///
signed int fatopen(char fname[], char mode[], FILE* stream);
signed int fatreopen(char fname[], char mode[], FILE* stream);
signed int fatclose(FILE* stream);
signed int fatgetc(FILE* stream);
signed int fatputc(int ch, FILE* stream);
char* fatgets(char* str, int num, FILE* stream);
signed int fatputs(char* str, FILE* stream);
signed int fatprintf(FILE* stream);
signed int fatgetpos(FILE* stream, fatpos_t* position);
signed int fatsetpos(FILE* stream, fatpos_t* position);
signed int fatseek(FILE* stream, int32 offset, int origin);
signed int fateof(FILE* stream);
signed int faterror(FILE* stream);
signed int fatread(void* buffer, int size, int32 num, FILE* stream);
signed int fatwrite(void* buffer, int size, int32 count, FILE* stream );
signed int fatflush(FILE* stream);
signed int remove(char* fname);
void clearerr(FILE* stream);
void rewind(FILE* stream);
fatpos_t fattell(FILE* stream);

/// Non-Standard C Functions ///
signed int rm_file(char fname[]);
signed int rm_dir(char dname[]);
signed int mk_file(char fname[]);
signed int mk_dir(char dname[]);

/// Functions' Utility Functions ///
signed int set_file(char fname[], int attrib, FILE* stream);
signed int get_file_name(int32 file_entry_addr, char name[]);
signed int set_file_name(int32 parent_dir_addr, int32* entry_addr, char name[]);
signed int get_short_file_name(int32 file_entry_addr, char sname[], int type);
signed int make_short_file_name(int32 parent_dir_addr, char fname[], char sname[]);
int long_name_chksum (int* pFcbName);
signed int check_invalid_char(char fname[]);
#ifdef FAT32
signed int get_next_free_cluster(int32* my_cluster);
signed int dealloc_clusters(int32 start_cluster);
signed int alloc_clusters(int32 start_cluster, int32* new_cluster_addr);
signed int clear_cluster(int32 cluster);
signed int write_fat(int32 cluster, int32 data);
#else // FAT16
signed int get_next_free_cluster(int16* my_cluster);
signed int dealloc_clusters(int16 start_cluster);
signed int alloc_clusters(int16 start_cluster, int32* new_cluster_addr);
signed int clear_cluster(int16 cluster);
signed int write_fat(int16 cluster, int16 data);
#endif // #ifdef FAT32
signed int get_next_file(FILE* stream);
signed int get_prev_file(FILE* stream);
signed int get_next_free_addr(int32* my_addr);
signed int get_next_free_entry(int32* start_addr);
signed int get_next_entry(int32* start_addr);
signed int get_prev_entry(int32* start_addr);
signed int read_buffer(FILE* stream, int* val);
signed int write_buffer(FILE* stream, int val);
void fill_entry(char the_entry[], char val, int8 start_ind);
void disp_timestamp(int16 timestamp);
void disp_datestamp(int16 datestamp);

/// Data Utility Functions ///
signed int fat_init();
#ifdef FAT32
signed int get_next_cluster(int32* my_cluster);
signed int get_prev_cluster(int32* my_cluster);
int32 cluster_to_addr(int32 cluster);
int32 addr_to_cluster(int32 addr);
#else // FAT16
signed int get_next_cluster(int16* my_cluster);
signed int get_prev_cluster(int16* my_cluster);
int32 cluster_to_addr(int16 cluster);
int16 addr_to_cluster(int32 addr);
#endif // #ifdef FAT32
signed int get_next_addr(int32* my_addr);
signed int get_prev_addr(int32* my_addr);
signed int format(int32 DskSize);

/// Debugging Utility Functions ///
signed int disp_folder_contents(char foldername[]);
signed int dump_addr(int32 from, int32 to);
signed int dump_clusters(int32 from, int32 to);
void disp_fat_stats();
signed int fatprintfinfo(FILE* stream);

////////////////////////////////
///                          ///
/// Function Implementations ///
///                          ///
////////////////////////////////

/// Standard C Functions ///

/*
signed int fatopen(char fname[], char mode[], FILE* stream)
Summary: This will open up a file stream for reading, writing, or appending.
Param fname: The full path of the file to open.
Param mode: The mode to open up the stream into.
             "r" = Read
             "w" = Write
             "a" = Append
             "rb", "wb", "ab" = Read, Write, or Append in Binary mode
Param stream: The stream to open up.
Returns: EOF if there was a problem, GOODEC if everything went okay.
Note: fname must be in the form of /filename.fil for a file in the root directory
       /Directory/filename.fil for a file in a subdirectory of root
       /Directory/Subdirectory/filename.fil and so on...
Note: Standard C will make a file in case a file isn't found,
       however due to recursion this is not possible in CCSC.
*/
signed int fatopen(char fname[], char mode[], FILE* stream)
{
   int fname_parse_pos = 1;    // the current index of the fname character

   char target_file[MAX_FILE_NAME_LENGTH];   // temporary buffer to hold names of files

   FILE cur_stream;     // this will   be the stream that will be returned if all goes well

#ifndef FAST_FAT
   int
      depth = 0,              // how many subdirectories deep the file is
      target_file_parse_pos;  // the current index of the target_file character
#endif // #ifndef FAST_FAT

   // set flags
#ifdef FAST_FAT
   switch(mode[0])
   {
      case 'w':
         cur_stream.Flags = Write;
         break;
      case 'a':
         cur_stream.Flags = Append;
         break;
      default:
         return EOF;
   }

   // start looking for the file, start at root
   cur_stream.Start_Addr = cur_stream.Parent_Start_Addr = Root_Dir;

   while(fname[fname_parse_pos] != '\0')
   {
      target_file[fname_parse_pos - 1] = fname[fname_parse_pos];
      fname_parse_pos += 1;
   }

   target_file[fname_parse_pos] = '\0';

   // find the file inside of its subdirectory
   if(set_file(target_file, 0x20, &cur_stream) != GOODEC)
   {
      cur_stream.Flags |= File_Not_Found;
      *stream = cur_stream;
      return EOF;
   }

   // at this point, we've found the file
   *stream = cur_stream;
   return GOODEC;
#else // NO FAST_FAT
   switch(mode[0])
   {
      case 'r':
         cur_stream.Flags = Read;
         break;
      case 'w':
         cur_stream.Flags = Write;
         break;
      case 'a':
         cur_stream.Flags = Append;
         break;
      default:
         return EOF;
   }

   if(mode[1] == 'b')
      cur_stream.Flags |= Binary;

   // start looking for the file, start at root
   cur_stream.Start_Addr = cur_stream.Parent_Start_Addr = Root_Dir;

   // figure out how deep we have to go, count how many '/' we have in the string
   while(fname[fname_parse_pos] != '\0')
   {
      if(fname[fname_parse_pos] == '/')
         depth++;
      fname_parse_pos += 1;
   }

   // start the fname index at 1 to skip over the '/'
   fname_parse_pos = 1;

   // open up to the subdirectory, if possible
   while(depth > 0)
   {
      // find the name of our next target directory
      target_file_parse_pos = 0;
      while(fname[fname_parse_pos] != '/')
      {
         // check to make sure that we're not at the end of a poorly formatted string
         if(fname[fname_parse_pos] == '\0')
            return EOF;

         // fill up the buffer and increment the indexes
         target_file[target_file_parse_pos] = fname[fname_parse_pos];
         fname_parse_pos += 1;
         target_file_parse_pos += 1;
      }

      // increment the fname index one more because it's currently pointing at the '/'
      fname_parse_pos += 1;

      // tack on a \0 to the end of the target file to terminate the string
      target_file[target_file_parse_pos] = '\0';

      // check to see if the directory exists and open it if possible, otherwise exit because the directory doesn't exist
      if(set_file(target_file, 0x10, &cur_stream) != GOODEC)
      {
         cur_stream.Flags |= File_Not_Found;
         *stream = cur_stream;
         return EOF;
      }
      depth -= 1;
   }

   // check to see if we're trying to open just a directory
   if(fname[fname_parse_pos] == '\0')
   {
      *stream = cur_stream;
      return GOODEC;
   }

   // now that we have the location of the subdirectory that the file is in, attempt to open the file
   target_file_parse_pos = 0;
   while(fname[fname_parse_pos] != '\0')
   {
      // fill up the buffer and increment the indexes
      target_file[target_file_parse_pos] = fname[fname_parse_pos];
      fname_parse_pos += 1;
      target_file_parse_pos += 1;
   }

   // tack on a \0 to the end of the target file to terminate the string
   target_file[target_file_parse_pos] = '\0';

   // find the file inside of its subdirectory
   if(set_file(target_file, 0x20, &cur_stream) != GOODEC)
   {
      cur_stream.Flags |= File_Not_Found;
      *stream = cur_stream;
      return EOF;
   }

   // at this point, we've found the file
   *stream = cur_stream;
   return GOODEC;
#endif // #ifdef FAST_FAT
}

/*
signed int fatreopen(char fname[], char mode[], FILE* old_stream, FILE* new_stream)
Summary: This will close a stream and then reopen it using new parameters.
Param fname: The full path of the file to open.
Param mode: The mode to open up the stream into.
             "r" = Read
             "w" = Write
             "a" = Append
             "rb", "wb", "ab" = Read, Write, or Append in Binary mode
Param stream: The stream to close and reopen.
Returns: EOF if there was a problem, GOODEC if everything went okay.
Note: fname must be in the form of /filename.fil for a file in the root directory
         /Directory/filename.fil for a file in a subdirectory of root
         /Directory/Subdirectory/filename.fil and so on...
Note: Standard C will make a file in case a file isn't found,
       however due to recursion this is not possible in CCSC.
*/
signed int fatreopen(char fname[], char mode[], FILE* stream)
{
   // close the old stream
   if(fatclose(stream) == EOF)
     return EOF;

   // open the new stream
   if(fatopen(fname, mode, stream) == EOF)
      return EOF;

   return GOODEC;
}

/*
signed int fatclose(FILE* stream)
Summary: Closes a stream and commits any changes done to the file.
Param: The stream to close.
Returns: EOF if there was a problem, 0 if everything went okay.
*/
signed int fatclose(FILE* stream)
{
   int ec = 0;

   int32 first_cluster;

   // commit data back to the stream's entry, if needed
   if((stream->Flags & Write) || (stream->Flags & Append))
   {
      // write the new size of the file
      if(mmcsd_write_data(stream->Entry_Addr + 0x1C, 4, &(stream->Size)) != GOODEC)
      {
         stream->Flags |= Write_Error;
         return EOF;
      }

      // check to see if the first cluster is already linked in the file
      ec += mmcsd_read_data(stream->Entry_Addr + 0x14, 2, (int16*)&first_cluster + 1);
      ec += mmcsd_read_data(stream->Entry_Addr + 0x1A, 2, &first_cluster);

      if(ec != GOODEC)
      {
         stream->Flags |= Read_Error;
         return EOF;
      }

      // write the first cluster to the entry if needed
      if(first_cluster == 0)
      {
         // convert the start address to a cluster number
         first_cluster = addr_to_cluster(stream->Start_Addr);

         ec += mmcsd_write_data(stream->Entry_Addr + 0x14, 2, (int16*)&first_cluster + 1);
         ec += mmcsd_write_data(stream->Entry_Addr + 0x1A, 2, &first_cluster);

         if(ec != GOODEC)
         {
            stream->Flags |= Write_Error;
            return EOF;
         }
      }
     
      // dump the remaining buffer to the card
      if(fatflush(stream) == EOF)
         return EOF;
   }
   // nullify the data
   stream->Cur_Char = 0;
   stream->Entry_Addr = 0;
   stream->Size = 0;
   stream->Start_Addr = 0;
   stream->Flags = 0;
   return 0;
}

/*
signed int fatgetc(FILE* stream)
Summary: Gets a character from a stream.
Param: The stream to get a character from.
Returns: The character that was gotten from the stream,
          EOF if the stream has reached the end of the file or doesn't have permissions to read,
*/
signed int fatgetc(FILE* stream)
{
   char ch; // character read in

   // check to see if the stream has proper permissions to read
   if(stream->Flags & Read)
   {
      // when the number of bytes until eof hit zero, we know we are at the end of any file
      if(stream->Bytes_Until_EOF == 0)
      {
         stream->Flags |= EOF_Reached;
         return EOF;
      }

      // read in the next byte in the buffer
      if(read_buffer(stream, &ch) == EOF)
         return EOF;

      // a 0x00 will signify the end of a non-binary file
      if((ch == '\0') && !(stream->Flags & Binary))
      {
         stream->Flags |= EOF_Reached;
         return EOF;
      }

      // get the next contiguous address of the stream
      if(get_next_addr(&(stream->Cur_Char)) != GOODEC)
         return EOF;
         
      // we just got 1 byte closer to the end of the file
      stream->Bytes_Until_EOF -= 1;
      return ch;
   }

   // if the stream doesn't have proper permissions to read, return an EOF
   else
      return EOF;
}

/*
signed int fatputc(int ch, FILE* stream)
Summary: Puts a character into a stream.
Param ch: The character to put into the stream.
Param stream: The stream to put a character into.
Returns: The character that was put into the stream,
          EOF if the stream doesn't have permissions to write, or if a problem happened.
*/
signed int fatputc(int ch, FILE* stream)
{
   // check to see if the stream has proper permissions to write
   if(((stream->Flags & Write) || (stream->Flags & Append)) && (stream->File_Type == Data_File))
   {
      // if there isn't any space allocated yet, allocate some
      if(stream->Cur_Char < Data_Start)
      {
         if(get_next_free_cluster(&Next_Free_Clust) == EOF)
            return EOF;
#ifdef FAT32
         if(write_fat(Next_Free_Clust, 0x0FFFFFFF) == EOF)
            return EOF;
#else // FAT16
         if(write_fat(Next_Free_Clust, 0xFFFF) == EOF)
            return EOF;
#endif // #ifdef FAT32
         if(clear_cluster(Next_Free_Clust) == EOF)
            return EOF;
         stream->Cur_Char = stream->Start_Addr = cluster_to_addr(Next_Free_Clust);
      }

      // write the next character to the buffer
      if(write_buffer(stream, ch) == EOF)
         return EOF;

      // get the next address, increment Cur_Char
      if(get_next_addr(&(stream->Cur_Char)) == EOF)
      {
         // write the current buffer to the end of the current cluster
         if(mmcsd_write_data(stream->Cur_Char - STREAM_BUF_SIZE + 1, STREAM_BUF_SIZE, stream->Buf) != GOODEC)
         {
            stream->Flags |= Write_Error;
            return EOF;
         }
         // start looking for a new cluster to allocate
         if(alloc_clusters(addr_to_cluster(stream->Cur_Char), &(stream->Cur_Char)) == EOF)
            return EOF;
      }

      // our file just got bigger by 1 byte
      stream->Size += 1;

      return ch;
   }

   // if the stream doesn't have proper permissions to write, return an EOF
   else
      return EOF;
}

/*
char* fatgets(char* str, int num, FILE* stream)
Summary: Reads characters from a stream into a string.
Param str: A pointer to the beginning of the string to put characters into.
Param num: The number of characters to put into the string - 1.
Param stream: The stream to read from.
Returns: A pointer to the most recently added character, or NULL if there was an error.
Note: If a newline is read from the stream, then str will be terminated with a newline.
       If num - 1 or EOF is reached, then str will be null terminated.
*/
char* fatgets(char* str, int num, FILE* stream)
{
   int i;   // counter for loops

   // loop until num - 1
   for(i = 0; i < num - 1; i += 1)
   {
      str[i] = fatgetc(stream);
      if(str[i] == '\n')
         return str;
      if(str[i] == EOF)
         break;
   }

   // close off str with a null terminator
   str[i] = '\0';

   return str;
}

/*
signed int fatputs(char* str, FILE* stream)
Summary: Writes characters from a string into a stream.
Param str: A pointer to the beginning of the string to write into the stream.
Param stream: The stream to write into.
Returns: EOF if there was a problem, GOODEC if everything went okay.
*/
signed int fatputs(char* str, FILE* stream)
{
   int i = 0;   // counter for loops

   // fatputc every character in the stream
   while(str[i] != '\0')
   {
      if(fatputc(str[i], stream) == EOF)
        return EOF;
      i += 1;
   }

   return GOODEC;
}

/*
signed int fatprintf(FILE* stream)
Summary: This will print off the entire contents of the stream to the console.
Param: The stream to print off.
Returns: The last character printed off to the console.
*/
signed int fatprintf(FILE* stream)
{
   signed int ch; // character read in

   // keep on printf any characters read in as long as we don't run into an end of file or a media error
   do
   {
      ch = fatgetc(stream);
      printf("%c", ch);
   } while(ch != EOF);

   return ch;
}

/*
signed int fatgetpos(FILE* stream, fatpos_t* position)
Summary: Returns the current position of where the stream is pointing to relative to the beginning of the stream.
Param stream: The stream to get the position of.
Param position: A pointer to a variable put the current position of the pointer into.
Returns: 0 on success.
*/
signed int fatgetpos(FILE* stream, fatpos_t* position)
{
   *position = stream->Size - stream->Bytes_Until_EOF;
   return 0;
}

/*
signed int fatsetpos(FILE* stream, fatpos_t* position)
Summary: Sets the current position of where the stream is pointing to in memory relative to the beginning of the stream.
Param stream: The stream to set the position of.
Param position: A pointer the a variable that has the value of the new position.
Returns: 0 on success, or EOF if there was error.
*/
signed int fatsetpos(FILE* stream, fatpos_t* position)
{
#ifndef FAST_FAT
#ifdef FAT32
   int32 cur_cluster; // the current cluster we're pointing to
#else // FAT16
   int16 cur_cluster; // the current cluster we're pointing to
#endif // #ifdef FAT32
   int32 i;    // pointer to memory
#endif // #ifndef FAST_FAT

   // check to see if we want to just rewind the file
   if(*position == 0)
   {
      rewind(stream);
      return GOODEC;
   }
   
   // this whole process is much different and easier if we're writing or appending at a spot after EOF
   //  this will essentially write null characters to the file from EOF to the desired position
   if(((stream->Flags & Write) || (stream->Flags & Append)) && (stream->Size < *position))
   {
      while(stream->Size < *position)
         if(fatputc('\0', stream) == EOF)
            return EOF;
     
      return 0;
   }

#ifdef FAST_FAT
   stream->Cur_Char = stream->Start_Addr + *position;
#else // NO FAST_FAT
   // figure out how many clusters into the file the position is to be set to
   i = *position / Bytes_Per_Cluster;
   cur_cluster = addr_to_cluster(stream->Start_Addr);

   // head to that cluster
   while(i > 0)
   {
      if(get_next_cluster(&cur_cluster) != GOODEC)
         return EOF;
      i -= 1;
   }

   // head to the correct cluster
   stream->Cur_Char = cluster_to_addr(cur_cluster);

   // now that we're in the correct cluster, tack on the remaining position
   stream->Cur_Char += (*position % Bytes_Per_Cluster);

   if(stream->Flags & Read)
   {
      // we now need to change how far it is until EOF
      stream->Bytes_Until_EOF = stream->Size - *position;

      // fill up the buffer
      if(mmcsd_read_data(stream->Cur_Char, STREAM_BUF_SIZE, stream->Buf) != GOODEC)
      {
         stream->Flags |= Read_Error;
         return EOF;
      }
   }

   else
      stream->Size = *position;
#endif // #ifdef FAST_FAT
   return 0;
}

/*
signed int fatseek(FILE* stream, int32 offset, int origin)
Summary: This will set the position of the file stream according to the input. The EOF flag will also be cleared.
Param stream: The stream to set the position of.
Param offset: How many bytes relative of origin the file stream position will be set.
Param origin: This will be one of 3 values...
               SEEK_CUR: Set position relative to the current stream position.
               SEEK_END: Set position relative to the end of the stream.
               SEEK_SET: Set position relative to the beginning of the stream.
Returns: 0 on success, or EOF if there was error.
*/
signed int fatseek(FILE* stream, int32 offset, int origin)
{
   int32 myoffset;   // since fatsetpos requires a pointer to a variable, we need this here

   switch(origin)
   {
      case SEEK_CUR:
         myoffset = stream->Cur_Char + offset;
         if(fatsetpos(stream, &myoffset) != 0)
            return EOF;
         break;
      case SEEK_END:
         myoffset = stream->Size - offset;
         if(fatsetpos(stream, &myoffset) != 0)
            return EOF;
         break;
      case SEEK_SET:
         myoffset = offset;
         if(fatsetpos(stream, &myoffset) != 0)
            return EOF;
         break;
      default:
         return EOF;
   }

   // clear the EOF flag
   stream->Flags &= 0xEF;

   return GOODEC;
}

/*
signed int fateof(FILE* stream)
Summary: Determines whether or not the stream is at the end of the file.
Param: The stream to query for EOF.
Returns: A non-zero value if the file is at EOF,
          0 if the file is not at EOF.
*/
signed int fateof(FILE* stream)
{
   return stream->Flags & EOF_Reached;
}

/*
signed int fatread(void* buffer, int size, int32 num, FILE* stream)
Summary: Fills up an array with data from a stream.
Param buffer: A pointer to the beginning of an array of any type.
Param size: How many bytes each element in the array is.
Param num: How many elements to fill in the array.
Param stream: The stream to read from.
Returns: How many values were written to the array.
*/
signed int fatread(void* buffer, int size, int32 num, FILE* stream)
{
   int32 i; // counter for loop

   // fill up every byte
   for(i = 0; i < (num * size); i += 1)
      buffer[i] = fatgetc(stream);

   return i;
}

/*
signed int fatwrite(void* buffer, int size, int32 count, FILE* stream )
Summary: Fills up a stream with data from an array
Param buffer: A pointer to the beginning of an array of any type.
Param size: How many bytes each element in the array is.
Param num: How many elements to write to the stream.
Param stream: The stream to write to.
Returns: How many values were written to the stream.
*/
signed int fatwrite(void* buffer, int size, int32 count, FILE* stream )
{
   int32 i; // counter for loop

   // write every byte
   for(i = 0; i < (count * (int32)size); i += 1)
      if(fatputc(buffer[i], stream) == EOF)
         return EOF;

   return i;
}

/*
signed int fatflush(FILE* stream)
Summary: Flushes the buffer of a given stream.
Param: The stream to flush the buffer of.
Returns: EOF if there was a problem, 0 if everything went okay
*/
signed int fatflush(FILE* stream)
{
   // check to see if we have a buffer
   if((stream->Flags & Write) || (stream->Flags & Append))
   {
      // check to see if we need to flush the buffer
      if(stream->Cur_Char % STREAM_BUF_SIZE == 0)
      {
         // flush the buffer to the card
         if(mmcsd_write_data(stream->Cur_Char - STREAM_BUF_SIZE, STREAM_BUF_SIZE, stream->Buf) != GOODEC)
         {
            stream->Flags |= Write_Error;
            return EOF;
         }
      }
      else
      {
         // flush the buffer to the card
         //  we need to make sure that the buffer gets flushed into the proper location, hence all this weird % math
         if(mmcsd_write_data(stream->Cur_Char - (stream->Cur_Char % STREAM_BUF_SIZE), STREAM_BUF_SIZE, stream->Buf) != GOODEC)
         {
            stream->Flags |= Write_Error;
            return EOF;
         }
      }
      return(mmcsd_flush_buffer());
   }
   return 0;
}

/*
signed int remove(char* fname)
Summary: Removes a file from disk.
Param: The full path of the file to remove.
Returns: 0 on success, or EOF if there was error.
Note: This function does not work for removing directories, use rm_dir instead.
Note: fname must be in the form of /filename.fil for a file in the root directory
       /Directory/filename.fil for a file in a subdirectory of root
       /Directory/Subdirectory/filename.fil and so on...
*/
signed int remove(char* fname)
{
   if(rm_file(fname) == EOF)
       return EOF;

   return 0;
}

/*
signed int faterror(FILE* stream)
Summary: Checks for an error in a given stream.
Param: The stream to check for an error in.
Returns: A non-zero value of there is an error in the stream,
          0 if there is no error in the stream
*/
signed int faterror(FILE* stream)
{
   return stream->Flags & 0xF0;
}

/*
void clearerr(FILE* stream)
Summary: Clears off all error in a given stream.
Param: The stream to clear off the errors in.
Returns: Nothing.
*/
void clearerr(FILE* stream)
{
   stream->Flags &= 0x0F;
}

/*
void rewind(FILE* stream)
Summary: Sets the stream to point back to the beginning of a file.
Param: The stream to rewind.
Returns: Nothing.
*/
void rewind(FILE* stream)
{
   // set the stream back to the beginning
   stream->Cur_Char = stream->Start_Addr;
   stream->Bytes_Until_EOF = stream->Size;
}

/*
fatpos_t fattell(FILE* stream)
Summary: Returns the current position of where the stream is pointing to relative to the beginning of the stream.
Param: The stream to return the position of.
Returns: The position of where the stream is pointing to relative to the beginning of the stream, or 0 if there was a problem.
*/
fatpos_t fattell(FILE* stream)
{
   fatpos_t retval;

   if(fatgetpos(stream, &retval) != 0)
      return 0;

   return retval;
}

/// Non-Standard C Functions ///

/*
signed int rm_file(char fname[])
Summary: Deletes a file.
Param: The full path of the file to delete.
Returns: GOODEC if everything went okay, EOF if there was a problem.
Note: fname must be in the form of /filename.fil for a file in the root directory
       /Directory/filename.fil for a file in a subdirectory of root
       /Directory/Subdirectory/filename.fil and so on...
*/
signed int rm_file(char fname[])
{
   int
      order,
      ulinked_entry = 0xE5; // 0xE5 is put into the file's entry to indicate unlinking

   int32 i;

   char mode[] = "r";        // r is the safest mode to remove files with

   FILE stream;              // the stream that we'll be working with

   // attempt to open the stream
   if(fatopen(fname, mode, &stream) == EOF)
      return EOF;

   // we need to un-link the file's clusters from the FAT if there are clusters allocated
   if(stream.Start_Addr > Root_Dir)
   {
      if(dealloc_clusters(addr_to_cluster(stream.Start_Addr)) == EOF)
         return EOF;
   }
   // get rid of the first entry
   i = stream.Entry_Addr;
   if(mmcsd_write_data(i, 1, &ulinked_entry) == EOF)
      return EOF;
   
   // check to see if there is a long file name
   get_prev_entry(&i);
   if(mmcsd_read_data(i + 11, 1, &order) == EOF)
      return EOF;

   // get rid of all of the long file name entries if they're there
   while(order == 0x0F)
   {
      if(mmcsd_write_data(i, 1, &ulinked_entry) == EOF)
         return EOF;

      if(get_prev_entry(&i) == EOF)
         return EOF;

      if(mmcsd_read_data(i + 11, 1, &order) == EOF)
         return EOF;
   }
   
   if(fatclose(&stream) == EOF)
      return EOF;

   return GOODEC;
}

/*
signed int rm_dir(char dname[])
Summary: Deletes a directory.
Param: The full path of the directory to delete.
Returns: GOODEC if everything went okay, EOF if there was a problem.
Note: dname must be in the form of /Dirname/ for a directory in the root directory
       /Dirname/Subdirname/ for a directory in a subdirectory of root and so on...
Note: This function cannot remove all of the files
       and subdirectories of the directory. Manually remove all subdirectories
       and files before calling this command.
*/
signed int rm_dir(char dname[])
{
   char mode[] = "r";        // r is the safest mode to remove files with

   FILE stream;              // the stream that we'll be working with

   // attempt to open the stream
   if(fatopen(dname, mode, &stream) == EOF)
      return EOF;

   // jump over the . and .. entries in the directory
   stream.Entry_Addr = stream.Start_Addr + 64;
   
   // check to make sure that there isn't stuff in this directory
   if(get_next_file(&stream) != EOF)
      return EOF;

   // since removing files is a lot like removing directories, we
   //  can just call rm_file
   if(rm_file(dname) == EOF)
      return EOF;

   return GOODEC;
}

/*
signed int mk_file(char fname[])
Summary: Creates a file.
Param: The full path of the file to create.
Returns: GOODEC if everything went okay, EOF if there was a problem.
Note: This function will not create directories if parent directories don't exist.
Note: fname must be in the form of /filename.fil for a file in the root directory
       /Directory/filename.fil for a file in a subdirectory of root
       /Directory/Subdirectory/filename.fil and so on...
*/
signed int mk_file(char fname[])
{
   char
      filename[MAX_FILE_NAME_LENGTH],   // the file name we're trying to make
      mode[] = "r";                     // reading is the safest mode to work in

   int
      buf,               // buffer to hold values
      entire_entry[0x20],// entire first entry
      filename_pos = 0,  // the current parse position of the file name we're trying to create
      fname_pos;         // the current parse position of the input the the function

   int32 i;      // pointer to memory

   FILE stream;   // the stream that we'll be working with

   // attempt to open up to the directory
   if(fatopen(fname, mode, &stream) == GOODEC)
      return EOF; // we shouldn't get an GOODEC back from fatopen()

   // check to see if the file is already there.
   if(!(stream.Flags & File_Not_Found))
      return EOF;

   // make a file name
   fname_pos = strrchr(fname, '/') - fname + 1;
   while((fname[fname_pos] != '\0') && (filename_pos < MAX_FILE_NAME_LENGTH))
   {
      filename[filename_pos] = fname[fname_pos];
      fname_pos += 1;
      filename_pos += 1;
   }
   filename[filename_pos] = '\0';

   // write the name
   if(set_file_name(stream.Start_Addr, &i, filename) == EOF)
      return EOF;

   // throw in some values in the file's first entry
   for(buf = 0; buf < 0x20; buf += 1)
      entire_entry[buf] = 0;

   // this is a file
   entire_entry[0x0B] = 0x20;

   // read what set_file_name gave us for the short name
   if(mmcsd_read_data(i, 11, entire_entry) != GOODEC)
      return EOF;

   // write the entry
   if(mmcsd_write_data(i, 0x20, entire_entry) != GOODEC)
      return EOF;

   return GOODEC;
}

/*
signed int mk_dir(char dname[])
Summary: Creates a directory.
Param: The full path of the directory to create.
Returns: GOODEC if everything went okay, EOF if there was a problem.
Note: This function will not create directories if parent directories don't exist.
Note: dname must be in the form of /Dirname/ for a directory in the root directory
       /Dirname/Subdirname/ for a directory in a subdirectory of root and so on...
*/
signed int mk_dir(char dname[])
{
   char
      dirname[MAX_FILE_NAME_LENGTH],    // the directory name we're trying to make
      entire_entry[0x20],               // used to hold the link entries (. and ..) to the directory and its parent
      mode[] = "r";                     // reading is the safest mode to work in

   int
      dirname_pos = 0,   // the current parse position of the directory name we're trying to create
      dname_pos,         // the current parse position of the input the the function
      j;                 // counter for loops

   int32 i;   // pointer to memory

   FILE stream;   // the stream that we'll be working with

   // attempt to open up to the directory
   if(fatopen(dname, mode, &stream) == GOODEC)
      return EOF; // we shouldn't get an GOODEC back from fatopen()

   // check to see if the directory is already there.
   if(!(stream.Flags & File_Not_Found))
      return EOF;

   // make the directory name
   dname_pos = strrchr(dname, '/') - dname;
   dname[dname_pos] = '\0';
   dname_pos = strrchr(dname, '/') - dname + 1;
   while((dname[dname_pos] != '\0') && (dirname_pos < MAX_FILE_NAME_LENGTH))
   {
      dirname[dirname_pos] = dname[dname_pos];
      dname_pos += 1;
      dirname_pos += 1;
   }
   dirname[dirname_pos] = '\0';
   dname[dname_pos] = '/';

   // write the file's name
   if(set_file_name(stream.Start_Addr, &i, dirname) == EOF)
      return EOF;

   // find and allocate an open cluster
   if(get_next_free_cluster(&Next_Free_Clust) == EOF)
      return EOF;
   if(clear_cluster(Next_Free_Clust) == EOF)
      return EOF;
#ifdef FAT32
   if(write_fat(Next_Free_Clust, 0x0FFFFFFF) == EOF)
      return EOF;
#else // FAT16
   if(write_fat(Next_Free_Clust, 0xFFFF) == EOF)
      return EOF;
#endif // #ifdef FAT32

   // throw in some values in the file's first entry
   for(j = 0; j < 0x20; j += 1)
      entire_entry[j] = 0;

   // this is a directory
   entire_entry[0x0B] = 0x10;

   entire_entry[0x1A] = make8(Next_Free_Clust, 0);
   entire_entry[0x1B] = make8(Next_Free_Clust, 1);
#ifdef FAT32
   entire_entry[0x14] = make8(Next_Free_Clust, 2);
   entire_entry[0x15] = make8(Next_Free_Clust, 3);
#endif // #ifdef FAT32

   if(mmcsd_read_data(i, 11, entire_entry) != GOODEC)
      return EOF;

   // write the file's first entry
   if(mmcsd_write_data(i, 0x20, entire_entry) != GOODEC)
      return EOF;

   // make the two links that point to the directory and the directory's parent
   i = cluster_to_addr(Next_Free_Clust);

   // put in the first link that points to the directory itself
   for(j = 0; j < 0x20; j += 1)
   {
      if(j < 0x01)
         entire_entry[j] = '.';
      else if(j < 0x0B)
         entire_entry[j] = 0x20;
      else if(j == 0x0B)
         entire_entry[j] = 0x10;
      else
         entire_entry[j] = 0x00;
   }

   entire_entry[0x1A] = make8(Next_Free_Clust, 0);
   entire_entry[0x1B] = make8(Next_Free_Clust, 1);
#ifdef FAT32
   entire_entry[0x14] = make8(Next_Free_Clust, 2);
   entire_entry[0x15] = make8(Next_Free_Clust, 3);
#endif // #ifdef FAT32

   if(mmcsd_write_data(i, 0x20, entire_entry) != GOODEC)
      return EOF;

   for(j = 0; j < 0x0C; j += 1)
   {
      if(j < 0x02)
         entire_entry[j] = '.';
      else if(j < 0x0B)
         entire_entry[j] = 0x20;
      else
         entire_entry[j] = 0x10;
   }

   if(stream.Parent_Start_Addr == Root_Dir)
   {
      entire_entry[0x14] = 0x00;
      entire_entry[0x15] = 0x00;
      entire_entry[0x1A] = 0x00;
      entire_entry[0x1B] = 0x00;
   }
   else
   {
      entire_entry[0x1A] = make8(addr_to_cluster(stream.Parent_Start_Addr), 0);
      entire_entry[0x1B] = make8(addr_to_cluster(stream.Parent_Start_Addr), 1);
#ifdef FAT32
      entire_entry[0x14] = make8(addr_to_cluster(stream.Parent_Start_Addr), 2);
      entire_entry[0x15] = make8(addr_to_cluster(stream.Parent_Start_Addr), 3);
#endif // #ifdef FAT32
   }

   if(mmcsd_write_data(i + 0x20, 0x20, entire_entry) != GOODEC)
      return EOF;

   return GOODEC;
}

/// Functions' Utility Functions ///
/// NOTE: A library user should not need to use any of the functions in this section ///

/*
signed int set_file(char fname[], int attrib, FILE* stream)
Summary: This will set the stream to point to the specified file.
Param fname: The file name to search for.
Param attrib: The file attributes to search for. 0x10 is a directory, 0x20 is a file.
Param stream: The stream to set.
Returns: EOF if there was a problem, GOODEC if everything went okay.
Note: The stream has to be pointing to the parent directory's start address when coming in to this function.
*/
signed int set_file(char fname[], int attrib, FILE* stream)
{
   int
      cur_attrib,    // the attribute of the most recently read entry
      cur_state,     // the state of the most recently read entry
      ec = 0;        // error checking byte

   int32 i;   // pointer to memory
#ifndef FAST_FAT
   char name_buffer[MAX_FILE_NAME_LENGTH];   // buffer to hold in the most recently read in name
#endif // #ifndef FAST_FAT

   // set the memory pointer to the parent start address
   i = stream->Start_Addr;

   // search for the name of our target file inside of the parent directory
   do
   {
      // read the state and the attribute of the current entry
      ec += mmcsd_read_data(i, 1, &cur_state);
      ec += mmcsd_read_data(i + 0x0B, 1, &cur_attrib);
      if(ec != GOODEC)
      {
         stream->Flags |= Read_Error;
         return EOF;
      }

       // check to make sure that this entry exists and the entry is the type we're looking for
      if((cur_state != 0xE5) && (cur_attrib == attrib))
      {
#ifndef FAST_FAT
         // get the long file name of the current entry
         if(get_file_name(i, name_buffer) == EOF)
            return EOF;

         // if the target entry and the long file name are equal, strcmp will return a zero
         if(strcmp(fname, name_buffer) == 0)
#endif // #ifndef FAST_FAT
         {
            // we have found our target entry, set the current entry and break out of this function
            // set stream's parent address
            stream->Parent_Start_Addr = stream->Start_Addr;

            ec += mmcsd_read_data(i + 0x1C, 4, &(stream->Size));

            // stream->Start_Addr is going to temporarily have a cluster number
            ec += mmcsd_read_data(i + 0x14, 2, (int16*)&stream->Start_Addr + 1);
            ec += mmcsd_read_data(i + 0x1A, 2, &stream->Start_Addr);

            if(ec != GOODEC)
            {
               stream->Flags |= Read_Error;
               return EOF;
            }

            // convert stream->Start_Addr to an address
            stream->Start_Addr = cluster_to_addr(stream->Start_Addr);

            stream->Entry_Addr = i;
            stream->Bytes_Until_EOF = stream->Size;

            // set up some permission-specific parameters if we're at a file
            if(attrib == 0x20)
            {
               stream->File_Type = Data_File;
               if(stream->Flags & Write)
               {
                  // delete all previous data in the file
                  stream->Bytes_Until_EOF = stream->Size = 0;

                  // if there is already space allocated, get rid of it
                  if(stream->Start_Addr >= Data_Start)
                     if(dealloc_clusters(addr_to_cluster(stream->Start_Addr)) == EOF)
                        return EOF;
                  stream->Cur_Char = 0;
               }

               if((stream->Flags & Append) && (stream->Size != 0))
               {
                  // set the position to the end of the file and fill the buffer with the contents of the end of the file
                  ec = fatsetpos(stream, &(stream->Size));
                  if(stream->Cur_Char % STREAM_BUF_SIZE == 0)
                     ec += mmcsd_read_data(stream->Cur_Char - STREAM_BUF_SIZE, STREAM_BUF_SIZE, stream->Buf);
                  else
                     ec += mmcsd_read_data(stream->Cur_Char - (stream->Cur_Char % STREAM_BUF_SIZE), STREAM_BUF_SIZE, stream->Buf);
               }
#ifndef FAST_FAT
               if(stream->Flags & Read)
               {
                  stream->Cur_Char = stream->Start_Addr;

                  // fill up the read buffer for reading
                  ec = mmcsd_read_data(stream->Cur_Char, STREAM_BUF_SIZE, stream->Buf);
               }
#endif // #ifndef FAST_FAT
               if(ec != GOODEC)
               {
                  stream->Flags |= Read_Error;
                  return EOF;
               }               
            }
            else
               stream->File_Type = Directory;
            return GOODEC;
         }
      }

      // check to make sure that the next iteration will give us a contiguous cluster
      if(get_next_entry(&i) == EOF)
         return EOF;

   } while(cur_state != 0x00);

   // if we reach this point, we know that the file won't be found
   stream->Flags |= File_Not_Found;
   return EOF;
}

/*
signed int get_file_name(int32 file_entry_addr, char name[])
Summary: This will get a name of a file.
Param file_entry_addr: The position in memory that the file's entry is.
Param name[]: The place to put the name of the file into.
Returns: EOF if there was a problem, GOODEC if everything went okay.
*/
signed int get_file_name(int32 file_entry_addr, char name[])
{
   int
      j,       // counter for loops
      k = 0,   // current character in array
      order,   // byte to hold the current long file name order
      type;    // the type of entry that was just read in

   int32 i;          // pointer for memory

   // the long file name isn't fragmented across clusters
   i = file_entry_addr;

   // check to make sure that this file has a long file name
   if(mmcsd_read_data(i - 0x15, 1, &type) != GOODEC)
      return EOF;

   if(type != 0x0F)
   {
      // this file doesn't have a long file name
      if(get_short_file_name(i, name, type) == EOF)
         return EOF;
      return GOODEC;
   }

   do
   {
      // head to the previous entry
      if(get_prev_entry(&i) == EOF)
         return EOF;

      for(j = 1; j < 0x20; j += 2, k += 1)
      {
         if(j == 11)
            j = 14;
         else if(j == 26)
            j = 28;
         if(mmcsd_read_data(j + i, 1, &(name[k])) != GOODEC)
            return EOF;
      }

      // now that that's done with, get the entry's order
      if(mmcsd_read_data(i, 1, &order) != GOODEC)
         return EOF;

   } while(!(order & 0x40));  // the last entry will be 0b01xxxxxx

   // end the name[] buffer with a \0
   name[k] = '\0';

   return GOODEC;
}

/*
signed int set_file_name(int32 parent_dir_addr, int32 entry_addr, char name[])
Summary: Creates both a short and long file name at the first free entry in a directory.
Param parent_dir_addr: The address of the parent directory to create the short file name in.
Param entry_addr: The address the function put the short file name entry.
Param name: The full file name.
Returns: EOF if there was a problem, GOODEC if everything went okay.
*/
signed int set_file_name(int32 parent_dir_addr, int32* entry_addr, char name[])
{
   char sname[12];   // place to hold the short file name

   signed int name_pos = 0;   // the current parse position of name[]

   int
      chksum,               // the long file name checksum
      entire_entry[0x20],   // the entire entry to put write onto the media
      entry_pos,            // the current position inside of entire_entry
      long_entry = 1;       // the current long entry number we're on

   int32 i;   // pointer to memory

   // check for invalid characters
   if(check_invalid_char(name) == EOF)
      return EOF;

   // make a short file name of this
   if(make_short_file_name(parent_dir_addr, name, sname) == EOF)
      return EOF;

   // get a checksum for the long file name entries
   chksum = long_name_chksum(sname);

   // start writing the long file name
   // zero out entry[]
   for(entry_pos = 0; entry_pos < 0x20; entry_pos += 1)
      entire_entry[entry_pos] = 0;   

   i = parent_dir_addr;
   if(get_next_free_entry(&i) == EOF)
      return EOF;

   // 0x0F signifies an file entry
   entire_entry[11] = 0x0F;

   // since we're working in reverse, write the final long name entry
   name_pos = strlen(name);
   name_pos %= 13;

   if(name_pos != 0)
   {
      // add 1 to account for the \0 terminator
      name_pos += 1;

      fill_entry(entire_entry, 0xFF, name_pos);
   }

   // start writing the long file name entries
   name_pos = strlen(name);

   // figure out how many entries this name will take up
   long_entry = (name_pos / 13) + 1;

   if(name_pos % 13 == 0)
      long_entry -= 1;

   // set the bit to signify this is the final entry
   long_entry |= 0x40;

   while(name_pos >= 0)
   {
      entry_pos = name_pos % 13;

      if(entry_pos < 5)
         entire_entry[(entry_pos << 1) + 1] = name[name_pos];

      else if(entry_pos < 11)
         entire_entry[(entry_pos << 1) + 4] = name[name_pos];

      else
         entire_entry[(entry_pos << 1) + 6] = name[name_pos];

      if((entry_pos == 0)
         && (name_pos != strlen (name)))
      {
         entire_entry[0] = long_entry;

         // clear off the bits at positions 6 and 7 if the most recent entry was the final one.
         if(name_pos != 0)
            long_entry &= 0x3F;

         long_entry -= 1;

         entire_entry[13] = chksum;
         if(mmcsd_write_data(i, 0x20, entire_entry) != GOODEC)
            return EOF;
         if(get_next_free_entry(&i) == EOF)
            return EOF;
         fill_entry(entire_entry, 0x00, 0);
      }
      name_pos -= 1;
   }

   // write the short file name to the entry
   if(mmcsd_write_data(i, 11, sname) != GOODEC)
      return EOF;

   // set the new entry addr
   *entry_addr = i;

   return GOODEC;
}

/*
signed int get_short_file_name(int32 file_entry_addr, char sname[], int type)
Summary: Reads a file's short file name, puts all the characters into lower case, and puts it into a buffer.
Param file_entry_addr: Where the file's entry address is located.
Param sname: The buffer to put the short file name.
Returns: EOF if there was a problem, GOODEC if everything went okay.

signed int get_short_file_name(int32 file_entry_addr, char sname[], int type)
{
   int
      buf,
      i,
      j = 0;

   // one short file name has, at the most, 11 characters
   for(i = 0; i < 11; i += 1)
   {     
      // read in a character
      if(mmcsd_read_data(i + file_entry_addr, 1, &buf) != GOODEC)
         return EOF;
     
      // convert the character
      if(buf != ' ')
      {         
         sname[j] = tolower(buf);
         j += 1;
      }
     
   }   

   // tack on a null terminator
   sname[j] = '\0';
   
   //printf("\r\n%s, %u\r\n",sname, strlen(sname));

   if(type != 0x10 && strlen(sname) > 3)
   {
      j = strlen(sname);
      for(i=j; i > j-3; --i)
         sname[i] = sname[i-1];
      sname[i] = '.';
   }
   
   sname[j+1] = '\0';

   return GOODEC;
}
*/

signed int get_short_file_name(int32 file_entry_addr, char sname[], int type)
{
 int
   buf,
   i,
   j = 0;
// one short file name has, at the most, 11 characters
   for(i = 0; i < 11; ++i)
      {
       // read in a character
       if(mmcsd_read_data(i + file_entry_addr, 1, &buf) != GOODEC)
       return EOF;
       // convert the character
       if(buf != ' ')
         {
          if (i == 8 && type != 0x10) sname[j++] = '.';
          sname[j++] = tolower(buf);
         }
      }
   if (sname[j - 1] == '.') --j;
   sname[j] = '\0';
   return GOODEC;
}





/*
signed int make_short_file_name(int32 parent_dir_addr, char fname[], char sname[])
Summary: Creates a unique short file name in a directory.
Param parent_dir_addr: The address of the parent directory to create the short file name in.
Param fname: The full file name.
Param sname: Character array that will hold the short file name upon function completion.
Returns: EOF if there was a problem, GOODEC if everything went okay.
*/
signed int make_short_file_name(int32 parent_dir_addr, char fname[], char sname[])
{
   char
      val[12] = "           ",
      cur_fname[12] = "           ",
      cur_fnum[7] = "      ";

   int
      buf,
      ext_pos,
      fname_parse_pos = 0,
      val_parse_pos = 0;

   int32
      fnum = 0,
      i;

   // figure out where the extension position is
   ext_pos = strchr(fname, '.');

   // check to see if this file has an extension
   if(ext_pos == 0)
   {
      while((val_parse_pos < 8) && (fname[fname_parse_pos] != '\0'))
      {
         val[val_parse_pos] = toupper(fname[fname_parse_pos]);
         val_parse_pos += 1;
         fname_parse_pos += 1;

         // we can't have a '.' or ' ' in the short name
         while((fname[fname_parse_pos] == '.') || (fname[fname_parse_pos] == ' '))
            fname_parse_pos += 1;
      }
   }
   else
   {
      ext_pos -= fname - 1;
      while((val_parse_pos < 11) && (fname[fname_parse_pos] != '\0'))
      {
         val[val_parse_pos] = toupper(fname[fname_parse_pos]);
         val_parse_pos += 1;
         fname_parse_pos += 1;

         // we can't have a '.' or ' ' in the short name
         while((fname[fname_parse_pos] == '.') || (fname[fname_parse_pos] == ' '))
            fname_parse_pos += 1;

         // check to see if it's time to skip val_parse_pos ahead to the file extension
         if(fname_parse_pos == ext_pos)
            val_parse_pos = 8;

         // check to see if it's time to skip name_parse_pos ahead to the file extension
         else if(val_parse_pos == 8)
            fname_parse_pos = ext_pos;
      }
   }

   // now that we've got the short file name, we need to make it unique
   i = parent_dir_addr;
   if(mmcsd_read_data(i + 0x0B, 1, &buf) != GOODEC)
      return EOF;

   // keep reading until we hit empty space
   while(buf != 0x00)
   {
      // check to see if this is a short file name entry
      if((buf == 0x20) || (buf == 0x10))
      {
         // read in the short file name that we're currently pointing at
         if(mmcsd_read_data(i, 11, cur_fname) != GOODEC)
            return EOF;

         cur_fname[11] = '\0';

         // strcmp will return a 0 if the file name we're currently pointing at and the file name that we created above are the same
         if(strcmp(cur_fname, val) == 0)
         {
            // we now need to create a unique file name
            //  increment the unique file number by one
            fnum += 1;

            // convert the unique file number to a string
            sprintf(cur_fnum, "%u", fnum);

            // put the unique file number, along with a '~' into our short file name
            fname_parse_pos = 0;

            // find out the last posiiton of a space
            val_parse_pos = strchr(val, ' ');
            if(val_parse_pos == 0)
               // if there isn't a space, then we're going to have to put the ~x at the end of the short name
               val_parse_pos = 7 - strlen(cur_fnum);
            else
               // if there is a space, then put the ~x there
               val_parse_pos -= val + 2;

            // make some room for extra digits
            buf = 10;
            while(fnum >= buf)
            {
               val_parse_pos -= 1;
               buf *= 10;
            }

            // write in the ~
            val[val_parse_pos] = '~';

            // write in the number
            val_parse_pos += 1;
            while(cur_fnum[fname_parse_pos] != '\0')
            {
               val[val_parse_pos] = cur_fnum[fname_parse_pos];
               val_parse_pos += 1;
               fname_parse_pos += 1;
            }

            // start the search over again to see if that unique file name/number combination is still taken up
            i = parent_dir_addr;
         }
      }

      // head to the next entry
      if(get_next_entry(&i) == EOF)
      {
         // we're going to have to allocate another cluster
         if(alloc_clusters(addr_to_cluster(i), &i) == EOF)
            return EOF;         
      }
      if(mmcsd_read_data(i + 0x0B, 1, &buf) != GOODEC)
         return EOF;
   }

   // copy the short name into the input buffer
   for(i = 0; i < 12; i += 1)
      sname[i] = val[i];

   return GOODEC;
}

/*
int long_name_chksum (int* FcbName)
Summary: Returns an unsigned byte checksum computed on an unsigned byte
          array. The array must be 11 bytes long and is assumed to contain
          a name stored in the format of a MS-DOS directory entry.
Param: Pointer to an unsigned byte array assumed to be 11 bytes long.
Returns: Sum An 8-bit unsigned checksum of the array pointed to by pFcbName.
*/
int long_name_chksum (int* pFcbName)
{
   int
      FcbNameLen,
      Sum = 0;

   for(FcbNameLen = 11; FcbNameLen != 0; FcbNameLen -= 1)
      // The operation is an unsigned char rotate right
      Sum = ((Sum & 1) ? 0x80 : 0) + (Sum >> 1) + *pFcbName++;

   return Sum;
}

/*
signed int check_invalid_char(char fname[])
Summary: Checks the filename for any invalid characters.
Param: The name of the file to check.
Returns: EOF if an invalid character was found, GOODEC otherwise.
*/
signed int check_invalid_char(char fname[])
{
   int fname_pos;

   for(fname_pos = 0; (fname[fname_pos] != '\0') && (fname_pos < MAX_FILE_NAME_LENGTH); fname_pos += 1)
      if(isamoung(fname[fname_pos], "\\/:*?\"<>|"))
         return EOF;

   return GOODEC;
}
Neo2a



Joined: 02 May 2009
Posts: 7
Location: Hungary

View user's profile Send private message Send e-mail MSN Messenger

Main code
PostPosted: Wed Aug 22, 2012 2:49 am     Reply with quote

The main code is this
based on the example in ccsc
Code:

#include <fat16 proba.h>

//#use rs232(UART1,baud=9600,parity=N,bits=8,stream=RS232)

#byte PLLDIV = 0x746   // bits 8--0 = Pll div = 0x1e
#byte CLKDIV = 0x744   // bits 7--6 = Pll post = 0  // bits 4--0 = Pll Pre = 0
#byte SPI2CON1 = 0x262

#include "\mmcsd.c"
#include "\fat.c"

//////////////////////////////////////
#include <stdlib.h> // for atoi32


//////////////////////
///                ///
/// Useful Defines ///
///                ///
//////////////////////

#define COMMAND_SIZE 10
#define NUM_COMMANDS 11

////////////////////////
///                  ///
/// Global Variables ///
///                  ///
////////////////////////

char g_CWD[200] = "/"; //current working directory

char commands[NUM_COMMANDS][COMMAND_SIZE]=
{
   "del",      //option1=filename.  delete file.
   "make",     //option1=filename.  create an empty file, give error if file already exists
   "append",   //option1=filename, option2=string.  append string to end of file
   "cd",    //option1=new cwd.  change working directory.  / is root.
   "dir",    //show files in directory
   "cat",    //option1=filename.  display full contents in ascii
   "tail",  //option1=filename.  display the last 20 lines of file.
   "mkdir", //option1=dir.  create directory.  see 'cd' for rules on dir
   "rmdir",  //option1=dir.  remove directory.  see 'cd' for rules on dir.
   "format",   // option1=media size in bytes. formats the media.
   "help"   // help!
};

////////////////////////////////
///                          ///
/// Function Implementations ///
///                          ///
////////////////////////////////

/*
Summary: Finds a command from the global list of commands.
Param: A pointer to the command string.
Returns: The command number if the command is found in the command list.
         0xFF if the command isn't found
*/
int FindCommand(char *cmd)
{
   char buf[COMMAND_SIZE];
   int i;
   
   for (i=0; i<NUM_COMMANDS; i++)
   {
      strcpy(buf, &commands[i][0]);
      if (stricmp(buf, cmd)==0)
         return(i);
   }
   
   return(0xFF);
}

/*
Summary: Displays the current working directory.
Param: None.
Returns: None.
*/
void DisplayPrompt(void)
{
   printf("\r\n\n%s> ", g_CWD);
}

/*
Summary: Deletes a file.
Param: The full path of the file to delete.
Returns: None.
*/
void DeleteFile(char *fileName)
{
   printf("\r\nDeleting '%s': ", fileName);
   if(rm_file(fileName) != GOODEC)
   {
      printf("Error deleting file");
      return;
   }
   printf("OK");
}

/*
Summary: Creates a file.
Param: The full path of the file to create.
Returns: None.
Example Usage: \> make "Log.txt"
*/
void MakeFile(char *fileName)
{
   printf("\r\nMaking file '%s': ", fileName);
   if(mk_file(fileName) != GOODEC)
   {
      printf("Error creating file");
      return;
   }
   printf("OK");
}

/*
Summary: Append a string to a file.
Param: The full path of the file to append to.
Param: A pointer to a string to append to the file.
Returns: None.
Example Usage: \> append "Log.txt" "This will be appended to the end of Log.txt"
Note: A "\r\n" will be appended after the appendString.
*/
void AppendFile(char *fileName, char *appendString)
{
   FILE stream;
   printf("\r\nAppending '%s' to '%s': ", appendString, fileName);
   if(fatopen(fileName, "a", &stream) != GOODEC)
   {
      printf("Error opening file");
      return;
   }
   
   fatputs(appendString, &stream);
   fatputs("\r\n", &stream);

   if(fatclose(&stream) != GOODEC)
   {
      printf("Error closing file");
      return;
   }
   printf("OK");
}

/*
Summary: Change the working directory.
Param: The new working directory to switch to.
Returns: None.
Example Usage: \> cd ftp/     -> /ftp/
               \ftp\> cd files/  -> /ftp/files/
               \ftp\files> cd..  -> /ftp/
               \ftp\> cd ..      -> /
               \> cd /ftp/files/ -> /ftp/files/
               
Note: Changing the directory to .. will go up a directory.
*/
void ChangeDirectory(char *newCWD)
{
   FILE stream;
   
   //append a / to the end of the filename if it doesn't exist
   //making an assumption here that newCWD can hold 1 more character
   if (newCWD[strlen(newCWD)-1] != '/')
     strcat(newCWD, "/");

   if((strstr(newCWD, "../") != 0) && (strcmp(g_CWD, "/") != 0))
   {
      g_CWD[strlen(g_CWD) - 1] = '\0';
           
      g_CWD[strrchr(g_CWD, '/') - g_CWD + 1] = '\0';     
   }
   else
   {
      if(fatopen(newCWD, "r", &stream) != GOODEC)
      {
         printf("\r\nError changing directory");
         return;
      }
      strcpy(g_CWD, newCWD);
   }
}

/*
Summary: Display the contents of the working directory.
Param: The full path of the directory contents to display.
Returns: None.
Example Usage: /> dir
*/
void DisplayDirectory(char *dir)
{
   disp_folder_contents(dir);
}

/*
Summary: Create a directory.
Param: The full path of the directory to create.
Returns: None.
Example Usage: /> mkdir "Backlog"
*/
void MakeDirectory(char *dir)
{
   //append a / to the end of the filename if it doesn't exist
   //making an assumption here that newCWD can hold 1 more character
   if (dir[strlen(dir)-1] != '/')
     strcat(dir, "/");

   printf("\r\nMaking directory '%s': ", dir);

   if(mk_dir(dir) != GOODEC)
   {
      printf("Error creating directory");
      return;
   }
   printf("OK");
}

/*
Summary: Remove a directory.
Param: The full path of the directory to remove.
Returns: None.
Example Usage: /> rmdir "Backlog"
Note: The directory needs to be empty in order for this command to work.
*/
void RemoveDirectory(char *dir)
{
   printf("\r\nRemoving directory '%s': ", dir);

   //append a / to the end of the filename if it doesn't exist
   //making an assumption here that newCWD can hold 1 more character
   if (dir[strlen(dir)-1] != '/')
     strcat(dir, "/");

   if(rm_dir(dir) != GOODEC)
   {
      printf("Error removing directory");
      return;
   }
   printf("OK");
}

#define CAT_FROM_START  FALSE
#define CAT_FROM_END    TRUE
/*
Summary: Prints either all of or the last 80 characters in a file.
Param: The full path of the file to print off.
Param: If true, this function will print off the last 80 characters in the file.
       If false, this funciton will print off the entire file.
Returns: None.
Example Usage: /> cat "Logs.txt" (this will display the entire file)
Example Usage: /> tail "Logs.txt" (this will display the last 80 characters in the file)
*/
void PrintFile(char *fileName, int1 startFromEnd)
{
   FILE stream;

   if(fatopen(fileName, "r", &stream) != GOODEC)
   {
      printf("\r\nError opening file");
      return;
   }

   printf("\r\n");

   if(startFromEnd)
      fatseek(&stream, 80, SEEK_END);

   fatprintf(&stream);
   fatclose(&stream);
}

/*
Summary: Formats the media to a specified size.
Param: The size of the media, in kB, in string form.
Returns: None.
Example Usage: /> format 524288 (format a 512MB card)
*/
void FormatMedia(char *mediaSize)
{
   int32 size;
   
   size = atoi32(mediaSize);
   
   printf("\r\nFormatting media (size=%LU): ", size);
 
   if(format(size) != GOODEC)
   {
      printf("Error formatting media");
      return;
   }
   printf("OK");
}

/*
Summary: Shows a help prompt.
Param: None.
Returns: None.
Example Usage: /> help
*/
void ShowHelp()
{
   printf("\r\nFAT Shell Help");
   printf("\r\n del filename --- Deletes the file");
   printf("\r\n make filename --- Creates an empty file");
   printf("\r\n append filename string --- Appends string to the end of the file");
   printf("\r\n cd dir --- Change the working directory");
   printf("\r\n dir --- Shows the contents of the directory");
   printf("\r\n cat filename --- Displays content of file");
   printf("\r\n tail filename --- Displays the last 80 characters of file");
   printf("\r\n mkdir dir --- Create a directory");
   printf("\r\n rmdir dir --- Deletes the directory");
   printf("\r\n format size --- Format card.  (Example: 'format 5524288' formats a 512MB card)");
   printf("\r\n help\tYou are here");
   printf("\r\n\n Put a parameter in quotes if it has spaces");
}

char * GetCMD(char *in)
{
   char tokens[]=" \r\n";
   return(strtok(in,tokens));
}

char * GetOption(char *in)
{
   char tokensSpace[]=" \r\n";
   char tokensQuote[]="\"\r\n";
   
   //trim leading spaces
   while (*in==' ')
      in++;
   
   //if first char is a quote, then end token on a quote.  ELSE end token on a space
   if (*in == '\"')
      return(strtok(in,tokensQuote));
   else
      return(strtok(in,tokensSpace));
}


/////////////////////////////////////

void main(void)
{
   //PLL setting for 32M and SPI CLK settings for hardware SPI2
   PLLDIV=30;
   CLKDIV=128;
   SPI2CON1=60;   
   set_tris_g (80);


   output_high(PIN_C4);              // Disable Serial Flash module
   output_high(PIN_G12);             // Disable MP3 module
   output_low(PIN_D7);               // LCD backlight off   


   setup_spi( FALSE );               //Kill hardware SPI
   setup_spi2( FALSE );              //Kill hardware SPI2   


   printf("Program Started!");
   delay_ms(2000);
   char buffer[255];
   char opt_buffer[255];
   char *cmd, *option1, *option2;
   
   int i;   // pointer to the buffer

   // initialize the FAT
   //  keep in mind that this will automagically initialize the media
   i = fat_init();
   if (i)
      printf("\r\n\nERROR INITIALIZING FAT\r\n\n");
   
   // main loop
   while(TRUE)
   {
      i = 0;
     
      DisplayPrompt();
     
      do
      {
         buffer[i] = getch();
         
         // check for a backspace
         if(buffer[i] != 8)
         {
            printf("%c", buffer[i]);
            i++;
         }
         else if(i > 0)
         {
            // delete the last character
            i--;
            putc(8);
            putc(' ');
            putc(8);
         }
         buffer[i] = '\0';
      } while(buffer[i - 1] != '\r');
     
      // parse the command and options
      cmd = GetCMD(buffer);
      option1 = GetOption(cmd + strlen(cmd) + 1);
      option2 = GetOption(option1 + strlen(option1) + 1);

      //if option1 starts with a '/', that means the file in the option includes
      //the full path to the file.  if the file doesn't start with a '/', the
      //current working directory must be added.
      if (option1 && (option1[0]=='/'))
      {
         //option1 is a full path
         strcpy(opt_buffer, option1);
      }
      else if (option1)
      {
         // tack on the current working directory to option1
         strcpy(opt_buffer, g_CWD);
         strcat(opt_buffer, option1);
      }         
     
      if (cmd)
      {
         switch(FindCommand(cmd))
         {
            case 0:  //del
               DeleteFile(opt_buffer);
               break;
           
            case 1:  //make
               MakeFile(opt_buffer);
               break;
           
            case 2:  //append
               AppendFile(opt_buffer, option2);
               break;
           
            case 3:  //change directory
               ChangeDirectory(opt_buffer);
               break;
           
            case 4:  //show directory contents
               DisplayDirectory(g_CWD);
               break;
               
            case 5:  //cat, display file
               PrintFile(opt_buffer, CAT_FROM_START);
               break;
           
            case 6:  //tail, display last 80 charachters
               PrintFile(opt_buffer, CAT_FROM_END);
               break;
           
            case 7: //mkdir, make a directory
               MakeDirectory(opt_buffer);
               break;

            case 8: //rmdir, make a directory
               RemoveDirectory(opt_buffer);
               break;

            case 9: //format, format the card
               FormatMedia(option1);
               break;

            case 10: //help, display help
               ShowHelp();
               break;

            default:
               printf("\r\nUnkown Command '%s'", cmd);
               break;
         }
      }
   }


}



The header file in the fat16 proba.h


Code:


#include <33FJ256GP710A.h>
#device ICD=TRUE
#device PASS_STRINGS = IN_RAM

#device ADC=12
#FUSES WDT                    //Watch Dog Timer
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOBSS                    //No boot segment
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOOSCIO                    //OSC2 is general purpose output
#FUSES PR_PLL                     //Pimary oscillator
#FUSES XT
#FUSES WPRES128                 //Watch Dog Timer PreScalar 1:128
#FUSES WPOSTS16                 //Watch Dog Timer PostScalar 1:32768
#FUSES PUT128                   //Power On Reset Timer value 128ms
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES NORSS                    //No secure segment RAM
#FUSES NOSSS                    //No secure segment
#FUSES NOWRTSS                  //Secure segment not write protected
#FUSES NORBS                    //No Boot RAM defined
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOJTAG                   //JTAG disabled

#use delay(clock=32000000)
#use fixed_IO(E_outputs = PIN_E0,PIN_E0,PIN_E1,PIN_E1,PIN_E2,PIN_E2)

#use rs232(baud=9600,xmit=PIN_F5,rcv=PIN_F4,parity=N,bits=8,stream=USB,errors)



I hope somebody will help me.

Sad

Thax
Steve
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group