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 30 06:52:54 2015 +0000
Revision:
11:da08a7b0947d
Parent:
10:a8594af40a50
fix stop func

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,
nameless129 10:a8594af40a50 12 PinName csPin, PinName dcsPin, 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),
nameless129 10:a8594af40a50 17 dcs(dcsPin),
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;
nameless129 10:a8594af40a50 25 dcs = 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 10:a8594af40a50 36 dcs = 1;
nameless129 7:b61cd12eabc5 37 cs = 0;
nameless129 7:b61cd12eabc5 38 }
nameless129 7:b61cd12eabc5 39
nameless129 7:b61cd12eabc5 40 //SCI disable
nameless129 7:b61cd12eabc5 41 void VS1053::sci_dis(void)
nameless129 7:b61cd12eabc5 42 {
nameless129 10:a8594af40a50 43 dcs = 1;
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 cs = 1;
nameless129 10:a8594af40a50 51 dcs = 0;
nameless129 7:b61cd12eabc5 52 }
nameless129 7:b61cd12eabc5 53
nameless129 7:b61cd12eabc5 54 //SDI disable
nameless129 7:b61cd12eabc5 55 void VS1053::sdi_dis(void)
nameless129 7:b61cd12eabc5 56 {
nameless129 10:a8594af40a50 57 cs = 1;
nameless129 10:a8594af40a50 58 dcs = 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 10:a8594af40a50 81 dcs = 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 10:a8594af40a50 93 writeReg(SCI_CLOCKF, 0xc000); // SC_MULT=6 (4.0x)
nameless129 10:a8594af40a50 94 wait(0.01);
nameless129 10:a8594af40a50 95
nameless129 7:b61cd12eabc5 96 cs = 1;
nameless129 10:a8594af40a50 97 dcs = 1;
kayekss 0:708868399033 98 }
kayekss 0:708868399033 99
nameless129 9:1dd0ecaac8e5 100 void VS1053::VolControl(uint16_t vol)
nameless129 9:1dd0ecaac8e5 101 {
nameless129 9:1dd0ecaac8e5 102 writeReg(SCI_VOL,vol);
nameless129 9:1dd0ecaac8e5 103 }
nameless129 9:1dd0ecaac8e5 104
nameless129 9:1dd0ecaac8e5 105
nameless129 7:b61cd12eabc5 106 /** SDI Send a data byte to VS1053. */
nameless129 7:b61cd12eabc5 107 void VS1053::sendDataByte(uint8_t data) {
nameless129 7:b61cd12eabc5 108 sdi_en();
nameless129 7:b61cd12eabc5 109
nameless129 7:b61cd12eabc5 110 while (!dreq);
nameless129 7:b61cd12eabc5 111 spi.write(data);
nameless129 7:b61cd12eabc5 112
nameless129 7:b61cd12eabc5 113 sdi_dis();
nameless129 7:b61cd12eabc5 114 }
nameless129 7:b61cd12eabc5 115
nameless129 10:a8594af40a50 116 bool VS1053::checkDREQ()
nameless129 10:a8594af40a50 117 {
nameless129 10:a8594af40a50 118 bool dreq_return = 0;
nameless129 10:a8594af40a50 119 dreq_return = dreq;
nameless129 10:a8594af40a50 120 return dreq_return;
nameless129 10:a8594af40a50 121 }
nameless129 10:a8594af40a50 122
nameless129 7:b61cd12eabc5 123 /** SDI Send a data block specified as a pointer to VS1053.
kayekss 2:47ba7e2259cd 124 * @return Data length successfully sent.
kayekss 2:47ba7e2259cd 125 */
kayekss 4:6e0fb5342efa 126 size_t VS1053::sendDataBlock(uint8_t* data, size_t length) {
kayekss 5:cbf43dc9c947 127 size_t n, sizeSent = 0;
kayekss 0:708868399033 128
kayekss 4:6e0fb5342efa 129 if (!data || !length) return 0;
nameless129 7:b61cd12eabc5 130 sdi_en();
kayekss 5:cbf43dc9c947 131 while (length) {
kayekss 5:cbf43dc9c947 132 n = length < 32 ? length : 32;
nameless129 7:b61cd12eabc5 133 for (uint32_t i = 0; i < n; i++)
nameless129 7:b61cd12eabc5 134 {
nameless129 10:a8594af40a50 135 while (!dreq);
kayekss 4:6e0fb5342efa 136 spi.write(*data++);
kayekss 5:cbf43dc9c947 137 sizeSent++; length--;
kayekss 0:708868399033 138 }
kayekss 0:708868399033 139 }
nameless129 7:b61cd12eabc5 140 sdi_dis();
kayekss 0:708868399033 141 return sizeSent;
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() {
nameless129 11:da08a7b0947d 149 uint16_t n, length;
nameless129 8:171effe49517 150
nameless129 11:da08a7b0947d 151 // Send 0 2052 byte
nameless129 11:da08a7b0947d 152 length = 256;
nameless129 10:a8594af40a50 153 sdi_en();
kayekss 0:708868399033 154 while (length) {
kayekss 5:cbf43dc9c947 155 n = length < 32 ? length : 32;
kayekss 5:cbf43dc9c947 156 for (uint32_t i = 0; i < n; i++) {
nameless129 10:a8594af40a50 157 while (!dreq);
nameless129 8:171effe49517 158 spi.write(0x00);
kayekss 5:cbf43dc9c947 159 length--;
kayekss 0:708868399033 160 }
kayekss 0:708868399033 161 }
nameless129 10:a8594af40a50 162 sdi_dis();
nameless129 11:da08a7b0947d 163
nameless129 11:da08a7b0947d 164 writeReg(SCI_MODE,( (SM_SDINEW)|(SM_RESET) ) );
nameless129 11:da08a7b0947d 165 writeReg(SCI_CLOCKF, 0x9800);
nameless129 11:da08a7b0947d 166
kayekss 0:708868399033 167 // Check if both HDAT0 and HDAT1 are cleared
kayekss 0:708868399033 168 return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000;
kayekss 0:708868399033 169 }
kayekss 0:708868399033 170
kayekss 2:47ba7e2259cd 171 /** Write to an SCI (Serial Control Interface) register entry. */
kayekss 0:708868399033 172 void VS1053::writeReg(uint8_t addr, uint16_t word) {
kayekss 0:708868399033 173 // If addr is out-of-range, do nothing
kayekss 0:708868399033 174 if (addr > 0x0f) {
kayekss 0:708868399033 175 return;
kayekss 0:708868399033 176 }
nameless129 7:b61cd12eabc5 177 sci_en();
kayekss 0:708868399033 178 while (!dreq);
kayekss 0:708868399033 179 spi.write(0x02); // Send a "Write SCI" instruction (02h),
kayekss 0:708868399033 180 spi.write(addr); // target address,
kayekss 0:708868399033 181 spi.write(word >> 8); // high byte,
kayekss 0:708868399033 182 spi.write(word & 0xff); // then low byte
nameless129 7:b61cd12eabc5 183 sci_dis();
kayekss 0:708868399033 184 }
kayekss 0:708868399033 185
kayekss 3:696c8e6744b2 186 /** Read an SCI (Serial Control Interface) register entry.
kayekss 3:696c8e6744b2 187 * @return Register value or 0000h when invalid address was specified.
kayekss 3:696c8e6744b2 188 */
kayekss 0:708868399033 189 uint16_t VS1053::readReg(uint8_t addr) {
kayekss 0:708868399033 190 uint16_t word;
kayekss 0:708868399033 191
kayekss 3:696c8e6744b2 192 // If addr is out-of-range, return 0000h
kayekss 0:708868399033 193 if (addr > 0x0f) {
kayekss 3:696c8e6744b2 194 return 0x0000;
kayekss 0:708868399033 195 }
nameless129 10:a8594af40a50 196 sci_en();
kayekss 0:708868399033 197 while (!dreq);
kayekss 0:708868399033 198 spi.write(0x03); // Send a "Read SCI" instruction (03h)
kayekss 0:708868399033 199 spi.write(addr); // and target address
kayekss 0:708868399033 200 word = spi.write(0xff) << 8; // Receive high byte with dummy data FFh
kayekss 0:708868399033 201 word |= spi.write(0xff); // Receive low byte
nameless129 10:a8594af40a50 202 sci_dis();
kayekss 0:708868399033 203 return word;
kayekss 0:708868399033 204 }
nameless129 7:b61cd12eabc5 205
nameless129 7:b61cd12eabc5 206 void VS1053::sine_test_activate(unsigned char wave)
nameless129 7:b61cd12eabc5 207 {
nameless129 7:b61cd12eabc5 208 hardwareReset();
nameless129 7:b61cd12eabc5 209 spi.format(8, 0);
nameless129 7:b61cd12eabc5 210 spi.frequency(1000000);
nameless129 7:b61cd12eabc5 211 writeReg(SCI_MODE,(SM_SDINEW+SM_TESTS));
nameless129 7:b61cd12eabc5 212 sdi_en();
nameless129 7:b61cd12eabc5 213
nameless129 7:b61cd12eabc5 214 while(dreq == 0)
nameless129 7:b61cd12eabc5 215 {
nameless129 7:b61cd12eabc5 216 } //wait unitl data request is high
nameless129 7:b61cd12eabc5 217 spi.write(0x53); //SDI write
nameless129 7:b61cd12eabc5 218 spi.write(0xEF); //SDI write
nameless129 7:b61cd12eabc5 219 spi.write(0x6E); //SDI write
nameless129 7:b61cd12eabc5 220 spi.write(wave); //SDI write
nameless129 7:b61cd12eabc5 221 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 222 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 223 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 224 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 225
nameless129 7:b61cd12eabc5 226 sdi_dis();
nameless129 7:b61cd12eabc5 227 }
nameless129 7:b61cd12eabc5 228 void VS1053::sine_test_deactivate(void)
nameless129 7:b61cd12eabc5 229 {
nameless129 7:b61cd12eabc5 230 sdi_en();
nameless129 7:b61cd12eabc5 231
nameless129 7:b61cd12eabc5 232 while(dreq == 0)
nameless129 7:b61cd12eabc5 233 {
nameless129 7:b61cd12eabc5 234 }
nameless129 7:b61cd12eabc5 235 spi.write(0x45); //SDI write
nameless129 7:b61cd12eabc5 236 spi.write(0x78); //SDI write
nameless129 7:b61cd12eabc5 237 spi.write(0x69); //SDI write
nameless129 7:b61cd12eabc5 238 spi.write(0x74); //SDI write
nameless129 7:b61cd12eabc5 239 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 240 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 241 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 242 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 243
nameless129 7:b61cd12eabc5 244 sdi_dis();
nameless129 7:b61cd12eabc5 245 }