Just a simple library for VLSI's mp3/midi codec chip
Dependents: IsuProject_LPC1768
Diff: VS1053.cpp
- Revision:
- 0:708868399033
- Child:
- 1:00c19f771676
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VS1053.cpp Fri Nov 08 10:41:54 2013 +0000 @@ -0,0 +1,154 @@ +// ==================================================== Nov 04 2013, kayeks == +// VS1053.cpp +// =========================================================================== +// Just a simple library for VLSI's mp3/midi codec chip +// - Minimal and simple implementation (and dirty too) + +#include "mbed.h" +#include "VS1053.h" + +/** Constructor of class VS1053 */ +VS1053::VS1053(PinName mosiPin, PinName misoPin, PinName sckPin, + PinName csPin, PinName bsyncPin, PinName dreqPin, + PinName rstPin, uint32_t spiFrequency) +: + spi(mosiPin, misoPin, sckPin), + cs(csPin), + bsync(bsyncPin), + dreq(dreqPin), + rst(rstPin) +{ + spi.format(8, 0); + spi.frequency(spiFrequency); + + // Initialize outputs + cs = 1; + bsync = 1; + rst = 1; +} + +/** Destructor of class VS1053 */ +VS1053::~VS1053() { +} + +/** Do a hardware reset by hitting VS1053's RESET pin */ +void VS1053::hardwareReset() { + rst = 0; + wait(.05); + rst = 1; + wait(.05); +} + +/** Send a byte to VS1053 */ +void VS1053::sendDataByte(uint8_t b) { + while (!dreq); + bsync = 0; + spi.write(b); + bsync = 1; +} + +/** Send a data block specified as a pointer to VS1053 */ +size_t VS1053::sendDataBlock(uint8_t* p, size_t length) { + size_t sizeSent = 0; + + if (!p || !length) return 0; + while (length) { + while (!dreq); + cs = 0; + for (uint8_t i = 0; i < 32 && length--; i++) { + spi.write(*p++); + sizeSent++; + } + cs = 1; + } + return sizeSent; +} + +/** Change VS1053's PLL setting for speedup */ +void VS1053::clockUp() { + // Set CLKI to 43.0-55.3 MHz + writeReg(SCI_CLOCKF, 0x8800); // SC_MULT=4 (3.5x), SC_ADD=1 (+1.0x) +} + +/** Send cancel request to VS1053 */ +bool VS1053::sendCancel() { + uint16_t reg; + + // Set SM_CANCEL bit + reg = readReg(SCI_MODE); + if (reg & 0x0008) { + // Abort if SM_CANCEL is still set + return 0; + } + writeReg(SCI_MODE, reg | 0x0008); + return 1; +} + +/** Stop playing (CALL AFTER sendCancel SUCCESSES) */ +bool VS1053::stop() { + uint16_t reg; + uint8_t endFillByte; + size_t length; + + // If SM_CANCEL is still set, do nothing + reg = readReg(SCI_MODE); + if (reg & 0x0008) { + return 0; + } + + // Read endFillByte from XRAM <1E06h> + writeReg(SCI_WRAMADDR, 0x1e06); + reg = readReg(SCI_WRAM); + + // Send lower 8 bits of endFillByte 2,052 times + endFillByte = reg & 0xff; + length = 2052; + while (length) { + while (!dreq); + cs = 0; + for (uint8_t i = 0; i < 32 && length--; i++) { + spi.write(endFillByte); + } + cs = 1; + } + + // Check if both HDAT0 and HDAT1 are cleared + return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000; +} + +/** Write to an SCI (Serial Control Interface) register entry */ +void VS1053::writeReg(uint8_t addr, uint16_t word) { + // If addr is out-of-range, do nothing + if (addr > 0x0f) { + return; + } + + while (!dreq); + cs = 0; + spi.write(0x02); // Send a "Write SCI" instruction (02h), + spi.write(addr); // target address, + spi.write(word >> 8); // high byte, + spi.write(word & 0xff); // then low byte + while (!dreq); + cs = 1; +} + +/** Read an SCI (Serial Control Interface) register entry */ +uint16_t VS1053::readReg(uint8_t addr) { + uint16_t word; + + // If addr is out-of-range, return a beef + if (addr > 0x0f) { + return 0xbeef; + } + + while (!dreq); + cs = 0; + spi.write(0x03); // Send a "Read SCI" instruction (03h) + spi.write(addr); // and target address + word = spi.write(0xff) << 8; // Receive high byte with dummy data FFh + word |= spi.write(0xff); // Receive low byte + while (!dreq); + cs = 1; + return word; +}