mbeduino MP3 Sheild player MP3 player that runs on mebeduin with MP3 Shield. Regarding mbeduino, refer to: http://mbed.org/users/okini3939/notebook/mbeduino/ Regarding MP3 Shiled, refer to: http://www.sparkfun.com/commerce/product_info.php?products_id=9736

Dependencies:   mbed SDFileSystem

VS1053.cpp

Committer:
xshige
Date:
2010-10-16
Revision:
1:c47269f0e9e1
Parent:
0:67cb2f650c15

File content as of revision 1:c47269f0e9e1:

#include "VS1053.h"
#include "mbed.h"

// patch binary
#include "VS1053b_patch.c"
// spectrum analyzer binary
#include "VS1053b_specana.c"

Serial pc(USBTX, USBRX);

/* ==================================================================
 * Constructor
 * =================================================================*/
VS1053::VS1053(
         PinName mosi, PinName miso, PinName sck, PinName cs, PinName rst,
         PinName dreq, PinName dcs, PinName vol)
    :
     _spi(mosi, miso, sck), 
     _CS(cs), 
     _RST(rst), 
     _DREQ(dreq),
     _DCS(dcs), 
     _VOL(vol) {
        firstTime=-1;    
    }    

/*===================================================================
 * Functions
 *==================================================================*/
 
void VS1053::cs_low(void)
{
    _CS = 0;                                
}
void VS1053::cs_high(void)
{
    _CS = 1;                                
}
void VS1053::dcs_low(void)
{
    _DCS = 0;
 
}
void VS1053::dcs_high(void)
{
    _DCS = 1;
}
void VS1053::sci_en(void)                    //SCI enable
{
    cs_high();
    dcs_high();
    cs_low();
}
void VS1053::sci_dis(void)                    //SCI disable
{
    cs_high();
}
void VS1053::sdi_en(void)                    //SDI enable
{
    dcs_high();
    cs_high();
    dcs_low();
}
void VS1053::sdi_dis(void)                    //SDI disable
{
    dcs_high();
}
void VS1053::reset(void)                    //hardware reset
{
//    wait(0.01);
    wait_ms(10);
    _RST = 0;
//    wait(0.01);
    wait_ms(5);
    _RST = 1;
//    wait(0.10);
    wait_ms(10);
}
void VS1053::power_down(void)                //hardware and software reset
{
    cs_low();
    reset();
//    sci_write(0x00, SM_PDOWN);
    sci_write(0x00, 0x10); // tempo
    wait(0.01);
    reset();
}
void VS1053::sci_initialise(void)
{
    _RST = 1;                                //no reset
    _spi.format(8,0);                        //spi 8bit interface, steady state low
 //   _spi.frequency(1000000);                //rising edge data record, freq. 1Mhz
    _spi.frequency(2000000);                //rising edge data record, freq. 2Mhz

    
    cs_low();
    for(int i=0; i<4; i++)
    {
    _spi.write(0xFF);                        //clock the chip a bit
    }
    cs_high();
    dcs_high();
    wait_us(5);
}
void VS1053::sdi_initialise(void)
{
    _spi.format(8,0);
//    _spi.frequency(7000000);                //set to 7MHz
//    _spi.frequency(12000000);                //set to 12MHz to make fast transfer
    _spi.frequency(18000000);                //set to 18MHz to make fast transfer
//NG does not work//    _spi.frequency(24000000);                //set to 24MHz to make fast transfer
    
    cs_high();
    dcs_high();
}
void VS1053::sci_write(unsigned char address, unsigned short int data)
{
    sci_en();                                //enables SCI/disables SDI
    
    while(!_DREQ);                            //wait unitl data request is high
    _spi.write(0x02);                        //SCI write
    _spi.write(address);                    //register address
    _spi.write((data >> 8) & 0xFF);            //write out first half of data word
    _spi.write(data & 0xFF);                //write out second half of data word
    
    sci_dis();                                //enables SDI/disables SCI
    wait_us(5);
}
void VS1053::sdi_write(unsigned char datum)
{
    sdi_en();
    
    while(!_DREQ);
    _spi.write(datum);
    
//?    sci_dis();
      sdi_dis();
}
unsigned short int VS1053::sci_read(unsigned short int address)
{
    cs_low();                                //enables SCI/disables SDI
    
    while(!_DREQ);                            //wait unitl data request is high
    _spi.write(0x03);                        //SCI write
    _spi.write(address);                    //register address
    unsigned short int received = _spi.write(0x00);    //write out dummy byte
    received <<= 8;
    received += _spi.write(0x00);            //write out dummy byte
    
    cs_high();                                //enables SDI/disables SCI
    
    return received;                        //return received word
}
void VS1053::sine_test_activate(unsigned char wave)
{
    cs_high();                                //enables SDI/disables SCI
    
    while(!_DREQ);                            //wait unitl data request is high
    _spi.write(0x53);                        //SDI write
    _spi.write(0xEF);                        //SDI write
    _spi.write(0x6E);                        //SDI write
    _spi.write(wave);                        //SDI write
    _spi.write(0x00);                        //filler byte
    _spi.write(0x00);                        //filler byte
    _spi.write(0x00);                        //filler byte
    _spi.write(0x00);                        //filler byte

    cs_low();                                //enables SCI/disables SDI
}
void VS1053::sine_test_deactivate(void)
{
    cs_high();
    
    while(!_DREQ);
    _spi.write(0x45);                        //SDI write
    _spi.write(0x78);                        //SDI write
    _spi.write(0x69);                        //SDI write
    _spi.write(0x74);                        //SDI write
    _spi.write(0x00);                        //filler byte
    _spi.write(0x00);                        //filler byte
    _spi.write(0x00);                        //filler byte
    _spi.write(0x00);                        //filler byte
}
void VS1053::volume(void)
{
 #ifdef FIXED_VOL
    unsigned char volumize = (0 * 255); // FIXED VOL (not support volume input)
 #else
    unsigned char volumize = (_VOL * 255);
 #endif
    while(!_DREQ);
    
    unsigned short int attenuation = ((256 * volumize) + volumize);
    sci_write(0x0B, attenuation);
}

void VS1053::writeStream(unsigned char *array, int size)
{
   for(int i=0; i<size; i++)
   {
       sdi_write(array[i]);
   }
   volume();
}

#if 0
// this function does not work
// because of function call overhead
void VS1053::putcStream(unsigned char datum)
{
    sdi_write(datum);
}
#endif

unsigned short int VS1053::wram_read(unsigned short int address)
{
    unsigned short int tmp1,tmp2;
    sci_write(SCI_WRAMADDR,address);
    tmp1=sci_read(SCI_WRAM);
    sci_write(SCI_WRAMADDR,address);
    tmp2=sci_read(SCI_WRAM);
    if (tmp1==tmp2) return tmp1;
    sci_write(SCI_WRAMADDR,address);
    tmp1=sci_read(SCI_WRAM);
    if (tmp1==tmp2) return tmp1;
    sci_write(SCI_WRAMADDR,address);    
    tmp1=sci_read(SCI_WRAM);
    if (tmp1==tmp2) return tmp1;
    return tmp1;    
}

void VS1053::wram_write(unsigned short int address, unsigned short int data)
{
    sci_write(SCI_WRAMADDR,address);
    sci_write(SCI_WRAM,data);
    return;
}


void VS1053::terminateStream(void)
{
#if 1
    unsigned int endFillByte=wram_read(para_endFillByte);
//    printf("endFillByte:%04X\r\n",endFillByte); // debug
    for(int n=0; n<2052; n++) sdi_write(0xFF&endFillByte);
    sci_write(SCI_MODE,(SM_SDINEW+SM_CANCEL));
    for(int n=0; n<2048; n++) sdi_write(0xFF&endFillByte);
    // don't reset if you don't want to lose the patch 
    //    sci_write(SCI_MODE,(SM_SDINEW+SM_RESET)); //  set mode reg.
    //    wait_ms(10); 
#endif 
}

void VS1053::write_plugin(const unsigned short *plugin, unsigned int len)
{
  unsigned int i;
  unsigned short addr, n, val;

  for(i=0; i<len;)
  {
    addr = plugin[i++];
    n    = plugin[i++];
    if(n & 0x8000U) //RLE run, replicate n samples
    {
      n  &= 0x7FFF;
      val = plugin[i++];
      while(n--) 
      {
        sci_write(addr,val);
      }
    }
    else //copy run, copy n sample
    {
      while(n--)
      {
        val = plugin[i++];
        sci_write(addr,val);
      }
    }
  }

  return;
}


void VS1053::initialize(void)
{
    _RST = 1;
    cs_high();                           //chip disabled
    sci_initialise();                    //initialise MBED
    sci_write(SCI_MODE,(SM_SDINEW+SM_RESET)); //  set mode reg.
    wait_ms(10); 
#if 1
       // debug
        unsigned int chipID_0=wram_read(para_chipID_0);
        if (firstTime) printf("chipID_0:%04X\r\n",chipID_0); // debug
        unsigned int chipID_1=wram_read(para_chipID_1);
        if (firstTime) printf("chipID_1:%04X\r\n",chipID_1); // debug      
        unsigned int struct_version=wram_read(para_version);
        if (firstTime) printf("structure version:%04X\r\n",struct_version); // debug      
 #endif
    //get chip version, set clock multiplier and load patch
    int i = (sci_read(SCI_STATUS)&0xF0)>>4;
    if(i == 4) 
    {
        if (firstTime) printf("Installed Chip is: VS1053\r\n");
        sci_write(SCI_CLOCKF, (SC_MULT_XTALIx50+SC_ADD_20x)); 
#ifdef VS_PATCH
        // loading patch
        write_plugin(vs1053b_patch, sizeof(vs1053b_patch)/2);
        if (firstTime) {
            printf("VS1053b patch loaded.\r\n");
            printf("patch size:%d bytes\r\n",sizeof(vs1053b_patch));
        }
#endif
#ifdef VS_SPECANA
        // loading plugin(spectrum analyzer)
        write_plugin(vs1053b_specana, sizeof(vs1053b_specana)/2);
        if (firstTime) printf("VS1053b specana loaded.\r\n");
#endif
    }
    else printf("??? Not Supported Chip???\r\n");
    sdi_initialise(); 
    firstTime=0; // disable message when init after 1st time
}