writing a class function for the VS1053

I'm trying to create a class function that will play various sound files in response to input [the more complex version of this will utilize a MPR121]. As an experiment in understanding how class functions / libraries work in C++, I wrote this:

/*
  MorseSound.cpp - Library for using VS1053 to play sounds as if they were Morse code.
*/

#include "Arduino.h"
#include "MorseSound.h"
#include <Adafruit_VS1053.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>

MorseSound::playFullFile(const char *trackname) { //this is where the problem lies
  if (! startPlayingFile(trackname)) return false;

  while (playingMusic) {
    // twiddle thumbs
    noInterrupts();
    feedBuffer();
    interrupts();
    delay(100);           // give IRQs a chance
  }
  // music file finished!
  return true;
}

MorseSound::MorseSound(int pin) //is this needed? if so where should I point the pin?
{
  pinMode(pin, OUTPUT);
  _pin = pin;
}

void MorseSound::dot()
{
  playFullFile("DO.WAV");
  delay(250);
}

void MorseSound::dash()
{
  playFullFile("LA.WAV");
  delay(250);
}

with the full setup from Adafruit's VS1053 and this simple loop borrowed from the Morse code example:

void loop()
{
  morse.dot(); morse.dot(); morse.dot();
  morse.dash(); morse.dash(); morse.dash();
  morse.dot(); morse.dot(); morse.dot();
  delay(3000);
}

I'm getting the error message: "prototype for 'int MorseSound::playFullFile(const char*)' does not match any in class 'MorseSound'". clearly I need to call the VS1053 code somehow / to create a variable to hold fileplayer and then redefine it here? what am I missing in terms of understanding the VS1053 code?

What is in MorseSound.h?

/*
MorseSound.h - Library for making Morse code sounds.

*/
#ifndef MorseSound_h
#define MorseSound_h

#include "Arduino.h"
#include <Adafruit_VS1053.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>

class MorseSound
{
public:
MorseSound(int pin); // do i need a pin?
void dot();
void dash();
void playFullFile();
private:
int _pin;
};

#endif

  void playFullFile();``MorseSound::playFullFile(const char *trackname) {

"prototype for 'int MorseSound::playFullFile(const char*)' does not match any in class 'MorseSound'

Clear now?

MorseSound(int pin); // do i need a pin?

When in doubt, toss it out. You will either find out why its there and learn something. Or, find out it wasn't needed and make your problem simpler to deal with.

-jim lee

You should NOT be setting the mode of a pin in your constructor. The hardware is not ready yet.

You should have a begin() method where you set the mode of pins and do other hardware-dependent stuff.

AWOL:

   void playFullFile();
"prototype for 'int MorseSound::playFullFile(const char*)' does not match any in class 'MorseSound'

Clear now?

should I put playFullFile() into the .cpp file? rather than include the (const char*)?
I will try it, but I am not clear on what you are communicating here.

but I am not clear on what you are communicating here.

You defined a function that takes no arguments. You are calling it with an argument. The compiler is telling you that you can not do that. AWOL pointed out where you defined the function and the compiler message related to that function.

Either it takes an argument (the name of the file to play) and the declaration of the function is wrong, or it doesn't and the call is wrong.

Do I need to replicate more of the VS1053 code in my MorseSound.cpp file?

I've altered the cpp and the header files

/*
  MorseSound.cpp - Library for using VS1053 to play sounds as if they were Morse code.
*/

#include "Arduino.h"
#include "MorseSound.h"
#include <Adafruit_VS1053.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>


void MorseSound::playFullFile() {
	playFullFile();
}

void MorseSound::dot()
{
  playFullFile("DO.WAV");  // the error message is pointing here
  delay(250);
}

void MorseSound::dash()
{
  playFullFile("LA.WAV"); // the error message is pointing here
  delay(250);
}

the header:

/*
  MorseSound.h - Library for making Morse code sounds.
  
*/
#ifndef MorseSound_h
#define MorseSound_h

#include "Arduino.h"
#include <Adafruit_VS1053.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>

class MorseSound
{
  public: 
  void dot();
  void dash();
  void playFullFile();
  
private:
  const char _trackname;
};

#endif

and am now getting the error message: "no matching function for call to 'MorseSound::playFullFile(const char [7])'"

made a few changes...

header file:

class MorseSound
{
  public: 
  void dot();
  void dash();
  void playFullFile(const char _trackname);
  
private:
  const char _trackname;
  const char *trackname;
};

cpp file:

void MorseSound::playFullFile(const char _trackname) {
	playFullFile(*trackname);
}

void MorseSound::dot()
{
  playFullFile("DO.WAV");
  delay(250);
}

void MorseSound::dash()
{
  playFullFile("LA.WAV");
  delay(250);
}

and the ino file:

void loop()
{
  MorseSound.dot(); MorseSound.dot(); MorseSound.dot();
  MorseSound.dash(); MorseSound.dash(); MorseSound.dash();
  MorseSound.dot(); MorseSound.dot(); MorseSound.dot();
  delay(3000);
}

now the error message is: "request for member 'dot' in 'MorseSound', which is of non-class type 'MorseSound()'".

The .Ino file you posted doesn't compile because it is incomplete, but MorseSound.dot();looks a bit odd because MorseSound is the name of the class, not the instance I assume you're using.

  void playFullFile(const char _trackname);

So, you have files that have one letter names?

  playFullFile("DO.WAV");

I didn't think so.

so this version works, but I've commented out the library:

/*
  MorseSound.ino - play sounds as if they were Morse code.
*/

//#include "MorseSound.h"
#include <Adafruit_VS1053.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>

const char *trackname;

int irqpin = 2; // That means pins 6, 7, 8, 9 and the 6 analog in pins (also known as digital i/o pins 14-20) are available

// define the pins used
#define CLK 13       // SPI Clock, shared with SD card
#define MISO 12      // Input data, from VS1053/SD card
#define MOSI 11      // Output data, to VS1053/SD card


// These are the pins used for the music maker shield
#define SHIELD_RESET  8      // VS1053 reset pin (unused!)
#define SHIELD_CS     7      // VS1053 chip select pin (output)
#define SHIELD_DCS    6      // VS1053 Data/command select pin (output)

// These are common pins between breakout and shield
#define CARDCS 4     // Card chip select pin
// DREQ should be an Int pin, see http://arduino.cc/en/Reference/attachInterrupt
#define DREQ 3       // VS1053 Data request, ideally an Interrupt pin

Adafruit_VS1053_FilePlayer musicPlayer = 
  // create shield-example object!
  Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);


void dot()
{
  musicPlayer.playFullFile("DO.WAV");
  delay(250);
}

void dash()
{
  musicPlayer.playFullFile("LA.WAV");
  delay(250);
}


void setup() {

  Serial.begin(9600);
  Wire.begin();
  Serial.println("Adafruit VS1053 Simple Test");

  if (! musicPlayer.begin()) { // initialise the music player
     Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
     while (1);
  }
  Serial.println(F("VS1053 found"));
  
  musicPlayer.sineTest(0x44, 500);    // replace this with an introduction to the LJP
  
  SD.begin(CARDCS);    // initialise the SD card
  
  // Set volume for left, right channels. lower numbers == louder volume!
  musicPlayer.setVolume(20,20);

  // Timer interrupts are not suggested, better to use DREQ interrupt!
  //musicPlayer.useInterrupt(VS1053_FILEPLAYER_TIMER0_INT); // timer int

  // If DREQ is on an interrupt pin (on uno, #2 or #3) we can do background
  // audio playing
  musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);  // DREQ int

}

void loop()
{
 dot(); dot(); dot();
 dash(); dash(); dash();
 dot(); dot(); dot();
  delay(3000);
}

I'm going to experiment with referencing the Adafruit music player in the .cpp and .h files...

S.O.S. ?

You making a distress beacon?

-jim lee

no, no. Just trying to figure out how to integrate the VS1053 library with the MPR121 library && have the music player play different songs based on the length of time (short or long) that the sensor is touched. thought breaking the problem into smaller pieces would help.

my goal is to have something like this:

class electrodeSong
{
  // Class Member Variables
  // These are initialized at startup
  int electrodeTouched;      // the number of the electrode 
  //long durationHeld = touchTime(); // this is already included in the MPR121 code
  char song1;     
  char song2;    

  // Constructor - creates a Song 
  // and initializes the member variables and state
  public:
  electrodeSong(int electrodeTouched, char song1, char song2)
  {
  electrodeTouched = sensor; 
  song1 = fileName;
  song2 = fileName;
  }
   
};

  electrodeSong sensor0(0, "LA.WAV", "SO.WAV");
  electrodeSong sensor1(1, "FA.WAV", "DO.WAV");
// repeat for all 12 sensors
  electrodeSong sensor0(0, "LA.WAV", "SO.WAV");

The second and third arguments are STILL not chars.

When you get it, you'll discover the marvel of arrays.

this is the code from Adafruit VS1053.cpp:

 boolean startPlayingFile(const char *trackname);

& Jim Lee had suggested this:

char filePath[20];

on the Adafruit product forum.... which is why I've continued to gnaw on the problem from this angle.

const char *trackname is a pointer to some memory location where the first of many characters are stored.

char filePath[20] is an array where many characters can be stored.

Both are different from char song1, where ONE character can be stored.

AH!

and can I access classes from other header & cpp files in my own library?

if I define void playfullfile in the cpp, I get one error message: too many arguments to function 'void playFullFile()'
if I don't, I get this: 'playFullFile' was not declared in this scope.

should I create an instance of the File player from the VS1053 code in my header?

thanks everyone for your help. I am going to switch back to working a Switch Case version of the code.