📄 main.c
字号:
/* * 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 + -