Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of VS1053 by
Diff: VS1053.cpp
- Revision:
- 9:e5337a55871a
- Parent:
- 8:5ad25d480d5f
diff -r 5ad25d480d5f -r e5337a55871a VS1053.cpp
--- a/VS1053.cpp	Thu Nov 26 14:21:36 2015 +0000
+++ b/VS1053.cpp	Wed Feb 21 14:57:39 2018 +0000
@@ -1,200 +1,326 @@
-/**
- *  ==================================================== Dec 21 2013, kayeks ==
- *  VS1053.cpp
- *  ===========================================================================
- *  Just a simple library for VLSI's mp3/midi codec chip
- *       - Minimal and simple implementation (and dirty too)
- *
- *  Modified on 05 September 2015 by Vassilis Serasidis.
- *       -   Added a patch for playing MP3 files on some "LC Technology" VS1053 boards.
- *
- *
- */
-
+#include "VS1053.h"
 #include "mbed.h"
-#include "VS1053.h"
-
-/** Constructor of class VS1053. */
-VS1053::VS1053(PinName mosiPin, PinName misoPin, PinName sckPin,
-               PinName csPin, PinName bsyncPin, PinName dreqPin,
-               PinName rstPin, uint32_t spiFrequency)
-:
-    spi(mosiPin, misoPin, sckPin),
-    cs(csPin),
-    bsync(bsyncPin), //dcs pin
-    dreq(dreqPin),
-    rst(rstPin)
+ 
+// 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)
 {
-    //spi.format(8, 0);
-    //spi.frequency(spiFrequency);
-
-    // Initialize outputs
-    cs = 1;
-    bsync = 1;
-    rst = 1;
+    _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();
 }
-
-/** Destructor of class VS1053. */
-VS1053::~VS1053() {
+void VS1053::sdi_dis(void)                    //SDI disable
+{
+    dcs_high();
 }
-
-/** Make a hardware reset by hitting VS1053's RESET pin. */
-void VS1053::hardwareReset() {
-    rst = 0;
-    wait(.05);
-    rst = 1;
-    wait(.05);
+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();
 }
-
-/** Patch for some LC Technology VS1053 board with "no sound" problem. 
- *  5 September 2015 bby Vassilis Serasidis 
- */
-void VS1053::modeSwitch(void)
+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)
 {
-    //GPIO_DDR
-    writeReg(SCI_WRAMADDR, 0xc017);
-    writeReg(SCI_WRAM, 0x0003);
-  
-    wait(.05);
-    writeReg(SCI_MODE, (1<<SM_SDINEW) | (1<<SM_RESET));
-    wait(.05);
+    _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();
 }
-
-/** Send a data byte to VS1053. */
-void VS1053::sendDataByte(uint8_t data) {
-    while (!dreq);
-    bsync = 0;
-    spi.write(data);
-    bsync = 1;
+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);
 }
-
-/** Send a data block specified as a pointer to VS1053.
- *  @return Data length successfully sent.
- */
-size_t VS1053::sendDataBlock(char* data, size_t length) {
-    size_t n, sizeSent = 0;
+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
     
-    if (!data || !length) return 0;
-    while (length) {
-        n = length < 32 ? length : 32;
-        while (!dreq);
-        bsync = 0;
-        for (uint32_t i = 0; i < n; i++) {
-            spi.write(*data++);
-            sizeSent++; length--;
-        }
-        bsync = 1;
-    }
-    return sizeSent;
+    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
 }
-
-/** Change VS1053's PLL setting for speedup. */
-void VS1053::clockUp() {
-    // Set CLKI to 43.0-55.3 MHz
-    writeReg(SCI_CLOCKF, 0x8800);  // SC_MULT=4 (3.5x), SC_ADD=1 (+1.0x)
-    wait(0.01);
+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(uint8_t left, uint8_t right)
+{
 
-/** Send cancel request to VS1053.
- *  @return Zero at failure, non-zero at success.
- */
-bool VS1053::sendCancel() {
-    uint16_t reg;
-    
-    // Set SM_CANCEL bit
-    reg = readReg(SCI_MODE);
-    if (reg & 0x0008) {
-        // Abort if SM_CANCEL is still set
-        return false;
-    }
-    writeReg(SCI_MODE, reg | 0x0008);
-    return true;
-}
 
-/** Attempt a termination of playing.
- *  Please call this repeatedly during data stream tramsission until it successes.
- *  @return Zero at failure, non-zero at success.
- */
-bool VS1053::stop() {
-    uint16_t reg;
-    uint8_t  endFillByte;
-    size_t   n, length;
-    
-    // If SM_CANCEL is still set, do nothing
-    reg = readReg(SCI_MODE);
-    if (reg & 0x0008) {
-        return false;
-    }
-    
-    // Read endFillByte from XRAM <1E06h>
-    writeReg(SCI_WRAMADDR, 0x1e06);
-    reg = readReg(SCI_WRAM);
-    
-    // Send lower 8 bits of endFillByte 2,052 times
-    endFillByte = reg & 0xff;
-    length = 2052;
-    while (length) {
-        n = length < 32 ? length : 32;
-        while (!dreq);
-        bsync = 0;
-        for (uint32_t i = 0; i < n; i++) {
-            spi.write(endFillByte);
-            length--;
-        }
-        bsync = 1;
-    }
-    // Check if both HDAT0 and HDAT1 are cleared
-    return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000;
-}
+  uint16_t v;
+  v = left;
+  v <<= 8;
+  v |= right;
 
-/**
- * Set the VS1053 volume.
- *
- */
-void VS1053::setVolume(uint8_t vol)
+    while(!_DREQ);
+    
+    sci_write(0x0B, v);
+}
+ 
+void VS1053::writeStream(unsigned char *array, int size)
+{
+   for(int i=0; i<size; i++)
+   {
+       sdi_write(array[i]);
+   }
+   volume(50,50);
+}
+ 
+#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)
 {
-  uint16_t value = vol;
-  value <<= 8;
-  value |= vol;
-
-  writeReg(SCI_VOL,value); // VOL
+    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;
 }
-
-/** Write to an SCI (Serial Control Interface) register entry. */
-void VS1053::writeReg(uint8_t addr, uint16_t word) {
-    // If addr is out-of-range, do nothing
-    if (addr > 0x0f) {
-        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);
+      }
     }
-
-    while (!dreq);
-    cs = 0;
-    spi.write(0x02);         // Send a "Write SCI" instruction (02h),
-    spi.write(addr);         // target address,
-    spi.write(word >> 8);    // high byte,
-    spi.write(word & 0xff);  // then low byte
-    while (!dreq);
-    cs = 1;
+    else //copy run, copy n sample
+    {
+      while(n--)
+      {
+        val = plugin[i++];
+        sci_write(addr,val);
+      }
+    }
+  }
+ 
+  return;
 }
-
-/** Read an SCI (Serial Control Interface) register entry.
- *  @return Register value or 0000h when invalid address was specified.
- */
-uint16_t VS1053::readReg(uint8_t addr) {
-    uint16_t word;
-    
-    // If addr is out-of-range, return 0000h
-    if (addr > 0x0f) {
-        return 0x0000;
+ 
+ 
+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
     }
-
-    while (!dreq);
-    cs = 0;
-    spi.write(0x03);              // Send a "Read SCI" instruction (03h)
-    spi.write(addr);              // and target address
-    word = spi.write(0xff) << 8;  // Receive high byte with dummy data FFh
-    word |= spi.write(0xff);      // Receive low byte
-    while (!dreq);
-    cs = 1;
-    return word;
-}
+    else printf("??? Not Supported Chip???\r\n");
+    sdi_initialise(); 
+    firstTime=0; // disable message when init after 1st time
+}
\ No newline at end of file
    