How can I read a HEX command that has been sent to Arduino?

I am trying to make an MP3 player using the Catalex YX5300 chip. I am wanting to be able to interrupt the current song playing in folder 01, play a new song in folder 02 and when it finishes return to folder 01 and play the song that was playing.

I know I need to be able to read/store an ansbuf line, and I need to look for the command 0x4c on ansbuf[3], but I need to store what is returned on ansbuf[6] in HEX format (0xFF where F is the track being played.)

I have found/used code that prints what track is being played (which is the value of ansbuf[6] but not in HEX), but it prints it as a 1, 2, 3, etc.

How can I read that value as HEX?

Below is my code and here is a link to a previous forum post about the problem.

#include <SoftwareSerial.h>
#include <SD.h>

#define ARDUINO_RX 5//should connect to TX of the Serial MP3 Player module
#define ARDUINO_TX 6//connect to RX of the module
SoftwareSerial mp3(ARDUINO_RX, ARDUINO_TX);
static int8_t Send_buf[8] = {0}; // Buffer for Send commands.  // BETTER LOCALLY
static uint8_t ansbuf[10] = {0}; // Buffer for the answers.    // BETTER LOCALLY
# define Start_Byte 0x7E
# define Version_Byte 0xFF
# define Command_Length 0x06
# define End_Byte 0xEF
# define Acknowledge 0x00 //Returns info with command 0x41 [0x01: info, 0x00: no info]

# define ACTIVATED HIGH

int buttonHorn = 2;
int buttonPause = 3;
int buttonPrevious = 7;
int buttonNext = 8;
boolean isPlaying = false;


/************Command byte**************************/
#define CMD_NEXT_SONG 0X01
#define CMD_PREV_SONG 0X02
#define CMD_PLAY_W_INDEX 0X03
#define CMD_VOLUME_UP 0X04
#define CMD_VOLUME_DOWN 0X05
#define CMD_SET_VOLUME 0X06
#define CMD_SINGLE_CYCLE_PLAY 0X08
#define CMD_SEL_DEV 0X09
#define DEV_TF 0X02
#define CMD_SLEEP_MODE 0X0A
#define CMD_WAKE_UP 0X0B
#define CMD_RESET 0X0C
#define CMD_PLAY 0X0D
#define CMD_PAUSE 0X0E
#define CMD_PLAY_FOLDER_FILE 0X0F
#define CMD_STOP_PLAY 0X16
#define CMD_FOLDER_CYCLE 0X17
#define CMD_SHUFFLE_PLAY 0X18
#define CMD_SET_SINGLE_CYCLE 0X19
#define SINGLE_CYCLE_ON 0X00
#define SINGLE_CYCLE_OFF 0X01
#define CMD_SET_DAC 0X1A
#define DAC_ON  0X00
#define DAC_OFF 0X01
#define CMD_PLAY_W_VOL 0X22
#define CMD_FOUND_NUM_FILES 0x48
#define CMD_CURRENT_TRACK 0X4C
#define CMD_FOUND_FOLDER 0X4F

int potPin = A0;
int potVal;
float last;
unsigned int track;
int folder; 

void setup() {
  Serial.begin(9600);
  mp3.begin (9600);

  pinMode(buttonPause, INPUT);

  pinMode(buttonNext, INPUT);

  pinMode(buttonPrevious, INPUT);

  pinMode(buttonHorn, INPUT);

  delay(500);


  sendCommand(CMD_SEL_DEV, DEV_TF); //Selects SD card
  delay(200);
  sendCommand(DAC_ON, 0X00); // I turned DAC on, but I have no idea what it does
  delay(200);
  sendCommand(CMD_FOUND_NUM_FILES, 0X48); // Detects number of files on card
  delay(200);
  sendCommand(CMD_FOUND_FOLDER, 0X4F);
  delay(200);
  playFirst();

  isPlaying = true;

  last = millis();
}
static int8_t pre_vol = 0x0f;

void loop() {
  potVal = analogRead(potPin);
  int8_t volume;

  volume = map(potVal, 0, 1023, 0, 30); // Potentiometer controls volume
  if (volume != pre_vol)
  {
    sendCommand(CMD_SET_VOLUME, volume);
    pre_vol = volume;
  }
  delay(100);

  if (mp3.available()) //Returns commands, and determines what file is being played
  {
    if ( answer ( ) )
    {
    
      if ( ansbuf [ 3 ] == 0x4c ) // currently playing
      {
        Serial. print ( "currently playing file " ) ;
        Serial.println(ansbuf[6]); // had to add -1 to get it to display a 1 for file 1 in folder 01. Any idea why?
        
        track = (ansbuf[6]); //I tried storing the value of ansbuf[6] thinking i could use it to return to the file I was playing, but it changes when I play the horn file.
        Serial.println(track);
      }
    }
  }
  if ( ( millis ( ) - last ) > 5000 ) // We ask every 5 sec
  {
    last = millis();
    sendCommand ( 0x4c , 0X0000 ) ; // Ask for the number of the file being played
    delay(200);
    sendCommand ( 0X17, 0X01);
  }


  if (digitalRead(buttonPause) == ACTIVATED)
  {
    Serial.println("Button is pressed");
    if (isPlaying)
    {
      pause();
      isPlaying = false;
    }
    else
    {
      isPlaying = true;
      play();
    }
  }


  if (digitalRead(buttonNext) == ACTIVATED)
  {
    Serial.print("Next");
    if (isPlaying)
    {
      playNext();
    }
  }

  if (digitalRead(buttonPrevious) == ACTIVATED)
  {
    Serial.print("Prev");
    if (isPlaying)
    {
      playPrevious();
    }
  }
  if (digitalRead(buttonHorn) == ACTIVATED)
  {
    Serial.print("horn");
    horn();
  }


}

void playFirst()
{

  sendCommand(CMD_FOLDER_CYCLE, 0X0100);
  delay(200);
}

void pause()
{
  sendCommand(CMD_PAUSE, 0X0E);
  delay(200);
}

void play()
{ sendCommand(CMD_PLAY, 0X0D);
  delay(200);
}

void playNext()
{
  sendCommand(CMD_NEXT_SONG, 0X01);
  delay(200);

}

void playPrevious()
{
  sendCommand(CMD_PREV_SONG, 0X02);
  delay(200);
}

void setVolume(int volume)
{
  sendCommand(CMD_SET_VOLUME, volume); // Set the volume (0x00~0x30)
  delay(200);
}
void horn() //This is my attempt at the horn interrupt. It will pause and play the horn sound, but wont return to the previous track from folder 01
{
  sendCommand(CMD_PAUSE, 0X0E);
  delay(200);

  sendCommand(CMD_PLAY_FOLDER_FILE, 0X0201);
  delay(100);

  sendCommand(0x01, track);

}
void sendCommand(int8_t command, int16_t dat)
{
  delay(20);
  Send_buf[0] = 0x7e;   //
  Send_buf[1] = 0xff;   //
  Send_buf[2] = 0x06;   // Len
  Send_buf[3] = command;//
  Send_buf[4] = 0x01;   // 0x00 NO, 0x01 feedback
  Send_buf[5] = (int8_t)(dat >> 8);  //datah
  Send_buf[6] = (int8_t)(dat);       //datal
  Send_buf[7] = 0xef;   //
  for (uint8_t i = 0; i < 8; i++)
  {
    mp3.write(Send_buf[i]) ;
  }
}
void byte2hex(uint8_t b)
{
  Serial.print("0x");
  if (b < 16) Serial.print("0");
  Serial.print(b, HEX);
  Serial.print(" ");
}

// Function to retrieve answers
boolean answer(void)
{
  uint8_t i = 0;

  // Get only 10 bytes
  while (mp3.available() && (i < 10))
  {
    uint8_t b = mp3.read();
    ansbuf[i] = b;
    i++;
    byte2hex(b);
  }

  Serial.println();

  // If the correct response format
  if ((ansbuf[0] == 0x7E) && (ansbuf[9] == 0xEF))
  {
    return true;
  }

  return false;
}

I have found/used code that prints what track is being played (which is the value of ansbuf[6] but not in HEX), but it prints it as a 1, 2, 3, etc.

You can print the value in HEX, if you like, or DECimal, or OCTal, or base 23. That does NOT change the fact that the value is stored in memory in binary.

Ok, then how can I use it as a command for the Catalex board? It requires communication in HEX format.

1, 2, 3 are valid hex digits. Please give an example of the "HEX" format you need to use.

It requires communication in HEX format.

The board can NOT tell if the VALUE that you send is 2, 0x02, 0s, or 0b10. So, your idea that the VALUE must be in HEX is nonsense.

PaulS:
The board can NOT tell if the VALUE that you send is 2, 0x02, 0s, or 0b10. So, your idea that the VALUE must be in HEX is nonsense.

Instead of dismissing it as nonsense, how about telling me how it communicates if not via HEX. Examples of the commands are 0x4c, 0x4F, 0X0B, etc. If that is not a HEX format, then what is it?

aarg:
1, 2, 3 are valid hex digits. Please give an example of the "HEX" format you need to use.

I need the command to look like this: 0X01FF where the 01 represents the file folder, and the FF represents the track that was playing before I hit the horn button.

I can get the Catalex board to play through a folder, pause, skip, and play the horn. I can even get it to go back to the first file in folder 01 and start over after the horn plays, but I want it to go back to the file it was playing before I hit the horn.

how about telling me how it communicates if not via HEX

Communication is in BINARY.

HEX is a human readable representation of BINARY numbers.

Delta_G:
They're numbers. Just numbers. And no matter what base you write them in they will still be the same numbers.

If you write the following three lines:

Serial.write(10);

Serial.write(0x0A);
Serial.write(0b1010);




They will all three put out EXACTLY the same data on the serial line. Everything that the computer does it does in binary. Hex or decimal or octal are just for the humans reading the code. The computer only knows binary. Quite often a datasheet will list the commands in hex notation because it is easier to read. But those are just numbers. And writing them differently does not change them at all.

If it communicates in binary, but the commands are written in HEX then how do I tell it what file to return to and then loop through the rest? I have stored the number of the track in an integer, and I can use the integer to tell it to go play that file, but it just plays that file and doesn't loop through the rest of the files in the folder.

If you have 10 fingers, you learn to think in decimal (base 10).
If you had 16 fingers, you'd learn to think in hexadecimal (base 16).
The Arduino has two fingers. It thinks in binary.

It, and you (well, I can, I'm not so sure about you anymore), can convert from binary to decimal or to hexadecimal, as needed, and can convert from hexadecimal to binary or decimal to binary, IF it knows what conversion to perform.

In communicating with the Catalex, it sends a value. It should not matter to you how it gets that VALUE to the device. You specify the VALUE using whatever representation is convenient FOR YOU - 2, 0b10, 0x02, etc. The Arduino will store the bits 00000010 regardless of which representation you use to specify the value. When it sends the VALUE to the Catalex, it will send 00000010 regardless of whether you told it to send 2, 0x02, 0b10, or atoi("2").

I'm getting the impression that you are asking it which track it is playing (or only paying attention to the answer it automatically sends) AFTER you start playing the horn track. Of course, when you ask then, it will tell you that it is playing the horn track.

You need to ask it which folder and track it is playing BEFORE you start it playing something else. Record the track and folder values. Then, change the track/folder to play the horn sound. When that it is done, you can resume playing the track and folder that was playing.

PaulS:
It, and you (well, I can, I'm not so sure about you anymore)

Classy.

Looking at the comment on this line of your code

        track = (ansbuf[6]); //I tried storing the value of ansbuf[6] thinking i could use it to return to the file I was playing, but it changes when I play the horn file.

I suspect that if you change to another track that line will change track.

If so, you will need a little more to remember that. One idea is to use an array to store it and write a new track into the array

void loop()
{
  static byte history[10];
  static byte historyIndex;

  if (mp3.available()) //Returns commands, and determines what file is being played
  {
    if ( answer ( ) )
    {
   
      if ( ansbuf [ 3 ] == 0x4c ) // currently playing
      {
        Serial. print ( "currently playing file " ) ;
        Serial.println(ansbuf[6]); // had to add -1 to get it to display a 1 for file 1 in folder 01. Any idea why?
       
        history[historyIndex] = (ansbuf[6]); //I tried storing the value of ansbuf[6] thinking i could use it to return to the file I was playing, but it changes when I play the horn file.
        Serial.println(tracks[historyIndex]);
        historyIndex++;
      }
    }
  }

  ...
  ...

}

Note that you need to make sure that you don't go over the size of the history array so you need to limite historyIndex between 0 and 9 (both included).

I have no idea how you detect if a track is finished. Once you have detected that, decrement historyIndex, get the last song that was played from the history array and start playing that. I suspect that this change will result in a new entry in the history array and hence you will end up in a endless loop playing that one forever. You will have to find a clever way not to put this track back in the history.

It might be something in the line of

void loop()
{
  static byte history[10];
  static byte historyIndex;

  if (mp3.available()) //Returns commands, and determines what file is being played
  {
    if ( answer ( ) )
    {
   
      if ( ansbuf [ 3 ] == 0x4c ) // currently playing
      {
        Serial. print ( "currently playing file " ) ;
        Serial.println(ansbuf[6]); // had to add -1 to get it to display a 1 for file 1 in folder 01. Any idea why?

        if(history[historyIndex] != ansbuf[6])
        {
        history[historyIndex] = (ansbuf[6]); //I tried storing the value of ansbuf[6] thinking i could use it to return to the file I was playing, but it changes when I play the horn file.
        }
        Serial.println(tracks[historyIndex]);
        historyIndex++;
      }
    }
  }

  ...
  ...

}

This is just to give you the idea; I'm sure that the presented code is buggy. I'll leave the correct implementation to you.

PS
No experience with the Catalex YX5300

sterretje:
Looking at the comment on this line of your code

        track = (ansbuf[6]); //I tried storing the value of ansbuf[6] thinking i could use it to return to the file I was playing, but it changes when I play the horn file.

I suspect that if you change to another track that line will change track.

If so, you will need a little more to remember that. One idea is to use an array to store it and write a new track into the array

void loop()

{
  static byte history[10];
  static byte historyIndex;

if (mp3.available()) //Returns commands, and determines what file is being played
  {
    if ( answer ( ) )
    {
 
      if ( ansbuf [ 3 ] == 0x4c ) // currently playing
      {
        Serial. print ( "currently playing file " ) ;
        Serial.println(ansbuf[6]); // had to add -1 to get it to display a 1 for file 1 in folder 01. Any idea why?
     
        history[historyIndex] = (ansbuf[6]); //I tried storing the value of ansbuf[6] thinking i could use it to return to the file I was playing, but it changes when I play the horn file.
        Serial.println(tracks[historyIndex]);
        historyIndex++;
      }
    }
  }

...
  ...

}



Note that you need to make sure that you don't go over the size of the history array so you need to limite historyIndex between 0 and 9 (both included).

I have no idea how you detect if a track is finished. Once you have detected that, decrement historyIndex, get the last song that was played from the history array and start playing that. I suspect that this change will result in a new entry in the history array and hence you will end up in a endless loop playing that one forever. You will have to find a clever way not to put this track back in the history.

It might be something in the line of


void loop()
{
  static byte history[10];
  static byte historyIndex;

if (mp3.available()) //Returns commands, and determines what file is being played
  {
    if ( answer ( ) )
    {
 
      if ( ansbuf [ 3 ] == 0x4c ) // currently playing
      {
        Serial. print ( "currently playing file " ) ;
        Serial.println(ansbuf[6]); // had to add -1 to get it to display a 1 for file 1 in folder 01. Any idea why?

if(history[historyIndex] != ansbuf[6])
        {
        history[historyIndex] = (ansbuf[6]); //I tried storing the value of ansbuf[6] thinking i could use it to return to the file I was playing, but it changes when I play the horn file.
        }
        Serial.println(tracks[historyIndex]);
        historyIndex++;
      }
    }
  }

...
  ...

}




This is just to give you the idea; I'm sure that the presented code is buggy. I'll leave the correct implementation to you.

PS
No experience with the Catalex YX5300

Thank you for your help. I actually got it working late last night. It was a matter of changing the delays between the commands to cycle a folder and play a song in that folder. Once I did that it worked. Thanks