msu1.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #include <string.h>
  2. #include "config.h"
  3. #include "uart.h"
  4. #include "ff.h"
  5. #include "diskio.h"
  6. #include "spi.h"
  7. #include "fpga_spi.h"
  8. #include "cli.h"
  9. #include "fileops.h"
  10. #include "msu1.h"
  11. #include "snes.h"
  12. #include "timer.h"
  13. #include "smc.h"
  14. FIL msufile;
  15. DWORD msu_cltbl[CLTBL_SIZE] IN_AHBRAM;
  16. DWORD pcm_cltbl[CLTBL_SIZE] IN_AHBRAM;
  17. extern snes_romprops_t romprops;
  18. int msu1_check_reset(void) {
  19. static tick_t rising_ticks;
  20. static uint8_t resbutton=0, resbutton_prev=0;
  21. resbutton = get_snes_reset();
  22. if(resbutton && !resbutton_prev) { /* push */
  23. rising_ticks = getticks();
  24. } else if(resbutton && resbutton_prev) { /* hold */
  25. if(getticks() > rising_ticks + 99) {
  26. return 1;
  27. }
  28. }
  29. resbutton_prev = resbutton;
  30. return 0;
  31. }
  32. int msu1_check(uint8_t* filename) {
  33. /* open MSU file */
  34. strcpy((char*)file_buf, (char*)filename);
  35. strcpy(strrchr((char*)file_buf, (int)'.'), ".msu");
  36. printf("MSU datafile: %s\n", file_buf);
  37. if(f_open(&msufile, (const TCHAR*)file_buf, FA_READ) != FR_OK) {
  38. printf("MSU datafile not found\n");
  39. return 0;
  40. }
  41. msufile.cltbl = msu_cltbl;
  42. msu_cltbl[0] = CLTBL_SIZE;
  43. if(f_lseek(&msufile, CREATE_LINKMAP)) {
  44. printf("Error creating FF linkmap for MSU file!\n");
  45. }
  46. romprops.fpga_features |= FEAT_MSU1;
  47. return 1;
  48. }
  49. int msu1_loop() {
  50. /* it is assumed that the MSU file is already opened by calling msu1_check(). */
  51. UINT bytes_read = 1024;
  52. UINT bytes_read2 = 1;
  53. FRESULT res;
  54. set_dac_vol(0x00);
  55. while(fpga_status() & 0x4000);
  56. uint16_t fpga_status_prev = fpga_status();
  57. uint16_t fpga_status_now = fpga_status();
  58. uint16_t dac_addr = 0;
  59. uint16_t msu_addr = 0;
  60. uint8_t msu_repeat = 0;
  61. uint16_t msu_track = 0;
  62. uint32_t msu_offset = 0;
  63. uint32_t msu_loop_point = 0;
  64. uint32_t msu_page1_start = 0x0000;
  65. uint32_t msu_page2_start = 0x2000;
  66. uint32_t msu_page_size = 0x2000;
  67. set_msu_addr(0x0);
  68. msu_reset(0x0);
  69. ff_sd_offload=1;
  70. sd_offload_tgt=2;
  71. f_lseek(&msufile, 0L);
  72. ff_sd_offload=1;
  73. sd_offload_tgt=2;
  74. f_read(&msufile, file_buf, 16384, &bytes_read2);
  75. set_dac_addr(dac_addr);
  76. dac_pause();
  77. dac_reset();
  78. /* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */
  79. while(1){
  80. cli_entrycheck();
  81. fpga_status_now = fpga_status();
  82. /* Data buffer refill */
  83. if((fpga_status_now & 0x2000) != (fpga_status_prev & 0x2000)) {
  84. DBG_MSU1 printf("data\n");
  85. uint8_t pageno = 0;
  86. if(fpga_status_now & 0x2000) {
  87. msu_addr = 0x0;
  88. msu_page1_start = msu_page2_start + msu_page_size;
  89. pageno = 1;
  90. } else {
  91. msu_addr = 0x2000;
  92. msu_page2_start = msu_page1_start + msu_page_size;
  93. pageno = 2;
  94. }
  95. set_msu_addr(msu_addr);
  96. sd_offload_tgt=2;
  97. ff_sd_offload=1;
  98. res = f_read(&msufile, file_buf, 8192, &bytes_read2);
  99. DBG_MSU1 printf("data buffer refilled. res=%d page1=%08lx page2=%08lx\n", res, msu_page1_start, msu_page2_start);
  100. }
  101. /* Audio buffer refill */
  102. if((fpga_status_now & 0x4000) != (fpga_status_prev & 0x4000)) {
  103. if(fpga_status_now & 0x4000) {
  104. dac_addr = 0;
  105. } else {
  106. dac_addr = MSU_DAC_BUFSIZE/2;
  107. }
  108. set_dac_addr(dac_addr);
  109. sd_offload_tgt=1;
  110. ff_sd_offload=1;
  111. f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE/2, &bytes_read);
  112. }
  113. if(fpga_status_now & 0x0020) {
  114. char suffix[11];
  115. /* get trackno */
  116. msu_track = get_msu_track();
  117. DBG_MSU1 printf("Audio requested! Track=%d\n", msu_track);
  118. /* open file, fill buffer */
  119. f_close(&file_handle);
  120. snprintf(suffix, sizeof(suffix), "-%d.pcm", msu_track);
  121. strcpy((char*)file_buf, (char*)file_lfn);
  122. strcpy(strrchr((char*)file_buf, (int)'.'), suffix);
  123. DBG_MSU1 printf("filename: %s\n", file_buf);
  124. f_open(&file_handle, (const TCHAR*)file_buf, FA_READ);
  125. file_handle.cltbl = pcm_cltbl;
  126. pcm_cltbl[0] = CLTBL_SIZE;
  127. f_lseek(&file_handle, CREATE_LINKMAP);
  128. f_lseek(&file_handle, 4L);
  129. f_read(&file_handle, &msu_loop_point, 4, &bytes_read);
  130. DBG_MSU1 printf("loop point: %ld samples\n", msu_loop_point);
  131. ff_sd_offload=1;
  132. sd_offload_tgt=1;
  133. f_lseek(&file_handle, 8L);
  134. set_dac_addr(0);
  135. dac_pause();
  136. dac_reset();
  137. ff_sd_offload=1;
  138. sd_offload_tgt=1;
  139. f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE, &bytes_read);
  140. /* clear busy bit */
  141. set_msu_status(0x00, 0x20); /* set no bits, reset bit 5 */
  142. }
  143. if(fpga_status_now & 0x0010) {
  144. /* get address */
  145. msu_offset=get_msu_offset();
  146. DBG_MSU1 printf("Data requested! Offset=%08lx page1=%08lx page2=%08lx\n", msu_offset, msu_page1_start, msu_page2_start);
  147. if( ((msu_offset < msu_page1_start)
  148. || (msu_offset >= msu_page1_start + msu_page_size))
  149. && ((msu_offset < msu_page2_start)
  150. || (msu_offset >= msu_page2_start + msu_page_size))) {
  151. DBG_MSU1 printf("offset %08lx out of range (%08lx-%08lx, %08lx-%08lx), reload\n", msu_offset, msu_page1_start,
  152. msu_page1_start+msu_page_size-1, msu_page2_start, msu_page2_start+msu_page_size-1);
  153. /* "cache miss" */
  154. /* fill buffer */
  155. set_msu_addr(0x0);
  156. sd_offload_tgt=2;
  157. ff_sd_offload=1;
  158. res = f_lseek(&msufile, msu_offset);
  159. DBG_MSU1 printf("seek to %08lx, res = %d\n", msu_offset, res);
  160. sd_offload_tgt=2;
  161. ff_sd_offload=1;
  162. res = f_read(&msufile, file_buf, 16384, &bytes_read2);
  163. DBG_MSU1 printf("read res = %d\n", res);
  164. DBG_MSU1 printf("read %d bytes\n", bytes_read2);
  165. msu_reset(0x0);
  166. msu_page1_start = msu_offset;
  167. msu_page2_start = msu_offset + msu_page_size;
  168. } else {
  169. if (msu_offset >= msu_page1_start && msu_offset <= msu_page1_start + msu_page_size) {
  170. msu_reset(0x0000 + msu_offset - msu_page1_start);
  171. DBG_MSU1 printf("inside page1, new offset: %08lx\n", 0x0000 + msu_offset-msu_page1_start);
  172. if(!(msu_page2_start == msu_page1_start + msu_page_size)) {
  173. set_msu_addr(0x2000);
  174. sd_offload_tgt=2;
  175. ff_sd_offload=1;
  176. f_read(&msufile, file_buf, 8192, &bytes_read2);
  177. DBG_MSU1 printf("next page dirty (was: %08lx), loaded page2 (start now: ", msu_page2_start);
  178. msu_page2_start = msu_page1_start + msu_page_size;
  179. DBG_MSU1 printf("%08lx)\n", msu_page2_start);
  180. }
  181. } else if (msu_offset >= msu_page2_start && msu_offset <= msu_page2_start + msu_page_size) {
  182. DBG_MSU1 printf("inside page2, new offset: %08lx\n", 0x2000 + msu_offset-msu_page2_start);
  183. msu_reset(0x2000 + msu_offset - msu_page2_start);
  184. if(!(msu_page1_start == msu_page2_start + msu_page_size)) {
  185. set_msu_addr(0x0);
  186. sd_offload_tgt=2;
  187. ff_sd_offload=1;
  188. f_read(&msufile, file_buf, 8192, &bytes_read2);
  189. DBG_MSU1 printf("next page dirty (was: %08lx), loaded page1 (start now: ", msu_page1_start);
  190. msu_page1_start = msu_page2_start + msu_page_size;
  191. DBG_MSU1 printf("%08lx)\n", msu_page1_start);
  192. }
  193. } else printf("!!!WATWATWAT!!!\n");
  194. }
  195. /* clear bank bit to mask bank reset artifact */
  196. fpga_status_now &= ~0x2000;
  197. fpga_status_prev &= ~0x2000;
  198. /* clear busy bit */
  199. set_msu_status(0x00, 0x10);
  200. }
  201. if(fpga_status_now & 0x0001) {
  202. if(fpga_status_now & 0x0004) {
  203. msu_repeat = 1;
  204. set_msu_status(0x04, 0x01); /* set bit 2, reset bit 0 */
  205. DBG_MSU1 printf("Repeat set!\n");
  206. } else {
  207. msu_repeat = 0;
  208. set_msu_status(0x00, 0x05); /* set no bits, reset bit 0+2 */
  209. DBG_MSU1 printf("Repeat clear!\n");
  210. }
  211. if(fpga_status_now & 0x0002) {
  212. DBG_MSU1 printf("PLAY!\n");
  213. set_msu_status(0x02, 0x01); /* set bit 0, reset bit 1 */
  214. dac_play();
  215. } else {
  216. DBG_MSU1 printf("PAUSE!\n");
  217. set_msu_status(0x00, 0x03); /* set no bits, reset bit 1+0 */
  218. dac_pause();
  219. }
  220. }
  221. fpga_status_prev = fpga_status_now;
  222. /* handle loop / end */
  223. if(bytes_read < MSU_DAC_BUFSIZE / 2) {
  224. ff_sd_offload=0;
  225. sd_offload=0;
  226. if(msu_repeat) {
  227. DBG_MSU1 printf("loop\n");
  228. ff_sd_offload=1;
  229. sd_offload_tgt=1;
  230. f_lseek(&file_handle, 8L+msu_loop_point*4);
  231. ff_sd_offload=1;
  232. sd_offload_tgt=1;
  233. f_read(&file_handle, file_buf, (MSU_DAC_BUFSIZE / 2) - bytes_read, &bytes_read);
  234. } else {
  235. set_msu_status(0x00, 0x02); /* clear play bit */
  236. dac_pause();
  237. }
  238. bytes_read = MSU_DAC_BUFSIZE;
  239. }
  240. if(msu1_check_reset()) {
  241. f_close(&msufile);
  242. f_close(&file_handle);
  243. return 1;
  244. }
  245. }
  246. }
  247. /* END OF MSU1 STUFF */