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:
silis
Date:
Thu Nov 26 14:21:36 2015 +0000
Revision:
8:5ad25d480d5f
Parent:
7:97a8edd44fe9
Added setVolume function

Who changed what in which revision?

UserRevisionLine numberNew contents of line
silis 7:97a8edd44fe9 1 /**
silis 7:97a8edd44fe9 2 * ==================================================== Dec 21 2013, kayeks ==
silis 7:97a8edd44fe9 3 * VS1053.cpp
silis 7:97a8edd44fe9 4 * ===========================================================================
silis 7:97a8edd44fe9 5 * Just a simple library for VLSI's mp3/midi codec chip
silis 7:97a8edd44fe9 6 * - Minimal and simple implementation (and dirty too)
silis 7:97a8edd44fe9 7 *
silis 7:97a8edd44fe9 8 * Modified on 05 September 2015 by Vassilis Serasidis.
silis 7:97a8edd44fe9 9 * - Added a patch for playing MP3 files on some "LC Technology" VS1053 boards.
silis 7:97a8edd44fe9 10 *
silis 7:97a8edd44fe9 11 *
silis 7:97a8edd44fe9 12 */
kayekss 0:708868399033 13
kayekss 0:708868399033 14 #include "mbed.h"
kayekss 0:708868399033 15 #include "VS1053.h"
kayekss 0:708868399033 16
kayekss 2:47ba7e2259cd 17 /** Constructor of class VS1053. */
kayekss 0:708868399033 18 VS1053::VS1053(PinName mosiPin, PinName misoPin, PinName sckPin,
kayekss 0:708868399033 19 PinName csPin, PinName bsyncPin, PinName dreqPin,
kayekss 0:708868399033 20 PinName rstPin, uint32_t spiFrequency)
kayekss 0:708868399033 21 :
kayekss 0:708868399033 22 spi(mosiPin, misoPin, sckPin),
kayekss 0:708868399033 23 cs(csPin),
silis 8:5ad25d480d5f 24 bsync(bsyncPin), //dcs pin
kayekss 0:708868399033 25 dreq(dreqPin),
kayekss 0:708868399033 26 rst(rstPin)
kayekss 0:708868399033 27 {
silis 8:5ad25d480d5f 28 //spi.format(8, 0);
silis 8:5ad25d480d5f 29 //spi.frequency(spiFrequency);
kayekss 0:708868399033 30
kayekss 0:708868399033 31 // Initialize outputs
kayekss 0:708868399033 32 cs = 1;
kayekss 0:708868399033 33 bsync = 1;
kayekss 0:708868399033 34 rst = 1;
kayekss 0:708868399033 35 }
kayekss 0:708868399033 36
kayekss 2:47ba7e2259cd 37 /** Destructor of class VS1053. */
kayekss 0:708868399033 38 VS1053::~VS1053() {
kayekss 0:708868399033 39 }
kayekss 0:708868399033 40
kayekss 2:47ba7e2259cd 41 /** Make a hardware reset by hitting VS1053's RESET pin. */
kayekss 0:708868399033 42 void VS1053::hardwareReset() {
kayekss 0:708868399033 43 rst = 0;
kayekss 0:708868399033 44 wait(.05);
kayekss 0:708868399033 45 rst = 1;
kayekss 0:708868399033 46 wait(.05);
kayekss 0:708868399033 47 }
kayekss 0:708868399033 48
silis 7:97a8edd44fe9 49 /** Patch for some LC Technology VS1053 board with "no sound" problem.
silis 7:97a8edd44fe9 50 * 5 September 2015 bby Vassilis Serasidis
silis 7:97a8edd44fe9 51 */
silis 7:97a8edd44fe9 52 void VS1053::modeSwitch(void)
silis 7:97a8edd44fe9 53 {
silis 7:97a8edd44fe9 54 //GPIO_DDR
silis 7:97a8edd44fe9 55 writeReg(SCI_WRAMADDR, 0xc017);
silis 7:97a8edd44fe9 56 writeReg(SCI_WRAM, 0x0003);
silis 7:97a8edd44fe9 57
silis 7:97a8edd44fe9 58 wait(.05);
silis 7:97a8edd44fe9 59 writeReg(SCI_MODE, (1<<SM_SDINEW) | (1<<SM_RESET));
silis 7:97a8edd44fe9 60 wait(.05);
silis 7:97a8edd44fe9 61 }
silis 7:97a8edd44fe9 62
kayekss 2:47ba7e2259cd 63 /** Send a data byte to VS1053. */
kayekss 2:47ba7e2259cd 64 void VS1053::sendDataByte(uint8_t data) {
kayekss 0:708868399033 65 while (!dreq);
kayekss 0:708868399033 66 bsync = 0;
kayekss 2:47ba7e2259cd 67 spi.write(data);
kayekss 0:708868399033 68 bsync = 1;
kayekss 0:708868399033 69 }
kayekss 0:708868399033 70
kayekss 2:47ba7e2259cd 71 /** Send a data block specified as a pointer to VS1053.
kayekss 2:47ba7e2259cd 72 * @return Data length successfully sent.
kayekss 2:47ba7e2259cd 73 */
silis 8:5ad25d480d5f 74 size_t VS1053::sendDataBlock(char* data, size_t length) {
kayekss 5:cbf43dc9c947 75 size_t n, sizeSent = 0;
kayekss 0:708868399033 76
kayekss 4:6e0fb5342efa 77 if (!data || !length) return 0;
kayekss 5:cbf43dc9c947 78 while (length) {
kayekss 5:cbf43dc9c947 79 n = length < 32 ? length : 32;
kayekss 0:708868399033 80 while (!dreq);
kayekss 1:00c19f771676 81 bsync = 0;
kayekss 4:6e0fb5342efa 82 for (uint32_t i = 0; i < n; i++) {
kayekss 4:6e0fb5342efa 83 spi.write(*data++);
kayekss 5:cbf43dc9c947 84 sizeSent++; length--;
kayekss 0:708868399033 85 }
kayekss 1:00c19f771676 86 bsync = 1;
kayekss 0:708868399033 87 }
kayekss 0:708868399033 88 return sizeSent;
kayekss 0:708868399033 89 }
kayekss 0:708868399033 90
kayekss 2:47ba7e2259cd 91 /** Change VS1053's PLL setting for speedup. */
kayekss 0:708868399033 92 void VS1053::clockUp() {
kayekss 0:708868399033 93 // Set CLKI to 43.0-55.3 MHz
kayekss 0:708868399033 94 writeReg(SCI_CLOCKF, 0x8800); // SC_MULT=4 (3.5x), SC_ADD=1 (+1.0x)
kayekss 4:6e0fb5342efa 95 wait(0.01);
kayekss 0:708868399033 96 }
kayekss 0:708868399033 97
kayekss 2:47ba7e2259cd 98 /** Send cancel request to VS1053.
kayekss 3:696c8e6744b2 99 * @return Zero at failure, non-zero at success.
kayekss 2:47ba7e2259cd 100 */
kayekss 0:708868399033 101 bool VS1053::sendCancel() {
kayekss 0:708868399033 102 uint16_t reg;
kayekss 0:708868399033 103
kayekss 0:708868399033 104 // Set SM_CANCEL bit
kayekss 0:708868399033 105 reg = readReg(SCI_MODE);
kayekss 0:708868399033 106 if (reg & 0x0008) {
kayekss 0:708868399033 107 // Abort if SM_CANCEL is still set
kayekss 3:696c8e6744b2 108 return false;
kayekss 0:708868399033 109 }
kayekss 0:708868399033 110 writeReg(SCI_MODE, reg | 0x0008);
kayekss 3:696c8e6744b2 111 return true;
kayekss 0:708868399033 112 }
kayekss 0:708868399033 113
kayekss 4:6e0fb5342efa 114 /** Attempt a termination of playing.
kayekss 4:6e0fb5342efa 115 * Please call this repeatedly during data stream tramsission until it successes.
kayekss 3:696c8e6744b2 116 * @return Zero at failure, non-zero at success.
kayekss 2:47ba7e2259cd 117 */
kayekss 0:708868399033 118 bool VS1053::stop() {
kayekss 0:708868399033 119 uint16_t reg;
kayekss 5:cbf43dc9c947 120 uint8_t endFillByte;
kayekss 5:cbf43dc9c947 121 size_t n, length;
kayekss 0:708868399033 122
kayekss 0:708868399033 123 // If SM_CANCEL is still set, do nothing
kayekss 0:708868399033 124 reg = readReg(SCI_MODE);
kayekss 0:708868399033 125 if (reg & 0x0008) {
kayekss 3:696c8e6744b2 126 return false;
kayekss 0:708868399033 127 }
kayekss 0:708868399033 128
kayekss 0:708868399033 129 // Read endFillByte from XRAM <1E06h>
kayekss 0:708868399033 130 writeReg(SCI_WRAMADDR, 0x1e06);
kayekss 0:708868399033 131 reg = readReg(SCI_WRAM);
kayekss 0:708868399033 132
kayekss 0:708868399033 133 // Send lower 8 bits of endFillByte 2,052 times
kayekss 0:708868399033 134 endFillByte = reg & 0xff;
kayekss 0:708868399033 135 length = 2052;
kayekss 0:708868399033 136 while (length) {
kayekss 5:cbf43dc9c947 137 n = length < 32 ? length : 32;
kayekss 0:708868399033 138 while (!dreq);
kayekss 1:00c19f771676 139 bsync = 0;
kayekss 5:cbf43dc9c947 140 for (uint32_t i = 0; i < n; i++) {
kayekss 0:708868399033 141 spi.write(endFillByte);
kayekss 5:cbf43dc9c947 142 length--;
kayekss 0:708868399033 143 }
kayekss 1:00c19f771676 144 bsync = 1;
kayekss 0:708868399033 145 }
kayekss 0:708868399033 146 // Check if both HDAT0 and HDAT1 are cleared
kayekss 0:708868399033 147 return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000;
kayekss 0:708868399033 148 }
kayekss 0:708868399033 149
silis 8:5ad25d480d5f 150 /**
silis 8:5ad25d480d5f 151 * Set the VS1053 volume.
silis 8:5ad25d480d5f 152 *
silis 8:5ad25d480d5f 153 */
silis 8:5ad25d480d5f 154 void VS1053::setVolume(uint8_t vol)
silis 8:5ad25d480d5f 155 {
silis 8:5ad25d480d5f 156 uint16_t value = vol;
silis 8:5ad25d480d5f 157 value <<= 8;
silis 8:5ad25d480d5f 158 value |= vol;
silis 8:5ad25d480d5f 159
silis 8:5ad25d480d5f 160 writeReg(SCI_VOL,value); // VOL
silis 8:5ad25d480d5f 161 }
silis 8:5ad25d480d5f 162
kayekss 2:47ba7e2259cd 163 /** Write to an SCI (Serial Control Interface) register entry. */
kayekss 0:708868399033 164 void VS1053::writeReg(uint8_t addr, uint16_t word) {
kayekss 0:708868399033 165 // If addr is out-of-range, do nothing
kayekss 0:708868399033 166 if (addr > 0x0f) {
kayekss 0:708868399033 167 return;
kayekss 0:708868399033 168 }
kayekss 0:708868399033 169
kayekss 0:708868399033 170 while (!dreq);
kayekss 0:708868399033 171 cs = 0;
kayekss 0:708868399033 172 spi.write(0x02); // Send a "Write SCI" instruction (02h),
kayekss 0:708868399033 173 spi.write(addr); // target address,
kayekss 0:708868399033 174 spi.write(word >> 8); // high byte,
kayekss 0:708868399033 175 spi.write(word & 0xff); // then low byte
kayekss 0:708868399033 176 while (!dreq);
kayekss 0:708868399033 177 cs = 1;
kayekss 0:708868399033 178 }
kayekss 0:708868399033 179
kayekss 3:696c8e6744b2 180 /** Read an SCI (Serial Control Interface) register entry.
kayekss 3:696c8e6744b2 181 * @return Register value or 0000h when invalid address was specified.
kayekss 3:696c8e6744b2 182 */
kayekss 0:708868399033 183 uint16_t VS1053::readReg(uint8_t addr) {
kayekss 0:708868399033 184 uint16_t word;
kayekss 0:708868399033 185
kayekss 3:696c8e6744b2 186 // If addr is out-of-range, return 0000h
kayekss 0:708868399033 187 if (addr > 0x0f) {
kayekss 3:696c8e6744b2 188 return 0x0000;
kayekss 0:708868399033 189 }
kayekss 0:708868399033 190
kayekss 0:708868399033 191 while (!dreq);
kayekss 0:708868399033 192 cs = 0;
kayekss 0:708868399033 193 spi.write(0x03); // Send a "Read SCI" instruction (03h)
kayekss 0:708868399033 194 spi.write(addr); // and target address
kayekss 0:708868399033 195 word = spi.write(0xff) << 8; // Receive high byte with dummy data FFh
kayekss 0:708868399033 196 word |= spi.write(0xff); // Receive low byte
kayekss 0:708868399033 197 while (!dreq);
kayekss 0:708868399033 198 cs = 1;
kayekss 0:708868399033 199 return word;
kayekss 0:708868399033 200 }