preliminary MSU-1 audio support

This commit is contained in:
ikari 2010-12-17 02:58:41 +01:00
parent 6c27daa30b
commit e2e628d6fb
11 changed files with 404 additions and 54 deletions

View File

@ -27,7 +27,7 @@ void clock_init() {
-> FPGA freq = 11289473.7Hz -> FPGA freq = 11289473.7Hz
First, disable and disconnect PLL0. First, disable and disconnect PLL0.
*/ */
clock_disconnect(); // clock_disconnect();
/* PLL is disabled and disconnected. setup PCLK NOW as it cannot be changed /* PLL is disabled and disconnected. setup PCLK NOW as it cannot be changed
reliably with PLL0 connected. reliably with PLL0 connected.

View File

@ -2,6 +2,7 @@
#define _CONFIG_H #define _CONFIG_H
// #define DEBUG_SD // #define DEBUG_SD
// #define DEBUG_IRQ
#define VER "0.0.1(NSFW)" #define VER "0.0.1(NSFW)"
#define IN_AHBRAM __attribute__ ((section(".ahbram"))) #define IN_AHBRAM __attribute__ ((section(".ahbram")))
@ -38,7 +39,7 @@
#define CONFIG_UART_BAUDRATE 921600 #define CONFIG_UART_BAUDRATE 921600
#define CONFIG_UART_DEADLOCKABLE #define CONFIG_UART_DEADLOCKABLE
#define SSP_CLK_DIVISOR_FAST 4 #define SSP_CLK_DIVISOR_FAST 2
#define SSP_CLK_DIVISOR_SLOW 250 #define SSP_CLK_DIVISOR_SLOW 250
#define SSP_CLK_DIVISOR_FPGA_FAST 6 #define SSP_CLK_DIVISOR_FPGA_FAST 6

View File

@ -62,7 +62,10 @@ void disk_init(void);
/* Will be set to DISK_ERROR if any access on the card fails */ /* Will be set to DISK_ERROR if any access on the card fails */
enum diskstates { DISK_CHANGED = 0, DISK_REMOVED, DISK_OK, DISK_ERROR }; enum diskstates { DISK_CHANGED = 0, DISK_REMOVED, DISK_OK, DISK_ERROR };
extern int sd_offload, ff_sd_offload, newcard; extern int sd_offload, ff_sd_offload, sd_offload_tgt, newcard;
extern int sd_offload_partial;
extern uint16_t sd_offload_partial_start;
extern uint16_t sd_offload_partial_end;
extern volatile enum diskstates disk_state; extern volatile enum diskstates disk_state;
/* Disk type - part of the external API except for ATA2! */ /* Disk type - part of the external API except for ATA2! */

View File

@ -87,7 +87,8 @@
#include "ff.h" /* FatFs configurations and declarations */ #include "ff.h" /* FatFs configurations and declarations */
#include "diskio.h" /* Declarations of low level disk I/O functions */ #include "diskio.h" /* Declarations of low level disk I/O functions */
#include "config.h"
#include "uart.h"
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
@ -2013,7 +2014,6 @@ FRESULT f_open (
BYTE *dir; BYTE *dir;
DEF_NAMEBUF; DEF_NAMEBUF;
fp->fs = 0; /* Clear file object */ fp->fs = 0; /* Clear file object */
#if !_FS_READONLY #if !_FS_READONLY
@ -2186,8 +2186,8 @@ FRESULT f_read (
if (fp->fs->wflag && fp->fs->winsect - sect < cc) if (fp->fs->wflag && fp->fs->winsect - sect < cc)
mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs));
#else #else
if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc) if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc){
mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); uart_putc('Y');}
#endif #endif
#endif #endif
rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
@ -2196,27 +2196,45 @@ FRESULT f_read (
#if !_FS_TINY #if !_FS_TINY
#if !_FS_READONLY #if !_FS_READONLY
if (fp->flag & FA__DIRTY) { /* Write sector I/O buffer if needed */ if (fp->flag & FA__DIRTY) { /* Write sector I/O buffer if needed */
printf("DIRTY!?!\n");
if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
ABORT(fp->fs, FR_DISK_ERR); ABORT(fp->fs, FR_DISK_ERR);
fp->flag &= ~FA__DIRTY; fp->flag &= ~FA__DIRTY;
} }
#endif #endif
if (fp->dsect != sect) { /* Fill sector buffer with file data */ if (fp->dsect != sect) { /* Fill sector buffer with file data */
if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) if(!ff_sd_offload) {
ABORT(fp->fs, FR_DISK_ERR); if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK)
ABORT(fp->fs, FR_DISK_ERR);
}
} }
#endif #endif
fp->dsect = sect; fp->dsect = sect;
} }
rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */
if (rcnt > btr) rcnt = btr; if (rcnt > btr) rcnt = btr;
if(!ff_sd_offload) {
#if _FS_TINY #if _FS_TINY
if (move_window(fp->fs, fp->dsect)) /* Move sector window */ if (move_window(fp->fs, fp->dsect)) /* Move sector window */
ABORT(fp->fs, FR_DISK_ERR); ABORT(fp->fs, FR_DISK_ERR);
mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */
#else #else
mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */
// printf("final mem_cpy, rcnt=%d, rbuff-buff=%d\n", rcnt, (void*)rbuff-buff);
} else {
sd_offload_partial_start = fp->fptr % SS(fp->fs);
sd_offload_partial_end = sd_offload_partial_start + rcnt;
// printf("partial dma. sect=%08lx start=%d end=%d\n", fp->dsect, sd_offload_partial_start, sd_offload_partial_end);
/* set start + end */
sd_offload = 1;
sd_offload_partial = 1;
if(disk_read(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) {
sd_offload = 0;
ABORT(fp->fs, FR_DISK_ERR);
}
sd_offload = 0;
#endif #endif
}
} }
ff_sd_offload = 0; ff_sd_offload = 0;
LEAVE_FF(fp->fs, FR_OK); LEAVE_FF(fp->fs, FR_OK);
@ -2356,6 +2374,7 @@ FRESULT f_sync (
res = validate(fp->fs, fp->id); /* Check validity of the object */ res = validate(fp->fs, fp->id); /* Check validity of the object */
if (res == FR_OK) { if (res == FR_OK) {
if (fp->flag & FA__WRITTEN) { /* Has the file been written? */ if (fp->flag & FA__WRITTEN) { /* Has the file been written? */
printf("DIRTY?!?!?!\n");
#if !_FS_TINY /* Write-back dirty buffer */ #if !_FS_TINY /* Write-back dirty buffer */
if (fp->flag & FA__DIRTY) { if (fp->flag & FA__DIRTY) {
if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
@ -2696,8 +2715,14 @@ FRESULT f_lseek (
fp->flag &= ~FA__DIRTY; fp->flag &= ~FA__DIRTY;
} }
#endif #endif
if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) if(!ff_sd_offload) {
ABORT(fp->fs, FR_DISK_ERR); sd_offload_partial=0;
if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK)
ABORT(fp->fs, FR_DISK_ERR);
} else {
sd_offload_partial=1;
sd_offload_partial_start = fp->fptr % SS(fp->fs);
}
#endif #endif
fp->dsect = nsect; fp->dsect = nsect;
} }
@ -2708,7 +2733,7 @@ FRESULT f_lseek (
} }
#endif #endif
} }
ff_sd_offload = 0;
LEAVE_FF(fp->fs, res); LEAVE_FF(fp->fs, res);
} }

View File

@ -29,20 +29,50 @@
cmd param function cmd param function
============================================= =============================================
00 bbhhll set address to 0xbbhhll 0t bbhhll set address to 0xbbhhll
01 bbhhll set SNES input address mask to 0xbbhhll t = target
02 bbhhll set SRAM address mask to 0xbbhhll target: 0 = RAM
1 = MSU Audio buffer
2 = MSU Data buffer
targets 1 & 2 only require 2 address bytes to
be written.
10 bbhhll set SNES input address mask to 0xbbhhll
20 bbhhll set SRAM address mask to 0xbbhhll
3m - set mapper to m 3m - set mapper to m
0=HiROM, 1=LoROM, 2=ExHiROM, 6=SF96, 7=Menu 0=HiROM, 1=LoROM, 2=ExHiROM, 6=SF96, 7=Menu
40 - trigger SD DMA (512b from SD to memory)
80 - read with increment 4s - trigger SD DMA (512b from SD to memory)
81 - read w/o increment s: Bit 2 = partial, Bit 1:0 = target
90 {xx}* write xx with increment target: see above
91 {xx}* write xx w/o increment
Eu - set memory unit (u=0: "ROM"; u=1: SRAM) 60 sssseeee set SD DMA partial transfer start+end
ssss = start offset (msb first)
eeee = end offset (msb first)
80 - read with increment (RAM only)
81 - read w/o increment (RAM only)
90 {xx}* write xx with increment (RAM only)
91 {xx}* write xx w/o increment (RAM only)
E0 ssrr set MSU-1 status register (=FPGA status byte 2)
ss = bits to set in status register (1=set)
rr = bits to reset in status register (1=reset)
E1 - pause DAC
E2 - resume/play DAC
E3 - reset DAC playback pointer (0)
F0 - receive test token (to see if FPGA is alive) F0 - receive test token (to see if FPGA is alive)
F1 - receive status F1 - receive status
F2 - get MSU data address (32bit, MSB first)
F3 - get MSU audio track no. (16bit, MSB first)
F4 - get MSU volume (8bit)
FF {xx]* echo (returns the sent data in the next byte)
*/ */
#include <arm/NXP/LPC17xx/LPC17xx.h> #include <arm/NXP/LPC17xx/LPC17xx.h>
@ -58,6 +88,22 @@ void fpga_spi_init(void) {
spi_init(SPI_SPEED_FPGA_FAST); spi_init(SPI_SPEED_FPGA_FAST);
} }
void set_msu_addr(uint32_t address) {
FPGA_SELECT();
FPGA_TX_BYTE(0x02);
FPGA_TX_BYTE((address>>8)&0xff);
FPGA_TX_BYTE((address)&0xff);
FPGA_DESELECT();
}
void set_dac_addr(uint32_t address) {
FPGA_SELECT();
FPGA_TX_BYTE(0x01);
FPGA_TX_BYTE((address>>8)&0xff);
FPGA_TX_BYTE((address)&0xff);
FPGA_DESELECT();
}
void set_mcu_addr(uint32_t address) { void set_mcu_addr(uint32_t address) {
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x00); FPGA_TX_BYTE(0x00);
@ -69,7 +115,7 @@ void set_mcu_addr(uint32_t address) {
void set_saveram_mask(uint32_t mask) { void set_saveram_mask(uint32_t mask) {
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x02); FPGA_TX_BYTE(0x20);
FPGA_TX_BYTE((mask>>16)&0xff); FPGA_TX_BYTE((mask>>16)&0xff);
FPGA_TX_BYTE((mask>>8)&0xff); FPGA_TX_BYTE((mask>>8)&0xff);
FPGA_TX_BYTE((mask)&0xff); FPGA_TX_BYTE((mask)&0xff);
@ -78,7 +124,7 @@ void set_saveram_mask(uint32_t mask) {
void set_rom_mask(uint32_t mask) { void set_rom_mask(uint32_t mask) {
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x01); FPGA_TX_BYTE(0x10);
FPGA_TX_BYTE((mask>>16)&0xff); FPGA_TX_BYTE((mask>>16)&0xff);
FPGA_TX_BYTE((mask>>8)&0xff); FPGA_TX_BYTE((mask>>8)&0xff);
FPGA_TX_BYTE((mask)&0xff); FPGA_TX_BYTE((mask)&0xff);
@ -100,25 +146,116 @@ uint8_t fpga_test() {
return result; return result;
} }
uint8_t fpga_status() { uint16_t fpga_status() {
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xF1); /* STATUS */ FPGA_TX_BYTE(0xF1); /* STATUS */
FPGA_TX_BYTE(0x00); /* dummy */ FPGA_TX_BYTE(0x00); /* dummy */
uint16_t result = (FPGA_RX_BYTE()) << 8;
result |= FPGA_RX_BYTE();
FPGA_DESELECT();
return result;
}
void fpga_set_sddma_range(uint16_t start, uint16_t end) {
FPGA_SELECT();
FPGA_TX_BYTE(0x60); /* DMA_RANGE */
FPGA_TX_BYTE(start>>8);
FPGA_TX_BYTE(start&0xff);
FPGA_TX_BYTE(end>>8);
FPGA_TX_BYTE(end&0xff);
//if(tgt==1 && (test=FPGA_RX_BYTE()) != 0x41) printf("!!!!!!!!!!!!!!! -%02x- \n", test);
FPGA_DESELECT();
}
void fpga_sddma(uint8_t tgt, uint8_t partial) {
uint32_t test = 0;
uint8_t status = 0;
BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 0;
FPGA_SELECT();
FPGA_TX_BYTE(0x40 | (tgt & 0x3) | ((partial & 1) << 2) ); /* DO DMA */
FPGA_TX_BYTE(0x00); /* dummy for falling DMA_EN edge */
//if(tgt==1 && (test=FPGA_RX_BYTE()) != 0x41) printf("!!!!!!!!!!!!!!! -%02x- \n", test);
FPGA_DESELECT();
FPGA_SELECT();
FPGA_TX_BYTE(0xF1); /* STATUS */
FPGA_TX_BYTE(0x00); /* dummy */
while((status=FPGA_RX_BYTE()) & 0x80) {
FPGA_RX_BYTE(); /* eat the 2nd status byte */
test++;
}
FPGA_DESELECT();
if(test<10)printf("loopy: %ld %02x\n", test, status);
BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1;
}
void set_dac_vol(uint8_t volume) {
FPGA_SELECT();
FPGA_TX_BYTE(0x50);
FPGA_TX_BYTE(volume);
FPGA_TX_BYTE(0x00); /* latch rise */
FPGA_TX_BYTE(0x00); /* latch fall */
FPGA_DESELECT();
}
void dac_play() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe2);
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_DESELECT();
}
void dac_pause() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe1);
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_DESELECT();
}
void dac_reset() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe3);
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_DESELECT();
}
void set_msu_status(uint8_t set, uint8_t reset) {
FPGA_SELECT();
FPGA_TX_BYTE(0xe0);
FPGA_TX_BYTE(set);
FPGA_TX_BYTE(reset);
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_TX_BYTE(0x00); /* latch reset */
FPGA_DESELECT();
}
uint8_t get_msu_volume() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF4); /* MSU_VOLUME */
FPGA_TX_BYTE(0x00); /* dummy */
uint8_t result = FPGA_RX_BYTE(); uint8_t result = FPGA_RX_BYTE();
FPGA_DESELECT(); FPGA_DESELECT();
return result; return result;
} }
void fpga_sd2ram() { uint16_t get_msu_track() {
BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 0;
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x40); /* DO DMA */ FPGA_TX_BYTE(0xF3); /* MSU_TRACK */
FPGA_TX_BYTE(0x00); /* dummy for falling DMA_EN edge */
FPGA_DESELECT();
FPGA_SELECT();
FPGA_TX_BYTE(0xF1); /* STATUS */
FPGA_TX_BYTE(0x00); /* dummy */ FPGA_TX_BYTE(0x00); /* dummy */
while(FPGA_RX_BYTE() & 0x80); uint16_t result = (FPGA_RX_BYTE()) << 8;
result |= FPGA_RX_BYTE();
FPGA_DESELECT(); FPGA_DESELECT();
BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1; return result;
} }
uint32_t get_msu_offset() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF2); /* MSU_OFFSET */
FPGA_TX_BYTE(0x00); /* dummy */
uint32_t result = (FPGA_RX_BYTE()) << 24;
result |= (FPGA_RX_BYTE()) << 16;
result |= (FPGA_RX_BYTE()) << 8;
result |= (FPGA_RX_BYTE());
FPGA_DESELECT();
return result;
}

View File

@ -1,6 +1,6 @@
/* sd2snes - SD card based universal cartridge for the SNES /* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net> Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion uC firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al. Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h. See sdcard.c|h, config.h.
@ -34,7 +34,9 @@
#define FPGA_SS_REG LPC_GPIO0 #define FPGA_SS_REG LPC_GPIO0
#define FPGA_SELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOCLR, FPGA_SS_BIT) = 1;} while (0) #define FPGA_SELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOCLR, FPGA_SS_BIT) = 1;} while (0)
#define FPGA_SELECT_ASYNC() do {BITBAND(FPGA_SS_REG->FIOCLR, FPGA_SS_BIT) = 1;} while (0)
#define FPGA_DESELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOSET, FPGA_SS_BIT) = 1;} while (0) #define FPGA_DESELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOSET, FPGA_SS_BIT) = 1;} while (0)
#define FPGA_DESELECT_ASYNC() do {BITBAND(FPGA_SS_REG->FIOSET, FPGA_SS_BIT) = 1;} while (0)
#define FPGA_TX_SYNC() spi_tx_sync() #define FPGA_TX_SYNC() spi_tx_sync()
#define FPGA_TX_BYTE(x) spi_tx_byte(x) #define FPGA_TX_BYTE(x) spi_tx_byte(x)
@ -48,14 +50,24 @@
void fpga_spi_init(void); void fpga_spi_init(void);
uint8_t fpga_test(void); uint8_t fpga_test(void);
uint8_t fpga_status(void); uint16_t fpga_status(void);
void spi_fpga(void); void spi_fpga(void);
void spi_sd(void); void spi_sd(void);
void spi_none(void); void spi_none(void);
void set_mcu_addr(uint32_t); void set_mcu_addr(uint32_t);
void set_dac_addr(uint32_t);
void set_dac_vol(uint8_t);
void dac_play(void);
void dac_pause(void);
void dac_reset(void);
void set_msu_addr(uint32_t);
void set_msu_status(uint8_t set, uint8_t reset);
void set_saveram_mask(uint32_t); void set_saveram_mask(uint32_t);
void set_rom_mask(uint32_t); void set_rom_mask(uint32_t);
void set_mapper(uint8_t val); void set_mapper(uint8_t val);
void fpga_sd2ram(void); void fpga_sddma(uint8_t tgt, uint8_t partial);
void fpga_set_sddma_range(uint16_t start, uint16_t end);
uint8_t get_msu_volume(void);
uint16_t get_msu_track(void);
uint32_t get_msu_offset(void);
#endif #endif

View File

@ -30,7 +30,11 @@
int i; int i;
int sd_offload = 0, ff_sd_offload = 0; int sd_offload = 0, ff_sd_offload = 0, sd_offload_tgt = 0;
int sd_offload_partial = 0;
uint16_t sd_offload_partial_start = 0;
uint16_t sd_offload_partial_end = 0;
/* FIXME HACK */ /* FIXME HACK */
volatile enum diskstates disk_state; volatile enum diskstates disk_state;
extern volatile tick_t ticks; extern volatile tick_t ticks;
@ -44,9 +48,8 @@ int main(void) {
/* connect UART3 on P0[25:26] + SSP0 on P0[15:18] SSP1 on P0[6:9] + MAT3.0 on P0[10] */ /* connect UART3 on P0[25:26] + SSP0 on P0[15:18] SSP1 on P0[6:9] + MAT3.0 on P0[10] */
LPC_PINCON->PINSEL1 = BV(18) | BV(19) | BV(20) | BV(21) /* UART3 */ LPC_PINCON->PINSEL1 = BV(18) | BV(19) | BV(20) | BV(21) /* UART3 */
| BV(3) | BV(5); /* SSP0 (FPGA) except SS */ | BV(3) | BV(5); /* SSP0 (FPGA) except SS */
LPC_PINCON->PINSEL0 = BV(31) /* SSP0 */ LPC_PINCON->PINSEL0 = BV(31); /* SSP0 */
/* | BV(13) | BV(15) | BV(17) | BV(19) SSP1 (SD) */ /* | BV(13) | BV(15) | BV(17) | BV(19) SSP1 (SD) */
| BV(20) | BV(21); /* MAT3.0 (FPGA clock) */
/* pull-down CIC data lines */ /* pull-down CIC data lines */
LPC_PINCON->PINMODE3 = BV(18) | BV(19) | BV(20) | BV(21); LPC_PINCON->PINMODE3 = BV(18) | BV(19) | BV(20) | BV(21);
@ -62,6 +65,7 @@ int main(void) {
led_init(); led_init();
/* do this last because the peripheral init()s change PCLK dividers */ /* do this last because the peripheral init()s change PCLK dividers */
clock_init(); clock_init();
LPC_PINCON->PINSEL0 |= BV(20) | BV(21); /* MAT3.0 (FPGA clock) */
led_pwm(); led_pwm();
sdn_init(); sdn_init();
fpga_spi_init(); fpga_spi_init();
@ -76,7 +80,6 @@ led_pwm();
LPC_TIM3->MR0=1; LPC_TIM3->MR0=1;
LPC_TIM3->TCR=1; LPC_TIM3->TCR=1;
fpga_init(); fpga_init();
// fpga_pgm((uint8_t*)"/main.bit.rle");
fpga_rompgm(); fpga_rompgm();
restart: restart:
if(disk_state == DISK_CHANGED) { if(disk_state == DISK_CHANGED) {
@ -121,7 +124,7 @@ restart:
snes_bootprint(" Loading ... \0"); snes_bootprint(" Loading ... \0");
if(get_cic_state() == CIC_PAIR) { if(get_cic_state() == CIC_PAIR) {
printf("PAIR MODE ENGAGED!\n"); printf("PAIR MODE ENGAGED!\n");
cic_pair(CIC_PAL, CIC_PAL); cic_pair(CIC_NTSC, CIC_NTSC);
} }
rdyled(1); rdyled(1);
readled(0); readled(0);
@ -176,6 +179,7 @@ restart:
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR); load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
} }
/* load menu */ /* load menu */
fpga_pgm((uint8_t*)"/main.bit.rle");
uart_putc('('); uart_putc('(');
load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR); load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR);
/* force memory size + mapper */ /* force memory size + mapper */
@ -222,7 +226,7 @@ restart:
} }
set_mcu_ovr(0); set_mcu_ovr(0);
snes_reset(1); snes_reset(1);
delay_ms(1); delay_ms(10);
snes_reset(0); snes_reset(0);
break; break;
case SNES_CMD_SETRTC: case SNES_CMD_SETRTC:
@ -234,8 +238,161 @@ restart:
break; break;
} }
} }
printf("cmd was %x, going to snes main loop\n", cmd); printf("cmd was %x, going to snes main loop\n", cmd);
/* MSU1 STUFF, GET ME OUTTA HERE */
FIL durr;
f_open(&durr, "/SF96SOE.smc", FA_READ);
ff_sd_offload=1;
sd_offload_tgt=2;
f_lseek(&durr, 79L);
set_msu_addr(0);
UINT bytes_read = 1024;
UINT bytes_read2 = 1;
uint16_t volume=0;
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;
uint8_t msu_volume = 0;
uint8_t msu_volupdate = 0;
uint8_t msu_volupdate_cnt = 0;
set_dac_addr(dac_addr);
dac_pause();
dac_reset();
/* audio_start, data_start, volume_start, audio_ctrl[1:0], ctrl_start */
while(1){
fpga_status_now = fpga_status();
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.wav", msu_track);
strcpy((char*)file_buf, (char*)file_lfn);
strcpy(strrchr((char*)file_buf, (int)'.'), suffix);
f_open(&file_handle, (const TCHAR*)file_buf, FA_READ);
ff_sd_offload=1;
sd_offload_tgt=1;
f_lseek(&file_handle, 44L);
ff_sd_offload=1;
sd_offload_tgt=1;
set_dac_addr(0);
dac_pause();
dac_reset();
f_read(&file_handle, file_buf, 2048, &bytes_read);
/* clear busy bit */
set_msu_status(0x00, 0x20); /* set no bits, reset bit 5 */
}
if(fpga_status_now & 0x0010) {
msu_offset=get_msu_offset();
printf("Data requested! Offset=%08lx\n", msu_offset);
// get address
// open file + fill buffer
// 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();
}
}
/* Audio buffer refill */
if((fpga_status_now & 0x4000) != (fpga_status_prev & 0x4000)) {
if(fpga_status_now & 0x4000) {
dac_addr = 0x0;
} else {
dac_addr = 0x400;
}
set_dac_addr(dac_addr);
sd_offload_tgt=1;
ff_sd_offload=1;
f_read(&file_handle, file_buf, 1024, &bytes_read);
}
/* volume update */
if(msu_volupdate && !(msu_volupdate_cnt++ & 0x1)) {
if(volume < msu_volume) {
volume++;
} else if(volume > msu_volume) {
volume--;
} else {
msu_volupdate = 0;
}
printf("should not see me!\n");
set_dac_vol(volume);
}
/* Data buffer refill */
if((fpga_status_now & 0x2000) != (fpga_status_prev & 0x2000)) {
printf("data\n");
if(fpga_status_now & 0x2000) {
msu_addr = 0x0;
} else {
msu_addr = 0x2000;
}
set_msu_addr(msu_addr);
sd_offload_tgt=2;
ff_sd_offload=1;
f_read(&durr, file_buf, 8192, &bytes_read2);
}
fpga_status_prev = fpga_status_now;
/* handle loop / end */
if(bytes_read<1024) {
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, 44L);
ff_sd_offload=1;
sd_offload_tgt=1;
f_read(&file_handle, file_buf, 1024 - bytes_read, &bytes_read);
} else {
set_msu_status(0x00, 0x02); /* clear play bit */
}
bytes_read=1024;
}
if(!bytes_read2) {
f_lseek(&durr, 0L);
uart_putc('*');
}
}
/* END OF MSU1 STUFF */
cmd=0; cmd=0;
uint8_t snes_reset_prev=0, snes_reset_now=0, snes_reset_state=0; uint8_t snes_reset_prev=0, snes_reset_now=0, snes_reset_state=0;
uint16_t reset_count=0; uint16_t reset_count=0;

View File

@ -186,6 +186,7 @@ printf("%s\n", filename);
// FPGA_TX_BYTE(0x91); /* write w/ increment */ // FPGA_TX_BYTE(0x91); /* write w/ increment */
for(;;) { for(;;) {
ff_sd_offload=1; ff_sd_offload=1;
sd_offload_tgt=0;
tickstmp=getticks(); tickstmp=getticks();
bytes_read = file_read(); bytes_read = file_read();
ticks_read+=getticks()-tickstmp; ticks_read+=getticks()-tickstmp;

View File

@ -348,7 +348,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
do { do {
if(dat) { if(dat) {
if(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) { if(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
DBG_SD printf("data start during response\n"); printf("data start during response\n");
j=datcnt; j=datcnt;
state=CMD_RSPDAT; state=CMD_RSPDAT;
break; break;
@ -401,6 +401,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
} }
if(dat && state != CMD_DAT) { /* response ended before data */ if(dat && state != CMD_DAT) { /* response ended before data */
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
state=CMD_DAT; state=CMD_DAT;
j=datcnt; j=datcnt;
datshift=8; datshift=8;
@ -410,7 +411,13 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
} }
wiggle_fast_neg1(); /* eat the start bit */ wiggle_fast_neg1(); /* eat the start bit */
if(sd_offload) { if(sd_offload) {
fpga_sd2ram(); if(sd_offload_partial) {
fpga_set_sddma_range(sd_offload_partial_start, sd_offload_partial_end);
fpga_sddma(sd_offload_tgt, 1);
sd_offload_partial=0;
} else {
fpga_sddma(sd_offload_tgt, 0);
}
state=CMD_RSP; state=CMD_RSP;
return rsplen; return rsplen;
} }
@ -460,6 +467,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
} }
rsp-=rsplen; rsp-=rsplen;
DBG_SD printf("send_command_fast: CMD%d response: %02x%02x%02x%02x%02x%02x\n", cmdno, rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5]); DBG_SD printf("send_command_fast: CMD%d response: %02x%02x%02x%02x%02x%02x\n", cmdno, rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5]);
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
return rsplen; return rsplen;
} }
@ -528,7 +536,13 @@ void stream_datablock(uint8_t *buf) {
} }
wiggle_fast_neg1(); /* eat the start bit */ wiggle_fast_neg1(); /* eat the start bit */
if(sd_offload) { if(sd_offload) {
fpga_sd2ram(); if(sd_offload_partial) {
fpga_set_sddma_range(sd_offload_partial_start, sd_offload_partial_end);
fpga_sddma(sd_offload_tgt, 1);
sd_offload_partial=0;
} else {
fpga_sddma(sd_offload_tgt, 0);
}
} else { } else {
while(1) { while(1) {
datdata = SD_DAT << 4; datdata = SD_DAT << 4;
@ -677,6 +691,7 @@ void read_block(uint32_t address, uint8_t *buf) {
last_block=address; last_block=address;
} else { } else {
if(during_blocktrans) { if(during_blocktrans) {
// uart_putc('_');
//printf("nonseq read (%lx -> %lx), restarting transmission\n", last_block, address); //printf("nonseq read (%lx -> %lx), restarting transmission\n", last_block, address);
/* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */
cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp); cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);

View File

@ -47,7 +47,7 @@ void timer_init(void) {
BITBAND(LPC_SC->PCLKSEL1, 26) = 1; BITBAND(LPC_SC->PCLKSEL1, 26) = 1;
BITBAND(LPC_SC->PCLKSEL1, PCLK_TIMER3) = 1; BITBAND(LPC_SC->PCLKSEL1, PCLK_TIMER3) = 1;
/* enable SysTick */ /* enable SysTick */
SysTick_Config(SysTick->CALIB & SysTick_CALIB_TENMS_Msk); SysTick_Config((SysTick->CALIB & SysTick_CALIB_TENMS_Msk));
} }
void delay_us(unsigned int time) { void delay_us(unsigned int time) {

View File

@ -111,7 +111,6 @@ static volatile unsigned int read_idx,write_idx;
void UART_HANDLER(void) { void UART_HANDLER(void) {
int iir = UART_REGS->IIR; int iir = UART_REGS->IIR;
if (!(iir & 1)) { if (!(iir & 1)) {
/* Interrupt is pending */ /* Interrupt is pending */
switch (iir & 14) { switch (iir & 14) {