I was looking at the VS1003 lib and thought it would be good to try to playback and MP3 from the SD card, but rather than running both the SD and the VS1003 MP3 player on the same SPI, I thought I’d change the VS1003 lib so that I can add an extra argument to the constructor for the SPI device / Class instance, which is defaulted to SPI
However, I ram into 2 issues
I’m not keen on the style of code here, either,… run with me on this one.
First add an argument for the _spi and default it to SPI
VS1003( uint8_t _cs_pin, uint8_t _dcs_pin, uint8_t _dreq_pin, uint8_t _reset_pin, SPIClass _spi = SPI);
then set the member my_SPI with this in the constructor.
VS1003::VS1003( uint8_t _cs_pin, uint8_t _dcs_pin, uint8_t _dreq_pin, uint8_t _reset_pin, SPIClass _spiChan):
cs_pin(_cs_pin), dcs_pin(_dcs_pin), dreq_pin(_dreq_pin), reset_pin(_reset_pin), my_SPI(_spiChan)
{
}
You could set the priority of the SPI constructor to a lower number (higher priority) than the VS1003 library constructor.
But that means having to change both libraries to add priority numbers.
If we start down that path, of assigning different priorities to each constructor, we may end up with too many of those and then having to go checking libraries to find what has a higher priority than something else.
Either we carefully go around assigning priorities to everything depending on what depends on what else, or we better don’t try to use devices in the constructor.
That is just my opinion. Now, I am sure that if you set a priority to those 2 making the VS the lowest priority one, that should solve the problem for this case. I just don’t like doing it.
Besides that, another option could be to change the VS library constructor, so it instantiates the SPI ports itself before trying to do anything else
I’d rather not go down the route of assigning priorities either.
I will find another way.
At the moment I’m not sure whether my_SPI is null, when the constructor of the VS1003 is called, or whether its something inside SPI that is not valid.
Thinking about it, I’m not even sure what the compiler would have done when I assigned my_SPI = SPI
I.e
I assumed that my_SPI is effectively a pointer to the class object, as is SPI, But I’m a bit hazy on this, as normally if I was not coding for Arduino I would always use new to instantiate a class, which returns pointer to a class, which makes everything a lot more obvious.
Btw, there is also something else odd going on, which hangs the compiler
If a lib needs SPI, it can include SPI.h in its header or cpp, well it seems to need to do this, but if I omit including SPI.h from the sketch, the compiler seems to hang when compiling the lib in question.
I presume this is an Arduino quirk, but it seems odd to hang the compiler.
If a lib needs SPI, it can include SPI.h in its header or cpp, well it seems to need to do this, but if I omit including SPI.h from the sketch, the compiler seems to hang when compiling the lib in question.
I presume this is an Arduino quirk, but it seems odd to hang the compiler.
/*
* ActiveLowBlink - example of using class and inline new
*
*/
#include "ActiveLowLED.h"
inline void* operator new( size_t sz, void* here ) { return here; }
ActiveLowLED &led() {
static char _ActiveLowLED_mem[sizeof(ActiveLowLED)];
static ActiveLowLED *ptr;
if ( !ptr ) {
ptr = new ((void *)_ActiveLowLED_mem) ActiveLowLED(BOARD_LED_PIN,false);
}
return *ptr;
}
void setup() {
// led is initialized in first blink, no setup needed
}
void loop() {
// 2 long blinks
led().blink(50,950);
led().blink(50,950);
delay(1000);
// 4 short blinks
int x = 4;
do {
led().blink(50,450);
} while(--x);
delay(1000);
}
Very, very interesting!
Ray
I can understand why the Arduno team originally did this, but as the capabilities of all devices get more complex, we end up with more and more hacks and work arounds.
I’m inclined to copy the SPI class folder and rename it SPI_STM and remove the global instantiation
Actually, I’d really rather call it something more useful but SPI_NOGLOBAL is perhaps a bit long for a name (but perhaps not)
Then if someone wanted SPI to be SPI device 2, they could declar it themselves
SPIClass SPI(2)
Though I admit, I’m not sure whether other Arduino libs that use SPI as a global would freak out.
I’d need to try it. But perhaps the extern in the SPI header may stop the other libs going mad.
If instantiate the VS1003 class inside setup, it works fine on SPI channel 1 and SPI channel 2.
SPIClass *SPI_2;
void setup () {
Serial.begin(115200);
SPI_2 = new SPIClass(2);
Serial.println("VS1003 test");
player= new VS1003(PC14, PB10, PA8, PA9,*SPI_2); // cs_pin, dcs_pin, dreq_pin, reset_pin
player->begin();
player->modeSwitch(); //Change mode from MIDI to MP3 decoding (Vassilis Serasidis).
// set maximum output volume
player->setVolume(0x00);
}
void loop() {
// play hellomp3 flow each 0.5s ;)
player->playChunk(HelloMP3, sizeof(HelloMP3));
delay(500);
}
I think I have a workaround for this, but I admit I’m not sure why this works.
If I use this as the declaration for the constructor, it doesn’t work
VS1003( uint8_t _cs_pin, uint8_t _dcs_pin, uint8_t _dreq_pin, uint8_t _reset_pin, SPIClass _spi = SPI);
