From a9ea821c0d3a57fa75fd6d3873062799d55d60c3 Mon Sep 17 00:00:00 2001 From: Maximilian Rehkopf Date: Mon, 9 Jul 2012 02:27:53 +0200 Subject: [PATCH] Firmware: implement MSU1 interface changes --- src/msu1.c | 310 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 173 insertions(+), 137 deletions(-) diff --git a/src/msu1.c b/src/msu1.c index 824e0e3..3207b62 100644 --- a/src/msu1.c +++ b/src/msu1.c @@ -13,25 +13,132 @@ #include "smc.h" FIL msufile; +FRESULT msu_res; DWORD msu_cltbl[CLTBL_SIZE] IN_AHBRAM; DWORD pcm_cltbl[CLTBL_SIZE] IN_AHBRAM; +UINT msu_audio_bytes_read = 1024; +UINT msu_data_bytes_read = 1; extern snes_romprops_t romprops; +uint32_t msu_loop_point = 0; +uint32_t msu_page1_start = 0x0000; +uint32_t msu_page2_start = 0x2000; +uint32_t msu_page_size = 0x2000; +uint16_t fpga_status_prev; +uint16_t fpga_status_now; + +enum msu_reset_state { MSU_RESET_NONE = 0, MSU_RESET_SHORT, MSU_RESET_LONG }; + +void prepare_audio_track(uint16_t msu_track) { + /* open file, fill buffer */ + char suffix[11]; + f_close(&file_handle); + snprintf(suffix, sizeof(suffix), "-%d.pcm", msu_track); + strcpy((char*)file_buf, (char*)file_lfn); + strcpy(strrchr((char*)file_buf, (int)'.'), suffix); + DBG_MSU1 printf("filename: %s\n", file_buf); + if(f_open(&file_handle, (const TCHAR*)file_buf, FA_READ) == FR_OK) { + file_handle.cltbl = pcm_cltbl; + pcm_cltbl[0] = CLTBL_SIZE; + f_lseek(&file_handle, CREATE_LINKMAP); + f_lseek(&file_handle, 4L); + f_read(&file_handle, &msu_loop_point, 4, &msu_audio_bytes_read); + DBG_MSU1 printf("loop point: %ld samples\n", msu_loop_point); + ff_sd_offload=1; + sd_offload_tgt=1; + f_lseek(&file_handle, 8L); + set_dac_addr(0); + dac_pause(); + dac_reset(); + ff_sd_offload=1; + sd_offload_tgt=1; + f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE, &msu_audio_bytes_read); + /* clear busy bit */ + set_msu_status(0x00, 0x28); /* set no bits, reset audio_busy + audio_error */ + } else { + f_close(&file_handle); + set_msu_status(0x08, 0x20); /* reset audio_busy, set audio_error */ + } +} + +void prepare_data(uint32_t msu_offset) { + DBG_MSU1 printf("Data requested! Offset=%08lx page1=%08lx page2=%08lx\n", msu_offset, msu_page1_start, msu_page2_start); + if( ((msu_offset < msu_page1_start) + || (msu_offset >= msu_page1_start + msu_page_size)) + && ((msu_offset < msu_page2_start) + || (msu_offset >= msu_page2_start + msu_page_size))) { + DBG_MSU1 printf("offset %08lx out of range (%08lx-%08lx, %08lx-%08lx), reload\n", msu_offset, msu_page1_start, + msu_page1_start+msu_page_size-1, msu_page2_start, msu_page2_start+msu_page_size-1); + /* "cache miss" */ + /* fill buffer */ + set_msu_addr(0x0); + sd_offload_tgt=2; + ff_sd_offload=1; + msu_res = f_lseek(&msufile, msu_offset); + DBG_MSU1 printf("seek to %08lx, res = %d\n", msu_offset, msu_res); + sd_offload_tgt=2; + ff_sd_offload=1; + msu_res = f_read(&msufile, file_buf, 16384, &msu_data_bytes_read); + DBG_MSU1 printf("read res = %d\n", msu_res); + DBG_MSU1 printf("read %d bytes\n", msu_data_bytes_read); + msu_reset(0x0); + msu_page1_start = msu_offset; + msu_page2_start = msu_offset + msu_page_size; + } else { + if (msu_offset >= msu_page1_start && msu_offset <= msu_page1_start + msu_page_size) { + msu_reset(0x0000 + msu_offset - msu_page1_start); + DBG_MSU1 printf("inside page1, new offset: %08lx\n", 0x0000 + msu_offset-msu_page1_start); + if(!(msu_page2_start == msu_page1_start + msu_page_size)) { + set_msu_addr(0x2000); + sd_offload_tgt=2; + ff_sd_offload=1; + f_read(&msufile, file_buf, 8192, &msu_data_bytes_read); + DBG_MSU1 printf("next page dirty (was: %08lx), loaded page2 (start now: ", msu_page2_start); + msu_page2_start = msu_page1_start + msu_page_size; + DBG_MSU1 printf("%08lx)\n", msu_page2_start); + } + } else if (msu_offset >= msu_page2_start && msu_offset <= msu_page2_start + msu_page_size) { + DBG_MSU1 printf("inside page2, new offset: %08lx\n", 0x2000 + msu_offset-msu_page2_start); + msu_reset(0x2000 + msu_offset - msu_page2_start); + if(!(msu_page1_start == msu_page2_start + msu_page_size)) { + set_msu_addr(0x0); + sd_offload_tgt=2; + ff_sd_offload=1; + f_read(&msufile, file_buf, 8192, &msu_data_bytes_read); + DBG_MSU1 printf("next page dirty (was: %08lx), loaded page1 (start now: ", msu_page1_start); + msu_page1_start = msu_page2_start + msu_page_size; + DBG_MSU1 printf("%08lx)\n", msu_page1_start); + } + } else printf("!!!WATWATWAT!!!\n"); + } + /* clear bank bit to mask bank reset artifact */ + fpga_status_now &= ~0x2000; + fpga_status_prev &= ~0x2000; + /* clear busy bit */ + set_msu_status(0x00, 0x10); +} int msu1_check_reset(void) { static tick_t rising_ticks; static uint8_t resbutton=0, resbutton_prev=0; + int result = MSU_RESET_NONE; resbutton = get_snes_reset(); if(resbutton && !resbutton_prev) { /* push */ rising_ticks = getticks(); } else if(resbutton && resbutton_prev) { /* hold */ if(getticks() > rising_ticks + 99) { - return 1; + result = MSU_RESET_LONG; } + } else if(!resbutton && resbutton_prev) { /* release */ + if(getticks() < rising_ticks + 99) { + result = MSU_RESET_SHORT; + } + } else { + result = MSU_RESET_NONE; } resbutton_prev = resbutton; - return 0; + return result; } int msu1_check(uint8_t* filename) { @@ -54,23 +161,29 @@ int msu1_check(uint8_t* filename) { int msu1_loop() { /* it is assumed that the MSU file is already opened by calling msu1_check(). */ - UINT bytes_read = 1024; - UINT bytes_read2 = 1; - FRESULT res; set_dac_vol(0x00); while(fpga_status() & 0x4000); - uint16_t fpga_status_prev = fpga_status(); - uint16_t fpga_status_now = fpga_status(); uint16_t dac_addr = 0; uint16_t msu_addr = 0; uint8_t msu_repeat = 0; uint16_t msu_track = 0; uint32_t msu_offset = 0; - uint32_t msu_loop_point = 0; + fpga_status_prev = fpga_status(); + fpga_status_now = fpga_status(); + int msu_res; - uint32_t msu_page1_start = 0x0000; - uint32_t msu_page2_start = 0x2000; - uint32_t msu_page_size = 0x2000; +/* set_msu_addr(0x0); + msu_reset(0x0); + ff_sd_offload=1; + sd_offload_tgt=2; + f_lseek(&msufile, 0L); + ff_sd_offload=1; + sd_offload_tgt=2; + f_read(&msufile, file_buf, 16384, &msu_data_bytes_read); +*/ + set_dac_addr(dac_addr); + dac_pause(); + dac_reset(); set_msu_addr(0x0); msu_reset(0x0); @@ -79,13 +192,12 @@ int msu1_loop() { f_lseek(&msufile, 0L); ff_sd_offload=1; sd_offload_tgt=2; - f_read(&msufile, file_buf, 16384, &bytes_read2); + f_read(&msufile, file_buf, 16384, &msu_data_bytes_read); - set_dac_addr(dac_addr); - dac_pause(); - dac_reset(); + prepare_audio_track(0); + prepare_data(0); /* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */ - while(1){ + while((msu_res = msu1_check_reset()) == MSU_RESET_NONE){ cli_entrycheck(); fpga_status_now = fpga_status(); @@ -94,175 +206,99 @@ int msu1_loop() { DBG_MSU1 printf("data\n"); uint8_t pageno = 0; if(fpga_status_now & 0x2000) { - msu_addr = 0x0; - msu_page1_start = msu_page2_start + msu_page_size; - pageno = 1; + msu_addr = 0x0; + msu_page1_start = msu_page2_start + msu_page_size; + pageno = 1; } else { - msu_addr = 0x2000; - msu_page2_start = msu_page1_start + msu_page_size; - pageno = 2; + msu_addr = 0x2000; + msu_page2_start = msu_page1_start + msu_page_size; + pageno = 2; } set_msu_addr(msu_addr); sd_offload_tgt=2; ff_sd_offload=1; - res = f_read(&msufile, file_buf, 8192, &bytes_read2); - DBG_MSU1 printf("data buffer refilled. res=%d page1=%08lx page2=%08lx\n", res, msu_page1_start, msu_page2_start); + msu_res = f_read(&msufile, file_buf, 8192, &msu_data_bytes_read); + DBG_MSU1 printf("data buffer refilled. res=%d page1=%08lx page2=%08lx\n", msu_res, msu_page1_start, msu_page2_start); } /* Audio buffer refill */ if((fpga_status_now & 0x4000) != (fpga_status_prev & 0x4000)) { if(fpga_status_now & 0x4000) { - dac_addr = 0; + dac_addr = 0; } else { - dac_addr = MSU_DAC_BUFSIZE/2; + dac_addr = MSU_DAC_BUFSIZE/2; } set_dac_addr(dac_addr); sd_offload_tgt=1; ff_sd_offload=1; - f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE/2, &bytes_read); + f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE/2, &msu_audio_bytes_read); } if(fpga_status_now & 0x0020) { - char suffix[11]; - /* get trackno */ msu_track = get_msu_track(); DBG_MSU1 printf("Audio requested! Track=%d\n", msu_track); - /* open file, fill buffer */ - f_close(&file_handle); - snprintf(suffix, sizeof(suffix), "-%d.pcm", msu_track); - strcpy((char*)file_buf, (char*)file_lfn); - strcpy(strrchr((char*)file_buf, (int)'.'), suffix); - DBG_MSU1 printf("filename: %s\n", file_buf); - f_open(&file_handle, (const TCHAR*)file_buf, FA_READ); - file_handle.cltbl = pcm_cltbl; - pcm_cltbl[0] = CLTBL_SIZE; - f_lseek(&file_handle, CREATE_LINKMAP); - f_lseek(&file_handle, 4L); - f_read(&file_handle, &msu_loop_point, 4, &bytes_read); - DBG_MSU1 printf("loop point: %ld samples\n", msu_loop_point); - ff_sd_offload=1; - sd_offload_tgt=1; - f_lseek(&file_handle, 8L); - set_dac_addr(0); - dac_pause(); - dac_reset(); - ff_sd_offload=1; - sd_offload_tgt=1; - f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE, &bytes_read); - - /* clear busy bit */ - set_msu_status(0x00, 0x20); /* set no bits, reset bit 5 */ + prepare_audio_track(msu_track); } if(fpga_status_now & 0x0010) { /* get address */ msu_offset=get_msu_offset(); - DBG_MSU1 printf("Data requested! Offset=%08lx page1=%08lx page2=%08lx\n", msu_offset, msu_page1_start, msu_page2_start); - if( ((msu_offset < msu_page1_start) - || (msu_offset >= msu_page1_start + msu_page_size)) - && ((msu_offset < msu_page2_start) - || (msu_offset >= msu_page2_start + msu_page_size))) { - DBG_MSU1 printf("offset %08lx out of range (%08lx-%08lx, %08lx-%08lx), reload\n", msu_offset, msu_page1_start, - msu_page1_start+msu_page_size-1, msu_page2_start, msu_page2_start+msu_page_size-1); - /* "cache miss" */ - /* fill buffer */ - set_msu_addr(0x0); - sd_offload_tgt=2; - ff_sd_offload=1; - res = f_lseek(&msufile, msu_offset); - DBG_MSU1 printf("seek to %08lx, res = %d\n", msu_offset, res); - sd_offload_tgt=2; - ff_sd_offload=1; - - res = f_read(&msufile, file_buf, 16384, &bytes_read2); - DBG_MSU1 printf("read res = %d\n", res); - DBG_MSU1 printf("read %d bytes\n", bytes_read2); - msu_reset(0x0); - msu_page1_start = msu_offset; - msu_page2_start = msu_offset + msu_page_size; - } else { - if (msu_offset >= msu_page1_start && msu_offset <= msu_page1_start + msu_page_size) { - msu_reset(0x0000 + msu_offset - msu_page1_start); - DBG_MSU1 printf("inside page1, new offset: %08lx\n", 0x0000 + msu_offset-msu_page1_start); - if(!(msu_page2_start == msu_page1_start + msu_page_size)) { - set_msu_addr(0x2000); - sd_offload_tgt=2; - ff_sd_offload=1; - f_read(&msufile, file_buf, 8192, &bytes_read2); - DBG_MSU1 printf("next page dirty (was: %08lx), loaded page2 (start now: ", msu_page2_start); - msu_page2_start = msu_page1_start + msu_page_size; - DBG_MSU1 printf("%08lx)\n", msu_page2_start); - } - } else if (msu_offset >= msu_page2_start && msu_offset <= msu_page2_start + msu_page_size) { - DBG_MSU1 printf("inside page2, new offset: %08lx\n", 0x2000 + msu_offset-msu_page2_start); - msu_reset(0x2000 + msu_offset - msu_page2_start); - if(!(msu_page1_start == msu_page2_start + msu_page_size)) { - set_msu_addr(0x0); - sd_offload_tgt=2; - ff_sd_offload=1; - f_read(&msufile, file_buf, 8192, &bytes_read2); - DBG_MSU1 printf("next page dirty (was: %08lx), loaded page1 (start now: ", msu_page1_start); - msu_page1_start = msu_page2_start + msu_page_size; - DBG_MSU1 printf("%08lx)\n", msu_page1_start); - } - } else printf("!!!WATWATWAT!!!\n"); - } - /* clear bank bit to mask bank reset artifact */ - fpga_status_now &= ~0x2000; - fpga_status_prev &= ~0x2000; - /* clear busy bit */ - set_msu_status(0x00, 0x10); + prepare_data(msu_offset); } if(fpga_status_now & 0x0001) { if(fpga_status_now & 0x0004) { - msu_repeat = 1; - set_msu_status(0x04, 0x01); /* set bit 2, reset bit 0 */ - DBG_MSU1 printf("Repeat set!\n"); + msu_repeat = 1; + set_msu_status(0x04, 0x01); /* set bit 2, reset bit 0 */ + DBG_MSU1 printf("Repeat set!\n"); } else { - msu_repeat = 0; - set_msu_status(0x00, 0x05); /* set no bits, reset bit 0+2 */ - DBG_MSU1 printf("Repeat clear!\n"); + msu_repeat = 0; + set_msu_status(0x00, 0x05); /* set no bits, reset bit 0+2 */ + DBG_MSU1 printf("Repeat clear!\n"); } if(fpga_status_now & 0x0002) { - DBG_MSU1 printf("PLAY!\n"); - set_msu_status(0x02, 0x01); /* set bit 0, reset bit 1 */ - dac_play(); + DBG_MSU1 printf("PLAY!\n"); + set_msu_status(0x02, 0x01); /* set bit 0, reset bit 1 */ + dac_play(); } else { - DBG_MSU1 printf("PAUSE!\n"); - set_msu_status(0x00, 0x03); /* set no bits, reset bit 1+0 */ - dac_pause(); + DBG_MSU1 printf("PAUSE!\n"); + set_msu_status(0x00, 0x03); /* set no bits, reset bit 1+0 */ + dac_pause(); } } fpga_status_prev = fpga_status_now; /* handle loop / end */ - if(bytes_read < MSU_DAC_BUFSIZE / 2) { + if(msu_audio_bytes_read < MSU_DAC_BUFSIZE / 2) { ff_sd_offload=0; sd_offload=0; if(msu_repeat) { - DBG_MSU1 printf("loop\n"); - ff_sd_offload=1; - sd_offload_tgt=1; - f_lseek(&file_handle, 8L+msu_loop_point*4); - ff_sd_offload=1; - sd_offload_tgt=1; - f_read(&file_handle, file_buf, (MSU_DAC_BUFSIZE / 2) - bytes_read, &bytes_read); + DBG_MSU1 printf("loop\n"); + ff_sd_offload=1; + sd_offload_tgt=1; + f_lseek(&file_handle, 8L+msu_loop_point*4); + ff_sd_offload=1; + sd_offload_tgt=1; + f_read(&file_handle, file_buf, (MSU_DAC_BUFSIZE / 2) - msu_audio_bytes_read, &msu_audio_bytes_read); } else { - set_msu_status(0x00, 0x02); /* clear play bit */ - dac_pause(); + set_msu_status(0x00, 0x02); /* clear play bit */ + dac_pause(); } - bytes_read = MSU_DAC_BUFSIZE; - } - if(msu1_check_reset()) { - f_close(&msufile); - f_close(&file_handle); - return 1; + msu_audio_bytes_read = MSU_DAC_BUFSIZE; } } + f_close(&file_handle); + DBG_MSU1 printf("Reset "); + if(msu_res == MSU_RESET_LONG) { + f_close(&msufile); + DBG_MSU1 printf("to menu\n"); + return 1; + } + DBG_MSU1 printf("game\n"); + return 0; } /* END OF MSU1 STUFF */