Firmware: implement MSU1 interface changes
This commit is contained in:
parent
9baa4b7f9f
commit
a9ea821c0d
250
src/msu1.c
250
src/msu1.c
@ -13,25 +13,132 @@
|
|||||||
#include "smc.h"
|
#include "smc.h"
|
||||||
|
|
||||||
FIL msufile;
|
FIL msufile;
|
||||||
|
FRESULT msu_res;
|
||||||
DWORD msu_cltbl[CLTBL_SIZE] IN_AHBRAM;
|
DWORD msu_cltbl[CLTBL_SIZE] IN_AHBRAM;
|
||||||
DWORD pcm_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;
|
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) {
|
int msu1_check_reset(void) {
|
||||||
static tick_t rising_ticks;
|
static tick_t rising_ticks;
|
||||||
|
|
||||||
static uint8_t resbutton=0, resbutton_prev=0;
|
static uint8_t resbutton=0, resbutton_prev=0;
|
||||||
|
int result = MSU_RESET_NONE;
|
||||||
resbutton = get_snes_reset();
|
resbutton = get_snes_reset();
|
||||||
if(resbutton && !resbutton_prev) { /* push */
|
if(resbutton && !resbutton_prev) { /* push */
|
||||||
rising_ticks = getticks();
|
rising_ticks = getticks();
|
||||||
} else if(resbutton && resbutton_prev) { /* hold */
|
} else if(resbutton && resbutton_prev) { /* hold */
|
||||||
if(getticks() > rising_ticks + 99) {
|
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;
|
resbutton_prev = resbutton;
|
||||||
return 0;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int msu1_check(uint8_t* filename) {
|
int msu1_check(uint8_t* filename) {
|
||||||
@ -54,23 +161,29 @@ int msu1_check(uint8_t* filename) {
|
|||||||
|
|
||||||
int msu1_loop() {
|
int msu1_loop() {
|
||||||
/* it is assumed that the MSU file is already opened by calling msu1_check(). */
|
/* 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);
|
set_dac_vol(0x00);
|
||||||
while(fpga_status() & 0x4000);
|
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 dac_addr = 0;
|
||||||
uint16_t msu_addr = 0;
|
uint16_t msu_addr = 0;
|
||||||
uint8_t msu_repeat = 0;
|
uint8_t msu_repeat = 0;
|
||||||
uint16_t msu_track = 0;
|
uint16_t msu_track = 0;
|
||||||
uint32_t msu_offset = 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;
|
/* set_msu_addr(0x0);
|
||||||
uint32_t msu_page2_start = 0x2000;
|
msu_reset(0x0);
|
||||||
uint32_t msu_page_size = 0x2000;
|
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);
|
set_msu_addr(0x0);
|
||||||
msu_reset(0x0);
|
msu_reset(0x0);
|
||||||
@ -79,13 +192,12 @@ int msu1_loop() {
|
|||||||
f_lseek(&msufile, 0L);
|
f_lseek(&msufile, 0L);
|
||||||
ff_sd_offload=1;
|
ff_sd_offload=1;
|
||||||
sd_offload_tgt=2;
|
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);
|
prepare_audio_track(0);
|
||||||
dac_pause();
|
prepare_data(0);
|
||||||
dac_reset();
|
|
||||||
/* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */
|
/* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */
|
||||||
while(1){
|
while((msu_res = msu1_check_reset()) == MSU_RESET_NONE){
|
||||||
cli_entrycheck();
|
cli_entrycheck();
|
||||||
fpga_status_now = fpga_status();
|
fpga_status_now = fpga_status();
|
||||||
|
|
||||||
@ -105,8 +217,8 @@ int msu1_loop() {
|
|||||||
set_msu_addr(msu_addr);
|
set_msu_addr(msu_addr);
|
||||||
sd_offload_tgt=2;
|
sd_offload_tgt=2;
|
||||||
ff_sd_offload=1;
|
ff_sd_offload=1;
|
||||||
res = f_read(&msufile, file_buf, 8192, &bytes_read2);
|
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", res, msu_page1_start, msu_page2_start);
|
DBG_MSU1 printf("data buffer refilled. res=%d page1=%08lx page2=%08lx\n", msu_res, msu_page1_start, msu_page2_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Audio buffer refill */
|
/* Audio buffer refill */
|
||||||
@ -119,101 +231,21 @@ int msu1_loop() {
|
|||||||
set_dac_addr(dac_addr);
|
set_dac_addr(dac_addr);
|
||||||
sd_offload_tgt=1;
|
sd_offload_tgt=1;
|
||||||
ff_sd_offload=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) {
|
if(fpga_status_now & 0x0020) {
|
||||||
char suffix[11];
|
|
||||||
|
|
||||||
/* get trackno */
|
/* get trackno */
|
||||||
msu_track = get_msu_track();
|
msu_track = get_msu_track();
|
||||||
DBG_MSU1 printf("Audio requested! Track=%d\n", msu_track);
|
DBG_MSU1 printf("Audio requested! Track=%d\n", msu_track);
|
||||||
|
|
||||||
/* open file, fill buffer */
|
prepare_audio_track(msu_track);
|
||||||
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 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fpga_status_now & 0x0010) {
|
if(fpga_status_now & 0x0010) {
|
||||||
/* get address */
|
/* get address */
|
||||||
msu_offset=get_msu_offset();
|
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);
|
prepare_data(msu_offset);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fpga_status_now & 0x0001) {
|
if(fpga_status_now & 0x0001) {
|
||||||
@ -241,7 +273,7 @@ int msu1_loop() {
|
|||||||
fpga_status_prev = fpga_status_now;
|
fpga_status_prev = fpga_status_now;
|
||||||
|
|
||||||
/* handle loop / end */
|
/* handle loop / end */
|
||||||
if(bytes_read < MSU_DAC_BUFSIZE / 2) {
|
if(msu_audio_bytes_read < MSU_DAC_BUFSIZE / 2) {
|
||||||
ff_sd_offload=0;
|
ff_sd_offload=0;
|
||||||
sd_offload=0;
|
sd_offload=0;
|
||||||
if(msu_repeat) {
|
if(msu_repeat) {
|
||||||
@ -251,18 +283,22 @@ int msu1_loop() {
|
|||||||
f_lseek(&file_handle, 8L+msu_loop_point*4);
|
f_lseek(&file_handle, 8L+msu_loop_point*4);
|
||||||
ff_sd_offload=1;
|
ff_sd_offload=1;
|
||||||
sd_offload_tgt=1;
|
sd_offload_tgt=1;
|
||||||
f_read(&file_handle, file_buf, (MSU_DAC_BUFSIZE / 2) - bytes_read, &bytes_read);
|
f_read(&file_handle, file_buf, (MSU_DAC_BUFSIZE / 2) - msu_audio_bytes_read, &msu_audio_bytes_read);
|
||||||
} else {
|
} else {
|
||||||
set_msu_status(0x00, 0x02); /* clear play bit */
|
set_msu_status(0x00, 0x02); /* clear play bit */
|
||||||
dac_pause();
|
dac_pause();
|
||||||
}
|
}
|
||||||
bytes_read = MSU_DAC_BUFSIZE;
|
msu_audio_bytes_read = MSU_DAC_BUFSIZE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(msu1_check_reset()) {
|
|
||||||
f_close(&msufile);
|
|
||||||
f_close(&file_handle);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
DBG_MSU1 printf("game\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
/* END OF MSU1 STUFF */
|
/* END OF MSU1 STUFF */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user