vs1053_avr_renesas_uno 0.1.0
Arduino Library for VS1053 shield
Loading...
Searching...
No Matches
vs1053_avr_renesas_uno.cpp
Go to the documentation of this file.
1
9// Include the SPI library.
10#include "SPI.h"
11// Excludes the avr/pgmspace library as it is incompatible with the Renesas architecture.
12#if !defined(ARDUINO_ARCH_RENESAS)
13// The avr/pgmspace library for storing the LUT in program flash memory instead of SRAM.
14#include <avr/pgmspace.h>
15#endif
16
27static const uint16_t bitrate_table[15][6] PROGMEM = {
28 { 0, 0, 0, 0, 0, 0}, //0000
29 { 32, 32, 32, 32, 8, 8}, //0001
30 { 64, 48, 40, 48, 16, 16}, //0010
31 { 96, 56, 48, 56, 24, 24}, //0011
32 {128, 64, 56, 64, 32, 32}, //0100
33 {160, 80, 64, 80, 40, 40}, //0101
34 {192, 96, 80, 96, 48, 48}, //0110
35 {224,112, 96,112, 56, 56}, //0111
36 {256,128,112,128, 64, 64}, //1000
37 {288,160,128,144, 80, 80}, //1001
38 {320,192,160,160, 96, 69}, //1010
39 {352,224,192,176,112,112}, //1011
40 {384,256,224,192,128,128}, //1100
41 {416,320,256,224,144,144}, //1101
42 {448,384,320,256,160,160} //1110
43 };
44
45/*
46 * Format of a MIDI file into a char arrar. Simply one note on and then off.
47*/
48// MIDI Event Specifics.
49#define MIDI_NOTE_ON 9
50#define MIDI_NOTE_OFF 8
51
52// MIDI File structure.
53// Header Chunk.
54#define MIDI_HDR_CHUNK_ID 0x4D, 0x54, 0x68, 0x64 // const for MIDI
55#define MIDI_CHUNKSIZE 0, 0, 0, 6
56#define MIDI_FORMAT 0, 0 // VSdsp only support Format 0!.
57#define MIDI_NUMBER_OF_TRACKS 0, 1 // ergo must be 1 track.
58#define MIDI_TIME_DIVISION 0, 96
59// Track Chunk.
60#define MIDI_TRACK_CHUNK_ID 0x4D, 0x54, 0x72, 0x6B // const for MIDI.
61#define MIDI_CHUNK_SIZE 0, 0, 0, sizeof(MIDI_EVENT_NOTE_ON) + sizeof(MIDI_EVENT_NOTE_OFF) + sizeof(MIDI_END_OF_TRACK) // hard coded with zero padded.
62// Events.
63#define MIDI_EVENT_NOTE_ON 0, (MIDI_NOTE_ON<<4) + MIDI_CHANNEL, MIDI_NOTE_NUMBER, MIDI_INTENSITY
64#define MIDI_EVENT_NOTE_OFF MIDI_NOTE_DURATION, (MIDI_NOTE_OFF<<4) + MIDI_CHANNEL, MIDI_NOTE_NUMBER, MIDI_INTENSITY
65//
66#define MIDI_END_OF_TRACK 0, 0xFF, 0x2F, 0
67
68/*
69 * Retrieves the interrupt identifier corresponding to the MP3_DREQ pin.
70 * If the pin is valid for interrupts, its IRQ number is assigned.
71 */
72int8_t irq = digitalPinToInterrupt(MP3_DREQ);
73
91
92//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
93/* Initialize static classes and variables.
94 */
95
99SdFile vs1053::track;
100
105
109uint32_t vs1053::spi_Max_Rate;
110
111// Only needed for specific means of refilling.
112#if defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer
113 SimpleTimer timer;
114 int timerId_mp3;
115#endif
116
117// Buffer for music.
118uint8_t vs1053::mp3DataBuffer[32];
119
120//------------------------------------------------------------------------------
139uint8_t vs1053::begin() {
140
141/*
142 This test is to assit in the migration from versions prior to 1.01.00.
143 It is not really needed, simply prints an easy error, to better assist.
144 If you are using SdFat objects other than "sd" the below may be omitted
145 or whant to save 222 bytes of Flash space.
146 */
147#if (1)
148if (int8_t(sd.vol()->fatType()) == 0) {
149 Serial.println(F("If you get this error, you likely do not have a sd.begin in the main sketch, See Trouble Shooting Guide!"));
150 Serial.println(F("http://mpflaga.github.com/Sparkfun-MP3-Player-Shield-Arduino-Library/#Troubleshooting"));
151}
152#endif
153
154 pinMode(MP3_DREQ, INPUT);
155 pinMode(MP3_XCS, OUTPUT);
156 pinMode(MP3_XDCS, OUTPUT);
157 pinMode(MP3_RESET, OUTPUT);
158
159#if PERF_MON_PIN != -1
160 pinMode(PERF_MON_PIN, OUTPUT);
161 digitalWrite(PERF_MON_PIN,HIGH);
162#endif
163
164 cs_high(); // MP3_XCS, Init Control Select to deselected.
165 dcs_high(); // MP3_XDCS, Init Data Select to deselected.
166 digitalWrite(MP3_RESET, LOW); // put VS1053 into hardware reset.
167
169
170 uint8_t result = vs_init();
171 if(result) {
172 return result;
173 }
174
175#if defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_Timer1
176 Timer1.initialize(MP3_REFILL_PERIOD);
177#elif defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer
178 timerId_mp3 = timer.setInterval(MP3_REFILL_PERIOD, refill);
179 timer.disable(timerId_mp3);
180#endif
181
182 return 0;
183}
184
195
196 stopTrack(); // stop and CLOSE any open tracks.
197 disableRefill(); // shut down specific interrupts.
198 cs_high(); // MP3_XCS, Init Control Select to deselected.
199 dcs_high(); // MP3_XDCS, Init Data Select to deselected.
200
201 // Most importantly...
202 digitalWrite(MP3_RESET, LOW); // put VS1053 into hardware reset.
203
205}
206
207//------------------------------------------------------------------------------
228
229 // Initialize VS1053 chip.
230
231 // Reset if not already.
232 delay(100); // keep clear of anything prior.
233 digitalWrite(MP3_RESET, LOW); // shut down VS1053.
234 delay(100);
235
236 // Bring out of reset.
237 digitalWrite(MP3_RESET, HIGH); // bring up VS1053.
238
239 // From section 7.6 of datasheet, max SCI reads are CLKI/7.
240 // Assuming CLKI = 12.288MgHz for Shield and 16.0MgHz for Arduino
241 // the VS1053's internal clock multiplier SCI_CLOCKF:SC_MULT is 1.0x after power up.
242 // For a maximum SPI rate of 1.8MgHz = (CLKI/7) = (12.288/7) the VS1053's default.
243
244 // Warning:
245 // Note that SPI transfers interleave between SdCard and VS10xx.
246 // Where Sd2Card.cpp sets SPCR & SPSR each and every transfer.
247
248 // The SDfatlib using SPI_FULL_SPEED results in an 8MHz SPI clock rate,
249 // faster than initial allowed SPI rate of 1.8MgHz.
250
251 // Set initial MP3's SPI to safe rate.
252 spi_Max_Rate = 1000000; // 1 MHz for initializations.
253 delay(10);
254
255 // Let's check the status of the VS1053.
256 int MP3Mode = Mp3ReadRegister(SCI_MODE);
257
258/* // Debug information disabled.
259 Serial.print(F("SCI_Mode (0x4800) = 0x"));
260 Serial.println(MP3Mode, HEX);
261
262 int MP3Status = Mp3ReadRegister(SCI_Status);
263 Serial.print(F("SCI_Status (0x48) = 0x"));
264 Serial.println(MP3Status, HEX);
265
266 int MP3Clock = Mp3ReadRegister(SCI_CLOCKF);
267 Serial.print(F("SCI_ClockF = 0x"));
268 Serial.println(MP3Clock, HEX);
269 */
270
271 // Validate VS1053 initialization.
272 if (MP3Mode != (SM_LINE1 | SM_SDINEW)) return 4;
273
274 // Now that we have the VS1053 up and running, increase the internal clock multiplier and up our SPI rate.
275 Mp3WriteRegister(SCI_CLOCKF, 0x6000); // set multiplier to 3.0x.
276 // Internal clock multiplier is now 3x.
277 // Therefore, max SPI speed is 52MgHz.
278
279 // Adjust SPI based on microcontroller type.
280#if (ARDUINO_ARCH_AVR)
281 spi_Max_Rate = 4000000; // 4 MHz for AVR based boards.
282#elif (ARDUINO_ARCH_RENESAS)
283 spi_Max_Rate = 7900000; // 7.9 MHz for Arduino UNO R4 boards.
284#endif
285
286 delay(10); // settle time.
287
288 // Test reading after data rate change.
289 int MP3Clock = Mp3ReadRegister(SCI_CLOCKF);
290 if (MP3Clock != 0x6000) return 5;
291
292 setVolume(40, 40);
293 // One would think the following patch would over write the volume.
294 // But the SCI_VOL register space is not in the VSdsp's WRAM space.
295 // Note to keep an eye on it for future patches.
296
297 if (VSLoadUserCode("patches.053")) return 6;
298
299 delay(100); // Just a good idea to let settle.
300
301 return 0; // indicating all was good.
302}
303
304//------------------------------------------------------------------------------
332uint8_t vs1053::VSLoadUserCode(char* fileName){
333
334 union twobyte val;
335 union twobyte addr;
336 union twobyte n;
337
338 if(!digitalRead(MP3_RESET)) return 3;
339 if(isPlaying()) return 1;
340 if(!digitalRead(MP3_RESET)) return 3;
341
342 // Open the file in read mode.
343 if(!track.open(fileName, O_READ)) return 2;
344 // playing_state = loading;
345 // while(i<size_of_Plugin/sizeof(Plugin[0])) {
346 while(1) {
347 // addr = Plugin[i++];
348 if(!track.read(addr.byte, 2)) break;
349 // n = Plugin[i++];
350 if(!track.read(n.byte, 2)) break;
351 if(n.word & 0x8000U) { /* RLE run, replicate n samples */
352 n.word &= 0x7FFF;
353 // val = Plugin[i++];
354 if(!track.read(val.byte, 2)) break;
355 while(n.word--) {
356 Mp3WriteRegister(addr.word, val.word);
357 }
358 } else { /* Copy run, copy n samples */
359 while(n.word--) {
360 // val = Plugin[i++];
361 if(!track.read(val.byte, 2)) break;
362 Mp3WriteRegister(addr.word, val.word);
363 }
364 }
365 }
366 track.close(); // close out this track.
367 // playing_state = ready;
368 return 0;
369}
370
371//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
372// @{
373// SelfTest_Group
374
375//------------------------------------------------------------------------------
394uint8_t vs1053::enableTestSineWave(uint8_t freq) {
395
396 if(isPlaying() || !digitalRead(MP3_RESET)) {
397 Serial.println(F("Warning Tests are not available."));
398 return -1;
399 }
400
401 uint16_t MP3SCI_MODE = Mp3ReadRegister(SCI_MODE);
402 if(MP3SCI_MODE & SM_TESTS) {
403 return 2;
404 }
405
406 Mp3WriteRegister(SCI_MODE, MP3SCI_MODE | SM_TESTS);
407
408 for(int y = 0 ; y <= 1 ; y++) { // need to do it twice if it was already done once before.
409 // Wait for DREQ to go high indicating IC is available.
410 while(!digitalRead(MP3_DREQ)) ;
411 // Select control.
412 dcs_low();
413 // SCI consists of instruction byte, address byte, and 16-bit data word.
414 SPI.transfer(0x53);
415 SPI.transfer(0xEF);
416 SPI.transfer(0x6E);
417 SPI.transfer(freq);
418 SPI.transfer(0x00);
419 SPI.transfer(0x00);
420 SPI.transfer(0x00);
421 SPI.transfer(0x00);
422 while(!digitalRead(MP3_DREQ)) ; // wait for DREQ to go high indicating command is complete.
423 dcs_high(); // deselect Control.
424 SPI.endTransaction(); // ends SPI transaction, freeing the bus.
425 }
426
428 return 1;
429}
430
431//------------------------------------------------------------------------------
447
448 if(isPlaying() || !digitalRead(MP3_RESET)) {
449 Serial.println(F("Warning Tests are not available."));
450 return -1;
451 }
452
453 uint16_t MP3SCI_MODE = Mp3ReadRegister(SCI_MODE);
454 if(!(MP3SCI_MODE & SM_TESTS)) {
455 return 0;
456 }
457
458 // Wait for DREQ to go high indicating IC is available.
459 while(!digitalRead(MP3_DREQ)) ;
460
461 // Select SPI Control channel.
462 dcs_low();
463
464 // SDI consists of instruction byte, address byte, and 16-bit data word.
465 SPI.transfer(0x45);
466 SPI.transfer(0x78);
467 SPI.transfer(0x69);
468 SPI.transfer(0x74);
469 SPI.transfer(0x00);
470 SPI.transfer(0x00);
471 SPI.transfer(0x00);
472 SPI.transfer(0x00);
473 while(!digitalRead(MP3_DREQ)) ; // wait for DREQ to go high indicating command is complete.
474
475 // Deselect SPI Control channel.
476 dcs_high();
477 SPI.endTransaction(); // ends SPI transaction, freeing the bus.
478
479 // Turn test mode bit off.
481
483 return 0;
484}
485
486//------------------------------------------------------------------------------
503
504 if(isPlaying() || !digitalRead(MP3_RESET)) {
505 Serial.println(F("Warning Tests are not available."));
506 return -1;
507 }
508
510
511 vs_init();
512
513 uint16_t MP3SCI_MODE = Mp3ReadRegister(SCI_MODE);
514 if(MP3SCI_MODE & SM_TESTS) {
516 return 2;
517 }
518
519 Mp3WriteRegister(SCI_MODE, MP3SCI_MODE | SM_TESTS);
520
521// for(int y = 0 ; y <= 1 ; y++) { // need to do it twice if it was already done once before.
522 // Wait for DREQ to go high indicating IC is available.
523 while(!digitalRead(MP3_DREQ)) ;
524
525 // Select SPI Control channel.
526 dcs_low();
527
528 // SCI consists of instruction byte, address byte, and 16-bit data word.
529 SPI.transfer(0x4D);
530 SPI.transfer(0xEA);
531 SPI.transfer(0x6D);
532 SPI.transfer(0x54);
533 SPI.transfer(0x00);
534 SPI.transfer(0x00);
535 SPI.transfer(0x00);
536 SPI.transfer(0x00);
537 while(!digitalRead(MP3_DREQ)); // wait for DREQ to go high indicating command is complete.
538
539 // Deselect SPI Control channel.
540 dcs_high();
541 SPI.endTransaction(); // ends SPI transaction, freeing the bus.
542// }
543 delay(250);
544
545 uint16_t MP3SCI_HDAT0 = Mp3ReadRegister(SCI_HDAT0);
546
548
549 vs_init();
550
552 return MP3SCI_HDAT0;
553}
554// @}
555// SelfTest_Group
556
557//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
558// @{
559// Volume_Group
560
561//------------------------------------------------------------------------------
572void vs1053::setVolume(uint16_t data) {
573 union twobyte val;
574 val.word = data;
575 setVolume(val.byte[1], val.byte[0]);
576}
577
578//------------------------------------------------------------------------------
589void vs1053::setVolume(uint8_t data) {
590 setVolume(data, data);
591}
592
593//------------------------------------------------------------------------------
606void vs1053::setVolume(uint8_t leftchannel, uint8_t rightchannel){
607
608 VolL = leftchannel;
609 VolR = rightchannel;
610 Mp3WriteRegister(SCI_VOL, leftchannel, rightchannel);
611}
612
613//------------------------------------------------------------------------------
629 uint16_t MP3SCI_VOL = Mp3ReadRegister(SCI_VOL);
630 return MP3SCI_VOL;
631}
632// @}
633// Volume_Group
634
635//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
636// @{
637// Base_Treble_Group
638
639//------------------------------------------------------------------------------
647{
648 union sci_bass_m sci_base_value;
649 sci_base_value.word = Mp3ReadRegister(SCI_BASS);
650 return (sci_base_value.nibble.Treble_Freqlimt * 1000);
651}
652
653//------------------------------------------------------------------------------
661{
662 union sci_bass_m sci_base_value;
663 sci_base_value.word = Mp3ReadRegister(SCI_BASS);
664 return (sci_base_value.nibble.Treble_Amplitude);
665}
666//------------------------------------------------------------------------------
674{
675 union sci_bass_m sci_base_value;
676 sci_base_value.word = Mp3ReadRegister(SCI_BASS);
677 return (sci_base_value.nibble.Bass_Freqlimt * 10);
678}
679
680//------------------------------------------------------------------------------
692{
693 union sci_bass_m sci_base_value;
694 sci_base_value.word = Mp3ReadRegister(SCI_BASS);
695 return (sci_base_value.nibble.Bass_Amplitude);
696}
697//------------------------------------------------------------------------------
705void vs1053::setTrebleFrequency(uint16_t frequency)
706{
707 union sci_bass_m sci_base_value;
708
709 frequency /= 1000;
710
711 if(frequency < 1)
712 {
713 frequency = 1;
714 }
715 else if(frequency > 15)
716 {
717 frequency = 15;
718 }
719
720 sci_base_value.word = Mp3ReadRegister(SCI_BASS);
721 sci_base_value.nibble.Treble_Freqlimt = frequency;
722 Mp3WriteRegister(SCI_BASS, sci_base_value.word);
723}
724
725//------------------------------------------------------------------------------
733void vs1053::setTrebleAmplitude(int8_t amplitude)
734{
735 union sci_bass_m sci_base_value;
736
737 if(amplitude < -8)
738 {
739 amplitude = -8;
740 }
741 else if(amplitude > 7)
742 {
743 amplitude = 7;
744 }
745
746 sci_base_value.word = Mp3ReadRegister(SCI_BASS);
747 sci_base_value.nibble.Treble_Amplitude = amplitude;
748 Mp3WriteRegister(SCI_BASS, sci_base_value.word);
749}
750
751//------------------------------------------------------------------------------
759void vs1053::setBassFrequency(uint16_t frequency)
760{
761 union sci_bass_m sci_base_value;
762
763 frequency /= 10;
764
765 if(frequency < 2)
766 {
767 frequency = 2;
768 }
769 else if(frequency > 15)
770 {
771 frequency = 15;
772 }
773
774 sci_base_value.word = Mp3ReadRegister(SCI_BASS);
775 sci_base_value.nibble.Bass_Freqlimt = frequency;
776 Mp3WriteRegister(SCI_BASS, sci_base_value.word);
777}
778
779//------------------------------------------------------------------------------
791void vs1053::setBassAmplitude(uint8_t amplitude)
792{
793 union sci_bass_m sci_base_value;
794
795 if(amplitude < 0)
796 {
797 amplitude = 0;
798 }
799 else if(amplitude > 15)
800 {
801 amplitude = 15;
802 }
803
804 sci_base_value.word = Mp3ReadRegister(SCI_BASS);
805 sci_base_value.nibble.Bass_Amplitude = amplitude;
806 Mp3WriteRegister(SCI_BASS, sci_base_value.word);
807}
808// @}
809// Base_Treble_Group
810
811//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
812// @{
813// PlaySpeed_Group
814
815//------------------------------------------------------------------------------
832 uint16_t MP3playspeed = Mp3ReadWRAM(para_playSpeed);
833 return MP3playspeed;
834}
835
836//------------------------------------------------------------------------------
851void vs1053::setPlaySpeed(uint16_t data) {
853}
854// @}
855// PlaySpeed_Group
856
857//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
858// @{
859// EarSpeaker_Group
860
861//------------------------------------------------------------------------------
872 uint8_t result = 0;
873 uint16_t MP3SCI_MODE = Mp3ReadRegister(SCI_MODE);
874
875 // SM_EARSPEAKER bits are not adjacent hence need to add them together.
876 if(MP3SCI_MODE & SM_EARSPEAKER_LO) {
877 result += 0b01;
878 }
879 if(MP3SCI_MODE & SM_EARSPEAKER_HI) {
880 result += 0b10;
881 }
882 return result;
883}
884
885//------------------------------------------------------------------------------
895void vs1053::setEarSpeaker(uint16_t EarSpeaker) {
896 uint16_t MP3SCI_MODE = Mp3ReadRegister(SCI_MODE);
897
898 // SM_EARSPEAKER bits are not adjacent hence need to add them individually.
899 if(EarSpeaker & 0b01) {
900 MP3SCI_MODE |= SM_EARSPEAKER_LO;
901 } else {
902 MP3SCI_MODE &= ~SM_EARSPEAKER_LO;
903 }
904
905 if(EarSpeaker & 0b10) {
906 MP3SCI_MODE |= SM_EARSPEAKER_HI;
907 } else {
908 MP3SCI_MODE &= ~SM_EARSPEAKER_HI;
909 }
910 Mp3WriteRegister(SCI_MODE, MP3SCI_MODE);
911}
912// @}
913// EarSpeaker_Group
914
915//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
916// @{
917// Differential_Output_Mode_Group
918
919//------------------------------------------------------------------------------
936 uint8_t result = 0;
937 uint16_t MP3SCI_MODE = Mp3ReadRegister(SCI_MODE);
938
939 if(MP3SCI_MODE & SM_DIFF) {
940 result = 1;
941 }
942 return result;
943}
944
945//------------------------------------------------------------------------------
959void vs1053::setDifferentialOutput(uint16_t DiffMode) {
960 uint16_t MP3SCI_MODE = Mp3ReadRegister(SCI_MODE);
961
962 if(DiffMode) {
963 MP3SCI_MODE |= SM_DIFF;
964 } else {
965 MP3SCI_MODE &= ~SM_DIFF;
966 }
967 Mp3WriteRegister(SCI_MODE, MP3SCI_MODE);
968}
969// @}
970// Differential_Output_Mode_Group
971
972//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
973// @{
974// Stereo_Group
975
976//------------------------------------------------------------------------------
990 uint16_t result = (Mp3ReadWRAM(para_MonoOutput) & 0x0001);
991 return result;
992}
993
994//------------------------------------------------------------------------------
1005void vs1053::setMonoMode(uint16_t StereoMode) {
1006 uint16_t data = (Mp3ReadWRAM(para_MonoOutput) & ~0x0001); // preserve other bits.
1007 Mp3WriteWRAM(0x1e09, (StereoMode | (data & 0x0001)));
1008}
1009// @}
1010// Stereo_Group
1011
1012//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1013// @{
1014// Play_Control_Group
1015
1016//------------------------------------------------------------------------------
1032uint8_t vs1053::playTrack(uint8_t trackNo){
1033
1034 // A storage place for track names.
1035 char trackName[] = "track001.mp3";
1036 uint8_t trackNumber = 1;
1037
1038 // Tack the number onto the rest of the filename.
1039 sprintf(trackName, "track%03d.mp3", trackNo);
1040
1041 // Play the file.
1042 return playMP3(trackName);
1043}
1044
1045//------------------------------------------------------------------------------
1073
1074uint8_t vs1053::playMP3(char* fileName, uint32_t timecode) {
1075
1076 if(isPlaying()) return 1;
1077 if(!digitalRead(MP3_RESET)) return 3;
1078
1079 // Open the file in read mode.
1080 if(!track.open(fileName, O_READ)) return 2;
1081
1082 // Calculate the length of the file name.
1083 int len = strlen(fileName);
1084
1085 // Only know how to read bitrate from MP3 file. ignore the rest.
1086 // Note bitrate may get updated later by getAudioInfo().
1087 if (len > 3 && !strcasecmp(fileName + len - 3, "mp3")) {
1088 getBitRateFromMP3File(fileName);
1089 if (timecode > 0) {
1090 track.seekSet(timecode * bitrate + start_of_music); // skip to X ms.
1091 }
1092 }
1093
1095
1096 Mp3WriteRegister(SCI_DECODE_TIME, 0); // reset the Decode and bitrate from previous play back.
1097 delay(100); // experimentally found that we need to let this settle before sending data.
1098
1099 // Gotta start feeding that hungry mp3 chip.
1100 refill();
1101
1102 // Attach refill interrupt off DREQ line, pin 2.
1103 enableRefill();
1104
1105 return 0;
1106}
1107
1108//------------------------------------------------------------------------------
1117
1118 if(((playing_state != playback) && (playing_state != paused_playback)) || !digitalRead(MP3_RESET))
1119 return;
1120
1121 // Cancel external interrupt.
1122 disableRefill();
1124
1125 track.close(); // close out this track.
1126
1127 flush_cancel(pre); // possible mode of "none" for faster response.
1128
1129 // Serial.println(F("Track is done!"));
1130
1131}
1132
1133//------------------------------------------------------------------------------
1145 uint8_t result;
1146
1147 if(!digitalRead(MP3_RESET))
1148 result = 3;
1149 else if(getState() == playback)
1150 result = 1;
1151 else if(getState() == paused_playback)
1152 result = 1;
1153 else
1154 result = 0;
1155
1156 return result;
1157}
1158
1170
1171//------------------------------------------------------------------------------
1178
1179 // Cancel external interrupt.
1180 if((playing_state == playback) && digitalRead(MP3_RESET))
1181 {
1182 disableRefill();
1184 }
1185}
1186
1187//------------------------------------------------------------------------------
1195
1196 if((playing_state == paused_playback) && digitalRead(MP3_RESET)) {
1197 // See if it is already ready for more.
1198 refill();
1199
1201 // Attach refill interrupt off DREQ line, pin 2.
1202 enableRefill();
1203 }
1204}
1205
1206//------------------------------------------------------------------------------
1218
1219//------------------------------------------------------------------------------
1235uint8_t vs1053::resumeMusic(uint32_t timecode) {
1236 if((playing_state == paused_playback) && digitalRead(MP3_RESET)) {
1237
1238 if(!track.seekSet(((timecode * Mp3ReadWRAM(para_byteRate))/1000) + start_of_music)) //if(!track.seekCur((uint32_t(timecode/1000 * Mp3ReadWRAM(para_byteRate)))))
1239 return 2;
1240
1242 return 0;
1243 }
1244 return 1;
1245}
1246
1247//------------------------------------------------------------------------------
1261 if((playing_state == paused_playback) && digitalRead(MP3_RESET)) {
1263 return 0;
1264 }
1265 return 1;
1266}
1267
1268//------------------------------------------------------------------------------
1284uint8_t vs1053::skip(int32_t timecode){
1285
1286 if(isPlaying() && digitalRead(MP3_RESET)) {
1287
1288 // Stop interupt for now.
1289 disableRefill();
1291
1292 // Try to set the files position to current position + offset(in bytes)
1293 // as calculated from current byte rate, as per VSdsp.
1294 if(!track.seekCur((uint32_t(timecode/1000 * Mp3ReadWRAM(para_byteRate))))) // skip next X ms.
1295 return 2;
1296
1297 Mp3WriteRegister(SCI_VOL, 0xFE, 0xFE);
1298 // Seeked successfully.
1299
1300 flush_cancel(pre); // possible mode of "none" for faster response.
1301
1302 // Gotta start feeding that hungry mp3 chip.
1303 refill();
1304
1305 // Again, I'm being bad and not following the spec sheet.
1306 // I already turned the volume down, so when the MP3 chip gets upset at me
1307 // for just slammin in new bits of the file, you won't hear it.
1308 // So we'll wait a bit, and restore the volume to previous level.
1309 delay(50);
1310
1311 // One of these days I'll come back and try to do it the right way.
1313
1315 // Attach refill interrupt off DREQ line, pin 2.
1316 enableRefill();
1317
1318 return 0;
1319 }
1320
1321 return 1;
1322}
1323
1324//------------------------------------------------------------------------------
1340uint8_t vs1053::skipTo(uint32_t timecode){
1341
1342 if(isPlaying() && digitalRead(MP3_RESET)) {
1343
1344 // Stop interupt for now.
1345 disableRefill();
1347
1348 // Try to set the files position to current position + offset(in bytes)
1349 // as calculated from current byte rate, as per VSdsp.
1350 if(!track.seekSet(((timecode * Mp3ReadWRAM(para_byteRate))/1000) + start_of_music)) // skip to X ms.
1351 // if(!track.seekCur((uint32_t(timecode/1000 * Mp3ReadWRAM(para_byteRate))))) // skip next X ms.
1352 return 2;
1353
1354 Mp3WriteRegister(SCI_VOL, 0xFE, 0xFE);
1355 // Seeked successfully.
1356
1357 flush_cancel(pre); // possible mode of "none" for faster response.
1358
1359 // Gotta start feeding that hungry mp3 chip.
1360 refill();
1361
1362 // Again, I'm being bad and not following the spec sheet.
1363 // I already turned the volume down, so when the MP3 chip gets upset at me
1364 // for just slammin in new bits of the file, you won't hear it.
1365 // So we'll wait a bit, and restore the volume to previous level
1366 delay(50);
1367
1368 // One of these days I'll come back and try to do it the right way.
1370
1372 // Attach refill interrupt off DREQ line, pin 2.
1373 enableRefill();
1374
1375 return 0;
1376 }
1377
1378 return 1;
1379}
1380
1381//------------------------------------------------------------------------------
1397
1398 return(Mp3ReadRegister(SCI_DECODE_TIME) << 10); // multiply by 1024 to convert to milliseconds.
1399}
1400
1401// @}
1402// Play_Control_Group
1403
1404//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1405// @{
1406// Audio_Information_Group
1407
1408//------------------------------------------------------------------------------
1420void vs1053::trackArtist(char* infobuffer){
1421 getTrackInfo(TRACK_ARTIST, infobuffer);
1422}
1423
1424//------------------------------------------------------------------------------
1436void vs1053::trackTitle(char* infobuffer){
1437 getTrackInfo(TRACK_TITLE, infobuffer);
1438}
1439
1440//------------------------------------------------------------------------------
1452void vs1053::trackAlbum(char* infobuffer){
1453 getTrackInfo(TRACK_ALBUM, infobuffer);
1454}
1455
1456//------------------------------------------------------------------------------
1469void vs1053::getTrackInfo(uint8_t offset, char* infobuffer){
1470
1471 // Disable interupts.
1472 if(playing_state == playback) {
1473 disableRefill();
1474 }
1475
1476 // Record current file position.
1477 uint32_t currentPos = track.curPosition();
1478
1479 // Skip to end.
1480 track.seekEnd((-128 + offset));
1481
1482 // Read 30 bytes of tag informat at -128 + offset.
1483 track.read(infobuffer, 30);
1484 infobuffer = strip_nonalpha_inplace(infobuffer);
1485
1486 // Seek back to saved file position.
1487 track.seekSet(currentPos);
1488
1489 // Renable interupt.
1490 if(playing_state == playback) {
1491 enableRefill();
1492 }
1493
1494}
1495
1496//------------------------------------------------------------------------------
1509
1510 // Disable interupts
1511 // already disabled in Mp3ReadRegister function.
1512 // pauseDataStream();
1513
1514 Serial.print(F("HDAT1"));
1515 Serial.print(F("\tHDAT0"));
1516 Serial.print(F("\tVOL"));
1517 Serial.print(F("\tMode"));
1518 Serial.print(F("\tStatus"));
1519 Serial.print(F("\tClockF"));
1520 Serial.print(F("\tpversion"));
1521 Serial.print(F("\t[Bytes/S]"));
1522 Serial.print(F("\t[KBits/S]"));
1523 Serial.print(F("\tPlaySpeed"));
1524 Serial.print(F("\tDECODE_TIME"));
1525 Serial.print(F("\tCurrentPos"));
1526 Serial.println();
1527
1528 uint16_t MP3HDAT1 = Mp3ReadRegister(SCI_HDAT1);
1529 Serial.print(F("0x"));
1530 Serial.print(MP3HDAT1, HEX);
1531
1532 uint16_t MP3HDAT0 = Mp3ReadRegister(SCI_HDAT0);
1533 Serial.print(F("\t0x"));
1534 Serial.print(MP3HDAT0, HEX);
1535
1536 uint16_t MP3SCI_VOL = Mp3ReadRegister(SCI_VOL);
1537 Serial.print(F("\t0x"));
1538 Serial.print(MP3SCI_VOL, HEX);
1539
1540 uint16_t MP3Mode = Mp3ReadRegister(SCI_MODE);
1541 Serial.print(F("\t0x"));
1542 Serial.print(MP3Mode, HEX);
1543
1544 uint16_t MP3Status = Mp3ReadRegister(SCI_STATUS);
1545 Serial.print(F("\t0x"));
1546 Serial.print(MP3Status, HEX);
1547
1548 uint16_t MP3Clock = Mp3ReadRegister(SCI_CLOCKF);
1549 Serial.print(F("\t0x"));
1550 Serial.print(MP3Clock, HEX);
1551
1552 uint16_t MP3para_version = Mp3ReadWRAM(para_version);
1553 Serial.print(F("\t0x"));
1554 Serial.print(MP3para_version, HEX);
1555
1556 uint16_t MP3ByteRate = Mp3ReadWRAM(para_byteRate);
1557 Serial.print(F("\t\t"));
1558 Serial.print(MP3ByteRate, HEX);
1559
1560 Serial.print(F("\t\t"));
1561 Serial.print((MP3ByteRate>>7), DEC); // shift 7 is the same as *8/1024, and easier math.
1562
1563 uint16_t MP3playSpeed = Mp3ReadWRAM(para_playSpeed);
1564 Serial.print(F("\t\t"));
1565 Serial.print(MP3playSpeed, HEX);
1566
1567 uint16_t MP3SCI_DECODE_TIME = Mp3ReadRegister(SCI_DECODE_TIME);
1568 Serial.print(F("\t\t"));
1569 Serial.print(MP3SCI_DECODE_TIME, DEC);
1570
1571 Serial.print(F("\t\t"));
1572 Serial.print(currentPosition(), DEC);
1573
1574 Serial.println();
1575}
1576
1577//------------------------------------------------------------------------------
1592void vs1053::getBitRateFromMP3File(char* fileName) {
1593 // Look for first MP3 frame (11 1's).
1594 bitrate = 0;
1595 uint8_t temp = 0;
1596 uint8_t row_num =0;
1597
1598 for(uint16_t i = 0; i<65535; i++) {
1599 if(track.read() == 0xFF) {
1600
1601 temp = track.read();
1602
1603 if(((temp & 0b11100000) == 0b11100000) && ((temp & 0b00000110) != 0b00000000)) {
1604
1605 // Found the 11 1's
1606 // parse version, layer and bitrate out and save bitrate.
1607 if(!(temp & 0b00001000)) { // !true if Version 1, !false version 2 and 2.5.
1608 row_num = 3;
1609 }
1610 else if((temp & 0b00000110) == 0b00000100) { // true if layer 2, false if layer 1 or 3.
1611 row_num += 1;
1612 }
1613 else if((temp & 0b00000110) == 0b00000010) { // true if layer 3, false if layer 2 or 1.
1614 row_num += 2;
1615 } else {
1616 continue; // not found, need to skip the rest and continue looking.
1617 // \warning But this can lead to a dead end and file end of file.
1618 }
1619
1620 // Parse bitrate code from next byte.
1621 temp = track.read();
1622 temp = temp>>4;
1623
1624 // Lookup bitrate.
1625 bitrate = pgm_read_word_near ( &(bitrate_table[temp][row_num]) );
1626
1627 // Convert kbps to Bytes per mS.
1628 bitrate /= 8;
1629
1630 // Record file position.
1631 track.seekCur(-3);
1632 start_of_music = track.curPosition();
1633
1634// Serial.print(F("POS: "));
1635// Serial.println(start_of_music);
1636
1637// Serial.print(F("Bitrate: "));
1638// Serial.println(bitrate);
1639
1640 // Break out of for loop.
1641 break;
1642
1643 }
1644 }
1645 }
1646 }
1647
1648//------------------------------------------------------------------------------
1660 return 1;
1661 }
1662 return 0;
1663 }
1664
1665//------------------------------------------------------------------------------
1678int8_t vs1053::setVUmeter(int8_t enable) {
1679 uint16_t MP3Status = Mp3ReadRegister(SCI_STATUS);
1680
1681 if(enable) {
1683 } else {
1685 }
1686 return 1; // in future return if not available, if patch not applied.
1687 }
1688
1689//------------------------------------------------------------------------------
1703}
1704
1705// @}
1706// Audio_Information_Group
1707
1708//------------------------------------------------------------------------------
1717void vs1053::setBitRate(uint16_t bitr){
1718
1719 bitrate = bitr;
1720 return;
1721}
1722
1723//------------------------------------------------------------------------------
1733 // Set SPI port configuration.
1734 SPI.beginTransaction(SPISettings(spi_Max_Rate, MSBFIRST, SPI_MODE0));
1735}
1736
1737//------------------------------------------------------------------------------
1748 spiInit();
1749 digitalWrite(MP3_XCS, LOW);
1750}
1751
1752//------------------------------------------------------------------------------
1760 digitalWrite(MP3_XCS, HIGH);
1761}
1762
1763//------------------------------------------------------------------------------
1774 spiInit();
1775 digitalWrite(MP3_XDCS, LOW);
1776}
1777
1778//------------------------------------------------------------------------------
1786 digitalWrite(MP3_XDCS, HIGH);
1787}
1788
1789//------------------------------------------------------------------------------
1799void vs1053::Mp3WriteRegister(uint8_t addressbyte, uint16_t data) {
1800 union twobyte val;
1801 val.word = data;
1802 Mp3WriteRegister(addressbyte, val.byte[1], val.byte[0]);
1803}
1804
1805//------------------------------------------------------------------------------
1816void vs1053::Mp3WriteRegister(uint8_t addressbyte, uint8_t highbyte, uint8_t lowbyte) {
1817
1818 // Skip if the chip is in reset.
1819 if(!digitalRead(MP3_RESET)) return;
1820
1821 // Cancel interrupt if playing.
1822 if(playing_state == playback)
1823 disableRefill();
1824
1825 // Wait for DREQ to go high indicating IC is available.
1826 while(!digitalRead(MP3_DREQ)) ;
1827
1828 cs_low(); // select control.
1829
1830 // SCI consists of instruction byte, address byte, and 16-bit data word.
1831 SPI.transfer(0x02); // write instruction.
1832 SPI.transfer(addressbyte);
1833 SPI.transfer(highbyte);
1834 SPI.transfer(lowbyte);
1835 while(!digitalRead(MP3_DREQ)); // wait for DREQ to go high indicating command is complete.
1836 cs_high(); // deselect Control.
1837 SPI.endTransaction(); // ends SPI transaction, freeing the bus.
1838
1839 // Resume interrupt if playing.
1840 if(playing_state == playback) {
1841 // See if it is already ready for more.
1842 refill();
1843
1844 // Attach refill interrupt off DREQ line, pin 2.
1845 enableRefill();
1846 }
1847
1848}
1849
1850//------------------------------------------------------------------------------
1860uint16_t vs1053::Mp3ReadRegister (uint8_t addressbyte){
1861
1862 union twobyte resultvalue;
1863
1864 // Skip if the chip is in reset.
1865 if(!digitalRead(MP3_RESET)) return 0;
1866
1867 // Cancel interrupt if playing.
1868 if(playing_state == playback)
1869 disableRefill();
1870
1871 while(!digitalRead(MP3_DREQ)); // wait for DREQ to go high indicating IC is available.
1872
1873 cs_low(); // select control.
1874
1875 // SCI consists of instruction byte, address byte, and 16-bit data word.
1876 SPI.transfer(0x03); // read instruction.
1877 SPI.transfer(addressbyte);
1878
1879 resultvalue.byte[1] = SPI.transfer(0xFF); // read the first byte.
1880 while(!digitalRead(MP3_DREQ)); // wait for DREQ to go high indicating command is complete.
1881 resultvalue.byte[0] = SPI.transfer(0xFF); // read the second byte.
1882 while(!digitalRead(MP3_DREQ)); // wait for DREQ to go high indicating command is complete.
1883
1884 cs_high(); // deselect Control.
1885 SPI.endTransaction(); // ends SPI transaction, freeing the bus.
1886
1887 // Resume interrupt if playing.
1888 if(playing_state == playback) {
1889 // See if it is already ready for more.
1890 refill();
1891
1892 // Attach refill interrupt off DREQ line, pin 2.
1893 enableRefill();
1894 }
1895 return resultvalue.word;
1896}
1897
1898//------------------------------------------------------------------------------
1908uint16_t vs1053::Mp3ReadWRAM (uint16_t addressbyte){
1909
1910 unsigned short int tmp1,tmp2;
1911
1912 // Set SPI bus for write.
1913 spiInit();
1914
1915 Mp3WriteRegister(SCI_WRAMADDR, addressbyte);
1916 tmp1 = Mp3ReadRegister(SCI_WRAM);
1917
1918 Mp3WriteRegister(SCI_WRAMADDR, addressbyte);
1919 tmp2 = Mp3ReadRegister(SCI_WRAM);
1920
1921 if(tmp1==tmp2) return tmp1;
1922 Mp3WriteRegister(SCI_WRAMADDR, addressbyte);
1923 tmp2 = Mp3ReadRegister(SCI_WRAM);
1924
1925 if(tmp1==tmp2) return tmp1;
1926 Mp3WriteRegister(SCI_WRAMADDR, addressbyte);
1927 tmp2 = Mp3ReadRegister(SCI_WRAM);
1928
1929 if(tmp1==tmp2) return tmp1;
1930 return tmp1;
1931}
1932
1933//------------------------------------------------------------------------------
1942// Write the 16-bit value of a VS10xx WRAM location
1943void vs1053::Mp3WriteWRAM(uint16_t addressbyte, uint16_t data){
1944
1945 Mp3WriteRegister(SCI_WRAMADDR, addressbyte);
1947}
1948
1949//------------------------------------------------------------------------------
1957#if defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer
1958 timer.run();
1959#elif defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_Polled
1960 refill();
1961#endif
1962}
1963
1964//------------------------------------------------------------------------------
1979
1980 // Serial.println(F("filling"));
1981#if PERF_MON_PIN != -1
1982 digitalWrite(PERF_MON_PIN,LOW);
1983#endif
1984
1985 // No need to keep interrupts blocked, allow other ISR such as timer0 to continue.
1986#if !defined(USE_MP3_REFILL_MEANS) || USE_MP3_REFILL_MEANS == irq
1987 interrupts(); // renable interrupts for other processes.
1988#endif
1989
1990 while(digitalRead(MP3_DREQ)) {
1991
1992 if(!track.read(mp3DataBuffer, sizeof(mp3DataBuffer))) { // go out to SD card and try reading 32 new bytes of the song.
1993 track.close(); // close out this track.
1995
1996 // Cancel external interrupt.
1997 disableRefill();
1998
1999 flush_cancel(post); // possible mode of "none" for faster response.
2000
2001 // Oh no! There is no data left to read!.
2002 // Time to exit.
2003 break;
2004 }
2005
2006 // Once DREQ is released (high) we now feed 32 bytes of data to the VS1053 from our SD read buffer.
2007#if !defined(USE_MP3_REFILL_MEANS) || USE_MP3_REFILL_MEANS == irq
2008 noInterrupts(); // allow transfer to occur with out interruption.
2009#endif
2010 dcs_low(); // select Data.
2011 for(uint8_t y = 0 ; y < sizeof(mp3DataBuffer) ; y++) {
2012 // while(!digitalRead(MP3_DREQ)); // wait until DREQ is or goes high // turns out it is not needed.
2013 SPI.transfer(mp3DataBuffer[y]); // send SPI byte.
2014 }
2015
2016 dcs_high(); // deselect Data.
2017 SPI.endTransaction(); // ends SPI transaction, freeing the bus.
2018
2019 // We've just dumped 32 bytes into VS1053 so our SD read buffer is empty. Go get more data.
2020#if !defined(USE_MP3_REFILL_MEANS) || USE_MP3_REFILL_MEANS == irq
2021 interrupts(); // renable interrupts for other processes.
2022#endif
2023 }
2024
2025#if PERF_MON_PIN != -1
2026 digitalWrite(PERF_MON_PIN,HIGH);
2027#endif
2028}
2029
2030//------------------------------------------------------------------------------
2041
2042 if(!digitalRead(MP3_RESET))
2043 return;
2044
2045 // Cancel and store current state to restore after.
2046 disableRefill();
2047 state_m prv_state = playing_state;
2049
2050 // Need to quickly purge the exiting formate of decoder.
2052
2053 // Wait for VS1053 to be available.
2054 while(!digitalRead(MP3_DREQ)); // wait until DREQ is or goes high.
2055
2056#if !defined(USE_MP3_REFILL_MEANS) || USE_MP3_REFILL_MEANS == irq
2057 noInterrupts(); // allow transfer to occur with out interruption.
2058#endif
2059
2060 dcs_low(); // select Data.
2061 for(uint8_t y = 0 ; y < sizeof(SingleMIDInoteFile) ; y++) { // sizeof(mp3DataBuffer)
2062 // Every 32 check if not ready for next buffer chunk.
2063 if ( !(y % 32) ) {
2064 while(!digitalRead(MP3_DREQ)); // wait until DREQ is or goes high.
2065 }
2066 SPI.transfer( pgm_read_byte_near( &(SingleMIDInoteFile[y]))); // send next byte.
2067 }
2068 dcs_high(); // deselect Data.
2069 SPI.endTransaction(); // ends SPI transaction, freeing the bus.
2070
2071#if !defined(USE_MP3_REFILL_MEANS) || USE_MP3_REFILL_MEANS == irq
2072 interrupts(); // renable interrupts for other processes.
2073#endif
2074
2075 flush_cancel(none); // need to quickly purge the exiting format of decoder.
2076 playing_state = prv_state;
2077 enableRefill();
2078}
2079
2080//------------------------------------------------------------------------------
2088 if(playing_state == playback) {
2089 #if defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_Timer1
2090 Timer1.attachInterrupt( refill );
2091 #elif defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer
2092 timer.enable(timerId_mp3);
2093 #elif !defined(USE_MP3_REFILL_MEANS) || USE_MP3_REFILL_MEANS == irq
2094 refill();
2095 attachInterrupt(irq, refill, RISING);
2096 #endif
2097 }
2098}
2099
2100//------------------------------------------------------------------------------
2108#if defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_Timer1
2109 Timer1.detachInterrupt();
2110#elif defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer
2111 timer.disable(timerId_mp3);
2112#elif !defined(USE_MP3_REFILL_MEANS) || USE_MP3_REFILL_MEANS == irq
2113 detachInterrupt(irq);
2114#endif
2115}
2116
2117//------------------------------------------------------------------------------
2135 int8_t endFillByte = (int8_t) (Mp3ReadWRAM(para_endFillByte) & 0xFF);
2136
2137 if((mode == post) || (mode == both)) {
2138
2139 dcs_low(); // select Data.
2140 for(int y = 0 ; y < 2052 ; y++) {
2141 while(!digitalRead(MP3_DREQ)); // wait until DREQ is or goes high.
2142 SPI.transfer(endFillByte); // send SPI byte.
2143 }
2144 dcs_high(); // deselect Data.
2145 SPI.endTransaction(); // ends SPI transaction, freeing the bus.
2146 }
2147
2148 for (int n = 0; n < 64 ; n++)
2149 {
2150// Mp3WriteRegister(SCI_MODE, SM_LINE1 | SM_SDINEW | SM_CANCEL); // old way of SCI_MODE WRITE.
2152
2153 dcs_low(); // select Data.
2154 for(int y = 0 ; y < 32 ; y++) {
2155 while(!digitalRead(MP3_DREQ)); // wait until DREQ is or goes high.
2156 SPI.transfer(endFillByte); // send SPI byte.
2157 }
2158 dcs_high(); // deselect Data.
2159 SPI.endTransaction(); // ends SPI transaction, freeing the bus.
2160
2161 int cancel = Mp3ReadRegister(SCI_MODE) & SM_CANCEL;
2162 if(cancel == 0) {
2163 // Cancel has succeeded.
2164 if((mode == pre) || (mode == both)) {
2165 dcs_low(); // select Data.
2166 for(int y = 0 ; y < 2052 ; y++) {
2167 while(!digitalRead(MP3_DREQ)); // wait until DREQ is or goes high.
2168 SPI.transfer(endFillByte); // send SPI byte.
2169 }
2170 dcs_high(); // deselect Data.
2171 SPI.endTransaction(); // ends SPI transaction, freeing the bus.
2172 }
2173 return;
2174 }
2175 }
2176 // Cancel has not succeeded.
2177// Serial.println(F("Warning: VS10XX chip did not cancel, reseting chip!"));
2178// Mp3WriteRegister(SCI_MODE, SM_LINE1 | SM_SDINEW | SM_RESET); // old way of SCI_MODE WRITE.
2179 Mp3WriteRegister(SCI_MODE, (Mp3ReadRegister(SCI_MODE) | SM_RESET)); // software reset. But vs_init will HW reset anyways.
2180// vs_init(); // perform hardware reset followed by re-initializing.
2181// vs_init(); // however, vs1053::begin() is member function that does not exist statically.
2182}
2183
2184//------------------------------------------------------------------------------
2206uint8_t vs1053::ADMixerLoad(char* fileName){
2207
2208 if(!digitalRead(MP3_RESET)) return 3;
2209 if(isPlaying() != FALSE)
2210 return 1;
2211
2213 if(VSLoadUserCode(fileName)) {
2215 return 2;
2216 // Serial.print(F("Error: ")); Serial.print(fileName); Serial.println(F(", file not found, skipping."));
2217 }
2218
2219 // Set Input Mode to either Line1 or Microphone.
2220#if defined(VS_LINE1_MODE)
2222#else
2224#endif
2226 return 0;
2227}
2228
2229//------------------------------------------------------------------------------
2243void vs1053::ADMixerVol(int8_t ADM_volume){
2244 union twobyte MP3AIADDR;
2245 union twobyte MP3AICTRL0;
2246
2247 MP3AIADDR.word = Mp3ReadRegister(SCI_AIADDR);
2248
2249 if((ADM_volume > -3) || (-31 > ADM_volume)) {
2250 // Disable Mixer Patch.
2251 MP3AIADDR.word = 0x0F01;
2252 Mp3WriteRegister(SCI_AIADDR, MP3AIADDR.word);
2253 } else {
2254 // Set Volume.
2255 // MP3AICTRL0.word = Mp3ReadRegister(SCI_AICTRL0);
2256 MP3AICTRL0.byte[1] = (uint8_t) ADM_volume; // upper byte appears to have no affect
2257 MP3AICTRL0.byte[0] = (uint8_t) ADM_volume;
2258 Mp3WriteRegister(SCI_AICTRL0, MP3AICTRL0.word);
2259
2260 // Enable Mixer Patch.
2261 MP3AIADDR.word = 0x0F00;
2262 Mp3WriteRegister(SCI_AIADDR, MP3AIADDR.word);
2263 }
2264}
2265
2266//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2267// Global Function
2268
2277 for ( ; *s && !isalpha(*s); ++s)
2278 ; // skip leading non-alpha chars.
2279 if(*s == '\0')
2280 return s; // there are no alpha characters.
2281
2282 char *tail = s + strlen(s);
2283 for ( ; !isalpha(*tail); --tail)
2284 ; // skip trailing non-alpha chars.
2285 *++tail = '\0'; // truncate after the last alpha.
2286
2287 return s;
2288}
2289
2298bool isFnMusic(char* filename) {
2299 int8_t len = strlen(filename);
2300 bool result;
2301 if (len > 4 &&
2302 (!strcasecmp(filename + len - 4, ".mp3")
2303 || !strcasecmp(filename + len - 4, ".aac")
2304 || !strcasecmp(filename + len - 4, ".wma")
2305 || !strcasecmp(filename + len - 4, ".wav")
2306 || !strcasecmp(filename + len - 4, ".fla")
2307 || !strcasecmp(filename + len - 4, ".mid"))) {
2308
2309 result = true;
2310 } else {
2311 result = false;
2312 }
2313 return result;
2314}
static void Mp3WriteWRAM(uint16_t, uint16_t)
Write a VS10xx WRAM Location.
static void spiInit()
Initialize the SPI for VS10xx use.
uint8_t getDifferentialOutput()
Get the current SM_DIFF setting from the VS10xx chip.
void resumeDataStream()
Unpause streaming data to the VSdsp.
static void dcs_low()
Select Data Channel.
uint8_t VolL
contains a local value of the VSdsp's master volume left channels
void setDifferentialOutput(uint16_t)
Set the current SM_DIFF setting of the VS10xx chip.
uint16_t getVolume()
Get the current volume from the VS10xx chip.
uint16_t memoryTest()
Perform Memory Test.
static void cs_low()
Select Control Channel.
static void dcs_high()
Deselect Data Channel.
static void Mp3WriteRegister(uint8_t, uint8_t, uint8_t)
Write a value a VSDsp's register.
uint8_t VolR
contains a local value of the VSdsp's master volume Right channels
void trackAlbum(char *)
Get Track's Album.
uint16_t getBassFrequency()
Get the current Bass Frequency limit from the VS10xx chip.
void setBassFrequency(uint16_t)
Set the current Bass Boost Frequency limit cutoff in VS10xx chip.
uint8_t disableTestSineWave()
Disable Test Sine wave.
state_m getState()
Get the current state of the device.
static state_m playing_state
Boolean flag indicating if filehandle is streaming.
void stopTrack()
Gracefully close track and cancel refill.
void setBitRate(uint16_t)
Force bit rate.
uint8_t begin()
Initialize the MP3 Player shield.
static SdFile track
Initializer for the instance of the SdCard's static member.
uint8_t skipTo(uint32_t)
Skips to a certain point in the track.
uint8_t ADMixerLoad(char *)
Initially load ADMixer patch and configure line/mic mode.
uint8_t isPlaying()
Inidicate if a song is playing?
uint8_t playMP3(char *, uint32_t timecode=0)
Begin playing a mp3 file by its filename.
uint8_t playTrack(uint8_t)
Begin playing a mp3 file, just with a number.
void setEarSpeaker(uint16_t)
Set the current Spatial EarSpeaker setting of the VS10xx chip.
void SendSingleMIDInote()
Play hardcoded MIDI file.
int8_t getBassAmplitude()
Get the current Bass boost amplitude from the VS10xx chip.
int8_t setVUmeter(int8_t)
enable VSdsp VU Meter
uint8_t bitrate
contains a local value of the beleived current bit-rate.
void getAudioInfo()
Display various Audio information from the VSdsp.
static void cs_high()
Deselect Control Channel.
int8_t getVUmeter()
get the status of the VSdsp VU Meter
void setTrebleFrequency(uint16_t)
Set the current treble frequency limit in VS10xx chip.
uint32_t currentPosition()
Current timecode in ms.
uint16_t getMonoMode()
Get the current Stereo/Mono setting of the VS10xx output.
void end()
Disables the MP3 Player shield.
static uint16_t Mp3ReadWRAM(uint16_t)
Read a VS10xx WRAM Location.
int8_t getTrebleAmplitude()
Get the current Treble Amplitude from the VS10xx chip.
static uint32_t spi_Max_Rate
Rate of the SPI to be used with communicating to the VSdsp.
void setBassAmplitude(uint8_t)
Set the current Bass Boost amplitude in VS10xx chip.
void setVolume(uint8_t, uint8_t)
Store and Push member volume to VS10xx chip.
uint16_t getTrebleFrequency()
Get the current Treble Frequency limit from the VS10xx chip.
void setTrebleAmplitude(int8_t)
Set the current Treble Amplitude in VS10xx chip.
void getBitRateFromMP3File(char *)
Read the Bit-Rate from the current track's filehandle.
static void refill()
Refill the VS10xx buffer with new data.
uint8_t VSLoadUserCode(char *)
load VS1xxx with patch or plugin from file on SDcard.
static void available()
Public interface of refill.
void pauseDataStream()
Pause streaming data to the VSdsp.
void ADMixerVol(int8_t)
Set ADMixer's attenuation of input to between -3 and -31 dB otherwise disable.
void setMonoMode(uint16_t)
Set the current Stereo/Mono setting of the VS10xx output.
uint8_t vs_init()
Initialize the VS10xx Audio Decoder Chip.
void setPlaySpeed(uint16_t)
Set the current playSpeed of the VS10xx chip.
int16_t getVUlevel()
get current measured VU Meter
uint32_t start_of_music
contains a filehandles offset to the begining of the current file.
static void disableRefill()
Disable the Interrupts for refill.
uint8_t getEarSpeaker()
Get the current Spatial EarSpeaker setting from the VS10xx chip.
void trackTitle(char *)
Get Track's Title.
bool resumeMusic()
Resume music from where it was paused.
static void enableRefill()
Enable the Interrupts for refill.
void pauseMusic()
Pause music.
static uint16_t Mp3ReadRegister(uint8_t)
Read a VS10xx register.
uint8_t enableTestSineWave(uint8_t)
Generate Test Sine wave.
uint8_t skip(int32_t)
Skips to a duration in the track.
void getTrackInfo(uint8_t, char *)
Fetch ID3 Tag information.
uint16_t getPlaySpeed()
Get the current playSpeed from the VS10xx chip.
void trackArtist(char *)
Get Track's Artist.
static void flush_cancel(flush_m)
flush the VSdsp buffer and cancel
static uint8_t mp3DataBuffer[32]
Buffer for moving data between Filehandle and VSdsp.
A handler for accessing bytes of a word.
uint16_t word
whole word value
uint8_t byte[2]
individual bytes
A handler for accessing nibbles of the SCI_BASS word.
struct vs1053::sci_bass_m::@122063340134256071104100347103242272313255100340 nibble
individual Nibbles
uint16_t word
whole word value
#define MIDI_NUMBER_OF_TRACKS
static const uint16_t bitrate_table[15][6] PROGMEM
bitrate lookup table
int8_t irq
External reference to the interrupt identifier for MP3_DREQ.
#define MIDI_CHUNK_SIZE
bool isFnMusic(char *filename)
is the filename music
#define MIDI_EVENT_NOTE_OFF
#define MIDI_EVENT_NOTE_ON
#define MIDI_CHUNKSIZE
#define MIDI_TIME_DIVISION
#define MIDI_HDR_CHUNK_ID
#define MIDI_END_OF_TRACK
PROGMEM const uint8_t SingleMIDInoteFile[]
a MIDI File of one Note
char * strip_nonalpha_inplace(char *s)
chomp non printable characters out of string.
#define MIDI_FORMAT
#define MIDI_TRACK_CHUNK_ID
Header file for the vs1053_avr_renesas_uno library.
#define para_playSpeed
A macro of the WRAM para_playSpeed register's address (R/W)
#define SCI_AICTRL0
A macro of the SCI AICTRL[x] register's address (R/W)
#define SM_LINE1
A macro of the SM_LINE1 bit mask of the SCI_MODE register.
#define para_MonoOutput
A macro of the WRAM para_MonoOutput register's address (R/W)
SdFat sd
SdFat sd;.
#define SCI_BASS
A macro of the SCI BASS register's address (R/W)
#define TRACK_TITLE
A macro of the offset for the track's Title.
state_m
State of the vs1053 device.
@ testing_sinewave
@ paused_playback
#define para_byteRate
A macro of the WRAM para_byteRate register's address (R/W)
#define SCI_CLOCKF
A macro of the SCI CLOCKF register's address (R/W)
int8_t irq
External reference to the interrupt identifier for MP3_DREQ.
#define TRACK_ARTIST
A macro of the offset for the track's Artist.
#define SCI_HDAT0
A macro of the SCI HDAT0 register's address (R/W)
#define para_endFillByte
A macro of the WRAM para_endFillByte register's address (R/W)
#define SM_EARSPEAKER_HI
A macro of the SM_EARSPEAKER_HI bit mask of the SCI_MODE register.
#define SCI_AICTRL3
A macro of the SCI AICTRL[x] register (R/W)
#define SS_VU_ENABLE
A macro of the SS_VU_ENABLE bit mask of the SCI_STATUS register.
#define SCI_AIADDR
A macro of the SCI AIADDR register's address (R/W)
#define FALSE
#define SCI_HDAT1
A macro of the SCI HDAT1 register's address (R/W)
#define SM_RESET
A macro of the SM_DIFF bit mask of the SM_RESET register.
#define SM_CANCEL
A macro of the SM_DIFF bit mask of the SCI_MODE register.
char * strip_nonalpha_inplace(char *s)
chomp non printable characters out of string.
#define SCI_VOL
A macro of the SCI VOL register's address (R/W)
#define SM_EARSPEAKER_LO
A macro of the SM_EARSPEAKER_LO bit mask of the SCI_MODE register.
#define SM_TESTS
A macro of the SM_TESTS bit mask of the SCI_MODE register.
#define SM_SDINEW
A macro of the SM_SDINEW bit mask of the SCI_MODE register.
flush_m
How to flush the VSdsp's buffer.
@ pre
Flush First.
@ none
Don't Flush.
@ post
Flush After.
@ both
Flush both First and After.
#define para_version
A macro of the WRAM para_version register's address (R/W)
#define SCI_STATUS
A macro of the SCI STATUS register's address (R/W)
#define SCI_DECODE_TIME
A macro of the SCI Decode Time register's address (R/W)
#define SM_DIFF
A macro of the SM_DIFF bit mask of the SCI_MODE register.
#define TRACK_ALBUM
A macro of the offset for the track's Album.
#define SCI_WRAMADDR
A macro of the SCI WRAMADDR register (W)
#define SCI_MODE
A macro of the SCI MODE register's address (R/W)
#define SCI_WRAM
A macro of the SCI WRAM register's address (R/W)
#define PERF_MON_PIN
A macro to configure a Pin to analyze performance.
#define MP3_DREQ
A macro to configure the DREQ pin.
#define MP3_RESET
A macro to configure the RESET pin.
#define MP3_XCS
A macro to configure the XCS pin.
#define MP3_XDCS
A macro to configure the XDCS pin.