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

Dependents:   IsuProject_LPC1768

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 }