⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp3menus.c

📁 Frank s MP3 Player Source Files
💻 C
📖 第 1 页 / 共 4 页
字号:
    // 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 + -