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:
Thu Dec 19 19:14:15 2013 +0000
Revision:
5:cbf43dc9c947
Parent:
4:6e0fb5342efa
Child:
6:1f57fbd3aeb5
Fixed a bug where stop function dows not work

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kayekss 4:6e0fb5342efa 1 // ==================================================== Dec 18 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 4:6e0fb5342efa 53 size_t VS1053::sendDataBlock(uint8_t* data, size_t length) {
kayekss 5:cbf43dc9c947 54 size_t n, sizeSent = 0;
kayekss 0:708868399033 55
kayekss 4:6e0fb5342efa 56 if (!data || !length) return 0;
kayekss 5:cbf43dc9c947 57 while (length) {
kayekss 5:cbf43dc9c947 58 n = length < 32 ? length : 32;
kayekss 0:708868399033 59 while (!dreq);
kayekss 1:00c19f771676 60 bsync = 0;
kayekss 4:6e0fb5342efa 61 for (uint32_t i = 0; i < n; i++) {
kayekss 4:6e0fb5342efa 62 spi.write(*data++);
kayekss 5:cbf43dc9c947 63 sizeSent++; length--;
kayekss 0:708868399033 64 }
kayekss 1:00c19f771676 65 bsync = 1;
kayekss 0:708868399033 66 }
kayekss 0:708868399033 67 return sizeSent;
kayekss 0:708868399033 68 }
kayekss 0:708868399033 69
kayekss 2:47ba7e2259cd 70 /** Change VS1053's PLL setting for speedup. */
kayekss 0:708868399033 71 void VS1053::clockUp() {
kayekss 0:708868399033 72 // Set CLKI to 43.0-55.3 MHz
kayekss 0:708868399033 73 writeReg(SCI_CLOCKF, 0x8800); // SC_MULT=4 (3.5x), SC_ADD=1 (+1.0x)
kayekss 4:6e0fb5342efa 74 wait(0.01);
kayekss 0:708868399033 75 }
kayekss 0:708868399033 76
kayekss 2:47ba7e2259cd 77 /** Send cancel request to VS1053.
kayekss 3:696c8e6744b2 78 * @return Zero at failure, non-zero at success.
kayekss 2:47ba7e2259cd 79 */
kayekss 0:708868399033 80 bool VS1053::sendCancel() {
kayekss 0:708868399033 81 uint16_t reg;
kayekss 0:708868399033 82
kayekss 0:708868399033 83 // Set SM_CANCEL bit
kayekss 0:708868399033 84 reg = readReg(SCI_MODE);
kayekss 0:708868399033 85 if (reg & 0x0008) {
kayekss 0:708868399033 86 // Abort if SM_CANCEL is still set
kayekss 3:696c8e6744b2 87 return false;
kayekss 0:708868399033 88 }
kayekss 0:708868399033 89 writeReg(SCI_MODE, reg | 0x0008);
kayekss 3:696c8e6744b2 90 return true;
kayekss 0:708868399033 91 }
kayekss 0:708868399033 92
kayekss 4:6e0fb5342efa 93 /** Attempt a termination of playing.
kayekss 4:6e0fb5342efa 94 * Please call this repeatedly during data stream tramsission until it successes.
kayekss 3:696c8e6744b2 95 * @return Zero at failure, non-zero at success.
kayekss 2:47ba7e2259cd 96 */
kayekss 0:708868399033 97 bool VS1053::stop() {
kayekss 0:708868399033 98 uint16_t reg;
kayekss 5:cbf43dc9c947 99 uint8_t endFillByte;
kayekss 5:cbf43dc9c947 100 size_t n, length;
kayekss 0:708868399033 101
kayekss 0:708868399033 102 // If SM_CANCEL is still set, do nothing
kayekss 0:708868399033 103 reg = readReg(SCI_MODE);
kayekss 0:708868399033 104 if (reg & 0x0008) {
kayekss 3:696c8e6744b2 105 return false;
kayekss 0:708868399033 106 }
kayekss 0:708868399033 107
kayekss 0:708868399033 108 // Read endFillByte from XRAM <1E06h>
kayekss 0:708868399033 109 writeReg(SCI_WRAMADDR, 0x1e06);
kayekss 0:708868399033 110 reg = readReg(SCI_WRAM);
kayekss 0:708868399033 111
kayekss 0:708868399033 112 // Send lower 8 bits of endFillByte 2,052 times
kayekss 0:708868399033 113 endFillByte = reg & 0xff;
kayekss 0:708868399033 114 length = 2052;
kayekss 0:708868399033 115 while (length) {
kayekss 5:cbf43dc9c947 116 n = length < 32 ? length : 32;
kayekss 0:708868399033 117 while (!dreq);
kayekss 1:00c19f771676 118 bsync = 0;
kayekss 5:cbf43dc9c947 119 for (uint32_t i = 0; i < n; i++) {
kayekss 0:708868399033 120 spi.write(endFillByte);
kayekss 5:cbf43dc9c947 121 length--;
kayekss 0:708868399033 122 }
kayekss 1:00c19f771676 123 bsync = 1;
kayekss 0:708868399033 124 }
kayekss 0:708868399033 125 // Check if both HDAT0 and HDAT1 are cleared
kayekss 0:708868399033 126 return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000;
kayekss 0:708868399033 127 }
kayekss 0:708868399033 128
kayekss 2:47ba7e2259cd 129 /** Write to an SCI (Serial Control Interface) register entry. */
kayekss 0:708868399033 130 void VS1053::writeReg(uint8_t addr, uint16_t word) {
kayekss 0:708868399033 131 // If addr is out-of-range, do nothing
kayekss 0:708868399033 132 if (addr > 0x0f) {
kayekss 0:708868399033 133 return;
kayekss 0:708868399033 134 }
kayekss 0:708868399033 135
kayekss 0:708868399033 136 while (!dreq);
kayekss 0:708868399033 137 cs = 0;
kayekss 0:708868399033 138 spi.write(0x02); // Send a "Write SCI" instruction (02h),
kayekss 0:708868399033 139 spi.write(addr); // target address,
kayekss 0:708868399033 140 spi.write(word >> 8); // high byte,
kayekss 0:708868399033 141 spi.write(word & 0xff); // then low byte
kayekss 0:708868399033 142 while (!dreq);
kayekss 0:708868399033 143 cs = 1;
kayekss 0:708868399033 144 }
kayekss 0:708868399033 145
kayekss 3:696c8e6744b2 146 /** Read an SCI (Serial Control Interface) register entry.
kayekss 3:696c8e6744b2 147 * @return Register value or 0000h when invalid address was specified.
kayekss 3:696c8e6744b2 148 */
kayekss 0:708868399033 149 uint16_t VS1053::readReg(uint8_t addr) {
kayekss 0:708868399033 150 uint16_t word;
kayekss 0:708868399033 151
kayekss 3:696c8e6744b2 152 // If addr is out-of-range, return 0000h
kayekss 0:708868399033 153 if (addr > 0x0f) {
kayekss 3:696c8e6744b2 154 return 0x0000;
kayekss 0:708868399033 155 }
kayekss 0:708868399033 156
kayekss 0:708868399033 157 while (!dreq);
kayekss 0:708868399033 158 cs = 0;
kayekss 0:708868399033 159 spi.write(0x03); // Send a "Read SCI" instruction (03h)
kayekss 0:708868399033 160 spi.write(addr); // and target address
kayekss 0:708868399033 161 word = spi.write(0xff) << 8; // Receive high byte with dummy data FFh
kayekss 0:708868399033 162 word |= spi.write(0xff); // Receive low byte
kayekss 0:708868399033 163 while (!dreq);
kayekss 0:708868399033 164 cs = 1;
kayekss 0:708868399033 165 return word;
kayekss 0:708868399033 166 }