VS1005 MP3 Player with USB Host

Installing and using VSIDE tools for VLSI Solution's devices that contain a VSDSP signal processor.
Srikanth
User
Posts: 10
Joined: Thu 2016-08-18 9:03

Re: VS1005 MP3 Player with USB Host

Post by Srikanth » Tue 2016-09-06 12:45

Hello VLSI Team,

Thank you for the kind support. I am here again with few more doubts.
The alternative way provided by Henrik contains more of assembly code which I am not that good at. I will stick to 'C' based solution.

The below is the MP3 player code that I have written for our application.

Code: Select all

#include <vo_stdio.h>
#include <stdlib.h>
#include <codec.h>
#include <sysmemory.h>
#include <vsos.h>
#include <apploader.h>
#include <libaudiodec.h>
#include <aucommon.h>
#include <vsostasks.h>
#include <clockspeed.h>
#include "MP3_Drv.h"
//#include "hw_config.h"
//#include "GPIO_Drv.h"


#define SET 1
#define RESET 0



volatile PlayerFlagStructure PlayerFlags; 

FILE *PlayFile;
void *decoderLibrary = NULL;
AUDIO_DECODER *audioDecoder = NULL;
char *errorString = "";
int eCode = 0;
volatile int fileNum = 0;
int running = 1;

auto ioresult Load(char *filespec);
auto ioresult Play(void);
auto ioresult Pause(void);
auto ioresult NextTrack(void);
auto ioresult PreviousTrack(void);
auto ioresult FastForward(void);
auto ioresult Rewind(void);
auto ioresult VolumePlus(void);
auto ioresult VolumeMinus(void);
auto ioresult Stop(void);
auto ioresult Source(void);

void PlayerThread(void) {
  eCode = DecodeAudio(decoderLibrary, audioDecoder, &errorString);
}

// this is the MP3 start file from where the MP3 processing is done. 
// this function takes MP3 file path i.e. directory as argument and process according to it
// the below code is extracted from the various MP3 player examples available in the forum. 
auto ioresult Load(char *filespec)
{
	volatile u_int16 FileNumber=0;
	static char fnumMode[MAX_FILENAME_LENGTH];
	PlayFile = NULL;
	decoderLibrary = LoadLibrary("audiodec");
	if (!decoderLibrary) {
		return S_ERROR;
	}
	PlayerFlags.PlayPause = RESET;
	PlayerFlags.PlayPause = RESET;			// 1 = Play, 0 = Pause
	PlayerFlags.NextTrack = RESET;
	PlayerFlags.PreviousTrack = RESET;
	PlayerFlags.FastForward = RESET;
	PlayerFlags.Rewind = RESET;
	PlayerFlags.VolumePlus = RESET;
	PlayerFlags.VolumeMinus = RESET;
	PlayerFlags.Stop = RESET;
	running=1;
	FileNumber=0;
	while(running) 
	{
		if(PlayerFlags.Stop!=RESET)
		{
			break;
		}
		printf("Open file %d...\n",FileNumber);
		sprintf(fnumMode,"rb#%d",FileNumber);
		PlayFile = fopen(filespec,fnumMode); // e.g. fopen("N:MUSIC\*","rb#123");
		if (PlayFile) 
		{
			printf("Playing '%s' ",PlayFile->Identify(PlayFile,NULL,0)); //this Identify is good to be right after the fopen
			printf("from device %s...\n",PlayFile->dev->Identify(PlayFile->dev,NULL,0));
	
			RunLibraryFunction("METADATA",ENTRY_2,(int)PlayFile);
	
			//PlayFile(PlayFile);
			audioDecoder = CreateAudioDecoder(decoderLibrary, PlayFile, stdaudioout, NULL, auDecFGuess);
			if (!audioDecoder) 
			{
				printf("Couldn't create audio decoder\n");
				return S_ERROR;
			}
			StartTask(TASK_DECODER, PlayerThread);
			while (pSysTasks[TASK_DECODER].task.tc_State && pSysTasks[TASK_DECODER].task.tc_State != TS_REMOVED) 
			{
					DelayMicroSec(100000);
				if (PlayerFlags.Stop == SET) {
					audioDecoder->cs.cancel = 1;
					running = RESET;
					PlayerFlags.Stop=RESET;
				}
				if (PlayerFlags.NextTrack == SET) { // > Next
					audioDecoder->cs.cancel = 1;
					PlayerFlags.NextTrack = RESET;
				}
				if (PlayerFlags.PreviousTrack == SET) { // < Previous
					audioDecoder->cs.cancel = 1;
					FileNumber -= 2;
					PlayerFlags.PreviousTrack = RESET;
				}
				if(PlayerFlags.VolumePlus == SET)
				{
					s_int16 t = ioctl(stdaudioout, IOCTL_AUDIO_GET_VOLUME, NULL)-256;
	    			if (t >= -256) 
			    	{
			    		if (t > 0) 
						{
							t--;
						}
						#if 0
						if (t < 100) 
						{
							t++;
						}
						#endif
				    }
					 ioctl(stdaudioout, IOCTL_AUDIO_SET_VOLUME, (void *)(t+256));
				    printf("Vol=%d\n",t);
					PlayerFlags.VolumePlus = RESET;
				}
				if(PlayerFlags.VolumeMinus == SET)
				{
					s_int16 t = ioctl(stdaudioout, IOCTL_AUDIO_GET_VOLUME, NULL)-256;
	    			if (t >= -256) 
			    	{
			    		#if 0
			    		if (t > 0) 
						{
							t--;
						}
						#endif
						if (t < 100) 
						{
							t++;
						}
				    }
					ioctl(stdaudioout, IOCTL_AUDIO_SET_VOLUME, (void *)(t+256));
				    printf("Vol=%d\n",t);
					PlayerFlags.VolumeMinus = RESET;
				}
				if(PlayerFlags.FastForward == SET)
				{
					PlayerFlags.FastForward = RESET;
				}
				if(PlayerFlags.Rewind == SET)
				{
					PlayerFlags.Rewind = RESET;
				}
					
			}
			DeleteAudioDecoder(decoderLibrary, audioDecoder);
			fclose(PlayFile);
			FileNumber++;
		}
		else {
			printf("File %d not found, finished playing.\n",fileNum+1);
			FileNumber=0; //Restart from first file
			break; //end of files, end playing
		}
	}

	DropLibrary(decoderLibrary);
	return S_OK; //End of files, ok exit
}
	
auto ioresult Play(void){
	PlayerFlags.PlayPause = 1;
	return S_OK;
}
auto ioresult Pause(void){
	PlayerFlags.PlayPause = 0;
	return S_OK;	
}
auto ioresult NextTrack(void){
	PlayerFlags.NextTrack = 1;
		return S_OK;
}
auto ioresult PreviousTrack(void){
	PlayerFlags.PreviousTrack = 1;
	return S_OK;
}
auto ioresult FastForward(void){
	PlayerFlags.FastForward = 1;
	return S_OK;
}
auto ioresult Rewind(void){
	PlayerFlags.Rewind = 1;
	return S_OK;
}
auto ioresult VolumePlus(void){
	PlayerFlags.VolumePlus = 1;
	return S_OK;
}
auto ioresult VolumeMinus(void){
	PlayerFlags.VolumeMinus = 1;
	return S_OK;
}
auto ioresult Stop(void){
	PlayerFlags.Stop = 1;
	return S_OK;
}
auto ioresult Source(void){
// not yet implemented
	return S_OK;
}

These are the doubts in the above code i.e. I don't know what they do but I used it because many of the MP3 examples used in the same way.

1) PlayFile = fopen(filespec,fnumMode); // e.g. fopen("N:MUSIC\*","rb#123");
in example code it says like "rb#123" I assume it as file number but I don't know how it is numbered or is it the right way of picking file or do we have to name the complete file name. Will the above line automatically searches for the file in the path specified and fetches the data from it. if it searches then will it be index based or filename based.If indexbased, how does the indexing of files done in the filesystem. i.e. automatically by the filesystem or we have to name the files with numbers as filename.

2) RunLibraryFunction("METADATA",ENTRY_2,(int)PlayFile);
may I know what "METADATA" does here and what does "ENTRY_2" does and what does "(int)PlayFile" returns, as PlayFile is of type FILE

3) StartTask(TASK_DECODER, PlayerThread);
is the "StartTask" function predefined and is that TASK_DECODER is predefined for audio decode or just a #define mentioned in one of the header file.

4) while (pSysTasks[TASK_DECODER].task.tc_State && pSysTasks[TASK_DECODER].task.tc_State != TS_REMOVED)
I don't know what the above line do. All I did was copy paste the example line. I assume it as the current state of the thread

5) How does the FILE fetches the next MP3 frame to play continuously. as I am not calling anywhere to read the file again.

6) eCode = DecodeAudio(decoderLibrary, audioDecoder, &errorString);
what does the above line do. I am still confused how would this VS1005 manage to pick the next mp3 frame and play continuously.

I am afraid VS1005 has less documented details of API used by VSOS. If we have one, please do share the API apart from the one searching from header files. Header files only give the declaration of a particular variable or function but it does not explain the properties of what actually the function do.

I have a lot of doubts about USB interfacing as Host .. but will add it once I am clear with the MP3 part.

Its my request to VLSI team to excuse me on my typical doubts which may be silly to experts.

User avatar
Panu
VLSI Staff
Posts: 2561
Joined: Tue 2010-06-22 13:43

Re: VS1005 MP3 Player with USB Host

Post by Panu » Tue 2016-09-06 14:00

Hi, Srikanth!

I am currentry updating our old MP3 player Model-View-Controller approach, of which there is an example at viewtopic.php?f=13&t=1318 labeled "Controlling MP3 playback: a Model-View-Controller approach". This example is quite old, from 2014 and as I said, I'm rewriting it so don't copy it now. But the basic idea in that approach is that you shouldn't need to write VSDSP or VSOS software to do the actual music playing. Instead, you load a player library ("MP3MODEL", written by VLSI) which runs in the background. And from the foreground, or from the UART command line, you send messages to it, asking it to start and stop playing, go to next file etc. So once I get that job done, I think it will change what is the simplest way to do stuff. Perhaps.

1) PlayFile = fopen(filespec,fnumMode); // e.g. fopen("N:MUSIC\*","rb#123");
in example code it says like "rb#123" I assume it as file number but I don't know how it is numbered or is it the right way of picking file or do we have to name the complete file name.
Indeed, the "rb#123" means the file number: specifically it means that the first 123 entries that match the filespec "N:MUSIC/*" should be skipped.

The file numbering is the order where the index entries are stored in the FAT, e.g. the files are not in any meaningful order (except perhaps they may be in the order in which they were copied to the card, but this is not guaranteed). To find out the number, you must do a directory listing with the DIR program. It will report the index numbers of the file as in:
S:>dir d:
- 1. 01_MP3~1.MP3 4394324 2005-06-01 13:46:34 01_mp3_160kbps_Dian_-_Airscrewed_.mp3
- 2. 02_ADP~1.WAV 81212 2005-06-01 13:23:58 02_ADPCM000.WAV
- 3. 04_WAV~1.WAV 10470 2005-06-01 13:52:26 04_wav_maltese_lock_door.wav
- 4. 05_PLU~1.MV3 492643 2005-06-01 14:01:14 05_plusv_dream.mv3
- 5. ADPCM000.WAV 12604 2005-09-15 10:12:06 ADPCM000.WAV
- 7. DARUDE~1.OGG 3156163 2008-11-11 18:36:52 Darude_Sandstorm.ogg
- 8. OUT000.RAW 9999872 2000-01-01 00:00:00 OUT000.RAW
- 6. UTOPIA~1.MP3 1471792 2004-06-15 15:15:48 Utopia-free-sample.mp3
This information can be also obtained programmatically: if you call the MakePlayList() entry function of DIR, you will get an array of entry numbers of all files in the current directory in alphabetical order.

The #rb123 method is useful when you don't know the file name. You can also give the real file name if you know it, so instead of fopen("N:MUSIC/*","rb#123") you can use fopen("N:MUSIC/01 - Watermark.mp3","rb");

2) RunLibraryFunction("METADATA",ENTRY_2,(int)PlayFile);
may I know what "METADATA" does here and what does "ENTRY_2" does and what does "(int)PlayFile" returns, as PlayFile is of type FILE
It doesn't return anything. It runs the METADATA.DL3 program in the flash, which scans the file for any information regarding album, artist, title etc and reports that to the View component, e.g. by default prints that information to the serial port. ENTRY_2 means the entry function of that library that takes a file pointer as a parameter. That call should be done exactly as in the example, including the casting of file pointer to (int). If you don't need to get the Artist/Song/Title information, then you don't need to run METADATA.

May I ask if you might consider writing variable names starting with low case letters? I only ask this because this is VLSI internal coding style, and all of us who work at VLSI write variable names like that, and it would just help us a little bit to read and understand your code faster. But it's 100% up to you.

3) StartTask(TASK_DECODER, PlayerThread);
is the "StartTask" function predefined and is that TASK_DECODER is predefined for audio decode or just a #define mentioned in one of the header file.
Always, when you start to run a decoder in the background, you must use TASK_DECODER task, that's what it is meant for. That task has preassigned stack memory, which is needed to do audio decoding. You can also run the decoder in foreground and not start a task for it, but then you can't do stuff such as check the user interface etc while the decoder is running.

4) while (pSysTasks[TASK_DECODER].task.tc_State && pSysTasks[TASK_DECODER].task.tc_State != TS_REMOVED)
I don't know what the above line do. All I did was copy paste the example line. I assume it as the current state of the thread
It checks whether the decoder task is still running or has exited.

5) How does the FILE fetches the next MP3 frame to play continuously. as I am not calling anywhere to read the file again.
There's a while (running) and
printf("File %d not found, finished playing.\n",fileNum+1);
FileNumber=0; //Restart from first file
in your source code, I think that explains it.
I am not calling anywhere to read the file again.
I think you are, "PlayFile = fopen(filespec,fnumMode);" seems to be inside the while(running) loop.

6) eCode = DecodeAudio(decoderLibrary, audioDecoder, &errorString);
what does the above line do. I am still confused how would this VS1005 manage to pick the next mp3 frame and play continuously.
That line plays the entire file and then returns.


I hope this helps, and I hope that my upcoming new examples regarding the Model-View-Controller and MP3 player foreground tasks will clarify the situation in the future.

Panu
Info: Line In and Line Out, VS1000 User interface, Overlay howto, Latest VSIDE, MCU Howto, Youtube
Panu-Kristian Poiksalo, VLSI Solution Oy

Srikanth
User
Posts: 10
Joined: Thu 2016-08-18 9:03

Re: VS1005 MP3 Player with USB Host

Post by Srikanth » Thu 2016-09-22 8:38

Hello Panu,

I am sorry for the delayed reply. I was out station for couple of weeks and was unable to look at the current project. Its my humble request that can you provide a simple code snippet to interface USB as Host and get the list of files and directories. I am bit confused by the way the USB Host interfaced in various examples provided in forum and in the VSOS_330a_RootAndLibrariesSourceCode solutions.
Hi, Srikanth!

I am currentry updating our old MP3 player Model-View-Controller approach, of which there is an example at viewtopic.php?f=13&t=1318 labeled "Controlling MP3 playback: a Model-View-Controller approach". This example is quite old, from 2014 and as I said, I'm rewriting it so don't copy it now. But the basic idea in that approach is that you shouldn't need to write VSDSP or VSOS software to do the actual music playing. Instead, you load a player library ("MP3MODEL", written by VLSI) which runs in the background. And from the foreground, or from the UART command line, you send messages to it, asking it to start and stop playing, go to next file etc. So once I get that job done, I think it will change what is the simplest way to do stuff. Perhaps.
Dear Panu, are you updating the old MP3 Player solution. as you said you are rewriting it. May I know the changes that would be added to the older version.
Thanks and regards,

Srikanth

Srikanth
User
Posts: 10
Joined: Thu 2016-08-18 9:03

Re: VS1005 MP3 Player with USB Host

Post by Srikanth » Tue 2016-09-27 12:35

Hello VLSI Team,

I guess Panu is busy with his schedule. could anyone look at my query and do the needful. All I need is sample USB Host code snippet from which I can read files in USB Device and call the playfile function to read MP3 file from USB device. I already implemented MP3 player code to which the File has to be sent as argument to that function.

My doubt is .. Do I have to keep in a forever loop to check for any usb device connection.
if any usb device connected, how to read the filesystem and files from that USB device.

does VSOS handles USB device connection or we have to handle it in our code.

regards,
Srikanth

User avatar
Panu
VLSI Staff
Posts: 2561
Joined: Tue 2010-06-22 13:43

Re: VS1005 MP3 Player with USB Host

Post by Panu » Wed 2016-09-28 9:28

Hi, Srikanth!

I'm afraid I don't undestand your question 100%. When the USBHOST library is loaded, either with USBHOST U in CONFIG.TXT or for example with something like "void *lib = LoadLibraryP("USBHOST","U");" then the USB memory stick becomes drive U. Then you can use things like f=fopen("U:FILE.TXT","r"); to read a file or call RunProgram("PLAYFILE","U:MUSIC/A wonderful life.mp3"); to play a song. The source code of PLAYFILE and other players such as PlayDir, the Classic Player etc are all in the root and solutions source code distro, so you should have no problems to find examples.

I'm working on a better USB host driver that can handle attach, detach etc. For now, you must do it yourself, see for example the discussion at: viewtopic.php?t=1970&start=20#p10067 about the GET_LINES method.

-Panu
Info: Line In and Line Out, VS1000 User interface, Overlay howto, Latest VSIDE, MCU Howto, Youtube
Panu-Kristian Poiksalo, VLSI Solution Oy

Srikanth
User
Posts: 10
Joined: Thu 2016-08-18 9:03

Re: VS1005 MP3 Player with USB Host

Post by Srikanth » Wed 2016-09-28 12:55

Dear Panu,

Thank you for your response. Can I ask you few more questions which might be dumb questions as well.
I'm afraid I don't undestand your question 100%. When the USBHOST library is loaded, either with USBHOST U in CONFIG.TXT or for example with something like "void *lib = LoadLibraryP("USBHOST","U");" then the USB memory stick becomes drive U. Then you can use things like f=fopen("U:FILE.TXT","r"); to read a file or call RunProgram("PLAYFILE","U:MUSIC/A wonderful life.mp3"); to play a song. The source code of PLAYFILE and other players such as PlayDir, the Classic Player etc are all in the root and solutions source code distro, so you should have no problems to find examples.
where can I find the CONFIG.TXT file.
what is the purpose of CONFIG.TXT file.
Is there any particular rules to follow while writing CONFIG.TXT file.
I can't see any CONFIG.TXT file in VSIDE. Is that file reside inside VS1005 Flash.


When the USBHOST library is loaded, either with USBHOST U in CONFIG.TXT or for example with something like "void *lib = LoadLibraryP("USBHOST","U");"
Is there any API Documentation for VLSI in which I can find the functions like "LoadLibraryP()" are described with its purpose.
then the USB memory stick becomes drive U. Then you can use things like f=fopen("U:FILE.TXT","r"); to read a file or call RunProgram("PLAYFILE","U:MUSIC/A wonderful life.mp3"); to play a song
Does it mean that the library internally detects USB i.e. checking USB lines and sending SOF packets whenever any USB device is connected.



please excuse me for asking basic questions. This is my first project on VLSI product.

Srikanth
User
Posts: 10
Joined: Thu 2016-08-18 9:03

Re: VS1005 MP3 Player with USB Host

Post by Srikanth » Mon 2016-10-03 7:33

Dear VLSI Team or any forum members,

Please do the needful for the above queries. I am afraid that I am neglected or my queries are ignored for my silly doubts. I don't know the reason for neglecting my queries. may be the queries I posted are silly but I have the right to know the answers for those questions.

Regards,
Srikanth

User avatar
Panu
VLSI Staff
Posts: 2561
Joined: Tue 2010-06-22 13:43

Re: VS1005 MP3 Player with USB Host

Post by Panu » Mon 2016-10-03 8:28

Hi!

The problem is that there are unusually many support requests and debugging projects underway at the moment. Sorry for not being able to answer to your request as fast as I would like. I'll try to help you as soon as I can or arrange help for you today.

Have you taken a look at the videos at viewtopic.php?t=1273? and the Getting Started document at viewtopic.php?t=1915?

-Panu
Info: Line In and Line Out, VS1000 User interface, Overlay howto, Latest VSIDE, MCU Howto, Youtube
Panu-Kristian Poiksalo, VLSI Solution Oy

Hannu
Senior User
Posts: 40
Joined: Mon 2016-05-30 11:54

Re: VS1005 MP3 Player with USB Host

Post by Hannu » Mon 2016-10-03 9:27

Srikanth wrote:Dear Panu,

Thank you for your response. Can I ask you few more questions which might be dumb questions as well.
I'm afraid I don't undestand your question 100%. When the USBHOST library is loaded, either with USBHOST U in CONFIG.TXT or for example with something like "void *lib = LoadLibraryP("USBHOST","U");" then the USB memory stick becomes drive U. Then you can use things like f=fopen("U:FILE.TXT","r"); to read a file or call RunProgram("PLAYFILE","U:MUSIC/A wonderful life.mp3"); to play a song. The source code of PLAYFILE and other players such as PlayDir, the Classic Player etc are all in the root and solutions source code distro, so you should have no problems to find examples.
where can I find the CONFIG.TXT file.
what is the purpose of CONFIG.TXT file.
Is there any particular rules to follow while writing CONFIG.TXT file.
I can't see any CONFIG.TXT file in VSIDE. Is that file reside inside VS1005 Flash.
Hello Srikanth,

I'm assuming you have the developer board. The config.txt file is on the flash disk which can is S: disk in VSOS. Accessing config .txt with computer can be done with pressing S1 button and resetting the board. Then about 2 MB USB disk should show up. That would be the system disk of the device. Config.txt file should have quite extensive comments to describe its behaviour.

You might also want to look at getting started application note http://www.vlsi.fi/fileadmin/app_notes/ ... tarted.zip
Srikanth wrote:
When the USBHOST library is loaded, either with USBHOST U in CONFIG.TXT or for example with something like "void *lib = LoadLibraryP("USBHOST","U");"
Is there any API Documentation for VLSI in which I can find the functions like "LoadLibraryP()" are described with its purpose.
The documentation isn't the strongest part of VSOS as it is quite fast evolving platform. However VSIDE is here to help. CTRL-Shift-F key combination pops up find dialog which has library search if you know what you are looking for. Another neat thing in VSIDE is right clicking included .h file and selecting show in editor or aux view. Anyway LoadLibraryP is declared in apploader.h and it takes file name and parameters to pass main() function of the library.

As Panu suggested, the source code distribution is also good source for examples. The package has source codes for playfile and usbhost libraries and many other applications. You can find it from the latest VSOS thread viewtopic.php?f=13&t=680&p=10183
Srikanth wrote:
then the USB memory stick becomes drive U. Then you can use things like f=fopen("U:FILE.TXT","r"); to read a file or call RunProgram("PLAYFILE","U:MUSIC/A wonderful life.mp3"); to play a song
Does it mean that the library internally detects USB i.e. checking USB lines and sending SOF packets whenever any USB device is connected.
USBHOST library tries to mount USB disk and it timeouts if there isn't one. So you don't have to worry about USB related stuff. Only check if the disk drive is there and try to run it again if it isn't.

I hope this will help you getting started and feel free to ask if you get into troubles with VSOS.

-Hannu

User avatar
Panu
VLSI Staff
Posts: 2561
Joined: Tue 2010-06-22 13:43

Re: VS1005 MP3 Player with USB Host

Post by Panu » Mon 2016-10-03 10:48

Hi!

Actually, USBHOST tries to detect the USB stick only when it's started. If it finds the stick, it sets up a disk, usually U: If not, it timeouts in a few seconds. It doesn't detect detach, and it doesn't unload itself or do any other stuff automatically right now. I'm working on a new approach which would handle attach and detach in the background, but currently you must handle loading and unloading the USBHOST driver yourself. But not for long, I hope.

-Panu
Info: Line In and Line Out, VS1000 User interface, Overlay howto, Latest VSIDE, MCU Howto, Youtube
Panu-Kristian Poiksalo, VLSI Solution Oy

Post Reply