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

Dependents:   IsuProject_LPC1768

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 }