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 12:42:50 2015 +0000
Revision:
8:171effe49517
Parent:
7:b61cd12eabc5
Child:
9:1dd0ecaac8e5
fix func stop() for VS1033

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 7:b61cd12eabc5 97 /** SDI Send a data byte to VS1053. */
nameless129 7:b61cd12eabc5 98 void VS1053::sendDataByte(uint8_t data) {
nameless129 7:b61cd12eabc5 99 sdi_en();
nameless129 7:b61cd12eabc5 100
nameless129 7:b61cd12eabc5 101 while (!dreq);
nameless129 7:b61cd12eabc5 102 spi.write(data);
nameless129 7:b61cd12eabc5 103
nameless129 7:b61cd12eabc5 104 sdi_dis();
nameless129 7:b61cd12eabc5 105 }
nameless129 7:b61cd12eabc5 106
nameless129 7:b61cd12eabc5 107 /** SDI Send a data block specified as a pointer to VS1053.
kayekss 2:47ba7e2259cd 108 * @return Data length successfully sent.
kayekss 2:47ba7e2259cd 109 */
kayekss 4:6e0fb5342efa 110 size_t VS1053::sendDataBlock(uint8_t* data, size_t length) {
kayekss 5:cbf43dc9c947 111 size_t n, sizeSent = 0;
kayekss 0:708868399033 112
kayekss 4:6e0fb5342efa 113 if (!data || !length) return 0;
nameless129 7:b61cd12eabc5 114 sdi_en();
kayekss 5:cbf43dc9c947 115 while (length) {
kayekss 5:cbf43dc9c947 116 n = length < 32 ? length : 32;
kayekss 0:708868399033 117 while (!dreq);
nameless129 7:b61cd12eabc5 118 for (uint32_t i = 0; i < n; i++)
nameless129 7:b61cd12eabc5 119 {
kayekss 4:6e0fb5342efa 120 spi.write(*data++);
kayekss 5:cbf43dc9c947 121 sizeSent++; length--;
kayekss 0:708868399033 122 }
kayekss 0:708868399033 123 }
nameless129 7:b61cd12eabc5 124 sdi_dis();
kayekss 0:708868399033 125 return sizeSent;
kayekss 0:708868399033 126 }
kayekss 0:708868399033 127
kayekss 2:47ba7e2259cd 128 /** Send cancel request to VS1053.
kayekss 3:696c8e6744b2 129 * @return Zero at failure, non-zero at success.
kayekss 2:47ba7e2259cd 130 */
kayekss 0:708868399033 131 bool VS1053::sendCancel() {
kayekss 0:708868399033 132 uint16_t reg;
kayekss 0:708868399033 133
kayekss 0:708868399033 134 // Set SM_CANCEL bit
kayekss 0:708868399033 135 reg = readReg(SCI_MODE);
kayekss 0:708868399033 136 if (reg & 0x0008) {
kayekss 0:708868399033 137 // Abort if SM_CANCEL is still set
kayekss 3:696c8e6744b2 138 return false;
kayekss 0:708868399033 139 }
kayekss 0:708868399033 140 writeReg(SCI_MODE, reg | 0x0008);
kayekss 3:696c8e6744b2 141 return true;
kayekss 0:708868399033 142 }
kayekss 0:708868399033 143
kayekss 4:6e0fb5342efa 144 /** Attempt a termination of playing.
kayekss 4:6e0fb5342efa 145 * Please call this repeatedly during data stream tramsission until it successes.
kayekss 3:696c8e6744b2 146 * @return Zero at failure, non-zero at success.
kayekss 2:47ba7e2259cd 147 */
kayekss 0:708868399033 148 bool VS1053::stop() {
kayekss 5:cbf43dc9c947 149 size_t n, length;
nameless129 8:171effe49517 150
nameless129 8:171effe49517 151 // Send 0 2056 times
nameless129 8:171effe49517 152 length = 257;
kayekss 0:708868399033 153 while (length) {
kayekss 5:cbf43dc9c947 154 n = length < 32 ? length : 32;
nameless129 7:b61cd12eabc5 155 sdi_en();
kayekss 0:708868399033 156 while (!dreq);
kayekss 5:cbf43dc9c947 157 for (uint32_t i = 0; i < n; i++) {
nameless129 8:171effe49517 158 spi.write(0x00);
kayekss 5:cbf43dc9c947 159 length--;
kayekss 0:708868399033 160 }
nameless129 7:b61cd12eabc5 161 sdi_dis();
kayekss 0:708868399033 162 }
kayekss 0:708868399033 163 // Check if both HDAT0 and HDAT1 are cleared
kayekss 0:708868399033 164 return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000;
kayekss 0:708868399033 165 }
kayekss 0:708868399033 166
kayekss 2:47ba7e2259cd 167 /** Write to an SCI (Serial Control Interface) register entry. */
kayekss 0:708868399033 168 void VS1053::writeReg(uint8_t addr, uint16_t word) {
kayekss 0:708868399033 169 // If addr is out-of-range, do nothing
kayekss 0:708868399033 170 if (addr > 0x0f) {
kayekss 0:708868399033 171 return;
kayekss 0:708868399033 172 }
nameless129 7:b61cd12eabc5 173 sci_en();
kayekss 0:708868399033 174 while (!dreq);
kayekss 0:708868399033 175 spi.write(0x02); // Send a "Write SCI" instruction (02h),
kayekss 0:708868399033 176 spi.write(addr); // target address,
kayekss 0:708868399033 177 spi.write(word >> 8); // high byte,
kayekss 0:708868399033 178 spi.write(word & 0xff); // then low byte
nameless129 7:b61cd12eabc5 179 sci_dis();
kayekss 0:708868399033 180 }
kayekss 0:708868399033 181
kayekss 3:696c8e6744b2 182 /** Read an SCI (Serial Control Interface) register entry.
kayekss 3:696c8e6744b2 183 * @return Register value or 0000h when invalid address was specified.
kayekss 3:696c8e6744b2 184 */
kayekss 0:708868399033 185 uint16_t VS1053::readReg(uint8_t addr) {
kayekss 0:708868399033 186 uint16_t word;
kayekss 0:708868399033 187
kayekss 3:696c8e6744b2 188 // If addr is out-of-range, return 0000h
kayekss 0:708868399033 189 if (addr > 0x0f) {
kayekss 3:696c8e6744b2 190 return 0x0000;
kayekss 0:708868399033 191 }
nameless129 7:b61cd12eabc5 192 cs = 0;
kayekss 0:708868399033 193 while (!dreq);
kayekss 0:708868399033 194 spi.write(0x03); // Send a "Read SCI" instruction (03h)
kayekss 0:708868399033 195 spi.write(addr); // and target address
kayekss 0:708868399033 196 word = spi.write(0xff) << 8; // Receive high byte with dummy data FFh
kayekss 0:708868399033 197 word |= spi.write(0xff); // Receive low byte
kayekss 0:708868399033 198 cs = 1;
kayekss 0:708868399033 199 return word;
kayekss 0:708868399033 200 }
nameless129 7:b61cd12eabc5 201
nameless129 7:b61cd12eabc5 202 void VS1053::sine_test_activate(unsigned char wave)
nameless129 7:b61cd12eabc5 203 {
nameless129 7:b61cd12eabc5 204 hardwareReset();
nameless129 7:b61cd12eabc5 205 spi.format(8, 0);
nameless129 7:b61cd12eabc5 206 spi.frequency(1000000);
nameless129 7:b61cd12eabc5 207 writeReg(SCI_MODE,(SM_SDINEW+SM_TESTS));
nameless129 7:b61cd12eabc5 208 sdi_en();
nameless129 7:b61cd12eabc5 209
nameless129 7:b61cd12eabc5 210 while(dreq == 0)
nameless129 7:b61cd12eabc5 211 {
nameless129 7:b61cd12eabc5 212 } //wait unitl data request is high
nameless129 7:b61cd12eabc5 213 spi.write(0x53); //SDI write
nameless129 7:b61cd12eabc5 214 spi.write(0xEF); //SDI write
nameless129 7:b61cd12eabc5 215 spi.write(0x6E); //SDI write
nameless129 7:b61cd12eabc5 216 spi.write(wave); //SDI write
nameless129 7:b61cd12eabc5 217 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 218 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 219 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 220 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 221
nameless129 7:b61cd12eabc5 222 sdi_dis();
nameless129 7:b61cd12eabc5 223 }
nameless129 7:b61cd12eabc5 224 void VS1053::sine_test_deactivate(void)
nameless129 7:b61cd12eabc5 225 {
nameless129 7:b61cd12eabc5 226 sdi_en();
nameless129 7:b61cd12eabc5 227
nameless129 7:b61cd12eabc5 228 while(dreq == 0)
nameless129 7:b61cd12eabc5 229 {
nameless129 7:b61cd12eabc5 230 }
nameless129 7:b61cd12eabc5 231 spi.write(0x45); //SDI write
nameless129 7:b61cd12eabc5 232 spi.write(0x78); //SDI write
nameless129 7:b61cd12eabc5 233 spi.write(0x69); //SDI write
nameless129 7:b61cd12eabc5 234 spi.write(0x74); //SDI write
nameless129 7:b61cd12eabc5 235 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 236 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 237 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 238 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 239
nameless129 7:b61cd12eabc5 240 sdi_dis();
nameless129 7:b61cd12eabc5 241 }