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

Committer:
kayekss
Date:
Sat Nov 09 10:23:04 2013 +0000
Revision:
2:47ba7e2259cd
Parent:
1:00c19f771676
Child:
3:696c8e6744b2
Added API documentation

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kayekss 2:47ba7e2259cd 1 // ==================================================== Nov 09 2013, kayeks ==
kayekss 0:708868399033 2 // VS1053.cpp
kayekss 0:708868399033 3 // ===========================================================================
kayekss 0:708868399033 4 // Just a simple library for VLSI's mp3/midi codec chip
kayekss 0:708868399033 5 // - Minimal and simple implementation (and dirty too)
kayekss 0:708868399033 6
kayekss 0:708868399033 7 #include "mbed.h"
kayekss 0:708868399033 8 #include "VS1053.h"
kayekss 0:708868399033 9
kayekss 2:47ba7e2259cd 10 /** Constructor of class VS1053. */
kayekss 0:708868399033 11 VS1053::VS1053(PinName mosiPin, PinName misoPin, PinName sckPin,
kayekss 0:708868399033 12 PinName csPin, PinName bsyncPin, PinName dreqPin,
kayekss 0:708868399033 13 PinName rstPin, uint32_t spiFrequency)
kayekss 0:708868399033 14 :
kayekss 0:708868399033 15 spi(mosiPin, misoPin, sckPin),
kayekss 0:708868399033 16 cs(csPin),
kayekss 0:708868399033 17 bsync(bsyncPin),
kayekss 0:708868399033 18 dreq(dreqPin),
kayekss 0:708868399033 19 rst(rstPin)
kayekss 0:708868399033 20 {
kayekss 0:708868399033 21 spi.format(8, 0);
kayekss 0:708868399033 22 spi.frequency(spiFrequency);
kayekss 0:708868399033 23
kayekss 0:708868399033 24 // Initialize outputs
kayekss 0:708868399033 25 cs = 1;
kayekss 0:708868399033 26 bsync = 1;
kayekss 0:708868399033 27 rst = 1;
kayekss 0:708868399033 28 }
kayekss 0:708868399033 29
kayekss 2:47ba7e2259cd 30 /** Destructor of class VS1053. */
kayekss 0:708868399033 31 VS1053::~VS1053() {
kayekss 0:708868399033 32 }
kayekss 0:708868399033 33
kayekss 2:47ba7e2259cd 34 /** Make a hardware reset by hitting VS1053's RESET pin. */
kayekss 0:708868399033 35 void VS1053::hardwareReset() {
kayekss 0:708868399033 36 rst = 0;
kayekss 0:708868399033 37 wait(.05);
kayekss 0:708868399033 38 rst = 1;
kayekss 0:708868399033 39 wait(.05);
kayekss 0:708868399033 40 }
kayekss 0:708868399033 41
kayekss 2:47ba7e2259cd 42 /** Send a data byte to VS1053. */
kayekss 2:47ba7e2259cd 43 void VS1053::sendDataByte(uint8_t data) {
kayekss 0:708868399033 44 while (!dreq);
kayekss 0:708868399033 45 bsync = 0;
kayekss 2:47ba7e2259cd 46 spi.write(data);
kayekss 0:708868399033 47 bsync = 1;
kayekss 0:708868399033 48 }
kayekss 0:708868399033 49
kayekss 2:47ba7e2259cd 50 /** Send a data block specified as a pointer to VS1053.
kayekss 2:47ba7e2259cd 51 * @return Data length successfully sent.
kayekss 2:47ba7e2259cd 52 */
kayekss 2:47ba7e2259cd 53 size_t VS1053::sendDataBlock(uint8_t* pData, size_t length) {
kayekss 0:708868399033 54 size_t sizeSent = 0;
kayekss 0:708868399033 55
kayekss 2:47ba7e2259cd 56 if (!pData || !length) return 0;
kayekss 0:708868399033 57 while (length) {
kayekss 0:708868399033 58 while (!dreq);
kayekss 1:00c19f771676 59 bsync = 0;
kayekss 0:708868399033 60 for (uint8_t i = 0; i < 32 && length--; i++) {
kayekss 2:47ba7e2259cd 61 spi.write(*pData++);
kayekss 0:708868399033 62 sizeSent++;
kayekss 0:708868399033 63 }
kayekss 1:00c19f771676 64 bsync = 1;
kayekss 0:708868399033 65 }
kayekss 0:708868399033 66 return sizeSent;
kayekss 0:708868399033 67 }
kayekss 0:708868399033 68
kayekss 2:47ba7e2259cd 69 /** Change VS1053's PLL setting for speedup. */
kayekss 0:708868399033 70 void VS1053::clockUp() {
kayekss 0:708868399033 71 // Set CLKI to 43.0-55.3 MHz
kayekss 0:708868399033 72 writeReg(SCI_CLOCKF, 0x8800); // SC_MULT=4 (3.5x), SC_ADD=1 (+1.0x)
kayekss 0:708868399033 73 }
kayekss 0:708868399033 74
kayekss 2:47ba7e2259cd 75 /** Send cancel request to VS1053.
kayekss 2:47ba7e2259cd 76 * @return 0 at failure, 1 at success.
kayekss 2:47ba7e2259cd 77 */
kayekss 0:708868399033 78 bool VS1053::sendCancel() {
kayekss 0:708868399033 79 uint16_t reg;
kayekss 0:708868399033 80
kayekss 0:708868399033 81 // Set SM_CANCEL bit
kayekss 0:708868399033 82 reg = readReg(SCI_MODE);
kayekss 0:708868399033 83 if (reg & 0x0008) {
kayekss 0:708868399033 84 // Abort if SM_CANCEL is still set
kayekss 0:708868399033 85 return 0;
kayekss 0:708868399033 86 }
kayekss 0:708868399033 87 writeReg(SCI_MODE, reg | 0x0008);
kayekss 0:708868399033 88 return 1;
kayekss 0:708868399033 89 }
kayekss 0:708868399033 90
kayekss 2:47ba7e2259cd 91 /** Attempts a termination of play.
kayekss 2:47ba7e2259cd 92 * Call this repeatedly during data stream tramsission until it successes.
kayekss 2:47ba7e2259cd 93 * @return 0 at failure, 1 at success.
kayekss 2:47ba7e2259cd 94 */
kayekss 0:708868399033 95 bool VS1053::stop() {
kayekss 0:708868399033 96 uint16_t reg;
kayekss 0:708868399033 97 uint8_t endFillByte;
kayekss 0:708868399033 98 size_t length;
kayekss 0:708868399033 99
kayekss 0:708868399033 100 // If SM_CANCEL is still set, do nothing
kayekss 0:708868399033 101 reg = readReg(SCI_MODE);
kayekss 0:708868399033 102 if (reg & 0x0008) {
kayekss 0:708868399033 103 return 0;
kayekss 0:708868399033 104 }
kayekss 0:708868399033 105
kayekss 0:708868399033 106 // Read endFillByte from XRAM <1E06h>
kayekss 0:708868399033 107 writeReg(SCI_WRAMADDR, 0x1e06);
kayekss 0:708868399033 108 reg = readReg(SCI_WRAM);
kayekss 0:708868399033 109
kayekss 0:708868399033 110 // Send lower 8 bits of endFillByte 2,052 times
kayekss 0:708868399033 111 endFillByte = reg & 0xff;
kayekss 0:708868399033 112 length = 2052;
kayekss 0:708868399033 113 while (length) {
kayekss 0:708868399033 114 while (!dreq);
kayekss 1:00c19f771676 115 bsync = 0;
kayekss 0:708868399033 116 for (uint8_t i = 0; i < 32 && length--; i++) {
kayekss 0:708868399033 117 spi.write(endFillByte);
kayekss 0:708868399033 118 }
kayekss 1:00c19f771676 119 bsync = 1;
kayekss 0:708868399033 120 }
kayekss 0:708868399033 121
kayekss 0:708868399033 122 // Check if both HDAT0 and HDAT1 are cleared
kayekss 0:708868399033 123 return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000;
kayekss 0:708868399033 124 }
kayekss 0:708868399033 125
kayekss 2:47ba7e2259cd 126 /** Write to an SCI (Serial Control Interface) register entry. */
kayekss 0:708868399033 127 void VS1053::writeReg(uint8_t addr, uint16_t word) {
kayekss 0:708868399033 128 // If addr is out-of-range, do nothing
kayekss 0:708868399033 129 if (addr > 0x0f) {
kayekss 0:708868399033 130 return;
kayekss 0:708868399033 131 }
kayekss 0:708868399033 132
kayekss 0:708868399033 133 while (!dreq);
kayekss 0:708868399033 134 cs = 0;
kayekss 0:708868399033 135 spi.write(0x02); // Send a "Write SCI" instruction (02h),
kayekss 0:708868399033 136 spi.write(addr); // target address,
kayekss 0:708868399033 137 spi.write(word >> 8); // high byte,
kayekss 0:708868399033 138 spi.write(word & 0xff); // then low byte
kayekss 0:708868399033 139 while (!dreq);
kayekss 0:708868399033 140 cs = 1;
kayekss 0:708868399033 141 }
kayekss 0:708868399033 142
kayekss 2:47ba7e2259cd 143 /** Read an SCI (Serial Control Interface) register entry. */
kayekss 0:708868399033 144 uint16_t VS1053::readReg(uint8_t addr) {
kayekss 0:708868399033 145 uint16_t word;
kayekss 0:708868399033 146
kayekss 0:708868399033 147 // If addr is out-of-range, return a beef
kayekss 0:708868399033 148 if (addr > 0x0f) {
kayekss 0:708868399033 149 return 0xbeef;
kayekss 0:708868399033 150 }
kayekss 0:708868399033 151
kayekss 0:708868399033 152 while (!dreq);
kayekss 0:708868399033 153 cs = 0;
kayekss 0:708868399033 154 spi.write(0x03); // Send a "Read SCI" instruction (03h)
kayekss 0:708868399033 155 spi.write(addr); // and target address
kayekss 0:708868399033 156 word = spi.write(0xff) << 8; // Receive high byte with dummy data FFh
kayekss 0:708868399033 157 word |= spi.write(0xff); // Receive low byte
kayekss 0:708868399033 158 while (!dreq);
kayekss 0:708868399033 159 cs = 1;
kayekss 0:708868399033 160 return word;
kayekss 0:708868399033 161 }