Forum Replies Created
-
AuthorPosts
-
Michael P. FlagaMember
Please refer to Volume Library it will explain the volume.
Most coding knows what the value sent are so they don’t need to read it. Where below is likely the simplest way to read it and print it.
twobyte mp3_vol;
mp3_vol.word = MP3player.getVolume();
Serial.print(F("Right Volume = "));
Serial.println(mp3_vol.byte[0]);
Serial.print(F("Left Volume = "));
Serial.println(mp3_vol.byte[1]);
Note that the union for twobyte is already defined in the library.
Michael P. FlagaMember
Thanks for the feedback your observations are very astute.
The call to SPI.setClockDivider(spiRate) was implemented as a safeguard. As libraries (aka Drivers) are implemented for different external resources there are often overlap. This is the case with the SPI. Where initially Bill implemented SPI settings in MP3player.resumeDataStream(), as to allow the use of other devices on the SPI, such as Temp Sensors. Where the resumeDataStream() restored the config away from whatever deviations the other SPI devices implemented. That said the SdCard is a SPI device and does not necessarily (or even typically) have the same clock speed as the Vdsp. It is faster and lead to un-reliability in reading back data. Though, miraculously it worked in sending. I re-discovered this in attempts to expand the library and then later found this stated on VSLI’s forum.
So yes it is more overhead to reconfigure the SPI with each block of transfer, but insignificant. It is a necessary requirement for robust and interoperable library/driver. I actually see that the SdFat does this. Never assume shared resources are what you expect.
As you have noted the Vdsp has a 2K buffer, where the driver transfers 32 at a time. Yes, it would appear that it would be a good idea to transfer larger chunks. Whereas there are more subtle issues at hand. First the Vdsp has a 32 byte pre buffer that does not require over fill checking. Hence this driver as recommended by VLSI is to send 32 at a time and then check. While the DREQ check is not required after each byte within the 32bytes, it is still required to allow proper time for the 32B to be transferred. Sending without waiting may cause skips.
It is very insightful watching a logic analyzer scope of the transfers. It reveals that Software or Timer Polling appears more efficient. Note that the library supports several methods of refilling the buffer. Please review http://mpflaga.github.io/Sparkfun-MP3-Player-Shield-Arduino-Library/_s_f_e_m_p3_shield_config_8h.html#a4c60fb7c286789d19f9ed13a19891653 . Where Timer method initially appears to transfers blocks and interrupt continuously feeds the buffer as it needs it. Either way it is cosmetic in that it takes the same amount of time to transfer the data. Looking closer reveals, the overhead of doing smaller blocks versus larger blocks, is mitigated by the need to check and wait for the DREQ internal transfer every 32.
The Due’s Extended SPI is attractive. In that it manages the interchanging of SPI configurations between assigned Chip Selects (aka channels), to avoid above mentioned conflicts. Where in reading the Due’s SPI.cpp it really is only software. The SPI_CONTINUE option is simply for the CS management, as each transfer is still individually done. Where I don’t see it transferring frames, Rather I read the spi.cpp of the SAM as transferring ONE byte at a time, not using the SAM’s internal DMA. Please point me to an example of it sending frames, Versus channels.
I would recommend reading the following thread: http://www.billporter.info/forum/topic/sfemp3shield-works-with-arduino-due/ as I came to the above conclusion in attempting to implement such improvements and found them not actually providing the expected benefits.
Normal
0false
false
falseEN-US
X-NONE
X-NONE/* Style Definitions */
table.MsoNormalTable
{mso-style-name:”Table Normal”;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:””;
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin:0in;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:”Calibri”,”sans-serif”;
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:”Times New Roman”;
mso-bidi-theme-font:minor-bidi;}Michael P. FlagaMemberyes, you can use D10 as an output.
It light up the LED, as your digitalread(D10) came back with a one. I am sure that the spi.begin() in the library initializes the SS (or D10) as an output and likely as 1, driving your LED.
Michael P. FlagaMemberOn the SFE MP3 Shield it IS FREE. But only as an output. It cannot be used as a simple input.
A0,A1,A2,A3,A4,A5,D5 are entirely free. Where D3 and D4 may be used if SJ1 and SJ2 are cut and their cut positions of MIDI and GPIO1 are acceptable for ones application. D1 and D0 can be used if there is no need for Serial, other than Arduino Boot Kernel.
Note: Directly from http://arduino.cc/en/Reference/SPI
Note about Slave Select (SS) pin on AVR based boards
All AVR based boards have an SS pin that is useful when they act as a slave controlled by an external master. Since this library supports only master mode, this pin should be set always as OUTPUT otherwise the SPI interface could be put automatically into slave mode by hardware, rendering the library inoperative.It is, however, possible to use any pin as the Slave Select (SS) for the devices. For example, the Arduino Ethernet shield uses pin 4 to control the SPI connection to the on-board SD card, and pin 10 to control the connection to the Ethernet controller.
OK, so what does that last part mean… The above assumes you already understand what a slave and master means, and along with the implied orientation. In short the SPI can be either Slave or Master. The SdCard and the VS1053 are Slaves, where the Arduino or the underlying ATmega328 is the Master. The slaves have a dedicated input pin for selecting it, allowing other slaves to exist on the same SPI, so that the Master may select one at a time to talk to.
The Arduino’s CPU (ATmega328) can be configured to be a slave. And when so the SS or pin10 can(must) be used as the select, which is an input. But Arduino’s native Libraries only support the ATmega328 as a Master and not as a Slave. So when the ATmega328’s SPI is used as a Master the SS pin means nothing.
The ATmega328’s method of configuring its SPI between Slave or Master modes is determined by the configured direction of SS or pin 10. So when the SS or pin 10 is configured as an input the ATmega328’s SPI is a slave, which is NOT supported by Arduino’s libraries. Basically the SPI does not work. Since the ATmega328 SCK pin is now an input expecting clock, rather than generating clock towards slave, as when a Master. Hence SS or pin10 must be configured as an Output, if one desires the SPI to work (i.e. as a Master). In which that output can by used for any purpose. By convenience it is often used to drive the enable of the attached slave SPI devices. But it could be any digital output that drives external slaves enables, it does not have to be SS (as it means nothing in master mode). On the SFE MP3 Shield D6, D7 and D8 are used as SPI slave selects of for the SdCard (D8) and VS1053 (D6-commands and D7 for audio Stream data).
Michael P. FlagaMemberYou need only add
MP3player.stopTrack();
in front of the
MP3player.playTrack(??);
To stop any currently playing tracks, and it won’t care if there is no track playing, it will just fall through.
Michael P. FlagaMemberplease refer to the trouble shooting guide, located at http://mpflaga.github.io/Sparkfun-MP3-Player-Shield-Arduino-Library/
And also search this forum this is not an uncommon symptom.
In short its either a interrupt problem with the shield or an SdCard problem.
Michael P. FlagaMemberSee https://gist.github.com/mpflaga/5569322
Signalonly needs to be typed once and each digital read will over right its prior value. along with no need to compartmentalize as much.note the use of
while(MP3player.isPlaying()) {
//wait until done playing
}with out it you can attempt to play others, but will have an error as it is already playing. Note the commented out line of
MP3player.stopTrack();which will help that if you desire. which won’t work with the abovewhile(MP3player.isPlaying())as you wont’ get to it. So you have some choices.Michael P. FlagaMemberGreat. I recommend you add debug prints so that you know what the code is seeing as input and attempting to do.
Have fun.Michael P. FlagaMemberIts been a while since I updated that section and memory is fading. but I recall that bit rate can be variable, which may lead to incorrect location. So reading the chips is best. Hence I recall it use CBR from file to get started, until the header was complete then used CBR from chip. The real way is to cycle through the jump points frames, which is different for each format. Which is a larger scope.
Michael P. FlagaMemberI have posted GISTHUB with corrected code that compiles at https://gist.github.com/mpflaga/5522030#file-froggy14_mp3_pir-ino
You were basically correct. The pasting of code into wordpress’s web page altered several characters, creating some additional errors.
I believe there were some invisible(or altered) characters in the setVolume line that was making the call not match the signature of the available member functions, resulting in your error.
I simply deleted the whole line and re-typed it. Where a cut and paste carried the problem.
Additionally you needed to instance the “
SdFat sd;” object.Michael P. FlagaMemberIt may have worked. But it was not working for some of the right reasons.
I thought I had sent a follow up this morning, about some items I subsequently learned and some I was perplexed about.The main purpose of the F() and PROGMEM was to avoid the tendency of C++ to place const variables, strings or arrays into and consuming RAM. A dangerous waist, when the AVR is limited to 2K and easily consumed. I don’t recall if the ARM tool chain does this, regardless the SAM3X8E 100K of SRAM is plenty.
Thanks for the links about digital read back problems. In reading the tool chains code and how the ARM’s helper functions are significantly different than the AVR’s, I see how the arduino core wiring_digital.c definition of digitalRead has problems reading back an assigned out. Yuck. This is possible on the ARM, but was skipped in the Arduino Due core library implementation, likely due to its complexity. And I see future room for improvement. (some day, I don’t even have a Due).
This read back is common on most all Micro’s I have worked with. It is common to use it, as it is an actual Register just like RAM, should be just as fast as other RAM. Keeping a copy of it only doubles the work and overhead. And in 8bitters every byte or bit counts, it is too easy to pile up. I have done it. The SFEMP3 library is very efficient on memory. As libraries should be, using as little of a footprint as possible leaving as much as possible for the main objective. You will notice this library does not store copies of parameters internal to the VDSP. But rather gets them.
Regardless the Due as is makes this convoluted. So a copy is simplest, as it has plenty of space.About the DueExtendedSPI, I may be repeating an apparently lost posting from this morning. I read the spi.c for the Due and see the functions are overloaded with original and new enhanced. The later having the channelized Chip Selects. Where I see that only pins D4, D10 and D52 can function as automatic chip selects. Where original commands are still available, without CS and CONTINUE (defaulting to assert D52, anyways). Note the MP3_XCS and MP3_DXCS are correspondingly mapped to D6 and D7, and therefore should not work when placed into ExtendedSPI methods, they actually fall through not matching any of the allowed Chip Selects and assert SS3 (aka D78 not available) by default. I notice your forks dcs_low() uses SPI.setDataMode( MP3_XCS, SPI_MODE0 ) but note that both dcs_low() and cs_low() still have the original digitalWrite(MP3_?XCS, LOW) in them. Hence I believe the d/cs_low()’s are still asserting the correct chip selects D6/D7, making it work.
Note that while the SPI_CONTINUE is nice and sounds more efficient, the SPI.transfer with CS still while() loops and BLOCKING until the transfer is done, to be read back. No real speed increase. So the important reason for including the SPI_CONTINUE, in conjunction with including the CS, is not speed or ease, but to remove the glitch of the CS bouncing between transfers, when using the Extended method. Where it is not truly applicable in the case of MP3_XCS(D6) and MP3_DXCS(D7). As an FYI, I would mention that SdFat’s SPI for the ARM does not use the Arduino Due Core SPI functions but appears to use is own to take advantage of the SAM3X8E DMA features.
That all said I see errors or miss-conceptions in my suggested branch and need to clean them up. I don’t want to be propagating false code.
Michael P. FlagaMemberI have incorporated your changes into a branch for evaluation, that will dynamically detect ARM vs AVR at compile time, along with using some helper functions, to do so. The branch can be found at
https://github.com/mpflaga/Sparkfun-MP3-Player-Shield-Arduino-Library/tree/Due
Give it a try. I have verified that it compiles on IDE 1.0.4 and 1.5.2, along with working for UNO. Where I don’t have a Due to validate.
Where I am still suspicious of the digitalRead(MP3_RESET) problem. And for the moment have used the local mp3Reset.
Michael P. FlagaMemberTry replacing the pinMode 2 through 13 with the below
pinMode(6, OUTPUT); //MP3_XCS
pinMode(7, OUTPUT); //MP3_XDCS
pinMode(8, OUTPUT); //MP3_RESET
digitalWrite(6, HIGH); //negate XCS
digitalWrite(7, HIGH); //negate DXCS
digitalWrite(8, LOW); //Put VS1053 into hardware reset
Put the above code “as the first thing”, into the setup() of each INO that you try: SdInfo.ino, SdFormatter.ino and MP3Shield_Library_Demo.ino.
Michael P. FlagaMemberI have reviewed your code and find the following and some questions about some of them that follow.
1) PROGMEM does not exist on the SAM3X8E.2) There is a problem reading back the MP3reset pin.
3) SPI member functions between UNO and DUE have some differences.
a. SPI.tranfer’s member function requires the Chip Select in the function call.
b. Default setup can’t be used for setBitOrder and setDataMode
c. setClockDivider is obviously different4) attachInterrupt() and detachInterrupt() have changed from INT(x) vector to actual pin.
For the most part we can use either the following to merge a correspondingly distinguish the appropriate code to use:
#ifdef __AVR__
Or
#if defined(__arm__) && !defined(CORE_TEENSY)"
I see the SdFatLib uses the later.What Shield are you using and how have mated it to the DUE?
Other than the MISO,MOSI,SCK of the SPI; Does it require any jumpers? If so please describe.
Or does it work connected straight up ?I have the following concerns:
5) cs_low() and dcs_low(), you have commented out ” SPI.setClockDivider(spiRate);” and not replaced it with “SPI.setClockDivider( MP3_XCS, spiRate );”.
This may appear initially acceptable. Whereas it may not account for SdCard calls’s which the change setClockDivider to faster rates for the SdCard. One cannot assume other user functions don’t change the SPI speed for their purposes. Can you provide a better explanation for this?6) I don’t understand the reason for digitalRead(MP3_RESET) not reading back the MP3_RESET pin. Do you know of a reason for this? Perhaps you could direct me to a Link explaining why. Or is this something you are observing?
I am suspicious this may because of the SparkFun MP3 shield is actually designed for 5V. Where the Due is only 3V which may not be supplying or reading proper signals.
Is it possible that your board or PIN is not actually going low and resetting?Michael P. FlagaMemberyour symptom is identical to that of step #4 of the Gravitech Tutorial. You system is not finding the Sd Card, hence the Error. Which is not with the MP3 library, as it has not gotten to it yet.
have you followed the trouble shooting guide: http://mpflaga.github.io/Sparkfun-MP3-Player-Shield-Arduino-Library/#Troubleshooting
use SdFat Example Library’s QuickStart.ino as to see if it can access the card. Additionaly, SdInfo.ino may indicate if it can mount the card. Which may then need to formatted in FAT16 or FAT32. Where SdFormatter.ino can do this for you.
-
AuthorPosts






