📄 main.c
字号:
state = S_CACHING; caching_step = 0; r = SP; printfd("S_READ_DIR, mp3_fd=%d %x\r\n", mp3_fd, r); songStartFrameCount = GetFrameCount(); playback.mode_known = 0; play_blocks(-1); set_timer(TIMER_LCD_UPDATE, LCD_UPDATE_INTERVAL); update_playlist_state_needed = 1; param_restart_write_timer(25); trackCounter++; //parse_event_setup(); 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); if (param_value[PARAM_STARTUP_MODE] == STARTUP_MODE_PLAYING || trackCounter != 1) { state = S_PLAYING_AND_CACHING; } else { // generate PAUSE event put_back_event(E_PLAY_PAUSE); } } 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; disk_spin_down_timer(); clear_timer(TIMER_POST_PLAYING); set_timer(TIMER_POST_PLAYING, 20); //out of memory if(r == 2) { //print a message printf("\\[\\B $Buffer Memory Full\\]\r\n"); } do_id3 = 1; // 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) { current_file = next_file(current_file, 0); begin_simple_timeout(); 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(); begin_simple_timeout(); while (!ide_init()) { if (simple_timeout(150)) { reboot(); } } tweak_rand_seed(); } state = S_READ_DIR; } else { if (simple_timeout(900)) { reboot(); } } do_id3 = 0; // songStartFrameCount = GetFrameCount(); break; case S_PAUSED: if (prior_state == S_PLAYING_AND_CACHING || prior_state == S_CACHING) { r = file_cache_work(mp3_fd); if (r) { prior_state = S_PLAYING; disk_spin_down_timer(); do_id3 = 1; clear_timer(TIMER_POST_PLAYING); set_timer(TIMER_POST_PLAYING, 20); // 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 switch (play_state) { case S_START_NEW_FILE: case S_PLAYING_FILE: case S_FINISH_PLAYING_FILE: case S_FINISHED_FILE: case S_PAUSED: break; default: print("Illegal play_state\r\n"); play_state = S_START_NEW_FILE; break; } // And this separate state machine will be responsible for // disk access. The idea is to be able to do various things // with the disk drive independent of what the current state // of the playback might happen to be. switch (disk_state) { case S_DRIVE_INACTIVE: if (disk_activity_needed) { // TODO && sleep not pending ide_hard_reset(); disk_time_mark = clock_tick(); disk_state = S_WAIT_DRIVE_READY; } break; case S_WAIT_DRIVE_READY: if (ide_init()) { disk_latency = (clock_tick() - disk_time_mark); disk_state = S_CACHING_PRIORITY_1; caching_priority = 1; } else { // TODO, timeout, go back to and try again } break; case S_CACHING: if (highest_priority == NULL) { ide_sleep(); free_fat_memory(); disk_state = S_WAIT_SHUTDOWN; break; } r = file_cache_work(highest_priority->file_desc); if (r == 1) { // finished caching this file highest_priority->priority = 0; highest_priority = highest_priority->next; break; } if (r == 2) { // ran out of memory highest_priority = NULL; } break; case S_WAIT_SHUTDOWN: // TODO, check if drive is actually in sleep mode // and remain in this state until it really is disk_state = S_DRIVE_INACTIVE; break; default: print("Illegal disk_state\r\n"); play_state = S_DRIVE_INACTIVE; break; }#endif //NEW_STATE_MACHINE } pm2_exit();}/* choose "current_file" for initial startup */void init_current_list_and_file(void){ playlist_state_t state; if (first_playlist == 0) { print("\\[\\B \" - No files found - \\]\r\n"); print("No files found...\r\n"); pm2_exit(); } state.byte.list_offset_lsb = param_value[PARAM_PLST_INDEX_LO]; state.byte.list_offset_msb = param_value[PARAM_PLST_INDEX_HI]; state.byte.song_offset_lsb = param_value[PARAM_TRACK_INDEX_LO]; state.byte.song_offset_msb = param_value[PARAM_TRACK_INDEX_HI]; print("resuming playlist state = "); print_hex32(state.whole); print_crlf(); update_playlist_state_needed = 0; current_file = state_to_playlist(state.whole); //current_file = ((playlist_list_t *)Addr6(first_playlist))->playlist_start_sequential;}void save_playlist_state(void){ playlist_state_t state; state.whole = playlist_to_state(Addr7(current_file)); ibuf[0]=state.byte.list_offset_lsb; write_flash_param(PARAM_PLST_INDEX_LO, ibuf); ibuf[0]=state.byte.list_offset_msb; write_flash_param(PARAM_PLST_INDEX_HI, ibuf); ibuf[0]=state.byte.song_offset_lsb; write_flash_param(PARAM_TRACK_INDEX_LO, ibuf); ibuf[0]=state.byte.song_offset_msb; write_flash_param(PARAM_TRACK_INDEX_HI, ibuf); update_playlist_state_needed = 0;}code unsigned int disk_times[EPARAM_DISK_SPIN_COUNT] = { 0, 0xffff, 10, 20, 50, 100, 150, 200, 300, 600, 1200, 3000, 6000,};void disk_spin_down_timer(){ static xdata unsigned int duration; duration = disk_times[param_value[PARAM_DISK_SPIN_DOWN_DELAY]]; printf("Duration is %d\r\n", duration); timer_spin_down_mode = 1; switch(duration) { case 0: // Never - nothing to do break; case 0xffff: // ASAP put_back_event(E_DISK_SPIN_TIMER); break; default: set_timer(TIMER_DISK_SPIN, duration); break; }}// start the spin up timer// // there are two ways we can end up here. At the end of the spin down// timer and at the end of the play started timer. We will only start// the spin up timer if the spin down and play started timers hav// startedvoid disk_spin_up_timer(){#if 0 xdata unsigned int file_remaining_seconds; xdata unsigned int file_length_seconds; // check timer is not running and bitrate is valid if (read_timer(TIMER_DISK_SPIN) != 0 && playback.mode_known != 0) { // wait for spin down or playback timer to elapse return; } // divide by 1024 (bytes to kbytes) & multiply by 8 (bytes to bits) // => shift by 7 bits file_length_seconds = (current_file_size / playback.bitrate) >> 7; file_remaining_seconds = file_length_seconds - (GetFrameCount() * playback.ms_per_frame / 1000); printf("file_remaining_seconds = %d\r\n", file_remaining_seconds); timer_spin_down_mode = 0; switch(disk_times[param_value[PARAM_DISK_SPIN_UP_AHEAD]]) { case 0: // Never - nothing to do break; case 0xffff: // ASAP put_back_event(E_DISK_SPIN_TIMER); break; default: file_remaining_seconds *= 10; file_remaining_seconds -= disk_times[param_value[PARAM_DISK_SPIN_UP_AHEAD]]; printf("spinning up in %d seconds\r\n", file_remaining_seconds/10); set_timer(TIMER_DISK_SPIN, file_remaining_seconds); break; }#endif}char is_state_normal(unsigned char state){ if (state == S_PLAYING || state == S_PLAYING_AND_CACHING || state == S_FINISH_PLAYING) { return 1; } return 0;}#define BLOCK_SIZE 4096/* return 0 if there is more to play, or non-zero if we have played *//* everything or nothing more can play for some reason */char play_blocks(char mp3_fd){ unsigned int block; static unsigned long played_bytes; static unsigned char eof_count; if (mp3_fd == -1) { played_bytes = 0; eof_count = 0; return 1; } if (current_file_size == 0xFFFFFFFF) { print("WARNING: play_blocks called without known file size\r\n"); return 1; } while (play_queue_avail()) { block = file_read_block(mp3_fd); printfd("FRB, r=%x, played=%lx, size=%lx\r\n", block, played_bytes, current_file_size); if (block == 0) { return 0; // not in cache yet } if (block == 0xFFFF) { if (++eof_count > 240) { played_bytes = 0; // end of file (physical on disk) return 1; } else { return 0; // maybe more will be read soon? } } if (current_file_size - played_bytes > BLOCK_SIZE) { play_block(block, BLOCK_SIZE); played_bytes += BLOCK_SIZE; } else { play_block(block, current_file_size - played_bytes); played_bytes = current_file_size; return 1; } } eof_count = 0; return 0;}static unsigned long simple_timout_start_time;void begin_simple_timeout(void){ simple_timout_start_time = clock_tick();}unsigned char simple_timeout(unsigned int ticks){ if ((clock_tick() - simple_timout_start_time) > (unsigned long)ticks) { return 1; } return 0;}void reboot(void){ _asm mov r0, #000001$: mov r1, #000002$: nop ;delay, hopefully to allow any nop ;buffered serial output djnz r1, 00002$ djnz r0, 00001$ clr ea ljmp 0 _endasm;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -