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

📄 mp3init.c

📁 Frank s MP3 Player Source Files
💻 C
📖 第 1 页 / 共 4 页
字号:


void DisplayReady (void)
/* Simply writes "Ready" on the 3rd line of the LCD display, blanks out 4th line */
{
	UART1_TxCharWaitC(0x5c);
	UART1_TxCharWaitC(0x42);
	UART1_TxCharWaitC(32);
	UART1_TxCharWaitC(34);									/* put cursor on start of 3rd row (row #2) */								/* put cursor on start of 2nd row */
	uart1_putwaitPROGstr(PSTR("Ready                                       "));	/* and display "ready" */
}



void DisplayWait (void)
/* Simply writes "One moment please..." on the 4th line of the LCD display */
/* Used at power-up. */
{
	UART1_TxCharWaitC(0x5c);
	UART1_TxCharWaitC(0x42);
	UART1_TxCharWaitC(32);
	UART1_TxCharWaitC(35);									/* put cursor on start of 4th line (row #3) */								/* put cursor on start of 2nd row */
	uart1_putwaitPROGstr(PSTR("One moment please..."));	    /* and display the string */
}



void DisplayName (void)
// Simply writes MP3 player's name on top line of LCD display
{
	UART1_TxCharWaitC(0x5c);
	UART1_TxCharWaitC(0x42);
	UART1_TxCharWaitC(32);
	UART1_TxCharWaitC(32);	
	uart1_putwaitPROGstr(PSTR("   Frank's MP3 Player"));    /* write string to LCD display */
}



void LED_ON (void)
// turns the AVR LED on
{
	*AVR_DDRB  = *AVR_DDRB | 0x10;						    /* make the LED bit an output */
	*AVR_PORTB = *AVR_PORTB & 0xEF;						    /* and set the bit low */
}



void LED_OFF (void)
// turns the AVR LED off (set PortB bit 4 high)
{
    *AVR_PORTB = *AVR_PORTB | 0x10;				            /* turn front-panel LED off */
	*AVR_DDRB  = *AVR_DDRB | 0x10;						    /* make the LED bit an output */
}



void LCD_LIGHT_ON (void)
// turns the LCD Backlighting on; Port F bit 5 high to switch it on
{
	*AVR_PORTF = *AVR_PORTF | 0x20;						    /* set the LCD backlight bit high */
	*AVR_DDRF  = *AVR_DDRF | 0x20;						    /* make the LCD backlight bit an output */
}


void LCD_LIGHT_OFF (void)
// turns the LCD Backlighting off; Port F bit 5 low to switch it off
{
	*AVR_PORTF = *AVR_PORTF & 0xDF;						    /* set the LCD backlight bit low */
	*AVR_DDRF  = *AVR_DDRF | 0x20;						    /* ensure the LCD backlight bit an output */
}




void CntMP3files (void)
/* This routine may be called at startup to ensure we know the number of MP3 files in the */
/* current directory. At some point this will be extended to support playlists & subdirectories */
/* (maybe!) but not right now. We need to know the number of MP3 files for random mode, and */
/* the FastFind table, to work. */
/* Better to count them once at power-up than interrupt playing if the user selects random */
/* mode and we have to count them then. */
/* FYI, the eeprom count value is zeroed if the user plugs the USB cable in. */
{
    u16     i;

    PositionLCDcursor (2, 1);                           // place cursor at start of second row of display
	uart1_putwaitPROGstr(PSTR("Counting MP3 Files      "));	/* tell user what's going on */
	
	i = CountMP3files();								/* count the files */

	EEPROM_Write(StoreNumFilesL, (u08)(i&0x00ff));		/* write low count byte into eeprom */
	EEPROM_Write(StoreNumFilesH, (u08)(i>>8));			/* write high count bye into eeprom */	

    PositionLCDcursor (2, 1);                           // place cursor at start of second row of display
    PrintASCIIword (i, 1);                              // display ascii number of files on lcd
	uart1_putwaitPROGstr(PSTR(" MP3 files found."));	// followed by some helpful text
}




u16 CountMP3files (void)
// Warning: SLOW. Does not return until completed.
// This routine counts the number of MP3 files in the current directory, 
// without using FindFileC. Hopefully it'll be faster! It uses StreamFileC
// to stream the entire directory into the MP3dataQ, then reads out the files,
// counting the MP3 files as it goes, until the directory ends. 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!
{
    u16     filecount;
    u08     i, firstchar, extm, extp, ext3, attr;

    // 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     = CURRENT_DIRCL;			    // cluster number for start of current directory
    STREAMFILE_QPOINTER = &MP3DATAQ[0];					// point StreamFile to the MP3 Data queue
    STREAMFILE_CMD      = StreamFile_Cmd_Stream;        // command StreamFileC to start streaming
    StreamFileC();    
    StreamFileC();

    filecount = 0;
    // Don't really loop forever -  we'll break out of this while loop with return statements!
    while (1) {
        // Wait until 32 bytes in queue. If StreamFileC goes idle, return.
        while ( Q_HowMuchDataC((u08*)&MP3DATAQ[0]) < 32 ) {
            StreamFileC();
            if ( (STREAMFILE_ST==StreamFile_St_Idle) && (Q_HowMuchDataC((u08*)&MP3DATAQ[0])<32) )
                return filecount;
        }

        // 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 files 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 filecount;
        }
        for (i=7;i;i--)
            Q_read_C((u08*)&MP3DATAQ[0]);               // ignore next 7 characters of the filename
        extm = Q_read_C((u08*)&MP3DATAQ[0]);
        extp = Q_read_C((u08*)&MP3DATAQ[0]);
        ext3 = Q_read_C((u08*)&MP3DATAQ[0]);            // hopefully these 3 are "MP3"
        attr = Q_read_C((u08*)&MP3DATAQ[0]);            // get file attributes
        for (i=20;i;i--)
            Q_read_C((u08*)&MP3DATAQ[0]);               // throwaway remainder of the 32 bytes
        
        // Increment filecount if we've found an MP3 file
        if ( firstchar!=0xE5 && extm=='M' && extp=='P' && ext3=='3' && !(attr&0x1E) )
            filecount++;
    
        // give StreamFileC another chance to run, then loop back for the next directory entry
        StreamFileC();
    }
}



void BuildFastFindTable (void)
// This routine builds the FastFind table, used by FindNthMP3 to greatly accelerate
// the location of the "Nth" MP3 file. Here's how it works:
// - There are NumFFEntries entries in the table. Each entry is 6 bytes: a 2-byte file 
//   number and a 4-byte cluster number.
// - The file number is the number of the first MP3 file in that cluster.
// - The first file number in the table is always 1. 
// This routine makes an "estimate" of the number of MP3 files per entry by dividing the total
// number of files in the directory by NumFFEntries. This is then used to set "target"
// file numbers. We count though the files on the disk, and when the "target" filenumber
// is reached we record in the table the file number of the first MP3 file in the current cluster.
{
    u08     entries, i, firstchar, extm, extp, ext3, attr;
    u16     filecount, filestep, filetarget, firstfile, eepromaddr, clusterbytecount;
    u32     cluster;


    // display message to user on 3rd line of lcd display
    PositionLCDcursor (3, 1);                           // place cursor at start of third row of display
	uart1_putwaitPROGstr(PSTR("Building FastFind table "));	    /* and display the string */

    // general initializations
    eepromaddr = (u16)FFTableStart;                     // eeprom address of start of table
    cluster    = (u32)CURRENT_DIRCL;                    // cluster number for start of current directory
    clusterbytecount = 0;                               // we've read nothing from the current cluster yet
    filetarget = 1;                                     // initial file number target
    filecount  = 0;                                     // no files counted yet
    firstfile  = 0;                                     // this init just to keep compiler happy

    // get number of MP3 files in directory (use filestep variable just 'cause it's free :-)
    filestep = (((u16)EEPROM_ReadC(StoreNumFilesH))<<8) + (u16)EEPROM_ReadC(StoreNumFilesL);

    // if too few MP3 files, don't properly build the table; just fill it with "dummy" data & return
    if (filestep <= 2*NumFFEntries) {
        for (i=0; i<NumFFEntries; i++) {
            EEPROM_Write(eepromaddr++, 1);		
        	EEPROM_Write(eepromaddr++, 0);                      // filenumber = 0x0001
            EEPROM_Write(eepromaddr++, (u08)cluster);
            EEPROM_Write(eepromaddr++, (u08)(cluster>>8));
            EEPROM_Write(eepromaddr++, (u08)(cluster>>16));
            EEPROM_Write(eepromaddr++, (u08)(cluster>>24));     // cluster number is always first cluster
        }
        return;
    }

    // Calculate estimated step between filenumbers: number of files / number of table entries
    filestep = (filestep - 1) / NumFFEntries;

    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

    // 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     = cluster;			            // cluster number for start of current directory
    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();
    StreamFileC();


    // loop until we've written into the table NumFFEntries times
    entries = NumFFEntries;
    while (entries) {
        // if clusterbytecount is zero, we need to read the 4-byte cluster number out of the data Q,
        // and reset the clusterbyte counter. FYI, a multiply by 512 is a left-shift of 9 bits.
        if (clusterbytecount == 0) {
            // wait until 4 bytes in data Q. If StreamFileC goes idle, return
            while ( Q_HowMuchDataC((u08*)&MP3DATAQ[0]) < 4 ) {
                StreamFileC();
                if ( (STREAMFILE_ST==StreamFile_St_Idle) && (Q_HowMuchDataC((u08*)&MP3DATAQ[0])<4) )
                    return;
            }            
            // extract cluster number low-byte first, reset clusterbytecount, save current filecount, and continue along...
            cluster = ((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);
            clusterbytecount = ((u16)SEC_PER_CLUS)<<9;      // number of bytes per cluster
            firstfile = filecount + 1;                      // filenumber for first file in this upcoming cluster
        }

        // Wait until 32 bytes (a directory entry) in queue. If StreamFileC goes idle, return.
        while ( Q_HowMuchDataC((u08*)&MP3DATAQ[0]) < 32 ) {
            StreamFileC();
            if ( (STREAMFILE_ST==StreamFile_St_Idle) && (Q_HowMuchDataC((u08*)&MP3DATAQ[0])<32) )
                return;
        }

        // 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 files 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;
        }
        for (i=7;i;i--)
            Q_read_C((u08*)&MP3DATAQ[0]);                   // ignore next 7 characters of the filename
        extm = Q_read_C((u08*)&MP3DATAQ[0]);
        extp = Q_read_C((u08*)&MP3DATAQ[0]);
        ext3 = Q_read_C((u08*)&MP3DATAQ[0]);                // hopefully these 3 are "MP3"
        attr = Q_read_C((u08*)&MP3DATAQ[0]);                // get file attributes
        for (i=20;i;i--)
            Q_read_C((u08*)&MP3DATAQ[0]);                   // throwaway remainder of the 32 bytes
        
        // Increment filecount if we've found an MP3 file
        if ( firstchar!=0xE5 && extm=='M' && extp=='P' && ext3=='3' && !(attr&0x1E) )
            filecount++;
    
        // decrement cluster byte counter by the 32 bytes we just read out; give StreamFileC another chance to run
        clusterbytecount -= 32;
        StreamFileC();

        // check to see if we've reached our target filecount number, ie, if time to put entry into table
        if (filecount == filetarget) {
             // Fill in table entry. Low bytes first.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -