Just a simple library for VLSI's mp3/midi codec chip

Dependents:   IsuProject_LPC1768

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;
+}