📄 player.c
字号:
//Player.c
#include <string.h> //memcmp
#include <stdio.h> //sprintf
#include "SPI_SD.h"
#include "Player.h"
#include "I2S.h"
BYTE databuffer[512];
ULONG CachedSectorAddress; //DataBuffer address
BYTE playbuffer[512];
//FAT information
BYTE FATType; //0:FAT12, 1:FAT16
ULONG SectPerClust; //Sectors in Cluster
ULONG RootDirEntrys; //Entrys in Root Sector
ULONG FATStartSect; //Sector, FAT starts
ULONG DIRStartSect; //Sector, Root Dir starts
ULONG DataStartSect; //Sector, Data Area starts
FILEINFO WAVFiles[32]; //max 32 wave file can be played.
//Music Information
ULONG MusicNum; //Playing Musics Number, from 1
ULONG TotalMusics; //Total WAV File Num, from 1
ULONG CurrentClust; //Playing Cluster
ULONG StartSectofClust; //First Sector in current Playing Cluster
ULONG CurrentSectinClust; //Playing Sector in Playing Cluster
ULONG SectorCounter; //Counter for Sector in cluster, from 0, < SectPerClust
ULONG RemainingSect; //Sector remain in current music
ULONG PlayedSect; //Sector Played in current music
//These are 512bytes/128samples/2.9ms
//Basics of Operation
//Sector: 512Byte block, reading minimum unit from SD card.
//Cluster: 64 Sector = 32KB block in SD card.
//FAT sectors: Cluster address listing table. 256 index in one sector.
// 3 minutes of wave file size is about 31MB, it contains > 1000 cluster.
//reading one Sector needs 1.4ms.
//One Sector, 512Byte is consumed in 2.9ms.
//So reading cluster between playing can cause glitch.
//CBs will store Cluster chain listing.
// if Cluster chain is 0x0004 to 0x0024, 0x0045 to 0x0208
// CBs[0].Start_Cluster = 0x0004
// CBs[0].End_Cluster = 0x0024
// CBs[1].Start_Cluster = 0x0045
// CBs[1].End_Cluster = 0x0208
// Pros:So there are no FAT sector lookup when playing music.
// Cons:too much flagmented, chains > 128 file can not be played. maybe never happen by NORMAL operation
CLUSTERBLOCK CBs[128];
WORD CurrentCBIndex;
//DMA Flag, controlled by I2S.c
extern BYTE DMA_Flag_A;
//DMA Buffer, exists in I2S.c
extern WORD dci1TxBuffA[512] __attribute__((space(dma)));
extern WORD dci1TxBuffB[512] __attribute__((space(dma)));
//0x 00:00 buffer
char MinSec[10];
BYTE Player_Init(void)
{
BYTE ret = 0;
CachedSectorAddress = 0;
memset(WAVFiles,0x00,sizeof(WAVFiles));
//read FAT information, store into local variables
ret = read_FAT_info();
if (ret != 0) return ret;
//search wave files.
ret = search_WAV(32);
TotalMusics = ret;
MusicNum = 1;
//do simple sort, by file name
SortMusic();
//just initializing variables: set again at Player_GotoMusicHead
CurrentClust = 0;
CurrentSectinClust = 0;
RemainingSect = 0;
PlayedSect = 0;
return ret;
}
void Player_NusicName(char * dest)
{
memcpy(dest, WAVFiles[MusicNum - 1].fname, 8);
}
DWORD Player_FileSize(void)
{
return WAVFiles[MusicNum -1].fsize;
}
UINT Player_MusicNum(void)
{
return (UINT)MusicNum;
}
//For starting info
void Player_TotalMinSec(char * dest)
{
memset(MinSec,0x00,sizeof(MinSec));
//return mm:ss as Total minutes:second
UINT TotalSecond = 0;
UINT Minutes = 0;
UINT Seconds = 0;
TotalSecond = ((WAVFiles[MusicNum -1].fsize)>>10) / 176;
Minutes = (UINT)(TotalSecond / 60);
Seconds = TotalSecond % 60;
sprintf(&MinSec[0],"%02u ", (UINT)(MusicNum & 0x00FF));
sprintf(&MinSec[3],"%02u", Minutes);
sprintf(&MinSec[5],":");
sprintf(&MinSec[6],"%02u", Seconds);
memcpy(dest, MinSec, 8);
}
//Playing info, erapsed min:sec
void Player_MinSec(char * dest)
{
memset(MinSec,0x00,sizeof(MinSec));
//return mm:ss as played minutes:second
UINT PlayedSecond = 0;
UINT Minutes = 0;
UINT Seconds = 0;
PlayedSecond = (PlayedSect * 30) >> 10 ;
Minutes = (UINT)(PlayedSecond / 60);
Seconds = PlayedSecond % 60;
sprintf(&MinSec[0],"%02u ", (UINT)(MusicNum & 0x00FF));
sprintf(&MinSec[3],"%02u", Minutes);
sprintf(&MinSec[5],":");
sprintf(&MinSec[6],"%02u", Seconds);
memcpy(dest, MinSec, 8);
}
void Player_GotoMusicHead(ULONG Music)
{
WORD SearchingClust = 0;
WORD NextClust = 0;
//Go to Starting Cluster
CurrentClust = WAVFiles[Music - 1].org_clust;
//Get First Sector Address in Cluster
StartSectofClust = (CurrentClust -2) * SectPerClust + DataStartSect;
//Current Sector is starting Sector in Cluster
CurrentSectinClust = StartSectofClust;
//SectorCounter is 0
SectorCounter = 0;
//All sector is remaining
RemainingSect = ((WAVFiles[Music - 1].fsize) >> 9);
//Nothing Played yet
PlayedSect = 0;
//Get Cluster Listing
memset(CBs, 0x00, sizeof(CBs));
CurrentCBIndex = 0;
CBs[CurrentCBIndex].Start_Clust = WAVFiles[Music-1].org_clust;
SearchingClust = CBs[CurrentCBIndex].Start_Clust;
while(CurrentCBIndex < 128 - 1 )
{
NextClust = GetnextClusterByFAT(SearchingClust);
if (NextClust == (SearchingClust + 1))
{
//continuous cluster.
SearchingClust += 1;
}
else
{
//case, end of cluster chain
if ((NextClust == 0xFFFF)||(NextClust == 0x0000))
{
CBs[CurrentCBIndex].End_Cluster = SearchingClust;
break;
}
//jump to another location
else
{
CBs[CurrentCBIndex].End_Cluster = SearchingClust;
CBs[CurrentCBIndex+1].Start_Clust = NextClust;
CBs[CurrentCBIndex+1].End_Cluster = NextClust; //avoid missing link
CurrentCBIndex++;
}
}
}
CurrentCBIndex = 0; //reset cluster-block index.
}
void Player_Stop(void)
{
//Stop SPDIF Stream
initI2sBuff();
i2s_stop();
//Player goes to first music, first Cluster, first sector
MusicNum = 1;
Player_GotoMusicHead(MusicNum);
}
void Player_Start(void)
{
dma0_start(); //restart DMA
//start SPDIF Stream
i2s_start();
}
void Player_Pause(void)
{
//SPDIF Stream is set to all zero. keep stream.
initI2sBuff();
}
void Player_FF(void)
{
//go to next music
MusicNum += 1;
if (MusicNum > TotalMusics)
{
MusicNum = TotalMusics;
}
//goto head of music
Player_GotoMusicHead(MusicNum);
}
void Player_Prev(void)
{
//go to previous music
MusicNum -= 1;
if (MusicNum < 1)
{
MusicNum = 1;
}
//goto head of music
Player_GotoMusicHead(MusicNum);
}
BYTE Player_Play(void)
{
ULONG TailFillerSize = 0;
int i = 0;
BYTE ret = 0;
BYTE ToContinue = 1; //initially, continue mode
ret = SD_Read_Single_Block(CurrentSectinClust * 512, playbuffer);
//Modify Head and Tail sector
if (PlayedSect == 0) //This is first sector, includes headder
{
//fill WAVE headder with 0x00
memset(playbuffer, 0x00, 44);
}
if (RemainingSect < 1) //now this is last sector.
{
//Fill tail of sector with 0x00
TailFillerSize = (WAVFiles[MusicNum - 1].WaveSize + 44) % 512;
TailFillerSize &= 0x000001FF; //limit 512 to avoid miss-fill. just in case..
memset(playbuffer + (512 - TailFillerSize), 0x00, (512 - TailFillerSize));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -