Just a simple library for VLSI's mp3/midi codec chip
Dependents: IsuProject_LPC1768
VS1053.cpp
00001 // ==================================================== Dec 21 2013, kayeks == 00002 // VS1053.cpp 00003 // =========================================================================== 00004 // Just a simple library for VLSI's mp3/midi codec chip 00005 // - Minimal and simple implementation (and dirty too) 00006 00007 #include "mbed.h" 00008 #include "VS1053.h" 00009 00010 /** Constructor of class VS1053. */ 00011 VS1053::VS1053(PinName mosiPin, PinName misoPin, PinName sckPin, 00012 PinName csPin, PinName bsyncPin, PinName dreqPin, 00013 PinName rstPin, uint32_t spiFrequency) 00014 : 00015 spi(mosiPin, misoPin, sckPin), 00016 cs(csPin), 00017 bsync(bsyncPin), 00018 dreq(dreqPin), 00019 rst(rstPin) 00020 { 00021 spi.format(8, 0); 00022 spi.frequency(spiFrequency); 00023 00024 // Initialize outputs 00025 cs = 1; 00026 bsync = 1; 00027 rst = 1; 00028 } 00029 00030 /** Destructor of class VS1053. */ 00031 VS1053::~VS1053() { 00032 } 00033 00034 /** Make a hardware reset by hitting VS1053's RESET pin. */ 00035 void VS1053::hardwareReset() { 00036 rst = 0; 00037 wait(.05); 00038 rst = 1; 00039 wait(.05); 00040 } 00041 00042 /** Send a data byte to VS1053. */ 00043 void VS1053::sendDataByte(uint8_t data) { 00044 while (!dreq); 00045 bsync = 0; 00046 spi.write(data); 00047 bsync = 1; 00048 } 00049 00050 /** Send a data block specified as a pointer to VS1053. 00051 * @return Data length successfully sent. 00052 */ 00053 size_t VS1053::sendDataBlock(uint8_t* data, size_t length) { 00054 size_t n, sizeSent = 0; 00055 00056 if (!data || !length) return 0; 00057 while (length) { 00058 n = length < 32 ? length : 32; 00059 while (!dreq); 00060 bsync = 0; 00061 for (uint32_t i = 0; i < n; i++) { 00062 spi.write(*data++); 00063 sizeSent++; length--; 00064 } 00065 bsync = 1; 00066 } 00067 return sizeSent; 00068 } 00069 00070 /** Change VS1053's PLL setting for speedup. */ 00071 void VS1053::clockUp() { 00072 // Set CLKI to 43.0-55.3 MHz 00073 writeReg(SCI_CLOCKF, 0x8800); // SC_MULT=4 (3.5x), SC_ADD=1 (+1.0x) 00074 wait(0.01); 00075 } 00076 00077 /** Send cancel request to VS1053. 00078 * @return Zero at failure, non-zero at success. 00079 */ 00080 bool VS1053::sendCancel() { 00081 uint16_t reg; 00082 00083 // Set SM_CANCEL bit 00084 reg = readReg(SCI_MODE); 00085 if (reg & 0x0008) { 00086 // Abort if SM_CANCEL is still set 00087 return false; 00088 } 00089 writeReg(SCI_MODE, reg | 0x0008); 00090 return true; 00091 } 00092 00093 /** Attempt a termination of playing. 00094 * Please call this repeatedly during data stream tramsission until it successes. 00095 * @return Zero at failure, non-zero at success. 00096 */ 00097 bool VS1053::stop() { 00098 uint16_t reg; 00099 uint8_t endFillByte; 00100 size_t n, length; 00101 00102 // If SM_CANCEL is still set, do nothing 00103 reg = readReg(SCI_MODE); 00104 if (reg & 0x0008) { 00105 return false; 00106 } 00107 00108 // Read endFillByte from XRAM <1E06h> 00109 writeReg(SCI_WRAMADDR, 0x1e06); 00110 reg = readReg(SCI_WRAM); 00111 00112 // Send lower 8 bits of endFillByte 2,052 times 00113 endFillByte = reg & 0xff; 00114 length = 2052; 00115 while (length) { 00116 n = length < 32 ? length : 32; 00117 while (!dreq); 00118 bsync = 0; 00119 for (uint32_t i = 0; i < n; i++) { 00120 spi.write(endFillByte); 00121 length--; 00122 } 00123 bsync = 1; 00124 } 00125 // Check if both HDAT0 and HDAT1 are cleared 00126 return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000; 00127 } 00128 00129 /** Write to an SCI (Serial Control Interface) register entry. */ 00130 void VS1053::writeReg(uint8_t addr, uint16_t word) { 00131 // If addr is out-of-range, do nothing 00132 if (addr > 0x0f) { 00133 return; 00134 } 00135 00136 while (!dreq); 00137 cs = 0; 00138 spi.write(0x02); // Send a "Write SCI" instruction (02h), 00139 spi.write(addr); // target address, 00140 spi.write(word >> 8); // high byte, 00141 spi.write(word & 0xff); // then low byte 00142 while (!dreq); 00143 cs = 1; 00144 } 00145 00146 /** Read an SCI (Serial Control Interface) register entry. 00147 * @return Register value or 0000h when invalid address was specified. 00148 */ 00149 uint16_t VS1053::readReg(uint8_t addr) { 00150 uint16_t word; 00151 00152 // If addr is out-of-range, return 0000h 00153 if (addr > 0x0f) { 00154 return 0x0000; 00155 } 00156 00157 while (!dreq); 00158 cs = 0; 00159 spi.write(0x03); // Send a "Read SCI" instruction (03h) 00160 spi.write(addr); // and target address 00161 word = spi.write(0xff) << 8; // Receive high byte with dummy data FFh 00162 word |= spi.write(0xff); // Receive low byte 00163 while (!dreq); 00164 cs = 1; 00165 return word; 00166 }
Generated on Tue Jul 12 2022 21:40:39 by 1.7.2