📄 mp3pc.c
字号:
// Now decide whether to return 0 (play on) or non-zero (stop playing)
if (!PC_Flag_Mode && !PC_Flag_Repeat)
return 1; // stop playing if wrap AND normal_play AND no_repeat
else
return 0;
}
}
u08 PrevFileNumber (void)
// Determines PREVIOUS file number. Simply subtracts StepSize from FileNumber and deals with
// any wraparound (ie FileNumber ending up being less than 1). Note that valid filenumbers are 1...NumFiles.
// Zero is not a valid filenumber, but NumFiles is valid. This routine returns 0 to indicate it completed OK.
{
u16 NumFiles;
NumFiles = (((u16)EEPROM_ReadC(StoreNumFilesH))<<8) + (u16)EEPROM_ReadC(StoreNumFilesL);
if (FileNumber > StepSize)
FileNumber -= StepSize; // step back if no wrap to deal with
else
FileNumber = NumFiles - (StepSize-FileNumber); // step back with wrap
return 0;
}
void FileNameOnLCD (void)
/* Writes the filename of the current song on the LCD display. */
/* Note that the file name can only consume 4 LCD lines max. */
{
u08 i;
/* clear the old filename off the display */
UART1_TxCharWaitC(0x5c);
UART1_TxCharWaitC(0x42);
UART1_TxCharWaitC(0x20);
UART1_TxCharWaitC(0x22); /* put cursor on start of 3nd row (row #2) */
for (i=0; i<24*4; i++)
UART1_TxCharWaitC(' '); /* overwrite rows #2 through 5 with spaces */
// This is where we improve the format the name for displaying on the LCD
// eg pad spaces to prevent words from breaking across lines
FINDFILE_RET_NAME[97] = 0; // ensure there's a null char after 4 lines of text
FormatFileNameString(4); // format filename, remove .mp3 extension
/* print new filename on the LCD display */
UART1_TxCharWaitC(0x5c);
UART1_TxCharWaitC(0x42);
UART1_TxCharWaitC(0x20);
UART1_TxCharWaitC(0x22); /* put cursor on start of 3rd row (row #2) */
uart1_putwaitstr((u08*)(&FINDFILE_RET_NAME[1])); /* print filename */
return;
}
// PCChangeFileNumber
//
// This routine changes the value of FileNumber (the song number playing). It is
// passed in TrackChange, which specifies the amount to change FileNumber by (eg 10)
// and Direction, which states whether to add or subtract TrackChange from FileNumber
// (positive value = add, zero = subtract).
//
// Important: This routine ignores things like repeat mode, random mode, etc. It will
// change the value of FileNumber regardless. Also, this routine does not wrap. If the
// requested change to FileNumber would take FileNumber to an illegal value (ie less than 1
// or greater than the number of songs in the current directory) then this routine returns
// 1 or the number of songs respectively. IE it stops at the ends of acceptable FileNumber
// values. In these ways it's different to the NextFileNumber and PrevFileNumber routines.
// (also because it doesn't care about StepSize).
//
// The primary use of this routine is in conjunction with the up/down/left/right arrows
// during song playing (which jump forward/back 10/100 songs).
void PCChangeFileNumber (u16 TrackChange, u08 Direction)
{
u16 NumFiles;
if (Direction) {
// Execute here if we're adding TrackChange to FileNumber
/* determine how many files in the player */
NumFiles = (((u16)EEPROM_ReadC(StoreNumFilesH))<<8) + EEPROM_ReadC(StoreNumFilesL);
FileNumber += TrackChange; // Increase FileNumber
if (FileNumber > NumFiles)
FileNumber = NumFiles; // Ensure FileNumber no larger than number of actual files
return;
}
else {
// Execute here if we're subtracting TrackChange from FileNumber
if (FileNumber > TrackChange)
FileNumber -= TrackChange; // Decrease value of FileNumber if possible
else
FileNumber = 1; // otherwise limit FileNumber to 1 (illegal to be less than 1)
return;
}
}
void MuteSTcodec (void)
/* Sets the output attenuation of the codec to maximum */
{
u08 RC;
RC = sta013_writeTWI (0x14, 0x01); // set the mute bit in STA013
if (RC != TWI_write_OK) StopOnError(RC + 10); /* report error if it occurs */
}
void unMuteSTcodec (void)
/* Sets the output attenuation of the codec to minimum */
{
u08 RC;
RC = sta013_writeTWI (0x14, 0x00); // clear the mute bit in STA013
if (RC != TWI_write_OK) StopOnError(RC + 30); /* report error if it occurs */
}
/******************************************************************************
Routines associated with RANDOM mode, including EEPROM accesses, are below.
Also look at CntMP3files() in mp3init.c, as it handles the file counting,
which is performed at power-up (if reqd) and also when the current directory
is changed, with the resultant number of files stored in eeprom.
******************************************************************************/
void EEPROM_Write (u16 addr, u08 data)
/* This routine writes a single byte to the specified eeprom location */
/* Read the AVR Mega128 datasheet to make any sense of it! */
{
/* ensure no other write still happening - wait until hardware ready */
while (*AVR_EECR & 0x02);
/* set up eeprom address & data registers */
*AVR_EEARH = (u08)(addr>>8); /* upper 8 bits of address into EEARH */
*AVR_EEARL = (u08)(addr & 0x00ff); /* lower 8 bits of address into EEARL */
*AVR_EEDR = data;
/* set EEMWE bit (this is like a gating bit) */
*AVR_EECR = 0x04;
/* now set the EEWE bit as well (causes the hardware write sequence to commence) */
*AVR_EECR = 0x06;
}
u16 GetRandomNumber (u16 maxnum)
/* This routine returns a random number in the range of 1..maxnum inclusive. */
/* It starts off by determining a 16-bit random number by reading the 8-bit counter */
// value TCNT0 (timer/counter 0) as well as the low byte of timer/counter 1 value.
/* Then it determines the remainder from trying to divide maxnum+1 into this random number. */
{
u16 i;
i = *AVR_TCNT0 + (((u16)*AVR_TCNT1L)<<8); /* read the 16-bit counter */
/* shuffle counter value around right here if you want to shuffle! */
i = i % maxnum; /* this gives a number 0..maxnum-1 */
i = i+1; /* now the number is 1..maxnum */
return (i);
}
u08 FindNthMP3(u16 N)
/* WARNING: DOES NOT RETURN UNTIL COMPLETED - VERY VERY SLOW */
/* This routine finds the Nth MP3 in the current directory, where N is passed in. */
/* It returns FindFile_done if it succeeeded, and FindFile_err if it was unable */
/* to get it - this would be due to N being higher than the number of files on the drive, */
/* or N being zero. Minimum value of N is 1; there is no zero'th file. */
// Basically, this routine counts MP3 files in the current directory until it has
// counted the indicated number of files. Then, because it's not using FindFile
// (because FindFile is too slow) this routine fills in the usual FindFile global variables,
// such as file start cluster, length, etc, so that other routines needing that information
// will have it. This routine uses StreamFileC to feed it the directory. Some notes:
// - If the FAT has an error in it, the directory cluster chain can end before
// the directory is properly finished. This is detected by noticing that
// StreamFileC has idled prematurely.
// - Directory entires are 32 bytes. So don't try reading anything until you
// know you have at least 32 bytes in the data queue.
// - We don't know how long the directory is. So give StreamFileC a huge file size
// number, so that it'll stream until it can't stream no more!
//
// StreamFileC is told to provide cluster numbers. So at the beginning of each cluster
// StreamFileC puts the 4-byte cluster number, low-byte first, into the data Q. This routine
// needs to keep track of the number of bytes taken from the data Q, and extract those 4
// bytes at the beginning of each cluster's worth. Number of bytes in a cluster equals
// number of sectors per cluster (SEC_PER_CLUS) times 512 (bytes per sector).
// FINDFILE_CLUS contains the current cluster number we're reading directory data from.
// FINDFILE_PREV_CLUS contains the previous value of FINDFILE_CLUS; used by GetLongFileName
// FINDFILE_OFSET contains the number of bytes we're currently offset into the current cluster.
// (At completion of this routine, it'll be just _past_ the directory entry for the Nth file.)
// We keep track of this information in globals because GetLongFileName needs it later on.
// (FINDFILE_PREV_CLUS just remembers the previous values of FINDFILE_CLUS so make it
// easier for GetLongFileName to go backwards in the directory structure.)
//
// FINDFILE_RET_CLUS & FINDFILE_RET_SIZE contain starting cluster number & file size of the
// MP3 file this routine was told to find. FINDFILE_RET_NAME contains its 8.3 filename.
//
// This routine wants to make sure that in the process of working through the directory structure
// to find the Nth MP3, it passes by the (N-1)th MP3. This is because the long file name for
// the Nth MP3 is located in the directory structure between the (N-1)th file and the Nth file.
// Put another way, the long file name for the Nth file actually comes before the directory entry
// for that Nth file. The directory structure may cross a cluster boundary in that time, ie, part
// of the long file name for the Nth file may be on the cluster containing the directory entry for
// that Nth file, and part of the long name may be on the cluster containing the directory entry for
// the (N-1)th file. And, the clusters need not be contiguous; these two clusters may have very
// different cluster numbers. What we want to end up with is the cluster number of the Nth MP3 file
// directory entry being in FINDFILE_CLUS, and the cluster number of the (N-1)th file directory entry
// being in FINDFILE_PREV_CLUS. Usually these two cluster numbers will be the same, but sometimes not.
//
// So, this routine looks in the FastFile table for the (N-1)th MP3 file directory entry cluster number and
// starts working through the directory structure from there. This guarantees it'll go past the (N-1)th
// MP3 directory entry on its way to the Nth directory entry. In the code this is accomplished by
// using the NN variable, which tells the code looking in the FastFile table which filenumber to look for.
{
u16 NN, filecount, filenum, eepromaddr;
u08 i, firstchar, extm, extp, ext3, attr;
if (N==0)
return FindFile_err; // error if we're asked for zero'th file
if (N > ((((u16)EEPROM_ReadC(StoreNumFilesH))<<8) + (u16)EEPROM_ReadC(StoreNumFilesL)) )
return FindFile_err; // error if we're asked for more files than in player
FeedSTcodec_Command = FSC_Cmd_Stop; // ensure ST codec not trying to read MP3 data Q
// Look (backwards) through the FastFind table to locate a cluster number to start searching
// for our "Nth MP3" from. Saves us from having to start at the beginning of the directory.
// Format of the table is: 2-byte file number followed by 4-byte cluster number. Low bytes stored first.
// File number refers to the number of the first MP3 file in that directory cluster.
NN = N-1; // Look in FastFind table for (N-1)th file unless
if (NN == 0) NN = 1; // that takes us to the zero'th (non-existent) file
eepromaddr = (u16)(FFTableEnd+3); // Point just above start of last record in table
filenum = 0x7FFF; // Start with a big filenumber read from table
// step backwards through table until we find a filenumber <= NN
while (filenum > NN) {
eepromaddr -= 8; // point to start of previous record in table
filenum = (u16)EEPROM_ReadC(eepromaddr++);
filenum += (((u16)EEPROM_ReadC(eepromaddr++))<<8); // pull filenumber from table
}
// Now that we've found a suitable table entry, get the cluster number, save all results
FINDFILE_CLUS = (u32)EEPROM_ReadC(eepromaddr++);
FINDFILE_CLUS += (((u32)EEPROM_ReadC(eepromaddr++))<<8);
FINDFILE_CLUS += (((u32)EEPROM_ReadC(eepromaddr++))<<16);
FINDFILE_CLUS += (((u32)EEPROM_ReadC(eepromaddr++))<<24); // this is cluster # we start reading directory data from
FINDFILE_PREV_CLUS = FINDFILE_CLUS; // initial value of previous dir cluster
filecount = filenum - 1; // this is how many files we've skipped thanks to table
// Note filecount can start at zero.
// Ensure StreamFileC stopped
STREAMFILE_CMD = StreamFile_Cmd_Stop; // command StreamFileC to STOP
StreamFileC();
while (STREAMFILE_ST!=StreamFile_St_Idle) StreamFileC(); // wait until StreamFileC idle
// Ensure MP3dataQ empty
Q_clear_C((u08*)&MP3DATAQ[0]);
// Command StreamFileC to stream current directory into the MP3dataQ
STREAMFILE_FILESZ = 0xFFFFFFF; // huge "file size"
STREAMFILE_CLUS = FINDFILE_CLUS; // cluster number to start reading directory data from
STREAMFILE_QPOINTER = &MP3DATAQ[0]; // point StreamFile to the MP3 Data queue
STREAMFILE_CMD = StreamFile_Cmd_SmWithCl; // command StreamFileC to start streaming, provide cluster numbers
StreamFileC();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -