Compare commits

...

5 Commits

134 changed files with 21049 additions and 16614 deletions

View File

@ -79,3 +79,18 @@ v0.1.4a (bugfix release)
* Fix DMA initialization in the menu (could cause sprite corruption in some games) * Fix DMA initialization in the menu (could cause sprite corruption in some games)
v0.1.5
======
* Sort directories by entire file name instead of first 20 characters only
* Correctly map SRAM larger than 8192 bytes (HiROM) / 32768 bytes (LoROM)
(fixes Dezaemon, Ongaku Tsukuuru - Kanadeeru)
* SPC player: fix soft fade-in (first note cut off) on S-APU consoles
(1CHIP / some Jr.)
* More accurate BS-X memory map
* Ignore input from non-standard controllers (Super Scope, Mouse etc.)
* Fixes:
- minor memory access timing tweaks
(should help with occasional glitches on some systems)

View File

@ -2,7 +2,8 @@ version .byt " v0.1",0
zero .word 0 zero .word 0
bg2tile .byt $20 bg2tile .byt $20
space64 .byt $20, $20, $20, $20, $20, $20, $20, $20 space64
.byt $20, $20, $20, $20, $20, $20, $20, $20
.byt $20, $20, $20, $20, $20, $20, $20, $20 .byt $20, $20, $20, $20, $20, $20, $20, $20
.byt $20, $20, $20, $20, $20, $20, $20, $20 .byt $20, $20, $20, $20, $20, $20, $20, $20
.byt $20, $20, $20, $20, $20, $20, $20, $20 .byt $20, $20, $20, $20, $20, $20, $20, $20

View File

@ -26,7 +26,8 @@ textdmasize .word 0 ; number of bytes to copy each frame
infloop .byt 0,0 ; to be filled w/ 80 FE infloop .byt 0,0 ; to be filled w/ 80 FE
printloop_wram .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 printloop_wram
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
@ -34,7 +35,8 @@ printloop_wram .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
loprint_wram .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 loprint_wram
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

View File

@ -4,7 +4,15 @@ read_pad:
read_pad1 read_pad1
ldx pad1mem ;byetUDLRaxlriiii ldx pad1mem ;byetUDLRaxlriiii
lda $4218 lda $4218
ora $421a and #$000f
bne +
lda $4218
+ sta pad1mem
lda $421a
and #$000f
bne +
lda $421a
+ ora pad1mem
sta pad1mem sta pad1mem
and #$0f00 and #$0f00
bne read_pad1_count bne read_pad1_count

View File

@ -261,7 +261,19 @@ upload_dsp_regs:
ldx #$0000 ldx #$0000
- -
; initialize FLG and KON ($6c/$4c) to avoid artifacts
cpx #$4C
bne +
lda #$00
bra upload_skip_load
+
cpx #$6C
bne +
lda #$E0
bra upload_skip_load
+
lda @SPC_DSP_REGS,x lda @SPC_DSP_REGS,x
upload_skip_load
jsr spc_upload_byte jsr spc_upload_byte
inx inx
cpx #128 cpx #128
@ -439,6 +451,14 @@ restore_final:
ldx #$f3C4 ; MOV $f3,A -> $f2 has been set-up before by SPC700 loader ldx #$f3C4 ; MOV $f3,A -> $f2 has been set-up before by SPC700 loader
jsr exec_instr jsr exec_instr
; ---- wait a bit (the newer S-APU takes its time to ramp up the volume)
lda #$10
- pha
jsr waitblank
pla
dec
bne -
; ---- Restore DSP KON register ; ---- Restore DSP KON register
lda #$4C lda #$4C

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 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 sysinfo.c cfg.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 sysinfo.c cfg.c tests.c
# usbcontrol.c usb_hid.c usbhw_lpc.c usbinit.c usbstdreq.c # usbcontrol.c usb_hid.c usbhw_lpc.c usbinit.c usbstdreq.c
@ -75,7 +75,7 @@ ASRC = startup.S crc.S
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.) # (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
# Use s -mcall-prologues when you really need size... # Use s -mcall-prologues when you really need size...
#OPT = 2 #OPT = 2
OPT = 2 OPT = s
# Debugging format. # Debugging format.
DEBUG = dwarf-2 DEBUG = dwarf-2
@ -124,7 +124,8 @@ NM = $(ARCH)-nm
REMOVE = rm -f REMOVE = rm -f
COPY = cp COPY = cp
AWK = awk AWK = awk
RLE = ../utils/rle
BIN2H = utils/bin2h
#---------------- Compiler Options ---------------- #---------------- Compiler Options ----------------
# -g*: generate debugging information # -g*: generate debugging information
@ -197,7 +198,7 @@ ALL_ASFLAGS = -I. -x assembler-with-cpp $(ASFLAGS) $(CDEFS)
# Default target. # Default target.
all: build all: build
build: elf bin hex build: snesboot.h cfgware.h elf bin hex
$(E) " SIZE $(TARGET).elf" $(E) " SIZE $(TARGET).elf"
$(Q)$(ELFSIZE)|grep -v debug $(Q)$(ELFSIZE)|grep -v debug
cp $(TARGET).bin $(OBJDIR)/firmware.img cp $(TARGET).bin $(OBJDIR)/firmware.img
@ -217,19 +218,37 @@ sym: $(TARGET).sym
program: build program: build
utils/lpcchksum $(TARGET).bin utils/lpcchksum $(TARGET).bin
openocd -f openocd-usb.cfg -f lpc1754.cfg -f flash.cfg openocd -f interface/olimex-arm-usb-ocd.cfg -f lpc1754.cfg -f flash.cfg
debug: build debug: build
openocd -f openocd-usb.cfg -f lpc1754.cfg openocd -f interface/olimex-arm-usb-ocd.cfg -f lpc1754.cfg
reset: reset:
openocd -f openocd-usb.cfg -f lpc1754.cfg -f reset.cfg openocd -f interface/olimex-arm-usb-ocd.cfg -f lpc1754.cfg -f reset.cfg
# Display size of file. # Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -A $(TARGET).elf ELFSIZE = $(SIZE) -A $(TARGET).elf
# Generate cfgware.h
cfgware.h: $(OBJDIR)/fpga_rle.bit
$(E) " BIN2H $@"
$(Q) $(BIN2H) $< $@ cfgware
$(OBJDIR)/fpga_rle.bit: ../verilog/sd2sneslite/main.bit
$(E) " RLE $@"
$(Q) $(RLE) $< $@
#generate snesboot.h
snesboot.h: $(OBJDIR)/snesboot.rle
$(E) " BIN2H $@"
$(Q) $(BIN2H) $< $@ bootrle
$(OBJDIR)/snesboot.rle: ../snes/boot/menu.bin
$(E) " RLE $@"
$(Q) $(RLE) $< $@
# Generate autoconf.h from config # Generate autoconf.h from config
.PRECIOUS : $(OBJDIR)/autoconf.h .PRECIOUS : $(OBJDIR)/autoconf.h
@ -302,6 +321,7 @@ clean_list :
$(Q)$(REMOVE) $(TARGET).sym $(Q)$(REMOVE) $(TARGET).sym
$(Q)$(REMOVE) $(TARGET).lss $(Q)$(REMOVE) $(TARGET).lss
$(Q)$(REMOVE) $(OBJ) $(Q)$(REMOVE) $(OBJ)
$(Q)$(REMOVE) cfgware.h
$(Q)$(REMOVE) $(OBJDIR)/autoconf.h $(Q)$(REMOVE) $(OBJDIR)/autoconf.h
$(Q)$(REMOVE) $(OBJDIR)/*.bin $(Q)$(REMOVE) $(OBJDIR)/*.bin
$(Q)$(REMOVE) $(LST) $(Q)$(REMOVE) $(LST)

View File

@ -4,14 +4,14 @@
/* The classic macro */ /* The classic macro */
#define BV(x) (1<<(x)) #define BV(x) (1<<(x))
/* CM3 bit-band access macro - no error checks! */ /* CM3 bit-bang access macro - no error checks! */
#define BITBAND(addr,bit) \ #define BITBANG(addr,bit) \
(*((volatile unsigned long *)( \ (*((volatile unsigned long *)( \
((unsigned long)&(addr) & 0x01ffffff)*32 + \ ((unsigned long)&(addr) & 0x01ffffff)*32 + \
(bit)*4 + 0x02000000 + ((unsigned long)&(addr) & 0xfe000000) \ (bit)*4 + 0x02000000 + ((unsigned long)&(addr) & 0xfe000000) \
))) )))
#define BITBAND_OFF(addr,offset,bit) \ #define BITBANG_OFF(addr,offset,bit) \
(*((volatile unsigned long *)( \ (*((volatile unsigned long *)( \
(((unsigned long)&(addr) + offset) & 0x01ffffff)*32 + \ (((unsigned long)&(addr) + offset) & 0x01ffffff)*32 + \
(bit)*4 + 0x02000000 + (((unsigned long)&(addr) + offset) & 0xfe000000) \ (bit)*4 + 0x02000000 + (((unsigned long)&(addr) + offset) & 0xfe000000) \

View File

@ -31,7 +31,8 @@
#if _CODE_PAGE == 437 #if _CODE_PAGE == 437
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP437(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@ -53,7 +54,8 @@ const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 720 #elif _CODE_PAGE == 720
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP720(0x80-0xFF) to Unicode conversion table */
{
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9,
@ -75,7 +77,8 @@ const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 737 #elif _CODE_PAGE == 737
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP737(0x80-0xFF) to Unicode conversion table */
{
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398,
0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9,
@ -97,7 +100,8 @@ const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 775 #elif _CODE_PAGE == 775
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP775(0x80-0xFF) to Unicode conversion table */
{
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107,
0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A,
@ -119,7 +123,8 @@ const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 850 #elif _CODE_PAGE == 850
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP850(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@ -141,7 +146,8 @@ const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 852 #elif _CODE_PAGE == 852
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP852(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7,
0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A,
@ -163,7 +169,8 @@ const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 855 #elif _CODE_PAGE == 855
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP855(0x80-0xFF) to Unicode conversion table */
{
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404,
0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C,
@ -185,7 +192,8 @@ const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 857 #elif _CODE_PAGE == 857
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP857(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@ -207,7 +215,8 @@ const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 858 #elif _CODE_PAGE == 858
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP858(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@ -229,7 +238,8 @@ const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 862 #elif _CODE_PAGE == 862
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP862(0x80-0xFF) to Unicode conversion table */
{
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
@ -251,7 +261,8 @@ const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 866 #elif _CODE_PAGE == 866
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP866(0x80-0xFF) to Unicode conversion table */
{
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
@ -273,7 +284,8 @@ const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 874 #elif _CODE_PAGE == 874
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP874(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, 0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -295,7 +307,8 @@ const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1250 #elif _CODE_PAGE == 1250
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1250(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -317,7 +330,8 @@ const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1251 #elif _CODE_PAGE == 1251
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1251(0x80-0xFF) to Unicode conversion table */
{
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -339,7 +353,8 @@ const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1252 #elif _CODE_PAGE == 1252
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1252(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -361,7 +376,8 @@ const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1253 #elif _CODE_PAGE == 1253
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1253(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000, 0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -383,7 +399,8 @@ const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1254 #elif _CODE_PAGE == 1254
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1254(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -405,7 +422,8 @@ const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1255 #elif _CODE_PAGE == 1255
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1255(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -427,7 +445,8 @@ const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1256 #elif _CODE_PAGE == 1256
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1256(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -449,7 +468,8 @@ const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1257 #elif _CODE_PAGE == 1257
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1257(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8, 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -471,7 +491,8 @@ const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1258 #elif _CODE_PAGE == 1258
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1258(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, 0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -506,17 +527,28 @@ WCHAR ff_convert ( /* Converted character, Returns zero on error */
WCHAR c; WCHAR c;
if (src < 0x80) { /* ASCII */ if ( src < 0x80 ) /* ASCII */
{
c = src; c = src;
} else { }
if (dir) { /* OEMCP to Unicode */ else
{
if ( dir ) /* OEMCP to Unicode */
{
c = ( src >= 0x100 ) ? 0 : Tbl[src - 0x80]; c = ( src >= 0x100 ) ? 0 : Tbl[src - 0x80];
} else { /* Unicode to OEMCP */
for (c = 0; c < 0x80; c++) {
if (src == Tbl[c]) break;
} }
else /* Unicode to OEMCP */
{
for ( c = 0; c < 0x80; c++ )
{
if ( src == Tbl[c] )
{
break;
}
}
c = ( c + 0x80 ) & 0xFF; c = ( c + 0x80 ) & 0xFF;
} }
} }

View File

@ -7,12 +7,14 @@
#include "bits.h" #include "bits.h"
#include "uart.h" #include "uart.h"
void clock_disconnect() { void clock_disconnect()
{
disconnectPLL0(); disconnectPLL0();
disablePLL0(); disablePLL0();
} }
void clock_init() { void clock_init()
{
/* set flash access time to 6 clks (safe setting) */ /* set flash access time to 6 clks (safe setting) */
setFlashAccessTime( 6 ); setFlashAccessTime( 6 );
@ -54,54 +56,67 @@ void clock_init() {
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

@ -4,7 +4,7 @@
# file to a C header. No copyright claimed. # file to a C header. No copyright claimed.
BEGIN { BEGIN {
print "// autoconf.h generated from " ARGV[1] " at " strftime() "\n" \ print "// autoconf.h generated from " ARGV[1] " at NOW\n" \
"#ifndef AUTOCONF_H\n" \ "#ifndef AUTOCONF_H\n" \
"#define AUTOCONF_H" "#define AUTOCONF_H"
} }

View File

@ -27,12 +27,12 @@
#define IN_AHBRAM __attribute__ ((section(".ahbram"))) #define IN_AHBRAM __attribute__ ((section(".ahbram")))
#define SD_DT_INT_SETUP() do {\ #define SD_DT_INT_SETUP() do {\
BITBAND(LPC_GPIOINT->IO2IntEnR, SD_DT_BIT) = 1;\ BITBANG(LPC_GPIOINT->IO2IntEnR, SD_DT_BIT) = 1;\
BITBAND(LPC_GPIOINT->IO2IntEnF, SD_DT_BIT) = 1;\ BITBANG(LPC_GPIOINT->IO2IntEnF, SD_DT_BIT) = 1;\
} while(0) } while(0)
#define SD_CHANGE_DETECT (BITBAND(LPC_GPIOINT->IO2IntStatR, SD_DT_BIT)\ #define SD_CHANGE_DETECT (BITBANG(LPC_GPIOINT->IO2IntStatR, SD_DT_BIT)\
|BITBAND(LPC_GPIOINT->IO2IntStatF, SD_DT_BIT)) |BITBANG(LPC_GPIOINT->IO2IntStatF, SD_DT_BIT))
#define SD_CHANGE_CLR() do {LPC_GPIOINT->IO2IntClr = BV(SD_DT_BIT);} while(0) #define SD_CHANGE_CLR() do {LPC_GPIOINT->IO2IntClr = BV(SD_DT_BIT);} while(0)
@ -41,8 +41,8 @@
#define SD_WP_REG LPC_GPIO0 #define SD_WP_REG LPC_GPIO0
#define SD_WP_BIT 6 #define SD_WP_BIT 6
#define SDCARD_DETECT (!(BITBAND(SD_DT_REG->FIOPIN, SD_DT_BIT))) #define SDCARD_DETECT (!(BITBANG(SD_DT_REG->FIOPIN, SD_DT_BIT)))
#define SDCARD_WP (BITBAND(SD_WP_REG->FIOPIN, SD_WP_BIT)) #define SDCARD_WP (BITBANG(SD_WP_REG->FIOPIN, SD_WP_BIT))
#define SD_SUPPLY_VOLTAGE (1L<<21) /* 3.3V - 3.4V */ #define SD_SUPPLY_VOLTAGE (1L<<21) /* 3.3V - 3.4V */
#define CONFIG_SD_BLOCKTRANSFER 1 #define CONFIG_SD_BLOCKTRANSFER 1
#define CONFIG_SD_AUTO_RETRIES 10 #define CONFIG_SD_AUTO_RETRIES 10
@ -55,8 +55,8 @@
//#define CONFIG_CPU_FREQUENCY 46000000 //#define CONFIG_CPU_FREQUENCY 46000000
#define CONFIG_UART_PCLKDIV 1 #define CONFIG_UART_PCLKDIV 1
#define CONFIG_UART_TX_BUF_SHIFT 8 #define CONFIG_UART_TX_BUF_SHIFT 8
#define CONFIG_UART_BAUDRATE 921600 //#define CONFIG_UART_BAUDRATE 921600
//#define CONFIG_UART_BAUDRATE 115200 #define CONFIG_UART_BAUDRATE 115200
#define CONFIG_UART_DEADLOCKABLE #define CONFIG_UART_DEADLOCKABLE
#define SSP_CLK_DIVISOR_FAST 2 #define SSP_CLK_DIVISOR_FAST 2

View File

@ -32,11 +32,13 @@ uint32_t crc_reflect(uint32_t data, size_t data_len)
uint32_t ret; uint32_t ret;
ret = data & 0x01; ret = data & 0x01;
for ( i = 1; i < data_len; i++ ) for ( i = 1; i < data_len; i++ )
{ {
data >>= 1; data >>= 1;
ret = ( ret << 1 ) | ( data & 0x01 ); ret = ( ret << 1 ) | ( data & 0x01 );
} }
return ret; return ret;
} }
@ -56,16 +58,24 @@ uint32_t crc32_update(uint32_t crc, const unsigned char data)
unsigned char c; unsigned char c;
c = data; c = data;
for (i = 0x01; i & 0xff; i <<= 1) {
for ( i = 0x01; i & 0xff; i <<= 1 )
{
bit = crc & 0x80000000; bit = crc & 0x80000000;
if (c & i) {
if ( c & i )
{
bit = !bit; bit = !bit;
} }
crc <<= 1; crc <<= 1;
if (bit) {
if ( bit )
{
crc ^= 0x04c11db7; crc ^= 0x04c11db7;
} }
} }
return crc & 0xffffffff; return crc & 0xffffffff;
} }

View File

@ -16,7 +16,8 @@
typedef BYTE DSTATUS; typedef BYTE DSTATUS;
/* Results of Disk Functions */ /* Results of Disk Functions */
typedef enum { typedef enum
{
RES_OK = 0, /* 0: Successful */ RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */ RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */ RES_WRPRT, /* 2: Write Protected */
@ -35,7 +36,8 @@ typedef enum {
* This is the struct returned in the data buffer when disk_getinfo * This is the struct returned in the data buffer when disk_getinfo
* is called with page=0. * is called with page=0.
*/ */
typedef struct { typedef struct
{
uint8_t validbytes; uint8_t validbytes;
uint8_t maxpage; uint8_t maxpage;
uint8_t disktype; uint8_t disktype;

View File

@ -2,21 +2,26 @@
#include "config.h" #include "config.h"
#include "uart.h" #include "uart.h"
void HardFault_Handler(void) { void HardFault_Handler( void )
{
DBG_BL printf( "HFSR: %lx\n", SCB->HFSR ); DBG_BL printf( "HFSR: %lx\n", SCB->HFSR );
DBG_UART uart_putc( 'H' ); DBG_UART uart_putc( 'H' );
while ( 1 ) ; while ( 1 ) ;
} }
void MemManage_Handler(void) { void MemManage_Handler( void )
{
DBG_BL printf( "MemManage - CFSR: %lx; MMFAR: %lx\n", SCB->CFSR, SCB->MMFAR ); DBG_BL printf( "MemManage - CFSR: %lx; MMFAR: %lx\n", SCB->CFSR, SCB->MMFAR );
} }
void BusFault_Handler(void) { void BusFault_Handler( void )
{
DBG_BL printf( "BusFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR ); DBG_BL printf( "BusFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR );
} }
void UsageFault_Handler(void) { void UsageFault_Handler( void )
{
DBG_BL printf( "UsageFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR ); DBG_BL printf( "UsageFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR );
} }

File diff suppressed because it is too large Load Diff

View File

@ -229,7 +229,8 @@ extern "C" {
#if _MULTI_PARTITION /* Multiple partition configuration */ #if _MULTI_PARTITION /* Multiple partition configuration */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */ #define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */ #define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */
typedef struct { typedef struct
{
BYTE pd; /* Physical drive# */ BYTE pd; /* Physical drive# */
BYTE pt; /* Partition # (0-3) */ BYTE pt; /* Partition # (0-3) */
} PARTITION; } PARTITION;
@ -268,7 +269,8 @@ typedef char TCHAR;
/* File system object structure (FATFS) */ /* File system object structure (FATFS) */
typedef struct { typedef struct
{
BYTE fs_type; /* FAT sub-type (0:Not mounted) */ BYTE fs_type; /* FAT sub-type (0:Not mounted) */
BYTE drv; /* Physical drive number */ BYTE drv; /* Physical drive number */
BYTE csize; /* Sectors per cluster (1,2,4...128) */ BYTE csize; /* Sectors per cluster (1,2,4...128) */
@ -304,7 +306,8 @@ typedef struct {
/* File object structure (FIL) */ /* File object structure (FIL) */
typedef struct { typedef struct
{
FATFS *fs; /* Pointer to the owner file system object */ FATFS *fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */ WORD id; /* Owner file system mount ID */
BYTE flag; /* File status flags */ BYTE flag; /* File status flags */
@ -333,7 +336,8 @@ typedef struct {
/* Directory object structure (DIR) */ /* Directory object structure (DIR) */
typedef struct { typedef struct
{
FATFS *fs; /* Pointer to the owner file system object */ FATFS *fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */ WORD id; /* Owner file system mount ID */
WORD index; /* Current read/write index number */ WORD index; /* Current read/write index number */
@ -352,7 +356,8 @@ typedef struct {
/* File status structure (FILINFO) */ /* File status structure (FILINFO) */
typedef struct { typedef struct
{
DWORD fsize; /* File size */ DWORD fsize; /* File size */
WORD fdate; /* Last modified date */ WORD fdate; /* Last modified date */
WORD ftime; /* Last modified time */ WORD ftime; /* Last modified time */
@ -369,7 +374,8 @@ typedef struct {
/* File function return code (FRESULT) */ /* File function return code (FRESULT) */
typedef enum { typedef enum
{
FR_OK = 0, /* (0) Succeeded */ FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */ FR_INT_ERR, /* (2) Assertion failed */
@ -397,7 +403,8 @@ typedef enum {
/* FatFs module application interface */ /* FatFs module application interface */
/* Low Level functions */ /* 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 */ 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 */ /* application level functions */
FRESULT f_mount ( BYTE, FATFS * ); /* Mount/Unmount a logical drive */ FRESULT f_mount ( BYTE, FATFS * ); /* Mount/Unmount a logical drive */

View File

@ -12,36 +12,44 @@ WCHAR ff_convert(WCHAR w, UINT dir) {
int newcard; int newcard;
void file_init() { void file_init()
{
file_res = f_mount( 0, &fatfs ); file_res = f_mount( 0, &fatfs );
newcard = 0; newcard = 0;
} }
void file_reinit(void) { void file_reinit( void )
{
disk_init(); disk_init();
file_init(); file_init();
} }
void file_open_by_filinfo(FILINFO* fno) { void file_open_by_filinfo( FILINFO *fno )
{
file_res = l_openfilebycluster( &fatfs, &file_handle, ( TCHAR * )"", 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 )
if (disk_state == DISK_CHANGED) { {
if ( disk_state == DISK_CHANGED )
{
file_reinit(); file_reinit();
newcard = 1; newcard = 1;
} }
file_res = f_open( &file_handle, ( TCHAR * )filename, flags ); file_res = f_open( &file_handle, ( TCHAR * )filename, flags );
file_block_off = sizeof( file_buf ); file_block_off = sizeof( file_buf );
file_block_max = sizeof( file_buf ); file_block_max = sizeof( file_buf );
file_status = file_res ? FILE_ERR : FILE_OK; file_status = file_res ? FILE_ERR : FILE_OK;
} }
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;
@ -56,12 +64,16 @@ UINT file_read() {
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;
} }
@ -74,11 +86,19 @@ UINT file_readblock(void* buf, uint32_t addr, uint16_t size) {
return bytes_written; return bytes_written;
}*/ }*/
uint8_t file_getc() { uint8_t file_getc()
if(file_block_off == file_block_max) { {
if ( file_block_off == file_block_max )
{
file_block_max = file_read(); file_block_max = file_read();
if(file_block_max == 0) file_status = FILE_EOF;
if ( file_block_max == 0 )
{
file_status = FILE_EOF;
}
file_block_off = 0; file_block_off = 0;
} }
return file_buf[file_block_off++]; return file_buf[file_block_off++];
} }

View File

@ -31,13 +31,14 @@
enum filestates { FILE_OK = 0, FILE_ERR, FILE_EOF }; enum filestates { FILE_OK = 0, FILE_ERR, FILE_EOF };
BYTE file_buf[512]; #define GCC_ALIGN_WORKAROUND __attribute__ ((aligned(4)))
FATFS fatfs; extern BYTE file_buf[512];
FIL file_handle; extern FATFS fatfs;
FRESULT file_res; extern FIL file_handle;
uint8_t file_lfn[258]; extern FRESULT file_res;
uint16_t file_block_off, file_block_max; extern uint8_t file_lfn[258];
enum filestates file_status; extern uint16_t file_block_off, file_block_max;
extern enum filestates file_status;
void file_init( void ); void file_init( void );
void file_open( uint8_t *filename, BYTE flags ); void file_open( uint8_t *filename, BYTE flags );

View File

@ -14,75 +14,103 @@ uint32_t flash_sig[4];
IAP iap_entry = ( IAP ) IAP_LOCATION; IAP iap_entry = ( IAP ) IAP_LOCATION;
uint32_t calc_flash_crc(uint32_t start, uint32_t len) { uint32_t calc_flash_crc( uint32_t start, uint32_t len )
{
DBG_BL printf( "calc_flash_crc(%08lx, %08lx) {\n", start, len ); DBG_BL printf( "calc_flash_crc(%08lx, %08lx) {\n", start, len );
uint32_t end = start + len; uint32_t end = start + len;
if(end > 0x20000) {
if ( end > 0x20000 )
{
len = 0x1ffff - start; len = 0x1ffff - start;
end = 0x20000; end = 0x20000;
} }
uint32_t crc = 0xffffffff; uint32_t crc = 0xffffffff;
uint32_t s = start; uint32_t s = start;
while(s < end) {
while ( s < end )
{
crc = crc32_update( crc, *( const unsigned char * )( s ) ); crc = crc32_update( crc, *( const unsigned char * )( s ) );
s++; s++;
} }
crc = crc_finalize( crc ); crc = crc_finalize( crc );
DBG_BL printf( " crc generated. result=%08lx\n", crc ); DBG_BL printf( " crc generated. result=%08lx\n", crc );
DBG_BL printf( "} //calc_flash_crc\n" ); DBG_BL printf( "} //calc_flash_crc\n" );
return crc; return crc;
} }
void test_iap() { void test_iap()
{
iap_cmd[0] = 54; iap_cmd[0] = 54;
iap_entry( iap_cmd, iap_res ); iap_entry( iap_cmd, iap_res );
DBG_BL printf( "Part ID=%08lx\n", iap_res[1] ); DBG_BL printf( "Part ID=%08lx\n", iap_res[1] );
} }
void print_header(sd2snes_fw_header *header) { void print_header( sd2snes_fw_header *header )
{
DBG_BL printf( " magic = %08lx\n version = %08lx\n size = %08lx\n crc = %08lx\n ~crc = %08lx\n", DBG_BL printf( " magic = %08lx\n version = %08lx\n size = %08lx\n crc = %08lx\n ~crc = %08lx\n",
header->magic, header->version, header->size, header->magic, header->version, header->size,
header->crc, header->crcc ); header->crc, header->crcc );
} }
int check_header(sd2snes_fw_header *header, uint32_t crc) { int check_header( sd2snes_fw_header *header, uint32_t crc )
{
if ( ( header->magic != FW_MAGIC ) if ( ( header->magic != FW_MAGIC )
|| ( header->size < 0x200 ) || ( header->size < 0x200 )
|| ( header->size > ( 0x1ffff - FW_START ) ) || ( header->size > ( 0x1ffff - FW_START ) )
|| ((header->crc ^ header->crcc) != 0xffffffff)) { || ( ( header->crc ^ header->crcc ) != 0xffffffff ) )
{
return ERR_FLASHHD; return ERR_FLASHHD;
} }
if(header->crc != crc) {
if ( header->crc != crc )
{
return ERR_FLASHCRC; return ERR_FLASHCRC;
} }
return ERR_OK; return ERR_OK;
} }
FLASH_RES check_flash() { FLASH_RES check_flash()
{
sd2snes_fw_header *fw_header = ( sd2snes_fw_header * ) FW_START; sd2snes_fw_header *fw_header = ( sd2snes_fw_header * ) FW_START;
uint32_t flash_addr = FW_START; uint32_t flash_addr = FW_START;
if(flash_addr != FW_START) {
DBG_BL printf("address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", FW_START, flash_addr); if ( flash_addr != FW_START )
{
DBG_BL printf( "address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n",
FW_START, flash_addr );
return ERR_HW; return ERR_HW;
} }
DBG_BL printf( "Current flash contents:\n" ); DBG_BL printf( "Current flash contents:\n" );
DBG_BL print_header( fw_header ); DBG_BL print_header( fw_header );
uint32_t crc = calc_flash_crc( flash_addr + 0x100, ( fw_header->size & 0x1ffff ) ); uint32_t crc = calc_flash_crc( flash_addr + 0x100, ( fw_header->size & 0x1ffff ) );
return check_header( fw_header, crc ); return check_header( fw_header, crc );
} }
IAP_RES iap_wrap(uint32_t *iap_cmd, uint32_t *iap_res) { IAP_RES iap_wrap( uint32_t *iap_cmd, uint32_t *iap_res )
{
// NVIC_DisableIRQ(RIT_IRQn); // NVIC_DisableIRQ(RIT_IRQn);
// NVIC_DisableIRQ(UART_IRQ); // NVIC_DisableIRQ(UART_IRQ);
for ( volatile int i = 0; i < 2048; i++ ); for ( volatile int i = 0; i < 2048; i++ );
iap_entry( iap_cmd, iap_res ); iap_entry( iap_cmd, iap_res );
for ( volatile int i = 0; i < 2048; i++ ); for ( volatile int i = 0; i < 2048; i++ );
// NVIC_EnableIRQ(UART_IRQ); // NVIC_EnableIRQ(UART_IRQ);
return iap_res[0]; return iap_res[0];
} }
IAP_RES iap_prepare_for_write(uint32_t start, uint32_t end) { IAP_RES iap_prepare_for_write( uint32_t start, uint32_t end )
if(start < (FW_START / 0x1000)) return INVALID_SECTOR; {
if ( start < ( FW_START / 0x1000 ) )
{
return INVALID_SECTOR;
}
iap_cmd[0] = 50; iap_cmd[0] = 50;
iap_cmd[1] = start; iap_cmd[1] = start;
iap_cmd[2] = end; iap_cmd[2] = end;
@ -90,8 +118,13 @@ IAP_RES iap_prepare_for_write(uint32_t start, uint32_t end) {
return iap_res[0]; return iap_res[0];
} }
IAP_RES iap_erase(uint32_t start, uint32_t end) { IAP_RES iap_erase( uint32_t start, uint32_t end )
if(start < (FW_START / 0x1000)) return INVALID_SECTOR; {
if ( start < ( FW_START / 0x1000 ) )
{
return INVALID_SECTOR;
}
iap_cmd[0] = 52; iap_cmd[0] = 52;
iap_cmd[1] = start; iap_cmd[1] = start;
iap_cmd[2] = end; iap_cmd[2] = end;
@ -100,7 +133,8 @@ IAP_RES iap_erase(uint32_t start, uint32_t end) {
return iap_res[0]; return iap_res[0];
} }
IAP_RES iap_ram2flash(uint32_t tgt, uint8_t *src, int num) { IAP_RES iap_ram2flash( uint32_t tgt, uint8_t *src, int num )
{
iap_cmd[0] = 51; iap_cmd[0] = 51;
iap_cmd[1] = tgt; iap_cmd[1] = tgt;
iap_cmd[2] = ( uint32_t )src; iap_cmd[2] = ( uint32_t )src;
@ -110,43 +144,67 @@ IAP_RES iap_ram2flash(uint32_t tgt, uint8_t *src, int num) {
return iap_res[0]; return iap_res[0];
} }
FLASH_RES flash_file(uint8_t *filename) { FLASH_RES flash_file( uint8_t *filename )
{
sd2snes_fw_header *fw_header = ( sd2snes_fw_header * ) FW_START; sd2snes_fw_header *fw_header = ( sd2snes_fw_header * ) FW_START;
uint32_t flash_addr = FW_START; uint32_t flash_addr = FW_START;
uint32_t file_crc = 0xffffffff; uint32_t file_crc = 0xffffffff;
uint16_t count; uint16_t count;
sd2snes_fw_header file_header; sd2snes_fw_header file_header;
UINT bytes_read; UINT bytes_read;
if(flash_addr != FW_START) {
DBG_BL printf("address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", FW_START, flash_addr); if ( flash_addr != FW_START )
{
DBG_BL printf( "address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n",
FW_START, flash_addr );
return ERR_HW; return ERR_HW;
} }
file_open( filename, FA_READ ); file_open( filename, FA_READ );
if(file_res) {
if ( file_res )
{
DBG_BL printf( "file_open: error %d\n", file_res ); DBG_BL printf( "file_open: error %d\n", file_res );
return ERR_FS; return ERR_FS;
} }
DBG_BL printf( "firmware image found. file size: %ld\n", file_handle.fsize ); DBG_BL printf( "firmware image found. file size: %ld\n", file_handle.fsize );
DBG_BL printf( "reading header...\n" ); DBG_BL printf( "reading header...\n" );
f_read( &file_handle, &file_header, 32, &bytes_read ); f_read( &file_handle, &file_header, 32, &bytes_read );
DBG_BL 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) {
if ( check_flash() || file_header.version != fw_header->version || file_header.version == FW_MAGIC
|| fw_header->version == FW_MAGIC )
{
DBG_UART uart_putc( 'F' ); DBG_UART uart_putc( 'F' );
f_read( &file_handle, file_buf, 0xe0, &bytes_read ); f_read( &file_handle, file_buf, 0xe0, &bytes_read );
for(;;) {
for ( ;; )
{
bytes_read = file_read(); bytes_read = file_read();
if(file_res || !bytes_read) break;
for(count = 0; count < bytes_read; count++) { if ( file_res || !bytes_read )
{
break;
}
for ( count = 0; count < bytes_read; count++ )
{
file_crc = crc32_update( file_crc, file_buf[count] ); file_crc = crc32_update( file_crc, file_buf[count] );
} }
} }
file_crc = crc_finalize( file_crc ); file_crc = crc_finalize( file_crc );
DBG_BL printf( "file crc=%08lx\n", file_crc ); DBG_BL printf( "file crc=%08lx\n", file_crc );
if(check_header(&file_header, file_header.crc) != ERR_OK) {
if ( check_header( &file_header, file_header.crc ) != ERR_OK )
{
DBG_BL printf( "Invalid firmware file (header corrupted).\n" ); DBG_BL printf( "Invalid firmware file (header corrupted).\n" );
return ERR_FILEHD; return ERR_FILEHD;
} }
if(file_header.crc != file_crc) {
if ( file_header.crc != file_crc )
{
DBG_BL printf( "Firmware file checksum error.\n" ); DBG_BL printf( "Firmware file checksum error.\n" );
return ERR_FILECHK; return ERR_FILECHK;
} }
@ -156,53 +214,82 @@ FLASH_RES flash_file(uint8_t *filename) {
writeled( 1 ); writeled( 1 );
DBG_BL printf( "erasing flash...\n" ); DBG_BL printf( "erasing flash...\n" );
DBG_UART uart_putc( 'P' ); DBG_UART uart_putc( 'P' );
if((res = iap_prepare_for_write(FW_START / 0x1000, FLASH_SECTORS)) != CMD_SUCCESS) {
if ( ( res = iap_prepare_for_write( FW_START / 0x1000, FLASH_SECTORS ) ) != CMD_SUCCESS )
{
DBG_BL printf( "error %ld while preparing for erase\n", res ); DBG_BL printf( "error %ld while preparing for erase\n", res );
DBG_UART uart_putc( 'X' ); DBG_UART uart_putc( 'X' );
return ERR_FLASHPREP; return ERR_FLASHPREP;
}; };
DBG_UART uart_putc( 'E' ); DBG_UART uart_putc( 'E' );
if((res = iap_erase(FW_START / 0x1000, FLASH_SECTORS)) != CMD_SUCCESS) {
if ( ( res = iap_erase( FW_START / 0x1000, FLASH_SECTORS ) ) != CMD_SUCCESS )
{
DBG_BL printf( "error %ld while erasing\n", res ); DBG_BL printf( "error %ld while erasing\n", res );
DBG_UART uart_putc( 'X' ); DBG_UART uart_putc( 'X' );
return ERR_FLASHERASE; return ERR_FLASHERASE;
} }
DBG_BL printf( "writing... @%08lx\n", flash_addr ); DBG_BL printf( "writing... @%08lx\n", flash_addr );
file_close(); file_close();
file_open( filename, FA_READ ); file_open( filename, FA_READ );
uint8_t current_sec; uint8_t current_sec;
uint32_t total_read = 0; uint32_t total_read = 0;
for(flash_addr = FW_START; flash_addr < 0x00020000; flash_addr += 0x200) {
for ( flash_addr = FW_START; flash_addr < 0x00020000; flash_addr += 0x200 )
{
total_read += ( bytes_read = file_read() ); total_read += ( bytes_read = file_read() );
if(file_res || !bytes_read) break;
if ( file_res || !bytes_read )
{
break;
}
current_sec = flash_addr & 0x10000 ? ( 16 + ( ( flash_addr >> 15 ) & 1 ) ) current_sec = flash_addr & 0x10000 ? ( 16 + ( ( flash_addr >> 15 ) & 1 ) )
: ( flash_addr >> 12 ); : ( flash_addr >> 12 );
DBG_BL printf( "current_sec=%d flash_addr=%08lx\n", current_sec, flash_addr ); DBG_BL printf( "current_sec=%d flash_addr=%08lx\n", current_sec, flash_addr );
DBG_UART uart_putc( '.' ); DBG_UART uart_putc( '.' );
if(current_sec < (FW_START / 0x1000)) return ERR_FLASH;
if ( current_sec < ( FW_START / 0x1000 ) )
{
return ERR_FLASH;
}
DBG_UART uart_putc( current_sec["0123456789ABCDEFGH"] ); DBG_UART uart_putc( current_sec["0123456789ABCDEFGH"] );
DBG_UART uart_putc( 'p' ); DBG_UART uart_putc( 'p' );
if((res = iap_prepare_for_write(current_sec, current_sec)) != CMD_SUCCESS) {
if ( ( res = iap_prepare_for_write( current_sec, current_sec ) ) != CMD_SUCCESS )
{
DBG_BL printf( "error %ld while preparing sector %d for write\n", res, current_sec ); DBG_BL printf( "error %ld while preparing sector %d for write\n", res, current_sec );
DBG_UART uart_putc( 'X' ); DBG_UART uart_putc( 'X' );
return ERR_FLASH; return ERR_FLASH;
} }
DBG_UART uart_putc( 'w' ); DBG_UART uart_putc( 'w' );
if((res = iap_ram2flash(flash_addr, file_buf, 512)) != CMD_SUCCESS) {
DBG_BL printf("error %ld while writing to address %08lx (sector %d)\n", res, flash_addr, current_sec); if ( ( res = iap_ram2flash( flash_addr, file_buf, 512 ) ) != CMD_SUCCESS )
{
//printf("error %ld while writing to address %08lx (sector %d)\n", res, flash_addr, current_sec);
DBG_UART uart_putc( 'X' ); DBG_UART uart_putc( 'X' );
return ERR_FLASH; return ERR_FLASH;
} }
} }
if(total_read != (file_header.size + 0x100)) {
if ( total_read != ( file_header.size + 0x100 ) )
{
DBG_BL printf( "wrote less data than expected! (%08lx vs. %08lx)\n", total_read, file_header.size ); DBG_BL printf( "wrote less data than expected! (%08lx vs. %08lx)\n", total_read, file_header.size );
// DBG_UART uart_putc('X'); // DBG_UART uart_putc('X');
return ERR_FILECHK; return ERR_FILECHK;
} }
writeled( 0 ); writeled( 0 );
} else { }
else
{
DBG_UART 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" ); DBG_BL printf( "flash content is ok, no version mismatch, no forced upgrade. No need to flash\n" );
} }
return ERR_OK; return ERR_OK;
} }

View File

@ -6,7 +6,8 @@ typedef void (*IAP)(uint32_t*, uint32_t*);
typedef enum {ERR_OK = 0, ERR_HW, ERR_FS, ERR_FILEHD, ERR_FILECHK, ERR_FLASHHD, ERR_FLASHCRC, ERR_FLASHPREP, ERR_FLASHERASE, ERR_FLASH} FLASH_RES; typedef enum {ERR_OK = 0, ERR_HW, ERR_FS, ERR_FILEHD, ERR_FILECHK, ERR_FLASHHD, ERR_FLASHCRC, ERR_FLASHPREP, ERR_FLASHERASE, ERR_FLASH} FLASH_RES;
typedef enum { typedef enum
{
/* 0*/ CMD_SUCCESS = 0, /* 0*/ CMD_SUCCESS = 0,
/* 1*/ INVALID_COMMAND, /* 1*/ INVALID_COMMAND,
/* 2*/ SRC_ADDR_ERROR, /* 2*/ SRC_ADDR_ERROR,
@ -23,7 +24,8 @@ typedef enum {
#define FW_MAGIC (0x44534E53) #define FW_MAGIC (0x44534E53)
typedef struct { typedef struct
{
uint32_t magic; uint32_t magic;
uint32_t version; uint32_t version;
uint32_t size; uint32_t size;

View File

@ -18,23 +18,28 @@ int led_writeledstate = 0;
write red P1.23 PWM1[4] write red P1.23 PWM1[4]
*/ */
void rdyled(unsigned int state) { void rdyled( unsigned int state )
BITBAND(LPC_GPIO2->FIODIR, 4) = state; {
BITBANG( LPC_GPIO2->FIODIR, 4 ) = state;
led_rdyledstate = state; led_rdyledstate = state;
} }
void readled(unsigned int state) { void readled( unsigned int state )
BITBAND(LPC_GPIO2->FIODIR, 5) = state; {
BITBANG( LPC_GPIO2->FIODIR, 5 ) = state;
led_readledstate = state; led_readledstate = state;
} }
void writeled(unsigned int state) { void writeled( unsigned int state )
BITBAND(LPC_GPIO1->FIODIR, 23) = state; {
BITBANG( LPC_GPIO1->FIODIR, 23 ) = state;
led_writeledstate = state; led_writeledstate = state;
} }
void led_clkout32(uint32_t val) { void led_clkout32( uint32_t val )
while(1) { {
while ( 1 )
{
rdyled( 1 ); rdyled( 1 );
delay_ms( 400 ); delay_ms( 400 );
readled( ( val & BV( 31 ) ) >> 31 ); readled( ( val & BV( 31 ) ) >> 31 );
@ -44,20 +49,25 @@ void led_clkout32(uint32_t val) {
} }
} }
void toggle_rdy_led() { void toggle_rdy_led()
{
rdyled( ~led_rdyledstate ); rdyled( ~led_rdyledstate );
} }
void toggle_read_led() { void toggle_read_led()
{
readled( ~led_readledstate ); readled( ~led_readledstate );
} }
void toggle_write_led() { void toggle_write_led()
{
writeled( ~led_writeledstate ); writeled( ~led_writeledstate );
} }
void led_panic() { void led_panic()
while(1) { {
while ( 1 )
{
LPC_GPIO2->FIODIR |= BV( 4 ) | BV( 5 ); LPC_GPIO2->FIODIR |= BV( 4 ) | BV( 5 );
LPC_GPIO1->FIODIR |= BV( 23 ); LPC_GPIO1->FIODIR |= BV( 23 );
delay_ms( 350 ); delay_ms( 350 );
@ -67,24 +77,26 @@ void led_panic() {
} }
} }
void led_std() { void led_std()
BITBAND(LPC_PINCON->PINSEL4, 9) = 0; {
BITBAND(LPC_PINCON->PINSEL4, 8) = 0; BITBANG( LPC_PINCON->PINSEL4, 9 ) = 0;
BITBANG( LPC_PINCON->PINSEL4, 8 ) = 0;
BITBAND(LPC_PINCON->PINSEL4, 11) = 0; BITBANG( LPC_PINCON->PINSEL4, 11 ) = 0;
BITBAND(LPC_PINCON->PINSEL4, 10) = 0; BITBANG( LPC_PINCON->PINSEL4, 10 ) = 0;
BITBAND(LPC_PINCON->PINSEL3, 15) = 0; BITBANG( LPC_PINCON->PINSEL3, 15 ) = 0;
BITBAND(LPC_PINCON->PINSEL3, 14) = 0; BITBANG( LPC_PINCON->PINSEL3, 14 ) = 0;
BITBAND(LPC_PWM1->PCR, 12) = 0; BITBANG( LPC_PWM1->PCR, 12 ) = 0;
BITBAND(LPC_PWM1->PCR, 13) = 0; BITBANG( LPC_PWM1->PCR, 13 ) = 0;
BITBAND(LPC_PWM1->PCR, 14) = 0; BITBANG( LPC_PWM1->PCR, 14 ) = 0;
} }
void led_init() { void led_init()
{
/* power is already connected by default */ /* power is already connected by default */
/* set PCLK divider to 8 */ /* set PCLK divider to 8 */
BITBAND(LPC_SC->PCLKSEL1, 21) = 1; BITBANG( LPC_SC->PCLKSEL1, 21 ) = 1;
BITBAND(LPC_SC->PCLKSEL1, 20) = 1; BITBANG( LPC_SC->PCLKSEL1, 20 ) = 1;
} }

View File

@ -27,9 +27,9 @@ if { [info exists CPUTAPID ] } {
#delays on reset lines #delays on reset lines
#if your OpenOCD version rejects "jtag_nsrst_delay" replace it with: #if your OpenOCD version rejects "jtag_nsrst_delay" replace it with:
#adapter_nsrst_delay 200 adapter_nsrst_delay 200
jtag_nsrst_delay 200 #jtag_nsrst_delay 200
jtag_ntrst_delay 200 #jtag_ntrst_delay 200
# LPC2000 & LPC1700 -> SRST causes TRST # LPC2000 & LPC1700 -> SRST causes TRST
#reset_config srst_pulls_trst #reset_config srst_pulls_trst
@ -56,7 +56,7 @@ flash bank $_FLASHNAME lpc2000 0x0 0x20000 0 0 $_TARGETNAME \
# Run with *real slow* clock by default since the # Run with *real slow* clock by default since the
# boot rom could have been playing with the PLL, so # boot rom could have been playing with the PLL, so
# we have no idea what clock the target is running at. # we have no idea what clock the target is running at.
jtag_khz 1000 adapter_khz 1000
$_TARGETNAME configure -event reset-init { $_TARGETNAME configure -event reset-init {
# Do not remap 0x0000-0x0020 to anything but the flash (i.e. select # Do not remap 0x0000-0x0020 to anything but the flash (i.e. select

View File

@ -20,14 +20,24 @@
int i; int i;
BYTE file_buf[512] GCC_ALIGN_WORKAROUND;
FATFS fatfs;
FIL file_handle;
FRESULT file_res;
uint8_t file_lfn[258];
uint16_t file_block_off, file_block_max;
enum filestates file_status;
volatile enum diskstates disk_state; volatile enum diskstates disk_state;
extern volatile tick_t ticks; extern volatile tick_t ticks;
int ( *chain )( void ); int ( *chain )( void );
int main(void) { int main( void )
{
SNES_CIC_PAIR_REG->FIODIR = BV( SNES_CIC_PAIR_BIT ); SNES_CIC_PAIR_REG->FIODIR = BV( SNES_CIC_PAIR_BIT );
BITBAND(SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT) = 1; BITBANG( SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT ) = 1;
/* LPC_GPIO2->FIODIR = BV(0) | BV(1) | BV(2); */ /* LPC_GPIO2->FIODIR = BV(0) | BV(1) | BV(2); */
// LPC_GPIO0->FIODIR = BV(16); // LPC_GPIO0->FIODIR = BV(16);
@ -52,8 +62,16 @@ int main(void) {
clock_init(); clock_init();
// LPC_PINCON->PINSEL0 |= BV(20) | BV(21); /* MAT3.0 (FPGA clock) */ // LPC_PINCON->PINSEL0 |= BV(20) | BV(21); /* MAT3.0 (FPGA clock) */
sdn_init(); sdn_init();
for ( i = 0; i < 20; i++ )
{
uart_putc( '-' );
}
uart_putc( '\n' );
DBG_BL printf( "chksum=%08lx\n", *( uint32_t * )28 ); DBG_BL printf( "chksum=%08lx\n", *( uint32_t * )28 );
DBG_BL printf("\n\nsd2snes mk.2 bootloader\nver.: " VER "\ncpu clock: %ld Hz\n", CONFIG_CPU_FREQUENCY); /*DBG_BL*/ printf( "\n\nsd2snes mk.2 bootloader\nver.: " VER "\ncpu clock: %ld Hz\n", CONFIG_CPU_FREQUENCY );
DBG_BL printf( "PCONP=%lx\n", LPC_SC->PCONP ); DBG_BL printf( "PCONP=%lx\n", LPC_SC->PCONP );
/* setup timer (fpga clk) */ /* setup timer (fpga clk) */
LPC_TIM3->CTCR = 0; LPC_TIM3->CTCR = 0;
@ -64,24 +82,35 @@ DBG_BL printf("PCONP=%lx\n", LPC_SC->PCONP);
NVIC->ICER[0] = 0xffffffff; NVIC->ICER[0] = 0xffffffff;
NVIC->ICER[1] = 0xffffffff; NVIC->ICER[1] = 0xffffffff;
FLASH_RES res = flash_file( ( uint8_t * )"/sd2snes/firmware.img" ); FLASH_RES res = flash_file( ( uint8_t * )"/sd2snes/firmware.img" );
if(res == ERR_FLASHPREP || res == ERR_FLASHERASE || res == ERR_FLASH) {
if ( res == ERR_FLASHPREP || res == ERR_FLASHERASE || res == ERR_FLASH )
{
rdyled( 0 ); rdyled( 0 );
writeled( 1 ); writeled( 1 );
} }
if(res == ERR_FILEHD || res == ERR_FILECHK) {
if ( res == ERR_FILEHD || res == ERR_FILECHK )
{
rdyled( 0 ); rdyled( 0 );
readled( 1 ); readled( 1 );
} }
DBG_BL printf( "flash result = %d\n", res ); DBG_BL printf( "flash result = %d\n", res );
if(res != ERR_OK) {
if((res = check_flash()) != ERR_OK) { if ( res != ERR_OK )
{
if ( ( res = check_flash() ) != ERR_OK )
{
DBG_BL printf( "check_flash() failed with error %d, not booting.\n", res ); DBG_BL printf( "check_flash() failed with error %d, not booting.\n", res );
while(1) {
while ( 1 )
{
toggle_rdy_led(); toggle_rdy_led();
delay_ms( 500 ); delay_ms( 500 );
} }
} }
} }
NVIC_DisableIRQ( RIT_IRQn ); NVIC_DisableIRQ( RIT_IRQn );
NVIC_DisableIRQ( UART_IRQ ); NVIC_DisableIRQ( UART_IRQ );
@ -97,6 +126,7 @@ DBG_BL printf("PCONP=%lx\n", LPC_SC->PCONP);
uart_putc( "0123456789abcdef"[( ( uint32_t )chain ) & 15] ); uart_putc( "0123456789abcdef"[( ( uint32_t )chain ) & 15] );
uart_putc( '\n' ); uart_putc( '\n' );
chain(); chain();
while ( 1 ); while ( 1 );
} }

View File

@ -5,8 +5,14 @@
# #
interface ft2232 interface ft2232
ft2232_vid_pid 0x0403 0x6010 ft2232_vid_pid 0x15ba 0x0003
ft2232_device_desc "Dual RS232" ft2232_device_desc "Olimex OpenOCD JTAG"
ft2232_layout "oocdlink" ft2232_layout "olimex-jtag"
ft2232_latency 2
#interface ft2232
#ft2232_vid_pid 0x0403 0x6010
#ft2232_device_desc "Dual RS232"
#ft2232_layout "oocdlink"
#ft2232_latency 2
#adapter_khz 10 #adapter_khz 10

View File

@ -15,7 +15,8 @@
* USB [enabled via usb_init] * USB [enabled via usb_init]
* PWM1 * PWM1
*/ */
void power_init() { void power_init()
{
LPC_SC->PCONP = BV( PCSSP0 ) LPC_SC->PCONP = BV( PCSSP0 )
| BV( PCTIM3 ) | BV( PCTIM3 )
| BV( PCRTC ) | BV( PCRTC )

View File

@ -62,8 +62,10 @@ static char *outptr;
static int maxlen; static int maxlen;
/* printf */ /* printf */
static void outchar(char x) { static void outchar( char x )
if (maxlen) { {
if ( maxlen )
{
maxlen--; maxlen--;
outfunc( x ); outfunc( x );
outlength++; outlength++;
@ -71,15 +73,18 @@ static void outchar(char x) {
} }
/* sprintf */ /* sprintf */
static void outstr(char x) { static void outstr( char x )
if (maxlen) { {
if ( maxlen )
{
maxlen--; maxlen--;
*outptr++ = x; *outptr++ = x;
outlength++; outlength++;
} }
} }
static int internal_nprintf(void (*output_function)(char c), const char *fmt, va_list ap) { static int internal_nprintf( void ( *output_function )( char c ), const char *fmt, va_list ap )
{
unsigned int width; unsigned int width;
unsigned int flags; unsigned int flags;
unsigned int base = 0; unsigned int base = 0;
@ -87,16 +92,24 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
outlength = 0; outlength = 0;
while (*fmt) { while ( *fmt )
while (1) { {
while ( 1 )
{
if ( *fmt == 0 ) if ( *fmt == 0 )
{
goto end; goto end;
}
if (*fmt == '%') { if ( *fmt == '%' )
{
fmt++; fmt++;
if ( *fmt != '%' ) if ( *fmt != '%' )
{
break; break;
} }
}
output_function( *fmt++ ); output_function( *fmt++ );
} }
@ -105,9 +118,12 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
width = 0; width = 0;
/* read all flags */ /* read all flags */
do { do
if (flags < FLAG_WIDTH) { {
switch (*fmt) { if ( flags < FLAG_WIDTH )
{
switch ( *fmt )
{
case '0': case '0':
flags |= FLAG_ZEROPAD; flags |= FLAG_ZEROPAD;
continue; continue;
@ -126,8 +142,10 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
} }
} }
if (flags < FLAG_LONG) { if ( flags < FLAG_LONG )
if (*fmt >= '0' && *fmt <= '9') { {
if ( *fmt >= '0' && *fmt <= '9' )
{
unsigned char tmp = *fmt - '0'; unsigned char tmp = *fmt - '0';
width = 10 * width + tmp; width = 10 * width + tmp;
flags |= FLAG_WIDTH; flags |= FLAG_WIDTH;
@ -135,20 +153,26 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
} }
if ( *fmt == 'h' ) if ( *fmt == 'h' )
{
continue; continue;
}
if (*fmt == 'l') { if ( *fmt == 'l' )
{
flags |= FLAG_LONG; flags |= FLAG_LONG;
continue; continue;
} }
} }
break; break;
} while (*fmt++); }
while ( *fmt++ );
/* Strings */ /* Strings */
if (*fmt == 'c' || *fmt == 's') { if ( *fmt == 'c' || *fmt == 's' )
switch (*fmt) { {
switch ( *fmt )
{
case 'c': case 'c':
buffer[0] = va_arg( ap, int ); buffer[0] = va_arg( ap, int );
ptr = buffer; ptr = buffer;
@ -163,9 +187,11 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
} }
/* Numbers */ /* Numbers */
switch (*fmt) { switch ( *fmt )
{
case 'u': case 'u':
flags |= FLAG_UNSIGNED; flags |= FLAG_UNSIGNED;
case 'd': case 'd':
base = 10; base = 10;
break; break;
@ -179,6 +205,7 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
output_function( '0' ); output_function( '0' );
output_function( 'x' ); output_function( 'x' );
width -= 2; width -= 2;
case 'x': case 'x':
case 'X': case 'X':
base = 16; base = 16;
@ -188,59 +215,89 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
unsigned int num; unsigned int num;
if (!(flags & FLAG_UNSIGNED)) { if ( !( flags & FLAG_UNSIGNED ) )
{
int tmp = va_arg( ap, int ); int tmp = va_arg( ap, int );
if (tmp < 0) {
if ( tmp < 0 )
{
num = -tmp; num = -tmp;
flags |= FLAG_NEGATIVE; flags |= FLAG_NEGATIVE;
} else }
else
{
num = tmp; num = tmp;
} else { }
}
else
{
num = va_arg( ap, unsigned int ); num = va_arg( ap, unsigned int );
} }
/* Convert number into buffer */ /* Convert number into buffer */
ptr = buffer + sizeof( buffer ); ptr = buffer + sizeof( buffer );
*--ptr = 0; *--ptr = 0;
do {
do
{
*--ptr = hexdigits[num % base]; *--ptr = hexdigits[num % base];
num /= base; num /= base;
} while (num != 0); }
while ( num != 0 );
/* Sign */ /* Sign */
if (flags & FLAG_NEGATIVE) { if ( flags & FLAG_NEGATIVE )
{
output_function( '-' ); output_function( '-' );
width--; width--;
} else if (flags & FLAG_FORCESIGN) { }
else if ( flags & FLAG_FORCESIGN )
{
output_function( '+' ); output_function( '+' );
width--; width--;
} else if (flags & FLAG_BLANK) { }
else if ( flags & FLAG_BLANK )
{
output_function( ' ' ); output_function( ' ' );
width--; width--;
} }
output: output:
/* left padding */ /* left padding */
if ((flags & FLAG_WIDTH) && !(flags & FLAG_LEFTADJ)) { if ( ( flags & FLAG_WIDTH ) && !( flags & FLAG_LEFTADJ ) )
while (strlen(ptr) < width) { {
while ( strlen( ptr ) < width )
{
if ( flags & FLAG_ZEROPAD ) if ( flags & FLAG_ZEROPAD )
{
output_function( '0' ); output_function( '0' );
}
else else
{
output_function( ' ' ); output_function( ' ' );
}
width--; width--;
} }
} }
/* data */ /* data */
while (*ptr) { while ( *ptr )
{
output_function( *ptr++ ); output_function( *ptr++ );
if ( width ) if ( width )
{
width--; width--;
} }
}
/* right padding */ /* right padding */
if (flags & FLAG_WIDTH) { if ( flags & FLAG_WIDTH )
while (width) { {
while ( width )
{
output_function( ' ' ); output_function( ' ' );
width--; width--;
} }
@ -253,7 +310,8 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
return outlength; return outlength;
} }
int printf(const char *format, ...) { int printf( const char *format, ... )
{
va_list ap; va_list ap;
int res; int res;
@ -264,7 +322,8 @@ int printf(const char *format, ...) {
return res; return res;
} }
int snprintf(char *str, size_t size, const char *format, ...) { int snprintf( char *str, size_t size, const char *format, ... )
{
va_list ap; va_list ap;
int res; int res;
@ -273,28 +332,43 @@ int snprintf(char *str, size_t size, const char *format, ...) {
va_start( ap, format ); va_start( ap, format );
res = internal_nprintf( outstr, format, ap ); res = internal_nprintf( outstr, format, ap );
va_end( ap ); va_end( ap );
if ( res < size ) if ( res < size )
{
str[res] = 0; str[res] = 0;
}
return res; return res;
} }
/* Required for gcc compatibility */ /* Required for gcc compatibility */
int puts(const char *str) { int puts( const char *str )
{
uart_puts( str ); uart_puts( str );
uart_putc( '\n' ); uart_putc( '\n' );
return 0; return 0;
} }
#undef putchar #undef putchar
int putchar(int c) { int putchar( int c )
{
uart_putc( c ); uart_putc( c );
return 0; return 0;
} }
#else #else
int printf(const char *format, ...) { return 0; } int printf( const char *format, ... )
int snprintf(char *str, size_t size, const char *format, ...) { return 0; } {
int puts(const char *str) { return 0; } return 0;
}
//int snprintf(char *str, size_t size, const char *format, ...) { return 0; }
int puts( const char *str )
{
return 0;
}
#undef putchar #undef putchar
int putchar(int c) { return 0; } int putchar( int c )
{
return 0;
}
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
/* ___INGO___ */ /* ___INGO___ */
#include <arm/NXP/LPC17xx/LPC17xx.h> #include <arm/NXP/LPC17xx/LPC17xx.h>
#include "bits.h" #include "bits.h"
#include "config.h" #include "config.h"
@ -18,39 +17,42 @@ extern volatile int sd_changed;
volatile tick_t ticks; volatile tick_t ticks;
volatile int wokefromrit; volatile int wokefromrit;
void timer_init(void) { void timer_init( void )
{
/* turn on power to RIT */ /* turn on power to RIT */
BITBAND(LPC_SC->PCONP, PCRIT) = 1; BITBANG( 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; BITBANG( LPC_SC->PCLKSEL1, 26 ) = 1;
BITBAND(LPC_SC->PCLKSEL1, PCLK_TIMER3) = 1; BITBANG( LPC_SC->PCLKSEL1, PCLK_TIMER3 ) = 1;
} }
void delay_us(unsigned int time) { void delay_us( unsigned int time )
{
/* Prepare RIT */ /* Prepare RIT */
LPC_RIT->RICOUNTER = 0; LPC_RIT->RICOUNTER = 0;
LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000000 ) * time; LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000000 ) * time;
LPC_RIT->RICTRL = BV( RITEN ) | BV( RITINT ); LPC_RIT->RICTRL = BV( RITEN ) | BV( RITINT );
/* Wait until RIT signals an interrupt */ /* Wait until RIT signals an interrupt */
while (!(BITBAND(LPC_RIT->RICTRL, RITINT))) ; while ( !( BITBANG( LPC_RIT->RICTRL, RITINT ) ) ) ;
/* Disable RIT */ /* Disable RIT */
LPC_RIT->RICTRL = 0; LPC_RIT->RICTRL = 0;
} }
void delay_ms(unsigned int time) { void delay_ms( unsigned int time )
{
/* Prepare RIT */ /* Prepare RIT */
LPC_RIT->RICOUNTER = 0; LPC_RIT->RICOUNTER = 0;
LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000 ) * time; LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000 ) * time;
LPC_RIT->RICTRL = BV( RITEN ) | BV( RITINT ); LPC_RIT->RICTRL = BV( RITEN ) | BV( RITINT );
/* Wait until RIT signals an interrupt */ /* Wait until RIT signals an interrupt */
while (!(BITBAND(LPC_RIT->RICTRL, RITINT))) ; while ( !( BITBANG( LPC_RIT->RICTRL, RITINT ) ) ) ;
/* Disable RIT */ /* Disable RIT */
LPC_RIT->RICTRL = 0; LPC_RIT->RICTRL = 0;

View File

@ -13,7 +13,8 @@ extern volatile tick_t ticks;
* *
* This inline function returns the current system tick count. * This inline function returns the current system tick count.
*/ */
static inline tick_t getticks(void) { static inline tick_t getticks( void )
{
return ticks; return ticks;
} }

View File

@ -77,44 +77,60 @@
//static char txbuf[1 << CONFIG_UART_TX_BUF_SHIFT]; //static char txbuf[1 << CONFIG_UART_TX_BUF_SHIFT];
static volatile unsigned int read_idx, write_idx; static volatile unsigned int read_idx, write_idx;
void uart_putc(char c) { void uart_putc( char c )
{
if ( c == '\n' ) if ( c == '\n' )
{
uart_putc( '\r' ); uart_putc( '\r' );
}
while ( !( UART_REGS->LSR & ( 0x20 ) ) ); while ( !( UART_REGS->LSR & ( 0x20 ) ) );
UART_REGS->THR = c; UART_REGS->THR = c;
} }
/* Polling version only */ /* Polling version only */
unsigned char uart_getc(void) { unsigned char uart_getc( void )
{
/* wait for character */ /* wait for character */
while (!(BITBAND(UART_REGS->LSR, 0))) ; while ( !( BITBANG( UART_REGS->LSR, 0 ) ) ) ;
return UART_REGS->RBR; return UART_REGS->RBR;
} }
/* Returns true if a char is ready */ /* Returns true if a char is ready */
unsigned char uart_gotc(void) { unsigned char uart_gotc( void )
return BITBAND(UART_REGS->LSR, 0); {
return BITBANG( UART_REGS->LSR, 0 );
} }
void uart_init(void) { void uart_init( void )
{
uint32_t div; uint32_t div;
/* Turn on power to UART */ /* Turn on power to UART */
BITBAND(LPC_SC->PCONP, UART_PCONBIT) = 1; BITBANG( LPC_SC->PCONP, UART_PCONBIT ) = 1;
/* UART clock = CPU clock - this block is reduced at compile-time */ /* UART clock = CPU clock - this block is reduced at compile-time */
if (CONFIG_UART_PCLKDIV == 1) { if ( CONFIG_UART_PCLKDIV == 1 )
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1; {
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 0; BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
} else if (CONFIG_UART_PCLKDIV == 2) { BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0;
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0; }
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 1; else if ( CONFIG_UART_PCLKDIV == 2 )
} else if (CONFIG_UART_PCLKDIV == 4) { {
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0; BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 0; BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1;
} else { // Fallback: Divide by 8 }
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1; else if ( CONFIG_UART_PCLKDIV == 4 )
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 1; {
BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0;
}
else // Fallback: Divide by 8
{
BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1;
} }
/* set baud rate - no fractional stuff for now */ /* set baud rate - no fractional stuff for now */
@ -123,9 +139,10 @@ void uart_init(void) {
UART_REGS->DLL = div & 0xff; UART_REGS->DLL = div & 0xff;
UART_REGS->DLM = ( div >> 8 ) & 0xff; UART_REGS->DLM = ( div >> 8 ) & 0xff;
BITBAND(UART_REGS->LCR, 7) = 0; BITBANG( UART_REGS->LCR, 7 ) = 0;
if (div & 0xff0000) { if ( div & 0xff0000 )
{
UART_REGS->FDR = ( div >> 16 ) & 0xff; UART_REGS->FDR = ( div >> 16 ) & 0xff;
} }
@ -136,67 +153,101 @@ void uart_init(void) {
} }
/* --- generic code below --- */ /* --- generic code below --- */
void uart_puthex(uint8_t num) { void uart_puthex( uint8_t num )
{
uint8_t tmp; uint8_t tmp;
tmp = ( num & 0xf0 ) >> 4; tmp = ( num & 0xf0 ) >> 4;
if (tmp < 10)
uart_putc('0'+tmp);
else
uart_putc('a'+tmp-10);
tmp = num & 0x0f;
if ( tmp < 10 ) if ( tmp < 10 )
{
uart_putc( '0' + tmp ); uart_putc( '0' + tmp );
}
else else
{
uart_putc( 'a' + tmp - 10 ); uart_putc( 'a' + tmp - 10 );
} }
void uart_trace(void *ptr, uint16_t start, uint16_t len) { tmp = num & 0x0f;
if ( tmp < 10 )
{
uart_putc( '0' + tmp );
}
else
{
uart_putc( 'a' + tmp - 10 );
}
}
void uart_trace( void *ptr, uint16_t start, uint16_t len )
{
uint16_t i; uint16_t i;
uint8_t j; uint8_t j;
uint8_t ch; uint8_t ch;
uint8_t *data = ptr; uint8_t *data = ptr;
data += start; data += start;
for(i=0;i<len;i+=16) {
for ( i = 0; i < len; i += 16 )
{
uart_puthex( start >> 8 ); uart_puthex( start >> 8 );
uart_puthex( start & 0xff ); uart_puthex( start & 0xff );
uart_putc( '|' ); uart_putc( '|' );
uart_putc( ' ' ); uart_putc( ' ' );
for(j=0;j<16;j++) {
if(i+j<len) { for ( j = 0; j < 16; j++ )
{
if ( i + j < len )
{
ch = *( data + j ); ch = *( data + j );
uart_puthex( ch ); uart_puthex( ch );
} else { }
else
{
uart_putc( ' ' ); uart_putc( ' ' );
uart_putc( ' ' ); uart_putc( ' ' );
} }
uart_putc( ' ' ); uart_putc( ' ' );
} }
uart_putc( '|' ); uart_putc( '|' );
for(j=0;j<16;j++) {
if(i+j<len) { for ( j = 0; j < 16; j++ )
{
if ( i + j < len )
{
ch = *( data++ ); ch = *( data++ );
if ( ch < 32 || ch > 0x7e ) if ( ch < 32 || ch > 0x7e )
{
ch = '.'; ch = '.';
}
uart_putc( ch ); uart_putc( ch );
} else { }
else
{
uart_putc( ' ' ); uart_putc( ' ' );
} }
} }
uart_putc( '|' ); uart_putc( '|' );
uart_putcrlf(); uart_putcrlf();
start += 16; start += 16;
} }
} }
void uart_flush(void) { void uart_flush( void )
{
while ( read_idx != write_idx ) ; while ( read_idx != write_idx ) ;
} }
void uart_puts(const char *text) { void uart_puts( const char *text )
while (*text) { {
while ( *text )
{
uart_putc( *text++ ); uart_putc( *text++ );
} }
} }

View File

@ -31,7 +31,8 @@
#if _CODE_PAGE == 437 #if _CODE_PAGE == 437
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP437(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@ -53,7 +54,8 @@ const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 720 #elif _CODE_PAGE == 720
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP720(0x80-0xFF) to Unicode conversion table */
{
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9,
@ -75,7 +77,8 @@ const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 737 #elif _CODE_PAGE == 737
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP737(0x80-0xFF) to Unicode conversion table */
{
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398,
0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9,
@ -97,7 +100,8 @@ const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 775 #elif _CODE_PAGE == 775
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP775(0x80-0xFF) to Unicode conversion table */
{
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107,
0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A,
@ -119,7 +123,8 @@ const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 850 #elif _CODE_PAGE == 850
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP850(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@ -141,7 +146,8 @@ const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 852 #elif _CODE_PAGE == 852
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP852(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7,
0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A,
@ -163,7 +169,8 @@ const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 855 #elif _CODE_PAGE == 855
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP855(0x80-0xFF) to Unicode conversion table */
{
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404,
0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C,
@ -185,7 +192,8 @@ const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 857 #elif _CODE_PAGE == 857
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP857(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@ -207,7 +215,8 @@ const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 858 #elif _CODE_PAGE == 858
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP858(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@ -229,7 +238,8 @@ const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 862 #elif _CODE_PAGE == 862
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP862(0x80-0xFF) to Unicode conversion table */
{
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
@ -251,7 +261,8 @@ const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 866 #elif _CODE_PAGE == 866
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP866(0x80-0xFF) to Unicode conversion table */
{
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
@ -273,7 +284,8 @@ const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 874 #elif _CODE_PAGE == 874
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP874(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, 0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -295,7 +307,8 @@ const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1250 #elif _CODE_PAGE == 1250
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1250(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -317,7 +330,8 @@ const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1251 #elif _CODE_PAGE == 1251
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1251(0x80-0xFF) to Unicode conversion table */
{
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -339,7 +353,8 @@ const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1252 #elif _CODE_PAGE == 1252
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1252(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -361,7 +376,8 @@ const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1253 #elif _CODE_PAGE == 1253
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1253(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000, 0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -383,7 +399,8 @@ const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1254 #elif _CODE_PAGE == 1254
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1254(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -405,7 +422,8 @@ const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1255 #elif _CODE_PAGE == 1255
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1255(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -427,7 +445,8 @@ const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1256 #elif _CODE_PAGE == 1256
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1256(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -449,7 +468,8 @@ const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1257 #elif _CODE_PAGE == 1257
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1257(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8, 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -471,7 +491,8 @@ const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1258 #elif _CODE_PAGE == 1258
#define _TBLDEF 1 #define _TBLDEF 1
static static
const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */ const WCHAR Tbl[] = /* CP1258(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, 0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@ -506,17 +527,28 @@ WCHAR ff_convert ( /* Converted character, Returns zero on error */
WCHAR c; WCHAR c;
if (src < 0x80) { /* ASCII */ if ( src < 0x80 ) /* ASCII */
{
c = src; c = src;
} else { }
if (dir) { /* OEMCP to Unicode */ else
{
if ( dir ) /* OEMCP to Unicode */
{
c = ( src >= 0x100 ) ? 0 : Tbl[src - 0x80]; c = ( src >= 0x100 ) ? 0 : Tbl[src - 0x80];
} else { /* Unicode to OEMCP */
for (c = 0; c < 0x80; c++) {
if (src == Tbl[c]) break;
} }
else /* Unicode to OEMCP */
{
for ( c = 0; c < 0x80; c++ )
{
if ( src == Tbl[c] )
{
break;
}
}
c = ( c + 0x80 ) & 0xFF; c = ( c + 0x80 ) & 0xFF;
} }
} }

View File

@ -3,7 +3,8 @@
#include "uart.h" #include "uart.h"
#include "fileops.h" #include "fileops.h"
cfg_t CFG = { cfg_t CFG =
{
.cfg_ver_maj = 1, .cfg_ver_maj = 1,
.cfg_ver_min = 0, .cfg_ver_min = 0,
.last_game_valid = 0, .last_game_valid = 0,
@ -14,27 +15,36 @@ cfg_t CFG = {
.bsx_time = 0x0619970301180530LL .bsx_time = 0x0619970301180530LL
}; };
int cfg_save() { int cfg_save()
{
int err = 0; int err = 0;
file_open( CFG_FILE, FA_CREATE_ALWAYS | FA_WRITE ); file_open( CFG_FILE, FA_CREATE_ALWAYS | FA_WRITE );
if(file_writeblock(&CFG, 0, sizeof(CFG)) < sizeof(CFG)) {
if ( file_writeblock( &CFG, 0, sizeof( CFG ) ) < sizeof( CFG ) )
{
err = file_res; err = file_res;
} }
file_close(); file_close();
return err; return err;
} }
int cfg_load() { int cfg_load()
{
int err = 0; int err = 0;
file_open( CFG_FILE, FA_READ ); file_open( CFG_FILE, FA_READ );
if(file_readblock(&CFG, 0, sizeof(CFG)) < sizeof(CFG)) {
if ( file_readblock( &CFG, 0, sizeof( CFG ) ) < sizeof( CFG ) )
{
err = file_res; err = file_res;
} }
file_close(); file_close();
return err; return err;
} }
int cfg_save_last_game(uint8_t *fn) { int cfg_save_last_game( uint8_t *fn )
{
int err = 0; int err = 0;
file_open( LAST_FILE, FA_CREATE_ALWAYS | FA_WRITE ); file_open( LAST_FILE, FA_CREATE_ALWAYS | FA_WRITE );
err = f_puts( ( const TCHAR * )fn, &file_handle ); err = f_puts( ( const TCHAR * )fn, &file_handle );
@ -42,7 +52,8 @@ int cfg_save_last_game(uint8_t *fn) {
return err; return err;
} }
int cfg_get_last_game(uint8_t *fn) { int cfg_get_last_game( uint8_t *fn )
{
int err = 0; int err = 0;
file_open( LAST_FILE, FA_READ ); file_open( LAST_FILE, FA_READ );
f_gets( ( TCHAR * )fn, 255, &file_handle ); f_gets( ( TCHAR * )fn, 255, &file_handle );
@ -50,10 +61,12 @@ int cfg_get_last_game(uint8_t *fn) {
return err; return err;
} }
void cfg_set_last_game_valid(uint8_t valid) { void cfg_set_last_game_valid( uint8_t valid )
{
CFG.last_game_valid = valid; CFG.last_game_valid = valid;
} }
uint8_t cfg_is_last_game_valid() { uint8_t cfg_is_last_game_valid()
{
return CFG.last_game_valid; return CFG.last_game_valid;
} }

View File

@ -6,13 +6,15 @@
#define CFG_FILE ((const uint8_t*)"/sd2snes/sd2snes.cfg") #define CFG_FILE ((const uint8_t*)"/sd2snes/sd2snes.cfg")
#define LAST_FILE ((const uint8_t*)"/sd2snes/lastgame.cfg") #define LAST_FILE ((const uint8_t*)"/sd2snes/lastgame.cfg")
typedef enum { typedef enum
{
VIDMODE_AUTO = 0, VIDMODE_AUTO = 0,
VIDMODE_60, VIDMODE_60,
VIDMODE_50 VIDMODE_50
} cfg_vidmode_t; } cfg_vidmode_t;
typedef struct _cfg_block { typedef struct _cfg_block
{
uint8_t cfg_ver_maj; uint8_t cfg_ver_maj;
uint8_t cfg_ver_min; uint8_t cfg_ver_min;
uint8_t last_game_valid; uint8_t last_game_valid;

File diff suppressed because it is too large Load Diff

View File

@ -7,54 +7,80 @@
char *cicstatenames[4] = { "CIC_OK", "CIC_FAIL", "CIC_PAIR", "CIC_SCIC" }; char *cicstatenames[4] = { "CIC_OK", "CIC_FAIL", "CIC_PAIR", "CIC_SCIC" };
char *cicstatefriendly[4] = {"Original or no CIC", "Original CIC(failed)", "SuperCIC enhanced", "SuperCIC detected, not used"}; char *cicstatefriendly[4] = {"Original or no CIC", "Original CIC(failed)", "SuperCIC enhanced", "SuperCIC detected, not used"};
void print_cic_state() { void print_cic_state()
{
printf( "CIC state: %s\n", get_cic_statename( get_cic_state() ) ); printf( "CIC state: %s\n", get_cic_statename( get_cic_state() ) );
} }
inline char *get_cic_statefriendlyname(enum cicstates state) { inline char *get_cic_statefriendlyname( enum cicstates state )
{
return cicstatefriendly[state]; return cicstatefriendly[state];
} }
inline char *get_cic_statename(enum cicstates state) { inline char *get_cic_statename( enum cicstates state )
{
return cicstatenames[state]; return cicstatenames[state];
} }
enum cicstates get_cic_state() { enum cicstates get_cic_state()
{
uint32_t count; uint32_t count;
uint32_t togglecount = 0; uint32_t togglecount = 0;
uint8_t state, state_old; uint8_t state, state_old;
state_old = BITBAND( SNES_CIC_STATUS_REG->FIOPIN, SNES_CIC_STATUS_BIT ); state_old = BITBAND( SNES_CIC_STATUS_REG->FIOPIN, SNES_CIC_STATUS_BIT );
/* this loop samples at ~10MHz */ /* this loop samples at ~10MHz */
for(count=0; count<CIC_SAMPLECOUNT; count++) { for ( count = 0; count < CIC_SAMPLECOUNT; count++ )
{
state = BITBAND( SNES_CIC_STATUS_REG->FIOPIN, SNES_CIC_STATUS_BIT ); state = BITBAND( SNES_CIC_STATUS_REG->FIOPIN, SNES_CIC_STATUS_BIT );
if(state != state_old) {
if ( state != state_old )
{
togglecount++; togglecount++;
} }
state_old = state; state_old = state;
} }
printf( "%ld\n", togglecount ); printf( "%ld\n", togglecount );
/* CIC_TOGGLE_THRESH_PAIR > CIC_TOGGLE_THRESH_SCIC */ /* CIC_TOGGLE_THRESH_PAIR > CIC_TOGGLE_THRESH_SCIC */
if(togglecount > CIC_TOGGLE_THRESH_PAIR) { if ( togglecount > CIC_TOGGLE_THRESH_PAIR )
{
return CIC_PAIR; return CIC_PAIR;
} else if(togglecount > CIC_TOGGLE_THRESH_SCIC) { }
else if ( togglecount > CIC_TOGGLE_THRESH_SCIC )
{
return CIC_SCIC; return CIC_SCIC;
} else if(state) { }
else if ( state )
{
return CIC_OK; return CIC_OK;
} else return CIC_FAIL; }
else
{
return CIC_FAIL;
}
} }
void cic_init(int allow_pairmode) { void cic_init( int allow_pairmode )
{
BITBAND( SNES_CIC_PAIR_REG->FIODIR, SNES_CIC_PAIR_BIT ) = 1; BITBAND( SNES_CIC_PAIR_REG->FIODIR, SNES_CIC_PAIR_BIT ) = 1;
if(allow_pairmode) {
if ( allow_pairmode )
{
BITBAND( SNES_CIC_PAIR_REG->FIOCLR, SNES_CIC_PAIR_BIT ) = 1; BITBAND( SNES_CIC_PAIR_REG->FIOCLR, SNES_CIC_PAIR_BIT ) = 1;
} else { }
else
{
BITBAND( SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT ) = 1; BITBAND( SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT ) = 1;
} }
} }
/* prepare GPIOs for pair mode + set initial modes */ /* prepare GPIOs for pair mode + set initial modes */
void cic_pair(int init_vmode, int init_d4) { void cic_pair( int init_vmode, int init_d4 )
{
cic_videomode( init_vmode ); cic_videomode( init_vmode );
cic_d4( init_d4 ); cic_d4( init_d4 );
@ -62,18 +88,26 @@ void cic_pair(int init_vmode, int init_d4) {
BITBAND( SNES_CIC_D1_REG->FIODIR, SNES_CIC_D1_BIT ) = 1; BITBAND( SNES_CIC_D1_REG->FIODIR, SNES_CIC_D1_BIT ) = 1;
} }
void cic_videomode(int value) { void cic_videomode( int value )
if(value) { {
if ( value )
{
BITBAND( SNES_CIC_D0_REG->FIOSET, SNES_CIC_D0_BIT ) = 1; BITBAND( SNES_CIC_D0_REG->FIOSET, SNES_CIC_D0_BIT ) = 1;
} else { }
else
{
BITBAND( SNES_CIC_D0_REG->FIOCLR, SNES_CIC_D0_BIT ) = 1; BITBAND( SNES_CIC_D0_REG->FIOCLR, SNES_CIC_D0_BIT ) = 1;
} }
} }
void cic_d4(int value) { void cic_d4( int value )
if(value) { {
if ( value )
{
BITBAND( SNES_CIC_D1_REG->FIOSET, SNES_CIC_D1_BIT ) = 1; BITBAND( SNES_CIC_D1_REG->FIOSET, SNES_CIC_D1_BIT ) = 1;
} else { }
else
{
BITBAND( SNES_CIC_D1_REG->FIOCLR, SNES_CIC_D1_BIT ) = 1; BITBAND( SNES_CIC_D1_REG->FIOCLR, SNES_CIC_D1_BIT ) = 1;
} }
} }

370
src/cli.c
View File

@ -42,6 +42,7 @@
#include "fileops.h" #include "fileops.h"
#include "memory.h" #include "memory.h"
#include "snes.h" #include "snes.h"
#include "tests.h"
#include "fpga.h" #include "fpga.h"
#include "fpga_spi.h" #include "fpga_spi.h"
#include "cic.h" #include "cic.h"
@ -58,35 +59,42 @@ static char *curchar;
/* Word lists */ /* Word lists */
static char command_words[] = static char command_words[] =
"cd\0reset\0sreset\0dir\0ls\0test\0resume\0loadrom\0loadraw\0saveraw\0put\0rm\0mkdir\0d4\0vmode\0mapper\0settime\0time\0setfeature\0hexdump\0w8\0w16\0"; "cd\0reset\0sreset\0dir\0ls\0test\0exit\0loadrom\0loadraw\0saveraw\0put\0rm\0mkdir\0d4\0vmode\0mapper\0settime\0time\0setfeature\0hexdump\0w8\0w16\0memset\0memtest\0";
enum { CMD_CD = 0, CMD_RESET, CMD_SRESET, CMD_DIR, CMD_LS, CMD_TEST, CMD_RESUME, CMD_LOADROM, CMD_LOADRAW, CMD_SAVERAW, CMD_PUT, CMD_RM, CMD_MKDIR, CMD_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME, CMD_SETFEATURE, CMD_HEXDUMP, CMD_W8, CMD_W16 }; enum { CMD_CD = 0, CMD_RESET, CMD_SRESET, CMD_DIR, CMD_LS, CMD_TEST, CMD_EXIT, CMD_LOADROM, CMD_LOADRAW, CMD_SAVERAW, CMD_PUT, CMD_RM, CMD_MKDIR, CMD_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME, CMD_SETFEATURE, CMD_HEXDUMP, CMD_W8, CMD_W16, CMD_MEMSET, CMD_MEMTEST };
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* Parse functions */ /* Parse functions */
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* Skip spaces at curchar */ /* Skip spaces at curchar */
static uint8_t skip_spaces(void) { static uint8_t skip_spaces( void )
{
uint8_t res = ( *curchar == ' ' || *curchar == 0 ); uint8_t res = ( *curchar == ' ' || *curchar == 0 );
while ( *curchar == ' ' ) while ( *curchar == ' ' )
{
curchar++; curchar++;
}
return res; return res;
} }
/* Parse the string in curchar for an integer with bounds [lower,upper] */ /* Parse the string in curchar for an integer with bounds [lower,upper] */
static int32_t parse_unsigned(uint32_t lower, uint32_t upper, uint8_t base) { static int32_t parse_unsigned( uint32_t lower, uint32_t upper, uint8_t base )
{
char *end; char *end;
uint32_t result; uint32_t result;
if (strlen(curchar) == 1 && *curchar == '?') { if ( strlen( curchar ) == 1 && *curchar == '?' )
{
printf( "Number between %ld[0x%lx] and %ld[0x%lx] expected\n", lower, lower, upper, upper ); printf( "Number between %ld[0x%lx] and %ld[0x%lx] expected\n", lower, lower, upper, upper );
return -2; return -2;
} }
result = strtoul( curchar, &end, base ); result = strtoul( curchar, &end, base );
if ((*end != ' ' && *end != 0) || errno != 0) {
if ( ( *end != ' ' && *end != 0 ) || errno != 0 )
{
printf( "Invalid numeric argument\n" ); printf( "Invalid numeric argument\n" );
return -1; return -1;
} }
@ -94,7 +102,8 @@ static int32_t parse_unsigned(uint32_t lower, uint32_t upper, uint8_t base) {
curchar = end; curchar = end;
skip_spaces(); skip_spaces();
if (result < lower || result > upper) { if ( result < lower || result > upper )
{
printf( "Numeric argument out of range (%ld..%ld)\n", lower, upper ); printf( "Numeric argument out of range (%ld..%ld)\n", lower, upper );
return -1; return -1;
} }
@ -102,112 +111,157 @@ static int32_t parse_unsigned(uint32_t lower, uint32_t upper, uint8_t base) {
return result; return result;
} }
/* Parse the string starting with curchar for a word in wordlist */ /* Parse the string starting with curchar for a word in wordlist */
static int8_t parse_wordlist(char *wordlist) { static int8_t parse_wordlist( char *wordlist )
{
uint8_t i, matched; uint8_t i, matched;
char *cur, *ptr; unsigned char *cur, *ptr;
char c; unsigned char c;
i = 0; i = 0;
ptr = wordlist; ptr = ( unsigned char * )wordlist;
// Command list on "?" // Command list on "?"
if (strlen(curchar) == 1 && *curchar == '?') { if ( strlen( curchar ) == 1 && *curchar == '?' )
{
printf( "Commands available: \n " ); printf( "Commands available: \n " );
while (1) {
while ( 1 )
{
c = *ptr++; c = *ptr++;
if (c == 0) {
if (*ptr == 0) { if ( c == 0 )
{
if ( *ptr == 0 )
{
printf( "\n" ); printf( "\n" );
return -2; return -2;
} else { }
else
{
printf( "\n " ); printf( "\n " );
} }
} else }
else
{
uart_putc( c ); uart_putc( c );
} }
} }
}
while (1) { while ( 1 )
cur = curchar; {
cur = ( unsigned char * )curchar;
matched = 1; matched = 1;
c = *ptr; c = *ptr;
do {
do
{
// If current word list character is \0: No match found // If current word list character is \0: No match found
if (c == 0) { if ( c == 0 )
{
printf( "Unknown word: %s\n(use ? for help)", curchar ); printf( "Unknown word: %s\n(use ? for help)", curchar );
return -1; return -1;
} }
if (tolower(c) != tolower(*cur)) { if ( tolower( ( int )c ) != tolower( ( int )*cur ) )
{
// Check for end-of-word // Check for end-of-word
if (cur != curchar && (*cur == ' ' || *cur == 0)) { if ( cur != ( unsigned char * )curchar && ( *cur == ' ' || *cur == 0 ) )
{
// Partial match found, return that // Partial match found, return that
break; break;
} else { }
else
{
matched = 0; matched = 0;
break; break;
} }
} }
ptr++; ptr++;
cur++; cur++;
c = *ptr; c = *ptr;
} while (c != 0); }
while ( c != 0 );
if (matched) { if ( matched )
{
char *tmp = curchar; char *tmp = curchar;
curchar = cur; curchar = ( char * )cur;
// Return match only if whitespace or end-of-string follows // Return match only if whitespace or end-of-string follows
// (avoids mismatching partial words) // (avoids mismatching partial words)
if (skip_spaces()) { if ( skip_spaces() )
{
return i; return i;
} else { }
else
{
printf( "Unknown word: %s\n(use ? for help)\n", tmp ); printf( "Unknown word: %s\n(use ? for help)\n", tmp );
return -1; return -1;
} }
} else { }
else
{
// Try next word in list // Try next word in list
i++; i++;
while ( *ptr++ != 0 ) ; while ( *ptr++ != 0 ) ;
} }
} }
} }
/* Read a line from serial, uses cmdbuffer as storage */ /* Read a line from serial, uses cmdbuffer as storage */
static char *getline(char *prompt) { static char *getline( char *prompt )
{
int i = 0; int i = 0;
char c; char c;
printf( "\n%s", prompt ); printf( "\n%s", prompt );
memset( cmdbuffer, 0, sizeof( cmdbuffer ) ); memset( cmdbuffer, 0, sizeof( cmdbuffer ) );
while (1) { while ( 1 )
{
c = uart_getc(); c = uart_getc();
if (c == 13)
break;
if (c == 27 || c == 3) { if ( c == 13 )
{
break;
}
if ( c == 27 || c == 3 )
{
printf( "\\\n%s", prompt ); printf( "\\\n%s", prompt );
i = 0; i = 0;
memset( cmdbuffer, 0, sizeof( cmdbuffer ) ); memset( cmdbuffer, 0, sizeof( cmdbuffer ) );
continue; continue;
} }
if (c == 127 || c == 8) { if ( c == 127 || c == 8 )
if (i > 0) { {
if ( i > 0 )
{
i--; i--;
uart_putc( 8 ); // backspace uart_putc( 8 ); // backspace
uart_putc( ' ' ); // erase character uart_putc( ' ' ); // erase character
uart_putc( 8 ); // backspace uart_putc( 8 ); // backspace
} else }
else
{
continue; continue;
} else { }
if (i < sizeof(cmdbuffer)-1) { }
else
{
if ( i < sizeof( cmdbuffer ) - 1 )
{
cmdbuffer[i++] = c; cmdbuffer[i++] = c;
uart_putc( c ); uart_putc( c );
} }
} }
} }
cmdbuffer[i] = 0; cmdbuffer[i] = 0;
return cmdbuffer; return cmdbuffer;
} }
@ -218,7 +272,8 @@ static char *getline(char *prompt) {
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* Reset */ /* Reset */
static void cmd_reset(void) { static void cmd_reset( void )
{
/* force watchdog reset */ /* force watchdog reset */
LPC_WDT->WDTC = 256; // minimal timeout LPC_WDT->WDTC = 256; // minimal timeout
LPC_WDT->WDCLKSEL = BV( 31 ); // internal RC, lock register LPC_WDT->WDCLKSEL = BV( 31 ); // internal RC, lock register
@ -228,7 +283,8 @@ static void cmd_reset(void) {
} }
/* Show the contents of the current directory */ /* Show the contents of the current directory */
static void cmd_show_directory(void) { static void cmd_show_directory( void )
{
FRESULT res; FRESULT res;
DIR dh; DIR dh;
FILINFO finfo; FILINFO finfo;
@ -237,7 +293,9 @@ static void cmd_show_directory(void) {
f_getcwd( ( TCHAR * )file_lfn, 255 ); f_getcwd( ( TCHAR * )file_lfn, 255 );
res = f_opendir( &dh, ( TCHAR * )file_lfn ); res = f_opendir( &dh, ( TCHAR * )file_lfn );
if (res != FR_OK) {
if ( res != FR_OK )
{
printf( "f_opendir failed, result %d\n", res ); printf( "f_opendir failed, result %d\n", res );
return; return;
} }
@ -245,136 +303,203 @@ static void cmd_show_directory(void) {
finfo.lfname = ( TCHAR * )file_lfn; finfo.lfname = ( TCHAR * )file_lfn;
finfo.lfsize = 255; finfo.lfsize = 255;
do { do
{
/* Read the next entry */ /* Read the next entry */
res = f_readdir( &dh, &finfo ); res = f_readdir( &dh, &finfo );
if (res != FR_OK) {
if ( res != FR_OK )
{
printf( "f_readdir failed, result %d\n", res ); printf( "f_readdir failed, result %d\n", res );
return; return;
} }
/* Abort if none was found */ /* Abort if none was found */
if ( !finfo.fname[0] ) if ( !finfo.fname[0] )
{
break; break;
}
/* Skip volume labels */ /* Skip volume labels */
if ( finfo.fattrib & AM_VOL ) if ( finfo.fattrib & AM_VOL )
{
continue; continue;
}
/* Select between LFN and 8.3 name */ /* Select between LFN and 8.3 name */
if ( finfo.lfname[0] ) if ( finfo.lfname[0] )
{
name = ( uint8_t * )finfo.lfname; name = ( uint8_t * )finfo.lfname;
else { }
else
{
name = ( uint8_t * )finfo.fname; name = ( uint8_t * )finfo.fname;
strlwr( ( char * )name ); strlwr( ( char * )name );
} }
printf("%s",name); printf( "%s [%s] (%ld)", finfo.lfname, finfo.fname, finfo.fsize );
/* Directory indicator (Unix-style) */ /* Directory indicator (Unix-style) */
if ( finfo.fattrib & AM_DIR ) if ( finfo.fattrib & AM_DIR )
{
uart_putc( '/' ); uart_putc( '/' );
}
printf( "\n" ); printf( "\n" );
} while (finfo.fname[0]); }
while ( finfo.fname[0] );
} }
static void cmd_loadrom(void) { static void cmd_loadrom( void )
{
uint32_t address = 0; uint32_t address = 0;
uint8_t flags = LOADROM_WITH_SRAM | LOADROM_WITH_RESET; uint8_t flags = LOADROM_WITH_SRAM | LOADROM_WITH_RESET;
load_rom( ( uint8_t * )curchar, address, flags ); load_rom( ( uint8_t * )curchar, address, flags );
} }
static void cmd_loadraw(void) { static void cmd_loadraw( void )
{
uint32_t address = parse_unsigned( 0, 16777216, 16 ); uint32_t address = parse_unsigned( 0, 16777216, 16 );
load_sram( ( uint8_t * )curchar, address ); load_sram( ( uint8_t * )curchar, address );
} }
static void cmd_saveraw(void) { static void cmd_saveraw( void )
{
uint32_t address = parse_unsigned( 0, 16777216, 16 ); uint32_t address = parse_unsigned( 0, 16777216, 16 );
uint32_t length = parse_unsigned( 0, 16777216, 16 ); uint32_t length = parse_unsigned( 0, 16777216, 16 );
if ( address != -1 && length != -1 ) if ( address != -1 && length != -1 )
{
save_sram( ( uint8_t * )curchar, length, address ); save_sram( ( uint8_t * )curchar, length, address );
} }
}
static void cmd_d4(void) { static void cmd_d4( void )
{
int32_t hz; int32_t hz;
if(get_cic_state() != CIC_PAIR) { if ( get_cic_state() != CIC_PAIR )
{
printf( "not in pair mode\n" ); printf( "not in pair mode\n" );
} else { }
else
{
hz = parse_unsigned( 50, 60, 10 ); hz = parse_unsigned( 50, 60, 10 );
if(hz==50) {
if ( hz == 50 )
{
cic_d4( CIC_PAL ); cic_d4( CIC_PAL );
} else { }
else
{
cic_d4( CIC_NTSC ); cic_d4( CIC_NTSC );
} }
printf( "ok\n" ); printf( "ok\n" );
} }
} }
static void cmd_vmode(void) { static void cmd_vmode( void )
{
int32_t hz; int32_t hz;
if(get_cic_state() != CIC_PAIR) {
if ( get_cic_state() != CIC_PAIR )
{
printf( "not in pair mode\n" ); printf( "not in pair mode\n" );
} else { }
else
{
hz = parse_unsigned( 50, 60, 10 ); hz = parse_unsigned( 50, 60, 10 );
if(hz==50) {
if ( hz == 50 )
{
cic_videomode( CIC_PAL ); cic_videomode( CIC_PAL );
} else { }
else
{
cic_videomode( CIC_NTSC ); cic_videomode( CIC_NTSC );
} }
printf( "ok\n" ); printf( "ok\n" );
} }
} }
void cmd_put(void) { void cmd_put( void )
if(*curchar != 0) { {
if ( *curchar != 0 )
{
file_open( ( uint8_t * )curchar, FA_CREATE_ALWAYS | FA_WRITE ); file_open( ( uint8_t * )curchar, FA_CREATE_ALWAYS | FA_WRITE );
if(file_res) {
if ( file_res )
{
printf( "FAIL: error opening file %s\n", curchar ); printf( "FAIL: error opening file %s\n", curchar );
} else { }
else
{
printf( "OK, start xmodem transfer now.\n" ); printf( "OK, start xmodem transfer now.\n" );
xmodem_rxfile( &file_handle ); xmodem_rxfile( &file_handle );
} }
file_close(); file_close();
} else { }
else
{
printf( "Usage: put <filename>\n" ); printf( "Usage: put <filename>\n" );
} }
} }
void cmd_rm(void) { void cmd_rm( void )
{
FRESULT res = f_unlink( curchar ); FRESULT res = f_unlink( curchar );
if(res) printf("Error %d removing %s\n", res, curchar);
if ( res )
{
printf( "Error %d removing %s\n", res, curchar );
}
} }
void cmd_mkdir(void) { void cmd_mkdir( void )
{
FRESULT res = f_mkdir( curchar ); FRESULT res = f_mkdir( curchar );
if(res) printf("Error %d creating directory %s\n", res, curchar);
if ( res )
{
printf( "Error %d creating directory %s\n", res, curchar );
}
} }
void cmd_mapper(void) { void cmd_mapper( void )
{
int32_t mapper; int32_t mapper;
mapper = parse_unsigned( 0, 7, 10 ); mapper = parse_unsigned( 0, 7, 10 );
set_mapper( ( uint8_t )mapper & 0x7 ); set_mapper( ( uint8_t )mapper & 0x7 );
printf( "mapper set to %ld\n", mapper ); printf( "mapper set to %ld\n", mapper );
} }
void cmd_sreset(void) { void cmd_sreset( void )
if(*curchar != 0) { {
if ( *curchar != 0 )
{
int32_t resetstate; int32_t resetstate;
resetstate = parse_unsigned( 0, 1, 10 ); resetstate = parse_unsigned( 0, 1, 10 );
snes_reset( resetstate ); snes_reset( resetstate );
} else { }
else
{
snes_reset_pulse(); snes_reset_pulse();
} }
} }
void cmd_settime(void) { void cmd_settime( void )
{
struct tm time; struct tm time;
if(strlen(curchar) != 4+2+2 + 2+2+2) {
if ( strlen( curchar ) != 4 + 2 + 2 + 2 + 2 + 2 )
{
printf( "invalid time format (need YYYYMMDDhhmmss)\n" ); printf( "invalid time format (need YYYYMMDDhhmmss)\n" );
} else { }
else
{
time.tm_sec = atoi( curchar + 4 + 2 + 2 + 2 + 2 ); time.tm_sec = atoi( curchar + 4 + 2 + 2 + 2 + 2 );
curchar[4 + 2 + 2 + 2 + 2] = 0; curchar[4 + 2 + 2 + 2 + 2] = 0;
time.tm_min = atoi( curchar + 4 + 2 + 2 + 2 ); time.tm_min = atoi( curchar + 4 + 2 + 2 + 2 );
@ -390,105 +515,148 @@ void cmd_settime(void) {
} }
} }
void cmd_time(void) { void cmd_time( void )
{
struct tm time; struct tm time;
read_rtc( &time ); read_rtc( &time );
printf( "%04d-%02d-%02d %02d:%02d:%02d\n", time.tm_year, 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 ); time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec );
} }
void cmd_setfeature(void) { void cmd_setfeature( void )
{
uint8_t feat = parse_unsigned( 0, 255, 16 ); uint8_t feat = parse_unsigned( 0, 255, 16 );
fpga_set_features( feat ); fpga_set_features( feat );
} }
void cmd_hexdump(void) { void cmd_hexdump( void )
{
uint32_t offset = parse_unsigned( 0, 16777215, 16 ); uint32_t offset = parse_unsigned( 0, 16777215, 16 );
uint32_t len = parse_unsigned( 0, 16777216, 16 ); uint32_t len = parse_unsigned( 0, 16777216, 16 );
sram_hexdump( offset, len ); sram_hexdump( offset, len );
} }
void cmd_w8(void) { void cmd_w8( void )
{
uint32_t offset = parse_unsigned( 0, 16777215, 16 ); uint32_t offset = parse_unsigned( 0, 16777215, 16 );
uint8_t val = parse_unsigned( 0, 255, 16 ); uint8_t val = parse_unsigned( 0, 255, 16 );
sram_writebyte( val, offset ); sram_writebyte( val, offset );
} }
void cmd_w16(void) { void cmd_w16( void )
{
uint32_t offset = parse_unsigned( 0, 16777215, 16 ); uint32_t offset = parse_unsigned( 0, 16777215, 16 );
uint16_t val = parse_unsigned( 0, 65535, 16 ); uint16_t val = parse_unsigned( 0, 65535, 16 );
sram_writeshort( val, offset ); sram_writeshort( val, offset );
} }
void cmd_memset( void )
{
uint32_t offset = parse_unsigned( 0, 16777215, 16 );
uint32_t len = parse_unsigned( 0, 16777216, 16 );
uint8_t val = parse_unsigned( 0, 255, 16 );
sram_memset( offset, len, val );
}
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* CLI interface functions */ /* CLI interface functions */
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
void cli_init(void) { void cli_init( void )
{
} }
void cli_entrycheck() { void cli_entrycheck()
if(uart_gotc() && uart_getc() == 27) { {
if ( uart_gotc() && uart_getc() == 27 )
{
printf( "*** BREAK\n" ); printf( "*** BREAK\n" );
cli_loop(); cli_loop();
} }
} }
void cli_loop(void) { void cli_loop( void )
while (1) { {
while ( 1 )
{
curchar = getline( ">" ); curchar = getline( ">" );
printf( "\n" ); printf( "\n" );
/* Process medium changes before executing the command */ /* Process medium changes before executing the command */
if (disk_state != DISK_OK && disk_state != DISK_REMOVED) { if ( disk_state != DISK_OK && disk_state != DISK_REMOVED )
{
FRESULT res; FRESULT res;
printf( "Medium changed... " ); printf( "Medium changed... " );
res = f_mount( 0, &fatfs ); res = f_mount( 0, &fatfs );
if (res != FR_OK) {
if ( res != FR_OK )
{
printf( "Failed to mount new medium, result %d\n", res ); printf( "Failed to mount new medium, result %d\n", res );
} else { }
else
{
printf( "Ok\n" ); printf( "Ok\n" );
} }
} }
/* Remove whitespace */ /* Remove whitespace */
while (*curchar == ' ') curchar++; while ( *curchar == ' ' )
{
curchar++;
}
while ( strlen( curchar ) > 0 && curchar[strlen( curchar ) - 1] == ' ' ) while ( strlen( curchar ) > 0 && curchar[strlen( curchar ) - 1] == ' ' )
{
curchar[strlen( curchar ) - 1] = 0; curchar[strlen( curchar ) - 1] = 0;
}
/* Ignore empty lines */ /* Ignore empty lines */
if ( strlen( curchar ) == 0 ) if ( strlen( curchar ) == 0 )
{
continue; continue;
}
/* Parse command */ /* Parse command */
int8_t command = parse_wordlist( command_words ); int8_t command = parse_wordlist( command_words );
if ( command < 0 ) if ( command < 0 )
{
continue; continue;
}
FRESULT res; FRESULT res;
switch (command) {
switch ( command )
{
case CMD_CD: case CMD_CD:
#if _FS_RPATH #if _FS_RPATH
if (strlen(curchar) == 0) { if ( strlen( curchar ) == 0 )
{
f_getcwd( ( TCHAR * )file_lfn, 255 ); f_getcwd( ( TCHAR * )file_lfn, 255 );
printf( "%s\n", file_lfn ); printf( "%s\n", file_lfn );
break; break;
} }
res = f_chdir( ( const TCHAR * )curchar ); res = f_chdir( ( const TCHAR * )curchar );
if (res != FR_OK) {
if ( res != FR_OK )
{
printf( "chdir %s failed with result %d\n", curchar, res ); printf( "chdir %s failed with result %d\n", curchar, res );
} else { }
else
{
printf( "Ok.\n" ); printf( "Ok.\n" );
} }
#else #else
printf( "cd not supported.\n" ); printf( "cd not supported.\n" );
res; res;
#endif #endif
break; break;
case CMD_RESET: case CMD_RESET:
cmd_reset(); cmd_reset();
break; break;
@ -502,7 +670,7 @@ void cli_loop(void) {
cmd_show_directory(); cmd_show_directory();
break; break;
case CMD_RESUME: case CMD_EXIT:
return; return;
break; break;
@ -569,7 +737,15 @@ void cli_loop(void) {
case CMD_W16: case CMD_W16:
cmd_w16(); cmd_w16();
break; break;
}
case CMD_MEMSET:
cmd_memset();
break;
case CMD_MEMTEST:
test_mem();
break;
} }
} }
}

View File

@ -7,12 +7,14 @@
#include "bits.h" #include "bits.h"
#include "uart.h" #include "uart.h"
void clock_disconnect() { void clock_disconnect()
{
disconnectPLL0(); disconnectPLL0();
disablePLL0(); disablePLL0();
} }
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 );
@ -27,7 +29,7 @@ void clock_init() {
-> FPGA freq = 11289473.7Hz -> FPGA freq = 11289473.7Hz
First, disable and disconnect PLL0. First, disable and disconnect PLL0.
*/ */
// clock_disconnect(); clock_disconnect();
/* PLL is disabled and disconnected. setup PCLK NOW as it cannot be changed /* PLL is disabled and disconnected. setup PCLK NOW as it cannot be changed
reliably with PLL0 connected. reliably with PLL0 connected.
@ -54,54 +56,67 @@ void clock_init() {
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

@ -74,6 +74,4 @@ void disableMainOsc(void);
void PLL0feed( void ); void PLL0feed( void );
void setClkSrc( uint8_t src ); void setClkSrc( uint8_t src );
#endif #endif

View File

@ -1,4 +1,4 @@
CONFIG_VERSION="0.1.4a" CONFIG_VERSION="0.1.5"
#FWVER=00010300 #FWVER=00010300
CONFIG_FWVER=0x01010400 CONFIG_FWVER=0x00010500
CONFIG_MCU_FOSC=12000000 CONFIG_MCU_FOSC=12000000

View File

@ -64,6 +64,7 @@
#define FPGA_MCU_RDY_BIT 9 #define FPGA_MCU_RDY_BIT 9
#define QSORT_MAXELEM 2048 #define QSORT_MAXELEM 2048
#define SORT_STRLEN 256
#define CLTBL_SIZE 100 #define CLTBL_SIZE 100
#define DIR_FILE_MAX 16380 #define DIR_FILE_MAX 16380

View File

@ -20,7 +20,8 @@
/** /**
* Static table used for the table_driven implementation. * Static table used for the table_driven implementation.
*****************************************************************************/ *****************************************************************************/
static const uint16_t crc_table[256] = { static const uint16_t crc_table[256] =
{
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,

View File

@ -22,7 +22,8 @@
/** /**
* Static table used for the table_driven implementation. * Static table used for the table_driven implementation.
*****************************************************************************/ *****************************************************************************/
static const uint32_t crc32_table[256] = { static const uint32_t crc32_table[256] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,

View File

@ -16,7 +16,8 @@
typedef BYTE DSTATUS; typedef BYTE DSTATUS;
/* Results of Disk Functions */ /* Results of Disk Functions */
typedef enum { typedef enum
{
RES_OK = 0, /* 0: Successful */ RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */ RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */ RES_WRPRT, /* 2: Write Protected */
@ -35,7 +36,8 @@ typedef enum {
* This is the struct returned in the data buffer when disk_getinfo * This is the struct returned in the data buffer when disk_getinfo
* is called with page=0. * is called with page=0.
*/ */
typedef struct { typedef struct
{
uint8_t validbytes; uint8_t validbytes;
uint8_t maxpage; uint8_t maxpage;
uint8_t disktype; uint8_t disktype;

View File

@ -1,20 +1,25 @@
#include <arm/NXP/LPC17xx/LPC17xx.h> #include <arm/NXP/LPC17xx/LPC17xx.h>
#include "uart.h" #include "uart.h"
void HardFault_Handler(void) { void HardFault_Handler( void )
{
printf( "HFSR: %lx\n", SCB->HFSR ); printf( "HFSR: %lx\n", SCB->HFSR );
while ( 1 ) ; while ( 1 ) ;
} }
void MemManage_Handler(void) { void MemManage_Handler( void )
{
printf( "MemManage - CFSR: %lx; MMFAR: %lx\n", SCB->CFSR, SCB->MMFAR ); printf( "MemManage - CFSR: %lx; MMFAR: %lx\n", SCB->CFSR, SCB->MMFAR );
} }
void BusFault_Handler(void) { void BusFault_Handler( void )
{
printf( "BusFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR ); printf( "BusFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR );
} }
void UsageFault_Handler(void) { void UsageFault_Handler( void )
{
printf( "UsageFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR ); printf( "UsageFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR );
} }

3293
src/ff.c

File diff suppressed because it is too large Load Diff

View File

@ -229,7 +229,8 @@ extern "C" {
#if _MULTI_PARTITION /* Multiple partition configuration */ #if _MULTI_PARTITION /* Multiple partition configuration */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */ #define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */ #define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */
typedef struct { typedef struct
{
BYTE pd; /* Physical drive# */ BYTE pd; /* Physical drive# */
BYTE pt; /* Partition # (0-3) */ BYTE pt; /* Partition # (0-3) */
} PARTITION; } PARTITION;
@ -268,7 +269,8 @@ typedef char TCHAR;
/* File system object structure (FATFS) */ /* File system object structure (FATFS) */
typedef struct { typedef struct
{
BYTE fs_type; /* FAT sub-type (0:Not mounted) */ BYTE fs_type; /* FAT sub-type (0:Not mounted) */
BYTE drv; /* Physical drive number */ BYTE drv; /* Physical drive number */
BYTE csize; /* Sectors per cluster (1,2,4...128) */ BYTE csize; /* Sectors per cluster (1,2,4...128) */
@ -304,7 +306,8 @@ typedef struct {
/* File object structure (FIL) */ /* File object structure (FIL) */
typedef struct { typedef struct
{
FATFS *fs; /* Pointer to the owner file system object */ FATFS *fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */ WORD id; /* Owner file system mount ID */
BYTE flag; /* File status flags */ BYTE flag; /* File status flags */
@ -333,7 +336,8 @@ typedef struct {
/* Directory object structure (DIR) */ /* Directory object structure (DIR) */
typedef struct { typedef struct
{
FATFS *fs; /* Pointer to the owner file system object */ FATFS *fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */ WORD id; /* Owner file system mount ID */
WORD index; /* Current read/write index number */ WORD index; /* Current read/write index number */
@ -352,7 +356,8 @@ typedef struct {
/* File status structure (FILINFO) */ /* File status structure (FILINFO) */
typedef struct { typedef struct
{
DWORD fsize; /* File size */ DWORD fsize; /* File size */
WORD fdate; /* Last modified date */ WORD fdate; /* Last modified date */
WORD ftime; /* Last modified time */ WORD ftime; /* Last modified time */
@ -369,7 +374,8 @@ typedef struct {
/* File function return code (FRESULT) */ /* File function return code (FRESULT) */
typedef enum { typedef enum
{
FR_OK = 0, /* (0) Succeeded */ FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */ FR_INT_ERR, /* (2) Assertion failed */
@ -397,7 +403,8 @@ typedef enum {
/* FatFs module application interface */ /* FatFs module application interface */
/* Low Level functions */ /* 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 */ 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 */
FRESULT l_opendirbycluster ( FATFS *fs, DIR *dj, const TCHAR *path, DWORD clust ); FRESULT l_opendirbycluster ( FATFS *fs, DIR *dj, const TCHAR *path, DWORD clust );
/* application level functions */ /* application level functions */

View File

@ -37,81 +37,113 @@ WCHAR ff_convert(WCHAR w, UINT dir) {
int newcard; int newcard;
void file_init() { void file_init()
{
file_res = f_mount( 0, &fatfs ); file_res = f_mount( 0, &fatfs );
newcard = 0; newcard = 0;
} }
void file_reinit(void) { void file_reinit( void )
{
disk_init(); disk_init();
file_init(); file_init();
} }
FRESULT dir_open_by_filinfo(DIR* dir, FILINFO* fno) { FRESULT dir_open_by_filinfo( DIR *dir, FILINFO *fno )
{
return l_opendirbycluster( &fatfs, dir, ( TCHAR * )"", fno->clust ); return l_opendirbycluster( &fatfs, dir, ( TCHAR * )"", fno->clust );
} }
void file_open_by_filinfo(FILINFO* fno) { void file_open_by_filinfo( FILINFO *fno )
{
file_res = l_openfilebycluster( &fatfs, &file_handle, ( TCHAR * )"", fno->clust, fno->fsize ); file_res = l_openfilebycluster( &fatfs, &file_handle, ( TCHAR * )"", fno->clust, fno->fsize );
} }
void file_open(const uint8_t* filename, BYTE flags) { void file_open( const uint8_t *filename, BYTE flags )
if (disk_state == DISK_CHANGED) { {
if ( disk_state == DISK_CHANGED )
{
file_reinit(); file_reinit();
newcard = 1; newcard = 1;
} }
file_res = f_open( &file_handle, ( TCHAR * )filename, flags ); file_res = f_open( &file_handle, ( TCHAR * )filename, flags );
file_block_off = sizeof( file_buf ); file_block_off = sizeof( file_buf );
file_block_max = sizeof( file_buf ); file_block_max = sizeof( file_buf );
file_status = file_res ? FILE_ERR : FILE_OK; file_status = file_res ? FILE_ERR : FILE_OK;
} }
void file_close() { void file_close()
{
file_res = f_close( &file_handle ); file_res = f_close( &file_handle );
} }
void file_seek(uint32_t offset) { void file_seek( uint32_t offset )
{
file_res = f_lseek( &file_handle, ( DWORD )offset ); file_res = f_lseek( &file_handle, ( DWORD )offset );
} }
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 );
if(bytes_written < sizeof(file_buf)) {
if ( bytes_written < sizeof( file_buf ) )
{
printf( "wrote less than expected - card full?\n" ); printf( "wrote less than expected - card full?\n" );
} }
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;
} }
uint8_t file_getc() { uint8_t file_getc()
if(file_block_off == file_block_max) { {
if ( file_block_off == file_block_max )
{
file_block_max = file_read(); file_block_max = file_read();
if(file_block_max == 0) file_status = FILE_EOF;
if ( file_block_max == 0 )
{
file_status = FILE_EOF;
}
file_block_off = 0; file_block_off = 0;
} }
return file_buf[file_block_off++]; return file_buf[file_block_off++];
} }

View File

@ -36,24 +36,35 @@
#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) {
for (;;) { if ( res == FR_OK )
{
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;
} }
uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_tgt) { uint32_t scan_dir( char *path, FILINFO *fno_param, char mkdb, uint32_t this_dir_tgt )
{
DIR dir; DIR dir;
FILINFO fno; FILINFO fno;
FRESULT res; FRESULT res;
@ -80,7 +91,9 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
uint16_t entrycnt; uint16_t entrycnt;
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;
@ -93,10 +106,15 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
fno.lfsize = 255; fno.lfsize = 255;
fno.lfname = ( TCHAR * )file_lfn; fno.lfname = ( TCHAR * )file_lfn;
numentries = 0; numentries = 0;
for(pass = 0; pass < (mkdb ? 2 : 1); pass++) {
if(pass) { for ( pass = 0; pass < ( mkdb ? 2 : 1 ); pass++ )
{
if ( pass )
{
dirsize = 4 * ( numentries ); dirsize = 4 * ( numentries );
if(((next_subdir_tgt + dirsize + 8) & 0xff0000) > (next_subdir_tgt & 0xff0000)) {
if ( ( ( next_subdir_tgt + dirsize + 8 ) & 0xff0000 ) > ( next_subdir_tgt & 0xff0000 ) )
{
printf( "switchdir! old=%lX ", next_subdir_tgt + dirsize + 4 ); printf( "switchdir! old=%lX ", next_subdir_tgt + dirsize + 4 );
next_subdir_tgt &= 0xffff0000; next_subdir_tgt &= 0xffff0000;
next_subdir_tgt += 0x00010004; next_subdir_tgt += 0x00010004;
@ -104,34 +122,54 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
dir_tgt &= 0xffff0000; dir_tgt &= 0xffff0000;
dir_tgt += 0x00010004; dir_tgt += 0x00010004;
} }
switched_dir_tgt = dir_tgt; switched_dir_tgt = dir_tgt;
next_subdir_tgt += dirsize + 4; next_subdir_tgt += dirsize + 4;
if(parent_tgt) next_subdir_tgt += 4;
if(next_subdir_tgt > dir_end) { if ( parent_tgt )
{
next_subdir_tgt += 4;
}
if ( next_subdir_tgt > dir_end )
{
dir_end = next_subdir_tgt; dir_end = next_subdir_tgt;
} }
DBG_FS 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);
if(mkdb) { DBG_FS 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 );
if ( mkdb )
{
num_dirs_total++; num_dirs_total++;
// printf("d=%d Saving %lx to Address %lx [end]\n", depth, 0L, next_subdir_tgt - 4); // printf("d=%d Saving %lx to Address %lx [end]\n", depth, 0L, next_subdir_tgt - 4);
sram_writelong( 0L, next_subdir_tgt - 4 ); sram_writelong( 0L, next_subdir_tgt - 4 );
} }
} }
if(fno_param) {
if ( fno_param )
{
res = dir_open_by_filinfo( &dir, fno_param ); res = dir_open_by_filinfo( &dir, fno_param );
} else { }
else
{
res = f_opendir( &dir, path ); res = f_opendir( &dir, path );
} }
if (res == FR_OK) {
if(pass && parent_tgt && mkdb) { if ( res == FR_OK )
{
if ( pass && parent_tgt && mkdb )
{
/* write backlink to parent dir /* write backlink to parent dir
switch to next bank if record does not fit in current bank */ switch to next bank if record does not fit in current bank */
if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt)+sizeof(len)+4))&0xffff)) { if ( ( db_tgt & 0xffff ) > ( ( 0x10000 - ( sizeof( next_subdir_tgt ) + sizeof( len ) + 4 ) ) & 0xffff ) )
{
printf( "switch! old=%lx ", db_tgt ); printf( "switch! old=%lx ", db_tgt );
db_tgt &= 0xffff0000; db_tgt &= 0xffff0000;
db_tgt += 0x00010000; db_tgt += 0x00010000;
printf( "new=%lx\n", db_tgt ); printf( "new=%lx\n", db_tgt );
} }
// printf("writing link to parent, %lx to address %lx [../]\n", parent_tgt-SRAM_MENU_ADDR, db_tgt); // printf("writing link to parent, %lx to address %lx [../]\n", parent_tgt-SRAM_MENU_ADDR, db_tgt);
sram_writelong( ( parent_tgt - SRAM_MENU_ADDR ), db_tgt ); sram_writelong( ( parent_tgt - SRAM_MENU_ADDR ), db_tgt );
sram_writebyte( 0, db_tgt + sizeof( next_subdir_tgt ) ); sram_writebyte( 0, db_tgt + sizeof( next_subdir_tgt ) );
@ -140,40 +178,63 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
db_tgt += sizeof( next_subdir_tgt ) + sizeof( len ) + 4; db_tgt += sizeof( next_subdir_tgt ) + sizeof( len ) + 4;
dir_tgt += 4; dir_tgt += 4;
} }
len = strlen( ( char * )path ); len = strlen( ( char * )path );
/* scan at most DIR_FILE_MAX entries per directory */ /* scan at most DIR_FILE_MAX entries per directory */
for(entrycnt=0; entrycnt < DIR_FILE_MAX; entrycnt++) { for ( entrycnt = 0; entrycnt < DIR_FILE_MAX; entrycnt++ )
{
// toggle_read_led(); // toggle_read_led();
res = f_readdir( &dir, &fno ); res = f_readdir( &dir, &fno );
if (res != FR_OK || fno.fname[0] == 0) {
if(pass) { if ( res != FR_OK || fno.fname[0] == 0 )
if(!numentries) was_empty=1; {
if ( pass )
{
/* if(!numentries) was_empty=1;*/
} }
break; break;
} }
fn = *fno.lfname ? fno.lfname : fno.fname; fn = *fno.lfname ? fno.lfname : fno.fname;
if ((*fn == '.') || !(strncasecmp(fn, SYS_DIR_NAME, sizeof(SYS_DIR_NAME)))) continue;
if (fno.fattrib & AM_DIR) { if ( ( *fn == '.' ) || !( strncasecmp( fn, SYS_DIR_NAME, sizeof( SYS_DIR_NAME ) ) ) )
{
continue;
}
if ( fno.fattrib & AM_DIR )
{
depth++; depth++;
if(depth < FS_MAX_DEPTH) {
if ( depth < FS_MAX_DEPTH )
{
numentries++; numentries++;
if(pass && mkdb) {
if ( pass && mkdb )
{
path[len] = '/'; path[len] = '/';
strncpy( path + len + 1, ( char * )fn, sizeof( fs_path ) - len ); strncpy( path + len + 1, ( char * )fn, sizeof( fs_path ) - len );
uint16_t pathlen = 0; uint16_t pathlen = 0;
uint32_t old_db_tgt = 0; uint32_t old_db_tgt = 0;
if(mkdb) {
if ( mkdb )
{
pathlen = strlen( path ); pathlen = strlen( path );
DBG_FS printf( "d=%d Saving %lx to Address %lx [dir]\n", depth, db_tgt, dir_tgt ); DBG_FS printf( "d=%d Saving %lx to Address %lx [dir]\n", depth, db_tgt, dir_tgt );
/* save element: /* save element:
- path name - path name
- pointer to sub dir structure */ - pointer to sub dir structure */
if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2))&0xffff)) { if ( ( db_tgt & 0xffff ) > ( ( 0x10000 - ( sizeof( next_subdir_tgt ) + sizeof( len ) + pathlen + 2 ) ) & 0xffff ) )
{
printf( "switch! old=%lx ", db_tgt ); printf( "switch! old=%lx ", db_tgt );
db_tgt &= 0xffff0000; db_tgt &= 0xffff0000;
db_tgt += 0x00010000; db_tgt += 0x00010000;
printf( "new=%lx\n", db_tgt ); printf( "new=%lx\n", db_tgt );
} }
/* write element pointer to current dir structure */ /* write element pointer to current dir structure */
sram_writelong( ( db_tgt - SRAM_MENU_ADDR ) | ( ( uint32_t )0x80 << 24 ), dir_tgt ); sram_writelong( ( db_tgt - SRAM_MENU_ADDR ) | ( ( uint32_t )0x80 << 24 ), dir_tgt );
/* save element: /* save element:
@ -183,49 +244,68 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
old_db_tgt = db_tgt; old_db_tgt = db_tgt;
db_tgt += sizeof( next_subdir_tgt ) + sizeof( len ) + pathlen + 2; db_tgt += sizeof( next_subdir_tgt ) + sizeof( len ) + pathlen + 2;
} }
parent_tgt = this_dir_tgt; parent_tgt = this_dir_tgt;
/* scan subdir before writing current dir element to account for bank switches */ /* scan subdir before writing current dir element to account for bank switches */
uint32_t corrected_subdir_tgt = scan_dir( path, &fno, mkdb, next_subdir_tgt ); uint32_t corrected_subdir_tgt = scan_dir( path, &fno, mkdb, next_subdir_tgt );
if(mkdb) {
if ( mkdb )
{
DBG_FS printf( " Saving dir descriptor to %lx tgt=%lx, path=%s\n", old_db_tgt, corrected_subdir_tgt, path ); DBG_FS printf( " Saving dir descriptor to %lx tgt=%lx, path=%s\n", old_db_tgt, corrected_subdir_tgt, path );
sram_writelong( ( corrected_subdir_tgt - SRAM_MENU_ADDR ), old_db_tgt ); sram_writelong( ( corrected_subdir_tgt - SRAM_MENU_ADDR ), old_db_tgt );
sram_writebyte( len + 1, old_db_tgt + sizeof( next_subdir_tgt ) ); sram_writebyte( len + 1, old_db_tgt + sizeof( next_subdir_tgt ) );
sram_writeblock( path, old_db_tgt + sizeof( next_subdir_tgt ) + sizeof( len ), pathlen ); sram_writeblock( path, old_db_tgt + sizeof( next_subdir_tgt ) + sizeof( len ), pathlen );
sram_writeblock( "/\0", old_db_tgt + sizeof( next_subdir_tgt ) + sizeof( len ) + pathlen, 2 ); sram_writeblock( "/\0", old_db_tgt + sizeof( next_subdir_tgt ) + sizeof( len ) + pathlen, 2 );
} }
dir_tgt += 4; dir_tgt += 4;
was_empty = 0; /* was_empty = 0;*/
} else if(!mkdb) { }
else if ( !mkdb )
{
path[len] = '/'; path[len] = '/';
strncpy( path + len + 1, ( char * )fn, sizeof( fs_path ) - len ); strncpy( path + len + 1, ( char * )fn, sizeof( fs_path ) - len );
scan_dir( path, &fno, mkdb, next_subdir_tgt ); scan_dir( path, &fno, mkdb, next_subdir_tgt );
} }
} }
depth--; depth--;
path[len] = 0; path[len] = 0;
} else { }
else
{
SNES_FTYPE type = determine_filetype( ( char * )fn ); SNES_FTYPE type = determine_filetype( ( char * )fn );
if(type != TYPE_UNKNOWN) {
if ( type != TYPE_UNKNOWN )
{
numentries++; numentries++;
if(pass) {
if(mkdb) { if ( pass )
{
if ( mkdb )
{
num_files_total++; num_files_total++;
/* snes_romprops_t romprops; */ /* snes_romprops_t romprops; */
path[len] = '/'; path[len] = '/';
strncpy( path + len + 1, ( char * )fn, sizeof( fs_path ) - len ); strncpy( path + len + 1, ( char * )fn, sizeof( fs_path ) - len );
uint16_t pathlen = strlen( path ); uint16_t pathlen = strlen( path );
switch(type) {
switch ( type )
{
case TYPE_IPS: case TYPE_IPS:
case TYPE_SMC: case TYPE_SMC:
case TYPE_SPC: case TYPE_SPC:
/* write element pointer to current dir structure */ /* write element pointer to current dir structure */
DBG_FS printf( "d=%d Saving %lX to Address %lX [file %s]\n", depth, db_tgt, dir_tgt, path ); DBG_FS printf( "d=%d Saving %lX to Address %lX [file %s]\n", depth, db_tgt, dir_tgt, path );
if((db_tgt&0xffff) > ((0x10000-(sizeof(len) + pathlen + sizeof(buf)-1 + 1))&0xffff)) {
if ( ( db_tgt & 0xffff ) > ( ( 0x10000 - ( sizeof( len ) + pathlen + sizeof( buf ) - 1 + 1 ) ) & 0xffff ) )
{
printf( "switch! old=%lx ", db_tgt ); printf( "switch! old=%lx ", db_tgt );
db_tgt &= 0xffff0000; db_tgt &= 0xffff0000;
db_tgt += 0x00010000; db_tgt += 0x00010000;
printf( "new=%lx\n", db_tgt ); printf( "new=%lx\n", db_tgt );
} }
sram_writelong( ( db_tgt - SRAM_MENU_ADDR ) | ( ( uint32_t )type << 24 ), dir_tgt ); sram_writelong( ( db_tgt - SRAM_MENU_ADDR ) | ( ( uint32_t )type << 24 ), dir_tgt );
dir_tgt += 4; dir_tgt += 4;
/* save element: /* save element:
@ -235,10 +315,13 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
/* sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); */ /* sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); */
entry_fsize = fno.fsize; entry_fsize = fno.fsize;
entry_unit_idx = 0; entry_unit_idx = 0;
while(entry_fsize > 9999) {
while ( entry_fsize > 9999 )
{
entry_fsize >>= 10; entry_fsize >>= 10;
entry_unit_idx++; entry_unit_idx++;
} }
snprintf( buf, sizeof( buf ), "% 5ld", entry_fsize ); snprintf( buf, sizeof( buf ), "% 5ld", entry_fsize );
strncat( buf, size_units[entry_unit_idx], 1 ); strncat( buf, size_units[entry_unit_idx], 1 );
sram_writeblock( buf, db_tgt, sizeof( buf ) - 1 ); sram_writeblock( buf, db_tgt, sizeof( buf ) - 1 );
@ -247,86 +330,131 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
// sram_writelong(fno.fsize, db_tgt + sizeof(len) + pathlen + 1); // sram_writelong(fno.fsize, db_tgt + sizeof(len) + pathlen + 1);
db_tgt += sizeof( len ) + pathlen + sizeof( buf ) - 1 + 1; db_tgt += sizeof( len ) + pathlen + sizeof( buf ) - 1 + 1;
break; break;
case TYPE_UNKNOWN: case TYPE_UNKNOWN:
default: default:
break; break;
} }
path[len] = 0; path[len] = 0;
/* printf("%s ", path); /* printf("%s ", path);
_delay_ms(30); */ _delay_ms(30); */
} }
} else { }
else
{
TCHAR *fn2 = fn; TCHAR *fn2 = fn;
fncrc = 0; fncrc = 0;
while(*fn2 != 0) {
while ( *fn2 != 0 )
{
fncrc += crc_xmodem_update( fncrc, *( ( unsigned char * )fn2++ ) ); fncrc += crc_xmodem_update( fncrc, *( ( unsigned char * )fn2++ ) );
} }
crc += fncrc; crc += fncrc;
} }
} }
} }
} }
} else uart_putc(0x30+res);
} }
else
{
uart_putc( 0x30 + res );
}
}
DBG_FS printf( "db_tgt=%lx dir_end=%lx\n", db_tgt, dir_end ); DBG_FS printf( "db_tgt=%lx dir_end=%lx\n", db_tgt, dir_end );
sram_writelong( db_tgt, SRAM_DB_ADDR + 4 ); sram_writelong( db_tgt, SRAM_DB_ADDR + 4 );
sram_writelong( dir_end, SRAM_DB_ADDR + 8 ); sram_writelong( dir_end, SRAM_DB_ADDR + 8 );
sram_writeshort( num_files_total, SRAM_DB_ADDR + 12 ); sram_writeshort( num_files_total, SRAM_DB_ADDR + 12 );
sram_writeshort( num_dirs_total, SRAM_DB_ADDR + 14 ); sram_writeshort( num_dirs_total, SRAM_DB_ADDR + 14 );
if(depth==0) return crc;
else return switched_dir_tgt; if ( depth == 0 )
{
return crc;
}
else
{
return switched_dir_tgt;
}
return was_empty; // tricky!
} }
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" ) )
|| ( !strcasecmp( ext + 1, "SFC" ) ) || ( !strcasecmp( ext + 1, "SFC" ) )
|| ( !strcasecmp( ext + 1, "FIG" ) ) || ( !strcasecmp( ext + 1, "FIG" ) )
|| ( !strcasecmp( ext + 1, "BS" ) ) || ( !strcasecmp( ext + 1, "BS" ) )
) { )
{
return TYPE_SMC; return TYPE_SMC;
} }
/* if( (!strcasecmp(ext+1, "IPS")) /* if( (!strcasecmp(ext+1, "IPS"))
||(!strcasecmp(ext+1, "UPS")) ||(!strcasecmp(ext+1, "UPS"))
) { ) {
return TYPE_IPS; return TYPE_IPS;
}*/ }*/
if(!strcasecmp(ext+1, "SPC")) { if ( !strcasecmp( ext + 1, "SPC" ) )
{
return TYPE_SPC; return TYPE_SPC;
} }
return TYPE_UNKNOWN; return TYPE_UNKNOWN;
} }
FRESULT get_db_id(uint32_t* id) { FRESULT get_db_id( uint32_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, 4 ); file_readblock( id, 0, 4 );
/* XXX */// *id=0xdead; /* XXX */// *id=0xdead;
file_close(); file_close();
} else { }
else
{
*id = 0xdeadbeef; *id = 0xdeadbeef;
} }
return file_res; return file_res;
} }
int get_num_dirent(uint32_t addr) { int get_num_dirent( uint32_t addr )
{
int result = 0; int result = 0;
while(sram_readlong(addr+result*4)) {
while ( sram_readlong( addr + result * 4 ) )
{
result++; result++;
} }
return result; return result;
} }
void sort_all_dir(uint32_t endaddr) { void sort_all_dir( uint32_t endaddr )
{
uint32_t entries = 0; uint32_t entries = 0;
uint32_t current_base = SRAM_DIR_ADDR; uint32_t current_base = SRAM_DIR_ADDR;
while(current_base<(endaddr)) {
while(sram_readlong(current_base+entries*4)) { while ( current_base < ( endaddr ) )
{
while ( sram_readlong( current_base + entries * 4 ) )
{
entries++; entries++;
} }
printf( "sorting dir @%lx, entries: %ld\n", current_base, entries ); printf( "sorting dir @%lx, entries: %ld\n", current_base, entries );
sort_dir( current_base, entries ); sort_dir( current_base, entries );
current_base += 4 * entries + 4; current_base += 4 * entries + 4;

View File

@ -37,7 +37,8 @@
#define FS_MAX_DEPTH (10) #define FS_MAX_DEPTH (10)
#define SYS_DIR_NAME ((const char*)"sd2snes") #define SYS_DIR_NAME ((const char*)"sd2snes")
typedef enum { typedef enum
{
TYPE_UNKNOWN = 0, /* 0 */ TYPE_UNKNOWN = 0, /* 0 */
TYPE_SMC, /* 1 */ TYPE_SMC, /* 1 */
TYPE_SRM, /* 2 */ TYPE_SRM, /* 2 */

View File

@ -52,25 +52,37 @@
#include "rle.h" #include "rle.h"
#include "cfgware.h" #include "cfgware.h"
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) {
if(val)
BITBAND(CCLKREG->FIOSET, CCLKBIT) = 1;
else
BITBAND(CCLKREG->FIOCLR, CCLKBIT) = 1;
} }
int fpga_get_initb() { void fpga_set_cclk( uint8_t val )
{
if ( val )
{
BITBAND( CCLKREG->FIOSET, CCLKBIT ) = 1;
}
else
{
BITBAND( CCLKREG->FIOCLR, CCLKBIT ) = 1;
}
}
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 */
@ -79,119 +91,168 @@ void fpga_init() {
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( DONEREG->FIOPIN, DONEBIT ); return BITBAND( DONEREG->FIOPIN, DONEBIT );
} }
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;
uint8_t data; uint8_t data;
int i; int i;
tick_t timeout; tick_t timeout;
do {
do
{
i = 0; i = 0;
timeout = getticks() + 100; timeout = getticks() + 100;
fpga_set_prog_b( 0 ); fpga_set_prog_b( 0 );
if(BITBAND(PROGBREG->FIOPIN, PROGBBIT)) {
if ( BITBAND( PROGBREG->FIOPIN, PROGBBIT ) )
{
printf( "PROGB is stuck high!\n" ); printf( "PROGB is stuck high!\n" );
led_panic(); led_panic();
} }
uart_putc( 'P' ); uart_putc( 'P' );
fpga_set_prog_b( 1 ); fpga_set_prog_b( 1 );
while(!fpga_get_initb()){
if(getticks() > timeout) { while ( !fpga_get_initb() )
{
if ( getticks() > timeout )
{
printf( "no response from FPGA trying to initiate configuration!\n" ); printf( "no response from FPGA trying to initiate configuration!\n" );
led_panic(); led_panic();
} }
}; };
if(fpga_get_done()) {
if ( fpga_get_done() )
{
printf( "DONE is stuck high!\n" ); printf( "DONE is stuck high!\n" );
led_panic(); led_panic();
} }
LPC_GPIO2->FIOMASK1 = ~( BV( 0 ) ); LPC_GPIO2->FIOMASK1 = ~( BV( 0 ) );
uart_putc( 'p' ); uart_putc( 'p' );
/* 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;
} }
uart_putc( 'C' ); uart_putc( 'C' );
for (;;) { for ( ;; )
{
data = rle_file_getc(); data = rle_file_getc();
i++; i++;
if (file_status || file_res) break; /* error or eof */
if ( file_status || file_res )
{
break; /* error or eof */
}
FPGA_SEND_BYTE_SERIAL( data ); FPGA_SEND_BYTE_SERIAL( data );
} }
uart_putc( 'c' ); uart_putc( 'c' );
file_close(); file_close();
printf( "fpga_pgm: %d bytes programmed\n", i ); printf( "fpga_pgm: %d bytes programmed\n", i );
delay_ms( 1 ); delay_ms( 1 );
} while (!fpga_get_done() && retries--); }
if(!fpga_get_done()) { while ( !fpga_get_done() && retries-- );
if ( !fpga_get_done() )
{
printf( "FPGA failed to configure after %d tries.\n", MAXRETRIES ); printf( "FPGA failed to configure after %d tries.\n", MAXRETRIES );
led_panic(); led_panic();
} }
printf( "FPGA configured\n" ); printf( "FPGA configured\n" );
fpga_postinit(); fpga_postinit();
} }
void fpga_rompgm() { void fpga_rompgm()
{
int MAXRETRIES = 10; int MAXRETRIES = 10;
int retries = MAXRETRIES; int retries = MAXRETRIES;
uint8_t data; uint8_t data;
int i; int i;
tick_t timeout; tick_t timeout;
do {
do
{
i = 0; i = 0;
timeout = getticks() + 100; timeout = getticks() + 100;
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()){
if(getticks() > timeout) { while ( !fpga_get_initb() )
{
if ( getticks() > timeout )
{
printf( "no response from FPGA trying to initiate configuration!\n" ); printf( "no response from FPGA trying to initiate configuration!\n" );
led_panic(); led_panic();
} }
}; };
if(fpga_get_done()) {
if ( fpga_get_done() )
{
printf( "DONE is stuck high!\n" ); printf( "DONE is stuck high!\n" );
led_panic(); led_panic();
} }
LPC_GPIO2->FIOMASK1 = ~( BV( 0 ) ); LPC_GPIO2->FIOMASK1 = ~( BV( 0 ) );
uart_putc( 'p' ); uart_putc( 'p' );
/* open configware file */ /* open configware file */
rle_mem_init( cfgware, sizeof( cfgware ) ); rle_mem_init( cfgware, sizeof( cfgware ) );
printf( "sizeof(cfgware) = %d\n", sizeof( cfgware ) ); printf( "sizeof(cfgware) = %d\n", sizeof( cfgware ) );
for (;;) {
for ( ;; )
{
data = rle_mem_getc(); data = rle_mem_getc();
if(rle_state) break;
if ( rle_state )
{
break;
}
i++; i++;
FPGA_SEND_BYTE_SERIAL( data ); FPGA_SEND_BYTE_SERIAL( data );
} }
uart_putc( 'c' ); uart_putc( 'c' );
printf( "fpga_pgm: %d bytes programmed\n", i ); printf( "fpga_pgm: %d bytes programmed\n", i );
delay_ms( 1 ); delay_ms( 1 );
} while (!fpga_get_done() && retries--); }
if(!fpga_get_done()) { while ( !fpga_get_done() && retries-- );
if ( !fpga_get_done() )
{
printf( "FPGA failed to configure after %d tries.\n", MAXRETRIES ); printf( "FPGA failed to configure after %d tries.\n", MAXRETRIES );
led_panic(); led_panic();
} }
printf( "FPGA configured\n" ); printf( "FPGA configured\n" );
fpga_postinit(); fpga_postinit();
} }

View File

@ -1,6 +1,6 @@
/* sd2snes - SD card based universal cartridge for the SNES /* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net> Copyright (C) 2009-2012 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion uC firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al. Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h. See sdcard.c|h, config.h.
@ -142,145 +142,151 @@
#include "timer.h" #include "timer.h"
#include "sdnative.h" #include "sdnative.h"
void fpga_spi_init(void) { void fpga_spi_init( void )
{
spi_init(); spi_init();
BITBAND( FPGA_MCU_RDY_REG->FIODIR, FPGA_MCU_RDY_BIT ) = 0; BITBAND( FPGA_MCU_RDY_REG->FIODIR, FPGA_MCU_RDY_BIT ) = 0;
} }
void set_msu_addr(uint16_t address) { void set_msu_addr( uint16_t address )
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x02); FPGA_TX_BYTE( FPGA_CMD_SETADDR | FPGA_TGT_MSUBUF );
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_dac_addr(uint16_t address) { void set_dac_addr( uint16_t address )
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x01); FPGA_TX_BYTE( FPGA_CMD_SETADDR | FPGA_TGT_DACBUF );
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_mcu_addr(uint32_t address) { void set_mcu_addr( uint32_t address )
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x00); FPGA_TX_BYTE( FPGA_CMD_SETADDR | FPGA_TGT_MEM );
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( FPGA_CMD_SETRAMMASK );
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( FPGA_CMD_SETROMMASK );
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( FPGA_CMD_SETMAPPER( val ) );
FPGA_DESELECT(); FPGA_DESELECT();
} }
uint8_t fpga_test() { uint8_t fpga_test()
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xF0); /* TEST */ FPGA_TX_BYTE( FPGA_CMD_TEST );
uint8_t result = FPGA_RX_BYTE(); uint8_t result = FPGA_RX_BYTE();
FPGA_DESELECT(); FPGA_DESELECT();
return result; return result;
} }
uint16_t fpga_status() { uint16_t fpga_status()
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xF1); /* STATUS */ FPGA_TX_BYTE( FPGA_CMD_GETSTATUS );
uint16_t result = ( FPGA_RX_BYTE() ) << 8; uint16_t result = ( FPGA_RX_BYTE() ) << 8;
result |= FPGA_RX_BYTE(); result |= FPGA_RX_BYTE();
FPGA_DESELECT(); FPGA_DESELECT();
return result; return result;
} }
void fpga_set_sddma_range(uint16_t start, uint16_t end) { void fpga_set_sddma_range( uint16_t start, uint16_t end )
{
printf( "%s %08X -> %08X\n", __func__, start, end );
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x60); /* DMA_RANGE */ FPGA_TX_BYTE( FPGA_CMD_SDDMA_RANGE );
FPGA_TX_BYTE( start >> 8 ); FPGA_TX_BYTE( start >> 8 );
FPGA_TX_BYTE( start & 0xff ); FPGA_TX_BYTE( start & 0xff );
FPGA_TX_BYTE( end >> 8 ); FPGA_TX_BYTE( end >> 8 );
FPGA_TX_BYTE( end & 0xff ); FPGA_TX_BYTE( end & 0xff );
//if(tgt==1 && (test=FPGA_RX_BYTE()) != 0x41) printf("!!!!!!!!!!!!!!! -%02x- \n", test);
FPGA_DESELECT(); FPGA_DESELECT();
} }
void fpga_sddma(uint8_t tgt, uint8_t partial) { void fpga_sddma( uint8_t tgt, uint8_t partial )
uint32_t test = 0; {
uint8_t status = 0; //printf("%s %02X -> %02X\n", __func__, tgt, partial);
//uint32_t test = 0;
//uint8_t status = 0;
BITBAND( SD_CLKREG->FIODIR, SD_CLKPIN ) = 0; BITBAND( SD_CLKREG->FIODIR, SD_CLKPIN ) = 0;
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x40 | (tgt & 0x3) | ((partial & 1) << 2) ); /* DO DMA */ FPGA_TX_BYTE( FPGA_CMD_SDDMA | ( tgt & 3 ) | ( partial ? FPGA_SDDMA_PARTIAL : 0 ) );
FPGA_TX_BYTE( 0x00 ); /* dummy for falling DMA_EN edge */ FPGA_TX_BYTE( 0x00 ); /* dummy for falling DMA_EN edge */
//if(tgt==1 && (test=FPGA_RX_BYTE()) != 0x41) printf("!!!!!!!!!!!!!!! -%02x- \n", test);
FPGA_DESELECT(); FPGA_DESELECT();
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xF1); /* STATUS */ FPGA_TX_BYTE( FPGA_CMD_GETSTATUS );
DBG_SD printf( "FPGA DMA request sent, wait for completion..." ); DBG_SD printf( "FPGA DMA request sent, wait for completion..." );
while((status=FPGA_RX_BYTE()) & 0x80) {
while ( FPGA_RX_BYTE() & 0x80 )
{
FPGA_RX_BYTE(); /* eat the 2nd status byte */ FPGA_RX_BYTE(); /* eat the 2nd status byte */
test++;
} }
DBG_SD printf( "...complete\n" ); DBG_SD printf( "...complete\n" );
FPGA_DESELECT(); FPGA_DESELECT();
// if(test<5)printf("loopy: %ld %02x\n", test, status);
BITBAND( SD_CLKREG->FIODIR, SD_CLKPIN ) = 1; BITBAND( SD_CLKREG->FIODIR, SD_CLKPIN ) = 1;
} }
void set_dac_vol(uint8_t volume) { void dac_play()
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x50); FPGA_TX_BYTE( FPGA_CMD_DACPLAY );
FPGA_TX_BYTE(volume);
FPGA_TX_BYTE(0x00); /* latch rise */
FPGA_TX_BYTE(0x00); /* latch fall */
FPGA_DESELECT();
}
void dac_play() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe2);
FPGA_TX_BYTE( 0x00 ); /* latch reset */ FPGA_TX_BYTE( 0x00 ); /* latch reset */
FPGA_DESELECT(); FPGA_DESELECT();
} }
void dac_pause() { void dac_pause()
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xe1); FPGA_TX_BYTE( FPGA_CMD_DACPAUSE );
FPGA_TX_BYTE( 0x00 ); /* latch reset */ FPGA_TX_BYTE( 0x00 ); /* latch reset */
FPGA_DESELECT(); FPGA_DESELECT();
} }
void dac_reset() { void dac_reset()
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xe3); FPGA_TX_BYTE( FPGA_CMD_DACRESETPTR );
FPGA_TX_BYTE( 0x00 ); /* latch reset */ FPGA_TX_BYTE( 0x00 ); /* latch reset */
FPGA_TX_BYTE( 0x00 ); /* latch reset */ FPGA_TX_BYTE( 0x00 ); /* latch reset */
FPGA_DESELECT(); FPGA_DESELECT();
} }
void msu_reset(uint16_t address) { void msu_reset( uint16_t address )
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xe4); FPGA_TX_BYTE( FPGA_CMD_MSUSETPTR );
FPGA_TX_BYTE( ( address >> 8 ) & 0xff ); /* address hi */ FPGA_TX_BYTE( ( address >> 8 ) & 0xff ); /* address hi */
FPGA_TX_BYTE( address & 0xff ); /* address lo */ FPGA_TX_BYTE( address & 0xff ); /* address lo */
FPGA_TX_BYTE( 0x00 ); /* latch reset */ FPGA_TX_BYTE( 0x00 ); /* latch reset */
@ -288,35 +294,30 @@ void msu_reset(uint16_t address) {
FPGA_DESELECT(); FPGA_DESELECT();
} }
void set_msu_status(uint8_t set, uint8_t reset) { void set_msu_status( uint8_t set, uint8_t reset )
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xe0); FPGA_TX_BYTE( FPGA_CMD_MSUSETBITS );
FPGA_TX_BYTE( set ); FPGA_TX_BYTE( set );
FPGA_TX_BYTE( reset ); FPGA_TX_BYTE( reset );
FPGA_TX_BYTE( 0x00 ); /* latch reset */ FPGA_TX_BYTE( 0x00 ); /* latch reset */
FPGA_DESELECT(); FPGA_DESELECT();
} }
uint8_t get_msu_volume() { uint16_t get_msu_track()
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xF4); /* MSU_VOLUME */ FPGA_TX_BYTE( FPGA_CMD_MSUGETTRACK );
uint8_t result = FPGA_RX_BYTE();
FPGA_DESELECT();
return result;
}
uint16_t get_msu_track() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF3); /* MSU_TRACK */
uint16_t result = ( FPGA_RX_BYTE() ) << 8; uint16_t result = ( FPGA_RX_BYTE() ) << 8;
result |= FPGA_RX_BYTE(); result |= FPGA_RX_BYTE();
FPGA_DESELECT(); FPGA_DESELECT();
return result; return result;
} }
uint32_t get_msu_offset() { uint32_t get_msu_offset()
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xF2); /* MSU_OFFSET */ FPGA_TX_BYTE( FPGA_CMD_MSUGETADDR );
uint32_t result = ( FPGA_RX_BYTE() ) << 24; uint32_t result = ( FPGA_RX_BYTE() ) << 24;
result |= ( FPGA_RX_BYTE() ) << 16; result |= ( FPGA_RX_BYTE() ) << 16;
result |= ( FPGA_RX_BYTE() ) << 8; result |= ( FPGA_RX_BYTE() ) << 8;
@ -325,9 +326,10 @@ uint32_t get_msu_offset() {
return result; return result;
} }
uint32_t get_snes_sysclk() { uint32_t get_snes_sysclk()
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xFE); /* GET_SYSCLK */ FPGA_TX_BYTE( FPGA_CMD_GETSYSCLK );
FPGA_TX_BYTE( 0x00 ); /* dummy (copy current sysclk count to register) */ FPGA_TX_BYTE( 0x00 ); /* dummy (copy current sysclk count to register) */
uint32_t result = ( FPGA_RX_BYTE() ) << 24; uint32_t result = ( FPGA_RX_BYTE() ) << 24;
result |= ( FPGA_RX_BYTE() ) << 16; result |= ( FPGA_RX_BYTE() ) << 16;
@ -337,18 +339,20 @@ uint32_t get_snes_sysclk() {
return result; return result;
} }
void set_bsx_regs(uint8_t set, uint8_t reset) { void set_bsx_regs( uint8_t set, uint8_t reset )
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xe6); FPGA_TX_BYTE( FPGA_CMD_BSXSETBITS );
FPGA_TX_BYTE( set ); FPGA_TX_BYTE( set );
FPGA_TX_BYTE( reset ); FPGA_TX_BYTE( reset );
FPGA_TX_BYTE( 0x00 ); /* latch reset */ FPGA_TX_BYTE( 0x00 ); /* latch reset */
FPGA_DESELECT(); FPGA_DESELECT();
} }
void set_fpga_time(uint64_t time) { void set_fpga_time( uint64_t time )
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xe5); FPGA_TX_BYTE( FPGA_CMD_RTCSET );
FPGA_TX_BYTE( ( time >> 48 ) & 0xff ); FPGA_TX_BYTE( ( time >> 48 ) & 0xff );
FPGA_TX_BYTE( ( time >> 40 ) & 0xff ); FPGA_TX_BYTE( ( time >> 40 ) & 0xff );
FPGA_TX_BYTE( ( time >> 32 ) & 0xff ); FPGA_TX_BYTE( ( time >> 32 ) & 0xff );
@ -360,25 +364,28 @@ void set_fpga_time(uint64_t time) {
FPGA_DESELECT(); FPGA_DESELECT();
} }
void fpga_reset_srtc_state() { void fpga_reset_srtc_state()
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xe7); FPGA_TX_BYTE( FPGA_CMD_SRTCRESET );
FPGA_TX_BYTE( 0x00 ); FPGA_TX_BYTE( 0x00 );
FPGA_TX_BYTE( 0x00 ); FPGA_TX_BYTE( 0x00 );
FPGA_DESELECT(); FPGA_DESELECT();
} }
void fpga_reset_dspx_addr() { void fpga_reset_dspx_addr()
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xe8); FPGA_TX_BYTE( FPGA_CMD_DSPRESETPTR );
FPGA_TX_BYTE( 0x00 ); FPGA_TX_BYTE( 0x00 );
FPGA_TX_BYTE( 0x00 ); FPGA_TX_BYTE( 0x00 );
FPGA_DESELECT(); FPGA_DESELECT();
} }
void fpga_write_dspx_pgm(uint32_t data) { void fpga_write_dspx_pgm( uint32_t data )
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xe9); FPGA_TX_BYTE( FPGA_CMD_DSPWRITEPGM );
FPGA_TX_BYTE( ( data >> 16 ) & 0xff ); FPGA_TX_BYTE( ( data >> 16 ) & 0xff );
FPGA_TX_BYTE( ( data >> 8 ) & 0xff ); FPGA_TX_BYTE( ( data >> 8 ) & 0xff );
FPGA_TX_BYTE( ( data ) & 0xff ); FPGA_TX_BYTE( ( data ) & 0xff );
@ -387,9 +394,10 @@ void fpga_write_dspx_pgm(uint32_t data) {
FPGA_DESELECT(); FPGA_DESELECT();
} }
void fpga_write_dspx_dat(uint16_t data) { void fpga_write_dspx_dat( uint16_t data )
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xea); FPGA_TX_BYTE( FPGA_CMD_DSPWRITEDAT );
FPGA_TX_BYTE( ( data >> 8 ) & 0xff ); FPGA_TX_BYTE( ( data >> 8 ) & 0xff );
FPGA_TX_BYTE( ( data ) & 0xff ); FPGA_TX_BYTE( ( data ) & 0xff );
FPGA_TX_BYTE( 0x00 ); FPGA_TX_BYTE( 0x00 );
@ -397,25 +405,28 @@ void fpga_write_dspx_dat(uint16_t data) {
FPGA_DESELECT(); FPGA_DESELECT();
} }
void fpga_dspx_reset(uint8_t reset) { void fpga_dspx_reset( uint8_t reset )
{
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(reset ? 0xeb : 0xec); FPGA_TX_BYTE( reset ? FPGA_CMD_DSPRESET : FPGA_CMD_DSPUNRESET );
FPGA_TX_BYTE( 0x00 ); FPGA_TX_BYTE( 0x00 );
FPGA_DESELECT(); FPGA_DESELECT();
} }
void fpga_set_features(uint8_t feat) { void fpga_set_features( uint8_t feat )
{
printf( "set features: %02x\n", feat ); printf( "set features: %02x\n", feat );
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xed); FPGA_TX_BYTE( FPGA_CMD_SETFEATURE );
FPGA_TX_BYTE( feat ); FPGA_TX_BYTE( feat );
FPGA_DESELECT(); FPGA_DESELECT();
} }
void fpga_set_213f(uint8_t data) { void fpga_set_213f( uint8_t data )
{
printf( "set 213f: %d\n", data ); printf( "set 213f: %d\n", data );
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0xee); FPGA_TX_BYTE( FPGA_CMD_SET213F );
FPGA_TX_BYTE( data ); FPGA_TX_BYTE( data );
FPGA_DESELECT(); FPGA_DESELECT();
} }

View File

@ -57,6 +57,44 @@
#define FPGA_WAIT_RDY() do {while(BITBAND(SSP_REGS->SR, SSP_BSY)); while(!BITBAND(FPGA_MCU_RDY_REG->FIOPIN, FPGA_MCU_RDY_BIT));} while (0) #define FPGA_WAIT_RDY() do {while(BITBAND(SSP_REGS->SR, SSP_BSY)); while(!BITBAND(FPGA_MCU_RDY_REG->FIOPIN, FPGA_MCU_RDY_BIT));} while (0)
/* command parameters */
#define FPGA_MEM_AUTOINC (0x8)
#define FPGA_SDDMA_PARTIAL (0x4)
#define FPGA_TGT_MEM (0x0)
#define FPGA_TGT_DACBUF (0x1)
#define FPGA_TGT_MSUBUF (0x2)
/* commands */
#define FPGA_CMD_SETADDR (0x00)
#define FPGA_CMD_SETROMMASK (0x10)
#define FPGA_CMD_SETRAMMASK (0x20)
#define FPGA_CMD_SETMAPPER(x) (0x30 | (x & 15))
#define FPGA_CMD_SDDMA (0x40)
#define FPGA_CMD_SDDMA_RANGE (0x60)
#define FPGA_CMD_READMEM (0x80)
#define FPGA_CMD_WRITEMEM (0x90)
#define FPGA_CMD_MSUSETBITS (0xe0)
#define FPGA_CMD_DACPAUSE (0xe1)
#define FPGA_CMD_DACPLAY (0xe2)
#define FPGA_CMD_DACRESETPTR (0xe3)
#define FPGA_CMD_MSUSETPTR (0xe4)
#define FPGA_CMD_RTCSET (0xe5)
#define FPGA_CMD_BSXSETBITS (0xe6)
#define FPGA_CMD_SRTCRESET (0xe7)
#define FPGA_CMD_DSPRESETPTR (0xe8)
#define FPGA_CMD_DSPWRITEPGM (0xe9)
#define FPGA_CMD_DSPWRITEDAT (0xea)
#define FPGA_CMD_DSPRESET (0xeb)
#define FPGA_CMD_DSPUNRESET (0xec)
#define FPGA_CMD_SETFEATURE (0xed)
#define FPGA_CMD_SET213F (0xee)
#define FPGA_CMD_TEST (0xf0)
#define FPGA_CMD_GETSTATUS (0xf1)
#define FPGA_CMD_MSUGETADDR (0xf2)
#define FPGA_CMD_MSUGETTRACK (0xf3)
#define FPGA_CMD_GETSYSCLK (0xfe)
#define FPGA_CMD_ECHO (0xff)
void fpga_spi_init( void ); void fpga_spi_init( void );
uint8_t fpga_test( void ); uint8_t fpga_test( void );
uint16_t fpga_status( void ); uint16_t fpga_status( void );
@ -65,7 +103,6 @@ void spi_sd(void);
void spi_none( void ); void spi_none( void );
void set_mcu_addr( uint32_t ); void set_mcu_addr( uint32_t );
void set_dac_addr( uint16_t ); void set_dac_addr( uint16_t );
void set_dac_vol(uint8_t);
void dac_play( void ); void dac_play( void );
void dac_pause( void ); void dac_pause( void );
void dac_reset( void ); void dac_reset( void );
@ -77,7 +114,6 @@ void set_rom_mask(uint32_t);
void set_mapper( uint8_t val ); void set_mapper( uint8_t val );
void fpga_sddma( uint8_t tgt, uint8_t partial ); void fpga_sddma( uint8_t tgt, uint8_t partial );
void fpga_set_sddma_range( uint16_t start, uint16_t end ); void fpga_set_sddma_range( uint16_t start, uint16_t end );
uint8_t get_msu_volume(void);
uint16_t get_msu_track( void ); uint16_t get_msu_track( void );
uint32_t get_msu_offset( void ); uint32_t get_msu_offset( void );
uint32_t get_snes_sysclk( void ); uint32_t get_snes_sysclk( void );

View File

@ -4,9 +4,12 @@
#include "sdnative.h" #include "sdnative.h"
#include "uart.h" #include "uart.h"
void EINT3_IRQHandler(void) { void EINT3_IRQHandler( void )
{
NVIC_ClearPendingIRQ( EINT3_IRQn ); NVIC_ClearPendingIRQ( EINT3_IRQn );
if(SD_CHANGE_DETECT) {
if ( SD_CHANGE_DETECT )
{
SD_CHANGE_CLR(); SD_CHANGE_CLR();
sdn_changed(); sdn_changed();
} }

View File

@ -22,48 +22,68 @@ int led_pwmstate = 0;
write red P1.23 PWM1[4] write red P1.23 PWM1[4]
*/ */
void rdyled(unsigned int state) { void rdyled( unsigned int state )
if(led_pwmstate) { {
if ( led_pwmstate )
{
rdybright( state ? 15 : 0 ); rdybright( state ? 15 : 0 );
} else { }
else
{
BITBAND( LPC_GPIO2->FIODIR, 4 ) = state; BITBAND( LPC_GPIO2->FIODIR, 4 ) = state;
} }
led_rdyledstate = state; led_rdyledstate = state;
} }
void readled(unsigned int state) { void readled( unsigned int state )
if(led_pwmstate) { {
if ( led_pwmstate )
{
readbright( state ? 15 : 0 ); readbright( state ? 15 : 0 );
} else { }
else
{
BITBAND( LPC_GPIO2->FIODIR, 5 ) = state; BITBAND( LPC_GPIO2->FIODIR, 5 ) = state;
} }
led_readledstate = state; led_readledstate = state;
} }
void writeled(unsigned int state) { void writeled( unsigned int state )
if(led_pwmstate) { {
if ( led_pwmstate )
{
writebright( state ? 15 : 0 ); writebright( state ? 15 : 0 );
} else { }
else
{
BITBAND( LPC_GPIO1->FIODIR, 23 ) = state; BITBAND( LPC_GPIO1->FIODIR, 23 ) = state;
} }
led_writeledstate = state; led_writeledstate = state;
} }
void rdybright(uint8_t bright) { void rdybright( uint8_t bright )
{
LPC_PWM1->MR5 = led_bright[( bright & 15 )]; LPC_PWM1->MR5 = led_bright[( bright & 15 )];
BITBAND( LPC_PWM1->LER, 5 ) = 1; BITBAND( LPC_PWM1->LER, 5 ) = 1;
} }
void readbright(uint8_t bright) { void readbright( uint8_t bright )
{
LPC_PWM1->MR6 = led_bright[( bright & 15 )]; LPC_PWM1->MR6 = led_bright[( bright & 15 )];
BITBAND( LPC_PWM1->LER, 6 ) = 1; BITBAND( LPC_PWM1->LER, 6 ) = 1;
} }
void writebright(uint8_t bright) { void writebright( uint8_t bright )
{
LPC_PWM1->MR4 = led_bright[( bright & 15 )]; LPC_PWM1->MR4 = led_bright[( bright & 15 )];
BITBAND( LPC_PWM1->LER, 4 ) = 1; BITBAND( LPC_PWM1->LER, 4 ) = 1;
} }
void led_clkout32(uint32_t val) { void led_clkout32( uint32_t val )
while(1) { {
while ( 1 )
{
rdyled( 1 ); rdyled( 1 );
delay_ms( 400 ); delay_ms( 400 );
readled( ( val & BV( 31 ) ) >> 31 ); readled( ( val & BV( 31 ) ) >> 31 );
@ -73,21 +93,27 @@ void led_clkout32(uint32_t val) {
} }
} }
void toggle_rdy_led() { void toggle_rdy_led()
{
rdyled( ~led_rdyledstate ); rdyled( ~led_rdyledstate );
} }
void toggle_read_led() { void toggle_read_led()
{
readled( ~led_readledstate ); readled( ~led_readledstate );
} }
void toggle_write_led() { void toggle_write_led()
{
writeled( ~led_writeledstate ); writeled( ~led_writeledstate );
} }
void led_panic() { void led_panic()
{
led_std(); led_std();
while(1) {
while ( 1 )
{
rdyled( 1 ); rdyled( 1 );
readled( 1 ); readled( 1 );
writeled( 1 ); writeled( 1 );
@ -100,7 +126,8 @@ void led_panic() {
} }
} }
void led_pwm() { void led_pwm()
{
/* Rev.C P2.4, P2.5, P1.23 */ /* Rev.C P2.4, P2.5, P1.23 */
BITBAND( LPC_PINCON->PINSEL4, 9 ) = 0; BITBAND( LPC_PINCON->PINSEL4, 9 ) = 0;
BITBAND( LPC_PINCON->PINSEL4, 8 ) = 1; BITBAND( LPC_PINCON->PINSEL4, 8 ) = 1;
@ -118,7 +145,8 @@ void led_pwm() {
led_pwmstate = 1; led_pwmstate = 1;
} }
void led_std() { void led_std()
{
BITBAND( LPC_PINCON->PINSEL4, 9 ) = 0; BITBAND( LPC_PINCON->PINSEL4, 9 ) = 0;
BITBAND( LPC_PINCON->PINSEL4, 8 ) = 0; BITBAND( LPC_PINCON->PINSEL4, 8 ) = 0;
@ -135,7 +163,8 @@ void led_std() {
led_pwmstate = 0; led_pwmstate = 0;
} }
void led_init() { void led_init()
{
/* power is already connected by default */ /* power is already connected by default */
/* set PCLK divider to 8 */ /* set PCLK divider to 8 */
BITBAND( LPC_SC->PCLKSEL0, 13 ) = 1; BITBAND( LPC_SC->PCLKSEL0, 13 ) = 1;

View File

@ -27,8 +27,8 @@ if { [info exists CPUTAPID ] } {
#delays on reset lines #delays on reset lines
#if your OpenOCD version rejects "jtag_nsrst_delay" replace it with: #if your OpenOCD version rejects "jtag_nsrst_delay" replace it with:
#adapter_nsrst_delay 200 adapter_nsrst_delay 200
jtag_nsrst_delay 200 #jtag_nsrst_delay 200
jtag_ntrst_delay 200 jtag_ntrst_delay 200
# LPC2000 & LPC1700 -> SRST causes TRST # LPC2000 & LPC1700 -> SRST causes TRST
@ -39,7 +39,8 @@ jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID
#jtag newtap x3s tap -irlen 6 -ircapture 0x11 -irmask 0x11 -expected-id 0x0141c093 #jtag newtap x3s tap -irlen 6 -ircapture 0x11 -irmask 0x11 -expected-id 0x0141c093
set _TARGETNAME $_CHIPNAME.cpu set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m3 -chain-position $_TARGETNAME -event reset-init 0 #target create $_TARGETNAME cortex_m3 -chain-position $_TARGETNAME -event reset-init 0
target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME -event reset-init 0
# LPC1754 has 16kB of SRAM In the ARMv7-M "Code" area (at 0x10000000) # LPC1754 has 16kB of SRAM In the ARMv7-M "Code" area (at 0x10000000)
# and 16K more on AHB, in the ARMv7-M "SRAM" area, (at 0x2007c000). # and 16K more on AHB, in the ARMv7-M "SRAM" area, (at 0x2007c000).
@ -56,7 +57,7 @@ flash bank $_FLASHNAME lpc2000 0x0 0x20000 0 0 $_TARGETNAME \
# Run with *real slow* clock by default since the # Run with *real slow* clock by default since the
# boot rom could have been playing with the PLL, so # boot rom could have been playing with the PLL, so
# we have no idea what clock the target is running at. # we have no idea what clock the target is running at.
jtag_khz 1000 adapter_khz 1000
$_TARGETNAME configure -event reset-init { $_TARGETNAME configure -event reset-init {
# Do not remap 0x0000-0x0020 to anything but the flash (i.e. select # Do not remap 0x0000-0x0020 to anything but the flash (i.e. select

View File

@ -48,12 +48,24 @@ extern volatile int reset_changed;
extern volatile cfg_t CFG; extern volatile cfg_t CFG;
enum system_states { enum system_states
{
SYS_RTC_STATUS = 0, SYS_RTC_STATUS = 0,
SYS_LAST_STATUS = 1 SYS_LAST_STATUS = 1
}; };
int main(void) { int main( void )
{
uint8_t card_go = 0;
uint32_t saved_dir_id;
uint32_t mem_dir_id;
uint32_t mem_magic;
uint8_t cmd = 0;
uint64_t btime = 0;
uint32_t filesize = 0;
uint8_t snes_reset_prev = 0, snes_reset_now = 0, snes_reset_state = 0;
uint16_t reset_count = 0;
LPC_GPIO2->FIODIR = BV( 4 ) | BV( 5 ); LPC_GPIO2->FIODIR = BV( 4 ) | BV( 5 );
LPC_GPIO1->FIODIR = BV( 23 ) | BV( SNES_CIC_PAIR_BIT ); LPC_GPIO1->FIODIR = BV( 23 ) | BV( SNES_CIC_PAIR_BIT );
BITBAND( SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT ) = 1; BITBAND( SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT ) = 1;
@ -68,45 +80,62 @@ int main(void) {
/* pull-down CIC data lines */ /* pull-down CIC data lines */
LPC_PINCON->PINMODE0 = BV( 0 ) | BV( 1 ) | BV( 2 ) | BV( 3 ); LPC_PINCON->PINMODE0 = BV( 0 ) | BV( 1 ) | BV( 2 ) | BV( 3 );
clock_disconnect(); clock_disconnect(); /* Disable clock */
snes_init(); snes_init(); /* Set SNES Reset */
snes_reset(1); power_init(); /* Enable power block of LPC */
power_init(); timer_init(); /* Enable internal timer */
timer_init(); uart_init(); /* Configure UART */
uart_init(); fpga_spi_init(); /* Configure FPGA_SPI IOs */
fpga_spi_init(); spi_preinit(); /* Initialise SPI IO */
spi_preinit(); led_init(); /* Initialise LEDs IO */
led_init();
/* do this last because the peripheral init()s change PCLK dividers */ /* do this last because the peripheral init()s change PCLK dividers */
clock_init(); clock_init();
/* Output FPGA clock */
LPC_PINCON->PINSEL0 |= BV( 20 ) | BV( 21 ); /* MAT3.0 (FPGA clock) */ LPC_PINCON->PINSEL0 |= BV( 20 ) | BV( 21 ); /* MAT3.0 (FPGA clock) */
led_pwm();
sdn_init();
printf("\n\nsd2snes mk.2\n============\nfw ver.: " CONFIG_VERSION "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY);
printf("PCONP=%lx\n", LPC_SC->PCONP);
led_pwm(); /* Enabke PWM on LED (even if not used...) */
sdn_init(); /* SD init */
/* Print banner */
printf( "\n\nsd2snes mk.2\n============\nfw ver.: " CONFIG_VERSION "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY );
/* Init file manager */
file_init(); file_init();
/* */
cic_init( 0 ); cic_init( 0 );
/* setup timer (fpga clk) */ /* setup timer (fpga clk) */
LPC_TIM3->TCR = 2;
LPC_TIM3->CTCR = 0; LPC_TIM3->CTCR = 0;
LPC_TIM3->PR = 0;
LPC_TIM3->EMR = EMC0TOGGLE; LPC_TIM3->EMR = EMC0TOGGLE;
LPC_TIM3->MCR = MR0R; LPC_TIM3->MCR = MR0R;
LPC_TIM3->MR0 = 1; LPC_TIM3->MR0 = 1;
LPC_TIM3->TCR = 1; LPC_TIM3->TCR = 1;
fpga_init(); fpga_init();
fpga_rompgm(); fpga_rompgm();
sram_writebyte( 0, SRAM_CMD_ADDR ); sram_writebyte( 0, SRAM_CMD_ADDR );
while(1) {
if(disk_state == DISK_CHANGED) { while ( 1 ) /* Main loop */
sdn_init(); {
if ( disk_state == DISK_CHANGED )
{
sdn_init(); /* Reinit SD card */
newcard = 1; newcard = 1;
} }
load_bootrle( SRAM_MENU_ADDR ); load_bootrle( SRAM_MENU_ADDR );
set_saveram_mask(0x1fff); set_saveram_mask( 0xffff );
set_rom_mask( 0x3fffff ); set_rom_mask( 0x3fffff );
set_mapper( 0x7 ); set_mapper( 0x7 );
snes_reset( 0 ); snes_reset( 0 );
while(get_cic_state() == CIC_FAIL) {
while ( get_cic_state() == CIC_FAIL )
{
rdyled( 0 ); rdyled( 0 );
readled( 0 ); readled( 0 );
writeled( 0 ); writeled( 0 );
@ -116,59 +145,86 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
writeled( 1 ); writeled( 1 );
delay_ms( 500 ); delay_ms( 500 );
} }
/* some sanity checks */
uint8_t card_go = 0; /* Wait for valid card inserted */
while(!card_go) { card_go = 0;
if(disk_status(0) & (STA_NOINIT|STA_NODISK)) {
while ( !card_go )
{
if ( disk_status( 0 ) & ( STA_NOINIT | STA_NODISK ) )
{
snes_bootprint( " No SD Card found! \0" ); snes_bootprint( " No SD Card found! \0" );
while ( disk_status( 0 ) & ( STA_NOINIT | STA_NODISK ) ); while ( disk_status( 0 ) & ( STA_NOINIT | STA_NODISK ) );
delay_ms( 200 ); delay_ms( 200 );
} }
file_open( ( uint8_t * )"/sd2snes/menu.bin", FA_READ ); file_open( ( uint8_t * )"/sd2snes/menu.bin", FA_READ );
if(file_status != FILE_OK) {
if ( file_status != FILE_OK )
{
snes_bootprint( " /sd2snes/menu.bin not found! \0" ); snes_bootprint( " /sd2snes/menu.bin not found! \0" );
while ( disk_status( 0 ) == RES_OK ); while ( disk_status( 0 ) == RES_OK );
} else { }
else
{
/* Card found ! */
card_go = 1; card_go = 1;
} }
file_close(); file_close();
} }
snes_bootprint( " Loading ... \0" ); snes_bootprint( " Loading ... \0" );
if(get_cic_state() == CIC_PAIR) {
if ( get_cic_state() == CIC_PAIR )
{
printf( "PAIR MODE ENGAGED!\n" ); printf( "PAIR MODE ENGAGED!\n" );
cic_pair( CIC_NTSC, CIC_NTSC ); cic_pair( CIC_NTSC, CIC_NTSC );
} }
rdyled( 1 ); rdyled( 1 );
readled( 0 ); readled( 0 );
writeled( 0 ); writeled( 0 );
/* Load user config */
cfg_load(); cfg_load();
cfg_save(); cfg_save();
sram_writebyte( cfg_is_last_game_valid(), SRAM_STATUS_ADDR + SYS_LAST_STATUS ); sram_writebyte( cfg_is_last_game_valid(), SRAM_STATUS_ADDR + SYS_LAST_STATUS );
cfg_get_last_game( file_lfn ); cfg_get_last_game( file_lfn );
sram_writeblock( strrchr( ( const char * )file_lfn, '/' ) + 1, SRAM_LASTGAME_ADDR, 256 ); sram_writeblock( strrchr( ( const char * )file_lfn, '/' ) + 1, SRAM_LASTGAME_ADDR, 256 );
*fs_path = 0; *fs_path = 0;
uint32_t saved_dir_id;
get_db_id( &saved_dir_id ); get_db_id( &saved_dir_id );
uint32_t mem_dir_id = sram_readlong(SRAM_DIRID); mem_dir_id = sram_readlong( SRAM_DIRID );
uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD); mem_magic = sram_readlong( SRAM_SCRATCHPAD );
printf( "mem_magic=%lx mem_dir_id=%lx saved_dir_id=%lx\n", mem_magic, mem_dir_id, saved_dir_id ); printf( "mem_magic=%lx mem_dir_id=%lx saved_dir_id=%lx\n", mem_magic, mem_dir_id, saved_dir_id );
if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id) || (newcard)) {
if ( ( mem_magic != 0x12345678 ) || ( mem_dir_id != saved_dir_id ) || ( newcard ) )
{
newcard = 0; newcard = 0;
/* generate fs footprint (interesting files only) */ /* generate fs footprint (interesting files only) */
uint32_t curr_dir_id = scan_dir( fs_path, NULL, 0, 0 ); uint32_t curr_dir_id = scan_dir( fs_path, NULL, 0, 0 );
printf( "curr dir id = %lx\n", curr_dir_id ); printf( "curr dir id = %lx\n", curr_dir_id );
/* files changed or no database found? */ /* files changed or no database found? */
if((get_db_id(&saved_dir_id) != FR_OK) if ( ( get_db_id( &saved_dir_id ) != FR_OK ) || saved_dir_id != curr_dir_id )
|| saved_dir_id != curr_dir_id) { {
uint32_t endaddr, direndaddr;
/* rebuild database */ /* rebuild database */
printf( "saved dir id = %lx\n", saved_dir_id ); printf( "saved dir id = %lx\n", saved_dir_id );
printf( "rebuilding database..." ); printf( "rebuilding database..." );
snes_bootprint( " rebuilding database ... \0" ); snes_bootprint( " rebuilding database ... \0" );
curr_dir_id = scan_dir( fs_path, NULL, 1, 0 ); curr_dir_id = scan_dir( fs_path, NULL, 1, 0 );
sram_writeblock( &curr_dir_id, SRAM_DB_ADDR, 4 ); sram_writeblock( &curr_dir_id, SRAM_DB_ADDR, 4 );
uint32_t endaddr, direndaddr;
sram_readblock( &endaddr, SRAM_DB_ADDR + 4, 4 ); sram_readblock( &endaddr, SRAM_DB_ADDR + 4, 4 );
sram_readblock( &direndaddr, SRAM_DB_ADDR + 8, 4 ); sram_readblock( &direndaddr, SRAM_DB_ADDR + 8, 4 );
printf( "%lx %lx\n", endaddr, direndaddr ); printf( "%lx %lx\n", endaddr, direndaddr );
@ -181,27 +237,33 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
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 );
fpga_pgm( ( uint8_t * )"/sd2snes/fpga_base.bit" ); fpga_pgm( ( uint8_t * )"/sd2snes/fpga_base.bit" );
printf( "done\n" ); printf( "done\n" );
} else { }
else
{
printf( "saved dir id = %lx\n", saved_dir_id ); printf( "saved dir id = %lx\n", saved_dir_id );
printf( "different card, consistent db, loading db...\n" ); printf( "different card, consistent db, loading db...\n" );
fpga_pgm( ( uint8_t * )"/sd2snes/fpga_base.bit" ); fpga_pgm( ( uint8_t * )"/sd2snes/fpga_base.bit" );
load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.db", SRAM_DB_ADDR ); load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.db", SRAM_DB_ADDR );
load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR ); load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR );
} }
sram_writelong( curr_dir_id, SRAM_DIRID ); sram_writelong( curr_dir_id, SRAM_DIRID );
sram_writelong( 0x12345678, SRAM_SCRATCHPAD ); sram_writelong( 0x12345678, SRAM_SCRATCHPAD );
} else { }
snes_bootprint(" same card, loading db... \0"); else
printf("same card, loading db...\n"); {
snes_bootprint( " same card, loading db... \n" );
fpga_pgm( ( uint8_t * )"/sd2snes/fpga_base.bit" ); fpga_pgm( ( uint8_t * )"/sd2snes/fpga_base.bit" );
load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.db", SRAM_DB_ADDR ); load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.db", SRAM_DB_ADDR );
load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR ); load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR );
} }
/* cli_loop(); */ /* cli_loop(); */
/* load menu */ /* load menu */
fpga_dspx_reset( 1 ); fpga_dspx_reset( 1 );
uart_putc( '(' ); uart_putc( '(' );
uart_putcrlf();
load_rom( ( uint8_t * )"/sd2snes/menu.bin", SRAM_MENU_ADDR, 0 ); load_rom( ( uint8_t * )"/sd2snes/menu.bin", SRAM_MENU_ADDR, 0 );
/* force memory size + mapper */ /* force memory size + mapper */
set_rom_mask( 0x3fffff ); set_rom_mask( 0x3fffff );
@ -211,17 +273,24 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
sram_writebyte( 0, SRAM_CMD_ADDR ); sram_writebyte( 0, SRAM_CMD_ADDR );
if((rtc_state = rtc_isvalid()) != RTC_OK) { snes_bootprint( " same card, loading db... \n" );
if ( ( rtc_state = rtc_isvalid() ) != RTC_OK )
{
printf( "RTC invalid!\n" ); printf( "RTC invalid!\n" );
sram_writebyte( 0xff, SRAM_STATUS_ADDR + SYS_RTC_STATUS ); sram_writebyte( 0xff, SRAM_STATUS_ADDR + SYS_RTC_STATUS );
set_bcdtime( 0x20120701000000LL ); set_bcdtime( 0x20120701000000LL );
set_fpga_time( 0x20120701000000LL ); set_fpga_time( 0x20120701000000LL );
invalidate_rtc(); invalidate_rtc();
} else { }
else
{
printf( "RTC valid!\n" ); printf( "RTC valid!\n" );
sram_writebyte( 0x00, SRAM_STATUS_ADDR + SYS_RTC_STATUS ); sram_writebyte( 0x00, SRAM_STATUS_ADDR + SYS_RTC_STATUS );
set_fpga_time( get_bcdtime() ); set_fpga_time( get_bcdtime() );
} }
sram_memset( SRAM_SYSINFO_ADDR, 13 * 40, 0x20 ); sram_memset( SRAM_SYSINFO_ADDR, 13 * 40, 0x20 );
printf( "SNES GO!\n" ); printf( "SNES GO!\n" );
snes_reset( 1 ); snes_reset( 1 );
@ -230,23 +299,33 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
sram_writebyte( 32, SRAM_CMD_ADDR ); sram_writebyte( 32, SRAM_CMD_ADDR );
snes_reset( 0 ); snes_reset( 0 );
uint8_t cmd = 0; cmd = 0;
uint64_t btime = 0; btime = 0;
uint32_t filesize=0; filesize = 0;
printf("test sram\n");
while(!sram_reliable()) cli_entrycheck(); printf( "test sram... " );
printf("ok\n");
while ( !sram_reliable() )
{
cli_entrycheck();
}
printf( "ok\nWaiting command from menu...\n" );
//while(1) { //while(1) {
// delay_ms(1000); // delay_ms(1000);
// printf("Estimated SNES master clock: %ld Hz\n", get_snes_sysclk()); // printf("Estimated SNES master clock: %ld Hz\n", get_snes_sysclk());
//} //}
//sram_hexdump(SRAM_DB_ADDR, 0x200); //sram_hexdump(SRAM_DB_ADDR, 0x200);
//sram_hexdump(SRAM_MENU_ADDR, 0x400); //sram_hexdump(SRAM_MENU_ADDR, 0x400);
while(!cmd) {
while ( !cmd )
{
cmd = menu_main_loop(); cmd = menu_main_loop();
printf( "cmd: %d\n", cmd ); printf( "cmd: %d\n", cmd );
uart_putc('-');
switch(cmd) { switch ( cmd )
{
case SNES_CMD_LOADROM: case SNES_CMD_LOADROM:
get_selected_name( file_lfn ); get_selected_name( file_lfn );
printf( "Selected name: %s\n", file_lfn ); printf( "Selected name: %s\n", file_lfn );
@ -254,7 +333,9 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
cfg_set_last_game_valid( 1 ); cfg_set_last_game_valid( 1 );
cfg_save(); cfg_save();
filesize = load_rom( file_lfn, SRAM_ROM_ADDR, LOADROM_WITH_SRAM | LOADROM_WITH_RESET ); filesize = load_rom( file_lfn, SRAM_ROM_ADDR, LOADROM_WITH_SRAM | LOADROM_WITH_RESET );
printf( "Filesize = %lu\n", filesize );
break; break;
case SNES_CMD_SETRTC: case SNES_CMD_SETRTC:
/* get time from RAM */ /* get time from RAM */
btime = sram_gettime( SRAM_PARAM_ADDR ); btime = sram_gettime( SRAM_PARAM_ADDR );
@ -263,11 +344,13 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
set_fpga_time( btime ); set_fpga_time( btime );
cmd = 0; /* stay in menu loop */ cmd = 0; /* stay in menu loop */
break; break;
case SNES_CMD_SYSINFO: case SNES_CMD_SYSINFO:
/* go to sysinfo loop */ /* go to sysinfo loop */
sysinfo_loop(); sysinfo_loop();
cmd = 0; /* stay in menu loop */ cmd = 0; /* stay in menu loop */
break; break;
case SNES_CMD_LOADSPC: case SNES_CMD_LOADSPC:
/* load SPC file */ /* load SPC file */
get_selected_name( file_lfn ); get_selected_name( file_lfn );
@ -275,73 +358,104 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
filesize = load_spc( file_lfn, SRAM_SPC_DATA_ADDR, SRAM_SPC_HEADER_ADDR ); filesize = load_spc( file_lfn, SRAM_SPC_DATA_ADDR, SRAM_SPC_HEADER_ADDR );
cmd = 0; /* stay in menu loop */ cmd = 0; /* stay in menu loop */
break; break;
case SNES_CMD_RESET: case SNES_CMD_RESET:
/* process RESET request from SNES */ /* process RESET request from SNES */
printf( "RESET requested by SNES\n" ); printf( "RESET requested by SNES\n" );
snes_reset_pulse(); snes_reset_pulse();
cmd = 0; /* stay in menu loop */ cmd = 0; /* stay in menu loop */
break; break;
case SNES_CMD_LOADLAST: case SNES_CMD_LOADLAST:
cfg_get_last_game( file_lfn ); cfg_get_last_game( file_lfn );
printf( "Selected name: %s\n", file_lfn ); printf( "Selected name: %s\n", file_lfn );
filesize = load_rom( file_lfn, SRAM_ROM_ADDR, LOADROM_WITH_SRAM | LOADROM_WITH_RESET ); filesize = load_rom( file_lfn, SRAM_ROM_ADDR, LOADROM_WITH_SRAM | LOADROM_WITH_RESET );
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;
} }
} }
printf( "loaded %lu bytes\n", filesize );
printf( "cmd was %x, going to snes main loop\n", cmd ); printf( "cmd was %x, going to snes main loop\n", cmd );
if(romprops.has_msu1 && msu1_loop()) { if ( romprops.has_msu1 )
{
while ( !msu1_loop() );
prepare_reset(); prepare_reset();
continue; continue;
} }
cmd = 0; cmd = 0;
uint8_t snes_reset_prev=0, snes_reset_now=0, snes_reset_state=0; snes_reset_prev = 0;
uint16_t reset_count=0; snes_reset_now = 0;
while(fpga_test() == FPGA_TEST_TOKEN) { snes_reset_state = 0;
reset_count = 0;
while ( fpga_test() == FPGA_TEST_TOKEN )
{
cli_entrycheck(); cli_entrycheck();
sleep_ms( 250 ); sleep_ms( 250 );
sram_reliable(); sram_reliable();
printf( "%s ", get_cic_statename( get_cic_state() ) ); printf( "%s ", get_cic_statename( get_cic_state() ) );
if(reset_changed) {
if ( reset_changed )
{
printf( "reset\n" ); printf( "reset\n" );
reset_changed = 0; reset_changed = 0;
fpga_reset_srtc_state(); fpga_reset_srtc_state();
} }
snes_reset_now = get_snes_reset(); snes_reset_now = get_snes_reset();
if(snes_reset_now) {
if(!snes_reset_prev) { if ( snes_reset_now )
{
if ( !snes_reset_prev )
{
printf( "RESET BUTTON DOWN\n" ); printf( "RESET BUTTON DOWN\n" );
snes_reset_state = 1; snes_reset_state = 1;
reset_count = 0; reset_count = 0;
} }
} else { }
if(snes_reset_prev) { else
{
if ( snes_reset_prev )
{
printf( "RESET BUTTON UP\n" ); printf( "RESET BUTTON UP\n" );
snes_reset_state = 0; snes_reset_state = 0;
} }
} }
if(snes_reset_state) {
if ( snes_reset_state )
{
reset_count++; reset_count++;
} else { }
else
{
sram_reliable(); sram_reliable();
snes_main_loop(); snes_main_loop();
} }
if(reset_count>4) {
if ( reset_count > 4 )
{
reset_count = 0; reset_count = 0;
prepare_reset(); prepare_reset();
break; break;
} }
snes_reset_prev = snes_reset_now; snes_reset_prev = snes_reset_now;
} }
/* fpga test fail: panic */ /* fpga test fail: panic */
if(fpga_test() != FPGA_TEST_TOKEN){ if ( fpga_test() != FPGA_TEST_TOKEN )
{
led_panic(); led_panic();
} }
/* else reset */ /* else reset */
} }
} }

View File

@ -49,16 +49,21 @@ char* hex = "0123456789ABCDEF";
extern snes_romprops_t romprops; extern snes_romprops_t romprops;
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, addr );
} }
} }
void sram_writebyte(uint8_t val, uint32_t addr) { void sram_writebyte( uint8_t val, uint32_t addr )
{
//printf("WriteB %8Xh @%08lXh\n", val, addr);
set_mcu_addr( addr ); set_mcu_addr( addr );
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE( 0x98 ); /* WRITE */ FPGA_TX_BYTE( 0x98 ); /* WRITE */
@ -67,17 +72,21 @@ void sram_writebyte(uint8_t val, uint32_t addr) {
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( 0x88 ); /* READ */ FPGA_TX_BYTE( 0x88 ); /* READ */
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
uint8_t val = FPGA_RX_BYTE(); uint8_t val = FPGA_RX_BYTE();
FPGA_DESELECT(); FPGA_DESELECT();
//printf(" ReadB %8Xh @%08lXh\n", val, addr);
return val; return val;
} }
void sram_writeshort(uint16_t val, uint32_t addr) { void sram_writeshort( uint16_t val, uint32_t addr )
{
//printf("WriteS %8Xh @%08lXh\n", val, addr);
set_mcu_addr( addr ); set_mcu_addr( addr );
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE( 0x98 ); /* WRITE */ FPGA_TX_BYTE( 0x98 ); /* WRITE */
@ -88,7 +97,9 @@ void sram_writeshort(uint16_t val, uint32_t addr) {
FPGA_DESELECT(); FPGA_DESELECT();
} }
void sram_writelong(uint32_t val, uint32_t addr) { void sram_writelong( uint32_t val, uint32_t addr )
{
//printf("WriteL %8lXh @%08lXh\n", val, addr);
set_mcu_addr( addr ); set_mcu_addr( addr );
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE( 0x98 ); /* WRITE */ FPGA_TX_BYTE( 0x98 ); /* WRITE */
@ -103,7 +114,8 @@ void sram_writelong(uint32_t val, uint32_t addr) {
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( 0x88 ); FPGA_TX_BYTE( 0x88 );
@ -112,10 +124,12 @@ uint16_t sram_readshort(uint32_t addr) {
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
val |= ( ( uint32_t )FPGA_RX_BYTE() << 8 ); val |= ( ( uint32_t )FPGA_RX_BYTE() << 8 );
FPGA_DESELECT(); FPGA_DESELECT();
//printf(" ReadS %8lXh @%08lXh\n", val, addr);
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( 0x88 ); FPGA_TX_BYTE( 0x88 );
@ -128,15 +142,19 @@ uint32_t sram_readlong(uint32_t addr) {
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
val |= ( ( uint32_t )FPGA_RX_BYTE() << 24 ); val |= ( ( uint32_t )FPGA_RX_BYTE() << 24 );
FPGA_DESELECT(); FPGA_DESELECT();
//printf(" ReadL %8lXh @%08lXh\n", val, addr);
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( 0x88 ); FPGA_TX_BYTE( 0x88 );
uint16_t i = 0; uint16_t i = 0;
while(i<count) {
while ( i < count )
{
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
uint32_t val = ( uint32_t )FPGA_RX_BYTE() << 24; uint32_t val = ( uint32_t )FPGA_RX_BYTE() << 24;
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
@ -147,76 +165,127 @@ void sram_readlongblock(uint32_t* buf, uint32_t addr, uint16_t count) {
val |= FPGA_RX_BYTE(); val |= FPGA_RX_BYTE();
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( 0x88 ); /* READ */ FPGA_TX_BYTE( 0x88 ); /* READ */
while(count--) {
while ( count-- )
{
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
*( tgt++ ) = FPGA_RX_BYTE(); *( tgt++ ) = FPGA_RX_BYTE();
} }
FPGA_DESELECT(); FPGA_DESELECT();
} }
void sram_writeblock(void* buf, uint32_t addr, uint16_t size) { void sram_readstrn( void *buf, uint32_t addr, uint16_t size )
{
uint16_t count = size;
uint8_t *tgt = buf;
set_mcu_addr( addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x88 ); /* READ */
while ( count-- )
{
FPGA_WAIT_RDY();
if ( !( *( tgt++ ) = FPGA_RX_BYTE() ) )
{
break;
}
}
FPGA_DESELECT();
}
void sram_writeblock( void *buf, uint32_t addr, uint16_t size )
{
//printf("WriteZ %08lX -> %08lX [%d]\n", addr, addr+size, 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( 0x98 ); /* WRITE */ FPGA_TX_BYTE( 0x98 ); /* WRITE */
while(count--) {
while ( count-- )
{
FPGA_TX_BYTE( *src++ ); FPGA_TX_BYTE( *src++ );
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
} }
FPGA_DESELECT(); FPGA_DESELECT();
} }
uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) { uint32_t load_rom( uint8_t *filename, uint32_t base_addr, uint8_t flags )
{
UINT bytes_read; UINT bytes_read;
DWORD filesize; DWORD filesize, read_size = 0;
UINT count = 0; UINT count = 0;
tick_t ticksstart, ticks_total = 0; tick_t ticksstart, ticks_total = 0;
ticksstart = getticks(); ticksstart = getticks();
printf( "%s\n", filename ); printf( "%s\n", filename );
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 0; return 0;
} }
filesize = file_handle.fsize; filesize = file_handle.fsize;
smc_id( &romprops ); smc_id( &romprops );
file_close(); file_close();
/* reconfigure FPGA if necessary */ /* reconfigure FPGA if necessary */
if(romprops.fpga_conf) { if ( romprops.fpga_conf )
{
printf( "reconfigure FPGA with %s...\n", romprops.fpga_conf ); printf( "reconfigure FPGA with %s...\n", romprops.fpga_conf );
fpga_pgm( ( uint8_t * )romprops.fpga_conf ); fpga_pgm( ( uint8_t * )romprops.fpga_conf );
} }
set_mcu_addr( base_addr ); set_mcu_addr( base_addr );
file_open( filename, FA_READ ); file_open( filename, FA_READ );
ff_sd_offload = 1; ff_sd_offload = 1;
sd_offload_tgt = 0; sd_offload_tgt = 0;
f_lseek( &file_handle, romprops.offset ); f_lseek( &file_handle, romprops.offset );
for(;;) {
for ( ;; )
{
ff_sd_offload = 1; ff_sd_offload = 1;
sd_offload_tgt = 0; sd_offload_tgt = 0;
bytes_read = file_read(); bytes_read = file_read();
if (file_res || !bytes_read) break; read_size += bytes_read;
if(!(count++ % 512)) {
if ( file_res || !bytes_read )
{
break;
}
if ( !( count++ % 512 ) )
{
uart_putc( '.' ); uart_putc( '.' );
} }
} }
file_close(); file_close();
printf( "Read %ld [%08lX] bytes...\n", read_size, read_size );
set_mapper( romprops.mapper_id ); set_mapper( romprops.mapper_id );
printf( "rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id ); printf( "rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id );
ticks_total = getticks() - ticksstart; ticks_total = getticks() - ticksstart;
printf( "%u ticks total\n", ticks_total ); printf( "%u ticks total\n", ticks_total );
if(romprops.mapper_id==3) {
if ( romprops.mapper_id == 3 )
{
printf( "BSX Flash cart image\n" ); printf( "BSX Flash cart image\n" );
printf( "attempting to load BSX BIOS /sd2snes/bsxbios.bin...\n" ); printf( "attempting to load BSX BIOS /sd2snes/bsxbios.bin...\n" );
load_sram_offload( ( uint8_t * )"/sd2snes/bsxbios.bin", 0x800000 ); load_sram_offload( ( uint8_t * )"/sd2snes/bsxbios.bin", 0x800000 );
@ -225,63 +294,97 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) {
printf( "Type: %02x\n", romprops.header.destcode ); printf( "Type: %02x\n", romprops.header.destcode );
set_bsx_regs( 0xc0, 0x3f ); set_bsx_regs( 0xc0, 0x3f );
uint16_t rombase; uint16_t rombase;
if(romprops.header.ramsize & 1) {
if ( romprops.header.ramsize & 1 )
{
rombase = 0xff00; rombase = 0xff00;
// set_bsx_regs(0x36, 0xc9); // set_bsx_regs(0x36, 0xc9);
} else { }
else
{
rombase = 0x7f00; rombase = 0x7f00;
// set_bsx_regs(0x34, 0xcb); // set_bsx_regs(0x34, 0xcb);
} }
sram_writebyte( 0x33, rombase + 0xda ); sram_writebyte( 0x33, rombase + 0xda );
sram_writebyte( 0x00, rombase + 0xd4 ); sram_writebyte( 0x00, rombase + 0xd4 );
sram_writebyte( 0xfc, rombase + 0xd5 ); sram_writebyte( 0xfc, rombase + 0xd5 );
set_fpga_time( 0x0220110301180530LL ); set_fpga_time( 0x0220110301180530LL );
} }
if(romprops.has_dspx || romprops.has_cx4) {
if ( romprops.has_dspx || romprops.has_cx4 )
{
printf( "DSPx game. Loading firmware image %s...\n", romprops.dsp_fw ); printf( "DSPx game. Loading firmware image %s...\n", romprops.dsp_fw );
load_dspx( romprops.dsp_fw, romprops.fpga_features ); load_dspx( romprops.dsp_fw, romprops.fpga_features );
/* fallback to DSP1B firmware if DSP1.bin is not present */ /* fallback to DSP1B firmware if DSP1.bin is not present */
if(file_res && romprops.dsp_fw == DSPFW_1) { if ( file_res && romprops.dsp_fw == DSPFW_1 )
{
load_dspx( DSPFW_1B, romprops.fpga_features ); load_dspx( DSPFW_1B, romprops.fpga_features );
} }
if(file_res) {
if ( file_res )
{
snes_menu_errmsg( MENU_ERR_NODSP, ( void * )romprops.dsp_fw ); snes_menu_errmsg( MENU_ERR_NODSP, ( void * )romprops.dsp_fw );
} }
} }
uint32_t rammask; uint32_t rammask;
uint32_t rommask; uint32_t rommask;
while(filesize > (romprops.romsize_bytes + romprops.offset)) { while ( 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);
if ( rommask >= SRAM_SAVE_ADDR )
{
rommask = SRAM_SAVE_ADDR - 1;
}
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 );
readled( 0 ); readled( 0 );
if(flags & LOADROM_WITH_SRAM) {
if(romprops.ramsize_bytes) { if ( flags & LOADROM_WITH_SRAM )
{
if ( romprops.ramsize_bytes )
{
strcpy( strrchr( ( char * )filename, ( int )'.' ), ".srm" ); strcpy( strrchr( ( char * )filename, ( int )'.' ), ".srm" );
printf( "SRM file: %s\n", filename ); printf( "SRM file: %s\n", filename );
load_sram( filename, SRAM_SAVE_ADDR ); load_sram( filename, SRAM_SAVE_ADDR );
} else { }
else
{
printf( "No SRAM\n" ); printf( "No SRAM\n" );
} }
} }
printf( "check MSU..." ); printf( "check MSU..." );
if(msu1_check(filename)) {
if ( msu1_check( filename ) )
{
romprops.fpga_features |= FEAT_MSU1; romprops.fpga_features |= FEAT_MSU1;
romprops.has_msu1 = 1; romprops.has_msu1 = 1;
} else { }
else
{
romprops.has_msu1 = 0; romprops.has_msu1 = 0;
} }
printf( "done\n" ); printf( "done\n" );
romprops.fpga_features |= FEAT_SRTC; romprops.fpga_features |= FEAT_SRTC;
@ -290,7 +393,8 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) {
fpga_set_213f( romprops.region ); fpga_set_213f( romprops.region );
fpga_set_features( romprops.fpga_features ); fpga_set_features( romprops.fpga_features );
if(flags & LOADROM_WITH_RESET) { if ( flags & LOADROM_WITH_RESET )
{
fpga_dspx_reset( 1 ); fpga_dspx_reset( 1 );
snes_reset_pulse(); snes_reset_pulse();
fpga_dspx_reset( 0 ); fpga_dspx_reset( 0 );
@ -299,7 +403,8 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) {
return ( uint32_t )filesize; return ( uint32_t )filesize;
} }
uint32_t load_spc(uint8_t* filename, uint32_t spc_data_addr, uint32_t spc_header_addr) { uint32_t load_spc( uint8_t *filename, uint32_t spc_data_addr, uint32_t spc_header_addr )
{
DWORD filesize; DWORD filesize;
UINT bytes_read; UINT bytes_read;
uint8_t data; uint8_t data;
@ -308,9 +413,16 @@ uint32_t load_spc(uint8_t* filename, uint32_t spc_data_addr, uint32_t spc_header
printf( "%s\n", filename ); printf( "%s\n", filename );
file_open( filename, FA_READ ); /* Open SPC file */ file_open( filename, FA_READ ); /* Open SPC file */
if(file_res) return 0;
if ( file_res )
{
return 0;
}
filesize = file_handle.fsize; filesize = file_handle.fsize;
if (filesize < 65920) { /* At this point, we care about filesize only */
if ( filesize < 65920 ) /* At this point, we care about filesize only */
{
file_close(); /* since SNES decides if it is an SPC file */ file_close(); /* since SNES decides if it is an SPC file */
sram_writebyte( 0, spc_header_addr ); /* If file is too small, destroy previous SPC header */ sram_writebyte( 0, spc_header_addr ); /* If file is too small, destroy previous SPC header */
return 0; return 0;
@ -319,15 +431,24 @@ uint32_t load_spc(uint8_t* filename, uint32_t spc_data_addr, uint32_t spc_header
set_mcu_addr( spc_data_addr ); set_mcu_addr( spc_data_addr );
f_lseek( &file_handle, 0x100L ); /* Load 64K data segment */ f_lseek( &file_handle, 0x100L ); /* Load 64K data segment */
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( 0x98 ); FPGA_TX_BYTE( 0x98 );
for(j=0; j<bytes_read; j++) {
for ( j = 0; j < bytes_read; j++ )
{
FPGA_TX_BYTE( file_buf[j] ); FPGA_TX_BYTE( file_buf[j] );
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
} }
FPGA_DESELECT(); FPGA_DESELECT();
} }
@ -339,11 +460,14 @@ uint32_t load_spc(uint8_t* filename, uint32_t spc_data_addr, uint32_t spc_header
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE( 0x98 ); FPGA_TX_BYTE( 0x98 );
for (j = 0; j < 256; j++) {
for ( j = 0; j < 256; j++ )
{
data = file_getc(); data = file_getc();
FPGA_TX_BYTE( data ); FPGA_TX_BYTE( data );
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
} }
FPGA_DESELECT(); FPGA_DESELECT();
file_close(); file_close();
@ -354,11 +478,14 @@ uint32_t load_spc(uint8_t* filename, uint32_t spc_data_addr, uint32_t spc_header
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE( 0x98 ); FPGA_TX_BYTE( 0x98 );
for (j = 0; j < 128; j++) {
for ( j = 0; j < 128; j++ )
{
data = file_getc(); data = file_getc();
FPGA_TX_BYTE( data ); FPGA_TX_BYTE( data );
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
} }
FPGA_DESELECT(); FPGA_DESELECT();
file_close(); /* Done ! */ file_close(); /* Done ! */
@ -366,7 +493,9 @@ uint32_t load_spc(uint8_t* filename, uint32_t spc_data_addr, uint32_t spc_header
uint8_t esa = sram_readbyte( spc_header_addr + 0x100 + 0x6d ); uint8_t esa = sram_readbyte( spc_header_addr + 0x100 + 0x6d );
uint8_t edl = sram_readbyte( spc_header_addr + 0x100 + 0x7d ); uint8_t edl = sram_readbyte( spc_header_addr + 0x100 + 0x7d );
uint8_t flg = sram_readbyte( spc_header_addr + 0x100 + 0x6c ); uint8_t flg = sram_readbyte( spc_header_addr + 0x100 + 0x6c );
if(!(flg & 0x20) && (edl & 0x0f)) {
if ( !( flg & 0x20 ) && ( edl & 0x0f ) )
{
int echo_start = esa << 8; int echo_start = esa << 8;
int echo_length = ( edl & 0x0f ) << 11; int echo_length = ( edl & 0x0f ) << 11;
printf( "clearing echo buffer %04x-%04x...\n", echo_start, echo_start + echo_length - 1 ); printf( "clearing echo buffer %04x-%04x...\n", echo_start, echo_start + echo_length - 1 );
@ -376,69 +505,110 @@ uint32_t load_spc(uint8_t* filename, uint32_t spc_data_addr, uint32_t spc_header
return ( uint32_t )filesize; return ( uint32_t )filesize;
} }
uint32_t load_sram_offload(uint8_t* filename, uint32_t base_addr) { uint32_t load_sram_offload( 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;
for(;;) { if ( file_res )
{
return 0;
}
for ( ;; )
{
ff_sd_offload = 1; ff_sd_offload = 1;
sd_offload_tgt = 0; sd_offload_tgt = 0;
bytes_read = file_read(); bytes_read = file_read();
if (file_res || !bytes_read) break;
if ( file_res || !bytes_read )
{
break;
} }
}
file_close(); file_close();
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) {
if ( file_res )
{
printf( "load_sram: could not open %s, res=%d\n", filename, file_res ); printf( "load_sram: could not open %s, res=%d\n", filename, file_res );
return 0; 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( 0x98 ); FPGA_TX_BYTE( 0x98 );
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_WAIT_RDY(); FPGA_WAIT_RDY();
} }
FPGA_DESELECT(); FPGA_DESELECT();
} }
file_close(); file_close();
return ( uint32_t )filesize; return ( uint32_t )filesize;
} }
uint32_t load_sram_rle(uint8_t* filename, uint32_t base_addr) { uint32_t load_sram_rle( uint8_t *filename, uint32_t base_addr )
{
uint8_t data; uint8_t data;
set_mcu_addr( base_addr ); set_mcu_addr( base_addr );
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;
}
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE( 0x98 ); FPGA_TX_BYTE( 0x98 );
for(;;) {
for ( ;; )
{
data = rle_file_getc(); data = rle_file_getc();
if (file_res || file_status) break;
if ( file_res || file_status )
{
break;
}
FPGA_TX_BYTE( data ); FPGA_TX_BYTE( data );
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
} }
FPGA_DESELECT(); FPGA_DESELECT();
file_close(); file_close();
return ( uint32_t )filesize; return ( uint32_t )filesize;
} }
uint32_t load_bootrle(uint32_t base_addr) { uint32_t load_bootrle( uint32_t base_addr )
{
uint8_t data; uint8_t data;
set_mcu_addr( base_addr ); set_mcu_addr( base_addr );
DWORD filesize = 0; DWORD filesize = 0;
@ -446,47 +616,67 @@ uint32_t load_bootrle(uint32_t base_addr) {
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE( 0x98 ); FPGA_TX_BYTE( 0x98 );
for(;;) {
for ( ;; )
{
data = rle_mem_getc(); data = rle_mem_getc();
if(rle_state) break;
if ( rle_state )
{
break;
}
FPGA_TX_BYTE( data ); FPGA_TX_BYTE( data );
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
filesize++; filesize++;
} }
FPGA_DESELECT(); FPGA_DESELECT();
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( 0x88 ); /* read */ FPGA_TX_BYTE( 0x88 ); /* read */
for(int j=0; j<sizeof(file_buf); j++) {
for ( int j = 0; j < sizeof( file_buf ); j++ )
{
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
file_buf[j] = FPGA_RX_BYTE(); file_buf[j] = FPGA_RX_BYTE();
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;
uint32_t crc; uint32_t crc;
@ -495,23 +685,31 @@ uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size) {
set_mcu_addr( base_addr ); set_mcu_addr( base_addr );
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE( 0x88 ); FPGA_TX_BYTE( 0x88 );
for(count=0; count<size; count++) {
for ( count = 0; count < size; count++ )
{
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
data = FPGA_RX_BYTE(); data = FPGA_RX_BYTE();
if(get_snes_reset()) {
if ( get_snes_reset() )
{
crc_valid = 0; crc_valid = 0;
break; break;
} }
crc += crc32_update( crc, data ); crc += crc32_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;
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++;
@ -520,68 +718,90 @@ uint8_t sram_reliable() {
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 {
printf("i=%d val=%08lX\n", i, val);
//printf("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;
} }
void sram_memset(uint32_t base_addr, uint32_t len, uint8_t val) { void sram_memset( uint32_t base_addr, uint32_t len, uint8_t val )
{
set_mcu_addr( base_addr ); set_mcu_addr( base_addr );
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE( 0x98 ); FPGA_TX_BYTE( 0x98 );
for(uint32_t i=0; i<len; i++) {
for ( uint32_t i = 0; i < len; i++ )
{
FPGA_TX_BYTE( val ); FPGA_TX_BYTE( val );
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
} }
FPGA_DESELECT(); FPGA_DESELECT();
} }
uint64_t sram_gettime(uint32_t base_addr) { uint64_t sram_gettime( uint32_t base_addr )
{
set_mcu_addr( base_addr ); set_mcu_addr( base_addr );
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE( 0x88 ); FPGA_TX_BYTE( 0x88 );
uint8_t data; uint8_t data;
uint64_t result = 0LL; uint64_t result = 0LL;
/* 1st nibble is the century - 10 (binary) /* 1st nibble is the century - 10 (binary)
4th nibble is the month (binary) 4th nibble is the month (binary)
all other fields are BCD */ all other fields are BCD */
for(int i=0; i<12; i++) { for ( int i = 0; i < 12; i++ )
{
FPGA_WAIT_RDY(); FPGA_WAIT_RDY();
data = FPGA_RX_BYTE(); data = FPGA_RX_BYTE();
data &= 0xf; data &= 0xf;
switch(i) {
switch ( i )
{
case 0: case 0:
result = ( result << 4 ) | ( ( data / 10 ) + 1 ); result = ( result << 4 ) | ( ( data / 10 ) + 1 );
result = ( result << 4 ) | ( data % 10 ); result = ( result << 4 ) | ( data % 10 );
break; break;
case 3: case 3:
result = ( result << 4 ) | ( ( data / 10 ) ); result = ( result << 4 ) | ( ( data / 10 ) );
result = ( result << 4 ) | ( data % 10 ); result = ( result << 4 ) | ( data % 10 );
break; break;
default: default:
result = ( result << 4 ) | data; result = ( result << 4 ) | data;
} }
} }
FPGA_DESELECT(); FPGA_DESELECT();
return result & 0x00ffffffffffffffLL; return result & 0x00ffffffffffffffLL;
} }
void load_dspx(const uint8_t *filename, uint8_t coretype) { void load_dspx( const uint8_t *filename, uint8_t coretype )
{
UINT bytes_read; UINT bytes_read;
DWORD filesize; //DWORD filesize;
uint16_t word_cnt; uint16_t word_cnt;
uint8_t wordsize_cnt = 0; uint8_t wordsize_cnt = 0;
uint16_t sector_remaining = 0; uint16_t sector_remaining = 0;
@ -591,39 +811,53 @@ void load_dspx(const uint8_t *filename, uint8_t coretype) {
uint32_t pgmdata = 0; uint32_t pgmdata = 0;
uint16_t datdata = 0; uint16_t datdata = 0;
if(coretype & FEAT_ST0010) { if ( coretype & FEAT_ST0010 )
{
datsize = 1536; datsize = 1536;
pgmsize = 2048; pgmsize = 2048;
} else if (coretype & FEAT_DSPX) { }
else if ( coretype & FEAT_DSPX )
{
datsize = 1024; datsize = 1024;
pgmsize = 2048; pgmsize = 2048;
} else if (coretype & FEAT_CX4) { }
else if ( coretype & FEAT_CX4 )
{
datsize = 0; datsize = 0;
pgmsize = 1024; /* Cx4 data ROM */ pgmsize = 1024; /* Cx4 data ROM */
} else { }
else
{
printf( "load_dspx: unknown core (%02x)!\n", coretype ); printf( "load_dspx: unknown core (%02x)!\n", coretype );
} }
file_open( ( uint8_t * )filename, FA_READ ); file_open( ( uint8_t * )filename, FA_READ );
filesize = file_handle.fsize;
if(file_res) { /*filesize = file_handle.fsize;*/
if ( file_res )
{
printf( "Could not read %s: error %d\n", filename, file_res ); printf( "Could not read %s: error %d\n", filename, file_res );
return; return;
} }
fpga_reset_dspx_addr(); fpga_reset_dspx_addr();
for(word_cnt = 0; word_cnt < pgmsize;) { for ( word_cnt = 0; word_cnt < pgmsize; )
if(!sector_remaining) { {
if ( !sector_remaining )
{
bytes_read = file_read(); bytes_read = file_read();
sector_remaining = bytes_read; sector_remaining = bytes_read;
sector_cnt = 0; sector_cnt = 0;
} }
pgmdata = ( pgmdata << 8 ) | file_buf[sector_cnt]; pgmdata = ( pgmdata << 8 ) | file_buf[sector_cnt];
sector_cnt++; sector_cnt++;
wordsize_cnt++; wordsize_cnt++;
sector_remaining--; sector_remaining--;
if(wordsize_cnt == 3){
if ( wordsize_cnt == 3 )
{
wordsize_cnt = 0; wordsize_cnt = 0;
word_cnt++; word_cnt++;
fpga_write_dspx_pgm( pgmdata ); fpga_write_dspx_pgm( pgmdata );
@ -631,22 +865,29 @@ void load_dspx(const uint8_t *filename, uint8_t coretype) {
} }
wordsize_cnt = 0; wordsize_cnt = 0;
if(coretype & FEAT_ST0010) {
if ( coretype & FEAT_ST0010 )
{
file_seek( 0xc000 ); file_seek( 0xc000 );
sector_remaining = 0; sector_remaining = 0;
} }
for(word_cnt = 0; word_cnt < datsize;) { for ( word_cnt = 0; word_cnt < datsize; )
if(!sector_remaining) { {
if ( !sector_remaining )
{
bytes_read = file_read(); bytes_read = file_read();
sector_remaining = bytes_read; sector_remaining = bytes_read;
sector_cnt = 0; sector_cnt = 0;
} }
datdata = ( datdata << 8 ) | file_buf[sector_cnt]; datdata = ( datdata << 8 ) | file_buf[sector_cnt];
sector_cnt++; sector_cnt++;
wordsize_cnt++; wordsize_cnt++;
sector_remaining--; sector_remaining--;
if(wordsize_cnt == 2){
if ( wordsize_cnt == 2 )
{
wordsize_cnt = 0; wordsize_cnt = 0;
word_cnt++; word_cnt++;
fpga_write_dspx_dat( datdata ); fpga_write_dspx_dat( datdata );

View File

@ -30,25 +30,49 @@
#include <arm/NXP/LPC17xx/LPC17xx.h> #include <arm/NXP/LPC17xx/LPC17xx.h>
#include "smc.h" #include "smc.h"
#define SRAM_ROM_ADDR (0x000000L) #define MASK_BITS (0x000000)
#define SRAM_SAVE_ADDR (0xE00000L) #if 0
#define SRAM_ROM_ADDR ((0x000000L) & ~MASK_BITS)
#define SRAM_SAVE_ADDR ((0x400000L) & ~MASK_BITS)
#define SRAM_MENU_ADDR (0xC00000L) #define SRAM_MENU_ADDR ((0x7A0000L) & ~MASK_BITS)
#define SRAM_DIR_ADDR (0xC10000L) #define SRAM_DIR_ADDR ((0x410000L) & ~MASK_BITS)
#define SRAM_DB_ADDR (0xC80000L) #define SRAM_DB_ADDR ((0x420000L) & ~MASK_BITS)
#define SRAM_SPC_DATA_ADDR (0xFD0000L) #define SRAM_SPC_DATA_ADDR ((0x430000L) & ~MASK_BITS)
#define SRAM_SPC_HEADER_ADDR (0xFE0000L) #define SRAM_SPC_HEADER_ADDR ((0x440000L) & ~MASK_BITS)
#define SRAM_MENU_SAVE_ADDR (0xFF0000L) #define SRAM_MENU_SAVE_ADDR ((0x7F0000L) & ~MASK_BITS)
#define SRAM_CMD_ADDR (0xFF1000L) #define SRAM_CMD_ADDR ((0x7F1000L) & ~MASK_BITS)
#define SRAM_PARAM_ADDR (0xFF1004L) #define SRAM_PARAM_ADDR ((0x7F1004L) & ~MASK_BITS)
#define SRAM_STATUS_ADDR (0xFF1100L) #define SRAM_STATUS_ADDR ((0x7F1100L) & ~MASK_BITS)
#define SRAM_SYSINFO_ADDR (0xFF1200L) #define SRAM_SYSINFO_ADDR ((0x7F1200L) & ~MASK_BITS)
#define SRAM_LASTGAME_ADDR (0xFF1420L) #define SRAM_LASTGAME_ADDR ((0x7F1420L) & ~MASK_BITS)
#define SRAM_SCRATCHPAD (0xFFFF00L) #define SRAM_SCRATCHPAD ((0x7FFF00L) & ~MASK_BITS)
#define SRAM_DIRID (0xFFFFF0L) #define SRAM_DIRID ((0x7FFFF0L) & ~MASK_BITS)
#define SRAM_RELIABILITY_SCORE (0x100) #define SRAM_RELIABILITY_SCORE (0x100)
#else
#define SRAM_ROM_ADDR ((0x000000L) & ~MASK_BITS)
#define SRAM_SAVE_ADDR ((0x600000L) & ~MASK_BITS)
#define SRAM_MENU_ADDR ((0x500000L) & ~MASK_BITS)
#define SRAM_DIR_ADDR ((0x510000L) & ~MASK_BITS)
#define SRAM_DB_ADDR ((0x580000L) & ~MASK_BITS)
#define SRAM_SPC_DATA_ADDR ((0x7D0000L) & ~MASK_BITS)
#define SRAM_SPC_HEADER_ADDR ((0x7E0000L) & ~MASK_BITS)
#define SRAM_MENU_SAVE_ADDR ((0x7F0000L) & ~MASK_BITS)
#define SRAM_CMD_ADDR ((0x7F1000L) & ~MASK_BITS)
#define SRAM_PARAM_ADDR ((0x7F1004L) & ~MASK_BITS)
#define SRAM_STATUS_ADDR ((0x7F1100L) & ~MASK_BITS)
#define SRAM_SYSINFO_ADDR ((0x7F1200L) & ~MASK_BITS)
#define SRAM_LASTGAME_ADDR ((0x7F1420L) & ~MASK_BITS)
#define SRAM_SCRATCHPAD ((0x7FFF00L) & ~MASK_BITS)
#define SRAM_DIRID ((0x7FFFF0L) & ~MASK_BITS)
#define SRAM_RELIABILITY_SCORE (0x100)
#endif
#define LOADROM_WITH_SRAM (1) #define LOADROM_WITH_SRAM (1)
#define LOADROM_WITH_RESET (2) #define LOADROM_WITH_RESET (2)
@ -75,5 +99,5 @@ uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size);
uint8_t sram_reliable( void ); uint8_t sram_reliable( void );
void sram_memset( uint32_t base_addr, 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 ); uint64_t sram_gettime( uint32_t base_addr );
void sram_readstrn( void *buf, uint32_t addr, uint16_t size );
#endif #endif

View File

@ -29,7 +29,8 @@ uint16_t fpga_status_now;
enum msu_reset_state { MSU_RESET_NONE = 0, MSU_RESET_SHORT, MSU_RESET_LONG }; enum msu_reset_state { MSU_RESET_NONE = 0, MSU_RESET_SHORT, MSU_RESET_LONG };
void prepare_audio_track(uint16_t msu_track) { void prepare_audio_track( uint16_t msu_track )
{
/* open file, fill buffer */ /* open file, fill buffer */
char suffix[11]; char suffix[11];
f_close( &file_handle ); f_close( &file_handle );
@ -37,7 +38,9 @@ void prepare_audio_track(uint16_t msu_track) {
strcpy( ( char * )file_buf, ( char * )file_lfn ); strcpy( ( char * )file_buf, ( char * )file_lfn );
strcpy( strrchr( ( char * )file_buf, ( int )'.' ), suffix ); strcpy( strrchr( ( char * )file_buf, ( int )'.' ), suffix );
DBG_MSU1 printf( "filename: %s\n", file_buf ); DBG_MSU1 printf( "filename: %s\n", file_buf );
if(f_open(&file_handle, (const TCHAR*)file_buf, FA_READ) == FR_OK) {
if ( f_open( &file_handle, ( const TCHAR * )file_buf, FA_READ ) == FR_OK )
{
file_handle.cltbl = pcm_cltbl; file_handle.cltbl = pcm_cltbl;
pcm_cltbl[0] = CLTBL_SIZE; pcm_cltbl[0] = CLTBL_SIZE;
f_lseek( &file_handle, CREATE_LINKMAP ); f_lseek( &file_handle, CREATE_LINKMAP );
@ -55,18 +58,24 @@ void prepare_audio_track(uint16_t msu_track) {
f_read( &file_handle, file_buf, MSU_DAC_BUFSIZE, &msu_audio_bytes_read ); f_read( &file_handle, file_buf, MSU_DAC_BUFSIZE, &msu_audio_bytes_read );
/* clear busy bit */ /* clear busy bit */
set_msu_status( 0x00, 0x28 ); /* set no bits, reset audio_busy + audio_error */ set_msu_status( 0x00, 0x28 ); /* set no bits, reset audio_busy + audio_error */
} else { }
else
{
f_close( &file_handle ); f_close( &file_handle );
set_msu_status( 0x08, 0x20 ); /* reset audio_busy, set audio_error */ set_msu_status( 0x08, 0x20 ); /* reset audio_busy, set audio_error */
} }
} }
void prepare_data(uint32_t msu_offset) { void prepare_data( uint32_t msu_offset )
DBG_MSU1 printf("Data requested! Offset=%08lx page1=%08lx page2=%08lx\n", msu_offset, msu_page1_start, msu_page2_start); {
DBG_MSU1 printf( "Data requested! Offset=%08lx page1=%08lx page2=%08lx\n", msu_offset, msu_page1_start,
msu_page2_start );
if ( ( ( msu_offset < msu_page1_start ) if ( ( ( msu_offset < msu_page1_start )
|| ( msu_offset >= msu_page1_start + msu_page_size ) ) || ( msu_offset >= msu_page1_start + msu_page_size ) )
&& ( ( msu_offset < msu_page2_start ) && ( ( msu_offset < msu_page2_start )
|| (msu_offset >= msu_page2_start + msu_page_size))) { || ( msu_offset >= msu_page2_start + msu_page_size ) ) )
{
DBG_MSU1 printf( "offset %08lx out of range (%08lx-%08lx, %08lx-%08lx), reload\n", msu_offset, msu_page1_start, DBG_MSU1 printf( "offset %08lx out of range (%08lx-%08lx, %08lx-%08lx), reload\n", msu_offset, msu_page1_start,
msu_page1_start + msu_page_size - 1, msu_page2_start, msu_page2_start + msu_page_size - 1 ); msu_page1_start + msu_page_size - 1, msu_page2_start, msu_page2_start + msu_page_size - 1 );
/* "cache miss" */ /* "cache miss" */
@ -84,11 +93,16 @@ void prepare_data(uint32_t msu_offset) {
msu_reset( 0x0 ); msu_reset( 0x0 );
msu_page1_start = msu_offset; msu_page1_start = msu_offset;
msu_page2_start = msu_offset + msu_page_size; msu_page2_start = msu_offset + msu_page_size;
} else { }
if (msu_offset >= msu_page1_start && msu_offset <= msu_page1_start + msu_page_size) { else
{
if ( msu_offset >= msu_page1_start && msu_offset <= msu_page1_start + msu_page_size )
{
msu_reset( 0x0000 + msu_offset - msu_page1_start ); msu_reset( 0x0000 + msu_offset - msu_page1_start );
DBG_MSU1 printf( "inside page1, new offset: %08lx\n", 0x0000 + msu_offset - msu_page1_start ); DBG_MSU1 printf( "inside page1, new offset: %08lx\n", 0x0000 + msu_offset - msu_page1_start );
if(!(msu_page2_start == msu_page1_start + msu_page_size)) {
if ( !( msu_page2_start == msu_page1_start + msu_page_size ) )
{
set_msu_addr( 0x2000 ); set_msu_addr( 0x2000 );
sd_offload_tgt = 2; sd_offload_tgt = 2;
ff_sd_offload = 1; ff_sd_offload = 1;
@ -97,10 +111,14 @@ void prepare_data(uint32_t msu_offset) {
msu_page2_start = msu_page1_start + msu_page_size; msu_page2_start = msu_page1_start + msu_page_size;
DBG_MSU1 printf( "%08lx)\n", msu_page2_start ); DBG_MSU1 printf( "%08lx)\n", msu_page2_start );
} }
} else if (msu_offset >= msu_page2_start && msu_offset <= msu_page2_start + msu_page_size) { }
else if ( msu_offset >= msu_page2_start && msu_offset <= msu_page2_start + msu_page_size )
{
DBG_MSU1 printf( "inside page2, new offset: %08lx\n", 0x2000 + msu_offset - msu_page2_start ); DBG_MSU1 printf( "inside page2, new offset: %08lx\n", 0x2000 + msu_offset - msu_page2_start );
msu_reset( 0x2000 + msu_offset - msu_page2_start ); msu_reset( 0x2000 + msu_offset - msu_page2_start );
if(!(msu_page1_start == msu_page2_start + msu_page_size)) {
if ( !( msu_page1_start == msu_page2_start + msu_page_size ) )
{
set_msu_addr( 0x0 ); set_msu_addr( 0x0 );
sd_offload_tgt = 2; sd_offload_tgt = 2;
ff_sd_offload = 1; ff_sd_offload = 1;
@ -109,8 +127,13 @@ void prepare_data(uint32_t msu_offset) {
msu_page1_start = msu_page2_start + msu_page_size; msu_page1_start = msu_page2_start + msu_page_size;
DBG_MSU1 printf( "%08lx)\n", msu_page1_start ); DBG_MSU1 printf( "%08lx)\n", msu_page1_start );
} }
} else printf("!!!WATWATWAT!!!\n");
} }
else
{
printf( "!!!WATWATWAT!!!\n" );
}
}
/* clear bank bit to mask bank reset artifact */ /* clear bank bit to mask bank reset artifact */
fpga_status_now &= ~0x2000; fpga_status_now &= ~0x2000;
fpga_status_prev &= ~0x2000; fpga_status_prev &= ~0x2000;
@ -118,51 +141,71 @@ void prepare_data(uint32_t msu_offset) {
set_msu_status( 0x00, 0x10 ); set_msu_status( 0x00, 0x10 );
} }
int msu1_check_reset(void) { int msu1_check_reset( void )
{
static tick_t rising_ticks; static tick_t rising_ticks;
static uint8_t resbutton = 0, resbutton_prev = 0; static uint8_t resbutton = 0, resbutton_prev = 0;
int result = MSU_RESET_NONE; int result = MSU_RESET_NONE;
resbutton = get_snes_reset(); resbutton = get_snes_reset();
if(resbutton && !resbutton_prev) { /* push */
if ( resbutton && !resbutton_prev ) /* push */
{
rising_ticks = getticks(); rising_ticks = getticks();
} else if(resbutton && resbutton_prev) { /* hold */ }
if(getticks() > rising_ticks + 99) { else if ( resbutton && resbutton_prev ) /* hold */
{
if ( getticks() > rising_ticks + 99 )
{
result = MSU_RESET_LONG; result = MSU_RESET_LONG;
} }
} else if(!resbutton && resbutton_prev) { /* release */ }
if(getticks() < rising_ticks + 99) { else if ( !resbutton && resbutton_prev ) /* release */
{
if ( getticks() < rising_ticks + 99 )
{
result = MSU_RESET_SHORT; result = MSU_RESET_SHORT;
} }
} else { }
else
{
result = MSU_RESET_NONE; result = MSU_RESET_NONE;
} }
resbutton_prev = resbutton; resbutton_prev = resbutton;
return result; return result;
} }
int msu1_check(uint8_t* filename) { int msu1_check( uint8_t *filename )
{
/* open MSU file */ /* open MSU file */
strcpy( ( char * )file_buf, ( char * )filename ); strcpy( ( char * )file_buf, ( char * )filename );
strcpy( strrchr( ( char * )file_buf, ( int )'.' ), ".msu" ); strcpy( strrchr( ( char * )file_buf, ( int )'.' ), ".msu" );
printf( "MSU datafile: %s\n", file_buf ); printf( "MSU datafile: %s\n", file_buf );
if(f_open(&msufile, (const TCHAR*)file_buf, FA_READ) != FR_OK) {
if ( f_open( &msufile, ( const TCHAR * )file_buf, FA_READ ) != FR_OK )
{
printf( "MSU datafile not found\n" ); printf( "MSU datafile not found\n" );
return 0; return 0;
} }
msufile.cltbl = msu_cltbl; msufile.cltbl = msu_cltbl;
msu_cltbl[0] = CLTBL_SIZE; msu_cltbl[0] = CLTBL_SIZE;
if(f_lseek(&msufile, CREATE_LINKMAP)) {
if ( f_lseek( &msufile, CREATE_LINKMAP ) )
{
printf( "Error creating FF linkmap for MSU file!\n" ); printf( "Error creating FF linkmap for MSU file!\n" );
} }
romprops.fpga_features |= FEAT_MSU1; romprops.fpga_features |= FEAT_MSU1;
return 1; return 1;
} }
int msu1_loop() { int msu1_loop()
{
/* it is assumed that the MSU file is already opened by calling msu1_check(). */ /* it is assumed that the MSU file is already opened by calling msu1_check(). */
set_dac_vol(0x00);
while ( fpga_status() & 0x4000 ); while ( fpga_status() & 0x4000 );
uint16_t dac_addr = 0; uint16_t dac_addr = 0;
uint16_t msu_addr = 0; uint16_t msu_addr = 0;
uint8_t msu_repeat = 0; uint8_t msu_repeat = 0;
@ -196,24 +239,29 @@ int msu1_loop() {
prepare_audio_track( 0 ); prepare_audio_track( 0 );
prepare_data( 0 ); prepare_data( 0 );
/* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */ /* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */
while((msu_res = msu1_check_reset()) == MSU_RESET_NONE){ while ( ( msu_res = msu1_check_reset() ) == MSU_RESET_NONE )
{
cli_entrycheck(); cli_entrycheck();
fpga_status_now = fpga_status(); fpga_status_now = fpga_status();
/* Data buffer refill */ /* Data buffer refill */
if((fpga_status_now & 0x2000) != (fpga_status_prev & 0x2000)) { if ( ( fpga_status_now & 0x2000 ) != ( fpga_status_prev & 0x2000 ) )
{
DBG_MSU1 printf( "data\n" ); DBG_MSU1 printf( "data\n" );
uint8_t pageno = 0;
if(fpga_status_now & 0x2000) { if ( fpga_status_now & 0x2000 )
{
msu_addr = 0x0; msu_addr = 0x0;
msu_page1_start = msu_page2_start + msu_page_size; msu_page1_start = msu_page2_start + msu_page_size;
pageno = 1; }
} else { else
{
msu_addr = 0x2000; msu_addr = 0x2000;
msu_page2_start = msu_page1_start + msu_page_size; msu_page2_start = msu_page1_start + msu_page_size;
pageno = 2;
} }
set_msu_addr( msu_addr ); set_msu_addr( msu_addr );
sd_offload_tgt = 2; sd_offload_tgt = 2;
ff_sd_offload = 1; ff_sd_offload = 1;
@ -222,19 +270,25 @@ int msu1_loop() {
} }
/* Audio buffer refill */ /* Audio buffer refill */
if((fpga_status_now & 0x4000) != (fpga_status_prev & 0x4000)) { if ( ( fpga_status_now & 0x4000 ) != ( fpga_status_prev & 0x4000 ) )
if(fpga_status_now & 0x4000) { {
if ( fpga_status_now & 0x4000 )
{
dac_addr = 0; dac_addr = 0;
} else { }
else
{
dac_addr = MSU_DAC_BUFSIZE / 2; dac_addr = MSU_DAC_BUFSIZE / 2;
} }
set_dac_addr( dac_addr ); set_dac_addr( dac_addr );
sd_offload_tgt = 1; sd_offload_tgt = 1;
ff_sd_offload = 1; ff_sd_offload = 1;
f_read( &file_handle, file_buf, MSU_DAC_BUFSIZE / 2, &msu_audio_bytes_read ); f_read( &file_handle, file_buf, MSU_DAC_BUFSIZE / 2, &msu_audio_bytes_read );
} }
if(fpga_status_now & 0x0020) { if ( fpga_status_now & 0x0020 )
{
/* get trackno */ /* get trackno */
msu_track = get_msu_track(); msu_track = get_msu_track();
DBG_MSU1 printf( "Audio requested! Track=%d\n", msu_track ); DBG_MSU1 printf( "Audio requested! Track=%d\n", msu_track );
@ -242,28 +296,36 @@ int msu1_loop() {
prepare_audio_track( msu_track ); prepare_audio_track( msu_track );
} }
if(fpga_status_now & 0x0010) { if ( fpga_status_now & 0x0010 )
{
/* get address */ /* get address */
msu_offset = get_msu_offset(); msu_offset = get_msu_offset();
prepare_data( msu_offset ); prepare_data( msu_offset );
} }
if(fpga_status_now & 0x0001) { if ( fpga_status_now & 0x0001 )
if(fpga_status_now & 0x0004) { {
if ( fpga_status_now & 0x0004 )
{
msu_repeat = 1; msu_repeat = 1;
set_msu_status( 0x04, 0x01 ); /* set bit 2, reset bit 0 */ set_msu_status( 0x04, 0x01 ); /* set bit 2, reset bit 0 */
DBG_MSU1 printf( "Repeat set!\n" ); DBG_MSU1 printf( "Repeat set!\n" );
} else { }
else
{
msu_repeat = 0; msu_repeat = 0;
set_msu_status( 0x00, 0x05 ); /* set no bits, reset bit 0+2 */ set_msu_status( 0x00, 0x05 ); /* set no bits, reset bit 0+2 */
DBG_MSU1 printf( "Repeat clear!\n" ); DBG_MSU1 printf( "Repeat clear!\n" );
} }
if(fpga_status_now & 0x0002) { if ( fpga_status_now & 0x0002 )
{
DBG_MSU1 printf( "PLAY!\n" ); DBG_MSU1 printf( "PLAY!\n" );
set_msu_status( 0x02, 0x01 ); /* set bit 0, reset bit 1 */ set_msu_status( 0x02, 0x01 ); /* set bit 0, reset bit 1 */
dac_play(); dac_play();
} else { }
else
{
DBG_MSU1 printf( "PAUSE!\n" ); DBG_MSU1 printf( "PAUSE!\n" );
set_msu_status( 0x00, 0x03 ); /* set no bits, reset bit 1+0 */ set_msu_status( 0x00, 0x03 ); /* set no bits, reset bit 1+0 */
dac_pause(); dac_pause();
@ -273,10 +335,13 @@ int msu1_loop() {
fpga_status_prev = fpga_status_now; fpga_status_prev = fpga_status_now;
/* handle loop / end */ /* handle loop / end */
if(msu_audio_bytes_read < MSU_DAC_BUFSIZE / 2) { if ( msu_audio_bytes_read < MSU_DAC_BUFSIZE / 2 )
{
ff_sd_offload = 0; ff_sd_offload = 0;
sd_offload = 0; sd_offload = 0;
if(msu_repeat) {
if ( msu_repeat )
{
DBG_MSU1 printf( "loop\n" ); DBG_MSU1 printf( "loop\n" );
ff_sd_offload = 1; ff_sd_offload = 1;
sd_offload_tgt = 1; sd_offload_tgt = 1;
@ -284,20 +349,27 @@ int msu1_loop() {
ff_sd_offload = 1; ff_sd_offload = 1;
sd_offload_tgt = 1; sd_offload_tgt = 1;
f_read( &file_handle, file_buf, ( MSU_DAC_BUFSIZE / 2 ) - msu_audio_bytes_read, &msu_audio_bytes_read ); f_read( &file_handle, file_buf, ( MSU_DAC_BUFSIZE / 2 ) - msu_audio_bytes_read, &msu_audio_bytes_read );
} else { }
else
{
set_msu_status( 0x00, 0x02 ); /* clear play bit */ set_msu_status( 0x00, 0x02 ); /* clear play bit */
dac_pause(); dac_pause();
} }
msu_audio_bytes_read = MSU_DAC_BUFSIZE; msu_audio_bytes_read = MSU_DAC_BUFSIZE;
} }
} }
f_close( &file_handle ); f_close( &file_handle );
DBG_MSU1 printf( "Reset " ); DBG_MSU1 printf( "Reset " );
if(msu_res == MSU_RESET_LONG) {
if ( msu_res == MSU_RESET_LONG )
{
f_close( &msufile ); f_close( &msufile );
DBG_MSU1 printf( "to menu\n" ); DBG_MSU1 printf( "to menu\n" );
return 1; return 1;
} }
DBG_MSU1 printf( "game\n" ); DBG_MSU1 printf( "game\n" );
return 0; return 0;
} }

View File

@ -4,9 +4,16 @@
# http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html # http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html
# #
interface ft2232 #interface ft2232
ft2232_vid_pid 0x0403 0x6010 interface ftdi
ft2232_device_desc "Dual RS232" #ft2232_vid_pid 0x15ba 0x0003
ft2232_layout "oocdlink" #ft2232_device_desc "Olimex OpenOCD JTAG"
ft2232_latency 2 #ft2232_layout "olimex-jtag"
#interface ft2232
#ft2232_vid_pid 0x0403 0x6010
#ft2232_device_desc "Dual RS232"
#ft2232_layout "oocdlink"
#ft2232_latency 2
#adapter_khz 10 #adapter_khz 10

View File

@ -15,12 +15,12 @@
* USB [enabled via usb_init] * USB [enabled via usb_init]
* PWM1 * PWM1
*/ */
void power_init() { void power_init()
{
LPC_SC->PCONP = BV( PCSSP0 ) LPC_SC->PCONP = BV( PCSSP0 )
| BV( PCTIM3 ) | BV( PCTIM3 )
| BV( PCRTC ) | BV( PCRTC )
| BV( PCGPIO ) | BV( PCGPIO )
| BV( PCPWM1 ) | BV( PCPWM1 )
// | BV(PCUSB) | BV( PCUSB );
;
} }

View File

@ -61,8 +61,10 @@ static char *outptr;
static int maxlen; static int maxlen;
/* printf */ /* printf */
static void outchar(char x) { static void outchar( char x )
if (maxlen) { {
if ( maxlen )
{
maxlen--; maxlen--;
outfunc( x ); outfunc( x );
outlength++; outlength++;
@ -70,15 +72,18 @@ static void outchar(char x) {
} }
/* sprintf */ /* sprintf */
static void outstr(char x) { static void outstr( char x )
if (maxlen) { {
if ( maxlen )
{
maxlen--; maxlen--;
*outptr++ = x; *outptr++ = x;
outlength++; outlength++;
} }
} }
static int internal_nprintf(void (*output_function)(char c), const char *fmt, va_list ap) { static int internal_nprintf( void ( *output_function )( char c ), const char *fmt, va_list ap )
{
unsigned int width; unsigned int width;
unsigned int flags; unsigned int flags;
unsigned int base = 0; unsigned int base = 0;
@ -86,16 +91,24 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
outlength = 0; outlength = 0;
while (*fmt) { while ( *fmt )
while (1) { {
while ( 1 )
{
if ( *fmt == 0 ) if ( *fmt == 0 )
{
goto end; goto end;
}
if (*fmt == '%') { if ( *fmt == '%' )
{
fmt++; fmt++;
if ( *fmt != '%' ) if ( *fmt != '%' )
{
break; break;
} }
}
output_function( *fmt++ ); output_function( *fmt++ );
} }
@ -104,9 +117,12 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
width = 0; width = 0;
/* read all flags */ /* read all flags */
do { do
if (flags < FLAG_WIDTH) { {
switch (*fmt) { if ( flags < FLAG_WIDTH )
{
switch ( *fmt )
{
case '0': case '0':
flags |= FLAG_ZEROPAD; flags |= FLAG_ZEROPAD;
continue; continue;
@ -125,8 +141,10 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
} }
} }
if (flags < FLAG_LONG) { if ( flags < FLAG_LONG )
if (*fmt >= '0' && *fmt <= '9') { {
if ( *fmt >= '0' && *fmt <= '9' )
{
unsigned char tmp = *fmt - '0'; unsigned char tmp = *fmt - '0';
width = 10 * width + tmp; width = 10 * width + tmp;
flags |= FLAG_WIDTH; flags |= FLAG_WIDTH;
@ -134,20 +152,26 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
} }
if ( *fmt == 'h' ) if ( *fmt == 'h' )
{
continue; continue;
}
if (*fmt == 'l') { if ( *fmt == 'l' )
{
flags |= FLAG_LONG; flags |= FLAG_LONG;
continue; continue;
} }
} }
break; break;
} while (*fmt++); }
while ( *fmt++ );
/* Strings */ /* Strings */
if (*fmt == 'c' || *fmt == 's') { if ( *fmt == 'c' || *fmt == 's' )
switch (*fmt) { {
switch ( *fmt )
{
case 'c': case 'c':
buffer[0] = va_arg( ap, int ); buffer[0] = va_arg( ap, int );
ptr = buffer; ptr = buffer;
@ -162,9 +186,11 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
} }
/* Numbers */ /* Numbers */
switch (*fmt) { switch ( *fmt )
{
case 'u': case 'u':
flags |= FLAG_UNSIGNED; flags |= FLAG_UNSIGNED;
case 'd': case 'd':
base = 10; base = 10;
break; break;
@ -178,6 +204,7 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
output_function( '0' ); output_function( '0' );
output_function( 'x' ); output_function( 'x' );
width -= 2; width -= 2;
case 'x': case 'x':
case 'X': case 'X':
base = 16; base = 16;
@ -187,59 +214,89 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
unsigned int num; unsigned int num;
if (!(flags & FLAG_UNSIGNED)) { if ( !( flags & FLAG_UNSIGNED ) )
{
int tmp = va_arg( ap, int ); int tmp = va_arg( ap, int );
if (tmp < 0) {
if ( tmp < 0 )
{
num = -tmp; num = -tmp;
flags |= FLAG_NEGATIVE; flags |= FLAG_NEGATIVE;
} else }
else
{
num = tmp; num = tmp;
} else { }
}
else
{
num = va_arg( ap, unsigned int ); num = va_arg( ap, unsigned int );
} }
/* Convert number into buffer */ /* Convert number into buffer */
ptr = buffer + sizeof( buffer ); ptr = buffer + sizeof( buffer );
*--ptr = 0; *--ptr = 0;
do {
do
{
*--ptr = hexdigits[num % base]; *--ptr = hexdigits[num % base];
num /= base; num /= base;
} while (num != 0); }
while ( num != 0 );
/* Sign */ /* Sign */
if (flags & FLAG_NEGATIVE) { if ( flags & FLAG_NEGATIVE )
{
output_function( '-' ); output_function( '-' );
width--; width--;
} else if (flags & FLAG_FORCESIGN) { }
else if ( flags & FLAG_FORCESIGN )
{
output_function( '+' ); output_function( '+' );
width--; width--;
} else if (flags & FLAG_BLANK) { }
else if ( flags & FLAG_BLANK )
{
output_function( ' ' ); output_function( ' ' );
width--; width--;
} }
output: output:
/* left padding */ /* left padding */
if ((flags & FLAG_WIDTH) && !(flags & FLAG_LEFTADJ)) { if ( ( flags & FLAG_WIDTH ) && !( flags & FLAG_LEFTADJ ) )
while (strlen(ptr) < width) { {
while ( strlen( ptr ) < width )
{
if ( flags & FLAG_ZEROPAD ) if ( flags & FLAG_ZEROPAD )
{
output_function( '0' ); output_function( '0' );
}
else else
{
output_function( ' ' ); output_function( ' ' );
}
width--; width--;
} }
} }
/* data */ /* data */
while (*ptr) { while ( *ptr )
{
output_function( *ptr++ ); output_function( *ptr++ );
if ( width ) if ( width )
{
width--; width--;
} }
}
/* right padding */ /* right padding */
if (flags & FLAG_WIDTH) { if ( flags & FLAG_WIDTH )
while (width) { {
while ( width )
{
output_function( ' ' ); output_function( ' ' );
width--; width--;
} }
@ -252,7 +309,8 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
return outlength; return outlength;
} }
int printf(const char *format, ...) { int printf( const char *format, ... )
{
va_list ap; va_list ap;
int res; int res;
@ -263,7 +321,8 @@ int printf(const char *format, ...) {
return res; return res;
} }
int snprintf(char *str, size_t size, const char *format, ...) { int snprintf( char *str, size_t size, const char *format, ... )
{
va_list ap; va_list ap;
int res; int res;
@ -272,20 +331,26 @@ int snprintf(char *str, size_t size, const char *format, ...) {
va_start( ap, format ); va_start( ap, format );
res = internal_nprintf( outstr, format, ap ); res = internal_nprintf( outstr, format, ap );
va_end( ap ); va_end( ap );
if ( res < size ) if ( res < size )
{
str[res] = 0; str[res] = 0;
}
return res; return res;
} }
/* Required for gcc compatibility */ /* Required for gcc compatibility */
int puts(const char *str) { int puts( const char *str )
{
uart_puts( str ); uart_puts( str );
uart_putc( '\n' ); uart_putc( '\n' );
return 0; return 0;
} }
#undef putchar #undef putchar
int putchar(int c) { int putchar( int c )
{
uart_putc( c ); uart_putc( c );
return 0; return 0;
} }

View File

@ -2,65 +2,92 @@
#include "rle.h" #include "rle.h"
#include "fileops.h" #include "fileops.h"
uint8_t rle_file_getc() { uint8_t rle_file_getc()
{
static uint16_t rle_filled = 0; static uint16_t rle_filled = 0;
static uint8_t data; static uint8_t data;
if(!rle_filled) {
if ( !rle_filled )
{
data = file_getc(); data = file_getc();
switch(data) {
switch ( data )
{
case RLE_RUN: case RLE_RUN:
data = file_getc(); data = file_getc();
rle_filled = file_getc() - 1; rle_filled = file_getc() - 1;
break; break;
case RLE_RUNLONG: case RLE_RUNLONG:
data = file_getc(); data = file_getc();
rle_filled = file_getc(); rle_filled = file_getc();
rle_filled |= file_getc() << 8; rle_filled |= file_getc() << 8;
rle_filled--; rle_filled--;
break; break;
case RLE_ESC: case RLE_ESC:
data = file_getc(); data = file_getc();
break; break;
} }
} else { }
else
{
rle_filled--; rle_filled--;
} }
if(file_status || file_res) rle_filled = 0;
if ( file_status || file_res )
{
rle_filled = 0;
}
return data; return data;
} }
void rle_mem_init(const uint8_t* address, uint32_t len) { void rle_mem_init( const uint8_t *address, uint32_t len )
{
rle_mem_ptr = address; rle_mem_ptr = address;
rle_mem_endptr = address + len; rle_mem_endptr = address + len;
rle_state = 0; rle_state = 0;
} }
uint8_t rle_mem_getc() { uint8_t rle_mem_getc()
{
static uint16_t rle_mem_filled = 0; static uint16_t rle_mem_filled = 0;
static uint8_t rle_mem_data; static uint8_t rle_mem_data;
if(!rle_mem_filled) {
if ( !rle_mem_filled )
{
rle_mem_data = *( rle_mem_ptr++ ); rle_mem_data = *( rle_mem_ptr++ );
switch(rle_mem_data) {
switch ( rle_mem_data )
{
case RLE_RUN: case RLE_RUN:
rle_mem_data = *( rle_mem_ptr )++; rle_mem_data = *( rle_mem_ptr )++;
rle_mem_filled = *( rle_mem_ptr )++ - 1; rle_mem_filled = *( rle_mem_ptr )++ - 1;
break; break;
case RLE_RUNLONG: case RLE_RUNLONG:
rle_mem_data = *( rle_mem_ptr )++; rle_mem_data = *( rle_mem_ptr )++;
rle_mem_filled = *( rle_mem_ptr )++; rle_mem_filled = *( rle_mem_ptr )++;
rle_mem_filled |= *( rle_mem_ptr )++ << 8; rle_mem_filled |= *( rle_mem_ptr )++ << 8;
rle_mem_filled--; rle_mem_filled--;
break; break;
case RLE_ESC: case RLE_ESC:
rle_mem_data = *( rle_mem_ptr )++; rle_mem_data = *( rle_mem_ptr )++;
break; break;
} }
} else { }
else
{
rle_mem_filled--; rle_mem_filled--;
} }
if(rle_mem_ptr>=rle_mem_endptr){
if ( rle_mem_ptr >= rle_mem_endptr )
{
rle_mem_filled = 0; rle_mem_filled = 0;
rle_state = 1; rle_state = 1;
} }
return rle_mem_data; return rle_mem_data;
} }

View File

@ -11,23 +11,32 @@ rtcstate_t rtc_state;
#define CLKEN 0 #define CLKEN 0
#define CTCRST 1 #define CTCRST 1
uint8_t rtc_isvalid(void) { uint8_t rtc_isvalid( void )
if(LPC_RTC->GPREG0 == RTC_MAGIC) { {
if ( LPC_RTC->GPREG0 == RTC_MAGIC )
{
return RTC_OK; return RTC_OK;
} }
return RTC_INVALID; return RTC_INVALID;
} }
void rtc_init(void) { void rtc_init( void )
if (LPC_RTC->CCR & BV(CLKEN)) { {
if ( LPC_RTC->CCR & BV( CLKEN ) )
{
rtc_state = RTC_OK; rtc_state = RTC_OK;
} else { }
else
{
rtc_state = RTC_INVALID; rtc_state = RTC_INVALID;
} }
} }
void read_rtc(struct tm *time) { void read_rtc( struct tm *time )
do { {
do
{
time->tm_sec = LPC_RTC->SEC; time->tm_sec = LPC_RTC->SEC;
time->tm_min = LPC_RTC->MIN; time->tm_min = LPC_RTC->MIN;
time->tm_hour = LPC_RTC->HOUR; time->tm_hour = LPC_RTC->HOUR;
@ -35,24 +44,33 @@ void read_rtc(struct tm *time) {
time->tm_mon = LPC_RTC->MONTH; time->tm_mon = LPC_RTC->MONTH;
time->tm_year = LPC_RTC->YEAR; time->tm_year = LPC_RTC->YEAR;
time->tm_wday = LPC_RTC->DOW; time->tm_wday = LPC_RTC->DOW;
} while (time->tm_sec != LPC_RTC->SEC); }
while ( time->tm_sec != LPC_RTC->SEC );
} }
uint8_t calc_weekday(struct tm *time) { uint8_t calc_weekday( struct tm *time )
{
int month = time->tm_mon; int month = time->tm_mon;
int year = time->tm_year; int year = time->tm_year;
int day = time->tm_mday; int day = time->tm_mday;
/* Variation of Sillke for the Gregorian calendar. /* Variation of Sillke for the Gregorian calendar.
* http://www.mathematik.uni-bielefeld.de/~sillke/ALGORITHMS/calendar/weekday.c */ * http://www.mathematik.uni-bielefeld.de/~sillke/ALGORITHMS/calendar/weekday.c */
if (month <= 2) { if ( month <= 2 )
{
month += 10; month += 10;
year--; year--;
} else month -= 2; }
else
{
month -= 2;
}
return ( 83 * month / 32 + day + year + year / 4 - year / 100 + year / 400 ) % 7; return ( 83 * month / 32 + day + year + year / 4 - year / 100 + year / 400 ) % 7;
} }
void set_rtc(struct tm *time) { void set_rtc( struct tm *time )
{
LPC_RTC->CCR = BV( CTCRST ); LPC_RTC->CCR = BV( CTCRST );
LPC_RTC->SEC = time->tm_sec; LPC_RTC->SEC = time->tm_sec;
LPC_RTC->MIN = time->tm_min; LPC_RTC->MIN = time->tm_min;
@ -65,11 +83,13 @@ void set_rtc(struct tm *time) {
LPC_RTC->GPREG0 = RTC_MAGIC; LPC_RTC->GPREG0 = RTC_MAGIC;
} }
void invalidate_rtc() { void invalidate_rtc()
{
LPC_RTC->GPREG0 = 0; LPC_RTC->GPREG0 = 0;
} }
uint32_t get_fattime(void) { uint32_t get_fattime( void )
{
struct tm time; struct tm time;
read_rtc( &time ); read_rtc( &time );
@ -81,7 +101,8 @@ uint32_t get_fattime(void) {
( ( uint32_t )time.tm_sec ) >> 1; ( ( uint32_t )time.tm_sec ) >> 1;
} }
uint64_t get_bcdtime(void) { uint64_t get_bcdtime( void )
{
struct tm time; struct tm time;
read_rtc( &time ); read_rtc( &time );
uint16_t year = time.tm_year; uint16_t year = time.tm_year;
@ -103,7 +124,8 @@ uint64_t get_bcdtime(void) {
| ( time.tm_sec % 10 ); | ( time.tm_sec % 10 );
} }
void set_bcdtime(uint64_t btime) { void set_bcdtime( uint64_t btime )
{
struct tm time; struct tm time;
time.tm_sec = ( btime & 0xf ) + ( ( btime >> 4 ) & 0xf ) * 10; time.tm_sec = ( btime & 0xf ) + ( ( btime >> 4 ) & 0xf ) * 10;
time.tm_min = ( ( btime >> 8 ) & 0xf ) + ( ( btime >> 12 ) & 0xf ) * 10; time.tm_min = ( ( btime >> 8 ) & 0xf ) + ( ( btime >> 12 ) & 0xf ) * 10;
@ -116,12 +138,14 @@ void set_bcdtime(uint64_t btime) {
set_rtc( &time ); set_rtc( &time );
} }
void printtime(struct tm *time) { void printtime( struct tm *time )
{
printf( "%04d-%02d-%02d %02d:%02d:%02d\n", time->tm_year, 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 ); time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
} }
void testbattery() { void testbattery()
{
printf( "%lx\n", LPC_RTC->GPREG0 ); printf( "%lx\n", LPC_RTC->GPREG0 );
LPC_RTC->GPREG0 = RTC_MAGIC; LPC_RTC->GPREG0 = RTC_MAGIC;
printf( "%lx\n", LPC_RTC->GPREG0 ); printf( "%lx\n", LPC_RTC->GPREG0 );

View File

@ -29,13 +29,15 @@
#include <stdint.h> #include <stdint.h>
typedef enum { typedef enum
{
RTC_NOT_FOUND, /* No RTC present */ RTC_NOT_FOUND, /* No RTC present */
RTC_INVALID, /* RTC present, but contents invalid */ RTC_INVALID, /* RTC present, but contents invalid */
RTC_OK /* RTC present and working */ RTC_OK /* RTC present and working */
} rtcstate_t; } rtcstate_t;
struct tm { struct tm
{
uint8_t tm_sec; // 0..59 uint8_t tm_sec; // 0..59
uint8_t tm_min; // 0..59 uint8_t tm_min; // 0..59
uint8_t tm_hour; // 0..23 uint8_t tm_hour; // 0..23

View File

@ -1,46 +0,0 @@
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
Copyright (C) 2007-2010 Ingo Korb <ingo@akana.de>
Inspiration and low-level SD/MMC access based on code from MMC2IEC
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License only.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
sdcard.h: Definitions for the SD/MMC access routines
*/
#ifndef SDCARD_H
#define SDCARD_H
#include "diskio.h"
#define SD_TX_BYTE(x) spi_tx_byte(x, SPI_SD);
#define SD_RX_BYTE(x) spi_rx_byte(x, SPI_SD);
#define SD_TX_BLOCK(x,y) spi_tx_block(x,y, SPI_SD);
#define SD_RX_BLOCK(x,y) spi_rx_block(x,y, SPI_SD);
/* These functions are weak-aliased to disk_... */
void sd_init(void);
DSTATUS sd_status(BYTE drv);
DSTATUS sd_initialize(BYTE drv);
DRESULT sd_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count);
DRESULT sd_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count);
DRESULT sd_getinfo(BYTE drv, BYTE page, void *buffer);
void sd_changed(void);
#endif

File diff suppressed because it is too large Load Diff

226
src/smc.c
View File

@ -35,27 +35,39 @@ snes_romprops_t romprops;
uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0}; uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0};
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 = 1; res = 1;
} }
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 );
@ -64,17 +76,25 @@ void smc_id(snes_romprops_t* props) {
props->has_cx4 = 0; props->has_cx4 = 0;
props->fpga_features = 0; props->fpga_features = 0;
props->fpga_conf = NULL; props->fpga_conf = NULL;
for(uint8_t num = 0; num < 6; num++) {
for ( uint8_t num = 0; num < 6; num++ )
{
score = smc_headerscore( hdr_addr[num], header ); score = smc_headerscore( hdr_addr[num], header );
printf( "%d: offset = %lX; score = %d\n", num, hdr_addr[num], score ); // */ printf( "%d: offset = %lX; score = %d\n", num, hdr_addr[num], score ); // */
if(score>=maxscore) {
if ( score >= maxscore )
{
score_idx = num; score_idx = num;
maxscore = score; maxscore = score;
} }
} }
if(score_idx & 1) {
if ( score_idx & 1 )
{
props->offset = 0x200; props->offset = 0x200;
} else { }
else
{
props->offset = 0; props->offset = 0;
} }
@ -82,12 +102,17 @@ void smc_id(snes_romprops_t* props) {
/*dprintf("winner is %d\n", score_idx); */ /*dprintf("winner is %d\n", score_idx); */
file_readblock( header, hdr_addr[score_idx], sizeof( snes_header_t ) ); file_readblock( header, hdr_addr[score_idx], sizeof( snes_header_t ) );
if(header->name[0x13] == 0x00 || header->name[0x13] == 0xff) { if ( header->name[0x13] == 0x00 || header->name[0x13] == 0xff )
if(header->name[0x14] == 0x00) { {
if ( header->name[0x14] == 0x00 )
{
const uint8_t n15 = header->map; const uint8_t n15 = header->map;
if ( n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c if ( n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c
|| n15 == 0xbc || n15 == 0xfc) { || n15 == 0xbc || n15 == 0xfc )
if(header->licensee == 0x33 || header->licensee == 0xff) { {
if ( header->licensee == 0x33 || header->licensee == 0xff )
{
props->mapper_id = 0; props->mapper_id = 0;
/*XXX do this properly */ /*XXX do this properly */
props->ramsize_bytes = 0x8000; props->ramsize_bytes = 0x8000;
@ -100,54 +125,75 @@ void smc_id(snes_romprops_t* props) {
} }
} }
} }
switch(header->map & 0xef) {
switch ( header->map & 0xef )
{
case 0x21: /* HiROM */ case 0x21: /* HiROM */
props->mapper_id = 0; props->mapper_id = 0;
if(header->map == 0x31 && (header->carttype == 0x03 || header->carttype == 0x05)) {
if ( header->map == 0x31 && ( header->carttype == 0x03 || header->carttype == 0x05 ) )
{
props->has_dspx = 1; props->has_dspx = 1;
props->dsp_fw = DSPFW_1B; props->dsp_fw = DSPFW_1B;
props->fpga_features |= FEAT_DSPX; props->fpga_features |= FEAT_DSPX;
} }
break; break;
case 0x20: /* LoROM */ case 0x20: /* LoROM */
props->mapper_id = 1; props->mapper_id = 1;
if (header->map == 0x20 && header->carttype == 0xf3) {
if ( header->map == 0x20 && header->carttype == 0xf3 )
{
props->has_cx4 = 1; props->has_cx4 = 1;
props->dsp_fw = CX4FW; props->dsp_fw = CX4FW;
props->fpga_conf = FPGA_CX4; props->fpga_conf = FPGA_CX4;
props->fpga_features |= FEAT_CX4; props->fpga_features |= FEAT_CX4;
} }
else if ( ( header->map == 0x20 && header->carttype == 0x03 ) || else if ( ( header->map == 0x20 && header->carttype == 0x03 ) ||
(header->map == 0x30 && header->carttype == 0x05 && header->licensee != 0xb2)) { ( header->map == 0x30 && header->carttype == 0x05 && header->licensee != 0xb2 ) )
{
props->has_dspx = 1; props->has_dspx = 1;
props->fpga_features |= FEAT_DSPX; props->fpga_features |= FEAT_DSPX;
/* Pilotwings uses DSP1 instead of DSP1B */ /* Pilotwings uses DSP1 instead of DSP1B */
if(!memcmp(header->name, "PILOTWINGS", 10)) { if ( !memcmp( header->name, "PILOTWINGS", 10 ) )
{
props->dsp_fw = DSPFW_1; props->dsp_fw = DSPFW_1;
} else { }
else
{
props->dsp_fw = DSPFW_1B; props->dsp_fw = DSPFW_1B;
} }
} else if (header->map == 0x20 && header->carttype == 0x05) { }
else if ( header->map == 0x20 && header->carttype == 0x05 )
{
props->has_dspx = 1; props->has_dspx = 1;
props->dsp_fw = DSPFW_2; props->dsp_fw = DSPFW_2;
props->fpga_features |= FEAT_DSPX; props->fpga_features |= FEAT_DSPX;
} else if (header->map == 0x30 && header->carttype == 0x05 && header->licensee == 0xb2) { }
else if ( header->map == 0x30 && header->carttype == 0x05 && header->licensee == 0xb2 )
{
props->has_dspx = 1; props->has_dspx = 1;
props->dsp_fw = DSPFW_3; props->dsp_fw = DSPFW_3;
props->fpga_features |= FEAT_DSPX; props->fpga_features |= FEAT_DSPX;
} else if (header->map == 0x30 && header->carttype == 0x03) { }
else if ( header->map == 0x30 && header->carttype == 0x03 )
{
props->has_dspx = 1; props->has_dspx = 1;
props->dsp_fw = DSPFW_4; props->dsp_fw = DSPFW_4;
props->fpga_features |= FEAT_DSPX; props->fpga_features |= FEAT_DSPX;
} else if (header->map == 0x30 && header->carttype == 0xf6 && header->romsize >= 0xa) { }
else if ( header->map == 0x30 && header->carttype == 0xf6 && header->romsize >= 0xa )
{
props->has_dspx = 1; props->has_dspx = 1;
props->has_st0010 = 1; props->has_st0010 = 1;
props->dsp_fw = DSPFW_ST0010; props->dsp_fw = DSPFW_ST0010;
props->fpga_features |= FEAT_ST0010; props->fpga_features |= FEAT_ST0010;
header->ramsize = 2; header->ramsize = 2;
} }
break; break;
case 0x25: /* ExHiROM */ case 0x25: /* ExHiROM */
@ -155,91 +201,159 @@ void smc_id(snes_romprops_t* props) {
break; break;
case 0x22: /* ExLoROM */ case 0x22: /* ExLoROM */
if(file_handle.fsize > 0x400200) { if ( file_handle.fsize > 0x400200 )
{
props->mapper_id = 6; /* SO96 */ props->mapper_id = 6; /* SO96 */
} else { }
else
{
props->mapper_id = 1; props->mapper_id = 1;
} }
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:
if(file_handle.fsize > 0x800200) { if ( file_handle.fsize > 0x800200 )
{
props->mapper_id = 6; /* SO96 interleaved */ props->mapper_id = 6; /* SO96 interleaved */
} else if(file_handle.fsize > 0x400200) { }
else if ( file_handle.fsize > 0x400200 )
{
props->mapper_id = 1; /* ExLoROM */ props->mapper_id = 1; /* ExLoROM */
} else { }
else
{
props->mapper_id = 1; /* LoROM */ props->mapper_id = 1; /* LoROM */
} }
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 )
{
props->romsize_bytes = 1024; props->romsize_bytes = 1024;
header->romsize = 0; header->romsize = 0;
if(file_handle.fsize >= 1024) {
while(props->romsize_bytes < file_handle.fsize-1) { if ( file_handle.fsize >= 1024 )
{
while ( props->romsize_bytes < file_handle.fsize - 1 )
{
header->romsize++; header->romsize++;
props->romsize_bytes <<= 1; props->romsize_bytes <<= 1;
} }
} }
} }
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); */
if(props->ramsize_bytes > 32768 || props->ramsize_bytes < 2048) { //dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes);
if ( props->ramsize_bytes > 32768 || props->ramsize_bytes < 2048 )
{
props->ramsize_bytes = 0; props->ramsize_bytes = 0;
} }
props->region = ( header->destcode <= 1 || header->destcode >= 13 ) ? 0 : 1; props->region = ( header->destcode <= 1 || header->destcode >= 13 ) ? 0 : 1;
/*dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); */ /*dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); */
} }
uint8_t smc_headerscore(uint32_t addr, snes_header_t* header) { uint8_t smc_headerscore( uint32_t addr, snes_header_t *header )
{
int score = 0; int score = 0;
uint8_t reset_inst; uint8_t reset_inst;
uint16_t header_offset; uint16_t header_offset;
if((addr & 0xfff) == 0x1b0) {
if ( ( addr & 0xfff ) == 0x1b0 )
{
header_offset = 0x200; header_offset = 0x200;
} else { }
else
{
header_offset = 0; header_offset = 0;
} }
if ( ( file_readblock( header, addr, sizeof( snes_header_t ) ) < sizeof( snes_header_t ) ) if ( ( file_readblock( header, addr, sizeof( snes_header_t ) ) < sizeof( snes_header_t ) )
|| file_res) { || file_res )
{
return 0; return 0;
} }
uint8_t mapper = header->map & ~0x10; uint8_t mapper = header->map & ~0x10;
uint16_t resetvector = header->vect_reset; /* not endian safe! */ uint16_t resetvector = header->vect_reset; /* not endian safe! */
uint32_t file_addr = ( ( ( addr - header_offset ) & ~0x7fff ) | ( resetvector & 0x7fff ) ) + header_offset; uint32_t file_addr = ( ( ( addr - header_offset ) & ~0x7fff ) | ( resetvector & 0x7fff ) ) + header_offset;
if(resetvector < 0x8000) return 0;
if ( resetvector < 0x8000 )
{
return 0;
}
score += 2 * isFixed( &header->licensee, sizeof( header->licensee ), 0x33 ); score += 2 * isFixed( &header->licensee, sizeof( header->licensee ), 0x33 );
score += 4 * checkChksum( header->cchk, header->chk ); score += 4 * checkChksum( header->cchk, header->chk );
if(header->carttype < 0x08) score++;
if(header->romsize < 0x10) score++;
if(header->ramsize < 0x08) score++;
if(header->destcode < 0x0e) score++;
if((addr-header_offset) == 0x007fc0 && mapper == 0x20) score += 2; if ( header->carttype < 0x08 )
if((addr-header_offset) == 0x00ffc0 && mapper == 0x21) score += 2; {
if((addr-header_offset) == 0x007fc0 && mapper == 0x22) score += 2; score++;
if((addr-header_offset) == 0x40ffc0 && mapper == 0x25) score += 2; }
if ( header->romsize < 0x10 )
{
score++;
}
if ( header->ramsize < 0x08 )
{
score++;
}
if ( header->destcode < 0x0e )
{
score++;
}
if ( ( addr - header_offset ) == 0x007fc0 && mapper == 0x20 )
{
score += 2;
}
if ( ( addr - header_offset ) == 0x00ffc0 && mapper == 0x21 )
{
score += 2;
}
if ( ( addr - header_offset ) == 0x007fc0 && mapper == 0x22 )
{
score += 2;
}
if ( ( addr - header_offset ) == 0x40ffc0 && mapper == 0x25 )
{
score += 2;
}
file_readblock( &reset_inst, file_addr, 1 ); file_readblock( &reset_inst, file_addr, 1 );
switch(reset_inst) {
switch ( reset_inst )
{
case 0x78: /* sei */ case 0x78: /* sei */
case 0x18: /* clc */ case 0x18: /* clc */
case 0x38: /* sec */ case 0x38: /* sec */
@ -281,8 +395,16 @@ uint8_t smc_headerscore(uint32_t addr, snes_header_t* header) {
break; break;
} }
if(score && addr > 0x400000) score += 4; if ( score && addr > 0x400000 )
if(score < 0) score = 0; {
score += 4;
}
if ( score < 0 )
{
score = 0;
}
return score; return score;
} }

View File

@ -37,7 +37,8 @@
#define FPGA_CX4 ((const uint8_t*)"/sd2snes/fpga_cx4.bit") #define FPGA_CX4 ((const uint8_t*)"/sd2snes/fpga_cx4.bit")
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 */
@ -69,7 +70,8 @@ typedef struct _snes_header {
uint16_t vect_brk8; /* 0xFE */ uint16_t vect_brk8; /* 0xFE */
} 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 */

View File

@ -25,6 +25,7 @@
*/ */
#include <arm/NXP/LPC17xx/LPC17xx.h> #include <arm/NXP/LPC17xx/LPC17xx.h>
#include <string.h>
#include "bits.h" #include "bits.h"
#include "config.h" #include "config.h"
#include "uart.h" #include "uart.h"
@ -46,32 +47,41 @@ extern snes_romprops_t romprops;
volatile int reset_changed; volatile int reset_changed;
volatile int reset_pressed; volatile int reset_pressed;
void prepare_reset() { void prepare_reset()
{
snes_reset( 1 ); snes_reset( 1 );
delay_ms( SNES_RESET_PULSELEN_MS ); delay_ms( SNES_RESET_PULSELEN_MS );
if(romprops.ramsize_bytes && fpga_test() == FPGA_TEST_TOKEN) {
if ( romprops.ramsize_bytes && fpga_test() == FPGA_TEST_TOKEN )
{
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 );
} }
rdyled( 1 ); rdyled( 1 );
readled( 1 ); readled( 1 );
writeled( 1 ); writeled( 1 );
snes_reset( 0 ); snes_reset( 0 );
while ( get_snes_reset() ); while ( get_snes_reset() );
snes_reset( 1 ); snes_reset( 1 );
fpga_dspx_reset( 1 ); fpga_dspx_reset( 1 );
delay_ms( 200 ); delay_ms( 200 );
} }
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 );
} }
void snes_reset_pulse() { void snes_reset_pulse()
{
snes_reset( 1 ); snes_reset( 1 );
delay_ms( SNES_RESET_PULSELEN_MS ); delay_ms( SNES_RESET_PULSELEN_MS );
snes_reset( 0 ); snes_reset( 0 );
@ -82,7 +92,8 @@ void snes_reset_pulse() {
* *
* 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;
} }
@ -91,7 +102,8 @@ 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 );
} }
@ -101,35 +113,55 @@ 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(initloop) { if ( !romprops.ramsize_bytes )
{
return;
}
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(saveram_crc != saveram_crc_old) { if ( crc_valid && sram_valid )
if(samecount) { {
if ( saveram_crc != saveram_crc_old )
{
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) {
printf("SaveRAM CRC: 0x%04lx; saving\n", saveram_crc); if ( diffcount >= 1 && samecount == 5 )
{
printf( "SaveRAM CRC: 0x%04lx; saving %s\n", saveram_crc, file_lfn );
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 );
@ -137,44 +169,66 @@ void snes_main_loop() {
didnotsave = 0; didnotsave = 0;
writeled( 1 ); writeled( 1 );
} }
saveram_crc_old = saveram_crc; saveram_crc_old = saveram_crc;
} }
printf("crc=%lx crc_valid=%d sram_valid=%d diffcount=%ld samecount=%ld, didnotsave=%ld\n", saveram_crc, crc_valid, sram_valid, diffcount, samecount, didnotsave);
printf( "crc=%lx crc_valid=%d sram_valid=%d diffcount=%ld samecount=%ld, didnotsave=%ld\n", saveram_crc, crc_valid,
sram_valid, diffcount, samecount, didnotsave );
} }
/* /*
* SD2SNES menu loop. * SD2SNES menu 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) {
if(!get_snes_reset()) { while ( !cmd )
while(!sram_reliable())printf("hurr\n"); {
cmd = sram_readbyte(SRAM_CMD_ADDR); if ( !get_snes_reset() )
{
while ( !sram_reliable() )
{
printf( "hurr\n" );
} }
if(get_snes_reset()) {
cmd = sram_readbyte( SRAM_CMD_ADDR );
//cmd = SNES_CMD_LOADSPC;
}
if ( get_snes_reset() )
{
cmd = 0; cmd = 0;
} }
sleep_ms( 20 ); sleep_ms( 20 );
cli_entrycheck(); cli_entrycheck();
} }
return cmd; return cmd;
} }
void get_selected_name(uint8_t* fn) { void get_selected_name( uint8_t *fn )
{
uint32_t addr; uint32_t addr;
addr = sram_readlong( SRAM_PARAM_ADDR ); addr = sram_readlong( SRAM_PARAM_ADDR );
printf( "fd addr=%lx\n", addr ); printf( "fd addr=%lx\n", addr );
sram_readblock( fn, addr + 7 + SRAM_MENU_ADDR, 256 ); sram_readblock( fn, addr + 7 + SRAM_MENU_ADDR, 256 );
//memcpy(fn, "dossier sans titre/ff6.sfc", 28);
} }
void snes_bootprint(void* msg) { void snes_bootprint( void *msg )
{
printf( "SNES SAY: %s\n", ( char * )msg );
sram_writeblock( msg, SRAM_CMD_ADDR, 33 ); sram_writeblock( msg, SRAM_CMD_ADDR, 33 );
} }
void snes_menu_errmsg(int err, void* msg) { void snes_menu_errmsg( int err, void *msg )
{
printf( "%d: %s\n", err, ( char * )msg );
sram_writeblock( msg, SRAM_CMD_ADDR + 1, 64 ); sram_writeblock( msg, SRAM_CMD_ADDR + 1, 64 );
sram_writebyte( err, SRAM_CMD_ADDR ); sram_writebyte( err, SRAM_CMD_ADDR );
} }

View File

@ -38,7 +38,7 @@
#define MENU_ERR_NODSP (1) #define MENU_ERR_NODSP (1)
#define MENU_ERR_NOBSX (2) #define MENU_ERR_NOBSX (2)
#define SNES_RESET_PULSELEN_MS (1) #define SNES_RESET_PULSELEN_MS (100)
uint8_t crc_valid; uint8_t crc_valid;

View File

@ -1,330 +1,295 @@
const uint8_t bootrle[] = { const uint8_t bootrle[] = {
0xe2, 0x20, 0xc2, 0x10, 0xa9, 0x00, 0x48, 0xab, 0xE2, 0x20, 0xC2, 0x10, 0xA9, 0x00, 0x48, 0xAB, 0xAD,
0xad, 0x10, 0x42, 0xa2, 0x00, 0x58, 0x8e, 0x16, 0x10, 0x42, 0xA2, 0x00, 0x58, 0x8E, 0x16, 0x21, 0xA9,
0x21, 0xa9, 0x01, 0x8d, 0x15, 0x00, 0xa2, 0x00, 0x01, 0x8D, 0x15, 0x00, 0xA2, 0x00, 0xB0, 0xA9, 0x7F,
0xb0, 0xa9, 0x7f, 0x8e, 0x10, 0x00, 0x8d, 0x0f, 0x8E, 0x10, 0x00, 0x8D, 0x0F, 0x00, 0xA2, 0x00, 0x09,
0x00, 0xa2, 0x00, 0x09, 0x8e, 0x13, 0x00, 0xa9, 0x8E, 0x13, 0x00, 0xA9, 0x18, 0x8D, 0x12, 0x00, 0x20,
0x18, 0x8d, 0x12, 0x00, 0x20, 0xdc, 0x0b, 0xa9, 0xDC, 0x0B, 0xA9, 0x01, 0x8D, 0x16, 0x00, 0x6B, 0xE2,
0x01, 0x8d, 0x16, 0x00, 0x6b, 0xe2, 0x20, 0xad, 0x20, 0xAD, 0x11, 0x42, 0x6B, 0xE2, 0x20, 0xC2, 0x10,
0x11, 0x42, 0x6b, 0xe2, 0x20, 0xc2, 0x10, 0x78, 0x78, 0x9C, 0x00, 0x42, 0x20, 0x2A, 0x01, 0xA9, 0x01,
0x9c, 0x00, 0x42, 0x20, 0x2a, 0x01, 0xa9, 0x01, 0x8D, 0x0D, 0x42, 0x20, 0x84, 0x02, 0x20, 0x93, 0x01,
0x8d, 0x0d, 0x42, 0x20, 0x84, 0x02, 0x20, 0x93, 0x20, 0x8B, 0x01, 0x20, 0x04, 0x0C, 0x20, 0x57, 0x02,
0x01, 0x20, 0x8b, 0x01, 0x20, 0x04, 0x0c, 0x20, 0xA2, 0x41, 0x00, 0xA9, 0x00, 0xCA, 0x9F, 0x00, 0x70,
0x57, 0x02, 0xa2, 0x41, 0x00, 0xa9, 0x00, 0xca, 0x30, 0xD0, 0xF9, 0xA9, 0x7E, 0xA2, 0x1B, 0x00, 0x8D,
0x9f, 0x00, 0x70, 0x30, 0xd0, 0xf9, 0xa9, 0x7e, 0x83, 0x21, 0x8E, 0x81, 0x21, 0xA9, 0x00, 0x8D, 0x15,
0xa2, 0x1b, 0x00, 0x8d, 0x83, 0x21, 0x8e, 0x81, 0x00, 0xA2, 0xBC, 0x00, 0xA9, 0xC0, 0x8E, 0x10, 0x00,
0x21, 0xa9, 0x00, 0x8d, 0x15, 0x00, 0xa2, 0xbc, 0x8D, 0x0F, 0x00, 0xA2, 0x6F, 0x00, 0x8E, 0x13, 0x00,
0x00, 0xa9, 0xc0, 0x8e, 0x10, 0x00, 0x8d, 0x0f, 0xA9, 0x80, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0xA9,
0x00, 0xa2, 0x6f, 0x00, 0x8e, 0x13, 0x00, 0xa9, 0x7E, 0xA2, 0x8B, 0x00, 0x8D, 0x83, 0x21, 0x8E, 0x81,
0x80, 0x8d, 0x12, 0x00, 0x20, 0xdc, 0x0b, 0xa9, 0x21, 0xA9, 0x00, 0x8D, 0x15, 0x00, 0xA2, 0x8C, 0x0B,
0x7e, 0xa2, 0x8b, 0x00, 0x8d, 0x83, 0x21, 0x8e, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D, 0x0F, 0x00, 0xA2,
0x81, 0x21, 0xa9, 0x00, 0x8d, 0x15, 0x00, 0xa2, 0x4F, 0x00, 0x8E, 0x13, 0x00, 0xA9, 0x80, 0x8D, 0x12,
0x8c, 0x0b, 0xa9, 0xc0, 0x8e, 0x10, 0x00, 0x8d, 0x00, 0x20, 0xDC, 0x0B, 0x22, 0x1B, 0x00, 0x7E, 0xC2,
0x0f, 0x00, 0xa2, 0x4f, 0x00, 0x8e, 0x13, 0x00, 0x10, 0xE2, 0x20, 0xA9, 0x00, 0x8F, 0x00, 0x00, 0x7E,
0xa9, 0x80, 0x8d, 0x12, 0x00, 0x20, 0xdc, 0x0b, 0xA9, 0x0D, 0x8F, 0x02, 0x00, 0x7E, 0xA9, 0x30, 0x8F,
0x22, 0x1b, 0x00, 0x7e, 0xc2, 0x10, 0xe2, 0x20, 0x06, 0x00, 0x7E, 0xC2, 0x20, 0xA9, 0x00, 0x70, 0x8F,
0xa9, 0x00, 0x8f, 0x00, 0x00, 0x7e, 0xa9, 0x0d, 0x04, 0x00, 0x7E, 0xE2, 0x20, 0xA9, 0x00, 0x8F, 0x07,
0x8f, 0x02, 0x00, 0x7e, 0xa9, 0x30, 0x8f, 0x06, 0x00, 0x7E, 0x20, 0x8B, 0x00, 0xC2, 0x20, 0xA9, 0x00,
0x00, 0x7e, 0xc2, 0x20, 0xa9, 0x00, 0x70, 0x8f, 0x58, 0x8D, 0x16, 0x21, 0xE2, 0x20, 0xA9, 0x01, 0x8D,
0x04, 0x00, 0x7e, 0xe2, 0x20, 0xa9, 0x00, 0x8f, 0x00, 0x43, 0xA9, 0x18, 0x8D, 0x01, 0x43, 0xA9, 0x7F,
0x07, 0x00, 0x7e, 0x20, 0x8b, 0x00, 0xc2, 0x20, 0x8D, 0x04, 0x43, 0xA2, 0x00, 0xB0, 0x8E, 0x02, 0x43,
0xa9, 0x00, 0x58, 0x8d, 0x16, 0x21, 0xe2, 0x20, 0xA2, 0x00, 0x09, 0x8E, 0x05, 0x43, 0xAF, 0x12, 0x42,
0xa9, 0x01, 0x8d, 0x00, 0x43, 0xa9, 0x18, 0x8d, 0x00, 0x29, 0x80, 0xD0, 0xF8, 0xAF, 0x12, 0x42, 0x00,
0x01, 0x43, 0xa9, 0x7f, 0x8d, 0x04, 0x43, 0xa2, 0x29, 0x80, 0xF0, 0xF8, 0xA9, 0x01, 0x8D, 0x0B, 0x42,
0x00, 0xb0, 0x8e, 0x02, 0x43, 0xa2, 0x00, 0x09, 0x80, 0x9A, 0x58, 0x9C, 0x00, 0x42, 0x5C, 0x19, 0x00,
0x8e, 0x05, 0x43, 0xaf, 0x12, 0x42, 0x00, 0x29, 0x7E, 0x9C, 0x0B, 0x42, 0x9C, 0x0C, 0x42, 0x9C, 0x10,
0x80, 0xd0, 0xf8, 0xaf, 0x12, 0x42, 0x00, 0x29, 0x43, 0x9C, 0x11, 0x43, 0x9C, 0x12, 0x43, 0x9C, 0x13,
0x80, 0xf0, 0xf8, 0xa9, 0x01, 0x8d, 0x0b, 0x42, 0x43, 0x9C, 0x14, 0x43, 0x9C, 0x20, 0x43, 0x9C, 0x21,
0x80, 0x9a, 0x58, 0x9c, 0x00, 0x42, 0x5c, 0x19, 0x43, 0x9C, 0x22, 0x43, 0x9C, 0x23, 0x43, 0x9C, 0x24,
0x00, 0x7e, 0x9c, 0x0b, 0x42, 0x9c, 0x0c, 0x42, 0x43, 0x9C, 0x30, 0x43, 0x9C, 0x31, 0x43, 0x9C, 0x32,
0x9c, 0x10, 0x43, 0x9c, 0x11, 0x43, 0x9c, 0x12, 0x43, 0x9C, 0x33, 0x43, 0x9C, 0x34, 0x43, 0x9C, 0x40,
0x43, 0x9c, 0x13, 0x43, 0x9c, 0x14, 0x43, 0x9c, 0x43, 0x9C, 0x41, 0x43, 0x9C, 0x42, 0x43, 0x9C, 0x43,
0x20, 0x43, 0x9c, 0x21, 0x43, 0x9c, 0x22, 0x43, 0x43, 0x9C, 0x44, 0x43, 0x9C, 0x50, 0x43, 0x9C, 0x51,
0x9c, 0x23, 0x43, 0x9c, 0x24, 0x43, 0x9c, 0x30, 0x43, 0x9C, 0x52, 0x43, 0x9C, 0x53, 0x43, 0x9C, 0x54,
0x43, 0x9c, 0x31, 0x43, 0x9c, 0x32, 0x43, 0x9c, 0x43, 0x60, 0xAD, 0x12, 0x42, 0x29, 0x80, 0xD0, 0xF9,
0x33, 0x43, 0x9c, 0x34, 0x43, 0x9c, 0x40, 0x43, 0xAD, 0x12, 0x42, 0x29, 0x80, 0xF0, 0xF9, 0x60, 0xE2,
0x9c, 0x41, 0x43, 0x9c, 0x42, 0x43, 0x9c, 0x43, 0x20, 0xC2, 0x10, 0x9C, 0x30, 0x21, 0x60, 0xE2, 0x20,
0x43, 0x9c, 0x44, 0x43, 0x9c, 0x50, 0x43, 0x9c, 0xC2, 0x10, 0x9C, 0x00, 0x42, 0x9C, 0x0B, 0x42, 0x9C,
0x51, 0x43, 0x9c, 0x52, 0x43, 0x9c, 0x53, 0x43, 0x0C, 0x42, 0xA2, 0x00, 0xB0, 0x8E, 0x81, 0x21, 0xA9,
0x9c, 0x54, 0x43, 0x60, 0xad, 0x12, 0x42, 0x29, 0x01, 0x8D, 0x83, 0x21, 0xA9, 0x08, 0x8D, 0x15, 0x00,
0x80, 0xd0, 0xf9, 0xad, 0x12, 0x42, 0x29, 0x80, 0xA2, 0x59, 0xFF, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D,
0xf0, 0xf9, 0x60, 0xe2, 0x20, 0xc2, 0x10, 0x9c, 0x0F, 0x00, 0xA2, 0x40, 0x07, 0x8E, 0x13, 0x00, 0xA9,
0x30, 0x21, 0x60, 0xe2, 0x20, 0xc2, 0x10, 0x9c, 0x80, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0xA2, 0x00,
0x00, 0x42, 0x9c, 0x0b, 0x42, 0x9c, 0x0c, 0x42, 0x00, 0x8E, 0x16, 0x21, 0xA9, 0x01, 0x8D, 0x15, 0x00,
0xa2, 0x00, 0xb0, 0x8e, 0x81, 0x21, 0xa9, 0x01, 0xA2, 0x7C, 0x03, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D,
0x8d, 0x83, 0x21, 0xa9, 0x08, 0x8d, 0x15, 0x00, 0x0F, 0x00, 0xA2, 0x00, 0x08, 0x8E, 0x13, 0x00, 0xA9,
0xa2, 0x59, 0xff, 0xa9, 0xc0, 0x8e, 0x10, 0x00, 0x18, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0xA2, 0x00,
0x8d, 0x0f, 0x00, 0xa2, 0x40, 0x07, 0x8e, 0x13, 0x58, 0x8E, 0x16, 0x21, 0xA9, 0x09, 0x8D, 0x15, 0x00,
0x00, 0xa9, 0x80, 0x8d, 0x12, 0x00, 0x20, 0xdc, 0xA2, 0x59, 0xFF, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D,
0x0b, 0xa2, 0x00, 0x00, 0x8e, 0x16, 0x21, 0xa9, 0x0F, 0x00, 0xA2, 0x40, 0x07, 0x8E, 0x13, 0x00, 0xA9,
0x01, 0x8d, 0x15, 0x00, 0xa2, 0x7c, 0x03, 0xa9, 0x18, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0xA2, 0x00,
0xc0, 0x8e, 0x10, 0x00, 0x8d, 0x0f, 0x00, 0xa2, 0x00, 0x8E, 0x02, 0x21, 0xA9, 0x08, 0x8D, 0x15, 0x00,
0x00, 0x08, 0x8e, 0x13, 0x00, 0xa9, 0x18, 0x8d, 0xA2, 0x59, 0xFF, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D,
0x12, 0x00, 0x20, 0xdc, 0x0b, 0xa2, 0x00, 0x58, 0x0F, 0x00, 0xA2, 0x20, 0x02, 0x8E, 0x13, 0x00, 0xA9,
0x8e, 0x16, 0x21, 0xa9, 0x09, 0x8d, 0x15, 0x00, 0x04, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0x9C, 0x21,
0xa2, 0x59, 0xff, 0xa9, 0xc0, 0x8e, 0x10, 0x00, 0x21, 0xA9, 0x00, 0x8D, 0x15, 0x00, 0xA2, 0x7C, 0x0B,
0x8d, 0x0f, 0x00, 0xa2, 0x40, 0x07, 0x8e, 0x13, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D, 0x0F, 0x00, 0xA2,
0x00, 0xa9, 0x18, 0x8d, 0x12, 0x00, 0x20, 0xdc, 0x10, 0x00, 0x8E, 0x13, 0x00, 0xA9, 0x22, 0x8D, 0x12,
0x0b, 0xa2, 0x00, 0x00, 0x8e, 0x02, 0x21, 0xa9, 0x00, 0x20, 0xDC, 0x0B, 0x60, 0xE2, 0x20, 0xC2, 0x10,
0x08, 0x8d, 0x15, 0x00, 0xa2, 0x59, 0xff, 0xa9, 0xA9, 0x00, 0x8D, 0x05, 0x21, 0xA9, 0x58, 0x09, 0x02,
0xc0, 0x8e, 0x10, 0x00, 0x8d, 0x0f, 0x00, 0xa2, 0x8D, 0x07, 0x21, 0xA9, 0x40, 0x8D, 0x0B, 0x21, 0xA9,
0x20, 0x02, 0x8e, 0x13, 0x00, 0xa9, 0x04, 0x8d, 0x01, 0x8D, 0x2C, 0x21, 0xA9, 0x01, 0x8D, 0x2D, 0x21,
0x12, 0x00, 0x20, 0xdc, 0x0b, 0x9c, 0x21, 0x21, 0xA9, 0x00, 0x8D, 0x30, 0x21, 0x9C, 0x21, 0x21, 0xA9,
0xa9, 0x00, 0x8d, 0x15, 0x00, 0xa2, 0x7c, 0x0b, 0x0F, 0x8D, 0x00, 0x21, 0x60, 0xE2, 0x20, 0xC2, 0x10,
0xa9, 0xc0, 0x8e, 0x10, 0x00, 0x8d, 0x0f, 0x00, 0x9C, 0x00, 0x42, 0xA9, 0xFF, 0x8D, 0x01, 0x42, 0x9C,
0xa2, 0x10, 0x00, 0x8e, 0x13, 0x00, 0xa9, 0x22, 0x02, 0x42, 0x9C, 0x03, 0x42, 0x9C, 0x04, 0x42, 0x9C,
0x8d, 0x12, 0x00, 0x20, 0xdc, 0x0b, 0x60, 0xe2, 0x05, 0x42, 0x9C, 0x06, 0x42, 0x9C, 0x07, 0x42, 0x9C,
0x20, 0xc2, 0x10, 0xa9, 0x00, 0x8d, 0x05, 0x21, 0x08, 0x42, 0x9C, 0x09, 0x42, 0x9C, 0x0A, 0x42, 0x9C,
0xa9, 0x58, 0x09, 0x02, 0x8d, 0x07, 0x21, 0xa9, 0x0B, 0x42, 0x9C, 0x0C, 0x42, 0xA9, 0x00, 0x8D, 0x0D,
0x40, 0x8d, 0x0b, 0x21, 0xa9, 0x01, 0x8d, 0x2c, 0x42, 0xA9, 0x8F, 0x8D, 0x00, 0x21, 0xA9, 0x03, 0x8D,
0x21, 0xa9, 0x01, 0x8d, 0x2d, 0x21, 0xa9, 0x00, 0x01, 0x21, 0x9C, 0x02, 0x21, 0x9C, 0x03, 0x21, 0x9C,
0x8d, 0x30, 0x21, 0x9c, 0x21, 0x21, 0xa9, 0x0f, 0x05, 0x21, 0x9C, 0x06, 0x21, 0x9C, 0x07, 0x21, 0x9C,
0x8d, 0x00, 0x21, 0x60, 0xe2, 0x20, 0xc2, 0x10, 0x08, 0x21, 0x9C, 0x09, 0x21, 0x9C, 0x0A, 0x21, 0x9C,
0x9c, 0x00, 0x42, 0xa9, 0xff, 0x8d, 0x01, 0x42, 0x0B, 0x21, 0x9C, 0x0C, 0x21, 0x9C, 0x0D, 0x21, 0x9C,
0x9c, 0x02, 0x42, 0x9c, 0x03, 0x42, 0x9c, 0x04, 0x0D, 0x21, 0x9C, 0x0E, 0x21, 0x9C, 0x0E, 0x21, 0x9C,
0x42, 0x9c, 0x05, 0x42, 0x9c, 0x06, 0x42, 0x9c, 0x0F, 0x21, 0x9C, 0x0F, 0x21, 0xA9, 0x05, 0x8D, 0x10,
0x07, 0x42, 0x9c, 0x08, 0x42, 0x9c, 0x09, 0x42, 0x21, 0x9C, 0x10, 0x21, 0x9C, 0x11, 0x21, 0x9C, 0x11,
0x9c, 0x0a, 0x42, 0x9c, 0x0b, 0x42, 0x9c, 0x0c, 0x21, 0x9C, 0x12, 0x21, 0x9C, 0x12, 0x21, 0x9C, 0x13,
0x42, 0xa9, 0x00, 0x8d, 0x0d, 0x42, 0xa9, 0x8f, 0x21, 0x9C, 0x13, 0x21, 0x9C, 0x14, 0x21, 0x9C, 0x14,
0x8d, 0x00, 0x21, 0xa9, 0x03, 0x8d, 0x01, 0x21, 0x21, 0xA9, 0x80, 0x8D, 0x15, 0x21, 0x9C, 0x16, 0x21,
0x9c, 0x02, 0x21, 0x9c, 0x03, 0x21, 0x9c, 0x05, 0x9C, 0x17, 0x21, 0x9C, 0x1A, 0x21, 0x9C, 0x1B, 0x21,
0x21, 0x9c, 0x06, 0x21, 0x9c, 0x07, 0x21, 0x9c, 0xA9, 0x01, 0x8D, 0x1B, 0x21, 0x9C, 0x1C, 0x21, 0x9C,
0x08, 0x21, 0x9c, 0x09, 0x21, 0x9c, 0x0a, 0x21, 0x1C, 0x21, 0x9C, 0x1D, 0x21, 0x9C, 0x1D, 0x21, 0x9C,
0x9c, 0x0b, 0x21, 0x9c, 0x0c, 0x21, 0x9c, 0x0d, 0x1E, 0x21, 0x8D, 0x1E, 0x21, 0x9C, 0x1F, 0x21, 0x9C,
0x21, 0x9c, 0x0d, 0x21, 0x9c, 0x0e, 0x21, 0x9c, 0x1F, 0x21, 0x9C, 0x20, 0x21, 0x9C, 0x20, 0x21, 0x9C,
0x0e, 0x21, 0x9c, 0x0f, 0x21, 0x9c, 0x0f, 0x21, 0x21, 0x21, 0x9C, 0x23, 0x21, 0x9C, 0x24, 0x21, 0x9C,
0xa9, 0x05, 0x8d, 0x10, 0x21, 0x9c, 0x10, 0x21, 0x25, 0x21, 0x9C, 0x26, 0x21, 0x9C, 0x27, 0x21, 0x9C,
0x9c, 0x11, 0x21, 0x9c, 0x11, 0x21, 0x9c, 0x12, 0x28, 0x21, 0x9C, 0x29, 0x21, 0x9C, 0x2A, 0x21, 0x9C,
0x21, 0x9c, 0x12, 0x21, 0x9c, 0x13, 0x21, 0x9c, 0x2B, 0x21, 0x9C, 0x2C, 0x21, 0x9C, 0x2D, 0x21, 0x9C,
0x13, 0x21, 0x9c, 0x14, 0x21, 0x9c, 0x14, 0x21, 0x2E, 0x21, 0xA9, 0x30, 0x8D, 0x30, 0x21, 0x9C, 0x31,
0xa9, 0x80, 0x8d, 0x15, 0x21, 0x9c, 0x16, 0x21, 0x21, 0xA9, 0xE0, 0x8D, 0x32, 0x21, 0x9C, 0x33, 0x21,
0x9c, 0x17, 0x21, 0x9c, 0x1a, 0x21, 0x9c, 0x1b, 0x60, 0x77, 0x00, 0x11, 0x02, 0x30, 0x30, 0x48, 0x30,
0x21, 0xa9, 0x01, 0x8d, 0x1b, 0x21, 0x9c, 0x1c, 0x48, 0x30, 0x48, 0x20, 0x58, 0x00, 0x30, 0x30, 0x48,
0x21, 0x9c, 0x1c, 0x21, 0x9c, 0x1d, 0x21, 0x9c, 0x00, 0x30, 0x00, 0x6C, 0x6C, 0x92, 0x24, 0x5A, 0x00,
0x1d, 0x21, 0x9c, 0x1e, 0x21, 0x8d, 0x1e, 0x21, 0x36, 0x5B, 0x00, 0x09, 0x6C, 0x6C, 0x92, 0xFE, 0x01,
0x9c, 0x1f, 0x21, 0x9c, 0x1f, 0x21, 0x9c, 0x20, 0x6C, 0x92, 0xFE, 0x01, 0x6C, 0x92, 0x00, 0x6C, 0x00,
0x21, 0x9c, 0x20, 0x21, 0x9c, 0x21, 0x21, 0x9c, 0x00, 0x10, 0x6C, 0x7C, 0xC6, 0xC6, 0x39, 0xF0, 0x0E,
0x23, 0x21, 0x9c, 0x24, 0x21, 0x9c, 0x25, 0x21, 0x1E, 0xE1, 0xC6, 0x39, 0x7C, 0xC6, 0x10, 0x6C, 0x42,
0x9c, 0x26, 0x21, 0x9c, 0x27, 0x21, 0x9c, 0x28, 0xA5, 0xA4, 0x5A, 0x48, 0xB4, 0x10, 0x6C, 0x24, 0x5A,
0x21, 0x9c, 0x29, 0x21, 0x9c, 0x2a, 0x21, 0x9c, 0x4A, 0xB5, 0x84, 0x4A, 0x00, 0x84, 0x70, 0xC8, 0xC0,
0x2b, 0x21, 0x9c, 0x2c, 0x21, 0x9c, 0x2d, 0x21, 0x34, 0xC4, 0x2E, 0x6E, 0xDB, 0xC4, 0x2A, 0xC4, 0x3A,
0x9c, 0x2e, 0x21, 0xa9, 0x30, 0x8d, 0x30, 0x21, 0x7C, 0xC6, 0x00, 0x7C, 0x00, 0x18, 0x18, 0x24, 0x10,
0x9c, 0x31, 0x21, 0xa9, 0xe0, 0x8d, 0x32, 0x21, 0x28, 0x00, 0x10, 0x5B, 0x00, 0x08, 0x18, 0x24, 0x30,
0x9c, 0x33, 0x21, 0x60, 0x77, 0x00, 0x11, 0x02, 0x68, 0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x30, 0x68,
0x30, 0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x20, 0x18, 0x24, 0x00, 0x18, 0x30, 0x48, 0x18, 0x2C, 0x18,
0x58, 0x00, 0x30, 0x30, 0x48, 0x00, 0x30, 0x00, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x2C, 0x30, 0x48,
0x6c, 0x6c, 0x92, 0x24, 0x5a, 0x00, 0x36, 0x5b, 0x00, 0x30, 0x00, 0x6C, 0x6C, 0x92, 0x38, 0x44, 0x7C,
0x00, 0x09, 0x6c, 0x6c, 0x92, 0xfe, 0x01, 0x6c, 0x82, 0x38, 0x44, 0x6C, 0x92, 0x00, 0x6C, 0x00, 0x00,
0x92, 0xfe, 0x01, 0x6c, 0x92, 0x00, 0x6c, 0x00, 0x00, 0x18, 0x18, 0x24, 0x18, 0x66, 0x7E, 0x81, 0x18,
0x00, 0x10, 0x6c, 0x7c, 0xc6, 0xc6, 0x39, 0xf0, 0x66, 0x18, 0x24, 0x00, 0x18, 0x5B, 0x00, 0x0B, 0x18,
0x0e, 0x1e, 0xe1, 0xc6, 0x39, 0x7c, 0xc6, 0x10, 0x18, 0x24, 0x18, 0x24, 0x10, 0x28, 0x5B, 0x00, 0x05,
0x6c, 0x42, 0xa5, 0xa4, 0x5a, 0x48, 0xb4, 0x10, 0x7E, 0x7E, 0x81, 0x00, 0x7E, 0x5B, 0x00, 0x0F, 0x18,
0x6c, 0x24, 0x5a, 0x4a, 0xb5, 0x84, 0x4a, 0x00, 0x18, 0x24, 0x18, 0x24, 0x00, 0x18, 0x03, 0x04, 0x06,
0x84, 0x70, 0xc8, 0xc0, 0x34, 0xc4, 0x2e, 0x6e, 0x09, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x90,
0xdb, 0xc4, 0x2a, 0xc4, 0x3a, 0x7c, 0xc6, 0x00, 0xC0, 0x20, 0x00, 0xC0, 0x7C, 0xC6, 0xE6, 0x39, 0xC6,
0x7c, 0x00, 0x18, 0x18, 0x24, 0x10, 0x28, 0x00, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xCE, 0x39, 0x7C, 0xC6,
0x10, 0x5b, 0x00, 0x08, 0x18, 0x24, 0x30, 0x68, 0x00, 0x7C, 0x18, 0x34, 0x18, 0x24, 0x18, 0x24, 0x18,
0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x30, 0x68, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x00, 0x18,
0x18, 0x24, 0x00, 0x18, 0x30, 0x48, 0x18, 0x2c, 0xFC, 0x06, 0x06, 0xF9, 0x06, 0x79, 0x7C, 0x86, 0xC0,
0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x2c, 0xBC, 0xC0, 0x3E, 0xFE, 0x01, 0x00, 0xFE, 0xFC, 0x06,
0x30, 0x48, 0x00, 0x30, 0x00, 0x6c, 0x6c, 0x92, 0x06, 0xF9, 0x06, 0x39, 0x3C, 0x46, 0x06, 0x39, 0x06,
0x38, 0x44, 0x7c, 0x82, 0x38, 0x44, 0x6c, 0x92, 0xF9, 0xFC, 0x06, 0x00, 0xFC, 0xC6, 0x29, 0xC6, 0x29,
0x00, 0x6c, 0x00, 0x00, 0x00, 0x18, 0x18, 0x24, 0xC6, 0x39, 0x7E, 0xC1, 0x06, 0x79, 0x06, 0x09, 0x06,
0x18, 0x66, 0x7e, 0x81, 0x18, 0x66, 0x18, 0x24, 0x09, 0x00, 0x06, 0xFE, 0x01, 0xC0, 0x3E, 0xC0, 0x3C,
0x00, 0x18, 0x5b, 0x00, 0x0b, 0x18, 0x18, 0x24, 0xFC, 0x06, 0x06, 0xF9, 0x06, 0xF9, 0xFC, 0x06, 0x00,
0x18, 0x24, 0x10, 0x28, 0x5b, 0x00, 0x05, 0x7e, 0xF8, 0x7C, 0xC2, 0xC0, 0x3C, 0xC0, 0x3C, 0xFC, 0x06,
0x7e, 0x81, 0x00, 0x7e, 0x5b, 0x00, 0x0f, 0x18, 0xC6, 0x39, 0xC6, 0x39, 0x7C, 0xC6, 0x00, 0x7C, 0xFC,
0x18, 0x24, 0x18, 0x24, 0x00, 0x18, 0x03, 0x04, 0x06, 0x06, 0xF9, 0x06, 0x09, 0x06, 0x09, 0x06, 0x09,
0x06, 0x09, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x06, 0x09, 0x06, 0x09, 0x00, 0x06, 0x7C, 0xC6, 0xC6,
0x60, 0x90, 0xc0, 0x20, 0x00, 0xc0, 0x7c, 0xc6, 0x39, 0xC6, 0x39, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, 0x39,
0xe6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, 0x7C, 0xC6, 0x00, 0x7C, 0x7C, 0xC6, 0xC6, 0x39, 0xC6,
0xce, 0x39, 0x7c, 0xc6, 0x00, 0x7c, 0x18, 0x34, 0x39, 0x7E, 0xC1, 0x06, 0x79, 0x06, 0x79, 0x7C, 0x86,
0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x30, 0x30, 0x48, 0x00,
0x18, 0x24, 0x18, 0x24, 0x00, 0x18, 0xfc, 0x06, 0x30, 0x00, 0x30, 0x30, 0x48, 0x00, 0x30, 0x5B, 0x00,
0x06, 0xf9, 0x06, 0x79, 0x7c, 0x86, 0xc0, 0xbc, 0x05, 0x30, 0x30, 0x48, 0x00, 0x30, 0x00, 0x30, 0x30,
0xc0, 0x3e, 0xfe, 0x01, 0x00, 0xfe, 0xfc, 0x06, 0x48, 0x20, 0x50, 0x00, 0x20, 0x00, 0x18, 0x18, 0x24,
0x06, 0xf9, 0x06, 0x39, 0x3c, 0x46, 0x06, 0x39, 0x30, 0x48, 0x60, 0x90, 0x30, 0x48, 0x18, 0x24, 0x00,
0x06, 0xf9, 0xfc, 0x06, 0x00, 0xfc, 0xc6, 0x29, 0x18, 0x5B, 0x00, 0x05, 0x3C, 0x3C, 0x42, 0x00, 0x3C,
0xc6, 0x29, 0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79, 0x00, 0x3C, 0x3C, 0x42, 0x00, 0x3C, 0x00, 0x00, 0x00,
0x06, 0x09, 0x06, 0x09, 0x00, 0x06, 0xfe, 0x01, 0x30, 0x30, 0x48, 0x18, 0x24, 0x0C, 0x12, 0x18, 0x24,
0xc0, 0x3e, 0xc0, 0x3c, 0xfc, 0x06, 0x06, 0xf9, 0x30, 0x48, 0x00, 0x30, 0x00, 0x00, 0xF8, 0x0C, 0x0C,
0x06, 0xf9, 0xfc, 0x06, 0x00, 0xf8, 0x7c, 0xc2, 0xF2, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x00, 0x30,
0xc0, 0x3c, 0xc0, 0x3c, 0xfc, 0x06, 0xc6, 0x39, 0x30, 0x48, 0x00, 0x30, 0x7C, 0xC6, 0xC6, 0x39, 0xC6,
0xc6, 0x39, 0x7c, 0xc6, 0x00, 0x7c, 0xfc, 0x06, 0x39, 0xDE, 0x21, 0xDE, 0x21, 0xC0, 0x3E, 0x7E, 0xC1,
0x06, 0xf9, 0x06, 0x09, 0x06, 0x09, 0x06, 0x09, 0x00, 0x7E, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, 0x39, 0xDE,
0x06, 0x09, 0x06, 0x09, 0x00, 0x06, 0x7c, 0xc6, 0x21, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29, 0x00, 0xC6,
0xc6, 0x39, 0xc6, 0x39, 0x7c, 0xc6, 0xc6, 0x39, 0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x39, 0xDC, 0x26, 0xC6,
0xc6, 0x39, 0x7c, 0xc6, 0x00, 0x7c, 0x7c, 0xc6, 0x39, 0xC6, 0x39, 0xFC, 0x06, 0x00, 0xFC, 0x7E, 0xC1,
0xc6, 0x39, 0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79, 0xC0, 0x3E, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0,
0x06, 0x79, 0x7c, 0x86, 0x00, 0x7c, 0x00, 0x00, 0x3E, 0x7E, 0xC1, 0x00, 0x7E, 0xFC, 0x02, 0xC6, 0x3B,
0x00, 0x30, 0x30, 0x48, 0x00, 0x30, 0x00, 0x30, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x3B, 0xFC,
0x30, 0x48, 0x00, 0x30, 0x5b, 0x00, 0x05, 0x30, 0x02, 0x00, 0xFC, 0xFE, 0x01, 0xC0, 0x3E, 0xC0, 0x38,
0x30, 0x48, 0x00, 0x30, 0x00, 0x30, 0x30, 0x48, 0xF8, 0x04, 0xC0, 0x38, 0xC0, 0x3E, 0xFE, 0x01, 0x00,
0x20, 0x50, 0x00, 0x20, 0x00, 0x18, 0x18, 0x24, 0xFE, 0xFE, 0x01, 0xC0, 0x3E, 0xC0, 0x38, 0xF8, 0x04,
0x30, 0x48, 0x60, 0x90, 0x30, 0x48, 0x18, 0x24, 0xC0, 0x38, 0xC0, 0x20, 0xC0, 0x20, 0x00, 0xC0, 0x7E,
0x00, 0x18, 0x5b, 0x00, 0x05, 0x3c, 0x3c, 0x42, 0xC1, 0xC0, 0x3E, 0xC0, 0x2E, 0xCE, 0x33, 0xC6, 0x29,
0x00, 0x3c, 0x00, 0x3c, 0x3c, 0x42, 0x00, 0x3c, 0xC6, 0x39, 0x7C, 0xC6, 0x00, 0x7C, 0xC6, 0x29, 0xC6,
0x00, 0x00, 0x00, 0x30, 0x30, 0x48, 0x18, 0x24, 0x29, 0xC6, 0x39, 0xFE, 0x01, 0xC6, 0x39, 0xC6, 0x29,
0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x00, 0x30, 0xC6, 0x29, 0x00, 0xC6, 0x18, 0x24, 0x18, 0x24, 0x18,
0x00, 0x00, 0xf8, 0x0c, 0x0c, 0xf2, 0x0c, 0x12, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24,
0x18, 0x24, 0x30, 0x48, 0x00, 0x30, 0x30, 0x48, 0x00, 0x18, 0x0C, 0x12, 0x0C, 0x12, 0x0C, 0x12, 0x0C,
0x00, 0x30, 0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x39, 0x12, 0x0C, 0x12, 0x0C, 0xF6, 0xF8, 0x06, 0x00, 0xFC,
0xde, 0x21, 0xde, 0x21, 0xc0, 0x3e, 0x7e, 0xc1, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x38, 0xFC, 0x06, 0xC6,
0x00, 0x7e, 0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x39, 0x39, 0xC6, 0x29, 0xC6, 0x29, 0x00, 0xC7, 0xC0, 0x20,
0xde, 0x21, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0,
0x00, 0xc6, 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x39, 0x3C, 0xFC, 0x02, 0x00, 0xFC, 0xEC, 0x16, 0xD6, 0x29,
0xdc, 0x26, 0xc6, 0x39, 0xc6, 0x39, 0xfc, 0x06, 0xD6, 0x29, 0xD6, 0x29, 0xC6, 0x39, 0xC6, 0x29, 0xC6,
0x00, 0xfc, 0x7e, 0xc1, 0xc0, 0x3e, 0xc0, 0x20, 0x29, 0x00, 0xC7, 0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x29,
0xc0, 0x20, 0xc0, 0x20, 0xc0, 0x3e, 0x7e, 0xc1, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0x00,
0x00, 0x7e, 0xfc, 0x02, 0xc6, 0x3b, 0xc6, 0x29, 0xC6, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29,
0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x3b, 0xfc, 0x02, 0xC6, 0x29, 0xC6, 0x39, 0x7C, 0xC6, 0x00, 0x7C, 0xFC,
0x00, 0xfc, 0xfe, 0x01, 0xc0, 0x3e, 0xc0, 0x38, 0x06, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x39, 0xFC, 0x06,
0xf8, 0x04, 0xc0, 0x38, 0xc0, 0x3e, 0xfe, 0x01, 0xC0, 0x3C, 0xC0, 0x20, 0x00, 0xC0, 0x7C, 0x82, 0xC6,
0x00, 0xfe, 0xfe, 0x01, 0xc0, 0x3e, 0xc0, 0x38, 0xBB, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xCE, 0x31,
0xf8, 0x04, 0xc0, 0x38, 0xc0, 0x20, 0xc0, 0x20, 0x7E, 0xC1, 0x00, 0x7E, 0xFC, 0x06, 0xC6, 0x39, 0xC6,
0x00, 0xc0, 0x7e, 0xc1, 0xc0, 0x3e, 0xc0, 0x2e, 0x39, 0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29,
0xce, 0x33, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6, 0x00, 0xC6, 0x7E, 0xC1, 0xC0, 0x3E, 0xC0, 0x3C, 0x7C,
0x00, 0x7c, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, 0xC6, 0x06, 0x79, 0x06, 0xF9, 0xFC, 0x06, 0x00, 0xFC,
0xfe, 0x01, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0xFE, 0x01, 0x18, 0xE6, 0x18, 0x24, 0x18, 0x24, 0x18,
0x00, 0xc6, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x24, 0x18, 0x24, 0x18, 0x24, 0x00, 0x18, 0xC6, 0x29,
0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xC6,
0x00, 0x18, 0x0c, 0x12, 0x0c, 0x12, 0x0c, 0x12, 0x39, 0x7C, 0xC6, 0x00, 0x7C, 0xC6, 0x29, 0xC6, 0x29,
0x0c, 0x12, 0x0c, 0x12, 0x0c, 0xf6, 0xf8, 0x06, 0xC6, 0x29, 0xC6, 0x29, 0x66, 0x99, 0x36, 0x49, 0x1E,
0x00, 0xfc, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x38, 0x21, 0x00, 0x1F, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x39,
0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0xD6, 0x29, 0xD6, 0x29, 0xD6, 0x29, 0x6E, 0xD1, 0x00,
0x00, 0xc7, 0xc0, 0x20, 0xc0, 0x20, 0xc0, 0x20, 0x6E, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x39, 0x7C, 0xC6,
0xc0, 0x20, 0xc0, 0x20, 0xc0, 0x3c, 0xfc, 0x02, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29, 0x00, 0xC6, 0xC6,
0x00, 0xfc, 0xec, 0x16, 0xd6, 0x29, 0xd6, 0x29, 0x29, 0xC6, 0x29, 0xC6, 0x39, 0x7E, 0xC1, 0x06, 0x79,
0xd6, 0x29, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0x06, 0xF9, 0xFC, 0x06, 0x00, 0xFC, 0xFE, 0x01, 0x06,
0x00, 0xc7, 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x29, 0xF9, 0x06, 0x79, 0x7C, 0xC6, 0xC0, 0x3C, 0xC0, 0x3E,
0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, 0xFE, 0x01, 0x00, 0xFE, 0x3C, 0x42, 0x30, 0x4C, 0x30,
0x00, 0xc6, 0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x29, 0x48, 0x30, 0x48, 0x30, 0x48, 0x30, 0x4C, 0x3C, 0x42,
0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6, 0x00, 0x3C, 0xC0, 0x20, 0x60, 0x90, 0x30, 0x48, 0x18,
0x00, 0x7c, 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x29, 0x24, 0x0C, 0x12, 0x06, 0x09, 0x03, 0x04, 0x00, 0x03,
0xc6, 0x39, 0xfc, 0x06, 0xc0, 0x3c, 0xc0, 0x20, 0x3C, 0x42, 0x0C, 0x32, 0x0C, 0x12, 0x0C, 0x12, 0x0C,
0x00, 0xc0, 0x7c, 0x82, 0xc6, 0xbb, 0xc6, 0x29, 0x12, 0x0C, 0x32, 0x3C, 0x42, 0x00, 0x3C, 0x18, 0x24,
0xc6, 0x29, 0xc6, 0x29, 0xce, 0x31, 0x7e, 0xc1, 0x3C, 0x66, 0x66, 0x99, 0x00, 0x66, 0x5B, 0x00, 0x13,
0x00, 0x7e, 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x39, 0x7E, 0x7E, 0x81, 0x00, 0x7E, 0x30, 0x48, 0x18, 0x24,
0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0x18, 0x24, 0x00, 0x18, 0x5B, 0x00, 0x0B, 0x7C, 0x7C,
0x00, 0xc6, 0x7e, 0xc1, 0xc0, 0x3e, 0xc0, 0x3c, 0x86, 0x06, 0x79, 0x7E, 0xC1, 0xC6, 0x39, 0x7E, 0xC1,
0x7c, 0xc6, 0x06, 0x79, 0x06, 0xf9, 0xfc, 0x06, 0x00, 0x7E, 0xC0, 0x20, 0xC0, 0x3C, 0xFC, 0x06, 0xC6,
0x00, 0xfc, 0xfe, 0x01, 0x18, 0xe6, 0x18, 0x24, 0x39, 0xC6, 0x29, 0xC6, 0x39, 0xFC, 0x06, 0x00, 0xFC,
0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0xC1, 0xC0, 0x3E, 0xC0,
0x00, 0x18, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, 0x20, 0xC0, 0x3E, 0x7E, 0xC1, 0x00, 0x7E, 0x06, 0x09,
0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6, 0x06, 0x79, 0x7E, 0xC1, 0xC6, 0x39, 0xC6, 0x29, 0xC6,
0x00, 0x7c, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, 0x39, 0x7E, 0xC1, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7C,
0xc6, 0x29, 0x66, 0x99, 0x36, 0x49, 0x1e, 0x21, 0x7C, 0xC6, 0xC6, 0x39, 0xFE, 0x01, 0xC0, 0x3E, 0x7E,
0x00, 0x1f, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, 0xC3, 0x00, 0x7E, 0x1E, 0x21, 0x30, 0x6E, 0x30, 0x4C,
0xd6, 0x29, 0xd6, 0x29, 0xd6, 0x29, 0x6e, 0xd1, 0x3C, 0x42, 0x30, 0x4C, 0x30, 0x48, 0x30, 0x48, 0x30,
0x00, 0x6e, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, 0x48, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0xC1, 0xC6, 0x39,
0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0xC6, 0x39, 0x7E, 0xC1, 0x06, 0x79, 0x7C, 0x86, 0xC0,
0x00, 0xc6, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, 0x20, 0xC0, 0x3C, 0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x29,
0x7e, 0xc1, 0x06, 0x79, 0x06, 0xf9, 0xfc, 0x06, 0xC6, 0x29, 0xC6, 0x29, 0x00, 0xC6, 0x00, 0x18, 0x18,
0x00, 0xfc, 0xfe, 0x01, 0x06, 0xf9, 0x06, 0x79, 0x24, 0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24,
0x7c, 0xc6, 0xc0, 0x3c, 0xc0, 0x3e, 0xfe, 0x01, 0x18, 0x24, 0x00, 0x18, 0x00, 0x18, 0x18, 0x24, 0x00,
0x00, 0xfe, 0x3c, 0x42, 0x30, 0x4c, 0x30, 0x48, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x2C,
0x30, 0x48, 0x30, 0x48, 0x30, 0x4c, 0x3c, 0x42, 0x30, 0x48, 0xC0, 0x20, 0xC0, 0x26, 0xC6, 0x29, 0xC6,
0x00, 0x3c, 0xc0, 0x20, 0x60, 0x90, 0x30, 0x48, 0x2B, 0xFC, 0x06, 0xC6, 0x2B, 0xC6, 0x29, 0x00, 0xC7,
0x18, 0x24, 0x0c, 0x12, 0x06, 0x09, 0x03, 0x04, 0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x30,
0x00, 0x03, 0x3c, 0x42, 0x0c, 0x32, 0x0c, 0x12, 0x48, 0x30, 0x68, 0x18, 0x24, 0x00, 0x1C, 0x00, 0x00,
0x0c, 0x12, 0x0c, 0x12, 0x0c, 0x32, 0x3c, 0x42, 0x00, 0xEC, 0xEC, 0x16, 0xD6, 0x29, 0xD6, 0x29, 0xD6,
0x00, 0x3c, 0x18, 0x24, 0x3c, 0x66, 0x66, 0x99, 0x29, 0xC6, 0x39, 0x00, 0xC7, 0x00, 0x00, 0x00, 0xFC,
0x00, 0x66, 0x5b, 0x00, 0x13, 0x7e, 0x7e, 0x81, 0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29, 0xC6,
0x00, 0x7e, 0x30, 0x48, 0x18, 0x24, 0x18, 0x24, 0x29, 0x00, 0xC6, 0x00, 0x00, 0x00, 0x7C, 0x7C, 0xC6,
0x00, 0x18, 0x5b, 0x00, 0x0b, 0x7c, 0x7c, 0x86, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x39, 0x7C, 0xC6, 0x00,
0x06, 0x79, 0x7e, 0xc1, 0xc6, 0x39, 0x7e, 0xc1, 0x7C, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0x06, 0xC6, 0x39,
0x00, 0x7e, 0xc0, 0x20, 0xc0, 0x3c, 0xfc, 0x06, 0xC6, 0x39, 0xFC, 0x06, 0xC0, 0x3C, 0xC0, 0x20, 0x00,
0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x39, 0xfc, 0x06, 0x00, 0x00, 0x7E, 0x7E, 0xC1, 0xC6, 0x39, 0xC6, 0x39,
0x00, 0xfc, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0xc1, 0x7E, 0xC1, 0x06, 0x79, 0x06, 0x09, 0x00, 0x00, 0x00,
0xc0, 0x3e, 0xc0, 0x20, 0xc0, 0x3e, 0x7e, 0xc1, 0x7C, 0x7C, 0xC2, 0xC0, 0x3C, 0xC0, 0x20, 0xC0, 0x20,
0x00, 0x7e, 0x06, 0x09, 0x06, 0x79, 0x7e, 0xc1, 0xC0, 0x20, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x7E, 0x7E,
0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x39, 0x7e, 0xc1, 0xC1, 0xC0, 0x3E, 0x7C, 0xC6, 0x06, 0xF9, 0xFC, 0x06,
0x00, 0x7f, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0xc6, 0x00, 0xFC, 0x30, 0x48, 0x30, 0x4C, 0x3C, 0x42, 0x30,
0xc6, 0x39, 0xfe, 0x01, 0xc0, 0x3e, 0x7e, 0xc3, 0x4C, 0x30, 0x48, 0x30, 0x4E, 0x1E, 0x31, 0x00, 0x1E,
0x00, 0x7e, 0x1e, 0x21, 0x30, 0x6e, 0x30, 0x4c, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x29, 0xC6, 0x29, 0xC6,
0x3c, 0x42, 0x30, 0x4c, 0x30, 0x48, 0x30, 0x48, 0x29, 0xC6, 0x39, 0x7C, 0xC6, 0x00, 0x7C, 0x00, 0x00,
0x30, 0x48, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0xc1, 0x00, 0xC6, 0xC6, 0x29, 0xC6, 0x29, 0x66, 0x99, 0x36,
0xc6, 0x39, 0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79, 0x49, 0x1E, 0x21, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xC6,
0x7c, 0x86, 0xc0, 0x20, 0xc0, 0x3c, 0xfc, 0x06, 0xC6, 0x39, 0xD6, 0x29, 0xD6, 0x29, 0xD6, 0x29, 0x6E,
0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, 0xD1, 0x00, 0x6E, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x29,
0x00, 0xc6, 0x00, 0x18, 0x18, 0x24, 0x00, 0x18, 0xC6, 0x39, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, 0x29, 0x00,
0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0xC6, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x29, 0xC6, 0x39,
0x00, 0x18, 0x00, 0x18, 0x18, 0x24, 0x00, 0x18, 0x7E, 0xC1, 0x06, 0x79, 0x06, 0xF9, 0xFC, 0x06, 0x00,
0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x2c, 0x00, 0x00, 0xFE, 0xFE, 0x01, 0x06, 0xF9, 0x7C, 0xC6,
0x30, 0x48, 0xc0, 0x20, 0xc0, 0x26, 0xc6, 0x29, 0xC0, 0x3E, 0xFE, 0x01, 0x00, 0xFE, 0x18, 0x24, 0x30,
0xc6, 0x2b, 0xfc, 0x06, 0xc6, 0x2b, 0xc6, 0x29, 0x48, 0x30, 0x48, 0x70, 0x88, 0x30, 0x48, 0x30, 0x48,
0x00, 0xc7, 0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x18, 0x24, 0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18,
0x30, 0x48, 0x30, 0x48, 0x30, 0x68, 0x18, 0x24, 0x24, 0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24,
0x00, 0x1c, 0x00, 0x00, 0x00, 0xec, 0xec, 0x16, 0x00, 0x18, 0x30, 0x48, 0x18, 0x24, 0x18, 0x24, 0x1C,
0xd6, 0x29, 0xd6, 0x29, 0xd6, 0x29, 0xc6, 0x39, 0x22, 0x18, 0x24, 0x18, 0x24, 0x30, 0x48, 0x00, 0x30,
0x00, 0xc7, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x06, 0x00, 0x00, 0x00, 0x72, 0x72, 0x9D, 0xFE, 0x01, 0x9C,
0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, 0x72, 0x00, 0x9C, 0x5B, 0x00, 0x14, 0x42, 0x08, 0xFF,
0x00, 0xc6, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0xc6, 0x7F, 0x00, 0x00, 0x9C, 0x73, 0x42, 0x08, 0xFF, 0x43,
0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6, 0x00, 0x00, 0x18, 0x63, 0xC2, 0x30, 0xAD, 0x00, 0x00,
0x00, 0x7c, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x06, 0x29, 0xFF, 0x00, 0x0A, 0x18, 0x69, 0x00, 0xB0, 0x8D,
0xc6, 0x39, 0xc6, 0x39, 0xfc, 0x06, 0xc0, 0x3c, 0x09, 0x00, 0xAD, 0x02, 0x00, 0x29, 0xFF, 0x00, 0x5B,
0xc0, 0x20, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0xc1, 0x0A, 0x06, 0x18, 0x6D, 0x09, 0x00, 0x8F, 0x81, 0x21,
0xc6, 0x39, 0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79, 0x00, 0xE2, 0x20, 0xA9, 0x7F, 0x8F, 0x83, 0x21, 0x00,
0x06, 0x09, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0xc2, 0xAE, 0x04, 0x00, 0xAD, 0x06, 0x00, 0x48, 0xAB, 0xBD,
0xc0, 0x3c, 0xc0, 0x20, 0xc0, 0x20, 0xc0, 0x20, 0x00, 0x00, 0xF0, 0x11, 0x8F, 0x80, 0x21, 0x00, 0xA9,
0x00, 0xc0, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0xc1, 0x00, 0x69, 0x00, 0x09, 0x20, 0x8F, 0x80, 0x21, 0x00,
0xc0, 0x3e, 0x7c, 0xc6, 0x06, 0xf9, 0xfc, 0x06, 0xE8, 0x80, 0xEA, 0xA9, 0x00, 0x48, 0xAB, 0x60, 0xFF,
0x00, 0xfc, 0x30, 0x48, 0x30, 0x4c, 0x3c, 0x42, 0xC2, 0x10, 0xE2, 0x20, 0xAD, 0x15, 0x00, 0x8D, 0x00,
0x30, 0x4c, 0x30, 0x48, 0x30, 0x4e, 0x1e, 0x31, 0x43, 0xAD, 0x12, 0x00, 0x8D, 0x01, 0x43, 0xAD, 0x0F,
0x00, 0x1e, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x29, 0x00, 0xAE, 0x10, 0x00, 0x8E, 0x02, 0x43, 0x8D, 0x04,
0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6, 0x43, 0xAE, 0x13, 0x00, 0x8E, 0x05, 0x43, 0xA9, 0x01,
0x00, 0x7c, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x29, 0x8D, 0x0B, 0x42, 0x60, 0xE2, 0x20, 0xC2, 0x10, 0x9C,
0xc6, 0x29, 0x66, 0x99, 0x36, 0x49, 0x1e, 0x21, 0x0B, 0x42, 0x9C, 0x0C, 0x42, 0x9C, 0x00, 0x42, 0x60,
0x00, 0x1e, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x39, 0x77, 0x00, 0xEE, 0xF2, 0x78, 0x18, 0xFB, 0x5C, 0x3B,
0xd6, 0x29, 0xd6, 0x29, 0xd6, 0x29, 0x6e, 0xd1, 0x00, 0xC0, 0x08, 0xC2, 0x30, 0x48, 0xDA, 0x5A, 0x0B,
0x00, 0x6e, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x29, 0x8B, 0x22, 0x35, 0x00, 0xC0, 0xC2, 0x30, 0xAB, 0x2B,
0xc6, 0x39, 0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x29, 0x7A, 0xFA, 0x68, 0x28, 0x40, 0x08, 0xC2, 0x30, 0x48,
0x00, 0xc6, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x29, 0xDA, 0x5A, 0x0B, 0x8B, 0x22, 0x00, 0x00, 0xC0, 0xC2,
0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79, 0x06, 0xf9, 0x30, 0xAB, 0x2B, 0x7A, 0xFA, 0x68, 0x28, 0x40, 0xCB,
0xfc, 0x06, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x01, 0xAF, 0xEF, 0xCD, 0xAB, 0x80, 0xF9, 0x5B, 0x20, 0x1C,
0x06, 0xf9, 0x7c, 0xc6, 0xc0, 0x3e, 0xfe, 0x01, 0x76, 0x30, 0x2E, 0x31, 0x00, 0x00, 0x00, 0x5B, 0x20,
0x00, 0xfe, 0x18, 0x24, 0x30, 0x48, 0x30, 0x48, 0x41, 0x00, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x3E, 0x5B,
0x70, 0x88, 0x30, 0x48, 0x30, 0x48, 0x18, 0x24, 0x00, 0x0D, 0x4D, 0x52, 0x42, 0x4F, 0x4F, 0x54, 0x5B,
0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x00, 0x0A, 0x53, 0x44, 0x32, 0x53, 0x4E, 0x45, 0x53,
0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x20, 0x42, 0x4F, 0x4F, 0x54, 0x5B, 0x20, 0x09, 0x31,
0x00, 0x18, 0x30, 0x48, 0x18, 0x24, 0x18, 0x24, 0x02, 0x06, 0x03, 0x09, 0x33, 0x00, 0x4F, 0x87, 0xB0,
0x1c, 0x22, 0x18, 0x24, 0x18, 0x24, 0x30, 0x48, 0x78, 0x5B, 0x00, 0x04, 0x31, 0xFF, 0x31, 0xFF, 0x31,
0x00, 0x30, 0x00, 0x00, 0x00, 0x72, 0x72, 0x9d, 0xFF, 0x1C, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x5B, 0x00,
0xfe, 0x01, 0x9c, 0x72, 0x00, 0x9c, 0x5b, 0x00, 0x04, 0x31, 0xFF, 0x00, 0x00, 0x31, 0xFF, 0x31, 0xFF,
0x14, 0x42, 0x08, 0xff, 0x7f, 0x00, 0x00, 0x9c, 0x00, 0xFF, 0x31, 0xFF, 0xFF,
0x73, 0x42, 0x08, 0xff, 0x43, 0x00, 0x00, 0x18, };
0x63, 0xc2, 0x30, 0xad, 0x00, 0x00, 0x29, 0xff,
0x00, 0x0a, 0x18, 0x69, 0x00, 0xb0, 0x8d, 0x09,
0x00, 0xad, 0x02, 0x00, 0x29, 0xff, 0x00, 0x5b,
0x0a, 0x06, 0x18, 0x6d, 0x09, 0x00, 0x8f, 0x81,
0x21, 0x00, 0xe2, 0x20, 0xa9, 0x7f, 0x8f, 0x83,
0x21, 0x00, 0xae, 0x04, 0x00, 0xad, 0x06, 0x00,
0x48, 0xab, 0xbd, 0x00, 0x00, 0xf0, 0x11, 0x8f,
0x80, 0x21, 0x00, 0xa9, 0x00, 0x69, 0x00, 0x09,
0x20, 0x8f, 0x80, 0x21, 0x00, 0xe8, 0x80, 0xea,
0xa9, 0x00, 0x48, 0xab, 0x60, 0xff, 0xc2, 0x10,
0xe2, 0x20, 0xad, 0x15, 0x00, 0x8d, 0x00, 0x43,
0xad, 0x12, 0x00, 0x8d, 0x01, 0x43, 0xad, 0x0f,
0x00, 0xae, 0x10, 0x00, 0x8e, 0x02, 0x43, 0x8d,
0x04, 0x43, 0xae, 0x13, 0x00, 0x8e, 0x05, 0x43,
0xa9, 0x01, 0x8d, 0x0b, 0x42, 0x60, 0xe2, 0x20,
0xc2, 0x10, 0x9c, 0x0b, 0x42, 0x9c, 0x0c, 0x42,
0x9c, 0x00, 0x42, 0x60, 0x77, 0x00, 0xee, 0xf2,
0x78, 0x18, 0xfb, 0x5c, 0x3b, 0x00, 0xc0, 0x08,
0xc2, 0x30, 0x48, 0xda, 0x5a, 0x0b, 0x8b, 0x22,
0x35, 0x00, 0xc0, 0xc2, 0x30, 0xab, 0x2b, 0x7a,
0xfa, 0x68, 0x28, 0x40, 0x08, 0xc2, 0x30, 0x48,
0xda, 0x5a, 0x0b, 0x8b, 0x22, 0x00, 0x00, 0xc0,
0xc2, 0x30, 0xab, 0x2b, 0x7a, 0xfa, 0x68, 0x28,
0x40, 0xcb, 0xaf, 0xef, 0xcd, 0xab, 0x80, 0xf9,
0x5b, 0x20, 0x1c, 0x76, 0x30, 0x2e, 0x31, 0x00,
0x00, 0x00, 0x5b, 0x20, 0x41, 0x00, 0x20, 0x3c,
0x64, 0x69, 0x72, 0x3e, 0x5b, 0x00, 0x0d, 0x4d,
0x52, 0x42, 0x4f, 0x4f, 0x54, 0x5b, 0x00, 0x0a,
0x53, 0x44, 0x32, 0x53, 0x4e, 0x45, 0x53, 0x20,
0x42, 0x4f, 0x4f, 0x54, 0x5b, 0x20, 0x09, 0x31,
0x02, 0x06, 0x03, 0x09, 0x33, 0x00, 0x4f, 0x87,
0xb0, 0x78, 0x5b, 0x00, 0x04, 0x31, 0xff, 0x31,
0xff, 0x31, 0xff, 0x1c, 0xff, 0x00, 0x00, 0x07,
0xff, 0x5b, 0x00, 0x04, 0x31, 0xff, 0x00, 0x00,
0x31, 0xff, 0x31, 0xff, 0x00, 0xff, 0x31, 0xff};

View File

@ -15,98 +15,135 @@
*/ */
uint32_t stat_getstring = 0; uint32_t stat_getstring = 0;
static char sort_str1[21], sort_str2[21]; static char sort_str1[SORT_STRLEN + 1], sort_str2[SORT_STRLEN + 1];
uint32_t ptrcache[QSORT_MAXELEM] IN_AHBRAM; uint32_t ptrcache[QSORT_MAXELEM] IN_AHBRAM;
/* get element from pointer table in external RAM*/ /* get element from pointer table in external RAM*/
uint32_t sort_get_elem(uint32_t base, unsigned int index) { uint32_t sort_get_elem( uint32_t base, unsigned int index )
{
return sram_readlong( base + 4 * index ); return sram_readlong( base + 4 * index );
} }
/* put element from pointer table in external RAM */ /* put element from pointer table in external RAM */
void sort_put_elem(uint32_t base, unsigned int index, uint32_t elem) { void sort_put_elem( uint32_t base, unsigned int index, uint32_t elem )
{
sram_writelong( elem, base + 4 * index ); sram_writelong( elem, base + 4 * index );
} }
/* compare strings pointed to by elements of pointer table */ /* compare strings pointed to by elements of pointer table */
int sort_cmp_idx(uint32_t base, unsigned int index1, unsigned int index2) { int sort_cmp_idx( uint32_t base, unsigned int index1, unsigned int index2 )
{
uint32_t elem1, elem2; uint32_t elem1, elem2;
elem1 = sort_get_elem( base, index1 ); elem1 = sort_get_elem( base, index1 );
elem2 = sort_get_elem( base, index2 ); elem2 = sort_get_elem( base, index2 );
return sort_cmp_elem( ( void * )&elem1, ( void * )&elem2 ); return sort_cmp_elem( ( void * )&elem1, ( void * )&elem2 );
} }
int sort_cmp_elem(const void* elem1, const void* elem2) { int sort_cmp_elem( const void *elem1, const void *elem2 )
{
uint32_t el1 = *( uint32_t * )elem1; uint32_t el1 = *( uint32_t * )elem1;
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 );
/*printf("i1=%d i2=%d elem1=%lx elem2=%lx ; compare %s --- %s\n", index1, index2, elem1, elem2, sort_str1, sort_str2); */ /*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;
} }
if (!(el1 & 0x80000000) && (el2 & 0x80000000)) { if ( !( el1 & 0x80000000 ) && ( el2 & 0x80000000 ) )
{
return 1; return 1;
} }
if (*sort_str1 == '.') return -1; if ( *sort_str1 == '.' )
if (*sort_str2 == '.') return 1; {
return -1;
}
if ( *sort_str2 == '.' )
{
return 1;
}
/* Do not compare trailing slashes of directory names */ /* Do not compare trailing slashes of directory names */
if ((el1 & 0x80000000) && (el2 & 0x80000000)) { if ( ( el1 & 0x80000000 ) && ( el2 & 0x80000000 ) )
{
char *str1_slash = strrchr( sort_str1, '/' ); char *str1_slash = strrchr( sort_str1, '/' );
char *str2_slash = strrchr( sort_str2, '/' ); char *str2_slash = strrchr( sort_str2, '/' );
if(str1_slash != NULL) *str1_slash = 0;
if(str2_slash != NULL) *str2_slash = 0; if ( str1_slash != NULL )
{
*str1_slash = 0;
}
if ( str2_slash != NULL )
{
*str2_slash = 0;
}
} }
return strcasecmp( sort_str1, sort_str2 ); return strcasecmp( sort_str1, sort_str2 );
} }
/* get truncated string from database */ /* get truncated string from database */
void sort_getstring_for_dirent(char *ptr, uint32_t addr) { void sort_getstring_for_dirent( char *ptr, uint32_t addr )
{
uint8_t leaf_offset; uint8_t leaf_offset;
if(addr & 0x80000000) {
if ( addr & 0x80000000 )
{
/* is directory link, name offset 4 */ /* is directory link, name offset 4 */
leaf_offset = sram_readbyte( addr + 4 + SRAM_MENU_ADDR ); leaf_offset = sram_readbyte( addr + 4 + SRAM_MENU_ADDR );
sram_readblock(ptr, addr + 5 + leaf_offset + SRAM_MENU_ADDR, 20); sram_readstrn( ptr, addr + 5 + leaf_offset + SRAM_MENU_ADDR, SORT_STRLEN );
} else { }
else
{
/* is file link, name offset 6 */ /* is file link, name offset 6 */
leaf_offset = sram_readbyte( addr + 6 + SRAM_MENU_ADDR ); leaf_offset = sram_readbyte( addr + 6 + SRAM_MENU_ADDR );
sram_readblock(ptr, addr + 7 + leaf_offset + SRAM_MENU_ADDR, 20); sram_readstrn( ptr, addr + 7 + leaf_offset + SRAM_MENU_ADDR, SORT_STRLEN );
} }
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 ) if ( r < heapsize && sort_cmp_idx( addr, largest, r ) < 0 )
{
largest = r; largest = r;
}
if(largest != i) { if ( largest != i )
{
uint32_t tmp = sort_get_elem( addr, i ); uint32_t tmp = sort_get_elem( addr, i );
sort_put_elem( addr, i, sort_get_elem( addr, largest ) ); sort_put_elem( addr, i, sort_get_elem( addr, largest ) );
sort_put_elem( addr, largest, tmp ); sort_put_elem( addr, largest, tmp );
i = largest; i = largest;
} }
else break; else
{
break;
}
} }
} }
void sort_dir( uint32_t addr, unsigned int size ) void sort_dir( uint32_t addr, unsigned int size )
{ {
stat_getstring = 0; stat_getstring = 0;
if(size > QSORT_MAXELEM) {
if ( size > QSORT_MAXELEM )
{
printf( "more than %d dir entries, doing slower in-place sort\n", QSORT_MAXELEM ); printf( "more than %d dir entries, doing slower in-place sort\n", QSORT_MAXELEM );
ext_heapsort( addr, size ); ext_heapsort( addr, size );
} else { }
else
{
/* retrieve, sort, and store dir table */ /* retrieve, sort, and store dir table */
sram_readblock( ptrcache, addr, size * 4 ); sram_readblock( ptrcache, addr, size * 4 );
qsort( ( void * )ptrcache, size, 4, sort_cmp_elem ); qsort( ( void * )ptrcache, size, 4, sort_cmp_elem );
@ -114,10 +151,15 @@ stat_getstring=0;
} }
} }
void ext_heapsort(uint32_t addr, unsigned int size) { 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 );

View File

@ -30,13 +30,14 @@
#include "spi.h" #include "spi.h"
#include "uart.h" #include "uart.h"
void spi_preinit() { void spi_preinit()
{
/* Set clock prescaler to 1:1 */ /* Set clock prescaler to 1:1 */
BITBAND( LPC_SC->SSP_PCLKREG, SSP_PCLKBIT ) = 1; BITBAND( LPC_SC->SSP_PCLKREG, SSP_PCLKBIT ) = 1;
} }
void spi_init() { void spi_init()
{
/* configure data format - 8 bits, SPI, CPOL=0, CPHA=0, 1 clock per bit */ /* configure data format - 8 bits, SPI, CPOL=0, CPHA=0, 1 clock per bit */
SSP_REGS->CR0 = ( 8 - 1 ); SSP_REGS->CR0 = ( 8 - 1 );
@ -52,12 +53,14 @@ void spi_init() {
LPC_GPDMA->DMACConfig = 1; LPC_GPDMA->DMACConfig = 1;
} }
void spi_tx_sync() { void spi_tx_sync()
{
/* Wait until TX fifo is flushed */ /* Wait until TX fifo is flushed */
while ( BITBAND( SSP_REGS->SR, SSP_BSY ) ) ; while ( BITBAND( SSP_REGS->SR, SSP_BSY ) ) ;
} }
void spi_tx_byte(uint8_t data) { void spi_tx_byte( uint8_t data )
{
/* Wait until TX fifo can accept data */ /* Wait until TX fifo can accept data */
while ( !BITBAND( SSP_REGS->SR, SSP_TNF ) ) ; while ( !BITBAND( SSP_REGS->SR, SSP_TNF ) ) ;
@ -65,13 +68,16 @@ void spi_tx_byte(uint8_t data) {
SSP_REGS->DR = data; SSP_REGS->DR = data;
} }
uint8_t spi_txrx_byte(uint8_t data) { uint8_t spi_txrx_byte( uint8_t data )
{
/* Wait until SSP is not busy */ /* Wait until SSP is not busy */
while ( BITBAND( SSP_REGS->SR, SSP_BSY ) ) ; while ( BITBAND( SSP_REGS->SR, SSP_BSY ) ) ;
/* Clear RX fifo */ /* Clear RX fifo */
while ( BITBAND( SSP_REGS->SR, SSP_RNE ) ) while ( BITBAND( SSP_REGS->SR, SSP_RNE ) )
{
( void ) SSP_REGS->DR; ( void ) SSP_REGS->DR;
}
/* Transmit a single byte */ /* Transmit a single byte */
SSP_REGS->DR = data; SSP_REGS->DR = data;
@ -82,13 +88,16 @@ uint8_t spi_txrx_byte(uint8_t data) {
return SSP_REGS->DR; return SSP_REGS->DR;
} }
uint8_t spi_rx_byte() { uint8_t spi_rx_byte()
{
/* Wait until SSP is not busy */ /* Wait until SSP is not busy */
while ( BITBAND( SSP_REGS->SR, SSP_BSY ) ) ; while ( BITBAND( SSP_REGS->SR, SSP_BSY ) ) ;
/* Clear RX fifo */ /* Clear RX fifo */
while ( BITBAND( SSP_REGS->SR, SSP_RNE ) ) while ( BITBAND( SSP_REGS->SR, SSP_RNE ) )
{
( void ) SSP_REGS->DR; ( void ) SSP_REGS->DR;
}
/* Transmit a single dummy byte */ /* Transmit a single dummy byte */
SSP_REGS->DR = 0xff; SSP_REGS->DR = 0xff;
@ -99,10 +108,12 @@ uint8_t spi_rx_byte() {
return SSP_REGS->DR; return SSP_REGS->DR;
} }
void spi_tx_block(const void *ptr, unsigned int length) { void spi_tx_block( const void *ptr, unsigned int length )
{
const uint8_t *data = ( const uint8_t * )ptr; const uint8_t *data = ( const uint8_t * )ptr;
while (length--) { while ( length-- )
{
/* Wait until TX fifo can accept data */ /* Wait until TX fifo can accept data */
while ( !BITBAND( SSP_REGS->SR, SSP_TNF ) ) ; while ( !BITBAND( SSP_REGS->SR, SSP_TNF ) ) ;
@ -110,7 +121,8 @@ void spi_tx_block(const void *ptr, unsigned int length) {
} }
} }
void spi_rx_block(void *ptr, unsigned int length) { void spi_rx_block( void *ptr, unsigned int length )
{
uint8_t *data = ( uint8_t * )ptr; uint8_t *data = ( uint8_t * )ptr;
unsigned int txlen = length; unsigned int txlen = length;
@ -119,28 +131,36 @@ void spi_rx_block(void *ptr, unsigned int length) {
/* Clear RX fifo */ /* Clear RX fifo */
while ( BITBAND( SSP_REGS->SR, SSP_RNE ) ) while ( BITBAND( SSP_REGS->SR, SSP_RNE ) )
{
( void ) SSP_REGS->DR; ( void ) SSP_REGS->DR;
}
if ((length & 3) != 0 || ((uint32_t)ptr & 3) != 0) { if ( ( length & 3 ) != 0 || ( ( uint32_t )ptr & 3 ) != 0 )
{
/* Odd length or unaligned buffer */ /* Odd length or unaligned buffer */
while (length > 0) { while ( length > 0 )
{
/* Wait until TX or RX FIFO are ready */ /* Wait until TX or RX FIFO are ready */
while ( txlen > 0 && !BITBAND( SSP_REGS->SR, SSP_TNF ) && while ( txlen > 0 && !BITBAND( SSP_REGS->SR, SSP_TNF ) &&
!BITBAND( SSP_REGS->SR, SSP_RNE ) ) ; !BITBAND( SSP_REGS->SR, SSP_RNE ) ) ;
/* Try to receive data */ /* Try to receive data */
while (length > 0 && BITBAND(SSP_REGS->SR, SSP_RNE)) { while ( length > 0 && BITBAND( SSP_REGS->SR, SSP_RNE ) )
{
*data++ = SSP_REGS->DR; *data++ = SSP_REGS->DR;
length--; length--;
} }
/* Send dummy data until TX full or RX ready */ /* Send dummy data until TX full or RX ready */
while (txlen > 0 && BITBAND(SSP_REGS->SR, SSP_TNF) && !BITBAND(SSP_REGS->SR, SSP_RNE)) { while ( txlen > 0 && BITBAND( SSP_REGS->SR, SSP_TNF ) && !BITBAND( SSP_REGS->SR, SSP_RNE ) )
{
txlen--; txlen--;
SSP_REGS->DR = 0xff; SSP_REGS->DR = 0xff;
} }
} }
} else { }
else
{
/* Clear interrupt flags of DMA channels 0 */ /* Clear interrupt flags of DMA channels 0 */
LPC_GPDMA->DMACIntTCClear = BV( 0 ); LPC_GPDMA->DMACIntTCClear = BV( 0 );
LPC_GPDMA->DMACIntErrClr = BV( 0 ); LPC_GPDMA->DMACIntErrClr = BV( 0 );
@ -167,8 +187,10 @@ void spi_rx_block(void *ptr, unsigned int length) {
/* Write <length> bytes into TX FIFO */ /* Write <length> bytes into TX FIFO */
// FIXME: Any value in doing this using DMA too? // FIXME: Any value in doing this using DMA too?
while (txlen > 0) { while ( txlen > 0 )
while (txlen > 0 && BITBAND(SSP_REGS->SR, SSP_TNF)) { {
while ( txlen > 0 && BITBAND( SSP_REGS->SR, SSP_TNF ) )
{
txlen--; txlen--;
SSP_REGS->DR = 0xff; SSP_REGS->DR = 0xff;
} }

View File

@ -18,16 +18,20 @@
static uint32_t sd_tacc_max, sd_tacc_avg; static uint32_t sd_tacc_max, sd_tacc_avg;
void sysinfo_loop() { void sysinfo_loop()
{
sd_tacc_max = 0; sd_tacc_max = 0;
sd_tacc_avg = 0; sd_tacc_avg = 0;
while(sram_readbyte(SRAM_CMD_ADDR) != 0x00) {
while ( sram_readbyte( SRAM_CMD_ADDR ) != 0x00 )
{
write_sysinfo(); write_sysinfo();
delay_ms( 100 ); delay_ms( 100 );
} }
} }
void write_sysinfo() { void write_sysinfo()
{
uint32_t sram_addr = SRAM_SYSINFO_ADDR; uint32_t sram_addr = SRAM_SYSINFO_ADDR;
char linebuf[40]; char linebuf[40];
int len; int len;
@ -49,7 +53,9 @@ void write_sysinfo() {
sram_writeblock( linebuf, sram_addr, 40 ); sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 ); sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40; sram_addr += 40;
if(disk_state == DISK_REMOVED) {
if ( disk_state == DISK_REMOVED )
{
sd_tacc_max = 0; sd_tacc_max = 0;
sd_tacc_avg = 0; sd_tacc_avg = 0;
len = snprintf( linebuf, sizeof( linebuf ), " " ); len = snprintf( linebuf, sizeof( linebuf ), " " );
@ -69,28 +75,40 @@ void write_sysinfo() {
sram_memset( sram_addr + len, 40 - len, 0x20 ); sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40; sram_addr += 40;
sd_ok = 0; sd_ok = 0;
} else { }
else
{
len = snprintf( linebuf, sizeof( linebuf ), "SD Maker/OEM: 0x%02x, \"%c%c\"", sd_cid[1], sd_cid[2], sd_cid[3] ); len = snprintf( linebuf, sizeof( linebuf ), "SD Maker/OEM: 0x%02x, \"%c%c\"", sd_cid[1], sd_cid[2], sd_cid[3] );
sram_writeblock( linebuf, sram_addr, 40 ); sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 ); sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40; sram_addr += 40;
len = snprintf(linebuf, sizeof(linebuf), "SD Product Name: \"%c%c%c%c%c\", Rev. %d.%d", sd_cid[4], sd_cid[5], sd_cid[6], sd_cid[7], sd_cid[8], sd_cid[9]>>4, sd_cid[9]&15); len = snprintf( linebuf, sizeof( linebuf ), "SD Product Name: \"%c%c%c%c%c\", Rev. %d.%d", sd_cid[4], sd_cid[5],
sd_cid[6], sd_cid[7], sd_cid[8], sd_cid[9] >> 4, sd_cid[9] & 15 );
sram_writeblock( linebuf, sram_addr, 40 ); sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 ); sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40; sram_addr += 40;
len = snprintf(linebuf, sizeof(linebuf), "SD Serial No.: %02x%02x%02x%02x, Mfd. %d/%02d", sd_cid[10], sd_cid[11], sd_cid[12], sd_cid[13], 2000+((sd_cid[14]&15)<<4)+(sd_cid[15]>>4), sd_cid[15]&15); len = snprintf( linebuf, sizeof( linebuf ), "SD Serial No.: %02x%02x%02x%02x, Mfd. %d/%02d", sd_cid[10], sd_cid[11],
sd_cid[12], sd_cid[13], 2000 + ( ( sd_cid[14] & 15 ) << 4 ) + ( sd_cid[15] >> 4 ), sd_cid[15] & 15 );
sram_writeblock( linebuf, sram_addr, 40 ); sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 ); sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40; sram_addr += 40;
if ( sd_tacc_max ) if ( sd_tacc_max )
len = snprintf(linebuf, sizeof(linebuf), "SD acc. time: %ld.%03ld / %ld.%03ld ms avg/max", sd_tacc_avg_int, sd_tacc_avg_frac, sd_tacc_max_int, sd_tacc_max_frac); {
len = snprintf( linebuf, sizeof( linebuf ), "SD acc. time: %ld.%03ld / %ld.%03ld ms avg/max", sd_tacc_avg_int,
sd_tacc_avg_frac, sd_tacc_max_int, sd_tacc_max_frac );
}
else else
{
len = snprintf( linebuf, sizeof( linebuf ), "SD acc. time: measuring... " ); len = snprintf( linebuf, sizeof( linebuf ), "SD acc. time: measuring... " );
}
sram_writeblock( linebuf, sram_addr, 40 ); sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 ); sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40; sram_addr += 40;
sd_ok = 1; sd_ok = 1;
} }
len = snprintf( linebuf, sizeof( linebuf ), " " ); len = snprintf( linebuf, sizeof( linebuf ), " " );
sram_writeblock( linebuf, sram_addr, 40 ); sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 ); sram_memset( sram_addr + len, 40 - len, 0x20 );
@ -99,10 +117,16 @@ void write_sysinfo() {
sram_writeblock( linebuf, sram_addr, 40 ); sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 ); sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40; sram_addr += 40;
if ( sysclk == -1 ) if ( sysclk == -1 )
{
len = snprintf( linebuf, sizeof( linebuf ), "SNES master clock: measuring..." ); len = snprintf( linebuf, sizeof( linebuf ), "SNES master clock: measuring..." );
}
else else
{
len = snprintf( linebuf, sizeof( linebuf ), "SNES master clock: %ldHz ", get_snes_sysclk() ); len = snprintf( linebuf, sizeof( linebuf ), "SNES master clock: %ldHz ", get_snes_sysclk() );
}
sram_writeblock( linebuf, sram_addr, 40 ); sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 ); sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40; sram_addr += 40;
@ -122,6 +146,10 @@ void write_sysinfo() {
sram_writeblock( linebuf, sram_addr, 40 ); sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 ); sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_hexdump( SRAM_SYSINFO_ADDR, 13 * 40 ); sram_hexdump( SRAM_SYSINFO_ADDR, 13 * 40 );
if(sysclk != -1 && sd_ok)sdn_gettacc(&sd_tacc_max, &sd_tacc_avg);
if ( sysclk != -1 && sd_ok )
{
sdn_gettacc( &sd_tacc_max, &sd_tacc_avg );
}
} }

View File

@ -7,5 +7,6 @@ void test_sdbench_local(char *filename);
void test_rom_rw(void); void test_rom_rw(void);
void test_fpga_echo(void); void test_fpga_echo(void);
int test_mem(void);
#endif #endif

View File

@ -138,7 +138,8 @@ CFLAGS += $(CDEFS) $(CINCS)
CFLAGS += -O$(OPT) CFLAGS += -O$(OPT)
CFLAGS += $(CPUFLAGS) -nostartfiles CFLAGS += $(CPUFLAGS) -nostartfiles
#CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums #CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wstrict-prototypes -Werror CFLAGS += -Wall -Wstrict-prototypes
# -Werror
CFLAGS += -Wa,-adhlns=$(OBJDIR)/$(<:.c=.lst) CFLAGS += -Wa,-adhlns=$(OBJDIR)/$(<:.c=.lst)
CFLAGS += -I$(OBJDIR) CFLAGS += -I$(OBJDIR)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))

View File

@ -38,7 +38,8 @@
//#define CONFIG_CPU_FREQUENCY 46000000 //#define CONFIG_CPU_FREQUENCY 46000000
#define CONFIG_UART_PCLKDIV 1 #define CONFIG_UART_PCLKDIV 1
#define CONFIG_UART_TX_BUF_SHIFT 8 #define CONFIG_UART_TX_BUF_SHIFT 8
#define CONFIG_UART_BAUDRATE 921600 //#define CONFIG_UART_BAUDRATE 921600
#define CONFIG_UART_BAUDRATE 115200
#define CONFIG_UART_DEADLOCKABLE #define CONFIG_UART_DEADLOCKABLE
#define SSP_CLK_DIVISOR_FAST 2 #define SSP_CLK_DIVISOR_FAST 2

View File

@ -101,9 +101,9 @@ led_pwm();
testresults[TEST_SD] = test_sd(); testresults[TEST_SD] = test_sd();
//testresults[TEST_USB] = test_usb(); //testresults[TEST_USB] = test_usb();
testresults[TEST_RTC] = test_rtc(); //testresults[TEST_RTC] = test_rtc();
delay_ms(209); delay_ms(209);
testresults[TEST_CIC] = test_cic(); // testresults[TEST_CIC] = test_cic();
testresults[TEST_FPGA] = test_fpga(); testresults[TEST_FPGA] = test_fpga();
testresults[TEST_RAM] = test_mem(); testresults[TEST_RAM] = test_mem();
printf("Loading SNES test ROM\n=====================\n"); printf("Loading SNES test ROM\n=====================\n");

View File

@ -5,8 +5,14 @@
# #
interface ft2232 interface ft2232
ft2232_vid_pid 0x0403 0x6010 ft2232_vid_pid 0x15ba 0x0003
ft2232_device_desc "Dual RS232" ft2232_device_desc "Olimex OpenOCD JTAG"
ft2232_layout "oocdlink" ft2232_layout "olimex-jtag"
ft2232_latency 2
#interface ft2232
#ft2232_vid_pid 0x0403 0x6010
#ft2232_device_desc "Dual RS232"
#ft2232_layout "oocdlink"
#ft2232_latency 2
#adapter_khz 10 #adapter_khz 10

View File

@ -152,74 +152,178 @@ int test_fpga() {
return PASSED; return PASSED;
} }
int test_mem() { /*************************************************************************************/
printf("RAM test\n========\n"); /*************************************************************************************/
printf("Testing RAM0 (128Mbit) - writing RAM -");
uint32_t addr; typedef struct memory_test
{
char name[20];
int a_len;
int d_len;
unsigned int (*read)(unsigned int addr);
void (*write)(unsigned int addr, unsigned int data);
void (*open)(void);
void (*close)(void);
} memory_test;
/*************************************************************************************/
void rom_open(void)
{
snes_reset(1); snes_reset(1);
fpga_select_mem(0); fpga_select_mem(0);
set_mcu_addr(0);
FPGA_DESELECT(); FPGA_DESELECT();
delay_ms(1); delay_ms(1);
FPGA_SELECT(); FPGA_SELECT();
delay_ms(1); delay_ms(1);
FPGA_TX_BYTE(0x98);
for(addr=0; addr < 16777216; addr++) {
if((addr&0xffff) == 0)printf("\x8%c", PROGRESS[(addr>>16)&3]);
FPGA_TX_BYTE((addr)+(addr>>8)+(addr>>16));
FPGA_WAIT_RDY();
} }
FPGA_DESELECT(); void rom_close(void)
printf(" verifying RAM -"); {
uint8_t data, expect, error=0, failed=0;
set_mcu_addr(0);
FPGA_SELECT();
FPGA_TX_BYTE(0x88);
for(addr=0; addr < 16777216; addr++) {
if((addr&0xffff) == 0)printf("\x8%c", PROGRESS[(addr>>16)&3]);
FPGA_WAIT_RDY();
data = FPGA_RX_BYTE();
expect = (addr)+(addr>>8)+(addr>>16);
if(data != expect) {
printf("error @0x%06lx: expected 0x%02x, got 0x%02x\n", addr, expect, data);
error++;
failed=1;
if(error>20) {
printf("too many errors, aborting\n");
break;
} }
unsigned int rom_read(unsigned int addr)
{
return sram_readbyte(addr);
} }
void rom_write(unsigned int addr, unsigned int data)
{
sram_writebyte(data, addr);
} }
FPGA_DESELECT();
if(error) printf("RAM0 FAILED\n"); memory_test rom = {
else printf("RAM0 PASSED\n"); .name = "RAM0 (128Mbit)",
printf("Testing RAM1 (4Mbit) - writing RAM - "); .a_len = 22,
.d_len = 8,
.read = rom_read,
.write = rom_write,
.open = rom_open,
.close = rom_close,
};
/*************************************************************************************/
void sram_open(void)
{
snes_reset(1); snes_reset(1);
fpga_select_mem(1); fpga_select_mem(1);
for(addr=0; addr < 524288; addr++) {
sram_writebyte((addr)+(addr>>8)+(addr>>16), addr);
} }
printf("verifying RAM...");
error = 0; void sram_close(void)
for(addr=0; addr < 524288; addr++) { {
data = sram_readbyte(addr); }
expect = (addr)+(addr>>8)+(addr>>16);
if(data != expect) { unsigned int sram_read(unsigned int addr)
printf("error @0x%05lx: expected 0x%02x, got 0x%02x\n", addr, expect, data); {
error++; return sram_readbyte(addr);
failed=1; }
if(error>20) {
printf("too many errors, aborting\n"); void sram_write(unsigned int addr, unsigned int data)
{
sram_writebyte(data, addr);
}
memory_test sram =
{
.name = "RAM1(4Mbit)",
.a_len = 19,
.d_len = 8,
.read = sram_read,
.write = sram_write,
.open = sram_open,
.close = sram_close,
};
int do_test(memory_test *test)
{
int i, j, read, want;
int ret = 0;
int a_mask = (1 << test->a_len) - 1;
int d_mask = (1 << test->d_len) - 1;
test->open();
printf("-- Will test %s\n", test->name);
printf("---- Fill with AA55 ");
test->write(0, 0xAA);
for (i = 1; i < a_mask; i++)
{
if((i&0xffff) == 0)printf("\x8%c", PROGRESS[(i>>16)&3]);
want = (i&1)?0x55:0xAA;
test->write(i, want);
want = ((i-1)&1)?0x55:0xAA;
read = test->read(i-1);
if (read != want)
{
printf("Failed [@%8X Want: %02X Get: %02X]", i-1, want, read);
ret |= 1;
break; break;
} }
} }
printf("Ok \n---- Fill with 00 ");
for (i = 0; i < a_mask; i++)
{
if((i&0xffff) == 0)printf("\x8%c", PROGRESS[(i>>16)&3]);
test->write(i, 0);
} }
if(error) printf("RAM1 FAILED\n\n\n");
else printf("RAM1 PASSED\n\n\n"); printf("Ok \n---- Check data lines...\n"
if(failed) return FAILED; "----- ");
for (i = 0; i < test->d_len; i++) printf("%X", i);
printf("\n");
/* Check on 4 addresses, taken evenly */
#define TEST_NUM (10)
for (j = 0; j < TEST_NUM; j ++)
{
printf("----- %8X [", j * a_mask/TEST_NUM);
for (i = 0; i < test->d_len; i++)
{
read = test->read(j * a_mask/TEST_NUM);
if ((test->read(j * a_mask/TEST_NUM) & (1<<i)) != 0)
{
printf("1", read);
ret |= 2;
goto next_data;
}
test->write(j * a_mask/TEST_NUM, (1<<i));
read = test->read(j * a_mask/TEST_NUM);
if (read == 0)
{
printf("0");
ret |= 4;
goto next_data;
}
printf("x");
next_data:
test->write(j * a_mask/4, 0);
}
printf("]\n");
}
test->close();
return ret;
}
int test_mem()
{
int ret = PASSED;
printf("RAM test\n========\n");
if (do_test(&rom) != 0)
ret = FAILED;
if (do_test(&sram) != 0);
ret = FAILED;
return PASSED; return PASSED;
} }
int test_clk() { int test_clk() {
uint32_t sysclk[4]; uint32_t sysclk[4];
int32_t diff, max_diff = 0; int32_t diff, max_diff = 0;

View File

@ -73,7 +73,8 @@ void RIT_IRQHandler(void) {
RIT_Hook(); RIT_Hook();
} }
void timer_init(void) { void timer_init(void)
{
/* turn on power to RIT */ /* turn on power to RIT */
BITBAND(LPC_SC->PCONP, PCRIT) = 1; BITBAND(LPC_SC->PCONP, PCRIT) = 1;
@ -87,7 +88,8 @@ void timer_init(void) {
SysTick_Config((SysTick->CALIB & SysTick_CALIB_TENMS_Msk)); SysTick_Config((SysTick->CALIB & SysTick_CALIB_TENMS_Msk));
} }
void delay_us(unsigned int time) { void delay_us(unsigned int time)
{
/* Prepare RIT */ /* Prepare RIT */
LPC_RIT->RICOUNTER = 0; LPC_RIT->RICOUNTER = 0;
LPC_RIT->RICOMPVAL = (CONFIG_CPU_FREQUENCY / 1000000) * time; LPC_RIT->RICOMPVAL = (CONFIG_CPU_FREQUENCY / 1000000) * time;

View File

@ -18,53 +18,73 @@ extern volatile int reset_pressed;
volatile tick_t ticks; volatile tick_t ticks;
volatile int wokefromrit; volatile int wokefromrit;
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 */
void SysTick_Handler(void) { void SysTick_Handler( void )
{
ticks++; ticks++;
static uint16_t sdch_state = 0; static uint16_t sdch_state = 0;
static uint16_t reset_state = 0; static uint16_t reset_state = 0;
sdch_state = ( sdch_state << 1 ) | SDCARD_DETECT | 0xe000; sdch_state = ( sdch_state << 1 ) | SDCARD_DETECT | 0xe000;
if((sdch_state == 0xf000) || (sdch_state == 0xefff)) {
if ( ( sdch_state == 0xf000 ) || ( sdch_state == 0xefff ) )
{
sd_changed = 1; sd_changed = 1;
} }
reset_state = ( reset_state << 1 ) | get_snes_reset() | 0xe000; reset_state = ( reset_state << 1 ) | get_snes_reset() | 0xe000;
if((reset_state == 0xf000) || (reset_state == 0xefff)) {
if ( ( reset_state == 0xf000 ) || ( reset_state == 0xefff ) )
{
reset_pressed = ( reset_state == 0xf000 ); reset_pressed = ( reset_state == 0xf000 );
reset_changed = 1; reset_changed = 1;
} }
sdn_changed(); sdn_changed();
SysTick_Hook(); SysTick_Hook();
} }
void __attribute__((weak,noinline)) RIT_Hook(void) { void __attribute__( ( weak, noinline ) ) RIT_Hook( void )
{
} }
void RIT_IRQHandler(void) { void RIT_IRQHandler( void )
{
LPC_RIT->RICTRL = BV( RITINT ); LPC_RIT->RICTRL = BV( RITINT );
NVIC_ClearPendingIRQ( RIT_IRQn ); NVIC_ClearPendingIRQ( RIT_IRQn );
wokefromrit = 1; wokefromrit = 1;
RIT_Hook(); RIT_Hook();
} }
void timer_init(void) { void timer_init( void )
{
/* turn on power to RIT */ /* turn on power to RIT */
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_RIT = CCLK */
BITBAND( LPC_SC->PCLKSEL1, 27 ) = 0;
BITBAND( LPC_SC->PCLKSEL1, 26 ) = 1; BITBAND( LPC_SC->PCLKSEL1, 26 ) = 1;
/* PCLK_TIMER3 = CCLK/4 */
BITBAND( LPC_SC->PCLKSEL1, 15 ) = 0;
BITBAND( LPC_SC->PCLKSEL1, 14 ) = 0;
/* enable timer 3 */
BITBAND( LPC_SC->PCLKSEL1, PCLK_TIMER3 ) = 1; BITBAND( LPC_SC->PCLKSEL1, PCLK_TIMER3 ) = 1;
/* enable SysTick */ /* enable SysTick */
SysTick_Config( ( SysTick->CALIB & SysTick_CALIB_TENMS_Msk ) ); SysTick_Config( ( SysTick->CALIB & SysTick_CALIB_TENMS_Msk ) );
} }
void delay_us(unsigned int time) { void delay_us( unsigned int time )
{
/* Prepare RIT */ /* Prepare RIT */
LPC_RIT->RICOUNTER = 0; LPC_RIT->RICOUNTER = 0;
LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000000 ) * time; LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000000 ) * time;
@ -77,7 +97,8 @@ void delay_us(unsigned int time) {
LPC_RIT->RICTRL = 0; LPC_RIT->RICTRL = 0;
} }
void delay_ms(unsigned int time) { void delay_ms( unsigned int time )
{
/* Prepare RIT */ /* Prepare RIT */
LPC_RIT->RICOUNTER = 0; LPC_RIT->RICOUNTER = 0;
LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000 ) * time; LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000 ) * time;
@ -90,7 +111,8 @@ void delay_ms(unsigned int time) {
LPC_RIT->RICTRL = 0; LPC_RIT->RICTRL = 0;
} }
void sleep_ms(unsigned int time) { void sleep_ms( unsigned int time )
{
wokefromrit = 0; wokefromrit = 0;
/* Prepare RIT */ /* Prepare RIT */
@ -101,9 +123,11 @@ void sleep_ms(unsigned int time) {
/* Wait until RIT signals an interrupt */ /* Wait until RIT signals an interrupt */
//uart_putc(';'); //uart_putc(';');
while(!wokefromrit) { while ( !wokefromrit )
{
__WFI(); __WFI();
} }
NVIC_DisableIRQ( RIT_IRQn ); NVIC_DisableIRQ( RIT_IRQn );
/* Disable RIT */ /* Disable RIT */
LPC_RIT->RICTRL = BV( RITINT ); LPC_RIT->RICTRL = BV( RITINT );

View File

@ -42,7 +42,8 @@
#else #else
# error CONFIG_UART_NUM is not set or has an invalid value! # error CONFIG_UART_NUM is not set or has an invalid value!
#endif #endif
static uint8_t uart_lookupratio(float f_fr) { static uint8_t uart_lookupratio( float f_fr )
{
uint16_t errors[72] = {0, 67, 71, 77, 83, 91, 100, 111, 125, uint16_t errors[72] = {0, 67, 71, 77, 83, 91, 100, 111, 125,
133, 143, 154, 167, 182, 200, 214, 222, 231, 133, 143, 154, 167, 182, 200, 214, 222, 231,
250, 267, 273, 286, 300, 308, 333, 357, 364, 250, 267, 273, 286, 300, 308, 333, 357, 364,
@ -50,7 +51,8 @@ static uint8_t uart_lookupratio(float f_fr) {
500, 533, 538, 545, 556, 571, 583, 600, 615, 500, 533, 538, 545, 556, 571, 583, 600, 615,
625, 636, 643, 667, 692, 700, 714, 727, 733, 625, 636, 643, 667, 692, 700, 714, 727, 733,
750, 769, 778, 786, 800, 818, 833, 846, 857, 750, 769, 778, 786, 800, 818, 833, 846, 857,
867,875,889,900,909,917,923,929,933}; 867, 875, 889, 900, 909, 917, 923, 929, 933
};
uint8_t ratios[72] = {0x10, 0xf1, 0xe1, 0xd1, 0xc1, 0xb1, 0xa1, 0x91, 0x81, uint8_t ratios[72] = {0x10, 0xf1, 0xe1, 0xd1, 0xc1, 0xb1, 0xa1, 0x91, 0x81,
0xf2, 0x71, 0xd2, 0x61, 0xb2, 0x51, 0xe3, 0x92, 0xd3, 0xf2, 0x71, 0xd2, 0x61, 0xb2, 0x51, 0xe3, 0x92, 0xd3,
@ -59,26 +61,36 @@ static uint8_t uart_lookupratio(float f_fr) {
0x21, 0xf8, 0xd7, 0xb6, 0x95, 0x74, 0xc7, 0x53, 0xd8, 0x21, 0xf8, 0xd7, 0xb6, 0x95, 0x74, 0xc7, 0x53, 0xd8,
0x85, 0xb7, 0xe9, 0x32, 0xd9, 0xa7, 0x75, 0xb8, 0xfb, 0x85, 0xb7, 0xe9, 0x32, 0xd9, 0xa7, 0x75, 0xb8, 0xfb,
0x43, 0xda, 0x97, 0xeb, 0x54, 0xb9, 0x65, 0xdb, 0x76, 0x43, 0xda, 0x97, 0xeb, 0x54, 0xb9, 0x65, 0xdb, 0x76,
0xfd,0x87,0x98,0xa9,0xba,0xcb,0xdc,0xed,0xfe}; 0xfd, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe
};
int fr = ( f_fr - 1 ) * 1000; int fr = ( f_fr - 1 ) * 1000;
int i = 0, i_result = 0; int i = 0, i_result = 0;
int err = 0, lasterr = 1000; int err = 0, lasterr = 1000;
for(i=0; i<72; i++) {
if(fr<errors[i]) { for ( i = 0; i < 72; i++ )
{
if ( fr < errors[i] )
{
err = errors[i] - fr; err = errors[i] - fr;
} else { }
else
{
err = fr - errors[i]; err = fr - errors[i];
} }
if(err<lasterr) {
if ( err < lasterr )
{
i_result = i; i_result = i;
lasterr = err; lasterr = err;
} }
} }
return ratios[i_result]; return ratios[i_result];
} }
static uint32_t baud2divisor(unsigned int baudrate) { static uint32_t baud2divisor( unsigned int baudrate )
{
uint32_t int_ratio; uint32_t int_ratio;
uint32_t error; uint32_t error;
uint32_t dl = 0; uint32_t dl = 0;
@ -90,18 +102,26 @@ static uint32_t baud2divisor(unsigned int baudrate) {
f_ratio = ( f_pclk / 16 / baudrate ); f_ratio = ( f_pclk / 16 / 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;
} else { }
else
{
return ( ( fract_ratio << 16 ) & 0xff0000 ) | dl; return ( ( fract_ratio << 16 ) & 0xff0000 ) | dl;
} }
} }
@ -109,29 +129,40 @@ static uint32_t baud2divisor(unsigned int baudrate) {
static char txbuf[1 << CONFIG_UART_TX_BUF_SHIFT]; static char txbuf[1 << CONFIG_UART_TX_BUF_SHIFT];
static volatile unsigned int read_idx, write_idx; static volatile unsigned int read_idx, write_idx;
void UART_HANDLER(void) { void UART_HANDLER( void )
{
int iir = UART_REGS->IIR; int iir = UART_REGS->IIR;
if (!(iir & 1)) {
if ( !( iir & 1 ) )
{
/* Interrupt is pending */ /* Interrupt is pending */
switch (iir & 14) { switch ( iir & 14 )
{
#if CONFIG_UART_NUM == 1 #if CONFIG_UART_NUM == 1
case 0: /* modem status */ case 0: /* modem status */
( void ) UART_REGS->MSR; // dummy read to clear ( void ) UART_REGS->MSR; // dummy read to clear
break; break;
#endif #endif
case 2: /* THR empty - send */ case 2: /* THR empty - send */
if (read_idx != write_idx) { if ( read_idx != write_idx )
{
int maxchars = 16; int maxchars = 16;
while (read_idx != write_idx && --maxchars > 0) {
while ( read_idx != write_idx && --maxchars > 0 )
{
UART_REGS->THR = ( unsigned char )txbuf[read_idx]; UART_REGS->THR = ( unsigned char )txbuf[read_idx];
read_idx = ( read_idx + 1 ) & ( sizeof( txbuf ) - 1 ); read_idx = ( read_idx + 1 ) & ( sizeof( txbuf ) - 1 );
} }
if (read_idx == write_idx) {
if ( read_idx == write_idx )
{
/* buffer empty - turn off THRE interrupt */ /* buffer empty - turn off THRE interrupt */
BITBAND( UART_REGS->IER, 1 ) = 0; BITBAND( UART_REGS->IER, 1 ) = 0;
} }
} }
break; break;
case 12: /* RX timeout */ case 12: /* RX timeout */
@ -147,18 +178,26 @@ void UART_HANDLER(void) {
} }
} }
void uart_putc(char c) { void uart_putc( char c )
{
if ( c == '\n' ) if ( c == '\n' )
{
uart_putc( '\r' ); uart_putc( '\r' );
}
unsigned int tmp = ( write_idx + 1 ) & ( sizeof( txbuf ) - 1 ) ; unsigned int tmp = ( write_idx + 1 ) & ( sizeof( txbuf ) - 1 ) ;
if (read_idx == write_idx && (BITBAND(UART_REGS->LSR, 5))) { if ( read_idx == write_idx && ( BITBAND( UART_REGS->LSR, 5 ) ) )
{
/* buffer empty, THR empty -> send immediately */ /* buffer empty, THR empty -> send immediately */
UART_REGS->THR = ( unsigned char )c; UART_REGS->THR = ( unsigned char )c;
} else { }
else
{
#ifdef CONFIG_UART_DEADLOCKABLE #ifdef CONFIG_UART_DEADLOCKABLE
while ( tmp == read_idx ) ; while ( tmp == read_idx ) ;
#endif #endif
BITBAND( UART_REGS->IER, 1 ) = 0; // turn off UART interrupt BITBAND( UART_REGS->IER, 1 ) = 0; // turn off UART interrupt
txbuf[write_idx] = c; txbuf[write_idx] = c;
@ -168,34 +207,45 @@ void uart_putc(char c) {
} }
/* Polling version only */ /* Polling version only */
unsigned char uart_getc(void) { unsigned char uart_getc( void )
{
/* wait for character */ /* wait for character */
while ( !( BITBAND( UART_REGS->LSR, 0 ) ) ) ; while ( !( BITBAND( UART_REGS->LSR, 0 ) ) ) ;
return UART_REGS->RBR; return UART_REGS->RBR;
} }
/* Returns true if a char is ready */ /* Returns true if a char is ready */
unsigned char uart_gotc(void) { unsigned char uart_gotc( void )
{
return BITBAND( UART_REGS->LSR, 0 ); return BITBAND( UART_REGS->LSR, 0 );
} }
void uart_init(void) { void uart_init( void )
{
uint32_t div; uint32_t div;
/* Turn on power to UART */ /* Turn on power to UART */
BITBAND( LPC_SC->PCONP, UART_PCONBIT ) = 1; BITBAND( LPC_SC->PCONP, UART_PCONBIT ) = 1;
/* UART clock = CPU clock - this block is reduced at compile-time */ /* UART clock = CPU clock - this block is reduced at compile-time */
if (CONFIG_UART_PCLKDIV == 1) { if ( CONFIG_UART_PCLKDIV == 1 )
{
BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1; BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0; BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0;
} else if (CONFIG_UART_PCLKDIV == 2) { }
else if ( CONFIG_UART_PCLKDIV == 2 )
{
BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0; BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1; BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1;
} else if (CONFIG_UART_PCLKDIV == 4) { }
else if ( CONFIG_UART_PCLKDIV == 4 )
{
BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0; BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0; BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0;
} else { // Fallback: Divide by 8 }
else // Fallback: Divide by 8
{
BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1; BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1; BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1;
} }
@ -208,7 +258,8 @@ void uart_init(void) {
UART_REGS->DLM = ( div >> 8 ) & 0xff; UART_REGS->DLM = ( div >> 8 ) & 0xff;
BITBAND( UART_REGS->LCR, 7 ) = 0; BITBAND( UART_REGS->LCR, 7 ) = 0;
if (div & 0xff0000) { if ( div & 0xff0000 )
{
UART_REGS->FDR = ( div >> 16 ) & 0xff; UART_REGS->FDR = ( div >> 16 ) & 0xff;
} }
@ -223,67 +274,102 @@ void uart_init(void) {
} }
/* --- generic code below --- */ /* --- generic code below --- */
void uart_puthex(uint8_t num) { void uart_puthex( uint8_t num )
{
uint8_t tmp; uint8_t tmp;
tmp = ( num & 0xf0 ) >> 4; tmp = ( num & 0xf0 ) >> 4;
if (tmp < 10)
uart_putc('0'+tmp);
else
uart_putc('a'+tmp-10);
tmp = num & 0x0f;
if ( tmp < 10 ) if ( tmp < 10 )
{
uart_putc( '0' + tmp ); uart_putc( '0' + tmp );
}
else else
{
uart_putc( 'a' + tmp - 10 ); uart_putc( 'a' + tmp - 10 );
} }
void uart_trace(void *ptr, uint16_t start, uint16_t len) { tmp = num & 0x0f;
if ( tmp < 10 )
{
uart_putc( '0' + tmp );
}
else
{
uart_putc( 'a' + tmp - 10 );
}
}
void uart_trace( void *ptr, uint16_t start, uint16_t len, uint32_t addr )
{
uint16_t i; uint16_t i;
uint8_t j; uint8_t j;
uint8_t ch; uint8_t ch;
uint8_t *data = ptr; uint8_t *data = ptr;
data += start; data += start;
for(i=0;i<len;i+=16) {
uart_puthex(start>>8); for ( i = 0; i < len; i += 16 )
uart_puthex(start&0xff); {
uart_puthex( ( addr + start ) >> 16 );
uart_puthex( ( ( addr + start ) >> 8 ) & 0xff );
uart_puthex( ( addr + start ) & 0xff );
uart_putc( '|' ); uart_putc( '|' );
uart_putc( ' ' ); uart_putc( ' ' );
for(j=0;j<16;j++) {
if(i+j<len) { for ( j = 0; j < 16; j++ )
{
if ( i + j < len )
{
ch = *( data + j ); ch = *( data + j );
uart_puthex( ch ); uart_puthex( ch );
} else { }
else
{
uart_putc( ' ' ); uart_putc( ' ' );
uart_putc( ' ' ); uart_putc( ' ' );
} }
uart_putc( ' ' ); uart_putc( ' ' );
} }
uart_putc( '|' ); uart_putc( '|' );
for(j=0;j<16;j++) {
if(i+j<len) { for ( j = 0; j < 16; j++ )
{
if ( i + j < len )
{
ch = *( data++ ); ch = *( data++ );
if ( ch < 32 || ch > 0x7e ) if ( ch < 32 || ch > 0x7e )
{
ch = '.'; ch = '.';
}
uart_putc( ch ); uart_putc( ch );
} else { }
else
{
uart_putc( ' ' ); uart_putc( ' ' );
} }
} }
uart_putc( '|' ); uart_putc( '|' );
uart_putcrlf(); uart_putcrlf();
start += 16; start += 16;
} }
} }
void uart_flush(void) { void uart_flush( void )
{
while ( read_idx != write_idx ) ; while ( read_idx != write_idx ) ;
} }
void uart_puts(const char *text) { void uart_puts( const char *text )
while (*text) { {
while ( *text )
{
uart_putc( *text++ ); uart_putc( *text++ );
} }
} }

View File

@ -26,7 +26,7 @@ unsigned char uart_gotc(void);
void uart_putc(char c); void uart_putc(char c);
void uart_puts(const char *str); void uart_puts(const char *str);
void uart_puthex(uint8_t num); void uart_puthex(uint8_t num);
void uart_trace(void *ptr, uint16_t start, uint16_t len); void uart_trace(void *ptr, uint16_t start, uint16_t len, uint32_t addr);
void uart_flush(void); void uart_flush(void);
int printf(const char *fmt, ...); int printf(const char *fmt, ...);
int snprintf(char *str, size_t size, const char *format, ...); int snprintf(char *str, size_t size, const char *format, ...);

16
src/uncfgware.c Normal file
View File

@ -0,0 +1,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "cfgware.h"
int main( int argc, char *argv[] )
{
int i;
for ( i = 0; i < sizeof( cfgware ); i++ )
{
printf( "%c", cfgware[i] );
}
return 0;
}

View File

@ -2,11 +2,14 @@
CC = gcc CC = gcc
CFLAGS = -Wall -Wstrict-prototypes -Werror CFLAGS = -Wall -Wstrict-prototypes -Werror
all: lpcchksum genhdr all: lpcchksum genhdr bin2h
genhdr: genhdr.o genhdr: genhdr.o
$(CC) $(CFLAGS) $^ --output $@ $(CC) $(CFLAGS) $^ --output $@
bin2h: bin2h.o
$(CC) $(CFLAGS) $^ --output $@
lpcchksum: lpcchksum.o lpcchksum: lpcchksum.o
$(CC) $(CFLAGS) $^ --output $@ $(CC) $(CFLAGS) $^ --output $@

77
src/utils/bin2h.c Normal file
View File

@ -0,0 +1,77 @@
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] )
{
char var_name[30] = "cfgware";
FILE *fpIn = NULL, *fpOut = NULL;
unsigned char buffer[5], i;
printf( "argc: %d\n", argc );
if ( argc == 4 )
{
fpIn = fopen( argv[1], "rb" );
fpOut = fopen( argv[2], "wt" );
sprintf( var_name, "%s", argv[3] );
}
else if ( argc == 3 )
{
fpIn = fopen( argv[1], "rb" );
fpOut = fopen( argv[2], "wt" );
}
else if ( argc == 2 )
{
fpIn = fopen( argv[1], "rb" );
fpOut = stdout;
}
else if ( argc == 1 )
{
fpIn = stdin;
fpOut = stdout;
}
else
{
fprintf( stderr, "usage: %s [infile] [outfile] [name]\n", argv[0] );
return -1;
}
// if (argc > 1)
// sprintf()
if ( fpIn == NULL )
{
fprintf( stderr, "Can't open '%s`: Aborting.", argv[1] );
return -1;
}
if ( fpOut == NULL )
{
fprintf( stderr, "Can't open '%s`: Aborting.", argv[2] );
return -1;
}
fprintf( fpOut, "const uint8_t %s[] = {\n", var_name );
i = 0;
while ( !feof( fpIn ) )
{
fread( buffer, 1, 1, fpIn );
fprintf( fpOut, "0x%02X, ", buffer[0] );
i++;
if ( i > 8 )
{
fprintf( fpOut, "\n" );
i = 0;
}
}
if ( i > 0 )
{
fprintf( fpOut, "\n" );
}
fprintf( fpOut, "};" );
fclose( fpOut ); fclose( fpIn );
return 0;
}

View File

@ -18,41 +18,56 @@ uint32_t crc_reflect(uint32_t data, size_t data_len)
uint32_t ret; uint32_t ret;
ret = data & 0x01; ret = data & 0x01;
for ( i = 1; i < data_len; i++ ) for ( i = 1; i < data_len; i++ )
{ {
data >>= 1; data >>= 1;
ret = ( ret << 1 ) | ( data & 0x01 ); ret = ( ret << 1 ) | ( data & 0x01 );
} }
return ret; return ret;
} }
uint32_t crc_update(uint32_t crc, const uint8_t *buf, uint32_t len) { uint32_t crc_update( uint32_t crc, const uint8_t *buf, uint32_t len )
{
unsigned int i; unsigned int i;
uint32_t bit; uint32_t bit;
uint8_t c; uint8_t c;
while (len--) { while ( len-- )
{
c = *buf++; c = *buf++;
for (i = 0x01; i & 0xff; i <<= 1) {
for ( i = 0x01; i & 0xff; i <<= 1 )
{
bit = crc & 0x80000000; bit = crc & 0x80000000;
if (c & i) {
if ( c & i )
{
bit = bit ? 0 : 1; bit = bit ? 0 : 1;
} }
crc <<= 1; crc <<= 1;
if (bit) {
if ( bit )
{
crc ^= 0x04c11db7; crc ^= 0x04c11db7;
} }
} }
crc &= 0xffffffff; crc &= 0xffffffff;
} }
return crc & 0xffffffff; return crc & 0xffffffff;
} }
int main(int argc, char **argv) { int main( int argc, char **argv )
{
FILE *f; FILE *f;
size_t flen; size_t flen;
if(argc < 3) { if ( argc < 3 )
{
printf( "Usage: genhdr <input file> <signature> <version>\n" printf( "Usage: genhdr <input file> <signature> <version>\n"
" input file: file to be headered\n" " input file: file to be headered\n"
" signature : magic value at start of header (4-char string)\n" " signature : magic value at start of header (4-char string)\n"
@ -60,33 +75,45 @@ int main(int argc, char **argv) {
"Output is written in place.\n" ); "Output is written in place.\n" );
return 1; return 1;
} }
if((f=fopen(argv[1], "rb+"))==NULL) {
if ( ( f = fopen( argv[1], "rb+" ) ) == NULL )
{
printf( "Unable to open input file %s", argv[1] ); printf( "Unable to open input file %s", argv[1] );
perror( "" ); perror( "" );
return 1; return 1;
} }
fseek( f, 0, SEEK_END ); fseek( f, 0, SEEK_END );
flen = ftell( f ); flen = ftell( f );
if(flen+256 < flen) { if ( flen + 256 < flen )
{
printf( "File too large ;)\n" ); printf( "File too large ;)\n" );
return 1; return 1;
} }
char *remaining = NULL; char *remaining = NULL;
uint32_t version = ( uint32_t )strtol( argv[3], &remaining, 0 ); uint32_t version = ( uint32_t )strtol( argv[3], &remaining, 0 );
if(*remaining) {
if ( *remaining )
{
printf( "could not parse version number (remaining portion: %s)\n", remaining ); printf( "could not parse version number (remaining portion: %s)\n", remaining );
fclose( f ); fclose( f );
return 1; return 1;
} }
if(strlen(argv[2]) > 4) { if ( strlen( argv[2] ) > 4 )
{
printf( "Magic string '%s' too long. Truncated to 4 characters.\n", argv[2] ); printf( "Magic string '%s' too long. Truncated to 4 characters.\n", argv[2] );
} }
uint8_t *buf = malloc( flen + 256 ); uint8_t *buf = malloc( flen + 256 );
if(!buf) {
if ( !buf )
{
perror( "malloc" ); perror( "malloc" );
} }
memset( buf, 0xff, 256 ); memset( buf, 0xff, 256 );
fseek( f, 0, SEEK_SET ); fseek( f, 0, SEEK_SET );
fread( buf + 256, 1, flen, f ); fread( buf + 256, 1, flen, f );

Binary file not shown.

View File

@ -7,30 +7,35 @@
#include <stdint.h> #include <stdint.h>
uint32_t getu32(uint8_t *buffer) { uint32_t getu32( uint8_t *buffer )
{
return buffer[0] + ( buffer[1] << 8 ) + ( buffer[2] << 16 ) + ( buffer[3] << 24 ); return buffer[0] + ( buffer[1] << 8 ) + ( buffer[2] << 16 ) + ( buffer[3] << 24 );
} }
void putu32(uint8_t *buffer, uint32_t data) { void putu32( uint8_t *buffer, uint32_t data )
{
buffer[0] = ( uint8_t )( data & 0xff ); buffer[0] = ( uint8_t )( data & 0xff );
buffer[1] = ( uint8_t )( ( data >> 8 ) & 0xff ); buffer[1] = ( uint8_t )( ( data >> 8 ) & 0xff );
buffer[2] = ( uint8_t )( ( data >> 16 ) & 0xff ); buffer[2] = ( uint8_t )( ( data >> 16 ) & 0xff );
buffer[3] = ( uint8_t )( ( data >> 24 ) & 0xff ); buffer[3] = ( uint8_t )( ( data >> 24 ) & 0xff );
} }
int main(int argc, char **argv) { int main( int argc, char **argv )
{
FILE *bin; FILE *bin;
uint32_t data; uint32_t data;
size_t len; size_t len;
int count; int count;
uint8_t *buffer; uint8_t *buffer;
if(argc<2) { if ( argc < 2 )
{
fprintf( stderr, "Usage: %s <binfile>\nThe original file will be modified!\n", argv[0] ); fprintf( stderr, "Usage: %s <binfile>\nThe original file will be modified!\n", argv[0] );
return 1; return 1;
} }
if((bin=fopen(argv[1], "rb"))==NULL) { if ( ( bin = fopen( argv[1], "rb" ) ) == NULL )
{
perror( "could not open input file" ); perror( "could not open input file" );
return 1; return 1;
} }
@ -38,22 +43,29 @@ int main(int argc, char **argv) {
fseek( bin, 0, SEEK_END ); fseek( bin, 0, SEEK_END );
len = ftell( bin ); len = ftell( bin );
fseek( bin, 0, SEEK_SET ); fseek( bin, 0, SEEK_SET );
if((buffer=malloc(len))==NULL) {
if ( ( buffer = malloc( len ) ) == NULL )
{
perror( "could not reserve memory" ); perror( "could not reserve memory" );
fclose( bin ); fclose( bin );
return 1; return 1;
} }
fread( buffer, len, 1, bin ); fread( buffer, len, 1, bin );
fclose( bin ); fclose( bin );
data = 0; data = 0;
for(count=0; count<7; count++) {
for ( count = 0; count < 7; count++ )
{
data += getu32( buffer + 4 * count ); data += getu32( buffer + 4 * count );
} }
printf( "data=%x chksum=%x\n", data, ~data + 1 ); printf( "data=%x chksum=%x\n", data, ~data + 1 );
putu32( buffer + 28, ~data + 1 ); putu32( buffer + 28, ~data + 1 );
if((bin=fopen(argv[1], "wb"))==NULL) { if ( ( bin = fopen( argv[1], "wb" ) ) == NULL )
{
perror( "could not open output file" ); perror( "could not open output file" );
return 1; return 1;
} }

Binary file not shown.

View File

@ -5,7 +5,8 @@
#include "ff.h" #include "ff.h"
#include "xmodem.h" #include "xmodem.h"
void xmodem_rxfile(FIL* fil) { void xmodem_rxfile( FIL *fil )
{
uint8_t rxbuf[XMODEM_BLKSIZE], sum = 0, sender_sum; uint8_t rxbuf[XMODEM_BLKSIZE], sum = 0, sender_sum;
uint8_t blknum, blknum2; uint8_t blknum, blknum2;
uint8_t count; uint8_t count;
@ -14,24 +15,36 @@ void xmodem_rxfile(FIL* fil) {
UINT written; UINT written;
FRESULT res; FRESULT res;
uart_flush(); uart_flush();
do {
do
{
delay_ms( 3000 ); delay_ms( 3000 );
uart_putc( ASC_NAK ); uart_putc( ASC_NAK );
} while (uart_getc() != ASC_SOH); }
do { while ( uart_getc() != ASC_SOH );
do
{
blknum = uart_getc(); blknum = uart_getc();
blknum2 = uart_getc(); blknum2 = uart_getc();
for(count=0; count<XMODEM_BLKSIZE; count++) {
for ( count = 0; count < XMODEM_BLKSIZE; count++ )
{
sum += rxbuf[count] = uart_getc(); sum += rxbuf[count] = uart_getc();
totalbytes++; totalbytes++;
} }
sender_sum = uart_getc();
/*sender_sum =*/ uart_getc();
res = f_write( fil, rxbuf, XMODEM_BLKSIZE, &written ); res = f_write( fil, rxbuf, XMODEM_BLKSIZE, &written );
totalwritten += written; totalwritten += written;
uart_putc( ASC_ACK ); uart_putc( ASC_ACK );
} while (uart_getc() != ASC_EOT); }
while ( uart_getc() != ASC_EOT );
uart_putc( ASC_ACK ); uart_putc( ASC_ACK );
uart_flush(); uart_flush();
sleep_ms( 1000 ); sleep_ms( 1000 );
sender_sum = blknum + blknum2;
printf( "%x:%x:%x\n", blknum, blknum2, sender_sum );
printf( "received %ld bytes, wrote %ld bytes. last res = %d\n", totalbytes, totalwritten, res ); printf( "received %ld bytes, wrote %ld bytes. last res = %d\n", totalbytes, totalwritten, res );
} }

View File

@ -33,6 +33,7 @@ module address(
output msu_enable, output msu_enable,
output srtc_enable, output srtc_enable,
output use_bsx, output use_bsx,
output bsx_tristate,
input [14:0] bsx_regs, input [14:0] bsx_regs,
output dspx_enable, output dspx_enable,
output dspx_dp_enable, output dspx_dp_enable,
@ -71,20 +72,51 @@ wire [23:0] SRAM_SNES_ADDR;
assign IS_ROM = ((!SNES_ADDR[22] & SNES_ADDR[15]) assign IS_ROM = ((!SNES_ADDR[22] & SNES_ADDR[15])
|(SNES_ADDR[22])); |(SNES_ADDR[22]));
/* HiROM SRAM is 8K end at 0x8000 and is at bank 0x20 and 0xA0 */
assign IS_SAVERAM_HIROM = ((SNES_ADDR[22:21] == 2'b01)
& SNES_ADDR[15:13] == 3'b011)
/* LoROM: SRAM @ Bank 0x70-0x7d, 0xf0-0xfd Offset 0000-7fff
TODO: 0000-ffff for small ROMs? */
assign IS_SAVERAM_LOROM = SNES_ADDR[22:16] == 7'b111
( &SNES_ADDR[22:20]
& (SNES_ADDR[19:16] < 4'b1110)
& !SNES_ADDR[15] )
assign IS_SAVERAM_EXHIROM = (!SNES_ADDR[22]
& SNES_ADDR[21]
& &SNES_ADDR[14:13]
& !SNES_ADDR[15])
assign IS_SAVERAM_BSX = ( (SNES_ADDR[23:19] == 5'b00010)
& (SNES_ADDR[15:12] == 4'b0101)
)
assign IS_SAVERAM_STARTOCEAN = (!SNES_ADDR[22]
& SNES_ADDR[21]
& &SNES_ADDR[14:13]
& !SNES_ADDR[15])
assign IS_SAVERAM_MENU = (!SNES_ADDR[22]
& SNES_ADDR[21]
& &SNES_ADDR[14:13]
& !SNES_ADDR[15])
assign IS_SAVERAM = SAVERAM_MASK[0] assign IS_SAVERAM = SAVERAM_MASK[0]
&(featurebits[FEAT_ST0010] &(featurebits[FEAT_ST0010]
?((SNES_ADDR[22:19] == 4'b1101) ?((SNES_ADDR[22:19] == 4'b1101)
& &(~SNES_ADDR[15:12]) & &(~SNES_ADDR[15:12])
& SNES_ADDR[11]) & SNES_ADDR[11])
:((MAPPER == 3'b000 :(
( MAPPER == 3'b000
|| MAPPER == 3'b010 || MAPPER == 3'b010
|| MAPPER == 3'b110 || MAPPER == 3'b110
|| MAPPER == 3'b111) || MAPPER == 3'b111)
? (!SNES_ADDR[22] ? (!SNES_ADDR[22]
& SNES_ADDR[21] & SNES_ADDR[21]
& &SNES_ADDR[14:13] & &SNES_ADDR[14:13]
& !SNES_ADDR[15] & !SNES_ADDR[15])
)
/* LoROM: SRAM @ Bank 0x70-0x7d, 0xf0-0xfd Offset 0000-7fff /* LoROM: SRAM @ Bank 0x70-0x7d, 0xf0-0xfd Offset 0000-7fff
TODO: 0000-ffff for small ROMs? */ TODO: 0000-ffff for small ROMs? */
:(MAPPER == 3'b001) :(MAPPER == 3'b001)
@ -97,21 +129,44 @@ assign IS_SAVERAM = SAVERAM_MASK[0]
? ( (SNES_ADDR[23:19] == 5'b00010) ? ( (SNES_ADDR[23:19] == 5'b00010)
& (SNES_ADDR[15:12] == 4'b0101) & (SNES_ADDR[15:12] == 4'b0101)
) )
: 1'b0)); : 1'b0
)
);
/* BS-X has 4 MBits of extra RAM that can be mapped to various places */ /* BS-X has 4 MBits of extra RAM that can be mapped to various places */
wire [2:0] BSX_PSRAM_BANK = {bsx_regs[2], bsx_regs[6], bsx_regs[5]};
wire [23:0] BSX_CHKADDR = bsx_regs[2] ? SNES_ADDR : {SNES_ADDR[23], 1'b0, SNES_ADDR[22:16], SNES_ADDR[14:0]};
wire BSX_PSRAM_LOHI = (bsx_regs[3] & ~SNES_ADDR[23]) | (bsx_regs[4] & SNES_ADDR[23]);
wire BSX_IS_PSRAM = BSX_PSRAM_LOHI
& (( (BSX_CHKADDR[22:20] == BSX_PSRAM_BANK)
&(SNES_ADDR[15] | bsx_regs[2])
&(~(SNES_ADDR[19] & bsx_regs[2])))
| (bsx_regs[2]
? (SNES_ADDR[22:21] == 2'b01 & SNES_ADDR[15:13] == 3'b011)
: (&SNES_ADDR[22:20] & ~SNES_ADDR[15]))
);
wire BSX_IS_CARTROM = ((bsx_regs[7] & (SNES_ADDR[23:22] == 2'b00))
|(bsx_regs[8] & (SNES_ADDR[23:22] == 2'b10)))
& SNES_ADDR[15];
wire BSX_HOLE_LOHI = (bsx_regs[9] & ~SNES_ADDR[23]) | (bsx_regs[10] & SNES_ADDR[23]);
wire BSX_IS_HOLE = BSX_HOLE_LOHI
& (bsx_regs[2] ? (SNES_ADDR[21:20] == {bsx_regs[11], 1'b0})
: (SNES_ADDR[22:21] == {bsx_regs[11], 1'b0}));
assign bsx_tristate = (MAPPER == 3'b011) & ~BSX_IS_CARTROM & ~BSX_IS_PSRAM & BSX_IS_HOLE;
assign IS_WRITABLE = IS_SAVERAM assign IS_WRITABLE = IS_SAVERAM
|((MAPPER == 3'b011) |((MAPPER == 3'b011)
?((bsx_regs[3] && SNES_ADDR[23:20]==4'b0110) ? BSX_IS_PSRAM
|(!bsx_regs[5] && SNES_ADDR[23:20]==4'b0100)
|(!bsx_regs[6] && SNES_ADDR[23:20]==4'b0101)
|(SNES_ADDR[23:19] == 5'b01110)
|(SNES_ADDR[23:21] == 3'b001
&& SNES_ADDR[15:13] == 3'b011)
)
: 1'b0); : 1'b0);
wire [23:0] BSX_ADDR = bsx_regs[2] ? {1'b0, SNES_ADDR[22:0]}
: {2'b00, SNES_ADDR[22:16], SNES_ADDR[14:0]};
/* BSX regs: /* BSX regs:
Index Function Index Function
1 0=map flash to ROM area; 1=map PRAM to ROM area 1 0=map flash to ROM area; 1=map PRAM to ROM area
@ -125,25 +180,25 @@ assign IS_WRITABLE = IS_SAVERAM
assign SRAM_SNES_ADDR = ((MAPPER == 3'b000) assign SRAM_SNES_ADDR = ((MAPPER == 3'b000)
?(IS_SAVERAM ?(IS_SAVERAM
? 24'hE00000 + ((SNES_ADDR[14:0] - 15'h6000) ? 24'h600000 + ((SNES_ADDR[14:0] - 15'h6000)
& SAVERAM_MASK) & SAVERAM_MASK)
: ({1'b0, SNES_ADDR[22:0]} & ROM_MASK)) : ({1'b0, SNES_ADDR[22:0]} & ROM_MASK))
:(MAPPER == 3'b001) :(MAPPER == 3'b001)
?(IS_SAVERAM ?(IS_SAVERAM
? 24'hE00000 + (SNES_ADDR[14:0] & SAVERAM_MASK) ? 24'h600000 + (SNES_ADDR[14:0] & SAVERAM_MASK)
: ({2'b00, SNES_ADDR[22:16], SNES_ADDR[14:0]} : ({2'b00, SNES_ADDR[22:16], SNES_ADDR[14:0]}
& ROM_MASK)) & ROM_MASK))
:(MAPPER == 3'b010) :(MAPPER == 3'b010)
?(IS_SAVERAM ?(IS_SAVERAM
? 24'hE00000 + ((SNES_ADDR[14:0] - 15'h6000) ? 24'h600000 + ((SNES_ADDR[14:0] - 15'h6000)
& SAVERAM_MASK) & SAVERAM_MASK)
: ({1'b0, !SNES_ADDR[23], SNES_ADDR[21:0]} : ({1'b0, !SNES_ADDR[23], SNES_ADDR[21:0]}
& ROM_MASK)) & ROM_MASK))
:(MAPPER == 3'b011) :(MAPPER == 3'b011)
?(IS_SAVERAM ?(IS_SAVERAM
? 24'hE00000 + {SNES_ADDR[18:16], SNES_ADDR[11:0]} ? 24'h600000 + {SNES_ADDR[18:16], SNES_ADDR[11:0]}
: IS_WRITABLE : IS_WRITABLE
? (24'h400000 + (SNES_ADDR & 24'h07FFFF)) ? (24'h400000 + (SNES_ADDR & 24'h07FFFF))
: bs_page_enable : bs_page_enable
@ -169,7 +224,7 @@ assign SRAM_SNES_ADDR = ((MAPPER == 3'b000)
) )
:(MAPPER == 3'b110) :(MAPPER == 3'b110)
?(IS_SAVERAM ?(IS_SAVERAM
? 24'hE00000 + ((SNES_ADDR[14:0] - 15'h6000) ? 24'h600000 + ((SNES_ADDR[14:0] - 15'h6000)
& SAVERAM_MASK) & SAVERAM_MASK)
:(SNES_ADDR[15] :(SNES_ADDR[15]
?({1'b0, SNES_ADDR[23:16], SNES_ADDR[14:0]}) ?({1'b0, SNES_ADDR[23:16], SNES_ADDR[14:0]})
@ -182,7 +237,7 @@ assign SRAM_SNES_ADDR = ((MAPPER == 3'b000)
) )
:(MAPPER == 3'b111) :(MAPPER == 3'b111)
?(IS_SAVERAM ?(IS_SAVERAM
? 24'hFF0000 + ((SNES_ADDR[14:0] - 15'h6000) ? 24'h7F0000 + ((SNES_ADDR[14:0] - 15'h6000)
& SAVERAM_MASK) & SAVERAM_MASK)
: (({1'b0, SNES_ADDR[22:0]} & ROM_MASK) : (({1'b0, SNES_ADDR[22:0]} & ROM_MASK)
+ 24'hC00000) + 24'hC00000)

View File

@ -135,8 +135,8 @@ wire [7:0] rtc_year100 = rtc_data[51:48] + (rtc_data[55:52] << 3) + (rtc_data[55
wire [15:0] rtc_year = (rtc_year100 << 6) + (rtc_year100 << 5) + (rtc_year100 << 2) + rtc_year1; wire [15:0] rtc_year = (rtc_year100 << 6) + (rtc_year100 << 5) + (rtc_year100 << 2) + rtc_year1;
initial begin initial begin
regs_tmpr <= 15'b000000100000000; regs_tmpr <= 15'b000101111101100;
regs_outr <= 15'b000000100000000; regs_outr <= 15'b000101111101100;
bsx_counter <= 0; bsx_counter <= 0;
base_regs[5'h08] <= 0; base_regs[5'h08] <= 0;
base_regs[5'h09] <= 0; base_regs[5'h09] <= 0;
@ -213,7 +213,7 @@ always @(posedge clkin) begin
14: reg_data_outr <= rtc_day; 14: reg_data_outr <= rtc_day;
15: reg_data_outr <= rtc_month; 15: reg_data_outr <= rtc_month;
16: reg_data_outr <= rtc_year[7:0]; 16: reg_data_outr <= rtc_year[7:0];
17: reg_data_outr <= rtc_year[15:8]; 17: reg_data_outr <= rtc_hour;
default: reg_data_outr <= 8'h0; default: reg_data_outr <= 8'h0;
endcase endcase
end end
@ -240,8 +240,8 @@ always @(posedge clkin) begin
regs_tmpr[8:1] <= (regs_tmpr[8:1] | reg_set_bits[7:0]) & ~reg_reset_bits[7:0]; regs_tmpr[8:1] <= (regs_tmpr[8:1] | reg_set_bits[7:0]) & ~reg_reset_bits[7:0];
regs_outr[8:1] <= (regs_outr[8:1] | reg_set_bits[7:0]) & ~reg_reset_bits[7:0]; regs_outr[8:1] <= (regs_outr[8:1] | reg_set_bits[7:0]) & ~reg_reset_bits[7:0];
end else if(reg_we_rising && cart_enable) begin end else if(reg_we_rising && cart_enable) begin
if(reg_addr == 4'he && reg_data_in[7]) if(reg_addr == 4'he)
regs_outr <= regs_tmpr | 15'b100000000000000; regs_outr <= regs_tmpr;
else else
regs_tmpr[reg_addr] <= reg_data_in[7]; regs_tmpr[reg_addr] <= reg_data_in[7];
end else if(reg_we_rising && base_enable) begin end else if(reg_we_rising && base_enable) begin

View File

@ -440,6 +440,7 @@ address snes_addr(
.bs_page_offset(bs_page_offset), .bs_page_offset(bs_page_offset),
.bs_page(bs_page), .bs_page(bs_page),
.bs_page_enable(bs_page_enable), .bs_page_enable(bs_page_enable),
.bsx_tristate(bsx_tristate),
//SRTC //SRTC
.srtc_enable(srtc_enable), .srtc_enable(srtc_enable),
//uPD77C25 //uPD77C25
@ -472,10 +473,10 @@ parameter ST_MCU_WR_WAIT = 18'b000100000000000000;
parameter ST_MCU_WR_WAIT2 = 18'b001000000000000000; parameter ST_MCU_WR_WAIT2 = 18'b001000000000000000;
parameter ST_MCU_WR_END = 18'b010000000000000000; parameter ST_MCU_WR_END = 18'b010000000000000000;
parameter ROM_RD_WAIT = 4'h0; parameter ROM_RD_WAIT = 4'h1;
parameter ROM_RD_WAIT_MCU = 4'h6; parameter ROM_RD_WAIT_MCU = 4'h6;
parameter ROM_WR_WAIT = 4'h4; parameter ROM_WR_WAIT = 4'h4;
parameter ROM_WR_WAIT1 = 4'h2; parameter ROM_WR_WAIT1 = 4'h3;
parameter ROM_WR_WAIT2 = 4'h1; parameter ROM_WR_WAIT2 = 4'h1;
parameter ROM_WR_WAIT_MCU = 4'h5; parameter ROM_WR_WAIT_MCU = 4'h5;
@ -533,8 +534,12 @@ initial ROM_SAr = 1'b1;
//wire ROM_SA = SNES_FAKE_CLK | ((STATE == ST_IDLE) ^ (~RQ_MCU_RDYr & SNES_cycle_end)); //wire ROM_SA = SNES_FAKE_CLK | ((STATE == ST_IDLE) ^ (~RQ_MCU_RDYr & SNES_cycle_end));
wire ROM_SA = ROM_SAr; wire ROM_SA = ROM_SAr;
assign ROM_ADDR = (SD_DMA_TO_ROM) ? MCU_ADDR[23:1] : (ROM_SA) ? MAPPED_SNES_ADDR[23:1] : ROM_ADDRr[23:1]; //assign ROM_ADDR = (SD_DMA_TO_ROM) ? MCU_ADDR[23:1] : (ROM_SA) ? MAPPED_SNES_ADDR[23:1] : ROM_ADDRr[23:1];
assign ROM_ADDR0 = (SD_DMA_TO_ROM) ? MCU_ADDR[0] : (ROM_SA) ? MAPPED_SNES_ADDR[0] : ROM_ADDRr[0]; //assign ROM_ADDR0 = (SD_DMA_TO_ROM) ? MCU_ADDR[0] : (ROM_SA) ? MAPPED_SNES_ADDR[0] : ROM_ADDRr[0];
//WARNING DUE TO BAD SOLDER WE LOST HALF OF THE PSRAM!!!
assign ROM_ADDR = (SD_DMA_TO_ROM) ? MCU_ADDR[22:0] : (ROM_SA) ? MAPPED_SNES_ADDR[22:0] : ROM_ADDRr[22:0];
assign ROM_ADDR0 = 1'b0; //(SD_DMA_TO_ROM) ? MCU_ADDR[0] : (ROM_SA) ? MAPPED_SNES_ADDR[0] : ROM_ADDRr[0];
reg ROM_WEr; reg ROM_WEr;
initial ROM_WEr = 1'b1; initial ROM_WEr = 1'b1;
@ -581,14 +586,12 @@ always @(posedge CLK2) begin
ROM_DOUT_ENr <= 1'b0; ROM_DOUT_ENr <= 1'b0;
if(SNES_cycle_start & ~SNES_WRITE) begin if(SNES_cycle_start & ~SNES_WRITE) begin
STATE <= ST_SNES_WR_ADDR; STATE <= ST_SNES_WR_ADDR;
if(IS_SAVERAM | IS_WRITABLE | IS_FLASHWR) begin if(IS_WRITABLE | (IS_FLASHWR & ~bsx_tristate)) begin
ROM_WEr <= 1'b0; ROM_WEr <= 1'b0;
ROM_DOUT_ENr <= 1'b1;
end end
end else if(SNES_cycle_start) begin end else if(SNES_cycle_start) begin
// STATE <= ST_SNES_RD_ADDR; STATE <= ST_SNES_RD_ADDR;
STATE <= ST_SNES_RD_END; // STATE <= ST_SNES_RD_END;
SNES_DOUTr <= (ROM_ADDR0 ? ROM_DATA[7:0] : ROM_DATA[15:8]);
end else if(SNES_DEADr & MCU_RD_PENDr) begin end else if(SNES_DEADr & MCU_RD_PENDr) begin
STATE <= ST_MCU_RD_ADDR; STATE <= ST_MCU_RD_ADDR;
end else if(SNES_DEADr & MCU_WR_PENDr) begin end else if(SNES_DEADr & MCU_WR_PENDr) begin
@ -601,12 +604,15 @@ always @(posedge CLK2) begin
end end
ST_SNES_RD_WAIT: begin ST_SNES_RD_WAIT: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 1; ST_MEM_DELAYr <= ST_MEM_DELAYr - 1;
// if(ST_MEM_DELAYr == 0) begin if(ST_MEM_DELAYr == 0) begin
// end STATE <= ST_SNES_RD_END;
// else STATE <= ST_SNES_RD_WAIT; SNES_DOUTr <= (ROM_ADDR0 ? ROM_DATA[7:0] : ROM_DATA[15:8]);
end
else STATE <= ST_SNES_RD_WAIT;
end end
ST_SNES_WR_ADDR: begin ST_SNES_WR_ADDR: begin
ROM_DOUT_ENr <= 1'b1;
ST_MEM_DELAYr <= ROM_WR_WAIT1; ST_MEM_DELAYr <= ROM_WR_WAIT1;
STATE <= ST_SNES_WR_WAIT1; STATE <= ST_SNES_WR_WAIT1;
end end
@ -624,11 +630,12 @@ always @(posedge CLK2) begin
if(ST_MEM_DELAYr == 0) begin if(ST_MEM_DELAYr == 0) begin
STATE <= ST_SNES_WR_END; STATE <= ST_SNES_WR_END;
ROM_WEr <= 1'b1; ROM_WEr <= 1'b1;
ROM_DOUT_ENr <= 1'b0;
end end
else STATE <= ST_SNES_WR_WAIT2; else STATE <= ST_SNES_WR_WAIT2;
end end
ST_SNES_RD_END, ST_SNES_WR_END: begin ST_SNES_RD_END, ST_SNES_WR_END: begin
ROM_DOUT_ENr <= 1'b0; // ROM_DOUT_ENr <= 1'b0;
if(MCU_RD_PENDr) begin if(MCU_RD_PENDr) begin
STATE <= ST_MCU_RD_ADDR; STATE <= ST_MCU_RD_ADDR;
end else if(MCU_WR_PENDr) begin end else if(MCU_WR_PENDr) begin
@ -648,7 +655,7 @@ always @(posedge CLK2) begin
else STATE <= ST_MCU_RD_WAIT; else STATE <= ST_MCU_RD_WAIT;
end end
ST_MCU_RD_END: begin ST_MCU_RD_END: begin
MCU_DINr <= ROM_ADDRr[0] ? ROM_DATA[7:0] : ROM_DATA[15:8]; MCU_DINr <= ROM_DATA[7:0] | ROM_DATA[15:8]; /*ROM_ADDRr[0] ? ROM_DATA[7:0] : ROM_DATA[15:8];*/
STATE <= ST_IDLE; STATE <= ST_IDLE;
end end
@ -657,11 +664,11 @@ always @(posedge CLK2) begin
ROM_SAr <= 1'b0; ROM_SAr <= 1'b0;
ST_MEM_DELAYr <= ROM_WR_WAIT_MCU; ST_MEM_DELAYr <= ROM_WR_WAIT_MCU;
STATE <= ST_MCU_WR_WAIT; STATE <= ST_MCU_WR_WAIT;
ROM_DOUT_ENr <= 1'b1;
ROM_WEr <= 1'b0; ROM_WEr <= 1'b0;
end end
ST_MCU_WR_WAIT: begin ST_MCU_WR_WAIT: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 1; ST_MEM_DELAYr <= ST_MEM_DELAYr - 1;
ROM_DOUT_ENr <= 1'b1;
if(ST_MEM_DELAYr == 0) begin if(ST_MEM_DELAYr == 0) begin
ROM_WEr <= 1'b1; ROM_WEr <= 1'b1;
STATE <= ST_MCU_WR_END; STATE <= ST_MCU_WR_END;
@ -704,18 +711,25 @@ always @(posedge CLK2) begin
MCU_WRITE_1<= MCU_WRITE; MCU_WRITE_1<= MCU_WRITE;
end end
/*
assign ROM_DATA[7:0] = ROM_ADDR0 assign ROM_DATA[7:0] = ROM_ADDR0
?(SD_DMA_TO_ROM ? (!MCU_WRITE_1 ? MCU_DOUT : 8'bZ) ?(SD_DMA_TO_ROM ? (!MCU_WRITE_1 ? MCU_DOUT : 8'bZ)
/*: ((~SNES_WRITE & (IS_WRITABLE | IS_FLASHWR)) ? SNES_DATA */ //: ((~SNES_WRITE & (IS_WRITABLE | IS_FLASHWR)) ? SNES_DATA
: (ROM_DOUT_ENr ? ROM_DOUTr : 8'bZ) //) : (ROM_DOUT_ENr ? ROM_DOUTr : 8'bZ) //)
) )
:8'bZ; :8'bZ;
assign ROM_DATA[15:8] = ROM_ADDR0 ? 8'bZ assign ROM_DATA[15:8] = ROM_ADDR0 ? 8'bZ
:(SD_DMA_TO_ROM ? (!MCU_WRITE_1 ? MCU_DOUT : 8'bZ) :(SD_DMA_TO_ROM ? (!MCU_WRITE_1 ? MCU_DOUT : 8'bZ)
/*: ((~SNES_WRITE & (IS_WRITABLE | IS_FLASHWR)) ? SNES_DATA */ //: ((~SNES_WRITE & (IS_WRITABLE | IS_FLASHWR)) ? SNES_DATA
: (ROM_DOUT_ENr ? ROM_DOUTr : 8'bZ) //) : (ROM_DOUT_ENr ? ROM_DOUTr : 8'bZ) //)
); );
*/
assign ROM_DATA[7:0] = SD_DMA_TO_ROM ? (!MCU_WRITE_1 ? MCU_DOUT : 8'bZ)
: (ROM_DOUT_ENr ? ROM_DOUTr : 8'bZ);
assign ROM_DATA[15:8] = SD_DMA_TO_ROM ? (!MCU_WRITE_1 ? MCU_DOUT : 8'bZ)
: (ROM_DOUT_ENr ? ROM_DOUTr : 8'bZ);
assign ROM_WE = SD_DMA_TO_ROM assign ROM_WE = SD_DMA_TO_ROM
?MCU_WRITE ?MCU_WRITE
@ -726,8 +740,8 @@ assign ROM_OE = 1'b0;
assign ROM_CE = 1'b0; assign ROM_CE = 1'b0;
assign ROM_BHE = /*(~SD_DMA_TO_ROM & ~ROM_WE & ~ROM_SA) ?*/ ROM_ADDR0 /*: 1'b0*/; assign ROM_BHE = 1'b0; ///*(~SD_DMA_TO_ROM & ~ROM_WE & ~ROM_SA) ?*/ ROM_ADDR0 /*: 1'b0*/;
assign ROM_BLE = /*(~SD_DMA_TO_ROM & ~ROM_WE & ~ROM_SA) ?*/ !ROM_ADDR0 /*: 1'b0*/; assign ROM_BLE = 1'b0; ///*(~SD_DMA_TO_ROM & ~ROM_WE & ~ROM_SA) ?*/ !ROM_ADDR0 /*: 1'b0*/;
assign SNES_DATABUS_OE = (dspx_enable | dspx_dp_enable) ? 1'b0 : assign SNES_DATABUS_OE = (dspx_enable | dspx_dp_enable) ? 1'b0 :
msu_enable ? 1'b0 : msu_enable ? 1'b0 :
@ -739,6 +753,7 @@ assign SNES_DATABUS_OE = (dspx_enable | dspx_dp_enable) ? 1'b0 :
((IS_ROM & SNES_CS) ((IS_ROM & SNES_CS)
|(!IS_ROM & !IS_SAVERAM & !IS_WRITABLE & !IS_FLASHWR) |(!IS_ROM & !IS_SAVERAM & !IS_WRITABLE & !IS_FLASHWR)
|(SNES_READr[0] & SNES_WRITEr[0]) |(SNES_READr[0] & SNES_WRITEr[0])
| bsx_tristate
); );
assign SNES_DATABUS_DIR = (!SNES_READr[0] | (!SNES_PARD & (r213f_enable | snescmd_rd_enable))) assign SNES_DATABUS_DIR = (!SNES_READr[0] | (!SNES_PARD & (r213f_enable | snescmd_rd_enable)))
@ -747,7 +762,7 @@ assign SNES_DATABUS_DIR = (!SNES_READr[0] | (!SNES_PARD & (r213f_enable | snescm
assign SNES_IRQ = 1'b0; assign SNES_IRQ = 1'b0;
assign p113_out = 1'b0; assign p113_out = 1'b1;
/* /*
wire [35:0] CONTROL0; wire [35:0] CONTROL0;

View File

@ -12,7 +12,7 @@
<!-- Copyright (c) 1995-2012 Xilinx, Inc. All rights reserved. --> <!-- Copyright (c) 1995-2012 Xilinx, Inc. All rights reserved. -->
</header> </header>
<version xil_pn:ise_version="14.1" xil_pn:schema_version="2"/> <version xil_pn:ise_version="14.2" xil_pn:schema_version="2"/>
<files> <files>
<file xil_pn:name="address.v" xil_pn:type="FILE_VERILOG"> <file xil_pn:name="address.v" xil_pn:type="FILE_VERILOG">

View File

@ -370,13 +370,13 @@ parameter ST_CX4_RD_ADDR = 21'b000100000000000000000;
parameter ST_CX4_RD_WAIT = 21'b001000000000000000000; parameter ST_CX4_RD_WAIT = 21'b001000000000000000000;
parameter ST_CX4_RD_END = 21'b010000000000000000000; parameter ST_CX4_RD_END = 21'b010000000000000000000;
parameter ROM_RD_WAIT = 4'h0; parameter ROM_RD_WAIT = 4'h1;
parameter ROM_RD_WAIT_MCU = 4'h6; parameter ROM_RD_WAIT_MCU = 4'h6;
parameter ROM_WR_WAIT = 4'h4; parameter ROM_WR_WAIT = 4'h4;
parameter ROM_WR_WAIT1 = 4'h2; parameter ROM_WR_WAIT1 = 4'h3;
parameter ROM_WR_WAIT2 = 4'h1; parameter ROM_WR_WAIT2 = 4'h1;
parameter ROM_WR_WAIT_MCU = 4'h5; parameter ROM_WR_WAIT_MCU = 4'h5;
parameter ROM_RD_WAIT_CX4 = 4'h6; parameter ROM_RD_WAIT_CX4 = 4'h7;
parameter SNES_DEAD_TIMEOUT = 17'd88000; // 1ms parameter SNES_DEAD_TIMEOUT = 17'd88000; // 1ms
@ -510,9 +510,8 @@ always @(posedge CLK2) begin
ROM_DOUT_ENr <= 1'b1; ROM_DOUT_ENr <= 1'b1;
end end
end else if(SNES_cycle_start) begin end else if(SNES_cycle_start) begin
// STATE <= ST_SNES_RD_ADDR; STATE <= ST_SNES_RD_ADDR;
STATE <= ST_SNES_RD_END; // STATE <= ST_SNES_RD_END;
SNES_DOUTr <= (ROM_ADDR0 ? ROM_DATA[7:0] : ROM_DATA[15:8]);
end else if(SNES_DEADr & MCU_RD_PENDr) begin end else if(SNES_DEADr & MCU_RD_PENDr) begin
STATE <= ST_MCU_RD_ADDR; STATE <= ST_MCU_RD_ADDR;
end else if(SNES_DEADr & MCU_WR_PENDr) begin end else if(SNES_DEADr & MCU_WR_PENDr) begin
@ -525,12 +524,15 @@ always @(posedge CLK2) begin
end end
ST_SNES_RD_WAIT: begin ST_SNES_RD_WAIT: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 1; ST_MEM_DELAYr <= ST_MEM_DELAYr - 1;
// if(ST_MEM_DELAYr == 0) begin if(ST_MEM_DELAYr == 0) begin
// end STATE <= ST_SNES_RD_END;
// else STATE <= ST_SNES_RD_WAIT; SNES_DOUTr <= (ROM_ADDR0 ? ROM_DATA[7:0] : ROM_DATA[15:8]);
end
else STATE <= ST_SNES_RD_WAIT;
end end
ST_SNES_WR_ADDR: begin ST_SNES_WR_ADDR: begin
ROM_DOUT_ENr <= 1'b1;
ST_MEM_DELAYr <= ROM_WR_WAIT1; ST_MEM_DELAYr <= ROM_WR_WAIT1;
STATE <= ST_SNES_WR_WAIT1; STATE <= ST_SNES_WR_WAIT1;
end end
@ -552,7 +554,7 @@ always @(posedge CLK2) begin
else STATE <= ST_SNES_WR_WAIT2; else STATE <= ST_SNES_WR_WAIT2;
end end
ST_SNES_RD_END, ST_SNES_WR_END: begin ST_SNES_RD_END, ST_SNES_WR_END: begin
ROM_DOUT_ENr <= 1'b0; // ROM_DOUT_ENr <= 1'b0;
if(MCU_RD_PENDr) begin if(MCU_RD_PENDr) begin
STATE <= ST_MCU_RD_ADDR; STATE <= ST_MCU_RD_ADDR;
end else if(MCU_WR_PENDr) begin end else if(MCU_WR_PENDr) begin
@ -581,11 +583,11 @@ always @(posedge CLK2) begin
ROM_SAr <= 1'b0; ROM_SAr <= 1'b0;
ST_MEM_DELAYr <= ROM_WR_WAIT_MCU; ST_MEM_DELAYr <= ROM_WR_WAIT_MCU;
STATE <= ST_MCU_WR_WAIT; STATE <= ST_MCU_WR_WAIT;
ROM_DOUT_ENr <= 1'b1;
ROM_WEr <= 1'b0; ROM_WEr <= 1'b0;
end end
ST_MCU_WR_WAIT: begin ST_MCU_WR_WAIT: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 1; ST_MEM_DELAYr <= ST_MEM_DELAYr - 1;
ROM_DOUT_ENr <= 1'b1;
if(ST_MEM_DELAYr == 0) begin if(ST_MEM_DELAYr == 0) begin
ROM_WEr <= 1'b1; ROM_WEr <= 1'b1;
STATE <= ST_MCU_WR_END; STATE <= ST_MCU_WR_END;
@ -604,13 +606,13 @@ always @(posedge CLK2) begin
ST_CX4_RD_WAIT: begin ST_CX4_RD_WAIT: begin
ST_MEM_DELAYr <= ST_MEM_DELAYr - 1; ST_MEM_DELAYr <= ST_MEM_DELAYr - 1;
if(ST_MEM_DELAYr == 0) begin if(ST_MEM_DELAYr == 0) begin
CX4_DINr <= CX4_ADDRr[0] ? ROM_DATA[7:0] : ROM_DATA[15:8];
STATE <= ST_CX4_RD_END; STATE <= ST_CX4_RD_END;
end end
else STATE <= ST_CX4_RD_WAIT; else STATE <= ST_CX4_RD_WAIT;
end end
ST_CX4_RD_END: begin ST_CX4_RD_END: begin
ROM_CAr <= 1'b0; ROM_CAr <= 1'b0;
CX4_DINr <= CX4_ADDRr[0] ? ROM_DATA[7:0] : ROM_DATA[15:8];
STATE <= ST_IDLE; STATE <= ST_IDLE;
end end

View File

@ -1,7 +1,7 @@
############################################################## ##############################################################
# #
# Xilinx Core Generator version 13.2 # Xilinx Core Generator version 13.4
# Date: Fri Dec 9 20:36:25 2011 # Date: Fri Aug 17 17:03:15 2012
# #
############################################################## ##############################################################
# #
@ -99,7 +99,7 @@ CSET write_width_a=8
CSET write_width_b=8 CSET write_width_b=8
# END Parameters # END Parameters
# BEGIN Extra information # BEGIN Extra information
MISC pkg_timestamp=2011-03-11T08:24:14.000Z MISC pkg_timestamp=2011-03-11T08:24:14Z
# END Extra information # END Extra information
GENERATE GENERATE
# CRC: 213d12c4 # CRC: 370f2518

View File

@ -12,7 +12,7 @@
<!-- Copyright (c) 1995-2011 Xilinx, Inc. All rights reserved. --> <!-- Copyright (c) 1995-2011 Xilinx, Inc. All rights reserved. -->
</header> </header>
<version xil_pn:ise_version="13.2" xil_pn:schema_version="2"/> <version xil_pn:ise_version="13.4" xil_pn:schema_version="2"/>
<files> <files>
<file xil_pn:name="PA.ngc" xil_pn:type="FILE_NGC"> <file xil_pn:name="PA.ngc" xil_pn:type="FILE_NGC">

Some files were not shown because too many files have changed in this diff Show More