mk2 fw wip (cleanup indent+comment)

This commit is contained in:
ikari 2010-09-24 23:38:59 +02:00
parent db45a5afaf
commit f063cb31f9
23 changed files with 946 additions and 966 deletions

View File

@ -55,7 +55,7 @@ TARGET = $(OBJDIR)/sd2snes
# List C source files here. (C dependencies are automatically generated.) # List C source files here. (C dependencies are automatically generated.)
SRC = main.c ff.c ccsbcs.c clock.c uart.c power.c led.c timer.c printf.c sdcard.c spi.c fileops.c rtc.c fpga.c fpga_spi.c snes.c smc.c memory.c crc16.c filetypes.c faulthandler.c sort.c SRC = main.c ff.c ccsbcs.c clock.c uart.c power.c led.c timer.c printf.c sdcard.c spi.c fileops.c rtc.c fpga.c fpga_spi.c snes.c smc.c memory.c filetypes.c faulthandler.c sort.c
# List Assembler source files here. # List Assembler source files here.

View File

@ -15,7 +15,7 @@ void clock_disconnect() {
void clock_init() { void clock_init() {
/* set flash access time to 5 clks (80<f<=100MHz) */ /* set flash access time to 5 clks (80<f<=100MHz) */
setFlashAccessTime(5); setFlashAccessTime(5);
/* setup PLL0 for ~44100*256*8 Hz /* setup PLL0 for ~44100*256*8 Hz
Base clock: 12MHz Base clock: 12MHz
@ -46,62 +46,62 @@ void clock_init() {
connect PLL0 connect PLL0
done done
*/ */
enableMainOsc(); enableMainOsc();
setClkSrc(CLKSRC_MAINOSC); setClkSrc(CLKSRC_MAINOSC);
setPLL0MultPrediv(429, 19); setPLL0MultPrediv(429, 19);
enablePLL0(); enablePLL0();
setCCLKDiv(6); setCCLKDiv(6);
connectPLL0(); connectPLL0();
} }
void setFlashAccessTime(uint8_t clocks) { void setFlashAccessTime(uint8_t clocks) {
LPC_SC->FLASHCFG=FLASHTIM(clocks); LPC_SC->FLASHCFG=FLASHTIM(clocks);
} }
void setPLL0MultPrediv(uint16_t mult, uint8_t prediv) { void setPLL0MultPrediv(uint16_t mult, uint8_t prediv) {
LPC_SC->PLL0CFG=PLL_MULT(mult) | PLL_PREDIV(prediv); LPC_SC->PLL0CFG=PLL_MULT(mult) | PLL_PREDIV(prediv);
PLL0feed(); PLL0feed();
} }
void enablePLL0() { void enablePLL0() {
LPC_SC->PLL0CON |= PLLE0; LPC_SC->PLL0CON |= PLLE0;
PLL0feed(); PLL0feed();
} }
void disablePLL0() { void disablePLL0() {
LPC_SC->PLL0CON &= ~PLLE0; LPC_SC->PLL0CON &= ~PLLE0;
PLL0feed(); PLL0feed();
} }
void connectPLL0() { void connectPLL0() {
while(!(LPC_SC->PLL0STAT&PLOCK0)); while(!(LPC_SC->PLL0STAT&PLOCK0));
LPC_SC->PLL0CON |= PLLC0; LPC_SC->PLL0CON |= PLLC0;
PLL0feed(); PLL0feed();
} }
void disconnectPLL0() { void disconnectPLL0() {
LPC_SC->PLL0CON &= ~PLLC0; LPC_SC->PLL0CON &= ~PLLC0;
PLL0feed(); PLL0feed();
} }
void setCCLKDiv(uint8_t div) { void setCCLKDiv(uint8_t div) {
LPC_SC->CCLKCFG=CCLK_DIV(div); LPC_SC->CCLKCFG=CCLK_DIV(div);
} }
void enableMainOsc() { void enableMainOsc() {
LPC_SC->SCS=OSCEN; LPC_SC->SCS=OSCEN;
while(!(LPC_SC->SCS&OSCSTAT)); while(!(LPC_SC->SCS&OSCSTAT));
} }
void disableMainOsc() { void disableMainOsc() {
LPC_SC->SCS=0; LPC_SC->SCS=0;
} }
void PLL0feed() { void PLL0feed() {
LPC_SC->PLL0FEED=0xaa; LPC_SC->PLL0FEED=0xaa;
LPC_SC->PLL0FEED=0x55; LPC_SC->PLL0FEED=0x55;
} }
void setClkSrc(uint8_t src) { void setClkSrc(uint8_t src) {
LPC_SC->CLKSRCSEL=src; LPC_SC->CLKSRCSEL=src;
} }

View File

@ -1 +1,2 @@
CONFIG_VERSION=0.0.1
CONFIG_MCU_FOSC=12000000 CONFIG_MCU_FOSC=12000000

View File

@ -1,6 +1,7 @@
#ifndef _CONFIG_H #ifndef _CONFIG_H
#define _CONFIG_H #define _CONFIG_H
#define VER "0.0.1"
#define IN_AHBRAM __attribute__ ((section(".ahbram"))) #define IN_AHBRAM __attribute__ ((section(".ahbram")))
#define SDCARD_DETECT (1) #define SDCARD_DETECT (1)
@ -28,7 +29,7 @@
#define SNES_RESET_REG LPC_GPIO1 #define SNES_RESET_REG LPC_GPIO1
#define SNES_RESET_BIT 29 #define SNES_RESET_BIT 29
// Rev.B: 26 /* XXX Rev.B: 26 */
#define QSORT_MAXELEM 1024 #define QSORT_MAXELEM 1024

View File

@ -2,20 +2,59 @@
* \file stdout * \file stdout
* Functions and types for CRC checks. * Functions and types for CRC checks.
* *
* Generated on Tue Jun 30 23:02:59 2009, * Generated on Tue Sep 15 09:32:35 2009,
* by pycrc v0.7.1, http://www.tty1.net/pycrc/ * by pycrc v0.7.1, http://www.tty1.net/pycrc/
* using the configuration: * using the configuration:
* Width = 16 * Width = 16
* Poly = 0x8005 * Poly = 0x8005
* XorIn = 0x0000 * XorIn = 0xffff
* ReflectIn = True * ReflectIn = True
* XorOut = 0x0000 * XorOut = 0xffff
* ReflectOut = True * ReflectOut = True
* Algorithm = bit-by-bit-fast * Algorithm = table-driven
* Direct = True * Direct = True
*****************************************************************************/ *****************************************************************************/
#include <stdint.h> #include <arm/NXP/LPC17xx/LPC17xx.h>
#include "crc16.h" #include "crc16.h"
/**
* Static table used for the table_driven implementation.
*****************************************************************************/
static const crc_t crc_table[256] = {
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
};
/** /**
* Update the crc value with new data. * Update the crc value with new data.
* *
@ -26,26 +65,13 @@
*****************************************************************************/ *****************************************************************************/
crc_t crc16_update(crc_t crc, const unsigned char *data, size_t data_len) crc_t crc16_update(crc_t crc, const unsigned char *data, size_t data_len)
{ {
unsigned int i; unsigned int tbl_idx;
uint8_t bit; while (data_len--) {
unsigned char c; tbl_idx = (crc ^ *data) & 0xff;
crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffff;
while (data_len--) { data++;
c = *data++; }
for (i = 0x01; i & 0xff; i <<= 1) { return crc & 0xffff;
bit = (crc & 0x8000 ? 1 : 0);
if (c & i) {
bit ^= 1;
}
crc <<= 1;
if (bit) {
crc ^= 0x8005;
}
}
crc &= 0xffff;
}
return crc & 0xffff;
} }

View File

@ -1639,6 +1639,8 @@ void get_fileinfo ( /* No return code */
fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */ fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */
fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */ fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */
fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */ fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */
fno->clust = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16)
| LD_WORD(dir+DIR_FstClusLO);
} }
*p = 0; /* Terminate SFN str by a \0 */ *p = 0; /* Terminate SFN str by a \0 */
@ -2821,6 +2823,25 @@ FRESULT f_stat (
} }
FRESULT l_openfilebycluster (
FATFS *fs, /* Pointer to file system object */
FIL *fp, /* Pointer to the blank file object */
const TCHAR *path,
DWORD clust, /* Cluster number to be opened */
DWORD fsize /* File size to be assumed */
)
{
chk_mounted(&path, &fs, 0);
fp->flag = FA_READ;
fp->org_clust = clust;
fp->fsize = fsize;
fp->fptr = 0;
fp->dsect = 0;
fp->fs = fs;
return FR_OK;
}
#if !_FS_READONLY #if !_FS_READONLY
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -358,6 +358,7 @@ typedef struct {
WORD ftime; /* Last modified time */ WORD ftime; /* Last modified time */
BYTE fattrib; /* Attribute */ BYTE fattrib; /* Attribute */
TCHAR fname[13]; /* Short file name (8.3 format) */ TCHAR fname[13]; /* Short file name (8.3 format) */
DWORD clust; /* start cluster */
#if _USE_LFN #if _USE_LFN
TCHAR* lfname; /* Pointer to the LFN buffer */ TCHAR* lfname; /* Pointer to the LFN buffer */
UINT lfsize; /* Size of LFN buffer in TCHAR */ UINT lfsize; /* Size of LFN buffer in TCHAR */
@ -395,6 +396,10 @@ typedef enum {
/*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/
/* FatFs module application interface */ /* FatFs module application interface */
/* Low Level functions */
FRESULT l_openfilebycluster(FATFS *fs, FIL *fp, const TCHAR *path, DWORD clust, DWORD fsize); /* Open a file by its start cluster using supplied file size */
/* application level functions */
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */ FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */ FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */
FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */ FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */

View File

@ -29,52 +29,53 @@
#include "ff.h" #include "ff.h"
#include "fileops.h" #include "fileops.h"
/*WCHAR ff_convert(WCHAR w, UINT dir) { /*
return w; WCHAR ff_convert(WCHAR w, UINT dir) {
return w;
}*/ }*/
void file_init() { void file_init() {
file_res=f_mount(0, &fatfs); file_res=f_mount(0, &fatfs);
} }
/*void file_open_by_filinfo(FILINFO* fno) { void file_open_by_filinfo(FILINFO* fno) {
file_res = l_openfilebycluster(&fatfs, &file_handle, (UCHAR*)"", fno->clust, fno->fsize); file_res = l_openfilebycluster(&fatfs, &file_handle, (TCHAR*)"", fno->clust, fno->fsize);
}*/ }
void file_open(uint8_t* filename, BYTE flags) { void file_open(uint8_t* filename, BYTE flags) {
file_res = f_open(&file_handle, (TCHAR*)filename, flags); file_res = f_open(&file_handle, (TCHAR*)filename, flags);
} }
void file_close() { void file_close() {
file_res = f_close(&file_handle); file_res = f_close(&file_handle);
} }
UINT file_read() { UINT file_read() {
UINT bytes_read; UINT bytes_read;
file_res = f_read(&file_handle, file_buf, sizeof(file_buf), &bytes_read); file_res = f_read(&file_handle, file_buf, sizeof(file_buf), &bytes_read);
return bytes_read; return bytes_read;
} }
UINT file_write() { UINT file_write() {
UINT bytes_written; UINT bytes_written;
file_res = f_write(&file_handle, file_buf, sizeof(file_buf), &bytes_written); file_res = f_write(&file_handle, file_buf, sizeof(file_buf), &bytes_written);
return bytes_written; return bytes_written;
} }
UINT file_readblock(void* buf, uint32_t addr, uint16_t size) { UINT file_readblock(void* buf, uint32_t addr, uint16_t size) {
UINT bytes_read; UINT bytes_read;
file_res = f_lseek(&file_handle, addr); file_res = f_lseek(&file_handle, addr);
if(file_handle.fptr != addr) { if(file_handle.fptr != addr) {
return 0; return 0;
} }
file_res = f_read(&file_handle, buf, size, &bytes_read); file_res = f_read(&file_handle, buf, size, &bytes_read);
return bytes_read; return bytes_read;
} }
UINT file_writeblock(void* buf, uint32_t addr, uint16_t size) { UINT file_writeblock(void* buf, uint32_t addr, uint16_t size) {
UINT bytes_written; UINT bytes_written;
file_res = f_lseek(&file_handle, addr); file_res = f_lseek(&file_handle, addr);
if(file_res) return 0; if(file_res) return 0;
file_res = f_write(&file_handle, buf, size, &bytes_written); file_res = f_write(&file_handle, buf, size, &bytes_written);
return bytes_written; return bytes_written;
} }

View File

@ -32,244 +32,230 @@
#include "ff.h" #include "ff.h"
#include "smc.h" #include "smc.h"
#include "fileops.h" #include "fileops.h"
#include "crc16.h" #include "crc.h"
#include "memory.h" #include "memory.h"
#include "led.h" #include "led.h"
#include "sort.h" #include "sort.h"
uint16_t scan_flat(const char* path) { uint16_t scan_flat(const char* path) {
DIR dir; DIR dir;
FRESULT res; FRESULT res;
FILINFO fno; FILINFO fno;
fno.lfname = NULL; fno.lfname = NULL;
res = f_opendir(&dir, (TCHAR*)path); res = f_opendir(&dir, (TCHAR*)path);
uint16_t numentries = 0; uint16_t numentries = 0;
if (res == FR_OK) { if (res == FR_OK) {
for (;;) { for (;;) {
res = f_readdir(&dir, &fno); res = f_readdir(&dir, &fno);
if(res != FR_OK || fno.fname[0] == 0)break; if(res != FR_OK || fno.fname[0] == 0)break;
numentries++; numentries++;
} }
} }
return numentries; return numentries;
} }
uint16_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) { uint16_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
DIR dir; DIR dir;
FILINFO fno; FILINFO fno;
FRESULT res; FRESULT res;
uint8_t len; uint8_t len;
TCHAR* fn; TCHAR* fn;
static unsigned char depth = 0; static unsigned char depth = 0;
static uint16_t crc; static uint16_t crc;
static uint32_t db_tgt; static uint32_t db_tgt;
static uint32_t next_subdir_tgt; static uint32_t next_subdir_tgt;
static uint32_t parent_tgt; static uint32_t parent_tgt;
static uint32_t dir_end = 0; static uint32_t dir_end = 0;
static uint8_t was_empty = 0; static uint8_t was_empty = 0;
uint32_t dir_tgt; uint32_t dir_tgt;
uint16_t numentries; uint16_t numentries;
uint32_t dirsize; uint32_t dirsize;
uint8_t pass = 0; uint8_t pass = 0;
dir_tgt = this_dir_tgt; dir_tgt = this_dir_tgt;
if(depth==0) { if(depth==0) {
crc = 0; crc = 0;
db_tgt = SRAM_DB_ADDR+0x10; db_tgt = SRAM_DB_ADDR+0x10;
dir_tgt = SRAM_DIR_ADDR; dir_tgt = SRAM_DIR_ADDR;
next_subdir_tgt = SRAM_DIR_ADDR; next_subdir_tgt = SRAM_DIR_ADDR;
this_dir_tgt = SRAM_DIR_ADDR; this_dir_tgt = SRAM_DIR_ADDR;
parent_tgt = 0; parent_tgt = 0;
printf("root dir @%lx\n", dir_tgt); printf("root dir @%lx\n", dir_tgt);
} }
fno.lfsize = 255; fno.lfsize = 255;
fno.lfname = (TCHAR*)file_lfn; fno.lfname = (TCHAR*)file_lfn;
numentries=0; numentries=0;
for(pass = 0; pass < 2; pass++) { for(pass = 0; pass < 2; pass++) {
if(pass) { if(pass) {
dirsize = 4*(numentries); dirsize = 4*(numentries);
// dir_tgt_next = dir_tgt + dirsize + 4; // number of entries + end marker next_subdir_tgt += dirsize + 4;
next_subdir_tgt += dirsize + 4; if(parent_tgt) next_subdir_tgt += 4;
if(parent_tgt) next_subdir_tgt += 4; if(next_subdir_tgt > dir_end) {
if(next_subdir_tgt > dir_end) { dir_end = next_subdir_tgt;
dir_end = next_subdir_tgt; }
} printf("path=%s depth=%d ptr=%lx entries=%d parent=%lx next subdir @%lx\n", path, depth, db_tgt, numentries, parent_tgt, next_subdir_tgt);
printf("path=%s depth=%d ptr=%lx entries=%d parent=%lx next subdir @%lx\n", path, depth, db_tgt, numentries, parent_tgt, next_subdir_tgt /*dir_tgt_next*/); if(mkdb) {
// _delay_ms(50); printf("d=%d Saving %lx to Address %lx [end]\n", depth, 0L, next_subdir_tgt - 4);
if(mkdb) { sram_writelong(0L, next_subdir_tgt - 4);
printf("d=%d Saving %lx to Address %lx [end]\n", depth, 0L, next_subdir_tgt - 4); }
// _delay_ms(50); }
sram_writelong(0L, next_subdir_tgt - 4); res = f_opendir(&dir, (TCHAR*)path);
} if (res == FR_OK) {
} if(pass && parent_tgt && mkdb) {
res = f_opendir(&dir, (TCHAR*)path); /* write backlink to parent dir
if (res == FR_OK) { switch to next bank if record does not fit in current bank */
if(pass && parent_tgt && mkdb) { if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt)+sizeof(len)+4))&0xffff)) {
// write backlink to parent dir printf("switch! old=%lx ", db_tgt);
// switch to next bank if record does not fit in current bank db_tgt &= 0xffff0000;
if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt)+sizeof(len)+4))&0xffff)) { db_tgt += 0x00010000;
printf("switch! old=%lx ", db_tgt); printf("new=%lx\n", db_tgt);
db_tgt &= 0xffff0000; }
db_tgt += 0x00010000; sram_writelong((parent_tgt-SRAM_MENU_ADDR), db_tgt);
printf("new=%lx\n", db_tgt); sram_writebyte(0, db_tgt+sizeof(next_subdir_tgt));
} sram_writeblock("../\0", db_tgt+sizeof(next_subdir_tgt)+sizeof(len), 4);
sram_writelong((parent_tgt-SRAM_MENU_ADDR), db_tgt); sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x80<<24), dir_tgt);
sram_writebyte(0, db_tgt+sizeof(next_subdir_tgt)); db_tgt += sizeof(next_subdir_tgt)+sizeof(len)+4;
sram_writeblock("../\0", db_tgt+sizeof(next_subdir_tgt)+sizeof(len), 4); dir_tgt += 4;
sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x80<<24), dir_tgt); }
db_tgt += sizeof(next_subdir_tgt)+sizeof(len)+4; len = strlen((char*)path);
dir_tgt += 4; for (;;) {
} toggle_read_led();
len = strlen((char*)path); res = f_readdir(&dir, &fno);
for (;;) { if (res != FR_OK || fno.fname[0] == 0) {
toggle_read_led(); if(pass) {
res = f_readdir(&dir, &fno); if(!numentries) was_empty=1;
if (res != FR_OK || fno.fname[0] == 0) { }
if(pass) { break;
if(!numentries) was_empty=1; }
} fn = *fno.lfname ? fno.lfname : fno.fname;
break; if (*fn == '.') continue;
} if (fno.fattrib & AM_DIR) {
fn = *fno.lfname ? fno.lfname : fno.fname; numentries++;
// printf("%s\n", fn); if(pass) {
// _delay_ms(100); path[len]='/';
if (*fn == '.') continue; strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
if (fno.fattrib & AM_DIR) { depth++;
numentries++; if(mkdb) {
if(pass) { uint16_t pathlen = strlen(path);
path[len]='/'; /* write element pointer to current dir structure */
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len); printf("d=%d Saving %lx to Address %lx [dir]\n", depth, db_tgt, dir_tgt);
depth++; sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x80<<24), dir_tgt);
if(mkdb) { /* save element:
uint16_t pathlen = strlen(path); - path name
// write element pointer to current dir structure - pointer to sub dir structure */
printf("d=%d Saving %lx to Address %lx [dir]\n", depth, db_tgt, dir_tgt); if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2))&0xffff)) {
// _delay_ms(50); printf("switch! old=%lx ", db_tgt);
sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x80<<24), dir_tgt); db_tgt &= 0xffff0000;
// sram_writeblock((uint8_t*)&db_tgt, dir_tgt_save, sizeof(dir_tgt_save)); db_tgt += 0x00010000;
printf("new=%lx\n", db_tgt);
// save element: }
// - path name printf(" Saving dir descriptor to %lx tgt=%lx, path=%s\n", db_tgt, next_subdir_tgt, path);
// - pointer to sub dir structure sram_writelong((next_subdir_tgt-SRAM_MENU_ADDR), db_tgt);
if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2))&0xffff)) { sram_writebyte(len+1, db_tgt+sizeof(next_subdir_tgt));
printf("switch! old=%lx ", db_tgt); sram_writeblock(path, db_tgt+sizeof(next_subdir_tgt)+sizeof(len), pathlen);
db_tgt &= 0xffff0000; sram_writeblock("/\0", db_tgt + sizeof(next_subdir_tgt) + sizeof(len) + pathlen, 2);
db_tgt += 0x00010000; db_tgt += sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2;
printf("new=%lx\n", db_tgt); }
} parent_tgt = this_dir_tgt;
printf(" Saving dir descriptor to %lx tgt=%lx, path=%s\n", db_tgt, next_subdir_tgt, path); scan_dir(path, mkdb, next_subdir_tgt);
// _delay_ms(100); dir_tgt += 4;
sram_writelong((next_subdir_tgt-SRAM_MENU_ADDR), db_tgt); was_empty = 0;
sram_writebyte(len+1, db_tgt+sizeof(next_subdir_tgt)); depth--;
sram_writeblock(path, db_tgt+sizeof(next_subdir_tgt)+sizeof(len), pathlen); path[len]=0;
sram_writeblock("/\0", db_tgt + sizeof(next_subdir_tgt) + sizeof(len) + pathlen, 2); }
// sram_writeblock((uint8_t*)&dir_tgt, db_tgt+256, sizeof(dir_tgt)); } else {
db_tgt += sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2; SNES_FTYPE type = determine_filetype((char*)fn);
} if(type != TYPE_UNKNOWN) {
parent_tgt = this_dir_tgt; numentries++;
scan_dir(path, mkdb, next_subdir_tgt); if(pass) {
dir_tgt += 4; if(mkdb) {
// if(was_empty)dir_tgt_next += 4; snes_romprops_t romprops;
was_empty = 0; path[len]='/';
depth--; strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
path[len]=0; uint16_t pathlen = strlen(path);
} switch(type) {
} else { case TYPE_SMC:
SNES_FTYPE type = determine_filetype((char*)fn); /* file_open_by_filinfo(&fno);
if(type != TYPE_UNKNOWN) { if(file_res){
numentries++; printf("ZOMG NOOOO %d\n", file_res);
if(pass) { }
if(mkdb) { smc_id(&romprops);
snes_romprops_t romprops; file_close();
path[len]='/'; */
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len); /* write element pointer to current dir structure */
uint16_t pathlen = strlen(path); printf("d=%d Saving %lX to Address %lX [file]\n", depth, db_tgt, dir_tgt);
switch(type) { if((db_tgt&0xffff) > ((0x10000-(sizeof(romprops) + sizeof(len) + pathlen + 1))&0xffff)) {
case TYPE_SMC: printf("switch! old=%lx ", db_tgt);
// XXX file_open_by_filinfo(&fno); db_tgt &= 0xffff0000;
// XXX if(file_res){ db_tgt += 0x00010000;
// XXX printf("ZOMG NOOOO %d\n", file_res); printf("new=%lx\n", db_tgt);
// XXX _delay_ms(30); }
// XXX } sram_writelong((db_tgt-SRAM_MENU_ADDR), dir_tgt);
// XXX smc_id(&romprops); dir_tgt += 4;
// XXX file_close(); /* save element:
// _delay_ms(30); - index of last slash character
// write element pointer to current dir structure - file name */
// printf("d=%d Saving %lX to Address %lX [file]\n", depth, db_tgt, dir_tgt); /* sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); */
// _delay_ms(50); sram_writebyte(len+1, db_tgt);
if((db_tgt&0xffff) > ((0x10000-(sizeof(romprops) + sizeof(len) + pathlen + 1))&0xffff)) { sram_writeblock(path, db_tgt + sizeof(len), pathlen + 1);
printf("switch! old=%lx ", db_tgt); db_tgt += sizeof(len) + pathlen + 1;
db_tgt &= 0xffff0000; break;
db_tgt += 0x00010000; case TYPE_UNKNOWN:
printf("new=%lx\n", db_tgt); default:
} break;
sram_writelong((db_tgt-SRAM_MENU_ADDR), dir_tgt); }
// sram_writeblock((uint8_t*)&db_tgt, dir_tgt, sizeof(db_tgt)); path[len]=0;
dir_tgt += 4; /* printf("%s ", path);
// save element: _delay_ms(30); */
// - SNES header information }
// - file name } else {
sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); TCHAR* sfn = fno.fname;
sram_writebyte(len+1, db_tgt + sizeof(romprops)); while(*sfn != 0) {
sram_writeblock(path, db_tgt + sizeof(romprops) + sizeof(len), pathlen + 1); crc += crc_xmodem_update(crc, *((unsigned char*)sfn++));
db_tgt += sizeof(romprops) + sizeof(len) + pathlen + 1; }
break; }
case TYPE_UNKNOWN: }
default: /* printf("%s/%s\n", path, fn);
break; _delay_ms(50); */
} }
path[len]=0; }
// printf("%s ", path); } else uart_putc(0x30+res);
// _delay_ms(30); }
} /*printf("%x\n", crc);
} else { _delay_ms(50); */
TCHAR* sfn = fno.fname; sram_writelong(db_tgt, SRAM_DB_ADDR+4);
while(*sfn != 0) { sram_writelong(dir_end, SRAM_DB_ADDR+8);
crc += crc16_update(crc, (unsigned char*)sfn++, 1); return crc;
}
}
}
// printf("%s/%s\n", path, fn);
// _delay_ms(50);
}
}
} else uart_putc(0x30+res);
}
// printf("%x\n", crc);
// _delay_ms(50);
sram_writelong(db_tgt, SRAM_DB_ADDR+4);
sram_writelong(dir_end, SRAM_DB_ADDR+8);
return crc;
} }
SNES_FTYPE determine_filetype(char* filename) { SNES_FTYPE determine_filetype(char* filename) {
char* ext = strrchr(filename, '.'); char* ext = strrchr(filename, '.');
if(ext == NULL) if(ext == NULL)
return TYPE_UNKNOWN; return TYPE_UNKNOWN;
if(!strcasecmp(ext+1, "SMC")) { if(!strcasecmp(ext+1, "SMC")) {
return TYPE_SMC; return TYPE_SMC;
}/* later }/* later
if(!strcasecmp_P(ext+1, PSTR("SRM"))) { if(!strcasecmp_P(ext+1, PSTR("SRM"))) {
return TYPE_SRM; return TYPE_SRM;
} }
if(!strcasecmp_P(ext+1, PSTR("SPC"))) { if(!strcasecmp_P(ext+1, PSTR("SPC"))) {
return TYPE_SPC; return TYPE_SPC;
}*/ }*/
return TYPE_UNKNOWN; return TYPE_UNKNOWN;
} }
FRESULT get_db_id(uint16_t* id) { FRESULT get_db_id(uint16_t* id) {
file_open((uint8_t*)"/sd2snes/sd2snes.db", FA_READ); file_open((uint8_t*)"/sd2snes/sd2snes.db", FA_READ);
if(file_res == FR_OK) { if(file_res == FR_OK) {
file_readblock(id, 0, 2); file_readblock(id, 0, 2);
/* XXX */// *id=0xdead; /* XXX */// *id=0xdead;
file_close(); file_close();
} else { } else {
*id=0xdead; *id=0xdead;
} }
return file_res; return file_res;
} }
int get_num_dirent(uint32_t addr) { int get_num_dirent(uint32_t addr) {

View File

@ -29,10 +29,10 @@
#include "ff.h" #include "ff.h"
typedef enum { typedef enum {
TYPE_UNKNOWN = 0, /* 0 */ TYPE_UNKNOWN = 0, /* 0 */
TYPE_SMC, /* 1 */ TYPE_SMC, /* 1 */
TYPE_SRM, /* 2 */ TYPE_SRM, /* 2 */
TYPE_SPC /* 3 */ TYPE_SPC /* 3 */
} SNES_FTYPE; } SNES_FTYPE;

View File

@ -52,101 +52,99 @@
#include "led.h" #include "led.h"
#include "timer.h" #include "timer.h"
/*DWORD get_fattime(void) { /*
return 0L; DWORD get_fattime(void) {
return 0L;
}*/ }*/
void fpga_set_prog_b(uint8_t val) { void fpga_set_prog_b(uint8_t val) {
if(val) if(val)
BITBAND(PROGBREG->FIOSET, PROGBBIT) = 1; BITBAND(PROGBREG->FIOSET, PROGBBIT) = 1;
else else
BITBAND(PROGBREG->FIOCLR, PROGBBIT) = 1; BITBAND(PROGBREG->FIOCLR, PROGBBIT) = 1;
} }
void fpga_set_cclk(uint8_t val) { void fpga_set_cclk(uint8_t val) {
if(val) if(val)
BITBAND(CCLKREG->FIOSET, CCLKBIT) = 1; BITBAND(CCLKREG->FIOSET, CCLKBIT) = 1;
else else
BITBAND(CCLKREG->FIOCLR, CCLKBIT) = 1; BITBAND(CCLKREG->FIOCLR, CCLKBIT) = 1;
} }
int fpga_get_initb() { int fpga_get_initb() {
return BITBAND(INITBREG->FIOPIN, INITBBIT); return BITBAND(INITBREG->FIOPIN, INITBBIT);
} }
void fpga_init() { void fpga_init() {
/* mainly GPIO directions */ /* mainly GPIO directions */
BITBAND(CCLKREG->FIODIR, CCLKBIT) = 1; /* CCLK */ BITBAND(CCLKREG->FIODIR, CCLKBIT) = 1; /* CCLK */
BITBAND(DONEREG->FIODIR, DONEBIT) = 0; /* DONE */ BITBAND(DONEREG->FIODIR, DONEBIT) = 0; /* DONE */
BITBAND(PROGBREG->FIODIR, PROGBBIT) = 1; /* PROG_B */ BITBAND(PROGBREG->FIODIR, PROGBBIT) = 1; /* PROG_B */
BITBAND(DINREG->FIODIR, DINBIT) = 1; /* DIN */ BITBAND(DINREG->FIODIR, DINBIT) = 1; /* DIN */
BITBAND(INITBREG->FIODIR, INITBBIT) = 0; /* INIT_B */ BITBAND(INITBREG->FIODIR, INITBBIT) = 0; /* INIT_B */
LPC_GPIO2->FIOMASK1 = 0; LPC_GPIO2->FIOMASK1 = 0;
SPI_OFFLOAD=0; SPI_OFFLOAD=0;
fpga_set_cclk(0); /* initial clk=0 */ fpga_set_cclk(0); /* initial clk=0 */
} }
int fpga_get_done(void) { int fpga_get_done(void) {
return BITBAND(LPC_GPIO0->FIOPIN, 22); return BITBAND(LPC_GPIO0->FIOPIN, 22);
} }
void fpga_postinit() { void fpga_postinit() {
LPC_GPIO2->FIOMASK1 = 0; LPC_GPIO2->FIOMASK1 = 0;
} }
void fpga_pgm(uint8_t* filename) { void fpga_pgm(uint8_t* filename) {
int MAXRETRIES = 10; int MAXRETRIES = 10;
int retries = MAXRETRIES; int retries = MAXRETRIES;
do { do {
fpga_set_prog_b(0); fpga_set_prog_b(0);
uart_putc('P'); uart_putc('P');
fpga_set_prog_b(1); fpga_set_prog_b(1);
while(!fpga_get_initb()); while(!fpga_get_initb());
LPC_GPIO2->FIOMASK1 = ~(BV(0)); LPC_GPIO2->FIOMASK1 = ~(BV(0));
uart_putc('p'); uart_putc('p');
UINT bytes_read; UINT bytes_read;
// open configware file /* open configware file */
file_open(filename, FA_READ); file_open(filename, FA_READ);
if(file_res) { if(file_res) {
uart_putc('?'); uart_putc('?');
uart_putc(0x30+file_res); uart_putc(0x30+file_res);
return; return;
} }
for (;;) { for (;;) {
bytes_read = file_read(); bytes_read = file_read();
if (file_res || bytes_read == 0) break; // error or eof if (file_res || bytes_read == 0) break; /* error or eof */
for(int i=0; i<bytes_read; i++) { for(int i=0; i<bytes_read; i++) {
FPGA_SEND_BYTE_SERIAL(file_buf[i]); FPGA_SEND_BYTE_SERIAL(file_buf[i]);
} }
} }
file_close(); file_close();
} while (!fpga_get_done() && retries--); } while (!fpga_get_done() && retries--);
if(!fpga_get_done()) { if(!fpga_get_done()) {
printf("FPGA failed to configure after %d tries.\n", MAXRETRIES); printf("FPGA failed to configure after %d tries.\n", MAXRETRIES);
delay_ms(50); led_panic();
led_panic(); }
} printf("FPGA configured\n");
printf("FPGA configured\n"); fpga_postinit();
fpga_postinit();
} }
void set_mcu_ovr(uint8_t val) { void set_mcu_ovr(uint8_t val) {
if(!val) { // shared mode if(!val) {
FPGA_SPI_SLOW(); /* shared mode */
SET_MCU_OVR(); FPGA_SPI_SLOW();
// Disable SPI double speed mode -> clock = f/4 SET_MCU_OVR();
// XXX SPSR = 0; printf("SPI slow\n");
printf("SPI slow\n"); } else {
} else { // mcu only /* mcu exclusive mode */
FPGA_SPI_FAST(); FPGA_SPI_FAST();
CLR_MCU_OVR(); CLR_MCU_OVR();
// Enable SPI double speed mode -> clock = f/2 printf("SPI fast\n");
// XXX SPSR = _BV(SPI2X); }
printf("SPI fast\n");
}
} }

View File

@ -52,48 +52,48 @@
#include "timer.h" #include "timer.h"
void fpga_spi_init(void) { void fpga_spi_init(void) {
spi_init(SPI_SPEED_FPGA_FAST, SPI_FPGA); spi_init(SPI_SPEED_FPGA_FAST, SPI_FPGA);
} }
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);
FPGA_TX_BYTE((address>>16)&0xff); FPGA_TX_BYTE((address>>16)&0xff);
FPGA_TX_BYTE((address>>8)&0xff); FPGA_TX_BYTE((address>>8)&0xff);
FPGA_TX_BYTE((address)&0xff); FPGA_TX_BYTE((address)&0xff);
FPGA_DESELECT(); FPGA_DESELECT();
} }
void set_saveram_mask(uint32_t mask) { void set_saveram_mask(uint32_t mask) {
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x20); 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);
FPGA_DESELECT(); FPGA_DESELECT();
} }
void set_rom_mask(uint32_t mask) { void set_rom_mask(uint32_t mask) {
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x10); 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);
FPGA_DESELECT(); FPGA_DESELECT();
} }
void set_mapper(uint8_t val) { void set_mapper(uint8_t val) {
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x30 | (val & 0x0f)); FPGA_TX_BYTE(0x30 | (val & 0x0f));
FPGA_DESELECT(); FPGA_DESELECT();
} }
uint8_t fpga_test() { uint8_t fpga_test() {
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xF0); // TEST FPGA_TX_BYTE(0xF0); /* TEST */
FPGA_TX_BYTE(0x00); // dummy 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;
} }

View File

@ -10,27 +10,27 @@
#include <windows.h> #include <windows.h>
#include <tchar.h> #include <tchar.h>
#else /* Embedded platform */ #else /* Embedded platform */
/* These types must be 16-bit, 32-bit or larger integer */ /* These types must be 16-bit, 32-bit or larger integer */
typedef int INT; typedef int INT;
typedef unsigned int UINT; typedef unsigned int UINT;
/* These types must be 8-bit integer */ /* These types must be 8-bit integer */
typedef char CHAR; typedef char CHAR;
typedef unsigned char UCHAR; typedef unsigned char UCHAR;
typedef unsigned char BYTE; typedef unsigned char BYTE;
/* These types must be 16-bit integer */ /* These types must be 16-bit integer */
typedef short SHORT; typedef short SHORT;
typedef unsigned short USHORT; typedef unsigned short USHORT;
typedef unsigned short WORD; typedef unsigned short WORD;
typedef unsigned short WCHAR; typedef unsigned short WCHAR;
/* These types must be 32-bit integer */ /* These types must be 32-bit integer */
typedef long LONG; typedef long LONG;
typedef unsigned long ULONG; typedef unsigned long ULONG;
typedef unsigned long DWORD; typedef unsigned long DWORD;
#endif #endif

View File

@ -1,6 +1,7 @@
#include <arm/NXP/LPC17xx/LPC17xx.h> #include <arm/NXP/LPC17xx/LPC17xx.h>
#include <string.h> #include <string.h>
#include "config.h" #include "config.h"
#include "obj/autoconf.h"
#include "clock.h" #include "clock.h"
#include "uart.h" #include "uart.h"
#include "bits.h" #include "bits.h"
@ -19,6 +20,8 @@
#include "led.h" #include "led.h"
#include "sort.h" #include "sort.h"
#include "tests.h"
#define EMC0TOGGLE (3<<4) #define EMC0TOGGLE (3<<4)
#define MR0R (1<<1) #define MR0R (1<<1)
@ -56,7 +59,7 @@ int main(void) {
sd_init(); sd_init();
fpga_spi_init(); fpga_spi_init();
delay_ms(10); delay_ms(10);
printf("\n\nsd2snes mk.2\n============\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY); printf("\n\nsd2snes mk.2\n============\nfw ver.: " VER "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY);
file_init(); file_init();
/* uart_putc('S'); /* uart_putc('S');
for(p1=0; p1<8192; p1++) { for(p1=0; p1<8192; p1++) {
@ -80,7 +83,8 @@ restart:
rdyled(1); rdyled(1);
readled(0); readled(0);
writeled(0); writeled(0);
set_mcu_ovr(1); // exclusive mode /* exclusive mode */
set_mcu_ovr(1);
*fs_path=0; *fs_path=0;
uint16_t saved_dir_id; uint16_t saved_dir_id;
@ -89,14 +93,18 @@ restart:
uint16_t mem_dir_id = sram_readshort(SRAM_DIRID); uint16_t mem_dir_id = sram_readshort(SRAM_DIRID);
uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD); uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD);
if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id)) { if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id)) {
uint16_t curr_dir_id = scan_dir(fs_path, 0, 0); // generate files footprint /* generate fs footprint (interesting files only) */
uint16_t curr_dir_id = scan_dir(fs_path, 0, 0);
printf("curr dir id = %x\n", curr_dir_id); printf("curr dir id = %x\n", curr_dir_id);
if((get_db_id(&saved_dir_id) != FR_OK) // no database? /* files changed or no database found? */
|| saved_dir_id != curr_dir_id) { // files changed? // XXX if((get_db_id(&saved_dir_id) != FR_OK)
|| saved_dir_id != curr_dir_id) {
/* rebuild database */
printf("saved dir id = %x\n", saved_dir_id); printf("saved dir id = %x\n", saved_dir_id);
printf("rebuilding database..."); printf("rebuilding database...");
curr_dir_id = scan_dir(fs_path, 1, 0); // then rebuild database curr_dir_id = scan_dir(fs_path, 1, 0);
sram_writeblock(&curr_dir_id, SRAM_DB_ADDR, 2); sram_writeblock(&curr_dir_id, SRAM_DB_ADDR, 2);
uint32_t endaddr, direndaddr; uint32_t endaddr, direndaddr;
sram_readblock(&endaddr, SRAM_DB_ADDR+4, 4); sram_readblock(&endaddr, SRAM_DB_ADDR+4, 4);
@ -108,18 +116,12 @@ restart:
save_sram((uint8_t*)"/sd2snes/sd2snes.db", endaddr-SRAM_DB_ADDR, SRAM_DB_ADDR); 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); save_sram((uint8_t*)"/sd2snes/sd2snes.dir", direndaddr-(SRAM_DIR_ADDR), SRAM_DIR_ADDR);
printf("done\n"); printf("done\n");
// sram_hexdump(SRAM_DB_ADDR, 0x400);
} else { } else {
printf("saved dir id = %x\n", saved_dir_id); printf("saved dir id = %x\n", saved_dir_id);
printf("different card, consistent db, loading db...\n"); printf("different card, consistent db, loading db...\n");
load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR); load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR); load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
} }
// save_sram((uint8_t*)"/debug.smc", 0x400000, 0);
// uart_putc('[');
// load_sram((uint8_t*)"/test.srm", SRAM_SAVE_ADDR);
// uart_putc(']');
sram_writeshort(curr_dir_id, SRAM_DIRID); sram_writeshort(curr_dir_id, SRAM_DIRID);
sram_writelong(0x12345678, SRAM_SCRATCHPAD); sram_writelong(0x12345678, SRAM_SCRATCHPAD);
} else { } else {
@ -128,18 +130,18 @@ restart:
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR); load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
} }
/* load menu */
uart_putc('('); uart_putc('(');
load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR); load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR);
set_rom_mask(0x3fffff); // force mirroring off /* force memory size + mapper */
set_mapper(0x7); // menu mapper XXX set_rom_mask(0x3fffff);
set_mapper(0x7);
uart_putc(')'); uart_putc(')');
uart_putcrlf(); uart_putcrlf();
// sram_hexdump(0x7ffff0, 0x10);
// sram_hexdump(0, 0x400);
// save_sram((uint8_t*)"/sd2snes/dump", 65536, 0);
sram_writebyte(0, SRAM_CMD_ADDR); sram_writebyte(0, SRAM_CMD_ADDR);
/* shared mode */
set_mcu_ovr(0); set_mcu_ovr(0);
printf("SNES GO!\n"); printf("SNES GO!\n");
@ -150,25 +152,15 @@ restart:
while(!sram_reliable()) uart_puts("DERP"); while(!sram_reliable()) uart_puts("DERP");
printf("ok\n"); printf("ok\n");
/* uint8_t *teststring=(uint8_t*)"Wer das liest ist doof! 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; sram_hexdump(SRAM_DB_ADDR, 0x200);
uint8_t testbuf[80];
while(1) {
sram_writeblock(teststring, 0xd00000, 61);
sram_readblock(testbuf, 0xd00000, 61);
testbuf[60]=0;
printf("%p %s\n",testbuf, (char*)testbuf);
} */
while(!cmd) { while(!cmd) {
cmd=menu_main_loop(); cmd=menu_main_loop();
switch(cmd) { switch(cmd) {
case SNES_CMD_LOADROM: case SNES_CMD_LOADROM:
get_selected_name(file_lfn); get_selected_name(file_lfn);
// snes_reset(1);
set_mcu_ovr(1); set_mcu_ovr(1);
printf("Selected name: %s\n", file_lfn); printf("Selected name: %s\n", file_lfn);
load_rom(file_lfn, SRAM_ROM_ADDR); load_rom(file_lfn, SRAM_ROM_ADDR);
// save_sram((uint8_t*)"/sd2snes/test.smc", romprops.romsize_bytes, 0);
if(romprops.ramsize_bytes) { if(romprops.ramsize_bytes) {
strcpy(strrchr((char*)file_lfn, (int)'.'), ".srm"); strcpy(strrchr((char*)file_lfn, (int)'.'), ".srm");
printf("SRM file: %s\n", file_lfn); printf("SRM file: %s\n", file_lfn);
@ -185,7 +177,7 @@ while(1) {
break; break;
default: default:
printf("unknown cmd: %d\n", cmd); printf("unknown cmd: %d\n", cmd);
cmd=0; // unknown cmd: stay in loop cmd=0; /* unknown cmd: stay in loop */
break; break;
} }
} }
@ -200,7 +192,6 @@ while(1) {
if(!snes_reset_prev) { if(!snes_reset_prev) {
printf("RESET BUTTON DOWN\n"); printf("RESET BUTTON DOWN\n");
snes_reset_state=1; snes_reset_state=1;
// reset reset counter
reset_count=0; reset_count=0;
} }
} else { } else {
@ -231,37 +222,7 @@ while(1) {
} }
snes_reset_prev = snes_reset_now; snes_reset_prev = snes_reset_now;
} }
// FPGA TEST FAIL. PANIC. /* fpga test fail: panic */
led_panic(); led_panic();
while(1);
} }
void teststuff(void) {
uint8_t i=0, data;
uint32_t p1;
sram_writebyte(0x5e, 0);
sram_writebyte(0x6f, 1);
sram_writelong(0x3451451e, 4);
sram_hexdump(0x0, 0x10);
sram_hexdump(0x620000, 0x200);
while(i<10) {
FPGA_SELECT();
FPGA_TX_BYTE(0xff);
FPGA_TX_BYTE(0xff);
data=FPGA_TXRX_BYTE(i);
FPGA_DESELECT();
printf("%x %x\n", i, data);
i++;
}
while(1) {
// if((data=fpga_test())!=0xa5) printf("Unexpected FPGA test token 0x%x\n", data);
}
while (1) {
p1 = LPC_GPIO1->FIOPIN;
BITBAND(LPC_GPIO2->FIOPIN, 1) = (p1 & BV(29))>>29;
}
}

View File

@ -28,7 +28,7 @@
#include "config.h" #include "config.h"
#include "uart.h" #include "uart.h"
#include "fpga.h" #include "fpga.h"
#include "crc16.h" #include "crc.h"
#include "ff.h" #include "ff.h"
#include "fileops.h" #include "fileops.h"
#include "spi.h" #include "spi.h"
@ -42,288 +42,277 @@
char* hex = "0123456789ABCDEF"; char* hex = "0123456789ABCDEF";
void sram_hexdump(uint32_t addr, uint32_t len) { void sram_hexdump(uint32_t addr, uint32_t len) {
static uint8_t buf[16]; static uint8_t buf[16];
uint32_t ptr; uint32_t ptr;
for(ptr=0; ptr < len; ptr += 16) { for(ptr=0; ptr < len; ptr += 16) {
sram_readblock((void*)buf, ptr+addr, 16); sram_readblock((void*)buf, ptr+addr, 16);
uart_trace(buf, 0, 16); uart_trace(buf, 0, 16);
} }
} }
void sram_writebyte(uint8_t val, uint32_t addr) { void sram_writebyte(uint8_t val, uint32_t addr) {
set_mcu_addr(addr); set_mcu_addr(addr);
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x91); // WRITE FPGA_TX_BYTE(0x91); /* WRITE */
FPGA_TX_BYTE(val); FPGA_TX_BYTE(val);
FPGA_TX_BYTE(0x00); // dummy FPGA_TX_BYTE(0x00); /* dummy */
FPGA_DESELECT(); FPGA_DESELECT();
} }
uint8_t sram_readbyte(uint32_t addr) { uint8_t sram_readbyte(uint32_t addr) {
set_mcu_addr(addr); set_mcu_addr(addr);
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x81); // READ FPGA_TX_BYTE(0x81); /* READ */
FPGA_TX_BYTE(0x00); // dummy FPGA_TX_BYTE(0x00); /* dummy */
uint8_t val = FPGA_TXRX_BYTE(0x00); uint8_t val = FPGA_TXRX_BYTE(0x00);
FPGA_DESELECT(); FPGA_DESELECT();
return val; return val;
} }
void sram_writeshort(uint16_t val, uint32_t addr) { void sram_writeshort(uint16_t val, uint32_t addr) {
set_mcu_addr(addr); set_mcu_addr(addr);
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x91); // WRITE FPGA_TX_BYTE(0x91); /* WRITE */
FPGA_TX_BYTE(val&0xff); // 7-0 FPGA_TX_BYTE(val&0xff);
FPGA_TX_BYTE((val>>8)&0xff); // 15-8 FPGA_TX_BYTE((val>>8)&0xff);
FPGA_TX_BYTE(0x00); // dummy FPGA_TX_BYTE(0x00); /* dummy */
FPGA_DESELECT(); FPGA_DESELECT();
} }
void sram_writelong(uint32_t val, uint32_t addr) { void sram_writelong(uint32_t val, uint32_t addr) {
set_mcu_addr(addr); set_mcu_addr(addr);
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x91); // WRITE FPGA_TX_BYTE(0x91); /* WRITE */
FPGA_TX_BYTE(val&0xff); // 7-0 FPGA_TX_BYTE(val&0xff);
FPGA_TX_BYTE((val>>8)&0xff); // 15-8 FPGA_TX_BYTE((val>>8)&0xff);
FPGA_TX_BYTE((val>>16)&0xff); // 23-15 FPGA_TX_BYTE((val>>16)&0xff);
FPGA_TX_BYTE((val>>24)&0xff); // 31-24 FPGA_TX_BYTE((val>>24)&0xff);
FPGA_TX_BYTE(0x00); // dummy FPGA_TX_BYTE(0x00);
FPGA_DESELECT(); FPGA_DESELECT();
} }
uint16_t sram_readshort(uint32_t addr) { uint16_t sram_readshort(uint32_t addr) {
set_mcu_addr(addr); set_mcu_addr(addr);
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x81); FPGA_TX_BYTE(0x81);
FPGA_TX_BYTE(0x00); FPGA_TX_BYTE(0x00);
uint32_t val = FPGA_TXRX_BYTE(0x00);
uint32_t val = FPGA_TXRX_BYTE(0x00); val |= ((uint32_t)FPGA_TXRX_BYTE(0x00)<<8);
val |= ((uint32_t)FPGA_TXRX_BYTE(0x00)<<8); FPGA_DESELECT();
FPGA_DESELECT(); return val;
return val;
} }
uint32_t sram_readlong(uint32_t addr) { uint32_t sram_readlong(uint32_t addr) {
set_mcu_addr(addr); set_mcu_addr(addr);
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x81); FPGA_TX_BYTE(0x81);
FPGA_TX_BYTE(0x00); FPGA_TX_BYTE(0x00);
uint32_t val = FPGA_TXRX_BYTE(0x00); uint32_t val = FPGA_TXRX_BYTE(0x00);
val |= ((uint32_t)FPGA_TXRX_BYTE(0x00)<<8); val |= ((uint32_t)FPGA_TXRX_BYTE(0x00)<<8);
val |= ((uint32_t)FPGA_TXRX_BYTE(0x00)<<16); val |= ((uint32_t)FPGA_TXRX_BYTE(0x00)<<16);
val |= ((uint32_t)FPGA_TXRX_BYTE(0x00)<<24); val |= ((uint32_t)FPGA_TXRX_BYTE(0x00)<<24);
FPGA_DESELECT(); FPGA_DESELECT();
return val; return val;
} }
void sram_readlongblock(uint32_t* buf, uint32_t addr, uint16_t count) { void sram_readlongblock(uint32_t* buf, uint32_t addr, uint16_t count) {
set_mcu_addr(addr); set_mcu_addr(addr);
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x81); FPGA_TX_BYTE(0x81);
FPGA_TX_BYTE(0x00); FPGA_TX_BYTE(0x00);
uint16_t i=0; uint16_t i=0;
while(i<count) { while(i<count) {
uint32_t val = (uint32_t)FPGA_TXRX_BYTE(0x00)<<24; uint32_t val = (uint32_t)FPGA_TXRX_BYTE(0x00)<<24;
val |= ((uint32_t)FPGA_TXRX_BYTE(0x00)<<16); val |= ((uint32_t)FPGA_TXRX_BYTE(0x00)<<16);
val |= ((uint32_t)FPGA_TXRX_BYTE(0x00)<<8); val |= ((uint32_t)FPGA_TXRX_BYTE(0x00)<<8);
val |= FPGA_TXRX_BYTE(0x00); val |= FPGA_TXRX_BYTE(0x00);
buf[i++] = val; buf[i++] = val;
} }
FPGA_DESELECT(); FPGA_DESELECT();
} }
void sram_readblock(void* buf, uint32_t addr, uint16_t size) { void sram_readblock(void* buf, uint32_t addr, uint16_t size) {
uint16_t count=size; uint16_t count=size;
uint8_t* tgt = buf; uint8_t* tgt = buf;
set_mcu_addr(addr); set_mcu_addr(addr);
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x81); // READ FPGA_TX_BYTE(0x81); /* READ */
FPGA_TX_BYTE(0x00); // dummy FPGA_TX_BYTE(0x00); /* dummy */
while(count--) { while(count--) {
*(tgt++) = FPGA_TXRX_BYTE(0x00); *(tgt++) = FPGA_TXRX_BYTE(0x00);
} }
FPGA_DESELECT(); FPGA_DESELECT();
} }
void sram_writeblock(void* buf, uint32_t addr, uint16_t size) { void sram_writeblock(void* buf, uint32_t addr, uint16_t size) {
uint16_t count=size; uint16_t count=size;
uint8_t* src = buf; uint8_t* src = buf;
set_mcu_addr(addr); set_mcu_addr(addr);
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x91); // WRITE FPGA_TX_BYTE(0x91); /* WRITE */
while(count--) { while(count--) {
FPGA_TX_BYTE(*src++); FPGA_TX_BYTE(*src++);
} }
FPGA_TX_BYTE(0x00); // dummy FPGA_TX_BYTE(0x00); /* dummy */
FPGA_DESELECT(); FPGA_DESELECT();
} }
uint32_t load_rom(uint8_t* filename, uint32_t base_addr) { uint32_t load_rom(uint8_t* filename, uint32_t base_addr) {
// uint8_t dummy; UINT bytes_read;
UINT bytes_read; DWORD filesize;
DWORD filesize; UINT count=0;
UINT count=0; file_open(filename, FA_READ);
file_open(filename, FA_READ); filesize = file_handle.fsize;
filesize = file_handle.fsize; smc_id(&romprops);
smc_id(&romprops); set_mcu_addr(base_addr);
set_mcu_addr(base_addr); printf("no nervous breakdown beyond this point! or else!\n");
printf("no nervous breakdown beyond this point! or else!\n"); if(file_res) {
if(file_res) { uart_putc('?');
uart_putc('?'); uart_putc(0x30+file_res);
uart_putc(0x30+file_res); return 0;
return 0; }
} f_lseek(&file_handle, romprops.offset);
f_lseek(&file_handle, romprops.offset); FPGA_DESELECT();
FPGA_DESELECT(); for(;;) {
for(;;) { /* SPI_OFFLOAD=1; */
// SPI_OFFLOAD=1; bytes_read = file_read();
bytes_read = file_read(); if (file_res || !bytes_read) break;
if (file_res || !bytes_read) break; if(!(count++ % 32)) {
if(!(count++ % 32)) { toggle_read_led();
toggle_read_led(); /* bounce_busy_led(); */
// bounce_busy_led(); uart_putc('.');
uart_putc('.'); }
} FPGA_SELECT();
FPGA_SELECT(); FPGA_TX_BYTE(0x91); /* write w/ increment */
FPGA_TX_BYTE(0x91); // write w/ increment for(int j=0; j<bytes_read; j++) {
if(!(count++ % 8)) { FPGA_TX_BYTE(file_buf[j]);
// toggle_busy_led(); }
// bounce_busy_led(); FPGA_TX_BYTE(0x00); /* dummy tx for increment+write pulse */
uart_putc('.'); FPGA_DESELECT();
} }
for(int j=0; j<bytes_read; j++) { file_close();
FPGA_TX_BYTE(file_buf[j]); set_mapper(romprops.mapper_id);
/* SPDR = file_buf[j]; printf("rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id);
loop_until_bit_is_set(SPSR, SPIF);
dummy = SPDR;*/
}
FPGA_TX_BYTE(0x00); // dummy tx for increment+write pulse */
FPGA_DESELECT();
}
file_close();
set_mapper(romprops.mapper_id);
printf("rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id);
uint32_t rammask; uint32_t rammask;
uint32_t rommask; uint32_t rommask;
if(filesize > (romprops.romsize_bytes + romprops.offset)) { if(filesize > (romprops.romsize_bytes + romprops.offset)) {
romprops.romsize_bytes <<= 1; romprops.romsize_bytes <<= 1;
} }
if(romprops.header.ramsize == 0) { if(romprops.header.ramsize == 0) {
rammask = 0; rammask = 0;
} else { } else {
rammask = romprops.ramsize_bytes - 1; rammask = romprops.ramsize_bytes - 1;
} }
rommask = romprops.romsize_bytes - 1; rommask = romprops.romsize_bytes - 1;
printf("ramsize=%x rammask=%lx\nromsize=%x rommask=%lx\n", romprops.header.ramsize, rammask, romprops.header.romsize, rommask); printf("ramsize=%x rammask=%lx\nromsize=%x rommask=%lx\n", romprops.header.ramsize, rammask, romprops.header.romsize, rommask);
set_saveram_mask(rammask); set_saveram_mask(rammask);
set_rom_mask(rommask); set_rom_mask(rommask);
return (uint32_t)filesize; return (uint32_t)filesize;
} }
uint32_t load_sram(uint8_t* filename, uint32_t base_addr) { uint32_t load_sram(uint8_t* filename, uint32_t base_addr) {
set_mcu_addr(base_addr); set_mcu_addr(base_addr);
UINT bytes_read; UINT bytes_read;
DWORD filesize; DWORD filesize;
file_open(filename, FA_READ); file_open(filename, FA_READ);
filesize = file_handle.fsize; filesize = file_handle.fsize;
if(file_res) return 0; if(file_res) return 0;
for(;;) { for(;;) {
bytes_read = file_read(); bytes_read = file_read();
if (file_res || !bytes_read) break; if (file_res || !bytes_read) break;
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x91); FPGA_TX_BYTE(0x91);
for(int j=0; j<bytes_read; j++) { for(int j=0; j<bytes_read; j++) {
FPGA_TX_BYTE(file_buf[j]); FPGA_TX_BYTE(file_buf[j]);
} }
FPGA_TX_BYTE(0x00); // dummy tx FPGA_TX_BYTE(0x00); /* dummy tx */
FPGA_DESELECT(); FPGA_DESELECT();
} }
file_close(); file_close();
return (uint32_t)filesize; return (uint32_t)filesize;
} }
void save_sram(uint8_t* 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 count = 0;
uint32_t num = 0; uint32_t num = 0;
FPGA_DESELECT(); FPGA_DESELECT();
file_open(filename, FA_CREATE_ALWAYS | FA_WRITE); file_open(filename, FA_CREATE_ALWAYS | FA_WRITE);
if(file_res) { if(file_res) {
uart_putc(0x30+file_res); uart_putc(0x30+file_res);
} }
while(count<sram_size) { while(count<sram_size) {
set_mcu_addr(base_addr+count); set_mcu_addr(base_addr+count);
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x81); // read FPGA_TX_BYTE(0x81); /* read */
FPGA_TX_BYTE(0); // dummy FPGA_TX_BYTE(0x00); /* dummy */
for(int j=0; j<sizeof(file_buf); j++) { for(int j=0; j<sizeof(file_buf); j++) {
file_buf[j] = FPGA_TXRX_BYTE(0x00); file_buf[j] = FPGA_TXRX_BYTE(0x00);
count++; count++;
} }
FPGA_DESELECT(); FPGA_DESELECT();
num = file_write(); num = file_write();
if(file_res) { if(file_res) {
uart_putc(0x30+file_res); uart_putc(0x30+file_res);
} }
} }
file_close(); file_close();
} }
uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size) { uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size) {
uint8_t data; uint8_t data;
uint32_t count; uint32_t count;
uint16_t crc; uint16_t crc;
crc=0; crc=0;
crc_valid=1; crc_valid=1;
set_mcu_addr(base_addr); set_mcu_addr(base_addr);
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x81); FPGA_TX_BYTE(0x81);
FPGA_TX_BYTE(0x00); FPGA_TX_BYTE(0x00);
for(count=0; count<size; count++) { for(count=0; count<size; count++) {
data = FPGA_TXRX_BYTE(0x00); data = FPGA_TXRX_BYTE(0x00);
if(get_snes_reset()) { if(get_snes_reset()) {
crc_valid = 0; crc_valid = 0;
break; break;
} }
crc += crc16_update(crc, &data, 1); crc += crc_xmodem_update(crc, data);
} }
FPGA_DESELECT(); FPGA_DESELECT();
return crc; return crc;
} }
uint8_t sram_reliable() { uint8_t sram_reliable() {
uint16_t score=0; uint16_t score=0;
uint32_t val; uint32_t val;
// uint32_t val = sram_readlong(SRAM_SCRATCHPAD); uint8_t result = 0;
uint8_t result = 0; /*while(score<SRAM_RELIABILITY_SCORE) {
/* while(score<SRAM_RELIABILITY_SCORE) { if(sram_readlong(SRAM_SCRATCHPAD)==val) {
if(sram_readlong(SRAM_SCRATCHPAD)==val) { score++;
score++; } else {
} else { set_pwr_led(0);
set_pwr_led(0); score=0;
score=0; }
} } */
}*/ for(uint16_t i = 0; i < SRAM_RELIABILITY_SCORE; i++) {
for(uint16_t i = 0; i < SRAM_RELIABILITY_SCORE; i++) { val=sram_readlong(SRAM_SCRATCHPAD);
val=sram_readlong(SRAM_SCRATCHPAD); if(val==0x12345678) {
if(val==0x12345678) { score++;
score++; /* } else {
// } else { dprintf("i=%d val=%08lX\n", i, val); */
// dprintf("i=%d val=%08lX\n", i, val); }
} }
} if(score<SRAM_RELIABILITY_SCORE) {
if(score<SRAM_RELIABILITY_SCORE) { result = 0;
result = 0; /* dprintf("score=%d\n", score); */
// dprintf("score=%d\n", score); } else {
} else { result = 1;
result = 1; }
} rdyled(result);
rdyled(result); return result;
return result;
} }

View File

@ -28,6 +28,7 @@
#define MEMORY_H #define MEMORY_H
#include <arm/NXP/LPC17xx/LPC17xx.h> #include <arm/NXP/LPC17xx/LPC17xx.h>
#include "smc.h"
#define SRAM_ROM_ADDR (0x000000L) #define SRAM_ROM_ADDR (0x000000L)
#define SRAM_SAVE_ADDR (0xE00000L) #define SRAM_SAVE_ADDR (0xE00000L)
@ -42,22 +43,21 @@
#define SRAM_DIRID (0xFFFFF0L) #define SRAM_DIRID (0xFFFFF0L)
#define SRAM_RELIABILITY_SCORE (0x100) #define SRAM_RELIABILITY_SCORE (0x100)
uint32_t load_rom(uint8_t* filename, uint32_t base_addr); uint32_t load_rom(uint8_t* filename, uint32_t base_addr);
uint32_t load_sram(uint8_t* filename, uint32_t base_addr); uint32_t load_sram(uint8_t* filename, uint32_t base_addr);
void sram_hexdump(uint32_t addr, uint32_t len); void sram_hexdump(uint32_t addr, uint32_t len);
uint8_t sram_readbyte(uint32_t addr); uint8_t sram_readbyte(uint32_t addr);
uint16_t sram_readshort(uint32_t addr); uint16_t sram_readshort(uint32_t addr);
uint32_t sram_readlong(uint32_t addr); uint32_t sram_readlong(uint32_t addr);
void sram_writebyte(uint8_t val, uint32_t addr); void sram_writebyte(uint8_t val, uint32_t addr);
void sram_writeshort(uint16_t val, uint32_t addr); void sram_writeshort(uint16_t val, uint32_t addr);
void sram_writelong(uint32_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_readblock(void* buf, uint32_t addr, uint16_t size);
void sram_readlongblock(uint32_t* buf, uint32_t addr, uint16_t count); void sram_readlongblock(uint32_t* buf, uint32_t addr, uint16_t count);
void sram_writeblock(void* buf, uint32_t addr, uint16_t size); void sram_writeblock(void* buf, uint32_t addr, uint16_t size);
void save_sram(uint8_t* 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); uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size);
uint8_t sram_reliable(void); uint8_t sram_reliable(void);
#include "smc.h" snes_romprops_t romprops;
snes_romprops_t romprops;
#endif #endif

View File

@ -5,9 +5,9 @@
#include "bits.h" #include "bits.h"
#define PCUART3 (25) #define PCUART3 (25)
#define PCUART0 (3) #define PCUART0 (3)
#define PCTIM3 (23) #define PCTIM3 (23)
void power_init(void); void power_init(void);

234
src/smc.c
View File

@ -31,143 +31,139 @@
uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0}; uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0};
uint8_t countAllASCII(uint8_t* data, int size) { uint8_t countAllASCII(uint8_t* data, int size) {
uint8_t res = 0; uint8_t res = 0;
do { do {
size--; size--;
if(data[size] >= 0x20 && data[size] <= 0x7e) { if(data[size] >= 0x20 && data[size] <= 0x7e) {
res++; res++;
} }
} while (size); } while (size);
return res; return res;
} }
uint8_t countAllJISX0201(uint8_t* data, int size) { uint8_t countAllJISX0201(uint8_t* data, int size) {
uint8_t res = 0; uint8_t res = 0;
do { do {
size--; size--;
if((data[size] >= 0x20 && data[size] <= 0x7e) if((data[size] >= 0x20 && data[size] <= 0x7e)
||(data[size] >= 0xa1 && data[size] <= 0xdf)) { ||(data[size] >= 0xa1 && data[size] <= 0xdf)) {
res++; res++;
} }
} while (size); } while (size);
return res; return res;
} }
uint8_t isFixed(uint8_t* data, int size, uint8_t value) { uint8_t isFixed(uint8_t* data, int size, uint8_t value) {
uint8_t res = 1; uint8_t res = 1;
do { do {
size--; size--;
if(data[size] != value) { if(data[size] != value) {
res = 0; res = 0;
} }
} while (size); } while (size);
return res; return res;
} }
uint8_t checkChksum(uint16_t cchk, uint16_t chk) { uint8_t checkChksum(uint16_t cchk, uint16_t chk) {
uint32_t sum = cchk + chk; uint32_t sum = cchk + chk;
uint8_t res = 0; uint8_t res = 0;
if(sum==0x0000ffff) { if(sum==0x0000ffff) {
res = 0x10; res = 0x10;
} }
return res; return res;
} }
void smc_id(snes_romprops_t* props) { void smc_id(snes_romprops_t* props) {
uint8_t score, maxscore=1, score_idx=2; // assume LoROM uint8_t score, maxscore=1, score_idx=2; /* assume LoROM */
snes_header_t* header = &(props->header); snes_header_t* header = &(props->header);
for(uint8_t num = 0; num < 6; num++) { for(uint8_t num = 0; num < 6; num++) {
if(!file_readblock(header, hdr_addr[num], sizeof(snes_header_t)) if(!file_readblock(header, hdr_addr[num], sizeof(snes_header_t))
|| file_res) { || file_res) {
// dprintf("uh oh... %d\n", file_res); score = 0;
// _delay_ms(30); } else {
score = 0; score = smc_headerscore(header)/(1+(num&1));
} else { if((file_handle.fsize & 0x2ff) == 0x200) {
score = smc_headerscore(header)/(1+(num&1)); if(num&1) {
if((file_handle.fsize & 0x2ff) == 0x200) { score+=20;
if(num&1) { } else {
score+=20; score=0;
} else { }
score=0; } else {
} if(!(num&1)) {
} else { score+=20;
if(!(num&1)) { } else {
score+=20; score=0;
} else { }
score=0; }
} }
} /* dprintf("%d: offset = %lX; score = %d\n", num, hdr_addr[num], score); */
} if(score>=maxscore) {
// dprintf("%d: offset = %lX; score = %d\n", num, hdr_addr[num], score); score_idx=num;
// _delay_ms(100); maxscore=score;
if(score>=maxscore) { }
score_idx=num; }
maxscore=score;
}
}
if(score_idx & 1) { if(score_idx & 1) {
props->offset = 0x200; props->offset = 0x200;
} else { } else {
props->offset = 0; props->offset = 0;
} }
// restore the chosen one /* restore the chosen one */
// dprintf("winner is %d\n", score_idx); /*dprintf("winner is %d\n", score_idx); */
// _delay_ms(30); file_readblock(header, hdr_addr[score_idx], sizeof(snes_header_t));
file_readblock(header, hdr_addr[score_idx], sizeof(snes_header_t)); switch(header->map & 0xef) {
switch(header->map & 0xef) { case 0x20:
case 0x20: props->mapper_id = 1;
props->mapper_id = 1; break;
break; case 0x21:
case 0x21: props->mapper_id = 0;
props->mapper_id = 0; break;
break; case 0x25:
case 0x25: props->mapper_id = 2;
props->mapper_id = 2; break;
break; default: /* invalid/unsupported mapper, use header location */
default: // invalid/unsupported mapper, use header location switch(score_idx) {
switch(score_idx) { case 0:
case 0: case 1:
case 1: props->mapper_id = 0;
props->mapper_id = 0; break;
break; case 2:
case 2: case 3:
case 3: props->mapper_id = 1;
props->mapper_id = 1; break;
break; case 4:
case 4: case 5:
case 5: props->mapper_id = 2;
props->mapper_id = 2; break;
break; default:
default: props->mapper_id = 1; // whatever
props->mapper_id = 1; // whatever }
} }
} if(header->romsize == 0 || header->romsize > 13) {
if(header->romsize == 0 || header->romsize > 13) { header->romsize = 13;
header->romsize = 13; }
} props->ramsize_bytes = (uint32_t)1024 << header->ramsize;
props->ramsize_bytes = (uint32_t)1024 << header->ramsize; props->romsize_bytes = (uint32_t)1024 << header->romsize;
props->romsize_bytes = (uint32_t)1024 << header->romsize; props->expramsize_bytes = (uint32_t)1024 << header->expramsize;
props->expramsize_bytes = (uint32_t)1024 << header->expramsize; /*dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); */
// dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); if(props->ramsize_bytes > 32768 || props->ramsize_bytes < 2048) {
if(props->ramsize_bytes > 32768 || props->ramsize_bytes < 2048) { props->ramsize_bytes = 0;
props->ramsize_bytes = 0; }
} /*dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); */
// dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); f_lseek(&file_handle, 0);
f_lseek(&file_handle, 0);
} }
uint8_t smc_headerscore(snes_header_t* header) { uint8_t smc_headerscore(snes_header_t* header) {
uint8_t score=0; uint8_t score=0;
score += countAllASCII(header->maker, sizeof(header->maker)); score += countAllASCII(header->maker, sizeof(header->maker));
score += countAllASCII(header->gamecode, sizeof(header->gamecode)); score += countAllASCII(header->gamecode, sizeof(header->gamecode));
score += isFixed(header->fixed_00, sizeof(header->fixed_00), 0x00); score += isFixed(header->fixed_00, sizeof(header->fixed_00), 0x00);
score += countAllJISX0201(header->name, sizeof(header->name)); score += countAllJISX0201(header->name, sizeof(header->name));
score += 3*isFixed(&header->fixed_33, sizeof(header->fixed_33), 0x33); score += 3*isFixed(&header->fixed_33, sizeof(header->fixed_33), 0x33);
score += checkChksum(header->cchk, header->chk); score += checkChksum(header->cchk, header->chk);
return score; return score;
} }

View File

@ -28,32 +28,32 @@
#define SMC_H #define SMC_H
typedef struct _snes_header { typedef struct _snes_header {
uint8_t maker[2]; // 0xB0 uint8_t maker[2]; /* 0xB0 */
uint8_t gamecode[4]; // 0xB2 uint8_t gamecode[4]; /* 0xB2 */
uint8_t fixed_00[7]; // 0xB6 uint8_t fixed_00[7]; /* 0xB6 */
uint8_t expramsize; // 0xBD uint8_t expramsize; /* 0xBD */
uint8_t specver; // 0xBE uint8_t specver; /* 0xBE */
uint8_t carttype2; // 0xBF uint8_t carttype2; /* 0xBF */
uint8_t name[21]; // 0xC0 uint8_t name[21]; /* 0xC0 */
uint8_t map; // 0xD5 uint8_t map; /* 0xD5 */
uint8_t carttype; // 0xD6 uint8_t carttype; /* 0xD6 */
uint8_t romsize; // 0xD7 uint8_t romsize; /* 0xD7 */
uint8_t ramsize; // 0xD8 uint8_t ramsize; /* 0xD8 */
uint8_t destcode; // 0xD9 uint8_t destcode; /* 0xD9 */
uint8_t fixed_33; // 0xDA uint8_t fixed_33; /* 0xDA */
uint8_t ver; // 0xDB uint8_t ver; /* 0xDB */
uint16_t cchk; // 0xDC uint16_t cchk; /* 0xDC */
uint16_t chk; // 0xDE uint16_t chk; /* 0xDE */
} snes_header_t; } snes_header_t;
typedef struct _snes_romprops { typedef struct _snes_romprops {
uint16_t offset; // start of actual ROM image uint16_t offset; /* start of actual ROM image */
uint8_t mapper_id; // FPGA mapper uint8_t mapper_id; /* FPGA mapper */
uint8_t pad1; // for alignment uint8_t pad1; /* for alignment */
uint32_t expramsize_bytes; // ExpRAM size in bytes uint32_t expramsize_bytes; /* ExpRAM size in bytes */
uint32_t ramsize_bytes; // CartRAM size in bytes uint32_t ramsize_bytes; /* CartRAM size in bytes */
uint32_t romsize_bytes; // ROM size in bytes (rounded up) uint32_t romsize_bytes; /* ROM size in bytes (rounded up) */
snes_header_t header; // original header from ROM image snes_header_t header; /* original header from ROM image */
} snes_romprops_t; } snes_romprops_t;
void smc_id(snes_romprops_t*); void smc_id(snes_romprops_t*);

View File

@ -38,10 +38,10 @@
uint8_t initloop=1; uint8_t initloop=1;
uint32_t saveram_crc, saveram_crc_old; uint32_t saveram_crc, saveram_crc_old;
void snes_init() { void snes_init() {
/* put reset level on reset pin */ /* put reset level on reset pin */
BITBAND(SNES_RESET_REG->FIOCLR, SNES_RESET_BIT) = 1; BITBAND(SNES_RESET_REG->FIOCLR, SNES_RESET_BIT) = 1;
/* reset the SNES */ /* reset the SNES */
snes_reset(1); snes_reset(1);
} }
/* /*
@ -50,7 +50,7 @@ void snes_init() {
* state: put SNES in reset state when 1, release when 0 * state: put SNES in reset state when 1, release when 0
*/ */
void snes_reset(int state) { void snes_reset(int state) {
BITBAND(SNES_RESET_REG->FIODIR, SNES_RESET_BIT) = state; BITBAND(SNES_RESET_REG->FIODIR, SNES_RESET_BIT) = state;
} }
/* /*
@ -59,7 +59,7 @@ void snes_reset(int state) {
* returns: 1 when reset, 0 when not reset * returns: 1 when reset, 0 when not reset
*/ */
uint8_t get_snes_reset() { uint8_t get_snes_reset() {
return !BITBAND(SNES_RESET_REG->FIOPIN, SNES_RESET_BIT); return !BITBAND(SNES_RESET_REG->FIOPIN, SNES_RESET_BIT);
} }
/* /*
@ -69,44 +69,44 @@ uint8_t get_snes_reset() {
uint32_t diffcount = 0, samecount = 0, didnotsave = 0; uint32_t diffcount = 0, samecount = 0, didnotsave = 0;
uint8_t sram_valid = 0; uint8_t sram_valid = 0;
void snes_main_loop() { void snes_main_loop() {
if(!romprops.ramsize_bytes)return; if(!romprops.ramsize_bytes)return;
if(initloop) { if(initloop) {
saveram_crc_old = calc_sram_crc(SRAM_SAVE_ADDR, romprops.ramsize_bytes); saveram_crc_old = calc_sram_crc(SRAM_SAVE_ADDR, romprops.ramsize_bytes);
initloop=0; initloop=0;
} }
saveram_crc = calc_sram_crc(SRAM_SAVE_ADDR, romprops.ramsize_bytes); saveram_crc = calc_sram_crc(SRAM_SAVE_ADDR, romprops.ramsize_bytes);
sram_valid = sram_reliable(); sram_valid = sram_reliable();
if(crc_valid && sram_valid) { if(crc_valid && sram_valid) {
if(saveram_crc != saveram_crc_old) { if(saveram_crc != saveram_crc_old) {
if(samecount) { if(samecount) {
diffcount=1; diffcount=1;
} else { } else {
diffcount++; diffcount++;
didnotsave++; didnotsave++;
} }
samecount=0; samecount=0;
} }
if(saveram_crc == saveram_crc_old) { if(saveram_crc == saveram_crc_old) {
samecount++; samecount++;
} }
if(diffcount>=1 && samecount==5) { if(diffcount>=1 && samecount==5) {
printf("SaveRAM CRC: 0x%04lx; saving\n", saveram_crc); printf("SaveRAM CRC: 0x%04lx; saving\n", saveram_crc);
writeled(1); writeled(1);
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR); save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
writeled(0); writeled(0);
didnotsave=0; didnotsave=0;
} }
if(didnotsave>50) { if(didnotsave>50) {
printf("periodic save (sram contents keep changing...)\n"); printf("periodic save (sram contents keep changing...)\n");
diffcount=0; diffcount=0;
writeled(1); writeled(1);
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR); save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
didnotsave=0; didnotsave=0;
writeled(0); writeled(0);
} }
saveram_crc_old = saveram_crc; saveram_crc_old = saveram_crc;
} }
printf("crc_valid=%d sram_valid=%d diffcount=%ld samecount=%ld, didnotsave=%ld\n", crc_valid, sram_valid, diffcount, samecount, didnotsave); printf("crc_valid=%d sram_valid=%d diffcount=%ld samecount=%ld, didnotsave=%ld\n", crc_valid, sram_valid, diffcount, samecount, didnotsave);
} }
/* /*
@ -114,22 +114,22 @@ void snes_main_loop() {
* monitors menu selection. return when selection was made. * monitors menu selection. return when selection was made.
*/ */
uint8_t menu_main_loop() { uint8_t menu_main_loop() {
uint8_t cmd = 0; uint8_t cmd = 0;
sram_writebyte(0, SRAM_CMD_ADDR); sram_writebyte(0, SRAM_CMD_ADDR);
while(!cmd) { while(!cmd) {
if(!get_snes_reset()) { if(!get_snes_reset()) {
while(!sram_reliable())printf("hurr\n");; while(!sram_reliable())printf("hurr\n");;
cmd = sram_readbyte(SRAM_CMD_ADDR); cmd = sram_readbyte(SRAM_CMD_ADDR);
} }
if(get_snes_reset()) { if(get_snes_reset()) {
cmd = 0; cmd = 0;
} }
} }
return cmd; return cmd;
} }
void get_selected_name(uint8_t* fn) { void get_selected_name(uint8_t* fn) {
uint32_t addr = sram_readlong(SRAM_PARAM_ADDR); uint32_t addr = sram_readlong(SRAM_PARAM_ADDR);
printf("fd addr=%lx\n", addr); printf("fd addr=%lx\n", addr);
sram_readblock(fn, addr+0x41+SRAM_MENU_ADDR, 256); sram_readblock(fn, addr+1+SRAM_MENU_ADDR, 256);
} }

View File

@ -41,9 +41,7 @@ int sort_cmp_elem(const void* elem1, const void* elem2) {
uint32_t el2 = *(uint32_t*)elem2; uint32_t el2 = *(uint32_t*)elem2;
sort_getstring_for_dirent(sort_str1, el1); sort_getstring_for_dirent(sort_str1, el1);
sort_getstring_for_dirent(sort_str2, el2); sort_getstring_for_dirent(sort_str2, el2);
//sort_getlong_for_dirent(sort_long1, elem1); /*printf("i1=%d i2=%d elem1=%lx elem2=%lx ; compare %s --- %s\n", index1, index2, elem1, elem2, sort_str1, sort_str2); */
//sort_getlong_for_dirent(sort_long2, elem2);
// printf("i1=%d i2=%d elem1=%lx elem2=%lx ; compare %s --- %s\n", index1, index2, elem1, elem2, sort_str1, sort_str2);
if ((el1 & 0x80000000) && !(el2 & 0x80000000)) { if ((el1 & 0x80000000) && !(el2 & 0x80000000)) {
return -1; return -1;
@ -58,7 +56,7 @@ int sort_cmp_elem(const void* elem1, const void* elem2) {
if(cmp_i==8) { if(cmp_i==8) {
return 0; return 0;
} }
return sort_long1[cmp_i]-sort_long2[cmp_i];*/ return sort_long1[cmp_i]-sort_long2[cmp_i]; */
return strcasecmp(sort_str1, sort_str2); return strcasecmp(sort_str1, sort_str2);
} }
@ -70,32 +68,29 @@ stat_getstring++;
sram_readblock(ptr, addr+0x6+SRAM_MENU_ADDR, 20); sram_readblock(ptr, addr+0x6+SRAM_MENU_ADDR, 20);
} else { } else {
/* is file link, name offset 65 */ /* is file link, name offset 65 */
sram_readblock(ptr, addr+0x41+SRAM_MENU_ADDR, 20); sram_readblock(ptr, addr+1+SRAM_MENU_ADDR, 20);
} }
ptr[20]=0; ptr[20]=0;
} }
void sort_heapify(uint32_t addr, unsigned int i, unsigned int heapsize) void sort_heapify(uint32_t addr, unsigned int i, unsigned int heapsize)
{ {
while(1) while(1) {
{ unsigned int l = 2*i+1;
unsigned int l = 2*i+1; unsigned int r = 2*i+2;
unsigned int r = 2*i+2; unsigned int largest = (l < heapsize && sort_cmp_idx(addr, i, l) < 0) ? l : i;
unsigned int largest = (l < heapsize && sort_cmp_idx(addr, i, l) < 0) ? l : i; if(r < heapsize && sort_cmp_idx(addr, largest, r) < 0)
largest = r;
if(r < heapsize && sort_cmp_idx(addr, largest, r) < 0) if(largest != i) {
largest = r; uint32_t tmp = sort_get_elem(addr, i);
sort_put_elem(addr, i, sort_get_elem(addr, largest));
if(largest != i) sort_put_elem(addr, largest, tmp);
{ i = largest;
uint32_t tmp = sort_get_elem(addr, i);
sort_put_elem(addr, i, sort_get_elem(addr, largest));
sort_put_elem(addr, largest, tmp);
i = largest;
}
else break;
} }
else break;
}
} }
void sort_dir(uint32_t addr, unsigned int size) void sort_dir(uint32_t addr, unsigned int size)
@ -116,10 +111,10 @@ void ext_heapsort(uint32_t addr, unsigned int size) {
for(unsigned int i = size/2; i > 0;) sort_heapify(addr, --i, size); for(unsigned int i = size/2; i > 0;) sort_heapify(addr, --i, size);
for(unsigned int i = size-1; i>0; --i) { for(unsigned int i = size-1; i>0; --i) {
uint32_t tmp = sort_get_elem(addr, 0); uint32_t tmp = sort_get_elem(addr, 0);
sort_put_elem(addr, 0, sort_get_elem(addr, i)); sort_put_elem(addr, 0, sort_get_elem(addr, i));
sort_put_elem(addr, i, tmp); sort_put_elem(addr, i, tmp);
sort_heapify(addr, 0, i); sort_heapify(addr, 0, i);
} }
} }

View File

@ -16,7 +16,7 @@
volatile tick_t ticks; volatile tick_t ticks;
void __attribute__((weak,noinline)) SysTick_Hook(void) { void __attribute__((weak,noinline)) SysTick_Hook(void) {
// Empty function for hooking the systick handler /* Empty function for hooking the systick handler */
} }
/* Systick interrupt handler */ /* Systick interrupt handler */
@ -30,7 +30,7 @@ void timer_init(void) {
BITBAND(LPC_SC->PCONP, PCRIT) = 1; BITBAND(LPC_SC->PCONP, PCRIT) = 1;
/* clear RIT mask */ /* clear RIT mask */
LPC_RIT->RIMASK = 0; //xffffffff; LPC_RIT->RIMASK = 0; /*xffffffff;*/
/* PCLK = CCLK */ /* PCLK = CCLK */
BITBAND(LPC_SC->PCLKSEL1, 26) = 1; BITBAND(LPC_SC->PCLKSEL1, 26) = 1;

View File

@ -91,13 +91,13 @@ static uint32_t baud2divisor(unsigned int baudrate) {
int_ratio = (int)f_ratio; int_ratio = (int)f_ratio;
error=(f_ratio*1000)-(int_ratio*1000); error=(f_ratio*1000)-(int_ratio*1000);
if(error>990) { if(error>990) {
int_ratio++; int_ratio++;
} else if(error>10) { } else if(error>10) {
f_fr=1.5; f_fr=1.5;
f_dl=f_pclk / (16 * baudrate * (f_fr)); f_dl=f_pclk / (16 * baudrate * (f_fr));
dl = (int)f_dl; dl = (int)f_dl;
f_fr=f_pclk / (16 * baudrate * dl); f_fr=f_pclk / (16 * baudrate * dl);
fract_ratio = uart_lookupratio(f_fr); fract_ratio = uart_lookupratio(f_fr);
} }
if(!dl) { if(!dl) {
return int_ratio; return int_ratio;