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

📄 main.c

📁 A MP3 Player Source Code, Enjoy it!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * MP3 Player, Main Program, http://www.pjrc.com/tech/mp3 * Copyright (c) 2000, PJRC.COM, LLC * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. * * As a specific exception to the GPL, the executable object code built * from this source code may be combined with hardware configuration data * files.  A hardware configuration data file is a set of data that is * transmitted to an intergrated circuit that is not a general purpose * microprocessor or microcontroller, in order to establish its normal * operation.  The process of combining the executable ojbect code built * from the GPL licensed source code with the hardware configuration data * shall be considered an aggregation of another work not based on the * Program.  While the GPL does not restrict use of the program, any * use restriction associated with the hardware configuration data (for * example, that it only be used with particular hardware) shall apply * to the combined file which includes a copy of the hardware configuration * data. * * Contact: paul@pjrc.com */#include "paulmon2.h"#include "as31glue.h"#include "startup.h"#include "printf.h"#include "display.h"#include "parse.h"#include "malloc.h"#include "dirlist.h"#include "playlist.h"#include "sta013.h"#include "stricmp.h"#include "rand.h"#include "id3.h"#include "params.h"#include "treedir.h"#include <8051.h>#include "main.h"char is_state_normal(unsigned char state);unsigned int get_move_count(char direction);void pl_l_next();void pl_l_prev();void pl_next();void pl_prev();char play_blocks(char mp3_fd);void process_resume();void save_resume_info();void dram_test(void);typedef enum {   S_READ_DIR,   S_CACHING,   S_PLAYING_AND_CACHING,   S_PLAYING,   S_FINISH_PLAYING,   S_PAUSED} state_t;// When debugging, waiting for the drive to spin up can be a pain. Use// the parameter editor to set the spin value to Neverbit dummy_bit;volatile xdata unsigned char playing;unsigned int dir_position;idata unsigned char ibuf[4];xdata simm_id current_file;xdata unsigned long current_file_size=0xFFFFFFFF;char resume;play_modes_t play_mode;unsigned int playlist_index,track_index;// We reset this from the sta013 before we start each song.  It's used in display.c// to display elapsed time. -ZSB 12-Aug-2001 3:15 PMunsigned long songStartFrameCount=0;bit update_rand_needed; // Whether timer 3 updates the random seedbit update_mode_needed;bit update_sta013_needed;bit do_id3; // Whether timer 3 scans the ID3 tagvoid main(){	event_t event;	char mp3_fd=-1;	char r;	state_t state;	state_t prior_state;	char caching_step;        xdata struct playlist_list_struct * pl_l_struct;        xdata struct playlist_struct * pl_struct;	xdata struct filelist_struct * fl_struct;	update_rand_needed = 0;	do_id3 = 0;	/* initialize everything */	init_uart();	// from here forward, use print/printf	print("\r\n\r\n\\\[\\A0\\@!0PJRC MP3 Player 0.6.10\\]\r\n\MP3 Player, Version 0.6.10, April 30, 2002\r\n\Copyright (C) 2001, PJRC.COM, LLC\r\n\r\n\Type 'QUIT' to return to the monitor\r\n\r\n");	// indicate EXPERIMENTAL RELEASE on relevant versions	//print("\\[\\B &EXPERIMENTAL DEV RELEASE\\]\r\n");	printf("\\[\\C \\B 'Built %s\\]\r\n", __DATE__);	playback.mode_known = 0;	timer_setup();	param_init();	play_dma_irq_enable();	print("\\[\\B !Waiting for Hard Drive\r\n\r\n\\]\r\n");	while (!ide_init())		;  // keep waiting until init is complete	lcd_setup();	parse_init();	if (detect_filesystem() == 0) pm2_exit();	restore_sta013_settings();	update_sta013_needed = 0;	debug = 0;	print_memory_available();        playlist_init();	print("\\[\\B !Scanning directories    \\]\r\n");	print("Building Playlist(s): Scan All Directories:\r\n");	dirlist_init();	treedir_init(); // must be done after root defined	print_memory_available();	// these print lots of info, but they take a very long	// time to print if the drive has many gigs of files.	//dirlist_show();	print("\\[\\B \"Building M3U playlists  \\]\r\n");	m3u_list_show();	//process_m3u();    // playlist_show_all();	// loop until we find a non-empty playlist	// or reach the end of the playlists list	current_playlist = first_playlist;	while(current_playlist != 0) {	  pl_l_struct = addr6(current_playlist);	  if(pl_l_struct->playlist_start==0) {	    current_playlist=pl_l_struct->next;	  } else {	    break;	  }	}	//current_playlist = first_playlist;	//pl_l_struct = addr6(current_playlist);        if(pl_l_struct->playlist_start == 0)          {	    print("\\[\\B \"   - No files found -   \\]\r\n");            print("No files found...\r\n");            pm2_exit();          }        else          {	  current_file = pl_l_struct->playlist_start;          }	dir_position = 0;	restore_rand_settings();	/* This is the code for a simple resume function. Since	   there is no way to set resume to 1 via the display, this	   feature will be off unless explicitly turned on in the	   code. This is just as well, because at the moment it breaks	   if the playlist- or prev buttons are used until they cause 	   a rollover. Im thinking about the best way to resolve this issue. */	resume = param_value[PARAM_RESUME];	//resume=1;	playlist_index=0;	track_index=0;	if(resume) {	    process_resume();	}	play_mode = param_value[PARAM_PLAY_MODE];	if (play_mode == MODE_ALLRAND || play_mode == MODE_DIRRAND) 	{		// Since we always start at the first file of the first playlist,		// we'll always start with the same song regardless of whether		// we've retrieved a random mode from NV storage or not.  The next		// line forces us to jump forward one track on startup if the saved		// mode was random.					//		// NOTE: If the conditions that determine a random state ever		// change (IE in pl_next()), please be		// be sure to update those condtions here.		//		// -ZSB 12-Aug-2001 12:17 AM		// play_abort();		// ide_flush();		pl_next();			} 	else if (play_mode == MODE_PLSTRAND)	{	   // next playlist in playlist random to force a new random playlist	   pl_l_next();	}	update_mode_needed = 0;	playing = 1;	print("\r\nMP3 Player, Begin Playback\r\n");	lcd_change_menu(0);	init_silent_mp3_clip();	lcd_display_id3_init();	/* this infinite loop runs all the actions of the MP3 player */	state = prior_state = S_READ_DIR;	while (1) {		/* first, process any events from the user interface */		parse_serial_input();		event = get_next_event();				switch (event) {		  case E_NOTHING: {			break;		  }		  case E_PLAY_PAUSE: {			  			if (state == S_PAUSED) {				print("Play\r\n");				state = prior_state;				play_resume();				playing = 1;				lcd_change(PARAM_PLAY_MODE);				// lcd_play_pause_change();			} else {				if (is_state_normal(state)) {					print("Pause\r\n");					prior_state = state;					state = S_PAUSED;					play_suspend();					playing = 0;					lcd_change(PARAM_PLAY_MODE);					// lcd_play_pause_change();				} else {					put_back_event(event);				}			}			break;		  }		  case E_NEXT:			if (is_state_normal(state)) {				print("Next File\r\n");				mute_sta013_output();				play_abort();				ide_flush();				pl_next();				play_silent_mp3_clip();				state = S_FINISH_PLAYING;			} else {				put_back_event(event);			}			break;					  case E_PREV:			if (is_state_normal(state)) {				print("Previous File\r\n");				mute_sta013_output();				play_abort();				ide_flush();				pl_prev();				play_silent_mp3_clip();				state = S_FINISH_PLAYING;			} else {				put_back_event(event);			}			break;		   case E_VOL_UP:                        action_vol_up();                        break;	                    case E_VOL_DOWN:                        action_vol_down();                        break;		  case E_NEXT_LIST:			if (is_state_normal(state)) {				print("Next Play List\r\n");				mute_sta013_output();				play_abort();				ide_flush();				pl_l_next();				play_silent_mp3_clip();				state = S_FINISH_PLAYING;			} else {				put_back_event(event);			}			break;					  case E_PREV_LIST:			if (is_state_normal(state)) {				print("Previous Play List\r\n");				mute_sta013_output();				play_abort();				ide_flush();				pl_l_prev();				play_silent_mp3_clip();				state = S_FINISH_PLAYING;			} else {				put_back_event(event);			}			break;		  case E_RANDOM:		        random_mode_next();			lcd_change(PARAM_PLAY_MODE);		    		        break;		  case E_LCD_SCROLL_TIMER:			set_timer(TIMER_LCD_SCROLL, SCROLL_SPEED);			lcd_timer_callback();			if (state == S_PLAYING_AND_CACHING || state == S_PLAYING) {								lcd_screen_dynamic(0);			}			break;		  		  		  case E_PARAM_WRITE_TIMER:			// Any time the various NV parameters are changed, set timer 3			// to a reasonable timeout (like 100 = 10 seconds).  That way,			// if the user is cycling through an option a bunch of times,			// hitting the volume buttons repeatedly, etc., we should			// reduce the number of writes to the flash by only saving			// them every 10 seconds, not for every single keypress.  If			// we lose power within the 10 second timeout, the new			// settings won't be saved, but that's hardly the end of the			// world...   -ZSB 11-Aug-2001 11:39 PM						eparam_write_flash();			if (update_sta013_needed) {				backup_sta013_settings();				update_sta013_needed = 0;			}			if (update_mode_needed) {		        	ibuf[0] = play_mode;		        	write_flash_param(PARAM_PLAY_MODE, ibuf);				update_mode_needed = 0;			}			if (update_rand_needed) {								// First 8				backup_rand_settings();				update_rand_needed = 0;			}			break;		  case E_ID3_UPDATE_TIMER:			if (do_id3) {			  process_id3(mp3_fd, current_file_size);			  do_id3 = 0;			}			break;		  default:			lcd_user_action(event);			break;		}		do_ide_loop(6);		/* and then do the next step to actually play MP3 files */#ifndef NEW_STATE_MACHINE		switch(state) {		  case S_READ_DIR:			pl_l_struct = addr6(current_playlist);			lcd_set_playlistname(pl_l_struct->name);			pl_struct = addr6(current_file);			fl_struct = addr5(pl_struct->fl_rec);			current_file_size = fl_struct->size;			lcd_set_filename(fl_struct->long_name);  // uses addr7			mp3_fd = file_open_by_1st_cluster(fl_struct->cluster);			file_cache(mp3_fd, 0, current_file_size);			state = S_CACHING;			caching_step = 0;			r = SP;			printfd("S_READ_DIR, mp3_fd=%d %x\r\n", mp3_fd, r);			songStartFrameCount = GetFrameCount();			play_blocks(-1);			set_timer(TIMER_LCD_SCROLL, SCROLL_SPEED);			break;		  case S_CACHING:			r = SP;			printfd("S_CACHING, mp3_fd=%d %x\r\n", mp3_fd, r);			r = file_cache_work(mp3_fd);			/* TODO: check return value from file_cache_work */			if (++caching_step > 6) {				file_seek(mp3_fd, 0);				state = S_PLAYING_AND_CACHING;			}						break;		  case S_PLAYING_AND_CACHING:			printfd("S_PLAYING_CACHING, mp3_fd=%d\r\n", mp3_fd);			r = file_cache_work(mp3_fd);			if (r) {				state = S_PLAYING;				if (param_value[PARAM_DISK_SPIN_DELAY] != 0) {				   ide_sleep();				}				do_id3 = 1;				clear_timer(TIMER_ID3_UPDATE);				set_timer(TIMER_ID3_UPDATE, 50);								// process_id3(mp3_fd, current_file_size);				free_fat_memory();			}			/* fall through into S_PLAYING's code */		  case S_PLAYING:			printfd("S_PLAYING\r\n");			if (play_blocks(mp3_fd) != 0) {				pl_next();				play_silent_mp3_clip();				state = S_FINISH_PLAYING;			}			break;		  case S_FINISH_PLAYING:			// Resettings the songStartFrameCount here should			// get us a new count at the start of each song			printfd("S_FINISH_PLAYING, q=\r\n", play_queue_avail());			if (is_play_queue_empty() && is_ide_idle()) {                                lcd_display_id3_init();				file_close(mp3_fd);				current_file_size = 0xFFFFFFFF;				free_fat_memory();				print_memory_available();				if (is_ide_sleeping()) {					ide_hard_reset();					while (!ide_init())						; // wait until init complete				}				state = S_READ_DIR;			}			songStartFrameCount = GetFrameCount();			break;		  case S_PAUSED:			if (prior_state == S_PLAYING_AND_CACHING) {				r = file_cache_work(mp3_fd);				if (r) {					prior_state = S_PLAYING;					if (param_value[PARAM_DISK_SPIN_DELAY] != 0) {					   ide_sleep();					}					do_id3 = 1;					clear_timer(TIMER_ID3_UPDATE);					set_timer(TIMER_ID3_UPDATE, 50);					// process_id3(mp3_fd, current_file_size);					free_fat_memory();				}			 }			break;		  default:					    print("ILLEGAL STATE:");			print_hex16(state);			print_crlf();		}#else //NEW_STATE_MACHINE		// This state machine will control playing data from memory

⌨️ 快捷键说明

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