From dc5b58312ef84b23596f062498ba39f7ccc6caac Mon Sep 17 00:00:00 2001 From: ikari Date: Tue, 8 Feb 2011 01:07:47 +0100 Subject: [PATCH] firmware: MSU1 support --- src/msu1.c | 250 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/msu1.h | 14 +++ 2 files changed, 264 insertions(+) create mode 100644 src/msu1.c create mode 100644 src/msu1.h diff --git a/src/msu1.c b/src/msu1.c new file mode 100644 index 0000000..87e6dbb --- /dev/null +++ b/src/msu1.c @@ -0,0 +1,250 @@ +#include +#include "config.h" +#include "uart.h" +#include "ff.h" +#include "diskio.h" +#include "spi.h" +#include "fpga_spi.h" +#include "cli.h" +#include "fileops.h" +#include "msu1.h" +#include "snes.h" +#include "timer.h" + +int msu1_check_reset(void) { + static tick_t rising_ticks; + + static uint8_t resbutton=0, resbutton_prev=0; + 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; + } + } + resbutton_prev = resbutton; + return 0; +} + +int msu1_entrycheck_and_loop() { +/* MSU1 STUFF, GET ME OUTTA HERE */ + FIL durr; +// open MSU file + strcpy((char*)file_buf, (char*)file_lfn); + strcpy(strrchr((char*)file_buf, (int)'.'), ".msu"); + printf("MSU datafile: %s\n", file_buf); + if(f_open(&durr, (const TCHAR*)file_buf, FA_READ) != FR_OK) { + printf("MSU datafile not found\n"); + return 0; + } + UINT bytes_read = 1024; + UINT bytes_read2 = 1; + FRESULT res; + set_dac_vol(0x00); + spi_set_speed(SSP_CLK_DIVISOR_FAST); + 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; + + 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(&durr, 0L); + ff_sd_offload=1; + sd_offload_tgt=2; + f_read(&durr, file_buf, 16384, &bytes_read2); + + set_dac_addr(dac_addr); + dac_pause(); + dac_reset(); +/* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */ + while(1){ + cli_entrycheck(); + fpga_status_now = fpga_status(); + + /* Data buffer refill */ + if((fpga_status_now & 0x2000) != (fpga_status_prev & 0x2000)) { + 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; + } else { + 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(&durr, 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); + } + + /* Audio buffer refill */ + if((fpga_status_now & 0x4000) != (fpga_status_prev & 0x4000)) { + if(fpga_status_now & 0x4000) { + dac_addr = 0; + } else { + 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); + } + + if(fpga_status_now & 0x0020) { + char suffix[11]; + + /* get trackno */ + msu_track = get_msu_track(); + printf("Audio requested! Track=%d\n", msu_track); + + /* open file */ + 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); + printf("filename: %s\n", file_buf); + f_open(&file_handle, (const TCHAR*)file_buf, FA_READ); + f_lseek(&file_handle, 4L); + f_read(&file_handle, &msu_loop_point, 4, &bytes_read); + 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) { + /* get address */ + msu_offset=get_msu_offset(); + 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))) { + 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(&durr, 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(&durr, 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(&durr, 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(&durr, 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 & 0x0004) { + msu_repeat = 1; + set_msu_status(0x04, 0x01); /* set bit 2, reset bit 0 */ + printf("Repeat set!\n"); + } else { + msu_repeat = 0; + set_msu_status(0x00, 0x05); /* set no bits, reset bit 0+2 */ + printf("Repeat clear!\n"); + } + + if(fpga_status_now & 0x0002) { + printf("PLAY!\n"); + set_msu_status(0x02, 0x01); /* set bit 0, reset bit 1 */ + dac_play(); + } else { + 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) { + ff_sd_offload=0; + sd_offload=0; + if(msu_repeat) { + 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); + } else { + set_msu_status(0x00, 0x02); /* clear play bit */ + } + bytes_read = MSU_DAC_BUFSIZE; + } + if(msu1_check_reset()) { + f_close(&durr); + f_close(&file_handle); + spi_set_speed(SSP_CLK_DIVISOR_FPGA_SLOW); + return 1; + } + } +} +/* END OF MSU1 STUFF */ diff --git a/src/msu1.h b/src/msu1.h new file mode 100644 index 0000000..6646e2c --- /dev/null +++ b/src/msu1.h @@ -0,0 +1,14 @@ +#ifndef MSU1_H +#define MSU1_H + +#ifdef DEBUG_MSU1 +#define DBG_MSU1 +#else +#define DBG_MSU1 while(0) +#endif + +#define MSU_DAC_BUFSIZE (2048) + +int msu1_entrycheck_and_loop(void); + +#endif