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

Dependents:   IsuProject_LPC1768

Committer:
kayekss
Date:
Fri Nov 08 11:01:00 2013 +0000
Revision:
1:00c19f771676
Parent:
0:708868399033
Child:
2:47ba7e2259cd
Fixed errors in sendDataBlock/stop

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kayekss 1:00c19f771676 1 // ==================================================== Nov 08 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 0:708868399033 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 0:708868399033 30 /** Destructor of class VS1053 */
kayekss 0:708868399033 31 VS1053::~VS1053() {
kayekss 0:708868399033 32 }
kayekss 0:708868399033 33
kayekss 0:708868399033 34 /** Do 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 0:708868399033 42 /** Send a byte to VS1053 */
kayekss 0:708868399033 43 void VS1053::sendDataByte(uint8_t b) {
kayekss 0:708868399033 44 while (!dreq);
kayekss 0:708868399033 45 bsync = 0;
kayekss 0:708868399033 46 spi.write(b);
kayekss 0:708868399033 47 bsync = 1;
kayekss 0:708868399033 48 }
kayekss 0:708868399033 49
kayekss 0:708868399033 50 /** Send a data block specified as a pointer to VS1053 */
kayekss 0:708868399033 51 size_t VS1053::sendDataBlock(uint8_t* p, size_t length) {
kayekss 0:708868399033 52 size_t sizeSent = 0;
kayekss 0:708868399033 53
kayekss 0:708868399033 54 if (!p || !length) return 0;
kayekss 0:708868399033 55 while (length) {
kayekss 0:708868399033 56 while (!dreq);
kayekss 1:00c19f771676 57 bsync = 0;
kayekss 0:708868399033 58 for (uint8_t i = 0; i < 32 && length--; i++) {
kayekss 0:708868399033 59 spi.write(*p++);
kayekss 0:708868399033 60 sizeSent++;
kayekss 0:708868399033 61 }
kayekss 1:00c19f771676 62 bsync = 1;
kayekss 0:708868399033 63 }
kayekss 0:708868399033 64 return sizeSent;
kayekss 0:708868399033 65 }
kayekss 0:708868399033 66
kayekss 0:708868399033 67 /** Change VS1053's PLL setting for speedup */
kayekss 0:708868399033 68 void VS1053::clockUp() {
kayekss 0:708868399033 69 // Set CLKI to 43.0-55.3 MHz
kayekss 0:708868399033 70 writeReg(SCI_CLOCKF, 0x8800); // SC_MULT=4 (3.5x), SC_ADD=1 (+1.0x)
kayekss 0:708868399033 71 }
kayekss 0:708868399033 72
kayekss 0:708868399033 73 /** Send cancel request to VS1053 */
kayekss 0:708868399033 74 bool VS1053::sendCancel() {
kayekss 0:708868399033 75 uint16_t reg;
kayekss 0:708868399033 76
kayekss 0:708868399033 77 // Set SM_CANCEL bit
kayekss 0:708868399033 78 reg = readReg(SCI_MODE);
kayekss 0:708868399033 79 if (reg & 0x0008) {
kayekss 0:708868399033 80 // Abort if SM_CANCEL is still set
kayekss 0:708868399033 81 return 0;
kayekss 0:708868399033 82 }
kayekss 0:708868399033 83 writeReg(SCI_MODE, reg | 0x0008);
kayekss 0:708868399033 84 return 1;
kayekss 0:708868399033 85 }
kayekss 0:708868399033 86
kayekss 0:708868399033 87 /** Stop playing (CALL AFTER sendCancel SUCCESSES) */
kayekss 0:708868399033 88 bool VS1053::stop() {
kayekss 0:708868399033 89 uint16_t reg;
kayekss 0:708868399033 90 uint8_t endFillByte;
kayekss 0:708868399033 91 size_t length;
kayekss 0:708868399033 92
kayekss 0:708868399033 93 // If SM_CANCEL is still set, do nothing
kayekss 0:708868399033 94 reg = readReg(SCI_MODE);
kayekss 0:708868399033 95 if (reg & 0x0008) {
kayekss 0:708868399033 96 return 0;
kayekss 0:708868399033 97 }
kayekss 0:708868399033 98
kayekss 0:708868399033 99 // Read endFillByte from XRAM <1E06h>
kayekss 0:708868399033 100 writeReg(SCI_WRAMADDR, 0x1e06);
kayekss 0:708868399033 101 reg = readReg(SCI_WRAM);
kayekss 0:708868399033 102
kayekss 0:708868399033 103 // Send lower 8 bits of endFillByte 2,052 times
kayekss 0:708868399033 104 endFillByte = reg & 0xff;
kayekss 0:708868399033 105 length = 2052;
kayekss 0:708868399033 106 while (length) {
kayekss 0:708868399033 107 while (!dreq);
kayekss 1:00c19f771676 108 bsync = 0;
kayekss 0:708868399033 109 for (uint8_t i = 0; i < 32 && length--; i++) {
kayekss 0:708868399033 110 spi.write(endFillByte);
kayekss 0:708868399033 111 }
kayekss 1:00c19f771676 112 bsync = 1;
kayekss 0:708868399033 113 }
kayekss 0:708868399033 114
kayekss 0:708868399033 115 // Check if both HDAT0 and HDAT1 are cleared
kayekss 0:708868399033 116 return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000;
kayekss 0:708868399033 117 }
kayekss 0:708868399033 118
kayekss 0:708868399033 119 /** Write to an SCI (Serial Control Interface) register entry */
kayekss 0:708868399033 120 void VS1053::writeReg(uint8_t addr, uint16_t word) {
kayekss 0:708868399033 121 // If addr is out-of-range, do nothing
kayekss 0:708868399033 122 if (addr > 0x0f) {
kayekss 0:708868399033 123 return;
kayekss 0:708868399033 124 }
kayekss 0:708868399033 125
kayekss 0:708868399033 126 while (!dreq);
kayekss 0:708868399033 127 cs = 0;
kayekss 0:708868399033 128 spi.write(0x02); // Send a "Write SCI" instruction (02h),
kayekss 0:708868399033 129 spi.write(addr); // target address,
kayekss 0:708868399033 130 spi.write(word >> 8); // high byte,
kayekss 0:708868399033 131 spi.write(word & 0xff); // then low byte
kayekss 0:708868399033 132 while (!dreq);
kayekss 0:708868399033 133 cs = 1;
kayekss 0:708868399033 134 }
kayekss 0:708868399033 135
kayekss 0:708868399033 136 /** Read an SCI (Serial Control Interface) register entry */
kayekss 0:708868399033 137 uint16_t VS1053::readReg(uint8_t addr) {
kayekss 0:708868399033 138 uint16_t word;
kayekss 0:708868399033 139
kayekss 0:708868399033 140 // If addr is out-of-range, return a beef
kayekss 0:708868399033 141 if (addr > 0x0f) {
kayekss 0:708868399033 142 return 0xbeef;
kayekss 0:708868399033 143 }
kayekss 0:708868399033 144
kayekss 0:708868399033 145 while (!dreq);
kayekss 0:708868399033 146 cs = 0;
kayekss 0:708868399033 147 spi.write(0x03); // Send a "Read SCI" instruction (03h)
kayekss 0:708868399033 148 spi.write(addr); // and target address
kayekss 0:708868399033 149 word = spi.write(0xff) << 8; // Receive high byte with dummy data FFh
kayekss 0:708868399033 150 word |= spi.write(0xff); // Receive low byte
kayekss 0:708868399033 151 while (!dreq);
kayekss 0:708868399033 152 cs = 1;
kayekss 0:708868399033 153 return word;
kayekss 0:708868399033 154 }