modified for VS1033

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

Fork of VS1033 by en 129

Committer:
nameless129
Date:
Sat Jul 11 19:42:28 2015 +0000
Revision:
7:b61cd12eabc5
Parent:
6:1f57fbd3aeb5
Child:
8:171effe49517
first commit;

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 0:708868399033 149 uint16_t reg;
kayekss 5:cbf43dc9c947 150 uint8_t endFillByte;
kayekss 5:cbf43dc9c947 151 size_t n, length;
kayekss 0:708868399033 152
kayekss 0:708868399033 153 // If SM_CANCEL is still set, do nothing
kayekss 0:708868399033 154 reg = readReg(SCI_MODE);
kayekss 0:708868399033 155 if (reg & 0x0008) {
kayekss 3:696c8e6744b2 156 return false;
kayekss 0:708868399033 157 }
kayekss 0:708868399033 158
kayekss 0:708868399033 159 // Read endFillByte from XRAM <1E06h>
kayekss 0:708868399033 160 writeReg(SCI_WRAMADDR, 0x1e06);
kayekss 0:708868399033 161 reg = readReg(SCI_WRAM);
kayekss 0:708868399033 162
kayekss 0:708868399033 163 // Send lower 8 bits of endFillByte 2,052 times
kayekss 0:708868399033 164 endFillByte = reg & 0xff;
kayekss 0:708868399033 165 length = 2052;
kayekss 0:708868399033 166 while (length) {
kayekss 5:cbf43dc9c947 167 n = length < 32 ? length : 32;
nameless129 7:b61cd12eabc5 168 sdi_en();
kayekss 0:708868399033 169 while (!dreq);
kayekss 5:cbf43dc9c947 170 for (uint32_t i = 0; i < n; i++) {
kayekss 0:708868399033 171 spi.write(endFillByte);
kayekss 5:cbf43dc9c947 172 length--;
kayekss 0:708868399033 173 }
nameless129 7:b61cd12eabc5 174 sdi_dis();
kayekss 0:708868399033 175 }
kayekss 0:708868399033 176 // Check if both HDAT0 and HDAT1 are cleared
kayekss 0:708868399033 177 return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000;
kayekss 0:708868399033 178 }
kayekss 0:708868399033 179
kayekss 2:47ba7e2259cd 180 /** Write to an SCI (Serial Control Interface) register entry. */
kayekss 0:708868399033 181 void VS1053::writeReg(uint8_t addr, uint16_t word) {
kayekss 0:708868399033 182 // If addr is out-of-range, do nothing
kayekss 0:708868399033 183 if (addr > 0x0f) {
kayekss 0:708868399033 184 return;
kayekss 0:708868399033 185 }
nameless129 7:b61cd12eabc5 186 sci_en();
kayekss 0:708868399033 187 while (!dreq);
kayekss 0:708868399033 188 spi.write(0x02); // Send a "Write SCI" instruction (02h),
kayekss 0:708868399033 189 spi.write(addr); // target address,
kayekss 0:708868399033 190 spi.write(word >> 8); // high byte,
kayekss 0:708868399033 191 spi.write(word & 0xff); // then low byte
nameless129 7:b61cd12eabc5 192 sci_dis();
kayekss 0:708868399033 193 }
kayekss 0:708868399033 194
kayekss 3:696c8e6744b2 195 /** Read an SCI (Serial Control Interface) register entry.
kayekss 3:696c8e6744b2 196 * @return Register value or 0000h when invalid address was specified.
kayekss 3:696c8e6744b2 197 */
kayekss 0:708868399033 198 uint16_t VS1053::readReg(uint8_t addr) {
kayekss 0:708868399033 199 uint16_t word;
kayekss 0:708868399033 200
kayekss 3:696c8e6744b2 201 // If addr is out-of-range, return 0000h
kayekss 0:708868399033 202 if (addr > 0x0f) {
kayekss 3:696c8e6744b2 203 return 0x0000;
kayekss 0:708868399033 204 }
nameless129 7:b61cd12eabc5 205 cs = 0;
kayekss 0:708868399033 206 while (!dreq);
kayekss 0:708868399033 207 spi.write(0x03); // Send a "Read SCI" instruction (03h)
kayekss 0:708868399033 208 spi.write(addr); // and target address
kayekss 0:708868399033 209 word = spi.write(0xff) << 8; // Receive high byte with dummy data FFh
kayekss 0:708868399033 210 word |= spi.write(0xff); // Receive low byte
kayekss 0:708868399033 211 cs = 1;
kayekss 0:708868399033 212 return word;
kayekss 0:708868399033 213 }
nameless129 7:b61cd12eabc5 214
nameless129 7:b61cd12eabc5 215 void VS1053::sine_test_activate(unsigned char wave)
nameless129 7:b61cd12eabc5 216 {
nameless129 7:b61cd12eabc5 217 hardwareReset();
nameless129 7:b61cd12eabc5 218 spi.format(8, 0);
nameless129 7:b61cd12eabc5 219 spi.frequency(1000000);
nameless129 7:b61cd12eabc5 220 writeReg(SCI_MODE,(SM_SDINEW+SM_TESTS));
nameless129 7:b61cd12eabc5 221 sdi_en();
nameless129 7:b61cd12eabc5 222
nameless129 7:b61cd12eabc5 223 while(dreq == 0)
nameless129 7:b61cd12eabc5 224 {
nameless129 7:b61cd12eabc5 225 } //wait unitl data request is high
nameless129 7:b61cd12eabc5 226 spi.write(0x53); //SDI write
nameless129 7:b61cd12eabc5 227 spi.write(0xEF); //SDI write
nameless129 7:b61cd12eabc5 228 spi.write(0x6E); //SDI write
nameless129 7:b61cd12eabc5 229 spi.write(wave); //SDI write
nameless129 7:b61cd12eabc5 230 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 231 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 232 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 233 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 234
nameless129 7:b61cd12eabc5 235 sdi_dis();
nameless129 7:b61cd12eabc5 236 }
nameless129 7:b61cd12eabc5 237 void VS1053::sine_test_deactivate(void)
nameless129 7:b61cd12eabc5 238 {
nameless129 7:b61cd12eabc5 239 sdi_en();
nameless129 7:b61cd12eabc5 240
nameless129 7:b61cd12eabc5 241 while(dreq == 0)
nameless129 7:b61cd12eabc5 242 {
nameless129 7:b61cd12eabc5 243 }
nameless129 7:b61cd12eabc5 244 spi.write(0x45); //SDI write
nameless129 7:b61cd12eabc5 245 spi.write(0x78); //SDI write
nameless129 7:b61cd12eabc5 246 spi.write(0x69); //SDI write
nameless129 7:b61cd12eabc5 247 spi.write(0x74); //SDI write
nameless129 7:b61cd12eabc5 248 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 249 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 250 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 251 spi.write(0x00); //filler byte
nameless129 7:b61cd12eabc5 252
nameless129 7:b61cd12eabc5 253 sdi_dis();
nameless129 7:b61cd12eabc5 254 }