⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp3_player_06.c

📁 基于ATmega64单片机以及vs1003的SD卡方案的MP3播放源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*****************************************************/
/*                mp3 player V2.1                                                   */
/* Description : A mp3 player support lrc sd & U disk                 */
/* Platform     : AVRStudio4.13 + WinAVR20070525  m64        */
/* Author       : Michael Zhang - 章其波                            */
/* Email         : sudazqb@163.com                                          */
/* MSN          : zhangqibo_1985@hotmail.com                          */
/* Date          : 2007-11-03                                                    */
/* NOT FOR COMMERCIAL USE,     ALL RIGHT RESERVED!         */
/*****************************************************/

/*********************  old  ***************************/
/*                   MP3/Wma/Midi播放器                      */
/*  环境WinAVR 20060421                                      */
/*  作者:Bozai(章其波)                                    */
/*  E-mail:sudazqb@163.com                                  */
/*  2006年12月12日                                           */
/*************************************************************/
/*  20071122: add teminal control code                                   */
/*  20071121: solve glitch problem when playing 320Kbps files            */
/*  20071109: add & modify function for any directory music file playing */
/*  20071103: add function for lyric display                             */


#include<avr/io.h>
#include<avr/eeprom.h>
#include"CH375/CH375.h"
#include"FAT/FAT.h"
#include"UART/UART.H"
#include"VS1003B/VS1003B.h"
#include<avr/pgmspace.h>
#include"LCD/LCD_ASCII.h"
#include"LCD/LCD.H" 
#include"LCD/LCD_GBK.h"
#include"MMC_SD/MMC_SD.h"
#include"LCD/LCD_APP.h"
#include<avr/interrupt.h>
//#include"IDE/IDE.h"

#define STOP_KEY 0

#define uint unsigned int

#define ENTER_KEY 0x0d
#define BACK_KEY  0x08
#define ESC_KEY   0x1b
#define MAX       64

#if STOP_KEY
	#define MODE _BV(PE7)
	#define STOP _BV(PE6)
#else
	#define MODE _BV(PE6)
	#define STOP _BV(PE7)
#endif

#define NEXT _BV(PE3)
#define UP   _BV(PE5)
#define DOWN _BV(PE4)
#define PREV _BV(PE2)

#define LCD_BL PG3
#define LCD_BL_CON DDRG |= 1<<LCD_BL
#define LCD_BL_ON  PORTG &= ~(1<<LCD_BL)
#define LCD_BL_OFF  PORTG |= 1<<LCD_BL
#define LCD_BL_INV PORTG ^= 1<<LCD_BL

#define MP3 1
#define WMA 2
#define MID 3
#define WAV 4

//mode
#define REPET_ALL 0
#define REPET_ONE 1
#define RANDOM    2

/* enum for ICON */
enum IconTag
{
	Playing,Pause,RepetAll,RepetOne,Shuffle,Time,Music,Speaker
};

/* Long name buffer and flag */
extern unsigned char LongNameBuffer[MAX_LONG_NAME_SIZE];
extern unsigned char LongNameFlag;

/* indicate if the file system is FAT32 , ortherwise it is FAT16, note FAT12 is not supported */
extern BYTE FAT32_Enable;

extern WORD SectorsPerClust;//每簇扇区数
extern WORD FirstDataSector;//第一个数据扇区数

//struct FileInfoStruct FileInfo;//文件信息

struct direntry MusicInfo;	/* Music file information, 32Bytes short directory record, contain the short name and others */
struct direntry LrcInfo;	/* lyric file information, 32Bytes short directory record, the short name and others */


/* The path of the music file & lyric file , caution: each driectory should long longer than 8, that is not support long name*/
#if FIX_DIRECTORY
#define MUSIC_PATH "\\music"
#endif

#define LRC_PATH "\\lrc"

void (*BootLoaderEntry)(void) = 0xf800;	/* boot loader entry, bootloader size: 2048Bytes */

uint16 totalsongs;	/* total number of songs*/
uint8 type;			/* current song's file type, mp3 wma mid or wav */
uint8 lrc =0;			/* Gloable variable to indicate wether the songs has a lyric file, 1 means have */
uint8 HanziEnable = 0;	/* Gloable variable to indicate wether the firmware are exist, and 1 means exist */

/* Time tag structure */
struct LrcStruct_s {
	struct LrcStruct_s * next;	/* the next node */
	uint32 time;				/* Time */
	uint16 eeaddr;			/* Address, start with 0, value greater than MAXLRCDATSIZE is the eeprom address*/
};


struct LrcStructHead_s {
	struct LrcStruct_s *header;	/* Pointer to the first node of time tag struct */
#define TI_LEN 32
	uint8 title[TI_LEN];			/* Title */
#define AR_LEN 16
	uint8 artist[AR_LEN];			/* Artist */
	uint16 offset;					/* Offset */
       uint8 sign;					/* "1" means "+", and "0" means "-" */
};

#define DEBUG 0	/* Macro for DEBUG, if 1 DEBUG message will show throw the UART */


struct LrcStructHead_s LrcStructHead;	/* Gloable struct variable to record the lyric info */

/* Use to record the time tag info */
#define MAXITEM 80
uint8 lrcbuffer[sizeof(struct LrcStruct_s) * MAXITEM];

/* Use to record the lyric data */
#define MAXLRCDATSIZE 650			/* Max data size in SRAM, other will be store in EEPROM */
uint8 lrcdatbuf[MAXLRCDATSIZE];


uint8 track[128];			/* stroe the information of songs (bit set indicate songs has been played) */

void ClearTrackInfo()		/* cleare the array track[128] */
{
	uint8 i;
	for(i=0;i<128;i++)track[i] = 0;
}

uint8 SetTrack(uint16 songs)/* set the track bit, return 1 means the song has been played */
{
	uint8 byte_offset;
	uint8 bit_offset;
	songs--;
	byte_offset = songs/8;
	bit_offset = songs%8;
	if(track[byte_offset] & (1<<bit_offset))return 1;
	else
	{
		track[byte_offset] |= 1<<bit_offset;
		return 0;
	}
}

/*void nextline()
{
	USART_putchar(0x0d);
	USART_putchar(0x0a);
}*/

void Delay(uint16 n)//延时
{
	while(n--)asm("nop");
}

//Timer initialization offer seed of the srandom()
void Timer1_Initial()
{
	TCNT1H=0x00;
	TCNT1L=0x00;
	TCCR1A=0x03;
	TCCR1B=0x01;
	ICR1H=0xff;
	ICR1L=0xff;
}

uint8 strcomp(uint8 * src, uint8 * dst) /* String compare */
{
	while(*src)
	{
		if(*src++ != *dst++)return 0;
	}
	return 1;
}

uint8 strcomp_noncase(uint8 * src, uint8 * dst)/*we should make sure the src is upcase*/
{
	uint8 * p1 = src, * p2 = dst;
	while(*p1)
	{
		if((*p1 == *p2) || ((*p1<*p2)&&((*p2-*p1) == 0x20 )) )
		{
			p1 ++;
			p2 ++;
		}
		else return 0;
	}
	return 1;
}

/* Lyric proccess fuction */
#if FIX_DIRECTORY
uint8 LrcProc(uint8 *LongNameBuffer) /* Parameter is the song's long name or short name, note: do not contain the extention*/
#else
uint8 LrcProc(uint8 *LongNameBuffer,WORD music_record_addr) /* Parameter is the song's long name or short name, note: do not contain the extention*/
#endif
{
	/* lyric time tag struct pointer for process*/
	struct LrcStruct_s * LrcStruct_p;
	struct LrcStruct_s * LrcStruct_p_up, * LrcStruct_p_temp,* LrcStruct_p_down;
	struct LrcStruct_s * LrcStruct_p_header;
		
	uint16 lrcaddr;		/* The address to store each lyric */
	uint8 part;			/* the sector number of one cluster */
	uint16 i;				/* loop variable for gerneral perpus */
	uint16 j;
	uint8 temp;			/* temp variable */
	uint8 * buffer;		/* buffer pointer, later will use malloc to get the data area for it*/
	uint16 min,sec,ms;	/* temp variable for time tag process, minter, second, and milisecond */
	uint8 sector;			/* sector number to record current sector, with variable j to determine wether the file is ended*/
	uint8 totalsect;		/* total sectors the file contains */
	uint16 leftbytes;		/* how many data contained in the last sector */
	uint32 p;			/* cluster number of file, next ,etc */
	uint8 mscnt;			/* counter for ms, you konw 2.3 means 2300ms not 2003ms, so need this variable to determin this*/
       
	LrcStructHead.header = (struct LrcStruct_s *)lrcbuffer;	/* set lrc info struct 's header to the buffer */

#if FIX_DIRECTORY
	if(SearchLrc(LRC_PATH,LongNameBuffer,&LrcInfo)==0)	/* search the path specified, and if found lyric file it will return 0*/
#else
	if(SearchLrc(LRC_PATH,LongNameBuffer,&LrcInfo,music_record_addr)==0)	/* search the path specified, and if found lyric file it will return 0*/
#endif
	{ 
		printf_P(PSTR("\r\n\r\n*****************************************************"));
		printf_P(PSTR("\r\nFound LRC file!"));
		printf_P(PSTR("\r\n\r\nAnalyzing LRC file ...........\r\n"));
	   
		lrc = 1;								/* Set the flag */
		lrcaddr = 0;							/* Clear the address */
	   
		LrcStruct_p = LrcStructHead.header;		/* intialize the sigle direction node */
		for(i=0;i<MAXITEM-1;i++)
		{
			LrcStruct_p->next = LrcStruct_p + 1;
			LrcStruct_p = LrcStruct_p->next;
		}
		LrcStruct_p->next = 0;
		LrcStruct_p = LrcStructHead.header;
								  
		LrcStructHead.offset = 0;				/* clear the lyc info struct */
		LrcStructHead.title[0] = '\0';
		LrcStructHead.artist[0] = '\0';
	   
		buffer = malloc(520);					/* allocate memory for read the lyric file */
		if(buffer==0)
		{
			#if DEBUG
			printf_P(PSTR("\r\nERROR: No enough memory!"));
			#endif
			return 1;
		}

		p = LrcInfo.deStartCluster+(((unsigned long)LrcInfo.deHighClust)<<16);	/* Calculate the first cluster of the lyric file */
		totalsect = LrcInfo.deFileSize/512; /*计算扇区数			//calculate the total sectors */
		leftbytes = LrcInfo.deFileSize%512; /*计算剩余的字节数	//calculate the left bytes */	
		sector=0;				/* clear the sector counter */

/*  here to start analyze the lyric file */    
		while(1)
		{
			for(part=0;part<SectorsPerClust;part++)	/* first loop for read a sector of a culster */
			{
				if(FAT_LoadPartCluster(p,part,buffer))
				{
					#if DEBUG
						printf_P(PSTR("\r\nERROR: Failed to read one sector"));
					#endif
					free(buffer);
					return 1;
				}
				for(j=0;j<512;)	/* second loop for analyze each byte of the sector */
				{
					if(sector == totalsect && j == leftbytes)	/* see if it is the end of file */
					{
						part = SectorsPerClust;		/* next loop it will get out */
						break;
					}
					if(buffer[j] == '[')			/* if it is the "[" : the tag start */
					{
						#if DEBUG
							printf_P(PSTR("\r\nfound tag start ["));
						#endif
/**********************************************************************************************************/                                    
						i = 0;
						if(strcomp_noncase("TI:",&buffer[j+1]))		/* string compare to check if this is a title tag */
						{
							j+=4;		/* count add 4 */
							while(1)		/* store the title */
							{
								temp = buffer[j++];
								if(temp == 0x0d || temp == 0x0a || temp == ']' || i> (TI_LEN - 2)) /* title ended */
									break;
								LrcStructHead.title[i++] = temp;
							}
							LrcStructHead.title[i] = 0;	/* need a 0 to end the string */
                        
							#if DEBUG
								printf_P(PSTR(" found title tag: %s ]"),LrcStructHead.title);
							#else
								printf_P(PSTR("\r\nTitle  : %s "),LrcStructHead.title);
							#endif
                                            
						}
/**********************************************************************************************************/						
						else if(strcomp_noncase("AR:",&buffer[j+1]))	/* string compare to check if this is a artist tag */
						{
							j+=4;	/* count += 4 */
							while(1)	/* store the content */
							{
								temp = buffer[j++];
								if(temp == 0x0d || temp == 0x0a || temp == ']' || i>(AR_LEN - 2))	/* tag ended */
									break;
								LrcStructHead.artist[i++] = temp;
							}
							LrcStructHead.artist[i] = 0;		/* need a 0 to end the string */
                        
							#if DEBUG
   								printf_P(PSTR(" found artist tag: %s ]"),LrcStructHead.artist);
							#else
								printf_P(PSTR("\r\nArtist : %s "),LrcStructHead.artist);
							#endif
	 
						}
/**********************************************************************************************************/
						else if(strcomp_noncase("OFFSET:",&buffer[j+1]))	/* string compare to check if this is a offset tag */
						{
							j+=8;	/* count += 8 */
						
							LrcStructHead.offset = 0;	/* default value, in case the tag like this [offset:] */
 							LrcStructHead.sign = 1;

							#if DEBUG
								printf_P(PSTR(" found offset tag: "));
							#else
								//printf_P(PSTR("\r\n"));
							#endif
                                           
							while(1)	/* proceed the offset */
							{
								temp = buffer[j++];

								#if DEBUG
									USART_putchar(temp);
								#endif
                                                       
								if(temp == ']')break;	/* tag end */
								if(temp == '-')			/* sign */
								{
									LrcStructHead.sign = 0;
									continue;
								}
								LrcStructHead.offset *= 10;			/* calculate the value */
								LrcStructHead.offset += (temp-0x30);
							}
                                           
							#if DEBUG
								printf_P(PSTR("the value in the structure is : %d"),LrcStructHead.offset);
							#endif
                                             
						}
/**********************************************************************************************************/					
						else if(strcomp_noncase("BY:",&buffer[j+1]))	/* string compare to check if this is a By tag */
						{											/* but we do not need this tag */
							j+=4;
                                              
							#if DEBUG
								printf_P(PSTR(" found by tag: "));
							#endif
                                               
							while(1)
							{
								temp = buffer[j++];

								#if DEBUG
									USART_putchar(temp);
								#endif
                                                       
								if(temp == 0x0d || temp == 0x0a || temp == ']' ||i>30)break;
							}
						}
/**********************************************************************************************************/									 
						else if(strcomp_noncase("AL:",&buffer[j+1]))	/* string compare to check if this is a album tag */
						{
							j+=4;

							#if DEBUG
								printf_P(PSTR(" found al tag: "));
							#else
								printf_P(PSTR("\r\nAlbum  : "));
							#endif

							while(1)
							{
								temp = buffer[j++];   
								if(temp == 0x0d || temp == 0x0a || temp == ']' ||i>30)break;
								USART_putchar(temp);
							}
						}
/**********************************************************************************************************/									   
						else		/* otherwise this must the time tag or other not recognize tag */
						{
							j+=1;
							/****************************************************************/
							if(sector == totalsect && j == leftbytes + 1) goto end; /* if the file is end */
							if(j == 512)	/* wether the sector is end, need to read the next sector */
							{
								if(part == (SectorsPerClust - 1))	/* if need to read next cluster */
								{
									//p=FAT_NextCluster_NEW(p);//读下一簇数据			//read next cluster
									p=FAT_NextCluster(p);
									if(p == 0x0fffffff || p == 0x0ffffff8 || (FAT32_Enable == 0 && p == 0xffff))//如果无后续簇则结束,	//no more cluster  
									{
										#if DEBUG
											printf_P(PSTR("\r\nNo next cluster or read next cluster error"));
										#endif
										goto end;
									}
									part = 0;	/* clear the part count */
									if(FAT_LoadPartCluster(p,part,buffer))
									{
										#if DEBUG
											printf_P(PSTR("\r\nERROR: Faild to load a sector"));
										#endif
										free(buffer);
										return 1;
									}
								}
								else 	/* else just read the next part of the cluster */
								{
									part ++;	/* part ++ */
									if(FAT_LoadPartCluster(p,part,buffer))
									{
										#if DEBUG
											printf_P(PSTR("\r\nERROR: Faild to load a sector"));
										#endif
										free(buffer);
										return 1;
									}
								}
								sector ++;	/* sector count +=1 */
								j = 0;		/* loop value clear to 0*/
							}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -