Problem with uint16_t current track count in MD_YX5300 Library

Hi,

I am building an mp3 player for my very small nephew, with an YX-5300 Mp3 player, inspired by this project (sadly with a different chip).

After experimenting with directly sending serial commands via softwareSerial, I am now using the MD_YX5300 library from GitHub - MajicDesigns/MD_YX5300: Library for Serial MP3 Player based on YX5300 IC (Catalex Module), as it works asynchronously, without interruptions.

I can't query the number of files in a folder now - the example code does query it, but it gets the information in the uint16_t format.

#include <MD_YX5300.h>
//  https://github.com/MajicDesigns/MD_YX5300/


// Connections for serial interface to the YX5300 module
const uint8_t ARDUINO_RX = 5;    // connect to TX of MP3 Player module
const uint8_t ARDUINO_TX = 6;    // connect to RX of MP3 Player module

// Constants for Buttons
#define PIN_KEY A3
#define BUTTON_TOLERANCE 25
#define LONG_KEY_PRESS_TIME_MS 2000L

#define DEBUG 1 // enable/disable debug output

#ifdef DEBUG
#define PRINT(s,v)    { Serial.print(F(s)); Serial.print(v); }
#define PRINTX(s,v)   { Serial.print(F(s)); Serial.print(v, HEX); }
#define PRINTS(s)     { Serial.print(F(s)); }
#else
#define PRINT(s,v)
#define PRINTX(s,v)
#define PRINTS(s)
#endif

bool showFolderFiles = true;
long int lastCheck;

// Define global variables
MD_YX5300 mp3(ARDUINO_RX, ARDUINO_TX);

/********************************************************************************/
/****************************** VARIABLES (May change) **************************/
/********************************************************************************/

/****** Folder Management *****/
int numberOfFolders = 9;
uint8_t currentFolder = 1; // start with folder 1
unsigned int currentFile = 1; // FIXME change Type?
unsigned int numberOfFiles[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0}; // for 9 Folders
int numberoffilesinfolder;
/******************************/

/****** Button Management *****/
int key = -1;
unsigned long keyPressTimeMs = 0;

unsigned long nowMs;

int keyPressRepeats = 0; //???

long buttonTimer = 0;
long longPressTime = 250;

boolean buttonActive = false;
boolean longPressActive = false;
// from https://www.instructables.com/id/Arduino-Dual-Function-Button-Long-PressShort-Press/

enum {
  MODE_NORMAL, MODE_SET_TIMER
} mode = MODE_NORMAL;
/******************************/

/****** Status Information ****/
enum playMode_t { M_SEQ, M_SHUFFLE, M_LOOP, M_EJECTED };
enum playStatus_t { S_PAUSED, S_PLAYING, S_STOPPED };
enum encMode_t { E_VOLUME, E_TRACK };

struct    // contains all the running status information
{
  bool needUpdate;        // flag for display update required
  bool initialising;      // loading data from the device
  bool waiting;           // waiting initialisation response

  playMode_t playMode;    // playing mode 
  playStatus_t playStatus;// playing status
  encMode_t encMode;      // encoder mode
  uint16_t numTracks;     // number of tracks in this folder
  uint16_t curTrack;       // current track being played
  uint16_t volume;        // the current audio volume
} S;

/********** Initialize MP3 Data ************/
bool initData(bool reset = false)
// initialise data from the MP3 device. 
// This needs to be measured out as the data requests will generate 
// unsolicited messages to be handled in the callback and message 
// sequence is must be maintained with the synchronous message processing
// stream.
// Returns true if the initilisation must keep going, fals when completed.
{
  static uint8_t state = 0;
  bool b = true;

  if (reset)    // just rest the sequencing
  {
    state = 0;
  }
  else
  {
    switch (state)
    {
    case 0:   // set a default state in the devioce and then ask for first data
      mp3.playSpecific(currentFolder, currentFile);
      mp3.playPause();
      S.playMode = M_SEQ;
      S.playStatus = S_PAUSED;

      if (S.volume == 0)
        S.volume = (mp3.volumeMax() / 3) * 2;   // 2/3 of volume to start with
      mp3.volume(S.volume);

      // load number of files in the folder - needs wait for response
      mp3.queryFolderFiles(currentFolder);
      S.waiting = true;
      state++;
      break;

    case 1: // now load the track cplaying - needs wait for response
      mp3.queryFile();
      S.waiting = true;
      state++;
      break;

    default:
      // end of sequence handler
      state = 0;
      b = false;
      break;
    }
  }

  return(b);
}

/************ Callback Response *********/
void cbResponse(const MD_YX5300::cbData *status)
// Callback function used to process device unsolicited messages
// or responses to datya requests
{
  PRINTS("\n");
  switch (status->code)
  {
  case MD_YX5300::STS_FILE_END:   // track has ended
    PRINTS("STS_FILE_END");
    selectNextSong();
    break;

  case MD_YX5300::STS_TF_INSERT:  // card has been inserted
    PRINTS("STS_TF_INSERT"); 
    S.initialising = initData(true);
    break;

  case MD_YX5300::STS_TF_REMOVE:  // card has been removed
    PRINTS("STS_TF_REMOVE"); 
    S.playMode = M_EJECTED;
    S.playStatus = S_STOPPED;
    S.needUpdate = true;
    break;

  case MD_YX5300::STS_PLAYING:   // current track index 
    PRINTS("STS_PLAYING");    
    S.curTrack = status->data;
    S.needUpdate = true;
    break;

  case MD_YX5300::STS_FLDR_FILES: // number of files in the folder
    PRINTS("STS_FLDR_FILES"); 
    S.numTracks = status->data;
    S.needUpdate = true;
     numberOfFiles[currentFolder-1] = S.numTracks; // #FIXME - Data type / Conversion Problem ??
     Serial.println("numberOfFiles in Folder" + String(currentFolder) + " is " + String(numberOfFiles[currentFolder-1]));
    break;

  // unhandled cases
  case MD_YX5300::STS_VOLUME:     PRINTS("STS_VOLUME");     break;
  case MD_YX5300::STS_TOT_FILES:  PRINTS("STS_TOT_FILES");  break;
  case MD_YX5300::STS_ERR_FILE:   PRINTS("STS_ERR_FILE");   break;
  case MD_YX5300::STS_ACK_OK:     PRINTS("STS_ACK_OK");     break;
  case MD_YX5300::STS_INIT:       PRINTS("STS_INIT");       break;
  case MD_YX5300::STS_STATUS:     PRINTS("STS_STATUS");     break;
  case MD_YX5300::STS_EQUALIZER:  PRINTS("STS_EQUALIZER");  break;
  case MD_YX5300::STS_TOT_FLDR:   PRINTS("STS_TOT_FLDR");   break;
  default: PRINTX("STS_??? 0x", status->code); break;
  }

  PRINTX(", 0x", status->data);
  S.waiting = false;
}

void processPause(bool b)
// switches pause on if b == true; of if b == false
{
 
  if (b == true) {mp3.playPause();} else mp3.playStart();
}

void handleKeyPress() {
// this function listens for keypresses and sends commands
// see attachment for complete code (above character limit for post)

}

void setup() {

#if DEBUG
  Serial.begin(9600);
#endif
  PRINTS("\n[MD_YX5300 Test]");

  // Initialize global libraries
  mp3.begin();
  mp3.setSynchronous(true);
  mp3.setCallback(cbResponse);
  S.initialising = initData(true);  // initialize data from MP3 device
  // Returns true if the initilisation must keep going, fails when completed.

  /*** buttons ***/
  pinMode(PIN_KEY, INPUT_PULLUP);
    
  Serial.print("Buttons ready");
}

void loop() {
  long int nowMs = millis();
  
  
  mp3.check();        // run the mp3 receiver   
  if (S.initialising && !S.waiting) S.initialising = initData();
  // initialize if waiting
  else {
    // check buttons, act on key press
    handleKeyPress(); 
  }
}

The problem: How can I fill this array with the number of files in each folder? for example, it should look like this:

numberOfFiles[] = { 3, 5, 2, 7, 3, 2, 1, 6, 7}

This is where the problem starts, the value is stores in S.numTracks , which is defined as

uint16_t numTracks;     // number of tracks in this folder

When the answer is received and interpreted, I try to store the value in the array but fail:

case MD_YX5300::STS_FLDR_FILES: // number of files in the folder
    PRINTS("STS_FLDR_FILES"); 
    S.numTracks = status->data;
    S.needUpdate = true;
     numberOfFiles[currentFolder-1] = S.numTracks; // *** this does not work***
    break;

How can I get the number of files in each folder? The examples for the MD_YX5300 library only store all the files in one folder, but in my project I need 9 folders to keep the different audiobooks apart.

Thanks!

-Complete Code attached, also on Github:

2019-09-kidsmp3player_MD_YX5300.ino (8.96 KB)

What isn't working? How do you know? I don't see that you print the information anywhere.

wildbill:
What isn't working? How do you know? I don't see that you print the information anywhere.

In this version I posted only the minimum, due to character constraints in the forum.

I modufied the post above to include the debugging .Serial.println-Statement. It is this part:

 S.needUpdate = true;
     numberOfFiles[currentFolder-1] = S.numTracks; // #FIXME - Data type / Conversion Problem ??
     Serial.println("numberOfFiles in Folder" + String(currentFolder) + " is " + String(numberOfFiles[currentFolder-1]));

instead of printing a number for numberOfFiles[currentFolder-1] (=the number of files in the folder), there is just a blank

Strings (capital S) are bad news on the Arduino due to memory constraints.

Try printing your data with a series of serial.print and serial.println statements instead.

I tried this already with individual print statements, it also does not work. This is not about printing the data.

In this part, data is received and interpreted from the mp3 player:

case MD_YX5300::STS_FLDR_FILES: // number of files in the folder
    PRINTS("STS_FLDR_FILES"); 
    S.numTracks = status->data;
    S.needUpdate = true;
     numberOfFiles[currentFolder-1] = S.numTracks; 
    break;

So now I should have a new value, the number of files from the current folder, that are stored in the array position numberOfFiles[currentFolder-1]

I need to use this value for the following statement:

// plays the next file 

if (key = 11) {

   if ((currentFile + 1) < numberOfFiles[currentFolder-1]) {
   // if a next file exists, play this one
   mp3.playSpecific(currentFolder, currentFile +1);
   } else {
   // else start playing file 1
   mp3.playSpecific(currentFolder, 1);
   }

}

In this case, it only plays file number one - the content of the array numberOfFiles[currentFolder-1]) is still 0, or interpreted as such

nmarkus:
This is not about printing the data.

Actually, I would say that it is. If your code can't print a simple unsigned int, something is very wrong. Does it work if you print the variables in setup immediately after the serial.begin?

Are you very short of free memory?

Good Question. I experimented some more and it seems that the synchronous mode has a bigger strain on the memory, as there is some progress with fewer Serial.print statements. I'll experiment some more..

thanks!