firmware: adjustments for Mk.II Rev.C; enable timesetting from SNES menu

This commit is contained in:
ikari 2011-03-14 01:45:34 +01:00
parent 9af83658e7
commit bfe9a91d07
34 changed files with 2811 additions and 2564 deletions

View File

@ -55,7 +55,7 @@ TARGET = $(OBJDIR)/sd2snes
# 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 spi.c fileops.c rtc.c fpga.c fpga_spi.c snes.c smc.c memory.c filetypes.c faulthandler.c sort.c crc32.c cic.c cli.c xmodem.c irq.c rle.c sdnative.c msu1.c
SRC = main.c ff.c ccsbcs.c clock.c uart.c power.c led.c timer.c printf.c spi.c fileops.c rtc.c fpga.c fpga_spi.c snes.c smc.c memory.c filetypes.c faulthandler.c sort.c crc32.c cic.c cli.c xmodem.c irq.c rle.c sdnative.c msu1.c crc16.c
# usbcontrol.c usb_hid.c usbhw_lpc.c usbinit.c usbstdreq.c
@ -215,12 +215,11 @@ sym: $(TARGET).sym
# cp $(TARGET).bin /mbed/hw_LPC1768.bin
program: bin
program: build
utils/lpcchksum $(TARGET).bin
openocd -f openocd-usb.cfg -f lpc1754.cfg -f flash.cfg
make -C bootldr program
debug: bin
debug: build
openocd -f openocd-usb.cfg -f lpc1754.cfg
reset:

View File

@ -55,7 +55,7 @@ TARGET = $(OBJDIR)/sd2snes_bootldr
# List C source files here. (C dependencies are automatically generated.)
SRC = timer.c main.c ff.c clock.c uart.c power.c led.c faulthandler.c crc32.c sdnative.c fileops.c iap.c printf.c crc.c
SRC = timer.c main.c ff.c clock.c uart.c power.c led.c faulthandler.c crc16.c crc32.c sdnative.c fileops.c iap.c printf.c
# usbcontrol.c usb_hid.c usbhw_lpc.c usbinit.c usbstdreq.c
@ -67,7 +67,7 @@ SRC = timer.c main.c ff.c clock.c uart.c power.c led.c faulthandler.c crc32.c sd
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC = startup.S
ASRC = startup.S crc.S
# Optimization level, can be [0, 1, 2, 3, s].

View File

@ -5,17 +5,18 @@
// #define DEBUG_IRQ
// #define DEBUG_MSU1
//#define DEBUG_BL
#ifdef DEBUG_BL
#define DBG_BL
#ifdef DEBUG_UART
#define DBG_UART
#else
#define DBG_BL while(0)
#define DBG_UART while(0)
#endif
#define DBG_BL while(0)
#define FW_START (0x00002000L)
#define FLASH_SECTORS (17)
#define VER "0.0.1(NSFW)"
#define IN_AHBRAM __attribute__ ((section(".ahbram")))
@ -29,10 +30,10 @@
#define SD_CHANGE_CLR() do {LPC_GPIOINT->IO2IntClr = BV(SD_DT_BIT);} while(0)
#define SD_DT_REG LPC_GPIO2
#define SD_DT_BIT 3
#define SD_WP_REG LPC_GPIO2
#define SD_WP_BIT 4
#define SD_DT_REG LPC_GPIO0
#define SD_DT_BIT 8
#define SD_WP_REG LPC_GPIO0
#define SD_WP_BIT 6
#define SDCARD_DETECT (!(BITBAND(SD_DT_REG->FIOPIN, SD_DT_BIT)))
#define SDCARD_WP (BITBAND(SD_WP_REG->FIOPIN, SD_WP_BIT))
@ -40,16 +41,16 @@
#define CONFIG_SD_BLOCKTRANSFER 1
#define CONFIG_SD_AUTO_RETRIES 10
// #define SD_CHANGE_VECT
// #define CONFIG_SD_DATACRC 1
#define CONFIG_SD_DATACRC 1
#define CONFIG_UART_NUM 3
// #define CONFIG_CPU_FREQUENCY 90315789
#define CONFIG_CPU_FREQUENCY (92000000L)
//#define CONFIG_CPU_FREQUENCY 46000000
#define CONFIG_UART_PCLKDIV 1
#define CONFIG_UART_TX_BUF_SHIFT 1
#define CONFIG_UART_TX_BUF_SHIFT 8
#define CONFIG_UART_BAUDRATE 921600
#define CONFIG_UART_DEADLOCKABLE
//#define CONFIG_UART_DEADLOCKABLE
#define SSP_CLK_DIVISOR_FAST 2
#define SSP_CLK_DIVISOR_SLOW 250
@ -58,20 +59,19 @@
#define SSP_CLK_DIVISOR_FPGA_SLOW 20
#define SNES_RESET_REG LPC_GPIO1
#define SNES_RESET_BIT 29
/* XXX Rev.B: 1.26 */
#define SNES_CIC_D0_REG LPC_GPIO1
#define SNES_CIC_D0_BIT 26
/* XXX Rev.B: 0.1 */
#define SNES_CIC_D1_REG LPC_GPIO1
#define SNES_CIC_D1_BIT 25
/* XXX Rev.B: 0.0 */
#define SNES_CIC_STATUS_REG LPC_GPIO0
#define SNES_CIC_STATUS_BIT 1
/* XXX Rev.B: 1.29 */
#define SNES_CIC_PAIR_REG LPC_GPIO0
#define SNES_CIC_PAIR_BIT 0
/* XXX Rev.B: 1.25 */
#define SNES_RESET_BIT 26
#define SNES_CIC_D0_REG LPC_GPIO0
#define SNES_CIC_D0_BIT 1
#define SNES_CIC_D1_REG LPC_GPIO0
#define SNES_CIC_D1_BIT 0
#define SNES_CIC_STATUS_REG LPC_GPIO1
#define SNES_CIC_STATUS_BIT 29
#define SNES_CIC_PAIR_REG LPC_GPIO1
#define SNES_CIC_PAIR_BIT 25
#define QSORT_MAXELEM 1024
@ -88,20 +88,18 @@
#define SD_CLKREG LPC_GPIO0
#define SD_CMDREG LPC_GPIO0
#define SD_DAT0REG LPC_GPIO0
#define SD_DAT1REG LPC_GPIO1
#define SD_DAT2REG LPC_GPIO1
#define SD_DAT3REG LPC_GPIO0
#define SD_DAT0REG LPC_GPIO2
#define SD_DAT1REG LPC_GPIO2
#define SD_DAT2REG LPC_GPIO2
#define SD_DAT3REG LPC_GPIO2
#define SD_CLKPIN (7)
#define SD_CMDPIN (9)
#define SD_DAT0PIN (8)
#define SD_DAT1PIN (14)
#define SD_DAT2PIN (15)
#define SD_DAT3PIN (6)
#define SD_DAT0PIN (0)
#define SD_DAT1PIN (1)
#define SD_DAT2PIN (2)
#define SD_DAT3PIN (3)
#define SD_DAT ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))\
|((SD_DAT1REG->FIOPIN1 >> 5) & 0x6)\
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3))
#define SD_DAT (LPC_GPIO2->FIOPIN & 0xf)
#endif

View File

@ -26,22 +26,6 @@ loop:
uxtb r0, r0 // clear top bits of result
bx lr // return
/* uint16_t crc_xmodem_block(uint16_t crc, uint8_t *data, uint32_t len) */
.global crc_xmodem_block
.thumb_func
crc_xmodem_block:
adr r12, crc_table // load address of crc table
blockloop:
ldrb.w r3, [r1], #1 // read data byte
eor r3, r3, r0, lsr #8 // EOR data byte
ldrh r3, [r12, r3, lsl #1] // load value from CRC table
eor r0, r3, r0, lsl #8 // update CRC
uxth r0, r0 // clear top bits of result
subs r2, r2, #1 // decrement length
bne blockloop // loop while length > 0
bx lr // return
/* uint16_t crc_xmodem_block(uint16_t crc, uint8_t *data, uint32_t len) */
.global crc_xmodem_update
.thumb_func

View File

@ -4,7 +4,7 @@
void HardFault_Handler(void) {
DBG_BL printf("HFSR: %lx\n", SCB->HFSR);
uart_putc('H');
DBG_UART uart_putc('H');
while (1) ;
}

View File

@ -2183,7 +2183,7 @@ FRESULT f_read (
mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs));
#else
if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc){
mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); uart_putc('Y');}
mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); }
#endif
#endif
rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */

View File

@ -127,9 +127,9 @@ FLASH_RES flash_file(uint8_t *filename) {
DBG_BL printf("firmware image found. file size: %ld\n", file_handle.fsize);
DBG_BL printf("reading header...\n");
f_read(&file_handle, &file_header, 32, &bytes_read);
print_header(&file_header);
DBG_BL print_header(&file_header);
if(check_flash() || file_header.version != fw_header->version || file_header.version == FW_MAGIC || fw_header->version == FW_MAGIC) {
uart_putc('F');
DBG_UART uart_putc('F');
f_read(&file_handle, file_buf, 0xe0, &bytes_read);
for(;;) {
bytes_read = file_read();
@ -171,7 +171,7 @@ FLASH_RES flash_file(uint8_t *filename) {
current_sec = flash_addr & 0x10000 ? (16 + ((flash_addr >> 15) & 1))
: (flash_addr >> 12);
DBG_BL printf("current_sec=%d flash_addr=%08lx\n", current_sec, flash_addr);
uart_putc('.');
DBG_UART uart_putc('.');
toggle_rdy_led();
if(current_sec < (FW_START / 0x1000)) return ERR_FLASH;
if((res = iap_prepare_for_write(current_sec, current_sec)) != CMD_SUCCESS) {
@ -185,11 +185,11 @@ FLASH_RES flash_file(uint8_t *filename) {
}
if(total_read != file_header.size) {
DBG_BL printf("wrote less data than expected! (%08lx vs. %08lx)\n", total_read, file_header.size);
uart_putc('X');
DBG_UART uart_putc('X');
return ERR_FILECHK;
}
} else {
uart_putc('n');
DBG_UART uart_putc('n');
DBG_BL printf("flash content is ok, no version mismatch, no forced upgrade. No need to flash\n");
}
return ERR_OK;

View File

@ -9,18 +9,27 @@ int led_rdyledstate = 0;
int led_readledstate = 0;
int led_writeledstate = 0;
/* LED connections (Rev.C)
LED color IO PWM
---------------------------
ready green P2.4 PWM1[5]
read yellow P2.5 PWM1[6]
write red P1.23 PWM1[4]
*/
void rdyled(unsigned int state) {
BITBAND(LPC_GPIO2->FIODIR, 0) = state;
BITBAND(LPC_GPIO2->FIODIR, 4) = state;
led_rdyledstate = state;
}
void readled(unsigned int state) {
BITBAND(LPC_GPIO2->FIODIR, 1) = state;
BITBAND(LPC_GPIO2->FIODIR, 5) = state;
led_readledstate = state;
}
void writeled(unsigned int state) {
BITBAND(LPC_GPIO2->FIODIR, 2) = state;
BITBAND(LPC_GPIO1->FIODIR, 23) = state;
led_writeledstate = state;
}
@ -36,7 +45,7 @@ void led_clkout32(uint32_t val) {
}
void toggle_rdy_led() {
rdyled(!led_rdyledstate);
rdyled(~led_rdyledstate);
}
void toggle_read_led() {
@ -49,21 +58,28 @@ void toggle_write_led() {
void led_panic() {
while(1) {
LPC_GPIO2->FIODIR |= BV(0) | BV(1) | BV(2);
LPC_GPIO2->FIODIR |= BV(4) | BV(5);
LPC_GPIO1->FIODIR |= BV(23);
delay_ms(350);
LPC_GPIO2->FIODIR &= ~(BV(0) | BV(1) | BV(2));
LPC_GPIO2->FIODIR &= ~(BV(4) | BV(5));
LPC_GPIO1->FIODIR &= ~BV(23);
delay_ms(350);
}
}
void led_std() {
BITBAND(LPC_PINCON->PINSEL4, 1) = 0;
BITBAND(LPC_PINCON->PINSEL4, 3) = 0;
BITBAND(LPC_PINCON->PINSEL4, 5) = 0;
BITBAND(LPC_PINCON->PINSEL4, 9) = 0;
BITBAND(LPC_PINCON->PINSEL4, 8) = 0;
BITBAND(LPC_PINCON->PINSEL4, 0) = 0;
BITBAND(LPC_PINCON->PINSEL4, 2) = 0;
BITBAND(LPC_PINCON->PINSEL4, 4) = 0;
BITBAND(LPC_PINCON->PINSEL4, 11) = 0;
BITBAND(LPC_PINCON->PINSEL4, 10) = 0;
BITBAND(LPC_PINCON->PINSEL3, 15) = 0;
BITBAND(LPC_PINCON->PINSEL3, 14) = 0;
BITBAND(LPC_PWM1->PCR, 12) = 0;
BITBAND(LPC_PWM1->PCR, 13) = 0;
BITBAND(LPC_PWM1->PCR, 14) = 0;
}
void led_init() {

View File

@ -10,7 +10,7 @@ ENTRY(_start)
MEMORY
{
flash (rx) : ORIGIN = 0x00000000, LENGTH = 0x03000
flash (rx) : ORIGIN = 0x00000000, LENGTH = 0x02000
ram (rwx) : ORIGIN = 0x10000000, LENGTH = 0x03fe0 /* leave room for IAP */
ahbram (rwx) : ORIGIN = 0x2007C000, LENGTH = 0x04000
}

View File

@ -42,7 +42,7 @@ int main(void) {
clock_disconnect();
power_init();
timer_init();
uart_init();
DBG_UART uart_init();
led_init();
readled(0);
rdyled(0);

View File

@ -66,12 +66,13 @@
#define CARD_SDHC (1<<1)
/*
1 DAT3/SS P0.6
2 CMD/DI P0.9
5 Clock P0.7
7 DAT0/DO P0.8
8 DAT1/IRQ P1.14
9 DAT2/NC P1.15
Rev.A Rev.C
1 DAT3/SS P0.6 P2.3
2 CMD/DI P0.9 P0.9
5 Clock P0.7 P0.7
7 DAT0/DO P0.8 P2.0
8 DAT1/IRQ P1.14 P2.1
9 DAT2/NC P1.15 P2.2
*/
/* SD init procedure
@ -195,6 +196,42 @@ static inline void wiggle_fast_pos1(void) {
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
}
int get_and_check_datacrc(uint8_t *buf) {
uint16_t crc0=0, crc1=0, crc2=0, crc3=0;
uint16_t sdcrc0=0, sdcrc1=0, sdcrc2=0, sdcrc3=0;
uint8_t d0=0, d1=0, d2=0, d3=0;
uint8_t datdata;
uint16_t datcnt;
/* get crcs from card */
for (datcnt=0; datcnt < 16; datcnt++) {
datdata = SD_DAT;
wiggle_fast_neg1();
sdcrc0 = ((sdcrc0 << 1) & 0xfffe) | ((datdata >> 3) & 0x0001);
sdcrc1 = ((sdcrc1 << 1) & 0xfffe) | ((datdata >> 2) & 0x0001);
sdcrc2 = ((sdcrc2 << 1) & 0xfffe) | ((datdata >> 1) & 0x0001);
sdcrc3 = ((sdcrc3 << 1) & 0xfffe) | ((datdata >> 0) & 0x0001);
}
wiggle_fast_neg1();
/* calc crcs from data */
for (datcnt=0; datcnt < 512; datcnt++) {
d0 = ((d0 << 2) & 0xfc) | ((buf[datcnt] >> 6) & 0x02) | ((buf[datcnt] >> 3) & 0x01) ;
d1 = ((d1 << 2) & 0xfc) | ((buf[datcnt] >> 5) & 0x02) | ((buf[datcnt] >> 2) & 0x01) ;
d2 = ((d2 << 2) & 0xfc) | ((buf[datcnt] >> 4) & 0x02) | ((buf[datcnt] >> 1) & 0x01) ;
d3 = ((d3 << 2) & 0xfc) | ((buf[datcnt] >> 3) & 0x02) | ((buf[datcnt] >> 0) & 0x01) ;
if((datcnt % 4) == 3) {
crc0 = crc_xmodem_update(crc0, d0);
crc1 = crc_xmodem_update(crc1, d1);
crc2 = crc_xmodem_update(crc2, d2);
crc3 = crc_xmodem_update(crc3, d3);
}
}
if((crc0 != sdcrc0) || (crc1 != sdcrc1) || (crc2 != sdcrc2) || (crc3 != sdcrc3)) {
DBG_SD printf("CRC mismatch\nSDCRC CRC\n %04x %04x\n %04x %04x\n %04x %04x\n %04x %04x\n", sdcrc0, crc0, sdcrc1, crc1, sdcrc2, crc2, sdcrc3, crc3);
return 1;
}
return 0;
}
static inline void wait_busy(void) {
while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
wiggle_fast_neg1();
@ -446,8 +483,16 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
}
}
}
/* just eat the crcs for now */
if(dat) wiggle_fast_neg(17);
if(dat) {
#ifdef CONFIG_SD_DATACRC
if(get_and_check_datacrc(buf-512)) {
return CRC_ERROR;
}
#else
/* eat the crcs */
wiggle_fast_neg(17);
#endif
}
if(waitbusy) {
DBG_SD printf("waitbusy after send_cmd\n");
@ -515,7 +560,7 @@ int acmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* r
return cmd_fast(cmd, param, crc, dat, rsp);
}
void stream_datablock(uint8_t *buf) {
int stream_datablock(uint8_t *buf) {
// uint8_t datshift=8;
int j=512;
uint8_t datdata=0;
@ -537,8 +582,13 @@ void stream_datablock(uint8_t *buf) {
j--;
if(!j) break;
}
/* eat the crc for now */
#ifdef CONFIG_SD_DATACRC
return get_and_check_datacrc(buf-512);
#else
/* eat the crcs */
wiggle_fast_neg(17);
#endif
return 0;
}
void send_datablock(uint8_t *buf) {
@ -667,7 +717,17 @@ void send_datablock(uint8_t *buf) {
void read_block(uint32_t address, uint8_t *buf) {
if(during_blocktrans == TRANS_READ && (last_block == address-1)) {
//uart_putc('r');
#ifdef CONFIG_SD_DATACRC
int cmd_res;
if((cmd_res = stream_datablock(buf)) == CRC_ERROR) {
while(cmd_res == CRC_ERROR) {
cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
cmd_res = cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
}
}
#else
stream_datablock(buf);
#endif
last_block=address;
} else {
if(during_blocktrans) {
@ -680,7 +740,14 @@ void read_block(uint32_t address, uint8_t *buf) {
if(!ccs) {
address <<= 9;
}
#ifdef CONFIG_SD_DATACRC
while(1) {
if(cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp) != CRC_ERROR) break;
cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
};
#else
cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
#endif
during_blocktrans = TRANS_READ;
}
}

View File

@ -11,6 +11,8 @@
#include "diskio.h"
#define CRC_ERROR (0xf000)
/* These functions are weak-aliased to disk_... */
void sdn_init(void);
DSTATUS sdn_status(BYTE drv);

File diff suppressed because it is too large Load Diff

View File

@ -388,7 +388,7 @@ void cmd_settime(void) {
curchar[4+2] = 0;
time.tm_mon = atoi(curchar+4);
curchar[4] = 0;
time.tm_year = atoi(curchar) - 1900;
time.tm_year = atoi(curchar);
set_rtc(&time);
}
}
@ -396,7 +396,7 @@ void cmd_settime(void) {
void cmd_time(void) {
struct tm time;
read_rtc(&time);
printf("%04d-%02d-%02d %02d:%02d:%02d\n", time.tm_year+1900, time.tm_mon,
printf("%04d-%02d-%02d %02d:%02d:%02d\n", time.tm_year, time.tm_mon,
time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec);
}
@ -513,6 +513,11 @@ void cli_loop(void) {
case CMD_TIME:
cmd_time();
break;
case CMD_TEST:
testbattery();
break;
}
}
}

View File

@ -49,7 +49,8 @@ void clock_init() {
enableMainOsc();
setClkSrc(CLKSRC_MAINOSC);
// XXX setPLL0MultPrediv(429, 19);
setPLL0MultPrediv(23, 2);
// XXX setPLL0MultPrediv(23, 2);
setPLL0MultPrediv(12, 1);
enablePLL0();
setCCLKDiv(3);
connectPLL0();

View File

@ -18,10 +18,10 @@
#define SD_CHANGE_CLR() do {LPC_GPIOINT->IO2IntClr = BV(SD_DT_BIT);} while(0)
#define SD_DT_REG LPC_GPIO2
#define SD_DT_BIT 3
#define SD_WP_REG LPC_GPIO2
#define SD_WP_BIT 4
#define SD_DT_REG LPC_GPIO0
#define SD_DT_BIT 8
#define SD_WP_REG LPC_GPIO0
#define SD_WP_BIT 6
#define SDCARD_DETECT (!(BITBAND(SD_DT_REG->FIOPIN, SD_DT_BIT)))
#define SDCARD_WP (BITBAND(SD_WP_REG->FIOPIN, SD_WP_BIT))
@ -33,12 +33,12 @@
#define CONFIG_UART_NUM 3
// #define CONFIG_CPU_FREQUENCY 90315789
#define CONFIG_CPU_FREQUENCY 92000000
#define CONFIG_CPU_FREQUENCY 96000000
//#define CONFIG_CPU_FREQUENCY 46000000
#define CONFIG_UART_PCLKDIV 1
#define CONFIG_UART_TX_BUF_SHIFT 10
#define CONFIG_UART_TX_BUF_SHIFT 8
#define CONFIG_UART_BAUDRATE 921600
//#define CONFIG_UART_DEADLOCKABLE
#define CONFIG_UART_DEADLOCKABLE
#define SSP_CLK_DIVISOR_FAST 2
#define SSP_CLK_DIVISOR_SLOW 250
@ -47,20 +47,19 @@
#define SSP_CLK_DIVISOR_FPGA_SLOW 20
#define SNES_RESET_REG LPC_GPIO1
#define SNES_RESET_BIT 29
/* XXX Rev.B: 1.26 */
#define SNES_CIC_D0_REG LPC_GPIO1
#define SNES_CIC_D0_BIT 26
/* XXX Rev.B: 0.1 */
#define SNES_CIC_D1_REG LPC_GPIO1
#define SNES_CIC_D1_BIT 25
/* XXX Rev.B: 0.0 */
#define SNES_CIC_STATUS_REG LPC_GPIO0
#define SNES_CIC_STATUS_BIT 1
/* XXX Rev.B: 1.29 */
#define SNES_CIC_PAIR_REG LPC_GPIO0
#define SNES_CIC_PAIR_BIT 0
/* XXX Rev.B: 1.25 */
#define SNES_RESET_BIT 26
#define SNES_CIC_D0_REG LPC_GPIO0
#define SNES_CIC_D0_BIT 1
#define SNES_CIC_D1_REG LPC_GPIO0
#define SNES_CIC_D1_BIT 0
#define SNES_CIC_STATUS_REG LPC_GPIO1
#define SNES_CIC_STATUS_BIT 29
#define SNES_CIC_PAIR_REG LPC_GPIO1
#define SNES_CIC_PAIR_BIT 25
#define QSORT_MAXELEM 1024
@ -77,20 +76,18 @@
#define SD_CLKREG LPC_GPIO0
#define SD_CMDREG LPC_GPIO0
#define SD_DAT0REG LPC_GPIO0
#define SD_DAT1REG LPC_GPIO1
#define SD_DAT2REG LPC_GPIO1
#define SD_DAT3REG LPC_GPIO0
#define SD_DAT0REG LPC_GPIO2
#define SD_DAT1REG LPC_GPIO2
#define SD_DAT2REG LPC_GPIO2
#define SD_DAT3REG LPC_GPIO2
#define SD_CLKPIN (7)
#define SD_CMDPIN (9)
#define SD_DAT0PIN (8)
#define SD_DAT1PIN (14)
#define SD_DAT2PIN (15)
#define SD_DAT3PIN (6)
#define SD_DAT0PIN (0)
#define SD_DAT1PIN (1)
#define SD_DAT2PIN (2)
#define SD_DAT3PIN (3)
#define SD_DAT ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))\
|((SD_DAT1REG->FIOPIN1 >> 5) & 0x6)\
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3))
#define SD_DAT (LPC_GPIO2->FIOPIN0)
#endif

View File

@ -20,7 +20,7 @@
/**
* Static table used for the table_driven implementation.
*****************************************************************************/
static const crc_t crc_table[256] = {
static const uint16_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,
@ -63,14 +63,11 @@ static const crc_t crc_table[256] = {
* \param data_len Number of bytes in the \a data buffer.
* \return The updated crc value.
*****************************************************************************/
crc_t crc16_update(crc_t crc, const unsigned char *data, size_t data_len)
uint16_t crc16_update(uint16_t crc, const unsigned char data)
{
unsigned int tbl_idx;
while (data_len--) {
tbl_idx = (crc ^ *data) & 0xff;
tbl_idx = (crc ^ data) & 0xff;
crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffff;
data++;
}
return crc & 0xffff;
}

View File

@ -29,13 +29,6 @@ extern "C" {
*****************************************************************************/
#define CRC_ALGO_BIT_BY_BIT_FAST 1
/**
* The type of the CRC values.
*
* This type must be big enough to contain at least 16 bits.
*****************************************************************************/
typedef uint16_t crc_t;
/**
* Update the crc value with new data.
*
@ -44,7 +37,7 @@ typedef uint16_t crc_t;
* \param data_len Number of bytes in the \a data buffer.
* \return The updated crc value.
*****************************************************************************/
crc_t crc16_update(crc_t crc, const unsigned char *data, size_t data_len);
uint16_t crc16_update(uint16_t crc, const unsigned char data);
#ifdef __cplusplus
} /* closing brace for extern "C" */

View File

@ -178,6 +178,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
uint16_t pathlen = strlen(path);
switch(type) {
case TYPE_IPS:
case TYPE_SMC:
/* file_open_by_filinfo(&fno);
if(file_res){
@ -194,7 +195,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
db_tgt += 0x00010000;
printf("new=%lx\n", db_tgt);
}
sram_writelong((db_tgt-SRAM_MENU_ADDR), dir_tgt);
sram_writelong((db_tgt-SRAM_MENU_ADDR) | ((uint32_t)type << 24), dir_tgt);
dir_tgt += 4;
/* save element:
- index of last slash character
@ -252,7 +253,13 @@ SNES_FTYPE determine_filetype(char* filename) {
||(!strcasecmp(ext+1, "FIG"))
) {
return TYPE_SMC;
}/* later
}
if( (!strcasecmp(ext+1, "IPS"))
||(!strcasecmp(ext+1, "UPS"))
) {
return TYPE_IPS;
}
/* later
if(!strcasecmp_P(ext+1, PSTR("SRM"))) {
return TYPE_SRM;
}

View File

@ -32,7 +32,8 @@ typedef enum {
TYPE_UNKNOWN = 0, /* 0 */
TYPE_SMC, /* 1 */
TYPE_SRM, /* 2 */
TYPE_SPC /* 3 */
TYPE_SPC, /* 3 */
TYPE_IPS /* 4 */
} SNES_FTYPE;

View File

@ -6,7 +6,7 @@
#flash info 0
reset init
flash write_image erase unlock obj/sd2snes.elf
flash write_image erase unlock obj/firmware.img 8192
reset run
shutdown

View File

@ -53,10 +53,10 @@
8p - read (RAM only)
p: 0 = no increment after read
1 = increment after read
8 = increment after read
9p {xx}* write xx
p: tt-i
p: i-tt
tt = target (see above)
i = increment (see above)
@ -73,6 +73,7 @@
nibbles packed)
eg 0x20111210094816 is 2011-12-10, 9:48:16
E6 ssrr set/reset BS-X status register [7:0]
E7 - reset SRTC state
F0 - receive test token (to see if FPGA is alive)
F1 - receive status (16bit, MSB first), see below
@ -336,3 +337,11 @@ void set_fpga_time(uint64_t time) {
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
void fpga_reset_srtc_state() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe7);
FPGA_TX_BYTE(0x00);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}

View File

@ -74,5 +74,6 @@ uint32_t get_msu_offset(void);
uint32_t get_snes_sysclk(void);
void set_bsx_regs(uint8_t set, uint8_t reset);
void set_fpga_time(uint64_t time);
void fpga_reset_srtc_state(void);
#endif

View File

@ -12,11 +12,20 @@ int led_readledstate = 0;
int led_writeledstate = 0;
int led_pwmstate = 0;
/* LED connections (Rev.C)
LED color IO PWM
---------------------------
ready green P2.4 PWM1[5]
read yellow P2.5 PWM1[6]
write red P1.23 PWM1[4]
*/
void rdyled(unsigned int state) {
if(led_pwmstate) {
rdybright(state?15:0);
} else {
BITBAND(LPC_GPIO2->FIODIR, 0) = state;
BITBAND(LPC_GPIO2->FIODIR, 4) = state;
}
led_rdyledstate = state;
}
@ -25,7 +34,7 @@ void readled(unsigned int state) {
if(led_pwmstate) {
readbright(state?15:0);
} else {
BITBAND(LPC_GPIO2->FIODIR, 1) = state;
BITBAND(LPC_GPIO2->FIODIR, 5) = state;
}
led_readledstate = state;
}
@ -34,22 +43,22 @@ void writeled(unsigned int state) {
if(led_pwmstate) {
writebright(state?15:0);
} else {
BITBAND(LPC_GPIO2->FIODIR, 2) = state;
BITBAND(LPC_GPIO1->FIODIR, 23) = state;
}
led_writeledstate = state;
}
void rdybright(uint8_t bright) {
LPC_PWM1->MR1 = led_bright[(bright & 15)];
BITBAND(LPC_PWM1->LER, 1) = 1;
LPC_PWM1->MR5 = led_bright[(bright & 15)];
BITBAND(LPC_PWM1->LER, 5) = 1;
}
void readbright(uint8_t bright) {
LPC_PWM1->MR2 = led_bright[(bright & 15)];
BITBAND(LPC_PWM1->LER, 2) = 1;
LPC_PWM1->MR6 = led_bright[(bright & 15)];
BITBAND(LPC_PWM1->LER, 6) = 1;
}
void writebright(uint8_t bright) {
LPC_PWM1->MR3 = led_bright[(bright & 15)];
BITBAND(LPC_PWM1->LER, 3) = 1;
LPC_PWM1->MR4 = led_bright[(bright & 15)];
BITBAND(LPC_PWM1->LER, 4) = 1;
}
void led_clkout32(uint32_t val) {
@ -77,43 +86,46 @@ void toggle_write_led() {
void led_panic() {
while(1) {
LPC_GPIO2->FIODIR |= BV(0) | BV(1) | BV(2);
LPC_GPIO2->FIODIR |= BV(4) | BV(5);
LPC_GPIO1->FIODIR |= BV(23);
delay_ms(350);
LPC_GPIO2->FIODIR &= ~(BV(0) | BV(1) | BV(2));
LPC_GPIO2->FIODIR &= ~(BV(4) | BV(5));
LPC_GPIO1->FIODIR &= ~BV(23);
delay_ms(350);
}
}
void led_pwm() {
/* connect PWM to P2.0 - P2.2 */
/* XXX Rev.B P2.???? */
BITBAND(LPC_PINCON->PINSEL4, 1) = 0;
BITBAND(LPC_PINCON->PINSEL4, 3) = 0;
BITBAND(LPC_PINCON->PINSEL4, 5) = 0;
/* Rev.C P2.4, P2.5, P1.23 */
BITBAND(LPC_PINCON->PINSEL4, 9) = 0;
BITBAND(LPC_PINCON->PINSEL4, 8) = 1;
BITBAND(LPC_PINCON->PINSEL4, 0) = 1;
BITBAND(LPC_PINCON->PINSEL4, 2) = 1;
BITBAND(LPC_PINCON->PINSEL4, 4) = 1;
BITBAND(LPC_PINCON->PINSEL4, 11) = 0;
BITBAND(LPC_PINCON->PINSEL4, 10) = 1;
BITBAND(LPC_PWM1->PCR, 9) = 1;
BITBAND(LPC_PWM1->PCR, 10) = 1;
BITBAND(LPC_PWM1->PCR, 11) = 1;
BITBAND(LPC_PINCON->PINSEL3, 15) = 1;
BITBAND(LPC_PINCON->PINSEL3, 14) = 0;
BITBAND(LPC_PWM1->PCR, 12) = 1;
BITBAND(LPC_PWM1->PCR, 13) = 1;
BITBAND(LPC_PWM1->PCR, 14) = 1;
led_pwmstate = 1;
}
void led_std() {
BITBAND(LPC_PINCON->PINSEL4, 1) = 0;
BITBAND(LPC_PINCON->PINSEL4, 3) = 0;
BITBAND(LPC_PINCON->PINSEL4, 5) = 0;
BITBAND(LPC_PINCON->PINSEL4, 9) = 0;
BITBAND(LPC_PINCON->PINSEL4, 8) = 0;
BITBAND(LPC_PINCON->PINSEL4, 0) = 0;
BITBAND(LPC_PINCON->PINSEL4, 2) = 0;
BITBAND(LPC_PINCON->PINSEL4, 4) = 0;
BITBAND(LPC_PINCON->PINSEL4, 11) = 0;
BITBAND(LPC_PINCON->PINSEL4, 10) = 0;
BITBAND(LPC_PWM1->PCR, 9) = 0;
BITBAND(LPC_PWM1->PCR, 10) = 0;
BITBAND(LPC_PWM1->PCR, 11) = 0;
BITBAND(LPC_PINCON->PINSEL3, 15) = 0;
BITBAND(LPC_PINCON->PINSEL3, 14) = 0;
BITBAND(LPC_PWM1->PCR, 12) = 0;
BITBAND(LPC_PWM1->PCR, 13) = 0;
BITBAND(LPC_PWM1->PCR, 14) = 0;
led_pwmstate = 0;
}

View File

@ -10,7 +10,7 @@ ENTRY(_start)
MEMORY
{
flash (rx) : ORIGIN = 0x00004100, LENGTH = 0x1bf00 /* leave room for bootldr + metadata */
flash (rx) : ORIGIN = 0x00002100, LENGTH = 0x1df00 /* leave room for bootldr + metadata */
ram (rwx) : ORIGIN = 0x10000000, LENGTH = 0x04000
ahbram (rwx) : ORIGIN = 0x2007C000, LENGTH = 0x04000
}

View File

@ -25,8 +25,8 @@
#include "crc.h"
#include "smc.h"
#include "msu1.h"
#include "rtc.h"
#include "usb_hid.h"
#define EMC0TOGGLE (3<<4)
#define MR0R (1<<1)
@ -37,14 +37,18 @@ int sd_offload_partial = 0;
uint16_t sd_offload_partial_start = 0;
uint16_t sd_offload_partial_end = 0;
/* FIXME HACK */
volatile enum diskstates disk_state;
extern volatile tick_t ticks;
extern snes_romprops_t romprops;
extern volatile int reset_changed;
enum system_states {
SYS_RTC_STATUS = 0
};
int main(void) {
LPC_GPIO2->FIODIR = BV(0) | BV(1) | BV(2);
LPC_GPIO1->FIODIR = 0;
LPC_GPIO2->FIODIR = BV(4) | BV(5);
LPC_GPIO1->FIODIR = BV(23);
LPC_GPIO0->FIODIR = BV(16);
/* connect UART3 on P0[25:26] + SSP0 on P0[15:18] + MAT3.0 on P0[10] */
@ -54,7 +58,7 @@ int main(void) {
/* | BV(13) | BV(15) | BV(17) | BV(19) SSP1 (SD) */
/* pull-down CIC data lines */
LPC_PINCON->PINMODE3 = BV(18) | BV(19) | BV(20) | BV(21);
LPC_PINCON->PINMODE0 = BV(0) | BV(1) | BV(2) | BV(3);
clock_disconnect();
snes_init();
@ -72,6 +76,7 @@ led_pwm();
sdn_init();
printf("\n\nsd2snes mk.2\n============\nfw ver.: " VER "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY);
printf("PCONP=%lx\n", LPC_SC->PCONP);
file_init();
cic_init(0);
/* setup timer (fpga clk) */
@ -197,22 +202,35 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
/* shared mode */
set_mcu_ovr(0);
if((rtc_state = rtc_isvalid()) != RTC_OK) {
printf("RTC invalid!\n");
sram_writebyte(0xff, SRAM_STATUS_ADDR+SYS_RTC_STATUS);
set_bcdtime(0x20110401000000LL);
set_fpga_time(0x20110401000000LL);
invalidate_rtc();
} else {
printf("RTC valid!\n");
sram_writebyte(0x00, SRAM_STATUS_ADDR+SYS_RTC_STATUS);
set_fpga_time(get_bcdtime());
}
printf("SNES GO!\n");
snes_reset(1);
delay_ms(1);
snes_reset(0);
uint8_t cmd = 0;
uint64_t btime = 0;
uint32_t filesize=0;
sram_writebyte(32, SRAM_CMD_ADDR);
printf("test sram\n");
while(!sram_reliable());
printf("ok\n");
//while(1) {
// delay_ms(1000);
// printf("Estimated SNES master clock: %ld Hz\n", get_snes_sysclk());
//}
sram_hexdump(SRAM_DIR_ADDR, 0x300);
//while(1) {
// delay_ms(1000);
// printf("Estimated SNES master clock: %ld Hz\n", get_snes_sysclk());
//}
//sram_hexdump(SRAM_DB_ADDR, 0x200);
//sram_hexdump(SRAM_MENU_ADDR, 0x400);
while(!cmd) {
@ -241,6 +259,11 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
snes_reset(0);
break;
case SNES_CMD_SETRTC:
/* get time from RAM */
btime = sram_gettime(SRAM_PARAM_ADDR);
/* set RTC */
set_bcdtime(btime);
set_fpga_time(btime);
cmd=0; /* stay in loop */
break;
default:
@ -265,6 +288,11 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
sleep_ms(250);
sram_reliable();
printf("%s ", get_cic_statename(get_cic_state()));
if(reset_changed) {
printf("reset\n");
reset_changed = 0;
fpga_reset_srtc_state();
}
snes_reset_now=get_snes_reset();
if(snes_reset_now) {
if(!snes_reset_prev) {

View File

@ -227,7 +227,7 @@ ticks_total=getticks()-ticksstart;
sram_writebyte(0x33, rombase+0xda);
sram_writebyte(0x00, rombase+0xd4);
sram_writebyte(0xfc, rombase+0xd5);
set_fpga_time(0x0020110212180500LL);
set_fpga_time(0x0220110301180530LL);
}
uint32_t rammask;
uint32_t rommask;
@ -418,3 +418,33 @@ void sram_memset(uint32_t base_addr, uint32_t len, uint8_t val) {
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
uint64_t sram_gettime(uint32_t base_addr) {
set_mcu_addr(base_addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x88);
FPGA_TX_BYTE(0x00);
uint8_t data;
uint64_t result = 0LL;
/* 1st nibble is the century - 10 (binary)
4th nibble is the month (binary)
all other fields are BCD */
for(int i=0; i<12; i++) {
data = FPGA_TXRX_BYTE(0x00);
data &= 0xf;
switch(i) {
case 0:
result = (result << 4) | ((data / 10) + 1);
result = (result << 4) | (data % 10);
break;
case 3:
result = (result << 4) | ((data / 10));
result = (result << 4) | (data % 10);
break;
default:
result = (result << 4) | data;
}
}
FPGA_DESELECT();
return result & 0x00ffffffffffffffLL;
}

View File

@ -38,6 +38,7 @@
#define SRAM_DIR_ADDR (0xE10000L)
#define SRAM_CMD_ADDR (0xFF1000L)
#define SRAM_PARAM_ADDR (0xFF1004L)
#define SRAM_STATUS_ADDR (0xFF1100L)
#define SRAM_MENU_SAVE_ADDR (0xFF0000L)
#define SRAM_SCRATCHPAD (0xFFFF00L)
#define SRAM_DIRID (0xFFFFF0L)
@ -61,6 +62,7 @@ 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);
uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size);
uint8_t sram_reliable(void);
void sram_memset(uint32_t base_adde, uint32_t len, uint8_t val);
void sram_memset(uint32_t base_addr, uint32_t len, uint8_t val);
uint64_t sram_gettime(uint32_t base_addr);
#endif

View File

@ -2,12 +2,22 @@
#include <arm/bits.h>
#include "config.h"
#include "rtc.h"
#include "uart.h"
#include "timer.h"
#include "power.h"
rtcstate_t rtc_state;
#define CLKEN 0
#define CTCRST 1
uint8_t rtc_isvalid(void) {
if(LPC_RTC->GPREG0 == RTC_MAGIC) {
return RTC_OK;
}
return RTC_INVALID;
}
void rtc_init(void) {
if (LPC_RTC->CCR & BV(CLKEN)) {
rtc_state = RTC_OK;
@ -23,11 +33,25 @@ void read_rtc(struct tm *time) {
time->tm_hour = LPC_RTC->HOUR;
time->tm_mday = LPC_RTC->DOM;
time->tm_mon = LPC_RTC->MONTH;
time->tm_year = LPC_RTC->YEAR - 1900;
time->tm_year = LPC_RTC->YEAR;
time->tm_wday = LPC_RTC->DOW;
} while (time->tm_sec != LPC_RTC->SEC);
}
uint8_t calc_weekday(struct tm *time) {
int month = time->tm_mon;
int year = time->tm_year;
int day = time->tm_mday;
/* Variation of Sillke for the Gregorian calendar.
* http://www.mathematik.uni-bielefeld.de/~sillke/ALGORITHMS/calendar/weekday.c */
if (month <= 2) {
month += 10;
year--;
} else month -= 2;
return (83*month/32 + day + year + year/4 - year/100 + year/400) % 7;
}
void set_rtc(struct tm *time) {
LPC_RTC->CCR = BV(CTCRST);
LPC_RTC->SEC = time->tm_sec;
@ -35,17 +59,21 @@ void set_rtc(struct tm *time) {
LPC_RTC->HOUR = time->tm_hour;
LPC_RTC->DOM = time->tm_mday;
LPC_RTC->MONTH = time->tm_mon;
LPC_RTC->YEAR = time->tm_year + 1900;
LPC_RTC->DOW = time->tm_wday;
LPC_RTC->YEAR = time->tm_year;
LPC_RTC->DOW = calc_weekday(time);
LPC_RTC->CCR = BV(CLKEN);
LPC_RTC->GPREG0 = RTC_MAGIC;
}
void invalidate_rtc() {
LPC_RTC->GPREG0 = 0;
}
uint32_t get_fattime(void) {
struct tm time;
read_rtc(&time);
return ((uint32_t)time.tm_year-80) << 25 |
return ((uint32_t)time.tm_year-1980) << 25 |
((uint32_t)time.tm_mon) << 21 |
((uint32_t)time.tm_mday) << 16 |
((uint32_t)time.tm_hour) << 11 |
@ -56,7 +84,7 @@ uint32_t get_fattime(void) {
uint64_t get_bcdtime(void) {
struct tm time;
read_rtc(&time);
uint16_t year = time.tm_year + 1900;
uint16_t year = time.tm_year;
return ((uint64_t)(time.tm_wday % 7) << 56)
|((uint64_t)((year / 1000) % 10) << 52)
@ -74,3 +102,34 @@ uint64_t get_bcdtime(void) {
|((time.tm_sec / 10) << 4)
|(time.tm_sec % 10);
}
void set_bcdtime(uint64_t btime) {
struct tm time;
time.tm_sec = (btime & 0xf) + ((btime >> 4) & 0xf) * 10;
time.tm_min = ((btime >> 8) & 0xf) + ((btime >> 12) & 0xf) * 10;
time.tm_hour = ((btime >> 16) & 0xf) + ((btime >> 20) & 0xf) * 10;
time.tm_mday = ((btime >> 24) & 0xf) + ((btime >> 28) & 0xf) * 10;
time.tm_mon = ((btime >> 32) & 0xf) + ((btime >> 36) & 0xf) * 10;
time.tm_year = ((btime >> 40) & 0xf) + ((btime >> 44) & 0xf) * 10
+ ((btime >> 48) & 0xf) * 100 + ((btime >> 52) & 0xf) * 1000;
printtime(&time);
set_rtc(&time);
}
void printtime(struct tm *time) {
printf("%04d-%02d-%02d %02d:%02d:%02d\n", time->tm_year, time->tm_mon,
time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec);
}
void testbattery() {
printf("%lx\n", LPC_RTC->GPREG0);
LPC_RTC->GPREG0 = RTC_MAGIC;
printf("%lx\n", LPC_RTC->GPREG0);
LPC_RTC->CCR = 0;
BITBAND(LPC_SC->PCONP, PCRTC) = 0;
delay_ms(20000);
BITBAND(LPC_SC->PCONP, PCRTC) = 1;
printf("%lx\n", LPC_RTC->GPREG0);
delay_ms(20);
LPC_RTC->CCR = BV(CLKEN);
}

View File

@ -22,9 +22,6 @@
rtc.h: Definitions for RTC support
There is no rtc.c, the functions defined here are implemented by a
device-specific .c file, e.g. pcf8583.c.
*/
#ifndef RTC_H
@ -44,22 +41,38 @@ struct tm {
uint8_t tm_hour; // 0..23
uint8_t tm_mday; // 1..[28..31]
uint8_t tm_mon; // 0..11
uint8_t tm_year; // since 1900, i.e. 2000 is 100
uint16_t tm_year; // since 0 A.D.
uint8_t tm_wday; // 0 to 6, sunday is 6
// A Unix struct tm has a few more fields we don't need in this application
};
#define RTC_MAGIC (0x43545253L)
extern rtcstate_t rtc_state;
void rtc_init(void);
/* return RTC valid state based on magic token in backup register */
uint8_t rtc_isvalid(void);
/* Return current time in struct tm */
void read_rtc(struct tm *time);
/* Set time from struct tm */
/* Set time from struct tm, also sets RTC valid */
void set_rtc(struct tm *time);
/* Set RTC invalid */
void invalidate_rtc(void);
/* get current time in 60-bit BCD format (WYYYYMMDDHHMMSS) (W=DOW) */
uint64_t get_bcdtime(void);
/* set current time from 56-bit BCD format (YYYYMMDDHHMMSS)
DOW is calculated */
void set_bcdtime(uint64_t btime);
/* print the time to the console */
void printtime(struct tm *time);
void testbattery(void);
#endif

View File

@ -2,6 +2,7 @@
#include <stdio.h>
#include "config.h"
#include "crc.h"
#include "crc16.h"
#include "diskio.h"
#include "spi.h"
#include "timer.h"
@ -68,12 +69,13 @@
#define CARD_SDHC (1<<1)
/*
1 DAT3/SS P0.6
2 CMD/DI P0.9
5 Clock P0.7
7 DAT0/DO P0.8
8 DAT1/IRQ P1.14
9 DAT2/NC P1.15
Rev.A Rev.C
1 DAT3/SS P0.6 P2.3
2 CMD/DI P0.9 P0.9
5 Clock P0.7 P0.7
7 DAT0/DO P0.8 P2.0
8 DAT1/IRQ P1.14 P2.1
9 DAT2/NC P1.15 P2.2
*/
/* SD init procedure
@ -197,6 +199,42 @@ static inline void wiggle_fast_pos1(void) {
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
}
int get_and_check_datacrc(uint8_t *buf) {
uint16_t crc0=0, crc1=0, crc2=0, crc3=0;
uint16_t sdcrc0=0, sdcrc1=0, sdcrc2=0, sdcrc3=0;
uint8_t d0=0, d1=0, d2=0, d3=0;
uint8_t datdata;
uint16_t datcnt;
/* get crcs from card */
for (datcnt=0; datcnt < 16; datcnt++) {
datdata = SD_DAT;
wiggle_fast_neg1();
sdcrc0 = ((sdcrc0 << 1) & 0xfffe) | ((datdata >> 3) & 0x0001);
sdcrc1 = ((sdcrc1 << 1) & 0xfffe) | ((datdata >> 2) & 0x0001);
sdcrc2 = ((sdcrc2 << 1) & 0xfffe) | ((datdata >> 1) & 0x0001);
sdcrc3 = ((sdcrc3 << 1) & 0xfffe) | ((datdata >> 0) & 0x0001);
}
wiggle_fast_neg1();
/* calc crcs from data */
for (datcnt=0; datcnt < 512; datcnt++) {
d0 = ((d0 << 2) & 0xfc) | ((buf[datcnt] >> 6) & 0x02) | ((buf[datcnt] >> 3) & 0x01) ;
d1 = ((d1 << 2) & 0xfc) | ((buf[datcnt] >> 5) & 0x02) | ((buf[datcnt] >> 2) & 0x01) ;
d2 = ((d2 << 2) & 0xfc) | ((buf[datcnt] >> 4) & 0x02) | ((buf[datcnt] >> 1) & 0x01) ;
d3 = ((d3 << 2) & 0xfc) | ((buf[datcnt] >> 3) & 0x02) | ((buf[datcnt] >> 0) & 0x01) ;
if((datcnt % 4) == 3) {
crc0 = crc_xmodem_update(crc0, d0);
crc1 = crc_xmodem_update(crc1, d1);
crc2 = crc_xmodem_update(crc2, d2);
crc3 = crc_xmodem_update(crc3, d3);
}
}
if((crc0 != sdcrc0) || (crc1 != sdcrc1) || (crc2 != sdcrc2) || (crc3 != sdcrc3)) {
printf("CRC mismatch\nSDCRC CRC\n %04x %04x\n %04x %04x\n %04x %04x\n %04x %04x\n", sdcrc0, crc0, sdcrc1, crc1, sdcrc2, crc2, sdcrc3, crc3);
return 1;
}
return 0;
}
static inline void wait_busy(void) {
while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
wiggle_fast_neg1();
@ -459,8 +497,16 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
}
}
}
/* just eat the crcs for now */
if(dat) wiggle_fast_neg(17);
if(dat) {
#ifdef CONFIG_SD_DATACRC
if(get_and_check_datacrc(buf-512)) {
return CRC_ERROR;
}
#else
/* eat the crcs */
wiggle_fast_neg(17);
#endif
}
if(waitbusy) {
DBG_SD printf("waitbusy after send_cmd\n");
@ -528,7 +574,7 @@ int acmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* r
return cmd_fast(cmd, param, crc, dat, rsp);
}
void stream_datablock(uint8_t *buf) {
int stream_datablock(uint8_t *buf) {
// uint8_t datshift=8;
int j=512;
uint8_t datdata=0;
@ -559,9 +605,14 @@ void stream_datablock(uint8_t *buf) {
j--;
if(!j) break;
}
/* eat the crc for now */
#ifdef CONFIG_SD_DATACRC
return get_and_check_datacrc(buf-512);
#else
/* eat the crcs */
wiggle_fast_neg(17);
#endif
}
return 0;
}
void send_datablock(uint8_t *buf) {
@ -585,7 +636,7 @@ void send_datablock(uint8_t *buf) {
datshift=8;
do {
datshift-=4;
if(((*buf)>>datshift) & 0x8) {
/* if(((*buf)>>datshift) & 0x8) {
BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
} else {
BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
@ -604,7 +655,8 @@ void send_datablock(uint8_t *buf) {
BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
} else {
BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
}
}*/
SD_DAT0REG->FIOPIN0 = (*buf) >> datshift;
wiggle_fast_pos1();
} while (datshift);
@ -690,7 +742,17 @@ void send_datablock(uint8_t *buf) {
void read_block(uint32_t address, uint8_t *buf) {
if(during_blocktrans == TRANS_READ && (last_block == address-1)) {
//uart_putc('r');
#ifdef CONFIG_SD_DATACRC
int cmd_res;
if((cmd_res = stream_datablock(buf)) == CRC_ERROR) {
while(cmd_res == CRC_ERROR) {
cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
cmd_res = cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
}
}
#else
stream_datablock(buf);
#endif
last_block=address;
} else {
if(during_blocktrans) {
@ -703,7 +765,14 @@ void read_block(uint32_t address, uint8_t *buf) {
if(!ccs) {
address <<= 9;
}
#ifdef CONFIG_SD_DATACRC
while(1) {
if(cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp) != CRC_ERROR) break;
cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
};
#else
cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
#endif
during_blocktrans = TRANS_READ;
}
}
@ -840,6 +909,8 @@ void sdn_init(void) {
BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1;
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN) = 1;
LPC_GPIO2->FIOPIN0 = 0x00;
LPC_GPIO2->FIOMASK0 = ~0xf;
}
void disk_init(void) __attribute__ ((weak, alias("sdn_init")));

View File

@ -11,6 +11,8 @@
#include "diskio.h"
#define CRC_ERROR (0xf000)
extern int sd_offload;
/* These functions are weak-aliased to disk_... */

View File

@ -43,6 +43,8 @@ uint8_t initloop=1;
uint32_t saveram_crc, saveram_crc_old;
extern snes_romprops_t romprops;
volatile int reset_changed;
void prepare_reset() {
set_mcu_ovr(1);
snes_reset(1);
@ -142,7 +144,7 @@ uint8_t menu_main_loop() {
sram_writebyte(0, SRAM_CMD_ADDR);
while(!cmd) {
if(!get_snes_reset()) {
while(!sram_reliable())printf("hurr\n");;
while(!sram_reliable())printf("hurr\n");
cmd = sram_readbyte(SRAM_CMD_ADDR);
}
if(get_snes_reset()) {
@ -155,7 +157,8 @@ uint8_t menu_main_loop() {
}
void get_selected_name(uint8_t* fn) {
uint32_t addr = sram_readlong(SRAM_PARAM_ADDR);
uint32_t addr;
addr = sram_readlong(SRAM_PARAM_ADDR);
printf("fd addr=%lx\n", addr);
sram_readblock(fn, addr + 7 + SRAM_MENU_ADDR, 256);
}

View File

@ -7,6 +7,7 @@
#include "clock.h"
#include "uart.h"
#include "sdnative.h"
#include "snes.h"
/* bit definitions */
#define RITINT 0
@ -15,6 +16,7 @@
#define PCRIT 16
extern volatile int sd_changed;
extern volatile int reset_changed;
volatile tick_t ticks;
volatile int wokefromrit;
@ -26,10 +28,15 @@ void __attribute__((weak,noinline)) SysTick_Hook(void) {
void SysTick_Handler(void) {
ticks++;
static uint16_t sdch_state = 0;
static uint16_t reset_state = 0;
sdch_state = (sdch_state << 1) | SDCARD_DETECT | 0xe000;
if((sdch_state == 0xf000) || (sdch_state == 0xefff)) {
sd_changed = 1;
}
reset_state = (reset_state << 1) | get_snes_reset() | 0xe000;
if((reset_state == 0xf000) || (reset_state == 0xefff)) {
reset_changed = 1;
}
sdn_changed();
SysTick_Hook();
}