📄 mp3_player_06.c
字号:
/*****************************************************/
/* 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 + -