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

Dependents:   IsuProject_LPC1768

Committer:
kayekss
Date:
Fri Dec 20 21:34:03 2013 +0000
Revision:
6:1f57fbd3aeb5
Parent:
5:cbf43dc9c947
Unified parameter names on constructor

Who changed what in which revision?

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