Merge branch 'master' of ssh://shion.micecat.ath.cx/~ikari/public_html/git/sd2snes

This commit is contained in:
Maximilian Rehkopf
2009-11-06 10:48:07 +01:00
37 changed files with 4984 additions and 2697 deletions

View File

@@ -343,7 +343,7 @@ endif
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y
AVRDUDE_ERASE_COUNTER = -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.

View File

@@ -27,7 +27,7 @@
CONFIG_MCU=atmega644
CONFIG_LINKER_RELAX=n
CONFIG_MCU_FREQ=13500000
CONFIG_MCU_FREQ=12288000
CONFIG_BOOTLOADER=y
CONFIG_BOOT_DEVID=0x4e534453
CONFIG_UART_DEBUG=y
@@ -39,3 +39,4 @@ CONFIG_SD_AUTO_RETRIES=10
CONFIG_EEPROM_SIZE=512
CONFIG_EEPROM_OFFSET=512
CONFIG_MAX_PARTITIONS=1
CONFIG_DEADLOCK_ME_HARDER=y

View File

@@ -62,8 +62,8 @@
# error Unknown chip!
# endif
# define SD_CHANGE_VECT INT0_vect
# define SDCARD_WP (PINB & _BV(PB3))
# define SDCARD_WP_SETUP() do { DDRB &= ~ _BV(PB3); PORTB |= _BV(PB3); } while(0)
# define SDCARD_WP (PINB & _BV(PB1))
# define SDCARD_WP_SETUP() do { DDRB &= ~ _BV(PB1); PORTB |= _BV(PB1); } while(0)
# define SD_CHANGE_ICR MCUCR
# define SD_SUPPLY_VOLTAGE (1L<<21)
# define DEVICE_SELECT (8+!(PINA & _BV(PA2))+2*!(PINA & _BV(PA3)))

View File

@@ -59,7 +59,7 @@
#include "config.h"
#include "ff.h" /* FatFs declarations */
#include "diskio.h" /* Include file for user provided disk functions */
#include "uart.h"
/*--------------------------------------------------------------------------
@@ -1651,7 +1651,7 @@ FRESULT f_write (
*bw = 0;
res = validate(fs /*, fp->id*/); /* Check validity of the object */
if (res != FR_OK) return res;
if (fp->flag & FA__ERROR) return FR_RW_ERROR; /* Check error flag */
if (fp->flag & FA__ERROR) {dprintf("fp->flag & FA__ERROR \n"); return FR_RW_ERROR;} /* Check error flag */
if (!(fp->flag & FA_WRITE)) return FR_DENIED; /* Check access mode */
if (fp->fsize + btw < fp->fsize) return FR_OK; /* File size cannot reach 4GB */
@@ -1669,18 +1669,18 @@ FRESULT f_write (
clust = create_chain(fs, fp->curr_clust); /* Trace or streach cluster chain */
}
if (clust == 0) break; /* Disk full */
if (clust == 1 || clust >= fs->max_clust) goto fw_error;
if (clust == 1 || clust >= fs->max_clust) { dprintf("cluster alloc error\n"); goto fw_error; }
fp->curr_clust = clust; /* Current cluster */
sect = clust2sect(fs, clust); /* Get current sector */
fp->csect = fs->csize; /* Re-initialize the left sector counter */
}
if(!move_fp_window(fp,0)) goto fw_error;
if(!move_fp_window(fp,0)) {dprintf("move_fp_window error\n"); goto fw_error;}
fp->curr_sect = sect; /* Update current sector */
cc = btw / SS(fs); /* When left bytes >= SS(fs), */
if (cc) { /* Write maximum contiguous sectors directly */
if (cc > fp->csect) cc = fp->csect;
if (disk_write(fs->drive, wbuff, sect, (BYTE)cc) != RES_OK)
goto fw_error;
{ dprintf("disk_write error\n"); goto fw_error;}
fp->csect -= (BYTE)(cc - 1);
fp->curr_sect += cc - 1;
wcnt = cc * SS(fs);
@@ -1695,7 +1695,7 @@ FRESULT f_write (
fp->fptr < fp->fsize && /* Fill sector buffer with file data if needed */
#endif
!move_fp_window(fp,fp->curr_sect))
goto fw_error;
{ dprintf("fract write error\n "); goto fw_error; }
memcpy(&FPBUF.data[fp->fptr & (SS(fs) - 1)], wbuff, wcnt);
FPBUF.dirty=TRUE;
}

View File

@@ -18,7 +18,7 @@ void file_init() {
void file_open_by_filinfo(FILINFO* fno) {
file_res = l_openfilebycluster(&fatfs, &file_handle, (UCHAR*)"", fno->clust, fno->fsize);
}
void file_open(char* filename, BYTE flags) {
void file_open(uint8_t* filename, BYTE flags) {
file_res = f_open(&file_handle, (unsigned char*)filename, flags);
}

View File

@@ -9,9 +9,10 @@ BYTE file_buf[512];
FATFS fatfs;
FIL file_handle;
FRESULT file_res;
uint8_t file_lfn[256];
void file_init(void);
void file_open(char* filename, BYTE flags);
void file_open(uint8_t* filename, BYTE flags);
void file_open_by_filinfo(FILINFO* fno);
void file_close(void);
UINT file_read(void);

View File

@@ -12,88 +12,176 @@
#include "fileops.h"
#include "crc16.h"
#include "memory.h"
#include "led.h"
uint16_t scan_flat(const char* path) {
DIR dir;
FRESULT res;
FILINFO fno;
fno.lfn = NULL;
res = f_opendir(&dir, (unsigned char*)path);
uint16_t numentries = 0;
if (res == FR_OK) {
for (;;) {
res = f_readdir(&dir, &fno);
if(res != FR_OK || fno.fname[0] == 0)break;
numentries++;
}
}
return numentries;
}
uint16_t scan_dir(char* path, char mkdb) {
DIR dir;
FILINFO fno;
FRESULT res;
int len;
uint8_t len;
unsigned char* fn;
static unsigned char lfn[256];
static unsigned char depth = 0;
static uint16_t crc;
static uint32_t db_tgt;
static uint32_t dir_tgt;
static uint32_t dir_end = 0;
static uint8_t was_empty = 0;
uint32_t dir_tgt_save, dir_tgt_next;
uint16_t numentries;
uint32_t dirsize;
uint8_t pass = 0;
if(depth==0) {
crc = 0;
db_tgt = SRAM_WORK_ADDR+0x10;
}
// dprintf("path=%s depth=%d ptr=%lx\n", path, depth, db_tgt);
// _delay_ms(50);
fno.lfn = lfn;
res = f_opendir(&dir, (unsigned char*)path);
if (res == FR_OK) {
len = strlen((char*)path);
for (;;) {
res = f_readdir(&dir, &fno);
if (res != FR_OK || fno.fname[0] == 0) break;
fn = *fno.lfn ? fno.lfn : fno.fname;
// dprintf("%s\n", fn);
// _delay_ms(100);
if (*fn == '.') continue;
if (fno.fattrib & AM_DIR) {
path[len]='/';
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
depth++;
scan_dir(path, mkdb);
depth--;
path[len]=0;
// if (res != FR_OK) {
// break;
// }
} else {
SNES_FTYPE type = determine_filetype((char*)fn);
if(type != TYPE_UNKNOWN) {
if(mkdb) {
snes_romprops_t romprops;
db_tgt = SRAM_DB_ADDR+0x10;
dir_tgt = SRAM_DIR_ADDR;
dprintf("root dir @%lx\n", dir_tgt);
}
fno.lfn = file_lfn;
numentries=0;
dir_tgt_next=0;
for(pass = 0; pass < 2; pass++) {
if(pass) {
dirsize = 4*(numentries);
dir_tgt_next = dir_tgt + dirsize + 4; // number of entries + end marker
if(dir_tgt_next > dir_end) {
dir_end = dir_tgt_next;
}
// dprintf("path=%s depth=%d ptr=%lx entries=%d next subdir @%lx\n", path, depth, db_tgt, numentries, dir_tgt_next);
// _delay_ms(50);
if(mkdb) {
// dprintf("d=%d Saving %lX to Address %lX [end]\n", depth, 0L, dir_tgt_next - 4);
// _delay_ms(50);
sram_writelong(0L, dir_tgt_next - 4);
}
}
res = f_opendir(&dir, (unsigned char*)path);
if (res == FR_OK) {
len = strlen((char*)path);
for (;;) {
toggle_busy_led();
res = f_readdir(&dir, &fno);
if (res != FR_OK || fno.fname[0] == 0) {
if(pass) {
if(!numentries) was_empty=1;
}
break;
}
fn = *fno.lfn ? fno.lfn : fno.fname;
// dprintf("%s\n", fn);
// _delay_ms(100);
if (*fn == '.') continue;
if (fno.fattrib & AM_DIR) {
numentries++;
if(pass) {
path[len]='/';
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
switch(type) {
case TYPE_SMC:
file_open_by_filinfo(&fno);
if(file_res){
dprintf("ZOMG NOOOO %d\n", file_res);
_delay_ms(30);
}
smc_id(&romprops);
file_close();
dprintf("%lx\n", db_tgt);
// _delay_ms(30);
sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops));
sram_writeblock(path, db_tgt + sizeof(romprops), 256);
db_tgt += 0x140;
break;
case TYPE_UNKNOWN:
default:
break;
depth++;
dir_tgt_save = dir_tgt;
dir_tgt = dir_tgt_next;
if(mkdb) {
uint16_t pathlen = strlen(path);
// write element pointer to current dir structure
// dprintf("d=%d Saving %lX to Address %lX [dir]\n", depth, db_tgt, dir_tgt_save);
// _delay_ms(50);
sram_writelong(db_tgt|((uint32_t)0x80<<24), dir_tgt_save);
// sram_writeblock((uint8_t*)&db_tgt, dir_tgt_save, sizeof(dir_tgt_save));
// save element:
// - path name
// - pointer to sub dir structure
// dprintf(" Saving dir descriptor to %lX, tgt=%lX, path=%s\n", db_tgt, dir_tgt, path);
// _delay_ms(100);
sram_writelong(dir_tgt, db_tgt);
sram_writebyte(len+1, db_tgt+sizeof(dir_tgt));
sram_writeblock(path, db_tgt+sizeof(dir_tgt)+sizeof(len), pathlen + 1);
// sram_writeblock((uint8_t*)&dir_tgt, db_tgt+256, sizeof(dir_tgt));
db_tgt += sizeof(dir_tgt) + sizeof(len) + pathlen + 1;
}
scan_dir(path, mkdb);
dir_tgt = dir_tgt_save + 4;
if(was_empty)dir_tgt_next += 4;
was_empty = 0;
depth--;
path[len]=0;
// dprintf("%s ", path);
// _delay_ms(30);
}
unsigned char* sfn = fno.fname;
while(*sfn != 0) {
crc += crc16_update(crc, sfn++, 1);
} else {
SNES_FTYPE type = determine_filetype((char*)fn);
if(type != TYPE_UNKNOWN) {
numentries++;
if(pass) {
if(mkdb) {
snes_romprops_t romprops;
path[len]='/';
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
uint16_t pathlen = strlen(path);
switch(type) {
case TYPE_SMC:
file_open_by_filinfo(&fno);
if(file_res){
dprintf("ZOMG NOOOO %d\n", file_res);
_delay_ms(30);
}
smc_id(&romprops);
file_close();
// _delay_ms(30);
// write element pointer to current dir structure
// dprintf("d=%d Saving %lX to Address %lX [file]\n", depth, db_tgt, dir_tgt);
// _delay_ms(50);
sram_writelong(db_tgt, dir_tgt);
// sram_writeblock((uint8_t*)&db_tgt, dir_tgt, sizeof(db_tgt));
dir_tgt += 4;
// save element:
// - SNES header information
// - file name
sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops));
sram_writebyte(len+1, db_tgt + sizeof(romprops));
sram_writeblock(path, db_tgt + sizeof(romprops) + sizeof(len), pathlen + 1);
db_tgt += sizeof(romprops) + sizeof(len) + pathlen + 1;
break;
case TYPE_UNKNOWN:
default:
break;
}
path[len]=0;
// dprintf("%s ", path);
// _delay_ms(30);
}
} else {
unsigned char* sfn = fno.fname;
while(*sfn != 0) {
crc += crc16_update(crc, sfn++, 1);
}
}
}
// dprintf("%s/%s\n", path, fn);
// _delay_ms(50);
}
// dprintf("%s/%s\n", path, fn);
// _delay_ms(50);
// _delay_ms(10);
}
}
} else uart_putc(0x30+res);
}
} else uart_putc(0x30+res);
}
// dprintf("%x\n", crc);
// _delay_ms(50);
sram_writeblock(&db_tgt, SRAM_WORK_ADDR+4, sizeof(db_tgt));
sram_writeblock(&db_tgt, SRAM_DB_ADDR+4, sizeof(db_tgt));
sram_writeblock(&dir_end, SRAM_DB_ADDR+8, sizeof(dir_end));
return crc;
}
@@ -115,7 +203,7 @@ SNES_FTYPE determine_filetype(char* filename) {
}
FRESULT get_db_id(uint16_t* id) {
file_open("/sd2snes/sd2snes.db", FA_READ);
file_open((uint8_t*)"/sd2snes/sd2snes.db", FA_READ);
if(file_res == FR_OK) {
file_readblock(id, 0, 2);
/* XXX */// *id=0xdead;

View File

@@ -7,34 +7,15 @@
FPGA pin mapping
================
PSM:
====
FPGA AVR dir
------------------------
PROG_B PD3 OUT
CCLK PD4 OUT
CS_B PD7 OUT
INIT_B PB2 IN
RDWR_B PB3 OUT
D7 PC0 OUT
D6 PC1 OUT
D5 PC2 OUT
D4 PC3 OUT
D3 PC4 OUT
D2 PC5 OUT
D1 PC6 OUT
D0 PC7 OUT
SSM:
====
PROG_B PD3 OUT
CCLK PD4 OUT
INIT_B PD7 IN
DIN PC7 OUT
DONE PA3 IN
*/
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "fpga.h"
#include "config.h"
#include "uart.h"
@@ -58,22 +39,6 @@ void set_prog_b(uint8_t val) {
}
}
void set_cs_b(uint8_t val) {
if(val) {
PORTD |= _BV(PD7);
} else {
PORTD &= ~_BV(PD7);
}
}
void set_rdwr_b(uint8_t val) {
if(val) {
PORTB |= _BV(PB3);
} else {
PORTB &= ~_BV(PB3);
}
}
void set_cclk(uint8_t val) {
if(val) {
PORTD |= _BV(PD4);
@@ -83,80 +48,63 @@ void set_cclk(uint8_t val) {
}
void fpga_init() {
DDRB |= _BV(PB3); // PB3 is output
DDRD &= ~_BV(PD7); // PD7 is input
DDRD &= ~_BV(PD7); // PD7 is input
DDRC = _BV(PC7); // for FPGA config, PC7 is output
DDRC = _BV(PC7); // for FPGA config, PC7 is output
DDRD |= _BV(PD3) | _BV(PD4); // PD3, PD4 are outputs
DDRA = ~_BV(PA3); // PA3 is input <- DONE
set_cclk(0); // initial clk=0
}
int fpga_get_done(void) {
return 0;
return PINA & _BV(PA3);
}
void fpga_postinit() {
DDRA |= _BV(PA0) | _BV(PA1) | _BV(PA2) | _BV(PA4) | _BV(PA5) | _BV(PA6); // MAPPER+NEXTADDR output
DDRB |= _BV(PB2) | _BV(PB1) | _BV(PB0); // turn PB2 into output, enable AVR_BANK
DDRD |= _BV(PD7); // turn PD7 into output
DDRD |= _BV(PD7); // turn PD7 into output
}
void fpga_pgm(char* filename) {
set_prog_b(0);
uart_putc('P');
set_prog_b(1);
loop_until_bit_is_set(PIND, PD7);
uart_putc('p');
// FIL in;
// FRESULT res;
UINT bytes_read;
void fpga_pgm(uint8_t* filename) {
int MAXRETRIES = 10;
int retries = MAXRETRIES;
do {
set_prog_b(0);
uart_putc('P');
set_prog_b(1);
loop_until_bit_is_set(PIND, PD7);
uart_putc('p');
UINT bytes_read;
// open configware file
// res=f_open(&in, filename, FA_READ);
file_open(filename, FA_READ);
if(file_res) {
uart_putc('?');
uart_putc(0x30+file_res);
return;
}
// file open successful
set_cs_b(0);
set_rdwr_b(0);
for (;;) {
// res = f_read(&in, file_buf, sizeof(file_buf), &bytes_read);
bytes_read = file_read();
if (file_res || bytes_read == 0) break; // error or eof
for(int i=0; i<bytes_read; i++) {
//FPGA_SEND_BYTE(file_buf[i]);
FPGA_SEND_BYTE_SERIAL(file_buf[i]);
// open configware file
file_open(filename, FA_READ);
if(file_res) {
uart_putc('?');
uart_putc(0x30+file_res);
return;
}
}
file_close();
for (;;) {
bytes_read = file_read();
if (file_res || bytes_read == 0) break; // error or eof
for(int i=0; i<bytes_read; i++) {
FPGA_SEND_BYTE_SERIAL(file_buf[i]);
}
}
file_close();
_delay_ms(10);
} while (!fpga_get_done() && retries--);
if(!fpga_get_done()) {
dprintf("FPGA failed to configure after %d tries.\n", MAXRETRIES);
_delay_ms(50);
}
fpga_postinit();
}
void set_avr_read(uint8_t val) {
if(val) {
PORTB |= _BV(PB3);
} else {
PORTB &= ~_BV(PB3);
}
}
void set_avr_write(uint8_t val) {
if(val) {
PORTB |= _BV(PB2);
} else {
PORTB &= ~_BV(PB2);
}
}
void set_avr_ena(uint8_t val) {
if(val) {
PORTD |= _BV(PD7);
@@ -165,34 +113,6 @@ void set_avr_ena(uint8_t val) {
}
}
void set_avr_nextaddr(uint8_t val) {
if(val) {
PORTA |= _BV(PA4);
} else {
PORTA &= ~_BV(PA4);
}
}
void set_avr_addr_reset(uint8_t val) {
if(val) {
PORTA |= _BV(PA5);
} else {
PORTA &= ~_BV(PA5);
}
}
void set_avr_data(uint8_t data) {
PORTC = data;
}
void set_avr_addr_en(uint8_t val) {
if(val) {
PORTA |= _BV(PA6);
} else {
PORTA &= ~_BV(PA6);
}
}
void set_avr_mapper(uint8_t val) {
SPI_SS_HIGH();
FPGA_SS_LOW();
@@ -211,3 +131,4 @@ void set_avr_bank(uint8_t val) {
FPGA_SS_HIGH();
SPI_SS_LOW();
}

View File

@@ -7,7 +7,7 @@
void fpga_init(void);
void fpga_postinit(void);
void fpga_pgm(char* filename);
void fpga_pgm(uint8_t* filename);
void set_avr_read(uint8_t val);
void set_avr_write(uint8_t val);

View File

@@ -20,7 +20,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
led.c: Overdesigned LED handling
led.c: LED handling
*/
@@ -28,30 +28,61 @@
#include "config.h"
#include "led.h"
static uint8_t led_bright[16]={255,253,252,251,249,247,244,239,232,223,210,191,165,127,74,0};
static uint8_t curr_bright = 0;
static uint8_t led_bounce_dir = 0;
volatile uint8_t led_state;
/**
* update_leds - set LEDs to correspond to the buffer status
*
* This function sets the busy/dirty LEDs to correspond to the current state
* of the buffers, i.e. busy on of at least one non-system buffer is
* allocated and dirty on if at least one buffer is allocated for writing.
* Call if you have manually changed the LEDs and you want to restore the
* "default" state.
*/
void update_leds(void) {
}
void toggle_busy_led(void) {
PORTB &= ~_BV(PB1);
DDRB ^= _BV(PB1);
PORTB &= ~_BV(PB3);
DDRB ^= _BV(PB3);
}
void set_busy_led(uint8_t state) {
PORTB &= ~_BV(PB1);
PORTB &= ~_BV(PB3);
if(state) {
DDRB |= _BV(PB1);
DDRB |= _BV(PB3);
} else {
DDRB &= ~_BV(PB1);
DDRB &= ~_BV(PB3);
}
}
void set_pwr_led(uint8_t state) {
PORTB &= ~_BV(PB0);
if(state) {
DDRB |= _BV(PB0);
} else {
DDRB &= ~_BV(PB0);
}
}
void set_busy_pwm(uint8_t brightness) {
OCR0A = led_bright[brightness];
set_busy_led(1);
}
void bounce_busy_led() {
set_busy_pwm(curr_bright);
if(led_bounce_dir) {
curr_bright--;
if(curr_bright==0) {
led_bounce_dir = 0;
}
} else {
curr_bright++;
if(curr_bright==15) {
led_bounce_dir = 1;
}
}
}
void led_pwm() {
set_busy_led(1);
TCCR0A = 0x83;
TCCR0B = 0x01;
}
void led_std() {
TCCR0A = 0;
}

View File

@@ -38,9 +38,11 @@
extern volatile uint8_t led_state;
/* Update the LEDs to match the buffer state */
void update_leds(void);
void toggle_busy_led(void);
void set_busy_led(uint8_t);
void set_pwr_led(uint8_t);
void set_busy_pwm(uint8_t brightness);
void bounce_busy_led(void);
void led_pwm(void);
void led_std(void);
#endif

View File

@@ -125,67 +125,108 @@ int main(void) {
#endif
#ifdef CLOCK_PRESCALE
clock_prescale_set(CLOCK_PRESCALE);
clock_prescale_set(CLOCK_PRESCALE);
#endif
set_pwr_led(0);
set_busy_led(1);
spi_none();
snes_reset(1);
uart_init();
sei(); // suspected to reset the AVR when inserting an SD card
_delay_ms(100);
disk_init();
snes_init();
timer_init();
uart_puts_P(PSTR("\nsd2snes " VERSION));
uart_putcrlf();
snes_reset(1);
uart_init();
sei(); // suspected to reset the AVR when inserting an SD card
_delay_ms(100);
disk_init();
snes_init();
timer_init();
uart_puts_P(PSTR("\nsd2snes " VERSION));
uart_putcrlf();
file_init();
FATFS fatfs;
f_mount(0,&fatfs);
set_busy_led(1);
uart_putc('W');
fpga_init();
fpga_pgm("/sd2snes/main.bit");
FATFS fatfs;
f_mount(0,&fatfs);
uart_putc('W');
fpga_init();
fpga_pgm((uint8_t*)"/sd2snes/main.bit");
_delay_ms(100);
set_pwr_led(1);
fpga_spi_init();
uart_putc('!');
uart_putc('!');
_delay_ms(100);
set_avr_ena(0);
set_avr_ena(0);
snes_reset(1);
*fs_path=0;
sram_writelong(0x12345678, SRAM_SCRATCHPAD);
*fs_path=0;
uint16_t curr_dir_id = scan_dir(fs_path, 0); // generate files footprint
dprintf("curr dir id = %x\n", curr_dir_id);
uint16_t saved_dir_id;
led_pwm();
if((get_db_id(&saved_dir_id) != FR_OK) // no database?
|| saved_dir_id != curr_dir_id) { // files changed?
|| saved_dir_id != curr_dir_id) { // files changed? // XXX
dprintf("saved dir id = %x\n", saved_dir_id);
_delay_ms(50);
dprintf("rebuilding database...");
_delay_ms(50);
curr_dir_id = scan_dir(fs_path, 1); // then rebuild database
sram_writeblock(&curr_dir_id, SRAM_WORK_ADDR, 2);
uint32_t endaddr;
sram_readblock(&endaddr, SRAM_WORK_ADDR+4, 4);
dprintf("%lx\n", endaddr);
save_sram("/sd2snes/sd2snes.db", endaddr-SRAM_WORK_ADDR, SRAM_WORK_ADDR);
sram_writeblock(&curr_dir_id, SRAM_DB_ADDR, 2);
uint32_t endaddr, direndaddr;
sram_readblock(&endaddr, SRAM_DB_ADDR+4, 4);
sram_readblock(&direndaddr, SRAM_DB_ADDR+8, 4);
dprintf("%lx %lx\n", endaddr, direndaddr);
save_sram((uint8_t*)"/sd2snes/sd2snes.db", endaddr-SRAM_DB_ADDR, SRAM_DB_ADDR);
save_sram((uint8_t*)"/sd2snes/sd2snes.dir", direndaddr-(SRAM_DIR_ADDR), SRAM_DIR_ADDR);
dprintf("done\n");
sram_hexdump(SRAM_DB_ADDR, 0x400);
} else {
dprintf("loading db...\n");
load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
}
uart_putc('[');
load_sram("/test.srm");
uart_putc(']');
// save_sram((uint8_t*)"/debug.smc", 0x400000, 0);
// uart_putc('[');
// load_sram((uint8_t*)"/test.srm", SRAM_SAVE_ADDR);
// uart_putc(']');
uart_putc('(');
load_rom("/test.smc");
load_rom((uint8_t*)"/sd2snes/menu.bin");
uart_putc(')');
sram_writebyte(0, SRAM_CMD_ADDR);
set_busy_led(0);
set_avr_ena(1);
_delay_ms(100);
uart_puts_P(PSTR("SNES GO!\n"));
snes_reset(0);
uint8_t cmd = 0;
while(!sram_reliable());
while(!cmd) {
cmd=menu_main_loop();
switch(cmd) {
case 0x01: // SNES_CMD_LOADROM:
get_selected_name(file_lfn);
_delay_ms(100);
// snes_reset(1);
set_avr_ena(0);
dprintf("Selected name: %s\n", file_lfn);
load_rom(file_lfn);
set_avr_ena(1);
snes_reset(1);
_delay_ms(100);
snes_reset(0);
break;
default:
break;
}
}
dprintf("cmd was %x, going to snes main loop\n", cmd);
cmd=0;
while(1) {
snes_main_loop();
}
@@ -200,22 +241,22 @@ while(1) {
uart_putcrlf();
uint8_t buff[21];
for(uint8_t cnt=0; cnt<21; cnt++) {
uint8_t data=spiTransferByte(0x00);
uint8_t data=spiTransferByte(0x00);
buff[cnt]=data;
}
for(uint8_t cnt=0; cnt<21; cnt++) {
uint8_t data = buff[cnt];
_delay_ms(2);
if(data>=0x20 && data <= 0x7a) {
if(data>=0x20 && data <= 0x7a) {
uart_putc(data);
} else {
} else {
// uart_putc('.');
uart_putc("0123456789ABCDEF"[data>>4]);
uart_putc("0123456789ABCDEF"[data&15]);
uart_putc(' ');
}
}
// set_avr_bank(3);
}
}
spi_none();
}
while(1);

View File

@@ -16,9 +16,64 @@
#include "led.h"
#include "smc.h"
#include "fpga_spi.h"
#include "memory.h"
char* hex = "0123456789ABCDEF";
void sram_hexdump(uint32_t addr, uint32_t len) {
static uint8_t buf[16];
uint32_t ptr;
for(ptr=0; ptr < len; ptr += 16) {
sram_readblock((void*)buf, ptr+addr, 16);
uart_trace(buf, 0, 16);
}
}
void sram_writebyte(uint8_t val, uint32_t addr) {
set_avr_addr(addr);
spi_fpga();
spiTransferByte(0x91); // WRITE
spiTransferByte(val);
spiTransferByte(0x00); // dummy
spi_none();
}
uint8_t sram_readbyte(uint32_t addr) {
set_avr_addr(addr);
spi_fpga();
spiTransferByte(0x81); // READ
spiTransferByte(0x00); // dummy
uint8_t val = spiTransferByte(0x00);
spi_none();
return val;
}
void sram_writelong(uint32_t val, uint32_t addr) {
set_avr_addr(addr);
spi_fpga();
spiTransferByte(0x91); // WRITE
spiTransferByte(val&0xff); // 7-0
spiTransferByte((val>>8)&0xff); // 15-8
spiTransferByte((val>>16)&0xff); // 23-15
spiTransferByte((val>>24)&0xff); // 31-24
spiTransferByte(0x00); // dummy
spi_none();
}
uint32_t sram_readlong(uint32_t addr) {
set_avr_addr(addr);
spi_fpga();
spiTransferByte(0x81);
spiTransferByte(0x00);
uint32_t val = spiTransferByte(0x00);
val |= ((uint32_t)spiTransferByte(0x00)<<8);
val |= ((uint32_t)spiTransferByte(0x00)<<16);
val |= ((uint32_t)spiTransferByte(0x00)<<24);
spi_none();
return val;
}
void sram_readblock(void* buf, uint32_t addr, uint16_t size) {
uint16_t count=size;
uint8_t* tgt = buf;
@@ -33,21 +88,19 @@ void sram_readblock(void* buf, uint32_t addr, uint16_t size) {
}
void sram_writeblock(void* buf, uint32_t addr, uint16_t size) {
uint16_t count=size>>1;
uint16_t* src = buf;
uint16_t count=size;
uint8_t* src = buf;
set_avr_addr(addr);
spi_fpga();
spiTransferByte(0x91); // WRITE
while(count--) {
spiTransferByte((*src)>>8);
spiTransferByte((*src)&0xff);
src++;
spiTransferByte(*src++);
}
spiTransferByte(0x00); // dummy
spi_none();
}
uint32_t load_rom(char* filename) {
uint32_t load_rom(uint8_t* filename) {
snes_romprops_t romprops;
set_avr_bank(0);
UINT bytes_read;
@@ -70,8 +123,9 @@ uint32_t load_rom(char* filename) {
if (file_res || !bytes_read) break;
FPGA_SS_LOW();
spiTransferByte(0x91); // write w/ increment
if(!(count++ % 16)) {
toggle_busy_led();
if(!(count++ % 8)) {
// toggle_busy_led();
bounce_busy_led();
uart_putc('.');
}
for(int j=0; j<bytes_read; j++) {
@@ -114,8 +168,8 @@ uint32_t load_rom(char* filename) {
return (uint32_t)filesize;
}
uint32_t load_sram(char* filename) {
set_avr_bank(3);
uint32_t load_sram(uint8_t* filename, uint32_t base_addr) {
set_avr_addr(base_addr);
UINT bytes_read;
DWORD filesize;
file_open(filename, FA_READ);
@@ -140,7 +194,7 @@ uint32_t load_sram(char* filename) {
}
void save_sram(char* filename, uint32_t sram_size, uint32_t base_addr) {
void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr) {
uint32_t count = 0;
uint32_t num = 0;
@@ -184,3 +238,16 @@ uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size) {
spi_none();
return crc;
}
uint8_t sram_reliable() {
uint16_t score=0;
uint32_t val = sram_readlong(SRAM_SCRATCHPAD);
while(score<SRAM_RELIABILITY_SCORE) {
if(sram_readlong(SRAM_SCRATCHPAD)==val) {
score++;
} else {
score=0;
}
}
return 1;
}

View File

@@ -5,11 +5,24 @@
#define MEMORY_H
#define SRAM_WORK_ADDR (0x100000L)
#define SRAM_DB_ADDR (0x080000L)
#define SRAM_DIR_ADDR (0x300000L)
#define SRAM_CMD_ADDR (0x600004L)
#define SRAM_FD_ADDR (0x600000L)
#define SRAM_SAVE_ADDR (0x600000L)
#define SRAM_SCRATCHPAD (0x7FFFF0L)
#define SRAM_RELIABILITY_SCORE (0x100)
uint32_t load_rom(char* filename);
uint32_t load_sram(char* filename);
uint32_t load_rom(uint8_t* filename);
uint32_t load_sram(uint8_t* filename, uint32_t base_addr);
void sram_hexdump(uint32_t addr, uint32_t len);
uint8_t sram_readbyte(uint32_t addr);
uint32_t sram_readlong(uint32_t addr);
void sram_writebyte(uint8_t val, uint32_t addr);
void sram_writelong(uint32_t val, uint32_t addr);
void sram_readblock(void* buf, uint32_t addr, uint16_t size);
void sram_writeblock(void* buf, uint32_t addr, uint16_t size);
void save_sram(char* filename, uint32_t sram_size, uint32_t base_addr);
void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr);
uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size);
uint8_t sram_reliable(void);
#endif

View File

@@ -181,8 +181,8 @@ static uint8_t sdResponse(uint8_t expected)
static uint8_t sdWaitWriteFinish(void)
{
unsigned short count = 0xFFFF; // wait for quite some time
uint32_t count = 0x1FFFF; // wait for quite some time
while ((spiTransferByte(0xFF) == 0) && count )
count--;
@@ -640,6 +640,7 @@ DRESULT sd_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) {
res = sendCommand(drv, WRITE_BLOCK, (sector+sec)<<9, 0);
if (res != 0) {
uart_putc('C');
SPI_SS_HIGH(drv);
disk_state = DISK_ERROR;
return RES_ERROR;
@@ -678,6 +679,7 @@ DRESULT sd_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) {
// Wait for write finish
if (!sdWaitWriteFinish()) {
uart_putc('W');
SPI_SS_HIGH(drv);
disk_state = DISK_ERROR;
return RES_ERROR;

View File

@@ -42,12 +42,11 @@ void snes_reset(int state) {
/*
* SD2SNES main loop.
* monitors SRAM changes, menu selections and other things
* monitors SRAM changes and other things
*/
void snes_main_loop() {
if(initloop) {
saveram_crc_old = calc_sram_crc(saveram_base_addr, saveram_size);
save_sram("/test.srm", saveram_size, saveram_base_addr);
initloop=0;
}
saveram_crc = calc_sram_crc(saveram_base_addr, saveram_size);
@@ -56,8 +55,27 @@ void snes_main_loop() {
uart_puthexshort(saveram_crc);
uart_putcrlf();
set_busy_led(1);
save_sram("/test.srm", saveram_size, saveram_base_addr);
save_sram((uint8_t*)"/test.srm", saveram_size, saveram_base_addr);
set_busy_led(0);
}
saveram_crc_old = saveram_crc;
}
/*
* SD2SNES menu loop.
* monitors menu selection. return when selection was made.
*/
uint8_t menu_main_loop() {
uint8_t cmd = 0;
sram_writebyte(0, SRAM_CMD_ADDR);
while(!cmd) {
cmd = sram_readbyte(SRAM_CMD_ADDR);
}
return cmd;
}
void get_selected_name(uint8_t* fn) {
uint32_t addr = sram_readlong(SRAM_FD_ADDR);
dprintf("fd addr=%lX\n", addr);
sram_readblock(fn, addr+0x41, 256);
}

View File

@@ -8,4 +8,6 @@
void snes_init(void);
void snes_reset(int state);
void snes_main_loop(void);
uint8_t menu_main_loop(void);
void get_selected_name(uint8_t* lfn);
#endif