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

📄 main.c

📁 一款MP3 Player Firmware 的原代码,非常有参考价值
💻 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"// this define could be moved to a header which// contains "customization" compilation options#define CDPLAYER_STYLE_PREVvoid init_current_list_and_file(void);char is_state_normal(unsigned char state);char play_blocks(char mp3_fd);void disk_spin_down_timer();void disk_spin_up_timer();void save_playlist_state(void);void begin_simple_timeout(void);unsigned char simple_timeout(unsigned int ticks);void reboot(void);typedef enum {   S_READ_DIR,   S_CACHING,   S_PLAYING_AND_CACHING,   S_PLAYING,   S_FINISH_PLAYING,   S_PAUSED} state_t;xdata simm_id /* playlist_t */ current_file;xdata simm_id /* playlist_t */ e_play_selected_file;// 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;idata unsigned char ibuf[4];xdata unsigned long current_file_size=0xFFFFFFFF;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_sta013_needed;bit update_playlist_state_needed;bit update_mode_needed;bit update_rand_seed_needed;bit timer_spin_down_mode;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;	filelist_t * fl_struct;    unsigned int trackCounter = 0;	debug = 0;	do_id3 = 0;	/* initialize everything */	init_uart();	// from here forward, use print/printf	init_malloc();	print("\r\n\r\n\\\[\\A0\\@!0PJRC MP3 Player 0.6.90\\]\r\n\MP3 Player, Version 0.6.90, July 27, 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();	restore_rand_settings();	print("\\[\\B !Waiting for Hard Drive\r\n\r\n\\]\r\n");	begin_simple_timeout();	while (!ide_init()) {		if (simple_timeout(600)) reboot();		// keep waiting until init is complete	}	tweak_rand_seed();	parse_init();	// clear the dev release and build date lines before        // displaying partitions	print("\\L&\\L'\r\n");	if (detect_filesystem() == 0) pm2_exit();	// would be nice if disks with mutliple FAT32 partitions        // displayed a menu asking which partition to use+	//	// -- Please do not halt the startup process with an	// interactive menu!  Use a NV param and default to the	// first FAT32 partition if it matches none of them.	// The user can choose the partition from Tom's nice	// param menu (that already exists), and no matter what	// happens the player never should pause and wait for	// user input during startup.  It should always begin	// playing if it can.	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_purge_empty();	//playlist_show_all();	init_current_list_and_file();	play_mode_set(param_value[PARAM_PLAY_MODE]);	// if a random mode, advance to 'next_file' to avoid	// starting at a non-random position	if (play_mode == MODE_ALLRAND || play_mode == MODE_DIRRAND	  || play_mode == MODE_PLSTRAND) {		current_file = next_file(current_file, 0);	}	playing = 1;	print("\r\nMP3 Player, Begin Playback\r\n");	lcd_setup();	//lcd_change_menu(0);	//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) || state == S_CACHING) {					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();				current_file = next_file(current_file, 1);				begin_simple_timeout();				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();#ifdef CDPLAYER_STYLE_PREV				if( get_elapsed_seconds() < 3 )#endif					current_file = prev_file(current_file);				begin_simple_timeout();				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();				current_file = next_playlist(current_file, 1);				begin_simple_timeout();				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();				current_file = prev_playlist(current_file);				begin_simple_timeout();				state = S_FINISH_PLAYING;			} else {				put_back_event(event);			}			break;		  case E_PLAYMODE_TOGGLE:		        play_mode_toggle();			lcd_change(PARAM_PLAY_MODE);		    		        break;		  case E_PLAYMODE_UP:		        play_mode_next();			lcd_change(PARAM_PLAY_MODE);		    		        break;		  case E_PLAYMODE_DOWN:		        play_mode_prev();			lcd_change(PARAM_PLAY_MODE);		    		        break;		  case E_LCD_UPDATE_TIMER:			set_timer(TIMER_LCD_UPDATE, LCD_UPDATE_INTERVAL);			if (state == S_PLAYING_AND_CACHING || state == S_PLAYING) {				lcd_screen_dynamic(0);			}			break;		  		                    case E_DISK_SPIN_TIMER:		        print("Disk Spin timer elapsed\r\n");			// spin down if we are still playing			if (state == S_PLAYING) 			{			   if (timer_spin_down_mode)			   {			      // spin down and start spin up timer			      ide_sleep();			      disk_spin_up_timer();			   }#if 0			   else if (is_ide_sleeping()) 			   {			      // spin up			      ide_hard_reset();			      ide_init();			      ide_init();			      ide_init();			      ide_init();			      set_timer(TIMER_DISK_SPIN, 5);			   }			   else if (!ide_init())			   {			      ide_init();			      ide_init();			      ide_init();			      set_timer(TIMER_DISK_SPIN, 5);			   }#endif			}		        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) {				update_sta013_needed = 0;				backup_sta013_settings();			}			if (update_mode_needed) {				save_play_mode();			}			if (update_playlist_state_needed) {				save_playlist_state();			}			if (update_rand_seed_needed) {				backup_rand_settings();			}			break;		  case E_POST_PLAYING_TIMER:			if (do_id3) {			  process_id3(mp3_fd, current_file_size);			  do_id3 = 0;			}			disk_spin_up_timer();			break;					  case E_PLAY_SELECTED:			mute_sta013_output();			play_abort();			ide_flush();			current_file = e_play_selected_file;			play_mode_change(); // req'd to reinit random modes			begin_simple_timeout();			state = S_FINISH_PLAYING;			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:			lcd_set_name(((playlist_list_t *)Addr6(((playlist_t *)Addr6(current_file))->playlist))->name, PLAYLISTNAME);			fl_struct = addr5(((playlist_t *)Addr6(current_file))->fl_rec);			current_file_size = fl_struct->size;			lcd_set_name(fl_struct->long_name, FILENAME);  // uses addr7			mp3_fd = file_open_by_1st_cluster(fl_struct->cluster);			file_cache(mp3_fd, 0, current_file_size);

⌨️ 快捷键说明

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