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

📄 mp3pc.c

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