📄 mp3menus.c
字号:
It does this by displaying the names of the directories in the current
directory, and allowing the user to press SELECT to choose one. The FAT32
directory structure includes the "." and ".." directories for the current
and parent directory respectively, so the user can select either of those
as well if desired.
******************************************************************************/
void ChangeDir (void)
{
u16 dirnumber;
u08 stopflag;
PositionLCDcursor(1, 1); // place cursor at start of top display line
uart1_putwaitPROGstr(PSTR(" Change Directory Up / Down / Select"));
// check there's at least one directory in the current directory - tell user if not
if (FindNthDir(1)) {
ClearLCDlines(2, 3); // clear lines 2, 3, 4
PositionLCDcursor(3, 1);
uart1_putwaitPROGstr(PSTR(" No Directories Found. Press SELECT to exit."));
while (ButtonPress != BUT_MENUSEL); // wait for SELECT button to be pressed.
ButtonPress = 0; // clear out that button press.
IDE_AutoPD(); // tell the drive to auto power-down
return;
}
stopflag = 0; // stopflag controls the do-while (outer) loop
do {
// If we got this far, there's at least one directory entry in the current directory. So loop,
// (inner loop, the while loop), printing their names, until the user presses SELECT to choose one.
// Also print name of the directory we're currently residing in.
GetCurrentDirName(); // get name of directory we're currently in
ClearLCDlines(3, 2); // clear lcd lines 3 & 4
PositionLCDcursor(3, 1);
uart1_putwaitstr((u08*)&FINDFILE_RET_NAME[1]); // and print current directory name on LCD screen
dirnumber = 1; // start with the first directory...
FindNthDir(dirnumber); // get the details on this directory (name etc)
DisplayDirName(); // manage & display dir name on lcd
while (ButtonPress != BUT_MENUSEL) {
switch (ButtonPress) {
case BUT_ONOFF:
ButtonPress = 0;
SwitchOff(); /* switch the player off - this routine never returns */
break;
case BUT_UP:
ButtonPress = 0;
dirnumber--; // previous directory - we know it exists (that's the
if (dirnumber==0) dirnumber = 1; // definition of "previous") so just do it. Ensure we
FindNthDir(dirnumber); // don't go too far back though.
DisplayDirName(); // manage & display dir name on lcd
break;
case BUT_DOWN:
ButtonPress = 0;
dirnumber++; // look for the next directory entry
if (FindNthDir(dirnumber)) { // if there are no more directories, then...
dirnumber--;
FindNthDir(dirnumber); // ...redo the last one we did
}
DisplayDirName(); // manage & display dir name on lcd
break;
}
} // bottom of inner (while) loop
// If we're here it's because the user pressed SELECT, choosing the displayed directory as their new one.
// So change into that new directory. If the user pressed select on a "Select This Directory" entry,
// also known as a "." directory, they're saying that they're finished navigating through the directories.
// We can easily detect that case because the new dir cluster number (FINDFILE_RET_CLUS) will be the
// same as the current dir cluster number (CURRENT_DIRCL). In that case set the stopflag.
ButtonPress = 0; // clear out that (SELECT) button press.
if (CURRENT_DIRCL == FINDFILE_RET_CLUS) stopflag = 1; // check to see if user finished
CURRENT_DIRCL = FINDFILE_RET_CLUS; // directory starting cluster is now changed
} while (stopflag==0); // bottom of the outer (do-while) loop
// If we're here it's because the user pressed SELECT on a "Select This Directory" entry, also known as
// a "." directory. In other words, we're finished. Save the new directory cluster number in eeprom.
// Then we need to count the number of MP3 files in the new dir and build the new fast-find table.
// Clean-up and exit.
EEPROM_Write(DIRcluster0, (u08)(CURRENT_DIRCL)); // write cluster number low-byte into eeprom
EEPROM_Write(DIRcluster1, (u08)(CURRENT_DIRCL>>8));
EEPROM_Write(DIRcluster2, (u08)(CURRENT_DIRCL>>16));
EEPROM_Write(DIRcluster3, (u08)(CURRENT_DIRCL>>24)); // write cluster number high-byte in eeprom
ClearLCDlines(4, 4); // clear lcd lines 4 - 7 (where the DIR name just was)
CntMP3files(); // count how many MP3s in the new directory
BuildFastFindTable(); // build the FastFind table for this new directory
if (PC_Flag_Mode)
InitRandomVariables(); // if random mode currently on, re-init it
else
FileNumber = 1; // else by default we'll just play the first MP3 in the new directory
IDE_AutoPD(); // tell the drive to auto power-down
}
// DisplayDirName
//
// Not quite as trivial as the name suggests, this routine manages the directory name and displays it.
// If the name is ".." it displays "Up to Parent Directory". It retrieves the long directory name where
// appropriate. It prints the name on the LCD display.
//
// Note that . and .. are special cases, for the current and up-one-level directories respectively.
// They don't have long names, and we display them differently. We change the strings from the rather
// uninformative "." and ".." to more useful text strings names.
//
// If the directory is not "." or ".." then we go and get it's long name.
// Theoretically the dir name can be quite long, spanning multiple lcd lines and requiring name formatting.
// Which is why FormatFileNameString(0) is called. Although most dir names are shorter than 1 LCD line (24 chars)
// in practice.
void DisplayDirName (void)
{
if (strncmp_P((u08*)&FINDFILE_RET_NAME[1], PSTR(".. "), 8)==0)
strcpy_P((u08*)&FINDFILE_RET_NAME[1], PSTR("Up One Directory Level"));
else if (strncmp_P((u08*)&FINDFILE_RET_NAME[1], PSTR(". "), 8)==0)
strcpy_P((u08*)&FINDFILE_RET_NAME[1], PSTR("Select this Directory"));
else
GetLongFileName(); // get the dir's long filename
FormatFileNameString(0); // format the long name so it looks OK on the LCD
ClearLCDlines(5, 3); // clear lcd lines 5, 6 & 7
PositionLCDcursor(5, 1); // place cursor at start of 5th line
uart1_putwaitstr((u08*)&FINDFILE_RET_NAME[1]); // print directory name on LCD screen
}
// FindNthDir
//
// This routine is the directory equivilent of FindNthMP3 (in mp3pc.c). It is,
// to a large degree, a copy&paste of FindNthMP3. But there are some differences.
// As there is no FastFind table for directories, that part of FindNthMP3 is
// omitted. Therefore this routine is slower; it starts from the very beginning of
// the current directory and plods all the way though until it finds the Nth
// directory entry in the current directory.
//
// N must be 1 or greater; zero is not permitted. This routine returns zero if the
// directory was found, and non-zero otherwise. Again borrowing from FindNthMP3,
// FINDFILE_RET_CLUS contains the starting cluster number of the Nth directory, and
// FINDFILE_RET_NAME contains its name. FINDFILE_PREV_CLUS contains the cluster number
// for the previous (N-1) directory; this info is used by GetLongFileName.
//
// This routine has one wierd complexity. It deals with the "special case" of the root
// directory not containing a "." directory entry. So... if we're in the root directory,
// it pretends to return a "." entry if N == 1, and returns a real directory entry if
// N == 2 or greater (in which case it subtracts 1 from N to ensure it doesn't skip the
// first real directory entry). Again, this is only when we're reading out of the root
// directory, and it's to simulate having a "." entry in the root directory (but microsoft
// didn't put one in, making the root dir a special case; every other dir has one.)
// (Root's also missing a ".." dir but we don't care about that.)
//
// Another special case for the root directory: subdirectories pointing back to root with
// their ".." directory report cluster 0, whereas for FAT32 the root cluster is defined as 2.
// So check for & correct that as well (clusters 0 & 1 are basically illegal).
u08 FindNthDir (u16 N)
{
u16 NN, dircount;
u08 i, firstchar, attr;
if (N==0)
return 1; // error if we're asked for zero'th file
// deal with the root directory special case of the missing "." directory
if (CURRENT_DIRCL==2) { // if we're in the root directory...
if (N==1) {
FakeRootDotDir(); // if we're asked for the first directory in the root dir
return 0; // then return a faked "." entry
}
else
N--; // if not first root dir requested, dec N & continue normally
}
NN = N-1; // Want to know the number of the (N-1)th file unless
if (NN == 0) NN = 1; // that is the zero'th (a non-existent) file
FeedSTcodec_Command = FSC_Cmd_Stop; // ensure ST codec not trying to read MP3 data Q
// Ensure StreamFileC stopped
STREAMFILE_CMD = StreamFile_Cmd_Stop; // command StreamFileC to STOP
StreamFileC();
while (STREAMFILE_ST!=StreamFile_St_Idle) StreamFileC(); // wait until StreamFileC idle
Q_clear_C((u08*)&MP3DATAQ[0]); // Ensure MP3dataQ empty
FINDFILE_CLUS = CURRENT_DIRCL; // start of current directory cluster number
// Command StreamFileC to stream current directory into the MP3dataQ
STREAMFILE_FILESZ = 0xFFFFFFF; // tell streamfile to stream LOTS of data (we'll stop it later)
STREAMFILE_CLUS = FINDFILE_CLUS; // cluster number streamfile starts streaming 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();
StreamFileC();
// this is the "offset into cluster" counter (512 bytes per sector, hence the multiply by 512)
FINDFILE_OFSET = ((u16)SEC_PER_CLUS)<<9;
// Loop until we've counted through the required number of file records
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -