modified for VS1033

Dependents:   11U68_MP3Player with TFTLCD 11U68_MP3Player-with-TFTLCD Mp3_1

Fork of VS1033 by en 129

Committer:
nameless129
Date:
Thu Jul 16 18:17:42 2015 +0000
Revision:
9:1dd0ecaac8e5
Parent:
8:171effe49517
Child:
10:a8594af40a50
add vol control

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kayekss 6:1f57fbd3aeb5 1 // ==================================================== Dec 21 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 {
nameless129 7:b61cd12eabc5 21 useSpiFreq = spiFrequency;
kayekss 0:708868399033 22
kayekss 0:708868399033 23 // Initialize outputs
kayekss 0:708868399033 24 cs = 1;
kayekss 0:708868399033 25 bsync = 1;
kayekss 0:708868399033 26 rst = 1;
kayekss 0:708868399033 27 }
kayekss 0:708868399033 28
kayekss 2:47ba7e2259cd 29 /** Destructor of class VS1053. */
kayekss 0:708868399033 30 VS1053::~VS1053() {
kayekss 0:708868399033 31 }
kayekss 0:708868399033 32
nameless129 7:b61cd12eabc5 33 //SCI enable
nameless129 7:b61cd12eabc5 34 void VS1053::sci_en(void)
nameless129 7:b61cd12eabc5 35 {
nameless129 7:b61cd12eabc5 36 cs = 1;
nameless129 7:b61cd12eabc5 37 bsync = 1;
nameless129 7:b61cd12eabc5 38 cs = 0;
nameless129 7:b61cd12eabc5 39 }
nameless129 7:b61cd12eabc5 40
nameless129 7:b61cd12eabc5 41 //SCI disable
nameless129 7:b61cd12eabc5 42 void VS1053::sci_dis(void)
nameless129 7:b61cd12eabc5 43 {
nameless129 7:b61cd12eabc5 44 cs = 1;
nameless129 7:b61cd12eabc5 45 }
nameless129 7:b61cd12eabc5 46
nameless129 7:b61cd12eabc5 47 //SDI enable
nameless129 7:b61cd12eabc5 48 void VS1053::sdi_en(void)
nameless129 7:b61cd12eabc5 49 {
nameless129 7:b61cd12eabc5 50 bsync = 1;
nameless129 7:b61cd12eabc5 51 cs = 1;
nameless129 7:b61cd12eabc5 52 bsync = 0;
nameless129 7:b61cd12eabc5 53 }
nameless129 7:b61cd12eabc5 54
nameless129 7:b61cd12eabc5 55 //SDI disable
nameless129 7:b61cd12eabc5 56 void VS1053::sdi_dis(void)
nameless129 7:b61cd12eabc5 57 {
nameless129 7:b61cd12eabc5 58 bsync = 1;
nameless129 7:b61cd12eabc5 59 }
nameless129 7:b61cd12eabc5 60
kayekss 2:47ba7e2259cd 61 /** Make a hardware reset by hitting VS1053's RESET pin. */
kayekss 0:708868399033 62 void VS1053::hardwareReset() {
kayekss 0:708868399033 63 rst = 0;
nameless129 7:b61cd12eabc5 64 wait(0.1);
kayekss 0:708868399033 65 rst = 1;
nameless129 7:b61cd12eabc5 66 wait(0.1);
kayekss 0:708868399033 67 }
kayekss 0:708868399033 68
nameless129 7:b61cd12eabc5 69 //Serial Command Interface(SCI) init
nameless129 7:b61cd12eabc5 70 void VS1053::sci_init()
nameless129 7:b61cd12eabc5 71 {
nameless129 7:b61cd12eabc5 72 spi.format(8, 0);
nameless129 7:b61cd12eabc5 73 spi.frequency(1000000);
nameless129 7:b61cd12eabc5 74
nameless129 7:b61cd12eabc5 75 cs = 0;
nameless129 7:b61cd12eabc5 76 for(int i=0; i<4; i++)
nameless129 7:b61cd12eabc5 77 {
nameless129 7:b61cd12eabc5 78 spi.write(0xFF); //clock the chip a bit
nameless129 7:b61cd12eabc5 79 }
nameless129 7:b61cd12eabc5 80 cs = 1;
nameless129 7:b61cd12eabc5 81 bsync = 1;
nameless129 7:b61cd12eabc5 82 wait_us(5);
nameless129 7:b61cd12eabc5 83 writeReg(SCI_MODE,(SM_SDINEW));
nameless129 7:b61cd12eabc5 84 writeReg(SCI_CLOCKF, 0x9800);
nameless129 7:b61cd12eabc5 85 }
nameless129 7:b61cd12eabc5 86
nameless129 7:b61cd12eabc5 87 //Serial Data Interface(SDI) init
nameless129 7:b61cd12eabc5 88 void VS1053::sdi_init()
nameless129 7:b61cd12eabc5 89 {
nameless129 7:b61cd12eabc5 90 spi.format(8, 0);
nameless129 7:b61cd12eabc5 91 spi.frequency(useSpiFreq);
nameless129 7:b61cd12eabc5 92
nameless129 7:b61cd12eabc5 93 cs = 1;
kayekss 0:708868399033 94 bsync = 1;
kayekss 0:708868399033 95 }
kayekss 0:708868399033 96
nameless129 9:1dd0ecaac8e5 97 void VS1053::VolControl(uint16_t vol)
nameless129 9:1dd0ecaac8e5 98 {
nameless129 9:1dd0ecaac8e5 99 writeReg(SCI_VOL,vol);
nameless129 9:1dd0ecaac8e5 100 }
nameless129 9:1dd0ecaac8e5 101
nameless129 9:1dd0ecaac8e5 102
nameless129 7:b61cd12eabc5 103 /** SDI Send a data byte to VS1053. */
nameless129 7:b61cd12eabc5 104 void VS1053::sendDataByte(uint8_t data) {
nameless129 7:b61cd12eabc5 105 sdi_en();
nameless129 7:b61cd12eabc5 106
nameless129 7:b61cd12eabc5 107 while (!dreq);
nameless129 7:b61cd12eabc5 108 spi.write(data);
nameless129 7:b61cd12eabc5 109
nameless129 7:b61cd12eabc5 110 sdi_dis();
nameless129 7:b61cd12eabc5 111 }
nameless129 7:b61cd12eabc5 112
nameless129 7:b61cd12eabc5 113 /** SDI Send a data block specified as a pointer to VS1053.
kayekss 2:47ba7e2259cd 114 * @return Data length successfully sent.
kayekss 2:47ba7e2259cd 115 */
kayekss 4:6e0fb5342efa 116 size_t VS1053::sendDataBlock(uint8_t* data, size_t length) {
kayekss 5:cbf43dc9c947 117 size_t n, sizeSent = 0;
kayekss 0:708868399033 118
kayekss 4:6e0fb5342efa 119 if (!data || !length) return 0;
nameless129 7:b61cd12eabc5 120 sdi_en();
kayekss 5:cbf43dc9c947 121 while (length) {
kayekss 5:cbf43dc9c947 122 n = length < 32 ? length : 32;
kayekss 0:708868399033 123 while (!dreq);
nameless129 7:b61cd12eabc5 124 for (uint32_t i = 0; i < n; i++)
nameless129 7:b61cd12eabc5 125 {
kayekss 4:6e0fb5342efa 126 spi.write(*data++);
kayekss 5:cbf43dc9c947 127 sizeSent++; length--;
kayekss 0:708868399033 128 }
kayekss 0:708868399033 129 }
nameless129 7:b61cd12eabc5 130 sdi_dis();
kayekss 0:708868399033 131 return sizeSent;
kayekss 0:708868399033 132 }
kayekss 0:708868399033 133
kayekss 2:47ba7e2259cd 134 /** Send cancel request to VS1053.
kayekss 3:696c8e6744b2 135 * @return Zero at failure, non-zero at success.
kayekss 2:47ba7e2259cd 136 */
kayekss 0:708868399033 137 bool VS1053::sendCancel() {
kayekss 0:708868399033 138 uint16_t reg;
kayekss 0:708868399033 139
kayekss 0:708868399033 140 // Set SM_CANCEL bit
kayekss 0:708868399033 141 reg = readReg(SCI_MODE);
kayekss 0:708868399033 142 if (reg & 0x0008) {
kayekss 0:708868399033 143 // Abort if SM_CANCEL is still set
kayekss 3:696c8e6744b2 144 return false;
kayekss 0:708868399033 145 }
kayekss 0:708868399033 146 writeReg(SCI_MODE, reg | 0x0008);
kayekss 3:696c8e6744b2 147 return true;
kayekss 0:708868399033 148 }
kayekss 0:708868399033 149
kayekss 4:6e0fb5342efa 150 /** Attempt a termination of playing.
kayekss 4:6e0fb5342efa 151 * Please call this repeatedly during data stream tramsission until it successes.
kayekss 3:696c8e6744b2 152 * @return Zero at failure, non-zero at success.
kayekss 2:47ba7e2259cd 153 */
kayekss 0:708868399033 154 bool VS1053::stop() {
kayekss 5:cbf43dc9c947 155 size_t n, length;
nameless129 8:171effe49517 156
nameless129 8:171effe49517 157 // Send 0 2056 times
nameless129 8:171effe49517 158 length = 257;
kayekss 0:708868399033 159 while (length) {
kayekss 5:cbf43dc9c947 160 n = length < 32 ? length : 32;
nameless129 7:b61cd12eabc5 161 sdi_en();
kayekss 0:708868399033 162 while (!dreq);
kayekss 5:cbf43dc9c947 163 for (uint32_t i = 0; i < n; i++) {
nameless129 8:171effe49517 164 spi.write(0x00);
kayekss 5:cbf43dc9c947 165 length--;
kayekss 0:708868399033 166 }
nameless129 7:b61cd12eabc5 167 sdi_dis();
kayekss 0:708868399033 168 }
kayekss 0:708868399033 169 // Check if both HDAT0 and HDAT1 are cleared
kayekss 0:708868399033 170 return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000;
kayekss 0:708868399033 171 }
kayekss 0:708868399033 172
kayekss 2:47ba7e2259cd 173 /** Write to an SCI (Serial Control Interface) register entry. */
kayekss 0:708868399033 174 void VS1053::writeReg(uint8_t addr, uint16_t word) {
kayekss 0:708868399033 175 // If addr is out-of-range, do nothing
kayekss 0:708868399033 176 if (addr > 0x0f) {
kayekss 0:708868399033 177 return;
kayekss 0:708868399033 178 }
nameless129 7:b61cd12eabc5 179 sci_en();
kayekss 0:708868399033 180 while (!dreq);
kayekss 0:708868399033 181 spi.write(0x02); // Send a "Write SCI" instruction (02h),
kayekss 0:708868399033 182 spi.write(addr); // target address,
kayekss 0:708868399033 183 spi.write(word >> 8); // high byte,
kayekss 0:708868399033 184 spi.write(word & 0xff); // then low byte
nameless129 7:b61cd12eabc5 185 sci_dis();
kayekss 0:708868399033 186 }
kayekss 0:708868399033 187
kayekss 3:696c8e6744b2 188 /** Read an SCI (Serial Control Interface) register entry.
kayekss 3:696c8e6744b2 189 * @return Register value or 0000h when invalid address was specified.
kayekss 3:696c8e6744b2 190 */
kayekss 0:708868399033 191 uint16_t VS1053::readReg(uint8_t addr) {
kayekss 0:708868399033 192 uint16_t word;
kayekss 0:708868399033 193
kayekss 3:696c8e6744b2 194 // If addr is out-of-range, return 0000h
kayekss 0:708868399033 195 if (addr > 0x0f) {
kayekss 3:696c8e6744b2 196 return 0x0000;
kayekss 0:708868399033 197 }
nameless129 7:b61cd12eabc5 198 cs = 0;
kayekss 0:708868399033 199 while (!dreq);
kayekss 0:708868399033 200 spi.write(0x03); // Send a "Read SCI" instruction (03h)
kayekss 0:708868399033 201 spi.write(addr); // and target address
kayekss 0:708868399033 202 word = spi.write(0xff) << 8; // Receive high byte with dummy data FFh
kayekss 0:708868399033 203 word |= spi.write(0xff); // Receive low byte
kayekss 0:708868399033 204 cs = 1;
kayekss 0:708868399033 205 return word;
kayekss 0:708868399033 206 }
nameless129 7:b61cd12eabc5 207
nameless129 7:b61cd12eabc5 208 void VS1053::sine_test_activate(unsigned char wave)
nameless129 7:b61cd12eabc5 209 {
nameless129 7:b61cd12eabc5 210 hardwareReset();
nameless129 7:b61cd12eabc5 211 spi.format(8, 0);
nameless129 7:b61cd12eabc5 212 spi.frequency(1000000);
nameless129 7:b61cd12eabc5 213 writeReg(SCI_MODE,(SM_SDINEW+SM_TESTS));
nameless129 7:b61cd12eabc5 214 sdi_en();
nameless129 7:b61cd12eabc5 215
nameless129 7:b61cd12eabc5 216 while(dreq == 0)
nameless129 7:b61cd12eabc5 217 {
nameless129 7:b61cd12eabc5 218 } //wait unitl data request is high
nameless129 7:b61cd12eabc5 219 spi.write(0x53); //SDI write
nameless129 7:b61cd12eabc5 220 spi.write(0xEF); //SDI write
nameless129 7:b61cd12eabc5 221 spi.write(0x6E); //SDI write
nameless129 7:b61cd12eabc5 222 spi.write(wave); //SDI write
nameless129 7:b61cd12eabc5 223 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 224 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 225 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 226 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 227
nameless129 7:b61cd12eabc5 228 sdi_dis();
nameless129 7:b61cd12eabc5 229 }
nameless129 7:b61cd12eabc5 230 void VS1053::sine_test_deactivate(void)
nameless129 7:b61cd12eabc5 231 {
nameless129 7:b61cd12eabc5 232 sdi_en();
nameless129 7:b61cd12eabc5 233
nameless129 7:b61cd12eabc5 234 while(dreq == 0)
nameless129 7:b61cd12eabc5 235 {
nameless129 7:b61cd12eabc5 236 }
nameless129 7:b61cd12eabc5 237 spi.write(0x45); //SDI write
nameless129 7:b61cd12eabc5 238 spi.write(0x78); //SDI write
nameless129 7:b61cd12eabc5 239 spi.write(0x69); //SDI write
nameless129 7:b61cd12eabc5 240 spi.write(0x74); //SDI write
nameless129 7:b61cd12eabc5 241 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 242 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 243 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 244 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 245
nameless129 7:b61cd12eabc5 246 sdi_dis();
nameless129 7:b61cd12eabc5 247 }