ButterflyMP3

mmc.c

Go to the documentation of this file.
00001 
00046 #include <avr/io.h>
00047 #include <avr/pgmspace.h>
00048 #include <avr/interrupt.h>
00049 
00050 #define MMC_C
00051 #include "types.h"
00052 #include "mmc.h"
00053 #include "delay.h"
00054 #include "main.h"
00055 #include "uart.h"
00056 #include "vs1001.h" 
00057 
00058 uint8 mmc_sbuf[512];    
00059 uint8 mmc_scratch[32];  
00060 
00061 
00065 void SpiInit(void)
00066 {
00067         uint8 dummy;
00068         
00069         SBI(SPI_DDR, SPI_SS);           // SS must be output for Master mode to work
00070         SBI(SPI_DDR, SPI_MOSI);         // set MOSI a output
00071         SBI(SPI_DDR, SPI_SCK);          // set SCK as output
00072         CBI(SPI_DDR, SPI_MISO);         // MISO is input
00073         //CBI(SPI_PORT, SPI_SCK);               // set SCK low
00074         
00075         SBI(MMC_PORT,MMC_CS);
00076         SBI(MMC_DDR,MMC_CS);
00077         
00078         // hold dataflash in reset so it doesn't interfere with 
00079         // MMC or VS1001.
00080         DDRF |= (1<<PE7);       // PE7 is output.
00081         PORTF &= ~(1<<PE7); // hold PE7 low
00082         
00083         /* enable SPI as master, set clk divider fosc/4 */
00084         // Although the MMC card is capable of clock speeds up to 20Mhz
00085         // We are limited to 2Mhz for the VS1001k until we set the clock doubler 
00086         // after which we are limited to 4Mhz by the butterfly.
00087         /* later we will enable 2X mode once vS1001 has been initialized.*/
00088         SPCR = (0<<SPIE)|(1<<SPE)|(0<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)|(0<<SPR1)|(0<<SPR0);     
00089         SPSR = (0<<SPI2X);
00090         dummy = SPSR;   // clear status
00091         dummy = SPDR;
00092 }
00093 
00094 
00105 uint8 SpiByte(unsigned char byte)
00106 {
00107         uint8 i,dummy;
00108 
00109         SPDR = byte;                            // put byte to send in SPDR, which initiates xmit  
00110         
00111         loop_until_bit_is_set(SPSR, SPIF);      //wait for completion 
00112         
00113         //delay(5); //wait 5 microseconds after sending data to control port
00114         for (i=0;i<8;i++) // 2 + 5i clock cycles -> 42 clocks at 8 Mhz -> 5.25uS
00115                 asm volatile("nop");
00116                 
00117         i = SPSR;       // clear status
00118         dummy = SPDR;
00119         return dummy;                   // return with byte shifted in from slave
00120         
00121 }
00122 
00123 
00130 uint8 MMCGet(void)
00131 {
00132         uint8 i,Byte;
00133         
00134         for (i=0;i<8;i++){                      
00135            Byte = SpiByte(0xff);
00136            if (Byte != 0xff) return Byte;
00137         }
00138         
00139         return Byte;
00140 }
00141 
00155 void MMCCommand(unsigned char command, uint8 px, uint8 py, uint8 pz)
00156 {
00157         CBI(MMC_PORT,MMC_CS);   // Select card
00158 //      CBI( BSYNC_PORT,   BSYNC_PIN );         // byte sync lo
00159 
00160         SpiByte(0xff);
00161         SpiByte(command | 0x40);
00162         SpiByte(px);
00163         SpiByte(py);
00164         SpiByte(pz);
00165         SpiByte(0x00);
00166         SpiByte(0x95);            
00167         /* 
00168         correct CRC for first command in SPI          
00169         after that CRC is ignored, so no problem with 
00170         always sending 0x95
00171     */
00172         /*
00173          the reason I did not re set the MMC_CS line was because I didn't want to 
00174          de-assert the line after the command while waiting for a response.  
00175          The card is selected here as a backup to make sure it is selected. 
00176          I might go through and remove places where it is redundant when 
00177          i get a chance.  
00178                 
00179          <<!! the following behaviour has been removed as redundent
00180                 I may add it back in a new mode compatable form if needed.
00181          
00182         The BSYNC line is held low to ensure that the spi data is sent as a command 
00183          to the MMC and not as data to teh vs1001 as I have combinned both the 
00184          interfaces on the vs1001 to save pins. 
00185          
00186          !!>>
00187                 
00188         Any data on the spi lines is read as data by the vs1001 when the
00189          BSYNC line is high.
00190         */
00191 }
00192 
00193 
00200 uint8 MMC_Reset(void)                   
00201 {
00202         unsigned char Byte;
00203         unsigned int i;
00204 
00205         SBI(MMC_PORT,MMC_CS);
00206         //CBI( BSYNC_PORT,   BSYNC_PIN );       // byte sync lo
00207         
00208         /* start off with 80 bits of high data with card deselected */
00209         for(i=0;i<10;i++)
00210                 Byte = SpiByte(0xff);
00211                 
00212         /* now send CMD0 - go to idle state, try up to 100 times */
00213         MMCCommand(0,0,0,0);  /* software reset command */
00214 
00215         if (MMCGet() != 1)
00216           {
00217                   SBI(MMC_PORT ,MMC_CS);
00218                   SpiByte(0xff);
00219                   return -1;  // MMC Not detected
00220           }
00221         
00222          
00223         /* send CMD1 until we get a 0 back, indicating card is done initializing */
00224         i =0xffff;    /* but only do it up to 1000 times */
00225         Byte = 1;
00226         
00227         while (Byte && i--){
00228            MMCCommand(1,0,0,0);
00229            Byte = MMCGet();
00230            }
00231         
00232         SBI(MMC_PORT,MMC_CS);
00233         SpiByte(0xff); // Clear SPI
00234         
00235         if (Byte){
00236           return -2;  // Init Fail
00237           }
00238           
00239 
00240         return 0;
00241 }
00242 
00251 uint8 MMC_Detect(void)
00252 {
00253         uint8 i;
00254         #if (REV >='B') // MMC detect only available on rev_b boards.
00255         MMC_DDR &= ~(1<<MMC_CS); // set as input
00256         MMC_PORT &= ~(1<<MMC_CS); // disable pullup
00257         
00258         //wait 18 microseconds after sending data to control port
00259         for (i=0;i<29;i++) // 2 + 5i clock cycles -> 147 clocks at 8 Mhz -> 18.375uS
00260                 asm volatile("nop");
00261                 
00262         if((MMC_PIN & (1<<MMC_CS)) == 0)        
00263         {
00264                 MMC_PORT |= (1<<MMC_CS); 
00265                 MMC_DDR |= (1<<MMC_CS);
00266                 return FALSE;
00267         }
00268         MMC_PORT |= (1<<MMC_CS); 
00269         MMC_DDR |= (1<<MMC_CS); 
00270         #endif
00271         return TRUE;
00272 }
00273 
00274 
00281 uint16 MMC_Check(void)
00282 {
00283         uint16 word;
00284 
00285         MMCCommand(MMC_SEND_STATUS,0,0,0); // check card ststus
00286         word = MMCGet();
00287         word = (word<<8) + SpiByte(0xff); // NOTE spibyte and not MMCGET!!!
00288         
00289         SBI(MMC_PORT,MMC_CS); // Deselect card
00290         SpiByte(0xff); // Clear SPI
00291         
00292         return word;
00293 }
00294 
00303 /*
00304 uint8 MMC_Identify(void)
00305 {
00306         uint8 byte,data,i;
00307         
00308 
00309         MMCCommand(MMC_SEND_CID,0,0,0); // send cmd
00310         byte = MMCGet(); // check reponse
00311         
00312         if (byte==0){ // get the CID...
00313                 for (i=0;i<32;i++){
00314                         data = SpiByte(0xff); 
00315                         mmc_scratch[i]=data;
00316                 }
00317         }
00318 
00319         SBI(MMC_PORT,MMC_CS); // Deselect card
00320         SpiByte(0xff); // Clear SPI
00321         
00322         return byte;
00323 }
00324 */
00325 
00332 /*
00333 uint8 MMC_CardType(void)
00334 {
00335         uint8 byte,data,i;
00336         
00337         MMCCommand(MMC_SEND_CSD,0,0,0); // send cmd
00338         byte = MMCGet(); // check reponse
00339         
00340         if (byte==0){ // get the CID...
00341                 for (i=0;i<32;i++){
00342                         data = SpiByte(0xff); 
00343                         mmc_scratch[i]=data;
00344                 }
00345         }
00346 
00347         SBI(MMC_PORT,MMC_CS); // Deselect card
00348         SpiByte(0xff); // Clear SPI
00349         
00350         return byte;
00351 }
00352 */
00358 //
00359 //uint32 MMC_Capacity(void)
00360 //{
00361 //      uint8 byte,data,multi,blk_len;
00362 //      uint32 c_size;
00363 //      uint32 capacity;
00364 //      byte = MMC_CardType();
00365 //      if (byte==0) {// got info okay
00366 //              blk_len = 0x0F & mmc_scratch[6]; // this should equal 9 -> 512 bytes
00367 //              /*      ; get size into reg 
00368 //                      ;         7                             8                       9
00369 //                      ; xxxx xxxx    xxxx xxxx    xxxx xxxx
00370 //                      ;        ^^    ^^^^ ^^^^    ^^ 
00371 //              */
00372 //              data =(mmc_scratch[7] & 0x03)<<6;
00373 //              data |= (mmc_scratch[8] >> 2);
00374 //              c_size = data << 4;
00375 //              data =(mmc_scratch[8] << 2 ) | ((mmc_scratch[9] & 0xC0)>>6 );
00376 //              c_size |= data;
00377 //              
00378 //              /*      ; get multiplier
00379 //                      ;       10                      11
00380 //                      ; xxxx xxxx    xxxx xxxx
00381 //                      ;        ^^    ^
00382 //              */
00383 //              multi = ((mmc_scratch[10] & 0x03 ) << 1 ) ;
00384 //              multi |= ((mmc_scratch[11] & 0x80) >> 7);
00385 //              // sectors = (size+1)<<(multiplier+2)
00386 //              capacity = (c_size + 1)<<(multi + blk_len + 2);
00387 //
00388 //              return capacity;
00389 //      }
00390 //      return 0xFFFFFFFF;
00391 //}
00392 //
00393 
00399 //uint8 MMC_Name(void)
00400 //{
00401 //      uint8 byte,i;
00402 //      
00403 //      byte = MMC_Identify(); // Grab CID into mmc_scratch 
00404 //
00405 //      if (byte==0){
00406 //              for (i=0;i<6;i++)
00407 //                      mmc_scratch[i]=mmc_scratch[i+4];
00408 //              mmc_scratch[6]=0;
00409 //      }
00410 //      
00411 //      return byte;
00412 //}
00413     
00414         
00415 /***************************************************************************
00416 *       MMC_Read        
00417 *       Read one sector from the memory card into mmc_sbuf[]
00418 *       Note this assumes block length of 512 Bytes
00419 *       @Param          <lba> the number of the sector to read
00420 *       @Return         Status from the read call.
00421 ***************************************************************************/
00422 uint8 MMC_Read(uint32 lba)
00423 {
00424         uint8 byte,data,px,py,pz;
00425         uint16 sec,i;
00426         uint16 word;
00427 #ifdef USE_MMC_CACHE
00428         static uint32 last_read_lba=0xffffffff; // remember last sector for caching purposes
00429 
00430         if (last_read_lba == lba){ // exit ASSUMING BUFFER HAS NOT BEEN ALTERED
00431                 return 0x00; // OK
00432         }
00433 #endif
00434         
00435         SpiByte(0xff);
00436         CBI(MMC_PORT,MMC_CS);   // Select card
00437         MMCCommand(MMC_SEND_STATUS,0,0,0); // check card status
00438         word = MMCGet();
00439         word = (word<<8) + SpiByte(0xff);
00440         
00441         
00442         lba <<=9; // * 512
00443         pz = (lba>>8 & 0xff);
00444         py =( lba>>16 & 0xff);
00445         px =( lba>>24 & 0xff);
00446         
00447         SpiByte(0xff);
00448         CBI(MMC_PORT,MMC_CS);   // Select card
00449         MMCCommand(MMC_READ_SINGLE_BLOCK, px , py, pz);
00450         byte = MMCGet(); // check reponse
00451         
00452         //TODO:  if i get a byte == 0x05 should I resend?
00453         
00454         if (byte==0){ // then everything okay
00455                 i=500; // wait up to 255 bytes for response
00456                 data = SpiByte(0xff);
00457                 
00458                 while ((data != MMC_STARTBLOCK_READ) && (i--)){
00459                         data = SpiByte(0xff);
00460                 }
00461                 
00462                 if (i!=0){ // read okay. start grabbing the data
00463                         for(sec=0;sec<512;sec++)
00464                                 mmc_sbuf[sec] = SpiByte(0xff);
00465                         SpiByte(0xff); // flush MMC CRC 
00466                         SpiByte(0xff); // 
00467                         SpiByte(0xff); //Clear SPI
00468                         SpiByte(0xff); //
00469                 }else{
00470                         byte = 0xff;// signal MMC Coms error
00471                 }
00472         //}else{
00473         //      PRINT("MMC_READ_SINGLE_BLOCK\t");
00474         //      PRINT("\t");UART_Printfu32(lba<<9);
00475         //      PRINT("\t");UART_Printfu16(word);
00476         //      PRINT("\t");UART_Printfu08(byte);
00477         //      PRINT("\t");UART_Printfu08(SpiByte(0xff));
00478         //      EOL();
00479                 
00480         }
00481 
00482         SBI(MMC_PORT,MMC_CS); // Deselect card
00483         SpiByte(0xff); // Clear SPI
00484 
00485 #ifdef USE_MMC_CACHE
00486         if (byte == 0){
00487                         last_read_lba = lba;// save for next time.
00488         }
00489 #endif
00490         return byte;
00491 }
00492 
00493  /*************************************************************************
00494  *      uint8 MMCWriteSector(uint32lba)
00495  *
00496  * - writes a sector to the card (512 bytes)
00497  * - takes sector # as param
00498  * - data is in mmc_sbuf[] 
00499  * - returns success/failure status of operation.
00500  **************************************************************************/
00501  // ****** UNTESTED ******
00502 //uint8 MMC_Write(uint32 lba)
00503 //{
00504 //      unsigned char px,py,pz;
00505 //      unsigned int i;
00506 //      lba <<=1;
00507 //      pz = (lba & 0xff);
00508 //      lba >>= 8;
00509 //      py =( lba & 0xff);
00510 //      lba >>= 8;
00511 //      px =( lba & 0xff);
00512 //      
00513 //      CBI(MMC_PORT,MMC_CS);   // Select card
00515 //      if (MMCGet() == 0xff) return 0xff;
00516 //      
00517 //      SpiByte(0xfe);  // Send Start Byte
00518 //      
00519 //      for (i=0;i<512;i++)       // read the sector 
00520 //         {
00521 //              SpiByte(mmc_sbuf[i]);
00522 //         }
00523 //      SpiByte(0xff);          // checksum -> don't care about it for now 
00524 //      SpiByte(0xff);       // checksum -> don't care about it for now 
00525 //      SpiByte(0xff);       // Read "data response byte"                 
00526 //      
00527 //      if (MMCGet() == 0xff) return 0xff;
00528 //      
00529 //      SBI(MMC_PORT,MMC_CS); // Deselect card
00530 //      SpiByte(0xff); // Clear SPI
00531 //      
00532 //      return 0;
00533 //}
00534 
00535 //void MMC_Flush(void)
00536 //{
00537 //      uint8 i;
00538 //      SBI(MMC_PORT,MMC_CS);
00539 //      /* start off with 80 bits of high data with card deselected */
00540 //      for(i=0;i<10;i++)
00541 //              SpiByte(0xff);
00542 //      //CBI(MMC_PORT,MMC_CS);        /* select card */
00543 //}
00544 
00545 
00546 /***************************************************************************
00547 *   Name:                       MMC_WriteProtect
00548 *       Description:    Set or clear the MMC Writeprotect
00549 *       Parameters:             <set> determines weather to set or clear the write protection
00550 *       Returns:                error code.
00551 ***************************************************************************/
00552 //uint8 MMC_WriteProtect(uint8 set){
00553 //      uint8 byte;
00554 //      
00555 //      if (set){
00556 //              MMCCommand(MMC_SET_WRITE_PROT,0,0,0); // send cmd
00557 //      }else{
00558 //              MMCCommand(MMC_CLR_WRITE_PROT,0,0,0); // send cmd
00559 //      }
00560 //      byte = MMCGet(); // check reponse
00561 //
00562 //      SBI(MMC_PORT,MMC_CS); // Deselect card
00563 //      SpiByte(0xff); // Clear SPI
00564 //      
00565 //      return byte;
00566 //}
 All Files Functions Variables Typedefs Enumerations Enumerator Defines