A simple library for decoding MP3 files with the VS1053 CoDec chip. The initial library was written by Kaoru Onoe. The library is patched to work with some "LC Technology" VS1053 board that have some IC pins disconnected. Because of that problem, there was no sound out of that boards. Now, these board work ok !

Dependents:   W7500_and_VS1053_MP3_decoder VS1053_MP3_decoder_WIZwiki-W7500 VS1053Player Scat

Fork of VS1053 by Kaoru Onoe

Revision:
0:708868399033
Child:
1:00c19f771676
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VS1053.cpp	Fri Nov 08 10:41:54 2013 +0000
@@ -0,0 +1,154 @@
+// ==================================================== Nov 04 2013, kayeks ==
+// VS1053.cpp
+// ===========================================================================
+// Just a simple library for VLSI's mp3/midi codec chip
+//   - Minimal and simple implementation (and dirty too)
+
+#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),
+    dreq(dreqPin),
+    rst(rstPin)
+{
+    spi.format(8, 0);
+    spi.frequency(spiFrequency);
+
+    // Initialize outputs
+    cs = 1;
+    bsync = 1;
+    rst = 1;
+}
+
+/** Destructor of class VS1053 */
+VS1053::~VS1053() {
+}
+
+/** Do a hardware reset by hitting VS1053's RESET pin */
+void VS1053::hardwareReset() {
+    rst = 0;
+    wait(.05);
+    rst = 1;
+    wait(.05);
+}
+
+/** Send a byte to VS1053 */
+void VS1053::sendDataByte(uint8_t b) {
+    while (!dreq);
+    bsync = 0;
+    spi.write(b);
+    bsync = 1;
+}
+
+/** Send a data block specified as a pointer to VS1053 */
+size_t VS1053::sendDataBlock(uint8_t* p, size_t length) {
+    size_t sizeSent = 0;
+    
+    if (!p || !length) return 0;
+    while (length) {
+        while (!dreq);
+        cs = 0;
+        for (uint8_t i = 0; i < 32 && length--; i++) {
+            spi.write(*p++);
+            sizeSent++;
+        }
+        cs = 1;
+    }
+    return sizeSent;
+}
+
+/** 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)
+}
+
+/** Send cancel request to VS1053 */
+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 0;
+    }
+    writeReg(SCI_MODE, reg | 0x0008);
+    return 1;
+}
+
+/** Stop playing (CALL AFTER sendCancel SUCCESSES) */
+bool VS1053::stop() {
+    uint16_t reg;
+    uint8_t endFillByte;
+    size_t length;
+    
+    // If SM_CANCEL is still set, do nothing
+    reg = readReg(SCI_MODE);
+    if (reg & 0x0008) {
+        return 0;
+    }
+    
+    // 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) {
+        while (!dreq);
+        cs = 0;
+        for (uint8_t i = 0; i < 32 && length--; i++) {
+            spi.write(endFillByte);
+        }
+        cs = 1;
+    }
+    
+    // Check if both HDAT0 and HDAT1 are cleared
+    return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000;
+}
+
+/** 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;
+    }
+
+    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;
+}
+
+/** Read an SCI (Serial Control Interface) register entry */
+uint16_t VS1053::readReg(uint8_t addr) {
+    uint16_t word;
+    
+    // If addr is out-of-range, return a beef
+    if (addr > 0x0f) {
+        return 0xbeef;
+    }
+
+    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;
+}