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:
Fri Nov 08 10:41:54 2013 +0000
Revision:
0:708868399033
Child:
1:00c19f771676
Just a simple library for VLSI's mp3/midi codec chip

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kayekss 0:708868399033 1 // ==================================================== Nov 04 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 0:708868399033 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 0:708868399033 30 /** Destructor of class VS1053 */
kayekss 0:708868399033 31 VS1053::~VS1053() {
kayekss 0:708868399033 32 }
kayekss 0:708868399033 33
kayekss 0:708868399033 34 /** Do 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 0:708868399033 42 /** Send a byte to VS1053 */
kayekss 0:708868399033 43 void VS1053::sendDataByte(uint8_t b) {
kayekss 0:708868399033 44 while (!dreq);
kayekss 0:708868399033 45 bsync = 0;
kayekss 0:708868399033 46 spi.write(b);
kayekss 0:708868399033 47 bsync = 1;
kayekss 0:708868399033 48 }
kayekss 0:708868399033 49
kayekss 0:708868399033 50 /** Send a data block specified as a pointer to VS1053 */
kayekss 0:708868399033 51 size_t VS1053::sendDataBlock(uint8_t* p, size_t length) {
kayekss 0:708868399033 52 size_t sizeSent = 0;
kayekss 0:708868399033 53
kayekss 0:708868399033 54 if (!p || !length) return 0;
kayekss 0:708868399033 55 while (length) {
kayekss 0:708868399033 56 while (!dreq);
kayekss 0:708868399033 57 cs = 0;
kayekss 0:708868399033 58 for (uint8_t i = 0; i < 32 && length--; i++) {
kayekss 0:708868399033 59 spi.write(*p++);
kayekss 0:708868399033 60 sizeSent++;
kayekss 0:708868399033 61 }
kayekss 0:708868399033 62 cs = 1;
kayekss 0:708868399033 63 }
kayekss 0:708868399033 64 return sizeSent;
kayekss 0:708868399033 65 }
kayekss 0:708868399033 66
kayekss 0:708868399033 67 /** Change VS1053's PLL setting for speedup */
kayekss 0:708868399033 68 void VS1053::clockUp() {
kayekss 0:708868399033 69 // Set CLKI to 43.0-55.3 MHz
kayekss 0:708868399033 70 writeReg(SCI_CLOCKF, 0x8800); // SC_MULT=4 (3.5x), SC_ADD=1 (+1.0x)
kayekss 0:708868399033 71 }
kayekss 0:708868399033 72
kayekss 0:708868399033 73 /** Send cancel request to VS1053 */
kayekss 0:708868399033 74 bool VS1053::sendCancel() {
kayekss 0:708868399033 75 uint16_t reg;
kayekss 0:708868399033 76
kayekss 0:708868399033 77 // Set SM_CANCEL bit
kayekss 0:708868399033 78 reg = readReg(SCI_MODE);
kayekss 0:708868399033 79 if (reg & 0x0008) {
kayekss 0:708868399033 80 // Abort if SM_CANCEL is still set
kayekss 0:708868399033 81 return 0;
kayekss 0:708868399033 82 }
kayekss 0:708868399033 83 writeReg(SCI_MODE, reg | 0x0008);
kayekss 0:708868399033 84 return 1;
kayekss 0:708868399033 85 }
kayekss 0:708868399033 86
kayekss 0:708868399033 87 /** Stop playing (CALL AFTER sendCancel SUCCESSES) */
kayekss 0:708868399033 88 bool VS1053::stop() {
kayekss 0:708868399033 89 uint16_t reg;
kayekss 0:708868399033 90 uint8_t endFillByte;
kayekss 0:708868399033 91 size_t length;
kayekss 0:708868399033 92
kayekss 0:708868399033 93 // If SM_CANCEL is still set, do nothing
kayekss 0:708868399033 94 reg = readReg(SCI_MODE);
kayekss 0:708868399033 95 if (reg & 0x0008) {
kayekss 0:708868399033 96 return 0;
kayekss 0:708868399033 97 }
kayekss 0:708868399033 98
kayekss 0:708868399033 99 // Read endFillByte from XRAM <1E06h>
kayekss 0:708868399033 100 writeReg(SCI_WRAMADDR, 0x1e06);
kayekss 0:708868399033 101 reg = readReg(SCI_WRAM);
kayekss 0:708868399033 102
kayekss 0:708868399033 103 // Send lower 8 bits of endFillByte 2,052 times
kayekss 0:708868399033 104 endFillByte = reg & 0xff;
kayekss 0:708868399033 105 length = 2052;
kayekss 0:708868399033 106 while (length) {
kayekss 0:708868399033 107 while (!dreq);
kayekss 0:708868399033 108 cs = 0;
kayekss 0:708868399033 109 for (uint8_t i = 0; i < 32 && length--; i++) {
kayekss 0:708868399033 110 spi.write(endFillByte);
kayekss 0:708868399033 111 }
kayekss 0:708868399033 112 cs = 1;
kayekss 0:708868399033 113 }
kayekss 0:708868399033 114
kayekss 0:708868399033 115 // Check if both HDAT0 and HDAT1 are cleared
kayekss 0:708868399033 116 return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000;
kayekss 0:708868399033 117 }
kayekss 0:708868399033 118
kayekss 0:708868399033 119 /** Write to an SCI (Serial Control Interface) register entry */
kayekss 0:708868399033 120 void VS1053::writeReg(uint8_t addr, uint16_t word) {
kayekss 0:708868399033 121 // If addr is out-of-range, do nothing
kayekss 0:708868399033 122 if (addr > 0x0f) {
kayekss 0:708868399033 123 return;
kayekss 0:708868399033 124 }
kayekss 0:708868399033 125
kayekss 0:708868399033 126 while (!dreq);
kayekss 0:708868399033 127 cs = 0;
kayekss 0:708868399033 128 spi.write(0x02); // Send a "Write SCI" instruction (02h),
kayekss 0:708868399033 129 spi.write(addr); // target address,
kayekss 0:708868399033 130 spi.write(word >> 8); // high byte,
kayekss 0:708868399033 131 spi.write(word & 0xff); // then low byte
kayekss 0:708868399033 132 while (!dreq);
kayekss 0:708868399033 133 cs = 1;
kayekss 0:708868399033 134 }
kayekss 0:708868399033 135
kayekss 0:708868399033 136 /** Read an SCI (Serial Control Interface) register entry */
kayekss 0:708868399033 137 uint16_t VS1053::readReg(uint8_t addr) {
kayekss 0:708868399033 138 uint16_t word;
kayekss 0:708868399033 139
kayekss 0:708868399033 140 // If addr is out-of-range, return a beef
kayekss 0:708868399033 141 if (addr > 0x0f) {
kayekss 0:708868399033 142 return 0xbeef;
kayekss 0:708868399033 143 }
kayekss 0:708868399033 144
kayekss 0:708868399033 145 while (!dreq);
kayekss 0:708868399033 146 cs = 0;
kayekss 0:708868399033 147 spi.write(0x03); // Send a "Read SCI" instruction (03h)
kayekss 0:708868399033 148 spi.write(addr); // and target address
kayekss 0:708868399033 149 word = spi.write(0xff) << 8; // Receive high byte with dummy data FFh
kayekss 0:708868399033 150 word |= spi.write(0xff); // Receive low byte
kayekss 0:708868399033 151 while (!dreq);
kayekss 0:708868399033 152 cs = 1;
kayekss 0:708868399033 153 return word;
kayekss 0:708868399033 154 }