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

FAT32 code for MultiMedia Cards
Goto page Previous  1, 2, 3, 4, 5  Next
 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
manish12



Joined: 18 Jan 2009
Posts: 15

View user's profile Send private message

WHAT IS/SHOULD THE SIZE OF CARD AND WHAT TYPE ?
PostPosted: Mon Jan 19, 2009 1:21 am     Reply with quote

I AM USING 512MB SD CARD , BUT NOT SUCEESES.
asmallri



Joined: 12 Aug 2004
Posts: 1630
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

Re: WHAT IS/SHOULD THE SIZE OF CARD AND WHAT TYPE ?
PostPosted: Mon Jan 19, 2009 6:48 pm     Reply with quote

manish12 wrote:
I AM USING 512MB SD CARD , BUT NOT SUCEESES.


Why would you use FAT32 on such a small SD card?

FAT16 is SIGNIFICANTLY faster than FAT32 when used with a PIC.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
manish12



Joined: 18 Jan 2009
Posts: 15

View user's profile Send private message

PostPosted: Mon Jan 19, 2009 10:52 pm     Reply with quote

I am concerned about the fat32 code given,

code for fat 32, so I am not able to use lower memory value i.e 32MB even it is fast .
asmallri



Joined: 12 Aug 2004
Posts: 1630
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Jan 20, 2009 3:47 am     Reply with quote

manish12 wrote:
I am concerned about the fat32 code given,

code for fat 32, so I am not able to use lower memory value i.e 32MB even it is fast .


FAT16 supports up to 2GB
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
manish12



Joined: 18 Jan 2009
Posts: 15

View user's profile Send private message

PostPosted: Tue Jan 20, 2009 4:42 am     Reply with quote

how you format it ?
asmallri



Joined: 12 Aug 2004
Posts: 1630
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Jan 20, 2009 7:28 am     Reply with quote

manish12 wrote:
how you format it ?


To format an SD/MMC card for FAT16, from windows select the drive (SD/MMC Card), right click, select format. On the file system drop down box select FAT. It will then format using FAT16.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
manish12



Joined: 18 Jan 2009
Posts: 15

View user's profile Send private message

PostPosted: Tue Jan 20, 2009 12:02 pm     Reply with quote

check it yourself.

any way for those who haven't format the memory size > 32bm windows not support for fat16, it will show as fat but from fdisk you will find that it is fat32 .

and for 32bm it is format with fat16 only! by default
asmallri



Joined: 12 Aug 2004
Posts: 1630
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Jan 20, 2009 4:11 pm     Reply with quote

manish12 wrote:
check it yourself.


I develop and sell File System Software for PICs and am continually testing cards and features. I regularly format cards from 256MB to 2GB with FAT16 as part of my test procedures for my software to identify the FAT used.

Quote:

any way for those who haven't format the memory size > 32bm windows not support for fat16, it will show as fat but from fdisk you will find that it is fat32 .


No this is not true. Perhaps there is something wrong with your windows installation.

Quote:
and for 32bm it is format with fat16 only! by default


Here is an extract of a Kingston 2GB card initially formatted to FAT32

Code:

Partition boot sector:
00000050 - 20 20 46 41 54 33 32 20 20 20 33 C9 8E D1 BC F4   FAT32   3ɎѼô

Volume is FAT32
Bytes per Sector = 512
Reserved Sectors = 34
Sectors per Cluster = 8
Cluster_size_bytes = 4096
Root directory Entries = 0
Total Sectors = 3921920
Sectors for FAT = 3823
FAT 1 address = 0x00004400
FAT 2 address = 0x001E2200
Root directory address = 0x003C0000
Data area address = 0x003C0000
Root directory sectors = 0
Sectors for data = 3914240
Total Clusters = 489280
Hidden Sectors = 0


Here is the same card formatted to FAT16 using the procedure I described above:
Code:

Partition boot sector:
0001E630 - 4D 45 20 20 20 20 46 41 54 31 36 20 20 20 33 C9 ME    FAT16   3É

Volume is FAT16
Bytes per Sector = 512
Reserved Sectors = 4
Sectors per Cluster = 64
Cluster_size_bytes = 32768
Root directory Entries = 512
Total Sectors = 4022029
Sectors for FAT = 246
FAT 1 address = 0x0001EE00
FAT 2 address = 0x0003DA00
Root directory address = 0x0005C600
Data area address = 0x00060600
Root directory sectors = 32
Sectors for data = 4021501
Total Clusters = 62835
Hidden Sectors = 243


You can clearly see the card has been formatted to FAT16.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
manish12



Joined: 18 Jan 2009
Posts: 15

View user's profile Send private message

PostPosted: Tue Jan 20, 2009 11:31 pm     Reply with quote

You might be right, I may be wrong.

Thank you!

I highly appreciate your efforts

I now I can suggest to others.
CLK.Tech



Joined: 30 Apr 2009
Posts: 5

View user's profile Send private message

PostPosted: Thu Apr 30, 2009 4:36 am     Reply with quote

Hi guys!

Just a question: does anybody migrate this code to a PIC24 device? I'm trying that and I have so much errors.

The SPI Hardware runs properly but some loops fail.

Did anybody do that?
dynamitron



Joined: 18 Mar 2009
Posts: 38

View user's profile Send private message

PostPosted: Tue Apr 13, 2010 3:22 pm     Reply with quote

I must says that I have try all the driver and format methods mentionned in the diffrent posts of this forum. For my case, none of them was a success.

I decided to buy the driver from asmallri (brushelectronics.com) and they works out of the box !! Everything went perfect after having simply formated my 2 gb SD card with a camera. For the moment, I do not even know if the card is formated in FAT16 or 32.
I am able to create a file with the pic, write into it, read it and send it over rs232.
On my PC, I can read the file, modify it and if I put back the card on the pic, I see the modification done on the PC.

Dynamitron.
Scythe



Joined: 05 Mar 2010
Posts: 5

View user's profile Send private message

PostPosted: Thu May 13, 2010 11:46 am     Reply with quote

Code working without any problem. But I couldn't manage to update the contents of file previously opened and written. Whenever I tried to log something new, it overwrites the previous value. Is there anyway to overcome this ?
neochrome32



Joined: 09 Jun 2013
Posts: 153

View user's profile Send private message Visit poster's website

FAT32 with Tomi
PostPosted: Mon Jun 10, 2013 8:56 pm     Reply with quote

this is the demo code
Code:

// main.c

#include <main.h>


// Current Pin Setup for the SDCARD //
// TESTED SO FAR AND WORKING //
/*
   Transcend SD 2GIG (cheap o card) - WORKING
   
*/

/* THESE ARE MY CHIP SPECIFICS */
#define MMC_CS    PIN_c2
#define MMC_CLK   PIN_c3
#define MMC_DI    PIN_C4
#define MMC_DO    PIN_C5


#define MMCSD_PIN_SELECT  MMC_CS //o
#define MMCSD_PIN_SCL     MMC_CLK //o
#define MMCSD_PIN_SDI     MMC_DI //i
#define MMCSD_PIN_SDO     MMC_DO //o


#use FAST_IO(C)

#include <string.h>

#include "mmcsd.c"


#include "gofat.c"   // Tomi- Fat32 using CCS C (2007) Modified MMCSD.C Driver



void PrintData(char *data, long len){
   long i;
   long j;
   long k;
   int8   step1;
   //int8   step2;
   printf ("Showing Block Length: %lx [%lu byte(s)]\n", len,len);
   
   j = 0;
   
   step1=0;
   //step2=0;
   for (i = 0; i < len; i++){
      printf (" %02X", data[i]);
      if((i%8)==7)
         putc(' ');
      if (j >= 31) {
         printf (" | ");

         for (k = (i - 31); k <= i; k++)         {
            if (! isalnum (data[k])) printf (".");
            else printf ("%c", data[k]);
           
           
            if((k%8)==7)
               putc(' ');
           
         }

         printf ("\r\n");
         j = 0;
         
      } else {
         j++;
      }
   }
   putc('\n');
}

/*------------- FAT32 TESTING -----------*/
char buffer[512];
int8 *ptra;
char filename[32];   // 32 size names, (TESTED WITH 8+3 type though this worked)
int32 AllocSpace;
char fs;   // File system ID (for when you open systems, this supports 2 only (save on already bloated ram usage)
int8 g;





void main(){

   /* my chip specifics */
   setup_wdt(WDT_OFF);
   setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
   setup_timer_4(T4_DISABLED,0,1);
   setup_timer_5(T5_DISABLED | T5_DIV_BY_1);
   setup_timer_6(T6_DISABLED,0,1);
    setup_adc(ADC_OFF);
   setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard   
   /* end */


   printf("\n\nBooting...\n\n");

   ptra = &(buffer[0]);
   
   // ALL YOU NEED REALLY IS mcscd_init() and InitFat()
   
   if(mmcsd_init()==MMCSD_GOODEC){
      AllocSpace=InitFAT();   // (AllocSpace ot really needed, but can be used to verify FAT32 startup)
      printf("ROOT LOCATION : %Lu\n", AllocSpace+2);   // print the location
      ReadSector(AllocSpace+2,ptra);   // READ Sector into buffer (ptra is the pointer for buffer[]) the first sector of the FS part - again not really important
      PrintData(Buffer,512);
   }
   
   
   strcpy(filename,"FASTROM.TXT");
   
   // CREATE THE FILE if you KNOW this file doesn't exist on your sdcard. otherwise leave commented out
   /*   
   fs=fopen(filename, 'w');
      printf("chunk 0... ");
      strcpy(buffer, "new file\r\n");
      fwrite(buffer, strlen(buffer),fs);
   fclose(fs);
   */
   
   /* IN THIS part, we're demonstrating that you can append text to a file,
      IMPORTANT NOTE is before you can append another set of text you need to close file and reopen again    .
         seems important otherwise your just going to over write the buffer, fclose just writes the buffer to sector.
         
   */
   
   /*
   fs=fopen(filename, 'a');
      printf("chunk 1... ");
      strcpy(buffer, "something new to put in to the rom ball.\r\n");
      fwrite(buffer, strlen(buffer),fs);
   fclose(fs);

   fs=fopen(filename, 'a');
      printf("chunk 2... ");
      strcpy(buffer, "i want to make sure this works ok. \r\n");
      fwrite(buffer, strlen(buffer),fs);
   fclose(fs);

   fs=fopen(filename, 'a');
      printf("chunk 3... ");
      strcpy(buffer, "**I dont know what to put in to the rom, but i want to see it work like this **\r\n");
      fwrite(buffer, strlen(buffer),fs);
   fclose(fs);

   fs=fopen(filename, 'a');
      printf("chunk 4... ");
      strcpy(buffer, "**Need something better than just a few bytes of text though... how hmm**\r\n");
      fwrite(buffer, strlen(buffer),fs);
   fclose(fs);
   */
   
   /* check out the data, this worked */


   /* for this test to work, make a file On your sdcard, name it "test.txt" and put in 'hello world' for example or anything you like
      if successfull you should get the data..
      NOTE: appears that you can only load 512bytes at a time, (im sure we all knew that already)
   */
   
   //strcpy(filename, "STUFF1/FILE1.TXT"); // this was a demo to see if i could do directories - it worked. NOTE: STUFF1/FILE1.TXT, there is NO leading '/'
   strcpy(filename, "STUFF1/FILE1.TXT"); // note this is in CAPS? seems i haven't worked out yet how to use the ansi names (long names) this works anyways
   fs=fopen(filename, 'r');   //r=read. if this file doesn't exist, the file is created!
   
      fread(buffer,256, fs);   // this will read 32 bytes from the file... i suspect tho that if you read off the end of a file, that is also loaded, hmm
      buffer[256]=0;   // null char at the end, as fread does NOT terminate string... this is RAW
   fclose(fs);
   
   printf("String from File: TEST.TXT was %s\n" , buffer);
   
   delay_ms(1000);
   
   
   
   printf("\nDone.:");

   for(;;);

}
[/code]
neochrome32



Joined: 09 Jun 2013
Posts: 153

View user's profile Send private message Visit poster's website

main.h
PostPosted: Mon Jun 10, 2013 8:57 pm     Reply with quote

main.c
this code is really specific to the chip im using, but i tried to make sure it didn't bother the rest of the code and to keep it as generic as possible

Code:

#include <18F46K22.h>
#device *=16


#FUSES NOXINST
#FUSES NOPBADEN                   //PORTB pins are configured as analog input channels on RESET
#fuses HSH,PUT,NOPROTECT,NOLVP,NOWDT,NOBROWNOUT,PLLEN,NOPBADEN,WDT128
#device WRITE_EEPROM = NOINT

#use delay(crystal=8M,  clock=32000000)

#use rs232(baud=115200,parity=N,xmit=PIN_D1,rcv=PIN_D2,bits=8,stream=PORT1)



neochrome32



Joined: 09 Jun 2013
Posts: 153

View user's profile Send private message Visit poster's website

mmcsd.c
PostPosted: Mon Jun 10, 2013 8:59 pm     Reply with quote

again i needed something for SDcards only, BUT this served....

there are modifications to the one Tomi did, NOT MUCH though mind...

i used this code really to get the read sector and write sector working in the follow codes (gofat.c) and (gofat.h)



Code:


/////////////////////////////////////////////////////////////////////////
////                           MMCSD.c                               ////
////                                                                 ////
////    This is a low-level driver for MMC and SD cards.             ////
////                                                                 ////
//// --User Functions--                                              ////
////                                                                 ////
//// mmcsd_init(): Initializes the media.                            ////
////                                                                 ////
//// mmcsd_read_byte(a, p)                                           ////
////  Reads a byte from the MMC/SD card at location a, saves to      ////
////  pointer p.  Returns 0 if OK, non-zero if error.                ////
////                                                                 ////
//// mmcsd_read_data(a, n, p)                                        ////
////  Reads n bytes of data from the MMC/SD card starting at address ////
////  a, saves result to pointer p.  Returns 0 if OK, non-zero if    ////
////  error.                                                         ////
////                                                                 ////
//// mmcsd_flush_buffer()                                            ////
////  The two user write functions (mmcsd_write_byte() and           ////
////  mmcsd_write_data()) maintain a buffer to speed up the writing  ////
////  process.  Whenever a read or write is performed, the write     ////
////  buffer is loaded with the specified page and only the          ////
////  contents of this buffer is changed.  If any future writes      ////
////  cross a page boundary then the buffer in RAM is written        ////
////  to the MMC/SD and then the next page is loaded into the        ////
////  buffer.  mmcsd_flush_buffer() forces the contents in RAM       ////
////  to the MMC/SD card.  Returns 0 if OK, non-zero if errror.      ////
////                                                                 ////
//// mmcsd_write_byte(a, d)                                          ////
////  Writes data byte d to the MMC/SD address a.  Intelligently     ////
////  manages a write buffer, therefore you may need to call         ////
////  mmcsd_flush_buffer() to flush the buffer.                      ////
////                                                                 ////
//// mmcsd_write_data(a, n, p)                                       ////
////  Writes n bytes of data from pointer p to the MMC/SD card       ////
////  starting at address a.  This function intelligently manages    ////
////  a write buffer, therefore if you may need to call              ////
////  mmcsd_flush_buffer() to flush any buffered characters.         ////
////  returns 0 if OK, non-zero if error.                            ////
////                                                                 ////
//// mmcsd_read_block(a, s, p)                                       ////
////  Reads an entire page from the SD/MMC.  Keep in mind that the   ////
////  start of the read has to be aligned to a block                 ////
////  (Address % 512 = 0).  Therefore s must be evenly divisible by  ////
////  512.  At the application level it is much more effecient to    ////
////  to use mmcsd_read_data() or mmcsd_read_byte().  Returns 0      ////
////  if successful, non-zero if error.                              ////
////                                                                 ////
//// mmcsd_write_block(a, s, p):                                     ////
////  Writes an entire page to the SD/MMC.  This will write an       ////
////  entire page to the SD/MMC, so the address and size must be     ////
////  evenly  divisble by 512.  At the application level it is much  ////
////  more effecient to use mmcsd_write_data() or mmcsd_write_byte().////
////  Returns 0 if successful, non-zero if error.                    ////
////                                                                 ////
//// mmcsd_print_cid(): Displays all data in the Card Identification ////
////                     Register. Note this only works on SD cards. ////
////                                                                 ////
//// mmcsd_print_csd(): Displays all data in the Card Specific Data  ////
////                     Register. Note this only works on SD cards. ////
////                                                                 ////
////                                                                 ////
//// --Non-User Functions--                                          ////
////                                                                 ////
//// mmcsd_go_idle_state(): Sends the GO_IDLE_STATE command to the   ////
////                        SD/MMC.                                  ////
//// mmcsd_send_op_cond(): Sends the SEND_OP_COND command to the     ////
////                        SD. Note this command only works on SD.  ////
//// mmcsd_send_if_cond(): Sends the SEND_IF_COND command to the     ////
////                        SD. Note this command only works on SD.  ////
//// mmcsd_sd_status(): Sends the SD_STATUS command to the SD. Note  ////
////                     This command only works on SD cards.        ////
//// mmcsd_send_status(): Sends the SEND_STATUS command to the       ////
////                       SD/MMC.                                   ////
//// mmcsd_set_blocklen(): Sends the SET_BLOCKLEN command along with ////
////                        the desired block length.                ////
//// mmcsd_app_cmd(): Sends the APP_CMD command to the SD. This only ////
////                   works on SD cards and is used just before any ////
////                   SD-only command (e.g. send_op_cond()).        ////
//// mmcsd_read_ocr(): Sends the READ_OCR command to the SD/MMC.     ////
//// mmcsd_crc_on_off(): Sends the CRC_ON_OFF command to the SD/MMC  ////
////                      along with a bit to turn the CRC on/off.   ////
//// mmcsd_send_cmd(): Sends a command and argument to the SD/MMC.   ////
//// mmcsd_get_r1(): Waits for an R1 response from the SD/MMC and    ////
////                  then saves the response to a buffer.           ////
//// mmcsd_get_r2(): Waits for an R2 response from the SD/MMC and    ////
////                  then saves the response to a buffer.           ////
//// mmcsd_get_r3(): Waits for an R3 response from the SD/MMC and    ////
////                  then saves the response to a buffer.           ////
//// mmcsd_get_r7(): Waits for an R7 response from the SD/MMC and    ////
////                  then saves the response to a buffer.           ////
//// mmcsd_wait_for_token(): Waits for a specified token from the    ////
////                          SD/MMC.                                ////
//// mmcsd_crc7(): Generates a CRC7 using a pointer to some data,    ////
////                and how many bytes long the data is.             ////
//// mmcsd_crc16(): Generates a CRC16 using a pointer to some data,  ////
////                and how many bytes long the data is.             ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////        (C) Copyright 2007 Custom Computer Services              ////
//// This source code may only be used by licensed users of the CCS  ////
//// C compiler.  This source code may only be distributed to other  ////
//// licensed users of the CCS C compiler.  No other use,            ////
//// reproduction or distribution is permitted without written       ////
//// permission.  Derivative programs created using this software    ////
//// in object code form are not restricted in any way.              ////
/////////////////////////////////////////////////////////////////////////

#ifndef MMCSD_C
#define MMCSD_C

/////////////////////
////             ////
//// User Config ////
////             ////
/////////////////////

#include "stdint.h"

#ifndef MMCSD_PIN_SCL
 #define MMCSD_PIN_SCL     PIN_C3 //o
 #define MMCSD_PIN_SDI     PIN_C4 //i
 #define MMCSD_PIN_SDO     PIN_C5 //o
 #define MMCSD_PIN_SELECT  PIN_B4 //o
#endif

#use spi(MASTER, DI=MMCSD_PIN_SDI, DO=MMCSD_PIN_SDO, CLK=MMCSD_PIN_SCL, BITS=8, MSB_FIRST, MODE=3, stream=mmcsd_spi, BAUD=10000)

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

enum MMCSD_err
   {MMCSD_GOODEC = 0,
   MMCSD_IDLE = 0x01,
   MMCSD_ERASE_RESET = 0x02,
   MMCSD_ILLEGAL_CMD = 0x04,
   MMCSD_CRC_ERR = 0x08,
   MMCSD_ERASE_SEQ_ERR = 0x10,
   MMCSD_ADDR_ERR = 0x20,
   MMCSD_PARAM_ERR = 0x40,
   RESP_TIMEOUT = 0x80};

#define GO_IDLE_STATE 0
#define SEND_OP_COND 1
#define SEND_IF_COND 8
#define SEND_CSD 9
#define SEND_CID 10
#define SD_STATUS 13
#define SEND_STATUS 13
#define SET_BLOCKLEN 16
#define READ_SINGLE_BLOCK 17
#define WRITE_BLOCK 24
#define SD_SEND_OP_COND 41
#define APP_CMD 55
#define READ_OCR 58
#define CRC_ON_OFF 59

#define IDLE_TOKEN 0x01
#define DATA_START_TOKEN 0xFE

#define MMCSD_MAX_BLOCK_SIZE 512

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

uint8_t g_mmcsd_buffer[MMCSD_MAX_BLOCK_SIZE];

int1 g_CRC_enabled;
int1 g_MMCSDBufferChanged;

uint32_t g_mmcsdBufferAddress;

enum _card_type{SD, MMC} g_card_type;
uint32_t g_mmcsdPartitionOffset;
/////////////////////////////
////                     ////
//// Function Prototypes ////
////                     ////
/////////////////////////////

MMCSD_err mmcsd_init(int32 offset);
MMCSD_err mmcsd_read_data(uint32_t address, uint16_t size, uint8_t* ptr);
MMCSD_err mmcsd_read_block(uint32_t address, uint16_t size, uint8_t* ptr);
MMCSD_err mmcsd_write_data(uint32_t address, uint16_t size, uint8_t* ptr);
MMCSD_err mmcsd_write_block(uint32_t address, uint16_t size, uint8_t* ptr);
MMCSD_err mmcsd_go_idle_state(void);
MMCSD_err mmcsd_send_op_cond(void);
MMCSD_err mmcsd_send_if_cond(uint8_t r7[]);
MMCSD_err mmcsd_print_csd();
MMCSD_err mmcsd_print_cid();
MMCSD_err mmcsd_sd_status(uint8_t r2[]);
MMCSD_err mmcsd_send_status(uint8_t r2[]);
MMCSD_err mmcsd_set_blocklen(uint32_t blocklen);
MMCSD_err mmcsd_read_single_block(uint32_t address);
MMCSD_err mmcsd_write_single_block(uint32_t address);
MMCSD_err mmcsd_sd_send_op_cond(void);
MMCSD_err mmcsd_app_cmd(void);
MMCSD_err mmcsd_read_ocr(uint8_t* r1);
MMCSD_err mmcsd_crc_on_off(int1 crc_enabled);
MMCSD_err mmcsd_send_cmd(uint8_t cmd, uint32_t arg);
MMCSD_err mmcsd_get_r1(void);
MMCSD_err mmcsd_get_r2(uint8_t r2[]);
MMCSD_err mmcsd_get_r3(uint8_t r3[]);
MMCSD_err mmcsd_get_r7(uint8_t r7[]);
MMCSD_err mmcsd_wait_for_token(uint8_t token);
uint8_t mmcsd_crc7(char *data, uint8_t length);
uint16_t mmcsd_crc16(char *data, uint8_t length);
void mmcsd_select();
void mmcsd_deselect();

/// Fast Functions ! ///

MMCSD_err mmcsd_load_buffer(void);
MMCSD_err mmcsd_flush_buffer(void);
MMCSD_err mmcsd_move_buffer(uint32_t new_addr);
MMCSD_err mmcsd_read_byte(uint32_t addr, char* data);
MMCSD_err mmcsd_write_byte(uint32_t addr, char data);


void mmcsd_check_part(uint16_t off)
{
    printf("find offset from physical to logical %X\r\n",g_mmcsd_buffer[off] ) ;

  if (g_mmcsd_buffer[off + 1] == 0x00)
  { printf("check part  OK \r\n");
   
    g_mmcsdPartitionOffset = g_mmcsd_buffer[off];
   // active partition
   /* uint8_t t;
    t = g_mmcsd_buffer[off + 4];
    if (t == 0x04 || t == 0x06 || t == 0x0B)
    {
      // FAT16 or FAT32 partition
      = 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;
    }*/
  }
}

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

MMCSD_err mmcsd_init(){
   uint8_t
      i,
      r1;
     
    printf("CARD Starting... \r\n");
   g_CRC_enabled = TRUE;
   g_mmcsdBufferAddress = 0;

 
 
   output_drive(MMCSD_PIN_SCL);
   output_drive(MMCSD_PIN_SDO);
   output_drive(MMCSD_PIN_SELECT);
   output_float(MMCSD_PIN_SDI);

   mmcsd_deselect();
   delay_ms(15);
     
   /* begin initialization */
   i = 0;
   do{
      delay_ms(1);
      mmcsd_select();     
      r1=mmcsd_go_idle_state();
      mmcsd_deselect();
      i++;
      if(i == 0xFF){
         mmcsd_deselect();
           return r1;
      }
   } while(!bit_test(r1, 0));

   i = 0;
   do{
      delay_ms(1);
      mmcsd_select();
      r1=mmcsd_send_op_cond();
      mmcsd_deselect();
      i++;
      if(i == 0xFF){
         mmcsd_deselect();
         return r1;
      }
   } while(r1 & MMCSD_IDLE);

   /* figure out if we have an SD or MMC */
   mmcsd_select();
   r1=mmcsd_app_cmd();
   r1=mmcsd_sd_send_op_cond();
   mmcsd_deselect();
     printf("The card is: 0x%2X => ",r1);
   /* an mmc will return an 0x04 here */
   if(r1 == 0x04){ 
      g_card_type = MMC; printf("MMC.\r\n");}
   
   else{
      g_card_type = SD;  printf("SD.\r\n");
       //  mmcsd_print_cid();
       //  mmcsd_print_csd();
   }
   delay_ms(200);
   /* set block length to 512 bytes */
   mmcsd_select();
   r1 = mmcsd_set_blocklen(MMCSD_MAX_BLOCK_SIZE);
 
     if(r1 != MMCSD_GOODEC){
      mmcsd_deselect();
      return r1;
   }
   mmcsd_deselect();

   mmcsd_select();
   r1 = mmcsd_crc_on_off(0);
   if(r1 != MMCSD_GOODEC) {
      mmcsd_deselect();
      return r1;
   }
   mmcsd_deselect();

   r1 = mmcsd_load_buffer();
   
   g_mmcsdPartitionOffset = 0;
   //mmcsd_check_part(0x1EE);
   //mmcsd_check_part(0x1DE);
   //mmcsd_check_part(0x1CE);
   //mmcsd_check_part(0x1BE);
   //we need to calculate the offset adresss between phy. and logic. address from the offset sector at the address 0x1C6

   //  printf("find offset from physical to logical %X\r\n",g_mmcsd_buffer[0x1C6] ) ;
   //more detail at  http://www.secure-digital-card-source-code-driver.com/layout-of-a-mmc-or-sd-card-with-fat/the-boot-record
   if (g_mmcsd_buffer[0x1C6] < 80 )
      g_mmcsdBufferAddress = g_mmcsd_buffer[0x1C6]*0x200;
      // for card => 1GByte need to add more offset
   else
      g_mmcsdBufferAddress = g_mmcsd_buffer[0x1C6]*0x200 + 0x10000;

    printf("offset Adr : %lX\r\n",g_mmcsdBufferAddress ) ;

   g_mmcsdPartitionOffset=g_mmcsdBufferAddress; ;

    r1 = mmcsd_load_buffer();

   if (g_mmcsd_buffer[0] == 0xEB){
      printf("Boot sector found.\n" ) ;
   }
 
 
    return r1;
}

MMCSD_err mmcsd_read_data(uint32_t address, uint16_t size, uint8_t* ptr)
{
   MMCSD_err r1;
   uint16_t i;  // counter for loops

   for(i = 0; i < size; i++)
   {
      r1 = mmcsd_read_byte(address++, ptr++);
      if(r1 != MMCSD_GOODEC)
         return r1;
   }
   
   return MMCSD_GOODEC;
}

MMCSD_err mmcsd_read_block(uint32_t address, uint16_t size, uint8_t* ptr)
{
   MMCSD_err ec;
   uint16_t i; // counter for loops

   // send command
   mmcsd_select();
   ec = mmcsd_read_single_block(address);
   if(ec != MMCSD_GOODEC)
   {
      mmcsd_deselect();
      return ec;
   }
   
   // wait for the data start token
   ec = mmcsd_wait_for_token(DATA_START_TOKEN);
   if(ec != MMCSD_GOODEC)
   {
      mmcsd_deselect();
      return ec;
   }
   
   // read in the data
   for(i = 0; i < size; i += 1)
      ptr[i] = spi_xfer(mmcsd_spi, 0xFF);

   if(g_CRC_enabled)
   {
      /* check the crc */
      if(make16(spi_xfer(mmcsd_spi, 0xFF), spi_xfer(mmcsd_spi, 0xFF)) != mmcsd_crc16(g_mmcsd_buffer, MMCSD_MAX_BLOCK_SIZE))
      {
         mmcsd_deselect();
         return MMCSD_CRC_ERR;
      }
   }
   else
   {
      /* have the card transmit the CRC, but ignore it */
      spi_xfer(mmcsd_spi, 0xFF);
      spi_xfer(mmcsd_spi, 0xFF);
   }
   mmcsd_deselect();
//printf("print block \r\n") ;
//for(i = 0; i < 32; i += 1)

// printf("adr :%x -> %X \r\n", i, ptr[i] ) ;
// printf(" %c ", ptr[i] ) ;


   return MMCSD_GOODEC;
}

MMCSD_err mmcsd_write_data(uint32_t address, uint16_t size, uint8_t* ptr)
{
   MMCSD_err ec;
   uint16_t i;  // counter for loops
 
   for(i = 0; i < size; i++)
   {
      ec = mmcsd_write_byte(address++, *ptr++);
  //  if (*ptr++ != 0x00)
   // printf(" writ data at adr : -> %lX data -> %X  : i = %X, size = %X\r\n", address, ptr[i],i,size ) ;
   
    if(ec != MMCSD_GOODEC)
         return ec;
   }
   
   return MMCSD_GOODEC;
}

MMCSD_err mmcsd_write_block(uint32_t address, uint16_t size, uint8_t* ptr)
{
   MMCSD_err ec;
   uint16_t i;

   // send command
   mmcsd_select();
   ec = mmcsd_write_single_block(address);
   if(ec != MMCSD_GOODEC)
   {
      mmcsd_deselect();
      return ec;
   }
   
   // send a data start token
   spi_xfer(mmcsd_spi, DATA_START_TOKEN);
   
   // send all the data
   for(i = 0; i < size; i += 1)
      spi_xfer(mmcsd_spi, ptr[i]);

   // if the CRC is enabled we have to calculate it, otherwise just send an 0xFFFF
   if(g_CRC_enabled)
      spi_xfer(mmcsd_spi, mmcsd_crc16(ptr, size));
   else
   {
      spi_xfer(mmcsd_spi, 0xFF);
      spi_xfer(mmcsd_spi, 0xFF);
   }
   
   // get the error code back from the card; "data accepted" is 0bXXX00101
   ec = mmcsd_get_r1();
   if(ec & 0x0A)
   {
      mmcsd_deselect();
      return ec;
   }
   
   // wait for the line to go back high, this indicates that the write is complete
   while(spi_xfer(mmcsd_spi, 0xFF) == 0);
   mmcsd_deselect();

   return MMCSD_GOODEC;
}

MMCSD_err mmcsd_go_idle_state(void)
{
   mmcsd_send_cmd(GO_IDLE_STATE, 0);
   
   return mmcsd_get_r1();
}

MMCSD_err mmcsd_send_op_cond(void)
{
   mmcsd_send_cmd(SEND_OP_COND, 0);
   
   return mmcsd_get_r1();
}

MMCSD_err mmcsd_send_if_cond(uint8_t r7[])
{
   mmcsd_send_cmd(SEND_IF_COND, 0x45A);

   return mmcsd_get_r7(r7);
}

MMCSD_err mmcsd_print_csd()
{
   uint8_t
      buf[16],
      i,
      r1;

   // MMCs don't support this command
   if(g_card_type == MMC)
      return MMCSD_PARAM_ERR;

   mmcsd_select();   
   mmcsd_send_cmd(SEND_CSD, 0);
   r1 = mmcsd_get_r1();
   if(r1 != MMCSD_GOODEC)
   {
      mmcsd_deselect();
      return r1;
   }
   
   r1 = mmcsd_wait_for_token(DATA_START_TOKEN);
   if(r1 != MMCSD_GOODEC)
   {
      mmcsd_deselect();
      return r1;
   }

   for(i = 0; i < 16; i++)
      buf[i] = spi_xfer(mmcsd_spi, 0xFF);
   mmcsd_deselect();

   printf("\r\nCSD_STRUCTURE: %X", (buf[0] & 0x0C) >> 2);
   printf("\r\nTAAC: %X", buf[1]);
   printf("\r\nNSAC: %X", buf[2]);
   printf("\r\nTRAN_SPEED: %X", buf[3]);
   printf("\r\nCCC: %lX", (make16(buf[4], buf[5]) & 0xFFF0) >> 4);
   printf("\r\nREAD_BL_LEN: %X", buf[5] & 0x0F);   
   printf("\r\nREAD_BL_PARTIAL: %X", (buf[6] & 0x80) >> 7);
   printf("\r\nWRITE_BLK_MISALIGN: %X", (buf[6] & 0x40) >> 6);
   printf("\r\nREAD_BLK_MISALIGN: %X", (buf[6] & 0x20) >> 5);
   printf("\r\nDSR_IMP: %X", (buf[6] & 0x10) >> 4);
   printf("\r\nC_SIZE: %lX", (((buf[6] & 0x03) << 10) | (buf[7] << 2) | ((buf[8] & 0xC0) >> 6)));
   printf("\r\nVDD_R_CURR_MIN: %X", (buf[8] & 0x38) >> 3);
   printf("\r\nVDD_R_CURR_MAX: %X", buf[8] & 0x07);
   printf("\r\nVDD_W_CURR_MIN: %X", (buf[9] & 0xE0) >> 5);
   printf("\r\nVDD_W_CURR_MAX: %X", (buf[9] & 0x1C) >> 2);
   printf("\r\nC_SIZE_MULT: %X", ((buf[9] & 0x03) << 1) | ((buf[10] & 0x80) >> 7));
   printf("\r\nERASE_BLK_EN: %X", (buf[10] & 0x40) >> 6);
   printf("\r\nSECTOR_SIZE: %X", ((buf[10] & 0x3F) << 1) | ((buf[11] & 0x80) >> 7));
   printf("\r\nWP_GRP_SIZE: %X", buf[11] & 0x7F);
   printf("\r\nWP_GRP_ENABLE: %X", (buf[12] & 0x80) >> 7);
   printf("\r\nR2W_FACTOR: %X", (buf[12] & 0x1C) >> 2);
   printf("\r\nWRITE_BL_LEN: %X", ((buf[12] & 0x03) << 2) | ((buf[13] & 0xC0) >> 6));
   printf("\r\nWRITE_BL_PARTIAL: %X", (buf[13] & 0x20) >> 5);
   printf("\r\nFILE_FORMAT_GRP: %X", (buf[14] & 0x80) >> 7);
   printf("\r\nCOPY: %X", (buf[14] & 0x40) >> 6);
   printf("\r\nPERM_WRITE_PROTECT: %X", (buf[14] & 0x20) >> 5);
   printf("\r\nTMP_WRITE_PROTECT: %X", (buf[14] & 0x10) >> 4);
   printf("\r\nFILE_FORMAT: %X", (buf[14] & 0x0C) >> 2);
   printf("\r\nCRC: %X", buf[15]);

   return r1;
}

MMCSD_err mmcsd_print_cid()
{
   uint8_t
      buf[16],
      i,
      r1;

   // MMCs don't support this command
   if(g_card_type == MMC)
      return MMCSD_PARAM_ERR;
   
   mmcsd_select();
   mmcsd_send_cmd(SEND_CID, 0);
   r1 = mmcsd_get_r1();
   if(r1 != MMCSD_GOODEC)
   {
      mmcsd_deselect();
      return r1;
   }
   r1 = mmcsd_wait_for_token(DATA_START_TOKEN);
   if(r1 != MMCSD_GOODEC)
   {
      mmcsd_deselect();
      return r1;
   }
   
   for(i = 0; i < 16; i++)
      buf[i] = spi_xfer(mmcsd_spi, 0xFF);
   mmcsd_deselect();
   
   printf("\r\nManufacturer ID: %X", buf[0]);
   printf("\r\nOEM/Application ID: %c%c", buf[1], buf[2]);
   printf("\r\nOEM/Application ID: %c%c%c%c%c", buf[3], buf[4], buf[5], buf[6], buf[7]);
   printf("\r\nProduct Revision: %X", buf[8]);
   printf("\r\nSerial Number: %X%X%X%X", buf[9], buf[10], buf[11], buf[12]);
   printf("\r\nManufacturer Date Code: %X%X", buf[13] & 0x0F, buf[14]);
   printf("\r\nCRC-7 Checksum: %X", buf[15]);

   return r1;
}

MMCSD_err mmcsd_sd_status(uint8_t r2[])
{
   uint8_t i;

   mmcsd_select();
   mmcsd_send_cmd(APP_CMD, 0);
   r2[0]=mmcsd_get_r1();
   mmcsd_deselect();

   mmcsd_select();
   mmcsd_send_cmd(SD_STATUS, 0);

   for(i = 0; i < 64; i++)
      spi_xfer(mmcsd_spi, 0xFF);     

   mmcsd_deselect();

   return mmcsd_get_r2(r2);
}

MMCSD_err mmcsd_send_status(uint8_t r2[])
{
   mmcsd_send_cmd(SEND_STATUS, 0);   
   
   return mmcsd_get_r2(r2);
}

MMCSD_err mmcsd_set_blocklen(uint32_t blocklen)
{
   mmcsd_send_cmd(SET_BLOCKLEN, blocklen);
   
   return mmcsd_get_r1();
}

MMCSD_err mmcsd_read_single_block(uint32_t address)
{
   mmcsd_send_cmd(READ_SINGLE_BLOCK, address);
   
   return mmcsd_get_r1();
}

MMCSD_err mmcsd_write_single_block(uint32_t address)
{
   mmcsd_send_cmd(WRITE_BLOCK, address);
 
   return mmcsd_get_r1();
}

MMCSD_err mmcsd_sd_send_op_cond(void)
{
   mmcsd_send_cmd(SD_SEND_OP_COND, 0);
   
   return mmcsd_get_r1();
}

MMCSD_err mmcsd_app_cmd(void)
{
   mmcsd_send_cmd(APP_CMD, 0);
   
   return mmcsd_get_r1();
}

MMCSD_err mmcsd_read_ocr(int r3[])
{
   mmcsd_send_cmd(READ_OCR, 0);
   
   return mmcsd_get_r3(r3);
}

MMCSD_err mmcsd_crc_on_off(int1 crc_enabled)
{
   mmcsd_send_cmd(CRC_ON_OFF, crc_enabled);
   
   g_CRC_enabled = crc_enabled;
   
   return mmcsd_get_r1();
}

MMCSD_err mmcsd_send_cmd(uint8_t cmd, uint32_t arg)
{   
   uint8_t packet[6]; // the entire command, argument, and crc in one variable
 
   // construct the packet
   // every command on an SD card is or'ed with 0x40
   packet[0] = cmd | 0x40;
   packet[1] = make8(arg, 3);
   packet[2] = make8(arg, 2);
   packet[3] = make8(arg, 1);
   packet[4] = make8(arg, 0);

   // calculate the crc if needed
   if(g_CRC_enabled)
      packet[5] = mmcsd_crc7(packet, 5);
   else
      packet[5] = 0xFF;

   // transfer the command and argument, with an extra 0xFF hacked in there
   spi_xfer(mmcsd_spi, packet[0]);
   spi_xfer(mmcsd_spi, packet[1]);
   spi_xfer(mmcsd_spi, packet[2]);
   spi_xfer(mmcsd_spi, packet[3]);
   spi_xfer(mmcsd_spi, packet[4]);
   spi_xfer(mmcsd_spi, packet[5]);
//!   spi_write2(packet[0]);
//!   spi_write2(packet[1]);
//!   spi_write2(packet[2]);
//!   spi_write2(packet[3]);
//!   spi_write2(packet[4]);
//!   spi_write2(packet[5]);
   

   return MMCSD_GOODEC;
}

MMCSD_err mmcsd_get_r1(void)
{
   uint8_t
      response = 0,  // place to hold the response coming back from the SPI line
      timeout = 0xFF; // maximum amount loops to wait for idle before getting impatient and leaving the function with an error code
   
   // loop until timeout == 0
   while(timeout)
   {
      // read what's on the SPI line
      //  the SD/MMC requires that you leave the line high when you're waiting for data from it
      response = spi_xfer(mmcsd_spi, 0xFF);
      //response = spi_xfer(mmcsd_spi, 0x00);//leave the line idle
     
      // check to see if we got a response
      if(response != 0xFF)
      {   
         // fill in the response that we got and leave the function
         return response;
      }

      // wait for a little bit longer
      timeout--;
   }
   
   // for some reason, we didn't get a response back from the card
   //  return the proper error codes
   return RESP_TIMEOUT;
}

MMCSD_err mmcsd_get_r2(uint8_t r2[])
{
   r2[1] = mmcsd_get_r1();
   
   r2[0] = spi_xfer(mmcsd_spi, 0xFF);
   
   return 0;
}

MMCSD_err mmcsd_get_r3(uint8_t r3[])
{
   return mmcsd_get_r7(r3);
}

MMCSD_err mmcsd_get_r7(uint8_t r7[])
{
   uint8_t i;   // counter for loop
   
   // the top byte of r7 is r1
   r7[4]=mmcsd_get_r1();
   
   // fill in the other 4 bytes
   for(i = 0; i < 4; i++)
      r7[3 - i] = spi_xfer(mmcsd_spi, 0xFF);

   return r7[4];
}

MMCSD_err mmcsd_wait_for_token(uint8_t token)
{
   MMCSD_err r1;
   
   // get a token
   r1 = mmcsd_get_r1();
   
   // check to see if the token we recieved was the one that we were looking for
   if(r1 == token)
      return MMCSD_GOODEC;
   
   // if that wasn't right, return the error
   return r1;   
}

unsigned int8 mmcsd_crc7(char *data,uint8_t length)
{
   uint8_t i, ibit, c, crc;
   
   crc = 0x00;                                                                // Set initial value

   for (i = 0; i < length; i++, data++)
   {
      c = *data;

      for (ibit = 0; ibit < 8; ibit++)
      {
         crc = crc << 1;
         if ((c ^ crc) & 0x80) crc = crc ^ 0x09;                              // ^ is XOR
         c = c << 1;
      }

       crc = crc & 0x7F;
   }

   shift_left(&crc, 1, 1);                                                    // MMC card stores the result in the top 7 bits so shift them left 1
                                                                              // Should shift in a 1 not a 0 as one of the cards I have won't work otherwise
   return crc;
}

uint16_t mmcsd_crc16(char *data, uint8_t length)
{
   uint8_t i, ibit, c;

   uint16_t crc;

   crc = 0x0000;                                                                // Set initial value

   for (i = 0; i < length; i++, data++)
   {
      c = *data;

      for (ibit = 0; ibit < 8; ibit++)
      {
         crc = crc << 1;
         if ((c ^ crc) & 0x8000) crc = crc ^ 0x1021;                              // ^ is XOR
         c = c << 1;
      }

       crc = crc & 0x7FFF;
   }

   shift_left(&crc, 2, 1);                                                    // MMC card stores the result in the top 7 bits so shift them left 1
                                                                              // Should shift in a 1 not a 0 as one of the cards I have won't work otherwise
   return crc;
}

void mmcsd_select()
{
   output_low(MMCSD_PIN_SELECT);
}

void mmcsd_deselect()
{
   spi_xfer(mmcsd_spi, 0xFF);
   output_high(MMCSD_PIN_SELECT);
}

MMCSD_err mmcsd_load_buffer(void)
{
   g_MMCSDBufferChanged = FALSE;
   return(mmcsd_read_block(g_mmcsdBufferAddress, MMCSD_MAX_BLOCK_SIZE, g_mmcsd_buffer));
}

MMCSD_err mmcsd_flush_buffer(void)
{
   if (g_MMCSDBufferChanged)
   {  //printf(" flush buffer \r\n");
      g_MMCSDBufferChanged = FALSE;
      return(mmcsd_write_block(g_mmcsdBufferAddress, MMCSD_MAX_BLOCK_SIZE, g_mmcsd_buffer));
   }
   return(0);  //ok
}

MMCSD_err mmcsd_move_buffer(uint32_t new_addr)
{
   MMCSD_err ec = MMCSD_GOODEC;
   uint32_t
      //cur_block,
      new_block,address;
   //int value;
   // make sure we're still on the same block
   //cur_block = g_mmcsdBufferAddress - (g_mmcsdBufferAddress % MMCSD_MAX_BLOCK_SIZE);
  // new_block = (new_addr) % MMCSD_MAX_BLOCK_SIZE;
 // printf(" move buffer: new ad = %lX,  new_addr mod max_block --> %lX \n\r", new_addr,  new_block) ;
 
   address = new_addr-g_mmcsdPartitionOffset;
  // new_block = new_addr - (new_addr % MMCSD_MAX_BLOCK_SIZE);
   new_block = address - (address % MMCSD_MAX_BLOCK_SIZE);
 //   printf(" move buffer: new block befor offset = %lX \n\r",  new_block) ;
   
   new_block += g_mmcsdPartitionOffset;
 
//   printf(" move buffer: g_mmcsdBufferAddress = %lX \n\r",  g_mmcsdBufferAddress) ;
//  printf(" move buffer: new block = %lX \n\r",  new_block) ;
 
   
   
   //if(cur_block != new_block)
   if(g_mmcsdBufferAddress != new_block)
   {   //  printf(" move buffer: g_mmcsdBufferAddress = %lX :new block = %lX \n\r",  g_mmcsdBufferAddress, new_block ) ;
     
   
   // dump the old buffer
      if (g_MMCSDBufferChanged)
      { printf(" update data\n\r") ;
 
         ec = mmcsd_flush_buffer();
         if(ec != MMCSD_GOODEC)
            return ec;
         g_MMCSDBufferChanged = FALSE;
      }
         
      // figure out the best place for a block
      g_mmcsdBufferAddress = new_block;
 //    printf(" move buffer: new_block = %lX \n\r", g_mmcsdBufferAddress) ;
 
      // load up a new buffer
      ec = mmcsd_load_buffer();
 //printf("move_buffer:  load new buffer: \r\n");
     
// for(address= 0 ; address <=  0x20; address++)
//  {
//     printf(" %c", g_mmcsd_buffer[address]) ;
 
//  }
// printf("\r\n");
 
 }
   
   return ec;
}

MMCSD_err mmcsd_read_byte(uint32_t addr, char* data)
{
   MMCSD_err ec;
   
   ec = mmcsd_move_buffer(addr);
   if(ec != MMCSD_GOODEC)
   {
     return ec;
   }
 
   *data = g_mmcsd_buffer[addr % MMCSD_MAX_BLOCK_SIZE];

   return MMCSD_GOODEC;
}

MMCSD_err mmcsd_write_byte(uint32_t addr, char data){
   //int32 value;
   MMCSD_err ec;
 
 
  ec = mmcsd_move_buffer(addr);
   if(ec != MMCSD_GOODEC)
     return ec;
   
   g_mmcsd_buffer[addr % MMCSD_MAX_BLOCK_SIZE] = data;
 // value = addr % MMCSD_MAX_BLOCK_SIZE;
//  printf("value=%lX:x%c ",value,g_mmcsd_buffer[value]) ;
  g_MMCSDBufferChanged = TRUE;
   

   return MMCSD_GOODEC;
}

#endif
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Goto page Previous  1, 2, 3, 4, 5  Next
Page 4 of 5

 
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