Forum Replies Created

Viewing 12 posts - 1 through 12 (of 12 total)
  • Author
    Posts
  • in reply to: SFEMP3Shield works with Arduino Due #2838

    the_ether
    Member

    Thanks very much. You’ve been very kind. Based on what you have said it would seem that I have a hardware problem, perhaps a poor solder connection. I’ll have a look at it again later this week and will keep you updated.

    in reply to: SFEMP3Shield works with Arduino Due #2832

    the_ether
    Member

    I think that there is a misunderstanding. I am not using an IR receiver. I only have the Due and the Sparkfun MP3 shield.

    1- I saw the use of USE_ARDUINO_SPI_LIBRARY in Sd2Card.cpp but since we use a different chip select pin for the SD card and for the MP3 chip I couldn’t see why there should be a conflict.

    Any way, evidently there is a conflict so either I change SFEMP3Shield.cpp to use the native DMA capability of the Due or I set USE_ARDUINO_SPI_LIBRARY to 1. I’ll keep life simple and stick to setting USE_ARDUINO_SPI_LIBRARY to 1.

    2- I understand the extended SPI functionality and the use of SPI_CONTINUE and SPI_LAST. I was just surprised that only using SPI_LAST should cause problems. I suppose it’s because there needs to be some kind of delay between each write if SPI_LAST is used.

    More importantly, I was surprised that the source code that I downloaded from you used SPI_LAST for every write which doesn’t work for me. Either the source code on GitHub is not the same version as you’re using or I have a hardware issue.

    I suppose that it’s possible that yours worked purely by luck and that the clock frequencies of my system are very slightly different – just enough to cause problems.

    3- “I assume you want to say SFEMP3Shield::playMP3() instead of SFEMP3Shield::begin()”

    Yes. Apologies, my mistake.

    Yes, I do call SFEMP3Shield::available() in my loop() function.

    I have tried MP3Shield_Library_Demo.ino and I have the same problems – whether I have #define USE_MP3_REFILL_MEANS USE_MP3_Polled or #define USE_MP3_REFILL_MEANS USE_MP3_INTx.

    I have tried two different MP3 files: one I created myself and one I downloaded from Amazon. The Amazon properties are:

    sample rate of 44.1kHz, 16 bit, 250kbps, contains album art and ID Tags ID3v2.3 and v1.1

    My file is:

    sample rate of 44.1kHz, 16 bit, 223kbps, contains ID Tags ID3v2.3 and v1.1

    “That means your file plays entirely with that modification?”

    No. Unfortunately neither of the two MP3 files I have tried work.

    What I see is that SFEMP3Shield::refill() gets called several times but the total number of bytes written to the MP3 chip is less than 2kB. The exact amount varies each time I reset the chip but is never more than 2048 bytes.

    Since there is a variation, it feels to me like there is some kind of clocking problem. Maybe something is too fast or there needs to be a pause between a read or write maybe.

    4- I have tried changing setup() so as to no longer try and play an MP3 file but instead run the memory test, SFEMP3Shield::memoryTest(). I get a result of 0. The correct answer should be 0x83ff (see p67 of the data sheet http://www.vlsi.fi/fileadmin/datasheets/vlsi/vs1053.pdf).

    BTW, the definition of SFEMP3Shield::memoryTest() is wrong. It is defined as returning an unsigned value. This should be changed to signed since the function can return -1. Same for SFEMP3Shield::disableTestSineWave() and SFEMP3Shield::enableTestSineWave().

    I wonder if I have a hardware problem. However:

    – I can read the contents of a text file on my SD card with no problems;
    – the diagnostic print outs from SFEMP3Shield::vs_init() , SCI_Mode and SCI_Status are correct.

    5- The diagnostic print out for SCI_ClockF in SFEMP3Shield::vs_init() I get is 0. Is that the correct value?

    in reply to: SFEMP3Shield works with Arduino Due #2830

    the_ether
    Member

    Thank you for continuing to help me. I couldn’t do this without you.

    Yes, the patch files have been copied. Yes, I am using sdfatlib20130629.

    1- Okay, changing USE_ARDUINO_SPI_LIBRARY 1 fixes the problem and MP3_XCS drops to 0V

    But why does changing USE_ARDUINO_SPI_LIBRARY affect this? That macro is in the SDFat stuff. The problem I was getting occurred early in SFEMP3Shield::vs_init() before the patch files are loaded and AFAIK, no SD card access is taking place (except for the initialisation of the SD card before the MP3 chip initialisation). I was not getting any problems when simply accessing a file on the SD card when USE_ARDUINO_SPI_LIBRARY was 0. So why should a setting in SDFat affect the initialisation of the MP3 chip?

    2- I changed SFEMP3Shield::spiTransfer() from
    return SPI.transfer( MP3_XCS, value, SPI_CONTINUE );

    to

    return SPI.transfer( MP3_XCS, value, SPI_LAST );

    and I get problems again. Any idea why that should be? I was hoping to make a version that could use pins other than 4 and 10. I thought that the only extended API stuff was just using SPI_CONTINUE and that the default SPI calls used SPI_LAST anyway.

    3- I now have a new problem. This seems the same as I used to have when trying Bill’s version of the software.

    I have #define USE_MP3_REFILL_MEANS USE_MP3_Polled. When I call MP3player.begin() the following happens.

    In MP3player.begin() there are the lines:

    playing_state = playback;
    Mp3WriteRegister(SCI_DECODE_TIME, 0);

    In SFEMP3Shield::Mp3WriteRegister() it has:

    if(playing_state == playback)
    refill()

    SFEMP3Shield::refill() then keeps on pulling data from the SD card

    After about 54 seconds, there is no more data to read from the file on the SD card and track.close() is called. I hear no sound during this time.

    The MP3 file is 8,908,772 bytes which, according to the file properties in Windows, should play for 5 minutes and 19 seconds. So it would seem that digitalRead(MP3_DREQ) is always returning TRUE. So either no data is getting to the MP3 chip or MP3_DREQ is not going low.

    In case it means something, uncommenting lines 230 to 241 in SFEMP3Shield.ccp means I get the following diagnostic data:

    SCI_Mode (0x4800) = 0x4800
    SCI_Status (0x48) = 0x48
    SCI_ClockF = 0x0
    MP3Clock = 6000

    I see that in SFEMP3Shield::refill() you have:

    for(uint8_t y = 0 ; y < sizeof(mp3DataBuffer) ; y++) {
    //while(!digitalRead(MP3_DREQ)); // wait until DREQ is or goes high // turns out it is not needed.
    spiLastTransfer(mp3DataBuffer[y]); // Send SPI byte
    }

    Why call spiLastTransfer() for every write instead of spiTransfer() for all but the last one?

    I just tried replacing the above with this:

    uint8_t y;
    for(y = 0 ; y < (sizeof(mp3DataBuffer) – 1) ; y++) {
    //while(!digitalRead(MP3_DREQ)); // wait until DREQ is or goes high // turns out it is not needed.
    spiTransfer( mp3DataBuffer[y] ); // Send SPI byte
    }
    spiLastTransfer( mp3DataBuffer[y] ); // Send SPI byte

    Things now appear to work properly.

    Why didn’t you have the same problem and why should it matter if spiLastTransfer() is called for every write?

    in reply to: SFEMP3Shield works with Arduino Due #2826

    the_ether
    Member

    Thanks for your reply.

    1- No, not pins 10 to 12, but pins 11 to 13 of the Sparkfun shield are bent and connected to the Due’s SPI. (Trick question, eh? ūüėČ )

    2- Yes, SD card works fine.

    3- I originally tried Bill’s branch and after some time realised that it is only partially complete. I have been trying yours lately and the current problems are when using yours.

    Yes, I understand the low to high bit about SPI transfer. I pause the program straight after the call spiTransfer(0x03). You edited spiTransfer() so that it calls SPI.transfer( MP3_XCS, value, SPI_CONTINUE ). This means that CS should be low after the transfer. It should only go high after the line, spiLastTransfer(0xFF).

    The only obvious difference between my and your setups is that you cut a track on the Sparkfun shield for pin 4 which is normally connected to GPIO1. I’m not using pin 4 so I can’t see that being an issue.

    in reply to: SFEMP3Shield works with Arduino Due #2824

    the_ether
    Member

    gallegojm, I’m having problems getting things to work properly. Have I forgotten some configuration setting?

    I’m using the Sparkfun MP3 shield with the Due only, no Ethernet shield. I have modified SFEMP3ShieldConfig.h to set MP3_XCS to 10 under #ifdef __arm__

    I have bent pin 6 of the Sparkfun card and used a jumper lead to connect pin 6 of the Sparkfun card to pin 10 of the Sparkfun (i.e. pin 10 of the Due).

    The problem is that pin 10 never seems to go low. It is always high.

    As a result, SFEMP3Shield::vs_init() fails and returns 4. This is because Mp3ReadRegister(SCI_MODE) returns 0xFFFF.

    In SFEMP3Shield::Mp3ReadRegister() I paused the program just after the line spiTransfer(0x03). Using my voltmeter I can see that the MP3_XCS pin (i.e. pin 10 in my case) is 3.3V, i.e. high. It ought to be low. The same thing happens if I set MP3_XCS to 4 in the config file. Pin 4 always stays high.

    However, if I set MP3_XCS to another pin such as 50, then that pin goes low.

    Any ideas?

    in reply to: SFEMP3Shield works with Arduino Due #2822

    the_ether
    Member

    Thanks for your reply. So as I understand it, SDFat doesn’t use extended SPI functionality but the SPI implementation means that it defaults to use pin 52 anyway. Since we are using an SD card which needs SPI and also MP3 which needs SPI, we can’t use pin 52 for the MP3 chip otherwise the SD card access and MP3 chip access would get confused. We can therefore only use pin 4 or pin 10 as the chip select pin for the MP3 chip when using the Due (if we want to use extended SPI capabilities).

    Also, as I understand it the way you have modified the SFEMP3Shield software, we can only use extended SPI when using a Due.

    in reply to: SFEMP3Shield works with Arduino Due #2816

    the_ether
    Member

    gallegojm, I didn’t understand your comment, “pin 52 is the default CS when former SPI functions are used. This the case of SdFat library.”

    What do you mean by “former SPI functions”? I didn’t see anything referring to pin 52 in SdFatConfig.h

    in reply to: Strange behaviour with Due #2768

    the_ether
    Member

    The problem seems to be that the line while(digitalRead(MP3_DREQ)) in SFEMP3Shield::refill() is always true for some reason. Any idea how that could be?

    I’ve checked the value of¬†digitalRead(MP3_DREQ) in various places leading up to initialisation. It is zero up until¬†vs_init() is called in¬†SFEMP3Shield::begin() which implies there is not a hardware problem – at least not with that I/O port. SPI would also seem to be fine judging from my ability to read data from the SD card.

    Could I have a chip select issue?

    BTW, I also tried the FilePlayer example. Initialisation is fine and it lists the MP3 files correctly but then I see the same problems when trying to play a file.

    I also get the same problems if I do not define USE_MP3_REFILL_MEANS.

     

    in reply to: Suggested refinements #2659

    the_ether
    Member

    I don’t believe that there is a problem with the rate of transmission / ingestion. SPI sends the data in serial form. The rate at which the data is sent can be set up to a maximum rate defined by the hardware specification. That defined rate should be sufficient. If there was ever a concern otherwise then a lower clock rate should be set. After all, why only pause by checking for a response from the slave every 8 bits, we could have stomped on data before then.

    Furthermore, there is already an inherent delay between sending bytes. The time taken to call the routine SPIClass::transfer(), the initial steps of that routine prior to sending data and the steps taken by the calling routine before every call already constitute an appreciable delay.

    My view is that¬†SPIClass::transfer() has been written for generic devices. Some may respond after a byte has been sent with eg an error message, or the slave may send an unsolicited message and if it weren’t read quickly it could be lost. But with the VLSI chip there is a separate line used for handshaking (DREQ) and AFAIK, there are no unsolicited messages to expect.

    So in the specific case of sending data to this VLSI chip I do not see a need to read after every byte has been sent, only to check DREQ after every 32 bits.

    in reply to: Suggested refinements #2657

    the_ether
    Member

    That’s a pain.

    Just for completeness, in case this subject comes up again, according to this site, http://forum.arduino.cc/index.php?topic=132130.0 and http://arduino.cc/en/Reference/DueExtendedSPI the Due has three pins that could be used for chip select: D10 (same as D77), D4 (same as D87) or D52.

     

    BTW, does¬†SPIClass::transfer()¬†really need to read back from SPI every time we write to the MP3 shield? I’m wondering why there are aren’t separate read() and write() methods instead and whether just writing would be faster when writing audio data.

    in reply to: Suggested refinements #2655

    the_ether
    Member

    I’m not sure I agree with what you say about the usefulness of the¬†SPI_CONTINUE flag. Here’s the source code for¬†SPIClass::transfer():

    byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) {

    uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);

     

    // Reverse bit order

    if (bitOrder[ch] == LSBFIRST)

    _data = __REV(__RBIT(_data));

     

    uint32_t d = _data | SPI_PCS(ch);

     

    if (_mode == SPI_LAST)

    d |= SPI_TDR_LASTXFER;

     

    // SPI_Write(spi, _channel, _data);

    while ((spi->SPI_SR & SPI_SR_TDRE) == 0)

    ;

    spi->SPI_TDR = d;

     

    // return SPI_Read(spi);

    while ((spi->SPI_SR & SPI_SR_RDRF) == 0)

    ;

    d = spi->SPI_RDR;

     

    // Reverse bit order

    if (bitOrder[ch] == LSBFIRST)

    d = __REV(__RBIT(d));

    return d & 0xFF;

    }

    Note that if¬†SPI_LAST is passed as a flag, d is OR’d with¬†SPI_TDR_LASTXFER and d (a 32-bit word) is written to the SPI port. So passing the SPI_CONTINUE flag does not simply affect how the Arduino code keeps track of the CS.

    Thanks for the tip re.¬†OutputCompare¬†. I’ll try and find more information about it.

    in reply to: Suggested refinements #2651

    the_ether
    Member

    Thank you for your very thorough reply.

    Although the actual transfer speeds may be the same, I’d still have thought that the time spent by the CPU would overall be less if transferring say, 64 bytes instead of 2 x 32 bytes. Although the difference maybe small there is the set up times for a transfer from the SD card to the CPU and then from the CPU to the DAC chip. Just the act of calling any method (eg rack.read() or dcs_low()) takes CPU cycles to push / pull parameters from the stack and make the jump. When using the Due-only SPI extensions, that difference in CPU time should be greater though probably not an awful lot.

    This is probably all nit-picking. I’m not sure what percentage difference it would make.

    I’ll be using the Sparkfun MP3 shield so I’m not sure that the channel selection capability of the Due helps. If I understand correctly, the shield uses specific output pins of the Due which can’t be changed without soldering a new connection. However, what does help is the ability of the Due to specify that a transfer will comprise of several bytes through the use of the¬†SPI_CONTINUE parameter, eg:
    It’s possible to send more than one byte in a transaction by telling the the transfer command to not deselect the SPI device after the transfer :

    void loop(){
    //transfer 0x0F to the device on pin 10, keep the chip selected
    SPI.transfer(10, 0xF0, SPI_CONTINUE);
    //transfer 0x00 to the device on pin 10, keep the chip selected
    SPI.transfer(10, 0×00, SPI_CONTINUE);
    //transfer 0x00 to the device on pin 10, store byte received in response1, keep the chip selected
    byte response1 = SPI.transfer(10, 0×00, SPI_CONTINUE);
    //transfer 0x00 to the device on pin 10, store byte received in response2, deselect the chip
    byte response2 = SPI.transfer(10, 0×00);
    }

    The parameter SPI_CONTINUE ensures that chip selection is keep active between transfers. On the last transfer SPI_CONTINUE is not specified as it’s the last byte transferred.

    The above excerpt was taken from: http://arduino.cc/en/Reference/DueExtendedSPI

    In my case I will be running a stepper motor concurrently with playing music. Since the VLSI chip has a 2kbyte buffer, it is not a real-time device and can be handled with a lower priority than the motor which must receive a pulse at a specific time so as to maintain a specific velocity or acceleration. So for my specific case, what I am planning is to use a timer for generating the next motor pulse. I would then have a simple loop that polled the VLSI chip to see if I needed to send more data. Since the motor would be driven by a timer-based interrupt, it would have top priority by interrupting any step involving music playback.

    What I’m not sure about is the best method of checking when to send more data to the VLSI chip. Constantly calling¬†digitalRead(MP3_DREQ) would seem to be the least efficient. Testing the specific bit on the port would seem to be faster, but what I might do is have a timer-driven interrupt that simply sets a flag. My main loop would then need simply check the status of that flag. Although the triggering of that timer would interrupt any currently executing step involving the motor, the time taken for the method to be called that only sets one flag should be insignificantly small. Using a timer would also give me the flexibility of less frequent transfers too if I so wanted. However there is a downside of increased complexity with having too many timers. Maybe I should just keep it simple by testing elapsed time instead of using a timer.

    Your views would be very welcome.

    Thanks for the link to the forum discussion re. the Ethernet and MP3 shields connected to a Due. If I have understood correctly, you say that the use of the new SPI_CONTINUE parameter has no real world benefit. Is that correct? According to the Arduino page I listed above:

    The chip selection is handled automatically by the SPI controller, the transfer command implies the following:

    Select device by setting pin 4 to LOW
    Send 0xFF through the SPI bus and return the byte received
    Deselect device by setting pin 4 to HIGH

    So from reading the other forum I think you made your conclusion from reading the source code whereas the above implies that the chip is automatically selecting / deselecting which maybe is not evident from reading the Arduino source code.

Viewing 12 posts - 1 through 12 (of 12 total)