📄 mp3menus.c
字号:
// Note that dircount starts at zero, whereas N and NN start at 1.
dircount = 0; // we've found no directories yet
while (dircount < N) {
// If we're at the (N-1)th directory entry, put its directory cluster number in FINDFILE_PREV_CLUS
if (dircount == (NN-1))
FINDFILE_PREV_CLUS = FINDFILE_CLUS;
// if clusterbytecount == numberofbytespercluster, we need to read the 4-byte cluster number out of the data Q,
// and reset the OffsetIntoCluster counter. FYI, a multiply by 512 is a left-shift of 9 bits. StreamFile has
// been putting the cluster numbers of the clusters it's reading from into the Q; we want to remember them.
if (FINDFILE_OFSET == ((u16)SEC_PER_CLUS)<<9) {
// wait until 4 bytes in data Q
while ( Q_HowMuchDataC((u08*)&MP3DATAQ[0]) < 4 ) {
StreamFileC();
if ( (STREAMFILE_ST==StreamFile_St_Idle) && (Q_HowMuchDataC((u08*)&MP3DATAQ[0])<4) )
return 2;
}
// extract cluster number low-byte first, reset OffsetIntoCluster counter, and continue along...
FINDFILE_CLUS = ((u32)Q_read_C((u08*)&MP3DATAQ[0])) + (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<8) + \
+ (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<16) + (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<24);
FINDFILE_OFSET = 0;
}
// Wait until 32 bytes in queue. If StreamFileC goes idle, return with error, because we've run out
// of directory data before we reached the required number of directories. Possibly due to FAT corruption,
// but more likely because we were inadvertently asked for a higher directory number than the number
// of directory entries actually in the current directory.
while ( Q_HowMuchDataC((u08*)&MP3DATAQ[0]) < 32 ) {
StreamFileC();
if ( (STREAMFILE_ST==StreamFile_St_Idle) && (Q_HowMuchDataC((u08*)&MP3DATAQ[0])<32) )
return 4;
}
// We now have 32 bytes in the queue; a directory entry's worth. Read them out of
// the queue, keeping a few of them for later review, discarding the rest. The first 12 bytes in
// the queue are the short filename (8.3) and the file attributes. If the first byte is zero,
// return, also telling StreamFileC to stop, because there are no more entries in this directory.
firstchar = Q_read_C((u08*)&MP3DATAQ[0]); // get first character of filename
if (firstchar == 0x00 ) {
STREAMFILE_CMD = StreamFile_Cmd_Stop; // tell StreamFileC to stop, then
while (STREAMFILE_ST!=StreamFile_St_Idle) StreamFileC(); // wait until it's idle
return 8;
}
// put the 8 characters of the short filename into the filename array
FINDFILE_RET_NAME[0] = 12; // first array element is length
FINDFILE_RET_NAME[1] = firstchar; // save first character of filename
FINDFILE_RET_NAME[2] = Q_read_C((u08*)&MP3DATAQ[0]); // get 2nd character of filename
FINDFILE_RET_NAME[3] = Q_read_C((u08*)&MP3DATAQ[0]); // get 3rd character of filename
FINDFILE_RET_NAME[4] = Q_read_C((u08*)&MP3DATAQ[0]); // get 4th character of filename
FINDFILE_RET_NAME[5] = Q_read_C((u08*)&MP3DATAQ[0]); // get 5th character of filename
FINDFILE_RET_NAME[6] = Q_read_C((u08*)&MP3DATAQ[0]); // get 6th character of filename
FINDFILE_RET_NAME[7] = Q_read_C((u08*)&MP3DATAQ[0]); // get 7th character of filename
FINDFILE_RET_NAME[8] = Q_read_C((u08*)&MP3DATAQ[0]); // get 8th character of filename
FINDFILE_RET_NAME[9] = '.';
FINDFILE_RET_NAME[10] = Q_read_C((u08*)&MP3DATAQ[0]); // get 1st character of extension
FINDFILE_RET_NAME[11] = Q_read_C((u08*)&MP3DATAQ[0]); // get 2nd character of extension
FINDFILE_RET_NAME[12] = Q_read_C((u08*)&MP3DATAQ[0]); // get 3rd character of extension
FINDFILE_RET_NAME[13] = 0; // null-terminate file name array
attr = Q_read_C((u08*)&MP3DATAQ[0]); // get file attributes
for (i=8;i;i--)
Q_read_C((u08*)&MP3DATAQ[0]); // throwaway next 8 bytes in directory structure
// get the 32-bit starting cluster number for (what is hopefully a) directory (the high 2 bytes)
FINDFILE_RET_CLUS = (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<16) + (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<24);
// throw away the time & date of the last save
for (i=4;i;i--)
Q_read_C((u08*)&MP3DATAQ[0]); // toss the 4 bytes of time & date saved
// get the 32-bit starting cluster number for (what is hopefully a) directory (the low 2 bytes)
FINDFILE_RET_CLUS += (((u32)Q_read_C((u08*)&MP3DATAQ[0]))) + (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<8);
// throw away the 32-bit file size - for directories it's set to zero anyway
for (i=4;i;i--)
Q_read_C((u08*)&MP3DATAQ[0]); // toss 4 byte filesize
// Increment dircount if we've found a directory entry
if ( firstchar!=0xE5 && (attr&0x10) )
dircount++;
// increment OffsetIntoCluster by the number of bytes we've just read
FINDFILE_OFSET += 32;
// give StreamFileC another chance to run, then loop back for the next directory entry
StreamFileC();
}
STREAMFILE_CMD = StreamFile_Cmd_Stop; // command StreamFileC to STOP; we're all done now
// deal with the root dir special case (dirs pointing back to root return cluster 0 instead of the correct 2)
if (FINDFILE_RET_CLUS==0) FINDFILE_RET_CLUS = 2;
if (FINDFILE_PREV_CLUS==0) FINDFILE_PREV_CLUS = 2;
return 0;
}
// FakeRootDotDir
//
// Let me tell you about the dumb things microsoft does (or this this case, doesn't do...)
// For some reason, uS in their infinite wisdom decreed there would be no "." directory in the FAT32 root
// directory. Thereby making the root directory a special case. That sucks. The purpose of this routine is to
// fake having a "." directory. It configures the information (ie global variables) that FindNthDir() would
// do, if it were called on a "." directory in the root directory. It's just a big pretender.
// (The only things that truely count in here are FINDFILE_RET_CLUS and the name string.)
void FakeRootDotDir (void)
{
FINDFILE_RET_CLUS = 2; // root directory commences at cluster 2 for FAT32
FINDFILE_PREV_CLUS = 2;
strcpy_P((u08*)&FINDFILE_RET_NAME[1], PSTR(". . ")); // dir name is "."
FINDFILE_RET_NAME[0] = 12; // length byte at start of string
FINDFILE_OFSET = 32; // we'd only be one directory entry worth into the directory
}
// GetCurrentDirName
//
// This routine determines the name of the directory we're currently in. It returns that name in the
// FINDFILE_RET_NAME[] string.
//
// It manages this trick by returning "root" if we're in the root directory. If not, it finds the name
// by (1) finding the ".." dir entry in the current dir (2) changing dir to that (ie it goes up one dir
// level) (3) finding the dir entry in that parent directory which contains the cluster number as our
// directory of interest, and returning its name. In the process it messes up all of the FINDFILE
// global variables, but it does restore CURRENT_DIRCL before it returns.
void GetCurrentDirName (void)
{
u32 CurrentDirClCopy;
u16 dircount;
// deal with being in the root directory; the easy case
if (CURRENT_DIRCL==2) {
strcpy_P((u08*)&FINDFILE_RET_NAME[1], PSTR("Root Directory")); // dir name is root
return;
}
// Otherwise execute here, we have to change dir into our parent directory
CurrentDirClCopy = CURRENT_DIRCL; // keep this for restoration at the end
FindNthDir(2); // ".." is always second dir
CURRENT_DIRCL = FINDFILE_RET_CLUS; // directory starting cluster is now changed to parent
// Now search through parent dirs until we find the dir cluster number of interest
dircount = 1;
do
FindNthDir(dircount++);
while (FINDFILE_RET_CLUS != CurrentDirClCopy);
// We've found the dir entry of interest; get the full name, clean up & exit
GetLongFileName(); // get the dir's long filename
CURRENT_DIRCL = CurrentDirClCopy; // change back to dir where we started from
}
/******************************************************************************
LearnRemoteControl
This Menu-accessible routine allows the user to train the MP3 player to
learn IR remote control codes. So that a variety of different IR remote
controls can be used with this player.
This routine displays a menu of player functions (play, stop, next, etc)
and allows the user to select which one to train for. Then it calls the
training routine which actually performs the reception, analysis & storing
(in eeprom) of the received IR signal for the actual training.
******************************************************************************/
void LearnRemoteControl (void)
{
PGM_VOID_P FnArrayPtr; // used to point to current mp3 player function array
u08 trainon; // flag used to indicate training to continue
trainon = 1;
while (trainon) { // outer loop of "do you want to train another?"
// Display something helpful at the top of the LCD display
PositionLCDcursor(1, 1);
uart1_putwaitPROGstr(PSTR("Choose function to train Up / Down / Select "));
// Make FnArrayPtr point to a function structure (any one will do)
FnArrayPtr = (PGM_VOID_P)&f_array[0];
// Display the name of the first menu item (first move cursor to start of 4th line)
PositionLCDcursor(4, 1);
uart1_putwaitPROGstr((u08*)pgm_read_word(FnArrayPtr+IRFuncString));
while (ButtonPress != BUT_MENUSEL) { // remain in this loop until a menu function has been selected
switch (ButtonPress) {
case BUT_ONOFF:
ButtonPress = 0;
SwitchOff(); /* switch the player off - this routine never returns */
break;
case BUT_UP:
ButtonPress = 0; // clear out the button press so we don't do this again
// clear out the old menu name on the LCD display
ClearLCDlines(4, 2);
// Point to previous menu record (ie previous in the linked list)
FnArrayPtr = (PGM_VOID_P)pgm_read_word(FnArrayPtr+IRPrevFunc);
// Display the name of our new menu item (first move cursor to start of 4th line)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -